public void GoldfarbIdnaniConstructorTest2()
{
// Solve the following optimization problem:
//
// min f(x) = 2x² - xy + 4y² - 5x - 6y
//
// s.t. x - y == 5 (x minus y should be equal to 5)
// x >= 10 (x should be greater than or equal to 10)
//
// Lets first group the quadratic and linear terms. The
// quadratic terms are +2x², +3y² and -4xy. The linear
// terms are -2x and +1y. So our matrix of quadratic
// terms can be expressed as:
double[,] Q = // 2x² -1xy +4y²
{
/* x y */
/*x*/ { +2 /*xx*/ *2, -1 /*xy*/ },
/*y*/ { -1 /*xy*/ , +4 /*yy*/ *2 },
};
// Accordingly, our vector of linear terms is given by:
double[] d = { -5 /*x*/, -6 /*y*/ }; // -5x -6y
// We have now to express our constraints. We can do it
// either by directly specifying a matrix A in which each
// line refers to one of the constraints, expressing the
// relationship between the different variables in the
// constraint, like this:
double[,] A =
{
{ 1, -1 }, // This line says that x + (-y) ... (a)
{ 1, 0 }, // This line says that x alone ... (b)
};
double[] b =
{
5, // (a) ... should be equal to 5.
10, // (b) ... should be greater than or equal to 10.
};
// Equalities must always come first, and in this case
// we have to specify how many of the constraints are
// actually equalities:
int numberOfEqualities = 1;
// Alternatively, we may use a more explicitly form:
List<LinearConstraint> list = new List<LinearConstraint>();
// Define the first constraint, which involves only x
list.Add(new LinearConstraint(numberOfVariables: 1)
{
// x is the first variable, thus located at
// index 0. We are specifying that x >= 10:
VariablesAtIndices = new[] { 0 }, // index 0 (x)
ShouldBe = ConstraintType.GreaterThanOrEqualTo,
Value = 10
});
// Define the second constraint, which involves x and y
list.Add(new LinearConstraint(numberOfVariables: 2)
{
// x is the first variable, located at index 0, and y is
// the second, thus located at 1. We are specifying that
// x - y = 5 by saying that the variable at position 0
// times 1 plus the variable at position 1 times -1
// should be equal to 5.
VariablesAtIndices = new int[] { 0, 1 }, // index 0 (x) and index 1 (y)
CombinedAs = new double[] { 1, -1 }, // when combined as x - y
ShouldBe = ConstraintType.EqualTo,
Value = 5
});
// Now we can finally create our optimization problem
var target = new GoldfarbIdnani(new QuadraticObjectiveFunction(Q, d), constraints: list);
Assert.IsTrue(A.IsEqual(target.ConstraintMatrix));
Assert.IsTrue(b.IsEqual(target.ConstraintValues));
Assert.AreEqual(numberOfEqualities, target.NumberOfEqualities);
// And attempt to solve it.
Assert.IsTrue(target.Minimize());
double minimumValue = target.Value;
Assert.AreEqual(170, minimumValue, 1e-10);
Assert.AreEqual(10, target.Solution[0]);
Assert.AreEqual(05, target.Solution[1]);
foreach (double v in target.Solution)
Assert.IsFalse(double.IsNaN(v));
foreach (double v in target.Lagrangian)
Assert.IsFalse(double.IsNaN(v));
}