Getting Started
Documentation under construction
Creating polynomials¶
In PolyAny a polynomial can be created in many forms. The most flexible way is defining a matrix of exponents
and a vector of coefficients
.
From exponents and coefficients¶
The exponents
matrix contains the exponents of each monomial of the polynomial, and the coefficients
vector contains the corresponding scalars multipliers.
Basic example
Consider the monomial \(M(\mathbf{x}) = 5\,x_1^2\,x_2\,x_3^4\,x_5\), its exponents and coefficient are given by:
- When declaring the exponents matrix, variables are ordered increasingly, i.e., \([x_1,\,x_2,\,x_3,\,\dots,\,x_n]\).
Note that the exponent matrix represents the complete monomial, meaning that it must include all variables, even those raised to the power of \(0\).
Example
If we want to represent a polynomial, we declare the exponents and coefficients of each monomial. Consider:
The monomials of \(P(\mathbf{x})\) are:
- \(M_1(\mathbf{x}) = 3\,x_1\,x_2\)
- \(M_2(\mathbf{x}) = 4\,x_4^4\,x_5^3\)
- \(M_3(\mathbf{x}) = 5\,x_1^2\,x_2\,x_3^4\,x_5\)
To represent \(P(\mathbf{x})\), we define:
It is very important that the coefficients appear in the same order as their corresponding rows in the exponents matrix.
To create a polynomial from an exponents matrix and a coefficients vector in PolyAny, use the following syntax:
from polyany import Polynomial
exponents = [[0, 0, 0], [1, 0, 0], [0, 1, 0]] #(1)!
coefficients = [1, 2, 3] #(2)!
poly = Polynomial(exponents, coefficients)
- The exponents matrix can also be a nested tuples or a NumPy 2D array
- The coefficients vector can also be a tuple or a NumPy 1D array
The code above creates the following multivariate polynomial:
Univariate Polynomials¶
Univariate Polynomials
A univariate polynomial \(P(x_1)\) is a polynomial that depends on a single variable \(x_1\). An example of univariate polynomial is:
To create univariate polynomials, a simpler syntax can be used, it only requires a coefficients
vector.
from polyany import Polynomial
coefficients = [1, 5, 8, 9]
univar_poly = Polynomial.univariate(coefficients)
The coefficients are related with power of the variable \(x_1\) in increasing degree. The code above creates the polynomial:
Quadratic forms¶
Quadratic forms
A quadratic form is a second-degree homogeneous multivariate polynomial. It can be represented using a symmetric matrix \(A \in \mathbb{R}^{n \times n}\) as:
For further reading, see Linear Algebra Done Right by Sheldon Axler
To create a quadratic form a square matrix must be provided.
from polyany import Polynomial
matrix = [[1, 2], [2, 3]] #(1)!
quadratic_form_poly = Polynomial.quadratic_form(matrix)
- The input matrix can also be nested tuples or a NumPy 2D array
The code above creates the polynomial:
Non-symmetric matrices
If the input matrix \(A\) is not symmetric, a warning is raised and it's symmetric part \(A_{\mathrm{sym}}\) is used instead, where
Example
Suppose the input matrix is:
Its symmetric part is:
which corresponds to the polynomial:
Evaluating polynomials¶
Polynomials can be easily evaluated in PolyAny by treating the polynomial object as a callable function.
The input argument (point
) must be a vector with n_vars
components.
- Even for univariate polynomials,
point
needs to be a list, tuple or NumPy 1D-array.
For multivariate polynomials:
>>> matrix = [[1, 2, 3],
... [2, 4, 5],
... [3, 5, 6]]
>>> poly = Polynomial.quadratic_form(matrix)
>>> poly([0, 0, 0])
np.float64(0.0)
>>> poly([1, 1, 1])
np.float64(31.0)
Comparing polynomials¶
In PolyAny, Polynomial objects support equality comparisons (==
) with other polynomials, but do not support ordering comparisons (<
, <=
, >
, >=
), which raises a TypeError
.
Two polynomials are considered equal if and only if they have:
- The same number of variables (
n_vars
attribute) - The same total degree (
degree
attribute) - The same coefficients (
coefficients
attribute)1
Comparison with other types (sequences, scalars, NumPy arrays) always returns NotImplemented
.
Example
Internally, the polynomial object stores the coefficients and exponents in an ordered way, meaning that a polynomial is created regardless of the order of the input coefficients and exponents.
Pruning¶
Pruning is the process of removing empty monomials of a polynomial. The
Polynomial
object stores the exponents and coefficients
provided by the user in a ordered way.
>>> poly = Polynomial([[0, 0], [0, 1], [1, 0], [1, 1]], [1, 0, 2, 0])
>>> poly.exponents
array([[0, 0],
[1, 0],
[0, 1],
[1, 1]])
>>> poly.coefficients
array([1., 2., 0., 0.])
When a polynomial is pruned, all empty monomials are removed, that is, the entries in
exponents
whose associated coefficients are exactly zero, which have no effect
on the polynomial behavior.
To prune a polynomial, use the prune
method:
>>> pruned = poly.prune()
>>> pruned.exponents
array([[0, 0],
[1, 0]])
>>> pruned.coefficients
array([1., 2.])
The pruned polynomial retains only the first and second term, which are the non-empty monomials.
Addition and subtraction¶
In PolyAny, Polynomial objects can be added or subtracted with scalars2 and other polynomials.
>>> poly = Polynomial.univariate([1, -2, 3])
>>> poly
1 - 2*x_1 + 3*x_1^2
>>> poly + 5
6 - 2*x_1 + 3*x_1^2
>>> poly - 1
-2*x_1 + 3*x_1^2
For addition/subtraction between polynomials:
>>> another_poly = Polynomial([[0, 0], [1, 0], [0, 1], [1, 1]], [1, -2, 3, -4])
>>> another_poly
1 - 2*x_1 + 3*x_2 - 4*x_1*x_2
>>> poly + another_poly
2 - 4*x_1 + 3*x_2 + 3*x_1^2 - 4*x_1*x_2
>>> poly - another_poly
-3*x_2 + 3*x_1^2 + 4*x_1*x_2
-
A comparison is made by using
np.allclose()
, which checks if two arrays are equal within a tolerance. ↩ -
Python builtins numeric types (
int
,float
) and NumPy scalars. SeeScalar
↩