Skip to content

Commit

Permalink
Version 0.2.1
Browse files Browse the repository at this point in the history
Updated Vensim translator to make use of parsimonious node visitor.
  • Loading branch information
JamesPHoughton committed Mar 28, 2015
1 parent a61b974 commit b4a4c6d
Show file tree
Hide file tree
Showing 7 changed files with 461 additions and 231 deletions.
18 changes: 8 additions & 10 deletions pysd/functions/functions.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@

# coding: utf-8

# In[5]:

import numpy as np

def if_then_else(condition, val_if_true, val_if_false):
Expand All @@ -12,18 +8,22 @@ def if_then_else(condition, val_if_true, val_if_false):
return val_if_false


def step(value, tstep, t):
def step(value, tstep):
t = self.components.state['t']
return value if t >=tstep else 0


def pulse(start, duration, t):
def pulse(start, duration):
t = self.components.state['t']
return 1 if t>=start and t<start+duration else 0

# I'm not totally sure if this is correct
def pulse_train(start, duration, repeattime, end, t):
def pulse_train(start, duration, repeattime, end):
t = self.components.state['t']
return 1 if t>=start and (t-start)%repeattime < duration else 0

def ramp(slope, start, finish, t):
def ramp(slope, start, finish):
t = self.components.state['t']
if t<start:
return 0
elif t>finish:
Expand All @@ -40,7 +40,5 @@ def bounded_normal(minimum, maximum, mean, std, seed):
return value


# In[ ]:



57 changes: 40 additions & 17 deletions pysd/translators/component_class_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,36 @@

# Todo:
# - the __doc__ attribute isn't something that you can call, need to rework it, along with the __str_ method
#
#
#
#
#
#
#
#
#
#
#
#

# it would be nice to dynamically generate the docstring (or some sortof 'help' string)
# so that if the model is modified, the user can see the current state of modifications



class component_class_template:
"""
This is a template class to be subclassed and fleshed out by the translation tools.
The state dictionary should be expanded to include all of the model stocks.
A function should be added for every flow or auxiliary variable, having the name of that
variable, taking no parameters, which calculates the value of the variable.
A function should be added for each stock called d<stockname>_dt() which calculates
the net inflow to the stock as a function of the flows.
A function should be added for each stock called <stockname>_init() which calculates
the (potentially dynamically generated) initial value for the stock.
This docstring will be rewritten and dynamically generated.
"""

state = {}

def __init__(self):
self.reset_state()


def __doc__(self):
docstring = self.__str__ + '\n\n'
for method in dir(self):
Expand All @@ -38,14 +47,24 @@ def __doc__(self):
pass

return docstring


def initial_time(self):
"""
This function represents the initial time as set in the model file
It should be overwritten during the class extension.
"""
return 0


def reset_state(self):
self.t = self.initial_time() #set the initial time

for key in self.state.keys():
self.state[key] = eval('self._'+key+'_init()') #set the initial state
self.state[key] = eval('self.'+key+'_init()') #set the initial state
pass



def d_dt(self, state_vector, t):
"""
The primary purpose of this function is to interact with the integrator.
Expand All @@ -64,7 +83,11 @@ def d_dt(self, state_vector, t):

def state_vector(self):
"""
This function interacts with the integrator by setting the initial values of the state vector.
It returns the values of the state dictionary, sorted alphabetically by key
This function interacts with the integrator by setting the
initial values of the state vector.
It returns the values of the state dictionary, sorted
alphabetically by key.
"""
return [self.state[key] for key in sorted(self.state.keys())]

27 changes: 1 addition & 26 deletions pysd/translators/helpers.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,11 @@
import collections

def clean_identifier(string):
"""
at the moment, we may have trailing spaces on an identifier that need to be dealt with
in the future, it would be better to improve the parser so that it handles that whitespace properly
"""
string = string.lower()
string = string.strip()
string = string.replace(' ', '_')
return string



def update(d, u):
"""
Facilitates nested dictionary updating.
This is stolen from:
http://stackoverflow.com/questions/3232943/update-value-of-a-nested-dictionary-of-varying-depth
"""
for k, v in u.iteritems():
if isinstance(v, collections.Mapping):
r = update(d.get(k, {}), v)
d[k] = r
else:
d[k] = u[k]
return d



def getChildren(node, name):
"""
Returns the children of node 'node' that are named 'name'
in a list.
"""
return [child for child in node.children if child.expr_name == name]

0 comments on commit b4a4c6d

Please sign in to comment.