Signomials¶
A signomial is a linear combination of exponentials, composed with linear functions. Signomials look like the following:
Signomial objects covers sageopt’s Signomial class, plus two extra helper functions. The section on conditioning covers the basics of a powerful connection between signomials and convexity. Sageopt has convenience functions for constructing and working with convex relaxations of signomial minimization problems (both constrained, and unconstrained). Those convenience functions are described in the section on optimization. We also address some advanced topics.
Signomial objects¶
This section covers how to construct and use instances of the sageopt.Signomial class.
-
class
sageopt.Signomial(alpha, c)¶ A concrete representation for a function of the form \(x \mapsto \sum_{i=1}^m c_i \exp(\alpha_i \cdot x)\).
Operator overloading.
The operators
+,-, and*are defined between pairs of Signomials, and pairs{s, t}wheresis a Signomial andtis “scalar-like.” Specific examples of “scalar-like” objects include numeric types, and coniclifts Expressions of size one.A Signomial
scan be raised to a numeric powerpby writings**p; ifs.ccontains more than one nonzero entry, it can only be raised to nonnegative integer powers.The Signomial class implements
s1 / s2wheres2is a numeric type or Signomial; ifs2is a Signomial, then its coefficient vectors2.ccan only contain one nonzero entry.Function evaluations.
Signomial objects are callable. If
sis a Signomial object andxis a numpy array of lengths.n, thens(x)computes the Signomial object as though it were any other elementary Python function.Signomial objects provide functions to compute gradients (equivalently, Jacobians) and Hessians. These methods operate by caching and evaluating symbolic representations of partial derivatives.
- Parameters
alpha (ndarray) – The rows of
alphacomprise this Signomial’s exponent vectors.c (None or ndarray) – An ndarray of coefficients, with one coefficient for each row in alpha.
Examples
There are three ways to make Signomial objects. The first way is to call the constructor:
alpha = np.array([[1, 0], [0, 1], [1, 1]]) c = np.array([1, 2, 3]) f = Signomial(alpha, c) x = np.random.randn(2) print(f(x) - c @ np.exp(alpha @ x)) # zero, up to rounding errors.
You can also use
Signomial.from_dictwhich maps exponent vectors (represented as tuples) to scalars:alpha_and_c = {(1,): 2} f = Signomial.from_dict(alpha_and_c) print(f(1)) # equal to 2 * np.exp(1), print(f(0)) # equal to 2.
The final way to construct a Signomial is with algebraic syntax, like:
y = sageopt.standard_sig_monomials(2) # y[i] represents exp(x[i]) f = (y[0] - y[1]) ** 3 + 1 / y[0] # a Signomial in two variables x = np.array([1, 1]) print(f(x)) # np.exp(-1), up rounding errors.
Signomial objects are not limited to numeric problem data for
alphaandc. In fact, it’s very common to haveccontain a coniclifts Expression. For example, if we started with a Signomialfand then updatedgamma = sageopt.coniclifts.Variable() f = f - gamma
then
f.cwould be a coniclifts Expression depending on the variablegamma.Notes
Signomial objects have a dictionary attribute called
metadata. You can store any information you’d like in this dictionary. However, the information in this dictionary will not automatically be propogated when creating new Signomial objects (as happens when performing arithmetic on Signomials).-
property
n¶ The dimension of the space over which this Signomial is defined; this Signomial accepts inputs in \(\mathbb{R}^{n}\).
-
property
m¶ The number of monomial basis functions \(x \mapsto \exp(a \cdot x)\) used by this Signomial.
-
property
alpha¶ Has shape
(m, n). Each row specifies a vector appearing in an exponential function which defines this Signomial. The rows are ordered for consistency with the propertyc.
-
property
c¶ Has shape
(m,). The scalarc[i]is this Signomial’s coefficient on the basis functionlambda x: exp(alpha[i, :] @ x). It’s possible to havec.dtype == object.
-
property
alpha_c¶ The keys of
alpha_care tuples of lengthn, containing real numeric types (e.g int, float). These tuples define linear functions. This Signomial could be evaluated by the code snippetlambda x: np.sum([ alpha_c[a] * np.exp(a @ x) for a in alpha_c]).
-
property
grad¶ A numpy ndarray of shape
(n,)whose entries are Signomials. For a numpy ndarrayx,grad[i](x)is the partial derivative of this Signomial with respect to coordinatei, evaluated atx. This array is constructed only when necessary, and is cached upon construction.
-
property
hess¶ A numpy ndarray of shape
(n, n), whose entries are Signomials. For a numpy ndarrayx,hess[i,j](x)is the (i,j)-th partial derivative of this Signomial, evaluated atx. This array is constructed only when necessary, and is cached upon construction.
-
query_coeff(a)¶ Returns the coefficient of the basis function
lambda x: np.exp(a @ x)for this Signomial.
-
constant_location()¶ Return the index
iso thatalpha[i, :]is the zero vector.
-
without_zeros()¶ Return a Signomial which is symbolically equivalent to
self, but which doesn’t track basis functionsalpha[i,:]for whichc[i] == 0.
-
grad_val(x)¶ Return the gradient of this Signomial (as an ndarray) at the point
x.
-
hess_val(x)¶ Return the Hessian of this Signomial (as an ndarray) at the point
x.
-
as_polynomial()¶ This function is only applicable if
alphais a matrix of nonnegative integers.- Returns
f – For every vector
x, we haveself(x) == f(np.exp(x)).- Return type
-
sageopt.standard_sig_monomials(n)¶ Return
ywherey[i](x) = np.exp(x[i])for every numericxof lengthn.- Parameters
n (int) – The signomials will be defined on \(R^n\).
- Returns
y – An array of length
n, containing Signomial objects.- Return type
ndarray
Example
This function is useful for constructing signomials in an algebraic form.
y = standard_sig_monomials(3) f = (y[0] ** 1.5) * (y[2] ** -0.6) - y[1] * y[2]
Conditioning¶
Convex sets have a special place in the theory of SAGE relaxations. In particular, SAGE can incorporate convex constraints into a problem by a lossless process known as partial dualization MCW2019. You can think of partial dualization as a type of “conditioning”, in the sense of conditional probability.
We designed sageopt so users can leverage the full power of partial dualization without being experts on the subject. If you want to optimize a signomial over the set
then you just need to focus on constructing the lists of signomials gts and eqs.
Once these lists are constructed, you can call the following function to obtain
a convex set \(X \supset \Omega\) which is implied by the constraint signomials.
-
sageopt.relaxations.sage_sigs.infer_domain(f, gts, eqs, check_feas=True)¶ Identify a subset of the constraints in
gtsandeqswhich can be incorporated into conditional SAGE relaxations for signomials. Construct a SigDomain object from the inferred constraints.- Parameters
f (Signomial) – The objective in a desired SAGE relaxation. This parameter is only used to determine the dimension of the set defined by constraints in
gtsandeqs.gts (list of Signomials) – For every
g in gts, there is a desired constraint that variablesxsatisfyg(x) >= 0.eqs (list of Signomials) – For every
g in eqs, there is a desired constraint that variablesxsatisfyg(x) == 0.check_feas (bool) – Indicates whether or not to verify that the returned SigDomain is nonempty.
- Returns
X
- Return type
SigDomain or None
It is possible that the function above cannot capture a convex set of interest. This is particularly likely if the desired convex set is not naturally described by signomials. If your find yourself in this situation, refer to the advanced topics section.
Optimization¶
Here are sageopt’s convenience functions for signomial optimization:
We assume the user has already read the section on signomial Conditioning. Newcomers to sageopt might benefit from reading this section in one browser window, and keeping our page of Examples open in an adjacent window. It might also be useful to have a copy of MCW2019 at hand, since that article is referenced throughout this section.
A remark: The functions described here are reference implementations. Depending on the specifics of your problem, it may be beneficial to implement variants of these functions by directly working with sageopt’s backend: coniclifts.
Optimization with convex constraints¶
-
sageopt.sig_relaxation(f, X=None, form='dual', **kwargs)¶ Construct a coniclifts Problem instance for producing a lower bound on
\[f_X^{\star} \doteq \min\{ f(x) \,:\, x \in X \}\]where X = \(\mathbb{R}^{\texttt{f.n}}\) by default.
When
form='dual', a solution to this convex relaxation can be used to recover optimal solutions to the problem above. Refer to the Notes for keyword arguments accepted by this function.- Parameters
- Returns
prob – A coniclifts Problem which represents the SAGE relaxation, with given parameters. The relaxation can be solved by calling
prob.solve().- Return type
Notes
This function also accepts the following keyword arguments:
- ellint
The level of the reference SAGE hierarchy. Must be nonnegative.
- mod_suppNumPy ndarray
Only used when
ell > 0. Ifmod_suppis not None, then the rows of this array define the exponents of a positive definite modulating Signomialtin the reference SAGE hierarchy.
When form='primal', the problem returned by sig_relaxation can be stated in full generality without too much
trouble. We define a modulator signomial t (with the canonical choice t = Signomial(f.alpha, np.ones(f.m))),
then return problem data representing
The rationale behind this formation is simple: the minimum value of a function \(f\) over a set \(X\) is equal to the largest number \(\gamma\) where \(f - \gamma\) is nonnegative over \(X\). The SAGE constraint in the problem is a proof that \(f - \gamma\) is nonnegative over \(X\). However the SAGE constraint may be too restrictive, in that it’s possible that \(f - \gamma\) is nonnegative on \(X\), but not “X-SAGE”. Increasing \(\ell\) expands the set of functions which SAGE can prove as nonnegative, and thereby improve the quality the bound produced on \(f_X^\star\). The improved bound comes at the expense of solving a larger optimization problem. For more discussion, refer to Section 2.3 of MCW2019.
Optimization with arbitrary signomial constraints¶
The next function allows the user to specify their problem not only with convex constraints via a set “\(X\)”, but also with explicit signomial equations and inequalities. Such signomial constraints are necessary when the feasible set is nonconvex, although they can be useful in other contexts.
-
sageopt.sig_constrained_relaxation(f, gts, eqs, X=None, form='dual', **kwargs)¶ Construct a coniclifts Problem representing a SAGE relaxation for the signomial program
\[\begin{split}\begin{align*} \min\{ f(x) :~& g(x) \geq 0 \text{ for } g \in \mathtt{gts}, \\ & g(x) = 0 \text{ for } g \in \mathtt{eqs}, \\ & \text{and } x \in X \} \end{align*}\end{split}\]where X = \(R^{\texttt{f.n}}\) by default. When
form='dual', a solution to this relaxation can be used to help recover optimal solutions to the problem described above. Refer to the Notes for keyword arguments accepted by this function.- Parameters
f (Signomial) – The objective function to be minimized.
gts (list of Signomial) – For every
g in gts, there is a desired constraint that variablesxsatisfyg(x) >= 0.eqs (list of Signomial) – For every
g in eqs, there is a desired constraint that variablesxsatisfyg(x) == 0.X (SigDomain) – If
Xis None, then we produce a bound onfsubject only to the constraints ingtsandeqs.form (str) – Either
form='primal'orform='dual'.
- Returns
prob
- Return type
Notes
This function also accepts the following keyword arguments:
- pint
Controls the complexity of Lagrange multipliers on explicit signomial constraints
gtsandeqs. Defaults top=0, which corresponds to scalar Lagrange multipliers.- qint
The lists
gtsandeqsare replaced by lists of signomials formed by all products of<= qelements fromgtsandeqsrespectively. Defaults toq = 1.- ellint
Controls the strength of the SAGE proof system, as applied to the Lagrangian. Defaults to
ell=0, which means the primal Lagrangian must be an X-SAGE signomial.- slacksbool
For dual relaxations, determines if constraints “
mat @ vecin dual SAGE cone” is represented by “mat @ vec == temp,tempin dual SAGE cone”. Defaults to False.
For further explanation of the parameters p, q, and ell in the function above, we refer the user
to the Advanced topics section.
Solution recovery for signomial optimization¶
Section 3.2 of MCW2019 introduces two solution recovery algorithms for dual SAGE relaxations.
The main algorithm (“Algorithm 1”) is implemented by sageopt’s function sig_solrec, and the second algorithm
(“Algorithm 1L”) is simply to use a local solver to refine the solution produced by the main algorithm.
The exact choice of local solver is not terribly important. For completeness, sageopt includes
a local_refine function which relies on the COBYLA solver, as described in MCW2019.
-
sageopt.sig_solrec(prob, ineq_tol=1e-08, eq_tol=1e-06, skip_ls=False)¶ Recover a list of candidate solutions from a dual SAGE relaxation. Solutions are guaranteed to be feasible up to specified tolerances, but not necessarily optimal.
- Parameters
prob (coniclifts.Problem) – A dual-form SAGE relaxation.
ineq_tol (float) – The amount by which recovered solutions can violate inequality constraints.
eq_tol (float) – The amount by which recovered solutions can violate equality constraints.
skip_ls (bool) – Whether or not to skip constrained least-squares solution recovery.
- Returns
sols – A list of feasible solutions, sorted in increasing order of objective function value. It is possible that this list is empty, in which case no feasible solutions were recovered.
- Return type
list of ndarrays
sig_solrec actually implements a slight generalization of “Algorithm 1” from MCW2019. The generalization
is used to improve performance in more complex SAGE relaxations, such as those from
sig_constrained_relaxation with ell > 0.
Users can replicate “Algorithm 1L” from MCW2019 by running sig_solrec, and then applying the following function
to its output.
-
sageopt.local_refine(f, gts, eqs, x0, rhobeg=1, rhoend=1e-07, maxfun=10000.0)¶ Use SciPy’s COBYLA solver in an attempt to find a minimizer of
fsubject to inequality constraints ingtsand equality constraints ineqs.- Parameters
f (a callable function) – The minimization objective.
gts (a list of callable functions) – Each
g in gtsspecifies an inequality constraintg(x) >= 0.eqs (a list of callable functions) – Each
g in eqsspecifies an equality constraintg(x) == 0.x0 (ndarray) – An initial point for COBYLA.
rhobeg (float) – Controls the size of COBYLA’s initial search space.
rhoend (float) – Termination criteria, controlling the size of COBYLA’s smallest search space.
maxfun (int) – Termination criteria, bounding the number of COBYLA’s iterations.
- Returns
x – The solution returned by COBYLA.
- Return type
ndarray
Advanced topics¶
SigDomain objects¶
-
class
sageopt.SigDomain(n, **kwargs)¶ Represent a convex set \(X \subset R^n\), for use in signomial conditional SAGE relaxations.
- Parameters
n (int) – The dimension of the space in which this set lives.
Example
Suppose you want to represent the \(\ell_2\) unit ball in \(R^{5}\). This can be done as follows,
import sageopt as so import sageopt.coniclifts as cl x_var = cl.Variable(shape=(5,), name='temp') cons = [cl.vector2norm(x_var) <= 1] X = so.SigDomain(5) X.parse_coniclifts_constraints(cons)
As written, that SigDomain cannot be used for solution recovery from SAGE relaxations. To fully specify a SigDomain, you need to set attributes
gtsandeqs, which are lists of inequality constraints (g(x) >= 0) and equality constraints (g(x) == 0) respectively. The following code completes the example aboveimport numpy as np my_gts = [lambda dummy_x: 1 - np.linalg.norm(dummy_x, ord=2)] X.gts = my_gts X.eqs = []
This class does not check for correctness of
eqsandgts. It is up to the user to ensure these values represent this SigDomain in the intended way.Notes
The constructor accepts the following keyword arguments:
- coniclifts_cons: list of coniclifts.constraints.Constraint
Constraints over a single coniclifts Variable, which define this SigDomain.
- gtslist of callable
Inequality constraint functions (
g(x) >= 0) which can be used to representX.- eqslist of callable
Equality constraint functions (
g(x) == 0) which can be used to representX.- check_feasbool
Whether or not to check that
Xis nonempty. Defaults to True.- AbKtuple
Specify a convex set in the coniclifts standard.
AbK[0]is a SciPy sparse matrix. The firstncolumns of this matrix correspond to the variables over which this set is supposed to be defined. Any remaining columns are for auxiliary variables.
Only one of
AbKandconiclifts_conscan be provided upon construction. If more than one of these value is provided, the constructor will raise an error.-
parse_coniclifts_constraints(constraints)¶ Modify this SigDomain object, so that it represents the set of values which satisfy the provided constraints.
- Parameters
constraints (list of coniclifts.Constraint) – The provided constraints must be defined over a single coniclifts Variable.
-
check_membership(x_val, tol)¶ Evaluate
self.gtsandself.eqsatx_val, to check ifx_valbelongs to this SigDomain.- Parameters
x_val (ndarray) – Check if
x_valbelongs in this domain.tol (float) – Infeasibility tolerance.
- Returns
res – True iff
x_valbelongs in the domain represented byself, up to infeasibility tolerancetol.- Return type
bool
-
suppfunc(y)¶ The support function of the convex set \(X\) associated with this SigDomain, evaluated at \(y\):
\[\sigma_X(y) \doteq \max\{ y^\intercal x \,:\, x \in X \}.\]
reference hierarchy parameters¶
Here we describe the precise meanings of parameters
p and ell in sig_constrained_relaxation.
In primal form, sig_constrained_relaxation operates by
moving explicit signomial constraints into a Lagrangian,
and attempting to certify the Lagrangian as nonnegative over X;
this is a standard combination of the concepts reviewed in Section 2 of MCW2019.
Parameter ell is essentially the same as in sig_relaxation:
to improve the strength of the SAGE
proof system, modulate the Lagrangian L - gamma by powers of the signomial
t = Signomial(L.alpha, np.ones(L.m)).
Parameters p and q affect the unmodulated Lagrangian seen by
sig_constrained_relaxation;
this unmodulated Lagrangian is constructed with the following function.
-
sageopt.relaxations.sage_sigs.make_sig_lagrangian(f, gts, eqs, p, q)¶ Given a problem
\[\begin{split}\begin{align*} \min\{ f(x) :~& g(x) \geq 0 \text{ for } g \in \mathtt{gts}, \\ & g(x) = 0 \text{ for } g \in \mathtt{eqs}, \\ & \text{and } x \in X \} \end{align*}\end{split}\]construct the q-fold constraints
q-gtsandq-eqs, by taking all products of<= qelements fromgtsandeqsrespectively. Then form the Lagrangian\[L = f - \gamma - \sum_{g \, \in \, \mathtt{q-gts}} s_g \cdot g - \sum_{g \, \in \, \mathtt{q-eqs}} z_g \cdot g\]where \(\gamma\) is a coniclifts Variable of dimension 1, and the coefficients on Signomials \(s_g\) and \(z_g\) are coniclifts Variables of a dimension determined by
p.- Parameters
f (Signomial) – The objective in a desired minimization problem.
gts (list of Signomials) – For every
g in gts, there is a desired constraint that variablesxsatisfyg(x) >= 0.eqs (list of Signomials) – For every
g in eqs, there is a desired constraint that variablesxsatisfyg(x) == 0.p (int) – Controls the complexity of
s_gandz_g.q (int) – The number of folds of constraints
gtsandeqs.
- Returns
L (Signomial) –
L.cis an affine expression of coniclifts Variables.ineq_dual_sigs (a list of pairs of Signomial objects.) – If the pair
(s_g, g)is in this list, thens_gis a generalized Lagrange multiplier to the constraintg(x) >= 0.eq_dual_sigs (a list of pairs of Signomial objects.) – If the pair
(z_g, g)is in this list, thenz_gis a generalized Lagrange multiplier to the constraintg(x) == 0.gamma (coniclifts.Variable.) – In primal-form SAGE relaxations, we want to maximize
gamma. In dual form SAGE relaxations,gammainduces an equality constraint.
Notes
The Lagrange multipliers
s_gandz_gshare a common matrix of exponent vectors, which we callalpha_hat.When
p = 0,alpha_hatconsists of a single row, of all zeros. In this case,s_gandz_gare constant Signomials, and the coefficient vectorss_g.candz_g.care effectively scalars. Whenp > 0, the rows ofalpha_hatare set to allp-wise sums of exponent vectors appearing in eitherf, or someg in gts, or someg in eqs.