TEST(AgradRevMatrix, trace_gen_quad_form_mat_grad_vdd) { using stan::math::trace_gen_quad_form; using stan::math::sum; using stan::agrad::matrix_v; using stan::math::matrix_d; matrix_v av(4,4); matrix_d ad(4,4); matrix_d bd(4,2); matrix_v bv(4,2); matrix_d cd(2,2); matrix_v cv(2,2); AVAR res; AVEC vars; VEC grad; size_t i,j,pos; bd << 100, 10, 0, 1, -3, -3, 5, 2; bv << 100, 10, 0, 1, -3, -3, 5, 2; ad << 2.0, 3.0, 4.0, 5.0, 6.0, 10.0, 2.0, 2.0, 7.0, 2.0, 7.0, 1.0, 8.0, 2.0, 1.0, 112.0; av << 2.0, 3.0, 4.0, 5.0, 6.0, 10.0, 2.0, 2.0, 7.0, 2.0, 7.0, 1.0, 8.0, 2.0, 1.0, 112.0; cd.setIdentity(2,2); cv.setIdentity(2,2); matrix_d dqdc(bd.transpose()*ad.transpose()*bd); res = trace_gen_quad_form(cv,ad,bd); vars.clear(); for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) vars.push_back(cv(i,j)); grad = cgradvec(res,vars); pos = 0; for (i = 0; i < 2; i++) for (j = 0; j < 2; j++, pos++) EXPECT_FLOAT_EQ(grad[pos], dqdc(i,j)); }
TEST(AgradRevMatrix, trace_gen_inv_quad_form_ldlt_grad_ddv) { using stan::math::sum; using stan::agrad::matrix_v; using stan::math::matrix_d; matrix_d ad(4,4); matrix_d bd(4,2); matrix_v bv(4,2); matrix_d cd(2,2); AVAR res; AVEC vars; VEC grad; size_t i,j,pos; bd << 100, 10, 0, 1, -3, -3, 5, 2; bv << 100, 10, 0, 1, -3, -3, 5, 2; ad << 9.0, 3.0, 3.0, 3.0, 3.0, 10.0, 2.0, 2.0, 3.0, 2.0, 7.0, 1.0, 3.0, 2.0, 1.0, 112.0; cd.setIdentity(2,2); stan::math::LDLT_factor<double,-1,-1> ldlt_ad; ldlt_ad.compute(ad); ASSERT_TRUE(ldlt_ad.success()); matrix_d ainv(ad.inverse()); matrix_d dqdb(ainv*bd*cd.transpose() + ainv.transpose()*bd*cd); // var-var res = trace_gen_inv_quad_form_ldlt(cd,ldlt_ad,bv); vars.clear(); for (i = 0; i < 4; i++) for (j = 0; j < 2; j++) vars.push_back(bv(i,j)); grad = cgradvec(res,vars); pos = 0; for (i = 0; i < 4; i++) for (j = 0; j < 2; j++, pos++) EXPECT_FLOAT_EQ(grad[pos], dqdb(i,j)); }
TEST(AgradRevMatrix, trace_quad_form_ldlt_mat_grad_vd) { using stan::math::sum; using stan::math::matrix_v; using stan::math::matrix_d; matrix_v av(4,4); matrix_d ad(4,4); matrix_d bd(4,2); AVAR res; AVEC vars; VEC grad; size_t i,j,pos; bd << 100, 10, 0, 1, -3, -3, 5, 2; ad << 9.0, 3.0, 3.0, 3.0, 3.0, 10.0, 2.0, 2.0, 3.0, 2.0, 7.0, 1.0, 3.0, 2.0, 1.0, 112.0; av << 9.0, 3.0, 3.0, 3.0, 3.0, 10.0, 2.0, 2.0, 3.0, 2.0, 7.0, 1.0, 3.0, 2.0, 1.0, 112.0; stan::math::LDLT_factor<stan::math::var,-1,-1> ldlt_av; ldlt_av.compute(av); ASSERT_TRUE(ldlt_av.success()); matrix_d ainv(ad.inverse()); matrix_d dqda(-ainv*bd*bd.transpose()*ainv); // var-var res = trace_inv_quad_form_ldlt(ldlt_av,bd); vars.clear(); for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) vars.push_back(av(i,j)); grad = cgradvec(res,vars); pos = 0; for (i = 0; i < 4; i++) for (j = 0; j < 4; j++, pos++) EXPECT_FLOAT_EQ(grad[pos], dqda(i,j)); }
TEST(AgradRevMatrix, quad_form_sym_vec_grad_vv) { using stan::math::quad_form_sym; using stan::agrad::matrix_v; using stan::agrad::vector_v; using stan::math::matrix_d; using stan::math::vector_d; matrix_v av(4,4); matrix_d ad(4,4); vector_d bd(4); vector_v bv(4); stan::agrad::var res; AVEC vars; VEC grad; size_t pos, i, j; bd << 100, 0, -3, 5; bv << 100, 0, -3, 5; ad << 2.0, 3.0, 4.0, 5.0, 3.0, 10.0, 2.0, 2.0, 4.0, 2.0, 7.0, 1.0, 5.0, 2.0, 1.0, 112.0; av << 2.0, 3.0, 4.0, 5.0, 3.0, 10.0, 2.0, 2.0, 4.0, 2.0, 7.0, 1.0, 5.0, 2.0, 1.0, 112.0; matrix_d dqda(bd*bd.transpose()); vector_d dqdb(ad*bd + ad.transpose()*bd); // var-var res = quad_form_sym(av,bv); vars.clear(); for (size_t i = 0; i < 4; i++) vars.push_back(bv[i]); for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) vars.push_back(av(i,j)); grad = cgradvec(res,vars); for (i = 0, pos = 0; i < 4; i++, pos++) EXPECT_FLOAT_EQ(grad[pos], dqdb[i]); for (i = 0; i < 4; i++) for (j = 0; j < 4; j++, pos++) EXPECT_FLOAT_EQ(grad[pos], dqda(i,j)); }
TEST(AgradRevMatrix, quad_form_mat_grad_vd) { using stan::math::quad_form; using stan::math::sum; using stan::agrad::matrix_v; using stan::math::matrix_d; matrix_v av(4,4); matrix_d ad(4,4); matrix_d bd(4,2); AVAR res; AVEC vars; VEC grad; size_t i,j,pos; bd << 100, 10, 0, 1, -3, -3, 5, 2; ad << 2.0, 3.0, 4.0, 5.0, 6.0, 10.0, 2.0, 2.0, 7.0, 2.0, 7.0, 1.0, 8.0, 2.0, 1.0, 112.0; av << 2.0, 3.0, 4.0, 5.0, 6.0, 10.0, 2.0, 2.0, 7.0, 2.0, 7.0, 1.0, 8.0, 2.0, 1.0, 112.0; matrix_d dqda(bd*matrix_d::Ones(2,2)*bd.transpose()); // var-var res = sum(quad_form(av,bd)); vars.clear(); for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) vars.push_back(av(i,j)); grad = cgradvec(res,vars); pos = 0; for (i = 0; i < 4; i++) for (j = 0; j < 4; j++, pos++) EXPECT_FLOAT_EQ(grad[pos], dqda(i,j)); }
TEST(AgradRevMatrix, trace_gen_inv_quad_form_ldlt_grad_vvv_basic) { using stan::math::sum; using stan::agrad::matrix_v; using stan::math::matrix_d; using stan::math::inverse; using stan::math::multiply; using stan::math::trace; using stan::math::transpose; matrix_v cv(2,2); matrix_v av(4,4); matrix_v bv(4,2); AVAR result, result_basic; double result_val, result_basic_val; AVEC vars; VEC grad, grad_basic; size_t i,j; stan::math::LDLT_factor<stan::agrad::var,-1,-1> ldlt_av; // calculate gradient using trace_gen_inv_quad_form_ldlt bv << 100, 10, 0, 1, -3, -3, 5, 2; av << 9.0, 3.0, 3.0, 3.0, 3.0, 10.0, 2.0, 2.0, 3.0, 2.0, 7.0, 1.0, 3.0, 2.0, 1.0, 112.0; cv << 1, 2, 3, 4; ldlt_av.compute(av); ASSERT_TRUE(ldlt_av.success()); result = trace_gen_inv_quad_form_ldlt(cv,ldlt_av,bv); vars.clear(); for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) vars.push_back(cv(i,j)); for (i = 0; i < 4; i++) for (j = 0; j < 2; j++) vars.push_back(bv(i,j)); for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) vars.push_back(av(i,j)); grad = cgradvec(result,vars); result_val = result.val(); // calculate gradient using basic math bv << 100, 10, 0, 1, -3, -3, 5, 2; av << 9.0, 3.0, 3.0, 3.0, 3.0, 10.0, 2.0, 2.0, 3.0, 2.0, 7.0, 1.0, 3.0, 2.0, 1.0, 112.0; cv << 1, 2, 3, 4; matrix_v tmp = bv.transpose() * inverse(av) * bv; matrix_v gen_inv_quad_form = multiply(cv, tmp); result_basic = trace(gen_inv_quad_form); vars.clear(); for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) vars.push_back(cv(i,j)); for (i = 0; i < 4; i++) for (j = 0; j < 2; j++) vars.push_back(bv(i,j)); for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) vars.push_back(av(i,j)); grad_basic = cgradvec(result_basic,vars); result_basic_val = result_basic.val(); // check values; EXPECT_FLOAT_EQ(result_basic_val, result_val); ASSERT_EQ(grad_basic.size(), grad.size()); for (size_t n = 0; n < grad_basic.size(); n++) { EXPECT_FLOAT_EQ(grad_basic[n], grad[n]); } }