caproject.gms : Test Connect agent Projection

Description

This test ensures the correctness of the Connect agent "Projection".

Contributor: Michael Bussieck, February 2022


Small Model of Type : GAMS


Category : GAMS Test library


Main file : caproject.gms

$title 'Test Connect agent Projection' (CAPROJECT,SEQ=889)

$onText
This test ensures the correctness of the Connect agent "Projection".

Contributor: Michael Bussieck, February 2022
$offText


$log --- Using Python library %sysEnv.GMSPYTHONLIB%

set i /i1*i5/;
set j /j1*j5/;
set k /k1*k5/;
set m /m1*m5,m100/;
set date /'2002,May,17', '1998,May,20', '2022,May,08', '2023,November,10', '2024,September,08'/;

set p(i, date) /
'i1'.'2002,May,17'
'i2'.'2024,September,08'
'i3'.'1998,May,20'
'i4'.'2022,May,08'
'i5'.'2023,November,10'
/;

scalar q0, p0;
parameter q2(j,i), p2(j,i);
parameter q3(k,i,j), p3(i,j,k) /
'i1'.'j2'.'k4' 0.596558144
'i2'.'j4'.'k4' 0.511448928
'i3'.'j1'.'k5' 0.045066059
'i3'.'j2'.'k4' 0.783102004
'i3'.'j3'.'k1' 0.945749415
'i3'.'j4'.'k1' 0.596462556
'i4'.'j1'.'k5' 0.607341301
'i4'.'j2'.'k2' 0.362509471
'i4'.'j5'.'k4' 0.594067961
'i5'.'j1'.'k1' 0.679854079
'i5'.'j1'.'k2' 0.506588022
'i5'.'j4'.'k4' 0.159253884
/;

parameter q4(i,j,k);
parameter p2m(m,i);
p2m(m,i) = uniformInt(0,10);
variable v0, v2(j,i);
variable v3(i,j,k), w3(k,j,i);

equation e3(i,j,k);

set t3(k,i,j), s3(i,j,k) /
'i1'.'j2'.'k4'
'i2'.'j4'.'k4'
'i3'.'j1'.'k5'
'i3'.'j2'.'k4'
'i3'.'j3'.'k1'
'i3'.'j4'.'k1'
'i4'.'j1'.'k5'
'i4'.'j2'.'k2'
'i4'.'j5'.'k4'
'i5'.'j1'.'k1' First
'i5'.'j1'.'k2' Last
'i5'.'j4'.'k4'
/;
set t2(j,i), s2(j,i);

v0.l = 0; v0.m=100;
v3.l(s3) = p3(s3); v3.scale(s3) = p3(s3);
e3.l(s3) = p3(s3);

$onEchoV > p.gms
$if %TYPE%==VAR Variable one /L 1/, two /L 2/, three /L 3/; Variable combined(*);
$if %TYPE%==EQU Equation one /L 1/, two /L 2/, three /L 3/; Equation combined(*);
$if %TYPE%==PAR Scalar   one /1/,   two /2/,   three /3/;   Parameter combined(*);
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'one'}, {'name':'two'}, {'name':'three'}]
- Projection:
    name: ['one', 'two', 'three']
    newName: combined
- GAMSWriter:
    symbols:
      - name: combined
$offEmbeddedCode combined
$offEcho
$call.checkErrorLevel gams p.gms lo=%gams.lo% --TYPE=VAR
$call.checkErrorLevel gams p.gms lo=%gams.lo% --TYPE=EQU
$call.checkErrorLevel gams p.gms lo=%gams.lo% --TYPE=PAR

$log test newName missing
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3(i,j,k)
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors
$log test name missing
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    newName: p3(i,j,k)
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors
$log test correct dim on name
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3(i,j)
    newName: p2(j,i)
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors
$log test unknown index in newName
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3(i,j,k)
    newName: p2(x,i)
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors
$log test suffix on newName
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3(i,j,k)
    newName: p2.l(j,i)
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors
$log test invalid name
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3(i,j).l
    newName: p2(j,i)
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors
$log test invalid newName
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3(i,j)
    newName: p2(j,i
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors
$log test suffix on parameter symbol
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3.l(i,j,k)
    newName: p2(j,i)
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors
$log test wrong suffix name
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v3'}]
- Projection:
    name: v3.lower(i,j,k)
    newName: p2(j,i)
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors
$log test aggregationMethod callable
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3(i,j,k)
    newName: p2(j,k)
    aggregationMethod: groups
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors
$log test aggregationMethod unknown
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3(i,j,k)
    newName: p2(j,k)
    aggregationMethod: pingpong
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors
$log test empty suffix list
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v3'}]
- Projection:
    name: v3.[](i,j,k)
    newName: p2(j,k)
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors

$log test using newName as an existing symbol
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v0'}, {'name':'p0'}]
- Projection:
    name: v0.l
    newName: p0
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors

$log test target parameter exists
$onEmbeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'},{'name':'q3'}]
- Projection:
    name: p3(i,j,k)
    newName: q3(k,i,j)
$offEmbeddedCode
$if errorFree $abort 'Expect errors'
$clearErrors

put_utility 'log' / 'test scalar variable';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v0'}]
- Projection:
    name: v0.[l,m,up,lo,scale]
    newName: v0_new
- Projection:
    name: v0.all
    newName: v0_new_all
- PythonCode:
    code: |
        data = connect.container['v0_new'].records.values.tolist()
        data_all = connect.container['v0_new_all'].records.values.tolist()
        expected = [['level', 0.0],
                    ['marginal', 100.0],
                    ['lower', float('-inf')],
                    ['upper', float('inf')],
                    ['scale', 1.0]]
        if data != expected or data_all != expected:
            raise Exception("Unexpected data while testing scalar variable")
endEmbeddedCode

put_utility 'log' / 'test count on scalar variable';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v0'}]
- Projection:
    name: v0.[l,m,up,lo,scale]
    newName: v0_new
    aggregationMethod: count
- PythonCode:
    code: |
        data = connect.container['v0_new'].records.values.tolist()
        expected = [['level', 1.0],
                    ['marginal', 1.0],
                    ['lower', 1.0],
                    ['upper', 1.0],
                    ['scale', 1.0]]
        if data != expected:
            raise Exception("Unexpected data while testing count on scalar variable")
endEmbeddedCode

put_utility 'log' / 'test count on scalar parameter';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p0'}]
- Projection:
    name: p0
    newName: p0_new
    aggregationMethod: count
- PythonCode:
    code: |
        data = connect.container['p0_new'].records.values.tolist()
        expected = [[1.0]]
        if data != expected:
            raise Exception("Unexpected data while testing count on scalar parameter")
endEmbeddedCode

put_utility 'log' / 'test parameter permutation';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3(i,j,k)
    newName: q3(k,i,j)
- GAMSWriter:
    symbols: [{'name':'q3'}]
endEmbeddedCode q3
abort$(sum((i,j,k), abs(p3(i,j,k)-q3(k,i,j)))>1e-6) 'wrong q3', p3, q3;

put_utility 'log' / 'test variable level permutation';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v3'}]
- Projection:
    name: v3.l(i,j,k)
    newName: q3(k,i,j)
- GAMSWriter:
    symbols: [{'name':'q3'}]
endEmbeddedCode q3
abort$(sum((i,j,k), abs(v3.l(i,j,k)-q3(k,i,j)))>1e-6) 'wrong q3', v3.l, q3;

put_utility 'log' / 'test variable scale permutation';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v3'}]
- Projection:
    name: v3.scale(i,j,k)
    newName: q3(k,i,j)
    aggregationMethod: null
- GAMSWriter:
    symbols: [{'name':'q3'}]
endEmbeddedCode q3
abort$(sum((s3(i,j,k)), abs(v3.scale(i,j,k)-q3(k,i,j)))>1e-6) 'wrong q3', v3.scale, q3;

put_utility 'log' / 'test equation level permutation';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'e3'}]
- Projection:
    name: e3.l(i,j,k)
    newName: q3(k,i,j)
