User guide¶
Variables¶
Quadratic programming (QP) aims at optimizing a quadratic expression of several variables, subject to linear constraints on these variables.
Let’s for example solve this very simple quadratic programming problem: find values of \(x_1\) and \(x_2\) that minimize
subject to
So, let’s start with variables:
Variable x1, x2;
This defines two instances of the Variable
class, representing the variables of your QP problem.
Solving your quadratic problem means finding values for these variables.
The Variable
class has some sort of “pointer” semantics:
an instance represents a variable of your QP problem, and if you copy this instance,
the copy represents the same variable. The original and the copy can be used interchangeably anywhere.
They are also immutable: Variable
instances represent
the same variable from their construction to their destruction.
Linear and quadratic expressions¶
Variables
can then be combined into
LinearExpressions
and QuadraticExpressions
using conventional operators and floating point numbers.
All operators producing degree zero, one, or two polynomials are available. Here are a few examples:
Variable a, b, c;
LinearExpression l1 = a + 2 * b - c / 3 + 4;
LinearExpression l2 = l1 + 2 * a;
QuadraticExpression q1 = a * a + 2 * b + 1;
QuadraticExpression q2 = a * a - (l1 - b) * l2;
Linear and quadratic expressions have value semantics. Copying them creates an independent expression that can be mutated independently:
LinearExpression l3 = l2;
l3 *= 4;
QuadraticExpression q3 = q2;
q3 += l3;
Constraints¶
Constraints
can be constructed using (in)equality operators between
LinearExpressions
:
Constraint c1 = a <= b + 2;
Constraint c2 = c - 2 * a == b;
Solving¶
The minimize
and maximize
functions solve QP problems.
For our original example, we just have to translate the mathematical expressions to their close equivalent in C++:
Solution s = minimize(
0.5 * x1 * x1 + x2 * x2 - x1 * x2 - 2 * x1 - 6 * x2,
{
x1 + x2 <= 2,
2 * x2 <= x1 + 2,
2 * x1 + x2 <= 3,
x1 >= 0,
x2 >= 0,
}
);
The optimal (here, minimal) value is available through Solution::getCost
:
std::cout << "Optimal value: " << s.getCost() << std::endl;
Optimal value: -8.22222
The values that variables must take to reach this optimum are available through Solution::get
:
std::cout << "x1: " << s.get(x1) << std::endl;
std::cout << "x2: " << s.get(x2) << std::endl;
x1: 0.666667
x2: 1.33333