GitLab Repo

amachine.am_create.am_disjoint_isomorphic

 1from amachine.am_id_generator import next_group_id
 2from ..am_hmm          import HMM
 3from ..am_vocabulary import Vocabulary
 4
 5from .am_random_machine import random_machine
 6from .am_isomorphic_to import isomorphic_to
 7from .am_star_composition import star_composition
 8
 9import numpy as np
10
11def disjoint_isomorphic(
12    n_components : int,
13    n_states : int,
14    n_base_symbols : int,
15    connectedness : float,
16    randomness : float,
17    star_joined : bool,
18    residency_factor : float = 0.75,
19    instances_per_component : int = 1,
20    np_rng : np.random.Generator | None = None ) -> HMM | list[HMM] :
21
22    base_symbol_pool  = Vocabulary.digits()      + Vocabulary.letters_lower()
23    enter_symbol_pool = Vocabulary.greek_lower() + Vocabulary.greek_upper()
24    exit_symbol = '*'
25
26    max_n_symbols = min( len(base_symbol_pool), len(enter_symbol_pool) )
27
28    if n_base_symbols*n_components > max_n_symbols :
29        raise ValueError( f"Only up to {len(base_symbol_pool)} base symbols supported" )
30
31    alphabets = [
32        base_symbol_pool[ start:start + n_base_symbols ]
33        for start in range( 0, n_base_symbols*n_components, n_base_symbols )
34    ]
35
36    enter_symbols = enter_symbol_pool[ 0:n_components ]
37
38    m = random_machine( 
39        n_states=n_states, 
40        symbols=alphabets[0], 
41        randomness=randomness,
42        connectedness=connectedness,
43        ensure_strongly_connected=True,
44        ensure_minimal=True,
45        np_rng=np_rng )
46
47    group_id = next_group_id()
48
49    machines = [ m ]
50    for i in range( 1, n_components ) :
51
52        alphabet = alphabets[ i ]
53        im = isomorphic_to( m, alphabet=alphabet.copy(), decorator=enter_symbols[ i ] )
54        machines.append( im )
55
56    for im in machines :
57        for state in im.states :
58            
59            # get the undecorated name
60            undecorated   = state.name[ 0:-1 ]
61            my_decoration = state.name[-1]
62
63            # capture decorated names of all isomorphic states
64            for a in enter_symbols :
65
66                # self not storing self as isomorph
67                if a == my_decoration :
68                    continue
69
70                decorated = undecorated + a
71                state.add_isomorph( decorated )
72
73    if star_joined :
74
75        final_machine = star_composition(  
76            exit_symbol=exit_symbol, 
77            enter_symbols=enter_symbols,
78            component_residency_factor=residency_factor,
79            component_groups={ group_id : machines },
80            instances_per_component=instances_per_component
81        )
82
83        if not final_machine.is_row_stochastic() :
84            raise Exception( "Disjoint isomorphic is not row stochastic" )
85
86        if not  final_machine.is_unifilar() :
87            raise Exception( "Disjoint isomorphic is not unifilar" )
88
89        return final_machine
90
91    else : 
92        return machines
def disjoint_isomorphic( n_components: int, n_states: int, n_base_symbols: int, connectedness: float, randomness: float, star_joined: bool, residency_factor: float = 0.75, instances_per_component: int = 1, np_rng: numpy.random._generator.Generator | None = None) -> amachine.am_hmm.HMM | list[amachine.am_hmm.HMM]:
12def disjoint_isomorphic(
13    n_components : int,
14    n_states : int,
15    n_base_symbols : int,
16    connectedness : float,
17    randomness : float,
18    star_joined : bool,
19    residency_factor : float = 0.75,
20    instances_per_component : int = 1,
21    np_rng : np.random.Generator | None = None ) -> HMM | list[HMM] :
22
23    base_symbol_pool  = Vocabulary.digits()      + Vocabulary.letters_lower()
24    enter_symbol_pool = Vocabulary.greek_lower() + Vocabulary.greek_upper()
25    exit_symbol = '*'
26
27    max_n_symbols = min( len(base_symbol_pool), len(enter_symbol_pool) )
28
29    if n_base_symbols*n_components > max_n_symbols :
30        raise ValueError( f"Only up to {len(base_symbol_pool)} base symbols supported" )
31
32    alphabets = [
33        base_symbol_pool[ start:start + n_base_symbols ]
34        for start in range( 0, n_base_symbols*n_components, n_base_symbols )
35    ]
36
37    enter_symbols = enter_symbol_pool[ 0:n_components ]
38
39    m = random_machine( 
40        n_states=n_states, 
41        symbols=alphabets[0], 
42        randomness=randomness,
43        connectedness=connectedness,
44        ensure_strongly_connected=True,
45        ensure_minimal=True,
46        np_rng=np_rng )
47
48    group_id = next_group_id()
49
50    machines = [ m ]
51    for i in range( 1, n_components ) :
52
53        alphabet = alphabets[ i ]
54        im = isomorphic_to( m, alphabet=alphabet.copy(), decorator=enter_symbols[ i ] )
55        machines.append( im )
56
57    for im in machines :
58        for state in im.states :
59            
60            # get the undecorated name
61            undecorated   = state.name[ 0:-1 ]
62            my_decoration = state.name[-1]
63
64            # capture decorated names of all isomorphic states
65            for a in enter_symbols :
66
67                # self not storing self as isomorph
68                if a == my_decoration :
69                    continue
70
71                decorated = undecorated + a
72                state.add_isomorph( decorated )
73
74    if star_joined :
75
76        final_machine = star_composition(  
77            exit_symbol=exit_symbol, 
78            enter_symbols=enter_symbols,
79            component_residency_factor=residency_factor,
80            component_groups={ group_id : machines },
81            instances_per_component=instances_per_component
82        )
83
84        if not final_machine.is_row_stochastic() :
85            raise Exception( "Disjoint isomorphic is not row stochastic" )
86
87        if not  final_machine.is_unifilar() :
88            raise Exception( "Disjoint isomorphic is not unifilar" )
89
90        return final_machine
91
92    else : 
93        return machines