Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 
44 namespace Zoltan2{
45 
68 template<typename Adapter>
69 class MatrixPartitioningProblem : public Problem<Adapter>
70 {
71 public:
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;
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 
232 private:
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 
251 template <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 
273 template <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 
347 template <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 HELLO
Zoltan2::BaseAdapter< userTypes_t > base_adapter_t
Time an algorithm (or other entity) as a whole.
MatrixPartitioningProblem(Adapter *A, ParameterList *p, const RCP< const Teuchos::Comm< int > > &comm)
Constructor where Teuchos communicator is specified.
static void getValidParameters(ParameterList &pl)
Set up validators specific to this Problem.
#define Z2_FORWARD_EXCEPTIONS
Forward an exception back through call stack.
MatrixPartitioningProblem sets up partitioning problems for the user.
map_t::global_ordinal_type gno_t
Definition: mapRemotes.cpp:27
MatrixPartitioningProblem(Adapter *A, ParameterList *p)
Constructor where communicator is the Teuchos default.
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
Teuchos::ParameterList & getParametersNonConst()
Returns a reference to a non-const copy of the parameters.
A PartitioningSolution is a solution to a partitioning problem.
const PartitioningSolution< Adapter > & getSolution()
Get the solution to the problem.
BaseAdapterType
An enum to identify general types of adapters.
Problem base class from which other classes (PartitioningProblem, ColoringProblem, OrderingProblem, MatchingProblem, etc.) derive.
Defines the Problem base class.
map_t::local_ordinal_type lno_t
Definition: mapRemotes.cpp:26
The user parameters, debug, timing and memory profiling output objects, and error checking methods...
void solve(bool updateInputData=true)
Direct the problem to create a solution.
A PartitioningSolution is a solution to a partitioning problem.
Zoltan2::BasicUserTypes< zscalar_t, zlno_t, zgno_t > user_t
Definition: Metric.cpp:39