25 #include "constMap.rcd" 26 #include "dimension.rcd" 27 #include "hypercube.rcd" 28 #include "hypercube.xcd" 33 #include "tensorInterface.rcd" 34 #include "tensorInterface.xcd" 35 #include "tensorVal.rcd" 36 #include "tensorVal.xcd" 39 #include "variableValue.rcd" 40 #include "variableValues.rcd" 41 #include "variableValues.xcd" 42 #include "xvector.rcd" 53 string quoted(
const string& x)
67 std::vector<double,CIVITA_ALLOCATOR<double>> ValueVector::stockVars(1);
68 std::vector<double,CIVITA_ALLOCATOR<double>> ValueVector::flowVars(1);
74 using ITensorVal::operator=;
81 static VariableValuePtr s_zero(make_shared<SpecialConst>(
"constant:zero",
"0"));
85 static VariableValuePtr s_one(make_shared<SpecialConst>(
"constant:one",
"1"));
89 bool VariableValue::idxInRange()
const 90 {
return m_type==undefined || idx()+size()<=
91 (isFlowVar()?ValueVector::flowVars.size(): ValueVector::stockVars.size());}
95 double& VariableValue::operator[](
size_t i)
97 assert(i<size() && idxInRange());
98 return *(&valRef()+i);
101 VariableValue& VariableValue::operator=(minsky::TensorVal
const& x)
104 hypercube(x.hypercube());
105 assert(idxInRange());
107 memcpy(&valRef(), x.begin(), x.size()*
sizeof(x[0]));
115 assert(idxInRange());
116 for (
size_t i=0; i<x.
size(); ++i)
132 m_idx=ValueVector::flowVars.size();
135 if (ValueVector::flowVars.max_size()-ValueVector::flowVars.size()<size())
136 throw runtime_error(
"Maximum processing data exceeded.");
137 ValueVector::flowVars.resize(ValueVector::flowVars.size()+size());
141 m_idx=ValueVector::stockVars.size();
144 if (ValueVector::stockVars.max_size()-ValueVector::stockVars.size()<size())
145 throw runtime_error(
"Maximum processing data exceeded.");
146 ValueVector::stockVars.resize(ValueVector::stockVars.size()+size());
153 const double& VariableValue::valRef()
const 162 if (
size_t(m_idx)<ValueVector::flowVars.size())
163 return ValueVector::flowVars[m_idx];
168 if (
size_t(m_idx)<ValueVector::stockVars.size())
169 return ValueVector::stockVars[m_idx];
173 static const double zero=0;
177 double& VariableValue::valRef()
187 assert(idxInRange());
188 if (
size_t(m_idx+size())<=ValueVector::flowVars.size())
189 return ValueVector::flowVars[m_idx];
192 assert(idxInRange());
193 if (
size_t(m_idx+size())<=ValueVector::stockVars.size())
194 return ValueVector::stockVars[m_idx];
198 throw error(
"invalid access of variable value reference: %s",name.c_str());
207 if (tensorInit.size()>size()) m_idx=-1;
208 index(tensorInit.index());
209 hypercube(tensorInit.hypercube());
213 const Hypercube& VariableValue::hypercube()
const 215 if (rhs)
return rhs->hypercube();
218 return tensorInit.hypercube();
222 void VariableValue::sliderSet(
double x)
225 if (x<sliderMin) x=sliderMin;
226 if (x>sliderMax) x=sliderMax;
227 sliderStep=maxSliderSteps();
232 void VariableValue::incrSlider(
double step)
234 sliderSet(value()+
step*(sliderStepRel? value(): 1)*sliderStep);
237 void VariableValue::adjustSliderBounds()
239 if (size()==1 && !
isnan(value()))
241 if (!
isfinite(sliderMax) ||sliderMax<value())
242 sliderMax=value()? abs(10*value()):1;
243 if (!
isfinite(sliderMin) || sliderMin>=value())
244 sliderMin=value()? -abs(10*value()):-1;
245 assert(sliderMin<sliderMax);
246 sliderStep=maxSliderSteps();
251 TensorVal VariableValues::initValue
258 if (
trimWS(fc.name).empty())
262 auto p=fc.name.find(
'(');
267 const char* x=fc.name.c_str()+p+1;
269 vector<unsigned> dims;
272 auto tmp=strtol(x,&e,10);
273 if (tmp>0 && e>x && *e)
284 if (fc.name.starts_with(
"iota"))
285 for (
size_t i=0; i<r.size(); ++i)
287 else if (fc.name.starts_with(
"one"))
288 for (
size_t i=0; i<r.size(); ++i)
290 else if (fc.name.starts_with(
"zero") || fc.name.starts_with(
"eye"))
292 for (
size_t i=0; i<r.size(); ++i)
294 if (fc.name.starts_with(
"eye"))
298 size_t mind=r.size(), stride=1;
300 mind=min(mind,
size_t(i));
301 for (
size_t i=0; i<dims.size()-1; ++i)
303 for (
size_t i=0; i<mind; ++i)
307 else if (fc.name.starts_with(
"rand"))
309 for (
size_t i=0; i<r.size(); ++i)
310 r[i]=
double(rand())/RAND_MAX;
318 throw error(
"circular definition of initial value for %s",
320 const VariableValues::const_iterator vv=find(
valueId);
322 throw error(
"Unknown variable %s in initialisation of %s",fc.name.c_str(), v.
name.c_str());
325 return fc.coef*initValue(*vv->second, visited);
338 for (
auto& xv: hc.xvectors)
341 if (dim!=
cminsky().dimensions.end())
342 xv.dimension=dim->second;
355 string VariableValues::newName(
const string& name)
const 360 trialName=utf_to_utf<char>(name)+
to_string(i++);
361 while (count(
valueId(trialName)));
368 ValueVector::stockVars.clear();
369 ValueVector::flowVars.clear();
370 for (
auto& v: *
this) {
377 bool VariableValues::validEntries()
const 379 return all_of(begin(), end(), [](
const value_type& v){
return isValueId(v.first);});
396 int width, decimal_places;
397 digits=std::max(digits, 3);
398 switch (e.sciExp-e.engExp)
400 case -3: width=digits+4; decimal_places=digits+1;
break;
401 case -2: width=digits+3; decimal_places=digits;
break;
402 case 0:
case -1: width=digits+2; decimal_places=digits-1;
break;
403 case 1: width=digits+2; decimal_places=digits-2;
break;
404 case 2:
case 3: width=digits+2; decimal_places=digits-3;
break;
408 const char conv[]=
"%*.*f";
409 snprintf(val,
sizeof(val),conv,width,decimal_places,value*
pow(10,-e.engExp));
417 void VariableValue::exportAsCSV(
const string& filename,
const string& comment,
bool tabular)
const 419 ofstream of(filename);
420 if (!comment.empty())
421 of<<R
"(""")"<<comment<<R"(""")"<<endl; 424 auto dims=hypercube().dims();
425 auto longestDim=max_element(dims.begin(),dims.end())-dims.begin();
427 const auto& xv=hypercube().xvectors;
430 for (
const auto& i: xv)
432 if (&i>xv.data()) os<<
",";
433 os<<json(static_cast<const NamedDimension&>(i));
435 of<<quoted(
"RavelHypercube=["+os.str()+
"]")<<endl;
437 of<<
"HorizontalDimension="<<quoted(xv[longestDim].name)<<endl;
439 for (
size_t i=0; i<xv.size(); ++i)
440 if (!tabular || i!=longestDim)
444 for (
size_t k=0; k<dims[longestDim]; ++k)
447 of<<
CSVQuote(
str(xv[longestDim][k],xv[longestDim].dimension.units),
',');
458 for (
size_t i=0; i<longestDim; ++i)
460 for (
size_t i=0; i<hypercube().numElements(); i+=stride*dims[longestDim])
461 for (
size_t j=0; j<stride; ++j)
466 data.reserve(dims[longestDim]);
467 for (
size_t k=0; k<stride*dims[longestDim]; k+=stride)
469 data.push_back(this->atHCIndex(i+j+k));
470 if (
isfinite(data.back())) isData=
true;
475 for (
size_t k=0; k<rank(); ++k)
477 auto div=std::div(idx, ssize_t(dims[k]));
480 if (k>1 || (k>0 && longestDim>0)) of<<
",";
481 of <<
"\""<<
str(xv[k][div.rem], xv[k].dimension.units) <<
"\"";
497 for (
auto d=begin(); d!=end(); ++i, ++d)
500 ssize_t idx=idxv.empty()? i: idxv[i];
501 for (
size_t j=0; j<rank(); ++j)
503 auto div=std::div(idx, ssize_t(dims[j]));
504 of <<
"\""<<
str(xv[j][div.rem], xv[j].dimension.units) <<
"\",";
527 string scopeName=
":";
528 if (
auto scope=m_scope.lock())
533 string definition=varNode && varNode->rhs? varNode->rhs->latexStr():
"";
534 string udfDefinition;
537 udfDefinition=varNode && varNode->rhs? varNode->rhs->matlabStr():
"";
539 catch (
const std::exception& ex)
541 udfDefinition=ex.what();
545 if (
auto controller=dynamic_pointer_cast<GodleyIcon>(
var->controller.lock()))
546 godleyName=controller->table.title.empty()? controller->id(): controller->table.title;
547 if (
auto p=
var->ports(1).lock())
548 if (!p->wires().empty())
549 if (
auto udf=dynamic_cast<UserFunction*>(&p->wires().front()->from()->item()))
551 definition=
"\\text{"+udf->expression+
"}";
552 udfDefinition=udf->expression;
564 sliderStep, sliderMin, sliderMax,
std::string expMultiplier(int exp)
TensorVal initValue(const VariableValue &, std::set< std::string > &visited) const
evaluates the initial value of a given variableValue in the context given by this. visited is used to check for circular definitions
EngNotation engExp(double value)
return formatted mantissa and exponent in engineering format
classdesc::Exclude< std::weak_ptr< Group > > m_scope
virtual const Hypercube & hypercube() const
information describing the axes, types and labels of this tensor
bool isFlowVar() const
returns true if variable's data is allocated on the flowVariables vector
UnitsExpressionWalker pow(const UnitsExpressionWalker &x, const UnitsExpressionWalker &y)
SpecialConst(const string &name, const string &init)
VariableValues variableValues
virtual const Index & index() const
the index vector - assumed to be ordered and unique
size_t scope(const string &name)
extract scope from a qualified variable name
summary for the variable tab (aka summary tab).
string valueId(const string &name)
construct a valueId from fully qualified name @ name should not be canonicalised
a shared_ptr that default constructs a default target, and is always valid
const std::string & init() const
VariableDAGPtr getNodeFromIntVar(const std::string &valueId)
struct TCLcmd::trap::init_t init
virtual std::size_t size() const
return number of elements in tensor - maybe less than hypercube.numElements if sparse ...
Creation and access to the minskyTCL_obj object, which has code to record whenever Minsky's state cha...
TensorVal tensorInit
when init is a tensor of values, this overrides the init string
std::string trimWS(const std::string &s)
double isfinite(double x)
represents the units (in sense of dimensional analysis) of a variable.
std::string str(T x)
utility function to create a string representation of a numeric type
VariablePtr definingVar(const std::string &valueId) const
returns reference to variable defining (ie input wired) for valueId
const Minsky & cminsky()
const version to help in const correctness
std::string mantissa(double value, const EngNotation &, int digits=3)
represents a numerical coefficient times a variable (a "flow")
bool isValueId(const string &name)
check that name is a valid valueId (useful for assertions)
VariableDAGPtr getNodeFromValueId(const std::string &v)
std::string valueId() const
VariableValue & allocValue()
allocate space in the variable vector.
std::string CSVQuote(const std::string &x, char sep)
quotes a string if it contains a separator character, and double quotes quotes
string to_string(CONST84 char *x)
shared_ptr< VariableDAG > VariableDAGPtr
CLASSDESC_ACCESS_EXPLICIT_INSTANTIATION(minsky::Units)