Class Pygen

Librairie C++ de calcul formel/ C++ symbolic computation library

Modérateur : xcasadmin

jpapot
Messages : 13
Inscription : mer. nov. 16, 2016 6:43 am

Class Pygen

Message par jpapot » lun. nov. 21, 2016 2:11 pm

Bonjour.

J'apprends à utiliser la bibliothèque Giac dans Python.
Les objets créés sont du type "Pygen".

1) Pouvez-vous expliquer de quoi il s'agit ?
2) Je ne parviens pas à transformer les objets du type pygen en un autre type plus classique dans python (list, str, float, int ...). J'aimerais pouvoir le faire afin d'utiliser la bibliothèque Matplotlib. Comment faire ?

Un essai pour transformer une liste Pygen en une liste Python (hélas les éléments sont aussi du type Pygen) :
Listes et pygen.png
Listes et pygen.png (102.33 Kio) Consulté 6178 fois
Merci de vos éclaircissements et aide bienvenue !

JP

frederic han
Messages : 1137
Inscription : dim. mai 20, 2007 7:09 am
Localisation : Paris
Contact :

Re: Class Pygen

Message par frederic han » mar. nov. 22, 2016 11:54 am

Bonjour,

La classe Pygen va absorber les objets python et donner aux opérations le sens qu'elles ont dans giac/xcas. Techniquement elle ne garde qu'un pointeur vers un objet de type gen de la librairie C++ giac, ce qui permet de limiter le temps perdu en conversions.

Il est fort probable que from giacpy import * importe trop de mots (par exemple int)

Il y a quelques informations dans

from giacpy import giac
help(giac)

par exemple dans la partie: Lists of Pygen and Giac lists on voit que:

Code : Tout sélectionner

       >>> l1=giac(range(10)); l2=[1/(i**2+1) for i in l1]
       >>> sum(l2)
       33054527/16762850
    
       So l1+l1 is done in giac and means a vector addition. But l2+l2 is done in Python so it is the list concatenation.
    
       >>> l1+l1
       [0,2,4,6,8,10,12,14,16,18]
       >>> l2+l2
       [1, 1/2, 1/5, 1/10, 1/17, 1/26, 1/37, 1/50, 1/65, 1/82, 1, 1/2, 1/5, 1/10, 1/17, 1/26, 1/37, 1/50, 1/65, 1/82]
Les objets de type Pygen sont aussi appelables au sens de giac/xcas.
Ex:

Code : Tout sélectionner

