Hi Rob I am building some layers on top of this model . The model referenced in the link below, will get the cheapest way to ship from Point A to Point B respecting the weight and volume of boxes available for that lane. It would factor in the costs and make the minimal cost decision. You had helped me to tune the constraints. Now the new problem I am trying to solve is this. I am not sure if I have formulated it correct. I am looking for suggestions and I can change my model to behave the way I wanted it to behave. The one thing that I can right away think is to cut the number of possibilities by grouping similar charge buckets with same rate basis. Eg. Charge type A, charge type B all have a Volume based calculation. So i can just club all those and put a one aggregated number so that the problem size is small and solve time is faster. Anyways, here is the problem I want to solve: This is a ocean movement in this example. There are some origins (Point A, Shanghai in our example) and destinations (Point B, Atlanta in our example) generally. In my example, there is only one origin and one destination. For this origin port, there are many vendors in Shanghai area. There are two different Method of Loading (CFS and CYS). The logic is that any vendor can send to CFS or CYS. There is a node called T1 which is just the day number of an year and T2 which is the week number of that year. Specific rules to use CFS and CYS are below. For using CYS: This is like each vendor taking a full container to their factory and loading all their stuff in it and sending to CYS from where it goes to Atlanta. This will be daily, meaning, each vendor, at the end of that day, if he can send all his goods by himself in this CYS, he can send. Next day he can take another container(s) and sends to Atlanta via this CYS option. In other words, if a vendor goes to CYS method, then only his stuff is there in the container and no other vendors' stuff gets contaminated in his container. It is like an exclusive/dedicated container only for that vendor and only for that day's load. For CFS: If a vendor is not able to send via CYS daily (because it may be expensive to ship so little on a day) , then he has an option of consolidating his goods with other such vendors, and so, many such vendors go to a CFS, which is like a consolidation center. However at this CFS, the goods are consolidated for 1 week. At the end of week 1, all the vendors stuff are consolidated at CFS and sent finally to Atlanta. In other words, we will just consolidate across a week (T2) for CFS . For CYS, consolidation is at T1 level (day) and for CFS it is weekly (T2 level). I am trying to decide, if a vendor can send all his stuff to CYS daily or if it is not feasible , he can send to CFS to be consolidated with other vendors for the week and then sent. I want to see for a given week, which vendor should send via CYS (daily) and which vendors go to CFS (weekly), obviously those who cannot do CYS their only other option is to get consolidated at CFS and send. Here is my code. The CFSSpecific constraint is the one that are not right but CYSSpecific may be right, i am not sure. Appreciate your support. Have attached data as well. Am I missing something else? The rates are the same for a lane for a given ratetype and MOL. But I have it set up for all the combinations of dates and weeks in the data. Not sure if it is efficient way as well. proc optmodel;
set <str> ORG;
read data CASUSER.Unique_ORG into ORG = [ORG];
set <str> DES;
read data CASUSER.Unique_DES into DES = [DES];
set <str> BOX;
read data CASUSER.Unique_BOX into BOX = [BOX];
set <str> MOL;
read data CASUSER.Unique_MOL into MOL = [MOL];
set <str> T1;
read data CASUSER.Unique_T1 into T1 = [T1];
set <str> T2;
read data CASUSER.Unique_T2 into T2 = [T2];
/*Read ISN Wt and Volume for a given ISN* - START */
set <str> ISN;
str Org_ISN {ISN};
str Des_ISN {ISN};
num Volume_ISN {ISN} init 0;
num Weight_ISN {ISN} init 0;
read data CASUSER.InputData_AssetMix into ISN=[ISN] Org_ISN=ORG Des_ISN=DES Volume_ISN=Volume Weight_ISN=Weight;
/*Read ISN Wt and Volume for a given ISN* - END*/
/*Read Wt and Volume Capacity for a given ORG, DES, BOX - START */
num Volume_Capacity {ORG,DES,BOX,MOL,T1,T2} init 0; num Volume_Min {ORG,DES,BOX,MOL,T1,T2} init 0;
num Weight_Capacity {ORG,DES,BOX,MOL,T1,T2} init 0; num Weight_Min {ORG,DES,BOX,MOL,T1,T2} init 0;
read data CASUSER.BOXSPECS into [ORG DES BOX MOL T1 T2]
Volume_Capacity=Volume_Capacity
Weight_Capacity=Weight_Capacity
Volume_Min=Volume_Min
Weight_Min=Weight_Min;
/*Read Wt and Volume Capacity for a given ORG, DES, BOX - END */
/* A Binary variable 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,MOL,T1,T2};
read data CASUSER.BOXSpecs into [ORG Des Box Mol T1 T2] Is_BoxAvalable_for_a_lane = BoxAvailability;
/* Decision Variable and Associated Impvars - START */
var BoxesNeeded {ISN,BOX,MOL,T1,T2} >= 0 integer;
var Proportion {ISN,BOX,MOL,T1,T2} >= 0 <= 1;
impvar VolumeInsideBox {i in ISN, b in BOX,m in MOL,d in T1,w in T2} = Volume_ISN[i] * Proportion[i,b,m,d,w];
impvar WeightInsideBox {i in ISN, b in BOX,m in MOL,d in T1,w in T2} = Weight_ISN[i] * Proportion[i,b,m,d,w];
NUM BigM;
READ DATA CASUSER.BigM INTO BigM=Volume;
/* var Is_MOL {MOL} binary; */
var Is_ISN_MOL {ISN,MOL} binary;
/* Decision Variable and Associated Impvars - END */
/* Define Rates and Implicit Variables - START */
set <str,str,str,str,str,str> PerBox_Based_Rate_NoZeroes;
num PerBox_Based_Rate {PerBox_Based_Rate_NoZeroes};
read data CASUSER.BOXRATE
(where=(RateBasis="PerBox" and Ratetype='Linehaul' and Rate>0))
into PerBox_Based_Rate_NoZeroes=[ORG DES BOX MOL T1 T2] PerBox_Based_Rate=Rate;
impvar PerBox_Based_Costs = sum {i in ISN, b in BOX,m in MOL,d in T1,w in T2: <Org_ISN[i],Des_ISN[i],b,m,d,w> in PerBox_Based_Rate_NoZeroes}
PerBox_Based_Rate[Org_ISN[i],Des_ISN[i],b,m,d,w] * BoxesNeeded[i,b,m,d,w];
set <str,str,str,str,str,str> PerVol_Based_Rate_NoZeroes_Carrier_BOL;
num PerVol_Based_Rate_Carrier_BOL {PerVol_Based_Rate_NoZeroes_Carrier_BOL};
read data CASUSER.BOXRATE
(where=(RateBasis="PerVolUOM" and Ratetype='Carrier_BOL' and Rate>0))
into PerVol_Based_Rate_NoZeroes_Carrier_BOL=[ORG DES MOL BOX T1 T2] PerVol_Based_Rate_Carrier_BOL=Rate;
impvar PerVol_Based_Costs_Carrier_BOL = sum {i in ISN, b in BOX, m in MOL,d in T1,w in T2: <Org_ISN[i],Des_ISN[i],b,m,d,w> in PerVol_Based_Rate_NoZeroes_Carrier_BOL}
PerVol_Based_Rate_Carrier_BOL[Org_ISN[i],Des_ISN[i],b,m,d,w] * VolumeInsideBox[i,b,m,d,w];
set <str,str,str,str,str,str> PerShp_Based_Rate_NoZeroes_Entry;
num PerShp_Based_Rate_Entry {PerShp_Based_Rate_NoZeroes_Entry};
read data CASUSER.BOXRATE
(where=(RateBasis="PerShipment" and Ratetype='Export_Declaration' and Rate>0))
into PerShp_Based_Rate_NoZeroes_Entry=[ORG DES BOX MOL T1 T2] PerShp_Based_Rate_Entry=Rate;
impvar PerShp_Based_Costs_Entry = sum {i in ISN, b in BOX,m in MOL,d in T1,w in T2: <Org_ISN[i],Des_ISN[i],b,m,d,w> in PerShp_Based_Rate_NoZeroes_Entry}
PerShp_Based_Rate_Entry[Org_ISN[i],Des_ISN[i],b,m,d,w];
/* impvar BoxesNeededatMOL{m in MOL}=sum{i in ISN,b in BOX} BoxesNeeded [i,b,m]; */
/*Define Implicit Variables - END */
Min TotalCost = PerBox_Based_Costs + PerVol_Based_Costs_Carrier_BOL+PerShp_Based_Costs_Entry;
/* Constraints - START */
for {i in ISN, b in BOX,m in MOL,d in T1,w in T2: Is_BoxAvalable_for_a_lane[Org_ISN[i],Des_ISN[i],b,m,d,w] = 0}
fix BoxesNeeded[i,b,m,d,w] = 0;
con SumProportionToOne {i in ISN}:
sum {b in BOX,m in MOL,d in T1,w in T2} Proportion[i,b,m,d,w] = 1;
con OneMOL{i in ISN}:
sum{M in MOL} Is_ISN_MOL[i,m] = 1;
con CYSSpecific {m in {'CYS'},i in ISN}:
sum {b in BOX,d in T1,w in T2} VolumeInsideBox[i,b,'CYS',d,w]= Volume_ISN[i]*Is_ISN_MOL[i,'CYS'];
con CFSSpecific {m in {'CFS'},w in T2}:
sum {i in ISN, b in BOX, d in T1} VolumeInsideBox[i,b,'CFS',d,w]= sum{i in ISN} Volume_ISN[i]*Is_ISN_MOL[i,'CFS'];
expand CFSSpecific; /* I want to sum volume of all ISNs in a given week only across all box types but I know it is not right */
/* The following constraints are for determining type and number of boxes and the associated wt and volume constraints */
con Volume_Constraint {i in ISN, b in BOX, m in MOL}:
Volume_Capacity[Org_ISN[i],Des_ISN[i],b,m] * BoxesNeeded[i,b,m] >= VolumeInsideBox[i,b,m];
con Volume_Constraint_MinThreshold {i in ISN, b in BOX, m in MOL}:
Volume_Min[Org_ISN[i],Des_ISN[i],b,m] * BoxesNeeded[i,b,m] <= VolumeInsideBox[i,b,m];
con Weight_Constraint {i in ISN, b in BOX, m in MOL}:
Weight_Capacity[Org_ISN[i],Des_ISN[i],b,m] * BoxesNeeded[i,b,m] >= WeightInsideBox[i,b,m];
con Weight_Constraint_MinThreshold {i in ISN, b in BOX, m in MOL}:
Weight_Min[Org_ISN[i],Des_ISN[i],b,m] * BoxesNeeded[i,b,m] <= WeightInsideBox[i,b,m];
/* Constraints - END */
solve with milp / decomp=(method=concomp);
... View more