bool opt_val_hes(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; // temporary indices size_t j, k; // x space vector size_t n = 1; BaseVector x(n); x[0] = 2. * 3.141592653; // y space vector size_t m = 1; BaseVector y(m); y[0] = 1.; // t and z vectors size_t ell = 10; BaseVector t(ell); BaseVector z(ell); for(k = 0; k < ell; k++) { t[k] = double(k) / double(ell); // time of measurement z[k] = y[0] * sin( x[0] * t[k] ); // data without noise } // construct the function object Fun fun(t, z); // evaluate the Jacobian and Hessian BaseVector jac(n), hes(n * n); int signdet = CppAD::opt_val_hes(x, y, fun, jac, hes); // we know that F_yy is positive definate for this case assert( signdet == 1 ); // create ADFun object g corresponding to V(x) ADVector a_x(n), a_v(1); for(j = 0; j < n; j++) a_x[j] = x[j]; Independent(a_x); a_v[0] = V(a_x, t, z); CppAD::ADFun<double> g(a_x, a_v); // accuracy for checks double eps = 10. * CppAD::numeric_limits<double>::epsilon(); // check Jacobian BaseVector check_jac = g.Jacobian(x); for(j = 0; j < n; j++) ok &= NearEqual(jac[j], check_jac[j], eps, eps); // check Hessian BaseVector check_hes = g.Hessian(x, 0); for(j = 0; j < n*n; j++) ok &= NearEqual(hes[j], check_hes[j], eps, eps); return ok; }
bool interp_retape(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; // domain space vector size_t n = 1; CPPAD_TESTVECTOR(AD<double>) X(n); // loop over argument values size_t k; for(k = 0; k < TableLength - 1; k++) { X[0] = .4 * ArgumentValue[k] + .6 * ArgumentValue[k+1]; // declare independent variables and start tape recording // (use a different tape for each argument value) CppAD::Independent(X); // evaluate piecewise linear interpolant at X[0] AD<double> A = Argument(X[0]); AD<double> F = Function(X[0]); AD<double> S = Slope(X[0]); AD<double> I = F + (X[0] - A) * S; // range space vector size_t m = 1; CPPAD_TESTVECTOR(AD<double>) Y(m); Y[0] = I; // create f: X -> Y and stop tape recording CppAD::ADFun<double> f(X, Y); // vectors for arguments to the function object f CPPAD_TESTVECTOR(double) x(n); // argument values CPPAD_TESTVECTOR(double) y(m); // function values CPPAD_TESTVECTOR(double) dx(n); // differentials in x space CPPAD_TESTVECTOR(double) dy(m); // differentials in y space // to check function value we use the fact that X[0] is between // ArgumentValue[k] and ArgumentValue[k+1] double delta, check; x[0] = Value(X[0]); delta = ArgumentValue[k+1] - ArgumentValue[k]; check = FunctionValue[k+1] * (x[0]-ArgumentValue[k]) / delta + FunctionValue[k] * (ArgumentValue[k+1]-x[0]) / delta; ok &= NearEqual(Y[0], check, 1e-10, 1e-10); // evaluate partials w.r.t. x[0] dx[0] = 1.; dy = f.Forward(1, dx); // check that the derivative is the slope check = (FunctionValue[k+1] - FunctionValue[k]) / (ArgumentValue[k+1] - ArgumentValue[k]); ok &= NearEqual(dy[0], check, 1e-10, 1e-10); } return ok; }
bool BenderQuad(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; // temporary indices size_t i, j; // x space vector size_t n = 1; BAvector x(n); x[0] = 2. * 3.141592653; // y space vector size_t m = 1; BAvector y(m); y[0] = 1.; // t and z vectors size_t N = 10; BAvector t(N); BAvector z(N); for(i = 0; i < N; i++) { t[i] = double(i) / double(N); // time of measurement z[i] = y[0] * sin( x[0] * t[i] ); // data without noise } // construct the function object Fun fun(t, z); // evaluate the G(x), G'(x) and G''(x) BAvector g(1), gx(n), gxx(n * n); CppAD::BenderQuad(x, y, fun, g, gx, gxx); // create ADFun object Gfun corresponding to G(x) ADvector a_x(n), a_g(1); for(j = 0; j < n; j++) a_x[j] = x[j]; Independent(a_x); a_g[0] = G(a_x, t, z); CppAD::ADFun<double> Gfun(a_x, a_g); // accuracy for checks double eps = 10. * CppAD::numeric_limits<double>::epsilon(); // check Jacobian BAvector check_gx = Gfun.Jacobian(x); for(j = 0; j < n; j++) ok &= NearEqual(gx[j], check_gx[j], eps, eps); // check Hessian BAvector check_gxx = Gfun.Hessian(x, 0); for(j = 0; j < n*n; j++) ok &= NearEqual(gxx[j], check_gxx[j], eps, eps); return ok; }
bool forward_order(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; double eps = 10. * std::numeric_limits<double>::epsilon(); // domain space vector size_t n = 2; CPPAD_TESTVECTOR(AD<double>) ax(n); ax[0] = 0.; ax[1] = 1.; // declare independent variables and starting recording CppAD::Independent(ax); // range space vector size_t m = 1; CPPAD_TESTVECTOR(AD<double>) ay(m); ay[0] = ax[0] * ax[0] * ax[1]; // create f: x -> y and stop tape recording CppAD::ADFun<double> f(ax, ay); // initially, the variable values during taping are stored in f ok &= f.size_order() == 1; // Compute three forward orders at one size_t q = 2, q1 = q+1; CPPAD_TESTVECTOR(double) xq(n*q1), yq; xq[q1*0 + 0] = 3.; xq[q1*1 + 0] = 4.; // x^0 (order zero) xq[q1*0 + 1] = 1.; xq[q1*1 + 1] = 0.; // x^1 (order one) xq[q1*0 + 2] = 0.; xq[q1*1 + 2] = 0.; // x^2 (order two) // X(t) = x^0 + x^1 * t + x^2 * t^2 // = [ 3 + t, 4 ] yq = f.Forward(q, xq); ok &= size_t( yq.size() ) == m*q1; // Y(t) = F[X(t)] // = (3 + t) * (3 + t) * 4 // = y^0 + y^1 * t + y^2 * t^2 + o(t^3) // // check y^0 (order zero) CPPAD_TESTVECTOR(double) x0(n); x0[0] = xq[q1*0 + 0]; x0[1] = xq[q1*1 + 0]; ok &= NearEqual(yq[q1*0 + 0] , x0[0]*x0[0]*x0[1], eps, eps); // // check y^1 (order one) ok &= NearEqual(yq[q1*0 + 1] , 2.*x0[0]*x0[1], eps, eps); // // check y^2 (order two) double F_00 = 2. * yq[q1*0 + 2]; // second partial F w.r.t. x_0, x_0 ok &= NearEqual(F_00, 2.*x0[1], eps, eps); // check number of orders per variable ok &= f.size_order() == 3; return ok; }
bool atanh(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; // 10 times machine epsilon double eps = 10. * std::numeric_limits<double>::epsilon(); // domain space vector size_t n = 1; double x0 = 0.5; CPPAD_TESTVECTOR(AD<double>) ax(n); ax[0] = x0; // declare independent variables and start tape recording CppAD::Independent(ax); // a temporary value AD<double> tanh_of_x0 = CppAD::tanh(ax[0]); // range space vector size_t m = 1; CPPAD_TESTVECTOR(AD<double>) ay(m); ay[0] = CppAD::atanh(tanh_of_x0); // create f: x -> y and stop tape recording CppAD::ADFun<double> f(ax, ay); // check value ok &= NearEqual(ay[0] , x0, eps, eps); // forward computation of first partial w.r.t. x[0] CPPAD_TESTVECTOR(double) dx(n); CPPAD_TESTVECTOR(double) dy(m); dx[0] = 1.; dy = f.Forward(1, dx); ok &= NearEqual(dy[0], 1., eps, eps); // forward computation of higher order partials w.r.t. x[0] size_t n_order = 5; for(size_t order = 2; order < n_order; order++) { dx[0] = 0.; dy = f.Forward(order, dx); ok &= NearEqual(dy[0], 0., eps, eps); } // reverse computation of derivatives CPPAD_TESTVECTOR(double) w(m); CPPAD_TESTVECTOR(double) dw(n_order * n); w[0] = 1.; dw = f.Reverse(n_order, w); ok &= NearEqual(dw[0], 1., eps, eps); for(size_t order = 1; order < n_order; order++) ok &= NearEqual(dw[order * n + 0], 0., eps, eps); return ok; }
bool Div(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; double eps99 = 99.0 * std::numeric_limits<double>::epsilon(); // domain space vector size_t n = 1; double x0 = 0.5; CPPAD_TESTVECTOR(AD<double>) x(n); x[0] = x0; // declare independent variables and start tape recording CppAD::Independent(x); // some binary division operations AD<double> a = x[0] / 1.; // AD<double> / double AD<double> b = a / 2; // AD<double> / int AD<double> c = 3. / b; // double / AD<double> AD<double> d = 4 / c; // int / AD<double> // range space vector size_t m = 1; CPPAD_TESTVECTOR(AD<double>) y(m); y[0] = (x[0] * x[0]) / d; // AD<double> / AD<double> // create f: x -> y and stop tape recording CppAD::ADFun<double> f(x, y); // check value ok &= NearEqual(y[0], x0*x0*3.*2.*1./(4.*x0), eps99, eps99); // forward computation of partials w.r.t. x[0] CPPAD_TESTVECTOR(double) dx(n); CPPAD_TESTVECTOR(double) dy(m); dx[0] = 1.; dy = f.Forward(1, dx); ok &= NearEqual(dy[0], 3.*2.*1./4., eps99, eps99); // reverse computation of derivative of y[0] CPPAD_TESTVECTOR(double) w(m); CPPAD_TESTVECTOR(double) dw(n); w[0] = 1.; dw = f.Reverse(1, w); ok &= NearEqual(dw[0], 3.*2.*1./4., eps99, eps99); // use a VecAD<Base>::reference object with division CppAD::VecAD<double> v(1); AD<double> zero(0); v[zero] = d; AD<double> result = (x[0] * x[0]) / v[zero]; ok &= (result == y[0]); return ok; }
bool atan2(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; double eps99 = 99.0 * std::numeric_limits<double>::epsilon(); // domain space vector size_t n = 1; double x0 = 0.5; CPPAD_TESTVECTOR(AD<double>) x(n); x[0] = x0; // declare independent variables and start tape recording CppAD::Independent(x); // a temporary value AD<double> sin_of_x0 = CppAD::sin(x[0]); AD<double> cos_of_x0 = CppAD::cos(x[0]); // range space vector size_t m = 1; CPPAD_TESTVECTOR(AD<double>) y(m); y[0] = CppAD::atan2(sin_of_x0, cos_of_x0); // create f: x -> y and stop tape recording CppAD::ADFun<double> f(x, y); // check value ok &= NearEqual(y[0] , x0, eps99, eps99); // forward computation of first partial w.r.t. x[0] CPPAD_TESTVECTOR(double) dx(n); CPPAD_TESTVECTOR(double) dy(m); dx[0] = 1.; dy = f.Forward(1, dx); ok &= NearEqual(dy[0], 1., eps99, eps99); // reverse computation of derivative of y[0] CPPAD_TESTVECTOR(double) w(m); CPPAD_TESTVECTOR(double) dw(n); w[0] = 1.; dw = f.Reverse(1, w); ok &= NearEqual(dw[0], 1., eps99, eps99); // use a VecAD<Base>::reference object with atan2 CppAD::VecAD<double> v(2); AD<double> zero(0); AD<double> one(1); v[zero] = sin_of_x0; v[one] = cos_of_x0; AD<double> result = CppAD::atan2(v[zero], v[one]); ok &= NearEqual(result, x0, eps99, eps99); return ok; }
bool AddEq(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; double eps99 = 99.0 * std::numeric_limits<double>::epsilon(); // domain space vector size_t n = 1; double x0 = .5; CPPAD_TESTVECTOR(AD<double>) x(n); x[0] = x0; // declare independent variables and start tape recording CppAD::Independent(x); // range space vector size_t m = 2; CPPAD_TESTVECTOR(AD<double>) y(m); y[0] = x[0]; // initial value y[0] += 2; // AD<double> += int y[0] += 4.; // AD<double> += double y[1] = y[0] += x[0]; // use the result of a compound assignment // create f: x -> y and stop tape recording CppAD::ADFun<double> f(x, y); // check value ok &= NearEqual(y[0] , x0+2.+4.+x0, eps99, eps99); ok &= NearEqual(y[1] , y[0], eps99, eps99); // forward computation of partials w.r.t. x[0] CPPAD_TESTVECTOR(double) dx(n); CPPAD_TESTVECTOR(double) dy(m); dx[0] = 1.; dy = f.Forward(1, dx); ok &= NearEqual(dy[0], 2., eps99, eps99); ok &= NearEqual(dy[1], 2., eps99, eps99); // reverse computation of derivative of y[0] CPPAD_TESTVECTOR(double) w(m); CPPAD_TESTVECTOR(double) dw(n); w[0] = 1.; w[1] = 0.; dw = f.Reverse(1, w); ok &= NearEqual(dw[0], 2., eps99, eps99); // use a VecAD<Base>::reference object with computed addition CppAD::VecAD<double> v(1); AD<double> zero(0); AD<double> result = 1; v[zero] = 2; result += v[zero]; ok &= (result == 3); return ok; }
bool pow_int(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; // declare independent variables and start tape recording size_t n = 1; double x0 = -0.5; CPPAD_TESTVECTOR(AD<double>) x(n); x[0] = x0; CppAD::Independent(x); // dependent variable vector size_t m = 7; CPPAD_TESTVECTOR(AD<double>) y(m); int i; for(i = 0; i < int(m); i++) y[i] = CppAD::pow(x[0], i - 3); // create f: x -> y and stop tape recording CppAD::ADFun<double> f(x, y); // check value double check; for(i = 0; i < int(m); i++) { check = std::pow(x0, double(i - 3)); ok &= NearEqual(y[i] , check, 1e-10 , 1e-10); } // forward computation of first partial w.r.t. x[0] CPPAD_TESTVECTOR(double) dx(n); CPPAD_TESTVECTOR(double) dy(m); dx[0] = 1.; dy = f.Forward(1, dx); for(i = 0; i < int(m); i++) { check = double(i-3) * std::pow(x0, double(i - 4)); ok &= NearEqual(dy[i] , check, 1e-10 , 1e-10); } // reverse computation of derivative of y[i] CPPAD_TESTVECTOR(double) w(m); CPPAD_TESTVECTOR(double) dw(n); for(i = 0; i < int(m); i++) w[i] = 0.; for(i = 0; i < int(m); i++) { w[i] = 1.; dw = f.Reverse(1, w); check = double(i-3) * std::pow(x0, double(i - 4)); ok &= NearEqual(dw[0] , check, 1e-10 , 1e-10); w[i] = 0.; } return ok; }
/* $$ $head Use Atomic Function$$ $codep */ bool get_started(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; double eps = 10. * CppAD::numeric_limits<double>::epsilon(); /* $$ $subhead Constructor$$ $codep */ // Create the atomic get_started object atomic_get_started afun("atomic_get_started"); /* $$ $subhead Recording$$ $codep */ // Create the function f(x) // // domain space vector size_t n = 1; double x0 = 0.5; vector< AD<double> > ax(n); ax[0] = x0; // declare independent variables and start tape recording CppAD::Independent(ax); // range space vector size_t m = 1; vector< AD<double> > ay(m); // call user function and store get_started(x) in au[0] vector< AD<double> > au(m); afun(ax, au); // u = 1 / x // now use AD division to invert to invert the operation ay[0] = 1.0 / au[0]; // y = 1 / u = x // create f: x -> y and stop tape recording CppAD::ADFun<double> f; f.Dependent (ax, ay); // f(x) = x /* $$ $subhead forward$$ $codep */ // check function value double check = x0; ok &= NearEqual( Value(ay[0]) , check, eps, eps); // check zero order forward mode size_t p; vector<double> x_p(n), y_p(m); p = 0; x_p[0] = x0; y_p = f.Forward(p, x_p); ok &= NearEqual(y_p[0] , check, eps, eps); return ok; }
bool Add(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; double eps99 = 99.0 * std::numeric_limits<double>::epsilon(); // domain space vector size_t n = 1; double x0 = 0.5; CPPAD_TESTVECTOR(AD<double>) x(n); x[0] = x0; // declare independent variables and start tape recording CppAD::Independent(x); // some binary addition operations AD<double> a = x[0] + 1.; // AD<double> + double AD<double> b = a + 2; // AD<double> + int AD<double> c = 3. + b; // double + AD<double> AD<double> d = 4 + c; // int + AD<double> // range space vector size_t m = 1; CPPAD_TESTVECTOR(AD<double>) y(m); y[0] = d + x[0]; // AD<double> + AD<double> // create f: x -> y and stop tape recording CppAD::ADFun<double> f(x, y); // check value ok &= NearEqual(y[0] , 2. * x0 + 10, eps99, eps99); // forward computation of partials w.r.t. x[0] CPPAD_TESTVECTOR(double) dx(n); CPPAD_TESTVECTOR(double) dy(m); dx[0] = 1.; dy = f.Forward(1, dx); ok &= NearEqual(dy[0], 2., eps99, eps99); // reverse computation of derivative of y[0] CPPAD_TESTVECTOR(double) w(m); CPPAD_TESTVECTOR(double) dw(n); w[0] = 1.; dw = f.Reverse(1, w); ok &= NearEqual(dw[0], 2., eps99, eps99); // use a VecAD<Base>::reference object with addition CppAD::VecAD<double> v(1); AD<double> zero(0); v[zero] = a; AD<double> result = v[zero] + 2; ok &= (result == b); return ok; }
bool SubEq(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; // domain space vector size_t n = 1; double x0 = .5; CPPAD_TEST_VECTOR< AD<double> > x(n); x[0] = x0; // declare independent variables and start tape recording CppAD::Independent(x); // range space vector size_t m = 2; CPPAD_TEST_VECTOR< AD<double> > y(m); y[0] = 3. * x[0]; // initial value y[0] -= 2; // AD<double> -= int y[0] -= 4.; // AD<double> -= double y[1] = y[0] -= x[0]; // use the result of a computed assignment // create f: x -> y and stop tape recording CppAD::ADFun<double> f(x, y); // check value ok &= NearEqual(y[0] , 3.*x0-(2.+4.+x0), 1e-10 , 1e-10); ok &= NearEqual(y[1] , y[0], 1e-10 , 1e-10); // forward computation of partials w.r.t. x[0] CPPAD_TEST_VECTOR<double> dx(n); CPPAD_TEST_VECTOR<double> dy(m); dx[0] = 1.; dy = f.Forward(1, dx); ok &= NearEqual(dy[0], 2., 1e-10, 1e-10); ok &= NearEqual(dy[1], 2., 1e-10, 1e-10); // reverse computation of derivative of y[0] CPPAD_TEST_VECTOR<double> w(m); CPPAD_TEST_VECTOR<double> dw(n); w[0] = 1.; w[1] = 0.; dw = f.Reverse(1, w); ok &= NearEqual(dw[0], 2., 1e-10, 1e-10); // use a VecAD<Base>::reference object with computed subtraction CppAD::VecAD<double> v(1); AD<double> zero(0); AD<double> result = 1; v[zero] = 2; result -= v[zero]; ok &= (result == -1); return ok; }
bool MulEq(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; // domain space vector size_t n = 1; double x0 = .5; CPPAD_TESTVECTOR(AD<double>) x(n); x[0] = x0; // declare independent variables and start tape recording CppAD::Independent(x); // range space vector size_t m = 2; CPPAD_TESTVECTOR(AD<double>) y(m); y[0] = x[0]; // initial value y[0] *= 2; // AD<double> *= int y[0] *= 4.; // AD<double> *= double y[1] = y[0] *= x[0]; // use the result of a computed assignment // create f: x -> y and stop tape recording CppAD::ADFun<double> f(x, y); // check value ok &= NearEqual(y[0] , x0*2.*4.*x0, 1e-10 , 1e-10); ok &= NearEqual(y[1] , y[0], 1e-10 , 1e-10); // forward computation of partials w.r.t. x[0] CPPAD_TESTVECTOR(double) dx(n); CPPAD_TESTVECTOR(double) dy(m); dx[0] = 1.; dy = f.Forward(1, dx); ok &= NearEqual(dy[0], 8.*2.*x0, 1e-10, 1e-10); ok &= NearEqual(dy[1], 8.*2.*x0, 1e-10, 1e-10); // reverse computation of derivative of y[0] CPPAD_TESTVECTOR(double) w(m); CPPAD_TESTVECTOR(double) dw(n); w[0] = 1.; w[1] = 0.; dw = f.Reverse(1, w); ok &= NearEqual(dw[0], 8.*2.*x0, 1e-10, 1e-10); // use a VecAD<Base>::reference object with computed multiplication CppAD::VecAD<double> v(1); AD<double> zero(0); AD<double> result = 1; v[zero] = 2; result *= v[zero]; ok &= (result == 2); return ok; }
bool Mul(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; // domain space vector size_t n = 1; double x0 = .5; CPPAD_TEST_VECTOR< AD<double> > x(n); x[0] = x0; // declare independent variables and start tape recording CppAD::Independent(x); // some binary multiplication operations AD<double> a = x[0] * 1.; // AD<double> * double AD<double> b = a * 2; // AD<double> * int AD<double> c = 3. * b; // double * AD<double> AD<double> d = 4 * c; // int * AD<double> // range space vector size_t m = 1; CPPAD_TEST_VECTOR< AD<double> > y(m); y[0] = x[0] * d; // AD<double> * AD<double> // create f: x -> y and stop tape recording CppAD::ADFun<double> f(x, y); // check value ok &= NearEqual(y[0] , x0*(4.*3.*2.*1.)*x0, 1e-10 , 1e-10); // forward computation of partials w.r.t. x[0] CPPAD_TEST_VECTOR<double> dx(n); CPPAD_TEST_VECTOR<double> dy(m); dx[0] = 1.; dy = f.Forward(1, dx); ok &= NearEqual(dy[0], (4.*3.*2.*1.)*2.*x0, 1e-10 , 1e-10); // reverse computation of derivative of y[0] CPPAD_TEST_VECTOR<double> w(m); CPPAD_TEST_VECTOR<double> dw(n); w[0] = 1.; dw = f.Reverse(1, w); ok &= NearEqual(dw[0], (4.*3.*2.*1.)*2.*x0, 1e-10 , 1e-10); // use a VecAD<Base>::reference object with multiplication CppAD::VecAD<double> v(1); AD<double> zero(0); v[zero] = c; AD<double> result = 4 * v[zero]; ok &= (result == d); return ok; }
bool Sub(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; double eps99 = 99.0 * std::numeric_limits<double>::epsilon(); // domain space vector size_t n = 1; double x0 = .5; CPPAD_TESTVECTOR(AD<double>) x(1); x[0] = x0; // declare independent variables and start tape recording CppAD::Independent(x); AD<double> a = 2. * x[0] - 1.; // AD<double> - double AD<double> b = a - 2; // AD<double> - int AD<double> c = 3. - b; // double - AD<double> AD<double> d = 4 - c; // int - AD<double> // range space vector size_t m = 1; CPPAD_TESTVECTOR(AD<double>) y(m); y[0] = x[0] - d; // AD<double> - AD<double> // create f: x -> y and stop tape recording CppAD::ADFun<double> f(x, y); // check value ok &= NearEqual(y[0], x0-4.+3.+2.-2.*x0+1., eps99, eps99); // forward computation of partials w.r.t. x[0] CPPAD_TESTVECTOR(double) dx(n); CPPAD_TESTVECTOR(double) dy(m); dx[0] = 1.; dy = f.Forward(1, dx); ok &= NearEqual(dy[0], -1., eps99, eps99); // reverse computation of derivative of y[0] CPPAD_TESTVECTOR(double) w(m); CPPAD_TESTVECTOR(double) dw(n); w[0] = 1.; dw = f.Reverse(1, w); ok &= NearEqual(dw[0], -1., eps99, eps99); // use a VecAD<Base>::reference object with subtraction CppAD::VecAD<double> v(1); AD<double> zero(0); v[zero] = b; AD<double> result = 3. - v[zero]; ok &= (result == c); return ok; }
bool Tanh(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; double eps = 10. * CppAD::numeric_limits<double>::epsilon(); // domain space vector size_t n = 1; double x0 = 0.5; CPPAD_TESTVECTOR(AD<double>) x(n); x[0] = x0; // declare independent variables and start tape recording CppAD::Independent(x); // range space vector size_t m = 1; CPPAD_TESTVECTOR(AD<double>) y(m); y[0] = CppAD::tanh(x[0]); // create f: x -> y and stop tape recording CppAD::ADFun<double> f(x, y); // check value double check = std::tanh(x0); ok &= NearEqual(y[0] , check, eps, eps); // forward computation of first partial w.r.t. x[0] CPPAD_TESTVECTOR(double) dx(n); CPPAD_TESTVECTOR(double) dy(m); dx[0] = 1.; dy = f.Forward(1, dx); check = 1. - std::tanh(x0) * std::tanh(x0); ok &= NearEqual(dy[0], check, eps, eps); // reverse computation of derivative of y[0] CPPAD_TESTVECTOR(double) w(m); CPPAD_TESTVECTOR(double) dw(n); w[0] = 1.; dw = f.Reverse(1, w); ok &= NearEqual(dw[0], check, eps, eps); // use a VecAD<Base>::reference object with tan CppAD::VecAD<double> v(1); AD<double> zero(0); v[zero] = x0; AD<double> result = CppAD::tanh(v[zero]); check = std::tanh(x0); ok &= NearEqual(result, check, eps, eps); return ok; }
bool log10(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; // domain space vector size_t n = 1; double x0 = 0.5; CPPAD_TESTVECTOR(AD<double>) x(n); x[0] = x0; // declare independent variables and start tape recording CppAD::Independent(x); // ten raised to the x0 power AD<double> ten = 10.; AD<double> pow_10_x0 = CppAD::pow(ten, x[0]); // range space vector size_t m = 1; CPPAD_TESTVECTOR(AD<double>) y(m); y[0] = CppAD::log10(pow_10_x0); // create f: x -> y and stop tape recording CppAD::ADFun<double> f(x, y); // check value ok &= NearEqual(y[0] , x0, 1e-10 , 1e-10); // forward computation of first partial w.r.t. x[0] CPPAD_TESTVECTOR(double) dx(n); CPPAD_TESTVECTOR(double) dy(m); dx[0] = 1.; dy = f.Forward(1, dx); ok &= NearEqual(dy[0], 1., 1e-10, 1e-10); // reverse computation of derivative of y[0] CPPAD_TESTVECTOR(double) w(m); CPPAD_TESTVECTOR(double) dw(n); w[0] = 1.; dw = f.Reverse(1, w); ok &= NearEqual(dw[0], 1., 1e-10, 1e-10); // use a VecAD<Base>::reference object with log10 CppAD::VecAD<double> v(1); AD<double> zero(0); v[zero] = pow_10_x0; AD<double> result = CppAD::log10(v[zero]); ok &= NearEqual(result, x0, 1e-10, 1e-10); return ok; }
bool mul_level(void) { bool ok = true; // initialize test result using CppAD::NearEqual; double eps = 10. * std::numeric_limits<double>::epsilon(); typedef CppAD::AD<double> ADdouble; // for one level of taping typedef CppAD::AD<ADdouble> ADDdouble; // for two levels of taping size_t n = 2; // dimension for example CPPAD_TEST_VECTOR<ADdouble> a_x(n); CPPAD_TEST_VECTOR<ADDdouble> aa_x(n); // value of the independent variables a_x[0] = 2.; a_x[1] = 3.; Independent(a_x); aa_x[0] = a_x[0]; aa_x[1] = a_x[1]; CppAD::Independent(aa_x); // compute the function f(x) = 2 * x[0] * x[1] CPPAD_TEST_VECTOR<ADDdouble> aa_f(1); aa_f[0] = 2. * aa_x[0] * aa_x[1]; CppAD::ADFun<ADdouble> F(aa_x, aa_f); // re-evaluate f(2, 3) (must get proper deepedence on a_x). size_t p = 0; CPPAD_TEST_VECTOR<ADdouble> a_fp(1); a_fp = F.Forward(p, a_x); ok &= NearEqual(a_fp[0], 2. * a_x[0] * a_x[1], eps, eps); // compute the function g(x) = 2 * partial_x[0] f(x) = 4 * x[1] p = 1; CPPAD_TEST_VECTOR<ADdouble> a_dx(n), a_g(1); a_dx[0] = 1.; a_dx[1] = 0.; a_fp = F.Forward(p, a_dx); a_g[0] = 2. * a_fp[0]; CppAD::ADFun<double> G(a_x, a_g); // compute partial_x[1] g(x) CPPAD_TEST_VECTOR<double> xp(n), gp(1); p = 0; xp[0] = 4.; xp[1] = 5.; gp = G.Forward(p, xp); ok &= NearEqual(gp[0], 4. * xp[1], eps, eps); p = 1; xp[0] = 0.; xp[1] = 1.; gp = G.Forward(p, xp); ok &= NearEqual(gp[0], 4., eps, eps); return ok; }
bool Asin(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; // domain space vector size_t n = 1; double x0 = 0.5; CPPAD_TEST_VECTOR< AD<double> > x(n); x[0] = x0; // declare independent variables and start tape recording CppAD::Independent(x); // a temporary value AD<double> sin_of_x0 = CppAD::sin(x[0]); // range space vector size_t m = 1; CPPAD_TEST_VECTOR< AD<double> > y(m); y[0] = CppAD::asin(sin_of_x0); // create f: x -> y and stop tape recording CppAD::ADFun<double> f(x, y); // check value ok &= NearEqual(y[0] , x0, 1e-10 , 1e-10); // forward computation of first partial w.r.t. x[0] CPPAD_TEST_VECTOR<double> dx(n); CPPAD_TEST_VECTOR<double> dy(m); dx[0] = 1.; dy = f.Forward(1, dx); ok &= NearEqual(dy[0], 1., 1e-10, 1e-10); // reverse computation of derivative of y[0] CPPAD_TEST_VECTOR<double> w(m); CPPAD_TEST_VECTOR<double> dw(n); w[0] = 1.; dw = f.Reverse(1, w); ok &= NearEqual(dw[0], 1., 1e-10, 1e-10); // use a VecAD<Base>::reference object with asin CppAD::VecAD<double> v(1); AD<double> zero(0); v[zero] = sin_of_x0; AD<double> result = CppAD::asin(v[zero]); ok &= NearEqual(result, x0, 1e-10, 1e-10); return ok; }
bool OdeErrControl_three(void) { bool ok = true; // initial return value using CppAD::NearEqual; double alpha = 10.; Method_three method(alpha); CppAD::vector<double> xi(2); xi[0] = 1.; xi[1] = 0.; CppAD::vector<double> eabs(2); eabs[0] = 1e-4; eabs[1] = 1e-4; // inputs double ti = 0.; double tf = 1.; double smin = 1e-4; double smax = 1.; double scur = 1.; double erel = 0.; // outputs CppAD::vector<double> ef(2); CppAD::vector<double> xf(2); CppAD::vector<double> maxabs(2); size_t nstep; xf = OdeErrControl(method, ti, tf, xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep); double x0 = exp( alpha * tf * tf ); ok &= NearEqual(x0, xf[0], 1e-4, 1e-4); ok &= NearEqual(0., ef[0], 1e-4, 1e-4); double root_pi = sqrt( 4. * atan(1.)); double root_alpha = sqrt( alpha ); double x1 = CppAD::erf(alpha * tf) * root_pi / (2 * root_alpha); ok &= NearEqual(x1, xf[1], 1e-4, 1e-4); ok &= NearEqual(0., ef[1], 1e-4, 1e-4); ok &= method.F.was_negative(); return ok; }
bool compare_op(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; double eps10 = 10.0 * std::numeric_limits<double>::epsilon(); // domain space vector size_t n = 1; CPPAD_TESTVECTOR(AD<double>) ax(n); ax[0] = 0.5; // range space vector size_t m = 1; CPPAD_TESTVECTOR(AD<double>) ay(m); for(size_t k = 0; k < 2; k++) { // optimization options std::string options = ""; if( k == 0 ) options = "no_compare_op"; // declare independent variables and start tape recording CppAD::Independent(ax); // compute function value tape_size before, after; fun(options, ax, ay, before, after); // create f: x -> y and stop tape recording CppAD::ADFun<double> f(ax, ay); ok &= f.size_var() == before.n_var; ok &= f.size_op() == before.n_op; // Optimize the operation sequence f.optimize(options); ok &= f.size_var() == after.n_var; ok &= f.size_op() == after.n_op; // Check result for a zero order calculation for a different x, // where the result of the comparison is he same. CPPAD_TESTVECTOR(double) x(n), y(m), check(m); x[0] = 0.75; y = f.Forward(0, x); if ( options == "" ) ok &= f.compare_change_number() == 0; fun(options, x, check, before, after); ok &= NearEqual(y[0], check[0], eps10, eps10); // Check case where result of the comparision is differnent // (hence one needs to re-tape to get correct result) x[0] = 2.0; y = f.Forward(0, x); if ( options == "" ) ok &= f.compare_change_number() == 1; fun(options, x, check, before, after); ok &= std::fabs(y[0] - check[0]) > 0.5; } return ok; }
bool OdeErrControl_two(void) { bool ok = true; // initial return value using CppAD::NearEqual; CppAD::vector<double> w(2); w[0] = 10.; w[1] = 1.; Method_two method(w); CppAD::vector<double> xi(2); xi[0] = 1.; xi[1] = 0.; CppAD::vector<double> eabs(2); eabs[0] = 1e-4; eabs[1] = 1e-4; // inputs double ti = 0.; double tf = 1.; double smin = 1e-4; double smax = 1.; double scur = .5; double erel = 0.; // outputs CppAD::vector<double> ef(2); CppAD::vector<double> xf(2); CppAD::vector<double> maxabs(2); size_t nstep; xf = OdeErrControl(method, ti, tf, xi, smin, smax, scur, eabs, erel, ef, maxabs, nstep); double x0 = exp(-w[0]*tf); ok &= NearEqual(x0, xf[0], 1e-4, 1e-4); ok &= NearEqual(0., ef[0], 1e-4, 1e-4); double x1 = w[0] * (exp(-w[0]*tf) - exp(-w[1]*tf))/(w[1] - w[0]); ok &= NearEqual(x1, xf[1], 1e-4, 1e-4); ok &= NearEqual(0., ef[1], 1e-4, 1e-4); return ok; }
bool std_math(void) { using CppAD::NearEqual; bool ok = true; ADDdouble half = .5; ADDdouble one = 1.; ADDdouble two = 2.; ADDdouble ten = 10.; ADDdouble small = 1e-6; ADDdouble pi_4 = 3.141592653 / 4.; ADDdouble root_2 = sqrt(two); ADDdouble y = acos(one / root_2); ok &= NearEqual( pi_4, y, small, small ); y = cos(pi_4); ok &= NearEqual( one / root_2, y, small, small ); y = asin(one / root_2); ok &= NearEqual( pi_4, y, small, small ); y = sin(pi_4); ok &= NearEqual( one / root_2, y, small, small ); y = atan(one); ok &= NearEqual( pi_4, y, small, small ); y = tan(pi_4); ok &= NearEqual( one, y, small, small ); y = two * cosh(one); ok &= NearEqual( exp(one) + exp(-one), y, small, small ); y = two * sinh(one); ok &= NearEqual( exp(one) - exp(-one), y, small, small ); y = log( exp(one) ); ok &= NearEqual( one, y, small, small ); y = log10( exp( log(ten) ) ); ok &= NearEqual( one, y, small, small ); return ok; }
bool RevTwo() { bool ok = true; using CppAD::AD; using CppAD::vector; using CppAD::NearEqual; size_t n = 2; vector< AD<double> > X(n); X[0] = 1.; X[1] = 1.; Independent(X); size_t m = 1; vector< AD<double> > Y(m); Y[0] = X[0] * X[0] + X[0] * X[1] + 2. * X[1] * X[1]; CppAD::ADFun<double> F(X,Y); vector<double> x(n); x[0] = .5; x[1] = 1.5; size_t L = 1; vector<size_t> I(L); vector<size_t> J(L); vector<double> H(n); I[0] = 0; J[0] = 0; H = F.RevTwo(x, I, J); ok &= NearEqual(H[0], 2., 1e-10, 1e-10); ok &= NearEqual(H[1], 1., 1e-10, 1e-10); J[0] = 1; H = F.RevTwo(x, I, J); ok &= NearEqual(H[0], 1., 1e-10, 1e-10); ok &= NearEqual(H[1], 4., 1e-10, 1e-10); return ok; }
bool sparse_jac_fun(void) { using CppAD::NearEqual; using CppAD::AD; bool ok = true; size_t j, k; double eps = CppAD::numeric_limits<double>::epsilon(); size_t n = 3; size_t m = 4; size_t K = 5; CppAD::vector<size_t> row(K), col(K); CppAD::vector<double> x(n), yp(K); CppAD::vector< AD<double> > a_x(n), a_y(m); // choose x for(j = 0; j < n; j++) a_x[j] = x[j] = double(j + 1); // choose row, col for(k = 0; k < K; k++) { row[k] = k % m; col[k] = (K - k) % n; } // declare independent variables Independent(a_x); // evaluate function size_t order = 0; CppAD::sparse_jac_fun< AD<double> >(m, n, a_x, row, col, order, a_y); // evaluate derivative order = 1; CppAD::sparse_jac_fun<double>(m, n, x, row, col, order, yp); // use AD to evaluate derivative CppAD::ADFun<double> f(a_x, a_y); CppAD::vector<double> jac(m * n); jac = f.Jacobian(x); for(k = 0; k < K; k++) { size_t index = row[k] * n + col[k]; ok &= NearEqual(jac[index], yp[k] , eps, eps); } return ok; }
bool eigen_array(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; using Eigen::Matrix; using Eigen::Dynamic; // typedef Matrix< AD<double> , Dynamic, 1 > a_vector; // // some temporary indices size_t i, j; // domain and range space vectors size_t n = 10, m = n; a_vector a_x(n), a_y(m); // set and declare independent variables and start tape recording for(j = 0; j < n; j++) a_x[j] = double(1 + j); CppAD::Independent(a_x); // evaluate a component wise function a_y = a_x.array() + a_x.array().sin(); // create f: x -> y and stop tape recording CppAD::ADFun<double> f(a_x, a_y); // compute the derivative of y w.r.t x using CppAD CPPAD_TESTVECTOR(double) x(n); for(j = 0; j < n; j++) x[j] = double(j) + 1.0 / double(j+1); CPPAD_TESTVECTOR(double) jac = f.Jacobian(x); // check Jacobian double eps = 100. * CppAD::numeric_limits<double>::epsilon(); for(i = 0; i < m; i++) { for(j = 0; j < n; j++) { double check = 1.0 + cos(x[i]); if( i != j ) check = 0.0; ok &= NearEqual(jac[i * n + j], check, eps, eps); } } return ok; }
bool OdeErrControl_one(void) { bool ok = true; // initial return value using CppAD::NearEqual; // Runge45 should yield exact results for x_i (t) = t^(i+1), i < 4 size_t n = 6; // construct method for n component solution Method_one method(n); // inputs to OdeErrControl double ti = 0.; double tf = .9; double smin = 1e-2; double smax = 1.; double scur = .5; double erel = 1e-7; CppAD::vector<double> xi(n); CppAD::vector<double> eabs(n); size_t i; for(i = 0; i < n; i++) { xi[i] = 0.; eabs[i] = 0.; } // outputs from OdeErrControl CppAD::vector<double> ef(n); CppAD::vector<double> xf(n); xf = OdeErrControl(method, ti, tf, xi, smin, smax, scur, eabs, erel, ef); double check = 1.; for(i = 0; i < n; i++) { check *= tf; ok &= NearEqual(check, xf[i], erel, 0.); } return ok; }
bool ode_evaluate(void) { using CppAD::NearEqual; using CppAD::AD; bool ok = true; size_t n = 3; CppAD::vector<double> x(n); CppAD::vector<double> ym(n * n); CppAD::vector< AD<double> > X(n); CppAD::vector< AD<double> > Ym(n); // choose x size_t j; for(j = 0; j < n; j++) { x[j] = double(j + 1); X[j] = x[j]; } // declare independent variables Independent(X); // evaluate function size_t m = 0; CppAD::ode_evaluate(X, m, Ym); // evaluate derivative m = 1; CppAD::ode_evaluate(x, m, ym); // use AD to evaluate derivative CppAD::ADFun<double> F(X, Ym); CppAD::vector<double> dy(n * n); dy = F.Jacobian(x); size_t k; for(k = 0; k < n * n; k++) ok &= NearEqual(ym[k], dy[k] , 1e-7, 1e-7); return ok; }
bool NearEqualExt(void) { bool ok = true; using CppAD::AD; using CppAD::NearEqual; // double double x = 1.00000; double y = 1.00001; double a = .00005; double r = .00005; double zero = 0.; // AD<double> AD<double> ax(x); AD<double> ay(y); ok &= NearEqual(ax, ay, zero, a); ok &= NearEqual(ax, y, r, zero); ok &= NearEqual(x, ay, r, a); // std::complex<double> AD<double> cx(x); AD<double> cy(y); // AD< std::complex<double> > AD<double> acx(x); AD<double> acy(y); ok &= NearEqual(acx, acy, zero, a); ok &= NearEqual(acx, cy, r, zero); ok &= NearEqual(acx, y, r, a); ok &= NearEqual( cx, acy, r, a); ok &= NearEqual( x, acy, r, a); return ok; }
bool StackMachine(void) { bool ok = true; using std::string; using std::stack; using CppAD::AD; using CppAD::NearEqual; using CppAD::vector; // The users program in that stack machine language const char *program[] = { "1.0", "a", "+", "=", "b", // b = a + 1 "2.0", "b", "*", "=", "c", // c = b * 2 "3.0", "c", "-", "=", "d", // d = c - 3 "4.0", "d", "/", "=", "e" // e = d / 4 }; size_t n_program = sizeof( program ) / sizeof( program[0] ); // put the program in the token stack stack< string > token_stack; size_t i = n_program; while(i--) token_stack.push( program[i] ); // domain space vector size_t n = 1; vector< AD<double> > X(n); X[0] = 0.; // declare independent variables and start tape recording CppAD::Independent(X); // x[0] corresponds to a in the stack machine vector< AD<double> > variable(26); variable[0] = X[0]; // calculate the resutls of the program StackMachine( token_stack , variable); // range space vector size_t m = 4; vector< AD<double> > Y(m); Y[0] = variable[1]; // b = a + 1 Y[1] = variable[2]; // c = (a + 1) * 2 Y[2] = variable[3]; // d = (a + 1) * 2 - 3 Y[3] = variable[4]; // e = ( (a + 1) * 2 - 3 ) / 4 // create f : X -> Y and stop tape recording CppAD::ADFun<double> f(X, Y); // use forward mode to evaluate function at different argument value size_t p = 0; vector<double> x(n); vector<double> y(m); x[0] = 1.; y = f.Forward(p, x); // check function values ok &= (y[0] == x[0] + 1.); ok &= (y[1] == (x[0] + 1.) * 2.); ok &= (y[2] == (x[0] + 1.) * 2. - 3.); ok &= (y[3] == ( (x[0] + 1.) * 2. - 3.) / 4.); // Use forward mode (because x is shorter than y) to calculate Jacobian p = 1; vector<double> dx(n); vector<double> dy(m); dx[0] = 1.; dy = f.Forward(p, dx); ok &= NearEqual(dy[0], 1., 1e-10, 1e-10); ok &= NearEqual(dy[1], 2., 1e-10, 1e-10); ok &= NearEqual(dy[2], 2., 1e-10, 1e-10); ok &= NearEqual(dy[3], .5, 1e-10, 1e-10); // Use Jacobian routine (which automatically decides which mode to use) dy = f.Jacobian(x); ok &= NearEqual(dy[0], 1., 1e-10, 1e-10); ok &= NearEqual(dy[1], 2., 1e-10, 1e-10); ok &= NearEqual(dy[2], 2., 1e-10, 1e-10); ok &= NearEqual(dy[3], .5, 1e-10, 1e-10); return ok; }