A GAMS programozási nyelv

Utasítások, vezérlési szerkezetek

Utasítások

Egyenlőségek, egyenlőtlenségek

Az egyes változókra - skalárok, paraméterek, stb. - tehetünk algebrai megkötéseket egyenlőségek, egyenlőtlenségek formájában. Megadási mód az eddigieknek megfelelően történik:

equation eqname(setdependency) opcionalis_magyarazat ;

Itt is a setdependency megadja, hogy mely halmaz(ok)hoz kapcsoljuk az egyenlőséget, legfeljebb tízhez lehet, de nem kötelező. Az equation helyett használható az equations is.

A ".." egyenlőség specifikáció

A fentiekben deklarált egyenlőségek algebrai struktúráját adhatjuk meg a ".." specifikáció segítségével, az alábbi formában:

eqname(setdependency)$conditional .. lefthand eqtype righthand ;

Ahol eqname egy korábban deklarált, a setdependency által meghatározott halmazhoz kapcsolódó egyenlőség, a $conditional egy opcionálisan megadható feltétel, lefthand az egyenlőség bal oldalán álló, righthand pedig a jobb oldalán álló kifejezés, eqtype pedig egy relációs jel. Lássunk is erre egy példát!

Példa

Az alábbi példában adott két halmaz, x és y, ezeken definiált két változó, costx és costy, ezek valamilyen költségeket jelentenek. Szeretnénk meghatározni az összköltséget úgy, hogy az x halmaz bármely elemének költsége kisebb legyen az y halmaz bármely elemének költségénél. (Természetesen kell még olyan utasítás is, amely a feltételeknek megfelelően bállítja costx és costy értékeit, de ezekkel itt most nem foglalkozunk.)

A feladat az alábbi formában oldaható meg:

SETs x, y ; variables costx(x), costy(y); variable tot; Equations total 'ez lesz az osszeg' kisebb(x,y) 'costx elemei kisebbek costy elemeinel' ; total .. tot =e= sum(x, costx(x)) + sum(y, costy(y)) ; kisebb(x,y) .. costx(x) =l= costy(y) ;

Ahogy látható, nem a hagyományos formában kell a relációkat megadni. A megfeleltetések a következők:

Egyenlőség attribútumok

A változókhoz hasonlóan az egyenlőségeknek is vannak attribútumaik:

  1. Alsó korlát: Ez vagy mínusz végtelen, vagy pedig a "=g=", illetve "=e=" típusú egyenlőség jobboldala. A fenti példával élve: total.lo
  2. Felső korlát: Ez pedig vagy plusz végtelen, vagy pedig a "=l=", illetve "=e=" tíupsú egyenlőség jobboldala. Pl.: total.up
  3. Optimális érték (level): total.l
  4. Határérték: total.m
  5. Skálázási faktor: az együtthatók átskálázására használatos, pl.: total.scale = 2;

Model utasítás

A modellek olyan objektumok a GAMS-ban, amelyeket megold a rendszer. Egy modellben összegyűjtjük az egyenlőségek, változók (azok minden attribútumával együtt) egy részét, vagy akár az összeset. Három alapvető típusú modellt különböztetünk meg egymástól:

  1. optimizációs modellek (LP, NLP, stb.), amikor a modell utasítás meghatározza a használt egyenlőségeket;
  2. egyenlőség-, illetve egyenlőtlenségrendszerek (CNS) definiálására szolgáló utasítás;
  3. kevert komplementaritási problémák (MCP), ekkor az utasítás megmondja, mely egyenlőségek tartoznak a modellhez, illetve ezek komplementaritási relációjukat a benne lévő változókkal.

Az általános megadási forma:

MODEL modelname megjegyzes / tartalom / ;

Ahol a model kulcsszó helyett használható a models kulcsszó is, illetve egy utasítás alatt több modellt is definiálhatunk, továbbá a tartalom megadási módja az alábbiak közül bármelyik lehet:

Solve utasítás

Ezzel az utasítással lehet a fentebb definiált modelleket megoldani. Ha optimizációs problémát szeretnénk megoldani, megadhatjuk az optimalizálás irányát is, azaz maximalizálni, illetve minimalizálni szeretnénk, a másik két esetben (MCP, CNS) ez hiányzik. A megadási módok tehát a következők:

