11 #if !defined(CGRAPHPARTITIONER_H) 12 #error "This file can't be included from outside of CGraphPartitioner.h" 23 template <
class GRAPH_MATRIX,
typename num_t>
35 if (in_A.getColCount() != (nodeCount = in_A.getRowCount()) )
44 Adj.setSize(nodeCount,nodeCount);
45 for (
size_t i=0;i<nodeCount;i++)
46 for (
size_t j=i;j<nodeCount;j++)
47 Adj(i,j)=Adj(j,i)= 0.5f*(in_A(i,j)+in_A(j,i));
52 GRAPH_MATRIX LAPLACIAN;
53 Adj.laplacian(LAPLACIAN);
72 for(
size_t i=0;i<nRows;i++)
75 out_part1.push_back( i );
76 else out_part2.push_back( i );
82 if (!out_part1.size() || !out_part2.size())
87 for (
size_t i=0;i<Adj.getColCount();i++)
88 if (i<=Adj.getColCount()/2)
89 out_part1.push_back(i);
90 else out_part2.push_back(i);
94 out_cut_value = nCut( Adj, out_part1, out_part2);
100 template <
class GRAPH_MATRIX,
typename num_t>
103 std::vector<vector_uint> &out_parts,
104 num_t threshold_Ncut,
106 bool useSpectralBisection,
108 unsigned minSizeClusters,
122 if (in_A.getColCount() != (nodeCount = in_A.getRowCount()) )
129 out_parts.push_back(p1);
136 Adj.setSize(nodeCount,nodeCount);
137 for (i=0;i<nodeCount;i++)
138 for (j=i;j<nodeCount;j++)
139 Adj(i,j)=Adj(j,i)= 0.5f*(in_A(i,j)+in_A(j,i));
144 if (useSpectralBisection)
145 SpectralBisection( Adj, p1, p2, cut_value,
false);
146 else exactBisection(Adj, p1, p2, cut_value,
false);
149 std::cout <<
format(
"Cut:%u=%u+%u,nCut=%.02f->",(
unsigned int)nodeCount,(
unsigned int)p1.size(),(
unsigned int)p2.size(),cut_value);
152 if (cut_value>threshold_Ncut || p1.size()<minSizeClusters || p2.size()<minSizeClusters )
155 std::cout <<
"->NO!" << std::endl;
159 for (i=0;i<nodeCount;i++) p1.push_back(i);
160 out_parts.push_back(p1);
165 std::cout <<
"->YES!" << std::endl;
168 std::vector<vector_uint> p1_parts, p2_parts;
175 GRAPH_MATRIX A_1( p1.size(),p1.size() );
176 for (i=0;i<p1.size();i++)
177 for (j=0;j<p1.size();j++)
178 A_1(i,j)= in_A(p1[i],p1[j]);
180 RecursiveSpectralPartition(A_1,p1_parts, threshold_Ncut, forceSimetry,useSpectralBisection, recursive, minSizeClusters);
185 GRAPH_MATRIX A_2( p2.size(),p2.size() );
186 for (i=0;i<p2.size();i++)
187 for (j=0;j<p2.size();j++)
188 A_2(i,j)= in_A(p2[i],p2[j]);
190 RecursiveSpectralPartition(A_2,p2_parts, threshold_Ncut, forceSimetry,useSpectralBisection, recursive, minSizeClusters);
196 for (i=0;i<p1_parts.size();i++)
198 for (j=0;j<p1_parts[i].size();j++)
199 p1_parts[i][j] = p1[ p1_parts[i][j] ];
200 out_parts.push_back(p1_parts[i]);
204 for (i=0;i<p2_parts.size();i++)
206 for (j=0;j<p2_parts[i].size();j++)
207 p2_parts[i][j] = p2[ p2_parts[i][j] ];
209 out_parts.push_back(p2_parts[i]);
216 out_parts.push_back(p1);
217 out_parts.push_back(p2);
228 template <
class GRAPH_MATRIX,
typename num_t>
230 const GRAPH_MATRIX &in_A,
235 size_t size1=in_part1.size();
236 size_t size2=in_part2.size();
243 cut_AB += in_A(in_part1[i],in_part2[j]);
249 assoc_AA += in_A(in_part1[i],in_part1[j]);
255 assoc_BB += in_A(in_part2[i],in_part2[j]);
257 num_t assoc_AV = assoc_AA + cut_AB;
258 num_t assoc_BV = assoc_BB + cut_AB;
262 else return cut_AB/assoc_AV + cut_AB/assoc_BV;
270 template <
class GRAPH_MATRIX,
typename num_t>
275 num_t &out_cut_value,
283 num_t partCutValue, bestCutValue = std::numeric_limits<num_t>::max();
287 if (in_A.getColCount() != (nodeCount = in_A.getRowCount()) )
295 Adj.setSize(nodeCount,nodeCount);
296 for (i=0;i<nodeCount;i++)
297 for (j=i;j<nodeCount;j++)
298 Adj(i,j)=Adj(j,i)= 0.5f*(in_A(i,j)+in_A(j,i));
309 partition.resize(nodeCount,
false);
318 for (i=0;i<nodeCount;i++)
322 else part1.push_back(i);
326 partCutValue = nCut(Adj,part1,part2);
328 if (partCutValue<bestCutValue)
330 bestCutValue = partCutValue;
331 bestPartition = partition;
339 carry = partition[i];
340 partition[i]=!partition[i];
342 }
while ( carry && i<nodeCount );
346 for (i=0;
end && i<nodeCount;i++)
347 end =
end && partition[i];
353 out_cut_value = bestCutValue;
358 for (i=0;i<nodeCount;i++)
360 if (bestPartition[i])
361 out_part2.push_back(i);
362 else out_part1.push_back(i);
std::vector< uint32_t > vector_uint
static void RecursiveSpectralPartition(GRAPH_MATRIX &in_A, std::vector< vector_uint > &out_parts, num_t threshold_Ncut=1, bool forceSimetry=true, bool useSpectralBisection=true, bool recursive=true, unsigned minSizeClusters=1, const bool verbose=false)
Performs the spectral recursive partition into K-parts for a given graph.
EIGEN_STRONG_INLINE bool eigenVectors(MATRIX1 &eVecs, MATRIX2 &eVals) const
[For square matrices only] Compute the eigenvectors and eigenvalues (sorted), both returned as matric...
#define THROW_EXCEPTION(msg)
std::vector< bool > vector_bool
A type for passing a vector of bools.
static void SpectralBisection(GRAPH_MATRIX &in_A, vector_uint &out_part1, vector_uint &out_part2, num_t &out_cut_value, bool forceSimetry=true)
Performs the spectral bisection of a graph.
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
static void exactBisection(GRAPH_MATRIX &in_A, vector_uint &out_part1, vector_uint &out_part2, num_t &out_cut_value, bool forceSimetry=true)
Performs an EXACT minimum n-Cut graph bisection, (Use CGraphPartitioner::SpectralBisection for a fast...
EIGEN_STRONG_INLINE void eigenValues(VECTOR &eVals) const
[For square matrices only] Compute the eigenvectors and eigenvalues (sorted), and return only the eig...
static num_t nCut(const GRAPH_MATRIX &in_A, const vector_uint &in_part1, const vector_uint &in_part2)
Returns the normaliced cut of a graph, given its adjacency matrix A and a bisection: ...
EIGEN_STRONG_INLINE double mean() const
Computes the mean of the entire matrix.