GAMS has strict domain checking (type checking). This has some interesting consequences. Basically all good: much better protection against errors compared to simply using integer indices \(1,\dots,n\). Consider the square matrix \(\color{darkblue}A_{i,j}\):
set |
The so-called "minij" matrix looks like:
---- 7 PARAMETER Asquare matrix
1234
a 1.0001.0001.0001.000
b 1.0002.0002.0002.000
c 1.0002.0003.0003.000
d 1.0002.0003.0004.000
The task to invert a parameter \(\color{darkred}A_{i,j}\), can be stated as finding a feasible solution to: \[\color{darkred}B\cdot \color{darkblue}A = \color{darkblue}I\] or \[\sum_i \color{darkred}B_{j,i}\cdot \color{darkblue}A_{i,j'} = \color{darkblue}I_{j,j'} \> \>\>\forall j,j'\] The first index of \(\color{darkblue}A\) is \(i\) which means the second index of \(\color{darkblue}B\) is also \(i\).
So our GAMS code should look like:
set |
This shows:
---- 23 VARIABLE B.L inverse of A
a b c d
12.000 -1.000
2 -1.0002.000 -1.000
3 -1.0002.000 -1.000
4 -1.0001.000
The same argument holds when we write: \[ \color{darkblue}A \cdot \color{darkred}B = \color{darkblue}I\] or \[\sum_j \color{darkblue}A_{i,j} \cdot \color{darkred}B_{j,i'} = \color{darkblue}I_{i,i'} \> \>\>\forall i,i'\] The second index of \(\color{darkblue}A\) is \(j\) which means the first index of \(\color{darkblue}B\) is also \(j\).
The conclusion is: the inverse of A(i,j) is a symbol with signature B(j,i).
Note that usually we use a single set \(i\) and make \(j,k\) aliases. That will not reveal the above issue:set |
---- 25 PARAMETER Asquare matrix
a b c d
a 1.0001.0001.0001.000
b 1.0002.0002.0002.000
c 1.0002.0003.0003.000
d 1.0002.0003.0004.000
---- 25 VARIABLE B.L inverse of A
a b c d
a 2.000 -1.000
b -1.0002.000 -1.000
c -1.0002.000 -1.000
d -1.0001.000
Similarly, numerical codes for inverting matrices don't worry about this at all: they just see everything in terms of integer index positions \(i,j \in \{1,\dots,n\}\).