Trouble adding a function of a vector with known gradients

I’m trying to add a function demo to Stan as a learning exercise. I’m struggling with adding a scalar function of a vector. I figure I’m missing something pretty fundamental, so any advice would be appreciated.

New function:

namespace foo {
    double foo(std::vector<double>& x) {
        return x[0] + x[1];
    }

    std::vector<double> grad_foo(std::vector<double>& x) {
        std::vector<double> v;
        v[0] = 1;
        v[1] = 1;
        return v;
    }
}

namespace stan {
    namespace math {

        double demo(std::vector<double>& x) {
            return foo::foo(x);
        }

        var demo(std::vector<var>& x) {
            std::vector<double> a = value_of(x); // x.val();
            double fa = foo::foo(a);
            std::vector<double> grad_fa = foo::grad_foo(a);
            return precomputed_gradients(fa, x, grad_fa);
        }

    }
}

Signature:

add("demo", bare_expr_type(double_type()), bare_expr_type(vector_type()));

Stan file:

data {
  int<lower=0> N;
  real alpha[N];
}
parameters {
  vector[2] alpha_est;
}
transformed parameters {
  real transformed_alpha;
  transformed_alpha = demo(alpha_est);
}
model {
  alpha_est[0] ~ normal(0,10);
  alpha_est[1] ~ normal(0,10);
  for (n in 1:N)
    alpha[n] ~ normal(transformed_alpha, 1);
}

I get the error:

./examples/demo/demo.hpp:289:51: error: no matching function for call to ‘demo’ stan::math::assign(transformed_alpha, demo(alpha_est));

Followed by several more lines of related error messaging. Thanks for any help!

Probably trivial but I’ve always seen additional namespaces such as you’re using foo included within stan and math. What is var wouldn’t you typically use return type of auto?

I had a misunderstanding of the relationship between std::vector in C++ and the Stan type vector. The Stan type vector maps on to the “Eigen” vector type. std::vector maps onto the Stan real[] type.

The fix was:

Signature:

add("demo", bare_expr_type(double_type()), bare_expr_type(bare_array_type(double_type(), 1)));

Stan file:

data {
  int<lower=0> N;
  real alpha[N];
}
parameters {
  real alpha_est[2];
}
transformed parameters {
  real transformed_alpha;
  transformed_alpha = demo(alpha_est);
}
model {
  alpha_est[1] ~ normal(0,10);
  alpha_est[2] ~ normal(0,10);
  for (n in 1:N)
    alpha[n] ~ normal(transformed_alpha, .1);
}
1 Like