alpar@1
|
1 |
%* gmpl.tex *%
|
alpar@1
|
2 |
|
alpar@1
|
3 |
%***********************************************************************
|
alpar@1
|
4 |
% This code is part of GLPK (GNU Linear Programming Kit).
|
alpar@1
|
5 |
%
|
alpar@1
|
6 |
% Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
|
alpar@1
|
7 |
% 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
|
alpar@1
|
8 |
% Moscow Aviation Institute, Moscow, Russia. All rights reserved.
|
alpar@1
|
9 |
% E-mail: <mao@gnu.org>.
|
alpar@1
|
10 |
%
|
alpar@1
|
11 |
% GLPK is free software: you can redistribute it and/or modify it
|
alpar@1
|
12 |
% under the terms of the GNU General Public License as published by
|
alpar@1
|
13 |
% the Free Software Foundation, either version 3 of the License, or
|
alpar@1
|
14 |
% (at your option) any later version.
|
alpar@1
|
15 |
%
|
alpar@1
|
16 |
% GLPK is distributed in the hope that it will be useful, but WITHOUT
|
alpar@1
|
17 |
% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
alpar@1
|
18 |
% or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
alpar@1
|
19 |
% License for more details.
|
alpar@1
|
20 |
%
|
alpar@1
|
21 |
% You should have received a copy of the GNU General Public License
|
alpar@1
|
22 |
% along with GLPK. If not, see <http://www.gnu.org/licenses/>.
|
alpar@1
|
23 |
%***********************************************************************
|
alpar@1
|
24 |
|
alpar@1
|
25 |
\documentclass[10pt]{article}
|
alpar@1
|
26 |
\usepackage[dvipdfm,linktocpage,colorlinks,linkcolor=blue]{hyperref}
|
alpar@1
|
27 |
|
alpar@1
|
28 |
\begin{document}
|
alpar@1
|
29 |
|
alpar@1
|
30 |
\thispagestyle{empty}
|
alpar@1
|
31 |
|
alpar@1
|
32 |
\begin{center}
|
alpar@1
|
33 |
|
alpar@1
|
34 |
\vspace*{1in}
|
alpar@1
|
35 |
|
alpar@1
|
36 |
\begin{huge}
|
alpar@1
|
37 |
\sf\bfseries Modeling Language GNU MathProg
|
alpar@1
|
38 |
\end{huge}
|
alpar@1
|
39 |
|
alpar@1
|
40 |
\vspace{0.5in}
|
alpar@1
|
41 |
|
alpar@1
|
42 |
\begin{LARGE}
|
alpar@1
|
43 |
\sf Language Reference
|
alpar@1
|
44 |
\end{LARGE}
|
alpar@1
|
45 |
|
alpar@1
|
46 |
\vspace{0.5in}
|
alpar@1
|
47 |
|
alpar@1
|
48 |
\begin{LARGE}
|
alpar@1
|
49 |
\sf for GLPK Version 4.45
|
alpar@1
|
50 |
\end{LARGE}
|
alpar@1
|
51 |
|
alpar@1
|
52 |
\vspace{0.5in}
|
alpar@1
|
53 |
\begin{Large}
|
alpar@1
|
54 |
\sf (DRAFT, December 2010)
|
alpar@1
|
55 |
\end{Large}
|
alpar@1
|
56 |
|
alpar@1
|
57 |
\end{center}
|
alpar@1
|
58 |
|
alpar@1
|
59 |
\newpage
|
alpar@1
|
60 |
|
alpar@1
|
61 |
\vspace*{1in}
|
alpar@1
|
62 |
|
alpar@1
|
63 |
\vfill
|
alpar@1
|
64 |
|
alpar@1
|
65 |
\noindent
|
alpar@1
|
66 |
The GLPK package is part of the GNU Project released under the aegis of
|
alpar@1
|
67 |
GNU.
|
alpar@1
|
68 |
|
alpar@1
|
69 |
\medskip\noindent
|
alpar@1
|
70 |
Copyright \copyright{} 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
alpar@1
|
71 |
2008, 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
|
alpar@1
|
72 |
Moscow Aviation Institute, Moscow, Russia. All rights reserved.
|
alpar@1
|
73 |
|
alpar@1
|
74 |
\medskip\noindent
|
alpar@1
|
75 |
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
|
alpar@1
|
76 |
MA 02110-1301, USA.
|
alpar@1
|
77 |
|
alpar@1
|
78 |
\medskip\noindent
|
alpar@1
|
79 |
Permission is granted to make and distribute verbatim copies of this
|
alpar@1
|
80 |
manual provided the copyright notice and this permission notice are
|
alpar@1
|
81 |
preserved on all copies.
|
alpar@1
|
82 |
|
alpar@1
|
83 |
\medskip\noindent
|
alpar@1
|
84 |
Permission is granted to copy and distribute modified versions of this
|
alpar@1
|
85 |
manual under the conditions for verbatim copying, provided also that
|
alpar@1
|
86 |
the entire resulting derived work is distributed under the terms of
|
alpar@1
|
87 |
a permission notice identical to this one.
|
alpar@1
|
88 |
|
alpar@1
|
89 |
\medskip\noindent
|
alpar@1
|
90 |
Permission is granted to copy and distribute translations of this
|
alpar@1
|
91 |
manual into another language, under the above conditions for modified
|
alpar@1
|
92 |
versions.
|
alpar@1
|
93 |
|
alpar@1
|
94 |
\newpage
|
alpar@1
|
95 |
|
alpar@1
|
96 |
\tableofcontents
|
alpar@1
|
97 |
|
alpar@1
|
98 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
alpar@1
|
99 |
|
alpar@1
|
100 |
\newpage
|
alpar@1
|
101 |
|
alpar@1
|
102 |
\section{Introduction}
|
alpar@1
|
103 |
|
alpar@1
|
104 |
{\it GNU MathProg} is a modeling language intended for describing
|
alpar@1
|
105 |
linear mathematical programming models.\footnote{The GNU MathProg
|
alpar@1
|
106 |
language is a subset of the AMPL language. Its GLPK implementation is
|
alpar@1
|
107 |
mainly based on the paper: {\it Robert Fourer}, {\it David M. Gay}, and
|
alpar@1
|
108 |
{\it Brian W. Kernighan}, ``A Modeling Language for Mathematical
|
alpar@1
|
109 |
Programming.'' {\it Management Science} 36 (1990)\linebreak pp. 519-54.}
|
alpar@1
|
110 |
|
alpar@1
|
111 |
Model descriptions written in the GNU MathProg language consist of
|
alpar@1
|
112 |
a set of statements and data blocks constructed by the user from the
|
alpar@1
|
113 |
language elements described in this document.
|
alpar@1
|
114 |
|
alpar@1
|
115 |
In a process called {\it translation}, a program called the {\it model
|
alpar@1
|
116 |
translator} analyzes the model description and translates it into
|
alpar@1
|
117 |
internal data structures, which may be then used either for generating
|
alpar@1
|
118 |
mathematical programming problem instance or directly by a program
|
alpar@1
|
119 |
called the {\it solver} to obtain numeric solution of the problem.
|
alpar@1
|
120 |
|
alpar@1
|
121 |
\subsection{Linear programming problem}
|
alpar@1
|
122 |
\label{problem}
|
alpar@1
|
123 |
|
alpar@1
|
124 |
In MathProg the linear programming (LP) problem is stated as follows:
|
alpar@1
|
125 |
|
alpar@1
|
126 |
\medskip
|
alpar@1
|
127 |
|
alpar@1
|
128 |
\noindent\hspace{.7in}minimize (or maximize)
|
alpar@1
|
129 |
$$z=c_1x_1+c_2x_2+\dots+c_nx_n+c_0\eqno(1.1)$$
|
alpar@1
|
130 |
\noindent\hspace{.7in}subject to linear constraints
|
alpar@1
|
131 |
$$
|
alpar@1
|
132 |
\begin{array}{l@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }l}
|
alpar@1
|
133 |
L_1&\leq&a_{11}x_1&+&a_{12}x_2&+\dots+&a_{1n}x_n&\leq&U_1\\
|
alpar@1
|
134 |
L_2&\leq&a_{21}x_1&+&a_{22}x_2&+\dots+&a_{2n}x_n&\leq&U_2\\
|
alpar@1
|
135 |
\multicolumn{9}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\
|
alpar@1
|
136 |
L_m&\leq&a_{m1}x_1&+&a_{m2}x_2&+\dots+&a_{mn}x_n&\leq&U_m\\
|
alpar@1
|
137 |
\end{array}\eqno(1.2)
|
alpar@1
|
138 |
$$
|
alpar@1
|
139 |
\noindent\hspace{.7in}and bounds of variables
|
alpar@1
|
140 |
$$
|
alpar@1
|
141 |
\begin{array}{l@{\ }c@{\ }c@{\ }c@{\ }l}
|
alpar@1
|
142 |
l_1&\leq&x_1&\leq&u_1\\
|
alpar@1
|
143 |
l_2&\leq&x_2&\leq&u_2\\
|
alpar@1
|
144 |
\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .}\\
|
alpar@1
|
145 |
l_n&\leq&x_n&\leq&u_n\\
|
alpar@1
|
146 |
\end{array}\eqno(1.3)
|
alpar@1
|
147 |
$$
|
alpar@1
|
148 |
where $x_1$, $x_2$, \dots, $x_n$ are variables; $z$ is the objective
|
alpar@1
|
149 |
function; $c_1$, $c_2$, \dots, $c_n$ are objective coefficients; $c_0$
|
alpar@1
|
150 |
is the constant term (``shift'') of the objective function; $a_{11}$,
|
alpar@1
|
151 |
$a_{12}$, \dots, $a_{mn}$ are constraint coefficients; $L_1$, $L_2$,
|
alpar@1
|
152 |
\dots, $L_m$ are lower constraint bounds; $U_1$, $U_2$, \dots, $U_m$
|
alpar@1
|
153 |
are upper constraint bounds; $l_1$, $l_2$, \dots, $l_n$ are lower
|
alpar@1
|
154 |
bounds of variables; $u_1$, $u_2$, \dots, $u_n$ are upper bounds of
|
alpar@1
|
155 |
variables.
|
alpar@1
|
156 |
|
alpar@1
|
157 |
Bounds of variables and constraint bounds can be finite as well as
|
alpar@1
|
158 |
infinite. Besides, lower bounds can be equal to corresponding upper
|
alpar@1
|
159 |
bounds. Thus, the following types of variables and constraints are
|
alpar@1
|
160 |
allowed:
|
alpar@1
|
161 |
|
alpar@1
|
162 |
\newpage
|
alpar@1
|
163 |
|
alpar@1
|
164 |
\begin{tabular}{@{}r@{\ }c@{\ }c@{\ }c@{\ }l@{\hspace*{38pt}}l}
|
alpar@1
|
165 |
$-\infty$&$<$&$x$&$<$&$+\infty$&Free (unbounded) variable\\
|
alpar@1
|
166 |
$l$&$\leq$&$x$&$<$&$+\infty$&Variable with lower bound\\
|
alpar@1
|
167 |
$-\infty$&$<$&$x$&$\leq$&$u$&Variable with upper bound\\
|
alpar@1
|
168 |
$l$&$\leq$&$x$&$\leq$&$u$&Double-bounded variable\\
|
alpar@1
|
169 |
$l$&$=$&$x$&=&$u$&Fixed variable\\
|
alpar@1
|
170 |
\end{tabular}
|
alpar@1
|
171 |
|
alpar@1
|
172 |
\bigskip
|
alpar@1
|
173 |
|
alpar@1
|
174 |
\begin{tabular}{@{}r@{\ }c@{\ }c@{\ }c@{\ }ll}
|
alpar@1
|
175 |
$-\infty$&$<$&$\sum a_jx_j$&$<$&$+\infty$&Free (unbounded) linear
|
alpar@1
|
176 |
form\\
|
alpar@1
|
177 |
$L$&$\leq$&$\sum a_jx_j$&$<$&$+\infty$&Inequality constraint ``greater
|
alpar@1
|
178 |
than or equal to''\\
|
alpar@1
|
179 |
$-\infty$&$<$&$\sum a_jx_j$&$\leq$&$U$&Inequality constraint ``less
|
alpar@1
|
180 |
than or equal to''\\
|
alpar@1
|
181 |
$L$&$\leq$&$\sum a_jx_j$&$\leq$&$U$&Double-bounded inequality
|
alpar@1
|
182 |
constraint\\
|
alpar@1
|
183 |
$L$&$=$&$\sum a_jx_j$&=&$U$&Equality constraint\\
|
alpar@1
|
184 |
\end{tabular}
|
alpar@1
|
185 |
|
alpar@1
|
186 |
\bigskip
|
alpar@1
|
187 |
|
alpar@1
|
188 |
In addition to pure LP problems MathProg also allows mixed integer
|
alpar@1
|
189 |
linear programming (MIP) problems, where some or all variables are
|
alpar@1
|
190 |
restricted to be integer or binary.
|
alpar@1
|
191 |
|
alpar@1
|
192 |
\subsection{Model objects}
|
alpar@1
|
193 |
|
alpar@1
|
194 |
In MathProg the model is described in terms of sets, parameters,
|
alpar@1
|
195 |
variables, constraints, and objectives, which are called {\it model
|
alpar@1
|
196 |
objects}.
|
alpar@1
|
197 |
|
alpar@1
|
198 |
The user introduces particular model objects using the language
|
alpar@1
|
199 |
statements. Each model object is provided with a symbolic name that
|
alpar@1
|
200 |
uniquely identifies the object and is intended for referencing purposes.
|
alpar@1
|
201 |
|
alpar@1
|
202 |
Model objects, including sets, can be multidimensional arrays built
|
alpar@1
|
203 |
over indexing sets. Formally, $n$-dimensional array $A$ is the mapping:
|
alpar@1
|
204 |
$$A:\Delta\rightarrow\Xi,\eqno(1.4)$$
|
alpar@1
|
205 |
where $\Delta\subseteq S_1\times\dots\times S_n$ is a subset of the
|
alpar@1
|
206 |
Cartesian product of indexing sets,\linebreak $\Xi$ is a set of array members.
|
alpar@1
|
207 |
In MathProg the set $\Delta$ is called the {\it subscript domain}. Its
|
alpar@1
|
208 |
members are $n$-tuples $(i_1,\dots,i_n)$, where $i_1\in S_1$, \dots,
|
alpar@1
|
209 |
$i_n\in S_n$.
|
alpar@1
|
210 |
|
alpar@1
|
211 |
If $n=0$, the Cartesian product above has exactly one member (namely,
|
alpar@1
|
212 |
\linebreak 0-tuple), so it is convenient to think scalar objects as
|
alpar@1
|
213 |
0-dimensional arrays having one member.
|
alpar@1
|
214 |
|
alpar@1
|
215 |
The type of array members is determined by the type of corresponding
|
alpar@1
|
216 |
model object as follows:
|
alpar@1
|
217 |
|
alpar@1
|
218 |
\medskip
|
alpar@1
|
219 |
|
alpar@1
|
220 |
\noindent\hfil
|
alpar@1
|
221 |
\begin{tabular}{@{}ll@{}}
|
alpar@1
|
222 |
Model object&Array member\\
|
alpar@1
|
223 |
\hline
|
alpar@1
|
224 |
Set&Elemental plain set\\
|
alpar@1
|
225 |
Parameter&Number or symbol\\
|
alpar@1
|
226 |
Variable&Elemental variable\\
|
alpar@1
|
227 |
Constraint&Elemental constraint\\
|
alpar@1
|
228 |
Objective&Elemental objective\\
|
alpar@1
|
229 |
\end{tabular}
|
alpar@1
|
230 |
|
alpar@1
|
231 |
\medskip
|
alpar@1
|
232 |
|
alpar@1
|
233 |
In order to refer to a particular object member the object should be
|
alpar@1
|
234 |
provided with {\it subscripts}. For example, if $a$ is a 2-dimensional
|
alpar@1
|
235 |
parameter defined over $I\times J$, a reference to its particular
|
alpar@1
|
236 |
member can be written as $a[i,j]$, where $i\in I$ and $j\in J$. It is
|
alpar@1
|
237 |
understood that scalar objects being 0-dimensional need no subscripts.
|
alpar@1
|
238 |
|
alpar@1
|
239 |
\subsection{Structure of model description}
|
alpar@1
|
240 |
|
alpar@1
|
241 |
It is sometimes desirable to write a model which, at various points,
|
alpar@1
|
242 |
may require different data for each problem instance to be solved using
|
alpar@1
|
243 |
that model. For this reason in MathProg the model description consists
|
alpar@1
|
244 |
of two parts: the {\it model section} and the {\it data section}.
|
alpar@1
|
245 |
|
alpar@1
|
246 |
The model section is a main part of the model description that contains
|
alpar@1
|
247 |
declarations of model objects and is common for all problems based on
|
alpar@1
|
248 |
the corresponding model.
|
alpar@1
|
249 |
|
alpar@1
|
250 |
The data section is an optional part of the model description that
|
alpar@1
|
251 |
contains data specific for a particular problem instance.
|
alpar@1
|
252 |
|
alpar@1
|
253 |
Depending on what is more convenient the model and data sections can be
|
alpar@1
|
254 |
placed either in one file or in two separate files. The latter feature
|
alpar@1
|
255 |
allows having arbitrary number of different data sections to be used
|
alpar@1
|
256 |
with the same model section.
|
alpar@1
|
257 |
|
alpar@1
|
258 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
alpar@1
|
259 |
|
alpar@1
|
260 |
\newpage
|
alpar@1
|
261 |
|
alpar@1
|
262 |
\section{Coding model description}
|
alpar@1
|
263 |
\label{coding}
|
alpar@1
|
264 |
|
alpar@1
|
265 |
The model description is coded in plain text format using ASCII
|
alpar@1
|
266 |
character set. Characters valid in the model description are the
|
alpar@1
|
267 |
following:
|
alpar@1
|
268 |
|
alpar@1
|
269 |
\begin{itemize}
|
alpar@1
|
270 |
\item alphabetic characters:\\
|
alpar@1
|
271 |
\verb|A B C D E F G H I J K L M N O P Q R S T U V W X Y Z|\\
|
alpar@1
|
272 |
\verb|a b c d e f g h i j k l m n o p q r s t u v w x y z _|
|
alpar@1
|
273 |
\item numeric characters:\\
|
alpar@1
|
274 |
\verb|0 1 2 3 4 5 6 7 8 9|
|
alpar@1
|
275 |
\item special characters:\\
|
alpar@1
|
276 |
\verb?! " # & ' ( ) * + , - . / : ; < = > [ ] ^ { | }?
|
alpar@1
|
277 |
\item white-space characters:\\
|
alpar@1
|
278 |
\verb|SP HT CR NL VT FF|
|
alpar@1
|
279 |
\end{itemize}
|
alpar@1
|
280 |
|
alpar@1
|
281 |
Within string literals and comments any ASCII characters (except
|
alpar@1
|
282 |
control characters) are valid.
|
alpar@1
|
283 |
|
alpar@1
|
284 |
White-space characters are non-significant. They can be used freely
|
alpar@1
|
285 |
between lexical units to improve readability of the model description.
|
alpar@1
|
286 |
They are also used to separate lexical units from each other if there
|
alpar@1
|
287 |
is no other way to do that.
|
alpar@1
|
288 |
|
alpar@1
|
289 |
Syntactically model description is a sequence of lexical units in the
|
alpar@1
|
290 |
following categories:
|
alpar@1
|
291 |
|
alpar@1
|
292 |
\begin{itemize}
|
alpar@1
|
293 |
\item symbolic names;
|
alpar@1
|
294 |
\item numeric literals;
|
alpar@1
|
295 |
\item string literals;
|
alpar@1
|
296 |
\item keywords;
|
alpar@1
|
297 |
\item delimiters;
|
alpar@1
|
298 |
\item comments.
|
alpar@1
|
299 |
\end{itemize}
|
alpar@1
|
300 |
|
alpar@1
|
301 |
The lexical units of the language are discussed below.
|
alpar@1
|
302 |
|
alpar@1
|
303 |
\subsection{Symbolic names}
|
alpar@1
|
304 |
|
alpar@1
|
305 |
A {\it symbolic name} consists of alphabetic and numeric characters,
|
alpar@1
|
306 |
the first of which must be alphabetic. All symbolic names are distinct
|
alpar@1
|
307 |
(case sensitive).
|
alpar@1
|
308 |
|
alpar@1
|
309 |
\medskip
|
alpar@1
|
310 |
|
alpar@1
|
311 |
\noindent{\bf Examples}
|
alpar@1
|
312 |
|
alpar@1
|
313 |
\medskip
|
alpar@1
|
314 |
|
alpar@1
|
315 |
\noindent\verb|alpha123|
|
alpar@1
|
316 |
|
alpar@1
|
317 |
\noindent\verb|This_is_a_name|
|
alpar@1
|
318 |
|
alpar@1
|
319 |
\noindent\verb|_P123_abc_321|
|
alpar@1
|
320 |
|
alpar@1
|
321 |
\newpage
|
alpar@1
|
322 |
|
alpar@1
|
323 |
Symbolic names are used to identify model objects (sets, parameters,
|
alpar@1
|
324 |
variables, constraints, objectives) and dummy indices.
|
alpar@1
|
325 |
|
alpar@1
|
326 |
All symbolic names (except names of dummy indices) must be unique, i.e.
|
alpar@1
|
327 |
the model description must have no objects with identical names.
|
alpar@1
|
328 |
Symbolic names of dummy indices must be unique within the scope, where
|
alpar@1
|
329 |
they are valid.
|
alpar@1
|
330 |
|
alpar@1
|
331 |
\subsection{Numeric literals}
|
alpar@1
|
332 |
|
alpar@1
|
333 |
A {\it numeric literal} has the form {\it xx}{\tt E}{\it syy}, where
|
alpar@1
|
334 |
{\it xx} is a number with optional decimal point, {\it s} is the sign
|
alpar@1
|
335 |
{\tt+} or {\tt-}, {\it yy} is a decimal exponent. The letter {\tt E} is
|
alpar@1
|
336 |
case insensitive and can be coded as {\tt e}.
|
alpar@1
|
337 |
|
alpar@1
|
338 |
\medskip
|
alpar@1
|
339 |
|
alpar@1
|
340 |
\noindent{\bf Examples}
|
alpar@1
|
341 |
|
alpar@1
|
342 |
\medskip
|
alpar@1
|
343 |
|
alpar@1
|
344 |
\noindent\verb|123|
|
alpar@1
|
345 |
|
alpar@1
|
346 |
\noindent\verb|3.14159|
|
alpar@1
|
347 |
|
alpar@1
|
348 |
\noindent\verb|56.E+5|
|
alpar@1
|
349 |
|
alpar@1
|
350 |
\noindent\verb|.78|
|
alpar@1
|
351 |
|
alpar@1
|
352 |
\noindent\verb|123.456e-7|
|
alpar@1
|
353 |
|
alpar@1
|
354 |
\medskip
|
alpar@1
|
355 |
|
alpar@1
|
356 |
Numeric literals are used to represent numeric quantities. They have
|
alpar@1
|
357 |
obvious fixed meaning.
|
alpar@1
|
358 |
|
alpar@1
|
359 |
\subsection{String literals}
|
alpar@1
|
360 |
|
alpar@1
|
361 |
A {\it string literal} is a sequence of arbitrary characters enclosed
|
alpar@1
|
362 |
either in single quotes or in double quotes. Both these forms are
|
alpar@1
|
363 |
equivalent.
|
alpar@1
|
364 |
|
alpar@1
|
365 |
If the single quote is part of a string literal enclosed in single
|
alpar@1
|
366 |
quotes, it must be coded twice. Analogously, if the double quote is
|
alpar@1
|
367 |
part of a string literal enclosed in double quotes, it must be coded
|
alpar@1
|
368 |
twice.
|
alpar@1
|
369 |
|
alpar@1
|
370 |
\medskip
|
alpar@1
|
371 |
|
alpar@1
|
372 |
\noindent{\bf Examples}
|
alpar@1
|
373 |
|
alpar@1
|
374 |
\medskip
|
alpar@1
|
375 |
|
alpar@1
|
376 |
\noindent\verb|'This is a string'|
|
alpar@1
|
377 |
|
alpar@1
|
378 |
\noindent\verb|"This is another string"|
|
alpar@1
|
379 |
|
alpar@1
|
380 |
\noindent\verb|'1 + 2 = 3'|
|
alpar@1
|
381 |
|
alpar@1
|
382 |
\noindent\verb|'That''s all'|
|
alpar@1
|
383 |
|
alpar@1
|
384 |
\noindent\verb|"She said: ""No"""|
|
alpar@1
|
385 |
|
alpar@1
|
386 |
\medskip
|
alpar@1
|
387 |
|
alpar@1
|
388 |
String literals are used to represent symbolic quantities.
|
alpar@1
|
389 |
|
alpar@1
|
390 |
\subsection{Keywords}
|
alpar@1
|
391 |
|
alpar@1
|
392 |
A {\it keyword} is a sequence of alphabetic characters and possibly
|
alpar@1
|
393 |
some special characters.
|
alpar@1
|
394 |
|
alpar@1
|
395 |
All keywords fall into two categories: {\it reserved keywords}, which
|
alpar@1
|
396 |
cannot be used as symbolic names, and {\it non-reserved keywords},
|
alpar@1
|
397 |
which being recognized by context can be used as symbolic names.
|
alpar@1
|
398 |
|
alpar@1
|
399 |
\newpage
|
alpar@1
|
400 |
|
alpar@1
|
401 |
The reserved keywords are the following:
|
alpar@1
|
402 |
|
alpar@1
|
403 |
\medskip
|
alpar@1
|
404 |
|
alpar@1
|
405 |
\noindent\hfil
|
alpar@1
|
406 |
\begin{tabular}{@{}p{.7in}p{.7in}p{.7in}p{.7in}@{}}
|
alpar@1
|
407 |
{\tt and}&{\tt else}&{\tt mod}&{\tt union}\\
|
alpar@1
|
408 |
{\tt by}&{\tt if}&{\tt not}&{\tt within}\\
|
alpar@1
|
409 |
{\tt cross}&{\tt in}&{\tt or}\\
|
alpar@1
|
410 |
{\tt diff}&{\tt inter}&{\tt symdiff}\\
|
alpar@1
|
411 |
{\tt div}&{\tt less}&{\tt then}\\
|
alpar@1
|
412 |
\end{tabular}
|
alpar@1
|
413 |
|
alpar@1
|
414 |
\medskip
|
alpar@1
|
415 |
|
alpar@1
|
416 |
Non-reserved keywords are described in following sections.
|
alpar@1
|
417 |
|
alpar@1
|
418 |
All the keywords have fixed meaning, which will be explained on
|
alpar@1
|
419 |
discussion of corresponding syntactic constructions, where the keywords
|
alpar@1
|
420 |
are used.
|
alpar@1
|
421 |
|
alpar@1
|
422 |
\subsection{Delimiters}
|
alpar@1
|
423 |
|
alpar@1
|
424 |
A {\it delimiter} is either a single special character or a sequence of
|
alpar@1
|
425 |
two special characters as follows:
|
alpar@1
|
426 |
|
alpar@1
|
427 |
\medskip
|
alpar@1
|
428 |
|
alpar@1
|
429 |
\noindent\hfil
|
alpar@1
|
430 |
\begin{tabular}{@{}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in}p{.3in}@{}}
|
alpar@1
|
431 |
{\tt+}&{\tt\textasciicircum}&{\tt==}&{\tt!}&{\tt:}&{\tt)}\\
|
alpar@1
|
432 |
{\tt-}&{\tt\&}&{\tt>=}&{\tt\&\&}&{\tt;}&{\tt[}\\
|
alpar@1
|
433 |
{\tt*}&{\tt<}&{\tt>}&{\tt||}&{\tt:=}&{\tt|}\\
|
alpar@1
|
434 |
{\tt/}&{\tt<=}&{\tt<>}&{\tt.}&{\tt..}&{\tt\{}\\
|
alpar@1
|
435 |
{\tt**}&{\tt=}&{\tt!=}&{\tt,}&{\tt(}&{\tt\}}\\
|
alpar@1
|
436 |
\end{tabular}
|
alpar@1
|
437 |
|
alpar@1
|
438 |
\medskip
|
alpar@1
|
439 |
|
alpar@1
|
440 |
If the delimiter consists of two characters, there must be no spaces
|
alpar@1
|
441 |
between the characters.
|
alpar@1
|
442 |
|
alpar@1
|
443 |
All the delimiters have fixed meaning, which will be explained on
|
alpar@1
|
444 |
discussion corresponding syntactic constructions, where the delimiters
|
alpar@1
|
445 |
are used.
|
alpar@1
|
446 |
|
alpar@1
|
447 |
\subsection{Comments}
|
alpar@1
|
448 |
|
alpar@1
|
449 |
For documenting purposes the model description can be provided with
|
alpar@1
|
450 |
{\it comments}, which may have two different forms. The first form is
|
alpar@1
|
451 |
a {\it single-line comment}, which begins with the character {\tt\#}
|
alpar@1
|
452 |
and extends until end of line. The second form is a {\it comment
|
alpar@1
|
453 |
sequence}, which is a sequence of any characters enclosed within
|
alpar@1
|
454 |
{\tt/*} and {\tt*/}.
|
alpar@1
|
455 |
|
alpar@1
|
456 |
\medskip
|
alpar@1
|
457 |
|
alpar@1
|
458 |
\noindent{\bf Examples}
|
alpar@1
|
459 |
|
alpar@1
|
460 |
\medskip
|
alpar@1
|
461 |
|
alpar@1
|
462 |
\noindent\verb|param n := 10; # This is a comment|
|
alpar@1
|
463 |
|
alpar@1
|
464 |
\noindent\verb|/* This is another comment */|
|
alpar@1
|
465 |
|
alpar@1
|
466 |
\medskip
|
alpar@1
|
467 |
|
alpar@1
|
468 |
Comments are ignored by the model translator and can appear anywhere in
|
alpar@1
|
469 |
the model description, where white-space characters are allowed.
|
alpar@1
|
470 |
|
alpar@1
|
471 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
alpar@1
|
472 |
|
alpar@1
|
473 |
\newpage
|
alpar@1
|
474 |
|
alpar@1
|
475 |
\section{Expressions}
|
alpar@1
|
476 |
|
alpar@1
|
477 |
An {\it expression} is a rule for computing a value. In model
|
alpar@1
|
478 |
description expressions are used as constituents of certain statements.
|
alpar@1
|
479 |
|
alpar@1
|
480 |
In general case expressions consist of operands and operators.
|
alpar@1
|
481 |
|
alpar@1
|
482 |
Depending on the type of the resultant value all expressions fall into
|
alpar@1
|
483 |
the following categories:
|
alpar@1
|
484 |
|
alpar@1
|
485 |
\begin{itemize}
|
alpar@1
|
486 |
\item numeric expressions;
|
alpar@1
|
487 |
\item symbolic expressions;
|
alpar@1
|
488 |
\item indexing expressions;
|
alpar@1
|
489 |
\item set expressions;
|
alpar@1
|
490 |
\item logical expressions;
|
alpar@1
|
491 |
\item linear expressions.
|
alpar@1
|
492 |
\end{itemize}
|
alpar@1
|
493 |
|
alpar@1
|
494 |
\subsection{Numeric expressions}
|
alpar@1
|
495 |
|
alpar@1
|
496 |
A {\it numeric expression} is a rule for computing a single numeric
|
alpar@1
|
497 |
value represented as a floating-point number.
|
alpar@1
|
498 |
|
alpar@1
|
499 |
The primary numeric expression may be a numeric literal, dummy index,
|
alpar@1
|
500 |
unsubscripted parameter, subscripted parameter, built-in function
|
alpar@1
|
501 |
reference, iterated numeric expression, conditional numeric expression,
|
alpar@1
|
502 |
or another numeric expression enclosed in parentheses.
|
alpar@1
|
503 |
|
alpar@1
|
504 |
\medskip
|
alpar@1
|
505 |
|
alpar@1
|
506 |
\noindent{\bf Examples}
|
alpar@1
|
507 |
|
alpar@1
|
508 |
\medskip
|
alpar@1
|
509 |
|
alpar@1
|
510 |
\noindent
|
alpar@1
|
511 |
\begin{tabular}{@{}ll@{}}
|
alpar@1
|
512 |
\verb|1.23|&(numeric literal)\\
|
alpar@1
|
513 |
\verb|j|&(dummy index)\\
|
alpar@1
|
514 |
\verb|time|&(unsubscripted parameter)\\
|
alpar@1
|
515 |
\verb|a['May 2003',j+1]|&(subscripted parameter)\\
|
alpar@1
|
516 |
\verb|abs(b[i,j])|&(function reference)\\
|
alpar@1
|
517 |
\verb|sum{i in S diff T} alpha[i] * b[i,j]|&(iterated expression)\\
|
alpar@1
|
518 |
\verb|if i in I then 2 * p else q[i+1]|&(conditional expression)\\
|
alpar@1
|
519 |
\verb|(b[i,j] + .5 * c)|&(parenthesized expression)\\
|
alpar@1
|
520 |
\end{tabular}
|
alpar@1
|
521 |
|
alpar@1
|
522 |
\medskip
|
alpar@1
|
523 |
|
alpar@1
|
524 |
More general numeric expressions containing two or more primary numeric
|
alpar@1
|
525 |
expressions may be constructed by using certain arithmetic operators.
|
alpar@1
|
526 |
|
alpar@1
|
527 |
\medskip
|
alpar@1
|
528 |
|
alpar@1
|
529 |
\noindent{\bf Examples}
|
alpar@1
|
530 |
|
alpar@1
|
531 |
\medskip
|
alpar@1
|
532 |
|
alpar@1
|
533 |
\noindent\verb|j+1|
|
alpar@1
|
534 |
|
alpar@1
|
535 |
\noindent\verb|2 * a[i-1,j+1] - b[i,j]|
|
alpar@1
|
536 |
|
alpar@1
|
537 |
\noindent\verb|sum{j in J} a[i,j] * x[j] + sum{k in K} b[i,k] * x[k]|
|
alpar@1
|
538 |
|
alpar@1
|
539 |
\noindent\verb|(if i in I then 2 * p else q[i+1]) / (a[i,j] + 1.5)|
|
alpar@1
|
540 |
|
alpar@1
|
541 |
\subsubsection{Numeric literals}
|
alpar@1
|
542 |
|
alpar@1
|
543 |
If the primary numeric expression is a numeric literal, the resultant
|
alpar@1
|
544 |
value is obvious.
|
alpar@1
|
545 |
|
alpar@1
|
546 |
\subsubsection{Dummy indices}
|
alpar@1
|
547 |
|
alpar@1
|
548 |
If the primary numeric expression is a dummy index, the resultant value
|
alpar@1
|
549 |
is current value assigned to that dummy index.
|
alpar@1
|
550 |
|
alpar@1
|
551 |
\subsubsection{Unsubscripted parameters}
|
alpar@1
|
552 |
|
alpar@1
|
553 |
If the primary numeric expression is an unsubscripted parameter (which
|
alpar@1
|
554 |
must be 0-dimensional), the resultant value is the value of that
|
alpar@1
|
555 |
parameter.
|
alpar@1
|
556 |
|
alpar@1
|
557 |
\subsubsection{Subscripted parameters}
|
alpar@1
|
558 |
|
alpar@1
|
559 |
The primary numeric expression, which refers to a subscripted parameter,
|
alpar@1
|
560 |
has the following syntactic form:
|
alpar@1
|
561 |
|
alpar@1
|
562 |
\medskip
|
alpar@1
|
563 |
|
alpar@1
|
564 |
\noindent\hfil
|
alpar@1
|
565 |
{\it name}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} $i_n${\tt]}
|
alpar@1
|
566 |
|
alpar@1
|
567 |
\medskip
|
alpar@1
|
568 |
|
alpar@1
|
569 |
\noindent where {\it name} is the symbolic name of the parameter,
|
alpar@1
|
570 |
$i_1$, $i_2$, \dots, $i_n$ are subscripts.
|
alpar@1
|
571 |
|
alpar@1
|
572 |
Each subscript must be a numeric or symbolic expression. The number of
|
alpar@1
|
573 |
subscripts in the subscript list must be the same as the dimension of
|
alpar@1
|
574 |
the parameter with which the subscript list is associated.
|
alpar@1
|
575 |
|
alpar@1
|
576 |
Actual values of subscript expressions are used to identify
|
alpar@1
|
577 |
a particular member of the parameter that determines the resultant
|
alpar@1
|
578 |
value of the primary expression.
|
alpar@1
|
579 |
|
alpar@1
|
580 |
\subsubsection{Function references}
|
alpar@1
|
581 |
|
alpar@1
|
582 |
In MathProg there exist the following built-in functions which may be
|
alpar@1
|
583 |
used in numeric expressions:
|
alpar@1
|
584 |
|
alpar@1
|
585 |
\medskip
|
alpar@1
|
586 |
|
alpar@1
|
587 |
\begin{tabular}{@{}p{96pt}p{222pt}@{}}
|
alpar@1
|
588 |
{\tt abs(}$x${\tt)}&$|x|$, absolute value of $x$\\
|
alpar@1
|
589 |
{\tt atan(}$x${\tt)}&$\arctan x$, principal value of the arc tangent of
|
alpar@1
|
590 |
$x$ (in radians)\\
|
alpar@1
|
591 |
{\tt atan(}$y${\tt,} $x${\tt)}&$\arctan y/x$, principal value of the
|
alpar@1
|
592 |
arc tangent of $y/x$ (in radians). In this case the signs of both
|
alpar@1
|
593 |
arguments $y$ and $x$ are used to determine the quadrant of the
|
alpar@1
|
594 |
resultant value\\
|
alpar@1
|
595 |
{\tt card(}$X${\tt)}&$|X|$, cardinality (the number of elements) of
|
alpar@1
|
596 |
set $X$\\
|
alpar@1
|
597 |
{\tt ceil(}$x${\tt)}&$\lceil x\rceil$, smallest integer not less than
|
alpar@1
|
598 |
$x$ (``ceiling of $x$'')\\
|
alpar@1
|
599 |
{\tt cos(}$x${\tt)}&$\cos x$, cosine of $x$ (in radians)\\
|
alpar@1
|
600 |
{\tt exp(}$x${\tt)}&$e^x$, base-$e$ exponential of $x$\\
|
alpar@1
|
601 |
{\tt floor(}$x${\tt)}&$\lfloor x\rfloor$, largest integer not greater
|
alpar@1
|
602 |
than $x$ (``floor of $x$'')\\
|
alpar@1
|
603 |
\end{tabular}
|
alpar@1
|
604 |
|
alpar@1
|
605 |
\begin{tabular}{@{}p{96pt}p{222pt}@{}}
|
alpar@1
|
606 |
{\tt gmtime()}&the number of seconds elapsed since 00:00:00~Jan~1, 1970,
|
alpar@1
|
607 |
Coordinated Universal Time (for details see Subsection \ref{gmtime},
|
alpar@1
|
608 |
page \pageref{gmtime})\\
|
alpar@1
|
609 |
{\tt length(}$s${\tt)}&$|s|$, length of character string $s$\\
|
alpar@1
|
610 |
{\tt log(}$x${\tt)}&$\log x$, natural logarithm of $x$\\
|
alpar@1
|
611 |
{\tt log10(}$x${\tt)}&$\log_{10}x$, common (decimal) logarithm of $x$\\
|
alpar@1
|
612 |
{\tt max(}$x_1${\tt,} $x_2${\tt,} \dots{\tt,} $x_n${\tt)}&the largest
|
alpar@1
|
613 |
of values $x_1$, $x_2$, \dots, $x_n$\\
|
alpar@1
|
614 |
{\tt min(}$x_1${\tt,} $x_2${\tt,} \dots{\tt,} $x_n${\tt)}&the smallest
|
alpar@1
|
615 |
of values $x_1$, $x_2$, \dots, $x_n$\\
|
alpar@1
|
616 |
{\tt round(}$x${\tt)}&rounding $x$ to nearest integer\\
|
alpar@1
|
617 |
{\tt round(}$x${\tt,} $n${\tt)}&rounding $x$ to $n$ fractional decimal
|
alpar@1
|
618 |
digits\\
|
alpar@1
|
619 |
{\tt sin(}$x${\tt)}&$\sin x$, sine of $x$ (in radians)\\
|
alpar@1
|
620 |
{\tt sqrt(}$x${\tt)}&$\sqrt{x}$, non-negative square root of $x$\\
|
alpar@1
|
621 |
{\tt str2time(}$s${\tt,} $f${\tt)}&converting character string $s$ to
|
alpar@1
|
622 |
calendar time (for details see Subsection \ref{str2time}, page
|
alpar@1
|
623 |
\pageref{str2time})\\
|
alpar@1
|
624 |
{\tt trunc(}$x${\tt)}&truncating $x$ to nearest integer\\
|
alpar@1
|
625 |
{\tt trunc(}$x${\tt,} $n${\tt)}&truncating $x$ to $n$ fractional
|
alpar@1
|
626 |
decimal digits\\
|
alpar@1
|
627 |
{\tt Irand224()}&generating pseudo-random integer uniformly distributed
|
alpar@1
|
628 |
in $[0,2^{24})$\\
|
alpar@1
|
629 |
{\tt Uniform01()}&generating pseudo-random number uniformly distributed
|
alpar@1
|
630 |
in $[0,1)$\\
|
alpar@1
|
631 |
{\tt Uniform(}$a${\tt,} $b${\tt)}&generating pseudo-random number
|
alpar@1
|
632 |
uniformly distributed in $[a,b)$\\
|
alpar@1
|
633 |
{\tt Normal01()}&generating Gaussian pseudo-random variate with
|
alpar@1
|
634 |
$\mu=0$ and $\sigma=1$\\
|
alpar@1
|
635 |
{\tt Normal(}$\mu${\tt,} $\sigma${\tt)}&generating Gaussian
|
alpar@1
|
636 |
pseudo-random variate with given $\mu$ and $\sigma$\\
|
alpar@1
|
637 |
\end{tabular}
|
alpar@1
|
638 |
|
alpar@1
|
639 |
\medskip
|
alpar@1
|
640 |
|
alpar@1
|
641 |
Arguments of all built-in functions, except {\tt card}, {\tt length},
|
alpar@1
|
642 |
and {\tt str2time}, must be numeric expressions. The argument of
|
alpar@1
|
643 |
{\tt card} must be a set expression. The argument of {\tt length} and
|
alpar@1
|
644 |
both arguments of {\tt str2time} must be symbolic expressions.
|
alpar@1
|
645 |
|
alpar@1
|
646 |
The resultant value of the numeric expression, which is a function
|
alpar@1
|
647 |
reference, is the result of applying the function to its argument(s).
|
alpar@1
|
648 |
|
alpar@1
|
649 |
Note that each pseudo-random generator function has a latent argument
|
alpar@1
|
650 |
(i.e. some internal state), which is changed whenever the function has
|
alpar@1
|
651 |
been applied. Thus, if the function is applied repeatedly even to
|
alpar@1
|
652 |
identical arguments, due to the side effect different resultant values
|
alpar@1
|
653 |
are always produced.
|
alpar@1
|
654 |
|
alpar@1
|
655 |
\subsubsection{Iterated expressions}
|
alpar@1
|
656 |
\label{itexpr}
|
alpar@1
|
657 |
|
alpar@1
|
658 |
An {\it iterated numeric expression} is a primary numeric expression,
|
alpar@1
|
659 |
which has the following syntactic form:
|
alpar@1
|
660 |
|
alpar@1
|
661 |
\medskip
|
alpar@1
|
662 |
|
alpar@1
|
663 |
\noindent\hfil
|
alpar@1
|
664 |
{\it iterated-operator indexing-expression integrand}
|
alpar@1
|
665 |
|
alpar@1
|
666 |
\medskip
|
alpar@1
|
667 |
|
alpar@1
|
668 |
\noindent where {\it iterated-operator} is the symbolic name of the
|
alpar@1
|
669 |
iterated operator to be performed (see below), {\it indexing-expression}
|
alpar@1
|
670 |
is an indexing expression which introduces dummy indices and controls
|
alpar@1
|
671 |
iterating, {\it integrand} is a numeric expression that participates in
|
alpar@1
|
672 |
the operation.
|
alpar@1
|
673 |
|
alpar@1
|
674 |
In MathProg there exist four iterated operators, which may be used in
|
alpar@1
|
675 |
numeric expressions:
|
alpar@1
|
676 |
|
alpar@1
|
677 |
\medskip
|
alpar@1
|
678 |
|
alpar@1
|
679 |
\noindent\hfil
|
alpar@1
|
680 |
\begin{tabular}{@{}lll@{}}
|
alpar@1
|
681 |
{\tt sum}&summation&$\displaystyle\sum_{(i_1,\dots,i_n)\in\Delta}
|
alpar@1
|
682 |
f(i_1,\dots,i_n)$\\
|
alpar@1
|
683 |
{\tt prod}&production&$\displaystyle\prod_{(i_1,\dots,i_n)\in\Delta}
|
alpar@1
|
684 |
f(i_1,\dots,i_n)$\\
|
alpar@1
|
685 |
{\tt min}&minimum&$\displaystyle\min_{(i_1,\dots,i_n)\in\Delta}
|
alpar@1
|
686 |
f(i_1,\dots,i_n)$\\
|
alpar@1
|
687 |
{\tt max}&maximum&$\displaystyle\max_{(i_1,\dots,i_n)\in\Delta}
|
alpar@1
|
688 |
f(i_1,\dots,i_n)$\\
|
alpar@1
|
689 |
\end{tabular}
|
alpar@1
|
690 |
|
alpar@1
|
691 |
\medskip
|
alpar@1
|
692 |
|
alpar@1
|
693 |
\noindent where $i_1$, \dots, $i_n$ are dummy indices introduced in
|
alpar@1
|
694 |
the indexing expression, $\Delta$ is the domain, a set of $n$-tuples
|
alpar@1
|
695 |
specified by the indexing expression which defines particular values
|
alpar@1
|
696 |
assigned to the dummy indices on performing the iterated operation,
|
alpar@1
|
697 |
$f(i_1,\dots,i_n)$ is the integrand, a numeric expression whose
|
alpar@1
|
698 |
resultant value depends on the dummy indices.
|
alpar@1
|
699 |
|
alpar@1
|
700 |
The resultant value of an iterated numeric expression is the result of
|
alpar@1
|
701 |
applying of the iterated operator to its integrand over all $n$-tuples
|
alpar@1
|
702 |
contained in the domain.
|
alpar@1
|
703 |
|
alpar@1
|
704 |
\subsubsection{Conditional expressions}
|
alpar@1
|
705 |
\label{ifthen}
|
alpar@1
|
706 |
|
alpar@1
|
707 |
A {\it conditional numeric expression} is a primary numeric expression,
|
alpar@1
|
708 |
which has one of the following two syntactic forms:
|
alpar@1
|
709 |
|
alpar@1
|
710 |
\medskip
|
alpar@1
|
711 |
|
alpar@1
|
712 |
\noindent\hfil
|
alpar@1
|
713 |
{\tt if} $b$ {\tt then} $x$ {\tt else} $y$
|
alpar@1
|
714 |
|
alpar@1
|
715 |
\medskip
|
alpar@1
|
716 |
|
alpar@1
|
717 |
\noindent\hspace{126.5pt}
|
alpar@1
|
718 |
{\tt if} $b$ {\tt then} $x$
|
alpar@1
|
719 |
|
alpar@1
|
720 |
\medskip
|
alpar@1
|
721 |
|
alpar@1
|
722 |
\noindent where $b$ is an logical expression, $x$ and $y$ are numeric
|
alpar@1
|
723 |
expressions.
|
alpar@1
|
724 |
|
alpar@1
|
725 |
The resultant value of the conditional expression depends on the value
|
alpar@1
|
726 |
of the logical expression that follows the keyword {\tt if}. If it
|
alpar@1
|
727 |
takes on the value {\it true}, the value of the conditional expression
|
alpar@1
|
728 |
is the value of the expression that follows the keyword {\tt then}.
|
alpar@1
|
729 |
Otherwise, if the logical expression takes on the value {\it false},
|
alpar@1
|
730 |
the value of the conditional expression is the value of the expression
|
alpar@1
|
731 |
that follows the keyword {\it else}. If the second, reduced form of the
|
alpar@1
|
732 |
conditional expression is used and the logical expression takes on the
|
alpar@1
|
733 |
value {\it false}, the resultant value of the conditional expression is
|
alpar@1
|
734 |
zero.
|
alpar@1
|
735 |
|
alpar@1
|
736 |
\subsubsection{Parenthesized expressions}
|
alpar@1
|
737 |
|
alpar@1
|
738 |
Any numeric expression may be enclosed in parentheses that
|
alpar@1
|
739 |
syntactically makes it a primary numeric expression.
|
alpar@1
|
740 |
|
alpar@1
|
741 |
Parentheses may be used in numeric expressions, as in algebra, to
|
alpar@1
|
742 |
specify the desired order in which operations are to be performed.
|
alpar@1
|
743 |
Where parentheses are used, the expression within the parentheses is
|
alpar@1
|
744 |
evaluated before the resultant value is used.
|
alpar@1
|
745 |
|
alpar@1
|
746 |
The resultant value of the parenthesized expression is the same as the
|
alpar@1
|
747 |
value of the expression enclosed within parentheses.
|
alpar@1
|
748 |
|
alpar@1
|
749 |
\subsubsection{Arithmetic operators}
|
alpar@1
|
750 |
|
alpar@1
|
751 |
In MathProg there exist the following arithmetic operators, which may
|
alpar@1
|
752 |
be used in numeric expressions:
|
alpar@1
|
753 |
|
alpar@1
|
754 |
\medskip
|
alpar@1
|
755 |
|
alpar@1
|
756 |
\begin{tabular}{@{}p{96pt}p{222pt}@{}}
|
alpar@1
|
757 |
{\tt +} $x$&unary plus\\
|
alpar@1
|
758 |
{\tt -} $x$&unary minus\\
|
alpar@1
|
759 |
$x$ {\tt +} $y$&addition\\
|
alpar@1
|
760 |
$x$ {\tt -} $y$&subtraction\\
|
alpar@1
|
761 |
$x$ {\tt less} $y$&positive difference (if $x<y$ then 0 else $x-y$)\\
|
alpar@1
|
762 |
$x$ {\tt *} $y$&multiplication\\
|
alpar@1
|
763 |
$x$ {\tt /} $y$&division\\
|
alpar@1
|
764 |
$x$ {\tt div} $y$"ient of exact division\\
|
alpar@1
|
765 |
$x$ {\tt mod} $y$&remainder of exact division\\
|
alpar@1
|
766 |
$x$ {\tt **} $y$, $x$ {\tt\textasciicircum} $y$&exponentiation (raising
|
alpar@1
|
767 |
to power)\\
|
alpar@1
|
768 |
\end{tabular}
|
alpar@1
|
769 |
|
alpar@1
|
770 |
\medskip
|
alpar@1
|
771 |
|
alpar@1
|
772 |
\noindent where $x$ and $y$ are numeric expressions.
|
alpar@1
|
773 |
|
alpar@1
|
774 |
If the expression includes more than one arithmetic operator, all
|
alpar@1
|
775 |
operators are performed from left to right according to the hierarchy
|
alpar@1
|
776 |
of operations (see below) with the only exception that the
|
alpar@1
|
777 |
exponentiaion operators are performed from right to left.
|
alpar@1
|
778 |
|
alpar@1
|
779 |
The resultant value of the expression, which contains arithmetic
|
alpar@1
|
780 |
operators, is the result of applying the operators to their operands.
|
alpar@1
|
781 |
|
alpar@1
|
782 |
\subsubsection{Hierarchy of operations}
|
alpar@1
|
783 |
\label{hierarchy}
|
alpar@1
|
784 |
|
alpar@1
|
785 |
The following list shows the hierarchy of operations in numeric
|
alpar@1
|
786 |
expressions:
|
alpar@1
|
787 |
|
alpar@1
|
788 |
\medskip
|
alpar@1
|
789 |
|
alpar@1
|
790 |
\noindent\hfil
|
alpar@1
|
791 |
\begin{tabular}{@{}ll@{}}
|
alpar@1
|
792 |
Operation&Hierarchy\\
|
alpar@1
|
793 |
\hline
|
alpar@1
|
794 |
Evaluation of functions ({\tt abs}, {\tt ceil}, etc.)&1st\\
|
alpar@1
|
795 |
Exponentiation ({\tt**}, {\tt\textasciicircum})&2nd\\
|
alpar@1
|
796 |
Unary plus and minus ({\tt+}, {\tt-})&3rd\\
|
alpar@1
|
797 |
Multiplication and division ({\tt*}, {\tt/}, {\tt div}, {\tt mod})&4th\\
|
alpar@1
|
798 |
Iterated operations ({\tt sum}, {\tt prod}, {\tt min}, {\tt max})&5th\\
|
alpar@1
|
799 |
Addition and subtraction ({\tt+}, {\tt-}, {\tt less})&6th\\
|
alpar@1
|
800 |
Conditional evaluation ({\tt if} \dots {\tt then} \dots {\tt else})&
|
alpar@1
|
801 |
7th\\
|
alpar@1
|
802 |
\end{tabular}
|
alpar@1
|
803 |
|
alpar@1
|
804 |
\medskip
|
alpar@1
|
805 |
|
alpar@1
|
806 |
This hierarchy is used to determine which of two consecutive operations
|
alpar@1
|
807 |
is performed first. If the first operator is higher than or equal to
|
alpar@1
|
808 |
the second, the first operation is performed. If it is not, the second
|
alpar@1
|
809 |
operator is compared to the third, etc. When the end of the expression
|
alpar@1
|
810 |
is reached, all of the remaining operations are performed in the
|
alpar@1
|
811 |
reverse order.
|
alpar@1
|
812 |
|
alpar@1
|
813 |
\newpage
|
alpar@1
|
814 |
|
alpar@1
|
815 |
\subsection{Symbolic expressions}
|
alpar@1
|
816 |
|
alpar@1
|
817 |
A {\it symbolic expression} is a rule for computing a single symbolic
|
alpar@1
|
818 |
value represented as a character string.
|
alpar@1
|
819 |
|
alpar@1
|
820 |
The primary symbolic expression may be a string literal, dummy index,
|
alpar@1
|
821 |
unsubscripted parameter, subscripted parameter, built-in function
|
alpar@1
|
822 |
reference, conditional symbolic expression, or another symbolic
|
alpar@1
|
823 |
expression enclosed in parentheses.
|
alpar@1
|
824 |
|
alpar@1
|
825 |
It is also allowed to use a numeric expression as the primary symbolic
|
alpar@1
|
826 |
expression, in which case the resultant value of the numeric expression
|
alpar@1
|
827 |
is automatically converted to the symbolic type.
|
alpar@1
|
828 |
|
alpar@1
|
829 |
\medskip
|
alpar@1
|
830 |
|
alpar@1
|
831 |
\noindent{\bf Examples}
|
alpar@1
|
832 |
|
alpar@1
|
833 |
\medskip
|
alpar@1
|
834 |
|
alpar@1
|
835 |
\noindent
|
alpar@1
|
836 |
\begin{tabular}{@{}ll@{}}
|
alpar@1
|
837 |
\verb|'May 2003'|&(string literal)\\
|
alpar@1
|
838 |
\verb|j|&(dummy index)\\
|
alpar@1
|
839 |
\verb|p|&(unsubscripted parameter)\\
|
alpar@1
|
840 |
\verb|s['abc',j+1]|&(subscripted parameter)\\
|
alpar@1
|
841 |
\verb|substr(name[i],k+1,3)|&(function reference)\\
|
alpar@1
|
842 |
\verb|if i in I then s[i,j] else t[i+1]|&(conditional expression)\\
|
alpar@1
|
843 |
\verb|((10 * b[i,j]) & '.bis')|&(parenthesized expression)\\
|
alpar@1
|
844 |
\end{tabular}
|
alpar@1
|
845 |
|
alpar@1
|
846 |
\medskip
|
alpar@1
|
847 |
|
alpar@1
|
848 |
More general symbolic expressions containing two or more primary
|
alpar@1
|
849 |
symbolic expressions may be constructed by using the concatenation
|
alpar@1
|
850 |
operator.
|
alpar@1
|
851 |
|
alpar@1
|
852 |
\medskip
|
alpar@1
|
853 |
|
alpar@1
|
854 |
\noindent{\bf Examples}
|
alpar@1
|
855 |
|
alpar@1
|
856 |
\medskip
|
alpar@1
|
857 |
|
alpar@1
|
858 |
\noindent\verb|'abc[' & i & ',' & j & ']'|
|
alpar@1
|
859 |
|
alpar@1
|
860 |
\noindent\verb|"from " & city[i] & " to " & city[j]|
|
alpar@1
|
861 |
|
alpar@1
|
862 |
\medskip
|
alpar@1
|
863 |
|
alpar@1
|
864 |
The principles of evaluation of symbolic expressions are completely
|
alpar@1
|
865 |
analogous to the ones given for numeric expressions (see above).
|
alpar@1
|
866 |
|
alpar@1
|
867 |
\subsubsection{Function references}
|
alpar@1
|
868 |
|
alpar@1
|
869 |
In MathProg there exist the following built-in functions which may be
|
alpar@1
|
870 |
used in symbolic expressions:
|
alpar@1
|
871 |
|
alpar@1
|
872 |
\medskip
|
alpar@1
|
873 |
|
alpar@1
|
874 |
\begin{tabular}{@{}p{96pt}p{222pt}@{}}
|
alpar@1
|
875 |
{\tt substr(}$s${\tt,} $x${\tt)}&substring of $s$ starting from
|
alpar@1
|
876 |
position $x$\\
|
alpar@1
|
877 |
{\tt substr(}$s${\tt,} $x${\tt,} $y${\tt)}&substring of $s$ starting
|
alpar@1
|
878 |
from position $x$ and having length $y$\\
|
alpar@1
|
879 |
{\tt time2str(}$t${\tt,} $f${\tt)}&converting calendar time to
|
alpar@1
|
880 |
character string (for details see Subsection \ref{time2str}, page
|
alpar@1
|
881 |
\pageref{time2str})\\
|
alpar@1
|
882 |
\end{tabular}
|
alpar@1
|
883 |
|
alpar@1
|
884 |
\medskip
|
alpar@1
|
885 |
|
alpar@1
|
886 |
The first argument of {\tt substr} must be a symbolic expression while
|
alpar@1
|
887 |
its second and optional third arguments must be numeric expressions.
|
alpar@1
|
888 |
|
alpar@1
|
889 |
The first argument of {\tt time2str} must be a numeric expression, and
|
alpar@1
|
890 |
its second argument must be a symbolic expression.
|
alpar@1
|
891 |
|
alpar@1
|
892 |
The resultant value of the symbolic expression, which is a function
|
alpar@1
|
893 |
reference, is the result of applying the function to its arguments.
|
alpar@1
|
894 |
|
alpar@1
|
895 |
\subsubsection{Symbolic operators}
|
alpar@1
|
896 |
|
alpar@1
|
897 |
Currently in MathProg there exists the only symbolic operator:
|
alpar@1
|
898 |
|
alpar@1
|
899 |
\medskip
|
alpar@1
|
900 |
|
alpar@1
|
901 |
\noindent\hfil
|
alpar@1
|
902 |
{\tt s \& t}
|
alpar@1
|
903 |
|
alpar@1
|
904 |
\medskip
|
alpar@1
|
905 |
|
alpar@1
|
906 |
\noindent where $s$ and $t$ are symbolic expressions. This operator
|
alpar@1
|
907 |
means concatenation of its two symbolic operands, which are character
|
alpar@1
|
908 |
strings.
|
alpar@1
|
909 |
|
alpar@1
|
910 |
\subsubsection{Hierarchy of operations}
|
alpar@1
|
911 |
|
alpar@1
|
912 |
The following list shows the hierarchy of operations in symbolic
|
alpar@1
|
913 |
expressions:
|
alpar@1
|
914 |
|
alpar@1
|
915 |
\medskip
|
alpar@1
|
916 |
|
alpar@1
|
917 |
\noindent\hfil
|
alpar@1
|
918 |
\begin{tabular}{@{}ll@{}}
|
alpar@1
|
919 |
Operation&Hierarchy\\
|
alpar@1
|
920 |
\hline
|
alpar@1
|
921 |
Evaluation of numeric operations&1st-7th\\
|
alpar@1
|
922 |
Concatenation ({\tt\&})&8th\\
|
alpar@1
|
923 |
Conditional evaluation ({\tt if} \dots {\tt then} \dots {\tt else})&
|
alpar@1
|
924 |
7th\\
|
alpar@1
|
925 |
\end{tabular}
|
alpar@1
|
926 |
|
alpar@1
|
927 |
\medskip
|
alpar@1
|
928 |
|
alpar@1
|
929 |
This hierarchy has the same meaning as was explained above for numeric
|
alpar@1
|
930 |
expressions (see Subsection \ref{hierarchy}, page \pageref{hierarchy}).
|
alpar@1
|
931 |
|
alpar@1
|
932 |
\subsection{Indexing expressions and dummy indices}
|
alpar@1
|
933 |
\label{indexing}
|
alpar@1
|
934 |
|
alpar@1
|
935 |
An {\it indexing expression} is an auxiliary construction, which
|
alpar@1
|
936 |
specifies a plain set of $n$-tuples and introduces dummy indices. It
|
alpar@1
|
937 |
has two syntactic forms:
|
alpar@1
|
938 |
|
alpar@1
|
939 |
\medskip
|
alpar@1
|
940 |
|
alpar@1
|
941 |
\noindent\hspace{73.5pt}
|
alpar@1
|
942 |
{\tt\{} {\it entry}$_1${\tt,} {\it entry}$_2${\tt,} \dots{\tt,}
|
alpar@1
|
943 |
{\it entry}$_m$ {\tt\}}
|
alpar@1
|
944 |
|
alpar@1
|
945 |
\medskip
|
alpar@1
|
946 |
|
alpar@1
|
947 |
\noindent\hfil
|
alpar@1
|
948 |
{\tt\{} {\it entry}$_1${\tt,} {\it entry}$_2${\tt,} \dots{\tt,}
|
alpar@1
|
949 |
{\it entry}$_m$ {\tt:} {\it predicate} {\tt\}}
|
alpar@1
|
950 |
|
alpar@1
|
951 |
\medskip
|
alpar@1
|
952 |
|
alpar@1
|
953 |
\noindent where {\it entry}{$_1$}, {\it entry}{$_2$}, \dots,
|
alpar@1
|
954 |
{\it entry}{$_m$} are indexing entries, {\it predicate} is a logical
|
alpar@1
|
955 |
expression that specifies an optional predicate (logical condition).
|
alpar@1
|
956 |
|
alpar@1
|
957 |
Each {\it indexing entry} in the indexing expression has one of the
|
alpar@1
|
958 |
following three forms:
|
alpar@1
|
959 |
|
alpar@1
|
960 |
\medskip
|
alpar@1
|
961 |
|
alpar@1
|
962 |
\noindent\hspace{123pt}
|
alpar@1
|
963 |
$i$ {\tt in} $S$
|
alpar@1
|
964 |
|
alpar@1
|
965 |
\medskip
|
alpar@1
|
966 |
|
alpar@1
|
967 |
\noindent\hfil
|
alpar@1
|
968 |
{\tt(}$i_1${\tt,} $i_2${\tt,} \dots{\tt,}$i_n${\tt)} {\tt in} $S$
|
alpar@1
|
969 |
|
alpar@1
|
970 |
\medskip
|
alpar@1
|
971 |
|
alpar@1
|
972 |
\noindent\hspace{123pt}
|
alpar@1
|
973 |
$S$
|
alpar@1
|
974 |
|
alpar@1
|
975 |
\medskip
|
alpar@1
|
976 |
|
alpar@1
|
977 |
\noindent where $i_1$, $i_2$, \dots, $i_n$ are indices, $S$ is a set
|
alpar@1
|
978 |
expression (discussed in the next section) that specifies the basic set.
|
alpar@1
|
979 |
|
alpar@1
|
980 |
The number of indices in the indexing entry must be the same as the
|
alpar@1
|
981 |
dimension of the basic set $S$, i.e. if $S$ consists of 1-tuples, the
|
alpar@1
|
982 |
first form must be used, and if $S$ consists of $n$-tuples, where
|
alpar@1
|
983 |
$n>1$, the second form must be used.
|
alpar@1
|
984 |
|
alpar@1
|
985 |
If the first form of the indexing entry is used, the index $i$ can be
|
alpar@1
|
986 |
a dummy index only (see below). If the second form is used, the indices
|
alpar@1
|
987 |
$i_1$, $i_2$, \dots, $i_n$ can be either dummy indices or some numeric
|
alpar@1
|
988 |
or symbolic expressions, where at least one index must be a dummy index.
|
alpar@1
|
989 |
The third, reduced form of the indexing entry has the same effect as if
|
alpar@1
|
990 |
there were $i$ (if $S$ is 1-dimensional) or $i_1$, $i_2$, \dots, $i_n$
|
alpar@1
|
991 |
(if $S$ is $n$-dimensional) all specified as dummy indices.
|
alpar@1
|
992 |
|
alpar@1
|
993 |
A {\it dummy index} is an auxiliary model object, which acts like an
|
alpar@1
|
994 |
individual variable. Values assigned to dummy indices are components of
|
alpar@1
|
995 |
$n$-tuples from basic sets, i.e. some numeric and symbolic quantities.
|
alpar@1
|
996 |
|
alpar@1
|
997 |
For referencing purposes dummy indices can be provided with symbolic
|
alpar@1
|
998 |
names. However, unlike other model objects (sets, parameters, etc.)
|
alpar@1
|
999 |
dummy indices need not be explicitly declared. Each {\it undeclared}
|
alpar@1
|
1000 |
symbolic name being used in the indexing position of an indexing entry
|
alpar@1
|
1001 |
is recognized as the symbolic name of corresponding dummy index.
|
alpar@1
|
1002 |
|
alpar@1
|
1003 |
Symbolic names of dummy indices are valid only within the scope of the
|
alpar@1
|
1004 |
indexing expression, where the dummy indices were introduced. Beyond
|
alpar@1
|
1005 |
the scope the dummy indices are completely inaccessible, so the same
|
alpar@1
|
1006 |
symbolic names may be used for other purposes, in particular, to
|
alpar@1
|
1007 |
represent dummy indices in other indexing expressions.
|
alpar@1
|
1008 |
|
alpar@1
|
1009 |
The scope of indexing expression, where implicit declarations of dummy
|
alpar@1
|
1010 |
indices are valid, depends on the context, in which the indexing
|
alpar@1
|
1011 |
expression is used:
|
alpar@1
|
1012 |
|
alpar@1
|
1013 |
\begin{enumerate}
|
alpar@1
|
1014 |
\item If the indexing expression is used in iterated operator, its
|
alpar@1
|
1015 |
scope extends until the end of the integrand.
|
alpar@1
|
1016 |
\item If the indexing expression is used as a primary set expression,
|
alpar@1
|
1017 |
its scope extends until the end of that indexing expression.
|
alpar@1
|
1018 |
\item If the indexing expression is used to define the subscript domain
|
alpar@1
|
1019 |
in declarations of some model objects, its scope extends until the end
|
alpar@1
|
1020 |
of the corresponding statement.
|
alpar@1
|
1021 |
\end{enumerate}
|
alpar@1
|
1022 |
|
alpar@1
|
1023 |
The indexing mechanism implemented by means of indexing expressions is
|
alpar@1
|
1024 |
best explained by some examples discussed below.
|
alpar@1
|
1025 |
|
alpar@1
|
1026 |
Let there be given three sets:
|
alpar@1
|
1027 |
|
alpar@1
|
1028 |
\medskip
|
alpar@1
|
1029 |
|
alpar@1
|
1030 |
\noindent\hspace{33.5pt}
|
alpar@1
|
1031 |
$A=\{4,7,9\}$,
|
alpar@1
|
1032 |
|
alpar@1
|
1033 |
\medskip
|
alpar@1
|
1034 |
|
alpar@1
|
1035 |
\noindent\hfil
|
alpar@1
|
1036 |
$B=\{(1,Jan),(1,Feb),(2,Mar),(2,Apr),(3,May),(3,Jun)\}$,
|
alpar@1
|
1037 |
|
alpar@1
|
1038 |
\medskip
|
alpar@1
|
1039 |
|
alpar@1
|
1040 |
\noindent\hspace{33.5pt}
|
alpar@1
|
1041 |
$C=\{a,b,c\}$,
|
alpar@1
|
1042 |
|
alpar@1
|
1043 |
\medskip
|
alpar@1
|
1044 |
|
alpar@1
|
1045 |
\noindent where $A$ and $C$ consist of 1-tuples (singlets), $B$
|
alpar@1
|
1046 |
consists of 2-tuples (doublets). Consider the following indexing
|
alpar@1
|
1047 |
expression:
|
alpar@1
|
1048 |
|
alpar@1
|
1049 |
\medskip
|
alpar@1
|
1050 |
|
alpar@1
|
1051 |
\noindent\hfil
|
alpar@1
|
1052 |
{\tt\{i in A, (j,k) in B, l in C\}}
|
alpar@1
|
1053 |
|
alpar@1
|
1054 |
\medskip
|
alpar@1
|
1055 |
|
alpar@1
|
1056 |
\noindent where {\tt i}, {\tt j}, {\tt k}, and {\tt l} are dummy
|
alpar@1
|
1057 |
indices.
|
alpar@1
|
1058 |
|
alpar@1
|
1059 |
Although MathProg is not a procedural language, for any indexing
|
alpar@1
|
1060 |
expression an equivalent algorithmic description can be given. In
|
alpar@1
|
1061 |
particular, the algorithmic description of the indexing expression
|
alpar@1
|
1062 |
above could look like follows:
|
alpar@1
|
1063 |
|
alpar@1
|
1064 |
\medskip
|
alpar@1
|
1065 |
|
alpar@1
|
1066 |
\noindent\hfil
|
alpar@1
|
1067 |
\begin{tabular}{@{}l@{}}
|
alpar@1
|
1068 |
{\bf for all} $i\in A$ {\bf do}\\
|
alpar@1
|
1069 |
\hspace{12pt}{\bf for all} $(j,k)\in B$ {\bf do}\\
|
alpar@1
|
1070 |
\hspace{24pt}{\bf for all} $l\in C$ {\bf do}\\
|
alpar@1
|
1071 |
\hspace{36pt}{\it action};\\
|
alpar@1
|
1072 |
\end{tabular}
|
alpar@1
|
1073 |
|
alpar@1
|
1074 |
\newpage
|
alpar@1
|
1075 |
|
alpar@1
|
1076 |
\noindent where the dummy indices $i$, $j$, $k$, $l$ are consecutively
|
alpar@1
|
1077 |
assigned corresponding components of $n$-tuples from the basic sets $A$,
|
alpar@1
|
1078 |
$B$, $C$, and {\it action} is some action that depends on the context,
|
alpar@1
|
1079 |
where the indexing expression is used. For example, if the action were
|
alpar@1
|
1080 |
printing current values of dummy indices, the printout would look like
|
alpar@1
|
1081 |
follows:
|
alpar@1
|
1082 |
|
alpar@1
|
1083 |
\medskip
|
alpar@1
|
1084 |
|
alpar@1
|
1085 |
\noindent\hfil
|
alpar@1
|
1086 |
\begin{tabular}{@{}llll@{}}
|
alpar@1
|
1087 |
$i=4$&$j=1$&$k=Jan$&$l=a$\\
|
alpar@1
|
1088 |
$i=4$&$j=1$&$k=Jan$&$l=b$\\
|
alpar@1
|
1089 |
$i=4$&$j=1$&$k=Jan$&$l=c$\\
|
alpar@1
|
1090 |
$i=4$&$j=1$&$k=Feb$&$l=a$\\
|
alpar@1
|
1091 |
$i=4$&$j=1$&$k=Feb$&$l=b$\\
|
alpar@1
|
1092 |
\multicolumn{4}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\
|
alpar@1
|
1093 |
$i=9$&$j=3$&$k=Jun$&$l=b$\\
|
alpar@1
|
1094 |
$i=9$&$j=3$&$k=Jun$&$l=c$\\
|
alpar@1
|
1095 |
\end{tabular}
|
alpar@1
|
1096 |
|
alpar@1
|
1097 |
\medskip
|
alpar@1
|
1098 |
|
alpar@1
|
1099 |
Let the example indexing expression be used in the following iterated
|
alpar@1
|
1100 |
operation:
|
alpar@1
|
1101 |
|
alpar@1
|
1102 |
\medskip
|
alpar@1
|
1103 |
|
alpar@1
|
1104 |
\noindent\hfil
|
alpar@1
|
1105 |
{\tt sum\{i in A, (j,k) in B, l in C\} p[i,j,k,l]}
|
alpar@1
|
1106 |
|
alpar@1
|
1107 |
\medskip
|
alpar@1
|
1108 |
|
alpar@1
|
1109 |
\noindent where {\tt p} is a 4-dimensional numeric parameter or some
|
alpar@1
|
1110 |
numeric expression whose resultant value depends on {\tt i}, {\tt j},
|
alpar@1
|
1111 |
{\tt k}, and {\tt l}. In this case the action is summation, so the
|
alpar@1
|
1112 |
resultant value of the primary numeric expression is:
|
alpar@1
|
1113 |
$$\sum_{i\in A,(j,k)\in B,l\in C}(p_{ijkl}).$$
|
alpar@1
|
1114 |
|
alpar@1
|
1115 |
Now let the example indexing expression be used as a primary set
|
alpar@1
|
1116 |
expression. In this case the action is gathering all 4-tuples
|
alpar@1
|
1117 |
(quadruplets) of the form $(i,j,k,l)$ in one set, so the resultant
|
alpar@1
|
1118 |
value of such operation is simply the Cartesian product of the basic
|
alpar@1
|
1119 |
sets:
|
alpar@1
|
1120 |
$$A\times B\times C=\{(i,j,k,l):i\in A,(j,k)\in B,l\in C\}.$$
|
alpar@1
|
1121 |
Note that in this case the same indexing expression might be written in
|
alpar@1
|
1122 |
the reduced form:
|
alpar@1
|
1123 |
|
alpar@1
|
1124 |
\medskip
|
alpar@1
|
1125 |
|
alpar@1
|
1126 |
\noindent\hfil
|
alpar@1
|
1127 |
{\tt\{A, B, C\}}
|
alpar@1
|
1128 |
|
alpar@1
|
1129 |
\medskip
|
alpar@1
|
1130 |
|
alpar@1
|
1131 |
\noindent because the dummy indices $i$, $j$, $k$, and $l$ are not
|
alpar@1
|
1132 |
referenced and therefore their symbolic names need not be specified.
|
alpar@1
|
1133 |
|
alpar@1
|
1134 |
Finally, let the example indexing expression be used as the subscript
|
alpar@1
|
1135 |
domain in the declaration of a 4-dimensional model object, say,
|
alpar@1
|
1136 |
a numeric parameter:
|
alpar@1
|
1137 |
|
alpar@1
|
1138 |
\medskip
|
alpar@1
|
1139 |
|
alpar@1
|
1140 |
\noindent\hfil
|
alpar@1
|
1141 |
{\tt param p\{i in A, (j,k) in B, l in C\}} \dots {\tt;}
|
alpar@1
|
1142 |
|
alpar@1
|
1143 |
\medskip
|
alpar@1
|
1144 |
|
alpar@1
|
1145 |
\noindent In this case the action is generating the parameter members,
|
alpar@1
|
1146 |
where each member has the form $p[i,j,k,l]$.
|
alpar@1
|
1147 |
|
alpar@1
|
1148 |
As was said above, some indices in the second form of indexing entries
|
alpar@1
|
1149 |
may be numeric or symbolic expressions, not only dummy indices. In this
|
alpar@1
|
1150 |
case resultant values of such expressions play role of some logical
|
alpar@1
|
1151 |
conditions to select only that $n$-tuples from the Cartesian product of
|
alpar@1
|
1152 |
basic sets that satisfy these conditions.
|
alpar@1
|
1153 |
|
alpar@1
|
1154 |
Consider, for example, the following indexing expression:
|
alpar@1
|
1155 |
|
alpar@1
|
1156 |
\medskip
|
alpar@1
|
1157 |
|
alpar@1
|
1158 |
\noindent\hfil
|
alpar@1
|
1159 |
{\tt\{i in A, (i-1,k) in B, l in C\}}
|
alpar@1
|
1160 |
|
alpar@1
|
1161 |
\medskip
|
alpar@1
|
1162 |
|
alpar@1
|
1163 |
\noindent where {\tt i}, {\tt k}, {\tt l} are dummy indices, and
|
alpar@1
|
1164 |
{\tt i-1} is a numeric expression. The algorithmic decsription of this
|
alpar@1
|
1165 |
indexing expression is the following:
|
alpar@1
|
1166 |
|
alpar@1
|
1167 |
\medskip
|
alpar@1
|
1168 |
|
alpar@1
|
1169 |
\noindent\hfil
|
alpar@1
|
1170 |
\begin{tabular}{@{}l@{}}
|
alpar@1
|
1171 |
{\bf for all} $i\in A$ {\bf do}\\
|
alpar@1
|
1172 |
\hspace{12pt}{\bf for all} $(j,k)\in B$ {\bf and} $j=i-1$ {\bf do}\\
|
alpar@1
|
1173 |
\hspace{24pt}{\bf for all} $l\in C$ {\bf do}\\
|
alpar@1
|
1174 |
\hspace{36pt}{\it action};\\
|
alpar@1
|
1175 |
\end{tabular}
|
alpar@1
|
1176 |
|
alpar@1
|
1177 |
\medskip
|
alpar@1
|
1178 |
|
alpar@1
|
1179 |
\noindent Thus, if this indexing expression were used as a primary set
|
alpar@1
|
1180 |
expression, the resultant set would be the following:
|
alpar@1
|
1181 |
$$\{(4,May,a),(4,May,b),(4,May,c),(4,Jun,a),(4,Jun,b),(4,Jun,c)\}.$$
|
alpar@1
|
1182 |
Should note that in this case the resultant set consists of 3-tuples,
|
alpar@1
|
1183 |
not of 4-tuples, because in the indexing expression there is no dummy
|
alpar@1
|
1184 |
index that corresponds to the first component of 2-tuples from the set
|
alpar@1
|
1185 |
$B$.
|
alpar@1
|
1186 |
|
alpar@1
|
1187 |
The general rule is: the number of components of $n$-tuples defined by
|
alpar@1
|
1188 |
an indexing expression is the same as the number of dummy indices in
|
alpar@1
|
1189 |
that expression, where the correspondence between dummy indices and
|
alpar@1
|
1190 |
components on $n$-tuples in the resultant set is positional, i.e. the
|
alpar@1
|
1191 |
first dummy index corresponds to the first component, the second dummy
|
alpar@1
|
1192 |
index corresponds to the second component, etc.
|
alpar@1
|
1193 |
|
alpar@1
|
1194 |
In some cases it is needed to select a subset from the Cartesian
|
alpar@1
|
1195 |
product of some sets. This may be attained by using an optional logical
|
alpar@1
|
1196 |
predicate, which is specified in the indexing expression.
|
alpar@1
|
1197 |
|
alpar@1
|
1198 |
Consider, for example, the following indexing expression:
|
alpar@1
|
1199 |
|
alpar@1
|
1200 |
\medskip
|
alpar@1
|
1201 |
|
alpar@1
|
1202 |
\noindent\hfil
|
alpar@1
|
1203 |
{\tt\{i in A, (j,k) in B, l in C: i <= 5 and k <> 'Mar'\}}
|
alpar@1
|
1204 |
|
alpar@1
|
1205 |
\medskip
|
alpar@1
|
1206 |
|
alpar@1
|
1207 |
\noindent where the logical expression following the colon is a
|
alpar@1
|
1208 |
predicate. The algorithmic description of this indexing expression is
|
alpar@1
|
1209 |
the following:
|
alpar@1
|
1210 |
|
alpar@1
|
1211 |
\medskip
|
alpar@1
|
1212 |
|
alpar@1
|
1213 |
\noindent\hfil
|
alpar@1
|
1214 |
\begin{tabular}{@{}l@{}}
|
alpar@1
|
1215 |
{\bf for all} $i\in A$ {\bf do}\\
|
alpar@1
|
1216 |
\hspace{12pt}{\bf for all} $(j,k)\in B$ {\bf do}\\
|
alpar@1
|
1217 |
\hspace{24pt}{\bf for all} $l\in C$ {\bf do}\\
|
alpar@1
|
1218 |
\hspace{36pt}{\bf if} $i\leq 5$ {\bf and} $l\neq`Mar'$ {\bf then}\\
|
alpar@1
|
1219 |
\hspace{48pt}{\it action};\\
|
alpar@1
|
1220 |
\end{tabular}
|
alpar@1
|
1221 |
|
alpar@1
|
1222 |
\medskip
|
alpar@1
|
1223 |
|
alpar@1
|
1224 |
\noindent Thus, if this indexing expression were used as a primary set
|
alpar@1
|
1225 |
expression, the resultant set would be the following:
|
alpar@1
|
1226 |
$$\{(4,1,Jan,a),(4,1,Feb,a),(4,2,Apr,a),\dots,(4,3,Jun,c)\}.$$
|
alpar@1
|
1227 |
|
alpar@1
|
1228 |
If no predicate is specified in the indexing expression, one, which
|
alpar@1
|
1229 |
takes on the value {\it true}, is assumed.
|
alpar@1
|
1230 |
|
alpar@1
|
1231 |
\subsection{Set expressions}
|
alpar@1
|
1232 |
|
alpar@1
|
1233 |
A {\it set expression} is a rule for computing an elemental set, i.e.
|
alpar@1
|
1234 |
a collection of $n$-tuples, where components of $n$-tuples are numeric
|
alpar@1
|
1235 |
and symbolic quantities.
|
alpar@1
|
1236 |
|
alpar@1
|
1237 |
The primary set expression may be a literal set, unsubscripted set,
|
alpar@1
|
1238 |
subscripted set, ``arithmetic'' set, indexing expression, iterated set
|
alpar@1
|
1239 |
expression, conditional set expression, or another set expression
|
alpar@1
|
1240 |
enclosed in parentheses.
|
alpar@1
|
1241 |
|
alpar@1
|
1242 |
\medskip
|
alpar@1
|
1243 |
|
alpar@1
|
1244 |
\noindent{\bf Examples}
|
alpar@1
|
1245 |
|
alpar@1
|
1246 |
\medskip
|
alpar@1
|
1247 |
|
alpar@1
|
1248 |
\noindent
|
alpar@1
|
1249 |
\begin{tabular}{@{}ll@{}}
|
alpar@1
|
1250 |
\verb|{(123,'aa'), (i,'bb'), (j-1,'cc')}|&(literal set)\\
|
alpar@1
|
1251 |
\verb|I|&(unsubscripted set)\\
|
alpar@1
|
1252 |
\verb|S[i-1,j+1]|&(subscripted set)\\
|
alpar@1
|
1253 |
\verb|1..t-1 by 2|&(``arithmetic'' set)\\
|
alpar@1
|
1254 |
\verb|{t in 1..T, (t+1,j) in S: (t,j) in F}|&(indexing expression)\\
|
alpar@1
|
1255 |
\verb|setof{i in I, j in J}(i+1,j-1)|&(iterated expression)\\
|
alpar@1
|
1256 |
\verb|if i < j then S[i] else F diff S[j]|&(conditional expression)\\
|
alpar@1
|
1257 |
\verb|(1..10 union 21..30)|&(parenthesized expression)\\
|
alpar@1
|
1258 |
\end{tabular}
|
alpar@1
|
1259 |
|
alpar@1
|
1260 |
\medskip
|
alpar@1
|
1261 |
|
alpar@1
|
1262 |
More general set expressions containing two or more primary set
|
alpar@1
|
1263 |
expressions may be constructed by using certain set operators.
|
alpar@1
|
1264 |
|
alpar@1
|
1265 |
\medskip
|
alpar@1
|
1266 |
|
alpar@1
|
1267 |
\noindent{\bf Examples}
|
alpar@1
|
1268 |
|
alpar@1
|
1269 |
\medskip
|
alpar@1
|
1270 |
|
alpar@1
|
1271 |
\noindent\verb|(A union B) inter (I cross J)|
|
alpar@1
|
1272 |
|
alpar@1
|
1273 |
\noindent
|
alpar@1
|
1274 |
\verb|1..10 cross (if i < j then {'a', 'b', 'c'} else {'d', 'e', 'f'})|
|
alpar@1
|
1275 |
|
alpar@1
|
1276 |
\subsubsection{Literal sets}
|
alpar@1
|
1277 |
|
alpar@1
|
1278 |
A {\it literal set} is a primary set expression, which has the
|
alpar@1
|
1279 |
following two syntactic forms:
|
alpar@1
|
1280 |
|
alpar@1
|
1281 |
\medskip
|
alpar@1
|
1282 |
|
alpar@1
|
1283 |
\noindent\hspace{39pt}
|
alpar@1
|
1284 |
{\tt\{}$e_1${\tt,} $e_2${\tt,} \dots{\tt,} $e_m${\tt\}}
|
alpar@1
|
1285 |
|
alpar@1
|
1286 |
\medskip
|
alpar@1
|
1287 |
|
alpar@1
|
1288 |
\noindent\hfil
|
alpar@1
|
1289 |
{\tt\{(}$e_{11}${\tt,} \dots{\tt,} $e_{1n}${\tt),}
|
alpar@1
|
1290 |
{\tt(}$e_{21}${\tt,} \dots{\tt,} $e_{2n}${\tt),} \dots{\tt,}
|
alpar@1
|
1291 |
{\tt(}$e_{m1}${\tt,} \dots{\tt,} $e_{mn}${\tt)\}}
|
alpar@1
|
1292 |
|
alpar@1
|
1293 |
\medskip
|
alpar@1
|
1294 |
|
alpar@1
|
1295 |
\noindent where $e_1$, \dots, $e_m$, $e_{11}$, \dots, $e_{mn}$ are
|
alpar@1
|
1296 |
numeric or symbolic expressions.
|
alpar@1
|
1297 |
|
alpar@1
|
1298 |
If the first form is used, the resultant set consists of 1-tuples
|
alpar@1
|
1299 |
(singlets) enumerated within the curly braces. It is allowed to specify
|
alpar@1
|
1300 |
an empty set as {\tt\{\ \}}, which has no 1-tuples. If the second form
|
alpar@1
|
1301 |
is used, the resultant set consists of $n$-tuples enumerated within the
|
alpar@1
|
1302 |
curly braces, where a particular $n$-tuple consists of corresponding
|
alpar@1
|
1303 |
components enumerated within the parentheses. All $n$-tuples must have
|
alpar@1
|
1304 |
the same number of components.
|
alpar@1
|
1305 |
|
alpar@1
|
1306 |
\subsubsection{Unsubscripted sets}
|
alpar@1
|
1307 |
|
alpar@1
|
1308 |
If the primary set expression is an unsubscripted set (which must be
|
alpar@1
|
1309 |
0-dimen\-sional), the resultant set is an elemental set associated with
|
alpar@1
|
1310 |
the corresponding set object.
|
alpar@1
|
1311 |
|
alpar@1
|
1312 |
\newpage
|
alpar@1
|
1313 |
|
alpar@1
|
1314 |
\subsubsection{Subscripted sets}
|
alpar@1
|
1315 |
|
alpar@1
|
1316 |
The primary set expression, which refers to a subscripted set, has the
|
alpar@1
|
1317 |
following syntactic form:
|
alpar@1
|
1318 |
|
alpar@1
|
1319 |
\medskip
|
alpar@1
|
1320 |
|
alpar@1
|
1321 |
\noindent\hfil
|
alpar@1
|
1322 |
{\it name}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} $i_n${\tt]}
|
alpar@1
|
1323 |
|
alpar@1
|
1324 |
\medskip
|
alpar@1
|
1325 |
|
alpar@1
|
1326 |
\noindent where {\it name} is the symbolic name of the set object,
|
alpar@1
|
1327 |
$i_1$, $i_2$, \dots, $i_n$ are subscripts.
|
alpar@1
|
1328 |
|
alpar@1
|
1329 |
Each subscript must be a numeric or symbolic expression. The number of
|
alpar@1
|
1330 |
subscripts in the subscript list must be the same as the dimension of
|
alpar@1
|
1331 |
the set object with which the subscript list is associated.
|
alpar@1
|
1332 |
|
alpar@1
|
1333 |
Actual values of subscript expressions are used to identify a
|
alpar@1
|
1334 |
particular member of the set object that determines the resultant set.
|
alpar@1
|
1335 |
|
alpar@1
|
1336 |
\subsubsection{``Arithmetic'' sets}
|
alpar@1
|
1337 |
|
alpar@1
|
1338 |
The primary set expression, which is an ``arithmetic'' set, has the
|
alpar@1
|
1339 |
following two syntactic forms:
|
alpar@1
|
1340 |
|
alpar@1
|
1341 |
\medskip
|
alpar@1
|
1342 |
|
alpar@1
|
1343 |
\noindent\hfil
|
alpar@1
|
1344 |
$t_0$ {\tt..} $t_1$ {\tt by} $\delta t$
|
alpar@1
|
1345 |
|
alpar@1
|
1346 |
\medskip
|
alpar@1
|
1347 |
|
alpar@1
|
1348 |
\noindent\hspace{138.5pt}
|
alpar@1
|
1349 |
$t_0$ {\tt..} $t_1$
|
alpar@1
|
1350 |
|
alpar@1
|
1351 |
\medskip
|
alpar@1
|
1352 |
|
alpar@1
|
1353 |
\noindent where $t_0$, $t_1$, and $\delta t$ are numeric expressions
|
alpar@1
|
1354 |
(the value of $\delta t$ must not be zero). The second form is
|
alpar@1
|
1355 |
equivalent to the first form, where $\delta t=1$.
|
alpar@1
|
1356 |
|
alpar@1
|
1357 |
If $\delta t>0$, the resultant set is determined as follows:
|
alpar@1
|
1358 |
$$\{t:\exists k\in{\cal Z}(t=t_0+k\delta t,\ t_0\leq t\leq t_1)\}.$$
|
alpar@1
|
1359 |
Otherwise, if $\delta t<0$, the resultant set is determined as follows:
|
alpar@1
|
1360 |
$$\{t:\exists k\in{\cal Z}(t=t_0+k\delta t,\ t_1\leq t\leq t_0)\}.$$
|
alpar@1
|
1361 |
|
alpar@1
|
1362 |
\subsubsection{Indexing expressions}
|
alpar@1
|
1363 |
|
alpar@1
|
1364 |
If the primary set expression is an indexing expression, the resultant
|
alpar@1
|
1365 |
set is determined as described above in Subsection \ref{indexing}, page
|
alpar@1
|
1366 |
\pageref{indexing}.
|
alpar@1
|
1367 |
|
alpar@1
|
1368 |
\subsubsection{Iterated expressions}
|
alpar@1
|
1369 |
|
alpar@1
|
1370 |
An {\it iterated set expression} is a primary set expression, which has
|
alpar@1
|
1371 |
the following syntactic form:
|
alpar@1
|
1372 |
|
alpar@1
|
1373 |
\medskip
|
alpar@1
|
1374 |
|
alpar@1
|
1375 |
\noindent\hfil
|
alpar@1
|
1376 |
{\tt setof} {\it indexing-expression} {\it integrand}
|
alpar@1
|
1377 |
|
alpar@1
|
1378 |
\medskip
|
alpar@1
|
1379 |
|
alpar@1
|
1380 |
\noindent where {\it indexing-expression} is an indexing expression,
|
alpar@1
|
1381 |
which introduces dummy indices and controls iterating, {\it integrand}
|
alpar@1
|
1382 |
is either a single numeric or symbolic expression or a list of numeric
|
alpar@1
|
1383 |
and symbolic expressions separated by commae and enclosed in
|
alpar@1
|
1384 |
parentheses.
|
alpar@1
|
1385 |
|
alpar@1
|
1386 |
If the integrand is a single numeric or symbolic expression, the
|
alpar@1
|
1387 |
resultant set consists of 1-tuples and is determined as follows:
|
alpar@1
|
1388 |
$$\{x:(i_1,\dots,i_n)\in\Delta\},$$
|
alpar@1
|
1389 |
\noindent where $x$ is a value of the integrand, $i_1$, \dots, $i_n$
|
alpar@1
|
1390 |
are dummy indices introduced in the indexing expression, $\Delta$ is
|
alpar@1
|
1391 |
the domain, a set of $n$-tuples specified by the indexing expression,
|
alpar@1
|
1392 |
which defines particular values assigned to the dummy indices on
|
alpar@1
|
1393 |
performing the iterated operation.
|
alpar@1
|
1394 |
|
alpar@1
|
1395 |
If the integrand is a list containing $m$ numeric and symbolic
|
alpar@1
|
1396 |
expressions, the resultant set consists of $m$-tuples and is determined
|
alpar@1
|
1397 |
as follows:
|
alpar@1
|
1398 |
$$\{(x_1,\dots,x_m):(i_1,\dots,i_n)\in\Delta\},$$
|
alpar@1
|
1399 |
where $x_1$, \dots, $x_m$ are values of the expressions in the
|
alpar@1
|
1400 |
integrand list, $i_1$, \dots, $i_n$ and $\Delta$ have the same meaning
|
alpar@1
|
1401 |
as above.
|
alpar@1
|
1402 |
|
alpar@1
|
1403 |
\subsubsection{Conditional expressions}
|
alpar@1
|
1404 |
|
alpar@1
|
1405 |
A {\it conditional set expression} is a primary set expression that has
|
alpar@1
|
1406 |
the following syntactic form:
|
alpar@1
|
1407 |
|
alpar@1
|
1408 |
\medskip
|
alpar@1
|
1409 |
|
alpar@1
|
1410 |
\noindent\hfil
|
alpar@1
|
1411 |
{\tt if} $b$ {\tt then} $X$ {\tt else} $Y$
|
alpar@1
|
1412 |
|
alpar@1
|
1413 |
\medskip
|
alpar@1
|
1414 |
|
alpar@1
|
1415 |
\noindent where $b$ is an logical expression, $X$ and $Y$ are set
|
alpar@1
|
1416 |
expressions, which must define sets of the same dimension.
|
alpar@1
|
1417 |
|
alpar@1
|
1418 |
The resultant value of the conditional expression depends on the value
|
alpar@1
|
1419 |
of the logical expression that follows the keyword {\tt if}. If it
|
alpar@1
|
1420 |
takes on the value {\it true}, the resultant set is the value of the
|
alpar@1
|
1421 |
expression that follows the keyword {\tt then}. Otherwise, if the
|
alpar@1
|
1422 |
logical expression takes on the value {\it false}, the resultant set is
|
alpar@1
|
1423 |
the value of the expression that follows the keyword {\tt else}.
|
alpar@1
|
1424 |
|
alpar@1
|
1425 |
\subsubsection{Parenthesized expressions}
|
alpar@1
|
1426 |
|
alpar@1
|
1427 |
Any set expression may be enclosed in parentheses that syntactically
|
alpar@1
|
1428 |
makes it a primary set expression.
|
alpar@1
|
1429 |
|
alpar@1
|
1430 |
Parentheses may be used in set expressions, as in algebra, to specify
|
alpar@1
|
1431 |
the desired order in which operations are to be performed. Where
|
alpar@1
|
1432 |
parentheses are used, the expression within the parentheses is
|
alpar@1
|
1433 |
evaluated before the resultant value is used.
|
alpar@1
|
1434 |
|
alpar@1
|
1435 |
The resultant value of the parenthesized expression is the same as the
|
alpar@1
|
1436 |
value of the expression enclosed within parentheses.
|
alpar@1
|
1437 |
|
alpar@1
|
1438 |
\subsubsection{Set operators}
|
alpar@1
|
1439 |
|
alpar@1
|
1440 |
In MathProg there exist the following set operators, which may be used
|
alpar@1
|
1441 |
in set expressions:
|
alpar@1
|
1442 |
|
alpar@1
|
1443 |
\medskip
|
alpar@1
|
1444 |
|
alpar@1
|
1445 |
\begin{tabular}{@{}p{96pt}p{222pt}@{}}
|
alpar@1
|
1446 |
$X$ {\tt union} $Y$&union $X\cup Y$\\
|
alpar@1
|
1447 |
$X$ {\tt diff} $Y$&difference $X\backslash Y$\\
|
alpar@1
|
1448 |
$X$ {\tt symdiff} $Y$&symmetric difference $X\oplus Y$\\
|
alpar@1
|
1449 |
$X$ {\tt inter} $Y$&intersection $X\cap Y$\\
|
alpar@1
|
1450 |
$X$ {\tt cross} $Y$&cross (Cartesian) product $X\times Y$\\
|
alpar@1
|
1451 |
\end{tabular}
|
alpar@1
|
1452 |
|
alpar@1
|
1453 |
\medskip
|
alpar@1
|
1454 |
|
alpar@1
|
1455 |
\noindent where $X$ and Y are set expressions, which must define sets
|
alpar@1
|
1456 |
of the identical dimension (except the Cartesian product).
|
alpar@1
|
1457 |
|
alpar@1
|
1458 |
If the expression includes more than one set operator, all operators
|
alpar@1
|
1459 |
are performed from left to right according to the hierarchy of
|
alpar@1
|
1460 |
operations (see below).
|
alpar@1
|
1461 |
|
alpar@1
|
1462 |
The resultant value of the expression, which contains set operators, is
|
alpar@1
|
1463 |
the result of applying the operators to their operands.
|
alpar@1
|
1464 |
|
alpar@1
|
1465 |
The dimension of the resultant set, i.e. the dimension of $n$-tuples,
|
alpar@1
|
1466 |
of which the resultant set consists of, is the same as the dimension of
|
alpar@1
|
1467 |
the operands, except the Cartesian product, where the dimension of the
|
alpar@1
|
1468 |
resultant set is the sum of the dimensions of its operands.
|
alpar@1
|
1469 |
|
alpar@1
|
1470 |
\subsubsection{Hierarchy of operations}
|
alpar@1
|
1471 |
|
alpar@1
|
1472 |
The following list shows the hierarchy of operations in set
|
alpar@1
|
1473 |
expressions:
|
alpar@1
|
1474 |
|
alpar@1
|
1475 |
\medskip
|
alpar@1
|
1476 |
|
alpar@1
|
1477 |
\noindent\hfil
|
alpar@1
|
1478 |
\begin{tabular}{@{}ll@{}}
|
alpar@1
|
1479 |
Operation&Hierarchy\\
|
alpar@1
|
1480 |
\hline
|
alpar@1
|
1481 |
Evaluation of numeric operations&1st-7th\\
|
alpar@1
|
1482 |
Evaluation of symbolic operations&8th-9th\\
|
alpar@1
|
1483 |
Evaluation of iterated or ``arithmetic'' set ({\tt setof}, {\tt..})&
|
alpar@1
|
1484 |
10th\\
|
alpar@1
|
1485 |
Cartesian product ({\tt cross})&11th\\
|
alpar@1
|
1486 |
Intersection ({\tt inter})&12th\\
|
alpar@1
|
1487 |
Union and difference ({\tt union}, {\tt diff}, {\tt symdiff})&13th\\
|
alpar@1
|
1488 |
Conditional evaluation ({\tt if} \dots {\tt then} \dots {\tt else})&
|
alpar@1
|
1489 |
14th\\
|
alpar@1
|
1490 |
\end{tabular}
|
alpar@1
|
1491 |
|
alpar@1
|
1492 |
\medskip
|
alpar@1
|
1493 |
|
alpar@1
|
1494 |
This hierarchy has the same meaning as was explained above for numeric
|
alpar@1
|
1495 |
expressions (see Subsection \ref{hierarchy}, page \pageref{hierarchy}).
|
alpar@1
|
1496 |
|
alpar@1
|
1497 |
\subsection{Logical expressions}
|
alpar@1
|
1498 |
|
alpar@1
|
1499 |
A {\it logical expression} is a rule for computing a single logical
|
alpar@1
|
1500 |
value, which can be either {\it true} or {\it false}.
|
alpar@1
|
1501 |
|
alpar@1
|
1502 |
The primary logical expression may be a numeric expression, relational
|
alpar@1
|
1503 |
expression, iterated logical expression, or another logical expression
|
alpar@1
|
1504 |
enclosed in parentheses.
|
alpar@1
|
1505 |
|
alpar@1
|
1506 |
\medskip
|
alpar@1
|
1507 |
|
alpar@1
|
1508 |
\noindent{\bf Examples}
|
alpar@1
|
1509 |
|
alpar@1
|
1510 |
\medskip
|
alpar@1
|
1511 |
|
alpar@1
|
1512 |
\noindent
|
alpar@1
|
1513 |
\begin{tabular}{@{}ll@{}}
|
alpar@1
|
1514 |
\verb|i+1|&(numeric expression)\\
|
alpar@1
|
1515 |
\verb|a[i,j] < 1.5|&(relational expression)\\
|
alpar@1
|
1516 |
\verb|s[i+1,j-1] <> 'Mar'|&(relational expression)\\
|
alpar@1
|
1517 |
\verb|(i+1,'Jan') not in I cross J|&(relational expression)\\
|
alpar@1
|
1518 |
\verb|S union T within A[i] inter B[j]|&(relational expression)\\
|
alpar@1
|
1519 |
\verb|forall{i in I, j in J} a[i,j] < .5 * b|&(iterated expression)\\
|
alpar@1
|
1520 |
\verb|(a[i,j] < 1.5 or b[i] >= a[i,j])|&(parenthesized expression)\\
|
alpar@1
|
1521 |
\end{tabular}
|
alpar@1
|
1522 |
|
alpar@1
|
1523 |
\medskip
|
alpar@1
|
1524 |
|
alpar@1
|
1525 |
More general logical expressions containing two or more primary logical
|
alpar@1
|
1526 |
expressions may be constructed by using certain logical operators.
|
alpar@1
|
1527 |
|
alpar@1
|
1528 |
\newpage
|
alpar@1
|
1529 |
|
alpar@1
|
1530 |
\noindent{\bf Examples}
|
alpar@1
|
1531 |
|
alpar@1
|
1532 |
\medskip
|
alpar@1
|
1533 |
|
alpar@1
|
1534 |
\noindent\verb|not (a[i,j] < 1.5 or b[i] >= a[i,j]) and (i,j) in S|
|
alpar@1
|
1535 |
|
alpar@1
|
1536 |
\noindent\verb|(i,j) in S or (i,j) not in T diff U|
|
alpar@1
|
1537 |
|
alpar@1
|
1538 |
\subsubsection{Numeric expressions}
|
alpar@1
|
1539 |
|
alpar@1
|
1540 |
The resultant value of the primary logical expression, which is a
|
alpar@1
|
1541 |
numeric expression, is {\it true}, if the resultant value of the
|
alpar@1
|
1542 |
numeric expression is non-zero. Otherwise the resultant value of the
|
alpar@1
|
1543 |
logical expression is {\it false}.
|
alpar@1
|
1544 |
|
alpar@1
|
1545 |
\subsubsection{Relational operators}
|
alpar@1
|
1546 |
|
alpar@1
|
1547 |
In MathProg there exist the following relational operators, which may
|
alpar@1
|
1548 |
be used in logical expressions:
|
alpar@1
|
1549 |
|
alpar@1
|
1550 |
\medskip
|
alpar@1
|
1551 |
|
alpar@1
|
1552 |
\begin{tabular}{@{}ll@{}}
|
alpar@1
|
1553 |
$x$ {\tt<} $y$&test on $x<y$\\
|
alpar@1
|
1554 |
$x$ {\tt<=} $y$&test on $x\leq y$\\
|
alpar@1
|
1555 |
$x$ {\tt=} $y$, $x$ {\tt==} $y$&test on $x=y$\\
|
alpar@1
|
1556 |
$x$ {\tt>=} $y$&test on $x\geq y$\\
|
alpar@1
|
1557 |
$x$ {\tt>} $y$&test on $x>y$\\
|
alpar@1
|
1558 |
$x$ {\tt<>} $y$, $x$ {\tt!=} $y$&test on $x\neq y$\\
|
alpar@1
|
1559 |
$x$ {\tt in} $Y$&test on $x\in Y$\\
|
alpar@1
|
1560 |
{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt in} $Y$&test on
|
alpar@1
|
1561 |
$(x_1,\dots,x_n)\in Y$\\
|
alpar@1
|
1562 |
$x$ {\tt not} {\tt in} $Y$, $x$ {\tt!in} $Y$&test on $x\not\in Y$\\
|
alpar@1
|
1563 |
{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt not} {\tt in} $Y$,
|
alpar@1
|
1564 |
{\tt(}$x_1${\tt,}\dots{\tt,}$x_n${\tt)} {\tt !in} $Y$&test on
|
alpar@1
|
1565 |
$(x_1,\dots,x_n)\not\in Y$\\
|
alpar@1
|
1566 |
$X$ {\tt within} $Y$&test on $X\subseteq Y$\\
|
alpar@1
|
1567 |
$X$ {\tt not} {\tt within} $Y$, $X$ {\tt !within} $Y$&test on
|
alpar@1
|
1568 |
$X\not\subseteq Y$\\
|
alpar@1
|
1569 |
\end{tabular}
|
alpar@1
|
1570 |
|
alpar@1
|
1571 |
\medskip
|
alpar@1
|
1572 |
|
alpar@1
|
1573 |
\noindent where $x$, $x_1$, \dots, $x_n$, $y$ are numeric or symbolic
|
alpar@1
|
1574 |
expressions, $X$ and $Y$ are set expression.
|
alpar@1
|
1575 |
|
alpar@1
|
1576 |
{\it Notes:}
|
alpar@1
|
1577 |
|
alpar@1
|
1578 |
1. In the operations {\tt in}, {\tt not in}, and {\tt !in} the
|
alpar@1
|
1579 |
number of components in the first operands must be the same as the
|
alpar@1
|
1580 |
dimension of the second operand.
|
alpar@1
|
1581 |
|
alpar@1
|
1582 |
2. In the operations {\tt within}, {\tt not within}, and {\tt !within}
|
alpar@1
|
1583 |
both operands must have identical dimension.
|
alpar@1
|
1584 |
|
alpar@1
|
1585 |
All the relational operators listed above have their conventional
|
alpar@1
|
1586 |
mathematical meaning. The resultant value is {\it true}, if
|
alpar@1
|
1587 |
corresponding relation is satisfied for its operands, otherwise
|
alpar@1
|
1588 |
{\it false}. (Note that symbolic values are ordered lexicographically,
|
alpar@1
|
1589 |
and any numeric value precedes any symbolic value.)
|
alpar@1
|
1590 |
|
alpar@1
|
1591 |
\subsubsection{Iterated expressions}
|
alpar@1
|
1592 |
|
alpar@1
|
1593 |
An {\it iterated logical expression} is a primary logical expression,
|
alpar@1
|
1594 |
which has the following syntactic form:
|
alpar@1
|
1595 |
|
alpar@1
|
1596 |
\medskip
|
alpar@1
|
1597 |
|
alpar@1
|
1598 |
\noindent\hfil
|
alpar@1
|
1599 |
{\it iterated-operator} {\it indexing-expression} {\it integrand}
|
alpar@1
|
1600 |
|
alpar@1
|
1601 |
\medskip
|
alpar@1
|
1602 |
|
alpar@1
|
1603 |
\noindent where {\it iterated-operator} is the symbolic name of the
|
alpar@1
|
1604 |
iterated operator to be performed (see below), {\it indexing-expression}
|
alpar@1
|
1605 |
is an indexing expression which introduces dummy indices and controls
|
alpar@1
|
1606 |
iterating, {\it integrand} is a numeric expression that participates in
|
alpar@1
|
1607 |
the operation.
|
alpar@1
|
1608 |
|
alpar@1
|
1609 |
In MathProg there exist two iterated operators, which may be used in
|
alpar@1
|
1610 |
logical expressions:
|
alpar@1
|
1611 |
|
alpar@1
|
1612 |
\medskip
|
alpar@1
|
1613 |
|
alpar@1
|
1614 |
\noindent\hfil
|
alpar@1
|
1615 |
\begin{tabular}{@{}lll@{}}
|
alpar@1
|
1616 |
{\tt forall}&$\forall$-quantification&$\displaystyle
|
alpar@1
|
1617 |
\forall(i_1,\dots,i_n)\in\Delta[f(i_1,\dots,i_n)],$\\
|
alpar@1
|
1618 |
{\tt exists}&$\exists$-quantification&$\displaystyle
|
alpar@1
|
1619 |
\exists(i_1,\dots,i_n)\in\Delta[f(i_1,\dots,i_n)],$\\
|
alpar@1
|
1620 |
\end{tabular}
|
alpar@1
|
1621 |
|
alpar@1
|
1622 |
\medskip
|
alpar@1
|
1623 |
|
alpar@1
|
1624 |
\noindent where $i_1$, \dots, $i_n$ are dummy indices introduced in
|
alpar@1
|
1625 |
the indexing expression, $\Delta$ is the domain, a set of $n$-tuples
|
alpar@1
|
1626 |
specified by the indexing expression which defines particular values
|
alpar@1
|
1627 |
assigned to the dummy indices on performing the iterated operation,
|
alpar@1
|
1628 |
$f(i_1,\dots,i_n)$ is the integrand, a logical expression whose
|
alpar@1
|
1629 |
resultant value depends on the dummy indices.
|
alpar@1
|
1630 |
|
alpar@1
|
1631 |
For $\forall$-quantification the resultant value of the iterated
|
alpar@1
|
1632 |
logical expression is {\it true}, if the value of the integrand is
|
alpar@1
|
1633 |
{\it true} for all $n$-tuples contained in the domain, otherwise
|
alpar@1
|
1634 |
{\it false}.
|
alpar@1
|
1635 |
|
alpar@1
|
1636 |
For $\exists$-quantification the resultant value of the iterated
|
alpar@1
|
1637 |
logical expression is {\it false}, if the value of the integrand is
|
alpar@1
|
1638 |
{\it false} for all $n$-tuples contained in the domain, otherwise
|
alpar@1
|
1639 |
{\it true}.
|
alpar@1
|
1640 |
|
alpar@1
|
1641 |
\subsubsection{Parenthesized expressions}
|
alpar@1
|
1642 |
|
alpar@1
|
1643 |
Any logical expression may be enclosed in parentheses that
|
alpar@1
|
1644 |
syntactically makes it a primary logical expression.
|
alpar@1
|
1645 |
|
alpar@1
|
1646 |
Parentheses may be used in logical expressions, as in algebra, to
|
alpar@1
|
1647 |
specify the desired order in which operations are to be performed.
|
alpar@1
|
1648 |
Where parentheses are used, the expression within the parentheses is
|
alpar@1
|
1649 |
evaluated before the resultant value is used.
|
alpar@1
|
1650 |
|
alpar@1
|
1651 |
The resultant value of the parenthesized expression is the same as the
|
alpar@1
|
1652 |
value of the expression enclosed within parentheses.
|
alpar@1
|
1653 |
|
alpar@1
|
1654 |
\subsubsection{Logical operators}
|
alpar@1
|
1655 |
|
alpar@1
|
1656 |
In MathProg there exist the following logical operators, which may be
|
alpar@1
|
1657 |
used in logical expressions:
|
alpar@1
|
1658 |
|
alpar@1
|
1659 |
\medskip
|
alpar@1
|
1660 |
|
alpar@1
|
1661 |
\begin{tabular}{@{}p{96pt}p{222pt}@{}}
|
alpar@1
|
1662 |
{\tt not} $x$, {\tt!}$x$&negation $\neg\ x$\\
|
alpar@1
|
1663 |
$x$ {\tt and} $y$, $x$ {\tt\&\&} $y$&conjunction (logical ``and'')
|
alpar@1
|
1664 |
$x\;\&\;y$\\
|
alpar@1
|
1665 |
$x$ {\tt or} $y$, $x$ {\tt||} $y$&disjunction (logical ``or'')
|
alpar@1
|
1666 |
$x\vee y$\\
|
alpar@1
|
1667 |
\end{tabular}
|
alpar@1
|
1668 |
|
alpar@1
|
1669 |
\medskip
|
alpar@1
|
1670 |
|
alpar@1
|
1671 |
\noindent where $x$ and $y$ are logical expressions.
|
alpar@1
|
1672 |
|
alpar@1
|
1673 |
If the expression includes more than one logical operator, all
|
alpar@1
|
1674 |
operators are performed from left to right according to the hierarchy
|
alpar@1
|
1675 |
of the operations (see below). The resultant value of the expression,
|
alpar@1
|
1676 |
which contains logical operators, is the result of applying the
|
alpar@1
|
1677 |
operators to their operands.
|
alpar@1
|
1678 |
|
alpar@1
|
1679 |
\subsubsection{Hierarchy of operations}
|
alpar@1
|
1680 |
|
alpar@1
|
1681 |
The following list shows the hierarchy of operations in logical
|
alpar@1
|
1682 |
expressions:
|
alpar@1
|
1683 |
|
alpar@1
|
1684 |
\medskip
|
alpar@1
|
1685 |
|
alpar@1
|
1686 |
\noindent\hfil
|
alpar@1
|
1687 |
\begin{tabular}{@{}ll@{}}
|
alpar@1
|
1688 |
Operation&Hierarchy\\
|
alpar@1
|
1689 |
\hline
|
alpar@1
|
1690 |
Evaluation of numeric operations&1st-7th\\
|
alpar@1
|
1691 |
Evaluation of symbolic operations&8th-9th\\
|
alpar@1
|
1692 |
Evaluation of set operations&10th-14th\\
|
alpar@1
|
1693 |
Relational operations ({\tt<}, {\tt<=}, etc.)&15th\\
|
alpar@1
|
1694 |
Negation ({\tt not}, {\tt!})&16th\\
|
alpar@1
|
1695 |
Conjunction ({\tt and}, {\tt\&\&})&17th\\
|
alpar@1
|
1696 |
$\forall$- and $\exists$-quantification ({\tt forall}, {\tt exists})&
|
alpar@1
|
1697 |
18th\\
|
alpar@1
|
1698 |
Disjunction ({\tt or}, {\tt||})&19th\\
|
alpar@1
|
1699 |
\end{tabular}
|
alpar@1
|
1700 |
|
alpar@1
|
1701 |
\medskip
|
alpar@1
|
1702 |
|
alpar@1
|
1703 |
This hierarchy has the same meaning as was explained above for numeric
|
alpar@1
|
1704 |
expressions (see Subsection \ref{hierarchy}, page \pageref{hierarchy}).
|
alpar@1
|
1705 |
|
alpar@1
|
1706 |
\subsection{Linear expressions}
|
alpar@1
|
1707 |
|
alpar@1
|
1708 |
An {\it linear expression} is a rule for computing so called
|
alpar@1
|
1709 |
a {\it linear form} or simply a {\it formula}, which is a linear (or
|
alpar@1
|
1710 |
affine) function of elemental variables.
|
alpar@1
|
1711 |
|
alpar@1
|
1712 |
The primary linear expression may be an unsubscripted variable,
|
alpar@1
|
1713 |
subscripted variable, iterated linear expression, conditional linear
|
alpar@1
|
1714 |
expression, or another linear expression enclosed in parentheses.
|
alpar@1
|
1715 |
|
alpar@1
|
1716 |
It is also allowed to use a numeric expression as the primary linear
|
alpar@1
|
1717 |
expression, in which case the resultant value of the numeric expression
|
alpar@1
|
1718 |
is automatically converted to a formula that includes the constant term
|
alpar@1
|
1719 |
only.
|
alpar@1
|
1720 |
|
alpar@1
|
1721 |
\medskip
|
alpar@1
|
1722 |
|
alpar@1
|
1723 |
\noindent{\bf Examples}
|
alpar@1
|
1724 |
|
alpar@1
|
1725 |
\medskip
|
alpar@1
|
1726 |
|
alpar@1
|
1727 |
\noindent
|
alpar@1
|
1728 |
\begin{tabular}{@{}ll@{}}
|
alpar@1
|
1729 |
\verb|z|&(unsubscripted variable)\\
|
alpar@1
|
1730 |
\verb|x[i,j]|&(subscripted variable)\\
|
alpar@1
|
1731 |
\verb|sum{j in J} (a[i] * x[i,j] + 3 * y)|&(iterated expression)\\
|
alpar@1
|
1732 |
\verb|if i in I then x[i,j] else 1.5 * z + 3|&(conditional expression)\\
|
alpar@1
|
1733 |
\verb|(a[i,j] * x[i,j] + y[i-1] + .1)|&(parenthesized expression)\\
|
alpar@1
|
1734 |
\end{tabular}
|
alpar@1
|
1735 |
|
alpar@1
|
1736 |
\medskip
|
alpar@1
|
1737 |
|
alpar@1
|
1738 |
More general linear expressions containing two or more primary linear
|
alpar@1
|
1739 |
expressions may be constructed by using certain arithmetic operators.
|
alpar@1
|
1740 |
|
alpar@1
|
1741 |
\medskip
|
alpar@1
|
1742 |
|
alpar@1
|
1743 |
\noindent{\bf Examples}
|
alpar@1
|
1744 |
|
alpar@1
|
1745 |
\medskip
|
alpar@1
|
1746 |
|
alpar@1
|
1747 |
\noindent\verb|2 * x[i-1,j+1] + 3.5 * y[k] + .5 * z|
|
alpar@1
|
1748 |
|
alpar@1
|
1749 |
\noindent\verb|(- x[i,j] + 3.5 * y[k]) / sum{t in T} abs(d[i,j,t])|
|
alpar@1
|
1750 |
|
alpar@1
|
1751 |
\subsubsection{Unsubscripted variables}
|
alpar@1
|
1752 |
|
alpar@1
|
1753 |
If the primary linear expression is an unsubscripted variable (which
|
alpar@1
|
1754 |
must be 0-dimensional), the resultant formula is that unsubscripted
|
alpar@1
|
1755 |
variable.
|
alpar@1
|
1756 |
|
alpar@1
|
1757 |
\subsubsection{Subscripted variables}
|
alpar@1
|
1758 |
|
alpar@1
|
1759 |
The primary linear expression, which refers to a subscripted variable,
|
alpar@1
|
1760 |
has the following syntactic form:
|
alpar@1
|
1761 |
|
alpar@1
|
1762 |
\medskip
|
alpar@1
|
1763 |
|
alpar@1
|
1764 |
\noindent\hfil
|
alpar@1
|
1765 |
{\it name}{\tt[}$i_1${\tt,} $i_2${\tt,} \dots{\tt,} $i_n${\tt]}
|
alpar@1
|
1766 |
|
alpar@1
|
1767 |
\medskip
|
alpar@1
|
1768 |
|
alpar@1
|
1769 |
\noindent where {\it name} is the symbolic name of the model variable,
|
alpar@1
|
1770 |
$i_1$, $i_2$, \dots, $i_n$ are subscripts.
|
alpar@1
|
1771 |
|
alpar@1
|
1772 |
Each subscript must be a numeric or symbolic expression. The number of
|
alpar@1
|
1773 |
subscripts in the subscript list must be the same as the dimension of
|
alpar@1
|
1774 |
the model variable with which the subscript list is associated.
|
alpar@1
|
1775 |
|
alpar@1
|
1776 |
Actual values of the subscript expressions are used to identify a
|
alpar@1
|
1777 |
particular member of the model variable that determines the resultant
|
alpar@1
|
1778 |
formula, which is an elemental variable associated with corresponding
|
alpar@1
|
1779 |
member.
|
alpar@1
|
1780 |
|
alpar@1
|
1781 |
\subsubsection{Iterated expressions}
|
alpar@1
|
1782 |
|
alpar@1
|
1783 |
An {\it iterated linear expression} is a primary linear expression,
|
alpar@1
|
1784 |
which has the following syntactic form:
|
alpar@1
|
1785 |
|
alpar@1
|
1786 |
\medskip
|
alpar@1
|
1787 |
|
alpar@1
|
1788 |
\noindent\hfil
|
alpar@1
|
1789 |
{\tt sum} {\it indexing-expression} {\it integrand}
|
alpar@1
|
1790 |
|
alpar@1
|
1791 |
\medskip
|
alpar@1
|
1792 |
|
alpar@1
|
1793 |
\noindent where {\it indexing-expression} is an indexing expression,
|
alpar@1
|
1794 |
which introduces dummy indices and controls iterating, {\it integrand}
|
alpar@1
|
1795 |
is a linear expression that participates in the operation.
|
alpar@1
|
1796 |
|
alpar@1
|
1797 |
The iterated linear expression is evaluated exactly in the same way as
|
alpar@1
|
1798 |
the iterated numeric expression (see Subection \ref{itexpr}, page
|
alpar@1
|
1799 |
\pageref{itexpr}) with exception that the integrand participated in the
|
alpar@1
|
1800 |
summation is a formula, not a numeric value.
|
alpar@1
|
1801 |
|
alpar@1
|
1802 |
\subsubsection{Conditional expressions}
|
alpar@1
|
1803 |
|
alpar@1
|
1804 |
A {\it conditional linear expression} is a primary linear expression,
|
alpar@1
|
1805 |
which has one of the following two syntactic forms:
|
alpar@1
|
1806 |
|
alpar@1
|
1807 |
\medskip
|
alpar@1
|
1808 |
|
alpar@1
|
1809 |
\noindent\hfil
|
alpar@1
|
1810 |
{\tt if} $b$ {\tt then} $f$ {\tt else} $g$
|
alpar@1
|
1811 |
|
alpar@1
|
1812 |
\medskip
|
alpar@1
|
1813 |
|
alpar@1
|
1814 |
\noindent\hspace{127pt}
|
alpar@1
|
1815 |
{\tt if} $b$ {\tt then} $f$
|
alpar@1
|
1816 |
|
alpar@1
|
1817 |
\medskip
|
alpar@1
|
1818 |
|
alpar@1
|
1819 |
\noindent where $b$ is an logical expression, $f$ and $g$ are linear
|
alpar@1
|
1820 |
expressions.
|
alpar@1
|
1821 |
|
alpar@1
|
1822 |
The conditional linear expression is evaluated exactly in the same way
|
alpar@1
|
1823 |
as the conditional numeric expression (see Subsection \ref{ifthen},
|
alpar@1
|
1824 |
page \pageref{ifthen}) with exception that operands participated in the
|
alpar@1
|
1825 |
operation are formulae, not numeric values.
|
alpar@1
|
1826 |
|
alpar@1
|
1827 |
\subsubsection{Parenthesized expressions}
|
alpar@1
|
1828 |
|
alpar@1
|
1829 |
Any linear expression may be enclosed in parentheses that syntactically
|
alpar@1
|
1830 |
makes it a primary linear expression.
|
alpar@1
|
1831 |
|
alpar@1
|
1832 |
Parentheses may be used in linear expressions, as in algebra, to
|
alpar@1
|
1833 |
specify the desired order in which operations are to be performed.
|
alpar@1
|
1834 |
Where parentheses are used, the expression within the parentheses is
|
alpar@1
|
1835 |
evaluated before the resultant formula is used.
|
alpar@1
|
1836 |
|
alpar@1
|
1837 |
The resultant value of the parenthesized expression is the same as the
|
alpar@1
|
1838 |
value of the expression enclosed within parentheses.
|
alpar@1
|
1839 |
|
alpar@1
|
1840 |
\subsubsection{Arithmetic operators}
|
alpar@1
|
1841 |
|
alpar@1
|
1842 |
In MathProg there exists the following arithmetic operators, which may
|
alpar@1
|
1843 |
be used in linear expressions:
|
alpar@1
|
1844 |
|
alpar@1
|
1845 |
\medskip
|
alpar@1
|
1846 |
|
alpar@1
|
1847 |
\begin{tabular}{@{}p{96pt}p{222pt}@{}}
|
alpar@1
|
1848 |
{\tt+} $f$&unary plus\\
|
alpar@1
|
1849 |
{\tt-} $f$&unary minus\\
|
alpar@1
|
1850 |
$f$ {\tt+} $g$&addition\\
|
alpar@1
|
1851 |
$f$ {\tt-} $g$&subtraction\\
|
alpar@1
|
1852 |
$x$ {\tt*} $f$, $f$ {\tt*} $x$&multiplication\\
|
alpar@1
|
1853 |
$f$ {\tt/} $x$&division
|
alpar@1
|
1854 |
\end{tabular}
|
alpar@1
|
1855 |
|
alpar@1
|
1856 |
\medskip
|
alpar@1
|
1857 |
|
alpar@1
|
1858 |
\noindent where $f$ and $g$ are linear expressions, $x$ is a numeric
|
alpar@1
|
1859 |
expression (more precisely, a linear expression containing only the
|
alpar@1
|
1860 |
constant term).
|
alpar@1
|
1861 |
|
alpar@1
|
1862 |
If the expression includes more than one arithmetic operator, all
|
alpar@1
|
1863 |
operators are performed from left to right according to the hierarchy
|
alpar@1
|
1864 |
of operations (see below). The resultant value of the expression, which
|
alpar@1
|
1865 |
contains arithmetic operators, is the result of applying the operators
|
alpar@1
|
1866 |
to their operands.
|
alpar@1
|
1867 |
|
alpar@1
|
1868 |
\subsubsection{Hierarchy of operations}
|
alpar@1
|
1869 |
|
alpar@1
|
1870 |
The hierarchy of arithmetic operations used in linear expressions is
|
alpar@1
|
1871 |
the same as for numeric expressions (see Subsection \ref{hierarchy},
|
alpar@1
|
1872 |
page \pageref{hierarchy}).
|
alpar@1
|
1873 |
|
alpar@1
|
1874 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
alpar@1
|
1875 |
|
alpar@1
|
1876 |
\newpage
|
alpar@1
|
1877 |
|
alpar@1
|
1878 |
\section{Statements}
|
alpar@1
|
1879 |
|
alpar@1
|
1880 |
{\it Statements} are basic units of the model description. In MathProg
|
alpar@1
|
1881 |
all statements are divided into two categories: declaration statements
|
alpar@1
|
1882 |
and functional statements.
|
alpar@1
|
1883 |
|
alpar@1
|
1884 |
{\it Declaration statements} (set statement, parameter statement,
|
alpar@1
|
1885 |
variable statement, constraint statement, and objective statement) are
|
alpar@1
|
1886 |
used to declare model objects of certain kinds and define certain
|
alpar@1
|
1887 |
properties of such objects.
|
alpar@1
|
1888 |
|
alpar@1
|
1889 |
{\it Functional statements} (solve statement, check statement, display
|
alpar@1
|
1890 |
statement, printf statement, loop statement) are intended for
|
alpar@1
|
1891 |
performing some specific actions.
|
alpar@1
|
1892 |
|
alpar@1
|
1893 |
Note that declaration statements may follow in arbitrary order, which
|
alpar@1
|
1894 |
does not affect the result of translation. However, any model object
|
alpar@1
|
1895 |
must be declared before it is referenced in other statements.
|
alpar@1
|
1896 |
|
alpar@1
|
1897 |
\subsection{Set statement}
|
alpar@1
|
1898 |
|
alpar@1
|
1899 |
\medskip
|
alpar@1
|
1900 |
|
alpar@1
|
1901 |
\framebox[345pt][l]{
|
alpar@1
|
1902 |
\parbox[c][24pt]{345pt}{
|
alpar@1
|
1903 |
\hspace{6pt} {\tt set} {\it name} {\it alias} {\it domain} {\tt,}
|
alpar@1
|
1904 |
{\it attrib} {\tt,} \dots {\tt,} {\it attrib} {\tt;}
|
alpar@1
|
1905 |
}}
|
alpar@1
|
1906 |
|
alpar@1
|
1907 |
\setlength{\leftmargini}{60pt}
|
alpar@1
|
1908 |
|
alpar@1
|
1909 |
\begin{description}
|
alpar@1
|
1910 |
\item[{\rm Where:}\hspace*{23pt}] {\it name} is a symbolic name of the
|
alpar@1
|
1911 |
set;
|
alpar@1
|
1912 |
\item[\hspace*{54pt}] {\it alias} is an optional string literal, which
|
alpar@1
|
1913 |
specifies an alias of the set;
|
alpar@1
|
1914 |
\item[\hspace*{54pt}] {\it domain} is an optional indexing expression,
|
alpar@1
|
1915 |
which specifies a subscript domain of the set;
|
alpar@1
|
1916 |
\item[\hspace*{54pt}] {\it attrib}, \dots, {\it attrib} are optional
|
alpar@1
|
1917 |
attributes of the set. (Commae preceding attributes may be omitted.)
|
alpar@1
|
1918 |
\end{description}
|
alpar@1
|
1919 |
|
alpar@1
|
1920 |
\noindent Optional attributes:
|
alpar@1
|
1921 |
|
alpar@1
|
1922 |
\begin{description}
|
alpar@1
|
1923 |
\item[{\tt dimen} $n$\hspace*{19pt}] specifies the dimension of
|
alpar@1
|
1924 |
$n$-tuples, which the set consists of;
|
alpar@1
|
1925 |
\item[{\tt within} {\it expression}]\hspace*{0pt}\\
|
alpar@1
|
1926 |
specifies a superset which restricts the set or all its members
|
alpar@1
|
1927 |
(elemental sets) to be within that superset;
|
alpar@1
|
1928 |
\item[{\tt:=} {\it expression}]\hspace*{0pt}\\
|
alpar@1
|
1929 |
specifies an elemental set assigned to the set or its members;
|
alpar@1
|
1930 |
\item[{\tt default} {\it expression}]\hspace*{0pt}\\
|
alpar@1
|
1931 |
specifies an elemental set assigned to the set or its members whenever
|
alpar@1
|
1932 |
no appropriate data are available in the data section.
|
alpar@1
|
1933 |
\end{description}
|
alpar@1
|
1934 |
|
alpar@1
|
1935 |
\newpage
|
alpar@1
|
1936 |
|
alpar@1
|
1937 |
\noindent{\bf Examples}
|
alpar@1
|
1938 |
|
alpar@1
|
1939 |
\begin{verbatim}
|
alpar@1
|
1940 |
set V;
|
alpar@1
|
1941 |
set E within V cross V;
|
alpar@1
|
1942 |
set step{s in 1..maxiter} dimen 2 := if s = 1 then E else
|
alpar@1
|
1943 |
step[s-1] union setof{k in V, (i,k) in step[s-1], (k,j)
|
alpar@1
|
1944 |
in step[s-1]}(i,j);
|
alpar@1
|
1945 |
set A{i in I, j in J}, within B[i+1] cross C[j-1], within
|
alpar@1
|
1946 |
D diff E, default {('abc',123), (321,'cba')};
|
alpar@1
|
1947 |
\end{verbatim}
|
alpar@1
|
1948 |
|
alpar@1
|
1949 |
The set statement declares a set. If the subscript domain is not
|
alpar@1
|
1950 |
specified, the set is a simple set, otherwise it is an array of
|
alpar@1
|
1951 |
elemental sets.
|
alpar@1
|
1952 |
|
alpar@1
|
1953 |
The {\tt dimen} attribute specifies the dimension of $n$-tuples, which
|
alpar@1
|
1954 |
the set (if it is a simple set) or its members (if the set is an array
|
alpar@1
|
1955 |
of elemental sets) consist of, where $n$ must be unsigned integer from
|
alpar@1
|
1956 |
1 to 20. At most one {\tt dimen} attribute can be specified. If the
|
alpar@1
|
1957 |
{\tt dimen} attribute is not specified, the dimension of\linebreak
|
alpar@1
|
1958 |
$n$-tuples is implicitly determined by other attributes (for example,
|
alpar@1
|
1959 |
if there is a set expression that follows {\tt:=} or the keyword
|
alpar@1
|
1960 |
{\tt default}, the dimension of $n$-tuples of corresponding elemental
|
alpar@1
|
1961 |
set is used). If no dimension information is available, {\tt dimen 1}
|
alpar@1
|
1962 |
is assumed.
|
alpar@1
|
1963 |
|
alpar@1
|
1964 |
The {\tt within} attribute specifies a set expression whose resultant
|
alpar@1
|
1965 |
value is a superset used to restrict the set (if it is a simple set) or
|
alpar@1
|
1966 |
its members (if the set is an array of elemental sets) to be within
|
alpar@1
|
1967 |
that superset. Arbitrary number of {\tt within} attributes may be
|
alpar@1
|
1968 |
specified in the same set statement.
|
alpar@1
|
1969 |
|
alpar@1
|
1970 |
The assign ({\tt:=}) attribute specifies a set expression used to
|
alpar@1
|
1971 |
evaluate elemental set(s) assigned to the set (if it is a simple set)
|
alpar@1
|
1972 |
or its members (if the set is an array of elemental sets). If the
|
alpar@1
|
1973 |
assign attribute is specified, the set is {\it computable} and
|
alpar@1
|
1974 |
therefore needs no data to be provided in the data section. If the
|
alpar@1
|
1975 |
assign attribute is not specified, the set must be provided with data
|
alpar@1
|
1976 |
in the data section. At most one assign or default attribute can be
|
alpar@1
|
1977 |
specified for the same set.
|
alpar@1
|
1978 |
|
alpar@1
|
1979 |
The {\tt default} attribute specifies a set expression used to evaluate
|
alpar@1
|
1980 |
elemental set(s) assigned to the set (if it is a simple set) or its
|
alpar@1
|
1981 |
members (if the set is an array of elemental sets) whenever
|
alpar@1
|
1982 |
no appropriate data are available in the data section. If neither
|
alpar@1
|
1983 |
assign nor default attribute is specified, missing data will cause an
|
alpar@1
|
1984 |
error.
|
alpar@1
|
1985 |
|
alpar@1
|
1986 |
\subsection{Parameter statement}
|
alpar@1
|
1987 |
|
alpar@1
|
1988 |
\medskip
|
alpar@1
|
1989 |
|
alpar@1
|
1990 |
\framebox[345pt][l]{
|
alpar@1
|
1991 |
\parbox[c][24pt]{345pt}{
|
alpar@1
|
1992 |
\hspace{6pt} {\tt param} {\it name} {\it alias} {\it domain} {\tt,}
|
alpar@1
|
1993 |
{\it attrib} {\tt,} \dots {\tt,} {\it attrib} {\tt;}
|
alpar@1
|
1994 |
}}
|
alpar@1
|
1995 |
|
alpar@1
|
1996 |
\setlength{\leftmargini}{60pt}
|
alpar@1
|
1997 |
|
alpar@1
|
1998 |
\begin{description}
|
alpar@1
|
1999 |
\item[{\rm Where:}\hspace*{23pt}] {\it name} is a symbolic name of the
|
alpar@1
|
2000 |
parameter;
|
alpar@1
|
2001 |
\item[\hspace*{54pt}] {\it alias} is an optional string literal, which
|
alpar@1
|
2002 |
specifies an alias of the parameter;
|
alpar@1
|
2003 |
\item[\hspace*{54pt}] {\it domain} is an optional indexing expression,
|
alpar@1
|
2004 |
which specifies a subscript domain of the parameter;
|
alpar@1
|
2005 |
\item[\hspace*{54pt}] {\it attrib}, \dots, {\it attrib} are optional
|
alpar@1
|
2006 |
attributes of the parameter. (Commae preceding attributes may be
|
alpar@1
|
2007 |
omitted.)
|
alpar@1
|
2008 |
\end{description}
|
alpar@1
|
2009 |
|
alpar@1
|
2010 |
\noindent Optional attributes:
|
alpar@1
|
2011 |
|
alpar@1
|
2012 |
\begin{description}
|
alpar@1
|
2013 |
\item[{\tt integer}\hspace*{18.5pt}] specifies that the parameter is
|
alpar@1
|
2014 |
integer;
|
alpar@1
|
2015 |
\item[{\tt binary}\hspace*{24pt}] specifies that the parameter is
|
alpar@1
|
2016 |
binary;
|
alpar@1
|
2017 |
\item[{\tt symbolic}\hspace*{13.5pt}] specifies that the parameter is
|
alpar@1
|
2018 |
symbolic;
|
alpar@1
|
2019 |
\item[{\it relation expression}]\hspace*{0pt}\\
|
alpar@1
|
2020 |
(where {\it relation} is one of: {\tt<}, {\tt<=}, {\tt=}, {\tt==},
|
alpar@1
|
2021 |
{\tt>=}, {\tt>}, {\tt<>}, {\tt!=})\\
|
alpar@1
|
2022 |
specifies a condition that restricts the parameter or its members to
|
alpar@1
|
2023 |
satisfy that condition;
|
alpar@1
|
2024 |
\item[{\tt in} {\it expression}]\hspace*{0pt}\\
|
alpar@1
|
2025 |
specifies a superset that restricts the parameter or its members to be
|
alpar@1
|
2026 |
in that superset;
|
alpar@1
|
2027 |
\item[{\tt:=} {\it expression}]\hspace*{0pt}\\
|
alpar@1
|
2028 |
specifies a value assigned to the parameter or its members;
|
alpar@1
|
2029 |
\item[{\tt default} {\it expression}]\hspace*{0pt}\\
|
alpar@1
|
2030 |
specifies a value assigned to the parameter or its members whenever
|
alpar@1
|
2031 |
no appropriate data are available in the data section.
|
alpar@1
|
2032 |
\end{description}
|
alpar@1
|
2033 |
|
alpar@1
|
2034 |
\noindent{\bf Examples}
|
alpar@1
|
2035 |
|
alpar@1
|
2036 |
\begin{verbatim}
|
alpar@1
|
2037 |
param units{raw, prd} >= 0;
|
alpar@1
|
2038 |
param profit{prd, 1..T+1};
|
alpar@1
|
2039 |
param N := 20, integer, >= 0, <= 100;
|
alpar@1
|
2040 |
param comb 'n choose k' {n in 0..N, k in 0..n} :=
|
alpar@1
|
2041 |
if k = 0 or k = n then 1 else comb[n-1,k-1] + comb[n-1,k];
|
alpar@1
|
2042 |
param p{i in I, j in J}, integer, >= 0, <= i+j,
|
alpar@1
|
2043 |
in A[i] symdiff B[j], in C[i,j], default 0.5 * (i + j);
|
alpar@1
|
2044 |
param month symbolic default 'May' in {'Mar', 'Apr', 'May'};
|
alpar@1
|
2045 |
\end{verbatim}
|
alpar@1
|
2046 |
|
alpar@1
|
2047 |
The parameter statement declares a parameter. If a subscript domain is
|
alpar@1
|
2048 |
not specified, the parameter is a simple (scalar) parameter, otherwise
|
alpar@1
|
2049 |
it is a $n$-dimensional array.
|
alpar@1
|
2050 |
|
alpar@1
|
2051 |
The type attributes {\tt integer}, {\tt binary}, and {\tt symbolic}
|
alpar@1
|
2052 |
qualify the type of values that can be assigned to the parameter as
|
alpar@1
|
2053 |
shown below:
|
alpar@1
|
2054 |
|
alpar@1
|
2055 |
\medskip
|
alpar@1
|
2056 |
|
alpar@1
|
2057 |
\noindent\hfil
|
alpar@1
|
2058 |
\begin{tabular}{@{}ll@{}}
|
alpar@1
|
2059 |
Type attribute&Assigned values\\
|
alpar@1
|
2060 |
\hline
|
alpar@1
|
2061 |
(not specified)&Any numeric values\\
|
alpar@1
|
2062 |
{\tt integer}&Only integer numeric values\\
|
alpar@1
|
2063 |
{\tt binary}&Either 0 or 1\\
|
alpar@1
|
2064 |
{\tt symbolic}&Any numeric and symbolic values\\
|
alpar@1
|
2065 |
\end{tabular}
|
alpar@1
|
2066 |
|
alpar@1
|
2067 |
\newpage
|
alpar@1
|
2068 |
|
alpar@1
|
2069 |
The {\tt symbolic} attribute cannot be specified along with other type
|
alpar@1
|
2070 |
attributes. Being specified it must precede all other attributes.
|
alpar@1
|
2071 |
|
alpar@1
|
2072 |
The condition attribute specifies an optional condition that restricts
|
alpar@1
|
2073 |
values assigned to the parameter to satisfy that condition. This
|
alpar@1
|
2074 |
attribute has the following syntactic forms:
|
alpar@1
|
2075 |
|
alpar@1
|
2076 |
\medskip
|
alpar@1
|
2077 |
|
alpar@1
|
2078 |
\begin{tabular}{@{}ll@{}}
|
alpar@1
|
2079 |
{\tt<} $v$&check for $x<v$\\
|
alpar@1
|
2080 |
{\tt<=} $v$&check for $x\leq v$\\
|
alpar@1
|
2081 |
{\tt=} $v$, {\tt==} $v$&check for $x=v$\\
|
alpar@1
|
2082 |
{\tt>=} $v$&check for $x\geq v$\\
|
alpar@1
|
2083 |
{\tt>} $v$&check for $x\geq v$\\
|
alpar@1
|
2084 |
{\tt<>} $v$, {\tt!=} $v$&check for $x\neq v$\\
|
alpar@1
|
2085 |
\end{tabular}
|
alpar@1
|
2086 |
|
alpar@1
|
2087 |
\medskip
|
alpar@1
|
2088 |
|
alpar@1
|
2089 |
\noindent where $x$ is a value assigned to the parameter, $v$ is the
|
alpar@1
|
2090 |
resultant value of a numeric or symbolic expression specified in the
|
alpar@1
|
2091 |
condition attribute. Arbitrary number of condition attributes can be
|
alpar@1
|
2092 |
specified for the same parameter. If a value being assigned to the
|
alpar@1
|
2093 |
parameter during model evaluation violates at least one of specified
|
alpar@1
|
2094 |
conditions, an error is raised. (Note that symbolic values are ordered
|
alpar@1
|
2095 |
lexicographically, and any numeric value precedes any symbolic value.)
|
alpar@1
|
2096 |
|
alpar@1
|
2097 |
The {\tt in} attribute is similar to the condition attribute and
|
alpar@1
|
2098 |
specifies a set expression whose resultant value is a superset used to
|
alpar@1
|
2099 |
restrict numeric or symbolic values assigned to the parameter to be in
|
alpar@1
|
2100 |
that superset. Arbitrary number of the {\tt in} attributes can be
|
alpar@1
|
2101 |
specified for the same parameter. If a value being assigned to the
|
alpar@1
|
2102 |
parameter during model evaluation is not in at least one of specified
|
alpar@1
|
2103 |
supersets, an error is raised.
|
alpar@1
|
2104 |
|
alpar@1
|
2105 |
The assign ({\tt:=}) attribute specifies a numeric or symbolic
|
alpar@1
|
2106 |
expression used to compute a value assigned to the parameter (if it is
|
alpar@1
|
2107 |
a simple parameter) or its member (if the parameter is an array). If
|
alpar@1
|
2108 |
the assign attribute is specified, the parameter is {\it computable}
|
alpar@1
|
2109 |
and therefore needs no data to be provided in the data section. If the
|
alpar@1
|
2110 |
assign attribute is not specified, the parameter must be provided with
|
alpar@1
|
2111 |
data in the data section. At most one assign or {\tt default} attribute
|
alpar@1
|
2112 |
can be specified for the same parameter.
|
alpar@1
|
2113 |
|
alpar@1
|
2114 |
The {\tt default} attribute specifies a numeric or symbolic expression
|
alpar@1
|
2115 |
used to compute a value assigned to the parameter or its member
|
alpar@1
|
2116 |
whenever no appropriate data are available in the data section. If
|
alpar@1
|
2117 |
neither assign nor {\tt default} attribute is specified, missing data
|
alpar@1
|
2118 |
will cause an error.
|
alpar@1
|
2119 |
|
alpar@1
|
2120 |
\subsection{Variable statement}
|
alpar@1
|
2121 |
|
alpar@1
|
2122 |
\medskip
|
alpar@1
|
2123 |
|
alpar@1
|
2124 |
\framebox[345pt][l]{
|
alpar@1
|
2125 |
\parbox[c][24pt]{345pt}{
|
alpar@1
|
2126 |
\hspace{6pt} {\tt var} {\it name} {\it alias} {\it domain} {\tt,}
|
alpar@1
|
2127 |
{\it attrib} {\tt,} \dots {\tt,} {\it attrib} {\tt;}
|
alpar@1
|
2128 |
}}
|
alpar@1
|
2129 |
|
alpar@1
|
2130 |
\setlength{\leftmargini}{60pt}
|
alpar@1
|
2131 |
|
alpar@1
|
2132 |
\begin{description}
|
alpar@1
|
2133 |
\item[{\rm Where:}\hspace*{23pt}] {\it name} is a symbolic name of the
|
alpar@1
|
2134 |
variable;
|
alpar@1
|
2135 |
\item[\hspace*{54pt}] {\it alias} is an optional string literal, which
|
alpar@1
|
2136 |
specifies an alias of the variable;
|
alpar@1
|
2137 |
\item[\hspace*{54pt}] {\it domain} is an optional indexing expression,
|
alpar@1
|
2138 |
which specifies a subscript domain of the variable;
|
alpar@1
|
2139 |
\item[\hspace*{54pt}] {\it attrib}, \dots, {\it attrib} are optional
|
alpar@1
|
2140 |
attributes of the variable. (Commae preceding attributes may be
|
alpar@1
|
2141 |
omitted.)
|
alpar@1
|
2142 |
\end{description}
|
alpar@1
|
2143 |
|
alpar@1
|
2144 |
\noindent Optional attributes:
|
alpar@1
|
2145 |
|
alpar@1
|
2146 |
\begin{description}
|
alpar@1
|
2147 |
\item[{\tt integer}\hspace*{18.5pt}] restricts the variable to be
|
alpar@1
|
2148 |
integer;
|
alpar@1
|
2149 |
\item[{\tt binary}\hspace*{24pt}] restricts the variable to be binary;
|
alpar@1
|
2150 |
\item[{\tt>=} {\it expression}]\hspace*{0pt}\\
|
alpar@1
|
2151 |
specifies an lower bound of the variable;
|
alpar@1
|
2152 |
\item[{\tt<=} {\it expression}]\hspace*{0pt}\\
|
alpar@1
|
2153 |
specifies an upper bound of the variable;
|
alpar@1
|
2154 |
\item[{\tt=} {\it expression}]\hspace*{0pt}\\
|
alpar@1
|
2155 |
specifies a fixed value of the variable;
|
alpar@1
|
2156 |
\end{description}
|
alpar@1
|
2157 |
|
alpar@1
|
2158 |
\noindent{\bf Examples}
|
alpar@1
|
2159 |
|
alpar@1
|
2160 |
\begin{verbatim}
|
alpar@1
|
2161 |
var x >= 0;
|
alpar@1
|
2162 |
var y{I,J};
|
alpar@1
|
2163 |
var make{p in prd}, integer, >= commit[p], <= market[p];
|
alpar@1
|
2164 |
var store{raw, 1..T+1} >= 0;
|
alpar@1
|
2165 |
var z{i in I, j in J} >= i+j;
|
alpar@1
|
2166 |
\end{verbatim}
|
alpar@1
|
2167 |
|
alpar@1
|
2168 |
The variable statement declares a variable. If a subscript domain is
|
alpar@1
|
2169 |
not specified, the variable is a simple (scalar) variable, otherwise it
|
alpar@1
|
2170 |
is a $n$-dimensional array of elemental variables.
|
alpar@1
|
2171 |
|
alpar@1
|
2172 |
Elemental variable(s) associated with the model variable (if it is a
|
alpar@1
|
2173 |
simple variable) or its members (if it is an array) correspond to the
|
alpar@1
|
2174 |
variables in the LP/MIP problem formulation (see Subsection
|
alpar@1
|
2175 |
\ref{problem}, page \pageref{problem}). Note that only elemental
|
alpar@1
|
2176 |
variables actually referenced in some constraints and/or objectives are
|
alpar@1
|
2177 |
included in the LP/MIP problem instance to be generated.
|
alpar@1
|
2178 |
|
alpar@1
|
2179 |
The type attributes {\tt integer} and {\tt binary} restrict the
|
alpar@1
|
2180 |
variable to be integer or binary, respectively. If no type attribute is
|
alpar@1
|
2181 |
specified, the variable is continuous. If all variables in the model
|
alpar@1
|
2182 |
are continuous, the corresponding problem is of LP class. If there is
|
alpar@1
|
2183 |
at least one integer or binary variable, the problem is of MIP class.
|
alpar@1
|
2184 |
|
alpar@1
|
2185 |
The lower bound ({\tt>=}) attribute specifies a numeric expression for
|
alpar@1
|
2186 |
computing an lower bound of the variable. At most one lower bound can
|
alpar@1
|
2187 |
be specified. By default all variables (except binary ones) have no
|
alpar@1
|
2188 |
lower bound, so if a variable is required to be non-negative, its zero
|
alpar@1
|
2189 |
lower bound should be explicitly specified.
|
alpar@1
|
2190 |
|
alpar@1
|
2191 |
The upper bound ({\tt<=}) attribute specifies a numeric expression for
|
alpar@1
|
2192 |
computing an upper bound of the variable. At most one upper bound
|
alpar@1
|
2193 |
attribute can be specified.
|
alpar@1
|
2194 |
|
alpar@1
|
2195 |
The fixed value ({\tt=}) attribute specifies a numeric expression for
|
alpar@1
|
2196 |
computing a value, at which the variable is fixed. This attribute
|
alpar@1
|
2197 |
cannot be specified along with the bound attributes.
|
alpar@1
|
2198 |
|
alpar@1
|
2199 |
\subsection{Constraint statement}
|
alpar@1
|
2200 |
|
alpar@1
|
2201 |
\medskip
|
alpar@1
|
2202 |
|
alpar@1
|
2203 |
\framebox[345pt][l]{
|
alpar@1
|
2204 |
\parbox[c][96pt]{345pt}{
|
alpar@1
|
2205 |
\hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:}
|
alpar@1
|
2206 |
{\it expression} {\tt,} {\tt=} {\it expression} {\tt;}
|
alpar@1
|
2207 |
|
alpar@1
|
2208 |
\medskip
|
alpar@1
|
2209 |
|
alpar@1
|
2210 |
\hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:}
|
alpar@1
|
2211 |
{\it expression} {\tt,} {\tt<=} {\it expression} {\tt;}
|
alpar@1
|
2212 |
|
alpar@1
|
2213 |
\medskip
|
alpar@1
|
2214 |
|
alpar@1
|
2215 |
\hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:}
|
alpar@1
|
2216 |
{\it expression} {\tt,} {\tt>=} {\it expression} {\tt;}
|
alpar@1
|
2217 |
|
alpar@1
|
2218 |
\medskip
|
alpar@1
|
2219 |
|
alpar@1
|
2220 |
\hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:}
|
alpar@1
|
2221 |
{\it expression} {\tt,} {\tt<=} {\it expression} {\tt,} {\tt<=}
|
alpar@1
|
2222 |
{\it expression} {\tt;}
|
alpar@1
|
2223 |
|
alpar@1
|
2224 |
\medskip
|
alpar@1
|
2225 |
|
alpar@1
|
2226 |
\hspace{6pt} {\tt s.t.} {\it name} {\it alias} {\it domain} {\tt:}
|
alpar@1
|
2227 |
{\it expression} {\tt,} {\tt>=} {\it expression} {\tt,} {\tt>=}
|
alpar@1
|
2228 |
{\it expression} {\tt;}
|
alpar@1
|
2229 |
}}
|
alpar@1
|
2230 |
|
alpar@1
|
2231 |
\setlength{\leftmargini}{60pt}
|
alpar@1
|
2232 |
|
alpar@1
|
2233 |
\begin{description}
|
alpar@1
|
2234 |
\item[{\rm Where:}\hspace*{23pt}] {\it name} is a symbolic name of the
|
alpar@1
|
2235 |
constraint;
|
alpar@1
|
2236 |
\item[\hspace*{54pt}] {\it alias} is an optional string literal, which
|
alpar@1
|
2237 |
specifies an alias of the constraint;
|
alpar@1
|
2238 |
\item[\hspace*{54pt}] {\it domain} is an optional indexing expression,
|
alpar@1
|
2239 |
which specifies a subscript domain of the constraint;
|
alpar@1
|
2240 |
\item[\hspace*{54pt}] {\it expression} is a linear expression used to
|
alpar@1
|
2241 |
compute a component of the constraint. (Commae following expressions
|
alpar@1
|
2242 |
may be omitted.)
|
alpar@1
|
2243 |
\end{description}
|
alpar@1
|
2244 |
|
alpar@1
|
2245 |
\begin{description}
|
alpar@1
|
2246 |
\item[{\rm Note:}\hspace*{31pt}] The keyword {\tt s.t.} may be written
|
alpar@1
|
2247 |
as {\tt subject to} or as {\tt subj to}, or may be omitted at all.
|
alpar@1
|
2248 |
\end{description}
|
alpar@1
|
2249 |
|
alpar@1
|
2250 |
\noindent{\bf Examples}
|
alpar@1
|
2251 |
|
alpar@1
|
2252 |
\begin{verbatim}
|
alpar@1
|
2253 |
s.t. r: x + y + z, >= 0, <= 1;
|
alpar@1
|
2254 |
limit{t in 1..T}: sum{j in prd} make[j,t] <= max_prd;
|
alpar@1
|
2255 |
subject to balance{i in raw, t in 1..T}: store[i,t+1] -
|
alpar@1
|
2256 |
store[i,t] - sum{j in prd} units[i,j] * make[j,t];
|
alpar@1
|
2257 |
subject to rlim 'regular-time limit' {t in time}:
|
alpar@1
|
2258 |
sum{p in prd} pt[p] * rprd[p,t] <= 1.3 * dpp[t] * crews[t];
|
alpar@1
|
2259 |
\end{verbatim}
|
alpar@1
|
2260 |
|
alpar@1
|
2261 |
The constraint statement declares a constraint. If a subscript domain
|
alpar@1
|
2262 |
is not specified, the constraint is a simple (scalar) constraint,
|
alpar@1
|
2263 |
otherwise it is a $n$-dimensional array of elemental constraints.
|
alpar@1
|
2264 |
|
alpar@1
|
2265 |
Elemental constraint(s) associated with the model constraint (if it is
|
alpar@1
|
2266 |
a simple constraint) or its members (if it is an array) correspond to
|
alpar@1
|
2267 |
the linear constraints in the LP/MIP problem formulation (see
|
alpar@1
|
2268 |
Subsection \ref{problem}, page \pageref{problem}).
|
alpar@1
|
2269 |
|
alpar@1
|
2270 |
If the constraint has the form of equality or single inequality, i.e.
|
alpar@1
|
2271 |
includes two expressions, one of which follows the colon and other
|
alpar@1
|
2272 |
follows the relation sign {\tt=}, {\tt<=}, or {\tt>=}, both expressions
|
alpar@1
|
2273 |
in the statement can be linear expressions. If the constraint has the
|
alpar@1
|
2274 |
form of double inequality, i.e. includes three expressions, the middle
|
alpar@1
|
2275 |
expression can be a linear expression while the leftmost and rightmost
|
alpar@1
|
2276 |
ones can be only numeric expressions.
|
alpar@1
|
2277 |
|
alpar@1
|
2278 |
Generating the model is, roughly speaking, generating its constraints,
|
alpar@1
|
2279 |
which are always evaluated for the entire subscript domain. Evaluation
|
alpar@1
|
2280 |
of the constraints leads, in turn, to evaluation of other model objects
|
alpar@1
|
2281 |
such as sets, parameters, and variables.
|
alpar@1
|
2282 |
|
alpar@1
|
2283 |
Constructing an actual linear constraint included in the problem
|
alpar@1
|
2284 |
instance, which (constraint) corresponds to a particular elemental
|
alpar@1
|
2285 |
constraint, is performed as follows.
|
alpar@1
|
2286 |
|
alpar@1
|
2287 |
If the constraint has the form of equality or single inequality,
|
alpar@1
|
2288 |
evaluation of both linear expressions gives two resultant linear forms:
|
alpar@1
|
2289 |
$$\begin{array}{r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r@{\ }c@{\ }r}
|
alpar@1
|
2290 |
f&=&a_1x_1&+&a_2x_2&+\dots+&a_nx_n&+&a_0,\\
|
alpar@1
|
2291 |
g&=&b_1x_1&+&a_2x_2&+\dots+&a_nx_n&+&b_0,\\
|
alpar@1
|
2292 |
\end{array}$$
|
alpar@1
|
2293 |
where $x_1$, $x_2$, \dots, $x_n$ are elemental variables; $a_1$, $a_2$,
|
alpar@1
|
2294 |
\dots, $a_n$, $b_1$, $b_2$, \dots, $b_n$ are numeric coefficients;
|
alpar@1
|
2295 |
$a_0$ and $b_0$ are constant terms. Then all linear terms of $f$ and
|
alpar@1
|
2296 |
$g$ are carried to the left-hand side, and the constant terms are
|
alpar@1
|
2297 |
carried to the right-hand side, that gives the final elemental
|
alpar@1
|
2298 |
constraint in the standard form:
|
alpar@1
|
2299 |
$$(a_1-b_1)x_1+(a_2-b_2)x_2+\dots+(a_n-b_n)x_n\left\{
|
alpar@1
|
2300 |
\begin{array}{@{}c@{}}=\\\leq\\\geq\\\end{array}\right\}b_0-a_0.$$
|
alpar@1
|
2301 |
|
alpar@1
|
2302 |
If the constraint has the form of double inequality, evaluation of the
|
alpar@1
|
2303 |
middle linear expression gives the resultant linear form:
|
alpar@1
|
2304 |
$$f=a_1x_1+a_2x_2+\dots+a_nx_n+a_0,$$
|
alpar@1
|
2305 |
and evaluation of the leftmost and rightmost numeric expressions gives
|
alpar@1
|
2306 |
two numeric values $l$ and $u$, respectively. Then the constant term of
|
alpar@1
|
2307 |
the linear form is carried to both left-hand and right-handsides that
|
alpar@1
|
2308 |
gives the final elemental constraint in the standard form:
|
alpar@1
|
2309 |
$$l-a_0\leq a_1x_1+a_2x_2+\dots+a_nx_n\leq u-a_0.$$
|
alpar@1
|
2310 |
|
alpar@1
|
2311 |
\subsection{Objective statement}
|
alpar@1
|
2312 |
|
alpar@1
|
2313 |
\medskip
|
alpar@1
|
2314 |
|
alpar@1
|
2315 |
\framebox[345pt][l]{
|
alpar@1
|
2316 |
\parbox[c][44pt]{345pt}{
|
alpar@1
|
2317 |
\hspace{6pt} {\tt minimize} {\it name} {\it alias} {\it domain} {\tt:}
|
alpar@1
|
2318 |
{\it expression} {\tt;}
|
alpar@1
|
2319 |
|
alpar@1
|
2320 |
\medskip
|
alpar@1
|
2321 |
|
alpar@1
|
2322 |
\hspace{6pt} {\tt maximize} {\it name} {\it alias} {\it domain} {\tt:}
|
alpar@1
|
2323 |
{\it expression} {\tt;}
|
alpar@1
|
2324 |
}}
|
alpar@1
|
2325 |
|
alpar@1
|
2326 |
\setlength{\leftmargini}{60pt}
|
alpar@1
|
2327 |
|
alpar@1
|
2328 |
\begin{description}
|
alpar@1
|
2329 |
\item[{\rm Where:}\hspace*{23pt}] {\it name} is a symbolic name of the
|
alpar@1
|
2330 |
objective;
|
alpar@1
|
2331 |
\item[\hspace*{54pt}] {\it alias} is an optional string literal, which
|
alpar@1
|
2332 |
specifies an alias of the objective;
|
alpar@1
|
2333 |
\item[\hspace*{54pt}] {\it domain} is an optional indexing expression,
|
alpar@1
|
2334 |
which specifies a subscript domain of the objective;
|
alpar@1
|
2335 |
\item[\hspace*{54pt}] {\it expression} is a linear expression used to
|
alpar@1
|
2336 |
compute the linear form of the objective.
|
alpar@1
|
2337 |
\end{description}
|
alpar@1
|
2338 |
|
alpar@1
|
2339 |
\noindent{\bf Examples}
|
alpar@1
|
2340 |
|
alpar@1
|
2341 |
\begin{verbatim}
|
alpar@1
|
2342 |
minimize obj: x + 1.5 * (y + z);
|
alpar@1
|
2343 |
maximize total_profit: sum{p in prd} profit[p] * make[p];
|
alpar@1
|
2344 |
\end{verbatim}
|
alpar@1
|
2345 |
|
alpar@1
|
2346 |
The objective statement declares an objective. If a subscript domain is
|
alpar@1
|
2347 |
not specified, the objective is a simple (scalar) objective. Otherwise
|
alpar@1
|
2348 |
it is a $n$-dimensional array of elemental objectives.
|
alpar@1
|
2349 |
|
alpar@1
|
2350 |
Elemental objective(s) associated with the model objective (if it is a
|
alpar@1
|
2351 |
simple objective) or its members (if it is an array) correspond to
|
alpar@1
|
2352 |
general linear constraints in the LP/MIP problem formulation (see
|
alpar@1
|
2353 |
Subsection \ref{problem}, page \pageref{problem}). However, unlike
|
alpar@1
|
2354 |
constraints the corresponding linear forms are free (unbounded).
|
alpar@1
|
2355 |
|
alpar@1
|
2356 |
Constructing an actual linear constraint included in the problem
|
alpar@1
|
2357 |
instance, which (constraint) corresponds to a particular elemental
|
alpar@1
|
2358 |
constraint, is performed as follows. The linear expression specified in
|
alpar@1
|
2359 |
the objective statement is evaluated that, gives the resultant linear
|
alpar@1
|
2360 |
form:
|
alpar@1
|
2361 |
$$f=a_1x_1+a_2x_2+\dots+a_nx_n+a_0,$$
|
alpar@1
|
2362 |
where $x_1$, $x_2$, \dots, $x_n$ are elemental variables; $a_1$, $a_2$,
|
alpar@1
|
2363 |
\dots, $a_n$ are numeric coefficients; $a_0$ is the constant term. Then
|
alpar@1
|
2364 |
the linear form is used to construct the final elemental constraint in
|
alpar@1
|
2365 |
the standard form:
|
alpar@1
|
2366 |
$$-\infty<a_1x_1+a_2x_2+\dots+a_nx_n+a_0<+\infty.$$
|
alpar@1
|
2367 |
|
alpar@1
|
2368 |
As a rule the model description contains only one objective statement
|
alpar@1
|
2369 |
that defines the objective function used in the problem instance.
|
alpar@1
|
2370 |
However, it is allowed to declare arbitrary number of objectives, in
|
alpar@1
|
2371 |
which case the actual objective function is the first objective
|
alpar@1
|
2372 |
encountered in the model description. Other objectives are also
|
alpar@1
|
2373 |
included in the problem instance, but they do not affect the objective
|
alpar@1
|
2374 |
function.
|
alpar@1
|
2375 |
|
alpar@1
|
2376 |
\subsection{Solve statement}
|
alpar@1
|
2377 |
|
alpar@1
|
2378 |
\medskip
|
alpar@1
|
2379 |
|
alpar@1
|
2380 |
\framebox[345pt][l]{
|
alpar@1
|
2381 |
\parbox[c][24pt]{345pt}{
|
alpar@1
|
2382 |
\hspace{6pt} {\tt solve} {\tt;}
|
alpar@1
|
2383 |
}}
|
alpar@1
|
2384 |
|
alpar@1
|
2385 |
\setlength{\leftmargini}{60pt}
|
alpar@1
|
2386 |
|
alpar@1
|
2387 |
\begin{description}
|
alpar@1
|
2388 |
\item[{\rm Note:}\hspace*{31pt}] The solve statement is optional and
|
alpar@1
|
2389 |
can be used only once. If no solve statement is used, one is assumed at
|
alpar@1
|
2390 |
the end of the model section.
|
alpar@1
|
2391 |
\end{description}
|
alpar@1
|
2392 |
|
alpar@1
|
2393 |
The solve statement causes the model to be solved, that means computing
|
alpar@1
|
2394 |
numeric values of all model variables. This allows using variables in
|
alpar@1
|
2395 |
statements below the solve statement in the same way as if they were
|
alpar@1
|
2396 |
numeric parameters.
|
alpar@1
|
2397 |
|
alpar@1
|
2398 |
Note that the variable, constraint, and objective statements cannot be
|
alpar@1
|
2399 |
used below the solve statement, i.e. all principal components of the
|
alpar@1
|
2400 |
model must be declared above the solve statement.
|
alpar@1
|
2401 |
|
alpar@1
|
2402 |
\subsection{Check statement}
|
alpar@1
|
2403 |
|
alpar@1
|
2404 |
\medskip
|
alpar@1
|
2405 |
|
alpar@1
|
2406 |
\framebox[345pt][l]{
|
alpar@1
|
2407 |
\parbox[c][24pt]{345pt}{
|
alpar@1
|
2408 |
\hspace{6pt} {\tt check} {\it domain} {\tt:} {\it expression} {\tt;}
|
alpar@1
|
2409 |
}}
|
alpar@1
|
2410 |
|
alpar@1
|
2411 |
\setlength{\leftmargini}{60pt}
|
alpar@1
|
2412 |
|
alpar@1
|
2413 |
\begin{description}
|
alpar@1
|
2414 |
\item[{\rm Where:}\hspace*{23pt}] {\it domain} is an optional indexing
|
alpar@1
|
2415 |
expression, which specifies a subscript domain of the check statement;
|
alpar@1
|
2416 |
\item[\hspace*{54pt}] {\it expression} is an logical expression which
|
alpar@1
|
2417 |
specifies the logical condition to be checked. (The colon preceding
|
alpar@1
|
2418 |
{\it expression} may be omitted.)
|
alpar@1
|
2419 |
\end{description}
|
alpar@1
|
2420 |
|
alpar@1
|
2421 |
\noindent{\bf Examples}
|
alpar@1
|
2422 |
|
alpar@1
|
2423 |
\begin{verbatim}
|
alpar@1
|
2424 |
check: x + y <= 1 and x >= 0 and y >= 0;
|
alpar@1
|
2425 |
check sum{i in ORIG} supply[i] = sum{j in DEST} demand[j];
|
alpar@1
|
2426 |
check{i in I, j in 1..10}: S[i,j] in U[i] union V[j];
|
alpar@1
|
2427 |
\end{verbatim}
|
alpar@1
|
2428 |
|
alpar@1
|
2429 |
The check statement allows checking the resultant value of an logical
|
alpar@1
|
2430 |
expression specified in the statement. If the value is {\it false}, an
|
alpar@1
|
2431 |
error is reported.
|
alpar@1
|
2432 |
|
alpar@1
|
2433 |
If the subscript domain is not specified, the check is performed only
|
alpar@1
|
2434 |
once. Specifying the subscript domain allows performing multiple checks
|
alpar@1
|
2435 |
for every\linebreak $n$-tuple in the domain set. In the latter case the
|
alpar@1
|
2436 |
logical expression may include dummy indices introduced in
|
alpar@1
|
2437 |
corresponding indexing expression.
|
alpar@1
|
2438 |
|
alpar@1
|
2439 |
\subsection{Display statement}
|
alpar@1
|
2440 |
|
alpar@1
|
2441 |
\medskip
|
alpar@1
|
2442 |
|
alpar@1
|
2443 |
\framebox[345pt][l]{
|
alpar@1
|
2444 |
\parbox[c][24pt]{345pt}{
|
alpar@1
|
2445 |
\hspace{6pt} {\tt display} {\it domain} {\tt:} {\it item} {\tt,}
|
alpar@1
|
2446 |
\dots {\tt,} {\it item} {\tt;}
|
alpar@1
|
2447 |
}}
|
alpar@1
|
2448 |
|
alpar@1
|
2449 |
\setlength{\leftmargini}{60pt}
|
alpar@1
|
2450 |
|
alpar@1
|
2451 |
\begin{description}
|
alpar@1
|
2452 |
\item[{\rm Where:}\hspace*{23pt}] {\it domain} is an optional indexing
|
alpar@1
|
2453 |
expression, which specifies a subscript domain of the check statement;
|
alpar@1
|
2454 |
\item[\hspace*{54pt}] {\it item}, \dots, {\it item} are items to be
|
alpar@1
|
2455 |
displayed. (The colon preceding the first item may be omitted.)
|
alpar@1
|
2456 |
\end{description}
|
alpar@1
|
2457 |
|
alpar@1
|
2458 |
\noindent{\bf Examples}
|
alpar@1
|
2459 |
|
alpar@1
|
2460 |
\begin{verbatim}
|
alpar@1
|
2461 |
display: 'x =', x, 'y =', y, 'z =', z;
|
alpar@1
|
2462 |
display sqrt(x ** 2 + y ** 2 + z ** 2);
|
alpar@1
|
2463 |
display{i in I, j in J}: i, j, a[i,j], b[i,j];
|
alpar@1
|
2464 |
\end{verbatim}
|
alpar@1
|
2465 |
|
alpar@1
|
2466 |
\newpage
|
alpar@1
|
2467 |
|
alpar@1
|
2468 |
The display statement evaluates all items specified in the statement
|
alpar@1
|
2469 |
and writes their values to the terminal in plain text format.
|
alpar@1
|
2470 |
|
alpar@1
|
2471 |
If a subscript domain is not specified, items are evaluated and then
|
alpar@1
|
2472 |
displayed only once. Specifying the subscript domain causes items to be
|
alpar@1
|
2473 |
evaluated and displayed for every $n$-tuple in the domain set. In the
|
alpar@1
|
2474 |
latter case items may include dummy indices introduced in corresponding
|
alpar@1
|
2475 |
indexing expression.
|
alpar@1
|
2476 |
|
alpar@1
|
2477 |
An item to be displayed can be a model object (set, parameter, variable,
|
alpar@1
|
2478 |
constraint, objective) or an expression.
|
alpar@1
|
2479 |
|
alpar@1
|
2480 |
If the item is a computable object (i.e. a set or parameter provided
|
alpar@1
|
2481 |
with the assign attribute), the object is evaluated over the entire
|
alpar@1
|
2482 |
domain and then its content (i.e. the content of the object array) is
|
alpar@1
|
2483 |
displayed. Otherwise, if the item is not a computable object, only its
|
alpar@1
|
2484 |
current content (i.e. members actually generated during the model
|
alpar@1
|
2485 |
evaluation) is displayed.
|
alpar@1
|
2486 |
|
alpar@1
|
2487 |
If the item is an expression, the expression is evaluated and its
|
alpar@1
|
2488 |
resultant value is displayed.
|
alpar@1
|
2489 |
|
alpar@1
|
2490 |
\subsection{Printf statement}
|
alpar@1
|
2491 |
|
alpar@1
|
2492 |
\medskip
|
alpar@1
|
2493 |
|
alpar@1
|
2494 |
\framebox[345pt][l]{
|
alpar@1
|
2495 |
\parbox[c][60pt]{345pt}{
|
alpar@1
|
2496 |
\hspace{6pt} {\tt printf} {\it domain} {\tt:} {\it format} {\tt,}
|
alpar@1
|
2497 |
{\it expression} {\tt,} \dots {\tt,} {\it expression} {\tt;}
|
alpar@1
|
2498 |
|
alpar@1
|
2499 |
\medskip
|
alpar@1
|
2500 |
|
alpar@1
|
2501 |
\hspace{6pt} {\tt printf} {\it domain} {\tt:} {\it format} {\tt,}
|
alpar@1
|
2502 |
{\it expression} {\tt,} \dots {\tt,} {\it expression} {\tt>}
|
alpar@1
|
2503 |
{\it filename} {\tt;}
|
alpar@1
|
2504 |
|
alpar@1
|
2505 |
\medskip
|
alpar@1
|
2506 |
|
alpar@1
|
2507 |
\hspace{6pt} {\tt printf} {\it domain} {\tt:} {\it format} {\tt,}
|
alpar@1
|
2508 |
{\it expression} {\tt,} \dots {\tt,} {\it expression} {\tt>>}
|
alpar@1
|
2509 |
{\it filename} {\tt;}
|
alpar@1
|
2510 |
}}
|
alpar@1
|
2511 |
|
alpar@1
|
2512 |
\setlength{\leftmargini}{60pt}
|
alpar@1
|
2513 |
|
alpar@1
|
2514 |
\begin{description}
|
alpar@1
|
2515 |
\item[{\rm Where:}\hspace*{23pt}] {\it domain} is an optional indexing
|
alpar@1
|
2516 |
expression, which specifies a subscript domain of the printf statement;
|
alpar@1
|
2517 |
\item[\hspace*{54pt}] {\it format} is a symbolic expression whose value
|
alpar@1
|
2518 |
specifies a format control string. (The colon preceding the format
|
alpar@1
|
2519 |
expression may be omitted.)
|
alpar@1
|
2520 |
\item[\hspace*{54pt}] {\it expression}, \dots, {\it expression} are
|
alpar@1
|
2521 |
zero or more expressions whose values have to be formatted and printed.
|
alpar@1
|
2522 |
Each expression must be of numeric, symbolic, or logical type.
|
alpar@1
|
2523 |
\item[\hspace*{54pt}] {\it filename} is a symbolic expression whose
|
alpar@1
|
2524 |
value specifies a name of a text file, to which the output is
|
alpar@1
|
2525 |
redirected. The flag {\tt>} means creating a new empty file while the
|
alpar@1
|
2526 |
flag {\tt>>} means appending the output to an existing file. If no file
|
alpar@1
|
2527 |
name is specified, the output is written to the terminal.
|
alpar@1
|
2528 |
\end{description}
|
alpar@1
|
2529 |
|
alpar@1
|
2530 |
\noindent{\bf Examples}
|
alpar@1
|
2531 |
|
alpar@1
|
2532 |
\begin{verbatim}
|
alpar@1
|
2533 |
printf 'Hello, world!\n';
|
alpar@1
|
2534 |
printf: "x = %.3f; y = %.3f; z = %.3f\n",
|
alpar@1
|
2535 |
x, y, z > "result.txt";
|
alpar@1
|
2536 |
printf{i in I, j in J}: "flow from %s to %s is %d\n",
|
alpar@1
|
2537 |
i, j, x[i,j] >> result_file & ".txt";
|
alpar@1
|
2538 |
\end{verbatim}
|
alpar@1
|
2539 |
|
alpar@1
|
2540 |
\newpage
|
alpar@1
|
2541 |
|
alpar@1
|
2542 |
\begin{verbatim}
|
alpar@1
|
2543 |
printf{i in I} 'total flow from %s is %g\n',
|
alpar@1
|
2544 |
i, sum{j in J} x[i,j];
|
alpar@1
|
2545 |
printf{k in K} "x[%s] = " & (if x[k] < 0 then "?" else "%g"),
|
alpar@1
|
2546 |
k, x[k];
|
alpar@1
|
2547 |
\end{verbatim}
|
alpar@1
|
2548 |
|
alpar@1
|
2549 |
The printf statement is similar to the display statement, however, it
|
alpar@1
|
2550 |
allows formatting data to be written.
|
alpar@1
|
2551 |
|
alpar@1
|
2552 |
If a subscript domain is not specified, the printf statement is
|
alpar@1
|
2553 |
executed only once. Specifying a subscript domain causes executing the
|
alpar@1
|
2554 |
printf statement for every $n$-tuple in the domain set. In the latter
|
alpar@1
|
2555 |
case the format and expression may include dummy indices introduced in
|
alpar@1
|
2556 |
corresponding indexing expression.
|
alpar@1
|
2557 |
|
alpar@1
|
2558 |
The format control string is a value of the symbolic expression
|
alpar@1
|
2559 |
{\it format} specified in the printf statement. It is composed of zero
|
alpar@1
|
2560 |
or more directives as follows: ordinary characters (not {\tt\%}), which
|
alpar@1
|
2561 |
are copied unchanged to the output stream, and conversion
|
alpar@1
|
2562 |
specifications, each of which causes evaluating corresponding
|
alpar@1
|
2563 |
expression specified in the printf statement, formatting it, and
|
alpar@1
|
2564 |
writing its resultant value to the output stream.
|
alpar@1
|
2565 |
|
alpar@1
|
2566 |
Conversion specifications that may be used in the format control string
|
alpar@1
|
2567 |
are the following: {\tt d}, {\tt i}, {\tt f}, {\tt F}, {\tt e}, {\tt E},
|
alpar@1
|
2568 |
{\tt g}, {\tt G}, and {\tt s}. These specifications have the same
|
alpar@1
|
2569 |
syntax and semantics as in the C programming language.
|
alpar@1
|
2570 |
|
alpar@1
|
2571 |
\subsection{For statement}
|
alpar@1
|
2572 |
|
alpar@1
|
2573 |
\medskip
|
alpar@1
|
2574 |
|
alpar@1
|
2575 |
\framebox[345pt][l]{
|
alpar@1
|
2576 |
\parbox[c][44pt]{345pt}{
|
alpar@1
|
2577 |
\hspace{6pt} {\tt for} {\it domain} {\tt:} {\it statement} {\tt;}
|
alpar@1
|
2578 |
|
alpar@1
|
2579 |
\medskip
|
alpar@1
|
2580 |
|
alpar@1
|
2581 |
\hspace{6pt} {\tt for} {\it domain} {\tt:} {\tt\{} {\it statement}
|
alpar@1
|
2582 |
\dots {\it statement} {\tt\}} {\tt;}
|
alpar@1
|
2583 |
}}
|
alpar@1
|
2584 |
|
alpar@1
|
2585 |
\setlength{\leftmargini}{60pt}
|
alpar@1
|
2586 |
|
alpar@1
|
2587 |
\begin{description}
|
alpar@1
|
2588 |
\item[{\rm Where:}\hspace*{23pt}] {\it domain} is an indexing
|
alpar@1
|
2589 |
expression which specifies a subscript domain of the for statement.
|
alpar@1
|
2590 |
(The colon following the indexing expression may be omitted.)
|
alpar@1
|
2591 |
\item[\hspace*{54pt}] {\it statement} is a statement, which should be
|
alpar@1
|
2592 |
executed under control of the for statement;
|
alpar@1
|
2593 |
\item[\hspace*{54pt}] {\it statement}, \dots, {\it statement} is a
|
alpar@1
|
2594 |
sequence of statements (enclosed in curly braces), which should be
|
alpar@1
|
2595 |
executed under control of the for statement.
|
alpar@1
|
2596 |
\end{description}
|
alpar@1
|
2597 |
|
alpar@1
|
2598 |
\begin{description}
|
alpar@1
|
2599 |
\item[{\rm Note:}\hspace*{31pt}] Only the following statements can be
|
alpar@1
|
2600 |
used within the for statement: check, display, printf, and another for.
|
alpar@1
|
2601 |
\end{description}
|
alpar@1
|
2602 |
|
alpar@1
|
2603 |
\noindent{\bf Examples}
|
alpar@1
|
2604 |
|
alpar@1
|
2605 |
\begin{verbatim}
|
alpar@1
|
2606 |
for {(i,j) in E: i != j}
|
alpar@1
|
2607 |
{ printf "flow from %s to %s is %g\n", i, j, x[i,j];
|
alpar@1
|
2608 |
check x[i,j] >= 0;
|
alpar@1
|
2609 |
}
|
alpar@1
|
2610 |
\end{verbatim}
|
alpar@1
|
2611 |
|
alpar@1
|
2612 |
\newpage
|
alpar@1
|
2613 |
|
alpar@1
|
2614 |
\begin{verbatim}
|
alpar@1
|
2615 |
for {i in 1..n}
|
alpar@1
|
2616 |
{ for {j in 1..n} printf " %s", if x[i,j] then "Q" else ".";
|
alpar@1
|
2617 |
printf("\n");
|
alpar@1
|
2618 |
}
|
alpar@1
|
2619 |
for {1..72} printf("*");
|
alpar@1
|
2620 |
\end{verbatim}
|
alpar@1
|
2621 |
|
alpar@1
|
2622 |
The for statement causes a statement or a sequence of statements
|
alpar@1
|
2623 |
specified as part of the for statement to be executed for every
|
alpar@1
|
2624 |
$n$-tuple in the domain set. Thus, statements within the for statement
|
alpar@1
|
2625 |
may include dummy indices introduced in corresponding indexing
|
alpar@1
|
2626 |
expression.
|
alpar@1
|
2627 |
|
alpar@1
|
2628 |
\subsection{Table statement}
|
alpar@1
|
2629 |
|
alpar@1
|
2630 |
\medskip
|
alpar@1
|
2631 |
|
alpar@1
|
2632 |
\framebox[345pt][l]{
|
alpar@1
|
2633 |
\parbox[c][68pt]{345pt}{
|
alpar@1
|
2634 |
\hspace{6pt} {\tt table} {\it name} {\it alias} {\tt IN} {\it driver}
|
alpar@1
|
2635 |
{\it arg} \dots {\it arg} {\tt:}
|
alpar@1
|
2636 |
|
alpar@1
|
2637 |
\hspace{6pt} {\tt\ \ \ \ \ } {\it set} {\tt<-} {\tt[} {\it fld} {\tt,}
|
alpar@1
|
2638 |
\dots {\tt,} {\it fld} {\tt]} {\tt,} {\it par} {\tt\textasciitilde}
|
alpar@1
|
2639 |
{\it fld} {\tt,} \dots {\tt,} {\it par} {\tt\textasciitilde} {\it fld}
|
alpar@1
|
2640 |
{\tt;}
|
alpar@1
|
2641 |
|
alpar@1
|
2642 |
\medskip
|
alpar@1
|
2643 |
|
alpar@1
|
2644 |
\hspace{6pt} {\tt table} {\it name} {\it alias} {\it domain} {\tt OUT}
|
alpar@1
|
2645 |
{\it driver} {\it arg} \dots {\it arg} {\tt:}
|
alpar@1
|
2646 |
|
alpar@1
|
2647 |
\hspace{6pt} {\tt\ \ \ \ \ } {\it expr} {\tt\textasciitilde} {\it fld}
|
alpar@1
|
2648 |
{\tt,} \dots {\tt,} {\it expr} {\tt\textasciitilde} {\it fld} {\tt;}
|
alpar@1
|
2649 |
}}
|
alpar@1
|
2650 |
|
alpar@1
|
2651 |
\setlength{\leftmargini}{60pt}
|
alpar@1
|
2652 |
|
alpar@1
|
2653 |
\begin{description}
|
alpar@1
|
2654 |
\item[{\rm Where:}\hspace*{23pt}] {\it name} is a symbolic name of the
|
alpar@1
|
2655 |
table;
|
alpar@1
|
2656 |
\item[\hspace*{54pt}] {\it alias} is an optional string literal, which
|
alpar@1
|
2657 |
specifies an alias of the table;
|
alpar@1
|
2658 |
\item[\hspace*{54pt}] {\it domain} is an indexing expression, which
|
alpar@1
|
2659 |
specifies a subscript domain of the (output) table;
|
alpar@1
|
2660 |
\item[\hspace*{54pt}] {\tt IN} means reading data from the input table;
|
alpar@1
|
2661 |
\item[\hspace*{54pt}] {\tt OUT} means writing data to the output table;
|
alpar@1
|
2662 |
\item[\hspace*{54pt}] {\it driver} is a symbolic expression, which
|
alpar@1
|
2663 |
specifies the driver used to access the table (for details see Section
|
alpar@1
|
2664 |
\ref{drivers}, page \pageref{drivers});
|
alpar@1
|
2665 |
\item[\hspace*{54pt}] {\it arg} is an optional symbolic expression,
|
alpar@1
|
2666 |
which is an argument pass\-ed to the table driver. This symbolic
|
alpar@1
|
2667 |
expression must not include dummy indices specified in the domain;
|
alpar@1
|
2668 |
\item[\hspace*{54pt}] {\it set} is the name of an optional simple set
|
alpar@1
|
2669 |
called {\it control set}. It can be omitted along with the delimiter
|
alpar@1
|
2670 |
{\tt<-};
|
alpar@1
|
2671 |
\item[\hspace*{54pt}] {\it fld} is a field name. Within square brackets
|
alpar@1
|
2672 |
at least one field should be specified. The field name following
|
alpar@1
|
2673 |
a parameter name or expression is optional and can be omitted along
|
alpar@1
|
2674 |
with the delimiter {\tt\textasciitilde}, in which case the name of
|
alpar@1
|
2675 |
corresponding model object is used as the field name;
|
alpar@1
|
2676 |
\item[\hspace*{54pt}] {\it par} is a symbolic name of a model parameter;
|
alpar@1
|
2677 |
\item[\hspace*{54pt}] {\it expr} is a numeric or symbolic expression.
|
alpar@1
|
2678 |
\end{description}
|
alpar@1
|
2679 |
|
alpar@1
|
2680 |
\newpage
|
alpar@1
|
2681 |
|
alpar@1
|
2682 |
\noindent{\bf Examples}
|
alpar@1
|
2683 |
|
alpar@1
|
2684 |
\begin{verbatim}
|
alpar@1
|
2685 |
table data IN "CSV" "data.csv":
|
alpar@1
|
2686 |
S <- [FROM,TO], d~DISTANCE, c~COST;
|
alpar@1
|
2687 |
table result{(f,t) in S} OUT "CSV" "result.csv":
|
alpar@1
|
2688 |
f~FROM, t~TO, x[f,t]~FLOW;
|
alpar@1
|
2689 |
\end{verbatim}
|
alpar@1
|
2690 |
|
alpar@1
|
2691 |
The table statement allows reading data from a table into model
|
alpar@1
|
2692 |
objects such as sets and (non-scalar) parameters as well as writing
|
alpar@1
|
2693 |
data from the model to a table.
|
alpar@1
|
2694 |
|
alpar@1
|
2695 |
\subsubsection{Table structure}
|
alpar@1
|
2696 |
|
alpar@1
|
2697 |
A {\it data table} is an (unordered) set of {\it records}, where each
|
alpar@1
|
2698 |
record consists of the same number of {\it fields}, and each field is
|
alpar@1
|
2699 |
provided with a unique symbolic name called the {\it field name}. For
|
alpar@1
|
2700 |
example:
|
alpar@1
|
2701 |
|
alpar@1
|
2702 |
\bigskip
|
alpar@1
|
2703 |
|
alpar@1
|
2704 |
\begin{tabular}{@{\hspace*{38mm}}c@{\hspace*{11mm}}c@{\hspace*{10mm}}c
|
alpar@1
|
2705 |
@{\hspace*{9mm}}c}
|
alpar@1
|
2706 |
First&Second&&Last\\
|
alpar@1
|
2707 |
field&field&.\ \ .\ \ .&field\\
|
alpar@1
|
2708 |
$\downarrow$&$\downarrow$&&$\downarrow$\\
|
alpar@1
|
2709 |
\end{tabular}
|
alpar@1
|
2710 |
|
alpar@1
|
2711 |
\begin{tabular}{ll@{}}
|
alpar@1
|
2712 |
Table header&$\rightarrow$\\
|
alpar@1
|
2713 |
First record&$\rightarrow$\\
|
alpar@1
|
2714 |
Second record&$\rightarrow$\\
|
alpar@1
|
2715 |
\\
|
alpar@1
|
2716 |
\hfil .\ \ .\ \ .\\
|
alpar@1
|
2717 |
\\
|
alpar@1
|
2718 |
Last record&$\rightarrow$\\
|
alpar@1
|
2719 |
\end{tabular}
|
alpar@1
|
2720 |
\begin{tabular}{|l|l|c|c|}
|
alpar@1
|
2721 |
\hline
|
alpar@1
|
2722 |
{\tt FROM}&{\tt TO}&{\tt DISTANCE}&{\tt COST}\\
|
alpar@1
|
2723 |
\hline
|
alpar@1
|
2724 |
{\tt Seattle} &{\tt New-York}&{\tt 2.5}&{\tt 0.12}\\
|
alpar@1
|
2725 |
{\tt Seattle} &{\tt Chicago} &{\tt 1.7}&{\tt 0.08}\\
|
alpar@1
|
2726 |
{\tt Seattle} &{\tt Topeka} &{\tt 1.8}&{\tt 0.09}\\
|
alpar@1
|
2727 |
{\tt San-Diego}&{\tt New-York}&{\tt 2.5}&{\tt 0.15}\\
|
alpar@1
|
2728 |
{\tt San-Diego}&{\tt Chicago} &{\tt 1.8}&{\tt 0.10}\\
|
alpar@1
|
2729 |
{\tt San-Diego}&{\tt Topeka} &{\tt 1.4}&{\tt 0.07}\\
|
alpar@1
|
2730 |
\hline
|
alpar@1
|
2731 |
\end{tabular}
|
alpar@1
|
2732 |
|
alpar@1
|
2733 |
\subsubsection{Reading data from input table}
|
alpar@1
|
2734 |
|
alpar@1
|
2735 |
The input table statement causes reading data from the specified table
|
alpar@1
|
2736 |
record by record.
|
alpar@1
|
2737 |
|
alpar@1
|
2738 |
Once a next record has been read, numeric or symbolic values of fields,
|
alpar@1
|
2739 |
whose names are enclosed in square brackets in the table statement, are
|
alpar@1
|
2740 |
gathered into $n$-tuple, and if the control set is specified in the
|
alpar@1
|
2741 |
table statement, this $n$-tuple is added to it. Besides, a numeric or
|
alpar@1
|
2742 |
symbolic value of each field associated with a model parameter is
|
alpar@1
|
2743 |
assigned to the parameter member identified by subscripts, which are
|
alpar@1
|
2744 |
components of the $n$-tuple just read.
|
alpar@1
|
2745 |
|
alpar@1
|
2746 |
For example, the following input table statement:
|
alpar@1
|
2747 |
|
alpar@1
|
2748 |
\medskip
|
alpar@1
|
2749 |
|
alpar@1
|
2750 |
\noindent\hfil
|
alpar@1
|
2751 |
\verb|table data IN "...": S <- [FROM,TO], d~DISTANCE, c~COST;|
|
alpar@1
|
2752 |
|
alpar@1
|
2753 |
\medskip
|
alpar@1
|
2754 |
|
alpar@1
|
2755 |
\noindent
|
alpar@1
|
2756 |
causes reading values of four fields named {\tt FROM}, {\tt TO},
|
alpar@1
|
2757 |
{\tt DISTANCE}, and {\tt COST} from each record of the specified table.
|
alpar@1
|
2758 |
Values of fields {\tt FROM} and {\tt TO} give a pair $(f,t)$, which is
|
alpar@1
|
2759 |
added to the control set {\tt S}. The value of field {\tt DISTANCE} is
|
alpar@1
|
2760 |
assigned to parameter member ${\tt d}[f,t]$, and the value of field
|
alpar@1
|
2761 |
{\tt COST} is assigned to parameter member ${\tt c}[f,t]$.
|
alpar@1
|
2762 |
|
alpar@1
|
2763 |
Note that the input table may contain extra fields whose names are not
|
alpar@1
|
2764 |
specified in the table statement, in which case values of these fields
|
alpar@1
|
2765 |
on reading the table are ignored.
|
alpar@1
|
2766 |
|
alpar@1
|
2767 |
\subsubsection{Writing data to output table}
|
alpar@1
|
2768 |
|
alpar@1
|
2769 |
The output table statement causes writing data to the specified table.
|
alpar@1
|
2770 |
Note that some drivers (namely, CSV and xBASE) destroy the output table
|
alpar@1
|
2771 |
before writing data, i.e. delete all its existing records.
|
alpar@1
|
2772 |
|
alpar@1
|
2773 |
Each $n$-tuple in the specified domain set generates one record written
|
alpar@1
|
2774 |
to the output table. Values of fields are numeric or symbolic values of
|
alpar@1
|
2775 |
corresponding expressions specified in the table statement. These
|
alpar@1
|
2776 |
expressions are evaluated for each $n$-tuple in the domain set and,
|
alpar@1
|
2777 |
thus, may include dummy indices introduced in the corresponding indexing
|
alpar@1
|
2778 |
expression.
|
alpar@1
|
2779 |
|
alpar@1
|
2780 |
For example, the following output table statement:
|
alpar@1
|
2781 |
|
alpar@1
|
2782 |
\medskip
|
alpar@1
|
2783 |
|
alpar@1
|
2784 |
\noindent
|
alpar@1
|
2785 |
\verb| table result{(f,t) in S} OUT "...": f~FROM, t~TO, x[f,t]~FLOW;|
|
alpar@1
|
2786 |
|
alpar@1
|
2787 |
\medskip
|
alpar@1
|
2788 |
|
alpar@1
|
2789 |
\noindent
|
alpar@1
|
2790 |
causes writing records, by one record for each pair $(f,t)$ in set
|
alpar@1
|
2791 |
{\tt S}, to the output table, where each record consists of three
|
alpar@1
|
2792 |
fields named {\tt FROM}, {\tt TO}, and {\tt FLOW}. The values written
|
alpar@1
|
2793 |
to fields {\tt FROM} and {\tt TO} are current values of dummy indices
|
alpar@1
|
2794 |
{\tt f} and {\tt t}, and the value written to field {\tt FLOW} is
|
alpar@1
|
2795 |
a value of member ${\tt x}[f,t]$ of corresponding subscripted parameter
|
alpar@1
|
2796 |
or variable.
|
alpar@1
|
2797 |
|
alpar@1
|
2798 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
alpar@1
|
2799 |
|
alpar@1
|
2800 |
\newpage
|
alpar@1
|
2801 |
|
alpar@1
|
2802 |
\section{Model data}
|
alpar@1
|
2803 |
|
alpar@1
|
2804 |
{\it Model data} include elemental sets, which are ``values'' of model
|
alpar@1
|
2805 |
sets, and numeric and symbolic values of model parameters.
|
alpar@1
|
2806 |
|
alpar@1
|
2807 |
In MathProg there are two different ways to saturate model sets and
|
alpar@1
|
2808 |
parameters with data. One way is simply providing necessary data using
|
alpar@1
|
2809 |
the assign attribute. However, in many cases it is more practical to
|
alpar@1
|
2810 |
separate the model itself and particular data needed for the model. For
|
alpar@1
|
2811 |
the latter reason in MathProg there is another way, when the model
|
alpar@1
|
2812 |
description is divided into two parts: model section and data section.
|
alpar@1
|
2813 |
|
alpar@1
|
2814 |
A {\it model section} is a main part of the model description that
|
alpar@1
|
2815 |
contains declarations of all model objects and is common for all
|
alpar@1
|
2816 |
problems based on that model.
|
alpar@1
|
2817 |
|
alpar@1
|
2818 |
A {\it data section} is an optional part of the model description that
|
alpar@1
|
2819 |
contains model data specific for a particular problem.
|
alpar@1
|
2820 |
|
alpar@1
|
2821 |
In MathProg model and data sections can be placed either in one text
|
alpar@1
|
2822 |
file or in two separate text files.
|
alpar@1
|
2823 |
|
alpar@1
|
2824 |
1. If both model and data sections are placed in one file, the file is
|
alpar@1
|
2825 |
composed as follows:
|
alpar@1
|
2826 |
|
alpar@1
|
2827 |
\bigskip
|
alpar@1
|
2828 |
|
alpar@1
|
2829 |
\noindent\hfil
|
alpar@1
|
2830 |
\framebox{\begin{tabular}{l}
|
alpar@1
|
2831 |
{\it statement}{\tt;}\\
|
alpar@1
|
2832 |
{\it statement}{\tt;}\\
|
alpar@1
|
2833 |
\hfil.\ \ .\ \ .\\
|
alpar@1
|
2834 |
{\it statement}{\tt;}\\
|
alpar@1
|
2835 |
{\tt data;}\\
|
alpar@1
|
2836 |
{\it data block}{\tt;}\\
|
alpar@1
|
2837 |
{\it data block}{\tt;}\\
|
alpar@1
|
2838 |
\hfil.\ \ .\ \ .\\
|
alpar@1
|
2839 |
{\it data block}{\tt;}\\
|
alpar@1
|
2840 |
{\tt end;}
|
alpar@1
|
2841 |
\end{tabular}}
|
alpar@1
|
2842 |
|
alpar@1
|
2843 |
\bigskip
|
alpar@1
|
2844 |
|
alpar@1
|
2845 |
2. If the model and data sections are placed in two separate files, the
|
alpar@1
|
2846 |
files are composed as follows:
|
alpar@1
|
2847 |
|
alpar@1
|
2848 |
\bigskip
|
alpar@1
|
2849 |
|
alpar@1
|
2850 |
\noindent\hfil
|
alpar@1
|
2851 |
\begin{tabular}{@{}c@{}}
|
alpar@1
|
2852 |
\framebox{\begin{tabular}{l}
|
alpar@1
|
2853 |
{\it statement}{\tt;}\\
|
alpar@1
|
2854 |
{\it statement}{\tt;}\\
|
alpar@1
|
2855 |
\hfil.\ \ .\ \ .\\
|
alpar@1
|
2856 |
{\it statement}{\tt;}\\
|
alpar@1
|
2857 |
{\tt end;}\\
|
alpar@1
|
2858 |
\end{tabular}}\\
|
alpar@1
|
2859 |
\\\\Model file\\
|
alpar@1
|
2860 |
\end{tabular}
|
alpar@1
|
2861 |
\hspace{32pt}
|
alpar@1
|
2862 |
\begin{tabular}{@{}c@{}}
|
alpar@1
|
2863 |
\framebox{\begin{tabular}{l}
|
alpar@1
|
2864 |
{\tt data;}\\
|
alpar@1
|
2865 |
{\it data block}{\tt;}\\
|
alpar@1
|
2866 |
{\it data block}{\tt;}\\
|
alpar@1
|
2867 |
\hfil.\ \ .\ \ .\\
|
alpar@1
|
2868 |
{\it data block}{\tt;}\\
|
alpar@1
|
2869 |
{\tt end;}\\
|
alpar@1
|
2870 |
\end{tabular}}\\
|
alpar@1
|
2871 |
\\Data file\\
|
alpar@1
|
2872 |
\end{tabular}
|
alpar@1
|
2873 |
|
alpar@1
|
2874 |
\bigskip
|
alpar@1
|
2875 |
|
alpar@1
|
2876 |
\begin{description}
|
alpar@1
|
2877 |
\item[{\rm Note:}\hspace*{31pt}] If the data section is placed in a
|
alpar@1
|
2878 |
separate file, the keyword {\tt data} is optional and may be omitted
|
alpar@1
|
2879 |
along with the semicolon that follows it.
|
alpar@1
|
2880 |
\end{description}
|
alpar@1
|
2881 |
|
alpar@1
|
2882 |
\subsection{Coding data section}
|
alpar@1
|
2883 |
|
alpar@1
|
2884 |
The {\it data section} is a sequence of data blocks in various formats,
|
alpar@1
|
2885 |
which are discussed in following subsections. The order, in which data
|
alpar@1
|
2886 |
blocks follow in the data section, may be arbitrary, not necessarily
|
alpar@1
|
2887 |
the same, in which corresponding model objects follow in the model
|
alpar@1
|
2888 |
section.
|
alpar@1
|
2889 |
|
alpar@1
|
2890 |
The rules of coding the data section are commonly the same as the rules
|
alpar@1
|
2891 |
of coding the model description (see Subsection \ref{coding}, page
|
alpar@1
|
2892 |
\pageref{coding}), i.e. data blocks are composed from basic lexical
|
alpar@1
|
2893 |
units such as symbolic names, numeric and string literals, keywords,
|
alpar@1
|
2894 |
delimiters, and comments. However, for the sake of convenience and
|
alpar@1
|
2895 |
improving readability there is one deviation from the common rule: if
|
alpar@1
|
2896 |
a string literal consists of only alphanumeric characters (including
|
alpar@1
|
2897 |
the underscore character), the signs {\tt+} and {\tt-}, and/or the
|
alpar@1
|
2898 |
decimal point, it may be coded without bordering by (single or double)
|
alpar@1
|
2899 |
quotes.
|
alpar@1
|
2900 |
|
alpar@1
|
2901 |
All numeric and symbolic material provided in the data section is coded
|
alpar@1
|
2902 |
in the form of numbers and symbols, i.e. unlike the model section
|
alpar@1
|
2903 |
no expressions are allowed in the data section. Nevertheless, the signs
|
alpar@1
|
2904 |
{\tt+} and {\tt-} can precede numeric literals to allow coding signed
|
alpar@1
|
2905 |
numeric quantities, in which case there must be no white-space
|
alpar@1
|
2906 |
characters between the sign and following numeric literal (if there is
|
alpar@1
|
2907 |
at least one white-space, the sign and following numeric literal are
|
alpar@1
|
2908 |
recognized as two different lexical units).
|
alpar@1
|
2909 |
|
alpar@1
|
2910 |
\subsection{Set data block}
|
alpar@1
|
2911 |
|
alpar@1
|
2912 |
\medskip
|
alpar@1
|
2913 |
|
alpar@1
|
2914 |
\framebox[345pt][l]{
|
alpar@1
|
2915 |
\parbox[c][44pt]{345pt}{
|
alpar@1
|
2916 |
\hspace{6pt} {\tt set} {\it name} {\tt,} {\it record} {\tt,} \dots
|
alpar@1
|
2917 |
{\tt,} {\it record} {\tt;}
|
alpar@1
|
2918 |
|
alpar@1
|
2919 |
\medskip
|
alpar@1
|
2920 |
|
alpar@1
|
2921 |
\hspace{6pt} {\tt set} {\it name} {\tt[} {\it symbol} {\tt,} \dots
|
alpar@1
|
2922 |
{\tt,} {\it symbol} {\tt]} {\tt,} {\it record} {\tt,} \dots {\tt,}
|
alpar@1
|
2923 |
{\it record} {\tt;}
|
alpar@1
|
2924 |
}}
|
alpar@1
|
2925 |
|
alpar@1
|
2926 |
\setlength{\leftmargini}{60pt}
|
alpar@1
|
2927 |
|
alpar@1
|
2928 |
\begin{description}
|
alpar@1
|
2929 |
\item[{\rm Where:}\hspace*{23pt}] {\it name} is a symbolic name of the
|
alpar@1
|
2930 |
set;
|
alpar@1
|
2931 |
\item[\hspace*{54pt}] {\it symbol}, \dots, {\it symbol} are subscripts,
|
alpar@1
|
2932 |
which specify a particular member of the set (if the set is an array,
|
alpar@1
|
2933 |
i.e. a set of sets);
|
alpar@1
|
2934 |
\item[\hspace*{54pt}] {\it record}, \dots, {\it record} are data
|
alpar@1
|
2935 |
records.
|
alpar@1
|
2936 |
\end{description}
|
alpar@1
|
2937 |
|
alpar@1
|
2938 |
\begin{description}
|
alpar@1
|
2939 |
\item[{\rm Note:}\hspace*{31pt}] Commae preceding data records may be
|
alpar@1
|
2940 |
omitted.
|
alpar@1
|
2941 |
\end{description}
|
alpar@1
|
2942 |
|
alpar@1
|
2943 |
\noindent Data records:
|
alpar@1
|
2944 |
|
alpar@1
|
2945 |
\begin{description}
|
alpar@1
|
2946 |
\item[{\tt :=}\hspace*{45pt}] is a non-significant data record, which
|
alpar@1
|
2947 |
may be used freely to improve readability;
|
alpar@1
|
2948 |
\item[{\tt(} {\it slice} {\tt)}\hspace*{18.5pt}] specifies a slice;
|
alpar@1
|
2949 |
\item[{\it simple-data}\hspace*{5.5pt}] specifies set data in the
|
alpar@1
|
2950 |
simple format;
|
alpar@1
|
2951 |
\item[{\tt:} {\it matrix-data}]\hspace*{0pt}\\
|
alpar@1
|
2952 |
specifies set data in the matrix format;
|
alpar@1
|
2953 |
\item[{\tt(tr)} {\tt:} {\it matrix-data}]\hspace*{0pt}\\
|
alpar@1
|
2954 |
specifies set data in the transposed matrix format. (In this case the
|
alpar@1
|
2955 |
colon following the keyword {\tt(tr)} may be omitted.)
|
alpar@1
|
2956 |
\end{description}
|
alpar@1
|
2957 |
|
alpar@1
|
2958 |
\noindent{\bf Examples}
|
alpar@1
|
2959 |
|
alpar@1
|
2960 |
\begin{verbatim}
|
alpar@1
|
2961 |
set month := Jan Feb Mar Apr May Jun;
|
alpar@1
|
2962 |
set month "Jan", "Feb", "Mar", "Apr", "May", "Jun";
|
alpar@1
|
2963 |
set A[3,Mar] := (1,2) (2,3) (4,2) (3,1) (2,2) (4,4) (3,4);
|
alpar@1
|
2964 |
set A[3,'Mar'] := 1 2 2 3 4 2 3 1 2 2 4 4 2 4;
|
alpar@1
|
2965 |
set A[3,'Mar'] : 1 2 3 4 :=
|
alpar@1
|
2966 |
1 - + - -
|
alpar@1
|
2967 |
2 - + + -
|
alpar@1
|
2968 |
3 + - - +
|
alpar@1
|
2969 |
4 - + - + ;
|
alpar@1
|
2970 |
set B := (1,2,3) (1,3,2) (2,3,1) (2,1,3) (1,2,2) (1,1,1) (2,1,1);
|
alpar@1
|
2971 |
set B := (*,*,*) 1 2 3, 1 3 2, 2 3 1, 2 1 3, 1 2 2, 1 1 1, 2 1 1;
|
alpar@1
|
2972 |
set B := (1,*,2) 3 2 (2,*,1) 3 1 (1,2,3) (2,1,3) (1,1,1);
|
alpar@1
|
2973 |
set B := (1,*,*) : 1 2 3 :=
|
alpar@1
|
2974 |
1 + - -
|
alpar@1
|
2975 |
2 - + +
|
alpar@1
|
2976 |
3 - + -
|
alpar@1
|
2977 |
(2,*,*) : 1 2 3 :=
|
alpar@1
|
2978 |
1 + - +
|
alpar@1
|
2979 |
2 - - -
|
alpar@1
|
2980 |
3 + - - ;
|
alpar@1
|
2981 |
\end{verbatim}
|
alpar@1
|
2982 |
|
alpar@1
|
2983 |
\noindent(In these examples {\tt month} is a simple set of singlets,
|
alpar@1
|
2984 |
{\tt A} is a 2-dimensional array of doublets, and {\tt B} is a simple
|
alpar@1
|
2985 |
set of triplets. Data blocks for the same set are equivalent in the
|
alpar@1
|
2986 |
sense that they specify the same data in different formats.)
|
alpar@1
|
2987 |
|
alpar@1
|
2988 |
\medskip
|
alpar@1
|
2989 |
|
alpar@1
|
2990 |
The {\it set data block} is used to specify a complete elemental set,
|
alpar@1
|
2991 |
which is assigned to a set (if it is a simple set) or one of its
|
alpar@1
|
2992 |
members (if the set is an array of sets).\footnote{There is another way
|
alpar@1
|
2993 |
to specify data for a simple set along with data for parameters. This
|
alpar@1
|
2994 |
feature is discussed in the next subsection.}
|
alpar@1
|
2995 |
|
alpar@1
|
2996 |
Data blocks can be specified only for non-computable sets, i.e. for
|
alpar@1
|
2997 |
sets, which have no assign ({\tt:=}) attribute in the corresponding set
|
alpar@1
|
2998 |
statements.
|
alpar@1
|
2999 |
|
alpar@1
|
3000 |
If the set is a simple set, only its symbolic name should be specified
|
alpar@1
|
3001 |
in the header of the data block. Otherwise, if the set is a
|
alpar@1
|
3002 |
$n$-dimensional array, its symbolic name should be provided with a
|
alpar@1
|
3003 |
complete list of subscripts separated by commae and enclosed in square
|
alpar@1
|
3004 |
brackets to specify a particular member of the set array. The number of
|
alpar@1
|
3005 |
subscripts must be the same as the dimension of the set array, where
|
alpar@1
|
3006 |
each subscript must be a number or symbol.
|
alpar@1
|
3007 |
|
alpar@1
|
3008 |
An elemental set defined in the set data block is coded as a sequence
|
alpar@1
|
3009 |
of data records described below.\footnote{{\it Data record} is simply a
|
alpar@1
|
3010 |
technical term. It does not mean that data records have any special
|
alpar@1
|
3011 |
formatting.}
|
alpar@1
|
3012 |
|
alpar@1
|
3013 |
\newpage
|
alpar@1
|
3014 |
|
alpar@1
|
3015 |
\subsubsection{Assign data record}
|
alpar@1
|
3016 |
|
alpar@1
|
3017 |
The {\it assign} ({\tt:=}) {\it data record} is a non-signficant
|
alpar@1
|
3018 |
element. It may be used for improving readability of data blocks.
|
alpar@1
|
3019 |
|
alpar@1
|
3020 |
\subsubsection{Slice data record}
|
alpar@1
|
3021 |
|
alpar@1
|
3022 |
The {\it slice data record} is a control record, which specifies a
|
alpar@1
|
3023 |
{\it slice} of the elemental set defined in the data block. It has the
|
alpar@1
|
3024 |
following syntactic form:
|
alpar@1
|
3025 |
|
alpar@1
|
3026 |
\medskip
|
alpar@1
|
3027 |
|
alpar@1
|
3028 |
\noindent\hfil
|
alpar@1
|
3029 |
{\tt(} $s_1$ {\tt,} $s_2$ {\tt,} \dots {\tt,} $s_n$ {\tt)}
|
alpar@1
|
3030 |
|
alpar@1
|
3031 |
\medskip
|
alpar@1
|
3032 |
|
alpar@1
|
3033 |
\noindent where $s_1$, $s_2$, \dots, $s_n$ are components of the slice.
|
alpar@1
|
3034 |
|
alpar@1
|
3035 |
Each component of the slice can be a number or symbol or the asterisk
|
alpar@1
|
3036 |
({\tt*}). The number of components in the slice must be the same as the
|
alpar@1
|
3037 |
dimension of $n$-tuples in the elemental set to be defined. For
|
alpar@1
|
3038 |
instance, if the elemental set contains 4-tuples (quadruplets), the
|
alpar@1
|
3039 |
slice must have four components. The number of asterisks in the slice
|
alpar@1
|
3040 |
is called the {\it slice dimension}.
|
alpar@1
|
3041 |
|
alpar@1
|
3042 |
The effect of using slices is the following. If a $m$-dimensional slice
|
alpar@1
|
3043 |
(i.e. a slice having $m$ asterisks) is specified in the data block, all
|
alpar@1
|
3044 |
subsequent data records must specify tuples of the dimension $m$.
|
alpar@1
|
3045 |
Whenever a $m$-tuple is encountered, each asterisk in the slice is
|
alpar@1
|
3046 |
replaced by corresponding components of the $m$-tuple that gives the
|
alpar@1
|
3047 |
resultant $n$-tuple, which is included in the elemental set to be
|
alpar@1
|
3048 |
defined. For example, if the slice $(a,*,1,2,*)$ is in effect, and
|
alpar@1
|
3049 |
2-tuple $(3,b)$ is encountered in a subsequent data record, the
|
alpar@1
|
3050 |
resultant 5-tuple included in the elemental set is $(a,3,1,2,b)$.
|
alpar@1
|
3051 |
|
alpar@1
|
3052 |
The slice having no asterisks itself defines a complete $n$-tuple,
|
alpar@1
|
3053 |
which is included in the elemental set.
|
alpar@1
|
3054 |
|
alpar@1
|
3055 |
Being once specified the slice effects until either a new slice or the
|
alpar@1
|
3056 |
end of data block is encountered. Note that if no slice is specified in
|
alpar@1
|
3057 |
the data block, one, components of which are all asterisks, is assumed.
|
alpar@1
|
3058 |
|
alpar@1
|
3059 |
\subsubsection{Simple data record}
|
alpar@1
|
3060 |
|
alpar@1
|
3061 |
The {\it simple data record} defines one $n$-tuple in a simple format
|
alpar@1
|
3062 |
and has the following syntactic form:
|
alpar@1
|
3063 |
|
alpar@1
|
3064 |
\medskip
|
alpar@1
|
3065 |
|
alpar@1
|
3066 |
\noindent\hfil
|
alpar@1
|
3067 |
$t_1$ {\tt,} $t_2$ {\tt,} \dots {\tt,} $t_n$
|
alpar@1
|
3068 |
|
alpar@1
|
3069 |
\medskip
|
alpar@1
|
3070 |
|
alpar@1
|
3071 |
\noindent where $t_1$, $t_2$, \dots, $t_n$ are components of the
|
alpar@1
|
3072 |
$n$-tuple. Each component can be a number or symbol. Commae between
|
alpar@1
|
3073 |
components are optional and may be omitted.
|
alpar@1
|
3074 |
|
alpar@1
|
3075 |
\subsubsection{Matrix data record}
|
alpar@1
|
3076 |
|
alpar@1
|
3077 |
The {\it matrix data record} defines several 2-tuples (doublets) in
|
alpar@1
|
3078 |
a matrix format and has the following syntactic form:
|
alpar@1
|
3079 |
|
alpar@1
|
3080 |
\newpage
|
alpar@1
|
3081 |
|
alpar@1
|
3082 |
$$\begin{array}{cccccc}
|
alpar@1
|
3083 |
\mbox{{\tt:}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\
|
alpar@1
|
3084 |
r_1&a_{11}&a_{12}&\dots&a_{1n}&\\
|
alpar@1
|
3085 |
r_2&a_{21}&a_{22}&\dots&a_{2n}&\\
|
alpar@1
|
3086 |
\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\
|
alpar@1
|
3087 |
r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\
|
alpar@1
|
3088 |
\end{array}$$
|
alpar@1
|
3089 |
where $r_1$, $r_2$, \dots, $r_m$ are numbers and/or symbols
|
alpar@1
|
3090 |
corresponding to rows of the matrix; $c_1$, $c_2$, \dots, $c_n$ are
|
alpar@1
|
3091 |
numbers and/or symbols corresponding to columns of the matrix, $a_{11}$,
|
alpar@1
|
3092 |
$a_{12}$, \dots, $a_{mn}$ are matrix elements, which can be either
|
alpar@1
|
3093 |
{\tt+} or {\tt-}. (In this data record the delimiter {\tt:} preceding
|
alpar@1
|
3094 |
the column list and the delimiter {\tt:=} following the column list
|
alpar@1
|
3095 |
cannot be omitted.)
|
alpar@1
|
3096 |
|
alpar@1
|
3097 |
Each element $a_{ij}$ of the matrix data block (where $1\leq i\leq m$,
|
alpar@1
|
3098 |
$1\leq j\leq n$) corresponds to 2-tuple $(r_i,c_j)$. If $a_{ij}$ is the
|
alpar@1
|
3099 |
plus sign ({\tt+}), that 2-tuple (or a longer $n$-tuple, if a slice is
|
alpar@1
|
3100 |
used) is included in the elemental set. Otherwise, if $a_{ij}$ is the
|
alpar@1
|
3101 |
minus sign ({\tt-}), that 2-tuple is not included in the elemental set.
|
alpar@1
|
3102 |
|
alpar@1
|
3103 |
Since the matrix data record defines 2-tuples, either the elemental set
|
alpar@1
|
3104 |
must consist of 2-tuples or the slice currently used must be
|
alpar@1
|
3105 |
2-dimensional.
|
alpar@1
|
3106 |
|
alpar@1
|
3107 |
\subsubsection{Transposed matrix data record}
|
alpar@1
|
3108 |
|
alpar@1
|
3109 |
The {\it transposed matrix data record} has the following syntactic
|
alpar@1
|
3110 |
form:
|
alpar@1
|
3111 |
$$\begin{array}{cccccc}
|
alpar@1
|
3112 |
\mbox{{\tt(tr) :}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\
|
alpar@1
|
3113 |
r_1&a_{11}&a_{12}&\dots&a_{1n}&\\
|
alpar@1
|
3114 |
r_2&a_{21}&a_{22}&\dots&a_{2n}&\\
|
alpar@1
|
3115 |
\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\
|
alpar@1
|
3116 |
r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\
|
alpar@1
|
3117 |
\end{array}$$
|
alpar@1
|
3118 |
(In this case the delimiter {\tt:} following the keyword {\tt(tr)} is
|
alpar@1
|
3119 |
optional and may be omitted.)
|
alpar@1
|
3120 |
|
alpar@1
|
3121 |
This data record is completely analogous to the matrix data record (see
|
alpar@1
|
3122 |
above) with only exception that in this case each element $a_{ij}$ of
|
alpar@1
|
3123 |
the matrix corresponds to 2-tuple $(c_j,r_i)$ rather than $(r_i,c_j)$.
|
alpar@1
|
3124 |
|
alpar@1
|
3125 |
Being once specified the {\tt(tr)} indicator affects all subsequent
|
alpar@1
|
3126 |
data records until either a slice or the end of data block is
|
alpar@1
|
3127 |
encountered.
|
alpar@1
|
3128 |
|
alpar@1
|
3129 |
\subsection{Parameter data block}
|
alpar@1
|
3130 |
|
alpar@1
|
3131 |
\medskip
|
alpar@1
|
3132 |
|
alpar@1
|
3133 |
\framebox[345pt][l]{
|
alpar@1
|
3134 |
\parbox[c][80pt]{345pt}{
|
alpar@1
|
3135 |
\hspace{6pt} {\tt param} {\it name} {\tt,} {\it record} {\tt,} \dots
|
alpar@1
|
3136 |
{\tt,} {\it record} {\tt;}
|
alpar@1
|
3137 |
|
alpar@1
|
3138 |
\medskip
|
alpar@1
|
3139 |
|
alpar@1
|
3140 |
\hspace{6pt} {\tt param} {\it name} {\tt default} {\it value} {\tt,}
|
alpar@1
|
3141 |
{\it record} {\tt,} \dots {\tt,} {\it record} {\tt;}
|
alpar@1
|
3142 |
|
alpar@1
|
3143 |
\medskip
|
alpar@1
|
3144 |
|
alpar@1
|
3145 |
\hspace{6pt} {\tt param} {\tt:} {\it tabbing-data} {\tt;}
|
alpar@1
|
3146 |
|
alpar@1
|
3147 |
\medskip
|
alpar@1
|
3148 |
|
alpar@1
|
3149 |
\hspace{6pt} {\tt param} {\tt default} {\it value} {\tt:}
|
alpar@1
|
3150 |
{\it tabbing-data} {\tt;}
|
alpar@1
|
3151 |
}}
|
alpar@1
|
3152 |
|
alpar@1
|
3153 |
\newpage
|
alpar@1
|
3154 |
|
alpar@1
|
3155 |
\setlength{\leftmargini}{60pt}
|
alpar@1
|
3156 |
|
alpar@1
|
3157 |
\begin{description}
|
alpar@1
|
3158 |
\item[{\rm Where:}\hspace*{23pt}] {\it name} is a symbolic name of the
|
alpar@1
|
3159 |
parameter;
|
alpar@1
|
3160 |
\item[\hspace*{54pt}] {\it value} is an optional default value of the
|
alpar@1
|
3161 |
parameter;
|
alpar@1
|
3162 |
\item[\hspace*{54pt}] {\it record}, \dots, {\it record} are data
|
alpar@1
|
3163 |
records;
|
alpar@1
|
3164 |
\item[\hspace*{54pt}] {\it tabbing-data} specifies parameter data in
|
alpar@1
|
3165 |
the tabbing format.
|
alpar@1
|
3166 |
\end{description}
|
alpar@1
|
3167 |
|
alpar@1
|
3168 |
\begin{description}
|
alpar@1
|
3169 |
\item[{\rm Note:}\hspace*{31pt}] Commae preceding data records may be
|
alpar@1
|
3170 |
omitted.
|
alpar@1
|
3171 |
\end{description}
|
alpar@1
|
3172 |
|
alpar@1
|
3173 |
\noindent Data records:
|
alpar@1
|
3174 |
|
alpar@1
|
3175 |
\begin{description}
|
alpar@1
|
3176 |
\item[{\tt :=}\hspace*{45pt}] is a non-significant data record, which
|
alpar@1
|
3177 |
may be used freely to improve readability;
|
alpar@1
|
3178 |
\item[{\tt[} {\it slice} {\tt]}\hspace*{18.5pt}] specifies a slice;
|
alpar@1
|
3179 |
\item[{\it plain-data}\hspace*{11pt}] specifies parameter data in the
|
alpar@1
|
3180 |
plain format;
|
alpar@1
|
3181 |
\item[{\tt:} {\it tabular-data}]\hspace*{0pt}\\
|
alpar@1
|
3182 |
specifies parameter data in the tabular format;
|
alpar@1
|
3183 |
\item[{\tt(tr)} {\tt:} {\it tabular-data}]\hspace*{0pt}\\
|
alpar@1
|
3184 |
specifies set data in the transposed tabular format. (In this case the
|
alpar@1
|
3185 |
colon following the keyword {\tt(tr)} may be omitted.)
|
alpar@1
|
3186 |
\end{description}
|
alpar@1
|
3187 |
|
alpar@1
|
3188 |
\noindent{\bf Examples}
|
alpar@1
|
3189 |
|
alpar@1
|
3190 |
\begin{verbatim}
|
alpar@1
|
3191 |
param T := 4;
|
alpar@1
|
3192 |
param month := 1 'Jan' 2 'Feb' 3 'Mar' 4 'Apr' 5 'May';
|
alpar@1
|
3193 |
param month := [1] Jan, [2] Feb, [3] Mar, [4] Apr, [5] May;
|
alpar@1
|
3194 |
param day := [Sun] 0, [Mon] 1, [Tue] 2, [Wed] 3, [Thu] 4,
|
alpar@1
|
3195 |
[Fri] 5, [Sat] 6;
|
alpar@1
|
3196 |
param init_stock := iron 7.32 nickel 35.8;
|
alpar@1
|
3197 |
param init_stock [*] iron 7.32, nickel 35.8;
|
alpar@1
|
3198 |
param cost [iron] .025 [nickel] .03;
|
alpar@1
|
3199 |
param value := iron -.1, nickel .02;
|
alpar@1
|
3200 |
param : init_stock cost value :=
|
alpar@1
|
3201 |
iron 7.32 .025 -.1
|
alpar@1
|
3202 |
nickel 35.8 .03 .02 ;
|
alpar@1
|
3203 |
param : raw : init_stock cost value :=
|
alpar@1
|
3204 |
iron 7.32 .025 -.1
|
alpar@1
|
3205 |
nickel 35.8 .03 .02 ;
|
alpar@1
|
3206 |
param demand default 0 (tr)
|
alpar@1
|
3207 |
: FRA DET LAN WIN STL FRE LAF :=
|
alpar@1
|
3208 |
bands 300 . 100 75 . 225 250
|
alpar@1
|
3209 |
coils 500 750 400 250 . 850 500
|
alpar@1
|
3210 |
plate 100 . . 50 200 . 250 ;
|
alpar@1
|
3211 |
\end{verbatim}
|
alpar@1
|
3212 |
|
alpar@1
|
3213 |
\newpage
|
alpar@1
|
3214 |
|
alpar@1
|
3215 |
\begin{verbatim}
|
alpar@1
|
3216 |
param trans_cost :=
|
alpar@1
|
3217 |
[*,*,bands]: FRA DET LAN WIN STL FRE LAF :=
|
alpar@1
|
3218 |
GARY 30 10 8 10 11 71 6
|
alpar@1
|
3219 |
CLEV 22 7 10 7 21 82 13
|
alpar@1
|
3220 |
PITT 19 11 12 10 25 83 15
|
alpar@1
|
3221 |
[*,*,coils]: FRA DET LAN WIN STL FRE LAF :=
|
alpar@1
|
3222 |
GARY 39 14 11 14 16 82 8
|
alpar@1
|
3223 |
CLEV 27 9 12 9 26 95 17
|
alpar@1
|
3224 |
PITT 24 14 17 13 28 99 20
|
alpar@1
|
3225 |
[*,*,plate]: FRA DET LAN WIN STL FRE LAF :=
|
alpar@1
|
3226 |
GARY 41 15 12 16 17 86 8
|
alpar@1
|
3227 |
CLEV 29 9 13 9 28 99 18
|
alpar@1
|
3228 |
PITT 26 14 17 13 31 104 20 ;
|
alpar@1
|
3229 |
\end{verbatim}
|
alpar@1
|
3230 |
|
alpar@1
|
3231 |
The {\it parameter data block} is used to specify complete data for a
|
alpar@1
|
3232 |
parameter (or parameters, if data are specified in the tabbing format).
|
alpar@1
|
3233 |
|
alpar@1
|
3234 |
Data blocks can be specified only for non-computable parameters, i.e.
|
alpar@1
|
3235 |
for parameters, which have no assign ({\tt:=}) attribute in the
|
alpar@1
|
3236 |
corresponding parameter statements.
|
alpar@1
|
3237 |
|
alpar@1
|
3238 |
Data defined in the parameter data block are coded as a sequence of
|
alpar@1
|
3239 |
data records described below. Additionally the data block can be
|
alpar@1
|
3240 |
provided with the optional {\tt default} attribute, which specifies a
|
alpar@1
|
3241 |
default numeric or symbolic value of the parameter (parameters). This
|
alpar@1
|
3242 |
default value is assigned to the parameter or its members, if
|
alpar@1
|
3243 |
no appropriate value is defined in the parameter data block. The
|
alpar@1
|
3244 |
{\tt default} attribute cannot be used, if it is already specified in
|
alpar@1
|
3245 |
the corresponding parameter statement.
|
alpar@1
|
3246 |
|
alpar@1
|
3247 |
\subsubsection{Assign data record}
|
alpar@1
|
3248 |
|
alpar@1
|
3249 |
The {\it assign} ({\tt:=}) {\it data record} is a non-signficant
|
alpar@1
|
3250 |
element. It may be used for improving readability of data blocks.
|
alpar@1
|
3251 |
|
alpar@1
|
3252 |
\subsubsection{Slice data record}
|
alpar@1
|
3253 |
|
alpar@1
|
3254 |
The {\it slice data record} is a control record, which specifies a
|
alpar@1
|
3255 |
{\it slice} of the parameter array. It has the following syntactic form:
|
alpar@1
|
3256 |
|
alpar@1
|
3257 |
\medskip
|
alpar@1
|
3258 |
|
alpar@1
|
3259 |
\noindent\hfil
|
alpar@1
|
3260 |
{\tt[} $s_1$ {\tt,} $s_2$ {\tt,} \dots {\tt,} $s_n$ {\tt]}
|
alpar@1
|
3261 |
|
alpar@1
|
3262 |
\medskip
|
alpar@1
|
3263 |
|
alpar@1
|
3264 |
\noindent where $s_1$, $s_2$, \dots, $s_n$ are components of the slice.
|
alpar@1
|
3265 |
|
alpar@1
|
3266 |
Each component of the slice can be a number or symbol or the asterisk
|
alpar@1
|
3267 |
({\tt*}). The number of components in the slice must be the same as the
|
alpar@1
|
3268 |
dimension of the parameter. For instance, if the parameter is a
|
alpar@1
|
3269 |
4-dimensional array, the slice must have four components. The number of
|
alpar@1
|
3270 |
asterisks in the slice is called the {\it slice dimension}.
|
alpar@1
|
3271 |
|
alpar@1
|
3272 |
The effect of using slices is the following. If a $m$-dimensional slice
|
alpar@1
|
3273 |
(i.e. a slice having $m$ asterisks) is specified in the data block, all
|
alpar@1
|
3274 |
subsequent data records must specify subscripts of the parameter
|
alpar@1
|
3275 |
members as if the parameter were $m$-dimensional, not $n$-dimensional.
|
alpar@1
|
3276 |
|
alpar@1
|
3277 |
Whenever $m$ subscripts are encountered, each asterisk in the slice is
|
alpar@1
|
3278 |
replaced by corresponding subscript that gives $n$ subscripts, which
|
alpar@1
|
3279 |
define the actual parameter member. For example, if the slice
|
alpar@1
|
3280 |
$[a,*,1,2,*]$ is in effect, and subscripts 3 and $b$ are encountered in
|
alpar@1
|
3281 |
a subsequent data record, the complete subscript list used to choose a
|
alpar@1
|
3282 |
parameter member is $[a,3,1,2,b]$.
|
alpar@1
|
3283 |
|
alpar@1
|
3284 |
It is allowed to specify a slice having no asterisks. Such slice itself
|
alpar@1
|
3285 |
defines a complete subscript list, in which case the next data record
|
alpar@1
|
3286 |
should define only a single value of corresponding parameter member.
|
alpar@1
|
3287 |
|
alpar@1
|
3288 |
Being once specified the slice effects until either a new slice or the
|
alpar@1
|
3289 |
end of data block is encountered. Note that if no slice is specified in
|
alpar@1
|
3290 |
the data block, one, components of which are all asterisks, is assumed.
|
alpar@1
|
3291 |
|
alpar@1
|
3292 |
\subsubsection{Plain data record}
|
alpar@1
|
3293 |
|
alpar@1
|
3294 |
The {\it plain data record} defines a subscript list and a single value
|
alpar@1
|
3295 |
in the plain format. This record has the following syntactic form:
|
alpar@1
|
3296 |
|
alpar@1
|
3297 |
\medskip
|
alpar@1
|
3298 |
|
alpar@1
|
3299 |
\noindent\hfil
|
alpar@1
|
3300 |
$t_1$ {\tt,} $t_2$ {\tt,} \dots {\tt,} $t_n$ {\tt,} $v$
|
alpar@1
|
3301 |
|
alpar@1
|
3302 |
\medskip
|
alpar@1
|
3303 |
|
alpar@1
|
3304 |
\noindent where $t_1$, $t_2$, \dots, $t_n$ are subscripts, and $v$ is a
|
alpar@1
|
3305 |
value. Each subscript as well as the value can be a number or symbol.
|
alpar@1
|
3306 |
Commae following subscripts are optional and may be omitted.
|
alpar@1
|
3307 |
|
alpar@1
|
3308 |
In case of 0-dimensional parameter or slice the plain data record has
|
alpar@1
|
3309 |
no subscripts and consists of a single value only.
|
alpar@1
|
3310 |
|
alpar@1
|
3311 |
\subsubsection{Tabular data record}
|
alpar@1
|
3312 |
|
alpar@1
|
3313 |
The {\it tabular data record} defines several values, where each value
|
alpar@1
|
3314 |
is provided with two subscripts. This record has the following
|
alpar@1
|
3315 |
syntactic form:
|
alpar@1
|
3316 |
$$\begin{array}{cccccc}
|
alpar@1
|
3317 |
\mbox{{\tt:}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\
|
alpar@1
|
3318 |
r_1&a_{11}&a_{12}&\dots&a_{1n}&\\
|
alpar@1
|
3319 |
r_2&a_{21}&a_{22}&\dots&a_{2n}&\\
|
alpar@1
|
3320 |
\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\
|
alpar@1
|
3321 |
r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\
|
alpar@1
|
3322 |
\end{array}$$
|
alpar@1
|
3323 |
where $r_1$, $r_2$, \dots, $r_m$ are numbers and/or symbols
|
alpar@1
|
3324 |
corresponding to rows of the table; $c_1$, $c_2$, \dots, $c_n$ are
|
alpar@1
|
3325 |
numbers and/or symbols corresponding to columns of the table, $a_{11}$,
|
alpar@1
|
3326 |
$a_{12}$, \dots, $a_{mn}$ are table elements. Each element can be a
|
alpar@1
|
3327 |
number or symbol or the single decimal point ({\tt.}). (In this data
|
alpar@1
|
3328 |
record the delimiter {\tt:} preceding the column list and the delimiter
|
alpar@1
|
3329 |
{\tt:=} following the column list cannot be omitted.)
|
alpar@1
|
3330 |
|
alpar@1
|
3331 |
Each element $a_{ij}$ of the tabular data block ($1\leq i\leq m$,
|
alpar@1
|
3332 |
$1\leq j\leq n$) defines two subscripts, where the first subscript is
|
alpar@1
|
3333 |
$r_i$, and the second one is $c_j$. These subscripts are used in
|
alpar@1
|
3334 |
conjunction with the current slice to form the complete subscript list
|
alpar@1
|
3335 |
that identifies a particular member of the parameter array. If $a_{ij}$
|
alpar@1
|
3336 |
is a number or symbol, this value is assigned to the parameter member.
|
alpar@1
|
3337 |
However, if $a_{ij}$ is the single decimal point, the member is
|
alpar@1
|
3338 |
assigned a default value specified either in the parameter data block
|
alpar@1
|
3339 |
or in the parameter statement, or, if no default value is specified,
|
alpar@1
|
3340 |
the member remains undefined.
|
alpar@1
|
3341 |
|
alpar@1
|
3342 |
Since the tabular data record provides two subscripts for each value,
|
alpar@1
|
3343 |
either the parameter or the slice currently used must be 2-dimensional.
|
alpar@1
|
3344 |
|
alpar@1
|
3345 |
\subsubsection{Transposed tabular data record}
|
alpar@1
|
3346 |
|
alpar@1
|
3347 |
The {\it transposed tabular data record} has the following syntactic
|
alpar@1
|
3348 |
form:
|
alpar@1
|
3349 |
$$\begin{array}{cccccc}
|
alpar@1
|
3350 |
\mbox{{\tt(tr) :}}&c_1&c_2&\dots&c_n&\mbox{{\tt:=}}\\
|
alpar@1
|
3351 |
r_1&a_{11}&a_{12}&\dots&a_{1n}&\\
|
alpar@1
|
3352 |
r_2&a_{21}&a_{22}&\dots&a_{2n}&\\
|
alpar@1
|
3353 |
\multicolumn{5}{c}{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}&\\
|
alpar@1
|
3354 |
r_m&a_{m1}&a_{m2}&\dots&a_{mn}&\\
|
alpar@1
|
3355 |
\end{array}$$
|
alpar@1
|
3356 |
(In this case the delimiter {\tt:} following the keyword {\tt(tr)} is
|
alpar@1
|
3357 |
optional and may be omitted.)
|
alpar@1
|
3358 |
|
alpar@1
|
3359 |
This data record is completely analogous to the tabular data record
|
alpar@1
|
3360 |
(see above) with only exception that the first subscript defined by
|
alpar@1
|
3361 |
element $a_{ij}$ is $c_j$ while the second one is $r_i$.
|
alpar@1
|
3362 |
|
alpar@1
|
3363 |
Being once specified the {\tt(tr)} indicator affects all subsequent
|
alpar@1
|
3364 |
data records until either a slice or the end of data block is
|
alpar@1
|
3365 |
encountered.
|
alpar@1
|
3366 |
|
alpar@1
|
3367 |
\subsubsection{Tabbing data format}
|
alpar@1
|
3368 |
|
alpar@1
|
3369 |
The parameter data block in the {\it tabbing format} has the following
|
alpar@1
|
3370 |
syntactic form:
|
alpar@1
|
3371 |
$$\begin{array}{p{12pt}@{\ }l@{\ }c@{\ }l@{\ }c@{\ }l@{\ }r@{\ }l@{\ }c
|
alpar@1
|
3372 |
@{\ }l@{\ }c@{\ }l@{\ }l}
|
alpar@1
|
3373 |
\multicolumn{7}{@{}c@{}}{\mbox{\tt param}\ \mbox{\tt default}\ \mbox
|
alpar@1
|
3374 |
{\it value}\ \mbox{\tt:}\ \mbox{\it s}\ \mbox{\tt:}}&
|
alpar@1
|
3375 |
p_1&\mbox{\tt,}&p_2&\mbox{\tt,} \dots \mbox{\tt,}&p_k&\mbox{\tt:=}\\
|
alpar@1
|
3376 |
&t_{11}&\mbox{\tt,}&t_{12}&\mbox{\tt,} \dots \mbox{\tt,}&t_{1n}&
|
alpar@1
|
3377 |
\mbox{\tt,}&a_{11}&\mbox{\tt,}&a_{12}&\mbox{\tt,} \dots \mbox{\tt,}&
|
alpar@1
|
3378 |
a_{1k}\\
|
alpar@1
|
3379 |
&t_{21}&\mbox{\tt,}&t_{22}&\mbox{\tt,} \dots \mbox{\tt,}&t_{2n}&
|
alpar@1
|
3380 |
\mbox{\tt,}&a_{21}&\mbox{\tt,}&a_{22}&\mbox{\tt,} \dots \mbox{\tt,}&
|
alpar@1
|
3381 |
a_{2k}\\
|
alpar@1
|
3382 |
\multicolumn{13}{c}
|
alpar@1
|
3383 |
{.\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .\ \ .}\\
|
alpar@1
|
3384 |
&t_{m1}&\mbox{\tt,}&t_{m2}&\mbox{\tt,} \dots \mbox{\tt,}&t_{mn}&
|
alpar@1
|
3385 |
\mbox{\tt,}&a_{m1}&\mbox{\tt,}&a_{m2}&\mbox{\tt,} \dots \mbox{\tt,}&
|
alpar@1
|
3386 |
a_{mk}&\mbox{\tt;}\\
|
alpar@1
|
3387 |
\end{array}$$
|
alpar@1
|
3388 |
|
alpar@1
|
3389 |
{\it Notes:}
|
alpar@1
|
3390 |
|
alpar@1
|
3391 |
1. The keyword {\tt default} may be omitted along with a value
|
alpar@1
|
3392 |
following it.
|
alpar@1
|
3393 |
|
alpar@1
|
3394 |
2. Symbolic name {\tt s} may be omitted along with the colon following
|
alpar@1
|
3395 |
it.
|
alpar@1
|
3396 |
|
alpar@1
|
3397 |
3. All comae are optional and may be omitted.
|
alpar@1
|
3398 |
|
alpar@1
|
3399 |
\medskip
|
alpar@1
|
3400 |
|
alpar@1
|
3401 |
The data block in the tabbing format shown above is exactly equivalent
|
alpar@1
|
3402 |
to the following data blocks for $j=1,2,\dots,k$:
|
alpar@1
|
3403 |
|
alpar@1
|
3404 |
\medskip
|
alpar@1
|
3405 |
|
alpar@1
|
3406 |
{\tt set} {\it s} {\tt:=}
|
alpar@1
|
3407 |
{\tt(}$t_{11}${\tt,}$t_{12}${\tt,}\dots{\tt,}$t_{1n}${\tt)}
|
alpar@1
|
3408 |
{\tt(}$t_{21}${\tt,}$t_{22}${\tt,}\dots{\tt,}$t_{2n}${\tt)} \dots
|
alpar@1
|
3409 |
{\tt(}$t_{m1}${\tt,}$t_{m2}${\tt,}\dots{\tt,}$t_{mn}${\tt)} {\tt;}
|
alpar@1
|
3410 |
|
alpar@1
|
3411 |
{\tt param} $p_j$ {\tt default} {\it value} {\tt:=}
|
alpar@1
|
3412 |
|
alpar@1
|
3413 |
$\!${\tt[}$t_{11}${\tt,}$t_{12}${\tt,}\dots{\tt,}$t_{1n}${\tt]}
|
alpar@1
|
3414 |
$a_{1j}$
|
alpar@1
|
3415 |
{\tt[}$t_{21}${\tt,}$t_{22}${\tt,}\dots{\tt,}$t_{2n}${\tt]} $a_{2j}$
|
alpar@1
|
3416 |
\dots
|
alpar@1
|
3417 |
{\tt[}$t_{m1}${\tt,}$t_{m2}${\tt,}\dots{\tt,}$t_{mn}${\tt]} $a_{mj}$
|
alpar@1
|
3418 |
{\tt;}
|
alpar@1
|
3419 |
|
alpar@1
|
3420 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
alpar@1
|
3421 |
|
alpar@1
|
3422 |
\appendix
|
alpar@1
|
3423 |
|
alpar@1
|
3424 |
\newpage
|
alpar@1
|
3425 |
|
alpar@1
|
3426 |
\section{Using suffixes}
|
alpar@1
|
3427 |
|
alpar@1
|
3428 |
Suffixes can be used to retrieve additional values associated with
|
alpar@1
|
3429 |
model variables, constraints, and objectives.
|
alpar@1
|
3430 |
|
alpar@1
|
3431 |
A {\it suffix} consists of a period ({\tt.}) followed by a non-reserved
|
alpar@1
|
3432 |
keyword. For example, if {\tt x} is a two-dimensional variable,
|
alpar@1
|
3433 |
{\tt x[i,j].lb} is a numeric value equal to the lower bound of
|
alpar@1
|
3434 |
elemental variable {\tt x[i,j]}, which (value) can be used everywhere
|
alpar@1
|
3435 |
in expressions like a numeric parameter.
|
alpar@1
|
3436 |
|
alpar@1
|
3437 |
For model variables suffixes have the following meaning:
|
alpar@1
|
3438 |
|
alpar@1
|
3439 |
\medskip
|
alpar@1
|
3440 |
|
alpar@1
|
3441 |
\begin{tabular}{@{}p{96pt}p{222pt}@{}}
|
alpar@1
|
3442 |
{\tt.lb}&lower bound\\
|
alpar@1
|
3443 |
{\tt.ub}&upper bound\\
|
alpar@1
|
3444 |
{\tt.status}&status in the solution:\\
|
alpar@1
|
3445 |
&0 --- undefined\\
|
alpar@1
|
3446 |
&1 --- basic\\
|
alpar@1
|
3447 |
&2 --- non-basic on lower bound\\
|
alpar@1
|
3448 |
&3 --- non-basic on upper bound\\
|
alpar@1
|
3449 |
&4 --- non-basic free (unbounded) variable\\
|
alpar@1
|
3450 |
&5 --- non-basic fixed variable\\
|
alpar@1
|
3451 |
{\tt.val}&primal value in the solution\\
|
alpar@1
|
3452 |
{\tt.dual}&dual value (reduced cost) in the solution\\
|
alpar@1
|
3453 |
\end{tabular}
|
alpar@1
|
3454 |
|
alpar@1
|
3455 |
\medskip
|
alpar@1
|
3456 |
|
alpar@1
|
3457 |
For model constraints and objectives suffixes have the following
|
alpar@1
|
3458 |
meaning:
|
alpar@1
|
3459 |
|
alpar@1
|
3460 |
\medskip
|
alpar@1
|
3461 |
|
alpar@1
|
3462 |
\begin{tabular}{@{}p{96pt}p{222pt}@{}}
|
alpar@1
|
3463 |
{\tt.lb}&lower bound of the linear form\\
|
alpar@1
|
3464 |
{\tt.ub}&upper bound of the linear form\\
|
alpar@1
|
3465 |
{\tt.status}&status in the solution:\\
|
alpar@1
|
3466 |
&0 --- undefined\\
|
alpar@1
|
3467 |
&1 --- non-active\\
|
alpar@1
|
3468 |
&2 --- active on lower bound\\
|
alpar@1
|
3469 |
&3 --- active on upper bound\\
|
alpar@1
|
3470 |
&4 --- active free (unbounded) row\\
|
alpar@1
|
3471 |
&5 --- active equality constraint\\
|
alpar@1
|
3472 |
{\tt.val}&primal value of the linear form in the solution\\
|
alpar@1
|
3473 |
{\tt.dual}&dual value (reduced cost) of the linear form in the
|
alpar@1
|
3474 |
solution\\
|
alpar@1
|
3475 |
\end{tabular}
|
alpar@1
|
3476 |
|
alpar@1
|
3477 |
\medskip
|
alpar@1
|
3478 |
|
alpar@1
|
3479 |
Note that suffixes {\tt.status}, {\tt.val}, and {\tt.dual} can be used
|
alpar@1
|
3480 |
only below the solve statement.
|
alpar@1
|
3481 |
|
alpar@1
|
3482 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
alpar@1
|
3483 |
|
alpar@1
|
3484 |
\newpage
|
alpar@1
|
3485 |
|
alpar@1
|
3486 |
\section{Date and time functions}
|
alpar@1
|
3487 |
|
alpar@1
|
3488 |
\noindent\hfil
|
alpar@1
|
3489 |
by Andrew Makhorin \verb|<mao@gnu.org>|
|
alpar@1
|
3490 |
|
alpar@1
|
3491 |
\noindent\hfil
|
alpar@1
|
3492 |
and Heinrich Schuchardt \verb|<heinrich.schuchardt@gmx.de>|
|
alpar@1
|
3493 |
|
alpar@1
|
3494 |
\subsection{Obtaining current calendar time}
|
alpar@1
|
3495 |
\label{gmtime}
|
alpar@1
|
3496 |
|
alpar@1
|
3497 |
To obtain the current calendar time in MathProg there exists the
|
alpar@1
|
3498 |
function {\tt gmtime}. It has no arguments and returns the number of
|
alpar@1
|
3499 |
seconds elapsed since 00:00:00 on January 1, 1970, Coordinated
|
alpar@1
|
3500 |
Universal Time (UTC). For example:
|
alpar@1
|
3501 |
|
alpar@1
|
3502 |
\medskip
|
alpar@1
|
3503 |
|
alpar@1
|
3504 |
\verb| param utc := gmtime();|
|
alpar@1
|
3505 |
|
alpar@1
|
3506 |
\medskip
|
alpar@1
|
3507 |
|
alpar@1
|
3508 |
MathProg has no function to convert UTC time returned by the function
|
alpar@1
|
3509 |
{\tt gmtime} to {\it local} calendar times. Thus, if you need to
|
alpar@1
|
3510 |
determine the current local calendar time, you have to add to the UTC
|
alpar@1
|
3511 |
time returned the time offset from UTC expressed in seconds. For
|
alpar@1
|
3512 |
example, the time in Berlin during the winter is one hour ahead of UTC
|
alpar@1
|
3513 |
that corresponds to the time offset +1 hour = +3600 secs, so the
|
alpar@1
|
3514 |
current winter calendar time in Berlin may be determined as follows:
|
alpar@1
|
3515 |
|
alpar@1
|
3516 |
\medskip
|
alpar@1
|
3517 |
|
alpar@1
|
3518 |
\verb| param now := gmtime() + 3600;|
|
alpar@1
|
3519 |
|
alpar@1
|
3520 |
\medskip
|
alpar@1
|
3521 |
|
alpar@1
|
3522 |
\noindent Similarly, the summer time in Chicago (Central Daylight Time)
|
alpar@1
|
3523 |
is five hours behind UTC, so the corresponding current local calendar
|
alpar@1
|
3524 |
time may be determined as follows:
|
alpar@1
|
3525 |
|
alpar@1
|
3526 |
\medskip
|
alpar@1
|
3527 |
|
alpar@1
|
3528 |
\verb| param now := gmtime() - 5 * 3600;|
|
alpar@1
|
3529 |
|
alpar@1
|
3530 |
\medskip
|
alpar@1
|
3531 |
|
alpar@1
|
3532 |
Note that the value returned by {\tt gmtime} is volatile, i.e. being
|
alpar@1
|
3533 |
called several times this function may return different values.
|
alpar@1
|
3534 |
|
alpar@1
|
3535 |
\subsection{Converting character string to calendar time}
|
alpar@1
|
3536 |
\label{str2time}
|
alpar@1
|
3537 |
|
alpar@1
|
3538 |
The function {\tt str2time(}{\it s}{\tt,} {\it f}{\tt)} converts a
|
alpar@1
|
3539 |
character string (timestamp) specified by its first argument {\it s},
|
alpar@1
|
3540 |
which must be a symbolic expression, to the calendar time suitable for
|
alpar@1
|
3541 |
arithmetic calculations. The conversion is controlled by the specified
|
alpar@1
|
3542 |
format string {\it f} (the second argument), which also must be a
|
alpar@1
|
3543 |
symbolic expression.
|
alpar@1
|
3544 |
|
alpar@1
|
3545 |
The result of conversion returned by {\tt str2time} has the same
|
alpar@1
|
3546 |
meaning as values returned by the function {\tt gmtime} (see Subsection
|
alpar@1
|
3547 |
\ref{gmtime}, page \pageref{gmtime}). Note that {\tt str2time} does
|
alpar@1
|
3548 |
{\tt not} correct the calendar time returned for the local timezone,
|
alpar@1
|
3549 |
i.e. being applied to 00:00:00 on January 1, 1970 it always returns 0.
|
alpar@1
|
3550 |
|
alpar@1
|
3551 |
For example, the model statements:
|
alpar@1
|
3552 |
|
alpar@1
|
3553 |
\medskip
|
alpar@1
|
3554 |
|
alpar@1
|
3555 |
\verb| param s, symbolic, := "07/14/98 13:47";|
|
alpar@1
|
3556 |
|
alpar@1
|
3557 |
\verb| param t := str2time(s, "%m/%d/%y %H:%M");|
|
alpar@1
|
3558 |
|
alpar@1
|
3559 |
\verb| display t;|
|
alpar@1
|
3560 |
|
alpar@1
|
3561 |
\medskip
|
alpar@1
|
3562 |
|
alpar@1
|
3563 |
\noindent produce the following printout:
|
alpar@1
|
3564 |
|
alpar@1
|
3565 |
\medskip
|
alpar@1
|
3566 |
|
alpar@1
|
3567 |
\verb| t = 900424020|
|
alpar@1
|
3568 |
|
alpar@1
|
3569 |
\medskip
|
alpar@1
|
3570 |
|
alpar@1
|
3571 |
\noindent where the calendar time printed corresponds to 13:47:00 on
|
alpar@1
|
3572 |
July 14, 1998.
|
alpar@1
|
3573 |
|
alpar@1
|
3574 |
\newpage
|
alpar@1
|
3575 |
|
alpar@1
|
3576 |
The format string passed to the function {\tt str2time} consists of
|
alpar@1
|
3577 |
conversion specifiers and ordinary characters. Each conversion
|
alpar@1
|
3578 |
specifier begins with a percent ({\tt\%}) character followed by a
|
alpar@1
|
3579 |
letter.
|
alpar@1
|
3580 |
|
alpar@1
|
3581 |
The following conversion specifiers may be used in the format string:
|
alpar@1
|
3582 |
|
alpar@1
|
3583 |
\medskip
|
alpar@1
|
3584 |
|
alpar@1
|
3585 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3586 |
{\tt\%b}&The abbreviated month name (case insensitive). At least three
|
alpar@1
|
3587 |
first letters of the month name must appear in the input string.\\
|
alpar@1
|
3588 |
\end{tabular}
|
alpar@1
|
3589 |
|
alpar@1
|
3590 |
\medskip
|
alpar@1
|
3591 |
|
alpar@1
|
3592 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3593 |
{\tt\%d}&The day of the month as a decimal number (range 1 to 31).
|
alpar@1
|
3594 |
Leading zero is permitted, but not required.\\
|
alpar@1
|
3595 |
\end{tabular}
|
alpar@1
|
3596 |
|
alpar@1
|
3597 |
\medskip
|
alpar@1
|
3598 |
|
alpar@1
|
3599 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3600 |
{\tt\%h}&The same as {\tt\%b}.\\
|
alpar@1
|
3601 |
\end{tabular}
|
alpar@1
|
3602 |
|
alpar@1
|
3603 |
\medskip
|
alpar@1
|
3604 |
|
alpar@1
|
3605 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3606 |
{\tt\%H}&The hour as a decimal number, using a 24-hour clock (range 0
|
alpar@1
|
3607 |
to 23). Leading zero is permitted, but not required.\\
|
alpar@1
|
3608 |
\end{tabular}
|
alpar@1
|
3609 |
|
alpar@1
|
3610 |
\medskip
|
alpar@1
|
3611 |
|
alpar@1
|
3612 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3613 |
{\tt\%m}&The month as a decimal number (range 1 to 12). Leading zero is
|
alpar@1
|
3614 |
permitted, but not required.\\
|
alpar@1
|
3615 |
\end{tabular}
|
alpar@1
|
3616 |
|
alpar@1
|
3617 |
\medskip
|
alpar@1
|
3618 |
|
alpar@1
|
3619 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3620 |
{\tt\%M}&The minute as a decimal number (range 0 to 59). Leading zero
|
alpar@1
|
3621 |
is permitted, but not required.\\
|
alpar@1
|
3622 |
\end{tabular}
|
alpar@1
|
3623 |
|
alpar@1
|
3624 |
\medskip
|
alpar@1
|
3625 |
|
alpar@1
|
3626 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3627 |
{\tt\%S}&The second as a decimal number (range 0 to 60). Leading zero
|
alpar@1
|
3628 |
is permitted, but not required.\\
|
alpar@1
|
3629 |
\end{tabular}
|
alpar@1
|
3630 |
|
alpar@1
|
3631 |
\medskip
|
alpar@1
|
3632 |
|
alpar@1
|
3633 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3634 |
{\tt\%y}&The year without a century as a decimal number (range 0 to 99).
|
alpar@1
|
3635 |
Leading zero is permitted, but not required. Input values in the range
|
alpar@1
|
3636 |
0 to 68 are considered as the years 2000 to 2068 while the values 69 to
|
alpar@1
|
3637 |
99 as the years 1969 to 1999.\\
|
alpar@1
|
3638 |
\end{tabular}
|
alpar@1
|
3639 |
|
alpar@1
|
3640 |
\medskip
|
alpar@1
|
3641 |
|
alpar@1
|
3642 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3643 |
{\tt\%z}&The offset from GMT in ISO 8601 format.\\
|
alpar@1
|
3644 |
\end{tabular}
|
alpar@1
|
3645 |
|
alpar@1
|
3646 |
\medskip
|
alpar@1
|
3647 |
|
alpar@1
|
3648 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3649 |
{\tt\%\%}&A literal {\tt\%} character.\\
|
alpar@1
|
3650 |
\end{tabular}
|
alpar@1
|
3651 |
|
alpar@1
|
3652 |
\medskip
|
alpar@1
|
3653 |
|
alpar@1
|
3654 |
All other (ordinary) characters in the format string must have a
|
alpar@1
|
3655 |
matching character in the input string to be converted. Exceptions are
|
alpar@1
|
3656 |
spaces in the input string which can match zero or more space
|
alpar@1
|
3657 |
characters in the format string.
|
alpar@1
|
3658 |
|
alpar@1
|
3659 |
If some date and/or time component(s) are missing in the format and,
|
alpar@1
|
3660 |
therefore, in the input string, the function {\tt str2time} uses their
|
alpar@1
|
3661 |
default values corresponding to 00:00:00 on January 1, 1970, that is,
|
alpar@1
|
3662 |
the default value of the year is 1970, the default value of the month
|
alpar@1
|
3663 |
is January, etc.
|
alpar@1
|
3664 |
|
alpar@1
|
3665 |
The function {\tt str2time} is applicable to all calendar times in the
|
alpar@1
|
3666 |
range 00:00:00 on January 1, 0001 to 23:59:59 on December 31, 4000 of
|
alpar@1
|
3667 |
the Gregorian calendar.
|
alpar@1
|
3668 |
|
alpar@1
|
3669 |
\subsection{Converting calendar time to character string}
|
alpar@1
|
3670 |
\label{time2str}
|
alpar@1
|
3671 |
|
alpar@1
|
3672 |
The function {\tt time2str(}{\it t}{\tt,} {\it f}{\tt)} converts the
|
alpar@1
|
3673 |
calendar time specified by its first argument {\it t}, which must be a
|
alpar@1
|
3674 |
numeric expression, to a character string (symbolic value). The
|
alpar@1
|
3675 |
conversion is controlled by the specified format string {\it f} (the
|
alpar@1
|
3676 |
second argument), which must be a symbolic expression.
|
alpar@1
|
3677 |
|
alpar@1
|
3678 |
The calendar time passed to {\tt time2str} has the same meaning as
|
alpar@1
|
3679 |
values returned by the function {\tt gmtime} (see Subsection
|
alpar@1
|
3680 |
\ref{gmtime}, page \pageref{gmtime}). Note that {\tt time2str} does
|
alpar@1
|
3681 |
{\it not} correct the specified calendar time for the local timezone,
|
alpar@1
|
3682 |
i.e. the calendar time 0 always corresponds to 00:00:00 on January 1,
|
alpar@1
|
3683 |
1970.
|
alpar@1
|
3684 |
|
alpar@1
|
3685 |
For example, the model statements:
|
alpar@1
|
3686 |
|
alpar@1
|
3687 |
\medskip
|
alpar@1
|
3688 |
|
alpar@1
|
3689 |
\verb| param s, symbolic, := time2str(gmtime(), "%FT%TZ");|
|
alpar@1
|
3690 |
|
alpar@1
|
3691 |
\verb| display s;|
|
alpar@1
|
3692 |
|
alpar@1
|
3693 |
\medskip
|
alpar@1
|
3694 |
|
alpar@1
|
3695 |
\noindent may produce the following printout:
|
alpar@1
|
3696 |
|
alpar@1
|
3697 |
\medskip
|
alpar@1
|
3698 |
|
alpar@1
|
3699 |
\verb| s = '2008-12-04T00:23:45Z'|
|
alpar@1
|
3700 |
|
alpar@1
|
3701 |
\medskip
|
alpar@1
|
3702 |
|
alpar@1
|
3703 |
\noindent which is a timestamp in the ISO format.
|
alpar@1
|
3704 |
|
alpar@1
|
3705 |
The format string passed to the function {\tt time2str} consists of
|
alpar@1
|
3706 |
conversion specifiers and ordinary characters. Each conversion
|
alpar@1
|
3707 |
specifier begins with a percent ({\tt\%}) character followed by a
|
alpar@1
|
3708 |
letter.
|
alpar@1
|
3709 |
|
alpar@1
|
3710 |
The following conversion specifiers may be used in the format string:
|
alpar@1
|
3711 |
|
alpar@1
|
3712 |
\medskip
|
alpar@1
|
3713 |
|
alpar@1
|
3714 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3715 |
{\tt\%a}&The abbreviated (2-character) weekday name.\\
|
alpar@1
|
3716 |
\end{tabular}
|
alpar@1
|
3717 |
|
alpar@1
|
3718 |
\medskip
|
alpar@1
|
3719 |
|
alpar@1
|
3720 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3721 |
{\tt\%A}&The full weekday name.\\
|
alpar@1
|
3722 |
\end{tabular}
|
alpar@1
|
3723 |
|
alpar@1
|
3724 |
\medskip
|
alpar@1
|
3725 |
|
alpar@1
|
3726 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3727 |
{\tt\%b}&The abbreviated (3-character) month name.\\
|
alpar@1
|
3728 |
\end{tabular}
|
alpar@1
|
3729 |
|
alpar@1
|
3730 |
\medskip
|
alpar@1
|
3731 |
|
alpar@1
|
3732 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3733 |
{\tt\%B}&The full month name.\\
|
alpar@1
|
3734 |
\end{tabular}
|
alpar@1
|
3735 |
|
alpar@1
|
3736 |
\medskip
|
alpar@1
|
3737 |
|
alpar@1
|
3738 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3739 |
{\tt\%C}&The century of the year, that is the greatest integer not
|
alpar@1
|
3740 |
greater than the year divided by 100.\\
|
alpar@1
|
3741 |
\end{tabular}
|
alpar@1
|
3742 |
|
alpar@1
|
3743 |
\medskip
|
alpar@1
|
3744 |
|
alpar@1
|
3745 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3746 |
{\tt\%d}&The day of the month as a decimal number (range 01 to 31).\\
|
alpar@1
|
3747 |
\end{tabular}
|
alpar@1
|
3748 |
|
alpar@1
|
3749 |
\medskip
|
alpar@1
|
3750 |
|
alpar@1
|
3751 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3752 |
{\tt\%D}&The date using the format \verb|%m/%d/%y|.\\
|
alpar@1
|
3753 |
\end{tabular}
|
alpar@1
|
3754 |
|
alpar@1
|
3755 |
\medskip
|
alpar@1
|
3756 |
|
alpar@1
|
3757 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3758 |
{\tt\%e}&The day of the month like with \verb|%d|, but padded with
|
alpar@1
|
3759 |
blank rather than zero.\\
|
alpar@1
|
3760 |
\end{tabular}
|
alpar@1
|
3761 |
|
alpar@1
|
3762 |
\medskip
|
alpar@1
|
3763 |
|
alpar@1
|
3764 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3765 |
{\tt\%F}&The date using the format \verb|%Y-%m-%d|.\\
|
alpar@1
|
3766 |
\end{tabular}
|
alpar@1
|
3767 |
|
alpar@1
|
3768 |
\medskip
|
alpar@1
|
3769 |
|
alpar@1
|
3770 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3771 |
{\tt\%g}&The year corresponding to the ISO week number, but without the
|
alpar@1
|
3772 |
century (range 00 to 99). This has the same format and value as
|
alpar@1
|
3773 |
\verb|%y|, except that if the ISO week number (see \verb|%V|) belongs
|
alpar@1
|
3774 |
to the previous or next year, that year is used instead.\\
|
alpar@1
|
3775 |
\end{tabular}
|
alpar@1
|
3776 |
|
alpar@1
|
3777 |
\medskip
|
alpar@1
|
3778 |
|
alpar@1
|
3779 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3780 |
{\tt\%G}&The year corresponding to the ISO week number. This has the
|
alpar@1
|
3781 |
same format and value as \verb|%Y|, except that if the ISO week number
|
alpar@1
|
3782 |
(see \verb|%V|) belongs to the previous or next year, that year is used
|
alpar@1
|
3783 |
instead.
|
alpar@1
|
3784 |
\end{tabular}
|
alpar@1
|
3785 |
|
alpar@1
|
3786 |
\medskip
|
alpar@1
|
3787 |
|
alpar@1
|
3788 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3789 |
{\tt\%h}&The same as \verb|%b|.\\
|
alpar@1
|
3790 |
\end{tabular}
|
alpar@1
|
3791 |
|
alpar@1
|
3792 |
\medskip
|
alpar@1
|
3793 |
|
alpar@1
|
3794 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3795 |
{\tt\%H}&The hour as a decimal number, using a 24-hour clock (range 00
|
alpar@1
|
3796 |
to 23).\\
|
alpar@1
|
3797 |
\end{tabular}
|
alpar@1
|
3798 |
|
alpar@1
|
3799 |
\medskip
|
alpar@1
|
3800 |
|
alpar@1
|
3801 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3802 |
{\tt\%I}&The hour as a decimal number, using a 12-hour clock (range 01
|
alpar@1
|
3803 |
to 12).\\
|
alpar@1
|
3804 |
\end{tabular}
|
alpar@1
|
3805 |
|
alpar@1
|
3806 |
\medskip
|
alpar@1
|
3807 |
|
alpar@1
|
3808 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3809 |
{\tt\%j}&The day of the year as a decimal number (range 001 to 366).\\
|
alpar@1
|
3810 |
\end{tabular}
|
alpar@1
|
3811 |
|
alpar@1
|
3812 |
\medskip
|
alpar@1
|
3813 |
|
alpar@1
|
3814 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3815 |
{\tt\%k}&The hour as a decimal number, using a 24-hour clock like
|
alpar@1
|
3816 |
\verb|%H|, but padded with blank rather than zero.\\
|
alpar@1
|
3817 |
\end{tabular}
|
alpar@1
|
3818 |
|
alpar@1
|
3819 |
\medskip
|
alpar@1
|
3820 |
|
alpar@1
|
3821 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3822 |
{\tt\%l}&The hour as a decimal number, using a 12-hour clock like
|
alpar@1
|
3823 |
\verb|%I|, but padded with blank rather than zero.
|
alpar@1
|
3824 |
\end{tabular}
|
alpar@1
|
3825 |
|
alpar@1
|
3826 |
\medskip
|
alpar@1
|
3827 |
|
alpar@1
|
3828 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3829 |
{\tt\%m}&The month as a decimal number (range 01 to 12).\\
|
alpar@1
|
3830 |
\end{tabular}
|
alpar@1
|
3831 |
|
alpar@1
|
3832 |
\medskip
|
alpar@1
|
3833 |
|
alpar@1
|
3834 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3835 |
{\tt\%M}&The minute as a decimal number (range 00 to 59).\\
|
alpar@1
|
3836 |
\end{tabular}
|
alpar@1
|
3837 |
|
alpar@1
|
3838 |
\medskip
|
alpar@1
|
3839 |
|
alpar@1
|
3840 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3841 |
{\tt\%p}&Either {\tt AM} or {\tt PM}, according to the given time value.
|
alpar@1
|
3842 |
Midnight is treated as {\tt AM} and noon as {\tt PM}.\\
|
alpar@1
|
3843 |
\end{tabular}
|
alpar@1
|
3844 |
|
alpar@1
|
3845 |
\medskip
|
alpar@1
|
3846 |
|
alpar@1
|
3847 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3848 |
{\tt\%P}&Either {\tt am} or {\tt pm}, according to the given time value.
|
alpar@1
|
3849 |
Midnight is treated as {\tt am} and noon as {\tt pm}.\\
|
alpar@1
|
3850 |
\end{tabular}
|
alpar@1
|
3851 |
|
alpar@1
|
3852 |
\medskip
|
alpar@1
|
3853 |
|
alpar@1
|
3854 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3855 |
{\tt\%R}&The hour and minute in decimal numbers using the format
|
alpar@1
|
3856 |
\verb|%H:%M|.\\
|
alpar@1
|
3857 |
\end{tabular}
|
alpar@1
|
3858 |
|
alpar@1
|
3859 |
\medskip
|
alpar@1
|
3860 |
|
alpar@1
|
3861 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3862 |
{\tt\%S}&The second as a decimal number (range 00 to 59).\\
|
alpar@1
|
3863 |
\end{tabular}
|
alpar@1
|
3864 |
|
alpar@1
|
3865 |
\medskip
|
alpar@1
|
3866 |
|
alpar@1
|
3867 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3868 |
{\tt\%T}&The time of day in decimal numbers using the format
|
alpar@1
|
3869 |
\verb|%H:%M:%S|.\\
|
alpar@1
|
3870 |
\end{tabular}
|
alpar@1
|
3871 |
|
alpar@1
|
3872 |
\medskip
|
alpar@1
|
3873 |
|
alpar@1
|
3874 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3875 |
{\tt\%u}&The day of the week as a decimal number (range 1 to 7), Monday
|
alpar@1
|
3876 |
being 1.\\
|
alpar@1
|
3877 |
\end{tabular}
|
alpar@1
|
3878 |
|
alpar@1
|
3879 |
\medskip
|
alpar@1
|
3880 |
|
alpar@1
|
3881 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3882 |
{\tt\%U}&The week number of the current year as a decimal number (range
|
alpar@1
|
3883 |
00 to 53), starting with the first Sunday as the first day of the first
|
alpar@1
|
3884 |
week. Days preceding the first Sunday in the year are considered to be
|
alpar@1
|
3885 |
in week 00.
|
alpar@1
|
3886 |
\end{tabular}
|
alpar@1
|
3887 |
|
alpar@1
|
3888 |
\medskip
|
alpar@1
|
3889 |
|
alpar@1
|
3890 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3891 |
{\tt\%V}&The ISO week number as a decimal number (range 01 to 53). ISO
|
alpar@1
|
3892 |
weeks start with Monday and end with Sunday. Week 01 of a year is the
|
alpar@1
|
3893 |
first week which has the majority of its days in that year; this is
|
alpar@1
|
3894 |
equivalent to the week containing January 4. Week 01 of a year can
|
alpar@1
|
3895 |
contain days from the previous year. The week before week 01 of a year
|
alpar@1
|
3896 |
is the last week (52 or 53) of the previous year even if it contains
|
alpar@1
|
3897 |
days from the new year. In other word, if 1 January is Monday, Tuesday,
|
alpar@1
|
3898 |
Wednesday or Thursday, it is in week 01; if 1 January is Friday,
|
alpar@1
|
3899 |
Saturday or Sunday, it is in week 52 or 53 of the previous year.\\
|
alpar@1
|
3900 |
\end{tabular}
|
alpar@1
|
3901 |
|
alpar@1
|
3902 |
\medskip
|
alpar@1
|
3903 |
|
alpar@1
|
3904 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3905 |
{\tt\%w}&The day of the week as a decimal number (range 0 to 6), Sunday
|
alpar@1
|
3906 |
being 0.\\
|
alpar@1
|
3907 |
\end{tabular}
|
alpar@1
|
3908 |
|
alpar@1
|
3909 |
\medskip
|
alpar@1
|
3910 |
|
alpar@1
|
3911 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3912 |
{\tt\%W}&The week number of the current year as a decimal number (range
|
alpar@1
|
3913 |
00 to 53), starting with the first Monday as the first day of the first
|
alpar@1
|
3914 |
week. Days preceding the first Monday in the year are considered to be
|
alpar@1
|
3915 |
in week 00.\\
|
alpar@1
|
3916 |
\end{tabular}
|
alpar@1
|
3917 |
|
alpar@1
|
3918 |
\medskip
|
alpar@1
|
3919 |
|
alpar@1
|
3920 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3921 |
{\tt\%y}&The year without a century as a decimal number (range 00 to
|
alpar@1
|
3922 |
99), that is the year modulo 100.\\
|
alpar@1
|
3923 |
\end{tabular}
|
alpar@1
|
3924 |
|
alpar@1
|
3925 |
\medskip
|
alpar@1
|
3926 |
|
alpar@1
|
3927 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3928 |
{\tt\%Y}&The year as a decimal number, using the Gregorian calendar.\\
|
alpar@1
|
3929 |
\end{tabular}
|
alpar@1
|
3930 |
|
alpar@1
|
3931 |
\medskip
|
alpar@1
|
3932 |
|
alpar@1
|
3933 |
\begin{tabular}{@{}p{20pt}p{298pt}@{}}
|
alpar@1
|
3934 |
{\tt\%\%}&A literal \verb|%| character.\\
|
alpar@1
|
3935 |
\end{tabular}
|
alpar@1
|
3936 |
|
alpar@1
|
3937 |
\medskip
|
alpar@1
|
3938 |
|
alpar@1
|
3939 |
All other (ordinary) characters in the format string are simply copied
|
alpar@1
|
3940 |
to the resultant string.
|
alpar@1
|
3941 |
|
alpar@1
|
3942 |
The first argument (calendar time) passed to the function {\tt time2str}
|
alpar@1
|
3943 |
must be in the range from $-62135596800$ to $+64092211199$ that
|
alpar@1
|
3944 |
corresponds to the period from 00:00:00 on January 1, 0001 to 23:59:59
|
alpar@1
|
3945 |
on December 31, 4000 of the Gregorian calendar.
|
alpar@1
|
3946 |
|
alpar@1
|
3947 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
alpar@1
|
3948 |
|
alpar@1
|
3949 |
\newpage
|
alpar@1
|
3950 |
|
alpar@1
|
3951 |
\section{Table drivers}
|
alpar@1
|
3952 |
\label{drivers}
|
alpar@1
|
3953 |
|
alpar@1
|
3954 |
\noindent\hfil
|
alpar@1
|
3955 |
by Andrew Makhorin \verb|<mao@gnu.org>|
|
alpar@1
|
3956 |
|
alpar@1
|
3957 |
\noindent\hfil
|
alpar@1
|
3958 |
and Heinrich Schuchardt \verb|<heinrich.schuchardt@gmx.de>|
|
alpar@1
|
3959 |
|
alpar@1
|
3960 |
\bigskip\bigskip
|
alpar@1
|
3961 |
|
alpar@1
|
3962 |
The {\it table driver} is a program module which provides transmitting
|
alpar@1
|
3963 |
data between MathProg model objects and data tables.
|
alpar@1
|
3964 |
|
alpar@1
|
3965 |
Currently the GLPK package has four table drivers:
|
alpar@1
|
3966 |
|
alpar@1
|
3967 |
\setlength{\leftmargini}{2.5em}
|
alpar@1
|
3968 |
|
alpar@1
|
3969 |
\begin{itemize}
|
alpar@1
|
3970 |
\item built-in CSV table driver;
|
alpar@1
|
3971 |
\item built-in xBASE table driver;
|
alpar@1
|
3972 |
\item ODBC table driver;
|
alpar@1
|
3973 |
\item MySQL table driver.
|
alpar@1
|
3974 |
\end{itemize}
|
alpar@1
|
3975 |
|
alpar@1
|
3976 |
\subsection{CSV table driver}
|
alpar@1
|
3977 |
|
alpar@1
|
3978 |
The CSV table driver assumes that the data table is represented in the
|
alpar@1
|
3979 |
form of a plain text file in the CSV (comma-separated values) file
|
alpar@1
|
3980 |
format as described below.
|
alpar@1
|
3981 |
|
alpar@1
|
3982 |
To choose the CSV table driver its name in the table statement should
|
alpar@1
|
3983 |
be specified as \verb|"CSV"|, and the only argument should specify the
|
alpar@1
|
3984 |
name of a plain text file containing the table. For example:
|
alpar@1
|
3985 |
|
alpar@1
|
3986 |
\medskip
|
alpar@1
|
3987 |
|
alpar@1
|
3988 |
\verb| table data IN "CSV" "data.csv": ... ;|
|
alpar@1
|
3989 |
|
alpar@1
|
3990 |
\medskip
|
alpar@1
|
3991 |
|
alpar@1
|
3992 |
The filename suffix may be arbitrary, however, it is recommended to use
|
alpar@1
|
3993 |
the suffix `\verb|.csv|'.
|
alpar@1
|
3994 |
|
alpar@1
|
3995 |
On reading input tables the CSV table driver provides an implicit field
|
alpar@1
|
3996 |
named \verb|RECNO|, which contains the current record number. This
|
alpar@1
|
3997 |
field can be specified in the input table statement as if there were
|
alpar@1
|
3998 |
the actual field having the name \verb|RECNO| in the CSV file. For
|
alpar@1
|
3999 |
example:
|
alpar@1
|
4000 |
|
alpar@1
|
4001 |
\medskip
|
alpar@1
|
4002 |
|
alpar@1
|
4003 |
\verb| table list IN "CSV" "list.csv": num <- [RECNO], ... ;|
|
alpar@1
|
4004 |
|
alpar@1
|
4005 |
\subsubsection*{CSV format\footnote{This material is based on the RFC
|
alpar@1
|
4006 |
document 4180.}}
|
alpar@1
|
4007 |
|
alpar@1
|
4008 |
The CSV (comma-separated values) format is a plain text file format
|
alpar@1
|
4009 |
defined as follows.
|
alpar@1
|
4010 |
|
alpar@1
|
4011 |
1. Each record is located on a separate line, delimited by a line
|
alpar@1
|
4012 |
break. For example:
|
alpar@1
|
4013 |
|
alpar@1
|
4014 |
\medskip
|
alpar@1
|
4015 |
|
alpar@1
|
4016 |
\verb| aaa,bbb,ccc\n|
|
alpar@1
|
4017 |
|
alpar@1
|
4018 |
\verb| xxx,yyy,zzz\n|
|
alpar@1
|
4019 |
|
alpar@1
|
4020 |
\medskip
|
alpar@1
|
4021 |
|
alpar@1
|
4022 |
\noindent
|
alpar@1
|
4023 |
where \verb|\n| means the control character \verb|LF| ({\tt 0x0A}).
|
alpar@1
|
4024 |
|
alpar@1
|
4025 |
\newpage
|
alpar@1
|
4026 |
|
alpar@1
|
4027 |
2. The last record in the file may or may not have an ending line
|
alpar@1
|
4028 |
break. For example:
|
alpar@1
|
4029 |
|
alpar@1
|
4030 |
\medskip
|
alpar@1
|
4031 |
|
alpar@1
|
4032 |
\verb| aaa,bbb,ccc\n|
|
alpar@1
|
4033 |
|
alpar@1
|
4034 |
\verb| xxx,yyy,zzz|
|
alpar@1
|
4035 |
|
alpar@1
|
4036 |
\medskip
|
alpar@1
|
4037 |
|
alpar@1
|
4038 |
3. There should be a header line appearing as the first line of the
|
alpar@1
|
4039 |
file in the same format as normal record lines. This header should
|
alpar@1
|
4040 |
contain names corresponding to the fields in the file. The number of
|
alpar@1
|
4041 |
field names in the header line should be the same as the number of
|
alpar@1
|
4042 |
fields in the records of the file. For example:
|
alpar@1
|
4043 |
|
alpar@1
|
4044 |
\medskip
|
alpar@1
|
4045 |
|
alpar@1
|
4046 |
\verb| name1,name2,name3\n|
|
alpar@1
|
4047 |
|
alpar@1
|
4048 |
\verb| aaa,bbb,ccc\n|
|
alpar@1
|
4049 |
|
alpar@1
|
4050 |
\verb| xxx,yyy,zzz\n|
|
alpar@1
|
4051 |
|
alpar@1
|
4052 |
\medskip
|
alpar@1
|
4053 |
|
alpar@1
|
4054 |
4. Within the header and each record there may be one or more fields
|
alpar@1
|
4055 |
separated by commas. Each line should contain the same number of fields
|
alpar@1
|
4056 |
throughout the file. Spaces are considered as part of a field and
|
alpar@1
|
4057 |
therefore not ignored. The last field in the record should not be
|
alpar@1
|
4058 |
followed by a comma. For example:
|
alpar@1
|
4059 |
|
alpar@1
|
4060 |
\medskip
|
alpar@1
|
4061 |
|
alpar@1
|
4062 |
\verb| aaa,bbb,ccc\n|
|
alpar@1
|
4063 |
|
alpar@1
|
4064 |
\medskip
|
alpar@1
|
4065 |
|
alpar@1
|
4066 |
5. Fields may or may not be enclosed in double quotes. For example:
|
alpar@1
|
4067 |
|
alpar@1
|
4068 |
\medskip
|
alpar@1
|
4069 |
|
alpar@1
|
4070 |
\verb| "aaa","bbb","ccc"\n|
|
alpar@1
|
4071 |
|
alpar@1
|
4072 |
\verb| zzz,yyy,xxx\n|
|
alpar@1
|
4073 |
|
alpar@1
|
4074 |
\medskip
|
alpar@1
|
4075 |
|
alpar@1
|
4076 |
6. If a field is enclosed in double quotes, each double quote which is
|
alpar@1
|
4077 |
part of the field should be coded twice. For example:
|
alpar@1
|
4078 |
|
alpar@1
|
4079 |
\medskip
|
alpar@1
|
4080 |
|
alpar@1
|
4081 |
\verb| "aaa","b""bb","ccc"\n|
|
alpar@1
|
4082 |
|
alpar@1
|
4083 |
\medskip
|
alpar@1
|
4084 |
|
alpar@1
|
4085 |
\noindent{\bf Example}
|
alpar@1
|
4086 |
|
alpar@1
|
4087 |
\begin{verbatim}
|
alpar@1
|
4088 |
FROM,TO,DISTANCE,COST
|
alpar@1
|
4089 |
Seattle,New-York,2.5,0.12
|
alpar@1
|
4090 |
Seattle,Chicago,1.7,0.08
|
alpar@1
|
4091 |
Seattle,Topeka,1.8,0.09
|
alpar@1
|
4092 |
San-Diego,New-York,2.5,0.15
|
alpar@1
|
4093 |
San-Diego,Chicago,1.8,0.10
|
alpar@1
|
4094 |
San-Diego,Topeka,1.4,0.07
|
alpar@1
|
4095 |
\end{verbatim}
|
alpar@1
|
4096 |
|
alpar@1
|
4097 |
\subsection{xBASE table driver}
|
alpar@1
|
4098 |
|
alpar@1
|
4099 |
The xBASE table driver assumes that the data table is stored in the
|
alpar@1
|
4100 |
.dbf file format.
|
alpar@1
|
4101 |
|
alpar@1
|
4102 |
To choose the xBASE table driver its name in the table statement should
|
alpar@1
|
4103 |
be specified as \verb|"xBASE"|, and the first argument should specify
|
alpar@1
|
4104 |
the name of a .dbf file containing the table. For the output table there
|
alpar@1
|
4105 |
should be the second argument defining the table format in the form
|
alpar@1
|
4106 |
\verb|"FF...F"|, where \verb|F| is either {\tt C({\it n})},
|
alpar@1
|
4107 |
which specifies a character field of length $n$, or
|
alpar@1
|
4108 |
{\tt N({\it n}{\rm [},{\it p}{\rm ]})}, which specifies a numeric field
|
alpar@1
|
4109 |
of length $n$ and precision $p$ (by default $p$ is 0).
|
alpar@1
|
4110 |
|
alpar@1
|
4111 |
The following is a simple example which illustrates creating and
|
alpar@1
|
4112 |
reading a .dbf file:
|
alpar@1
|
4113 |
|
alpar@1
|
4114 |
\begin{verbatim}
|
alpar@1
|
4115 |
table tab1{i in 1..10} OUT "xBASE" "foo.dbf"
|
alpar@1
|
4116 |
"N(5)N(10,4)C(1)C(10)": 2*i+1 ~ B, Uniform(-20,+20) ~ A,
|
alpar@1
|
4117 |
"?" ~ FOO, "[" & i & "]" ~ C;
|
alpar@1
|
4118 |
set S, dimen 4;
|
alpar@1
|
4119 |
table tab2 IN "xBASE" "foo.dbf": S <- [B, C, RECNO, A];
|
alpar@1
|
4120 |
display S;
|
alpar@1
|
4121 |
end;
|
alpar@1
|
4122 |
\end{verbatim}
|
alpar@1
|
4123 |
|
alpar@1
|
4124 |
\subsection{ODBC table driver}
|
alpar@1
|
4125 |
|
alpar@1
|
4126 |
The ODBC table driver allows connecting to SQL databases using an
|
alpar@1
|
4127 |
implementation of the ODBC interface based on the Call Level Interface
|
alpar@1
|
4128 |
(CLI).\footnote{The corresponding software standard is defined in
|
alpar@1
|
4129 |
ISO/IEC 9075-3:2003.}
|
alpar@1
|
4130 |
|
alpar@1
|
4131 |
\paragraph{Debian GNU/Linux.}
|
alpar@1
|
4132 |
Under Debian GNU/Linux the ODBC table driver uses the iODBC
|
alpar@1
|
4133 |
package,\footnote{See {\tt<http://www.iodbc.org/>}.} which should be
|
alpar@1
|
4134 |
installed before building the GLPK package. The installation can be
|
alpar@1
|
4135 |
effected with the following command:
|
alpar@1
|
4136 |
|
alpar@1
|
4137 |
\begin{verbatim}
|
alpar@1
|
4138 |
sudo apt-get install libiodbc2-dev
|
alpar@1
|
4139 |
\end{verbatim}
|
alpar@1
|
4140 |
|
alpar@1
|
4141 |
Note that on configuring the GLPK package to enable using the iODBC
|
alpar@1
|
4142 |
library the option `\verb|--enable-odbc|' should be passed to the
|
alpar@1
|
4143 |
configure script.
|
alpar@1
|
4144 |
|
alpar@1
|
4145 |
The individual databases must be entered for systemwide usage in
|
alpar@1
|
4146 |
\linebreak \verb|/etc/odbc.ini| and \verb|/etc/odbcinst.ini|. Database
|
alpar@1
|
4147 |
connections to be used by a single user are specified by files in the
|
alpar@1
|
4148 |
home directory (\verb|.odbc.ini| and \verb|.odbcinst.ini|).
|
alpar@1
|
4149 |
|
alpar@1
|
4150 |
\paragraph{Microsoft Windows.}
|
alpar@1
|
4151 |
Under Microsoft Windows the ODBC table driver uses the Microsoft ODBC
|
alpar@1
|
4152 |
library. To enable this feature the symbol:
|
alpar@1
|
4153 |
|
alpar@1
|
4154 |
\begin{verbatim}
|
alpar@1
|
4155 |
#define ODBC_DLNAME "odbc32.dll"
|
alpar@1
|
4156 |
\end{verbatim}
|
alpar@1
|
4157 |
|
alpar@1
|
4158 |
\noindent
|
alpar@1
|
4159 |
should be defined in the GLPK configuration file `\verb|config.h|'.
|
alpar@1
|
4160 |
|
alpar@1
|
4161 |
Data sources can be created via the Administrative Tools from the
|
alpar@1
|
4162 |
Control Panel.
|
alpar@1
|
4163 |
|
alpar@1
|
4164 |
\bigskip
|
alpar@1
|
4165 |
|
alpar@1
|
4166 |
To choose the ODBC table driver its name in the table statement should
|
alpar@1
|
4167 |
be specified as \verb|'ODBC'| or \verb|'iODBC'|.
|
alpar@1
|
4168 |
|
alpar@1
|
4169 |
The argument list is specified as follows.
|
alpar@1
|
4170 |
|
alpar@1
|
4171 |
The first argument is the connection string passed to the ODBC library,
|
alpar@1
|
4172 |
for example:
|
alpar@1
|
4173 |
|
alpar@1
|
4174 |
\verb|'DSN=glpk;UID=user;PWD=password'|, or
|
alpar@1
|
4175 |
|
alpar@1
|
4176 |
\verb|'DRIVER=MySQL;DATABASE=glpkdb;UID=user;PWD=password'|.
|
alpar@1
|
4177 |
|
alpar@1
|
4178 |
Different parts of the string are separated by semicolons. Each part
|
alpar@1
|
4179 |
consists of a pair {\it fieldname} and {\it value} separated by the
|
alpar@1
|
4180 |
equal sign. Allowable fieldnames depend on the ODBC library. Typically
|
alpar@1
|
4181 |
the following fieldnames are allowed:
|
alpar@1
|
4182 |
|
alpar@1
|
4183 |
\verb|DATABASE | database;
|
alpar@1
|
4184 |
|
alpar@1
|
4185 |
\verb|DRIVER | ODBC driver;
|
alpar@1
|
4186 |
|
alpar@1
|
4187 |
\verb|DSN | name of a data source;
|
alpar@1
|
4188 |
|
alpar@1
|
4189 |
\verb|FILEDSN | name of a file data source;
|
alpar@1
|
4190 |
|
alpar@1
|
4191 |
\verb|PWD | user password;
|
alpar@1
|
4192 |
|
alpar@1
|
4193 |
\verb|SERVER | database;
|
alpar@1
|
4194 |
|
alpar@1
|
4195 |
\verb|UID | user name.
|
alpar@1
|
4196 |
|
alpar@1
|
4197 |
The second argument and all following are considered to be SQL
|
alpar@1
|
4198 |
statements
|
alpar@1
|
4199 |
|
alpar@1
|
4200 |
SQL statements may be spread over multiple arguments. If the last
|
alpar@1
|
4201 |
character of an argument is a semicolon this indicates the end of
|
alpar@1
|
4202 |
a SQL statement.
|
alpar@1
|
4203 |
|
alpar@1
|
4204 |
The arguments of a SQL statement are concatenated separated by space.
|
alpar@1
|
4205 |
The eventual trailing semicolon will be removed.
|
alpar@1
|
4206 |
|
alpar@1
|
4207 |
All but the last SQL statement will be executed directly.
|
alpar@1
|
4208 |
|
alpar@1
|
4209 |
For IN-table the last SQL statement can be a SELECT command starting
|
alpar@1
|
4210 |
with the capitalized letters \verb|'SELECT '|. If the string does not
|
alpar@1
|
4211 |
start with \verb|'SELECT '| it is considered to be a table name and a
|
alpar@1
|
4212 |
SELECT statement is automatically generated.
|
alpar@1
|
4213 |
|
alpar@1
|
4214 |
For OUT-table the last SQL statement can contain one or multiple
|
alpar@1
|
4215 |
question marks. If it contains a question mark it is considered a
|
alpar@1
|
4216 |
template for the write routine. Otherwise the string is considered a
|
alpar@1
|
4217 |
table name and an INSERT template is automatically generated.
|
alpar@1
|
4218 |
|
alpar@1
|
4219 |
The writing routine uses the template with the question marks and
|
alpar@1
|
4220 |
replaces the first question mark by the first output parameter, the
|
alpar@1
|
4221 |
second question mark by the second output parameter and so forth. Then
|
alpar@1
|
4222 |
the SQL command is issued.
|
alpar@1
|
4223 |
|
alpar@1
|
4224 |
The following is an example of the output table statement:
|
alpar@1
|
4225 |
|
alpar@1
|
4226 |
\begin{small}
|
alpar@1
|
4227 |
\begin{verbatim}
|
alpar@1
|
4228 |
table ta { l in LOCATIONS } OUT
|
alpar@1
|
4229 |
'ODBC'
|
alpar@1
|
4230 |
'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword'
|
alpar@1
|
4231 |
'DROP TABLE IF EXISTS result;'
|
alpar@1
|
4232 |
'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );'
|
alpar@1
|
4233 |
'INSERT INTO result 'VALUES ( 4, ?, ? )' :
|
alpar@1
|
4234 |
l ~ LOC, quantity[l] ~ QUAN;
|
alpar@1
|
4235 |
\end{verbatim}
|
alpar@1
|
4236 |
\end{small}
|
alpar@1
|
4237 |
|
alpar@1
|
4238 |
\noindent
|
alpar@1
|
4239 |
Alternatively it could be written as follows:
|
alpar@1
|
4240 |
|
alpar@1
|
4241 |
\begin{small}
|
alpar@1
|
4242 |
\begin{verbatim}
|
alpar@1
|
4243 |
table ta { l in LOCATIONS } OUT
|
alpar@1
|
4244 |
'ODBC'
|
alpar@1
|
4245 |
'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword'
|
alpar@1
|
4246 |
'DROP TABLE IF EXISTS result;'
|
alpar@1
|
4247 |
'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );'
|
alpar@1
|
4248 |
'result' :
|
alpar@1
|
4249 |
l ~ LOC, quantity[l] ~ QUAN, 4 ~ ID;
|
alpar@1
|
4250 |
\end{verbatim}
|
alpar@1
|
4251 |
\end{small}
|
alpar@1
|
4252 |
|
alpar@1
|
4253 |
Using templates with `\verb|?|' supports not only INSERT, but also
|
alpar@1
|
4254 |
UPDATE, DELETE, etc. For example:
|
alpar@1
|
4255 |
|
alpar@1
|
4256 |
\begin{small}
|
alpar@1
|
4257 |
\begin{verbatim}
|
alpar@1
|
4258 |
table ta { l in LOCATIONS } OUT
|
alpar@1
|
4259 |
'ODBC'
|
alpar@1
|
4260 |
'DSN=glpkdb;UID=glpkuser;PWD=glpkpassword'
|
alpar@1
|
4261 |
'UPDATE result SET DATE = ' & date & ' WHERE ID = 4;'
|
alpar@1
|
4262 |
'UPDATE result SET QUAN = ? WHERE LOC = ? AND ID = 4' :
|
alpar@1
|
4263 |
quantity[l], l;
|
alpar@1
|
4264 |
\end{verbatim}
|
alpar@1
|
4265 |
\end{small}
|
alpar@1
|
4266 |
|
alpar@1
|
4267 |
\subsection{MySQL table driver}
|
alpar@1
|
4268 |
|
alpar@1
|
4269 |
The MySQL table driver allows connecting to MySQL databases.
|
alpar@1
|
4270 |
|
alpar@1
|
4271 |
\paragraph{Debian GNU/Linux.}
|
alpar@1
|
4272 |
Under Debian GNU/Linux the MySQL table\linebreak driver uses the MySQL
|
alpar@1
|
4273 |
package,\footnote{For download development files see
|
alpar@1
|
4274 |
{\tt<http://dev.mysql.com/downloads/mysql/>}.} which should be installed
|
alpar@1
|
4275 |
before building the GLPK package. The installation can be effected with
|
alpar@1
|
4276 |
the following command:
|
alpar@1
|
4277 |
|
alpar@1
|
4278 |
\begin{verbatim}
|
alpar@1
|
4279 |
sudo apt-get install libmysqlclient15-dev
|
alpar@1
|
4280 |
\end{verbatim}
|
alpar@1
|
4281 |
|
alpar@1
|
4282 |
Note that on configuring the GLPK package to enable using the MySQL
|
alpar@1
|
4283 |
library the option `\verb|--enable-mysql|' should be passed to the
|
alpar@1
|
4284 |
configure script.
|
alpar@1
|
4285 |
|
alpar@1
|
4286 |
\paragraph{Microsoft Windows.}
|
alpar@1
|
4287 |
Under Microsoft Windows the MySQL table driver also uses the MySQL
|
alpar@1
|
4288 |
library. To enable this feature the symbol:
|
alpar@1
|
4289 |
|
alpar@1
|
4290 |
\begin{verbatim}
|
alpar@1
|
4291 |
#define MYSQL_DLNAME "libmysql.dll"
|
alpar@1
|
4292 |
\end{verbatim}
|
alpar@1
|
4293 |
|
alpar@1
|
4294 |
\noindent
|
alpar@1
|
4295 |
should be defined in the GLPK configuration file `\verb|config.h|'.
|
alpar@1
|
4296 |
|
alpar@1
|
4297 |
\bigskip
|
alpar@1
|
4298 |
|
alpar@1
|
4299 |
To choose the MySQL table driver its name in the table statement should
|
alpar@1
|
4300 |
be specified as \verb|'MySQL'|.
|
alpar@1
|
4301 |
|
alpar@1
|
4302 |
The argument list is specified as follows.
|
alpar@1
|
4303 |
|
alpar@1
|
4304 |
The first argument specifies how to connect the data base in the DSN
|
alpar@1
|
4305 |
style, for example:
|
alpar@1
|
4306 |
|
alpar@1
|
4307 |
\verb|'Database=glpk;UID=glpk;PWD=gnu'|.
|
alpar@1
|
4308 |
|
alpar@1
|
4309 |
Different parts of the string are separated by semicolons. Each part
|
alpar@1
|
4310 |
consists of a pair {\it fieldname} and {\it value} separated by the
|
alpar@1
|
4311 |
equal sign. The following fieldnames are allowed:
|
alpar@1
|
4312 |
|
alpar@1
|
4313 |
\verb|Server | server running the database (defaulting to localhost);
|
alpar@1
|
4314 |
|
alpar@1
|
4315 |
\verb|Database | name of the database;
|
alpar@1
|
4316 |
|
alpar@1
|
4317 |
\verb|UID | user name;
|
alpar@1
|
4318 |
|
alpar@1
|
4319 |
\verb|PWD | user password;
|
alpar@1
|
4320 |
|
alpar@1
|
4321 |
\verb|Port | port used by the server (defaulting to 3306).
|
alpar@1
|
4322 |
|
alpar@1
|
4323 |
The second argument and all following are considered to be SQL
|
alpar@1
|
4324 |
statements
|
alpar@1
|
4325 |
|
alpar@1
|
4326 |
SQL statements may be spread over multiple arguments. If the last
|
alpar@1
|
4327 |
character of an argument is a semicolon this indicates the end of
|
alpar@1
|
4328 |
a SQL statement.
|
alpar@1
|
4329 |
|
alpar@1
|
4330 |
The arguments of a SQL statement are concatenated separated by space.
|
alpar@1
|
4331 |
The eventual trailing semicolon will be removed.
|
alpar@1
|
4332 |
|
alpar@1
|
4333 |
All but the last SQL statement will be executed directly.
|
alpar@1
|
4334 |
|
alpar@1
|
4335 |
For IN-table the last SQL statement can be a SELECT command starting
|
alpar@1
|
4336 |
with the capitalized letters \verb|'SELECT '|. If the string does not
|
alpar@1
|
4337 |
start with \verb|'SELECT '| it is considered to be a table name and a
|
alpar@1
|
4338 |
SELECT statement is automatically generated.
|
alpar@1
|
4339 |
|
alpar@1
|
4340 |
For OUT-table the last SQL statement can contain one or multiple
|
alpar@1
|
4341 |
question marks. If it contains a question mark it is considered a
|
alpar@1
|
4342 |
template for the write routine. Otherwise the string is considered a
|
alpar@1
|
4343 |
table name and an INSERT template is automatically generated.
|
alpar@1
|
4344 |
|
alpar@1
|
4345 |
The writing routine uses the template with the question marks and
|
alpar@1
|
4346 |
replaces the first question mark by the first output parameter, the
|
alpar@1
|
4347 |
second question mark by the second output parameter and so forth. Then
|
alpar@1
|
4348 |
the SQL command is issued.
|
alpar@1
|
4349 |
|
alpar@1
|
4350 |
The following is an example of the output table statement:
|
alpar@1
|
4351 |
|
alpar@1
|
4352 |
\begin{small}
|
alpar@1
|
4353 |
\begin{verbatim}
|
alpar@1
|
4354 |
table ta { l in LOCATIONS } OUT
|
alpar@1
|
4355 |
'MySQL'
|
alpar@1
|
4356 |
'Database=glpkdb;UID=glpkuser;PWD=glpkpassword'
|
alpar@1
|
4357 |
'DROP TABLE IF EXISTS result;'
|
alpar@1
|
4358 |
'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );'
|
alpar@1
|
4359 |
'INSERT INTO result VALUES ( 4, ?, ? )' :
|
alpar@1
|
4360 |
l ~ LOC, quantity[l] ~ QUAN;
|
alpar@1
|
4361 |
\end{verbatim}
|
alpar@1
|
4362 |
\end{small}
|
alpar@1
|
4363 |
|
alpar@1
|
4364 |
\noindent
|
alpar@1
|
4365 |
Alternatively it could be written as follows:
|
alpar@1
|
4366 |
|
alpar@1
|
4367 |
\begin{small}
|
alpar@1
|
4368 |
\begin{verbatim}
|
alpar@1
|
4369 |
table ta { l in LOCATIONS } OUT
|
alpar@1
|
4370 |
'MySQL'
|
alpar@1
|
4371 |
'Database=glpkdb;UID=glpkuser;PWD=glpkpassword'
|
alpar@1
|
4372 |
'DROP TABLE IF EXISTS result;'
|
alpar@1
|
4373 |
'CREATE TABLE result ( ID INT, LOC VARCHAR(255), QUAN DOUBLE );'
|
alpar@1
|
4374 |
'result' :
|
alpar@1
|
4375 |
l ~ LOC, quantity[l] ~ QUAN, 4 ~ ID;
|
alpar@1
|
4376 |
\end{verbatim}
|
alpar@1
|
4377 |
\end{small}
|
alpar@1
|
4378 |
|
alpar@1
|
4379 |
Using templates with `\verb|?|' supports not only INSERT, but also
|
alpar@1
|
4380 |
UPDATE, DELETE, etc. For example:
|
alpar@1
|
4381 |
|
alpar@1
|
4382 |
\begin{small}
|
alpar@1
|
4383 |
\begin{verbatim}
|
alpar@1
|
4384 |
table ta { l in LOCATIONS } OUT
|
alpar@1
|
4385 |
'MySQL'
|
alpar@1
|
4386 |
'Database=glpkdb;UID=glpkuser;PWD=glpkpassword'
|
alpar@1
|
4387 |
'UPDATE result SET DATE = ' & date & ' WHERE ID = 4;'
|
alpar@1
|
4388 |
'UPDATE result SET QUAN = ? WHERE LOC = ? AND ID = 4' :
|
alpar@1
|
4389 |
quantity[l], l;
|
alpar@1
|
4390 |
\end{verbatim}
|
alpar@1
|
4391 |
\end{small}
|
alpar@1
|
4392 |
|
alpar@1
|
4393 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
alpar@1
|
4394 |
|
alpar@1
|
4395 |
\newpage
|
alpar@1
|
4396 |
|
alpar@1
|
4397 |
\section{Solving models with glpsol}
|
alpar@1
|
4398 |
|
alpar@1
|
4399 |
The GLPK package\footnote{{\tt http://www.gnu.org/software/glpk/}}
|
alpar@1
|
4400 |
includes the program {\tt glpsol}, which is a stand-alone LP/MIP solver.
|
alpar@1
|
4401 |
This program can be launched from the command line or from the shell to
|
alpar@1
|
4402 |
solve models written in the GNU MathProg modeling language.
|
alpar@1
|
4403 |
|
alpar@1
|
4404 |
In order to tell the solver that the input file contains a model
|
alpar@1
|
4405 |
description, you need to specify the option \verb|--model| in the
|
alpar@1
|
4406 |
command line. For example:
|
alpar@1
|
4407 |
|
alpar@1
|
4408 |
\medskip
|
alpar@1
|
4409 |
|
alpar@1
|
4410 |
\verb| glpsol --model foo.mod|
|
alpar@1
|
4411 |
|
alpar@1
|
4412 |
\medskip
|
alpar@1
|
4413 |
|
alpar@1
|
4414 |
Sometimes it is necessary to use the data section placed in a separate
|
alpar@1
|
4415 |
file, in which case you may use the following command:
|
alpar@1
|
4416 |
|
alpar@1
|
4417 |
\medskip
|
alpar@1
|
4418 |
|
alpar@1
|
4419 |
\verb| glpsol --model foo.mod --data foo.dat|
|
alpar@1
|
4420 |
|
alpar@1
|
4421 |
\medskip
|
alpar@1
|
4422 |
|
alpar@1
|
4423 |
\noindent Note that if the model file also contains the data section,
|
alpar@1
|
4424 |
that section is ignored.
|
alpar@1
|
4425 |
|
alpar@1
|
4426 |
If the model description contains some display and/or printf statements,
|
alpar@1
|
4427 |
by default the output is sent to the terminal. In order to redirect the
|
alpar@1
|
4428 |
output to a file you may use the following command:
|
alpar@1
|
4429 |
|
alpar@1
|
4430 |
\medskip
|
alpar@1
|
4431 |
|
alpar@1
|
4432 |
\verb| glpsol --model foo.mod --display foo.out|
|
alpar@1
|
4433 |
|
alpar@1
|
4434 |
\medskip
|
alpar@1
|
4435 |
|
alpar@1
|
4436 |
If you need to look at the problem, which has been generated by the
|
alpar@1
|
4437 |
model translator, you may use the option \verb|--wlp| as follows:
|
alpar@1
|
4438 |
|
alpar@1
|
4439 |
\medskip
|
alpar@1
|
4440 |
|
alpar@1
|
4441 |
\verb| glpsol --model foo.mod --wlp foo.lp|
|
alpar@1
|
4442 |
|
alpar@1
|
4443 |
\medskip
|
alpar@1
|
4444 |
|
alpar@1
|
4445 |
\noindent in which case the problem data is written to file
|
alpar@1
|
4446 |
\verb|foo.lp| in CPLEX LP format suitable for visual analysis.
|
alpar@1
|
4447 |
|
alpar@1
|
4448 |
Sometimes it is needed merely to check the model description not
|
alpar@1
|
4449 |
solving the generated problem instance. In this case you may specify
|
alpar@1
|
4450 |
the option \verb|--check|, for example:
|
alpar@1
|
4451 |
|
alpar@1
|
4452 |
\medskip
|
alpar@1
|
4453 |
|
alpar@1
|
4454 |
\verb| glpsol --check --model foo.mod --wlp foo.lp|
|
alpar@1
|
4455 |
|
alpar@1
|
4456 |
\medskip
|
alpar@1
|
4457 |
|
alpar@1
|
4458 |
In order to write a numeric solution obtained by the solver you may use
|
alpar@1
|
4459 |
the following command:
|
alpar@1
|
4460 |
|
alpar@1
|
4461 |
\medskip
|
alpar@1
|
4462 |
|
alpar@1
|
4463 |
\verb| glpsol --model foo.mod --output foo.sol|
|
alpar@1
|
4464 |
|
alpar@1
|
4465 |
\medskip
|
alpar@1
|
4466 |
|
alpar@1
|
4467 |
\noindent in which case the solution is written to file \verb|foo.sol|
|
alpar@1
|
4468 |
in a plain text format.
|
alpar@1
|
4469 |
|
alpar@1
|
4470 |
The complete list of the \verb|glpsol| options can be found in the
|
alpar@1
|
4471 |
reference manual included in the GLPK distribution.
|
alpar@1
|
4472 |
|
alpar@1
|
4473 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
alpar@1
|
4474 |
|
alpar@1
|
4475 |
\newpage
|
alpar@1
|
4476 |
|
alpar@1
|
4477 |
\section{Example model description}
|
alpar@1
|
4478 |
|
alpar@1
|
4479 |
\subsection{Model description written in MathProg}
|
alpar@1
|
4480 |
|
alpar@1
|
4481 |
Below here is a complete example of the model description written in
|
alpar@1
|
4482 |
the GNU MathProg modeling language.
|
alpar@1
|
4483 |
|
alpar@1
|
4484 |
\begin{small}
|
alpar@1
|
4485 |
\begin{verbatim}
|
alpar@1
|
4486 |
# A TRANSPORTATION PROBLEM
|
alpar@1
|
4487 |
#
|
alpar@1
|
4488 |
# This problem finds a least cost shipping schedule that meets
|
alpar@1
|
4489 |
# requirements at markets and supplies at factories.
|
alpar@1
|
4490 |
#
|
alpar@1
|
4491 |
# References:
|
alpar@1
|
4492 |
# Dantzig G B, "Linear Programming and Extensions."
|
alpar@1
|
4493 |
# Princeton University Press, Princeton, New Jersey, 1963,
|
alpar@1
|
4494 |
# Chapter 3-3.
|
alpar@1
|
4495 |
|
alpar@1
|
4496 |
set I;
|
alpar@1
|
4497 |
/* canning plants */
|
alpar@1
|
4498 |
|
alpar@1
|
4499 |
set J;
|
alpar@1
|
4500 |
/* markets */
|
alpar@1
|
4501 |
|
alpar@1
|
4502 |
param a{i in I};
|
alpar@1
|
4503 |
/* capacity of plant i in cases */
|
alpar@1
|
4504 |
|
alpar@1
|
4505 |
param b{j in J};
|
alpar@1
|
4506 |
/* demand at market j in cases */
|
alpar@1
|
4507 |
|
alpar@1
|
4508 |
param d{i in I, j in J};
|
alpar@1
|
4509 |
/* distance in thousands of miles */
|
alpar@1
|
4510 |
|
alpar@1
|
4511 |
param f;
|
alpar@1
|
4512 |
/* freight in dollars per case per thousand miles */
|
alpar@1
|
4513 |
|
alpar@1
|
4514 |
param c{i in I, j in J} := f * d[i,j] / 1000;
|
alpar@1
|
4515 |
/* transport cost in thousands of dollars per case */
|
alpar@1
|
4516 |
|
alpar@1
|
4517 |
var x{i in I, j in J} >= 0;
|
alpar@1
|
4518 |
/* shipment quantities in cases */
|
alpar@1
|
4519 |
|
alpar@1
|
4520 |
minimize cost: sum{i in I, j in J} c[i,j] * x[i,j];
|
alpar@1
|
4521 |
/* total transportation costs in thousands of dollars */
|
alpar@1
|
4522 |
|
alpar@1
|
4523 |
s.t. supply{i in I}: sum{j in J} x[i,j] <= a[i];
|
alpar@1
|
4524 |
/* observe supply limit at plant i */
|
alpar@1
|
4525 |
|
alpar@1
|
4526 |
s.t. demand{j in J}: sum{i in I} x[i,j] >= b[j];
|
alpar@1
|
4527 |
/* satisfy demand at market j */
|
alpar@1
|
4528 |
|
alpar@1
|
4529 |
data;
|
alpar@1
|
4530 |
|
alpar@1
|
4531 |
set I := Seattle San-Diego;
|
alpar@1
|
4532 |
|
alpar@1
|
4533 |
set J := New-York Chicago Topeka;
|
alpar@1
|
4534 |
|
alpar@1
|
4535 |
param a := Seattle 350
|
alpar@1
|
4536 |
San-Diego 600;
|
alpar@1
|
4537 |
|
alpar@1
|
4538 |
param b := New-York 325
|
alpar@1
|
4539 |
Chicago 300
|
alpar@1
|
4540 |
Topeka 275;
|
alpar@1
|
4541 |
|
alpar@1
|
4542 |
param d : New-York Chicago Topeka :=
|
alpar@1
|
4543 |
Seattle 2.5 1.7 1.8
|
alpar@1
|
4544 |
San-Diego 2.5 1.8 1.4 ;
|
alpar@1
|
4545 |
|
alpar@1
|
4546 |
param f := 90;
|
alpar@1
|
4547 |
|
alpar@1
|
4548 |
end;
|
alpar@1
|
4549 |
\end{verbatim}
|
alpar@1
|
4550 |
\end{small}
|
alpar@1
|
4551 |
|
alpar@1
|
4552 |
\subsection{Generated LP problem instance}
|
alpar@1
|
4553 |
|
alpar@1
|
4554 |
Below here is the result of the translation of the example model
|
alpar@1
|
4555 |
produced by the solver \verb|glpsol| and written in CPLEX LP format
|
alpar@1
|
4556 |
with the option \verb|--wlp|.
|
alpar@1
|
4557 |
|
alpar@1
|
4558 |
\begin{small}
|
alpar@1
|
4559 |
\begin{verbatim}
|
alpar@1
|
4560 |
\* Problem: transp *\
|
alpar@1
|
4561 |
|
alpar@1
|
4562 |
Minimize
|
alpar@1
|
4563 |
cost: + 0.225 x(Seattle,New~York) + 0.153 x(Seattle,Chicago)
|
alpar@1
|
4564 |
+ 0.162 x(Seattle,Topeka) + 0.225 x(San~Diego,New~York)
|
alpar@1
|
4565 |
+ 0.162 x(San~Diego,Chicago) + 0.126 x(San~Diego,Topeka)
|
alpar@1
|
4566 |
|
alpar@1
|
4567 |
Subject To
|
alpar@1
|
4568 |
supply(Seattle): + x(Seattle,New~York) + x(Seattle,Chicago)
|
alpar@1
|
4569 |
+ x(Seattle,Topeka) <= 350
|
alpar@1
|
4570 |
supply(San~Diego): + x(San~Diego,New~York) + x(San~Diego,Chicago)
|
alpar@1
|
4571 |
+ x(San~Diego,Topeka) <= 600
|
alpar@1
|
4572 |
demand(New~York): + x(Seattle,New~York) + x(San~Diego,New~York) >= 325
|
alpar@1
|
4573 |
demand(Chicago): + x(Seattle,Chicago) + x(San~Diego,Chicago) >= 300
|
alpar@1
|
4574 |
demand(Topeka): + x(Seattle,Topeka) + x(San~Diego,Topeka) >= 275
|
alpar@1
|
4575 |
|
alpar@1
|
4576 |
End
|
alpar@1
|
4577 |
\end{verbatim}
|
alpar@1
|
4578 |
\end{small}
|
alpar@1
|
4579 |
|
alpar@1
|
4580 |
\subsection{Optimal LP solution}
|
alpar@1
|
4581 |
|
alpar@1
|
4582 |
Below here is the optimal solution of the generated LP problem instance
|
alpar@1
|
4583 |
found by the solver \verb|glpsol| and written in plain text format
|
alpar@1
|
4584 |
with the option \verb|--output|.
|
alpar@1
|
4585 |
|
alpar@1
|
4586 |
\newpage
|
alpar@1
|
4587 |
|
alpar@1
|
4588 |
\begin{small}
|
alpar@1
|
4589 |
\begin{verbatim}
|
alpar@1
|
4590 |
Problem: transp
|
alpar@1
|
4591 |
Rows: 6
|
alpar@1
|
4592 |
Columns: 6
|
alpar@1
|
4593 |
Non-zeros: 18
|
alpar@1
|
4594 |
Status: OPTIMAL
|
alpar@1
|
4595 |
Objective: cost = 153.675 (MINimum)
|
alpar@1
|
4596 |
|
alpar@1
|
4597 |
No. Row name St Activity Lower bound Upper bound Marginal
|
alpar@1
|
4598 |
--- ------------ -- ------------ ------------ ------------ ------------
|
alpar@1
|
4599 |
1 cost B 153.675
|
alpar@1
|
4600 |
2 supply[Seattle]
|
alpar@1
|
4601 |
B 300 350
|
alpar@1
|
4602 |
3 supply[San-Diego]
|
alpar@1
|
4603 |
NU 600 600 < eps
|
alpar@1
|
4604 |
4 demand[New-York]
|
alpar@1
|
4605 |
NL 325 325 0.225
|
alpar@1
|
4606 |
5 demand[Chicago]
|
alpar@1
|
4607 |
NL 300 300 0.153
|
alpar@1
|
4608 |
6 demand[Topeka]
|
alpar@1
|
4609 |
NL 275 275 0.126
|
alpar@1
|
4610 |
|
alpar@1
|
4611 |
No. Column name St Activity Lower bound Upper bound Marginal
|
alpar@1
|
4612 |
--- ------------ -- ------------ ------------ ------------ ------------
|
alpar@1
|
4613 |
1 x[Seattle,New-York]
|
alpar@1
|
4614 |
B 0 0
|
alpar@1
|
4615 |
2 x[Seattle,Chicago]
|
alpar@1
|
4616 |
B 300 0
|
alpar@1
|
4617 |
3 x[Seattle,Topeka]
|
alpar@1
|
4618 |
NL 0 0 0.036
|
alpar@1
|
4619 |
4 x[San-Diego,New-York]
|
alpar@1
|
4620 |
B 325 0
|
alpar@1
|
4621 |
5 x[San-Diego,Chicago]
|
alpar@1
|
4622 |
NL 0 0 0.009
|
alpar@1
|
4623 |
6 x[San-Diego,Topeka]
|
alpar@1
|
4624 |
B 275 0
|
alpar@1
|
4625 |
|
alpar@1
|
4626 |
End of output
|
alpar@1
|
4627 |
\end{verbatim}
|
alpar@1
|
4628 |
\end{small}
|
alpar@1
|
4629 |
|
alpar@1
|
4630 |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
alpar@1
|
4631 |
|
alpar@1
|
4632 |
\newpage
|
alpar@1
|
4633 |
|
alpar@1
|
4634 |
\setcounter{secnumdepth}{-1}
|
alpar@1
|
4635 |
|
alpar@1
|
4636 |
\section{Acknowledgment}
|
alpar@1
|
4637 |
|
alpar@1
|
4638 |
The authors would like to thank the following people, who kindly read,
|
alpar@1
|
4639 |
commented, and corrected the draft of this document:
|
alpar@1
|
4640 |
|
alpar@1
|
4641 |
\medskip
|
alpar@1
|
4642 |
|
alpar@1
|
4643 |
\noindent Juan Carlos Borras \verb|<borras@cs.helsinki.fi>|
|
alpar@1
|
4644 |
|
alpar@1
|
4645 |
\medskip
|
alpar@1
|
4646 |
|
alpar@1
|
4647 |
\noindent Harley Mackenzie \verb|<hjm@bigpond.com>|
|
alpar@1
|
4648 |
|
alpar@1
|
4649 |
\medskip
|
alpar@1
|
4650 |
|
alpar@1
|
4651 |
\noindent Robbie Morrison \verb|<robbie@actrix.co.nz>|
|
alpar@1
|
4652 |
|
alpar@1
|
4653 |
\end{document}
|