27 #include <boost/locale.hpp> 29 using boost::locale::conv::utf_to_utf;
35 string readToken(istream& mdlFile,
char delim,
bool appendDelim=
false)
40 if (c[0]==delim || c[0]==
'~' || c[0]==
'|')
53 if (mdlFile>>
GetUtf8Char(c) && (c[0]==
'\n'||c[0]==
'\r'))
64 {
return c>0x7f || isalnum(c) || c==
'\'' || c==
'$';}
72 auto xx=utf_to_utf<uint32_t>(x);
73 basic_string<uint32_t> result;
75 bool quoted=
false, lastWS=
false, inIdentifier=
false;
78 if (i==
'"' &&lastNonWS!=
'\\')
83 if (!inIdentifier && result.back()==
'.')
84 result.erase(result.end()-1);
88 if (!quoted && !inIdentifier && isalpha(i))
90 if (!quoted && inIdentifier && !
identifierChar(i) && !isspace(i) && i!=
'_')
93 if (result.back()==
'.')
94 result.erase(result.end()-1);
98 if (!isspace(i) && i!=
'_')
102 basic_string<uint32_t> exprTkGoodChar;
104 exprTkGoodChar=utf_to_utf<uint32_t>(
".u"+
to_string(i)+
".");
113 result+=exprTkGoodChar;
120 result+=exprTkGoodChar;
126 result+=exprTkGoodChar;
133 return utf_to_utf<char>(result);
144 {
"arccos",{
"(x)",
"acos(x)"}},
145 {
"arcsin",{
"(x)",
"asin(x)"}},
146 {
"arctan",{
"(x)",
"atan(x)"}},
147 {
"gammaLn",{
"(x)",
"gammaLn(x)"}},
148 {
"integer",{
"(x)",
"floor(x)"}},
149 {
"ifThenElse",{
"(x,y,z)",
"x? y: z"}},
150 {
"ln",{
"(x)",
"log(x)"}},
151 {
"log",{
"(x,y)",
"log(x)/log(y)"}},
152 {
"modulo",{
"(x,y)",
"x%y"}},
153 {
"power",{
"(x,y)",
"x^y"}},
154 {
"pulse",{
"(x,y)",
"(time>=x)*(time<x+y)"}},
155 {
"pulseTrain",{
"(s,b,r,e)",
"tm:=time%r; (time<e)*(time>=s)*(tm<((s+b)%r))*(tm>=(s%r))"}},
156 {
"quantum",{
"(x,y)",
"floor(x/y)"}},
157 {
"ramp",{
"(s,a,b)",
"var t1:=min(a,b); var t2:=max(a,b); (clamp(t1,time,t2)-t1)*s"}},
158 {
"step",{
"(x,y)",
"y*(time>=x)"}},
159 {
"xidz",{
"(x,y,z)",
"var r:=y/z; isfinite(r)? r: x"}},
160 {
"zidz",{
"(x,y)",
"var r:=y/z; isfinite(r)? r:0"}}
164 regex
identifier(R
"([A-Za-z][A-Za-z0-9._]*[A-Za-z0-9_])"); 171 const VariablePtr rhs(VariableBase::flow, definition);
174 group.addWire(rhs->ports(0).lock(), port);
179 group.addItem(
function);
180 for (
auto& i: function->symbolNames())
190 group.addWire(function->ports(0), port);
195 const regex lookupPairsPattern(R
"((\[[^\]]*\],)?(\(.*\)))"); 197 map<double,double> xData; 198 if (regex_match(data,match,lookupPairsPattern))
200 const regex extractHead(R
"(\(([^,]*),([^)]*)\)(,(\(.*\)))*)"); 202 for (
auto d=match[2].
str(); regex_match(d, match, extractHead); d=match[4])
203 xData[stod(match[1])]=stod(match[2]);
207 vector<double> xyData;
208 for (
size_t offs=0; offs<data.size(); ++offs)
209 xyData.push_back(stod(data.substr(offs),&offs));
210 if (xyData.size()%2!=0)
211 throw runtime_error(
"Odd amount of data specified");
212 for (
size_t i=0; i<xyData.size()/2; ++i)
213 xData[xyData[i]]=xyData[i+xyData.size()/2];
215 auto f=make_shared<Group>();
219 const VariablePtr dataVar(VariableType::flow,
"data");
221 dataVar->moveTo(
f->x()-50,
f->y()-20);
224 gather->moveTo(
f->x()+30,
f->y()-10);
225 const VariablePtr inVar(VariableType::flow,
"in"), outVar(VariableType::flow,
"out");
228 f->inVariables.push_back(inVar);
229 f->outVariables.push_back(outVar);
230 f->addWire(*dataVar, *gather, 1);
231 f->addWire(*
f->inVariables[0], *gather, 2);
232 f->addWire(*gather, *
f->outVariables[0], 1);
234 XVector xVals(
"0",{Dimension::value,
""});
235 auto& tensorInit=dataVar->vValue()->tensorInit;
237 xVals.push_back(i.first);
238 Hypercube hc; hc.xvectors.push_back(std::move(xVals));
239 tensorInit.hypercube(std::move(hc));
241 assert(tensorInit.size()==xData.size());
242 auto j=tensorInit.begin();
246 *dataVar->vValue()=tensorInit;
252 set<string> integrationVariables;
253 const regex integ(R
"(\s*integ\s*\(([^,]*),([^,]*)\))"); 254 const regex number(R
"(\d*\.?\d+[Ee]?\d*)"); 255 const regex unitFieldPattern(R
"(([^\[\]]*)(\[.*\])?)"); 256 const regex sliderSpecPattern(R
"(\[([^,]*),?([^,]*),?([^,]*)\])"); 257 const regex lookupPattern(R
"(([^(]*)\((.*)\))"); 262 string currentMDLGroup;
265 if (isspace(c[0]))
continue;
271 throw runtime_error(
"only UTF-8 file encoding is supported");
290 string nameStr=
readToken(mdlFile,
'=',
true );
291 const string name=
collapseWS(
trimWS(c+nameStr.substr(0,nameStr.length()-1)));
292 if (name.substr(0,9)==R
"(\\\---///)") 295 if (nameStr.back()==
'=')
298 switch (definition[0])
301 definition.erase(definition.begin());
307 regex_match(unitField,match,unitFieldPattern);
308 const string units=
trimWS(match[1]);
316 if (currentMDLGroup==
".Control")
318 if (name==
"timeStep")
321 if (regex_match(definition,match,number))
322 simParms.
stepMax=stod(definition);
324 if (!regex_match(definition,match,number))
continue;
325 if (name==
"initialTime") simParms.
t0=stod(definition);
326 if (name==
"finalTime") simParms.
tmax=stod(definition);
329 if (regex_match(name,match,lookupPattern))
331 else if (regex_match(definition,match,integ))
333 auto intOp=
new IntOp;
334 group.addItem(intOp);
335 intOp->description(name);
336 intOp->detailedText(comments);
337 auto& v=intOp->intVar;
338 integrationVariables.insert(name);
339 auto integrand=match[1].str();
342 auto init=match[2].str();
355 v->detailedText(comments);
358 else if (regex_match(definition,match,number))
360 const VariablePtr v(VariableBase::parameter, name);
368 v->detailedText(comments);
369 if (
auto vv=v->vValue())
371 if (regex_match(sliderSpec,match,sliderSpecPattern))
374 for (
size_t i=1; i<=match.size(); ++i) spec.push_back(match[i]);
375 if (!spec.empty() && regex_match(spec[0],match,number))
376 vv->sliderMin=stod(spec[0]);
378 vv->sliderMin=0.1*stod(definition);
379 if (spec.size()>1 && regex_match(spec[1],match,number))
380 vv->sliderMax=stod(spec[1]);
382 vv->sliderMax=10*stod(definition);
383 if (spec.size()>2 && regex_match(spec[2],match,number))
384 vv->sliderStep=stod(spec[2]);
386 vv->adjustSliderBounds();
399 v->detailedText(comments);
shared_ptr class for polymorphic operation objects. Note, you may assume that this pointer is always ...
string readToken(istream &mdlFile, char delim, bool appendDelim=false)
map< string, FunctionDef > venSimFunctions
struct TCLcmd::trap::init_t init
set< string > functionsAdded
Creation and access to the minskyTCL_obj object, which has code to record whenever Minsky's state cha...
void readMdl(Group &group, Simulation &simParms, istream &mdlFile)
import a Vensim mdl file into group, also populating simParms from the control block ...
std::string trimWS(const std::string &s)
std::string str(T x)
utility function to create a string representation of a numeric type
void defineLookupFunction(Group &group, const std::string &name, const std::string &data)
void addDefinitionToPort(Group &group, const shared_ptr< Port > &port, const string &name, const string &definition)
string collapseWS(const string &x)
bool identifierChar(int c)
regex identifier(R"([A-Za-z][A-Za-z0-9._]*[A-Za-z0-9_])")
string to_string(CONST84 char *x)