How to Assign Values Based on the Two Highest Probabilities in GAMS?

Hello, I am having some difficulty with coding in GAMS and would like to ask for your help.

I have a parameter A(EV, Prob), where EV stands for electric vehicle and Prob represents probability.

Prob is defined by a set of 5 elements (p1 to p5).

I would like to create a new parameter B that assigns a value of 1 to the two Prob indices with the highest probability, and 0 to the rest.

For example:
A(“EV1”, “p1”) = 0.10;
A(“EV1”, “p2”) = 0.15;
A(“EV1”, “p3”) = 0.25;
A(“EV1”, “p4”) = 0.20;
A(“EV1”, “p5”) = 0.30;

In this case, I want B(“EV1”, “p3”) and B(“EV1”, “p5”) to be set to 1, and the other indices to be 0.

Could you please advise how I could structure the code to achieve this?

The below code is my approach but I guess there would be better way…

Loop(EV,
    maxProb = smax(Prob, A(EV, Prob));
    
    B(EV, Prob)$(A(EV, Prob) = maxProb) = 1;
    
    A(EV, Prob)$(A(EV, Prob) = maxProb) = -1e6;
    
    secondMaxProb = smax(Prob, A(EV, Prob));
    B(EV, Prob)$(A(EV, Prob) = secondMaxProb) = 1;
    
    A(EV, Prob)$(A(EV, Prob) = -1e6) = maxProb;
);

Hi @leewing159 ,

I think your code does not cover corner cases like same probabilities occurring multiple times. I created a little example with some dummy data that should take care of this.

$eolcom //
Set ev, p;
Parameter A(ev<,p<)/ EV1.p1 0.10
                     EV1.p2 0.15
                     EV1.p3 0.25
                     EV1.p4 0.20
                     EV1.p5 0.30
                     EV2.p1 0.05
                     EV2.p2 0.30
                     EV2.p3 0.30
                     EV2.p4 0.30
                     EV2.p5 0.05
                     EV3.p1 1.00
                     EV3.p2 0.00
                     EV3.p3 0.00
                     EV3.p4 0.00
                     EV3.p5 0.00 /
          B(ev,p);
scalar maxProb;          
                 
option clear=B;    
loop(ev,                                      // for each element in ev
  while(sum(p$B(ev,p),1)<2,                   // while less than 2 B(ev,p) have nonzero value   
    maxProb = smax(p$(not B(ev,p)), A(ev,p)); // define maxProb of smax(p, A(ev,p)) for which B(ev,p) is zero
    loop(p$(not B(ev,p) and A(ev,p)=maxProb), // find first record A(ev,p)=maxProb for which B(ev,p) is still zero
      B(ev,p) = 1;
      break;
    );
  );
);                    

display A, B;

I hope this helps!

Fred

I was able to learn much cleaner code and logic. As you pointed out, my previous code did not handle exceptions well. Fortunately, there have been no issues so far since there’s no chance of duplication, but I will revise the code as per your advice.

Have a great weekend! Thank you.