#include #include #include #include #include #include #include #include #include //#include using std::vector; using std::string; //using std::logic_error; StochasticNode::StochasticNode(Distribution const *dist, Index const &dim) : Node(dim), _dist(dist), _parameters() { if (dist->isDiscreteValued()) { data.setDiscreteValued(true); } } StochasticNode::~StochasticNode() { } bool StochasticNode::isBounded() const { if (_parameters.empty()) { return false; } else { return _dist->lowerBound(_parameters) || _dist->upperBound(_parameters); } } SArray const *StochasticNode::lowerBound() { return _dist->lowerBound(_parameters); } SArray const *StochasticNode::upperBound() { return _dist->upperBound(_parameters); } void StochasticNode::setBounds(Node *lBound, Node *uBound) { Index const &dim = data.dim(true); if (!_dist->canBound()) { throw NodeError(this, string("Distribution ") + _dist->name() + " cannot be bounded"); } if (_parameters.empty()) { throw NodeError(this, "Cannot set bounds before parameters"); } if ((lBound && lBound->data.dim(true) != dim) || (uBound && uBound->data.dim(true) != dim)) { throw NodeError(this,"Dimension mismatch when setting bounds"); } if (lBound) { SArray const *lb = _parameters[_parameters.size() - 2]; if (lb != 0) { throw NodeError(this, "Attempt to reset lower bound"); } _parameters[_parameters.size() - 2] = &lBound->data; addParent(lBound); } if (uBound) { SArray const *ub = _parameters[_parameters.size() - 1]; if (ub != 0) { throw NodeError(this, "Attempt to reset upper bound"); } _parameters[_parameters.size() - 1] = &uBound->data; addParent(uBound); } } Distribution const *StochasticNode::distribution() const { return _dist; } void StochasticNode::setParameters(vector const ¶meters) { if (_parameters.size() != 0) { throw NodeError(this, "Attempt to reset parameters"); } for (unsigned int i = 0; i < parameters.size(); ++i) { _parameters.push_back(&(parameters[i]->data)); this->addParent(parameters[i]); } // Push back zeros for the upper and lower bounds if (_dist->canBound()) { _parameters.push_back(0); _parameters.push_back(0); } if (_parameters.size() != _dist->npar()) { throw NodeError(this, "Incorrect number of parameters for distribution"); } if (!_dist->checkParameterDim(_parameters)) { throw NodeError(this,"Invalid parameter dimensions for distribution"); } if (_dist->dim(_parameters) != data.dim(true)) { throw NodeError(this, "Dimension mismatch between parameters and Node"); } } double StochasticNode::logDensity() const { return _dist->logLikelihood(data, _parameters); } vector const &StochasticNode::parameters() const { return _parameters; } void StochasticNode::forwardSample() { _dist->randomSample(data, _parameters); } StochasticNode const *asStochastic(Node const *node) { return dynamic_cast(node); } bool StochasticNode::isStochastic() const { return true; /* if (_parameters.empty()) throw logic_error("Cannot determine if node with no parameters is stochastic"); if (_dist->df(_parameters) == 0) { //Deterministic distributions are considered stochastic only //if they are observed, in which case they generate a likelihood. return isObserved(this); } else { return true; } */ }