symtegration-0.4.0: Library for symbolic integration of mathematical expressions.
CopyrightCopyright 2024 Yoo Chung
LicenseApache-2.0
Maintainerdev@chungyc.org
Safe HaskellNone
LanguageGHC2021

Symtegration.Polynomial

Description

This modules defines a type class that concrete types representing polynomials should be an instance of. It includes important algorithms operating on polynomials. In particular, algorithms for polynomial division and the extended Euclidean algorithm are included.

Synopsis

Polynomials

class (Integral e, Num c) => Polynomial (p :: Type -> Type -> Type) e c where Source #

Polynomials must support the operations specified in this type class. All powers must be non-negative.

Methods

degree :: p e c -> e Source #

Returns the degree of a given polynomial.

The following returns 9 for the highest term in \(3x^9 + 2x^4 + x\):

>>> degree (3 * power 9 + 2 * power 4 + power 1 :: IndexedPolynomial)
9

coefficient :: p e c -> e -> c Source #

Returns the coefficient for the term with the given power.

The following returns 4 from the \(4x^3\) term in \(x^4 + 4x^3 + 3\):

>>> coefficient (power 4 + 4 * power 3 + 3 :: IndexedPolynomial) 3
4 % 1

leadingCoefficient :: p e c -> c Source #

Returns the leading coefficient.

The following returns 6 from the \(6x^3\) term in \(6x^3 + 2x^2\):

>>> leadingCoefficient (6 * power 3 + 2 * power 2 :: IndexedPolynomial)
6 % 1

The leading coefficient is never zero unless the polynomial itself is zero.

deleteLeadingTerm :: p e c -> p e c Source #

Returns the polynomial without the leading term.

>>> deleteLeadingTerm (2 * power 3 + power 1 + 2 :: IndexedPolynomial)
x + 2

foldTerms :: Monoid m => (e -> c -> m) -> p e c -> m Source #

Fold the terms, i.e., the powers and coefficients, using the given monoid. Only terms with non-zero coefficients will be folded. Folding is ordered from lower to higher terms.

For example with \(3x^5 - 2x + 7\),

>>> foldTerms (\e c -> show (e, c)) (3 * power 5 - 2 * power 1 + 7 :: IndexedPolynomial)
"(0,7 % 1)(1,(-2) % 1)(5,3 % 1)"

scale :: c -> p e c -> p e c Source #

Multiplies a polynomial by a scalar.

The following divides \(6x + 2\) by 2:

>>> scale (1 % 2) (6 * power 1 + 2 :: IndexedPolynomial)
3x + 1

power :: e -> p e c Source #

Returns a single term with the variable raised to the given power.

The following is equivalent to \(x^5\):

>>> power 5 :: IndexedPolynomial
x^5

monic :: (Polynomial p e c, Eq c, Fractional c) => p e c -> p e c Source #

Scale the polynomial so that its leading coefficient is one.

>>> monic $ 4 * power 2 + 4 * power 1 + 4 :: IndexedPolynomial
x^2 + x + 1

The exception is when the polynomial is zero.

>>> monic 0 :: IndexedPolynomial
0

