#include <config.h>
#include <Console.h>
#include <compiler/Compiler.h>
#include <compiler/parser_extra.h>
#include <compiler/ParseTree.h>
#include <model/TraceMonitor.h>
#include <graph/NodeError.h>
#include <sampler/SamplerFactory.h>
#include <sampler/ConjugateFactory.h>
#include <sampler/FiniteFactory.h>
#include <sampler/SliceFactory.h>
#include <sampler/DSumFactory.h>
#include <graph/Node.h>
#include <sarray/Range.h>
#include <sarray/SArray.h>
#include <map>
#include <list>
#include <stdexcept>
#include <fstream>
#include <vector>
#include "Rmath.h"
using std::ostream;
using std::ofstream;
using std::endl;
using std::flush;
using std::vector;
using std::string;
using std::map;
using std::list;
Console::Console(ostream &out, ostream &err)
: _out(out), _err(err), _functab(), _disttab()
{
_pvariables = 0;
_prelations = 0;
_pdata = 0;
_model = 0;
}
Console::~Console()
{
/* FIXME: When do we delete _pvariables, _prelations, _pdata? */
delete _model;
}
bool Console::checkModel(string const &filename)
{
FILE *file = fopen(filename.c_str(), "r");
if (file) {
if (_model) {
_out << "Replacing existing model" << endl;
clearModel();
}
_model = new BUGSModel;
_out << "Parsing model file " << filename << endl;
int lineno = parse_bugs(file, &_pvariables, &_pdata, &_prelations);
if (lineno != 0) {
_err << endl << "Parse error on line " << lineno << endl;
clearModel();
return false;
}
fclose(file);
return true;
/* FIXME: we should free the memory associated wth
_pvariables, _prelations, _pdata after compiling
the model
*/
}
else {
_err << "Unable to open file " << filename << endl;
return false;
}
}
void Console::compile(map<string, SArray> &data_table,
unsigned int nchain)
{
if (nchain == 0) {
_err << "You must have at least one chain" << endl;
}
if (nchain > 1) {
_err << "Multiple chains not currently supported. Sorry" << endl;
}
if (_prelations == 0) {
_err << "No relations defined yet" << endl;
return;
}
if (_pdata) {
BUGSModel datagen_model;
Compiler compiler(datagen_model.graph(), datagen_model.symtab(),
_functab, _disttab, data_table);
_out << "Compiling data graph" << endl;
try {
if (_pvariables) {
_out << " Declaring variables" << endl;
compiler.declareVariables(*_pvariables);
}
_out << " Resolving undeclared variables" << endl;
compiler.undeclaredVariables(_pdata);
_out << " Allocating nodes" << endl;
compiler.writeRelations(_pdata);
_out << " Checking graph" << endl;
datagen_model.checkGraph();
_out << " Initializing" << endl;
datagen_model.initialize();
_out << " Reading data back into data table" << endl;
datagen_model.symtab().readData(data_table);
}
catch (NodeError except) {
_err << "Error in node " << datagen_model.symtab().getName(except.node) << endl;
_err << except.what() << endl;
return;
}
catch (std::runtime_error except) {
_err << "RUNTIME ERROR" << endl;
_err << except.what() << endl;
return;
}
catch (std::logic_error except) {
_err << "LOGIC ERROR" << endl;
_err << except.what() << endl;
_err << "Please send a bug report to " << PACKAGE_BUGREPORT << endl;
return;
}
}
Compiler compiler(_model->graph(), _model->symtab(), _functab, _disttab, data_table);
_out << "Compiling model graph" << endl;
try {
if (_pvariables) {
_out << " Declaring variables" << endl;
compiler.declareVariables(*_pvariables);
}
_out << " Resolving undeclared variables" << endl;
compiler.undeclaredVariables(_prelations);
_out << " Allocating nodes" << endl;
compiler.writeRelations(_prelations);
_out << " Checking graph" << endl;
_model->checkGraph();
_out << " Graph Size: " << _model->graph().size() << endl;
}
catch (NodeError except) {
_err << "Error in node " << _model->symtab().getName(except.node) << endl;
_err << except.what() << endl;
clearModel();
}
catch (std::runtime_error except) {
_err << "RUNTIME ERROR" << endl;
_err << except.what() << endl;
clearModel();
}
catch (std::logic_error except) {
_err << "LOGIC ERROR" << endl;
_err << except.what() << endl;
_err << "Please send a bug report to " << PACKAGE_BUGREPORT << endl;
clearModel();
}
}
bool Console::initialize()
{
if (_model == 0) {
_err << "Can't initialize. No model!" << endl;
return false;
}
if (_model->graph().size() == 0) {
_err << "Can't initialize. No nodes in graph (Have you compiled the model?)" << endl;
return false;
}
try {
_model->initialize();
vector<SamplerFactory const*> samplers;
DSumFactory dfac;
samplers.push_back(&dfac);
ConjugateFactory cfac;
samplers.push_back(&cfac);
FiniteFactory ffac;
samplers.push_back(&ffac);
SliceFactory sfac;
samplers.push_back(&sfac);
_model->chooseSamplers(samplers);
_model->addDevianceNode();
}
catch (NodeError except) {
_err << "Error in node " << _model->symtab().getName(except.node) << endl;
_err << except.what() << endl;
return false;
}
catch (std::runtime_error except) {
_err << "RUNTIME ERROR" << endl;
_err << except.what() << endl;
return false;
}
catch (std::logic_error except) {
_err << "LOGIC ERROR" << endl;
_err << except.what() << endl;
_err << "Please send a bug report to " << PACKAGE_BUGREPORT << endl;
return false;
}
return true;
}
bool Console::setParameters(map<string, SArray> const &init_table,
unsigned int chain)
{
if (_model == 0) {
_err << "Can't set initial values. No model!" << endl;
return false;
}
if (chain > 1) {
_err << "Multiple chains not currently supported. Sorry" << endl;
return false;
}
try {
_model->symtab().writeData(init_table, false);
}
catch (NodeError except) {
_err << "Error in node " << _model->symtab().getName(except.node) << endl;
_err << except.what() << endl;
clearModel();
return false;
}
catch (std::runtime_error except) {
_err << "RUNTIME ERROR" << endl;
_err << except.what() << endl;
clearModel();
return false;
}
catch (std::logic_error except) {
_err << "LOGIC ERROR" << endl;
_err << except.what() << endl;
_err << "Please send a bug report to " << PACKAGE_BUGREPORT << endl;
clearModel();
return false;
}
return true;
}
bool Console::update(long n)
{
if (_model == 0) {
_err << "Can't update. No model!" << endl;
return false;
}
if (!_model->isInitialized()) {
_err << "Model not initialized" << endl;
return false;
}
try {
_model->update(n);
}
catch (NodeError except) {
_err << "Error in node " << _model->symtab().getName(except.node) << endl;
_err << except.what() << endl;
return false;
}
catch (std::runtime_error except) {
_err << "RUNTIME ERROR" << endl;
_err << except.what() << endl;
return false;
}
catch (std::logic_error except) {
_err << "LOGIC ERROR" << endl;
_err << except.what() << endl;
_err << "Please send a bug report to " << PACKAGE_BUGREPORT << endl;
return false;
}
return true;
}
unsigned long Console::iter()
{
if (!_model) {
return 0;
}
else {
return _model->iteration();
}
}
bool Console::setMonitor(string const &name, Range const &range,
unsigned int thin)
{
if (!_model) {
_out << "Can't set monitor. No model!" << endl;
return false;
}
try {
_model->setMonitor(name, range, thin);
}
catch (std::logic_error except) {
_err << "LOGIC ERROR:" << endl;
_err << except.what() << endl;
_err << "Please send a bug report to " << PACKAGE_BUGREPORT << endl;
return false;
}
catch (std::runtime_error except) {
_err << "RUNTIME ERROR:" << endl;
_err << except.what() << endl;
return false;
}
return true;
}
bool Console::clearMonitor(string const &name, Range const &range)
{
if (!_model) {
_out << "Can't clear monitor. No model!" << endl;
return false;
}
try {
_model->clearMonitor(name, range);
}
catch (std::logic_error except) {
_err << "LOGIC ERROR:" << endl;
_err << except.what() << endl;
_err << "Please send a bug report to " << PACKAGE_BUGREPORT << endl;
return false;
}
catch (std::runtime_error except) {
_err << "RUNTIME ERROR:" << endl;
_err << except.what() << endl;
return false;
}
return true;
}
bool Console::setMonitor(string const &name, unsigned int thin)
{
if (!_model) {
_out << "Can't set monitor. No model!" << endl;
return false;
}
NodeArray *array = _model->symtab().getVariable(name);
if (array) {
return setMonitor(name, array->range(), thin);
}
else {
_err << "Variable " << name << " not found" << endl;
return false;
}
}
bool Console::clearMonitor(string const &name)
{
if (!_model) {
_out << "Can't clear monitor. No model!" << endl;
return false;
}
NodeArray *array = _model->symtab().getVariable(name);
if (array) {
return clearMonitor(name, array->range());
}
else {
_err << "Variable " << name << " not found" << endl;
return false;
}
}
void Console::clearModel()
{
_out << "Deleting model" << endl;
delete _model; _model = 0;
}
bool Console::dumpState(map<string,SArray> &data_table, unsigned int chain,
bool observed)
{
if (chain > 1) {
_err << "Multiple chains not supported. Sorry" << endl;
return false;
}
if (!_model) {
_err << "No model" << endl;
return false;
}
if (_model->symtab().size() == 0) {
_err << "Symbol table is empty" << endl;
return false;
}
_model->symtab().readData(data_table, observed);
return true;
}
bool Console::coda(ofstream &index, ofstream &output)
{
if (!_model) {
_err << "Can't dump CODA output. No model!" << endl;
return false;
}
vector<Node const *> nodes;
list<TraceMonitor*> const &monitors = _model->monitors();
for (list<TraceMonitor*>::const_iterator i = monitors.begin();
i != monitors.end(); i++)
{
nodes.push_back((*i)->node());
}
_model->coda(nodes, index, output);
return true;
}
bool Console::coda(string const &name, Range const &range,
ofstream &index, ofstream &output)
{
if (!_model) {
_err << "Can't dump CODA output. No model!" << endl;
return false;
}
NodeArray *array = _model->symtab().getVariable(name);
if (array) {
if (array->range().contains(range)) {
Node *node = array->getSubset(range);
if (node) {
vector<Node const *> nodes(1, array->getSubset(range));
_model->coda(nodes, index, output);
return true;
}
else {
_err << "Node is not being monitored" << endl;
return false;
}
}
else {
_err << "Requested invalid subset of node " << name << endl;
return false;
}
}
else {
_err << "Node " << name << " not found" << endl;
return false;
}
}
bool Console::coda(string const &name, ofstream &index, ofstream &output)
{
if (!_model) {
_err << "Can't dump CODA output. No model!" << endl;
return false;
}
NodeArray *array = _model->symtab().getVariable(name);
if (array) {
vector<Node const *> nodes(1, array->getSubset(array->range()));
_model->coda(nodes, index, output);
return true;
}
else {
_err << "Node " << name << " not found" << endl;
return false;
}
}
BUGSModel const *Console::model()
{
return _model;
}
void Console::setSeed(unsigned int seed)
{
/* Given a single seed, calculates seeds for the Marsaglia
* Multicarry random number generator
*/
unsigned int mmseeds[2];
for(int j = 0; j < 2; j++) {
seed = (69069 * seed + 1);
mmseeds[j] = seed;
}
/* Fix up zero seeds */
if (mmseeds[0] == 0)
mmseeds[0] = 1;
if (mmseeds[1] == 0)
mmseeds[1] = 1;
set_seed(mmseeds[0], mmseeds[1]);
}
syntax highlighted by Code2HTML, v. 0.9.1