Updating to new metis interface. Need to address prepareMetisGraph since its causing core dump on second edgeseparator test
parent
05e42ba452
commit
0aa32a748f
|
@ -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){
|
||||||
|
|
|
@ -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());
|
||||||
|
|
Loading…
Reference in New Issue