VPTissue Reference Manual
PTreeComparison.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2016 Universiteit Antwerpen
3  *
4  * Licensed under the EUPL, Version 1.1 or as soon they will be approved by
5  * the European Commission - subsequent versions of the EUPL (the "Licence");
6  * You may not use this work except in compliance with the Licence.
7  * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl5
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the Licence is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the Licence for the specific language governing
13  * permissions and limitations under the Licence.
14  */
20 #include "PTreeComparison.h"
21 
22 #include "util/misc/Exception.h"
23 #include "util/misc/StringUtils.h"
24 
25 #include <boost/optional.hpp>
26 #include <boost/property_tree/ptree.hpp>
27 #include <boost/property_tree/xml_parser.hpp>
28 #include <boost/property_tree/exceptions.hpp>
29 #include <cmath>
30 #include <iostream>
31 #include <map>
32 #include <string>
33 
34 using namespace std;
35 using namespace boost::property_tree;
36 using namespace boost::property_tree::xml_parser;
37 using boost::optional;
38 using namespace SimPT_Sim::Util;
39 
40 namespace SimPT_Shell {
41 
42 bool PTreeComparison::CompareRootValues(ptree const& pt1, ptree const& pt2, double acceptable_diff)
43 {
44  std::string pt1_value = pt1.get_value<std::string>();
45  std::string pt2_value = pt2.get_value<std::string>();
46 
47  if (acceptable_diff > 1.0e-15) {
48  bool pt1_value_is_number = false;
49  bool pt2_value_is_number = false;
50 
51  double pt1_value_parsed = 0.0;
52  double pt2_value_parsed = 0.0;
53 
54  try {
55  pt1_value_parsed = pt1.get_value<double>();
56  pt1_value_is_number = true;
57  } catch (ptree_bad_data &) {
58  pt1_value_is_number = false;
59  }
60 
61  try {
62  pt2_value_parsed = pt2.get_value<double>();
63  pt2_value_is_number = true;
64  } catch (ptree_bad_data &) {
65  pt2_value_is_number = false;
66  }
67 
68  if (pt1_value_is_number && pt2_value_is_number) {
69  if (pt1_value.find('.') == std::string::npos
70  && pt2_value.find('.') == std::string::npos) {
71  // both values are integers => must be exactly the same
72  return pt1_value == pt2_value;
73  } else {
74  double const diff = fabs(pt2_value_parsed - pt1_value_parsed)
75  / (1.0 + fabs(pt1_value_parsed));
76  bool equal = (diff < acceptable_diff);
77  if (!equal) {
78  cout << "LeafTransformer::CompareRootValues> Diff too large: " << diff << endl;
79  }
80  return equal;
81  }
82  }
83  }
84 
85  return pt1_value == pt2_value;
86 }
87 
88 bool PTreeComparison::CompareArray(ptree const& pt1, ptree const& pt2, double acceptable_diff)
89 {
90 
91  if (!CompareRootValues(pt1, pt2, acceptable_diff)) {
92  cout << "LeafTransformer::CompareArray> Root values not equal" << endl;
93  return false;
94  }
95 
96  if (pt1.size() != pt2.size()) {
97  cout << "LeafTransformer::CompareArray> Different number of children." << endl;
98  return false;
99  }
100 
101  auto pt1_child_entry = pt1.begin();
102  auto pt2_child_entry = pt2.begin();
103  while (pt1_child_entry != pt1.end() && pt2_child_entry != pt2.end()) {
104  if (pt1_child_entry->first != pt2_child_entry->first) {
105  cout << "LeafTransformer::CompareArray> Array elements have different keys." << endl;
106  return false;
107  }
108 
109  if (pt1_child_entry->first.rfind("_array") == pt1_child_entry->first.length()-6) {
110  if (!CompareArray(pt1_child_entry->second, pt2_child_entry->second, acceptable_diff)) {
111  return false;
112  }
113  } else {
114  if (!CompareNonArray(pt1_child_entry->second, pt2_child_entry->second, acceptable_diff)) {
115  cout << "LeafTransformer::CompareNonArray> Subtree: " << pt1_child_entry->first << endl;
116  return false;
117  }
118  }
119 
120  pt1_child_entry++;
121  pt2_child_entry++;
122  }
123  return true;
124 }
125 
126 bool PTreeComparison::CompareNonArray(ptree const& pt1, ptree const& pt2, double acceptable_diff)
127 {
128 
129  if (!CompareRootValues(pt1, pt2, acceptable_diff)) {
130  cout << "LeafTransformer::CompareNonArray> Root values not equal" << endl;
131  return false;
132  }
133 
134  if (pt1.size() != pt2.size()) {
135  cout << "LeafTransformer::CompareNonArray> Different number of children." << endl;
136  return false;
137  }
138 
139  for (auto const& pt1_child_entry : pt1) {
140  ptree const & pt1_child = pt1_child_entry.second;
141  optional<ptree const&> pt2_child = pt2.get_child_optional(pt1_child_entry.first);
142 
143  if (!pt2_child) {
144  cout << "LeafTransformer::CompareNonArray> Child doesn't exist: " << pt1_child_entry.first
145  << endl;
146  return false;
147  }
148 
149  if (pt1_child_entry.first.rfind("_array") == pt1_child_entry.first.length()-6) {
150  if (!CompareArray(pt1_child, *pt2_child, acceptable_diff)) {
151  return false;
152  }
153  } else {
154  if (!CompareNonArray(pt1_child, *pt2_child, acceptable_diff)) {
155  cout << "LeafTransformer::CompareNonArray> Subtree: " << pt1_child_entry.first << endl;
156  return false;
157  }
158  }
159  }
160  return true;
161 }
162 
163 } // namespace
STL namespace.
Namespace for miscellaneous utilities.
Definition: PTreeFile.cpp:44
Namespace for SimPT shell package.
Definition: Client.cpp:50
Interface for PTreeComparison.
String manipulation utilities.
Header file for Exception class.