Zoltan2
Loading...
Searching...
No Matches
Zoltan2_PartitioningProblem.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
14#ifndef _ZOLTAN2_PARTITIONINGPROBLEM_HPP_
15#define _ZOLTAN2_PARTITIONINGPROBLEM_HPP_
16
17#include <Zoltan2_Problem.hpp>
26#ifdef ZOLTAN2_TASKMAPPING_MOVE
28#endif
29
30#ifndef _WIN32
31#include <unistd.h>
32#else
33#include <process.h>
34#define NOMINMAX
35#include <windows.h>
36#endif
37
38#ifdef HAVE_ZOLTAN2_OVIS
39#include <ovis.h>
40#endif
41
42namespace Zoltan2{
43
67template<typename Adapter>
68class PartitioningProblem : public Problem<Adapter>
69{
70public:
71
72 typedef typename Adapter::scalar_t scalar_t;
73 typedef typename Adapter::gno_t gno_t;
74 typedef typename Adapter::lno_t lno_t;
75 typedef typename Adapter::part_t part_t;
76 typedef typename Adapter::user_t user_t;
77 typedef typename Adapter::base_adapter_t base_adapter_t;
78
80 PartitioningProblem(Adapter *A, ParameterList *p,
81 const RCP<const Teuchos::Comm<int> > &comm):
82 Problem<Adapter>(A,p,comm),
83 solution_(),
88 {
90 }
91
92#ifdef HAVE_ZOLTAN2_MPI
95 PartitioningProblem(Adapter *A, ParameterList *p, MPI_Comm mpicomm):
97 rcp<const Comm<int> >(new Teuchos::MpiComm<int>(
98 Teuchos::opaqueWrapper(mpicomm))))
99 {}
100#endif
101
103 PartitioningProblem(Adapter *A, ParameterList *p):
104 PartitioningProblem(A, p, Tpetra::getDefaultComm())
105 {}
106
110
112 //
113 // \param updateInputData If true this indicates that either
114 // this is the first attempt at solution, or that we
115 // are computing a new solution and the input data has
116 // changed since the previous solution was computed.
117 // By input data we mean coordinates, topology, or weights.
118 // If false, this indicates that we are computing a
119 // new solution using the same input data was used for
120 // the previous solution, even though the parameters
121 // may have been changed.
122 //
123 // For the sake of performance, we ask the caller to set \c updateInputData
124 // to false if he/she is computing a new solution using the same input data,
125 // but different problem parameters, than that which was used to compute
126 // the most recent solution.
127
128 void solve(bool updateInputData=true);
129
131 //
132 // \return a reference to the solution to the most recent solve().
133
135 return *(solution_.getRawPtr());
136 };
137
176 void setPartSizes(int len, part_t *partIds, scalar_t *partSizes,
177 bool makeCopy=true)
178 {
179 setPartSizesForCriteria(0, len, partIds, partSizes, makeCopy);
180 }
181
216 void setPartSizesForCriteria(int criteria, int len, part_t *partIds,
217 scalar_t *partSizes, bool makeCopy=true) ;
218/*
219 void setMachine(MachineRepresentation<typename Adapter::base_adapter_t::scalar_t> *machine);
220*/
221
224 static void getValidParameters(ParameterList & pl)
225 {
227
229
234
235 // This set up does not use tuple because we didn't have constructors
236 // that took that many elements - Tuple will need to be modified and I
237 // didn't want to have low level changes with this particular refactor
238 // TO DO: Add more Tuple constructors and then redo this code to be
239 // Teuchos::tuple<std::string> algorithm_names( "rcb", "multijagged" ... );
240 Array<std::string> algorithm_names(19);
241 algorithm_names[0] = "rcb";
242 algorithm_names[1] = "multijagged";
243 algorithm_names[2] = "rib";
244 algorithm_names[3] = "hsfc";
245 algorithm_names[4] = "patoh";
246 algorithm_names[5] = "phg";
247 algorithm_names[6] = "metis";
248 algorithm_names[7] = "parmetis";
249 algorithm_names[8] = "quotient";
250 algorithm_names[9] = "pulp";
251 algorithm_names[10] = "parma";
252 algorithm_names[11] = "scotch";
253 algorithm_names[12] = "ptscotch";
254 algorithm_names[13] = "block";
255 algorithm_names[14] = "cyclic";
256 algorithm_names[15] = "sarma";
257 algorithm_names[16] = "random";
258 algorithm_names[17] = "zoltan";
259 algorithm_names[18] = "forTestingOnly";
260 RCP<Teuchos::StringValidator> algorithm_Validator = Teuchos::rcp(
261 new Teuchos::StringValidator( algorithm_names ));
262 pl.set("algorithm", "random", "partitioning algorithm",
263 algorithm_Validator);
264
265 // bool parameter
266 pl.set("keep_partition_tree", false, "If true, will keep partition tree",
268
269 // bool parameter
270 pl.set("rectilinear", false, "If true, then when a cut is made, all of the "
271 "dots located on the cut are moved to the same side of the cut. The "
272 "resulting regions are then rectilinear. The resulting load balance may "
273 "not be as good as when the group of dots is split by the cut. ",
275
276 RCP<Teuchos::StringValidator> partitioning_objective_Validator =
277 Teuchos::rcp( new Teuchos::StringValidator(
278 Teuchos::tuple<std::string>( "balance_object_count",
279 "balance_object_weight", "multicriteria_minimize_total_weight",
280 "multicriteria_minimize_maximum_weight",
281 "multicriteria_balance_total_maximum", "minimize_cut_edge_count",
282 "minimize_cut_edge_weight", "minimize_neighboring_parts",
283 "minimize_boundary_vertices" )));
284 pl.set("partitioning_objective", "balance_object_weight",
285 "objective of partitioning", partitioning_objective_Validator);
286
287 pl.set("imbalance_tolerance", 1.1, "imbalance tolerance, ratio of "
288 "maximum load over average load", Environment::getAnyDoubleValidator());
289
290 // num_global_parts >= 1
291 RCP<Teuchos::EnhancedNumberValidator<int>> num_global_parts_Validator =
292 Teuchos::rcp( new Teuchos::EnhancedNumberValidator<int>(
293 1, Teuchos::EnhancedNumberTraits<int>::max()) ); // no maximum
294 pl.set("num_global_parts", 1, "global number of parts to compute "
295 "(0 means use the number of processes)", num_global_parts_Validator);
296
297 // num_local_parts >= 0
298 RCP<Teuchos::EnhancedNumberValidator<int>> num_local_parts_Validator =
299 Teuchos::rcp( new Teuchos::EnhancedNumberValidator<int>(
300 0, Teuchos::EnhancedNumberTraits<int>::max()) ); // no maximum
301 pl.set("num_local_parts", 0, "number of parts to compute for this "
302 "process (num_global_parts == sum of all num_local_parts)",
303 num_local_parts_Validator);
304
305 RCP<Teuchos::StringValidator> partitioning_approach_Validator =
306 Teuchos::rcp( new Teuchos::StringValidator(
307 Teuchos::tuple<std::string>( "partition", "repartition",
308 "maximize_overlap" )));
309 pl.set("partitioning_approach", "partition", "Partition from scratch, "
310 "partition incrementally from current partition, of partition from "
311 "scratch but maximize overlap with the current partition",
312 partitioning_approach_Validator);
313
314 RCP<Teuchos::StringValidator> objects_to_partition_Validator =
315 Teuchos::rcp( new Teuchos::StringValidator(
316 Teuchos::tuple<std::string>( "matrix_rows", "matrix_columns",
317 "matrix_nonzeros", "mesh_elements", "mesh_nodes", "graph_edges",
318 "graph_vertices", "coordinates", "identifiers" )));
319 pl.set("objects_to_partition", "graph_vertices", "Objects to be partitioned",
320 objects_to_partition_Validator);
321
322 RCP<Teuchos::StringValidator> model_Validator = Teuchos::rcp(
323 new Teuchos::StringValidator(
324 Teuchos::tuple<std::string>( "hypergraph", "graph",
325 "geometry", "ids" )));
326 pl.set("model", "graph", "This is a low level parameter. Normally the "
327 "library will choose a computational model based on the algorithm or "
328 "objective specified by the user.", model_Validator);
329
330 // bool parameter
331 pl.set("remap_parts", false, "remap part numbers to minimize migration "
332 "between old and new partitions", Environment::getBoolValidator() );
333
334 pl.set("mapping_type", -1, "Mapping of solution to the processors. -1 No"
335 " Mapping, 0 coordinate mapping.", Environment::getAnyIntValidator());
336
337 RCP<Teuchos::EnhancedNumberValidator<int>> ghost_layers_Validator =
338 Teuchos::rcp( new Teuchos::EnhancedNumberValidator<int>(1, 10, 1, 0) );
339 pl.set("ghost_layers", 2, "number of layers for ghosting used in "
340 "hypergraph ghost method", ghost_layers_Validator);
341 }
342
343protected:
344 void initializeProblem();
345 virtual void processAlgorithmName(const std::string& algorithm, const std::string& defString, const std::string& model,
346 Environment &env, bool& removeSelfEdges, bool &isGraphType, bool& needConsecutiveGlobalIds);
347
348 void createPartitioningProblem(bool newData);
349 virtual void createAlgorithm();
350
351 RCP<PartitioningSolution<Adapter> > solution_;
352#ifdef ZOLTAN2_TASKMAPPING_MOVE
353 RCP<MachineRepresentation<scalar_t,part_t> > machine_;
354#endif
355
357
361 std::string algName_;
362
364
365 // Suppose Array<part_t> partIds = partIds_[w]. If partIds.size() > 0
366 // then the user supplied part sizes for weight index "w", and the sizes
367 // corresponding to the Ids in partIds are partSizes[w].
368 //
369 // If numberOfWeights_ >= 0, then there is an Id and Sizes array for
370 // for each weight. Otherwise the user did not supply object weights,
371 // but they can still specify part sizes.
372 // So numberOfCriteria_ is numberOfWeights_ or one, whichever is greater.
373
374 ArrayRCP<ArrayRCP<part_t> > partIds_;
375 ArrayRCP<ArrayRCP<scalar_t> > partSizes_;
377
378 // Number of parts to be computed at each level in hierarchical partitioning.
379
380 ArrayRCP<int> levelNumberParts_;
382};
384
385/*
386template <typename Adapter>
387void PartitioningProblem<Adapter>::setMachine(MachineRepresentation<typename Adapter::base_adapter_t::scalar_t> *machine){
388 this->machine_ = RCP<MachineRepresentation<typename Adapter::base_adapter_t::scalar_t> > (machine, false);
389}
390*/
391
392
393template <typename Adapter>
395{
396 HELLO;
397
398 this->env_->debug(DETAILED_STATUS, "PartitioningProblem::initializeProblem");
399
400 if (getenv("DEBUGME")){
401#ifndef _WIN32
402 std::cout << getpid() << std::endl;
403 sleep(15);
404#else
405 std::cout << _getpid() << std::endl;
406 Sleep(15000);
407#endif
408 }
409
410#ifdef HAVE_ZOLTAN2_OVIS
411 ovis_enabled(this->comm_->getRank());
412#endif
413
414 // Create a copy of the user's communicator.
415
416#ifdef ZOLTAN2_TASKMAPPING_MOVE
417 machine_ = RCP<MachineRepresentation<scalar_t,part_t> >(
418 new MachineRepresentation<scalar_t,part_t>(*(this->comm_)));
419#endif
420
421 // Number of criteria is number of user supplied weights if non-zero.
422 // Otherwise it is 1 and uniform weight is implied.
423
424 numberOfWeights_ = this->inputAdapter_->getNumWeightsPerID();
425
426 numberOfCriteria_ = (numberOfWeights_ > 1) ? numberOfWeights_ : 1;
427
428 inputType_ = this->inputAdapter_->adapterType();
429
430 // The Caller can specify part sizes in setPartSizes(). If he/she
431 // does not, the part size arrays are empty.
432
433 ArrayRCP<part_t> *noIds = new ArrayRCP<part_t> [numberOfCriteria_];
434 ArrayRCP<scalar_t> *noSizes = new ArrayRCP<scalar_t> [numberOfCriteria_];
435
436 partIds_ = arcp(noIds, 0, numberOfCriteria_, true);
437 partSizes_ = arcp(noSizes, 0, numberOfCriteria_, true);
438
439 if (this->env_->getDebugLevel() >= DETAILED_STATUS){
440 std::ostringstream msg;
441 msg << this->comm_->getSize() << " procs,"
442 << numberOfWeights_ << " user-defined weights\n";
443 this->env_->debug(DETAILED_STATUS, msg.str());
444 }
445
446 this->env_->memory("After initializeProblem");
447}
448
449template <typename Adapter>
451 int criteria, int len, part_t *partIds, scalar_t *partSizes, bool makeCopy)
452{
453 this->env_->localInputAssertion(__FILE__, __LINE__, "invalid length",
454 len>= 0, BASIC_ASSERTION);
455
456 this->env_->localInputAssertion(__FILE__, __LINE__, "invalid criteria",
457 criteria >= 0 && criteria < numberOfCriteria_, BASIC_ASSERTION);
458
459 if (len == 0){
460 partIds_[criteria] = ArrayRCP<part_t>();
461 partSizes_[criteria] = ArrayRCP<scalar_t>();
462 return;
463 }
464
465 this->env_->localInputAssertion(__FILE__, __LINE__, "invalid arrays",
466 partIds && partSizes, BASIC_ASSERTION);
467
468 // The global validity of the partIds and partSizes arrays is performed
469 // by the PartitioningSolution, which computes global part distribution and
470 // part sizes.
471
472 part_t *z2_partIds = NULL;
473 scalar_t *z2_partSizes = NULL;
474 bool own_memory = false;
475
476 if (makeCopy){
477 z2_partIds = new part_t [len];
478 z2_partSizes = new scalar_t [len];
479 this->env_->localMemoryAssertion(__FILE__, __LINE__, len, z2_partSizes);
480 memcpy(z2_partIds, partIds, len * sizeof(part_t));
481 memcpy(z2_partSizes, partSizes, len * sizeof(scalar_t));
482 own_memory=true;
483 }
484 else{
485 z2_partIds = partIds;
486 z2_partSizes = partSizes;
487 }
488
489 partIds_[criteria] = arcp(z2_partIds, 0, len, own_memory);
490 partSizes_[criteria] = arcp(z2_partSizes, 0, len, own_memory);
491}
492
493 template <typename Adapter>
495 {
496 // Create the algorithm
497 if (algName_ == std::string("multijagged")) {
498 this->algorithm_ = rcp(new Zoltan2_AlgMJ<Adapter>(this->envConst_,
499 this->comm_,
500 this->baseInputAdapter_));
501 }
502 else if (algName_ == std::string("zoltan")) {
503 this->algorithm_ = rcp(new AlgZoltan<Adapter>(this->envConst_,
504 this->comm_,
505 this->baseInputAdapter_));
506 }
507 else if (algName_ == std::string("parma")) {
508 this->algorithm_ = rcp(new AlgParMA<Adapter>(this->envConst_,
509 this->comm_,
510 this->baseInputAdapter_));
511 }
512 else if (algName_ == std::string("scotch")) {
513 this->algorithm_ = rcp(new AlgPTScotch<Adapter>(this->envConst_,
514 this->comm_,
515 this->baseInputAdapter_));
516 }
517 else if (algName_ == std::string("parmetis")) {
518 using model_t = GraphModel<base_adapter_t>;
519 this->algorithm_ = rcp(new AlgParMETIS<Adapter, model_t>(this->envConst_,
520 this->comm_,
521 this->baseInputAdapter_,
522 this->graphFlags_));
523 }
524 else if (algName_ == std::string("quotient")) {
525 this->algorithm_ = rcp(new AlgQuotient<Adapter>(this->envConst_,
526 this->comm_,
527 this->baseInputAdapter_,
528 this->graphFlags_));
529 //"parmetis")); // The default alg. to use inside Quotient
530 } // is ParMETIS for now.
531 else if (algName_ == std::string("pulp")) {
532 this->algorithm_ = rcp(new AlgPuLP<Adapter>(this->envConst_,
533 this->comm_,
534 this->baseInputAdapter_));
535 }
536 else if (algName_ == std::string("block")) {
537 this->algorithm_ = rcp(new AlgBlock<Adapter>(this->envConst_,
538 this->comm_, this->baseInputAdapter_));
539 }
540 else if (algName_ == std::string("phg") ||
541 algName_ == std::string("patoh")) {
542 // phg and patoh provided through Zoltan
543 Teuchos::ParameterList &pl = this->env_->getParametersNonConst();
544 Teuchos::ParameterList &zparams = pl.sublist("zoltan_parameters",false);
545 if (numberOfWeights_ > 0) {
546 char strval[20];
547 sprintf(strval, "%d", numberOfWeights_);
548 zparams.set("OBJ_WEIGHT_DIM", strval);
549 }
550 zparams.set("LB_METHOD", algName_.c_str());
551 zparams.set("LB_APPROACH", "PARTITION");
552 algName_ = std::string("zoltan");
553
554 this->algorithm_ = rcp(new AlgZoltan<Adapter>(this->envConst_,
555 this->comm_,
556 this->baseInputAdapter_));
557 }
558 else if (algName_ == std::string("sarma")) {
559 this->algorithm_ = rcp(new AlgSarma<Adapter>(this->envConst_,
560 this->comm_,
561 this->baseInputAdapter_));
562 }
563 else if (algName_ == std::string("forTestingOnly")) {
564 this->algorithm_ = rcp(new AlgForTestingOnly<Adapter>(this->envConst_,
565 this->comm_,
566 this->baseInputAdapter_));
567 }
568 // else if (algName_ == std::string("rcb")) {
569 // this->algorithm_ = rcp(new AlgRCB<Adapter>(this->envConst_,this->comm_,
570 // this->coordinateModel_));
571 // }
572 else {
573 throw std::logic_error("partitioning algorithm not supported");
574 }
575 }
576
577template <typename Adapter>
578void PartitioningProblem<Adapter>::solve(bool updateInputData)
579{
580 this->env_->debug(DETAILED_STATUS, "Entering solve");
581
582 // Create the computational model.
583
584 this->env_->timerStart(MACRO_TIMERS, "create problem");
585
586 createPartitioningProblem(updateInputData);
587
588 this->env_->timerStop(MACRO_TIMERS, "create problem");
589
590 // TODO: If hierarchical_
591
592 // Create the solution. The algorithm will query the Solution
593 // for part and weight information. The algorithm will
594 // update the solution with part assignments and quality metrics.
595
596 // Create the algorithm
597 try {
598 this->createAlgorithm();
599 }
601 // Create the solution
602 this->env_->timerStart(MACRO_TIMERS, "create solution");
604
605 try{
607 this->envConst_, this->comm_, numberOfWeights_,
608 partIds_.view(0, numberOfCriteria_),
609 partSizes_.view(0, numberOfCriteria_), this->algorithm_);
610 }
612
613 solution_ = rcp(soln);
614
615 this->env_->timerStop(MACRO_TIMERS, "create solution");
616 this->env_->memory("After creating Solution");
617
618 // Call the algorithm
619
620 try {
621 this->algorithm_->partition(solution_);
622 }
624
625 //if mapping is requested
626 const Teuchos::ParameterEntry *pe = this->envConst_->getParameters().getEntryPtr("mapping_type");
627 int mapping_type = -1;
628 if (pe){
629 mapping_type = pe->getValue(&mapping_type);
630 }
631 //if mapping is 0 -- coordinate mapping
632
633#if ZOLTAN2_TASKMAPPING_MOVE
634 if (mapping_type == 0){
635
636 //part_t *task_communication_xadj = NULL, *task_communication_adj = NULL;
637
638 Zoltan2::CoordinateTaskMapper <Adapter, part_t> *ctm=
640 this->comm_.getRawPtr(),
641 machine_.getRawPtr(),
642 this->baseInputAdapter_.getRawPtr(),
643 solution_.getRawPtr(),
644 this->envConst_.getRawPtr()
645 //,task_communication_xadj,
646 //task_communication_adj
647 );
648
649 // KDD For now, we would need to re-map the part numbers in the solution.
650 // KDD I suspect we'll later need to distinguish between part numbers and
651 // KDD process numbers to provide separation between partitioning and
652 // KDD mapping. For example, does this approach here assume #parts == #procs?
653 // KDD If we map k tasks to p processes with k > p, do we effectively reduce
654 // KDD the number of tasks (parts) in the solution?
655
656#ifdef KDD_READY
657 const part_t *oldParts = solution_->getPartListView();
658 size_t nLocal = ia->getNumLocalIds();
659 for (size_t i = 0; i < nLocal; i++) {
660 // kind of cheating since oldParts is a view; probably want an interface in solution
661 // for resetting the PartList rather than hacking in like this.
662 oldParts[i] = ctm->getAssignedProcForTask(oldParts[i]);
663 }
664#endif
665
666 //for now just delete the object.
667 delete ctm;
668 }
669#endif
670
671 else if (mapping_type == 1){
672 //if mapping is 1 -- graph mapping
673 }
674
675 this->env_->debug(DETAILED_STATUS, "Exiting solve");
676}
677
678template <typename Adapter>
680 const std::string &algorithm, const std::string &defString,
681 const std::string &model, Environment &env, bool &removeSelfEdges,
682 bool &isGraphType, bool &needConsecutiveGlobalIds) {
683 ParameterList &pl = env.getParametersNonConst();
684
685 if (algorithm != defString) {
686 if (algorithm == std::string("block") ||
687 algorithm == std::string("random") ||
688 algorithm == std::string("cyclic") ||
689 algorithm == std::string("zoltan") ||
690 algorithm == std::string("parma") ||
691 algorithm == std::string("forTestingOnly") ||
692 algorithm == std::string("quotient") ||
693 algorithm == std::string("scotch") ||
694 algorithm == std::string("ptscotch") ||
695 algorithm == std::string("pulp") || algorithm == std::string("sarma") ||
696 algorithm == std::string("patoh") || algorithm == std::string("phg") ||
697 algorithm == std::string("multijagged")) {
698 algName_ = algorithm;
699 } else if (algorithm == std::string("rcb") ||
700 algorithm == std::string("rib") ||
701 algorithm == std::string("hsfc")) {
702 // rcb, rib, hsfc provided through Zoltan
703 Teuchos::ParameterList &zparams = pl.sublist("zoltan_parameters", false);
704 zparams.set("LB_METHOD", algorithm);
705 if (numberOfWeights_ > 0) {
706 char strval[20];
707 sprintf(strval, "%d", numberOfWeights_);
708 zparams.set("OBJ_WEIGHT_DIM", strval);
709 }
710 algName_ = std::string("zoltan");
711 } else if (algorithm == std::string("metis") ||
712 algorithm == std::string("parmetis")) {
713 algName_ = algorithm;
714 removeSelfEdges = true;
715 needConsecutiveGlobalIds = true;
716 isGraphType = true;
717 } else {
718 // Parameter list should ensure this does not happen.
719 throw std::logic_error("parameter list algorithm is invalid");
720 }
721 } else if (model != defString) {
722 // Figure out the algorithm suggested by the model.
723 if (model == std::string("hypergraph")) {
724 algName_ = std::string("phg");
725 } else if (model == std::string("graph")) {
726#ifdef HAVE_ZOLTAN2_SCOTCH
727 if (this->comm_->getSize() > 1)
728 algName_ = std::string("ptscotch");
729 else
730 algName_ = std::string("scotch");
731#else
732#ifdef HAVE_ZOLTAN2_PARMETIS
733 if (this->comm_->getSize() > 1)
734 algName_ = std::string("parmetis");
735 else
736 algName_ = std::string("metis");
737 removeSelfEdges = true;
738 needConsecutiveGlobalIds = true;
739 isGraphType = true;
740#else
741#ifdef HAVE_ZOLTAN2_PULP
742 // TODO: XtraPuLP
743 // if (this->comm_->getSize() > 1)
744 // algName_ = std::string("xtrapulp");
745 // else
746 algName_ = std::string("pulp");
747#else
748 algName_ = std::string("phg");
749#endif
750#endif
751#endif
752 } else if (model == std::string("geometry")) {
753 algName_ = std::string("multijagged");
754 } else if (model == std::string("ids")) {
755 algName_ = std::string("block");
756 } else {
757 // Parameter list should ensure this does not happen.
758 env.localBugAssertion(__FILE__, __LINE__,
759 "parameter list model type is invalid", 1,
761 }
762 } else {
763 // Determine an algorithm and model suggested by the input type.
764 // TODO: this is a good time to use the time vs. quality parameter
765 // in choosing an algorithm, and setting some parameters
766
767 if (inputType_ == MatrixAdapterType) {
768 algName_ = std::string("phg");
769 } else if (inputType_ == GraphAdapterType ||
770 inputType_ == MeshAdapterType) {
771 algName_ = std::string("phg");
772 } else if (inputType_ == VectorAdapterType) {
773 algName_ = std::string("multijagged");
774 } else if (inputType_ == IdentifierAdapterType) {
775 algName_ = std::string("block");
776 } else {
777 // This should never happen
778 throw std::logic_error("input type is invalid");
779 }
780 }
781}
782
783template <typename Adapter>
785{
786 this->env_->debug(DETAILED_STATUS,
787 "PartitioningProblem::createPartitioningProblem");
788
789 using Teuchos::ParameterList;
790
791 graphFlags_.reset();
792 idFlags_.reset();
793 coordFlags_.reset();
794
796 // It's possible at this point that the Problem may want to
797 // add problem parameters to the parameter list in the Environment.
798 //
799 // Since the parameters in the Environment have already been
800 // validated in its constructor, a new Environment must be created:
802 // Teuchos::RCP<const Teuchos::Comm<int> > oldComm = this->env_->comm_;
803 // const ParameterList &oldParams = this->env_->getUnvalidatedParameters();
804 //
805 // ParameterList newParams = oldParams;
806 // newParams.set("new_parameter", "new_value");
807 //
808 // ParameterList &newPartParams = newParams.sublist("partitioning");
809 // newPartParams.set("new_partitioning_parameter", "its_value");
810 //
811 // this->env_ = rcp(new Environment(newParams, oldComm));
813
814 this->env_->debug(DETAILED_STATUS, " parameters");
815 Environment &env = *(this->env_);
816 ParameterList &pl = env.getParametersNonConst();
817
818 std::string defString("default");
819
820 // Did the user specify a computational model?
821
822 std::string model(defString);
823 const Teuchos::ParameterEntry *pe = pl.getEntryPtr("model");
824 if (pe)
825 model = pe->getValue<std::string>(&model);
826
827 // Did the user specify an algorithm?
828
829 std::string algorithm(defString);
830 pe = pl.getEntryPtr("algorithm");
831 if (pe)
832 algorithm = pe->getValue<std::string>(&algorithm);
833
834 // Possible algorithm requirements that must be conveyed to the model:
835
836 bool needConsecutiveGlobalIds = false;
837 bool removeSelfEdges= false;
838 bool isGraphModel = false;
839
841 // Determine algorithm, model, and algorithm requirements. This
842 // is a first pass. Feel free to change this and add to it.
843
844 this->processAlgorithmName(algorithm, defString, model, env, removeSelfEdges,
845 isGraphModel, needConsecutiveGlobalIds);
846
847 // Hierarchical partitioning?
848
849 Array<int> valueList;
850 pe = pl.getEntryPtr("topology");
851
852 if (pe){
853 valueList = pe->getValue<Array<int> >(&valueList);
854
855 if (!Zoltan2::noValuesAreInRangeList<int>(valueList)){
856 int *n = new int [valueList.size() + 1];
857 levelNumberParts_ = arcp(n, 0, valueList.size() + 1, true);
858 int procsPerNode = 1;
859 for (int i=0; i < valueList.size(); i++){
860 levelNumberParts_[i+1] = valueList[i];
861 procsPerNode *= valueList[i];
862 }
863 // Number of parts in the first level
864 levelNumberParts_[0] = env.numProcs_ / procsPerNode;
865
866 if (env.numProcs_ % procsPerNode > 0)
867 levelNumberParts_[0]++;
868 }
869 }
870 else{
871 levelNumberParts_.clear();
872 }
873
874 hierarchical_ = levelNumberParts_.size() > 0;
875
876 // Object to be partitioned? (rows, columns, etc)
877
878 std::string objectOfInterest(defString);
879 pe = pl.getEntryPtr("objects_to_partition");
880 if (pe)
881 objectOfInterest = pe->getValue<std::string>(&objectOfInterest);
882
884 // Set model creation flags, if any.
885
886 this->env_->debug(DETAILED_STATUS, " models");
887
888 if (isGraphModel == true)
889 {
890
891 // Any parameters in the graph sublist?
892
893 std::string symParameter(defString);
894 pe = pl.getEntryPtr("symmetrize_graph");
895 if (pe){
896 symParameter = pe->getValue<std::string>(&symParameter);
897 if (symParameter == std::string("transpose"))
898 graphFlags_.set(SYMMETRIZE_INPUT_TRANSPOSE);
899 else if (symParameter == std::string("bipartite"))
900 graphFlags_.set(SYMMETRIZE_INPUT_BIPARTITE);
901 }
902
903 bool sgParameter = false;
904 pe = pl.getEntryPtr("subset_graph");
905 if (pe)
906 sgParameter = pe->getValue(&sgParameter);
907
908 if (sgParameter == 1)
909 graphFlags_.set(BUILD_SUBSET_GRAPH);
910
911 // Any special behaviors required by the algorithm?
912
913 if (removeSelfEdges)
914 graphFlags_.set(REMOVE_SELF_EDGES);
915
916 if (needConsecutiveGlobalIds)
917 graphFlags_.set(GENERATE_CONSECUTIVE_IDS);
918
919 // How does user input map to vertices and edges?
920
921 if (inputType_ == MatrixAdapterType){
922 if (objectOfInterest == defString ||
923 objectOfInterest == std::string("matrix_rows") )
924 graphFlags_.set(VERTICES_ARE_MATRIX_ROWS);
925 else if (objectOfInterest == std::string("matrix_columns"))
926 graphFlags_.set(VERTICES_ARE_MATRIX_COLUMNS);
927 else if (objectOfInterest == std::string("matrix_nonzeros"))
928 graphFlags_.set(VERTICES_ARE_MATRIX_NONZEROS);
929 }
930
931 else if (inputType_ == MeshAdapterType){
932 if (objectOfInterest == defString ||
933 objectOfInterest == std::string("mesh_nodes") )
934 graphFlags_.set(VERTICES_ARE_MESH_NODES);
935 else if (objectOfInterest == std::string("mesh_elements"))
936 graphFlags_.set(VERTICES_ARE_MESH_ELEMENTS);
937 }
938 }
939}
940
941} // namespace Zoltan2
942#endif
Serial greedy first-fit graph coloring (local graph only)
Defines the EvaluatePartition class.
#define Z2_FORWARD_EXCEPTIONS
Forward an exception back through call stack.
Defines the GraphModel interface.
Defines the IdentifierModel interface.
Define IntegerRangeList validator.
Defines the PartitioningSolution class.
Defines the Problem base class.
#define HELLO
static void getValidParameters(ParameterList &pl)
Set up validators specific to this algorithm.
static void getValidParameters(ParameterList &pl)
Set up validators specific to this algorithm.
static void getValidParameters(ParameterList &)
Set up validators specific to this algorithm.
static void getValidParameters(ParameterList &pl)
Set up validators specific to this algorithm.
static void getValidParameters(ParameterList &pl)
Set up validators specific to this algorithm.
part_t getAssignedProcForTask(part_t taskId)
getAssignedProcForTask function, returns the assigned processor id for the given task
The user parameters, debug, timing and memory profiling output objects, and error checking methods.
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.
int numProcs_
number of processes (relative to comm_)
static RCP< Teuchos::AnyNumberParameterEntryValidator > getAnyIntValidator()
Exists to make setting up validators less cluttered.
void localBugAssertion(const char *file, int lineNum, const char *msg, bool ok, AssertionLevel level) const
Test for valid library behavior on local process only.
Teuchos::ParameterList & getParametersNonConst()
Returns a reference to a non-const copy of the parameters.
GraphModel defines the interface required for graph models.
MachineRepresentation Class Base class for representing machine coordinates, networks,...
PartitioningProblem sets up partitioning problems for the user.
static void getValidParameters(ParameterList &pl)
Set up validators specific to this Problem.
ArrayRCP< ArrayRCP< part_t > > partIds_
virtual void processAlgorithmName(const std::string &algorithm, const std::string &defString, const std::string &model, Environment &env, bool &removeSelfEdges, bool &isGraphType, bool &needConsecutiveGlobalIds)
const PartitioningSolution< Adapter > & getSolution()
Get the solution to the problem.
void setPartSizesForCriteria(int criteria, int len, part_t *partIds, scalar_t *partSizes, bool makeCopy=true)
Set or reset the relative sizes (per weight) for the parts that Zoltan2 will create.
ArrayRCP< ArrayRCP< scalar_t > > partSizes_
PartitioningProblem(Adapter *A, ParameterList *p, const RCP< const Teuchos::Comm< int > > &comm)
Constructor where Teuchos communicator is specified.
void solve(bool updateInputData=true)
Direct the problem to create a solution.
RCP< PartitioningSolution< Adapter > > solution_
PartitioningProblem(Adapter *A, ParameterList *p)
Constructor where communicator is the Teuchos default.
void setPartSizes(int len, part_t *partIds, scalar_t *partSizes, bool makeCopy=true)
Set or reset relative sizes for the parts that Zoltan2 will create.
A PartitioningSolution is a solution to a partitioning problem.
Problem base class from which other classes (PartitioningProblem, ColoringProblem,...
Multi Jagged coordinate partitioning algorithm.
static void getValidParameters(ParameterList &pl)
Set up validators specific to this algorithm.
Created by mbenlioglu on Aug 31, 2020.
std::bitset< NUM_MODEL_FLAGS > modelFlag_t
@ MACRO_TIMERS
Time an algorithm (or other entity) as a whole.
@ DETAILED_STATUS
sub-steps, each method's entry and exit
@ BASIC_ASSERTION
fast typical checks for valid arguments
BaseAdapterType
An enum to identify general types of adapters.
@ VectorAdapterType
vector data
@ InvalidAdapterType
unused value
@ GraphAdapterType
graph data
@ MatrixAdapterType
matrix data
@ MeshAdapterType
mesh data
@ IdentifierAdapterType
identifier data, just a list of IDs
@ 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
SparseMatrixAdapter_t::part_t part_t