Random with Weighted results

Hi All,

I was wondering if anyone knew how to write the statement for a weighted random generator. 

I have a series of polygons that I am changing the colour of using just a simple Random(1,6) which appears to give random results between 1 and 5. I thenuse this to select the colour number. 

What we would like to do is weight the random results a bit to give say more of one colour. 

For example:

colour 1 80%

colour 2 5%

colour 3 5%

colour 4 5%

colour 5 5%

another question would be how to set the seed so you could replicate or fix the outcome so it was repeatable. Maybe then connect this to a slider for testing options. 

Thanks

Wayne

  • Hi Wayne,

    That's a cool question.

    What I would do in this case is to generate random numbers from 1 to 100 (for 100%). If the random number is from 1 to 80 then I'd assign color 1, 81 through 85 for color 2, etc. In some cases it may make sense to generate a larger range of random numbers and scale them to the target range in the model, e.g. 1 to 1000 and use 1 through 800 for color 1, etc.

    Traditional random number generators are not truly random. The SetRandomSeed(N) function can be used to make the random number results predictably reproducible. For each integer seed N the sequence of "randomly" generated numbers will be the same. This permits to create reproducible results while still allowing to vary the results by changing the random seed. Note that if the SetRandomSeed(N) function call has no dependency to the rest of the GC model, a manual Update Model command may be required to see the effects of a changed seed N reflected in the geometry. If the seed N is set through a slider it may make sense to hook that slider up to some part of the model that will trigger an update of the affected geometry, even if that dependency's only purpose is to force the update and is otherwise ineffective --only indirectly via the random seed and the change in random number sequence.

    I hope this makes sense.

    Good success with your experiments!

         Volker

       

  • Hi Volker,

    That is a great approach.

    I have created a sample file for some tile example.

    I am having an issue with the SetRandomSeed(N) it appears to just return a result that has one colour. 

    I have attached the DGN sample and code below, I have commented out the see at the moment.

    This is my function at the moment:

    function (Polygon InputPoly, int RandomPool, double Ratio1, double Ratio2, double Ratio3, double Ratio4, double Ratio5)
    {

        Polygon TilePoly = {};
        Polygon TilePolyArray = {};
        int TileColour = 1;
       
        for (int i = 0; i < InputPoly.Count; ++i)
        {
             Polygon TilePolylist= {};
            for (int j = 0; j < InputPoly[i].Count; ++j)
               
                {
             //   SetRandomSeed(5);
                int RNumber = Random(1,RandomPool);
     
    //select from the random numbers a weighted colour
     if(RNumber <= (RandomPool*Ratio1))
            {
              TileColour = 1;
            }
     if(RNumber > (RandomPool*Ratio1) && RNumber <= (RandomPool*(Ratio1+Ratio2)))
            {
              TileColour = 2;
            }
     if(RNumber > (RandomPool*(Ratio1+Ratio2)) && RNumber <= (RandomPool*(Ratio1+Ratio2+Ratio3)))
            {
              TileColour = 3;
            }
     if(RNumber > (RandomPool*(Ratio1+Ratio2+Ratio3)) && RNumber <= (RandomPool*(Ratio1+Ratio2+Ratio3+Ratio4)))
            {
              TileColour = 4;
            }
     if(RNumber > (RandomPool*(Ratio1+Ratio2+Ratio3+Ratio4)) && RNumber <= (RandomPool*(Ratio1+Ratio2+Ratio3+Ratio4+Ratio5)))
            {
              TileColour = 5;
            }
                TilePoly = new Polygon();
                TilePoly.ByVertices({InputPoly[i][j].Vertices[0], InputPoly[i][j].Vertices[1], InputPoly[i][j].Vertices[2],InputPoly[i][j].Vertices[3]});
                TilePoly.Color = TileColour;
                TilePolylist.Add(TilePoly);
                        }
               TilePolyArray.Add(TilePolylist);
              
        }
        return TilePolyArray;

    }

    Thanks

    Wayne

    GC_Tiles-small-test.dgn

  • Hi Wayne,

    In the function above you call SetRandomSeed( ) each time before calling Random( ). That will make Random( ) return the same number each time, because it'll reset the random sequence for each Random( ) call. SetRandomSeed( ) should be called only once for each full sequence of random numbers that is generated, for example at the start of a script, in any case before the first call to Random( ), then not until you want to start a new random sequence.

    HTH,

         Volker

       

  • This looks great. If you move SetRandomSeed( ) up outside of the loop in your function, then you'll get a consistent pattern.

       

    Answer Verified By: Wayne Dickerson