1 #include <config.h>
2 
3 #include "CODA.h"
4 #include <model/BUGSModel.h>
5 #include <model/Monitor.h>
6 #include <model/NodeArray.h>
7 #include <model/MonitorFactory.h>
8 #include <graph/StochasticNode.h>
9 #include <graph/GraphMarks.h>
10 #include <graph/Node.h>
11 #include <rng/RNG.h>
12 #include <sampler/Sampler.h>
13 #include <util/dim.h>
14 
15 #include <list>
16 #include <utility>
17 #include <stdexcept>
18 #include <fstream>
19 #include <cmath>
20 
21 using std::vector;
22 using std::ofstream;
23 using std::list;
24 using std::pair;
25 using std::string;
26 using std::logic_error;
27 using std::runtime_error;
28 using std::map;
29 
30 namespace jags {
31 
32 /*
33    Nodes accessible to the user in a BUGSModel are identified
34    by a variable name and range of indices
35 */
36 typedef pair<string, Range> NodeId;
37 
BUGSModel(unsigned int nchain)38 BUGSModel::BUGSModel(unsigned int nchain)
39     : Model(nchain), _symtab(this)
40 {
41 }
42 
~BUGSModel()43 BUGSModel::~BUGSModel()
44 {
45     for (list<MonitorInfo>::iterator i = _bugs_monitors.begin();
46 	 i != _bugs_monitors.end(); ++i)
47     {
48 	Monitor const *monitor = i->monitor();
49 	delete monitor; //FIXME: constant pointer
50     }
51 
52 }
53 
symtab()54 SymTab &BUGSModel::symtab()
55 {
56     return _symtab;
57 }
58 
coda(vector<NodeId> const & node_ids,string const & stem,string & warn)59 void BUGSModel::coda(vector<NodeId> const &node_ids, string const &stem,
60 		     string &warn)
61 {
62     warn.clear();
63 
64     list<MonitorControl> dump_nodes;
65     for (unsigned int i = 0; i < node_ids.size(); ++i) {
66 	string const &name = node_ids[i].first;
67 	Range const &range = node_ids[i].second;
68 	list<MonitorInfo>::const_iterator p;
69 	for (p = _bugs_monitors.begin(); p != _bugs_monitors.end(); ++p) {
70 	    if (p->name() == name && p->range() == range) {
71 		break;
72 	    }
73 	}
74 	if (p == _bugs_monitors.end()) {
75 	    string msg = string("No Monitor ") + name +
76 		print(range) + " found.\n";
77 	    warn.append(msg);
78 	}
79 	else {
80 	    list<MonitorControl>::const_iterator q;
81 	    for (q = monitors().begin(); q != monitors().end(); ++q) {
82 		if (q->monitor() == p->monitor()) {
83 		    dump_nodes.push_back(*q);
84 		    break;
85 		}
86 	    }
87 	    if (q == monitors().end()) {
88 		throw logic_error(string("Monitor ") + name + print(range) +
89 				  "not found");
90 	    }
91 	}
92     }
93 
94     if (dump_nodes.empty()) {
95 	warn.append("There are no matching monitors\n");
96 	return;
97     }
98 
99     CODA0(dump_nodes, stem, warn);
100     CODA(dump_nodes, stem, nchain(), warn);
101     TABLE0(dump_nodes, stem, warn);
102     TABLE(dump_nodes, stem, nchain(), warn);
103 }
104 
coda(string const & stem,string & warn)105 void BUGSModel::coda(string const &stem, string &warn)
106 {
107     warn.clear();
108 
109     if (monitors().empty()) {
110 	warn.append("There are no monitors\n");
111 	return;
112     }
113 
114     CODA0(monitors(), stem, warn);
115     CODA(monitors(), stem, nchain(), warn);
116     TABLE0(monitors(), stem, warn);
117     TABLE(monitors(), stem, nchain(), warn);
118 }
119 
120 
setParameters(map<string,SArray> const & param_table,unsigned int chain)121 void BUGSModel::setParameters(map<string, SArray> const &param_table,
122 			      unsigned int chain)
123 {
124     _symtab.writeValues(param_table, chain);
125 
126 
127     //Strip off .RNG.seed (user-supplied random seed)
128     if (param_table.find(".RNG.seed") != param_table.end()) {
129 	if (rng(chain) == 0) {
130 	    throw runtime_error(".RNG.seed supplied but RNG type not set");
131 	}
132 	SArray const &seed = param_table.find(".RNG.seed")->second;
133 	if (seed.length() != 1) {
134 	    throw runtime_error(".RNG.seed must be a single integer");
135 	}
136 	if (seed.value()[0] < 0) {
137 	    throw runtime_error(".RNG.seed must be non-negative");
138 	}
139 	int iseed = static_cast<int>(seed.value()[0]);
140 	rng(chain)->init(iseed);
141     }
142 
143     //Strip off .RNG.state (saved state from previous run)
144     if (param_table.find(".RNG.state") != param_table.end()) {
145 	if (rng(chain) == 0) {
146 	    throw runtime_error(".RNG.state supplied, but RNG type not set");
147 	}
148 	SArray const &state = param_table.find(".RNG.state")->second;
149 	vector<int>(istate);
150 	//double const *value = state.value();
151 	vector<double> const &value = state.value();
152 	for (unsigned int i = 0; i < state.length(); ++i) {
153 	    istate.push_back(static_cast<int>(value[i]));
154 	}
155 	if (rng(chain)->setState(istate) == false) {
156 	    throw runtime_error("Invalid .RNG.state");
157 	}
158     }
159 }
160 
161 
setMonitor(string const & name,Range const & range,unsigned int thin,string const & type,string & msg)162 bool BUGSModel::setMonitor(string const &name, Range const &range,
163 			   unsigned int thin, string const &type,
164 			   string &msg)
165 {
166     for (list<MonitorInfo>::const_iterator i = _bugs_monitors.begin();
167 	 i != _bugs_monitors.end(); ++i)
168     {
169 	if (i->name() == name && i->range() == range && i->type() == type) {
170 	    msg = "Monitor already exists and cannot be duplicated";
171 	    return false;
172 	}
173     }
174 
175     msg.clear();
176     Monitor *monitor = 0;
177 
178     list<pair<MonitorFactory*, bool> > const &faclist = monitorFactories();
179     for(list<pair<MonitorFactory*, bool> >::const_iterator j = faclist.begin();
180 	j != faclist.end(); ++j)
181     {
182 	if (j->second) {
183 	    monitor = j->first->getMonitor(name, range, this, type, msg);
184 	    if (monitor || !msg.empty())
185 		break;
186 	}
187     }
188 
189     if (monitor) {
190 	addMonitor(monitor, thin);
191 	_bugs_monitors.push_back(MonitorInfo(monitor, name, range, type));
192 	return true;
193     }
194     else {
195 	return false;
196     }
197 }
198 
deleteMonitor(string const & name,Range const & range,string const & type)199 bool BUGSModel::deleteMonitor(string const &name, Range const &range,
200 			      string const &type)
201 {
202     for (list<MonitorInfo>::iterator i = _bugs_monitors.begin();
203 	 i != _bugs_monitors.end(); ++i)
204     {
205 	if (i->name() == name && i->range() == range && i->type() == type) {
206 	    Monitor *monitor = i->monitor();
207 	    removeMonitor(monitor);
208 	    _bugs_monitors.erase(i);
209 	    delete monitor;
210 	    return true;
211 	}
212     }
213     return false;
214 }
215 
samplerNames(vector<vector<string>> & sampler_names) const216 void BUGSModel::samplerNames(vector<vector<string> > &sampler_names) const
217 {
218     sampler_names.clear();
219     sampler_names.reserve(_samplers.size());
220 
221     for (unsigned int i = 0; i < _samplers.size(); ++i) {
222 
223 	vector<string> names;
224 	vector<StochasticNode *> const &nodes = _samplers[i]->nodes();
225 	names.reserve(nodes.size()+1);
226 
227 	names.push_back(_samplers[i]->name());
228 	for (unsigned int j = 0; j < nodes.size(); ++j) {
229 	    names.push_back(_symtab.getName(nodes[j]));
230 	}
231 	sampler_names.push_back(names);
232     }
233 }
234 
235 } //namespace jags
236