/// <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()); }
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 }); }
/// <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); }
public bool IsInside(Complex number) => RealRange.IsInside(number.Real) && ImagRange.IsInside(number.Imaginary);
/// <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; }
/// <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)))); }
/// <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"); }
/// <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()); }
/// <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()); }
/// <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()); }