implset1.gms : Test for Implicit Set Definition

Description

With GAMS 25.2 we introduced the new feature called "Implicit Set Definition
(or: Domain Defining Symbol Declarations)".
Here we test for the expected behavior.

Contributor: Lutz Westermann, October 2018


Small Model of Type : GAMS


Category : GAMS Test library


Main file : implset1.gms

$title 'Test for Implicit Set Definition' (IMPLSET1,SEQ=788)

$onText
With GAMS 25.2 we introduced the new feature called "Implicit Set Definition
(or: Domain Defining Symbol Declarations)".
Here we test for the expected behavior.

Contributor: Lutz Westermann, October 2018
$offText


* Start with simple example from documentation
$onEcho > test.gms
Set
   i(*) 'canning plants'
   j(*) 'markets';

Table d(i<,j<) 'distance in thousands of miles'
              new-york  chicago  topeka
   seattle         2.5      1.7     1.8
   san-diego       2.5      1.8     1.4;

Alias(u,*);
Set iWant / seattle,  san-diego /
    jWant / new-york, chicago,  topeka /
    iTest(u)
    jTest(u);

iTest(u) = iWant(u) xor i(u);
abort$card(iTest) iTest;

jTest(u) = jWant(u) xor j(u);
abort$card(jTest) jTest;
$offEcho

$call gams test.gms lo=%GAMS.lo% gdx d
$ifE errorLevel<>0 $abort Problem in line %system.line%


* Another example from documentation using multiple symbols defining one set
$onEcho > test.gms
Set
   food(*)
   fruits(food<)    / apple, orange       /
$onMulti
   vegetable(food<) / carrot, cauliflower /
   meat(food<)      / beef, pork          /;

Alias(u,*);
Set foodWant / apple, orange, carrot, cauliflower, beef, pork /
    foodTest(u);

foodTest(u) = foodWant(u) xor food(u);
abort$card(foodTest) foodTest;
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel<>0 $abort Problem in line %system.line%


* Similar to the previous example, but with $onMultiR we just keep the last definition
$onEcho > test.gms
Set
   food(*)
   fruits(food<)    / apple, orange       /
$onMultiR
   vegetable(food<) / carrot, cauliflower /
   meat(food<)      / beef, pork          /;

Alias(u,*);
Set foodWant / beef, pork /
    foodTest(u);

foodTest(u) = foodWant(u) xor food(u);
abort$card(foodTest) foodTest;
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel<>0 $abort Problem in line %system.line%


* With onMulti, the implicitly defined set can also be prefilled
$onEcho > test.gms
Set
   food(*)          / apple, orange       /
$onMulti
   vegetable(food<) / carrot, cauliflower /
   meat(food<)      / beef, pork          /;

Alias(u,*);
Set foodWant / apple, orange, carrot, cauliflower, beef, pork /
    foodTest(u);

foodTest(u) = foodWant(u) xor food(u);
abort$card(foodTest) foodTest;
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel<>0 $abort Problem in line %system.line%


* A set could also be empty after being implicitly defined, but it should still be assigned in this case
$onEcho > test.gms
Set
   i;

Parameter
   p(i<) / i1 0 /;

Display i;
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel<>0 $abort Problem in line %system.line%


* Simple example with $load
$onEcho > test.gms
Set
   i(*) 'canning plants'
   j(*) 'markets';

Parameter d(i<,j<) 'distance in thousands of miles';

$gdxIn d.gdx
$load d

Alias(u,*);
Set iWant / seattle,  san-diego /
    jWant / new-york, chicago,  topeka /
    iTest(u)
    jTest(u);

iTest(u) = iWant(u) xor i(u);
abort$card(iTest) iTest;

jTest(u) = jWant(u) xor j(u);
abort$card(jTest) jTest;
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel<>0 $abort Problem in line %system.line%

* Example with $load exercising filtered loading
$onEcho > test.gms
Set ab / a1.b1
         a2.b1
               a3.b2 /;
$gdxout ab.gdx
$unload ab
$gdxout

Set a /a1,a2/, b(*), c(*),
    xx(a,b<);

$gdxin ab.gdx
$load xx=ab c<ab.dim2

Alias(u,*);
Set bWant / b1     /
    cWant / b1, b2 /
    bTest(u)
    cTest(u);

bTest(u) = bWant(u) xor b(u);
abort$card(bTest) bTest;

cTest(u) = cWant(u) xor c(u);
abort$card(cTest) cTest;
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel<>0 $abort Problem in line %system.line%

* Also works with variables
$onEcho > test.gms
Set
   i(*) 'canning plants'
   j(*) 'markets';

Variable Table d(i<,j<)
                   l
seattle.new-york  300
seattle.chicago   400
seattle.topeka    500
san-diego.chicago 600 ;

Alias(u,*);
Set iWant / seattle,  san-diego /
    jWant / new-york, chicago,  topeka /
    iTest(u)
    jTest(u);

iTest(u) = iWant(u) xor i(u);
abort$card(iTest) iTest;

jTest(u) = jWant(u) xor j(u);
abort$card(jTest) jTest;
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel<>0 $abort Problem in line %system.line%


