12#ifndef _ZOLTAN2_ALGND_HPP_
13#define _ZOLTAN2_ALGND_HPP_
46 template <
typename Adapter>
51 typedef typename Adapter::part_t part_t;
53 typedef typename Adapter::lno_t lno_t;
54 typedef typename Adapter::gno_t gno_t;
56 const RCP<const Environment> mEnv;
57 const RCP<const Comm<int>> mProblemComm;
59 std::string mPartitionMethod;
61 const RCP<const typename Adapter::base_adapter_t> mBaseInputAdapter;
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,
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);
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);
88 part_t targetPart,
const std::set<lno_t> &idsToExcl, std::set<lno_t> &outIds);
92 AlgND(
const RCP<const Environment> &env_,
93 const RCP<
const Comm<int>> &problemComm_,
94 const RCP<const typename Adapter::base_adapter_t> &baseInputAdapter_,
96 : mEnv(env_), mProblemComm(problemComm_), mPartitionMethod(
"rcb"),
97 mBaseInputAdapter(baseInputAdapter_), graphFlags(graphFlags_)
99#ifndef INCLUDE_ZOLTAN2_EXPERIMENTAL
103 if (mProblemComm->getSize() != 1)
108 const Teuchos::ParameterList &pl = mEnv->getParameters();
109 const Teuchos::ParameterEntry *pe;
111 pe = pl.getEntryPtr(
"edge_separator_method");
115 mPartitionMethod = pe->getValue<std::string>(&mPartitionMethod);
128 RCP<Teuchos::StringValidator> es_method_Validator =
129 Teuchos::rcp(
new Teuchos::StringValidator(Teuchos::tuple<std::string>(
"rcb",
"phg")));
131 pl.set(
"edge_separator_method",
"rcb",
"ND ordering - Edge separator method", es_method_Validator);
138 template <
typename Adapter>
142 throw std::logic_error(
"AlgND does not support global ordering.");
149 template <
typename Adapter>
162 Teuchos::ParameterList partParams;
164 part_t numParts = mEnv->getParameters().template get<part_t>(
"num_global_parts");
166 partParams.set(
"num_global_parts", numParts);
169 partParams.set(
"keep_partition_tree",
true);
172 Teuchos::ParameterList &zparams = partParams.sublist(
"zoltan_parameters",
false);
173 zparams.set(
"LB_METHOD", mPartitionMethod);
179 const RCP<const Environment> partEnv = rcp(
new Zoltan2::Environment(partParams, this->mEnv->comm_));
184 RCP<AlgZoltan<Adapter>> algZoltan = rcp(
new AlgZoltan<Adapter>(partEnv, mProblemComm, this->mBaseInputAdapter));
186 RCP<PartitioningSolution<Adapter>> partSoln;
190 algZoltan->partition(partSoln);
192 size_t numGlobalParts = partSoln->getTargetGlobalNumberOfParts();
194 const part_t *parts = partSoln->getPartListView();
208 assert(partSoln->isPartitioningTreeBinary() ==
true);
213 part_t numTreeVerts = 0;
214 std::vector<part_t> permPartNums;
216 std::vector<part_t> splitRangeBeg;
217 std::vector<part_t> splitRangeEnd;
218 std::vector<part_t> treeVertParents;
220 partSoln->getPartitionTree(numTreeVerts, permPartNums, splitRangeBeg,
221 splitRangeEnd, treeVertParents);
235 std::vector<part_t> levInds;
237 std::vector<part_t> sepLevels;
238 std::vector<std::set<part_t>> sepParts1;
239 std::vector<std::set<part_t>> sepParts2;
241 std::vector<std::pair<part_t, part_t>> treeIndxToSepLev(treeVertParents.size());
246 part_t *sepTreeView = solution_->getSeparatorTreeView();
248 part_t sepTreeIndx = treeVertParents.size() - 1;
250 sepTreeView[sepTreeIndx] = -1;
252 buildPartTree(0, levInds, numTreeVerts, permPartNums, splitRangeBeg, splitRangeEnd, treeVertParents,
253 sepLevels, sepParts1, sepParts2, maxLevel, sepTreeIndx, sepTreeView, treeIndxToSepLev);
255 solution_->setHaveSeparatorTree(
true);
270 part_t numSeparators = sepLevels.size();
279 part_t numLevels = maxLevel + 1;
281 std::vector<std::vector<part_t>> partLevelMap(numLevels, std::vector<part_t>(numGlobalParts));
283 std::vector<part_t> sepsInLev(numLevels, 0);
285 const auto graphModel = rcp(
new GraphModel<Adapter>(mBaseInputAdapter, mEnv, mProblemComm, graphFlags));
287 for (part_t i = 0; i < numSeparators; i++)
289 part_t level = sepLevels[i];
291 for (
typename std::set<part_t>::const_iterator iter = sepParts1[i].begin();
292 iter != sepParts1[i].end(); ++iter)
294 partLevelMap[level][*iter] = 2 * sepsInLev[level];
297 for (
typename std::set<part_t>::const_iterator iter = sepParts2[i].begin();
298 iter != sepParts2[i].end(); ++iter)
300 partLevelMap[level][*iter] = 2 * sepsInLev[level] + 1;
310 std::set<lno_t> sepVerts;
311 std::vector<std::vector<std::set<lno_t>>> sepVertsByLevel(numLevels);
318 for (part_t level = 0; level < numLevels; level++)
320 sepVertsByLevel[level].resize(sepsInLev[level]);
322 for (part_t levIndx = 0; levIndx < sepsInLev[level]; levIndx++)
328 lno_t bigraphNumU = 0, bigraphNumV = 0;
329 lno_t bigraphNumE = 0;
330 std::vector<lno_t> bigraphVMapU;
331 std::vector<lno_t> bigraphVMapV;
333 std::vector<lno_t> bigraphCRSRowPtr;
334 std::vector<lno_t> bigraphCRSCols;
336 getBoundLayer(levIndx, partLevelMap[level], parts, sepVerts,
337 bigraphNumU, bigraphNumV, bigraphNumE,
338 bigraphCRSRowPtr, bigraphCRSCols,
339 bigraphVMapU, bigraphVMapV, graphModel);
371 assert(bigraphNumV > 0);
373 Matcher<lno_t> bpMatch(bigraphCRSRowPtr.data(), bigraphCRSCols.data(), bigraphNumU, bigraphNumV, bigraphNumE);
383 std::vector<lno_t> VC;
385 bpMatch.
getVCfromMatching(bigraphCRSRowPtr, bigraphCRSCols, vertUMatches, vertVMatches,
386 bigraphVMapU, bigraphVMapV, VC);
388 for (
size_t i = 0; i < VC.size(); i++)
390 sepVerts.insert(VC[i]);
392 sepVertsByLevel[level][levIndx].insert(VC[i]);
405 lno_t *ipermView = solution_->getPermutationView(inverse);
406 lno_t *sepRangeView = solution_->getSeparatorRangeView();
408 fillSolutionIperm(graphModel, parts, sepVerts, sepVertsByLevel, treeIndxToSepLev, ipermView, sepRangeView);
410 solution_->setHaveInverse(
true);
411 solution_->setHaveSeparatorRange(
true);
417 std::cout <<
"Separators: " << std::endl;
419 part_t nLevels = sepVertsByLevel.size();
420 for (part_t level = 0; level < nLevels; level++)
423 part_t nSepsOnLev = sepVertsByLevel[level].size();
425 for (part_t levIndx = 0; levIndx < nSepsOnLev; levIndx++)
427 std::cout <<
" Separator " << level <<
" " << levIndx <<
": ";
429 typename std::set<lno_t>::const_iterator iterS;
430 for (iterS = sepVertsByLevel[level][levIndx].begin(); iterS != sepVertsByLevel[level][levIndx].end(); ++iterS)
432 std::cout << *iterS <<
" ";
434 std::cout << std::endl;
468 template <
typename Adapter>
471 const std::set<lno_t> &excVerts,
473 std::vector<lno_t> &bigraphCRSRowPtr, std::vector<lno_t> &bigraphCRSCols,
474 std::vector<lno_t> &bigraphVMapS, std::vector<lno_t> &bigraphVMapT,
477 typedef typename Adapter::offset_t offset_t;
480 lno_t numVerts = graphModel->getLocalNumVertices();
484 ArrayView<const gno_t> eIDs;
485 ArrayView<const offset_t> vOffsets;
486 ArrayView<input_t> wgts;
497 graphModel->getEdgeList(eIDs, vOffsets, wgts);
502 std::map<lno_t, std::set<lno_t>> bigraphEs;
503 std::set<lno_t> vSetS;
504 std::set<lno_t> vSetT;
508 for (
lno_t v1 = 0; v1 < numVerts; v1++)
511 part_t vpart1 = partMap[parts[v1]];
513 bool correctBL = (vpart1 >= 2 * levelIndx && vpart1 < 2 * (levelIndx + 1));
523 if (excVerts.find(v1) != excVerts.end())
530 for (offset_t j = vOffsets[v1]; j < vOffsets[v1 + 1]; j++)
535 part_t vpart2 = partMap[parts[v2]];
537 correctBL = (vpart2 >= 2 * levelIndx && vpart2 < 2 * (levelIndx + 1));
547 if (excVerts.find(v2) != excVerts.end())
552 if (vpart1 != vpart2)
560 if (bigraphEs.find(v1) == bigraphEs.end())
562 bigraphEs[v1] = std::set<lno_t>();
564 bigraphEs[v1].insert(v2);
579 bigraphNumS = vSetS.size();
580 bigraphNumT = vSetT.size();
586 bigraphVMapS.resize(bigraphNumS);
588 std::map<lno_t, lno_t> glob2LocTMap;
591 for (
typename std::set<lno_t>::const_iterator iter = vSetS.begin(); iter != vSetS.end(); ++iter)
593 bigraphVMapS[indx] = *iter;
597 bigraphVMapT.resize(bigraphNumT);
599 for (
typename std::set<lno_t>::const_iterator iter = vSetT.begin(); iter != vSetT.end(); ++iter)
601 bigraphVMapT[indx] = *iter;
602 glob2LocTMap[*iter] = indx;
610 bigraphCRSRowPtr.resize(bigraphNumS + 1);
611 bigraphCRSCols.resize(bigraphNumE);
617 bigraphCRSRowPtr[0] = 0;
621 typename std::map<lno_t, std::set<lno_t>>::const_iterator iterM;
622 for (iterM = bigraphEs.begin(); iterM != bigraphEs.end(); ++iterM)
624 bigraphCRSRowPtr[rownum + 1] = bigraphCRSRowPtr[rownum] + (*iterM).second.size();
626 for (
typename std::set<lno_t>::const_iterator iter = (*iterM).second.begin(); iter != (*iterM).second.end(); ++iter)
628 bigraphCRSCols[nzIndx] = glob2LocTMap[(*iter)];
641 template <
typename Adapter>
642 void AlgND<Adapter>::
643 buildPartTree(
part_t level, std::vector<part_t> &levIndx,
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,
652 part_t *sepTreeView, std::vector<std::pair<part_t, part_t>> &treeIndxToSepLev)
656 part_t tmpMaxLev = maxLev;
661 typename std::vector<part_t>::const_iterator iter;
662 std::vector<part_t> inds;
664 for (iter = treeVertParents.begin(); iter != treeVertParents.end(); ++iter)
678 assert(inds.size() == 2 || inds.size() == 0);
681 if (inds.size() == 2)
684 if ((
part_t)levIndx.size() < level + 1)
686 levIndx.push_back(0);
695 treeIndxToSepLev[gIndx].first = level;
696 treeIndxToSepLev[gIndx].second = levIndx[level];
701 sepLevels.push_back(level);
703 sepParts1.push_back(std::set<part_t>());
704 typename std::vector<std::set<part_t>>::iterator setIter = sepParts1.end();
707 for (
part_t k = splitRangeBeg[v0]; k < splitRangeEnd[v0]; k++)
709 (*setIter).insert(permPartNums[k]);
712 sepParts2.push_back(std::set<part_t>());
713 setIter = sepParts2.end();
716 for (
part_t k = splitRangeBeg[v1]; k < splitRangeEnd[v1]; k++)
718 (*setIter).insert(permPartNums[k]);
721 part_t parentNode = gIndx;
723 sepTreeView[gIndx] = parentNode;
726 buildPartTree(level + 1, levIndx, v0,
727 permPartNums, splitRangeBeg, splitRangeEnd, treeVertParents,
728 sepLevels, sepParts1, sepParts2,
730 gIndx, sepTreeView, treeIndxToSepLev);
731 if (tmpMaxLev > maxLev)
737 sepTreeView[gIndx] = parentNode;
739 buildPartTree(level + 1, levIndx, v1,
740 permPartNums, splitRangeBeg, splitRangeEnd, treeVertParents,
741 sepLevels, sepParts1, sepParts2,
743 gIndx, sepTreeView, treeIndxToSepLev);
744 if (tmpMaxLev > maxLev)
752 treeIndxToSepLev[gIndx].first = -1;
753 treeIndxToSepLev[gIndx].second = permPartNums[splitRangeBeg[startV]];
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,
773 lno_t sepRangeIndx = 0;
774 sepRangeView[sepRangeIndx] = 0;
776 for (
size_t i = 0; i < treeIndxToSepLev.size(); i++)
778 part_t lev = treeIndxToSepLev[i].first;
784 std::set<lno_t> idSet;
785 getIdsOfPart(graphModel, parts, treeIndxToSepLev[i].second, sepVerts, idSet);
787 for (
typename std::set<lno_t>::const_iterator setIter = idSet.begin(); setIter != idSet.end();
790 ipermView[permIndx] = *setIter;
793 sepRangeView[sepRangeIndx + 1] = sepRangeView[sepRangeIndx] + idSet.size();
802 const std::set<lno_t> &idSet = sepVertsByLevel[lev][treeIndxToSepLev[i].second];
804 for (
typename std::set<lno_t>::const_iterator setIter = idSet.begin();
805 setIter != idSet.end(); ++setIter)
807 ipermView[permIndx] = *setIter;
810 sepRangeView[sepRangeIndx + 1] = sepRangeView[sepRangeIndx] + idSet.size();
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)
825 size_t numVerts = graphModel->getLocalNumVertices();
827 for (
size_t i = 0; i < numVerts; i++)
829 if (parts[i] == targetPart && idsToExcl.find(i) == idsToExcl.end())
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