import lzma,glob,os,collections,itertools

def parse(fn):
 c=[]; n=0
 with lzma.open(fn,'rt') if fn.endswith('.xz') else open(fn) as f:
  for line in f:
   if line.startswith('p'):
    n=int(line.split()[2]); continue
   if line.startswith('c') or not line.strip(): continue
   a=list(map(int,line.split()))
   if a and a[-1]==0:a=a[:-1]
   if a:c.append(tuple(a))
 return n,c

def norm(cl): return tuple(sorted(cl, key=lambda x:(abs(x),x<0)))
for fn in glob.glob('/data/train/*.xz'):
 n,clauses=parse(fn); S=set(map(frozenset,clauses))
 bins=[c for c in clauses if len(c)==2]; ters=[c for c in clauses if len(c)==3]
 ands=[]
 # for ternary (sa*a, sb*b, sc*c) with one positive? Test all c, inputs
 for cvar in range(1,n+1):
  pass
 # detect gates from pair of binary clauses c->lit inputs: (-c or l1), (-c or l2) and (c or -l1 or -l2)
 bybin=collections.defaultdict(list)
 for a,b in bins:
  for x,y in [(a,b),(b,a)]:
   # clause (-c or l)
   if x<0: bybin[-x].append(y)
 for out, ins in bybin.items():
  for l1,l2 in itertools.combinations(ins,2):
   if frozenset((out,-l1,-l2)) in S:
    ands.append((out,l1,l2))
 print(os.path.basename(fn),'ands',len(ands),'sample',ands[:10])
 outs=collections.Counter(o for o,_,_ in ands); print('multi out',sum(1 for k,v in outs.items() if v>1), outs.most_common(5))
 defs=set(o for o,_,_ in ands); inputs=set(abs(l) for _,a,b in ands for l in (a,b))
 print('defined',len(defs),'undef used', len(inputs-defs), sorted(list(inputs-defs))[:40])
 # find 4-clause xor/xnor groups over triples
 tri_groups=collections.defaultdict(list)
 for cl in ters:
  key=tuple(sorted(abs(x) for x in cl))
  tri_groups[key].append(cl)
 xors=[]
 for key,cls in tri_groups.items():
  if len(cls)==4:
   signs=sorted(tuple(1 if next(x for x in cl if abs(x)==v)>0 else 0 for v in key) for cl in cls)
   # clause signs where literals true pattern prohibited? print common
   xors.append((key,signs))
 print('4cl groups',len(xors),'sign patterns',collections.Counter(tuple(s for ss in [signs] for s in ss) for key,signs in xors).most_common(3))
 print('sample xors', xors[:5])
