Proc Optmodel SAS Conditional Restriction

I'm new to proc optmodel and can't seem to work out any syntax.

Here is my dataset.

data opt_test;
        input ID GRP $ x1 MIN MAX y z;
cards;
2 F 10 9 11 1.5 100
3 F 10 9 11 1.2 50
4 F 11 9 11 .9 20
8 G 5 4 6 1.2 300
9 G 6 4 6 .9 200
1 H 21 18 22 1.2 300
7 H 20 18 22 .8 1000
;
run;

      

There are several things here:

IDs inside GRP must have the same x2, which is limited to MIN and MAX. Now I want to further constrain the increase / decrease of x2 based on the y value. If y <1, I don't want x2 to go below .95 * x1. If y> 1, I don't want x2 to exceed 1.05 * x1. I looked online and tried several things to make this happen. Here is my last try, cond_1 and cond_2 are issues of interest as everything else works:

proc optmodel;

set<num> ID;

string GRP{ID};
set GRPS = setof{i in ID} GRP[i];
set IDperGRP{gi in GRPS} = {i in ID: GRP[i] = gi};

number x1{ID}; 
number MIN{ID};
number MAX{ID}; 

var x2{gi in GRPS} >= max{i in IDperGRP[gi]} MIN[i] 
                   <= min{i in IDperGRP[gi]} MAX[i] 
;
impvar x2byID{i in ID} = x2[GRP[i]];
number y{ID}; 
number z{ID}; 

read data opt_test into
        ID=[ID]
        GRP
        x1 
        MIN 
        MAX 
        y 
        z 
        ;

max maximize = sum{gi in GRPS} sum{i in IDperGRP[gi]} 
            (x2[gi]) * (1-(x2[gi]-x1[i])*y[i]/x1[i]) * z[i];

con cond_1 {i in ID}: x2[i] >= 
        if y[i]<1 then .95*x1[i] else 0;
con cond_2 {i in ID}: x2[i] <= 
        if y[i]>=1 then 1.05*x1[i] else 99999999;

solve;

create data results from [ID]={ID} x2=x2byID GRP x1 MIN MAX y z;

print x2 maximize;
quit;

      

+3


source to share


2 answers


The biggest problem with the model in question is that the indexing var

x2

is wrong. You can fix this by referring to the ID group as such:

con cond_1 {i in ID}: x2[GRP[i]] >= 
        if y[i] < 1 then .95*x1[i] else 0;
con cond_2 {i in ID}: x2[GRP[i]] <= 
        if y[i]>=1 then 1.05*x1[i] else 99999999;

      

but the description of the constraint, which reads the business problem closer, is to put the filter in the constraint definition:



con Cond_1v2 {i in ID: y[i] < 1} : x2[GRP[i]] >=  .95 * x1[i]; 
con Cond_2v2 {i in ID: Y[i] >= 1}: x2[GRP[i]] <= 1.05 * x1[i];

      

In any case, the problem becomes impossible due to the Cond2v2 constraint, as you can see using expand

(as @DomPazz pointed out) and in particular a parameter expand / iis

that will print conflicting constraints when it can define them:

solve with nlp / iis=on;
expand / iis;

      

+2


source


I would calculate the global max and min in the data step outside the PROC OPTMODEL and then set the values. For example:

data opt_test;
set opt_test;
if y < 1 then
    min2 = .95*x1;
else
    min2 = 0;

if y>=1 then
    max2 = 1.05*x1;
else
    max2 = 9999999999;

Min_old = min;
max_old = max;

MIN = max(min,min2);
MAX = min(max,max2);
run;

      

But you have a problem with group G. Use it to see it.

proc optmodel;

set<num> ID;

string GRP{ID};
set GRPS = setof{i in ID} GRP[i];
set IDperGRP{gi in GRPS} = {i in ID: GRP[i] = gi};

number x1{ID}; 
number MIN{ID};
number MAX{ID}; 

var x2{gi in GRPS} >= max{i in IDperGRP[gi]} MIN[i] 
                   <= min{i in IDperGRP[gi]} MAX[i] 
;
impvar x2byID{i in ID} = x2[GRP[i]];
number y{ID}; 
number z{ID}; 

read data opt_test into
        ID=[ID]
        GRP
        x1 
        MIN 
        MAX 
        y 
        z 
        ;

max maximize = sum{gi in GRPS} sum{i in IDperGRP[gi]} 
            (x2[gi]) * (1-(x2[gi]-x1[i])*y[i]/x1[i]) * z[i];

/*con cond_1 {i in ID}: x2[i] >= 
        if y[i]<1 then .95*x1[i] else 0;
con cond_2 {i in ID}: x2[i] <= 
        if y[i]>=1 then 1.05*x1[i] else 99999999;*/

expand;
solve;

create data results from [ID]={ID} x2=x2byID GRP x1 MIN MAX y z;

print x2 maximize;
quit;

      

You will see that X2 [G] is invalid:

Var x2[G] >= 5.7 <= 5.25

      



X2 [G] starts at [4,6];

With ID = 8, X = 5 and Y = 1.2. By your logic, this sets the max to 5.25 (5 * 1.2).

Now X2 [G] from [4.5.25]

With ID = 9, X = 6 and Y = 0.9. By your logic, this sets the min value to 5.7 (0.95 * 6).

X2 [G] in [5.7.5.25] <- BAD!

+3


source







All Articles