Exemple #1
0
 /// <summary>
 /// allows us to have zero-probability values
 /// </summary>
 private static int ExemptZeroes(Object[] objs, IRandomChoiceChooserD chooser, int index)
 {
     //System.out.PrintLn(index);
     if (chooser.GetProbability(objs[index]) == 0.0)
     // I need to scan forward because I'm in a left-trail
     // scan forward
     {
         while (index < objs.Length - 1 && chooser.GetProbability(objs[index]) == 0.0)
         {
             index++;
         }
     }
     // scan backwards
     else
     {
         while (index > 0 && chooser.GetProbability(objs[index]) == chooser.GetProbability(objs[index - 1]))
         {
             index--;
         }
     }
     return(index);
 }
Exemple #2
0
        /// <summary>
        /// Picks a random item from an array of objects, each with an
        /// associated probability that is accessed by taking an object
        /// and passing it to chooser.GetProbability(obj).  The objects'
        /// probabilities are  normalized and summed as follows:
        /// For example, if four probabilities are {0.3, 0.2, 0.1, 0.4},
        /// then they should get normalized and summed by the outside owners
        /// as: {0.3, 0.5, 0.6, 1.0}.  If probabilities.Length &lt; checkboundary,
        /// then a linear search is used, else a binary search is used.
        /// </summary>
        public static int PickFromDistribution(Object[] objs, IRandomChoiceChooserD chooser, double prob, int checkboundary)
        {
            if (prob < 0.0 || prob > 1.0)
            {
                throw new ArithmeticException("Invalid probability for pickFromDistribution (must be 0.0<=x<=1.0)");
            }
            if (objs.Length == 1)
            {
                return(0);
            }
            if (objs.Length < checkboundary)
            {
                // simple linear scan
                for (var x = 0; x < objs.Length - 1; x++)
                {
                    if (chooser.GetProbability(objs[x]) > prob)
                    {
                        return(ExemptZeroes(objs, chooser, x));
                    }
                }
                return(ExemptZeroes(objs, chooser, objs.Length - 1));
            }

            // binary search
            var top    = objs.Length - 1;
            var bottom = 0;

            while (top != bottom)
            {
                var cur = (top + bottom) / 2; // integer division

                if (chooser.GetProbability(objs[cur]) > prob)
                {
                    if (cur == 0 || chooser.GetProbability(objs[cur - 1]) <= prob)
                    {
                        return(ExemptZeroes(objs, chooser, cur));
                    }
                    // step down
                    else
                    {
                        top = cur;
                    }
                }
                else if (cur == objs.Length - 1)
                {
                    // oops
                    return(ExemptZeroes(objs, chooser, cur));
                }
                else if (bottom == cur)
                {
                    // step up
                    bottom++;
                }
                // (8 + 9)/2 = 8
                else
                {
                    bottom = cur; // (8 + 10) / 2 = 9
                }
            }
            return(ExemptZeroes(objs, chooser, bottom)); // oops
        }
Exemple #3
0
 /// <summary>
 /// Picks a random item from an array of objects, each with an
 /// associated probability that is accessed by taking an object
 /// and passing it to chooser.getProbability(obj).  The objects'
 /// probabilities are  normalized and summed as follows:
 /// For example, if four probabilities are {0.3, 0.2, 0.1, 0.4},
 /// then they should get normalized and summed by the outside owners
 /// as: {0.3, 0.5, 0.6, 1.0}.  If probabilities.Length &lt; CHECKBOUNDARY,
 /// then a linear search is used, else a binary search is used.
 /// </summary>
 public static int PickFromDistribution(Object[] objs, IRandomChoiceChooserD chooser, double prob)
 {
     return(PickFromDistribution(objs, chooser, prob, CHECKBOUNDARY));
 }
Exemple #4
0
        /// <summary>
        /// Normalizes the probabilities associated with an array of objects,
        /// then converts them into continuing sums.
        /// This prepares them for being usable in pickFromDistribution.
        /// If the probabilities are all 0, then selection is uniform, unless allowAllZeros
        /// is false, in which case an ArithmeticException is thrown.  If any of them are negative,
        /// or if the distribution is empty, then an ArithmeticException is thrown.
        /// For example,
        /// {0.6, 0.4, 0.2, 0.8} -> {0.3, 0.2, 0.1, 0.4} -> {0.3, 0.5, 0.6, 1.0}
        /// The probabilities are retrieved and set using chooser.
        /// </summary>
        public static void  OrganizeDistribution(Object[] objs, IRandomChoiceChooserD chooser, bool allowAllZeros)
        {
            // first normalize
            var sum = 0.0;

            if (objs.Length == 0)
            {
                throw new ArithmeticException("Distribution has no elements");
            }

            foreach (var t in objs)
            {
                if (chooser.GetProbability(t) < 0.0)
                {
                    throw new ArithmeticException("Distribution has negative probabilities");
                }
                sum += chooser.GetProbability(t);
            }

            if (sum == 0.0)
            {
                if (!allowAllZeros)
                {
                    throw new ArithmeticException("Distribution has all zero probabilities");
                }
                else
                {
                    foreach (var t in objs)
                    {
                        chooser.SetProbability(t, 1.0);
                    }
                    sum = objs.Length;
                }
            }

            foreach (var t in objs)
            {
                chooser.SetProbability(t, chooser.GetProbability(t) / sum);
            }

            // now sum
            sum = 0.0;
            foreach (var t in objs)
            {
                sum += chooser.GetProbability(t);
                chooser.SetProbability(t, sum);
            }

            // now we need to work backwards setting 0 values
            int x2;

            for (x2 = objs.Length - 1; x2 > 0; x2--)
            {
                if (chooser.GetProbability(objs[x2]) == chooser.GetProbability(objs[x2 - 1]))
                {
                    // we're 0.0
                    chooser.SetProbability(objs[x2], 1.0);
                }
                else
                {
                    break;
                }
            }
            chooser.SetProbability(objs[x2], 1.0);
        }
Exemple #5
0
 /// <summary>
 /// Same as organizeDistribution(objs, chooser, <b>false</b>);
 /// </summary>
 public static void  OrganizeDistribution(Object[] objs, IRandomChoiceChooserD chooser)
 {
     OrganizeDistribution(objs, chooser, false);
 }