Disciplined Nonlinear Programming¶
Disciplined nonlinear programming (DNLP) is a system for constructing nonlinear programs (NLPs) with rules similar to those of disciplined convex programming (DCP). DNLP extends DCP by allowing smooth functions to be freely mixed with nonsmooth convex and concave functions, with rules governing how nonsmooth functions can be used.
CVXPY lets you form and solve DNLP problems. For example, the following code solves a simple (nonconvex) nonlinear program:
import cvxpy as cp
import numpy as np
# problem data
np.random.seed(0)
n = 3
A = np.random.randn(n, n)
A = A.T @ A
# formulate optimization problem
x = cp.Variable(n)
obj = cp.Maximize(cp.quad_form(x, A))
constraints = [cp.sum_squares(x) == 1]
# initialize and solve
x.value = np.ones(n)
prob = cp.Problem(obj, constraints)
prob.solve(nlp=True)
print("Optimal value from DNLP:", prob.value)
# the optimal value can also be found via the maximum eigenvalue of A
eigenvalues = np.linalg.eigvalsh(A)
print("Maximum eigenvalue: ", np.max(eigenvalues))
Note that for CVXPY to treat the problem as an NLP, you must pass the option nlp=True to the
solve() method.
Warning
In convex optimization and DCP, solvers are guaranteed to find globally optimal solutions.
In contrast, when solving a nonconvex NLP, there are no guarantees of finding globally optimal solutions,
or even locally optimal solutions. An NLP solver may converge to an infeasible point, even if the problem
is feasible. Furthermore, the solution returned by an NLP solver may depend on the initial point provided.
Specifying a good initial point (by setting the value attribute of
the variables) can significantly improve convergence.
For an in-depth reference on DNLP, see our accompanying paper.
Atoms and expressions¶
DNLP classifies atoms into three categories: smooth, nonsmooth convex, and nonsmooth concave. A full list of new DNLP atoms is presented at the end of this page.
DNLP classifies expressions based on the types of atoms they contain and how those atoms are composed. There are three expression types: smooth, linearizable convex (L-convex), and linearizable concave (L-concave). If you are familiar with DCP, there are very compact definitions of these expression types in terms of the DCP curvature types:
A smooth expression is an expression that only consists of smooth atoms. Smooth is the analog of affine in DCP.
An expression is linearizable convex (L-convex) if it is DCP convex when all smooth atoms in the expression are treated as affine.
An expression is linearizable concave (L-concave) if it is DCP concave when all smooth atoms in the expression are treated as affine.
You can check expression classifications using the methods expr.is_smooth(),
expr.is_linearizable_convex(), and expr.is_linearizable_concave().
Note that smooth expressions are both L-convex and L-concave.
It is also possible to define the DNLP expression types without reference to DCP. For more details, see Section 3.2 of the DNLP paper.
DNLP problems¶
A DNLP problem minimizes an L-convex objective or maximizes an L-concave objective. The valid constraint types are:
smooth
==smoothL-convex
<=L-concaveL-concave
>=L-convex
You can check that a problem satisfies the DNLP rules by calling
problem.is_dnlp(). CVXPY will raise an exception if you call
problem.solve(nlp=True) on a non-DNLP problem.
Solvers¶
DNLP problems require a nonlinear programming (NLP) solver. The following solvers are supported; see the Install page for installation instructions.
IPOPT (recommended, open-source, EPL-2.0)
UNO (open-source, MIT)
COPT (commercial)
KNITRO (commercial)
Set the solver explicitly if needed: prob.solve(nlp=True, solver=cp.IPOPT).
DNLP atoms¶
In DNLP, all atoms from the DCP atom library are available and classified as smooth if they are twice continuously differentiable on the interior of their domain. Convex and concave DCP atoms that are not smooth (such as abs, maximum, norm1, minimum, min, etc.) retain their convexity/concavity and can appear in L-convex and L-concave expressions respectively.
Some existing CVXPY atoms gain new meaning in DNLP. These are summarized in the table below.
For example, in DCP, the multiply atom requires that one of the arguments is a constant,
but in DNLP, multiply is smooth and can be used with two variable arguments.
Warning
When using division as in 1/x or 1/f(x) in DNLP, it is always assumed that the denominator
is nonnegative. If not, an error will be raised. If you wish to model 1/(-x^2),
you must formulate it as -1/x^2.
Function |
Meaning |
Domain |
Monotonicity |
|---|---|---|---|
multiply(x, y) |
\(xy\) |
\(x, y \in \mathbf{R}\) |
depends on sign |
quad_form(x, Q) \(Q \in \mathbf{S}^n\) |
\(x^T Q x\) |
\(x \in \mathbf{R}^n\) |
depends on sign |
In addition, DNLP introduces the following new smooth atoms that are neither convex
nor concave. These atoms can only be used in DNLP problems and are available in the
cp.nlp module.
Function |
Meaning |
Domain |
Monotonicity |
|---|---|---|---|
cp.nlp.sin(x) |
\(\sin(x)\) |
\(x \in \mathbf{R}\) |
none |
cp.nlp.cos(x) |
\(\cos(x)\) |
\(x \in \mathbf{R}\) |
none |
cp.nlp.tan(x) |
\(\tan(x)\) |
\(x \in (-\pi/2, \pi/2)\) |
none |
cp.nlp.sinh(x) |
\((e^x - e^{-x})/2\) |
\(x \in \mathbf{R}\) |
incr. |
cp.nlp.tanh(x) |
\((e^x - e^{-x})/(e^x + e^{-x})\) |
\(x \in \mathbf{R}\) |
incr. |
cp.nlp.asinh(x) |
\(\ln(x + \sqrt{x^2 + 1})\) |
\(x \in \mathbf{R}\) |
incr. |
cp.nlp.atanh(x) |
\(\frac{1}{2} \ln \frac{1+x}{1-x}\) |
\(x \in (-1, 1)\) |
incr. |