{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "*This notebook contains course material from [CBE30338](https://jckantor.github.io/CBE30338)\n", "by Jeffrey Kantor (jeff at nd.edu); the content is available [on Github](https://github.com/jckantor/CBE30338.git).\n", "The text is released under the [CC-BY-NC-ND-4.0 license](https://creativecommons.org/licenses/by-nc-nd/4.0/legalcode),\n", "and code is released under the [MIT license](https://opensource.org/licenses/MIT).*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "< [Discrete Events](http://nbviewer.jupyter.org/github/jckantor/CBE30338/blob/master/notebooks/09.00-Discrete-Events.ipynb) | [Contents](toc.ipynb) | [State-Task Networks](http://nbviewer.jupyter.org/github/jckantor/CBE30338/blob/master/notebooks/09.02-State--Task-Networks.ipynb) >

\"Open

\"Download\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Scheduling State-Task Networks" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Example (Kondili, et al., 1993)\n", "\n", "A state-task network is a graphical representation of the activities in a multiproduct batch process. The representation includes the minimum details needed for short term scheduling of batch operations.\n", "\n", "Shown below is a well-studied example due to Kondili (1993). Other examples are available in the references cited above.\n", "\n", "![Kondili_1993](figures/Kondili_1993.png)\n", "\n", "Each circular node in the diagram designates material in a particular state. The materials are generally held in suitable vessels with a known capacity. The relevant information for each state is the initial inventory, storage capacity, and the unit price of the material in that state. The price of materials in intermediate states may be assigned penalities in order to minimize the amount of work in progress.\n", "\n", "The rectangular nodes denote process tasks. When scheduled for execution, each task is assigned an appropriate piece of equipment, and assigned a batch of material according to the incoming arcs. Each incoming arc begins at a state where the associated label indicates the mass fraction of the batch coming from that particular state. Outgoing arcs indicate the disposition of the batch to product states. The outgoing are labels indicate the fraction of the batch assigned to each product state, and the time necessary to produce that product. \n", "\n", "Not shown in the diagram is the process equipment used to execute the tasks. A separate list of process units is available, each characterized by a capacity and list of tasks which can be performed in that unit." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Encoding the STN data\n", "\n", "The basic data structure specifies the states, tasks, and units comprising a state-task network. The intention is for all relevant problem data to be contained in a single JSON-like structure." ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [], "source": [ "H = 12\n", "\n", "Kondili = {\n", " 'TIME': range(0,H+1),\n", " 'STATES': {\n", " 'Feed_A' : {'capacity': 500, 'initial': 500, 'price': 0},\n", " 'Feed_B' : {'capacity': 500, 'initial': 500, 'price': 0},\n", " 'Feed_C' : {'capacity': 500, 'initial': 500, 'price': 0},\n", " 'Hot_A' : {'capacity': 100, 'initial': 0, 'price': -1},\n", " 'Int_AB' : {'capacity': 200, 'initial': 0, 'price': -10},\n", " 'Int_BC' : {'capacity': 150, 'initial': 0, 'price': -1},\n", " 'Impure_E' : {'capacity': 100, 'initial': 0, 'price': -1},\n", " 'Product_1': {'capacity': 500, 'initial': 0, 'price': 10},\n", " 'Product_2': {'capacity': 500, 'initial': 0, 'price': 10},\n", " },\n", " 'ST_ARCS': {\n", " ('Feed_A', 'Heating') : {'rho': 1.0},\n", " ('Feed_B', 'Reaction_1'): {'rho': 0.5},\n", " ('Feed_C', 'Reaction_1'): {'rho': 0.5},\n", " ('Feed_C', 'Reaction_3'): {'rho': 0.2},\n", " ('Hot_A', 'Reaction_2'): {'rho': 0.4},\n", " ('Int_AB', 'Reaction_3'): {'rho': 0.8},\n", " ('Int_BC', 'Reaction_2'): {'rho': 0.6},\n", " ('Impure_E', 'Separation'): {'rho': 1.0},\n", " },\n", " 'TS_ARCS': {\n", " ('Heating', 'Hot_A') : {'dur': 1, 'rho': 1.0},\n", " ('Reaction_2', 'Product_1'): {'dur': 2, 'rho': 0.4},\n", " ('Reaction_2', 'Int_AB') : {'dur': 2, 'rho': 0.6},\n", " ('Reaction_1', 'Int_BC') : {'dur': 2, 'rho': 1.0},\n", " ('Reaction_3', 'Impure_E') : {'dur': 1, 'rho': 1.0},\n", " ('Separation', 'Int_AB') : {'dur': 2, 'rho': 0.1},\n", " ('Separation', 'Product_2'): {'dur': 1, 'rho': 0.9},\n", " },\n", " 'UNIT_TASKS': {\n", " ('Heater', 'Heating') : {'Bmin': 0, 'Bmax': 100, 'Cost': 1, 'vCost': 0, 'Tclean': 0},\n", " ('Reactor_1', 'Reaction_1'): {'Bmin': 0, 'Bmax': 80, 'Cost': 1, 'vCost': 0, 'Tclean': 0},\n", " ('Reactor_1', 'Reaction_2'): {'Bmin': 0, 'Bmax': 80, 'Cost': 1, 'vCost': 0, 'Tclean': 0},\n", " ('Reactor_1', 'Reaction_3'): {'Bmin': 0, 'Bmax': 80, 'Cost': 1, 'vCost': 0, 'Tclean': 0},\n", " ('Reactor_2', 'Reaction_1'): {'Bmin': 0, 'Bmax': 80, 'Cost': 1, 'vCost': 0, 'Tclean': 0},\n", " ('Reactor_2', 'Reaction_2'): {'Bmin': 0, 'Bmax': 80, 'Cost': 1, 'vCost': 0, 'Tclean': 0},\n", " ('Reactor_2', 'Reaction_3'): {'Bmin': 0, 'Bmax': 80, 'Cost': 1, 'vCost': 0, 'Tclean': 0},\n", " ('Reactor_3', 'Reaction_1'): {'Bmin': 0, 'Bmax': 120, 'Cost': 1, 'vCost': 0, 'Tclean': 0},\n", " ('Reactor_3', 'Reaction_2'): {'Bmin': 0, 'Bmax': 120, 'Cost': 1, 'vCost': 0, 'Tclean': 0},\n", " ('Reactor_3', 'Reaction_3'): {'Bmin': 0, 'Bmax': 120, 'Cost': 1, 'vCost': 0, 'Tclean': 0},\n", " ('Still', 'Separation'): {'Bmin': 0, 'Bmax': 200, 'Cost': 1, 'vCost': 0, 'Tclean': 0},\n", " },\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Setting a Time Grid\n", "\n", "The following computations can be done on any time grid, including real-valued time points. TIME is a list of time points commencing at 0." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Creating a Pyomo Model\n", "\n", "The following Pyomo model closely follows the development in Kondili, et al. (1993). In particular, the first step in the model is to process the STN data to create sets as given in Kondili. Two differences from Kondili are: \n", "\n", "* a natural time scale commencing at $t = 0$ and extending to $t = H$ (rather than from 1 to H+1).\n", "* an additional decision variable denoted by $Q_{j,t}$ indicating the amount of material in unit $j$ at time $t$. A material balance then reads\n", "\n", "\\begin{align*}\n", "Q_{jt} & = Q_{j(t-1)} + \\sum_{i\\in I_j}B_{ijt} - \\sum_{i\\in I_j}\\sum_{\\substack{s \\in \\bar{S}_i\\\\s\\ni t-P_{is} \\geq 0}}\\bar{\\rho}_{is}B_{ij(t-P_{is})} \\qquad \\forall j,t\n", "\\end{align*}\n", "\n", "Following Kondili's notation, $I_j$ is the set of tasks that can be performed in unit $j$, and $\\bar{S}_i$ is the set of states fed by task $j$. We assume the units are empty at the beginning and end of production period, i.e.,\n", "\n", "\\begin{align*}\n", "Q_{j(-1)} & = 0 \\qquad \\forall j \\\\\n", "Q_{j,H} & = 0 \\qquad \\forall j\n", "\\end{align*}\n", "\n", "The unit allocation constraints are written the full backward aggregation method described by Shah (1993). The allocation constraint reads\n", "\n", "\\begin{align*}\n", "\\sum_{i \\in I_j} \\sum_{t'=t}^{t-p_i+1} W_{ijt'} & \\leq 1 \\qquad \\forall j,t\n", "\\end{align*}\n", "\n", "Each processing unit $j$ is tagged with a minimum and maximum capacity, $B_{ij}^{min}$ and $B_{ij}^{max}$, respectively, denoting the minimum and maximum batch sizes for each task $i$. A minimum capacity may be needed to cover heat exchange coils in a reactor or mixing blades in a blender, for example. The capacity may depend on the nature of the task being performed. These constraints are written\n", "\n", "\\begin{align*}\n", "B_{ij}^{min}W_{ijt} & \\leq B_{ijt} \\leq B_{ij}^{max}W_{ijt} \\qquad \\forall j, \\forall i\\in I_j, \\forall t\n", "\\end{align*}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Characterization of Tasks" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [], "source": [ "STN = Kondili\n", "\n", "STATES = STN['STATES']\n", "ST_ARCS = STN['ST_ARCS']\n", "TS_ARCS = STN['TS_ARCS']\n", "UNIT_TASKS = STN['UNIT_TASKS']\n", "TIME = STN['TIME']\n", "H = max(TIME)" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [], "source": [ "TASKS = set([i for (j,i) in UNIT_TASKS]) # set of all tasks \n", "\n", "S = {i: set() for i in TASKS} # S[i] input set of states which feed task i\n", "for (s,i) in ST_ARCS:\n", " S[i].add(s)\n", "\n", "S_ = {i: set() for i in TASKS} # S_[i] output set of states fed by task i\n", "for (i,s) in TS_ARCS:\n", " S_[i].add(s)\n", "\n", "rho = {(i,s): ST_ARCS[(s,i)]['rho'] for (s,i) in ST_ARCS} # rho[(i,s)] input fraction of task i from state s\n", "\n", "rho_ = {(i,s): TS_ARCS[(i,s)]['rho'] for (i,s) in TS_ARCS} # rho_[(i,s)] output fraction of task i to state s\n", "\n", "P = {(i,s): TS_ARCS[(i,s)]['dur'] for (i,s) in TS_ARCS} # P[(i,s)] time for task i output to state s \n", "\n", "p = {i: max([P[(i,s)] for s in S_[i]]) for i in TASKS} # p[i] completion time for task i\n", "\n", "K = {i: set() for i in TASKS} # K[i] set of units capable of task i\n", "for (j,i) in UNIT_TASKS:\n", " K[i].add(j) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Characterization of States" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [], "source": [ "T = {s: set() for s in STATES} # T[s] set of tasks receiving material from state s \n", "for (s,i) in ST_ARCS:\n", " T[s].add(i)\n", "\n", "T_ = {s: set() for s in STATES} # set of tasks producing material for state s\n", "for (i,s) in TS_ARCS:\n", " T_[s].add(i)\n", "\n", "C = {s: STATES[s]['capacity'] for s in STATES} # C[s] storage capacity for state s" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Characterization of Units" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [], "source": [ "UNITS = set([j for (j,i) in UNIT_TASKS])\n", "\n", "I = {j: set() for j in UNITS} # I[j] set of tasks performed with unit j\n", "for (j,i) in UNIT_TASKS:\n", " I[j].add(i)\n", "\n", "Bmax = {(i,j):UNIT_TASKS[(j,i)]['Bmax'] for (j,i) in UNIT_TASKS} # Bmax[(i,j)] maximum capacity of unit j for task i\n", "Bmin = {(i,j):UNIT_TASKS[(j,i)]['Bmin'] for (j,i) in UNIT_TASKS} # Bmin[(i,j)] minimum capacity of unit j for task i" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Pyomo Model" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "# ==========================================================\n", "# = Solver Results =\n", "# ==========================================================\n", "# ----------------------------------------------------------\n", "# Problem Information\n", "# ----------------------------------------------------------\n", "Problem: \n", "- Name: unknown\n", " Lower bound: 6992.91666666667\n", " Upper bound: 6992.91666666667\n", " Number of objectives: 1\n", " Number of constraints: 659\n", " Number of variables: 471\n", " Number of nonzeros: 1991\n", " Sense: maximize\n", "# ----------------------------------------------------------\n", "# Solver Information\n", "# ----------------------------------------------------------\n", "Solver: \n", "- Status: ok\n", " Termination condition: optimal\n", " Statistics: \n", " Branch and bound: \n", " Number of bounded subproblems: 12747\n", " Number of created subproblems: 12747\n", " Error rc: 0\n", " Time: 7.91475510597229\n", "# ----------------------------------------------------------\n", "# Solution Information\n", "# ----------------------------------------------------------\n", "Solution: \n", "- number of solutions: 0\n", " number of solutions displayed: 0\n" ] } ], "source": [ "from pyomo.environ import *\n", "import numpy as np\n", "\n", "TIME = np.array(TIME)\n", "\n", "model = ConcreteModel()\n", "\n", "model.W = Var(TASKS, UNITS, TIME, domain=Boolean) # W[i,j,t] 1 if task i starts in unit j at time t\n", "model.B = Var(TASKS, UNITS, TIME, domain=NonNegativeReals) # B[i,j,t,] size of batch assigned to task i in unit j at time t\n", "model.S = Var(STATES.keys(), TIME, domain=NonNegativeReals) # S[s,t] inventory of state s at time t\n", "model.Q = Var(UNITS, TIME, domain=NonNegativeReals) # Q[j,t] inventory of unit j at time t\n", "model.Cost = Var(domain=NonNegativeReals)\n", "model.Value = Var(domain=NonNegativeReals)\n", "\n", "# Objective is to maximize the value of the final state (see Kondili, Sec. 5)\n", "model.Obj = Objective(expr = model.Value - model.Cost, sense = maximize)\n", "\n", "# Constraints\n", "model.cons = ConstraintList()\n", "model.cons.add(model.Value == sum([STATES[s]['price']*model.S[s,H] for s in STATES]))\n", "model.cons.add(model.Cost == sum([UNIT_TASKS[(j,i)]['Cost']*model.W[i,j,t] +\n", " UNIT_TASKS[(j,i)]['vCost']*model.B[i,j,t] for i in TASKS for j in K[i] for t in TIME])) \n", "\n", "# unit constraints\n", "for j in UNITS:\n", " rhs = 0\n", " for t in TIME:\n", " # a unit can only be allocated to one task \n", " lhs = 0\n", " for i in I[j]:\n", " for tprime in TIME:\n", " if tprime >= (t-p[i]+1-UNIT_TASKS[(j,i)]['Tclean']) and tprime <= t:\n", " lhs += model.W[i,j,tprime]\n", " model.cons.add(lhs <= 1)\n", "\n", " # capacity constraints (see Konkili, Sec. 3.1.2)\n", " for i in I[j]:\n", " model.cons.add(model.W[i,j,t]*Bmin[i,j] <= model.B[i,j,t])\n", " model.cons.add(model.B[i,j,t] <= model.W[i,j,t]*Bmax[i,j])\n", "\n", " # unit mass balance\n", " rhs += sum([model.B[i,j,t] for i in I[j]])\n", " for i in I[j]:\n", " for s in S_[i]:\n", " if t >= P[(i,s)]:\n", " rhs -= rho_[(i,s)]*model.B[i,j,max(TIME[TIME <= t-P[(i,s)]])]\n", " model.cons.add(model.Q[j,t] == rhs)\n", " rhs = model.Q[j,t]\n", " \n", " # terminal condition \n", " model.cons.add(model.Q[j,H] == 0)\n", "\n", "# state constraints\n", "for s in STATES.keys():\n", " rhs = STATES[s]['initial']\n", " for t in TIME:\n", " # state capacity constraint\n", " model.cons.add(model.S[s,t] <= C[s])\n", " \n", " # state mass balanace\n", " for i in T_[s]:\n", " for j in K[i]:\n", " if t >= P[(i,s)]: \n", " rhs += rho_[(i,s)]*model.B[i,j,max(TIME[TIME <= t-P[(i,s)]])] \n", " for i in T[s]:\n", " rhs -= rho[(i,s)]*sum([model.B[i,j,t] for j in K[i]])\n", " model.cons.add(model.S[s,t] == rhs)\n", " rhs = model.S[s,t] \n", " \n", "# additional production constraints \n", "model.cons.add(model.S['Product_2',H] >= 250)\n", "\n", "\n", "SolverFactory('glpk').solve(model).write()\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Analysis" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Profitability\n", "\n" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Value of State Inventories = 7017.92\n", " Cost of Unit Assignments = 25.00\n", " Net Objective = 6992.92\n" ] } ], "source": [ "print(\"Value of State Inventories = {0:12.2f}\".format(model.Value()))\n", "print(\" Cost of Unit Assignments = {0:12.2f}\".format(model.Cost()))\n", "print(\" Net Objective = {0:12.2f}\".format(model.Value() - model.Cost()))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### State Inventories" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Feed_AFeed_BFeed_CHot_AInt_ABInt_BCImpure_EProduct_1Product_2
0424.000000360.0360.000.0000000.00.00.000.0000000.0
1324.000000360.0360.0076.0000000.00.00.000.0000000.0
2324.000000360.0360.0064.0000000.0112.00.000.0000000.0
3324.000000360.0360.0064.0000000.0112.00.000.0000000.0
4324.000000360.0320.0032.0000008.064.00.00112.0000000.0
5324.000000300.0260.000.0000008.016.00.00112.0000000.0
6233.333333300.0246.000.0000000.016.00.00144.000000180.0
7233.333333300.0230.0010.6666674.016.070.00176.000000180.0
8233.333333300.0230.0010.6666674.016.00.00176.000000180.0
9233.333333300.0199.000.0000000.00.00.00256.000000315.0
10233.333333300.0199.000.00000015.00.00.00256.000000315.0
11233.333333300.0191.250.0000000.00.00.00266.666667454.5
12233.333333300.0191.250.00000015.50.038.75266.666667454.5
\n", "
" ], "text/plain": [ " Feed_A Feed_B Feed_C Hot_A Int_AB Int_BC Impure_E \\\n", "0 424.000000 360.0 360.00 0.000000 0.0 0.0 0.00 \n", "1 324.000000 360.0 360.00 76.000000 0.0 0.0 0.00 \n", "2 324.000000 360.0 360.00 64.000000 0.0 112.0 0.00 \n", "3 324.000000 360.0 360.00 64.000000 0.0 112.0 0.00 \n", "4 324.000000 360.0 320.00 32.000000 8.0 64.0 0.00 \n", "5 324.000000 300.0 260.00 0.000000 8.0 16.0 0.00 \n", "6 233.333333 300.0 246.00 0.000000 0.0 16.0 0.00 \n", "7 233.333333 300.0 230.00 10.666667 4.0 16.0 70.00 \n", "8 233.333333 300.0 230.00 10.666667 4.0 16.0 0.00 \n", "9 233.333333 300.0 199.00 0.000000 0.0 0.0 0.00 \n", "10 233.333333 300.0 199.00 0.000000 15.0 0.0 0.00 \n", "11 233.333333 300.0 191.25 0.000000 0.0 0.0 0.00 \n", "12 233.333333 300.0 191.25 0.000000 15.5 0.0 38.75 \n", "\n", " Product_1 Product_2 \n", "0 0.000000 0.0 \n", "1 0.000000 0.0 \n", "2 0.000000 0.0 \n", "3 0.000000 0.0 \n", "4 112.000000 0.0 \n", "5 112.000000 0.0 \n", "6 144.000000 180.0 \n", "7 176.000000 180.0 \n", "8 176.000000 180.0 \n", "9 256.000000 315.0 \n", "10 256.000000 315.0 \n", "11 266.666667 454.5 \n", "12 266.666667 454.5 " ] }, "execution_count": 41, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "import pandas as pd\n", "from IPython.display import display, HTML\n", "\n", "pd.DataFrame([[model.S[s,t]() for s in STATES.keys()] for t in TIME], columns = STATES.keys(), index = TIME)" ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "scrolled": false }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.figure(figsize=(10,6))\n", "for (s,idx) in zip(STATES.keys(),range(0,len(STATES.keys()))):\n", " plt.subplot(ceil(len(STATES.keys())/3),3,idx+1)\n", " tlast,ylast = 0,STATES[s]['initial']\n", " for (t,y) in zip(list(TIME),[model.S[s,t]() for t in TIME]):\n", " plt.plot([tlast,t,t],[ylast,ylast,y],'b')\n", " #plt.plot([tlast,t],[ylast,y],'b.',ms=10)\n", " tlast,ylast = t,y\n", " plt.ylim(0,1.1*C[s])\n", " plt.plot([0,H],[C[s],C[s]],'r--')\n", " plt.title(s)\n", "plt.tight_layout()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Unit Assignment" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
HeaterReactor_1Reactor_2Reactor_3Still
0(Heating, 76.0)(Reaction_1, 80.0)(Reaction_1, 80.0)(Reaction_1, 120.0)None
1(Heating, 100.0)NoneNoneNoneNone
2None(Reaction_2, 80.0)(Reaction_2, 80.0)(Reaction_2, 120.0)None
3NoneNoneNoneNoneNone
4None(Reaction_3, 80.0)(Reaction_2, 80.0)(Reaction_3, 120.0)None
5None(Reaction_2, 80.0)None(Reaction_1, 120.0)(Separation, 200.0)
6(Heating, 90.6666666666667)None(Reaction_3, 70.0)NoneNone
7None(Reaction_2, 80.0)(Reaction_3, 80.0)(Reaction_2, 120.0)None
8NoneNoneNoneNone(Separation, 150.0)
9None(Reaction_3, 80.0)(Reaction_3, 75.0)(Reaction_2, 26.6666666666667)None
10NoneNoneNoneNone(Separation, 155.0)
11NoneNoneNone(Reaction_3, 38.75)None
12NoneNoneNoneNoneNone
\n", "
" ], "text/plain": [ " Heater Reactor_1 Reactor_2 \\\n", "0 (Heating, 76.0) (Reaction_1, 80.0) (Reaction_1, 80.0) \n", "1 (Heating, 100.0) None None \n", "2 None (Reaction_2, 80.0) (Reaction_2, 80.0) \n", "3 None None None \n", "4 None (Reaction_3, 80.0) (Reaction_2, 80.0) \n", "5 None (Reaction_2, 80.0) None \n", "6 (Heating, 90.6666666666667) None (Reaction_3, 70.0) \n", "7 None (Reaction_2, 80.0) (Reaction_3, 80.0) \n", "8 None None None \n", "9 None (Reaction_3, 80.0) (Reaction_3, 75.0) \n", "10 None None None \n", "11 None None None \n", "12 None None None \n", "\n", " Reactor_3 Still \n", "0 (Reaction_1, 120.0) None \n", "1 None None \n", "2 (Reaction_2, 120.0) None \n", "3 None None \n", "4 (Reaction_3, 120.0) None \n", "5 (Reaction_1, 120.0) (Separation, 200.0) \n", "6 None None \n", "7 (Reaction_2, 120.0) None \n", "8 None (Separation, 150.0) \n", "9 (Reaction_2, 26.6666666666667) None \n", "10 None (Separation, 155.0) \n", "11 (Reaction_3, 38.75) None \n", "12 None None " ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "UnitAssignment = pd.DataFrame({j:[None for t in TIME] for j in UNITS},index=TIME)\n", "\n", "for t in TIME:\n", " for j in UNITS:\n", " for i in I[j]:\n", " for s in S_[i]:\n", " if t-p[i] >= 0:\n", " if model.W[i,j,max(TIME[TIME <= t-p[i]])]() > 0:\n", " UnitAssignment.loc[t,j] = None \n", " for i in I[j]:\n", " if model.W[i,j,t]() > 0:\n", " UnitAssignment.loc[t,j] = (i,model.B[i,j,t]())\n", "\n", "UnitAssignment" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Unit Batch Inventories" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
StillReactor_2Reactor_3HeaterReactor_1
00.080.0120.00000076.00000080.0
10.080.0120.000000100.00000080.0
20.080.0120.0000000.00000080.0
30.080.0120.0000000.00000080.0
40.080.0120.0000000.00000080.0
5200.080.0120.0000000.00000080.0
620.070.0120.00000090.66666780.0
70.080.0120.0000000.00000080.0
8150.00.0120.0000000.00000080.0
915.075.026.6666670.00000080.0
10155.00.026.6666670.0000000.0
1115.50.038.7500000.0000000.0
120.00.00.0000000.0000000.0
\n", "
" ], "text/plain": [ " Still Reactor_2 Reactor_3 Heater Reactor_1\n", "0 0.0 80.0 120.000000 76.000000 80.0\n", "1 0.0 80.0 120.000000 100.000000 80.0\n", "2 0.0 80.0 120.000000 0.000000 80.0\n", "3 0.0 80.0 120.000000 0.000000 80.0\n", "4 0.0 80.0 120.000000 0.000000 80.0\n", "5 200.0 80.0 120.000000 0.000000 80.0\n", "6 20.0 70.0 120.000000 90.666667 80.0\n", "7 0.0 80.0 120.000000 0.000000 80.0\n", "8 150.0 0.0 120.000000 0.000000 80.0\n", "9 15.0 75.0 26.666667 0.000000 80.0\n", "10 155.0 0.0 26.666667 0.000000 0.0\n", "11 15.5 0.0 38.750000 0.000000 0.0\n", "12 0.0 0.0 0.000000 0.000000 0.0" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pd.DataFrame([[model.Q[j,t]() for j in UNITS] for t in TIME], columns = UNITS, index = TIME)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Gannt Chart" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%matplotlib inline\n", "import matplotlib.pyplot as plt\n", "\n", "plt.figure(figsize=(12,6))\n", "\n", "gap = H/500\n", "idx = 1\n", "lbls = []\n", "ticks = []\n", "for j in sorted(UNITS):\n", " idx -= 1\n", " for i in sorted(I[j]):\n", " idx -= 1\n", " ticks.append(idx)\n", " lbls.append(\"{0:s} -> {1:s}\".format(j,i))\n", " plt.plot([0,H],[idx,idx],lw=20,alpha=.3,color='y')\n", " for t in TIME:\n", " if model.W[i,j,t]() > 0:\n", " plt.plot([t+gap,t+p[i]-gap], [idx,idx],'b', lw=20, solid_capstyle='butt')\n", " txt = \"{0:.2f}\".format(model.B[i,j,t]())\n", " plt.text(t+p[i]/2, idx, txt, color='white', weight='bold', ha='center', va='center')\n", "plt.xlim(0,H)\n", "plt.gca().set_yticks(ticks)\n", "plt.gca().set_yticklabels(lbls);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Trace of Events and States" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "--------------------------------------------------------------------------------------------\n", "\n", "Starting Conditions\n", " Initial Inventories:\n", " Feed_A 500.0 kg\n", " Feed_B 500.0 kg\n", " Feed_C 500.0 kg\n", " Hot_A 0.0 kg\n", " Int_AB 0.0 kg\n", " Int_BC 0.0 kg\n", " Impure_E 0.0 kg\n", " Product_1 0.0 kg\n", " Product_2 0.0 kg\n", "\n", "--------------------------------------------------------------------------------------------\n", "\n", "Time = 0 hr\n", " Instructions:\n", " Assign Reactor_2 with capacity 80 kg to task Reaction_1 for 2 hours\n", " Transfer 40.0 kg from Feed_B to Reactor_2\n", " Transfer 40.0 kg from Feed_C to Reactor_2\n", " Assign Reactor_3 with capacity 120 kg to task Reaction_1 for 2 hours\n", " Transfer 60.0 kg from Feed_B to Reactor_3\n", " Transfer 60.0 kg from Feed_C to Reactor_3\n", " Assign Heater with capacity 100 kg to task Heating for 1 hours\n", " Transfer 76.0 kg from Feed_A to Heater\n", " Assign Reactor_1 with capacity 80 kg to task Reaction_1 for 2 hours\n", " Transfer 40.0 kg from Feed_B to Reactor_1\n", " Transfer 40.0 kg from Feed_C to Reactor_1\n", "\n", " Inventories are now:\n", " Feed_A 424.0 kg\n", " Feed_B 360.0 kg\n", " Feed_C 360.0 kg\n", " Hot_A 0.0 kg\n", " Int_AB 0.0 kg\n", " Int_BC 0.0 kg\n", " Impure_E 0.0 kg\n", " Product_1 0.0 kg\n", " Product_2 0.0 kg\n", "\n", " Unit Assignments are now:\n", " Reactor_2 performs the Reaction_1 task with a 80.00 kg batch for hour 1.000000 of 2.000000\n", " Reactor_3 performs the Reaction_1 task with a 120.00 kg batch for hour 1.000000 of 2.000000\n", " Heater performs the Heating task with a 76.00 kg batch for hour 1.000000 of 1.000000\n", " Reactor_1 performs the Reaction_1 task with a 80.00 kg batch for hour 1.000000 of 2.000000\n", "\n", "--------------------------------------------------------------------------------------------\n", "\n", "Time = 1 hr\n", " Instructions:\n", " Transfer 76.0 kg from Heater to Hot_A\n", " Release Heater from Heating\n", " Assign Heater with capacity 100 kg to task Heating for 1 hours\n", " Transfer 100.0 kg from Feed_A to Heater\n", "\n", " Inventories are now:\n", " Feed_A 324.0 kg\n", " Feed_B 360.0 kg\n", " Feed_C 360.0 kg\n", " Hot_A 76.0 kg\n", " Int_AB 0.0 kg\n", " Int_BC 0.0 kg\n", " Impure_E 0.0 kg\n", " Product_1 0.0 kg\n", " Product_2 0.0 kg\n", "\n", " Unit Assignments are now:\n", " Reactor_2 performs the Reaction_1 task with a 80.00 kg batch for hour 2.000000 of 2.000000\n", " Reactor_3 performs the Reaction_1 task with a 120.00 kg batch for hour 2.000000 of 2.000000\n", " Heater performs the Heating task with a 100.00 kg batch for hour 1.000000 of 1.000000\n", " Reactor_1 performs the Reaction_1 task with a 80.00 kg batch for hour 2.000000 of 2.000000\n", "\n", "--------------------------------------------------------------------------------------------\n", "\n", "Time = 2 hr\n", " Instructions:\n", " Transfer 80.0 kg from Reactor_2 to Int_BC\n", " Transfer 120.0 kg from Reactor_3 to Int_BC\n", " Transfer 100.0 kg from Heater to Hot_A\n", " Transfer 80.0 kg from Reactor_1 to Int_BC\n", " Release Reactor_2 from Reaction_1\n", " Assign Reactor_2 with capacity 80 kg to task Reaction_2 for 2 hours\n", " Transfer 32.0 kg from Hot_A to Reactor_2\n", " Transfer 48.0 kg from Int_BC to Reactor_2\n", " Release Reactor_3 from Reaction_1\n", " Assign Reactor_3 with capacity 120 kg to task Reaction_2 for 2 hours\n", " Transfer 48.0 kg from Hot_A to Reactor_3\n", " Transfer 72.0 kg from Int_BC to Reactor_3\n", " Release Heater from Heating\n", " Release Reactor_1 from Reaction_1\n", " Assign Reactor_1 with capacity 80 kg to task Reaction_2 for 2 hours\n", " Transfer 32.0 kg from Hot_A to Reactor_1\n", " Transfer 48.0 kg from Int_BC to Reactor_1\n", "\n", " Inventories are now:\n", " Feed_A 324.0 kg\n", " Feed_B 360.0 kg\n", " Feed_C 360.0 kg\n", " Hot_A 64.0 kg\n", " Int_AB 0.0 kg\n", " Int_BC 112.0 kg\n", " Impure_E 0.0 kg\n", " Product_1 0.0 kg\n", " Product_2 0.0 kg\n", "\n", " Unit Assignments are now:\n", " Reactor_2 performs the Reaction_2 task with a 80.00 kg batch for hour 1.000000 of 2.000000\n", " Reactor_3 performs the Reaction_2 task with a 120.00 kg batch for hour 1.000000 of 2.000000\n", " Reactor_1 performs the Reaction_2 task with a 80.00 kg batch for hour 1.000000 of 2.000000\n", "\n", "--------------------------------------------------------------------------------------------\n", "\n", "Time = 3 hr\n", " Instructions:\n", "\n", " Inventories are now:\n", " Feed_A 324.0 kg\n", " Feed_B 360.0 kg\n", " Feed_C 360.0 kg\n", " Hot_A 64.0 kg\n", " Int_AB 0.0 kg\n", " Int_BC 112.0 kg\n", " Impure_E 0.0 kg\n", " Product_1 0.0 kg\n", " Product_2 0.0 kg\n", "\n", " Unit Assignments are now:\n", " Reactor_2 performs the Reaction_2 task with a 80.00 kg batch for hour 2.000000 of 2.000000\n", " Reactor_3 performs the Reaction_2 task with a 120.00 kg batch for hour 2.000000 of 2.000000\n", " Reactor_1 performs the Reaction_2 task with a 80.00 kg batch for hour 2.000000 of 2.000000\n", "\n", "--------------------------------------------------------------------------------------------\n", "\n", "Time = 4 hr\n", " Instructions:\n", " Transfer 48.0 kg from Reactor_2 to Int_AB\n", " Transfer 32.0 kg from Reactor_2 to Product_1\n", " Transfer 72.0 kg from Reactor_3 to Int_AB\n", " Transfer 48.0 kg from Reactor_3 to Product_1\n", " Transfer 48.0 kg from Reactor_1 to Int_AB\n", " Transfer 32.0 kg from Reactor_1 to Product_1\n", " Release Reactor_2 from Reaction_2\n", " Assign Reactor_2 with capacity 80 kg to task Reaction_2 for 2 hours\n", " Transfer 32.0 kg from Hot_A to Reactor_2\n", " Transfer 48.0 kg from Int_BC to Reactor_2\n", " Release Reactor_3 from Reaction_2\n", " Assign Reactor_3 with capacity 120 kg to task Reaction_3 for 1 hours\n", " Transfer 96.0 kg from Int_AB to Reactor_3\n", " Transfer 24.0 kg from Feed_C to Reactor_3\n", " Release Reactor_1 from Reaction_2\n", " Assign Reactor_1 with capacity 80 kg to task Reaction_3 for 1 hours\n", " Transfer 64.0 kg from Int_AB to Reactor_1\n", " Transfer 16.0 kg from Feed_C to Reactor_1\n", "\n", " Inventories are now:\n", " Feed_A 324.0 kg\n", " Feed_B 360.0 kg\n", " Feed_C 320.0 kg\n", " Hot_A 32.0 kg\n", " Int_AB 8.0 kg\n", " Int_BC 64.0 kg\n", " Impure_E 0.0 kg\n", " Product_1 112.0 kg\n", " Product_2 0.0 kg\n", "\n", " Unit Assignments are now:\n", " Reactor_2 performs the Reaction_2 task with a 80.00 kg batch for hour 1.000000 of 2.000000\n", " Reactor_3 performs the Reaction_3 task with a 120.00 kg batch for hour 1.000000 of 1.000000\n", " Reactor_1 performs the Reaction_3 task with a 80.00 kg batch for hour 1.000000 of 1.000000\n", "\n", "--------------------------------------------------------------------------------------------\n", "\n", "Time = 5 hr\n", " Instructions:\n", " Transfer 120.0 kg from Reactor_3 to Impure_E\n", " Transfer 80.0 kg from Reactor_1 to Impure_E\n", " Assign Still with capacity 200 kg to task Separation for 2 hours\n", " Transfer 200.0 kg from Impure_E to Still\n", " Release Reactor_3 from Reaction_3\n", " Assign Reactor_3 with capacity 120 kg to task Reaction_1 for 2 hours\n", " Transfer 60.0 kg from Feed_B to Reactor_3\n", " Transfer 60.0 kg from Feed_C to Reactor_3\n", " Release Reactor_1 from Reaction_3\n", " Assign Reactor_1 with capacity 80 kg to task Reaction_2 for 2 hours\n", " Transfer 32.0 kg from Hot_A to Reactor_1\n", " Transfer 48.0 kg from Int_BC to Reactor_1\n", "\n", " Inventories are now:\n", " Feed_A 324.0 kg\n", " Feed_B 300.0 kg\n", " Feed_C 260.0 kg\n", " Hot_A 0.0 kg\n", " Int_AB 8.0 kg\n", " Int_BC 16.0 kg\n", " Impure_E 0.0 kg\n", " Product_1 112.0 kg\n", " Product_2 0.0 kg\n", "\n", " Unit Assignments are now:\n", " Still performs the Separation task with a 200.00 kg batch for hour 1.000000 of 2.000000\n", " Reactor_2 performs the Reaction_2 task with a 80.00 kg batch for hour 2.000000 of 2.000000\n", " Reactor_3 performs the Reaction_1 task with a 120.00 kg batch for hour 1.000000 of 2.000000\n", " Reactor_1 performs the Reaction_2 task with a 80.00 kg batch for hour 1.000000 of 2.000000\n", "\n", "--------------------------------------------------------------------------------------------\n", "\n", "Time = 6 hr\n", " Instructions:\n", " Transfer 180.0 kg from Still to Product_2\n", " Transfer 48.0 kg from Reactor_2 to Int_AB\n", " Transfer 32.0 kg from Reactor_2 to Product_1\n", " Release Reactor_2 from Reaction_2\n", " Assign Reactor_2 with capacity 80 kg to task Reaction_3 for 1 hours\n", " Transfer 56.0 kg from Int_AB to Reactor_2\n", " Transfer 14.0 kg from Feed_C to Reactor_2\n", " Assign Heater with capacity 100 kg to task Heating for 1 hours\n", " Transfer 90.6666666666667 kg from Feed_A to Heater\n", "\n", " Inventories are now:\n", " Feed_A 233.3 kg\n", " Feed_B 300.0 kg\n", " Feed_C 246.0 kg\n", " Hot_A 0.0 kg\n", " Int_AB 0.0 kg\n", " Int_BC 16.0 kg\n", " Impure_E 0.0 kg\n", " Product_1 144.0 kg\n", " Product_2 180.0 kg\n", "\n", " Unit Assignments are now:\n", " Still performs the Separation task with a 20.00 kg batch for hour 2.000000 of 2.000000\n", " Reactor_2 performs the Reaction_3 task with a 70.00 kg batch for hour 1.000000 of 1.000000\n", " Reactor_3 performs the Reaction_1 task with a 120.00 kg batch for hour 2.000000 of 2.000000\n", " Heater performs the Heating task with a 90.67 kg batch for hour 1.000000 of 1.000000\n", " Reactor_1 performs the Reaction_2 task with a 80.00 kg batch for hour 2.000000 of 2.000000\n", "\n", "--------------------------------------------------------------------------------------------\n", "\n", "Time = 7 hr\n", " Instructions:\n", " Transfer 20.0 kg from Still to Int_AB\n", " Transfer 70.0 kg from Reactor_2 to Impure_E\n", " Transfer 120.0 kg from Reactor_3 to Int_BC\n", " Transfer 90.6666666666667 kg from Heater to Hot_A\n", " Transfer 48.0 kg from Reactor_1 to Int_AB\n", " Transfer 32.0 kg from Reactor_1 to Product_1\n", " Release Still from Separation\n", " Release Reactor_2 from Reaction_3\n", " Assign Reactor_2 with capacity 80 kg to task Reaction_3 for 1 hours\n", " Transfer 64.0 kg from Int_AB to Reactor_2\n", " Transfer 16.0 kg from Feed_C to Reactor_2\n", " Release Reactor_3 from Reaction_1\n", " Assign Reactor_3 with capacity 120 kg to task Reaction_2 for 2 hours\n", " Transfer 48.0 kg from Hot_A to Reactor_3\n", " Transfer 72.0 kg from Int_BC to Reactor_3\n", " Release Heater from Heating\n", " Release Reactor_1 from Reaction_2\n", " Assign Reactor_1 with capacity 80 kg to task Reaction_2 for 2 hours\n", " Transfer 32.0 kg from Hot_A to Reactor_1\n", " Transfer 48.0 kg from Int_BC to Reactor_1\n", "\n", " Inventories are now:\n", " Feed_A 233.3 kg\n", " Feed_B 300.0 kg\n", " Feed_C 230.0 kg\n", " Hot_A 10.7 kg\n", " Int_AB 4.0 kg\n", " Int_BC 16.0 kg\n", " Impure_E 70.0 kg\n", " Product_1 176.0 kg\n", " Product_2 180.0 kg\n", "\n", " Unit Assignments are now:\n", " Reactor_2 performs the Reaction_3 task with a 80.00 kg batch for hour 1.000000 of 1.000000\n", " Reactor_3 performs the Reaction_2 task with a 120.00 kg batch for hour 1.000000 of 2.000000\n", " Reactor_1 performs the Reaction_2 task with a 80.00 kg batch for hour 1.000000 of 2.000000\n", "\n", "--------------------------------------------------------------------------------------------\n", "\n", "Time = 8 hr\n", " Instructions:\n", " Transfer 80.0 kg from Reactor_2 to Impure_E\n", " Assign Still with capacity 200 kg to task Separation for 2 hours\n", " Transfer 150.0 kg from Impure_E to Still\n", " Release Reactor_2 from Reaction_3\n", "\n", " Inventories are now:\n", " Feed_A 233.3 kg\n", " Feed_B 300.0 kg\n", " Feed_C 230.0 kg\n", " Hot_A 10.7 kg\n", " Int_AB 4.0 kg\n", " Int_BC 16.0 kg\n", " Impure_E 0.0 kg\n", " Product_1 176.0 kg\n", " Product_2 180.0 kg\n", "\n", " Unit Assignments are now:\n", " Still performs the Separation task with a 150.00 kg batch for hour 1.000000 of 2.000000\n", " Reactor_3 performs the Reaction_2 task with a 120.00 kg batch for hour 2.000000 of 2.000000\n", " Reactor_1 performs the Reaction_2 task with a 80.00 kg batch for hour 2.000000 of 2.000000\n", "\n", "--------------------------------------------------------------------------------------------\n", "\n", "Time = 9 hr\n", " Instructions:\n", " Transfer 135.0 kg from Still to Product_2\n", " Transfer 72.0 kg from Reactor_3 to Int_AB\n", " Transfer 48.0 kg from Reactor_3 to Product_1\n", " Transfer 48.0 kg from Reactor_1 to Int_AB\n", " Transfer 32.0 kg from Reactor_1 to Product_1\n", " Assign Reactor_2 with capacity 80 kg to task Reaction_3 for 1 hours\n", " Transfer 60.0 kg from Int_AB to Reactor_2\n", " Transfer 15.0 kg from Feed_C to Reactor_2\n", " Release Reactor_3 from Reaction_2\n", " Assign Reactor_3 with capacity 120 kg to task Reaction_2 for 2 hours\n", " Transfer 10.66666666666668 kg from Hot_A to Reactor_3\n", " Transfer 16.000000000000018 kg from Int_BC to Reactor_3\n", " Release Reactor_1 from Reaction_2\n", " Assign Reactor_1 with capacity 80 kg to task Reaction_3 for 1 hours\n", " Transfer 64.0 kg from Int_AB to Reactor_1\n", " Transfer 16.0 kg from Feed_C to Reactor_1\n", "\n", " Inventories are now:\n", " Feed_A 233.3 kg\n", " Feed_B 300.0 kg\n", " Feed_C 199.0 kg\n", " Hot_A 0.0 kg\n", " Int_AB 0.0 kg\n", " Int_BC 0.0 kg\n", " Impure_E 0.0 kg\n", " Product_1 256.0 kg\n", " Product_2 315.0 kg\n", "\n", " Unit Assignments are now:\n", " Still performs the Separation task with a 15.00 kg batch for hour 2.000000 of 2.000000\n", " Reactor_2 performs the Reaction_3 task with a 75.00 kg batch for hour 1.000000 of 1.000000\n", " Reactor_3 performs the Reaction_2 task with a 26.67 kg batch for hour 1.000000 of 2.000000\n", " Reactor_1 performs the Reaction_3 task with a 80.00 kg batch for hour 1.000000 of 1.000000\n", "\n", "--------------------------------------------------------------------------------------------\n", "\n", "Time = 10 hr\n", " Instructions:\n", " Transfer 15.0 kg from Still to Int_AB\n", " Transfer 75.0 kg from Reactor_2 to Impure_E\n", " Transfer 80.0 kg from Reactor_1 to Impure_E\n", " Release Still from Separation\n", " Assign Still with capacity 200 kg to task Separation for 2 hours\n", " Transfer 155.0 kg from Impure_E to Still\n", " Release Reactor_2 from Reaction_3\n", " Release Reactor_1 from Reaction_3\n", "\n", " Inventories are now:\n", " Feed_A 233.3 kg\n", " Feed_B 300.0 kg\n", " Feed_C 199.0 kg\n", " Hot_A 0.0 kg\n", " Int_AB 15.0 kg\n", " Int_BC 0.0 kg\n", " Impure_E 0.0 kg\n", " Product_1 256.0 kg\n", " Product_2 315.0 kg\n", "\n", " Unit Assignments are now:\n", " Still performs the Separation task with a 155.00 kg batch for hour 1.000000 of 2.000000\n", " Reactor_3 performs the Reaction_2 task with a 26.67 kg batch for hour 2.000000 of 2.000000\n", "\n", "--------------------------------------------------------------------------------------------\n", "\n", "Time = 11 hr\n", " Instructions:\n", " Transfer 139.5 kg from Still to Product_2\n", " Transfer 16.000000000000018 kg from Reactor_3 to Int_AB\n", " Transfer 10.66666666666668 kg from Reactor_3 to Product_1\n", " Release Reactor_3 from Reaction_2\n", " Assign Reactor_3 with capacity 120 kg to task Reaction_3 for 1 hours\n", " Transfer 31.0 kg from Int_AB to Reactor_3\n", " Transfer 7.75 kg from Feed_C to Reactor_3\n", "\n", " Inventories are now:\n", " Feed_A 233.3 kg\n", " Feed_B 300.0 kg\n", " Feed_C 191.2 kg\n", " Hot_A 0.0 kg\n", " Int_AB 0.0 kg\n", " Int_BC 0.0 kg\n", " Impure_E 0.0 kg\n", " Product_1 266.7 kg\n", " Product_2 454.5 kg\n", "\n", " Unit Assignments are now:\n", " Still performs the Separation task with a 15.50 kg batch for hour 2.000000 of 2.000000\n", " Reactor_3 performs the Reaction_3 task with a 38.75 kg batch for hour 1.000000 of 1.000000\n", "\n", "--------------------------------------------------------------------------------------------\n", "\n", "Time = 12 hr\n", " Instructions:\n", " Transfer 15.5 kg from Still to Int_AB\n", " Transfer 38.75 kg from Reactor_3 to Impure_E\n", " Release Still from Separation\n", " Release Reactor_3 from Reaction_3\n", "\n", " Inventories are now:\n", " Feed_A 233.3 kg\n", " Feed_B 300.0 kg\n", " Feed_C 191.2 kg\n", " Hot_A 0.0 kg\n", " Int_AB 15.5 kg\n", " Int_BC 0.0 kg\n", " Impure_E 38.8 kg\n", " Product_1 266.7 kg\n", " Product_2 454.5 kg\n", "\n", " Unit Assignments are now:\n", "\n", "--------------------------------------------------------------------------------------------\n", "\n", "Final Conditions\n", " Final Inventories:\n", " Feed_A 233.3 kg\n", " Feed_B 300.0 kg\n", " Feed_C 191.2 kg\n", " Hot_A 0.0 kg\n", " Int_AB 15.5 kg\n", " Int_BC 0.0 kg\n", " Impure_E 38.8 kg\n", " Product_1 266.7 kg\n", " Product_2 454.5 kg\n" ] } ], "source": [ "sep = '\\n--------------------------------------------------------------------------------------------\\n'\n", "print(sep)\n", "print(\"Starting Conditions\")\n", "print(\" Initial Inventories:\") \n", "for s in STATES.keys():\n", " print(\" {0:10s} {1:6.1f} kg\".format(s,STATES[s]['initial']))\n", " \n", "units = {j:{'assignment':'None', 't':0} for j in UNITS}\n", "\n", "for t in TIME:\n", " print(sep)\n", " print(\"Time =\",t,\"hr\")\n", " print(\" Instructions:\")\n", " for j in UNITS:\n", " units[j]['t'] += 1\n", " # transfer from unit to states\n", " for i in I[j]: \n", " for s in S_[i]:\n", " if t-P[(i,s)] >= 0:\n", " amt = rho_[(i,s)]*model.B[i,j,max(TIME[TIME <= t - P[(i,s)]])]()\n", " if amt > 0:\n", " print(\" Transfer\", amt, \"kg from\", j, \"to\", s)\n", " for j in UNITS:\n", " # release units from tasks\n", " for i in I[j]:\n", " if t-p[i] >= 0:\n", " if model.W[i,j,max(TIME[TIME <= t-p[i]])]() > 0:\n", " print(\" Release\", j, \"from\", i)\n", " units[j]['assignment'] = 'None'\n", " units[j]['t'] = 0\n", " # assign units to tasks \n", " for i in I[j]:\n", " if model.W[i,j,t]() > 0:\n", " print(\" Assign\", j, \"with capacity\", Bmax[(i,j)], \"kg to task\",i,\"for\",p[i],\"hours\")\n", " units[j]['assignment'] = i\n", " units[j]['t'] = 1\n", " # transfer from states to starting tasks\n", " for i in I[j]:\n", " for s in S[i]:\n", " amt = rho[(i,s)]*model.B[i,j,t]()\n", " if amt > 0:\n", " print(\" Transfer\", amt,\"kg from\", s, \"to\", j)\n", " print(\"\\n Inventories are now:\") \n", " for s in STATES.keys():\n", " print(\" {0:10s} {1:6.1f} kg\".format(s,model.S[s,t]()))\n", " print(\"\\n Unit Assignments are now:\")\n", " for j in UNITS:\n", " if units[j]['assignment'] != 'None':\n", " fmt = \" {0:s} performs the {1:s} task with a {2:.2f} kg batch for hour {3:f} of {4:f}\"\n", " i = units[j]['assignment']\n", " print(fmt.format(j,i,model.Q[j,t](),units[j]['t'],p[i]))\n", " \n", "print(sep)\n", "print('Final Conditions')\n", "print(\" Final Inventories:\") \n", "for s in STATES.keys():\n", " print(\" {0:10s} {1:6.1f} kg\".format(s,model.S[s,H]()))\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "< [Discrete Events](http://nbviewer.jupyter.org/github/jckantor/CBE30338/blob/master/notebooks/09.00-Discrete-Events.ipynb) | [Contents](toc.ipynb) | [State-Task Networks](http://nbviewer.jupyter.org/github/jckantor/CBE30338/blob/master/notebooks/09.02-State--Task-Networks.ipynb) >

\"Open

\"Download\"" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.7.4" } }, "nbformat": 4, "nbformat_minor": 2 }