Consider the problem of minimizing a linear function subject to a matrix inequality as follows:

minimize x  c T x   s.t.
     F ( x ) 0
    Ax = b,  

with F ( x ) = G + i = 1 m x i F i

where x  R m , c  R m and G, F 1 , ... , F m  S n are m + 1 symmetric matrices. The inequality sign in F ( x ) 0 means that S ( x ) =-F ( x ) is positive semidefinite, i.e. v T S ( x ) v 0 for all v  R n . We call the inequality F ( x ) 0 a linear matrix inequality (LMI) and the problem is given the name of semidefinite program (it is a convex optimization problem since its objective and constraints are convex).
See S.Boyd and L.Vandenberghe, "Convex Optimization", p. 168 for a more formal definition and details.

You can use the Barrier Method algorithm available with Solver4J for solving this type of problems, passing in the generalized barrier function for the positive semidefinite cone S + n as the barrier function (see S.Boyd and L.Vandenberghe, "Convex Optimization", p. 600):

Φ ( x ) = logdet ( - F ( x ) - 1 )

with dom Φ = x  | F(x) < 0 . For strictly feasible x the gradient is equal to

( x ) dx i = - tr ( - F ( x ) - 1 F i )

and the hessian is

d 2 Φ ( x ) dx i dx j = tr ( ( - F ( x ) - 1 F i ) ( - F ( x ) - 1 F j ) )

This function is represented in Solver4J with the class SDPLogarithmicBarrier.

Code example

Here we want to solve a QCQP we already know the solution of as a SDP.
In order to proceed, we first observe (see S.Boyd and L.Vandenberghe, "SEMIDEFINITE PROGRAMMING", SIAM REVIEW Vol. 38, No. 1, pp. 49-95, March 1996) that a convex quadratic constraint ( Ax + b ) T ( Ax + b ) - c T x - d 0 , with x  R k , can be written as

I Ax + b ( Ax + b ) T c T x + d 0

The left hand side is an affine function of x, and can be expressed as

F ( x ) = G + x 1 F 1 + ... + x k F k 0   with

G = -  I b b T d F i = -  0 a i a i T c i i = 1,. .. , k ( a i are the columns of A )

It follows that a QCQP

minimize x f 0 ( x )   s.t.
     f i ( x ) 0 i = 1,. .. , L

in which the objective function and the constraints are in the form of:

f i ( x ) = ( A i x + b i ) T ( A i x + b i ) - c i T x - d i i=0,...,L

can be rewritten as

minimize x , t  t   s.t.
     I A 0 x + b 0 ( A 0 x + b 0 ) T c 0 T x + d 0 + t 0
     I A i x + b i ( A i x + b i ) T c i T x + d i 0 i=1,...,L

which is a SDP with variables ( x , t )  ∈  R k + 1 , n = ( n 0 +1) + ... + ( n L +1) and A i  R n i x k , and the matrices G, F i are given by

G = -  I b0 . . . 0 0 b0T d0 0 0 . . . . . . . . . 0 0 I b L 0 0 . . . b L T d L

F i = -  0 A 0i ...0 0 A 0i T c 0 0 0 . . . . . . . . . 0 0 0 A Li 0 0 . . . A Li T c L i=1,...,k

.

Keeping all this in mind, we now want to find the solution of this QCQP

minimize x , y - 21 50 0 - 2 5 - 1 2 x y T - 21 50 0 - 2 5 - 1 2 x y   s.t.
     1 0 0 1 x y + 2 2 T 1 0 0 1 x y + 2 2 - 1.75 2 0

(this is the same problem considered in QCQP - 2D example) threating it as a SDP; for a graphical reference, we show the plot of the function h(x,y)=det(-F(x,y,t)) for a fixed value of t=10 and its level curves in the (x,y) plane: the blue colored surface and curves are relative to the circle that defines the feasible region of the original problem

