random.seed
Random seed management for reproducible fuzzy number generation.
This module provides a centralized random state management system that ensures reproducible random generation across the entire AxisFuzzy library while maintaining thread safety and high performance. It serves as the foundation for all random fuzzy number generation operations.
The module implements a global singleton pattern for random state management, ensuring that all random generators throughout the library share a consistent and controllable random state. This is essential for scientific reproducibility and deterministic behavior in fuzzy computations.
Architecture
The random state management follows these key principles:
Global Consistency: Single source of truth for random state across the library
Thread Safety: All operations are protected by locks for concurrent access
Reproducibility: Deterministic behavior through proper seed management
Independence: Ability to spawn independent generators for parallel operations
Performance: Efficient NumPy generator usage with minimal overhead
The system is built around NumPy’s modern random number generation framework, using numpy.random.Generator instances for high-performance random sampling.
Classes
- GlobalRandomState
Thread-safe manager for global random state and generator instances.
Functions
set_seed : Set global random seed for reproducible generation get_rng : Get the global random number generator instance spawn_rng : Create independent generator for parallel operations get_seed : Retrieve the current global seed value
See also
axisfuzzy.random.apiHigh-level random generation API
axisfuzzy.random.baseAbstract base classes for random generators
numpy.randomNumPy’s random number generation framework
Examples
Basic seed management:
import axisfuzzy.random as fr
# Set global seed for reproducibility
fr.set_seed(42)
# Generate random fuzzy numbers - results will be reproducible
num1 = fr.rand('qrofn', q=2)
arr1 = fr.rand('qrofn', shape=(100,), q=3)
# Reset to same seed to get identical results
fr.set_seed(42)
num2 = fr.rand('qrofn', q=2) # Identical to num1
arr2 = fr.rand('qrofn', shape=(100,), q=3) # Identical to arr1
Advanced usage with independent generators:
import axisfuzzy.random as fr
import numpy as np
# Set global seed
fr.set_seed(123)
# Get the global generator for custom use
rng = fr.get_rng()
custom_samples = rng.uniform(0, 1, size=10)
# Spawn independent generator for parallel work
independent_rng = fr.spawn_rng()
parallel_samples = independent_rng.normal(0, 1, size=100)
Notes
The module uses NumPy’s modern random number generation system introduced in NumPy 1.17+. This provides better performance, statistical properties, and parallel support compared to the legacy numpy.random interface.
All generators are instances of numpy.random.Generator, which is the recommended interface for new code. The module ensures thread safety through appropriate locking mechanisms without significant performance penalties for typical usage patterns.
- class axisfuzzy.random.seed.GlobalRandomState[source]
Bases:
objectThread-safe global random state manager for AxisFuzzy.
This class manages a single numpy.random.Generator instance that serves as the primary source of randomness throughout the AxisFuzzy library. It provides thread-safe access to random number generation capabilities while ensuring reproducible behavior through proper seed management.
The class implements a singleton-like pattern where a single global instance manages the random state for the entire library, ensuring consistency across all random operations.
- _lock
Thread synchronization lock for safe concurrent access.
- Type:
threading.Lock
- _rng
The primary random number generator instance.
- Type:
numpy.random.Generator
- _seed
The current seed used to initialize the generator.
- Type:
int, numpy.random.SeedSequence, numpy.random.BitGenerator, or None
Notes
This class uses NumPy’s modern random number generation framework based on numpy.random.Generator. This provides better performance and statistical properties compared to the legacy numpy.random interface.
All methods are thread-safe and can be called concurrently from multiple threads without data races or inconsistent state.
The generator can be seeded with various types: - int: Simple integer seed - numpy.random.SeedSequence: Advanced seed sequence for better entropy - numpy.random.BitGenerator: Pre-configured bit generator
Examples
Basic usage (typically done through module functions):
# Create and configure global state state = GlobalRandomState() state.set_seed(42) # Get generator for random operations rng = state.get_generator() values = rng.uniform(0, 1, size=100) # Spawn independent generator independent_rng = state.spawn_generator() parallel_values = independent_rng.normal(0, 1, size=50)
- get_generator()[source]
Get the global random number generator instance.
Returns the current Generator instance used for all random operations in the library. This generator can be used directly for custom random sampling operations that need to be consistent with the global random state.
- Returns:
The current global random number generator instance.
- Return type:
numpy.random.Generator
Notes
The returned generator is the actual instance used internally, not a copy. This means that using it directly will advance the internal random state and affect subsequent library operations.
For operations that should not interfere with the global state, consider using
spawn_generator()instead.Thread safety is maintained through internal locking, so the generator can be safely accessed from multiple threads.
Examples
Direct generator usage:
# Get global generator rng = state.get_generator() # Use for custom sampling custom_values = rng.uniform(0, 1, size=1000) beta_values = rng.beta(2, 5, size=500) # This advances the global state, affecting subsequent # library operations fuzz_num = fr.rand('qrofn') # Uses advanced state
- get_seed()[source]
Get the current global random seed.
Returns the seed value that was used to initialize the current random number generator. This can be useful for debugging, logging, or re-creating the current random state.
- Returns:
The seed value used to initialize the current generator. Returns None if the generator was initialized with system entropy.
- Return type:
int, numpy.random.SeedSequence, numpy.random.BitGenerator, or None
Notes
The returned value is the original seed passed to
set_seed(), not the current internal state of the generator. The generator’s internal state changes with each random number drawn.To fully reproduce a sequence, you need both the original seed and knowledge of how many random numbers have been drawn since initialization.
Examples
# Set a seed and retrieve it state.set_seed(42) current_seed = state.get_seed() print(f"Current seed: {current_seed}") # Output: Current seed: 42 # Use for logging or debugging if current_seed is not None: print(f"Random state is deterministic with seed {current_seed}") else: print("Random state uses system entropy")
- set_seed(seed=None)[source]
Set the global random seed for reproducible generation.
Configures the internal random number generator with a specific seed, enabling reproducible random number generation across the entire AxisFuzzy library. This is essential for scientific reproducibility and debugging.
- Parameters:
seed (int, numpy.random.SeedSequence, numpy.random.BitGenerator, optional) –
The seed to use for random number generation. Different types provide different levels of control:
int: Simple integer seed (0 to 2^32-1)
numpy.random.SeedSequence: Advanced seed with entropy mixing
numpy.random.BitGenerator: Pre-configured bit generator
None: Use system entropy for non-reproducible behavior
Notes
Setting the seed affects all subsequent random operations in the library, including fuzzy number generation, random sampling, and stochastic operations. Once set, the sequence of random numbers becomes deterministic and reproducible.
For maximum reproducibility across different platforms and NumPy versions, consider using numpy.random.SeedSequence instead of raw integers.
Examples
Different seeding approaches:
# Simple integer seed state.set_seed(42) # Using SeedSequence for better entropy seed_seq = np.random.SeedSequence(12345) state.set_seed(seed_seq) # Using specific bit generator bit_gen = np.random.PCG64(67890) state.set_seed(bit_gen) # Reset to non-deterministic behavior state.set_seed(None)
- spawn_generator()[source]
Create an independent random number generator.
Spawns a new Generator instance that is statistically independent of the global generator. This is useful for parallel operations, isolated random processes, or when you need randomness that doesn’t interfere with the global random state.
- Returns:
A new, statistically independent random number generator.
- Return type:
numpy.random.Generator
Notes
The spawned generator is completely independent of the parent: - Drawing numbers from it doesn’t affect the global state - It has its own internal state and sequence - It’s suitable for parallel processing without interference
Spawning uses NumPy’s recommended approach for creating independent generators, ensuring proper statistical independence and avoiding correlation issues that can occur with naive approaches.
This method is particularly useful for: - Parallel fuzzy number generation - Isolated experiments within larger computations - Monte Carlo simulations with independent streams
Examples
Independent random generation:
# Set global state state.set_seed(42) # Spawn independent generator independent_rng = state.spawn_generator() # Use independent generator independent_values = independent_rng.uniform(0, 1, size=100) # Global state is unaffected global_values = state.get_generator().uniform(0, 1, size=100) # These sequences are statistically independent print("Independent and global sequences are uncorrelated")
Parallel processing example:
import concurrent.futures def generate_random_array(seed_offset): # Each worker gets independent generator worker_rng = state.spawn_generator() return worker_rng.normal(0, 1, size=1000) # Generate multiple independent arrays in parallel with concurrent.futures.ThreadPoolExecutor() as executor: futures = [executor.submit(generate_random_array, i) for i in range(10)] results = [f.result() for f in futures]
- axisfuzzy.random.seed.get_rng()[source]
Get the global random number generator for AxisFuzzy.
Returns the Generator instance used throughout the library for all random operations. This can be used for custom random sampling that needs to be consistent with the library’s random state.
- Returns:
The global random number generator instance.
- Return type:
numpy.random.Generator
Notes
The returned generator is the actual instance used internally by the library. Using it directly will advance the global random state and affect subsequent library operations.
For independent random generation that doesn’t interfere with the global state, use
spawn_rng()instead.See also
Examples
Custom random sampling:
import axisfuzzy.random as fr # Set seed for reproducibility fr.set_seed(42) # Get global generator rng = fr.get_rng() # Use for custom sampling consistent with global state membership_values = rng.beta(2, 5, size=100) noise = rng.normal(0, 0.1, size=100) # Subsequent library operations use advanced state fuzz_array = fr.rand('qrofn', shape=(50,), q=2)
Integration with NumPy operations:
import axisfuzzy.random as fr import numpy as np # Get generator for NumPy compatibility rng = fr.get_rng() # Use NumPy methods with consistent state indices = rng.choice(1000, size=100, replace=False) weights = rng.dirichlet([1, 1, 1, 1]) # Mix with AxisFuzzy operations fuzzy_samples = fr.rand('qrofn', shape=(len(indices),), q=3)
- axisfuzzy.random.seed.get_seed()[source]
Get the current global random seed.
Returns the seed value that was used to initialize the global random number generator. This is useful for debugging, logging, experiment tracking, or reproducing specific random states.
- Returns:
The seed value used to initialize the current generator. Returns None if the generator was initialized with system entropy.
- Return type:
int, numpy.random.SeedSequence, numpy.random.BitGenerator, or None
Notes
This function returns the original seed passed to
set_seed(), not the current internal state of the generator. The generator’s internal state evolves with each random number generated.To fully reproduce a random sequence, you need both the original seed and knowledge of the generation history (how many random numbers have been drawn).
Examples
Basic seed retrieval:
import axisfuzzy.random as fr # Set and retrieve seed fr.set_seed(42) current_seed = fr.get_seed() print(f"Current seed: {current_seed}") # Output: Current seed: 42
Experiment logging:
import axisfuzzy.random as fr # Set up experiment experiment_seed = 12345 fr.set_seed(experiment_seed) # Log experiment parameters print(f"Starting experiment with seed: {fr.get_seed()}") # Run experiment results = fr.rand('qrofn', shape=(100,), q=2) # Log for reproducibility print(f"Experiment completed with seed {fr.get_seed()}") print(f"To reproduce: fr.set_seed({fr.get_seed()})")
Conditional behavior based on seed:
import axisfuzzy.random as fr # Check if random behavior is deterministic if fr.get_seed() is not None: print("Random generation is reproducible") print(f"Seed: {fr.get_seed()}") else: print("Random generation uses system entropy") print("Results will not be reproducible") # Generate data data = fr.rand('qrofn', shape=(10,), q=3)
- axisfuzzy.random.seed.set_seed(seed=None)[source]
Set the global random seed for AxisFuzzy.
This function provides the primary interface for controlling randomness throughout the AxisFuzzy library. Setting a seed ensures that all random operations (fuzzy number generation, random sampling, etc.) produce reproducible results.
- Parameters:
seed (int, numpy.random.SeedSequence, numpy.random.BitGenerator, optional) –
The seed to use for random number generation:
int: Simple integer seed (recommended for basic use)
numpy.random.SeedSequence: Advanced seed sequence for better control
numpy.random.BitGenerator: Pre-configured bit generator
None: Use system entropy for non-reproducible behavior
See also
Examples
Basic reproducible generation:
import axisfuzzy.random as fr # Set seed for reproducibility fr.set_seed(42) # Generate fuzzy numbers - results are reproducible num1 = fr.rand('qrofn', q=2) arr1 = fr.rand('qrofn', shape=(10,), q=3) # Reset seed to get identical results fr.set_seed(42) num2 = fr.rand('qrofn', q=2) # Identical to num1 arr2 = fr.rand('qrofn', shape=(10,), q=3) # Identical to arr1 print(num1 == num2) # True print((arr1 == arr2).all()) # True
Scientific workflow with reproducibility:
import axisfuzzy.random as fr # Set seed at start of experiment EXPERIMENT_SEED = 12345 fr.set_seed(EXPERIMENT_SEED) # Generate datasets training_data = fr.rand('qrofn', shape=(1000, 10), q=2) test_data = fr.rand('qrofn', shape=(200, 10), q=2) # Results are now reproducible across runs print(f"Experiment run with seed {EXPERIMENT_SEED}")
Different seed types:
import numpy as np import axisfuzzy.random as fr # Simple integer seed fr.set_seed(123) # Advanced seed sequence seed_seq = np.random.SeedSequence(123, spawn_key=(1, 2, 3)) fr.set_seed(seed_seq) # Custom bit generator bit_gen = np.random.PCG64(456) fr.set_seed(bit_gen)
- axisfuzzy.random.seed.spawn_rng()[source]
Create an independent random number generator.
Spawns a new Generator instance that is statistically independent of the global generator. This is ideal for parallel operations, isolated computations, or when you need random numbers without affecting the global random state.
- Returns:
A new, statistically independent random number generator.
- Return type:
numpy.random.Generator
Notes
The spawned generator is completely independent: - Using it doesn’t affect the global random state - It maintains its own internal state and sequence - It’s safe for parallel processing without interference
This function uses NumPy’s recommended spawning mechanism to ensure proper statistical independence and avoid correlation issues.
See also
Examples
Independent random operations:
import axisfuzzy.random as fr # Set global seed fr.set_seed(42) # Create independent generator independent_rng = fr.spawn_rng() # Use independent generator without affecting global state independent_data = independent_rng.uniform(0, 1, size=1000) # Global state remains unaffected global_fuzz = fr.rand('qrofn', q=2) # Predictable based on seed 42
Parallel processing with independent streams:
import axisfuzzy.random as fr from concurrent.futures import ThreadPoolExecutor def worker_function(worker_id): # Each worker gets its own independent generator worker_rng = fr.spawn_rng() # Generate data independently data = worker_rng.normal(0, 1, size=100) fuzzy_data = [] # Use worker's generator for fuzzy generation for _ in range(10): # This would typically use a custom generator # For demonstration, we'll use direct values md = worker_rng.uniform(0, 1) nmd = worker_rng.uniform(0, 1-md**2)**(1/2) # q=2 constraint fuzzy_data.append((md, nmd)) return worker_id, data, fuzzy_data # Run parallel workers with independent randomness fr.set_seed(123) # Global seed for reproducibility with ThreadPoolExecutor(max_workers=4) as executor: results = list(executor.map(worker_function, range(4))) # Each worker produced independent results for worker_id, data, fuzzy_data in results: print(f"Worker {worker_id}: generated {len(data)} samples")
Monte Carlo simulation with independent streams:
import axisfuzzy.random as fr def monte_carlo_trial(): # Independent generator for each trial trial_rng = fr.spawn_rng() # Generate random fuzzy scenario scenario_data = trial_rng.uniform(0, 1, size=100) # Simulate some process result = scenario_data.mean() return result # Run multiple independent trials fr.set_seed(456) trials = [monte_carlo_trial() for _ in range(1000)] # Analyze results import numpy as np print(f"Monte Carlo estimate: {np.mean(trials):.4f} ± {np.std(trials):.4f}")