Re: [ojAlgo-user] Problems with the quadratic solver (format problems fixed)
Mathematics, linear algebra and optimisation
Brought to you by:
apete
From: Joao M. <ma...@gm...> - 2010-02-22 00:50:18
|
Anders, Thank you for your help. I removed the code about the objective function, and after studying MarkowitzModel.generateOptimisationModel method, I concluded I should set lower limits for variables that have lower limits. It also looked like the method addSimpleWeightExpression is used to define the objective function, however, when I tried this, I got a NullPointerException because my objective function has quadratic terms. So, I used the method addEmptyQuadraticExpression, and defined a big "contribution weight" (BigMath.VERY_POSITIVE) by calling method setContributionWeight. I think that, by doing this, I defined this quadratic equation as my objective function, is this correct? The objective function is dm1^2 + dm2^2 + dm3^2, so, my final code for the expression looks like this: model.addEmptyQuadraticExpression( "eq9" ); model.getExpression( "eq9" ).setQuadraticFactor( model.indexOfVariable( "dm1" ), model.indexOfVariable( "dm1" ), BigMath.ONE ); model.getExpression( "eq9" ).setQuadraticFactor( model.indexOfVariable( "dm2" ), model.indexOfVariable( "dm2" ), BigMath.ONE ); model.getExpression( "eq9" ).setQuadraticFactor( model.indexOfVariable( "dm3" ), model.indexOfVariable( "dm3" ), BigMath.ONE ); model.getExpression( "eq9" ).setContributionWeight( BigMath.VERY_POSITIVE ); The model I created has all these variables (the complete code is at the end of this message) However, I am not quite sure about how to set the constraints of my problem. They are the following: eq1: 0.5*a + 2*b + 3*c - e1 = 2 eq2: a - 0.5*b - 2*c - e2 = 3 eq3: -0.3*a + 3*c - e3 = 0 eq4: e1 + e2 + e3 - 3*mean = 0 eq5: e1 - mean - dm1 = 0 eq6: e2 - mean - dm2 = 0 eq7: e3 - mean - dm3 = 0 eq8: a + b + c = 1 By reading the javadocs, I understood that the method I should use is addConstraint, which receives the lower and the upper limits. So, in order to get an equality, I just have to make upperLimit = lowerLimit. So, my code looked like this (notice that I used upperLimit = lowerLimit = 0, and setConstant to define the equality): model.addConstraint( "eq1", BigMath.ZERO, BigMath.ZERO ); model.addConstraint( "eq2", BigMath.ZERO, BigMath.ZERO ); model.addConstraint( "eq3", BigMath.ZERO, BigMath.ZERO ); model.addConstraint( "eq4", BigMath.ZERO, BigMath.ZERO ); model.addConstraint( "eq5", BigMath.ZERO, BigMath.ZERO ); model.addConstraint( "eq6", BigMath.ZERO, BigMath.ZERO ); model.addConstraint( "eq7", BigMath.ZERO, BigMath.ZERO ); model.addConstraint( "eq8", BigMath.ZERO, BigMath.ZERO ); model.getExpression( "eq1" ).setLinearFactor( model.indexOfVariable( "A" ), BigMath.HALF ); model.getExpression( "eq1" ).setLinearFactor( model.indexOfVariable( "B" ), new BigDecimal( 2 ) ); model.getExpression( "eq1" ).setLinearFactor( model.indexOfVariable( "C" ), new BigDecimal( 3 ) ); model.getExpression( "eq1" ).setLinearFactor( model.indexOfVariable( "e1" ), new BigDecimal( -1 ) ); model.getExpression( "eq1" ).setConstant( new BigDecimal( -2 ) ); model.getExpression( "eq2" ).setLinearFactor( model.indexOfVariable( "A" ), BigMath.ONE ); model.getExpression( "eq2" ).setLinearFactor( model.indexOfVariable( "B" ), new BigDecimal( -0.5 ) ); model.getExpression( "eq2" ).setLinearFactor( model.indexOfVariable( "C" ), new BigDecimal( -2 ) ); model.getExpression( "eq2" ).setLinearFactor( model.indexOfVariable( "e2" ), new BigDecimal( -1 ) ); model.getExpression( "eq2" ).setConstant( new BigDecimal( -3 ) ); model.getExpression( "eq3" ).setLinearFactor( model.indexOfVariable( "A" ), new BigDecimal( -0.3 ) ); model.getExpression( "eq3" ).setLinearFactor( model.indexOfVariable( "B" ), new BigDecimal( 3 ) ); model.getExpression( "eq3" ).setLinearFactor( model.indexOfVariable( "C" ), new BigDecimal( -0.8 ) ); model.getExpression( "eq3" ).setLinearFactor( model.indexOfVariable( "e3" ), new BigDecimal( -1 ) ); model.getExpression( "eq3" ).setConstant( BigMath.ZERO ); model.getExpression( "eq4" ).setLinearFactor( model.indexOfVariable( "e1" ), BigMath.ONE ); model.getExpression( "eq4" ).setLinearFactor( model.indexOfVariable( "e2" ), BigMath.ONE ); model.getExpression( "eq4" ).setLinearFactor( model.indexOfVariable( "e3" ), BigMath.ONE ); model.getExpression( "eq4" ).setLinearFactor( model.indexOfVariable( "mean" ), new BigDecimal( -3 ) ); model.getExpression( "eq4" ).setConstant( BigMath.ZERO ); model.getExpression( "eq5" ).setLinearFactor( model.indexOfVariable( "e1" ), BigMath.ONE ); model.getExpression( "eq5" ).setLinearFactor( model.indexOfVariable( "mean" ), new BigDecimal( -1 ) ); model.getExpression( "eq5" ).setLinearFactor( model.indexOfVariable( "dm1" ), new BigDecimal( -1 ) ); model.getExpression( "eq5" ).setConstant( BigMath.ZERO ); model.getExpression( "eq6" ).setLinearFactor( model.indexOfVariable( "e2" ), BigMath.ONE ); model.getExpression( "eq6" ).setLinearFactor( model.indexOfVariable( "mean" ), new BigDecimal( -1 ) ); model.getExpression( "eq6" ).setLinearFactor( model.indexOfVariable( "dm2" ), new BigDecimal( -1 ) ); model.getExpression( "eq6" ).setConstant( BigMath.ZERO ); model.getExpression( "eq7" ).setLinearFactor( model.indexOfVariable( "e3" ), BigMath.ONE ); model.getExpression( "eq7" ).setLinearFactor( model.indexOfVariable( "mean" ), new BigDecimal( -1 ) ); model.getExpression( "eq7" ).setLinearFactor( model.indexOfVariable( "dm3" ), new BigDecimal( -1 ) ); model.getExpression( "eq7" ).setConstant( BigMath.ZERO ); model.getExpression( "eq8" ).setLinearFactor( model.indexOfVariable( "A" ), BigMath.ONE ); model.getExpression( "eq8" ).setLinearFactor( model.indexOfVariable( "B" ), BigMath.ONE ); model.getExpression( "eq8" ).setLinearFactor( model.indexOfVariable( "C" ), BigMath.ONE ); model.getExpression( "eq8" ).setConstant( new BigDecimal( -1 ) ); So, I defined minimisation (by calling setMinimisation), generated a solver (by calling getDefaultSolver), and invoked the method solve, as in the following code: model.setMaximisation( false ); model.setMinimisation( true ); final OptimisationSolver solver = model.getDefaultSolver(); final Result res = solver.solve(); This time, I did not get an exception, but the following result: OPTIMAL (1) { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 } But this is not what I expected. Please, can you tell me what I am doing wrong? Cheers Joao Magalhaes --- -------- Code: import java.math.BigDecimal; import java.util.HashSet; import java.util.Set; import org.ojalgo.constant.BigMath; import org.ojalgo.optimisation.ModelValidationException; import org.ojalgo.optimisation.OptimisationSolver; import org.ojalgo.optimisation.Variable; import org.ojalgo.optimisation.OptimisationSolver.Result; import org.ojalgo.optimisation.quadratic.QuadraticExpressionsModel; public class Test { public static void main( final String[] args ) throws ModelValidationException { final Set<Variable> variables = new HashSet<Variable>(); final Variable A = new Variable( "A" ); final Variable B = new Variable( "B" ); final Variable C = new Variable( "C" ); final Variable e1 = new Variable( "e1" ); final Variable e2 = new Variable( "e2" ); final Variable e3 = new Variable( "e3" ); final Variable mean = new Variable( "mean" ); final Variable dm1 = new Variable( "dm1" ); final Variable dm2 = new Variable( "dm2" ); final Variable dm3 = new Variable( "dm3" ); variables.add( A ); variables.add( B ); variables.add( C ); variables.add( e1 ); variables.add( e2 ); variables.add( e3 ); variables.add( mean ); variables.add( dm1 ); variables.add( dm2 ); variables.add( dm3 ); A.setLowerLimit( BigMath.ZERO ); B.setLowerLimit( BigMath.ZERO ); C.setLowerLimit( BigMath.ZERO ); e1.setLowerLimit( BigMath.ZERO ); e2.setLowerLimit( BigMath.ZERO ); e3.setLowerLimit( BigMath.ZERO ); mean.setLowerLimit( BigMath.ZERO ); dm1.setLowerLimit( BigMath.VERY_NEGATIVE ); dm2.setLowerLimit( BigMath.VERY_NEGATIVE ); dm3.setLowerLimit( BigMath.VERY_NEGATIVE ); A.setUpperLimit( BigMath.VERY_POSITIVE ); B.setUpperLimit( BigMath.VERY_POSITIVE ); C.setUpperLimit( BigMath.VERY_POSITIVE ); e1.setUpperLimit( BigMath.VERY_POSITIVE ); e2.setUpperLimit( BigMath.VERY_POSITIVE ); e3.setUpperLimit( BigMath.VERY_POSITIVE ); mean.setUpperLimit( BigMath.VERY_POSITIVE ); dm1.setUpperLimit( BigMath.VERY_POSITIVE ); dm2.setUpperLimit( BigMath.VERY_POSITIVE ); dm3.setUpperLimit( BigMath.VERY_POSITIVE ); final QuadraticExpressionsModel model = new QuadraticExpressionsModel( variables ); model.addConstraint( "eq1", BigMath.ZERO, BigMath.ZERO ); model.addConstraint( "eq2", BigMath.ZERO, BigMath.ZERO ); model.addConstraint( "eq3", BigMath.ZERO, BigMath.ZERO ); model.addConstraint( "eq4", BigMath.ZERO, BigMath.ZERO ); model.addConstraint( "eq5", BigMath.ZERO, BigMath.ZERO ); model.addConstraint( "eq6", BigMath.ZERO, BigMath.ZERO ); model.addConstraint( "eq7", BigMath.ZERO, BigMath.ZERO ); model.addConstraint( "eq8", BigMath.ZERO, BigMath.ZERO ); model.addEmptyQuadraticExpression( "eq9" ); model.getExpression( "eq1" ).setLinearFactor( model.indexOfVariable( "A" ), BigMath.HALF ); model.getExpression( "eq1" ).setLinearFactor( model.indexOfVariable( "B" ), new BigDecimal( 2 ) ); model.getExpression( "eq1" ).setLinearFactor( model.indexOfVariable( "C" ), new BigDecimal( 3 ) ); model.getExpression( "eq1" ).setLinearFactor( model.indexOfVariable( "e1" ), new BigDecimal( -1 ) ); model.getExpression( "eq1" ).setConstant( new BigDecimal( -2 ) ); model.getExpression( "eq2" ).setLinearFactor( model.indexOfVariable( "A" ), BigMath.ONE ); model.getExpression( "eq2" ).setLinearFactor( model.indexOfVariable( "B" ), new BigDecimal( -0.5 ) ); model.getExpression( "eq2" ).setLinearFactor( model.indexOfVariable( "C" ), new BigDecimal( -2 ) ); model.getExpression( "eq2" ).setLinearFactor( model.indexOfVariable( "e2" ), new BigDecimal( -1 ) ); model.getExpression( "eq2" ).setConstant( new BigDecimal( -3 ) ); model.getExpression( "eq3" ).setLinearFactor( model.indexOfVariable( "A" ), new BigDecimal( -0.3 ) ); model.getExpression( "eq3" ).setLinearFactor( model.indexOfVariable( "B" ), new BigDecimal( 3 ) ); model.getExpression( "eq3" ).setLinearFactor( model.indexOfVariable( "C" ), new BigDecimal( -0.8 ) ); model.getExpression( "eq3" ).setLinearFactor( model.indexOfVariable( "e3" ), new BigDecimal( -1 ) ); model.getExpression( "eq3" ).setConstant( BigMath.ZERO ); model.getExpression( "eq4" ).setLinearFactor( model.indexOfVariable( "e1" ), BigMath.ONE ); model.getExpression( "eq4" ).setLinearFactor( model.indexOfVariable( "e2" ), BigMath.ONE ); model.getExpression( "eq4" ).setLinearFactor( model.indexOfVariable( "e3" ), BigMath.ONE ); model.getExpression( "eq4" ).setLinearFactor( model.indexOfVariable( "mean" ), new BigDecimal( -3 ) ); model.getExpression( "eq4" ).setConstant( BigMath.ZERO ); model.getExpression( "eq5" ).setLinearFactor( model.indexOfVariable( "e1" ), BigMath.ONE ); model.getExpression( "eq5" ).setLinearFactor( model.indexOfVariable( "mean" ), new BigDecimal( -1 ) ); model.getExpression( "eq5" ).setLinearFactor( model.indexOfVariable( "dm1" ), new BigDecimal( -1 ) ); model.getExpression( "eq5" ).setConstant( BigMath.ZERO ); model.getExpression( "eq6" ).setLinearFactor( model.indexOfVariable( "e2" ), BigMath.ONE ); model.getExpression( "eq6" ).setLinearFactor( model.indexOfVariable( "mean" ), new BigDecimal( -1 ) ); model.getExpression( "eq6" ).setLinearFactor( model.indexOfVariable( "dm2" ), new BigDecimal( -1 ) ); model.getExpression( "eq6" ).setConstant( BigMath.ZERO ); model.getExpression( "eq7" ).setLinearFactor( model.indexOfVariable( "e3" ), BigMath.ONE ); model.getExpression( "eq7" ).setLinearFactor( model.indexOfVariable( "mean" ), new BigDecimal( -1 ) ); model.getExpression( "eq7" ).setLinearFactor( model.indexOfVariable( "dm3" ), new BigDecimal( -1 ) ); model.getExpression( "eq7" ).setConstant( BigMath.ZERO ); model.getExpression( "eq8" ).setLinearFactor( model.indexOfVariable( "A" ), BigMath.ONE ); model.getExpression( "eq8" ).setLinearFactor( model.indexOfVariable( "B" ), BigMath.ONE ); model.getExpression( "eq8" ).setLinearFactor( model.indexOfVariable( "C" ), BigMath.ONE ); model.getExpression( "eq8" ).setConstant( new BigDecimal( -1 ) ); model.getExpression( "eq9" ).setQuadraticFactor( model.indexOfVariable( "dm1" ), model.indexOfVariable( "dm1" ), BigMath.ONE ); model.getExpression( "eq9" ).setQuadraticFactor( model.indexOfVariable( "dm2" ), model.indexOfVariable( "dm2" ), BigMath.ONE ); model.getExpression( "eq9" ).setQuadraticFactor( model.indexOfVariable( "dm3" ), model.indexOfVariable( "dm3" ), BigMath.ONE ); model.getExpression( "eq9" ).setContributionWeight( BigMath.VERY_POSITIVE ); model.setMaximisation( false ); model.setMinimisation( true ); final OptimisationSolver solver = model.getDefaultSolver(); final Result res = solver.solve(); System.out.println( res.getState().toString() ); System.out.println( res.toString() ); } } > Haven't looked into exactly what your problem is, but: > 1) You define the objective function by setting the "contribution weight" on one or more exssions and/or variables. The method getObjectiveExssion() will give > you a derived/aggregated exssion. You most likely do not need to call this method. If you want to call it, you should do so when the optimization model is > complete. > 2) Lok in the MarkowitzModel class (even if that's not the model you're after). In that class there is a private method generateOptimisationModel(...). Study > that code. > /Anders On Sun, Feb 21, 2010 at 6:18 PM, Joao Magalhaes <ma...@gm...> wrote: > Hello again, > > Looks like the matrix got messed up in my previous post. So, I am > sending the message again, but with the equations instead of the > matrix. > Apologies for this. > My name is Joao Magalhaes, I am an undegraduate student from Brazil. > I have to solve an optimization problem that has to do with > financial stuff. It can be summarized by the equations below: > > Constraints: > > eq1: 0.5*a + 2*b + 3*c - e1 = 2 > eq2: a - 0.5*b - 2*c - e2 = 3 > eq3: -0.3*a + 3*c - e3 = 0 > eq4: e1 + e2 + e3 - 3*mean = 0 > eq5: e1 - mean - dm1 = 0 > eq6: e2 - mean - dm2 = 0 > eq7: e3 - mean - dm3 = 0 > eq8: a + b + c = 1 > > Objective: minimize dm1^2 + dm2^2 + dm3^2 > > The goal is to minimize the function dm1^2 + dm2^2 + dm3^2, subject to > the constraints. > I searched for Quadratic Solvers in google, and came across ojAlgo. > Based on the javadocs and some source code inspection, I have written > the code and the end of this message. However, I came across two > problems: > > 1) I cannot set quadratic factors for the objective function. I get a > NullPointerException. Inspecting the source code, I concluded that the > objective function must be linear, is this correct? If so, it would be > also possible to model the problem a little bit differently, by adding > a new quadratic constraint and minimizing the new created variable, > just as follows: > > eq1: 0.5*a + 2*b + 3*c - e1 = 2 > eq2: a - 0.5*b - 2*c - e2 = 3 > eq3: -0.3*a + 3*c - e3 = 0 > eq4: e1 + e2 + e3 - 3*mean = 0 > eq5: e1 - mean - dm1 = 0 > eq6: e2 - mean - dm2 = 0 > eq7: e3 - mean - dm3 = 0 > eq8: a + b + c = 1 > eq9: 3* var - dm1^2 - dm2^2 - dm3^2 = 0 > > Objective: minimize var > > However, I tried this too, but it did not work. > > 2) In order to keep moving on, I used the first model with 8 > equations, but changed the objective function to something linear > (just the sum of the dm variables), so that nothing in the problem is > quadratic, everything is linear. But again, I get a > NullPointerException in the Lagrange Solver: > > Exception in thread "main" java.lang.NullPointerException > at org.ojalgo.matrix.store.MergedRowsStore.<init>(MergedRowsStore.java:46) > at org.ojalgo.optimisation.quadratic.LagrangeSolver.buildIterationSolver(LagrangeSolver.java:56) > at org.ojalgo.optimisation.quadratic.LagrangeSolver.performIteration(LagrangeSolver.java:84) > at org.ojalgo.optimisation.quadratic.QuadraticSolver.iterate(QuadraticSolver.java:303) > at org.ojalgo.optimisation.quadratic.QuadraticSolver.solve(QuadraticSolver.java:275) > at org.ojalgo.optimisation.quadratic.QuadraticSolver.solve(QuadraticSolver.java:256) > at br.com.mindsatwork.ojalgo.test.TestClass.main(TestClass.java:143) > > My source code is as follows. Can anyone give me some light on what I > am doing wrong? Please, apologies if this is a very basic question, > but it is the very first time I try ojAlgo. I promise to improve my > questions in the future :-) > > Cheers, > Joao Magalhaes |