slightlyoff / cassowary.js

Cassowary/JS, better, faster, future-ready
Other
1.69k stars 107 forks source link

Wrong optimisation #47

Open danielepolencic opened 10 years ago

danielepolencic commented 10 years ago

Hello,

consider the following problem: maximise P = 3x + 4y subject to:

x + y ≤ 4
2x + y ≤ 5
x ≥ 0, y ≥ 0

the maximum P=16 can be obtained with: x = 0, y = 4

The same linear optimisation in cassowary:

var c = require('cassowary');
var solver = new c.SimplexSolver();

var p = new c.Variable({name: 'p'})
  , x = new c.Variable({name: 'x'})
  , y = new c.Variable({name: 'y'});

solver.addConstraint(new c.Equation(p, c.plus(c.times(x, 3), c.times(y, 4))));
solver.addConstraint(new c.Inequality(c.plus(x, y), c.LEQ, 4));
solver.addConstraint(new c.Inequality(c.plus(c.times(x, 2), y), c.LEQ, 5));

solver.addConstraint(new c.Inequality(x, c.GEQ, 0));
solver.addConstraint(new c.Inequality(y, c.GEQ, 0));

solver.optimize(p);

console.log('p: ', p) //15
console.log('x: ', x) //1
console.log('y: ', y) //3

results in P=15, x=1, y=3, which is not the optimum solution. Any idea on what I'm doing wrong?

Thanks Daniele

bchevalier commented 9 years ago

Hello Daniele,

This reply might come a bit late but I think I can solve your problem. You have 2 issues:

1 - You need to call solver.resolve() in order to run the optimisation (I think that by default only a feasible solution will be computed, not the optimal one) 2 - Cassowary will solve a minimization problem, therefore you need to inverse the sign of p to get the value of P=16 that you were looking for, for instance by changing your constraint P = -3x - 4y

The following code seem to work:

var solver = new c.SimplexSolver();

var p = new c.Variable({name: 'p'})
  , x = new c.Variable({name: 'x'})
  , y = new c.Variable({name: 'y'});

solver.addConstraint(new c.Equation(p, c.plus(c.times(x, -3), c.times(y, -4))));
solver.addConstraint(new c.Inequality(c.plus(x, y), c.LEQ, 4));
solver.addConstraint(new c.Inequality(c.plus(c.times(x, 2), y), c.LEQ, 5));

solver.addConstraint(new c.Inequality(x, c.GEQ, 0));
solver.addConstraint(new c.Inequality(y, c.GEQ, 0));

solver.optimize(p);
solver.resolve();

console.log('p: ', p) //-16
console.log('x: ', x) //0
console.log('y: ', y) //4