source: pyromaths/trunk/fuentes/src/pyromaths/classes/Polynome.py @ 423

Last change on this file since 423 was 423, checked in by mabarracus, 4 years ago

add sources from pyromaths 15.10

File size: 12.7 KB
Line 
1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3#
4# Pyromaths
5# Un programme en Python qui permet de créer des fiches d'exercices types de
6# mathématiques niveau collège ainsi que leur corrigé en LaTeX.
7# Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org)
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22#
23
24if __name__ == "__main__":
25    import sys, os
26    sys.path.append(os.path.join('..'))
27
28# from .Racine import simplifie_racine, RacineDegre2, sqrt
29from .Racine import RacineDegre2
30from .Fractions import Fraction
31from pyromaths.outils import Priorites3
32import re
33# from pyromaths.outils.Affichage import pTeX, TeX, radicalTeX, fTeX, Fractions, tTeX
34from pyromaths.outils.Affichage import TeX, tTeX
35
36class Polynome:
37    '''Classe de polynôme pour le lycee'''
38    def __init__(self, liste_coeff, var="x"):
39        self.var = var  # Lettre pour la var
40        liste_reduite = {}
41        if isinstance(liste_coeff, str):
42            liste_coeff = str_Polynome(liste_coeff, var)
43        elif isinstance(liste_coeff, list):
44            liste_coeff = dict((i, liste_coeff[i])for i in range(len(liste_coeff)))
45        elif isinstance(liste_coeff, int) or isinstance(liste_coeff, Fraction) or isinstance(liste_coeff, float):
46            liste_coeff = {0:liste_coeff}
47        for i in liste_coeff.iterkeys():
48            if liste_coeff[i] != 0:
49                if isinstance(liste_coeff[i], (RacineDegre2, Fraction)):
50                    #===========================================================
51                    # print liste_coeff[i]
52                    #===========================================================
53                    liste_reduite[i] = liste_coeff[i].simplifie()
54                else:
55                    liste_reduite[i] = Fraction(liste_coeff[i], 1)
56        if liste_reduite == {} or liste_coeff == []:
57            liste_reduite = {0:0}
58        self.dictio = liste_reduite
59        self.puiss = liste_reduite.keys()
60        self.puiss.sort(reverse=True)
61        self.deg = self.degre()
62        self.degre_max = max(0, self.deg)
63
64    def __len__(self):
65        return max(0, self.deg) + 1
66
67    def degre(self):
68        degre = float("-inf")
69        for i in self.dictio.iterkeys():
70            if i > degre and self.dictio[i] != 0:
71                degre = i
72        return degre
73
74    def __getitem__(self, i):
75        '''P[i] renvoie le coefficient de rang i'''
76        return self.dictio.get(i, 0)
77
78    def __str__(self):
79        '''renvoie une str pour un affichage python'''
80        return self.TeX(var=self.var)
81
82
83    def TeX(self, var='', display=True, parenthese=False):
84        '''renvoie une chaine de caractere imprimant les fractions dans TeX'''
85        if var == '':
86            var = self.var
87        exposants = [] + self.puiss
88        premier = 1
89        string = ''
90        #=======================================================================
91        # if display:
92        #     fractex="\\dfrac"
93        # else:
94        #     fractex="\\frac"
95        #=======================================================================
96        for exposant in exposants :
97            if premier:
98                if self[exposant] == 1 and exposant != 0:
99                    string = ''
100                elif self[exposant] == -1 and exposant != 0:
101                    string = '-'
102                else:
103                    string = TeX(self[exposant])
104                premier = 0
105            elif self[exposant] != 1:
106                if self.dictio[exposant] == -1:
107                    string += '-'
108                else:
109                    string += tTeX(self[exposant])
110            else:
111                string += "+"
112            if exposant == 1:
113                terme = var
114            elif (exposant == 0) and ((self[exposant] == 1) or (self[exposant] == -1)):
115                terme = '1'
116            elif exposant == 0:
117                terme = ''
118            else:
119                terme = var + u'^' + str(exposant)
120            string += terme
121        if parenthese and (len(self.puiss) > 1 or self[self.degre_max] < 0):
122            return "\\left(" + string + "\\right)"
123        else:
124            return string
125
126    def __add__(self, other):
127        if isinstance(other, int) or isinstance(other, float) or  isinstance(other, Fraction) or isinstance(other, RacineDegre2):
128            return self +Polynome({0:other}, var=self.var)
129        result = {0:0}
130        liste1 = self.puiss
131        liste2 = other.puiss
132        for i in liste1 :
133            s = self.dictio.get(i) + other.dictio.get(i, 0)
134            if s != 0:
135                result[i] = s
136        for i in liste2:
137            if i not in liste1:
138                result[i] = other.dictio[i]
139        return Polynome(result, var=self.var)
140
141    def __mul__(self, other):
142        if isinstance(other, Polynome):
143            result = Polynome({0:0}, var=self.var)
144            for i in self.dictio.iterkeys():
145                for j in other.dictio.iterkeys():
146                    exposant = i + j
147                    coefficient = self.dictio[i] * other.dictio[j]
148                    result = result + Polynome({exposant:coefficient}, var=self.var)
149            return result
150        else:
151            return self * Polynome(other)
152    def __ne__(self, other):
153        return not(self == other)
154    def __eq__(self, other):
155        if (isinstance(other, int) or isinstance(other, Fraction) or isinstance(other, float)):
156            if self.degre_max == 0 and self[0] == other:
157                return True
158            else:
159                return False
160        elif self.var == other.var and self.dictio == other.dictio:
161            return True
162        else:
163            return False
164
165    def __pow__(self, other):
166        if isinstance(other, int) and other >= 0:
167            result = Polynome({0:1}, self.var)
168            for dummy in xrange(other):
169                result *= self
170            return result
171
172    def __radd__(self, other):
173        if isinstance(other, int) or isinstance(other, float) or isinstance(other, Fraction):
174            return self +Polynome({0:other}, var=self.var)
175        return self +other
176
177    def __sub__(self, other):
178        return self +(-other)
179
180    def __rsub__(self, other):
181        return -(self -other)
182
183    def __neg__(self):
184        return self * Polynome({0:-1}, var=self.var)
185
186    def __rmul__(self, nombre):
187        return self * Polynome({0:nombre})
188
189    def __div__(self, other):
190        if isinstance(other, int):
191            return Fraction(1, other) * self
192        elif isinstance(other, Fraction) or isinstance(other, float)or isinstance(other, RacineDegre2):
193            return (1 / other) * self
194        else:
195            quotient = Polynome({}, var=self.var)
196            reste = self
197            diviseur_degre = other.deg
198            while diviseur_degre <= reste.deg:
199                ajout_quotient_deg = reste.deg - diviseur_degre
200                facteur = reste.dictio[reste.deg] / other.dictio[other.deg]
201                ajout_quotient = Polynome({ajout_quotient_deg:facteur}, var=self.var)
202                quotient = quotient + ajout_quotient
203                soustrait_reste = ajout_quotient * other
204                reste = reste - soustrait_reste
205            return quotient, reste
206    def simplifie(self):
207        result = {}
208        for i in self.puiss:
209            if isinstance(self[i], (Fraction, RacineDegre2)):
210                result[i] = self[i].simplifie()
211            else:
212                result[i] = self[i]
213        return Polynome(result)
214
215    def __call__(self, x,):
216        '''renvoie la Fraction ou l'int P(x)'''
217        if x == float("inf") or x == float("-inf"):
218            if self.degre_max == 0:
219                return self[0]
220            elif self.deg % 2 == 0:
221                return self[self.deg] * float("inf")
222            else:
223                return self[self.deg] * x
224        elif isinstance(x, str):
225            return self.TeX(var=x)
226        else:
227            result = 0
228            for i in self.dictio.iterkeys():
229                result = result + self[i] * x ** i
230            if isinstance(result, str):
231                result = eval(Priorites3.priorites(result)[-1][0])
232            if isinstance(result, (int, float)):
233                return result
234            elif isinstance(result, Fraction):
235                result = result.simplifie()
236                if isinstance(result, int):
237                    return result
238                if result.d == 1:
239                    return result.n
240                else:
241                    return result
242            elif result.denominateur == 1:
243                return result.numerateur
244            else:
245                return result
246
247    def racine_evidente(self, liste=[-2, -1, 0, 1, 2]):
248        listerac = []
249        for i in liste:
250            if self(i) == 0:
251                listerac = listerac + [i]
252        return listerac
253
254    def factorise(self, TeX=False, racines=[0, -1, 1, 2, -2]):
255        facteurs = [Polynome({0:self.dictio[self.deg]}, var=self.var)]
256        developpe, reste = self / facteurs[0]
257        for r in racines:
258            while developpe(r) == 0:
259                rac = -r
260                developpe, reste = developpe / Polynome({1:1, 0:rac}, var=self.var)
261                facteurs = facteurs + [Polynome({1:1, 0:rac})]
262        if TeX:
263            stringTeX = ""
264            if not(facteurs[0] == Polynome({0:1}, var=self.var)):
265                stringTeX += facteurs[0].TeX()
266            for i in facteurs[1:]:
267                if i[0] != 0:
268                    stringTeX += "\\left(" + i.TeX() + "\\right) \\times "
269                else:
270                    stringTeX += i.TeX() + " \\times "
271            if developpe == Polynome({0:1}, var=self.var):
272                return stringTeX[:-7]
273            else:
274                return stringTeX + "\\left(" + developpe.TeX() + "\\right)"
275        else:
276            return facteurs + [developpe]
277
278    def derive(self):
279        result = {}
280        for i in self.dictio.iterkeys():
281            if i == 0:
282                result[0] = 0
283            else:
284                result[i - 1] = int(i) * self[i]
285        return Polynome(result, self.var)
286    def primitive(self):
287        result = {}
288        for i in self.dictio.iterkeys():
289            result[i + 1] = Fraction(1, int(i + 1)) * self.dictio[i]
290        return Polynome(result, self.var)
291
292def str_Polynome(string, var='x'):
293    '''str -> dict'''
294    # TODO reconnaitre les coefficients fractionnaires
295    resultat = []
296    termes = {}
297    separeplus = (string).split("+")
298    for element in separeplus:
299        temp = []
300        temp = element.split("-")
301        for bis in temp:
302            resultat.append(bis)
303            if temp.index(bis) != len(temp) - 1:
304                resultat.append(-1)
305        if separeplus.index(element) != len(separeplus) - 1:
306            resultat.append(1)
307    if '' in resultat:
308        resultat.remove('')
309    for element in resultat:
310        index = resultat.index(element)
311        if index > 0:
312            coeff = resultat[index - 1]
313        else:
314            coeff = 1
315        if (element not in [-1, 1]):
316            if element == var:
317                termes[1] = (coeff)
318            else:
319                a = re.findall('\d+(?:\.\d*)?', element)
320                if (len(a) == 1) and (not re.findall('\^', element)) and (re.findall(var, element)):
321                    termes[1] = coeff * Fraction(eval(a[0]))
322                elif (len(a) == 1) and (re.findall(var, element)):
323                    termes[int(a[0])] = coeff * 1
324                elif (len(a) == 1):
325                    termes[0] = coeff * Fraction(eval(a[0]))
326                else:
327                    termes[int(a[1])] = coeff * Fraction(eval(a[0]))
328    return termes
329
330if __name__ == "__main__":
331    from TEST.imprimetest import *
332    X = Polynome("x")
333    P = Polynome({2:4, 1:8, 0:1, 3:0})
334# #    Q=Polynome({2:-4,0:-1,1:8})
335# #    R=Polynome({3:1,2:1,1:-2})
336# #    D=Polynome({1:1,0:2})
337# #    F=Polynome("x-4")
338# #    FF=Polynome("x^2-3")
339# #    Divi=FF*F+7
340# #    FR=Polynome({3:Fraction(2,3),2:Fraction(2,3),1:Fraction(-4,3)})
341# #    print "P=", P
342# #    print "Q=", Q
343# #    print "R=", R
344# #    print "FR=",FR
345# #    R_facteur=R.factorise()
346# #    print "R=",R.factorise(TeX=True)
347# #    #TeX_division(R,D)
348# #    print Divi*Polynome("x^3")-28*X
349# #    #imprime_TeX(TeX_division(Divi*Polynome("x^3")-28*X,F*X))
Note: See TracBrowser for help on using the repository browser.