- GAMSWriter:
    symbols: [{'name':'q3'}]
endEmbeddedCode q3
abort$(sum((i,j,k), abs(e3.l(i,j,k)-q3(k,i,j)))>1e-6) 'wrong q3', v3.l, q3;

put_utility 'log' / 'test variable permutation';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v3'}]
- Projection:
    name: v3(i,j,k)
    newName: w3(k,j,i)
- GAMSWriter:
    symbols: [{'name':'w3'}]
endEmbeddedCode w3
abort$(sum((i,j,k), abs(v3.l(i,j,k)-w3.l(k,j,i)))>1e-6) 'wrong w3.l', v3.l, w3.l;
abort$(sum((i,j,k), abs(v3.scale(i,j,k)-w3.scale(k,j,i)))>1e-6) 'wrong w3.scale', v3.scale, w3.scale;

put_utility 'log' / 'test parameter projection (max)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3(i,j,k)
    newName: p2(j,i)
    aggregationMethod: max
- GAMSWriter:
    symbols: [{'name':'p2'}]
endEmbeddedCode p2
q2(j,i) = smax(k, p3(i,j,k));
abort$(sum((j,i), abs(p2(j,i)-q2(j,i)))>1e-6) 'wrong p2', p2, q2;

put_utility 'log' / 'test parameter projection (count)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3(i,j,k)
    newName: p2(j,i)
    aggregationMethod: count
- GAMSWriter:
    symbols: [{'name':'p2'}]
endEmbeddedCode p2
q2(j,i) = sum(k$p3(i,j,k),1);
abort$(sum((j,i), abs(p2(j,i)-q2(j,i)))>1e-6) 'wrong p2', p2, q2;

put_utility 'log' / 'test parameter projection (first)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3(i,j,k)
    newName: p2(j,i)
    aggregationMethod: first
- GAMSWriter:
    symbols: [{'name':'p2'}]
endEmbeddedCode p2
q2(j,i) = sum(k, p3(i,j,k));
q2('j1','i5') = 0.679854079;
abort$(sum((j,i), abs(p2(j,i)-q2(j,i)))>1e-6) 'wrong p2', p2, q2;

put_utility 'log' / 'test variable projection (first)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v3'}]
- Projection:
    name: v3(i,j,k)
    newName: v2(j,i)
    aggregationMethod: first
- GAMSWriter:
    symbols: [{'name':'v2'}]
endEmbeddedCode v2
abort$(sum((j,i), abs(v2.l(j,i)-q2(j,i)))>1e-6) 'wrong v2.l', v2.l, q2;
abort$(sum((j,i)$q2(j,i), abs(v2.scale(j,i)-q2(j,i)))>1e-6) 'wrong v2.scale', v2.scale, q2;

put_utility 'log' / 'test parameter projection (last)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3(i,j,k)
    newName: p2(j,i)
    aggregationMethod: last
- GAMSWriter:
    symbols: [{'name':'p2'}]
endEmbeddedCode p2
q2(j,i) = sum(k, p3(i,j,k));
q2('j1','i5') = 0.506588022;
abort$(sum((j,i), abs(p2(j,i)-q2(j,i)))>1e-6) 'wrong p2', p2, q2;

put_utility 'log' / 'test variable projection (last)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v3'}]
- Projection:
    name: v3(i,j,k)
    newName: v2(j,i)
    aggregationMethod: last
- GAMSWriter:
    symbols: [{'name':'v2'}]
endEmbeddedCode v2
abort$(sum((j,i), abs(v2.l(j,i)-q2(j,i)))>1e-6) 'wrong v2.l', v2.l, q2;
abort$(sum((j,i)$q2(j,i), abs(v2.scale(j,i)-q2(j,i)))>1e-6) 'wrong v2.scale', v2.scale, q2;

put_utility 'log' / 'test parameter projection (sum)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3(i,j,k)
    newName: p2(j,i)
    aggregationMethod: sum
- GAMSWriter:
    symbols: [{'name':'p2'}]
endEmbeddedCode p2
q2(j,i) = sum(k, p3(i,j,k));
abort$(sum((j,i), abs(p2(j,i)-q2(j,i)))>1e-6) 'wrong p2', p2, q2;

