Пример #1
0
 /// <summary>
 /// Evaluates the specified function.
 /// </summary>
 /// <param name="func">The function.</param>
 /// <param name="upperFunc">The upper function.</param>
 /// <param name="lowerFunc">The lower function.</param>
 /// <param name="range">The range.</param>
 /// <returns>
 /// The points representing the function evaluated over the given range.
 /// </returns>
 public static PointWithBounds[] Evaluate(
     Func <double, double> func,
     Func <double, double> upperFunc,
     Func <double, double> lowerFunc,
     RealRange range)
 {
     return(range.Values.Select(x => new PointWithBounds(x, func(x), lowerFunc(x), upperFunc(x))).ToArray());
 }
Пример #2
0
        public void TestRound()
        {
            Action <RealRange, RealRange> compare = (i, t) =>
            {
                RealRange r = i.Round();
                Assert.IsTrue(r.Equals(t), "Inputs: {0}\nExpected: {1}\nActual: {2}", i, t, r);
            };

            const double D1 = 0.0081564574540389997;
            const double D2 = 0.997722;

            compare(new RealRange {
                Min = D1, Max = D2
            }, new RealRange {
                Min = 0.0, Max = 1.0
            });
            compare(new RealRange {
                Min = D1, Max = D2 * 10
            }, new RealRange {
                Min = 0.0, Max = 10.0
            });
            compare(new RealRange {
                Min = D1 + 9, Max = D2 + 9
            }, new RealRange {
                Min = 9.0, Max = 10.0
            });
            compare(new RealRange {
                Min = D1 - 0.5, Max = D2 - 0.5
            }, new RealRange {
                Min = -0.5, Max = 0.5
            });
            compare(new RealRange {
                Min = -D2, Max = -D1
            }, new RealRange {
                Min = -1.0, Max = 0.0
            });
        }
Пример #3
0
        /// <summary>
        /// Stepped gaussian.
        /// </summary>
        /// <param name="gaussian">The gaussian.</param>
        /// <param name="range">The range.</param>
        /// <returns>The points.</returns>
        private IEnumerable <Point> SteppedGaussian(Gaussian gaussian, RealRange range)
        {
            var steps = new List <Point>();

            double sum = 0.0;

            var xvals = range.Values.ToArray();

            for (int i = 0; i < range.Count; i++)
            {
                double x1 = xvals[i] - (range.StepSize / 2);
                double x2 = xvals[i] + (range.StepSize / 2);

                double d = gaussian.CumulativeDistributionFunction(x2) - gaussian.CumulativeDistributionFunction(x1);

                if (i == 0)
                {
                    x1 = range.Min;
                }

                if (i == range.Count - 1)
                {
                    x2 = range.Max;
                }

                steps.Add(new Point(x1, 0));
                steps.Add(new Point(x1, d));
                steps.Add(new Point(x2, d));
                steps.Add(new Point(x2, 0));
                sum += d;
            }

            Console.WriteLine($@"The sum of the probabilities in the stepped plot is {sum}");

            return(steps);
        }
Пример #4
0
 public bool IsInside(Complex number) =>
 RealRange.IsInside(number.Real) &&
 ImagRange.IsInside(number.Imaginary);
