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

Hello,

 

I am having trouble with declaration of parameter i. Trying to write  a constraint  per vehicle, although I defined the parameter i and j, at the if part of  constraint I got error that i has't been declared.How can I solve this?Thanks in advance:)

 

 con Balance { k in VEHICLES}:
       sum {<i,j)> in ARCS} Flow[i,j,k]<= (if demand[i]<500 then 1000 else demand[i]);

 

1 ACCEPTED SOLUTION

Accepted Solutions
RobPratt
SAS Super FREQ

OK, I think I understand now.  Besides the binary variables UseNode and UseEdge that you already have, you will also need continuous flow variables to represent the amount of liquid or solid delivered to each factory by each vehicle:

 

   var LiquidFlow {i in FACTORIES, v in VEHICLES} >= 0 <= liquid[v];
   var SolidFlow {i in FACTORIES, v in VEHICLES} >= 0 <= solid[v];

 

 

Then the following constraints should capture the delivery of the liquids and solids:

   /* each vehicle must deliver its liquid */
   con LiquidVehicle {v in VEHICLES}:
      sum {i in FACTORIES} LiquidFlow[i,v] = liquid[v];

   /* each vehicle must deliver its solid */
   con SolidVehicle {v in VEHICLES}:
      sum {i in FACTORIES} SolidFlow[i,v] = solid[v];

   /* respect factory capacities */
   con LiquidFactory {i in FACTORIES}:
      sum {v in VEHICLES} LiquidFlow[i,v] 
   <= (if inventory[i] = 'liquid' then supply[i] else 0);
   con SolidFactory {i in FACTORIES}:
      sum {v in VEHICLES} SolidFlow[i,v] 
   <= (if inventory[i] = 'solid' then supply[i] else 0);

   /* if LiquidFlow[i,v] > 0 then UseNode[i,v] = 1 */
   con LiquidLogical {i in FACTORIES, v in VEHICLES}:
      LiquidFlow[i,v] <= LiquidFlow[i,v].ub * UseNode[i,v];

   /* if SolidFlow[i,v] > 0 then UseNode[i,v] = 1 */
   con SolidLogical {i in FACTORIES, v in VEHICLES}:
      SolidFlow[i,v] <= SolidFlow[i,v].ub * UseNode[i,v];

A more efficient approach would use sparse index sets instead of introducing variables that must be 0.  See the Sparse Modeling example in the PROC OPTMODEL documentation.

 

You will need additional constraints to link the UseNode and UseEdge variables and to eliminate subtours.  See the "Milk Collection" and "Lost Baggage Distribution" examples in the Mathematical Programming Examples documentation.

View solution in original post

11 REPLIES 11
RobPratt
SAS Super FREQ
The constraint is indexed by k, but the rhs depends on i. In words, what is the constraint intended to enforce?
ALexandraJ86
Calcite | Level 5
 con Balance { k in VEHICLES}:
       sum {<i,j)> in ARCS} Flow[i,j,k]<= (if demand[i]<500 then 1000 else volume[k]);

You're right. rhs part depends on k,I added,  but still can't define i.

 

if I declare  it like below, it works but doesn't calculate  per vehicle.

con Balance { k in VEHICLES,i in NODES}:
sum {<(i),j)> in ARCS} Flow[i,j,k]<= (if demand[i]<500 then 1000 else volume[k]);

 

RobPratt
SAS Super FREQ

I'm not sure what "doesn't calculate per vehicle" means.  The lhs variables and the rhs do depend on k.  Is volume[k] different for different values of k?  You might find it helpful to use the EXPAND statement to see the expanded form of the constraint.

ALexandraJ86
Calcite | Level 5

Hi, i could not do with expand statement. I tried to write a sample below that describes what I am trying to do.

 

There is a metarial data and the factory data.  Each vehicle on material data  try to use its liquid and solid stock by delivering it to the factories. Vehicles that have liquid volume goes to factories that have liquid inventory.

And I am trying to write a flow constraint per vehicle  if inventory is liquid on factory data then use the liquid variable on material data else use solid variable.

Thx:)

 

 

data material;
input liquid solid vehicle ;
datalines ;
50 10 1
40 30 2
10 60 3
0 100 4
100 0 5
;
data  factory;
input  id inventory $ x y supply;
datalines;
1 liquid 10 20 10
2 solid 11 20 20
3 liquid 15 30 40
4 liquid  12 20 100
5 solid  13 15 100
;
proc optmodel;
   set material;
   num liquid{material};
   num solid{material};
   num vehicle{material};
  
   read data material into material=[vehicle] liquid solid;

  
