Documentation
UncertainData.SamplingConstraints.constrain
— Methodconstrain(uv::AbstractUncertainValue, constraint::SamplingConstraint)
Apply the constraint
and truncate the support of the distribution furnishing the uncertain value uv
. Returns a constrained uncertain value.
Examples: constraining uncertain values
Theoretical distributions
using UncertainData, Distributions
# Define an uncertain value furnished by a theoretical distribution
uv = UncertainValue(Normal, 1, 0.5)
# Constrain the support of the furnishing distribution using various
# constraints
uvc_lq = constrain(uv, TruncateLowerQuantile(0.2))
uvc_uq = constrain(uv, TruncateUpperQuantile(0.8))
uvc_q = constrain(uv, TruncateQuantiles(0.2, 0.8))
uvc_min = constrain(uv, TruncateMinimum(0.5))
uvc_max = constrain(uv, TruncateMaximum(1.5))
uvc_range = constrain(uv, TruncateRange(0.5, 1.5))
Theoretical distributions with fitted parameters
using UncertainData, Distributions
# Define an uncertain value furnished by a theoretical distribution with
# parameters fitted to empirical data
uv = UncertainValue(Normal, rand(Normal(-1, 0.2), 1000))
# Constrain the support of the furnishing distribution using various
# constraints
uvc_lq = constrain(uv, TruncateLowerQuantile(0.2))
uvc_uq = constrain(uv, TruncateUpperQuantile(0.8))
uvc_q = constrain(uv, TruncateQuantiles(0.2, 0.8))
uvc_min = constrain(uv, TruncateMinimum(0.5))
uvc_max = constrain(uv, TruncateMaximum(1.5))
uvc_range = constrain(uv, TruncateRange(0.5, 1.5))
Kernel density estimated distributions
# Define an uncertain value furnished by a kernel density estimate to the
# distribution of the empirical data
uv = UncertainValue(UnivariateKDE, rand(Uniform(10, 15), 1000))
# Constrain the support of the furnishing distribution using various
# constraints
uvc_lq = constrain(uv, TruncateLowerQuantile(0.2))
uvc_uq = constrain(uv, TruncateUpperQuantile(0.8))
uvc_q = constrain(uv, TruncateQuantiles(0.2, 0.8))
uvc_min = constrain(uv, TruncateMinimum(13))
uvc_max = constrain(uv, TruncateMaximum(13))
uvc_range = constrain(uv, TruncateRange(11, 12))
(nested) weighted populations of uncertain values
Let's define a complicated uncertain value that is defined by a nested weighted population.
# Some subpopulations consisting of both scalar values and distributions
subpop1_members = [UncertainValue(Normal, 0, 1), UncertainValue(Uniform, -2, 2), -5]
subpop2_members = [UncertainValue(Normal, -2, 1), UncertainValue(Uniform, -6, -1),
-3, UncertainValue(Gamma, 1, 0.4)]
# Define the probabilities of sampling the different population members within the
# subpopulations. Weights are normalised, so we can input any numbers here indicating
# relative importance
subpop1_probs = [1, 2, 1]
subpop2_probs = [0.1, 0.2, 0.3, 0.1]
pop1 = UncertainValue(subpop1_members, subpop1_probs)
pop2 = UncertainValue(subpop2_members, subpop2_probs)
# Define the probabilities of sampling the two subpopulations in the overall population.
pop_probs = [0.3, 0.7]
# Construct overall population
pop_mixed = UncertainValue([pop1, pop2], pop_probs)
Now we can draw samples from this nested population. Sampling directly from the entire distribution is done by calling resample(pop_mixed, n_draws)
. However, in some cases we might want to constrain the sampling to some minimum, maximum or range of values. You can do that by using sampling constraints.
TruncateMinimum
To truncate the overall population below at some absolute value, use a TruncateMinimum
sampling constraint.
constraint = TruncateMinimum(-1.1)
pop_mixed_constrained = constrain(pop_mixed, constraint);
n_draws = 500
x = resample(pop_mixed, n_draws)
xc = resample(pop_mixed_constrained, n_draws)
p1 = scatter(x, label = "", title = "resampling before constraint")
p2 = scatter(xc, label = "", title = "resampling after constraint")
hline!([constraint.min], label = "TruncateMinimum(-1.1)")
plot(p1, p2, layout = (2, 1), link = :both, ylims = (-3, 3), ms = 1)
xlabel!("Sampling #"); ylabel!("Value")
TruncateMaximum
To truncate the overall population above at some absolute value, use a TruncateMaximum
sampling constraint.
constraint = TruncateMaximum(1.5)
pop_mixed_constrained = constrain(pop_mixed, constraint);
n_draws = 500
x = resample(pop_mixed, n_draws)
xc = resample(pop_mixed_constrained, n_draws)
p1 = scatter(x, label = "", title = "resampling before constraint")
p2 = scatter(xc, label = "", title = "resampling after constraint")
hline!([constraint.max], label = "TruncateMaximum(1.5)")
plot(p1, p2, layout = (2, 1), link = :both, ylims = (-3, 3), ms = 1)
xlabel!("Sampling #"); ylabel!("Value")
TruncateRange
To truncate the overall population above at some range of values, use a TruncateRange
sampling constraint.
constraint = TruncateRange(-1.5, 1.7)
pop_mixed_constrained = constrain(pop_mixed, constraint);
n_draws = 500
x = resample(pop_mixed, n_draws)
xc = resample(pop_mixed_constrained, n_draws)
p1 = scatter(x, label = "", title = "resampling before constraint")
p2 = scatter(xc, label = "", title = "resampling after constraint")
hline!([constraint.min, constraint.max], label = "TruncateRange(-1.5, 1.7)")
plot(p1, p2, layout = (2, 1), link = :both, ylims = (-3, 3), ms = 1)
xlabel!("Sampling #"); ylabel!("Value")
TruncateLowerQuantile
To truncate the overall population below at some quantile of the overall population, use a TruncateLowerQuantile
sampling constraint.
constraint = TruncateLowerQuantile(0.2)
# Constrain the population below at the lower 20th percentile
# Resample the entire population (and its subpopulations) according to
# their probabilities 30000 times to determine the percentile bound.
n_draws = 30000
pop_mixed_constrained = constrain(pop_mixed, constraint, n_draws);
# Calculate quantile using the same number of samples for plotting.
# Will not be exactly the same as the quantile actually used for
# truncating, except in the limit n -> ∞
q = quantile(resample(pop_mixed, n_draws), constraint.lower_quantile)
n_draws_plot = 3000
x = resample(pop_mixed, n_draws_plot)
xc = resample(pop_mixed_constrained, n_draws_plot)
p1 = scatter(x, label = "", title = "resampling before constraint")
p2 = scatter(xc, label = "", title = "resampling after constraint")
hline!([lq], label = "TruncateLowerQuantile(0.2)")
plot(p1, p2, layout = (2, 1), link = :both, ms = 1, ylims = (-6, 4))
xlabel!("Sampling #"); ylabel!("Value")
TruncateUpperQuantile
To truncate the overall population below at some quantile of the overall population, use a TruncateUpperQuantile
sampling constraint.
constraint = TruncateUpperQuantile(0.8)
# Constrain the population below at the lower 20th percentile
# Resample the entire population (and its subpopulations) according to
# their probabilities 30000 times to determine the percentile bound.
n_resample_draws = 30000
pop_mixed_constrained = constrain(pop_mixed, constraint, n_resample_draws);
# Calculate quantile using the same number of samples for plotting.
# Will not be exactly the same as the quantile actually used for
# truncating, except in the limit n_resample_draws -> ∞
q = quantile(resample(pop_mixed, n_resample_draws), constraint.upper_quantile)
n_plot_draws = 3000
x = resample(pop_mixed, n_plot_draws)
xc = resample(pop_mixed_constrained, n_plot_draws)
p1 = scatter(x, label = "", title = "resampling before constraint")
p2 = scatter(xc, label = "", title = "resampling after constraint")
hline!([q], label = "TruncateUpperQuantile(0.8)")
plot(p1, p2, layout = (2, 1), link = :both, ms = 1, ylims = (-6, 4))
xlabel!("Sampling #"); ylabel!("Value")
TruncateQuantiles
To truncate the overall population below at some quantile of the overall population, use a TruncateQuantiles
sampling constraint.
constraint = TruncateQuantiles(0.2, 0.8)
# Constrain the population below at the lower 20th percentile
# Resample the entire population (and its subpopulations) according to
# their probabilities 30000 times to determine the percentile bound.
n_resample_draws = 30000
pop_mixed_constrained = constrain(pop_mixed, constraint, n_resample_draws);
# Calculate quantile using the same number of samples for plotting.
# Will not be exactly the same as the quantile actually used for
# truncating, except in the limit n_resample_draws -> ∞
s = resample(pop_mixed, n_resample_draws)
qs = quantile(s, [constraint.lower_quantile, constraint.upper_quantile])
n_plot_draws = 3000
x = resample(pop_mixed, n_plot_draws)
xc = resample(pop_mixed_constrained, n_plot_draws)
p1 = scatter(x, label = "", title = "resampling before constraint")
p2 = scatter(xc, label = "", title = "resampling after constraint")
hline!([qs], label = "TruncateQuantiles(0.2, 0.8)")
plot(p1, p2, layout = (2, 1), link = :both, ms = 1, ylims = (-6, 4))
xlabel!("Sampling #"); ylabel!("Value")