13#ifndef OPTIMIST_FINITE_DIFFERENCE_HH
14#define OPTIMIST_FINITE_DIFFERENCE_HH
24 Real
const m_epsilon{std::numeric_limits<Real>::epsilon()};
25 Real
const m_epsilon1{std::sqrt(std::numeric_limits<Real>::epsilon())};
26 Real
const m_epsilon2{std::pow(std::numeric_limits<Real>::epsilon(), 0.75)};
27 Real
const m_epsilon3{std::pow(std::numeric_limits<Real>::epsilon(), 0.25)};
55 return ((h1/h2)*df2 - (h2/h1)*df1) / dH;
70 Real t1{-(h2/h1) / dH};
71 Real t2{(h1/h2) / dH};
72 diff = t1 * (f1 - f0) + t2 * (f2 - f0);
73 return diff.allFinite();
93 Real diff_r{(fun_r-fun_c)/h};
94 Real diff_l{(fun_c-fun_l)/h};
95 Real weight_r{std::abs(diff_r) + EPSILON};
96 Real weight_l{std::abs(diff_l) + EPSILON};
97 Real weight_max{std::max(weight_r, weight_l)};
98 weight_r = std::sqrt(weight_r/weight_max);
99 weight_l = std::sqrt(weight_l/weight_max);
100 return (diff_r*weight_l + diff_l*weight_r) / (weight_r+weight_l);
106 const Real fun_l,
const bool is_finite_l,
107 const Real fun_c,
const bool is_finite_c,
108 const Real fun_r,
const bool is_finite_r,
113 if (is_finite_r && is_finite_l && is_finite_c) {
116 }
else if (is_finite_c && is_finite_r) {
117 diff = (fun_r-fun_c)/h;
119 }
else if (is_finite_c && is_finite_l) {
120 diff = (fun_c-fun_l)/h;
131 const Vector<N> & fun_l,
bool is_finite_l,
132 const Vector<N> & fun_c,
bool is_finite_c,
133 const Vector<N> & fun_r,
bool is_finite_r,
137 if ( is_finite_r && is_finite_l && is_finite_c ) {
138 Vector<N> diff_r((fun_r - fun_c) / h);
139 Vector<N> diff_l((fun_c - fun_l) / h);
140 Vector<N> weight_r{diff_r.array().abs() + EPSILON};
141 Vector<N> weight_l{diff_l.array().abs() + EPSILON};
142 Vector<N> weight_max = weight_r.array().max(weight_l.array());
143 weight_r = (weight_r/weight_max).array().sqrt();
144 weight_l = (weight_l/weight_max).array().sqrt();
145 diff = (diff_r*weight_l + diff_l*weight_r) / (weight_r+weight_l);
147 }
else if ( is_finite_c && is_finite_r ) {
148 diff = (fun_r-fun_c)/h;
150 }
else if ( is_finite_c && is_finite_l ) {
151 diff = (fun_c-fun_l)/h;
167 template <
typename FUNCTION,
typename Real>
177 static FiniteDifferenceEpsilon<Real> EPS;
179 auto FUN = [&fun]( Real
const x[], Real & f ) ->
bool {
180 bool ok{fun( x, f )};
181 if ( ok ) ok = std::is_finite(f);
185 Real vC{0}, vR{0}, vL{0};
186 bool is_finite_c = FUN( x, vC );
187 if ( !is_finite_c )
return false;
189 Real * X =
const_cast<Real*
>(x);
191 for (
Integer i{0}; i < dim_x; ++i ) {
193 Real h1{EPS.epsilon1(temp)};
194 Real h2{EPS.epsilon2(temp)};
195 X[i] = temp+h1;
bool is_finite_r{FUN( X, vR )};
196 X[i] = temp-h1;
bool is_finite_l{FUN( X, vL )};
205 bool is_finite_rr{FUN( X, vRR )};
207 if ( ! (is_finite_rr&&std::is_finite(grad[i])) ) grad[i] = (vR-vC)/h1;
214 bool is_finite_ll{FUN( X, vLL )};
216 if ( ! (is_finite_ll&&std::is_finite(grad[i])) ) grad[i] = (vC-vL)/h1;
224 if ( !std::is_finite(grad[i]) )
return false;
238 template <
typename FUNCTION,
typename Real>
252 static FiniteDifferenceEpsilon<Real> EPS;
256 "finite_difference_jacobian(...,dim_f={},...,lwork={}), lwork must be >= 3*dim_f\n",
261 Real * vR{work+dim_f};
262 Real * vL{work+2*dim_f};
264 auto FUN = [&fun,dim_f]( Real
const x[], Real f[] ) ->
bool {
265 bool ok{fun( x, f )};
266 for (
Integer i{0}; ok && i < dim_f; ++i ) ok = std::is_finite(f[i]);
270 bool is_finite_c{FUN( x, vC )};
271 if ( !is_finite_c )
return false;
273 Real * X{
const_cast<Real*
>(x)};
276 for (
Integer j{0}; j < dim_x; ++j ) {
278 Real h1{EPS.epsilon1(temp)};
279 Real h2{EPS.epsilon2(temp)};
281 X[j] = temp+h1;
bool is_finite_r{FUN( X, vR )};
282 X[j] = temp-h1;
bool is_finite_l{FUN( X, vL )};
293 bool is_finite_rr{FUN( X, vRR )};
295 if ( !is_finite_rr ) {
296 for (
Integer i{0}; i < dim_f; ++i ) {
297 pjac[i] = (vR[i]-vC[i])/h1;
298 if ( !std::is_finite( pjac[i] ) )
return false;
307 bool is_finite_ll{FUN( X, vLL )};
309 if ( !is_finite_ll ) {
310 for (
Integer i{0}; i < dim_f; ++i ) {
311 pjac[i] = (vC[i]-vL[i])/h1;
312 if ( !std::is_finite( pjac[i] ) )
return false;
336 template <
typename FUNCTION,
typename Real>
346 static FiniteDifferenceEpsilon<Real> EPS;
348 auto FUN = [&fun]( Real
const x[], Real & f ) ->
bool {
349 bool ok{fun( x, f )};
350 if ( ok ) ok = std::is_finite(f);
354 Real fp{0}, fm{0}, fc{0}, hij{0}, tempi{0}, tempj{0}, hi{0}, hj{0},
355 fpp{0}, fpm{0}, fmp{0}, fmm{0};
358 Real * X{
const_cast<Real*
>(x)};
359 for (
Integer j{0}; j < dim_x && ok; ++j ) {
361 hj = EPS.epsilon3(tempj);
363 if ( !ok )
goto skip;
366 if ( !ok )
goto skip;
369 if ( !ok )
goto skip;
370 Hess[j*(ldH+1)] = ((fp+fm)-2*fc)/(hj*hj);
371 for (
Integer i{j+1}; i < dim_x && ok; ++i ) {
373 hi = EPS.epsilon3(tempi);
377 if ( !ok )
goto skip2;
380 if ( !ok )
goto skip2;
383 if ( !ok )
goto skip2;
386 if ( !ok )
goto skip2;
388 Hess[j+i*ldH] = Hess[i+j*ldH] = ( (fpp+fmm) - (fpm+fmp) )/hij;
Definition FiniteDifference.hh:23
Real epsilon2(Real v) const
Definition FiniteDifference.hh:30
Real epsilon1(Real v) const
Definition FiniteDifference.hh:29
Real epsilon3(Real v) const
Definition FiniteDifference.hh:31
Real const m_epsilon3
Definition FiniteDifference.hh:27
Real const m_epsilon
Definition FiniteDifference.hh:24
Real const m_epsilon2
Definition FiniteDifference.hh:26
Real const m_epsilon1
Definition FiniteDifference.hh:25
Definition FiniteDifference.hh:20
static bool finite_difference_hessian(Real const x[], Integer dim_x, FUNCTION fun, Real Hess[], Integer ldH)
Definition FiniteDifference.hh:339
static Real finite_difference_side(Real f0, Real f1, Real f2, Real h1, Real h2)
Definition FiniteDifference.hh:45
static Real finite_difference_centered(const Real fun_l, const Real fun_c, const Real fun_r, const Real h)
Definition FiniteDifference.hh:87
static bool finite_difference_gradient(Real const x[], Integer dim_x, FUNCTION fun, Real grad[])
Definition FiniteDifference.hh:170
static bool finite_difference_jacobian(Real const x[], Integer dim_x, FUNCTION fun, Integer dim_f, Real Jac[], Integer ldJ, Real *work, Integer lwork)
Definition FiniteDifference.hh:241
Namespace for the Optimist library.
Definition Optimist.hh:87
OPTIMIST_DEFAULT_INTEGER_TYPE Integer
The Integer type as used for the API.
Definition Optimist.hh:95