type config = Config.config
type bound = Bound.bound
type literal = Term.literal
type clause = Term.clause
type state = State.state
type context = Context.context
type choice_point = State.choice_point
type explanation = State.explanation
type propositional_lemmas
type raw_context_unifier = Context_unifier.raw_context_unifier
type candidates = Selection_assert.candidates
type selected = Selection_types.selected
type space = Context_unifier.context_unifier_space
type space_registry = Context_unifier_space.space_registry
type status =
| True of Context.element
| False of Context.element
| Undetermined
type abstraction = {
abs_literal: literal;
mutable abs_status: status;
}
module LiteralTable = Term.LiteralTable
module AbstractionTable =
Hashtbl.Make (
struct
type t = abstraction
let equal x y : bool =
Term.literal_equal x.abs_literal y.abs_literal
let hash x : int =
Term.hash_of_literal x.abs_literal
end
)
class index_data =
object
method is_equal (x: abstraction) (y: abstraction) =
x == y
method to_string abstraction : string =
Term.literal_to_string abstraction.abs_literal
end
type predicate_index = abstraction Term_indexing.predicate_index
type index = abstraction Term_indexing.index
type lemma = {
clause: clause;
space: space;
global: bool;
abstraction: abstraction array;
mutable watched1: int;
mutable watched2: int;
}
module LemmaTable =
Hashtbl.Make (
struct
type t = lemma
let equal x y : bool =
x == y
let hash x : int =
x.space.Context_unifier.cus_id
end
)
module ClauseTable = Term.ClauseTable
type lemmas_propositional = {
config: config;
state: state;
context: context;
space_registry: space_registry;
candidates: candidates;
process_close: (raw_context_unifier -> unit);
process_assert: (raw_context_unifier -> bool);
literal_to_abstraction: abstraction LiteralTable.t;
abstraction_to_lemmas: (unit LemmaTable.t) AbstractionTable.t;
lemmas: lemma ClauseTable.t;
subsumed: index;
mutable propagations: (choice_point * lemma) list;
}
let create config state context candidates process_close process_assert space_registry = {
config = config;
state = state;
context = context;
space_registry = space_registry;
candidates = candidates;
process_close = process_close;
process_assert = process_assert;
literal_to_abstraction = LiteralTable.create 1023;
abstraction_to_lemmas = AbstractionTable.create 1023;
lemmas = ClauseTable.create 51;
subsumed = Discrimination_tree.create_index false (new index_data);
propagations = [];
}
let prune_lemmas lemmas_propositional : unit =
let max_lemmas = Config.lemma_max lemmas_propositional.config
and min_lemmas = Config.lemma_min lemmas_propositional.config
in
if max_lemmas > 0 && ClauseTable.length lemmas_propositional.lemmas >= max_lemmas then begin
let rec find_min min =
let pruned =
ClauseTable.fold
(fun _ lemma pruned ->
if !(lemma.space.Context_unifier.cus_utility) > min then
pruned
else
pruned + 1
)
lemmas_propositional.lemmas
0
in
if pruned >= (max_lemmas - min_lemmas) then
pruned
else
find_min (min + 1)
in
let min =
find_min 0
in
let _, remove =
ClauseTable.fold
(fun clause lemma ((pruned, remove) as acc) ->
if
(pruned >= (max_lemmas - min_lemmas))
||
(!(lemma.space.Context_unifier.cus_utility) > min)
then begin
acc
end
else begin
(pruned + 1, clause :: remove)
end
)
lemmas_propositional.lemmas
(0, [])
in
List.iter
(fun clause -> ClauseTable.remove lemmas_propositional.lemmas clause)
remove
end
let get_lemmas lemmas_propositional =
List.rev (
ClauseTable.fold
(fun _ lemma acc ->
if lemma.global then
lemma.clause :: acc
else
acc
)
lemmas_propositional.lemmas
[]
)
let filter_lemma lemmas_propositional (clause: clause) : bool =
ClauseTable.mem
lemmas_propositional.lemmas
clause
let register_watched_literal lemmas_propositional abstraction lemma =
let lemmas =
try
AbstractionTable.find lemmas_propositional.abstraction_to_lemmas abstraction
with
| Not_found ->
let lemmas =
LemmaTable.create 63
in
AbstractionTable.add lemmas_propositional.abstraction_to_lemmas abstraction lemmas;
lemmas
in
LemmaTable.add lemmas lemma ()
let unregister_watched_literal lemmas_propositional abstraction lemma =
let lemmas =
try
AbstractionTable.find lemmas_propositional.abstraction_to_lemmas abstraction
with
| Not_found ->
failwith "unregister_watched_literal"
in
LemmaTable.remove lemmas lemma
let rec find_watched_literal abstraction i j =
if i >= Array.length abstraction then
i
else if i == j then
find_watched_literal abstraction (i + 1) j
else match abstraction.(i).abs_status with
| True _ ->
i
| False _ ->
find_watched_literal abstraction (i + 1) j
| Undetermined ->
i
let compute_context_unifier lemma =
let context_partners =
Array.map
(fun abstraction ->
match abstraction.abs_status with
| False element ->
Context_unifier.create_context_partner
element
None
true
| Undetermined ->
Context_unifier.assert_partner;
| True _ ->
failwith "compute_propagation: not inconsistent but subsumed"
)
lemma.abstraction
in
Context_unifier.create_context_unifier
lemma.space
context_partners
false
let rec compute_propagation lemmas_propositional lemma =
match lemma.abstraction.(lemma.watched1).abs_status, lemma.abstraction.(lemma.watched2).abs_status with
| True _, _
| _, True _ ->
()
| False _, Undetermined ->
let i =
find_watched_literal lemma.abstraction 0 lemma.watched2
in
if i = Array.length lemma.abstraction then begin
lemmas_propositional.propagations <-
(State.active_choice_point lemmas_propositional.state, lemma) :: lemmas_propositional.propagations;
ignore (lemmas_propositional.process_assert (compute_context_unifier lemma): bool)
end
else begin
unregister_watched_literal lemmas_propositional lemma.abstraction.(lemma.watched1) lemma;
lemma.watched1 <- i;
register_watched_literal lemmas_propositional lemma.abstraction.(lemma.watched1) lemma;
end
| Undetermined, False _ ->
let i =
find_watched_literal lemma.abstraction 0 lemma.watched1
in
if i = Array.length lemma.abstraction then begin
lemmas_propositional.propagations <-
(State.active_choice_point lemmas_propositional.state, lemma) :: lemmas_propositional.propagations;
ignore (lemmas_propositional.process_assert (compute_context_unifier lemma): bool)
end
else begin
unregister_watched_literal lemmas_propositional lemma.abstraction.(lemma.watched2) lemma;
lemma.watched2 <- i;
register_watched_literal lemmas_propositional lemma.abstraction.(lemma.watched2) lemma;
end
| False _, False _ ->
let i =
find_watched_literal lemma.abstraction 0 (-1)
in
if i = Array.length lemma.abstraction then begin
raise (Context_unifier.CLOSE (compute_context_unifier lemma))
end
else begin
unregister_watched_literal lemmas_propositional lemma.abstraction.(lemma.watched1) lemma;
lemma.watched1 <- i;
register_watched_literal lemmas_propositional lemma.abstraction.(lemma.watched1) lemma;
end;
compute_propagation lemmas_propositional lemma
| Undetermined, Undetermined ->
if Array.length lemma.abstraction = 1 then begin
lemmas_propositional.propagations <-
(State.active_choice_point lemmas_propositional.state, lemma) :: lemmas_propositional.propagations;
ignore (lemmas_propositional.process_assert (compute_context_unifier lemma): bool)
end
else begin
()
end
let add_lemma lemmas_propositional clause global =
let clause' =
Term.sort_clause (
List.map
(fun literal -> Subst.apply_to_literal Subst.empty literal 0)
clause
)
in
if filter_lemma lemmas_propositional clause' then begin
()
end
else begin
prune_lemmas lemmas_propositional;
let clause =
Term.request_skolemized_clause clause'
in
let abstraction =
List.fold_left
(fun acc literal ->
let literal =
Subst.apply_to_literal Subst.empty literal 0
in
try
let abstraction =
LiteralTable.find lemmas_propositional.literal_to_abstraction literal
in
Tools.list_add (==) acc abstraction
with
| Not_found ->
let status =
match Context.check_contradictory lemmas_propositional.context literal with
| None ->
Undetermined
| Some element ->
False element
in
let abstraction = {
abs_literal = literal;
abs_status = status;
}
in
LiteralTable.add lemmas_propositional.literal_to_abstraction literal abstraction;
(lemmas_propositional.subsumed#find literal)#add literal.Term.atom abstraction;
abstraction :: acc
)
[]
clause
in
let abstraction =
Array.of_list (List.rev abstraction)
in
let input_partners =
Array.mapi
(fun i abstraction ->
Context_unifier.create_input_partner
i
abstraction.abs_literal
[]
)
abstraction
in
let space =
Context_unifier.create_space
(Context_unifier_space.get_id lemmas_propositional.space_registry)
clause
[]
[]
[]
input_partners
[| |]
lemmas_propositional.process_close
lemmas_propositional.process_assert
(fun _ -> ())
(fun _ -> false)
(fun _ -> false)
true
in
let lemma = {
clause = clause;
space = space;
global = global;
abstraction = abstraction;
watched1 = 0;
watched2 = (-1);
}
in
if Array.length abstraction > 1 then begin
lemma.watched1 <- find_watched_literal abstraction 0 (-1);
lemma.watched2 <- find_watched_literal abstraction (lemma.watched1 + 1) lemma.watched1;
if lemma.watched1 == Array.length abstraction then begin
failwith "new lemma: all literals falsified"
end;
if lemma.watched2 = Array.length abstraction then begin
if lemma.watched1 = 0 then
lemma.watched2 <- 1
else
lemma.watched2 <- 0;
register_watched_literal lemmas_propositional lemma.abstraction.(lemma.watched1) lemma;
register_watched_literal lemmas_propositional lemma.abstraction.(lemma.watched2) lemma;
compute_propagation lemmas_propositional lemma;
end
else begin
register_watched_literal lemmas_propositional lemma.abstraction.(lemma.watched1) lemma;
register_watched_literal lemmas_propositional lemma.abstraction.(lemma.watched2) lemma;
end;
end
else begin
lemma.watched2 <- 0;
register_watched_literal lemmas_propositional lemma.abstraction.(lemma.watched1) lemma;
compute_propagation lemmas_propositional lemma;
end;
ClauseTable.add lemmas_propositional.lemmas clause' lemma;
()
end
let extend_context lemmas_propositional element =
let literal =
element.Context.el_literal
in
let contradictory =
(lemmas_propositional.subsumed#find (Term.request_negated_literal literal))#find_all_instances
~p_preserving:true literal.Term.atom
in
List.iter
(fun abstraction ->
match abstraction.abs_status with
| True _ ->
print_endline (Term.literal_to_string abstraction.abs_literal ^ " : True");
failwith "extend_context 1"
| False _ ->
()
| Undetermined ->
abstraction.abs_status <- False element;
begin
try
let lemmas =
AbstractionTable.find lemmas_propositional.abstraction_to_lemmas abstraction
in
LemmaTable.iter
(fun lemma _ -> compute_propagation lemmas_propositional lemma)
lemmas
with
| Not_found ->
()
end
)
contradictory;
let subsumed =
(lemmas_propositional.subsumed#find literal)#find_all_instances
~p_preserving:true literal.Term.atom
in
List.iter
(fun abstraction ->
match abstraction.abs_status with
| True _ ->
()
| False _ ->
failwith "extend_context 2"
| Undetermined ->
abstraction.abs_status <- True element;
)
subsumed;
()
let backtrack lemmas_propositional =
LiteralTable.iter
(fun _ abstraction ->
match abstraction.abs_status with
| True element
| False element when
State.is_choice_point_invalid element.Context.el_choice_point ->
abstraction.abs_status <- Undetermined
| _ ->
()
)
lemmas_propositional.literal_to_abstraction;
let keep, remove =
List.partition
(fun (cp, _) ->
if State.is_choice_point_valid cp then
true
else
false
)
lemmas_propositional.propagations
in
lemmas_propositional.propagations <- keep;
List.iter
(fun (_, lemma) ->
compute_propagation lemmas_propositional lemma
)
remove