Hi Rob I am trying to solve this problem. I have used sparse modeling approach based on your recommendation an year ago to reduce the number of variables. Basically I have like 20 ports from which goods are produced. 608 final destinations. In between these ports and DC are ICs that are 15 in number. There is a production cost that is indexed over ports. There is an outbound cost that is indexed over IC and DC. I am trying to solve for minimizing the total cost = production + outbound, thereby picking which ICs it should flow. I have some constraints as to how much quantity can be produced at each port. and how much flow in terms of Kgs and Units can traverse via IC. Specifically, i have a constraint saying, the total Kgs and Units flowing via any IC with O suffix(indicates ocean) can be only x% of total kgs and wt. Similarly for FTL, LTL and Parcel there is a cut off. eg. Parcel is any shipment (a shipment is defined as a flow from Ports to IC to DC) shd not be more than 75 kgs. this seems to be working fine. FTL it needs to be atleast 3K kgs and LTL shd be between 75 and 3K Kgs. Another thing that I should tell is that there is a binary variable called LogicalValue that is indexed over Ports, IC and DC. There are like 20x15x608= 182,400 combinations out of which, almost 97% of that is 0. I have only 5,514 out of 182,400 values of that variable that are really valid for consideration. I have created a set as below to reduce set PortstoICtoDC_SET = {p in Ports, c in IC, d in DC: LogicalValue[p,c,d] > 0}; I have my code along with. The IC is structured in a way that the last letter of it tells the actual mode (A for air, P for parcel, F for Fulltruckload, L for Lessthantruckload and O for Ocean. The model seems to be solving. My questions are (a) I am not sure why the model does not pick any FTL or LTL mode for any lane. It chooses ocean, air and parcel. As an experiment, I tried to close out Air so that the model can play between FTL, LTL , Ocean and Parcel. The model becomes infeasible. So I am not sure if I am doing something wrong about it here. (b) Am i missing/ overlooking something in the code apart from this? (c) Lastly, in the create data step, can i cull out the last digit from IC to get the Unique mode. I tried to do right and substring but it did not work. appreciate your help. proc optmodel;
set<str> DC; /* this is a set of DCs*/
set<str> Ports;
set IC={'BUD_A','BUD_O','BUD_F','BUD_L','BUD_P','MTY_A','MTY_O','MTY_F','MTY_L','MTY_P','HKG_A','HKG_O','HKG_F','HKG_L','HKG_P'};
set UniqueMode={'A','O','F','L','P'};
/*read data into the DC*/
read data STDOPT.PN11299_Destcode into DC=[dest_code];
read data STDOPT.PN11299_Origincode into Ports=[Origin_Code];
num Units {DC};
num Kgs {DC};
NUM BigMKgs;
NUM BigMUnits;
read data STDOPT.PN11299_BigM into BigMKgs=Kgs;
read data STDOPT.PN11299_BigM into BigMUnits=Units;
read data STDOPT.PN11299 into [dest_code] Units=Units;
read data STDOPT.PN11299 into [dest_code] Kgs=Kgs;
/* declare Constants*/
num MinQty_IC=0;
num MinKgs_IC=0;
num Max_Per_at_IC_Ocean=0.1;
num FTL_Max = 3000;
num MTY_SY_MaxQty=5000000;
num BUD_SY_MaxQty=5000000;
num HKG_SY_MaxQty=5000000;
num MTY_RA_MaxQty=5000000;
num BUD_RA_MaxQty=5000000;
num HKG_RA_MaxQty=5000000;
var Build {IC} binary;
var BuildUniqueMode{UniqueMode} binary;
/*Declaring an Array of Costs - THIS IS INPUT data */
num Production_Cost {Ports};
read data STDOPT.PN11299_PRODUCTION_COST into [Origin_Code] Production_Cost=Inbound_Rate;
num OutboundLinehaul {IC,DC}; /*This is an array of OutboundLinehaul Costs indexed over IC and DC*/
/*read data into the OutboundLinehaul parameter*/
read data STDOPT.PN11299_RATEOUTBOUND into [mot1 Dest_Code] OutboundLinehaul=Outbound_Rate;
num LogicalValue {Ports,IC,DC}; /*This is an array of OutboundLinehaul Costs indexed over IC and DC*/
read data STDOPT.PN11299_PortsICDC into [Origin_code mot1 Dest_Code]LogicalValue=LogicalValue;
set PortstoICtoDC_SET = {p in Ports, c in IC, d in DC: LogicalValue[p,c,d] > 0};
/*set KgsfromPortstoICtoDC_SET = {p in Ports, c in IC, d in DC: LogicalValue[p,c,d] > 0};*/
/*set IsIC_SET = {c in IC: LogicalValue[c] > 0};*/
/* Declaring an Array of Decision Variables*/
var UnitsfromPortstoICtoDC {PortstoICtoDC_SET}>=0;
var KgsfromPortstoICtoDC {PortstoICtoDC_SET}>=0;
/* Binary Variables */
var IsIC {IC} binary;
var IsPortsIC {Ports,IC} binary;
var ISPortsDC {Ports,DC} binary;
var IsPortsICDC {Ports,IC,DC} binary;
/*var UnitsfromPortstoICtoDC {Ports,IC,DC}>=0;
var KgsfromPortstoICtoDC {Ports,IC,DC}>=0;*/
/*Declaring Implicit Variables*/
impvar UnitsatIC{c in IC}=sum{<p,(c),d> in PortstoICtoDC_SET} UnitsfromPortstoICtoDC [p,c,d];
/*Print UnitsatIC;*/
impvar KgsatIC{c in IC}=sum{<p,(c),d> in PortstoICtoDC_SET} KgsfromPortstoICtoDC [p,c,d];
impvar Production_Costs=sum{<p,c,d> in PortstoICtoDC_SET} Production_Cost [p] * UnitsfromPortstoICtoDC[p,c,d];
impvar Outbound_Linehaul_Costs = sum {<p,c,d> in PortstoICtoDC_SET} OutboundLinehaul [c,d] * KgsfromPortstoICtoDC [p,c,d];
/* declare Objective Function*/
Min TotalCost = Production_Costs+Outbound_Linehaul_Costs;
/* declare General Constraints for units*/
con Min_Qty_at_IC_is_Respected {c in IC}:
sum{<p,(c),d> in PortstoICtoDC_SET} UnitsfromPortstoICtoDC [p,c,d]>=MinQty_IC*IsIC[c];
/*expand Min_Qty_at_IC_is_Respected;*/
con Link_Units_Kgs {p in Ports, d in DC}:
sum{<(p),c,(d)> in PortstoICtoDC_SET} UnitsfromPortstoICtoDC [p,c,d]=Units[d]*ISPortsDC[p,d];
con UnitsFlows_from_Ports_to_DC_Modelequals_FlowFromPortstoDC_inInputData {d in DC}:
sum {<p,c,(d)> in PortstoICtoDC_SET} UnitsfromPortstoICtoDC[p, c, d] = Units[d]; /*the flow from p to d that goes through ALL ICs*/
con BigM_Units {c in IC,d in DC}: UnitsatIC[c] <= BigMUnits*IsIC[c];
con MakeSure_RightFlowsHappen_Units{<p,c,d> in PortstoICtoDC_SET}:
UnitsfromPortstoICtoDC[p,c,d] <= BigMUnits*IsPortsICDC[p,c,d]; /*All binary variables with 0 IsPortsIC will be taken care here */
/* declare General Constraints for Kgs*/
con Min_Kgs_at_IC_is_Respected {c in IC}:
sum{<p,(c),d> in PortstoICtoDC_SET} KgsfromPortstoICtoDC [p,c,d]>=MinKgs_IC*IsIC[c];
con Link_Kgs_Units {p in Ports, d in DC}:
sum{<(p),c,(d)> in PortstoICtoDC_SET} KgsfromPortstoICtoDC [p,c,d]=Kgs[d]*ISPortsDC[p,d];
con KgsFlows_from_Ports_to_DC_Modelequals_FlowFromPortstoDC_inInputData {d in DC}:
sum {<p,c,(d)> in PortstoICtoDC_SET} KgsfromPortstoICtoDC[p, c, d] =Kgs[d]; /*the flow from p to d that goes through ALL ICs*/
con BigM_Kgs {c in IC,d in DC}: KgsatIC[c] <= BigMKgs*IsIC[c];
con MakeSure_RightFlowsHappen_Kgs{<p,c,d> in PortstoICtoDC_SET}:
KgsfromPortstoICtoDC[p,c,d] <= BigMKgs* IsPortsICDC[p,c,d]; /*All binary variables with 0 IsPortsIC will be taken care here */
/* Restricting Ocean to only x% of Weight */
con OceanMaxKgs{u in {'O'},c in {'BUD_O','MTY_O','HKG_O'}, d in DC}: sum{<p,(c),(d)> in PortstoICtoDC_SET} KgsfromPortstoICtoDC [p,c,d]
<=BuildUniqueMode['O']*Kgs[d]*Max_Per_at_IC_Ocean;
/* Expand OceanMaxKgs; */
/* Restricting Ocean to only x% of Units */
con OceanMaxUnits{u in {'O'},c in {'BUD_O','MTY_O','HKG_O'},d in DC}: sum{<p,(c),(d)> in PortstoICtoDC_SET} UnitsfromPortstoICtoDC [p,c,d]
<=BuildUniqueMode['O']*Units[d]*Max_Per_at_IC_Ocean;
/* Restricting FTL to Min 3000 Kg of Weight */
con FTLMinKgs {c in {'BUD_F','MTY_F','HKG_F'}, d in DC}:
sum{<p,(c),(d)> in PortstoICtoDC_SET} KgsfromPortstoICtoDC [p,c,d]>=3001*IsIC[c];
con LTLMaxKgs {c in {'BUD_L','MTY_L','HKG_L'}, d in DC}:
sum{<p,(c),(d)> in PortstoICtoDC_SET} KgsfromPortstoICtoDC [p,c,d]<=3000*IsIC[c];
con LTLMinKgs {c in {'BUD_L','MTY_L','HKG_L'}, d in DC}:
sum{<p,(c),(d)> in PortstoICtoDC_SET} KgsfromPortstoICtoDC [p,c,d]>=75*IsIC[c];
con ParcelMaxKgs {c in {'BUD_P','MTY_P','HKG_P'}, d in DC}:
sum{<p,(c),(d)> in PortstoICtoDC_SET} KgsfromPortstoICtoDC [p,c,d]<=75*IsIC[c];
/* Restricting Production Capacities */
con ProductionMTYSY{p in ports: p in {'MTY_SY_3','MTY_SY_2'}} :
sum{<(p),c,d> in PortstoICtoDC_SET} UnitsfromPortstoICtoDC[p,c,d]<=MTY_SY_MaxQty;
con ProductionBUDSY{p in ports: p in {'BUD_SY_3','BUD_SY_2'}} :
sum{<(p),c,d> in PortstoICtoDC_SET} UnitsfromPortstoICtoDC[p,c,d]<=BUD_SY_MaxQty;
con ProductionHKGSY{p in ports: p in {'HKG_SY_3','HKG_SY_2'}} :
sum{<(p),c,d> in PortstoICtoDC_SET} UnitsfromPortstoICtoDC[p,c,d]<=HKG_SY_MaxQty;
con ProductionMTYRA{p in ports: p in {'MTY_RA_3'}} :
sum{<(p),c,d> in PortstoICtoDC_SET} UnitsfromPortstoICtoDC[p,c,d]<=MTY_RA_MaxQty;
con ProductionBUDRA{p in ports: p in {'BUD_RA_3'}} :
sum{<(p),c,d> in PortstoICtoDC_SET} UnitsfromPortstoICtoDC[p,c,d]<=BUD_RA_MaxQty;
con ProductionHKGRA{p in ports: p in {'HKG_RA_3'}} :
sum{<(p),c,d> in PortstoICtoDC_SET} UnitsfromPortstoICtoDC[p,c,d]<=HKG_RA_MaxQty;
solve with milp / allcuts=aggressive;
/*Outputs*/
create data STDOPT.PN11299_Output (where=(OhWeightChrg > 0.0000001)) from
[Ports=p IC=c DC=d]
ScenarioName='PN11299-Alt1'
OhWeightChrg=KgsfromPortstoICtoDC
Percentage = Kgs[d]
Units= Units[d]
Production_Cost = Production_Cost[p]
Production_Costs=(Production_Cost [p] * SUM(UnitsfromPortstoICtoDC[p,c,d]))
Outbound_Linehaul_Costs = (OutboundLinehaul [c,d] * sum (KgsfromPortstoICtoDC [p,c,d]))
;
... View more