{ "metadata": { "name": "" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "heading", "level": 6, "metadata": {}, "source": [ "The latest version of this IPython notebook is available at [http://github.com/jckantor/ESTM60203](http://github.com/jckantor/ESTM60203) for noncommercial use under terms of the [Creative Commons Attribution Noncommericial ShareAlike License (CC BY-NC-SA 4.0)](http://creativecommons.org/licenses/by-nc-sa/4.0/)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "J.C. Kantor (Kantor.1@nd.edu)" ] }, { "cell_type": "heading", "level": 1, "metadata": {}, "source": [ "Optimal Mixture and Blending Problems" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This [IPython notebook](http://ipython.org/notebook.html) demonstrates the development of models to solve optimal blending and mixture problems using GLPK/MathProg." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Initializations" ] }, { "cell_type": "code", "collapsed": false, "input": [ "from IPython.core.display import HTML\n", "HTML(open(\"styles/custom.css\", \"r\").read())" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n" ], "metadata": {}, "output_type": "pyout", "prompt_number": 1, "text": [ "" ] } ], "prompt_number": 1 }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Background" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Mixture and blending problems are among the most commonly encountered optimization problems in real world applications. The basic problem is to determine a blend (mixture) of components maximizing subject to constraints on the blend. Examples include diet, product blending, financial portfolios, and many, many others.\n", "\n", "This notebook uses a the diet problem from [Chapter 2 of the AMPL book](http://www.ampl.com/BOOK/download.html) to demonstrate the formulation and solution of blending problems in MathProg. The problem is solved several times in order to demonstrate features of MathProg useful in constructing models that can be reused for other data sets, and extended to much larger applications." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Diet Problem" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We'll begin by reviewing data for The data is organized as three [pandas DataFrames](http://pandas.pydata.org/) (some information on DataFrames is [here](http://pandas.pydata.org/pandas-docs/dev/dsintro.html) and [here](http://pandas.pydata.org/pandas-docs/dev/10min.html?highlight=panels)). For larger scale problems, this data would be extracted from spreadsheets or databases." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Weekly Nutrition Requirements" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first data set contains lower and upper bounds on weekly nutrition expressed a percentage of the recommended minimum daily requirements." ] }, { "cell_type": "code", "collapsed": false, "input": [ "import pandas as pd\n", "\n", "req = {\n", " 'A' : [700, 10000],\n", " 'C' : [700, 10000],\n", " 'B1': [700, 10000],\n", " 'B2': [700, 10000]}\n", "\n", "display(pd.DataFrame(req.values(), index = req.keys(), columns = ['n_min', 'n_max']))" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
n_minn_max
A 700 10000
C 700 10000
B1 700 10000
B2 700 10000
\n", "

4 rows \u00d7 2 columns

\n", "
" ], "metadata": {}, "output_type": "display_data", "text": [ " n_min n_max\n", "A 700 10000\n", "C 700 10000\n", "B1 700 10000\n", "B2 700 10000\n", "\n", "[4 rows x 2 columns]" ] } ], "prompt_number": 1 }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Nutrition Data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The second data set includes 'label data' from some typical package goods." ] }, { "cell_type": "code", "collapsed": false, "input": [ "nutr = {\n", " 'BEF' : {'A': 60, 'C': 20, 'B1': 10, 'B2': 15},\n", " 'CHK' : {'A': 8, 'C': 0, 'B1': 20, 'B2': 20},\n", " 'FSH' : {'A': 8, 'C': 10, 'B1': 15, 'B2': 10},\n", " 'HAM' : {'A': 40, 'C': 40, 'B1': 35, 'B2': 10},\n", " 'MCH' : {'A': 15, 'C': 35, 'B1': 15, 'B2': 15},\n", " 'MTL' : {'A': 70, 'C': 30, 'B1': 15, 'B2': 15},\n", " 'SPG' : {'A': 25, 'C': 50, 'B1': 25, 'B2': 15},\n", " 'TUR' : {'A': 60, 'C': 20, 'B1': 15, 'B2': 10}}\n", "\n", "display(pd.DataFrame.from_dict(nutr).transpose())" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
AB1B2C
BEF 60 10 15 20
CHK 8 20 20 0
FSH 8 15 10 10
HAM 40 35 10 40
MCH 15 15 15 35
MTL 70 15 15 30
SPG 25 25 15 50
TUR 60 15 10 20
\n", "

8 rows \u00d7 4 columns

\n", "
" ], "metadata": {}, "output_type": "display_data", "text": [ " A B1 B2 C\n", "BEF 60 10 15 20\n", "CHK 8 20 20 0\n", "FSH 8 15 10 10\n", "HAM 40 35 10 40\n", "MCH 15 15 15 35\n", "MTL 70 15 15 30\n", "SPG 25 25 15 50\n", "TUR 60 15 10 20\n", "\n", "[8 rows x 4 columns]" ] } ], "prompt_number": 14 }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Price Data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The third data set provides price information for the packaged foods." ] }, { "cell_type": "code", "collapsed": false, "input": [ "price ={'BEF' : ['Beef', 3.19],\n", " 'CHK' : ['Chicken', 2.59],\n", " 'FSH' : ['Fish', 2.29],\n", " 'HAM' : ['Ham', 2.89],\n", " 'MCH' : ['Macaroni & Cheese', 1.89],\n", " 'MTL' : ['Meat Loaf', 1.99],\n", " 'SPG' : ['Spaghetti', 1.99],\n", " 'TUR' : ['Turkey', 2.49]}\n", "\n", "display(pd.DataFrame(price.values(), index = price.keys(), columns = ['food','price']))" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
foodprice
HAM Ham 2.89
MTL Meat Loaf 1.99
MCH Macaroni & Cheese 1.89
FSH Fish 2.29
TUR Turkey 2.49
CHK Chicken 2.59
BEF Beef 3.19
SPG Spaghetti 1.99
\n", "

8 rows \u00d7 2 columns

\n", "
" ], "metadata": {}, "output_type": "display_data", "text": [ " food price\n", "HAM Ham 2.89\n", "MTL Meat Loaf 1.99\n", "MCH Macaroni & Cheese 1.89\n", "FSH Fish 2.29\n", "TUR Turkey 2.49\n", "CHK Chicken 2.59\n", "BEF Beef 3.19\n", "SPG Spaghetti 1.99\n", "\n", "[8 rows x 2 columns]" ] } ], "prompt_number": 15 }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Problem Statement" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Determine a shopping list that meets the nutrition requirements for minimum cost." ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "A Basic Model" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This first attempt at a model for the diet problem will encode the basic elements of the problem. We'll include a decision variable for each type of packaged good, and explicitly write out the objective function, and each of the nutrition requirements.\n", "\n", "The following cell uses the `script` cell magic to run the MathProg model with the `glpsol` command line. This requires that you [install the `glpk` package](http://en.wikibooks.org/wiki/GLPK/Obtaining_GLPK) on the machine used to execute this notebook." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%script glpsol -m /dev/stdin -o /dev/stdout\n", "\n", "var xBEF >= 0; \n", "var xCHK >= 0; \n", "var xFSH >= 0;\n", "var xHAM >= 0; \n", "var xMCH >= 0; \n", "var xMTL >= 0;\n", "var xSPG >= 0; \n", "var xTUR >= 0;\n", "\n", "minimize Total_Cost:\n", " 3.19*xBEF + 2.59*xCHK + 2.29*xFSH + 2.89*xHAM \n", " + 1.89*xMCH + 1.99*xMTL + 1.99*xSPG + 2.49*xTUR;\n", " \n", "subject to A:\n", " 700 <= 60*xBEF + 8*xCHK + 8*xFSH + 40*xHAM \n", " + 15*xMCH + 70*xMTL + 25*xSPG + 60*xTUR <= 10000;\n", " \n", "subject to C:\n", " 700 <= 20*xBEF + 0*xCHK + 10*xFSH + 40*xHAM\n", " + 35*xMCH + 30*xMTL + 50*xSPG + 20*xTUR <= 10000;\n", " \n", "subject to B1:\n", " 700 <= 10*xBEF + 20*xCHK + 15*xFSH + 35*xHAM\n", " + 15*xMCH + 15*xMTL + 25*xSPG + 15*xTUR <= 10000;\n", " \n", "subject to B2:\n", " 700 <= 15*xBEF + 20*xCHK + 10*xFSH + 10*xHAM\n", " + 15*xMCH + 15*xMTL + 15*xSPG + 10*xTUR <= 10000;\n", "\n", "end;" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "GLPSOL: GLPK LP/MIP Solver, v4.52\n", "Parameter(s) specified in the command line:\n", " -m /dev/stdin -o /dev/stdout\n", "Reading model section from /dev/stdin...\n", "/dev/stdin:31: warning: final NL missing before end of file\n", "31 lines were read\n", "Generating Total_Cost...\n", "Generating A...\n", "Generating C...\n", "Generating B1...\n", "Generating B2...\n", "Model has been successfully generated\n", "GLPK Simplex Optimizer, v4.52\n", "5 rows, 8 columns, 39 non-zeros\n", "Preprocessing...\n", "4 rows, 8 columns, 31 non-zeros\n", "Scaling...\n", " A: min|aij| = 8.000e+00 max|aij| = 7.000e+01 ratio = 8.750e+00\n", "GM: min|aij| = 5.017e-01 max|aij| = 1.993e+00 ratio = 3.972e+00\n", "EQ: min|aij| = 2.549e-01 max|aij| = 1.000e+00 ratio = 3.922e+00\n", "Constructing initial basis...\n", "Size of triangular part is 4\n", " 0: obj = 0.000000000e+00 infeas = 2.845e+03 (0)\n", "* 4: obj = 1.185625000e+02 infeas = 0.000e+00 (0)\n", "* 7: obj = 8.820000000e+01 infeas = 0.000e+00 (0)\n", "OPTIMAL LP SOLUTION FOUND\n", "Time used: 0.0 secs\n", "Memory used: 0.1 Mb (110559 bytes)\n", "Writing basic solution to `/dev/stdout'...\n", "Problem: stdin\n", "Rows: 5\n", "Columns: 8\n", "Non-zeros: 39\n", "Status: OPTIMAL\n", "Objective: Total_Cost = 88.2 (MINimum)\n", "\n", " No. Row name St Activity Lower bound Upper bound Marginal\n", "------ ------------ -- ------------- ------------- ------------- -------------\n", " 1 Total_Cost B 88.2 \n", " 2 A NL 700 700 10000 0.00181818 \n", " 3 C B 1633.33 700 10000 \n", " 4 B1 B 700 700 10000 \n", " 5 B2 NL 700 700 10000 0.124182 \n", "\n", " No. Column name St Activity Lower bound Upper bound Marginal\n", "------ ------------ -- ------------- ------------- ------------- -------------\n", " 1 xBEF NL 0 0 1.21818 \n", " 2 xCHK NL 0 0 0.0918182 \n", " 3 xFSH NL 0 0 1.03364 \n", " 4 xHAM NL 0 0 1.57545 \n", " 5 xMCH B 46.6667 0 \n", " 6 xMTL B 0 0 \n", " 7 xSPG NL 0 0 0.0818182 \n", " 8 xTUR NL 0 0 1.13909 \n", "\n", "Karush-Kuhn-Tucker optimality conditions:\n", "\n", "KKT.PE: max.abs.err = 1.14e-13 on row 2\n", " max.rel.err = 8.11e-17 on row 2\n", " High quality\n", "\n", "KKT.PB: max.abs.err = 1.14e-13 on row 4\n", " max.rel.err = 1.62e-16 on row 4\n", " High quality\n", "\n", "KKT.DE: max.abs.err = 2.22e-16 on column 1\n", " max.rel.err = 6.00e-17 on column 8\n", " High quality\n", "\n", "KKT.DB: max.abs.err = 0.00e+00 on row 0\n", " max.rel.err = 0.00e+00 on row 0\n", " High quality\n", "\n", "End of output\n" ] } ], "prompt_number": 16 }, { "cell_type": "markdown", "metadata": {}, "source": [ "The previous cell used a 'cell magic' to run the model, with the results placed into a file `output.txt`. This next cell uses standard python commands to read and display the output file." ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Questions" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* What is the total cost of What are we eating, and how much does it cost?\n", "* Is this a realistic solution? How would like to modify the problem?\n", "* What do the shadow costs (also called marginal costs, or sensitivities) mean?\n", "* Can we apply this same model to other data sets?" ] }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Extending the Model" ] }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Introducing MathProg Sets" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this second version we introduce a set to represent all types of packaged foods. The use of a set allows us to declare all of the decision variables in one line. The decision variables now have subscripts associated with members from the set of foods." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%script glpsol -m /dev/stdin -o /dev/stdout --out output\n", "\n", "set FOODS := {'BEF','CHK','FSH','HAM','MCH','MTL','SPG','TUR'};\n", "\n", "var x{FOODS} >= 0;\n", "\n", "minimize Total_Cost:\n", " 3.19*x['BEF'] + 2.59*x['CHK'] + 2.29*x['FSH'] + 2.89*x['HAM'] \n", " + 1.89*x['MCH'] + 1.99*x['MTL'] + 1.99*x['SPG'] + 2.49*x['TUR'];\n", " \n", "subject to A:\n", " 700 <= 60*x['BEF'] + 8*x['CHK'] + 8*x['FSH'] + 40*x['HAM']\n", " + 15*x['MCH'] + 70*x['MTL'] + 25*x['SPG'] + 60*x['TUR'] <= 10000;\n", " \n", "subject to C:\n", " 700 <= 20*x['BEF'] + 0*x['CHK'] + 10*x['FSH'] + 40*x['HAM']\n", " + 35*x['MCH'] + 30*x['MTL'] + 50*x['SPG'] + 20*x['TUR'] <= 10000;\n", " \n", "subject to B1:\n", " 700 <= 10*x['BEF'] + 20*x['CHK'] + 15*x['FSH'] + 35*x['HAM']\n", " + 15*x['MCH'] + 15*x['MTL'] + 25*x['SPG'] + 15*x['TUR'] <= 10000;\n", " \n", "subject to B2:\n", " 700 <= 15*x['BEF'] + 20*x['CHK'] + 10*x['FSH'] + 10*x['HAM']\n", " + 15*x['MCH'] + 15*x['MTL'] + 15*x['SPG'] + 10*x['TUR'] <= 10000;\n", "\n", "end;" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 17 }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Adding a Data Section" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next we introduce a set for the nutrients. Much of the problem data can be indexed by memebers of the set of nutrients, and this data is defined in the data section. " ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%script glpsol -m /dev/stdin -o /dev/stdout --out output\n", "\n", "set FOODS;\n", "set NUTRS;\n", "\n", "param price{FOODS} >= 0;\n", "param n_min{NUTRS} >= 0;\n", "param n_max{NUTRS} >= 0;\n", "\n", "var x{FOODS} >= 0;\n", "\n", "minimize Total_Cost: sum {f in FOODS} price[f]*x[f];\n", " \n", "subject to A:\n", " n_min['A'] <= 60*x['BEF'] + 8*x['CHK'] + 8*x['FSH'] + 40*x['HAM']\n", " + 15*x['MCH'] + 70*x['MTL'] + 25*x['SPG'] + 60*x['TUR'] <= n_max['A'];\n", " \n", "subject to C:\n", " n_min['C'] <= 20*x['BEF'] + 0*x['CHK'] + 10*x['FSH'] + 40*x['HAM']\n", " + 35*x['MCH'] + 30*x['MTL'] + 50*x['SPG'] + 20*x['TUR'] <= n_max['C'];\n", " \n", "subject to B1:\n", " n_min['B1'] <= 10*x['BEF'] + 20*x['CHK'] + 15*x['FSH'] + 35*x['HAM']\n", " + 15*x['MCH'] + 15*x['MTL'] + 25*x['SPG'] + 15*x['TUR'] <= n_max['B1'];\n", " \n", "subject to B2:\n", " n_min['B2'] <= 15*x['BEF'] + 20*x['CHK'] + 10*x['FSH'] + 10*x['HAM']\n", " + 15*x['MCH'] + 15*x['MTL'] + 15*x['SPG'] + 10*x['TUR'] <= n_max['B2'];\n", " \n", "data;\n", "\n", "param : FOODS : price :=\n", " BEF 3.19\n", " CHK 2.59\n", " FSH 2.29\n", " HAM 2.89\n", " MCH 1.89\n", " MTL 1.99\n", " SPG 1.99\n", " TUR 2.49;\n", "\n", "param : NUTRS : n_min n_max :=\n", " A 700 10000\n", " C 700 10000\n", " B1 700 10000\n", " B2 700 10000;\n", " \n", "end;" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 18 }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Factoring the Model and Data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The factoring of the problem into separate model and data sections is completed by introducing a two dimensional data set for the nutrient content of the packaged foods. The parameter data is placed in the data section, and the model constraints written in terms of the indexed parameters." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%script glpsol -m /dev/stdin -o /dev/stdout --out output\n", "\n", "set FOODS;\n", "set NUTRS;\n", "\n", "param price{FOODS} >= 0;\n", "param n_min{NUTRS} >= 0;\n", "param n_max{NUTRS} >= 0;\n", "param a{FOODS,NUTRS} >= 0;\n", "\n", "var x{FOODS} >= 0;\n", "\n", "minimize Total_Cost: sum {f in FOODS} price[f]*x[f];\n", "\n", "subject to n_req {n in NUTRS}:\n", " n_min[n] <= sum {f in FOODS} a[f,n] * x[f] <= n_max[n];\n", "\n", "data;\n", "\n", "param : FOODS : price :=\n", " BEF 3.19\n", " CHK 2.59\n", " FSH 2.29\n", " HAM 2.89\n", " MCH 1.89\n", " MTL 1.99\n", " SPG 1.99\n", " TUR 2.49;\n", "\n", "param : NUTRS : n_min n_max :=\n", " A 700 10000\n", " C 700 10000\n", " B1 700 10000\n", " B2 700 10000;\n", "\n", "param a : A C B1 B2 :=\n", " BEF 60 20 10 15\n", " CHK 8 0 20 20\n", " FSH 8 10 15 10\n", " HAM 40 40 35 10\n", " MCH 15 35 15 15\n", " MTL 70 30 15 15\n", " SPG 25 50 25 15\n", " TUR 60 20 15 10;\n", " \n", "end;" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 19 }, { "cell_type": "heading", "level": 3, "metadata": {}, "source": [ "Post-Processing Results" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The output from glpk/MathProg can be enchanced by adding `printf` statements for selected data, or `table` statements for access to structured data indexed by sets." ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%script glpsol -m /dev/stdin -o output.txt -y display.txt --out output\n", "\n", "set FOODS;\n", "set NUTRS;\n", "\n", "param price{FOODS} >= 0;\n", "param x_min{FOODS} >= 0;\n", "param x_max{FOODS} >= 0;\n", "\n", "param n_min{NUTRS} >= 0;\n", "param n_max{NUTRS} >= 0;\n", "\n", "param a{FOODS,NUTRS} >= 0;\n", "\n", "var x{f in FOODS} >= 0;\n", "\n", "minimize Total_Cost: sum {f in FOODS} price[f]*x[f];\n", "\n", "subject to n_req {n in NUTRS}:\n", " n_min[n] <= sum {f in FOODS} a[f,n] * x[f] <= n_max[n];\n", "\n", "solve;\n", "\n", "printf \"\\nMinimum Cost Diet = %6.2f $/week.\\n\\n\", Total_Cost;\n", "\n", "table results {f in FOODS} OUT \"CSV\" \"output.csv\" \"Table\":\n", " f ~ Food,\n", " x[f] ~ Quantity,\n", " price[f] ~ Price;\n", " \n", "data;\n", "\n", "param : FOODS : price :=\n", " BEF 3.19\n", " CHK 2.59\n", " FSH 2.29\n", " HAM 2.89\n", " MCH 1.89\n", " MTL 1.99\n", " SPG 1.99\n", " TUR 2.49;\n", "\n", "param : NUTRS : n_min n_max :=\n", " A 700 10000\n", " C 700 10000\n", " B1 700 10000\n", " B2 700 10000;\n", "\n", "param a : A C B1 B2 :=\n", " BEF 60 20 10 15\n", " CHK 8 0 20 20\n", " FSH 8 10 15 10\n", " HAM 40 40 35 10\n", " MCH 15 35 15 15\n", " MTL 70 30 15 15\n", " SPG 25 50 25 15\n", " TUR 60 20 15 10;\n", " \n", "end;" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 20 }, { "cell_type": "code", "collapsed": false, "input": [ "print output" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "GLPSOL: GLPK LP/MIP Solver, v4.52\n", "Parameter(s) specified in the command line:\n", " -m /dev/stdin -o output.txt -y display.txt\n", "Reading model section from /dev/stdin...\n", "Reading data section from /dev/stdin...\n", "/dev/stdin:58: warning: final NL missing before end of file\n", "58 lines were read\n", "Generating Total_Cost...\n", "Generating n_req...\n", "Model has been successfully generated\n", "GLPK Simplex Optimizer, v4.52\n", "5 rows, 8 columns, 39 non-zeros\n", "Preprocessing...\n", "4 rows, 8 columns, 31 non-zeros\n", "Scaling...\n", " A: min|aij| = 8.000e+00 max|aij| = 7.000e+01 ratio = 8.750e+00\n", "GM: min|aij| = 5.017e-01 max|aij| = 1.993e+00 ratio = 3.972e+00\n", "EQ: min|aij| = 2.549e-01 max|aij| = 1.000e+00 ratio = 3.922e+00\n", "Constructing initial basis...\n", "Size of triangular part is 4\n", " 0: obj = 0.000000000e+00 infeas = 2.845e+03 (0)\n", "* 4: obj = 1.185625000e+02 infeas = 0.000e+00 (0)\n", "* 7: obj = 8.820000000e+01 infeas = 0.000e+00 (0)\n", "OPTIMAL LP SOLUTION FOUND\n", "Time used: 0.0 secs\n", "Memory used: 0.1 Mb (135090 bytes)\n", "Writing results...\n", "Model has been successfully processed\n", "Writing basic solution to `output.txt'...\n", "\n" ] } ], "prompt_number": 21 }, { "cell_type": "code", "collapsed": false, "input": [ "print(open('output.txt').read())" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Problem: stdin\n", "Rows: 5\n", "Columns: 8\n", "Non-zeros: 39\n", "Status: OPTIMAL\n", "Objective: Total_Cost = 88.2 (MINimum)\n", "\n", " No. Row name St Activity Lower bound Upper bound Marginal\n", "------ ------------ -- ------------- ------------- ------------- -------------\n", " 1 Total_Cost B 88.2 \n", " 2 n_req[A] NL 700 700 10000 0.00181818 \n", " 3 n_req[C] B 1633.33 700 10000 \n", " 4 n_req[B1] B 700 700 10000 \n", " 5 n_req[B2] NL 700 700 10000 0.124182 \n", "\n", " No. Column name St Activity Lower bound Upper bound Marginal\n", "------ ------------ -- ------------- ------------- ------------- -------------\n", " 1 x[BEF] NL 0 0 1.21818 \n", " 2 x[CHK] NL 0 0 0.0918182 \n", " 3 x[FSH] NL 0 0 1.03364 \n", " 4 x[HAM] NL 0 0 1.57545 \n", " 5 x[MCH] B 46.6667 0 \n", " 6 x[MTL] B 0 0 \n", " 7 x[SPG] NL 0 0 0.0818182 \n", " 8 x[TUR] NL 0 0 1.13909 \n", "\n", "Karush-Kuhn-Tucker optimality conditions:\n", "\n", "KKT.PE: max.abs.err = 1.14e-13 on row 2\n", " max.rel.err = 8.11e-17 on row 2\n", " High quality\n", "\n", "KKT.PB: max.abs.err = 1.14e-13 on row 4\n", " max.rel.err = 1.62e-16 on row 4\n", " High quality\n", "\n", "KKT.DE: max.abs.err = 2.22e-16 on column 1\n", " max.rel.err = 6.00e-17 on column 8\n", " High quality\n", "\n", "KKT.DB: max.abs.err = 0.00e+00 on row 0\n", " max.rel.err = 0.00e+00 on row 0\n", " High quality\n", "\n", "End of output\n", "\n" ] } ], "prompt_number": 22 }, { "cell_type": "code", "collapsed": false, "input": [ "print(open('display.txt').read())" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "\n", "Minimum Cost Diet = 88.20 $/week.\n", "\n", "\n" ] } ], "prompt_number": 23 }, { "cell_type": "code", "collapsed": false, "input": [ "import pandas\n", "df = pandas.read_csv('output.csv')\n", "display(df)\n", "df['Quantity'].plot(kind='bar').set_xticklabels(df['Food']);" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
FoodQuantityPrice
0 BEF 0.000000 3.19
1 CHK 0.000000 2.59
2 FSH 0.000000 2.29
3 HAM 0.000000 2.89
4 MCH 46.666667 1.89
5 MTL 0.000000 1.99
6 SPG 0.000000 1.99
7 TUR 0.000000 2.49
\n", "

8 rows \u00d7 3 columns

\n", "
" ], "metadata": {}, "output_type": "display_data", "text": [ " Food Quantity Price\n", "0 BEF 0.000000 3.19\n", "1 CHK 0.000000 2.59\n", "2 FSH 0.000000 2.29\n", "3 HAM 0.000000 2.89\n", "4 MCH 46.666667 1.89\n", "5 MTL 0.000000 1.99\n", "6 SPG 0.000000 1.99\n", "7 TUR 0.000000 2.49\n", "\n", "[8 rows x 3 columns]" ] }, { "metadata": {}, "output_type": "display_data", "png": "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\nAElFTkSuQmCC\n", "text": [ "" ] } ], "prompt_number": 24 }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Adding Problem Features" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The new model adds a number of additional features, including\n", "\n", "* Force diversification by imposing bounds on the minimum and maximum number of packages.\n", "* Constraining the solution to integer values" ] }, { "cell_type": "code", "collapsed": false, "input": [ "%%script glpsol -m /dev/stdin -o display.txt --out output\n", "\n", "set FOODS;\n", "set NUTRS;\n", "\n", "param price{FOODS} >= 0;\n", "param x_min{FOODS} >= 0;\n", "param x_max{FOODS} >= 0;\n", "\n", "param n_min{NUTRS} >= 0;\n", "param n_max{NUTRS} >= 0;\n", "\n", "param a{FOODS,NUTRS} >= 0;\n", "\n", "var x{f in FOODS} integer >= x_min[f], <= x_max[f];\n", "\n", "minimize Total_Cost: sum {f in FOODS} price[f]*x[f];\n", "\n", "subject to n_req {n in NUTRS}:\n", " n_min[n] <= sum {f in FOODS} a[f,n] * x[f] <= n_max[n];\n", " \n", "solve;\n", "\n", "printf \"\\nMinimum Cost Diet = %6.2f $/week.\\n\\n\", Total_Cost;\n", "\n", "table results {f in FOODS} OUT \"CSV\" \"output.csv\" \"Table\":\n", " f ~ Food,\n", " x[f] ~ Quantity,\n", " price[f] ~ Price;\n", "\n", "data;\n", "\n", "param : FOODS : price x_min x_max :=\n", " BEF 3.19 2 30\n", " CHK 2.59 2 30\n", " FSH 2.29 2 30\n", " HAM 2.89 2 30\n", " MCH 1.89 2 30\n", " MTL 1.99 2 30\n", " SPG 1.99 2 30\n", " TUR 2.49 2 30;\n", "\n", "param : NUTRS : n_min n_max :=\n", " A 700 10000 \n", " C 700 10000\n", " B1 700 10000\n", " B2 700 10000\n", " NA 0 40000\n", " CAL 16000 24000;\n", "\n", "param a : A C B1 B2 NA CAL :=\n", " BEF 60 20 10 15 938 295\n", " CHK 8 0 20 20 2180 770\n", " FSH 8 10 15 10 945 440\n", " HAM 40 40 35 10 278 430\n", " MCH 15 35 15 15 1182 315\n", " MTL 70 30 15 15 896 400\n", " SPG 25 50 25 15 1329 370\n", " TUR 60 20 15 10 1397 450;\n", " \n", "end;" ], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 25 }, { "cell_type": "code", "collapsed": false, "input": [ "print output" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "GLPSOL: GLPK LP/MIP Solver, v4.52\n", "Parameter(s) specified in the command line:\n", " -m /dev/stdin -o display.txt\n", "Reading model section from /dev/stdin...\n", "Reading data section from /dev/stdin...\n", "/dev/stdin:60: warning: final NL missing before end of file\n", "60 lines were read\n", "Generating Total_Cost...\n", "Generating n_req...\n", "Model has been successfully generated\n", "GLPK Integer Optimizer, v4.52\n", "7 rows, 8 columns, 55 non-zeros\n", "8 integer variables, none of which are binary\n", "Preprocessing...\n", "6 rows, 8 columns, 47 non-zeros\n", "8 integer variables, none of which are binary\n", "Scaling...\n", " A: min|aij| = 8.000e+00 max|aij| = 2.180e+03 ratio = 2.725e+02\n", "GM: min|aij| = 3.996e-01 max|aij| = 2.502e+00 ratio = 6.262e+00\n", "EQ: min|aij| = 1.597e-01 max|aij| = 1.000e+00 ratio = 6.262e+00\n", "2N: min|aij| = 1.172e-01 max|aij| = 1.250e+00 ratio = 1.067e+01\n", "Constructing initial basis...\n", "Size of triangular part is 6\n", "Solving LP relaxation...\n", "GLPK Simplex Optimizer, v4.52\n", "6 rows, 8 columns, 47 non-zeros\n", " 0: obj = 3.864000000e+01 infeas = 5.163e+01 (0)\n", "* 10: obj = 1.628185401e+02 infeas = 0.000e+00 (0)\n", "* 13: obj = 1.364032777e+02 infeas = 0.000e+00 (0)\n", "OPTIMAL LP SOLUTION FOUND\n", "Integer optimization begins...\n", "+ 13: mip = not found yet >= -inf (1; 0)\n", "Solution found by heuristic: 138.94\n", "+ 36: mip = 1.389400000e+02 >= tree is empty 0.0% (0; 15)\n", "INTEGER OPTIMAL SOLUTION FOUND\n", "Time used: 0.0 secs\n", "Memory used: 0.1 Mb (148951 bytes)\n", "\n", "Minimum Cost Diet = 138.94 $/week.\n", "\n", "Writing results...\n", "Model has been successfully processed\n", "Writing MIP solution to `display.txt'...\n", "\n" ] } ], "prompt_number": 26 }, { "cell_type": "code", "collapsed": false, "input": [ "print(open('display.txt').read())" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "Problem: stdin\n", "Rows: 7\n", "Columns: 8 (8 integer, 0 binary)\n", "Non-zeros: 55\n", "Status: INTEGER OPTIMAL\n", "Objective: Total_Cost = 138.94 (MINimum)\n", "\n", " No. Row name Activity Lower bound Upper bound\n", "------ ------------ ------------- ------------- -------------\n", " 1 Total_Cost 138.94 \n", " 2 n_req[A] 2682 700 10000 \n", " 3 n_req[C] 1840 700 10000 \n", " 4 n_req[B1] 1360 700 10000 \n", " 5 n_req[B2] 705 700 10000 \n", " 6 n_req[NA] 39916 0 40000 \n", " 7 n_req[CAL] 23630 16000 24000 \n", "\n", " No. Column name Activity Lower bound Upper bound\n", "------ ------------ ------------- ------------- -------------\n", " 1 x[BEF] * 2 2 30 \n", " 2 x[CHK] * 2 2 30 \n", " 3 x[FSH] * 2 2 30 \n", " 4 x[HAM] * 25 2 30 \n", " 5 x[MCH] * 2 2 30 \n", " 6 x[MTL] * 19 2 30 \n", " 7 x[SPG] * 2 2 30 \n", " 8 x[TUR] * 2 2 30 \n", "\n", "Integer feasibility conditions:\n", "\n", "KKT.PE: max.abs.err = 0.00e+00 on row 0\n", " max.rel.err = 0.00e+00 on row 0\n", " High quality\n", "\n", "KKT.PB: max.abs.err = 0.00e+00 on row 0\n", " max.rel.err = 0.00e+00 on row 0\n", " High quality\n", "\n", "End of output\n", "\n" ] } ], "prompt_number": 27 }, { "cell_type": "code", "collapsed": false, "input": [ "import pandas\n", "df = pandas.read_csv('output.csv')\n", "display(df)\n", "df['Quantity'].plot(kind='bar').set_xticklabels(df['Food']);" ], "language": "python", "metadata": {}, "outputs": [ { "html": [ "
\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
FoodQuantityPrice
0 BEF 2 3.19
1 CHK 2 2.59
2 FSH 2 2.29
3 HAM 25 2.89
4 MCH 2 1.89
5 MTL 19 1.99
6 SPG 2 1.99
7 TUR 2 2.49
\n", "

8 rows \u00d7 3 columns

\n", "
" ], "metadata": {}, "output_type": "display_data", "text": [ " Food Quantity Price\n", "0 BEF 2 3.19\n", "1 CHK 2 2.59\n", "2 FSH 2 2.29\n", "3 HAM 25 2.89\n", "4 MCH 2 1.89\n", "5 MTL 19 1.99\n", "6 SPG 2 1.99\n", "7 TUR 2 2.49\n", "\n", "[8 rows x 3 columns]" ] }, { "metadata": {}, "output_type": "display_data", "png": "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\n", "text": [ "" ] } ], "prompt_number": 28 }, { "cell_type": "heading", "level": 2, "metadata": {}, "source": [ "Exercises" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Lowering the upper limit on the number of packages that can be purchased will eventually lead to an infeasible solution. Deliberately modify the constraints so that you see this behavior, and learn how to identify these situations.\n", "\n", "2. Alter the table output to include the marginal values of the nutrient constraints. What nutrients have the highest marginal values?" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [], "prompt_number": 13 } ], "metadata": {} } ] }