11void ttk::SeparatrixStability::assignmentSolver(
12 std::vector<std::vector<double>> &costMatrix,
13 std::vector<ttk::MatchingType> &matching) {
14 if(costMatrix.size() > 0) {
22void ttk::SeparatrixStability::buildCostMatrix(
23 const std::vector<std::array<double, 3>> &coords1,
24 const std::vector<std::array<double, 3>> &coords2,
25 const std::vector<double> &scalars1,
26 const std::vector<double> &scalars2,
27 std::vector<std::vector<double>> &costMatrix) {
28 int size_1 = coords1.size();
29 int size_2 = coords2.size();
30 if(size_1 == size_2) {
31 costMatrix.resize(size_1);
32 for(
int i = 0; i < size_1; i++) {
33 costMatrix[i].resize(size_1);
35 for(
int i = 0; i < size_1; i++) {
36 for(
int j = 0; j < size_1; j++) {
38 = std::sqrt(Px * std::pow(coords1[i][0] - coords2[j][0], 2)
39 + Py * std::pow(coords1[i][1] - coords2[j][1], 2)
40 + Pz * std::pow(coords1[i][2] - coords2[j][2], 2)
41 + Pf * std::pow(scalars1[i] - scalars2[j], 2));
46 costMatrix.resize(size_1 + size_2);
47 for(
int i = 0; i < size_1 + size_2; i++) {
48 costMatrix[i].resize(size_1 + size_2);
50 for(
int i = 0; i < size_1; i++) {
51 for(
int j = 0; j < size_2; j++) {
53 = std::sqrt(Px * std::pow(coords1[i][0] - coords2[j][0], 2)
54 + Py * std::pow(coords1[i][1] - coords2[j][1], 2)
55 + Pz * std::pow(coords1[i][2] - coords2[j][2], 2));
58 for(
int i = size_1; i < size_1 + size_2; i++) {
59 for(
int j = 0; j < size_2; j++) {
60 costMatrix[i][j] = epsilon;
63 for(
int i = 0; i < size_1; i++) {
64 for(
int j = size_2; j < size_2 + size_1; j++) {
65 costMatrix[i][j] = epsilon;
71int ttk::SeparatrixStability::buildMatchingsWithOtherBlocks(
72 const std::vector<std::vector<std::array<double, 3>>> &coords,
73 const std::vector<std::vector<double>> &scalars,
75 std::vector<std::vector<MatchingType>> &matchings) {
77 int n_blocks = coords.size();
79 for(
int i = 0; i < n_blocks; i++) {
82 std::vector<std::vector<double>> costMatrix;
83 int blockIdInMatchingVector = i < block_id ? i : i - 1;
85 coords[block_id], coords[i], scalars[block_id], scalars[i], costMatrix);
86 assignmentSolver(costMatrix, matchings[blockIdInMatchingVector]);
91int ttk::SeparatrixStability::buildOccurrenceArraysFull(
92 const std::vector<GraphMatrixFull> &adjacencyMatrices,
93 const int &n_separatrices,
94 const std::vector<std::vector<std::array<double, 3>>> &coordsSource,
95 const std::vector<std::vector<std::array<double, 3>>> &coordsDestination,
96 const std::vector<std::vector<double>> &scalarsSource,
97 const std::vector<std::vector<double>> &scalarsDestination,
99 std::vector<int> &edgeOccurrences,
100 std::vector<bool> &isIsomorphicWith,
101 std::vector<std::vector<int>> &matchingArraySource,
102 std::vector<std::vector<int>> &matchingArrayDestination,
103 std::vector<std::vector<int>> &matchingArraySeparatrix) {
105 int n_blocks = adjacencyMatrices.size();
106 int n_sourceThisBlock = adjacencyMatrices[block_id].size();
107 int n_destinationThisBlock = adjacencyMatrices[block_id][0].size();
109 isIsomorphicWith.resize(n_blocks,
true);
110 matchingArraySource.resize(n_blocks, std::vector<int>());
111 for(
int k = 0; k < n_blocks; k++) {
112 matchingArraySource[k].resize(adjacencyMatrices[k].size(), -2);
114 matchingArrayDestination.resize(n_blocks, std::vector<int>());
115 for(
int k = 0; k < n_blocks; k++) {
116 matchingArrayDestination[k].resize(adjacencyMatrices[k][0].size(), -2);
119 edgeOccurrences.resize(n_separatrices, 1);
121 std::vector<std::vector<MatchingType>> matchingsSource(n_blocks - 1);
122 std::vector<std::vector<MatchingType>> matchingsDestination(n_blocks - 1);
124 buildMatchingsWithOtherBlocks(
125 coordsSource, scalarsSource, block_id, matchingsSource);
126 buildMatchingsWithOtherBlocks(
127 coordsDestination, scalarsDestination, block_id, matchingsDestination);
129 for(
int k = 0; k < n_blocks; k++) {
131 int n_source = adjacencyMatrices[k].size();
132 int n_destination = adjacencyMatrices[k][0].size();
135 for(
int i = 0; i < n_destination; i++) {
136 matchingArrayDestination[k][i] = i;
138 for(
int i = 0; i < n_source; i++) {
139 matchingArraySource[k][i] = i;
141 for(
int i = 0; i < n_separatrices; i++) {
142 matchingArraySeparatrix[k][i] = i;
147 int otherBlockdIdMatchingsVector = k < block_id ? k : k - 1;
148 int matchingsSourceSize
149 = n_source == n_sourceThisBlock ? n_source : n_source + n_sourceThisBlock;
150 int matchingsDestinationSize = n_destination == n_destinationThisBlock
152 : n_destination + n_destinationThisBlock;
153 for(
int i = 0; i < matchingsSourceSize; i++) {
154 for(
int j = 0; j < matchingsDestinationSize; j++) {
155 int thisBlockSourceId
156 = std::get<0>(matchingsSource[otherBlockdIdMatchingsVector][i]);
157 int thisBlockDestinationId
158 = std::get<0>(matchingsDestination[otherBlockdIdMatchingsVector][j]);
159 int otherBlockSourceId
160 = std::get<1>(matchingsSource[otherBlockdIdMatchingsVector][i]);
161 int otherBlockDestinationId
162 = std::get<1>(matchingsDestination[otherBlockdIdMatchingsVector][j]);
163 if(otherBlockDestinationId >= n_destination
164 || otherBlockSourceId >= n_source)
166 if(thisBlockSourceId >= n_sourceThisBlock) {
167 matchingArraySource[k][otherBlockSourceId] = -1;
169 if(thisBlockDestinationId >= n_destinationThisBlock) {
170 matchingArrayDestination[k][otherBlockDestinationId] = -1;
172 if(thisBlockDestinationId >= n_destinationThisBlock
173 || thisBlockSourceId >= n_sourceThisBlock)
176 matchingArrayDestination[k][otherBlockDestinationId]
177 = thisBlockDestinationId;
178 matchingArraySource[k][otherBlockSourceId] = thisBlockSourceId;
179 if(adjacencyMatrices[block_id][thisBlockSourceId]
180 [thisBlockDestinationId]
182 && adjacencyMatrices[k][otherBlockSourceId][otherBlockDestinationId]
184 int separatriceId = adjacencyMatrices[block_id][thisBlockSourceId]
185 [thisBlockDestinationId];
186 int separatriceIdInOtherBlock
187 = adjacencyMatrices[k][otherBlockSourceId][otherBlockDestinationId];
188 edgeOccurrences[separatriceId]++;
189 matchingArraySeparatrix[k][separatriceIdInOtherBlock] = separatriceId;
190 }
else if((adjacencyMatrices[block_id][thisBlockSourceId]
191 [thisBlockDestinationId]
193 ^ (adjacencyMatrices[k][otherBlockSourceId]
194 [otherBlockDestinationId]
196 isIsomorphicWith[k] =
false;
205 matchingArrayDestination.begin(), matchingArrayDestination.end(),
206 [](
const std::vector<int> &a,
const std::vector<int> &b) {
207 return a.size() < b.size();
210 for(
int i = 0; i < n_blocks; i++) {
211 int sourceSize = matchingArraySource[i].size();
212 for(
int j = 0; j < sourceSize; j++) {
213 matchingArraySource[i][j] += offset;
220void ttk::SeparatrixStability::computeGraphMinor(
221 const GraphMatrixFull &adjacencyMatrixFull,
222 GraphMatrixMinor &adjacencyMatrix) {
223 int n_row = adjacencyMatrixFull.size();
224 int n_col = adjacencyMatrixFull[0].size();
225 adjacencyMatrix.resize(n_col);
226 for(
int i = 0; i < n_col; i++) {
227 adjacencyMatrix[i].resize(n_col);
230 for(
int i = 0; i < n_row; i++) {
231 for(
int j = 0; j < n_col; j++) {
232 if(adjacencyMatrixFull[i][j] != -1) {
233 for(
int k = 0; k < j; k++) {
234 if(adjacencyMatrixFull[i][k] != -1) {
235 std::pair<int, int> newEdge = std::make_pair(
236 adjacencyMatrixFull[i][j], adjacencyMatrixFull[i][k]);
237 adjacencyMatrix[k][j].push_back(newEdge);
245int ttk::SeparatrixStability::buildOccurrenceArraysMinor(
246 const std::vector<GraphMatrixFull> &adjacencyMatricesFull,
247 const int &n_separatrices,
248 const std::vector<std::vector<std::array<double, 3>>> &coords,
249 const std::vector<std::vector<double>> &scalars,
251 std::vector<int> &edgeOccurrences,
252 std::vector<bool> &isIsomorphicWith,
253 std::vector<std::vector<int>> &matchingArray,
254 std::vector<std::vector<int>> &matchingArraySeparatrix) {
256 int n_blocks = adjacencyMatricesFull.size();
257 isIsomorphicWith.resize(n_blocks,
true);
259 std::vector<GraphMatrixMinor> adjacencyMatricesMinor(n_blocks);
261 for(
int i = 0; i < n_blocks; i++) {
262 computeGraphMinor(adjacencyMatricesFull[i], adjacencyMatricesMinor[i]);
265 int n_pointsThisBlock = adjacencyMatricesMinor[block_id].size();
267 matchingArray.resize(n_blocks, std::vector<int>());
268 for(
int i = 0; i < n_blocks; i++) {
269 matchingArray[i].resize(adjacencyMatricesMinor[i].size(), -2);
272 for(
int i = 0; i < n_pointsThisBlock; i++) {
273 matchingArray[block_id][i] = i;
276 edgeOccurrences.resize(n_separatrices);
278 for(
int i = 0; i < n_pointsThisBlock; i++) {
279 for(
int j = 0; j < n_pointsThisBlock; j++) {
280 if(!adjacencyMatricesMinor[block_id][i][j].empty()) {
282 for(
auto edge : adjacencyMatricesMinor[block_id][i][j]) {
283 edgeOccurrences[edge.first] = 1;
284 edgeOccurrences[edge.second] = 1;
290 int mergeSeparatrixCount{};
291 for(
int i = 0; i < n_pointsThisBlock; i++) {
292 for(
int j = 0; j < n_pointsThisBlock; j++) {
293 if(!adjacencyMatricesMinor[block_id][i][j].empty()) {
294 for(
auto e : adjacencyMatricesMinor[block_id][i][j]) {
295 int sepId_1 = e.first;
296 int sepId_2 = e.second;
297 matchingArraySeparatrix[block_id][sepId_1] = mergeSeparatrixCount;
298 matchingArraySeparatrix[block_id][sepId_2] = mergeSeparatrixCount;
299 mergeSeparatrixCount++;
305 std::vector<std::vector<MatchingType>> matchings(n_blocks - 1);
306 buildMatchingsWithOtherBlocks(coords, scalars, block_id, matchings);
308 for(
int k = 0; k < n_blocks; k++) {
311 int n_points = adjacencyMatricesMinor[k].size();
313 int otherBlockdIdMatchingsVector = k < block_id ? k : k - 1;
315 = n_points == n_pointsThisBlock ? n_points : n_points + n_pointsThisBlock;
317 for(
int i = 0; i < n_matchings; i++) {
319 = std::get<0>(matchings[otherBlockdIdMatchingsVector][i]);
320 int otherBlockPointId
321 = std::get<1>(matchings[otherBlockdIdMatchingsVector][i]);
322 if(otherBlockPointId >= n_points)
324 if(thisBlockPointId >= n_pointsThisBlock) {
325 matchingArray[k][otherBlockPointId] = -1;
328 matchingArray[k][otherBlockPointId]
329 = matchingArray[block_id][thisBlockPointId];
332 for(
int i = 0; i < n_matchings; i++) {
333 for(
int j = i + 1; j < n_matchings; j++) {
334 int tmp2 = std::get<0>(matchings[otherBlockdIdMatchingsVector][j]);
335 int tmp1 = std::get<0>(matchings[otherBlockdIdMatchingsVector][i]);
336 int thisBlockVertex1 = std::min(tmp1, tmp2);
337 int thisBlockVertex2 = std::max(tmp1, tmp2);
338 tmp1 = std::get<1>(matchings[otherBlockdIdMatchingsVector][i]);
339 tmp2 = std::get<1>(matchings[otherBlockdIdMatchingsVector][j]);
340 int otherBlockVertex1 = std::min(tmp1, tmp2);
341 int otherBlockVertex2 = std::max(tmp1, tmp2);
342 if(thisBlockVertex1 >= n_pointsThisBlock
343 || thisBlockVertex2 >= n_pointsThisBlock
344 || otherBlockVertex1 >= n_points || otherBlockVertex2 >= n_points)
346 bool existsInOtherBlock
347 = !adjacencyMatricesMinor[k][otherBlockVertex1][otherBlockVertex2]
350 if(!adjacencyMatricesMinor[block_id][thisBlockVertex1][thisBlockVertex2]
352 && existsInOtherBlock > 0) {
353 for(
auto edge : adjacencyMatricesMinor[block_id][thisBlockVertex1]
354 [thisBlockVertex2]) {
355 std::pair<int, int> edgeInOtherBlock
356 = adjacencyMatricesMinor[k][otherBlockVertex1][otherBlockVertex2]
358 edgeOccurrences[edge.first] += existsInOtherBlock;
359 edgeOccurrences[edge.second] += existsInOtherBlock;
360 matchingArraySeparatrix[k][edgeInOtherBlock.first]
361 = matchingArraySeparatrix[block_id][edge.first];
362 matchingArraySeparatrix[k][edgeInOtherBlock.second]
363 = matchingArraySeparatrix[block_id][edge.second];
365 }
else if((!adjacencyMatricesMinor[block_id][thisBlockVertex1]
368 ^ existsInOtherBlock) {
369 isIsomorphicWith[k] =
false;
378 const std::vector<GraphMatrixFull> &adjacencyMatrices,
379 const std::vector<int> &separatrixCountForEachBlock,
380 const std::vector<std::vector<std::array<double, 3>>> &coordsSource,
381 const std::vector<std::vector<std::array<double, 3>>> &coordsDestination,
382 const std::vector<std::vector<double>> &scalarsSource,
383 const std::vector<std::vector<double>> &scalarsDestination,
384 const bool &mergeEdgesOnSaddles,
385 std::vector<std::vector<int>> &edgesOccurrencesForEachBlock,
386 std::vector<std::vector<bool>> &isomorphismForEachBlock,
387 std::vector<std::vector<std::vector<int>>> &matchingArrayForEachBlockSource,
388 std::vector<std::vector<std::vector<int>>>
389 &matchingArrayForEachBlockDestination,
390 std::vector<std::vector<std::vector<int>>>
391 &matchingArraySeparatrixForEachBlock) {
393 int n_blocks = adjacencyMatrices.size();
395 for(
int i = 0; i < n_blocks; i++) {
396 matchingArraySeparatrixForEachBlock[i].resize(n_blocks);
397 for(
int j = 0; j < n_blocks; j++) {
398 matchingArraySeparatrixForEachBlock[i][j].resize(
399 separatrixCountForEachBlock[j], -1);
403#ifdef TTK_ENABLE_OPENMP
404#pragma omp parallel for num_threads(threadNumber_)
406 for(
int i = 0; i < n_blocks; i++) {
407 if(!mergeEdgesOnSaddles) {
408 status = this->buildOccurrenceArraysFull(
409 adjacencyMatrices, separatrixCountForEachBlock[i], coordsSource,
410 coordsDestination, scalarsSource, scalarsDestination, i,
411 edgesOccurrencesForEachBlock[i], isomorphismForEachBlock[i],
412 matchingArrayForEachBlockSource[i],
413 matchingArrayForEachBlockDestination[i],
414 matchingArraySeparatrixForEachBlock[i]);
416 status = this->buildOccurrenceArraysMinor(
417 adjacencyMatrices, separatrixCountForEachBlock[i], coordsDestination,
418 scalarsDestination, i, edgesOccurrencesForEachBlock[i],
419 isomorphismForEachBlock[i], matchingArrayForEachBlockDestination[i],
420 matchingArraySeparatrixForEachBlock[i]);
int run(std::vector< MatchingType > &matchings) override
virtual int setInput(std::vector< std::vector< dataType > > &C_)
virtual void clearMatrix()
void setDebugMsgPrefix(const std::string &prefix)
int buildOccurrenceArrays(const std::vector< GraphMatrixFull > &adjacencyMatrices, const std::vector< int > &separatrixCountForEachBlock, const std::vector< std::vector< std::array< double, 3 > > > &coordsSource, const std::vector< std::vector< std::array< double, 3 > > > &coordsDestination, const std::vector< std::vector< double > > &scalarsSource, const std::vector< std::vector< double > > &scalarsDestination, const bool &mergeEdgesOnSaddles, std::vector< std::vector< int > > &edgesOccurrencesForEachBlock, std::vector< std::vector< bool > > &isomorphismForEachBlock, std::vector< std::vector< std::vector< int > > > &matchingArrayForEachBlockSource, std::vector< std::vector< std::vector< int > > > &matchingArrayForEachBlockDestination, std::vector< std::vector< std::vector< int > > > &matchingArraySeparatrixForEachBlock)