Пример #5
0
        /// <summary>
        /// Builds the view.
        /// </summary>
        private void BuildView()
        {
            bool usePriorPosteriors    = false;
            var  priorPosteriorIndices = new List <Pair <int, int> >();

            this.gaussians.Clear();

            Gaussian?g = DataContext as Gaussian?;

            if (g.HasValue)
            {
                this.gaussians.Add(new KeyValuePair <string, Gaussian>(g.Value.ToString(), g.Value));
            }
            else
            {
                var gaussianEnumerable = DataContext as IEnumerable <Gaussian>;
                if (gaussianEnumerable != null)
                {
                    foreach (
                        var gaussian in
                        gaussianEnumerable.Where(gaussian => this.gaussians.All(ia => ia.Key != gaussian.ToString())).Take(this.MaxToShow))
                    {
                        this.gaussians.Add(new KeyValuePair <string, Gaussian>(gaussian.ToString(), gaussian));
                    }
                }
                else
                {
                    var gaussianDict = DataContext as IEnumerable <KeyValuePair <string, Gaussian> >;
                    if (gaussianDict != null)
                    {
                        foreach (var kvp in gaussianDict.Where(kvp => this.gaussians.All(ia => ia.Key != kvp.Key)).Take(this.MaxToShow))
                        {
                            this.gaussians.Add(new KeyValuePair <string, Gaussian>(kvp.Key, kvp.Value));
                        }
                    }
                    else
                    {
                        var dictOfDicts = DataContext as Dictionary <string, Dictionary <MBMLCommon.DistributionType, Gaussian> >;
                        int i           = 0;
                        if (dictOfDicts != null)
                        {
                            foreach (var dict in dictOfDicts)
                            {
                                priorPosteriorIndices.Add(new Pair <int, int>(i, i + 1));
                                i += 2;

                                foreach (var kvp in dict.Value)
                                {
                                    this.gaussians.Add(
                                        new KeyValuePair <string, Gaussian>(dict.Key + string.Format(" ({0})", kvp.Key), kvp.Value));
                                }
                            }

                            usePriorPosteriors = true;
                        }
                    }
                }
            }

            if (this.gaussians.Count == 0)
            {
                return;
            }

            double min = double.PositiveInfinity;
            double max = double.NegativeInfinity;

            // loop over gaussians to get x range, using 3x sigma on each side
            foreach (var kvp in this.gaussians)
            {
                min = Math.Min(min, -(4 * Math.Sqrt(kvp.Value.GetVariance())) + kvp.Value.GetMean());
                max = Math.Max(max, (4 * Math.Sqrt(kvp.Value.GetVariance())) + kvp.Value.GetMean());
            }

            List <Brush> palette = this.Palette;

            foreach (var pair in this.gaussians.Select((kvp, i) => new { kvp.Value, i }))
            {
                this.CellLegend.Children.Add(
                    new BulletDecorator
                {
                    Bullet = new Rectangle
                    {
                        Fill   = palette[pair.i % palette.Count],
                        Width  = 8,
                        Height = 8
                    },
                    VerticalAlignment = VerticalAlignment.Center,
                    Child             =
                        new TextBlock
                    {
                        Text     = FormatText(pair.Value),
                        FontSize = 12,
                        Margin   = new Thickness(3, 0, 0, 0)
                    }
                });
            }

            ////CellText.Text = string.Join(
            ////    "\n", this.gaussians.Select(ia => string.Format("Gaussian({0}, {1})", ia.GetMean().ToString("#0.0"), ia.GetVariance().ToString("#0.0"))));

            int interpolants = this.gaussians.Count > 10 ? 200 : 1000;

            var range = new RealRange {
                Min = min, Max = max, Steps = interpolants
            };

            // Use slightly shortened version of string (without mean) for legend
            this.series = this.gaussians.ToDictionary(ia => ia.Key, ia => this.GetData(ia.Value, range).ToArray());

            // Enumerate over gaussians again to add means after all Gaussians
            foreach (var kvp in this.gaussians)
            {
                if (this.LogarithmicYAxis || !this.DrawMean)
                {
                    continue;
                }

                double mean = kvp.Value.GetMean();
                string mkey = string.Format("μ={0}", mean.ToString("N"));

                if (!this.series.ContainsKey(mkey))
                {
                    this.series.Add(mkey, this.GetMeanSeries(kvp.Value));
                }
            }

            // And again for standard deviations
            foreach (var kvp in this.gaussians)
            {
                if (this.LogarithmicYAxis || !this.DrawStandardDeviation)
                {
                    continue;
                }

                double stdDev = Math.Sqrt(kvp.Value.GetVariance());
                string mkey   = string.Format("σ={0}", stdDev.ToString("N"));

                if (this.series.ContainsKey("±" + mkey))
                {
                    continue;
                }

                this.series.Add("±" + mkey, this.GetStandardDeviationSeries(kvp.Value));

                this.yMin = 0.0;
                this.PropertyChanged(this, new PropertyChangedEventArgs("YMinimum"));
            }

            MyChart.MaxNumberOfDataPoints = interpolants;

            MyChart.DataContext     = this.Series;
            MyCellChart.DataContext = this.Series;

            if (this.DrawMean && !string.IsNullOrEmpty(this.MeanAnnotation))
            {
                double mean = this.gaussians[0].Value.GetMean();
                double yval = Math.Exp(this.gaussians[0].Value.GetLogProb(mean)) / 4;

                // Add extra fake series
                this.MyChart.Series.Add(
                    new FastAnnotatedScatterSeries <double, double>
                {
                    ItemsSource =
                        new[] { new ChartPoint <double, double> {
                                    X = mean, Y = yval
                                } },
                    LineMarker      = MarkerType.None,
                    MarkerSize      = 0,
                    OffsetX         = 10,
                    OffsetY         = 2,
                    TextFormat      = this.MeanAnnotation,
                    AnnotationBrush = Brushes.Black,
                    FontSize        = 16,
                    LegendItemStyle = (Style)this.Resources["NullLegendItem"]
                });

                // None of the below works to actually remove the legend item ...
                ////MyChart.LegendItems.RemoveAt(MyChart.LegendItems.Count - 1);
                ////var legendItemsList = MyChart.LegendItems as AggregatedObservableCollection<object>;
                ////if (legendItemsList != null)
                ////{
                ////    legendItemsList.ChildCollections.Remove(this.MyChart.Series.Last().LegendItems);
                ////}
            }

            if (!usePriorPosteriors)
            {
                return;
            }

            this.MyChart.Series.Clear();
            var p = this.MyChart.Palette;

            this.MyChart.Palette = null;

            var newPalette = new Collection <ResourceDictionary>();

            int idx = 0;

            foreach (var kvp in this.series)
            {
                // Assume priors come before posteriors
                bool isPrior = (idx++ % 2) == 0;
                newPalette.Add(isPrior ? p[idx / 2] : newPalette.Last());

                var fs = (FastSeries)this.CreateFastSeries(kvp.Value.Select(ia => new ChartPoint <double, double>(ia.X, ia.Y)), isPrior);
                fs.Title = kvp.Key;

                this.MyChart.Series.Add(fs);
            }

            this.MyChart.Palette = newPalette;
        }
