#include <algorithm>
#include <cassert>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <limits>
#include <queue>
#include <string>
#include <utility>
#include <vector>

namespace {

using Clock = std::chrono::steady_clock;

struct FastInput {
    static constexpr size_t BUFSZ = 1 << 20;
    FILE* f = nullptr;
    std::vector<char> buf;
    size_t pos = 0, len = 0;

    explicit FastInput(const char* path) : f(std::fopen(path, "rb")), buf(BUFSZ) {}
    ~FastInput() {
        if (f) std::fclose(f);
    }
    bool ok() const { return f != nullptr; }
    int get() {
        if (pos >= len) {
            len = std::fread(buf.data(), 1, buf.size(), f);
            pos = 0;
            if (len == 0) return EOF;
        }
        return buf[pos++];
    }
    int peek() {
        int c = get();
        if (c != EOF) --pos;
        return c;
    }
    void skip_line() {
        int c;
        while ((c = get()) != EOF && c != '\n') {}
    }
    bool read_word(std::string& out) {
        out.clear();
        int c;
        do {
            c = get();
            if (c == EOF) return false;
        } while (c <= ' ');
        do {
            out.push_back(static_cast<char>(c));
            c = get();
        } while (c != EOF && c > ' ');
        return true;
    }
    bool read_int(int& out) {
        int c;
        do {
            c = get();
            if (c == EOF) return false;
        } while (c <= ' ');
        int sign = 1;
        if (c == '-') {
            sign = -1;
            c = get();
        }
        int x = 0;
        while (c > ' ') {
            x = x * 10 + (c - '0');
            c = get();
        }
        out = sign * x;
        return true;
    }
};

struct ProofWriter {
    FILE* f = nullptr;
    std::vector<char> buf;
    bool failed = false;

    explicit ProofWriter(const char* path) : f(std::fopen(path, "wb")), buf(1 << 20) {
        if (f) {
            std::setvbuf(f, buf.data(), _IOFBF, buf.size());
            write_raw("pseudo-Boolean proof version 3.0\n");
        } else {
            failed = true;
        }
    }
    ~ProofWriter() {
        if (f) std::fclose(f);
    }
    void write_raw(const char* s) {
        if (failed) return;
        if (std::fputs(s, f) < 0) failed = true;
    }
    void write_lit(int lit) {
        if (failed) return;
        if (lit > 0) {
            std::fprintf(f, "1 x%d ", lit);
        } else {
            std::fprintf(f, "1 ~x%d ", -lit);
        }
    }
    void rup_clause(const std::vector<int>& clause) {
        if (failed) return;
        std::fputs("rup ", f);
        for (int lit : clause) write_lit(lit);
        std::fputs(">= 1 ;\n", f);
    }
    void rup_empty() {
        if (failed) return;
        std::fputs("rup >= 1 ;\n", f);
    }
    void del_id(uint64_t id) {
        if (failed) return;
        std::fprintf(f, "del id %llu ;\n", static_cast<unsigned long long>(id));
    }
    void finish_unsat() {
        if (failed) return;
        std::fputs("output NONE ;\nconclusion UNSAT : -1 ;\nend pseudo-Boolean proof ;\n", f);
        if (std::fflush(f) != 0) failed = true;
    }
};

struct Clause {
    uint32_t start = 0;
    uint32_t size = 0;
    uint32_t lbd = 0;
    uint64_t proof_id = 0;
    bool learnt = false;
    bool deleted = false;
};

struct Solver {
    enum Result { SAT, UNSAT, UNKNOWN };

    int nvars = 0;
    int declared_clauses = 0;
    std::vector<int> lits;
    std::vector<Clause> clauses;
    std::vector<std::vector<int>> watches;

    std::vector<int8_t> assigns;      // 0 unassigned, 1 true, -1 false
    std::vector<int> levels;
    std::vector<int> reasons;
    std::vector<int> trail;
    std::vector<int> trail_lim;
    size_t qhead = 0;

    std::vector<double> activity;
    std::vector<int> heap;
    std::vector<int> heap_pos;
    std::vector<int> polarity_score;
    std::vector<int8_t> saved_phase;
    std::vector<uint32_t> seen_stamp;
    std::vector<uint32_t> lbd_stamp;
    uint32_t stamp = 1;
    uint32_t lbd_counter = 1;
    double var_inc = 1.0;
    double var_decay = 0.95;
    double order_bias = -1.0;
    uint64_t restart_base = 100;
    int initial_phase_mode = 0; // 0 polarity score, 1 true, -1 false

