SDPSL
Semidefinite Programming Specification Library
|
The syntax for adding polynomial constraints if very similar to that for adding linear constraints. Here we give an overview of how polynomial constraints are dealt with by SDPSL.
Before discussing polynomial constraints, let us briefly discuss how polynomials can be created and manipulated.
Recall that we actually use Laurent polynomials, that is, polynomials in which variables can assume positive as well as negative powers. In SDPSL, Laurent polynomials are instances of class Polynomial
. The coefficients are instances of Number
, and therefore are either double-precision floating-points, or istances of mpf_class
, depending on whether the double-precision version or the GMP version of the library is used.
Polynomials can be either univariate or multivariate. They are basically maps associating monomials (instances of class Monomial
) with coefficients. Many operations are defined for polynomials, such as addition and multiplication.
To create polynomials, first variables have to be defined. Variables have names, but these need not be unique, since they are uniquely identified by indices.
Since polynomials can be constructed from variables, variables can be multiplied and added together in order to construct polynomials. Monomials, on the other hand, have to be explicitly constructed from variables. This is made so as to avoid ambiguity when variables are multiplied together, for instance.
Iteration over polynomials is carried out over pairs of monomials and coefficients, that is, over structures std::pair<Monomial, Number>
.
The following code illustrates the basics of polynomial creation and iteration.
PolynomialVariable
, Monomial
, and Polynomial
.Adding polynomial constraints is an operation very similar to adding linear constraints, except that we might have to specify a basis used to represent the polynomial constraint as linear constraints (cf. Polynomial constraints).
The left-hand side of a polynomial constraint is an expression like
\[ \sum_{j=1}^r \langle A_j, X_j \rangle \]
where the \(A_j\) are matrices whose entries are Laurent polynomials and the \(X_j\) are the variables of the problem.
Such expressions are represented in SDPSL by instances of SDPPolynomialCombination
, which is basically a map associating matrices of polynomials (instances of Matrix<Polynomial>
) to variables of the problem.
Polynomial combinations work very similarly to linear combinations and can be specified using a similar syntax. Masks can also be specified for each matrix of polynomials using SDPMaskedPolyMatrix
.
A polynomial constraint is represented by an instance of SDPPolynomialConstraint
. Such instances contain the left-hand side of the constraint, which is an instance of SDPPolynomialCombination
, and the right-hand side, which is a polynomial. Instances of SDPPolynomialConstraint
can be created from instances of SDPPolynomialCombination
and Polynomial
using the operator ==
.
We can add polynomial constraints to a constraint container without having to specify a basis for the constraints representation. In this case, the standard monomial basis is used, that is, the basis consisting of all monomials occurring on the left-hand side and on the right-hand side is used.
As an example of the use of polynomial constraints, consider the problem of fiding the global minimum of a univariate polynomial. The global minimum of a univariate polynomial \(p\) equals
\[ \max \{\, \lambda : \text{$p - \lambda$ is nonnegative}\,\} = \max \{\, \lambda : \text{$p - \lambda$ is a sum-of-squares}\,\}. \]
The problem of finding the maximum above can be formulated as an SDPSL semidefinite program in a standard way. Say \(p\) has degree \(2d\) and consider the vector \(v(x) = (1, x, x^2, \ldots, x^d)\) of monomials. Then \(v(x) v(x)^{\sf T}\) is a moment matrix and the maximum above is equal to the optimal value of the problem
\[ \begin{array}{rl} {\rm maximize}&s - t\\ &\langle v(x) v(x)^{\sf T}, X\rangle + s - t = p,\\ &\text{$X$ is positive semidefinite, $s$, $t \geq 0$.} \end{array} \]
Here, we have three variables, \(X\), \(s\), and \(t\). We see \(s\) and \(t\) as 1-by-1 matrix variables (we use this trick to represent the free variable \(\lambda\) as the difference \(s-t\) of nonnegative numbers).
The program below uses SDPSL to output the above SDP in sparse SDPA format.
Other bases can be specified when a polynomial constraint is added to a constraint container. This can have a great effect on the numerical stability of the resulting semidefinite programming problem.
Different bases are specified using classes that implement the interface of SparseBasisCoefficients
. An instance of such a class must implement two functions:
basis_size:
a function that returns the size of the basis in question;basis_coefficients:
a function that takes a polynomial p
, a reference to a vector of numbers (either doubles or instances of mpf_class
), and a reference to a VectorMask
, and puts in the vector of numbers the expansion of the polynomial on the basis, putting in the mask the nonzero positions of the expansion. Function basis_coefficients
returns true
if it could successfully compute the expansion, and false
otherwise. When it returns false
, an exception is thrown by the constraint container.In the previous example, we did not specify the monomial basis explicitly; it was deduced from the polynomials given. What really happens behind the scenes is that an instance of class SparseMonomialBasis
is then used. This class is derived from SparseBasisCoefficients
and implements a basis of monomials.
Such bases can also be explicitly specified. For instance, lines 72-73 of the code above could be equivalently changed to the following:
In some applications, for efficiency reasons, it is useful to implement a specific class derived from SparseBasisCoefficients
to deal with polynomial constraints. In general, however, one may use SparseBasisChanger
.
This class takes a monomial basis and a basis of polynomials spanning the same subspace and computes a basis change matrix between the two bases. Later, it expands polynomials given to it in the polynomial basis specified.
As an example, suppose that instead of using the standard monomial basis in the previous example, we want to use a basis of Laguerre polynomials. This can be done by substituting lines 69-73 by the following code:
Function compute_laguerre_polys
computes all Laguerre polynomials of degree 0
upto deg
and parameter 0
, and puts them in the vector laguerre_basis
. The call SparseMonomialBasis(C)
creates a monomial basis taking all monomials occurring in the polynomials that appear in the constraint C
. Finally, when we add the constraint C
, we specify the basis changer sc
.