Commit c01bc4d3 authored by Claus Jonathan Fritzemeier's avatar Claus Jonathan Fritzemeier
Browse files

added new vignette

parent 9c99a93d
# ignore pdf files
*.pdf
# ignore build r package:
glpkAPI_*.tar.gz
# ignore files made from build process
config.log
config.status
..Rcheck
*.o
*.so
src/Makevars
src/config.h
src/symbols.rds
Package: glpkAPI
Type: Package
Title: R Interface to C API of GLPK
Version: 1.2.11
Date: 2014-11-16
Version: 1.2.12
Date: 2015-01-05
Authors@R: c(person("Gabriel", "Gelius-Dietrich", role = c("aut", "cre"), email = "geliudie@uni-duesseldorf.de"))
Maintainer: Gabriel Gelius-Dietrich <geliudie@uni-duesseldorf.de>
Depends: R (>= 2.6.0)
......@@ -12,8 +12,8 @@ SystemRequirements: GLPK (>= 4.42)
License: GPL-3
LazyLoad: yes
Collate: generics.R glpk_ptrClass.R glpk.R glpkAPI.R zzz.R
Packaged: 2014-11-16 17:16:33 UTC; gabriel
Packaged: 2015-01-05 16:02:16 UTC; jonathan
Author: Gabriel Gelius-Dietrich [aut, cre]
NeedsCompilation: yes
Repository: CRAN
Date/Publication: 2014-11-16 22:12:16
Date/Publication: 2015-01-05 16:02:16
......@@ -4,6 +4,17 @@
\title{glpkAPI News}
\encoding{UTF-8}
% ---------------------------------------------------------------------------- %
\section{Changes in version 1.2.12 2015-01-05}{
\itemize{
\item added new vignette that describes the use of glpkAPI and GNU MathProg
language (GMPL). Thanks to Louis Luangkesorn
\footnote{lugerpitt@gmail.com. Thanks to Leo Lopes for his comments
and suggestions.}.
}
}
% ---------------------------------------------------------------------------- %
\section{Changes in version 1.2.11 2014-11-16}{
......
# A TRANSPORTATION PROBLEM
#
# This problem finds a least cost shipping schedule that meets
# requirements at markets and supplies at factories.
#
# References:
# Dantzig, G B., Linear Programming and Extensions
# Princeton University Press, Princeton, New Jersey, 1963,
# Chapter 3-3.
set I;
/* canning plants */
set J;
/* markets */
param a{i in I};
/* capacity of plant i in cases */
param b{j in J};
/* demand at market j in cases */
param d{i in I, j in J};
/* distance in thousands of miles */
param f;
/* freight in dollars per case per thousand miles */
param c{i in I, j in J} := f * d[i,j] / 1000;
/* transport cost in thousands of dollars per case */
var x{i in I, j in J} >= 0;
/* shipment quantities in cases */
minimize cost: sum{i in I, j in J} c[i,j] * x[i,j];
/* total transportation costs in thousands of dollars */
s.t. supply{i in I}: sum{j in J} x[i,j] <= a[i];
/* observe supply limit at plant i */
s.t. demand{j in J}: sum{i in I} x[i,j] >= b[j];
/* satisfy demand at market j */
data;
set I := Seattle San-Diego;
set J := New-York Chicago Topeka;
param a := Seattle 350
San-Diego 600;
param b := New-York 325
Chicago 300
Topeka 275;
param d : New-York Chicago Topeka :=
Seattle 2.5 1.7 1.8
San-Diego 2.5 1.8 1.4 ;
param f := 90;
end;
% \VignetteIndexEntry{R package for using the GNU Linear Programming Toolkit (GLPK) using MathProg or the API}
% \VignetteDepends{glpkAPI}
% \VignetteKeyword{Linear Progamming}
\documentclass[letterpaper]{article}
\usepackage{fancyvrb}
\title{Introduction to glpkAPI}
\author{Louis Luangkesorn \footnote{lugerpitt@gmail.com. Thanks to Leo Lopes for his comments and suggestions.}}
\begin{document}
\SweaveOpts{concordance=TRUE}
\maketitle
\section{Introduction}
This document introduces the use of the glpkAPI package\footnote{Package glpkAPI maintained by Gabriel Gelius-Dietrich} for R. The GNU Linear Programming Package (GLPK) is intended for solving linear programming (LP) and mixed integer programming (MIP) and other related problems. In addition, it includes facilities for converting problem information between the GNU MathProg language (a subset of the AMPL mathematical programming language), free and fixed MPS, and the CPLEX LP formats.\footnote{GNU Linear Programming Kit: Reference Manual, Version 4.54 Draft, March 2014.} The GLPK package is an interface into the C Application Programming Interface (API) to the GLPK solver.
This document will introduce the use of the GLPK package through the use of the cannery problem from Dantzig\footnote{The demand data here is from the GLPK documentation, which differs slightly from Dantzig, Linear Programming and Extensions, Princeton University Press, Princeton, NJ, 1963. The documentation demand values are used here for consistancy.} which is used in the GNU MathProg documentation.\footnote{GNU Linear Programming Kit: Modeling Language GNU MathProg, Version 4.50 Draft, May 2013.} The model file describing the cannery problem can be found in Appendix \ref{app:model}.
\section{Entering the model}
To use {\tt glpk}, first load the package.
<<>>=
library(glpkAPI)
@
Next read in the model and data.
There are several ways of entering the model. {\tt glpk} can read the model and data in a GNU MathProg Language (GMPL) model file. Alternatively, the model and data can be entered using the GLPK API.
\subsection{Reading a GNU MathProg Language model}
To use a GNU MathProg model requires several steps.
\begin{enumerate}
\item Allocating the workspace using {\tt initProbGLPK()}. The problem can then be given an name using {\tt setProbNameGLPK()}.
\item Reading model section using {\tt mplAllocWkspGLPK()} and
{\tt mplReadModelGLPK()}.
\item Reading data section(s) using {\tt mplReadDataGLPK()}.
\item Generating the model using {\tt mplGenerateGLPK()}.
\item Building the problem object using {\tt result <- mplBuildProbGLPK()}.
\item Solving the problem using {\tt solveSimplexGLPK()}.
\item Postsolving the model using {\tt mplPostsolveGLPK()}.
\item Freeing the workspace using {\tt mplFreeWkspGLPK()} and {\tt delProbGLPK()}
\end{enumerate}
<<>>=
mip <- initProbGLPK()
setProbNameGLPK(mip, "transport")
trans <- mplAllocWkspGLPK()
result <- mplReadModelGLPK(trans,
system.file("extdata", "transport.mod", package = "glpkAPI"), skip=0)
result <- mplGenerateGLPK(trans)
result <- mplBuildProbGLPK(trans, mip)
@
If the data was in a separate file, it would need to be read in using
\begin{verbatim}
mplReadDataGLPK(trans, "transport.mod")
\end{verbatim}
Then examine the problem size within R.
The rows represent the objective function as well as the supply and demand constraints.
<<>>=
numrows <- getNumRowsGLPK(mip)
numrows
for (i in 1:numrows){
print(getRowNameGLPK(mip, i))
}
@
The columns represent the decision variables, which are the units sent over the cannary-market links.
<<>>=
numcols <- getNumColsGLPK(mip)
numcols
for (j in 1:numcols){
print(getColNameGLPK(mip, j))
}
print(getNumNnzGLPK(mip))
@
After the model and data are entered, the model can then be solved using any one of many algorithms and the output would go to the specified output file. For the Simplex method, the {\tt solveSimplexGLPK()} takes the problem name and solves it using the Simplex method.
<<>>=
return <- solveSimplexGLPK(mip)
return <- mplPostsolveGLPK(trans, mip, GLP_MIP);
@
We can then look at the solution in terms of the objective and constraints
<<>>=
for (i in 1:numrows){
print(getRowNameGLPK(mip, i))
print(getRowPrimGLPK(mip, i))
}
@
as well as the decision variables.
<<>>=
for (j in 1:numcols){
print(getColNameGLPK(mip, j))
print(getColPrimGLPK(mip, j))
}
@
Finally, clean up the workspace.
<<>>=
mplFreeWkspGLPK(trans)
delProbGLPK(mip)
@
\subsection{Using the API}
If the problem data already in {\em R}, such as pulled from a database or the result of previous analysis, the model and the data can be specified using the API.
First create R data objects to hold the various model parameters.
<<>>=
print ("USING API")
canneries <- c("Seattle", "San-Diego")
capacity <- c(350, 600)
markets <- c("New-York", "Chicago", "Topeka")
demand <- c(325, 300, 275)
distance <- c(2.5, 2.5, 1.7, 1.8, 1.8, 1.4)
dim(distance) <- c(2, 3)
freight <- 90
@
To use the API, define a problem instance and indicate that the objective is to minimize cost.
<<>>=
lpi <- initProbGLPK()
setProbNameGLPK(lpi, "cannery API")
setObjNameGLPK(lpi, "Total Cost")
setObjDirGLPK(lpi, GLP_MIN)
@
There are 6 columns, corresponding to the six potential cannery-market pairs whose transport the model solving for, each of which has a lower bound of zero.
<<>>=
numlinks <- length(distance)
nummarkets <- length(markets)
numcanneries <- length(canneries)
addColsGLPK(lpi, numlinks)
for (i in 1:numcanneries){
cannerystartrow <- (i-1) * nummarkets
for (j in 1:nummarkets){
colname <-toString(c(canneries[i], markets[j]))
transcost <- distance[i, j]*freight/1000
setColNameGLPK(lpi, cannerystartrow+j, colname)
setColBndGLPK(lpi, cannerystartrow+j, GLP_LO, 0.0, 0.0)
setObjCoefsGLPK(lpi, cannerystartrow+j, transcost)
}
}
@
Next, we will add constraints. There are 5 constraints, two supply constraints relating to the canneries and three demand constraints relating to the markets. In addition, we will make the first row correspond to the objective function. The objective row will be free, and does not have upper or lower bounds.
<<>>=
numcanneries <- length(canneries)
nummarkets <- length(markets)
addRowsGLPK(lpi, numcanneries+nummarkets+1)
setRowsNamesGLPK(lpi, 1, getObjNameGLPK(lpi))
for (i in 1:numcanneries){
setRowsNamesGLPK(lpi, i+1, toString(c("Supply", canneries[i])))
setRowBndGLPK(lpi, i+1, GLP_UP, 0, capacity[i])
}
for (j in 1:nummarkets){
setRowsNamesGLPK(lpi, numcanneries+j+1, toString(c("Demand", markets[j])))
setRowBndGLPK(lpi, numcanneries+j+1, GLP_LO, demand[j], 0)
}
@
Now, load the constraint matrix which represents the objective function and the constraints. The non-zero values of the matrix are entered as three vectors, each with one element for each non-zero value. A vector to indicate the row, a vector to indicate the column, and a vector which contains the matrix element value. Last, we call {\tt loadMatrixGLPK(lpi)} to finish.
<<>>=
# create variables to hold the constraint information
ia <- numeric()
ja <- numeric()
ar <- numeric()
# add in objective coefficients
for (i in 1:numcols){
ia[i] <- 1
ja[i] <- i
ar[i] <- getObjCoefGLPK(lpi, i)
}
for (i in 1:numcanneries){
#supply constraints
cannerysupplyrow = numcols + (i-1)*nummarkets
for (j in 1:nummarkets){
ia[cannerysupplyrow+j] <- (i+1)
ja[cannerysupplyrow+j] <- (i-1)+numcanneries *(j-1)+1
ar[cannerysupplyrow+j] <- 1
}
#demand constraints
marketdemandrow = numcols+numcanneries * nummarkets
for (j in 1:nummarkets){
colnum <- (i-1)*nummarkets+j
ia[marketdemandrow + colnum] <- numcanneries+j+1
ja[marketdemandrow + colnum] <- colnum
ar[marketdemandrow + colnum] <- 1
}
}
loadMatrixGLPK(lpi, length(ia), ia, ja, ar)
@
Then, examine the problem entered in the API.
<<>>=
numrows <- getNumRowsGLPK(lpi)
numrows
numcols <- getNumColsGLPK(lpi)
numcols
for (i in 1:numrows){
print(getRowNameGLPK(lpi, i))
}
for (j in 1:numcols){
print(getColNameGLPK(lpi, j))
}
print(getNumNnzGLPK(lpi))
@
Finally solve using the simplex method and look at the solution.
<<>>=
solveSimplexGLPK(lpi)
for (i in 1:numrows){
print(getRowNameGLPK(lpi, i))
print(getRowPrimGLPK(lpi, i))
}
for (j in 1:numcols){
print(getColNameGLPK(lpi, j))
print(getColPrimGLPK(lpi, j))
}
@
And save the results to a file.
<<>>=
printSolGLPK(lpi, "transout.api")
@
\subsection{Using API to modify the model}
Now, we will solve the version of the problem that is found in Dantzig. The demand at New York and Topeka are both 300 instead of 325 and 275. This next section will use the API to modify the problem as read through the MathProg file.
In order to examine an individual row, we need to index the rows and columns. This is done through the use of {\tt createIndexGLPK()}. Then we can use the {\tt findRowGLPK()} and {\tt findColGLPK()}
<<>>=
cindex <- createIndexGLPK(lpi)
new_york_row = findRowGLPK(lpi, "Demand, New-York")
topeka_row = findRowGLPK(lpi, "Demand, Topeka")
new_york_row
topeka_row
setRowBndGLPK(lpi, new_york_row, GLP_LO, 300, 0)
setRowBndGLPK(lpi, topeka_row, GLP_LO, 300, 0)
@
We can solve this modified problem and look at the results.
<<>>=
solveSimplexGLPK(lpi)
for (i in 1:numrows){
print(getRowNameGLPK(lpi, i))
print(getRowPrimGLPK(lpi, i))
print(getRowDualGLPK(lpi, i))
}
for (j in 1:numcols){
print(getColNameGLPK(lpi, j))
print(getColPrimGLPK(lpi, j))
print(getColDualGLPK(lpi,j))
print(getObjCoefGLPK(lpi, j))
}
@
Finally, clean up the workspace.
<<>>=
delProbGLPK(lpi)
@
\appendix
\section{Model file \label{app:model}}
{\bf {\it TRANSPORT.MOD}}
\VerbatimInput{"../inst/extdata/transport.mod"}
\section{Output \label{app:output}}
The following is the output of the command:
{\tt printSolGLPK(lpi, "transout.api")}
\VerbatimInput{transout.api}
\end{document}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment