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		)