GitLab Repo

amachine.am_generator

  1import random
  2import numpy as np
  3import matplotlib.pyplot as plt
  4from pathlib import Path
  5from copy import deepcopy
  6
  7from .am_create import star, star_join, isomorphic_to
  8import random
  9
 10class Generator :
 11
 12    def __init__(self, random_seed=None ) -> None :
 13        
 14        if random_seed :
 15        
 16            np.random.seed( random_seed ) 
 17            random.seed( random_seed )
 18
 19        self.vocabulary = { 
 20            
 21            # 1. Printable ASCII: space (32) through tilde (126) → 95 chars
 22            "ASCII" : [chr(i) for i in range(32, 127)],
 23
 24            # 2. Greek capitals Α–Τ (19), skipping U+03A2 (undefined slot)
 25            "greek_upper" : [chr(i) for i in range(0x0391, 0x03A5) if i != 0x03A2][:19],
 26
 27            # 3. Greek smalls α–τ (19), skipping U+03C2 (ς, final-sigma variant)
 28            "greek_lower" : [chr(i) for i in range(0x03B1, 0x03C5) if i != 0x03C2][:19],
 29
 30            # 4. Geometric Shapes block: U+25A0–U+25FF → 96 chars
 31            "geometric" : [chr(i) for i in range(0x25A0, 0x2600)]
 32        }
 33
 34        self.exit_symbol = self.vocabulary[ "geometric" ][ 0 ]
 35
 36    def generate( 
 37        self, n_states : int, 
 38        n_symbols, 
 39        n_modes : int,
 40        mode_alphas : list[float],
 41        residency_factor : float,
 42        levels : int ) :
 43        
 44        # 0-9 ASCII + lowercase letters + uppercase letters
 45        normal_symbols  = [ chr(i) for i in range( 48,  58 ) ]
 46        normal_symbols += [ chr(i) for i in range( 97, 123 ) ]
 47        normal_symbols += [ chr(i) for i in range( 65,  91 ) ]
 48        enter_symbols = self.vocabulary[ "greek_lower" ] + self.vocabulary[ "greek_upper" ]
 49
 50        n_gen = n_modes*2
 51
 52        # n_gen^levels leaves
 53        machines = [
 54            star(
 55                exit_symbol=self.exit_symbol,
 56                enter_symbols=enter_symbols[ 0:n_modes*2 ],
 57                normal_symbols=normal_symbols,
 58                n_modes=n_modes,
 59                n_isomorphic=2,
 60                randomness=0.3,
 61                connectedness=0.5,
 62                residency_factor=residency_factor,
 63                n_normal_symbols=n_symbols,
 64                t_states_per_machine=n_states
 65            )
 66            for i in range( n_gen**levels )
 67        ]
 68
 69        es_per_lev = n_gen
 70        es_offset = n_modes*2
 71
 72        # Reduce bottom-up, levels-1 times
 73        for i in range( levels - 1 ) :
 74            next_level = []
 75            x = 0
 76
 77            es = enter_symbols[ es_offset + es_per_lev*i : es_offset+es_per_lev*(i+1) ]
 78
 79            for k in range( len(machines) // n_gen ) :  # shrinks each pass
 80                m = star_join(
 81                    exit_symbol=self.exit_symbol,
 82                    enter_symbols=es,
 83                    machines=machines[ x:x+n_gen ],
 84                    mode_residency_factor=0.5
 85                )
 86                next_level.append( m )
 87                x += n_gen
 88            machines = deepcopy( next_level )
 89
 90        # machines now has exactly n_gen elements — join into root
 91        return star_join(
 92            exit_symbol=self.exit_symbol,
 93            enter_symbols=normal_symbols,
 94            machines=machines,
 95            mode_residency_factor=0.5
 96        )
 97
 98if __name__ == "__main__":
 99
100    n_modes = 1
101    alpha = 0.3
102    residency_factor = 0.5
103    n_symbols = 4
104    n_states = 27
105    random_seed=42
106
107    generator = Generator( random_seed=random_seed )
108
109    path = Path("../data/aM_7-mode-iso" )
110    path.mkdir(parents=True, exist_ok=True)
111
112    aM = generator.generate( 
113        n_states=n_states, 
114        n_symbols=n_symbols, 
115        n_modes=n_modes, 
116        mode_alphas=[ alpha ]*n_modes,
117        residency_factor=residency_factor,
118        levels=3 )
119
120    aM.minimize(retain_names=True)
121    print( aM.is_epsilon_HMM() )
122
123    aM.draw_graph()
124
125    print( f"h_mu : {aM.h_mu()}" )
126    print( f"C_mu : {aM.C_mu()}" )
class Generator:
11class Generator :
12
13    def __init__(self, random_seed=None ) -> None :
14        
15        if random_seed :
16        
17            np.random.seed( random_seed ) 
18            random.seed( random_seed )
19
20        self.vocabulary = { 
21            
22            # 1. Printable ASCII: space (32) through tilde (126) → 95 chars
23            "ASCII" : [chr(i) for i in range(32, 127)],
24
25            # 2. Greek capitals Α–Τ (19), skipping U+03A2 (undefined slot)
26            "greek_upper" : [chr(i) for i in range(0x0391, 0x03A5) if i != 0x03A2][:19],
27
28            # 3. Greek smalls α–τ (19), skipping U+03C2 (ς, final-sigma variant)
29            "greek_lower" : [chr(i) for i in range(0x03B1, 0x03C5) if i != 0x03C2][:19],
30
31            # 4. Geometric Shapes block: U+25A0–U+25FF → 96 chars
32            "geometric" : [chr(i) for i in range(0x25A0, 0x2600)]
33        }
34
35        self.exit_symbol = self.vocabulary[ "geometric" ][ 0 ]
36
37    def generate( 
38        self, n_states : int, 
39        n_symbols, 
40        n_modes : int,
41        mode_alphas : list[float],
42        residency_factor : float,
43        levels : int ) :
44        
45        # 0-9 ASCII + lowercase letters + uppercase letters
46        normal_symbols  = [ chr(i) for i in range( 48,  58 ) ]
47        normal_symbols += [ chr(i) for i in range( 97, 123 ) ]
48        normal_symbols += [ chr(i) for i in range( 65,  91 ) ]
49        enter_symbols = self.vocabulary[ "greek_lower" ] + self.vocabulary[ "greek_upper" ]
50
51        n_gen = n_modes*2
52
53        # n_gen^levels leaves
54        machines = [
55            star(
56                exit_symbol=self.exit_symbol,
57                enter_symbols=enter_symbols[ 0:n_modes*2 ],
58                normal_symbols=normal_symbols,
59                n_modes=n_modes,
60                n_isomorphic=2,
61                randomness=0.3,
62                connectedness=0.5,
63                residency_factor=residency_factor,
64                n_normal_symbols=n_symbols,
65                t_states_per_machine=n_states
66            )
67            for i in range( n_gen**levels )
68        ]
69
70        es_per_lev = n_gen
71        es_offset = n_modes*2
72
73        # Reduce bottom-up, levels-1 times
74        for i in range( levels - 1 ) :
75            next_level = []
76            x = 0
77
78            es = enter_symbols[ es_offset + es_per_lev*i : es_offset+es_per_lev*(i+1) ]
79
80            for k in range( len(machines) // n_gen ) :  # shrinks each pass
81                m = star_join(
82                    exit_symbol=self.exit_symbol,
83                    enter_symbols=es,
84                    machines=machines[ x:x+n_gen ],
85                    mode_residency_factor=0.5
86                )
87                next_level.append( m )
88                x += n_gen
89            machines = deepcopy( next_level )
90
91        # machines now has exactly n_gen elements — join into root
92        return star_join(
93            exit_symbol=self.exit_symbol,
94            enter_symbols=normal_symbols,
95            machines=machines,
96            mode_residency_factor=0.5
97        )
Generator(random_seed=None)
13    def __init__(self, random_seed=None ) -> None :
14        
15        if random_seed :
16        
17            np.random.seed( random_seed ) 
18            random.seed( random_seed )
19
20        self.vocabulary = { 
21            
22            # 1. Printable ASCII: space (32) through tilde (126) → 95 chars
23            "ASCII" : [chr(i) for i in range(32, 127)],
24
25            # 2. Greek capitals Α–Τ (19), skipping U+03A2 (undefined slot)
26            "greek_upper" : [chr(i) for i in range(0x0391, 0x03A5) if i != 0x03A2][:19],
27
28            # 3. Greek smalls α–τ (19), skipping U+03C2 (ς, final-sigma variant)
29            "greek_lower" : [chr(i) for i in range(0x03B1, 0x03C5) if i != 0x03C2][:19],
30
31            # 4. Geometric Shapes block: U+25A0–U+25FF → 96 chars
32            "geometric" : [chr(i) for i in range(0x25A0, 0x2600)]
33        }
34
35        self.exit_symbol = self.vocabulary[ "geometric" ][ 0 ]
vocabulary
exit_symbol
def generate( self, n_states: int, n_symbols, n_modes: int, mode_alphas: list[float], residency_factor: float, levels: int):
37    def generate( 
38        self, n_states : int, 
39        n_symbols, 
40        n_modes : int,
41        mode_alphas : list[float],
42        residency_factor : float,
43        levels : int ) :
44        
45        # 0-9 ASCII + lowercase letters + uppercase letters
46        normal_symbols  = [ chr(i) for i in range( 48,  58 ) ]
47        normal_symbols += [ chr(i) for i in range( 97, 123 ) ]
48        normal_symbols += [ chr(i) for i in range( 65,  91 ) ]
49        enter_symbols = self.vocabulary[ "greek_lower" ] + self.vocabulary[ "greek_upper" ]
50
51        n_gen = n_modes*2
52
53        # n_gen^levels leaves
54        machines = [
55            star(
56                exit_symbol=self.exit_symbol,
57                enter_symbols=enter_symbols[ 0:n_modes*2 ],
58                normal_symbols=normal_symbols,
59                n_modes=n_modes,
60                n_isomorphic=2,
61                randomness=0.3,
62                connectedness=0.5,
63                residency_factor=residency_factor,
64                n_normal_symbols=n_symbols,
65                t_states_per_machine=n_states
66            )
67            for i in range( n_gen**levels )
68        ]
69
70        es_per_lev = n_gen
71        es_offset = n_modes*2
72
73        # Reduce bottom-up, levels-1 times
74        for i in range( levels - 1 ) :
75            next_level = []
76            x = 0
77
78            es = enter_symbols[ es_offset + es_per_lev*i : es_offset+es_per_lev*(i+1) ]
79
80            for k in range( len(machines) // n_gen ) :  # shrinks each pass
81                m = star_join(
82                    exit_symbol=self.exit_symbol,
83                    enter_symbols=es,
84                    machines=machines[ x:x+n_gen ],
85                    mode_residency_factor=0.5
86                )
87                next_level.append( m )
88                x += n_gen
89            machines = deepcopy( next_level )
90
91        # machines now has exactly n_gen elements — join into root
92        return star_join(
93            exit_symbol=self.exit_symbol,
94            enter_symbols=normal_symbols,
95            machines=machines,
96            mode_residency_factor=0.5
97        )