#!/usr/bin/env python3
import sys, lzma, math, collections
path=sys.argv[1]
openf = lzma.open if path.endswith('.xz') else open
vars=clauses=0
cnf=[]
with openf(path,'rt') as f:
    for line in f:
        if not line or line[0]=='c': continue
        if line[0]=='p':
            parts=line.split(); vars=int(parts[2]); clauses=int(parts[3]); continue
        lits=list(map(int,line.split()))[:-1]
        if lits: cnf.append(lits)
pairs=vars//2
n=(1+math.isqrt(1+4*pairs))//2
print('vars clauses pairs n',vars,clauses,pairs,n)
# map id to ordered pair assuming row-major excluding diagonal
id_to_uv={}
uv_to_id={}
p=1
for u in range(n):
    for v in range(n):
        if u==v: continue
        id_to_uv[p]=(u,v); uv_to_id[(u,v)]=p; p+=1
binset=set(); trans=[]; pred=[]; types=collections.Counter(); blockcnt=collections.Counter()
seen=set()
for c in cnf:
    ids=tuple((abs(c[i])+1)//2 for i in range(0,len(c),2))
    sig=tuple('S' if (c[i]>0)==(c[i+1]>0) else 'D' for i in range(0,len(c),2))
    key=(ids,sig)
    # first clause per block-signature? Actually block has multiple same ids/sig? use ids only parent
    if ids in seen: continue
    seen.add(ids); types[sig]+=1
    if len(ids)==2: binset.add(ids)
    elif sig==('S','S','S'): pred.append(ids)
    else: trans.append(ids)
print('types', types)
print('pred count',len(pred))
for ids in pred[:20]: print('pred ids',ids,'uv',[id_to_uv.get(i) for i in ids])
# Validate trans mapping count examples
bad=0
for a,b,c in trans[:10000]:
    if a not in id_to_uv: continue
    u,v=id_to_uv[a]; v2,w=id_to_uv[b]; u2,w2=id_to_uv[c]
    if not (v==v2 and u==u2 and w==w2): bad+=1
print('trans rowmajor bad sample',bad)
print('pred graph incoming:')
for ids in pred:
    print(id_to_uv[ids[0]], id_to_uv[ids[1]], id_to_uv[ids[2]])
