This notebook is licenced under CC BY-SA 4.0.

# FriCAS Tutorial (Laurent Polynomial)¶

## Ralf Hemmecke <ralf@hemmecke.org>¶

Sources at Github.

In [1]:
)set message type off
)set output algebra off
setFormat!(FormatMathJax)$JFriCASSupport )set message type on  In [2]: )version  Value = "FriCAS a9422d32eb6f6b03d98ac6adfc9bf05ec0f5e8bd compiled at Sa 03 Apr 2021 00:29:13 CEST"  ## Builtin LaurentPolynomial constructor¶ There is a builtin constructor for univariate (not multivariate) Laurent polynomials. See also the fricas-devel mailing list for a discussion of its problems. Below we construct univariate Laurent polynomials (in x) over$\mathbb{Q}$. In [8]: Z ==> Integer Q ==> Fraction Z P ==> UnivariatePolynomial('x, Q) R ==> Fraction P L ==> LaurentPolynomial(Q, P) px := x :: P lx := x :: L  Out[8]: Out[8]: Out[8]: Out[8]: Out[8]: Out[8]: $x$ Out[8]: $x$ Unfortunately, since exponentiation with a negative power is not implemented (in general the result is not a Laurent polynomial), we cannot simply enter a Laurent polynomial like this. In [9]: l := lx^(-3)+5*lx^(-1)+7+lx^2  Out[9]: $\frac{{x}^{6}+7\, {x}^{4}+5\, {x}^{3}+x}{{x}^{4}}$ There is, however, an operation that can create a negative power of the variable. In fact, there are two. In [11]: ix := divide(1,lx).quotient ix := monomial(1, -1)$L

Out[11]:
${x}^{-1}$
Out[11]:
${x}^{-1}$

We can enter the above polynomial like this.

In [13]:
m(x,y) ==> monomial(x, y)$L l := m(1,-3) + m(5,-1) + 7 + m(1,2)  Out[13]: Out[13]: ${x}^{2}+7+5\, {x}^{-1}+{x}^{-3}$ On can also create Laurent polynomials by the following function. In [14]: separate((11+px+px^10)/(px^3*(1-px)))$L

Out[14]:
$\left[polyPart=-{x}^{6}-{x}^{5}-{x}^{4}-{x}^{3}-{x}^{2}-x-1+12\, {x}^{-1}+12\, {x}^{-2}+11\, {x}^{-3}, fracPart=-\frac{13}{x-1}\right]$

The above $l$ might then be written as follows.

In [15]:
l := (separate((1+5*px^2+7*px^3+px^5)/px^3)$L).polyPart  Out[15]: ${x}^{2}+7+5\, {x}^{-1}+{x}^{-3}$ We also want to truncate a Laurent series at a certain point and optain a Laurent polynomial. In [18]: S ==> UnivariateLaurentSeries(Q, 'x, 0) sx := x :: S s := (sx^3-7*sx)/(3*sx^7-sx^4)  Out[18]: Out[18]: $x$ Out[18]: $7\, {x}^{-3}-{x}^{-1}+21-3\, {x}^{2}+63\, {x}^{3}-9\, {x}^{5}+189\, {x}^{6}+O\left({x}^{8}\right)$ In [19]: rf := rationalFunction(s, 3)  Out[19]: $\frac{63\, {x}^{6}-3\, {x}^{5}+21\, {x}^{3}-{x}^{2}+7}{{x}^{3}}$ rationalFunction leads to a more general type than we want. Therefore, we simply try to coerce/retract it into the domain we want, i.e., a quotient field of univariate polynomials. In [20]: pf := rf :: R  Out[20]: $\frac{63\, {x}^{6}-3\, {x}^{5}+21\, {x}^{3}-{x}^{2}+7}{{x}^{3}}$ In [21]: (separate(pf)$L).polyPart

Out[21]:
$63\, {x}^{3}-3\, {x}^{2}+21-{x}^{-1}+7\, {x}^{-3}$

Putting the above into a macro, we can make truncation a little simpler.

In [23]:
TRUNC(s, n) ==> (separate(rationalFunction(s, n)::R)$L).polyPart TRUNC(s, 3)  Out[23]: Out[23]: $63\, {x}^{3}-3\, {x}^{2}+21-{x}^{-1}+7\, {x}^{-3}$ ## Univariate case¶ For (internal) computation, one can also be more direct and create a monoid ring with the monoid being the integers and the coefficients being the rational numbers. Clearly, also this is a representation of a Laurent polynomial ring. In [24]: QZ ==> PolynomialRing(Q, Z)  Out[24]: Unfortunately, entering an element of this domain is a bit tricky and also the output does not look as one would expect from a Laurent polynomial. Our example polynomial from above would look like this. In [28]: qx := monomial(1, 1)$QZ
iqx := monomial(1, -1)$QZ l := iqx^3 + 5*iqx + 7 + qx^2 l^2  Out[28]: $1$ Out[28]: $-1$ Out[28]: $2+7\, 0+5\, \left(-1\right)-3$ Out[28]: $4+14\, 2+49\, 0+35\, \left(-1\right)+7\, \left(-3\right)$ That is certainly hard to interpret, but one can easily add a new domain that behaves like integers, but prints in a multiplicative form. In the following we escape to the shell to create a file with the contents shown below. This will only work in a jFriCAS (i.e., the Jupyter notebook frontend for FriCAS). If you are working with another frontend, then simply create a file /tmp/xint.spad with the contents given between the lines "cat <<'EOF' > /tmp/xint.spad" and "EOF". In [16]: )! cat <<'EOF' > /tmp/xint.spad )abbrev domain XINT XInteger XInteger(sy: Symbol): IntegerNumberSystem == Integer add coerce(x: %): OutputForm == o := sy :: OutputForm one? x => o i: Integer := x pretend Integer x >= 0 => o^(i::OutputForm) o^paren(i::OutputForm) EOF  Now we compile that file. Since FriCAS resets certain variables during compilation, we must reset the output format to MathJax. In [30]: )compile /tmp/xint.spad setFormat!(FormatMathJax)$JFriCASSupport

