tiny.smt.Solver
Defined in sat.solver.
A SAT solver that learns a clause from each conflict above decision level zero over the clauses a caller adds, answers under assumed literals, and records an unsat core and a proof trace after each unsatisfiable answer.
API (56)
Actions
Public operations.
activeAssumptions: Returns the solver's assumption list, oldest first.addClause: Adds a copy ofliteralsas a clause and adds any variable it names that the solver lacks.addVariable: Adds one unassigned variable and returns its index, counting from 0.assume: Addsliteralto the solver's assumption list and adds its variable when the solver lacks it.clauseCount: Returns the number of entries inclauses.clearAssumptionFrames: Empties the assumption list and closes every frame.deinit: Frees every clause, list, fixed store, trace and proof step, and leaves the solver undefined.frameDepth: Returns the number of open frames.init: Returns an empty solver that allocates withallocator.lastProofArtifact: Returns a copy of the clauses, assumptions and steps behind the last unsatisfiable answer, allocated withallocatorand owned by the caller, or null when the trace is empty.lastProofTrace: Returns the proof steps of the last solve, in order.lastProofTraceValid: Returns true when the trace is nonempty, each step follows by unit propagation from the starting clauses, the assumptions and the earlier steps, and the last step is the empty clause.lastSolveStats: Returns the work counts of the last solve.lastUnsatCore: Returns a set of the last solve's assumptions that the clauses refute together, after an unsatisfiable answer.literalValue: Returns the value ofliteralin the current assignment:.true,.false, or.unsetwhen its variable is unassigned or at or above the variable count.popAssumptionFrame: Returns the assumption list to the length the latest push saved and closes that frame.pushAssumptionFrame: Saves the current length of the assumption list, so the nextpopAssumptionFramereturns the list to it.replaceableLearnedClauses: Returns the number of learned clauses whose literals span more than two decision levels.restartPolicy: Returns the restart schedule later solves use.retainedLearnedClauses: Returns the number of learned clauses the solver holds, at every block distance.setRestartPolicy: Sets the restart schedule for later solves.solve: Solves the clauses alone, assolveWithAssumptionsdoes with an empty list.solveWithActiveAssumptions: Solves under the solver's own assumption list, assolveWithAssumptionsdoes.solveWithAssumptions: Decides whether the clauses and every literal ofassumptionscan all be true, and returns.sat,.unsator.unknown.value: Returns the value ofvariable_indexin the current assignment, or null when the variable is unassigned or at or above the variable count.variableCount: Returns the number of variables: one more than the highest variable index the solver has added or seen.
Fields and members
Public fields and members.
allocatorassignmentassumptionsclausesconflict_budgetconflicts_since_restartdecision_limitsframesglue_clause_counthas_empty_clauseinconsistentlast_corelast_statslearned_clause_countlearned_storelevelmax_learned_clausesnext_restart_conflictsproof_assumptionsproof_base_clause_countproof_stepsproof_traceproof_trace_slabpropagation_cursorreasonrestart_policyrup_assignmentsaved_phasetrailwatches
Source
Source: lib/smt/src/sat/solver.zig:134
zig
/// A SAT solver that learns a clause from each conflict above decision level zero over the clauses/// a caller adds, answers under assumed literals, and records an unsat core and a proof trace after/// each unsatisfiable answer. The package's bit-vector encoder (`bitvec.Encoder`) turns terms into/// variables and clauses of a solver it is given, and a caller then solves and reads the answer/// through the solver. `init` takes an allocator, and the solver allocates every list, clause copy/// and proof step with it and frees them in `deinit`. A caller sets `conflict_budget` and/// `max_learned_clauses`, and reads `clauses` and `has_empty_clause`. The other fields are search/// state, which a caller reads through the solver's functions. Each clause of two or more literals/// watches two of them, and a unit clause watches its one literal. A decision gives the variable/// the value it last held, or true for a variable assigned for the first time. The list of assigned/// literals in assignment order has room past the variable count for the scratch memory of conflict/// analysis (`ConflictScratch`).pub const Solver = struct { allocator: std.mem.Allocator, /// Every clause the solver holds: the caller's nonempty clauses and the learned clauses it /// keeps. An empty clause from the caller stays out of the list and sets `has_empty_clause`. /// Clause order changes when the solver removes a learned clause under a cap, because the last /// clause moves into the removed clause's place. A solve with assumptions removes the clauses /// added during it when it returns. `clauseCount` counts the list, and `dimacs.write` writes it /// with learned clauses included. clauses: std.ArrayList(Clause) = .empty, watches: std.ArrayList(std.ArrayList(ClauseRef)) = .empty, assignment: std.ArrayList(BoolValue) = .empty, saved_phase: std.ArrayList(BoolValue) = .empty, level: std.ArrayList(u32) = .empty, reason: std.ArrayList(?usize) = .empty, trail: std.ArrayList(Literal) = .empty, propagation_cursor: usize = 0, decision_limits: std.ArrayList(usize) = .empty, assumptions: std.ArrayList(Literal) = .empty, frames: std.ArrayList(usize) = .empty, last_core: std.ArrayList(Literal) = .empty, proof_steps: std.ArrayList(ProofStep) = .empty, proof_assumptions: std.ArrayList(Literal) = .empty, proof_base_clause_count: usize = 0, last_stats: SolveStats = .{}, restart_policy: RestartPolicy = .{}, conflicts_since_restart: usize = 0, next_restart_conflicts: usize = 0, /// The most conflicts one solve may meet before it returns `.unknown`. The default `null` /// leaves the search unlimited. A caller sets it before a solve to bound the search's work. /// While it is set, the solver keeps the solve's proof steps in fixed memory sized from it and /// the variable count (`ProofTrace`). The extra solves of core minimization share what is left /// of it after the main search. conflict_budget: ?usize = null, /// The most replaceable learned clauses the solver keeps. The default `null` leaves the learned /// clauses uncapped. A caller sets it before a solve to bound the memory learned clauses take. /// At the start of each solve, and whenever the count passes the cap during a search, the /// solver removes replaceable learned clauses, highest block distance first and then the /// longest. The solver keeps each clause that justifies a current value and the newly learned /// clause, so the count can pass the cap by those clauses. While it is set, the solver keeps /// replaceable learned clauses in fixed memory sized from the cap and the variable count /// (`LearnedStore`). After a caller sets it back to `null`, the next solve moves those clauses /// to heap memory. max_learned_clauses: ?usize = null, learned_clause_count: usize = 0, glue_clause_count: usize = 0, learned_store: ?store.Store = null, proof_trace: ?trace.Trace = null, proof_trace_slab: bool = true, rup_assignment: std.ArrayList(BoolValue) = .empty, /// True once the caller has added an empty clause. Every later solve then answers `.unsat`. /// `dimacs.write` writes an empty clause for it, and `lastProofArtifact` adds an empty starting /// clause for it. The solver's own proof checks accept every step while it is set. The default /// is false. has_empty_clause: bool = false, inconsistent: bool = false, /// Returns an empty solver that allocates with `allocator`. A caller creates one solver per /// formula and hands it to the code that adds the clauses. The call allocates nothing. pub fn init(allocator: std.mem.Allocator) Solver { return .{ .allocator = allocator }; } /// Frees every clause, list, fixed store, trace and proof step, and leaves the solver /// undefined. The owner of a solver calls it once, when it is done with the formula. Slices /// from `lastUnsatCore`, `lastProofTrace` and `activeAssumptions` become invalid. Artifacts /// from `lastProofArtifact` stay valid, because each owns its own copy. pub fn deinit(self: *Solver) void { for (self.clauses.items) |clause| { if (clause.storage == .heap) self.allocator.free(clause.literals); } if (self.learned_store) |*pool| pool.deinit(self.allocator); self.clauses.deinit(self.allocator); for (self.watches.items) |*watch| { watch.deinit(self.allocator); } self.watches.deinit(self.allocator); self.assignment.deinit(self.allocator); self.saved_phase.deinit(self.allocator); self.level.deinit(self.allocator); self.reason.deinit(self.allocator); self.trail.deinit(self.allocator); self.decision_limits.deinit(self.allocator); self.assumptions.deinit(self.allocator); self.frames.deinit(self.allocator); self.last_core.deinit(self.allocator); self.clearProofTrace(); if (self.proof_trace) |*owner| owner.deinit(self.allocator); self.proof_steps.deinit(self.allocator); self.proof_assumptions.deinit(self.allocator); self.rup_assignment.deinit(self.allocator); self.* = undefined; } /// Returns the number of variables: one more than the highest variable index the solver has /// added or seen. A caller reports it as a size of the encoded formula. A clause or an /// assumption that names a higher variable raises it. pub fn variableCount(self: *const Solver) usize { return self.assignment.items.len; } /// Returns the number of entries in `clauses`. A caller reports it as a size of the encoded /// formula, and `dimacs.write` prints it in its header. The count includes the learned clauses /// the solver keeps and leaves out an empty clause from the caller. pub fn clauseCount(self: *const Solver) usize { return self.clauses.items.len; } /// Returns the number of learned clauses the solver holds, at every block distance. A caller /// checks how many learned clauses survive a capped search. The count drops when the solver /// removes a learned clause under a cap and when a solve with assumptions returns. pub fn retainedLearnedClauses(self: *const Solver) usize { return self.learned_clause_count; } /// Returns the number of learned clauses whose literals span more than two decision levels. A /// caller compares it with `max_learned_clauses` after a capped search. These are the clauses /// the cap bounds. pub fn replaceableLearnedClauses(self: *const Solver) usize { assert(self.glue_clause_count <= self.learned_clause_count); return self.learned_clause_count - self.glue_clause_count; } /// Sets the restart schedule for later solves. A caller that wants restarts at a different /// pace, such as after every conflict, sets it before solving. The schedule takes effect at the /// start of the next solve. pub fn setRestartPolicy(self: *Solver, policy: RestartPolicy) void { self.restart_policy = policy; } /// Returns the restart schedule later solves use. A caller reads back the schedule that /// `setRestartPolicy` set, or the default. pub fn restartPolicy(self: *const Solver) RestartPolicy { return self.restart_policy; } /// Adds one unassigned variable and returns its index, counting from 0. `bitvec.Encoder` adds a /// variable for each Boolean it encodes, and `dimacs.parse` adds the variable count of its /// header. The call clears the recorded core and trace. The call returns `error.OutOfMemory` /// when a list fails to grow. An index at or above 2^31 overflows the literal's packed number, /// so building a literal for it panics in safe builds. pub fn addVariable(self: *Solver) !u32 { self.last_core.clearRetainingCapacity(); self.clearProofTrace(); const variable_index: u32 = @intCast(self.assignment.items.len); try self.ensureVariable(variable_index); return variable_index; } /// Adds a copy of `literals` as a clause and adds any variable it names that the solver lacks. /// `bitvec.Encoder` asserts each encoded fact through it, and `dimacs.parse` adds each clause /// of its input. The caller keeps `literals`. An empty slice sets `has_empty_clause`, and every /// later solve answers `.unsat`. The solver assigns the literal of a unit clause at once. When /// the literal of a unit clause is false under the assignment the last search left, every later /// solve skips the search and checks the final empty clause at once, so it returns /// `error.InvalidProofTrace` for a formula that is still satisfiable. The call clears the /// recorded core and trace. The call returns `error.OutOfMemory` when a copy or a list fails to /// grow, and then the clause is left out while variables it named may stay added. pub fn addClause(self: *Solver, literals: []const Literal) !void { self.last_core.clearRetainingCapacity(); self.clearProofTrace(); if (literals.len == 0) { self.has_empty_clause = true; self.inconsistent = true; return; } for (literals) |literal| { try self.ensureVariable(literal.variable()); } const owned = try self.allocator.dupe(Literal, literals); errdefer self.allocator.free(owned); const clause_index = self.clauses.items.len; const clause = Clause{ .literals = owned, .learned = false, .lbd = 0, .storage = .heap, .watch_a = 0, .watch_b = if (owned.len > 1) 1 else 0, }; try self.clauses.append(self.allocator, clause); errdefer _ = self.clauses.pop(); try self.addWatch(owned[0], clause_index); errdefer _ = self.removeWatch(owned[0], clause_index); if (owned.len > 1) { try self.addWatch(owned[1], clause_index); } if (owned.len == 1) { if (!try self.enqueue(owned[0], clause_index)) self.inconsistent = true; } } /// Solves the clauses alone, as `solveWithAssumptions` does with an empty list. A caller that /// asks one question of a formula calls it. The solver's own assumption list, which `assume` /// fills, takes no part. pub fn solve(self: *Solver) !Status { return self.solveWithAssumptions(&.{}); } /// Saves the current length of the assumption list, so the next `popAssumptionFrame` returns /// the list to it. A caller that nests questions pushes a frame before it assumes the literals /// of an inner question. The call clears the recorded core and trace. The call returns /// `error.OutOfMemory` when the frame list fails to grow. pub fn pushAssumptionFrame(self: *Solver) !void { self.last_core.clearRetainingCapacity(); self.clearProofTrace(); try self.frames.append(self.allocator, self.assumptions.items.len); } /// Returns the assumption list to the length the latest push saved and closes that frame. A /// caller that nests questions pops a frame to leave an inner question. With no frame open, the /// list stays as it is. The call clears the recorded core and trace in both cases. pub fn popAssumptionFrame(self: *Solver) void { self.last_core.clearRetainingCapacity(); self.clearProofTrace(); const frame_start = self.frames.pop() orelse return; self.assumptions.shrinkRetainingCapacity(frame_start); } /// Adds `literal` to the solver's assumption list and adds its variable when the solver lacks /// it. `bitvec.Encoder` assumes the literal of each assumed term through it, for a later /// `solveWithActiveAssumptions`. The literal stays in the list until a pop past its frame or /// `clearAssumptionFrames`. The call clears the recorded core and trace. The call returns /// `error.OutOfMemory` when a list fails to grow. pub fn assume(self: *Solver, literal: Literal) !void { self.last_core.clearRetainingCapacity(); self.clearProofTrace(); try self.ensureVariable(literal.variable()); try self.assumptions.append(self.allocator, literal); } /// Empties the assumption list and closes every frame. A caller that starts a new round of /// questions calls it to drop every assumption and frame at once. The call clears the recorded /// core and trace. pub fn clearAssumptionFrames(self: *Solver) void { self.last_core.clearRetainingCapacity(); self.clearProofTrace(); self.assumptions.clearRetainingCapacity(); self.frames.clearRetainingCapacity(); } /// Solves under the solver's own assumption list, as `solveWithAssumptions` does. /// `bitvec.Encoder.solve` calls it, so the literals assumed with `assume` take part. pub fn solveWithActiveAssumptions(self: *Solver) !Status { return self.solveWithAssumptions(self.assumptions.items); } /// Returns the solver's assumption list, oldest first. A caller reads the assumptions in force /// after pushes and pops. The slice stays valid until the list changes. pub fn activeAssumptions(self: *const Solver) []const Literal { return self.assumptions.items; } /// Returns the number of open frames. A caller checks how deep its nesting is. pub fn frameDepth(self: *const Solver) usize { return self.frames.items.len; } /// Returns a set of the last solve's assumptions that the clauses refute together, after an /// unsatisfiable answer. A caller maps the core back to the named assumptions it made, to /// report which of them conflict. The solver first records as the core the assumptions it had /// assigned when the conflict came. When that recorded core holds two or more assumptions, the /// core is the smaller set that the extra solves of core minimization certified. The core is /// empty when the clauses were refuted before the search began, as by two opposite unit clauses /// or an empty clause, after a satisfiable or unknown answer, and after any change that clears /// it. A recorded core of one assumption stays as it is, because core minimization runs only /// for two or more, so the core can hold that assumption even when the clauses alone are /// unsatisfiable. A conflict while the solver assigns the assumptions records only those /// assigned so far, so a solve under two or more assumptions can end with a core of one and no /// shrinking. Under a conflict limit, the core holds every assumption when the limit ran out /// during the drops, and it is empty with an `.unknown` answer when the limit ran out during /// the certifying solve. The slice stays valid until the next change to the solver. pub fn lastUnsatCore(self: *const Solver) []const Literal { return self.last_core.items; } /// Returns the work counts of the last solve. A caller reports them beside the answer. A solve /// resets them at its start. After core minimization certifies a smaller core, `proof_steps` /// holds the certifying solve's step count, and it is the one count core minimization sets. The /// other counts leave out the work of the extra solves of core minimization. pub fn lastSolveStats(self: *const Solver) SolveStats { return self.last_stats; } /// Returns the proof steps of the last solve, in order. A caller reads the steps in place, and /// `lastProofArtifact` makes a copy that outlives later changes. The trace holds one step per /// learned clause and, after an unsatisfiable answer, a final empty clause. After a satisfiable /// or unknown answer, the trace can still hold the steps learned during the solve. The slices /// stay valid until the next change to the solver. pub fn lastProofTrace(self: *const Solver) []const ProofStep { return self.proof_steps.items; } /// Returns true when the trace is nonempty, each step follows by unit propagation from the /// starting clauses, the assumptions and the earlier steps, and the last step is the empty /// clause. A caller confirms an unsatisfiable answer in place. The check accepts every step /// while `has_empty_clause` is set. pub fn lastProofTraceValid(self: *const Solver) bool { if (self.proof_steps.items.len == 0) return false; for (self.proof_steps.items, 0..) |step, index| { if (!self.rupCheck(step.literals, index)) return false; } return self.proof_steps.items[self.proof_steps.items.len - 1].literals.len == 0; } /// Returns a copy of the clauses, assumptions and steps behind the last unsatisfiable answer, /// allocated with `allocator` and owned by the caller, or null when the trace is empty. A /// caller keeps the evidence after the solver moves on, checks it with `ProofArtifact.valid`, /// or writes it out. The starting clauses are every clause the solver held when the solve /// began, learned clauses it kept included, then an empty clause when `has_empty_clause` is /// set. The artifact covers the solver's variable count. After a solve that learned clauses and /// then answered `.sat`, or `.unknown` at the main search's conflict limit, the call returns an /// artifact that `ProofArtifact.valid` rejects. After an `.unknown` answer from the certifying /// solve of core minimization, the artifact holds the refutation under every assumption of the /// solve, and `ProofArtifact.valid` accepts it. The call returns `error.OutOfMemory` when a /// copy fails, and then frees what it copied. pub fn lastProofArtifact(self: *const Solver, allocator: std.mem.Allocator) !?ProofArtifact { if (self.proof_steps.items.len == 0) return null; assert(self.last_stats.proof_steps == self.proof_steps.items.len); var artifact = ProofArtifact.init(allocator, self.assignment.items.len); errdefer artifact.deinit(); const base_count = @min(self.proof_base_clause_count, self.clauses.items.len); for (self.clauses.items[0..base_count]) |clause| { try artifact.appendClause(clause.literals); } if (self.has_empty_clause) try artifact.appendClause(&.{}); try artifact.appendAssumptions(self.proof_assumptions.items); for (self.proof_steps.items) |step| { try artifact.appendStep(step.literals); } return artifact; } /// Decides whether the clauses and every literal of `assumptions` can all be true, and returns /// `.sat`, `.unsat` or `.unknown`. A caller asks a question under temporary hypotheses and /// learns which of them the clauses refute together. The solve assigns the assumptions first, /// in order, at decision level zero, and adds any variable they name that the solver lacks. /// After `.unsat`, `lastUnsatCore` holds one of three sets: the assumptions the solve had /// assigned when the conflict came, the smaller set that core minimization certified when that /// recorded core holds two or more, or every assumption of the solve when a conflict limit runs /// out while core minimization drops assumptions. When `assumptions` is nonempty, every clause /// added during the solve is removed when the solve returns. The solve clears the recorded /// core, trace and counts only after it has made room for conflict analysis, so a failure /// before that point leaves the old evidence in place. The call returns `error.OutOfMemory` /// when an allocation fails, `error.CapacityOverflow` when a size for the solve overflows /// `usize`, `error.InvalidProofTrace` when a learned clause or the final step fails its check, /// `error.InvalidConflictGraph` when conflict analysis runs out of assigned literals to resolve /// on, `error.InvalidUnsatCore` when the certifying solve satisfies the core, and the errors of /// `ConflictScratch`. The assignment stays after the call, and `value` and `literalValue` read /// it. pub fn solveWithAssumptions(self: *Solver, assumptions: []const Literal) !Status { return try self.solveWithAssumptionsMode(assumptions, true); } fn solveWithAssumptionsMode( self: *Solver, assumptions: []const Literal, minimize_core: bool, ) anyerror!Status { const required_variables = try self.requiredVariableCount(assumptions); const scratch_capacity = try self.ensureConflictScratchStorage(required_variables); self.clearSolveEvidence(); errdefer self.clearSolveEvidence(); self.conflicts_since_restart = 0; self.next_restart_conflicts = self.restart_policy.first_conflict_interval; for (assumptions) |assumption| { try self.ensureVariable(assumption.variable()); } if (self.max_learned_clauses != null) { self.backtrack(0); self.proof_base_clause_count = 0; self.reduceLearned(0, null); } try self.ensureLearnedStore(); try self.ensureProofTrace(); var conflict_scratch: ?scratch.ConflictScratch = null; if (scratch_capacity) |capacity| { const storage = self.conflictScratchStorage(capacity); conflict_scratch = try scratch.ConflictScratch.init( storage, .{ .variables = capacity.variables }, ); conflict_scratch.?.activate(); } defer if (conflict_scratch) |*owner| { const expected_pointer = @intFromPtr(owner.storage.ptr); const expected_length = owner.storage.len; const returned = owner.deinit(); assert(expected_pointer == @intFromPtr(returned.ptr)); assert(expected_length == returned.len); }; const retained_clause_count = self.clauses.items.len; defer if (assumptions.len > 0) self.discardClausesFrom(retained_clause_count); self.proof_base_clause_count = retained_clause_count; try self.proof_assumptions.appendSlice(self.allocator, assumptions); self.clearSearch(); if (self.inconsistent) { self.recordConflict(); try self.recordFinalProofStep(); return .unsat; } for (assumptions, 0..) |assumption, assumption_index| { try self.ensureVariable(assumption.variable()); if (!try self.enqueue(assumption, null)) { self.recordConflict(); return try self.finishAssumptionUnsat( assumptions[0 .. assumption_index + 1], minimize_core, ); } switch (try self.propagate()) { .consistent => {}, .conflict => { self.recordConflict(); return try self.finishAssumptionUnsat( assumptions[0 .. assumption_index + 1], minimize_core, ); }, } } while (true) { switch (try self.propagate()) { .consistent => {}, .conflict => |clause_index| { self.recordConflict(); if (self.decisionLevel() == 0) { return try self.finishAssumptionUnsat(assumptions, minimize_core); } if (!try self.learnFromConflict(&conflict_scratch.?, clause_index)) { if (assumptions.len == 0) self.inconsistent = true; return try self.finishAssumptionUnsat(assumptions, minimize_core); } if (self.conflict_budget) |budget| { if (self.last_stats.conflicts >= budget) return .unknown; } self.maybeRestart(); continue; }, } if (self.nextUnassignedVariable()) |variable_index| { try self.newDecisionLevel(); self.last_stats.decisions += 1; const decision_literal = self.decisionLiteral(variable_index); if (self.saved_phase.items[variable_index] != .unset) { self.last_stats.phase_saved_decisions += 1; } if (!try self.enqueue(decision_literal, null)) { self.recordConflict(); try self.recordFinalProofStep(); return .unsat; } continue; } return .sat; } } /// Returns the value of `variable_index` in the current assignment, or null when the variable /// is unassigned or at or above the variable count. A caller reads a satisfying assignment /// after `.sat`. The values form a satisfying assignment only after `.sat`. pub fn value(self: *const Solver, variable_index: u32) ?bool { if (variable_index >= self.assignment.items.len) return null; return switch (self.assignment.items[variable_index]) { .unset => null, .false => false, .true => true, }; } fn finishAssumptionUnsat( self: *Solver, assumptions: []const Literal, minimize_core: bool, ) anyerror!Status { if (assumptions.len > 0) try self.recordUnsatCore(assumptions); try self.recordFinalProofStep(); if (minimize_core and assumptions.len > 1) return try self.minimizeLastUnsatCore(); return .unsat; } fn minimizeLastUnsatCore(self: *Solver) anyerror!Status { var pool: ?usize = if (self.conflict_budget) |budget| budget -| self.last_stats.conflicts else null; var core: std.ArrayList(Literal) = .empty; defer core.deinit(self.allocator); try core.appendSlice(self.allocator, self.last_core.items); var trial: std.ArrayList(Literal) = .empty; defer trial.deinit(self.allocator); var index: usize = 0; while (index < core.items.len) { if (poolDrained(pool)) break; trial.clearRetainingCapacity(); for (core.items, 0..) |literal, candidate_index| { if (candidate_index != index) try trial.append(self.allocator, literal); } const outcome = try self.probeStatusWithAssumptions(trial.items, pool); drainPool(&pool, outcome.conflicts); if (outcome.status == .unsat) { core.clearRetainingCapacity(); try core.appendSlice(self.allocator, trial.items); } else { index += 1; } } if (!poolDrained(pool)) { var probe = try self.baseProbe(pool); defer probe.deinit(); const certified = try probe.solveWithAssumptionsMode(core.items, false); drainPool(&pool, probe.lastSolveStats().conflicts); switch (certified) { .sat => return error.InvalidUnsatCore, .unknown => { self.last_core.clearRetainingCapacity(); return .unknown; }, .unsat => { const base_count = self.proof_base_clause_count; self.clearProofTrace(); self.proof_base_clause_count = base_count; try self.proof_assumptions.appendSlice(self.allocator, probe.lastUnsatCore()); for (probe.proof_steps.items) |step| { try self.appendStepStorage(step.literals); } self.last_stats.proof_steps = self.proof_steps.items.len; try self.recordUnsatCore(probe.lastUnsatCore()); return .unsat; }, } } try self.recordUnsatCore(self.proof_assumptions.items); return .unsat; } fn poolDrained(pool: ?usize) bool { return if (pool) |remaining| remaining == 0 else false; } fn drainPool(pool: *?usize, spent: usize) void { if (pool.*) |remaining| pool.* = remaining -| spent; } fn probeStatusWithAssumptions( self: *const Solver, assumptions: []const Literal, pool: ?usize, ) anyerror!ProbeOutcome { var probe = try self.baseProbe(pool); defer probe.deinit(); const status = try probe.solveWithAssumptionsMode(assumptions, false); return .{ .status = status, .conflicts = probe.lastSolveStats().conflicts }; } fn baseProbe(self: *const Solver, pool: ?usize) anyerror!Solver { var probe = Solver.init(self.allocator); errdefer probe.deinit(); probe.conflict_budget = pool; probe.proof_trace_slab = false; probe.max_learned_clauses = self.max_learned_clauses; probe.setRestartPolicy(self.restart_policy); for (self.clauses.items) |clause| { if (!clause.learned) try probe.addClause(clause.literals); } if (self.has_empty_clause) try probe.addClause(&.{}); return probe; } fn recordUnsatCore(self: *Solver, assumptions: []const Literal) !void { self.last_core.clearRetainingCapacity(); try self.last_core.appendSlice(self.allocator, assumptions); } fn recordConflict(self: *Solver) void { self.last_stats.conflicts += 1; self.conflicts_since_restart += 1; if (self.decisionLevel() == 0) self.last_stats.root_conflicts += 1; } fn clearProofTrace(self: *Solver) void { if (self.proof_trace) |*owner| { for (self.proof_steps.items) |step| { if (step.literals.len == 0) continue; assert(owner.owns(step.literals)); } owner.clear(); } else { for (self.proof_steps.items) |step| { self.allocator.free(step.literals); } } self.proof_steps.clearRetainingCapacity(); self.proof_assumptions.clearRetainingCapacity(); self.proof_base_clause_count = 0; } fn clearSolveEvidence(self: *Solver) void { self.clearProofTrace(); self.last_core.clearRetainingCapacity(); self.last_stats = .{}; } fn acquireStepStorage(self: *Solver, literals: []const Literal) ![]Literal { if (self.proof_trace) |*owner| { if (literals.len == 0) return owner.acquireEmpty(); return owner.acquire(literals); } return try self.allocator.dupe(Literal, literals); } fn appendStepStorage(self: *Solver, literals: []const Literal) !void { const owned = try self.acquireStepStorage(literals); if (self.proof_trace != null) { assert(self.proof_steps.items.len < self.proof_steps.capacity); self.proof_steps.appendAssumeCapacity(.{ .literals = owned }); return; } errdefer self.allocator.free(owned); try self.proof_steps.append(self.allocator, .{ .literals = owned }); } fn appendProofStep(self: *Solver, literals: []const Literal) !void { try self.appendStepStorage(literals); self.last_stats.proof_steps += 1; } fn removeLastProofStep(self: *Solver) void { const step = self.proof_steps.pop() orelse return; if (self.proof_trace) |*owner| { owner.releaseLast(step.literals); } else { self.allocator.free(step.literals); } self.last_stats.proof_steps -= 1; } fn recordFinalProofStep(self: *Solver) !void { if (!self.rupCheck(&.{}, self.proof_steps.items.len)) return error.InvalidProofTrace; try self.appendProofStep(&.{}); } fn traceBudget(self: *const Solver) ?usize { if (!self.proof_trace_slab) return null; return self.conflict_budget; } fn rupCheck(self: *const Solver, literals: []const Literal, proof_step_limit: usize) bool { if (self.has_empty_clause) return true; assert(self.rup_assignment.items.len == self.assignment.items.len); const base_count = @min(self.proof_base_clause_count, self.clauses.items.len); return proof.rupCheckKnownVariablesWithClauses( self.rup_assignment.items, Clause, self.clauses.items[0..base_count], self.proof_assumptions.items, self.proof_steps.items, literals, proof_step_limit, ); } fn rupCheckConflict(self: *const Solver, literals: []const Literal, conflict: usize) bool { return proof.rupCheckKnownVariablesWithReasons( self.rup_assignment.items, Clause, self.clauses.items, self.proof_assumptions.items, literals, .{ .trail = self.trail.items, .reasons = self.reason.items, .conflict = conflict }, ); } fn ensureProofTrace(self: *Solver) !void { assert(self.proof_steps.items.len == 0); const budget = self.traceBudget() orelse { if (self.proof_trace) |*owner| { owner.deinit(self.allocator); self.proof_trace = null; } return; }; const limits = trace.Trace.Limits.inspect(budget, self.variableCount()); const required = try trace.Trace.Capacity.derive(limits); if (self.proof_trace) |*existing| { if (existing.admits(required)) { try self.proof_steps.ensureTotalCapacity(self.allocator, existing.capacity.steps); return; } existing.deinit(self.allocator); self.proof_trace = null; } var fresh = try trace.Trace.init(self.allocator, limits); fresh.activate(); self.proof_trace = fresh; try self.proof_steps.ensureTotalCapacity(self.allocator, required.steps); } fn requiredVariableCount( self: *const Solver, assumptions: []const Literal, ) error{CapacityOverflow}!usize { var required = self.variableCount(); for (assumptions) |assumption| { const assumption_variables = std.math.add( usize, @as(usize, assumption.variable()), 1, ) catch return error.CapacityOverflow; required = @max(required, assumption_variables); } return required; } fn ensureConflictScratchStorage( self: *Solver, required_variables: usize, ) !?scratch.ConflictScratch.Capacity { if (required_variables == 0) return null; const limits = scratch.ConflictScratch.Limits.inspect(required_variables); const required = try scratch.ConflictScratch.Capacity.derive(limits); try self.trail.ensureTotalCapacityPrecise( self.allocator, required.trail_capacity, ); return required; } fn conflictScratchStorage( self: *Solver, capacity: scratch.ConflictScratch.Capacity, ) scratch.ConflictScratch.Storage { assert(self.trail.items.len <= capacity.variables); assert(self.trail.capacity >= capacity.trail_capacity); const backing = self.trail.allocatedSlice()[capacity.variables..capacity.trail_capacity]; const bytes = std.mem.sliceAsBytes(backing); assert(bytes.len >= capacity.storage_bytes); return @alignCast(bytes[0..capacity.storage_bytes]); } fn ensureLearnedStore(self: *Solver) !void { const limit = self.max_learned_clauses orelse { try self.evacuateLearnedStore(); return; }; const limits = store.Store.Limits.inspect(limit, self.variableCount()); const required = try store.Store.Capacity.derive(limits); if (self.learned_store) |*existing| { if (existing.admits(required)) return; } var fresh = try store.Store.init(self.allocator, limits); fresh.activate(); if (self.learned_store) |*old| { for (self.clauses.items) |*clause| { if (clause.storage == .pool) { assert(old.owns(clause.literals)); clause.literals = fresh.acquire(clause.literals); } } old.deinit(self.allocator); } self.learned_store = fresh; } fn evacuateLearnedStore(self: *Solver) !void { if (self.learned_store == null) return; for (self.clauses.items) |*clause| { if (clause.storage == .pool) { const heap_copy = try self.allocator.dupe(Literal, clause.literals); self.learnedPool().release(clause.literals); clause.literals = heap_copy; clause.storage = .heap; } } self.learnedPool().deinit(self.allocator); self.learned_store = null; } fn maybeRestart(self: *Solver) void { if (self.next_restart_conflicts != 0 and self.decisionLevel() > 0 and self.conflicts_since_restart >= self.next_restart_conflicts) { self.backtrack(0); self.last_stats.restarts += 1; self.conflicts_since_restart = 0; if (self.restart_policy.growth > 1) { self.next_restart_conflicts = std.math.mul( usize, self.next_restart_conflicts, self.restart_policy.growth, ) catch std.math.maxInt(usize); } } const limit = self.max_learned_clauses orelse return; if (self.replaceableLearnedClauses() <= limit) return; assert(self.clauses.items.len > 0); if (self.decisionLevel() > 0) { self.backtrack(0); self.last_stats.restarts += 1; self.conflicts_since_restart = 0; } const just_learned = self.clauses.items.len - 1; const protected = if (just_learned >= self.proof_base_clause_count) just_learned else null; self.reduceLearned(self.proof_base_clause_count, protected); } fn reduceLearned(self: *Solver, first_candidate: usize, protected: ?usize) void { const limit = self.max_learned_clauses orelse return; assert(self.decisionLevel() == 0); assert(first_candidate >= self.proof_base_clause_count); assert(self.learned_clause_count == self.countLearnedClauses()); assert(self.glue_clause_count == self.countGlueClauses()); var bound = self.clauses.items.len; while (self.replaceableLearnedClauses() > limit and bound > 0) : (bound -= 1) { const victim = self.selectVictim(first_candidate, protected) orelse break; self.removeLearnedClause(victim); self.last_stats.evicted_clauses += 1; } } fn selectVictim(self: *const Solver, first_candidate: usize, protected: ?usize) ?usize { assert(first_candidate <= self.clauses.items.len); var worst: ?usize = null; for (self.clauses.items[first_candidate..], first_candidate..) |clause, clause_index| { if (!clause.learned) continue; if (clause.lbd <= glue_lbd_max) continue; if (protected == clause_index) continue; if (self.clauseLocked(clause_index)) continue; if (worst) |current| { if (self.evictsBefore(clause_index, current)) worst = clause_index; } else { worst = clause_index; } } return worst; } fn evictsBefore(self: *const Solver, left_index: usize, right_index: usize) bool { const left = self.clauses.items[left_index]; const right = self.clauses.items[right_index]; if (left.lbd != right.lbd) return left.lbd > right.lbd; return left.literals.len > right.literals.len; } fn countLearnedClauses(self: *const Solver) usize { var count: usize = 0; for (self.clauses.items) |clause| { if (clause.learned) count += 1; } return count; } fn countGlueClauses(self: *const Solver) usize { var count: usize = 0; for (self.clauses.items) |clause| { if (clause.learned and clause.lbd <= glue_lbd_max) count += 1; } return count; } /// Returns the value of `literal` in the current assignment: `.true`, `.false`, or `.unset` /// when its variable is unassigned or at or above the variable count. `bitvec.Encoder` reads /// each Boolean of a model through it. The values form a satisfying assignment only after /// `.sat`. pub fn literalValue(self: *const Solver, literal: Literal) BoolValue { if (literal.variable() >= self.assignment.items.len) return .unset; const assigned = self.assignment.items[literal.variable()]; return if (literal.isPositive()) assigned else assigned.invert(); } fn ensureVariable(self: *Solver, variable_index: u32) !void { const needed = @as(usize, variable_index) + 1; while (self.assignment.items.len < needed) { try self.assignment.append(self.allocator, .unset); errdefer _ = self.assignment.pop(); try self.saved_phase.append(self.allocator, .unset); errdefer _ = self.saved_phase.pop(); try self.level.append(self.allocator, 0); errdefer _ = self.level.pop(); try self.reason.append(self.allocator, null); errdefer _ = self.reason.pop(); try self.rup_assignment.append(self.allocator, .unset); errdefer _ = self.rup_assignment.pop(); try self.watches.append(self.allocator, .empty); errdefer { var removed = self.watches.pop().?; removed.deinit(self.allocator); } try self.watches.append(self.allocator, .empty); } } fn addWatch(self: *Solver, literal: Literal, clause_index: usize) !void { try self.watches.items[literal.index()].append(self.allocator, .{ .index = clause_index }); } fn removeWatch(self: *Solver, literal: Literal, clause_index: usize) bool { const watch = &self.watches.items[literal.index()]; for (watch.items, 0..) |clause_ref, index| { if (clause_ref.index == clause_index) { _ = watch.swapRemove(index); return true; } } return false; } fn patchWatch(self: *Solver, literal: Literal, from_index: usize, to_index: usize) void { const watch = &self.watches.items[literal.index()]; for (watch.items) |*clause_ref| { if (clause_ref.index == from_index) { clause_ref.index = to_index; return; } } unreachable; } fn clauseLocked(self: *const Solver, clause_index: usize) bool { assert(clause_index < self.clauses.items.len); for (self.trail.items) |trail_literal| { const variable_index = trail_literal.variable(); if (self.reason.items[variable_index]) |reason_index| { if (reason_index == clause_index) return true; } } return false; } fn removeLearnedClause(self: *Solver, clause_index: usize) void { assert(self.decisionLevel() == 0); assert(clause_index >= self.proof_base_clause_count); assert(clause_index < self.clauses.items.len); const clause = self.clauses.items[clause_index]; assert(clause.learned); assert(!self.clauseLocked(clause_index)); const removed_first = self.removeWatch(clause.literals[clause.watch_a], clause_index); assert(removed_first); if (clause.watch_b != clause.watch_a) { const removed_second = self.removeWatch(clause.literals[clause.watch_b], clause_index); assert(removed_second); } const last_index = self.clauses.items.len - 1; _ = self.clauses.swapRemove(clause_index); if (clause_index != last_index) { const moved = self.clauses.items[clause_index]; self.patchWatch(moved.literals[moved.watch_a], last_index, clause_index); if (moved.watch_b != moved.watch_a) { self.patchWatch(moved.literals[moved.watch_b], last_index, clause_index); } for (self.trail.items) |trail_literal| { const variable_index = trail_literal.variable(); if (self.reason.items[variable_index]) |reason_index| { if (reason_index == last_index) { self.reason.items[variable_index] = clause_index; } } } } assert(self.learned_clause_count > 0); self.learned_clause_count -= 1; if (clause.lbd <= glue_lbd_max) { assert(self.glue_clause_count > 0); self.glue_clause_count -= 1; } self.freeClauseLiterals(clause); } fn clearSearch(self: *Solver) void { for (self.assignment.items) |*item| item.* = .unset; for (self.level.items) |*item| item.* = 0; for (self.reason.items) |*item| item.* = null; self.trail.clearRetainingCapacity(); self.decision_limits.clearRetainingCapacity(); self.propagation_cursor = 0; for (self.clauses.items, 0..) |clause, clause_index| { if (clause.literals.len == 1) { if (!(self.enqueue(clause.literals[0], clause_index) catch false)) { self.inconsistent = true; return; } } } } fn discardClausesFrom(self: *Solver, retained_clause_count: usize) void { while (self.clauses.items.len > retained_clause_count) { const clause_index = self.clauses.items.len - 1; const clause = self.clauses.pop().?; _ = self.removeWatch(clause.literals[clause.watch_a], clause_index); if (clause.watch_b != clause.watch_a) { _ = self.removeWatch(clause.literals[clause.watch_b], clause_index); } if (clause.learned) { assert(self.learned_clause_count > 0); self.learned_clause_count -= 1; if (clause.lbd <= glue_lbd_max) { assert(self.glue_clause_count > 0); self.glue_clause_count -= 1; } } self.freeClauseLiterals(clause); } } fn freeClauseLiterals(self: *Solver, clause: Clause) void { switch (clause.storage) { .heap => self.allocator.free(clause.literals), .pool => self.learnedPool().release(clause.literals), } } fn learnedPool(self: *Solver) *store.Store { assert(self.learned_store != null); return &self.learned_store.?; } fn decisionLevel(self: *const Solver) u32 { return @intCast(self.decision_limits.items.len); } fn newDecisionLevel(self: *Solver) !void { try self.decision_limits.append(self.allocator, self.trail.items.len); const level = self.decisionLevel(); if (level > self.last_stats.max_decision_level) { self.last_stats.max_decision_level = level; } } fn backtrack(self: *Solver, target_level: u32) void { while (self.decisionLevel() > target_level) { const start = self.decision_limits.pop().?; var index = self.trail.items.len; while (index > start) { index -= 1; const variable_index = self.trail.items[index].variable(); self.assignment.items[variable_index] = .unset; self.reason.items[variable_index] = null; self.level.items[variable_index] = 0; } self.trail.shrinkRetainingCapacity(start); if (self.propagation_cursor > start) self.propagation_cursor = start; } } fn enqueue(self: *Solver, literal: Literal, reason: ?usize) !bool { const variable_index = literal.variable(); assert(variable_index < self.variableCount()); const current = self.literalValue(literal); if (current == .true) return true; if (current == .false) return false; self.assignment.items[variable_index] = BoolValue.fromBool(literal.isPositive()); self.saved_phase.items[variable_index] = self.assignment.items[variable_index]; self.level.items[variable_index] = self.decisionLevel(); self.reason.items[variable_index] = reason; try self.trail.append(self.allocator, literal); return true; } fn propagate(self: *Solver) !PropagationResult { while (self.propagation_cursor < self.trail.items.len) { const literal = self.trail.items[self.propagation_cursor]; self.propagation_cursor += 1; const false_literal = literal.negated(); const watch = &self.watches.items[false_literal.index()]; var index: usize = 0; while (index < watch.items.len) { const clause_index = watch.items[index].index; const update = try self.propagateClause(clause_index, false_literal); switch (update) { .moved => { _ = watch.swapRemove(index); }, .kept => { index += 1; }, .unit => |unit_literal| { if (!try self.enqueue(unit_literal, clause_index)) { return .{ .conflict = clause_index }; } self.last_stats.propagations += 1; index += 1; }, .conflict => return .{ .conflict = clause_index }, } } } return .consistent; } fn propagateClause( self: *Solver, clause_index: usize, false_literal: Literal, ) !ClausePropagation { var clause = &self.clauses.items[clause_index]; const false_watch_is_a = clause.literals[clause.watch_a].raw == false_literal.raw; const false_watch = if (false_watch_is_a) clause.watch_a else clause.watch_b; const other_watch = if (false_watch_is_a) clause.watch_b else clause.watch_a; const other_literal = clause.literals[other_watch]; if (self.literalValue(other_literal) == .true) return .kept; for (clause.literals, 0..) |candidate, candidate_index| { if (candidate_index == other_watch or candidate_index == false_watch) continue; if (self.literalValue(candidate) != .false) { if (false_watch_is_a) { clause.watch_a = candidate_index; } else { clause.watch_b = candidate_index; } try self.addWatch(candidate, clause_index); return .moved; } } return switch (self.literalValue(other_literal)) { .unset => .{ .unit = other_literal }, .false => .conflict, .true => .kept, }; } fn learnFromConflict( self: *Solver, owner: *scratch.ConflictScratch, clause_index: usize, ) !bool { assert(owner.capacity.variables == self.variableCount()); const storage = self.conflictScratchStorage(owner.capacity); assert(storage.ptr == owner.storage.ptr); assert(storage.len == owner.storage.len); var loan: scratch.ConflictScratch.Loan = undefined; try owner.acquire(self.variableCount(), &loan); defer owner.release(&loan) catch unreachable; const conflict_level = self.decisionLevel(); var path_count: usize = 0; var clause_ref = clause_index; var cursor = self.trail.items.len; var resolved_literal: ?Literal = null; while (true) { try loan.recordResolution(); const clause = self.clauses.items[clause_ref]; for (clause.literals) |literal| { const variable_index = literal.variable(); if (!try loan.markSeen(variable_index)) continue; if (self.level.items[variable_index] == conflict_level) { path_count += 1; } else { try loan.append(literal); } } while (cursor > 0) { cursor -= 1; const trail_literal = self.trail.items[cursor]; if (try loan.isSeen(trail_literal.variable())) { resolved_literal = trail_literal; break; } } const pivot = resolved_literal orelse return error.InvalidConflictGraph; try loan.clearSeen(pivot.variable()); path_count -= 1; if (path_count == 0) { try loan.append(pivot.negated()); break; } clause_ref = self.reason.items[pivot.variable()] orelse { try loan.append(pivot.negated()); break; }; } const learned = try loan.literals(); var backtrack_level: u32 = 0; for (learned) |literal| { const literal_level = self.level.items[literal.variable()]; if (literal_level != conflict_level and literal_level > backtrack_level) { backtrack_level = literal_level; } } const lbd = self.blockDistance(learned); if (!self.rupCheckConflict(learned, clause_index)) return error.InvalidProofTrace; self.backtrack(backtrack_level); const assert_literal = learned[learned.len - 1]; try self.addLearnedClause(learned, lbd); return try self.enqueue(assert_literal, self.clauses.items.len - 1); } fn blockDistance(self: *const Solver, literals: []const Literal) u32 { assert(literals.len > 0); var distinct: u32 = 0; for (literals, 0..) |literal, index| { const literal_level = self.level.items[literal.variable()]; var counted = false; for (literals[0..index]) |prior| { if (self.level.items[prior.variable()] == literal_level) { counted = true; break; } } if (!counted) distinct += 1; } assert(distinct >= 1); assert(distinct <= literals.len); return distinct; } fn addLearnedClause(self: *Solver, literals: []const Literal, lbd: u32) !void { assert(lbd >= 1); assert(lbd <= literals.len); try self.appendProofStep(literals); errdefer self.removeLastProofStep(); const pooled = self.learned_store != null and lbd > glue_lbd_max; const owned = if (pooled) self.learnedPool().acquire(literals) else try self.allocator.dupe(Literal, literals); errdefer if (pooled) self.learnedPool().release(owned) else self.allocator.free(owned); const clause_index = self.clauses.items.len; const clause = Clause{ .literals = owned, .learned = true, .lbd = lbd, .storage = if (pooled) .pool else .heap, .watch_a = 0, .watch_b = if (owned.len > 1) 1 else 0, }; try self.clauses.append(self.allocator, clause); errdefer _ = self.clauses.pop(); try self.addWatch(owned[0], clause_index); errdefer _ = self.removeWatch(owned[0], clause_index); if (owned.len > 1) { try self.addWatch(owned[1], clause_index); } self.learned_clause_count += 1; if (lbd <= glue_lbd_max) self.glue_clause_count += 1; self.last_stats.learned_clauses += 1; } fn nextUnassignedVariable(self: *const Solver) ?u32 { for (self.assignment.items, 0..) |assigned_value, index| { if (assigned_value == .unset) return @intCast(index); } return null; } fn decisionLiteral(self: *const Solver, variable_index: u32) Literal { return switch (self.saved_phase.items[variable_index]) { .false => Literal.negative(variable_index), .true, .unset => Literal.positive(variable_index), }; }};Source: lib/smt/src/root.zig:103
zig
pub const Solver = sat.Solver;Also reachable as
Complete caller list for Solver.addClause
31 direct callers.
lib.smt.src.properties.model.loadedSolver[function] — private source atlib/smt/src/properties/model.zig:160in nearest public ownerlib.smt.src.properties.modellib.smt.src.sat.solver.Solver.baseProbe[method] — private source atlib/smt/src/sat/solver.zig:685in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_bounded_solve_preserves_status_and_proof_under_eviction[function] — test source atlib/smt/src/sat/solver.zig:1565in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_budgeted_solve_keeps_proof_steps_in_the_trace_slab[function] — test source atlib/smt/src/sat/solver.zig:1707in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_entry_eviction_enforces_a_newly_set_cap[function] — test source atlib/smt/src/sat/solver.zig:1785in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_eviction_removes_worst_lbd_first_then_longest_and_never_glue[function] — test source atlib/smt/src/sat/solver.zig:1480in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_learned_clause_records_multi-level_block_distance[function] — test source atlib/smt/src/sat/solver.zig:1893in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_learned_clause_records_single-level_block_distance[function] — test source atlib/smt/src/sat/solver.zig:1871in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_learned_store_pool_survives_variable_growth_and_cap_removal[function] — test source atlib/smt/src/sat/solver.zig:1651in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_proof_trace_survives_budget_growth_and_removal[function] — test source atlib/smt/src/sat/solver.zig:1742in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_removing_a_learned_clause_preserves_base_prefix_and_behavior[function] — test source atlib/smt/src/sat/solver.zig:1802in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_removing_a_middle_learned_clause_patches_the_moved_clause[function] — test source atlib/smt/src/sat/solver.zig:1826in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.test.checkSolveAllocationFailureEvidence[function] — private source atlib/smt/src/sat/test.zig:356in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_base_inconsistency_keeps_artifact_scope_broader_than_its_empty_core[function] — test source atlib/smt/src/sat/test.zig:91in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_conflict_budget_preserves_genuine_results_within_budget[function] — test source atlib/smt/src/sat/test.zig:498in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_conflict_budget_returns_unknown_instead_of_spinning[function] — test source atlib/smt/src/sat/test.zig:478in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_conflict_scratch_growth_rejects_before_solve_evidence_mutation_and_retries[function] — test source atlib/smt/src/sat/test.zig:161in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_proof_artifact_records_assumptions[function] — test source atlib/smt/src/sat/test.zig:241in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_accepts_simple_satisfiable_clauses[function] — test source atlib/smt/src/sat/test.zig:30in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_clears_proof_trace_after_satisfiable_solve[function] — test source atlib/smt/src/sat/test.zig:257in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_conflict_scratch_preserves_binary_implication_learning[function] — test source atlib/smt/src/sat/test.zig:114in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_detects_unsatisfiable_unit_conflict[function] — test source atlib/smt/src/sat/test.zig:74in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_exports_independent_proof_artifact[function] — test source atlib/smt/src/sat/test.zig:216in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_keeps_assumptions_through_learned_conflicts[function] — test source atlib/smt/src/sat/test.zig:426in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_keeps_core_proof_scope_and_step_statistics_aligned[function] — test source atlib/smt/src/sat/test.zig:327in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_prunes_irrelevant_assumptions_from_unsat_core[function] — test source atlib/smt/src/sat/test.zig:311in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_reports_unknown_when_core_certification_exhausts_budget[function] — test source atlib/smt/src/sat/test.zig:405in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_restarts_after_learned_conflicts[function] — test source atlib/smt/src/sat/test.zig:273in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_saves_phases_across_solves[function] — test source atlib/smt/src/sat/test.zig:55in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_supports_assumptions[function] — test source atlib/smt/src/sat/test.zig:289in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_supports_nested_assumption_frames[function] — test source atlib/smt/src/sat/test.zig:445in nearest public ownerlib.smt.src.sat.test
Complete caller list for Solver.addVariable
32 direct callers.
lib.smt.src.properties.model.loadedSolver[function] — private source atlib/smt/src/properties/model.zig:160in nearest public ownerlib.smt.src.properties.modellib.smt.src.sat.solver.test_bounded_solve_preserves_status_and_proof_under_eviction[function] — test source atlib/smt/src/sat/solver.zig:1565in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_budgeted_solve_keeps_proof_steps_in_the_trace_slab[function] — test source atlib/smt/src/sat/solver.zig:1707in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_entry_eviction_enforces_a_newly_set_cap[function] — test source atlib/smt/src/sat/solver.zig:1785in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_eviction_removes_worst_lbd_first_then_longest_and_never_glue[function] — test source atlib/smt/src/sat/solver.zig:1480in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_eviction_skips_locked_and_protected_clauses[function] — test source atlib/smt/src/sat/solver.zig:1536in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_learned_clause_records_multi-level_block_distance[function] — test source atlib/smt/src/sat/solver.zig:1893in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_learned_clause_records_single-level_block_distance[function] — test source atlib/smt/src/sat/solver.zig:1871in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_learned_store_pool_survives_variable_growth_and_cap_removal[function] — test source atlib/smt/src/sat/solver.zig:1651in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_proof_trace_survives_budget_growth_and_removal[function] — test source atlib/smt/src/sat/solver.zig:1742in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_removing_a_learned_clause_preserves_base_prefix_and_behavior[function] — test source atlib/smt/src/sat/solver.zig:1802in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_removing_a_middle_learned_clause_patches_the_moved_clause[function] — test source atlib/smt/src/sat/solver.zig:1826in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.test.checkSolveAllocationFailureEvidence[function] — private source atlib/smt/src/sat/test.zig:356in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_base_inconsistency_keeps_artifact_scope_broader_than_its_empty_core[function] — test source atlib/smt/src/sat/test.zig:91in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_conflict_budget_preserves_genuine_results_within_budget[function] — test source atlib/smt/src/sat/test.zig:498in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_conflict_budget_returns_unknown_instead_of_spinning[function] — test source atlib/smt/src/sat/test.zig:478in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_conflict_scratch_growth_rejects_before_solve_evidence_mutation_and_retries[function] — test source atlib/smt/src/sat/test.zig:161in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_proof_artifact_records_assumptions[function] — test source atlib/smt/src/sat/test.zig:241in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_accepts_simple_satisfiable_clauses[function] — test source atlib/smt/src/sat/test.zig:30in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_clears_proof_trace_after_satisfiable_solve[function] — test source atlib/smt/src/sat/test.zig:257in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_conflict_scratch_preserves_binary_implication_learning[function] — test source atlib/smt/src/sat/test.zig:114in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_detects_unsatisfiable_unit_conflict[function] — test source atlib/smt/src/sat/test.zig:74in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_exports_independent_proof_artifact[function] — test source atlib/smt/src/sat/test.zig:216in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_keeps_assumptions_through_learned_conflicts[function] — test source atlib/smt/src/sat/test.zig:426in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_keeps_core_proof_scope_and_step_statistics_aligned[function] — test source atlib/smt/src/sat/test.zig:327in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_prunes_irrelevant_assumptions_from_unsat_core[function] — test source atlib/smt/src/sat/test.zig:311in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_reports_decision_stats[function] — test source atlib/smt/src/sat/test.zig:42in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_reports_unknown_when_core_certification_exhausts_budget[function] — test source atlib/smt/src/sat/test.zig:405in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_restarts_after_learned_conflicts[function] — test source atlib/smt/src/sat/test.zig:273in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_saves_phases_across_solves[function] — test source atlib/smt/src/sat/test.zig:55in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_supports_assumptions[function] — test source atlib/smt/src/sat/test.zig:289in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_supports_nested_assumption_frames[function] — test source atlib/smt/src/sat/test.zig:445in nearest public ownerlib.smt.src.sat.test
Complete caller list for Solver.deinit
37 direct callers.
lib.smt.src.profiling.sat.boundedConflictChurn[function] — private source atlib/smt/src/profiling/sat.zig:117in nearest public ownerlib.smt.src.profiling.satlib.smt.src.profiling.sat.incrementalAssumptions[function] — private source atlib/smt/src/profiling/sat.zig:151in nearest public ownerlib.smt.src.profiling.satlib.smt.src.profiling.sat.pigeonholeUnsat[function] — private source atlib/smt/src/profiling/sat.zig:137in nearest public ownerlib.smt.src.profiling.satlib.smt.src.profiling.sat.randomConflictChurn[function] — private source atlib/smt/src/profiling/sat.zig:101in nearest public ownerlib.smt.src.profiling.satlib.smt.src.properties.model.loadedSolver[function] — private source atlib/smt/src/properties/model.zig:160in nearest public ownerlib.smt.src.properties.modellib.smt.src.sat.solver.Solver.baseProbe[method] — private source atlib/smt/src/sat/solver.zig:685in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_bounded_solve_preserves_status_and_proof_under_eviction[function] — test source atlib/smt/src/sat/solver.zig:1565in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_budgeted_solve_keeps_proof_steps_in_the_trace_slab[function] — test source atlib/smt/src/sat/solver.zig:1707in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_entry_eviction_enforces_a_newly_set_cap[function] — test source atlib/smt/src/sat/solver.zig:1785in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_eviction_removes_worst_lbd_first_then_longest_and_never_glue[function] — test source atlib/smt/src/sat/solver.zig:1480in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_eviction_skips_locked_and_protected_clauses[function] — test source atlib/smt/src/sat/solver.zig:1536in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_learned_clause_records_multi-level_block_distance[function] — test source atlib/smt/src/sat/solver.zig:1893in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_learned_clause_records_single-level_block_distance[function] — test source atlib/smt/src/sat/solver.zig:1871in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_learned_store_pool_survives_variable_growth_and_cap_removal[function] — test source atlib/smt/src/sat/solver.zig:1651in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_proof_trace_survives_budget_growth_and_removal[function] — test source atlib/smt/src/sat/solver.zig:1742in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_removing_a_learned_clause_preserves_base_prefix_and_behavior[function] — test source atlib/smt/src/sat/solver.zig:1802in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_removing_a_middle_learned_clause_patches_the_moved_clause[function] — test source atlib/smt/src/sat/solver.zig:1826in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.test.checkSolveAllocationFailureEvidence[function] — private source atlib/smt/src/sat/test.zig:356in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_base_inconsistency_keeps_artifact_scope_broader_than_its_empty_core[function] — test source atlib/smt/src/sat/test.zig:91in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_conflict_budget_preserves_genuine_results_within_budget[function] — test source atlib/smt/src/sat/test.zig:498in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_conflict_budget_returns_unknown_instead_of_spinning[function] — test source atlib/smt/src/sat/test.zig:478in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_conflict_scratch_growth_rejects_before_solve_evidence_mutation_and_retries[function] — test source atlib/smt/src/sat/test.zig:161in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_proof_artifact_records_assumptions[function] — test source atlib/smt/src/sat/test.zig:241in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_accepts_simple_satisfiable_clauses[function] — test source atlib/smt/src/sat/test.zig:30in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_clears_proof_trace_after_satisfiable_solve[function] — test source atlib/smt/src/sat/test.zig:257in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_conflict_scratch_preserves_binary_implication_learning[function] — test source atlib/smt/src/sat/test.zig:114in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_detects_unsatisfiable_unit_conflict[function] — test source atlib/smt/src/sat/test.zig:74in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_exports_independent_proof_artifact[function] — test source atlib/smt/src/sat/test.zig:216in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_keeps_assumptions_through_learned_conflicts[function] — test source atlib/smt/src/sat/test.zig:426in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_keeps_core_proof_scope_and_step_statistics_aligned[function] — test source atlib/smt/src/sat/test.zig:327in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_prunes_irrelevant_assumptions_from_unsat_core[function] — test source atlib/smt/src/sat/test.zig:311in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_reports_decision_stats[function] — test source atlib/smt/src/sat/test.zig:42in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_reports_unknown_when_core_certification_exhausts_budget[function] — test source atlib/smt/src/sat/test.zig:405in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_restarts_after_learned_conflicts[function] — test source atlib/smt/src/sat/test.zig:273in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_saves_phases_across_solves[function] — test source atlib/smt/src/sat/test.zig:55in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_supports_assumptions[function] — test source atlib/smt/src/sat/test.zig:289in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_supports_nested_assumption_frames[function] — test source atlib/smt/src/sat/test.zig:445in nearest public ownerlib.smt.src.sat.test
Complete caller list for Solver.init
37 direct callers.
lib.smt.src.profiling.sat.boundedConflictChurn[function] — private source atlib/smt/src/profiling/sat.zig:117in nearest public ownerlib.smt.src.profiling.satlib.smt.src.profiling.sat.incrementalAssumptions[function] — private source atlib/smt/src/profiling/sat.zig:151in nearest public ownerlib.smt.src.profiling.satlib.smt.src.profiling.sat.pigeonholeUnsat[function] — private source atlib/smt/src/profiling/sat.zig:137in nearest public ownerlib.smt.src.profiling.satlib.smt.src.profiling.sat.randomConflictChurn[function] — private source atlib/smt/src/profiling/sat.zig:101in nearest public ownerlib.smt.src.profiling.satlib.smt.src.properties.model.loadedSolver[function] — private source atlib/smt/src/properties/model.zig:160in nearest public ownerlib.smt.src.properties.modellib.smt.src.sat.solver.Solver.baseProbe[method] — private source atlib/smt/src/sat/solver.zig:685in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_bounded_solve_preserves_status_and_proof_under_eviction[function] — test source atlib/smt/src/sat/solver.zig:1565in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_budgeted_solve_keeps_proof_steps_in_the_trace_slab[function] — test source atlib/smt/src/sat/solver.zig:1707in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_entry_eviction_enforces_a_newly_set_cap[function] — test source atlib/smt/src/sat/solver.zig:1785in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_eviction_removes_worst_lbd_first_then_longest_and_never_glue[function] — test source atlib/smt/src/sat/solver.zig:1480in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_eviction_skips_locked_and_protected_clauses[function] — test source atlib/smt/src/sat/solver.zig:1536in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_learned_clause_records_multi-level_block_distance[function] — test source atlib/smt/src/sat/solver.zig:1893in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_learned_clause_records_single-level_block_distance[function] — test source atlib/smt/src/sat/solver.zig:1871in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_learned_store_pool_survives_variable_growth_and_cap_removal[function] — test source atlib/smt/src/sat/solver.zig:1651in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_proof_trace_survives_budget_growth_and_removal[function] — test source atlib/smt/src/sat/solver.zig:1742in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_removing_a_learned_clause_preserves_base_prefix_and_behavior[function] — test source atlib/smt/src/sat/solver.zig:1802in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_removing_a_middle_learned_clause_patches_the_moved_clause[function] — test source atlib/smt/src/sat/solver.zig:1826in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.test.checkSolveAllocationFailureEvidence[function] — private source atlib/smt/src/sat/test.zig:356in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_base_inconsistency_keeps_artifact_scope_broader_than_its_empty_core[function] — test source atlib/smt/src/sat/test.zig:91in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_conflict_budget_preserves_genuine_results_within_budget[function] — test source atlib/smt/src/sat/test.zig:498in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_conflict_budget_returns_unknown_instead_of_spinning[function] — test source atlib/smt/src/sat/test.zig:478in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_conflict_scratch_growth_rejects_before_solve_evidence_mutation_and_retries[function] — test source atlib/smt/src/sat/test.zig:161in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_proof_artifact_records_assumptions[function] — test source atlib/smt/src/sat/test.zig:241in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_accepts_simple_satisfiable_clauses[function] — test source atlib/smt/src/sat/test.zig:30in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_clears_proof_trace_after_satisfiable_solve[function] — test source atlib/smt/src/sat/test.zig:257in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_conflict_scratch_preserves_binary_implication_learning[function] — test source atlib/smt/src/sat/test.zig:114in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_detects_unsatisfiable_unit_conflict[function] — test source atlib/smt/src/sat/test.zig:74in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_exports_independent_proof_artifact[function] — test source atlib/smt/src/sat/test.zig:216in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_keeps_assumptions_through_learned_conflicts[function] — test source atlib/smt/src/sat/test.zig:426in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_keeps_core_proof_scope_and_step_statistics_aligned[function] — test source atlib/smt/src/sat/test.zig:327in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_prunes_irrelevant_assumptions_from_unsat_core[function] — test source atlib/smt/src/sat/test.zig:311in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_reports_decision_stats[function] — test source atlib/smt/src/sat/test.zig:42in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_reports_unknown_when_core_certification_exhausts_budget[function] — test source atlib/smt/src/sat/test.zig:405in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_restarts_after_learned_conflicts[function] — test source atlib/smt/src/sat/test.zig:273in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_saves_phases_across_solves[function] — test source atlib/smt/src/sat/test.zig:55in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_supports_assumptions[function] — test source atlib/smt/src/sat/test.zig:289in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_supports_nested_assumption_frames[function] — test source atlib/smt/src/sat/test.zig:445in nearest public ownerlib.smt.src.sat.test
Complete caller list for Solver.lastProofTraceValid
7 direct callers.
lib.smt.src.sat.solver.test_bounded_solve_preserves_status_and_proof_under_eviction[function] — test source atlib/smt/src/sat/solver.zig:1565in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_budgeted_solve_keeps_proof_steps_in_the_trace_slab[function] — test source atlib/smt/src/sat/solver.zig:1707in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_proof_trace_survives_budget_growth_and_removal[function] — test source atlib/smt/src/sat/solver.zig:1742in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.test.test_conflict_scratch_growth_rejects_before_solve_evidence_mutation_and_retries[function] — test source atlib/smt/src/sat/test.zig:161in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_clears_proof_trace_after_satisfiable_solve[function] — test source atlib/smt/src/sat/test.zig:257in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_conflict_scratch_preserves_binary_implication_learning[function] — test source atlib/smt/src/sat/test.zig:114in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_detects_unsatisfiable_unit_conflict[function] — test source atlib/smt/src/sat/test.zig:74in nearest public ownerlib.smt.src.sat.test
Complete caller list for Solver.lastSolveStats
13 direct callers.
lib.smt.src.profiling.sat.boundedConflictChurn[function] — private source atlib/smt/src/profiling/sat.zig:117in nearest public ownerlib.smt.src.profiling.satlib.smt.src.profiling.sat.pigeonholeUnsat[function] — private source atlib/smt/src/profiling/sat.zig:137in nearest public ownerlib.smt.src.profiling.satlib.smt.src.profiling.sat.randomConflictChurn[function] — private source atlib/smt/src/profiling/sat.zig:101in nearest public ownerlib.smt.src.profiling.satlib.smt.src.sat.solver.test_bounded_solve_preserves_status_and_proof_under_eviction[function] — test source atlib/smt/src/sat/solver.zig:1565in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_entry_eviction_enforces_a_newly_set_cap[function] — test source atlib/smt/src/sat/solver.zig:1785in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.test.checkSolveAllocationFailureEvidence[function] — private source atlib/smt/src/sat/test.zig:356in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_conflict_budget_returns_unknown_instead_of_spinning[function] — test source atlib/smt/src/sat/test.zig:478in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_conflict_scratch_preserves_binary_implication_learning[function] — test source atlib/smt/src/sat/test.zig:114in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_detects_unsatisfiable_unit_conflict[function] — test source atlib/smt/src/sat/test.zig:74in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_keeps_core_proof_scope_and_step_statistics_aligned[function] — test source atlib/smt/src/sat/test.zig:327in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_reports_decision_stats[function] — test source atlib/smt/src/sat/test.zig:42in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_restarts_after_learned_conflicts[function] — test source atlib/smt/src/sat/test.zig:273in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_saves_phases_across_solves[function] — test source atlib/smt/src/sat/test.zig:55in nearest public ownerlib.smt.src.sat.test
Complete caller list for Solver.lastUnsatCore
9 direct callers.
lib.smt.src.sat.test.checkSolveAllocationFailureEvidence[function] — private source atlib/smt/src/sat/test.zig:356in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_base_inconsistency_keeps_artifact_scope_broader_than_its_empty_core[function] — test source atlib/smt/src/sat/test.zig:91in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_detects_unsatisfiable_unit_conflict[function] — test source atlib/smt/src/sat/test.zig:74in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_keeps_assumptions_through_learned_conflicts[function] — test source atlib/smt/src/sat/test.zig:426in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_keeps_core_proof_scope_and_step_statistics_aligned[function] — test source atlib/smt/src/sat/test.zig:327in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_prunes_irrelevant_assumptions_from_unsat_core[function] — test source atlib/smt/src/sat/test.zig:311in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_reports_unknown_when_core_certification_exhausts_budget[function] — test source atlib/smt/src/sat/test.zig:405in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_supports_assumptions[function] — test source atlib/smt/src/sat/test.zig:289in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_supports_nested_assumption_frames[function] — test source atlib/smt/src/sat/test.zig:445in nearest public ownerlib.smt.src.sat.test
Complete caller list for Solver.replaceableLearnedClauses
7 direct callers.
lib.smt.src.profiling.sat.boundedConflictChurn[function] — private source atlib/smt/src/profiling/sat.zig:117in nearest public ownerlib.smt.src.profiling.satlib.smt.src.sat.solver.Solver.maybeRestart[method] — private source atlib/smt/src/sat/solver.zig:908in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.Solver.reduceLearned[method] — private source atlib/smt/src/sat/solver.zig:937in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_bounded_solve_preserves_status_and_proof_under_eviction[function] — test source atlib/smt/src/sat/solver.zig:1565in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_entry_eviction_enforces_a_newly_set_cap[function] — test source atlib/smt/src/sat/solver.zig:1785in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_eviction_removes_worst_lbd_first_then_longest_and_never_glue[function] — test source atlib/smt/src/sat/solver.zig:1480in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_eviction_skips_locked_and_protected_clauses[function] — test source atlib/smt/src/sat/solver.zig:1536in nearest public ownertiny.smt.sat.solver
Complete caller list for Solver.solve
24 direct callers.
lib.smt.src.profiling.sat.boundedConflictChurn[function] — private source atlib/smt/src/profiling/sat.zig:117in nearest public ownerlib.smt.src.profiling.satlib.smt.src.profiling.sat.pigeonholeUnsat[function] — private source atlib/smt/src/profiling/sat.zig:137in nearest public ownerlib.smt.src.profiling.satlib.smt.src.profiling.sat.randomConflictChurn[function] — private source atlib/smt/src/profiling/sat.zig:101in nearest public ownerlib.smt.src.profiling.satlib.smt.src.sat.solver.test_bounded_solve_preserves_status_and_proof_under_eviction[function] — test source atlib/smt/src/sat/solver.zig:1565in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_budgeted_solve_keeps_proof_steps_in_the_trace_slab[function] — test source atlib/smt/src/sat/solver.zig:1707in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_entry_eviction_enforces_a_newly_set_cap[function] — test source atlib/smt/src/sat/solver.zig:1785in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_learned_clause_records_multi-level_block_distance[function] — test source atlib/smt/src/sat/solver.zig:1893in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_learned_clause_records_single-level_block_distance[function] — test source atlib/smt/src/sat/solver.zig:1871in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_learned_store_pool_survives_variable_growth_and_cap_removal[function] — test source atlib/smt/src/sat/solver.zig:1651in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_proof_trace_survives_budget_growth_and_removal[function] — test source atlib/smt/src/sat/solver.zig:1742in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_removing_a_learned_clause_preserves_base_prefix_and_behavior[function] — test source atlib/smt/src/sat/solver.zig:1802in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.solver.test_removing_a_middle_learned_clause_patches_the_moved_clause[function] — test source atlib/smt/src/sat/solver.zig:1826in nearest public ownertiny.smt.sat.solverlib.smt.src.sat.test.test_conflict_budget_preserves_genuine_results_within_budget[function] — test source atlib/smt/src/sat/test.zig:498in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_conflict_budget_returns_unknown_instead_of_spinning[function] — test source atlib/smt/src/sat/test.zig:478in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_conflict_scratch_growth_rejects_before_solve_evidence_mutation_and_retries[function] — test source atlib/smt/src/sat/test.zig:161in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_accepts_simple_satisfiable_clauses[function] — test source atlib/smt/src/sat/test.zig:30in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_clears_proof_trace_after_satisfiable_solve[function] — test source atlib/smt/src/sat/test.zig:257in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_conflict_scratch_preserves_binary_implication_learning[function] — test source atlib/smt/src/sat/test.zig:114in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_detects_unsatisfiable_unit_conflict[function] — test source atlib/smt/src/sat/test.zig:74in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_exports_independent_proof_artifact[function] — test source atlib/smt/src/sat/test.zig:216in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_keeps_assumptions_through_learned_conflicts[function] — test source atlib/smt/src/sat/test.zig:426in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_reports_decision_stats[function] — test source atlib/smt/src/sat/test.zig:42in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_restarts_after_learned_conflicts[function] — test source atlib/smt/src/sat/test.zig:273in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_saves_phases_across_solves[function] — test source atlib/smt/src/sat/test.zig:55in nearest public ownerlib.smt.src.sat.test
Complete caller list for Solver.solveWithAssumptions
14 direct callers.
lib.smt.src.profiling.sat.incrementalAssumptions[function] — private source atlib/smt/src/profiling/sat.zig:151in nearest public ownerlib.smt.src.profiling.sattiny.smt.Solver.solve[method] atlib/smt/src/sat/solver.zig:328tiny.smt.Solver.solveWithActiveAssumptions[method] atlib/smt/src/sat/solver.zig:376lib.smt.src.sat.test.checkSolveAllocationFailureEvidence[function] — private source atlib/smt/src/sat/test.zig:356in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_base_inconsistency_keeps_artifact_scope_broader_than_its_empty_core[function] — test source atlib/smt/src/sat/test.zig:91in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_conflict_scratch_growth_rejects_before_solve_evidence_mutation_and_retries[function] — test source atlib/smt/src/sat/test.zig:161in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_proof_artifact_records_assumptions[function] — test source atlib/smt/src/sat/test.zig:241in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_clears_proof_trace_after_satisfiable_solve[function] — test source atlib/smt/src/sat/test.zig:257in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_keeps_assumptions_through_learned_conflicts[function] — test source atlib/smt/src/sat/test.zig:426in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_keeps_core_proof_scope_and_step_statistics_aligned[function] — test source atlib/smt/src/sat/test.zig:327in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_prunes_irrelevant_assumptions_from_unsat_core[function] — test source atlib/smt/src/sat/test.zig:311in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_reports_unknown_when_core_certification_exhausts_budget[function] — test source atlib/smt/src/sat/test.zig:405in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_saves_phases_across_solves[function] — test source atlib/smt/src/sat/test.zig:55in nearest public ownerlib.smt.src.sat.testlib.smt.src.sat.test.test_sat_solver_supports_assumptions[function] — test source atlib/smt/src/sat/test.zig:289in nearest public ownerlib.smt.src.sat.test
Audit
| Definitions | 27 |
|---|---|
| Public names | 81 |
| Members | 30 |
| Version | 26.7.0 |
| Revision | daab053ee433 |