Re: Solver delivers wrong answer when 2 constraints are close
Heinrich Schuchardt <[email protected]> Thu, 4 Mar 2021 17:47:08 +0100
| Newsgroups | gmane.comp.gnu.glpk |
|---|---|
| Message-ID | <[email protected]> |
On 3/4/21 4:44 PM, Antti Lehtila wrote: > Hi, > > I think it works fully as documented, and so *per design*. Singleton > rows are treated as column bounds by the preprocessor. See documentation > for *npp_implied_lower*: > *--------------- > * Processing implied column lower bound l'[q] includes the following > * cases: > * > * 1) if l'[q] < l[q] + eps, implied lower bound is redundant; > * > * 2) if l[q] + eps <= l[q] <= u[q] + eps, current column lower bound In this line an apostrophe is missing. 2) if l[q] + eps <= l'[q] <= u[q] + eps, current column lower bound > * l[q] can be strengthened by replacing it with l'[q]. If in this > * case new column lower bound becomes close to current column upper > * bound u[q], the column can be fixed on its upper bound; It is this strengthening that fails: src/npp/npp3.c:567 eps = (q->is_int ? 1e-3 : 1e-3 + 1e-8 * fabs(q->lb)); Set eps to 1E-5 and you are fine. Or run with --nopresol. @Andrew: Shouldn't 1E-5 be good enough? Why do we need eps > 0? Best regards. Heinrich > * > * 3) if l'[q] > u[q] + eps, implied lower bound violates current > * column upper bound u[q], in which case the problem has no primal > * feasible solution. */ > *--------------- > The lower bound can have only a single value, but if you define multiple > values for a column lower bound, they must of course be processed in > some order. In this case, the lower bound is first defined l(q)=0, then > l'(q)=1, and finally l'(q)=1.0001. The third value for the bound is thus > considered *redundant*, as per design, and so the second value l(q)=1 > remains in effect. This is because *eps* is defined as 1e-3 + 1e-6 * > fabs(q->lb)). > > I guess it may be a considered a design flaw, but I think it should not > be called a bug, as it is working as designed and documented. Besides, > I think one should use the Bounds section for bounds, instead of using > multiple constraints for defining a single lower bound. > > Best, > Antti > _______________________ > On 04.03.2021 11:38, Domingo Alvarez Duarte wrote: >> >> Testing this problem I discover that if we change the order of >> constraint declarations it seems to give the expected answer as stated >> by Thiago (what I think could be another bug). >> >> ==== >> >> /param min_bound default 0;/ >> /var x >= 0; >> >> minimize y: x;/ >> * >> */*s.t. PART_MIN_X: x >= 1 + min_bound;* >> / >> /*s.t. LIM_INF_X: x >= 1; >> * >> / >> /solve; >> display min_bound; >> display x; # EXPECTED RESULT: X == 1.0001 >> >> data; >> param min_bound := 1e-4; >> end;/ >> >> ==== >> >> Output: >> >> ==== >> >> x.val = 1.0001 >> >> ==== >> >> On 3/3/21 19:19, Thiago Neves wrote: >>> Hi. >>> I've found a strange behaviour in glpk which I don't know how to fix >>> nor how to contour it. It seems like GLPK can't distinguish >>> constraints that differs from about 1e-4. >>> >>> Follows simple examples that explain and reproduce the problem.** >>> * >>> * >>> *The first model gives the desired answer (x = 1.0001):* >>> / >>> param min_bound default 0;/ >>> /var x >= 0; >>> >>> minimize y: x;/ >>> /* >>> s.t. PART_MIN_X: x >= 1 + min_bound;* >>> >>> solve; >>> display min_bound; >>> display x; # EXPECTED RESULT: X == 1.0001 >>> >>> data; >>> param min_bound := 1e-4; >>> end; >>> / >>> /_____________________________________/ >>> /OUTPUT:/ >>> /x.val = 1.0001/ >>> /_____________________________________ / >>> >>> *Now, if I add a second constraint "close" to the first one, the >>> solver will deliver an answer that is actually infeasible:* >>> >>> /param min_bound default 0;/ >>> /var x >= 0; >>> >>> minimize y: x;/ >>> >>> *s.t. LIM_INF_X: x >= 1; >>> >>> */*s.t. PART_MIN_X: x >= 1 + min_bound;* >>> >>> solve; >>> display min_bound; >>> display x; # EXPECTED RESULT: X == 1.0001 >>> >>> data; >>> param min_bound := 1e-4; >>> end;/ >>> /_____________________________________/ >>> /OUTPUT:/ >>> x.val = 1 >>> /_____________________________________ / >>> >>> *If I change the "min_bound" parameter to 1e-2, the second model >>> works as expected (x = 1.01):* >>> >>> /param min_bound default 0;/ >>> / >>> / >>> /var x >= 0; >>> >>> minimize y: x;/ >>> * >>> * >>> *s.t. LIM_INF_X: x >= 1; >>> >>> */*s.t. PART_MIN_X: x >= 1 + min_bound;* >>> >>> solve;/ >>> / >>> display x; # EXPECTED RESULT: X == 1.01 >>> >>> data; >>> param min_bound := 1e-2; >>> end;/ >>> /_____________________________________/ >>> /OUTPUT:/ >>> x.val = 1.01 >>> /_____________________________________ / >>> / >>> / >>> >>> Att, >>> >>> *Thiago H. Neves* >>> (31) 98608-0666 >>> > >