>>> from giacpy import giac
>>> x,y=giac('x,y')
>>> P=x**3+y*x+1/y
>>> f=P.unapply(y)
>>> f(1+2*x+y)
x**3+(1+2*x+y)*x+1/(1+2*x+y)
>>> A=giac([[1,2],[3,4]])
>>> A[0,1] # dans giac/xcas les indices commencent a 0
2
>>> A(1,2) # mais si l'on prefere qu'ils commencent a 1 giac/xcas propose cette syntaxe.
2
>>> A*A
[[7,10],[15,22]]
>>> A.matpow('n') # comme je n'ai pas fait  n=giac('n') avant on le met entre ' '
[[(sqrt(33)-3)*((sqrt(33)+5)/2)**n*sqrt(33)/66-(-sqrt(33)-3)*((-sqrt(33)+5)/2)**n*sqrt(33)/66,(sqrt(33)-3)*((sqrt(33)+5)/2)**n*(sqrt(33)+11)/132+(-sqrt(33)-3)*((-sqrt(33)+5)/2)**n*(-sqrt(33)+11)/132],[6*((sqrt(33)+5)/2)**n*sqrt(33)/66-6*((-sqrt(33)+5)/2)**n*sqrt(33)/66,6*((sqrt(33)+5)/2)**n*(sqrt(33)+11)/132+6*((-sqrt(33)+5)/2)**n*(-sqrt(33)+11)/132]]
>>> (A % 2).ker()  # A a bien un noyau non nul dans Z/2Z
[[0 % 2,-1]]
(NB: comme A etait de type Pygen, A %2 a bien eu le sens pour giac.
NB:

Code : Tout sélectionner

>>> giac(1 % 2) # ici 1 %2 est celui de python donc 1 que l'on envoit a giac
1
>>> giac('1 % 2') # 
1 % 2
>>> giac(1) % 2 # ici c'est l'operation au sens de giac xcas donc le 1 de Z/2Z
1 % 2



Il y a tres peu de types d'objets giac qui auraient un sens en python de base, et les entiers ne sont pas du tout les mêmes (alors que dans sage si) bref il faudra souvent passer par des strings.

Code : Tout sélectionner

from giacpy import giac
a=giac(2)
b=a**1000
c=int(str(b))
Il y a quelques conversions utiles qui evitent les str:

Dans votre exemple précédent il suffisait de faire (idem avec un tuple):

Code : Tout sélectionner

x1=list(a)
C'est normal que les elements de cette liste restent du type Pygen, même 1/2 n'aurait pas le meme sens.

Un autre cas qui peut vous etre utile pour eviter de passer par des str est celui des flottants. Si l'objet giac correspond bien à un flottant (et non pas un flottant multiprecision) alors cela a un sens de le convertir directement avec l'attribu: _double

Code : Tout sélectionner

>>> a=giacpy.approx('pi,100')
>>> b=giacpy.approx('pi,14') # la taille d'un flottant peut dependre de votre architecture
>>> a._type # flottant multiprecision
3
>>> a._double  # n'a pas de sens
3.434313810944179e+306
>>> b._type # flottant 
1
>>> b._double # a bien un sens
3.1415926535897967
Par exemple pour convertir quelques dessins de giac vers sage j'avais fait cela:

Code : Tout sélectionner

def mplot(self):
        """
        Basic export of some 2D plots to sage. Only generic plots are supported.
        lines, circles, ... are not implemented
        """
        xyscat=[]
        xyplot=[]
        plotdata=self
        if not plotdata.type()=='DOM_LIST':
           return

        for G in plotdata:
             if G.dim()>2:  # it is not a pnt. Ex: scatterplot
                for g in G:
                    xyscat=xyscat+[[(g.real())._double,(g.im())._double]]


             else:
                if G[1].type()=='DOM_LIST':
                   l=G[1].op()
                else:
                   l=G[1][2].op()
                xyplot=[[(u.real())._double,(u.im())._double] for u in l]


        if (xyscat != []):
           result=scatter_plot(xyscat)

        else:
           result=line(xyplot)

        return result
Si vous voulez voir le code cython qui a permis de creer giacpy, il est la:
https://gitlab.math.univ-paris-diderot. ... giacpy.pyx

frederic han
Messages : 1137
Inscription : dim. mai 20, 2007 7:09 am
Localisation : Paris
Contact :

Re: Class Pygen

Message par frederic han » mar. nov. 22, 2016 2:04 pm

Mon exemple avec la matrice modulaire n'etait pas tres bien choisi. Avec celui ci on voit mieux la différence entre le % de giac et celui de python:

Code : Tout sélectionner

>>> from giacpy import giac
>>> A=giac([[2,1],[1,3]])
>>> (A % 5)
[[2 % 5,1 % 5],[1 % 5,-2 % 5]]
>>> (A % 5).ker()
[[-2 % 5,-1]]
alors que si l'on n'utilise que le % de python:

Code : Tout sélectionner

>>> B=[[2 % 5, 1 % 5 ],[ 1 % 5 ,3 % 5]] # une liste de liste d'entiers python
>>> B
[[2, 1], [1, 3]]
>>> giac(B).ker() 
[]
>>> B % 5 # n'a pas de sens pour une liste python.
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for %: 'list' and 'int'
>>> giac(B) % 5  # ici on retrouve l'analogue de A
[[2 % 5,1 % 5],[1 % 5,-2 % 5]]

jpapot
Messages : 13
Inscription : mer. nov. 16, 2016 6:43 am

Re: Class Pygen

Message par jpapot » mar. nov. 22, 2016 9:04 pm

Merci pour cette longue réponse qui va me demander du temps de réflexion (et de digestion !)

J'en profite pour vous soumettre un résultat qui m'est apparu en faisant un essai de résolution d'équation. (J'ai trouvé cet exemple dans le mode d'emploi de xcas) : cos(2x)=1/2

Les 2 solutions modulo 2pi sont pi/6 et -pi/6

Avec solve j'obtiens pourtant des valeurs approchées :
Pb résolution.png
Pb résolution.png (21.63 Kio) Consulté 6161 fois
Qu'en pensez-vous ?

Bonne soirée et encore merci de m'accorder autant de votre temps.
Cordialement.
JP

frederic han
Messages : 1137
Inscription : dim. mai 20, 2007 7:09 am
Localisation : Paris
Contact :

Re: Class Pygen

Message par frederic han » mar. nov. 22, 2016 10:04 pm

Oui car vous avez entré

Code : Tout sélectionner

1/2
qui en python3 fait 0.5 car giacpy ne modifie pas les opérations entre 2 objets python, il ne s'occupe que de celles entre 2 Pygen ou 1 Pygen et 1 autre. (Donc prudence avec / et % et 2 entiers python)
Vous avez donc fait:

Code : Tout sélectionner

In [122]: equal(cos(2*x),0.5).solve()
Out[122]: list[-0.523598775598,0.523598775598]
Mais vous auriez pu faire:

Code : Tout sélectionner

In [123]: equal(cos(2*x),'1/2').solve()
Out[123]: list[-1/6*pi,1/6*pi]

In [124]: equal(cos(2*x),giac(1)/2).solve()
Out[124]: list[-1/6*pi,1/6*pi]
ou bien comme cela c'est peut être plus naturel

Code : Tout sélectionner

In [163]: (cos(2*x)-'1/2').solve()     
Warning, argument is not an equation, solving cos(2*x)-1/2=0
Out[163]: list[-1/6*pi,1/6*pi]

In [164]: cos(2*x).equal('1/2').solve()
Out[164]: list[-1/6*pi,1/6*pi]


Au fait je n'ai jamais su s'il existait un analogue de equal pour les inéquations,
@bernard, ca pourrait nous être utile.

Il y a un moyen de s'en sortir je l'explique dans la rubrique giacpy toute neuve.

parisse
Messages : 5739
Inscription : mar. déc. 20, 2005 4:02 pm
Contact :

Re: Class Pygen

Message par parisse » jeu. nov. 24, 2016 7:09 am

Il y a bien des fonctions pour les inequations: _superieur_strict, _superieur_equal, _inferieur_strict, _inferieur_equal

Répondre