embeddedSort.gms : Sorting of numerical data using the embedded code facility

Description

The embedded code facility allows to integrate external code (e.g. Python) during
both compile and execution time of a GAMS program. GAMS symbols are shared with
the external code, so no communication via disk is necessary.

This example demonstrates how to sort random numerical GAMS data in Python at
GAMS execution time.

Contributor: Lutz Westermann, July 2017


Category : GAMS Data Utilities library


Main file : embeddedSort.gms   includes :  embeddedSort.gms

$Title Sorting of numerical data using the embedded code facility

$ontext
The embedded code facility allows to integrate external code (e.g. Python) during
both compile and execution time of a GAMS program. GAMS symbols are shared with
the external code, so no communication via disk is necessary.

This example demonstrates how to sort random numerical GAMS data in Python at
GAMS execution time.

Contributor: Lutz Westermann, July 2017
$offtext


* On the major platforms (Windows, Linux, Mac), GMSPYTHONLIB gets automatically set 
* to use the internal Python installation in sysdir/GMSPython.
$if not setEnv GMSPYTHONLIB $abort.noError Embedded code Python not ready to be used
$log --- Using Python library %sysEnv.GMSPYTHONLIB%


Set       i         / 1*10 /;
Parameter a(i)      Random Data
          aIndex(i) Sorted Index of a;

* Generate random data
a(i) = uniformInt(1,10*card(i));

* Embedded Python code:
* - GAMS parameter "a" is read from GAMS as a list
* - It gets sorted
* - The index position of the original data gets stored in "aIndex"
* - "AIndex" gets written back to GAMS
embeddedCode Python:
  tmp = sorted(gams.get("a"), key=lambda x:x[-1])
  aIndex = [(rec[0], idx+1) for rec,idx in zip(tmp, range(len(tmp))) ]
  gams.set("aIndex",aIndex)
endEmbeddedCode aIndex

display a, aIndex;

********************************************************************************
* In some cases it might be expensive to initialize the embedded code
* environment. For this, it is possible to initialize it once, pause it's
* execution and continue after executing some GAMS statements


* Generate new random data
a(i) = uniformInt(1,10*card(i));

* Embedded Python code like above, just pause it at the end
embeddedCode Python:
  tmp = sorted(gams.get("a"), key=lambda x:x[-1])
  aIndex = [(rec[0], idx+1) for rec,idx in zip(tmp, range(len(tmp))) ]
  gams.set("aIndex",aIndex)
pauseEmbeddedCode aIndex

Display a,aIndex;

* Generate new random data
a(i) = uniformInt(1,10*card(i));

* Embedded Python code like above, just continue it without reinitialization
continueEmbeddedCode:
  tmp = sorted(gams.get("a"), key=lambda x:x[-1])
  aIndex = [(rec[0], idx+1) for rec,idx in zip(tmp, range(len(tmp))) ]
  gams.set("aIndex",aIndex)
endEmbeddedCode AIndex

Display a,aIndex;