JWally / jsLPSolver

Simple OOP javaScript library to solve linear programs, and mixed integer linear programs
The Unlicense
420 stars 69 forks source link

Solution Variables being dropped #53

Closed erikbrinkman closed 7 years ago

erikbrinkman commented 7 years ago

The solver is dropping solution variables for an unknown reason. e.g. a mwe:

var model = { optimize: 'total_z',
  opType: 'min',
  constraints: 
   { c_0_1: { min: 2 },
     c_0_2: { min: 2 },
     c_1_2: { min: 2 },
     a_0: { min: 1 },
     b_0: { min: -1 },
     a_1: { min: 2 },
     b_1: { min: -2 },
     a_2: { min: 3 },
     b_2: { min: -3 } },
  variables: 
   { y_0: { a_0: 1, b_0: -1, c_0_1: -1, c_0_2: -1 },
     z_0: { a_0: 1, b_0: 1, total_z: 1 },
     y_1: { a_1: 1, b_1: -1, c_0_1: 1, c_1_2: -1 },
     z_1: { a_1: 1, b_1: 1, total_z: 1 },
     y_2: { a_2: 1, b_2: -1, c_0_2: 1, c_1_2: 1 },
     z_2: { a_2: 1, b_2: 1, total_z: 1 } } };
console.log(solver.Solve(model));
// { feasible: true, result: 2, y_1: 2, z_2: 1, y_2: 4, z_0: 1 };

For some reason 'y_0' = 0 is missing from the result.

bchevalier commented 7 years ago

hey, thanks for using the solver! Actually, all missing variables can be assumed to have a value of 0. I think we should add this details to the readme. Would it be a satisfactory solution?

bchevalier commented 7 years ago

or do you absolutely want those variables as part of the result?

erikbrinkman commented 7 years ago

Thanks for the quick feedback and for the project, I didn't realize that it was only zeros that were excluded. I also didn't realize that all variables have an implied non-negativity constraint, which is why variables I didn't expect were zero. I don't think it's necessary that zeros are included, but documentation of that fact (and the non-negativity constraint) would be nice.

bchevalier commented 7 years ago

It is actually possible to specify which variables can be negative (we say that those variables are unrestricted):

var model = {
  optimize: 'total_z',
  opType: 'min',
  constraints: {
    c_0_1: { min: 2 },
    c_0_2: { min: 2 },
    c_1_2: { min: 2 },
    a_0: { min: 1 },
    b_0: { min: -1 },
    a_1: { min: 2 },
    b_1: { min: -2 },
    a_2: { min: 3 },
    b_2: { min: -3 }
  },
  variables: {
    y_0: { a_0: 1, b_0: -1, c_0_1: -1, c_0_2: -1 },
    z_0: { a_0: 1, b_0: 1, total_z: 1 },
    y_1: { a_1: 1, b_1: -1, c_0_1: 1, c_1_2: -1 },
    z_1: { a_1: 1, b_1: 1, total_z: 1 },
    y_2: { a_2: 1, b_2: -1, c_0_2: 1, c_1_2: 1 },
    z_2: { a_2: 1, b_2: 1, total_z: 1 }
  },
  unrestricted: {
    y_0: 1,
    y_1: 1
  }
};

Here I modified your problem so that variables y_0 and y_1 can have negative values in the optimal solution.

erikbrinkman commented 7 years ago

That's really handy. I just solved it by translating the problem into y_0+ and y_0-. Using unrestricted is almost assuredly more efficient. I also didn't see that aspect documented, or at least on the readme. Thanks for pointing it out.