question

Zixuan Xiong avatar image
1 Like"
Zixuan Xiong asked Ben Wilson commented

Generate Random Value Sequence

Background: I want to assign a store number label to the inbound order. Let's say I have ten stores and one order per store. That means ten orders per day.

Question: how can I generate a array or value stream that includes 10 numbers (1-10) but in a random sequence? I was looking at commands like "randstate" and "randinit" but sorry I didn't understand the instruction.

FlexSim 7.7.4
random sequence
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Zixuan Xiong avatar image
3 Likes"
Zixuan Xiong answered Ben Wilson commented

I found a algorithm called Fisher-Yates shuffle and I tried to populate that in FlexSim. It works pretty good. Looks easy and efficient. @Ben Wilson

int counts=10;
int dummy=0;
intarray numset = makearray(counts);
//Create a {1,2,3...10} array.
for (int i=1;i<=counts;i++){
	numset[i]=i;
}
//For each number i swap numset[i] and numset[j] and 
//j is a random index between 1 and i.  
for (int i=1;i<=counts;i++){
	int j = duniform(1,i);
	dummy=numset[i];
	numset[i]=numset[j];
	numset[j]=dummy;
}
return numset;
· 3
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Ben Wilson avatar image Ben Wilson ♦♦ commented ·

Great find! I knew there would be better answers than my made up on the fly stuff. Good work!

1 Like 1 ·
Mischa Spelt avatar image Mischa Spelt commented ·

@Ben Wilson: Now that arrays are becoming more important (with Process Flow I find myself using them a lot more than before) it may be worth implementing an arrayshuffle command in a next release? It could either encapsulate one of the above algorithms or trivially call C++'s std::shuffle.

1 Like 1 ·
Ben Wilson avatar image Ben Wilson ♦♦ Mischa Spelt commented ·

@Mischa Spelt, your request has been forwarded on to the dev team for consideration. Thanks!

1 Like 1 ·
Ben Wilson avatar image
1 Like"
Ben Wilson answered

Yet another example, this one also produces an intarray populated with values 1-10, randomly ordered.

This example code should scale decently well (better than the previous example, at any rate) for larger number sets.

Once again, I'm sure others in the community could come up with some better solutions, so please add your answer if you have one.

//how big is our set of numbers?
int numset_count = 10;
//initialize an array of zeros
intarray numset = makearray(numset_count);
//populate numset with our set of numbers 1-10.
for (int i=1; i<=numset_count; i++) {
    //randomEmptyIndex represents the first, fifth, eighth,
    // etc, empty spot, as opposed to just the first, fifth,
    // eighth, etc, index of the array. Also, for every value
    // we enter into the array, there will be one less empty
    // index to consider, so we can remove i from our random
    // empty index count:
    int randomEmptyIndex = duniform(1, numset_count+1-i);
    //loop through numset, counting empty indeces until we
    // get to the randomEmptyIndex empty index
    int emptyIndexCounter = 0;
    for (int j=1; j<=numset_count; j++) {
        //if index j of numset is empty, increment our
        // emptyIndexCounter counter variable
        if (!numset[j]) {
            emptyIndexCounter++;
            //if emptyIndexCounter has reached our
            // randomEmptyIndex, we can set our i value there
            // and break out of this inner for loop
            if (emptyIndexCounter==randomEmptyIndex) {
                numset[j] = i;
                break;
            }
        }
    }
}
//numset is now populated with values 1-10, randomly ordered
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Ben Wilson avatar image
1 Like"
Ben Wilson answered

Here is another example. In this case it all takes place in code, no external global table required. You end up with a randomly sorted intarray of your numbers, 1-10.

This example code could end up being expensive, as far as computing efficiency goes, if your set size gets too big. In that case you would modify this script to optimize it - for instance, below if I try to put a number into an index that already has a value, I just roll the dice again until I hit upon an available index. By the time there are only 1 or 2 spots left to fill, I'm having to roll the dice many times to find the available indeces, because I'm still considering all 10 spots when I roll the dice.

I'll probably make one more post with an optimized, albeit more complex, version that will be optimized for larger data sets.

In the mean time, since your number set is pretty small, for this first example we'll keep it simple (and less efficient) with this script:

//initialize an array of zeros
intarray numset = makearray(10);
//populate numset with our set of numbers 1-10
for (int i=1; i<=10; i++) {
    while (1) {
        int randomindex = duniform(1,10);
        if (!numset[randomindex]) {
            numset[randomindex] = i;
            break;
        }
    }
}
//numset is now populated with values 1-10, randomly ordered
5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.

Ben Wilson avatar image
1 Like"
Ben Wilson answered Ben Wilson edited

Let me restate the problem to see if I understood it correctly: You want a certain set of numbers, in your case 1-10, to be randomly ordered.

Here is one solution - there are probably many ways to do this.

Create a global table with 10 rows and 2 columns. Column 1 will have your desired values, 1-10. Column 2 will have a random value. In this example we'll just use the uniform(0,100) distribution. Then just sorttable on the random column.

Here is a quick script you could run from a Script window to populate your table:

//assumes you've already created a Global Table called "MyGlobalTable"
settablesize("MyGlobalTable", 10, 2);
for (int i=1; i<=gettablerows("MyGlobalTable"); i++) {
    //populate column 1 with values 1-10
    settablenum("MyGlobalTable", i, 1, i);
    //put a random value into column 2
    settablenum("MyGlobalTable", i, 2, uniform(0, 100));
}
//sort the table by the random value in column 2
sorttable("MyGlobalTable", 2);

This is just one way to solve this problem. I bet someone will come up with a better way than this, so hopefully we'll get several good answers to your question.

5 |100000

Up to 12 attachments (including images) can be used with a maximum of 23.8 MiB each and 47.7 MiB total.