27 namespace classdesc {
template <> Factory<minsky::Item,string>::Factory() {}}
40 void pack(classdesc::pack_t& b,
const civita::XVector& a)
42 b<<a.name<<a.dimension<<uint64_t(a.size());
43 for (
const auto& i: a)
47 void unpack(classdesc::pack_t& b, civita::XVector& a)
52 b>>a.name>>a.dimension>>size;
53 for (
size_t i=0; i<size; ++i)
60 void pack(classdesc::pack_t& b,
const civita::TensorVal& a)
62 b<<uint64_t(a.size());
65 b<<uint64_t(a.index().size());
66 for (
auto i: a.index())
69 b<<uint64_t(a.hypercube().xvectors.size());
70 for (
const auto& i: a.hypercube().xvectors)
75 void unpack(classdesc::pack_t& b, civita::TensorVal& a)
80 for (
size_t i=0; i<sz; ++i)
87 for (
size_t i=0; i<sz; ++i)
97 for (
size_t i=0; i<sz; ++i)
101 hc.xvectors.push_back(xv);
103 assert(std::find_if(index.begin(),index.end(),[&](
size_t i){
return i>=hc.numElements();})==index.end());
104 a.index(std::move(index));
105 a.hypercube(std::move(hc));
106 assert(a.size()==data.size());
107 memcpy(a.begin(),data.data(),data.size()*
sizeof(data[0]));
116 civita::TensorVal tmp;
126 struct IdMap:
public map<const void*,int>
130 int at(
const void* o) {
133 return emplace(o,nextId++).first->second;
139 for (
size_t i=0; i<item.
portsSize(); ++i)
140 r.push_back(at(item.
ports(i).lock().get()));
147 auto* j=
dynamic_cast<const T*
>(i);
151 if (
auto v=i->variableCast())
152 if (
auto g=dynamic_cast<minsky::GodleyIcon*>(v->controller.lock().get()))
153 for (
size_t i=0; !g->variableDisplay() && i<2; ++i)
154 if (
auto p=v->ports(i).lock())
155 if (p->wires().empty())
158 items.emplace_back(at(i), *j, at(*j));
159 if (
auto* g=dynamic_cast<const minsky::GodleyIcon*>(i))
162 items.back().ports.clear();
163 for (
const auto& v: g->flowVars())
164 items.back().ports.push_back(at(v->ports(1).lock().get()));
165 for (
const auto& v: g->stockVars())
166 items.back().ports.push_back(at(v->ports(0).lock().get()));
168 if (
auto* d=dynamic_cast<const minsky::DataOp*>(i))
170 items.back().dataOpData=d->data;
171 items.back().name=d->description();
173 if (
auto* s=dynamic_cast<const minsky::Sheet*>(i))
175 items.back().showSlice=s->showRowSlice;
176 items.back().showColSlice=s->showColSlice;
178 if (
auto* d=dynamic_cast<const minsky::UserFunction*>(i))
180 items.back().expression=d->expression;
181 items.back().name=d->description();
183 if (
auto* r=dynamic_cast<const minsky::Ravel*>(i))
186 lockGroups.insert(r->lockGroup.get());
187 auto s=r->getState();
188 if (!s.handleStates.empty())
190 items.back().ravelState=s;
191 items.back().dimensions=r->axisDimensions;
192 items.back().editorMode=r->editorMode();
194 if (r->flipped) items.back().rotation=180;
196 if (
auto* l=dynamic_cast<const minsky::Lock*>(i))
198 items.back().ravelState=l->lockedState;
208 const size_t n=min(x.length(),y.length());
209 return x.substr(0,n)==y.substr(0,n);
217 auto s=typeName<T>();
219 static const char* ns=
"minsky::";
220 static const int eop=strlen(ns);
221 if (s.substr(0,eop)==ns)
227 registerClassType<minsky::Item>();
228 registerClassType<minsky::IntOp>();
229 registerClassType<minsky::DataOp>();
230 registerClassType<minsky::UserFunction>();
231 registerClassType<minsky::Ravel>();
232 registerClassType<minsky::Lock>();
233 registerClassType<minsky::Sheet>();
234 registerClassType<minsky::VarConstant>();
235 registerClassType<minsky::GodleyIcon>();
236 registerClassType<minsky::PlotWidget>();
237 registerClassType<minsky::SwitchIcon>();
243 if (t==
"Operation:rho")
247 (enum_keys<minsky::OperationType::Type>()
248 (t.substr(t.find(
':')+1)));
251 (enum_keys<minsky::VariableType::Type>()
252 (t.substr(t.find(
':')+1)));
255 return classdesc::Factory<minsky::Item,string>::create(
"::minsky::"+t);
259 assert(!
"item type not registered");
269 for (
const auto& i: x)
273 i->json_pack(jbuf,
"");
274 json_unpack(jbuf,
"",layout[i->id]);
277 template <
class V,
class O>
279 vec.emplace_back(item);
280 if (layout.count(item.id))
281 vec.back().addLayout(layout[item.id]);
288 if (val->tensorInit.rank())
291 pack(buf,val->tensorInit);
302 void Minsky::makeImpl()
304 impl=make_shared<MinskyImpl>();
307 Minsky::~Minsky()=
default;
312 auto& itemMap=impl->itemMap;
324 if (
auto* v=(*i)->variableCast())
325 if (!items.back().tensorData)
326 items.back().packTensorInit(*v);
332 vector<int> inVars, outVars;
334 inVars.push_back(itemMap[i.get()]);
336 outVars.push_back(itemMap[i.get()]);
338 outVariables=outVars;
342 if (
auto* integ=dynamic_cast<minsky::IntOp*>(i->get()))
344 const int id=itemMap[i->get()];
351 assert(itemMap.count(static_cast<minsky::Item*>(integ->intVar.get())));
352 j.intVar.reset(
new int(itemMap[static_cast<minsky::Item*>(integ->intVar.get())]));
361 wires.emplace_back(itemMap[i->get()], **i);
362 assert(itemMap.count((*i)->from().get()) && itemMap.count((*i)->to().get()));
363 wires.back().from=itemMap[(*i)->from().get()];
364 wires.back().to=itemMap[(*i)->to().get()];
370 groups.emplace_back(itemMap[i->get()], **i);
371 for (
auto& j: (*i)->items)
374 assert(!j->visible() || itemMap.count(j.get()));
375 groups.back().items.push_back(itemMap[j.get()]);
376 if (j==(*i)->displayPlot)
377 groups.back().displayPlot=itemMap[j.get()];
379 for (
auto& j: (*i)->groups)
380 groups.back().items.push_back(itemMap[j.get()]);
381 for (
auto& v: (*i)->inVariables)
383 assert(itemMap.count(v.get()));
384 groups.back().inVariables->push_back(itemMap[v.get()]);
386 for (
auto& v: (*i)->outVariables)
388 assert(itemMap.count(v.get()));
389 groups.back().outVariables->push_back(itemMap[v.get()]);
397 for (
auto lg: itemMap.lockGroups)
399 lockGroups.emplace_back();
400 auto& slg=lockGroups.back();
401 for (
auto& wr: lg->ravels())
402 if (
auto r=wr.lock())
403 slg.ravels.push_back(itemMap.at(static_cast<minsky::Item*>(r.get())));
405 slg.ravels.push_back(-1);
406 for (
auto& hli: lg->handleLockInfo)
407 slg.handleLockInfo.emplace_back(hli);
414 for (
auto& [key,stock]: pd.
stocks)
417 for (
auto& [key,flow]: pd.
flows)
419 flows.emplace_back(itemMap[&flow], flow);
420 assert(itemMap.count(flow.from().get()) && itemMap.count(flow.to().get()));
421 flows.back().from=itemMap[flow.from().get()];
422 flows.back().to=itemMap[flow.to().get()];
423 for (
auto& term: flow.terms)
424 flows.back().terms.emplace_back(term.first,
Item(-1,term.second,{}));
428 void Minsky::populateSchemaPublicationTabs(
const std::vector<minsky::PubTab>& pubTabs)
431 auto& itemMap=impl->itemMap;
432 publicationTabs.clear();
433 if (pubTabs.size()==1 && pubTabs.front().items.empty())
return;
434 for (
auto& i: pubTabs)
436 publicationTabs.emplace_back();
437 publicationTabs.back().name=i.name;
438 for (
auto& j: i.items)
441 if (!itemMap.count(j.itemRef.get()))
443 publicationTabs.back().items.emplace_back(itemMap[j.itemRef.get()], j);
452 populateGroup(*m.
model);
455 m.
model->setZoom(zoomFactor);
456 m.
model->bookmarks.insert(bookmarks.begin(), bookmarks.end());
485 if (
auto* x1=dynamic_cast<minsky::DataOp*>(&x))
488 x1->description(*y.
name);
492 if (
auto* x1=dynamic_cast<minsky::UserFunction*>(&x))
495 x1->description(*y.
name);
500 if (
auto* x1=dynamic_cast<minsky::Ravel*>(&x))
505 x1->redistributeHandles();
512 x1->toggleEditorMode();
515 if (
auto* x1=dynamic_cast<minsky::Lock*>(&x))
520 x1->tooltip(ravel::Ravel::description(x1->lockedState));
523 if (
auto* x1=dynamic_cast<minsky::VariableBase*>(&x))
529 x1->sliderStepRel(y.
slider->stepRel);
530 x1->enableSlider(y.
slider->visible);
531 x1->sliderMin(y.
slider->min);
532 x1->sliderMax(y.
slider->max);
533 x1->sliderStep(y.
slider->step);
538 if (
auto* x1=dynamic_cast<minsky::OperationBase*>(&x))
541 if (y.
arg) x1->arg=*y.
arg;
543 if (
auto* x1=dynamic_cast<minsky::GodleyIcon*>(&x))
545 std::vector<std::vector<std::string>> data;
546 std::vector<minsky::GodleyAssetClass::AssetClass> assetClasses;
549 SchemaHelper::setPrivates(*x1,data,assetClasses);
552 x1->table.orderAssetClasses();
554 catch (
const std::exception&) {}
555 if (y.
name) x1->table.title=*y.
name;
557 x1->toggleEditorMode();
564 if (
auto* x1=dynamic_cast<minsky::PlotWidget*>(&x))
570 if (y.
ports.size()>x1->nBoundsPorts)
571 x1->numLines((y.
ports.size()-x1->nBoundsPorts)/4);
573 if (
auto* x1=dynamic_cast<minsky::Sheet*>(&x))
580 if (
auto* x1=dynamic_cast<minsky::SwitchIcon*>(&x))
583 if (y.
ports.size()>=2)
584 x1->setNumCases(y.
ports.size()-2);
586 if (
auto* x1=dynamic_cast<minsky::Group*>(&x))
592 x1->bookmarks.clear();
610 void Minsky::populatePublicationTabs(std::vector<minsky::PubTab>& pubTabs)
const 613 auto& itemMap=impl->reverseItemMap;
617 for (
auto& i: publicationItems)
622 for (
auto& pub: publicationTabs)
624 pubTabs.emplace_back(pub.name);
625 pubTabs.back().offsx=pub.x;
626 pubTabs.back().offsy=pub.y;
627 pubTabs.back().m_zoomFactor=pub.zoomFactor;
629 for (
auto& item: pub.items)
630 if (itemMap.contains(item.item))
631 pubTabs.back().items.emplace_back(itemMap[item.item], item);
633 if (pubTabs.empty()) pubTabs.emplace_back(
"Publication");
638 auto& itemMap=impl->reverseItemMap;
639 map<int, weak_ptr<minsky::Port>> portMap;
640 map<int, schema3::Item> schema3VarMap;
642 map<int,LockGroupFactory> lockGroups;
644 for (
const auto& i: items)
648 for (
size_t j=0; j<min(newItem->portsSize(), i.ports.size()); ++j)
649 portMap[i.ports[j]]=newItem->ports(j);
650 if (newItem->variableCast())
651 schema3VarMap[i.id]=i;
655 for (
auto i: *inVariables)
658 for (
auto i: *outVariables)
662 for (
const auto& i: items)
664 if ((i.type==
"IntOp" || i.type==
"Operation:integrate") && i.intVar)
666 assert(itemMap.count(i.id));
667 assert(dynamic_pointer_cast<minsky::IntOp>(itemMap[i.id]));
668 if (
auto* integ=dynamic_cast<minsky::IntOp*>(itemMap[i.id].get()))
670 assert(integ->intVar);
672 if (itemMap.contains(*i.intVar))
674 if (integ->coupled()) integ->toggleCoupled();
676 integ->intVar=itemMap[*i.intVar];
679 integ->description(integ->description());
681 auto iv=schema3VarMap.find(*i.intVar);
682 if (iv!=schema3VarMap.end())
683 if ((!i.ports.empty() && !iv->second.ports.empty() && i.ports[0]==iv->second.ports[0]) != integ->coupled())
684 integ->toggleCoupled();
686 if (!i.ports.empty())
687 portMap[i.ports[0]]=integ->coupled()? integ->intVar->ports(0): integ->ports(0);
690 if (i.type==
"GodleyIcon")
692 assert(itemMap.count(i.id));
693 if (
auto*
godley=dynamic_cast<minsky::GodleyIcon*>(itemMap[i.id].get()))
696 for (
auto p: i.ports)
698 auto newP=portMap.find(p);
699 if (newP!=portMap.end())
700 if (
auto ip=g.
findItem(newP->second.lock()->item()))
701 if (
auto v=dynamic_pointer_cast<minsky::VariableBase>(ip))
705 stockVars.push_back(v);
708 flowVars.push_back(v);
714 SchemaHelper::setStockAndFlow(*
godley, flowVars, stockVars);
722 if (i.type==
"Ravel" && i.lockGroup)
723 if (
auto r=dynamic_pointer_cast<minsky::Ravel>(itemMap[i.id]))
726 r->lockGroup=lockGroups[*i.lockGroup];
727 r->lockGroup->addRavel(r);
728 if (i.lockGroupHandles)
729 r->lockGroup->setLockHandles({i.lockGroupHandles->begin(), i.lockGroupHandles->end()});
734 for (
auto& lgi: this->lockGroups)
736 auto lockGroup=make_shared<minsky::RavelLockGroup>();
737 for (
auto i: lgi.ravels)
738 if (
auto r=dynamic_pointer_cast<minsky::Ravel>(itemMap[i]))
740 lockGroup->addRavel(r);
741 r->lockGroup=lockGroup;
744 lockGroup->addRavel({});
745 lockGroup->handleLockInfo=lgi.handleLockInfo;
748 for (
const auto& w: wires)
749 if (portMap.contains(w.to) && portMap.contains(w.from))
755 for (
const auto& i: groups)
759 for (
const auto& i: groups)
761 assert(itemMap.count(i.id));
762 auto newG=dynamic_pointer_cast<
minsky::Group>(itemMap[i.id]);
765 for (
auto j: i.items)
767 auto it=itemMap.find(j);
768 if (it!=itemMap.end())
770 newG->
addItem(it->second,
true);
773 if (i.displayPlot>=0)
775 auto it=itemMap.find(i.displayPlot);
776 if (it!=itemMap.end())
777 newG->displayPlot=dynamic_pointer_cast<minsky::PlotWidget>(it->second);
780 for (
auto j: *i.inVariables)
782 auto it=itemMap.find(j);
783 if (it!=itemMap.end())
784 if (
auto v=dynamic_pointer_cast<minsky::VariableBase>(it->second))
786 newG->addItem(it->second);
787 newG->inVariables.push_back(v);
792 for (
auto j: *i.outVariables)
794 auto it=itemMap.find(j);
795 if (it!=itemMap.end())
796 if (
auto v=dynamic_pointer_cast<minsky::VariableBase>(it->second))
798 newG->addItem(it->second);
799 newG->outVariables.push_back(v);
806 for (
auto& i: schema3VarMap)
808 auto it=itemMap.find(i.first);
809 if (!it->second)
continue;
810 if (
auto* v=it->second->variableCast())
813 v->init(*i.second.init);
815 v->setUnits(*i.second.units);
817 if (
auto val=v->vValue())
819 if (i.second.csvDataSpec)
820 val->csvDialog.spec=*i.second.csvDataSpec;
822 val->csvDialog.url=*i.second.url;
823 if (i.second.tensorData)
828 civita::TensorVal tmp;
831 val->tensorInit=std::move(tmp);
832 assert(val->idxInRange());
834 catch (
const std::exception& ex) {
835 val->tensorInit.hypercube({});
836 #if !defined(NDEBUG) || !defined(_WIN32) 837 cout<<ex.what()<<endl;
841 val->tensorInit.hypercube({});
842 assert(val->idxInRange());
853 map<int, weak_ptr<minsky::Port>> portMap;
854 for (
auto& i: stocks)
859 for (
size_t j=0; j<std::min(i.ports.size(), stock.
numPorts()); ++j)
860 portMap[i.ports[j]]=item.ports(j);
865 assert(portMap[i.from].lock() && portMap[i.to].lock());
868 for (
auto& j: i.terms)
873 auto fromId=flow.from()->item().variableCast()->valueId();
874 auto toId=flow.to()->item().variableCast()->valueId();
875 auto success=pd.
flows.emplace(make_pair(fromId, toId), flow).second;
std::size_t numPorts() const override
Optional< std::map< double, double > > dataOpData
std::vector< WirePtr > Wires
Optional< minsky::ShowSlice > showSlice
std::vector< VariablePtr > inVariables
void pack(classdesc::pack_t &, const classdesc::string &, classdesc::ref< ecolab::urand > &)
Optional< std::string > name
std::size_t portsSize() const
number of ports
Optional< std::string > axis
map< int, schema1::UnionLayout > layout
void populateWire(minsky::Wire &x, const Wire &y)
void addItem(V &vec, const O &item)
classdesc::pack_t decode(const classdesc::CDATA &data)
decode ascii-encoded representation to binary data
Optional< std::string > expression
ItemPtr addItem(const std::shared_ptr< Item > &it, bool inSchema=false) override
void unpack(classdesc::pack_t &, const classdesc::string &, classdesc::ref< ecolab::urand > &)
int operator[](const void *o)
Optional< bool > editorMode
map< int, minsky::ItemPtr > reverseItemMap
ravel::RavelState toRavelRavelState() const
Optional< string > currency
float m_sf
scale factor of item on canvas, or within group
void populateNote(minsky::NoteBase &x, const Note &y)
std::shared_ptr< Item > ItemPtr
Optional< Slider > slider
Optional< minsky::ShowSlice > showColSlice
Optional< std::vector< ecolab::Plot::LineStyle > > palette
bool recursiveDo(M GroupItems::*map, O op) const
Perform action heirarchically on elements of map map. If op returns true, the operation terminates...
convenience class to omit writing XML records when data absent or empty
virtual std::string const & tooltip() const
bool flipped(double rotation)
returns if the angle (in degrees) is in the second or third quadrant
Optional< schema2::RavelState > ravelState
static VariableBase * create(Type type)
std::vector< VariablePtr > outVariables
Optional< std::vector< minsky::Bookmark > > bookmarks
std::vector< float > coords() const
display coordinates
Optional< std::vector< std::vector< std::string > > > data
ItemPtr findItem(const Item &it) const
finds item within this group or subgroups. Returns null if not found
Creation and access to the minskyTCL_obj object, which has code to record whenever Minsky's state cha...
GroupPtr addGroup(const std::shared_ptr< Group > &)
Optional< std::string > detailedText
Optional< bool > variableDisplay
std::vector< ItemPtr > Items
CDATA encode(const pack_t &buf)
Optional< std::vector< float > > coords
std::vector< PubTab > publicationTabs
virtual std::string valueId() const
string used to link to the VariableValue associated with this
float scaleFactor
scale factor of item on canvas, or within group
Optional< std::vector< minsky::GodleyAssetClass::AssetClass > > assetClasses
bool bookmark
Is this item also a bookmark?
static OperationBase * create(Type type)
factory method.
void applyPlotOptions(PlotWidget &plot) const
std::vector< GroupPtr > Groups
std::map< std::pair< std::string, std::string >, PhillipsFlow > flows
Optional< minsky::Dimensions > dimensions
std::map< std::string, PhillipsStock > stocks
std::string str(T x)
utility function to create a string representation of a numeric type
Optional< std::string > tooltip
void unpack(classdesc::pack_t &b, civita::XVector &a)
std::unique_ptr< T > factory(const std::string &)
double rotation
rotation of icon, in degrees
vector< int > at(const minsky::Item &item)
set< minsky::RavelLockGroup * > lockGroups
std::vector< VariablePtr > Variables
WirePtr addWire(const Item &from, const Item &to, unsigned toPortIdx, const std::vector< float > &coords)
add a wire from item from, to item to, connecting to the toIdx port of to, with coordinates ...
void populateItem(minsky::Item &x, const Item &y)
bool matchesStart(const string &x, const string &y)
PhillipsDiagram phillipsDiagram
RAII set the minsky object to a different one for the current scope.
virtual std::weak_ptr< Port > ports(std::size_t i) const
callback to be run when item deleted from group
minsky::Item * create(const string &t) const
float m_y
position in canvas, or within group
Optional< bool > buttonDisplay
std::shared_ptr< VariableValue > vValue() const
variableValue associated with this. nullptr if not associated with a variableValue ...
Schema1Layout(const vector< shared_ptr< schema1::Layout >> &x)
virtual std::string const & detailedText() const
std::string fileVersion
Minsky version file was saved under.
float y
position in canvas, or within group
bool emplaceIf(vector< Item > &items, const minsky::Item *i)
ItemPtr removeItem(const Item &)