    std::vector<int> learnt_clause;
    std::vector<int> analyze_stack;
    std::vector<int> minimize_stack;
    std::vector<int> minimize_touched;
    std::vector<int> original_unit_lits;
    int top_unit_mask = 0;
    bool analysis_failed = false;

    ProofWriter* proof = nullptr;
    Clock::time_point start_time;
    double time_limit = 560.0;
    uint64_t conflicts = 0;
    uint64_t decisions = 0;
    uint64_t propagations = 0;
    uint64_t max_conflicts = std::numeric_limits<uint64_t>::max();
    uint64_t next_proof_id = 1;
    int active_learnts = 0;
    int first_learnt_cid = 0;
    bool reduce_enabled = false;
    int probe_limit = 0;
    bool debug_check = false;

    static int lit_index(int lit) {
        const int v = std::abs(lit) - 1;
        return (v << 1) ^ (lit < 0);
    }
    static int neg_index_from_lit(int lit) {
        const int v = std::abs(lit) - 1;
        return (v << 1) ^ (lit > 0);
    }
    int value_lit(int lit) const {
        const int8_t v = assigns[std::abs(lit)];
        if (v == 0) return 0;
        return (v > 0) == (lit > 0) ? 1 : -1;
    }
    int decision_level() const { return static_cast<int>(trail_lim.size()); }
    bool timed_out() const {
        const double elapsed = std::chrono::duration<double>(Clock::now() - start_time).count();
        return elapsed > time_limit;
    }

    bool parse(const char* path) {
        FastInput in(path);
        if (!in.ok()) return false;
        std::string w;
        while (in.read_word(w)) {
            if (w == "c") {
                in.skip_line();
                continue;
            }
            if (w == "p") {
                std::string fmt;
                if (!in.read_word(fmt)) return false;
                int nv = 0, nc = 0;
                if (!in.read_int(nv) || !in.read_int(nc)) return false;
                nvars = nv;
                declared_clauses = nc;
                clauses.reserve(nc + 1024);
                lits.reserve(static_cast<size_t>(nc) * 3);
                watches.assign(static_cast<size_t>(2 * nvars), {});
                assigns.assign(nvars + 1, 0);
                levels.assign(nvars + 1, 0);
                reasons.assign(nvars + 1, -1);
                activity.assign(nvars + 1, 0.0);
                heap_pos.assign(nvars + 1, -1);
                polarity_score.assign(nvars + 1, 0);
                saved_phase.assign(nvars + 1, 1);
                seen_stamp.assign(nvars + 1, 0);
                lbd_stamp.assign(nvars + 1, 0);
                next_proof_id = static_cast<uint64_t>(nc) + 1;
                continue;
            }

            if (nvars <= 0) return false;
            std::vector<int> tmp;
            int lit = std::atoi(w.c_str());
            while (true) {
                if (lit == 0) break;
                if (std::abs(lit) > nvars) return false;
                tmp.push_back(lit);
                polarity_score[std::abs(lit)] += lit > 0 ? 1 : -1;
                activity[std::abs(lit)] += 1.0;
                if (!in.read_int(lit)) return false;
            }
            if (!add_original_clause(tmp)) return false;
        }
        first_learnt_cid = static_cast<int>(clauses.size());
        build_heap();
        return true;
    }

    bool add_original_clause(std::vector<int>& c) {
        if (c.empty()) {
            Clause cl;
            cl.start = static_cast<uint32_t>(lits.size());
            cl.size = 0;
            clauses.push_back(cl);
            return true;
        }
        std::sort(c.begin(), c.end(), [](int a, int b) {
            int aa = std::abs(a), bb = std::abs(b);
            if (aa != bb) return aa < bb;
            return a < b;
        });
        size_t w = 0;
        for (size_t i = 0; i < c.size(); ++i) {
            if (i && c[i] == c[i - 1]) continue;
            if (i && std::abs(c[i]) == std::abs(c[i - 1])) return true;
            c[w++] = c[i];
        }
        c.resize(w);
        Clause cl;
        cl.start = static_cast<uint32_t>(lits.size());
        cl.size = static_cast<uint32_t>(c.size());
        cl.learnt = false;
        const int cid = static_cast<int>(clauses.size());
        clauses.push_back(cl);
        for (int x : c) lits.push_back(x);
        if (c.size() == 1) {
            original_unit_lits.push_back(c[0]);
            watches[lit_index(c[0])].push_back(cid);
        } else {
            watches[lit_index(c[0])].push_back(cid);
            watches[lit_index(c[1])].push_back(cid);
        }
        return true;
    }

