#include <config.h>
#include <sampler/ConjugateWishart.h>
#include <sampler/ConjugateSampler.h>
#include <distributions/DWish.h>
#include <graph/LogicalNode.h>
#include <graph/StochasticNode.h>
#include <set>
#include <stdexcept>
#include <vector>
#include <cmath>
#include <Rmath.h>
using std::vector;
using std::set;
using std::sqrt;
using std::invalid_argument;
using std::logic_error;
ConjugateWishart::ConjugateWishart(StochasticNode *snode, Graph const &graph)
: ConjugateSampler(snode, graph)
{
if (!canSample(snode, graph)) {
throw invalid_argument("Can't construct ConjugateWishart sampler");
}
}
ConjugateWishart::~ConjugateWishart()
{
}
bool ConjugateWishart::canSample(StochasticNode *snode, Graph const &graph)
{
if (getDist(snode) != WISH)
return false;
if (snode->isBounded())
return false;
vector<StochasticNode const*> stoch_nodes;
vector<Node*> dtrm_nodes;
classifyChildren(vector<StochasticNode*>(1,snode),
graph, stoch_nodes, dtrm_nodes);
/*
Create a set of nodes containing snode and its deterministic
descendants for the checks below.
*/
set<SArray const *> paramset;
paramset.insert(&snode->data);
for (unsigned int j = 0; j < dtrm_nodes.size(); ++j) {
paramset.insert(&dtrm_nodes[j]->data);
}
// Check stochastic children
for (unsigned int i = 0; i < stoch_nodes.size(); ++i) {
vector<SArray const *> const ¶m = stoch_nodes[i]->parameters();
if (stoch_nodes[i]->isBounded()) {
return false; //Bounded
}
switch(getDist(stoch_nodes[i])) {
case MNORM:
if (paramset.count(param[0])) {
return false; //mean parameter depends on snode
}
break;
default:
return false;
}
}
// Only direct children are allowed
if (!dtrm_nodes.empty()) {
return false;
}
return true; //We made it!
}
void ConjugateWishart::update()
{
vector<StochasticNode const*> const &stoch_children = stochasticChildren();
unsigned int nchildren = stoch_children.size();
vector<SArray const *> const ¶m = node()->parameters();
double k = *param[1]->value();
double const *Rprior = param[0]->value();
int nrow = param[0]->dim(true)[0];
int N = nrow * nrow;
double *R = new double[N];
for (int i = 0; i < N; ++i) {
R[i] = Rprior[i];
}
double *delta = new double[nrow];
for (unsigned int i = 0; i < nchildren; ++i) {
StochasticNode const *schild = stoch_children[i];
if (_child_dist[i] != MNORM)
throw logic_error("Invalid distribution in Conjugate Wishart sampler");
vector<SArray const *> const &cparam = schild->parameters();
double const *Y = schild->data.value();
double const *mu = cparam[0]->value();
for (int j = 0; j < nrow; j++) {
delta[j] = Y[j] - mu[j];
}
for (int j = 0; j < nrow; j++) {
for (int l = 0; l < nrow; l++) {
R[j*nrow + l] += delta[j]*delta[l];
}
}
}
delete [] delta;
k += nchildren;
double *xnew = new double[N];
DWish::randomSample(xnew, N, R, k, nrow);
delete [] R;
setValue(xnew, N);
delete [] xnew;
}
syntax highlighted by Code2HTML, v. 0.9.1