| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * FindSeparator-inl.h | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *   Created on: Nov 23, 2010 | 
					
						
							| 
									
										
										
										
											2014-02-21 03:36:14 +08:00
										 |  |  |  *   Updated: Feb 20. 2014 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  |  *       Author: nikai | 
					
						
							| 
									
										
										
										
											2014-02-21 03:36:14 +08:00
										 |  |  |  *       Author: Andrew Melim | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  |  *  Description: find the separator of bisectioning for a given graph | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <stdexcept>
 | 
					
						
							|  |  |  | #include <iostream>
 | 
					
						
							|  |  |  | #include <boost/tuple/tuple.hpp>
 | 
					
						
							|  |  |  | #include <boost/foreach.hpp>
 | 
					
						
							|  |  |  | #include <boost/shared_array.hpp>
 | 
					
						
							| 
									
										
										
										
											2014-02-21 03:36:14 +08:00
										 |  |  | #include <boost/timer.hpp>
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | extern "C" { | 
					
						
							|  |  |  | #include <metis.h>
 | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | #include "metislib.h"
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "FindSeparator.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace gtsam { namespace partition { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 03:36:14 +08:00
										 |  |  | 	typedef boost::shared_array<idx_t> sharedInts; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * Return the size of the separator and the partiion indices {part} | 
					
						
							|  |  |  | 	 * Part [j] is 0, 1, or 2, depending on | 
					
						
							|  |  |  | 	 * whether node j is in the left part of the graph, the right part, or the | 
					
						
							|  |  |  | 	 * separator, respectively | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 	std::pair<int, sharedInts> separatorMetis(idx_t n, const sharedInts& xadj, | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 		const sharedInts& adjncy, const sharedInts& adjwgt, bool verbose) { | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// control parameters
 | 
					
						
							| 
									
										
										
										
											2014-02-21 03:36:14 +08:00
										 |  |  | 		idx_t vwgt[n];                  // the weights of the vertices
 | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 		idx_t options[METIS_NOPTIONS]; | 
					
						
							|  |  |  | 		METIS_SetDefaultOptions(options);	// use defaults
 | 
					
						
							|  |  |  | 		idx_t sepsize;                      // the size of the separator, output
 | 
					
						
							|  |  |  | 		sharedInts part_(new idx_t[n]);      // the partition of each vertex, output
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// set uniform weights on the vertices
 | 
					
						
							|  |  |  | 		std::fill(vwgt, vwgt+n, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 03:36:14 +08:00
										 |  |  | 		// TODO: Fix at later time
 | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 		//boost::timer::cpu_timer TOTALTmr;
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		if (verbose) { | 
					
						
							|  |  |  | 			printf("**********************************************************************\n"); | 
					
						
							|  |  |  | 			printf("Graph Information ---------------------------------------------------\n"); | 
					
						
							|  |  |  | 			printf("  #Vertices: %d, #Edges: %u\n", n, *(xadj.get()+n) / 2); | 
					
						
							|  |  |  | 			printf("\nND Partitioning... -------------------------------------------\n"); | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 			//TOTALTmr.start()
 | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-21 03:36:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | 		// call metis parition routine
 | 
					
						
							| 
									
										
										
										
											2014-02-21 03:36:14 +08:00
										 |  |  | 		METIS_ComputeVertexSeparator(&n, xadj.get(), adjncy.get(),  | 
					
						
							|  |  |  |            vwgt, options, &sepsize, part_.get()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 		if (verbose) { | 
					
						
							|  |  |  | 			//boost::cpu_times const elapsed_times(timer.elapsed());
 | 
					
						
							|  |  |  | 			//printf("\nTiming Information --------------------------------------------------\n");
 | 
					
						
							|  |  |  | 			//printf("  Total:        \t\t %7.3f\n", elapsed_times);
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			printf("  Sep size:        \t\t %d\n", sepsize); | 
					
						
							|  |  |  | 			printf("**********************************************************************\n"); | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 		return std::make_pair(sepsize, part_); | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	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) | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-02-24 06:55:18 +08:00
										 |  |  |     idx_t i, ncon; | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | 		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;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		InitRandom(ctrl->seed); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		graph = SetupGraph(ctrl, *nvtxs, 1, xadj, adjncy, vwgt, NULL, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		AllocateWorkSpace(ctrl, graph); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   	ncon = graph->ncon; | 
					
						
							|  |  |  |   	ctrl->ncuts = 1; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  |   	/* determine the weights of the two partitions as a function of the weight of the
 | 
					
						
							|  |  |  |   	   target partition weights */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   	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);
 | 
					
						
							|  |  |  | 	//  *edgecut = graph->mincut;
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 	//  *sepsize = graph.pwgts[2];
 | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | 	  icopy(*nvtxs, graph->where, part); | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 		std::cout << "Finished bisection:" << *edgecut << std::endl; | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | 		FreeGraph(&graph); | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | 		FreeCtrl(&ctrl); | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	/**
 | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | 	 * Return the number of edge cuts and the partition indices {part} | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 	 * Part [j] is 0 or 1, depending on | 
					
						
							|  |  |  | 	 * whether node j is in the left part of the graph or the right part respectively | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 	std::pair<int, sharedInts> edgeMetis(idx_t n, const sharedInts& xadj,	const sharedInts& adjncy, | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | 		const sharedInts& adjwgt, bool verbose) { | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// control parameters
 | 
					
						
							| 
									
										
										
										
											2014-02-21 03:36:14 +08:00
										 |  |  | 		idx_t vwgt[n];                  // the weights of the vertices
 | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | 		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
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// set uniform weights on the vertices
 | 
					
						
							|  |  |  | 		std::fill(vwgt, vwgt+n, 1); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | 		//TODO: Fix later
 | 
					
						
							|  |  |  | 		//boost::timer TOTALTmr;
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		if (verbose) { | 
					
						
							|  |  |  | 			printf("**********************************************************************\n"); | 
					
						
							|  |  |  | 			printf("Graph Information ---------------------------------------------------\n"); | 
					
						
							|  |  |  | 			printf("  #Vertices: %d, #Edges: %u\n", n, *(xadj.get()+n) / 2); | 
					
						
							|  |  |  | 			printf("\nND Partitioning... -------------------------------------------\n"); | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | 			//cleartimer(TOTALTmr);
 | 
					
						
							|  |  |  | 			//starttimer(TOTALTmr);
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | 		//int wgtflag = 1; // only edge weights
 | 
					
						
							|  |  |  | 		//int numflag = 0; // c style numbering starting from 0
 | 
					
						
							|  |  |  | 		//int nparts = 2; // partition the graph to 2 submaps
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		modefied_EdgeComputeSeparator(&n, xadj.get(), adjncy.get(), vwgt, adjwgt.get(), | 
					
						
							|  |  |  | 				options, &edgecut, part_.get()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 03:36:14 +08:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		if (verbose) { | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | 			//stoptimer(TOTALTmr);
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			printf("\nTiming Information --------------------------------------------------\n"); | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | 			//printf("  Total:        \t\t %7.3f\n", gettimer(TOTALTmr));
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			printf("  Edge cuts:    \t\t %d\n", edgecut); | 
					
						
							|  |  |  | 			printf("**********************************************************************\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 		return std::make_pair(edgecut, part_); | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * Prepare the data structure {xadj} and {adjncy} required by metis | 
					
						
							|  |  |  | 	 * xadj always has the size equal to the no. of the nodes plus 1 | 
					
						
							|  |  |  | 	 * adjncy always has the size equal to two times of the no. of the edges in the Metis graph | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	template <class GenericGraph> | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 	void prepareMetisGraph(const GenericGraph& graph, const std::vector<size_t>& keys, WorkSpace& workspace, | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			sharedInts* ptr_xadj, sharedInts* ptr_adjncy, sharedInts* ptr_adjwgt) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		typedef int Weight; | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 		typedef std::vector<int> Weights; | 
					
						
							|  |  |  | 		typedef std::vector<int> Neighbors; | 
					
						
							|  |  |  | 		typedef std::pair<Neighbors, Weights> NeighborsInfo; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// set up dictionary
 | 
					
						
							|  |  |  | 		std::vector<int>& dictionary = workspace.dictionary; | 
					
						
							|  |  |  | 		workspace.prepareDictionary(keys); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-24 06:55:18 +08:00
										 |  |  | 		// prepare for {adjacencyMap}, a pair of neighbor indices and the correponding edge weights
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		int numNodes = keys.size(); | 
					
						
							|  |  |  | 		int numEdges = 0; | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 		std::vector<NeighborsInfo> adjacencyMap; | 
					
						
							| 
									
										
										
										
											2014-02-24 06:55:18 +08:00
										 |  |  | 		adjacencyMap.resize(numNodes); | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 		std::cout << "Number of nodes: " << adjacencyMap.size() << std::endl; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		int index1, index2; | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		BOOST_FOREACH(const typename GenericGraph::value_type& factor, graph){ | 
					
						
							|  |  |  | 			index1 = dictionary[factor->key1.index]; | 
					
						
							|  |  |  | 			index2 = dictionary[factor->key2.index]; | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			std::cout << "index1: " << index1 << std::endl; | 
					
						
							|  |  |  | 			std::cout << "index2: " << index2 << std::endl; | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 			// if both nodes are in the current graph, i.e. not a joint factor between frontal and separator
 | 
					
						
							|  |  |  | 			if (index1 >= 0 && index2 >= 0) {        | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			  std::pair<Neighbors, Weights>& adjacencyMap1 = adjacencyMap[index1]; | 
					
						
							|  |  |  | 			  std::pair<Neighbors, Weights>& adjacencyMap2 = adjacencyMap[index2]; | 
					
						
							| 
									
										
										
										
											2014-02-24 05:37:09 +08:00
										 |  |  | 				try{ | 
					
						
							| 
									
										
										
										
											2014-02-24 06:55:18 +08:00
										 |  |  | 				 adjacencyMap1.first.push_back(index2); | 
					
						
							|  |  |  | 				 adjacencyMap1.second.push_back(factor->weight); | 
					
						
							|  |  |  | 				 adjacencyMap2.first.push_back(index1); | 
					
						
							|  |  |  | 				 adjacencyMap2.second.push_back(factor->weight); | 
					
						
							| 
									
										
										
										
											2014-02-24 05:37:09 +08:00
										 |  |  | 				}catch(std::exception& e){ | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 					std::cout << e.what() << std::endl; | 
					
						
							| 
									
										
										
										
											2014-02-24 05:37:09 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 				numEdges++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// prepare for {xadj}, {adjncy}, and {adjwgt}
 | 
					
						
							| 
									
										
										
										
											2014-02-24 05:37:09 +08:00
										 |  |  | 		*ptr_xadj   = sharedInts(new idx_t[numNodes+1]); | 
					
						
							|  |  |  | 		*ptr_adjncy = sharedInts(new idx_t[numEdges*2]); | 
					
						
							|  |  |  | 		*ptr_adjwgt = sharedInts(new idx_t[numEdges*2]); | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		sharedInts& xadj = *ptr_xadj; | 
					
						
							|  |  |  | 		sharedInts& adjncy = *ptr_adjncy; | 
					
						
							|  |  |  | 		sharedInts& adjwgt = *ptr_adjwgt; | 
					
						
							|  |  |  | 		int ind_xadj = 0, ind_adjncy = 0; | 
					
						
							| 
									
										
										
										
											2014-02-24 06:55:18 +08:00
										 |  |  | 		BOOST_FOREACH(const NeighborsInfo& info, adjacencyMap) { | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			*(xadj.get() + ind_xadj) = ind_adjncy; | 
					
						
							|  |  |  | 			std::copy(info.first .begin(), info.first .end(), adjncy.get() + ind_adjncy); | 
					
						
							|  |  |  | 			std::copy(info.second.begin(), info.second.end(), adjwgt.get() + ind_adjncy); | 
					
						
							|  |  |  | 			assert(info.first.size() == info.second.size()); | 
					
						
							|  |  |  | 			ind_adjncy += info.first.size(); | 
					
						
							|  |  |  | 			ind_xadj ++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (ind_xadj != numNodes) throw std::runtime_error("prepareMetisGraph_: ind_xadj != numNodes"); | 
					
						
							|  |  |  | 		*(xadj.get() + ind_xadj) = ind_adjncy; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class GenericGraph> | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 	boost::optional<MetisResult> separatorPartitionByMetis(const GenericGraph& graph, | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 		const std::vector<size_t>& keys, WorkSpace& workspace, bool verbose) { | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		// create a metis graph
 | 
					
						
							|  |  |  | 		size_t numKeys = keys.size(); | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 		if (verbose)  | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			std::cout << graph.size() << " factors,\t" << numKeys << " nodes;\t" << std::endl; | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		sharedInts xadj, adjncy, adjwgt; | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		prepareMetisGraph<GenericGraph>(graph, keys, workspace, &xadj, &adjncy, &adjwgt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// run ND on the graph
 | 
					
						
							| 
									
										
										
										
											2014-02-24 06:55:18 +08:00
										 |  |  | 		size_t sepsize; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		sharedInts part; | 
					
						
							|  |  |  | 		boost::tie(sepsize, part) = separatorMetis(numKeys, xadj, adjncy, adjwgt, verbose); | 
					
						
							|  |  |  | 		if (!sepsize)	return boost::optional<MetisResult>(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 		// convert the 0-1-2 from Metis to 1-2-0, so that the separator is 0, as later
 | 
					
						
							|  |  |  | 		//  we will have more submaps
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		MetisResult result; | 
					
						
							|  |  |  | 		result.C.reserve(sepsize); | 
					
						
							|  |  |  | 		result.A.reserve(numKeys - sepsize); | 
					
						
							|  |  |  | 		result.B.reserve(numKeys - sepsize); | 
					
						
							|  |  |  | 		int* ptr_part = part.get(); | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 		std::vector<size_t>::const_iterator itKey = keys.begin(); | 
					
						
							|  |  |  | 		std::vector<size_t>::const_iterator itKeyLast = keys.end(); | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		while(itKey != itKeyLast) { | 
					
						
							|  |  |  | 			switch(*(ptr_part++)) { | 
					
						
							|  |  |  | 			case 0: result.A.push_back(*(itKey++)); break; | 
					
						
							|  |  |  | 			case 1: result.B.push_back(*(itKey++)); break; | 
					
						
							|  |  |  | 			case 2: result.C.push_back(*(itKey++)); break; | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			default: throw std::runtime_error("separatorPartitionByMetis: invalid results from Metis ND!"); | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (verbose) { | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			std::cout << "total key: " << keys.size() | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 										<< " result(A,B,C) = " << result.A.size() << ", " << result.B.size() << ", " | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 										<< result.C.size() << "; sepsize from Metis = " << sepsize << std::endl; | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 			//throw runtime_error("separatorPartitionByMetis:stop for debug");
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(result.C.size() != sepsize) { | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			std::cout << "total key: " << keys.size() | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 					<< " result(A,B,C) = " << result.A.size() << ", " << result.B.size() << ", " << result.C.size() | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 					<< "; sepsize from Metis = " << sepsize << std::endl; | 
					
						
							|  |  |  | 			throw std::runtime_error("separatorPartitionByMetis: invalid sepsize from Metis ND!"); | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return boost::make_optional<MetisResult >(result); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | 	/* *************************************************************************/  | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 	template<class GenericGraph> | 
					
						
							| 
									
										
										
										
											2014-02-22 07:20:43 +08:00
										 |  |  | 	boost::optional<MetisResult> edgePartitionByMetis(const GenericGraph& graph, | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 	 const std::vector<size_t>& keys, WorkSpace& workspace, bool verbose) { | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// a small hack for handling the camera1-camera2 case used in the unit tests
 | 
					
						
							|  |  |  | 		if (graph.size() == 1 && keys.size() == 2) { | 
					
						
							|  |  |  | 			MetisResult result; | 
					
						
							|  |  |  | 			result.A.push_back(keys.front()); | 
					
						
							|  |  |  | 			result.B.push_back(keys.back()); | 
					
						
							|  |  |  | 			return result; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// create a metis graph
 | 
					
						
							|  |  |  | 		size_t numKeys = keys.size(); | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 		if (verbose) std::cout << graph.size() << " factors,\t" << numKeys << " nodes;\t" << std::endl; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		sharedInts xadj, adjncy, adjwgt; | 
					
						
							|  |  |  | 		prepareMetisGraph<GenericGraph>(graph, keys, workspace, &xadj, &adjncy, &adjwgt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// run metis on the graph
 | 
					
						
							|  |  |  | 		int edgecut; | 
					
						
							|  |  |  | 		sharedInts part; | 
					
						
							|  |  |  | 		boost::tie(edgecut, part) = edgeMetis(numKeys, xadj, adjncy, adjwgt, verbose); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// convert the 0-1-2 from Metis to 1-2-0, so that the separator is 0, as later we will have more submaps
 | 
					
						
							|  |  |  | 		MetisResult result; | 
					
						
							|  |  |  | 		result.A.reserve(numKeys); | 
					
						
							|  |  |  | 		result.B.reserve(numKeys); | 
					
						
							|  |  |  | 		int* ptr_part = part.get(); | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 		std::vector<size_t>::const_iterator itKey = keys.begin(); | 
					
						
							|  |  |  | 		std::vector<size_t>::const_iterator itKeyLast = keys.end(); | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		while(itKey != itKeyLast) { | 
					
						
							|  |  |  | 			if (*ptr_part != 0 && *ptr_part != 1) | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 				std::cout << *ptr_part << "!!!" << std::endl; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			switch(*(ptr_part++)) { | 
					
						
							|  |  |  | 			case 0: result.A.push_back(*(itKey++)); break; | 
					
						
							|  |  |  | 			case 1: result.B.push_back(*(itKey++)); break; | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			default: throw std::runtime_error("edgePartitionByMetis: invalid results from Metis ND!"); | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (verbose) { | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			std::cout << "the size of two submaps in the reduced graph: " << result.A.size() | 
					
						
							|  |  |  | 				<< " " << result.B.size() << std::endl; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			int edgeCut = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			BOOST_FOREACH(const typename GenericGraph::value_type& factor, graph){ | 
					
						
							|  |  |  | 				int key1 = factor->key1.index; | 
					
						
							|  |  |  | 				int key2 = factor->key2.index; | 
					
						
							|  |  |  | 				// print keys and their subgraph assignment
 | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 				std::cout << key1; | 
					
						
							|  |  |  | 				if (std::find(result.A.begin(), result.A.end(), key1) != result.A.end()) std::cout <<"A "; | 
					
						
							|  |  |  | 				if (std::find(result.B.begin(), result.B.end(), key1) != result.B.end()) std::cout <<"B "; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 				std::cout << key2; | 
					
						
							|  |  |  | 				if (std::find(result.A.begin(), result.A.end(), key2) != result.A.end()) std::cout <<"A "; | 
					
						
							|  |  |  | 				if (std::find(result.B.begin(), result.B.end(), key2) != result.B.end()) std::cout <<"B "; | 
					
						
							|  |  |  |         std::cout << "weight " << factor->weight;; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// find vertices that were assigned to sets A & B. Their edge will be cut
 | 
					
						
							|  |  |  | 				if ((std::find(result.A.begin(), result.A.end(), key1) != result.A.end() && | 
					
						
							|  |  |  |   					 std::find(result.B.begin(), result.B.end(), key2) != result.B.end()) || | 
					
						
							|  |  |  |   					(std::find(result.B.begin(), result.B.end(), key1) != result.B.end() && | 
					
						
							|  |  |  |    					 std::find(result.A.begin(), result.A.end(), key2) != result.A.end())){ | 
					
						
							|  |  |  | 					edgeCut ++; | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 					std::cout << " CUT "; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 				std::cout << std::endl; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			std::cout << "edgeCut: " << edgeCut << std::endl; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return boost::make_optional<MetisResult >(result); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 	bool isLargerIsland(const std::vector<size_t>& island1, const std::vector<size_t>& island2) { | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		return island1.size() > island2.size(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	// debug functions
 | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 	void printIsland(const std::vector<size_t>& island) { | 
					
						
							|  |  |  | 		std::cout << "island: "; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		BOOST_FOREACH(const size_t key, island) | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			std::cout << key << " "; | 
					
						
							|  |  |  | 		std::cout << std::endl; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 	void printIslands(const std::list<std::vector<size_t> >& islands) { | 
					
						
							|  |  |  | 		BOOST_FOREACH(const std::vector<std::size_t>& island, islands) | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 				printIsland(island); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 	void printNumCamerasLandmarks(const std::vector<size_t>& keys, const std::vector<Symbol>& int2symbol) { | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		int numCamera = 0, numLandmark = 0; | 
					
						
							|  |  |  | 		BOOST_FOREACH(const size_t key, keys) | 
					
						
							|  |  |  | 		if (int2symbol[key].chr() == 'x') | 
					
						
							|  |  |  | 			numCamera++; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			numLandmark++; | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 		std::cout << "numCamera: " << numCamera << " numLandmark: " << numLandmark << std::endl; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class GenericGraph> | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 	void addLandmarkToPartitionResult(const GenericGraph& graph, const std::vector<size_t>& landmarkKeys, | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			MetisResult& partitionResult, WorkSpace& workspace) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// set up cameras in the dictionary
 | 
					
						
							|  |  |  | 		std::vector<size_t>& A = partitionResult.A; | 
					
						
							|  |  |  | 		std::vector<size_t>& B = partitionResult.B; | 
					
						
							|  |  |  | 		std::vector<size_t>& C = partitionResult.C; | 
					
						
							|  |  |  | 		std::vector<int>& dictionary = workspace.dictionary; | 
					
						
							|  |  |  | 		std::fill(dictionary.begin(), dictionary.end(), -1); | 
					
						
							|  |  |  | 		BOOST_FOREACH(const size_t a, A) | 
					
						
							|  |  |  | 			dictionary[a] = 1; | 
					
						
							|  |  |  | 		BOOST_FOREACH(const size_t b, B) | 
					
						
							|  |  |  | 			dictionary[b] = 2; | 
					
						
							|  |  |  | 		if (!C.empty()) | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			throw std::runtime_error("addLandmarkToPartitionResult: C is not empty"); | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// set up landmarks
 | 
					
						
							|  |  |  | 		size_t i,j; | 
					
						
							|  |  |  | 		BOOST_FOREACH(const typename GenericGraph::value_type& factor, graph) { | 
					
						
							|  |  |  | 			i = factor->key1.index; | 
					
						
							|  |  |  | 			j = factor->key2.index; | 
					
						
							|  |  |  | 			if (dictionary[j] == 0) // if the landmark is already in the separator, continue
 | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			else if (dictionary[j] == -1) | 
					
						
							|  |  |  | 				dictionary[j] = dictionary[i]; | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				if (dictionary[j] != dictionary[i]) | 
					
						
							|  |  |  | 					dictionary[j] = 0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | //			if (j == 67980)
 | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | //				std::cout << "dictionary[67980]" << dictionary[j] << std::endl;
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		BOOST_FOREACH(const size_t j, landmarkKeys) { | 
					
						
							|  |  |  | 			switch(dictionary[j]) { | 
					
						
							|  |  |  | 			case 0: C.push_back(j); break; | 
					
						
							|  |  |  | 			case 1: A.push_back(j); break; | 
					
						
							|  |  |  | 			case 2: B.push_back(j); break; | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			default: std::cout << j << ": " << dictionary[j] << std::endl; | 
					
						
							|  |  |  | 			throw std::runtime_error("addLandmarkToPartitionResult: wrong status for landmark"); | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define REDUCE_CAMERA_GRAPH
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class GenericGraph> | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 	boost::optional<MetisResult> findPartitoning(const GenericGraph& graph, const std::vector<size_t>& keys, | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			WorkSpace& workspace, bool verbose, | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			const boost::optional<std::vector<Symbol> >& int2symbol, const bool reduceGraph) { | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		boost::optional<MetisResult> result; | 
					
						
							|  |  |  | 		GenericGraph reducedGraph; | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 		std::vector<size_t> keyToPartition; | 
					
						
							|  |  |  | 		std::vector<size_t> cameraKeys, landmarkKeys; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		if (reduceGraph) { | 
					
						
							|  |  |  | 			if (!int2symbol.is_initialized()) | 
					
						
							|  |  |  | 				throw std::invalid_argument("findSeparator: int2symbol must be valid!"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// find out all the landmark keys, which are to be eliminated
 | 
					
						
							|  |  |  | 			cameraKeys.reserve(keys.size()); | 
					
						
							|  |  |  | 			landmarkKeys.reserve(keys.size()); | 
					
						
							|  |  |  | 			BOOST_FOREACH(const size_t key, keys) { | 
					
						
							|  |  |  | 				if((*int2symbol)[key].chr() == 'x') | 
					
						
							|  |  |  | 					cameraKeys.push_back(key); | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					landmarkKeys.push_back(key); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			keyToPartition = cameraKeys; | 
					
						
							|  |  |  | 			workspace.prepareDictionary(keyToPartition); | 
					
						
							|  |  |  | 			const std::vector<int>& dictionary = workspace.dictionary; | 
					
						
							|  |  |  | 			reduceGenericGraph(graph, cameraKeys, landmarkKeys, dictionary, reducedGraph); | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			std::cout << "original graph: V" << keys.size() << ", E" << graph.size() | 
					
						
							|  |  |  | 			<< " --> reduced graph: V" << cameraKeys.size() << ", E" << reducedGraph.size() << std::endl; | 
					
						
							| 
									
										
										
										
											2014-02-24 06:47:39 +08:00
										 |  |  | 			result = edgePartitionByMetis(reducedGraph, keyToPartition, workspace, verbose); | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		}	else // call Metis to partition the graph to A, B, C
 | 
					
						
							|  |  |  | 			result = separatorPartitionByMetis(graph, keys, workspace, verbose); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!result.is_initialized()) { | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			std::cout << "metis failed!" << std::endl; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (reduceGraph) { | 
					
						
							|  |  |  | 			addLandmarkToPartitionResult(graph, landmarkKeys, *result, workspace); | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			std::cout << "the separator size: " << result->C.size() << " landmarks" << std::endl; | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return result; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* ************************************************************************* */ | 
					
						
							|  |  |  | 	template<class GenericGraph> | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 	int findSeparator(const GenericGraph& graph, const std::vector<size_t>& keys, | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			const int minNodesPerMap, WorkSpace& workspace, bool verbose, | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			const boost::optional<std::vector<Symbol> >& int2symbol, const bool reduceGraph, | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			const int minNrConstraintsPerCamera, const int minNrConstraintsPerLandmark) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 		boost::optional<MetisResult> result = findPartitoning(graph, keys, workspace,  | 
					
						
							|  |  |  | 			verbose, int2symbol, reduceGraph); | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// find the island in A and B, and make them separated submaps
 | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 		typedef std::vector<size_t> Island; | 
					
						
							|  |  |  | 		std::list<Island> islands; | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 		std::list<Island> islands_in_A = findIslands(graph, result->A, workspace, | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 			minNrConstraintsPerCamera, minNrConstraintsPerLandmark); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 		std::list<Island> islands_in_B = findIslands(graph, result->B, workspace, | 
					
						
							| 
									
										
										
										
											2014-02-22 00:21:08 +08:00
										 |  |  | 			minNrConstraintsPerCamera, minNrConstraintsPerLandmark); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		islands.insert(islands.end(), islands_in_A.begin(), islands_in_A.end()); | 
					
						
							|  |  |  | 		islands.insert(islands.end(), islands_in_B.begin(), islands_in_B.end()); | 
					
						
							|  |  |  | 		islands.sort(isLargerIsland); | 
					
						
							|  |  |  | 		size_t numIsland0 = islands.size(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef NDEBUG
 | 
					
						
							|  |  |  | //		verbose = true;
 | 
					
						
							|  |  |  | //		if (!int2symbol) throw std::invalid_argument("findSeparator: int2symbol is not set!");
 | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | //		std::cout << "sep size: " << result->C.size() << "; ";
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | //		printNumCamerasLandmarks(result->C, *int2symbol);
 | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | //		std::cout << "no. of island: " << islands.size() << "; ";
 | 
					
						
							|  |  |  | //		std::cout << "island size: ";
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | //		BOOST_FOREACH(const Island& island, islands)
 | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | //			std::cout << island.size() << " ";
 | 
					
						
							|  |  |  | //		std::cout << std::endl;
 | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | //		BOOST_FOREACH(const Island& island, islands) {
 | 
					
						
							|  |  |  | //			printNumCamerasLandmarks(island, int2symbol);
 | 
					
						
							|  |  |  | //		}
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// absorb small components into the separator
 | 
					
						
							| 
									
										
										
										
											2014-02-24 06:55:18 +08:00
										 |  |  | 		size_t oldSize = islands.size(); | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 		while(true) { | 
					
						
							|  |  |  | 			if (islands.size() < 2) { | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 				std::cout << "numIsland: " << numIsland0 << std::endl; | 
					
						
							|  |  |  | 				throw std::runtime_error("findSeparator: found fewer than 2 submaps!"); | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			std::list<Island>::reference island = islands.back(); | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 			if ((int)island.size() >= minNodesPerMap) break; | 
					
						
							|  |  |  | 			result->C.insert(result->C.end(), island.begin(), island.end()); | 
					
						
							|  |  |  | 			islands.pop_back(); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-02-21 03:36:14 +08:00
										 |  |  | 		if (islands.size() != oldSize){ | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			if (verbose) std::cout << oldSize << "-" << oldSize - islands.size() << " submap(s);\t" << std::endl; | 
					
						
							| 
									
										
										
										
											2014-02-21 03:36:14 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else{ | 
					
						
							| 
									
										
										
										
											2014-05-06 04:35:22 +08:00
										 |  |  | 			if (verbose) std::cout << oldSize << " submap(s);\t" << std::endl; | 
					
						
							| 
									
										
										
										
											2014-02-21 03:36:14 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-01-29 08:38:28 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// generate the node map
 | 
					
						
							|  |  |  | 		std::vector<int>& partitionTable = workspace.partitionTable; | 
					
						
							|  |  |  | 		std::fill(partitionTable.begin(), partitionTable.end(), -1); | 
					
						
							|  |  |  | 		BOOST_FOREACH(const size_t key, result->C) | 
					
						
							|  |  |  | 			partitionTable[key] = 0; | 
					
						
							|  |  |  | 		int idx = 0; | 
					
						
							|  |  |  | 		BOOST_FOREACH(const Island& island, islands) { | 
					
						
							|  |  |  | 			idx++; | 
					
						
							|  |  |  | 			BOOST_FOREACH(const size_t key, island) { | 
					
						
							|  |  |  | 				partitionTable[key] = idx; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return islands.size(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }} //namespace
 |