SOLVE modelname maximizing valtozo using modeltype; SOLVE modelname using modeltype minimizing valtozo; SOLVE modelname using modeltype;

Amint látható, az optimalizás iránya és a használt modelltípus megadása felcserélhető. A fentiekben szereplő modelname egy korábban definiált modell, valtozo egy megszorítások nélküli változó, modeltype pedig az alábbi problématípusok valamelyike:

  1. LP (Linear Program): olyan optimalizációs probléma, amely nem tartalmazhat nemlineáris kifejezéseket és diszkrét (binary és integer) változókat.
  2. NLP (Non Linear Program): az előbbitől csak annyiban különbözik, hogy itt lehetnek sima nemlináris kifejezések is, de ugyanúgy nem tartalmazhat diszkrét változókat.
  3. DNLP (Discontinuous Non Linear Program): szintén optimizációs probléma, lehetnek benne nem sima nemlineáris kifejezések is, amelyeknek nem folytonos a deriváltjuk, de továbbra sem lehetnek diszkrét változók.
  4. MIP (Mixed Integer Program): diszkrét változókat tartalmazó LP.
  5. >
  6. RMIP (Relaxed MIP)
  7. MINLP (Mixed Integer Non Linear Program): sima nemlineáris kifejezéseket és diszkrét változókat tartalmazó optimizációs probléma.
  8. RMINLP (Relaxed MINLP)
  9. MPEC (Mathematical Programs with Equilibrium Constraints): nehéz problématípus, az erre szolgáló solverek még fejlesztés alatt állnak. (lásd: http://www.gamsworld.org)
  10. MCP (Mixed Complementary Problem): komplementaritási probléma, nemlineáris kifejezésekkel.
  11. CNS (Constrained Non linear System)

Vezérlési szerkezetek

A vezérlési szerkezetek tekintetében - a case-t kivéve - minden megtalálható a GAMS-ban, mint a legtöbb programozási nyelvben, természetesen sajátos formában. Ebben a fejezetben ezekről lesz szó.

Még mielőtt részletezném az egyes vezérlési szerkezeteket, megjegyzem, hogy mindegyik esetében kétféle szintaxis lehetséges: az egyik az "alapértelmezett", a másik a $Onend ún. dollár-parancs (ezekről lásd bővebben az erről szóló következő fejezetet!) használata mellett engedélyezett (az alternatív szintaxis nagyon hasonló az Ada95 megfelelő szintaxisához). Erről is szó lesz az egyes pontokban.

Továbbá fontos azt is tudni, hogy az alábbiakban taglalt egyik vezérlési szerkezet belsejében sem lehetnek parameter, set, acronym, file, table, model, equation, variable vagy scalar utasítások, illetve ".." egyenlőség-deklarációk.

Feltételes elágazás (if)

Az elágazás általános formája:

if (feltétel, utasítások; elseif feltétel, utasítások; else utasítások; ) ;

Ahol tetszőleges elseif ág lehet - akár nulla is -, továbbá nem kötelező módon lehet egy else ág is. A zárójelezéssel egyértelműen meghatározott, hogy az egyes else, illetve elseif ágak mely if-hez tartoznak, így nem kell külön szabály a csellengő ágak kezelésére.

Az alternatív szintaxis a $Onend dollár-parancs használata mellett pedig:

if feltétel then utasítások; elseif feltétel then utasítások; else utasítások; endif;

Egyszerű ciklus (loop)

Ha egy, vagy több halmaz elemeit bejárva szeretnénk ugyanazokat az utasításokat végrehajtani, akkor használható a loop utasítás, melynek szintaxisa:

loop ( (halmazok_vesszővel_elválasztva ), utasítások; ) ;

Ha csak egyetlen halmaz elemein szeretnénk csak a ciklusmagot végrehajtani, akkor a belső zárójelek elhagyhatók. A ciklus esetén is használható a $Onend által meghatározott alternatív szintaxis, amely a következőképpen néz ki:

loop halmaz do utasítások; endloop;

Sem a ciklusváltozó, sem a halmaz, amelynek eleme a ciklusváltozó, nem változtatható meg.

Elöltesztelős ciklus (while)

A while ciklus utasítások többszöri végrehajtására használatos, a ciklusmag mindaddig végre fog hajtódni, amíg a ciklusfeltétel igaz marad. Szintaxis:

while (feltétel, utasítások; );

Illetve az alternatív szintaxis:

while feltétel do utasítások; endwhile;

Hátultesztelős ciklus (repeat-until)

Ez a fajta ciklus a while ciklus párja, a ciklusmag mindaddig végrhatjódik, amíg a ciklusfeltétel igazzá nem válik. Egyetlen szintaxisa (nincs alternatív):

repeat ( utasítások; until feltétel);

Léptető ciklus (for)

Az általános szintaxis a következő:

for (skalár = kezd [down]to vég by növelés, utasítások; );

Ahol:

Megjegyzés:
a kezd, vég és növelés értékek nem csak egészek lehetnek, hanem tetszőleges valósak is (kivéve a növelés-t, az csak pozitív lehet).

Az alternatív szintaxis pedig:

for skalár = kezd [ down] to vég by növelés do utasítások; endfor;

Dollár-parancsok

Dollár-parancsokat a sor elején lévő '$'-jel vezet be, ez után közvetlenül jön a parancs neve (Nem engedélyezett semmilyen elválasztó karakter a '$'-jel és a parancs neve között!), majd szóközzel elválaszta az argumentuma(i), ha van(nak). A dollár-parancsokat bárhol elhelyezhetjük a forráskódban, egy soron belül akár többet is, és itt sincs különbség kis- és nagybetűk között. A dollár-parancsokat fordítási időben értékeli ki a rendszer.

Megjegyzés:
Érdekesség, hogy a bevezető '$'-jelet lecserélhetjük a $dollar dollár-paranccsal.
Továbbá megjegyzendő, hogy a fordítás eredményei között nem szerepel semmilyen futtatható fájl, a rendszer automatikusan már csak a végeredményt adja vissza listafájlokban.

Nagyon sok dollár-parancs van, ezek közül néhányat tárgyalok, a többi csak megemlítésre kerül. Az alábbi kategóriákba oszthatjuk a dollár-parancsokat:

A következő pontokban ezekről lesz szó.

Kommentezés

Ebben a pontban szereplő dollár-parancsok többsége már szerepelt a kommenteknél.

$Comment

Ezzel a dollár-paranccsal változtatható meg az egysoros komment delimitere (amely alapértelmezésben a '*'), használata:

* normal komment $comment ! ! uj delimiterrel irt komment
$EolCom

Átdefiniálja a sorvégi komment delimiterét (alapértelmezésben: '!!'). Használat:

x = 3; !! sorvegi komment $eolcom // x = x + 1; // uj delimiterrel
$Hidden

Rejtett komment megadására szolgál, amely nem jelenik meg a listafájlban. Példa:

$hidden ez egy rejtett komment, nem kerul a listafajlba
$InlineCom

Az in-line komment delimiterének megváltoztatására szolgál, használata:

x = x /* ez egy in-line komment */ + 1; $inlinecom { } x = x { ez pedig mar egy masik in-line komment } + 2;
$MaxCol és $MinCol

Beállítja a jobboldali, illetve a baloldali margót, használata:

$maxcol érték1 $mincol érték2

Illetve használhatók összevonva is:

$maxcol érték1 mincol érték2
Megjegyzés:
a $MaxCol esetén a nulla paraméter ekvivalens a default (32767) értékkel, $MinCol esetén a default érték 1.
$OnEolCom és $OffEolCom

Aktiválja, ill. deaktiválja a sorvégi kommentet.

$OnMargin és $OffMargin

Aktiválja, ill. deaktiválja a margó kommentet.

$OnNestCom és $OffNestCom

Engedélyezi, ill. tiltja az in-line kommentek egymásba ágyazását. Pl.:

$inline { } onnestcom { lehet { ilyet is } irni } $offnestcom
$OnText és $OffText

Többsoros kommenteket fognak közre, a közöttük lévő sorok a listafájlban sorszám nélkül szerepelnek. Pl.:

$ontext ez egy tobbsoros komment ez az utolso sora $offtext

Listafájlok

Itt a listafájllal és más kimeneti fájlokkal kapcsolatos dollár-parancsok kerülnek ismertetésre.

$Echo és $EchoN

Egy szöveget küld egy külső fájlba, használat:

$echo 'kuldendo szoveg' > kulso_file $echo 'ujabb szoveg' >> kulso_file

A kulso_file-nak tartalmaznia kell az elérési utat is, amennyiben ez szükséges. Mind a küldendő szöveg, mind a fájl lehet idézőjelek között, vagy nélkülük. A $Echo esetén egy sorvége jel is küldésre kerül, $EchoN esetén pedig nem, '>' a már létező fájlt felülírja, '>>' pedig a fájl végére ír. A megnyitott fájl csak akkor kerül bezárásra, amikor befejeződik a futás, vagy $Call, vagy $Include dollár-parancsok hívásával.

$OnDollar és $OffDollar

Engedélyezi, ill. tiltja a dollár-parancsok másolását az LST-fájlba, alapértelmezett a $OffDollar.

Külső fájlok belinkelése

Ebben a pontban arról lesz szó, hogy a GAMS milyen lehetőségeket kínál külső fájlok használatára.

$BatInclude

Külső fájl belinkelésére szolgál, itt van lehetőség argumentumok átadására is. Pl.:

$batinclude filename arg1, arg2, ...
$Include

Külső fájl argumentumok nélküli importálására használatos. Pl.:

$include filename
$LibInclude

A GAMS rendszerkönyvárban lévő inclib könyvtárból linkelhetünk be fájlokat, argumentumok átadása itt is lehetséges. Pl.:

$libinclude filename arg1, arg2, ...
További parancsok

További, fájlok belinkelésére szolgáló dollár-parancsok:

$OnGlobal, $OffGlobal, $OnInclude, $OffInclude, $Shift, $SysInclude

Numerikus eljárások

$OnDigit és $OffDigit

A számok tárolásának pontosságát kontrollálja. Az $OffDigit parancs hatására a GAMS a lehető legnagyobb pontosságot használja, a számok többi részét figyelmen kívül hagyja, az $OnDigit pedig megváltoztatja a számokat úgy, hogy azok az adott gépen ábrázolhatók legyenek (ez általában 16 bit). Alapértelmezésben ez utóbbi van érvényben.

$OnEps és $OffEps

Az $OnEps hatására a paraméterekben és táblázatokban lévő nullákat egy adott EPS-nek tekinti a rendszer. Alapértelmezett az $OffEps, amely a fenti opciót kikapcsolja.

Adatok törlése (reset)

$Clear

Visszaállítja az argumentumában megadott (akárhány) halmaz, paraméter, egyenlőség, illetve változó értékét az alapértelmezettre, azaz a halmazokat kiüríti, a numerikus értékeket pedig kinullázza. (Veszélyes a használata.)

$Kill

Az előbbi parancsnál erősebb, hatására nem csak a halmaz ürül ki, de minden más - paraméter, egyenlőség, illetve változó - adatszerkezethez tartozó adatok is törlődnek, csak a típus- és halmazdefiníciók maradnak érvényben. Fordítási időben hajtódik végre, nem pedig végrehajtási időben, ezért ez is nagyon veszélyes.

Külső program hívása

A $Call dollár-parancs segítségével indíthatunk külső programot is, amelynek parancssori argumentumokat is adhatunk át. Pl.:

$call 'copy file1 file2'
Megjegyzés:
Idézőjelek használhatók, de nem kötelezőek.

Dollár-parancsok listája

A többi dollár-parancs nem kerül részletes ismertetésre, ezek a felhasználói kézikönyvben megtalálhatók. Az összes dollár-parancs listája (ábécé-sorrendben, összesen 96 db) alább olvasható:

abort, batinclude, call, clear, comment, dollar, double, echo, echon, eject, eolcom, error, escape, exit, expose, gdxin, gdxout, goto, hidden, hide, if, if not, ifi, ifi not, include, inlinecom, kill, label, libinclude, lines, load, log, maxcol, mincol, [on|off]delim, [on|off]digit, [on|off]dollar, [on|off]echo, [on|off]empty, [on|off]end, [on|off]eolcom, [on|off]eps, [on|off]global, [on|off]include, [on|off]inline, [on|off]listing, [on|off]margin, [on|off]multi, [on|off]nestcom, [on|off]symlist, [on|off]symxref, [on|off]ext, [on|off]uellist, [on|off]uelxref, [on|off]upper, [on|off]warning, phantom, protect, purge, set, setargs, setlocal, shift, show, single, stars, stop, stitle, sysinclude, title, unload, use205, use225, use999.