random.registry
Random generator registry for managing mtype-specific random generators.
This module provides a centralized registry for managing random number generators for different fuzzy number types (mtypes). It follows AxisFuzzy’s extensible architecture based on mtype specialization and enables automatic registration and discovery of random generators.
The registry system serves as the foundation for AxisFuzzy’s plugin-style random generation architecture, where each fuzzy number type can provide its own specialized random generator while maintaining a unified interface.
Architecture
The registry follows these key design principles:
Singleton Pattern: Global registry ensures consistent state across the library
Thread Safety: All operations are protected by locks for concurrent access
Automatic Registration: Generators can self-register using the @register_random decorator
Type Safety: Validates generator types and mtype consistency during registration
The registry maintains a mapping from mtype strings to generator instances, enabling dynamic dispatch based on the requested fuzzy number type.
Classes
- RandomGeneratorRegistry
Thread-safe singleton registry for managing generator instances.
Functions
- register_randomdecorator
Class decorator for automatic generator registration.
- get_random_generatorfunction
Retrieve a registered generator by mtype.
- list_registered_randomfunction
List all registered mtypes.
- is_registered_randomfunction
Check if an mtype has a registered generator.
See also
axisfuzzy.random.baseAbstract base classes for generators
axisfuzzy.random.apiHigh-level API for random generation
axisfuzzy.fuzztype.qrofn.randomExample generator implementation
Examples
Registering a generator using the decorator:
from axisfuzzy.random.base import ParameterizedRandomGenerator
from axisfuzzy.random.registry import register_random
@register_random
class MyRandomGenerator(ParameterizedRandomGenerator):
mtype = "mytype"
def get_default_parameters(self):
return {'param1': 1.0}
def validate_parameters(self, **params):
pass
def fuzznum(self, rng, **params):
# Implementation
pass
def fuzzarray(self, rng, shape, **params):
# Implementation
pass
Using the registry programmatically:
from axisfuzzy.random.registry import (
get_registry_random, get_random_generator, list_registered_random
)
# Check available generators
print("Available generators:", list_registered_random())
# Get a specific generator
generator = get_random_generator('qrofn')
if generator is not None:
# Use the generator...
pass
# Manual registration (not recommended)
registry = get_registry_random()
registry.register('custom_type', my_generator_instance)
Notes
Generators are typically registered automatically using the @register_random decorator
Manual registration is available but not recommended for standard use cases
The registry is thread-safe and can be accessed concurrently
Generator instances are cached, so registration should occur at module import time
- class axisfuzzy.random.registry.RandomGeneratorRegistry[source]
Bases:
objectThread-safe registry for random generators.
This registry manages the mapping between fuzzy number types (mtypes) and their corresponding random generator instances. It ensures thread-safe access and follows the singleton pattern for global consistency across the entire AxisFuzzy library.
The registry serves as the central dispatch point for the random generation system, enabling automatic discovery and instantiation of appropriate generators based on the requested mtype.
- _instance
Singleton instance reference.
- Type:
RandomGeneratorRegistry or None
- _lock
Class-level lock for singleton creation.
- Type:
threading.RLock
Notes
This class implements the singleton pattern to ensure a single global registry instance. All methods are thread-safe and can be called concurrently from multiple threads.
The registry maintains generator instances (not classes), so generators should be stateless or properly handle concurrent access.
Examples
Basic registry usage:
# Get the global registry instance registry = get_registry_random() # Check what generators are available print("Registered mtypes:", registry.list_mtypes()) # Get a specific generator gen = registry.get_generator('qrofn') # Check if a type is registered if registry.is_registered('custom_type'): print("Custom type is available")
Manual registration (advanced usage):
from axisfuzzy.random.base import BaseRandomGenerator class CustomGenerator(BaseRandomGenerator): mtype = "custom" # ... implementation registry = get_registry_random() registry.register('custom', CustomGenerator())
- clear()[source]
Clear all registered generators.
Removes all generators from the registry. This method is primarily useful for testing or when completely reinitializing the system.
- Return type:
None
Notes
This operation is thread-safe but should be used with caution as it affects the global state of the random generation system.
After clearing, all random generation requests will fail until generators are re-registered.
Examples
# Typically only used in testing registry = get_registry_random() registry.clear() assert len(registry) == 0 assert registry.list_mtypes() == []
- get_generator(mtype)[source]
Get the random generator for a specific mtype.
Retrieves the generator instance associated with the given fuzzy number type. This is the primary method used by the random generation API to obtain the appropriate generator.
- Parameters:
mtype (str) – The fuzzy number type identifier.
- Returns:
The registered generator instance, or None if no generator is registered for the given mtype.
- Return type:
BaseRandomGenerator or None
Notes
This method is thread-safe and can be called concurrently. The returned generator instance should be stateless or handle concurrent access appropriately.
Examples
registry = get_registry_random() # Get a generator qrofn_gen = registry.get_generator('qrofn') if qrofn_gen is not None: # Use the generator fuzznum = qrofn_gen.fuzznum(rng, q=2, md_low=0.1) else: print("No generator available for qrofn")
- is_registered(mtype)[source]
Check if a generator is registered for the given mtype.
Provides a quick way to test generator availability without retrieving the actual generator instance.
- Parameters:
mtype (str) – The fuzzy number type identifier.
- Returns:
True if a generator is registered for the mtype, False otherwise.
- Return type:
bool
Notes
This method is thread-safe and more efficient than calling get_generator() when you only need to check availability.
Examples
registry = get_registry_random() # Check availability before use if registry.is_registered('qrofn'): generator = registry.get_generator('qrofn') # Use generator... else: raise ValueError("QROFN generator not available")
- list_mtypes()[source]
Get a list of all registered mtypes.
Returns all currently registered fuzzy number type identifiers, useful for introspection and validation.
- Returns:
A sorted list of registered mtype identifiers. The list is a copy, so modifications don’t affect the registry.
- Return type:
list of str
Notes
The returned list is sorted for consistent ordering across calls and is safe to modify without affecting the registry.
Examples
registry = get_registry_random() # List all available types available_types = registry.list_mtypes() print("Available random generators:", available_types) # Check if specific types are available required_types = ['qrofn', 'ivfn'] missing = [t for t in required_types if t not in available_types] if missing: print(f"Missing generators: {missing}")
- register(mtype, generator)[source]
Register a random generator for a specific mtype.
Associates a generator instance with a fuzzy number type identifier, making it available for random generation requests. The generator must implement the BaseRandomGenerator interface.
- Parameters:
mtype (str) – The fuzzy number type identifier (e.g., ‘qrofn’, ‘ivfn’). Must be a non-empty string and unique within the registry.
generator (BaseRandomGenerator) – The generator instance to register. Must implement the BaseRandomGenerator interface with all required methods.
- Raises:
TypeError – If generator is not a BaseRandomGenerator instance.
ValueError – If mtype is empty, already registered, or if the generator’s mtype attribute doesn’t match the registration mtype.
Notes
- Return type:
None
This method validates that the generator’s mtype attribute matches the registration mtype parameter to prevent configuration errors.
Registration is thread-safe and atomic - either the generator is fully registered or not at all.
Examples
# Manual registration (typically not needed) generator = MyCustomGenerator() registry = get_registry_random() registry.register('mytype', generator) # Verify registration assert registry.is_registered('mytype') assert registry.get_generator('mytype') is generator
- unregister(mtype)[source]
Unregister a random generator for a specific mtype.
Removes the generator associated with the given mtype from the registry. After unregistration, requests for this mtype will return None.
- Parameters:
mtype (str) – The fuzzy number type identifier to unregister.
- Returns:
True if the generator was successfully unregistered, False if the mtype was not registered.
- Return type:
bool
Notes
This method is thread-safe and idempotent - multiple calls with the same mtype have no additional effect.
Unregistration is typically not needed in normal usage, as generators are usually registered once at module import time and persist for the application lifetime.
Examples
registry = get_registry_random() # Unregister a type success = registry.unregister('mytype') if success: print("Successfully unregistered mytype") else: print("mytype was not registered") # Verify unregistration assert not registry.is_registered('mytype')
- axisfuzzy.random.registry.get_generator(mtype)
Get the registered random generator for a specific mtype.
This is the primary function used by the random generation API to obtain the appropriate generator for a given fuzzy number type.
- Parameters:
mtype (str) – The fuzzy number type identifier.
- Returns:
The generator instance, or None if not registered.
- Return type:
BaseRandomGenerator or None
Examples
# Get a generator directly generator = get_random_generator('qrofn') if generator is not None: # Use the generator for custom generation rng = np.random.default_rng(42) custom_num = generator.fuzznum(rng, q=3, md_low=0.2) else: print("QROFN generator not available")
- axisfuzzy.random.registry.get_random_generator(mtype)[source]
Get the registered random generator for a specific mtype.
This is the primary function used by the random generation API to obtain the appropriate generator for a given fuzzy number type.
- Parameters:
mtype (str) – The fuzzy number type identifier.
- Returns:
The generator instance, or None if not registered.
- Return type:
BaseRandomGenerator or None
Examples
# Get a generator directly generator = get_random_generator('qrofn') if generator is not None: # Use the generator for custom generation rng = np.random.default_rng(42) custom_num = generator.fuzznum(rng, q=3, md_low=0.2) else: print("QROFN generator not available")
- axisfuzzy.random.registry.get_registry_random()[source]
Get the global random generator registry instance.
This function provides access to the singleton registry instance used throughout AxisFuzzy for managing random generators. It ensures that all parts of the library use the same registry instance.
- Returns:
The singleton registry instance.
- Return type:
Notes
This function is thread-safe and uses lazy initialization - the registry is created on first access. The same instance is returned on all subsequent calls.
Examples
# Get the global registry registry = get_registry_random() # Use registry methods generators = registry.list_mtypes() print(f"Available generators: {generators}") # Check for specific generator if 'qrofn' in registry: qrofn_gen = registry.get_generator('qrofn')
- axisfuzzy.random.registry.is_registered(mtype)
Check if a random generator is registered for the given mtype.
Provides a quick way to test generator availability without retrieving the actual generator instance.
- Parameters:
mtype (str) – The fuzzy number type identifier.
- Returns:
True if registered, False otherwise.
- Return type:
bool
Examples
# Check before using if is_registered_random('qrofn'): num = fr.rand('qrofn', q=2) else: raise ValueError("QROFN random generation not available") # Use in conditional logic supported_types = [t for t in ['qrofn', 'ivfn', 'pfn'] if is_registered_random(t)]
- axisfuzzy.random.registry.is_registered_random(mtype)[source]
Check if a random generator is registered for the given mtype.
Provides a quick way to test generator availability without retrieving the actual generator instance.
- Parameters:
mtype (str) – The fuzzy number type identifier.
- Returns:
True if registered, False otherwise.
- Return type:
bool
Examples
# Check before using if is_registered_random('qrofn'): num = fr.rand('qrofn', q=2) else: raise ValueError("QROFN random generation not available") # Use in conditional logic supported_types = [t for t in ['qrofn', 'ivfn', 'pfn'] if is_registered_random(t)]
- axisfuzzy.random.registry.list_registered()
Get a list of all registered mtypes.
Returns all currently available fuzzy number types that have registered random generators.
- Returns:
A sorted list of registered mtype identifiers.
- Return type:
list of str
Examples
# Check what generators are available available = list_registered_random() print("Available random generators:", available) # Use in validation def validate_mtype(mtype): if mtype not in available: raise ValueError(f"No generator for mtype '{mtype}'. " f"Available: {available}")
- axisfuzzy.random.registry.list_registered_random()[source]
Get a list of all registered mtypes.
Returns all currently available fuzzy number types that have registered random generators.
- Returns:
A sorted list of registered mtype identifiers.
- Return type:
list of str
Examples
# Check what generators are available available = list_registered_random() print("Available random generators:", available) # Use in validation def validate_mtype(mtype): if mtype not in available: raise ValueError(f"No generator for mtype '{mtype}'. " f"Available: {available}")
- axisfuzzy.random.registry.register_random(cls)[source]
A class decorator to register a random generator.
This decorator automatically instantiates the generator class and registers it with the global registry based on the class’s mtype attribute. This is the recommended way to register generators as it ensures they are available as soon as the module is imported.
- Parameters:
cls (type[BaseRandomGenerator]) – The generator class to register. Must be a subclass of BaseRandomGenerator and have a non-empty mtype class attribute.
- Returns:
The original class (unmodified) for continued use.
- Return type:
type[BaseRandomGenerator]
- Raises:
TypeError – If the class doesn’t have an mtype attribute or if the mtype is empty.
Notes
The decorator instantiates the class with no arguments, so generator classes should not require constructor parameters. All configuration should be handled through the parameter system.
The registration happens at decoration time (typically module import), making the generator immediately available for use.
Examples
Basic generator registration:
from axisfuzzy.random.base import ParameterizedRandomGenerator from axisfuzzy.random.registry import register_random @register_random class QROFNRandomGenerator(ParameterizedRandomGenerator): mtype = "qrofn" def get_default_parameters(self): return { 'md_dist': 'uniform', 'md_low': 0.0, 'md_high': 1.0, 'nu_mode': 'orthopair' } # ... other required methods
After decoration, the generator is immediately available:
import axisfuzzy.random as fr # Generator is now available for use num = fr.rand('qrofn', q=2) arr = fr.rand('qrofn', shape=(100,), q=3)
- axisfuzzy.random.registry.registry()
Get the global random generator registry instance.
This function provides access to the singleton registry instance used throughout AxisFuzzy for managing random generators. It ensures that all parts of the library use the same registry instance.
- Returns:
The singleton registry instance.
- Return type:
Notes
This function is thread-safe and uses lazy initialization - the registry is created on first access. The same instance is returned on all subsequent calls.
Examples
# Get the global registry registry = get_registry_random() # Use registry methods generators = registry.list_mtypes() print(f"Available generators: {generators}") # Check for specific generator if 'qrofn' in registry: qrofn_gen = registry.get_generator('qrofn')
- axisfuzzy.random.registry.unregister_random(mtype)[source]
Unregister a random generator for a specific mtype.
Removes the generator associated with the given mtype from the global registry. This is typically not needed in normal usage.
- Parameters:
mtype (str) – The fuzzy number type identifier to unregister.
- Returns:
True if successfully unregistered, False if the mtype was not registered.
- Return type:
bool
Examples
# Unregister a generator success = unregister_random('qrofn') if success: print("QROFN generator unregistered")