Compiling FriCAS source code from file /tmp/xint.spad using old system
compiler.
XINT abbreviates domain XInteger
------------------------------------------------------------------------
initializing NRLIB XINT for XInteger
compiling into NRLIB XINT
Adding $modemaps Adding (OutputForm) modemaps compiling exported coerce :$ -> OutputForm
Time: 0.02 SEC.
(time taken in buildFunctor:  2363)
;;;     ***       |XInteger| REDEFINED
;;;     ***       |XInteger| REDEFINED
Time: 0.01 SEC.
Cumulative Statistics for Constructor XInteger
Time: 0.03 seconds
--------------non extending category----------------------
.. XInteger(#1) of cat
(|IntegerNumberSystem|)   has no
(|LinearlyExplicitOver| (|Integer|))    finalizing NRLIB XINT
Processing XInteger for Browser database:
--->-->XInteger(): Missing Description
; compiling file "/home/hemmecke/backup/git/fricas-notebooks/tmp/XINT.NRLIB/XINT.lsp" (written 03 APR 2021 01:13:45 AM):
; wrote /home/hemmecke/backup/git/fricas-notebooks/tmp/XINT.NRLIB/XINT.fasl
; compilation finished in 0:00:00.024
------------------------------------------------------------------------
XInteger is now explicitly exposed in frame initial
XInteger will be automatically loaded when needed from
/home/hemmecke/backup/git/fricas-notebooks/tmp/XINT.NRLIB/XINT

Out[30]:

Using XInteger instead of Integer, the output looks more pleasing.

In [35]:
QZ ==> PolynomialRing(Q, XInteger("x"::Symbol))
qx := monomial(1, 1)$QZ iqx := monomial(1, -1)$QZ
l := iqx^3 + 5*iqx + 7 + qx^2
l^2

Out[35]:
Out[35]:
$x$
Out[35]:
${x}^{\left(-1\right)}$
Out[35]:
${x}^{2}+7\, {x}^{0}+5\, {x}^{\left(-1\right)}+{x}^{\left(-3\right)}$
Out[35]:
${x}^{4}+14\, {x}^{2}+49\, {x}^{0}+35\, {x}^{\left(-1\right)}+7\, {x}^{\left(-3\right)}$

Truncation of the above Laurent series at degree 3 goes as follows.

In [36]:
tr(s: S, n: Z): QZ ==
qz: QZ := 0
while (e := order(s, n+1)) <= n repeat
qz := qz + monomial(leadingCoefficient s, e)$QZ s := reductum s qz  Function declaration tr : (UnivariateLaurentSeries(Fraction(Integer),x,0), Integer) -> PolynomialRing(Fraction(Integer),XInteger(x)) has been added to workspace.  Out[36]: In [37]: tr(s,3)  Compiling function tr with type (UnivariateLaurentSeries(Fraction(Integer),x, 0), Integer) -> PolynomialRing(Fraction(Integer),XInteger(x))  Out[37]: $63\, {x}^{3}-3\, {x}^{2}+21\, {x}^{0}-{x}^{\left(-1\right)}+7\, {x}^{\left(-3\right)}$ Or construct the Laurent polynomial like this. Note that we must use the complete function to expand the (finite) stream such that it is recognized as finite by the entries function. In [39]: mons := [monomial(r.c,r.k)$QZ for r in terms s while r.k < 4];
reduce(+, entries complete mons)

Out[39]:
Out[39]:
$63\, {x}^{3}-3\, {x}^{2}+21\, {x}^{0}-{x}^{\left(-1\right)}+7\, {x}^{\left(-3\right)}$