Source code for unicode_fol_kit.atp.z3_models

"""Satisfiability / validity checks and model (counterexample) extraction via Z3."""

from ..fol.nodes import Node
from z3 import Solver, sat, unsat, Not


[docs] def is_satisfiable(formula: Node, timeout: int = 10000) -> bool: """Return True if the formula has a model (Z3 reports sat). A Z3 ``unknown`` result (e.g. on hard quantified formulas hitting the timeout) is treated as not-known-satisfiable and returns False. """ solver = Solver() solver.set("timeout", timeout) solver.set("random_seed", 42) solver.add(formula.to_z3()) return solver.check() == sat
[docs] def is_valid(formula: Node, timeout: int = 10000) -> bool: """Return True if the formula is valid, i.e. its negation is unsatisfiable. A Z3 ``unknown`` result (e.g. on hard quantified formulas hitting the timeout) is treated as not-known-valid and returns False. """ solver = Solver() solver.set("timeout", timeout) solver.set("random_seed", 42) solver.add(Not(formula.to_z3())) return solver.check() == unsat
[docs] def get_model(formula: Node, timeout: int = 10000): """Return a satisfying assignment as a dict, or None if unsat/unknown. The dict maps each Z3 declaration name (constants, uninterpreted functions/predicates) to the string form of its interpretation. For an invalid equivalence or entailment, ``get_model(Not(...))`` yields the concrete counterexample. Returns None when the formula is unsatisfiable or Z3 cannot decide it within the timeout. """ solver = Solver() solver.set("timeout", timeout) solver.set("random_seed", 42) solver.add(formula.to_z3()) if solver.check() != sat: return None model = solver.model() return {str(decl.name()): str(model[decl]) for decl in model.decls()}