    void build_heap() {
        double bias = order_bias;
        if (bias < 0.0) bias = (nvars < 300000) ? 5000.0 : 1000.0;
        heap.clear();
        heap.reserve(nvars);
        for (int v = 1; v <= nvars; ++v) {
            if (bias != 0.0) {
                activity[v] += bias * static_cast<double>(nvars - v + 1) / static_cast<double>(nvars);
            }
            if (initial_phase_mode > 0) saved_phase[v] = 1;
            else if (initial_phase_mode < 0) saved_phase[v] = -1;
            else saved_phase[v] = polarity_score[v] >= 0 ? 1 : -1;
            heap_pos[v] = static_cast<int>(heap.size());
            heap.push_back(v);
        }
        for (int i = static_cast<int>(heap.size()) / 2 - 1; i >= 0; --i) heap_down(i);
    }
    bool heap_less(int a, int b) const {
        if (activity[a] != activity[b]) return activity[a] < activity[b];
        return a > b;
    }
    void heap_swap(int i, int j) {
        std::swap(heap[i], heap[j]);
        heap_pos[heap[i]] = i;
        heap_pos[heap[j]] = j;
    }
    void heap_up(int i) {
        while (i > 0) {
            int p = (i - 1) >> 1;
            if (!heap_less(heap[p], heap[i])) break;
            heap_swap(p, i);
            i = p;
        }
    }
    void heap_down(int i) {
        const int n = static_cast<int>(heap.size());
        while (true) {
            int l = i * 2 + 1, r = l + 1, best = i;
            if (l < n && heap_less(heap[best], heap[l])) best = l;
            if (r < n && heap_less(heap[best], heap[r])) best = r;
            if (best == i) break;
            heap_swap(i, best);
            i = best;
        }
    }
    void heap_insert(int v) {
        if (heap_pos[v] >= 0) return;
        heap_pos[v] = static_cast<int>(heap.size());
        heap.push_back(v);
        heap_up(heap_pos[v]);
    }
    void bump_var(int v) {
        activity[v] += var_inc;
        if (activity[v] > 1e100) {
            for (int i = 1; i <= nvars; ++i) activity[i] *= 1e-100;
            var_inc *= 1e-100;
        }
        int p = heap_pos[v];
        if (p >= 0) heap_up(p);
    }
    void decay_vars() { var_inc /= var_decay; }

    bool enqueue(int lit, int reason) {
        const int v = std::abs(lit);
        const int8_t val = lit > 0 ? 1 : -1;
        if (assigns[v] != 0) return assigns[v] == val;
        assigns[v] = val;
        saved_phase[v] = val;
        levels[v] = decision_level();
        reasons[v] = reason;
        trail.push_back(lit);
        return true;
    }

