JWally / jsLPSolver

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

absolute values in constraints |X| >= C nor working #130

Open robwieringa opened 11 months ago

robwieringa commented 11 months ago

The method descibed in https://optimization.cbe.cornell.edu/index.php?title=Optimization_with_absolute_values uses a binary (and Mixed-Integer Linear Programming) to resolve the non convexity issue.

I made the following test (extracted from a larger app) which does not not result in the optimal solution (the binary is 0, while 1 would deliver the optimal result).

Help is appreciated. Rob

--------------------------- %< ----------------------------------

// absolute value handling method for constraint |d| >= C: // introduce binary B and large constant N (> maximal d + C) // (a) d:min -> d >= C - NB // (b) d:max -> d <= -C + N(1-B) // (c) d can be negative, so must be set to 'unrestricted'

// absolute value handling method for optimizing b: introduce b+ and b- // (a): replace b by b+ - b-; // (b): replace |b| by b+ + b-; // (c): (implicit) -> b+ >= 0; // (d): (implicit) -> b- >= 0

let W = 600; let p1 = W/3; let p2 = W/3*2;

let w1 = 200; let w2 = 200;

let sep = 20;

let N = W * 2; let mind12 = (w1 + w2)/2+sep;

let model = { variables: { 'I1': { 'I1:max': 1, 'd12:def': -1, 'b1_def': -1, }, 'I2': { 'I2:max': 1, 'd12:def': 1, 'b2_def': -1, }, 'd12': { 'd12:def': 1, 'd12:min': 1, 'd12:max': 1, }, 'bin': { 'd12:min': N, 'd12:max': N, }, 'b1_pos': { 'b1_def': 1, 'bndOpt': 1, }, 'b1_neg': { 'b1_def': -1, 'bndOpt': 1, }, 'b2_pos': { 'b2_def': 1, 'bndOpt': 1, }, 'b2_neg': { 'b2_def': -1, 'bndOpt': 1, },

}, constraints: { 'I1:max': { max: W - w1 }, 'I2:max': { max: W - w2 }, 'd12:def': { equal: (w1 - w2)/2 }, 'd12:min': { min: mind12 }, 'd12:max': { max: N-mind12 }, 'b1_def': { equal: w1/2 - p1 }, 'b2_def': { equal: w2/2 - p2 }, }, binaries: { 'bin': 1 }, unrestricted: { 'd12': 1, }, optimize: 'bndOpt', opType: 'min', };

let result = solver.Solve(model); console.log(JSON.stringify(result));

// result: // {"feasible":true,"result":420,"bounded":true,"isIntegral":true,"b2_neg":120, // "I1":400,"b1_pos":300,"I2":180,"d12":220} // so |b1| + |b2| = 300 + 120 = 420 // this is because bin = 0

// expected result: // {"feasible":true,"result":20,"bounded":true,"isIntegral":true, // "I1":80,"d12":220,"I2":300,"b1_neg":20 ,"bin":1} // so |b1| + |b2| = 20 + 0 = 20 which is OK!