tiny.smt.sat.types
Defined in sat.
The values a caller hands to the solver and reads back from it: literals, answers, truth values that may be unset, counts of a solve's work, and the restart schedule.
API (5)
Types and contracts
Public types and contracts.
BoolValue: A truth value that may also be unset.Literal: A variable or its negation, packed into one 32-bit number.RestartPolicy: The restart schedule: the search goes back to the first decision after a conflict count that starts atfirst_conflict_intervaland multiplies bygrowthafter each restart.SolveStats: Counts of the work one solve did.Status: The answer of one solve.
Source
Source: lib/smt/src/sat/root.zig:52
zig
pub const types = @import("types.zig");Source: lib/smt/src/sat/types.zig
zig
//! The values a caller hands to the solver and reads back from it: literals, answers, truth values//! that may be unset, counts of a solve's work, and the restart schedule.//!//! A caller writes clauses as literals over variables numbered from 0, reads one of three answers//! after each solve, and reads the value of each variable after a satisfiable answer. Clause files//! in the common text format number variables from 1 and write a negated variable as a negative//! number (DIMACS), so a caller reading or writing them converts each literal.//!//! The solver keeps one list per literal, so a literal has to map to a small number that can index//! an array. A literal packs its variable and its sign into one 32-bit number (`Literal.raw`)://! twice the variable index, plus one for a negated literal. That number indexes the solver's//! per-literal lists directly, and negating a literal flips its lowest bit. `Literal.fromDimacs`//! and `Literal.toDimacs` convert between that number and the signed numbers of the text format. A//! truth value has a third state, unset (`BoolValue.unset`), for an unassigned variable./// The answer of one solve. A caller switches on it to decide whether to read a satisfying/// assignment, an unsat core and a proof, or neither.pub const Status = enum { /// Some assignment makes every clause and every assumption of the solve true. `Solver.value` /// and `Solver.literalValue` read that assignment until the next solve. sat, /// No assignment makes every clause and every assumption of the solve true. The solver then /// holds a proof trace that ends in the empty clause, and after a solve under assumptions an /// unsat core. unsat, /// The solve ran out of its conflict limit (`Solver.conflict_budget`) before it reached an /// answer, or while core minimization certified a smaller core. After the second case the core /// is empty, but the proof trace still holds a refutation under every assumption of the solve. unknown,};/// A truth value that may also be unset. A caller switches on the value `Solver.literalValue`/// returns to read a literal in a satisfying assignment.pub const BoolValue = enum { /// The variable is unassigned, or the literal names a variable at or above the solver's /// variable count. unset, /// The literal or variable is false. false, /// The literal or variable is true. true, /// Returns `.true` for true and `.false` for false. The solver and the proof checker record an /// assigned value through it. pub fn fromBool(value: bool) BoolValue { return if (value) .true else .false; } /// Returns the opposite value, and `.unset` for `.unset`. The solver and the proof checker read /// a negated literal's value from its variable's value through it. pub fn invert(self: BoolValue) BoolValue { return switch (self) { .unset => .unset, .false => .true, .true => .false, }; }};/// Counts of the work one solve did. A caller reads them from `Solver.lastSolveStats` to report how/// much work a solve took. The solver sets every count to zero when a solve starts. The counts/// cover the main search: the extra solves of core minimization change only `proof_steps`, which/// takes the certified trace's length.pub const SolveStats = struct { /// Decisions the search made, each giving an unassigned variable a value. decisions: usize = 0, /// Decisions that gave the variable the value it last held, in this solve or an earlier one, /// counted within `decisions`. phase_saved_decisions: usize = 0, /// Literals the search assigned because every other literal of a clause was false. Unit clauses /// of the formula and assumptions sit outside the count. propagations: usize = 0, /// Times the main search found a clause with every literal false. `Solver.conflict_budget` /// limits this count. conflicts: usize = 0, /// Clauses the search learned from conflicts in this solve. learned_clauses: usize = 0, /// Learned clauses the solver removed to stay within `Solver.max_learned_clauses`, removals at /// the start of the solve included. evicted_clauses: usize = 0, /// Steps in the proof trace at the end of the solve: one per learned clause, plus the final /// empty clause after an unsatisfiable answer. After core minimization certified a smaller /// core, the count is the certifying solve's step count. proof_steps: usize = 0, /// Times the search went back to the first decision, on the restart schedule or to remove /// learned clauses. restarts: usize = 0, /// The largest number of decisions in force at once during the solve. max_decision_level: u32 = 0, /// Conflicts found at decision level zero, counted within `conflicts`. Assumptions sit below /// every decision, so a conflict among the assumptions counts here. root_conflicts: usize = 0,};/// The restart schedule: the search goes back to the first decision after a conflict count that/// starts at `first_conflict_interval` and multiplies by `growth` after each restart. A caller/// passes one to `Solver.setRestartPolicy` to change the schedule, for example to restart after/// every conflict. The default restarts after 128 conflicts, then after 256 more, then 512,/// doubling each time. The solver keeps its learned clauses across a restart. The count starts over/// at each solve, and a restart happens only while a decision is in force.pub const RestartPolicy = struct { /// Conflicts before the first restart of each solve, 128 by default. Zero turns restarts off. first_conflict_interval: usize = 128, /// The factor the interval grows by after each restart, 2 by default. A factor of 0 or 1 keeps /// the interval fixed, and the interval stops growing at the largest `usize`. growth: usize = 2, /// Returns a policy that turns restarts off: an interval of 0 and a growth of 1. A caller that /// turns restarts off passes it to `Solver.setRestartPolicy`. pub fn disabled() RestartPolicy { return .{ .first_conflict_interval = 0, .growth = 1 }; }};/// A variable or its negation, packed into one 32-bit number. A caller builds every clause and/// every assumption from literals. Variables are numbered from 0 in the order `Solver.addVariable`/// returns them.pub const Literal = struct { /// The packed number: twice the variable index, plus one for a negated literal. Two literals /// are equal when their `raw` values are equal, and callers compare literals that way. raw: u32, /// Returns the literal of variable `variable_index`, unnegated when `polarity` is true and /// negated when it is false. Code that picks the sign at run time calls it. An index of /// 2147483648 or more overflows the packed number, which panics in safe builds. pub fn init(variable_index: u32, polarity: bool) Literal { return .{ .raw = variable_index * 2 + if (polarity) @as(u32, 0) else @as(u32, 1) }; } /// Returns the unnegated literal of variable `variable_index`. A caller writes a clause whose /// signs it knows in its source. pub fn positive(variable_index: u32) Literal { return init(variable_index, true); } /// Returns the negated literal of variable `variable_index`. A caller writes a clause whose /// signs it knows in its source. pub fn negative(variable_index: u32) Literal { return init(variable_index, false); } /// Returns the variable index of the literal. A caller finds which variable a literal names, /// for example to check it against a variable count. pub fn variable(self: Literal) u32 { return self.raw >> 1; } /// Returns true for an unnegated literal. A caller reads a literal's sign to evaluate it under /// an assignment. pub fn isPositive(self: Literal) bool { return self.raw & 1 == 0; } /// Returns the literal of the same variable with the opposite sign. An encoder calls it to /// state the negation of a condition. pub fn negated(self: Literal) Literal { return .{ .raw = self.raw ^ 1 }; } /// Returns the packed number as a `usize`. The solver indexes its per-literal lists of watching /// clauses by it, two entries per variable. pub fn index(self: Literal) usize { return @intCast(self.raw); } /// Returns the literal a DIMACS number stands for: variable `|value| - 1`, negated when `value` /// is negative. The DIMACS and proof readers call it on each number of a clause. The call /// returns `error.InvalidDimacsLiteral` for 0, the number that ends a clause in that format. /// The value -2147483648 makes it panic, because its negation does not fit in 32 bits. pub fn fromDimacs(value: i32) !Literal { if (value == 0) return error.InvalidDimacsLiteral; const magnitude: u32 = @intCast(if (value < 0) -value else value); return init(magnitude - 1, value > 0); } /// Returns the DIMACS number of the literal: the variable index plus one, negative for a /// negated literal. The DIMACS and proof writers call it on each literal they print. Variable /// index 2147483647 makes it panic, because its number does not fit in `i32`. pub fn toDimacs(self: Literal) i32 { const one_based: i32 = @intCast(self.variable() + 1); return if (self.isPositive()) one_based else -one_based; }};Audit
| Definitions | 1 |
|---|---|
| Public names | 1 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |