1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
import time, types, itertools
from scipy.interpolate import interp1d
from scipy.integrate import odeint
from scipy.optimize import fmin
class DiffEq(object):
"""designed to make numerically solving diff eqs more readable
setattr and getattr have been modified to provide the following effects:
>>> self._foo=2 #setting an _under var makes it still callable by...
>>> self.foo
2
>>> # Now suppose foo is a class method and bar is in _flags.
>>> self.foo #finding the object having not found it before
#self.foo() is called and stored to self.__foo
#self.__foo is returned
>>> self.foo #finding the object having asked for it before
#self.__foo is returned
>>> self.bar=2 #setting bar resets all self.__foos
>>> self.foo #self.foo() is called again, self.__foo returned
Note that with this behavior you should treat all variable names, be they
normal, _under, or __dunder, as in the same namespace. Don't even try to
differentiate variable names by underscores.
The benefit of this system is that every normal float will be optimized,
while every _under float will be ignored completely, and flagging a var
with _under will not change the behavior of any functions using it.
Additionally, if you suddenly realize that foo should be dependent on
bar and baz, you simply define:
def foo(self):
return do_stuff(self.bar, self.baz)
and bar and baz will be optimized while foo will be ignored -- and no
function code using foo needs to be rewritten.
"""
def __init__(self):
self._time = time.time()
# All floats lacking an initial _underscore will be optimized.
self.opt_vars = {}
for key, value in vars(self).items():
if key[0] == "_": continue
if type(value) != float: continue
self.opt_vars[key] = value
def time(self): return time.time() - self.time
def __getattribute__(self, attr):
"""Provides a few getattr psuedonyms:
allows self.foo to return:
self._foo if self.foo DNE
self.foo() if self.foo is a method
(be very wary of storing variables under these conditions!)
"""
sgetattr = super(DiffEq, self).__getattribute__
try:
value = sgetattr(attr)
if type(value) == types.MethodType:
try: value = sgetattr("__" + attr)
except AttributeError:
value = value()
setattr(self, "__" + attr, value)
except AttributeError as err:
if attr[0] == "_": raise err
else: value = sgetattr("_" + attr)
return value
_flags = []
def __setattribute__(self, attr):
"""Clears dunder updates when phi or phi1 are changed."""
sgetattr = super(DiffEq, self).__getattribute__
ssetattr = super(DiffEq, self).__setattribute__
if attr in self.flags:
for key, value in vars(self).items():
if key[:2] != "__": continue
if type(sgetattr(key[2:])) != types.MethodType: continue
vars(self).remove(key)
ssetattr(attr)
def check_in(self, variables):
"""Usage is as follows.
def method(self, var0=None, var1=None, ...):
self.check_in(vars())
return do_stuff_with_vars()
"""
for key, var in variables.items():
if var == None:
variables[key] = getattr(self, key)
def solve_fun(self, func=None, init_vars=None, timespace=None):
"""wrapper for odeint"""
check_in(vars())
time0 = current_time()
time = numpy.linspace(*timespace)
soln = odeint(func, init_vars, time)
print " :: took %s seconds" % (current_time() - time0)
return time, soln
#in optimize(): vars().update(self.opt_vars)
|