put_utility 'log' / 'test variable level projection (sum)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v3'}]
- Projection:
    name: v3.l(i,j,k)
    newName: p2(j,i)
    aggregationMethod: sum
- GAMSWriter:
    symbols: [{'name':'p2'}]
endEmbeddedCode p2
abort$(sum((j,i), abs(p2(j,i)-q2(j,i)))>1e-6) 'wrong p2', p2, q2;

put_utility 'log' / 'test variable scale projection (sum)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v3'}]
- Projection:
    name: v3.scale(i,j,k)
    newName: p2(j,i)
    aggregationMethod: sum
- GAMSWriter:
    symbols: [{'name':'p2'}]
endEmbeddedCode p2
abort$(sum((j,i), abs(p2(j,i)-q2(j,i)))>1e-6) 'wrong p2', p2, q2;

put_utility 'log' / 'test equation level projection (sum)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'e3'}]
- Projection:
    name: e3.l(i,j,k)
    newName: p2(j,i)
    aggregationMethod: sum
- GAMSWriter:
    symbols: [{'name':'p2'}]
endEmbeddedCode p2
abort$(sum((j,i), abs(p2(j,i)-q2(j,i)))>1e-6) 'wrong p2', p2, q2;

* Fails in GT #6325
*put_utility 'log' / 'test parameter projection to scalar without aggregation';
*embeddedCode Connect:
*- GAMSReader:
*    symbols: [{'name':'p3'}]
*- Projection:
*    name: p3(i,j,k)
*    newName: p0
*    aggregationMethod: null
*endEmbeddedCode

put_utility 'log' / 'test parameter projection to scalar(sum)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3(i,j,k)
    newName: p0
    aggregationMethod: sum
- GAMSWriter:
    symbols: [{'name':'p0'}]
endEmbeddedCode p0
q0 = sum((i,j,k), p3(i,j,k));
abort$(abs(p0-q0)>1e-6) 'wrong p0', p0, q0;

put_utility 'log' / 'test variable level projection to scalar (sum)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v3'}]
- Projection:
    name: v3.l(i,j,k)
    newName: p0
    aggregationMethod: sum
- GAMSWriter:
    symbols: [{'name':'p0'}]
endEmbeddedCode p0
abort$(abs(p0-q0)>1e-6) 'wrong p0', p0, q0;

put_utility 'log' / 'test permutation of set';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'s3'}]
- Projection:
    name: s3(i,j,k)
    newName: t3(k,i,j)
- GAMSWriter:
    symbols: [{'name':'t3'}]
endEmbeddedCode t3
abort$(sum((i,j,k), s3(i,j,k) xor t3(k,i,j))>1e-6) 'wrong t3', s3, t3;

put_utility 'log' / 'test projection of set (first)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'s3'}]
- Projection:
    name: s3(i,j,k)
    newName: s2(j,i)
    aggregationMethod: first
- GAMSWriter:
    symbols: [{'name':'s2'}]
endEmbeddedCode s2
t2(j,i) = sum(k, s3(i,j,k));
abort$(sum((j,i), s2(j,i) xor t2(j,i))>1e-6) 'wrong t3', s2, t2;

put_utility 'log' / 'test projection of set (first)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'s3'}]
- Projection:
    name: s3(i,j,k)
    newName: s2(j,i)
    aggregationMethod: first
- GAMSWriter:
    symbols: [{'name':'s2'}]
endEmbeddedCode s2
t2(j,i) = sum(k, s3(i,j,k));
put_utility 'shell.checkErrorLevel' / 'test ' s2.te('j1','i5') ' = First';
abort$(sum((j,i), s2(j,i) xor t2(j,i))>1e-6) 'wrong t3', s2, t2;

put_utility 'log' / 'test projection of set (last)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'s3'}]
- Projection:
    name: s3(i,j,k)
    newName: s2(j,i)
    aggregationMethod: last
- GAMSWriter:
    symbols:
      - name: s2
        mergeType: replace
endEmbeddedCode s2
put_utility 'shell.checkErrorLevel' / 'test ' s2.te('j1','i5') ' = Last';
abort$(sum((j,i), s2(j,i) xor t2(j,i))>1e-6) 'wrong t3', s2, t2;

set am "aggregation methods" / max, mean, median, min, prod, sem, sum, std, nunique, first, last /;
loop(am,
  put_utility 'log' / 'test aggregation method p3->p2 ' am.tl:0;
  put_utility 'ecarguments' / '--AGGMETHOD=' am.tl:0;
  embeddedCodeV Connect:
  - GAMSReader:
      symbols: [{'name':'p3'}]
  - Projection:
      name: p3(i,j,k)
      newName: p2(j,i)
      aggregationMethod: %AGGMETHOD%
  - GAMSWriter:
      symbols: [{'name':'p2'}]
  endEmbeddedCode p2
)

loop(am,
  put_utility 'log' / 'test aggregation method p3->p0 ' am.tl:0;
  put_utility 'ecarguments' / '--AGGMETHOD=' am.tl:0;
  embeddedCodeV Connect:
  - GAMSReader:
      symbols: [{'name':'p3'}]
  - Projection:
      name: p3(i,j,k)
      newName: p0
      aggregationMethod: %AGGMETHOD%
  - GAMSWriter:
      symbols: [{'name':'p0'}]
  endEmbeddedCode p0
)

loop(am,
  put_utility 'log' / 'test aggregation method v3.l->p0 ' am.tl:0;
  put_utility 'ecarguments' / '--AGGMETHOD=' am.tl:0;
  embeddedCodeV Connect:
  - GAMSReader:
      symbols: [{'name':'v3'}]
  - Projection:
      name: v3.l(i,j,k)
      newName: p0
      aggregationMethod: %AGGMETHOD%
  - GAMSWriter:
      symbols: [{'name':'p0'}]
  endEmbeddedCode p0
)

