J.C. Kantor ([email protected])

This IPython notebook describes the installation and use of GLPK/MathProg from an IPython notebook.

In [1]:

```
from IPython.core.display import HTML
HTML(open("styles/custom.css", "r").read())
```

Out[1]:

Mathematical programming languages are designed for the purpose of writing applied optimization problems in a concise, high-level, maintainable manner with sufficient precision to be translated and solved using optimization software.

GAMS (the General Algebraic Modeling System) is generally cited as the first example of a commercially successful mathematical programming language. Since the introduction of GAMS in the late 1970's, a number of succesful languages have been produced including AIMMS, AMPL, LINDO/LINGO, MPL, XPRESS-MOSEL, and many others. Of these, AMPL appears to be most widely adopted language for university training.

GNU MathProg) is part of the open source GNU GLPK project. MathProg offers a subset of the AMPL language roughly equivalent to AMPL as it distributed in the early 1990's and described in the AMPL book. Though distributed as part of GLPK, MathProg interfaces are available for other solvers including lpsolve and COIN-OR CBC. MathProg can export models in a several formats compatiable with most commercial and non-commericial solvers for mixed-integer linear programs.

You will need to install a working copy of GLPK before executing code cells in the following tutorial. Here some basic recommendations.

For Windows/PC hardware, the Windows for GLPK web site maintains a pre-compiled version of GLPK based on the lastest official release.

For MacOS users, the most convenient installation process is to use a package manager. If you are not already doing so, you may consider installing the excellect Homebrew package manager using the instructions on their homepage. Once Homebrew is installed, GLPK can be installed with two commands

brew tap homebrew/science brew install glpk

In [1]:

```
print "Hello World"
```

In [2]:

```
%%script glpsol -m /dev/stdin -o /dev/stdout --out output
printf "Hello, World\n";
end;
```

In [3]:

```
print output
```

Cell magics provide mechanisms for using GLPK/MathProg inside the cells of an IPython notebook.

To process a MathProg model from a cell, use the cell magic

`%%script glpsol -m /dev/stdin`

as the first line of the cell. This line uses the cell magic `%%script`

to run the command `glpsol -m /dev/stdin`

as if it were entered directly into a terminal window. `glpsol`

calls the glpk solver. The argument `-m /dev/stdin`

tells the solver to process a MathProg model from the standard input. In the case of IPython notebooks, is the remaining contents of the cell.

We'll demonstrate this for a simple model that adds two parameter values and displays the result. Look for the displayed result among the other output generated by the `glpsol`

command.

In [4]:

```
%%script glpsol -m /dev/stdin
param a := 12.3;
param b := 13;
display a + b;
end;
```

`glpsol`

.

In [5]:

```
%%script --out output glpsol -m /dev/stdin -y out.txt
param a := 12.3;
param b := 13;
display a + b;
end;
```

`-y out.txt`

option redirects display output to the file `out.txt`

. The file can be read and displayed using the usual python methods as shown here:

In [6]:

```
f = open('out.txt')
print f.read()
f.close()
```

`--out output`

is an option passed to script that redirects normal cell output to a python variable `output`

. This will contain the remaining output of the `glpsol`

command which can be displayed as follows:

In [7]:

```
print output
```

In [8]:

```
%%script --out output glpsol -m /dev/stdin
# declare problem variables
var x;
var y;
var z;
# list all equations
eqn1 : 3*x + 2*y + z = 12;
eqn2 : 2.1*x + y = -3;
eqn3 : y - z = 4;
# solve
solve;
# display results
display x, y, z;
end;
```

A few things to notice are that all unknowns must be declared as variables, and that all equations are written with a unique name followed by the equation itself.

First we'll look at the diagnostic output generated by `glpsol`

.

In [9]:

```
print output
```

If things went well we should see a line `OPTIMAL LP SOLUTION FOUND`

along with additional information that is useful in tuning larger models for efficient solution. If things didn't go well, an appropriate message will be displayed indicating an error in processing the model description, or problems in finding a numerical solution.

In this case `glpsol`

says an optimal solution was found. The next step is to show the displayed results that were written to the file `out.txt`

.

In [10]:

```
f = open('out.txt');
print(f.read())
f.close()
```

`.val`

appended to each variable name indicates that we are looking at value of the variable found by the solver. Also associated with each variable is a `.dual`

value that will be useful in analyzing the results of linear optimization problems.

In [11]:

```
%%writefile input.csv
Name, Age
Abigail, 22.1
Brent, 24.1
Carla, 21.0
Doug, 20.0
```

In [12]:

```
%%script --out output glpsol -m /dev/stdin
set NAMES;
param Age{NAMES};
table tin IN "CSV" "input.csv" : NAMES <- [Name], Age;
for {n in NAMES}: printf "%s\n", n;
end;
```

In [13]:

```
print output
```

In [14]:

```
import pandas
pandas.read_csv("input.csv")
```

Out[14]:

In [15]:

```
%%script --out output glpsol -m /dev/stdin
# declare problem variables
var x;
var y;
var z;
# list all equations
eqn1 : 3*x + 2*y + z = 12;
eqn2 : 2.1*x + y = -3;
eqn3 : y - z = 4;
# solve
solve;
# output results to .csv file
table result {1..1} OUT "CSV" "out.csv" : x, y, z;
end;
```

First check the diagnostic output to verify that no errors were encountered.

In [16]:

```
print output
```

`table`

command is a `.csv`

file that can be read by virtually any spreadsheet or data analysis software. Let's first verify the format

In [17]:

```
f = open('out.csv');
print(f.read())
f.close()
```

In [18]:

```
import pandas
df = pandas.read_csv("out.csv");
display(df)
df.plot(kind='bar')
```

Out[18]:

In [19]:

```
%%writefile input.csv
A,B,C
12.2, 13.1, 13.2
```

In [20]:

```
%%script --out output glpsol -m /dev/stdin
set S;
param a;
param b;
param c;
table input IN "CSV" "input.csv": S <- [A], a~A, b~B, c~C;
end;
```

In [21]:

```
print output
```