Re: [ojAlgo-user] Problems with the quadratic solver (format problems fixed)
Mathematics, linear algebra and optimisation
Brought to you by:
apete
From: Anders P. <an...@op...> - 2010-02-22 19:57:30
|
Use one of these methods: addEmptyLinearExpression(String) // Linear only addEmptyQuadraticExpression(String) // Quadratic only addGeneralExpression(String) // Linear and Quadratic Don't call getExpression(?) all the time - keep the reference instead. Turn those expressions into constraints and/or objectives by setting the lower/upper limits or the contribution weight. /Anders On 22 feb 2010, at 01.44, Joao Magalhaes wrote: > 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 > > ------------------------------------------------------------------------------ > Download Intel® Parallel Studio Eval > Try the new software tools for yourself. Speed compiling, find bugs > proactively, and fine-tune applications for parallel performance. > See why Intel Parallel Studio got high marks during beta. > http://p.sf.net/sfu/intel-sw-dev > _______________________________________________ > ojAlgo-user mailing list > ojA...@li... > https://lists.sourceforge.net/lists/listinfo/ojalgo-user > > |