loop(am$(sameas('first',am) or sameas('last',am)),
  put_utility 'log' / 'test aggregation method v3->v2 ' am.tl:0;
  put_utility 'ecarguments' / '--AGGMETHOD=' am.tl:0;
  embeddedCodeV Connect:
  - GAMSReader:
      symbols: [{'name':'v3'}]
  - Projection:
      name: v3(i,j,k)
      newName: v2(j,i)
      aggregationMethod: %AGGMETHOD%
  - GAMSWriter:
      symbols: [{'name':'v2'}]
  endEmbeddedCode v2
)

loop(am$(sameas('first',am) or sameas('last',am)),
  put_utility 'log' / 'test aggregation method v3->v0 ' am.tl:0;
  put_utility 'ecarguments' / '--AGGMETHOD=' am.tl:0;
  embeddedCodeV Connect:
  - GAMSReader:
      symbols: [{'name':'v3'}]
  - Projection:
      name: v3(i,j,k)
      newName: v0
      aggregationMethod: %AGGMETHOD%
  - GAMSWriter:
      symbols: [{'name':'v0'}]
  endEmbeddedCode v0
)
put_utility 'ecarguments' / '';

put_utility 'log' / 'test drop text';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'s3'}]
- Projection:
    name: s3(i,j,k)
    newName: s3noText(j,i)
    aggregationMethod: first
    text: ""
- PythonCode:
    code: |
      expected = [
        ['j1', 'i3', ''], ['j1', 'i4', ''], ['j1', 'i5', ''],
        ['j2', 'i1', ''], ['j2', 'i3', ''], ['j2', 'i4', ''],
        ['j3', 'i3', ''], ['j4', 'i2', ''],
        ['j4', 'i3', ''], ['j4', 'i5', ''],
        ['j5', 'i4', '']
      ]
      if connect._container.data['s3noText'].records.values.tolist() != expected:
        raise Exception("Unexpected Data")
endEmbeddedCode

put_utility 'log' / 'test asSet';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'s3'}, {'name':'p3'}, {'name':'v3'}, {'name':'e3'}]
- Projection:
    name: s3(i,j,k)
    newName: s2_p1(i)
    aggregationMethod: first
- Projection:
    name: s3(i,j,k)
    newName: s2_p2(i)
    aggregationMethod: first
    text: ""
- Projection:
    name: p3(i,j,k)
    newName: s2_p3(i)
    aggregationMethod: first
    asSet: True
    text: "{k}"
- Projection:
    name: v3(i,j,k)
    newName: s2_p4(i)
    aggregationMethod: first
    asSet: True
    text: "will not {k} be applied"
- Projection:
    name: v3.l(i,j,k)
    newName: s2_p5(i)
    aggregationMethod: first
    asSet: True
    text: "{k}"
- Projection:
    name: e3(i,j,k)
    newName: s2_p6(i)
    aggregationMethod: first
    asSet: True
    text: "will not {k} be applied"
- Projection:
    name: e3.l(i,j,k)
    newName: s2_p7(i)
    aggregationMethod: first
    asSet: True
    text: "{k}"
- Projection:
    name: s3(i,j,k)
    newName: s2_p8(i)
    aggregationMethod: first
    text: "{k}: {element_text}"
- PythonCode:
    code: |
      expected_p1 = [['i1', ''], ['i2', ''], ['i3', ''], ['i4', ''], ['i5', 'First']]
      expected_p2 = [['i1', ''], ['i2', ''], ['i3', ''], ['i4', ''], ['i5', '']]
      expected_p3 = [['i1', 'k4'], ['i2', 'k4'], ['i3', 'k5'], ['i4', 'k5'], ['i5', 'k1']]
      expected_p4 = [['i1', ''], ['i2', ''], ['i3', ''], ['i4', ''], ['i5', '']]
      expected_p5 = [['i1', 'k4'], ['i2', 'k4'], ['i3', 'k5'], ['i4', 'k5'], ['i5', 'k1']]
      expected_p6 = [['i1', ''], ['i2', ''], ['i3', ''], ['i4', ''], ['i5', '']]
      expected_p7 = [['i1', 'k4'], ['i2', 'k4'], ['i3', 'k5'], ['i4', 'k5'], ['i5', 'k1']]
      expected_p8 = [['i1', 'k4: '], ['i2', 'k4: '], ['i3', 'k5: '], ['i4', 'k5: '], ['i5', 'k1: First']]
      if connect._container.data['s2_p1'].records.values.tolist() != expected_p1:
        raise Exception("Unexpected Data")
      if connect._container.data['s2_p2'].records.values.tolist() != expected_p2:
        raise Exception("Unexpected Data")
      if connect._container.data['s2_p3'].records.values.tolist() != expected_p3:
        raise Exception("Unexpected Data")
      if connect._container.data['s2_p4'].records.values.tolist() != expected_p4:
        raise Exception("Unexpected Data")
      if connect._container.data['s2_p5'].records.values.tolist() != expected_p5:
        raise Exception("Unexpected Data")
      if connect._container.data['s2_p6'].records.values.tolist() != expected_p6:
        raise Exception("Unexpected Data")
      if connect._container.data['s2_p7'].records.values.tolist() != expected_p7:
        raise Exception("Unexpected Data")
      if connect._container.data['s2_p8'].records.values.tolist() != expected_p8:
        raise Exception("Unexpected Data")
endEmbeddedCode

put_utility 'log' / 'original order of j';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'s3'}]
- Projection:
    name: s3(i,j,k)
    newName: ij(i,j)
    aggregationMethod: first
    text: ""
- GDXWriter:
    file: ij.gdx
    symbols:
      - name: ij
endEmbeddedCode
execute 'gdxdump ij.gdx uelTable=uni symb=uni > ij.txt'
$onEcho > ijExpected.txt

Set uni /
  'i1' ,
  'i2' ,
  'i3' ,
  'i4' ,
  'i5' ,
  'j1' ,
  'j2' ,
  'j3' ,
  'j4' ,
  'j5' /;
Symbol not found: uni
$offEcho
execute.checkErrorLevel 'diff -bw ij.txt ijExpected.txt > %system.NullFile%'

set suffix / level ,marginal, lower, upper, scale/;
Parameter pv3(j,i,k,suffix);
Parameter pv3_all(j,i,k,suffix);
put_utility 'log' / 'test projection of variable as parameter v3->pv3';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v3'}]
- Projection:
    name: v3.[l,m,up,lo,scale](i,j,k)
    newName: pv3(j,i,k)
