Alex Herbert created RNG-138:
--------------------------------
Summary: CompositeSamplers to return a single sample from a
composite of 2 or more samplers of the same type
Key: RNG-138
URL: https://issues.apache.org/jira/browse/RNG-138
Project: Commons RNG
Issue Type: New Feature
Components: sampling
Affects Versions: 1.4
Reporter: Alex Herbert
Create a composite sampler that combines 2 or more samplers, each with its own
weight. The weights can be used to create a discrete probability distribution.
The composite sampler for example can be used to combine sampling from
different shapes to generate a sample from inside a more complex volume, such
as combining 6 triangles to create a hexagon.
We have 3 samplers that can sample efficiently from a weighted distribution:
- GuideTableDiscreteSampler
- AliasMethodDiscreteSampler
- MarsagliaTsangWangDiscreteSampler.Enumerated
So a composite sampler must accept a set of weighted samplers (of the same
type) and create a discrete sampler to select which one to sample. This is
facilitated using a builder API:
S is the type of sampler
{code:java}
public interface Builder<S> {
int size();
Builder<S> add(S sampler, double weight);
Builder<S> setFactory(DiscreteProbabilitySamplerFactory factory);
// Only works if size > 0
S build(UniformRandomProvider rng);
}
{code}
The factory specifies a mechanism to create the users choice of discrete
sampler:
{code:java}
public interface DiscreteProbabilitySamplerFactory {
DiscreteSampler create(UniformRandomProvider rng,
double[] probabilities);
}
{code}
It is not required to be set as a default will exist. The choice for the
DiscreteProbabilityCollectionSampler was the GuideTableDiscreteSampler due to
its low construction overhead (see RNG-109).
A static class provides a mechanism to create composite samplers via builders
typed to the final sample type:
{code:java}
public final class CompositeSamplers {
public static <T> Builder<ObjectSampler<T>> newObjectSamplerBuilder();
public static <T> Builder<SharedStateObjectSampler<T>>
newSharedStateObjectSamplerBuilder();
public static Builder<DiscreteSampler> newDiscreteSamplerBuilder();
public static Builder<SharedStateDiscreteSampler>
newSharedStateDiscreteSamplerBuilder();
public static Builder<ContinuousSampler> newContinuousSamplerBuilder();
public static Builder<SharedStateContinuousSampler>
newSharedStateContinuousSamplerBuilder();
}
{code}
An example of usage would be:
{code:java}
UniformRandomProvider rng = ...;
// Diamond vertices
double[] a = {0, 0};
double[] b = {1, 1};
double[] c = {2, 0};
double[] d = {1, -1};
// Note: The sample type (double[]) must be specified if the builder is not
assigned
ObjectSampler<double[]> diamond =
CompositeSamplers.<double[]>newObjectSamplerBuilder()
.add(TriangleSampler.of(a, b, c, rng), 1) // Upper
.add(TriangleSampler.of(a, d, c, rng), 1) // Lower
.build(rng);
double[] coord = diamond.sample();
// Note: Type is inferred if the builder is assigned and then used:
Builder<ObjectSampler<double[]>> builder =
CompositeSamplers.newObjectSamplerBuilder();
ObjectSampler<double[]> diamond =
builder
.add(TriangleSampler.of(a, b, c, rng), 1) // Upper
.add(TriangleSampler.of(a, d, c, rng), 1) // Lower
.build(rng);
{code}
--
This message was sent by Atlassian Jira
(v8.3.4#803005)