diff --git a/gtsam_unstable/partition/FindSeparator-inl.h b/gtsam_unstable/partition/FindSeparator-inl.h index 8b05984d2..2e147ff20 100644 --- a/gtsam_unstable/partition/FindSeparator-inl.h +++ b/gtsam_unstable/partition/FindSeparator-inl.h @@ -19,6 +19,7 @@ extern "C" { #include +#include "metislib.h" } #include "FindSeparator.h" @@ -41,7 +42,6 @@ namespace gtsam { namespace partition { // control parameters idx_t vwgt[n]; // the weights of the vertices - //int options[8]; options [0] = 0 ; idx_t options[METIS_NOPTIONS]; METIS_SetDefaultOptions(options); // use defaults idx_t sepsize; // the size of the separator, output @@ -60,10 +60,7 @@ namespace gtsam { namespace partition { //TOTALTmr.start() } - // call metis parition routine OLD!!!! - /*METIS_NodeComputeSeparator(&n, xadj.get(), adjncy.get(), vwgt, adjwgt.get(), - options, &sepsize, part_.get());*/ - // new + // call metis parition routine METIS_ComputeVertexSeparator(&n, xadj.get(), adjncy.get(), vwgt, options, &sepsize, part_.get()); @@ -78,103 +75,90 @@ namespace gtsam { namespace partition { return make_pair(sepsize, part_); } - /* ************************************************************************* * - void modefied_EdgeComputeSeparator(int *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, - idx_t *adjwgt, int *options, int *edgecut, idx_t *part) + /* ************************************************************************* */ + void modefied_EdgeComputeSeparator(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, + idx_t *adjwgt, idx_t *options, idx_t *edgecut, idx_t *part) { - int i, j, tvwgt, tpwgts[2]; - GraphType graph; - CtrlType ctrl; + idx_t i, j, ncon; + graph_t *graph; + real_t *tpwgts2; + ctrl_t *ctrl; + ctrl = SetupCtrl(METIS_OP_OMETIS, options, 1, 3, NULL, NULL); + ctrl->iptype = METIS_IPTYPE_GROW; + //if () == NULL) + // return METIS_ERROR_INPUT; - SetUpGraph(&graph, OP_ONMETIS, *nvtxs, 1, xadj, adjncy, vwgt, adjwgt, 3); - tvwgt = idxsum(*nvtxs, graph.vwgt); + InitRandom(ctrl->seed); - if (options[0] == 0) { // Use the default parameters - ctrl.CType = ONMETIS_CTYPE; - ctrl.IType = ONMETIS_ITYPE; - ctrl.RType = ONMETIS_RTYPE; - ctrl.dbglvl = ONMETIS_DBGLVL; - } - else { - ctrl.CType = options[OPTION_CTYPE]; - ctrl.IType = options[OPTION_ITYPE]; - ctrl.RType = options[OPTION_RTYPE]; - ctrl.dbglvl = options[OPTION_DBGLVL]; - } + graph = SetupGraph(ctrl, *nvtxs, 1, xadj, adjncy, vwgt, NULL, NULL); - ctrl.oflags = 0; - ctrl.pfactor = 0; - ctrl.nseps = 1; - ctrl.optype = OP_OEMETIS; - ctrl.CoarsenTo = amin(100, *nvtxs-1); - ctrl.maxvwgt = 1.5*tvwgt/ctrl.CoarsenTo; + AllocateWorkSpace(ctrl, graph); - InitRandom(options[7]); + ncon = graph->ncon; + ctrl->ncuts = 1; + + /* determine the weights of the two partitions as a function of the weight of the + target partition weights */ - AllocateWorkSpace(&ctrl, &graph, 2); + tpwgts2 = rwspacemalloc(ctrl, 2*ncon); + for (i=0; i>1), ctrl->tpwgts+i, ncon); + tpwgts2[ncon+i] = 1.0 - tpwgts2[i]; + } + /* perform the bisection */ + *edgecut = MultilevelBisect(ctrl, graph, tpwgts2); - //============================================================ - // Perform the bisection - //============================================================ - tpwgts[0] = tvwgt/2; - tpwgts[1] = tvwgt-tpwgts[0]; - - MlevelEdgeBisection(&ctrl, &graph, tpwgts, 1.05); - // ConstructMinCoverSeparator(&ctrl, &graph, 1.05); - *edgecut = graph.mincut; + // ConstructMinCoverSeparator(&ctrl, &graph, 1.05); + // *edgecut = graph->mincut; // *sepsize = graph.pwgts[2]; - idxcopy(*nvtxs, graph.where, part); - - GKfree((void**)&graph.gdata, &graph.rdata, &graph.label, LTERM); - - - FreeWorkSpace(&ctrl, &graph); + icopy(*nvtxs, graph->where, part); + cout << "Finished bisection:" << *edgecut << endl; + FreeGraph(&graph); + FreeCtrl(&ctrl); } /* ************************************************************************* */ /** - * Return the number of edge cuts and the partiion indices {part} + * Return the number of edge cuts and the partition indices {part} * Part [j] is 0 or 1, depending on * whether node j is in the left part of the graph or the right part respectively - * - pair edgeMetis(int n, const sharedInts& xadj, const sharedInts& adjncy, const sharedInts& adjwgt, bool verbose) { + */ + pair edgeMetis(idx_t n, const sharedInts& xadj, const sharedInts& adjncy, + const sharedInts& adjwgt, bool verbose) { // control parameters idx_t vwgt[n]; // the weights of the vertices - int options[10]; options [0] = 1; options [1] = 3; options [2] = 1; options [3] = 1; options [4] = 0; // use defaults - int edgecut; // the number of edge cuts, output - sharedInts part_(new int[n]); // the partition of each vertex, output + idx_t options[METIS_NOPTIONS]; + METIS_SetDefaultOptions(options); // use defaults + idx_t edgecut; // the number of edge cuts, output + sharedInts part_(new idx_t[n]); // the partition of each vertex, output // set uniform weights on the vertices std::fill(vwgt, vwgt+n, 1); - TODO: Fix later - boost::timer TOTALTmr; + //TODO: Fix later + //boost::timer TOTALTmr; if (verbose) { printf("**********************************************************************\n"); printf("Graph Information ---------------------------------------------------\n"); printf(" #Vertices: %d, #Edges: %u\n", n, *(xadj.get()+n) / 2); printf("\nND Partitioning... -------------------------------------------\n"); - cleartimer(TOTALTmr); - starttimer(TOTALTmr); + //cleartimer(TOTALTmr); + //starttimer(TOTALTmr); } - // call metis parition routine - int wgtflag = 1; // only edge weights - int numflag = 0; // c style numbering starting from 0 - int nparts = 2; // partition the graph to 2 submaps -// METIS_PartGraphRecursive(&n, xadj.get(), adjncy.get(), NULL, adjwgt.get(), &wgtflag, -// &numflag, &nparts, options, &edgecut, part_.get()); - + //int wgtflag = 1; // only edge weights + //int numflag = 0; // c style numbering starting from 0 + //int nparts = 2; // partition the graph to 2 submaps modefied_EdgeComputeSeparator(&n, xadj.get(), adjncy.get(), vwgt, adjwgt.get(), options, &edgecut, part_.get()); if (verbose) { - stoptimer(TOTALTmr); + //stoptimer(TOTALTmr); printf("\nTiming Information --------------------------------------------------\n"); - printf(" Total: \t\t %7.3f\n", gettimer(TOTALTmr)); + //printf(" Total: \t\t %7.3f\n", gettimer(TOTALTmr)); printf(" Edge cuts: \t\t %d\n", edgecut); printf("**********************************************************************\n"); } @@ -204,17 +188,21 @@ namespace gtsam { namespace partition { // prepare for {adjancyMap}, a pair of neighbor indices and the correponding edge weights int numNodes = keys.size(); int numEdges = 0; - vector adjancyMap; // TODO: set is slow, but have to use it to remove duplicated edges + vector adjancyMap; adjancyMap.resize(numNodes); + cout << "Number of nodes: " << adjancyMap.size() << endl; int index1, index2; BOOST_FOREACH(const typename GenericGraph::value_type& factor, graph){ index1 = dictionary[factor->key1.index]; index2 = dictionary[factor->key2.index]; + cout << "index1: " << index1 << endl; + cout << "index2: " << index2 << endl; // if both nodes are in the current graph, i.e. not a joint factor between frontal and separator if (index1 >= 0 && index2 >= 0) { pair& adjancyMap1 = adjancyMap[index1]; pair& adjancyMap2 = adjancyMap[index2]; + cout << adjancyMap1.first.size() << endl; adjancyMap1.first .push_back(index2); adjancyMap1.second.push_back(factor->weight); adjancyMap2.first .push_back(index1); @@ -297,9 +285,10 @@ namespace gtsam { namespace partition { return boost::make_optional(result); } - /* ************************************************************************* + /* *************************************************************************/ template - boost::optional edgePartitionByMetis(const GenericGraph& graph, const vector& keys, WorkSpace& workspace, bool verbose) { + boost::optional edgePartitionByMetis(const GenericGraph& graph, + const vector& keys, WorkSpace& workspace, bool verbose) { // a small hack for handling the camera1-camera2 case used in the unit tests if (graph.size() == 1 && keys.size() == 2) { @@ -338,7 +327,8 @@ namespace gtsam { namespace partition { } if (verbose) { - cout << "the size of two submaps in the reduced graph: " << result.A.size() << " " << result.B.size() << endl; + cout << "the size of two submaps in the reduced graph: " << result.A.size() + << " " << result.B.size() << endl; int edgeCut = 0; BOOST_FOREACH(const typename GenericGraph::value_type& factor, graph){ diff --git a/gtsam_unstable/partition/tests/testFindSeparator.cpp b/gtsam_unstable/partition/tests/testFindSeparator.cpp index 093f385f3..1bed2e0da 100644 --- a/gtsam_unstable/partition/tests/testFindSeparator.cpp +++ b/gtsam_unstable/partition/tests/testFindSeparator.cpp @@ -71,7 +71,7 @@ TEST ( Partition, separatorPartitionByMetis2 ) CHECK(C_expected == actual->C); } -/* ************************************************************************* +/* *************************************************************************/ // x0 - x2 - x3 - x5 TEST ( Partition, edgePartitionByMetis ) { @@ -83,24 +83,25 @@ TEST ( Partition, edgePartitionByMetis ) WorkSpace workspace(6); boost::optional actual = edgePartitionByMetis(graph, keys, - workspace, false); + workspace, true); + CHECK(actual.is_initialized()); vector A_expected; A_expected += 0, 2; // frontal vector B_expected; B_expected += 3, 5; // frontal vector C_expected; // separator -// BOOST_FOREACH(const size_t a, actual->A) -// cout << a << " "; -// cout << endl; -// BOOST_FOREACH(const size_t b, actual->B) -// cout << b << " "; -// cout << endl; + BOOST_FOREACH(const size_t a, actual->A) + cout << a << " "; + cout << endl; + BOOST_FOREACH(const size_t b, actual->B) + cout << b << " "; + cout << endl; CHECK(A_expected == actual->A || A_expected == actual->B); CHECK(B_expected == actual->B || B_expected == actual->A); CHECK(C_expected == actual->C); } - +/* *************************************************************************/ // x0 - x2 - x3 - x5 - x6 TEST ( Partition, edgePartitionByMetis2 ) { @@ -111,7 +112,7 @@ TEST ( Partition, edgePartitionByMetis2 ) graph.push_back(boost::make_shared(5, 6, 3, NODE_POSE_3D, NODE_POSE_3D, 1)); std::vector keys; keys += 0, 2, 3, 5, 6; - WorkSpace workspace(6); + WorkSpace workspace(5); boost::optional actual = edgePartitionByMetis(graph, keys, workspace, false); CHECK(actual.is_initialized());