Пример #6
0
        /// <summary>
        /// Gets the data.
        /// </summary>
        /// <param name="gaussian">The gaussian.</param>
        /// <param name="range">The range.</param>
        /// <returns>
        /// The points.
        /// </returns>
        private IEnumerable <Point> GetData(Gaussian gaussian, RealRange range)
        {
            Func <double, double> f = x => this.LogarithmicYAxis ? gaussian.GetLogProb(x) : Math.Exp(gaussian.GetLogProb(x));

            return(range.Values.Select(x => new Point(x, f(x))));
        }
Пример #7
0
        /// <summary>
        /// The Expectation Propagation message example.
        /// </summary>
        public void EpMessageExample()
        {
            AnnounceExperiment("EpMessageExample");

            // This version uses greater than factor
            const double Skill1              = 120;
            const double Skill2              = 100;
            const double Sigma1              = 40;
            const double Sigma2              = 5;
            const double Variance1           = Sigma1 * Sigma1;
            const double Variance2           = Sigma2 * Sigma2;
            const double Beta                = 5;
            const double PerformanceVariance = Beta * Beta;

            var skill1Prior = new Gaussian(Skill1, Variance1);
            var skill2Prior = new Gaussian(Skill2, Variance2);

            var model = new TwoPlayerMessages(PerformanceVariance, skill1Prior, skill2Prior, MatchOutcome.Player1Win, ShowFactorGraph);

            var performance1 = new Gaussian(Skill1, Variance1 + PerformanceVariance);
            var performance2 = new Gaussian(Skill2, Variance2 + PerformanceVariance);

            var range = new RealRange {
                Min = -200, Max = 400, Steps = 300
            };

            // Produce a plot of the belief propagation message, incoming message, and the two of these multiplied,
            // the projection of this onto a Gaussian, and the EP message for the message from the greater than
            // factor to Jill's performance variable
            Func <double, double> cdf = x => Utils.StandardGaussian.CumulativeDistributionFunction(x);

            // Exact message
            double mu               = performance2.GetMean();
            double sigma            = Math.Sqrt(performance2.GetVariance());
            Func <double, double> f = x => cdf((x - mu) / sigma) / sigma;

            // Arbitrary renormalisation so that it fits on the plot
            Func <double, double> exact = x => f(x) / 20;

            // The actual message generated by Infer.NET. This is proj[f_i(x) * q\i(x)] / q\i(x)
            var message = model.MessageHistories["JPerf_B"][0];

            // The projection proj[f_i(x) * q\i(x)]
            var proj = message * performance1;

            // f_i(x) * q\i(x)
            Func <double, double> fqnoti = x => f(x) * Math.Exp(performance1.GetLogProb(x));
            Func <double, double> ce     = x => fqnoti(x) / fqnoti.Integrate(range);

            var plot = new EPMessageDemoViewModel
            {
                { "e (Exact)", Utils.Evaluate(exact, range) },
                { "c (Context)", Utils.Evaluate(performance1, range) },
                { "c e", Utils.Evaluate(ce, range) },
                { "Proj(c e)", Utils.Evaluate(proj, range) },
                { "Proj(c e) / c", Utils.Evaluate(message, range) }
            };

            var bpMessageDemo = new Dictionary <string, object> {
                { "Summary", plot }
            };

            // Produce a plot of the belief propagation message, incoming message, and the two of these multiplied for
            // Jill's skill marginal
            double sigma1Sq                = performance2.GetVariance();
            Func <double, double> f1       = x => cdf((x - mu) / (sigma * Math.Sqrt(1 + (sigma1Sq / Variance1))));
            Func <double, double> f1N      = x => f1(x) / 60;
            Func <double, double> fqnoti1  = x => f1(x) * Math.Exp(skill1Prior.GetLogProb(x));
            Func <double, double> fqnotin1 = x => fqnoti1(x) / fqnoti1.Integrate(range);

            message = model.MessageHistories["JSkill_marginal_F"][0];
            proj    = message * skill1Prior;

            var skill1Marginal = new EPMessageDemoViewModel
            {
                { "e (Exact)", Utils.Evaluate(f1N, range) },
                { "c (Context)", Utils.Evaluate(skill1Prior, range) },
                { "c e", Utils.Evaluate(fqnotin1, range) },
            };

            bpMessageDemo["JSkillMarginal"] = skill1Marginal;
            bpMessageDemo["Model"]          = model;

            // Null plots
            Func <int, IEnumerable <KeyValuePair <string, object> > > nullFunc =
                x => Enumerable.Range(0, x).Select(i => new KeyValuePair <string, object>(i.ToString("D"), new Point[] { }));

            // Create extra variables because we can't serialize KeyValuePair<>[]
            bpMessageDemo.Add(
                "Subplots",
                new[]
            {
                new EPMessageDemoViewModel {
                    { plot.First().Key, plot.First().Value }
                },
                new EPMessageDemoViewModel(plot.Take(2)),
                new EPMessageDemoViewModel(plot.Take(3)),
            });

            bpMessageDemo.Add(
                "JSkillMarginalSubplots",
                new[]
            {
                new EPMessageDemoViewModel {
                    { skill1Marginal.First().Key, skill1Marginal.First().Value }
                },
                new EPMessageDemoViewModel(skill1Marginal.Take(2)),
                new EPMessageDemoViewModel(skill1Marginal.Take(3)),
            });

            outputter.Out(bpMessageDemo,
                          Contents.S2InferringThePlayersSkills.NumberedName,
                          "The belief propagation message example");

            //Section 3

            Console.WriteLine($"\n{Contents.S3ASolutionExpectationPropagation.NumberedName}.\n");

            skill1Marginal = new EPMessageDemoViewModel
            {
                { "e (Exact)", Utils.Evaluate(f1N, range) },
                { "c (Context)", Utils.Evaluate(skill1Prior, range) },
                { "c e", Utils.Evaluate(fqnotin1, range) },
                { "Proj(c e)", Utils.Evaluate(proj, range) },
                { "Proj(c e) / c", Utils.Evaluate(message, range) }
            };

            var exMessageDemo = new Dictionary <string, object> {
                { "Summary", plot }
            };

            exMessageDemo["JSkillMarginal"] = skill1Marginal;
            exMessageDemo["Model"]          = model;

            exMessageDemo.Add(
                "Subplots",
                new[]
            {
                new EPMessageDemoViewModel {
                    { plot.First().Key, plot.First().Value }
                },
                new EPMessageDemoViewModel(plot.Take(2)),
                new EPMessageDemoViewModel(plot.Take(3)),
                //Section 3
                new EPMessageDemoViewModel(nullFunc(2).Concat(plot.Skip(2).Take(2))),
                new EPMessageDemoViewModel(plot.Take(2).Concat(nullFunc(1).Concat(plot.Skip(3).Take(2))))
            });

            exMessageDemo.Add(
                "JSkillMarginalSubplots",
                new[]
            {
                new EPMessageDemoViewModel {
                    { skill1Marginal.First().Key, skill1Marginal.First().Value }
                },
                new EPMessageDemoViewModel(skill1Marginal.Take(2)),
                new EPMessageDemoViewModel(skill1Marginal.Take(3)),
                // Section 3
                new EPMessageDemoViewModel(nullFunc(2).Concat(skill1Marginal.Skip(2).Take(2))),
                new EPMessageDemoViewModel(skill1Marginal.Take(2).Concat(plot.Skip(3).Take(2)))
            });

            outputter.Out(exMessageDemo,
                          Contents.S3ASolutionExpectationPropagation.NumberedName,
                          "The expectation propagation message example");
        }