- Projection:
    name: v3.all(i,j,k)
    newName: pv3_all(j,i,k)
- GAMSWriter:
    symbols:
      - name: pv3
      - name: pv3_all
endEmbeddedCode pv3 pv3_all
abort$(sum((i,j,k), abs(v3.l(i,j,k) - pv3(j,i,k,'level')))>1e-6) 'wrong pv3', v3.l, pv3;
abort$(sum((i,j,k), abs(v3.l(i,j,k) - pv3_all(j,i,k,'level')))>1e-6) 'wrong pv3_all', v3.l, pv3_all;

Parameter pv2(j,i,suffix);
Parameter pv2_all(j,i,suffix);
put_utility 'log' / 'test projection of variable as parameter v3->pv2';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v3'}]
- Projection:
    name: v3(i,j,k)
    newName: v2(j,i)
    aggregationMethod: first
- Projection:
    name: v3.[l,m,up,lo,scale](i,j,k)
    newName: pv2(j,i)
    aggregationMethod: first
- Projection:
    name: v3.[all](i,j,k)
    newName: pv2_all(j,i)
    aggregationMethod: first
- GAMSWriter:
    symbols:
      - name: v2
      - name: pv2
      - name: pv2_all
endEmbeddedCode v2 pv2 pv2_all
abort$(sum((j,i), abs(v2.l(j,i) - pv2(j,i,'level')))>1e-6) 'wrong pv2', v2.l, pv2;
abort$(sum((j,i), abs(v2.l(j,i) - pv2_all(j,i,'level')))>1e-6) 'wrong pv2_all', v2.l, pv2_all;

Parameter pv0(suffix);
Parameter pv0_all(suffix);
put_utility 'log' / 'test projection of variable as parameter v3->pv0';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v3'}]
- Projection:
    name: v3(i,j,k)
    newName: v0
    aggregationMethod: first
- Projection:
    name: v3.[l,m,up,lo,scale](i,j,k)
    newName: pv0
    aggregationMethod: first
- Projection:
    name: v3.all(i,j,k)
    newName: pv0_all
    aggregationMethod: first
- GAMSWriter:
    symbols:
      - name: v0
      - name: pv0
      - name: pv0_all
endEmbeddedCode v0 pv0 pv0_all
abort$(abs(v0.l - pv0('level'))>1e-6) 'wrong pv0', v0.l, pv0;
abort$(abs(v0.l - pv0_all('level'))>1e-6) 'wrong pv0_all', v0.l, pv0_all;

put_utility 'log' / 'test projection of variable as parameter v0.l->q0';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v0'}]
- Projection:
    name: v0.l
    newName: q0
- GAMSWriter:
    symbols:
      - name: q0
endEmbeddedCode q0
abort$(abs(v0.l - q0)>1e-6) 'wrong q0', v0.l, q0;

put_utility 'log' / 'test projection of variable as parameter v0->pv0';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v0'}]
- Projection:
    name: v0.[l,m,up,lo,scale]
    newName: pv0
- Projection:
    name: v0.[all]
    newName: pv0_all
- GAMSWriter:
    symbols:
      - name: pv0
      - name: pv0_all
endEmbeddedCode pv0 pv0_all
abort$(abs(v0.l - pv0('level'))>1e-6) 'wrong pv0', v0.l, pv0;
abort$(abs(v0.l - pv0_all('level'))>1e-6) 'wrong pv0_all', v0.l, pv0_all;

put_utility 'log' / 'test case insensitivity';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v0'}]
- Projection:
    name: V0.l
    newName: q0
- GAMSWriter:
    symbols:
      - name: q0
endEmbeddedCode q0
abort$(abs(v0.l - q0)>1e-6) 'wrong q0', v0.l, q0;

put_utility 'log' / 'test multiple projections on the same symbol';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v0'}]
- Projection:
    name: v0.l
    newName: q0
- Projection:
    name: v0.l
    newName: p0
- GAMSWriter:
    symbols:
      - name: q0
      - name: p0
endEmbeddedCode q0 p0
abort$(abs(v0.l - q0)>1e-6) 'wrong q0', v0.l, q0;
abort$(abs(v0.l - p0)>1e-6) 'wrong p0', v0.l, p0;

put_utility 'log' / 'test empty symbol';
option clear=p2;
option clear=q2;
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p2'}]
- Projection:
    name: p2(j,i)
    newName: q2(j,i)
- GAMSWriter:
    symbols: [{'name':'q2'}]
endEmbeddedCode q2
abort$(card(q2)) 'q2 expected to be empty', q2;

put_utility 'log' / 'test None records symbol';
embeddedCode Connect:
- PythonCode:
    code: |
      connect.container.addParameter("p2", ["j", "i"])
- Projection:
    name: p2(j,i)
    newName: q2(j,i)
- PythonCode:
    code: |
      data = connect.container['q2'].records
      expected_cols =  ['j', 'i', 'value']

      if data is None or not data.empty:
        raise Exception("Expected >q2< to have an empty DataFrame.")

      if (data.columns != expected_cols).any():
        raise Exception("Unexpected columns for >d<.")
endEmbeddedCode

put_utility 'log' / 'test uel order';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p2m'}, {'name':'m'}]
- Projection:
    name: p2m(m,i)
    newName: p(m)
    aggregationMethod: first
- PythonCode:
    code: |
        sym = connect.container['p']
        data_sorted = sym.records.sort_values(sym.records.columns[:-1].tolist()).values.tolist()
        expected = [['m1', 1.0],
                    ['m2', 2.0],
                    ['m3', 10.0],
                    ['m4', 7.0],
                    ['m5', 3.0],
                    ['m100', 9.0]]
        if data_sorted != expected:
            raise Exception("Unexpected data while testing uel order")
endEmbeddedCode

$onecho > symbol_with_duplicate_records.csv
i1,j1,2.5
i1,j2,1.7
i2,j1,1.8
i2,j2,1.4
i2,j2,1.5
$offEcho

