
from pprint import pprint
import random

import numpy as np

from amachine.am_create import random_machine, isomorphic_to, star_join

np.random.seed( 42 ) 
random.seed(    42 )

# May have multiple recurrent subgraphs, terminal states, or tranistory states
m = random_machine( 
	n_states=11, 
	symbols=[ '0', '1', '2' ],
	connectedness=0.61,
	randomness=0.37 )

# # Collapse to the largest recurrent subgraph
m.collapse_to_largest_strongly_connected_subgraph()

# # Minimize the machine -> epsilon-machine.
m.minimize()

# Create a new machine with label permutation
m_iso_1 = isomorphic_to( m, alphabet=[ '1', '2', '0' ] )

# Create a new machine with relabeled edges
m_iso_2 = isomorphic_to( m, alphabet=[ '3', '4', '5' ] )

# Create a new machine with relabeled edges
m_iso_3 = isomorphic_to( m, alphabet=[ '4', '5', '3' ] )

# Join them together in a star formaton
# Needs len(machines) enter symbols (symbols from central node to each machine)
m_star = star_join(
	exit_symbol='x', 
	enter_symbols=['a','b', 'c', 'd' ],
	machines=[ m, m_iso_1, m_iso_2, m_iso_3 ],
	mode_residency_factor=0.75 
)

#Entropy rate, and statistical complexity, and H_1 (uncertainty when ignorance of the past)
print( f"h_mu : {m_star.h_mu():.3f}" )
print( f"C_mu : {m_star.C_mu():.3f}" )
print( f"H_1 : {m_star.H_1():.3f}" )

# Draw the graph 
m_star.draw_graph( output_dir=".", show=True, engine='dot' )

