I have a webform-based macroeconomics model here that takes parameters and inputs and solves a system of linear equations.
webapp2 handler:
class Islm(webapp2.RequestHandler):
def get(self):
a = self.request.get('a')
b = self.request.get('b')
c = self.request.get('c')
d = self.request.get('d')
A = self.request.get('A')
G = self.request.get('G')
T = self.request.get('T')
M = self.request.get('M')
P = self.request.get('P')
template_values = {
'url': url,
'url_linktext': url_linktext,
'a': a,
'b': b,
'c': c,
'd': d,
'A': A,
'G': G,
'T': T,
'M': M,
'P': P
}
if a: # need to change to have a better validation test.
kwargs = {'a': float(a),
'b': float(b),
'c': float(c),
'd': float(d),
'A': float(A),
'G': float(G),
'T': float(T),
'M': float(M),
'P': float(P)
}
Y, E, r = islm(**kwargs)
template_values['Y'] = float(Y)
template_values['E'] = float(E)
template_values['r'] = float(r)
else:
pre_solve = 'ENTER VALUES'
template_values['Y'] = pre_solve
template_values['E'] = pre_solve
template_values['r'] = pre_solve
template = jinja_environment.get_template('islm.html')
self.response.out.write(template.render(template_values))
solver:
import numpy as np
def islm(**kwargs):
a = kwargs['a']
b = kwargs['b']
c = kwargs['c']
d = kwargs['d']
A = kwargs['A']
G = kwargs['G']
T = kwargs['T']
M = kwargs['M']
P = kwargs['P']
matrix_a = np.matrix([[1,-1,0],
[-1*a,1,b],
[c,0,-1*d]],
dtype=float)
matrix_b = np.matrix([[0, 1, 0, 0],
[1, 0, -1*a, 0],
[0, 0, 0, 1/P]],
dtype=float)
matrix_c = np.matrix([[A],
[G],
[T],
[M]],
dtype=float)
return np.dot(np.linalg.inv(matrix_a), np.dot(matrix_b, matrix_c))
I know this code is disgusting, I just have no idea how to eliminate the DRY required to do the following for each parameter:
Thanks.
You can start by making tuples of all of your inputs and outputs:
input_vars = ('a', 'b', 'c', 'd', 'A', 'G', 'T', 'M', 'P')
output_vars = ('Y', 'E', 'r')
You can also just leave template_values
with a few values in it and populate the rest dynamically:
template_values = {
'url': url,
'url_linktext': url_linktext,
}
Now you can dynamically create kwargs
and fill up template_values
:
kwargs = {}
complete = True
for var in input_vars:
template_values[var] = self.request.get(var)
if var in self.request:
try:
kwargs[var] = float(self.request[var])
except ValueError:
# not a number
complete = False
else:
# not provided
complete = False
Here, we also have a variable complete
; if everything was provided and was successfully parsed as a float, complete
will be True
. If something wasn't provided or failed to parse as a float, complete
will be False
.
Now we can run the solver:
if complete:
output = islm(**kwargs)
for var, value in zip(output_vars, output):
template_values[var] = value
else:
for var in output_vars:
template_values[var] = 'ENTER VALUES'
Here, if it's complete, we can run the solver and then put the output values into the template_values
. Otherwise we just set each template variable to 'ENTER VALUES'
.
As for your solver, there's no need to take a **kwargs
argument. Just do this:
def islm(a, b, c, d, A, G, T, M, P):
matrix_a = # ...
# ...
return np.dot( # ...