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