set factory;
   num id{factory};
   str inventory{factory};
   num east{factory};
   num north {factory};
   num supply{factory};
   read data factory into factory=[id] inventory east north supply;

 set EDGES = {i in factory, j in factory: i < j};
   num distance {<i,j> in EDGES} = 
      sqrt((east[i]-east[j])^2+(north[i]-north[j])^2);

	   var UseNode {factory} binary;
   var UseEdge {edges,material} binary;

   min TotalDistance 
      = sum {<i,j> in EDGES,k in material} distance[i,j] * UseEdge[i,j,k];

   con flow{k in material}:
      sum{<i,j> in edges} supply[i]*Useedge[i,j,k]
   <= (if inventory[i]="liquid" then liquid[k] else solid[k] );

   solve;
   quit;

 

RobPratt
SAS Super FREQ

I want to help, but I don't quite understand the business problem.  Can you please provide a sample solution (not necessarily optimal) that goes along with your sample data?

ALexandraJ86
Calcite | Level 5

I couldn't a make proper sample to describe the problem clearly. I am trying to explain it again.

Each vehicle has both solid and liquid volumes.

The vehicles' volumes are specified at the material table as liquid and solid.

The factory's demand can be only solid or liquid.It is specified in factory data(inventory variable).

 

Each vehicle tries to complete its volumes(solid and liquid).for example if a vehicle goes to a factory that has liquid inventory, this vehicle uses its liquid volume.if the same vehicle goes to a factory that has solid inventory,the vehicle uses its solid volume. So the flow constraint per vehicle changes according to factory inventory. 

 

con flow{k in material}:
      sum{<i,j> in edges} supply[i]*UseEdge[i,j,k]
   <= (if inventory[i]="liquid" then liquid[k] else solid[k] );

The rhs part is important I couldnt declare the i parameter (inventory[i] )

Thank you for your help.

RobPratt
SAS Super FREQ

What is the meaning of the supply column?  Is it a capacity on the amount of liquid or solid that can be delivered to that factory?

 

Where do the vehicles start and end?  For example, can vehicle 1 start at factory 3 and pay no cost (in terms of your distance objective) to arrive there?

 

I really think that a sample solution would help clarify the problem that you are trying to solve.

ALexandraJ86
Calcite | Level 5
thank you. Yes volume is diffrent for diffrent values of k.
ALexandraJ86
Calcite | Level 5
I couldn't develop a model yet.Just trying to write ,declare parameters and constraints. I will add a depot that have no cost and every vehicle start and end their routes at this point. yes the supply column is the capacity that can be delivered to factories.
RobPratt
SAS Super FREQ

OK, I think I understand now.  Besides the binary variables UseNode and UseEdge that you already have, you will also need continuous flow variables to represent the amount of liquid or solid delivered to each factory by each vehicle:

 

   var LiquidFlow {i in FACTORIES, v in VEHICLES} >= 0 <= liquid[v];
   var SolidFlow {i in FACTORIES, v in VEHICLES} >= 0 <= solid[v];

 

 

Then the following constraints should capture the delivery of the liquids and solids:

   /* each vehicle must deliver its liquid */
   con LiquidVehicle {v in VEHICLES}:
      sum {i in FACTORIES} LiquidFlow[i,v] = liquid[v];

   /* each vehicle must deliver its solid */
   con SolidVehicle {v in VEHICLES}:
      sum {i in FACTORIES} SolidFlow[i,v] = solid[v];

   /* respect factory capacities */
   con LiquidFactory {i in FACTORIES}:
      sum {v in VEHICLES} LiquidFlow[i,v] 
   <= (if inventory[i] = 'liquid' then supply[i] else 0);
   con SolidFactory {i in FACTORIES}:
      sum {v in VEHICLES} SolidFlow[i,v] 
   <= (if inventory[i] = 'solid' then supply[i] else 0);

   /* if LiquidFlow[i,v] > 0 then UseNode[i,v] = 1 */
   con LiquidLogical {i in FACTORIES, v in VEHICLES}:
      LiquidFlow[i,v] <= LiquidFlow[i,v].ub * UseNode[i,v];

   /* if SolidFlow[i,v] > 0 then UseNode[i,v] = 1 */
   con SolidLogical {i in FACTORIES, v in VEHICLES}:
      SolidFlow[i,v] <= SolidFlow[i,v].ub * UseNode[i,v];

A more efficient approach would use sparse index sets instead of introducing variables that must be 0.  See the Sparse Modeling example in the PROC OPTMODEL documentation.

 

You will need additional constraints to link the UseNode and UseEdge variables and to eliminate subtours.  See the "Milk Collection" and "Lost Baggage Distribution" examples in the Mathematical Programming Examples documentation.

ALexandraJ86
Calcite | Level 5

Wow that isn't easy as I thought. Thank you very much.:smileyhappy

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
  • 1720 views
  • 0 likes
  • 2 in conversation