SAS code in NETFLOW procedure chapter (netflow)
/****************************************************************/
/* S A S S A M P L E L I B R A R Y */
/* */
/* NAME: netflow */
/* TITLE: SAS code in NETFLOW procedure chapter (netflow) */
/* PRODUCT: OR */
/* SYSTEM: ALL */
/* KEYS: NETFLOW */
/* PROCS: NETFLOW */
/* DATA: */
/* */
/* SUPPORT: UPDATE: */
/* REF: */
/* MISC: */
/* */
/****************************************************************/
/****************************************************************
* *
* Introductory Example *
* *
****************************************************************/
title 'Oil Industry Example';
title3 'Setting Up Nodedata = Noded For Proc Netflow';
data noded;
input _node_&$15. _sd_;
datalines;
middle east 100
u.s.a. 80
servstn1 gas -95
servstn1 diesel -30
servstn2 gas -40
servstn2 diesel -15
;
title3 'Setting Up Arcdata = Arcd1 For Proc Netflow';
data arcd1;
input _from_&$11. _to_&$15. _cost_ _capac_ _lo_ _name_ $;
datalines;
middle east refinery 1 63 95 20 m_e_ref1
middle east refinery 2 81 80 10 m_e_ref2
u.s.a. refinery 1 55 . . .
u.s.a. refinery 2 49 . . .
refinery 1 r1 200 175 50 thruput1
refinery 2 r2 220 100 35 thruput2
r1 ref1 gas . 140 . r1_gas
r1 ref1 diesel . 75 . .
r2 ref2 gas . 100 . r2_gas
r2 ref2 diesel . 75 . .
ref1 gas servstn1 gas 15 70 . .
ref1 gas servstn2 gas 22 60 . .
ref1 diesel servstn1 diesel 18 . . .
ref1 diesel servstn2 diesel 17 . . .
ref2 gas servstn1 gas 17 35 5 .
ref2 gas servstn2 gas 31 . . .
ref2 diesel servstn1 diesel 36 . . .
ref2 diesel servstn2 diesel 23 . . .
;
title3 'Setting Up Condata = Cond1 For Proc Netflow';
data cond1;
input m_e_ref1 m_e_ref2 thruput1 r1_gas thruput2 r2_gas
_type_ $ _rhs_;
datalines;
-2 . 1 . . . >= -15
. -2 . . 1 . GE -15
. . -3 4 . . EQ 0
. . . . -3 4 = 0
;
proc netflow
nodedata=noded /* the supply and demand data */
arcdata=arcd1 /* the arc descriptions */
condata=cond1 /* the side constraints */
conout=solution; /* the solution data set */
run;
proc print data=solution;
var _from_ _to_ _cost_ _capac_ _lo_ _name_
_supply_ _demand_ _flow_ _fcost_ _rcost_;
sum _fcost_;
title3 'Constrained Optimum';
run;
/****************************************************************
* *
* Syntax: NAMECTRL= Option *
* *
****************************************************************/
data arcdata;
input _from_ $ _to_ $ _name $ ;
datalines;
from to1 .
from to2 arc2
TAIL TO3 .
;
data densecon;
input from_to1 from_to2 arc2 tail_to3;
datalines;
2 3 3 5
;
proc netflow
arcdata=arcdata condata=densecon;
run;
/****************************************************************
* *
* Details: Input Data Sets: Condata *
* *
****************************************************************/
/* Dense formulations */
data cond1;
input m_e_ref1 m_e_ref2 thruput1 r1_gas thruput2 r2_gas
_type_ $ _rhs_;
datalines;
-2 . 1 . . . >= -15
. -2 . . 1 . GE -15
. . -3 4 . . EQ 0
. . . . -3 4 = 0
;
data cond1b;
input m_e_ref1 m_e_ref2 thruput1 r1_gas thruput2 r2_gas
_type_ $ _rhs_;
datalines;
63 81 200 . 220 . cost .
95 80 175 140 100 100 capac .
20 10 50 . 35 . lo .
-2 . 1 . . . >= -15
. -2 . . 1 . GE -15
. . -3 4 . . EQ 0
. . . . -3 4 = 0
;
data cond1c;
input _row_ $
m_e_ref1 m_e_ref2 thruput1 r1_gas thruput2 r2_gas
_type_ $ _rhs_;
datalines;
costrow 63 . . . . . . .
costrow . 81 200 . . . cost .
. . . . . 220 . cost .
caprow . . . . . . capac .
caprow 95 . 175 . 100 100 . .
caprow . 80 175 140 . . . .
lorow 20 10 50 . 35 . lo .
con1 -2 . 1 . . . . .
con1 . . . . . . >= -15
con2 . -2 . . 1 . GE -15
con3 . . -3 4 . . EQ 0
con4 . . . . -3 4 = 0
;
/* Sparse formulations */
title 'Setting Up Condata = Cond2 for PROC NETFLOW';
data cond2;
input _column_ $ _row1 $ _coef1 _row2 $ _coef2 ;
datalines;
m_e_ref1 con1 -2 . .
m_e_ref2 con2 -2 . .
thruput1 con1 1 con3 -3
r1_gas . . con3 4
thruput2 con2 1 con4 -3
r2_gas . . con4 4
_type_ con1 1 con2 1
_type_ con3 0 con4 0
_rhs_ con1 -15 con2 -15
;
title 'Setting Up Condata = Cond3 for PROC NETFLOW';
data cond3;
input _column_ $ _row1 $ _coef1 _row2 $ _coef2 _type_ $ ;
datalines;
m_e_ref1 con1 -2 . . >=
m_e_ref2 con2 -2 . . .
thruput1 con1 1 con3 -3 .
r1_gas . . con3 4 .
thruput2 con2 1 con4 -3 .
r2_gas . . con4 4 .
. con3 . con4 . eq
. con1 -15 con2 -15 ge
;
title3 'Setting Up Arcdata = Arcd2 for PROC NETFLOW';
data arcd2;
input _from_&$11. _to_&$15. ;
datalines;
middle east refinery 1
middle east refinery 2
u.s.a. refinery 1
u.s.a. refinery 2
refinery 1 r1
refinery 2 r2
r1 ref1 gas
r1 ref1 diesel
r2 ref2 gas
r2 ref2 diesel
ref1 gas servstn1 gas
ref1 gas servstn2 gas
ref1 diesel servstn1 diesel
ref1 diesel servstn2 diesel
ref2 gas servstn1 gas
ref2 gas servstn2 gas
ref2 diesel servstn1 diesel
ref2 diesel servstn2 diesel
;
title 'Setting Up Condata = Cond4 for PROC NETFLOW';
data cond4;
input _column_&$27. _row1 $ _coef1 _row2 $ _coef2 _type_ $ ;
datalines;
. con1 -15 con2 -15 ge
. costrow . . . cost
. . . caprow . capac
middle east_refinery 1 con1 -2 . . .
middle east_refinery 2 con2 -2 . . .
refinery 1_r1 con1 1 con3 -3 .
r1_ref1 gas . . con3 4 =
refinery 2_r2 con2 1 con4 -3 .
r2_ref2 gas . . con4 4 eq
middle east_refinery 1 costrow 63 caprow 95 .
middle east_refinery 2 costrow 81 caprow 80 .
u.s.a._refinery 1 costrow 55 . . .
u.s.a._refinery 2 costrow 49 . . .
refinery 1_r1 costrow 200 caprow 175 .
refinery 2_r2 costrow 220 caprow 100 .
r1_ref1 gas . . caprow 140 .
r1_ref1 diesel . . caprow 75 .
r2_ref2 gas . . caprow 100 .
r2_ref2 diesel . . caprow 75 .
ref1 gas_servstn1 gas costrow 15 caprow 70 .
ref1 gas_servstn2 gas costrow 22 caprow 60 .
ref1 diesel_servstn1 diesel costrow 18 . . .
ref1 diesel_servstn2 diesel costrow 17 . . .
ref2 gas_servstn1 gas costrow 17 caprow 35 .
ref2 gas_servstn2 gas costrow 31 . . .
ref2 diesel_servstn1 diesel costrow 36 . . .
ref2 diesel_servstn2 diesel costrow 23 . . .
middle east_refinery 1 . 20 . . lo
middle east_refinery 2 . 10 . . lo
refinery 1_r1 . 50 . . lo
refinery 2_r2 . 35 . . lo
ref2 gas_servstn1 gas . 5 . . lo
;
title 'Setting Up Condata = Cond5 for PROC NETFLOW';
data cond5;
input _column_&$27. _row1 $ _coef1 _row2 $ _coef2 _type_ $ ;
datalines;
middle east_refinery 1 con1 -2 costrow 63 .
middle east_refinery 2 con2 -2 lorow 10 .
refinery 1_r1 . . con3 -3 =
r1_ref1 gas caprow 140 con3 4 .
refinery 2_r2 con2 1 con4 -3 .
r2_ref2 gas . . con4 4 eq
. CON1 -15 CON2 -15 GE
ref2 diesel_servstn1 diesel . 36 costrow . cost
. . . caprow . capac
. lorow . . . lo
middle east_refinery 1 caprow 95 lorow 20 .
middle east_refinery 2 caprow 80 costrow 81 .
u.s.a._refinery 1 . . . 55 cost
u.s.a._refinery 2 costrow 49 . . .
refinery 1_r1 con1 1 caprow 175 .
refinery 1_r1 lorow 50 costrow 200 .
refinery 2_r2 costrow 220 caprow 100 .
refinery 2_r2 . 35 . . lo
r1_ref1 diesel caprow2 75 . . capac
r2_ref2 gas . . caprow 100 .
r2_ref2 diesel caprow2 75 . . .
ref1 gas_servstn1 gas costrow 15 caprow 70 .
ref1 gas_servstn2 gas caprow2 60 costrow 22 .
ref1 diesel_servstn1 diesel . . costrow 18 .
ref1 diesel_servstn2 diesel costrow 17 . . .
ref2 gas_servstn1 gas costrow 17 lorow 5 .
ref2 gas_servstn1 gas . . caprow2 35 .
ref2 gas_servstn2 gas . 31 . . cost
ref2 diesel_servstn2 diesel . . costrow 23 .
;
/****************************************************************
* *
* Missing S and Missing D Demand Parameters *
* *
****************************************************************/
title 'Oil Industry Example';
title3 'Crude Oil can come from anywhere';
data miss_s;
missing S;
input _node_&$15. _sd_;
datalines;
middle east S
u.s.a. S
servstn1 gas -95
servstn1 diesel -30
servstn2 gas -40
servstn2 diesel -15
;
proc netflow
nodedata=miss_s /* the supply (missing S) and */
/* demand data */
arcdata=arcd1 /* the arc descriptions */
condata=cond1 /* the side constraints */
conout=solution; /* the solution data set */
run;
print some_arcs('middle east' 'u.s.a.',_all_)/short;
proc print;
sum _fcost_;
run;
data miss_s_x;
missing S;
input _node_&$15. _sd_;
datalines;
middle east 1
u.s.a. 1
servstn1 gas -95
servstn1 diesel -30
servstn2 gas -40
servstn2 diesel -15
;
proc netflow
thrunet
nodedata=miss_s_x /* No supply (missing S) */
arcdata=arcd1 /* the arc descriptions */
condata=cond1 /* the side constraints */
conout=solution; /* the solution data set */
run;
print some_arcs('middle east' 'u.s.a.',_all_)/short;
proc print;
sum _fcost_;
run;
/****************************************************************
* *
* Network Models: Interior Point Algorithm *
* *
****************************************************************/
/* Introductory Example: Network Models:
Interior Point Algorithm */
proc netflow
intpoint /* <<<--- Interior Point used */
nodedata=noded /* the supply and demand data */
arcdata=arcd1 /* the arc descriptions */
condata=cond1 /* the side constraints */
conout=solution; /* the solution data set */
run;
proc print data=solution;
var _from_ _to_ _cost_ _capac_ _lo_ _name_
_supply_ _demand_ _flow_ _fcost_ ;
sum _fcost_;
title3 'Constrained Optimum';
run;
/* Introductory Example: Linear Programming Models:
Interior Point Algorithm */
data dcon1;
input _id_ $17.
a_light a_heavy brega naphthal naphthai
heatingo jet_1 jet_2
_type_ $ _rhs_;
datalines;
profit -175 -165 -205 0 0 0 300 300 max .
naphtha_l_conv .035 .030 .045 -1 0 0 0 0 eq 0
naphtha_i_conv .100 .075 .135 0 -1 0 0 0 eq 0
heating_o_conv .390 .300 .430 0 0 -1 0 0 eq 0
recipe_1 0 0 0 0 .3 .7 -1 0 eq 0
recipe_2 0 0 0 .2 0 .8 0 -1 eq 0
available 110 165 80 . . . . . upperbd .
;
proc netflow
arcdata=dcon1
condata=dcon1
conout=solutn1;
run;
print problem/short;
proc print data=solutn1;
var _name_ _objfn_ _upperbd _lowerbd _value_ _fcost_;
sum _fcost_;
title3 'LP Optimum';
run;
data scon2;
format _type_ $8. _col_ $8. _row_ $16. ;
input _type_ $ _col_ $ _row_ $ _coef_;
datalines;
max . profit .
eq . napha_l_conv .
eq . napha_i_conv .
eq . heating_oil_conv .
eq . recipe_1 .
eq . recipe_2 .
upperbd . available .
. a_light profit -175
. a_light napha_l_conv .035
. a_light napha_i_conv .100
. a_light heating_oil_conv .390
. a_light available 110
. a_heavy profit -165
. a_heavy napha_l_conv .030
. a_heavy napha_i_conv .075
. a_heavy heating_oil_conv .300
. a_heavy available 165
. brega profit -205
. brega napha_l_conv .045
. brega napha_i_conv .135
. brega heating_oil_conv .430
. brega available 80
. naphthal napha_l_conv -1
. naphthal recipe_2 .2
. naphthai napha_i_conv -1
. naphthai recipe_1 .3
. heatingo heating_oil_conv -1
. heatingo recipe_1 .7
. heatingo recipe_2 .8
. jet_1 profit 300
. jet_1 recipe_1 -1
. jet_2 profit 300
. jet_2 recipe_2 -1
;
proc netflow
sparsecondata
condata=scon2
conout=solutn2;
run;
data vars3;
input _name_ $ profit available;
datalines;
a_heavy -165 165
a_light -175 110
brega -205 80
heatingo 0 .
jet_1 300 .
jet_2 300 .
naphthai 0 .
naphthal 0 .
;
data dcon3;
input _id_ $17.
a_light a_heavy brega naphthal naphthai
heatingo jet_1 jet_2
_type_ $ _rhs_;
datalines;
naphtha_l_conv .035 .030 .045 -1 0 0 0 0 eq 0
naphtha_i_conv .100 .075 .135 0 -1 0 0 0 eq 0
heating_o_conv .390 .300 .430 0 0 -1 0 0 eq 0
recipe_1 0 0 0 0 .3 .7 -1 0 eq 0
recipe_2 0 0 0 .2 0 .8 0 -1 eq 0
;
proc netflow
maximize /* ***** necessary ***** */
arcdata=vars3
condata=dcon3
conout=solutn3;
objfn profit;
upperbd available;
run;
data vars4;
input _name_ $ profit available;
datalines;
a_heavy -165 165
a_light -175 110
brega -205 80
jet_1 300 .
jet_2 300 .
;
data dcon4;
input _id_ $17.
a_light a_heavy brega naphthal naphthai
heatingo jet_1 jet_2;
datalines;
naphtha_l_conv .035 .030 .045 -1 0 0 0 0
naphtha_i_conv .100 .075 .135 0 -1 0 0 0
heating_o_conv .390 .300 .430 0 0 -1 0 0
recipe_1 0 0 0 0 .3 .7 -1 0
recipe_2 0 0 0 .2 0 .8 0 -1
;
proc netflow
maximize defcontype=eq
arcdata=vars3
condata=dcon3
conout=solutn3;
objfn profit;
upperbd available;
run;
data scon5;
format _type_ $8. _col_ $8. _row_ $16. ;
input _type_ $ _col_ $ _row_ $ _coef_;
datalines;
eq . napha_l_conv .
eq . napha_i_conv .
eq . heating_oil_conv .
eq . recipe_1 .
eq . recipe_2 .
. a_light napha_l_conv .035
. a_light napha_i_conv .100
. a_light heating_oil_conv .390
. a_heavy napha_l_conv .030
. a_heavy napha_i_conv .075
. a_heavy heating_oil_conv .300
. brega napha_l_conv .045
. brega napha_i_conv .135
. brega heating_oil_conv .430
. naphthal napha_l_conv -1
. naphthal recipe_2 .2
. naphthai napha_i_conv -1
. naphthai recipe_1 .3
. heatingo heating_oil_conv -1
. heatingo recipe_1 .7
. heatingo recipe_2 .8
. jet_1 recipe_1 -1
. jet_2 recipe_2 -1
;
proc netflow
maximize
sparsecondata
arcdata=vars3 /* or arcdata=vars4 */
condata=scon5
conout=solutn5;
objfn profit;
upperbd available;
run;
data scon6;
input _col_ $ _row_&$16. _coef_;
datalines;
a_light napha_l_conv .035
a_light napha_i_conv .100
a_light heating_oil_conv .390
a_heavy napha_l_conv .030
a_heavy napha_i_conv .075
a_heavy heating_oil_conv .300
brega napha_l_conv .045
brega napha_i_conv .135
brega heating_oil_conv .430
naphthal napha_l_conv -1
naphthal recipe_2 .2
naphthai napha_i_conv -1
naphthai recipe_1 .3
heatingo heating_oil_conv -1
heatingo recipe_1 .7
heatingo recipe_2 .8
jet_1 recipe_1 -1
jet_2 recipe_2 -1
;
proc netflow
maximize
defcontype=eq
sparsecondata
arcdata=vars3 /* or arcdata=vars4 */
condata=scon6
conout=solutn6;
objfn profit;
upperbd available;
run;
/****************************************************************
* *
* Generalized Networks: *
* How to Specify Data for Arc Multipliers *
* *
****************************************************************/
/* All Arc Multiplier Data in the ARCDATA= Data Set */
data nodes;
input _node_ $ _sd_ ;
datalines;
N1 22
N4 -30
N5 -10
;
data arcs;
input _from_ $ _to_ $ _cost_ _mult_;
datalines;
N1 N2 2 4
N1 N3 10 0.5
N2 N4 0 1
N2 N5 7 3
N3 N2 12 2
N3 N5 10 2
N5 N4 55 0.9
;
title1 'The NETFLOW Procedure';
proc netflow
bytes = 100000
nodedata = nodes
arcdata = arcs
conout = solution;
run;
data arcs1b;
input _from_ $ _to_ $ _cost_;
datalines;
N1 N2 2
N1 N3 10
N2 N4 0
N2 N5 7
N3 N2 12
N3 N5 10
N5 N4 55
;
data MUdense;
input _type_ $ N1_N2 N1_N3 N2_N4 N2_N5 N3_N2 N3_N5 N5_N4;
datalines;
mult 4.0 0.5 1.0 0.3 2.0 2.0 0.9
;
proc netflow
gennet
nodedata = nodes
arcdata = arcs1b
condata = MUdense
conout = soln1b;
run;
data MUsparse;
input _type_ $ _col_ $ _coef_;
datalines;
mult N1_N2 4.0
mult N1_N3 0.5
mult N2_N4 1.0
mult N2_N5 0.3
mult N3_N2 2.0
mult N3_N5 2.0
mult N5_N4 0.9
;
proc netflow
gennet sparsecondata
nodedata = nodes
arcdata = arcs1b
condata = MUsparse
conout = soln1c;
run;
data arcs1c;
input _from_ $ _to_ $ _cost_ _mult_;
datalines;
N1 N2 2 4
N1 N3 10 .5
N2 N4 0 .
N2 N5 7 .
N3 N2 12 .
N3 N5 10 .
N5 N4 55 .
;
data MUdense1;
input _type_ $ N2_N4 N2_N5 N3_N2 N3_N5 N5_N4;
datalines;
mult 1.0 0.3 2.0 2.0 0.9
;
/****************************************************************
* *
* Example 1: Shortest Path Problem *
* *
****************************************************************/
title 'Shortest Path Problem';
title2 'How to get Hawaiian Pineapples to a London Restaurant';
data aircost1;
input ffrom&$13. tto&$15. _cost_ ;
datalines;
Honolulu Chicago 105
Honolulu San Francisco 75
Honolulu Los Angeles 68
Chicago Boston 45
Chicago New York 56
San Francisco Boston 71
San Francisco New York 48
San Francisco Atlanta 63
Los Angeles New York 44
Los Angeles Atlanta 57
Boston Heathrow London 88
New York Heathrow London 65
Atlanta Heathrow London 76
;
proc netflow
shortpath
sourcenode=Honolulu
sinknode='Heathrow London' /* Quotes for embedded blank */
ARCDATA=aircost1
arcout=spath;
tail ffrom;
head tto;
run;
proc print data=spath;
sum _fcost_;
run;
/****************************************************************
* *
* Example 2: Minimum Cost Flow Problem *
* *
****************************************************************/
title 'Minimum Cost Flow Problem';
title2 'How to get Hawaiian Pineapples to a London Restaurant';
proc netflow
defcapacity=350
sourcenode='Honolulu'
sinknode='Heathrow London' /* Quotes for embedded blank */
demand=500
arcdata=aircost1
arcout=arcout1
nodeout=nodeout1;
tail ffrom;
head tto;
set future1;
run;
quit;
proc print data=arcout1;sum _fcost_;run;
proc print data=nodeout1;
run;
/****************************************************************
* *
* Example 3: Using a Warm Start *
* *
****************************************************************/
title 'Minimum Cost Flow Problem - Warm Start';
title2 'How to get Hawaiian Pineapples to a London Restaurant';
data aircost2;
set arcout1;
oldcost=_cost_;
oldflow=_flow_;
oldfc=_fcost_;
if ffrom='Chicago' then _cost_=_cost_-30;
proc netflow
warm
arcdata=aircost2
nodedata=nodeout1
arcout=arcout2;
tail ffrom;
head tto;
run;
quit;
proc print data=arcout2;
var ffrom tto _cost_ oldcost _capac_ _lo_
_flow_ oldflow _fcost_ oldfc;
sum _fcost_ oldfc;
run;
/****************************************************************
* *
* Example 4: Production, Inventory, Distribution Problem *
* *
****************************************************************/
title 'Minimum Cost Flow problem';
title2 'Production Planning/Inventory/Distribution';
data node0;
input _node_ $ _supdem_ ;
datalines;
fact1_1 1000
fact2_1 850
fact1_2 1000
fact2_2 1500
shop1_1 -900
shop2_1 -900
shop1_2 -900
shop2_2 -1450
;
data arc0;
input _tail_ $ _head_ $ _cost_ _capac_ _lo_ diagonal factory
key_id $10. mth_made $ _name_&$17. ;
datalines;
fact1_1 f1_mar_1 127.9 500 50 19 1 production March prod f1 19 mar
fact1_1 f1_apr_1 78.6 600 50 19 1 production April prod f1 19 apl
fact1_1 f1_may_1 95.1 400 50 19 1 production May .
f1_mar_1 f1_apr_1 15 50 . 19 1 storage March .
f1_apr_1 f1_may_1 12 50 . 19 1 storage April .
f1_apr_1 f1_mar_1 28 20 . 19 1 backorder April back f1 19 apl
f1_may_1 f1_apr_1 28 20 . 19 1 backorder May back f1 19 may
f1_mar_1 f2_mar_1 11 . . 19 . f1_to_2 March .
f1_apr_1 f2_apr_1 11 . . 19 . f1_to_2 April .
f1_may_1 f2_may_1 16 . . 19 . f1_to_2 May .
f1_mar_1 shop1_1 -327.65 250 . 19 1 sales March .
f1_apr_1 shop1_1 -300 250 . 19 1 sales April .
f1_may_1 shop1_1 -285 250 . 19 1 sales May .
f1_mar_1 shop2_1 -362.74 250 . 19 1 sales March .
f1_apr_1 shop2_1 -300 250 . 19 1 sales April .
f1_may_1 shop2_1 -245 250 . 19 1 sales May .
fact2_1 f2_mar_1 88.0 450 35 19 2 production March prod f2 19 mar
fact2_1 f2_apr_1 62.4 480 35 19 2 production April prod f2 19 apl
fact2_1 f2_may_1 133.8 250 35 19 2 production May .
f2_mar_1 f2_apr_1 18 30 . 19 2 storage March .
f2_apr_1 f2_may_1 20 30 . 19 2 storage April .
f2_apr_1 f2_mar_1 17 15 . 19 2 backorder April back f2 19 apl
f2_may_1 f2_apr_1 25 15 . 19 2 backorder May back f2 19 may
f2_mar_1 f1_mar_1 10 40 . 19 . f2_to_1 March .
f2_apr_1 f1_apr_1 11 40 . 19 . f2_to_1 April .
f2_may_1 f1_may_1 13 40 . 19 . f2_to_1 May .
f2_mar_1 shop1_1 -297.4 250 . 19 2 sales March .
f2_apr_1 shop1_1 -290 250 . 19 2 sales April .
f2_may_1 shop1_1 -292 250 . 19 2 sales May .
f2_mar_1 shop2_1 -272.7 250 . 19 2 sales March .
f2_apr_1 shop2_1 -312 250 . 19 2 sales April .
f2_may_1 shop2_1 -299 250 . 19 2 sales May .
fact1_2 f1_mar_2 217.9 400 40 25 1 production March prod f1 25 mar
fact1_2 f1_apr_2 174.5 550 50 25 1 production April prod f1 25 apl
fact1_2 f1_may_2 133.3 350 40 25 1 production May .
f1_mar_2 f1_apr_2 20 40 . 25 1 storage March .
f1_apr_2 f1_may_2 18 40 . 25 1 storage April .
f1_apr_2 f1_mar_2 32 30 . 25 1 backorder April back f1 25 apl
f1_may_2 f1_apr_2 41 15 . 25 1 backorder May back f1 25 may
f1_mar_2 f2_mar_2 23 . . 25 . f1_to_2 March .
f1_apr_2 f2_apr_2 23 . . 25 . f1_to_2 April .
f1_may_2 f2_may_2 26 . . 25 . f1_to_2 May .
f1_mar_2 shop1_2 -559.76 . . 25 1 sales March .
f1_apr_2 shop1_2 -524.28 . . 25 1 sales April .
f1_may_2 shop1_2 -475.02 . . 25 1 sales May .
f1_mar_2 shop2_2 -623.89 . . 25 1 sales March .
f1_apr_2 shop2_2 -549.68 . . 25 1 sales April .
f1_may_2 shop2_2 -460.00 . . 25 1 sales May .
fact2_2 f2_mar_2 182.0 650 35 25 2 production March prod f2 25 mar
fact2_2 f2_apr_2 196.7 680 35 25 2 production April prod f2 25 apl
fact2_2 f2_may_2 201.4 550 35 25 2 production May .
f2_mar_2 f2_apr_2 28 50 . 25 2 storage March .
f2_apr_2 f2_may_2 38 50 . 25 2 storage April .
f2_apr_2 f2_mar_2 31 15 . 25 2 backorder April back f2 25 apl
f2_may_2 f2_apr_2 54 15 . 25 2 backorder May back f2 25 may
f2_mar_2 f1_mar_2 20 25 . 25 . f2_to_1 March .
f2_apr_2 f1_apr_2 21 25 . 25 . f2_to_1 April .
f2_may_2 f1_may_2 43 25 . 25 . f2_to_1 May .
f2_mar_2 shop1_2 -567.83 500 . 25 2 sales March .
f2_apr_2 shop1_2 -542.19 500 . 25 2 sales April .
f2_may_2 shop1_2 -461.56 500 . 25 2 sales May .
f2_mar_2 shop2_2 -542.83 500 . 25 2 sales March .
f2_apr_2 shop2_2 -559.19 500 . 25 2 sales April .
f2_may_2 shop2_2 -489.06 500 . 25 2 sales May .
;
proc netflow
nodedata=node0
arcdata=arc0;
set future1
nodeout=node2
arcout=arc1;
run;
quit;
options ls=80 ps = 50;
proc print data=arc1 heading=h width=min;
var _tail_ _head_ _cost_ _capac_ _lo_ _name_ _supply_ _demand_ _flow_ _fcost_;
sum _fcost_;
run;
options ls=80 ps = 50;
proc print data=arc1 heading=h width=min;
var _rcost_ _anumb_ _tnumb_ _status_ diagonal factory key_id mth_made;
run;
proc print data=node2;
run;
/****************************************************************
* *
* Example 5: Using an Unconstrained Solution Warm Start *
* *
****************************************************************/
title 'Minimum Cost Flow problem- Unconstrained Warm Start';
title2 'Production Planning/Inventory/Distribution';
data arc2;
set arc1;
oldcost=_cost_;
oldfc=_fcost_;
oldflow=_flow_;
if key_id='backorder'
then _cost_=_cost_*1.2;
else if _tail_='f2_may_2' then _cost_=_cost_-30;
if key_id='production' & mth_made='May' then
if diagonal=19 then _cost_=_cost_-5;
else _cost_=_cost_-20;
proc netflow
warm future1
nodedata=node2
arcdata=arc2
nodeout=node3
arcout=arc3;
run;
quit;
options ls=80 ps = 50;
proc print data=arc3 heading=h width=min;
sum _fcost_;
var _tail_ _head_ _capac_ _lo_ _supply_ _demand_ _name_ _cost_ _flow_ _fcost_;
run;
options ls=80 ps = 50;
proc print data=arc3 heading=h width=min;
sum oldfc;
var oldcost oldflow oldfc diagonal factory key_id mth_made _anumb_ _tnumb_;
run;
proc print data=node3;
run;
/****************************************************************
* *
* Example 6: Adding Side Constraints, Using a Warm Start *
* *
****************************************************************/
title 'Adding Side Constraints and Using a Warm Start';
title2 'Production Planning/Inventory/Distribution';
data con3;
input _column_ &$14. _row_ &$15. _coef_ ;
datalines;
prod f1 19 mar FACT1 MAR GIZMO 3
prod f1 25 mar FACT1 MAR GIZMO 4
CHIP/BO LIMIT FACT1 MAR GIZMO 2600
prod f2 19 mar FACT2 MAR GIZMO 3
prod f2 25 mar FACT2 MAR GIZMO 4
CHIP/BO LIMIT FACT2 MAR GIZMO 3750
prod f1 19 apl FACT1 APL GIZMO 3
prod f1 25 apl FACT1 APL GIZMO 4
CHIP/BO LIMIT FACT1 APL GIZMO 2600
prod f2 19 apl FACT2 APL GIZMO 3
prod f2 25 apl FACT2 APL GIZMO 4
CHIP/BO LIMIT FACT2 APL GIZMO 3750
back f1 19 apl TOTAL BACKORDER 1
back f1 25 apl TOTAL BACKORDER 1
back f2 19 apl TOTAL BACKORDER 1
back f2 25 apl TOTAL BACKORDER 1
back f1 19 may TOTAL BACKORDER 1
back f1 25 may TOTAL BACKORDER 1
back f2 19 may TOTAL BACKORDER 1
back f2 25 may TOTAL BACKORDER 1
CHIP/BO LIMIT TOTAL BACKORDER 50
;
proc netflow
nodedata=node3 arcdata=arc3 warm
condata=con3 sparsecondata rhsobs='CHIP/BO LIMIT'
future2 dualout=dual4 conout=con4;
id diagonal factory key_id mth_made;
run;
quit;
proc print data=con4 heading=h width=min;
sum _fcost_;
var _tail_ _head_ _cost_ _capac_ _lo_ _name_ _supply_ _demand_ _flow_ _fcost_;
run;
proc print data=con4 heading=h width=min;
var _rcost_ _anumb_ _tnumb_ _status_ diagonal factory key_id mth_made;
run;
proc print data=dual4;
run;
/****************************************************************
* *
* Example 7: Using a Constrained Solution Warm Start *
* *
****************************************************************/
title 'Using a Constrained Solution Warm Start';
title2 'Production Planning/Inventory/Distribution';
data new_con4;
set con4;
oldcost=_cost_;
oldflow=_flow_;
oldfc=_fcost_;
if _tail_='f1_may_2'
& (_head_='shop1_2' | _head_='shop2_2')
then _cost_=_cost_-40;
run;
proc netflow
warm
arcdata=new_con4
dualin=dual4
condata=con3
sparsecondata
rhsobs='CHIP/BO LIMIT'
dualout=dual5
conout=con5;
run;
quit;
proc print data=con5 heading=h width=min;
sum _fcost_;
var _tail_ _head_ _capac_ _lo_ _supply_ _demand_ _name_ _cost_ _flow_ _fcost_;
run;
proc print data=con5 heading=h width=min;
sum oldfc;
var oldcost oldflow oldfc diagonal factory key_id mth_made _anumb_ _tnumb_;
run;
proc print data=dual5;
run;
/****************************************************************
* *
* Example 8: Nonarc Variables in the Side Constraints *
* *
****************************************************************/
title 'Nonarc Variables in the Side Constraints';
title2 'Production Planning/Inventory/Distribution';
data con6;
input _column_ &$17. _row_ &$15. _coef_ ;
datalines;
prod f1 19 mar FACT1 MAR GIZMO 3
prod f1 25 mar FACT1 MAR GIZMO 4
f1 unused chips FACT1 MAR GIZMO 1
_RHS_ FACT1 MAR GIZMO 2615
prod f2 19 mar FACT2 MAR GIZMO 3
prod f2 25 mar FACT2 MAR GIZMO 4
f2 unused chips FACT2 MAR GIZMO 1
_RHS_ FACT2 MAR GIZMO 3750
prod f1 19 apl FACT1 APL GIZMO 3
prod f1 25 apl FACT1 APL GIZMO 4
f1 chips from mar FACT1 APL GIZMO -1
_RHS_ FACT1 APL GIZMO 2600
prod f2 19 apl FACT2 APL GIZMO 3
prod f2 25 apl FACT2 APL GIZMO 4
f2 chips from mar FACT2 APL GIZMO -1
_RHS_ FACT2 APL GIZMO 3750
f1 unused chips CHIP LEFTOVER 1
f2 unused chips CHIP LEFTOVER 1
f1 chips from mar CHIP LEFTOVER -1
f2 chips from mar CHIP LEFTOVER -1
_TYPE_ CHIP LEFTOVER 1
back f1 19 apl TOTAL BACKORDER 1
back f1 25 apl TOTAL BACKORDER 1
back f2 19 apl TOTAL BACKORDER 1
back f2 25 apl TOTAL BACKORDER 1
back f1 19 may TOTAL BACKORDER 1
back f1 25 may TOTAL BACKORDER 1
back f2 19 may TOTAL BACKORDER 1
back f2 25 may TOTAL BACKORDER 1
_TYPE_ TOTAL BACKORDER -1
_RHS_ TOTAL BACKORDER 50
;
data arc6;
set con5;
drop oldcost oldfc oldflow _flow_ _fcost_ _status_ _rcost_;
data arc6_b;
length key_id $10;
input _name_ &$17. _cost_ _capac_ factory key_id $ ;
datalines;
f1 unused chips . . 1 chips
f2 unused chips . . 2 chips
f1 chips from mar 1 150 1 chips
f2 chips from mar 1 150 2 chips
;
proc append force nowarn
base=arc6 data=arc6_b;
run;
proc netflow
nodedata=node0 arcdata=arc6
condata=con6 defcontype=eq sparsecondata
dualout=dual7 conout=con7;
run;
print nonarcs/short;
title 'Nonarc Variables in the Side Constraints';
title2 'Production Planning/Inventory/Distribution';
options ls=80 ps = 50;
proc print data=con7 heading=h width=min;
sum _fcost_;
var _tail_ _head_ _cost_ _capac_ _lo_ _name_ _supply_ _demand_ _flow_ _fcost_;
run;
options ls=80 ps = 50;
proc print data=con7 heading=h width=min;
var _rcost_ _anumb_ _tnumb_ _status_ diagonal factory key_id mth_made;
run;
options ls=80 ps = 50;
title 'Nonarc Variables in the Side Constraints';
title2 'Production Planning/Inventory/Distribution';
proc print data=dual7;
run;
/****************************************************************
* *
* Example 9: Pure Networks: Using the EXCESS= Option *
* *
****************************************************************/
data parcs;
input _from_ $ _to_ $ _cost_;
datalines;
s1 d1 1
s1 d2 8
s2 d1 4
s2 d2 2
;
data SleD;
input _node_ $ _sd_;
datalines;
s1 1
s2 10
d1 -10
d2 -5
;
title1 'The NETFLOW Procedure';
proc netflow
excess = slacks
arcdata = parcs
nodedata = SleD
conout = solex1;
run;
title1 'The NETFLOW Procedure';
proc netflow
thrunet
excess = slacks
arcdata = parcs
nodedata = SleD
conout = solex1t;
run;
data node_missingD1;
input _node_ $ _sd_;
missing D;
datalines;
s1 1
s2 10
d1 D
d2 -1
;
title1 'The NETFLOW Procedure';
proc netflow
excess = slacks
arcdata = parcs
nodedata = node_missingD1
conout = solex1b;
run;
title1 'The NETFLOW Procedure';
proc netflow
thrunet
excess = slacks
arcdata = parcs
nodedata = node_missingD1
conout = solex1c;
run;
/****************************************************************
* *
* Example 10: Maximum Flow Problem *
* *
****************************************************************/
data arcs;
input _from_ $ _to_ $ _cost_ _capac_;
datalines;
S a . .
S b . .
a c 1 7
b c 2 9
a d 3 5
b d 4 8
c e 5 15
d f 6 20
e g 7 11
f g 8 6
e h 9 12
f h 10 4
g T . .
h T . .
;
title1 'The NETFLOW Procedure';
proc netflow
intpoint
maxflow
excess = arcs
arcdata = arcs
source = S sink = T
conout = gout3;
run;
title1 'The NETFLOW Procedure';
proc netflow
intpoint
excess = slacks
arcdata = arcs
source = S sink = T
maxflow
conout = gout3b;
run;
/****************************************************************
* *
* Example 11: Generalized Networks: Using the EXCESS= Option *
* *
****************************************************************/
data garcs;
input _from_ $ _to_ $ _cost_ _mult_;
datalines;
s1 d1 1 .
s1 d2 8 .
s2 d1 4 2
s2 d2 2 2
s2 d3 1 2
s3 d2 5 0.5
s3 d3 4 0.5
;
data gnodes;
input _node_ $ _sd_ ;
datalines;
s1 5
s2 20
s3 10
d1 -5
d2 -10
d3 -20
;
title1 'The NETFLOW Procedure';
proc netflow
arcdata = garcs
nodedata = gnodes
excess = supply
conout = gnetout;
run;
data garcs1;
input _from_ $ _to_ $ _cost_ _mult_;
datalines;
s1 d1 1 0.5
s1 d2 8 0.5
s2 d1 4 .
s2 d2 2 .
s2 d3 1 .
s3 d2 5 0.5
s3 d3 4 0.5
;
title1 'The NETFLOW Procedure';
proc netflow
arcdata = garcs1
nodedata = gnodes
excess = demand
conout = gnetout1;
run;
/****************************************************************
* *
* Example 12: Generalized Networks: Maximum Flow Problem *
* *
****************************************************************/
data garcsM;
input _from_ $ _to_ $ _upper_ _mult_;
datalines;
A B 2 .
A C 2 .
C B 1 .
B D 1 .
C D 2 .
C E 1 3
D E 1 2
E F 5 .
D F 2 .
;
title1 'The NETFLOW Procedure';
proc netflow
arcdata = garcsM
maxflow
source = A sink = F
conout = gmfpout;
run;
/****************************************************************
* *
* Example 13: Machine Loading Problem *
* *
****************************************************************/
data mlarcs;
input _from_ $ _to_ $ _cost_ _mult_;
datalines;
P1 M1 4 .
P1 M2 3 2
P1 M3 3 2
P1 M4 1 3
P2 M1 .5 2
P2 M2 2 3
P2 M3 .5 2
P2 M4 3 1
P3 M1 2 3
P3 M2 5 .
P3 M3 1 2
P3 M4 .5 4
;
data mlnodes;
input _node_ $ _sd_;
datalines;
P1 10
P2 5
P3 10
M1 -40
M2 -40
M3 -50
M4 -50
;
title1 'The NETFLOW Procedure';
proc netflow
excess = demand
arcdata = mlarcs
nodedata = mlnodes
conout = mlsol;
run;
/****************************************************************
* *
* Example 14: Generalized Networks: Distribution Problem *
* *
****************************************************************/
data dnodes;
input _node_ $ _sd_ ;
missing S D;
datalines;
S1 700
S2 0
S3 200
D1 -200
D2 -300
D3 -200
D4 -150
D5 100
Y S
Z D
;
data darcs;
input _from_ $ _to_ $ _cost_ _capac_ _mult_;
datalines;
S1 D1 3 200 0.95
S1 D2 3 200 0.95
S1 D3 6 200 0.95
S1 D4 7 200 0.95
S2 D1 7 200 0.95
S2 D2 2 200 0.95
S2 D4 5 200 0.95
S3 D2 6 200 0.95
S3 D4 4 200 0.95
S3 D5 7 200 0.95
D4 D3 4 200 0.95
Y S2 10 300 .
Y S3 14 100 .
S1 Z -5 700 .
D2 Z -20 100 .
D3 Z -20 100 .
D5 Z -25 250 .
;
title1 'The NETFLOW Procedure';
proc netflow
nodedata = dnodes
arcdata = darcs
conout = dsol;
run;
/****************************************************************
* *
* Example 15: Converting to an MPS-Format SAS Data Set *
* *
****************************************************************/
data exdata;
input x1 x2 x3 _type_ $ _rhs_;
datalines;
2 -3 -4 min .
. -2 -3 >= -5
1 1 2 <= 6
1 2 3 >= 7
10 15 20 upperbd .
;
/* convert to MPS format */
proc netflow condata=exdata mpsout=mpsdata bytes=100000;
run;
/****************************************************************
* *
* Example 16: Migration to OPTMODEL: Generalized Networks *
* *
****************************************************************/
title 'Generalized Networks';
data garcs;
input _from_ $ _to_ $ _cost_ _mult_;
datalines;
s1 d1 1 .
s1 d2 8 .
s2 d1 4 2
s2 d2 2 2
s2 d3 1 2
s3 d2 5 0.5
s3 d3 4 0.5
;
data gnodes;
input _node_ $ _sd_ ;
datalines;
s1 5
s2 20
s3 10
d1 -5
d2 -10
d3 -20
;
proc optmodel;
set <str> NODES;
num _sd_ {NODES} init 0;
read data gnodes into NODES=[_node_] _sd_;
set <str,str> ARCS;
num _lo_ {ARCS} init 0;
num _capac_ {ARCS} init .;
num _cost_ {ARCS};
num _mult_ {ARCS} init 1;
read data garcs nomiss into ARCS=[_from_ _to_] _cost_ _mult_;
NODES = NODES union (union {<i,j> in ARCS} {i,j});
var Flow {<i,j> in ARCS} >= _lo_[i,j];
min obj = sum {<i,j> in ARCS} _cost_[i,j] * Flow[i,j];
con balance {i in NODES}: sum {<(i),j> in ARCS} Flow[i,j]
- sum {<j,(i)> in ARCS} _mult_[j,i] * Flow[j,i] = _sd_[i];
num infinity = min {r in {}} r;
/* change equality constraint to le constraint for supply nodes */
for {i in NODES: _sd_[i] > 0} balance[i].lb = -infinity;
solve;
num _supply_ {<i,j> in ARCS} = (if _sd_[i] ne 0 then _sd_[i] else .);
num _demand_ {<i,j> in ARCS} = (if _sd_[j] ne 0 then -_sd_[j] else .);
num _fcost_ {<i,j> in ARCS} = _cost_[i,j] * Flow[i,j].sol;
create data gnetout from [_from_ _to_]
_cost_ _capac_ _lo_ _mult_ _supply_ _demand_ _flow_=Flow _fcost_;
quit;
proc print data=gnetout;
run;
data garcs1;
input _from_ $ _to_ $ _cost_ _mult_;
datalines;
s1 d1 1 0.5
s1 d2 8 0.5
s2 d1 4 .
s2 d2 2 .
s2 d3 1 .
s3 d2 5 0.5
s3 d3 4 0.5
;
proc optmodel;
set <str> NODES;
num _sd_ {NODES} init 0;
read data gnodes into NODES=[_node_] _sd_;
set <str,str> ARCS;
num _lo_ {ARCS} init 0;
num _capac_ {ARCS} init .;
num _cost_ {ARCS};
num _mult_ {ARCS} init 1;
read data garcs1 nomiss into ARCS=[_from_ _to_] _cost_ _mult_;
NODES = NODES union (union {<i,j> in ARCS} {i,j});
var Flow {<i,j> in ARCS} >= _lo_[i,j];
for {<i,j> in ARCS: _capac_[i,j] ne .} Flow[i,j].ub = _capac_[i,j];
min obj = sum {<i,j> in ARCS} _cost_[i,j] * Flow[i,j];
con balance {i in NODES}: sum {<(i),j> in ARCS} Flow[i,j]
- sum {<j,(i)> in ARCS} _mult_[j,i] * Flow[j,i] = _sd_[i];
num infinity = min {r in {}} r;
/* change equality constraint to ge constraint */
for {i in NODES: _sd_[i] < 0} balance[i].ub = infinity;
solve;
num _supply_ {<i,j> in ARCS} = (if _sd_[i] ne 0 then _sd_[i] else .);
num _demand_ {<i,j> in ARCS} = (if _sd_[j] ne 0 then -_sd_[j] else .);
num _fcost_ {<i,j> in ARCS} = _cost_[i,j] * Flow[i,j].sol;
create data gnetout1 from [_from_ _to_]
_cost_ _capac_ _lo_ _mult_ _supply_ _demand_ _flow_=Flow _fcost_;
quit;
proc print data=gnetout1;
run;
/****************************************************************
* *
* Example 17: Migration to OPTMODEL: Maximum Flow *
* *
****************************************************************/
title 'Maximum Flow Problem';
data arcs;
input _from_ $ _to_ $ _cost_ _capac_;
datalines;
S a . .
S b . .
a c 1 7
b c 2 9
a d 3 5
b d 4 8
c e 5 15
d f 6 20
e g 7 11
f g 8 6
e h 9 12
f h 10 4
g T . .
h T . .
;
proc optmodel;
str source = 'S';
str sink = 'T';
set <str> NODES;
num _supdem_ {i in NODES} = (if i in {source, sink} then . else 0);
set <str,str> ARCS;
num _lo_ {ARCS} init 0;
num _capac_ {ARCS} init .;
num _cost_ {ARCS} init 0;
read data arcs nomiss into ARCS=[_from_ _to_] _cost_ _capac_;
NODES = (union {<i,j> in ARCS} {i,j});
var Flow {<i,j> in ARCS} >= _lo_[i,j];
for {<i,j> in ARCS: _capac_[i,j] ne .} Flow[i,j].ub = _capac_[i,j];
max obj = sum {<i,j> in ARCS: j = sink} Flow[i,j];
con balance {i in NODES diff {source, sink}}:
sum {<(i),j> in ARCS} Flow[i,j]
- sum {<j,(i)> in ARCS} Flow[j,i] = _supdem_[i];
solve;
num _supply_ {<i,j> in ARCS} =
(if _supdem_[i] ne 0 then _supdem_[i] else .);
num _demand_ {<i,j> in ARCS} =
(if _supdem_[j] ne 0 then -_supdem_[j] else .);
num _fcost_ {<i,j> in ARCS} = _cost_[i,j] * Flow[i,j].sol;
create data gout3 from [_from_ _to_]
_cost_ _capac_ _lo_ _supply_ _demand_ _flow_=Flow _fcost_;
quit;
proc print data=gout3;
run;
/****************************************************************
* *
* Example 18: Migration to OPTMODEL: Production, Inventory, *
* Distribution *
* *
****************************************************************/
title 'Minimum Cost Flow Problem';
title2 'Production Planning/Inventory/Distribution';
data node0;
input _node_ $ _supdem_ ;
datalines;
fact1_1 1000
fact2_1 850
fact1_2 1000
fact2_2 1500
shop1_1 -900
shop2_1 -900
shop1_2 -900
shop2_2 -1450
;
data arc0;
input _tail_ $ _head_ $ _cost_ _capac_ _lo_
diagonal factory key_id $10. mth_made $ _name_&$17.;
datalines;
fact1_1 f1_mar_1 127.9 500 50 19 1 production March prod f1 19 mar
fact1_1 f1_apr_1 78.6 600 50 19 1 production April prod f1 19 apl
fact1_1 f1_may_1 95.1 400 50 19 1 production May .
f1_mar_1 f1_apr_1 15 50 . 19 1 storage March .
f1_apr_1 f1_may_1 12 50 . 19 1 storage April .
f1_apr_1 f1_mar_1 28 20 . 19 1 backorder April back f1 19 apl
f1_may_1 f1_apr_1 28 20 . 19 1 backorder May back f1 19 may
f1_mar_1 f2_mar_1 11 . . 19 . f1_to_2 March .
f1_apr_1 f2_apr_1 11 . . 19 . f1_to_2 April .
f1_may_1 f2_may_1 16 . . 19 . f1_to_2 May .
f1_mar_1 shop1_1 -327.65 250 . 19 1 sales March .
f1_apr_1 shop1_1 -300 250 . 19 1 sales April .
f1_may_1 shop1_1 -285 250 . 19 1 sales May .
f1_mar_1 shop2_1 -362.74 250 . 19 1 sales March .
f1_apr_1 shop2_1 -300 250 . 19 1 sales April .
f1_may_1 shop2_1 -245 250 . 19 1 sales May .
fact2_1 f2_mar_1 88.0 450 35 19 2 production March prod f2 19 mar
fact2_1 f2_apr_1 62.4 480 35 19 2 production April prod f2 19 apl
fact2_1 f2_may_1 133.8 250 35 19 2 production May .
f2_mar_1 f2_apr_1 18 30 . 19 2 storage March .
f2_apr_1 f2_may_1 20 30 . 19 2 storage April .
f2_apr_1 f2_mar_1 17 15 . 19 2 backorder April back f2 19 apl
f2_may_1 f2_apr_1 25 15 . 19 2 backorder May back f2 19 may
f2_mar_1 f1_mar_1 10 40 . 19 . f2_to_1 March .
f2_apr_1 f1_apr_1 11 40 . 19 . f2_to_1 April .
f2_may_1 f1_may_1 13 40 . 19 . f2_to_1 May .
f2_mar_1 shop1_1 -297.4 250 . 19 2 sales March .
f2_apr_1 shop1_1 -290 250 . 19 2 sales April .
f2_may_1 shop1_1 -292 250 . 19 2 sales May .
f2_mar_1 shop2_1 -272.7 250 . 19 2 sales March .
f2_apr_1 shop2_1 -312 250 . 19 2 sales April .
f2_may_1 shop2_1 -299 250 . 19 2 sales May .
fact1_2 f1_mar_2 217.9 400 40 25 1 production March prod f1 25 mar
fact1_2 f1_apr_2 174.5 550 50 25 1 production April prod f1 25 apl
fact1_2 f1_may_2 133.3 350 40 25 1 production May .
f1_mar_2 f1_apr_2 20 40 . 25 1 storage March .
f1_apr_2 f1_may_2 18 40 . 25 1 storage April .
f1_apr_2 f1_mar_2 32 30 . 25 1 backorder April back f1 25 apl
f1_may_2 f1_apr_2 41 15 . 25 1 backorder May back f1 25 may
f1_mar_2 f2_mar_2 23 . . 25 . f1_to_2 March .
f1_apr_2 f2_apr_2 23 . . 25 . f1_to_2 April .
f1_may_2 f2_may_2 26 . . 25 . f1_to_2 May .
f1_mar_2 shop1_2 -559.76 . . 25 1 sales March .
f1_apr_2 shop1_2 -524.28 . . 25 1 sales April .
f1_may_2 shop1_2 -475.02 . . 25 1 sales May .
f1_mar_2 shop2_2 -623.89 . . 25 1 sales March .
f1_apr_2 shop2_2 -549.68 . . 25 1 sales April .
f1_may_2 shop2_2 -460.00 . . 25 1 sales May .
fact2_2 f2_mar_2 182.0 650 35 25 2 production March prod f2 25 mar
fact2_2 f2_apr_2 196.7 680 35 25 2 production April prod f2 25 apl
fact2_2 f2_may_2 201.4 550 35 25 2 production May .
f2_mar_2 f2_apr_2 28 50 . 25 2 storage March .
f2_apr_2 f2_may_2 38 50 . 25 2 storage April .
f2_apr_2 f2_mar_2 31 15 . 25 2 backorder April back f2 25 apl
f2_may_2 f2_apr_2 54 15 . 25 2 backorder May back f2 25 may
f2_mar_2 f1_mar_2 20 25 . 25 . f2_to_1 March .
f2_apr_2 f1_apr_2 21 25 . 25 . f2_to_1 April .
f2_may_2 f1_may_2 43 25 . 25 . f2_to_1 May .
f2_mar_2 shop1_2 -567.83 500 . 25 2 sales March .
f2_apr_2 shop1_2 -542.19 500 . 25 2 sales April .
f2_may_2 shop1_2 -461.56 500 . 25 2 sales May .
f2_mar_2 shop2_2 -542.83 500 . 25 2 sales March .
f2_apr_2 shop2_2 -559.19 500 . 25 2 sales April .
f2_may_2 shop2_2 -489.06 500 . 25 2 sales May .
;
proc optmodel;
set <str> NODES;
num _supdem_ {NODES} init 0;
read data node0 into NODES=[_node_] _supdem_;
set <str,str> ARCS;
num _lo_ {ARCS} init 0;
num _capac_ {ARCS} init .;
num _cost_ {ARCS};
num diagonal {ARCS};
num factory {ARCS};
str key_id {ARCS};
str mth_made {ARCS};
str _name_ {ARCS};
read data arc0 nomiss into ARCS=[_tail_ _head_] _lo_ _capac_ _cost_
diagonal factory key_id mth_made _name_;
NODES = NODES union (union {<i,j> in ARCS} {i,j});
var Flow {<i,j> in ARCS} >= _lo_[i,j];
for {<i,j> in ARCS: _capac_[i,j] ne .} Flow[i,j].ub = _capac_[i,j];
min obj = sum {<i,j> in ARCS} _cost_[i,j] * Flow[i,j];
con balance {i in NODES}:
sum {<(i),j> in ARCS} Flow[i,j]
- sum {<j,(i)> in ARCS} Flow[j,i] = _supdem_[i];
num infinity = min {r in {}} r;
num excess = sum {i in NODES} _supdem_[i];
if (excess > 0) then do;
/* change equality constraint to le constraint for supply nodes */
for {i in NODES: _supdem_[i] > 0} balance[i].lb = -infinity;
end;
else if (excess < 0) then do;
/* change equality constraint to ge constraint for demand nodes */
for {i in NODES: _supdem_[i] < 0} balance[i].ub = infinity;
end;
solve;
num _supply_ {<i,j> in ARCS} =
(if _supdem_[i] ne 0 then _supdem_[i] else .);
num _demand_ {<i,j> in ARCS} =
(if _supdem_[j] ne 0 then -_supdem_[j] else .);
num _fcost_ {<i,j> in ARCS} = _cost_[i,j] * Flow[i,j].sol;
create data arc1 from [_tail_ _head_]
_cost_ _capac_ _lo_ _name_ _supply_ _demand_ _flow_=Flow _fcost_
_rcost_ =
(if Flow[_tail_,_head_].rc ne 0 then Flow[_tail_,_head_].rc else .)
_status_ = Flow.status diagonal factory key_id mth_made;
create data node2 from [_node_]
_supdem_ = (if _supdem_[_node_] ne 0 then _supdem_[_node_] else .)
_dual_ = balance.dual;
quit;
options ls=80 ps=54;
proc print data=arc1 heading=h width=min;
var _tail_ _head_ _cost_ _capac_ _lo_ _name_
_supply_ _demand_ _flow_ _fcost_;
sum _fcost_;
run;
proc print data=arc1 heading=h width=min;
var _rcost_ _status_ diagonal factory key_id mth_made;
run;
proc print data=node2;
run;
/****************************************************************
* *
* Example 19: Migration to OPTMODEL: Shortest Path *
* *
****************************************************************/
title 'Shortest Path Problem';
title2 'How to get Hawaiian Pineapples to a London Restaurant';
data aircost1;
input ffrom&$13. tto&$15. _cost_;
datalines;
Honolulu Chicago 105
Honolulu San Francisco 75
Honolulu Los Angeles 68
Chicago Boston 45
Chicago New York 56
San Francisco Boston 71
San Francisco New York 48
San Francisco Atlanta 63
Los Angeles New York 44
Los Angeles Atlanta 57
Boston Heathrow London 88
New York Heathrow London 65
Atlanta Heathrow London 76
;
proc optmodel;
str sourcenode = 'Honolulu';
str sinknode = 'Heathrow London';
set <str> NODES;
num _supdem_ {i in NODES} = (if i = sourcenode then 1
else if i = sinknode then -1 else 0);
set <str,str> ARCS;
num _lo_ {ARCS} init 0;
num _capac_ {ARCS} init .;
num _cost_ {ARCS};
read data aircost1 into ARCS=[ffrom tto] _cost_;
NODES = (union {<i,j> in ARCS} {i,j});
var Flow {<i,j> in ARCS} >= _lo_[i,j];
min obj = sum {<i,j> in ARCS} _cost_[i,j] * Flow[i,j];
con balance {i in NODES}: sum {<(i),j> in ARCS} Flow[i,j]
- sum {<j,(i)> in ARCS} Flow[j,i] = _supdem_[i];
solve;
num _supply_ {<i,j> in ARCS} =
(if _supdem_[i] ne 0 then _supdem_[i] else .);
num _demand_ {<i,j> in ARCS} =
(if _supdem_[j] ne 0 then -_supdem_[j] else .);
num _fcost_ {<i,j> in ARCS} = _cost_[i,j] * Flow[i,j].sol;
create data spath from [ffrom tto]
_cost_ _capac_ _lo_ _supply_ _demand_ _flow_=Flow _fcost_
_rcost_ = (if Flow[ffrom,tto].rc ne 0 then Flow[ffrom,tto].rc else .)
_status_ = Flow.status;
quit;
proc print data=spath;
sum _fcost_;
run;