25 template <
class GRAPH_MATRIX,
typename num_t>
27 GRAPH_MATRIX& in_A, std::vector<uint32_t>& out_part1,
28 std::vector<uint32_t>& out_part2, num_t& out_cut_value,
bool forceSimetry)
31 GRAPH_MATRIX Adj, eigenVectors;
32 std::vector<typename GRAPH_MATRIX::Scalar> eigenValues;
35 if (in_A.cols() != int(nodeCount = in_A.rows()))
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));
53 GRAPH_MATRIX LAPLACIAN;
56 LAPLACIAN.eig(eigenVectors, eigenValues);
63 size_t nRows = eigenVectors.rows();
66 for (
size_t i = 0; i < nRows; i++)
mean += eigenVectors(i, colNo);
72 for (
size_t i = 0; i < nRows; i++)
74 if (eigenVectors(i, colNo) >=
mean)
75 out_part1.push_back(i);
77 out_part2.push_back(i);
83 if (!out_part1.size() || !out_part2.size())
88 for (
int i = 0; i < Adj.cols(); i++)
89 if (i <= Adj.cols() / 2)
90 out_part1.push_back(i);
92 out_part2.push_back(i);
96 out_cut_value = nCut(Adj, out_part1, out_part2);
102 template <
class GRAPH_MATRIX,
typename num_t>
104 GRAPH_MATRIX& in_A, std::vector<std::vector<uint32_t>>& out_parts,
105 num_t threshold_Ncut,
bool forceSimetry,
bool useSpectralBisection,
106 bool recursive,
unsigned minSizeClusters,
const bool verbose)
111 std::vector<uint32_t> p1, p2;
119 if (in_A.cols() != int(nodeCount = in_A.rows()))
126 out_parts.push_back(p1);
133 Adj.setSize(nodeCount, nodeCount);
134 for (i = 0; i < nodeCount; i++)
135 for (j = i; j < nodeCount; j++)
136 Adj(i, j) = Adj(j, i) = 0.5f * (in_A(i, j) + in_A(j, i));
142 if (useSpectralBisection)
143 SpectralBisection(Adj, p1, p2, cut_value,
false);
145 exactBisection(Adj, p1, p2, cut_value,
false);
149 "Cut:%u=%u+%u,nCut=%.02f->", (
unsigned int)nodeCount,
150 (
unsigned int)p1.size(), (
unsigned int)p2.size(), cut_value);
153 if (cut_value > threshold_Ncut || p1.size() < minSizeClusters ||
154 p2.size() < minSizeClusters)
156 if (
verbose) std::cout <<
"->NO!" << std::endl;
160 for (i = 0; i < nodeCount; i++) p1.push_back(i);
161 out_parts.push_back(p1);
165 if (
verbose) std::cout <<
"->YES!" << std::endl;
168 std::vector<std::vector<uint32_t>> 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++) A_1(i, j) = in_A(p1[i], p1[j]);
179 RecursiveSpectralPartition(
180 A_1, p1_parts, threshold_Ncut, forceSimetry,
181 useSpectralBisection, recursive, minSizeClusters);
186 GRAPH_MATRIX A_2(p2.size(), p2.size());
187 for (i = 0; i < p2.size(); i++)
188 for (j = 0; j < p2.size(); j++) A_2(i, j) = in_A(p2[i], p2[j]);
190 RecursiveSpectralPartition(
191 A_2, p2_parts, threshold_Ncut, forceSimetry,
192 useSpectralBisection, recursive, minSizeClusters);
198 for (i = 0; i < p1_parts.size(); i++)
200 for (j = 0; j < p1_parts[i].size(); j++)
201 p1_parts[i][j] = p1[p1_parts[i][j]];
202 out_parts.push_back(p1_parts[i]);
206 for (i = 0; i < p2_parts.size(); i++)
208 for (j = 0; j < p2_parts[i].size(); j++)
209 p2_parts[i][j] = p2[p2_parts[i][j]];
211 out_parts.push_back(p2_parts[i]);
218 out_parts.push_back(p1);
219 out_parts.push_back(p2);
229 template <
class GRAPH_MATRIX,
typename num_t>
231 const GRAPH_MATRIX& in_A,
const std::vector<uint32_t>& in_part1,
232 const std::vector<uint32_t>& in_part2)
235 const size_t size1 = in_part1.size();
236 const size_t size2 = in_part2.size();
241 for (i = 0; i < size1; i++)
242 for (j = 0; j < size2; j++) cut_AB += in_A(in_part1[i], in_part2[j]);
245 for (i = 0; i < size1; i++)
246 for (j = i; j < size1; j++)
247 if (i != j) assoc_AA += in_A(in_part1[i], in_part1[j]);
250 for (i = 0; i < size2; i++)
251 for (j = i; j < size2; j++)
252 if (i != j) assoc_BB += in_A(in_part2[i], in_part2[j]);
254 num_t assoc_AV = assoc_AA + cut_AB;
255 num_t assoc_BV = assoc_BB + cut_AB;
260 return cut_AB / assoc_AV + cut_AB / assoc_BV;
266 template <
class GRAPH_MATRIX,
typename num_t>
268 GRAPH_MATRIX& in_A, std::vector<uint32_t>& out_part1,
269 std::vector<uint32_t>& out_part2, num_t& out_cut_value,
bool forceSimetry)
274 std::vector<bool> partition, bestPartition;
275 std::vector<uint32_t> part1, part2;
276 num_t partCutValue, bestCutValue = std::numeric_limits<num_t>::max();
280 if (in_A.cols() != int(nodeCount = in_A.rows()))
288 Adj.setSize(nodeCount, nodeCount);
289 for (i = 0; i < nodeCount; i++)
290 for (j = i; j < nodeCount; j++)
291 Adj(i, j) = Adj(j, i) = 0.5f * (in_A(i, j) + in_A(j, i));
302 partition.resize(nodeCount,
false);
311 for (i = 0; i < nodeCount; i++)
320 partCutValue = nCut(Adj, part1, part2);
322 if (partCutValue < bestCutValue)
324 bestCutValue = partCutValue;
325 bestPartition = partition;
333 carry = partition[i];
334 partition[i] = !partition[i];
336 }
while (carry && i < nodeCount);
340 for (i = 0;
end && i < nodeCount; i++)
end =
end && partition[i];
345 out_cut_value = bestCutValue;
350 for (i = 0; i < nodeCount; i++)
352 if (bestPartition[i])
353 out_part2.push_back(i);
355 out_part1.push_back(i);
static num_t nCut(const GRAPH_MATRIX &in_A, const std::vector< uint32_t > &in_part1, const std::vector< uint32_t > &in_part2)
Returns the normaliced cut of a graph, given its adjacency matrix A and a bisection: ...
#define THROW_EXCEPTION(msg)
std::string std::string format(std::string_view fmt, ARGS &&... args)
Abstract graph and tree data structures, plus generic graph algorithms.
void laplacian(const MATIN &g, MATOUT &ret)
Computes the Laplacian of a square graph weight matrix.
This file implements miscelaneous matrix and matrix/vector operations, and internal functions in mrpt...
static void exactBisection(GRAPH_MATRIX &in_A, std::vector< uint32_t > &out_part1, std::vector< uint32_t > &out_part2, num_t &out_cut_value, bool forceSimetry=true)
Performs an EXACT minimum n-Cut graph bisection, (Use CGraphPartitioner::SpectralBisection for a fast...
#define ASSERT_(f)
Defines an assertion mechanism.
const_iterator end() const
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
static void RecursiveSpectralPartition(GRAPH_MATRIX &in_A, std::vector< std::vector< uint32_t >> &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.
double mean(const CONTAINER &v)
Computes the mean value of a vector.
static void SpectralBisection(GRAPH_MATRIX &in_A, std::vector< uint32_t > &out_part1, std::vector< uint32_t > &out_part2, num_t &out_cut_value, bool forceSimetry=true)
Performs the spectral bisection of a graph.
Finds the min-normalized-cut of a weighted undirected graph.