BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Santha
Pyrite | Level 9

num Min_Qty_at_IC=2500;

var Build {IC} binary;

var ContainersfromPortstoICtoDC {Ports,IC,DC}>=0;

con All_ICs_are_Used {c in IC} : sum{p in Ports, d in DC} ContainersfromPortstoICtoDC [p,c,d]>=Min_Qty_at_IC*Build[c];

 

I have a bunch of Ports (index by p), IC (indexed by c) and DC (indexed by d). The demand from Ports to DC is fixed. It is the number of ICs (x out of 19 total ICs, x is the answer) and which ones are the result of my model. There is a constraint that if an IC is open, it needs to have atleast 2,500 units flow through them. I ran the model. Model ran but this constraint is not being obeyed correctly as I see that there are some IC that are open but with flows less than 2,500. I am not sure what I am missing.

 

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
RobPratt
SAS Super FREQ

You have declared binary variables but then call the LP solver.  Just use SOLVE (or SOLVE WITH MILP) instead of SOLVE WITH LP.

View solution in original post

11 REPLIES 11
Santha
Pyrite | Level 9

There are some IC with 0 flows. thats ok. that means it is closed. But if any IC is open, it shd have atleast 2,500 that is the minimum

RobPratt
SAS Super FREQ

Your model enforces the logical implication:

if Build[c] = 1 then sum{p in Ports, d in DC} ContainersfromPortstoICtoDC[p,c,d] >= Min_Qty_at_IC.

 

But you also need ("big-M") constraints to enforce the following:

if ContainersfromPortstoICtoDC[p,c,d] > 0 then Build[c] = 1.

Santha
Pyrite | Level 9

I do have the Big M constraint. Sorry I did not add to the earlier message. Here it is.

con CheckIC {c in IC}: ContainersatIC[c] <= 15000*Build[c]

 

Big M in my case is the total flows plus little more rounded up to 15000. 

 

impvar ContainersatIC{c in IC}=sum{p in Ports, d in DC} ContainersfromPortstoICtoDC [p,c,d];

RobPratt
SAS Super FREQ

I don't immediately see anything wrong.  Please post the full code, including data.

Santha
Pyrite | Level 9

Hi Rob

Thank you. Here is my full code. I am not able to send the data as it contains price information. However, the data read is good and the data is clean. I have verified that part.

 

proc optmodel;

/* Declare Ports, ICs and DCs */
set<str> Ports;/* this is a set of Ports*/
set<str> DC; /* this is a set of ICs*/
set<str> IC; /* this is a set of DCs*/

 

/* declare Constants*/
num Min_Qty_at_IC=2500;
num Inbound_Fuel_Per_Container=10;
num Drayage_Fuel=2.8;/* This is a Percentage Based Charge*/
**num NumberofICsopen = x;

 

/* Delcare Variables for the Scenario involving many ICs and chosen IC to have >2,500 FEU */

var Build {IC} binary;  /*If C is selected, then it is 1, else 0 */

 

/*Declaring an Array of Costs - THIS IS INPUT data */
num InboundLinehaul {Ports,IC}; /* This is an array of InboundLinehaul Costs indexed over Ports and IC*/
num OutboundLinehaul {IC,DC}; /*This is an array of OutboundLinehaul Costs indexed over IC and DC*/
num Outbound_Fuel{IC,DC}; /* This is an array of Outbound Fuel Cost Per Mil;e indexed over IC and DC*/
num TransloadCost {IC};/*This is an array of Transload Costs at IC*/
num DrayageCost {IC};/*This is an array of Drayage Costs at IC*/
num PierPassCost {IC};/*This is an array of PierPass Costs at IC*/
num MilesBetweenIC_DC {IC,DC}; /*This is an array of Miles between IC and DC indexed over IC and DC */


/* Declaring an Array of Decision Variables*/

var ContainersfromPortstoICtoDC {Ports,IC,DC}>=0;


/*Declaring Implicit Variables*/
impvar ContainersatIC{c in IC}=sum{p in Ports, d in DC} ContainersfromPortstoICtoDC [p,c,d];

impvar Inbound_Linehaul_Costs= sum {p in Ports, c in IC, d in DC} InboundLinehaul [p,c] *ContainersfromPortstoICtoDC [p,c,d];
impvar Inbound_Fuel_Costs=Inbound_Fuel_Per_Container*sum {p in Ports, c in IC, d in DC} ContainersfromPortstoICtoDC [p,c,d];

