
    i              	       B   d Z ddlZddlZddlZddlZ	 ddlZdZn# e$ r dZY nw xY w ej	        e
          Zdej        z  Zd!dZd"d	ed
eddfdZd#dZd$dZd%dZdddddefdZd"ded
eddfdZd"dedee         d
eddfdZdddefdZdeddfdZd
ededefd ZdS )&u  Holographic Reduced Representations (HRR) with phase encoding.

HRRs are a vector symbolic architecture for encoding compositional structure
into fixed-width distributed representations. This module uses *phase vectors*:
each concept is a vector of angles in [0, 2π). The algebraic operations are:

  bind   — circular convolution (phase addition)  — associates two concepts
  unbind — circular correlation (phase subtraction) — retrieves a bound value
  bundle — superposition (circular mean)           — merges multiple concepts

Phase encoding is numerically stable, avoids the magnitude collapse of
traditional complex-number HRRs, and maps cleanly to cosine similarity.

Atoms are generated deterministically from SHA-256 so representations are
identical across processes, machines, and language versions.

References:
  Plate (1995) — Holographic Reduced Representations
  Gayler (2004) — Vector Symbolic Architectures answer Jackendoff's challenges
    NTF       @returnc                  2    t           st          d          d S )Nz,numpy is required for holographic operations)
_HAS_NUMPYRuntimeError     K/home/piyush/.hermes/hermes-agent/plugins/memory/holographic/holographic.py_require_numpyr   &   s&     KIJJJK Kr	      worddim
np.ndarrayc                    t                       d}t          j        ||z            }g }t          |          D ]g}t	          j        |  d|                                                                           }|                    t          j
        d|                     ht          j        |d|         t          j                  t          dz  z  }|S )u  Deterministic phase vector via SHA-256 counter blocks.

    Uses hashlib (not numpy RNG) for cross-platform reproducibility.

    Algorithm:
    - Generate enough SHA-256 blocks by hashing f"{word}:{i}" for i=0,1,2,...
    - Concatenate digests, interpret as uint16 values via struct.unpack
    - Scale to [0, 2π): phases = values * (2π / 65536)
    - Truncate to dim elements
    - Returns np.float64 array of shape (dim,)
       :z<16HNdtypeg      @)r   mathceilrangehashlibsha256encodedigestextendstructunpacknparrayfloat64_TWO_PI)r   r   values_per_blockblocks_neededuint16_valuesir   phasess           r
   encode_atomr(   +   s      Ic$4455M!M=!! < <4! 4 4 6 677>>@@V]66::;;;;XmDSD)<<<'@QRFMr	   abc                 8    t                       | |z   t          z  S )zCircular convolution = element-wise phase addition.

    Binding associates two concepts into a single composite vector.
    The result is dissimilar to both inputs (quasi-orthogonal).
    r   r"   r)   r*   s     r
   bindr.   F   s     EWr	   memorykeyc                 8    t                       | |z
  t          z  S )u   Circular correlation = element-wise phase subtraction.

    Unbinding retrieves the value associated with a key from a memory vector.
    unbind(bind(a, b), a) ≈ b  (up to superposition noise)
    r,   )r/   r0   s     r
   unbindr2   P   s     SLG##r	   vectorsc                      t                       t          j        d | D             d          }t          j        |          t          z  S )zSuperposition via circular mean of complex exponentials.

    Bundling merges multiple vectors into one that is similar to each input.
    The result can hold O(sqrt(dim)) items before similarity degrades.
    c                 <    g | ]}t          j        d |z            S )y              ?)r   exp).0vs     r
   
<listcomp>zbundle.<locals>.<listcomp>a   s$    :::Q"&a..:::r	   r   )axis)r   r   sumangler"   )r3   complex_sums     r
   bundler>   Z   sH     &::':::CCCK8K  7**r	   c                     t                       t          t          j        t          j        | |z
                                S )zPhase cosine similarity. Range [-1, 1].

    Returns 1.0 for identical vectors, near 0.0 for random (unrelated) vectors,
    and -1.0 for perfectly anti-correlated vectors.
    )r   floatr   meancosr-   s     r
   
