cns11.gms : CNS model - solvable, nonsingular start point

Description

The following model has a locally unique solution as shown by
the second and third Solve. However, the Jacobian is singular in
the initial point for the first solve so some solvers will fail
to solve from this start point - they should at least report the
infeasibility.


Small Model of Type : CNS


Category : GAMS Test library


Main file : cns11.gms

$title CNS model - solvable, nonsingular start point (cns11,SEQ=101)

$onText
  The following model has a locally unique solution as shown by
  the second and third Solve. However, the Jacobian is singular in
  the initial point for the first solve so some solvers will fail
  to solve from this start point - they should at least report the
  infeasibility.
$offText

$if not set TESTTOL $set TESTTOL 1e-6
scalar tol / %TESTTOL% /;
$if not set SLOWOK $set SLOWOK 0
scalar slowOK 'slow solves are OK: just abort.noerror in this case' / %SLOWOK% /;

* there are two solutions: the obvious one (1.5,2.5) and (n1,n2)
scalars rhs1, rhs2, n1, n2;
rhs1 = exp(1.5) -    (2.5);
rhs2 =   -(1.5) + exp(2.5);
n1 = -10.544654105393;
n2 = -1.98166273645465;

variable x1, x2;
equation e1, e2;

e1 .. exp(x1) -     x2  =e= rhs1;
e2 ..    -x1  + exp(x2) =e= rhs2;

model m / all /;

*  Case 1: A singular starting point. The model may be declared singular.
x1.l = 0;  x2.l = 0;
solve m using cns;
abort.noError$[slowOK and %solveStat.resourceInterrupt% = m.solvestat] 'Solve too slow';
abort$(m.solvestat <> %solveStat.normalCompletion%) 'bad solvestat', m.solvestat;
if   { (m.modelstat = %modelStat.locallyInfeasible%),
* locally infeasible, should report a row that way
  abort$(m.numinfes < 1)                             'wrong .numinfes';
else
  abort$(m.modelstat <> %modelStat.solved%) 'bad modelstat', m.modelstat;
  abort$(abs(x1.l-1.5) > tol and abs(x1.l-n1) > tol) 'bad x1.l';
  abort$(abs(x2.l-2.5) > tol and abs(x2.l-n2) > tol) 'bad x2.l';
  abort$(abs(e1.l-rhs1) > tol)                       'bad e1.l';
  abort$(abs(e2.l-rhs2) > tol)                       'bad e2.l';
};

*  Case 2: A nonsingular starting point. The model should solve.
x1.l = 1; x2.l = 1;
solve m using cns;
abort.noError$[slowOK and %solveStat.resourceInterrupt% = m.solvestat] 'Solve too slow';
abort$(m.solvestat <> %solveStat.normalCompletion% or m.modelstat <> %modelStat.solved%)
   'bad return codes', m.solvestat, m.modelstat;
abort$(abs(x1.l-1.5) > tol and abs(x1.l-n1) > tol) 'bad x1.l';
abort$(abs(x2.l-2.5) > tol and abs(x2.l-n2) > tol) 'bad x2.l';
abort$(abs(e1.l-rhs1) > tol)                       'bad e1.l';
abort$(abs(e2.l-rhs2) > tol)                       'bad e2.l';

*  Case 3: A nonsingular starting point. The model should solve.
*          The solution may be different from the one from case 2.
x1.l = -1; x2.l = -1;
solve m using cns;
abort.noError$[slowOK and %solveStat.resourceInterrupt% = m.solvestat] 'Solve too slow';
abort$(m.solvestat <> %solveStat.normalCompletion% or m.modelstat <> %modelStat.solved%)
   'bad return codes', m.solvestat, m.modelstat;
abort$(abs(x1.l-1.5) > tol and abs(x1.l-n1) > tol) 'bad x1.l';
abort$(abs(x2.l-2.5) > tol and abs(x2.l-n2) > tol) 'bad x2.l';
abort$(abs(e1.l-rhs1) > tol)                       'bad e1.l';
abort$(abs(e2.l-rhs2) > tol)                       'bad e2.l';