alpar@1: # EGYPT, a static model of fertilizer production alpar@1: # alpar@1: # References: alpar@1: # Robert Fourer, David M. Gay and Brian W. Kernighan, "A Modeling Language alpar@1: # for Mathematical Programming." Management Science 36 (1990) 519-554. alpar@1: alpar@1: ### SETS ### alpar@1: alpar@1: set center; # Locations from which final product may be shipped alpar@1: set port within center; # Locations at which imports can be received alpar@1: set plant within center; # Locations of plants alpar@1: alpar@1: set region; # Demand regions alpar@1: alpar@1: set unit; # Productive units alpar@1: set proc; # Processes alpar@1: alpar@1: set nutr; # Nutrients alpar@1: alpar@1: set c_final; # Final products (fertilizers) alpar@1: set c_inter; # Intermediate products alpar@1: set c_ship within c_inter; # Intermediates for shipment alpar@1: set c_raw; # Domestic raw materials and miscellaneous inputs alpar@1: alpar@1: set commod := c_final union c_inter union c_raw; alpar@1: alpar@1: # All commodities alpar@1: alpar@1: ### PARAMETERS ### alpar@1: alpar@1: param cf75 {region,c_final} >= 0; alpar@1: alpar@1: # Consumption of fertilizer 1974-75 (1000 tpy) alpar@1: alpar@1: param fn {c_final,nutr} >= 0; alpar@1: alpar@1: # Nutrient content of fertilizers alpar@1: alpar@1: param cn75 {r in region, n in nutr} := sum {c in c_final} cf75[r,c] * fn[c,n]; alpar@1: alpar@1: # Consumption of nutrients 1974-75 (1000 tpy) alpar@1: alpar@1: param road {region,center} >= 0; alpar@1: alpar@1: # Road distances alpar@1: alpar@1: param rail_half {plant,plant} >= 0; alpar@1: param rail {p1 in plant, p2 in plant} := alpar@1: if rail_half[p1,p2] > 0 then rail_half[p1,p2] else rail_half[p2,p1]; alpar@1: alpar@1: # Interplant rail distances (kms) alpar@1: alpar@1: param impd_barg {plant} >= 0; alpar@1: param impd_road {plant} >= 0; alpar@1: alpar@1: # Import distances (kms) by barge and road alpar@1: alpar@1: param tran_final {pl in plant, r in region} := alpar@1: if road[r,pl] > 0 then .5 + .0144 * road[r,pl] else 0; alpar@1: alpar@1: param tran_import {r in region, po in port} := alpar@1: if road[r,po] > 0 then .5 + .0144 * road[r,po] else 0; alpar@1: alpar@1: param tran_inter {p1 in plant, p2 in plant} := alpar@1: if rail[p1,p2] > 0 then 3.5 + .03 * rail[p1,p2] else 0; alpar@1: alpar@1: param tran_raw {pl in plant} := alpar@1: (if impd_barg[pl] > 0 then 1.0 + .0030 * impd_barg[pl] else 0) alpar@1: + (if impd_road[pl] > 0 then 0.5 + .0144 * impd_road[pl] else 0); alpar@1: alpar@1: # Transport cost (le per ton) for: alpar@1: # final products, imported final products, alpar@1: # interplant shipment, imported raw materials alpar@1: alpar@1: param io {commod,proc}; # Input-output coefficients alpar@1: alpar@1: param util {unit,proc} >= 0; alpar@1: alpar@1: # Capacity utilization coefficients alpar@1: alpar@1: param p_imp {commod} >= 0; # Import Price (cif US$ per ton 1975) alpar@1: alpar@1: param p_r {c_raw} >= 0; alpar@1: param p_pr {plant,c_raw} >= 0; alpar@1: alpar@1: param p_dom {pl in plant, c in c_raw} := alpar@1: if p_r[c] > 0 then p_r[c] else p_pr[pl,c]; alpar@1: alpar@1: # Domestic raw material prices alpar@1: alpar@1: param dcap {plant,unit} >= 0; alpar@1: alpar@1: # Design capacity of plants (t/day) alpar@1: alpar@1: param icap {u in unit, pl in plant} := 0.33 * dcap[pl,u]; alpar@1: alpar@1: # Initial capacity of plants (t/day) alpar@1: alpar@1: param exch := 0.4; # Exchange rate alpar@1: alpar@1: param util_pct := 0.85; # Utilization percent for initial capacity alpar@1: alpar@1: ### DERIVED SETS OF "POSSIBILITIES" ### alpar@1: alpar@1: set m_pos {pl in plant} := {u in unit: icap[u,pl] > 0}; alpar@1: alpar@1: # At each plant, set of units for which there is alpar@1: # initial capacity alpar@1: alpar@1: set p_cap {pl in plant} := alpar@1: {pr in proc: forall {u in unit: util[u,pr] > 0} u in m_pos[pl] }; alpar@1: alpar@1: # At each plant, set of processes for which alpar@1: # all necessary units have some initial capacity alpar@1: alpar@1: set p_except {plant} within proc; alpar@1: alpar@1: # At each plant, list of processes that are alpar@1: # arbitrarily ruled out alpar@1: alpar@1: set p_pos {pl in plant} := p_cap[pl] diff p_except[pl]; alpar@1: alpar@1: # At each plant, set of possible processes alpar@1: alpar@1: set cp_pos {c in commod} := {pl in plant: sum {pr in p_pos[pl]} io[c,pr] > 0}; alpar@1: alpar@1: set cc_pos {c in commod} := {pl in plant: sum {pr in p_pos[pl]} io[c,pr] < 0}; alpar@1: alpar@1: set c_pos {c in commod} := cp_pos[c] union cc_pos[c]; alpar@1: alpar@1: # For each commodity, set of plants that can alpar@1: # produce it (cp_pos) or consume it (cc_pos), alpar@1: # and their union (c_pos) alpar@1: alpar@1: ### VARIABLES ### alpar@1: alpar@1: var Z {pl in plant, p_pos[pl]} >= 0; alpar@1: alpar@1: # Z[pl,pr] is level of process pr at plant pl alpar@1: alpar@1: var Xf {c in c_final, cp_pos[c], region} >= 0; alpar@1: alpar@1: # Xf[c,pl,r] is amount of final product c alpar@1: # shipped from plant pl to region r alpar@1: alpar@1: var Xi {c in c_ship, cp_pos[c], cc_pos[c]} >= 0; alpar@1: alpar@1: # Xi[c,p1,p2] is amount of intermediate c alpar@1: # shipped from plant p1 to plant p2 alpar@1: alpar@1: var Vf {c_final,region,port} >= 0; alpar@1: alpar@1: # Vf[c,r,po] is amount of final product c alpar@1: # imported by region r from port po alpar@1: alpar@1: var Vr {c in c_raw, cc_pos[c]} >= 0; alpar@1: alpar@1: # Vr[c,pl] is amount of raw material c alpar@1: # imported for use at plant pl alpar@1: alpar@1: var U {c in c_raw, cc_pos[c]} >= 0; alpar@1: alpar@1: # U[c,pl] is amount of raw material c alpar@1: # purchased domestically for use at plant pl alpar@1: alpar@1: var Psip; # Domestic recurrent cost alpar@1: var Psil; # Transport cost alpar@1: var Psii; # Import cost alpar@1: alpar@1: ### OBJECTIVE ### alpar@1: alpar@1: minimize Psi: Psip + Psil + Psii; alpar@1: alpar@1: ### CONSTRAINTS ### alpar@1: alpar@1: subject to mbd {n in nutr, r in region}: alpar@1: alpar@1: sum {c in c_final} fn[c,n] * alpar@1: (sum {po in port} Vf[c,r,po] + alpar@1: sum {pl in cp_pos[c]} Xf[c,pl,r]) >= cn75[r,n]; alpar@1: alpar@1: # Total nutrients supplied to a region by all alpar@1: # final products (sum of imports plus internal alpar@1: # shipments from plants) must meet requirements alpar@1: alpar@1: subject to mbdb {c in c_final, r in region: cf75[r,c] > 0}: alpar@1: alpar@1: sum {po in port} Vf[c,r,po] + alpar@1: sum {pl in cp_pos[c]} Xf[c,pl,r] >= cf75[r,c]; alpar@1: alpar@1: # Total of each final product supplied to each alpar@1: # region (as in previous constraint) must meet alpar@1: # requirements alpar@1: alpar@1: subject to mb {c in commod, pl in plant}: alpar@1: alpar@1: sum {pr in p_pos[pl]} io[c,pr] * Z[pl,pr] alpar@1: alpar@1: + ( if c in c_ship then alpar@1: ( if pl in cp_pos[c] then sum {p2 in cc_pos[c]} Xi[c,pl,p2] ) alpar@1: - ( if pl in cc_pos[c] then sum {p2 in cp_pos[c]} Xi[c,p2,pl] )) alpar@1: alpar@1: + ( if (c in c_raw and pl in cc_pos[c]) then alpar@1: (( if p_imp[c] > 0 then Vr[c,pl] ) alpar@1: + ( if p_dom[pl,c] > 0 then U[c,pl] ))) alpar@1: alpar@1: >= if (c in c_final and pl in cp_pos[c]) then sum {r in region} Xf[c,pl,r]; alpar@1: alpar@1: # For each commodity at each plant: sum of alpar@1: # (1) production or consumption at plant, alpar@1: # (2) inter-plant shipments in or out, alpar@1: # (3) import and domestic purchases (raw only) alpar@1: # is >= 0 for raw materials and intermediates; alpar@1: # is >= the total shipped for final products alpar@1: alpar@1: subject to cc {pl in plant, u in m_pos[pl]}: alpar@1: alpar@1: sum {pr in p_pos[pl]} util[u,pr] * Z[pl,pr] <= util_pct * icap[u,pl]; alpar@1: alpar@1: # For each productive unit at each plant, alpar@1: # total utilization by all processes alpar@1: # may not exceed the unit's capacity alpar@1: alpar@1: subject to ap: alpar@1: alpar@1: Psip = sum {c in c_raw, pl in cc_pos[c]} p_dom[pl,c] * U[c,pl]; alpar@1: alpar@1: # Psip is the cost of domestic raw materials, alpar@1: # summed over all plants that consume them alpar@1: alpar@1: subject to al: alpar@1: alpar@1: Psil = sum {c in c_final} ( alpar@1: alpar@1: sum {pl in cp_pos[c], r in region} alpar@1: tran_final[pl,r] * Xf[c,pl,r] alpar@1: alpar@1: + sum {po in port, r in region} tran_import[r,po] * Vf[c,r,po] ) alpar@1: alpar@1: + sum {c in c_ship, p1 in cp_pos[c], p2 in cc_pos[c]} alpar@1: tran_inter[p1,p2] * Xi[c,p1,p2] alpar@1: alpar@1: + sum {c in c_raw, pl in cc_pos[c]: p_imp[c] > 0} alpar@1: tran_raw[pl] * Vr[c,pl]; alpar@1: alpar@1: # Total transport cost is sum of shipping costs for alpar@1: # (1) all final products from all plants, alpar@1: # (2) all imports of final products, alpar@1: # (3) all intermediates shipped between plants, alpar@1: # (4) all imports of raw materials alpar@1: alpar@1: subject to ai: alpar@1: alpar@1: Psii / exch = sum {c in c_final, r in region, po in port} alpar@1: p_imp[c] * Vf[c,r,po] alpar@1: alpar@1: + sum {c in c_raw, pl in cc_pos[c]} p_imp[c] * Vr[c,pl]; alpar@1: alpar@1: # Total import cost -- at exchange rate -- alpar@1: # is sum of import costs for final products alpar@1: # in each region and raw materials at each plant alpar@1: alpar@1: ### DATA ### alpar@1: alpar@1: data; alpar@1: alpar@1: set center := ASWAN HELWAN ASSIOUT KAFR_EL_ZT ABU_ZAABAL ABU_KIR TALKHA SUEZ ; alpar@1: alpar@1: set port := ABU_KIR ; alpar@1: alpar@1: set plant := ASWAN HELWAN ASSIOUT KAFR_EL_ZT ABU_ZAABAL ; alpar@1: alpar@1: set region := ALEXANDRIA BEHERA GHARBIA KAFR_EL_SH DAKAHLIA DAMIETTA alpar@1: SHARKIA ISMAILIA SUEZ MENOUFIA KALUBIA GIZA BENI_SUEF FAYOUM alpar@1: MINIA ASSIOUT NEW_VALLEY SOHAG QUENA ASWAN ; alpar@1: alpar@1: set unit := SULF_A_S SULF_A_P NITR_ACID AMM_ELEC AMM_C_GAS C_AMM_NITR alpar@1: AMM_SULF SSP ; alpar@1: alpar@1: set proc := SULF_A_S SULF_A_P NITR_ACID AMM_ELEC AMM_C_GAS CAN_310 CAN_335 alpar@1: AMM_SULF SSP_155 ; alpar@1: alpar@1: set nutr := N P205 ; alpar@1: alpar@1: set c_final := UREA CAN_260 CAN_310 CAN_335 AMM_SULF DAP SSP_155 C_250_55 alpar@1: C_300_100 ; alpar@1: alpar@1: set c_inter := AMMONIA NITR_ACID SULF_ACID ; alpar@1: alpar@1: set c_ship := AMMONIA SULF_ACID ; alpar@1: alpar@1: set c_raw := EL_ASWAN COKE_GAS PHOS_ROCK LIMESTONE EL_SULFUR PYRITES alpar@1: ELECTRIC BF_GAS WATER STEAM BAGS ; alpar@1: alpar@1: set p_except[ASWAN] := CAN_335 ; alpar@1: set p_except[HELWAN] := CAN_310 ; alpar@1: set p_except[ASSIOUT] := ; alpar@1: set p_except[KAFR_EL_ZT] := ; alpar@1: set p_except[ABU_ZAABAL] := ; alpar@1: alpar@1: param cf75 default 0.0 : alpar@1: alpar@1: CAN_260 CAN_310 CAN_335 AMM_SULF UREA := alpar@1: alpar@1: ALEXANDRIA . . 5.0 3.0 1.0 alpar@1: ASSIOUT 1.0 20.0 26.0 1.0 27.0 alpar@1: ASWAN . 40.0 . . . alpar@1: BEHERA 1.0 . 25.0 90.0 35.0 alpar@1: BENI_SUEF 1.0 . 15.0 1.0 20.0 alpar@1: DAKAHLIA 1.0 . 26.0 60.0 20.0 alpar@1: DAMIETTA . . 2.0 15.0 8.0 alpar@1: FAYOUM 1.0 . 20.0 6.0 20.0 alpar@1: GHARBIA . . 17.0 60.0 28.0 alpar@1: GIZA . . 40.0 6.0 2.0 alpar@1: ISMAILIA . . 4.0 6.0 2.0 alpar@1: KAFR_EL_SH 1.0 . 10.0 45.0 22.0 alpar@1: KALUBIA . . 25.0 16.0 7.0 alpar@1: MENOUFIA 1.0 . 24.0 21.0 30.0 alpar@1: MINIA 2.0 15.0 35.0 1.0 41.0 alpar@1: NEW_VALLEY . . . . 1.0 alpar@1: QUENA . 95.0 2.0 . 3.0 alpar@1: SHARKIA 1.0 . 31.0 50.0 28.0 alpar@1: SOHAG . 65.0 3.0 . 7.0 alpar@1: SUEZ . . 1.0 . . alpar@1: alpar@1: : SSP_155 C_250_55 C_300_100 DAP := alpar@1: alpar@1: ALEXANDRIA 8.0 . . . alpar@1: ASSIOUT 35.0 5.0 .1 . alpar@1: ASWAN 8.0 . . . alpar@1: BEHERA 64.0 1.0 .1 .1 alpar@1: BENI_SUEF 13.0 3.0 . . alpar@1: DAKAHLIA 52.0 1.0 . . alpar@1: DAMIETTA 5.0 . . . alpar@1: FAYOUM 17.0 1.0 . . alpar@1: GHARBIA 57.0 1.0 .2 .1 alpar@1: GIZA 14.0 1.0 .1 . alpar@1: ISMAILIA 4.0 . . . alpar@1: KAFR_EL_SH 25.0 2.0 .1 . alpar@1: KALUBIA 22.0 1.0 . .1 alpar@1: MENOUFIA 33.0 2.0 .1 .1 alpar@1: MINIA 50.0 3.0 .2 .1 alpar@1: NEW_VALLEY 1.0 . . . alpar@1: QUENA 8.0 . . . alpar@1: SHARKIA 43.0 1.0 .1 . alpar@1: SOHAG 20.0 1.0 . . alpar@1: SUEZ 1.0 . . . ; alpar@1: alpar@1: param fn default 0.0 : N P205 := alpar@1: alpar@1: AMM_SULF .206 . alpar@1: CAN_260 .26 . alpar@1: CAN_310 .31 . alpar@1: CAN_335 .335 . alpar@1: C_250_55 .25 .055 alpar@1: C_300_100 .30 .10 alpar@1: DAP .18 .46 alpar@1: SSP_155 . .15 alpar@1: UREA .46 . ; alpar@1: alpar@1: param road default 0.0 : alpar@1: alpar@1: ABU_KIR ABU_ZAABAL ASSIOUT ASWAN HELWAN KAFR_EL_ZT SUEZ TALKHA := alpar@1: alpar@1: ALEXANDRIA 16 210 607 1135 244 119 362 187 alpar@1: ASSIOUT 616 420 . 518 362 504 527 518 alpar@1: ASWAN 1134 938 518 . 880 1022 1045 1036 alpar@1: BEHERA 76 50 547 1065 184 42 288 120 alpar@1: BENI_SUEF 359 163 257 775 105 248 270 261 alpar@1: DAKAHLIA 208 138 515 1033 152 58 219 3 alpar@1: DAMIETTA 267 216 596 1114 233 131 286 66 alpar@1: FAYOUM 341 145 308 826 88 230 252 243 alpar@1: GHARBIA 150 65 485 1003 122 20 226 55 alpar@1: GIZA 287 48 372 890 .9 133 169 146 alpar@1: ISMAILIA 365 142 536 1054 173 241 89 146 alpar@1: KAFR_EL_SH 145 105 525 1043 162 20 266 35 alpar@1: KALUBIA 190 97 439 957 76 66 180 81 alpar@1: MENOUFIA 157 154 472 990 109 33 213 90 alpar@1: MINIA 384 288 132 650 230 372 394 386 alpar@1: NEW_VALLEY 815 619 199 519 561 703 726 717 alpar@1: QUENA 858 662 242 276 604 746 769 760 alpar@1: SHARKIA 240 60 473 991 110 78 214 58 alpar@1: SOHAG 715 519 99 419 461 603 626 617 alpar@1: SUEZ 370 224 541 1059 178 246 . 298 ; alpar@1: alpar@1: param rail_half default 0 : alpar@1: alpar@1: KAFR_EL_ZT ABU_ZAABAL HELWAN ASSIOUT := alpar@1: alpar@1: ABU_ZAABAL 85 . . . alpar@1: HELWAN 142 57 . . alpar@1: ASSIOUT 504 420 362 . alpar@1: ASWAN 1022 938 880 518 ; alpar@1: alpar@1: param : impd_barg impd_road := alpar@1: alpar@1: ABU_ZAABAL 210 .1 alpar@1: ASSIOUT 583 0 alpar@1: ASWAN 1087 10 alpar@1: HELWAN 183 0 alpar@1: KAFR_EL_ZT 104 6 ; alpar@1: alpar@1: param io default 0.0 := alpar@1: alpar@1: [*,AMM_C_GAS] AMMONIA 1.0 alpar@1: BF_GAS -609. alpar@1: COKE_GAS -2.0 alpar@1: ELECTRIC -1960. alpar@1: STEAM -4. alpar@1: WATER -700. alpar@1: alpar@1: [*,AMM_ELEC] AMMONIA 1.0 alpar@1: EL_ASWAN -12.0 alpar@1: alpar@1: [*,AMM_SULF] AMMONIA -.26 alpar@1: AMM_SULF 1.0 alpar@1: BAGS -22. alpar@1: ELECTRIC -19. alpar@1: SULF_ACID -.76 alpar@1: WATER -17. alpar@1: alpar@1: [*,CAN_310] AMMONIA -.20 alpar@1: BAGS -23. alpar@1: CAN_310 1.0 alpar@1: LIMESTONE -.12 alpar@1: NITR_ACID -.71 alpar@1: STEAM -.4 alpar@1: WATER -49. alpar@1: alpar@1: [*,CAN_335] AMMONIA -.21 alpar@1: BAGS -23. alpar@1: CAN_335 1.0 alpar@1: LIMESTONE -.04 alpar@1: NITR_ACID -.76 alpar@1: STEAM -.4 alpar@1: WATER -49. alpar@1: alpar@1: [*,NITR_ACID] AMMONIA -.292 alpar@1: ELECTRIC -231. alpar@1: NITR_ACID 1.0 alpar@1: WATER -.6 alpar@1: alpar@1: [*,SSP_155] BAGS -22. alpar@1: ELECTRIC -14. alpar@1: PHOS_ROCK -.62 alpar@1: SSP_155 1.0 alpar@1: SULF_ACID -.41 alpar@1: WATER -6. alpar@1: alpar@1: [*,SULF_A_P] ELECTRIC -75. alpar@1: PYRITES -.826 alpar@1: SULF_ACID 1.0 alpar@1: WATER -60. alpar@1: alpar@1: [*,SULF_A_S] ELECTRIC -50. alpar@1: EL_SULFUR -.334 alpar@1: SULF_ACID 1.0 alpar@1: WATER -20. ; alpar@1: alpar@1: param util default 0 := alpar@1: alpar@1: [*,*] SULF_A_S SULF_A_S 1 SULF_A_P SULF_A_P 1 alpar@1: NITR_ACID NITR_ACID 1 AMM_ELEC AMM_ELEC 1 alpar@1: AMM_C_GAS AMM_C_GAS 1 SSP SSP_155 1 alpar@1: C_AMM_NITR CAN_310 1 C_AMM_NITR CAN_335 1 alpar@1: AMM_SULF AMM_SULF 1 ; alpar@1: alpar@1: param p_imp default 0.0 := alpar@1: alpar@1: PYRITES 17.5 AMM_SULF 75. alpar@1: EL_SULFUR 55. DAP 175. alpar@1: UREA 150. SSP_155 80. alpar@1: CAN_260 75. C_250_55 100. alpar@1: CAN_310 90. C_300_100 130. alpar@1: CAN_335 100. ; alpar@1: alpar@1: param p_r default 0.0 := alpar@1: alpar@1: ELECTRIC .007 alpar@1: BF_GAS .007 alpar@1: WATER .031 alpar@1: STEAM 1.25 alpar@1: BAGS .28 ; alpar@1: alpar@1: param p_pr default 0.0 := alpar@1: alpar@1: [HELWAN,COKE_GAS] 16.0 alpar@1: [ASWAN,EL_ASWAN] 1.0 alpar@1: alpar@1: [*,LIMESTONE] ASWAN 1.2 alpar@1: HELWAN 1.2 alpar@1: alpar@1: [*,PHOS_ROCK] ABU_ZAABAL 4.0 alpar@1: ASSIOUT 3.5 alpar@1: KAFR_EL_ZT 5.0 ; alpar@1: alpar@1: param dcap default 0.0 := alpar@1: alpar@1: [ABU_ZAABAL,*] SSP 600 alpar@1: SULF_A_P 227 alpar@1: SULF_A_S 242 alpar@1: alpar@1: [ASSIOUT,*] SSP 600 alpar@1: SULF_A_S 250 alpar@1: alpar@1: [ASWAN,*] AMM_ELEC 450 alpar@1: C_AMM_NITR 1100 alpar@1: NITR_ACID 800 alpar@1: alpar@1: [HELWAN,*] AMM_C_GAS 172 alpar@1: AMM_SULF 24 alpar@1: C_AMM_NITR 364 alpar@1: NITR_ACID 282 alpar@1: alpar@1: [KAFR_EL_ZT,*] SSP 600 alpar@1: SULF_A_P 50 alpar@1: SULF_A_S 200 ; alpar@1: alpar@1: end;