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" {
#include <metis.h>
#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<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);
//============================================================
// 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<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
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<NeighborsInfo> adjancyMap; // TODO: set is slow, but have to use it to remove duplicated edges
vector<NeighborsInfo> 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<Neighbors, Weights>& adjancyMap1 = adjancyMap[index1];
pair<Neighbors, Weights>& 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<MetisResult >(result);
}
/* *************************************************************************
/* *************************************************************************/
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
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){

View File

@ -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<MetisResult> actual = edgePartitionByMetis<GenericGraph3D>(graph, keys,
workspace, false);
workspace, true);
CHECK(actual.is_initialized());
vector<size_t> A_expected; A_expected += 0, 2; // frontal
vector<size_t> B_expected; B_expected += 3, 5; // frontal
vector<size_t> 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<GenericFactor3D>(5, 6, 3, NODE_POSE_3D, NODE_POSE_3D, 1));
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,
workspace, false);
CHECK(actual.is_initialized());