put_utility 'log' / 'test aggregationMethod: sum on duplicate records';
EmbeddedCode Connect:
- CSVReader:
    header: False
    file: symbol_with_duplicate_records.csv
    name: p
    indexColumns: [1,2]
    valueColumns: 3
- Projection:
    name: p(i,j)
    newName: p2(j,i)
    aggregationMethod: sum
- PythonCode:
    code: |
        data = connect.container['p2'].records.values.tolist()
        expected = [['j1', 'i1', 2.5],
                    ['j1', 'i2', 1.8],
                    ['j2', 'i1', 1.7],
                    ['j2', 'i2', 2.9]]
        if data != expected:
            raise Exception("Unexpected data while summing duplicate records")
endEmbeddedCode

put_utility 'log' / 'test aggregationMethod: first on duplicate records';
EmbeddedCode Connect:
- CSVReader:
    header: False
    file: symbol_with_duplicate_records.csv
    name: p
    indexColumns: [1,2]
    valueColumns: 3
- Projection:
    name: p(i,j)
    newName: p2(j,i)
    aggregationMethod: first
- PythonCode:
    code: |
        data = connect.container['p2'].records.values.tolist()
        expected = [['j1', 'i1', 2.5],
                    ['j1', 'i2', 1.8],
                    ['j2', 'i1', 1.7],
                    ['j2', 'i2', 1.4]]
        if data != expected:
            raise Exception("Unexpected data while aggregating (first) duplicate records")
endEmbeddedCode

put_utility 'log' / 'test aggregationMethod: last on duplicate records without permutation of index';
EmbeddedCode Connect:
- CSVReader:
    header: False
    file: symbol_with_duplicate_records.csv
    name: p
    indexColumns: [1,2]
    valueColumns: 3
- Projection:
    name: p(i,j)
    newName: p2(i,j)
    aggregationMethod: last
- PythonCode:
    code: |
        data = connect.container['p2'].records.values.tolist()
        expected = [['i1', 'j1', 2.5],
                    ['i1', 'j2', 1.7],
                    ['i2', 'j1', 1.8],
                    ['i2', 'j2', 1.5]]
        if data != expected:
            raise Exception("Unexpected data while aggregating (last) duplicate records without permutation of index")
endEmbeddedCode

put_utility 'log' / 'test aggregationMethod: last on duplicate records with index extension';
EmbeddedCode Connect:
- CSVReader:
    header: False
    file: symbol_with_duplicate_records.csv
    name: p
    indexColumns: [1,2]
    valueColumns: 3
- Projection:
    name: p(i,j)
    newName: p2(i,j,i)
    aggregationMethod: last
- PythonCode:
    code: |
        data = connect.container['p2'].records.values.tolist()
        expected = [['i1', 'j1', 'i1', 2.5],
                    ['i1', 'j2', 'i1', 1.7],
                    ['i2', 'j1', 'i2', 1.8],
                    ['i2', 'j2', 'i2', 1.5]]
        if data != expected:
            raise Exception("Unexpected data while aggregating (last) duplicate records with index extension")
endEmbeddedCode

$onEcho > t.gms
Set i(*) canning plants /
'seattle', 
'san-diego' /;

Set j(*) markets /
'new-york', 
'chicago', 
'topeka' /;

free     Variable z total transportation costs in thousands of dollars /L 153.675 /;

positive Variable x(i,j) shipment quantities in cases /
'seattle'.'new-york'.L 50, 
'seattle'.'chicago'.L 300, 
'seattle'.'topeka'.M 0.036, 
'san-diego'.'new-york'.L 275, 
'san-diego'.'chicago'.M 0.00900000000000001, 
'san-diego'.'topeka'.L 275 /;

Equation supply(i) observe supply limit at plant i /
'seattle'.L 350, 
'seattle'.M Eps, 
'seattle'.LO -Inf, 
'seattle'.UP 350, 
'san-diego'.L 550, 
'san-diego'.LO -Inf, 
'san-diego'.UP 600 /;

Equation demand(j) satisfy demand at market j /
'new-york'.L 325, 
'new-york'.M 0.225, 
'new-york'.LO 325, 
'new-york'.UP +Inf, 
'chicago'.L 300, 
'chicago'.M 0.153, 
'chicago'.LO 300, 
'chicago'.UP +Inf, 
'topeka'.L 275, 
'topeka'.M 0.126, 
'topeka'.LO 275, 
'topeka'.UP +Inf /;
$offEcho
$call.checkErrorLevel gams t.gms lo=%gams.lo% a=c gdx=t.gdx

$log test suffix list
EmbeddedCode Connect:
- GDXReader:
    file: t.gdx
- Projection:
    name: demand.[m,l](j)
    newName: p2_demand(j)
    aggregationMethod: first
- Projection:
    name: x.[l](i,j)
    newName: p2_x(j)
    aggregationMethod: first
- Projection:
    name: x.[l](i,j)
    newName: p3_x(j,i)
- Projection:
    name: x.[l](i,j)
    newName: s2_x(j)
    aggregationMethod: first
    asSet: True
- Projection:
    name: x.[l](i,j)
    newName: s2_x_text(j)
    aggregationMethod: first
    asSet: True
    text: "does not work with suffix to index"
- Projection:
    name: supply.[l](i)
    newName: p1_supply
    aggregationMethod: first
- Projection:
    name: z.[l]
    newName: p1_z
