bool Main::runLDS() { #ifdef PARALLEL_STATIC if (m_options->par_postOnly) return true; // skip LDS for static post mode #endif // Run LDS if specified if (m_options->lds != NONE) { cout << "Running LDS with limit " << m_options->lds << endl; scoped_ptr<SearchSpace> spaceLDS(new SearchSpace(m_pseudotree.get(), m_options.get())); LimitedDiscrepancy lds(m_problem.get(), m_pseudotree.get(), spaceLDS.get(), m_heuristic.get(), m_options->lds); if (!m_options->in_subproblemFile.empty()) { if (!lds.restrictSubproblem(m_options->in_subproblemFile)) { err_txt("Subproblem restriction for LDS failed."); return false; } } // load current best solution into LDS if (lds.updateSolution(m_problem->getSolutionCost() #ifndef NO_ASSIGNMENT , m_problem->getSolutionAssg() #endif )) cout << "LDS: Initial solution loaded." << endl; BoundPropagator propLDS(m_problem.get(), spaceLDS.get(), false); // doCaching = false lds.finalizeHeuristic(); SearchNode* n = lds.nextLeaf(); while (n) { propLDS.propagate(n,true); // true = report solution n = lds.nextLeaf(); } cout << "LDS: explored " << spaceLDS->stats.numExpOR << '/' << spaceLDS->stats.numExpAND << " OR/AND nodes" << endl; cout << "LDS: solution cost " << lds.getCurOptValue() << endl; #ifndef NO_HEURISTIC if (m_search->getCurOptValue() >= m_heuristic->getGlobalUB()) { m_solved = true; cout << endl << "--------- Solved by LDS ---------" << endl; } #endif } return true; }
bool Main::parseOptions(int argc, char** argv) { // Reprint command line for (int i=0; i<argc; ++i) cout << argv[i] << ' '; cout << endl; // parse command line ProgramOptions* opt = parseCommandLine(argc, argv); if (!opt) { err_txt("Error parsing command line."); return false; } if (opt->seed == NONE) opt->seed = time(0); rand::seed(opt->seed); m_options.reset(opt); return true; }
/* static master mode for distributed execution */ bool Main::runSearchStatic() { bool preOnly = m_options->par_preOnly, postOnly = m_options->par_postOnly, local = m_options->par_solveLocal; bool success = true; if (!postOnly) { success = success && m_search->doLearning(); } if (true) { // TODO /* find frontier from scratch */ success = success && m_search->findFrontier(); } if (!postOnly) { /* writes CSV with subproblem stats */ success = success && m_search->writeSubprobStats(); } if (!postOnly && !local) { /* generate files for subproblems */ success = success && m_search->writeJobs(); if (m_search->getSubproblemCount()==0) m_solved = true; } if (local && !preOnly) { /* solve external subproblems locally */ success = success && m_search->extSolveLocal(); } if (!local && !preOnly && !postOnly) { /* run Condor and wait for results */ success = success && m_search->runCondor(); } if (!local && !preOnly) { /* read external results */ success = success && m_search->readExtResults(); } if (!success) { myprint("!!! Search failed. !!!\n"); err_txt("Main search routine failed."); return false; } return true; }
SEXP R_export2dataset(SEXP path, SEXP dataframe, SEXP shape, SEXP shape_info) { std::wstring dataset_name; tools::copy_to(path, dataset_name); struct _cleanup { typedef std::vector<cols_base*> c_type; std::vector<std::wstring> name; c_type c; //std::vector<c_type::const_iterator> shape; c_type shape; ~_cleanup() { for (size_t i = 0; i < c.size(); i++) delete c[i]; for (size_t i = 0; i < shape.size(); i++) delete shape[i]; } }cols; shape_extractor extractor; bool isShape = extractor.init(shape, shape_info) == S_OK; //SEXP sinfo = Rf_getAttrib(shape, Rf_mkChar("shape_info")); //cols.name = df.attr("names"); tools::getNames(dataframe, cols.name); //tools::vectorGeneric shape_info(sinfo); //std::string gt_type; //tools::copy_to(shape_info.at("type"), gt_type); esriGeometryType gt = extractor.type();//str2geometryType(gt_type.c_str()); R_xlen_t n = 0; ATLTRACE("dataframe type:%s", Rf_type2char(TYPEOF(dataframe))); if (Rf_isVectorList(dataframe)) { size_t k = tools::size(dataframe); cols.name.resize(k); for (size_t i = 0; i < k; i++) { n = std::max(n, tools::size(VECTOR_ELT(dataframe, (R_xlen_t)i))); if (cols.name[i].empty()) cols.name[i] = L"data"; } } else { n = tools::size(dataframe); ATLASSERT(cols.name.empty()); } if (isShape == false && n == 0) return showError<false>(L"nothing to save"), R_NilValue; if (isShape && n != extractor.size() ) return showError<false>(L"length of shape != data.frame"), R_NilValue; CComPtr<IGPUtilities> ipDEUtil; if (ipDEUtil.CoCreateInstance(CLSID_GPUtilities) != S_OK) return showError<true>(L"IDEUtilitiesImpl - CoCreateInstance has failed"), R_NilValue; HRESULT hr = 0; CComPtr<IName> ipName; if (isShape) hr = ipDEUtil->CreateFeatureClassName(CComBSTR(dataset_name.c_str()), &ipName); else hr = ipDEUtil->CreateTableName(CComBSTR(dataset_name.c_str()), &ipName); CComQIPtr<IDatasetName> ipDatasetName(ipName); CComPtr<IWorkspaceName> ipWksName; CComQIPtr<IWorkspace> ipWks; if (hr == S_OK) hr = ipDatasetName->get_WorkspaceName(&ipWksName); if (hr == S_OK) { CComPtr<IUnknown> ipUnk; hr = CComQIPtr<IName>(ipWksName)->Open(&ipUnk); ipWks = ipUnk; } if (hr != S_OK) return showError<true>(L"invalid table name"), R_NilValue; CComQIPtr<IFeatureWorkspace> ipFWKS(ipWks); ATLASSERT(ipFWKS); if (!ipFWKS) return showError<true>(L"not a FeatureWorkspace"), R_NilValue; CComBSTR bstrTableName; ipDatasetName->get_Name(&bstrTableName); CComPtr<IFieldsEdit> ipFields; hr = ipFields.CoCreateInstance(CLSID_Fields); if (hr != S_OK) return showError<true>(L"CoCreateInstance"), R_NilValue; createField(NULL, esriFieldTypeOID, ipFields); CComPtr<ISpatialReference> ipSR; if (isShape) { long pos = createField(NULL, esriFieldTypeGeometry, ipFields); CComPtr<IGeometryDef> ipGeoDef; CComPtr<IField> ipField; ipFields->get_Field(pos, &ipField); ipField->get_GeometryDef(&ipGeoDef); CComQIPtr<IGeometryDefEdit> ipGeoDefEd(ipGeoDef); ipGeoDefEd->put_GeometryType(gt); ipGeoDefEd->putref_SpatialReference(extractor.sr()); } if (cols.name.empty()) { cols.name.push_back(L"data"); cols_base* item = setup_field(ipFields, dataframe, cols.name[0].c_str()); if (!item) return showError<false>(L"unsupported datat.field column type"), NULL; cols.c.push_back(item); item->name_ref = &cols.name[0]; } else for (size_t i = 0; i < cols.name.size(); i++) { if (cols.name[i].empty()) continue; const wchar_t* str = cols.name[i].c_str(); SEXP it = VECTOR_ELT(dataframe, (R_len_t)i); cols_base* item = setup_field(ipFields, it, str); if (!item) return showError<false>(L"unsupported datat.field column type"), NULL; cols.c.push_back(item); item->name_ref = &cols.name[i]; } CComPtr<IFieldChecker> ipFieldChecker; ipFieldChecker.CoCreateInstance(CLSID_FieldChecker); if (ipFieldChecker) { ipFieldChecker->putref_ValidateWorkspace(ipWks); long error = 0; //fix fields names CComPtr<IFields> ipFixedFields; CComPtr<IEnumFieldError> ipEError; hr = ipFieldChecker->Validate(ipFields, &ipEError, &ipFixedFields); if (hr != S_OK) return showError<true>(L"validate fields failed"), NULL; if (ipFixedFields) { ipFields = ipFixedFields; for (size_t c = 0; c < cols.c.size(); c++) { CComPtr<IField> ipFixedField; ipFixedFields->get_Field(cols.c[c]->pos, &ipFixedField); _bstr_t name; ipFixedField->get_Name(name.GetAddress()); cols.c[c]->name_ref->assign(name); } } } CComPtr<IUID> ipUID; ipUID.CoCreateInstance(CLSID_UID); if (ipUID) { OLECHAR buf[256]; ::StringFromGUID2(isShape ? CLSID_Feature : CLSID_Row, buf, 256); ipUID->put_Value(CComVariant(buf)); } CComQIPtr<ITable> ipTableNew; CComBSTR keyword(L""); hr = E_FAIL; if (isShape) { CComPtr<IFeatureClass> ipFClass; hr = ipFWKS->CreateFeatureClass(bstrTableName, ipFields, ipUID, 0, esriFTSimple, CComBSTR(L"Shape"), keyword, &ipFClass); ipTableNew = ipFClass; } else { hr = ipFWKS->CreateTable(bstrTableName, ipFields, ipUID, 0, keyword, &ipTableNew); } if (hr != S_OK) { std::wstring err_txt(isShape ? L"Create FeatureClass :" : L"Create Table :"); err_txt += bstrTableName; err_txt += L" has failed"; return showError<true>(err_txt.c_str()), R_NilValue; } CComVariant oid; CComPtr<ICursor> ipCursor; CComPtr<IRowBuffer> ipRowBuffer; hr = ipTableNew->Insert(VARIANT_TRUE, &ipCursor); if (hr != S_OK) return showError<true>(L"Insert cursor failed"), R_NilValue; hr = ipTableNew->CreateRowBuffer(&ipRowBuffer); if (hr != S_OK) return showError<true>(L"Insert cursor failed"), R_NilValue; //re-map fields CComPtr<IFields> ipRealFields; ipCursor->get_Fields(&ipRealFields); for (size_t c = 0; c < cols.c.size(); c++) { ipRealFields->FindField(CComBSTR(cols.c[c]->name_ref->c_str()), &(cols.c[c]->pos)); CComPtr<IField> ipField; ipRealFields->get_Field(cols.c[c]->pos, &ipField); VARIANT_BOOL b = VARIANT_FALSE; ipField->get_IsNullable(&b); if (b == VARIANT_FALSE) { esriFieldType ft = esriFieldTypeInteger; ipField->get_Type(&ft); switch(ft) { case esriFieldTypeInteger: cols.c[c]->vNULL = 0;//std::numeric_limits<int>::min(); break; case esriFieldTypeDouble: cols.c[c]->vNULL = 0.0;//-std::numeric_limits<double>::max(); break; case esriFieldTypeString: cols.c[c]->vNULL = L""; } } } CComQIPtr<IFeatureBuffer> ipFBuffer(ipRowBuffer); for (R_len_t i = 0; i < n; i++) { //ATLTRACE("\n"); for (size_t c = 0; c < cols.c.size(); c++) { if (cols.c[c]->pos < 0) continue; CComVariant val; cols.c[c]->get(i, val); if (val.vt == VT_NULL) hr = ipRowBuffer->put_Value(cols.c[c]->pos, cols.c[c]->vNULL); else hr = ipRowBuffer->put_Value(cols.c[c]->pos, val); if (FAILED(hr)) return showError<true>(L"insert row value failed"), R_NilValue; } VARIANT oid; if (isShape) { ATLASSERT(ipFBuffer); CComQIPtr<IGeometry> ipNewShape; hr = extractor.at(i, &ipNewShape); if (hr != S_OK) return R_NilValue; hr = ipFBuffer->putref_Shape(ipNewShape); if (FAILED(hr)) return showError<true>(L"insert shape failed"), R_NilValue; } hr = ipCursor->InsertRow(ipRowBuffer, &oid); if (hr != S_OK) return showError<true>(L"insert row failed"), R_NilValue; } return R_NilValue; }
bool Main::compileHeuristic() { m_options->ibound = min(m_options->ibound, m_pseudotree->getWidthCond()); size_t sz = 0; if (m_options->memlimit != NONE) { sz = m_heuristic->limitSize(m_options->memlimit, & m_search->getAssignment() ); sz *= sizeof(double) / (1024*1024.0); cout << "Enforcing memory limit resulted in i-bound " << m_options->ibound << " with " << sz << " MByte." << endl; } if (m_options->nosearch) { cout << "Simulating mini bucket heuristic..." << endl; sz = m_heuristic->build(& m_search->getAssignment(), false); // false = just compute memory estimate } else { time(&_time_pre); bool mbFromFile = false; if (!m_options->in_minibucketFile.empty()) { mbFromFile = m_heuristic->readFromFile(m_options->in_minibucketFile); sz = m_heuristic->getSize(); } if (!mbFromFile) { cout << "Computing mini bucket heuristic..." << endl; sz = m_heuristic->build(& m_search->getAssignment(), true); // true = actually compute heuristic time_t cur_time; time(&cur_time); double time_passed = difftime(cur_time, _time_pre); cout << "\tMini bucket finished in " << time_passed << " seconds" << endl; } if (!mbFromFile && !m_options->in_minibucketFile.empty()) { cout << "\tWriting mini bucket to file " << m_options->in_minibucketFile << " ..." << flush; m_heuristic->writeToFile(m_options->in_minibucketFile); cout << " done" << endl; } } cout << '\t' << (sz / (1024*1024.0)) * sizeof(double) << " MBytes" << endl; // heuristic might have changed problem functions, pseudotree needs remapping m_pseudotree->addFunctionInfo(m_problem->getFunctions()); // set initial lower bound if provided (but only if no subproblem was specified) if (m_options->in_subproblemFile.empty() ) { if (m_options->in_boundFile.size()) { cout << "Loading initial lower bound from file " << m_options->in_boundFile << '.' << endl; if (!m_search->loadInitialBound(m_options->in_boundFile)) { err_txt("Loading initial bound failed"); return false; } } else if (!ISNAN ( m_options->initialBound )) { #ifdef NO_ASSIGNMENT cout << "Setting external lower bound " << m_options->initialBound << endl; m_search->updateSolution(m_options->initialBound); #else err_txt("Compiled with tuple support, value-based bound not possible."); return false; #endif } } #ifndef NO_HEURISTIC if (m_search->getCurOptValue() >= m_heuristic->getGlobalUB()) { m_solved = true; cout << endl << "--------- Solved during preprocessing ---------" << endl; } else if (m_heuristic->isAccurate()) { cout << endl << "Heuristic is accurate!" << endl; m_options->lds = 0; // set LDS to 0 (sufficient given perfect heuristic) m_solved = true; } #endif return true; }
bool Main::initDataStructs() { // The main search space #ifdef PARALLEL_DYNAMIC m_space.reset( new SearchSpaceMaster(m_pseudotree.get(), m_options.get()) ); #else m_space.reset( new SearchSpace(m_pseudotree.get(), m_options.get()) ); #endif // Heuristic is initialized here, built later in compileHeuristic() #ifdef NO_HEURISTIC m_heuristic.reset(new UnHeuristic); #else m_heuristic.reset(new MiniBucketElim(m_problem.get(), m_pseudotree.get(), m_options.get(), m_options->ibound) ); #endif // Main search engine #if defined PARALLEL_DYNAMIC m_search.reset(new BranchAndBoundMaster(m_problem.get(), m_pseudotree.get(), m_space.get(), m_heuristic.get())); // TODO #elif defined PARALLEL_STATIC m_search.reset(new ParallelManager(m_problem.get(), m_pseudotree.get(), m_space.get(), m_heuristic.get())); #else if (m_options->rotate) { m_search.reset(new BranchAndBoundRotate( m_problem.get(), m_pseudotree.get(), m_space.get(), m_heuristic.get())); } else { m_search.reset(new BranchAndBound( m_problem.get(), m_pseudotree.get(), m_space.get(), m_heuristic.get())); } #endif // Subproblem specified? If yes, restrict. if (!m_options->in_subproblemFile.empty()) { if (m_options->in_orderingFile.empty()) { err_txt("Subproblem specified but no ordering given."); return false; }else { m_problem->setSubprobOnly(); m_options->order_iterations = 0; cout << "Reading subproblem from file " << m_options->in_subproblemFile << '.' << endl; if (!m_search->restrictSubproblem(m_options->in_subproblemFile) ) { err_txt("Subproblem restriction failed."); return false; } } } cout << "Induced width:\t\t" << m_pseudotree->getWidthCond() << " / " << m_pseudotree->getWidth() << endl; cout << "Pseudotree depth:\t" << m_pseudotree->getHeightCond() << " / " << m_pseudotree->getHeight() << endl; cout << "Problem variables:\t" << m_pseudotree->getSizeCond() << " / " << m_pseudotree->getSize() << endl; #ifdef PARALLEL_STATIC cout << "State space bound:\t" << m_pseudotree->getStateSpaceCond() << endl; #endif cout << "Disconn. components:\t" << m_pseudotree->getComponentsCond() << " / " << m_pseudotree->getComponents() << endl; #ifdef MEMDEBUG malloc_stats(); #endif return true; }
bool Main::findOrLoadOrdering() { // Create primal graph of *reduced* problem Graph g(m_problem->getN()); const vector<Function*>& fns = m_problem->getFunctions(); for (vector<Function*>::const_iterator it = fns.begin(); it != fns.end(); ++it) { g.addClique((*it)->getScopeVec()); } cout << "Graph with " << g.getStatNodes() << " nodes and " << g.getStatEdges() << " edges created." << endl; #ifdef PARALLEL_STATIC // for static parallelization post-processing mode, look for // ordering from preprocessing step if (m_options->par_postOnly) { m_options->in_orderingFile = string("temp_elim.") + m_options->problemName + string(".") + m_options->runTag + string(".gz"); m_options->order_iterations = 0; } #endif // Find variable ordering vector<int> elim; int w = numeric_limits<int>::max(); bool orderFromFile = false; if (!m_options->in_orderingFile.empty()) { orderFromFile = m_problem->parseOrdering(m_options->in_orderingFile, elim); } // Init. pseudo tree m_pseudotree.reset(new Pseudotree(m_problem.get(), m_options->subprobOrder)); if (orderFromFile) { // Reading from file succeeded (i.e. file exists) m_pseudotree->build(g, elim, m_options->cbound); w = m_pseudotree->getWidth(); cout << "Read elimination ordering from file " << m_options->in_orderingFile << " (" << w << '/' << m_pseudotree->getHeight() << ")." << endl; } else { if (m_options->order_timelimit == NONE) // compute at least one m_options->order_iterations = max(1, m_options->order_iterations); } time_t time_order_start, time_order_cur; double timediff = 0.0; time(&time_order_start); // Search for variable elimination ordering, looking for min. induced // width, breaking ties via pseudo tree height cout << "Searching for elimination ordering,"; if (m_options->order_iterations != NONE) cout << " " << m_options->order_iterations << " iterations"; if (m_options->order_timelimit != NONE) cout << " " << m_options->order_timelimit << " seconds"; cout << ":" << flush; int iterCount=0, sinceLast=0; int remaining = m_options->order_iterations; while (true) { if (m_options->order_iterations != NONE && remaining == 0) break; vector<int> elimCand; // new ordering candidate bool improved = false; // improved in this iteration? int new_w = m_pseudotree->eliminate(g, elimCand, w, m_options->order_tolerance); if (new_w < w) { elim = elimCand; w = new_w; improved = true; m_pseudotree->build(g, elimCand, m_options->cbound); cout << " " << iterCount << ':' << w <<'/' << m_pseudotree->getHeight() << flush; } else if (new_w == w) { Pseudotree ptCand(m_problem.get(), m_options->subprobOrder); ptCand.build(g, elimCand, m_options->cbound); if (ptCand.getHeight() < m_pseudotree->getHeight()) { elim = elimCand; improved = true; m_pseudotree->build(g, elim, m_options->cbound); cout << " " << iterCount << ':' << w << '/' << m_pseudotree->getHeight() << flush; } } ++iterCount, ++sinceLast, --remaining; // Adaptive ordering scheme if (improved && m_options->autoIter && remaining > 0) { remaining = max(remaining, sinceLast+1); sinceLast = 0; } // check termination conditions time(&time_order_cur); timediff = difftime(time_order_cur, time_order_start); if (m_options->order_timelimit != NONE && timediff > m_options->order_timelimit) break; } time(&time_order_cur); timediff = difftime(time_order_cur, time_order_start); cout << endl << "Ran " << iterCount << " iterations (" << int(timediff) << " seconds), lowest width/height found: " << w << '/' << m_pseudotree->getHeight() << '\n'; // Save order to file? if (!m_options->in_orderingFile.empty() && !orderFromFile) { m_problem->saveOrdering(m_options->in_orderingFile, elim); cout << "Saved ordering to file " << m_options->in_orderingFile << endl; } #if defined PARALLEL_DYNAMIC || defined PARALLEL_STATIC #if defined PARALLEL_STATIC if (!m_options->par_solveLocal && !m_options->par_postOnly) // no need to write ordering #endif { m_options->in_orderingFile = string("temp_elim.") + m_options->problemName + string(".") + m_options->runTag + string(".gz"); m_problem->saveOrdering(m_options->in_orderingFile,elim); cout << "Saved ordering to file " << m_options->in_orderingFile << endl; } #endif // OR search? if (m_options->orSearch) { cout << "Rebuilding pseudo tree as chain." << endl; m_pseudotree->buildChain(g, elim, m_options->cbound); } // Pseudo tree has dummy node after build(), add to problem m_problem->addDummy(); // add dummy variable to problem, to be in sync with pseudo tree m_pseudotree->addFunctionInfo(m_problem->getFunctions()); m_pseudotree->addDomainInfo(m_problem->getDomains()); #if defined PARALLEL_STATIC m_pseudotree->computeSubprobStats(); #endif #if defined PARALLEL_DYNAMIC //|| defined PARALLEL_STATIC int cutoff = m_pseudotree->computeComplexities(m_options->threads); cout << "Suggested cutoff:\t" << cutoff << " (ignored)" << endl; // if (opt.autoCutoff) { // cout << "Auto cutoff:\t\t" << cutoff << endl; // opt.cutoff_depth = cutoff; // } #endif // Output pseudo tree to file for plotting? if (!m_options->out_pstFile.empty()) { m_pseudotree->outputToFile(m_options->out_pstFile); } if (m_options->maxWidthAbort != NONE && m_options->maxWidthAbort < m_pseudotree->getWidth()) { oss msg; msg << "Problem instance with width w="<< m_pseudotree->getWidth() << " is too complex, aborting (limit is w=" << m_options->maxWidthAbort << ")"; err_txt(msg.str()); return false; } return true; }