Created
November 2, 2013 11:09
-
-
Save tatyusa/7277835 to your computer and use it in GitHub Desktop.
"Infinite lazy polynomials"(http://jliszka.github.io/2013/10/31/infinite-lazy-polynomials.html)で紹介されている内容のPythonによる実装です
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import types | |
import math | |
# Supporting Functions | |
def prod(l): | |
temp = 1. | |
for i in xrange(len(l)): | |
temp *= l[i] | |
return temp | |
def isNumber(n): | |
return isinstance(n,int) or isinstance(n,float) or isinstance(n,long) or isinstance(n,complex) | |
def numberToPoly(number): | |
return Poly(lambda n: number if n==0 else 0) | |
def pExp(poly): | |
a = poly[0] | |
q = poly - a | |
ea = math.exp(a) | |
return Poly(lambda n: ea * sum( [ (q**i)[n] / prod( [ (j+1) for j in xrange(i) ] ) for i in xrange(n+1) ] ) ) | |
def pLog(poly): | |
a = poly[0] | |
if a==0: return | |
logA = math.log(a) | |
q = poly/a - 1 | |
return logA + Poly(lambda n: sum( [ (-1)**(i%2) / (i+1.) * (q**(i+1))[n] for i in xrange(n)] ) ) | |
def pGraph(poly,precision=10,x_min=-1.,x_max=1.,y_min=-1.,y_max=1.,scale=200.,step=0.01): | |
from Tkinter import Tk,Canvas | |
root = Tk() | |
c = Canvas(root, width = scale*(x_max-x_min), height = scale*(y_max-y_min)) | |
c.pack() | |
x = x_min | |
y = poly(x,precision=precision) | |
while x < x_max: | |
x0 = x | |
y0 = y | |
x += step | |
y = poly(x) | |
xb = scale*(x0-x_min) | |
yb = scale*(y_max-y_min)-scale*(y0-y_min) | |
xa = scale*(x-x_min) | |
ya = scale*(y_max-y_min)-scale*(y-y_min) | |
c.create_line(xb,yb,xa,ya) | |
root.mainloop() | |
# Definition of | |
# Infinite Lazy Polynomials Class | |
class Poly: | |
def __init__(self,coeffs): | |
# init with list | |
if isinstance(coeffs,list): | |
self.coeffs = lambda n: coeffs[n] if n < len(coeffs) else 0 | |
# init with lambda | |
if isinstance(coeffs, types.LambdaType): | |
self.coeffs = coeffs | |
# print poly | |
def __repr__(self): | |
return ", ".join([ str(self[i]) for i in xrange(10) ] + ["..."]) | |
# return nth coeff | |
def __getitem__(self,n): | |
return self.coeffs(n) | |
# poly(x) | |
def __call__(self,x,precision=10): | |
return sum([ self[i] * x**i for i in xrange(precision) ]) | |
# -poly | |
def __neg__(self): | |
return Poly(lambda n: -self.coeffs(n)) | |
# poly + scalar, poly0 + poly1 | |
def __add__(self,other): | |
if isNumber(other): other = numberToPoly(other) | |
return Poly(lambda n: self.coeffs(n) + other.coeffs(n)) | |
# scalar + poly, poly0 + poly1 | |
def __radd__(self, other): | |
if isNumber(other): other = numberToPoly(other) | |
return Poly(lambda n: other.coeffs(n) + self.coeffs(n)) | |
# poly - scalar, poly0 - poly1 | |
def __sub__(self,other): | |
if isNumber(other): other = numberToPoly(other) | |
return Poly(lambda n: self.coeffs(n) - other.coeffs(n)) | |
# scalar - poly, poly0 - poly1 | |
def __rsub__(self, other): | |
if isNumber(other): other = numberToPoly(other) | |
return Poly(lambda n: other.coeffs(n) - self.coeffs(n)) | |
# poly * scalar, poly0 * poly1 | |
def __mul__(self,other): | |
if isNumber(other): | |
return Poly(lambda n: self.coeffs(n) * other) | |
if isinstance(other,Poly): | |
return Poly(lambda n: sum([ self.coeffs(k) * other.coeffs(n-k) for k in xrange(n+1) ])) | |
# scalar * poly | |
def __rmul__(self,other): | |
if isNumber(other): | |
return Poly(lambda n: other * self.coeffs(n)) | |
# poly / scalar, poly0 / poly1 | |
def __div__(self,other): | |
if isNumber(other): | |
return Poly(lambda n: self.coeffs(n) / other) | |
if isinstance(other,Poly): | |
return self * other.inv() | |
# scalar / poly | |
def __rdiv__(self,other): | |
if isNumber(other): | |
return other * self.inv() | |
# poly ** r | |
def __pow__(self,other): | |
if isinstance(other,int) or isinstance(other,long): | |
if other==0: return numberToPoly(1) | |
elif other < 0: | |
return (self ** -other).inv() | |
else: | |
p2 = self ** (other/2) | |
if other%2==0: return p2 * p2 | |
else: return p2 * p2 * self | |
if isinstance(other,float): | |
a = self[0] | |
if a == 0: return | |
else: | |
ar = a ** other | |
q = self / a - 1 | |
def coeff(n): | |
return prod([ other - i for i in xrange(n) ]) / prod([ (i+1) for i in xrange(n)]) | |
return Poly(lambda n: ar * sum([coeff(i) * (q ** i)[n] for i in xrange(n+1) ])) | |
# inverse | |
def inv(self): | |
a = self[0] | |
if a == 0 : return | |
else: | |
q = 1 - self / a | |
return Poly(lambda n: sum([ (q**i)[n] for i in xrange(n+1) ]) / a) | |
# derivative | |
def derivative(self): | |
return Poly(lambda n: self[n+1]*(n+1)) | |
x = Poly(lambda n: 1 if n==1 else 0) | |
if __name__ == '__main__' : | |
print "This is Infinite lazy polynomials Class" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment