GLPK.js no primal feasible solution when a solution exists - javascript
I am using the glpk.js library in an Angular application to solve an ILP problem. I have been using the library for some time now and it usually works well. I have encountered similar issues in the past, but I was able to sidestep them without finding out why they occurred. It might very well be the case, that I am not using the library correctly as their documentation is quite lacking.
I construct a "base" ILP problem and then I iterate over some array, construct additional constraints depending on each element of my array and try to solve the base ILP with the new constrains for each element.
I know there is a solution for each of the ILPs, but the solver returns PROBLEM HAS NO PRIMAL FEASIBLE SOLUTION for all but one of the ILPs.
My base ILP (in human readable format):
p0 >= 0
p1 >= 0
p2 >= 0
p3 >= 0
p4 >= 0
p5 >= 0
p6 >= 0
p7 >= 0
p0 +p1 +p2 +p3 +p4 +p5 +p6 +p7 >= 1
p1 -p0 -rise0 = 0
p2 +p3 -p1 -rise1 = 0
p4 -p2 -rise2 = 0
p6 -p4 -rise3 = 0
p10 -p6 -p5 -rise4 = 0
p5 -p3 -rise5 = 0
where the objective function is to minimise the sum of the p-variables.
when I apply the following additional constraints, the solver returns a solution (p10 = 1, all other p = 0):
rise0 = 0
rise1 = 0
rise2 = 0
rise3 = 0
rise4 = 1
rise5 = 0
p0 = 0
when I apply the following additional constraints, the solver returns no solution, even if p0 = 1, all other p = 0, solves the ILP:
rise0 = -1
rise1 = 0
rise2 = 0
rise3 = 0
rise4 = 0
rise5 = 0
p0 = 1
all the other sets of constrains also contain some rise with a negative value, which seems to cause the issue.
I am using the following configuration as input to the solver (JSON for the second example ILP):
{
"name":"p0",
"objective": {
"direction":1,
"name":"region",
"vars": [
{"name":"p0","coef":1},
{"name":"p1","coef":1},
{"name":"p2","coef":1},
{"name":"p3","coef":1},
{"name":"p4","coef":1},
{"name":"p5","coef":1},
{"name":"p6","coef":1},
{"name":"p7","coef":1}
]
},
"subjectTo": [
{"name":"c0","vars":[{"name":"p0","coef":1}],"bnds":{"type":2,"ub":0,"lb":0}},
{"name":"c1","vars":[{"name":"p1","coef":1}],"bnds":{"type":2,"ub":0,"lb":0}},
{"name":"c2","vars":[{"name":"p2","coef":1}],"bnds":{"type":2,"ub":0,"lb":0}},
{"name":"c3","vars":[{"name":"p3","coef":1}],"bnds":{"type":2,"ub":0,"lb":0}},
{"name":"c4","vars":[{"name":"p4","coef":1}],"bnds":{"type":2,"ub":0,"lb":0}},
{"name":"c5","vars":[{"name":"p5","coef":1}],"bnds":{"type":2,"ub":0,"lb":0}},
{"name":"c6","vars":[{"name":"p6","coef":1}],"bnds":{"type":2,"ub":0,"lb":0}},
{"name":"c7","vars":[{"name":"p7","coef":1}],"bnds":{"type":2,"ub":0,"lb":0}},
{"name":"c8","vars":[{"name":"p0","coef":1},{"name":"p1","coef":1},{"name":"p2","coef":1},{"name":"p3","coef":1},{"name":"p4","coef":1},{"name":"p5","coef":1},{"name":"p6","coef":1},{"name":"p7","coef":1}],"bnds":{"type":2,"ub":0,"lb":1}},
{"name":"c9","vars":[{"name":"p1","coef":1},{"name":"p0","coef":-1},{"name":"rise0","coef":-1}],"bnds":{"type":5,"ub":0,"lb":0}},
{"name":"c10","vars":[{"name":"p2","coef":1},{"name":"p3","coef":1},{"name":"p1","coef":-1},{"name":"rise1","coef":-1}],"bnds":{"type":5,"ub":0,"lb":0}},
{"name":"c11","vars":[{"name":"p4","coef":1},{"name":"p2","coef":-1},{"name":"rise2","coef":-1}],"bnds":{"type":5,"ub":0,"lb":0}},
{"name":"c12","vars":[{"name":"p6","coef":1},{"name":"p4","coef":-1},{"name":"rise3","coef":-1}],"bnds":{"type":5,"ub":0,"lb":0}},
{"name":"c13","vars":[{"name":"p7","coef":1},{"name":"p6","coef":-1},{"name":"p5","coef":-1},{"name":"rise4","coef":-1}],"bnds":{"type":5,"ub":0,"lb":0}},
{"name":"c14","vars":[{"name":"p5","coef":1},{"name":"p3","coef":-1},{"name":"rise5","coef":-1}],"bnds":{"type":5,"ub":0,"lb":0}},
{"name":"c15","vars":[{"name":"rise0","coef":1}],"bnds":{"type":5,"ub":-1,"lb":-1}},
{"name":"c16","vars":[{"name":"rise1","coef":1}],"bnds":{"type":5,"ub":0,"lb":0}},
{"name":"c17","vars":[{"name":"rise5","coef":1}],"bnds":{"type":5,"ub":0,"lb":0}},
{"name":"c18","vars":[{"name":"rise2","coef":1}],"bnds":{"type":5,"ub":0,"lb":0}},
{"name":"c19","vars":[{"name":"rise3","coef":1}],"bnds":{"type":5,"ub":0,"lb":0}},
{"name":"c20","vars":[{"name":"rise4","coef":1}],"bnds":{"type":5,"ub":0,"lb":0}},
{"name":"c21","vars":[{"name":"p0","coef":1}],"bnds":{"type":5,"ub":1,"lb":1}}
],
"binaries":[],
"generals": ["p0","p1","p2","p3","p4","p5","p6","p7","rise0","rise1","rise2","rise3","rise4","rise5"]
}
I assumed all integers (including negative) are allowed as solutions. But the only logical explanation to my problem seems to be that this is not the case. How can I enable negative integers as possible solutions?
I should have just researched the library more. There is an issue in the repository of the library that answers my question.
It really is the case that variables are bound to non-negative integers.
Variables with negative values can be expressed by splitting them into a positive and a negative part.
In my case it means I have to create a rise0plus and a rise0minus variable and modify my constrains as follows (for each rise variable):
p1 - p0 -rise0plus +rise0minus = 0
...
rise0plus -rise0minus = -1
Related
mathematical value transformation / switch behavior in js
I use common functions like map() and clamp() to transform values. I wonder if there is a similar mathematical function which lets me translate a rising value to an on and off state (0 and 1). Could a square wave help? For more context: I want the value to be 1 whilst something is animating and 0 after it finished. The input value is clamped, the functionality of the function I'm looking for is like a switch. It would be a substitute for a complex if statement. Executed in a loop I'm trying to save resources by not using performance heavy if statements. Looking forward to your input!
This is what I came up with in the end. Not sure if this is helpful to anyone else. It converts any value between 0 and 1 to 1. But if the input value is equal to 0 or the input value is equal to 1, the function will return 0 as well. Resulting in the loopback / switch behavior. It returns 1 only whilst a value is progressing. Hope this makes sense and is correct. Happy to hear your thoughts. Also happy to hear some further thoughts on if such a function is more performant than an if-statement. In the end I had to solve this to prove to myself that it's possible to do with math. (of course it is):) const loopback = (i, m = 100) => { //returns 1 while value is progressing, returns 0 if value is 0 or 1 //based on triangle wave function: https://discourse.processing.org/t/sawtooth-wave-algorithm/27433 i = clamp(i) //normalize value to 0-1 return Math.ceil(Math.abs((i*(m)) % (m)) / m) } const clamp = (number, min = 0, max = 1) => { return Math.max(min, Math.min(number, max)); } //in my usecase, this is an alternative to following condition: /*if(i >= 1 || i <= 0) { return 0; } else { return 1; }
Portfolio Optimization Constraints wrong using quadprog in JavaScript
I cannot figure out what I am doing wrong with this portfolio optimization (find optimal weights) using quadprog in numeric.js My portfolio constraints are simple: weights should sum up to 1 and all weights (for each of the 3 assets) should be between 0 and 1 (no short selling, no leverage). Constraints are not recognized and weights get very high (and also negative). var constraintsmatrix = [[0,0,0,0], [1,0,1,0], [1,0,0,0]]; var covmatrix = [[0.00020817,0.00016281,0.00009747],[0.00016281,0.00026680,0.00009912],[0.00009747,0.00009912,0.00019958]]; var returnsmatrix = [0.1,0.05,0.1]; var bvec = 1; // [1,0,0,0,0,0,0,1,1,1]; var result = numeric.solveQP(covmatrix, returnsmatrix, constraintsmatrix, bvec); Any hint appreciated. Thanks
I believe your constraints are not correctly specified and the rhs is not passed on. We want the following constraints (equality first): x1+x2+x3 = 1 x1 >= 0 x2 >= 0 x3 >= 0 This corresponds to A=[[1,1,0,0],[1,0,1,0],[1,0,0,1]] b=[1,0,0,0] Here is what I get: Note that the objective of this model is 0.5*x'Dx-d'x. Also note I pass on 5 arguments to solveQP.
Decomposing a value into results of powers of two
Is it possible to get the integers that, being results of powers of two, forms a value? Example: 129 resolves [1, 128] 77 resolves [1, 4, 8, 64] I already thought about using Math.log and doing also a foreach with a bitwise comparator. Is any other more beautiful solution?
The easiest way is to use a single bit value, starting with 1 and shift that bit 'left' until its value is greater than the value to check, comparing each bit step bitwise with the value. The bits that are set can be stored in an array. function GetBits(value) { var b = 1; var res = []; while (b <= value) { if (b & value) res.push(b); b <<= 1; } return res; } console.log(GetBits(129)); console.log(GetBits(77)); console.log(GetBits(255)); Since shifting the bit can be seen as a power of 2, you can push the current bit value directly into the result array. Example
You can adapt solutions from other languages to javascript. In this SO question you'll find some ways of solving the problem using Java (you can choose the one you find more elegant). decomposing a value into powers of two I adapted one of those answers to javascript and come up with this code: var powers = [], power = 0, n = 129;// Gives [1,128] as output. while (n != 0) { if ((n & 1) != 0) { powers.push(1 << power); } ++power; n >>>= 1; } console.log(powers); Fiddle
Find the largest power of two contained in the number. Subtract from the original number and Add it to list. Decrement the exponent and check if new 2's power is less than the number. If less then subtract it from the original number and add it to list. Otherwise go to step 3. Exit when your number comes to 0.
I am thinking of creating a list of all power of 2 numbers <= your number, then use an addition- subtraction algorithm to find out the group of correct numbers. For example number 77: the group of factors is { 1,2,4,8,16,32,64} [ 64 is the greatest power of 2 less than or equal 77] An algorithm that continuously subtract the greatest number less than or equal to your number from the group you just created, until you get zero. 77-64 = 13 ==> [64] 13-8 = 7 ==> [8] 7-4 = 3 ==> [4] 3-2 = 1 ==> [2] 1-1 = 0 ==> [1] Hope you understand my algorithm, pardo my bad english.
function getBits(val, factor) { factor = factor || 1; if(val) { return (val % 2 ? [factor] : []).concat(getBits(val>>1, factor*2)) } return []; } alert(getBits(77));
Replace modulus by function
When I try to do 8067 % 80.67 I get 80.66999999999983, instead of 0 beacuse of known floating point javascript behaviour. So I went and made a function for this, to avoid floating point javascript errors. function math(a, b) { var left = Math.abs(a), times = 1, abs = a >= 0 ? 1 : -1; while (Math.abs(a) >= b * times) { left -= b; times++; } return (a - (b * (times - 1))) * abs; } http://jsfiddle.net/s5w3C/ So my question is: is this usefull, ie a good tool to use instead of %? is there cases where this will also give falsy results like the modulus % oprator. I am looking for a tools to calculate % consistently.
I didn't really inspect the algorithm for correctness, but if you care about efficiency, this is a bad idea. Basically, the larger the input, the slower your code will execute.
I think any fix will only work to a certain level of accuracy and for certain sized numbers. Perhaps something like the following will be sufficient: function nearlyMod(a, b) { var precision = ('' + b).split('.').length; var estimate = (a % b).toFixed(precision); return estimate == b ? 0 : +estimate; } console.log(nearlyMod(8067, 80.66)); // 1 console.log(nearlyMod(8067, 80.67)); // 0 console.log(nearlyMod(8067, 80.68)); // 79.68 It tests if the result is an even divisor within the precision of the original number. If so, it returns 0, otherwise it returns a number to the same precision (which may or may not be what you want). The result is always a number (the value returned from toFixed is a string, hence +estimate). A better name might be "roundedMod" or similar.
check whether the number is nearly equal javascript
I want to know whether it is possible? Let Suppose: var a = 2592; var b = 2584; if(a nearly equal to b) { // do something }
Like so. var diff = Math.abs( a - b ); if( diff > 50 ) { console.log('diff greater than 50'); } That would compare if the absolute difference is greater than 50 using Math.abs and simple comparison.
Here's the old school way to do it... approxeq = function(v1, v2, epsilon) { if (epsilon == null) { epsilon = 0.001; } return Math.abs(v1 - v2) < epsilon; }; so, approxeq(5,5.000001) is true, while approxeq(5,5.1) is false. You can adjust pass in epsilons explicitly to suit your needs. One part in a thousand usually covers my javascript roundoff issues.
var ratio = 0; if ( a > b) { ratio = b / a; } else { ratio = a / b; } if (ratio > 0.90) { //do something }
One line Es6 way version of The Software Barbarian: const approxeq = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) <= epsilon; console.log(approxeq(3.33333, 3.33322)); // true console.log(approxeq(2.3, 2.33322)); // false console.log(approxeq(3, 4, 1)); // true I changed it to include the number in the margin. So with an epsilon margin of 1 approxeq between 1 and 2 is true
Floating point comparison gets complicated in a hurry. It's not as simple as diff less than epsilon in a lot of cases. Here's an article about the subject, though not javascript specific. https://floating-point-gui.de/errors/comparison/ TLDR: When one of the numbers being compared is very close to zero, subtracting the smaller from the larger can lose digits of precision, making the diff appear smaller than it is (or zero). Very small numbers with different signs work in a weird way. Dividing by zero will cause problems. In the article is a function (java) which solves better for these cases: public static boolean nearlyEqual(float a, float b, float epsilon) { final float absA = Math.abs(a); final float absB = Math.abs(b); final float diff = Math.abs(a - b); if (a == b) { // shortcut, handles infinities return true; } else if (a == 0 || b == 0 || (absA + absB < Float.MIN_NORMAL)) { // a or b is zero or both are extremely close to it // relative error is less meaningful here return diff < (epsilon * Float.MIN_NORMAL); } else { // use relative error return diff / Math.min((absA + absB), Float.MAX_VALUE) < epsilon; } } Before you complain: Yes, that's Java, so you'd have to rewrite it in Javascript. It's just to illustrate the algorithm and it's just copied from the article. I'm still looking for a thorough solution to this problem, ideally with an NPM package so I don't have to figure this out again every time I need it. Edit: I've found a package which implements the solution from the article linked above (which has the same link in their readme). https://www.npmjs.com/package/#intocode-io/nearly-equal This will be a less error-prone solution than others shown in other answers. There are several npm packages which implement the naive solutions which have error cases near zero as described above. Make sure you look at the source before you use them.