Exemple #1
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);
        }