## [PyX-checkins] pyx/test/experimental test_solve.py,NONE,1.1 solve.py,1.4,1.5

 [PyX-checkins] pyx/test/experimental test_solve.py,NONE,1.1 solve.py,1.4,1.5 From: André Wobst - 2004-07-30 20:05:37 ```Update of /cvsroot/pyx/pyx/test/experimental In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16193 Modified Files: solve.py Added Files: test_solve.py Log Message: - allow for intermediate, non-linear terms - scalar()*vector() (however, as far as I can see, transformation still don't fit into the design) Index: solve.py =================================================================== RCS file: /cvsroot/pyx/pyx/test/experimental/solve.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** solve.py 29 Jul 2004 10:25:10 -0000 1.4 --- solve.py 30 Jul 2004 20:05:27 -0000 1.5 *************** *** 21,63 **** # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - import types, sets import Numeric, LinearAlgebra - valuetypes = (types.IntType, types.LongType, types.FloatType) - - class scalar: ! # this class represents a scalar variable ! def __init__(self, varname="(no variable name provided)"): ! self.varname = varname self.value = None ! self.zero = 0 def term(self): ! return term([1], [self], self.zero) def __add__(self, other): ! return term([1], [self], self.zero) + other __radd__ = __add__ - def __neg__(self): - return term([-1], [self], self.zero) - def __sub__(self, other): ! return term([1], [self], self.zero) - other def __rsub__(self, other): ! return term([-1], [self], self.zero) + other def __mul__(self, other): ! return term([other], [self], self.zero) __rmul__ = __mul__ def __div__(self, other): ! return term([1/other], [self], self.zero) def is_set(self): --- 21,63 ---- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import Numeric, LinearAlgebra class scalar: ! # represents a scalar variable or constant ! def __init__(self, value=None, varname="unnamed_scalar"): self.value = None ! if value is not None: ! self.set(value) ! self.varname = varname ! ! def addend(self): ! return addend([self], None) def term(self): ! return term([self.addend()]) def __add__(self, other): ! return self.term() + other __radd__ = __add__ def __sub__(self, other): ! return self.term() - other def __rsub__(self, other): ! return -self.term() + other ! ! def __neg__(self): ! return -self.addend() def __mul__(self, other): ! return self.addend()*other __rmul__ = __mul__ def __div__(self, other): ! return self.addend()/other def is_set(self): *************** *** 67,71 **** if self.is_set(): raise RuntimeError("variable already defined") ! self.value = value def get(self): --- 67,74 ---- if self.is_set(): raise RuntimeError("variable already defined") ! try: ! self.value = float(value) ! except: ! raise RuntimeError("float expected") def get(self): *************** *** 76,80 **** def __str__(self): if self.is_set(): ! return "%s[=%s]" % (self.varname, self.value) else: return self.varname --- 79,83 ---- def __str__(self): if self.is_set(): ! return "%s{=%s}" % (self.varname, self.value) else: return self.varname *************** *** 84,94 **** ! class vector(scalar): ! def __init__(self, dimension, varname="(no variable name provided)"): ! scalar.__init__(self, varname=varname) ! del self.value # XXX disallow is_set, set, get ! self.scalars = [scalar(varname="%s%i" % (varname, i)) for i in range(dimension)] ! self.zero = point(*([0]*len(self.scalars))) def __len__(self): --- 87,107 ---- ! class vector: ! # represents a vector, i.e. a list of scalars ! def __init__(self, dimension_or_values, varname="unnamed_vector"): ! try: ! varname + "" ! except TypeError: ! raise RuntimeError("a vectors varname should be a string (you probably wanted to write vector([x, y]) instead of vector(x, y))") ! try: ! # values ! self.scalars = [scalar(value=value, varname="%s[%i]" % (varname, i)) ! for i, value in enumerate(dimension_or_values)] ! except (TypeError, AttributeError): ! # dimension ! self.scalars = [scalar(varname="%s[%i]" % (varname, i)) ! for i in range(dimension_or_values)] ! self.varname = varname def __len__(self): *************** *** 98,200 **** return self.scalars[i] ! def __str__(self): ! return "%s[=(%s)]" % (self.varname, ",".join([str(scalar) for scalar in self.scalars])) ! class point: ! def __init__(self, *values): ! self.values = values ! def term(self): ! return term([], [], self) def __len__(self): ! return len(self.values) def __getitem__(self, i): ! return self.values[i] ! def __add__(self, other): try: ! # other might be a point and we should return a point ! # (this is the typical case for term.const in a vector equation) ! return point(*[x + y for x, y in zip(self.values, other.values)]) ! except AttributeError: ! # otherwise perform a term-like addition ! return self.term() + other ! __radd__ = __add__ ! def __neg__(self): ! return point(*[-value for value in self.values]) def __sub__(self, other): ! return -other+self def __rsub__(self, other): ! return -self+other def __mul__(self, other): ! return point(*[other*value for value in self.values]) __rmul__ = __mul__ def __div__(self, other): ! return point(*[value/other for value in self.values]) class term: ! # this class represents the linear term: ! # sum([prefactor*var.value for prefactor, var in zip(self.prefactors, self.vars]) + self.const ! def __init__(self, prefactors, vars, const): try: ! l = len(const) ! except (AttributeError, TypeError): ! for var in vars: try: ! len(var) ! except (AttributeError, TypeError): pass else: ! raise RuntimeError("vector variable found in a non-vector term") else: ! for var in vars: try: ! if l != len(var): ! raise RuntimeError("vector length mismatch in vector term") ! except (AttributeError, TypeError): ! raise RuntimeError("scalar variable found in a vector term") ! assert len(prefactors) == len(vars) ! self.prefactors = prefactors ! self.vars = vars ! self.const = const def term(self): return self def __add__(self, other): try: ! other = other.term() except: ! other = term([], [], other) ! vars = self.vars[:] ! prefactors = self.prefactors[:] ! for prefactor, var in zip(other.prefactors, other.vars): ! try: ! # try to modify prefactor for existing variables ! prefactors[vars.index(var)] += prefactor ! except ValueError: ! # or add the variable ! vars.append(var) ! prefactors.append(prefactor) ! return term(prefactors, vars, self.const + other.const) __radd__ = __add__ def __neg__(self): ! return term([-prefactor for prefactor in self.prefactors], self.vars, -self.const) def __sub__(self, other): --- 111,305 ---- return self.scalars[i] ! def __getattr__(self, attr): ! if attr == "x": ! return self[0] ! if attr == "y": ! return self[1] ! if attr == "z": ! return self[2] ! else: ! raise AttributeError(attr) + def addend(self): + return addend([], self) ! def term(self): ! return term([self.addend()]) ! def __add__(self, other): ! return self.term() + other ! ! __radd__ = __add__ ! ! def __sub__(self, other): ! return self.term() - other ! ! def __rsub__(self, other): ! return -self.term() + other ! ! def __neg__(self): ! return -self.addend() ! ! def __mul__(self, other): ! return self.addend()*other ! ! __rmul__ = __mul__ ! ! def __div__(self, other): ! return self.addend()/other ! ! def __str__(self): ! return "%s{=(%s)}" % (self.varname, ", ".join([str(scalar) for scalar in self.scalars])) ! ! class addend: ! # represents an addend of a term, i.e. a list of scalars and ! # optionally a vector (for a vector term) otherwise the vector ! # is None ! ! def __init__(self, scalars, vector): ! # self.vector might be None for a scalar addend ! self.scalars = scalars ! self.vector = vector def __len__(self): ! return len(self.vector) def __getitem__(self, i): ! return addend(self.scalars + [self.vector[i]], None) ! def addend(self): ! return self ! ! def term(self): ! return term([self.addend()]) ! ! def is_linear(self): ! assert self.vector is None ! return len([scalar for scalar in self.scalars if not scalar.is_set()]) < 2 ! ! def prefactor(self): ! assert self.is_linear() ! prefactor = 1 ! for scalar_set in [scalar for scalar in self.scalars if scalar.is_set()]: ! prefactor *= scalar_set.get() ! return prefactor ! ! def variable(self): ! assert self.is_linear() try: ! variable, = [scalar for scalar in self.scalars if not scalar.is_set()] ! except ValueError: ! return None ! else: ! return variable ! def __add__(self, other): ! return self.term() + other ! __radd__ = __add__ def __sub__(self, other): ! return self.term() - other def __rsub__(self, other): ! return -self.term() + other ! ! def __neg__(self): ! return addend([scalar(-1)] + self.scalars, self.vector) def __mul__(self, other): ! try: ! a = other.addend() ! except (TypeError, AttributeError): ! try: ! t = other.term() ! except (TypeError, AttributeError): ! return self*scalar(other) ! else: ! return term([self*a for a in t.addends]) ! else: ! if a.vector is not None: ! if self.vector is not None: ! if len(self.vector) != len(a.vector): ! raise RuntimeError("vector length mismatch in scalar product") ! return term([addend(self.scalars + a.scalars + [x*y], None) ! for x, y in zip(self.vector, a.vector)]) ! else: ! return addend(self.scalars + a.scalars, a.vector) ! else: ! return addend(self.scalars + a.scalars, self.vector) __rmul__ = __mul__ def __div__(self, other): ! return addend([scalar(1/other)] + self.scalars, self.vector) ! ! def __str__(self): ! scalarstring = " * ".join([str(scalar) for scalar in self.scalars]) ! if self.vector is None: ! return scalarstring ! else: ! if len(scalarstring): ! scalarstring += " * " ! return scalarstring + str(self.vector) class term: ! # represents a term, i.e. a list of addends ! def __init__(self, addends): ! assert len(addends) try: ! self.length = len(addends[0]) ! except (TypeError, AttributeError): ! for addend in addends[1:]: try: ! len(addend) ! except (TypeError, AttributeError): pass else: ! raise RuntimeError("vector addend in scalar term") ! self.length = None else: ! for addend in addends[1:]: try: ! l = len(addend) ! except (TypeError, AttributeError): ! raise RuntimeError("scalar addend in vector term") ! if l != self.length: ! raise RuntimeError("vector length mismatch in term constructor") ! self.addends = addends ! def __len__(self): ! if self.length is None: ! raise AttributeError("scalar term") ! else: ! return self.length ! ! def __getitem__(self, i): ! return term([addend[i] for addend in self.addends]) def term(self): return self + def is_linear(self): + is_linear = 1 + for addend in self.addends: + is_linear = is_linear and addend.is_linear() + return is_linear + def __add__(self, other): try: ! t = other.term() except: ! return self + scalar(other) ! else: ! return term(self.addends + t.addends) __radd__ = __add__ def __neg__(self): ! return term([-addend for addend in self.addends]) def __sub__(self, other): *************** *** 205,217 **** def __mul__(self, other): ! return term([other*prefactor for prefactor in self.prefactors], self.vars, other*self.const) __rmul__ = __mul__ def __div__(self, other): ! return term([prefactor/other for prefactor in self.prefactors], self.vars, self.const/other) def __str__(self): ! return "+".join(["%s*%s" % pv for pv in zip(self.prefactors, self.vars)]) + "+" + str(self.const) --- 310,322 ---- def __mul__(self, other): ! return term([addend*other for addend in self.addends]) __rmul__ = __mul__ def __div__(self, other): ! return term([addend/other for addend in self.addends]) def __str__(self): ! return " + ".join([str(addend) for addend in self.addends]) *************** *** 220,224 **** def __init__(self): ! self.eqs = [] # equations still to be taken into account def eq(self, lhs, rhs=None): --- 325,329 ---- def __init__(self): ! self.eqs = [] # scalar equations not yet solved (a equation is a term to be zero here) def eq(self, lhs, rhs=None): *************** *** 227,252 **** else: eq = lhs - rhs ! if not len(eq.vars): ! raise RuntimeError("equation without variables") try: # is it a vector equation? ! neqs = len(eq.vars[0].scalars) ! except AttributeError: ! for v in eq.vars[1:]: ! try: ! v.scalars ! except AttributeError: ! pass ! else: ! raise RuntimeError("mixed scalar/vector equation") ! solver.add(eq) else: - for v in eq.vars[1:]: - if len(v.scalars) != neqs: - raise RuntimeError("vectors of different dimension") - if len(eq.const.values) != neqs: - raise RuntimeError("wrong dimension of constant") for i in range(neqs): ! self.add(term(eq.prefactors, [var[i] for var in eq.vars], eq.const[i])) def add(self, equation): --- 332,344 ---- else: eq = lhs - rhs ! eq = eq.term() try: # is it a vector equation? ! neqs = len(eq) ! except (TypeError, AttributeError): ! self.add(eq) else: for i in range(neqs): ! self.add(eq[i]) def add(self, equation): *************** *** 263,267 **** def combine(self, eqs): ! # create combinations of equations if not len(eqs): yield [] --- 355,359 ---- def combine(self, eqs): ! # create combinations of linear equations if not len(eqs): yield [] *************** *** 269,293 **** for x in self.combine(eqs[1:]): yield x ! yield [eqs[0]] + x def solve(self, eqs): ! # try to solve a set of equations l = len(eqs) if l: vars = [] for eq in eqs: ! vars.extend([var for var in eq.vars if var not in vars and not var.is_set()]) if len(vars) == l: a = Numeric.zeros((l, l)) b = Numeric.zeros((l, )) for i, eq in enumerate(eqs): ! for p, v in zip(eq.prefactors, eq.vars): ! if v.is_set(): ! b[i] -= p*v.value else: ! a[i, vars.index(v)] += p ! b[i] -= eq.const for i, value in enumerate(LinearAlgebra.solve_linear_equations(a, b)): ! vars[i].value = value for eq in eqs: i, = [i for i, selfeq in enumerate(self.eqs) if selfeq == eq] --- 361,390 ---- for x in self.combine(eqs[1:]): yield x ! if eqs[0].is_linear(): ! for x in self.combine(eqs[1:]): ! yield [eqs[0]] + x def solve(self, eqs): ! # try to solve a set of linear equations l = len(eqs) if l: vars = [] for eq in eqs: ! for addend in eq.addends: ! var = addend.variable() ! if var is not None and var not in vars: ! vars.append(var) if len(vars) == l: a = Numeric.zeros((l, l)) b = Numeric.zeros((l, )) for i, eq in enumerate(eqs): ! for addend in eq.addends: ! var = addend.variable() ! if var is not None: ! a[i, vars.index(var)] += addend.prefactor() else: ! b[i] -= addend.prefactor() for i, value in enumerate(LinearAlgebra.solve_linear_equations(a, b)): ! vars[i].set(value) for eq in eqs: i, = [i for i, selfeq in enumerate(self.eqs) if selfeq == eq] *************** *** 307,316 **** z = vector(2, "z") ! solver.eq(4*x + y, 2*x - y + point(4, 0)) # => x + y = (2, 0) solver.eq(x[0] - y[0], z[1]) solver.eq(x[1] - y[1], z[0]) ! solver.eq(point(5, 0), z) ! ! print x, y, z ! --- 404,413 ---- z = vector(2, "z") ! solver.eq(4*x + y, 2*x - y + vector([4, 0])) # => x + y = (2, 0) solver.eq(x[0] - y[0], z[1]) solver.eq(x[1] - y[1], z[0]) ! solver.eq(vector([5, 0]), z) + print x + print y + print z --- NEW FILE: test_solve.py --- import unittest, operator from solve import scalar, vector, solver class ScalarTestCase(unittest.TestCase): def testInit(self): self.failUnlessRaises(RuntimeError, scalar, "") self.failUnlessRaises(RuntimeError, scalar, 1j) self.failUnlessEqual(str(scalar()), "unnamed_scalar") self.failUnlessEqual(str(scalar(varname="s")), "s") self.failUnlessEqual(str(scalar(1)), "unnamed_scalar{=1.0}") self.failUnlessEqual(str(scalar(-1, varname="s")), "s{=-1.0}") def testMath(self): self.failUnlessEqual(str(-scalar(varname="s")), "unnamed_scalar{=-1.0} * s") self.failUnlessEqual(str(scalar(varname="s") + scalar(varname="t")), "s + t") self.failUnlessEqual(str(scalar(varname="s") + 1), "s + unnamed_scalar{=1.0}") self.failUnlessEqual(str(1 + scalar(varname="s")), "s + unnamed_scalar{=1.0}") self.failUnlessEqual(str(scalar(varname="s") - scalar(varname="t")), "unnamed_scalar{=-1.0} * t + s") self.failUnlessEqual(str(1 - scalar(varname="s")), "unnamed_scalar{=-1.0} * s + unnamed_scalar{=1.0}") self.failUnlessEqual(str(2 * scalar(varname="s")), "s * unnamed_scalar{=2.0}") self.failUnlessEqual(str(scalar(varname="s") * 2), "s * unnamed_scalar{=2.0}") self.failUnlessEqual(str(scalar(varname="s") * scalar(varname="t")), "s * t") self.failUnlessEqual(str(scalar(varname="s") / 2.0), "unnamed_scalar{=0.5} * s") self.failUnlessEqual(str(scalar(varname="s") / 2), "unnamed_scalar{=0.0} * s") # integer logic! self.failUnlessRaises(TypeError, lambda: 2 / scalar()) self.failUnlessRaises(TypeError, lambda: scalar() / scalar()) self.failUnlessRaises(TypeError, lambda: vector(1) / scalar()) self.failUnlessRaises(TypeError, lambda: (scalar() + scalar()) / scalar()) self.failUnlessRaises(TypeError, lambda: (vector(1) + vector(1)) / scalar()) def testSetGetIs_Set(self): s = scalar() self.failUnlessEqual(s.is_set(), 0) self.failUnlessRaises(RuntimeError, s.get) self.failUnlessRaises(RuntimeError, float, s) s.set(2) self.failUnlessEqual(s.is_set(), 1) self.failUnlessAlmostEqual(s.get(), 2.0) self.failUnlessAlmostEqual(float(s), 2.0) self.failUnlessRaises(RuntimeError, s.set, 3) self.failUnlessEqual(s.is_set(), 1) self.failUnlessAlmostEqual(s.get(), 2.0) self.failUnlessAlmostEqual(float(s), 2.0) s = scalar(2) self.failUnlessEqual(scalar(2).is_set(), 1) self.failUnlessAlmostEqual(s.get(), 2.0) self.failUnlessAlmostEqual(float(s), 2.0) self.failUnlessRaises(RuntimeError, s.set, 3) self.failUnlessEqual(s.is_set(), 1) self.failUnlessAlmostEqual(s.get(), 2.0) self.failUnlessAlmostEqual(float(s), 2.0) class VectorTestCase(unittest.TestCase): def testInit(self): self.failUnlessRaises(RuntimeError, vector, 0, 0) self.failUnlessEqual(str(vector(2)), "unnamed_vector{=(unnamed_vector[0], unnamed_vector[1])}") self.failUnlessEqual(str(vector([1, 2])), "unnamed_vector{=(unnamed_vector[0]{=1.0}, unnamed_vector[1]{=2.0})}") self.failUnlessEqual(str(vector(3, "a")), "a{=(a[0], a[1], a[2])}") self.failUnlessEqual(str(vector([3, 2, 1], "a")), "a{=(a[0]{=3.0}, a[1]{=2.0}, a[2]{=1.0})}") def testAccess(self): a = vector(2) self.failUnlessEqual(str(a), "unnamed_vector{=(unnamed_vector[0], unnamed_vector[1])}") self.failUnlessEqual(a[0].is_set(), 0) self.failUnlessEqual(a.x.is_set(), 0) self.failUnlessEqual(a[1].is_set(), 0) self.failUnlessEqual(a.y.is_set(), 0) self.failUnlessRaises(IndexError, operator.__getitem__, a, 2) self.failUnlessRaises(IndexError, getattr, a, "z") a[0].set(2) self.failUnlessEqual(str(a), "unnamed_vector{=(unnamed_vector[0]{=2.0}, unnamed_vector[1])}") self.failUnlessAlmostEqual(a[0].get(), 2.0) self.failUnlessAlmostEqual(float(a[0]), 2.0) self.failUnlessAlmostEqual(a.x.get(), 2.0) self.failUnlessAlmostEqual(float(a.x), 2.0) self.failUnlessRaises(RuntimeError, a[1].get) self.failUnlessRaises(RuntimeError, float, a[1]) self.failUnlessRaises(RuntimeError, a.y.get) self.failUnlessRaises(RuntimeError, float, a.y) self.failUnlessEqual(a[0].is_set(), 1) self.failUnlessEqual(a.x.is_set(), 1) self.failUnlessEqual(a[1].is_set(), 0) self.failUnlessEqual(a.y.is_set(), 0) self.failUnlessRaises(RuntimeError, a[0].set, 3) self.failUnlessAlmostEqual(a[0].get(), 2.0) self.failUnlessAlmostEqual(float(a[0]), 2.0) self.failUnlessAlmostEqual(a.x.get(), 2.0) self.failUnlessAlmostEqual(float(a.x), 2.0) self.failUnlessRaises(RuntimeError, a[1].get) self.failUnlessRaises(RuntimeError, float, a[1]) self.failUnlessRaises(RuntimeError, a.y.get) self.failUnlessRaises(RuntimeError, float, a.y) self.failUnlessEqual(a[0].is_set(), 1) self.failUnlessEqual(a.x.is_set(), 1) self.failUnlessEqual(a[1].is_set(), 0) self.failUnlessEqual(a.y.is_set(), 0) a[1].set(3) self.failUnlessEqual(str(a), "unnamed_vector{=(unnamed_vector[0]{=2.0}, unnamed_vector[1]{=3.0})}") self.failUnlessAlmostEqual(a[0].get(), 2.0) self.failUnlessAlmostEqual(float(a[0]), 2.0) self.failUnlessAlmostEqual(a.x.get(), 2.0) self.failUnlessAlmostEqual(float(a.x), 2.0) self.failUnlessAlmostEqual(a[1].get(), 3.0) self.failUnlessAlmostEqual(float(a[1]), 3.0) self.failUnlessAlmostEqual(a.y.get(), 3.0) self.failUnlessAlmostEqual(float(a.y), 3.0) self.failUnlessEqual(a[0].is_set(), 1) self.failUnlessEqual(a.x.is_set(), 1) self.failUnlessEqual(a[1].is_set(), 1) self.failUnlessEqual(a.y.is_set(), 1) self.failUnlessRaises(RuntimeError, a[0].set, 4) self.failUnlessAlmostEqual(a[0].get(), 2.0) self.failUnlessAlmostEqual(float(a[0]), 2.0) self.failUnlessAlmostEqual(a.x.get(), 2.0) self.failUnlessAlmostEqual(float(a.x), 2.0) self.failUnlessAlmostEqual(a[1].get(), 3.0) self.failUnlessAlmostEqual(float(a[1]), 3.0) self.failUnlessAlmostEqual(a.y.get(), 3.0) self.failUnlessAlmostEqual(float(a.y), 3.0) self.failUnlessEqual(a[0].is_set(), 1) self.failUnlessEqual(a.x.is_set(), 1) self.failUnlessEqual(a[1].is_set(), 1) self.failUnlessEqual(a.y.is_set(), 1) a = vector([1, 2, 3]) self.failUnlessEqual(str(a.x), "unnamed_vector[0]{=1.0}") self.failUnlessEqual(str(a.y), "unnamed_vector[1]{=2.0}") self.failUnlessEqual(str(a.z), "unnamed_vector[2]{=3.0}") def testLen(self): for i in range(10): a = vector(i) self.failUnlessEqual(len(a), i) self.failUnlessEqual(str(a), "unnamed_vector{=(" + ", ".join(["unnamed_vector[%i]" % j for j in range(i)]) + ")}") for i in range(10): a = -vector(i) self.failUnlessEqual(len(a), i) self.failUnlessEqual(str(a), "unnamed_scalar{=-1.0} * unnamed_vector{=(" + ", ".join(["unnamed_vector[%i]" % j for j in range(i)]) + ")}") def testMath(self): self.failUnlessEqual(str(-vector(1, "a")), "unnamed_scalar{=-1.0} * a{=(a[0])}") self.failUnlessEqual(str(vector(1, "a") + vector(1, "t")), "a{=(a[0])} + t{=(t[0])}") self.failUnlessRaises(RuntimeError, operator.__add__, vector(1), scalar()) self.failUnlessRaises(RuntimeError, operator.__add__, vector(1), vector(2)) self.failUnlessEqual(str(vector(1, "a") - vector(1, "t")), "unnamed_scalar{=-1.0} * t{=(t[0])} + a{=(a[0])}") self.failUnlessRaises(RuntimeError, operator.__sub__, vector(1), scalar()) self.failUnlessRaises(RuntimeError, operator.__sub__, vector(1), vector(2)) self.failUnlessEqual(str(2 * vector(1, "a")), "unnamed_scalar{=2.0} * a{=(a[0])}") self.failUnlessEqual(str(vector(1, "a") * 2), "unnamed_scalar{=2.0} * a{=(a[0])}") self.failUnlessEqual(str(scalar(varname="s") * vector(1, "a")), "s * a{=(a[0])}") self.failUnlessEqual(str(vector(1, "a") * scalar(varname="s")), "s * a{=(a[0])}") self.failUnlessEqual(str(vector(2, "a") * vector(2, "b")), "a[0] * b[0] + a[1] * b[1]") self.failUnlessRaises(RuntimeError, operator.__mul__, vector(1, "a"), vector(2)) self.failUnlessEqual(str(vector(1, "a") / 2.0), "unnamed_scalar{=0.5} * a{=(a[0])}") self.failUnlessEqual(str(vector(1, "a") / 2), "unnamed_scalar{=0.0} * a{=(a[0])}") # integer logic! self.failUnlessRaises(TypeError, lambda: scalar() / vector(1)) self.failUnlessRaises(TypeError, lambda: vector(1) / vector(1)) self.failUnlessRaises(TypeError, lambda: (scalar() + scalar()) / vector(1)) self.failUnlessRaises(TypeError, lambda: (vector(1) + vector(1)) / vector(1)) if __name__ == "__main__": unittest.main() ```

 [PyX-checkins] pyx/test/experimental test_solve.py,NONE,1.1 solve.py,1.4,1.5 From: André Wobst - 2004-07-30 20:05:37 ```Update of /cvsroot/pyx/pyx/test/experimental In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16193 Modified Files: solve.py Added Files: test_solve.py Log Message: - allow for intermediate, non-linear terms - scalar()*vector() (however, as far as I can see, transformation still don't fit into the design) Index: solve.py =================================================================== RCS file: /cvsroot/pyx/pyx/test/experimental/solve.py,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** solve.py 29 Jul 2004 10:25:10 -0000 1.4 --- solve.py 30 Jul 2004 20:05:27 -0000 1.5 *************** *** 21,63 **** # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - import types, sets import Numeric, LinearAlgebra - valuetypes = (types.IntType, types.LongType, types.FloatType) - - class scalar: ! # this class represents a scalar variable ! def __init__(self, varname="(no variable name provided)"): ! self.varname = varname self.value = None ! self.zero = 0 def term(self): ! return term([1], [self], self.zero) def __add__(self, other): ! return term([1], [self], self.zero) + other __radd__ = __add__ - def __neg__(self): - return term([-1], [self], self.zero) - def __sub__(self, other): ! return term([1], [self], self.zero) - other def __rsub__(self, other): ! return term([-1], [self], self.zero) + other def __mul__(self, other): ! return term([other], [self], self.zero) __rmul__ = __mul__ def __div__(self, other): ! return term([1/other], [self], self.zero) def is_set(self): --- 21,63 ---- # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import Numeric, LinearAlgebra class scalar: ! # represents a scalar variable or constant ! def __init__(self, value=None, varname="unnamed_scalar"): self.value = None ! if value is not None: ! self.set(value) ! self.varname = varname ! ! def addend(self): ! return addend([self], None) def term(self): ! return term([self.addend()]) def __add__(self, other): ! return self.term() + other __radd__ = __add__ def __sub__(self, other): ! return self.term() - other def __rsub__(self, other): ! return -self.term() + other ! ! def __neg__(self): ! return -self.addend() def __mul__(self, other): ! return self.addend()*other __rmul__ = __mul__ def __div__(self, other): ! return self.addend()/other def is_set(self): *************** *** 67,71 **** if self.is_set(): raise RuntimeError("variable already defined") ! self.value = value def get(self): --- 67,74 ---- if self.is_set(): raise RuntimeError("variable already defined") ! try: ! self.value = float(value) ! except: ! raise RuntimeError("float expected") def get(self): *************** *** 76,80 **** def __str__(self): if self.is_set(): ! return "%s[=%s]" % (self.varname, self.value) else: return self.varname --- 79,83 ---- def __str__(self): if self.is_set(): ! return "%s{=%s}" % (self.varname, self.value) else: return self.varname *************** *** 84,94 **** ! class vector(scalar): ! def __init__(self, dimension, varname="(no variable name provided)"): ! scalar.__init__(self, varname=varname) ! del self.value # XXX disallow is_set, set, get ! self.scalars = [scalar(varname="%s%i" % (varname, i)) for i in range(dimension)] ! self.zero = point(*([0]*len(self.scalars))) def __len__(self): --- 87,107 ---- ! class vector: ! # represents a vector, i.e. a list of scalars ! def __init__(self, dimension_or_values, varname="unnamed_vector"): ! try: ! varname + "" ! except TypeError: ! raise RuntimeError("a vectors varname should be a string (you probably wanted to write vector([x, y]) instead of vector(x, y))") ! try: ! # values ! self.scalars = [scalar(value=value, varname="%s[%i]" % (varname, i)) ! for i, value in enumerate(dimension_or_values)] ! except (TypeError, AttributeError): ! # dimension ! self.scalars = [scalar(varname="%s[%i]" % (varname, i)) ! for i in range(dimension_or_values)] ! self.varname = varname def __len__(self): *************** *** 98,200 **** return self.scalars[i] ! def __str__(self): ! return "%s[=(%s)]" % (self.varname, ",".join([str(scalar) for scalar in self.scalars])) ! class point: ! def __init__(self, *values): ! self.values = values ! def term(self): ! return term([], [], self) def __len__(self): ! return len(self.values) def __getitem__(self, i): ! return self.values[i] ! def __add__(self, other): try: ! # other might be a point and we should return a point ! # (this is the typical case for term.const in a vector equation) ! return point(*[x + y for x, y in zip(self.values, other.values)]) ! except AttributeError: ! # otherwise perform a term-like addition ! return self.term() + other ! __radd__ = __add__ ! def __neg__(self): ! return point(*[-value for value in self.values]) def __sub__(self, other): ! return -other+self def __rsub__(self, other): ! return -self+other def __mul__(self, other): ! return point(*[other*value for value in self.values]) __rmul__ = __mul__ def __div__(self, other): ! return point(*[value/other for value in self.values]) class term: ! # this class represents the linear term: ! # sum([prefactor*var.value for prefactor, var in zip(self.prefactors, self.vars]) + self.const ! def __init__(self, prefactors, vars, const): try: ! l = len(const) ! except (AttributeError, TypeError): ! for var in vars: try: ! len(var) ! except (AttributeError, TypeError): pass else: ! raise RuntimeError("vector variable found in a non-vector term") else: ! for var in vars: try: ! if l != len(var): ! raise RuntimeError("vector length mismatch in vector term") ! except (AttributeError, TypeError): ! raise RuntimeError("scalar variable found in a vector term") ! assert len(prefactors) == len(vars) ! self.prefactors = prefactors ! self.vars = vars ! self.const = const def term(self): return self def __add__(self, other): try: ! other = other.term() except: ! other = term([], [], other) ! vars = self.vars[:] ! prefactors = self.prefactors[:] ! for prefactor, var in zip(other.prefactors, other.vars): ! try: ! # try to modify prefactor for existing variables ! prefactors[vars.index(var)] += prefactor ! except ValueError: ! # or add the variable ! vars.append(var) ! prefactors.append(prefactor) ! return term(prefactors, vars, self.const + other.const) __radd__ = __add__ def __neg__(self): ! return term([-prefactor for prefactor in self.prefactors], self.vars, -self.const) def __sub__(self, other): --- 111,305 ---- return self.scalars[i] ! def __getattr__(self, attr): ! if attr == "x": ! return self[0] ! if attr == "y": ! return self[1] ! if attr == "z": ! return self[2] ! else: ! raise AttributeError(attr) + def addend(self): + return addend([], self) ! def term(self): ! return term([self.addend()]) ! def __add__(self, other): ! return self.term() + other ! ! __radd__ = __add__ ! ! def __sub__(self, other): ! return self.term() - other ! ! def __rsub__(self, other): ! return -self.term() + other ! ! def __neg__(self): ! return -self.addend() ! ! def __mul__(self, other): ! return self.addend()*other ! ! __rmul__ = __mul__ ! ! def __div__(self, other): ! return self.addend()/other ! ! def __str__(self): ! return "%s{=(%s)}" % (self.varname, ", ".join([str(scalar) for scalar in self.scalars])) ! ! class addend: ! # represents an addend of a term, i.e. a list of scalars and ! # optionally a vector (for a vector term) otherwise the vector ! # is None ! ! def __init__(self, scalars, vector): ! # self.vector might be None for a scalar addend ! self.scalars = scalars ! self.vector = vector def __len__(self): ! return len(self.vector) def __getitem__(self, i): ! return addend(self.scalars + [self.vector[i]], None) ! def addend(self): ! return self ! ! def term(self): ! return term([self.addend()]) ! ! def is_linear(self): ! assert self.vector is None ! return len([scalar for scalar in self.scalars if not scalar.is_set()]) < 2 ! ! def prefactor(self): ! assert self.is_linear() ! prefactor = 1 ! for scalar_set in [scalar for scalar in self.scalars if scalar.is_set()]: ! prefactor *= scalar_set.get() ! return prefactor ! ! def variable(self): ! assert self.is_linear() try: ! variable, = [scalar for scalar in self.scalars if not scalar.is_set()] ! except ValueError: ! return None ! else: ! return variable ! def __add__(self, other): ! return self.term() + other ! __radd__ = __add__ def __sub__(self, other): ! return self.term() - other def __rsub__(self, other): ! return -self.term() + other ! ! def __neg__(self): ! return addend([scalar(-1)] + self.scalars, self.vector) def __mul__(self, other): ! try: ! a = other.addend() ! except (TypeError, AttributeError): ! try: ! t = other.term() ! except (TypeError, AttributeError): ! return self*scalar(other) ! else: ! return term([self*a for a in t.addends]) ! else: ! if a.vector is not None: ! if self.vector is not None: ! if len(self.vector) != len(a.vector): ! raise RuntimeError("vector length mismatch in scalar product") ! return term([addend(self.scalars + a.scalars + [x*y], None) ! for x, y in zip(self.vector, a.vector)]) ! else: ! return addend(self.scalars + a.scalars, a.vector) ! else: ! return addend(self.scalars + a.scalars, self.vector) __rmul__ = __mul__ def __div__(self, other): ! return addend([scalar(1/other)] + self.scalars, self.vector) ! ! def __str__(self): ! scalarstring = " * ".join([str(scalar) for scalar in self.scalars]) ! if self.vector is None: ! return scalarstring ! else: ! if len(scalarstring): ! scalarstring += " * " ! return scalarstring + str(self.vector) class term: ! # represents a term, i.e. a list of addends ! def __init__(self, addends): ! assert len(addends) try: ! self.length = len(addends[0]) ! except (TypeError, AttributeError): ! for addend in addends[1:]: try: ! len(addend) ! except (TypeError, AttributeError): pass else: ! raise RuntimeError("vector addend in scalar term") ! self.length = None else: ! for addend in addends[1:]: try: ! l = len(addend) ! except (TypeError, AttributeError): ! raise RuntimeError("scalar addend in vector term") ! if l != self.length: ! raise RuntimeError("vector length mismatch in term constructor") ! self.addends = addends ! def __len__(self): ! if self.length is None: ! raise AttributeError("scalar term") ! else: ! return self.length ! ! def __getitem__(self, i): ! return term([addend[i] for addend in self.addends]) def term(self): return self + def is_linear(self): + is_linear = 1 + for addend in self.addends: + is_linear = is_linear and addend.is_linear() + return is_linear + def __add__(self, other): try: ! t = other.term() except: ! return self + scalar(other) ! else: ! return term(self.addends + t.addends) __radd__ = __add__ def __neg__(self): ! return term([-addend for addend in self.addends]) def __sub__(self, other): *************** *** 205,217 **** def __mul__(self, other): ! return term([other*prefactor for prefactor in self.prefactors], self.vars, other*self.const) __rmul__ = __mul__ def __div__(self, other): ! return term([prefactor/other for prefactor in self.prefactors], self.vars, self.const/other) def __str__(self): ! return "+".join(["%s*%s" % pv for pv in zip(self.prefactors, self.vars)]) + "+" + str(self.const) --- 310,322 ---- def __mul__(self, other): ! return term([addend*other for addend in self.addends]) __rmul__ = __mul__ def __div__(self, other): ! return term([addend/other for addend in self.addends]) def __str__(self): ! return " + ".join([str(addend) for addend in self.addends]) *************** *** 220,224 **** def __init__(self): ! self.eqs = [] # equations still to be taken into account def eq(self, lhs, rhs=None): --- 325,329 ---- def __init__(self): ! self.eqs = [] # scalar equations not yet solved (a equation is a term to be zero here) def eq(self, lhs, rhs=None): *************** *** 227,252 **** else: eq = lhs - rhs ! if not len(eq.vars): ! raise RuntimeError("equation without variables") try: # is it a vector equation? ! neqs = len(eq.vars[0].scalars) ! except AttributeError: ! for v in eq.vars[1:]: ! try: ! v.scalars ! except AttributeError: ! pass ! else: ! raise RuntimeError("mixed scalar/vector equation") ! solver.add(eq) else: - for v in eq.vars[1:]: - if len(v.scalars) != neqs: - raise RuntimeError("vectors of different dimension") - if len(eq.const.values) != neqs: - raise RuntimeError("wrong dimension of constant") for i in range(neqs): ! self.add(term(eq.prefactors, [var[i] for var in eq.vars], eq.const[i])) def add(self, equation): --- 332,344 ---- else: eq = lhs - rhs ! eq = eq.term() try: # is it a vector equation? ! neqs = len(eq) ! except (TypeError, AttributeError): ! self.add(eq) else: for i in range(neqs): ! self.add(eq[i]) def add(self, equation): *************** *** 263,267 **** def combine(self, eqs): ! # create combinations of equations if not len(eqs): yield [] --- 355,359 ---- def combine(self, eqs): ! # create combinations of linear equations if not len(eqs): yield [] *************** *** 269,293 **** for x in self.combine(eqs[1:]): yield x ! yield [eqs[0]] + x def solve(self, eqs): ! # try to solve a set of equations l = len(eqs) if l: vars = [] for eq in eqs: ! vars.extend([var for var in eq.vars if var not in vars and not var.is_set()]) if len(vars) == l: a = Numeric.zeros((l, l)) b = Numeric.zeros((l, )) for i, eq in enumerate(eqs): ! for p, v in zip(eq.prefactors, eq.vars): ! if v.is_set(): ! b[i] -= p*v.value else: ! a[i, vars.index(v)] += p ! b[i] -= eq.const for i, value in enumerate(LinearAlgebra.solve_linear_equations(a, b)): ! vars[i].value = value for eq in eqs: i, = [i for i, selfeq in enumerate(self.eqs) if selfeq == eq] --- 361,390 ---- for x in self.combine(eqs[1:]): yield x ! if eqs[0].is_linear(): ! for x in self.combine(eqs[1:]): ! yield [eqs[0]] + x def solve(self, eqs): ! # try to solve a set of linear equations l = len(eqs) if l: vars = [] for eq in eqs: ! for addend in eq.addends: ! var = addend.variable() ! if var is not None and var not in vars: ! vars.append(var) if len(vars) == l: a = Numeric.zeros((l, l)) b = Numeric.zeros((l, )) for i, eq in enumerate(eqs): ! for addend in eq.addends: ! var = addend.variable() ! if var is not None: ! a[i, vars.index(var)] += addend.prefactor() else: ! b[i] -= addend.prefactor() for i, value in enumerate(LinearAlgebra.solve_linear_equations(a, b)): ! vars[i].set(value) for eq in eqs: i, = [i for i, selfeq in enumerate(self.eqs) if selfeq == eq] *************** *** 307,316 **** z = vector(2, "z") ! solver.eq(4*x + y, 2*x - y + point(4, 0)) # => x + y = (2, 0) solver.eq(x[0] - y[0], z[1]) solver.eq(x[1] - y[1], z[0]) ! solver.eq(point(5, 0), z) ! ! print x, y, z ! --- 404,413 ---- z = vector(2, "z") ! solver.eq(4*x + y, 2*x - y + vector([4, 0])) # => x + y = (2, 0) solver.eq(x[0] - y[0], z[1]) solver.eq(x[1] - y[1], z[0]) ! solver.eq(vector([5, 0]), z) + print x + print y + print z --- NEW FILE: test_solve.py --- import unittest, operator from solve import scalar, vector, solver class ScalarTestCase(unittest.TestCase): def testInit(self): self.failUnlessRaises(RuntimeError, scalar, "") self.failUnlessRaises(RuntimeError, scalar, 1j) self.failUnlessEqual(str(scalar()), "unnamed_scalar") self.failUnlessEqual(str(scalar(varname="s")), "s") self.failUnlessEqual(str(scalar(1)), "unnamed_scalar{=1.0}") self.failUnlessEqual(str(scalar(-1, varname="s")), "s{=-1.0}") def testMath(self): self.failUnlessEqual(str(-scalar(varname="s")), "unnamed_scalar{=-1.0} * s") self.failUnlessEqual(str(scalar(varname="s") + scalar(varname="t")), "s + t") self.failUnlessEqual(str(scalar(varname="s") + 1), "s + unnamed_scalar{=1.0}") self.failUnlessEqual(str(1 + scalar(varname="s")), "s + unnamed_scalar{=1.0}") self.failUnlessEqual(str(scalar(varname="s") - scalar(varname="t")), "unnamed_scalar{=-1.0} * t + s") self.failUnlessEqual(str(1 - scalar(varname="s")), "unnamed_scalar{=-1.0} * s + unnamed_scalar{=1.0}") self.failUnlessEqual(str(2 * scalar(varname="s")), "s * unnamed_scalar{=2.0}") self.failUnlessEqual(str(scalar(varname="s") * 2), "s * unnamed_scalar{=2.0}") self.failUnlessEqual(str(scalar(varname="s") * scalar(varname="t")), "s * t") self.failUnlessEqual(str(scalar(varname="s") / 2.0), "unnamed_scalar{=0.5} * s") self.failUnlessEqual(str(scalar(varname="s") / 2), "unnamed_scalar{=0.0} * s") # integer logic! self.failUnlessRaises(TypeError, lambda: 2 / scalar()) self.failUnlessRaises(TypeError, lambda: scalar() / scalar()) self.failUnlessRaises(TypeError, lambda: vector(1) / scalar()) self.failUnlessRaises(TypeError, lambda: (scalar() + scalar()) / scalar()) self.failUnlessRaises(TypeError, lambda: (vector(1) + vector(1)) / scalar()) def testSetGetIs_Set(self): s = scalar() self.failUnlessEqual(s.is_set(), 0) self.failUnlessRaises(RuntimeError, s.get) self.failUnlessRaises(RuntimeError, float, s) s.set(2) self.failUnlessEqual(s.is_set(), 1) self.failUnlessAlmostEqual(s.get(), 2.0) self.failUnlessAlmostEqual(float(s), 2.0) self.failUnlessRaises(RuntimeError, s.set, 3) self.failUnlessEqual(s.is_set(), 1) self.failUnlessAlmostEqual(s.get(), 2.0) self.failUnlessAlmostEqual(float(s), 2.0) s = scalar(2) self.failUnlessEqual(scalar(2).is_set(), 1) self.failUnlessAlmostEqual(s.get(), 2.0) self.failUnlessAlmostEqual(float(s), 2.0) self.failUnlessRaises(RuntimeError, s.set, 3) self.failUnlessEqual(s.is_set(), 1) self.failUnlessAlmostEqual(s.get(), 2.0) self.failUnlessAlmostEqual(float(s), 2.0) class VectorTestCase(unittest.TestCase): def testInit(self): self.failUnlessRaises(RuntimeError, vector, 0, 0) self.failUnlessEqual(str(vector(2)), "unnamed_vector{=(unnamed_vector[0], unnamed_vector[1])}") self.failUnlessEqual(str(vector([1, 2])), "unnamed_vector{=(unnamed_vector[0]{=1.0}, unnamed_vector[1]{=2.0})}") self.failUnlessEqual(str(vector(3, "a")), "a{=(a[0], a[1], a[2])}") self.failUnlessEqual(str(vector([3, 2, 1], "a")), "a{=(a[0]{=3.0}, a[1]{=2.0}, a[2]{=1.0})}") def testAccess(self): a = vector(2) self.failUnlessEqual(str(a), "unnamed_vector{=(unnamed_vector[0], unnamed_vector[1])}") self.failUnlessEqual(a[0].is_set(), 0) self.failUnlessEqual(a.x.is_set(), 0) self.failUnlessEqual(a[1].is_set(), 0) self.failUnlessEqual(a.y.is_set(), 0) self.failUnlessRaises(IndexError, operator.__getitem__, a, 2) self.failUnlessRaises(IndexError, getattr, a, "z") a[0].set(2) self.failUnlessEqual(str(a), "unnamed_vector{=(unnamed_vector[0]{=2.0}, unnamed_vector[1])}") self.failUnlessAlmostEqual(a[0].get(), 2.0) self.failUnlessAlmostEqual(float(a[0]), 2.0) self.failUnlessAlmostEqual(a.x.get(), 2.0) self.failUnlessAlmostEqual(float(a.x), 2.0) self.failUnlessRaises(RuntimeError, a[1].get) self.failUnlessRaises(RuntimeError, float, a[1]) self.failUnlessRaises(RuntimeError, a.y.get) self.failUnlessRaises(RuntimeError, float, a.y) self.failUnlessEqual(a[0].is_set(), 1) self.failUnlessEqual(a.x.is_set(), 1) self.failUnlessEqual(a[1].is_set(), 0) self.failUnlessEqual(a.y.is_set(), 0) self.failUnlessRaises(RuntimeError, a[0].set, 3) self.failUnlessAlmostEqual(a[0].get(), 2.0) self.failUnlessAlmostEqual(float(a[0]), 2.0) self.failUnlessAlmostEqual(a.x.get(), 2.0) self.failUnlessAlmostEqual(float(a.x), 2.0) self.failUnlessRaises(RuntimeError, a[1].get) self.failUnlessRaises(RuntimeError, float, a[1]) self.failUnlessRaises(RuntimeError, a.y.get) self.failUnlessRaises(RuntimeError, float, a.y) self.failUnlessEqual(a[0].is_set(), 1) self.failUnlessEqual(a.x.is_set(), 1) self.failUnlessEqual(a[1].is_set(), 0) self.failUnlessEqual(a.y.is_set(), 0) a[1].set(3) self.failUnlessEqual(str(a), "unnamed_vector{=(unnamed_vector[0]{=2.0}, unnamed_vector[1]{=3.0})}") self.failUnlessAlmostEqual(a[0].get(), 2.0) self.failUnlessAlmostEqual(float(a[0]), 2.0) self.failUnlessAlmostEqual(a.x.get(), 2.0) self.failUnlessAlmostEqual(float(a.x), 2.0) self.failUnlessAlmostEqual(a[1].get(), 3.0) self.failUnlessAlmostEqual(float(a[1]), 3.0) self.failUnlessAlmostEqual(a.y.get(), 3.0) self.failUnlessAlmostEqual(float(a.y), 3.0) self.failUnlessEqual(a[0].is_set(), 1) self.failUnlessEqual(a.x.is_set(), 1) self.failUnlessEqual(a[1].is_set(), 1) self.failUnlessEqual(a.y.is_set(), 1) self.failUnlessRaises(RuntimeError, a[0].set, 4) self.failUnlessAlmostEqual(a[0].get(), 2.0) self.failUnlessAlmostEqual(float(a[0]), 2.0) self.failUnlessAlmostEqual(a.x.get(), 2.0) self.failUnlessAlmostEqual(float(a.x), 2.0) self.failUnlessAlmostEqual(a[1].get(), 3.0) self.failUnlessAlmostEqual(float(a[1]), 3.0) self.failUnlessAlmostEqual(a.y.get(), 3.0) self.failUnlessAlmostEqual(float(a.y), 3.0) self.failUnlessEqual(a[0].is_set(), 1) self.failUnlessEqual(a.x.is_set(), 1) self.failUnlessEqual(a[1].is_set(), 1) self.failUnlessEqual(a.y.is_set(), 1) a = vector([1, 2, 3]) self.failUnlessEqual(str(a.x), "unnamed_vector[0]{=1.0}") self.failUnlessEqual(str(a.y), "unnamed_vector[1]{=2.0}") self.failUnlessEqual(str(a.z), "unnamed_vector[2]{=3.0}") def testLen(self): for i in range(10): a = vector(i) self.failUnlessEqual(len(a), i) self.failUnlessEqual(str(a), "unnamed_vector{=(" + ", ".join(["unnamed_vector[%i]" % j for j in range(i)]) + ")}") for i in range(10): a = -vector(i) self.failUnlessEqual(len(a), i) self.failUnlessEqual(str(a), "unnamed_scalar{=-1.0} * unnamed_vector{=(" + ", ".join(["unnamed_vector[%i]" % j for j in range(i)]) + ")}") def testMath(self): self.failUnlessEqual(str(-vector(1, "a")), "unnamed_scalar{=-1.0} * a{=(a[0])}") self.failUnlessEqual(str(vector(1, "a") + vector(1, "t")), "a{=(a[0])} + t{=(t[0])}") self.failUnlessRaises(RuntimeError, operator.__add__, vector(1), scalar()) self.failUnlessRaises(RuntimeError, operator.__add__, vector(1), vector(2)) self.failUnlessEqual(str(vector(1, "a") - vector(1, "t")), "unnamed_scalar{=-1.0} * t{=(t[0])} + a{=(a[0])}") self.failUnlessRaises(RuntimeError, operator.__sub__, vector(1), scalar()) self.failUnlessRaises(RuntimeError, operator.__sub__, vector(1), vector(2)) self.failUnlessEqual(str(2 * vector(1, "a")), "unnamed_scalar{=2.0} * a{=(a[0])}") self.failUnlessEqual(str(vector(1, "a") * 2), "unnamed_scalar{=2.0} * a{=(a[0])}") self.failUnlessEqual(str(scalar(varname="s") * vector(1, "a")), "s * a{=(a[0])}") self.failUnlessEqual(str(vector(1, "a") * scalar(varname="s")), "s * a{=(a[0])}") self.failUnlessEqual(str(vector(2, "a") * vector(2, "b")), "a[0] * b[0] + a[1] * b[1]") self.failUnlessRaises(RuntimeError, operator.__mul__, vector(1, "a"), vector(2)) self.failUnlessEqual(str(vector(1, "a") / 2.0), "unnamed_scalar{=0.5} * a{=(a[0])}") self.failUnlessEqual(str(vector(1, "a") / 2), "unnamed_scalar{=0.0} * a{=(a[0])}") # integer logic! self.failUnlessRaises(TypeError, lambda: scalar() / vector(1)) self.failUnlessRaises(TypeError, lambda: vector(1) / vector(1)) self.failUnlessRaises(TypeError, lambda: (scalar() + scalar()) / vector(1)) self.failUnlessRaises(TypeError, lambda: (vector(1) + vector(1)) / vector(1)) if __name__ == "__main__": unittest.main() ```