Zoltan2
Loading...
Searching...
No Matches
Zoltan2_MatrixPartitioningProblem.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_MATRIXPARTITIONINGPROBLEM_HPP_
15#define _ZOLTAN2_MATRIXPARTITIONINGPROBLEM_HPP_
16
17#include <Zoltan2_Problem.hpp>
18// #include <Zoltan2_PartitioningAlgorithms.hpp>
21// #include <Zoltan2_EvaluatePartition.hpp>
22// #include <Zoltan2_GraphModel.hpp>
23// #include <Zoltan2_IdentifierModel.hpp>
24// #include <Zoltan2_IntegerRangeList.hpp>
25// #include <Zoltan2_MachineRepresentation.hpp>
26// #include <Zoltan2_AlgSerialGreedy.hpp>
27
28
29// TODO:
30//
31// Currently, we are implementing this matrix partitioning with several
32// constraining assumptions. We should try to relax several of these.
33// In the meantime, we should report errors otherwise
34//
35// Assumptions:
36// 1. 2D Cartesian partitioning (generalize to all 2D, 1D+2D)
37// 2. Number of row processes = number of column processes (eventually relax this)
38// 3. Number of processors is a square number -- follows from 2
39// 4. Number of parts == number of processors
40// 5. Only supports matrix adapter (eventually maybe add graph, hypergraph)
41
42
43
44namespace Zoltan2{
45
68template<typename Adapter>
69class MatrixPartitioningProblem : public Problem<Adapter>
70{
71public:
72
73 typedef typename Adapter::scalar_t scalar_t;
74 typedef typename Adapter::gno_t gno_t;
75 typedef typename Adapter::lno_t lno_t;
76 typedef typename Adapter::part_t part_t;
77 typedef typename Adapter::user_t user_t;
78 typedef typename Adapter::base_adapter_t base_adapter_t;
79
80
81 //TODO FIND WAY TO LIMIT THIS TO ONLY WORK WITH MATRIX ADAPTER FOR NOW
82
84 MatrixPartitioningProblem(Adapter *A, ParameterList *p,
85 const RCP<const Teuchos::Comm<int> > &comm):
86 Problem<Adapter>(A,p,comm), solution_(),
87 inputType_(InvalidAdapterType),
88 algName_()
89 {
90 for(int i=0;i<MAX_NUM_MODEL_TYPES;i++) modelAvail_[i]=false;
91 initializeProblem();
92
93
94 }
95
96#ifdef HAVE_ZOLTAN2_MPI
97 typedef Teuchos::OpaqueWrapper<MPI_Comm> mpiWrapper_t;
100 MatrixPartitioningProblem(Adapter *A, ParameterList *p, MPI_Comm mpicomm):
102 rcp<const Comm<int> >(new Teuchos::MpiComm<int>(
103 Teuchos::opaqueWrapper(mpicomm))))
104 {
105 }
106
107
108 // Problem<Adapter>(A,p,comm), solution_(),
109 // inputType_(InvalidAdapterType),
110 // algName_()
111 // {
112 // for(int i=0;i<MAX_NUM_MODEL_TYPES;i++) modelAvail_[i]=false;
113 // initializeProblem();
114 // }
115#endif
116
118 MatrixPartitioningProblem(Adapter *A, ParameterList *p):
119 MatrixPartitioningProblem(A, p, Tpetra::getDefaultComm())
120 {
121
122 }
123
124
128
130 //
131 // \param updateInputData If true this indicates that either
132 // this is the first attempt at solution, or that we
133 // are computing a new solution and the input data has
134 // changed since the previous solution was computed.
135 // By input data we mean coordinates, topology, or weights.
136 // If false, this indicates that we are computing a
137 // new solution using the same input data was used for
138 // the previous solution, even though the parameters
139 // may have been changed.
140 //
141 // For the sake of performance, we ask the caller to set \c updateInputData
142 // to false if he/she is computing a new solution using the same input data,
143 // but different problem parameters, than that which was used to compute
144 // the most recent solution.
145
146 void solve(bool updateInputData=true );
147
149 //
150 // \return a reference to the solution to the most recent solve().
151
153 {
154 return *(solution_.getRawPtr());
155 };
156
159 static void getValidParameters(ParameterList & pl)
160 {
161 // Zoltan2_AlgMJ<Adapter>::getValidParameters(pl);
162 // AlgPuLP<Adapter>::getValidParameters(pl);
163 // AlgPTScotch<Adapter>::getValidParameters(pl);
164 // AlgSerialGreedy<Adapter>::getValidParameters(pl);
165 // AlgForTestingOnly<Adapter>::getValidParameters(pl);
166
167 // This set up does not use tuple because we didn't have constructors
168 // that took that many elements - Tuple will need to be modified and I
169 // didn't want to have low level changes with this particular refactor
170 // TO DO: Add more Tuple constructors and then redo this code to be
171 // Teuchos::tuple<std::string> algorithm_names( "rcb", "multijagged" ... );
172 Array<std::string> algorithm_names(1);
173 algorithm_names[0] = "2D Cartesian";
174 RCP<Teuchos::StringValidator> algorithm_Validator = Teuchos::rcp(
175 new Teuchos::StringValidator( algorithm_names ));
176 pl.set("algorithm", "2D Cartesian", "partitioning algorithm",
177 algorithm_Validator);
178
179
180 // TODO: create set of objectives for matrix partitioning: balance nonzeros, balance rows
181
182 // RCP<Teuchos::StringValidator> partitioning_objective_Validator =
183 // Teuchos::rcp( new Teuchos::StringValidator(
184 // Teuchos::tuple<std::string>( "balance_object_count",
185 // "balance_object_weight", "multicriteria_minimize_total_weight",
186 // "multicriteria_minimize_maximum_weight",
187 // "multicriteria_balance_total_maximum", "minimize_cut_edge_count",
188 // "minimize_cut_edge_weight", "minimize_neighboring_parts",
189 // "minimize_boundary_vertices" )));
190 // pl.set("partitioning_objective", "balance_object_weight",
191 // "objective of partitioning", partitioning_objective_Validator);
192
193 pl.set("imbalance_tolerance", 1.1, "imbalance tolerance, ratio of "
194 "maximum load over average load", Environment::getAnyDoubleValidator());
195
196 // num_global_parts >= 1
197 RCP<Teuchos::EnhancedNumberValidator<int>> num_global_parts_Validator =
198 Teuchos::rcp( new Teuchos::EnhancedNumberValidator<int>(
199 1, Teuchos::EnhancedNumberTraits<int>::max()) ); // no maximum
200 pl.set("num_global_parts", 1, "global number of parts to compute "
201 "(0 means use the number of processes)", num_global_parts_Validator);
202
203 // num_local_parts >= 0
204 RCP<Teuchos::EnhancedNumberValidator<int>> num_local_parts_Validator =
205 Teuchos::rcp( new Teuchos::EnhancedNumberValidator<int>(
206 0, Teuchos::EnhancedNumberTraits<int>::max()) ); // no maximum
207 pl.set("num_local_parts", 0, "number of parts to compute for this "
208 "process (num_global_parts == sum of all num_local_parts)",
209 num_local_parts_Validator);
210
211 // RCP<Teuchos::StringValidator> partitioning_approach_Validator =
212 // Teuchos::rcp( new Teuchos::StringValidator(
213 // Teuchos::tuple<std::string>( "partition", "repartition",
214 // "maximize_overlap" )));
215 // pl.set("partitioning_approach", "partition", "Partition from scratch, "
216 // "partition incrementally from current partition, of partition from "
217 // "scratch but maximize overlap with the current partition",
218 // partitioning_approach_Validator);
219
220 //TODO do I need new matrix model
221
222 // RCP<Teuchos::StringValidator> model_Validator = Teuchos::rcp(
223 // new Teuchos::StringValidator(
224 // Teuchos::tuple<std::string>( "hypergraph", "graph",
225 // "geometry", "ids" )));
226 // pl.set("model", "graph", "This is a low level parameter. Normally the "
227 // "library will choose a computational model based on the algorithm or "
228 // "objective specified by the user.", model_Validator);
229
230 }
231
232private:
233 void initializeProblem();
234
235 void createPartitioningProblem(bool newData);
236
237 RCP<MatrixPartitioningSolution<Adapter> > solution_;
238
239 BaseAdapterType inputType_;
240
241 bool modelAvail_[MAX_NUM_MODEL_TYPES];
242
243 std::string algName_;
244
245};
247
248
251template <typename Adapter>
252 void MatrixPartitioningProblem<Adapter>::initializeProblem()
253{
254 HELLO;
255
256 this->env_->debug(DETAILED_STATUS, "MatrixPartitioningProblem::initializeProblem");
257
258 inputType_ = this->inputAdapter_->adapterType();
259
260 if(inputType_ != MatrixAdapterType)
261 {
262 // TODO: Better error support
263 std::cerr << "Error: only matrix adapter type supported" << std::endl;
264 return;
265 }
266
267 this->env_->memory("After initializeProblem");
268}
270
273template <typename Adapter>
275{
276 std::cout << "MatrixPartitioningProblem solve " << std::endl;
277
278
279 this->env_->debug(DETAILED_STATUS, "Entering solve");
280
281 // Create the computational model.
282
283 this->env_->timerStart(MACRO_TIMERS, "create problem");
284
285 createPartitioningProblem(updateInputData);
286
287 this->env_->timerStop(MACRO_TIMERS, "create problem");
288
289 // Create the solution. The algorithm will query the Solution
290 // for part and weight information. The algorithm will
291 // update the solution with part assignments and quality metrics.
292
293 // Create the algorithm
294 try
295 {
296
297
298 //TODO NEED to add if statement back once parameters work
299 // if (algName_ == std::string("2D Cartesian"))
300 // {
301
302 // this->algorithm_ = rcp(new AlgMatrix<Adapter>(this->envConst_,
303 // this->comm_,
304 // this->baseInputAdapter_));
305
306
307 this->algorithm_ = rcp(new AlgMatrix<Adapter>(this->envConst_,
308 this->comm_,
309 this->baseInputAdapter_));
310 // }
311 // else {
312 // throw std::logic_error("partitioning algorithm not supported");
313 // }
314 }
316
317 // Create the solution
318 this->env_->timerStart(MACRO_TIMERS, "create solution");
320
321 try{
323 this->envConst_, this->comm_,
324 this->algorithm_);
325 }
327
328 solution_ = rcp(soln);
329
330 this->env_->timerStop(MACRO_TIMERS, "create solution");
331 this->env_->memory("After creating Solution");
332
333 // Call the algorithm
334
335 try
336 {
337 this->algorithm_->partitionMatrix(solution_);
338 }
340
341 this->env_->debug(DETAILED_STATUS, "Exiting solve");
342}
344
347template <typename Adapter>
349{
350 this->env_->debug(DETAILED_STATUS,
351 "MatrixPartitioningProblem::createPartitioningProblem");
352
353 using Teuchos::ParameterList;
354
355 // A Problem object may be reused. The input data may have changed and
356 // new parameters or part sizes may have been set.
357 //
358 // Save these values in order to determine if we need to create a new model.
359
360 // bool prevModelAvail[MAX_NUM_MODEL_TYPES];
361 // for(int i=0;i<MAX_NUM_MODEL_TYPES;i++)
362 // {
363 // prevModelAvail[i] = modelAvail_[i];
364 // }
365
366
367 // for(int i=0;i<MAX_NUM_MODEL_TYPES;i++)
368 // {
369 // modelAvail_[i] = false;
370 // }
371
372
373 this->env_->debug(DETAILED_STATUS, " parameters");
374 Environment &env = *(this->env_);
375 ParameterList &pl = env.getParametersNonConst();
376 const Teuchos::ParameterEntry *pe;
377 std::string defString("default");
378
379 // Did the user specify a computational model?
380 // Should I allow a model to be created?
381
382 // std::string model(defString);
383 // pe = pl.getEntryPtr("model");
384 // if (pe)
385 // model = pe->getValue<std::string>(&model);
386
387
388 // Did the user specify an algorithm?
389
390 std::string algorithm(defString);
391 pe = pl.getEntryPtr("algorithm");
392 if (pe)
393 algorithm = pe->getValue<std::string>(&algorithm);
394
395 // Possible algorithm requirements that must be conveyed to the model:
396
398 // Determine algorithm, model, and algorithm requirements. This
399 // is a first pass. Feel free to change this and add to it.
400
401 if (algorithm != defString)
402 {
403
404 // Figure out the model required by the algorithm
405 if (algorithm == std::string("2D Cartesian"))
406 {
407 algName_ = algorithm;
408 }
409 else
410 {
411 // Parameter list should ensure this does not happen.
412 throw std::logic_error("parameter list algorithm is invalid");
413 }
414 }
415
416 // Object to be partitioned? (rows, columns, etc)
417
418 // Perhaps should set this
419
420 // std::string objectOfInterest(defString);
421 // pe = pl.getEntryPtr("objects_to_partition");
422 // if (pe)
423 // objectOfInterest = pe->getValue<std::string>(&objectOfInterest);
424
425 this->env_->debug(DETAILED_STATUS, "createPartitioningProblem done");
426
427}
429
430
431} // namespace Zoltan2
432#endif
#define Z2_FORWARD_EXCEPTIONS
Forward an exception back through call stack.
Defines the Problem base class.
#define HELLO
The user parameters, debug, timing and memory profiling output objects, and error checking methods.
static RCP< Teuchos::AnyNumberParameterEntryValidator > getAnyDoubleValidator()
Exists to make setting up validators less cluttered.
Teuchos::ParameterList & getParametersNonConst()
Returns a reference to a non-const copy of the parameters.
MatrixPartitioningProblem sets up partitioning problems for the user.
static void getValidParameters(ParameterList &pl)
Set up validators specific to this Problem.
MatrixPartitioningProblem(Adapter *A, ParameterList *p)
Constructor where communicator is the Teuchos default.
const PartitioningSolution< Adapter > & getSolution()
Get the solution to the problem.
void solve(bool updateInputData=true)
Direct the problem to create a solution.
MatrixPartitioningProblem(Adapter *A, ParameterList *p, const RCP< const Teuchos::Comm< int > > &comm)
Constructor where Teuchos communicator is specified.
A PartitioningSolution is a solution to a partitioning problem.
A PartitioningSolution is a solution to a partitioning problem.
Problem base class from which other classes (PartitioningProblem, ColoringProblem,...
Created by mbenlioglu on Aug 31, 2020.
@ MAX_NUM_MODEL_TYPES
@ MACRO_TIMERS
Time an algorithm (or other entity) as a whole.
@ DETAILED_STATUS
sub-steps, each method's entry and exit
BaseAdapterType
An enum to identify general types of adapters.
@ InvalidAdapterType
unused value
@ MatrixAdapterType
matrix data