- PythonCode:
    code: |
        sym = connect.container['p2_demand']
        data = sym.records.sort_values(sym.records.columns[:-1].tolist()).values.tolist()
        expected = [['new-york', 'marginal', 0.225],
                    ['new-york', 'level', 325.0],
                    ['chicago', 'marginal', 0.153],
                    ['chicago', 'level', 300.0],
                    ['topeka', 'marginal', 0.126],
                    ['topeka', 'level', 275.0]]
        if data != expected:
            raise Exception("Unexpected data p2_demand")
            
        sym = connect.container['p2_x']
        data = sym.records.sort_values(sym.records.columns[:-1].tolist()).values.tolist()
        expected = [['new-york', 'level', 50.0],
                    ['chicago', 'level', 300.0],
                    ['topeka', 'level', 0.0]]

        if data != expected:
            raise Exception("Unexpected data p2_x")
            
        sym = connect.container['p3_x']
        data = sym.records.sort_values(sym.records.columns[:-1].tolist()).values.tolist()
        expected = [['new-york', 'seattle', 'level', 50.0],
                    ['new-york', 'san-diego', 'level', 275.0],
                    ['chicago', 'seattle', 'level', 300.0],
                    ['chicago', 'san-diego', 'level', 0.0],
                    ['topeka', 'seattle', 'level', 0.0],
                    ['topeka', 'san-diego', 'level', 275.0]]
        if data != expected:
            raise Exception("Unexpected data p3_x")
            
        sym = connect.container['s2_x']
        data = sym.records.sort_values(sym.records.columns[:-1].tolist()).values.tolist()
        expected = [['new-york', 'level', ''],
                    ['chicago', 'level', ''],
                    ['topeka', 'level', '']]
        if data != expected:
            raise Exception("Unexpected data s2_x")
            
        sym = connect.container['s2_x_text']
        data = sym.records.sort_values(sym.records.columns[:-1].tolist()).values.tolist()
        if data != expected:
            raise Exception("Unexpected data s2_x_text")

        sym = connect.container['p1_supply']
        data = sym.records.sort_values(sym.records.columns[:-1].tolist()).values.tolist()
        expected = [['level', 350.0]]
        if data != expected:
            raise Exception("Unexpected data p1_supply")
            
        sym = connect.container['p1_z']
        data = sym.records.sort_values(sym.records.columns[:-1].tolist()).values.tolist()
        expected = [['level', 153.675]]
        if data != expected:
            raise Exception("Unexpected data p1_z")
endEmbeddedCode

put_utility 'log' / 'test spaces are allowed in domain (parameter)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3(i, j,k)
    newName: q3(k  , i,j   )
- PythonCode:
    code: |
      data = connect.container['q3'].records
      expected_cols = ['k', 'i', 'j', 'value']

      if (data.columns != expected_cols).any():
        raise Exception("Unexpected columns for >q3<.")
endEmbeddedCode

put_utility 'log' / 'test spaces are allowed in domain (variable)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v3'}]
- Projection:
    name: v3.scale(i,j,k)
    newName: q4(k  , i,j   )
- PythonCode:
    code: |
      data = connect.container['q4'].records
      expected_cols = ['k', 'i', 'j', 'value']

      if (data.columns != expected_cols).any():
        raise Exception("Unexpected columns for >q4<.")
endEmbeddedCode

put_utility 'log' / 'test repeated indices are allowed; extended index space (set)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'s3'}]
- Projection:
    name: s3(i,j,k)
    newName: s4(k  , i,k, k   )
    aggregationMethod: last
- PythonCode:
    code: |
      data = connect.container['s4'].records.values.tolist()
      expected = [
        ['k1', 'i3', 'k1', 'k1', ''],
        ['k1', 'i5', 'k1', 'k1', 'First'],
        ['k2', 'i4', 'k2', 'k2', ''],
        ['k2', 'i5', 'k2', 'k2', 'Last'],
        ['k4', 'i1', 'k4', 'k4', ''],
        ['k4', 'i2', 'k4', 'k4', ''],
        ['k4', 'i3', 'k4', 'k4', ''],
        ['k4', 'i4', 'k4', 'k4', ''],
        ['k4', 'i5', 'k4', 'k4', ''],
        ['k5', 'i3', 'k5', 'k5', ''],
        ['k5', 'i4', 'k5', 'k5', '']
      ]

      if data != expected:
        raise Exception("Unexpected columns for >s4<.")
endEmbeddedCode

put_utility 'log' / 'test repeated indices are allowed; extended index space (parameter)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'p3'}]
- Projection:
    name: p3(i,j,k)
    newName: p4(j,i,j)
    aggregationMethod: sum
- PythonCode:
    code: |
      data = connect.container['p4'].records.values.tolist()
      expected = [
        ['j1', 'i3', 'j1', 0.045066059],
        ['j1', 'i4', 'j1', 0.607341301],
        ['j1', 'i5', 'j1', 1.186442101],
        ['j2', 'i1', 'j2', 0.596558144],
        ['j2', 'i3', 'j2', 0.783102004],
        ['j2', 'i4', 'j2', 0.362509471],
        ['j3', 'i3', 'j3', 0.945749415],
        ['j4', 'i2', 'j4', 0.511448928],
        ['j4', 'i3', 'j4', 0.596462556],
        ['j4', 'i5', 'j4', 0.159253884],
        ['j5', 'i4', 'j5', 0.594067961]
      ]

      if data != expected:
        raise Exception("Unexpected columns for >p4<.")
endEmbeddedCode

put_utility 'log' / 'test repeated indices are allowed; extended index space (variable level)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'v3'}]
- Projection:
    name: v3.l(i,j,k)
    newName: v4(k,k)
    aggregationMethod: min
- PythonCode:
    code: |
      data = connect.container['v4'].records.values.tolist()
      expected = [
        ['k1', 'k1', 0.596462556],
        ['k2', 'k2', 0.362509471],
        ['k4', 'k4', 0.159253884],
        ['k5', 'k5', 0.045066059]
      ]

      if data != expected:
        raise Exception("Unexpected columns for >v4<.")
endEmbeddedCode

put_utility 'log' / 'test repeated indices are allowed; extended index space (variable)';
embeddedCode Connect:
- GAMSReader:
    symbols: all
- Projection:
    name: v3(i,j,k)
    newName: v4(k,i,k)
    aggregationMethod: sum
