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)

Reply via email to