    int propagate() {
        while (qhead < trail.size()) {
            const int lit = trail[qhead++];
            ++propagations;
            auto& ws = watches[neg_index_from_lit(lit)];
            size_t i = 0;
            while (i < ws.size()) {
                const int cid = ws[i];
                Clause& c = clauses[cid];
                if (c.deleted) {
                    ws[i] = ws.back();
                    ws.pop_back();
                    continue;
                }
                int* cp = lits.data() + c.start;
                if (c.size == 1) {
                    if (value_lit(cp[0]) < 0) return cid;
                    ++i;
                    continue;
                }
                const int false_lit = -lit;
                if (cp[0] == false_lit) {
                    std::swap(cp[0], cp[1]);
                } else if (cp[1] != false_lit) {
                    // The clause can be present through a stale duplicate watch only
                    // after earlier swaps; leave it alone and drop this watch entry.
                    ws[i] = ws.back();
                    ws.pop_back();
                    continue;
                }
                if (value_lit(cp[0]) > 0) {
                    ++i;
                    continue;
                }
                bool found = false;
                for (uint32_t k = 2; k < c.size; ++k) {
                    if (value_lit(cp[k]) >= 0) {
                        std::swap(cp[1], cp[k]);
                        ws[i] = ws.back();
                        ws.pop_back();
                        watches[lit_index(cp[1])].push_back(cid);
                        found = true;
                        break;
                    }
                }
                if (found) continue;
                if (value_lit(cp[0]) < 0) return cid;
                if (debug_check) {
                    for (uint32_t k = 1; k < c.size; ++k) {
                        if (value_lit(cp[k]) >= 0) {
                            std::fprintf(stderr, "bad unit reason cid=%d lit=%d other=%d val=%d size=%u\n",
                                         cid, cp[0], cp[k], value_lit(cp[k]), c.size);
                            std::abort();
                        }
                    }
                }
                if (!enqueue(cp[0], cid)) return cid;
                ++i;
            }
        }
        return -1;
    }

    void new_decision_level() { trail_lim.push_back(static_cast<int>(trail.size())); }

    void backtrack(int level) {
        if (decision_level() <= level) return;
        const int target = trail_lim[level];
        for (int i = static_cast<int>(trail.size()) - 1; i >= target; --i) {
            const int v = std::abs(trail[i]);
            assigns[v] = 0;
            reasons[v] = -1;
            levels[v] = 0;
            heap_insert(v);
        }
        trail.resize(target);
        trail_lim.resize(level);
        qhead = trail.size();
    }

    int compute_lbd(const std::vector<int>& c) {
        ++lbd_counter;
        int n = 0;
        for (int lit : c) {
            const int lev = levels[std::abs(lit)];
            if (lbd_stamp[lev] != lbd_counter) {
                lbd_stamp[lev] = lbd_counter;
                ++n;
            }
        }
        return n;
    }

    int add_learnt_clause(const std::vector<int>& c, uint32_t lbd) {
        Clause cl;
        cl.start = static_cast<uint32_t>(lits.size());
        cl.size = static_cast<uint32_t>(c.size());
        cl.lbd = lbd;
        cl.learnt = true;
        cl.proof_id = next_proof_id++;
        const int cid = static_cast<int>(clauses.size());
        clauses.push_back(cl);
        ++active_learnts;
        for (int x : c) lits.push_back(x);
        if (c.size() == 1) {
            watches[lit_index(c[0])].push_back(cid);
        } else {
            watches[lit_index(c[0])].push_back(cid);
            watches[lit_index(c[1])].push_back(cid);
        }
        return cid;
    }

    bool locked_clause(int cid) const {
        const Clause& c = clauses[cid];
        const int* cp = lits.data() + c.start;
        for (uint32_t j = 0; j < c.size; ++j) {
            if (reasons[std::abs(cp[j])] == cid) return true;
        }
        return false;
    }

    void reduce_learnts() {
        if (!reduce_enabled) return;
        if (active_learnts < 60000) return;
        std::vector<int> cand;
        cand.reserve(active_learnts);
        for (int cid = first_learnt_cid; cid < static_cast<int>(clauses.size()); ++cid) {
            const Clause& c = clauses[cid];
            if (!c.learnt || c.deleted || c.size <= 2 || c.lbd <= 4) continue;
            if (locked_clause(cid)) continue;
            cand.push_back(cid);
        }
        if (cand.size() < 10000) return;
        std::sort(cand.begin(), cand.end(), [&](int a, int b) {
            const Clause& ca = clauses[a];
            const Clause& cb = clauses[b];
            if (ca.lbd != cb.lbd) return ca.lbd > cb.lbd;
            if (ca.size != cb.size) return ca.size > cb.size;
            return ca.proof_id < cb.proof_id;
        });
        size_t ndelete = cand.size() / 2;
        for (size_t i = 0; i < ndelete; ++i) {
            Clause& c = clauses[cand[i]];
            if (c.deleted || locked_clause(cand[i])) continue;
            c.deleted = true;
            --active_learnts;
            if (proof && c.proof_id) proof->del_id(c.proof_id);
        }
    }

