embodichain.lab.sim.motion.workspace.samplers#
Workspace sampling strategies deriving from BaseSampler.
The package exports uniform, random, Halton, Sobol, and Latin-hypercube
samplers. SamplerFactory and create_sampler additionally construct the
Gaussian and importance strategies.
Classes:
Abstract base class for all samplers. |
|
Halton sequence sampler using quasi-random low-discrepancy sequences. |
|
Interface for all samplers. |
|
Latin Hypercube Sampler (LHS) for stratified sampling. |
|
Random sampler using uniform distribution. |
|
Factory class for creating samplers (Singleton pattern). |
|
Sobol sequence sampler using quasi-random low-discrepancy sequences. |
|
Uniform grid sampler. |
Functions:
|
Convenience function to create a sampler. |
- class embodichain.lab.sim.motion.workspace.samplers.BaseSampler[source]#
Bases:
ABCAbstract base class for all samplers.
This class provides common functionality and enforces the implementation of the sampling method in all derived classes.
- seed#
Random seed for reproducibility.
- rng#
NumPy random number generator.
- device#
PyTorch device for tensor operations.
Methods:
__init__([seed, device])Initialize the base sampler.
Get the name of the sampling strategy.
sample(num_samples[, bounds])Generate samples within the given bounds.
- __init__(seed=42, device=None)[source]#
Initialize the base sampler.
- Parameters:
seed (
int) – Random seed for reproducibility. Defaults to 42.device (
device|None) – PyTorch device (cpu/cuda). Defaults to cpu.
- abstract get_strategy_name()[source]#
Get the name of the sampling strategy.
- Return type:
str- Returns:
String identifier for the sampling strategy.
- sample(num_samples, bounds=None)[source]#
Generate samples within the given bounds.
- Parameters:
num_samples (
int) – Number of samples to generate.bounds (
Tensor|ndarray|None) – Tensor/Array of shape (n_dims, 2) containing [lower, upper] bounds for each dimension.
- Return type:
Tensor- Returns:
Tensor of shape (num_samples, n_dims) containing the sampled points.
- Raises:
ValueError – If bounds are not provided.
NotImplementedError – If the method is not implemented in the derived class.
- class embodichain.lab.sim.motion.workspace.samplers.HaltonSampler[source]#
Bases:
BaseSamplerHalton sequence sampler using quasi-random low-discrepancy sequences.
The Halton sequence is a deterministic low-discrepancy sequence that provides better coverage than random sampling. It uses coprime bases (primes) for each dimension to generate well-distributed points.
- Advantages:
Better uniformity than random sampling
Deterministic (reproducible)
Fast convergence for Monte Carlo integration
Works well in low to medium dimensions (2-10)
- Disadvantages:
Performance degrades in high dimensions (>10)
Correlation between dimensions can appear
Sequential generation (not easily parallelizable)
- bases#
Prime bases for each dimension. If None, uses first n primes.
- skip#
Number of initial samples to skip (helps reduce correlation).
Methods:
__init__([seed, device, bases, skip])Initialize the Halton sampler.
Get the name of the sampling strategy.
- __init__(seed=42, device=None, bases=None, skip=0)[source]#
Initialize the Halton sampler.
- Parameters:
seed (
int) – Random seed (used for consistency, but Halton is deterministic).device (
device|None) – PyTorch device (cpu/cuda). Defaults to cpu.bases (
Optional[List[int]]) – List of prime bases for each dimension. If None, uses first n primes.skip (
int) – Number of initial samples to skip. Defaults to 0. Higher values (e.g., 100-1000) can improve distribution quality.
- class embodichain.lab.sim.motion.workspace.samplers.ISampler[source]#
Bases:
ProtocolInterface for all samplers.
This protocol defines the contract that all samplers must follow.
Methods:
__init__(*args, **kwargs)Get the name of the sampling strategy.
sample(bounds, num_samples)Generate samples within the given bounds.
- __init__(*args, **kwargs)#
- get_strategy_name()[source]#
Get the name of the sampling strategy.
- Return type:
str- Returns:
String identifier for the sampling strategy.
- sample(bounds, num_samples)[source]#
Generate samples within the given bounds.
- Parameters:
bounds (
Tensor|ndarray) – Tensor/Array of shape (n_dims, 2) containing [lower, upper] bounds for each dimension.num_samples (
int) – Number of samples to generate.
- Return type:
Tensor- Returns:
Tensor of shape (num_samples, n_dims) containing the sampled points.
- class embodichain.lab.sim.motion.workspace.samplers.LatinHypercubeSampler[source]#
Bases:
BaseSamplerLatin Hypercube Sampler (LHS) for stratified sampling.
Latin Hypercube Sampling ensures that each dimension is divided into equally probable intervals, with exactly one sample in each interval. This provides better coverage with fewer samples compared to random sampling.
- Advantages:
Excellent coverage with small sample sizes
Each dimension is uniformly sampled
No sample clustering in any dimension
Works well in high dimensions
Popular in experimental design and sensitivity analysis
- Disadvantages:
Samples may align in projections (can be mitigated with optimization)
Not deterministic across different sample sizes
May have correlation between dimensions (unless optimized)
- strength#
Strength of the LHS (1 or 2). Higher strength reduces correlation.
- optimization#
Optimization method (‘random-cd’, ‘lloyd’, None). ‘random-cd’: Random coordinate descent (fast, good quality) ‘lloyd’: Lloyd’s algorithm (slower, better quality) None: No optimization (fastest, may have correlation)
Methods:
__init__([seed, device, strength, optimization])Initialize the Latin Hypercube sampler.
Get the name of the sampling strategy.
sample(bounds, num_samples)Generate Latin Hypercube samples within the given bounds.
- __init__(seed=42, device=None, strength=1, optimization='random-cd')[source]#
Initialize the Latin Hypercube sampler.
- Parameters:
seed (
int) – Random seed for reproducibility. Defaults to 42.device (
device|None) – PyTorch device (cpu/cuda). Defaults to cpu.strength (
int) – Strength of the LHS (1 or 2). Defaults to 1. Strength 1: Standard LHS Strength 2: Improved spacing (requires more samples)optimization (
str|None) – Optimization method to reduce correlation. ‘random-cd’: Fast, good quality (recommended) ‘lloyd’: Better quality, slower None: No optimization (fastest) Defaults to ‘random-cd’.constraint – Optional geometric constraint for sampling (e.g., SphereConstraint).
- get_strategy_name()[source]#
Get the name of the sampling strategy.
- Return type:
str- Returns:
String identifier for the sampling strategy.
- sample(bounds, num_samples)[source]#
Generate Latin Hypercube samples within the given bounds.
- Parameters:
bounds (
Tensor|ndarray) – Tensor/Array of shape (n_dims, 2) containing [lower, upper] bounds.num_samples (
int) – Number of samples to generate.
- Return type:
Tensor- Returns:
Tensor of shape (num_samples, n_dims) containing the sampled points.
- Raises:
ValueError – If bounds are invalid or num_samples is non-positive.
Examples
>>> sampler = LatinHypercubeSampler(seed=42, optimization='random-cd') >>> bounds = torch.tensor([[-1.0, 1.0], [-1.0, 1.0]], dtype=torch.float32) >>> samples = sampler.sample(bounds, num_samples=50) >>> samples.shape torch.Size([50, 2])
- class embodichain.lab.sim.motion.workspace.samplers.RandomSampler[source]#
Bases:
BaseSamplerRandom sampler using uniform distribution.
This sampler generates samples uniformly at random within the specified bounds. It’s simple and fast, but doesn’t guarantee uniform coverage. Samples may cluster in some regions while leaving other regions sparse.
- Advantages:
Fast and simple
No assumptions about the space
Works well for any number of dimensions
- Disadvantages:
Uneven coverage (clusters and gaps)
Slower convergence than quasi-random methods
May miss important regions
Methods:
__init__([seed, device])Initialize the random sampler.
Get the name of the sampling strategy.
- class embodichain.lab.sim.motion.workspace.samplers.SamplerFactory[source]#
Bases:
objectFactory class for creating samplers (Singleton pattern).
This factory allows registration and creation of samplers based on the sampling strategy. It uses the singleton pattern to ensure only one instance exists throughout the application.
The factory comes pre-registered with the strategies defined by
SamplingStrategy.Additional samplers can be registered using register_sampler().
Examples
>>> factory = SamplerFactory() >>> sampler = factory.create_sampler(SamplingStrategy.UNIFORM, seed=42) >>> isinstance(sampler, UniformSampler) True
>>> # Register custom sampler >>> factory.register_sampler("custom", CustomSampler) >>> custom_sampler = factory.create_sampler("custom", seed=42)
Methods:
__init__()Initialize the factory with built-in samplers.
__new__(cls)Create or return the singleton instance.
create_sampler([strategy])Create a sampler instance based on the strategy.
is_registered(strategy)Check if a strategy is registered.
List all registered sampling strategies.
register_sampler(name, sampler_class)Register a new sampler class.
Reset the singleton instance (mainly for testing).
- __init__()[source]#
Initialize the factory with built-in samplers.
This method only runs once due to the singleton pattern.
- static __new__(cls)[source]#
Create or return the singleton instance.
- Returns:
The singleton SamplerFactory instance.
- create_sampler(strategy=None, **kwargs)[source]#
Create a sampler instance based on the strategy.
- Parameters:
strategy (
SamplingStrategy|str|None) – The sampling strategy to use. Can be a SamplingStrategy enum or a string identifier. If None, defaults to RANDOM.**kwargs (
Any) – Additional keyword arguments to pass to the sampler constructor. Common options includeseed,device, andsamples_per_dimforUniformSampler.
- Return type:
- Returns:
An instance of the requested sampler.
- Raises:
ValueError – If the strategy is not registered.
Examples
>>> factory = SamplerFactory() >>> # Bounds-based usage >>> sampler = factory.create_sampler(SamplingStrategy.UNIFORM, seed=42) >>> sampler = factory.create_sampler("random", seed=123)
Note
Constraint-based sampling is temporarily disabled.
- is_registered(strategy)[source]#
Check if a strategy is registered.
- Parameters:
strategy (
SamplingStrategy|str) – The sampling strategy to check.- Return type:
bool- Returns:
True if the strategy is registered, False otherwise.
- list_available_strategies()[source]#
List all registered sampling strategies.
- Return type:
list[str]- Returns:
List of registered strategy names.
- register_sampler(name, sampler_class)[source]#
Register a new sampler class.
- Parameters:
name (
str) – String identifier for the sampler strategy.sampler_class (
Type[BaseSampler]) – The sampler class to register. Must inherit from BaseSampler.
- Raises:
TypeError – If sampler_class is not a subclass of BaseSampler.
ValueError – If name already exists and overwrite=False.
- Return type:
None
Examples
>>> factory = SamplerFactory() >>> factory.register_sampler("my_sampler", MySamplerClass)
- class embodichain.lab.sim.motion.workspace.samplers.SobolSampler[source]#
Bases:
BaseSamplerSobol sequence sampler using quasi-random low-discrepancy sequences.
The Sobol sequence is a low-discrepancy sequence that provides excellent uniformity in high-dimensional spaces. It’s widely used in finance, engineering, and scientific computing for Monte Carlo simulations.
- Advantages:
Excellent uniformity in high dimensions (up to ~40 dimensions)
Industry standard for quasi-Monte Carlo methods
Better convergence than random sampling (O(1/n) vs O(1/√n))
Well-suited for integration and optimization
- Disadvantages:
Requires scipy library
Sequential generation (but can be scrambled for randomization)
Initial points may not be well-distributed (use skip parameter)
- scramble#
Whether to scramble the sequence for better randomization.
- skip#
Number of initial samples to skip.
Notes
This implementation uses scipy.stats.qmc.Sobol for efficient generation. Falls back to a basic implementation if scipy is not available.
Methods:
__init__([seed, device, scramble, skip])Initialize the Sobol sampler.
Get the name of the sampling strategy.
sample(bounds, num_samples)Generate Sobol sequence samples within the given bounds.
- __init__(seed=42, device=None, scramble=True, skip=0)[source]#
Initialize the Sobol sampler.
- Parameters:
seed (
int) – Random seed for scrambling. Defaults to 42.device (
device|None) – PyTorch device (cpu/cuda). Defaults to cpu.scramble (
bool) – Whether to scramble the sequence. Defaults to True. Scrambling improves randomization while maintaining low discrepancy.skip (
int) – Number of initial samples to skip. Defaults to 0. Recommended: 0 for scrambled, >0 (e.g., 100) for unscrambled.constraint – Optional geometric constraint for sampling (e.g., SphereConstraint).
- get_strategy_name()[source]#
Get the name of the sampling strategy.
- Return type:
str- Returns:
String identifier for the sampling strategy.
- sample(bounds, num_samples)[source]#
Generate Sobol sequence samples within the given bounds.
- Parameters:
bounds (
Tensor|ndarray) – Tensor/Array of shape (n_dims, 2) containing [lower, upper] bounds.num_samples (
int) – Number of samples to generate.
- Return type:
Tensor- Returns:
Tensor of shape (num_samples, n_dims) containing the sampled points.
- Raises:
ValueError – If bounds are invalid or num_samples is non-positive.
Examples
>>> sampler = SobolSampler(scramble=True, seed=42) >>> bounds = torch.tensor([[-1.0, 1.0], [-1.0, 1.0]], dtype=torch.float32) >>> samples = sampler.sample(bounds, num_samples=100) >>> samples.shape torch.Size([100, 2])
- class embodichain.lab.sim.motion.workspace.samplers.UniformSampler[source]#
Bases:
BaseSamplerUniform grid sampler.
This sampler generates samples on a regular grid within the specified bounds. It ensures even coverage of the entire space, but suffers from the curse of dimensionality - the number of samples grows exponentially with the number of dimensions.
Note: Geometric constraint sampling is temporarily disabled.
- samples_per_dim#
Number of samples to generate per dimension. When specified, this controls the grid density and takes precedence over num_samples. Total grid points = samples_per_dim^n_dims.
Methods:
__init__([seed, samples_per_dim, device])Initialize the uniform sampler.
Get the name of the sampling strategy.
- __init__(seed=42, samples_per_dim=None, device=None)[source]#
Initialize the uniform sampler.
- Parameters:
seed (
int) – Random seed for reproducibility. Defaults to 42.samples_per_dim (
int|None) – Fixed number of samples per dimension. If None, will be calculated automatically from num_samples. Defaults to None.device (
device|None) – PyTorch device for tensor operations.
- embodichain.lab.sim.motion.workspace.samplers.create_sampler(strategy=None, **kwargs)[source]#
Convenience function to create a sampler.
This is a shorthand for SamplerFactory().create_sampler().
- Parameters:
strategy (
SamplingStrategy|str|None) – The sampling strategy to use.**kwargs (
Any) – Additional keyword arguments to pass to the sampler constructor.
- Return type:
- Returns:
An instance of the requested sampler.
Examples
>>> sampler = create_sampler(SamplingStrategy.UNIFORM, seed=42) >>> sampler = create_sampler("random", seed=123)
Note
Constraint-based sampling is temporarily disabled.