A state-task network is a graphical representation of the activities in a multiproduct batch process. The representation includes the details needed for the short term scheduling of batch operations. A typical and well-studied example due to Kondili (1993) is shown below.
from IPython.display import Image
Image('../images/Kondili_1993.png')
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 each state. The price of materials in intermediate states may be assigned penalities in order to minimize the amount of work in progress.
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.
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.
%matplotlib inline
import sys
sys.path.append('../STN')
from STN import STN
# create instance
stn = STN()
# states
stn.state('FeedA', init = 200)
stn.state('FeedB', init = 200)
stn.state('FeedC', init = 200)
stn.state('HotA', price = -1)
stn.state('IntAB', price = -1)
stn.state('IntBC', price = -1)
stn.state('ImpureE', price = -1)
stn.state('Product_1', price = 10)
stn.state('Product_2', price = 10)
# state to task arcs
stn.stArc('FeedA', 'Heating')
stn.stArc('FeedB', 'Reaction_1', rho = 0.5)
stn.stArc('FeedC', 'Reaction_1', rho = 0.5)
stn.stArc('FeedC', 'Reaction_3', rho = 0.2)
stn.stArc('HotA', 'Reaction_2', rho = 0.4)
stn.stArc('IntAB', 'Reaction_3', rho = 0.8)
stn.stArc('IntBC', 'Reaction_2', rho = 0.6)
stn.stArc('ImpureE', 'Separation')
# task to state arcs
stn.tsArc('Heating', 'HotA', rho = 1.0, dur = 1)
stn.tsArc('Reaction_2', 'IntAB', rho = 0.6, dur = 2)
stn.tsArc('Reaction_2', 'Product_1', rho = 0.4, dur = 2)
stn.tsArc('Reaction_1', 'IntBC', dur = 2)
stn.tsArc('Reaction_3', 'ImpureE', dur = 1)
stn.tsArc('Separation', 'IntAB', rho = 0.1, dur = 2)
stn.tsArc('Separation', 'Product_2', rho = 0.9, dur = 1)
# unit-task data
stn.unit('Heater', 'Heating', Bmin = 0, Bmax = 100)
stn.unit('Reactor_1', 'Reaction_1', Bmin = 0, Bmax = 80)
stn.unit('Reactor_1', 'Reaction_2', Bmin = 0, Bmax = 80)
stn.unit('Reactor_1', 'Reaction_3', Bmin = 0, Bmax = 80)
stn.unit('Reactor_2', 'Reaction_1', Bmin = 0, Bmax = 50)
stn.unit('Reactor_2', 'Reaction_2', Bmin = 0, Bmax = 50)
stn.unit('Reactor_2', 'Reaction_3', Bmin = 0, Bmax = 50)
stn.unit('Still', 'Separation', Bmin = 0, Bmax = 200)
H = 10
stn.build(range(0,H+1))
stn.solve('glpk')
# ========================================================== # = Solver Results = # ========================================================== # ---------------------------------------------------------- # Problem Information # ---------------------------------------------------------- Problem: - Name: unknown Lower bound: 2744.375 Upper bound: 2744.375 Number of objectives: 1 Number of constraints: 410 Number of variables: 322 Number of nonzeros: 1158 Sense: maximize # ---------------------------------------------------------- # Solver Information # ---------------------------------------------------------- Solver: - Status: ok Termination condition: optimal Statistics: Branch and bound: Number of bounded subproblems: 597 Number of created subproblems: 597 Error rc: 0 Time: 0.19040894508361816 # ---------------------------------------------------------- # Solution Information # ---------------------------------------------------------- Solution: - number of solutions: 0 number of solutions displayed: 0
import matplotlib.pyplot as plt
stn.gantt()
plt.savefig('../images/Kondili_gantt.png')
stn.trace()
Starting Conditions Initial State Inventories are: FeedB 200.0 kg IntAB 0.0 kg FeedA 200.0 kg HotA 0.0 kg FeedC 200.0 kg ImpureE 0.0 kg Product_2 0.0 kg IntBC 0.0 kg Product_1 0.0 kg Time = 0 hr 1. Assign Heater to Heating for 84.00 kg batch for 1.0 hours 2. Transfer 84.00 from FeedA to Heater 3. Assign Reactor_1 to Reaction_1 for 76.00 kg batch for 2.0 hours 4. Transfer 38.00 from FeedC to Reactor_1 5. Transfer 38.00 from FeedB to Reactor_1 6. Assign Reactor_2 to Reaction_1 for 50.00 kg batch for 2.0 hours 7. Transfer 25.00 from FeedC to Reactor_2 8. Transfer 25.00 from FeedB to Reactor_2 State Inventories are now: FeedB 137.0 kg IntAB 0.0 kg FeedA 116.0 kg HotA 0.0 kg FeedC 137.0 kg ImpureE 0.0 kg Product_2 0.0 kg IntBC 0.0 kg Product_1 0.0 kg Unit Assignments are now: Heater on Heating with 84.00 kg batch for hour 1 of 1 Reactor_1 on Reaction_1 with 76.00 kg batch for hour 1 of 2 Still is unassigned Reactor_2 on Reaction_1 with 50.00 kg batch for hour 1 of 2 Time = 1 hr 1. Transfer 84.00 kg from Heater to HotA 2. Release Heater from Heating State Inventories are now: FeedB 137.0 kg IntAB 0.0 kg FeedA 116.0 kg HotA 84.0 kg FeedC 137.0 kg ImpureE 0.0 kg Product_2 0.0 kg IntBC 0.0 kg Product_1 0.0 kg Unit Assignments are now: Heater is unassigned Reactor_1 on Reaction_1 with 76.00 kg batch for hour 2 of 2 Still is unassigned Reactor_2 on Reaction_1 with 50.00 kg batch for hour 2 of 2 Time = 2 hr 1. Transfer 76.00 kg from Reactor_1 to IntBC 2. Transfer 50.00 kg from Reactor_2 to IntBC 3. Release Reactor_1 from Reaction_1 4. Assign Reactor_1 to Reaction_2 for 80.00 kg batch for 2.0 hours 5. Transfer 48.00 from IntBC to Reactor_1 6. Transfer 32.00 from HotA to Reactor_1 7. Release Reactor_2 from Reaction_1 8. Assign Reactor_2 to Reaction_2 for 50.00 kg batch for 2.0 hours 9. Transfer 30.00 from IntBC to Reactor_2 10. Transfer 20.00 from HotA to Reactor_2 State Inventories are now: FeedB 137.0 kg IntAB 0.0 kg FeedA 116.0 kg HotA 32.0 kg FeedC 137.0 kg ImpureE 0.0 kg Product_2 0.0 kg IntBC 48.0 kg Product_1 0.0 kg Unit Assignments are now: Heater is unassigned Reactor_1 on Reaction_2 with 80.00 kg batch for hour 1 of 2 Still is unassigned Reactor_2 on Reaction_2 with 50.00 kg batch for hour 1 of 2 Time = 3 hr State Inventories are now: FeedB 137.0 kg IntAB 0.0 kg FeedA 116.0 kg HotA 32.0 kg FeedC 137.0 kg ImpureE 0.0 kg Product_2 0.0 kg IntBC 48.0 kg Product_1 0.0 kg Unit Assignments are now: Heater is unassigned Reactor_1 on Reaction_2 with 80.00 kg batch for hour 2 of 2 Still is unassigned Reactor_2 on Reaction_2 with 50.00 kg batch for hour 2 of 2 Time = 4 hr 1. Transfer 48.00 kg from Reactor_1 to IntAB 2. Transfer 32.00 kg from Reactor_1 to Product_1 3. Transfer 30.00 kg from Reactor_2 to IntAB 4. Transfer 20.00 kg from Reactor_2 to Product_1 5. Assign Heater to Heating for 52.00 kg batch for 1.0 hours 6. Transfer 52.00 from FeedA to Heater 7. Release Reactor_1 from Reaction_2 8. Assign Reactor_1 to Reaction_2 for 80.00 kg batch for 2.0 hours 9. Transfer 48.00 from IntBC to Reactor_1 10. Transfer 32.00 from HotA to Reactor_1 11. Release Reactor_2 from Reaction_2 12. Assign Reactor_2 to Reaction_3 for 50.00 kg batch for 1.0 hours 13. Transfer 10.00 from FeedC to Reactor_2 14. Transfer 40.00 from IntAB to Reactor_2 State Inventories are now: FeedB 137.0 kg IntAB 38.0 kg FeedA 64.0 kg HotA 0.0 kg FeedC 127.0 kg ImpureE 0.0 kg Product_2 0.0 kg IntBC 0.0 kg Product_1 52.0 kg Unit Assignments are now: Heater on Heating with 52.00 kg batch for hour 1 of 1 Reactor_1 on Reaction_2 with 80.00 kg batch for hour 1 of 2 Still is unassigned Reactor_2 on Reaction_3 with 50.00 kg batch for hour 1 of 1 Time = 5 hr 1. Transfer 52.00 kg from Heater to HotA 2. Transfer 50.00 kg from Reactor_2 to ImpureE 3. Release Heater from Heating 4. Assign Still to Separation for 50.00 kg batch for 2.0 hours 5. Transfer 50.00 from ImpureE to Still 6. Release Reactor_2 from Reaction_3 7. Assign Reactor_2 to Reaction_3 for 47.50 kg batch for 1.0 hours 8. Transfer 9.50 from FeedC to Reactor_2 9. Transfer 38.00 from IntAB to Reactor_2 State Inventories are now: FeedB 137.0 kg IntAB 0.0 kg FeedA 64.0 kg HotA 52.0 kg FeedC 117.5 kg ImpureE 0.0 kg Product_2 0.0 kg IntBC 0.0 kg Product_1 52.0 kg Unit Assignments are now: Heater is unassigned Reactor_1 on Reaction_2 with 80.00 kg batch for hour 2 of 2 Still on Separation with 50.00 kg batch for hour 1 of 2 Reactor_2 on Reaction_3 with 47.50 kg batch for hour 1 of 1 Time = 6 hr 1. Transfer 48.00 kg from Reactor_1 to IntAB 2. Transfer 32.00 kg from Reactor_1 to Product_1 3. Transfer 45.00 kg from Still to Product_2 4. Transfer 47.50 kg from Reactor_2 to ImpureE 5. Release Reactor_1 from Reaction_2 6. Assign Reactor_1 to Reaction_1 for 78.00 kg batch for 2.0 hours 7. Transfer 39.00 from FeedC to Reactor_1 8. Transfer 39.00 from FeedB to Reactor_1 9. Release Reactor_2 from Reaction_3 10. Assign Reactor_2 to Reaction_3 for 16.25 kg batch for 1.0 hours 11. Transfer 3.25 from FeedC to Reactor_2 12. Transfer 13.00 from IntAB to Reactor_2 State Inventories are now: FeedB 98.0 kg IntAB 35.0 kg FeedA 64.0 kg HotA 52.0 kg FeedC 75.2 kg ImpureE 47.5 kg Product_2 45.0 kg IntBC 0.0 kg Product_1 84.0 kg Unit Assignments are now: Heater is unassigned Reactor_1 on Reaction_1 with 78.00 kg batch for hour 1 of 2 Still on Separation with 5.00 kg batch for hour 2 of 2 Reactor_2 on Reaction_3 with 16.25 kg batch for hour 1 of 1 Time = 7 hr 1. Transfer 5.00 kg from Still to IntAB 2. Transfer 16.25 kg from Reactor_2 to ImpureE 3. Release Still from Separation 4. Release Reactor_2 from Reaction_3 5. Assign Reactor_2 to Reaction_3 for 50.00 kg batch for 1.0 hours 6. Transfer 10.00 from FeedC to Reactor_2 7. Transfer 40.00 from IntAB to Reactor_2 State Inventories are now: FeedB 98.0 kg IntAB 0.0 kg FeedA 64.0 kg HotA 52.0 kg FeedC 65.2 kg ImpureE 63.8 kg Product_2 45.0 kg IntBC 0.0 kg Product_1 84.0 kg Unit Assignments are now: Heater is unassigned Reactor_1 on Reaction_1 with 78.00 kg batch for hour 2 of 2 Still is unassigned Reactor_2 on Reaction_3 with 50.00 kg batch for hour 1 of 1 Time = 8 hr 1. Transfer 78.00 kg from Reactor_1 to IntBC 2. Transfer 50.00 kg from Reactor_2 to ImpureE 3. Release Reactor_1 from Reaction_1 4. Assign Reactor_1 to Reaction_2 for 80.00 kg batch for 2.0 hours 5. Transfer 48.00 from IntBC to Reactor_1 6. Transfer 32.00 from HotA to Reactor_1 7. Assign Still to Separation for 113.75 kg batch for 2.0 hours 8. Transfer 113.75 from ImpureE to Still 9. Release Reactor_2 from Reaction_3 10. Assign Reactor_2 to Reaction_2 for 50.00 kg batch for 2.0 hours 11. Transfer 30.00 from IntBC to Reactor_2 12. Transfer 20.00 from HotA to Reactor_2 State Inventories are now: FeedB 98.0 kg IntAB 0.0 kg FeedA 64.0 kg HotA 0.0 kg FeedC 65.2 kg ImpureE 0.0 kg Product_2 45.0 kg IntBC 0.0 kg Product_1 84.0 kg Unit Assignments are now: Heater is unassigned Reactor_1 on Reaction_2 with 80.00 kg batch for hour 1 of 2 Still on Separation with 113.75 kg batch for hour 1 of 2 Reactor_2 on Reaction_2 with 50.00 kg batch for hour 1 of 2 Time = 9 hr 1. Transfer 102.38 kg from Still to Product_2 State Inventories are now: FeedB 98.0 kg IntAB 0.0 kg FeedA 64.0 kg HotA 0.0 kg FeedC 65.2 kg ImpureE 0.0 kg Product_2 147.4 kg IntBC 0.0 kg Product_1 84.0 kg Unit Assignments are now: Heater is unassigned Reactor_1 on Reaction_2 with 80.00 kg batch for hour 2 of 2 Still on Separation with 11.38 kg batch for hour 2 of 2 Reactor_2 on Reaction_2 with 50.00 kg batch for hour 2 of 2 Time = 10 hr 1. Transfer 48.00 kg from Reactor_1 to IntAB 2. Transfer 32.00 kg from Reactor_1 to Product_1 3. Transfer 11.38 kg from Still to IntAB 4. Transfer 30.00 kg from Reactor_2 to IntAB 5. Transfer 20.00 kg from Reactor_2 to Product_1 6. Release Reactor_1 from Reaction_2 7. Release Still from Separation 8. Release Reactor_2 from Reaction_2 State Inventories are now: FeedB 98.0 kg IntAB 89.4 kg FeedA 64.0 kg HotA 0.0 kg FeedC 65.2 kg ImpureE 0.0 kg Product_2 147.4 kg IntBC 0.0 kg Product_1 136.0 kg Unit Assignments are now: Heater is unassigned Reactor_1 is unassigned Still is unassigned Reactor_2 is unassigned