    int analyze(int confl) {
        learnt_clause.clear();
        learnt_clause.push_back(0);
        ++stamp;
        if (stamp == 0) {
            std::fill(seen_stamp.begin(), seen_stamp.end(), 0);
            stamp = 1;
        }
        int path_count = 0;
        int p = 0;
        int idx = static_cast<int>(trail.size()) - 1;
        int cid = confl;

        while (true) {
            Clause& c = clauses[cid];
            const int* cp = lits.data() + c.start;
            for (uint32_t j = 0; j < c.size; ++j) {
                int q = cp[j];
                int v = std::abs(q);
                if (v == std::abs(p) || seen_stamp[v] == stamp || levels[v] == 0) continue;
                seen_stamp[v] = stamp;
                bump_var(v);
                if (levels[v] == decision_level()) {
                    ++path_count;
                } else {
                    learnt_clause.push_back(q);
                }
            }
            while (idx >= 0 && seen_stamp[std::abs(trail[idx])] != stamp) --idx;
            p = trail[idx--];
            seen_stamp[std::abs(p)] = 0;
            --path_count;
            if (path_count <= 0) break;
            cid = reasons[std::abs(p)];
            if (cid < 0) {
                if (debug_check) {
                    int seen_current = 0;
                    for (int x : trail) {
                        int v = std::abs(x);
                        if (seen_stamp[v] == stamp && levels[v] == decision_level()) ++seen_current;
                    }
                    std::fprintf(stderr,
                                 "analysis failed p=%d level=%d path=%d seen_current=%d idx=%d trail=%zu\n",
                                 p, decision_level(), path_count, seen_current, idx, trail.size());
                }
                analysis_failed = true;
                return 0;
            }
        }

        learnt_clause[0] = -p;
        minimize_learnt_clause();
        if (learnt_clause.size() == 1) return 0;
        int best = 1;
        int back = levels[std::abs(learnt_clause[1])];
        for (int i = 2; i < static_cast<int>(learnt_clause.size()); ++i) {
            const int lev = levels[std::abs(learnt_clause[i])];
            if (lev > back) {
                back = lev;
                best = i;
            }
        }
        std::swap(learnt_clause[1], learnt_clause[best]);
        return back;
    }

    bool lit_redundant(int lit, uint32_t abstract_levels) {
        minimize_stack.clear();
        minimize_touched.clear();
        minimize_stack.push_back(std::abs(lit));
        for (size_t i = 0; i < minimize_stack.size(); ++i) {
            int v = minimize_stack[i];
            int rid = reasons[v];
            if (rid < 0) {
                for (int x : minimize_touched) seen_stamp[x] = 0;
                return false;
            }
            Clause& c = clauses[rid];
            const int* cp = lits.data() + c.start;
            for (uint32_t j = 0; j < c.size; ++j) {
                int qv = std::abs(cp[j]);
                if (qv == v || levels[qv] == 0 || seen_stamp[qv] == stamp) continue;
                if (((abstract_levels >> (levels[qv] & 31)) & 1u) == 0 || reasons[qv] < 0) {
                    for (int x : minimize_touched) seen_stamp[x] = 0;
                    return false;
                }
                seen_stamp[qv] = stamp;
                minimize_touched.push_back(qv);
                minimize_stack.push_back(qv);
            }
        }
        return true;
    }

    void minimize_learnt_clause() {
        if (learnt_clause.size() <= 2) return;
        uint32_t abstract_levels = 0;
        for (int lit : learnt_clause) abstract_levels |= 1u << (levels[std::abs(lit)] & 31);
        for (int lit : learnt_clause) seen_stamp[std::abs(lit)] = stamp;
        size_t out = 1;
        for (size_t i = 1; i < learnt_clause.size(); ++i) {
            int lit = learnt_clause[i];
            if (reasons[std::abs(lit)] >= 0 && lit_redundant(lit, abstract_levels)) {
                continue;
            }
            learnt_clause[out++] = lit;
        }
        learnt_clause.resize(out);
    }

    bool simplify_level0() {
        if (decision_level() != 0) return true;
        int confl = propagate();
        return confl < 0;
    }

