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 ¶m_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