#include #include #include #include #include #include #include #include #include #include #include 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 stoch_nodes; vector dtrm_nodes; classifyChildren(vector(1,snode), graph, stoch_nodes, dtrm_nodes); /* Create a set of nodes containing snode and its deterministic descendants for the checks below. */ set 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 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 const &stoch_children = stochasticChildren(); unsigned int nchildren = stoch_children.size(); vector 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 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; }