qcp01.gms : Test of correctness for levels and marginals of QCP

Description

Test of correctness of the levels and marginals returned.
We have QP terms in the objective only - all QCP solvers accept this.
All cases are considered, e.g.
  1) =L=, =G=, =E= constraints (should we add =N=?)
  2) variables at lower and upper bound, and not at bound
  3) min [convex obj] or max [concave obj]
  4) special attention paid to the form of the obj. constraint, i.e.
     cz * z = xQx + cx + b where cz and b take different values


Small Model of Type : QCP


Category : GAMS Test library


Main file : qcp01.gms

$title Test of correctness for levels & marginals of QCP (QCP01,SEQ=74)
$onText
Test of correctness of the levels and marginals returned.
We have QP terms in the objective only - all QCP solvers accept this.
All cases are considered, e.g.
  1) =L=, =G=, =E= constraints (should we add =N=?)
  2) variables at lower and upper bound, and not at bound
  3) min [convex obj] or max [concave obj]
  4) special attention paid to the form of the obj. constraint, i.e.
     cz * z = xQx + cx + b where cz and b take different values
$offText

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

scalar failed / 0 /;
$escape =
$echo if{%=1, display '%=1 failed', '%=2'; failed=1}; > gtest.gms
$escape %

set J / j1 * j7 /;
set GT / gt1 * gt2 /;
set LT / lt1 * lt2 /;
set EQ / eq1 /;

scalars
    cz,
    cb;

parameters
    c(J) / j1   0
           j2   0
           j3   1
           j4   2
           j5   -1
           j6   -1
           j7   3 /
    bgt(GT) /
           gt1  2
           gt2  4 /,
    blt(LT) /
           lt1  -17
           lt2  10 /,
    beq(EQ) /
           eq1  9 /;

table Agt(GT,J)
        j1      j2
gt1     1       1
gt2     4       1 ;

table Alt(LT,J)
        j3      j4
lt1     -6      1
lt2     1       2 ;

parameter Aeq(EQ,J);
Aeq('eq1',j)$(ord(j) le 7) = 1;


variable
    x(J)
    z;

* these bounds should never be active - but they help the global solvers
x.lo(J) = -2;
x.up(J) =  5;

* these are active and tested to be so
x.lo('j5') = 1;
x.up('j6') = 3;

equations
    gte(GT),
    lte(LT),
    eqe(EQ),
    obj;

obj..   cz*z =E= cb + sum{J,c(J)*x(J)}
         + sqr(x('j1')) + sqr(x('j2')) - x('j1')*x('j2')
         + sqr(x('j3')-x('j4'))
         + sqr(x('j5')+1) + sqr(x('j6')-4)
         + sqr(x('j7')-1);
gte(GT)..  sum{J, Agt(GT,J)*x(J)} =G= bgt(GT);
lte(LT)..  sum{J, Alt(LT,J)*x(J)} =L= blt(LT);
eqe(EQ)..  sum{J, Aeq(EQ,J)*x(J)} =E= beq(EQ);

model m / all /;

set czvals 'obj multipliers' /
'cz=1',
'cz=0.5'
'cz=3'
'cz=-1'
'cz=-0.5'
'cz=-3'
/;
parameter czv(czvals) /
'cz=1'          1
'cz=0.5'        0.5
'cz=3'          3
'cz=-1'         -1
'cz=-0.5'       -0.5
'cz=-3'         -3
/;

set cbvals 'obj constants' /
'cb=0'
'cb=2'
'cb=-2'
/;
parameter cbv(cbvals) /
'cb=0'          0
'cb=2'          2
'cb=-2'         -2
/;

scalars
    isMin   /    0 /,
    tol     /    %TESTTOL% /,
    obj_l   /    0.0 /
    obj_m   /    1.0 /
    objval  /   12.0 /;

parameters
   x_l(J)    / j1       1.0
               j2       1.0
               j3       3.0
               j4       1.0
               j5       1.0
               j6       3.0
               j7       -1.0 /
   x_m(J)    / j1       0.0
               j2       0.0
               j3       0.0
               j4       0.0
               j5       4.0
               j6       -2.0
               j7       0.0 /
   gte_l(GT) / gt1      2.0
               gt2      5.0 /
   gte_m(GT) / gt1      2.0
               gt2      0.0 /
   lte_l(LT) / lt1      -17.0
               lt2      5.0 /
   lte_m(LT) / lt1      -1.0
               lt2      0.0 /
   eqe_l(EQ) / eq1      9.0 /
   eqe_m(EQ) / eq1      -1.0 /;

loop {czvals$[ord(czvals) <= INF],
 cz = czv(czvals);
 loop {cbvals$[ord(cbvals) <= INF],
  cb = cbv(cbvals);
  if {(cz > 0),
    isMin = 1;
    solve m using %MTYPE% min z;
  else
    isMin = -1;
    solve m using %MTYPE% max z;
  };
  display m.solvestat, m.modelstat;
  abort.noError$[slowOK and %solveStat.resourceInterrupt% = m.solvestat] 'Solve too slow';
$ batInclude gtest "( m.solvestat <> %solveStat.normalCompletion% or (m.modelstat > %modelStat.locallyOptimal% and m.modelstat <> %modelStat.feasibleSolution%))" "wrong status codes"

$ batInclude gtest "(abs(cz*z.l-cb-objval) > tol)"             "bad z.l"
$ batInclude gtest "(abs(obj.l-cb) > tol)"                     "bad obj.l"
$ batInclude gtest "(smax(J, abs(x.l(j)-x_l(j))) > tol)"       "bad x.l"
$ batInclude gtest "(smax(GT,abs(gte.l(GT)-gte_l(GT))) > tol)" "bad gte.l"
$ batInclude gtest "(smax(LT,abs(lte.l(LT)-lte_l(LT))) > tol)" "bad lte.l"
$ batInclude gtest "(smax(EQ,abs(eqe.l(EQ)-eqe_l(EQ))) > tol)" "bad eqe.l"

  if {mchecks,
$   batInclude gtest "(abs(z.m) > tol)"                             "bad z.m"
$   batInclude gtest "(abs(cz*obj.m-obj_m) > tol)"                  "bad obj.m"
$   batInclude gtest "(smax(J, abs(cz*x.m(j)-x_m(j))) > tol)"       "bad x.m"
$   batInclude gtest "(smax(GT,abs(cz*gte.m(GT)-gte_m(GT))) > tol)" "bad gte.m"
$   batInclude gtest "(smax(LT,abs(cz*lte.m(LT)-lte_m(LT))) > tol)" "bad lte.m"
$   batInclude gtest "(smax(EQ,abs(cz*eqe.m(EQ)-eqe_m(EQ))) > tol)" "bad eqe.m"
  };

$if set doscalar
  if (failed, option %MTYPE%=convert; if {(cz > 0), solve m using %MTYPE% min z; else solve m using %MTYPE% max z;})
  abort$failed 'test failed', cz, cb;

 };
};