Module S.Lit
module T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign
false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printer
diff --git a/dev/sidekick-arith/Sidekick_arith_lra/Make/argument-1-A/S/Lit/index.html b/dev/sidekick-arith/Sidekick_arith_lra/Make/argument-1-A/S/Lit/index.html index 1e7d6789..da90129d 100644 --- a/dev/sidekick-arith/Sidekick_arith_lra/Make/argument-1-A/S/Lit/index.html +++ b/dev/sidekick-arith/Sidekick_arith_lra/Make/argument-1-A/S/Lit/index.html @@ -1,2 +1,2 @@ -
S.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
S.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endS.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val pp_debug : t Sidekick_core.Fmt.printerval pp_dot : t Sidekick_core.Fmt.printer optionOptional printer into DOT/graphviz
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
1-A.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
1-A.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
Make.1-Amodule S : Sidekick_core.SOLVERtype term = S.T.Term.ttype ty = S.T.Ty.tval mk_bool : S.T.Term.state -> bool -> termval mk_lra : S.T.Term.state -> term lra_view -> termMake a term from the given theory view
val ty_lra : S.T.Term.state -> tyval mk_eq : S.T.Term.state -> term -> term -> termsyntactic equality
val has_ty_real : term -> boolDoes this term have the type Real
module Gensym : sig ... endMake.1-Amodule S : Sidekick_core.SOLVERtype term = S.T.Term.ttype ty = S.T.Ty.tval mk_bool : S.T.Term.state -> bool -> termval mk_lra : S.T.Term.state -> term lra_view -> termMake a term from the given theory view
val ty_lra : S.T.Term.state -> tyval mk_eq : S.T.Term.state -> term -> term -> termsyntactic equality
val has_ty_real : term -> boolDoes this term have the type Real
module Gensym : sig ... endS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
S.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endS.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val pp_debug : t Sidekick_core.Fmt.printerval pp_dot : t Sidekick_core.Fmt.printer optionOptional printer into DOT/graphviz
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
ARG.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
ARG.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
Sidekick_arith_lra.ARGmodule S : Sidekick_core.SOLVERtype term = S.T.Term.ttype ty = S.T.Ty.tval mk_bool : S.T.Term.state -> bool -> termval mk_lra : S.T.Term.state -> term lra_view -> termMake a term from the given theory view
val ty_lra : S.T.Term.state -> tyval mk_eq : S.T.Term.state -> term -> term -> termsyntactic equality
val has_ty_real : term -> boolDoes this term have the type Real
module Gensym : sig ... endSidekick_arith_lra.ARGmodule S : Sidekick_core.SOLVERtype term = S.T.Term.ttype ty = S.T.Ty.tval mk_bool : S.T.Term.state -> bool -> termval mk_lra : S.T.Term.state -> term lra_view -> termMake a term from the given theory view
val ty_lra : S.T.Term.state -> tyval mk_eq : S.T.Term.state -> term -> term -> termsyntactic equality
val has_ty_real : term -> boolDoes this term have the type Real
module Gensym : sig ... endS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
S.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endS.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val pp_debug : t Sidekick_core.Fmt.printerval pp_dot : t Sidekick_core.Fmt.printer optionOptional printer into DOT/graphviz
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
A.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
A.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
S.Amodule S : Sidekick_core.SOLVERtype term = S.T.Term.ttype ty = S.T.Ty.tval mk_bool : S.T.Term.state -> bool -> termval mk_lra : S.T.Term.state -> term lra_view -> termMake a term from the given theory view
val ty_lra : S.T.Term.state -> tyval mk_eq : S.T.Term.state -> term -> term -> termsyntactic equality
val has_ty_real : term -> boolDoes this term have the type Real
module Gensym : sig ... endS.Amodule S : Sidekick_core.SOLVERtype term = S.T.Term.ttype ty = S.T.Ty.tval mk_bool : S.T.Term.state -> bool -> termval mk_lra : S.T.Term.state -> term lra_view -> termMake a term from the given theory view
val ty_lra : S.T.Term.state -> tyval mk_eq : S.T.Term.state -> term -> term -> termsyntactic equality
val has_ty_real : term -> boolDoes this term have the type Real
module Gensym : sig ... endBase_types.CstorBase_types.CstorTerm.Iter_dagBase_types.Termtype t = term = {mutable term_id : int; |
mutable term_ty : ty; |
term_view : t term_view; |
}type 'a view = 'a term_view = | Bool of bool |
| App_fun of fun_ * 'a Sidekick_util.IArray.t |
| Eq of 'a * 'a |
| Not of 'a |
| Ite of 'a * 'a * 'a |
| LRA of 'a lra_view |
val id : t -> intval view : t -> term viewval ty : t -> Ty.tval equal : t -> t -> boolval compare : t -> t -> intval hash : t -> intval create : ?size:int -> unit -> stateval make : state -> t view -> tval true_ : state -> tval false_ : state -> tval bool : state -> bool -> tval const : state -> fun_ -> tval app_fun : state -> fun_ -> t Sidekick_util.IArray.t -> tval eq : state -> t -> t -> tval not_ : state -> t -> tval ite : state -> t -> t -> t -> tval select : state -> select -> t -> tval app_cstor : state -> cstor -> t Sidekick_util.IArray.t -> tval is_a : state -> cstor -> t -> tval lra : state -> t lra_view -> tval abs : state -> t -> t * boolObtain unsigned version of t, + the sign as a boolean
module Iter_dag : sig ... endBase_types.Termtype t = term = {mutable term_id : int; |
mutable term_ty : ty; |
term_view : t term_view; |
}type 'a view = 'a term_view = | Bool of bool |
| App_fun of fun_ * 'a Sidekick_util.IArray.t |
| Eq of 'a * 'a |
| Not of 'a |
| Ite of 'a * 'a * 'a |
| LRA of 'a lra_view |
val id : t -> intval view : t -> term viewval ty : t -> Ty.tval equal : t -> t -> boolval compare : t -> t -> intval hash : t -> intval create : ?size:int -> unit -> stateval make : state -> t view -> tval true_ : state -> tval false_ : state -> tval bool : state -> bool -> tval const : state -> fun_ -> tval app_fun : state -> fun_ -> t Sidekick_util.IArray.t -> tval eq : state -> t -> t -> tval not_ : state -> t -> tval ite : state -> t -> t -> t -> tval select : state -> select -> t -> tval app_cstor : state -> cstor -> t Sidekick_util.IArray.t -> tval is_a : state -> cstor -> t -> tval lra : state -> t lra_view -> tval abs : state -> t -> t * boolObtain unsigned version of t, + the sign as a boolean
module Iter_dag : sig ... endval iter_dag_with : order:Iter_dag.order -> t -> t Iter.tval iter_dag : t -> t Iter.tval map_shallow : state -> (t -> t) -> t -> tval pp : t Fmt.printerBase_types.Tytype t = tytype state = unittype view = ty_view = | Ty_bool | |||
| Ty_real | |||
| Ty_atomic of {
} |
type def = ty_def = | Ty_uninterpreted of ID.t | |||
| Ty_data of {
} | |||
| Ty_def of {
} |
val id : t -> intval view : t -> viewval bool : state -> tval real : state -> tval atomic : def -> t list -> tval atomic_uninterpreted : ID.t -> tval finite : t -> boolval set_finite : t -> bool -> unitval is_bool : t -> boolval is_uninterpreted : t -> boolval equal : t -> t -> boolval compare : t -> t -> intval hash : t -> intval pp : t CCFormat.printermodule Fun : sig ... endBase_types.Tytype t = tytype state = unittype view = ty_view = | Ty_bool | |||
| Ty_real | |||
| Ty_atomic of {
} |
type def = ty_def = | Ty_uninterpreted of ID.t | |||
| Ty_data of {
} | |||
| Ty_def of {
} |
val id : t -> intval view : t -> viewval bool : state -> tval real : state -> tval atomic : def -> t list -> tval id_of_def : def -> ID.tval atomic_uninterpreted : ID.t -> tval finite : t -> boolval set_finite : t -> bool -> unitval is_bool : t -> boolval is_uninterpreted : t -> boolval equal : t -> t -> boolval compare : t -> t -> intval hash : t -> intval pp : t CCFormat.printermodule Fun : sig ... endSidekick_base_term.Base_typesmodule CC_view = Sidekick_core.CC_viewtype lra_pred = Sidekick_arith_lra.Predicate.t = | Leq |
| Geq |
| Lt |
| Gt |
| Eq |
| Neq |
type lra_op = Sidekick_arith_lra.op = | Plus |
| Minus |
type 'a lra_view = 'a Sidekick_arith_lra.lra_view = | LRA_pred of lra_pred * 'a * 'a |
| LRA_op of lra_op * 'a * 'a |
| LRA_mult of Q.t * 'a |
| LRA_const of Q.t |
| LRA_simplex_var of 'a |
| LRA_simplex_pred of 'a * Sidekick_arith_lra.S_op.t * Q.t |
| LRA_other of 'a |
type term = {mutable term_id : int; |
mutable term_ty : ty; |
term_view : term term_view; |
}and 'a term_view = | Bool of bool |
| App_fun of fun_ * 'a Sidekick_util.IArray.t |
| Eq of 'a * 'a |
| Not of 'a |
| Ite of 'a * 'a * 'a |
| LRA of 'a lra_view |
and fun_ = {fun_id : ID.t; |
fun_view : fun_view; |
}and fun_view = | Fun_undef of fun_ty | |||||||
| Fun_select of select | |||||||
| Fun_cstor of cstor | |||||||
| Fun_is_a of cstor | |||||||
| Fun_def of {
} | Methods on the custom term view whose arguments are
|
and fun_ty = {fun_ty_args : ty list; |
fun_ty_ret : ty; |
}Function type
and ty = {mutable ty_id : int; |
ty_view : ty_view; |
}Hashconsed type
and ty_view = | Ty_bool | |||
| Ty_real | |||
| Ty_atomic of {
} |
and ty_def = | Ty_uninterpreted of ID.t | |||
| Ty_data of {
} | |||
| Ty_def of {
} |
and data = {data_id : ID.t; |
data_cstors : cstor Sidekick_base_term__.ID.Map.t lazy_t; |
data_as_ty : ty lazy_t; |
}and cstor = {cstor_id : ID.t; |
cstor_is_a : ID.t; |
mutable cstor_arity : int; |
cstor_args : select list lazy_t; |
cstor_ty_as_data : data; |
cstor_ty : ty lazy_t; |
}and select = {select_id : ID.t; |
select_cstor : cstor; |
select_ty : ty lazy_t; |
select_i : int; |
}and value = | V_bool of bool | |||||
| V_element of {
} | a named constant, distinct from any other constant | ||||
| V_cstor of {
} | |||||
| V_custom of {
} | Custom value | ||||
| V_real of Q.t |
Semantic values, used for models (and possibly model-constructing calculi)
and value_custom_view = ..type definition = ID.t * ty * termtype statement = | Stmt_set_logic of string |
| Stmt_set_option of string list |
| Stmt_set_info of string * string |
| Stmt_data of data list |
| Stmt_ty_decl of ID.t * int |
| Stmt_decl of ID.t * ty list * ty |
| Stmt_define of definition list |
| Stmt_assert of term |
| Stmt_assert_clause of term list |
| Stmt_check_sat of (bool * term) list |
| Stmt_exit |
val term_equal_ : term -> term -> boolval term_hash_ : term -> intval term_cmp_ : term -> term -> intval fun_compare : fun_ -> fun_ -> intval pp_fun : CCFormat.t -> fun_ -> unitval id_of_fun : fun_ -> ID.tval eq_ty : ty -> ty -> boolval eq_cstor : cstor -> cstor -> boolval eq_value : value -> value -> boolval hash_value : value Sidekick_util.Hash.tval pp_value : value Sidekick_util.Util.printerval pp_db : Stdlib.Format.formatter -> (int * 'a) -> unitval pp_ty : ty Sidekick_util.Util.printerval string_of_lra_pred : lra_pred -> stringval pp_pred : Fmt.t -> lra_pred -> unitval string_of_lra_op : lra_op -> stringval pp_lra_op : Fmt.t -> lra_op -> unitval pp_term_view_gen : pp_id:(Fmt.t -> ID.t -> unit) -> pp_t:'a Fmt.printer -> Fmt.t -> 'a term_view -> unitval pp_term_top : ids:bool -> Fmt.t -> term -> unitval pp_term : Fmt.t -> term -> unitval pp_term_view : Fmt.t -> term term_view -> unitmodule Ty : sig ... endmodule Fun : sig ... endmodule Term_cell : sig ... endmodule Term : sig ... endmodule Value : sig ... endmodule Data : sig ... endmodule Select : sig ... endmodule Cstor : sig ... endmodule Proof : sig ... endmodule Statement : sig ... endSidekick_base_term.Base_typesmodule CC_view = Sidekick_core.CC_viewtype lra_pred = Sidekick_arith_lra.Predicate.t = | Leq |
| Geq |
| Lt |
| Gt |
| Eq |
| Neq |
type lra_op = Sidekick_arith_lra.op = | Plus |
| Minus |
type 'a lra_view = 'a Sidekick_arith_lra.lra_view = | LRA_pred of lra_pred * 'a * 'a |
| LRA_op of lra_op * 'a * 'a |
| LRA_mult of Q.t * 'a |
| LRA_const of Q.t |
| LRA_simplex_var of 'a |
| LRA_simplex_pred of 'a * Sidekick_arith_lra.S_op.t * Q.t |
| LRA_other of 'a |
type term = {mutable term_id : int; |
mutable term_ty : ty; |
term_view : term term_view; |
}and 'a term_view = | Bool of bool |
| App_fun of fun_ * 'a Sidekick_util.IArray.t |
| Eq of 'a * 'a |
| Not of 'a |
| Ite of 'a * 'a * 'a |
| LRA of 'a lra_view |
and fun_ = {fun_id : ID.t; |
fun_view : fun_view; |
}and fun_view = | Fun_undef of fun_ty | |||||||
| Fun_select of select | |||||||
| Fun_cstor of cstor | |||||||
| Fun_is_a of cstor | |||||||
| Fun_def of {
} | Methods on the custom term view whose arguments are
|
and fun_ty = {fun_ty_args : ty list; |
fun_ty_ret : ty; |
}Function type
and ty = {mutable ty_id : int; |
ty_view : ty_view; |
}Hashconsed type
and ty_view = | Ty_bool | |||
| Ty_real | |||
| Ty_atomic of {
} |
and ty_def = | Ty_uninterpreted of ID.t | |||
| Ty_data of {
} | |||
| Ty_def of {
} |
and data = {data_id : ID.t; |
data_cstors : cstor Sidekick_base_term__.ID.Map.t lazy_t; |
data_as_ty : ty lazy_t; |
}and cstor = {cstor_id : ID.t; |
cstor_is_a : ID.t; |
mutable cstor_arity : int; |
cstor_args : select list lazy_t; |
cstor_ty_as_data : data; |
cstor_ty : ty lazy_t; |
}and select = {select_id : ID.t; |
select_cstor : cstor; |
select_ty : ty lazy_t; |
select_i : int; |
}and value = | V_bool of bool | |||||
| V_element of {
} | a named constant, distinct from any other constant | ||||
| V_cstor of {
} | |||||
| V_custom of {
} | Custom value | ||||
| V_real of Q.t |
Semantic values, used for models (and possibly model-constructing calculi)
and value_custom_view = ..type definition = ID.t * ty * termtype statement = | Stmt_set_logic of string |
| Stmt_set_option of string list |
| Stmt_set_info of string * string |
| Stmt_data of data list |
| Stmt_ty_decl of ID.t * int |
| Stmt_decl of ID.t * ty list * ty |
| Stmt_define of definition list |
| Stmt_assert of term |
| Stmt_assert_clause of term list |
| Stmt_check_sat of (bool * term) list |
| Stmt_exit |
val term_equal_ : term -> term -> boolval term_hash_ : term -> intval term_cmp_ : term -> term -> intval fun_compare : fun_ -> fun_ -> intval pp_fun : CCFormat.t -> fun_ -> unitval id_of_fun : fun_ -> ID.tval eq_ty : ty -> ty -> boolval eq_cstor : cstor -> cstor -> boolval eq_value : value -> value -> boolval hash_value : value Sidekick_util.Hash.tval pp_value : value Sidekick_util.Util.printerval pp_db : Stdlib.Format.formatter -> (int * 'a) -> unitval pp_ty : ty Sidekick_util.Util.printerval string_of_lra_pred : lra_pred -> stringval pp_pred : Fmt.t -> lra_pred -> unitval string_of_lra_op : lra_op -> stringval pp_lra_op : Fmt.t -> lra_op -> unitval pp_term_view_gen : pp_id:(Fmt.t -> ID.t -> unit) -> pp_t:'a Fmt.printer -> Fmt.t -> 'a term_view -> unitval pp_term_top : ids:bool -> Fmt.t -> term -> unitval pp_term : Fmt.t -> term -> unitval pp_term_view : Fmt.t -> term term_view -> unitmodule Ty : sig ... endmodule Fun : sig ... endmodule Term_cell : sig ... endmodule Term : sig ... endmodule Value : sig ... endmodule Data : sig ... endmodule Select : sig ... endmodule Cstor : sig ... endmodule Statement : sig ... endProof.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
Sidekick_base_term.Proofinclude Sidekick_core.PROOF with type term = Base_types.Term.t and type ty = Base_types.Ty.ttype term = Base_types.Term.ttype ty = Base_types.Ty.ttype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endval isa_split : ty -> term Iter.t -> tval isa_disj : ty -> term -> term -> tval cstor_inj : Base_types.Cstor.t -> int -> term list -> term list -> tval bool_eq : term -> term -> tval bool_c : string -> term list -> tval ite_true : term -> tval ite_false : term -> tval lra : lit Iter.t -> tval lra_l : lit list -> tSidekick_base_termmodule Base_types : sig ... endmodule ID : sig ... endmodule Fun = Base_types.Funmodule Stat = Sidekick_util.Statmodule Model : sig ... endmodule Term = Base_types.Termmodule Value = Base_types.Valuemodule Term_cell = Base_types.Term_cellmodule Ty = Base_types.Tymodule Statement = Base_types.Statementmodule Data = Base_types.Datamodule Select = Base_types.Selectmodule Arg : Sidekick_core.TERM with type Term.t = Term.t and type Fun.t = Fun.t and type Ty.t = Ty.t and type Term.state = Term.stateSidekick_base_termmodule Base_types : sig ... endmodule ID : sig ... endmodule Fun = Base_types.Funmodule Stat = Sidekick_util.Statmodule Model : sig ... endmodule Term = Base_types.Termmodule Value = Base_types.Valuemodule Term_cell = Base_types.Term_cellmodule Ty = Base_types.Tymodule Statement = Base_types.Statementmodule Data = Base_types.Datamodule Select = Base_types.Selectmodule Proof : sig ... endmodule Arg : Sidekick_core.TERM with type Term.t = Term.t and type Fun.t = Fun.t and type Ty.t = Ty.t and type Term.state = Term.stateBase_types.Cstortype t = cstor = {cstor_id : Sidekick_base_term.ID.t; |
cstor_is_a : Sidekick_base_term.ID.t; |
mutable cstor_arity : int; |
cstor_args : select list lazy_t; |
cstor_ty_as_data : data; |
cstor_ty : ty lazy_t; |
}Base_types.Cstortype t = cstor = {cstor_id : Sidekick_base_term.ID.t; |
cstor_is_a : Sidekick_base_term.ID.t; |
mutable cstor_arity : int; |
cstor_args : select list lazy_t; |
cstor_ty_as_data : data; |
cstor_ty : ty lazy_t; |
}Term.Iter_dagBase_types.Termtype t = term = {mutable term_id : int; |
mutable term_ty : ty; |
term_view : t term_view; |
}type 'a view = 'a term_view = | Bool of bool |
| App_fun of fun_ * 'a Sidekick_util.IArray.t |
| Eq of 'a * 'a |
| Not of 'a |
| Ite of 'a * 'a * 'a |
| LRA of 'a lra_view |
val id : t -> intval view : t -> term viewval ty : t -> Ty.tval equal : t -> t -> boolval compare : t -> t -> intval hash : t -> intval create : ?size:int -> unit -> stateval make : state -> t view -> tval true_ : state -> tval false_ : state -> tval bool : state -> bool -> tval const : state -> fun_ -> tval app_fun : state -> fun_ -> t Sidekick_util.IArray.t -> tval eq : state -> t -> t -> tval not_ : state -> t -> tval ite : state -> t -> t -> t -> tval select : state -> select -> t -> tval app_cstor : state -> cstor -> t Sidekick_util.IArray.t -> tval is_a : state -> cstor -> t -> tval lra : state -> t lra_view -> tval abs : state -> t -> t * boolObtain unsigned version of t, + the sign as a boolean
module Iter_dag : sig ... endBase_types.Termtype t = term = {mutable term_id : int; |
mutable term_ty : ty; |
term_view : t term_view; |
}type 'a view = 'a term_view = | Bool of bool |
| App_fun of fun_ * 'a Sidekick_util.IArray.t |
| Eq of 'a * 'a |
| Not of 'a |
| Ite of 'a * 'a * 'a |
| LRA of 'a lra_view |
val id : t -> intval view : t -> term viewval ty : t -> Ty.tval equal : t -> t -> boolval compare : t -> t -> intval hash : t -> intval create : ?size:int -> unit -> stateval make : state -> t view -> tval true_ : state -> tval false_ : state -> tval bool : state -> bool -> tval const : state -> fun_ -> tval app_fun : state -> fun_ -> t Sidekick_util.IArray.t -> tval eq : state -> t -> t -> tval not_ : state -> t -> tval ite : state -> t -> t -> t -> tval select : state -> select -> t -> tval app_cstor : state -> cstor -> t Sidekick_util.IArray.t -> tval is_a : state -> cstor -> t -> tval lra : state -> t lra_view -> tval abs : state -> t -> t * boolObtain unsigned version of t, + the sign as a boolean
module Iter_dag : sig ... endval iter_dag_with : order:Iter_dag.order -> t -> t Iter.tval iter_dag : t -> t Iter.tval map_shallow : state -> (t -> t) -> t -> tval pp : t Fmt.printerBase_types.Tytype t = tytype state = unittype view = ty_view = | Ty_bool | |||
| Ty_real | |||
| Ty_atomic of {
} |
type def = ty_def = | Ty_uninterpreted of Sidekick_base_term.ID.t | |||
| Ty_data of {
} | |||
| Ty_def of {
} |
val id : t -> intval view : t -> viewval bool : state -> tval real : state -> tval atomic : def -> t list -> tval atomic_uninterpreted : Sidekick_base_term.ID.t -> tval finite : t -> boolval set_finite : t -> bool -> unitval is_bool : t -> boolval is_uninterpreted : t -> boolval equal : t -> t -> boolval compare : t -> t -> intval hash : t -> intval pp : t CCFormat.printermodule Fun : sig ... endBase_types.Tytype t = tytype state = unittype view = ty_view = | Ty_bool | |||
| Ty_real | |||
| Ty_atomic of {
} |
type def = ty_def = | Ty_uninterpreted of Sidekick_base_term.ID.t | |||
| Ty_data of {
} | |||
| Ty_def of {
} |
val id : t -> intval view : t -> viewval bool : state -> tval real : state -> tval atomic : def -> t list -> tval id_of_def : def -> Sidekick_base_term.ID.tval atomic_uninterpreted : Sidekick_base_term.ID.t -> tval finite : t -> boolval set_finite : t -> bool -> unitval is_bool : t -> boolval is_uninterpreted : t -> boolval equal : t -> t -> boolval compare : t -> t -> intval hash : t -> intval pp : t CCFormat.printermodule Fun : sig ... endSidekick_base_term__.Base_typesmodule CC_view = Sidekick_core.CC_viewtype lra_pred = Sidekick_arith_lra.Predicate.t = | Leq |
| Geq |
| Lt |
| Gt |
| Eq |
| Neq |
type lra_op = Sidekick_arith_lra.op = | Plus |
| Minus |
type 'a lra_view = 'a Sidekick_arith_lra.lra_view = | LRA_pred of lra_pred * 'a * 'a |
| LRA_op of lra_op * 'a * 'a |
| LRA_mult of Q.t * 'a |
| LRA_const of Q.t |
| LRA_simplex_var of 'a |
| LRA_simplex_pred of 'a * Sidekick_arith_lra.S_op.t * Q.t |
| LRA_other of 'a |
type term = {mutable term_id : int; |
mutable term_ty : ty; |
term_view : term term_view; |
}and 'a term_view = | Bool of bool |
| App_fun of fun_ * 'a Sidekick_util.IArray.t |
| Eq of 'a * 'a |
| Not of 'a |
| Ite of 'a * 'a * 'a |
| LRA of 'a lra_view |
and fun_ = {fun_id : Sidekick_base_term.ID.t; |
fun_view : fun_view; |
}and fun_view = | Fun_undef of fun_ty | |||||||
| Fun_select of select | |||||||
| Fun_cstor of cstor | |||||||
| Fun_is_a of cstor | |||||||
| Fun_def of {
} | Methods on the custom term view whose arguments are
|
and fun_ty = {fun_ty_args : ty list; |
fun_ty_ret : ty; |
}Function type
and ty = {mutable ty_id : int; |
ty_view : ty_view; |
}Hashconsed type
and ty_view = | Ty_bool | |||
| Ty_real | |||
| Ty_atomic of {
} |
and ty_def = | Ty_uninterpreted of Sidekick_base_term.ID.t | |||
| Ty_data of {
} | |||
| Ty_def of {
} |
and data = {data_id : Sidekick_base_term.ID.t; |
data_cstors : cstor Sidekick_base_term__.ID.Map.t lazy_t; |
data_as_ty : ty lazy_t; |
}and cstor = {cstor_id : Sidekick_base_term.ID.t; |
cstor_is_a : Sidekick_base_term.ID.t; |
mutable cstor_arity : int; |
cstor_args : select list lazy_t; |
cstor_ty_as_data : data; |
cstor_ty : ty lazy_t; |
}and select = {select_id : Sidekick_base_term.ID.t; |
select_cstor : cstor; |
select_ty : ty lazy_t; |
select_i : int; |
}and value = | V_bool of bool | |||||
| V_element of {
} | a named constant, distinct from any other constant | ||||
| V_cstor of {
} | |||||
| V_custom of {
} | Custom value | ||||
| V_real of Q.t |
Semantic values, used for models (and possibly model-constructing calculi)
and value_custom_view = ..type definition = Sidekick_base_term.ID.t * ty * termtype statement = | Stmt_set_logic of string |
| Stmt_set_option of string list |
| Stmt_set_info of string * string |
| Stmt_data of data list |
| Stmt_ty_decl of Sidekick_base_term.ID.t * int |
| Stmt_decl of Sidekick_base_term.ID.t * ty list * ty |
| Stmt_define of definition list |
| Stmt_assert of term |
| Stmt_assert_clause of term list |
| Stmt_check_sat of (bool * term) list |
| Stmt_exit |
val term_equal_ : term -> term -> boolval term_hash_ : term -> intval term_cmp_ : term -> term -> intval fun_compare : fun_ -> fun_ -> intval pp_fun : CCFormat.t -> fun_ -> unitval id_of_fun : fun_ -> Sidekick_base_term.ID.tval eq_ty : ty -> ty -> boolval eq_cstor : cstor -> cstor -> boolval eq_value : value -> value -> boolval hash_value : value Sidekick_util.Hash.tval pp_value : value Sidekick_util.Util.printerval pp_db : Stdlib.Format.formatter -> (int * 'a) -> unitval pp_ty : ty Sidekick_util.Util.printerval string_of_lra_pred : lra_pred -> stringval pp_pred : Fmt.t -> lra_pred -> unitval string_of_lra_op : lra_op -> stringval pp_lra_op : Fmt.t -> lra_op -> unitval pp_term_view_gen : pp_id:(Fmt.t -> Sidekick_base_term.ID.t -> unit) -> pp_t:'a Fmt.printer -> Fmt.t -> 'a term_view -> unitval pp_term_top : ids:bool -> Fmt.t -> term -> unitval pp_term : Fmt.t -> term -> unitval pp_term_view : Fmt.t -> term term_view -> unitmodule Ty : sig ... endmodule Fun : sig ... endmodule Term_cell : sig ... endmodule Term : sig ... endmodule Value : sig ... endmodule Data : sig ... endmodule Select : sig ... endmodule Cstor : sig ... endmodule Proof : sig ... endmodule Statement : sig ... endSidekick_base_term__.Base_typesmodule CC_view = Sidekick_core.CC_viewtype lra_pred = Sidekick_arith_lra.Predicate.t = | Leq |
| Geq |
| Lt |
| Gt |
| Eq |
| Neq |
type lra_op = Sidekick_arith_lra.op = | Plus |
| Minus |
type 'a lra_view = 'a Sidekick_arith_lra.lra_view = | LRA_pred of lra_pred * 'a * 'a |
| LRA_op of lra_op * 'a * 'a |
| LRA_mult of Q.t * 'a |
| LRA_const of Q.t |
| LRA_simplex_var of 'a |
| LRA_simplex_pred of 'a * Sidekick_arith_lra.S_op.t * Q.t |
| LRA_other of 'a |
type term = {mutable term_id : int; |
mutable term_ty : ty; |
term_view : term term_view; |
}and 'a term_view = | Bool of bool |
| App_fun of fun_ * 'a Sidekick_util.IArray.t |
| Eq of 'a * 'a |
| Not of 'a |
| Ite of 'a * 'a * 'a |
| LRA of 'a lra_view |
and fun_ = {fun_id : Sidekick_base_term.ID.t; |
fun_view : fun_view; |
}and fun_view = | Fun_undef of fun_ty | |||||||
| Fun_select of select | |||||||
| Fun_cstor of cstor | |||||||
| Fun_is_a of cstor | |||||||
| Fun_def of {
} | Methods on the custom term view whose arguments are
|
and fun_ty = {fun_ty_args : ty list; |
fun_ty_ret : ty; |
}Function type
and ty = {mutable ty_id : int; |
ty_view : ty_view; |
}Hashconsed type
and ty_view = | Ty_bool | |||
| Ty_real | |||
| Ty_atomic of {
} |
and ty_def = | Ty_uninterpreted of Sidekick_base_term.ID.t | |||
| Ty_data of {
} | |||
| Ty_def of {
} |
and data = {data_id : Sidekick_base_term.ID.t; |
data_cstors : cstor Sidekick_base_term__.ID.Map.t lazy_t; |
data_as_ty : ty lazy_t; |
}and cstor = {cstor_id : Sidekick_base_term.ID.t; |
cstor_is_a : Sidekick_base_term.ID.t; |
mutable cstor_arity : int; |
cstor_args : select list lazy_t; |
cstor_ty_as_data : data; |
cstor_ty : ty lazy_t; |
}and select = {select_id : Sidekick_base_term.ID.t; |
select_cstor : cstor; |
select_ty : ty lazy_t; |
select_i : int; |
}and value = | V_bool of bool | |||||
| V_element of {
} | a named constant, distinct from any other constant | ||||
| V_cstor of {
} | |||||
| V_custom of {
} | Custom value | ||||
| V_real of Q.t |
Semantic values, used for models (and possibly model-constructing calculi)
and value_custom_view = ..type definition = Sidekick_base_term.ID.t * ty * termtype statement = | Stmt_set_logic of string |
| Stmt_set_option of string list |
| Stmt_set_info of string * string |
| Stmt_data of data list |
| Stmt_ty_decl of Sidekick_base_term.ID.t * int |
| Stmt_decl of Sidekick_base_term.ID.t * ty list * ty |
| Stmt_define of definition list |
| Stmt_assert of term |
| Stmt_assert_clause of term list |
| Stmt_check_sat of (bool * term) list |
| Stmt_exit |
val term_equal_ : term -> term -> boolval term_hash_ : term -> intval term_cmp_ : term -> term -> intval fun_compare : fun_ -> fun_ -> intval pp_fun : CCFormat.t -> fun_ -> unitval id_of_fun : fun_ -> Sidekick_base_term.ID.tval eq_ty : ty -> ty -> boolval eq_cstor : cstor -> cstor -> boolval eq_value : value -> value -> boolval hash_value : value Sidekick_util.Hash.tval pp_value : value Sidekick_util.Util.printerval pp_db : Stdlib.Format.formatter -> (int * 'a) -> unitval pp_ty : ty Sidekick_util.Util.printerval string_of_lra_pred : lra_pred -> stringval pp_pred : Fmt.t -> lra_pred -> unitval string_of_lra_op : lra_op -> stringval pp_lra_op : Fmt.t -> lra_op -> unitval pp_term_view_gen : pp_id:(Fmt.t -> Sidekick_base_term.ID.t -> unit) -> pp_t:'a Fmt.printer -> Fmt.t -> 'a term_view -> unitval pp_term_top : ids:bool -> Fmt.t -> term -> unitval pp_term : Fmt.t -> term -> unitval pp_term_view : Fmt.t -> term term_view -> unitmodule Ty : sig ... endmodule Fun : sig ... endmodule Term_cell : sig ... endmodule Term : sig ... endmodule Value : sig ... endmodule Data : sig ... endmodule Select : sig ... endmodule Cstor : sig ... endmodule Statement : sig ... endProof.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
Sidekick_base_term__.Proofinclude Sidekick_core.PROOF with type term = Sidekick_base_term.Base_types.Term.t and type ty = Sidekick_base_term.Base_types.Ty.ttype term = Sidekick_base_term.Base_types.Term.ttype ty = Sidekick_base_term.Base_types.Ty.ttype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endval isa_split : ty -> term Iter.t -> tval isa_disj : ty -> term -> term -> tval cstor_inj : Sidekick_base_term.Base_types.Cstor.t -> int -> term list -> term list -> tval bool_eq : term -> term -> tval bool_c : string -> term list -> tval ite_true : term -> tval ite_false : term -> tval lra : lit Iter.t -> tval lra_l : lit list -> tSidekick_base_term__module Base_types : sig ... endmodule CCHet : sig ... endmodule Config : sig ... endmodule Hashcons : sig ... endmodule ID : sig ... endmodule Model : sig ... endSidekick_base_term__module Base_types : sig ... endmodule CCHet : sig ... endmodule Config : sig ... endmodule Hashcons : sig ... endmodule ID : sig ... endmodule Model : sig ... endmodule Proof : sig ... endSidekick_base_term__Base_types.Cstortype t = cstor = {cstor_id : Sidekick_base_term.ID.t; |
cstor_is_a : Sidekick_base_term.ID.t; |
mutable cstor_arity : int; |
cstor_args : select list lazy_t; |
cstor_ty_as_data : data; |
cstor_ty : ty lazy_t; |
}Sidekick_base_term__Base_types.Cstortype t = cstor = {cstor_id : Sidekick_base_term.ID.t; |
cstor_is_a : Sidekick_base_term.ID.t; |
mutable cstor_arity : int; |
cstor_args : select list lazy_t; |
cstor_ty_as_data : data; |
cstor_ty : ty lazy_t; |
}Term.Iter_dagSidekick_base_term__Base_types.Termtype t = term = {mutable term_id : int; |
mutable term_ty : ty; |
term_view : t term_view; |
}type 'a view = 'a term_view = | Bool of bool |
| App_fun of fun_ * 'a Sidekick_util.IArray.t |
| Eq of 'a * 'a |
| Not of 'a |
| Ite of 'a * 'a * 'a |
| LRA of 'a lra_view |
val id : t -> intval view : t -> term viewval ty : t -> Ty.tval equal : t -> t -> boolval compare : t -> t -> intval hash : t -> intval create : ?size:int -> unit -> stateval make : state -> t view -> tval true_ : state -> tval false_ : state -> tval bool : state -> bool -> tval const : state -> fun_ -> tval app_fun : state -> fun_ -> t Sidekick_util.IArray.t -> tval eq : state -> t -> t -> tval not_ : state -> t -> tval ite : state -> t -> t -> t -> tval select : state -> select -> t -> tval app_cstor : state -> cstor -> t Sidekick_util.IArray.t -> tval is_a : state -> cstor -> t -> tval lra : state -> t lra_view -> tval abs : state -> t -> t * boolObtain unsigned version of t, + the sign as a boolean
module Iter_dag : sig ... endSidekick_base_term__Base_types.Termtype t = term = {mutable term_id : int; |
mutable term_ty : ty; |
term_view : t term_view; |
}type 'a view = 'a term_view = | Bool of bool |
| App_fun of fun_ * 'a Sidekick_util.IArray.t |
| Eq of 'a * 'a |
| Not of 'a |
| Ite of 'a * 'a * 'a |
| LRA of 'a lra_view |
val id : t -> intval view : t -> term viewval ty : t -> Ty.tval equal : t -> t -> boolval compare : t -> t -> intval hash : t -> intval create : ?size:int -> unit -> stateval make : state -> t view -> tval true_ : state -> tval false_ : state -> tval bool : state -> bool -> tval const : state -> fun_ -> tval app_fun : state -> fun_ -> t Sidekick_util.IArray.t -> tval eq : state -> t -> t -> tval not_ : state -> t -> tval ite : state -> t -> t -> t -> tval select : state -> select -> t -> tval app_cstor : state -> cstor -> t Sidekick_util.IArray.t -> tval is_a : state -> cstor -> t -> tval lra : state -> t lra_view -> tval abs : state -> t -> t * boolObtain unsigned version of t, + the sign as a boolean
module Iter_dag : sig ... endval iter_dag_with : order:Iter_dag.order -> t -> t Iter.tval iter_dag : t -> t Iter.tval map_shallow : state -> (t -> t) -> t -> tval pp : t Fmt.printerSidekick_base_term__Base_types.Tytype t = tytype state = unittype view = ty_view = | Ty_bool | |||
| Ty_real | |||
| Ty_atomic of {
} |
type def = ty_def = | Ty_uninterpreted of Sidekick_base_term.ID.t | |||
| Ty_data of {
} | |||
| Ty_def of {
} |
val id : t -> intval view : t -> viewval bool : state -> tval real : state -> tval atomic : def -> t list -> tval atomic_uninterpreted : Sidekick_base_term.ID.t -> tval finite : t -> boolval set_finite : t -> bool -> unitval is_bool : t -> boolval is_uninterpreted : t -> boolval equal : t -> t -> boolval compare : t -> t -> intval hash : t -> intval pp : t CCFormat.printermodule Fun : sig ... endSidekick_base_term__Base_types.Tytype t = tytype state = unittype view = ty_view = | Ty_bool | |||
| Ty_real | |||
| Ty_atomic of {
} |
type def = ty_def = | Ty_uninterpreted of Sidekick_base_term.ID.t | |||
| Ty_data of {
} | |||
| Ty_def of {
} |
val id : t -> intval view : t -> viewval bool : state -> tval real : state -> tval atomic : def -> t list -> tval id_of_def : def -> Sidekick_base_term.ID.tval atomic_uninterpreted : Sidekick_base_term.ID.t -> tval finite : t -> boolval set_finite : t -> bool -> unitval is_bool : t -> boolval is_uninterpreted : t -> boolval equal : t -> t -> boolval compare : t -> t -> intval hash : t -> intval pp : t CCFormat.printermodule Fun : sig ... endSidekick_base_term__Base_typesmodule CC_view = Sidekick_core.CC_viewtype lra_pred = Sidekick_arith_lra.Predicate.t = | Leq |
| Geq |
| Lt |
| Gt |
| Eq |
| Neq |
type lra_op = Sidekick_arith_lra.op = | Plus |
| Minus |
type 'a lra_view = 'a Sidekick_arith_lra.lra_view = | LRA_pred of lra_pred * 'a * 'a |
| LRA_op of lra_op * 'a * 'a |
| LRA_mult of Q.t * 'a |
| LRA_const of Q.t |
| LRA_simplex_var of 'a |
| LRA_simplex_pred of 'a * Sidekick_arith_lra.S_op.t * Q.t |
| LRA_other of 'a |
type term = {mutable term_id : int; |
mutable term_ty : ty; |
term_view : term term_view; |
}and 'a term_view = | Bool of bool |
| App_fun of fun_ * 'a Sidekick_util.IArray.t |
| Eq of 'a * 'a |
| Not of 'a |
| Ite of 'a * 'a * 'a |
| LRA of 'a lra_view |
and fun_ = {fun_id : Sidekick_base_term.ID.t; |
fun_view : fun_view; |
}and fun_view = | Fun_undef of fun_ty | |||||||
| Fun_select of select | |||||||
| Fun_cstor of cstor | |||||||
| Fun_is_a of cstor | |||||||
| Fun_def of {
} | Methods on the custom term view whose arguments are
|
and fun_ty = {fun_ty_args : ty list; |
fun_ty_ret : ty; |
}Function type
and ty = {mutable ty_id : int; |
ty_view : ty_view; |
}Hashconsed type
and ty_view = | Ty_bool | |||
| Ty_real | |||
| Ty_atomic of {
} |
and ty_def = | Ty_uninterpreted of Sidekick_base_term.ID.t | |||
| Ty_data of {
} | |||
| Ty_def of {
} |
and data = {data_id : Sidekick_base_term.ID.t; |
data_cstors : cstor Sidekick_base_term__.ID.Map.t lazy_t; |
data_as_ty : ty lazy_t; |
}and cstor = {cstor_id : Sidekick_base_term.ID.t; |
cstor_is_a : Sidekick_base_term.ID.t; |
mutable cstor_arity : int; |
cstor_args : select list lazy_t; |
cstor_ty_as_data : data; |
cstor_ty : ty lazy_t; |
}and select = {select_id : Sidekick_base_term.ID.t; |
select_cstor : cstor; |
select_ty : ty lazy_t; |
select_i : int; |
}and value = | V_bool of bool | |||||
| V_element of {
} | a named constant, distinct from any other constant | ||||
| V_cstor of {
} | |||||
| V_custom of {
} | Custom value | ||||
| V_real of Q.t |
Semantic values, used for models (and possibly model-constructing calculi)
and value_custom_view = ..type definition = Sidekick_base_term.ID.t * ty * termtype statement = | Stmt_set_logic of string |
| Stmt_set_option of string list |
| Stmt_set_info of string * string |
| Stmt_data of data list |
| Stmt_ty_decl of Sidekick_base_term.ID.t * int |
| Stmt_decl of Sidekick_base_term.ID.t * ty list * ty |
| Stmt_define of definition list |
| Stmt_assert of term |
| Stmt_assert_clause of term list |
| Stmt_check_sat of (bool * term) list |
| Stmt_exit |
val term_equal_ : term -> term -> boolval term_hash_ : term -> intval term_cmp_ : term -> term -> intval fun_compare : fun_ -> fun_ -> intval pp_fun : CCFormat.t -> fun_ -> unitval id_of_fun : fun_ -> Sidekick_base_term.ID.tval eq_ty : ty -> ty -> boolval eq_cstor : cstor -> cstor -> boolval eq_value : value -> value -> boolval hash_value : value Sidekick_util.Hash.tval pp_value : value Sidekick_util.Util.printerval pp_db : Stdlib.Format.formatter -> (int * 'a) -> unitval pp_ty : ty Sidekick_util.Util.printerval string_of_lra_pred : lra_pred -> stringval pp_pred : Fmt.t -> lra_pred -> unitval string_of_lra_op : lra_op -> stringval pp_lra_op : Fmt.t -> lra_op -> unitval pp_term_view_gen : pp_id:(Fmt.t -> Sidekick_base_term.ID.t -> unit) -> pp_t:'a Fmt.printer -> Fmt.t -> 'a term_view -> unitval pp_term_top : ids:bool -> Fmt.t -> term -> unitval pp_term : Fmt.t -> term -> unitval pp_term_view : Fmt.t -> term term_view -> unitmodule Ty : sig ... endmodule Fun : sig ... endmodule Term_cell : sig ... endmodule Term : sig ... endmodule Value : sig ... endmodule Data : sig ... endmodule Select : sig ... endmodule Cstor : sig ... endmodule Proof : sig ... endmodule Statement : sig ... endSidekick_base_term__Base_typesmodule CC_view = Sidekick_core.CC_viewtype lra_pred = Sidekick_arith_lra.Predicate.t = | Leq |
| Geq |
| Lt |
| Gt |
| Eq |
| Neq |
type lra_op = Sidekick_arith_lra.op = | Plus |
| Minus |
type 'a lra_view = 'a Sidekick_arith_lra.lra_view = | LRA_pred of lra_pred * 'a * 'a |
| LRA_op of lra_op * 'a * 'a |
| LRA_mult of Q.t * 'a |
| LRA_const of Q.t |
| LRA_simplex_var of 'a |
| LRA_simplex_pred of 'a * Sidekick_arith_lra.S_op.t * Q.t |
| LRA_other of 'a |
type term = {mutable term_id : int; |
mutable term_ty : ty; |
term_view : term term_view; |
}and 'a term_view = | Bool of bool |
| App_fun of fun_ * 'a Sidekick_util.IArray.t |
| Eq of 'a * 'a |
| Not of 'a |
| Ite of 'a * 'a * 'a |
| LRA of 'a lra_view |
and fun_ = {fun_id : Sidekick_base_term.ID.t; |
fun_view : fun_view; |
}and fun_view = | Fun_undef of fun_ty | |||||||
| Fun_select of select | |||||||
| Fun_cstor of cstor | |||||||
| Fun_is_a of cstor | |||||||
| Fun_def of {
} | Methods on the custom term view whose arguments are
|
and fun_ty = {fun_ty_args : ty list; |
fun_ty_ret : ty; |
}Function type
and ty = {mutable ty_id : int; |
ty_view : ty_view; |
}Hashconsed type
and ty_view = | Ty_bool | |||
| Ty_real | |||
| Ty_atomic of {
} |
and ty_def = | Ty_uninterpreted of Sidekick_base_term.ID.t | |||
| Ty_data of {
} | |||
| Ty_def of {
} |
and data = {data_id : Sidekick_base_term.ID.t; |
data_cstors : cstor Sidekick_base_term__.ID.Map.t lazy_t; |
data_as_ty : ty lazy_t; |
}and cstor = {cstor_id : Sidekick_base_term.ID.t; |
cstor_is_a : Sidekick_base_term.ID.t; |
mutable cstor_arity : int; |
cstor_args : select list lazy_t; |
cstor_ty_as_data : data; |
cstor_ty : ty lazy_t; |
}and select = {select_id : Sidekick_base_term.ID.t; |
select_cstor : cstor; |
select_ty : ty lazy_t; |
select_i : int; |
}and value = | V_bool of bool | |||||
| V_element of {
} | a named constant, distinct from any other constant | ||||
| V_cstor of {
} | |||||
| V_custom of {
} | Custom value | ||||
| V_real of Q.t |
Semantic values, used for models (and possibly model-constructing calculi)
and value_custom_view = ..type definition = Sidekick_base_term.ID.t * ty * termtype statement = | Stmt_set_logic of string |
| Stmt_set_option of string list |
| Stmt_set_info of string * string |
| Stmt_data of data list |
| Stmt_ty_decl of Sidekick_base_term.ID.t * int |
| Stmt_decl of Sidekick_base_term.ID.t * ty list * ty |
| Stmt_define of definition list |
| Stmt_assert of term |
| Stmt_assert_clause of term list |
| Stmt_check_sat of (bool * term) list |
| Stmt_exit |
val term_equal_ : term -> term -> boolval term_hash_ : term -> intval term_cmp_ : term -> term -> intval fun_compare : fun_ -> fun_ -> intval pp_fun : CCFormat.t -> fun_ -> unitval id_of_fun : fun_ -> Sidekick_base_term.ID.tval eq_ty : ty -> ty -> boolval eq_cstor : cstor -> cstor -> boolval eq_value : value -> value -> boolval hash_value : value Sidekick_util.Hash.tval pp_value : value Sidekick_util.Util.printerval pp_db : Stdlib.Format.formatter -> (int * 'a) -> unitval pp_ty : ty Sidekick_util.Util.printerval string_of_lra_pred : lra_pred -> stringval pp_pred : Fmt.t -> lra_pred -> unitval string_of_lra_op : lra_op -> stringval pp_lra_op : Fmt.t -> lra_op -> unitval pp_term_view_gen : pp_id:(Fmt.t -> Sidekick_base_term.ID.t -> unit) -> pp_t:'a Fmt.printer -> Fmt.t -> 'a term_view -> unitval pp_term_top : ids:bool -> Fmt.t -> term -> unitval pp_term : Fmt.t -> term -> unitval pp_term_view : Fmt.t -> term term_view -> unitmodule Ty : sig ... endmodule Fun : sig ... endmodule Term_cell : sig ... endmodule Term : sig ... endmodule Value : sig ... endmodule Data : sig ... endmodule Select : sig ... endmodule Cstor : sig ... endmodule Statement : sig ... endSidekick_base_term__Proof.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
Sidekick_base_term__Proofinclude Sidekick_core.PROOF with type term = Sidekick_base_term.Base_types.Term.t and type ty = Sidekick_base_term.Base_types.Ty.ttype term = Sidekick_base_term.Base_types.Term.ttype ty = Sidekick_base_term.Base_types.Ty.ttype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endval isa_split : ty -> term Iter.t -> tval isa_disj : ty -> term -> term -> tval cstor_inj : Sidekick_base_term.Base_types.Cstor.t -> int -> term list -> term list -> tval bool_eq : term -> term -> tval bool_c : string -> term list -> tval ite_true : term -> tval ite_false : term -> tval lra : lit Iter.t -> tval lra_l : lit list -> tSolver.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerSolver.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
Solver.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endSolver.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val pp_debug : t Sidekick_core.Fmt.printerval pp_dot : t Sidekick_core.Fmt.printer optionOptional printer into DOT/graphviz
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
Solver.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
Solver.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
Process.Solvermodule T : Sidekick_core.TERM with type Term.t = Sidekick_base_term.Term.t and type Term.state = Sidekick_base_term.Term.state and type Ty.t = Sidekick_base_term.Ty.t and type Ty.state = Sidekick_base_term.Ty.statemodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
Process.Solvermodule T : Sidekick_core.TERM with type Term.t = Sidekick_base_term.Term.t and type Term.state = Sidekick_base_term.Term.state and type Ty.t = Sidekick_base_term.Ty.t and type Ty.state = Sidekick_base_term.Ty.statemodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
Sidekick_smtlib.Processmodule Solver : Sidekick_msat_solver.S with type T.Term.t = Sidekick_base_term.Term.t and type T.Term.state = Sidekick_base_term.Term.state and type T.Ty.t = Sidekick_base_term.Ty.t and type T.Ty.state = Sidekick_base_term.Ty.stateval th_bool : Solver.theoryval th_data : Solver.theoryval th_lra : Solver.theorymodule Check_cc : sig ... endval process_stmt : ?hyps:Solver.Atom.t list Sidekick_util.Vec.t -> ?gc:bool -> ?restarts:bool -> ?pp_cnf:bool -> ?dot_proof:string -> ?pp_model:bool -> ?check:bool -> ?time:float -> ?memory:float -> ?progress:bool -> Solver.t -> Sidekick_base_term.Statement.t -> unit or_errorSidekick_smtlib.Processmodule Solver : Sidekick_msat_solver.S with type T.Term.t = Sidekick_base_term.Term.t and type T.Term.state = Sidekick_base_term.Term.state and type T.Ty.t = Sidekick_base_term.Ty.t and type T.Ty.state = Sidekick_base_term.Ty.stateval th_bool : Solver.theoryval th_data : Solver.theoryval th_lra : Solver.theorymodule Check_cc : sig ... endval process_stmt : ?hyps:Solver.Atom.t list Sidekick_util.Vec.t -> ?gc:bool -> ?restarts:bool -> ?pp_cnf:bool -> ?dot_proof:string -> ?proof_file:string -> ?pp_model:bool -> ?check:bool -> ?time:float -> ?memory:float -> ?progress:bool -> Solver.t -> Sidekick_base_term.Statement.t -> unit or_errorSolver.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerSolver.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
Solver.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endSolver.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val pp_debug : t Sidekick_core.Fmt.printerval pp_dot : t Sidekick_core.Fmt.printer optionOptional printer into DOT/graphviz
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
Solver.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
Solver.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
Process.Solvermodule T : Sidekick_core.TERM with type Term.t = Sidekick_base_term.Term.t and type Term.state = Sidekick_base_term.Term.state and type Ty.t = Sidekick_base_term.Ty.t and type Ty.state = Sidekick_base_term.Ty.statemodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
Process.Solvermodule T : Sidekick_core.TERM with type Term.t = Sidekick_base_term.Term.t and type Term.state = Sidekick_base_term.Term.state and type Ty.t = Sidekick_base_term.Ty.t and type Ty.state = Sidekick_base_term.Ty.statemodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
Sidekick_smtlib__.Processmodule Solver : Sidekick_msat_solver.S with type T.Term.t = Sidekick_base_term.Term.t and type T.Term.state = Sidekick_base_term.Term.state and type T.Ty.t = Sidekick_base_term.Ty.t and type T.Ty.state = Sidekick_base_term.Ty.stateval th_bool : Solver.theoryval th_data : Solver.theoryval th_lra : Solver.theorymodule Check_cc : sig ... endval process_stmt : ?hyps:Solver.Atom.t list Sidekick_util.Vec.t -> ?gc:bool -> ?restarts:bool -> ?pp_cnf:bool -> ?dot_proof:string -> ?pp_model:bool -> ?check:bool -> ?time:float -> ?memory:float -> ?progress:bool -> Solver.t -> Sidekick_base_term.Statement.t -> unit or_errorSidekick_smtlib__.Processmodule Solver : Sidekick_msat_solver.S with type T.Term.t = Sidekick_base_term.Term.t and type T.Term.state = Sidekick_base_term.Term.state and type T.Ty.t = Sidekick_base_term.Ty.t and type T.Ty.state = Sidekick_base_term.Ty.stateval th_bool : Solver.theoryval th_data : Solver.theoryval th_lra : Solver.theorymodule Check_cc : sig ... endval process_stmt : ?hyps:Solver.Atom.t list Sidekick_util.Vec.t -> ?gc:bool -> ?restarts:bool -> ?pp_cnf:bool -> ?dot_proof:string -> ?proof_file:string -> ?pp_model:bool -> ?check:bool -> ?time:float -> ?memory:float -> ?progress:bool -> Solver.t -> Sidekick_base_term.Statement.t -> unit or_errorSolver.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerSolver.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
Solver.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endSolver.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val pp_debug : t Sidekick_core.Fmt.printerval pp_dot : t Sidekick_core.Fmt.printer optionOptional printer into DOT/graphviz
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
Solver.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
Solver.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
Sidekick_smtlib__Process.Solvermodule T : Sidekick_core.TERM with type Term.t = Sidekick_base_term.Term.t and type Term.state = Sidekick_base_term.Term.state and type Ty.t = Sidekick_base_term.Ty.t and type Ty.state = Sidekick_base_term.Ty.statemodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
Sidekick_smtlib__Process.Solvermodule T : Sidekick_core.TERM with type Term.t = Sidekick_base_term.Term.t and type Term.state = Sidekick_base_term.Term.state and type Ty.t = Sidekick_base_term.Ty.t and type Ty.state = Sidekick_base_term.Ty.statemodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
Sidekick_smtlib__Processmodule Solver : Sidekick_msat_solver.S with type T.Term.t = Sidekick_base_term.Term.t and type T.Term.state = Sidekick_base_term.Term.state and type T.Ty.t = Sidekick_base_term.Ty.t and type T.Ty.state = Sidekick_base_term.Ty.stateval th_bool : Solver.theoryval th_data : Solver.theoryval th_lra : Solver.theorymodule Check_cc : sig ... endval process_stmt : ?hyps:Solver.Atom.t list Sidekick_util.Vec.t -> ?gc:bool -> ?restarts:bool -> ?pp_cnf:bool -> ?dot_proof:string -> ?pp_model:bool -> ?check:bool -> ?time:float -> ?memory:float -> ?progress:bool -> Solver.t -> Sidekick_base_term.Statement.t -> unit or_errorSidekick_smtlib__Processmodule Solver : Sidekick_msat_solver.S with type T.Term.t = Sidekick_base_term.Term.t and type T.Term.state = Sidekick_base_term.Term.state and type T.Ty.t = Sidekick_base_term.Ty.t and type T.Ty.state = Sidekick_base_term.Ty.stateval th_bool : Solver.theoryval th_data : Solver.theoryval th_lra : Solver.theorymodule Check_cc : sig ... endval process_stmt : ?hyps:Solver.Atom.t list Sidekick_util.Vec.t -> ?gc:bool -> ?restarts:bool -> ?pp_cnf:bool -> ?dot_proof:string -> ?proof_file:string -> ?pp_model:bool -> ?check:bool -> ?time:float -> ?memory:float -> ?progress:bool -> Solver.t -> Sidekick_base_term.Statement.t -> unit or_errorMake.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Make.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
1-A.Actionsmodule T = Tmodule P = Pmodule Lit = Littype tAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
1-A.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype tAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
1-A.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printer1-A.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
1-A.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endMake.1-Amodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Tval cc_view : T.Term.t -> (T.Fun.t, T.Term.t, T.Term.t Iter.t) Sidekick_core.CC_view.tView the term through the lens of the congruence closure
Make.1-Amodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Tval cc_view : T.Term.t -> (T.Fun.t, T.Term.t, T.Term.t Iter.t) Sidekick_core.CC_view.tView the term through the lens of the congruence closure
Sidekick_cc.Makemodule T = A.Tmodule P = A.Pmodule Lit = A.Litmodule Actions = A.Actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Sidekick_cc.Makemodule T = A.Tmodule P = A.Pmodule Lit = A.Litmodule Actions = A.Actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
S.Actionsmodule T = Tmodule P = Pmodule Lit = Littype tAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
S.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype tAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
S.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
S.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
S.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
S.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endSidekick_cc.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Ttype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Sidekick_cc.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Ttype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
SI.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
SI.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
SI.LitA literal is a (preprocessed) term along with its sign. It is directly manipulated by the SAT solver.
module T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
SI.LitA literal is a (preprocessed) term along with its sign. It is directly manipulated by the SAT solver.
module T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
SI.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Fmt.printermodule Quip : sig ... endSI.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
SI.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
1-M.SItype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.ttype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
1-M.SItype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.ttype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
CC_ACTIONS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
CC_ACTIONS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
CC_ACTIONS.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Fmt.printermodule Quip : sig ... endSidekick_core.CC_ACTIONSActions provided to the congruence closure.
The congruence closure must be able to propagate literals when it detects that they are true or false; it must also be able to create conflicts when the set of (dis)equalities is inconsistent
type tAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
Sidekick_core.CC_ACTIONSActions provided to the congruence closure.
The congruence closure must be able to propagate literals when it detects that they are true or false; it must also be able to create conflicts when the set of (dis)equalities is inconsistent
type tAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC_ARG.Actionsmodule T = Tmodule P = Pmodule Lit = Littype tAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC_ARG.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype tAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC_ARG.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
CC_ARG.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
CC_ARG.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Fmt.printermodule Quip : sig ... endSidekick_core.CC_ARGArguments to a congruence closure's implementation
Sidekick_core.CC_ARGArguments to a congruence closure's implementation
CC_S.Actionsmodule T = Tmodule P = Pmodule Lit = Littype tAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC_S.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype tAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC_S.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC_S.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC_S.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
CC_S.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
CC_S.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Fmt.printermodule Quip : sig ... endSidekick_core.CC_SSignature of the congruence closure
type term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Sidekick_core.CC_SSignature of the congruence closure
type term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Sidekick_core.LITLiterals
Literals are a pair of a boolean-sorted term, and a sign. Positive literals are the same as their term, and negative literals are the negation of their term.
The SAT solver deals only in literals and clauses (sets of literals). Everything else belongs in the SMT solver.
val sign : t -> boolGet the sign. A negated literal has sign false.
Sidekick_core.LITLiterals
Literals are a pair of a boolean-sorted term, and a sign. Positive literals are the same as their term, and negative literals are the negation of their term.
The SAT solver deals only in literals and clauses (sets of literals). Everything else belongs in the SMT solver.
val sign : t -> boolGet the sign. A negated literal has sign false.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
SI.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
SI.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
SI.LitA literal is a (preprocessed) term along with its sign. It is directly manipulated by the SAT solver.
module T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
SI.LitA literal is a (preprocessed) term along with its sign. It is directly manipulated by the SAT solver.
module T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
SI.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Fmt.printermodule Quip : sig ... endSI.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
SI.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
MONOID_ARG.SItype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.ttype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
MONOID_ARG.SItype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.ttype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
PROOF.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
Sidekick_core.PROOFtype termtype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Fmt.printermodule Quip : sig ... endSOLVER.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
SOLVER.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
SOLVER.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Fmt.printermodule Quip : sig ... endSOLVER.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
SOLVER.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
SOLVER.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
Sidekick_core.SOLVERUser facing view of the solver
This is the solver a user of sidekick can see, after instantiating everything. The user can add some theories, clauses, etc. and asks the solver to check satisfiability.
Theory implementors will mostly interact with SOLVER_INTERNAL.
module Solver_internal : SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
Sidekick_core.SOLVERUser facing view of the solver
This is the solver a user of sidekick can see, after instantiating everything. The user can add some theories, clauses, etc. and asks the solver to check satisfiability.
Theory implementors will mostly interact with SOLVER_INTERNAL.
module Solver_internal : SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
SOLVER_INTERNAL.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
SOLVER_INTERNAL.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
SOLVER_INTERNAL.LitA literal is a (preprocessed) term along with its sign. It is directly manipulated by the SAT solver.
module T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
SOLVER_INTERNAL.LitA literal is a (preprocessed) term along with its sign. It is directly manipulated by the SAT solver.
module T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
SOLVER_INTERNAL.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Fmt.printermodule Quip : sig ... endSOLVER_INTERNAL.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
SOLVER_INTERNAL.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
Sidekick_core.SOLVER_INTERNALA view of the solver from a theory's point of view.
Theories should interact with the solver via this module, to assert new lemmas, propagate literals, access the congruence closure, etc.
type ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.ttype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
Sidekick_core.SOLVER_INTERNALA view of the solver from a theory's point of view.
Theories should interact with the solver via this module, to assert new lemmas, propagate literals, access the congruence closure, etc.
type ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.ttype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
Make.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerMake.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
Make.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val pp_debug : t Sidekick_core.Fmt.printerval pp_dot : t Sidekick_core.Fmt.printer optionOptional printer into DOT/graphviz
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
Make.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
Make.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
1-A.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endMake.1-Amodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOF with type term = T.Term.tSidekick_msat_solver.MakeMain functor to get a solver.
module T = A.Tmodule P = A.Pmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
Sidekick_msat_solver.MakeMain functor to get a solver.
module T = A.Tmodule P = A.Pmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
ARG.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endSidekick_msat_solver.ARGArgument to pass to the functor Make in order to create a new Msat-based SMT solver.
module T : Sidekick_core.TERMmodule P : Sidekick_core.PROOFSidekick_msat_solver.ARGArgument to pass to the functor Make in order to create a new Msat-based SMT solver.
module T : Sidekick_core.TERMmodule P : Sidekick_core.PROOF with type term = T.Term.tS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
S.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endS.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val pp_debug : t Sidekick_core.Fmt.printerval pp_dot : t Sidekick_core.Fmt.printer optionOptional printer into DOT/graphviz
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
Sidekick_msat_solver.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
Sidekick_msat_solver.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
S.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
S.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endS.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val pp_debug : t Sidekick_core.Fmt.printerval pp_dot : t Sidekick_core.Fmt.printer optionOptional printer into DOT/graphviz
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
1-A.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
1-A.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
Make.1-Amodule S : Sidekick_core.SOLVERtype term = S.T.Term.tval mk_bool : S.T.Term.state -> (term, term Sidekick_util.IArray.t) bool_view -> termMake a term from the given boolean view.
val check_congruence_classes : boolConfiguration: add final-check handler to verify if new boolean formulas are present in the congruence closure. Only enable if some theories are susceptible to create boolean formulas during the proof search.
module Gensym : sig ... endFresh symbol generator.
Make.1-Amodule S : Sidekick_core.SOLVERtype term = S.T.Term.tval proof_ite_true : S.T.Term.t -> S.P.tproof_ite_true (ite a b c) is a=true |- ite a b c = b
val proof_ite_false : S.T.Term.t -> S.P.tproof_ite_false (ite a b c) is a=false |- ite a b c = c
val proof_bool_eq : S.T.Term.t -> S.T.Term.t -> S.P.tBasic boolean logic for |- a=b
val mk_bool : S.T.Term.state -> (term, term Sidekick_util.IArray.t) bool_view -> termMake a term from the given boolean view.
val check_congruence_classes : boolConfiguration: add final-check handler to verify if new boolean formulas are present in the congruence closure. Only enable if some theories are susceptible to create boolean formulas during the proof search.
module Gensym : sig ... endFresh symbol generator.
S.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
S.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endS.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val pp_debug : t Sidekick_core.Fmt.printerval pp_dot : t Sidekick_core.Fmt.printer optionOptional printer into DOT/graphviz
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
ARG.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
ARG.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
Sidekick_th_bool_static.ARGArgument to the theory
module S : Sidekick_core.SOLVERtype term = S.T.Term.tval mk_bool : S.T.Term.state -> (term, term Sidekick_util.IArray.t) bool_view -> termMake a term from the given boolean view.
val check_congruence_classes : boolConfiguration: add final-check handler to verify if new boolean formulas are present in the congruence closure. Only enable if some theories are susceptible to create boolean formulas during the proof search.
module Gensym : sig ... endFresh symbol generator.
Sidekick_th_bool_static.ARGArgument to the theory
module S : Sidekick_core.SOLVERtype term = S.T.Term.tval proof_ite_true : S.T.Term.t -> S.P.tproof_ite_true (ite a b c) is a=true |- ite a b c = b
val proof_ite_false : S.T.Term.t -> S.P.tproof_ite_false (ite a b c) is a=false |- ite a b c = c
val proof_bool_eq : S.T.Term.t -> S.T.Term.t -> S.P.tBasic boolean logic for |- a=b
val mk_bool : S.T.Term.state -> (term, term Sidekick_util.IArray.t) bool_view -> termMake a term from the given boolean view.
val check_congruence_classes : boolConfiguration: add final-check handler to verify if new boolean formulas are present in the congruence closure. Only enable if some theories are susceptible to create boolean formulas during the proof search.
module Gensym : sig ... endFresh symbol generator.
S.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
S.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endS.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val pp_debug : t Sidekick_core.Fmt.printerval pp_dot : t Sidekick_core.Fmt.printer optionOptional printer into DOT/graphviz
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
A.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
A.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
S.Amodule S : Sidekick_core.SOLVERtype term = S.T.Term.tval mk_bool : S.T.Term.state -> (term, term Sidekick_util.IArray.t) bool_view -> termMake a term from the given boolean view.
val check_congruence_classes : boolConfiguration: add final-check handler to verify if new boolean formulas are present in the congruence closure. Only enable if some theories are susceptible to create boolean formulas during the proof search.
module Gensym : sig ... endFresh symbol generator.
S.Amodule S : Sidekick_core.SOLVERtype term = S.T.Term.tval proof_ite_true : S.T.Term.t -> S.P.tproof_ite_true (ite a b c) is a=true |- ite a b c = b
val proof_ite_false : S.T.Term.t -> S.P.tproof_ite_false (ite a b c) is a=false |- ite a b c = c
val proof_bool_eq : S.T.Term.t -> S.T.Term.t -> S.P.tBasic boolean logic for |- a=b
val mk_bool : S.T.Term.state -> (term, term Sidekick_util.IArray.t) bool_view -> termMake a term from the given boolean view.
val check_congruence_classes : boolConfiguration: add final-check handler to verify if new boolean formulas are present in the congruence closure. Only enable if some theories are susceptible to create boolean formulas during the proof search.
module Gensym : sig ... endFresh symbol generator.
S.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
S.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endS.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val pp_debug : t Sidekick_core.Fmt.printerval pp_dot : t Sidekick_core.Fmt.printer optionOptional printer into DOT/graphviz
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
1-A.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
1-A.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
S.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
S.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endS.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val pp_debug : t Sidekick_core.Fmt.printerval pp_dot : t Sidekick_core.Fmt.printer optionOptional printer into DOT/graphviz
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
ARG.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
ARG.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
S.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
S.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endS.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val pp_debug : t Sidekick_core.Fmt.printerval pp_dot : t Sidekick_core.Fmt.printer optionOptional printer into DOT/graphviz
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
A.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
A.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
S.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
S.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endS.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val pp_debug : t Sidekick_core.Fmt.printerval pp_dot : t Sidekick_core.Fmt.printer optionOptional printer into DOT/graphviz
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
1-A.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
1-A.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
Make.1-Amodule S : Sidekick_core.SOLVERmodule Cstor : sig ... endConstructor symbols.
val as_datatype : S.T.Ty.t -> (Cstor.t Iter.t, S.T.Ty.t) data_ty_viewTry to view type as a datatype (with its constructors)
val view_as_data : S.T.Term.t -> (Cstor.t, S.T.Term.t) data_viewTry to view term as a datatype term
val mk_cstor : S.T.Term.state -> Cstor.t -> S.T.Term.t Sidekick_util.IArray.t -> S.T.Term.tMake a constructor application term
val mk_is_a : S.T.Term.state -> Cstor.t -> S.T.Term.t -> S.T.Term.tMake a is-a term
val mk_sel : S.T.Term.state -> Cstor.t -> int -> S.T.Term.t -> S.T.Term.tMake a selector term
val mk_eq : S.T.Term.state -> S.T.Term.t -> S.T.Term.t -> S.T.Term.tMake a term equality
val ty_is_finite : S.T.Ty.t -> boolIs the given type known to be finite? For example a finite datatype (an "enum" in C parlance), or Bool, or Array Bool Bool.
val ty_set_is_finite : S.T.Ty.t -> bool -> unitModify the "finite" field (see ty_is_finite)
Make.1-Amodule S : Sidekick_core.SOLVERmodule Cstor : sig ... endConstructor symbols.
val as_datatype : S.T.Ty.t -> (Cstor.t Iter.t, S.T.Ty.t) data_ty_viewTry to view type as a datatype (with its constructors)
val view_as_data : S.T.Term.t -> (Cstor.t, S.T.Term.t) data_viewTry to view term as a datatype term
val mk_cstor : S.T.Term.state -> Cstor.t -> S.T.Term.t Sidekick_util.IArray.t -> S.T.Term.tMake a constructor application term
val mk_is_a : S.T.Term.state -> Cstor.t -> S.T.Term.t -> S.T.Term.tMake a is-a term
val mk_sel : S.T.Term.state -> Cstor.t -> int -> S.T.Term.t -> S.T.Term.tMake a selector term
val mk_eq : S.T.Term.state -> S.T.Term.t -> S.T.Term.t -> S.T.Term.tMake a term equality
val ty_is_finite : S.T.Ty.t -> boolIs the given type known to be finite? For example a finite datatype (an "enum" in C parlance), or Bool, or Array Bool Bool.
val ty_set_is_finite : S.T.Ty.t -> bool -> unitModify the "finite" field (see ty_is_finite)
val proof_isa_split : S.T.Ty.t -> S.T.Term.t Iter.t -> S.P.tval proof_isa_disj : S.T.Ty.t -> S.T.Term.t -> S.T.Term.t -> S.P.tval proof_cstor_inj : Cstor.t -> int -> S.T.Term.t list -> S.T.Term.t list -> S.P.tS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
S.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endS.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val pp_debug : t Sidekick_core.Fmt.printerval pp_dot : t Sidekick_core.Fmt.printer optionOptional printer into DOT/graphviz
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
ARG.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
ARG.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
Sidekick_th_data.ARGArgument to the functor
module S : Sidekick_core.SOLVERmodule Cstor : sig ... endConstructor symbols.
val as_datatype : S.T.Ty.t -> (Cstor.t Iter.t, S.T.Ty.t) data_ty_viewTry to view type as a datatype (with its constructors)
val view_as_data : S.T.Term.t -> (Cstor.t, S.T.Term.t) data_viewTry to view term as a datatype term
val mk_cstor : S.T.Term.state -> Cstor.t -> S.T.Term.t Sidekick_util.IArray.t -> S.T.Term.tMake a constructor application term
val mk_is_a : S.T.Term.state -> Cstor.t -> S.T.Term.t -> S.T.Term.tMake a is-a term
val mk_sel : S.T.Term.state -> Cstor.t -> int -> S.T.Term.t -> S.T.Term.tMake a selector term
val mk_eq : S.T.Term.state -> S.T.Term.t -> S.T.Term.t -> S.T.Term.tMake a term equality
val ty_is_finite : S.T.Ty.t -> boolIs the given type known to be finite? For example a finite datatype (an "enum" in C parlance), or Bool, or Array Bool Bool.
val ty_set_is_finite : S.T.Ty.t -> bool -> unitModify the "finite" field (see ty_is_finite)
Sidekick_th_data.ARGArgument to the functor
module S : Sidekick_core.SOLVERmodule Cstor : sig ... endConstructor symbols.
val as_datatype : S.T.Ty.t -> (Cstor.t Iter.t, S.T.Ty.t) data_ty_viewTry to view type as a datatype (with its constructors)
val view_as_data : S.T.Term.t -> (Cstor.t, S.T.Term.t) data_viewTry to view term as a datatype term
val mk_cstor : S.T.Term.state -> Cstor.t -> S.T.Term.t Sidekick_util.IArray.t -> S.T.Term.tMake a constructor application term
val mk_is_a : S.T.Term.state -> Cstor.t -> S.T.Term.t -> S.T.Term.tMake a is-a term
val mk_sel : S.T.Term.state -> Cstor.t -> int -> S.T.Term.t -> S.T.Term.tMake a selector term
val mk_eq : S.T.Term.state -> S.T.Term.t -> S.T.Term.t -> S.T.Term.tMake a term equality
val ty_is_finite : S.T.Ty.t -> boolIs the given type known to be finite? For example a finite datatype (an "enum" in C parlance), or Bool, or Array Bool Bool.
val ty_set_is_finite : S.T.Ty.t -> bool -> unitModify the "finite" field (see ty_is_finite)
val proof_isa_split : S.T.Ty.t -> S.T.Term.t Iter.t -> S.P.tval proof_isa_disj : S.T.Ty.t -> S.T.Term.t -> S.T.Term.t -> S.P.tval proof_cstor_inj : Cstor.t -> int -> S.T.Term.t list -> S.T.Term.t list -> S.P.tS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
val equal : t -> t -> boolval hash : t -> intval pp : t Sidekick_core.Fmt.printerS.Litmodule T = TLiterals depend on terms
val sign : t -> boolGet the sign. A negated literal has sign false.
P.Quipval output : Stdlib.out_channel -> t -> unitPrinter in Quip format (experimental)
S.Ptype term = T.Term.ttype tytype ttype hres_stephyper-resolution steps: resolution, unit resolution; bool paramodulation, unit bool paramodulation
val p : t -> lhs:term -> rhs:term -> hres_stepParamodulation using proof whose conclusion has a literal lhs=rhs
val pp_lit : lit Sidekick_core.Fmt.printerval lit_a : term -> litval lit_na : term -> litval lit_mk : bool -> term -> litval lit_eq : term -> term -> litval lit_neq : term -> term -> litval lit_not : lit -> litval lit_sign : lit -> boolval stepc : name:string -> lit list -> t -> composite_stepval deft : term -> term -> composite_stepdefine a (new) atomic term
val is_trivial_refl : t -> boolis this a proof of |- t=t? This can be used to remove some trivial steps that would build on the proof (e.g. rewriting using refl t is useless).
val assertion : term -> tval assertion_c : lit Iter.t -> tval ref_by_name : string -> tval assertion_c_l : lit list -> tval hres_iter : t -> hres_step Iter.t -> tval hres_l : t -> hres_step list -> tval res : pivot:term -> t -> t -> tval res1 : t -> t -> tval refl : term -> tval true_is_true : tval true_neq_false : tval nn : t -> tval cc_lemma : lit list -> tval cc_imply2 : t -> t -> term -> term -> tval cc_imply_l : t list -> term -> term -> tval composite_iter : ?assms:(string * lit) list -> composite_step Iter.t -> tval composite_l : ?assms:(string * lit) list -> composite_step list -> tval sorry : tval sorry_c : lit Iter.t -> tval sorry_c_l : lit list -> tval default : tval pp_debug : sharing:bool -> t Sidekick_core.Fmt.printermodule Quip : sig ... endS.Pre_proofA type or state convertible into P.t
val output : Stdlib.out_channel -> t -> unitOutput onto a channel, efficiently
val pp_debug : t Sidekick_core.Fmt.printerval pp_dot : t Sidekick_core.Fmt.printer optionOptional printer into DOT/graphviz
val check : t -> unitCheck the proof (to an unspecified level of confidence; this can be a no-op). May fail.
CC.Actionsmodule T = Tmodule P = Pmodule Lit = Littype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list) -> P.t -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.Actionsmodule T = Tmodule Lit = Litmodule P = Ptype t = actionsAn action handle. It is used by the congruence closure to perform the actions below. How it performs the actions is not specified and is solver-specific.
val raise_conflict : t -> Lit.t list -> P.t -> 'araise_conflict acts c pr declares that c is a tautology of the theory of congruence. This does not return (it should raise an exception).
the proof of c being a tautology
val propagate : t -> Lit.t -> reason:(unit -> Lit.t list * P.t) -> unitpropagate acts lit ~reason pr declares that reason() => lit is a tautology.
reason() should return a list of literals that are currently true.lit should be a literal of interest (see Sidekick_core.CC_S.set_as_lit).This function might never be called, a congruence closure has the right to not propagate and only trigger conflicts.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
CC.ExplExplanations
Explanations are specialized proofs, created by the congruence closure when asked to justify why 2 terms are equal.
Solver_internal.CCmodule T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.CCCongruence closure instance
module T = Tmodule P = Pmodule Lit = Litmodule Actions : Sidekick_core.CC_ACTIONS with module T = T and module Lit = Lit and module P = P and type t = actionstype term_state = T.Term.statetype term = T.Term.ttype fun_ = T.Fun.ttype lit = Lit.ttype proof = P.ttype actions = Actions.ttype tState of the congruence closure
module N : sig ... endAn equivalence class is a set of terms that are currently equal in the partial model built by the solver. The class is represented by a collection of nodes, one of which is distinguished and is called the "representative".
module Expl : sig ... endExplanations
type node = N.tA node of the congruence closure
type repr = N.tNode that is currently a representative
type explanation = Expl.tval term_state : t -> term_stateval find : t -> node -> reprCurrent representative
Events triggered by the congruence closure, to which other plugins can subscribe.
type ev_on_pre_merge = t -> actions -> N.t -> N.t -> Expl.t -> unitev_on_pre_merge cc acts n1 n2 expl is called right before n1 and n2 are merged with explanation expl.
type ev_on_post_merge = t -> actions -> N.t -> N.t -> unitev_on_post_merge cc acts n1 n2 is called right after n1 and n2 were merged. find cc n1 and find cc n2 will return the same node.
type ev_on_new_term = t -> N.t -> term -> unitev_on_new_term cc n t is called whenever a new term t is added to the congruence closure. Its node is n.
type ev_on_conflict = t -> th:bool -> lit list -> unitev_on_conflict acts ~th c is called when the congruence closure triggers a conflict by asserting the tautology c.
true if the explanation for this conflict involves at least one "theory" explanation; i.e. some of the equations participating in the conflict are purely syntactic theories like injectivity of constructors.
type ev_on_propagate = t -> lit -> (unit -> lit list * P.t) -> unitev_on_propagate cc lit reason is called whenever reason() => lit is a propagated lemma. See Sidekick_core.CC_ACTIONS.propagate.
type ev_on_is_subterm = N.t -> term -> unitev_on_is_subterm n t is called when n is a subterm of another node for the first time. t is the term corresponding to the node n. This can be useful for theory combination.
val create : ?stat:Sidekick_util.Stat.t -> ?on_pre_merge:ev_on_pre_merge list -> ?on_post_merge:ev_on_post_merge list -> ?on_new_term:ev_on_new_term list -> ?on_conflict:ev_on_conflict list -> ?on_propagate:ev_on_propagate list -> ?on_is_subterm:ev_on_is_subterm list -> ?size:[ `Small | `Big ] -> term_state -> tCreate a new congruence closure.
used to be able to create new terms. All terms interacting with this congruence closure must belong in this term state as well.
val allocate_bitfield : descr:string -> t -> N.bitfieldAllocate a new bitfield for the nodes. See N.bitfield.
val set_bitfield : t -> N.bitfield -> bool -> N.t -> unitSet the bitfield for the node. This will be backtracked. See N.bitfield.
val on_pre_merge : t -> ev_on_pre_merge -> unitAdd a function to be called when two classes are merged
val on_post_merge : t -> ev_on_post_merge -> unitAdd a function to be called when two classes are merged
val on_new_term : t -> ev_on_new_term -> unitAdd a function to be called when a new node is created
val on_conflict : t -> ev_on_conflict -> unitCalled when the congruence closure finds a conflict
val on_propagate : t -> ev_on_propagate -> unitCalled when the congruence closure propagates a literal
val on_is_subterm : t -> ev_on_is_subterm -> unitCalled on terms that are subterms of function symbols
val find_t : t -> term -> reprCurrent representative of the term.
if the term is not already add-ed.
val all_classes : t -> repr Iter.tAll current classes. This is costly, only use if there is no other solution
val assert_lit : t -> lit -> unitGiven a literal, assume it in the congruence closure and propagate its consequences. Will be backtracked.
Useful for the theory combination or the SAT solver's functor
val explain_eq : t -> N.t -> N.t -> lit listExplain why the two nodes are equal. Fails if they are not, in an unspecified way
val raise_conflict_from_expl : t -> actions -> Expl.t -> 'aRaise a conflict with the given explanation it must be a theory tautology that expl ==> absurd. To be used in theories.
val merge : t -> N.t -> N.t -> Expl.t -> unitMerge these two nodes given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val check : t -> actions -> unitPerform all pending operations done via assert_eq, assert_lit, etc. Will use the actions to propagate literals, declare conflicts, etc.
val push_level : t -> unitPush backtracking level
val pop_levels : t -> int -> unitRestore to state n calls to push_level earlier. Used during backtracking.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
Solver_internal.SimplifySimplify terms
val tst : t -> term_stateval ty_st : t -> ty_stateval clear : t -> unitReset internal cache, etc.
type hook = t -> term -> (term * proof) optionGiven a term, try to simplify it. Return None if it didn't change.
A simple example could be a hook that takes a term t, and if t is app "+" (const x) (const y) where x and y are number, returns Some (const (x+y)), and None otherwise.
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simp_t : t -> term -> termSimplify the term using the solver's simplifier (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list) -> proof -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> unit) -> term -> term optionGiven a term, try to preprocess it. Return None if it didn't change. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
S.Solver_internalInternal solver, available to theories.
module T = Tmodule P = Ptype ty = T.Ty.ttype term = T.Term.ttype term_state = T.Term.statetype ty_state = T.Ty.statetype proof = P.ttype ttype solver = tval tst : t -> term_stateval ty_st : t -> ty_stateval stats : t -> Sidekick_util.Stat.tmodule Lit = Littype lit = Lit.tmodule Simplify : sig ... endSimplify terms
type simplify_hook = Simplify.hookval add_simplifier : t -> Simplify.hook -> unitAdd a simplifier hook for preprocessing.
val simplifier : t -> Simplify.tval simplify_t : t -> term -> (term * proof) optionSimplify input term, returns Some (u, |- t=u) if some simplification occurred.
val simp_t : t -> term -> term * proofsimp_t si t returns u, |- t=u even if no simplification occurred (in which case t == u syntactically). (see simplifier)
val propagate : t -> actions -> lit -> reason:(unit -> lit list * proof) -> unitPropagate a literal for a reason. This is similar to asserting the clause reason => lit, but more lightweight, and in a way that is backtrackable.
val push_decision : t -> actions -> lit -> unitAsk the SAT solver to decide the given literal in an extension of the current trail. This is useful for theory combination. If the SAT solver backtracks, this (potential) decision is removed and forgotten.
val propagate : t -> actions -> lit -> (unit -> lit list * proof) -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val propagate_l : t -> actions -> lit -> lit list -> proof -> unitPropagate a boolean using a unit clause. expl => lit must be a theory lemma, that is, a T-tautology
val add_clause_temp : t -> actions -> lit list -> proof -> unitAdd local clause to the SAT solver. This clause will be removed when the solver backtracks.
val add_clause_permanent : t -> actions -> lit list -> proof -> unitAdd toplevel clause to the SAT solver. This clause will not be backtracked.
val mk_lit : t -> actions -> ?sign:bool -> term -> litCreate a literal. This automatically preprocesses the term.
val preprocess_term : t -> add_clause:(Lit.t list -> proof -> unit) -> term -> term * proofPreprocess a term.
val add_lit : t -> actions -> lit -> unitAdd the given literal to the SAT solver, so it gets assigned a boolean value
val add_lit_t : t -> actions -> ?sign:bool -> term -> unitAdd the given (signed) bool term to the SAT solver, so it gets assigned a boolean value
val cc_raise_conflict_expl : t -> actions -> CC.Expl.t -> 'aRaise a conflict with the given congruence closure explanation. it must be a theory tautology that expl ==> absurd. To be used in theories.
val cc_merge : t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unitMerge these two nodes in the congruence closure, given this explanation. It must be a theory tautology that expl ==> n1 = n2. To be used in theories.
val cc_merge_t : t -> actions -> term -> term -> CC.Expl.t -> unitMerge these two terms in the congruence closure, given this explanation. See cc_merge
val cc_add_term : t -> term -> CC.N.tAdd/retrieve congruence closure node for this term. To be used in theories
val cc_mem_term : t -> term -> boolReturn true if the term is explicitly in the congruence closure. To be used in theories
val on_cc_pre_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> CC.Expl.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called before)
val on_cc_post_merge : t -> (CC.t -> actions -> CC.N.t -> CC.N.t -> unit) -> unitCallback for when two classes containing data for this key are merged (called after)
val on_cc_new_term : t -> (CC.t -> CC.N.t -> term -> unit) -> unitCallback to add data on terms when they are added to the congruence closure
val on_cc_is_subterm : t -> (CC.N.t -> term -> unit) -> unitCallback for when a term is a subterm of another term in the congruence closure
val on_cc_conflict : t -> (CC.t -> th:bool -> lit list -> unit) -> unitCallback called on every CC conflict
val on_cc_propagate : t -> (CC.t -> lit -> (unit -> lit list * proof) -> unit) -> unitCallback called on every CC propagation
val on_partial_check : t -> (t -> actions -> lit Iter.t -> unit) -> unitRegister callbacked to be called with the slice of literals newly added on the trail.
This is called very often and should be efficient. It doesn't have to be complete, only correct. It's given only the slice of the trail consisting in new literals.
These preprocessors turn mixed, raw literals (possibly simplified) into literals suitable for reasoning. Typically some clauses are also added to the solver.
type preprocess_hook = t -> mk_lit:(term -> lit) -> add_clause:(lit list -> proof -> unit) -> term -> (term * proof) optionGiven a term, try to preprocess it. Return None if it didn't change, or Some (u,p) if t=u and p is a proof of t=u. Can also add clauses to define new terms.
Preprocessing might transform terms to make them more amenable to reasoning, e.g. by removing boolean formulas via Tseitin encoding, adding clauses that encode their meaning in the same move.
creates a new literal for a boolean term.
pushes a new clause into the SAT solver.
val on_preprocess : t -> preprocess_hook -> unitAdd a hook that will be called when terms are preprocessed
type model_hook = recurse:(t -> CC.N.t -> term) -> t -> CC.N.t -> term optionA model-production hook. It takes the solver, a class, and returns a term for this class. For example, an arithmetic theory might detect that a class contains a numeric constant, and return this constant as a model value.
If no hook assigns a value to a class, a fake value is created for it.
val on_model_gen : t -> model_hook -> unitAdd a hook that will be called when a model is being produced
A.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOFmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endmodule Proof : sig ... endtype proof = Proof.tval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.tTurn a literal into a SAT solver literal.
val mk_atom_t : t -> ?sign:bool -> term -> Atom.tTurn a boolean term, with a sign, into a SAT solver's literal.
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
val add_clause_l : t -> Atom.t list -> unitSame as add_clause but with a list of atoms.
type res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
A.Smodule T : Sidekick_core.TERMmodule P : Sidekick_core.PROOF with type term = T.Term.tmodule Lit : Sidekick_core.LIT with module T = Tmodule Solver_internal : Sidekick_core.SOLVER_INTERNAL with module T = T and module P = P and module Lit = LitInternal solver, available to theories.
module type THEORY = sig ... endtype theory = (module THEORY)A theory that can be used for this particular solver.
type 'a theory_p = (module THEORY with type t = 'a)A theory that can be used for this particular solver, with state of type 'a.
val mk_theory : name:string -> create_and_setup:(Solver_internal.t -> 'th) -> ?push_level:('th -> unit) -> ?pop_levels:('th -> int -> unit) -> unit -> theoryHelper to create a theory.
module Atom : sig ... endmodule Model : sig ... endModels
module Unknown : sig ... endval stats : t -> Sidekick_util.Stat.tval tst : t -> T.Term.stateval ty_st : t -> T.Ty.stateval create : ?stat:Sidekick_util.Stat.t -> ?size:[ `Big | `Tiny | `Small ] -> ?store_proof:bool -> theories:theory list -> T.Term.state -> T.Ty.state -> unit -> tCreate a new solver.
It needs a term state and a type state to manipulate terms and types. All terms and types interacting with this solver will need to come from these exact states.
if true, proofs from the SAT solver and theories are retained and potentially accessible after solve returns UNSAT.
influences the size of initial allocations.
theories to load from the start. Other theories can be added using add_theory.
val add_theory : t -> theory -> unitAdd a theory to the solver. This should be called before any call to solve or to add_clause and the likes (otherwise the theory will have a partial view of the problem).
val add_theory_l : t -> theory list -> unitval mk_atom_lit : t -> lit -> Atom.t * P.tmk_atom_lit _ lit returns atom, pr where atom is an internal atom for the solver, and pr is a proof of |- lit = atom
val mk_atom_t : t -> ?sign:bool -> term -> Atom.t * P.tmk_atom_t _ ~sign t returns atom, pr where atom is an internal representation of ± t, and pr is a proof of |- atom = (± t)
val add_clause : t -> Atom.t Sidekick_util.IArray.t -> P.t -> unitadd_clause solver cs adds a boolean clause to the solver. Subsequent calls to solve will need to satisfy this clause.
module Pre_proof : sig ... endtype res = | Sat of Model.t | Satisfiable | ||||
| Unsat of {
} | Unsatisfiable | ||||
| Unknown of Unknown.t | Unknown, obtained after a timeout, memory limit, etc. |
Result of solving for the current set of clauses
val solve : ?on_exit:(unit -> unit) list -> ?check:bool -> ?on_progress:(t -> unit) -> assumptions:Atom.t list -> t -> ressolve s checks the satisfiability of the clauses added so far to s.
if true, the model is checked before returning.
called regularly during solving.
a set of atoms held to be true. The unsat core, if any, will be a subset of assumptions.
functions to be run before this returns
val pp_stats : t CCFormat.printerPrint some statistics. What it prints exactly is unspecified.
S.Amodule S : Sidekick_core.SOLVERmodule Cstor : sig ... endConstructor symbols.
val as_datatype : S.T.Ty.t -> (Cstor.t Iter.t, S.T.Ty.t) data_ty_viewTry to view type as a datatype (with its constructors)
val view_as_data : S.T.Term.t -> (Cstor.t, S.T.Term.t) data_viewTry to view term as a datatype term
val mk_cstor : S.T.Term.state -> Cstor.t -> S.T.Term.t Sidekick_util.IArray.t -> S.T.Term.tMake a constructor application term
val mk_is_a : S.T.Term.state -> Cstor.t -> S.T.Term.t -> S.T.Term.tMake a is-a term
val mk_sel : S.T.Term.state -> Cstor.t -> int -> S.T.Term.t -> S.T.Term.tMake a selector term
val mk_eq : S.T.Term.state -> S.T.Term.t -> S.T.Term.t -> S.T.Term.tMake a term equality
val ty_is_finite : S.T.Ty.t -> boolIs the given type known to be finite? For example a finite datatype (an "enum" in C parlance), or Bool, or Array Bool Bool.
val ty_set_is_finite : S.T.Ty.t -> bool -> unitModify the "finite" field (see ty_is_finite)
S.Amodule S : Sidekick_core.SOLVERmodule Cstor : sig ... endConstructor symbols.
val as_datatype : S.T.Ty.t -> (Cstor.t Iter.t, S.T.Ty.t) data_ty_viewTry to view type as a datatype (with its constructors)
val view_as_data : S.T.Term.t -> (Cstor.t, S.T.Term.t) data_viewTry to view term as a datatype term
val mk_cstor : S.T.Term.state -> Cstor.t -> S.T.Term.t Sidekick_util.IArray.t -> S.T.Term.tMake a constructor application term
val mk_is_a : S.T.Term.state -> Cstor.t -> S.T.Term.t -> S.T.Term.tMake a is-a term
val mk_sel : S.T.Term.state -> Cstor.t -> int -> S.T.Term.t -> S.T.Term.tMake a selector term
val mk_eq : S.T.Term.state -> S.T.Term.t -> S.T.Term.t -> S.T.Term.tMake a term equality
val ty_is_finite : S.T.Ty.t -> boolIs the given type known to be finite? For example a finite datatype (an "enum" in C parlance), or Bool, or Array Bool Bool.
val ty_set_is_finite : S.T.Ty.t -> bool -> unitModify the "finite" field (see ty_is_finite)
val proof_isa_split : S.T.Ty.t -> S.T.Term.t Iter.t -> S.P.tval proof_isa_disj : S.T.Ty.t -> S.T.Term.t -> S.T.Term.t -> S.P.tval proof_cstor_inj : Cstor.t -> int -> S.T.Term.t list -> S.T.Term.t list -> S.P.tSidekick_util.IArraytype 'a t = private 'a arrayArray of values of type 'a. The underlying type really is an array, but it will never be modified.
It should be covariant but OCaml will not accept it.
val empty : 'a tval is_empty : _ t -> boolval length : _ t -> intval sub : 'a t -> int -> int -> 'a tval singleton : 'a -> 'a tval doubleton : 'a -> 'a -> 'a tval make : int -> 'a -> 'a tmake n x makes an array of n times x
val init : int -> (int -> 'a) -> 'a tinit n f makes the array [| f 0; f 1; ... ; f (n-1) |].
if n < 0
val get : 'a t -> int -> 'aAccess the element
val unsafe_get : 'a t -> int -> 'aUnsafe access, not bound-checked. Use with caution
val map : ('a -> 'b) -> 'a t -> 'b tval mapi : (int -> 'a -> 'b) -> 'a t -> 'b tval append : 'a t -> 'a t -> 'a tval iter : ('a -> unit) -> 'a t -> unitval iteri : (int -> 'a -> unit) -> 'a t -> unitval foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'aval fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'aval for_all : ('a -> bool) -> 'a t -> boolval exists : ('a -> bool) -> 'a t -> boolval of_list : 'a list -> 'a tval to_list : 'a t -> 'a listval of_list_map : ('a -> 'b) -> 'a list -> 'b tval to_list_map : ('a -> 'b) -> 'a t -> 'b listval of_array_map : ('a -> 'b) -> 'a array -> 'b tval to_array_map : ('a -> 'b) -> 'a t -> 'b arrayval of_array_unsafe : 'a array -> 'a tTake ownership of the given array. Careful, the array must NOT be modified afterwards!
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval compare : ('a -> 'a -> int) -> 'a t -> 'a t -> intval for_all2 : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval exists2 : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c tval fold2 : ('acc -> 'a -> 'b -> 'acc) -> 'acc -> 'a t -> 'b t -> 'accval iter2 : ('a -> 'b -> unit) -> 'a t -> 'b t -> unitSidekick_util.IArraytype 'a t = private 'a arrayArray of values of type 'a. The underlying type really is an array, but it will never be modified.
It should be covariant but OCaml will not accept it.
val empty : 'a tval is_empty : _ t -> boolval length : _ t -> intval sub : 'a t -> int -> int -> 'a tval singleton : 'a -> 'a tval doubleton : 'a -> 'a -> 'a tval make : int -> 'a -> 'a tmake n x makes an array of n times x
val init : int -> (int -> 'a) -> 'a tinit n f makes the array [| f 0; f 1; ... ; f (n-1) |].
if n < 0
val get : 'a t -> int -> 'aAccess the element
val unsafe_get : 'a t -> int -> 'aUnsafe access, not bound-checked. Use with caution
val map : ('a -> 'b) -> 'a t -> 'b tval mapi : (int -> 'a -> 'b) -> 'a t -> 'b tval append : 'a t -> 'a t -> 'a tval iter : ('a -> unit) -> 'a t -> unitval iteri : (int -> 'a -> unit) -> 'a t -> unitval foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'aval fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'aval for_all : ('a -> bool) -> 'a t -> boolval exists : ('a -> bool) -> 'a t -> boolval of_list : 'a list -> 'a tval to_list : 'a t -> 'a listval of_list_map : ('a -> 'b) -> 'a list -> 'b tval to_list_map : ('a -> 'b) -> 'a t -> 'b listval of_array_map : ('a -> 'b) -> 'a array -> 'b tval to_array_map : ('a -> 'b) -> 'a t -> 'b arrayval of_array_unsafe : 'a array -> 'a tTake ownership of the given array. Careful, the array must NOT be modified afterwards!
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval compare : ('a -> 'a -> int) -> 'a t -> 'a t -> intval for_all2 : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval exists2 : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c tval fold2 : ('acc -> 'a -> 'b -> 'acc) -> 'acc -> 'a t -> 'b t -> 'accval iteri2 : (int -> 'a -> 'b -> unit) -> 'a t -> 'b t -> unitval iter2 : ('a -> 'b -> unit) -> 'a t -> 'b t -> unitSidekick_util.Profileval null_probe : probeval enabled : unit -> boolval instant : string -> unitval begin_ : string -> probeval exit : probe -> unitval with_ : string -> (unit -> 'a) -> 'aval with1 : string -> ('a -> 'b) -> 'a -> 'bmodule type BACKEND = sig ... endtype backend = (module BACKEND)module Control : sig ... endSidekick_util.Profileval null_probe : probeval enabled : unit -> boolval instant : string -> unitval begin_ : string -> probeval exit : probe -> unitval with_ : string -> (unit -> 'a) -> 'aval with1 : string -> ('a -> 'b) -> 'a -> 'bval with2 : string -> ('a -> 'b -> 'c) -> 'a -> 'b -> 'cmodule type BACKEND = sig ... endtype backend = (module BACKEND)module Control : sig ... endSidekick_util__.IArraytype 'a t = private 'a arrayArray of values of type 'a. The underlying type really is an array, but it will never be modified.
It should be covariant but OCaml will not accept it.
val empty : 'a tval is_empty : _ t -> boolval length : _ t -> intval sub : 'a t -> int -> int -> 'a tval singleton : 'a -> 'a tval doubleton : 'a -> 'a -> 'a tval make : int -> 'a -> 'a tmake n x makes an array of n times x
val init : int -> (int -> 'a) -> 'a tinit n f makes the array [| f 0; f 1; ... ; f (n-1) |].
if n < 0
val get : 'a t -> int -> 'aAccess the element
val unsafe_get : 'a t -> int -> 'aUnsafe access, not bound-checked. Use with caution
val map : ('a -> 'b) -> 'a t -> 'b tval mapi : (int -> 'a -> 'b) -> 'a t -> 'b tval append : 'a t -> 'a t -> 'a tval iter : ('a -> unit) -> 'a t -> unitval iteri : (int -> 'a -> unit) -> 'a t -> unitval foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'aval fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'aval for_all : ('a -> bool) -> 'a t -> boolval exists : ('a -> bool) -> 'a t -> boolval of_list : 'a list -> 'a tval to_list : 'a t -> 'a listval of_list_map : ('a -> 'b) -> 'a list -> 'b tval to_list_map : ('a -> 'b) -> 'a t -> 'b listval of_array_map : ('a -> 'b) -> 'a array -> 'b tval to_array_map : ('a -> 'b) -> 'a t -> 'b arrayval of_array_unsafe : 'a array -> 'a tTake ownership of the given array. Careful, the array must NOT be modified afterwards!
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval compare : ('a -> 'a -> int) -> 'a t -> 'a t -> intval for_all2 : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval exists2 : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c tval fold2 : ('acc -> 'a -> 'b -> 'acc) -> 'acc -> 'a t -> 'b t -> 'accval iter2 : ('a -> 'b -> unit) -> 'a t -> 'b t -> unitSidekick_util__.IArraytype 'a t = private 'a arrayArray of values of type 'a. The underlying type really is an array, but it will never be modified.
It should be covariant but OCaml will not accept it.
val empty : 'a tval is_empty : _ t -> boolval length : _ t -> intval sub : 'a t -> int -> int -> 'a tval singleton : 'a -> 'a tval doubleton : 'a -> 'a -> 'a tval make : int -> 'a -> 'a tmake n x makes an array of n times x
val init : int -> (int -> 'a) -> 'a tinit n f makes the array [| f 0; f 1; ... ; f (n-1) |].
if n < 0
val get : 'a t -> int -> 'aAccess the element
val unsafe_get : 'a t -> int -> 'aUnsafe access, not bound-checked. Use with caution
val map : ('a -> 'b) -> 'a t -> 'b tval mapi : (int -> 'a -> 'b) -> 'a t -> 'b tval append : 'a t -> 'a t -> 'a tval iter : ('a -> unit) -> 'a t -> unitval iteri : (int -> 'a -> unit) -> 'a t -> unitval foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'aval fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'aval for_all : ('a -> bool) -> 'a t -> boolval exists : ('a -> bool) -> 'a t -> boolval of_list : 'a list -> 'a tval to_list : 'a t -> 'a listval of_list_map : ('a -> 'b) -> 'a list -> 'b tval to_list_map : ('a -> 'b) -> 'a t -> 'b listval of_array_map : ('a -> 'b) -> 'a array -> 'b tval to_array_map : ('a -> 'b) -> 'a t -> 'b arrayval of_array_unsafe : 'a array -> 'a tTake ownership of the given array. Careful, the array must NOT be modified afterwards!
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval compare : ('a -> 'a -> int) -> 'a t -> 'a t -> intval for_all2 : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval exists2 : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c tval fold2 : ('acc -> 'a -> 'b -> 'acc) -> 'acc -> 'a t -> 'b t -> 'accval iteri2 : (int -> 'a -> 'b -> unit) -> 'a t -> 'b t -> unitval iter2 : ('a -> 'b -> unit) -> 'a t -> 'b t -> unitSidekick_util__.Profileval null_probe : probeval enabled : unit -> boolval instant : string -> unitval begin_ : string -> probeval exit : probe -> unitval with_ : string -> (unit -> 'a) -> 'aval with1 : string -> ('a -> 'b) -> 'a -> 'bmodule type BACKEND = sig ... endtype backend = (module BACKEND)module Control : sig ... endSidekick_util__.Profileval null_probe : probeval enabled : unit -> boolval instant : string -> unitval begin_ : string -> probeval exit : probe -> unitval with_ : string -> (unit -> 'a) -> 'aval with1 : string -> ('a -> 'b) -> 'a -> 'bval with2 : string -> ('a -> 'b -> 'c) -> 'a -> 'b -> 'cmodule type BACKEND = sig ... endtype backend = (module BACKEND)module Control : sig ... endSidekick_util__IArraytype 'a t = private 'a arrayArray of values of type 'a. The underlying type really is an array, but it will never be modified.
It should be covariant but OCaml will not accept it.
val empty : 'a tval is_empty : _ t -> boolval length : _ t -> intval sub : 'a t -> int -> int -> 'a tval singleton : 'a -> 'a tval doubleton : 'a -> 'a -> 'a tval make : int -> 'a -> 'a tmake n x makes an array of n times x
val init : int -> (int -> 'a) -> 'a tinit n f makes the array [| f 0; f 1; ... ; f (n-1) |].
if n < 0
val get : 'a t -> int -> 'aAccess the element
val unsafe_get : 'a t -> int -> 'aUnsafe access, not bound-checked. Use with caution
val map : ('a -> 'b) -> 'a t -> 'b tval mapi : (int -> 'a -> 'b) -> 'a t -> 'b tval append : 'a t -> 'a t -> 'a tval iter : ('a -> unit) -> 'a t -> unitval iteri : (int -> 'a -> unit) -> 'a t -> unitval foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'aval fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'aval for_all : ('a -> bool) -> 'a t -> boolval exists : ('a -> bool) -> 'a t -> boolval of_list : 'a list -> 'a tval to_list : 'a t -> 'a listval of_list_map : ('a -> 'b) -> 'a list -> 'b tval to_list_map : ('a -> 'b) -> 'a t -> 'b listval of_array_map : ('a -> 'b) -> 'a array -> 'b tval to_array_map : ('a -> 'b) -> 'a t -> 'b arrayval of_array_unsafe : 'a array -> 'a tTake ownership of the given array. Careful, the array must NOT be modified afterwards!
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval compare : ('a -> 'a -> int) -> 'a t -> 'a t -> intval for_all2 : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval exists2 : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c tval fold2 : ('acc -> 'a -> 'b -> 'acc) -> 'acc -> 'a t -> 'b t -> 'accval iter2 : ('a -> 'b -> unit) -> 'a t -> 'b t -> unitSidekick_util__IArraytype 'a t = private 'a arrayArray of values of type 'a. The underlying type really is an array, but it will never be modified.
It should be covariant but OCaml will not accept it.
val empty : 'a tval is_empty : _ t -> boolval length : _ t -> intval sub : 'a t -> int -> int -> 'a tval singleton : 'a -> 'a tval doubleton : 'a -> 'a -> 'a tval make : int -> 'a -> 'a tmake n x makes an array of n times x
val init : int -> (int -> 'a) -> 'a tinit n f makes the array [| f 0; f 1; ... ; f (n-1) |].
if n < 0
val get : 'a t -> int -> 'aAccess the element
val unsafe_get : 'a t -> int -> 'aUnsafe access, not bound-checked. Use with caution
val map : ('a -> 'b) -> 'a t -> 'b tval mapi : (int -> 'a -> 'b) -> 'a t -> 'b tval append : 'a t -> 'a t -> 'a tval iter : ('a -> unit) -> 'a t -> unitval iteri : (int -> 'a -> unit) -> 'a t -> unitval foldi : ('a -> int -> 'b -> 'a) -> 'a -> 'b t -> 'aval fold : ('a -> 'b -> 'a) -> 'a -> 'b t -> 'aval for_all : ('a -> bool) -> 'a t -> boolval exists : ('a -> bool) -> 'a t -> boolval of_list : 'a list -> 'a tval to_list : 'a t -> 'a listval of_list_map : ('a -> 'b) -> 'a list -> 'b tval to_list_map : ('a -> 'b) -> 'a t -> 'b listval of_array_map : ('a -> 'b) -> 'a array -> 'b tval to_array_map : ('a -> 'b) -> 'a t -> 'b arrayval of_array_unsafe : 'a array -> 'a tTake ownership of the given array. Careful, the array must NOT be modified afterwards!
val equal : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval compare : ('a -> 'a -> int) -> 'a t -> 'a t -> intval for_all2 : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval exists2 : ('a -> 'a -> bool) -> 'a t -> 'a t -> boolval map2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c tval fold2 : ('acc -> 'a -> 'b -> 'acc) -> 'acc -> 'a t -> 'b t -> 'accval iteri2 : (int -> 'a -> 'b -> unit) -> 'a t -> 'b t -> unitval iter2 : ('a -> 'b -> unit) -> 'a t -> 'b t -> unitSidekick_util__Profileval null_probe : probeval enabled : unit -> boolval instant : string -> unitval begin_ : string -> probeval exit : probe -> unitval with_ : string -> (unit -> 'a) -> 'aval with1 : string -> ('a -> 'b) -> 'a -> 'bmodule type BACKEND = sig ... endtype backend = (module BACKEND)module Control : sig ... endSidekick_util__Profileval null_probe : probeval enabled : unit -> boolval instant : string -> unitval begin_ : string -> probeval exit : probe -> unitval with_ : string -> (unit -> 'a) -> 'aval with1 : string -> ('a -> 'b) -> 'a -> 'bval with2 : string -> ('a -> 'b -> 'c) -> 'a -> 'b -> 'cmodule type BACKEND = sig ... endtype backend = (module BACKEND)module Control : sig ... end