Operations Research topics: SAS/OR,
SAS Optimization, and SAS Simulation Studio

Parameter Declaring

Accepted Solution Solved
Reply
Occasional Contributor
Posts: 8
Accepted Solution

Parameter Declaring

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 advanceSmiley Happy

 

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

 


Accepted Solutions
Solution
‎03-15-2018 03:38 AM
SAS Employee
Posts: 575

Re: Parameter Declaring

Posted in reply to ALexandraJ86

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


All Replies
SAS Employee
Posts: 575

Re: Parameter Declaring

Posted in reply to ALexandraJ86
The constraint is indexed by k, but the rhs depends on i. In words, what is the constraint intended to enforce?
Occasional Contributor
Posts: 8

Re: Parameter Declaring

 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]);

 

SAS Employee
Posts: 575

Re: Parameter Declaring

Posted in reply to ALexandraJ86

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.

Occasional Contributor
Posts: 8

Re: Parameter Declaring

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.

ThxSmiley Happy

 

 

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;

 

SAS Employee
Posts: 575

Re: Parameter Declaring

Posted in reply to ALexandraJ86

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?

Occasional Contributor
Posts: 8

Re: Parameter Declaring

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.

SAS Employee
Posts: 575

Re: Parameter Declaring

Posted in reply to ALexandraJ86

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.

Occasional Contributor
Posts: 8

Re: Parameter Declaring

Posted in reply to ALexandraJ86
thank you. Yes volume is diffrent for diffrent values of k.
Occasional Contributor
Posts: 8

Re: Parameter Declaring

Posted in reply to ALexandraJ86
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.
Solution
‎03-15-2018 03:38 AM
SAS Employee
Posts: 575

Re: Parameter Declaring

Posted in reply to ALexandraJ86

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.

Occasional Contributor
Posts: 8

Re: Parameter Declaring

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

☑ This topic is solved.

Need further help from the community? Please ask a new question.

Discussion stats
  • 11 replies
  • 315 views
  • 0 likes
  • 2 in conversation