From 73e6c74c72715f048d115f51007c69c65b4a8265 Mon Sep 17 00:00:00 2001 From: lafrite Date: Tue, 11 Nov 2014 10:45:45 +0100 Subject: [PATCH] import old polynom and test_polynom from polynom branch --- pymath/polynom.py | 318 +++++++++++++++++++++++++++++++++++++++++++ test/test_polynom.py | 162 ++++++++++++++++++++++ 2 files changed, 480 insertions(+) create mode 100644 pymath/polynom.py create mode 100644 test/test_polynom.py diff --git a/pymath/polynom.py b/pymath/polynom.py new file mode 100644 index 0000000..ee4fce1 --- /dev/null +++ b/pymath/polynom.py @@ -0,0 +1,318 @@ +#!/usr/bin/env python +# encoding: utf-8 + + +from pymath.fraction import Fraction +from pymath.expression import Expression +from pymath.generic import mix_list, sum_postfix, expand_list + +__all__ = ["Polynom"] + + +class Polynom(object): + + """Docstring for Polynom. """ + + def __init__(self, coef = [1], letter = "x" ): + """Initiate the polynom + + :param coef: coefficients of the polynom (ascending degree sorted) - can be a list of list of coefficients. + 3 possibles type of list: + - [a,b,..] simple list of coefficients. [1,2] designate 1 + 2x + - [a, [c,b],...] list of coefficients with x^i repeated. [1,[2,3],4) designate 1 + 2x + 3x + 4x^2 + - [a, [b,c,"+"],...] list of coefficients with arithmetic expression (postfix form) in. [1, [2,3,"+"], 4] designate 1 + (2+3)x + 4x^2 + :param letter: the string describing the unknown + + """ + self.feed_coef(coef) + self._letter = letter + + + if self.is_monom(): + self.mainOp = "*" + else: + self.mainOp = "+" + + def feed_coef(self, l_coef): + """Feed coef of the polynom. Manage differently whether it's a number or an expression + + :l_coef: list of coef + """ + self._coef = [] + for coef in l_coef: + if type(coef) == list and len(coef)==1: + self._coef.append(coef[0]) + else: + self._coef.append(coef) + + def get_degree(self): + """Getting the degree fo the polynom + + :returns: the degree of the polynom + + """ + return len(self._coef) - 1 + + def is_monom(self): + """is the polynom a monom (only one coefficent) + :returns: 1 if yes 0 otherwise + """ + if len([i for i in self._coef if i != 0])==1: + return 1 + else: + return 0 + + def __str__(self): + # TODO: Voir si on peut utiliser un render |sam. juin 14 08:56:16 CEST 2014 + from .renders import txt + return txt(self.get_postfix()) + + def __repr__(self): + return "< Polynom " + str(self._coef) + ">" + + def coef_postfix(self, a, i): + """Return the postfix display of a coeficient + + :param a: value for the coeficient (/!\ as a list) + :param i: power + :returns: postfix tokens of coef + + """ + ans =[] + if a == 0: + return ans + if i == 0: + ans = a + elif i == 1: + ans = a * (a!=[1]) + [self._letter] + ["*"] * (a!=[1]) + else: + ans = a * (a!=[1]) + [self._letter, i, "^"] + ["*"] * (a!=[1]) + + return ans + + def get_postfix(self): + """Return the postfix form of the polynom + + :returns: the postfix list of polynom's tokens + + """ + self._postfix = [] + first_elem = 1 + for (i,a) in list(enumerate(self._coef))[::-1]: + if type(a) == list and str(a[-1]) in "+-*^/": + # case coef is an arithmetic expression + self._postfix += self.coef_postfix(a,i) + if not first_elem: + self._postfix.append("+") + first_elem = 0 + + elif type(a) == list and str(a[-1]) not in "+-*^/": + # case need to repeat the x^i + for b in a: + if type(b) == list: + self._postfix += self.coef_postfix(b,i) + else: + self._postfix += self.coef_postfix([b],i) + if not first_elem: + self._postfix.append("+") + first_elem = 0 + + elif a != 0: + self._postfix += self.coef_postfix([a],i) + if not first_elem: + self._postfix.append("+") + first_elem = 0 + + return self._postfix + + def convert_into_poly(self, other): + """Convert anything (int and fract) into a polynom """ + if type(other) in [int, Fraction]: + return Polynom([other]) + elif type(other) == Polynom: + return other + else: + raise ValueError(type(other) + " can't be converted into a polynom") + + def reduce(self): + """Compute coefficients which have same degree + + :returns: new Polynom with numbers coefficients + """ + steps = [] + for a in self._coef: + coef_steps = [] + if type(a) == list and str(a[-1]) in "+-*^": + # case coef is an arithmetic expression + exp = Expression(a) + coef_steps = list(exp.simplify(render = lambda x:x)) + + steps.append(coef_steps) + elif type(a) == list and str(a[-1]) not in "+-*^": + # case need to repeat the x^i + if [i for i in a if type(i) == list] != []: + # first we simplify arithmetic exp + # Et hop un coup de sorcelerie! + elem = [list(Expression(i).simplify(render = lambda x:self.list_or_num(x))) if type(i) == list else i for i in a ] + + elem = expand_list(elem) + coef_steps += elem + exp = elem[-1] + + else: + exp = a + + exp = sum_postfix(exp) + exp = Expression(exp) + + coef_steps += list(exp.simplify(render = lambda x:x)) + + steps.append(coef_steps) + else: + steps.append(a) + + steps = expand_list(steps) + + return [Polynom(s) for s in steps] + + @staticmethod + def list_or_num(x): + if len(x) == 1: + return x[0] + else: + return x + + + def simplify(self): + """Same as reduce """ + return self.reduce() + + + def __eq__(self, other): + if type(other) in [int, Fraction, Polynom] or other.isnumeric(): + o_poly = self.convert_into_poly(other) + + return self._coef == o_poly._coef + else: + return 0 + + def __add__(self, other): + steps = [] + + o_poly = self.convert_into_poly(other) + + n_coef = mix_list(self._coef, o_poly._coef) + p = Polynom(n_coef) + steps.append(p) + + steps += p.simplify() + return steps + + def __radd__(self, other): + return self.__add__(other) + + def __neg__(self): + return Polynom([-i for i in self._coef], letter = self._letter) + + def __sub__(self, other): + o_poly = self.convert_into_poly(other) + o_poly = -o_poly + + return self.__add__(o_poly) + + def __rsub__(self, other): + o_poly = self.convert_into_poly(other) + + return o_poly.__sub__(-self) + + def __mul__(self, other): + steps = [] + o_poly = self.convert_into_poly(other) + + coefs = [] + for (i,a) in enumerate(self._coef): + for (j,b) in enumerate(o_poly._coef): + if a == 0 or b == 0: + elem = 0 + else: + elem = [a, b, "*"] + try: + if coefs[i+j]==0: + coefs[i+j] = elem + elif elem != 0: + coefs[i+j] = [coefs[i+j], elem] + except IndexError: + coefs.append(elem) + + p = Polynom(coefs) + steps.append(p) + + steps += p.simplify() + return steps + + def __rmul__(self, other): + o_poly = self.convert_into_poly(other) + + return o_poly.__mul__(self) + + def __div__(self, other): + pass + + def __truediv__(self, other): + pass + + +def test(p,q): + print("---------------------") + print("---------------------") + print("p : ",p) + print("q : ",q) + + print("\n Plus ------") + for i in (p + q): + #print(repr(i)) + #print("\t", str(i.get_postfix())) + print(i) + + print("\n Moins ------") + for i in (p - q): + #print(repr(i)) + #print("\t", str(i.get_postfix())) + print(i) + + print("\n Multiplier ------") + for i in (p * q): + #print(repr(i)) + #print("\t", str(i.get_postfix())) + print(i) + + +if __name__ == '__main__': + p = Polynom([1, -2 ]) + q = Polynom([4, 7]) + #test(p,q) + + q = Polynom([0, Fraction(1,2), 0, Fraction(-4,3)]) + #test(p,q) + + p = Polynom([1, 1, 1 ]) + print(p) + + + #print("-- Poly étrange --") + #p = Polynom([1, [[2, 3, "*"],3], 4], "x") + #print(repr(p)) + #for i in p.simplify(): + # print(repr(i)) + #print("-- Poly étrange --") + #p = Polynom([1, [[2, 3, "*"], [4,5,"*"]], 4], "x") + #print(repr(p)) + #print(p) + #for i in p.simplify(): + # print(repr(i)) + + +# ----------------------------- +# Reglages pour 'vim' +# vim:set autoindent expandtab tabstop=4 shiftwidth=4: +# cursor: 16 del diff --git a/test/test_polynom.py b/test/test_polynom.py new file mode 100644 index 0000000..96e3199 --- /dev/null +++ b/test/test_polynom.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python +# encoding: utf-8 + + +import unittest + +from pymath.polynom import Polynom +from pymath.fraction import Fraction + + +class TestPolynom(unittest.TestCase): + """Testing functions from pymath.polynom""" + + def test_init(self): + p = Polynom([1, 2, 3], "x") + + def test_init_multi(self): + p = Polynom([1, [2, 3], 4], "x") + + def test_init_arith(self): + p = Polynom([1, [2, 3, "+"], 4], "x") + + def test_init_arith_2(self): + p = Polynom([1, [[2, 3, "*"],3], 4], "x") + + def test_deg(self): + pass + + def test_eval(self): + pass + + #def test_print(self): + # p = Polynom([1,2,3]) + # ans = "1 + 2 x + 3 x^2" + # self.assertEqual(ans, str(p)) + + #def test_print_monom(self): + # p = Polynom([0,2]) + # ans = "2 x" + # self.assertEqual(ans, str(p)) + + #def test_print_0_coef(self): + # p = Polynom([0,1,3]) + # ans = "x + 3 x^2" + # self.assertEqual(ans, str(p)) + + #def test_print_multi_coef(self): + # p = Polynom([1,[2, -2],3]) + # ans = "1 + 2 x - 2 x + 3 x^2" + # self.assertEqual(ans, str(p)) + + def test_get_postfix(self): + p = Polynom([1,2,3]) + #ans = [1, 2, "x", "*", "+", 3, "x", 2, "^", "*", "+"] + ans = [3, 'x', 2, '^', '*', 2, 'x', '*', '+', 1, '+'] + self.assertEqual(ans, p.get_postfix()) + + def test_get_postfix_monom(self): + p = Polynom([0,2]) + ans = [2, "x", "*"] + self.assertEqual(ans, p.get_postfix()) + + def test_get_postfix_0_coef(self): + p = Polynom([0,2,0,4]) + #ans = [2, "x", "*", 4, "x", 3, "^", "*", "+"] + ans = [4, 'x', 3, '^', '*', 2, 'x', '*', '+'] + self.assertEqual(ans, p.get_postfix()) + + def test_get_postfix_1_coef(self): + p = Polynom([0,1,1]) + #ans = ["x", "x", 2, "^", "+"] + ans = ["x", 2, "^", "x", "+"] + self.assertEqual(ans, p.get_postfix()) + + def test_get_postfix_neg_coef(self): + # TODO: Choix arbitraire (vis à vis des + et des -) il faudra faire en fonction de render |sam. juin 14 09:45:55 CEST 2014 + p = Polynom([-1,-2,-3]) + #ans = [-1, -2, "x", "*", "+", -3, "x", 2, "^", "*", "+"] + ans = [-3, 'x', 2, '^', '*', -2, 'x', '*', '+', -1, '+'] + self.assertEqual(ans, p.get_postfix()) + + def test_get_postfix_multi_coef(self): + p = Polynom([1,[2, 3],4]) + #ans = [1, 2, "x", "*", "+", 3, "x", "*", "+", 4, "x", 2, "^", "*", "+"] + ans = [4, 'x', 2, '^', '*', 2, 'x', '*', '+', 3, 'x', '*', '+', 1, '+'] + self.assertEqual(ans, p.get_postfix()) + + def test_get_postfix_arithm_coef(self): + p = Polynom([1,[2, 3, "+"],4]) + #ans = [1, 2, 3, "+", "x", "*", "+", 4, "x", 2, "^", "*", "+"] + ans = [4, 'x', 2, '^', '*', 2, 3, '+', 'x', '*', '+', 1, '+'] + self.assertEqual(ans, p.get_postfix()) + + def test_reduce_nilpo(self): + p = Polynom([1, 2, 3]) + self.assertEqual(p, p.reduce()[-1]) + + def test_reduce(self): + p = Polynom([1, [2, 3], 4]) + reducted = Polynom([1, 5, 4]) + self.assertEqual(p.reduce()[-1],reducted) + + def test_add_int(self): + p = Polynom([1, 2, 3]) + q = (p + 2)[-1] + self.assertEqual(q, Polynom([3, 2, 3])) + + def test_add_frac(self): + p = Polynom([1, 2, 3]) + f = Fraction(1, 2) + q = (p + f)[-1] + self.assertEqual(q, Polynom([Fraction(3, 2), 2, 3])) + + def test_add_poly(self): + p = Polynom([1, 0, 3]) + q = Polynom([0, 2, 3]) + r = (p + q)[-1] + self.assertEqual(r, Polynom([1, 2, 6])) + + def test_radd_int(self): + pass + + def test_radd_frac(self): + pass + + def test_radd_poly(self): + pass + + def test_mul_int(self): + pass + + def test_mul_frac(self): + pass + + def test_mul_poly(self): + pass + + def test_rmul_int(self): + pass + + def test_rmul_frac(self): + pass + + def test_rmul_poly(self): + pass + + +if __name__ == '__main__': + unittest.main() + + + + + + + + +# ----------------------------- +# Reglages pour 'vim' +# vim:set autoindent expandtab tabstop=4 shiftwidth=4: +# cursor: 16 del +