Container

Wrapper of symbols (like GDX file) More...

Wrapper of symbols (like GDX file)

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. GDX files can be operated in two different modes, default and indexed, which are also supported by GAMS Transfer Matlab containers, see Indexed GDX for more info. GAMS Transfer Matlab offers two types of containers:

  • Container: This should be your default choice.
  • ConstContainer: Need even higher efficiency? Try this one! But keep in mind, it's constant which means that symbols can't be updated once added.

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:

    Finally note that GDX files store multiple values per symbol. Sets have 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 text and value. Moreover, marginal has 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.

  • ...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:

c.write('path/to/file.gdx');
c.write('path/to/file.gdx', 'compress', true);
Note
It is not possible to write the container if any of its symbols 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.getUniverseSet returns this global UEL ordering and can be a help to establish the correct ordering. Note that Container.getUniverseSet 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 X after adding x 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 GAMSTransfer.Set]
j: [1×1 GAMSTransfer.Set]
a: [1×1 GAMSTransfer.Parameter]
b: [1×1 GAMSTransfer.Parameter]
d: [1×1 GAMSTransfer.Parameter]
f: [1×1 GAMSTransfer.Parameter]
c: [1×1 GAMSTransfer.Parameter]
x: [1×1 GAMSTransfer.Variable]
z: [1×1 GAMSTransfer.Variable]
cost: [1×1 GAMSTransfer.Equation]
supply: [1×1 GAMSTransfer.Equation]
demand: [1×1 GAMSTransfer.Equation]

In addition to accessing Container.data directly, symbol handle lists can be queried via the method Container.getSymbols given a list of symbol names.

>> vars = transpose(m.getSymbols({'x', 'z'}))
vars =
1×2 cell array
{1×1 GAMSTransfer.Variable} {1×1 GAMSTransfer.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 GAMSTransfer.Variable} {1×1 GAMSTransfer.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'});
Attention
If a Set is removed from the Container, a handle to that Set can still exist as a domain of another symbol or be linked to by an alias. This will make these other symbols invalid, see isValid.

Reordering Symbols

The GDX file requires the symbols to be sorted such that, for example, a Set used as domain of another symbol appears before that symbol. The Container will try to establish a valid ordering when writing the data to GDX. However, this operation can also be invoked manually by calling the method Container.reorderSymbols.

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. Note that *_level is called *_value or simply * for a Parameter.

Property / Statistic Description Set Alias Parameter Variable Equation
name Name of symbol x x x x x
is_alias Indicates if set is an alias (true) or not (false) 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
dim 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
num_recs Number of symbol GDX records x x x x x
num_vals 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_level Minimum value of level values x x x
mean_level Mean value of level values x x x
max_level Maximum value of level values x x x
where_max_abs_level Domain entry of record with maximum absolute level value x x x
count_na_level Number of GAMS special values NA in level values x x x
count_undef_level Number of GAMS special values UNDEF in level values x x x
count_eps_level Number of GAMS special values EPS in level values x x x
min_marginal Minimum value of marginal values x x
mean_marginal Mean value of marginal values x x
max_marginal Maximum value of marginal values x x
where_max_abs_marginal Domain entry of record with maximum absolute marginal value x x
count_na_marginal Number of GAMS special values NA in marginal values x x
count_undef_marginal Number of GAMS special values UNDEF in marginal values x x
count_eps_marginal Number of GAMS special values EPS in marginal values x x

For Example, this looks like:

>> tbl = m.describeVariables();
>> tbl(:,1:10)
ans =
2×10 table
name type format dim domain_type domain size num_recs num_vals sparsity
____ ________ ______ ___ ___________ ______ _____ ________ ________ ________
x positive table 2 regular [i,j] [2,3] 6 12 0.6
z free struct 0 none [] [] 1 1 0.8
>> tbl(:,11:17)
ans =
2×7 table
min_level mean_level max_level where_max_abs_level count_na_level count_undef_level count_eps_level
_________ __________ _________ ___________________ ______________ _________________ _______________
0 150 300 [seattle,chicago] 0 0 0
153.68 153.68 153.68 [] 0 0 0
>> tbl(:,18:24)
ans =
2×7 table
min_marginal mean_marginal max_marginal where_max_abs_marginal count_na_marginal count_undef_marginal count_eps_marginal
____________ _____________ ____________ ______________________ _________________ ____________________ __________________
0 0.0075 0.036 [seattle,topeka] 0 0 0
NaN NaN NaN <undefined> 0 0 0

Indexed GDX

GDX files can be operated in two different modes, default and indexed (also called IDX), which are also supported by GAMS Transfer Matlab containers:

The mode – default or indexed – can be specified when creating a Container and cannot be changed thereafter:

c = Container('indexed', true);

In indexed mode, pass the shape of the symbol instead of the domain to the symbol constructor. For example, to create a 2x3 matrix parameter, do:

d = Parameter(m, 'd', [2, 3], 'description', 'distance in thousands of miles');
Note
The only supported symbols in indexed mode are Parameters.
In indexed mode it is not possible to set the property domain or using the UEL related methods (e.g. getUELs or setUELs), while in default mode the property size cannot be set and is inferred from by the domain.

Classes

class  BaseContainer
 Container base (only use subclasses) More...
 
class  ConstContainer
 GAMS Transfer ConstContainer stores (multiple) symbols (read-only) More...
 
class  Container
 GAMS Transfer Container stores (multiple) symbols. More...