Zoltan2
Zoltan2_AlgND.hpp
Go to the documentation of this file.
1// @HEADER
2//
3// ***********************************************************************
4//
5// Zoltan2: A package of combinatorial algorithms for scientific computing
6// Copyright 2012 Sandia Corporation
7//
8// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9// the U.S. Government retains certain rights in this software.
10//
11// Redistribution and use in source and binary forms, with or without
12// modification, are permitted provided that the following conditions are
13// met:
14//
15// 1. Redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer.
17//
18// 2. Redistributions in binary form must reproduce the above copyright
19// notice, this list of conditions and the following disclaimer in the
20// documentation and/or other materials provided with the distribution.
21//
22// 3. Neither the name of the Corporation nor the names of the
23// contributors may be used to endorse or promote products derived from
24// this software without specific prior written permission.
25//
26// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37//
38// Questions? Contact Karen Devine (kddevin@sandia.gov)
39// Erik Boman (egboman@sandia.gov)
40// Siva Rajamanickam (srajama@sandia.gov)
41//
42// ***********************************************************************
43//
44// @HEADER
45
46//MMW need to specify that this requires Zoltan
47
48#ifndef _ZOLTAN2_ALGND_HPP_
49#define _ZOLTAN2_ALGND_HPP_
50
53#include <Zoltan2_Algorithm.hpp>
54#include <Zoltan2_AlgZoltan.hpp>
55
57
58
59#include <sstream>
60#include <string>
61#include <bitset>
62
67namespace Zoltan2
68{
69
70
72
84template <typename Adapter>
85class AlgND : public Algorithm<typename Adapter::base_adapter_t>
86{
87
88private:
89
90 typedef typename Adapter::part_t part_t;
91
92 typedef typename Adapter::lno_t lno_t;
93 typedef typename Adapter::gno_t gno_t;
94
95
96 const RCP<const Environment> mEnv;
97 const RCP<const Comm<int> > mProblemComm;
98
99 std::string mPartitionMethod;
100
101 const RCP<GraphModel<typename Adapter::base_adapter_t> > mGraphModel;
102 const RCP<const typename Adapter::base_adapter_t> mBaseInputAdapter;
103
104 void getBoundLayer(part_t levelIndx, const std::vector<part_t> &partMap,
105 const part_t * parts,
106 const std::set<lno_t> &excVerts,
107 lno_t &bigraphNumS, lno_t &bigraphNumT, lno_t &bigraphNumE,
108 std::vector<lno_t> &bigraphCRSRowPtr, std::vector<lno_t> &bigraphCRSCols,
109 std::vector<lno_t> &bigraphVMapU, std::vector<lno_t> &bigraphVMapV);
110
111 void buildPartTree(part_t level, std::vector<part_t> &levIndx,
112 part_t startV,
113 const std::vector<part_t> &permPartNums,
114 const std::vector<part_t> &splitRangeBeg,
115 const std::vector<part_t> &splitRangeEnd,
116 const std::vector<part_t> &treeVertParents,
117 std::vector<part_t> &sepLevels,
118 std::vector<std::set<part_t> > &sepParts1, std::vector<std::set<part_t> > &sepParts2,
119 part_t &maxLev,
120 part_t &sepTreeIndx,
121 part_t *sepTreeView, std::vector<std::pair<part_t,part_t> > &treeIndxToSepLev);
122
123 void fillSolutionIperm(const part_t *parts, const std::set<lno_t> &sepVerts,
124 const std::vector<std::vector< std::set<lno_t> > > & sepVertsByLevel,
125 const std::vector<std::pair<part_t,part_t> > &treeIndxToSepLev,
126 lno_t * ipermView, lno_t *sepRangeView);
127
128 void getIdsOfPart(const part_t *parts, part_t targetPart,const std::set<lno_t> &idsToExcl,
129 std::set<lno_t> &outIds);
130
131
132public:
133 // Constructor
134 AlgND(const RCP<const Environment> &env_,
135 const RCP<const Comm<int> > &problemComm_,
138 const RCP<const typename Adapter::base_adapter_t> baseInputAdapter_
139 )
140 :mEnv(env_), mProblemComm(problemComm_), mPartitionMethod("rcb"),
141 mGraphModel(gModel_),
142 mBaseInputAdapter(baseInputAdapter_)
143 {
144#ifndef INCLUDE_ZOLTAN2_EXPERIMENTAL
145 Z2_THROW_EXPERIMENTAL("Zoltan2 AlgND is strictly experimental software ")
146#endif
147
148 if(mProblemComm->getSize()!=1)
149 {
150 Z2_THROW_SERIAL("Zoltan2 AlgND is strictly serial!");
151 }
152
153
154 const Teuchos::ParameterList &pl = mEnv->getParameters();
155 const Teuchos::ParameterEntry *pe;
156
157
158 pe = pl.getEntryPtr("edge_separator_method");
159
160 if (pe)
161 {
162 mPartitionMethod = pe->getValue<std::string>(&mPartitionMethod);
163 }
164
165 }
166
167 // Ordering method
168 int localOrder(const RCP<LocalOrderingSolution<lno_t> > &solution_);
169 int globalOrder(const RCP<GlobalOrderingSolution<gno_t> > &solution_);
170
173 static void getValidParameters(ParameterList & pl)
174 {
175
176 RCP<Teuchos::StringValidator> es_method_Validator =
177 Teuchos::rcp( new Teuchos::StringValidator(Teuchos::tuple<std::string>( "rcb", "phg")));
178
179 pl.set("edge_separator_method", "rcb", "ND ordering - Edge separator method", es_method_Validator);
180 }
181
182};
184
187template <typename Adapter>
189 const RCP<GlobalOrderingSolution<gno_t> > &solution_)
190{
191 throw std::logic_error("AlgND does not support global ordering.");
192}
193
195
196
199template <typename Adapter>
201{
202 mEnv->debug(DETAILED_STATUS, std::string("Entering AlgND"));
203
205 // First, let's partition with RCB using Zoltan. Eventually, we will change
206 // to give an option to use PHG
208
210 // Create parameter list for partitioning environment
212 Teuchos::ParameterList partParams;
213
214 part_t numParts = mEnv->getParameters().template get<part_t>("num_global_parts");
215
216 partParams.set("num_global_parts", numParts);
217
218 // Keeping partitioning tree
219 partParams.set("keep_partition_tree", true);
220
221
222 // Set Zoltan parameter lists
223 Teuchos::ParameterList &zparams = partParams.sublist("zoltan_parameters",false);
224 zparams.set("LB_METHOD", mPartitionMethod);
226
228 //Create new environment with parameters for partitioning
230 const RCP<const Environment> partEnv = rcp(new Zoltan2::Environment(partParams,this->mEnv->comm_));
232
233 int nUserWts=0;
234
235 RCP<AlgZoltan<Adapter> > algZoltan = rcp(new AlgZoltan<Adapter>(partEnv, mProblemComm, this->mBaseInputAdapter));
236
237 RCP<PartitioningSolution<Adapter> > partSoln;
238 partSoln =
239 RCP<PartitioningSolution<Adapter> > (new PartitioningSolution<Adapter>(partEnv, mProblemComm, nUserWts,algZoltan));
240
241
242 algZoltan->partition(partSoln);
243
244 size_t numGlobalParts = partSoln->getTargetGlobalNumberOfParts();
245
246 const part_t *parts = partSoln->getPartListView();
247
248 // size_t numVerts = mGraphModel->getLocalNumVertices();
249 // for(size_t i=0; i< numVerts; i++)
250 // {
251 // std::cout << "part[" << i << "] = " << parts[i] <<std::endl;
252 // }
254
256 // Obtain partitioning tree info from solution
258
259 // Need to guarantee partitioning tree is binary
260 assert(partSoln->isPartitioningTreeBinary()==true);
261
263 // Get partitioning tree from solution
265 part_t numTreeVerts = 0;
266 std::vector<part_t> permPartNums; // peritab in Scotch
267
268 std::vector<part_t> splitRangeBeg;
269 std::vector<part_t> splitRangeEnd;
270 std::vector<part_t> treeVertParents;
271
272 partSoln->getPartitionTree(numTreeVerts,permPartNums,splitRangeBeg,
273 splitRangeEnd,treeVertParents);
275
277 // Grab part numbers that are to be split by the separators
278 //
279 // Each separator i is represented by 1 integer and two sets of part_t's in the
280 // the following 3 structure:
281 //
282 // sepLevels[i] - level of separator
283 // sepParts1[i] - 1st set of parts on one side of separator
284 // sepParts2[i] - 2nd set of parts on other side of separator
285 //
287 std::vector<part_t> levInds;
288
289 std::vector<part_t> sepLevels;
290 std::vector<std::set<part_t> > sepParts1;
291 std::vector<std::set<part_t> > sepParts2;
292
293 std::vector<std::pair<part_t,part_t> > treeIndxToSepLev(treeVertParents.size());
294
295 part_t maxLevel = 0;
296
297 //View of separator tree structure of solution
298 part_t *sepTreeView = solution_->getSeparatorTreeView();
299
300 part_t sepTreeIndx= treeVertParents.size()-1;
301
302 sepTreeView[sepTreeIndx]=-1;
303
304 buildPartTree(0, levInds, numTreeVerts, permPartNums, splitRangeBeg, splitRangeEnd, treeVertParents,
305 sepLevels, sepParts1, sepParts2, maxLevel, sepTreeIndx,sepTreeView,treeIndxToSepLev);
306
307 solution_->setHaveSeparatorTree(true);
308
309 // std::cout << "sepTreeView: ";
310 // for(part_t i=0; i<treeVertParents.size(); i++)
311 // {
312 // std::cout << sepTreeView[i] << " ";
313 // }
314 // std::cout << std::endl;
315
316
317 // std::cout << "treeIndxToSepLev:" << std::endl;
318 // for(part_t i=0; i<treeVertParents.size(); i++)
319 // {
320 // std::cout << treeIndxToSepLev[i].first << " " << treeIndxToSepLev[i].second <<std::endl;
321 // }
322
323 part_t numSeparators = sepLevels.size();
326
328 // Create a map that maps each part number to a new number based on
329 // the level of the hiearchy of the separator tree. This allows us
330 // to easily identify the boundary value vertices
332 part_t numLevels = maxLevel+1;
333
334 std::vector<std::vector<part_t> > partLevelMap(numLevels,std::vector<part_t>(numGlobalParts));
335
336 std::vector<part_t> sepsInLev(numLevels,0);
337
338 for(part_t i=0;i<numSeparators;i++)
339 {
340 part_t level = sepLevels[i];
341
342 for(typename std::set<part_t>::const_iterator iter = sepParts1[i].begin();
343 iter!=sepParts1[i].end();++iter)
344 {
345 partLevelMap[level][*iter] = 2*sepsInLev[level];
346 }
347
348
349 for(typename std::set<part_t>::const_iterator iter = sepParts2[i].begin();
350 iter!=sepParts2[i].end();++iter)
351 {
352 partLevelMap[level][*iter] = 2*sepsInLev[level]+1;
353 }
354
355 sepsInLev[level]++;
356 }
358
359 // Set of separator vertices. Used to keep track of what vertices are
360 // already in previous calculated separators. These vertices should be
361 // excluded from future separator calculations
362 std::set<lno_t> sepVerts;
363 std::vector<std::vector< std::set<lno_t> > > sepVertsByLevel(numLevels);
364
366 // Loop over each cut
367 // 1. Build boundary layer between parts
368 // 2. Build vertex separator from boundary layer
370 for(part_t level=0;level<numLevels;level++)
371 {
372 sepVertsByLevel[level].resize(sepsInLev[level]);
373
374 for(part_t levIndx=0;levIndx<sepsInLev[level];levIndx++)
375 {
376
378 // Build boundary layer between parts (edge separator)
380 lno_t bigraphNumU=0, bigraphNumV=0;
381 lno_t bigraphNumE=0; // Should probably be size_t, but making lno_t for Matcher
382 std::vector<lno_t> bigraphVMapU;
383 std::vector<lno_t> bigraphVMapV;
384
385 std::vector<lno_t> bigraphCRSRowPtr;
386 std::vector<lno_t> bigraphCRSCols;
387
388
389 getBoundLayer(levIndx, partLevelMap[level], parts, sepVerts,
390 bigraphNumU,bigraphNumV,bigraphNumE,
391 bigraphCRSRowPtr, bigraphCRSCols,
392 bigraphVMapU,bigraphVMapV);
393
394 // std::cout << "Bipartite graph: " << bigraphNumU << " " << bigraphNumV << " "
395 // << bigraphNumE << std::endl;
396
397 // for (size_t i=0;i<bigraphVMapU.size();i++)
398 // {
399 // std::cout << "boundVertU: " << bigraphVMapU[i] << std::endl;
400 // }
401
402 // for (size_t i=0;i<bigraphVMapV.size();i++)
403 // {
404 // std::cout << "boundVertV: " << bigraphVMapV[i] << std::endl;
405 // }
406
407
408
409 // for (lno_t rownum=0;rownum<bigraphNumU;rownum++)
410 // {
411
412 // for (lno_t eIdx=bigraphCRSRowPtr[rownum];eIdx<bigraphCRSRowPtr[rownum+1];eIdx++)
413 // {
414 // std::cout << "bipartite E: " << bigraphVMapU[rownum] << ", " << bigraphVMapV[ bigraphCRSCols[eIdx]]
415 // << " ( " << rownum << "," << bigraphCRSCols[eIdx] << " )" << std::endl;
416 // }
417
418 // }
420
422 // Calculate bipartite matching from boundary layer
424 if (bigraphNumU > 0)
425 {
426 assert(bigraphNumV>0);
427
428 Matcher<lno_t> bpMatch(bigraphCRSRowPtr.data(), bigraphCRSCols.data(), bigraphNumU, bigraphNumV, bigraphNumE);
429 bpMatch.match();
430
431 const std::vector<lno_t> &vertUMatches = bpMatch.getVertexUMatches();
432 const std::vector<lno_t> &vertVMatches = bpMatch.getVertexVMatches();
434
436 // Calculate vertex cover (which is vertex separator) from matching
438 std::vector<lno_t> VC;
439
440 bpMatch.getVCfromMatching(bigraphCRSRowPtr,bigraphCRSCols,vertUMatches,vertVMatches,
441 bigraphVMapU,bigraphVMapV,VC);
442
443 for(size_t i=0;i<VC.size();i++)
444 {
445 sepVerts.insert(VC[i]);
446
447 sepVertsByLevel[level][levIndx].insert(VC[i]);
448 // std::cout << "VC: " << VC[i] << std::endl;
449 }
451 }
452 }
453 }
455
457 // Fill solution structures: invperm and separatorRange
459 bool inverse=true;
460 lno_t *ipermView = solution_->getPermutationView(inverse);
461 lno_t *sepRangeView = solution_->getSeparatorRangeView();
462
463 fillSolutionIperm(parts, sepVerts,sepVertsByLevel,treeIndxToSepLev,ipermView, sepRangeView);
464
465 solution_->setHaveInverse(true);
466 solution_->setHaveSeparatorRange(true);
468
470 // Output separators
472 std::cout << "Separators: " << std::endl;
473
474 part_t nLevels = sepVertsByLevel.size();
475 for(part_t level=0;level<nLevels;level++)
476 {
477 //sepVertsByLevel[level].resize(sepsInLev[level]);
478 part_t nSepsOnLev = sepVertsByLevel[level].size();
479
480 for(part_t levIndx=0;levIndx<nSepsOnLev;levIndx++)
481 {
482 std::cout << " Separator " << level << " " << levIndx << ": ";
483
484 typename std::set<lno_t>::const_iterator iterS;
485 for (iterS=sepVertsByLevel[level][levIndx].begin();iterS!=sepVertsByLevel[level][levIndx].end();++iterS)
486 {
487 std::cout << *iterS << " ";
488 }
489 std::cout << std::endl;
490 }
491 }
493
494
495 // std::cout << "iPerm: ";
496 // for(part_t i=0; i<numVerts; i++)
497 // {
498 // std::cout << ipermView[i] << " ";
499 // }
500 // std::cout << std::endl;
501
502 // std::cout << "sepRange: ";
503 // for(part_t i=0; i<treeVertParents.size()+1; i++)
504 // {
505 // std::cout << sepRangeView[i] << " ";
506 // }
507 // std::cout << std::endl;
508
510
511
513
514 mEnv->debug(DETAILED_STATUS, std::string("Exiting AlgND"));
515 return 0;
516}
518
520// Create boundary layer of vertices between 2 partitions
521//
522// Could improve the efficiency here by first creating a boundary layer graph
523// between all parts
525template <typename Adapter>
526void AlgND<Adapter>::getBoundLayer(part_t levelIndx, const std::vector<part_t> &partMap,
527 const part_t * parts,
528 const std::set<lno_t> &excVerts,
529 lno_t &bigraphNumS, lno_t &bigraphNumT, lno_t &bigraphNumE,
530 std::vector<lno_t> &bigraphCRSRowPtr, std::vector<lno_t> &bigraphCRSCols,
531 std::vector<lno_t> &bigraphVMapS, std::vector<lno_t> &bigraphVMapT)
532{
533 typedef typename Adapter::offset_t offset_t; // offset_t
535
536 lno_t numVerts = mGraphModel->getLocalNumVertices();
537
538 //Teuchos ArrayView
539 // Original -- ArrayView< const lno_t > eIDs;
540 ArrayView< const gno_t > eIDs;
541 ArrayView< const offset_t > vOffsets;
542 ArrayView< input_t > wgts;
543
544 // MMW:
545 // For some reason getLocalEdgeList seems to be returning empty eIDs
546 // getEdgeList expects eIDs to be an array of gno_t
547 // I wanted eIDs to be lno_t since this ordering is computed on a single node and
548 // it seems unnecessary to use the potentially larger gno_t.
549 // The problem might be that the partitioning is being calculated on the gno_t.
550 // Perhaps a solution would be set gno_t = lno_t in the partitioning.
551 // For now, I'll leave this since the edgelist is unlikely to be prohibitively big
552
553
554 mGraphModel->getEdgeList(eIDs, vOffsets, wgts);
555
556 // original
557 // ( (GraphModel<typename Adapter::base_adapter_t>) *mGraphModel).getEdgeList(eIDs, vOffsets, wgts);
558
559
560 std::map<lno_t,std::set<lno_t> > bigraphEs;
561 std::set<lno_t> vSetS;
562 std::set<lno_t> vSetT;
563
564 bigraphNumE=0;
565
566 for(lno_t v1=0;v1<numVerts;v1++)
567 {
568
569 part_t vpart1 = partMap[parts[v1]];
570
571 bool correctBL = (vpart1 >= 2*levelIndx && vpart1 < 2*(levelIndx+1) );
572
573 // if vertex is not in the correct range of parts, it cannot be a member of
574 // this boundary layer
575 if(!correctBL)
576 {
577 continue;
578 }
579
580 // Ignore vertices that belong to set of vertices to exclude
581 if(excVerts.find(v1)!=excVerts.end())
582 {
583 continue;
584 }
585
586 //Loop over edges connected to v1
587 //MMW figure out how to get this from Zoltan2
588 for(offset_t j=vOffsets[v1];j<vOffsets[v1+1];j++)
589 {
590
591 lno_t v2 = eIDs[j];
592
593 part_t vpart2 = partMap[parts[v2]];
594
595 correctBL = (vpart2 >= 2*levelIndx && vpart2 < 2*(levelIndx+1) );
596
597 // if vertex is not in the correct range of parts, it cannot be a member of
598 // this boundary layer
599 if(!correctBL)
600 {
601 continue;
602 }
603
604 // Ignore vertices that belong to set of vertices to exclude
605 if(excVerts.find(v2)!=excVerts.end())
606 {
607 continue;
608 }
609
610 if ( vpart1 != vpart2 )
611 {
612 // Vertex added to 1st set of boundary vertices
613 if(vpart1<vpart2)
614 {
615 vSetS.insert(v1);
616
617 // v1, v2
618 if(bigraphEs.find(v1)==bigraphEs.end())
619 {
620 bigraphEs[v1] = std::set<lno_t>();
621 }
622 bigraphEs[v1].insert(v2);
623 bigraphNumE++;
624
625 }
626 // Vertex added to 2nd set of boundary vertices
627 else
628 {
629 vSetT.insert(v1);
630 }
631 }
632
633 }
634 }
635
637 // Set size of two vertex sets for bipartite graph
639 bigraphNumS = vSetS.size();
640 bigraphNumT = vSetT.size();
642
645
646 bigraphVMapS.resize(bigraphNumS);
647
648 std::map<lno_t,lno_t> glob2LocTMap;
649
650 lno_t indx=0;
651 for(typename std::set<lno_t>::const_iterator iter=vSetS.begin(); iter!=vSetS.end(); ++iter)
652 {
653 bigraphVMapS[indx] = *iter;
654 indx++;
655 }
656
657
658 bigraphVMapT.resize(bigraphNumT);
659 indx=0;
660 for(typename std::set<lno_t>::const_iterator iter=vSetT.begin();iter!=vSetT.end();++iter)
661 {
662 bigraphVMapT[indx] = *iter;
663 glob2LocTMap[*iter]=indx;
664 indx++;
665 }
667
668
670 // Set sizes for bipartite graph data structures
672 bigraphCRSRowPtr.resize(bigraphNumS+1);
673 bigraphCRSCols.resize(bigraphNumE);
675
677 // Copy bipartite graph edges into CRS format
679 bigraphCRSRowPtr[0]=0;
680
681 lno_t rownum=0;
682 size_t nzIndx=0;
683 typename std::map<lno_t,std::set<lno_t> >::const_iterator iterM;
684 for (iterM=bigraphEs.begin();iterM!=bigraphEs.end();++iterM)
685 {
686 bigraphCRSRowPtr[rownum+1] = bigraphCRSRowPtr[rownum] + (*iterM).second.size();
687
688 for(typename std::set<lno_t>::const_iterator iter=(*iterM).second.begin(); iter!=(*iterM).second.end(); ++iter)
689 {
690 bigraphCRSCols[nzIndx] = glob2LocTMap[(*iter)];
691
692 nzIndx++;
693 }
694
695 rownum++;
696 }
698
699}
701
704template <typename Adapter>
705void AlgND<Adapter>::
706buildPartTree(part_t level, std::vector<part_t> &levIndx,
707 part_t startV,
708 const std::vector<part_t> &permPartNums,
709 const std::vector<part_t> &splitRangeBeg,
710 const std::vector<part_t> &splitRangeEnd,
711 const std::vector<part_t> &treeVertParents,
712 std::vector<part_t> &sepLevels,
713 std::vector<std::set<part_t> > &sepParts1, std::vector<std::set<part_t> > &sepParts2,
714 part_t &maxLev, part_t &gIndx,
715 part_t *sepTreeView,std::vector<std::pair<part_t,part_t> > &treeIndxToSepLev)
716{
717 // Insert information for this separator
718 maxLev=level;
719 part_t tmpMaxLev=maxLev;
720
722 // Search for indices that have parent startV
724 typename std::vector<part_t>::const_iterator iter;
725 std::vector<part_t> inds;
726 part_t ind=0;
727 for(iter=treeVertParents.begin(); iter!=treeVertParents.end(); ++iter)
728 {
729 if(*iter == startV)
730 {
731 inds.push_back(ind);
732 }
733 ind++;
734 }
736
738 // If startV has children, this will correspond to a separator. Construct
739 // appropriate data structure and then recurse
741 assert(inds.size()==2 || inds.size()==0);
742
743 // If startV has children
744 if(inds.size()==2)
745 {
746
747
748 if((part_t)levIndx.size() < level+1)
749 {
750 levIndx.push_back(0);
751 }
752 else
753 {
754 levIndx[level]++;
755 }
756
757 // std::cout << "gIndx " << gIndx << ": separator " << level << " " << levIndx[level] << std::endl;
758
759 treeIndxToSepLev[gIndx].first = level;
760 treeIndxToSepLev[gIndx].second = levIndx[level];
761
762 part_t v0 = inds[0];
763 part_t v1 = inds[1];
764
765 sepLevels.push_back(level);
766
767 sepParts1.push_back(std::set<part_t>());
768 typename std::vector<std::set<part_t> >::iterator setIter = sepParts1.end();
769 setIter--; // set iterator to point to new set
770
771 for(part_t k=splitRangeBeg[v0]; k<splitRangeEnd[v0]; k++)
772 {
773 (*setIter).insert(permPartNums[k]);
774 }
775
776
777 sepParts2.push_back(std::set<part_t>());
778 setIter = sepParts2.end();
779 setIter--; // set iterator to point to new set
780
781 for(part_t k=splitRangeBeg[v1]; k<splitRangeEnd[v1]; k++)
782 {
783 (*setIter).insert(permPartNums[k]);
784 }
785
786 part_t parentNode = gIndx;
787 gIndx--;
788 sepTreeView[gIndx] = parentNode;
789
790 // Recursively call function on children
791 buildPartTree(level+1, levIndx,v0,
792 permPartNums, splitRangeBeg, splitRangeEnd, treeVertParents,
793 sepLevels, sepParts1, sepParts2,
794 tmpMaxLev,
795 gIndx,sepTreeView,treeIndxToSepLev);
796 if(tmpMaxLev>maxLev)
797 {
798 maxLev = tmpMaxLev;
799 }
800
801
802 gIndx--;
803 sepTreeView[gIndx] = parentNode;
804
805 buildPartTree(level+1, levIndx, v1,
806 permPartNums, splitRangeBeg, splitRangeEnd, treeVertParents,
807 sepLevels, sepParts1, sepParts2,
808 tmpMaxLev,
809 gIndx, sepTreeView,treeIndxToSepLev);
810 if(tmpMaxLev>maxLev)
811 {
812 maxLev = tmpMaxLev;
813 }
814
815
816 }
817 else // no children, so this is not a separator
818 {
819 // std::cout << "gIndx " << gIndx << " leaf: " << permPartNums[splitRangeBeg[startV]] << std::endl;
820 treeIndxToSepLev[gIndx].first = -1;
821 treeIndxToSepLev[gIndx].second = permPartNums[splitRangeBeg[startV]];
822
823 maxLev--;
824 }
826
827
828}
829
831
834template <typename Adapter>
835void AlgND<Adapter>::
836fillSolutionIperm(const part_t *parts, const std::set<lno_t> &sepVerts,
837 const std::vector<std::vector< std::set<lno_t> > > & sepVertsByLevel,
838 const std::vector<std::pair<part_t,part_t> > &treeIndxToSepLev,
839 lno_t * ipermView, lno_t *sepRangeView)
840{
841 lno_t permIndx=0;
842 lno_t sepRangeIndx=0;
843 sepRangeView[sepRangeIndx] = 0;
844
845 for(size_t i=0; i<treeIndxToSepLev.size();i++)
846 {
847 part_t lev = treeIndxToSepLev[i].first;
849 // Leaf node of separator tree
851 if(lev==-1)
852 {
853 std::set<lno_t> idSet;
854 getIdsOfPart(parts,treeIndxToSepLev[i].second,sepVerts,idSet);
855
856 for(typename std::set<lno_t>::const_iterator setIter=idSet.begin(); setIter != idSet.end();
857 ++setIter)
858 {
859 ipermView[permIndx]=*setIter;
860 permIndx++;
861 }
862 sepRangeView[sepRangeIndx+1]=sepRangeView[sepRangeIndx]+idSet.size();
863 sepRangeIndx++;
864
865 }
868 // Internal "separator node" of separator tree
870 else
871 {
872 const std::set<lno_t> &idSet = sepVertsByLevel[lev][treeIndxToSepLev[i].second];
873
874 for(typename std::set<lno_t>::const_iterator setIter=idSet.begin();
875 setIter != idSet.end(); ++setIter)
876 {
877 ipermView[permIndx]=*setIter;
878 permIndx++;
879 }
880 sepRangeView[sepRangeIndx+1]=sepRangeView[sepRangeIndx]+idSet.size();
881 sepRangeIndx++;
882
883 }
885
886 }
887}
889
890
893template <typename Adapter>
894void AlgND<Adapter>::
895getIdsOfPart(const part_t *parts, part_t targetPart,const std::set<lno_t> &idsToExcl,
896 std::set<lno_t> &outIds)
897{
898 size_t numVerts = mGraphModel->getLocalNumVertices();
899
900 for(size_t i=0; i<numVerts; i++)
901 {
902 if(parts[i]==targetPart && idsToExcl.find(i)==idsToExcl.end())
903 {
904 outIds.insert(i);
905 }
906 }
907
908}
910
911
912} // namespace Zoltan2
913
914
915
916
917
918#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.
AlgND(const RCP< const Environment > &env_, const RCP< const Comm< int > > &problemComm_, const RCP< GraphModel< typename Adapter::base_adapter_t > > &gModel_, const RCP< CoordinateModel< typename Adapter::base_adapter_t > > &cModel_, const RCP< const typename Adapter::base_adapter_t > baseInputAdapter_)
static void getValidParameters(ParameterList &pl)
Set up validators specific to this algorithm
int globalOrder(const RCP< GlobalOrderingSolution< gno_t > > &solution_)
Ordering method.
Algorithm defines the base class for all algorithms.
This class provides geometric coordinates with optional weights to the Zoltan2 algorithm.
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
Definition: mapRemotes.cpp:17
map_t::global_ordinal_type gno_t
Definition: mapRemotes.cpp:18
Created by mbenlioglu on Aug 31, 2020.
@ DETAILED_STATUS
sub-steps, each method's entry and exit
SparseMatrixAdapter_t::part_t part_t