#!/usr/bin/env python3
import lzma
import sys
from collections import Counter
from pathlib import Path


def aux_count(n, k):
    return sum(min(i, k) + 1 for i in range(1, n + 1))


def parse(path):
    opener = lzma.open if str(path).endswith(".xz") else open
    vars_n = clauses_n = None
    clauses = []
    cur = []
    with opener(path, "rt") as f:
        for line in f:
            if not line or line[0] == "c":
                continue
            if line[0] == "p":
                parts = line.split()
                vars_n = int(parts[2])
                clauses_n = int(parts[3])
                continue
            for tok in line.split():
                lit = int(tok)
                if lit == 0:
                    if cur:
                        clauses.append(cur)
                        cur = []
                else:
                    cur.append(lit)
    return vars_n, clauses_n, clauses


def infer_n_k(vars_n, clauses):
    max_clause = max(len(c) for c in clauses)
    k = max_clause - 1
    n = None
    for cand in range(k, min(vars_n, 5000) + 1):
        if vars_n - cand == aux_count(cand, k):
            n = cand
            break
    return n, k


def main(paths):
    for raw in paths:
        path = Path(raw)
        vars_n, clauses_decl, clauses = parse(path)
        n, k = infer_n_k(vars_n, clauses)
        sizes = Counter(map(len, clauses))
        pos = neg = 0
        edge_count = 0
        deg = [0] * (n or 0)
        if n:
            seen = set()
            for c in clauses:
                for lit in c:
                    if lit > 0:
                        pos += 1
                    else:
                        neg += 1
                if len(c) == 2 and c[0] < 0 and c[1] < 0 and abs(c[0]) <= n and abs(c[1]) <= n:
                    a, b = abs(c[0]) - 1, abs(c[1]) - 1
                    if a != b:
                        key = (min(a, b), max(a, b))
                        if key not in seen:
                            seen.add(key)
                            edge_count += 1
                            deg[a] += 1
                            deg[b] += 1
        name = path.name
        print(f"{name}\tvars={vars_n}\tclauses={len(clauses)}/{clauses_decl}\tN={n}\tK={k}\tedges={edge_count}")
        print("  sizes", " ".join(f"{s}:{sizes[s]}" for s in sorted(sizes)))
        if n:
            print(f"  degree min={min(deg)} max={max(deg)} avg={sum(deg)/n:.2f} pos={pos} neg={neg}")


if __name__ == "__main__":
    main(sys.argv[1:])