- PythonCode:
    code: |
      data = connect.container['v4'].records.values.tolist()
      expected = [
        ['k1', 'i3', 'k1', 1.542211971, 0.0, float('-inf'), float('inf'), 1.542211971],
        ['k1', 'i5', 'k1', 0.679854079, 0.0, float('-inf'), float('inf'), 0.679854079],
        ['k2', 'i4', 'k2', 0.362509471, 0.0, float('-inf'), float('inf'), 0.362509471],
        ['k2', 'i5', 'k2', 0.506588022, 0.0, float('-inf'), float('inf'), 0.506588022],
        ['k4', 'i1', 'k4', 0.596558144, 0.0, float('-inf'), float('inf'), 0.596558144],
        ['k4', 'i2', 'k4', 0.511448928, 0.0, float('-inf'), float('inf'), 0.511448928],
        ['k4', 'i3', 'k4', 0.783102004, 0.0, float('-inf'), float('inf'), 0.783102004],
        ['k4', 'i4', 'k4', 0.594067961, 0.0, float('-inf'), float('inf'), 0.594067961],
        ['k4', 'i5', 'k4', 0.159253884, 0.0, float('-inf'), float('inf'), 0.159253884],
        ['k5', 'i3', 'k5', 0.045066059, 0.0, float('-inf'), float('inf'), 0.045066059],
        ['k5', 'i4', 'k5', 0.607341301, 0.0, float('-inf'), float('inf'), 0.607341301]
      ]

      if data != expected:
        raise Exception("Unexpected columns for >v4<.")
endEmbeddedCode

put_utility 'log' / 'test repeated indices are allowed; extended index space (equation level)';
embeddedCode Connect:
- GAMSReader:
    symbols: [{'name':'e3'}]
- Projection:
    name: e3.l(i,j,k)
    newName: e4(j,j,j,j)
    aggregationMethod: max
- PythonCode:
    code: |
      data = connect.container['e4'].records.values.tolist()
      expected = [
        ['j1', 'j1', 'j1', 'j1', 0.679854079],
        ['j2', 'j2', 'j2', 'j2', 0.783102004],
        ['j3', 'j3', 'j3', 'j3', 0.945749415],
        ['j4', 'j4', 'j4', 'j4', 0.596462556],
        ['j5', 'j5', 'j5', 'j5', 0.594067961]
      ]

      if data != expected:
        raise Exception("Unexpected columns for >e4<.")
endEmbeddedCode

put_utility 'log' / 'test repeated indices are allowed; extended index space (equation)';
embeddedCode Connect:
- GAMSReader:
    symbols: all
- Projection:
    name: e3(i,j,k)
    newName: e4(j,j)
    aggregationMethod: sum
- PythonCode:
    code: |
      data = connect.container['e4'].records.values.tolist()
      expected = [
        ['j1', 'j1', 1.838849461, 0.0, float('-inf'), float('inf'), 4.0],
        ['j2', 'j2', 1.742169619, 0.0, float('-inf'), float('inf'), 3.0],
        ['j3', 'j3', 0.945749415, 0.0, float('-inf'), float('inf'), 1.0],
        ['j4', 'j4', 1.267165368, 0.0, float('-inf'), float('inf'), 3.0],
        ['j5', 'j5', 0.594067961, 0.0, float('-inf'), float('inf'), 1.0]
      ]

      if data != expected:
        raise Exception("Unexpected columns for >e4<.")
endEmbeddedCode

put_utility 'log' / 'test agent gives real domains when repeated indices exist';
embeddedCode Connect:
- GAMSReader:
    symbols: all
- Projection:
    name: p3(i,j,k)
    newName: p4(j,i,j,i)
    aggregationMethod: sum
- PythonCode:
    code: |
      import gams.transfer as gt
      data = connect.container['p4'].domain
      i = connect.container['i']
      j = connect.container['j']

      if data != [j, i, j, i]:
        raise Exception("Unexpected domains for >p4<.")
endEmbeddedCode

put_utility 'log' / 'test repeated indices with an empty symbol';
embeddedCode Connect:
- GAMSReader:
    symbols: all
- Projection:
    name: q4(i, j, k)
    newName: q5(k, j, i, i)
    aggregationMethod: sum
- PythonCode:
    code: |
      import gams.transfer as gt
      data = connect.container['q5'].domain
      
      i = connect.container['i']
      j = connect.container['j']
      k = connect.container['k']

      if data != [k, j, i, i]:
        raise Exception("Unexpected domains for >p5<.")
endEmbeddedCode

put_utility 'log' / 'test use case for turning non-atomic labels to atomic, individual dimensions using LabelManipulator and Projection';
embeddedCode Connect:
- GAMSReader:
    symbols:
        - name: date
        - name: i
        - name: p
- Projection:
    name: p(i, date)
    newName: p2(i, date, date, date)
- LabelManipulator:
    symbols:
      - name: p2
        dimension: 2
    code:
        rule: x.split(',')[2]
- LabelManipulator:
    symbols:
      - name: p2
        dimension: 3
    code:
        rule: x.split(',')[1]
- LabelManipulator:
    symbols:
      - name: p2
        dimension: 4
    code:
        rule: x.split(',')[0]
- DomainWriter:
    symbols:
      - name: p2(i,'day','month','year')
- PythonCode:
    code: |
      data = connect.container['p2'].records.values.tolist()
      expected = [
        ['i1', '17', 'May', '2002', ''],
        ['i2', '08', 'September', '2024', ''],
        ['i3', '20', 'May', '1998', ''],
        ['i4', '08', 'May', '2022', ''],
        ['i5', '10', 'November', '2023', '']
      ]

      if data != expected:
        raise Exception("Unexpected columns for >p2<.")
endEmbeddedCode

put_utility 'log' / 'test aggregationMethod being applied for extended index space';
embeddedCode Connect:
- GAMSReader:
    symbols:
        - name: p
- Projection:
    name: p(i, date)
    newName: p2(i, date, date, date)
    aggregationMethod: count
- PythonCode:
    code: |
      data = connect.container['p2'].records.values.tolist()
      expected = [
        ['i1', '2002,May,17', '2002,May,17', '2002,May,17', '1'],
        ['i2', '2024,September,08', '2024,September,08', '2024,September,08', '1'],
        ['i3', '1998,May,20', '1998,May,20', '1998,May,20', '1'],
        ['i4', '2022,May,08', '2022,May,08', '2022,May,08', '1'],
        ['i5', '2023,November,10', '2023,November,10', '2023,November,10', '1']
      ]
      if data != expected:
        raise Exception("Unexpected columns for >p2<.")
endEmbeddedCode