. It can be do like this:
		
		// Objective function (variables (x,y,t), dim = 3)
		double[] c = new double[]{0,0,1};
		LinearMultivariateRealFunction objectiveFunction = new LinearMultivariateRealFunction(c, 0);
		
		//constraint in the form (A0.x+b0)T.(A0.x+b0) - c0.x - d0 - t < 0
		double[][] A0 = new double[][]{
				{-Math.sqrt(21./50.),  0.             , 0},
				{-Math.sqrt(2)/5.   , -1./Math.sqrt(2), 0}};
		double[] b0 = new double[] { 0, 0, 0 };
		double[] c0 = new double[] { 0, 0, 1 };
		double d0 = 0;
		
		//constraint (this is a circle) in the form (A1.x+b1)T.(A1.x+b1) - c1.x - d1 < 0
		double[][] A1 = new double[][]{{1,0,0},
				                       {0,1,0}};
		double[] b1 = new double[] { 2, 2, 0 };
		double[] c1 = new double[] { 0, 0, 0 };
		double d1 = Math.pow(1.75, 2);
		
		//matrix G for SDP
		double[][] G = new double[][]{
				{1     ,0     ,b0[0] ,0     ,0     ,0},
				{0     ,1     ,b0[1] ,0     ,0     ,0},
				{b0[0] ,b0[1] ,d0    ,0     ,0     ,0},
				{0     ,0     ,0     ,1     ,0     ,b1[0]},
				{0     ,0     ,0     ,0     ,1     ,b1[1]},
				{0     ,0     ,0     ,b1[0] ,b1[1] ,d1}};
		//matrices Fi for SDP
		double[][] F1 =  new double[][]{
				{0        ,0        ,A0[0][0] ,0        ,0        ,0},
				{0        ,0        ,A0[1][0] ,0        ,0        ,0},
				{A0[0][0] ,A0[1][0] ,c0[0]    ,0        ,0        ,0},
				{0        ,0        ,0        ,0        ,0        ,A1[0][0]},
				{0        ,0        ,0        ,0        ,0        ,A1[1][0]},
				{0        ,0        ,0        ,A1[0][0] ,A1[1][0] ,c1[0]}};
		double[][] F2 =  new double[][]{
				{0        ,0        ,A0[0][1] ,0        ,0        ,0},
				{0        ,0        ,A0[1][1] ,0        ,0        ,0},
				{A0[0][1] ,A0[1][1] ,c0[1]    ,0        ,0        ,0},
				{0        ,0        ,0        ,0        ,0        ,A1[0][1]},
				{0        ,0        ,0        ,0        ,0        ,A1[1][1]},
				{0        ,0        ,0        ,A1[0][1] ,A1[1][1] ,c1[1]}};
		double[][] F3 =  new double[][]{
				{0        ,0        ,A0[0][2] ,0        ,0        ,0},
				{0        ,0        ,A0[1][2] ,0        ,0        ,0},
				{A0[0][2] ,A0[1][2] ,c0[2]    ,0        ,0        ,0},
				{0        ,0        ,0        ,0        ,0        ,A1[0][2]},
				{0        ,0        ,0        ,0        ,0        ,A1[1][2]},
				{0        ,0        ,0        ,A1[0][2] ,A1[1][2] ,c1[2]}};
		
		double[][] GMatrix = new Array2DRowRealMatrix(G).scalarMultiply(-1).getData();
		List<double[][]> FiMatrixList = new ArrayList<double[][]>();
		FiMatrixList.add(FiMatrixList.size(), new Array2DRowRealMatrix(F1).scalarMultiply(-1).getData());
		FiMatrixList.add(FiMatrixList.size(), new Array2DRowRealMatrix(F2).scalarMultiply(-1).getData());
		FiMatrixList.add(FiMatrixList.size(), new Array2DRowRealMatrix(F3).scalarMultiply(-1).getData());
		
		//optimization request
		OptimizationRequest or = new OptimizationRequest();
		or.setF0(objectiveFunction);
		//or.setInitialPoint(new double[] { -0.8, -0.8, 10});
		
		//optimization
		BarrierFunction bf = new SDPLogarithmicBarrier(FiMatrixList, GMatrix);
		BarrierMethod opt = new BarrierMethod(bf);
		opt.setOptimizationRequest(or);
		opt.optimize();
		
This will give the solution:
				double[] sol = opt.getOptimizationResponse().solution;
				sol[0] = -2 + 1.75/Math.sqrt(2)
				sol[1] = -2 + 1.75/Math.sqrt(2)
				sol[2] =  0.8141035444;
				

