Hello.
Could somebody help me with the following problem, I have to construct dummy variables z such that:
for x>0 z = 1 otherwise z = 0
(later I plan to add those dummy variables), in order to solve an optimisation problem
I tried without much success two methods:
1)if x>0 then 1 else 0;
2) x <= x.ub * z (taken from and example of the SAS/OR 9.3 User's Guide Mathematical Programming Examples.
None works, in the second case after solving the problem SAS returns z = 1 even for x = 0 as can be seen in the following modification of the diet problem (here x = diet, z = IsUsed).
1] | diet | IsUsed |
---|---|---|
Bread | 0.000000 | 1 |
Cheese | 0.449499 | 1 |
Fish | 0.500000 | 1 |
Milk | 0.053599 | 1 |
Potato | 1.865168 | 1 |
Yogurt | 0.000000 | 1 |
In the case diet[Bread] = 0 and diet[Yogurt] = 0 IsUsed is equal to 1 .... and not zero as I expected. I obtaitned the result above results from the program:
proc optmodel;
/* declare index set */
set<str> FOOD;
/*set <str> al;*/
/* declare variables */
var diet{FOOD} >= 0;
var IsUsed{FOOD} Binary;
/* objective function */
num cost{FOOD};
min f=sum{i in FOOD}cost*diet;
/* constraints */
num prot{FOOD};
num fat{FOOD};
num carb{FOOD};
num cal{FOOD};
num min_cal, max_prot, min_carb, min_fat;
con cal_con: sum{i in FOOD}cal*diet >= 300;
con prot_con: sum{i in FOOD}prot*diet <= 10;
con carb_con: sum{i in FOOD}carb*diet >= 10;
con fat_con: sum{i in FOOD}fat*diet >= 8;
/* read parameters */
read data fooddata into FOOD=[name] cost prot fat carb cal;
/* bounds on variables */
diet['Fish'].lb = 0.5;
diet['Fish'].ub = 1.2;
diet['Milk'].ub = 1.6;
diet ['Bread'].ub = 0.8;
diet ['Potato'].ub = 10.1;
diet ['Yogurt'].ub = 0.7;
diet ['Cheese'].ub = 0.6;
/* Bin bounds */
con link {al in FOOD}:
diet[al] <= diet[al].ub * IsUsed[al];
Many thanks in advance for answering.
C. FOparinetto
Your "link" constraints enforce only one side of the implication (if diet > 0 then IsUsed = 1) and the solution does respect that.
If you also want the converse (if IsUsed =1 then diet > 0), then you need another set of constraints. You also need to decide how small of a value for diet is considered to be positive. For example, would you accept diet = 1e-6 as positive? Suppose that your tolerance is called epsilon. Then the following constraints should do what you want:
con link2 {al in FOOD}:
diet[al] >= epsilon * IsUsed[al];
Your "link" constraints enforce only one side of the implication (if diet > 0 then IsUsed = 1) and the solution does respect that.
If you also want the converse (if IsUsed =1 then diet > 0), then you need another set of constraints. You also need to decide how small of a value for diet is considered to be positive. For example, would you accept diet = 1e-6 as positive? Suppose that your tolerance is called epsilon. Then the following constraints should do what you want:
con link2 {al in FOOD}:
diet[al] >= epsilon * IsUsed[al];
Many thanks Rob.
Your suggestion makes the program work properly, adding
con link2 {al in FOOD}:
diet[al] >= 1e-6*IsUsed[al];
I obtain:
[1] | diet | IsUsed |
---|---|---|
Bread | 0.000000 | 0 |
Cheese | 0.449499 | 1 |
Fish | 0.500000 | 1 |
Milk | 0.053599 | 1 |
Potato | 1.865168 | 1 |
Yogurt | 0.000000 | 0 |
Best regards.
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.