mapCoefficients :: (Polynomial p e c, Polynomial p e c', Num (p e c), Num (p e c')) => (c -> c') -> p e c -> p e c' Source #

Maps the coefficients in a polynomial to form another polynomial.

For example, it can be used to convert a polynomial with Rational coefficients into a polynomial with Expression coefficients.

>>> let p = 2 * power 1 + 1 :: IndexedPolynomial
>>> let q = mapCoefficients fromRational p :: IndexedSymbolicPolynomial
>>> simplify $ coefficient q 1
Number 2

Algorithms

divide Source #

Arguments

:: (Polynomial p e c, Eq (p e c), Num (p e c), Fractional c) 
=> p e c

Dividend polynomial being divided.

-> p e c

Divisor polynomial dividing the dividend.

-> (p e c, p e c)

Quotient and remainder.

Polynomial division. It returns the quotient polynomial and the remainder polynomial.

For example, dividing \(p = x^3-12x^2-42\) by \(q = x^2 - 2x + 1\) returns \(x-10\) as the quotient and \(-21x-32\) as the remainder, since \(p = (x-10)q -21x - 32\):

>>> let p = power 3 - 12 * power 2 - 42 :: IndexedPolynomial
>>> let q = power 2 - 2 * power 1 + 1 :: IndexedPolynomial
>>> divide p q
(x + (-10),(-21)x + (-32))

pseudoDivide Source #

Arguments

:: (Polynomial p e c, Eq (p e c), Num (p e c), Num c) 
=> p e c

Dividend polynomial being pseudo-divided.

-> p e c

Divisor polynomial pseudo-dividing the dividend.

-> (p e c, p e c)

Pseudo-quotient and pseudo-remainder.

Polynomial pseudo-division. It returns the pseudo-quotient and pseudo-remainder polynomials.

Equivalent to \(b^{\delta+1} p\) divided by \(q\), where \(p\) and \(q\) are polynomials with integer coefficients, \(b\) is the leading coefficient of \(q\) and \(\delta=\max(-1, \deg(p) - \deg(q))\). This guarantees the pseudo-quotient and pseudo-remainder exist, even when the quotient and remainder do not when only integer coefficients are allowed.

For example, with \(p = 3x^3 + x^2 + x + 5\) and \(q = 5x^2 - 3x + 1\), it is the case that \(5^2p = (15x + 14)q + (52x + 111)\):

>>> let p = 3 * power 3 + power 2 + power 1 + 5 :: IndexedPolynomial
>>> let q = 5 * power 2 - 3 * power 1 + 1 :: IndexedPolynomial
>>> pseudoDivide p q
(15x + 14,52x + 111)

extendedEuclidean Source #

Arguments

:: (Polynomial p e c, Eq (p e c), Num (p e c), Fractional c) 
=> p e c

Polynomial \(p\).

-> p e c

Polynomial \(q\).

-> (p e c, p e c, p e c)

\(s\), \(t\), and \(\gcd(p,q)\).

The extended Euclidean algorithm. For polynomials \(p\) and \(q\), it returns the greatest common divisor between \(p\) and \(q\). It also returns \(s\) and \(t\) such that \(sp+tq = \gcd(p,q)\).

For example, for \(p=2x^5-2x\) and \(q=x^4-2x^2+1\), it is the case that \(\gcd(p,q)=-x^2+1\) and \((-\frac{1}{4}x) p + (\frac{1}{2}x^2 + 1) q = -x^2+1\):

>>> let p = 2 * power 5 - 2 * power 1 :: IndexedPolynomial
>>> let q = power 4 - 2 * power 2 + 1 :: IndexedPolynomial
>>> extendedEuclidean p q
(((-1) % 4)x,(1 % 2)x^2 + 1,(-1)x^2 + 1)

diophantineEuclidean Source #

Arguments

:: (Polynomial p e c, Eq (p e c), Num (p e c), Fractional c) 
=> p e c

Polynomial \(a\).

-> p e c

Polynomial \(b\).

-> p e c

Polynomial \(c\).

-> Maybe (p e c, p e c)

\((s,t)\) such that \(sa + tb = c\).

Solves \(sa + tb = c\) for given polynomials \(a\), \(b\), and \(c\). It will be the case that either \(s=0\) or the degree of \(s\) will be less than the degree of \(b\).

>>> let a = power 4 - 2 * power 3 - 6 * power 2 + 12 * power 1 + 15 :: IndexedPolynomial
>>> let b = power 3 + power 2 - 4 * power 1 - 4 :: IndexedPolynomial
>>> let c = power 2 - 1 :: IndexedPolynomial
>>> diophantineEuclidean a b c
Just (((-1) % 5)x^2 + (4 % 5)x + ((-3) % 5),(1 % 5)x^3 + ((-7) % 5)x^2 + (16 % 5)x + (-2))

If there is no such \((s,t)\), then Nothing is returned.

greatestCommonDivisor Source #

Arguments

:: (Polynomial p e c, Eq (p e c), Num (p e c), Fractional c) 
=> p e c

Polynomial \(p\).

-> p e c

Polynomial \(q\).

-> p e c

\(\gcd(p,q)\).

Returns the greatest common divisor btween two polynomials.

Convenient wrapper over extendedEuclidean which only returns the greatest common divisor.

subresultant Source #

Arguments

:: (Polynomial p e c, Eq (p e c), Num (p e c), Num e, Fractional c) 
=> p e c

First element in the remainder sequence.

-> p e c

Second element in the remainder sequence.

-> (c, [p e c])

The resultant and the subresultant polynomial remainder sequence.

Returns the resultant and the subresultant polynomial remainder sequence for the given polynomials.

>>> subresultant (power 2 + 1) (power 2 - 1 :: IndexedPolynomial)
(4 % 1,[x^2 + 1,x^2 + (-1),(-2),0])
>>> subresultant (2 * power 2 - 3 * power 1 + 1) (5 * power 2 + power 1 - 6 :: IndexedPolynomial)
(0 % 1,[2x^2 + (-3)x + 1,5x^2 + x + (-6),17x + (-17),0])
>>> subresultant (power 3 + 2 * power 2 + 3 * power 1 + 4) (5 * power 2 + 6 * power 1 + 7 :: IndexedPolynomial)
(832 % 1,[x^3 + 2x^2 + 3x + 4,5x^2 + 6x + 7,16x + 72,832,0])

Reference

Expand

See sections 1.4 and 1.5 in Symbolic Integration I: Transcendental Functions by Manuel Bronstein for the definition of resultants, subresultants, polynomial remainder sequences, and subresultant polynomial remainder sequences.

differentiate :: (Polynomial p e c, Num (p e c), Num c) => p e c -> p e c Source #

Returns the derivative of the given polynomial.

>>> differentiate (power 2 + power 1 :: IndexedPolynomial)
2x + 1

integrate :: (Polynomial p e c, Num (p e c), Fractional c) => p e c -> p e c Source #

Returns the integral of the given polynomial.

>>> integrate (power 2 + power 1 :: IndexedPolynomial)
(1 % 3)x^3 + (1 % 2)x^2

squarefree :: (Polynomial p e c, Eq (p e c), Num (p e c), Eq c, Fractional c) => p e c -> [p e c] Source #

Returns the squarefree factorization of the given polynomial.

Specifically, for a polynomial \(p\), find \([p_1, p_2, \ldots, p_n]\) such that

\[ p = \sum_{k=1}^n p_k^k \]

where all \(p_k\) are squarefree, i.e., there is no polynomial \(q\) such that \(q^2 = p_k\).

For example, the squarefree factorization of \(x^8 + 6x^6 + 12x^4 + 8x^2\) is \(x^2 (x^2 + 2)^3\):

>>> squarefree (power 8 + 6 * power 6 + 12 * power 4 + 8 * power 2 :: IndexedPolynomial)
[1,x,x^2 + 2]