#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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 &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 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 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 &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 nodes; list const &monitors = _model->monitors(); for (list::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 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 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]); }