Description
From @rtrangucci on January 21, 2015 1:15
the test_gradients test in test_fixture_distr.hpp, test_fixture_cdf.hpp, test_fixture_cdf_log.hpp and test_fixture_ccdf_log.hpp is broken.
The test_gradients in test_fixture_distr.hpp is intended to test a density's implementation of partials with an autodiffed naive implementation of the density. However, due to the current pattern, the test always passes. To verify this, change line 87 in stan/src/test/unit-distribution/univariate/continuous/normal/normal_test.hpp from:
return -0.5 * (y - mu) * (y - mu) / (sigma * sigma)
to:
return -0.5 * (y - mu) * (y - mu) / (sigma * sigma) * 100
and run:
./runTests.py -j2 src/test/unit-distribution/univariate/continuous/normal/normal_00000_generated_v_test.cpp
noting that the "Function" tests for v32 and v36 pass when they shouldn't. The problematic section in test_fixture_distr.hpp are lines 522-552:
Scalar0 p0 = get_param<Scalar0>(parameters[n], 0);
Scalar1 p1 = get_param<Scalar1>(parameters[n], 1);
Scalar2 p2 = get_param<Scalar2>(parameters[n], 2);
Scalar3 p3 = get_param<Scalar3>(parameters[n], 3);
Scalar4 p4 = get_param<Scalar4>(parameters[n], 4);
Scalar5 p5 = get_param<Scalar5>(parameters[n], 5);
vector<var> x1;
vector<var> x2;
vector<var> x3;
vector<var> y1;
vector<var> y2;
vector<var> y3;
add_vars(x1, p0, p1, p2, p3, p4, p5);
add_vars(x2, p0, p1, p2, p3, p4, p5);
add_vars(x3, p0, p1, p2, p3, p4, p5);
add_vars(y1, p0, p1, p2, p3, p4, p5);
add_vars(y2, p0, p1, p2, p3, p4, p5);
add_vars(y3, p0, p1, p2, p3, p4, p5);
T_return_type logprob = TestClass.template log_prob
<Scalar0,Scalar1,Scalar2,Scalar3,Scalar4,Scalar5>
(p0,p1,p2,p3,p4,p5);
T_return_type logprob_funct = TestClass.template log_prob_function
<Scalar0,Scalar1,Scalar2,Scalar3,Scalar4,Scalar5>
(p0,p1,p2,p3,p4,p5);
calculate_gradients_1storder(expected_gradients1, logprob_funct, x1);
calculate_gradients_1storder(gradients1, logprob, y1);
The reason the tests pass is because calculate_gradients_1storder in stan/src/test/unit-distribution/test_fixture_distr.hpp calls stan::agrad::recover_memory()
and the naive implementation and the density function are called with the same vars. y1 and x1 point to the same varis, whose adjoints are updated when calculate_gradients_1storder is called the first time.
The fix is to change the order of how calculate_gradients is called and how vars are created for the naive implementation vs. the stan::prob densities within test_gradients.
Copied from original issue: stan-dev/stan#1224