Minsky
minskyTensorOps.h
Go to the documentation of this file.
1 /*
2  @copyright Steve Keen 2020
3  @author Russell Standish
4  This file is part of Minsky.
5 
6  Minsky is free software: you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Minsky is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with Minsky. If not, see <http://www.gnu.org/licenses/>.
18 */
19 #ifndef MINSKYTENSOROPS_H
20 #define MINSKYTENSOROPS_H
21 #include "variableValue.h"
22 #include "evalOp.h"
23 #include <tensorOp.h>
24 
25 namespace minsky
26 {
27  using namespace civita;
28 
29  struct FallBackToScalar: public std::exception
30  {
31  const char* what() const throw() {return "Falling back to scalar processing";}
32  };
33 
35  class EvalCommon
36  {
37  double* m_flowVars=nullptr;
38  std::size_t m_fvSize=0;
39  const double* m_stockVars=nullptr;
41  public:
42  double* flowVars() const {return m_flowVars;}
43  std::size_t fvSize() const {return m_fvSize;}
44  const double* stockVars() const {return m_stockVars;}
45  ITensor::Timestamp timestamp() const {return m_timestamp;}
50  void update(double* fv, std::size_t n, const double* sv)
51  {
52  m_flowVars=fv; m_fvSize=n; m_stockVars=sv; m_timestamp=ITensor::Timestamp::clock::now();
53  }
54  };
55 
57  {
58  shared_ptr<EvalCommon> ev;
60  TensorsFromPort(const shared_ptr<EvalCommon>& ev): ev(ev) {}
61 
64  std::vector<TensorPtr> tensorsFromPort(const Port&) const;
66  std::vector<TensorPtr> tensorsFromPorts(const Item&) const;
67  };
68 
72  class TensorOpFactory: public classdesc::Factory<civita::ITensor, OperationType::Type>
73  {
74  using classdesc::Factory<civita::ITensor, OperationType::Type>::create;
75  public:
80  std::shared_ptr<ITensor> create(const ItemPtr&, const TensorsFromPort& tp={});
81  };
82 
84 
87  {
89  virtual double dFlow(std::size_t ti, std::size_t fi) const=0;
91  virtual double dStock(std::size_t ti, std::size_t si) const=0;
92  };
93 
94  // a VariableValue that contains a references to overridable value vectors
95  template <class VV=const VariableValue, class I=ITensor>
96  struct TensorVarValBase: public I, public DerivativeMixin
97  {
98  std::shared_ptr<VV> value;
101  shared_ptr<EvalCommon> ev;
102 
103  int idx() const {return value->idx();}
104 
106  ITensor::Timestamp timestamp() const override {return ev->timestamp();}
107  double operator[](std::size_t i) const override {
108  return value->isFlowVar()? ev->flowVars()[value->idx()+i]: ev->stockVars()[value->idx()+i];
109  }
110  TensorVarValBase(const std::shared_ptr<VV>& vv, const shared_ptr<EvalCommon>& ev):
111  value(vv), ev(ev) {}
112  const Hypercube& hypercube() const override {return value->hypercube();}
113  const Index& index() const override {return value->index();}
114  using I::index;
115  std::size_t size() const override {return value->size();}
116 
117  double dFlow(std::size_t ti, std::size_t fi) const override
118  {return value->isFlowVar() && fi==ti+value->idx();}
119  double dStock(std::size_t ti, std::size_t si) const override
120  {return !value->isFlowVar() && si==ti+value->idx();}
121  };
122 
124 
125  struct TensorVarVal: public TensorVarValBase<VariableValue,ITensorVal>
126  {
127  TensorVarVal(const std::shared_ptr<VariableValue>& vv, const shared_ptr<EvalCommon>& ev):
128  TensorVarValBase<VariableValue,ITensorVal>(vv,ev) {}
129  using ITensorVal::index;
130  const Index& index(Index&& x) override {return value->index(std::move(x));}
131  const Index& index() const override {return value->index();}
132  const Hypercube& hypercube(const Hypercube& hc) override {return value->hypercube(hc);}
133  const Hypercube& hypercube(Hypercube&& hc) override {return value->hypercube(std::move(hc));}
134  const Hypercube& hypercube() const override {return value->hypercube();}
135  using ITensorVal::operator[];
136  double& operator[](std::size_t i) override {
137  assert(value->isFlowVar());
138  assert(
139  (ev->flowVars()==ValueVector::flowVars.data() &&
140  value->idx()+i<ValueVector::flowVars.size())
141  || value->idx()+i<ev->fvSize());
142  return ev->flowVars()[value->idx()+i];
143  }
144  TensorVarVal& operator=(const ITensor& t) override {
145  index(t.index());
146  hypercube(t.hypercube());
147  for (size_t i=0; i<size(); ++i)
148  operator[](i)=t[i];
149  // update timestamp
150  ev->update(ev->flowVars(), ev->fvSize(), ev->stockVars());
151  return *this;
152  }
153  };
154 
155 
157  class TensorEval: public classdesc::Poly<TensorEval, EvalOpBase>
158  // public classdesc::PolyPack<TensorEval>
159  {
162 
163  public:
164  // not used, but required to make this a concrete type
165  Type type() const override {assert(false); return OperationType::numOps;}
166  TensorEval(const std::shared_ptr<VariableValue>& v, const shared_ptr<EvalCommon>& ev,
167  const TensorPtr& rhs): result(v, ev), rhs(rhs) {
168  result.index(rhs->index());
169  assert(!rhs->index().empty() || rhs->hypercube().numElements()==rhs->size());
170  result.hypercube(rhs->hypercube());
171  assert(result.idx()>=0);
172  assert(result.size()==rhs->size());
173  }
174  TensorEval(const std::shared_ptr<VariableValue>& dest, const std::shared_ptr<VariableValue>& src);
175 
176  // pointer arguments are array arguments
177  void eval(double* fv, std::size_t,const double* sv) override;
178  // pointer arguments are array arguments
179  void deriv(double* df,std::size_t,const double* ds,const double* sv,const double* fv) override;
180  };
181 }
182 
183 
184 #endif
shared_ptr< EvalCommon > ev
reference to EvalOpVector owning this value, to extract flowVar and stockVarinfo
ITensor::Timestamp m_timestamp
A helper to evaluate a variable value.
ITensor::Timestamp timestamp() const
virtual const Hypercube & hypercube() const
information describing the axes, types and labels of this tensor
shared_ptr< EvalCommon > ev
ITensor::Timestamp timestamp() const override
const char * what() const
virtual const Index & index() const
the index vector - assumed to be ordered and unique
std::shared_ptr< Item > ItemPtr
Definition: item.h:57
const Index & index() const override
const Hypercube & hypercube(const Hypercube &hc) override
double dFlow(std::size_t ti, std::size_t fi) const override
partial derivative of tensor component ti wrt flow variable fi
const Hypercube & hypercube() const override
As it says on the tin, this is a factory for creating a TensorOp which can compute the result of op a...
double & operator[](std::size_t i) override
A place to store common data shared between TensorVarVals within a give calculation.
Creation and access to the minskyTCL_obj object, which has code to record whenever Minsky&#39;s state cha...
Definition: constMap.h:22
TensorsFromPort(const shared_ptr< EvalCommon > &ev)
std::shared_ptr< VV > value
std::chrono::time_point< std::chrono::high_resolution_clock > Timestamp
Type type() const override
support for partial derivatives needed for implicit method
void update(double *fv, std::size_t n, const double *sv)
initialise flow and stock var array pointers
const Index & index(Index &&x) override
std::shared_ptr< ITensor > TensorPtr
const Hypercube & hypercube() const override
static std::vector< double, CIVITA_ALLOCATOR< double > > flowVars
variables defined as a simple function of the stock variables, also known as lhs variables. These variables appear in the body of the Godley table
TensorVarVal(const std::shared_ptr< VariableValue > &vv, const shared_ptr< EvalCommon > &ev)
const Hypercube & hypercube(Hypercube &&hc) override
TensorEval(const std::shared_ptr< VariableValue > &v, const shared_ptr< EvalCommon > &ev, const TensorPtr &rhs)
const Index & index() const override
TensorVarVal & operator=(const ITensor &t) override
TensorOpFactory tensorOpFactory
std::size_t size() const override
double dStock(std::size_t ti, std::size_t si) const override
partial derivative of tensor component ti wrt stock variable si
double operator[](std::size_t i) const override
double * flowVars() const
const double * stockVars() const
TensorVarValBase(const std::shared_ptr< VV > &vv, const shared_ptr< EvalCommon > &ev)
std::size_t fvSize() const