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

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]dietIsUsed
Bread0.0000001
Cheese0.4494991
Fish0.5000001
Milk0.0535991
Potato1.8651681
Yogurt0.0000001

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

1 ACCEPTED SOLUTION

Accepted Solutions
RobPratt
SAS Super FREQ

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

View solution in original post

2 REPLIES 2
RobPratt
SAS Super FREQ

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

cfar
Calcite | Level 5

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]dietIsUsed
Bread0.0000000
Cheese0.4494991
Fish0.5000001
Milk0.0535991
Potato1.8651681
Yogurt0.0000000

Best regards.

sas-innovate-white.png

Missed SAS Innovate in Orlando?

Catch the best of SAS Innovate 2025 — anytime, anywhere. Stream powerful keynotes, real-world demos, and game-changing insights from the world’s leading data and AI minds.

 

Register now

Discussion stats
  • 2 replies
  • 1176 views
  • 0 likes
  • 2 in conversation