Loading...
Searching...
No Matches
Container

A GAMS Transfer Matlab container stores a collection of symbols and is therefore comparable to a GDX file.

It is indeed a fundamental feature of containers to read from or write to GDX files.

Creating a Container

Creating a container is easy. Either:

  • Create an Empty Container:
    c = Container();
  • Create a Container With Symbols From a GDX File:
    c = Container('path/to/file.gdx');
  • Create a Container With Symbols From Another Container:
    c1 = Container('path/to/file.gdx');
    ...
    c2 = Container(c1);

Reading From GDX

Above was a first example of how to read a whole GDX file into a container. But often it is useful to only read certain symbols or to specify the records format. With the container's Container.read method, you get more control.

Consider for the following that c is some container and source is either a GDX file (e.g. source = "path/to/file.gdx") or another container object. Then:

  • Reading all Symbols:
    Read in a all symbols with
    c.read(source);
  • Reading a Subset of Symbols:
    In order to only read the symbols x and z from a GDX file, do
    c.read(source, 'symbols', {'x', 'z'});
  • Reading Symbols in a Certain Records Format:
    GAMS Transfer can load the symbol records into different Matlab data structures also referred to as records format. There are struct, table (default), dense_matrix and sparse_matrix, each with certain advantages and disadvantages. In order to read in a symbols as dense_matrix, do
    c.read(source, 'format', 'dense_matrix');
  • Reading a Subset of Symbol Values:
    GDX files store multiple values per symbol. Sets have element_text, Parameters have value and Equations and Variables have level, marginal, lower, upper, scale, see Records for more information. On default, all values are read, but you can select a subset by
    c.read(source, 'values', {'level', 'marginal'});
    Note that here, level also enables element_text and value. Moreover, marginal, lower, upper, scale have no influence on Sets and Parameters. It is even possible to specify no values in order to read none GDX records. This would then only read the symbol meta data like name or description.
  • Reading an Indexed GDX File:
    Besides standard GDX files there exist so called Indexed GDX files. Read such a file by
    c.read(source, 'indexed', true);
  • ...and of course it is possible to mix and match all the above.
Note
When reading from different GDX files it can happen that two different symbols have the same name. It is currently not possible to rename a symbol on load or to merge symbol contents, for example. GAMS Transfer Matlab will simply raise an error.

Writing To GDX

A container with all symbols and symbol records can be written to a GDX file with it's Container.write method. It is possible to write a compressed GDX file. Simply write with:

  • Writing all Symbols:
    Write all symbols to a GDX file with
    c.write('path/to/file.gdx');
  • Writing a Subset of Symbols:
    In order to only write the symbols x and z to a GDX file, do
    c.write('path/to/file.gdx', 'symbols', {'x', 'z'});
  • Writing a Compressed GDX File:
    In order to write compressed, set the parameter compress to true:
    c.write('path/to/file.gdx', 'compress', true);
  • Writing an Indexed GDX File:
    Set the parameter indexed to true to write an Indexed GDX file:
    c.write('path/to/file.gdx', 'indexed', true);
    This will only write symbols to the file that support indexed, see also symbol.Abstract.indexed. A symbol is indexed if (1) it is a Parameter, (2) its UELs are ranges from 1 to size(i) and (3) its records are indexed by integers and not categorical in table-like formats. It is also possible to write indexed symbols to a standard GDX file, but the meaning may be different.
Note
It is not possible to write the container if any of the symbols to write is not valid (see also Validate Symbol Records). Further note that a symbol can be considered valid but still has domain violations, which would lead to an error when writing, see also Domain Violations.
Advanced Users Only:
GDX expects the symbol records to be sorted in a certain order. Since this can be difficult for the user to achieve, the records are sorted (without overwriting) on default when writing to GDX. Users who know that their symbol records are sorted correctly, can set the Container.write method argument sorted to true in order to improve efficiency. Symbol records dense_matrix and sparse_matrix are sorted per definition (sorted has no effect). GDX expects the following order for struct and table formats. Symbol records are sorted by domain UEL codes in ascending order w.r.t. dimension 1 first, then 2, then 3, etc. However, UEL codes are here not relative to the symbol, but global to the whole container where only the first occurence is relevant. This also means that symbol order within a container also influences the UEL order and hence symbol record order. The method Container.getUELs returns this global UEL ordering and can be a help to establish the correct ordering. Note that Container.getUELs creates this set only on request and is not very efficient.

Naming Symbols

GAMS Transfer follows the GDX convention for naming symbols. That means, symbol names can consist of alpha-numeric characters and _ (but not at the beginning). Name length must be shorter than 64. Symbol names are considered case insensitive, i.e. adding a symbol named X1 after adding x1 is not allowed because the names are considered equal. Methods that accept symbol names as input, accept symbol names in any case.

