nx_fmb.nx
buildroot/runtime/nx_fmb.nx
about
nx_fmb.nx -- Finite Model Building.
Per Vampire Trophy Cabinet (https://github.com/vprover/vampire/wiki/Trophy-Cabinet):
"Our success [in the FNT division] is supported heavily by our
implementation of finite model building."
FMB is the explicitly-named technique Vampire credits with its
Find-Non-Theorems wins. Shipping it closes the BLOCKED_ON_FMB axis
from the substrate's honest CASC verdict.
Algorithm (MACE-style, simplified):
For each domain size N = 1, 2, 3, ...:
1. Ground every clause over a domain of N constants
{d_1, d_2, ..., d_N}. Every variable in every clause is
instantiated as each domain element in turn (one variable ->
N copies of the clause; two variables -> N^2 copies; etc.).
2. Convert the ground clause set into a propositional SAT problem.
3. Run the SAT solver. If SAT, the original problem has a
finite model of size N -- emit MODEL_FOUND verdict.
If UNSAT, try N+1.
4. If no model found within max_size, return UNKNOWN.
Verdicts:
NX_FMB_MODEL_FOUND -- problem has a finite model (so the negated
conjecture is satisfiable; original was NOT
a theorem) -- CounterModel found
NX_FMB_NO_MODEL -- search ran up to max_size without finding
NX_FMB_ERROR -- bad input / capacity exceeded
This is the basic CounterSatisfiable detector. Real Vampire FMB
uses CSP-style constraints + sort inference + sym break; this MVP
uses naive grounding + DPLL on the SAT side. Sufficient for
FNT-easy problems.
Bits-up nx_int; uses existing nx_sat_solver DPLL backend.
dependencies 7 imports · 1 importers
imports: nx_syscalls.nxnx_runtime.nxnx_tier.nxnx_result.nxnx_unify.nxnx_resolution.nxnx_sat_solver.nx
imported by: nx_fmb_test.nx
structs
| 210 | struct FmbPropMap |
consts
| 50 | const NX_MAGIC_4096: i64 = 4096 |
| 52 | const NX_FMB_MODEL_FOUND: nx_int = 1 |
| 53 | const NX_FMB_NO_MODEL: nx_int = 2 |
| 54 | const NX_FMB_ERROR: nx_int = 3 |
| 59 | const NX_FMB_DOMAIN_BASE_SYM: nx_int = 500000 |
| 62 | const NX_FMB_MAX_VARS_PER_CLAUSE: nx_int = 8 |
| 208 | const NX_FMB_MAX_PROP_ATOMS: nx_int = 4096 |
| 214 | const NX_FMB_PROP_MAP_BYTES: nx_int = 16 |
functions
| 67 | func nx_fmb_term_vars(t: *Term, out: *nx_int, n_out: nx_int) -> nx_int |
| 92 | func nx_fmb_collect_vars(c: *Clause, out_vars: *nx_int) -> nx_int |
| 105 | func nx_fmb_subst_term(t: *Term, var_id: nx_int, dom_elem: nx_int) -> *Term |
| 131 | func nx_fmb_subst_clause(c: *Clause, var_id: nx_int, dom_elem: nx_int) -> *Clause called by 1: nx_fmb_ground_clause calls 5: nx_clause_newnx_clause_lit_atnx_fmb_subst_termnx_lit_makenx_clause_add |
| 147 | func nx_fmb_ground_clause(c: *Clause, domain_size: nx_int, |
| 216 | func nx_fmb_prop_map_new() -> *FmbPropMap |
| 225 | func nx_fmb_prop_id(m: *FmbPropMap, atom: *Term) -> nx_int |
| 244 | func nx_fmb_try_size(clauses: *Clause, n_clauses: nx_int, size: nx_int) -> nx_int |
| 288 | func nx_fmb_search(clauses: *Clause, n_clauses: nx_int, |
| 304 | func nx_fmb_verdict_name(v: nx_int) -> *u8 called by 1: main |