Zoltan2
Loading...
Searching...
No Matches
Zoltan2_AlgND.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Zoltan2: A package of combinatorial algorithms for scientific computing
4//
5// Copyright 2012 NTESS and the Zoltan2 contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10//MMW need to specify that this requires Zoltan
11
12#ifndef _ZOLTAN2_ALGND_HPP_
13#define _ZOLTAN2_ALGND_HPP_
14
17#include <Zoltan2_Algorithm.hpp>
18#include <Zoltan2_AlgZoltan.hpp>
19
21
22#include <sstream>
23#include <string>
24#include <bitset>
25
30namespace Zoltan2
31{
32
34
46 template <typename Adapter>
47 class AlgND : public Algorithm<Adapter>
48 {
49
50 private:
51 typedef typename Adapter::part_t part_t;
52
53 typedef typename Adapter::lno_t lno_t;
54 typedef typename Adapter::gno_t gno_t;
55
56 const RCP<const Environment> mEnv;
57 const RCP<const Comm<int>> mProblemComm;
58
59 std::string mPartitionMethod;
60
61 const RCP<const typename Adapter::base_adapter_t> mBaseInputAdapter;
62 modelFlag_t graphFlags;
63
64 void getBoundLayer(part_t levelIndx, const std::vector<part_t> &partMap,
65 const part_t *parts, const std::set<lno_t> &excVerts,
66 lno_t &bigraphNumS, lno_t &bigraphNumT, lno_t &bigraphNumE,
67 std::vector<lno_t> &bigraphCRSRowPtr, std::vector<lno_t> &bigraphCRSCols,
68 std::vector<lno_t> &bigraphVMapU, std::vector<lno_t> &bigraphVMapV,
69 const RCP<const GraphModel<Adapter>> &graphModel);
70
71 void buildPartTree(part_t level, std::vector<part_t> &levIndx,
72 part_t startV, const std::vector<part_t> &permPartNums,
73 const std::vector<part_t> &splitRangeBeg,
74 const std::vector<part_t> &splitRangeEnd,
75 const std::vector<part_t> &treeVertParents,
76 std::vector<part_t> &sepLevels, std::vector<std::set<part_t>> &sepParts1,
77 std::vector<std::set<part_t>> &sepParts2, part_t &maxLev,
78 part_t &sepTreeIndx, part_t *sepTreeView,
79 std::vector<std::pair<part_t, part_t>> &treeIndxToSepLev);
80
81 void fillSolutionIperm(const RCP<const GraphModel<Adapter>> &graphModel,
82 const part_t *parts, const std::set<lno_t> &sepVerts,
83 const std::vector<std::vector<std::set<lno_t>>> &sepVertsByLevel,
84 const std::vector<std::pair<part_t, part_t>> &treeIndxToSepLev,
85 lno_t *ipermView, lno_t *sepRangeView);
86
87 void getIdsOfPart(const RCP<const GraphModel<Adapter>> &graphModel, const part_t *parts,
88 part_t targetPart, const std::set<lno_t> &idsToExcl, std::set<lno_t> &outIds);
89
90 public:
91 // Constructor
92 AlgND(const RCP<const Environment> &env_,
93 const RCP<const Comm<int>> &problemComm_,
94 const RCP<const typename Adapter::base_adapter_t> &baseInputAdapter_,
95 const modelFlag_t &graphFlags_)
96 : mEnv(env_), mProblemComm(problemComm_), mPartitionMethod("rcb"),
97 mBaseInputAdapter(baseInputAdapter_), graphFlags(graphFlags_)
98 {
99#ifndef INCLUDE_ZOLTAN2_EXPERIMENTAL
100 Z2_THROW_EXPERIMENTAL("Zoltan2 AlgND is strictly experimental software ")
101#endif
102
103 if (mProblemComm->getSize() != 1)
104 {
105 Z2_THROW_SERIAL("Zoltan2 AlgND is strictly serial!");
106 }
107
108 const Teuchos::ParameterList &pl = mEnv->getParameters();
109 const Teuchos::ParameterEntry *pe;
110
111 pe = pl.getEntryPtr("edge_separator_method");
112
113 if (pe)
114 {
115 mPartitionMethod = pe->getValue<std::string>(&mPartitionMethod);
116 }
117 }
118
119 // Ordering method
120 int localOrder(const RCP<LocalOrderingSolution<lno_t>> &solution_);
121 int globalOrder(const RCP<GlobalOrderingSolution<gno_t>> &solution_);
122
125 static void getValidParameters(ParameterList &pl)
126 {
127
128 RCP<Teuchos::StringValidator> es_method_Validator =
129 Teuchos::rcp(new Teuchos::StringValidator(Teuchos::tuple<std::string>("rcb", "phg")));
130
131 pl.set("edge_separator_method", "rcb", "ND ordering - Edge separator method", es_method_Validator);
132 }
133 };
135
138 template <typename Adapter>
140 const RCP<GlobalOrderingSolution<gno_t>> &solution_)
141 {
142 throw std::logic_error("AlgND does not support global ordering.");
143 }
144
146
149 template <typename Adapter>
151 {
152 mEnv->debug(DETAILED_STATUS, std::string("Entering AlgND"));
153
155 // First, let's partition with RCB using Zoltan. Eventually, we will change
156 // to give an option to use PHG
158
160 // Create parameter list for partitioning environment
162 Teuchos::ParameterList partParams;
163
164 part_t numParts = mEnv->getParameters().template get<part_t>("num_global_parts");
165
166 partParams.set("num_global_parts", numParts);
167
168 // Keeping partitioning tree
169 partParams.set("keep_partition_tree", true);
170
171 // Set Zoltan parameter lists
172 Teuchos::ParameterList &zparams = partParams.sublist("zoltan_parameters", false);
173 zparams.set("LB_METHOD", mPartitionMethod);
175
177 //Create new environment with parameters for partitioning
179 const RCP<const Environment> partEnv = rcp(new Zoltan2::Environment(partParams, this->mEnv->comm_));
181
182 int nUserWts = 0;
183
184 RCP<AlgZoltan<Adapter>> algZoltan = rcp(new AlgZoltan<Adapter>(partEnv, mProblemComm, this->mBaseInputAdapter));
185
186 RCP<PartitioningSolution<Adapter>> partSoln;
187 partSoln =
188 RCP<PartitioningSolution<Adapter>>(new PartitioningSolution<Adapter>(partEnv, mProblemComm, nUserWts, algZoltan));
189
190 algZoltan->partition(partSoln);
191
192 size_t numGlobalParts = partSoln->getTargetGlobalNumberOfParts();
193
194 const part_t *parts = partSoln->getPartListView();
195
196 // size_t numVerts = mGraphModel->getLocalNumVertices();
197 // for(size_t i=0; i< numVerts; i++)
198 // {
199 // std::cout << "part[" << i << "] = " << parts[i] <<std::endl;
200 // }
202
204 // Obtain partitioning tree info from solution
206
207 // Need to guarantee partitioning tree is binary
208 assert(partSoln->isPartitioningTreeBinary() == true);
209
211 // Get partitioning tree from solution
213 part_t numTreeVerts = 0;
214 std::vector<part_t> permPartNums; // peritab in Scotch
215
216 std::vector<part_t> splitRangeBeg;
217 std::vector<part_t> splitRangeEnd;
218 std::vector<part_t> treeVertParents;
219
220 partSoln->getPartitionTree(numTreeVerts, permPartNums, splitRangeBeg,
221 splitRangeEnd, treeVertParents);
223
225 // Grab part numbers that are to be split by the separators
226 //
227 // Each separator i is represented by 1 integer and two sets of part_t's in the
228 // the following 3 structure:
229 //
230 // sepLevels[i] - level of separator
231 // sepParts1[i] - 1st set of parts on one side of separator
232 // sepParts2[i] - 2nd set of parts on other side of separator
233 //
235 std::vector<part_t> levInds;
236
237 std::vector<part_t> sepLevels;
238 std::vector<std::set<part_t>> sepParts1;
239 std::vector<std::set<part_t>> sepParts2;
240
241 std::vector<std::pair<part_t, part_t>> treeIndxToSepLev(treeVertParents.size());
242
243 part_t maxLevel = 0;
244
245 //View of separator tree structure of solution
246 part_t *sepTreeView = solution_->getSeparatorTreeView();
247
248 part_t sepTreeIndx = treeVertParents.size() - 1;
249
250 sepTreeView[sepTreeIndx] = -1;
251
252 buildPartTree(0, levInds, numTreeVerts, permPartNums, splitRangeBeg, splitRangeEnd, treeVertParents,
253 sepLevels, sepParts1, sepParts2, maxLevel, sepTreeIndx, sepTreeView, treeIndxToSepLev);
254
255 solution_->setHaveSeparatorTree(true);
256
257 // std::cout << "sepTreeView: ";
258 // for(part_t i=0; i<treeVertParents.size(); i++)
259 // {
260 // std::cout << sepTreeView[i] << " ";
261 // }
262 // std::cout << std::endl;
263
264 // std::cout << "treeIndxToSepLev:" << std::endl;
265 // for(part_t i=0; i<treeVertParents.size(); i++)
266 // {
267 // std::cout << treeIndxToSepLev[i].first << " " << treeIndxToSepLev[i].second <<std::endl;
268 // }
269
270 part_t numSeparators = sepLevels.size();
273
275 // Create a map that maps each part number to a new number based on
276 // the level of the hiearchy of the separator tree. This allows us
277 // to easily identify the boundary value vertices
279 part_t numLevels = maxLevel + 1;
280
281 std::vector<std::vector<part_t>> partLevelMap(numLevels, std::vector<part_t>(numGlobalParts));
282
283 std::vector<part_t> sepsInLev(numLevels, 0);
284
285 const auto graphModel = rcp(new GraphModel<Adapter>(mBaseInputAdapter, mEnv, mProblemComm, graphFlags));
286
287 for (part_t i = 0; i < numSeparators; i++)
288 {
289 part_t level = sepLevels[i];
290
291 for (typename std::set<part_t>::const_iterator iter = sepParts1[i].begin();
292 iter != sepParts1[i].end(); ++iter)
293 {
294 partLevelMap[level][*iter] = 2 * sepsInLev[level];
295 }
296
297 for (typename std::set<part_t>::const_iterator iter = sepParts2[i].begin();
298 iter != sepParts2[i].end(); ++iter)
299 {
300 partLevelMap[level][*iter] = 2 * sepsInLev[level] + 1;
301 }
302
303 sepsInLev[level]++;
304 }
306
307 // Set of separator vertices. Used to keep track of what vertices are
308 // already in previous calculated separators. These vertices should be
309 // excluded from future separator calculations
310 std::set<lno_t> sepVerts;
311 std::vector<std::vector<std::set<lno_t>>> sepVertsByLevel(numLevels);
312
314 // Loop over each cut
315 // 1. Build boundary layer between parts
316 // 2. Build vertex separator from boundary layer
318 for (part_t level = 0; level < numLevels; level++)
319 {
320 sepVertsByLevel[level].resize(sepsInLev[level]);
321
322 for (part_t levIndx = 0; levIndx < sepsInLev[level]; levIndx++)
323 {
324
326 // Build boundary layer between parts (edge separator)
328 lno_t bigraphNumU = 0, bigraphNumV = 0;
329 lno_t bigraphNumE = 0; // Should probably be size_t, but making lno_t for Matcher
330 std::vector<lno_t> bigraphVMapU;
331 std::vector<lno_t> bigraphVMapV;
332
333 std::vector<lno_t> bigraphCRSRowPtr;
334 std::vector<lno_t> bigraphCRSCols;
335
336 getBoundLayer(levIndx, partLevelMap[level], parts, sepVerts,
337 bigraphNumU, bigraphNumV, bigraphNumE,
338 bigraphCRSRowPtr, bigraphCRSCols,
339 bigraphVMapU, bigraphVMapV, graphModel);
340
341 // std::cout << "Bipartite graph: " << bigraphNumU << " " << bigraphNumV << " "
342 // << bigraphNumE << std::endl;
343
344 // for (size_t i=0;i<bigraphVMapU.size();i++)
345 // {
346 // std::cout << "boundVertU: " << bigraphVMapU[i] << std::endl;
347 // }
348
349 // for (size_t i=0;i<bigraphVMapV.size();i++)
350 // {
351 // std::cout << "boundVertV: " << bigraphVMapV[i] << std::endl;
352 // }
353
354 // for (lno_t rownum=0;rownum<bigraphNumU;rownum++)
355 // {
356
357 // for (lno_t eIdx=bigraphCRSRowPtr[rownum];eIdx<bigraphCRSRowPtr[rownum+1];eIdx++)
358 // {
359 // std::cout << "bipartite E: " << bigraphVMapU[rownum] << ", " << bigraphVMapV[ bigraphCRSCols[eIdx]]
360 // << " ( " << rownum << "," << bigraphCRSCols[eIdx] << " )" << std::endl;
361 // }
362
363 // }
365
367 // Calculate bipartite matching from boundary layer
369 if (bigraphNumU > 0)
370 {
371 assert(bigraphNumV > 0);
372
373 Matcher<lno_t> bpMatch(bigraphCRSRowPtr.data(), bigraphCRSCols.data(), bigraphNumU, bigraphNumV, bigraphNumE);
374 bpMatch.match();
375
376 const std::vector<lno_t> &vertUMatches = bpMatch.getVertexUMatches();
377 const std::vector<lno_t> &vertVMatches = bpMatch.getVertexVMatches();
379
381 // Calculate vertex cover (which is vertex separator) from matching
383 std::vector<lno_t> VC;
384
385 bpMatch.getVCfromMatching(bigraphCRSRowPtr, bigraphCRSCols, vertUMatches, vertVMatches,
386 bigraphVMapU, bigraphVMapV, VC);
387
388 for (size_t i = 0; i < VC.size(); i++)
389 {
390 sepVerts.insert(VC[i]);
391
392 sepVertsByLevel[level][levIndx].insert(VC[i]);
393 // std::cout << "VC: " << VC[i] << std::endl;
394 }
396 }
397 }
398 }
400
402 // Fill solution structures: invperm and separatorRange
404 bool inverse = true;
405 lno_t *ipermView = solution_->getPermutationView(inverse);
406 lno_t *sepRangeView = solution_->getSeparatorRangeView();
407
408 fillSolutionIperm(graphModel, parts, sepVerts, sepVertsByLevel, treeIndxToSepLev, ipermView, sepRangeView);
409
410 solution_->setHaveInverse(true);
411 solution_->setHaveSeparatorRange(true);
413
415 // Output separators
417 std::cout << "Separators: " << std::endl;
418
419 part_t nLevels = sepVertsByLevel.size();
420 for (part_t level = 0; level < nLevels; level++)
421 {
422 //sepVertsByLevel[level].resize(sepsInLev[level]);
423 part_t nSepsOnLev = sepVertsByLevel[level].size();
424
425 for (part_t levIndx = 0; levIndx < nSepsOnLev; levIndx++)
426 {
427 std::cout << " Separator " << level << " " << levIndx << ": ";
428
429 typename std::set<lno_t>::const_iterator iterS;
430 for (iterS = sepVertsByLevel[level][levIndx].begin(); iterS != sepVertsByLevel[level][levIndx].end(); ++iterS)
431 {
432 std::cout << *iterS << " ";
433 }
434 std::cout << std::endl;
435 }
436 }
438
439 // std::cout << "iPerm: ";
440 // for(part_t i=0; i<numVerts; i++)
441 // {
442 // std::cout << ipermView[i] << " ";
443 // }
444 // std::cout << std::endl;
445
446 // std::cout << "sepRange: ";
447 // for(part_t i=0; i<treeVertParents.size()+1; i++)
448 // {
449 // std::cout << sepRangeView[i] << " ";
450 // }
451 // std::cout << std::endl;
452
454
456
457 mEnv->debug(DETAILED_STATUS, std::string("Exiting AlgND"));
458 return 0;
459 }
461
463 // Create boundary layer of vertices between 2 partitions
464 //
465 // Could improve the efficiency here by first creating a boundary layer graph
466 // between all parts
468 template <typename Adapter>
469 void AlgND<Adapter>::getBoundLayer(part_t levelIndx, const std::vector<part_t> &partMap,
470 const part_t *parts,
471 const std::set<lno_t> &excVerts,
472 lno_t &bigraphNumS, lno_t &bigraphNumT, lno_t &bigraphNumE,
473 std::vector<lno_t> &bigraphCRSRowPtr, std::vector<lno_t> &bigraphCRSCols,
474 std::vector<lno_t> &bigraphVMapS, std::vector<lno_t> &bigraphVMapT,
475 const RCP<const GraphModel<Adapter>> &graphModel)
476 {
477 typedef typename Adapter::offset_t offset_t; // offset_t
479
480 lno_t numVerts = graphModel->getLocalNumVertices();
481
482 //Teuchos ArrayView
483 // Original -- ArrayView< const lno_t > eIDs;
484 ArrayView<const gno_t> eIDs;
485 ArrayView<const offset_t> vOffsets;
486 ArrayView<input_t> wgts;
487
488 // MMW:
489 // For some reason getLocalEdgeList seems to be returning empty eIDs
490 // getEdgeList expects eIDs to be an array of gno_t
491 // I wanted eIDs to be lno_t since this ordering is computed on a single node and
492 // it seems unnecessary to use the potentially larger gno_t.
493 // The problem might be that the partitioning is being calculated on the gno_t.
494 // Perhaps a solution would be set gno_t = lno_t in the partitioning.
495 // For now, I'll leave this since the edgelist is unlikely to be prohibitively big
496
497 graphModel->getEdgeList(eIDs, vOffsets, wgts);
498
499 // original
500 // ( (GraphModel<typename Adapter::base_adapter_t>) *mGraphModel).getEdgeList(eIDs, vOffsets, wgts);
501
502 std::map<lno_t, std::set<lno_t>> bigraphEs;
503 std::set<lno_t> vSetS;
504 std::set<lno_t> vSetT;
505
506 bigraphNumE = 0;
507
508 for (lno_t v1 = 0; v1 < numVerts; v1++)
509 {
510
511 part_t vpart1 = partMap[parts[v1]];
512
513 bool correctBL = (vpart1 >= 2 * levelIndx && vpart1 < 2 * (levelIndx + 1));
514
515 // if vertex is not in the correct range of parts, it cannot be a member of
516 // this boundary layer
517 if (!correctBL)
518 {
519 continue;
520 }
521
522 // Ignore vertices that belong to set of vertices to exclude
523 if (excVerts.find(v1) != excVerts.end())
524 {
525 continue;
526 }
527
528 //Loop over edges connected to v1
529 //MMW figure out how to get this from Zoltan2
530 for (offset_t j = vOffsets[v1]; j < vOffsets[v1 + 1]; j++)
531 {
532
533 lno_t v2 = eIDs[j];
534
535 part_t vpart2 = partMap[parts[v2]];
536
537 correctBL = (vpart2 >= 2 * levelIndx && vpart2 < 2 * (levelIndx + 1));
538
539 // if vertex is not in the correct range of parts, it cannot be a member of
540 // this boundary layer
541 if (!correctBL)
542 {
543 continue;
544 }
545
546 // Ignore vertices that belong to set of vertices to exclude
547 if (excVerts.find(v2) != excVerts.end())
548 {
549 continue;
550 }
551
552 if (vpart1 != vpart2)
553 {
554 // Vertex added to 1st set of boundary vertices
555 if (vpart1 < vpart2)
556 {
557 vSetS.insert(v1);
558
559 // v1, v2
560 if (bigraphEs.find(v1) == bigraphEs.end())
561 {
562 bigraphEs[v1] = std::set<lno_t>();
563 }
564 bigraphEs[v1].insert(v2);
565 bigraphNumE++;
566 }
567 // Vertex added to 2nd set of boundary vertices
568 else
569 {
570 vSetT.insert(v1);
571 }
572 }
573 }
574 }
575
577 // Set size of two vertex sets for bipartite graph
579 bigraphNumS = vSetS.size();
580 bigraphNumT = vSetT.size();
582
585
586 bigraphVMapS.resize(bigraphNumS);
587
588 std::map<lno_t, lno_t> glob2LocTMap;
589
590 lno_t indx = 0;
591 for (typename std::set<lno_t>::const_iterator iter = vSetS.begin(); iter != vSetS.end(); ++iter)
592 {
593 bigraphVMapS[indx] = *iter;
594 indx++;
595 }
596
597 bigraphVMapT.resize(bigraphNumT);
598 indx = 0;
599 for (typename std::set<lno_t>::const_iterator iter = vSetT.begin(); iter != vSetT.end(); ++iter)
600 {
601 bigraphVMapT[indx] = *iter;
602 glob2LocTMap[*iter] = indx;
603 indx++;
604 }
606
608 // Set sizes for bipartite graph data structures
610 bigraphCRSRowPtr.resize(bigraphNumS + 1);
611 bigraphCRSCols.resize(bigraphNumE);
613
615 // Copy bipartite graph edges into CRS format
617 bigraphCRSRowPtr[0] = 0;
618
619 lno_t rownum = 0;
620 size_t nzIndx = 0;
621 typename std::map<lno_t, std::set<lno_t>>::const_iterator iterM;
622 for (iterM = bigraphEs.begin(); iterM != bigraphEs.end(); ++iterM)
623 {
624 bigraphCRSRowPtr[rownum + 1] = bigraphCRSRowPtr[rownum] + (*iterM).second.size();
625
626 for (typename std::set<lno_t>::const_iterator iter = (*iterM).second.begin(); iter != (*iterM).second.end(); ++iter)
627 {
628 bigraphCRSCols[nzIndx] = glob2LocTMap[(*iter)];
629
630 nzIndx++;
631 }
632
633 rownum++;
634 }
636 }
638
641 template <typename Adapter>
642 void AlgND<Adapter>::
643 buildPartTree(part_t level, std::vector<part_t> &levIndx,
644 part_t startV,
645 const std::vector<part_t> &permPartNums,
646 const std::vector<part_t> &splitRangeBeg,
647 const std::vector<part_t> &splitRangeEnd,
648 const std::vector<part_t> &treeVertParents,
649 std::vector<part_t> &sepLevels,
650 std::vector<std::set<part_t>> &sepParts1, std::vector<std::set<part_t>> &sepParts2,
651 part_t &maxLev, part_t &gIndx,
652 part_t *sepTreeView, std::vector<std::pair<part_t, part_t>> &treeIndxToSepLev)
653 {
654 // Insert information for this separator
655 maxLev = level;
656 part_t tmpMaxLev = maxLev;
657
659 // Search for indices that have parent startV
661 typename std::vector<part_t>::const_iterator iter;
662 std::vector<part_t> inds;
663 part_t ind = 0;
664 for (iter = treeVertParents.begin(); iter != treeVertParents.end(); ++iter)
665 {
666 if (*iter == startV)
667 {
668 inds.push_back(ind);
669 }
670 ind++;
671 }
673
675 // If startV has children, this will correspond to a separator. Construct
676 // appropriate data structure and then recurse
678 assert(inds.size() == 2 || inds.size() == 0);
679
680 // If startV has children
681 if (inds.size() == 2)
682 {
683
684 if ((part_t)levIndx.size() < level + 1)
685 {
686 levIndx.push_back(0);
687 }
688 else
689 {
690 levIndx[level]++;
691 }
692
693 // std::cout << "gIndx " << gIndx << ": separator " << level << " " << levIndx[level] << std::endl;
694
695 treeIndxToSepLev[gIndx].first = level;
696 treeIndxToSepLev[gIndx].second = levIndx[level];
697
698 part_t v0 = inds[0];
699 part_t v1 = inds[1];
700
701 sepLevels.push_back(level);
702
703 sepParts1.push_back(std::set<part_t>());
704 typename std::vector<std::set<part_t>>::iterator setIter = sepParts1.end();
705 setIter--; // set iterator to point to new set
706
707 for (part_t k = splitRangeBeg[v0]; k < splitRangeEnd[v0]; k++)
708 {
709 (*setIter).insert(permPartNums[k]);
710 }
711
712 sepParts2.push_back(std::set<part_t>());
713 setIter = sepParts2.end();
714 setIter--; // set iterator to point to new set
715
716 for (part_t k = splitRangeBeg[v1]; k < splitRangeEnd[v1]; k++)
717 {
718 (*setIter).insert(permPartNums[k]);
719 }
720
721 part_t parentNode = gIndx;
722 gIndx--;
723 sepTreeView[gIndx] = parentNode;
724
725 // Recursively call function on children
726 buildPartTree(level + 1, levIndx, v0,
727 permPartNums, splitRangeBeg, splitRangeEnd, treeVertParents,
728 sepLevels, sepParts1, sepParts2,
729 tmpMaxLev,
730 gIndx, sepTreeView, treeIndxToSepLev);
731 if (tmpMaxLev > maxLev)
732 {
733 maxLev = tmpMaxLev;
734 }
735
736 gIndx--;
737 sepTreeView[gIndx] = parentNode;
738
739 buildPartTree(level + 1, levIndx, v1,
740 permPartNums, splitRangeBeg, splitRangeEnd, treeVertParents,
741 sepLevels, sepParts1, sepParts2,
742 tmpMaxLev,
743 gIndx, sepTreeView, treeIndxToSepLev);
744 if (tmpMaxLev > maxLev)
745 {
746 maxLev = tmpMaxLev;
747 }
748 }
749 else // no children, so this is not a separator
750 {
751 // std::cout << "gIndx " << gIndx << " leaf: " << permPartNums[splitRangeBeg[startV]] << std::endl;
752 treeIndxToSepLev[gIndx].first = -1;
753 treeIndxToSepLev[gIndx].second = permPartNums[splitRangeBeg[startV]];
754
755 maxLev--;
756 }
758 }
759
761
764 template <typename Adapter>
765 void AlgND<Adapter>::
766 fillSolutionIperm(const RCP<const GraphModel<Adapter>> &graphModel,
767 const part_t *parts, const std::set<lno_t> &sepVerts,
768 const std::vector<std::vector<std::set<lno_t>>> &sepVertsByLevel,
769 const std::vector<std::pair<part_t, part_t>> &treeIndxToSepLev,
770 lno_t *ipermView, lno_t *sepRangeView)
771 {
772 lno_t permIndx = 0;
773 lno_t sepRangeIndx = 0;
774 sepRangeView[sepRangeIndx] = 0;
775
776 for (size_t i = 0; i < treeIndxToSepLev.size(); i++)
777 {
778 part_t lev = treeIndxToSepLev[i].first;
780 // Leaf node of separator tree
782 if (lev == -1)
783 {
784 std::set<lno_t> idSet;
785 getIdsOfPart(graphModel, parts, treeIndxToSepLev[i].second, sepVerts, idSet);
786
787 for (typename std::set<lno_t>::const_iterator setIter = idSet.begin(); setIter != idSet.end();
788 ++setIter)
789 {
790 ipermView[permIndx] = *setIter;
791 permIndx++;
792 }
793 sepRangeView[sepRangeIndx + 1] = sepRangeView[sepRangeIndx] + idSet.size();
794 sepRangeIndx++;
795 }
798 // Internal "separator node" of separator tree
800 else
801 {
802 const std::set<lno_t> &idSet = sepVertsByLevel[lev][treeIndxToSepLev[i].second];
803
804 for (typename std::set<lno_t>::const_iterator setIter = idSet.begin();
805 setIter != idSet.end(); ++setIter)
806 {
807 ipermView[permIndx] = *setIter;
808 permIndx++;
809 }
810 sepRangeView[sepRangeIndx + 1] = sepRangeView[sepRangeIndx] + idSet.size();
811 sepRangeIndx++;
812 }
814 }
815 }
817
820 template <typename Adapter>
821 void AlgND<Adapter>::
822 getIdsOfPart(const RCP<const GraphModel<Adapter>> &graphModel, const part_t *parts,
823 part_t targetPart, const std::set<lno_t> &idsToExcl, std::set<lno_t> &outIds)
824 {
825 size_t numVerts = graphModel->getLocalNumVertices();
826
827 for (size_t i = 0; i < numVerts; i++)
828 {
829 if (parts[i] == targetPart && idsToExcl.find(i) == idsToExcl.end())
830 {
831 outIds.insert(i);
832 }
833 }
834 }
836
837} // namespace Zoltan2
838
839#endif
interface to the Zoltan package
#define Z2_THROW_SERIAL(mystr)
Throw an error when code is run on more than one processor.
#define Z2_THROW_EXPERIMENTAL(mystr)
Throw an error when experimental code is requested but not compiled.
Defines the IdentifierModel interface.
Defines the PartitioningSolution class.
int localOrder(const RCP< LocalOrderingSolution< lno_t > > &solution_)
Ordering method.
static void getValidParameters(ParameterList &pl)
Set up validators specific to this algorithm.
int globalOrder(const RCP< GlobalOrderingSolution< gno_t > > &solution_)
Ordering method.
AlgND(const RCP< const Environment > &env_, const RCP< const Comm< int > > &problemComm_, const RCP< const typename Adapter::base_adapter_t > &baseInputAdapter_, const modelFlag_t &graphFlags_)
Algorithm defines the base class for all algorithms.
The user parameters, debug, timing and memory profiling output objects, and error checking methods.
GraphModel defines the interface required for graph models.
An implementation of the Matcher interface that operates on Epetra matrices and Graphs.
const std::vector< LO > & getVertexVMatches()
const std::vector< LO > & getVertexUMatches()
void getVCfromMatching(const std::vector< LO > &bigraphCRSRowPtr, std::vector< LO > &bigraphCRSCols, const std::vector< LO > &vertUMatches, const std::vector< LO > &vertVMatches, const std::vector< LO > &bigraphVMapU, const std::vector< LO > &bigraphVMapV, std::vector< LO > &VC)
LO match()
Computes the maximum cardinality matching.
A PartitioningSolution is a solution to a partitioning problem.
The StridedData class manages lists of weights or coordinates.
map_t::local_ordinal_type lno_t
Created by mbenlioglu on Aug 31, 2020.
std::bitset< NUM_MODEL_FLAGS > modelFlag_t
@ DETAILED_STATUS
sub-steps, each method's entry and exit
SparseMatrixAdapter_t::part_t part_t