    Result probe_failed_literals() {
        if (probe_limit <= 0) return UNKNOWN;
        const int upto = std::min(nvars, probe_limit);
        for (int v = 1; v <= upto; ++v) {
            if ((v & 63) == 0 && timed_out()) return UNKNOWN;
            if (assigns[v] != 0) continue;
            int tries[2] = {v, -v};
            for (int lit : tries) {
                if (assigns[v] != 0) break;
                new_decision_level();
                bool ok = enqueue(lit, -1);
                int confl = ok ? propagate() : 0;
                backtrack(0);
                if (!ok || confl >= 0) {
                    std::vector<int> unit(1, -lit);
                    if (proof) proof->rup_clause(unit);
                    int cid = add_learnt_clause(unit, 1);
                    if (!enqueue(-lit, cid)) {
                        if (proof) {
                            proof->rup_empty();
                            proof->finish_unsat();
                        }
                        return UNSAT;
                    }
                    int c2 = propagate();
                    if (c2 >= 0) {
                        if (proof) {
                            proof->rup_empty();
                            proof->finish_unsat();
                        }
                        return UNSAT;
                    }
                    break;
                }
            }
        }
        return UNKNOWN;
    }

    int pick_branch_lit() {
        while (!heap.empty()) {
            int v = heap[0];
            if (assigns[v] == 0) {
                if (saved_phase[v] != 0) return saved_phase[v] > 0 ? v : -v;
                return polarity_score[v] >= 0 ? v : -v;
            }
            heap_swap(0, static_cast<int>(heap.size()) - 1);
            heap_pos[heap.back()] = -1;
            heap.pop_back();
            if (!heap.empty()) heap_down(0);
        }
        return 0;
    }

    static uint64_t luby(uint64_t y, uint64_t x) {
        uint64_t size = 1, seq = 0;
        while (size < x + 1) {
            size = 2 * size + 1;
            ++seq;
        }
        while (size - 1 != x) {
            size = (size - 1) >> 1;
            --seq;
            x %= size;
        }
        uint64_t r = 1;
        for (uint64_t i = 0; i < seq; ++i) r *= y;
        return r;
    }

    bool all_clauses_satisfied() const {
        for (const Clause& c : clauses) {
            if (c.deleted || c.learnt) continue;
            bool sat = false;
            const int* cp = lits.data() + c.start;
            for (uint32_t j = 0; j < c.size; ++j) {
                if (value_lit(cp[j]) > 0) {
                    sat = true;
                    break;
                }
            }
            if (!sat) return false;
        }
        return true;
    }

    Result solve() {
        start_time = Clock::now();
        std::vector<int> top_units;
        if (top_unit_mask != 0) {
            for (int lit : original_unit_lits) {
                if (lit > 0) top_units.push_back(lit);
                if (top_units.size() == 3) break;
            }
        }
        for (int lit : original_unit_lits) {
            if (top_unit_mask != 0 && lit > 0) {
                auto it = std::find(top_units.begin(), top_units.end(), lit);
                if (it != top_units.end()) {
                    int idx = static_cast<int>(it - top_units.begin());
                    if (((top_unit_mask >> idx) & 1) == 0) continue;
                }
            }
            if (!enqueue(lit, -1)) {
                if (proof) {
                    proof->rup_empty();
                    proof->finish_unsat();
                }
                return UNSAT;
            }
        }
        int confl = propagate();
        if (confl >= 0) {
            if (proof) {
                proof->rup_empty();
                proof->finish_unsat();
            }
            return UNSAT;
        }
        Result probe_res = probe_failed_literals();
        if (probe_res == UNSAT) return UNSAT;

        uint64_t restart_idx = 1;
        uint64_t next_restart = restart_base;

        while (true) {
            if ((conflicts & 4095ULL) == 0 && timed_out()) return UNKNOWN;
            confl = propagate();
            if (confl >= 0) {
                ++conflicts;
                if (decision_level() == 0) {
                    if (proof) {
                        proof->rup_empty();
                        proof->finish_unsat();
                    }
                    return UNSAT;
                }
                int back = analyze(confl);
                if (analysis_failed) return UNKNOWN;
                if (proof) proof->rup_clause(learnt_clause);
                uint32_t lbd = static_cast<uint32_t>(compute_lbd(learnt_clause));
                backtrack(back);
                int cid = add_learnt_clause(learnt_clause, lbd);
                if (debug_check) {
                    for (size_t k = 1; k < learnt_clause.size(); ++k) {
                        if (value_lit(learnt_clause[k]) >= 0) {
                            std::fprintf(stderr, "learnt not asserting lit=%d other=%d val=%d back=%d size=%zu\n",
                                         learnt_clause[0], learnt_clause[k], value_lit(learnt_clause[k]),
                                         back, learnt_clause.size());
                            std::abort();
                        }
                    }
                }
                if (!enqueue(learnt_clause[0], cid)) {
                    if (proof) {
                        proof->rup_empty();
                        proof->finish_unsat();
                    }
                    return UNSAT;
                }
                decay_vars();
                if (conflicts >= next_restart) {
                    backtrack(0);
                    ++restart_idx;
                    next_restart = conflicts + restart_base * luby(2, restart_idx);
                }
                if ((conflicts % 10000ULL) == 0) reduce_learnts();
                if (conflicts >= max_conflicts) return UNKNOWN;
            } else {
                int decision = pick_branch_lit();
                if (decision == 0) {
                    if (!all_clauses_satisfied()) return UNKNOWN;
                    return SAT;
                }
                ++decisions;
                new_decision_level();
                enqueue(decision, -1);
            }
        }
    }

