Table of Contents
Introduction
In this chapter we explicitly cover only parameter manipulation, including all aspects of data handling. Much of this material is relevant elsewhere (e.g. to sets), but for specifics related to assignment to sets, to conditions, and to assignments within flow control constructs such as the loop
statement, see chapters Dynamic Sets, Conditional Expressions, Assignments and Equations and Programming Flow Control Features respectively.
Once initialized, data often requires manipulation in order to bring it into a form most suitable for use in a model or an application. The assignment statement is the way to do this. All the possible components of the assignment statement except conditions are introduced and discussed in this chapter.
The Assignment Statement
The assignment statement is the fundamental data manipulation statement in GAMS. It may be used to define or alter values associated with sets, parameters, variables or equations.
A simple assignment is written in the style associated with many other computer languages. GAMS uses the traditional symbols for addition (+)
, subtraction (-)
, multiplication (*)
and division (/)
. We will use them in the examples that follow, and give more details in section Expressions.
Scalar Assignments
Consider the following artificial sequence:
scalar x / 1.5 /;
x = 1.2;
x = x + 2;
The scalar x
is initialized to be 1.5. The second statement changes the value to 1.2, and the third changes it to 3.2. The second and third statements are assignments: each replaces the current value of x
with a new one.
Note that the same symbol can be used on the left and right of the =
sign. The new value is not available until the calculation is complete, and the operation gives the expected result.
- Note
- An assignment cannot start with a reserved word. A semicolon is therefore required as a delimiter before all assignments.
Note that extended range identifiers (e.g. INF
) and acronyms may also be used in assignment statements. For specific details, see sections Extended Range Arithmetic and Acronym Usage respectively.
Indexed Assignments
The GAMS syntax for performing indexed assignments is extremely powerful. This operation offers what may be thought of as simultaneous or parallel assignments and provides a concise way of specifying large amounts of data. Consider the mathematical statement \( DJ_d = 2.75 \cdot DA_d \) for all elements of \(d\). This means that for every member of the set \(d\), a value is assigned to \(DJ\). This can be written in GAMS as follows:
dj(d) = 2.75*da(d) ;
This assignment is known technically as an indexed assignment and set d
as the controlling index or controlling set.
- Attention
- The index set(s) on the left hand side of an indexed assignment are referred to synonymously as the controlling indices, controlling sets, or controlling domain of the assignment.
The extension to two or more controlling indices should be obvious. There will be an assignment made for each label combination that can be constructed using the indices inside the parentheses. Consider the following example of an assignment to all 100 data elements of the parameter a
.
sets row / r-1*r-10 /
col / c-1*c-10 /
sro(row) / r-7*r-10 / ;
parameters r(row) /r-1*r-7 4, r-8*r-10 5/
c(col) /c-1*c-5 3, c-6*c-10 2/;
parameters a(row,col);
a(row,col) = 13.2 + r(row)*c(col) ;
The calculation in the last statement is carried out for each of the 100 unique two-label combinations that can be formed from the elements of row
and col
. An explicit formulation of the first of these assignments follows:
a('r-1','c-1') = 13.2 + r('r-1')*c('c-1');
Note that for indexed assignments a copy of the symbols on the right hand side is installed before the assignment is carried out. That means it does not work "in-place" or recursively. Consider the following example where we compute the first ten Fibonacci numbers and store them in parameter f
using a loop. The example also illustrates how such a recursive calculation does not work with a parallel assignment statement for parameter g
.
set i / i1*i10 /
parameter
f(i) / i1 1 /
g(i) / i1 1 /;
loop(i$(ord(i)>=2),
f(i) = f(i-2) + f(i-1);
);
g(i)$(ord(i)>=2) = g(i-2) + g(i-1)
display f,g;
The display statement results in the following output.
---- 9 PARAMETER f i1 1.000, i2 1.000, i3 2.000, i4 3.000, i5 5.000 i6 8.000, i7 13.000, i8 21.000, i9 34.000, i10 55.000 ---- 9 PARAMETER g i1 1.000, i2 1.000, i3 1.000
Restricting the Domain in Assignments
Sometimes it is necessary to make assignments over selected elements of a set instead of over the entire domain. There are several ways to accomplish this: using explicit labels, subsets, conditionals and tuples.
Restricting the Domain: Explicit Labels
The strongest restriction of the domain is assigning a value to just one element. Labels may be used explicitly in the context of assignments to accomplish this. The following example illustrates:
a('r-7','c-4') = -2.36 ;
This statement assigns a constant value to just one element of the parameter a
. All other elements of a
remain unchanged. Labels must be quoted when used in this way.
Restricting the Domain: Subsets
In general, wherever a set name may occur in an indexed assignment, a subset may be used instead.
Consider the following example:
a(sro,'col-10') = 2.44 -33*r(sro) ;
Since the set sro
was declared as a subset of the set row
, we can use sro
as a controlling index in the assignment above to make the assignment only for the elements of sro
.
Restricting the Domain: Conditionals
Conditional assignments are discussed in detail in section Conditional Assignments in chapter Conditional Expressions, Assignments and Equations. For details on the types of logical conditions, see section Logical Conditions. Here we present a simple example to illustrate:
a(row,col)$[a(row,col) >= 100] = INF ;
This assignment has the following effect: all elements of the parameter a
whose value was at least 100 are assigned the value INF, while all other elements of a
remain unchanged.
Restricting the Domain: Tuples
Tuples or multi-dimensional sets are introduced in section Many-to-Many Mapping. In this simple example we show how they may be used to restrict the domain. The example builds on the first example in this section. We repeat the whole code here for clarity.
sets row / r-1*r-10 /
col / c-1*c-10 /
sro(row) / r-7*r-10 / ;
set tuple(row,col) /r-1.c-1, r-1.c-10, r-10.c-1, r-10.c-10/;
parameters r(row) /r-1*r-7 4, r-8*r-10 5/
c(col) /c-1*c-5 3, c-6*c-10 2/;
parameters a(row,col), b(row,row);
a(row,col) = 13.2 + r(row)*c(col) ;
a(tuple(row,col)) = 7 + r(row)*c(col) ;
a(tuple) = 0.25 * a(tuple) ;
Note that we have introduced the new set tuple
. It is two-dimensional and contains just four elements. As before, the parameter a
is first assigned values for all its 100 elements. We then change some of these values using the set tuple
as domain. The values of the elements of the parameter a
that are not elements of the set tuple
remain unchanged.
For a more elaborate example involving tuples, see section Filtering Sets in Assignments.
Issues with Controlling Indices
- Attention
- The number of controlling indices on the left of the
=
sign should be at least as large as the number of indices on the right. There should be no index on the right-hand side of the assignment that is not present on the left unless it is operated on by an indexed operator. For more on indexed operators, see section Indexed Operations.
Consider the following statement:
a(row,'col-2') = 22 - c(col) ;
GAMS will flag this statement as an error since col
is an index on the right-hand side of the equation but not on the left.
Note that there would be no error here if col
were a singleton set
. Since there is only one element in a singleton set, the intent and behavior is well-defined even when col
is not under control.
- Attention
- Each set is counted only once to determine the number of controlling indices. If the intent is for a set to appear independently more than once within the controlling domain, the second and subsequent occurrences of the set should be
aliases
of the original set, so that the number of controlling indices is equal to the number of indices. For details on aliases, see section The Alias Statement: Multiple Names for a Set.
Consider the following statement as an illustration:
b(row,row) = 7.7 - r(row) ;
This statement has only one controlling index, namely row
. One element (on the diagonal of b
) is assigned for each element of row
, for a total of 10 assigned values. None of the off-diagonal elements of b
will be changed!
If the intent is to assign values to each element of b
, this can be done by introducing an alias rowp
for row
and using this alias in the second index position. There will then be two controlling indices and GAMS will make assignments over all 100 values of the full Cartesian product. The following example illustrates this method:
alias(row,rowp) ;
b(row,rowp) = 7.7 - (r(row) + r(rowp))/2 ;
Expressions
An expression is an arbitrarily complicated specification for a calculation, with parentheses nested as needed for clarity and intent. In this section the discussion of parameter assignments will continue by showing in more detail the expressions that may be used on the right of the =
sign. We will cover standard arithmetic operations and indexed operations here, and functions and extended range arithmetic in the next two sections.
Standard Arithmetic Operations
The standard arithmetic symbols and operations and their order of precedence are given in Table 1. Note that 1 denotes the highest order of precedence and 3 denotes the lowest order of precedence. Parentheses can be used to override the default precedence order in the usual way. Operators (including exponentiation) on the same level are evaluated from left to right.
Operation | Symbol | Order of Precedence |
---|---|---|
Exponentiation | ** | 1 |
Multiplication | * | 2 |
Division | / | 2 |
Addition | + | 3 |
Subtraction | - | 3 |
Table 1: Standard Arithmetic Operations
Note that the full GAMS operator precedence hierarchy also includes logical operators; it is given in section Mixed Logical Conditions. Note further that the symbols for addition, subtraction and multiplication have a different meaning if they are used in the context of sets. For details see sections Set Operations and Lag and Lead Operators.
- Attention
- The operation
x**y
is equivalent to the function rPower(x,y) and is calculated internally as \(e^{y \times \log(x)}\). This operation is not defined if \(x\) is negative; an error will result in this case. If the possibility of negative values for \(x\) is to be admitted and the exponent is known to be an integer, then the function power(x,n) may be used. -
Like many GAMS intrinsic functions, the operation
x**y
is not defined for all possible input values. When evaluating nonlinear functions and operators GAMS guards against evaluating at or very near singular points and in such cases signals an error or returns an appropriate function value.
- Note
- As usual, operations within parentheses or brackets are evaluated before other numerical calculations, where the innermost parentheses are resolved first. Any of the pairs
()
,[]
and{}
are allowed.
Consider for example:
x = 5 + 4*3**2;
For clarity, this could have been written as follows:
x = 5 + (4*[3**2]) ;
In both cases the result is 41.
- Note
- It is often better to use parentheses than to rely on the order of precedence of operators, since this prevents errors and clarifies intentions.
Note that expressions may be freely continued over many lines: an end of line is permissible at any point where a blank may be used. Blanks may be used for readability around identifiers, parentheses and operation symbols. Blanks are not allowed within identifiers or numbers, and are significant inside the quotes used to delimit labels.
Indexed Operations
In addition to the simple operations in Table 1, GAMS also provides the following six indexed operations.
Operation | Keyword |
---|---|
Summation | sum |
Product | prod |
Minimum value | smin |
Maximum value | smax |
Conjunction | sand |
Disjunction | sor |
Table 2: Indexed Operations
These six operations are performed over one or more controlling indices. The syntax in GAMS for these operations is:
indexed_op( (index_list), expression);
Indexed_op
is one of the four keywords for indexed operations, index_list
is the list of the controlling indices and expression
is the expression to be evaluated. If there is only one controlling index, the parentheses around it may be removed. Consider the following simple example adapted from [ANDEAN]:
sets i plants / cartagena, callao, moron /
m product / nitr-acid, sulf-acid, amm-sulf /;
parameter capacity(i,m) capacity in tons per day
totcap(m) total capacity by process ;
totcap(m) = sum(i, capacity(i,m));
The index over which the summation is done, i
, is separated from the reserved word sum
by a left parenthesis and from the data term capacity(i,m)
by a comma. The set i
is called the controlling index for this operation. The scope of the control is the pair of parentheses ()
that start immediately after the sum. Note that using normal mathematical representation the last line could be written as: \(totC_m = \sum_i C_{im}\).
It is also possible to sum simultaneously over the domain of two or more sets as in the first assignment that follows. The second assignment demonstrates the use of a less trivial expression than an identifier within the indexed operation.
count = sum((i,j), a(i,j)) ;
emp = sum(t, l(t)*m(t)) ;
The equivalent mathematical forms are:
\[ count = \sum_i\sum_j A_{ij} \quad \textrm{and} \quad emp = \sum_t L_t M_t. \]
Note that the following alternative notation may be used for the first assignment above:
count = sum(i, sum(j, a(i,j)));
In the context of sets the sum
operator may be used to compute the number of elements in a set and for projections. For details see section Projection and Aggregation of Sets.
The smin
and smax
operations are used to find the largest and smallest values over the domain of the index set or sets. The index for the smin
and smax
operators is specified in the same manner as in the index for the sum
operator. In the following example we want to find the largest capacity:
lrgunit = smax((i,m),capacity(i,m));
- Attention
- The indexed operations
smin
andsmax
may be used in equation definitions only if the corresponding model is of type DNLP. For more on GAMS model types, see GAMS Model Types.
- Note
- In the context of assignment statements, the attributes of variables and equations (e.g.
x.up(i,j)
) may be used in indexed operations just as scalars and parameters are used. For more on variable and equations attributes, see sections Variable Attributes and Equation Attributes respectively. - In the context of equation definitions, scalars, parameters and variables may appear freely in indexed operations. For more on equation definitions, see section Defining Equations.
- In the context of assignment statements, the attributes of variables and equations (e.g.
Sometimes it is necessary to restrict the domain of indexed operations. This may be done with the same techniques as in indexed assignments, see section Restricting the Domain in Assignments for details. See also section Conditional Indexed Operations for more details on conditions in the context of indexed operations.
We now turn to two additional capabilities that are available in GAMS to add power and flexibility to expression calculations: functions and extended range arithmetic.
Functions
Functions play an important role in the GAMS language, especially for nonlinear models. Like other programming languages, GAMS provides a number of built-in or intrinsic functions. GAMS is used in an extremely diverse set of application areas and this creates frequent requests for the addition of new and quite sophisticated or specialized functions. There is a trade-off between satisfying these requests and avoiding a complexity not needed by most users. The GAMS Function Library Facility provides the means for managing this trade-off, see subsection Extrinsic Functions below.
Intrinsic Functions
GAMS provides many functions, ranging from commonly used standard functions like exponentiation, logarithms, and trigonometric functions to utility functions for controlling and querying the running GAMS job or process. The complete list of available functions is given in the following tables: Mathematical Functions, String Manipulation Functions, Logical Functions, Time and Calendar Functions, and GAMS Utility and Performance Functions. For details specific to using these functions in equations, see the section on Expressions in Equation Definitions.
Some of the tables that follow contain an endogenous classification column "End. Classif." that specifies in which models the function may legally appear. In order of least to most restrictive, the choices are DNLP, NLP, any, none. See section Classification of Models for details on model types in GAMS. Note well: functions classified as any are only permitted with exogenous (constant) arguments.
Functions are typically used in assignment statements and equations. In these cases, they are only evaluated at execution time. Some functions can also be used at compile time, e.g. to compute the factorial or square root of a scalar. Some of the tables below contain a column "Compile Time" indicating which functions can be used at compile time.
A word on the notation in the tables below: for function arguments, lower case indicates that an endogenous variable is allowed. For details on endogenous variables, see section Functions in Equation Definitions. Upper case function arguments indicate that a constant is required. Arguments in square brackets may be omitted: the default values used in such cases are specified in the function description provided.
Mathematical Functions
Mathematical functions may be used as expressions in assignment statements and in equation definitions. We start with some simple examples to illustrate. A list with all mathematical functions available in GAMS is given in Table 3.
Exp(x)
a = exp(t);
b = exp(t+2);
The GAMS function exp(x)
returns the exponential \(e^x\) of its argument. The assignments above set \(a=e^t\) and \(b=e^{t+2}\) respectively.
Log(x)
z(j) = log(y(j));
The GAMS function log(x)
returns the natural logarithm of its argument. The assignment above evaluates the logarithm once for each element of the controlling domain j
.
Max(x1,x2,x3,...)
x = max(y+2, t, t*t);
The function max
returns the maximum of a set of expressions or terms. In the assignment above, x
will be assigned the maximum of \(y+2\), \(t\), and \(t \cdot t\).
Round(x[,DECPL])
The function round
rounds its argument x
to the specified number DECPL
of places, where positive values of DECPL
indicating rounding to the right of the decimal point. If the argument DECPL
is not specified, it defaults to zero, and the function rounds its argument to the nearest integer value. For example,
x = round(q);
y = round(q,d);
z = round(12.432,2);
h = round(515.5,-1);
In the first assignment q
is rounded to the nearest integer value, while in the second q
is rounded to the number of decimals specified by d
. The result of the third assignment is 12.43, while the final assignment results in a value of 520.
Table 3: Mathematical Functions
Function | Description | End. Classif. | Compile Time |
---|---|---|---|
abs(x) | Absolute value of the argument \(x\). | DNLP | yes |
arccos(x) | Inverse cosine of the argument \(x\), where \(x\) is a real number between -1 and 1 and the output is in radians, see MathWorld | NLP | no |
arcsin(x) | Inverse sine of the argument \(x\), where \(x\) is a real number between -1 and 1 and the output is in radians, see MathWorld | NLP | no |
arctan(x) | Inverse tangent of the argument \(x\), where \(x\) is a real number and the output is in radians, see MathWorld | NLP | no |
arctan2(y,x) | Four-quadrant arctan function yielding \( \arctan(\frac{y}{x})\) which is the angle the vector \((x,y) \) makes with (1,0) in radians. | NLP | no |
beta(x,y) | Beta function: \( B(x,y) = \frac{\Gamma(x)\Gamma(y)}{\Gamma(x+y)}\), see MathWorld | DNLP | no |
betaReg(x,y,z) | Regularized beta function, see MathWorld | NLP | no |
binomial(n,k) | (Generalized) Binomial coefficient for \( n > -1\), \( -1 < k < n+1 \). | NLP | no |
ceil(x) | Ceiling: returns the smallest integer greater than or equal to \(x\). | DNLP | yes |
centropy(x,y[,Z]) | Cross-entropy: \(\begin{cases} x \cdot \ln(\frac{x+Z}{y+Z}), & \text{if } x > 0, \\ 0,& \text{if } x = 0,\end{cases}\) where \(y > 0\), \(Z \geq 0\). Default \(Z=10^{-20}.\) | NLP | no |
cos(x) | Cosine of the argument \(x\), where \(x\) must be in radians, see MathWorld | NLP | yes |
cosh(x) | Hyperbolic Cosine of \(x\), where \(x\) must be in radians, see MathWorld | NLP | no |
cvPower(X,y) | Real power: \(\begin{cases} X^{y}, & \text{if } X>0, \\ 0, & \text{if } X = 0 \;(\text{also for } y \leq 0!).\end{cases}\) | NLP | no |
div(dividend,divisor) | Returns \(\frac{\text{dividend}}{\text{divisor}}\), but undefined for \(\text{divisor}=0\). | NLP | no |
div0(dividend,divisor) | Returns \( \frac{\text{dividend}}{\text{divisor}}\), but \(10^{299}\) for \(\text{divisor}=0\). | NLP | no |
eDist(x1[,x2,x3,...]) | Euclidean or L-2 Norm: \(\sqrt{ x_{1}^{2} + x_{2}^{2} + ... }\). | NLP | no |
entropy(x) | Entropy: \(\begin{cases}-x\cdot\ln(x), & \text{if } x>0, \\ 0, & \text{if } x=0.\end{cases}\) | NLP | no |
errorf(x) | Integral of the standard normal distribution from negative infinity to \(x\): \(\frac{1}{\sqrt{2\pi}} \int\limits_{-\infty}^x e^{\frac{-t^{2}}{2}}dt\). | NLP | no |
execSeed | Reads or resets the seed for the random number generator (RNG). Note that the state of the RNG cannot typically be captured in one seed value; in such cases "reading" the seed involves harvesting a seed from the RNG, resetting the RNG with this seed, and returning the seed. | none | no |
exp(x) | Exponential of \(x\): \(e^{x}\), see MathWorld | NLP | yes |
fact(N) | Factorial of \(N\), where \(N \geq 0\) is an integer. \(0!=1\). | any | yes |
floor(x) | Floor: greatest integer less than or equal to \(x\). | DNLP | yes |
frac(x) | Returns the fractional part of \(x\), s.t. x = trunc(x) + frac(x) | DNLP | yes |
gamma(x) | Gamma function : \( \Gamma(x)= \int\limits_{0}^{\infty} t^{x-1}e^{-t}dt\), see MathWorld | NLP | no |
gammaReg(x,a) | Lower Incomplete Regularized Gamma function, see GammaRegularized[a,0,x] in MathWorld | NLP | no |
log(x) | Natural logarithm: logarithm base \(e\), see MathWorld | NLP | yes |
logBeta(x,y) | Log Beta function: \(\log(B(x,y))\). | NLP | no |
logGamma(x) | Log Gamma function as discussed in MathWorld | NLP | no |
logit(x) | Logit Transformation: \(\log(x/(1-x))\), see MathWorld | NLP | yes |
log10(x) | Common logarithm: logarithm base 10, see MathWorld | NLP | yes |
log2(x) | Binary logarithm: logarithm base 2, see MathWorld | NLP | yes |
lseMax(x1[,x2,x3,...]) | Smoothed Max via the Logarithm of the Sum of Exponentials: \(\ln{(e^{x_{1}} + e^{x_{2}} + ... )}\), see Wikipedia | NLP | no |
lseMaxSc(T,x1[,x2,x3,...]) | Scaled smoothed Max via the Logarithm of the Sum of Exponentials: lseMaxSc(T,x) = lseMax(Tx)/T , see Wikipedia | NLP | no |
lseMin(x1[,x2,x3,...]) | Smoothed Min via the Logarithm of the Sum of Exponentials: \(-\ln{(e^{-x_{1}} + e^{-x_{2}} + ... )}\), see Wikipedia | NLP | no |
lseMinSc(T,x1[,x2,x3,...]) | Scaled smoothed Min via the Logarithm of the Sum of Exponentials: lseMinSc(T,x) = lseMin(Tx)/T , see Wikipedia | NLP | no |
max(x1,x2,x3,...) | Maximum value of the arguments, where the number of arguments may vary. | DNLP | yes |
min(x1,x2,x3,...) | Minimum value of the arguments, where the number of arguments may vary. | DNLP | yes |
mod(x,y) | Remainder of \(x\) divided by \(y\). | DNLP | yes |
ncpCM(x,y,Z) | Chen-Mangasarian smoothing: \(x-Z\cdot \ln(1+e^{\frac{x-y}{Z}})\). | NLP | no |
ncpF(x,y[,Z]) | Fisher-Burmeister smoothing: \(\sqrt{(x^{2}+y^{2}+2\cdot Z)}-x-y\), \(Z\geq0\). Default \(Z=0\). | NLP | no |
ncpVUpow(r,s[,μ]) | NCP Veelken-Ulbrich (smoothed min(r,s)): \( \begin{cases} \frac{1}{2}(r + s - \vert r-s \vert), & \text{if } \vert r-s \vert \geq \mu \geq 0,\\ \frac{1}{2}(r + s - \frac{\mu}{8} \cdot (- (\frac{r-s}{\mu})^{4}+6(\frac{r-s}{\mu})^{2} +3)), & \text{otherwise}. \end{cases}\) Default \(\mu=0\). | NLP | no |
ncpVUsin(r,s[,μ]) | NCP Veelken-Ulbrich (smoothed min(r,s)): \( \begin{cases} \frac{1}{2}(r + s - \vert r-s \vert), & \text{if } \vert r-s \vert \geq \mu \geq 0,\\ \frac{1}{2}(r + s - (\frac{2\mu}{\pi} \sin(\frac{\pi}{2\mu} +\frac{3\pi}{2})+\mu)), & \text{otherwise}. \end{cases}\) Default \(\mu=0\). | NLP | no |
normal(MEAN,STDDEV) | Generate a random number from the normal distribution with mean MEAN and standard deviation STDDEV , see MathWorld | none | no |
pi | Value of \( \mathbf{\pi=3.141593...}\). | any | yes |
poly(x,A0,A1,A2[,A3,...]) | Returns \(p(x)\), where the polynomial \(p(x) = A_{0}+A_{1}x+A_{2}x^{2}+A_{3}x^{3}+...+A_{20}x^{20}\). By default \(A_{3},...,A_{20}=0\). | NLP | no |
power(x,Y) | Returns \( x^Y\), where \(Y\) must be an integer. \(0^Y = \begin{cases} 0, & \text{if } Y > 0, \\ 1, &\text{if } Y=0, \\ \text{undefined}, & \text{if } Y < 0. \end{cases}\) | NLP | no |
randBinomial(N,P) | Generate a random number from the binomial distribution, where \(N\) is the number of trials and \(P\) the probability of success for each trial, see MathWorld | none | no |
randLinear(LOW,SLOPE,HIGH) | Generate a random number between LOW and HIGH with linear distribution, SLOPE must be greater than \(\frac{2}{\text{HIGH}-\text{LOW}}\) | none | no |
randTriangle(LOW,MID,HIGH) | Generate a random number between LOW and HIGH with triangular distribution, MID is the most probable number, see MathWorld | none | no |
round(x[,DECPL]) | Round \(x\) to DECPL decimal places. Default DECPL=0 | DNLP | yes |
rPower(x,y) | Returns \(\begin{cases} x^{y},& \text{if } x > 0,\\ 0, &\text{if } x=0,y>0, \\ 1, &\text{if } x=y=0.\end{cases}\) This function is equivalent to the operation x**y , see Standard Arithmetic Operations. | NLP | no |
sigmoid(x) | Sigmoid: \(\frac{1}{1+e^{-x}}\), see MathWorld | NLP | no |
sign(x) | Sign of \(x\): \(\begin{cases} 1, & \text{if } x > 0, \\ 0, & \text{if } x = 0, \\ -1, & \text{if } x < 0.\end{cases}\) | DNLP | yes |
signPower(x,Y) | Signed power: \(\text{sign}(x)\vert x\vert^{Y}\) for \(Y>0\). | NLP | no |
sin(x) | Sine of the argument \(x\), where \(x\) must be in radians, see MathWorld | NLP | yes |
sinh(x) | Hyperbolic sine of \(x\), where \(x\) must be in radians, see MathWorld | NLP | no |
slexp(x[,S]) | Smooth (linear) exponential: \( \begin{cases} e^{x}, & \text{if } x \leq S, \\ e^{x} \cdot (1 + (x - S)), & \text{otherwise}, \end{cases} \) where \(S\leq 150\). Default \(S=150\). | NLP | no |
sllog10(x[,S]) | Smooth (linear) logarithm base 10: \( \begin{cases} \log_{10}(x), & \text{if } x \geq S, \\ \frac{1}{\ln(10)} \cdot (\ln S + \frac{x - S}{S}), & \text{otherwise}, \end{cases} \) where \(S \geq 10^{-150}.\) Default \(S=10^{-150}\). | NLP | no |
slrec(x[,S]) | Smooth (linear) reciprocal: \( \begin{cases} \frac{1}{x}, & \text{if } x \geq S, \\ \frac{1}{S} - \frac{x - S}{S^2}, & \text{otherwise}, \end{cases}\) where \(S \geq 10^{-10}\). Default \(S=10^{-10}\). | NLP | no |
sqexp(x[,S]) | Smooth (quadratic) exponential: \( \begin{cases} e^{x}, & \text{if } x \leq S, \\ e^{x} \cdot (1 + (x - S) + \frac{{(x - S)}^{2}}{2}), & \text{otherwise}, \end{cases} \) where \(S\leq 150\). Default \(S=150\). | NLP | no |
sqlog10(x[,S]) | Smooth (quadratic) logarithm base 10: \( \begin{cases} \log_{10}(x), & \text{if } x \geq S, \\ \frac{1}{\ln(10)} \cdot (\ln S + \frac{x - S}{S} - \frac{(x - S)^2}{2S^2}), & \text{otherwise}, \end{cases} \) where \(S \geq 10^{-150}\). Default \(S=10^{-150}\). | NLP | no |
sqrec(x[,S]) | Smooth (quadratic) reciprocal: \( \begin{cases} \frac{1}{x}, & \text{if } x \geq S, \\ \frac{1}{S} - \frac{x - S}{S^2} + \frac{(x - S)^2}{S^3}, & \text{otherwise}, \end{cases} \) where \(S\geq 10^{-10}\). Default \(S=10^{-10}\). | NLP | no |
sqr(x) | Square of argument \(x\). | NLP | yes |
sqrt(x) | Square root of \(x\), see MathWorld | NLP | yes |
tan(x) | Tangent of the argument \(x\), where \(x\) must be in radians, see MathWorld | NLP | yes |
tanh(x) | Hyperbolic tangent of \(x\), where \(x\) must be in radians, see MathWorld | NLP | no |
trunc(x) | Truncation: returns the integer part of \(x\), truncating towards zero. | DNLP | yes |
uniform(LOW,HIGH) | Generates a random number from the uniform distribution between LOW and HIGH , see MathWorld | none | yes |
uniformInt(LOW,HIGH) | Generates an integer random number from the discrete uniform distribution whose outcomes are the integers between LOW and HIGH , inclusive, see MathWorld | none | no |
vcPower(x,Y) | Returns \(x^{Y}\) for \(x\geq0\). \(0^0=1\). | NLP | no |
String Manipulation Functions
GAMS provides some string manipulation capability by extending the card and ord operators to work on strings as well as sets. In Table 4 the extended behavior is described. In this context, the functions take strings and places as arguments, and the numeric places argument must be a constant. This behavior only applies to execution-time usage of these functions.
Table 4: String Manipulation Functions
There are four types or sources of strings in this context. A string may be a string literal, i.e. a concatenation of letters and blanks as in "drink it"
in the example that follows. It may be the symbol text (aka the explanatory text) associated with any symbol. Or it may be the labels or text associated with the elements of a set. The following table gives an overview:
Notation | Description | Comments |
---|---|---|
characters | A concatenation of characters and blanks: all legal GAMS characters are allowed, see section Characters for details. | The characters must be surrounded by double or single quotes. |
symbol_name.ts | The string is the explanatory text associated with a symbol name. | If the explanatory text is missing, the value of card is 0. |
set_name.tl | The string is the label for a set element. | This string type may be used only when set_name is part of the controlling domain. |
set_name.te | The string is the explanatory text associated with a set element. | This string type may be used only when set_name is part of the controlling domain. If the explanatory text is missing, the value of card is 0. |
The string types are illustrated in the following example. Note that the directive in the first line activates the end-of-line comment option, see eolCom.
$oneolcom
variable z 'any symbol can have explanatory text';
set teas "teas available to order" / black "English Breakfast", green, peppermint /;
scalar p;
p = card("drink it"); !! result: p=8
p = card(z.ts); !! result: p=36
p = card(teas.ts); !! result: p=23
loop{teas,
p = card(teas.tl) !! length of set element label from the set "teas": "teas" is the controlling set
display "length of set element label", p;
p = card(teas.te) !! length of set element explanatory text: "teas" is the controlling set
display "length of set element explanatory text", p;
};
Note that the strings teas.tl
and teas.te
are used in the context of a loop
statement (see section The Loop Statement). This is a typical usage pattern.
Logical Functions
Logical functions may be used as expressions in assignment statements as in the following example.
x = ifthen(tt=2, 3, 4+y);
Here \(x=3\) if \(tt=2\), otherwise \(x=4+y\).
The logical functions available in GAMS are given in Table 6. Note that logical functions may also be used in conditions and logic equations, see sections Logical Conditions and Logic Equations respectively. Most of the logical functions can also be indicated using the familiar operator notation, e.g. (x and y), (x >= y), etc. In such cases, the operator notation is allowed at compile time. The last column in Table 6 indicates if a logical function can be used at compile time (yes) or if only its alternative notation is available (alt). Further, note that the inputs and outputs of these functions are often logical/Boolean values, so GAMS does implicit conversions as necessary. As expected, false becomes 0 and true becomes 1 when converting logical values to numeric, and 0 becomes false and nonzero becomes true when numeric values are converted to logicals. For details on behavior when the inputs are special values, see sections Extended Range Arithmetic and Acronym Usage, but note that EPS
, +INF
, -INF
, and acronyms become true when converted to logicals.
Time and Calendar Functions
GAMS offers several functions that relate to time and dates. The fundamental measurement of time in GAMS is the serial day number beginning with January 1, 1900. This serial day number is a real number whose integer part contains a unique number for each day and whose fractional part contains information about hours, minutes, and seconds. We can think of the serial day number as being a date.time
pair. The day information extracted from serial day numbers is based on the Gregorian calendar.
- Note
- In all functions given in Table 7, serial day 1 is January 1, 1900.
All of the functions in Table 7 can be used at compile time.
Table 7: Time and Calendar Functions
GAMS Utility and Performance Functions
GAMS provides several functions that may be used to get (and in some cases set) GAMS system information, for example:
scalar o;
o = heapLimit;
heapLimit = 1024;
Table 8: GAMS Utility and Performance Functions
Function | Description | End. Classif. | Compile Time |
---|---|---|---|
embeddedHandle | Returns the handle for the last embedded code section executed, see section Syntax in chapter Embedded Code Facility for details. | none | no |
errorLevel | Return code of the most recently used command. | none | yes |
execError | Get or set the number of execution errors. | none | no |
gamsRelease | Returns the release number of the running GAMS system, for example 24.7. | none | yes |
gamsVersion | Returns the version number of the running GAMS system, for example 247. | none | yes |
handleCollect(HANDLE) | Tests if the solve of the model instance identified by the calling argument HANDLE is done: if so, it loads the solution into GAMS. For details, see Table 1 in section Grid Computing. | none | no |
handleDelete(HANDLE) | Deletes the model instance identified by HANDLE . For details, see Table 1 in section Grid Computing. | none | no |
handleStatus(HANDLE) | Tests if the solve of the model instance identified by HANDLE is done: if so, it loads the solution into a GDX file. For details, see Table 1 in section Grid Computing. | none | no |
handleSubmit(HANDLE) | Resubmits the model instance identified by HANDLE for solution. For details, see Table 1 in section Grid Computing. | none | no |
heapFree | Get the amount of free memory in the heap in MB, i.e. memory allocated to the process and available for future use by GAMS. | none | no |
heapLimit | Get or set the current heap limit (maximum allowable dynamic memory usage) in Mb. | none | no |
heapSize | Get the current heap size in Mb. | none | no |
jobHandle | Returns the process ID (PID ) of the last job started. | none | yes |
jobKill(PID) | Sends a kill signal to the job with process ID PID . The return value is 1 if this was successful, 0 otherwise. | none | yes |
jobStatus(PID) | Get the status of the job with process ID PID . Possible return values are: 0: error (input is not a valid PID or access is denied) 1: process is still running 2: process is finished with return code which could be accessed by errorlevel 3: process not running anymore or was never running, no return code available | none | yes |
jobTerminate(PID) | Sends an interrupt signal to the job with process ID PID . The return value is 1 if this was successful, 0 otherwise. | none | yes |
licenseLevel | Get an indicator for the type of license: 0: demo license, limited to small models 1: full unlimited developer license 2: run time license, no new variables or equations can be introduced besides those inherited from a work file 3: application license, only works with a specific work file which is locked to the license file 5: community license, limited to somewhat bigger models compared to demo license. | any | no |
licenseStatus | Returns non-zero if a license error has occurred. | any | no |
mapVal(x) | Returns an integer value that indicates what special value (if any) is stored in the input \(x\). Possible results: 0: \(x\) is not a special value 4: \(x\) is UNDF (undefined)5: \(x\) is NA (not available)6: \(x\) is INF ( \(\infty\)) 7: \(x\) is -INF ( \(-\infty\)) 8: \(x\) is EPS >8: \(x\) is an acronym | any | no |
maxExecError | Get or set the maximum number of execution errors. See also maxExecError. | none | no |
numCores | Get the number of logical CPU cores in the system | any | yes |
platformCode | Returns an integer indicating the current platform. Possible return values can be seen here. | any | yes |
readyCollect(HANDLES[,MAXWAIT]) | Waits until a model solution is ready to be collected. For details, see Table 1 in section Grid Computing. | none | no |
sleep(SEC) | Pause or sleep execution for SEC seconds. | none | yes |
timeClose | Returns the accumulated closedown time, i.e. the time GAMS uses to save its state to disk prior to a solve. | none | no |
timeComp | Returns the compilation time in seconds. | none | no |
timeElapsed | Returns the elapsed time since the start of a GAMS run in seconds. | none | no |
timeExec | Returns the execution time in seconds. | none | no |
timeStart | Returns the accumulated startup time, i.e. the time GAMS uses to restore its state from disk after a solve. | none | no |
Extrinsic Functions
Using the GAMS Function Library Facility, functions may be imported from an external library into a GAMS model. Apart from the import syntax, the imported functions may be used in the same way as intrinsic functions. In particular, they may be used in equation definitions. Some function libraries are included with the standard GAMS software distribution, but GAMS users can also create their own libraries using an open programming interface. The GAMS Test Library instances [TRILIB01], [TRILIB02], [TRILIB03], and [CPPLIB00] are simple examples (in the programming languages C, Delphi, Fortran and C++, respectively) that come with every GAMS system.
For details on using and creating extrinsic function libraries, and on the extrinsic function libraries that are provided with GAMS, see the chapter on Extrinsic Functions.
Function Suffixes
Up to this point, this section has described and discussed functions without mentioning their derivatives. These derivatives are very important, though: most of the nonlinear solvers integrated with GAMS will require first derivatives to solve models, and many will also use or require second derivatives as well. It is sometimes useful (e.g. when testing an extrinsic function) to evaluate the derivatives of GAMS functions instead of the functions themselves. This can be done via function suffixes.
Function suffixes can specify the evaluation of a gradient (i.e. first derivative), a Hessian (i.e. second derivative), a minimum or maximum value of the function over a given range, or the minimum or maximum value of the gradient over a given range. A full list of function suffixes is given in Table 9. For functions whose arguments are constant, the derivatives are zero, so typically func
is a mathematical function listed in Table 3 above. Note that function suffixes are not defined for functions without arguments (for example, pi
), so specifying something like pi.grad
results in a compilation error.
Consider the following simple example:
scalars g, l, h, gl, gh;
g = sin.grad(0);
l = sin.low(pi/3:pi/2);
h = sin.high(pi/3:pi/2);
gl = sin.gradL(pi/3:pi/2);
gh = sin.gradH(pi/3:pi/2);
display g, l, h, gl, gh;
For univariate functions like sine or cosine, there is no need to specify a variable index when evaluating derivatives. For multivariate functions, the default is to take partial derivatives w.r.t. the first variable. To specify other variables, the colon syntax in the example below is used.
scalars
x / 1 /
ylo / -1 /
yup / 2 /
e0, e1, elo, ehi
e_1, e_2
e_11, e_22, e_21
;
e0 = edist(x,ylo);
e1 = edist(x,yup);
elo = edist.low (x,ylo:x,yup);
ehi = edist.high(x,ylo:x,yup);
e_1 = edist.grad(x,yup);
* e_1 = edist.grad(1:x,yup); same as above
e_2 = edist.grad(2:x,yup);
e_11 = edist.hess(x,yup);
* e_11 = edist.hess(1:1:x,yup); same as above
e_22 = edist.hess(2:2:x,yup);
e_21 = edist.hess(2:1:x,yup);
display x, ylo, yup, e0, e1, elo, ehi, e_1, e_2, e_11, e_22, e_21;
For more examples, see model [FUNCS4] in the GAMS Test Library.
- Note
- The function suffixes
value
,grad
,gradn
,hess
andhessn
are also defined for extrinsic functions. When implementing an extrinsic function, be aware that missing derivatives will be computed numerically: see model [TRILIB01] for an example.
- The function suffixes
To compute derivatives numerically, GAMS uses finite difference approximations. This computation can be controlled with two options: the FDOpt option controls which variant of the finite difference method is used, while the FDDelta option controls the step size.
Extended Range Arithmetic and Error Handling
GAMS uses an extended range arithmetic to handle missing data, the results of undefined operations, infinite values, and zeros that are stored explicitly. The special values used in this arithmetic are listed and described in Table 10 below, along with the value of the mapVal function that corresponds to these values. We can think of special values as any value for which mapVal does not return 0.
Special value | Description | mapVal |
---|---|---|
INF | Plus infinity. Similar to IEEE plus infinity. Behaves in the expected way in computations, so that e.g. min(x,INF) = x unless x is also special. | 6 |
-INF | Minus infinity. Similar to IEEE minus infinity. Behaves in the expected way in computations, so that e.g. max(x,INF) = x unless x is also special. | 7 |
NA | Not available - used to indicate missing data. It is a sticky value: e.g. max(x,NA) = NA even for x = INF | 5 |
UNDF | Undefined - indicates the result of an undefined or illegal operation. Similar to IEEE NaN. A user cannot directly set a value to UNDF unless the dollar control option onUNDF is active. For details, see the chapter on Dollar Control Options. | 4 |
EPS | A stored zero value. If the dollar control option onEPS is active, zeros in a parameter or table statement are treated as EPS . For details on dollar control options, see chapter Dollar Control Options. | 8 |
Table 10: Special Values for Extended Range Arithmetic
- Attention
- Avoid creating or using numbers with very large (
1.0e299
or above) or very small (1.0e-299
or below) magnitudes. Large numbers may be treated by GAMS as undefined (UNDF
) or other special values, leading to unpredictable and unusable results. Always useINF
(or-INF
) explicitly for arbitrarily large (or small) numbers.
GAMS has defined the results of all arithmetic operations and all function evaluations that use these special values. The behavior is designed to both maximize utility and minimize surprise, and is illustrated in the library model [CRAZY]. For example: 1+INF
evaluates to INF
, 1-EPS
to 1
, NA
* 2 to NA
, and EPS*INF
to UNDF
.
The following table shows a selection of results for exponentiation and division for a variety of input parameters including NA
and INF
.
a | b | a**b | power(a,b) | a/b |
---|---|---|---|---|
2 | 2 | 4 | 4 | 1 |
-2 | 2 | UNDF | 4 | -1 |
2 | 2.1 | 4.28 | UNDF | .952 |
NA | 2.5 | NA | NA | NA |
3 | 0 | 1 | 1 | UNDF |
INF | 2 | INF | INF | INF |
2 | INF | UNDF | UNDF | 0 |
Table 11: Extended Range Arithmetic in Exponentiation and Division
Note that most extended range identifiers may be used in assignment statements, as illustrated below.
a(row,'col-3') = NA;
a(row,'col-4') = INF;
a(row,'col-5') = -INF;
The values most often used in assignments are NA
in incomplete tables and INF
for variable bounds.
The special value EPS
is numerically equal to zero, so when used in the context of numerical comparisons, it behaves as zero. For example, the logical expressions x > 0
and x > EPS
have the same result. However, EPS is a stored zero, so setting a parameter to zero (e.g. a(row,col)=0
) results in no values being stored for a
, while setting a parameter to EPS (e.g. a(row,col)=EPS
) results in the value EPS being stored for every (row,col)
tuple. This is sometimes useful, especially if a
is used later in loops (see Programming Flow Control Features) or dollar conditions (see Conditional Expressions, Assignments and Equations). For example, consider the statement
a(row,col)$[a(row,col)] = INF ;
In the case where a
was originally assigned to be zero, the dollar-condition is always false so no infinities are assigned. If a
was originally assigned the value EPS, the dollar-condition is always true and every tuple in a
will be set to infinity.
When an attempted arithmetic operation is illegal or has undefined results because of the value of arguments (division by zero is the normal example), an error is reported and the result is set to undefined (UNDF
). The error is marked on the output file with a row of four asterisks '****
' making this sequence a good search target in the editor. GAMS will also report the line number of the offending statement and give as much detail as possible about the cause. From there on, the resulting UNDF
is treated as a proper data value and does not trigger additional error messages. For more on error messages, see chapter GAMS Output.
- Note
- GAMS will not solve a model if an error has been detected, and it will terminate with an error condition.
It is therefore wise to anticipate and avoid operations like division by zero that will cause errors. This is most easily done with the dollar control, and is discussed in section The Dollar Condition.
Predefined Symbols
GAMS offers several predefined symbols including: sameAs, diag, sortedUels, solvers
, licenseCodes
, and solverCapabilities
. With the exception of sameAs
, diag
, and sortedUels
these predefined symbols are for very special (and mostly internal) purposes, but the way they work is identical.
These symbols can be used in a GAMS program without being declared but work in an idiosyncratic way. For example, the complete program
display solvers, sameAs;
compiles and executes without error and produces the following result in the listing file:
---- 1 SET Solvers Available Solvers ( EMPTY ) ---- 1 SET SameAs Set Element Comparison Without Checking ( EMPTY )
However, if labels have been declared (in any set) that corresponds to a solver name, then set solvers
will contain this label. Consider the following example:
Set titles / Lord, Baron, Duke /;
Set greeks / Euclid, Pythagoras, Antigone /;
display solvers, sameAs;
Note that Antigone
and Baron
are the names of solvers in GAMS and therefore they will be displayed as a member of the set solvers
. Also note that the set sameAs
contains the diagonal elements for both sets:
---- 3 SET Solvers Available Solvers Baron , Antigone ---- 3 SET SameAs Set Element Comparison Without Checking Lord Baron Duke Euclid Pythagoras Antigone Lord YES Baron YES Duke YES Euclid YES Pythagoras YES Antigone YES
User defined symbols can have the same name as a predefined symbol. In this case the user symbol hides the predefined symbols as demonstrated in the following example:
Set diag / 1*3 /;
$if setType diag $log diag is a set
$if preType diag $log diag is a predefined type
The log will only contain the line diag is a set
. The test $if preType diag
fails.
The list of all predefined symbols can be retrieved by declaring and displaying a set using some system data set pre /system.predefinedSymbols/; display pre;
which results in
---- 1 SET pre SameAs , Diag , Solvers LicenseCodes , SolverCapabilities , SortedUels
Summary
GAMS provides powerful facilities for data manipulation with parallel assignment statements, built-in functions and extended range arithmetic.