impvar Outbound_Linehaul_Costs = sum {p in Ports, c in IC, d in DC} OutboundLinehaul [c,d] * ContainersfromPortstoICtoDC [p,c,d];
impvar Outbound_Fuel_Costs = sum{c in IC, d in DC} Outbound_Fuel[c,d]*MilesBetweenIC_DC[c,d];

impvar Transloading_Costs = sum{p in Ports, c in IC, d in DC} ContainersfromPortstoICtoDC[p,c,d]*TransloadCost[c];
impvar Drayage_Costs =sum{p in Ports, c in IC, d in DC} ContainersfromPortstoICtoDC [p,c,d]*DrayageCost[c];
impvar Drayage_Fuel_Costs=Drayage_Fuel*sum{p in Ports, c in IC, d in DC} ContainersfromPortstoICtoDC [p,c,d]*DrayageCost[c];
impvar PierPass_Costs=sum{p in Ports, c in IC, d in DC} ContainersfromPortstoICtoDC[p,c,d]*PierPassCost[c];

 

/* declare Objective Function*/
Min TotalCost = Inbound_Linehaul_Costs+Inbound_Fuel_Costs+Outbound_Linehaul_Costs+Outbound_Fuel_Costs+Transloading_Costs+Drayage_Costs+Drayage_Fuel_Costs+PierPass_Costs;

 

/* declare Constraints*/

con All_ICs_are_Used{c in IC} :
sum{p in Ports, d in DC} ContainersfromPortstoICtoDC [p,c,d]>=Min_Qty_at_IC*Build[c];

 

con Flows_from_Ports_to_DC_Modelequals_FlowFromPortstoDC_inInputData {p in Ports, d in DC}:
sum {c in IC} ContainersfromPortstoICtoDC[p, c, d] = Containers [p,d]; /*the flow from p to d that goes through ALL ICs*/

 

con CheckIC {c in IC}: ContainersatIC[c] <= 15000*Build[c];/*15000 is the Big M- Have it as the sum demandfrom the data*/
**con HaveAtleastTheseManyICsopen: Sum{c in IC} Build [c] =NumberofICsopen;

 

**expand;
solve with lp;

 

/*Outputs*/
print ContainersfromPortstoICtoDC;
print ContainersatIC;
print TotalCost;
print Inbound_Linehaul_Costs;
print Inbound_Fuel_Costs;
print Outbound_Linehaul_Costs;
print Outbound_Fuel_Costs;
print Transloading_Costs;
print Drayage_Costs;
print Drayage_Fuel_Costs;
print PierPass_Costs;

RobPratt
SAS Super FREQ

You have declared binary variables but then call the LP solver.  Just use SOLVE (or SOLVE WITH MILP) instead of SOLVE WITH LP.

Santha
Pyrite | Level 9

Rob.

Thank you. That did it.  Too bad that I did not catch this.  Thank you for your time again.

 

Santha
Pyrite | Level 9

Hi rob. I have one last associated question.

how do i print a variable only when observation is >0? I tried this.

print Public.ContainersfromPortstoICtoDC; This prints everything. I want only when the value is not zero.

 

Proc print data=Public.ContainersfromPortstoICtoDC where ContainersfromPortstoICtoDC >0;? This was not successful.

RobPratt
SAS Super FREQ

To do this in PROC OPTMODEL, see this example.

 

For PROC PRINT, the correct syntax is:

Proc print data=Public.ContainersfromPortstoICtoDC(where=(ContainersfromPortstoICtoDC >0);
run;
Santha
Pyrite | Level 9

HI rob

I tried that but got an error that Public.ContainersfromPortstoICtoDC does not exist.

"ContainersfromPortstoICtoDC" is an implicit variable that I have declared. So I am not sure of the right syntax.

 

Santha
Pyrite | Level 9

Hi. 

I am trying to see my various cost buckets. For example, if i want to see my Inbound_Linehaul_Costs (that is an implicit variable in the model) by different lanes (lanes are Ports-IC combinations), how do i do that? Can you help me with that. My model succesfully solved. I just dont know how to extract the relevant outputs.

 

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

Multiple Linear Regression in SAS

Learn how to run multiple linear regression models with and without interactions, presented by SAS user Alex Chaplin.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 11 replies
  • 1894 views
  • 2 likes
  • 2 in conversation