The following code captures the business problem I think you want to solve, and I tried to keep things close to what you had already tried:
data Unique_ORG;
input ORG $;
datalines;
SHA
;
data Unique_DES;
input DES $;
datalines;
LAX
SEA
;
data Unique_BOX;
input BOX $;
datalines;
LCL
20F
40F
40H
45F
;
data InputData_AssetMix;
input ORG $ DES $ ISN $11. Volume Weight;
datalines;
SHA LAX SHA_LAX_123 32 15000
SHA LAX SHA_LAX_456 49 16000
SHA SEA SHA_SEA_789 2 4000
SHA SEA SHA_SEA_722 55 30000
;
data BOXSpecs;
input Org $ Des $ Box $ BoxAvailability Volume_Capacity Wt_Cap Volume_UOM $ Weight_UOM $;
datalines;
SHA LAX LCL 0 14 10000 CBM Kgs
SHA LAX 20F 1 30 14000 CBM Kgs
SHA LAX 40F 1 56 29000 CBM Kgs
SHA LAX 40H 1 65 35000 CBM Kgs
SHA LAX 45F 1 72 55000 CBM Kgs
SHA SEA LCL 1 17 10000 CBM Kgs
SHA SEA 20F 0 29 14000 CBM Kgs
SHA SEA 40F 1 60 29000 CBM Kgs
SHA SEA 40H 1 69 35000 CBM Kgs
SHA SEA 45F 1 75 55000 CBM Kgs
;
data BOXRATE;
input Org $ Des $ Box $ Ratetype $ Rate RateBasis $9.;
datalines;
SHA LAX LCL Linehaul 57.14285714 PerVolUOM
SHA LAX 20F Linehaul 800 PerBox
SHA LAX 40F Linehaul 1000 PerBox
SHA LAX 40H Linehaul 1100 PerBox
SHA LAX 45F Linehaul 1320 PerBox
SHA SEA LCL Linehaul 62.85714286 PerVolUOM
SHA SEA 20F Linehaul 880 PerBox
SHA SEA 40F Linehaul 1100 PerBox
SHA SEA 40H Linehaul 1210 PerBox
SHA SEA 45F Linehaul 1320 PerBox
;
proc optmodel;
set <str> ORG;
read data Unique_ORG into ORG=[ORG];
set <str> DES;
read data Unique_DES into DES=[DES];
set <str> BOX;
read data Unique_BOX into BOX=[BOX];
/* A Binary parameter that is 0 or 1 for a given asset for a given lane, 0 indicated not available, 1- available */
num Is_BoxAvalable_for_a_lane {ORG,DES,Box};
read data BOXSpecs into [ORG Des Box] Is_BoxAvalable_for_a_lane=BoxAvailability;
/* RATES */
num PerBox_Based_Rate {ORG,DES,BOX} init 0;
read data BOXRATE(where=(RateBasis="PerBox" and Ratetype='Linehaul')) into [ORG DES BOX] PerBox_Based_Rate=Rate;
print PerBox_Based_Rate;
/* End of Rates */
/* Input Dims */
set <str> ISN;
str Org_ISN {ISN};
str Des_ISN {ISN};
num Vol_ISN {ISN} init 0;
num Wt_ISN {ISN} init 0;
read data InputData_AssetMix into ISN=[ISN] Org_ISN=ORG Des_ISN=DES Vol_ISN=Volume Wt_ISN=Weight;
/* End of Input Dims */
/* Start Vol and Wt Capacity for Boxes */
num Vol_Capacity {ORG,DES,BOX};
num Wt_Capacity {ORG,DES,BOX};
read data BOXSPECS into [ORG DES BOX] Vol_Capacity=Volume_Capacity Wt_Capacity=Wt_Cap;
/* End of Vol and Wt Capacity for Boxes */
/* Decision Variable */
var BoxesNeeded {ISN, BOX} >= 0 integer;
/* Define Implicit Variables */
impvar PerBox_Based_Costs = sum {i in ISN, b in BOX} PerBox_Based_Rate[Org_ISN[i],Des_ISN[i],b] * BoxesNeeded[i,b];
/* Objective */
Min TotalCost = PerBox_Based_Costs;
/* Constraints */
for {i in ISN, b in BOX: Is_BoxAvalable_for_a_lane[Org_ISN[i],Des_ISN[i],b] = 0}
fix BoxesNeeded[i,b] = 0;
con Vol_Constraint {i in ISN}:
sum {b in BOX} Vol_Capacity[Org_ISN[i],Des_ISN[i],b] * BoxesNeeded[i,b] >= Vol_ISN[i];
con Wt_Constraint {i in ISN}:
sum {b in BOX} Wt_Capacity[Org_ISN[i],Des_ISN[i],b] * BoxesNeeded[i,b] >= Wt_ISN[i];
/* call MILP solver */
solve;
/* print optimal solution */
print BoxesNeeded;
quit;
Instead of declaring variables and then fixing some of them to 0, an alternative approach would be to use a sparse index set, say ISN_BOX, as illustrated in this Sparse Modeling example.
Note also that your problem completely decomposes by ISN into four independent problems. In such cases, you should consider using DECOMP, COFOR, or runOptmodel groupBy to exploit this structure.
... View more