similarityrC   e   s4     A''(((r	   textc                     t                       d |                                                                 D             }d |D             }|st          d          S fd|D             }t	          | S )a7  Bag-of-words: bundle of atom vectors for each token.

    Tokenizes by lowercasing, splitting on whitespace, and stripping
    leading/trailing punctuation from each token.

    Returns bundle of all token atom vectors.
    If text is empty or produces no tokens, returns encode_atom("__hrr_empty__", dim).
    c                 8    g | ]}|                     d           S )z.,!?;:"'()[]{})strip)r7   tokens     r
   r9   zencode_text.<locals>.<listcomp>z   s5        	%&&  r	   c                     g | ]}||S r   r   )r7   ts     r
   r9   zencode_text.<locals>.<listcomp>~   s    %%%A1%a%%%r	   __hrr_empty__c                 0    g | ]}t          |          S r   )r(   )r7   rH   r   s     r
   r9   zencode_text.<locals>.<listcomp>   s#    @@@Ks++@@@r	   )r   lowersplitr(   r>   )rD   r   tokensatom_vectorss    `  r
   encode_textrQ   o   s      ZZ\\''))  F &%%%%F 1?C000@@@@@@@L<  r	   contententitiesc           	      >   t                       t          d|          }t          d|          }t          t          | |          |          g}|D ]E}|                    t          t          |                                |          |                     Ft          | S )u  Structured encoding: content bound to ROLE_CONTENT, each entity bound to ROLE_ENTITY, all bundled.

    Role vectors are reserved atoms: "__hrr_role_content__", "__hrr_role_entity__"

    Components:
    1. bind(encode_text(content, dim), encode_atom("__hrr_role_content__", dim))
    2. For each entity: bind(encode_atom(entity.lower(), dim), encode_atom("__hrr_role_entity__", dim))
    3. bundle all components together

    This enables algebraic extraction:
        unbind(fact, bind(entity, ROLE_ENTITY)) ≈ content_vector
    __hrr_role_content____hrr_role_entity__)r   r(   r.   rQ   appendrM   r>   )rR   rS   r   role_contentrole_entity
componentsentitys          r
   encode_factr\      s     5s;;L3S99K 	[#&&55$J  O O${6<<>>3??MMNNNN:r	   r'   c                 F    t                       |                                 S )uF   Serialize phase vector to bytes. float64 tobytes — 8 KB at dim=1024.)r   tobytes)r'   s    r
   phases_to_bytesr_      s    >>r	   datac                     t                       t          j        | t          j                                                  S )zDeserialize bytes back to phase vector. Inverse of phases_to_bytes.

    The .copy() call is required because frombuffer returns a read-only view
    backed by the bytes object; callers expect a mutable array.
    r   )r   r   
frombufferr!   copy)r`   s    r
   bytes_to_phasesrd      s3     =RZ00055777r	   n_itemsc                     t                       |dk    rt          d          S t          j        | |z            }|dk     rt                              d|| |           |S )a  Signal-to-noise ratio estimate for holographic storage.

    SNR = sqrt(dim / n_items) when n_items > 0, else inf.

    The SNR falls below 2.0 when n_items > dim / 4, meaning retrieval
    errors become likely. Logs a warning when this threshold is crossed.
    r   infr   zHRR storage near capacity: SNR=%.2f (dim=%d, n_items=%d). Retrieval accuracy may degrade. Consider increasing dim or reducing stored items.)r   r@   r   sqrtloggerwarning)r   re   snrs      r
   snr_estimaterl      sm     !||U||
)C'M
"
"C
Syy`	
 	
 	
 Jr	   )r   N)r   )r)   r   r*   r   r   r   )r/   r   r0   r   r   r   )r3   r   r   r   )__doc__r   loggingr   r   numpyr   r   ImportError	getLogger__name__ri   pir"   r   strintr(   r.   r2   r>   r@   rC   rQ   listr\   bytesr_   rd   rl   r   r	   r
   <module>rx      s   *    JJ   JJJ 
	8	$	$
-K K K K
 c  |    6   $ $ $ $+ + + +), )< )E ) ) ) )! !c ! !| ! ! ! !0  S	  |    8L U    8% 8L 8 8 8 8c C E      s    %%