Skip to content

Commit

Permalink
Fix bugs and allow to translate models with no included functions
Browse files Browse the repository at this point in the history
  • Loading branch information
enekomartinmartinez committed Mar 3, 2022
1 parent 6ddcf87 commit 9d54d97
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 12 deletions.
2 changes: 1 addition & 1 deletion pysd/building/python/python_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# functions that can be diretcly applied over an array
functionspace = {
# directly build functions without dependencies
"elmcount": ("len(_subscript_dict['%(0)s'])", None),
"elmcount": ("len(%(0)s)", None),

# directly build numpy based functions
"abs": ("np.abs(%(0)s)", ("numpy",)),
Expand Down
27 changes: 24 additions & 3 deletions pysd/building/python/visitors.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,26 @@ def __init__(self, call_str, component):
elif function_name == "a_function_of":
self.build = self.build_incomplete_call
else:
# error
raise ValueError("Undefined function %s" % function_name)
self.function = function_name
self.build = self.build_not_implemented

def build_not_implemented(self, arguments):
final_subscripts = self.reorder(arguments, def_subs=self.def_subs)
warnings.warn(
"\n\nTrying to translate "
+ self.function
+ " which it is not implemented on PySD. The translated "
+ "model will crash... "
)
self.section.imports.add("functions", "not_implemented_function")

return BuildAST(
expression="not_implemented_function('%s', %s)" % (
self.function,
", ".join(arg.expression for arg in arguments.values())),
calls=self.join_calls(arguments),
subscripts=final_subscripts,
order=0)

def build_macro_call(self, arguments):
self.section.imports.add("statefuls", "Macro")
Expand Down Expand Up @@ -1045,7 +1063,10 @@ def visit_subscripts(self, expression, original_subs):
# NUMPY: subset value [:, :, np.array([1, 0]), :]
# NUMPY: as order may change we need to check if dim != orig_dim
# NUMPY: use also ranges [:, :, 2:5, :] when possible
loc.append("_subscript_dict['%s']" % dim)
if dim.endswith("!"):
loc.append("_subscript_dict['%s']" % dim[:-1])
else:
loc.append("_subscript_dict['%s']" % dim)
final_subs[dim] = coord
float = False
else:
Expand Down
7 changes: 4 additions & 3 deletions pysd/py_backend/lookups.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,21 +71,22 @@ def __init__(self, x, y, coords, py_name):
# TODO: avoid add and merge all declarations in one definition
self.is_float = not bool(coords)
self.py_name = py_name
y = np.array(y).reshape((len(x),) + (1,)*len(coords))
self.data = xr.DataArray(
np.array(y).reshape(tuple([len(x)] + utils.compute_shape(coords))),
np.tile(y, [1] + utils.compute_shape(coords)),
{"lookup_dim": x, **coords},
["lookup_dim"] + list(coords)
)
self.x = set(x)

def add(self, x, y, coords):
y = np.array(y).reshape((len(x),) + (1,)*len(coords))
self.data = self.data.combine_first(
xr.DataArray(
np.array(y).reshape(tuple([len(x)] + utils.compute_shape(coords))),
np.tile(y, [1] + utils.compute_shape(coords)),
{"lookup_dim": x, **coords},
["lookup_dim"] + list(coords)
))

if np.any(np.isnan(self.data)):
# fill missing values of different input lookup_dim values
values = self.data.values
Expand Down
10 changes: 5 additions & 5 deletions pysd/translation/vensim/parsing_expr/components.peg
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

expr_type = array / final_expr / empty

final_expr = logic_expr _ (logic_oper _ logic_expr)* # logic operators (:and:, :or:)
final_expr = logic_expr (_ logic_oper _ logic_expr)* # logic operators (:and:, :or:)
logic_expr = not_oper? _ comp_expr # :not: operator
comp_expr = add_expr _ (comp_oper _ add_expr)? # comparison (e.g. '<', '=>')
add_expr = prod_expr _ (add_oper _ prod_expr)* # addition and substraction
prod_expr = exp_expr _ (prod_oper _ exp_expr)* # product and division
exp_expr = neg_expr _ (exp_oper _ neg_expr)* # exponential
comp_expr = add_expr (_ comp_oper _ add_expr)? # comparison (e.g. '<', '=>')
add_expr = prod_expr (_ add_oper _ prod_expr)* # addition and substraction
prod_expr = exp_expr (_ prod_oper _ exp_expr)* # product and division
exp_expr = neg_expr (_ exp_oper _ neg_expr)* # exponential
neg_expr = pre_oper? _ expr # pre operators (-, +)
expr = lookup_with_def / call / parens / number / reference / nan

Expand Down

0 comments on commit 9d54d97

Please sign in to comment.