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]);
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.
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]);
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.
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;
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?
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.
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.
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.
Wow that isn't easy as I thought. Thank you very much.:smileyhappy
SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!
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.