Page 1 of 1

Select an element randomly from a multidimensional set

Posted: Mon Feb 11, 2019 7:41 am
by qploussard
Hello,

I have a problem for which I don't find a simple solution.

I have a multidimensional set s(i,j,k).
I would like to select randomly an element from this set.
I was thinking about using randomNum = uniformint(1,card(s)) to select a random number between 1 and the number of elements in s.
Then, I wanted to apply:
sRand(i,j,k) $ (ord(s(i,j,k)) = randomNum) = yes;
to make sRand the subset that contains the single random element from s.

The problem is that GAMS does not allow to use "ord" on multidimensional set.
It looks strange to me because we can think of a "naturel" order of multimensional set such as this one:
1.1.1
1.1.2
1.2.1
1.2.2
2.1.1
2.1.2
etc...
In this case, we would have ord(1.2.1) = 3.

Anyway, because I cannot use "ord" on this multidimensional set, I have no idea how to pick up randomly an element from this set.

Does anyone know a simple trick to do this?

Thank you

Re: Select an element randomly from a multidimensional set

Posted: Mon Feb 11, 2019 10:14 am
by Clemens
I see two possibilities to do this:

1) Splitting up the ord() into three individual parts:

Code: Select all

scalar rI, rJ, rK;
rI=uniformint(1,card(i));
rJ=uniformint(1,card(j));
rK=uniformint(1,card(k));

sRand(i,j,k)$(ord(i)=rI and ord(j)=rJ and ord(k)=rK) = yes;
2) Using an Embedded Code section (Python):

Code: Select all

embeddedCode Python:
    import random
    choice = random.choice(list(gams.get("s")))
    gams.set("sRand", [choice])
endEmbeddedCode sRand
Note that you need to use random.seed() if you want the Python code to be reproducible. Otherwise Python will pick a different element every time you execute the program.

Hope that helps.
Clemens

Re: Select an element randomly from a multidimensional set

Posted: Mon Feb 11, 2019 3:12 pm
by dirkse
I like Clemens' Python approach. But if that's not your style, you can construct the function you wanted - what you thought ord() would give you - in a parameter, and use that:

Code: Select all

sets
  i / i1, i2 /
  j / j1 * j3 /
  ij(i,j) / i1.(j1,j2), i2.(j2,j3) /
  rnd(i,j)
  ;
scalars n, r;
parameter pos(i,j) 'position in 1..card(ij)';
n = 0;
loop{ij(i,j),
  n = n + 1;
  pos(i,j) = n;
};
abort$[n <> card(ij)] 'bogus pos computation', n, ij;
execseed = 07041776;
r = uniformint(1,card(ij));
rnd(ij)$[pos(ij) = r] = yes;

Re: Select an element randomly from a multidimensional set

Posted: Mon Feb 11, 2019 5:12 pm
by qploussard
Thanks for your answers Clemens and dirkse.

I thought about the answer 1) from Clemens but, unfortunately, my set s does not contain all the possible combination of the sets i, j, and k.
I don't have 1.1.1, 1.1.2, 1.2.1, 1.2.2, 2.1.1, 2.1.2 ...
But rather something like 1.1.2, 1.2.1, 2.1.1...
Because of this, using the method 1) may select a combination of (i,j,k) that does not belong to s(i,j,k).

The python approach and the approach from dirkse are exactly what I was looking for though, thank you!