Getting Poly, Fraction and Matrix to interoperate has been fun.
I get into these operator precedence situations where two
objects have different implementations of __mul__, so the
__rmul__ of one triggers where what I want is the __mul__
of the other. So I end up doing type checking to force the
result I want.
For example, Poly knows how to coerce a Fraction into becoming
a polynomial of degree 0, but Fraction shouldn't ever try to
change a polynomial into a Fraction. So when it comes to
a Fraction * a Poly, it's the Poly version of * that takes
precedence over the Fraction version -- but only because I
type check, e.g.
def __mul__(self,n):
if type(n).__name__=='instance':
if n.__class__.__name__ == "Poly":
print "Fraction -> Poly"
return n.__mul__(self)
if n.__class__.__name__ == "Matrix":
print "Fraction -> Fraction"
return n.__mul__(self)
f = self.mkfract(n)
return Fraction(self.numer*f.numer,
self.denom*f.denom)
Anyway, below is an example of a session at the command line:
>>> C = Matrix([map(Fraction,[1,1,1]),
map(Fraction,[2,3,4]),
map(Fraction,[5,8,9])])
>>> C
[1, 1, 1]
[2, 3, 4]
[5, 8, 9]
>>> C.inverse()
[(5.0/2), (1.0/2), (-1.0/2)]
[-1.0, -2.0, 1.0]
[(-1.0/2), (3.0/2), (-1.0/2)]
>>> A = Matrix([[Poly([1,-3],'t'),2],
[Fraction(1,2),Poly([1,-4],'t')]])
>>> A
[t - 3, 2]
[(1/2), t - 4]
>>> A.det() # determinant of A
x**2 - 7*x + 11
>>> I = Matrix([[1,0,0],[0,1,0],[0,0,1]]) # identity matrix
>>> t = Poly([1,0],'t') # t
>>> t*I
[t, 0, 0]
[0, t, 0]
[0, 0, t]
>>> A = Matrix([[1,1,2],[0,3,2],[1,3,9]])
>>> A
[1, 1, 2]
[0, 3, 2]
[1, 3, 9]
>>> (t*I-A).det() # characteristic polynomial of A
t**3 - 13*t**2 + 31*t - 17
>>> p=(t*I-A).det() # t = 10
>>> p(10)
-7
Note that polynomials now optionally permit some variable
other than x. However, you can't multiply two polynomials
with differing variables and expect their identities to
stay separate. Getting evaluation to work no matter the
letter required a small modification to __call__ in
polynomial.py.
I've stowed polynomial,pyfraction and simplematrix as a package
called mathobjects. simplematrix is dependent on ciphers.py
however, which was my last project, and which has to do with
permutations in the context of group theory and cryptography.
A simple way to compute the determinant is to add the signed
products of all permutations of matrix elements, choosing one
from each row (a total of row! possibilities). ciphers.py is
in charge of returning a list of all those possibilities
(breaks down when n is double-digit or higher -- but that's
OK, as this is throwaway code)).
Kirby