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.base

Abstract base classes for generators

axisfuzzy.random.api

High-level API for random generation

axisfuzzy.fuzztype.qrofn.random

Example 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: object

Thread-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:

RandomGeneratorRegistry

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:

RandomGeneratorRegistry

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")