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 
67 namespace Zoltan2
68 {
69 
70 
72 
84 template <typename Adapter>
85 class AlgND : public Algorithm<typename Adapter::base_adapter_t>
86 {
87 
88 private:
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 
132 public:
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 
187 template <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 
199 template <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
525 template <typename Adapter>
526 void 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 
704 template <typename Adapter>
705 void AlgND<Adapter>::
706 buildPartTree(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 
834 template <typename Adapter>
835 void AlgND<Adapter>::
836 fillSolutionIperm(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 
893 template <typename Adapter>
894 void AlgND<Adapter>::
895 getIdsOfPart(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()
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.
const std::vector< LO > & getVertexUMatches()
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