22 #include <Teuchos_DefaultComm.hpp>
23 #include <Teuchos_Time.hpp>
32 using Teuchos::ParameterList;
37 using Teuchos::reduceAll;
38 using namespace Zoltan2_TestingFramework;
51 timers.insert(std::pair<
const std::string &, RCP<Time> >(name,rcp(
new Time(name))));
52 timers[name]->enable();
57 for(
auto it = timers.begin(); it != timers.end(); ++it) {
58 std::cout << it->first <<
" " << it->second->totalElapsedTime()
65 std::map<const std::string, RCP<Time> >
timers;
81 bool Compare(
const ParameterList &pList,
const RCP<
const Comm<int> > &comm);
87 void AddSource(
const string &name, RCP<ComparisonSource> source);
93 return this->sources.size();
97 map<const string,RCP<const ComparisonSource> > sources;
104 bool CompareSolutions(
const string &p1,
106 const RCP<
const Comm<int> > &comm);
120 const RCP<
const Comm<int> > &comm);
129 const RCP<
const Comm<int> > &comm);
138 const RCP<
const Comm<int> > &comm);
145 void loadMetricInfo(RCP<EvaluateFactory> problemFactory,
146 std::vector<MetricAnalyzerInfo> & metricInfo,
147 const ParameterList &metricsPlist);
153 bool CompareMetrics(
const ParameterList &metricsPlist,
154 const RCP<
const Comm<int> > &comm);
166 metricComparisonTest(
const RCP<
const Comm<int> > &comm,
169 const Teuchos::ParameterList & metricPlist,
170 std::ostringstream &msg);
182 timerComparisonTest(
const RCP<
const Comm<int> > &comm,
184 const double ref_time,
185 const Teuchos::ParameterList & metricPlist,
186 std::ostringstream &msg);
193 static std::map<const string, const double>
194 timerDataToMap(
const map<
const std::string, RCP<Time> > &timers);
202 static std::queue<ParameterList>
203 getMetricsToCompare(
const ParameterList & pList);
206 reduceWithMessage(
const RCP<
const Comm<int> > &comm,
207 const std::string &msg_in,
208 int &local_status, std::ostringstream &msg);
214 RCP<ComparisonSource> source)
216 typedef std::pair<const string &, RCP<const ComparisonSource> > pair_t;
217 this->sources.insert(pair_t(name, source));
221 const RCP<
const Comm<int> > &comm)
223 if(pList.isParameter(
"A") && pList.isParameter(
"B")) {
225 string pA = pList.get<
string>(
"A");
226 if(this->sources.find(pA) == this->sources.end())
228 std::cout <<
"\nProblem: " + pA +
", was not saved for comparison.";
229 std::cout <<
"\nThis typically indicates that an error ";
230 std::cout <<
"occurred while running the problem.";
231 std::cout <<
"\nSolution comparison FAILED." << std::endl;
235 string pB = pList.get<
string>(
"B");
236 if(this->sources.find(pB) == this->sources.end()) {
237 std::cout <<
"\nProblem: " + pB +
", was not saved for comparison.";
238 std::cout <<
"\nThis typically indicates that an error ";
239 std::cout <<
"occurred while running the problem.";
240 std::cout <<
"\nSolution comparison FAILED." << std::endl;
244 bool bResult = this->CompareSolutions(pA, pB, comm);
247 else if (pList.isParameter(
"Problem") && pList.isParameter(
"Reference")) {
249 string prb = pList.get<
string>(
"Problem");
250 if(this->sources.find(prb) == this->sources.end()) {
251 std::cout <<
"\nProblem: " + prb +
", was not saved for comparison.";
252 std::cout <<
"\nThis typically indicates that an error ";
253 std::cout <<
"occurred while running the problem.";
254 std::cout <<
"\nMetric comparison FAILED." << std::endl;
258 string ref = pList.get<
string>(
"Reference");
259 if(this->sources.find(ref) == this->sources.end()) {
260 std::cout <<
"\nReference: " + ref +
", was not saved for comparison.";
261 std::cout <<
"\nThis typically indicates that an error ";
262 std::cout <<
"occurred while running the problem.";
263 std::cout <<
"\nMetric comparison FAILED." << std::endl;
267 bool bResult = this->CompareMetrics(pList, comm);
270 else if (pList.isParameter(
"A") || pList.isParameter(
"B"))
272 if(comm->getRank() == 0)
274 std::cout <<
"Problem A or Problem B is not specified -- check input.";
275 std::cout <<
"\nSolution comparison FAILED." << std::endl;
278 else if (pList.isParameter(
"Problem") || pList.isParameter(
"Reference")) {
279 if(comm->getRank() == 0) {
280 std::cout <<
"Problem or reference is not specified -- check input.";
281 std::cout <<
"\nMetric comparison FAILED." << std::endl;
285 if (comm->getRank() == 0) {
286 std::cout <<
"ComparisonHelper did not understand how to read the xml. ";
287 std::cout <<
"Test FAILED." << std::endl;
293 bool ComparisonHelper::CompareSolutions(
const string &p1,
295 const RCP<
const Comm<int> > &comm)
297 if(comm->getRank() == 0) printf(
"\nComparing: %s and %s\n",
298 p1.c_str(), p2.c_str());
299 auto A = this->sources[p1];
300 auto B = this->sources[p2];
301 if(A->problemFactory->getProblemName() != B->problemFactory->getProblemName()) {
302 std::cout <<
"Problem A and B are of a different kind and cannot be compared.";
303 std::cout <<
"\nSolution comparison FAILED." << std::endl;
306 if(A->problemFactory->getProblemName() ==
"partitioning") {
307 return this->ComparePartitionSolutions(A.getRawPtr(), B.getRawPtr(), comm);
309 else if(A->problemFactory->getProblemName() ==
"coloring") {
310 return this->CompareColoringSolutions(A.getRawPtr(), B.getRawPtr(), comm);
312 else if(A->problemFactory->getProblemName() ==
"ordering"){
313 return this->CompareOrderingSolutions(A.getRawPtr(), B.getRawPtr(), comm);
316 std::cout <<
"Problem kind: " << A->problemFactory->getProblemName() <<
317 " not recognized. Check spelling.";
318 std::cout <<
"\nSolution comparison FAILED." << std::endl;
324 void ComparisonHelper::reduceWithMessage(
const RCP<
const Comm<int> > &comm,
325 const std::string &msg_in,
327 std::ostringstream &msg) {
330 Teuchos::Ptr<int> global(&global_buff);
331 reduceAll<int,int>(*comm.get(), Teuchos::EReductionType::REDUCE_MAX,
332 local_status , global);
333 local_status = *global;
334 if (local_status == 1) {
339 const zpart_t * ComparisonHelper::getPartListView(
340 RCP<ProblemFactory> problemFactory)
const {
341 #define GET_PROBLEM_PARTS(adapterClass) \
342 return (rcp_dynamic_cast<PartitioningProblem<adapterClass>>( \
343 problemFactory->getProblem()))->getSolution().getPartListView();
347 bool ComparisonHelper::ComparePartitionSolutions(
const ComparisonSource * sourceA,
349 const RCP<
const Comm<int> > &comm)
351 int rank = comm->getRank();
352 std::ostringstream status;
360 ComparisonHelper::reduceWithMessage(comm,
361 "Number of parts in Solution A != Solution B. \
362 Partitioning solution comparison FAILED.",
367 i < sourceA->
adapterFactory->getMainAdapter()->getLocalNumIDs(); i++) {
371 ComparisonHelper::reduceWithMessage(comm,
372 "Solution sets A and B have different values for getPartListView(). "
373 "Solution comparison FAILED.", failed, status);
379 status <<
"Solution sets A and B are the same. ";
380 status <<
"Solution set comparison PASSED.";
384 std::cout << status.str() << std::endl;
386 return (failed == 0);
390 bool ComparisonHelper::CompareColoringSolutions(
const ComparisonSource * sourceA,
392 const RCP<
const Comm<int> > &comm)
394 int rank = comm->getRank();
395 std::ostringstream status;
437 status <<
"Solution sets A and B are the same. ";
438 status <<
"Solution set comparison PASSED.";
442 std::cout << status.str() << std::endl;
444 return (failed == 0);
447 bool ComparisonHelper::CompareOrderingSolutions(
const ComparisonSource * sourceA,
449 const RCP<
const Comm<int> > &comm)
451 int rank = comm->getRank();
452 std::ostringstream status;
458 status <<
"Solution sets A and B are the same. ";
459 status <<
"Solution set comparison PASSED.";
463 std::cout << status.str() << std::endl;
465 return (failed == 0);
469 void ComparisonHelper::loadMetricInfo(RCP<EvaluateFactory> evaluateFactory,
470 std::vector<MetricAnalyzerInfo> & metricInfo,
471 const ParameterList &metricsPlist) {
473 #define LOAD_METRIC_INFO(adapterClass, metricAnalyzerClass) \
474 RCP<EvaluateBaseClass<adapterClass>> pCast = \
475 rcp_dynamic_cast<EvaluateBaseClass<adapterClass>>(evaluateFactory->getEvaluateClass()); \
476 if(pCast == Teuchos::null) throw std::logic_error( \
477 "Bad evaluate class cast in loadMetricInfo!" ); \
478 metricAnalyzerClass analyzer(pCast); \
479 analyzer.LoadMetricInfo(metricInfo, metricsPlist.sublist("Metrics"));
481 #define LOAD_METRIC_INFO_PARTITIONING(adapterClass) \
482 LOAD_METRIC_INFO(adapterClass, MetricAnalyzerEvaluatePartition<adapterClass>)
484 #define LOAD_METRIC_INFO_ORDERING(adapterClass) \
485 LOAD_METRIC_INFO(adapterClass, MetricAnalyzerEvaluateOrdering<adapterClass>)
487 if(evaluateFactory->getProblemName() ==
"partitioning") {
490 else if(evaluateFactory->getProblemName() ==
"ordering") {
494 throw std::logic_error(
495 "loadMetricInfo not implemented for this problem type!" );
500 bool ComparisonHelper::CompareMetrics(
const ParameterList &metricsPlist,
const RCP<
const Comm<int> > &comm)
502 int rank = comm->getRank();
505 const string prb_name = metricsPlist.get<
string>(
"Problem");
506 const string ref_name = metricsPlist.get<
string>(
"Reference");
508 std::cout <<
"\nMetric/Timer comparison of: " << prb_name <<
" and ";
509 std::cout << ref_name <<
" (reference source)\n";
513 RCP<const ComparisonSource> sourcePrb = this->sources[prb_name];
514 RCP<const ComparisonSource> sourceRef = this->sources[ref_name];
517 std::map< const string, const double> prb_timers = this->timerDataToMap(sourcePrb->timers);
518 std::map< const string, const double> ref_timers = this->timerDataToMap(sourceRef->timers);
521 std::queue<ParameterList> metrics = ComparisonHelper::getMetricsToCompare(metricsPlist);
524 int all_tests_pass = 1;
527 while(!metrics.empty()) {
529 std::ostringstream msg;
530 metric_name = metrics.front().name();
532 if (metric_name ==
"Metrics") {
533 std::vector<MetricAnalyzerInfo> metricInfoSetPrb;
534 std::vector<MetricAnalyzerInfo> metricInfoSetRef;
536 loadMetricInfo(sourcePrb.get()->evaluateFactory, metricInfoSetPrb, metricsPlist);
537 loadMetricInfo(sourceRef.get()->evaluateFactory, metricInfoSetRef, metricsPlist);
542 for (
size_t n = 0; n < metricInfoSetPrb.size(); ++n) {
543 if(!ComparisonHelper::metricComparisonTest(comm, metricInfoSetPrb[n], metricInfoSetRef[n], metrics.front(), msg)) {
547 std::cout << msg.str() << std::endl;
551 else if(prb_timers.find(metric_name) != prb_timers.end() && ref_timers.find(metric_name) != ref_timers.end()) {
552 if(rank == 0) std::cout <<
"\ncomparing timer: " << metric_name << std::endl;
553 if(!ComparisonHelper::timerComparisonTest(comm,
554 prb_timers.at(metric_name),
555 ref_timers.at(metric_name),
556 metrics.front(), msg)) {
559 std::cout <<
"timer comparison test caused a FAILED event." << std::endl;
564 std::cout << msg.str() << std::endl;
572 if(all_tests_pass == 1) {
573 std::cout <<
"\nAll metric/timer comparisons PASSED." << std::endl;
576 std::cout <<
"\nMetric/timer metric comparisons FAILED." << std::endl;
580 return (all_tests_pass == 1);
583 std::map<const string, const double> ComparisonHelper::timerDataToMap(
const map<
const std::string, RCP<Time> > &timers)
585 typedef std::pair<const string,const double> pair_t;
586 std::map<const string, const double> time_data;
587 for (
auto &i : timers) {
588 time_data.insert(pair_t(i.first, i.second->totalElapsedTime()));
593 bool ComparisonHelper::metricComparisonTest(
const RCP<
const Comm<int> > &comm,
596 const Teuchos::ParameterList & metricPlist,
597 std::ostringstream &msg)
602 string test_name = metricPlist.name() +
" test";
603 double ref_value = ref_metric.
theValue;
606 if (ref_value == 0) {
607 throw std::logic_error(
"The parameter list had a 0 value for the reference value so a percentage cannot be calculated." );
609 double percentRatio = value / ref_value;
615 if (percentRatio < min) {
616 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";
620 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";
626 if (percentRatio > max) {
627 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";
631 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";
640 bool ComparisonHelper::timerComparisonTest(
const RCP<
const Comm<int> > &comm,
642 const double ref_time,
643 const Teuchos::ParameterList & metricPlist,
644 std::ostringstream &msg)
648 Teuchos::Ptr<double> global(&global_time);
650 reduceAll<int, double>(*comm.get(),Teuchos::EReductionType::REDUCE_MAX,time,global);
653 double global_ref_time;
654 Teuchos::Ptr<double> globalRef(&global_ref_time);
656 reduceAll<int, double>(*comm.get(),Teuchos::EReductionType::REDUCE_MAX,ref_time,globalRef);
661 string test_name = metricPlist.name() +
" test";
663 if (metricPlist.isParameter(
"lower")) {
664 double min = metricPlist.get<
double>(
"lower")*global_ref_time;
666 if (global_time < min) {
667 msg << test_name <<
" FAILED: Minimum time, "
669 "[s], less than specified allowable minimum time, " << min <<
"[s]"<<
".\n";
673 msg << test_name <<
" PASSED: Minimum time, "
675 "[s], greater than specified allowable minimum time, " << min <<
"[s]"<<
".\n";
679 if (metricPlist.isParameter(
"upper" ) && pass !=
false) {
680 double max = metricPlist.get<
double>(
"upper") * global_ref_time;
681 if (global_time > max) {
682 msg << test_name <<
" FAILED: Maximum time, "
684 "[s], greater than specified allowable maximum time, " << max <<
"[s]"<<
".\n";
688 msg << test_name <<
" PASSED: Maximum time, "
690 "[s], less than specified allowable maximum time, " << max <<
"[s]"<<
".\n";
697 std::queue<ParameterList> ComparisonHelper::getMetricsToCompare(
const ParameterList &pList)
700 std::queue<ParameterList> metrics;
701 for(
auto it = pList.begin(); it != pList.end(); ++it) {
702 if (pList.isSublist(it->first)) {
703 metrics.push(pList.sublist(it->first));
keep typedefs that commonly appear in many places localized
const zpart_t * getPartListView(RCP< ProblemFactory > problemFactory)
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)