Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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
#define Z2_THROW_SERIAL(mystr)
Throw an error when code is run on more than one processor.
LO match()
Computes the maximum cardinality matching.
lno_t size() const
Return the length of the strided array.
interface to the Zoltan package
Defines the PartitioningSolution class.
An implementation of the Matcher interface that operates on Epetra matrices and Graphs.
sub-steps, each method&#39;s entry and exit
static void getValidParameters(ParameterList &pl)
Set up validators specific to this algorithm.
int globalOrder(const RCP< GlobalOrderingSolution< gno_t > > &solution_)
Ordering method.
SparseMatrixAdapter_t::part_t part_t
This class provides geometric coordinates with optional weights to the Zoltan2 algorithm.
Defines the IdentifierModel interface.
A PartitioningSolution is a solution to a partitioning problem.
The StridedData class manages lists of weights or coordinates.
Algorithm defines the base class for all algorithms.
The user parameters, debug, timing and memory profiling output objects, and error checking methods...
#define Z2_THROW_EXPERIMENTAL(mystr)
Throw an error when experimental code is requested but not compiled.
GraphModel defines the interface required for graph models.
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_)
int localOrder(const RCP< LocalOrderingSolution< lno_t > > &solution_)
Ordering method.