SPHinXsys  alpha version
dynamic_time_warping_method.hpp
1 
6 #pragma once
7 
9 
10  //=================================================================================================//
11 namespace SPH
12 {
13  //=================================================================================================//
14  template<class ObserveMethodType>
16  {
17  return std::abs(variable_a - variable_b);
18  };
19  //=================================================================================================//
20  template<class ObserveMethodType>
21  Real RegressionTestDynamicTimeWarping<ObserveMethodType>::calculatePNorm(Vecd variable_a, Vecd variable_b)
22  {
23  Real distance = 0;
24  for (int dimension_index = 0; dimension_index < variable_a.size(); ++dimension_index)
25  distance = std::pow(std::abs(variable_a[dimension_index] - variable_b[dimension_index]), 2);
26  return std::pow(distance, 0.5);
27  };
28  //=================================================================================================//
29  template<class ObserveMethodType>
31  {
33  Real distance = 0;
34  for (int dimension_index_i = 0; dimension_index_i != variable_a.size(); ++dimension_index_i)
35  for (int dimension_index_j = 0; dimension_index_j != variable_a.size(); ++dimension_index_j)
36  distance = std::pow(std::abs(variable_a[dimension_index_i][dimension_index_j] - variable_b[dimension_index_i][dimension_index_j]), 2);
37  return std::pow(distance, 0.5);
38  };
39  //=================================================================================================//
40  template<class ObserveMethodType>
42  (DoubleVec<VariableType> dataset_a_, DoubleVec<VariableType> dataset_b_)
43  {
44  /* define the container to hold the dtw distance.*/
45  StdVec<Real> dtw_distance;
46  for (int observation_index = 0; observation_index != this->observation_; ++observation_index)
47  {
48  int window_size_ = 5;
49  int a_length = dataset_a_[observation_index].size();
50  int b_length = dataset_b_[observation_index].size();
52  DoubleVec<Real> local_dtw_distance(a_length, StdVec<Real>(b_length, 0));
53  local_dtw_distance[0][0] = calculatePNorm(dataset_a_[observation_index][0], dataset_b_[observation_index][0]);
54  for (int index_i = 1; index_i < a_length; ++index_i)
55  local_dtw_distance[index_i][0] = local_dtw_distance[index_i - 1][0] + calculatePNorm(dataset_a_[observation_index][index_i], dataset_b_[observation_index][0]);
56  for (int index_j = 1; index_j < b_length; ++index_j)
57  local_dtw_distance[0][index_j] = local_dtw_distance[0][index_j - 1] + calculatePNorm(dataset_a_[observation_index][0], dataset_b_[observation_index][index_j]);
58 
60  window_size_ = SMAX(window_size_, ABS(a_length - b_length));
61  for (int index_i = 1; index_i != a_length; ++index_i)
62  for (int index_j = SMAX(1, index_i - window_size_); index_j != SMIN(b_length, index_i + window_size_); ++index_j)
63  local_dtw_distance[index_i][index_j] = calculatePNorm(dataset_a_[observation_index][index_i], dataset_b_[observation_index][index_j]) +
64  SMIN(local_dtw_distance[index_i - 1][index_j], local_dtw_distance[index_i][index_j - 1], local_dtw_distance[index_i - 1][index_j - 1]);
65  dtw_distance.push_back(local_dtw_distance[a_length - 1][b_length - 1]);
66  }
67  return dtw_distance;
68  };
69  //=================================================================================================//
70  template<class ObserveMethodType>
72  {
73  this->snapshot_ = this->current_result_.size();
74  this->observation_ = this->current_result_[0].size();
75 
76  StdVec<Real> dtw_distance_temp_(this->observation_, 0);
77  dtw_distance_ = dtw_distance_temp_;
78  dtw_distance_new_ = dtw_distance_;
79 
80  if ((this->number_of_run_ > 1) && (!fs::exists(dtw_distance_filefullpath_)))
81  {
82  std::cout << "\n Error: the input file:" << dtw_distance_filefullpath_ << " is not exists" << std::endl;
83  std::cout << __FILE__ << ':' << __LINE__ << std::endl;
84  exit(1);
85  }
86  };
87  //=================================================================================================//
88  template<class ObserveMethodType>
90  {
91  if (this->number_of_run_ > 1)
92  {
93  dtw_distance_xml_engine_in_.loadXmlFile(dtw_distance_filefullpath_);
94  SimTK::Xml::Element element_name_dtw_distance_ = dtw_distance_xml_engine_in_.root_element_;
95  SimTK::Xml::element_iterator ele_ite = element_name_dtw_distance_.element_begin();
96  for (; ele_ite != element_name_dtw_distance_.element_end(); ++ele_ite)
97  for (int observation_index = 0; observation_index != this->observation_; ++observation_index)
98  {
99  std::string attribute_name_ = this->quantity_name_ + "_" + std::to_string(observation_index);
100  dtw_distance_xml_engine_in_.getRequiredAttributeValue<Real>(ele_ite, attribute_name_, dtw_distance_[observation_index]);
101  }
102  }
103  };
104  //=================================================================================================//
105  template<class ObserveMethodType>
107  {
108  if (this->number_of_run_ > 1)
109  {
110  StdVec<Real> dtw_distance_local_(this->observation_, 0);
111  dtw_distance_local_ = calculateDTWDistance(this->current_result_trans_, this->result_in_);
112  for (int observation_index = 0; observation_index != this->observation_; ++observation_index)
113  {
114  dtw_distance_new_[observation_index] = SMAX(dtw_distance_local_[observation_index], dtw_distance_[observation_index], dtw_distance_new_[observation_index]);
115  }
116  this->result_in_.clear();
117  }
118  };
119  //=================================================================================================//
120  template<class ObserveMethodType>
122  {
123  SimTK::Xml::Element DTWElement = dtw_distance_xml_engine_out_.root_element_;
124  dtw_distance_xml_engine_out_.addChildToElement(DTWElement, "DTWDistance");
125  SimTK::Xml::element_iterator ele_ite = DTWElement.element_begin();
126  for (int observation_index = 0; observation_index != this->observation_; ++observation_index)
127  {
128  std::string attribute_name_ = this->quantity_name_ + "_" + std::to_string(observation_index);
129  dtw_distance_xml_engine_out_.setAttributeToElement(ele_ite, attribute_name_, dtw_distance_new_[observation_index]);
130  }
131  dtw_distance_xml_engine_out_.writeToXmlFile(dtw_distance_filefullpath_);
132  };
133  //=================================================================================================//
134  template<class ObserveMethodType>
136  {
137  if (this->number_of_run_ > 1)
138  {
139  int count_not_converged_ = 0;
140  for (int observation_index = 0; observation_index != this->observation_; ++observation_index)
141  {
142  if (std::abs(dtw_distance_[observation_index] - dtw_distance_new_[observation_index]) > threshold_value)
143  {
144  count_not_converged_++;
145  std::cout << "The DTW distance of " << this->quantity_name_ << " [" << observation_index << "] is not converged." << endl;
146  std::cout << "The old DTW distance is " << dtw_distance_[observation_index] << ", and the new DTW distance is " << dtw_distance_new_[observation_index] << "." << endl;
147  }
148  };
149 
150  if (count_not_converged_ == 0)
151  {
152  if (this->label_for_repeat_ == 4)
153  {
154  this->converged = "true";
155  std::cout << "The DTW distance of " << this->quantity_name_ << " are converged enough times, and rum will stop now." << endl;
156  return true;
157  }
158  else
159  {
160  this->converged = "false";
161  this->label_for_repeat_++;
162  std::cout << "The DTW distance of " << this->quantity_name_ << " are converged, and this is the " << this->label_for_repeat_
163  << " times. They should be converged more times to be stable." << endl;
164  }
165  }
166  else if (count_not_converged_ != 0)
167  {
168  this->converged = "false";
169  this->label_for_repeat_ = 0;
170  return false;
171  };
172  }
173  return true;
174  };
175  //=================================================================================================//
176  template<class ObserveMethodType>
177  void RegressionTestDynamicTimeWarping<ObserveMethodType>::resultTest()
178  {
179  int test_wrong = 0;
180  StdVec<Real> dtw_distance_current_;
181  dtw_distance_current_ = calculateDTWDistance(this->result_in_, this->current_result_trans_);
182  for (int observation_index = 0; observation_index != this->observation_; ++observation_index)
183  {
184  if (dtw_distance_current_[observation_index] > 1.01 * dtw_distance_[observation_index])
185  {
186  std::cout << "The maximum distance of " << this->quantity_name_ << "[" << observation_index << "] is " << dtw_distance_[observation_index]
187  << ", and the current distance is " << dtw_distance_current_[observation_index] << "." << endl;
188  test_wrong++;
189  }
190  };
191  if (test_wrong == 0)
192  {
193  std::cout << "The DTW distance of " << this->quantity_name_ << " between current result and this previous local result is within exception!" << endl;
194  }
195  else
196  {
197  std::cout << "The DTW distance of " << this->quantity_name_ << " between current result and this previous local result is beyond exception!" << endl;
198  std::cout << "Please try again. If it still post this sentence, the result is not correct!" << endl;
199  exit(1);
200  }
201  };
202  //=================================================================================================/
203 }
void readDTWDistanceFromXml()
Definition: dynamic_time_warping_method.hpp:89
Classes for the comparison between validated and tested results with dynamic time warping method...
StdVec< Real > calculateDTWDistance(DoubleVec< VariableType > dataset_a_, DoubleVec< VariableType > dataset_b_)
Definition: dynamic_time_warping_method.hpp:42
void updateDTWDistance()
Definition: dynamic_time_warping_method.hpp:106
void writeDTWDistanceToXml()
Definition: dynamic_time_warping_method.hpp:121
the regression test is based on the dynamic time warping.
Definition: dynamic_time_warping_method.h:40
Real calculatePNorm(Real variable_a, Real variable_b)
Definition: dynamic_time_warping_method.hpp:15
Definition: solid_body_supplementary.cpp:9