Updating to new metis interface. Need to address prepareMetisGraph since its causing core dump on second edgeseparator test

release/4.3a0
Andrew Melim 2014-02-21 18:20:43 -05:00
parent 05e42ba452
commit 0aa32a748f
2 changed files with 72 additions and 81 deletions

View File

@ -19,6 +19,7 @@
extern "C" { extern "C" {
#include <metis.h> #include <metis.h>
#include "metislib.h"
} }
#include "FindSeparator.h" #include "FindSeparator.h"
@ -41,7 +42,6 @@ namespace gtsam { namespace partition {
// control parameters // control parameters
idx_t vwgt[n]; // the weights of the vertices idx_t vwgt[n]; // the weights of the vertices
//int options[8]; options [0] = 0 ;
idx_t options[METIS_NOPTIONS]; idx_t options[METIS_NOPTIONS];
METIS_SetDefaultOptions(options); // use defaults METIS_SetDefaultOptions(options); // use defaults
idx_t sepsize; // the size of the separator, output idx_t sepsize; // the size of the separator, output
@ -60,10 +60,7 @@ namespace gtsam { namespace partition {
//TOTALTmr.start() //TOTALTmr.start()
} }
// call metis parition routine OLD!!!! // call metis parition routine
/*METIS_NodeComputeSeparator(&n, xadj.get(), adjncy.get(), vwgt, adjwgt.get(),
options, &sepsize, part_.get());*/
// new
METIS_ComputeVertexSeparator(&n, xadj.get(), adjncy.get(), METIS_ComputeVertexSeparator(&n, xadj.get(), adjncy.get(),
vwgt, options, &sepsize, part_.get()); vwgt, options, &sepsize, part_.get());
@ -78,103 +75,90 @@ namespace gtsam { namespace partition {
return make_pair(sepsize, part_); return make_pair(sepsize, part_);
} }
/* ************************************************************************* * /* ************************************************************************* */
void modefied_EdgeComputeSeparator(int *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt, void modefied_EdgeComputeSeparator(idx_t *nvtxs, idx_t *xadj, idx_t *adjncy, idx_t *vwgt,
idx_t *adjwgt, int *options, int *edgecut, idx_t *part) idx_t *adjwgt, idx_t *options, idx_t *edgecut, idx_t *part)
{ {
int i, j, tvwgt, tpwgts[2]; idx_t i, j, ncon;
GraphType graph; graph_t *graph;
CtrlType ctrl; 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); InitRandom(ctrl->seed);
tvwgt = idxsum(*nvtxs, graph.vwgt);
if (options[0] == 0) { // Use the default parameters graph = SetupGraph(ctrl, *nvtxs, 1, xadj, adjncy, vwgt, NULL, NULL);
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];
}
ctrl.oflags = 0; AllocateWorkSpace(ctrl, graph);
ctrl.pfactor = 0;
ctrl.nseps = 1;
ctrl.optype = OP_OEMETIS;
ctrl.CoarsenTo = amin(100, *nvtxs-1);
ctrl.maxvwgt = 1.5*tvwgt/ctrl.CoarsenTo;
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<ncon; i++) {
tpwgts2[i] = rsum((2>>1), ctrl->tpwgts+i, ncon);
tpwgts2[ncon+i] = 1.0 - tpwgts2[i];
}
/* perform the bisection */
*edgecut = MultilevelBisect(ctrl, graph, tpwgts2);
//============================================================ // ConstructMinCoverSeparator(&ctrl, &graph, 1.05);
// Perform the bisection // *edgecut = graph->mincut;
//============================================================
tpwgts[0] = tvwgt/2;
tpwgts[1] = tvwgt-tpwgts[0];
MlevelEdgeBisection(&ctrl, &graph, tpwgts, 1.05);
// ConstructMinCoverSeparator(&ctrl, &graph, 1.05);
*edgecut = graph.mincut;
// *sepsize = graph.pwgts[2]; // *sepsize = graph.pwgts[2];
idxcopy(*nvtxs, graph.where, part); icopy(*nvtxs, graph->where, part);
cout << "Finished bisection:" << *edgecut << endl;
GKfree((void**)&graph.gdata, &graph.rdata, &graph.label, LTERM); FreeGraph(&graph);
FreeWorkSpace(&ctrl, &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 * Part [j] is 0 or 1, depending on
* whether node j is in the left part of the graph or the right part respectively * whether node j is in the left part of the graph or the right part respectively
* */
pair<int, sharedInts> edgeMetis(int n, const sharedInts& xadj, const sharedInts& adjncy, const sharedInts& adjwgt, bool verbose) { pair<int, sharedInts> edgeMetis(idx_t n, const sharedInts& xadj, const sharedInts& adjncy,
const sharedInts& adjwgt, bool verbose) {
// control parameters // control parameters
idx_t vwgt[n]; // the weights of the vertices 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 idx_t options[METIS_NOPTIONS];
int edgecut; // the number of edge cuts, output METIS_SetDefaultOptions(options); // use defaults
sharedInts part_(new int[n]); // the partition of each vertex, output 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 // set uniform weights on the vertices
std::fill(vwgt, vwgt+n, 1); std::fill(vwgt, vwgt+n, 1);
TODO: Fix later //TODO: Fix later
boost::timer TOTALTmr; //boost::timer TOTALTmr;
if (verbose) { if (verbose) {
printf("**********************************************************************\n"); printf("**********************************************************************\n");
printf("Graph Information ---------------------------------------------------\n"); printf("Graph Information ---------------------------------------------------\n");
printf(" #Vertices: %d, #Edges: %u\n", n, *(xadj.get()+n) / 2); printf(" #Vertices: %d, #Edges: %u\n", n, *(xadj.get()+n) / 2);
printf("\nND Partitioning... -------------------------------------------\n"); printf("\nND Partitioning... -------------------------------------------\n");
cleartimer(TOTALTmr); //cleartimer(TOTALTmr);
starttimer(TOTALTmr); //starttimer(TOTALTmr);
} }
// call metis parition routine //int wgtflag = 1; // only edge weights
int wgtflag = 1; // only edge weights //int numflag = 0; // c style numbering starting from 0
int numflag = 0; // c style numbering starting from 0 //int nparts = 2; // partition the graph to 2 submaps
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());
modefied_EdgeComputeSeparator(&n, xadj.get(), adjncy.get(), vwgt, adjwgt.get(), modefied_EdgeComputeSeparator(&n, xadj.get(), adjncy.get(), vwgt, adjwgt.get(),
options, &edgecut, part_.get()); options, &edgecut, part_.get());
if (verbose) { if (verbose) {
stoptimer(TOTALTmr); //stoptimer(TOTALTmr);
printf("\nTiming Information --------------------------------------------------\n"); 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(" Edge cuts: \t\t %d\n", edgecut);
printf("**********************************************************************\n"); printf("**********************************************************************\n");
} }
@ -204,17 +188,21 @@ namespace gtsam { namespace partition {
// prepare for {adjancyMap}, a pair of neighbor indices and the correponding edge weights // prepare for {adjancyMap}, a pair of neighbor indices and the correponding edge weights
int numNodes = keys.size(); int numNodes = keys.size();
int numEdges = 0; int numEdges = 0;
vector<NeighborsInfo> adjancyMap; // TODO: set is slow, but have to use it to remove duplicated edges vector<NeighborsInfo> adjancyMap;
adjancyMap.resize(numNodes); adjancyMap.resize(numNodes);
cout << "Number of nodes: " << adjancyMap.size() << endl;
int index1, index2; int index1, index2;
BOOST_FOREACH(const typename GenericGraph::value_type& factor, graph){ BOOST_FOREACH(const typename GenericGraph::value_type& factor, graph){
index1 = dictionary[factor->key1.index]; index1 = dictionary[factor->key1.index];
index2 = dictionary[factor->key2.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 both nodes are in the current graph, i.e. not a joint factor between frontal and separator
if (index1 >= 0 && index2 >= 0) { if (index1 >= 0 && index2 >= 0) {
pair<Neighbors, Weights>& adjancyMap1 = adjancyMap[index1]; pair<Neighbors, Weights>& adjancyMap1 = adjancyMap[index1];
pair<Neighbors, Weights>& adjancyMap2 = adjancyMap[index2]; pair<Neighbors, Weights>& adjancyMap2 = adjancyMap[index2];
cout << adjancyMap1.first.size() << endl;
adjancyMap1.first .push_back(index2); adjancyMap1.first .push_back(index2);
adjancyMap1.second.push_back(factor->weight); adjancyMap1.second.push_back(factor->weight);
adjancyMap2.first .push_back(index1); adjancyMap2.first .push_back(index1);
@ -297,9 +285,10 @@ namespace gtsam { namespace partition {
return boost::make_optional<MetisResult >(result); return boost::make_optional<MetisResult >(result);
} }
/* ************************************************************************* /* *************************************************************************/
template<class GenericGraph> template<class GenericGraph>
boost::optional<MetisResult> edgePartitionByMetis(const GenericGraph& graph, const vector<size_t>& keys, WorkSpace& workspace, bool verbose) { boost::optional<MetisResult> edgePartitionByMetis(const GenericGraph& graph,
const vector<size_t>& keys, WorkSpace& workspace, bool verbose) {
// a small hack for handling the camera1-camera2 case used in the unit tests // a small hack for handling the camera1-camera2 case used in the unit tests
if (graph.size() == 1 && keys.size() == 2) { if (graph.size() == 1 && keys.size() == 2) {
@ -338,7 +327,8 @@ namespace gtsam { namespace partition {
} }
if (verbose) { 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; int edgeCut = 0;
BOOST_FOREACH(const typename GenericGraph::value_type& factor, graph){ BOOST_FOREACH(const typename GenericGraph::value_type& factor, graph){

View File

@ -71,7 +71,7 @@ TEST ( Partition, separatorPartitionByMetis2 )
CHECK(C_expected == actual->C); CHECK(C_expected == actual->C);
} }
/* ************************************************************************* /* *************************************************************************/
// x0 - x2 - x3 - x5 // x0 - x2 - x3 - x5
TEST ( Partition, edgePartitionByMetis ) TEST ( Partition, edgePartitionByMetis )
{ {
@ -83,24 +83,25 @@ TEST ( Partition, edgePartitionByMetis )
WorkSpace workspace(6); WorkSpace workspace(6);
boost::optional<MetisResult> actual = edgePartitionByMetis<GenericGraph3D>(graph, keys, boost::optional<MetisResult> actual = edgePartitionByMetis<GenericGraph3D>(graph, keys,
workspace, false); workspace, true);
CHECK(actual.is_initialized()); CHECK(actual.is_initialized());
vector<size_t> A_expected; A_expected += 0, 2; // frontal vector<size_t> A_expected; A_expected += 0, 2; // frontal
vector<size_t> B_expected; B_expected += 3, 5; // frontal vector<size_t> B_expected; B_expected += 3, 5; // frontal
vector<size_t> C_expected; // separator vector<size_t> C_expected; // separator
// BOOST_FOREACH(const size_t a, actual->A) BOOST_FOREACH(const size_t a, actual->A)
// cout << a << " "; cout << a << " ";
// cout << endl; cout << endl;
// BOOST_FOREACH(const size_t b, actual->B) BOOST_FOREACH(const size_t b, actual->B)
// cout << b << " "; cout << b << " ";
// cout << endl; cout << endl;
CHECK(A_expected == actual->A || A_expected == actual->B); CHECK(A_expected == actual->A || A_expected == actual->B);
CHECK(B_expected == actual->B || B_expected == actual->A); CHECK(B_expected == actual->B || B_expected == actual->A);
CHECK(C_expected == actual->C); CHECK(C_expected == actual->C);
} }
/* *************************************************************************/
// x0 - x2 - x3 - x5 - x6 // x0 - x2 - x3 - x5 - x6
TEST ( Partition, edgePartitionByMetis2 ) TEST ( Partition, edgePartitionByMetis2 )
{ {
@ -111,7 +112,7 @@ TEST ( Partition, edgePartitionByMetis2 )
graph.push_back(boost::make_shared<GenericFactor3D>(5, 6, 3, NODE_POSE_3D, NODE_POSE_3D, 1)); graph.push_back(boost::make_shared<GenericFactor3D>(5, 6, 3, NODE_POSE_3D, NODE_POSE_3D, 1));
std::vector<size_t> keys; keys += 0, 2, 3, 5, 6; std::vector<size_t> keys; keys += 0, 2, 3, 5, 6;
WorkSpace workspace(6); WorkSpace workspace(5);
boost::optional<MetisResult> actual = edgePartitionByMetis<GenericGraph3D>(graph, keys, boost::optional<MetisResult> actual = edgePartitionByMetis<GenericGraph3D>(graph, keys,
workspace, false); workspace, false);
CHECK(actual.is_initialized()); CHECK(actual.is_initialized());