Tomographer  v5.3
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) 2016 ETH Zurich, Institute for Theoretical Physics, Philippe Faist
7  * Copyright (c) 2017 Caltech, Institute for Quantum Information and Matter, Philippe Faist
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27 
28 #ifndef CHECK_DERIVATIVES_H
29 #define CHECK_DERIVATIVES_H
30 
31 #include <cstddef>
32 #include <iostream>
33 
34 #include <Eigen/Core>
35 
36 #include <tomographer/tools/cxxutil.h> // TOMO_STATIC_ASSERT_EXPR
37 
38 
47 namespace Tomographer {
48 namespace MathTools {
49 
99 template<typename Der1, typename Der2, typename fnType, typename ErrorStream>
100 TOMOGRAPHER_EXPORT
101 bool check_derivatives(const Eigen::ArrayBase<Der1> & derivatives, const Eigen::MatrixBase<Der2> & point,
102  fnType fn, Eigen::Index valdims,
103  const typename Eigen::MatrixBase<Der2>::Scalar delta = 1e-6,
104  const typename Eigen::MatrixBase<Der1>::Scalar tol = 1e-6,
105  ErrorStream & error_stream = std::cerr
106  )
107 {
108  bool ok = true;
109 
110  typedef typename Eigen::MatrixBase<Der2>::Scalar XScalar;
111  typedef typename Eigen::MatrixBase<Der1>::Scalar ValScalar;
112 
115 
116  const Eigen::Index xdims = derivatives.cols();
117  tomographer_assert(point.rows() == (int)xdims);
118  tomographer_assert(point.cols() == (int)1);
119  tomographer_assert(derivatives.rows() == (int)valdims);
120 
123 
124  ValVector val0(valdims);
125  ValVector dval1(valdims);
126  ValVector dvalFromDer(valdims);
127 
128  XVector pt2(point.rows());
129 
130  tomographer_assert(derivatives.allFinite());
131  tomographer_assert(point.allFinite());
132 
133  // calculate the base point
134  fn(val0, point);
135 
136  tomographer_assert(val0.allFinite());
137 
138  Eigen::Index i;
139  for (i = 0; i < xdims; ++i) {
140  // numerically calculate the differences ...
141 
142  pt2 = point;
143  pt2(i) += delta;
144 
145  fn(dval1, pt2);
146  dval1 -= val0;
147 
148  tomographer_assert(dval1.allFinite());
149 
150  dvalFromDer = delta * derivatives.matrix().col(i);//derivatives.matrix() * (delta*dir);
151 
152  XScalar thediff = (dval1 - dvalFromDer).norm();
153 
154  if (thediff/delta > tol ) {
155  // Error in the derivative
156 
157  // direction in which we probed, for the error_stream
158  XVector dir = XVector::Zero(xdims);
159  dir(i) = 1.0;
160 
161  ok = false;
162  error_stream
163  << "Error in derivative check: Derivative wrong in direction\n"
164  << "dir = " << dir.transpose() << " [basis vector #"<<i<<"]\n"
165  << "\tpoint = \t" << point.transpose() << "\n"
166  << "\tval0 = \t" << val0.transpose() << "\n"
167  << "\tdval1 = \t" << dval1.transpose() << "\n"
168  << "\tdvalFromDer = \t"<<dvalFromDer.transpose() << "\n"
169  << "\tderivative in this direction =\n\t\t\t\t" << derivatives.transpose().block(i,0,1,valdims) << "\n"
170  << "--> difference in p2-points: \t" << thediff << "\n"
171  << "--> difference in derivatives: \t" << thediff/delta << "\n\n";
172  }
173  }
174 
175  return ok;
176 }
177 
178 
179 
180 } // MathTools
181 } // Tomographer
182 
183 
184 
185 #endif
Base namespace for the Tomographer project.
Definition: densellh.h:45
bool allFinite() const
bool check_derivatives(const Eigen::ArrayBase< Der1 > &derivatives, const Eigen::MatrixBase< Der2 > &point, fnType fn, Eigen::Index valdims, const typename Eigen::MatrixBase< Der2 >::Scalar delta=1e-6, const typename Eigen::MatrixBase< Der1 >::Scalar tol=1e-6, ErrorStream &error_stream=std::cerr)
Check given derivatives against numerically-calculated finite differences.
#define TOMO_STATIC_ASSERT_EXPR(...)
Tool for static assertions without message.
Definition: cxxdefs.h:77
Some C++ utilities, with a tad of C++11 tricks.
Eigen::Transpose< Derived > transpose()
MatrixWrapper< Derived > matrix()
#define tomographer_assert(...)
Assertion test macro.
Definition: cxxdefs.h:84