Same error as before. Looking closely at part of the error
undefined reference to `boost::math::tools::promote_args<double, stan::math::var_value<double, void>, stan::math::var_value<double, void>, float, float, float>::type normal_test_model_namespace::new_normal_2_lpdf<false, double, stan::math::var_value<double, void>, stan::math::var_value<double, void> >(double const&, stan::math::var_value<double, void> const&, stan::math::var_value<double, void> const&, std::ostream*)'
it looks like its looking for new_normal_2_lpdf (which is what I called my function) in the normal_test_model_namespace namespace but unable to find it. So maybe I need to somehow make the function part of that namespace? however, the normal_test_model_namespace namespace isn’t currently defined within new_normal_2.hpp and I’m not sure how I would add it in
Here is my current hpp file with the new distribution function:
#ifndef NEW_NORMAL_2_LPDF_HPP
#define NEW_NORMAL_2_LPDF_HPP
#include <stan/math/prim.hpp>
//#include <stan/math/rev/core.hpp>
#include <stan/math.hpp>
inline stan::math::var new_normal_2_lpdf(const stan::math::var& y,
const stan::math::var& mu,
const stan::math::var& sigma,
std::ostream* pstream__){
// extract values (not derivatives of inputs)
double mu_val = mu.val();
double y_val = y.val();
double sigma_val = sigma.val();
double t0 = 1/sigma_val;
double t1 = t0 * t0;
double t2 = y_val - mu_val;
double t3 = t2 / t1;
double log_prob = -0.5 * t2 * t2 / t1 - std::log(sigma_val);
double df_dy = -t3;
double df_dmu = t3;
double df_dsigma = t2*t2/t1*t0 - t0;
return stan::math::var(new stan::math::precomp_vvv_vari(log_prob, y.vi_, mu.vi_, sigma.vi_, df_dy, df_dmu, df_dsigma));
}
#endif
Here is the stan model file
functions {
// real new_normal_2_lpdf(real y, real mu, real sigma){
// return -0.5 * pow((y - mu)/ sigma, 2) - log(sigma) - 0.5 * log(2*pi());
// }
real new_normal_2_lpdf(real y, real mu, real sigma);
}
data {
int <lower=0> N;
vector[N] x;
vector[N] y;
}
parameters {
real b;
real<lower=1e-6> r;
}
model {
r ~ cauchy(0, 1);
// y ~ normal(b * x, r);
for (n in 1:N){
target += new_normal_2_lpdf(y[n] | b * x[n], r);
}
}
I am compiling with the command
make STANCFLAGS=--allow-undefined USER_HEADER=~/git/cmdstan/new_normal_2.hpp normal_test
Here is the model hpp file that is being generated by stanc: Where it does look like the new_normal_2 function is defined inside the normal_test_model_namespace ?
// Code generated by stanc a8f502d5
#include <stan/model/model_header.hpp>
namespace normal_test_model_namespace {
using stan::io::dump;
using stan::model::assign;
using stan::model::index_uni;
using stan::model::index_max;
using stan::model::index_min;
using stan::model::index_min_max;
using stan::model::index_multi;
using stan::model::index_omni;
using stan::model::model_base_crtp;
using stan::model::rvalue;
using namespace stan::math;
stan::math::profile_map profiles__;
static constexpr std::array<const char*, 12> locations_array__ =
{" (found before start of program)",
" (in 'normal_test.stan', line 16, column 4 to column 11)",
" (in 'normal_test.stan', line 17, column 4 to column 23)",
" (in 'normal_test.stan', line 20, column 4 to column 21)",
" (in 'normal_test.stan', line 23, column 8 to column 56)",
" (in 'normal_test.stan', line 22, column 18 to line 24, column 5)",
" (in 'normal_test.stan', line 22, column 4 to line 24, column 5)",
" (in 'normal_test.stan', line 10, column 4 to column 20)",
" (in 'normal_test.stan', line 11, column 11 to column 12)",
" (in 'normal_test.stan', line 11, column 4 to column 16)",
" (in 'normal_test.stan', line 12, column 11 to column 12)",
" (in 'normal_test.stan', line 12, column 4 to column 16)"};
template <bool propto__, typename T0__, typename T1__, typename T2__>
stan::promote_args_t<T0__, T1__,
T2__>
new_normal_2_lpdf(const T0__& y, const T1__& mu, const T2__& sigma,
std::ostream* pstream__) ;
class normal_test_model final : public model_base_crtp<normal_test_model> {
private:
int N;
Eigen::Matrix<double, -1, 1> x__;
Eigen::Matrix<double, -1, 1> y__;
Eigen::Map<Eigen::Matrix<double, -1, 1>> x{nullptr, 0};
Eigen::Map<Eigen::Matrix<double, -1, 1>> y{nullptr, 0};
public:
~normal_test_model() { }
inline std::string model_name() const final { return "normal_test_model"; }
inline std::vector<std::string> model_compile_info() const noexcept {
return std::vector<std::string>{"stanc_version = stanc3 a8f502d5", "stancflags = --allow-undefined"};
}
normal_test_model(stan::io::var_context& context__,
unsigned int random_seed__ = 0,
std::ostream* pstream__ = nullptr) : model_base_crtp(0) {
int current_statement__ = 0;
using local_scalar_t__ = double ;
boost::ecuyer1988 base_rng__ =
stan::services::util::create_rng(random_seed__, 0);
(void) base_rng__; // suppress unused var warning
static constexpr const char* function__ = "normal_test_model_namespace::normal_test_model";
(void) function__; // suppress unused var warning
local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
(void) DUMMY_VAR__; // suppress unused var warning
try {
int pos__;
pos__ = 1;
current_statement__ = 7;
context__.validate_dims("data initialization","N","int",
std::vector<size_t>{});
N = std::numeric_limits<int>::min();
current_statement__ = 7;
N = context__.vals_i("N")[(1 - 1)];
current_statement__ = 7;
check_greater_or_equal(function__, "N", N, 0);
current_statement__ = 8;
validate_non_negative_index("x", "N", N);
current_statement__ = 9;
context__.validate_dims("data initialization","x","double",
std::vector<size_t>{static_cast<size_t>(N)});
x__ = Eigen::Matrix<double, -1, 1>(N);
new (&x) Eigen::Map<Eigen::Matrix<double, -1, 1>>(x__.data(), N);
{
std::vector<local_scalar_t__> x_flat__;
current_statement__ = 9;
x_flat__ = context__.vals_r("x");
current_statement__ = 9;
pos__ = 1;
current_statement__ = 9;
for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
current_statement__ = 9;
assign(x, x_flat__[(pos__ - 1)],
"assigning variable x", index_uni(sym1__));
current_statement__ = 9;
pos__ = (pos__ + 1);
}
}
current_statement__ = 10;
validate_non_negative_index("y", "N", N);
current_statement__ = 11;
context__.validate_dims("data initialization","y","double",
std::vector<size_t>{static_cast<size_t>(N)});
y__ = Eigen::Matrix<double, -1, 1>(N);
new (&y) Eigen::Map<Eigen::Matrix<double, -1, 1>>(y__.data(), N);
{
std::vector<local_scalar_t__> y_flat__;
current_statement__ = 11;
y_flat__ = context__.vals_r("y");
current_statement__ = 11;
pos__ = 1;
current_statement__ = 11;
for (int sym1__ = 1; sym1__ <= N; ++sym1__) {
current_statement__ = 11;
assign(y, y_flat__[(pos__ - 1)],
"assigning variable y", index_uni(sym1__));
current_statement__ = 11;
pos__ = (pos__ + 1);
}
}
} catch (const std::exception& e) {
stan::lang::rethrow_located(e, locations_array__[current_statement__]);
}
num_params_r__ = 1 + 1;
}
template <bool propto__, bool jacobian__ , typename VecR, typename VecI,
stan::require_vector_like_t<VecR>* = nullptr,
stan::require_vector_like_vt<std::is_integral, VecI>* = nullptr>
inline stan::scalar_type_t<VecR> log_prob_impl(VecR& params_r__,
VecI& params_i__,
std::ostream* pstream__ = nullptr) const {
using T__ = stan::scalar_type_t<VecR>;
using local_scalar_t__ = T__;
T__ lp__(0.0);
stan::math::accumulator<T__> lp_accum__;
stan::io::deserializer<local_scalar_t__> in__(params_r__, params_i__);
int current_statement__ = 0;
local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
(void) DUMMY_VAR__; // suppress unused var warning
static constexpr const char* function__ = "normal_test_model_namespace::log_prob";
(void) function__; // suppress unused var warning
try {
local_scalar_t__ b;
current_statement__ = 1;
b = in__.template read<local_scalar_t__>();
local_scalar_t__ r;
current_statement__ = 2;
r = in__.template read_constrain_lb<local_scalar_t__, jacobian__>(1e-6,
lp__);
{
current_statement__ = 3;
lp_accum__.add(cauchy_lpdf<propto__>(r, 0, 1));
current_statement__ = 6;
for (int n = 1; n <= N; ++n) {
current_statement__ = 4;
lp_accum__.add(
new_normal_2_lpdf<false>(rvalue(y, "y", index_uni(n)),
(b * rvalue(x, "x", index_uni(n))), r, pstream__));
}
}
} catch (const std::exception& e) {
stan::lang::rethrow_located(e, locations_array__[current_statement__]);
}
lp_accum__.add(lp__);
return lp_accum__.sum();
} // log_prob_impl()
template <typename RNG, typename VecR, typename VecI, typename VecVar,
stan::require_vector_like_vt<std::is_floating_point, VecR>* = nullptr,
stan::require_vector_like_vt<std::is_integral, VecI>* = nullptr,
stan::require_std_vector_vt<std::is_floating_point, VecVar>* = nullptr>
inline void write_array_impl(RNG& base_rng__, VecR& params_r__,
VecI& params_i__, VecVar& vars__,
const bool emit_transformed_parameters__ = true,
const bool emit_generated_quantities__ = true,
std::ostream* pstream__ = nullptr) const {
using local_scalar_t__ = double;
stan::io::deserializer<local_scalar_t__> in__(params_r__, params_i__);
stan::io::serializer<local_scalar_t__> out__(vars__);
static constexpr bool propto__ = true;
(void) propto__;
double lp__ = 0.0;
(void) lp__; // dummy to suppress unused var warning
int current_statement__ = 0;
stan::math::accumulator<double> lp_accum__;
local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
constexpr bool jacobian__ = false;
(void) DUMMY_VAR__; // suppress unused var warning
static constexpr const char* function__ = "normal_test_model_namespace::write_array";
(void) function__; // suppress unused var warning
try {
double b;
current_statement__ = 1;
b = in__.template read<local_scalar_t__>();
double r;
current_statement__ = 2;
r = in__.template read_constrain_lb<local_scalar_t__, jacobian__>(1e-6,
lp__);
out__.write(b);
out__.write(r);
if (logical_negation((primitive_value(emit_transformed_parameters__) ||
primitive_value(emit_generated_quantities__)))) {
return ;
}
if (logical_negation(emit_generated_quantities__)) {
return ;
}
} catch (const std::exception& e) {
stan::lang::rethrow_located(e, locations_array__[current_statement__]);
}
} // write_array_impl()
template <typename VecVar, typename VecI,
stan::require_std_vector_t<VecVar>* = nullptr,
stan::require_vector_like_vt<std::is_integral, VecI>* = nullptr>
inline void transform_inits_impl(VecVar& params_r__, VecI& params_i__,
VecVar& vars__,
std::ostream* pstream__ = nullptr) const {
using local_scalar_t__ = double;
stan::io::deserializer<local_scalar_t__> in__(params_r__, params_i__);
stan::io::serializer<local_scalar_t__> out__(vars__);
int current_statement__ = 0;
local_scalar_t__ DUMMY_VAR__(std::numeric_limits<double>::quiet_NaN());
try {
int pos__;
pos__ = 1;
local_scalar_t__ b;
b = in__.read<local_scalar_t__>();
out__.write(b);
local_scalar_t__ r;
r = in__.read<local_scalar_t__>();
out__.write_free_lb(1e-6, r);
} catch (const std::exception& e) {
stan::lang::rethrow_located(e, locations_array__[current_statement__]);
}
} // transform_inits_impl()
inline void get_param_names(std::vector<std::string>& names__) const {
names__ = std::vector<std::string>{"b", "r"};
} // get_param_names()
inline void get_dims(std::vector<std::vector<size_t>>& dimss__) const {
dimss__ = std::vector<std::vector<size_t>>{std::vector<size_t>{},
std::vector<size_t>{}};
} // get_dims()
inline void constrained_param_names(
std::vector<std::string>& param_names__,
bool emit_transformed_parameters__ = true,
bool emit_generated_quantities__ = true) const
final {
param_names__.emplace_back(std::string() + "b");
param_names__.emplace_back(std::string() + "r");
if (emit_transformed_parameters__) {
}
if (emit_generated_quantities__) {
}
} // constrained_param_names()
inline void unconstrained_param_names(
std::vector<std::string>& param_names__,
bool emit_transformed_parameters__ = true,
bool emit_generated_quantities__ = true) const
final {
param_names__.emplace_back(std::string() + "b");
param_names__.emplace_back(std::string() + "r");
if (emit_transformed_parameters__) {
}
if (emit_generated_quantities__) {
}
} // unconstrained_param_names()
inline std::string get_constrained_sizedtypes() const {
return std::string("[{\"name\":\"b\",\"type\":{\"name\":\"real\"},\"block\":\"parameters\"},{\"name\":\"r\",\"type\":{\"name\":\"real\"},\"block\":\"parameters\"}]");
} // get_constrained_sizedtypes()
inline std::string get_unconstrained_sizedtypes() const {
return std::string("[{\"name\":\"b\",\"type\":{\"name\":\"real\"},\"block\":\"parameters\"},{\"name\":\"r\",\"type\":{\"name\":\"real\"},\"block\":\"parameters\"}]");
} // get_unconstrained_sizedtypes()
// Begin method overload boilerplate
template <typename RNG>
inline void write_array(RNG& base_rng,
Eigen::Matrix<double,Eigen::Dynamic,1>& params_r,
Eigen::Matrix<double,Eigen::Dynamic,1>& vars,
const bool emit_transformed_parameters = true,
const bool emit_generated_quantities = true,
std::ostream* pstream = nullptr) const {
const size_t num_params__ =
(1 + 1);
const size_t num_transformed = 0;
const size_t num_gen_quantities = 0;
std::vector<double> vars_vec(num_params__
+ (emit_transformed_parameters * num_transformed)
+ (emit_generated_quantities * num_gen_quantities));
std::vector<int> params_i;
write_array_impl(base_rng, params_r, params_i, vars_vec,
emit_transformed_parameters, emit_generated_quantities, pstream);
vars = Eigen::Map<Eigen::Matrix<double,Eigen::Dynamic,1>>(
vars_vec.data(), vars_vec.size());
}
template <typename RNG>
inline void write_array(RNG& base_rng, std::vector<double>& params_r,
std::vector<int>& params_i,
std::vector<double>& vars,
bool emit_transformed_parameters = true,
bool emit_generated_quantities = true,
std::ostream* pstream = nullptr) const {
const size_t num_params__ =
(1 + 1);
const size_t num_transformed = 0;
const size_t num_gen_quantities = 0;
vars.resize(num_params__
+ (emit_transformed_parameters * num_transformed)
+ (emit_generated_quantities * num_gen_quantities));
write_array_impl(base_rng, params_r, params_i, vars, emit_transformed_parameters, emit_generated_quantities, pstream);
}
template <bool propto__, bool jacobian__, typename T_>
inline T_ log_prob(Eigen::Matrix<T_,Eigen::Dynamic,1>& params_r,
std::ostream* pstream = nullptr) const {
Eigen::Matrix<int, -1, 1> params_i;
return log_prob_impl<propto__, jacobian__>(params_r, params_i, pstream);
}
template <bool propto__, bool jacobian__, typename T__>
inline T__ log_prob(std::vector<T__>& params_r,
std::vector<int>& params_i,
std::ostream* pstream = nullptr) const {
return log_prob_impl<propto__, jacobian__>(params_r, params_i, pstream);
}
inline void transform_inits(const stan::io::var_context& context,
Eigen::Matrix<double, Eigen::Dynamic, 1>& params_r,
std::ostream* pstream = nullptr) const final {
std::vector<double> params_r_vec(params_r.size());
std::vector<int> params_i;
transform_inits(context, params_i, params_r_vec, pstream);
params_r = Eigen::Map<Eigen::Matrix<double,Eigen::Dynamic,1>>(
params_r_vec.data(), params_r_vec.size());
}
inline void transform_inits(const stan::io::var_context& context,
std::vector<int>& params_i,
std::vector<double>& vars,
std::ostream* pstream__ = nullptr) const {
constexpr std::array<const char*, 2> names__{"b", "r"};
const std::array<Eigen::Index, 2> num_params__{1, 1};
std::vector<double> params_r_flat__(num_params_r__);
Eigen::Index size_iter__ = 0;
Eigen::Index flat_iter__ = 0;
for (auto&& param_name__ : names__) {
const auto param_vec__ = context.vals_r(param_name__);
for (Eigen::Index i = 0; i < num_params__[size_iter__]; ++i) {
params_r_flat__[flat_iter__] = param_vec__[i];
++flat_iter__;
}
++size_iter__;
}
vars.resize(params_r_flat__.size());
transform_inits_impl(params_r_flat__, params_i, vars, pstream__);
} // transform_inits()
};
}
using stan_model = normal_test_model_namespace::normal_test_model;
#ifndef USING_R
// Boilerplate
stan::model::model_base& new_model(
stan::io::var_context& data_context,
unsigned int seed,
std::ostream* msg_stream) {
stan_model* m = new stan_model(data_context, seed, msg_stream);
return *m;
}
stan::math::profile_map& get_stan_profile_data() {
return normal_test_model_namespace::profiles__;
}
#endif
EDIT: @maxbiostat struggled to get the syntax highlighting to work in this post.