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 
83 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<CoordinateModel<typename Adapter::base_adapter_t> > mIds;
103 
104  const RCP<const typename Adapter::base_adapter_t> mBaseInputAdapter;
105 
106  void getBoundLayer(part_t levelIndx, const std::vector<part_t> &partMap,
107  const part_t * parts,
108  const std::set<lno_t> &excVerts,
109  lno_t &bigraphNumS, lno_t &bigraphNumT, lno_t &bigraphNumE,
110  std::vector<lno_t> &bigraphCRSRowPtr, std::vector<lno_t> &bigraphCRSCols,
111  std::vector<lno_t> &bigraphVMapU, std::vector<lno_t> &bigraphVMapV);
112 
113  void buildPartTree(part_t level, std::vector<part_t> &levIndx,
114  part_t startV,
115  const std::vector<part_t> &permPartNums,
116  const std::vector<part_t> &splitRangeBeg,
117  const std::vector<part_t> &splitRangeEnd,
118  const std::vector<part_t> &treeVertParents,
119  std::vector<part_t> &sepLevels,
120  std::vector<std::set<part_t> > &sepParts1, std::vector<std::set<part_t> > &sepParts2,
121  part_t &maxLev,
122  part_t &sepTreeIndx,
123  part_t *sepTreeView, std::vector<std::pair<part_t,part_t> > &treeIndxToSepLev);
124 
125  void fillSolutionIperm(const part_t *parts, const std::set<lno_t> &sepVerts,
126  const std::vector<std::vector< std::set<lno_t> > > & sepVertsByLevel,
127  const std::vector<std::pair<part_t,part_t> > &treeIndxToSepLev,
128  lno_t * ipermView, lno_t *sepRangeView);
129 
130  void getIdsOfPart(const part_t *parts, part_t targetPart,const std::set<lno_t> &idsToExcl,
131  std::set<lno_t> &outIds);
132 
133 
134 public:
135  // Constructor
136  AlgND(const RCP<const Environment> &env_,
137  const RCP<const Comm<int> > &problemComm_,
140  const RCP<const typename Adapter::base_adapter_t> baseInputAdapter_
141  )
142  :mEnv(env_), mProblemComm(problemComm_), mPartitionMethod("rcb"),
143  mGraphModel(gModel_),
144  mIds(cModel_), mBaseInputAdapter(baseInputAdapter_)
145  {
146 #ifndef INCLUDE_ZOLTAN2_EXPERIMENTAL
147  Z2_THROW_EXPERIMENTAL("Zoltan2 AlgND is strictly experimental software ")
148 #endif
149 
150  if(mProblemComm->getSize()!=1)
151  {
152  Z2_THROW_SERIAL("Zoltan2 AlgND is strictly serial!");
153  }
154 
155 
156  const Teuchos::ParameterList &pl = mEnv->getParameters();
157  const Teuchos::ParameterEntry *pe;
158 
159 
160  pe = pl.getEntryPtr("edge_separator_method");
161 
162  if (pe)
163  {
164  mPartitionMethod = pe->getValue<std::string>(&mPartitionMethod);
165  }
166 
167  }
168 
169  // Ordering method
170  int localOrder(const RCP<LocalOrderingSolution<lno_t> > &solution_);
171  int globalOrder(const RCP<GlobalOrderingSolution<gno_t> > &solution_);
172 
175  static void getValidParameters(ParameterList & pl)
176  {
177 
178  RCP<Teuchos::StringValidator> es_method_Validator =
179  Teuchos::rcp( new Teuchos::StringValidator(Teuchos::tuple<std::string>( "rcb", "phg")));
180 
181  pl.set("edge_separator_method", "rcb", "ND ordering - Edge separator method", es_method_Validator);
182  }
183 
184 };
186 
189 template <typename Adapter>
191  const RCP<GlobalOrderingSolution<gno_t> > &solution_)
192 {
193  throw std::logic_error("AlgND does not support global ordering.");
194 }
195 
197 
198 
201 template <typename Adapter>
203 {
204  typedef typename Adapter::lno_t lno_t; // local ids
205 
206  mEnv->debug(DETAILED_STATUS, std::string("Entering AlgND"));
207 
209  // First, let's partition with RCB using Zoltan. Eventually, we will change
210  // to give an option to use PHG
212 
214  // Create parameter list for partitioning environment
216  Teuchos::ParameterList partParams;
217 
218  part_t numParts = mEnv->getParameters().template get<part_t>("num_global_parts");
219 
220  partParams.set("num_global_parts", numParts);
221 
222  // Keeping partitioning tree
223  partParams.set("keep_partition_tree", true);
224 
225 
226  // Set Zoltan parameter lists
227  Teuchos::ParameterList &zparams = partParams.sublist("zoltan_parameters",false);
228  zparams.set("LB_METHOD", mPartitionMethod);
230 
232  //Create new environment with parameters for partitioning
234  const RCP<const Environment> partEnv = rcp(new Zoltan2::Environment(partParams,this->mEnv->comm_));
236 
237  int nUserWts=0;
238 
239  RCP<AlgZoltan<Adapter> > algZoltan = rcp(new AlgZoltan<Adapter>(partEnv, mProblemComm, this->mBaseInputAdapter));
240 
241  RCP<PartitioningSolution<Adapter> > partSoln;
242  partSoln =
243  RCP<PartitioningSolution<Adapter> > (new PartitioningSolution<Adapter>(partEnv, mProblemComm, nUserWts,algZoltan));
244 
245 
246  algZoltan->partition(partSoln);
247 
248  size_t numGlobalParts = partSoln->getTargetGlobalNumberOfParts();
249 
250  const part_t *parts = partSoln->getPartListView();
251 
252  // size_t numVerts = mGraphModel->getLocalNumVertices();
253  // for(size_t i=0; i< numVerts; i++)
254  // {
255  // std::cout << "part[" << i << "] = " << parts[i] <<std::endl;
256  // }
258 
260  // Obtain partitioning tree info from solution
262 
263  // Need to guarantee partitioning tree is binary
264  assert(partSoln->isPartitioningTreeBinary()==true);
265 
267  // Get partitioning tree from solution
269  part_t numTreeVerts = 0;
270  std::vector<part_t> permPartNums; // peritab in Scotch
271 
272  std::vector<part_t> splitRangeBeg;
273  std::vector<part_t> splitRangeEnd;
274  std::vector<part_t> treeVertParents;
275 
276  partSoln->getPartitionTree(numTreeVerts,permPartNums,splitRangeBeg,
277  splitRangeEnd,treeVertParents);
279 
281  // Grab part numbers that are to be split by the separators
282  //
283  // Each separator i is represented by 1 integer and two sets of part_t's in the
284  // the following 3 structure:
285  //
286  // sepLevels[i] - level of separator
287  // sepParts1[i] - 1st set of parts on one side of separator
288  // sepParts2[i] - 2nd set of parts on other side of separator
289  //
291  std::vector<part_t> levInds;
292 
293  std::vector<part_t> sepLevels;
294  std::vector<std::set<part_t> > sepParts1;
295  std::vector<std::set<part_t> > sepParts2;
296 
297  std::vector<std::pair<part_t,part_t> > treeIndxToSepLev(treeVertParents.size());
298 
299  part_t maxLevel = 0;
300 
301  //View of separator tree structure of solution
302  part_t *sepTreeView = solution_->getSeparatorTreeView();
303 
304  part_t sepTreeIndx= treeVertParents.size()-1;
305 
306  sepTreeView[sepTreeIndx]=-1;
307 
308  buildPartTree(0, levInds, numTreeVerts, permPartNums, splitRangeBeg, splitRangeEnd, treeVertParents,
309  sepLevels, sepParts1, sepParts2, maxLevel, sepTreeIndx,sepTreeView,treeIndxToSepLev);
310 
311  solution_->setHaveSeparatorTree(true);
312 
313  // std::cout << "sepTreeView: ";
314  // for(part_t i=0; i<treeVertParents.size(); i++)
315  // {
316  // std::cout << sepTreeView[i] << " ";
317  // }
318  // std::cout << std::endl;
319 
320 
321  // std::cout << "treeIndxToSepLev:" << std::endl;
322  // for(part_t i=0; i<treeVertParents.size(); i++)
323  // {
324  // std::cout << treeIndxToSepLev[i].first << " " << treeIndxToSepLev[i].second <<std::endl;
325  // }
326 
327  part_t numSeparators = sepLevels.size();
330 
332  // Create a map that maps each part number to a new number based on
333  // the level of the hiearchy of the separator tree. This allows us
334  // to easily identify the boundary value vertices
336  part_t numLevels = maxLevel+1;
337 
338  std::vector<std::vector<part_t> > partLevelMap(numLevels,std::vector<part_t>(numGlobalParts));
339 
340  std::vector<part_t> sepsInLev(numLevels,0);
341 
342  for(part_t i=0;i<numSeparators;i++)
343  {
344  part_t level = sepLevels[i];
345 
346  for(typename std::set<part_t>::const_iterator iter = sepParts1[i].begin();
347  iter!=sepParts1[i].end();++iter)
348  {
349  partLevelMap[level][*iter] = 2*sepsInLev[level];
350  }
351 
352 
353  for(typename std::set<part_t>::const_iterator iter = sepParts2[i].begin();
354  iter!=sepParts2[i].end();++iter)
355  {
356  partLevelMap[level][*iter] = 2*sepsInLev[level]+1;
357  }
358 
359  sepsInLev[level]++;
360  }
362 
363  // Set of separator vertices. Used to keep track of what vertices are
364  // already in previous calculated separators. These vertices should be
365  // excluded from future separator calculations
366  std::set<lno_t> sepVerts;
367  std::vector<std::vector< std::set<lno_t> > > sepVertsByLevel(numLevels);
368 
370  // Loop over each cut
371  // 1. Build boundary layer between parts
372  // 2. Build vertex separator from boundary layer
374  for(part_t level=0;level<numLevels;level++)
375  {
376  sepVertsByLevel[level].resize(sepsInLev[level]);
377 
378  for(part_t levIndx=0;levIndx<sepsInLev[level];levIndx++)
379  {
380 
382  // Build boundary layer between parts (edge separator)
384  lno_t bigraphNumU=0, bigraphNumV=0;
385  lno_t bigraphNumE=0; // Should probably be size_t, but making lno_t for Matcher
386  std::vector<lno_t> bigraphVMapU;
387  std::vector<lno_t> bigraphVMapV;
388 
389  std::vector<lno_t> bigraphCRSRowPtr;
390  std::vector<lno_t> bigraphCRSCols;
391 
392 
393  getBoundLayer(levIndx, partLevelMap[level], parts, sepVerts,
394  bigraphNumU,bigraphNumV,bigraphNumE,
395  bigraphCRSRowPtr, bigraphCRSCols,
396  bigraphVMapU,bigraphVMapV);
397 
398  // std::cout << "Bipartite graph: " << bigraphNumU << " " << bigraphNumV << " "
399  // << bigraphNumE << std::endl;
400 
401  // for (size_t i=0;i<bigraphVMapU.size();i++)
402  // {
403  // std::cout << "boundVertU: " << bigraphVMapU[i] << std::endl;
404  // }
405 
406  // for (size_t i=0;i<bigraphVMapV.size();i++)
407  // {
408  // std::cout << "boundVertV: " << bigraphVMapV[i] << std::endl;
409  // }
410 
411 
412 
413  // for (lno_t rownum=0;rownum<bigraphNumU;rownum++)
414  // {
415 
416  // for (lno_t eIdx=bigraphCRSRowPtr[rownum];eIdx<bigraphCRSRowPtr[rownum+1];eIdx++)
417  // {
418  // std::cout << "bipartite E: " << bigraphVMapU[rownum] << ", " << bigraphVMapV[ bigraphCRSCols[eIdx]]
419  // << " ( " << rownum << "," << bigraphCRSCols[eIdx] << " )" << std::endl;
420  // }
421 
422  // }
424 
426  // Calculate bipartite matching from boundary layer
428  if (bigraphNumU > 0)
429  {
430  assert(bigraphNumV>0);
431 
432  Matcher<lno_t> bpMatch(bigraphCRSRowPtr.data(), bigraphCRSCols.data(), bigraphNumU, bigraphNumV, bigraphNumE);
433  bpMatch.match();
434 
435  const std::vector<lno_t> &vertUMatches = bpMatch.getVertexUMatches();
436  const std::vector<lno_t> &vertVMatches = bpMatch.getVertexVMatches();
438 
440  // Calculate vertex cover (which is vertex separator) from matching
442  std::vector<lno_t> VC;
443 
444  bpMatch.getVCfromMatching(bigraphCRSRowPtr,bigraphCRSCols,vertUMatches,vertVMatches,
445  bigraphVMapU,bigraphVMapV,VC);
446 
447  for(size_t i=0;i<VC.size();i++)
448  {
449  sepVerts.insert(VC[i]);
450 
451  sepVertsByLevel[level][levIndx].insert(VC[i]);
452  // std::cout << "VC: " << VC[i] << std::endl;
453  }
455  }
456  }
457  }
459 
461  // Fill solution structures: invperm and separatorRange
463  bool inverse=true;
464  lno_t *ipermView = solution_->getPermutationView(inverse);
465  lno_t *sepRangeView = solution_->getSeparatorRangeView();
466 
467  fillSolutionIperm(parts, sepVerts,sepVertsByLevel,treeIndxToSepLev,ipermView, sepRangeView);
468 
469  solution_->setHaveInverse(true);
470  solution_->setHaveSeparatorRange(true);
472 
474  // Output separators
476  std::cout << "Separators: " << std::endl;
477 
478  part_t nLevels = sepVertsByLevel.size();
479  for(part_t level=0;level<nLevels;level++)
480  {
481  //sepVertsByLevel[level].resize(sepsInLev[level]);
482  part_t nSepsOnLev = sepVertsByLevel[level].size();
483 
484  for(part_t levIndx=0;levIndx<nSepsOnLev;levIndx++)
485  {
486  std::cout << " Separator " << level << " " << levIndx << ": ";
487 
488  typename std::set<lno_t>::const_iterator iterS;
489  for (iterS=sepVertsByLevel[level][levIndx].begin();iterS!=sepVertsByLevel[level][levIndx].end();++iterS)
490  {
491  std::cout << *iterS << " ";
492  }
493  std::cout << std::endl;
494  }
495  }
497 
498 
499  // std::cout << "iPerm: ";
500  // for(part_t i=0; i<numVerts; i++)
501  // {
502  // std::cout << ipermView[i] << " ";
503  // }
504  // std::cout << std::endl;
505 
506  // std::cout << "sepRange: ";
507  // for(part_t i=0; i<treeVertParents.size()+1; i++)
508  // {
509  // std::cout << sepRangeView[i] << " ";
510  // }
511  // std::cout << std::endl;
512 
514 
515 
517 
518  mEnv->debug(DETAILED_STATUS, std::string("Exiting AlgND"));
519  return 0;
520 }
522 
524 // Create boundary layer of vertices between 2 partitions
525 //
526 // Could improve the efficiency here by first creating a boundary layer graph
527 // between all parts
529 template <typename Adapter>
530 void AlgND<Adapter>::getBoundLayer(part_t levelIndx, const std::vector<part_t> &partMap,
531  const part_t * parts,
532  const std::set<lno_t> &excVerts,
533  lno_t &bigraphNumS, lno_t &bigraphNumT, lno_t &bigraphNumE,
534  std::vector<lno_t> &bigraphCRSRowPtr, std::vector<lno_t> &bigraphCRSCols,
535  std::vector<lno_t> &bigraphVMapS, std::vector<lno_t> &bigraphVMapT)
536 {
537  typedef typename Adapter::lno_t lno_t; // local ids
538  typedef typename Adapter::offset_t offset_t; // offset_t
539  typedef typename Adapter::scalar_t scalar_t; // scalars
540  typedef StridedData<lno_t, scalar_t> input_t;
541 
542  lno_t numVerts = mGraphModel->getLocalNumVertices();
543 
544  //Teuchos ArrayView
545  // Original -- ArrayView< const lno_t > eIDs;
546  ArrayView< const gno_t > eIDs;
547  ArrayView< const offset_t > vOffsets;
548  ArrayView< input_t > wgts;
549 
550  // MMW:
551  // For some reason getLocalEdgeList seems to be returning empty eIDs
552  // getEdgeList expects eIDs to be an array of gno_t
553  // I wanted eIDs to be lno_t since this ordering is computed on a single node and
554  // it seems unnecessary to use the potentially larger gno_t.
555  // The problem might be that the partitioning is being calculated on the gno_t.
556  // Perhaps a solution would be set gno_t = lno_t in the partitioning.
557  // For now, I'll leave this since the edgelist is unlikely to be prohibitively big
558 
559 
560  mGraphModel->getEdgeList(eIDs, vOffsets, wgts);
561 
562  // original
563  // ( (GraphModel<typename Adapter::base_adapter_t>) *mGraphModel).getEdgeList(eIDs, vOffsets, wgts);
564 
565 
566  std::map<lno_t,std::set<lno_t> > bigraphEs;
567  std::set<lno_t> vSetS;
568  std::set<lno_t> vSetT;
569 
570  bigraphNumE=0;
571 
572  for(lno_t v1=0;v1<numVerts;v1++)
573  {
574 
575  part_t vpart1 = partMap[parts[v1]];
576 
577  bool correctBL = (vpart1 >= 2*levelIndx && vpart1 < 2*(levelIndx+1) );
578 
579  // if vertex is not in the correct range of parts, it cannot be a member of
580  // this boundary layer
581  if(!correctBL)
582  {
583  continue;
584  }
585 
586  // Ignore vertices that belong to set of vertices to exclude
587  if(excVerts.find(v1)!=excVerts.end())
588  {
589  continue;
590  }
591 
592  //Loop over edges connected to v1
593  //MMW figure out how to get this from Zoltan2
594  for(offset_t j=vOffsets[v1];j<vOffsets[v1+1];j++)
595  {
596 
597  lno_t v2 = eIDs[j];
598 
599  part_t vpart2 = partMap[parts[v2]];
600 
601  correctBL = (vpart2 >= 2*levelIndx && vpart2 < 2*(levelIndx+1) );
602 
603  // if vertex is not in the correct range of parts, it cannot be a member of
604  // this boundary layer
605  if(!correctBL)
606  {
607  continue;
608  }
609 
610  // Ignore vertices that belong to set of vertices to exclude
611  if(excVerts.find(v2)!=excVerts.end())
612  {
613  continue;
614  }
615 
616  if ( vpart1 != vpart2 )
617  {
618  // Vertex added to 1st set of boundary vertices
619  if(vpart1<vpart2)
620  {
621  vSetS.insert(v1);
622 
623  // v1, v2
624  if(bigraphEs.find(v1)==bigraphEs.end())
625  {
626  bigraphEs[v1] = std::set<lno_t>();
627  }
628  bigraphEs[v1].insert(v2);
629  bigraphNumE++;
630 
631  }
632  // Vertex added to 2nd set of boundary vertices
633  else
634  {
635  vSetT.insert(v1);
636  }
637  }
638 
639  }
640  }
641 
643  // Set size of two vertex sets for bipartite graph
645  bigraphNumS = vSetS.size();
646  bigraphNumT = vSetT.size();
648 
651 
652  bigraphVMapS.resize(bigraphNumS);
653 
654  std::map<lno_t,lno_t> glob2LocTMap;
655 
656  lno_t indx=0;
657  for(typename std::set<lno_t>::const_iterator iter=vSetS.begin(); iter!=vSetS.end(); ++iter)
658  {
659  bigraphVMapS[indx] = *iter;
660  indx++;
661  }
662 
663 
664  bigraphVMapT.resize(bigraphNumT);
665  indx=0;
666  for(typename std::set<lno_t>::const_iterator iter=vSetT.begin();iter!=vSetT.end();++iter)
667  {
668  bigraphVMapT[indx] = *iter;
669  glob2LocTMap[*iter]=indx;
670  indx++;
671  }
673 
674 
676  // Set sizes for bipartite graph data structures
678  bigraphCRSRowPtr.resize(bigraphNumS+1);
679  bigraphCRSCols.resize(bigraphNumE);
681 
683  // Copy bipartite graph edges into CRS format
685  bigraphCRSRowPtr[0]=0;
686 
687  lno_t rownum=0;
688  size_t nzIndx=0;
689  typename std::map<lno_t,std::set<lno_t> >::const_iterator iterM;
690  for (iterM=bigraphEs.begin();iterM!=bigraphEs.end();++iterM)
691  {
692  bigraphCRSRowPtr[rownum+1] = bigraphCRSRowPtr[rownum] + (*iterM).second.size();
693 
694  for(typename std::set<lno_t>::const_iterator iter=(*iterM).second.begin(); iter!=(*iterM).second.end(); ++iter)
695  {
696  bigraphCRSCols[nzIndx] = glob2LocTMap[(*iter)];
697 
698  nzIndx++;
699  }
700 
701  rownum++;
702  }
704 
705 }
707 
710 template <typename Adapter>
711 void AlgND<Adapter>::
712 buildPartTree(part_t level, std::vector<part_t> &levIndx,
713  part_t startV,
714  const std::vector<part_t> &permPartNums,
715  const std::vector<part_t> &splitRangeBeg,
716  const std::vector<part_t> &splitRangeEnd,
717  const std::vector<part_t> &treeVertParents,
718  std::vector<part_t> &sepLevels,
719  std::vector<std::set<part_t> > &sepParts1, std::vector<std::set<part_t> > &sepParts2,
720  part_t &maxLev, part_t &gIndx,
721  part_t *sepTreeView,std::vector<std::pair<part_t,part_t> > &treeIndxToSepLev)
722 {
723  // Insert information for this separator
724  maxLev=level;
725  part_t tmpMaxLev=maxLev;
726 
728  // Search for indices that have parent startV
730  typename std::vector<part_t>::const_iterator iter;
731  std::vector<part_t> inds;
732  part_t ind=0;
733  for(iter=treeVertParents.begin(); iter!=treeVertParents.end(); ++iter)
734  {
735  if(*iter == startV)
736  {
737  inds.push_back(ind);
738  }
739  ind++;
740  }
742 
744  // If startV has children, this will correspond to a separator. Construct
745  // appropriate data structure and then recurse
747  assert(inds.size()==2 || inds.size()==0);
748 
749  // If startV has children
750  if(inds.size()==2)
751  {
752 
753 
754  if((part_t)levIndx.size() < level+1)
755  {
756  levIndx.push_back(0);
757  }
758  else
759  {
760  levIndx[level]++;
761  }
762 
763  // std::cout << "gIndx " << gIndx << ": separator " << level << " " << levIndx[level] << std::endl;
764 
765  treeIndxToSepLev[gIndx].first = level;
766  treeIndxToSepLev[gIndx].second = levIndx[level];
767 
768  part_t v0 = inds[0];
769  part_t v1 = inds[1];
770 
771  sepLevels.push_back(level);
772 
773  sepParts1.push_back(std::set<part_t>());
774  typename std::vector<std::set<part_t> >::iterator setIter = sepParts1.end();
775  setIter--; // set iterator to point to new set
776 
777  for(part_t k=splitRangeBeg[v0]; k<splitRangeEnd[v0]; k++)
778  {
779  (*setIter).insert(permPartNums[k]);
780  }
781 
782 
783  sepParts2.push_back(std::set<part_t>());
784  setIter = sepParts2.end();
785  setIter--; // set iterator to point to new set
786 
787  for(part_t k=splitRangeBeg[v1]; k<splitRangeEnd[v1]; k++)
788  {
789  (*setIter).insert(permPartNums[k]);
790  }
791 
792  part_t parentNode = gIndx;
793  gIndx--;
794  sepTreeView[gIndx] = parentNode;
795 
796  // Recursively call function on children
797  buildPartTree(level+1, levIndx,v0,
798  permPartNums, splitRangeBeg, splitRangeEnd, treeVertParents,
799  sepLevels, sepParts1, sepParts2,
800  tmpMaxLev,
801  gIndx,sepTreeView,treeIndxToSepLev);
802  if(tmpMaxLev>maxLev)
803  {
804  maxLev = tmpMaxLev;
805  }
806 
807 
808  gIndx--;
809  sepTreeView[gIndx] = parentNode;
810 
811  buildPartTree(level+1, levIndx, v1,
812  permPartNums, splitRangeBeg, splitRangeEnd, treeVertParents,
813  sepLevels, sepParts1, sepParts2,
814  tmpMaxLev,
815  gIndx, sepTreeView,treeIndxToSepLev);
816  if(tmpMaxLev>maxLev)
817  {
818  maxLev = tmpMaxLev;
819  }
820 
821 
822  }
823  else // no children, so this is not a separator
824  {
825  // std::cout << "gIndx " << gIndx << " leaf: " << permPartNums[splitRangeBeg[startV]] << std::endl;
826  treeIndxToSepLev[gIndx].first = -1;
827  treeIndxToSepLev[gIndx].second = permPartNums[splitRangeBeg[startV]];
828 
829  maxLev--;
830  }
832 
833 
834 }
835 
837 
840 template <typename Adapter>
841 void AlgND<Adapter>::
842 fillSolutionIperm(const part_t *parts, const std::set<lno_t> &sepVerts,
843  const std::vector<std::vector< std::set<lno_t> > > & sepVertsByLevel,
844  const std::vector<std::pair<part_t,part_t> > &treeIndxToSepLev,
845  lno_t * ipermView, lno_t *sepRangeView)
846 {
847  lno_t permIndx=0;
848  lno_t sepRangeIndx=0;
849  sepRangeView[sepRangeIndx] = 0;
850 
851  for(size_t i=0; i<treeIndxToSepLev.size();i++)
852  {
853  part_t lev = treeIndxToSepLev[i].first;
855  // Leaf node of separator tree
857  if(lev==-1)
858  {
859  std::set<lno_t> idSet;
860  getIdsOfPart(parts,treeIndxToSepLev[i].second,sepVerts,idSet);
861 
862  for(typename std::set<lno_t>::const_iterator setIter=idSet.begin(); setIter != idSet.end();
863  ++setIter)
864  {
865  ipermView[permIndx]=*setIter;
866  permIndx++;
867  }
868  sepRangeView[sepRangeIndx+1]=sepRangeView[sepRangeIndx]+idSet.size();
869  sepRangeIndx++;
870 
871  }
874  // Internal "separator node" of separator tree
876  else
877  {
878  const std::set<lno_t> &idSet = sepVertsByLevel[lev][treeIndxToSepLev[i].second];
879 
880  for(typename std::set<lno_t>::const_iterator setIter=idSet.begin();
881  setIter != idSet.end(); ++setIter)
882  {
883  ipermView[permIndx]=*setIter;
884  permIndx++;
885  }
886  sepRangeView[sepRangeIndx+1]=sepRangeView[sepRangeIndx]+idSet.size();
887  sepRangeIndx++;
888 
889  }
891 
892  }
893 }
895 
896 
899 template <typename Adapter>
900 void AlgND<Adapter>::
901 getIdsOfPart(const part_t *parts, part_t targetPart,const std::set<lno_t> &idsToExcl,
902  std::set<lno_t> &outIds)
903 {
904  size_t numVerts = mGraphModel->getLocalNumVertices();
905 
906  for(size_t i=0; i<numVerts; i++)
907  {
908  if(parts[i]==targetPart && idsToExcl.find(i)==idsToExcl.end())
909  {
910  outIds.insert(i);
911  }
912  }
913 
914 }
916 
917 
918 } // namespace Zoltan2
919 
920 
921 
922 
923 
924 #endif
Zoltan2::CoordinateModel
This class provides geometric coordinates with optional weights to the Zoltan2 algorithm.
Definition: Zoltan2_CoordinateModel.hpp:71
Zoltan2_MatcherHelper.hpp
Zoltan2::PartitioningSolution
A PartitioningSolution is a solution to a partitioning problem.
Definition: Zoltan2_PartitioningSolution.hpp:55
Z2_THROW_SERIAL
#define Z2_THROW_SERIAL(mystr)
Throw an error when code is run on more than one processor.
Definition: Zoltan2_Exceptions.hpp:154
Zoltan2::AlgND
Definition: Zoltan2_AlgND.hpp:85
Zoltan2::AlgND::AlgND
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_)
Definition: Zoltan2_AlgND.hpp:136
Zoltan2::DETAILED_STATUS
sub-steps, each method's entry and exit
Definition: Zoltan2_Parameters.hpp:101
part_t
SparseMatrixAdapter_t::part_t part_t
Definition: partitioningTree.cpp:74
Zoltan2_AlgZoltan.hpp
interface to the Zoltan package
Zoltan2::Matcher::match
LO match()
Definition: Zoltan2_MatcherHelper.hpp:547
Zoltan2::Environment
The user parameters, debug, timing and memory profiling output objects, and error checking methods.
Definition: Zoltan2_Environment.hpp:83
Zoltan2::Algorithm
Algorithm defines the base class for all algorithms.
Definition: Zoltan2_Algorithm.hpp:55
Zoltan2::AlgND::localOrder
int localOrder(const RCP< LocalOrderingSolution< lno_t > > &solution_)
Ordering method.
Definition: Zoltan2_AlgND.hpp:202
Zoltan2_IdentifierModel.hpp
Defines the IdentifierModel interface.
Zoltan2_PartitioningSolution.hpp
Defines the PartitioningSolution class.
Zoltan2::AlgZoltan
Definition: Zoltan2_AlgZoltan.hpp:77
Zoltan2::LocalOrderingSolution
Definition: Zoltan2_OrderingSolution.hpp:386
Zoltan2::GlobalOrderingSolution
Definition: Zoltan2_OrderingSolution.hpp:393
Z2_THROW_EXPERIMENTAL
#define Z2_THROW_EXPERIMENTAL(mystr)
Throw an error when experimental code is requested but not compiled.
Definition: Zoltan2_Exceptions.hpp:121
Zoltan2::AlgND::globalOrder
int globalOrder(const RCP< GlobalOrderingSolution< gno_t > > &solution_)
Ordering method.
Definition: Zoltan2_AlgND.hpp:190
Zoltan2
Definition: Zoltan2_AlgSerialGreedy.hpp:56
Zoltan2::AlgND::getValidParameters
static void getValidParameters(ParameterList &pl)
Set up validators specific to this algorithm
Definition: Zoltan2_AlgND.hpp:175
Zoltan2::Matcher
Definition: Zoltan2_MatcherHelper.hpp:40
Zoltan2_Algorithm.hpp
Zoltan2::GraphModel
GraphModel defines the interface required for graph models.
Definition: Zoltan2_GraphModel.hpp:80
Zoltan2::StridedData
The StridedData class manages lists of weights or coordinates.
Definition: Zoltan2_StridedData.hpp:76