{ "cells": [ { "cell_type": "markdown", "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": "markdown", "metadata": {}, "source": [ "# Newsvendor Problem" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This [Jupyter notebook](http://jupyter.org/notebook.html) demonstrates the formulation and solution of the well-known \"Newsvendor Problem\" using GLPK/Mathprog and Gurobi Python." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Background" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The newsvendor problem is a two stage decision problem with recourse. The vendor needs to decide how much inventory to order today to fulfill an uncertain demand. The data includes the unit cost, price, and salvage value of the product being sold, and a probabilistic forecast of demand. The objective is to maximize expected profit.\n", "\n", "As shown in lecture, this problem can be solved with a plot, and the solution interpreted in terms of a cumulative probability distribution. The advantage of a MathProg model is that additional constraints or other criteria may be considered, such as risk aversion.\n", " \n", "There is an extensive literature on the newsvendor problem which has been studied since at least 1888. See here for a thorough discussion." ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": true }, "outputs": [], "source": [ "%matplotlib inline\n", "import numpy as np\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "from gurobipy import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## MathProg Solution" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "GLPSOL: GLPK LP/MIP Solver, v4.60\n", "Parameter(s) specified in the command line:\n", " -m /dev/stdin\n", "Reading model section from /dev/stdin...\n", "Reading data section from /dev/stdin...\n", "86 lines were read\n", "Checking (line 10)...\n", "Checking (line 11)...\n", "Checking (line 19)...\n", "Generating OBJ...\n", "Generating PRFT...\n", "Generating SUPL...\n", "Generating DMND...\n", "Model has been successfully generated\n", "GLPK Simplex Optimizer, v4.60\n", "8 rows, 5 columns, 15 non-zeros\n", "Preprocessing...\n", "3 rows, 4 columns, 6 non-zeros\n", "Scaling...\n", " A: min|aij| = 1.000e+00 max|aij| = 1.000e+00 ratio = 1.000e+00\n", "Problem data seem to be well scaled\n", "Constructing initial basis...\n", "Size of triangular part is 3\n", "* 0: obj = -0.000000000e+00 inf = 0.000e+00 (3)\n", "* 5: obj = 4.000000000e+02 inf = 0.000e+00 (0)\n", "OPTIMAL LP SOLUTION FOUND\n", "Time used: 0.0 secs\n", "Memory used: 0.1 Mb (142447 bytes)\n", "Writing Table_EVM...\n", "Writing Table_EVPI...\n", "Writing Table_SP...\n", "Model has been successfully processed\n" ] } ], "source": [ "%%script glpsol -m /dev/stdin\n", "\n", "# Example: Newsvendor.mod\n", "\n", "/* Unit Price Data */\n", "param r >= 0; # Price\n", "param c >= 0; # Cost\n", "param w >= 0; # Salvage value\n", "\n", "/* Price data makes sense only if Price > Cost > Salvage */\n", "check: c <= r;\n", "check: w <= c;\n", "\n", "/* Probabilistic Demand Forecast */\n", "set SCENS; # Scenarios\n", "param D{SCENS} >= 0; # Demand\n", "param Pr{SCENS} >= 0; # Probability\n", "\n", "/* Probabilities must sum to one. */\n", "check: sum{k in SCENS} Pr[k] = 1;\n", "\n", "/* Expected Demand */\n", "param ExD := sum{k in SCENS} Pr[k]*D[k];\n", "\n", "/* Lower Bound on Profit: Expected Value of the Mean Solution */\n", "param EVM := -c*ExD + sum{k in SCENS} Pr[k]*(r*min(ExD,D[k])+w*max(ExD-D[k],0));\n", "\n", "/* Upper Bound on Profit: Expected Value with Perfect Information */\n", "param EVPI := sum{k in SCENS} Pr[k]*(r-c)*D[k];\n", "\n", "/* Two Stage Stochastic Programming */\n", "var x >= 0; # Stage 1 (Here and Now): Order Quqntity\n", "var y{SCENS}>= 0; # Stage 2 (Scenario Dep): Actual Sales\n", "var ExProfit; # Expected Profit\n", "\n", "/* Maximize Expected Profit */\n", "maximize OBJ: ExProfit;\n", "\n", "/* Goods sold are limited by the order quantities and the demand */\n", "s.t. PRFT: ExProfit = -c*x + sum{k in SCENS} Pr[k]*(r*y[k] + w*(x-y[k]));\n", "s.t. SUPL {k in SCENS}: y[k] <= x;\n", "s.t. DMND {k in SCENS}: y[k] <= D[k];\n", "\n", "solve;\n", "\n", "table Table_EVM {k in SCENS} OUT \"CSV\" \"evm.csv\" \"Table\":\n", " k~Scenario,\n", " Pr[k]~Probability, \n", " D[k]~Demand, \n", " ExD~Order, \n", " min(ExD,D[k])~Sold,\n", " max(ExD-D[k],0)~Salvage, \n", " -c*ExD + r*min(ExD,D[k]) + w*max(ExD-D[k],0)~Profit;\n", " \n", "table Table_EVPI {k in SCENS} OUT \"CSV\" \"evpi.csv\" \"Table\":\n", " k~Scenario,\n", " Pr[k]~Probability, \n", " D[k]~Demand, \n", " D[k]~Order, \n", " D[k]~Sold,\n", " 0~Salvage, \n", " -c*D[k] + r*D[k]~Profit;\n", " \n", "table Table_SP {k in SCENS} OUT \"CSV\" \"evsp.csv\" \"Table\":\n", " k~Scenario,\n", " Pr[k]~Probability, \n", " D[k]~Demand, \n", " x~Order, \n", " y[k]~Sold,\n", " x-y[k]~Salvage, \n", " -c*x + r*y[k] + w*(x-y[k])~Profit;\n", "\n", "data;\n", "\n", "/* Problem Data corresponds to a hypothetical case of selling programs prior \n", "to a home football game. */\n", "\n", "param r := 10.00; # Unit Price\n", "param c := 6.00; # Unit Cost\n", "param w := 2.00; # Unit Salvage Value\n", "\n", "param: SCENS: Pr D :=\n", " HiDmd 0.25 250\n", " MiDmd 0.50 125\n", " LoDmd 0.25 75 ;\n", "\n", "end;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Expected Value for the Mean Scenario (EVM)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Scenario Probability Demand Order Sold Salvage Profit\n", "0 HiDmd 0.25 250 143.75 143.75 0.00 575\n", "1 MiDmd 0.50 125 143.75 125.00 18.75 425\n", "2 LoDmd 0.25 75 143.75 75.00 68.75 25\n", "Expected Value for the Mean Scenario = 362.50\n" ] } ], "source": [ "evm = pd.read_csv(\"evm.csv\")\n", "print(evm)\n", "\n", "ev_evm = sum(evm['Probability']*evm['Profit'])\n", "print(\"Expected Value for the Mean Scenario = {:6.2f}\".format(ev_evm))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Expected Value with Perfect Information (EVPI)" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Scenario Probability Demand Order Sold Salvage Profit\n", "0 HiDmd 0.25 250 250 250 0 1000\n", "1 MiDmd 0.50 125 125 125 0 500\n", "2 LoDmd 0.25 75 75 75 0 300\n", "Expected Value with Perfect Information = 575.00\n" ] } ], "source": [ "evpi = pd.read_csv(\"evpi.csv\")\n", "print(evpi)\n", "\n", "ev_evpi = sum(evpi['Probability']*evpi['Profit'])\n", "print(\"Expected Value with Perfect Information = {:6.2f}\".format(ev_evpi))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Expected Value by Stochastic Programming" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " Scenario Probability Demand Order Sold Salvage Profit\n", "0 HiDmd 0.25 250 125 125 0 500\n", "1 MiDmd 0.50 125 125 125 0 500\n", "2 LoDmd 0.25 75 125 75 50 100\n", "Expected Value by Stochastic Programming = 400.00\n" ] } ], "source": [ "evsp = pd.read_csv(\"evsp.csv\")\n", "print(evsp)\n", "\n", "ev_evsp = sum(evsp['Probability']*evsp['Profit'])\n", "print(\"Expected Value by Stochastic Programming = {:6.2f}\".format(ev_evsp))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Value of Perfect Information" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Value of Perfect Information = 175.00\n" ] } ], "source": [ "print(\"Value of Perfect Information = {:6.2f}\".format(ev_evpi-ev_evsp))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Value of the Stochastic Solution" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Value of the Stochastic Solution = 37.50\n" ] } ], "source": [ "print(\"Value of the Stochastic Solution = {:6.2f}\".format(ev_evsp-ev_evm))" ] }, { "cell_type": "markdown", "metadata": { "collapsed": false }, "source": [ "## Plot of Expected Profit as function of Order Size" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "collapsed": false }, "outputs": [ { "ename": "TypeError", "evalue": "float() argument must be a string or a number, not 'function'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlinspace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m400\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m400\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 19\u001b[0;31m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mexprofit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mxx\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mxx\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 20\u001b[0m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mxlabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Order size'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 21\u001b[0m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mylabel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Expected Profit'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/Users/jeff/anaconda/lib/python3.5/site-packages/matplotlib/pyplot.py\u001b[0m in \u001b[0;36mplot\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 3316\u001b[0m mplDeprecation)\n\u001b[1;32m 3317\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 3318\u001b[0;31m \u001b[0mret\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0max\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3319\u001b[0m \u001b[0;32mfinally\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3320\u001b[0m \u001b[0max\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_hold\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mwashold\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/Users/jeff/anaconda/lib/python3.5/site-packages/matplotlib/__init__.py\u001b[0m in \u001b[0;36minner\u001b[0;34m(ax, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1890\u001b[0m warnings.warn(msg % (label_namer, func.__name__),\n\u001b[1;32m 1891\u001b[0m RuntimeWarning, stacklevel=2)\n\u001b[0;32m-> 1892\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfunc\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0max\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1893\u001b[0m \u001b[0mpre_doc\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0minner\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__doc__\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1894\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mpre_doc\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/Users/jeff/anaconda/lib/python3.5/site-packages/matplotlib/axes/_axes.py\u001b[0m in \u001b[0;36mplot\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1405\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1406\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mline\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_lines\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1407\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_line\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mline\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1408\u001b[0m \u001b[0mlines\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mline\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1409\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/Users/jeff/anaconda/lib/python3.5/site-packages/matplotlib/axes/_base.py\u001b[0m in \u001b[0;36madd_line\u001b[0;34m(self, line)\u001b[0m\n\u001b[1;32m 1785\u001b[0m \u001b[0mline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mset_clip_path\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpatch\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1786\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1787\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_update_line_limits\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mline\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1788\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_label\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1789\u001b[0m \u001b[0mline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mset_label\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'_line%d'\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlines\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/Users/jeff/anaconda/lib/python3.5/site-packages/matplotlib/axes/_base.py\u001b[0m in \u001b[0;36m_update_line_limits\u001b[0;34m(self, line)\u001b[0m\n\u001b[1;32m 1807\u001b[0m \u001b[0mFigures\u001b[0m \u001b[0mout\u001b[0m \u001b[0mthe\u001b[0m \u001b[0mdata\u001b[0m \u001b[0mlimit\u001b[0m \u001b[0mof\u001b[0m \u001b[0mthe\u001b[0m \u001b[0mgiven\u001b[0m \u001b[0mline\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mupdating\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdataLim\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1808\u001b[0m \"\"\"\n\u001b[0;32m-> 1809\u001b[0;31m \u001b[0mpath\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mline\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_path\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1810\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mpath\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvertices\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msize\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1811\u001b[0m \u001b[0;32mreturn\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/Users/jeff/anaconda/lib/python3.5/site-packages/matplotlib/lines.py\u001b[0m in \u001b[0;36mget_path\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 987\u001b[0m \"\"\"\n\u001b[1;32m 988\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_invalidy\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_invalidx\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 989\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrecache\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 990\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_path\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 991\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/Users/jeff/anaconda/lib/python3.5/site-packages/matplotlib/lines.py\u001b[0m in \u001b[0;36mrecache\u001b[0;34m(self, always)\u001b[0m\n\u001b[1;32m 683\u001b[0m \u001b[0my\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0masarray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0myconv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfloat_\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfilled\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnan\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 684\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 685\u001b[0;31m \u001b[0my\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0masarray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0myconv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfloat_\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 686\u001b[0m \u001b[0my\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mravel\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 687\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/Users/jeff/anaconda/lib/python3.5/site-packages/numpy/core/numeric.py\u001b[0m in \u001b[0;36masarray\u001b[0;34m(a, dtype, order)\u001b[0m\n\u001b[1;32m 480\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 481\u001b[0m \"\"\"\n\u001b[0;32m--> 482\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtype\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcopy\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mFalse\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0morder\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0morder\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 483\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 484\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0masanyarray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtype\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0morder\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mTypeError\u001b[0m: float() argument must be a string or a number, not 'function'" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXwAAAD8CAYAAAB0IB+mAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAADQdJREFUeJzt3F+IpfV9x/H3p7sRGpNGiZOQ7irZljVmobHoxEiR1jS0\n7tqLJeCFGiKVwCKNIZdKocmFN81FIQT/LIsskpvsRSPJppjYQkksWNOdBf+tokxXqquCq4YUDFQG\nv72Y087pdNd5duaZmXW+7xcMzHOe38z57o/Z9z57zpyTqkKStPX91mYPIEnaGAZfkpow+JLUhMGX\npCYMviQ1YfAlqYkVg5/kcJI3kjx7lvNJ8r0k80meTnLV+GNKktZqyBX+Q8De9zm/D9g9+TgAPLD2\nsSRJY1sx+FX1GPD2+yzZD3y/Fj0BXJTkU2MNKEkax/YRvscO4JWp41OT215fvjDJARb/F8CFF154\n9RVXXDHC3UtSH8ePH3+zqmZW87VjBH+wqjoEHAKYnZ2tubm5jbx7SfrAS/Ifq/3aMX5L51Xg0qnj\nnZPbJEnnkTGCfxS4bfLbOtcCv66q//dwjiRpc634kE6SHwDXA5ckOQV8G/gQQFUdBB4BbgTmgd8A\nt6/XsJKk1Vsx+FV1ywrnC/j6aBNJktaFr7SVpCYMviQ1YfAlqQmDL0lNGHxJasLgS1ITBl+SmjD4\nktSEwZekJgy+JDVh8CWpCYMvSU0YfElqwuBLUhMGX5KaMPiS1ITBl6QmDL4kNWHwJakJgy9JTRh8\nSWrC4EtSEwZfkpow+JLUhMGXpCYMviQ1YfAlqQmDL0lNGHxJasLgS1ITBl+SmjD4ktSEwZekJgy+\nJDVh8CWpiUHBT7I3yQtJ5pPcfYbzH0vykyRPJTmR5PbxR5UkrcWKwU+yDbgP2AfsAW5JsmfZsq8D\nz1XVlcD1wN8luWDkWSVJazDkCv8aYL6qTlbVu8ARYP+yNQV8NEmAjwBvAwujTipJWpMhwd8BvDJ1\nfGpy27R7gc8CrwHPAN+sqveWf6MkB5LMJZk7ffr0KkeWJK3GWE/a3gA8Cfwu8IfAvUl+Z/miqjpU\nVbNVNTszMzPSXUuShhgS/FeBS6eOd05um3Y78HAtmgdeAq4YZ0RJ0hiGBP8YsDvJrskTsTcDR5et\neRn4EkCSTwKfAU6OOagkaW22r7SgqhaS3Ak8CmwDDlfViSR3TM4fBO4BHkryDBDgrqp6cx3nliSd\noxWDD1BVjwCPLLvt4NTnrwF/Pu5okqQx+UpbSWrC4EtSEwZfkpow+JLUhMGXpCYMviQ1YfAlqQmD\nL0lNGHxJasLgS1ITBl+SmjD4ktSEwZekJgy+JDVh8CWpCYMvSU0YfElqwuBLUhMGX5KaMPiS1ITB\nl6QmDL4kNWHwJakJgy9JTRh8SWrC4EtSEwZfkpow+JLUhMGXpCYMviQ1YfAlqQmDL0lNGHxJasLg\nS1ITg4KfZG+SF5LMJ7n7LGuuT/JkkhNJfjHumJKktdq+0oIk24D7gD8DTgHHkhytquem1lwE3A/s\nraqXk3xivQaWJK3OkCv8a4D5qjpZVe8CR4D9y9bcCjxcVS8DVNUb444pSVqrIcHfAbwydXxqctu0\ny4GLk/w8yfEkt53pGyU5kGQuydzp06dXN7EkaVXGetJ2O3A18BfADcDfJLl8+aKqOlRVs1U1OzMz\nM9JdS5KGWPExfOBV4NKp452T26adAt6qqneAd5I8BlwJvDjKlJKkNRtyhX8M2J1kV5ILgJuBo8vW\n/Bi4Lsn2JB8GvgA8P+6okqS1WPEKv6oWktwJPApsAw5X1Ykkd0zOH6yq55P8DHgaeA94sKqeXc/B\nJUnnJlW1KXc8Oztbc3Nzm3LfkvRBleR4Vc2u5mt9pa0kNWHwJakJgy9JTRh8SWrC4EtSEwZfkpow\n+JLUhMGXpCYMviQ1YfAlqQmDL0lNGHxJasLgS1ITBl+SmjD4ktSEwZekJgy+JDVh8CWpCYMvSU0Y\nfElqwuBLUhMGX5KaMPiS1ITBl6QmDL4kNWHwJakJgy9JTRh8SWrC4EtSEwZfkpow+JLUhMGXpCYM\nviQ1YfAlqQmDL0lNDAp+kr1JXkgyn+Tu91n3+SQLSW4ab0RJ0hhWDH6SbcB9wD5gD3BLkj1nWfcd\n4B/HHlKStHZDrvCvAear6mRVvQscAfafYd03gB8Cb4w4nyRpJEOCvwN4Zer41OS2/5VkB/Bl4IH3\n+0ZJDiSZSzJ3+vTpc51VkrQGYz1p+13grqp67/0WVdWhqpqtqtmZmZmR7lqSNMT2AWteBS6dOt45\nuW3aLHAkCcAlwI1JFqrqR6NMKUlasyHBPwbsTrKLxdDfDNw6vaCqdv3P50keAv7B2EvS+WXF4FfV\nQpI7gUeBbcDhqjqR5I7J+YPrPKMkaQRDrvCpqkeAR5bddsbQV9Vfrn0sSdLYfKWtJDVh8CWpCYMv\nSU0YfElqwuBLUhMGX5KaMPiS1ITBl6QmDL4kNWHwJakJgy9JTRh8SWrC4EtSEwZfkpow+JLUhMGX\npCYMviQ1YfAlqQmDL0lNGHxJasLgS1ITBl+SmjD4ktSEwZekJgy+JDVh8CWpCYMvSU0YfElqwuBL\nUhMGX5KaMPiS1ITBl6QmDL4kNWHwJamJQcFPsjfJC0nmk9x9hvNfSfJ0kmeSPJ7kyvFHlSStxYrB\nT7INuA/YB+wBbkmyZ9myl4A/qao/AO4BDo09qCRpbYZc4V8DzFfVyap6FzgC7J9eUFWPV9WvJodP\nADvHHVOStFZDgr8DeGXq+NTktrP5GvDTM51IciDJXJK506dPD59SkrRmoz5pm+SLLAb/rjOdr6pD\nVTVbVbMzMzNj3rUkaQXbB6x5Fbh06njn5Lb/I8nngAeBfVX11jjjSZLGMuQK/xiwO8muJBcANwNH\npxckuQx4GPhqVb04/piSpLVa8Qq/qhaS3Ak8CmwDDlfViSR3TM4fBL4FfBy4PwnAQlXNrt/YkqRz\nlaralDuenZ2tubm5TblvSfqgSnJ8tRfUvtJWkpow+JLUhMGXpCYMviQ1YfAlqQmDL0lNGHxJasLg\nS1ITBl+SmjD4ktSEwZekJgy+JDVh8CWpCYMvSU0YfElqwuBLUhMGX5KaMPiS1ITBl6QmDL4kNWHw\nJakJgy9JTRh8SWrC4EtSEwZfkpow+JLUhMGXpCYMviQ1YfAlqQmDL0lNGHxJasLgS1ITBl+SmjD4\nktSEwZekJgYFP8neJC8kmU9y9xnOJ8n3JuefTnLV+KNKktZixeAn2QbcB+wD9gC3JNmzbNk+YPfk\n4wDwwMhzSpLWaMgV/jXAfFWdrKp3gSPA/mVr9gPfr0VPABcl+dTIs0qS1mD7gDU7gFemjk8BXxiw\nZgfw+vSiJAdY/B8AwH8lefacpt26LgHe3OwhzhPuxRL3Yol7seQzq/3CIcEfTVUdAg4BJJmrqtmN\nvP/zlXuxxL1Y4l4scS+WJJlb7dcOeUjnVeDSqeOdk9vOdY0kaRMNCf4xYHeSXUkuAG4Gji5bcxS4\nbfLbOtcCv66q15d/I0nS5lnxIZ2qWkhyJ/AosA04XFUnktwxOX8QeAS4EZgHfgPcPuC+D6166q3H\nvVjiXixxL5a4F0tWvRepqjEHkSSdp3ylrSQ1YfAlqYl1D75vy7BkwF58ZbIHzyR5PMmVmzHnRlhp\nL6bWfT7JQpKbNnK+jTRkL5Jcn+TJJCeS/GKjZ9woA/6OfCzJT5I8NdmLIc8XfuAkOZzkjbO9VmnV\n3ayqdftg8Unefwd+D7gAeArYs2zNjcBPgQDXAr9cz5k262PgXvwRcPHk832d92Jq3T+z+EsBN232\n3Jv4c3ER8Bxw2eT4E5s99ybuxV8D35l8PgO8DVyw2bOvw178MXAV8OxZzq+qm+t9he/bMixZcS+q\n6vGq+tXk8AkWX8+wFQ35uQD4BvBD4I2NHG6DDdmLW4GHq+plgKraqvsxZC8K+GiSAB9hMfgLGzvm\n+quqx1j8s53Nqrq53sE/21sunOuareBc/5xfY/Ff8K1oxb1IsgP4Mlv/jfiG/FxcDlyc5OdJjie5\nbcOm21hD9uJe4LPAa8AzwDer6r2NGe+8sqpubuhbK2iYJF9kMfjXbfYsm+i7wF1V9d7ixVxr24Gr\ngS8Bvw38a5InqurFzR1rU9wAPAn8KfD7wD8l+Zeq+s/NHeuDYb2D79syLBn050zyOeBBYF9VvbVB\ns220IXsxCxyZxP4S4MYkC1X1o40ZccMM2YtTwFtV9Q7wTpLHgCuBrRb8IXtxO/C3tfhA9nySl4Ar\ngH/bmBHPG6vq5no/pOPbMixZcS+SXAY8DHx1i1+9rbgXVbWrqj5dVZ8G/h74qy0Yexj2d+THwHVJ\ntif5MIvvVvv8Bs+5EYbsxcss/k+HJJ9k8Z0jT27olOeHVXVzXa/wa/3eluEDZ+BefAv4OHD/5Mp2\nobbgOwQO3IsWhuxFVT2f5GfA08B7wINVteXeWnzgz8U9wENJnmHxN1Tuqqot97bJSX4AXA9ckuQU\n8G3gQ7C2bvrWCpLUhK+0laQmDL4kNWHwJakJgy9JTRh8SWrC4EtSEwZfkpr4bz3EZ6V9PH3fAAAA\nAElFTkSuQmCC\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "r = 1.00\n", "c = 0.60\n", "w = 0.25\n", "\n", "scenarios = [['Low Demand',75,.25],['High Demand',200,.75]]\n", "\n", "def profit(D,x):\n", " return r*min([D,x]) + w*max([0,x-D]) - c*x\n", "\n", "\n", "\n", "def exprofit(x):\n", " v = 0\n", " for s in scenarios:\n", " v += s[2]*profit(s[1],x)\n", " return profit(04)\n", "\n", "x = np.linspace(0,400,400)\n", "plt.plot(x,[exprofit(xx) for xx in x])\n", "plt.xlabel('Order size')\n", "plt.ylabel('Expected Profit')\n", "\n" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "[,\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", " ,\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", " ,\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", " ,\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", " ,\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", " ,\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", " ]" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "[exprofit(x) for x in x]" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "map(exprofit,x)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": false }, "source": [ "## Gurobi Solution" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/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", "
ScenarioProbabilityDemand
0Hi Demand0.25250
1Med Demand0.50125
2Lo Demand0.2575
\n", "
" ], "text/plain": [ " Scenario Probability Demand\n", "0 Hi Demand 0.25 250\n", "1 Med Demand 0.50 125\n", "2 Lo Demand 0.25 75" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from gurobipy import *\n", "import pandas as pd\n", "\n", "# problem parameters\n", "\n", "# Problem Data corresponds to a hypothetical case of selling programs prior \n", "# to a home football game\n", "\n", "r = 10.00 # Unit Price\n", "c = 6.00 # Unit Cost\n", "w = 2.00 # Unit Salvage Value\n", "\n", "scenarios = pd.DataFrame([\n", " ['Hi Demand', 0.25, 250],\n", " ['Med Demand', 0.50, 125],\n", " ['Lo Demand', 0.25, 75]\n", "])\n", "scenarios.columns = ['Scenario','Probability','Demand']\n", "scenarios" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Optimize a model with 6 rows, 4 columns and 9 nonzeros\n", "Coefficient statistics:\n", " Matrix range [1e+00, 1e+00]\n", " Objective range [2e+00, 4e+00]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [8e+01, 2e+02]\n", "Presolve removed 3 rows and 0 columns\n", "Presolve time: 0.01s\n", "Presolved: 3 rows, 4 columns, 6 nonzeros\n", "\n", "Iteration Objective Primal Inf. Dual Inf. Time\n", " 0 1.1500000e+03 4.500000e+02 0.000000e+00 0s\n", " 2 4.0000000e+02 0.000000e+00 0.000000e+00 0s\n", "\n", "Solved in 2 iterations and 0.01 seconds\n", "Optimal objective 4.000000000e+02\n" ] }, { "data": { "text/plain": [ "125.0" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "m = Model('Newsvendor Problem')\n", "\n", "x = m.addVar()\n", "y = m.addVars(len(scenarios.index))\n", "\n", "m.update()\n", "\n", "p = sum([scenarios['Probability'][s]*(r*y[s] + w*(x-y[s]) - c*x) for s in scenarios.index])\n", "\n", "\n", "\n", "for s in scenarios.index:\n", " m.addConstr(y[s] <= scenarios['Demand'][s])\n", " m.addConstr(y[s] <= x)\n", " \n", "m.setObjective(p,GRB.MAXIMIZE)\n", "m.optimize()\n", "\n", "x.X" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "p" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python [default]", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.2" } }, "nbformat": 4, "nbformat_minor": 0 }