diff options
author | filip <“filip.rabiega@gmail.com”> | 2024-08-16 14:11:00 +0200 |
---|---|---|
committer | filip <“filip.rabiega@gmail.com”> | 2024-08-16 14:11:00 +0200 |
commit | 69de932f9116b30adfd689d38e35ace63aef0e2d (patch) | |
tree | f7e8621889d313e70186ef255fcf04fe0d55d4c3 /lib/satisfiability/satisfiable.ml | |
parent | 2e893fd0df7dae8c4ae843d4a23acb098dd97aff (diff) | |
download | chadprover-69de932f9116b30adfd689d38e35ace63aef0e2d.tar.gz chadprover-69de932f9116b30adfd689d38e35ace63aef0e2d.tar.bz2 chadprover-69de932f9116b30adfd689d38e35ace63aef0e2d.zip |
Diffstat (limited to 'lib/satisfiability/satisfiable.ml')
-rw-r--r-- | lib/satisfiability/satisfiable.ml | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/lib/satisfiability/satisfiable.ml b/lib/satisfiability/satisfiable.ml new file mode 100644 index 0000000..6eccc27 --- /dev/null +++ b/lib/satisfiability/satisfiable.ml @@ -0,0 +1,74 @@ +(* Find a satisfying interpretation via brute force *) + +open Types +open Lib_utils + +(* lazy list *) +type 'a seq = Nil | Cons of 'a * (unit -> 'a seq) + +let head = function + | Nil -> None + | Cons(x, _) -> Some x + +let tail = function + | Nil -> None + | Cons(_, tl) -> Some tl + +let rec get k s = + match k, s with + | 0, _ -> [] + | _, Nil -> [] + | k, Cons(x, f) -> x :: get (k - 1) (f ()) + +(* Find all the literals in a formula *) +let extract_symbols (prop : proposition) = + let rec search prop acc = + match prop with + | True -> acc + | False -> acc + | Lit s -> Lit s :: acc + | Not p -> search p acc + | And(p1, p2) -> search p1 (search p2 acc) + | Or(p1, p2) -> search p1 (search p2 acc) + | Implies(p1, p2) -> search p1 (search p2 acc) + | Iff(p1, p2) -> search p1 (search p2 acc) + in + search prop [] + +(* Generate all possible truth assignments for a list of symbols *) +let rec generate_truth_vals symbols = + let rec prepend_all x llist = (* prepend x to each item in the lazy list *) + match llist with + | Nil -> Nil + | Cons(xs, fn) -> Cons(x::xs, fun () -> prepend_all x (fn ())) + in + let rec interleave s1 s2 = + match s1, s2 with + | _, Nil -> s1 + | Nil, _ -> s2 + | Cons(x1, f1), _ -> Cons(x1, fun () -> interleave s2 (f1 ())) + in + match symbols with + | [] -> Cons ([], fun () -> Nil) + | Lit s :: tl -> + let tl_vals = generate_truth_vals tl in + let s_true = prepend_all (s, true) tl_vals in + let s_false = prepend_all (s, false) tl_vals in + interleave s_true s_false + | _ -> failwith "discovered a bug" + +(* brute force search for a satisfying interpretation *) +let satisfy prop = + let symbols = extract_symbols prop in + let truth_vals = generate_truth_vals symbols in + let rec try_next truth_vals = + match truth_vals with + | Nil -> None + | Cons(i, f) -> + begin + match test_interpretation prop i with + | Some true -> Some i + | _ -> try_next (f ()) + end + in + try_next truth_vals |