1 /* _______________________________________________________________________
2
3 Surfpack: A Software Library of Multidimensional Surface Fitting Methods
4 Copyright (c) 2006, Sandia National Laboratories.
5 This software is distributed under the GNU Lesser General Public License.
6 For more information, see the README file in the top Surfpack directory.
7 _______________________________________________________________________ */
8
9 #include "surfpack.h"
10 #include "AxesBounds.h"
11 #include "SurfpackParserArgs.h"
12 #include "SurfpackParser.h"
13 #include "SurfpackInterface.h"
14 #include "SurfpackInterpreter.h"
15 #include "SurfData.h"
16 #include "ModelFactory.h"
17 #include "SurfpackModel.h"
18
19 using std::cerr;
20 using std::cout;
21 using std::endl;
22 using std::ostream;
23 using std::runtime_error;
24 using std::string;
25 using std::vector;
26 using std::ostringstream;
27 ///////////////////////////////////////////////////////////////////////////////
28 ///// SurfpackInterpreter namespace functions /////
29 ///////////////////////////////////////////////////////////////////////////////
30
SurfpackInterpreter()31 SurfpackInterpreter::SurfpackInterpreter() : parser(SurfpackParser::instance())
32 {
33
34 }
35
~SurfpackInterpreter()36 SurfpackInterpreter::~SurfpackInterpreter()
37 {
38
39 }
40
execute(const string * input_string,const string * output_string)41 void SurfpackInterpreter::execute(const string* input_string,
42 const string* output_string)
43 {
44 if (parser.yyparse(input_string, output_string) == 0) {
45 commandLoop(cout , cerr);
46 } else {
47 cerr << "Command(s) not executed." << endl;
48 cerr << SurfpackParser::cmdstream.str() << endl;
49 }
50 }
51
commandLoop(ostream & os,ostream & es)52 void SurfpackInterpreter::commandLoop(ostream& os, ostream& es)
53 {
54 const vector<ParsedCommand>& fullCommands = parser.commandList();
55 vector<Command>& commands = parser.comms;
56 for (unsigned i = 0; i < commands.size(); i++) {
57 try {
58 //if (commands[i].isShellCommand()) {
59 // executeShellCommand(commands[i]);
60 if (commands[i].first == "CreateSample") {
61 execCreateSample(commands[i].second);
62 } else if (commands[i].first== "CreateSurface") {
63 execCreateSurface(commands[i].second);
64 } else if (commands[i].first == "Evaluate") {
65 execEvaluate(commands[i].second);
66 } else if (commands[i].first == "Fitness") {
67 execFitness(commands[i].second);
68 } else if (commands[i].first == "Load") {
69 execLoad(commands[i].second);
70 } else if (commands[i].first == "Save") {
71 execSave(commands[i].second);
72 } else if (commands[i].first == "CreateAxes") {
73 execCreateAxes(commands[i].second);
74 } else {
75 es << "Unrecognized command: " << commands[i].first << endl;
76 }
77 } catch (string& msg) {
78 es << "Error: " << msg;
79 es << "\n Failed Instruction: " << fullCommands[i].cmdstring << endl;
80 } catch (std::exception& e) {
81 es << "Exception: " << e.what()
82 << "\n Failed Instruction: " << fullCommands[i].cmdstring << endl;
83 } catch (...) {
84 es << "Exception (unknown)\n FailedInstruction: "
85 << fullCommands[i].cmdstring << endl;
86 }
87 }
88 }
89
getResponseIndex(const ArgList & arglist,const SurfData & sd)90 int getResponseIndex(const ArgList& arglist, const SurfData& sd)
91 {
92 bool valid;
93 bool is_response;
94 unsigned int response_index;
95 string response_name = SurfpackParser::parseIdentifier("response",
96 arglist,false);
97 if (response_name == "") {
98 response_index =
99 SurfpackParser::parseInteger("response_index",arglist,valid,false);
100 if (!valid) {
101 // Neither response nor response_index specified
102 // Default index is 0
103 return 0;
104 } else {
105 return response_index;
106 }
107 } else {
108 ostringstream os;
109 valid = sd.varIndex(response_name, response_index, is_response);
110 if (!valid) {
111 os << "No response named '" << response_name << "' found." << endl;
112 throw(os.str());
113 } else if (!is_response) {
114 os << "'" << response_name << "' is a predictor variable, but a"
115 << " response variable was requested" << endl;
116 throw(os.str());
117 } else {
118 return response_index;
119 }
120 }
121 }
122
123 ///////////////////////////////////////////////////////////////////////////////
124 ///// SurfpackInterpreter namespace functions /////
125 ///////////////////////////////////////////////////////////////////////////////
126
execLoad(ParamMap & args)127 void SurfpackInterpreter::execLoad(ParamMap& args)
128 {
129 bool valid;
130 string filename = asStr(args["file"]);
131 if (surfpack::hasExtension(filename,".sps") ||
132 surfpack::hasExtension(filename,".bsps")) {
133 execLoadSurface(args);
134 } else if (surfpack::hasExtension(filename,".spd") ||
135 surfpack::hasExtension(filename,".bspd") ||
136 surfpack::hasExtension(filename,".dat")) {
137 execLoadData(args);
138 } else {
139 throw string("Expected file extension: .sps/.bsps (surface) or "
140 ".spd/.bspd/.dat (data)");
141 }
142 }
143
execLoadData(ParamMap & args)144 void SurfpackInterpreter::execLoadData(ParamMap& args)
145 {
146 try {
147 SurfData* data = 0;
148 string name = asStr(args["name"]);
149 string filename = asStr(args["file"]);
150 bool valid = false;
151 int n_vars = asInt(args["n_predictors"],valid);
152 if (valid) {
153 // n_responses is required if n_vars is present
154 int n_responses = asInt(args["n_responses"]); // fail on error
155 int n_cols_to_skip = asInt(args["n_cols_to_skip"],valid);
156 if (!valid) n_cols_to_skip = 0;
157 data = SurfpackInterface::LoadData(filename,n_vars,n_responses,n_cols_to_skip);
158 } else {
159 data = SurfpackInterface::LoadData(filename);
160 }
161 assert(data);
162 symbolTable.dataVars.insert(SurfDataSymbol(name,data));
163 } catch (...) {
164 cout << "Error caught in execLoadData: Did you forget to specify n_predictors and n_responses?" << endl;
165 }
166 }
167
168 ///\todo Add support for LoadSurface in interpreter
execLoadSurface(ParamMap & args)169 void SurfpackInterpreter::execLoadSurface(ParamMap& args)
170 {
171 string name = asStr(args["name"]);
172 string filename = asStr(args["file"]);
173 SurfpackModel* model = SurfpackInterface::LoadModel(filename);
174 symbolTable.modelVars.insert(SurfpackModelSymbol(name, model));
175 }
176
execSaveData(ParamMap & args)177 void SurfpackInterpreter::execSaveData(ParamMap& args)
178 {
179 string data_name = asStr(args["data"]);
180 string filename = asStr(args["file"]);
181 SurfData* sd = symbolTable.lookupData(data_name);
182 // Call SaveData
183 SurfpackInterface::Save(sd, filename);
184 }
185
186
execSaveSurface(const SurfpackModel * model,const string & filename)187 void SurfpackInterpreter::execSaveSurface(const SurfpackModel* model,
188 const string& filename)
189 {
190 SurfpackInterface::Save(model, filename);
191 }
192
193
execSave(ParamMap & args)194 void SurfpackInterpreter::execSave(ParamMap& args)
195 {
196 try {
197 string filename = asStr(args["file"]);
198 // Don't automatically fail if either of these isn't defined
199 bool valid_data;
200 string data_name = asStr(args["data"],valid_data);
201 bool valid_model;
202 string model_name = asStr(args["surface"],valid_model);
203 if (!valid_data) {
204 if (!valid_model) {
205 // Do fail if both are missing
206 throw string("Save command requires either 'surface' or 'data' argument");
207 } else {
208 SurfpackModel* model = symbolTable.lookupModel(model_name);
209 execSaveSurface(model, filename);
210 }
211 } else {
212 if (valid_model) {
213 // Fail if both are specified
214 throw string("Save command may not have both 'surface' and 'data' arguments");
215 } else {
216 SurfData* sd = symbolTable.lookupData(data_name);
217 sd->write(filename);
218 }
219 }
220 } catch (string& e) {
221 cout << "Error (Save): " << e << endl;
222 } catch (std::exception& e) {
223 cout << "Exception (Save): " << e.what() << endl;
224 } catch (...) {
225 cout << "Exception (Save, unknown)" << endl;
226 }
227 }
228
229 //int getResponseIndex(const ArgList& arglist, const SurfData& sd)
230 //{
231 // bool valid;
232 // bool is_response;
233 // unsigned int response_index;
234 // string response_name = SurfpackParser::parseIdentifier("response",
235 // arglist,false);
236 // if (response_name == "") {
237 // response_index =
238 // SurfpackParser::parseInteger("response_index",arglist,valid,false);
239 // if (!valid) {
240 // // Neither response nor response_index specified
241 // // Default index is 0
242 // return 0;
243 // } else {
244 // return response_index;
245 // }
246 // } else {
247 // ostringstream os;
248 // valid = sd.varIndex(response_name, response_index, is_response);
249 // if (!valid) {
250 // os << "No response named '" << response_name << "' found." << endl;
251 // throw(os.str());
252 // } else if (!is_response) {
253 // os << "'" << response_name << "' is a predictor variable, but a"
254 // << " response variable was requested" << endl;
255 // throw(os.str());
256 // } else {
257 // return response_index;
258 // }
259 // }
260 //}
261 //
execCreateSurface(ParamMap & args)262 void SurfpackInterpreter::execCreateSurface(ParamMap& args)
263 {
264 // Extract the variable name for this SurfData object
265 string name = asStr(args["name"]);
266 string data = asStr(args["data"]);
267 bool valid = false;
268 SurfData* sd = symbolTable.lookupData(data);
269 // Call CreateSurface
270 SurfpackModelFactory* smf = ModelFactory::createModelFactory(args);
271 SurfpackModel* model = smf->Build(*sd);
272 delete smf;
273 assert(model);
274 symbolTable.modelVars.insert(SurfpackModelSymbol(name,model));
275 }
276
execCreateSample(ParamMap & args)277 void SurfpackInterpreter::execCreateSample(ParamMap& args)
278 {
279 // Extract the variable name for this SurfData object
280 string name = asStr(args["name"]);
281 string axes = asStr(args["axes"]);
282 bool valid_grid_points;
283 VecUns grid_points = asVecUns(args["grid_points"], valid_grid_points);
284 bool valid_size = false;
285 int n_points = asInt(args["size"],valid_size);
286 AxesBounds* ab = symbolTable.lookupAxes(axes);
287 SurfData* sd = 0;
288 if (valid_size) {
289 if (valid_grid_points) { // both size and grid_points specified
290 throw string("Cannot specify both size and grid_points");
291 } else { // only size specified
292 // MonteCarlo sample
293 sd = SurfpackInterface::CreateSample(ab,n_points);
294 }
295 } else {
296 if (!grid_points.empty()) { // only grid_points specified
297 // grid sample
298 sd = SurfpackInterface::CreateSample(ab,grid_points);
299 } else { // neither specified
300 throw string("Must specify either size or grid_points");
301 }
302 }
303 bool valid_functions;
304 VecStr test_functions = asVecStr(args["test_functions"], valid_functions);
305 if (valid_functions) {
306 SurfpackInterface::Evaluate(sd,test_functions);
307 }
308 symbolTable.dataVars.insert(SurfDataSymbol(name,sd));
309 }
310
execEvaluate(ParamMap & args)311 void SurfpackInterpreter::execEvaluate(ParamMap& args)
312 {
313 // Extract the variable name for this SurfData object
314 string surf_name = asStr(args["surface"]);
315 string data = asStr(args["data"]);
316 SurfpackModel* model = symbolTable.lookupModel(surf_name);
317 SurfData* sd = symbolTable.lookupData(data);
318 // Call Evaluate
319 VecDbl results = (*model)(*sd);
320 sd->addResponse(results,args["label"]);
321 }
322
execFitness(ParamMap & args)323 void SurfpackInterpreter::execFitness(ParamMap& args)
324 {
325 string surface = asStr(args["surface"]);
326 bool valid_data;
327 string data = asStr(args["data"],valid_data);
328 SurfpackModel* model = symbolTable.lookupModel(surface);
329 SurfData* sd = 0;
330 if (valid_data) {
331 sd = symbolTable.lookupData(data);
332 }
333 string metric = asStr(args["metric"]);
334 // Extract the response index for the input data set
335 bool valid_response_index;
336 int response_index = asInt(args["response_index"],valid_response_index);
337 bool valid_n;
338 int n = asInt(args["n"],valid_n);
339 if (!valid_response_index) { // No response_index was specified, use 0
340 response_index = 0;
341 }
342 double fitness;
343 if (valid_data) {
344 fitness = SurfpackInterface::Fitness(model,sd,metric,response_index,n);
345 } else {
346 fitness = SurfpackInterface::Fitness(model,metric,response_index,n);
347 }
348 cout << metric << " for " << surface;
349 if (data != "") cout << " on " << data;
350 cout << ": " << fitness << endl;
351 }
352
execCreateAxes(ParamMap & args)353 void SurfpackInterpreter::execCreateAxes(ParamMap& args)
354 {
355 string name = asStr(args["name"]);
356 string bounds = asStr(args["bounds"]);
357 AxesBounds* ab = SurfpackInterface::CreateAxes(bounds);
358 symbolTable.axesVars.insert(AxesBoundsSymbol(name,ab));
359 }
360 //
361 //void SurfpackInterpreter::
362 // executeShellCommand(ParamMap& args)
363 //{
364 // system(c.cmdstring.c_str());
365 //}
366
asInt(const string & arg)367 int SurfpackInterpreter::asInt(const string& arg)
368 {
369 if (arg == "") throw string("Expected integer value");
370 return atoi(arg.c_str());
371 }
372
asStr(const string & arg)373 std::string SurfpackInterpreter::asStr(const string& arg)
374 {
375 if (arg == "") throw string("Expected string value");
376 return arg;
377 }
378
asDbl(const string & arg)379 double SurfpackInterpreter::asDbl(const string& arg)
380 {
381 if (arg == "") throw string("Expected double value");
382 return atof(arg.c_str());
383 }
384
asVecUns(const string & arg)385 VecUns SurfpackInterpreter::asVecUns(const string& arg)
386 {
387 if (arg == "") throw string("Expected vector unsigned");
388 return surfpack::toVec<unsigned>(arg);
389 }
390
asVecStr(const string & arg)391 VecStr SurfpackInterpreter::asVecStr(const string& arg)
392 {
393 if (arg == "") throw string("Expected vector string");
394 return surfpack::toVec<std::string>(arg);
395 }
396
asInt(const string & arg,bool & valid)397 int SurfpackInterpreter::asInt(const string& arg, bool& valid)
398 {
399 if (arg == "") {
400 valid = false;
401 return 0;
402 }
403 valid = true;
404 return atoi(arg.c_str());
405 }
406
asStr(const string & arg,bool & valid)407 std::string SurfpackInterpreter::asStr(const string& arg, bool& valid)
408 {
409 if (arg == "") {
410 valid = false;
411 return "";
412 }
413 valid = true;
414 return arg;
415 }
416
asDbl(const string & arg,bool & valid)417 double SurfpackInterpreter::asDbl(const string& arg, bool& valid)
418 {
419 if (arg == "") {
420 valid = false;
421 return 0;
422 }
423 valid = true;
424 return atof(arg.c_str());
425 }
426
asVecUns(const string & arg,bool & valid)427 VecUns SurfpackInterpreter::asVecUns(const string& arg, bool& valid)
428 {
429 if (arg == "") {
430 valid = false;
431 return VecUns();
432 }
433 valid = true;
434 return surfpack::toVec<unsigned>(arg);
435 }
436
asVecStr(const string & arg,bool & valid)437 VecStr SurfpackInterpreter::asVecStr(const string& arg, bool& valid)
438 {
439 if (arg == "") {
440 valid = false;
441 return VecStr();
442 }
443 valid = true;
444 return surfpack::toVec<std::string>(arg);
445 }
446 //********************************************************************
~SymbolTable()447 SurfpackInterpreter::SymbolTable::~SymbolTable()
448 {
449 for (SurfDataMap::iterator iter = dataVars.begin();
450 iter != dataVars.end();
451 ++iter) {
452 delete iter->second;
453 }
454 for (SurfpackModelMap::iterator iter = modelVars.begin();
455 iter != modelVars.end();
456 ++iter) {
457 delete iter->second;
458 }
459 for (AxesBoundsMap::iterator iter = axesVars.begin();
460 iter != axesVars.end();
461 ++iter) {
462 delete iter->second;
463 }
464 }
465
466 SurfpackModel*
lookupModel(const std::string name)467 SurfpackInterpreter::SymbolTable::lookupModel(const std::string name)
468 {
469 SurfpackModel* result = modelVars[name];
470 if (result == 0) {
471 cout << "Bad lookup; table size: " << modelVars.size() << endl;
472 for (SurfpackModelMap::iterator itr = modelVars.begin();
473 itr != modelVars.end(); ++itr) {
474 cout << itr->first << " " << itr->second << endl;
475 }
476
477 string msg = "Model variable " + name + " not found in symbol table.";
478 throw msg;
479 }
480 return result;
481 }
482
lookupData(string name)483 SurfData* SurfpackInterpreter::SymbolTable::lookupData(string name)
484 {
485 SurfDataMap::iterator iter = dataVars.find(name);
486 if (iter == dataVars.end()) {
487 string msg = "Data variable " + name + " not found in symbol table.";
488 throw msg;
489 }
490 assert(iter->second);
491 return iter->second;
492 }
493
lookupAxes(string name)494 AxesBounds* SurfpackInterpreter::SymbolTable::lookupAxes(string name)
495 {
496 AxesBoundsMap::iterator iter = axesVars.find(name);
497 if (iter == axesVars.end()) {
498 string msg = "Axes variable " + name + " not found in symbol table.";
499 throw msg;
500 }
501 assert(iter->second);
502 return iter->second;
503 }
504