2014-11-11 09:45:45 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# encoding: utf-8
|
|
|
|
|
|
|
|
|
2014-11-11 15:52:30 +00:00
|
|
|
from .expression import Expression
|
2014-11-11 20:00:45 +00:00
|
|
|
from .operator import op
|
2015-04-03 14:07:07 +00:00
|
|
|
from .generic import isNumerand
|
2014-12-19 16:17:25 +00:00
|
|
|
from .random_expression import RdExpression
|
2015-04-03 14:07:07 +00:00
|
|
|
from .abstract_polynom import AbstractPolynom
|
2014-11-11 09:45:45 +00:00
|
|
|
|
2015-04-03 15:32:02 +00:00
|
|
|
from functools import wraps
|
|
|
|
import inspect
|
|
|
|
|
2014-11-11 09:45:45 +00:00
|
|
|
__all__ = ["Polynom"]
|
|
|
|
|
2015-04-03 15:32:02 +00:00
|
|
|
def polynom_factory(func):
|
|
|
|
""" Decorator which specify the type of polynom that the function returns """
|
|
|
|
@wraps(func)
|
|
|
|
def wrapper(*args, **kwrds):
|
|
|
|
P = func(*args, **kwrds)
|
2015-04-07 06:46:59 +00:00
|
|
|
if issubclass(type(P),AbstractPolynom) and P.degree == 2:
|
2015-04-03 15:32:02 +00:00
|
|
|
from .polynomDeg2 import Polynom_deg2
|
|
|
|
new_P = Polynom_deg2(poly=P)
|
|
|
|
new_P.steps = P.steps
|
|
|
|
return new_P
|
2015-04-07 06:46:59 +00:00
|
|
|
elif issubclass(type(P),AbstractPolynom):
|
|
|
|
new_P = Polynom(poly=P)
|
|
|
|
new_P.steps = P.steps
|
|
|
|
return new_P
|
2015-04-03 15:32:02 +00:00
|
|
|
else:
|
|
|
|
return P
|
|
|
|
return wrapper
|
|
|
|
|
2015-04-03 14:07:07 +00:00
|
|
|
class Polynom(AbstractPolynom):
|
2014-11-11 09:45:45 +00:00
|
|
|
|
2015-04-03 14:07:07 +00:00
|
|
|
"""Polynom view as a function.
|
|
|
|
|
|
|
|
It can be initiate like a AbstractPolynom
|
|
|
|
# Put example
|
|
|
|
Randomly
|
|
|
|
# Put example
|
|
|
|
It can be evaluate
|
|
|
|
# Put example
|
|
|
|
And derivate
|
|
|
|
# Put example
|
2014-11-11 09:45:45 +00:00
|
|
|
|
2015-04-03 14:07:07 +00:00
|
|
|
"""
|
2014-11-11 09:45:45 +00:00
|
|
|
|
2014-12-19 16:17:25 +00:00
|
|
|
@classmethod
|
2015-03-08 17:51:53 +00:00
|
|
|
def random(self, coefs_form=[], conditions=[], letter = "x", degree = 0, name = "P"):
|
2014-12-19 16:17:25 +00:00
|
|
|
""" Create a random polynom from coefs_form and conditions
|
|
|
|
|
|
|
|
:param coefs_form: list of forms (one by coef) (ascending degree sorted)
|
|
|
|
:param conditions: condition on variables
|
2015-02-21 10:01:34 +00:00
|
|
|
:param letter: the letter for the polynom
|
|
|
|
:param degree: degree of the polynom (can't be used with coefs_form, it will be overwrite) - can't be higher than 26 (number of letters in alphabet)
|
2014-12-19 16:17:25 +00:00
|
|
|
|
|
|
|
/!\ variables need to be in brackets {}
|
|
|
|
|
2015-02-21 10:01:34 +00:00
|
|
|
>>> Polynom.random(["{b}", "{a}"]) # doctest:+ELLIPSIS
|
2016-01-07 16:34:23 +00:00
|
|
|
< <class 'pymath.calculus.polynom.Polynom'> ...
|
2015-02-21 10:01:34 +00:00
|
|
|
>>> Polynom.random(degree = 2) # doctest:+ELLIPSIS
|
2016-01-07 16:34:23 +00:00
|
|
|
< <class 'pymath.calculus.polynomDeg2.Polynom_deg2'> ...
|
2015-04-07 06:46:59 +00:00
|
|
|
>>> Polynom.random(degree = 3) # doctest:+ELLIPSIS
|
2016-01-07 16:34:23 +00:00
|
|
|
< <class 'pymath.calculus.polynom.Polynom'> ...
|
2015-02-21 10:01:34 +00:00
|
|
|
>>> Polynom.random(degree = 2, conditions=["{b**2-4*a*c}>0"]) # Polynom deg 2 with positive Delta (ax^2 + bx + c)
|
2016-01-07 16:34:23 +00:00
|
|
|
< <class 'pymath.calculus.polynomDeg2.Polynom_deg2'> ...
|
2015-02-21 10:01:34 +00:00
|
|
|
>>> Polynom.random(["{c}", "{b}", "{a}"], conditions=["{b**2-4*a*c}>0"]) # Same as above
|
2016-01-07 16:34:23 +00:00
|
|
|
< <class 'pymath.calculus.polynomDeg2.Polynom_deg2'> ...
|
2015-02-21 10:01:34 +00:00
|
|
|
|
2014-12-19 16:17:25 +00:00
|
|
|
"""
|
2015-02-21 10:01:34 +00:00
|
|
|
if (degree > 0 and degree < 26):
|
|
|
|
# Générer assez de lettre pour les coefs
|
|
|
|
coefs_name = map(chr, range(97, 98+degree))
|
2015-02-27 21:26:53 +00:00
|
|
|
coefs_form = ["{" + i + "}" for i in coefs_name][::-1]
|
2015-02-21 10:01:34 +00:00
|
|
|
|
2014-12-19 16:17:25 +00:00
|
|
|
form = str(coefs_form)
|
2015-02-21 10:01:34 +00:00
|
|
|
# On créé les valeurs toutes concaténées dans un string
|
2014-12-19 16:17:25 +00:00
|
|
|
coefs = RdExpression(form, conditions)()
|
2015-02-21 10:01:34 +00:00
|
|
|
# On "parse" ce string pour créer les coefs
|
2014-12-19 16:29:12 +00:00
|
|
|
coefs = [eval(i) if type(i)==str else i for i in eval(coefs)]
|
2015-02-21 10:01:34 +00:00
|
|
|
# Création du polynom
|
2015-03-08 17:56:59 +00:00
|
|
|
return Polynom(coefs = coefs, letter = letter, name = name)
|
2014-12-19 16:17:25 +00:00
|
|
|
|
2015-04-07 06:46:59 +00:00
|
|
|
def __init__(self, coefs = [1], letter = "x", name = "P", poly = 0):
|
2014-11-11 09:45:45 +00:00
|
|
|
"""Initiate the polynom
|
|
|
|
|
2014-11-11 15:52:30 +00:00
|
|
|
:param coef: coefficients of the polynom (ascending degree sorted)
|
|
|
|
3 possibles type of coefficent:
|
|
|
|
- a : simple "number". [1,2] designate 1 + 2x
|
|
|
|
- [a,b,c]: list of coeficient for same degree. [1,[2,3],4] designate 1 + 2x + 3x + 4x^2
|
|
|
|
- a: a Expression. [1, Expression("2+3"), 4] designate 1 + (2+3)x + 4x^2
|
2014-11-11 09:45:45 +00:00
|
|
|
:param letter: the string describing the unknown
|
2015-03-08 17:51:53 +00:00
|
|
|
:param name: Name of the polynom
|
2014-11-11 09:45:45 +00:00
|
|
|
|
2015-03-08 17:51:53 +00:00
|
|
|
>>> P = Polynom([1, 2, 3])
|
|
|
|
>>> P.mainOp
|
2014-11-11 20:00:45 +00:00
|
|
|
'+'
|
2015-03-08 17:51:53 +00:00
|
|
|
>>> P.name
|
|
|
|
'P'
|
|
|
|
>>> P._letter
|
|
|
|
'x'
|
2014-11-11 20:00:45 +00:00
|
|
|
>>> Polynom([1]).mainOp
|
|
|
|
'*'
|
2015-03-07 17:22:46 +00:00
|
|
|
>>> Polynom([0, 0, 3]).mainOp
|
|
|
|
'*'
|
|
|
|
>>> Polynom([1, 2, 3])._letter
|
2014-11-11 20:00:45 +00:00
|
|
|
'x'
|
|
|
|
>>> Polynom([1, 2, 3], "y")._letter
|
|
|
|
'y'
|
2015-03-08 17:51:53 +00:00
|
|
|
>>> Polynom([1, 2, 3], name = "Q").name
|
|
|
|
'Q'
|
2014-11-11 09:45:45 +00:00
|
|
|
"""
|
2015-04-07 06:46:59 +00:00
|
|
|
if poly:
|
|
|
|
coefs = poly._coef
|
|
|
|
letter = poly._letter
|
|
|
|
name = poly.name
|
|
|
|
|
2015-04-03 14:07:07 +00:00
|
|
|
super(Polynom, self).__init__(coefs, letter, name)
|
2014-11-11 15:52:30 +00:00
|
|
|
|
2014-12-21 17:03:22 +00:00
|
|
|
def __call__(self, value):
|
|
|
|
""" Evaluate the polynom in value
|
|
|
|
|
|
|
|
:returns: Expression ready to be simplify
|
|
|
|
|
2015-03-07 08:15:38 +00:00
|
|
|
>>> P = Polynom([1, 2, 3])
|
|
|
|
>>> P(2)
|
|
|
|
17
|
|
|
|
>>> for i in P(2).explain():
|
|
|
|
... print(i)
|
|
|
|
3 \\times 2^{ 2 } + 2 \\times 2 + 1
|
|
|
|
3 \\times 4 + 4 + 1
|
|
|
|
12 + 4 + 1
|
|
|
|
16 + 1
|
|
|
|
17
|
|
|
|
>>> Q = P("1+h")
|
|
|
|
>>> print(Q)
|
|
|
|
3 h^{ 2 } + 8 h + 6
|
|
|
|
>>> R = P(Q)
|
2014-12-21 17:03:22 +00:00
|
|
|
"""
|
2015-06-21 18:43:38 +00:00
|
|
|
#if isNumerand(value) or Expression.isExpression(value):
|
|
|
|
# postfix_exp = [value if i==self._letter else i for i in self.postfix_tokens]
|
|
|
|
#else:
|
|
|
|
postfix_exp = [Expression(value) if i==self._letter else i for i in self.postfix_tokens]
|
2014-12-22 09:13:20 +00:00
|
|
|
|
2015-03-07 08:15:38 +00:00
|
|
|
return Expression(postfix_exp).simplify()
|
2014-12-21 17:03:22 +00:00
|
|
|
|
2015-03-06 16:00:09 +00:00
|
|
|
def derivate(self):
|
|
|
|
""" Return the derivated polynom
|
|
|
|
|
|
|
|
>>> P = Polynom([1, 2, 3])
|
|
|
|
>>> Q = P.derivate()
|
|
|
|
>>> Q
|
2016-01-07 16:34:23 +00:00
|
|
|
< <class 'pymath.calculus.polynom.Polynom'> [2, 6]>
|
2015-03-08 17:51:53 +00:00
|
|
|
>>> print(Q.name)
|
|
|
|
P'
|
2015-03-06 16:00:09 +00:00
|
|
|
>>> for i in Q.explain():
|
|
|
|
... print(i)
|
|
|
|
2 \\times 3 x + 1 \\times 2
|
|
|
|
6 x + 2
|
|
|
|
"""
|
|
|
|
derv_coefs = []
|
|
|
|
for (i,c) in enumerate(self._coef):
|
|
|
|
derv_coefs += [Expression([i, c, op.mul])]
|
2015-03-08 17:51:53 +00:00
|
|
|
|
|
|
|
ans = Polynom(derv_coefs[1:]).simplify()
|
|
|
|
ans.name = self.name + "'"
|
|
|
|
return ans
|
2015-03-06 16:00:09 +00:00
|
|
|
|
2015-04-03 15:32:02 +00:00
|
|
|
# Decorate methods which may return Polynoms
|
|
|
|
methods_list = ["__add__", "__call__", "__mul__", "__neg__", "__pow__",
|
|
|
|
"__radd__", "__rmul__", "__rsub__", "__sub__", "derivate",
|
|
|
|
"reduce", "simplify", "random"]
|
|
|
|
for name, func in inspect.getmembers(Polynom):
|
|
|
|
if name in methods_list:
|
|
|
|
setattr(Polynom, name, polynom_factory(func))
|
|
|
|
|
|
|
|
|
2014-11-11 09:45:45 +00:00
|
|
|
if __name__ == '__main__':
|
2014-12-22 13:20:56 +00:00
|
|
|
#from .fraction import Fraction
|
2015-03-07 08:15:38 +00:00
|
|
|
#with Expression.tmp_render(txt):
|
|
|
|
# p = Polynom([1, 2, 3])
|
|
|
|
# q = Polynom([4, 5, 6])
|
|
|
|
# for i in (p*q).explain():
|
|
|
|
# print(i)
|
2015-02-27 21:26:53 +00:00
|
|
|
# r = Polynom([0,1])
|
|
|
|
# for i in (r*3).explain():
|
|
|
|
# print(i)
|
2015-02-27 18:24:27 +00:00
|
|
|
# print("q = ", q)
|
|
|
|
# r = q.reduce()
|
|
|
|
# print("r = ", r)
|
|
|
|
# for i in r.explain():
|
|
|
|
# print("q = ", i)
|
|
|
|
# print(p-q)
|
|
|
|
# for i in p-q:
|
|
|
|
# print(i)
|
2015-03-07 08:15:38 +00:00
|
|
|
#Polynom.random(degree = 2, conditions=["{b**2-4*a*c}>0"]) # Polynom deg 2 with positive Delta (ax^2 + bx + c)
|
2015-02-27 17:04:50 +00:00
|
|
|
|
2015-06-21 18:43:38 +00:00
|
|
|
#import doctest
|
|
|
|
#doctest.testmod(optionflags=doctest.ELLIPSIS)
|
|
|
|
|
|
|
|
# while True:
|
|
|
|
# P = Polynom.random(degree = 2)
|
|
|
|
# e = Expression.random("{a}/{b}")
|
|
|
|
# try:
|
|
|
|
# P(e)
|
|
|
|
# except RuntimeError:
|
|
|
|
# print(" P -> " + str(P))
|
|
|
|
# print(" e -> " + str(e))
|
|
|
|
#
|
|
|
|
# import sys
|
|
|
|
# sys.setrecursionlimit(100)
|
|
|
|
|
|
|
|
from .fraction import Fraction
|
|
|
|
from itertools import permutations
|
|
|
|
P = Polynom([-5,6,-4])
|
|
|
|
f = Fraction(2,5)
|
|
|
|
P(f)
|
|
|
|
try:
|
|
|
|
P(f)
|
|
|
|
except Exception as e:
|
|
|
|
print(e)
|
|
|
|
|
|
|
|
print("-----------------\n")
|
|
|
|
f = Fraction(2,15)
|
|
|
|
print(str(P).replace('x','('+str(f)+')'),"= ", P(f))
|
|
|
|
|
|
|
|
print("-----------------\n")
|
|
|
|
f = Fraction(2,3)
|
|
|
|
print(P(f))
|
|
|
|
#coefs_p = [[(i-2),(j-2)] for i,j in permutations(range(20),2)]
|
|
|
|
#fractions = [Fraction(i,j) for i,j in coefs_p if j!=0]
|
|
|
|
#for f in fractions:
|
|
|
|
# try:
|
|
|
|
# P(f)
|
|
|
|
# #print("ok f -> " + str(f))
|
|
|
|
# except RuntimeError:
|
|
|
|
# print(" f -> " + str(f))
|
2014-11-11 20:00:45 +00:00
|
|
|
|
2014-11-11 09:45:45 +00:00
|
|
|
|
|
|
|
# -----------------------------
|
|
|
|
# Reglages pour 'vim'
|
|
|
|
# vim:set autoindent expandtab tabstop=4 shiftwidth=4:
|
|
|
|
# cursor: 16 del
|