Source code for pyhdc.encodings.holographic

#!/usr/bin/env python
"""
Holographic Encodings for HDC

HDC-compatible wrapper for HRR and FHRR encodings.
"""

from functools import partial
from typing import Any, Callable, Optional

import numpy as np

from pyhdc.components.binding import (
    CircularConvolution,
    CircularCorrelation,
    ElementAngleAddition,
    ElementAngleSubtraction,
)
from pyhdc.components.bundling import (
    AnglesOfElementAddition,
    ElementAddition,
    ElementAdditionConstantNormalized,
    ElementAdditionNormalized,
)
from pyhdc.components.elements import NormalReal, UniformAngles
from pyhdc.components.similarity import AngleDistance, CosineSimilarity
from pyhdc.components.thinning import NoThin
from pyhdc.encodings.base import Encoding
from pyhdc.generation.base import HDCGenerator
from pyhdc.hypervector import EncodingSpec
from pyhdc.types import Backend, Device

# ============================================================================
# Holographic Encodings
# ============================================================================


[docs] class HRR(Encoding): """ Holographic Reduced Representation. Uses circular convolution for binding and normalized bundling. Args: random_choice_range: Optional float (rho). When set, coordinates whose |pre-norm sum| <= rho * sqrt(N) are replaced by independent N(0,1) draws before normalization (band randomization). """ def __init__( self, dimension: int = 10_000, backend: Optional[Backend] = None, device: Optional[Device] = None, dtype: Optional[Any] = None, mask: Optional[int] = None, generator: Optional[HDCGenerator] = None, similarity_remap: Optional[Callable] = None, random_choice_range: Optional[float] = None, ) -> None: self._random_choice_range = random_choice_range super().__init__( dimension, backend, device, dtype, mask, generator, similarity_remap ) def _get_encoding_spec(self) -> EncodingSpec: if self._random_choice_range is not None: bundling_fn = partial( ElementAdditionNormalized, random_choice_range=self._random_choice_range ) else: bundling_fn = ElementAdditionNormalized return EncodingSpec( dtype=np.float32, element_generator=NormalReal, similarity_fn=CosineSimilarity, bundling_fn=bundling_fn, thinning_fn=NoThin, binding_fn=CircularConvolution, unbinding_fn=CircularCorrelation, generator_output_type="floats", )
[docs] class HRR_NoNorm(Encoding): """HRR without normalized bundling.""" def _get_encoding_spec(self) -> EncodingSpec: return EncodingSpec( dtype=np.float32, element_generator=NormalReal, similarity_fn=CosineSimilarity, bundling_fn=ElementAddition, thinning_fn=NoThin, binding_fn=CircularConvolution, unbinding_fn=CircularCorrelation, generator_output_type="floats", )
[docs] class HRR_ConstNorm(Encoding): """HRR with constant normalization for bundling.""" def _get_encoding_spec(self) -> EncodingSpec: return EncodingSpec( dtype=np.float32, element_generator=NormalReal, similarity_fn=CosineSimilarity, bundling_fn=ElementAdditionConstantNormalized, thinning_fn=NoThin, binding_fn=CircularConvolution, unbinding_fn=CircularCorrelation, generator_output_type="floats", )
[docs] class FHRR(Encoding): """ Fourier Holographic Reduced Representation. Uses angular/phase representations with angle-based operations. Args: random_choice_range: Optional float (rho). When set, coordinates whose phasor magnitude <= rho * sqrt(N/2) are replaced by independent Uniform[-pi, pi] draws (band randomization). """ def __init__( self, dimension: int = 10_000, backend: Optional[Backend] = None, device: Optional[Device] = None, dtype: Optional[Any] = None, mask: Optional[int] = None, generator: Optional[HDCGenerator] = None, similarity_remap: Optional[Callable] = None, random_choice_range: Optional[float] = None, ) -> None: self._random_choice_range = random_choice_range super().__init__( dimension, backend, device, dtype, mask, generator, similarity_remap ) def _get_encoding_spec(self) -> EncodingSpec: if self._random_choice_range is not None: bundling_fn = partial( AnglesOfElementAddition, random_choice_range=self._random_choice_range ) else: bundling_fn = AnglesOfElementAddition return EncodingSpec( dtype=np.float32, element_generator=UniformAngles, similarity_fn=AngleDistance, bundling_fn=bundling_fn, thinning_fn=NoThin, binding_fn=ElementAngleAddition, unbinding_fn=ElementAngleSubtraction, generator_output_type="floats", )