amachine.am_create.am_isomorphic_to_with_category_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 13 14def isomorphic_to_with_category_rotation( 15 m : HMM, 16 symbol_categories : dict[ str, int ], 17 categories_shifts : int | dict[ int, int ], 18 decorator : str ) -> HMM : 19 20 if ( not isinstance( categories_shifts, int ) and 21 set( categories_shifts.keys() ) != set( symbol_categories.values() ) 22 ) : 23 raise ValueError( "set( categories_shifts.keys() ) != set( symbol_categories.values() )" ) 24 25 alphabet = m.alphabet.copy() 26 27 states = [ 28 CausalState( 29 name=f"{s.name}{decorator}", 30 classes=s.classes.copy() 31 ) 32 for s in m.states 33 ] 34 35 s_cats = {} 36 for c in set( symbol_categories.values() ) : 37 s_cats[ c ] = sorted( [ 38 y for y in alphabet 39 if y in symbol_categories and symbol_categories[y] == c 40 ] ) 41 42 transitions = [] 43 for tr in m.transitions : 44 45 s = alphabet[ tr.symbol_idx ] 46 c = symbol_categories[ s ] 47 48 should_shift = ( 49 s in symbol_categories and ( 50 ( isinstance( categories_shifts, int ) and categories_shifts > 0 ) 51 or 52 ( not isinstance( categories_shifts, int ) 53 and categories_shifts[ symbol_categories[ s ] ] > 0 ) 54 ) 55 ) 56 57 # if the symbol has a category and we should rotate it 58 if should_shift : 59 60 # get the sorted list of symbols in the same category 61 category = symbol_categories[ s ] 62 s_cat = s_cats[ category ] 63 shift = ( 64 categories_shifts if isinstance( categories_shifts, int ) 65 else categories_shifts[ category ] 66 ) 67 68 # shift the symbol witin the category 69 sc_idx = ( s_cat.index( s ) + shift ) % len( s_cat ) 70 new_s = s_cat[ sc_idx ] 71 new_symbol_idx = m.symbol_idx_map[ new_s ] 72 73 # same transition but with different symbol 74 transitions.append( 75 Transition( 76 origin_state_idx=tr.origin_state_idx, 77 target_state_idx=tr.target_state_idx, 78 prob=tr.prob, 79 symbol_idx=new_symbol_idx, 80 pq=tr.pq, 81 cross_component=tr.cross_component 82 ) 83 ) 84 85 else : 86 transitions.append( copy.deepcopy( tr ) ) 87 88 return HMM( 89 states=states, 90 transitions=transitions, 91 start_state=0, 92 alphabet=alphabet 93 )
def
isomorphic_to_with_category_rotation( m: amachine.am_hmm.HMM, symbol_categories: dict[str, int], categories_shifts: int | dict[int, int], decorator: str) -> amachine.am_hmm.HMM:
15def isomorphic_to_with_category_rotation( 16 m : HMM, 17 symbol_categories : dict[ str, int ], 18 categories_shifts : int | dict[ int, int ], 19 decorator : str ) -> HMM : 20 21 if ( not isinstance( categories_shifts, int ) and 22 set( categories_shifts.keys() ) != set( symbol_categories.values() ) 23 ) : 24 raise ValueError( "set( categories_shifts.keys() ) != set( symbol_categories.values() )" ) 25 26 alphabet = m.alphabet.copy() 27 28 states = [ 29 CausalState( 30 name=f"{s.name}{decorator}", 31 classes=s.classes.copy() 32 ) 33 for s in m.states 34 ] 35 36 s_cats = {} 37 for c in set( symbol_categories.values() ) : 38 s_cats[ c ] = sorted( [ 39 y for y in alphabet 40 if y in symbol_categories and symbol_categories[y] == c 41 ] ) 42 43 transitions = [] 44 for tr in m.transitions : 45 46 s = alphabet[ tr.symbol_idx ] 47 c = symbol_categories[ s ] 48 49 should_shift = ( 50 s in symbol_categories and ( 51 ( isinstance( categories_shifts, int ) and categories_shifts > 0 ) 52 or 53 ( not isinstance( categories_shifts, int ) 54 and categories_shifts[ symbol_categories[ s ] ] > 0 ) 55 ) 56 ) 57 58 # if the symbol has a category and we should rotate it 59 if should_shift : 60 61 # get the sorted list of symbols in the same category 62 category = symbol_categories[ s ] 63 s_cat = s_cats[ category ] 64 shift = ( 65 categories_shifts if isinstance( categories_shifts, int ) 66 else categories_shifts[ category ] 67 ) 68 69 # shift the symbol witin the category 70 sc_idx = ( s_cat.index( s ) + shift ) % len( s_cat ) 71 new_s = s_cat[ sc_idx ] 72 new_symbol_idx = m.symbol_idx_map[ new_s ] 73 74 # same transition but with different symbol 75 transitions.append( 76 Transition( 77 origin_state_idx=tr.origin_state_idx, 78 target_state_idx=tr.target_state_idx, 79 prob=tr.prob, 80 symbol_idx=new_symbol_idx, 81 pq=tr.pq, 82 cross_component=tr.cross_component 83 ) 84 ) 85 86 else : 87 transitions.append( copy.deepcopy( tr ) ) 88 89 return HMM( 90 states=states, 91 transitions=transitions, 92 start_state=0, 93 alphabet=alphabet 94 )