18 #include <boost/shared_array.hpp>
32 namespace gtsam {
namespace partition {
47 std::vector<idx_t>
vwgt;
59 printf(
"**********************************************************************\n");
60 printf(
"Graph Information ---------------------------------------------------\n");
61 printf(
" #Vertices: %d, #Edges: %u\n",
n, *(
xadj.get()+
n) / 2);
62 printf(
"\nND Partitioning... -------------------------------------------\n");
74 printf(
" Sep size: \t\t %d\n",
sepsize);
75 printf(
"**********************************************************************\n");
78 return std::make_pair(
sepsize, part_);
109 tpwgts2[
ncon+
i] = 1.0 - tpwgts2[
i];
118 std::cout <<
"Finished bisection:" << *
edgecut << std::endl;
134 std::vector<idx_t>
vwgt;
146 printf(
"**********************************************************************\n");
147 printf(
"Graph Information ---------------------------------------------------\n");
148 printf(
" #Vertices: %d, #Edges: %u\n",
n, *(
xadj.get()+
n) / 2);
149 printf(
"\nND Partitioning... -------------------------------------------\n");
163 printf(
"\nTiming Information --------------------------------------------------\n");
165 printf(
" Edge cuts: \t\t %d\n",
edgecut);
166 printf(
"**********************************************************************\n");
169 return std::make_pair(
edgecut, part_);
178 template <
class GenericGraph>
182 typedef std::vector<int>
Weights;
183 typedef std::vector<int> Neighbors;
184 typedef std::pair<Neighbors, Weights> NeighborsInfo;
187 std::vector<int>& dictionary = workspace.
dictionary;
191 int numNodes =
keys.size();
193 std::vector<NeighborsInfo> adjacencyMap;
194 adjacencyMap.resize(numNodes);
195 std::cout <<
"Number of nodes: " << adjacencyMap.size() << std::endl;
198 for(
const typename GenericGraph::value_type&
factor:
graph){
199 index1 = dictionary[
factor->key1.index];
200 index2 = dictionary[
factor->key2.index];
201 std::cout <<
"index1: " << index1 << std::endl;
202 std::cout <<
"index2: " << index2 << std::endl;
204 if (index1 >= 0 && index2 >= 0) {
205 std::pair<Neighbors, Weights>& adjacencyMap1 = adjacencyMap[index1];
206 std::pair<Neighbors, Weights>& adjacencyMap2 = adjacencyMap[index2];
208 adjacencyMap1.first.push_back(index2);
209 adjacencyMap1.second.push_back(
factor->weight);
210 adjacencyMap2.first.push_back(index1);
211 adjacencyMap2.second.push_back(
factor->weight);
212 }
catch(std::exception&
e){
213 std::cout <<
e.what() << std::endl;
226 int ind_xadj = 0, ind_adjncy = 0;
227 for(
const NeighborsInfo&
info: adjacencyMap) {
228 *(
xadj.get() + ind_xadj) = ind_adjncy;
229 std::copy(
info.first .begin(),
info.first .end(),
adjncy.get() + ind_adjncy);
230 std::copy(
info.second.begin(),
info.second.end(),
adjwgt.get() + ind_adjncy);
231 assert(
info.first.size() ==
info.second.size());
232 ind_adjncy +=
info.first.size();
235 if (ind_xadj != numNodes)
throw std::runtime_error(
"prepareMetisGraph_: ind_xadj != numNodes");
236 *(
xadj.get() + ind_xadj) = ind_adjncy;
240 template<
class GenericGraph>
242 const std::vector<size_t>&
keys,
WorkSpace& workspace,
bool verbose) {
244 size_t numKeys =
keys.size();
246 std::cout <<
graph.size() <<
" factors,\t" << numKeys <<
" nodes;\t" << std::endl;
254 if (!
sepsize)
return std::optional<MetisResult>();
262 int* ptr_part =
part.get();
263 std::vector<size_t>::const_iterator itKey =
keys.begin();
264 std::vector<size_t>::const_iterator itKeyLast =
keys.end();
265 while(itKey != itKeyLast) {
266 switch(*(ptr_part++)) {
267 case 0:
result.A.push_back(*(itKey++));
break;
268 case 1:
result.B.push_back(*(itKey++));
break;
269 case 2:
result.C.push_back(*(itKey++));
break;
270 default:
throw std::runtime_error(
"separatorPartitionByMetis: invalid results from Metis ND!");
275 std::cout <<
"total key: " <<
keys.size()
276 <<
" result(A,B,C) = " <<
result.A.size() <<
", " <<
result.B.size() <<
", "
277 <<
result.C.size() <<
"; sepsize from Metis = " <<
sepsize << std::endl;
282 std::cout <<
"total key: " <<
keys.size()
283 <<
" result(A,B,C) = " <<
result.A.size() <<
", " <<
result.B.size() <<
", " <<
result.C.size()
284 <<
"; sepsize from Metis = " <<
sepsize << std::endl;
285 throw std::runtime_error(
"separatorPartitionByMetis: invalid sepsize from Metis ND!");
292 template<
class GenericGraph>
294 const std::vector<size_t>&
keys,
WorkSpace& workspace,
bool verbose) {
297 if (
graph.size() == 1 &&
keys.size() == 2) {
305 size_t numKeys =
keys.size();
306 if (verbose) std::cout <<
graph.size() <<
" factors,\t" << numKeys <<
" nodes;\t" << std::endl;
315 result.A.reserve(numKeys);
316 result.B.reserve(numKeys);
317 int* ptr_part =
part.get();
318 std::vector<size_t>::const_iterator itKey =
keys.begin();
319 std::vector<size_t>::const_iterator itKeyLast =
keys.end();
320 while(itKey != itKeyLast) {
321 if (*ptr_part != 0 && *ptr_part != 1)
322 std::cout << *ptr_part <<
"!!!" << std::endl;
323 switch(*(ptr_part++)) {
324 case 0:
result.A.push_back(*(itKey++));
break;
325 case 1:
result.B.push_back(*(itKey++));
break;
326 default:
throw std::runtime_error(
"edgePartitionByMetis: invalid results from Metis ND!");
331 std::cout <<
"the size of two submaps in the reduced graph: " <<
result.A.size()
332 <<
" " <<
result.B.size() << std::endl;
335 for(
const typename GenericGraph::value_type&
factor:
graph){
346 std::cout <<
"weight " <<
factor->weight;;
354 std::cout <<
" CUT ";
356 std::cout << std::endl;
358 std::cout <<
"edgeCut: " << edgeCut << std::endl;
365 bool isLargerIsland(
const std::vector<size_t>& island1,
const std::vector<size_t>& island2) {
366 return island1.size() > island2.size();
372 std::cout <<
"island: ";
373 for(
const size_t key: island)
374 std::cout <<
key <<
" ";
375 std::cout << std::endl;
379 for(
const std::vector<std::size_t>& island: islands)
384 int numCamera = 0, numLandmark = 0;
386 if (int2symbol[
key].chr() ==
'x')
390 std::cout <<
"numCamera: " << numCamera <<
" numLandmark: " << numLandmark << std::endl;
394 template<
class GenericGraph>
399 std::vector<size_t>&
A = partitionResult.
A;
400 std::vector<size_t>&
B = partitionResult.
B;
401 std::vector<size_t>&
C = partitionResult.
C;
402 std::vector<int>& dictionary = workspace.
dictionary;
403 std::fill(dictionary.begin(), dictionary.end(), -1);
404 for(
const size_t a:
A)
406 for(
const size_t b:
B)
409 throw std::runtime_error(
"addLandmarkToPartitionResult: C is not empty");
413 for(
const typename GenericGraph::value_type&
factor:
graph) {
416 if (dictionary[
j] == 0)
418 else if (dictionary[
j] == -1)
419 dictionary[
j] = dictionary[
i];
421 if (dictionary[
j] != dictionary[
i])
428 for(
const size_t j: landmarkKeys) {
429 switch(dictionary[
j]) {
430 case 0:
C.push_back(
j);
break;
431 case 1:
A.push_back(
j);
break;
432 case 2:
B.push_back(
j);
break;
433 default: std::cout <<
j <<
": " << dictionary[
j] << std::endl;
434 throw std::runtime_error(
"addLandmarkToPartitionResult: wrong status for landmark");
439 #define REDUCE_CAMERA_GRAPH
442 template<
class GenericGraph>
445 const std::optional<std::vector<Symbol> >& int2symbol,
const bool reduceGraph) {
446 std::optional<MetisResult>
result;
447 GenericGraph reducedGraph;
448 std::vector<size_t> keyToPartition;
449 std::vector<size_t> cameraKeys, landmarkKeys;
451 if (!int2symbol.has_value())
452 throw std::invalid_argument(
"findSeparator: int2symbol must be valid!");
455 cameraKeys.reserve(
keys.size());
456 landmarkKeys.reserve(
keys.size());
458 if((*int2symbol)[
key].chr() ==
'x')
459 cameraKeys.push_back(
key);
461 landmarkKeys.push_back(
key);
464 keyToPartition = cameraKeys;
466 const std::vector<int>& dictionary = workspace.
dictionary;
468 std::cout <<
"original graph: V" <<
keys.size() <<
", E" <<
graph.size()
469 <<
" --> reduced graph: V" << cameraKeys.size() <<
", E" << reducedGraph.size() << std::endl;
474 if (!
result.has_value()) {
475 std::cout <<
"metis failed!" << std::endl;
481 std::cout <<
"the separator size: " <<
result->C.size() <<
" landmarks" << std::endl;
488 template<
class GenericGraph>
490 const int minNodesPerMap,
WorkSpace& workspace,
bool verbose,
491 const std::optional<std::vector<Symbol> >& int2symbol,
const bool reduceGraph,
492 const int minNrConstraintsPerCamera,
const int minNrConstraintsPerLandmark) {
495 verbose, int2symbol, reduceGraph);
498 typedef std::vector<size_t> Island;
499 std::list<Island> islands;
502 minNrConstraintsPerCamera, minNrConstraintsPerLandmark);
505 minNrConstraintsPerCamera, minNrConstraintsPerLandmark);
507 islands.insert(islands.end(), islands_in_A.begin(), islands_in_A.end());
508 islands.insert(islands.end(), islands_in_B.begin(), islands_in_B.end());
510 size_t numIsland0 = islands.size();
529 size_t oldSize = islands.size();
531 if (islands.size() < 2) {
532 std::cout <<
"numIsland: " << numIsland0 << std::endl;
533 throw std::runtime_error(
"findSeparator: found fewer than 2 submaps!");
536 std::list<Island>::reference island = islands.back();
537 if ((
int)island.size() >= minNodesPerMap)
break;
538 result->C.insert(
result->C.end(), island.begin(), island.end());
541 if (islands.size() != oldSize){
542 if (verbose) std::cout << oldSize <<
"-" << oldSize - islands.size() <<
" submap(s);\t" << std::endl;
545 if (verbose) std::cout << oldSize <<
" submap(s);\t" << std::endl;
550 std::fill(partitionTable.begin(), partitionTable.end(), -1);
552 partitionTable[
key] = 0;
554 for(
const Island& island: islands) {
556 for(
const size_t key: island) {
557 partitionTable[
key] = idx;
561 return islands.size();