Tomographer  v1.0a
Tomographer C++ Framework Documentation
check_derivatives.h
Go to the documentation of this file.
1 /* This file is part of the Tomographer project, which is distributed under the
2  * terms of the MIT license.
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2015 ETH Zurich, Institute for Theoretical Physics, Philippe Faist
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26 
27 #ifndef CHECK_DERIVATIVES_H
28 #define CHECK_DERIVATIVES_H
29 
30 #include <cstddef>
31 #include <iostream>
32 
33 #include <Eigen/Core>
34 
43 namespace Tomographer
44 {
45 namespace Tools
46 {
47 
97 template<typename Der1, typename Der2, typename fnType, typename ErrorStream>
98 bool check_derivatives(const Eigen::ArrayBase<Der1> & derivatives, const Eigen::MatrixBase<Der2> & point,
99  fnType fn, std::size_t valdims,
100  typename Eigen::MatrixBase<Der2>::Scalar delta = 1e-6,
101  typename Eigen::MatrixBase<Der1>::Scalar tol = 1e-6,
102  ErrorStream & error_stream = std::cerr
103  )
104 {
105  bool ok = true;
106 
107  const std::size_t xdims = derivatives.cols();
108  eigen_assert(point.rows() == (int)xdims);
109  eigen_assert(point.cols() == (int)1);
110  eigen_assert(derivatives.rows() == (int)valdims);
111 
112  Eigen::VectorXd val0(valdims);
113  Eigen::VectorXd dval1(valdims);
114  Eigen::VectorXd dvalFromDer(valdims);
115 
116  Eigen::VectorXd pt2(point.rows());
117 
118  // calculate the base point
119  fn(val0, point);
120 
121  std::size_t i;
122  for (i = 0; i < xdims; ++i) {
123  // numerically calculate the differences ...
124 
125  pt2 = point;
126  pt2(i) += delta;
127 
128  fn(dval1, pt2);
129  dval1 -= val0;
130 
131  dvalFromDer = delta * derivatives.matrix().col(i);//derivatives.matrix() * (delta*dir);
132 
133  double thediff = (dval1 - dvalFromDer).norm();
134 
135  if (thediff/delta > tol ) {
136  // Error in the derivative
137 
138  // direction in which we probed, for the error_stream
139  Eigen::VectorXd dir = Eigen::VectorXd::Zero(xdims);
140  dir(i) = 1.0;
141 
142  ok = false;
143  error_stream
144  << "Error in derivative check: Derivative wrong in direction\n"
145  << "dir = " << dir.transpose() << " [basis vector #"<<i<<"]\n"
146  << "\tpoint = \t" << point.transpose() << "\n"
147  << "\tval0 = \t" << val0.transpose() << "\n"
148  << "\tdval1 = \t" << dval1.transpose() << "\n"
149  << "\tdvalFromDer = \t"<<dvalFromDer.transpose() << "\n"
150  << "\tderivative in this direction =\n\t\t\t\t" << derivatives.transpose().block(i,0,1,valdims) << "\n"
151  << "--> difference in p2-points: \t" << thediff << "\n"
152  << "--> difference in derivatives: \t" << thediff/delta << "\n\n";
153  }
154  }
155 
156  return ok;
157 }
158 
159 
160 
161 } // Tools
162 } // Tomographer
163 
164 
165 
166 #endif
Base namespace for the Tomographer project.
Definition: dmmhrw.h:51
Matrix< double, Dynamic, 1 > VectorXd
bool check_derivatives(const Eigen::ArrayBase< Der1 > &derivatives, const Eigen::MatrixBase< Der2 > &point, fnType fn, std::size_t valdims, typename Eigen::MatrixBase< Der2 >::Scalar delta=1e-6, typename Eigen::MatrixBase< Der1 >::Scalar tol=1e-6, ErrorStream &error_stream=std::cerr)
Check given derivatives against numerically-calculated finite differences.
Eigen::Transpose< Derived > transpose()
MatrixWrapper< Derived > matrix()