package mc2

  1. Overview
  2. Docs

Source file Solver.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
(*
MSAT is free software, using the Apache license, see file LICENSE
Copyright 2016 Guillaume Bury
Copyright 2016 Simon Cruanes
*)

open Solver_types

module S = Internal

type proof = Proof.t
type nonrec atom = atom (** The type of atoms given by the module argument for formulas *)

type 'clause clause_sets = {
  cs_hyps: 'clause Vec.t;
  cs_history: 'clause Vec.t;
  cs_local: 'clause Vec.t;
}
(** Current state of the SAT solver *)

exception UndecidedLit = Internal.UndecidedLit
exception Out_of_space = Internal.Out_of_space
exception Out_of_time = Internal.Out_of_time

(** Main type *)
type t = Internal.t

type 'a state =
  | St_sat : t -> [`SAT] state
  | St_unsat : t -> [`UNSAT] state (* unsat conflict *)

let[@inline] state_solver (type a) (st: a state) : t = match st with
  | St_sat s -> s
  | St_unsat s -> s

let[@inline] plugins t = S.plugins t
let[@inline] get_service t k = S.get_service t k
let[@inline] get_service_exn t k = S.get_service_exn t k
let[@inline] services t = S.services t

let pp_all t lvl status =
  Log.debugf lvl
    (fun k -> k
        "@[<v>%s - Full summary:@,@[<hov 2>Trail:@\n%a@]@,@[<hov 2>Temp:@\n%a@]@,\
         @[<hov 2>Hyps:@\n%a@]@,@[<hov 2>Lemmas:@\n%a@]@,@]@."
        status
        (Vec.pp ~sep:"" Term.pp) (S.trail t)
        (Vec.pp ~sep:"" Clause.debug) (S.temp t)
        (Vec.pp ~sep:"" Clause.debug) (S.hyps t)
        (Vec.pp ~sep:"" Clause.debug) (S.history t))

(* Wrappers around internal functions*)
let assume = S.assume

let unsat_core _ p = Proof.unsat_core p

let true_at_level0 _s a =
  try
    let b, lev = S.eval_level a in
    b && lev = 0
  with S.UndecidedLit _ -> false

let add_term = S.add_term

let clause_sets (s:t) = {
  cs_hyps = S.hyps s;
  cs_history = S.history s;
  cs_local = S.temp s;
}

module Sat_state = struct
  type t = [`SAT] state

  let iter_trail (St_sat s) f = Vec.iter f (S.trail s)

  let[@inline] eval (St_sat _s) a = S.eval a
  let[@inline] eval_opt (St_sat _s) a = try Some (S.eval a) with UndecidedLit _ -> None
  let[@inline] eval_level (St_sat _s) a = S.eval_level a
  let model (St_sat s) = S.model s

  let check_model (s:t) : bool =
    let St_sat s = s in
    begin match S.check s with
      | Ok _ -> true
      | Error msg ->
        Log.debugf 0
          (fun k->k "(@[solver.check_model.fail:@ %a@])" Format.pp_print_text msg);
        false
    end
end

module Unsat_state = struct
  type t = [`UNSAT] state

  let unsat_conflict (St_unsat s) : clause =
    begin match S.unsat_conflict s with
      | None -> assert false
      | Some c -> c
    end

  let get_proof (s:t) =
    let c = unsat_conflict s in
    Proof.prove_unsat c
end

type res =
  | Sat of Sat_state.t (** Returned when the solver reaches SAT *)
  | Unsat of Unsat_state.t (** Returned when the solver reaches UNSAT *)
(** Result type for the solver *)

let solve ?gc ?restarts ?time ?memory ?(progress=false) ?(assumptions=[]) ?switch (s:t): res =
  try
    S.pop s;
    S.push s;
    S.local s assumptions;
    S.solve ?gc ?restarts ?time ?memory ~progress ?switch s;
    if progress then S.clear_progress();
    pp_all s 99 "SAT";
    Sat (St_sat s)
  with S.Unsat ->
    if progress then S.clear_progress();
    pp_all s 99 "UNSAT";
    Unsat (St_unsat s)

let create ~plugins () =
  let solver = S.create() in
  (* sort by increasing priority *)
  let plugins = List.sort Plugin.Factory.compare plugins in
  List.iter (fun p -> ignore (S.add_plugin solver p)) plugins;
  solver

let pp_stats = S.pp_stats
OCaml

Innovation. Community. Security.