To get the original names of symbols registered in a container, use Container.getSymbolNames. To check if a symbol exists, use Container.hasSymbols. For example consider a container m with symbol sym1:

>> m.hasSymbols({'Sym1', 'sym1', 'sYM1'})
ans =
1×3 logical array
1 1 1
>> m.getSymbolNames({'Sym1', 'sym1', 'sYM1'})
ans =
1×3 cell array
{'sym1'} {'sym1'} {'sym1'}

Accessing Symbols

Symbols are stored in the struct Container.data, with fieldnames equal to the symbol names. For Example this is:

>> m.data
ans =
struct with fields:
i: [1×1 gams.transfer.symbol.Set]
j: [1×1 gams.transfer.symbol.Set]
a: [1×1 gams.transfer.symbol.Parameter]
b: [1×1 gams.transfer.symbol.Parameter]
d: [1×1 gams.transfer.symbol.Parameter]
f: [1×1 gams.transfer.symbol.Parameter]
c: [1×1 gams.transfer.symbol.Parameter]
x: [1×1 gams.transfer.symbol.Variable]
z: [1×1 gams.transfer.symbol.Variable]
cost: [1×1 gams.transfer.symbol.Equation]
supply: [1×1 gams.transfer.symbol.Equation]
demand: [1×1 gams.transfer.symbol.Equation]

In addition to accessing Container.data directly, symbol handle lists can be queried via the methods Container.getSets, Container.getParameters, Container.getVariables, Container.getEquations, Container.getAliases or via Container.getSymbols given a list of symbol names.

>> vars = m.getSymbols({'x', 'z'})'
vars =
1×2 cell array
{1×1 gams.transfer.Variable} {1×1 gams.transfer.Variable}

This can be particularly useful in combination with the functions Container.listSymbols, Container.listSets, Container.listAliases, Container.listParameters, Container.listVariables and Container.listEquations that list the names of symbols of the corresponding type, as shown below:

>> transpose(m.listVariables())
ans =
1×2 cell array
{'x'} {'z'}
>> vars = transpose(m.getSymbols(m.listVariables()))
vars =
1×2 cell array
{1×1 gams.transfer.Variable} {1×1 gams.transfer.Variable}
>> {vars{1}.name, vars{2}.name}
ans =
1×2 cell array
{'x'} {'z'}
Note
When accessing the symbols via Container.data, then the case of characters matters. This is not the case for Container.getSymbols.

Removing Symbols

To remove a symbol from the Container, simply call Container.removeSymbols:

m.removeSymbols('x');
m.removeSymbols({'a', 'b'});
Note
Removing a Set that is used in a domain of another symbol will relax those symbol domains.

Symbol Overview

The methods Container.describeSets, Container.describeAliases, Container.describeParameters, Container.describeVariables and Container.describeEquations allow for an overview over the symbols of the corresponding type stored in the Container. These methods return a table listing for each symbol the properties / statistics given in the following table. Here, an x means that this property / statistic is available for the symbol type.

Property / Statistic Description Set Alias Parameter Variable Equation
name Name of symbol x x x x x
is_singleton Indicates if set is a singleton set (true) or not (false) x x
alias_with Set an alias is linked to x
type Variable or Equation type, see VariableType and EquationType x x
format Format records are stored in, see Records Format x x x x x
dimension Dimension of symbol x x x x x
domain_type Type of domain, e.g. relaxed or regular x x x x x
domain Domain of symbol x x x x x
size Size or shape of symbol x x x x x
number_records Number of symbol GDX records x x x x x
number_values Number of stored records values x x x x x
sparsity Sparsity of symbol records w.r.t. to count x x x x x
min Minimum value x
mean Mean value x
max Maximum value x
where_min Domain entry of record with minimum value x
where_max Domain entry of record with maximum value x
min_level Minimum value of level values x x
mean_level Mean value of level values x x
max_level Maximum value of level values x x
where_max_abs_level Domain entry of record with maximum absolute level value x x

For Example, this looks like:

>> tbl = m.describeVariables();
>> tbl(:,1:9)
ans =
2×9 table
name type format dimension domain_type domain size number_records number_values
____ ________ ______ _________ ___________ ______ _____ ______________ _____________
x positive table 2 regular [i,j] [2,3] 6 30
z free table 0 none [] [] 1 5
>> tbl(:,10:14)
ans =
2×5 table
sparsity min_level mean_level max_level where_max_abs_level
________ _________ __________ _________ ___________________
0 0 150 300 [seattle,chicago]
0 153.68 153.68 153.68 []