    void print_model() const {
        std::puts("s SATISFIABLE");
        constexpr int per_line = 16;
        int k = 0;
        std::printf("v");
        for (int v = 1; v <= nvars; ++v) {
            int lit = assigns[v] >= 0 ? v : -v;
            std::printf(" %d", lit);
            if (++k == per_line && v != nvars) {
                std::printf(" 0\nv");
                k = 0;
            }
        }
        std::printf(" 0\n");
    }
};

}  // namespace

int main(int argc, char** argv) {
    if (argc != 3) {
        std::fprintf(stderr, "usage: solver <formula.cnf> <out.pbp>\n");
        return 1;
    }

    ProofWriter proof(argv[2]);
    Solver solver;
    solver.proof = &proof;
    const char* env_limit = std::getenv("SOLVER_TIME_LIMIT");
    if (env_limit) solver.time_limit = std::atof(env_limit);
    const char* env_conf = std::getenv("SOLVER_MAX_CONFLICTS");
    if (env_conf) solver.max_conflicts = std::strtoull(env_conf, nullptr, 10);
    const char* env_bias = std::getenv("SOLVER_ORDER_BIAS");
    if (env_bias) solver.order_bias = std::atof(env_bias);
    const char* env_restart = std::getenv("SOLVER_RESTART_BASE");
    if (env_restart) solver.restart_base = std::strtoull(env_restart, nullptr, 10);
    const char* env_phase = std::getenv("SOLVER_PHASE");
    if (env_phase) {
        if (std::strcmp(env_phase, "true") == 0) solver.initial_phase_mode = 1;
        else if (std::strcmp(env_phase, "false") == 0) solver.initial_phase_mode = -1;
    }
    solver.reduce_enabled = std::getenv("SOLVER_REDUCE") != nullptr;
    const char* env_probe = std::getenv("SOLVER_PROBE_LIMIT");
    if (env_probe) solver.probe_limit = std::atoi(env_probe);
    const char* env_unit_mask = std::getenv("SOLVER_TOP_UNIT_MASK");
    if (env_unit_mask) solver.top_unit_mask = std::atoi(env_unit_mask);
    solver.debug_check = std::getenv("SOLVER_DEBUG_CHECK") != nullptr;

    if (!solver.parse(argv[1])) {
        std::puts("s UNKNOWN");
        return 0;
    }

    Solver::Result res = solver.solve();
    std::fprintf(stderr, "c stats conflicts=%llu decisions=%llu propagations=%llu\n",
                 static_cast<unsigned long long>(solver.conflicts),
                 static_cast<unsigned long long>(solver.decisions),
                 static_cast<unsigned long long>(solver.propagations));
    if (res == Solver::UNSAT) {
        if (proof.failed) {
            std::puts("s UNKNOWN");
            return 0;
        }
        std::puts("s UNSATISFIABLE");
        return 20;
    }
    if (res == Solver::SAT) {
        solver.print_model();
        return 10;
    }
    std::puts("s UNKNOWN");
    return 0;
}
