Zoltan2
Zoltan2_ComparisonHelper.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Zoltan2: A package of combinatorial algorithms for scientific computing
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Karen Devine (kddevin@sandia.gov)
39 // Erik Boman (egboman@sandia.gov)
40 // Siva Rajamanickam (srajama@sandia.gov)
41 //
42 // ***********************************************************************
43 //
44 // @HEADER
45 
50 #pragma once
51 
52 #include "Zoltan2_TestHelpers.hpp"
54 #include <Zoltan2_Typedefs.hpp>
57 #include <AdapterForTests.hpp>
58 #include <Teuchos_DefaultComm.hpp>
59 #include <Teuchos_Time.hpp>
60 
61 #include <sstream>
62 #include <string>
63 #include <map>
64 #include <iostream>
65 
66 using Teuchos::Comm;
67 using Teuchos::RCP;
68 using Teuchos::ParameterList;
69 using Teuchos::Time;
70 using std::cout;
71 using std::endl;
72 using std::string;
73 using std::map;
74 using std::pair;
75 using std::ostringstream;
76 using Teuchos::reduceAll;
77 using namespace Zoltan2_TestingFramework;
78 
83 {
84 public:
85  /* \brief Add a timer by name to the comparison sources timers map.
86  * \param name is the name of the timer to be defined
87  */
88  void addTimer(const std::string &name)
89  {
90  timers.insert(std::pair<const std::string &, RCP<Time> >(name,rcp(new Time(name))));
91  timers[name]->enable();
92  }
93 
94  void printTimers()
95  {
96  for(auto it = timers.begin(); it != timers.end(); ++it) {
97  std::cout << it->first << " " << it->second->totalElapsedTime()
98  << std::endl;
99  }
100  }
101 
102  // TODO: Add method to print a timer summary: max/min/avg over all procs
103 
104  std::map<const std::string, RCP<Time> > timers;
105 
106  RCP<EvaluateFactory> evaluateFactory;
107  RCP<ProblemFactory> problemFactory;
108  RCP<AdapterFactory> adapterFactory;
109 };
110 
114 {
115 public:
116  /* \brief Compare the solutions, metrics or timers of two Zoltan2 solutions.
117  * \param pList is a parameter list defining the comparison
118  * \param comm is the process communicator
119  */
120  bool Compare(const ParameterList &pList, const RCP<const Comm<int> > &comm);
121 
122  /* \brief Add a new source by name to the comparison source map.
123  * \param name is the name of the new source
124  * \param source a problem source that to be used for comparison to another source
125  */
126  void AddSource(const string &name, RCP<ComparisonSource> source);
127 
128  /* \brief Return the total number of saved sources.
129  */
130  size_t getNumberOfSources() const
131  {
132  return this->sources.size();
133  }
134 
135 private:
136  map<const string,RCP<const ComparisonSource> > sources;
137 
138  /* \brief Method called to compare two solutions
139  * \param p1 is the name of problem 1
140  * \param p2 is the name of problem 2
141  * \param comm is the process communicator
142  */
143  bool CompareSolutions(const string &p1,
144  const string &p2,
145  const RCP<const Comm<int> > &comm);
146 
147  /* \brief Safely get parts list by adapter type
148  * \param problemFactory is the ProblemFactory
149  */
150  const zpart_t * getPartListView(RCP<ProblemFactory> problemFactory) const;
151 
152  /* \brief Method called to compare two paritioning solutions
153  * \param sourceA is a ptr to problem A's comparison source
154  * \param sourceB is a ptr to problem B's comparison source
155  * \param comm is the process communicator
156  */
157  bool ComparePartitionSolutions(const ComparisonSource * sourceA,
158  const ComparisonSource * sourceB,
159  const RCP<const Comm<int> > &comm);
160 
161  /* \brief Method called to compare two coloring solutions
162  * \param sourceA is a ptr to problem A's comparison source
163  * \param sourceB is a ptr to problem B's comparison source
164  * \param comm is the process communicator
165  */
166  bool CompareColoringSolutions(const ComparisonSource * sourceA,
167  const ComparisonSource * sourceB,
168  const RCP<const Comm<int> > &comm);
169 
170  /* \brief Method called to compare two ordering solutions
171  * \param sourceA is a ptr to problem A's comparison source
172  * \param sourceB is a ptr to problem B's comparison source
173  * \param comm is the process communicator
174  */
175  bool CompareOrderingSolutions(const ComparisonSource * sourceA,
176  const ComparisonSource * sourceB,
177  const RCP<const Comm<int> > &comm);
178 
179  /* \brief Safely get metric info by adapter type.
180  * \param problemFactory is the ProblemFactory
181  * \param metricInfo will be filled
182  * \param metricsPlist are the parameters to read
183  */
184  void loadMetricInfo(RCP<EvaluateFactory> problemFactory,
185  std::vector<MetricAnalyzerInfo> & metricInfo,
186  const ParameterList &metricsPlist);
187 
188  /* \brief Method called to compare the metrics/timers of two problems.
189  * \param metricsPlist is a parameter list defining the comparison
190  * \param comm is the process communicator
191  */
192  bool CompareMetrics(const ParameterList &metricsPlist,
193  const RCP<const Comm<int> > &comm);
194 
195  /* \brief Method that compares two metrics and returns a pass/fail message.
196  * \param[in] comm is the process communicator
197  * \param[in] metric is the metric to be compared to a reference metric
198  * \param[in] ref_metric is the reference metric for comparison
199  * \param[in] metricPlist is the parameter list defining the metric tolerances
200  * \param[out] msg is a returned pass/fail message
201  *
202  * \return boolean value indicated pass/fail status
203  */
204  static bool
205  metricComparisonTest(const RCP<const Comm<int> > &comm,
206  const MetricAnalyzerInfo & metric,
207  const MetricAnalyzerInfo &ref_metric,
208  const Teuchos::ParameterList & metricPlist,
209  ostringstream &msg);
210 
211  /* \brief Method that compares two timers and returns a pass/fail message.
212  * \param[in] comm is the process communicator
213  * \param[in] time is the timer data to be compared to a reference metric
214  * \param[in] ref_time is the reference timer for comparison
215  * \param[in] metricPlist is the parameter list defining the timer tolerances
216  * \param[out] msg is a returned pass/fail message
217  *
218  * \return boolean value indicated pass/fail status
219  */
220  static bool
221  timerComparisonTest(const RCP<const Comm<int> > &comm,
222  const double time,
223  const double ref_time,
224  const Teuchos::ParameterList & metricPlist,
225  ostringstream &msg);
226 
227  /* \brief Method for inserting data from all timers to a map of clocked times
228  * param[in] timers a map of timers
229  *
230  * \return a map with clocked times from timers
231  */
232  static std::map<const string, const double>
233  timerDataToMap(const map<const std::string, RCP<Time> > &timers);
234 
235 
236  /* \brief Method for extracting all methods to compare from a parameter list
237  * param[in] plist a parameter list defining 1 or more metric/timer comparisons
238  *
239  * \return a queue of metric comparison definitions
240  */
241  static std::queue<ParameterList>
242  getMetricsToCompare(const ParameterList & pList);
243 
244  static void
245  reduceWithMessage(const RCP<const Comm<int> > &comm,
246  const std::string &msg_in,
247  int &local_status, std::ostringstream &msg);
248 
249 };
250 
251 
252 void ComparisonHelper::AddSource(const string &name,
253  RCP<ComparisonSource> source)
254 {
255  typedef std::pair<const string &, RCP<const ComparisonSource> > pair_t;
256  this->sources.insert(pair_t(name, source));
257 }
258 
259 bool ComparisonHelper::Compare(const ParameterList &pList,
260  const RCP<const Comm<int> > &comm)
261 {
262  if(pList.isParameter("A") && pList.isParameter("B")) {
263  // comparing solutions
264  string pA = pList.get<string>("A");
265  if(this->sources.find(pA) == this->sources.end())
266  {
267  cout << "\nProblem: " + pA + ", was not saved for comparison.";
268  cout << "\nThis typically indicates that an error ";
269  cout << "occurred while running the problem.";
270  cout << "\nSolution comparison FAILED." << endl;
271  return false;
272  }
273 
274  string pB = pList.get<string>("B");
275  if(this->sources.find(pB) == this->sources.end()) {
276  cout << "\nProblem: " + pB + ", was not saved for comparison.";
277  cout << "\nThis typically indicates that an error ";
278  cout << "occurred while running the problem.";
279  cout << "\nSolution comparison FAILED." << endl;
280  return false;
281  }
282 
283  bool bResult = this->CompareSolutions(pA, pB, comm);
284  return bResult;
285  }
286  else if (pList.isParameter("Problem") && pList.isParameter("Reference")) {
287  // comparing metrics/timers
288  string prb = pList.get<string>("Problem");
289  if(this->sources.find(prb) == this->sources.end()) {
290  cout << "\nProblem: " + prb + ", was not saved for comparison.";
291  cout << "\nThis typically indicates that an error ";
292  cout << "occurred while running the problem.";
293  cout << "\nMetric comparison FAILED." << endl;
294  return false;
295  }
296 
297  string ref = pList.get<string>("Reference");
298  if(this->sources.find(ref) == this->sources.end()) {
299  cout << "\nReference: " + ref + ", was not saved for comparison.";
300  cout << "\nThis typically indicates that an error ";
301  cout << "occurred while running the problem.";
302  cout << "\nMetric comparison FAILED." << endl;
303  return false;
304  }
305 
306  bool bResult = this->CompareMetrics(pList, comm);
307  return bResult;
308  }
309  else if (pList.isParameter("A") || pList.isParameter("B"))
310  {
311  if(comm->getRank() == 0)
312  {
313  cout << "Problem A or Problem B is not specified -- check input.";
314  cout <<"\nSolution comparison FAILED." << endl;
315  }
316  }
317  else if (pList.isParameter("Problem") || pList.isParameter("Reference")) {
318  if(comm->getRank() == 0) {
319  cout << "Problem or reference is not specified -- check input.";
320  cout <<"\nMetric comparison FAILED." << endl;
321  }
322  }
323  else {
324  if (comm->getRank() == 0) {
325  cout << "ComparisonHelper did not understand how to read the xml. ";
326  cout << "Test FAILED." << endl;
327  }
328  }
329  return false;
330 }
331 
332 bool ComparisonHelper::CompareSolutions(const string &p1,
333  const string &p2,
334  const RCP<const Comm<int> > &comm)
335 {
336  if(comm->getRank() == 0) printf( "\nComparing: %s and %s\n",
337  p1.c_str(), p2.c_str());
338  auto A = this->sources[p1];
339  auto B = this->sources[p2];
340  if(A->problemFactory->getProblemName() != B->problemFactory->getProblemName()) {
341  cout << "Problem A and B are of a different kind and cannot be compared.";
342  cout <<"\nSolution comparison FAILED." << endl;
343  }
344  else {
345  if(A->problemFactory->getProblemName() == "partitioning") {
346  return this->ComparePartitionSolutions(A.getRawPtr(), B.getRawPtr(), comm);
347  }
348  else if(A->problemFactory->getProblemName() == "coloring") {
349  return this->CompareColoringSolutions(A.getRawPtr(), B.getRawPtr(), comm);
350  }
351  else if(A->problemFactory->getProblemName() == "ordering"){
352  return this->CompareOrderingSolutions(A.getRawPtr(), B.getRawPtr(), comm);
353  }
354  else {
355  cout << "Problem kind: " << A->problemFactory->getProblemName() <<
356  " not recognized. Check spelling.";
357  cout <<"\nSolution comparison FAILED." << endl;
358  }
359  }
360  return false;
361 }
362 
363 void ComparisonHelper::reduceWithMessage(const RCP<const Comm<int> > &comm,
364  const std::string &msg_in,
365  int &local_status,
366  std::ostringstream &msg) {
367  comm->barrier();
368  int global_buff;
369  Teuchos::Ptr<int> global(&global_buff);
370  reduceAll<int,int>(*comm.get(), Teuchos::EReductionType::REDUCE_MAX,
371  local_status , global);
372  local_status = *global;
373  if (local_status == 1) {
374  msg << msg_in;
375  }
376 }
377 
378 const zpart_t * ComparisonHelper::getPartListView(
379  RCP<ProblemFactory> problemFactory) const {
380  #define GET_PROBLEM_PARTS(adapterClass) \
381  return (rcp_dynamic_cast<PartitioningProblem<adapterClass>>( \
382  problemFactory->getProblem()))->getSolution().getPartListView();
383  Z2_TEST_UPCAST(problemFactory->getAdapterType(), GET_PROBLEM_PARTS)
384 }
385 
386 bool ComparisonHelper::ComparePartitionSolutions(const ComparisonSource * sourceA,
387  const ComparisonSource * sourceB,
388  const RCP<const Comm<int> > &comm)
389 {
390  int rank = comm->getRank();
391  ostringstream status;
392  int failed = 0;
393 
394  if(sourceA->adapterFactory->getMainAdapter()->getLocalNumIDs()
395  != sourceB->adapterFactory->getMainAdapter()->getLocalNumIDs()) {
396  failed = 1;
397  }
398 
399  ComparisonHelper::reduceWithMessage(comm,
400  "Number of parts in Solution A != Solution B. \
401  Partitioning solution comparison FAILED.",
402  failed, status);
403 
404  if (!failed) {
405  for(size_t i = 0;
406  i < sourceA->adapterFactory->getMainAdapter()->getLocalNumIDs(); i++) {
407  if(!failed && getPartListView(sourceA->problemFactory)[i] !=
408  getPartListView(sourceB->problemFactory)[i]) {
409  failed = 1;
410  ComparisonHelper::reduceWithMessage(comm,
411  "Solution sets A and B have different values for getPartListView(). "
412  "Solution comparison FAILED.", failed, status);
413  }
414  }
415  }
416 
417  if(!failed) {
418  status << "Solution sets A and B are the same. ";
419  status << "Solution set comparison PASSED.";
420  }
421 
422  if(rank == 0) {
423  cout << status.str() << endl;
424  }
425  return (failed == 0);
426 }
427 
428 
429 bool ComparisonHelper::CompareColoringSolutions(const ComparisonSource * sourceA,
430  const ComparisonSource * sourceB,
431  const RCP<const Comm<int> > &comm)
432 {
433  int rank = comm->getRank();
434  ostringstream status;
435  int failed = 0;
436 
437  // TO DO - implement coloring comparison
438  /*
439  if(sourceA->problemFactory->getNumColors()
440  != sourceB->problemFactory->getNumColors()) {
441  failed = 1;
442  }
443 
444  ComparisonHelper::reduceWithMessage(comm,
445  "Number of colors for Solution A != Solution B. \
446  Coloring solution comparison FAILED.",
447  failed, status);
448 
449  if (!failed) {
450  if(sourceA->problemFactory->getColorsSize()
451  != sourceB->problemFactory->getColorsSize()) {
452  failed = 1;
453  }
454  ComparisonHelper::reduceWithMessage(comm,
455  "Size of colors array for Solution A != Solution B. \
456  Coloring solution comparison FAILED.",
457  failed,
458  status);
459  }
460 
461  if (!failed) {
462  for(size_t i = 0; i < sourceA->problemFactory->getColorsSize(); i++) {
463  if (sourceA->problemFactory->getColors()[i] !=
464  sourceB->problemFactory->getColors()[i]) {
465  failed = 1; // fail
466  }
467  }
468  ComparisonHelper::reduceWithMessage(comm,
469  "Coloring solution comparison FAILED.",
470  failed,
471  status);
472  }
473  */
474 
475  if (!failed) {
476  status << "Solution sets A and B are the same. ";
477  status << "Solution set comparison PASSED.";
478  }
479 
480  if (rank == 0) {
481  cout << status.str() << endl;
482  }
483  return (failed == 0);
484 }
485 
486 bool ComparisonHelper::CompareOrderingSolutions(const ComparisonSource * sourceA,
487  const ComparisonSource * sourceB,
488  const RCP<const Comm<int> > &comm)
489 {
490  int rank = comm->getRank();
491  ostringstream status;
492  int failed = 0;
493 
494  // TO DO - implement ordering comparison
495 
496  if(!failed) {
497  status << "Solution sets A and B are the same. ";
498  status << "Solution set comparison PASSED.";
499  }
500 
501  if(rank == 0) {
502  cout << status.str() << endl;
503  }
504  return (failed == 0);
505 }
506 
507 // Utility function for safe type conversion of adapter
508 void ComparisonHelper::loadMetricInfo(RCP<EvaluateFactory> evaluateFactory,
509  std::vector<MetricAnalyzerInfo> & metricInfo,
510  const ParameterList &metricsPlist) {
511 
512  #define LOAD_METRIC_INFO(adapterClass, metricAnalyzerClass) \
513  RCP<EvaluateBaseClass<adapterClass>> pCast = \
514  rcp_dynamic_cast<EvaluateBaseClass<adapterClass>>(evaluateFactory->getEvaluateClass()); \
515  if(pCast == Teuchos::null) throw std::logic_error( \
516  "Bad evaluate class cast in loadMetricInfo!" ); \
517  metricAnalyzerClass analyzer(pCast); \
518  analyzer.LoadMetricInfo(metricInfo, metricsPlist.sublist("Metrics"));
519 
520  #define LOAD_METRIC_INFO_PARTITIONING(adapterClass) \
521  LOAD_METRIC_INFO(adapterClass, MetricAnalyzerEvaluatePartition<adapterClass>)
522 
523  #define LOAD_METRIC_INFO_ORDERING(adapterClass) \
524  LOAD_METRIC_INFO(adapterClass, MetricAnalyzerEvaluateOrdering<adapterClass>)
525 
526  if(evaluateFactory->getProblemName() == "partitioning") {
527  Z2_TEST_UPCAST(evaluateFactory->getAdapterType(), LOAD_METRIC_INFO_PARTITIONING)
528  }
529  else if(evaluateFactory->getProblemName() == "ordering") {
530  Z2_TEST_UPCAST(evaluateFactory->getAdapterType(), LOAD_METRIC_INFO_ORDERING)
531  }
532  else {
533  throw std::logic_error(
534  "loadMetricInfo not implemented for this problem type!" );
535  }
536 }
537 
538 // compare metrics
539 bool ComparisonHelper::CompareMetrics(const ParameterList &metricsPlist, const RCP<const Comm<int> > &comm)
540 {
541  int rank = comm->getRank();
542 
543  //get sources for problema nd reference
544  const string prb_name = metricsPlist.get<string>("Problem");
545  const string ref_name = metricsPlist.get<string>("Reference");
546  if(rank == 0) {
547  cout << "\nMetric/Timer comparison of: " << prb_name << " and ";
548  cout << ref_name <<" (reference source)\n";
549  }
550 
551  // get sources
552  RCP<const ComparisonSource> sourcePrb = this->sources[prb_name];
553  RCP<const ComparisonSource> sourceRef = this->sources[ref_name];
554 
555  // get timing data
556  std::map< const string, const double> prb_timers = this->timerDataToMap(sourcePrb->timers);
557  std::map< const string, const double> ref_timers = this->timerDataToMap(sourceRef->timers);
558 
559  // get all of the metrics to be tested
560  std::queue<ParameterList> metrics = ComparisonHelper::getMetricsToCompare(metricsPlist);
561 
562  // run comparison
563  int all_tests_pass = 1;
564  string metric_name;
565 
566  while(!metrics.empty()) {
567  // print their names...
568  ostringstream msg;
569  metric_name = metrics.front().name();
570 
571  if (metric_name == "Metrics") { // special key word means compare the metrics list
572  std::vector<MetricAnalyzerInfo> metricInfoSetPrb;
573  std::vector<MetricAnalyzerInfo> metricInfoSetRef;
574 
575  loadMetricInfo(sourcePrb.get()->evaluateFactory, metricInfoSetPrb, metricsPlist);
576  loadMetricInfo(sourceRef.get()->evaluateFactory, metricInfoSetRef, metricsPlist);
577 
578  // there is some redundancy here because the metric info holds both the questions and the results
579  // this happened because I wanted to reuse the MetricAnalyzer code for loading metric checks or comparisons
580  // we can iterate over either to get the questions
581  for (size_t n = 0; n < metricInfoSetPrb.size(); ++n) {
582  if(!ComparisonHelper::metricComparisonTest(comm, metricInfoSetPrb[n], metricInfoSetRef[n], metrics.front(), msg)) {
583  all_tests_pass = 0;
584  }
585  if(rank == 0) {
586  cout << msg.str() << endl;
587  }
588  }
589  }
590  else if(prb_timers.find(metric_name) != prb_timers.end() && ref_timers.find(metric_name) != ref_timers.end()) {
591  if(rank == 0) cout << "\ncomparing timer: " << metric_name << endl;
592  if(!ComparisonHelper::timerComparisonTest(comm,
593  prb_timers.at(metric_name),
594  ref_timers.at(metric_name),
595  metrics.front(), msg)) {
596  all_tests_pass = 0;
597  if (rank == 0) {
598  cout << "timer comparison test caused a FAILED event." << endl;
599  }
600  }
601 
602  if(rank == 0) {
603  cout << msg.str() << endl;
604  }
605  }
606 
607  metrics.pop();
608  }
609 
610  if(rank == 0) {
611  if(all_tests_pass == 1) {
612  cout << "\nAll metric/timer comparisons PASSED." << endl;
613  }
614  else {
615  cout << "\nMetric/timer metric comparisons FAILED." << endl;
616  }
617  }
618 
619  return (all_tests_pass == 1);
620 }
621 
622 std::map<const string, const double> ComparisonHelper::timerDataToMap(const map<const std::string, RCP<Time> > &timers)
623 {
624  typedef std::pair<const string,const double> pair_t;
625  std::map<const string, const double> time_data;
626  for (auto &i : timers) {
627  time_data.insert(pair_t(i.first, i.second->totalElapsedTime()));
628  }
629  return time_data;
630 }
631 
632 bool ComparisonHelper::metricComparisonTest(const RCP<const Comm<int> > &comm,
633  const MetricAnalyzerInfo & metric,
634  const MetricAnalyzerInfo & ref_metric,
635  const Teuchos::ParameterList & metricPlist,
636  ostringstream &msg)
637 {
638  // run a comparison of min and max against a given metric
639  // return an error message on failure
640  bool pass = true;
641  string test_name = metricPlist.name() + " test";
642  double ref_value = ref_metric.theValue;
643  double value = metric.theValue;
644 
645  if (ref_value == 0) {
646  throw std::logic_error( "The parameter list had a 0 value for the reference value so a percentage cannot be calculated." );
647  }
648  double percentRatio = value / ref_value;
649 
650  // want to reduce value to max value for all procs
651 
652  if (ref_metric.bFoundLowerBound) {
653  double min = ref_metric.lowerValue;
654  if (percentRatio < min) {
655  msg << test_name << " FAILED: " << ref_metric.parameterDescription << ": " << value << " is " << percentRatio << " percent of the reference value " << ref_value << ", which less than specified allowable minimum percent, " << min << ".\n";
656  pass = false;
657  }
658  else {
659  msg << test_name << " PASSED: " << ref_metric.parameterDescription << ": " << value << " is " << percentRatio << " percent of the reference value " << ref_value << ", which is greater than specified allowable minimum percent, " << min << ".\n";
660  }
661  }
662 
663  if (ref_metric.bFoundUpperBound) {
664  double max = ref_metric.upperValue;
665  if (percentRatio > max) {
666  msg << test_name << " FAILED: " << ref_metric.parameterDescription << ": " << value << " is " << percentRatio << " percent of the reference value " << ref_value << ", which is greater than specified allowable maximum percent, " << max << ".\n";
667  pass = false;
668  }
669  else {
670  msg << test_name << " PASSED: " << ref_metric.parameterDescription << ": " << value << " is " << percentRatio << " percent of the reference value " << ref_value << ", which is less than specified allowable maximum percent, " << max << ".\n";
671  }
672  }
673 
674  return pass;
675 }
676 // BDD, to do: print metrics even for pass
677 // reduce max metric to process 0
678 // print only on process 0 --- duh.
679 bool ComparisonHelper::timerComparisonTest(const RCP<const Comm<int> > &comm,
680  const double time,
681  const double ref_time,
682  const Teuchos::ParameterList & metricPlist,
683  ostringstream &msg)
684 {
685  // Reduce time from test
686  double global_time;
687  Teuchos::Ptr<double> global(&global_time);
688  comm->barrier();
689  reduceAll<int, double>(*comm.get(),Teuchos::EReductionType::REDUCE_MAX,time,global);
690 
691  // Reduce time from reference
692  double global_ref_time;
693  Teuchos::Ptr<double> globalRef(&global_ref_time);
694  comm->barrier();
695  reduceAll<int, double>(*comm.get(),Teuchos::EReductionType::REDUCE_MAX,ref_time,globalRef);
696 
697  // run a comparison of min and max against a given metric
698  // return an error message on failure
699  bool pass = true;
700  string test_name = metricPlist.name() + " test";
701 
702  if (metricPlist.isParameter("lower")) {
703  double min = metricPlist.get<double>("lower")*global_ref_time;
704 
705  if (global_time < min) {
706  msg << test_name << " FAILED: Minimum time, "
707  << time <<
708  "[s], less than specified allowable minimum time, " << min <<"[s]"<< ".\n";
709  pass = false;
710  }
711  else {
712  msg << test_name << " PASSED: Minimum time, "
713  << time <<
714  "[s], greater than specified allowable minimum time, " << min <<"[s]"<< ".\n";
715  }
716  }
717 
718  if (metricPlist.isParameter("upper" ) && pass != false) {
719  double max = metricPlist.get<double>("upper") * global_ref_time;
720  if (global_time > max) {
721  msg << test_name << " FAILED: Maximum time, "
722  << global_time <<
723  "[s], greater than specified allowable maximum time, " << max <<"[s]"<< ".\n";
724  pass = false;
725  }
726  else {
727  msg << test_name << " PASSED: Maximum time, "
728  << global_time <<
729  "[s], less than specified allowable maximum time, " << max <<"[s]"<< ".\n";
730  }
731  }
732 
733  return pass;
734 }
735 
736 std::queue<ParameterList> ComparisonHelper::getMetricsToCompare(const ParameterList &pList)
737 {
738  // extract all of the metrics to be tested
739  std::queue<ParameterList> metrics;
740  for(auto it = pList.begin(); it != pList.end(); ++it) {
741  if (pList.isSublist(it->first)) {
742  metrics.push(pList.sublist(it->first));
743  }
744  }
745  return metrics;
746 }
747 
keep typedefs that commonly appear in many places localized
Returns a pointer to new test classes. Is not responsible for memory management!
void AddSource(const string &name, RCP< ComparisonSource > source)
RCP< ProblemFactory > problemFactory
common code used by tests
#define LOAD_METRIC_INFO_ORDERING(adapterClass)
bool Compare(const ParameterList &pList, const RCP< const Comm< int > > &comm)
int zpart_t
#define Z2_TEST_UPCAST(adptr, TEMPLATE_ACTION)
#define LOAD_METRIC_INFO_PARTITIONING(adapterClass)
RCP< EvaluateFactory > evaluateFactory
A class for comparing solutions, metrics, and timing data of Zoltan2 problems.
std::map< const std::string, RCP< Time > > timers
static const std::string pass
A class used to save problem solutions and timers.
void addTimer(const std::string &name)
Generate Adapter for testing purposes.
RCP< AdapterFactory > adapterFactory
#define GET_PROBLEM_PARTS(adapterClass)