Standard form

A SDP is said to be in standard form if it is staded as

minimize X tr(CX)   s.t.
     tr ( A i X ) = b i , i=1,...,p
     X 0

with X S n

see "S.Boyd and L.Vandenberghe, Convex Optimization" example 11.11. Given a problem in standard form, it is simple to formulate and solve it with Solver4J, as shown in the following example.

Code example

		
		//definition of the standard form entities
		int p = 2;
		double[][] C = new double[][]{{2, 1}, {1, 3}};
		double[][] A1 = new double[][]{{2, 1}, {1, 2}};
		double[][] A2 = new double[][]{{5, 2}, {2, 5}};
		double[] b = new double[]{4, 10};
		
		//Solver4J formulation: the variables are the 3 distinctive elements of the symmetric 2x2 matrix X:
		//double[][] X = new double[][]{{x00, x01}, {x01, x11}};
		
		// Objective function: Tr(C, X)
		double[] trCX = new double[]{2, 2, 3};//2*x00 + 2*x01 + 3*x11
		LinearMultivariateRealFunction objectiveFunction = new LinearMultivariateRealFunction(trCX, 0);
		
		// Linear equalities constraints: Tr(A_i, X) = b_i, i=1,2
		double[][] EQcoeff = new double[2][3];
		double[] eqLimits = new double[2];
		EQcoeff[0] = new double[]{2, 2, 2};//2*x00 + 2*x01 + 2*x11 (Tr(A1, X))
		EQcoeff[1] = new double[]{5, 4, 5};//5*x00 + 4*x01 + 5*x11 (Tr(A2, X))
		eqLimits[0] = b[0];
		eqLimits[1] = b[1];
		
		// Linear matrix inequality, i.e X must be semidefinite positive:
		//for this, we decompose X into its components relative to the standard basis of S.
		//The standard basis in the subspace of symmetric matrices S consist of n matrices 
		//that have one element = 1 on the main diagonal (the rest of the elements are 0) and
		//(n-1)+(n-2)+...+2+1 = (n-1)n/2 matrices that have two elements equal 1, the elements 
		//that are placed symmetrically with respect to the main diagonal (remember that
		//symmetric matrices have aij = aji, i!=j)
		double[][] F0 = new double[][]{
				{0 ,0 },
				{0 ,0 }};
		//matrices Fi for SDP: they are the elements of the standard basis of S
		double[][] F1 =  new double[][]{
				{1,0},
				{0,0 }};
		double[][] F2 =  new double[][]{
				{0,1},
				{1,0 }};
		double[][] F3 =  new double[][]{
				{0,0},
				{0,1 }};
		
		double[][] GMatrix = new Array2DRowRealMatrix(F0).scalarMultiply(-1).getData();
		List<double[][]> FiMatrixList = new ArrayList<double[][]>();
		FiMatrixList.add(FiMatrixList.size(), new Array2DRowRealMatrix(F1).scalarMultiply(-1).getData());
		FiMatrixList.add(FiMatrixList.size(), new Array2DRowRealMatrix(F2).scalarMultiply(-1).getData());
		FiMatrixList.add(FiMatrixList.size(), new Array2DRowRealMatrix(F3).scalarMultiply(-1).getData());
		
		//optimization request
		OptimizationRequest or = new OptimizationRequest();
		or.setF0(objectiveFunction);
		or.setInitialPoint(new double[] { 1, 0, 1});
		//or.setNotFeasibleInitialPoint(new double[] { 1, 0, 1});
		or.setCheckKKTSolutionAccuracy(true);
		or.setA(EQcoeff);
		or.setB(eqLimits);
		
		//optimization
		BarrierFunction bf = new SDPLogarithmicBarrier(FiMatrixList, GMatrix);
		BarrierMethod opt = new BarrierMethod(bf);
		opt.setOptimizationRequest(or);
		opt.optimize();
		
This will give the solution:
					double[] sol = opt.getOptimizationResponse().solution;
					sol[0] = 2;
					sol[1] = 0;
					sol[2] = 0;
					

Download test source bundle

Download the entire test source bundle from here.

Back to top

Reflow Maven skin maintained by Olivier Lamy.