Back to SDS/2 Parametric Scripts
"""
Encapsulate
Mono-Multinomial equations
"""
class Monomial:
def __init__(self, coefficient, exponentX,
exponentY):
self.coeff = coefficient
self.expoX = exponentX
self.expoY = exponentY
def __repr__(self):
if abs(self.coeff) == 1:
coeffStr = ""
else:
coeffStr = '%s' % (abs(self.coeff))
if self.coeff < 0:
preStr = "-"
else:
preStr = "+"
if self.expoX == 0 and self.expoY == 0:
return '%s%s' % (preStr,
coeffStr)
elif self.expoX == 0 and self.expoY !=
1:
return '%s%s(y^%s)' % (preStr,
coeffStr, self.expoY)
elif self.expoY == 0 and self.expoX !=
1:
return '%s%s(x^%s)' % (preStr,
coeffStr, self.expoX)
elif self.expoX == 1 and self.expoY ==
1:
return '%s%s(x*y)' % (preStr,
coeffStr)
elif self.expoX == 1 and self.expoY ==
0:
return '%s%sx' % (preStr, coeffStr)
elif self.expoX == 0 and self.expoY ==
1:
return '%s%sy' % (preStr, coeffStr)
elif self.expoX == 1:
return '%s%s(x*y^%s)' % (preStr,
coeffStr, self.expoY)
elif self.expoY == 1:
return '%s%s(x^%s*y)' % (preStr,
coeffStr, self.expoX)
return '%s%s(x^%s*y^%s)' % (preStr,
coeffStr, self.expoX, self.expoY)
def __lt__(self, other):
return (self.expoX < other.expoX) or
((self.expoX == other.expoX) and (self.expoY < other.expoY))
def __gt__(self,other):
return (self.expoX > other.expoX) or
((self.expoX == other.expoX) and (self.expoY >other.expoY))
# addition method returns a Multinomial
object
def __add__(self, other):
outMult = None
return simplifyMult(Multinomial(self,
Multinomial(other, outMult)))
def __mul__(self, other):
return Monome(self.coeff * other.coeff,
self.expoX + other.expoX, self.expoY + other.expoY)
class Multinomial:
def
__init__(self,referenceMonomial,refnext):
self.refMon = referenceMonomial
self.next = refnext
sortMult(self)
def __repr__(self):
res = str(self.refMon)
a = self.next
while a:
res += str(a.refMon)
a = a.next
if res[0] == '+':
return res[1:]
return res
def __iter__(self):
m
= self
while m:
yield m.refMon
m = m.next
# methods to add and subtract a Monomial
and a Multinomial or add two Multinomials
# if adding or subtracting a Monomial, the
Multinomial object must appear first in the expression
# format: Multinomial_object +
Monomial_object or Multinomial_object + Multinomial_object
def __add__(self, other):
if isinstance(other, Monomial):
# if 'Monomial' in
str(other.__class__):
outMult = None
for m in iterMult(self):
outMult = Multinomial(m,
outMult)
return
simplifyMult(Multinomial(other, outMult))
else:
outMult = None
for m in self:
outMult = Multinomial(m,
outMult)
for m in other:
outMult = Multinomial(m,
outMult)
outMult = simplifyMult(outMult)
if outMult:
return outMult
else:
return 0
def __sub__(self, other):
if isinstance(other, Monomial):
# if 'Monomial' in
str(other.__class__):
outMult = None
for m in iterMult(self):
outMult = Multinomial(m,
outMult)
return
simplifyMult(Multinomial(Monomial(-other.coeff, other.expoX, other.expoY),
outMult))
else:
outMult = None
for m in self:
outMult = Multinomial(m,
outMult)
for m in other:
outMult =
Multinomial(Monomial(-m.coeff, m.expoX, m.expoY), outMult)
outMult = simplifyMult(outMult)
if outMult:
return outMult
else:
return 0
def __mul__(self, other):
outMult = None
for d1 in self:
for d2 in other:
outMult =
Multinomial(Monomial(d1.coeff * d2.coeff, d1.expoX + d2.expoX, d1.expoY +
d2.expoY), outMult)
return simplifyMult(outMult)
# in-place sort
function on Multinomial object in descending order of degree
def sortMult(d):
while d:
if d.next:
d2 = d.next
while d2:
if degre(d2.refMon) >
degre(d.refMon):
d.refMon, d2.refMon =
d2.refMon, d.refMon
elif degre(d2.refMon) ==
degre(d.refMon) and d2.refMon.expoX > d.refMon.expoX:
d.refMon, d2.refMon =
d2.refMon, d.refMon
elif degre(d2.refMon) ==
degre(d.refMon) and d2.refMon.expoX == d.refMon.expoX and d2.refMon.coeff >
d.refMon.coeff:
d.refMon, d2.refMon =
d2.refMon, d.refMon
d2 = d2.next
d = d.next
# return a sorted
Multinomial object in descending order of degree
def cmpMult(d):
mList = []
for m in iterMult(d):
mList.append((m.expoX+m.expoY, m.expoX,
m.expoY, m.coeff, m))
mList.sort()
outMult = None
for item in mList:
outMult = Multinomial(Monomial(item[3],
item[1], item[2]), outMult)
return outMult
# Add new Monomial
object to existing Multinomial object and sort in descending order of degree
def
insertMonomial(coefficient, exponentX, exponentY, d=None):
return
cmpMult(Multinomial(Monomial(coefficient, exponentX, exponentY), d))
# Multinomial
iterator
def iterMult(d):
while d:
yield d.refMon
d = d.next
# Simplify a
Multinomial object, combine like terms, skip terms with a coefficient of 0
def simplifyMult(d):
dMult = {}
for m in iterMult(d):
if (m.expoX, m.expoY) not in
dMult.keys():
dMult[(m.expoX, m.expoY)] = m.coeff
else:
dMult[(m.expoX, m.expoY)] =
dMult[(m.expoX, m.expoY)] + m.coeff
outMult = None
for key in dMult.keys():
if abs(dMult[key]) > 0:
outMult =
Multinomial(Monomial(dMult[key], key[0], key[1]), outMult)
return cmpMult(outMult)
# Combine 2
Multinomial objects, simplifying Monomials
# Return sorted
Multinomial in descending order of degree
def
joinMultinomials(d1, d2):
outMult = d1
for m in iterMult(d2):
outMult = Multinomial(m, outMult)
return simplifyMult(outMult)
m1 = Monomial(1,3,7)
m2 =
Monomial(-2,4,9)
print 'm1 = %s' % m1
print 'm2 = %s' % m2
print 'm1*m2 = %s' %
repr(m1*m2)
d1 =
Multinomial(Monomial(5,1,0),Multinomial(Monomial(-8,6,3),Multinomial(Monomial(1,3,7),Multinomial(Monomial(-2,4,9),
None))))
d2 =
Multinomial(Monomial(5,6,3),Multinomial(Monomial(-8,3,7),Multinomial(Monomial(1,9,5),Multinomial(Monomial(-2,1,0),
None))))
d3 =
joinMultinomials(d1, d2)
print 'd1 = %s' % d1
print 'd2 = %s' % d2
print 'd3 = %s' % d3
print 'd1+d2 = %s' %
repr(d1+d2)
print 'd1-d2 = %s' %
repr(d1-d2)
print 'd1-d2 = %s' %
repr(d1-d2)
print 'd1*d3 = %s' %
repr(d2*d3)
print
'd1-Monomial(7,6,3) = %s' % repr(d1-Monomial(7,6,3))
print
'Monomial(-8,6,3)+Monomial(1,9,5) = %s' % repr(Monomial(-8,6,3)+Monomial(1,9,5))
print
print
"Iteration on Monomial object d3 using built-in iteration method
(__iter__):"
for m in d3:
print m
print
# 5x^3-3x^2+x-2
d =
Multinomial(Monomial(5,3,0),Multinomial(Monomial(-3,2,0),Multinomial(Monomial(1,1,0),Multinomial(Monomial(-2,0,0),
None))))
print 'Polynomial to
solve using bisection method: %s' % d
def solve(d, vx,
vy=1.0):
r = 0.0
for m in iterMult(d):
r +=
m.coeff*float(vx)**m.expoX*float(vy)**m.expoY
return r
def bisection(d, U,
L, e):
if solve(d, U) > 0 and solve(d, L) <
0:
while abs(U - L) > e:
M = (U+L)/2
if solve(d, M)*solve(d,U) > 0:
U = M
else:
L = M
print U, L
return U,L
else:
return "Invalid arguments. f(U)
must be > 0 and f(L) must be < 0."
print bisection(d,
1.0, -1.0, 0.00001)
def solve2(s, x,
y=1.0):
return eval(s)
s =
'5*(x**3)-3*(x**2)+x-2'
print solve2(s, 4.0)
# Output:
"""
>>> m1 =
+(x^3*y^7)
m2 = -2(x^4*y^9)
m1*m2 = -2(x^7*y^16)
d1 =
5(x^6*y^3)-8(x^6*y^3)+5x-2x
d2 =
(x^9*y^5)-8(x^3*y^7)+5(x^6*y^3)-2x
d3 =
(x^9*y^5)-2(x^4*y^9)-7(x^3*y^7)-3(x^6*y^3)+3x
d1+d2 =
(x^9*y^5)-8(x^3*y^7)+2(x^6*y^3)+x
d1-d2 =
-(x^9*y^5)+8(x^3*y^7)-8(x^6*y^3)+5x
d1-d2 =
-(x^9*y^5)+8(x^3*y^7)-8(x^6*y^3)+5x
d1*d3 =
(x^18*y^10)-2(x^13*y^14)-15(x^12*y^12)+2(x^15*y^8)+16(x^7*y^16)-10(x^10*y^12)+56(x^6*y^14)\
-11(x^9*y^10)-15(x^12*y^6)+(x^10*y^5)+4(x^5*y^9)-10(x^4*y^7)+21(x^7*y^3)-6(x^2)
d1-Monomial(7,6,3) =
-10(x^6*y^3)+3x
Monomial(-8,6,3)+Monomial(1,9,5)
= (x^9*y^5)-8(x^6*y^3)
Iteration on
Monomial object d3 using built-in iteration method (__iter__):
+(x^9*y^5)
-2(x^4*y^9)
-7(x^3*y^7)
-3(x^6*y^3)
+3x
Polynomial to solve
using bisection method: 5(x^3)-3(x^2)+x-2
1.0 0.0
1.0 0.5
1.0 0.75
1.0 0.875
0.9375 0.875
0.90625 0.875
0.890625 0.875
0.890625 0.8828125
0.88671875 0.8828125
0.88671875
0.884765625
0.8857421875
0.884765625
0.88525390625
0.884765625
0.885009765625
0.884765625
0.884887695313
0.884765625
0.884887695313
0.884826660156
0.884857177734
0.884826660156
0.884857177734
0.884841918945
0.884857177734
0.88484954834
(0.884857177734375,
0.88484954833984375)
274.0
>>>
"""