Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Zoltan2_AlgPuLP.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Zoltan2: A package of combinatorial algorithms for scientific computing
4 //
5 // Copyright 2012 NTESS and the Zoltan2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef _ZOLTAN2_ALGPULP_HPP_
11 #define _ZOLTAN2_ALGPULP_HPP_
12 
13 #include <Zoltan2_GraphModel.hpp>
14 #include <Zoltan2_Algorithm.hpp>
16 #include <Zoltan2_Util.hpp>
17 #include <Zoltan2_TPLTraits.hpp>
18 
22 
24 #ifndef HAVE_ZOLTAN2_PULP
25 
26 namespace Zoltan2 {
27 // Error handling for when PuLP is requested
28 // but Zoltan2 not built with PuLP.
29 
30 template <typename Adapter>
31 class AlgPuLP : public Algorithm<Adapter>
32 {
33 public:
35  AlgPuLP(const RCP<const Environment> &/* env */,
36  const RCP<const Comm<int> > &/* problemComm */,
37  const RCP<const base_adapter_t> &/* adapter */
38  )
39  {
40  throw std::runtime_error(
41  "BUILD ERROR: PuLP requested but not compiled into Zoltan2.\n"
42  "Please set CMake flag TPL_ENABLE_PuLP:BOOL=ON.");
43  }
44 
47  static void getValidParameters(ParameterList & /* pl */)
48  {
49  // No parameters needed in this error-handling version of AlgPuLP
50  }
51 };
52 
53 }
54 #endif
55 
58 
59 #ifdef HAVE_ZOLTAN2_PULP
60 
61 namespace Zoltan2 {
62 
63 extern "C" {
64 // TODO: XtraPuLP
65 #ifndef HAVE_ZOLTAN2_MPI
66 #include "pulp.h"
67 #else
68 #include "xtrapulp.h"
69 #endif
70 }
71 
72 
73 template <typename Adapter>
74 class AlgPuLP : public Algorithm<Adapter>
75 {
76 public:
77  typedef typename Adapter::base_adapter_t base_adapter_t;
78  typedef typename Adapter::lno_t lno_t;
79  typedef typename Adapter::gno_t gno_t;
80  typedef typename Adapter::offset_t offset_t;
81  typedef typename Adapter::scalar_t scalar_t;
82  typedef typename Adapter::part_t part_t;
83  typedef typename Adapter::user_t user_t;
84  typedef typename Adapter::userCoord_t userCoord_t;
85 
96  AlgPuLP(const RCP<const Environment> &env__,
97  const RCP<const Comm<int> > &problemComm__,
98  const RCP<const IdentifierAdapter<user_t> > &adapter__) :
99  env(env__), problemComm(problemComm__), adapter(adapter__)
100  {
101  std::string errStr = "cannot build GraphModel from IdentifierAdapter, ";
102  errStr += "PuLP requires Graph, Matrix, or Mesh Adapter";
103  throw std::runtime_error(errStr);
104  }
105 
106  AlgPuLP(const RCP<const Environment> &env__,
107  const RCP<const Comm<int> > &problemComm__,
108  const RCP<const VectorAdapter<user_t> > &adapter__) :
109  env(env__), problemComm(problemComm__), adapter(adapter__)
110  {
111  std::string errStr = "cannot build GraphModel from VectorAdapter, ";
112  errStr += "PuLP requires Graph, Matrix, or Mesh Adapter";
113  throw std::runtime_error(errStr);
114  }
115 
116  AlgPuLP(const RCP<const Environment> &env__,
117  const RCP<const Comm<int> > &problemComm__,
118  const RCP<const GraphAdapter<user_t,userCoord_t> > &adapter__) :
119  env(env__), problemComm(problemComm__), adapter(adapter__)
120  {
121  modelFlag_t flags;
122  flags.reset();
123 
124  buildModel(flags);
125  }
126 
127  AlgPuLP(const RCP<const Environment> &env__,
128  const RCP<const Comm<int> > &problemComm__,
129  const RCP<const MatrixAdapter<user_t,userCoord_t> > &adapter__) :
130  env(env__), problemComm(problemComm__), adapter(adapter__)
131  {
132  modelFlag_t flags;
133  flags.reset();
134 
135  const ParameterList &pl = env->getParameters();
136  const Teuchos::ParameterEntry *pe;
137 
138  std::string defString("default");
139  std::string objectOfInterest(defString);
140  pe = pl.getEntryPtr("objects_to_partition");
141  if (pe)
142  objectOfInterest = pe->getValue<std::string>(&objectOfInterest);
143 
144  if (objectOfInterest == defString ||
145  objectOfInterest == std::string("matrix_rows") )
146  flags.set(VERTICES_ARE_MATRIX_ROWS);
147  else if (objectOfInterest == std::string("matrix_columns"))
148  flags.set(VERTICES_ARE_MATRIX_COLUMNS);
149  else if (objectOfInterest == std::string("matrix_nonzeros"))
150  flags.set(VERTICES_ARE_MATRIX_NONZEROS);
151 
152  buildModel(flags);
153  }
154 
155  AlgPuLP(const RCP<const Environment> &env__,
156  const RCP<const Comm<int> > &problemComm__,
157  const RCP<const MeshAdapter<user_t> > &adapter__) :
158  env(env__), problemComm(problemComm__), adapter(adapter__)
159  {
160  modelFlag_t flags;
161  flags.reset();
162 
163  const ParameterList &pl = env->getParameters();
164  const Teuchos::ParameterEntry *pe;
165 
166  std::string defString("default");
167  std::string objectOfInterest(defString);
168  pe = pl.getEntryPtr("objects_to_partition");
169  if (pe)
170  objectOfInterest = pe->getValue<std::string>(&objectOfInterest);
171 
172  if (objectOfInterest == defString ||
173  objectOfInterest == std::string("mesh_nodes") )
174  flags.set(VERTICES_ARE_MESH_NODES);
175  else if (objectOfInterest == std::string("mesh_elements"))
176  flags.set(VERTICES_ARE_MESH_ELEMENTS);
177 
178  buildModel(flags);
179  }
180 
183  static void getValidParameters(ParameterList & pl)
184  {
185  pl.set("pulp_vert_imbalance", 1.1, "vertex imbalance tolerance, ratio of "
186  "maximum load over average load",
188 
189  pl.set("pulp_edge_imbalance", 1.1, "edge imbalance tolerance, ratio of "
190  "maximum load over average load",
192 
193  pl.set("pulp_imbalance", 1.1, "multiweight imbalance tolerance, ratio of "
194  "maximum load over average load",
196 
197  // bool parameter
198  pl.set("pulp_lp_init", false, "perform label propagation-based "
199  "initialization", Environment::getBoolValidator() );
200 
201  // bool parameter
202  pl.set("pulp_minimize_maxcut", false, "perform per-part max cut "
203  "minimization", Environment::getBoolValidator() );
204 
205  // bool parameter
206  pl.set("pulp_verbose", false, "verbose output",
208 
209  // bool parameter
210  pl.set("pulp_do_repart", false, "perform repartitioning",
212 
213  pl.set("pulp_seed", 0, "set pulp seed", Environment::getAnyIntValidator());
214  }
215 
216  void partition(const RCP<PartitioningSolution<Adapter> > &solution);
217 
218 private:
219 
220  void buildModel(modelFlag_t &flags);
221 
222  int* scale_weights( size_t n, int nWgt,
223  ArrayView<StridedData<lno_t, scalar_t> > fwgts);
224 
225  const RCP<const Environment> env;
226  const RCP<const Comm<int> > problemComm;
227  const RCP<const base_adapter_t> adapter;
228  RCP<const GraphModel<base_adapter_t> > model;
229 };
230 
231 
233 template <typename Adapter>
234 void AlgPuLP<Adapter>::buildModel(modelFlag_t &flags)
235 {
236  const ParameterList &pl = env->getParameters();
237  const Teuchos::ParameterEntry *pe;
238 
239  std::string defString("default");
240  std::string symParameter(defString);
241  pe = pl.getEntryPtr("symmetrize_graph");
242  if (pe){
243  symParameter = pe->getValue<std::string>(&symParameter);
244  if (symParameter == std::string("transpose"))
245  flags.set(SYMMETRIZE_INPUT_TRANSPOSE);
246  else if (symParameter == std::string("bipartite"))
247  flags.set(SYMMETRIZE_INPUT_BIPARTITE); }
248 
249  bool sgParameter = false;
250  pe = pl.getEntryPtr("subset_graph");
251  if (pe)
252  sgParameter = pe->getValue(&sgParameter);
253  if (sgParameter)
254  flags.set(BUILD_SUBSET_GRAPH);
255 
256  flags.set(REMOVE_SELF_EDGES);
257  flags.set(GENERATE_CONSECUTIVE_IDS);
258 #ifndef HAVE_ZOLTAN2_MPI
259  flags.set(BUILD_LOCAL_GRAPH);
260 #endif
261  this->env->debug(DETAILED_STATUS, " building graph model");
262  this->model = rcp(new GraphModel<base_adapter_t>(this->adapter, this->env,
263  this->problemComm, flags));
264  this->env->debug(DETAILED_STATUS, " graph model built");
265 }
266 
267 /*
268 NOTE:
269  Assumes installed PuLP library is version pulp-0.2
270  Assumes installed XtraPuLP library is version xtrapulp-0.3
271 */
272 template <typename Adapter>
274  const RCP<PartitioningSolution<Adapter> > &solution
275 )
276 {
277  HELLO;
278 
279  size_t numGlobalParts = solution->getTargetGlobalNumberOfParts();
280 
281  int num_parts = (int)numGlobalParts;
282  //TPL_Traits<int, size_t>::ASSIGN(num_parts, numGlobalParts, env);
283 
284  //#ifdef HAVE_ZOLTAN2_MPI
285  // TODO: XtraPuLP
286 
287  int ierr = 0;
288  int np = problemComm->getSize();
289 
290  // Get number of vertices and edges
291  const size_t modelVerts = model->getLocalNumVertices();
292  const size_t modelEdges = model->getLocalNumEdges();
293  int num_verts = (int)modelVerts;
294  long num_edges = (long)modelEdges;
295  //TPL_Traits<int, size_t>::ASSIGN(num_verts, modelVerts, env);
296  //TPL_Traits<long, size_t>::ASSIGN(num_edges, modelEdges, env);
297 
298  // Get vertex info
299  ArrayView<const gno_t> vtxIDs;
300  ArrayView<StridedData<lno_t, scalar_t> > vwgts;
301  size_t nVtx = model->getVertexList(vtxIDs, vwgts);
302  int nVwgts = model->getNumWeightsPerVertex();
303 
304 
305 #ifndef HAVE_ZOLTAN2_MPI
306  // PuLP current only supports a single vertex weight
307  if (nVwgts > 1) {
308  std::cerr << "Warning: NumWeightsPerVertex is " << nVwgts
309  << " but PuLP allows only one weight. "
310  << " Zoltan2 will use only the first weight per vertex."
311  << std::endl;
312  }
313 
314  std::unique_ptr<int[]> vertex_weights;
315  long vertex_weights_sum = 0;
316  if (nVwgts) {
317  nVwgts = 1;
318  vertex_weights = std::unique_ptr<int[]>(scale_weights(nVtx, nVwgts, vwgts));
319 
320  for (int i = 0; i < num_verts; ++i)
321  vertex_weights_sum += (long)vertex_weights[i];
322  } else {
323  vertex_weights = std::unique_ptr<int[]>(nullptr);
324  }
325 #else
326  // XtraPuLP supports an arbitrary number of vertex weights
327  std::unique_ptr<int[]> vertex_weights;
328  if (nVwgts) {
329  vertex_weights = std::unique_ptr<int[]>(scale_weights(nVtx, nVwgts, vwgts));
330  } else {
331  vertex_weights = std::unique_ptr<int[]>(nullptr);
332  }
333 #endif
334 
335  // Get edge info
336  ArrayView<const gno_t> adjs;
337  ArrayView<const offset_t> offsets;
338  ArrayView<StridedData<lno_t, scalar_t> > ewgts;
339  size_t nEdge = model->getEdgeList(adjs, offsets, ewgts);
340  int nEwgts = model->getNumWeightsPerEdge();
341  if (nEwgts > 1) {
342  std::cerr << "Warning: NumWeightsPerEdge is " << nEwgts
343  << " but PuLP/XtraPuLP allows only one weight. "
344  << " Zoltan2 will use only the first weight per edge."
345  << std::endl;
346  }
347 
348  std::unique_ptr<int[]> edge_weights;
349  if (nEwgts) {
350  nEwgts = 1;
351  edge_weights = std::unique_ptr<int[]>(scale_weights(nEdge, nEwgts, ewgts));
352  if (!nVwgts) {
353  // For XtraPulp, we need to fill vertex_weights array if we have
354  // any edge weights.
355  vertex_weights = std::unique_ptr<int[]>(new int[nVtx]);
356  nVwgts = 1;
357  for (size_t i = 0; i < nVtx; ++i) {
358  vertex_weights[i] = 1;
359  }
360  }
361  } else if (nVwgts) {
362  // For XtraPulp, we need to fill edge_weights array if we have
363  // any vertex weights.
364  edge_weights = std::unique_ptr<int[]>(new int[nEdge]);
365  for (size_t i = 0; i < nEdge; ++i) {
366  edge_weights[i] = 1;
367  }
368  } else {
369  edge_weights = std::unique_ptr<int[]>(nullptr);
370  }
371 
372 #ifndef HAVE_ZOLTAN2_MPI
373  // Create PuLP's graph structure
374  int* out_edges = nullptr;
375  long* out_offsets = nullptr;
377  TPL_Traits<long, const offset_t>::ASSIGN_ARRAY(&out_offsets, offsets);
378 
379  pulp_graph_t g = {num_verts, num_edges,
380  out_edges, out_offsets,
381  vertex_weights.get(), edge_weights.get(),
382  vertex_weights_sum};
383 
384 #else
385  // Create XtraPuLP's graph structure
386  unsigned long* out_edges = nullptr;
387  unsigned long* out_offsets = nullptr;
390 
391  const size_t modelVertsGlobal = model->getGlobalNumVertices();
392  const size_t modelEdgesGlobal = model->getGlobalNumEdges();
393  unsigned long num_verts_global = (unsigned long)modelVertsGlobal;
394  unsigned long num_edges_global = (unsigned long)modelEdgesGlobal;
395 
396  unsigned long* global_ids = nullptr;
398 
399  ArrayView<size_t> vtxDist;
400  model->getVertexDist(vtxDist);
401  unsigned long* verts_per_rank = new unsigned long[np+1];
402  for (int i = 0; i < np+1; ++i)
403  verts_per_rank[i] = vtxDist[i];
404 
405  dist_graph_t g;
406  create_xtrapulp_dist_graph(&g, num_verts_global, num_edges_global,
407  (unsigned long)num_verts, (unsigned long)num_edges,
408  out_edges, out_offsets, global_ids, verts_per_rank,
409  nVwgts, vertex_weights.get(), edge_weights.get());
410 #endif
411 
412 
413  // Create array for PuLP to return results in.
414  // Or write directly into solution parts array
415  ArrayRCP<part_t> partList(new part_t[num_verts], 0, num_verts, true);
416  int* parts = nullptr;
417  if (num_verts && (sizeof(int) == sizeof(part_t))) {
418  // Can write directly into the solution's memory
419  parts = (int *)partList.getRawPtr();
420  }
421  else {
422  // Can't use solution memory directly; will have to copy later.
423  parts = new int[num_verts];
424  }
425 
426  // TODO
427  // Implement target part sizes
428 
429  // Grab options from parameter list
430  const Teuchos::ParameterList &pl = env->getParameters();
431  const Teuchos::ParameterEntry *pe;
432 
433  // figure out which parts of the algorithm we're going to run
434  // Default to PuLP with BFS init
435  // PuLP - do_edge_min = false, do_maxcut_min = false
436  // PuLP-M - do_edge_bal = true, do_maxcut_min = false
437  // PuLP-MM - do_edge_bal = true/false, do_maxcut_min = true
438  // PuLP-MC - do_edge_bal = false, do_maxcut_min = true/false
439  bool do_lp_init = false;
440  bool do_bfs_init = true;
441  bool do_edge_bal = false;
442  bool do_repart = false;
443  bool do_maxcut_min = false;
444  bool verbose_output = false;
445 
446  // Do label propagation initialization instead of bfs?
447  pe = pl.getEntryPtr("pulp_lp_init");
448  if (pe) do_lp_init = pe->getValue(&do_lp_init);
449  if (do_lp_init) do_bfs_init = false;
450 
451  // Now look at additional objective
452  pe = pl.getEntryPtr("pulp_minimize_maxcut");
453  if (pe) {
454  do_maxcut_min = pe->getValue(&do_maxcut_min);
455  // If we're doing the secondary objective,
456  // set the additional constraint as well
457  if (do_maxcut_min) do_edge_bal = true;
458  }
459 
460  pe = pl.getEntryPtr("pulp_do_repart");
461  if (pe) {
462  do_repart = pe->getValue(&do_repart);
463  if (do_repart) {
464  // Do repartitioning with input parts
465  // TODO: read in current parts
466  // for (int i = 0; i < num_verts; ++i)
467  // parts[i] = something;
468  do_bfs_init = false;
469  do_lp_init = false;
470  std::string errStr = "repartitioning within (Xtra)PuLP is ";
471  errStr += "currently unsupported.";
472  throw std::runtime_error(errStr);
473  }
474  }
475 
476  // Now grab vertex and edge imbalances, defaults at 10%
477  double vert_imbalance = 1.1;
478  double edge_imbalance = 1.1;
479  double imbalance = 1.1;
480 
481  pe = pl.getEntryPtr("pulp_vert_imbalance");
482  if (pe) vert_imbalance = pe->getValue<double>(&vert_imbalance);
483  pe = pl.getEntryPtr("pulp_edge_imbalance");
484  if (pe) {
485  edge_imbalance = pe->getValue<double>(&edge_imbalance);
486  // if manually set edge imbalance, add do_edge_bal flag to true
487  do_edge_bal = true;
488  }
489  pe = pl.getEntryPtr("pulp_imbalance");
490  if (pe) imbalance = pe->getValue<double>(&imbalance);
491 
492  if (vert_imbalance < 1.0)
493  throw std::runtime_error("pulp_vert_imbalance must be '1.0' or greater.");
494  if (edge_imbalance < 1.0)
495  throw std::runtime_error("pulp_edge_imbalance must be '1.0' or greater.");
496  if (imbalance < 1.0)
497  throw std::runtime_error("pulp_imbalance must be '1.0' or greater.");
498 
499  // verbose output?
500  // TODO: fully implement verbose flag throughout PuLP
501  pe = pl.getEntryPtr("pulp_verbose");
502  if (pe) verbose_output = pe->getValue(&verbose_output);
503 
504  // using pulp seed?
505  int pulp_seed = rand();
506  pe = pl.getEntryPtr("pulp_seed");
507  if (pe) pulp_seed = pe->getValue(&pulp_seed);
508 
509 
510  if (verbose_output) {
511  printf("procid: %d, n: %i, m: %li, vb: %f, eb: %f, imb: %f, p: %i\n",
512  problemComm->getRank(),
513  num_verts, num_edges,
514  vert_imbalance, edge_imbalance, imbalance, num_parts);
515  }
516 
517  // Call partitioning; result returned in parts array
518 #ifndef HAVE_ZOLTAN2_MPI
519  // Create PuLP's partitioning data structure
520  pulp_part_control_t ppc = {vert_imbalance, edge_imbalance,
521  do_lp_init, do_bfs_init, do_repart,
522  do_edge_bal, do_maxcut_min,
523  verbose_output, pulp_seed};
524 
525  ierr = pulp_run(&g, &ppc, parts, num_parts);
526 
527  env->globalInputAssertion(__FILE__, __LINE__, "pulp_run",
528  !ierr, BASIC_ASSERTION, problemComm);
529 #else
530  // Create XtraPuLP's partitioning data structure
531  std::unique_ptr<double[]> constraints;
532  if (nVwgts > 0) {
533  constraints = std::unique_ptr<double[]>(new double[nVwgts]);
534  for (int i = 0; i < nVwgts; ++i) {
535  constraints[i] = imbalance;
536  }
537  } else {
538  constraints = std::unique_ptr<double[]>(nullptr);
539  }
540 
541 
542  pulp_part_control_t ppc = {
543  vert_imbalance, edge_imbalance,
544  constraints.get(), nVwgts,
545  do_lp_init, do_bfs_init, do_repart,
546  do_edge_bal, do_maxcut_min,
547  verbose_output, pulp_seed};
548 
549  ierr = xtrapulp_run(&g, &ppc, parts, num_parts);
550 
551  env->globalInputAssertion(__FILE__, __LINE__, "xtrapulp_run",
552  !ierr, BASIC_ASSERTION, problemComm);
553 #endif
554 
555 
556  // Load answer into the solution if necessary
557  if ( (sizeof(int) != sizeof(part_t)) || (num_verts == 0) ) {
558  for (int i = 0; i < num_verts; i++)
559  partList[i] = parts[i];
560  delete [] parts;
561  }
562 
563  solution->setParts(partList);
564 
565  env->memory("Zoltan2-(Xtra)PuLP: After creating solution");
566 
567  // Clean up copies made due to differing data sizes.
568 #ifndef HAVE_ZOLTAN2_MPI
571 #else
575 #endif
576 
577 
578 //#endif // DO NOT HAVE_MPI
579 }
580 
582 // Scale and round scalar_t weights (typically float or double) to
583 // PuLP int
584 // subject to sum(weights) <= max_wgt_sum.
585 // Scale only if deemed necessary.
586 //
587 // Note that we use ceil() instead of round() to avoid
588 // rounding to zero weights.
589 // Based on Zoltan's scale_round_weights, mode 1
590 //
591 // Modified from scale_weights() in Zoltan2_AlgParMETIS.hpp
592 template <typename Adapter>
593 int* AlgPuLP<Adapter>::scale_weights(
594  size_t nVtx, int nWgt,
595  ArrayView<StridedData<typename Adapter::lno_t,
596  typename Adapter::scalar_t> > fwgts
597 )
598 {
599  const double INT_EPSILON = 1e-5;
600 
601  int *iwgts = new int[nVtx*nWgt];
602  int *nonint_local = new int[nWgt+nWgt];
603  int *nonint = nonint_local + nWgt;
604 
605  double *sum_wgt_local = new double[nWgt*4];
606  double *max_wgt_local = sum_wgt_local + nWgt;
607  double *sum_wgt = max_wgt_local + nWgt;
608  double *max_wgt = sum_wgt + nWgt;
609 
610  for (int i = 0; i < nWgt; i++) {
611  nonint_local[i] = 0;
612  sum_wgt_local[i] = 0.0;
613  max_wgt_local[i] = 0.0;
614  }
615 
616  // Compute local sums of the weights
617  // Check whether all weights are integers
618  for (int j = 0; j < nWgt; j++) {
619  for (size_t i = 0; i < nVtx; i++) {
620  double fw = double(fwgts[j][i]);
621  if (!nonint_local[j]) {
622  int tmp = (int) floor(fw + .5); /* Nearest int */
623  if (fabs((double)tmp-fw) > INT_EPSILON) {
624  nonint_local[j] = 1;
625  }
626  }
627  sum_wgt_local[j] += fw;
628  if (fw > max_wgt_local[j]) max_wgt_local[j] = fw;
629  }
630  }
631 
632  Teuchos::reduceAll<int,int> (*problemComm, Teuchos::REDUCE_MAX, nWgt,
633  nonint_local, nonint);
634  Teuchos::reduceAll<int,double>(*problemComm, Teuchos::REDUCE_SUM, nWgt,
635  sum_wgt_local, sum_wgt);
636  Teuchos::reduceAll<int,double>(*problemComm, Teuchos::REDUCE_MAX, nWgt,
637  max_wgt_local, max_wgt);
638 
639  const double max_wgt_sum = double(std::numeric_limits<int>::max()/8);
640  for (int j = 0; j < nWgt; j++) {
641  double scale = 1.;
642 
643  // Scaling needed if weights are not integers or weights'
644  // range is not sufficient
645  if (nonint[j] || (max_wgt[j]<=INT_EPSILON) || (sum_wgt[j]>max_wgt_sum)) {
646  /* Calculate scale factor */
647  if (sum_wgt[j] != 0.) scale = max_wgt_sum/sum_wgt[j];
648  }
649 
650  /* Convert weights to positive integers using the computed scale factor */
651  for (size_t i = 0; i < nVtx; i++)
652  iwgts[i*nWgt+j] = (int) ceil(double(fwgts[j][i])*scale);
653  }
654 
655  delete [] nonint_local;
656  delete [] sum_wgt_local;
657 
658  return iwgts;
659 }
660 
661 
662 } // namespace Zoltan2
663 
664 #endif // HAVE_ZOLTAN2_PULP
665 
667 
668 
669 #endif
670 
use columns as graph vertices
#define HELLO
Zoltan2::BaseAdapter< userTypes_t > base_adapter_t
ignore invalid neighbors
use mesh nodes as vertices
virtual void partition(const RCP< PartitioningSolution< Adapter > > &)
Partitioning method.
fast typical checks for valid arguments
Adapter::base_adapter_t base_adapter_t
static RCP< Teuchos::BoolParameterEntryValidator > getBoolValidator()
Exists to make setting up validators less cluttered.
algorithm requires consecutive ids
std::bitset< NUM_MODEL_FLAGS > modelFlag_t
model must symmetrize input
map_t::global_ordinal_type gno_t
Definition: mapRemotes.cpp:27
model must symmetrize input
Defines the PartitioningSolution class.
static RCP< Teuchos::AnyNumberParameterEntryValidator > getAnyDoubleValidator()
Exists to make setting up validators less cluttered.
sub-steps, each method&#39;s entry and exit
SparseMatrixAdapter_t::part_t part_t
use matrix rows as graph vertices
algorithm requires no self edges
Adapter::scalar_t scalar_t
use nonzeros as graph vertices
Adapter::part_t part_t
Algorithm defines the base class for all algorithms.
map_t::local_ordinal_type lno_t
Definition: mapRemotes.cpp:26
static RCP< Teuchos::AnyNumberParameterEntryValidator > getAnyIntValidator()
Exists to make setting up validators less cluttered.
Traits class to handle conversions between gno_t/lno_t and TPL data types (e.g., ParMETIS&#39;s idx_t...
use mesh elements as vertices
static void ASSIGN_ARRAY(first_t **a, ArrayView< second_t > &b)
Defines the GraphModel interface.
A gathering of useful namespace methods.
static void DELETE_ARRAY(first_t **a)
model represents graph within only one rank
static void getValidParameters(ParameterList &)
Set up validators specific to this algorithm.
AlgPuLP(const RCP< const Environment > &, const RCP< const Comm< int > > &, const RCP< const base_adapter_t > &)
Zoltan2::BasicUserTypes< zscalar_t, zlno_t, zgno_t > user_t
Definition: Metric.cpp:39