GitLab Repo

amachine.am_create.am_full_structured_isomorphic_rotation

  1from collections import defaultdict
  2import copy
  3import random
  4
  5import numpy as np
  6
  7from ..am_hmm          import HMM
  8from ..am_causal_state import CausalState
  9from ..am_transition   import Transition
 10
 11from ..am_random import exp_uniform_blend, resolve_rng
 12from ..am_vocabulary import Vocabulary
 13from ..am_structured_symbol_set import StructuredSymbolSet
 14
 15from .am_random_structured import random_structured
 16from .am_isomorphic_to_with_category_rotation import isomorphic_to_with_category_rotation
 17from .am_star_join import star_join
 18
 19def full_structured_isomorphic_rotation(
 20    isoclass_name : int,
 21    n_states : int,
 22    symbol_set : StructuredSymbolSet,
 23    connectedness : float,
 24    randomness : float,
 25    star_joined : bool,
 26    mode_residency_factor : float | None = None,
 27    existing_symbol_cohesion : np.ndarray | None = None,
 28    existing_symbol_categories : dict[str, int] | None = None,
 29    max_search_time : float = 120.0,
 30    n_search_workers = 3,
 31    random_seed : int | None = None
 32) -> HMM | list[HMM]:
 33
 34    if star_joined and mode_residency_factor is None :
 35        raise ValueError( "star_join requires mode_residency factor" )
 36
 37    m = random_structured(
 38        n_states=n_states,
 39        symbol_set=symbol_set,
 40        connectedness=connectedness,
 41        randomness=randomness,
 42        ensure_strongly_connected=True,
 43        ensure_minimal=True,
 44        max_search_time=max_search_time,
 45        n_search_workers=n_search_workers,
 46        random_seed=random_seed
 47    )
 48
 49    # Collapse to the largest recurrent subgraph
 50    m.collapse_to_largest_strongly_connected_subgraph()
 51
 52    # Minimize the machine -> epsilon-machine.
 53    m.minimize()
 54
 55    m.isoclass = isoclass_name
 56
 57    n_isomorphic = len( symbol_set.symbols ) // len( symbol_set.categories ) - 1
 58    m_isos = []
 59
 60    enter_symbol_pool = list( set( 
 61        Vocabulary.digits()
 62      + Vocabulary.letters_lower()
 63      + Vocabulary.letters_upper()
 64      + Vocabulary.greek_lower()
 65      + Vocabulary.greek_upper() ) - set( m.alphabet ) )
 66
 67    if len( enter_symbol_pool ) < n_isomorphic + 1 :
 68        raise ValueError( "Not enough symbols left over to construct star join." )
 69
 70    for i in range( 1, n_isomorphic+1 ) :
 71        
 72        m_iso = isomorphic_to_with_category_rotation(
 73            m=m,
 74            symbol_categories=symbol_set.symbol_categories,
 75            categories_to_rotate=symbol_set.categories,
 76            shift=i,
 77            decorator=f"@{i}" 
 78        )
 79
 80        m_iso.isoclass = isoclass_name
 81        m_isos.append( m_iso )
 82
 83    all_machines = [ m ] + m_isos
 84
 85    for ma in all_machines :
 86        for mb in all_machines :
 87            if ma != mb :
 88                for j, state in enumerate( ma.states ) : 
 89                    ma.states[ j ].add_isomorph( mb.states[ j ].name )
 90                    mb.states[ j ].add_isomorph( ma.states[ j ].name )
 91
 92    if star_joined :
 93
 94        # Join them together
 95        m_star = star_join(
 96            exit_symbol='x', 
 97            enter_symbols=enter_symbol_pool[ 0:len(all_machines) ],
 98            machines=all_machines,
 99            mode_residency_factor=mode_residency_factor 
100        )
101
102        return m_star
103    
104    else :
105        return all_machines
def full_structured_isomorphic_rotation( isoclass_name: int, n_states: int, symbol_set: amachine.am_structured_symbol_set.StructuredSymbolSet, connectedness: float, randomness: float, star_joined: bool, mode_residency_factor: float | None = None, existing_symbol_cohesion: numpy.ndarray | None = None, existing_symbol_categories: dict[str, int] | None = None, max_search_time: float = 120.0, n_search_workers=3, random_seed: int | None = None) -> amachine.am_hmm.HMM | list[amachine.am_hmm.HMM]:
 20def full_structured_isomorphic_rotation(
 21    isoclass_name : int,
 22    n_states : int,
 23    symbol_set : StructuredSymbolSet,
 24    connectedness : float,
 25    randomness : float,
 26    star_joined : bool,
 27    mode_residency_factor : float | None = None,
 28    existing_symbol_cohesion : np.ndarray | None = None,
 29    existing_symbol_categories : dict[str, int] | None = None,
 30    max_search_time : float = 120.0,
 31    n_search_workers = 3,
 32    random_seed : int | None = None
 33) -> HMM | list[HMM]:
 34
 35    if star_joined and mode_residency_factor is None :
 36        raise ValueError( "star_join requires mode_residency factor" )
 37
 38    m = random_structured(
 39        n_states=n_states,
 40        symbol_set=symbol_set,
 41        connectedness=connectedness,
 42        randomness=randomness,
 43        ensure_strongly_connected=True,
 44        ensure_minimal=True,
 45        max_search_time=max_search_time,
 46        n_search_workers=n_search_workers,
 47        random_seed=random_seed
 48    )
 49
 50    # Collapse to the largest recurrent subgraph
 51    m.collapse_to_largest_strongly_connected_subgraph()
 52
 53    # Minimize the machine -> epsilon-machine.
 54    m.minimize()
 55
 56    m.isoclass = isoclass_name
 57
 58    n_isomorphic = len( symbol_set.symbols ) // len( symbol_set.categories ) - 1
 59    m_isos = []
 60
 61    enter_symbol_pool = list( set( 
 62        Vocabulary.digits()
 63      + Vocabulary.letters_lower()
 64      + Vocabulary.letters_upper()
 65      + Vocabulary.greek_lower()
 66      + Vocabulary.greek_upper() ) - set( m.alphabet ) )
 67
 68    if len( enter_symbol_pool ) < n_isomorphic + 1 :
 69        raise ValueError( "Not enough symbols left over to construct star join." )
 70
 71    for i in range( 1, n_isomorphic+1 ) :
 72        
 73        m_iso = isomorphic_to_with_category_rotation(
 74            m=m,
 75            symbol_categories=symbol_set.symbol_categories,
 76            categories_to_rotate=symbol_set.categories,
 77            shift=i,
 78            decorator=f"@{i}" 
 79        )
 80
 81        m_iso.isoclass = isoclass_name
 82        m_isos.append( m_iso )
 83
 84    all_machines = [ m ] + m_isos
 85
 86    for ma in all_machines :
 87        for mb in all_machines :
 88            if ma != mb :
 89                for j, state in enumerate( ma.states ) : 
 90                    ma.states[ j ].add_isomorph( mb.states[ j ].name )
 91                    mb.states[ j ].add_isomorph( ma.states[ j ].name )
 92
 93    if star_joined :
 94
 95        # Join them together
 96        m_star = star_join(
 97            exit_symbol='x', 
 98            enter_symbols=enter_symbol_pool[ 0:len(all_machines) ],
 99            machines=all_machines,
100            mode_residency_factor=mode_residency_factor 
101        )
102
103        return m_star
104    
105    else :
106        return all_machines