* On the major platforms (Windows, Linux, Mac), GMSPYTHONLIB gets automatically set 
* to use the internal Python installation in sysdir/GMSPython.
$if not setEnv GMSPYTHONLIB $abort.noError Embedded code Python not ready to be used
$log --- Using Python library %sysEnv.GMSPYTHONLIB%

* Simple example with embeddedCode
$onEcho > test.gms
Set
   i(*) 'canning plants'
   j(*) 'markets';

Parameter d(i<,j<) 'distance in thousands of miles';

$onEmbeddedcode python:
gams.set('d',[('seattle',  'new-york',2.5),('seattle',  'chicago',1.7),('seattle',  'topeka',1.8),
              ('san-diego','new-york',2.5),('san-diego','chicago',1.8),('san-diego','topeka',1.4)])
$offEmbeddedcode d


Alias(u,*);
Set iWant / seattle,  san-diego /
    jWant / new-york, chicago,  topeka /
    iTest(u)
    jTest(u);

iTest(u) = iWant(u) xor i(u);
abort$card(iTest) iTest;

jTest(u) = jWant(u) xor j(u);
abort$card(jTest) jTest;
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel<>0 $abort Problem in line %system.line%

* Example with embedded Code exercising filtered loading
$onEcho > test.gms
Set a /a1,a2/, b(*), c(*);
Set xx(a,b<);

$onEmbeddedCode Python:
gams.set('xx',[('a1','b1'),('a2','b1'),('a3','b2')])
$offEmbeddedCode xx c<xx.dim2

Alias(u,*);
Set bWant / b1 /
    cWant / b1, b2 /
    bTest(u)
    cTest(u);

bTest(u) = bWant(u) xor b(u);
abort$card(bTest) bTest;

cTest(u) = cWant(u) xor c(u);
abort$card(cTest) cTest;
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel<>0 $abort Problem in line %system.line%

* Simple example with embeddedCode - at execution time, this is expected to fail
$onEcho > test.gms
Set
   i(*) 'canning plants'
   j(*) 'markets';

Parameter d(i<,j<) 'distance in thousands of miles';

Embeddedcode python:
gams.set('d',[('seattle',  'new-york',2.5),('seattle',  'chicago',1.7),('seattle',  'topeka',1.8),
              ('san-diego','new-york',2.5),('san-diego','chicago',1.8),('san-diego','topeka',1.4)])
endEmbeddedcode d


Alias(u,*);
Set iWant / seattle,  san-diego /
    jWant / new-york, chicago,  topeka /
    iTest(u)
    jTest(u);

iTest(u) = iWant(u) xor i(u);
abort$card(iTest) iTest;

jTest(u) = jWant(u) xor j(u);
abort$card(jTest) jTest;
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel=0 $abort Problem in line %system.line%

$label noEmbeddedPython

* Temporary problem reported by Michael
$onEcho > test.gms
Set   p, xs, ys;
Table tab(p<,xs<,ys<) 
        y1  y2  y3  y4  y5
p1.x1   1   1   1   1   1   
;
parameter pend(p) /p1 2/;
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel<>0 $abort Problem in line %system.line%

* Merging to start of existing data should not lead to out-of-order data (which would lead to an error when unloading to GDX), see #4340
$onEcho > test.gms
Alias(u,*);
Set t1 / 2021*2024/;
Set t2 / 2022 /;
$onMulti
Set t(t2<) / 2021 /
    t2Want / 2021, 2022 /
    t2Test(u);

t2Test(u) = t2Want(u) xor t2(u);
abort$card(t2Test) t2Test;

execute_unload 'all.gdx';
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel<>0 $abort Problem in line %system.line%

* Merging first UEL to start of existing data with first UEL should not lead to duplicate UEL (which would lead to an error when unloading to GDX), see #3657
$onEcho > test.gms
Set
   i 'canning plants' / seattle, kk /;

$onmulti
Alias(u,*);
Parameter
   a(i<) 'capacity of plant i in cases'
        / seattle    350/;

Set iWant / seattle, kk /
    iTest(u);

iTest(u) = iWant(u) xor i(u);
abort$card(iTest) iTest;

execute_unload 'all.gdx';
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel<>0 $abort Problem in line %system.line%

* The following tests expect an error
* Redefinition should be wrong by default
$onEcho > test.gms
Set
   food(*)          / apple, orange       /
   vegetable(food<) / carrot, cauliflower /
   meat(food<)      / beef, pork          /;
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel=0 $abort Expected problem in line %system.line%


* Implicit definition of domain set cannot be applied to the universe
$onEcho > test.gms
Alias (food,*);
Set
   meat(food<)      / beef, pork          /;
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel=0 $abort Expected problem in line %system.line%


* Implicit definition of domain set cannot be applied, if domain is identical to the symbol
$onEcho > test.gms
Set
   meat(meat<)      / beef, pork          /;
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel=0 $abort Expected problem in line %system.line%


* Implicit definition of domain set cannot be applied, if domain is a subset
$onEcho > test.gms
Set
   u
   food(u)
   meat(food<)      / beef, pork          /;
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel=0 $abort Expected problem in line %system.line%


* Do not allow two mismatching declaration
$onEcho > test.gms
Set
   food
   meat(food )
   meat(food<);
$offEcho

$call gams test.gms lo=%GAMS.lo%
$ifE errorLevel=0 $abort Expected problem in line %system.line%