Car Rental 2 (mpex26)
/***************************************************************/
/* */
/* S A S S A M P L E L I B R A R Y */
/* */
/* NAME: mpex26 */
/* TITLE: Car Rental 2 (mpex26) */
/* PRODUCT: OR */
/* SYSTEM: ALL */
/* KEYS: OR */
/* PROCS: OPTMODEL */
/* DATA: */
/* */
/* SUPPORT: UPDATE: */
/* REF: */
/* MISC: Example 26 from the Mathematical Programming */
/* Examples book. */
/* */
/***************************************************************/
data depot_data;
input depot $10.;
datalines;
Glasgow
Manchester
Birmingham
Plymouth
;
data demand_data;
input day $10. Glasgow Manchester Birmingham Plymouth;
datalines;
Monday 100 250 95 160
Tuesday 150 143 195 99
Wednesday 135 80 242 55
Thursday 83 225 111 96
Friday 120 210 70 115
Saturday 230 98 124 80
;
data length_data;
input length prob cost price_same price_diff;
datalines;
1 0.55 20 50 70
2 0.20 25 70 100
3 0.25 30 120 150
;
data transition_prob_data;
input i $10. Glasgow Manchester Birmingham Plymouth;
datalines;
Glasgow 60 20 10 10
Manchester 15 55 25 5
Birmingham 15 20 54 11
Plymouth 8 12 27 53
;
data transfer_cost_data;
input i $10. Glasgow Manchester Birmingham Plymouth;
datalines;
Glasgow . 20 30 50
Manchester 20 . 15 35
Birmingham 30 15 . 25
Plymouth 50 35 25 .
;
data repair_data;
input depot $10. repair_capacity;
datalines;
Manchester 12
Birmingham 20
;
%let opportunity_cost_per_week = 15;
%let transfer_length = 1;
%let repair_length = 1;
%let damage_prob = 0.10;
%let damage_charge = 100;
%let saturday_discount = 20;
/* missing expansion_prerequisite indicates no prerequisite */
data expansion_data;
input expansion expansion_depot $10. expansion_amount expansion_cost
expansion_prerequisite;
datalines;
1 Birmingham 5 18000 .
2 Birmingham 5 8000 1
3 Manchester 5 20000 .
4 Manchester 5 5000 3
5 Plymouth 5 19000 .
;
%let max_num_expansions = 3;
proc optmodel;
set <str> DEPOTS;
read data depot_data into DEPOTS=[depot];
set DAYS;
str day_name {DAYS};
num demand {DEPOTS, DAYS};
read data demand_data into DAYS=[_N_];
num num_days = card(DAYS);
DAYS = 0..num_days-1;
read data demand_data into [_N_]
{depot in DEPOTS} <demand[depot,_N_-1]=col(depot)>;
set LENGTHS;
num length_prob {LENGTHS};
num cost {LENGTHS};
num price_same {LENGTHS};
num price_diff {LENGTHS};
read data length_data into LENGTHS=[length]
length_prob=prob cost price_same price_diff;
num transition_prob {DEPOTS, DEPOTS};
read data transition_prob_data into [i]
{j in DEPOTS} <transition_prob[i,j]=col(j)>;
for {i in DEPOTS, j in DEPOTS}
transition_prob[i,j] = transition_prob[i,j] / 100;
num transfer_cost {DEPOTS, DEPOTS} init 0;
read data transfer_cost_data nomiss into [i]
{j in DEPOTS} <transfer_cost[i,j]=col(j)>;
num repair_capacity {DEPOTS} init 0;
read data repair_data into [depot] repair_capacity;
num rental_price {i in DEPOTS, j in DEPOTS, day in DAYS, length in LENGTHS} =
(if i = j then price_same[length] else price_diff[length])
- (if day = 5 and length = 1 then &saturday_discount);
num max_length = max {length in LENGTHS} length;
num mod {s in -max_length..num_days+max_length} = mod(s+num_days,num_days);
var NumCars >= 0;
var NumUndamagedCarsStart {DEPOTS, DAYS} >= 0;
var NumDamagedCarsStart {DEPOTS, DAYS} >= 0;
var NumCarsRented_i_day {i in DEPOTS, day in DAYS} >= 0 <= demand[i,day];
impvar NumCarsRented
{i in DEPOTS, j in DEPOTS, day in DAYS, length in LENGTHS} =
transition_prob[i,j] * length_prob[length] * NumCarsRented_i_day[i,day];
var NumUndamagedCarsIdle {DEPOTS, DAYS} >= 0;
var NumDamagedCarsIdle {DEPOTS, DAYS} >= 0;
var NumUndamagedCarsTransferred {i in DEPOTS, DEPOTS diff {i}, DAYS} >= 0;
var NumDamagedCarsTransferred {i in DEPOTS, DEPOTS diff {i}, DAYS} >= 0;
impvar NumCarsTransferred {i in DEPOTS, j in DEPOTS diff {i}, day in DAYS} =
NumUndamagedCarsTransferred[i,j,day]
+ NumDamagedCarsTransferred[i,j,day];
var NumDamagedCarsRepaired {i in DEPOTS, DAYS} >= 0 <= repair_capacity[i];
max Profit =
sum {i in DEPOTS, j in DEPOTS, day in DAYS, length in LENGTHS}
(rental_price[i,j,day,length] - cost[length])
* NumCarsRented[i,j,day,length]
+ sum {i in DEPOTS, day in DAYS}
&damage_prob * &damage_charge * NumCarsRented_i_day[i,day]
- sum {i in DEPOTS, j in DEPOTS diff {i}, day in DAYS}
transfer_cost[i,j] * NumCarsTransferred[i,j,day]
- &opportunity_cost_per_week * NumCars;
con Undamaged_Inflow_con {i in DEPOTS, day in DAYS}:
NumUndamagedCarsStart[i,day]
= (1 - &damage_prob) * sum {j in DEPOTS, length in LENGTHS}
NumCarsRented[j,i,mod[day-length],length]
+ sum {j in DEPOTS diff {i}}
NumUndamagedCarsTransferred[j,i,mod[day-&transfer_length]]
+ NumDamagedCarsRepaired[i,mod[day-&repair_length]]
+ NumUndamagedCarsIdle[i,mod[day-1]];
con Damaged_Inflow_con {i in DEPOTS, day in DAYS}:
NumDamagedCarsStart[i,day]
= &damage_prob * sum {j in DEPOTS, length in LENGTHS}
NumCarsRented[j,i,mod[day-length],length]
+ sum {j in DEPOTS diff {i}}
NumDamagedCarsTransferred[j,i,mod[day-&transfer_length]]
+ NumDamagedCarsIdle[i,mod[day-1]];
con Undamaged_Outflow_con {i in DEPOTS, day in DAYS}:
NumUndamagedCarsStart[i,day]
= NumCarsRented_i_day[i,day]
+ sum {j in DEPOTS diff {i}} NumUndamagedCarsTransferred[i,j,day]
+ NumUndamagedCarsIdle[i,day];
con Damaged_Outflow_con {i in DEPOTS, day in DAYS}:
NumDamagedCarsStart[i,day]
= NumDamagedCarsRepaired[i,day]
+ sum {j in DEPOTS diff {i}} NumDamagedCarsTransferred[i,j,day]
+ NumDamagedCarsIdle[i,day];
con NumCars_con:
NumCars = sum {i in DEPOTS} (
length_prob[3] * NumCarsRented_i_day[i,0]
+ sum {length in 2..3} length_prob[length] * NumCarsRented_i_day[i,1]
+ NumUndamagedCarsStart[i,2]
+ NumDamagedCarsStart[i,2]);
set EXPANSIONS;
str expansion_depot {EXPANSIONS};
num expansion_amount {EXPANSIONS};
num expansion_cost {EXPANSIONS};
num expansion_prerequisite {EXPANSIONS};
read data expansion_data into EXPANSIONS=[expansion]
expansion_depot expansion_amount expansion_cost expansion_prerequisite;
var ExpandCapacity {EXPANSIONS} binary;
for {expansion in EXPANSIONS, day in DAYS}
NumDamagedCarsRepaired[expansion_depot[expansion],day].ub =
constant('BIG');
con Expansion_con {i in DEPOTS, day in DAYS}:
NumDamagedCarsRepaired[i,day]
<= repair_capacity[i]
+ sum {expansion in EXPANSIONS: expansion_depot[expansion] = i}
expansion_amount[expansion] * ExpandCapacity[expansion];
con ExpansionPrerequisite_con {expansion in EXPANSIONS:
expansion_prerequisite[expansion] ne .}:
ExpandCapacity[expansion]
<= ExpandCapacity[expansion_prerequisite[expansion]];
con Cardinality:
sum {expansion in EXPANSIONS} ExpandCapacity[expansion]
<= &max_num_expansions;
max Profit2 = Profit -
sum {expansion in EXPANSIONS}
expansion_cost[expansion] * ExpandCapacity[expansion];
solve;
for {j in 1.._NVAR_} _VAR_[j] = round(_VAR_[j].sol);
print expansion_depot ExpandCapacity;
print NumDamagedCarsRepaired;
print NumCars;
quit;