summaryrefslogtreecommitdiff
path: root/diffeq.py
diff options
context:
space:
mode:
authorJoe Anderson <jandew+dev@gmail.com>2011-11-17 11:01:26 -0600
committerJoe Anderson <jandew+dev@gmail.com>2011-11-17 11:01:26 -0600
commit6217fa89192107bd4d9c651d095dd6f898ea78d6 (patch)
tree3b650e555289e6f8c5531a3b66306fa5d582fdb8 /diffeq.py
parentf99ad4ed9e5611ced9196e5e9cb875667e03bdc1 (diff)
downloadtoss-master.tar.gz
toss-master.zip
Lots of progress, still a ways to goHEADmaster
Diffstat (limited to 'diffeq.py')
-rw-r--r--diffeq.py86
1 files changed, 45 insertions, 41 deletions
diff --git a/diffeq.py b/diffeq.py
index 1a756e1..b2e8124 100644
--- a/diffeq.py
+++ b/diffeq.py
@@ -1,39 +1,34 @@
-import time, types, itertools
+import time, types, itertools, os.path
from scipy.interpolate import interp1d
from scipy.integrate import odeint
from scipy.optimize import fmin
+from collections import OrderedDict
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.#setting an _under var makes it still returned by...
>>> self.foo
- 2
- >>> self.foo is self._foo
- True #so they share the same namespace
-
- >>> # Now suppose foo is a class method and bar is in _flags.
+ 2.0
+ >>> self._foo=2 #but only if it's a float
+ >>> self.foo
+ AttributeError: self has no attribute 'foo'
+ >>> # Now suppose _foo is a class method and bar is in _flags.
+ >>> self._foo = lambda self: self.bar
+ >>> self.flags.append('bar')
+ >>> self.bar = 3.14
>>> 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() is called and stored to self.__foo
+ 3.14 #self.__foo is returned
>>> self.foo #finding the object having asked for it before:
- #self.__foo is returned
+ 3.14 #self.__foo is returned directly
>>> self.bar=2 #setting bar resets all self.__foos
- >>> self.foo #self.foo() is called again, self.__foo returned
-
- >>> # You can also subvert the second mechanism using the first,
- >>> # as the mechansims do not recurse on themselves.
- >>> # Suppose _foo is a class method, bar is in _flags
- >>> self.foo
- <bound method self._foo of ... >
- >>> self._foo
- <bound method self._foo of ... >
- >>> self
- >>> # The class is prevented from creating ___trunder variables.
+ >>> self.foo #self._foo() is called again, stored to self.__foo
+ 2 #the new self.__foo is 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
@@ -44,7 +39,7 @@ class DiffEq(object):
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):
+ 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.
@@ -53,33 +48,35 @@ class DiffEq(object):
self._time = time.time()
# All floats lacking an initial _underscore will be optimized.
- self.opt_vars = {}
+ self.opt_vars = OrderedDict()
for key, value in vars(self).items():
if key[0] == "_": continue
if type(value) != float: continue
self.opt_vars[key] = value
- def _gettime(self): return time.time() - self.time
+ def gettime(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
+ self.foo tries to return:
+ self.foo if foo exists
+ self._foo if _foo is a float
+ self._foo() if _foo is a method
see DiffEq's documentation for examples
"""
sgetattr = super(DiffEq, self).__getattribute__
- try:
- value = sgetattr(attr)
- if type(value) == types.MethodType and attr[0] != '_':
- try: value = sgetattr("__" + attr)
+ try: return sgetattr(attr)
+ except AttributeError as err:
+ if attr[0] == "_": raise err
+ value = sgetattr("_" + attr)
+ if type(value) == types.MethodType:
+ try: return 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
+ return value
+ if type(value) == float: return value
+ raise err
_flags = []
def __setattribute__(self, attr):
@@ -106,17 +103,24 @@ class DiffEq(object):
self.soln = odeint(self.diff_eq, self.init_vars, self.time)
print " :: took %s seconds" % (self.gettime() - time0)
- #in optimize(): vars().update(self.opt_vars)
+ def opt_init(self, guesses=None):
+ if guesses == None:
+ for var in self.opt_vars:
+ self.opt_vars[var] = getattr(self, var)
+ else:
+ for var, guess in itertools.izip(self.opt_vars, guesses):
+ setattr(self, var, guess)
+
+ #_outfile = tempfile.mktemp(dir='data', prefix=str(self.gettime()))
+ outfile = lambda: os.path.join('data', str(self.gettime()))
def opt_fun(self, guesses, f, func, init_vars):
"""Optimize the free variables for the diff eq."""
- for key, val in zip(opt_vars.iterkeys(), guesses):
- setattr(self, key, val)
- #map(setattr, self, opt_vars.iterkeys(), guesses)
+ self.opt_init()
+ map(setattr, itertools.repeat(self), self.opt_vars.iterkeys(), guesses)
self.__dict__.update(dict(zip(self.opt_vars.iterkeys(), guesses)))
outfile = self.__dict__.get('outfile')
- r0, r_roll, length, m, Mass = guesses
- time, soln = solve_fun(func, init_vars)
+ time, soln = self.solve_diff_eq()
phi, phi1, v_tan, tension, moment, momentum, max_arg = \
interpret(soln)