Пример #8
0
 /// <summary>
 /// Evaluations of the average of a list of Gaussian distributions.
 /// </summary>
 /// <param name="gaussians">The gaussians.</param>
 /// <param name="range">The range.</param>
 /// <returns>The <see cref="Point"/> array.</returns>
 public static Point[] GaussianAverage(IEnumerable <Gaussian> gaussians, RealRange range)
 {
     return(range.Values.Select(x => new Point(x, gaussians.Average(gaussian => Math.Exp(gaussian.GetLogProb(x))))).ToArray());
 }
Пример #9
0
 /// <summary>
 /// Evaluates the specified gaussian.
 /// </summary>
 /// <param name="gaussian">The gaussian.</param>
 /// <param name="range">The range.</param>
 /// <returns>
 /// The points representing the function evaluated over the given range.
 /// </returns>
 public static Point[] Evaluate(Gaussian gaussian, RealRange range)
 {
     return(range.Values.Select(x => new Point(x, Math.Exp(gaussian.GetLogProb(x)))).ToArray());
 }
Пример #10
0
 /// <summary>
 /// Evaluates the specified function.
 /// </summary>
 /// <param name="func">The function.</param>
 /// <param name="range">The range.</param>
 /// <returns>The points representing the function evaluated over the given range.</returns>
 public static Point[] Evaluate(Func <double, double> func, RealRange range)
 {
     return(range.Values.Select(x => new Point(x, func(x))).ToArray());
 }