Pexpect Interface to Giac - Interpreter Interfaces

Skip to content
Back to top
View this page
Edit this page

# Pexpect Interface to Giac

(You should prefer the cython interface: giacpy_sage and its libgiac command)

(adapted by F. Han from William Stein and Gregg Musiker maple’s interface)

You must have the Giac interpreter installed and available as the command `giac` in your PATH in order to use this interface. You need a giac version supporting “giac –sage” ( roughly after 0.9.1 ). In this case you do not have to install any optional Sage packages. If giac is not already installed, you can download binaries or sources or spkg (follow the sources link) from the homepage:

Homepage <https://www-fourier.ujf-grenoble.fr/~parisse/giac.html>

Type `giac.[tab]` for a list of all the functions available from your Giac install. Type `giac.[tab]?` for Giac’s help about a given function. Type `giac(...)` to create a new Giac object, and `giac.eval(...)` to run a string using Giac (and get the result back as a string).

If the giac spkg is installed, you should find the full html documentation there:

    $SAGE_LOCAL/share/giac/doc/en/cascmd_local/index.html

EXAMPLES:

Sage

    sage: giac('3 * 5')
    15
    sage: giac.eval('ifactor(2005)')
    '5*401'
    sage: giac.ifactor(2005)
    2005
    sage: l=giac.ifactors(2005) ; l; l[2]
    [5,1,401,1]
    401
    sage: giac.fsolve('x^2=cos(x)+4', 'x','0..5')
    [1.9140206190...
    sage: giac.factor('x^4 - y^4')
    (x-y)*(x+y)*(x^2+y^2)
    sage: R.<x,y>=QQ[];f=(x+y)^5;f2=giac(f);(f-f2).normal()
    0
    sage: x,y=giac('x,y'); giac.int(y/(cos(2*x)+cos(x)),x)     # random
    y*2*((-(tan(x/2)))/6+(-2*1/6/sqrt(3))*ln(abs(6*tan(x/2)-2*sqrt(3))/abs(6*tan(x/2)+2*sqrt(3))))

Python

    >>> from sage.all import *
    >>> giac('3 * 5')
    15
    >>> giac.eval('ifactor(2005)')
    '5*401'
    >>> giac.ifactor(Integer(2005))
    2005
    >>> l=giac.ifactors(Integer(2005)) ; l; l[Integer(2)]
    [5,1,401,1]
    401
    >>> giac.fsolve('x^2=cos(x)+4', 'x','0..5')
    [1.9140206190...
    >>> giac.factor('x^4 - y^4')
    (x-y)*(x+y)*(x^2+y^2)
    >>> R = QQ['x, y']; (x, y,) = R._first_ngens(2);f=(x+y)**Integer(5);f2=giac(f);(f-f2).normal()
    0
    >>> x,y=giac('x,y'); giac.int(y/(cos(Integer(2)*x)+cos(x)),x)     # random
    y*2*((-(tan(x/2)))/6+(-2*1/6/sqrt(3))*ln(abs(6*tan(x/2)-2*sqrt(3))/abs(6*tan(x/2)+2*sqrt(3))))

If the string “error” (case insensitive) occurs in the output of anything from Giac, a `RuntimeError` exception is raised.

## Tutorial

AUTHORS:

- Gregg Musiker (2006-02-02): initial version.

- Frederic Han: adapted to giac.

- Marcelo Forets (2017-04-06): conversions and cleanup.

This tutorial is based on the Maple Tutorial for number theory from http://www.math.mun.ca/~drideout/m3370/numtheory.html.

### Syntax

There are several ways to use the Giac Interface in Sage. We will discuss two of those ways in this tutorial.

1. If you have a giac expression such as

       factor( (x^4-1));

   We can write that in sage as

   Sage

       sage: giac('factor(x^4-1)')
       (x-1)*(x+1)*(x^2+1)

   Python

       >>> from sage.all import *
       >>> giac('factor(x^4-1)')
       (x-1)*(x+1)*(x^2+1)

   Notice, there is no need to use a semicolon.

2. Since Sage is written in Python, we can also import giac commands and write our scripts in a pythonic way. For example, `factor()` is a giac command, so we can also factor in Sage using

   Sage

       sage: giac('(x^4-1)').factor()
       (x-1)*(x+1)*(x^2+1)

   Python

       >>> from sage.all import *
       >>> giac('(x^4-1)').factor()
       (x-1)*(x+1)*(x^2+1)

   where `expression.command()` means the same thing as `command(expression)` in Giac. We will use this second type of syntax whenever possible, resorting to the first when needed.

   Sage

       sage: giac('(x^12-1)/(x-1)').normal()
       x^11+x^10+x^9+x^8+x^7+x^6+x^5+x^4+x^3+x^2+x+1

   [Python]

       >>> from sage.all import *
       >>> giac('(x^12-1)/(x-1)').normal()
       x^11+x^10+x^9+x^8+x^7+x^6+x^5+x^4+x^3+x^2+x+1

### Some typical input

The normal command will reduce a rational function to the lowest terms. In giac, simplify is slower than normal because it tries more sophisticated simplifications (ex algebraic extensions) The factor command will factor a polynomial with rational coefficients into irreducible factors over the ring of integers (if your default configuration of giac (cf .xcasrc) has not allowed square roots). So for example,

Sage

    sage: giac('(x^12-1)').factor( )
    (x-1)*(x+1)*(x^2+1)*(x^2-x+1)*(x^2+x+1)*(x^4-x^2+1)

Python

    >>> from sage.all import *
    >>> giac('(x^12-1)').factor( )
    (x-1)*(x+1)*(x^2+1)*(x^2-x+1)*(x^2+x+1)*(x^4-x^2+1)

Sage

    sage: giac('(x^28-1)').factor( )
    (x-1)*(x+1)*(x^2+1)*(x^6-x^5+x^4-x^3+x^2-x+1)*(x^6+x^5+x^4+x^3+x^2+x+1)*(x^12-x^10+x^8-x^6+x^4-x^2+1)

[Python]

    >>> from sage.all import *
    >>> giac('(x^28-1)').factor( )
    (x-1)*(x+1)*(x^2+1)*(x^6-x^5+x^4-x^3+x^2-x+1)*(x^6+x^5+x^4+x^3+x^2+x+1)*(x^12-x^10+x^8-x^6+x^4-x^2+1)

### Giac console

Another important feature of giac is its online help. We can access this through sage as well. After reading the description of the command, you can press `q` to immediately get back to your original prompt.

Incidentally you can always get into a giac console by the command

Sage

    sage: giac.console()                       # not tested
    sage: !giac                                # not tested

Python

    >>> from sage.all import *
    >>> giac.console()                       # not tested
    >>> !giac                                # not tested

Note that the above two commands are slightly different, and the first is preferred.

For example, for help on the giac command factors, we type

Sage

    sage: giac.help('factors')                     # not tested

[Python]

    >>> from sage.all import *
    >>> giac.help('factors')                     # not tested

Sage

    sage: alpha = giac((1+sqrt(5))/2)
    sage: beta = giac(1-sqrt(5))/2
    sage: f19  = alpha^19 - beta^19/sqrt(5)
    sage: f19
    (sqrt(5)/2+1/2)^19-((-sqrt(5)+1)/2)^19/sqrt(5)
    sage: (f19-(5778*sqrt(5)+33825)/5).normal()
    0

Python

    >>> from sage.all import *
    >>> alpha = giac((Integer(1)+sqrt(Integer(5)))/Integer(2))
    >>> beta = giac(Integer(1)-sqrt(Integer(5)))/Integer(2)
    >>> f19  = alpha**Integer(19) - beta**Integer(19)/sqrt(Integer(5))
    >>> f19
    (sqrt(5)/2+1/2)^19-((-sqrt(5)+1)/2)^19/sqrt(5)
    >>> (f19-(Integer(5778)*sqrt(Integer(5))+Integer(33825))/Integer(5)).normal()
    0

### Function definitions

Let’s say we want to write a giac program now that squares a number if it is positive and cubes it if it is negative. In giac, that would look like

    mysqcu := proc(x)
    if x > 0 then x^2;
    else x^3; fi;
    end;

In Sage, we write

Sage

    sage: mysqcu = giac('proc(x) if x > 0 then x^2 else x^3 fi end')
    sage: mysqcu(5)
    25
    sage: mysqcu(-5)
    -125

Python

    >>> from sage.all import *
    >>> mysqcu = giac('proc(x) if x > 0 then x^2 else x^3 fi end')
    >>> mysqcu(Integer(5))
    25
    >>> mysqcu(-Integer(5))
    -125

More complicated programs should be put in a separate file and loaded.

### Conversions

The `GiacElement.sage()` method tries to convert a Giac object to a Sage object. In many cases, it will just work. In particular, it should be able to convert expressions entirely consisting of:

- numbers, i.e. integers, floats, complex numbers;

- functions and named constants also present in Sage, where Sage knows how to translate the function or constant’s name from Giac’s

- symbolic variables whose names don’t pathologically overlap with objects already defined in Sage.

This method will not work when Giac’s output includes functions unknown to Sage.

If you want to convert more complicated Giac expressions, you can instead call `GiacElement._sage_()` and supply a translation dictionary:

Sage

    sage: g = giac('NewFn(x)')
    sage: g._sage_(locals={('NewFn', 1): sin})
    sin(x)

Python

    >>> from sage.all import *
    >>> g = giac('NewFn(x)')
    >>> g._sage_(locals={('NewFn', Integer(1)): sin})
    sin(x)

Moreover, new conversions can be permanently added using Pynac’s `register_symbol`, and this is the recommended approach for library code. For more details, see the documentation for `._sage_()`.

class sage.interfaces.giac.Giac(maxread=None, script_subdirectory=None, server=None, server_tmpdir=None, logfile=None)

  Bases: `Expect`

  Interface to the Giac interpreter.

  You must have the optional Giac interpreter installed and available as the command `giac` in your PATH in order to use this interface. Try the command: print(giac._install_hints()) for more informations on giac installation.

  Type `giac.[tab]` for a list of all the functions available from your Giac install. Type `giac.[tab]?` for Giac’s help about a given function. Type `giac(...)` to create a new Giac object.

  Full html documentation for giac is available from your giac installation at `$PREFIX`/share/giac/doc/en/cascmd_en/index.html

  EXAMPLES:

  Any Giac instruction can be evaluated as a string by the giac command. You can access the giac functions by adding the `giac.` prefix to the usual Giac name.

  Sage

      sage: l=giac('normal((y+sqrt(2))^4)'); l
      y^4+4*sqrt(2)*y^3+12*y^2+8*sqrt(2)*y+4
      sage: f=giac('(u,v)->{ if (u<v){ [u,v] } else { [v,u] }}');f(1,2),f(3,1)
      ([1,2], [1,3])

  Python

      >>> from sage.all import *
      >>> l=giac('normal((y+sqrt(2))^4)'); l
      y^4+4*sqrt(2)*y^3+12*y^2+8*sqrt(2)*y+4
      >>> f=giac('(u,v)->{ if (u<v){ [u,v] } else { [v,u] }}');f(Integer(1),Integer(2)),f(Integer(3),Integer(1))
      ([1,2], [1,3])

  The output of the giac command is a Giac object, and it can be used for another giac command.

  Sage

      sage: l.factors()
      [y+sqrt(2),4]
      sage: giac('(x^12-1)').factor( )
      (x-1)*(x+1)*(x^2+1)*(x^2-x+1)*(x^2+x+1)*(x^4-x^2+1)
      sage: giac('assume(y>0)'); giac('y^2=3').solve('y')
      y
      ...[sqrt(3)]

  [Python]

      >>> from sage.all import *
      >>> l.factors()
      [y+sqrt(2),4]
      >>> giac('(x^12-1)').factor( )
      (x-1)*(x+1)*(x^2+1)*(x^2-x+1)*(x^2+x+1)*(x^4-x^2+1)
      >>> giac('assume(y>0)'); giac('y^2=3').solve('y')
      y
      ...[sqrt(3)]

  You can create some Giac elements and avoid many quotes like this:

  Sage

      sage: x,y,z=giac('x,y,z');type(y)
      <class 'sage.interfaces.giac.GiacElement'>
      sage: I1=(1/(cos(2*y)+cos(y))).integral(y,0,pi/4).simplify()
      sage: (I1-((-2*ln((sqrt(3)-3*tan(1/8*pi))/(sqrt(3)+3*tan(1/8*pi)))*sqrt(3)-3*tan(1/8*pi))/9)).normal()
      0
      sage: ((y+z*sqrt(5))*(y-sqrt(5)*z)).normal()
      y^2-5*z^2

  Python

      >>> from sage.all import *
      >>> x,y,z=giac('x,y,z');type(y)
      <class 'sage.interfaces.giac.GiacElement'>
      >>> I1=(Integer(1)/(cos(Integer(2)*y)+cos(y))).integral(y,Integer(0),pi/Integer(4)).simplify()
      >>> (I1-((-Integer(2)*ln((sqrt(Integer(3))-Integer(3)*tan(Integer(1)/Integer(8)*pi))/(sqrt(Integer(3))+Integer(3)*tan(Integer(1)/Integer(8)*pi)))*sqrt(Integer(3))-Integer(3)*tan(Integer(1)/Integer(8)*pi))/Integer(9))).normal()
      0
      >>> ((y+z*sqrt(Integer(5)))*(y-sqrt(Integer(5))*z)).normal()
      y^2-5*z^2

  Polynomials or elements of SR can be evaluated directly by the giac interface.

  Sage

      sage: R.<a,b> = QQ[]; f = (2+a+b)
      sage: p = giac.gcd(f^3+5*f^5,f^2+f^5); p; R(p.sage())
      sageVARa^2+2*sageVARa*sageVARb+4*sageVARa+sageVARb^2+4*sageVARb+4
      a^2 + 2*a*b + b^2 + 4*a + 4*b + 4

  [Python]

      >>> from sage.all import *
      >>> R = QQ['a, b']; (a, b,) = R._first_ngens(2); f = (Integer(2)+a+b)
      >>> p = giac.gcd(f**Integer(3)+Integer(5)*f**Integer(5),f**Integer(2)+f**Integer(5)); p; R(p.sage())
      sageVARa^2+2*sageVARa*sageVARb+4*sageVARa+sageVARb^2+4*sageVARb+4
      a^2 + 2*a*b + b^2 + 4*a + 4*b + 4

  Variable names in python and giac are independent:

  Sage

      sage: a=sqrt(2);giac('Digits:=30;a:=5');a,giac('a'),giac(a),giac(a).evalf()
      30
      (sqrt(2), 5, sqrt(2), 1.41421356237309504880168872421)

  Python

      >>> from sage.all import *
      >>> a=sqrt(Integer(2));giac('Digits:=30;a:=5');a,giac('a'),giac(a),giac(a).evalf()
      30
      (sqrt(2), 5, sqrt(2), 1.41421356237309504880168872421)

  clear(var)

    Clear the variable named var.

    EXAMPLES:

    Sage

        sage: giac.set('xx', '2')
        sage: giac.get('xx')
        '2'
        sage: giac.clear('xx')
        sage: giac.get('xx')
        'xx'

    Python

        >>> from sage.all import *
        >>> giac.set('xx', '2')
        >>> giac.get('xx')
        '2'
        >>> giac.clear('xx')
        >>> giac.get('xx')
        'xx'

  completions(s)

    Return all commands that complete the command starting with the string s.

    EXAMPLES:

    Sage

        sage: c = giac.completions('cas')
        sage: 'cas_setup' in c
        True

    Python

        >>> from sage.all import *
        >>> c = giac.completions('cas')
        >>> 'cas_setup' in c
        True

  console()

    Spawn a new Giac command-line session.

    EXAMPLES:

    Sage

        sage: giac_console()                   # not tested - giac
        ...
        Homepage http://www-fourier.ujf-grenoble.fr/~parisse/giac.html
        Released under the GPL license 3.0 or above
        See http://www.gnu.org for license details
        -------------------------------------------------
        Press CTRL and D simultaneously to finish session
        Type ?commandname for help
        0>>

    Python

        >>> from sage.all import *
        >>> giac_console()                   # not tested - giac
        ...
        Homepage http://www-fourier.ujf-grenoble.fr/~parisse/giac.html
        Released under the GPL license 3.0 or above
        See http://www.gnu.org for license details
        -------------------------------------------------
        Press CTRL and D simultaneously to finish session
        Type ?commandname for help
        0>>

  cputime(t=None)

    Return the amount of CPU time that the Giac session has used.

    If `t` is not None, then it returns the difference between the current CPU time and `t`.

    EXAMPLES:

    Sage

        sage: t = giac.cputime()
        sage: t                     # random
        0.02
        sage: x = giac('x')
        sage: giac.diff(x^2, x)
        2*x
        sage: giac.cputime(t)       # random
        0.0

    Python

        >>> from sage.all import *
        >>> t = giac.cputime()
        >>> t                     # random
        0.02
        >>> x = giac('x')
        >>> giac.diff(x**Integer(2), x)
        2*x
        >>> giac.cputime(t)       # random
        0.0

  eval(code, strip=True, **kwds)

    Send the code x to the Giac interpreter. Remark: To enable multi-lines codes in the notebook magic mode: `%giac`, the `\n` are removed before sending the code to giac.

    INPUT:

    - `code` – str

    - `strip` – default is `True` and removes `\n`

    EXAMPLES:

    Sage

        sage: giac.eval("2+2;\n3")
        '4,3'
        sage: giac.eval("2+2;\n3",False)
        '4\n3'
        sage: s='g(x):={\nx+1;\nx+2;\n}'
        sage: giac(s)
        ...x+1...x+2...
        sage: giac.g(5)
        7

    Python

        >>> from sage.all import *
        >>> giac.eval("2+2;\n3")
        '4,3'
        >>> giac.eval("2+2;\n3",False)
        '4\n3'
        >>> s='g(x):={\nx+1;\nx+2;\n}'
        >>> giac(s)
        ...x+1...x+2...
        >>> giac.g(Integer(5))
        7

  expect()

    Return the pexpect object for this Giac session.

    EXAMPLES:

    Sage

        sage: m = Giac()
        sage: m.expect() is None
        True
        sage: m._start()
        sage: m.expect()
        Giac with PID ... running .../giac --sage
        sage: m.quit()

    Python

        >>> from sage.all import *
        >>> m = Giac()
        >>> m.expect() is None
        True
        >>> m._start()
        >>> m.expect()
        Giac with PID ... running .../giac --sage
        >>> m.quit()

  get(var)

    Get the value of the variable var.

    EXAMPLES:

    Sage

        sage: giac.set('xx', '2')
        sage: giac.get('xx')
        '2'

    Python

        >>> from sage.all import *
        >>> giac.set('xx', '2')
        >>> giac.get('xx')
        '2'

  help(string)

    Display Giac help about string.

    This is the same as typing “?string” in the Giac console.

    INPUT:

    - `string` – string to search for in the giac help system

    EXAMPLES:

    Sage

        sage: giac.help('Psi')         # not tested - depends of giac and $LANG
        Psi(a,n)=nth-derivative of the function DiGamma (=ln@Gamma) at point a (Psi(a,0)=Psi(a))...

    Python

        >>> from sage.all import *
        >>> giac.help('Psi')         # not tested - depends of giac and $LANG
        Psi(a,n)=nth-derivative of the function DiGamma (=ln@Gamma) at point a (Psi(a,0)=Psi(a))...

  set(var, value)

    Set the variable var to the given value.

    EXAMPLES:

    Sage

        sage: giac.set('xx', '2')
        sage: giac.get('xx')
        '2'

    Python

        >>> from sage.all import *
        >>> giac.set('xx', '2')
        >>> giac.get('xx')
        '2'

  version()

    Wrapper for giac’s version().

    EXAMPLES:

    Sage

        sage: giac.version()
        "giac...

    Python

        >>> from sage.all import *
        >>> giac.version()
        "giac...

class sage.interfaces.giac.GiacElement(parent, value, is_name=False, name=None)

  Bases: `ExpectElement`

  integral(var='x', min=None, max=None)

    Return the integral of `self` with respect to the variable \(x\).

    INPUT:

    - `var` – variable

    - `min` – (default: `None`)

    - `max` – (default: `None`)

    This returns the definite integral if xmin is not `None`, otherwise an indefinite integral.

    EXAMPLES:

    Sage

        sage: y=giac('y');f=(sin(2*y)/y).integral(y).simplify(); f
        Si(2*y)
        sage: f.diff(y).simplify()
        sin(2*y)/y

    Python

        >>> from sage.all import *
        >>> y=giac('y');f=(sin(Integer(2)*y)/y).integral(y).simplify(); f
        Si(2*y)
        >>> f.diff(y).simplify()
        sin(2*y)/y

    Sage

        sage: f = giac('exp(x^2)').integral('x',0,1) ; f
        1.46265174...
        sage: x,y=giac('x'),giac('y');integrate(cos(x+y),'x=0..pi').simplify()
        -2*sin(y)

    [Python]

        >>> from sage.all import *
        >>> f = giac('exp(x^2)').integral('x',Integer(0),Integer(1)) ; f
        1.46265174...
        >>> x,y=giac('x'),giac('y');integrate(cos(x+y),'x=0..pi').simplify()
        -2*sin(y)

  integrate(var='x', min=None, max=None)

    alias of `integral()`.

  sum(var, min=None, max=None)

    Return the sum of `self` with respect to the variable \(x\).

    INPUT:

    - `var` – variable

    - `min` – (default: `None`)

    - `max` – (default: `None`)

    This returns the definite integral if xmin is not `None`, otherwise an indefinite integral.

    EXAMPLES:

    Sage

        sage: giac('1/(1+k^2)').sum('k',-oo,+infinity).simplify()
        (pi*exp(pi)^2+pi)/(exp(pi)^2-1)

    Python

        >>> from sage.all import *
        >>> giac('1/(1+k^2)').sum('k',-oo,+infinity).simplify()
        (pi*exp(pi)^2+pi)/(exp(pi)^2-1)

  unapply(var)

    Create a Giac function in the given arguments from a Giac symbol.

    EXAMPLES:

    Sage

        sage: f=giac('y^3+1+t')
        sage: g=(f.unapply('y,t'))
        sage: g
        (y,t)->y^3+1+t
        sage: g(1,2)
        4

    Python

        >>> from sage.all import *
        >>> f=giac('y^3+1+t')
        >>> g=(f.unapply('y,t'))
        >>> g
        (y,t)->y^3+1+t
        >>> g(Integer(1),Integer(2))
        4

class sage.interfaces.giac.GiacFunction(parent, name)

  Bases: `ExpectFunction`

class sage.interfaces.giac.GiacFunctionElement(obj, name)

  Bases: `FunctionElement`

sage.interfaces.giac.giac_console()

  Spawn a new Giac command-line session.

  EXAMPLES:

  Sage

      sage: giac.console()  # not tested - giac
      ...
      Homepage http://www-fourier.ujf-grenoble.fr/~parisse/giac.html
      Released under the GPL license 3.0 or above
      See http://www.gnu.org for license details
      -------------------------------------------------
      Press CTRL and D simultaneously to finish session
      Type ?commandname for help

  Python

      >>> from sage.all import *
      >>> giac.console()  # not tested - giac
      ...
      Homepage http://www-fourier.ujf-grenoble.fr/~parisse/giac.html
      Released under the GPL license 3.0 or above
      See http://www.gnu.org for license details
      -------------------------------------------------
      Press CTRL and D simultaneously to finish session
      Type ?commandname for help

sage.interfaces.giac.reduce_load_Giac()

  Return the giac object created in sage.interfaces.giac.

  EXAMPLES:

  Sage

      sage: from sage.interfaces.giac import reduce_load_Giac
      sage: reduce_load_Giac()
      Giac

  Python

      >>> from sage.all import *
      >>> from sage.interfaces.giac import reduce_load_Giac
      >>> reduce_load_Giac()
      Giac