Zoltan2
Loading...
Searching...
No Matches
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
14#include <Zoltan2_Algorithm.hpp>
16#include <Zoltan2_Util.hpp>
17#include <Zoltan2_TPLTraits.hpp>
18
22
24#ifndef HAVE_ZOLTAN2_PULP
25
26namespace Zoltan2 {
27// Error handling for when PuLP is requested
28// but Zoltan2 not built with PuLP.
29
30template <typename Adapter>
31class AlgPuLP : public Algorithm<Adapter>
32{
33public:
34 typedef typename Adapter::base_adapter_t base_adapter_t;
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
61namespace Zoltan2 {
62
63extern "C" {
64// TODO: XtraPuLP
65#ifndef HAVE_ZOLTAN2_MPI
66#include "pulp.h"
67#else
68#include "xtrapulp.h"
69#endif
70}
71
72
73template <typename Adapter>
74class AlgPuLP : public Algorithm<Adapter>
75{
76public:
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"))
149 else if (objectOfInterest == std::string("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"))
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
218private:
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
233template <typename Adapter>
234void 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"))
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/*
268NOTE:
269 Assumes installed PuLP library is version pulp-0.2
270 Assumes installed XtraPuLP library is version xtrapulp-0.3
271*/
272template <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;
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
592template <typename Adapter>
593int* 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
Zoltan2::BasicUserTypes< zscalar_t, zlno_t, zgno_t > user_t
Definition Metric.cpp:39
Defines the GraphModel interface.
Defines the PartitioningSolution class.
#define HELLO
Traits class to handle conversions between gno_t/lno_t and TPL data types (e.g., ParMETIS's idx_t,...
A gathering of useful namespace methods.
AlgPuLP(const RCP< const Environment > &, const RCP< const Comm< int > > &, const RCP< const base_adapter_t > &)
Adapter::base_adapter_t base_adapter_t
static void getValidParameters(ParameterList &)
Set up validators specific to this algorithm.
Algorithm defines the base class for all algorithms.
virtual void partition(const RCP< PartitioningSolution< Adapter > > &)
Partitioning method.
Adapter::scalar_t scalar_t
static RCP< Teuchos::BoolParameterEntryValidator > getBoolValidator()
Exists to make setting up validators less cluttered.
static RCP< Teuchos::AnyNumberParameterEntryValidator > getAnyDoubleValidator()
Exists to make setting up validators less cluttered.
static RCP< Teuchos::AnyNumberParameterEntryValidator > getAnyIntValidator()
Exists to make setting up validators less cluttered.
Created by mbenlioglu on Aug 31, 2020.
std::bitset< NUM_MODEL_FLAGS > modelFlag_t
@ DETAILED_STATUS
sub-steps, each method's entry and exit
@ BASIC_ASSERTION
fast typical checks for valid arguments
@ VERTICES_ARE_MATRIX_ROWS
use matrix rows as graph vertices
@ VERTICES_ARE_MESH_ELEMENTS
use mesh elements as vertices
@ BUILD_SUBSET_GRAPH
ignore invalid neighbors
@ GENERATE_CONSECUTIVE_IDS
algorithm requires consecutive ids
@ SYMMETRIZE_INPUT_TRANSPOSE
model must symmetrize input
@ SYMMETRIZE_INPUT_BIPARTITE
model must symmetrize input
@ REMOVE_SELF_EDGES
algorithm requires no self edges
@ VERTICES_ARE_MESH_NODES
use mesh nodes as vertices
@ VERTICES_ARE_MATRIX_COLUMNS
use columns as graph vertices
@ VERTICES_ARE_MATRIX_NONZEROS
use nonzeros as graph vertices
@ BUILD_LOCAL_GRAPH
model represents graph within only one rank
SparseMatrixAdapter_t::part_t part_t
static void DELETE_ARRAY(first_t **a)
static void ASSIGN_ARRAY(first_t **a, ArrayView< second_t > &b)