Suppose you can calculate the shape of a continuous probability distribution but not the constant needed to make its density integrate to one. An unnormalized probability density function (PDF) keeps the relative weights: multiplying every value by the same positive constant changes the total area, but not the distribution those weights describe. The challenge is sampling from that shape without first finding the constant. section 16.3
A continuous distribution can expose this shape through Weight(double). Unlike a discrete distribution, it cannot enumerate all possible values to sum their weights. Its weights are real-valued, and Weight need not return a normalized PDF. For example, ContinuousUniform returns 1 inside its chosen interval and 0 outside, regardless of the interval’s width. section 15.2 section 12.4
A posterior without its normalizing constant
Given a prior and an observation, Bayes’ theorem makes the posterior density proportional to prior.Weight(a) * likelihood(a).Weight(evidence). The omitted divisor, P(evidence), is constant as a varies, so it is unnecessary if the sampler accepts unnormalized PDFs. There is a catch: likelihood distributions returned for different values of a must use consistent scaling. Otherwise, their Weight results distort the posterior’s relative weights. section 16.3
Func<double, double> posteriorPDF =
a => prior.Weight(a) * likelihood(a).Weight(evidence);
The posteriorPDF expression retains exactly the two factors that vary with a; it leaves out the constant evidence probability. section 16.3
That shortcut shifts work from normalization to sampling. Inverse-transform sampling uses a known quantile function; a numerically computed, unnormalized PDF may not come with one. Rejection sampling needs details about the PDF’s shape that may also be unavailable. Metropolis instead compares the target weights at a proposed and a current value. Their quotient cancels any shared normalization constant: a higher-weight proposal is accepted, while a lower-weight proposal is accepted with probability equal to that quotient. A rejection repeats the current value rather than searching in a loop. The initial and proposal distributions still need to be chosen appropriately. section 15.4 section 16.3 section 16.4
Listing 16.7 The Metropolis algorithm
public sealed class Metropolis: IContinuousDistribution
{
private readonly IEnumerator<double> enumerator;
private readonly Func<double, double> target;
public static Metropolis Distribution(
Func<double, double> target,
IDistribution<double> initial,
Func<double, IDistribution<double>> proposal)
{
var markov = Markov<double>.Distribution(initial, transition);
return new Metropolis(target, markov.Sample().GetEnumerator());
IDistribution<double> transition(double current)
{
double proposed = proposal(current).Sample();
return new Flip<double>(proposed, current,
target(proposed) / target(current));
}
}
private Metropolis(
Func<double, double> target, IEnumerator<double> enumerator)
{
this.enumerator = enumerator;
this.target = target;
}
public double Sample()
{
enumerator.MoveNext();
return enumerator.Current;
}
public double Weight(double d) => target(d);
}
The Metropolis transition samples a proposal, then passes target(proposed) / target(current) to a coin flip between the proposed and current values. section 16.4
The same relative-weight idea appears in discrete distributions, but its implementation differs. Integer weights give each outcome probability equal to its weight divided by the total. They avoid floating-point sums that miss one, yet combining a prior with conditional likelihoods can require least-common-multiple scaling to keep joint weights integral. Continuous posterior weights are multiplied directly as doubles instead. section 12.4 section 13.2 section 16.3

