public static void MaxOfOthers_Linear(IList <Gaussian> array, IList <Gaussian> result)
        {
            if (array.Count == 0)
            {
                return;
            }
            if (array.Count == 1)
            {
                result[0] = Gaussian.Uniform();
                return;
            }
            var maxBefore = result;

            // initialize maxBefore[i] to max(array[0..i-1])
            maxBefore[1] = array[0];
            for (int i = 2; i < array.Count; i++)
            {
                maxBefore[i] = MaxGaussianOp.MaxAverageConditional(Gaussian.Uniform(), maxBefore[i - 1], array[i - 1]);
            }
            Gaussian maxAfter = array[array.Count - 1];

            for (int i = array.Count - 2; i >= 1; i--)
            {
                result[i] = MaxGaussianOp.MaxAverageConditional(Gaussian.Uniform(), maxAfter, maxBefore[i]);
                maxAfter  = MaxGaussianOp.MaxAverageConditional(Gaussian.Uniform(), maxAfter, array[i]);
            }
            result[0] = maxAfter;
        }
        /// <include file='FactorDocs.xml' path='factor_docs/message_op_class[@name="IndexOfMaximumOp_Fast"]/message_doc[@name="IndexOfMaximumDoubleAverageConditional(IList{Gaussian}, Discrete)"]/*'/>
        public static Discrete IndexOfMaximumDoubleAverageConditional2(IList <Gaussian> list, Discrete result)
        {
            // Fast approximate calculation of downward message

            // TODO: sort list first
            // best accuracy is achieved by processing in decreasing order of means
            Gaussian max   = list[0];
            Vector   probs = result.GetWorkspace();

            probs[0] = 1.0;
            for (int i = 1; i < list.Count; i++)
            {
                Gaussian A    = max;
                Gaussian B    = list[i];
                double   pMax = ProbGreater(A, B).GetProbTrue();
                for (int j = 0; j < i; j++)
                {
                    probs[j] *= pMax;
                }
                probs[i] = 1 - pMax;
                max      = MaxGaussianOp.MaxAverageConditional(Gaussian.Uniform(), A, B);
            }
            result.SetProbs(probs);
            return(result);
        }
        public static void MaxOfOthers_Quadratic(IList <Gaussian> array, IList <Gaussian> result)
        {
            if (array.Count == 0)
            {
                return;
            }
            if (array.Count == 1)
            {
                result[0] = Gaussian.Uniform();
                return;
            }
            var maxBefore = Gaussian.Uniform();

            for (int i = 0; i < array.Count - 1; i++)
            {
                // maxBefore is max(array[..i-1])
                Gaussian maxBeforeAndNext, maxBeforeAndCurrent;
                if (i == 0)
                {
                    maxBeforeAndNext    = array[i + 1];
                    maxBeforeAndCurrent = array[i];
                }
                else
                {
                    maxBeforeAndNext    = MaxGaussianOp.MaxAverageConditional(Gaussian.Uniform(), maxBefore, array[i + 1]);
                    maxBeforeAndCurrent = MaxGaussianOp.MaxAverageConditional(Gaussian.Uniform(), maxBefore, array[i]);
                }
                // maxBeforeAndNext is max(array[..i-1], array[i+1])
                var max = maxBeforeAndNext;
                for (int j = i + 2; j < array.Count; j++)
                {
                    // max is max(array[..j-1] except i)
                    max = MaxGaussianOp.MaxAverageConditional(Gaussian.Uniform(), max, array[j]);
                }
                result[i] = max;
                maxBefore = maxBeforeAndCurrent;
            }
            result[array.Count - 1] = maxBefore;
        }