58 #include <Teuchos_DefaultComm.hpp>
59 #include <Teuchos_Time.hpp>
68 using Teuchos::ParameterList;
73 using Teuchos::reduceAll;
74 using namespace Zoltan2_TestingFramework;
87 timers.insert(std::pair<
const std::string &, RCP<Time> >(name,rcp(
new Time(name))));
88 timers[name]->enable();
93 for(
auto it = timers.begin(); it != timers.end(); ++it) {
94 std::cout << it->first <<
" " << it->second->totalElapsedTime()
101 std::map<const std::string, RCP<Time> >
timers;
117 bool Compare(
const ParameterList &pList,
const RCP<
const Comm<int> > &comm);
123 void AddSource(
const string &name, RCP<ComparisonSource> source);
129 return this->sources.size();
133 map<const string,RCP<const ComparisonSource> > sources;
140 bool CompareSolutions(
const string &p1,
142 const RCP<
const Comm<int> > &comm);
147 const zpart_t * getPartListView(RCP<ProblemFactory> problemFactory)
const;
156 const RCP<
const Comm<int> > &comm);
165 const RCP<
const Comm<int> > &comm);
174 const RCP<
const Comm<int> > &comm);
181 void loadMetricInfo(RCP<EvaluateFactory> problemFactory,
182 std::vector<MetricAnalyzerInfo> & metricInfo,
183 const ParameterList &metricsPlist);
189 bool CompareMetrics(
const ParameterList &metricsPlist,
190 const RCP<
const Comm<int> > &comm);
202 metricComparisonTest(
const RCP<
const Comm<int> > &comm,
205 const Teuchos::ParameterList & metricPlist,
206 std::ostringstream &msg);
218 timerComparisonTest(
const RCP<
const Comm<int> > &comm,
220 const double ref_time,
221 const Teuchos::ParameterList & metricPlist,
222 std::ostringstream &msg);
229 static std::map<const string, const double>
230 timerDataToMap(
const map<
const std::string, RCP<Time> > &timers);
238 static std::queue<ParameterList>
239 getMetricsToCompare(
const ParameterList & pList);
242 reduceWithMessage(
const RCP<
const Comm<int> > &comm,
243 const std::string &msg_in,
244 int &local_status, std::ostringstream &msg);
250 RCP<ComparisonSource> source)
252 typedef std::pair<const string &, RCP<const ComparisonSource> > pair_t;
253 this->sources.insert(pair_t(name, source));
257 const RCP<
const Comm<int> > &comm)
259 if(pList.isParameter(
"A") && pList.isParameter(
"B")) {
261 string pA = pList.get<
string>(
"A");
262 if(this->sources.find(pA) == this->sources.end())
264 std::cout <<
"\nProblem: " + pA +
", was not saved for comparison.";
265 std::cout <<
"\nThis typically indicates that an error ";
266 std::cout <<
"occurred while running the problem.";
267 std::cout <<
"\nSolution comparison FAILED." << std::endl;
271 string pB = pList.get<
string>(
"B");
272 if(this->sources.find(pB) == this->sources.end()) {
273 std::cout <<
"\nProblem: " + pB +
", was not saved for comparison.";
274 std::cout <<
"\nThis typically indicates that an error ";
275 std::cout <<
"occurred while running the problem.";
276 std::cout <<
"\nSolution comparison FAILED." << std::endl;
280 bool bResult = this->CompareSolutions(pA, pB, comm);
283 else if (pList.isParameter(
"Problem") && pList.isParameter(
"Reference")) {
285 string prb = pList.get<
string>(
"Problem");
286 if(this->sources.find(prb) == this->sources.end()) {
287 std::cout <<
"\nProblem: " + prb +
", was not saved for comparison.";
288 std::cout <<
"\nThis typically indicates that an error ";
289 std::cout <<
"occurred while running the problem.";
290 std::cout <<
"\nMetric comparison FAILED." << std::endl;
294 string ref = pList.get<
string>(
"Reference");
295 if(this->sources.find(ref) == this->sources.end()) {
296 std::cout <<
"\nReference: " + ref +
", was not saved for comparison.";
297 std::cout <<
"\nThis typically indicates that an error ";
298 std::cout <<
"occurred while running the problem.";
299 std::cout <<
"\nMetric comparison FAILED." << std::endl;
303 bool bResult = this->CompareMetrics(pList, comm);
306 else if (pList.isParameter(
"A") || pList.isParameter(
"B"))
308 if(comm->getRank() == 0)
310 std::cout <<
"Problem A or Problem B is not specified -- check input.";
311 std::cout <<
"\nSolution comparison FAILED." << std::endl;
314 else if (pList.isParameter(
"Problem") || pList.isParameter(
"Reference")) {
315 if(comm->getRank() == 0) {
316 std::cout <<
"Problem or reference is not specified -- check input.";
317 std::cout <<
"\nMetric comparison FAILED." << std::endl;
321 if (comm->getRank() == 0) {
322 std::cout <<
"ComparisonHelper did not understand how to read the xml. ";
323 std::cout <<
"Test FAILED." << std::endl;
329 bool ComparisonHelper::CompareSolutions(
const string &p1,
331 const RCP<
const Comm<int> > &comm)
333 if(comm->getRank() == 0) printf(
"\nComparing: %s and %s\n",
334 p1.c_str(), p2.c_str());
335 auto A = this->sources[p1];
336 auto B = this->sources[p2];
337 if(A->problemFactory->getProblemName() != B->problemFactory->getProblemName()) {
338 std::cout <<
"Problem A and B are of a different kind and cannot be compared.";
339 std::cout <<
"\nSolution comparison FAILED." << std::endl;
342 if(A->problemFactory->getProblemName() ==
"partitioning") {
343 return this->ComparePartitionSolutions(A.getRawPtr(), B.getRawPtr(), comm);
345 else if(A->problemFactory->getProblemName() ==
"coloring") {
346 return this->CompareColoringSolutions(A.getRawPtr(), B.getRawPtr(), comm);
348 else if(A->problemFactory->getProblemName() ==
"ordering"){
349 return this->CompareOrderingSolutions(A.getRawPtr(), B.getRawPtr(), comm);
352 std::cout <<
"Problem kind: " << A->problemFactory->getProblemName() <<
353 " not recognized. Check spelling.";
354 std::cout <<
"\nSolution comparison FAILED." << std::endl;
360 void ComparisonHelper::reduceWithMessage(
const RCP<
const Comm<int> > &comm,
361 const std::string &msg_in,
363 std::ostringstream &msg) {
366 Teuchos::Ptr<int> global(&global_buff);
367 reduceAll<int,int>(*comm.get(), Teuchos::EReductionType::REDUCE_MAX,
368 local_status , global);
369 local_status = *global;
370 if (local_status == 1) {
375 const zpart_t * ComparisonHelper::getPartListView(
376 RCP<ProblemFactory> problemFactory)
const {
377 #define GET_PROBLEM_PARTS(adapterClass) \
378 return (rcp_dynamic_cast<PartitioningProblem<adapterClass>>( \
379 problemFactory->getProblem()))->getSolution().getPartListView();
383 bool ComparisonHelper::ComparePartitionSolutions(
const ComparisonSource * sourceA,
385 const RCP<
const Comm<int> > &comm)
387 int rank = comm->getRank();
388 std::ostringstream status;
396 ComparisonHelper::reduceWithMessage(comm,
397 "Number of parts in Solution A != Solution B. \
398 Partitioning solution comparison FAILED.",
403 i < sourceA->
adapterFactory->getMainAdapter()->getLocalNumIDs(); i++) {
407 ComparisonHelper::reduceWithMessage(comm,
408 "Solution sets A and B have different values for getPartListView(). "
409 "Solution comparison FAILED.", failed, status);
415 status <<
"Solution sets A and B are the same. ";
416 status <<
"Solution set comparison PASSED.";
420 std::cout << status.str() << std::endl;
422 return (failed == 0);
426 bool ComparisonHelper::CompareColoringSolutions(
const ComparisonSource * sourceA,
428 const RCP<
const Comm<int> > &comm)
430 int rank = comm->getRank();
431 std::ostringstream status;
473 status <<
"Solution sets A and B are the same. ";
474 status <<
"Solution set comparison PASSED.";
478 std::cout << status.str() << std::endl;
480 return (failed == 0);
483 bool ComparisonHelper::CompareOrderingSolutions(
const ComparisonSource * sourceA,
485 const RCP<
const Comm<int> > &comm)
487 int rank = comm->getRank();
488 std::ostringstream status;
494 status <<
"Solution sets A and B are the same. ";
495 status <<
"Solution set comparison PASSED.";
499 std::cout << status.str() << std::endl;
501 return (failed == 0);
505 void ComparisonHelper::loadMetricInfo(RCP<EvaluateFactory> evaluateFactory,
506 std::vector<MetricAnalyzerInfo> & metricInfo,
507 const ParameterList &metricsPlist) {
509 #define LOAD_METRIC_INFO(adapterClass, metricAnalyzerClass) \
510 RCP<EvaluateBaseClass<adapterClass>> pCast = \
511 rcp_dynamic_cast<EvaluateBaseClass<adapterClass>>(evaluateFactory->getEvaluateClass()); \
512 if(pCast == Teuchos::null) throw std::logic_error( \
513 "Bad evaluate class cast in loadMetricInfo!" ); \
514 metricAnalyzerClass analyzer(pCast); \
515 analyzer.LoadMetricInfo(metricInfo, metricsPlist.sublist("Metrics"));
517 #define LOAD_METRIC_INFO_PARTITIONING(adapterClass) \
518 LOAD_METRIC_INFO(adapterClass, MetricAnalyzerEvaluatePartition<adapterClass>)
520 #define LOAD_METRIC_INFO_ORDERING(adapterClass) \
521 LOAD_METRIC_INFO(adapterClass, MetricAnalyzerEvaluateOrdering<adapterClass>)
523 if(evaluateFactory->getProblemName() ==
"partitioning") {
526 else if(evaluateFactory->getProblemName() ==
"ordering") {
530 throw std::logic_error(
531 "loadMetricInfo not implemented for this problem type!" );
536 bool ComparisonHelper::CompareMetrics(
const ParameterList &metricsPlist,
const RCP<
const Comm<int> > &comm)
538 int rank = comm->getRank();
541 const string prb_name = metricsPlist.get<
string>(
"Problem");
542 const string ref_name = metricsPlist.get<
string>(
"Reference");
544 std::cout <<
"\nMetric/Timer comparison of: " << prb_name <<
" and ";
545 std::cout << ref_name <<
" (reference source)\n";
549 RCP<const ComparisonSource> sourcePrb = this->sources[prb_name];
550 RCP<const ComparisonSource> sourceRef = this->sources[ref_name];
553 std::map< const string, const double> prb_timers = this->timerDataToMap(sourcePrb->timers);
554 std::map< const string, const double> ref_timers = this->timerDataToMap(sourceRef->timers);
557 std::queue<ParameterList> metrics = ComparisonHelper::getMetricsToCompare(metricsPlist);
560 int all_tests_pass = 1;
563 while(!metrics.empty()) {
565 std::ostringstream msg;
566 metric_name = metrics.front().name();
568 if (metric_name ==
"Metrics") {
569 std::vector<MetricAnalyzerInfo> metricInfoSetPrb;
570 std::vector<MetricAnalyzerInfo> metricInfoSetRef;
572 loadMetricInfo(sourcePrb.get()->evaluateFactory, metricInfoSetPrb, metricsPlist);
573 loadMetricInfo(sourceRef.get()->evaluateFactory, metricInfoSetRef, metricsPlist);
578 for (
size_t n = 0; n < metricInfoSetPrb.size(); ++n) {
579 if(!ComparisonHelper::metricComparisonTest(comm, metricInfoSetPrb[n], metricInfoSetRef[n], metrics.front(), msg)) {
583 std::cout << msg.str() << std::endl;
587 else if(prb_timers.find(metric_name) != prb_timers.end() && ref_timers.find(metric_name) != ref_timers.end()) {
588 if(rank == 0) std::cout <<
"\ncomparing timer: " << metric_name << std::endl;
589 if(!ComparisonHelper::timerComparisonTest(comm,
590 prb_timers.at(metric_name),
591 ref_timers.at(metric_name),
592 metrics.front(), msg)) {
595 std::cout <<
"timer comparison test caused a FAILED event." << std::endl;
600 std::cout << msg.str() << std::endl;
608 if(all_tests_pass == 1) {
609 std::cout <<
"\nAll metric/timer comparisons PASSED." << std::endl;
612 std::cout <<
"\nMetric/timer metric comparisons FAILED." << std::endl;
616 return (all_tests_pass == 1);
619 std::map<const string, const double> ComparisonHelper::timerDataToMap(
const map<
const std::string, RCP<Time> > &timers)
621 typedef std::pair<const string,const double> pair_t;
622 std::map<const string, const double> time_data;
623 for (
auto &i : timers) {
624 time_data.insert(pair_t(i.first, i.second->totalElapsedTime()));
629 bool ComparisonHelper::metricComparisonTest(
const RCP<
const Comm<int> > &comm,
632 const Teuchos::ParameterList & metricPlist,
633 std::ostringstream &msg)
638 string test_name = metricPlist.name() +
" test";
639 double ref_value = ref_metric.
theValue;
642 if (ref_value == 0) {
643 throw std::logic_error(
"The parameter list had a 0 value for the reference value so a percentage cannot be calculated." );
645 double percentRatio = value / ref_value;
651 if (percentRatio < min) {
652 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 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";
662 if (percentRatio > max) {
663 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 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";
676 bool ComparisonHelper::timerComparisonTest(
const RCP<
const Comm<int> > &comm,
678 const double ref_time,
679 const Teuchos::ParameterList & metricPlist,
680 std::ostringstream &msg)
684 Teuchos::Ptr<double> global(&global_time);
686 reduceAll<int, double>(*comm.get(),Teuchos::EReductionType::REDUCE_MAX,time,global);
689 double global_ref_time;
690 Teuchos::Ptr<double> globalRef(&global_ref_time);
692 reduceAll<int, double>(*comm.get(),Teuchos::EReductionType::REDUCE_MAX,ref_time,globalRef);
697 string test_name = metricPlist.name() +
" test";
699 if (metricPlist.isParameter(
"lower")) {
700 double min = metricPlist.get<
double>(
"lower")*global_ref_time;
702 if (global_time < min) {
703 msg << test_name <<
" FAILED: Minimum time, "
705 "[s], less than specified allowable minimum time, " << min <<
"[s]"<<
".\n";
709 msg << test_name <<
" PASSED: Minimum time, "
711 "[s], greater than specified allowable minimum time, " << min <<
"[s]"<<
".\n";
715 if (metricPlist.isParameter(
"upper" ) && pass !=
false) {
716 double max = metricPlist.get<
double>(
"upper") * global_ref_time;
717 if (global_time > max) {
718 msg << test_name <<
" FAILED: Maximum time, "
720 "[s], greater than specified allowable maximum time, " << max <<
"[s]"<<
".\n";
724 msg << test_name <<
" PASSED: Maximum time, "
726 "[s], less than specified allowable maximum time, " << max <<
"[s]"<<
".\n";
733 std::queue<ParameterList> ComparisonHelper::getMetricsToCompare(
const ParameterList &pList)
736 std::queue<ParameterList> metrics;
737 for(
auto it = pList.begin(); it != pList.end(); ++it) {
738 if (pList.isSublist(it->first)) {
739 metrics.push(pList.sublist(it->first));
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)
#define Z2_TEST_UPCAST(adptr, TEMPLATE_ACTION)
#define LOAD_METRIC_INFO_PARTITIONING(adapterClass)
size_t getNumberOfSources() const
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.
std::string parameterDescription
void addTimer(const std::string &name)
Generate Adapter for testing purposes.
RCP< AdapterFactory > adapterFactory
#define GET_PROBLEM_PARTS(adapterClass)