### Table of Contents

# Introduction

Data once initialized may require manipulation in order to bring it to the form required in the model. The first part of this chapter will deal explicitly with parameter manipulation. The rest of the chapter will be devoted to explaining the ramifications: indexed assignment functions, index operations.

# 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 any 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 statement assignments have the effect of replacing the previous value of `x`

, if any, 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.

- Attention
- An assignment cannot start with a reserved word. A semicolon is therefore required as a delimiter before all assignments.

## Indexed Assignments

The syntax in GAMS for performing indexed assignments is extremely powerful. This operation offers what may be thought of as simultaneous or parallel assignment and it provides a concise way of specifying large amounts of data. Consider the mathematical statement, \(DJ_d = 2.75 DA_d\) for all \(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`

will be referred to as the controlling index or controlling set.

- Attention
- The index sets on the left hand side of the assignment are together called the 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 parenthesis. Consider the following example of an assignment to all 100 data elements of `a`

.

Set row / r-1*r-10 / col / c-1*c-10 / sro(row) / r-7*r-10 / ; 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. The first of these is, explicitly,

a('r-1','c-1') = 13.2 + r('r-1')*c('c-1').

## Sparse Assignments

A sparse assignment will assign a value to the left hand side(LHS) of the `=`

sign only if the right hand side (RHS) is nonzero. Consider the following example:

*define end-of-line comment symbol: $eolcom !! $eolcom !! Set i /a,b,c/ Parameter d1(i) Data d1 /a 1, b 1, c 1/ d2(i) Data used to overwrite d1 /a 2, b 0 / p1(i) p1(i)=d2(i) Full replacement p2(i) p2(i)$(d2(i))=d2(i) Sparse replacement p3(i) p3(i)$=d2(i) Shorthand for sparse replacement; p1(i)=d1(i); !! result: p1('a')=1 p1('b')=1 p1('c')=1 p2(i)=d1(i); !! result: p2('a')=1 p2('b')=1 p2('c')=1 p3(i)=d1(i); !! result: p3('a')=1 p3('b')=1 p3('c')=1 p1(i)=d2(i); !! result: p1('a')=2 p2(i)$(d2(i))=d2(i); !! result: p2('a')=2 p2('b')=1 p2('c')=1 p3(i)$=d2(i); !! result: p3('a')=2 p3('b')=1 p3('c')=1 Display d1,d2,p1,p2,p3;

In the sparse assignments, the parameters p2(i) and p3(i) are replaced with values from parameter d2(i) only if the entry in d2(i) is nonzero. Hence, the nonzero entry d2('a') replaces entry p2('a') and p3('a').

## Using Labels Explicitly in Assignments

It is often necessary to use labels explicitly in assignments. This can be done as discussed earlier with parameters - by using quotes around the label. Consider the following assignment,

a('r-7','c-4') = -2.36 ;

This statement assigns a constant value to one element of `a`

. All other elements of `a`

remain unchanged. Either single or double quotes can be used around the labels.

## Assignments Over Subsets

In general, wherever a set name can occur in an indexed assignment, a subset (or even alabel) can be used instead if you need to make the assignment over a subset instead of the whole domain.

Consider the following example,

a(sro,'col-10') = 2.44 -33*r(sro) ;

where `sro`

has already been established to be a proper subset of `row`

.

## Issues with Controlling Indices

- Attention
- The number of controlling indices on the left of the
`=`

sign should be at least as many 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

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.

There would be no error here if `col`

would be a `singleton set`

. Since there is not more than one element in a `singleton set`

it is not required that this index gets controlled by an controlling index on the left or an indexed operator.

- Attention
- Each set is counted only once to determine the number of controlling indices. If the same set appears more than once within the controlling domain, the second and higher occurrences of the set should be
`aliases`

of the original set in order for the number of controlling indices to be equal to the number of indices.

Consider the following statement as an illustration,

b(row,row) = 7.7 - r(row) ;

This statement has only one controlling index (`row`

). If one steps through the elements of `row`

one at a time assignments will be made only to the diagonal entries in `b`

. This will assign exactly 10 values! None of the off-diagonal elements of `b`

will be filled.

If an additional name is provided for `row`

and used in the second index position, then there will be two controlling indices and GAMS will make assignments over the full Cartesian product, all 100 values. Consider the following example,

alias(row,rowp) ; b(row,rowp) = 7.7 - r(row) + r(rowp) ;

## Extended Range Identifiers in Assignments

The GAMS *extended range* identifiers can also be used in assignment statements, as in

a(row,'col-10') = inf ; a(row,'col-1') = -inf ;

Extended range arithmetic will be discussed later in this Section. The values most often used are `NA`

in incomplete tables, and `INF`

for variable bounds.

## Acronyms in Assignments

Acronyms can also be used in assignment statements, as in

acronym monday, tuesday, wednesday, thursday, friday ; parameter dayofweek ; dayofweek = wednesday ;

- Attention
- Acronyms contain no numeric value, and are treated as character strings
*only*.

# 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 can be used on the right of the `=`

sign. All numerical facilities available in both standard and *extended* arithmetic will be covered.

## Standard Arithmetic Operations

The standard arithmetic symbols and operations are

`**`

exponentiation

They are listed above in precedence order, which determines the order of evaluation in an expression without parentheses.

Consider, for example:

x = 5 + 4*3**2 :

For clarity, this could have been written:

x = 5 + (4*(3**2)) ;

In both cases the result is 41.

- Attention
- It is better to use parentheses than to rely on the precedence of operators, since it prevents errors and clarifies intentions.
- 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 operator symbols. Blanks are not allowed within identifiers or numbers, and are significant inside the quote marks used to delimit labels.
`x**n`

is equivalent to the function call rPower(x,y) and is calculated inside GAMS as`exp[n*log(x)]`

. This operation is not defined if`x`

has a negative value, and an error will result. If the possibility of negative values for`x`

is to be admitted*and*the exponent is known to be an integer, then a function call, power(x,n), is available.

Three additional capabilities are available to add power and flexibility of expression calculations. They are indexed operations, functions and extended range arithmetic.

## Indexed Operations

In addition to the simple operations explained before, GAMS also provides the following four indexed operations.

`sum`

Summation over controlling index

`prod`

Product over controlling index

These four operations are performed over one or more controlling indices. The syntax in GAMS for these operations is,

indexed_op( (controlling_indices), expression)

If there is only one controlling index, the parentheses around it can be removed. The most common of these is `sum`

, which is used to calculate totals over the domain of a set. Consider the following simple example adapted from [ANDEAN] for illustration.

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));

This would be written, using normal mathematical representation, as \(totC_m = \sum_i C_{im}\).

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. `i`

is again called the controlling index for this operation. The scope of the control is the pair of parentheses `()`

that starts immediately after the sum. It is not likely to be useful to have two independent index operations controlled by the same index.

It is also possible to sum simultaneously over the domain of two or more sets, in which case more parentheses are needed. Also, of course, an arithmetic expression may be used instead of an identifier;

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 and\quad emp = \sum_t L_t M_t \]

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. Consider the following example to find the largest capacity,

lrgunit = smax((i,m),capacity(i,m));

## Functions

Functions play an important part in the GAMS language, especially for non-linear models. Similar to other programming languages, GAMS provides a number of built-in (intrinsic) functions. However, GAMS is used in an extremely diverse set of application areas and this creates frequent requests for the addition of new and often sophisticated and specialized functions. There is a trade-off between satisfying these requests and avoiding complexity not needed by most users. The GAMS Function Library Facility (Section Functions) provides the means for managing that trade-off.

### Intrinsic Functions

GAMS provides commonly used standard functions such as exponentiation, and logarithmic, and trigonometric functions. The complete list of available functions is given in the following sections: Mathematical functions, Logical functions, Time and Calendar functions, and GAMS utility and performance functions. There are cautions to be taken when functions appear in equations; these are dealt with in Section Expressions in Equation Definitions, Chapter Equations.

In the following sections, the Endogenous Classification (third column) specifies in which models the function can legally appear. In order of least to most restrictive, the choices are *DNLP*, *NLP*, *any*, *none* (see Section Classification of Models for details). Functions classified as *any* are only permitted with exogenous (constant) arguments.

The following conventions are used for the function arguments. Lower case indicates that an endogenous variable is allowed. Upper case indicates that a constant argument is required. The arguments in square brackets can be omitted and default values will be used. Those default values are specified in the function description provided in the second column.

Function | Description | End. Classif. |
---|---|---|

`abs(x)` | returns the absolute value of an expression or term x | DNLP |

`arccos(x)` | returns the 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 |

`arcsin(x)` | returns the 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 |

`arctan(x)` | returns the inverse tangent of the argument x where x is a real number and the output is in radians, see MathWorld | NLP |

`arctan2(y,x)` | four-quadrant arctan function yielding arctangent(y/x) which is the angle the vector (x,y) makes with (1,0) in radians | NLP |

`Beta(x,y)` | beta function: \( B(x,y) = \frac{\gamma(x)\gamma(y)}{\gamma(x+y)}\), see MathWorld | DNLP |

`betaReg(x,y,z)` | regularized beta function, see MathWorld | NLP |

`binomial(n,k)` | returns the (generalized) binomial coefficient for \(n,k\geq 0\) | NLP |

`ceil(x)` | returns the smallest integer number greater than or equal to x | DNLP |

`centropy(x,y[,Z])` | Centropy: \(x \cdot \ln(\frac{x+Z}{y+Z})\), default setting: \(Z=0\) | NLP |

`cos(x)` | returns the cosine of the argument x where x must be in radians, see MathWorld | NLP |

`cosh(x)` | returns the hyperbolic cosine of x where x must be in radians, see MathWorld | NLP |

`cvPower(X,y)` | returns \(X^{y}\) for \(X\geq0\) | NLP |

`div(dividend,divisor)` | returns \(\frac{dividend}{divisor}\), undefined for \(divisor=0\) | NLP |

`div0(dividend,divisor)` | returns \(\frac{dividend}{divisor}\), returns \(10^{299}\) for \(divisor=0\) | NLP |

`eDist(x1[,x2,x3,...]) ` | Euclidean or L-2 Norm: \(\sqrt{ x_{1}^{2} + x_{2}^{2} + ... }\), default setting: \(x_{2},x_{3},...=0\) | NLP |

`entropy(x)` | Entropy: \(-x\cdot\ln(x)\) | NLP |

`errorf(x)` | calculates the integral of the standard normal distribution from negative infinity to x, \(errorf(x) = \frac{1}{\sqrt{2\pi}} \int\limits_{-\infty}^x e^{\frac{-t^{2}}{2}}dt\) | NLP |

`execSeed` | reads or writes the seed for the random number generator | none |

`exp(x)` | returns the exponential function \(e^{x}\) of an expression or term x, see MathWorld | NLP |

`fact(N)` | returns the factorial of N where N is an integer | any |

`floor(x)` | returns the greatest integer number less than or equal to x | DNLP |

`frac(x)` | returns the fractional part of x | DNLP |

`gamma(x)` | gamma function: \( \gamma(x)= \int\limits_{0}^{\infty} t^{x-1}e^{-t}dt\), see MathWorld | DNLP |

`gammaReg(x,a)` | regularized gamma function, see MathWorld | NLP |

`log(x)` | returns the natural logarithm, logarithm base e, see MathWorld | NLP |

`logBeta(x,y)` | log beta function: \(\log(B(x,y))\) | NLP |

`logGamma(x)` | log gamma function as discussed in MathWorld | NLP |

`log10(x)` | returns the common logarithm, logarithm base 10, see MathWorld | NLP |

`log2(x)` | returns the binary logarithm, logarithm base 2, see MathWorld | NLP |

`mapVal(x)` | Function that returns an integer value associated with a numerical result that can contain special values. Possible values are: 0 for all regular numbers 4 for UNDF which means undefined 5 for NA which means not available 6 for INF which means plus infinity 7 for -INF which means minus infinity 8 for EPS which means very close to zero but different from zero | any |

`max(x1,x2,x3,...)` | returns the maximum of a set of expressions or terms, the number of arguments is not limited | DNLP |

`min(x1,x2,x3,...)` | returns the minimum of a set of expressions or terms, the number of arguments is not limited | DNLP |

`mod(x,y)` | returns the remainder of x divided by y | DNLP |

`ncpCM(x,y,Z)` | function that computes a Chen-Mangasarian smoothing equaling: \(x-Z\cdot \ln(1+e^{\frac{x-y}{Z}})\) | NLP |

`ncpF(x,y[,Z])` | function that computes a Fisher smoothing equaling: \(\sqrt{(x^{2}+y^{2}+2\cdot Z)}-x-y\), \(Z\geq0\), default setting: Z=0 | NLP |

`ncpVUpow(r,s[,MU])` | NCP Veelken-Ulbrich: smoothed min ncpVUpow = \( \left\{ \begin{array}{ll}\frac{(r + s - |t|)}{2} & if |t| \geq \mu\\ \frac{(r + s - \frac{\mu}{8} \cdot (- (\frac{t}{\mu})^{4}+6(\frac{t}{\mu})^{2} +3))}{2} & otherwise \end{array} \right.\) where \(t=r-s\), default setting: \(MU=0\) | NLP |

`ncpVUsin(r,s[,MU])` | NCP Veelken-Ulbrich: smoothed min ncpVUsin = \( \left\{ \begin{array}{ll} \frac{(r + s - |t|)}{2} & if |t| \geq \mu\\\frac{(r + s - (\frac{2\mu}{\pi} \sin(\frac{\pi\cdot}{2\mu} +\frac{3\pi}{2})+\mu))}{2} & otherwise \end{array} \right.\) where \(t=r-s\),default setting: \(MU=0\) | NLP |

`normal(MEAN,STDDEV)` | generates a random number with normal distribution with mean MEAN and standard deviation STDDEV, see MathWorld | none |

`pi` | value of \(\pi=3.141593...\) | any |

`poly(x,A0,A1,A2[,A3,...])` | computes a polynomial over scalar x where result \(= A_{0}+A_{1}x+A_{2}x^{2}+A_{3}x^{3}+...\) - this has a maximum of 20 arguments, default setting: \(A_{3},...=0\) | NLP |

`power(x,Y)` | returns \(x^Y\) where Y must be an integer | NLP |

`randBinomial(N,P)` | generates a random number with binomial distribution where n is the number of trials and p the probability of success for each trial, see MathWorld | none |

`randLinear(LOW,SLOPE,HIGH)` | generates a random number between LOW and HIGH with linear distribution, SLOPE must be greater than \(\frac{2}{\mbox{HIGH}-\mbox{LOW}}\) | none |

`randTriangle(LOW,MID,HIGH)` | generates a random number between LOW and HIGH with triangular distribution, MID is the most probable number, see MathWorld | none |

`round(x[,DECPL])` | rounding x, DECPL declares the number of decimal places, default setting: \(\mbox{DECPL}=0\) | DNLP |

`rPower(x,y)` | returns \(x^{y}\) for \(x > 0\), however, if \(x = 0\) then other restrictions for \(y\) apply. This function is equal to the arithmetic operation '`x**y` ' which is explained at Standard Arithmetic Operations | NLP |

`sigmoid(x)` | Sigmoid calculation: \(\frac{1}{1+e^{-x}}\), see MathWorld | NLP |

`sign(x)` | sign of x, returns 1 if \(x > 0\), -1 if \(x < 0\), and 0 if \(x = 0\) | DNLP |

`signPower(x,Y)` | signed power where Y must be greater than 0, returns \(x^{Y}\) if \(x\geq 0\) and \(-1\cdot |x|^{Y}\) if \(x<0\) | NLP |

`sin(x)` | returns the sine of the argument x where x must be in radians, see MathWorld | NLP |

`sinh(x)` | returns the hyperbolic sine of x where x must be in radians, see MathWorld | NLP |

`slexp(x[,SP])` | smooth (linear) exponential function, SP means smoothing parameter, default setting: \(SP=150\) | NLP |

`sllog10(x[,SP])` | smooth (linear) logarithm base 10, SP means smoothing parameter, default setting: \(SP=10^{-150}\) | NLP |

`slrec(x[,SP])` | smooth (linear) reciprocal, SP means smoothing parameter, default setting: \(SP=10^{-10}\) | NLP |

`sqexp(x[,SP])` | smooth (quadratic) exponential funtion, SP means smoothing parameter, default setting: \(SP=150\) | NLP |

`sqlog10(x[,SP])` | smooth (quadratic) logarithm base 10, SP means smoothing parameter, default setting: \(SP=10^{-150}\) | NLP |

`sqr(x)` | returns the square of an expression or term x | NLP |

`sqrec(x[,SP])` | smooth (quadratic) reciprocal, SP means smoothing parameter, default setting: \(SP=10^{-10}\) | NLP |

`sqrt(x)` | returns the squareroot of x, see MathWorld | NLP |

`tan(x)` | returns the tangent of the argument x where x must be in radians, see MathWorld | NLP |

`tanh(x)` | returns the hyperbolic tangent of x where x must be in radians, see MathWorld | NLP |

`trunc(x)` | truncation, removes decimals from x | DNLP |

`uniform(LOW,HIGH)` | generates a random number between LOW and HIGH with uniform distribution, see MathWorld | none |

`uniformInt(LOW,HIGH)` | generates an integer random number between LOW and HIGH with uniform distribution, see MathWorld | none |

`vcPower(x,Y)` | returns \(x^{Y}\) for \(x\geq0\). | NLP |

Function | Description | End. Classif. |
---|---|---|

`bool_and(x,y)` | boolean and: returns 0 if \(x=0 \quad \vee \quad y=0\), else returns 1, another possible command is `'x and y'` | DNLP |

`bool_eqv(x,y)` | boolean equivalence: returns 0 if exactly one argument is 0, else returns 1, another possible command is '`x eqv y` ' | DNLP |

`bool_imp(x,y)` | boolean implication: returns 1 if \(x=0 \vee y \neq 0\), else returns 0, another possible command is '`x imp y` ' | DNLP |

`bool_not(x)` | boolean not: returns 1 if \(x=0\), else returns 0, another possible command is '`not x` ' | DNLP |

`bool_or(x,y)` | boolean or: returns 0 if \(x=y=0\), else returns 1, another possible command is '`x or y` ' | DNLP |

`bool_xor(x,y)` | boolean xor: returns 1 if exactly one argument is 0, else returns 0, another possible command is '`x xor y` ' | DNLP |

`ifThen(cond,iftrue,else)` | first argument contains a condition (e.g. \(x>y\)). If the condition is true, the function returns `iftrue` else it returns `else` . | DNLP |

`rel_eq(x,y)` | relation 'equal': returns 1 if \(x=y\), else returns 0, another possible command is '`x eq y` ' | DNLP |

`rel_ge(x,y)` | relation 'greater equal': returns 1 if \(x\geq y\), else returns 0, another possible command is '`x ge y` ' | DNLP |

`rel_gt(x,y)` | relation 'greater than': returns 1 if \(x>y\), else returns 0, another possible command is '`x gt y` ' | DNLP |

`rel_le(x,y)` | relation 'less equal': returns 1 if \(x\leq y\), else returns 0, another possible command is '`x le y` ' | DNLP |

`rel_lt(x,y)` | relation 'less than': returns 1 if \(x<y\), else returns 0, another possible command is '`x lt y` ' | DNLP |

`rel_ne(x,y)` | relation 'not equal': returns 1 if \(x\neq y\), else returns 0, another possible command is '`x ne y` ' | DNLP |

Function | Description | End. Classif. |
---|---|---|

`gday(SDAY)` | returns Gregorian day from a serial day number date.time, where Jan 1, 1900 is day 1 | any |

`gdow(SDAY)` | returns Gregorian day of week from a serial day number date.time, where Jan 1, 1900 is day 1 | any |

`ghour(SDAY)` | returns Gregorian hour of day from a serial day number date.time, where Jan 1, 1900 is day 1 | any |

`gleap(SDAY)` | returns 1 if the year that corresponds to a serial day number date.time, where Jan 1, 1900 is day 1, is a leap year, else returns 0 | any |

`gmillisec(SDAY)` | returns Gregorian milli second from a serial day number date.time, where Jan 1, 1900 is day 1 | any |

`gminute(SDAY)` | returns Gregorian minute of hour from a serial day number date.time, where Jan 1, 1900 is day 1 | any |

`gmonth(SDAY)` | returns Gregorian month from a serial day number date.time, where Jan 1, 1900 is day 1 | any |

`gsecond(SDAY)` | returns Gregorian second of minute from a serial day number date.time, where Jan 1, 1900 is day 1 | any |

`gyear(SDAY)` | returns Gregorian year from a serial day number date.time, where Jan 1, 1900 is day 1 | any |

`jdate(YEAR,MONTH,DAY)` | returns a serial day number, starting with Jan 1, 1900 as day 1 | any |

`jnow` | returns the current time as a serial day number, starting with Jan 1, 1900 as day 1 | none |

`jstart` | returns the time of the start of the GAMS job as a serial day number, starting with Jan 1, 1900 as day 1 | none |

`jtime(HOUR,MIN,SEC)` | returns fraction of a day that corresponds to hour, minute and second | any |

**GAMS utility and performance functions**

Consider the following example of a function used as an expression in an assignment statement,

x(j) = log(y(j)) ;

which replaces the current value of `x`

with the natural logarithm of `y`

over the domain of the index set `j`

.

### Extrinsic Functions

Using the GAMS Function Library Facility, functions can be imported from an external library into a GAMS model. Apart from the import syntax, the imported functions can be used in the same way as intrinsic functions. In particular, they can be used in equation definitions. Some function libraries are included with the standard GAMS software distribution (see Chapter Extrinsic Functions) 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++ that come with every GAMS system.

### Using Function Libraries

Function libraries are made available to a model using a compiler directive:

$FuncLibIn <InternalLibName> <ExternalLibName>

Note that the Function Library Facility gives you complete control over naming so that potential name conflicts between libraries can be avoided. The `<InternalLibName>`

is a sort of handle and will be used to refer to the library inside your model source code. The `<ExternalLibName>`

is the file name for the shared library that implements the extrinsic functions. To access libraries included with your GAMS distribution you use the library's name with no path prefix. GAMS will look for the library in a standard place within the GAMS installation. To access a library that does not reside in this standard place, the external name should include a relative or absolute path to the library's location. GAMS will search for the shared library you specify using the mechanisms specific to the host operating system. When processing the `$FuncLibIn`

directive, GAMS will validate the library, make the included functions available for use, and add a table of the included functions to the listing file.

Before using individual functions you must declare them:

Function <InternalFuncName> /<InternalLibName>.<FuncName>/;

Note that the syntax is similar to that used for declaring Sets, Parameters, Variables and so forth and that the control over potential naming conflicts extends to the names of the individual functions. The `<InternalFuncName>`

is the one that you will use in the rest of your model code. The `<InternalLibName>`

is the one that you created with the `$FuncLibIn`

directive and `<FuncName>`

is the name given the function when the library was created. Once functions have been declared with the `Function`

statement they may be used exactly like intrinsic functions in the remainder of your model code.

### Example

Here is an example that adds some concrete detail.

$eolcom // $FuncLibIn trilib testlib_ml%system.dirsep%tridclib // Make the library available. // trilib is the internal name being created now. // tridclib is the external name. // With no path, GAMS will look for tridclib in // the GAMS system directory. * Declare each of the functions that will be used. * myCos, mySin and MyPi are names being declared now for use in this model. * Cosine, Sine and Pi are the function names from the library. * Note the use of the internal library name. Function myCos /trilib.Cosine/ mySin /trilib.Sine/ myPi /trilib.Pi/; scalar i, grad, rad, intrinsic; for (i=1 to 360, intrinsic = cos(i/180*pi); grad = mycos(i,1); abort$round(abs(intrinsic-grad),4) 'cos', i, intrinsic, grad; rad = mycos(i/180*pi); abort$round(abs(intrinsic-rad) ,4) 'cos', i, intrinsic, rad;); variable x; equation e; e.. sqr(mysin(x)) + sqr(mycos(x)) =e= 1; model m /e/; x.lo = 0; x.l=3*mypi; solve m min x using nlp;

The following lines from the listing file describe the library loaded.

FUNCLIBIN trilib tridclib Function Library trilib Mod. Function Description Type NLP Cosine(x[,MODE]) Cosine: mode=0 (default) -> rad, mode=1 -> grad NLP Sine(x[,MODE]) Sine : mode=0 (default) -> rad, mode=1 -> grad any Pi Pi

A description of the libraries included in the GAMS system can be found in Chapter Extrinsic Functions.

### Stateful Libraries

While GAMS intrinsic function are stateless, a user can implement stateful extrinsic functions, meaning that the extrinsic libraries can have some memory. This can be done in two ways:

- Library initialization (see Section Piecewise Polynomial Librarty): At initialization time, the function library reads some data to provide the necessary functions
- Previous function calls (see Section Build Your Own: Trigonometric Library Example, function
`setMode`

): Function calls that alter the execution of successive function calls

The latter type of memory is problematic, since different parts of the GAMS system potentially use different instances of the function library. For example, if one sets `SetMode(1)`

before the solve statement and one uses GAMS option `solvelink<>5`

(see SolveLink), the solver runs in a separate process with a new instance of the function library and therefore uses the default `mode`

, which is 0. Even worse, if `solvelink=0`

is set, the GAMS process terminates in order to execute the solve statement and restarts a new GAMSprocess after the solve which again starts up with a fresh function library instance, so the function library's memory is lost also in this case. The GAMS Test Library model `trilib04`

demonstrates this problem.

## Extended Range Arithmetic and Error Handling

GAMS uses an *extended range* arithmetic to handle missing data, the results of undefined operations, and the representation of bounds that solver systems regard as *infinite*. The special symbols are listed in table Table 1 , with the brief explanation of the meaning of each.

**Table 1:** Special symbols for extended arithmetic

Special symbol | Description | mapval |
---|---|---|

`inf` | Plus infinity. A very large positive number | 6 |

`-inf` | Minus infinity. A very large negative number | 7 |

`na` | Not available. Used for missing data. Any Operation that uses the value `NA` will produce the result `NA` | 5 |

`undf` | Undefined. The result of an undefined or illegal operation. A user cannot directly set a value to `UNDF` | 4 |

`eps` | Very close to zero, but different from zero. | 8 |

GAMS has defined the results of all arithmetic operations and all function values using these special values.

The results can be inspected by running the model library problem [CRAZY]. As one would expect, `1+INF`

evaluates to `INF`

, and `1-EPS`

to `1`

.

- Attention
- The
`mapval`

function should be used in comparisons involving extended range arithmetic. Only the extended range arithmetic shown in the table above give non-zero values for`mapval`

. For example,`mapval(a)`

takes a value of`6`

if`a`

is`inf`

. All regular numbers result in a`mapval`

of`0`

.

The following table shows a selection of results for exponentiation and division for a variety of input parameters.

**Table 2:** Exponentiation and Division

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 |

- Attention
- One should avoid creating or using numbers with absolute values larger than
`1.0E20`

. If a number is too large, it may be treated by GAMS as undefined (`UNDF`

), and all values derived from it in a model may be unusable. Always use`INF`

(or`-INF`

) explicitly for arbitrarily large numbers

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`

).

From there on, `UNDF`

is treated as a proper data value and does not trigger additional error messages.

- Attention
- GAMS will not solve a model if an error has been detected, but will terminate with an error condition.

It is thus always necessary to anticipate conditions that will cause errors, such as divide by zero. This is most easily done with the dollar control, and will be discussed in the next section.

# Summary

GAMS provides powerful facilities for data manipulation with parallel assignment statements, built-in functions and extended range arithmetic.