|
#!/usr/bin/env wolframscript |
|
(* ::Package:: *) |
|
|
|
(* ::Text:: *) |
|
(*This script generates the second animated figure on my blog post "mackay_gaussian_2006".*) |
|
|
|
|
|
Print["https://jem-mosig.com/2019/03/mackay_gaussian_2006/"] |
|
|
|
|
|
(* ::Text:: *) |
|
(*Generate all frames of the animation, one sample from the bi-variate normal distribution for each frame.*) |
|
|
|
|
|
Print["Generating figure. This may take a minute..."] |
|
|
|
|
|
frames = BlockRandom[ |
|
SeedRandom[2019]; |
|
With[{x = {2}, \[Sigma] = 1, l = 1, x0 = 1, y0 = -1}, |
|
Module[{\[Mu], K, Kinv, A1, A2, B, \[Mu]post, Kpost}, |
|
\[Mu] = ConstantArray[0, Length[x] + 1]; |
|
K = N[Outer[\[Sigma]^2 Exp[-(#1 - #2)^2/(2 l^2)] &, |
|
Join[{x0}, x], Join[{x0}, x]], 40]; |
|
Kinv = Inverse[K]; |
|
A1 = Kinv[[1 ;; 1, 1 ;; 1]]; |
|
B = Kinv[[1 ;; 1, 2 ;;]]; |
|
A2 = Kinv[[2 ;;, 2 ;;]]; |
|
|
|
Assert[ |
|
AllTrue[ |
|
Flatten@Chop[Kinv - ArrayFlatten[{{A1, B}, {Transpose[B], A2}}]], # == 0 & |
|
] |
|
]; |
|
|
|
\[Mu]post = -Inverse[A2].Transpose[B].{{y0}} // Flatten; |
|
Kpost = Inverse[A2]; |
|
|
|
Quiet[ |
|
With[{ |
|
dist = MultinormalDistribution[\[Mu]post, Kpost], |
|
ah = |
|
Graphics[{Line[{{{0, -1}, {0, 1}}, {{-1, 0}, {0, 0}}}]}], |
|
contourPlot = ContourPlot[ |
|
PDF[MultinormalDistribution[\[Mu], K], {y1, y2}], |
|
{y1, -4, 4}, {y2, -4, 4}, |
|
Contours -> 10, |
|
ScalingFunctions -> "Log", |
|
ColorFunction -> GrayLevel, |
|
ImageSize -> Small, |
|
|
|
FrameLabel -> {"\!\(\*SubscriptBox[\(y\), \(1\)]\)", |
|
"\!\(\*SubscriptBox[\(y\), \(2\)]\)"}, |
|
|
|
Epilog -> {Dashed, ColorData[112, 1], |
|
InfiniteLine[{y0, 0}, {0, 1}]} |
|
] |
|
}, |
|
Table[ |
|
With[{y = RandomVariate[dist]}, |
|
Row[{ |
|
Show[{contourPlot, |
|
Graphics[{ColorData[112, 2], PointSize[Large], |
|
Point[{y0, y[[1]]}]}]} |
|
], |
|
ListPlot[ |
|
Prepend[Transpose[{x, y}], {x0, y0}], |
|
Joined -> True, InterpolationOrder -> 1, |
|
PlotStyle -> Directive[Thick, ColorData[112, 2]], |
|
PlotRange -> {{0.8, 2.2}, {-3, 3}}, |
|
FrameTicks -> {{Automatic, |
|
Automatic}, {{{1, |
|
"\!\(\*SubscriptBox[\(y\), \(1\)]\)"}, {2, |
|
"\!\(\*SubscriptBox[\(y\), \(2\)]\)"}}, None}}, |
|
Axes -> False, Frame -> True, |
|
Epilog -> { |
|
Black, |
|
PointSize[Large], |
|
Point[{x0, y0}] |
|
}, |
|
Prolog -> { |
|
Black, AbsoluteThickness[2], |
|
PointSize[Large], |
|
ColorData[112, 2], |
|
Point[Transpose[{x, y}]], |
|
Black, |
|
Arrowheads[{{.025, 1., ah}, {-.025, 0., ah}}], |
|
With[{i = 1}, |
|
Arrow[{{x[[i]], \[Mu]post[[i]] - |
|
Sqrt@Kpost[[i, i]]}, {x[[i]], \[Mu]post[[i]] + |
|
Sqrt@Kpost[[i, i]]}}] |
|
], |
|
Gray, Arrowheads[{{.025, 1., ah}, {-.025, 0., ah}}], |
|
With[{i = 2}, |
|
Arrow[{{2 + 0.05, 0 - Sqrt@K[[i, i]]}, {2 + 0.05, |
|
0 + Sqrt@K[[i, i]]}}] |
|
] |
|
}, |
|
ImageSize -> Medium |
|
] |
|
}] |
|
], |
|
100 |
|
] |
|
], |
|
{MultinormalDistribution::posdefprm, Transpose::nmtx} |
|
] |
|
] |
|
] |
|
]; |
|
|
|
|
|
(* ::Text:: *) |
|
(*Sort the frames to appear visually more pleasing.*) |
|
|
|
|
|
ordering = Quiet[ |
|
Last@FindShortestTour@Table[ |
|
FirstCase[frame[[1,1]],Point[pts_]:>pts,None,Infinity], |
|
{frame,frames} |
|
], |
|
{InterpolatingFunction::dmval} |
|
]; |
|
|
|
frames = frames[[ordering]]; |
|
|
|
|
|
Print@Export[ |
|
FileNameJoin[{"mackay_gaussian_2006-bi-posterior.gif"}], |
|
frames, |
|
AnimationRepetitions->Infinity, |
|
"DisplayDurations"->.1 |
|
] |