├── .github └── workflows │ ├── gh-pages.yml │ └── main.yml ├── .gitignore ├── .ocamlformat ├── CHANGELOG.md ├── LICENSE ├── Makefile ├── README.md ├── dune-project ├── examples └── icnf-solve │ ├── dune │ ├── icnf_solve.ml │ └── lexer.mll ├── minisat.opam ├── src ├── .clangd ├── Solver.cc ├── dune ├── libminisat_stubs.cpp ├── minisat-cpp │ ├── LICENSE │ ├── README │ ├── core │ │ ├── .clangd │ │ ├── Dimacs.h │ │ ├── Main.cc │ │ ├── Makefile │ │ ├── Solver.cc │ │ ├── Solver.h │ │ ├── SolverTypes.h │ │ └── depend.mk │ ├── doc │ │ └── ReleaseNotes-2.2.0.txt │ ├── mtl │ │ ├── .clangd │ │ ├── Alg.h │ │ ├── Alloc.h │ │ ├── Heap.h │ │ ├── IntTypes.h │ │ ├── Map.h │ │ ├── Queue.h │ │ ├── Vec.h │ │ ├── XAlloc.h │ │ ├── config.mk │ │ └── template.mk │ ├── simp │ │ ├── Main.cc │ │ ├── Makefile │ │ ├── SimpSolver.cc │ │ └── SimpSolver.h │ └── utils │ │ ├── .clangd │ │ ├── Makefile │ │ ├── Options.cc │ │ ├── Options.h │ │ ├── ParseUtils.h │ │ ├── System.cc │ │ └── System.h ├── minisat.ml └── minisat.mli └── tests ├── dune ├── icnf ├── dune ├── regression1.icnf ├── regression1.icnf.expected ├── regression2.icnf └── regression2.icnf.expected ├── phole.ml └── test1.ml /.github/workflows/gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: github pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - master # Set a branch name to trigger deployment 7 | 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | 14 | - name: Cache opam 15 | id: cache-opam 16 | uses: actions/cache@v2 17 | with: 18 | path: ~/.opam 19 | key: opam-ubuntu-latest-4.12.0 20 | 21 | - uses: ocaml/setup-ocaml@v2 22 | with: 23 | ocaml-compiler: '4.14.x' 24 | 25 | - name: Pin 26 | run: opam pin -n . 27 | 28 | - name: Depext 29 | run: opam depext -yt minisat 30 | 31 | - name: Deps 32 | run: opam install -d . --deps-only 33 | 34 | - name: Build 35 | run: opam exec -- dune build @doc 36 | 37 | - name: Deploy 38 | uses: peaceiris/actions-gh-pages@v3 39 | with: 40 | github_token: ${{ secrets.GITHUB_TOKEN }} 41 | publish_dir: ./_build/default/_doc/_html/ 42 | destination_dir: . 43 | enable_jekyll: true 44 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - main 7 | jobs: 8 | run: 9 | name: Build 10 | strategy: 11 | matrix: 12 | os: 13 | - macos-latest 14 | - ubuntu-latest 15 | #- windows-latest 16 | ocaml-compiler: 17 | - '4.03.x' 18 | - '4.14.x' 19 | - '5.1.x' 20 | exclude: 21 | - os: macos-latest 22 | ocaml-compiler: '4.03.x' 23 | runs-on: ${{ matrix.os }} 24 | steps: 25 | - uses: actions/checkout@v2 26 | - uses: ocaml/setup-ocaml@v2 27 | with: 28 | ocaml-compiler: ${{ matrix.ocaml-compiler }} 29 | allow-prerelease-opam: true 30 | - run: opam pin -n . 31 | - run: opam depext -yt minisat 32 | - run: opam install -t . --deps-only 33 | - run: opam exec -- dune build 34 | - run: opam exec -- dune runtest 35 | if: ${{ matrix.os == 'ubuntu-latest'}} 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .*.swp 2 | .*.swo 3 | _build 4 | *.native 5 | *.byte 6 | .session 7 | TAGS 8 | *.docdir 9 | setup.* 10 | qtest* 11 | *.html 12 | .merlin 13 | *.install 14 | -------------------------------------------------------------------------------- /.ocamlformat: -------------------------------------------------------------------------------- 1 | version = 0.24.1 2 | profile=conventional 3 | margin=80 4 | if-then-else=k-r 5 | parens-ite=true 6 | parens-tuple=multi-line-only 7 | sequence-style=terminator 8 | type-decl=sparse 9 | break-cases=toplevel 10 | cases-exp-indent=2 11 | field-space=tight-decl 12 | leading-nested-match-parens=true 13 | module-item-spacing=compact 14 | quiet=true 15 | ocaml-version=4.08.0 16 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.6 2 | 3 | - migrate from minisat-c 1.14 to minisat 2.2 (in C++); refactor it to build with C++11 4 | 5 | - add `Lit.{apply_sign,hash,equal,compare}` 6 | - add `ensure_lit_exists` 7 | - do not call `simplify` implicitly before `solve` 8 | - add `value_at_level_0` 9 | - add `unsat_core` 10 | - add `okay` 11 | 12 | ## 0.5 13 | 14 | - format C and OCaml code 15 | - add `pp_value` and `string_of_value` 16 | 17 | ## 0.4 18 | 19 | - move to github actions for CI 20 | - perf: release runtime lock in `solve` 21 | - perf: fast path for `add_clause` 22 | - perf: annotate some C functions as `noalloc` 23 | 24 | ## 0.3 25 | 26 | - fixes: 27 | * return code of caml_minisat_value 28 | * fallthrough comment 29 | * pointer cast 30 | - update travis file to add 4.09 31 | - only ask for dune 1.0 32 | 33 | ## 0.2 34 | 35 | - migrate to `dune` for build 36 | - upgrades to the CI 37 | 38 | ## 0.1 39 | 40 | - Edits for continous integration: 41 | * removed symlinks of `src/solver.h`, `src/solver.c`, `src/vec.c` 42 | and replaced them by the actual files; I did that because 43 | in cygwin, ocamlc wouldn't find solver.h in `#include "solver.h"`. 44 | I might be mistaken but it's the only thing I found to avoid the 45 | problem... 46 | * modified the uint64 typedef that was causing issues in cygwin+ocamlc. 47 | In fact, the `#ifdef _WIN32` wasn't proper for cygwin builds; 48 | plus, the `uint64` isn't standard, changed to `uint64_t`. 49 | See the SO topic here: http://stackoverflow.com/questions/126279 50 | 51 | - initial release 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Simon Cruanes 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. Redistributions in binary 9 | form must reproduce the above copyright notice, this list of conditions and 10 | the following disclaimer in the documentation and/or other materials 11 | provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 19 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 20 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 21 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | DUNE_OPTS=--profile=release 3 | 4 | build: 5 | @dune build $(DUNE_OPTS) 6 | 7 | clean: 8 | @dune clean 9 | 10 | doc: 11 | @dune build @doc 12 | 13 | test: 14 | @dune runtest --force --no-buffer 15 | 16 | WATCH?="@all" 17 | watch: 18 | @dune build $(WATCH) $(DUNE_OPTS) -w 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Minisat [![Build](https://github.com/c-cube/ocaml-minisat/actions/workflows/main.yml/badge.svg)](https://github.com/c-cube/ocaml-minisat/actions/workflows/main.yml) 2 | 3 | Bindings to the SAT solver [Minisat](http://minisat.se/) 2.2, with the solver included. 4 | 5 | ## Docs 6 | 7 | See https://c-cube.github.io/ocaml-minisat/ 8 | -------------------------------------------------------------------------------- /dune-project: -------------------------------------------------------------------------------- 1 | (lang dune 2.0) 2 | (name minisat) 3 | -------------------------------------------------------------------------------- /examples/icnf-solve/dune: -------------------------------------------------------------------------------- 1 | (executable 2 | (name icnf_solve) 3 | (modes native) 4 | (libraries containers minisat)) 5 | 6 | (ocamllex (modules lexer)) 7 | -------------------------------------------------------------------------------- /examples/icnf-solve/icnf_solve.ml: -------------------------------------------------------------------------------- 1 | module Vec = CCVector 2 | 3 | module Parse : sig 4 | type 'a event = 5 | | Add_clause of 'a array 6 | | Solve of 'a array 7 | 8 | type 'a t 9 | 10 | val make : file:string -> (int -> 'a) -> 'a t 11 | 12 | val next : 'a t -> 'a event 13 | (** @raise End_of_file when done *) 14 | end = struct 15 | module L = Lexer 16 | 17 | type 'a event = 18 | | Add_clause of 'a array 19 | | Solve of 'a array 20 | 21 | type 'a t = { 22 | mk: int -> 'a; 23 | vec: 'a Vec.vector; 24 | lex: Lexing.lexbuf; 25 | } 26 | 27 | let make ~file mk : _ t = 28 | let ic = open_in file in 29 | let lex = Lexing.from_channel ic in 30 | at_exit (fun () -> close_in_noerr ic); 31 | { lex; vec = Vec.create (); mk } 32 | 33 | let rec next (self : _ t) : _ event = 34 | match L.token self.lex with 35 | | L.EOF -> raise End_of_file 36 | | L.A -> 37 | let c = read_ints self in 38 | Solve c 39 | | L.I 0 -> Add_clause [||] 40 | | L.I x -> 41 | let c = read_ints ~first:(self.mk x) self in 42 | Add_clause c 43 | 44 | and read_ints ?first self : _ array = 45 | Vec.clear self.vec; 46 | (* reuse local vec *) 47 | CCOption.iter (Vec.push self.vec) first; 48 | let rec aux () = 49 | match L.token self.lex with 50 | | L.I 0 -> Vec.to_array self.vec (* done *) 51 | | L.I n -> 52 | let x = self.mk n in 53 | Vec.push self.vec x; 54 | aux () 55 | | L.A -> failwith "unexpected \"a\"" 56 | | L.EOF -> failwith "unexpected end of file" 57 | in 58 | aux () 59 | end 60 | 61 | module Solver = struct 62 | type 'lit internal = { 63 | mklit: int -> 'lit; 64 | to_int: 'lit -> int; 65 | add_clause: 'lit array -> bool; 66 | solve: 'lit array -> bool; 67 | unsat_core: unit -> 'lit array; 68 | } 69 | 70 | type t = Solver : 'lit internal -> t 71 | 72 | type builder = { 73 | name: string; 74 | make: unit -> t; 75 | } 76 | 77 | let mk_minisat : builder = 78 | { 79 | name = "minisat"; 80 | make = 81 | (fun () -> 82 | let module S = Minisat in 83 | let s = S.create () in 84 | let mklit i = 85 | let v = S.Lit.make (abs i) in 86 | if i > 0 then 87 | v 88 | else 89 | S.Lit.neg v 90 | in 91 | let add_clause c = 92 | try 93 | S.add_clause_a s c; 94 | true 95 | with S.Unsat -> false 96 | in 97 | let solve ass = 98 | try 99 | S.solve ~assumptions:ass s; 100 | true 101 | with S.Unsat -> false 102 | in 103 | let unsat_core () = S.unsat_core s in 104 | let to_int i = 105 | S.Lit.to_int (S.Lit.abs i) 106 | * 107 | if S.Lit.sign i then 108 | 1 109 | else 110 | -1 111 | in 112 | Solver { add_clause; unsat_core; solve; mklit; to_int }); 113 | } 114 | 115 | let name b = b.name 116 | let all = [ mk_minisat ] 117 | end 118 | 119 | let solve_with_solver ~debug solver file : unit = 120 | Printf.printf "c process %S with %s\n" file solver.Solver.name; 121 | let (Solver.Solver s) = solver.Solver.make () in 122 | let pp_arr out a = 123 | Array.iter (fun lit -> Printf.fprintf out "%d " (s.Solver.to_int lit)) a 124 | in 125 | let p = Parse.make ~file s.mklit in 126 | let rec process_problem () = 127 | match Parse.next p with 128 | | Parse.Add_clause c -> 129 | if debug then Printf.printf "add_clause %a\n%!" pp_arr c; 130 | let r = s.Solver.add_clause c in 131 | if r then 132 | process_problem () 133 | else ( 134 | Printf.printf "UNSAT\n%!"; 135 | skip_problem () 136 | ) 137 | | Parse.Solve assumptions -> 138 | if debug then Printf.printf "c solve %a\n%!" pp_arr assumptions; 139 | let r = s.Solver.solve assumptions in 140 | Printf.printf "%s\n%!" 141 | (if r then 142 | "SAT" 143 | else 144 | "UNSAT"); 145 | 146 | if not r then ( 147 | let core = s.Solver.unsat_core () in 148 | if debug then Printf.printf "unsat core %a\n%!" pp_arr core; 149 | 150 | (* core must be subset of assumptions *) 151 | assert ( 152 | Array.for_all 153 | (fun l -> Array.exists (fun l2 -> l = l2) assumptions) 154 | core); 155 | 156 | let r2 = s.Solver.solve core in 157 | if debug then 158 | Printf.printf "solving with only core: %s\n%!" 159 | (if r2 then 160 | "SAT" 161 | else 162 | "UNSAT"); 163 | assert (not r2) 164 | ); 165 | 166 | (* next problem! *) 167 | process_problem () 168 | | exception End_of_file -> done_ () 169 | and skip_problem () = 170 | match Parse.next p with 171 | | Parse.Add_clause _ -> skip_problem () 172 | | Parse.Solve _ -> process_problem () 173 | | exception End_of_file -> done_ () 174 | and done_ () = 175 | Printf.printf "c done for %S with %s\n%!" file solver.name; 176 | () 177 | in 178 | process_problem () 179 | 180 | let solve_with_file ~debug solvers file : unit = 181 | List.iter 182 | (fun s -> 183 | try solve_with_solver ~debug s file 184 | with e -> 185 | Printf.printf "error while solving %S with %s:\n%s" file s.Solver.name 186 | (Printexc.to_string e); 187 | exit 1) 188 | solvers 189 | 190 | let () = 191 | let solvers = ref [] in 192 | let files = ref [] in 193 | let debug = ref false in 194 | let opt_s = 195 | Arg.Symbol 196 | ( List.map Solver.name Solver.all, 197 | fun s -> 198 | solvers := Solver.(List.find (fun b -> b.name = s) all) :: !solvers ) 199 | in 200 | let opts = 201 | [ 202 | "-d", Arg.Set debug, " debug"; 203 | "--solver", opt_s, " use given solver"; 204 | "-s", opt_s, " alias to --solver"; 205 | ] 206 | |> Arg.align 207 | in 208 | Arg.parse opts (fun f -> files := f :: !files) "icnf_solve [options] "; 209 | if !solvers = [] then solvers := [ Solver.mk_minisat ]; 210 | (* default *) 211 | List.iter (fun f -> solve_with_file ~debug:!debug !solvers f) !files; 212 | () 213 | -------------------------------------------------------------------------------- /examples/icnf-solve/lexer.mll: -------------------------------------------------------------------------------- 1 | 2 | { 3 | type token = A | I of int | EOF 4 | } 5 | 6 | let space = [' ' '\t'] 7 | let nat = (['0'-'9'])+ 8 | let int = ('-' nat) | nat 9 | 10 | rule token = parse 11 | | '\n' { Lexing.new_line lexbuf; token lexbuf } 12 | | space { token lexbuf } 13 | | 'c' { skip_line lexbuf } 14 | | 'p' { skip_line lexbuf } 15 | | int { let i = int_of_string (Lexing.lexeme lexbuf) in I i } 16 | | 'a' { A } 17 | | eof { EOF } 18 | | _ as c 19 | { 20 | let msg = Printf.sprintf "lexer fails on char %c\n" c in 21 | failwith msg 22 | } 23 | 24 | and skip_line = parse 25 | | '\n' { Lexing.new_line lexbuf; token lexbuf } 26 | | eof { EOF } 27 | | _ { skip_line lexbuf } 28 | 29 | -------------------------------------------------------------------------------- /minisat.opam: -------------------------------------------------------------------------------- 1 | opam-version: "2.0" 2 | version: "0.6" 3 | author: "simon.cruanes.2007@m4x.org" 4 | maintainer: "simon.cruanes.2007@m4x.org" 5 | synopsis: "Bindings to the SAT solver Minisat, with the solver included." 6 | build: [ 7 | ["dune" "build" "-p" name "-j" jobs] 8 | ["dune" "runtest" "-p" name "-j" jobs] {with-test} 9 | ["dune" "build" "@doc" "-p" name "-j" jobs] {with-doc} 10 | ] 11 | license: "BSD-2-clause" 12 | depends: [ 13 | "ocaml" {>= "4.03" } 14 | "dune" {>= "2.0"} 15 | "odoc" {with-doc} 16 | "containers" {>= "3.0" & with-test} 17 | ] 18 | tags: [ "minisat" "solver" "SAT" ] 19 | homepage: "https://github.com/c-cube/ocaml-minisat/" 20 | dev-repo: "git+https://github.com/c-cube/ocaml-minisat.git" 21 | bug-reports: "https://github.com/c-cube/ocaml-minisat/issues" 22 | -------------------------------------------------------------------------------- /src/.clangd: -------------------------------------------------------------------------------- 1 | 2 | 3 | CompileFlags: 4 | Add: [--std=c++11, 5 | -I, minisat-cpp, 6 | -I, minisat-cpp/core, 7 | -I, minisat-cpp/utils, 8 | -I, minisat-cpp/mtl, 9 | -I, /usr/lib/ocaml/] 10 | -------------------------------------------------------------------------------- /src/Solver.cc: -------------------------------------------------------------------------------- 1 | minisat-cpp/core/Solver.cc -------------------------------------------------------------------------------- /src/dune: -------------------------------------------------------------------------------- 1 | 2 | (library 3 | (name minisat) 4 | (public_name minisat) 5 | (flags :standard -safe-string -warn-error -a+8 -w +a-4-40) 6 | (c_library_flags :standard -lstdc++) 7 | (foreign_stubs 8 | (language cxx) 9 | ;(ocamlopt_flags :standard -O3 -bin-annot -unbox-closures -unbox-closures-factor 20) 10 | (include_dirs minisat-cpp/ minisat-cpp/mtl minisat-cpp/core) 11 | (flags :standard -fPIC -std=c++11) 12 | (names libminisat_stubs Solver))) 13 | -------------------------------------------------------------------------------- /src/libminisat_stubs.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "assert.h" 9 | #include "core/Solver.h" 10 | #include "core/SolverTypes.h" 11 | #include "mtl/Vec.h" 12 | #include "stdlib.h" 13 | #include "string.h" 14 | 15 | using namespace Minisat; 16 | 17 | /// Make sure `lit` is valid inside the solver. 18 | void ensureVar(Solver &s, Lit lit) { 19 | Var v = Minisat::var(lit); 20 | while (v >= s.nVars()) { 21 | s.newVar(true, true); 22 | } 23 | } 24 | 25 | extern "C" { 26 | 27 | CAMLprim value caml_minisat_new(value unit) { 28 | CAMLparam0(); 29 | CAMLlocal1(block); 30 | 31 | Solver *s = new Solver(); 32 | 33 | // allocate a block to store the pointer 34 | block = caml_alloc_small(sizeof(Solver *), Abstract_tag); 35 | *((Solver **)(Data_custom_val(block))) = s; 36 | 37 | CAMLreturn(block); 38 | } 39 | 40 | // fast access to the solver 41 | static inline Solver *get_solver(value block) { 42 | Solver *s = *((Solver **)Data_custom_val(block)); 43 | return s; 44 | } 45 | 46 | CAMLprim value caml_minisat_delete(value block) { 47 | CAMLparam1(block); 48 | Solver *s; 49 | 50 | // already cleaned? 51 | if (*((Solver **)(Data_custom_val(block))) == 0) { 52 | goto exit; 53 | } 54 | 55 | s = get_solver(block); 56 | delete s; 57 | 58 | // clear block content 59 | memset(Data_custom_val(block), 0, sizeof(Solver *)); 60 | 61 | exit: 62 | CAMLreturn(Val_unit); 63 | } 64 | 65 | CAMLprim value caml_minisat_simplify(value block) { 66 | CAMLparam1(block); 67 | 68 | Solver *s = get_solver(block); 69 | bool res = s->simplify(); 70 | 71 | CAMLreturn(Val_bool(res)); 72 | } 73 | 74 | // we now directly use the minisat convention! 75 | static inline Lit lit_of_int(int i) { return Minisat::toLit(i); } 76 | 77 | CAMLprim value caml_minisat_solve(value block, value v_lits) { 78 | CAMLparam2(block, v_lits); 79 | 80 | // build an array out of [v_lits] 81 | size_t lits_size = Wosize_val(v_lits); 82 | 83 | vec lits; 84 | lits.capacity(lits_size); 85 | Solver *s = get_solver(block); 86 | 87 | for (size_t i = 0; i < lits_size; ++i) { 88 | Lit lit = lit_of_int(Int_val(Field(v_lits, i))); 89 | ensureVar(*s, lit); 90 | lits.push(lit); 91 | } 92 | 93 | // solve 94 | caml_release_runtime_system(); 95 | bool res = s->solve(lits); 96 | caml_acquire_runtime_system(); 97 | 98 | CAMLreturn(Val_bool(res)); 99 | } 100 | 101 | CAMLprim value caml_minisat_ensure_var(value block, value v_lit) { 102 | CAMLparam2(block, v_lit); 103 | 104 | Solver *s = get_solver(block); 105 | Lit lit = lit_of_int(Int_val(v_lit)); 106 | ensureVar(*s, lit); 107 | CAMLreturn(Val_unit); 108 | } 109 | 110 | CAMLprim value caml_minisat_add_clause_a(value block, value v_lits) { 111 | CAMLparam2(block, v_lits); 112 | 113 | // build an array out of [v_lits] 114 | size_t lits_size = Wosize_val(v_lits); 115 | 116 | Solver *s = get_solver(block); 117 | 118 | vec lits; 119 | lits.capacity(lits_size); 120 | for (size_t i = 0; i < lits_size; ++i) { 121 | Lit lit = lit_of_int(Int_val(Field(v_lits, i))); 122 | ensureVar(*s, lit); 123 | lits.push(lit); 124 | } 125 | 126 | bool res = s->addClause(lits); 127 | 128 | CAMLreturn(Val_bool(res)); 129 | } 130 | 131 | // convert lbool to int 132 | inline int convert_value(lbool cur_val) { 133 | if (cur_val == l_Undef) 134 | return 0; 135 | else if (cur_val == l_True) 136 | return 1; 137 | else if (cur_val == l_False) 138 | return -1; 139 | else 140 | return -2; 141 | 142 | } 143 | 144 | CAMLprim value caml_minisat_value(value block, value v_lit) { 145 | CAMLparam2(block, v_lit); 146 | 147 | Solver *s = get_solver(block); 148 | 149 | Lit lit = lit_of_int(Int_val(v_lit)); 150 | int var = Minisat::var(lit); 151 | lbool cur_val = var > s->nVars() ? l_Undef : s->modelValue(lit); 152 | 153 | int ret = convert_value(cur_val); 154 | CAMLreturn(Val_int(ret)); 155 | } 156 | 157 | CAMLprim value caml_minisat_value_level_0(value block, value v_lit) { 158 | CAMLparam2(block, v_lit); 159 | 160 | Solver *s = get_solver(block); 161 | 162 | Lit lit = lit_of_int(Int_val(v_lit)); 163 | int var = Minisat::var(lit); 164 | int level = var > s->nVars() ? 0 : s->level(var); 165 | lbool cur_val = (var > s->nVars() || level != 0) ? l_Undef : s->value(lit); 166 | int res = convert_value(cur_val); 167 | 168 | CAMLreturn(Val_int(res)); 169 | } 170 | 171 | CAMLprim value caml_minisat_core(value block) { 172 | CAMLparam1(block); 173 | CAMLlocal1(res); 174 | 175 | Solver *s = get_solver(block); 176 | 177 | vec &conflict = s->conflict; 178 | res = caml_alloc(conflict.size(), 0 /* tag for array */); 179 | 180 | for (int i = 0; i < conflict.size(); ++i) { 181 | Lit lit = ~conflict[i]; // we want the core, not conflict 182 | Store_field(res, i, Val_int(Minisat::toInt(lit))); 183 | } 184 | 185 | CAMLreturn(res); 186 | } 187 | 188 | CAMLprim value caml_minisat_set_verbose(value block, value v_lev) { 189 | CAMLparam2(block, v_lev); 190 | 191 | int lev = Int_val(v_lev); 192 | 193 | Solver *s = get_solver(block); 194 | s->verbosity = lev; 195 | 196 | CAMLreturn(Val_unit); 197 | } 198 | 199 | CAMLprim value caml_minisat_okay(value block) { 200 | CAMLparam1(block); 201 | 202 | Solver *s = get_solver(block); 203 | CAMLreturn(Val_bool(s->okay())); 204 | } 205 | 206 | CAMLprim value caml_minisat_to_dimacs(value block, value path) { 207 | CAMLparam2(block, path); 208 | 209 | Solver *s = get_solver(block); 210 | char const *file = String_val(path); 211 | 212 | s->toDimacs(file); 213 | 214 | CAMLreturn(Val_unit); 215 | } 216 | 217 | CAMLprim value caml_minisat_nvars(value block) { 218 | CAMLparam1(block); 219 | 220 | Solver *s = get_solver(block); 221 | CAMLreturn(Val_int(s->nVars())); 222 | } 223 | 224 | CAMLprim value caml_minisat_nclauses(value block) { 225 | CAMLparam1(block); 226 | 227 | Solver *s = get_solver(block); 228 | CAMLreturn(Val_int(s->nClauses())); 229 | } 230 | 231 | CAMLprim value caml_minisat_nconflicts(value block) { 232 | CAMLparam1(block); 233 | 234 | Solver *s = get_solver(block); 235 | CAMLreturn(Val_int(s->nLearnts())); 236 | } 237 | 238 | CAMLprim value caml_minisat_interrupt(value block) { 239 | CAMLparam1(block); 240 | Solver *s = get_solver(block); 241 | s->interrupt(); 242 | CAMLreturn(Val_unit); 243 | } 244 | 245 | 246 | CAMLprim value caml_minisat_clear_interrupt(value block) { 247 | CAMLparam1(block); 248 | Solver *s = get_solver(block); 249 | s->clearInterrupt(); 250 | CAMLreturn(Val_unit); 251 | } 252 | 253 | } // extern "C" 254 | -------------------------------------------------------------------------------- /src/minisat-cpp/LICENSE: -------------------------------------------------------------------------------- 1 | MiniSat -- Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 2 | Copyright (c) 2007-2010 Niklas Sorensson 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a 5 | copy of this software and associated documentation files (the 6 | "Software"), to deal in the Software without restriction, including 7 | without limitation the rights to use, copy, modify, merge, publish, 8 | distribute, sublicense, and/or sell copies of the Software, and to 9 | permit persons to whom the Software is furnished to do so, subject to 10 | the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included 13 | in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 19 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 20 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 21 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/minisat-cpp/README: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | DIRECTORY OVERVIEW: 3 | 4 | mtl/ Mini Template Library 5 | utils/ Generic helper code (I/O, Parsing, CPU-time, etc) 6 | core/ A core version of the solver 7 | simp/ An extended solver with simplification capabilities 8 | README 9 | LICENSE 10 | 11 | ================================================================================ 12 | BUILDING: (release version: without assertions, statically linked, etc) 13 | 14 | export MROOT= (or setenv in cshell) 15 | cd { core | simp } 16 | gmake rs 17 | cp minisat_static /minisat 18 | 19 | ================================================================================ 20 | EXAMPLES: 21 | 22 | Run minisat with same heuristics as version 2.0: 23 | 24 | > minisat -no-luby -rinc=1.5 -phase-saving=0 -rnd-freq=0.02 25 | -------------------------------------------------------------------------------- /src/minisat-cpp/core/.clangd: -------------------------------------------------------------------------------- 1 | 2 | CompileFlags: 3 | Add: [--std=c++11, -I, ..] 4 | -------------------------------------------------------------------------------- /src/minisat-cpp/core/Dimacs.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************************[Dimacs.h] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_Dimacs_h 22 | #define Minisat_Dimacs_h 23 | 24 | #include 25 | 26 | #include "utils/ParseUtils.h" 27 | #include "core/SolverTypes.h" 28 | 29 | namespace Minisat { 30 | 31 | //================================================================================================= 32 | // DIMACS Parser: 33 | 34 | template 35 | static void readClause(B& in, Solver& S, vec& lits) { 36 | int parsed_lit, var; 37 | lits.clear(); 38 | for (;;){ 39 | parsed_lit = parseInt(in); 40 | if (parsed_lit == 0) break; 41 | var = abs(parsed_lit)-1; 42 | while (var >= S.nVars()) S.newVar(); 43 | lits.push( (parsed_lit > 0) ? mkLit(var) : ~mkLit(var) ); 44 | } 45 | } 46 | 47 | template 48 | static void parse_DIMACS_main(B& in, Solver& S) { 49 | vec lits; 50 | int vars = 0; 51 | int clauses = 0; 52 | int cnt = 0; 53 | for (;;){ 54 | skipWhitespace(in); 55 | if (*in == EOF) break; 56 | else if (*in == 'p'){ 57 | if (eagerMatch(in, "p cnf")){ 58 | vars = parseInt(in); 59 | clauses = parseInt(in); 60 | // SATRACE'06 hack 61 | // if (clauses > 4000000) 62 | // S.eliminate(true); 63 | }else{ 64 | printf("PARSE ERROR! Unexpected char: %c\n", *in), exit(3); 65 | } 66 | } else if (*in == 'c' || *in == 'p') 67 | skipLine(in); 68 | else{ 69 | cnt++; 70 | readClause(in, S, lits); 71 | S.addClause_(lits); } 72 | } 73 | if (vars != S.nVars()) 74 | fprintf(stderr, "WARNING! DIMACS header mismatch: wrong number of variables.\n"); 75 | if (cnt != clauses) 76 | fprintf(stderr, "WARNING! DIMACS header mismatch: wrong number of clauses.\n"); 77 | } 78 | 79 | // Inserts problem into solver. 80 | // 81 | template 82 | static void parse_DIMACS(gzFile input_stream, Solver& S) { 83 | StreamBuffer in(input_stream); 84 | parse_DIMACS_main(in, S); } 85 | 86 | //================================================================================================= 87 | } 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /src/minisat-cpp/core/Main.cc: -------------------------------------------------------------------------------- 1 | /*****************************************************************************************[Main.cc] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | 26 | #include "utils/System.h" 27 | #include "utils/ParseUtils.h" 28 | #include "utils/Options.h" 29 | #include "core/Dimacs.h" 30 | #include "core/Solver.h" 31 | 32 | using namespace Minisat; 33 | 34 | //================================================================================================= 35 | 36 | 37 | void printStats(Solver& solver) 38 | { 39 | double cpu_time = cpuTime(); 40 | double mem_used = memUsedPeak(); 41 | printf("restarts : %ld\n", solver.starts); 42 | printf("conflicts : %-12lu (%.0f /sec)\n", solver.conflicts , solver.conflicts /cpu_time); 43 | printf("decisions : %-12lu (%4.2f %% random) (%.0f /sec)\n", solver.decisions, (float)solver.rnd_decisions*100 / (float)solver.decisions, solver.decisions /cpu_time); 44 | printf("propagations : %-12lu (%.0f /sec)\n", solver.propagations, solver.propagations/cpu_time); 45 | printf("conflict literals : %-12lu (%4.2f %% deleted)\n", solver.tot_literals, (solver.max_literals - solver.tot_literals)*100 / (double)solver.max_literals); 46 | if (mem_used != 0) printf("Memory used : %.2f MB\n", mem_used); 47 | printf("CPU time : %g s\n", cpu_time); 48 | } 49 | 50 | 51 | static Solver* solver; 52 | // Terminate by notifying the solver and back out gracefully. This is mainly to have a test-case 53 | // for this feature of the Solver as it may take longer than an immediate call to '_exit()'. 54 | static void SIGINT_interrupt(int signum) { solver->interrupt(); } 55 | 56 | // Note that '_exit()' rather than 'exit()' has to be used. The reason is that 'exit()' calls 57 | // destructors and may cause deadlocks if a malloc/free function happens to be running (these 58 | // functions are guarded by locks for multithreaded use). 59 | static void SIGINT_exit(int signum) { 60 | printf("\n"); printf("*** INTERRUPTED ***\n"); 61 | if (solver->verbosity > 0){ 62 | printStats(*solver); 63 | printf("\n"); printf("*** INTERRUPTED ***\n"); } 64 | _exit(1); } 65 | 66 | 67 | //================================================================================================= 68 | // Main: 69 | 70 | 71 | int main(int argc, char** argv) 72 | { 73 | try { 74 | setUsageHelp("USAGE: %s [options] \n\n where input may be either in plain or gzipped DIMACS.\n"); 75 | // printf("This is MiniSat 2.0 beta\n"); 76 | 77 | #if defined(__linux__) 78 | fpu_control_t oldcw, newcw; 79 | _FPU_GETCW(oldcw); newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE; _FPU_SETCW(newcw); 80 | printf("WARNING: for repeatability, setting FPU to use double precision\n"); 81 | #endif 82 | // Extra options: 83 | // 84 | IntOption verb ("MAIN", "verb", "Verbosity level (0=silent, 1=some, 2=more).", 1, IntRange(0, 2)); 85 | IntOption cpu_lim("MAIN", "cpu-lim","Limit on CPU time allowed in seconds.\n", INT32_MAX, IntRange(0, INT32_MAX)); 86 | IntOption mem_lim("MAIN", "mem-lim","Limit on memory usage in megabytes.\n", INT32_MAX, IntRange(0, INT32_MAX)); 87 | 88 | parseOptions(argc, argv, true); 89 | 90 | Solver S; 91 | double initial_time = cpuTime(); 92 | 93 | S.verbosity = verb; 94 | 95 | solver = &S; 96 | // Use signal handlers that forcibly quit until the solver will be able to respond to 97 | // interrupts: 98 | signal(SIGINT, SIGINT_exit); 99 | signal(SIGXCPU,SIGINT_exit); 100 | 101 | // Set limit on CPU-time: 102 | if (cpu_lim != INT32_MAX){ 103 | rlimit rl; 104 | getrlimit(RLIMIT_CPU, &rl); 105 | if (rl.rlim_max == RLIM_INFINITY || (rlim_t)cpu_lim < rl.rlim_max){ 106 | rl.rlim_cur = cpu_lim; 107 | if (setrlimit(RLIMIT_CPU, &rl) == -1) 108 | printf("WARNING! Could not set resource limit: CPU-time.\n"); 109 | } } 110 | 111 | // Set limit on virtual memory: 112 | if (mem_lim != INT32_MAX){ 113 | rlim_t new_mem_lim = (rlim_t)mem_lim * 1024*1024; 114 | rlimit rl; 115 | getrlimit(RLIMIT_AS, &rl); 116 | if (rl.rlim_max == RLIM_INFINITY || new_mem_lim < rl.rlim_max){ 117 | rl.rlim_cur = new_mem_lim; 118 | if (setrlimit(RLIMIT_AS, &rl) == -1) 119 | printf("WARNING! Could not set resource limit: Virtual memory.\n"); 120 | } } 121 | 122 | if (argc == 1) 123 | printf("Reading from standard input... Use '--help' for help.\n"); 124 | 125 | gzFile in = (argc == 1) ? gzdopen(0, "rb") : gzopen(argv[1], "rb"); 126 | if (in == NULL) 127 | printf("ERROR! Could not open file: %s\n", argc == 1 ? "" : argv[1]), exit(1); 128 | 129 | if (S.verbosity > 0){ 130 | printf("============================[ Problem Statistics ]=============================\n"); 131 | printf("| |\n"); } 132 | 133 | parse_DIMACS(in, S); 134 | gzclose(in); 135 | FILE* res = (argc >= 3) ? fopen(argv[2], "wb") : NULL; 136 | 137 | if (S.verbosity > 0){ 138 | printf("| Number of variables: %12d |\n", S.nVars()); 139 | printf("| Number of clauses: %12d |\n", S.nClauses()); } 140 | 141 | double parsed_time = cpuTime(); 142 | if (S.verbosity > 0){ 143 | printf("| Parse time: %12.2f s |\n", parsed_time - initial_time); 144 | printf("| |\n"); } 145 | 146 | // Change to signal-handlers that will only notify the solver and allow it to terminate 147 | // voluntarily: 148 | signal(SIGINT, SIGINT_interrupt); 149 | signal(SIGXCPU,SIGINT_interrupt); 150 | 151 | if (!S.simplify()){ 152 | if (res != NULL) fprintf(res, "UNSAT\n"), fclose(res); 153 | if (S.verbosity > 0){ 154 | printf("===============================================================================\n"); 155 | printf("Solved by unit propagation\n"); 156 | printStats(S); 157 | printf("\n"); } 158 | printf("UNSATISFIABLE\n"); 159 | exit(20); 160 | } 161 | 162 | vec dummy; 163 | lbool ret = S.solveLimited(dummy); 164 | if (S.verbosity > 0){ 165 | printStats(S); 166 | printf("\n"); } 167 | printf(ret == l_True ? "SATISFIABLE\n" : ret == l_False ? "UNSATISFIABLE\n" : "INDETERMINATE\n"); 168 | if (res != NULL){ 169 | if (ret == l_True){ 170 | fprintf(res, "SAT\n"); 171 | for (int i = 0; i < S.nVars(); i++) 172 | if (S.model[i] != l_Undef) 173 | fprintf(res, "%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1); 174 | fprintf(res, " 0\n"); 175 | }else if (ret == l_False) 176 | fprintf(res, "UNSAT\n"); 177 | else 178 | fprintf(res, "INDET\n"); 179 | fclose(res); 180 | } 181 | 182 | #ifdef NDEBUG 183 | exit(ret == l_True ? 10 : ret == l_False ? 20 : 0); // (faster than "return", which will invoke the destructor for 'Solver') 184 | #else 185 | return (ret == l_True ? 10 : ret == l_False ? 20 : 0); 186 | #endif 187 | } catch (OutOfMemoryException&){ 188 | printf("===============================================================================\n"); 189 | printf("INDETERMINATE\n"); 190 | exit(0); 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/minisat-cpp/core/Makefile: -------------------------------------------------------------------------------- 1 | EXEC = minisat 2 | DEPDIR = mtl utils 3 | 4 | include $(MROOT)/mtl/template.mk 5 | -------------------------------------------------------------------------------- /src/minisat-cpp/core/Solver.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************************[Solver.h] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_Solver_h 22 | #define Minisat_Solver_h 23 | 24 | #include 25 | #include "mtl/Vec.h" 26 | #include "mtl/Heap.h" 27 | #include "mtl/Alg.h" 28 | #include "utils/Options.h" 29 | #include "core/SolverTypes.h" 30 | 31 | 32 | namespace Minisat { 33 | 34 | //================================================================================================= 35 | // Solver -- the main class: 36 | 37 | class Solver { 38 | public: 39 | 40 | // Constructor/Destructor: 41 | // 42 | Solver(); 43 | virtual ~Solver(); 44 | 45 | // Problem specification: 46 | // 47 | Var newVar (bool polarity = true, bool dvar = true); // Add a new variable with parameters specifying variable mode. 48 | 49 | bool addClause (const vec& ps); // Add a clause to the solver. 50 | bool addEmptyClause(); // Add the empty clause, making the solver contradictory. 51 | bool addClause (Lit p); // Add a unit clause to the solver. 52 | bool addClause (Lit p, Lit q); // Add a binary clause to the solver. 53 | bool addClause (Lit p, Lit q, Lit r); // Add a ternary clause to the solver. 54 | bool addClause_( vec& ps); // Add a clause to the solver without making superflous internal copy. Will 55 | // change the passed vector 'ps'. 56 | 57 | // Solving: 58 | // 59 | bool simplify (); // Removes already satisfied clauses. 60 | bool solve (const vec& assumps); // Search for a model that respects a given set of assumptions. 61 | lbool solveLimited (const vec& assumps); // Search for a model that respects a given set of assumptions (With resource constraints). 62 | bool solve (); // Search without assumptions. 63 | bool solve (Lit p); // Search for a model that respects a single assumption. 64 | bool solve (Lit p, Lit q); // Search for a model that respects two assumptions. 65 | bool solve (Lit p, Lit q, Lit r); // Search for a model that respects three assumptions. 66 | bool okay () const; // FALSE means solver is in a conflicting state 67 | 68 | void toDimacs (FILE* f, const vec& assumps); // Write CNF to file in DIMACS-format. 69 | void toDimacs (const char *file, const vec& assumps); 70 | void toDimacs (FILE* f, Clause& c, vec& map, Var& max); 71 | 72 | // Convenience versions of 'toDimacs()': 73 | void toDimacs (const char* file); 74 | void toDimacs (const char* file, Lit p); 75 | void toDimacs (const char* file, Lit p, Lit q); 76 | void toDimacs (const char* file, Lit p, Lit q, Lit r); 77 | 78 | // Variable mode: 79 | // 80 | void setPolarity (Var v, bool b); // Declare which polarity the decision heuristic should use for a variable. Requires mode 'polarity_user'. 81 | void setDecisionVar (Var v, bool b); // Declare if a variable should be eligible for selection in the decision heuristic. 82 | 83 | // Read state: 84 | // 85 | lbool value (Var x) const; // The current value of a variable. 86 | lbool value (Lit p) const; // The current value of a literal. 87 | int level (Var x) const; // The current level of a variable, if assigned. 88 | lbool modelValue (Var x) const; // The value of a variable in the last model. The last call to solve must have been satisfiable. 89 | lbool modelValue (Lit p) const; // The value of a literal in the last model. The last call to solve must have been satisfiable. 90 | int nAssigns () const; // The current number of assigned literals. 91 | int nClauses () const; // The current number of original clauses. 92 | int nLearnts () const; // The current number of learnt clauses. 93 | int nVars () const; // The current number of variables. 94 | int nFreeVars () const; 95 | 96 | // Resource contraints: 97 | // 98 | void setConfBudget(int64_t x); 99 | void setPropBudget(int64_t x); 100 | void budgetOff(); 101 | void interrupt(); // Trigger a (potentially asynchronous) interruption of the solver. 102 | void clearInterrupt(); // Clear interrupt indicator flag. 103 | 104 | // Memory managment: 105 | // 106 | virtual void garbageCollect(); 107 | void checkGarbage(double gf); 108 | void checkGarbage(); 109 | 110 | // Extra results: (read-only member variable) 111 | // 112 | vec model; // If problem is satisfiable, this vector contains the model (if any). 113 | vec conflict; // If problem is unsatisfiable (possibly under assumptions), 114 | // this vector represent the final conflict clause expressed in the assumptions. 115 | 116 | // Mode of operation: 117 | // 118 | int verbosity; 119 | double var_decay; 120 | double clause_decay; 121 | double random_var_freq; 122 | double random_seed; 123 | bool luby_restart; 124 | int ccmin_mode; // Controls conflict clause minimization (0=none, 1=basic, 2=deep). 125 | int phase_saving; // Controls the level of phase saving (0=none, 1=limited, 2=full). 126 | bool rnd_pol; // Use random polarities for branching heuristics. 127 | bool rnd_init_act; // Initialize variable activities with a small random value. 128 | double garbage_frac; // The fraction of wasted memory allowed before a garbage collection is triggered. 129 | 130 | int restart_first; // The initial restart limit. (default 100) 131 | double restart_inc; // The factor with which the restart limit is multiplied in each restart. (default 1.5) 132 | double learntsize_factor; // The intitial limit for learnt clauses is a factor of the original clauses. (default 1 / 3) 133 | double learntsize_inc; // The limit for learnt clauses is multiplied with this factor each restart. (default 1.1) 134 | 135 | int learntsize_adjust_start_confl; 136 | double learntsize_adjust_inc; 137 | 138 | // Statistics: (read-only member variable) 139 | // 140 | uint64_t solves, starts, decisions, rnd_decisions, propagations, conflicts; 141 | uint64_t dec_vars, clauses_literals, learnts_literals, max_literals, tot_literals; 142 | 143 | protected: 144 | 145 | // Helper structures: 146 | // 147 | struct VarData { CRef reason; int level; }; 148 | static inline VarData mkVarData(CRef cr, int l){ VarData d = {cr, l}; return d; } 149 | 150 | struct Watcher { 151 | CRef cref; 152 | Lit blocker; 153 | Watcher(CRef cr, Lit p) : cref(cr), blocker(p) {} 154 | bool operator==(const Watcher& w) const { return cref == w.cref; } 155 | bool operator!=(const Watcher& w) const { return cref != w.cref; } 156 | }; 157 | 158 | struct WatcherDeleted 159 | { 160 | const ClauseAllocator& ca; 161 | WatcherDeleted(const ClauseAllocator& _ca) : ca(_ca) {} 162 | bool operator()(const Watcher& w) const { return ca[w.cref].mark() == 1; } 163 | }; 164 | 165 | struct VarOrderLt { 166 | const vec& activity; 167 | bool operator () (Var x, Var y) const { return activity[x] > activity[y]; } 168 | VarOrderLt(const vec& act) : activity(act) { } 169 | }; 170 | 171 | // Solver state: 172 | // 173 | bool ok; // If FALSE, the constraints are already unsatisfiable. No part of the solver state may be used! 174 | vec clauses; // List of problem clauses. 175 | vec learnts; // List of learnt clauses. 176 | double cla_inc; // Amount to bump next clause with. 177 | vec activity; // A heuristic measurement of the activity of a variable. 178 | double var_inc; // Amount to bump next variable with. 179 | OccLists, WatcherDeleted> 180 | watches; // 'watches[lit]' is a list of constraints watching 'lit' (will go there if literal becomes true). 181 | vec assigns; // The current assignments. 182 | vec polarity; // The preferred polarity of each variable. 183 | vec decision; // Declares if a variable is eligible for selection in the decision heuristic. 184 | vec trail; // Assignment stack; stores all assigments made in the order they were made. 185 | vec trail_lim; // Separator indices for different decision levels in 'trail'. 186 | vec vardata; // Stores reason and level for each variable. 187 | int qhead; // Head of queue (as index into the trail -- no more explicit propagation queue in MiniSat). 188 | int simpDB_assigns; // Number of top-level assignments since last execution of 'simplify()'. 189 | int64_t simpDB_props; // Remaining number of propagations that must be made before next execution of 'simplify()'. 190 | vec assumptions; // Current set of assumptions provided to solve by the user. 191 | Heap order_heap; // A priority queue of variables ordered with respect to the variable activity. 192 | double progress_estimate;// Set by 'search()'. 193 | bool remove_satisfied; // Indicates whether possibly inefficient linear scan for satisfied clauses should be performed in 'simplify'. 194 | 195 | ClauseAllocator ca; 196 | 197 | // Temporaries (to reduce allocation overhead). Each variable is prefixed by the method in which it is 198 | // used, exept 'seen' wich is used in several places. 199 | // 200 | vec seen; 201 | vec analyze_stack; 202 | vec analyze_toclear; 203 | vec add_tmp; 204 | 205 | double max_learnts; 206 | double learntsize_adjust_confl; 207 | int learntsize_adjust_cnt; 208 | 209 | // Resource contraints: 210 | // 211 | int64_t conflict_budget; // -1 means no budget. 212 | int64_t propagation_budget; // -1 means no budget. 213 | std::atomic asynch_interrupt; 214 | 215 | // Main internal methods: 216 | // 217 | void insertVarOrder (Var x); // Insert a variable in the decision order priority queue. 218 | Lit pickBranchLit (); // Return the next decision variable. 219 | void newDecisionLevel (); // Begins a new decision level. 220 | void uncheckedEnqueue (Lit p, CRef from = CRef_Undef); // Enqueue a literal. Assumes value of literal is undefined. 221 | bool enqueue (Lit p, CRef from = CRef_Undef); // Test if fact 'p' contradicts current state, enqueue otherwise. 222 | CRef propagate (); // Perform unit propagation. Returns possibly conflicting clause. 223 | void cancelUntil (int level); // Backtrack until a certain level. 224 | void analyze (CRef confl, vec& out_learnt, int& out_btlevel); // (bt = backtrack) 225 | void analyzeFinal (Lit p, vec& out_conflict); // COULD THIS BE IMPLEMENTED BY THE ORDINARIY "analyze" BY SOME REASONABLE GENERALIZATION? 226 | bool litRedundant (Lit p, uint32_t abstract_levels); // (helper method for 'analyze()') 227 | lbool search (int nof_conflicts); // Search for a given number of conflicts. 228 | lbool solve_ (); // Main solve method (assumptions given in 'assumptions'). 229 | void reduceDB (); // Reduce the set of learnt clauses. 230 | void removeSatisfied (vec& cs); // Shrink 'cs' to contain only non-satisfied clauses. 231 | void rebuildOrderHeap (); 232 | 233 | // Maintaining Variable/Clause activity: 234 | // 235 | void varDecayActivity (); // Decay all variables with the specified factor. Implemented by increasing the 'bump' value instead. 236 | void varBumpActivity (Var v, double inc); // Increase a variable with the current 'bump' value. 237 | void varBumpActivity (Var v); // Increase a variable with the current 'bump' value. 238 | void claDecayActivity (); // Decay all clauses with the specified factor. Implemented by increasing the 'bump' value instead. 239 | void claBumpActivity (Clause& c); // Increase a clause with the current 'bump' value. 240 | 241 | // Operations on clauses: 242 | // 243 | void attachClause (CRef cr); // Attach a clause to watcher lists. 244 | void detachClause (CRef cr, bool strict = false); // Detach a clause to watcher lists. 245 | void removeClause (CRef cr); // Detach and free a clause. 246 | bool locked (const Clause& c) const; // Returns TRUE if a clause is a reason for some implication in the current state. 247 | bool satisfied (const Clause& c) const; // Returns TRUE if a clause is satisfied in the current state. 248 | 249 | void relocAll (ClauseAllocator& to); 250 | 251 | // Misc: 252 | // 253 | int decisionLevel () const; // Gives the current decisionlevel. 254 | uint32_t abstractLevel (Var x) const; // Used to represent an abstraction of sets of decision levels. 255 | CRef reason (Var x) const; 256 | double progressEstimate () const; // DELETE THIS ?? IT'S NOT VERY USEFUL ... 257 | bool withinBudget () const; 258 | 259 | // Static helpers: 260 | // 261 | 262 | // Returns a random float 0 <= x < 1. Seed must never be 0. 263 | static inline double drand(double& seed) { 264 | seed *= 1389796; 265 | int q = (int)(seed / 2147483647); 266 | seed -= (double)q * 2147483647; 267 | return seed / 2147483647; } 268 | 269 | // Returns a random integer 0 <= x < size. Seed must never be 0. 270 | static inline int irand(double& seed, int size) { 271 | return (int)(drand(seed) * size); } 272 | }; 273 | 274 | 275 | //================================================================================================= 276 | // Implementation of inline methods: 277 | 278 | inline CRef Solver::reason(Var x) const { return vardata[x].reason; } 279 | inline int Solver::level (Var x) const { return vardata[x].level; } 280 | 281 | inline void Solver::insertVarOrder(Var x) { 282 | if (!order_heap.inHeap(x) && decision[x]) order_heap.insert(x); } 283 | 284 | inline void Solver::varDecayActivity() { var_inc *= (1 / var_decay); } 285 | inline void Solver::varBumpActivity(Var v) { varBumpActivity(v, var_inc); } 286 | inline void Solver::varBumpActivity(Var v, double inc) { 287 | if ( (activity[v] += inc) > 1e100 ) { 288 | // Rescale: 289 | for (int i = 0; i < nVars(); i++) 290 | activity[i] *= 1e-100; 291 | var_inc *= 1e-100; } 292 | 293 | // Update order_heap with respect to new activity: 294 | if (order_heap.inHeap(v)) 295 | order_heap.decrease(v); } 296 | 297 | inline void Solver::claDecayActivity() { cla_inc *= (1 / clause_decay); } 298 | inline void Solver::claBumpActivity (Clause& c) { 299 | if ( (c.activity() += cla_inc) > 1e20 ) { 300 | // Rescale: 301 | for (int i = 0; i < learnts.size(); i++) 302 | ca[learnts[i]].activity() *= 1e-20; 303 | cla_inc *= 1e-20; } } 304 | 305 | inline void Solver::checkGarbage(void){ return checkGarbage(garbage_frac); } 306 | inline void Solver::checkGarbage(double gf){ 307 | if (ca.wasted() > ca.size() * gf) 308 | garbageCollect(); } 309 | 310 | // NOTE: enqueue does not set the ok flag! (only public methods do) 311 | inline bool Solver::enqueue (Lit p, CRef from) { return value(p) != l_Undef ? value(p) != l_False : (uncheckedEnqueue(p, from), true); } 312 | inline bool Solver::addClause (const vec& ps) { ps.copyTo(add_tmp); return addClause_(add_tmp); } 313 | inline bool Solver::addEmptyClause () { add_tmp.clear(); return addClause_(add_tmp); } 314 | inline bool Solver::addClause (Lit p) { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp); } 315 | inline bool Solver::addClause (Lit p, Lit q) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp); } 316 | inline bool Solver::addClause (Lit p, Lit q, Lit r) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp); } 317 | inline bool Solver::locked (const Clause& c) const { return value(c[0]) == l_True && reason(var(c[0])) != CRef_Undef && ca.lea(reason(var(c[0]))) == &c; } 318 | inline void Solver::newDecisionLevel() { trail_lim.push(trail.size()); } 319 | 320 | inline int Solver::decisionLevel () const { return trail_lim.size(); } 321 | inline uint32_t Solver::abstractLevel (Var x) const { return 1 << (level(x) & 31); } 322 | inline lbool Solver::value (Var x) const { return assigns[x]; } 323 | inline lbool Solver::value (Lit p) const { return assigns[var(p)] ^ sign(p); } 324 | inline lbool Solver::modelValue (Var x) const { return model[x]; } 325 | inline lbool Solver::modelValue (Lit p) const { return model[var(p)] ^ sign(p); } 326 | inline int Solver::nAssigns () const { return trail.size(); } 327 | inline int Solver::nClauses () const { return clauses.size(); } 328 | inline int Solver::nLearnts () const { return learnts.size(); } 329 | inline int Solver::nVars () const { return vardata.size(); } 330 | inline int Solver::nFreeVars () const { return (int)dec_vars - (trail_lim.size() == 0 ? trail.size() : trail_lim[0]); } 331 | inline void Solver::setPolarity (Var v, bool b) { polarity[v] = b; } 332 | inline void Solver::setDecisionVar(Var v, bool b) 333 | { 334 | if ( b && !decision[v]) dec_vars++; 335 | else if (!b && decision[v]) dec_vars--; 336 | 337 | decision[v] = b; 338 | insertVarOrder(v); 339 | } 340 | inline void Solver::setConfBudget(int64_t x){ conflict_budget = conflicts + x; } 341 | inline void Solver::setPropBudget(int64_t x){ propagation_budget = propagations + x; } 342 | inline void Solver::interrupt(){ asynch_interrupt = true; } 343 | inline void Solver::clearInterrupt(){ asynch_interrupt = false; } 344 | inline void Solver::budgetOff(){ conflict_budget = propagation_budget = -1; } 345 | inline bool Solver::withinBudget() const { 346 | return !asynch_interrupt && 347 | (conflict_budget < 0 || conflicts < (uint64_t)conflict_budget) && 348 | (propagation_budget < 0 || propagations < (uint64_t)propagation_budget); } 349 | 350 | // FIXME: after the introduction of asynchronous interrruptions the solve-versions that return a 351 | // pure bool do not give a safe interface. Either interrupts must be possible to turn off here, or 352 | // all calls to solve must return an 'lbool'. I'm not yet sure which I prefer. 353 | inline bool Solver::solve () { budgetOff(); assumptions.clear(); return solve_() == l_True; } 354 | inline bool Solver::solve (Lit p) { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_() == l_True; } 355 | inline bool Solver::solve (Lit p, Lit q) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_() == l_True; } 356 | inline bool Solver::solve (Lit p, Lit q, Lit r) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_() == l_True; } 357 | inline bool Solver::solve (const vec& assumps){ budgetOff(); assumps.copyTo(assumptions); return solve_() == l_True; } 358 | inline lbool Solver::solveLimited (const vec& assumps){ assumps.copyTo(assumptions); return solve_(); } 359 | inline bool Solver::okay () const { return ok; } 360 | 361 | inline void Solver::toDimacs (const char* file){ vec as; toDimacs(file, as); } 362 | inline void Solver::toDimacs (const char* file, Lit p){ vec as; as.push(p); toDimacs(file, as); } 363 | inline void Solver::toDimacs (const char* file, Lit p, Lit q){ vec as; as.push(p); as.push(q); toDimacs(file, as); } 364 | inline void Solver::toDimacs (const char* file, Lit p, Lit q, Lit r){ vec as; as.push(p); as.push(q); as.push(r); toDimacs(file, as); } 365 | 366 | 367 | //================================================================================================= 368 | // Debug etc: 369 | 370 | 371 | //================================================================================================= 372 | } 373 | 374 | #endif 375 | -------------------------------------------------------------------------------- /src/minisat-cpp/core/SolverTypes.h: -------------------------------------------------------------------------------- 1 | /***********************************************************************************[SolverTypes.h] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | 22 | #ifndef Minisat_SolverTypes_h 23 | #define Minisat_SolverTypes_h 24 | 25 | #include 26 | 27 | #include "mtl/IntTypes.h" 28 | #include "mtl/Alg.h" 29 | #include "mtl/Vec.h" 30 | #include "mtl/Map.h" 31 | #include "mtl/Alloc.h" 32 | 33 | namespace Minisat { 34 | 35 | //================================================================================================= 36 | // Variables, literals, lifted booleans, clauses: 37 | 38 | 39 | // NOTE! Variables are just integers. No abstraction here. They should be chosen from 0..N, 40 | // so that they can be used as array indices. 41 | 42 | typedef int Var; 43 | #define var_Undef (-1) 44 | 45 | 46 | struct Lit { 47 | int x; 48 | 49 | bool operator == (Lit p) const { return x == p.x; } 50 | bool operator != (Lit p) const { return x != p.x; } 51 | bool operator < (Lit p) const { return x < p.x; } // '<' makes p, ~p adjacent in the ordering. 52 | }; 53 | 54 | // Use this as a constructor: 55 | inline Lit mkLit(Var var, bool sign = false) { Lit p; p.x = var + var + (int)sign; return p; } 56 | 57 | inline Lit operator ~(Lit p) { Lit q; q.x = p.x ^ 1; return q; } 58 | inline Lit operator ^(Lit p, bool b) { Lit q; q.x = p.x ^ (unsigned int)b; return q; } 59 | inline bool sign (Lit p) { return p.x & 1; } 60 | inline int var (Lit p) { return p.x >> 1; } 61 | 62 | // Mapping Literals to and from compact integers suitable for array indexing: 63 | inline int toInt (Var v) { return v; } 64 | inline int toInt (Lit p) { return p.x; } 65 | inline Lit toLit (int i) { Lit p; p.x = i; return p; } 66 | 67 | //const Lit lit_Undef = mkLit(var_Undef, false); // }- Useful special constants. 68 | //const Lit lit_Error = mkLit(var_Undef, true ); // } 69 | 70 | const Lit lit_Undef = { -2 }; // }- Useful special constants. 71 | const Lit lit_Error = { -1 }; // } 72 | 73 | 74 | //================================================================================================= 75 | // Lifted booleans: 76 | // 77 | // NOTE: this implementation is optimized for the case when comparisons between values are mostly 78 | // between one variable and one constant. Some care had to be taken to make sure that gcc 79 | // does enough constant propagation to produce sensible code, and this appears to be somewhat 80 | // fragile unfortunately. 81 | 82 | #define l_True (lbool((uint8_t)0)) // gcc does not do constant propagation if these are real constants. 83 | #define l_False (lbool((uint8_t)1)) 84 | #define l_Undef (lbool((uint8_t)2)) 85 | 86 | class lbool { 87 | uint8_t value; 88 | 89 | public: 90 | explicit lbool(uint8_t v) : value(v) { } 91 | 92 | lbool() : value(0) { } 93 | explicit lbool(bool x) : value(!x) { } 94 | 95 | bool operator == (lbool b) const { return ((b.value&2) & (value&2)) | (!(b.value&2)&(value == b.value)); } 96 | bool operator != (lbool b) const { return !(*this == b); } 97 | lbool operator ^ (bool b) const { return lbool((uint8_t)(value^(uint8_t)b)); } 98 | 99 | lbool operator && (lbool b) const { 100 | uint8_t sel = (this->value << 1) | (b.value << 3); 101 | uint8_t v = (0xF7F755F4 >> sel) & 3; 102 | return lbool(v); } 103 | 104 | lbool operator || (lbool b) const { 105 | uint8_t sel = (this->value << 1) | (b.value << 3); 106 | uint8_t v = (0xFCFCF400 >> sel) & 3; 107 | return lbool(v); } 108 | 109 | friend int toInt (lbool l); 110 | friend lbool toLbool(int v); 111 | }; 112 | inline int toInt (lbool l) { return l.value; } 113 | inline lbool toLbool(int v) { return lbool((uint8_t)v); } 114 | 115 | //================================================================================================= 116 | // Clause -- a simple class for representing a clause: 117 | 118 | class Clause; 119 | typedef RegionAllocator::Ref CRef; 120 | 121 | class Clause { 122 | struct { 123 | unsigned mark : 2; 124 | unsigned learnt : 1; 125 | unsigned has_extra : 1; 126 | unsigned reloced : 1; 127 | unsigned size : 27; } header; 128 | union { Lit lit; float act; uint32_t abs; CRef rel; } data[0]; 129 | 130 | friend class ClauseAllocator; 131 | 132 | // NOTE: This constructor cannot be used directly (doesn't allocate enough memory). 133 | template 134 | Clause(const V& ps, bool use_extra, bool learnt) { 135 | header.mark = 0; 136 | header.learnt = learnt; 137 | header.has_extra = use_extra; 138 | header.reloced = 0; 139 | header.size = ps.size(); 140 | 141 | for (int i = 0; i < ps.size(); i++) 142 | data[i].lit = ps[i]; 143 | 144 | if (header.has_extra){ 145 | if (header.learnt) 146 | data[header.size].act = 0; 147 | else 148 | calcAbstraction(); } 149 | } 150 | 151 | public: 152 | void calcAbstraction() { 153 | assert(header.has_extra); 154 | uint32_t abstraction = 0; 155 | for (int i = 0; i < size(); i++) 156 | abstraction |= 1 << (var(data[i].lit) & 31); 157 | data[header.size].abs = abstraction; } 158 | 159 | 160 | int size () const { return header.size; } 161 | void shrink (int i) { assert(i <= size()); if (header.has_extra) data[header.size-i] = data[header.size]; header.size -= i; } 162 | void pop () { shrink(1); } 163 | bool learnt () const { return header.learnt; } 164 | bool has_extra () const { return header.has_extra; } 165 | uint32_t mark () const { return header.mark; } 166 | void mark (uint32_t m) { header.mark = m; } 167 | const Lit& last () const { return data[header.size-1].lit; } 168 | 169 | bool reloced () const { return header.reloced; } 170 | CRef relocation () const { return data[0].rel; } 171 | void relocate (CRef c) { header.reloced = 1; data[0].rel = c; } 172 | 173 | // NOTE: somewhat unsafe to change the clause in-place! Must manually call 'calcAbstraction' afterwards for 174 | // subsumption operations to behave correctly. 175 | Lit& operator [] (int i) { return data[i].lit; } 176 | Lit operator [] (int i) const { return data[i].lit; } 177 | operator const Lit* (void) const { return (Lit*)data; } 178 | 179 | float& activity () { assert(header.has_extra); return data[header.size].act; } 180 | uint32_t abstraction () const { assert(header.has_extra); return data[header.size].abs; } 181 | 182 | Lit subsumes (const Clause& other) const; 183 | void strengthen (Lit p); 184 | }; 185 | 186 | 187 | //================================================================================================= 188 | // ClauseAllocator -- a simple class for allocating memory for clauses: 189 | 190 | 191 | const CRef CRef_Undef = RegionAllocator::Ref_Undef; 192 | class ClauseAllocator : public RegionAllocator 193 | { 194 | static int clauseWord32Size(int size, bool has_extra){ 195 | return (sizeof(Clause) + (sizeof(Lit) * (size + (int)has_extra))) / sizeof(uint32_t); } 196 | public: 197 | bool extra_clause_field; 198 | 199 | ClauseAllocator(uint32_t start_cap) : RegionAllocator(start_cap), extra_clause_field(false){} 200 | ClauseAllocator() : extra_clause_field(false){} 201 | 202 | void moveTo(ClauseAllocator& to){ 203 | to.extra_clause_field = extra_clause_field; 204 | RegionAllocator::moveTo(to); } 205 | 206 | template 207 | CRef alloc(const Lits& ps, bool learnt = false) 208 | { 209 | assert(sizeof(Lit) == sizeof(uint32_t)); 210 | assert(sizeof(float) == sizeof(uint32_t)); 211 | bool use_extra = learnt | extra_clause_field; 212 | 213 | CRef cid = RegionAllocator::alloc(clauseWord32Size(ps.size(), use_extra)); 214 | new (lea(cid)) Clause(ps, use_extra, learnt); 215 | 216 | return cid; 217 | } 218 | 219 | // Deref, Load Effective Address (LEA), Inverse of LEA (AEL): 220 | Clause& operator[](Ref r) { return (Clause&)RegionAllocator::operator[](r); } 221 | const Clause& operator[](Ref r) const { return (Clause&)RegionAllocator::operator[](r); } 222 | Clause* lea (Ref r) { return (Clause*)RegionAllocator::lea(r); } 223 | const Clause* lea (Ref r) const { return (Clause*)RegionAllocator::lea(r); } 224 | Ref ael (const Clause* t){ return RegionAllocator::ael((uint32_t*)t); } 225 | 226 | void free(CRef cid) 227 | { 228 | Clause& c = operator[](cid); 229 | RegionAllocator::free(clauseWord32Size(c.size(), c.has_extra())); 230 | } 231 | 232 | void reloc(CRef& cr, ClauseAllocator& to) 233 | { 234 | Clause& c = operator[](cr); 235 | 236 | if (c.reloced()) { cr = c.relocation(); return; } 237 | 238 | cr = to.alloc(c, c.learnt()); 239 | c.relocate(cr); 240 | 241 | // Copy extra data-fields: 242 | // (This could be cleaned-up. Generalize Clause-constructor to be applicable here instead?) 243 | to[cr].mark(c.mark()); 244 | if (to[cr].learnt()) to[cr].activity() = c.activity(); 245 | else if (to[cr].has_extra()) to[cr].calcAbstraction(); 246 | } 247 | }; 248 | 249 | 250 | //================================================================================================= 251 | // OccLists -- a class for maintaining occurence lists with lazy deletion: 252 | 253 | template 254 | class OccLists 255 | { 256 | vec occs; 257 | vec dirty; 258 | vec dirties; 259 | Deleted deleted; 260 | 261 | public: 262 | OccLists(const Deleted& d) : deleted(d) {} 263 | 264 | void init (const Idx& idx){ occs.growTo(toInt(idx)+1); dirty.growTo(toInt(idx)+1, 0); } 265 | // Vec& operator[](const Idx& idx){ return occs[toInt(idx)]; } 266 | Vec& operator[](const Idx& idx){ return occs[toInt(idx)]; } 267 | Vec& lookup (const Idx& idx){ if (dirty[toInt(idx)]) clean(idx); return occs[toInt(idx)]; } 268 | 269 | void cleanAll (); 270 | void clean (const Idx& idx); 271 | void smudge (const Idx& idx){ 272 | if (dirty[toInt(idx)] == 0){ 273 | dirty[toInt(idx)] = 1; 274 | dirties.push(idx); 275 | } 276 | } 277 | 278 | void clear(bool free = true){ 279 | occs .clear(free); 280 | dirty .clear(free); 281 | dirties.clear(free); 282 | } 283 | }; 284 | 285 | 286 | template 287 | void OccLists::cleanAll() 288 | { 289 | for (int i = 0; i < dirties.size(); i++) 290 | // Dirties may contain duplicates so check here if a variable is already cleaned: 291 | if (dirty[toInt(dirties[i])]) 292 | clean(dirties[i]); 293 | dirties.clear(); 294 | } 295 | 296 | 297 | template 298 | void OccLists::clean(const Idx& idx) 299 | { 300 | Vec& vec = occs[toInt(idx)]; 301 | int i, j; 302 | for (i = j = 0; i < vec.size(); i++) 303 | if (!deleted(vec[i])) 304 | vec[j++] = vec[i]; 305 | vec.shrink(i - j); 306 | dirty[toInt(idx)] = 0; 307 | } 308 | 309 | 310 | //================================================================================================= 311 | // CMap -- a class for mapping clauses to values: 312 | 313 | 314 | template 315 | class CMap 316 | { 317 | struct CRefHash { 318 | uint32_t operator()(CRef cr) const { return (uint32_t)cr; } }; 319 | 320 | typedef Map HashTable; 321 | HashTable map; 322 | 323 | public: 324 | // Size-operations: 325 | void clear () { map.clear(); } 326 | int size () const { return map.elems(); } 327 | 328 | 329 | // Insert/Remove/Test mapping: 330 | void insert (CRef cr, const T& t){ map.insert(cr, t); } 331 | void growTo (CRef cr, const T& t){ map.insert(cr, t); } // NOTE: for compatibility 332 | void remove (CRef cr) { map.remove(cr); } 333 | bool has (CRef cr, T& t) { return map.peek(cr, t); } 334 | 335 | // Vector interface (the clause 'c' must already exist): 336 | const T& operator [] (CRef cr) const { return map[cr]; } 337 | T& operator [] (CRef cr) { return map[cr]; } 338 | 339 | // Iteration (not transparent at all at the moment): 340 | int bucket_count() const { return map.bucket_count(); } 341 | const vec& bucket(int i) const { return map.bucket(i); } 342 | 343 | // Move contents to other map: 344 | void moveTo(CMap& other){ map.moveTo(other.map); } 345 | 346 | // TMP debug: 347 | void debug(){ 348 | printf(" --- size = %d, bucket_count = %d\n", size(), map.bucket_count()); } 349 | }; 350 | 351 | 352 | /*_________________________________________________________________________________________________ 353 | | 354 | | subsumes : (other : const Clause&) -> Lit 355 | | 356 | | Description: 357 | | Checks if clause subsumes 'other', and at the same time, if it can be used to simplify 'other' 358 | | by subsumption resolution. 359 | | 360 | | Result: 361 | | lit_Error - No subsumption or simplification 362 | | lit_Undef - Clause subsumes 'other' 363 | | p - The literal p can be deleted from 'other' 364 | |________________________________________________________________________________________________@*/ 365 | inline Lit Clause::subsumes(const Clause& other) const 366 | { 367 | //if (other.size() < size() || (extra.abst & ~other.extra.abst) != 0) 368 | //if (other.size() < size() || (!learnt() && !other.learnt() && (extra.abst & ~other.extra.abst) != 0)) 369 | assert(!header.learnt); assert(!other.header.learnt); 370 | assert(header.has_extra); assert(other.header.has_extra); 371 | if (other.header.size < header.size || (data[header.size].abs & ~other.data[other.header.size].abs) != 0) 372 | return lit_Error; 373 | 374 | Lit ret = lit_Undef; 375 | const Lit* c = (const Lit*)(*this); 376 | const Lit* d = (const Lit*)other; 377 | 378 | for (unsigned i = 0; i < header.size; i++) { 379 | // search for c[i] or ~c[i] 380 | for (unsigned j = 0; j < other.header.size; j++) 381 | if (c[i] == d[j]) 382 | goto ok; 383 | else if (ret == lit_Undef && c[i] == ~d[j]){ 384 | ret = c[i]; 385 | goto ok; 386 | } 387 | 388 | // did not find it 389 | return lit_Error; 390 | ok:; 391 | } 392 | 393 | return ret; 394 | } 395 | 396 | inline void Clause::strengthen(Lit p) 397 | { 398 | remove(*this, p); 399 | calcAbstraction(); 400 | } 401 | 402 | //================================================================================================= 403 | } 404 | 405 | #endif 406 | -------------------------------------------------------------------------------- /src/minisat-cpp/core/depend.mk: -------------------------------------------------------------------------------- 1 | /home/simon/w/ocaml-minisat/src/minisat-cpp/core/Main.o /home/simon/w/ocaml-minisat/src/minisat-cpp/core/Main.or /home/simon/w/ocaml-minisat/src/minisat-cpp/core/Main.od /home/simon/w/ocaml-minisat/src/minisat-cpp/core/Main.op: /home/simon/w/ocaml-minisat/src/minisat-cpp/core/Main.cc \ 2 | /home/simon/w/ocaml-minisat/src/minisat-cpp/utils/System.h \ 3 | /home/simon/w/ocaml-minisat/src/minisat-cpp/mtl/IntTypes.h \ 4 | /home/simon/w/ocaml-minisat/src/minisat-cpp/utils/ParseUtils.h \ 5 | /home/simon/w/ocaml-minisat/src/minisat-cpp/utils/Options.h \ 6 | /home/simon/w/ocaml-minisat/src/minisat-cpp/mtl/Vec.h \ 7 | /home/simon/w/ocaml-minisat/src/minisat-cpp/mtl/XAlloc.h \ 8 | /home/simon/w/ocaml-minisat/src/minisat-cpp/core/Dimacs.h \ 9 | /home/simon/w/ocaml-minisat/src/minisat-cpp/core/SolverTypes.h \ 10 | /home/simon/w/ocaml-minisat/src/minisat-cpp/mtl/Alg.h \ 11 | /home/simon/w/ocaml-minisat/src/minisat-cpp/mtl/Map.h \ 12 | /home/simon/w/ocaml-minisat/src/minisat-cpp/mtl/Alloc.h \ 13 | /home/simon/w/ocaml-minisat/src/minisat-cpp/core/Solver.h \ 14 | /home/simon/w/ocaml-minisat/src/minisat-cpp/mtl/Heap.h 15 | /home/simon/w/ocaml-minisat/src/minisat-cpp/core/Solver.o /home/simon/w/ocaml-minisat/src/minisat-cpp/core/Solver.or /home/simon/w/ocaml-minisat/src/minisat-cpp/core/Solver.od /home/simon/w/ocaml-minisat/src/minisat-cpp/core/Solver.op: /home/simon/w/ocaml-minisat/src/minisat-cpp/core/Solver.cc \ 16 | /home/simon/w/ocaml-minisat/src/minisat-cpp/mtl/Sort.h \ 17 | /home/simon/w/ocaml-minisat/src/minisat-cpp/mtl/Vec.h \ 18 | /home/simon/w/ocaml-minisat/src/minisat-cpp/mtl/IntTypes.h \ 19 | /home/simon/w/ocaml-minisat/src/minisat-cpp/mtl/XAlloc.h \ 20 | /home/simon/w/ocaml-minisat/src/minisat-cpp/core/Solver.h \ 21 | /home/simon/w/ocaml-minisat/src/minisat-cpp/mtl/Heap.h \ 22 | /home/simon/w/ocaml-minisat/src/minisat-cpp/mtl/Alg.h \ 23 | /home/simon/w/ocaml-minisat/src/minisat-cpp/utils/Options.h \ 24 | /home/simon/w/ocaml-minisat/src/minisat-cpp/utils/ParseUtils.h \ 25 | /home/simon/w/ocaml-minisat/src/minisat-cpp/core/SolverTypes.h \ 26 | /home/simon/w/ocaml-minisat/src/minisat-cpp/mtl/Map.h \ 27 | /home/simon/w/ocaml-minisat/src/minisat-cpp/mtl/Alloc.h 28 | -------------------------------------------------------------------------------- /src/minisat-cpp/doc/ReleaseNotes-2.2.0.txt: -------------------------------------------------------------------------------- 1 | Release Notes for MiniSat 2.2.0 2 | =============================== 3 | 4 | Changes since version 2.0: 5 | 6 | * Started using a more standard release numbering. 7 | 8 | * Includes some now well-known heuristics: phase-saving and luby 9 | restarts. The old heuristics are still present and can be activated 10 | if needed. 11 | 12 | * Detection/Handling of out-of-memory and vector capacity 13 | overflow. This is fairly new and relatively untested. 14 | 15 | * Simple resource controls: CPU-time, memory, number of 16 | conflicts/decisions. 17 | 18 | * CPU-time limiting is implemented by a more general, but simple, 19 | asynchronous interruption feature. This means that the solving 20 | procedure can be interrupted from another thread or in a signal 21 | handler. 22 | 23 | * Improved portability with respect to building on Solaris and with 24 | Visual Studio. This is not regularly tested and chances are that 25 | this have been broken since, but should be fairly easy to fix if 26 | so. 27 | 28 | * Changed C++ file-extention to the less problematic ".cc". 29 | 30 | * Source code is now namespace-protected 31 | 32 | * Introducing a new Clause Memory Allocator that brings reduced 33 | memory consumption on 64-bit architechtures and improved 34 | performance (to some extent). The allocator uses a region-based 35 | approach were all references to clauses are represented as a 32-bit 36 | index into a global memory region that contains all clauses. To 37 | free up and compact memory it uses a simple copying garbage 38 | collector. 39 | 40 | * Improved unit-propagation by Blocking Literals. For each entry in 41 | the watcher lists, pair the pointer to a clause with some 42 | (arbitrary) literal from the clause. The idea is that if the 43 | literal is currently true (i.e. the clause is satisfied) the 44 | watchers of the clause does not need to be altered. This can thus 45 | be detected without touching the clause's memory at all. As often 46 | as can be done cheaply, the blocking literal for entries to the 47 | watcher list of a literal 'p' is set to the other literal watched 48 | in the corresponding clause. 49 | 50 | * Basic command-line/option handling system. Makes it easy to specify 51 | options in the class that they affect, and whenever that class is 52 | used in an executable, parsing of options and help messages are 53 | brought in automatically. 54 | 55 | * General clean-up and various minor bug-fixes. 56 | 57 | * Changed implementation of variable-elimination/model-extension: 58 | 59 | - The interface is changed so that arbitrary remembering is no longer 60 | possible. If you need to mention some variable again in the future, 61 | this variable has to be frozen. 62 | 63 | - When eliminating a variable, only clauses that contain the variable 64 | with one sign is necessary to store. Thereby making the other sign 65 | a "default" value when extending models. 66 | 67 | - The memory consumption for eliminated clauses is further improved 68 | by storing all eliminated clauses in a single contiguous vector. 69 | 70 | * Some common utility code (I/O, Parsing, CPU-time, etc) is ripped 71 | out and placed in a separate "utils" directory. 72 | 73 | * The DIMACS parse is refactored so that it can be reused in other 74 | applications (not very elegant, but at least possible). 75 | 76 | * Some simple improvements to scalability of preprocessing, using 77 | more lazy clause removal from data-structures and a couple of 78 | ad-hoc limits (the longest clause that can be produced in variable 79 | elimination, and the longest clause used in backward subsumption). 80 | -------------------------------------------------------------------------------- /src/minisat-cpp/mtl/.clangd: -------------------------------------------------------------------------------- 1 | 2 | CompileFlags: 3 | Add: [--std=c++11, -I, ..] 4 | -------------------------------------------------------------------------------- /src/minisat-cpp/mtl/Alg.h: -------------------------------------------------------------------------------- 1 | /*******************************************************************************************[Alg.h] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_Alg_h 22 | #define Minisat_Alg_h 23 | 24 | #include "mtl/Vec.h" 25 | 26 | namespace Minisat { 27 | 28 | //================================================================================================= 29 | // Useful functions on vector-like types: 30 | 31 | //================================================================================================= 32 | // Removing and searching for elements: 33 | // 34 | 35 | template 36 | static inline void remove(V& ts, const T& t) 37 | { 38 | int j = 0; 39 | for (; j < ts.size() && ts[j] != t; j++); 40 | assert(j < ts.size()); 41 | for (; j < ts.size()-1; j++) ts[j] = ts[j+1]; 42 | ts.pop(); 43 | } 44 | 45 | 46 | template 47 | static inline bool find(V& ts, const T& t) 48 | { 49 | int j = 0; 50 | for (; j < ts.size() && ts[j] != t; j++); 51 | return j < ts.size(); 52 | } 53 | 54 | 55 | //================================================================================================= 56 | // Copying vectors with support for nested vector types: 57 | // 58 | 59 | // Base case: 60 | template 61 | static inline void copy(const T& from, T& to) 62 | { 63 | to = from; 64 | } 65 | 66 | // Recursive case: 67 | template 68 | static inline void copy(const vec& from, vec& to, bool append = false) 69 | { 70 | if (!append) 71 | to.clear(); 72 | for (int i = 0; i < from.size(); i++){ 73 | to.push(); 74 | copy(from[i], to.last()); 75 | } 76 | } 77 | 78 | template 79 | static inline void append(const vec& from, vec& to){ copy(from, to, true); } 80 | 81 | //================================================================================================= 82 | } 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /src/minisat-cpp/mtl/Alloc.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************************[Alloc.h] 2 | Copyright (c) 2008-2010, Niklas Sorensson 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 5 | associated documentation files (the "Software"), to deal in the Software without restriction, 6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 7 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or 11 | substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 14 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 16 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 17 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | **************************************************************************************************/ 19 | 20 | 21 | #ifndef Minisat_Alloc_h 22 | #define Minisat_Alloc_h 23 | 24 | #include "mtl/XAlloc.h" 25 | #include "mtl/Vec.h" 26 | 27 | namespace Minisat { 28 | 29 | //================================================================================================= 30 | // Simple Region-based memory allocator: 31 | 32 | template 33 | class RegionAllocator 34 | { 35 | T* memory; 36 | uint32_t sz; 37 | uint32_t cap; 38 | uint32_t wasted_; 39 | 40 | void capacity(uint32_t min_cap); 41 | 42 | public: 43 | // TODO: make this a class for better type-checking? 44 | typedef uint32_t Ref; 45 | enum { Ref_Undef = UINT32_MAX }; 46 | enum { Unit_Size = sizeof(uint32_t) }; 47 | 48 | explicit RegionAllocator(uint32_t start_cap = 1024*1024) : memory(NULL), sz(0), cap(0), wasted_(0){ capacity(start_cap); } 49 | ~RegionAllocator() 50 | { 51 | if (memory != NULL) 52 | ::free(memory); 53 | } 54 | 55 | 56 | uint32_t size () const { return sz; } 57 | uint32_t wasted () const { return wasted_; } 58 | 59 | Ref alloc (int size); 60 | void free (int size) { wasted_ += size; } 61 | 62 | // Deref, Load Effective Address (LEA), Inverse of LEA (AEL): 63 | T& operator[](Ref r) { assert(r >= 0 && r < sz); return memory[r]; } 64 | const T& operator[](Ref r) const { assert(r >= 0 && r < sz); return memory[r]; } 65 | 66 | T* lea (Ref r) { assert(r >= 0 && r < sz); return &memory[r]; } 67 | const T* lea (Ref r) const { assert(r >= 0 && r < sz); return &memory[r]; } 68 | Ref ael (const T* t) { assert((void*)t >= (void*)&memory[0] && (void*)t < (void*)&memory[sz-1]); 69 | return (Ref)(t - &memory[0]); } 70 | 71 | void moveTo(RegionAllocator& to) { 72 | if (to.memory != NULL) ::free(to.memory); 73 | to.memory = memory; 74 | to.sz = sz; 75 | to.cap = cap; 76 | to.wasted_ = wasted_; 77 | 78 | memory = NULL; 79 | sz = cap = wasted_ = 0; 80 | } 81 | 82 | 83 | }; 84 | 85 | template 86 | void RegionAllocator::capacity(uint32_t min_cap) 87 | { 88 | if (cap >= min_cap) return; 89 | 90 | uint32_t prev_cap = cap; 91 | while (cap < min_cap){ 92 | // NOTE: Multiply by a factor (13/8) without causing overflow, then add 2 and make the 93 | // result even by clearing the least significant bit. The resulting sequence of capacities 94 | // is carefully chosen to hit a maximum capacity that is close to the '2^32-1' limit when 95 | // using 'uint32_t' as indices so that as much as possible of this space can be used. 96 | uint32_t delta = ((cap >> 1) + (cap >> 3) + 2) & ~1; 97 | cap += delta; 98 | 99 | if (cap <= prev_cap) 100 | throw OutOfMemoryException(); 101 | } 102 | // printf(" .. (%p) cap = %u\n", this, cap); 103 | 104 | assert(cap > 0); 105 | memory = (T*)xrealloc(memory, sizeof(T)*cap); 106 | } 107 | 108 | 109 | template 110 | typename RegionAllocator::Ref 111 | RegionAllocator::alloc(int size) 112 | { 113 | // printf("ALLOC called (this = %p, size = %d)\n", this, size); fflush(stdout); 114 | assert(size > 0); 115 | capacity(sz + size); 116 | 117 | uint32_t prev_sz = sz; 118 | sz += size; 119 | 120 | // Handle overflow: 121 | if (sz < prev_sz) 122 | throw OutOfMemoryException(); 123 | 124 | return prev_sz; 125 | } 126 | 127 | 128 | //================================================================================================= 129 | } 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /src/minisat-cpp/mtl/Heap.h: -------------------------------------------------------------------------------- 1 | /******************************************************************************************[Heap.h] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_Heap_h 22 | #define Minisat_Heap_h 23 | 24 | #include "mtl/Vec.h" 25 | 26 | namespace Minisat { 27 | 28 | //================================================================================================= 29 | // A heap implementation with support for decrease/increase key. 30 | 31 | 32 | template 33 | class Heap { 34 | Comp lt; // The heap is a minimum-heap with respect to this comparator 35 | vec heap; // Heap of integers 36 | vec indices; // Each integers position (index) in the Heap 37 | 38 | // Index "traversal" functions 39 | static inline int left (int i) { return i*2+1; } 40 | static inline int right (int i) { return (i+1)*2; } 41 | static inline int parent(int i) { return (i-1) >> 1; } 42 | 43 | 44 | void percolateUp(int i) 45 | { 46 | int x = heap[i]; 47 | int p = parent(i); 48 | 49 | while (i != 0 && lt(x, heap[p])){ 50 | heap[i] = heap[p]; 51 | indices[heap[p]] = i; 52 | i = p; 53 | p = parent(p); 54 | } 55 | heap [i] = x; 56 | indices[x] = i; 57 | } 58 | 59 | 60 | void percolateDown(int i) 61 | { 62 | int x = heap[i]; 63 | while (left(i) < heap.size()){ 64 | int child = right(i) < heap.size() && lt(heap[right(i)], heap[left(i)]) ? right(i) : left(i); 65 | if (!lt(heap[child], x)) break; 66 | heap[i] = heap[child]; 67 | indices[heap[i]] = i; 68 | i = child; 69 | } 70 | heap [i] = x; 71 | indices[x] = i; 72 | } 73 | 74 | 75 | public: 76 | Heap(const Comp& c) : lt(c) { } 77 | 78 | int size () const { return heap.size(); } 79 | bool empty () const { return heap.size() == 0; } 80 | bool inHeap (int n) const { return n < indices.size() && indices[n] >= 0; } 81 | int operator[](int index) const { assert(index < heap.size()); return heap[index]; } 82 | 83 | 84 | void decrease (int n) { assert(inHeap(n)); percolateUp (indices[n]); } 85 | void increase (int n) { assert(inHeap(n)); percolateDown(indices[n]); } 86 | 87 | 88 | // Safe variant of insert/decrease/increase: 89 | void update(int n) 90 | { 91 | if (!inHeap(n)) 92 | insert(n); 93 | else { 94 | percolateUp(indices[n]); 95 | percolateDown(indices[n]); } 96 | } 97 | 98 | 99 | void insert(int n) 100 | { 101 | indices.growTo(n+1, -1); 102 | assert(!inHeap(n)); 103 | 104 | indices[n] = heap.size(); 105 | heap.push(n); 106 | percolateUp(indices[n]); 107 | } 108 | 109 | 110 | int removeMin() 111 | { 112 | int x = heap[0]; 113 | heap[0] = heap.last(); 114 | indices[heap[0]] = 0; 115 | indices[x] = -1; 116 | heap.pop(); 117 | if (heap.size() > 1) percolateDown(0); 118 | return x; 119 | } 120 | 121 | 122 | // Rebuild the heap from scratch, using the elements in 'ns': 123 | void build(vec& ns) { 124 | for (int i = 0; i < heap.size(); i++) 125 | indices[heap[i]] = -1; 126 | heap.clear(); 127 | 128 | for (int i = 0; i < ns.size(); i++){ 129 | indices[ns[i]] = i; 130 | heap.push(ns[i]); } 131 | 132 | for (int i = heap.size() / 2 - 1; i >= 0; i--) 133 | percolateDown(i); 134 | } 135 | 136 | void clear(bool dealloc = false) 137 | { 138 | for (int i = 0; i < heap.size(); i++) 139 | indices[heap[i]] = -1; 140 | heap.clear(dealloc); 141 | } 142 | }; 143 | 144 | 145 | //================================================================================================= 146 | } 147 | 148 | #endif 149 | -------------------------------------------------------------------------------- /src/minisat-cpp/mtl/IntTypes.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************************[IntTypes.h] 2 | Copyright (c) 2009-2010, Niklas Sorensson 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 5 | associated documentation files (the "Software"), to deal in the Software without restriction, 6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 7 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or 11 | substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 14 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 16 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 17 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | **************************************************************************************************/ 19 | 20 | #ifndef Minisat_IntTypes_h 21 | #define Minisat_IntTypes_h 22 | 23 | #ifdef __sun 24 | // Not sure if there are newer versions that support C99 headers. The 25 | // needed features are implemented in the headers below though: 26 | 27 | # include 28 | # include 29 | # include 30 | 31 | #else 32 | 33 | # include 34 | # include 35 | 36 | #endif 37 | 38 | #include 39 | 40 | //================================================================================================= 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/minisat-cpp/mtl/Map.h: -------------------------------------------------------------------------------- 1 | /*******************************************************************************************[Map.h] 2 | Copyright (c) 2006-2010, Niklas Sorensson 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 5 | associated documentation files (the "Software"), to deal in the Software without restriction, 6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 7 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or 11 | substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 14 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 16 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 17 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | **************************************************************************************************/ 19 | 20 | #ifndef Minisat_Map_h 21 | #define Minisat_Map_h 22 | 23 | #include "mtl/IntTypes.h" 24 | #include "mtl/Vec.h" 25 | 26 | namespace Minisat { 27 | 28 | //================================================================================================= 29 | // Default hash/equals functions 30 | // 31 | 32 | template struct Hash { uint32_t operator()(const K& k) const { return hash(k); } }; 33 | template struct Equal { bool operator()(const K& k1, const K& k2) const { return k1 == k2; } }; 34 | 35 | template struct DeepHash { uint32_t operator()(const K* k) const { return hash(*k); } }; 36 | template struct DeepEqual { bool operator()(const K* k1, const K* k2) const { return *k1 == *k2; } }; 37 | 38 | static inline uint32_t hash(uint32_t x){ return x; } 39 | static inline uint32_t hash(uint64_t x){ return (uint32_t)x; } 40 | static inline uint32_t hash(int32_t x) { return (uint32_t)x; } 41 | static inline uint32_t hash(int64_t x) { return (uint32_t)x; } 42 | 43 | 44 | //================================================================================================= 45 | // Some primes 46 | // 47 | 48 | static const int nprimes = 25; 49 | static const int primes [nprimes] = { 31, 73, 151, 313, 643, 1291, 2593, 5233, 10501, 21013, 42073, 84181, 168451, 337219, 674701, 1349473, 2699299, 5398891, 10798093, 21596719, 43193641, 86387383, 172775299, 345550609, 691101253 }; 50 | 51 | //================================================================================================= 52 | // Hash table implementation of Maps 53 | // 54 | 55 | template, class E = Equal > 56 | class Map { 57 | public: 58 | struct Pair { K key; D data; }; 59 | 60 | private: 61 | H hash; 62 | E equals; 63 | 64 | vec* table; 65 | int cap; 66 | int size; 67 | 68 | // Don't allow copying (error prone): 69 | Map& operator = (Map& other) { assert(0); } 70 | Map (Map& other) { assert(0); } 71 | 72 | bool checkCap(int new_size) const { return new_size > cap; } 73 | 74 | int32_t index (const K& k) const { return hash(k) % cap; } 75 | void _insert (const K& k, const D& d) { 76 | vec& ps = table[index(k)]; 77 | ps.push(); ps.last().key = k; ps.last().data = d; } 78 | 79 | void rehash () { 80 | const vec* old = table; 81 | 82 | int old_cap = cap; 83 | int newsize = primes[0]; 84 | for (int i = 1; newsize <= cap && i < nprimes; i++) 85 | newsize = primes[i]; 86 | 87 | table = new vec[newsize]; 88 | cap = newsize; 89 | 90 | for (int i = 0; i < old_cap; i++){ 91 | for (int j = 0; j < old[i].size(); j++){ 92 | _insert(old[i][j].key, old[i][j].data); }} 93 | 94 | delete [] old; 95 | 96 | // printf(" --- rehashing, old-cap=%d, new-cap=%d\n", cap, newsize); 97 | } 98 | 99 | 100 | public: 101 | 102 | Map () : table(NULL), cap(0), size(0) {} 103 | Map (const H& h, const E& e) : hash(h), equals(e), table(NULL), cap(0), size(0){} 104 | ~Map () { delete [] table; } 105 | 106 | // PRECONDITION: the key must already exist in the map. 107 | const D& operator [] (const K& k) const 108 | { 109 | assert(size != 0); 110 | const D* res = NULL; 111 | const vec& ps = table[index(k)]; 112 | for (int i = 0; i < ps.size(); i++) 113 | if (equals(ps[i].key, k)) 114 | res = &ps[i].data; 115 | assert(res != NULL); 116 | return *res; 117 | } 118 | 119 | // PRECONDITION: the key must already exist in the map. 120 | D& operator [] (const K& k) 121 | { 122 | assert(size != 0); 123 | D* res = NULL; 124 | vec& ps = table[index(k)]; 125 | for (int i = 0; i < ps.size(); i++) 126 | if (equals(ps[i].key, k)) 127 | res = &ps[i].data; 128 | assert(res != NULL); 129 | return *res; 130 | } 131 | 132 | // PRECONDITION: the key must *NOT* exist in the map. 133 | void insert (const K& k, const D& d) { if (checkCap(size+1)) rehash(); _insert(k, d); size++; } 134 | bool peek (const K& k, D& d) const { 135 | if (size == 0) return false; 136 | const vec& ps = table[index(k)]; 137 | for (int i = 0; i < ps.size(); i++) 138 | if (equals(ps[i].key, k)){ 139 | d = ps[i].data; 140 | return true; } 141 | return false; 142 | } 143 | 144 | bool has (const K& k) const { 145 | if (size == 0) return false; 146 | const vec& ps = table[index(k)]; 147 | for (int i = 0; i < ps.size(); i++) 148 | if (equals(ps[i].key, k)) 149 | return true; 150 | return false; 151 | } 152 | 153 | // PRECONDITION: the key must exist in the map. 154 | void remove(const K& k) { 155 | assert(table != NULL); 156 | vec& ps = table[index(k)]; 157 | int j = 0; 158 | for (; j < ps.size() && !equals(ps[j].key, k); j++); 159 | assert(j < ps.size()); 160 | ps[j] = ps.last(); 161 | ps.pop(); 162 | size--; 163 | } 164 | 165 | void clear () { 166 | cap = size = 0; 167 | delete [] table; 168 | table = NULL; 169 | } 170 | 171 | int elems() const { return size; } 172 | int bucket_count() const { return cap; } 173 | 174 | // NOTE: the hash and equality objects are not moved by this method: 175 | void moveTo(Map& other){ 176 | delete [] other.table; 177 | 178 | other.table = table; 179 | other.cap = cap; 180 | other.size = size; 181 | 182 | table = NULL; 183 | size = cap = 0; 184 | } 185 | 186 | // NOTE: given a bit more time, I could make a more C++-style iterator out of this: 187 | const vec& bucket(int i) const { return table[i]; } 188 | }; 189 | 190 | //================================================================================================= 191 | } 192 | 193 | #endif 194 | -------------------------------------------------------------------------------- /src/minisat-cpp/mtl/Queue.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************************[Queue.h] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_Queue_h 22 | #define Minisat_Queue_h 23 | 24 | #include "mtl/Vec.h" 25 | 26 | namespace Minisat { 27 | 28 | //================================================================================================= 29 | 30 | template 31 | class Queue { 32 | vec buf; 33 | int first; 34 | int end; 35 | 36 | public: 37 | typedef T Key; 38 | 39 | Queue() : buf(1), first(0), end(0) {} 40 | 41 | void clear (bool dealloc = false) { buf.clear(dealloc); buf.growTo(1); first = end = 0; } 42 | int size () const { return (end >= first) ? end - first : end - first + buf.size(); } 43 | 44 | const T& operator [] (int index) const { assert(index >= 0); assert(index < size()); return buf[(first + index) % buf.size()]; } 45 | T& operator [] (int index) { assert(index >= 0); assert(index < size()); return buf[(first + index) % buf.size()]; } 46 | 47 | T peek () const { assert(first != end); return buf[first]; } 48 | void pop () { assert(first != end); first++; if (first == buf.size()) first = 0; } 49 | void insert(T elem) { // INVARIANT: buf[end] is always unused 50 | buf[end++] = elem; 51 | if (end == buf.size()) end = 0; 52 | if (first == end){ // Resize: 53 | vec tmp((buf.size()*3 + 1) >> 1); 54 | //**/printf("queue alloc: %d elems (%.1f MB)\n", tmp.size(), tmp.size() * sizeof(T) / 1000000.0); 55 | int i = 0; 56 | for (int j = first; j < buf.size(); j++) tmp[i++] = buf[j]; 57 | for (int j = 0 ; j < end ; j++) tmp[i++] = buf[j]; 58 | first = 0; 59 | end = buf.size(); 60 | tmp.moveTo(buf); 61 | } 62 | } 63 | }; 64 | 65 | 66 | //================================================================================================= 67 | } 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /src/minisat-cpp/mtl/Vec.h: -------------------------------------------------------------------------------- 1 | /*******************************************************************************************[Vec.h] 2 | Copyright (c) 2003-2007, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_Vec_h 22 | #define Minisat_Vec_h 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #include "mtl/IntTypes.h" 29 | #include "mtl/XAlloc.h" 30 | 31 | namespace Minisat { 32 | 33 | //================================================================================================= 34 | // Automatically resizable arrays 35 | // 36 | // NOTE! Don't use this vector on datatypes that cannot be re-located in memory (with realloc) 37 | 38 | template 39 | class vec { 40 | T* data; 41 | int sz; 42 | int cap; 43 | 44 | // Don't allow copying (error prone): 45 | vec& operator = (vec& other) { assert(0); return *this; } 46 | vec (vec& other) { assert(0); } 47 | 48 | // Helpers for calculating next capacity: 49 | static inline int imax (int x, int y) { int mask = (y-x) >> (sizeof(int)*8-1); return (x&mask) + (y&(~mask)); } 50 | //static inline void nextCap(int& cap){ cap += ((cap >> 1) + 2) & ~1; } 51 | static inline void nextCap(int& cap){ cap += ((cap >> 1) + 2) & ~1; } 52 | 53 | public: 54 | // Constructors: 55 | vec() : data(NULL) , sz(0) , cap(0) { } 56 | explicit vec(int size) : data(NULL) , sz(0) , cap(0) { growTo(size); } 57 | vec(int size, const T& pad) : data(NULL) , sz(0) , cap(0) { growTo(size, pad); } 58 | ~vec() { clear(true); } 59 | 60 | // Pointer to first element: 61 | operator T* (void) { return data; } 62 | 63 | // Size operations: 64 | int size (void) const { return sz; } 65 | void shrink (int nelems) { assert(nelems <= sz); for (int i = 0; i < nelems; i++) sz--, data[sz].~T(); } 66 | void shrink_ (int nelems) { assert(nelems <= sz); sz -= nelems; } 67 | int capacity (void) const { return cap; } 68 | void capacity (int min_cap); 69 | void growTo (int size); 70 | void growTo (int size, const T& pad); 71 | void clear (bool dealloc = false); 72 | 73 | // Stack interface: 74 | void push (void) { if (sz == cap) capacity(sz+1); new (&data[sz]) T(); sz++; } 75 | void push (const T& elem) { if (sz == cap) capacity(sz+1); data[sz++] = elem; } 76 | void push_ (const T& elem) { assert(sz < cap); data[sz++] = elem; } 77 | void pop (void) { assert(sz > 0); sz--, data[sz].~T(); } 78 | // NOTE: it seems possible that overflow can happen in the 'sz+1' expression of 'push()', but 79 | // in fact it can not since it requires that 'cap' is equal to INT_MAX. This in turn can not 80 | // happen given the way capacities are calculated (below). Essentially, all capacities are 81 | // even, but INT_MAX is odd. 82 | 83 | const T& last (void) const { return data[sz-1]; } 84 | T& last (void) { return data[sz-1]; } 85 | 86 | // Vector interface: 87 | const T& operator [] (int index) const { return data[index]; } 88 | T& operator [] (int index) { return data[index]; } 89 | 90 | // Duplicatation (preferred instead): 91 | void copyTo(vec& copy) const { copy.clear(); copy.growTo(sz); for (int i = 0; i < sz; i++) copy[i] = data[i]; } 92 | void moveTo(vec& dest) { dest.clear(true); dest.data = data; dest.sz = sz; dest.cap = cap; data = NULL; sz = 0; cap = 0; } 93 | 94 | inline void sort() { std::sort(data, data + sz); } 95 | 96 | template void sort(LessThan cmp) { 97 | std::sort(data, data + sz, cmp); 98 | } 99 | }; 100 | 101 | 102 | template 103 | void vec::capacity(int min_cap) { 104 | if (cap >= min_cap) return; 105 | int add = imax((min_cap - cap + 1) & ~1, ((cap >> 1) + 2) & ~1); // NOTE: grow by approximately 3/2 106 | if (add > INT_MAX - cap || ((data = (T*)::realloc(data, (cap += add) * sizeof(T))) == NULL) && errno == ENOMEM) 107 | throw OutOfMemoryException(); 108 | } 109 | 110 | 111 | template 112 | void vec::growTo(int size, const T& pad) { 113 | if (sz >= size) return; 114 | capacity(size); 115 | for (int i = sz; i < size; i++) data[i] = pad; 116 | sz = size; } 117 | 118 | 119 | template 120 | void vec::growTo(int size) { 121 | if (sz >= size) return; 122 | capacity(size); 123 | for (int i = sz; i < size; i++) new (&data[i]) T(); 124 | sz = size; } 125 | 126 | 127 | template 128 | void vec::clear(bool dealloc) { 129 | if (data != NULL){ 130 | for (int i = 0; i < sz; i++) data[i].~T(); 131 | sz = 0; 132 | if (dealloc) free(data), data = NULL, cap = 0; } } 133 | 134 | //================================================================================================= 135 | } // namespace Minisat 136 | 137 | #endif 138 | -------------------------------------------------------------------------------- /src/minisat-cpp/mtl/XAlloc.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************************[XAlloc.h] 2 | Copyright (c) 2009-2010, Niklas Sorensson 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 5 | associated documentation files (the "Software"), to deal in the Software without restriction, 6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 7 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or 11 | substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 14 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 16 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 17 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | **************************************************************************************************/ 19 | 20 | 21 | #ifndef Minisat_XAlloc_h 22 | #define Minisat_XAlloc_h 23 | 24 | #include 25 | #include 26 | 27 | namespace Minisat { 28 | 29 | //================================================================================================= 30 | // Simple layer on top of malloc/realloc to catch out-of-memory situtaions and provide some typing: 31 | 32 | class OutOfMemoryException{}; 33 | static inline void* xrealloc(void *ptr, size_t size) 34 | { 35 | void* mem = realloc(ptr, size); 36 | if (mem == NULL && errno == ENOMEM){ 37 | throw OutOfMemoryException(); 38 | }else 39 | return mem; 40 | } 41 | 42 | //================================================================================================= 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/minisat-cpp/mtl/config.mk: -------------------------------------------------------------------------------- 1 | ## 2 | ## This file is for system specific configurations. For instance, on 3 | ## some systems the path to zlib needs to be added. Example: 4 | ## 5 | ## CFLAGS += -I/usr/local/include 6 | ## LFLAGS += -L/usr/local/lib 7 | -------------------------------------------------------------------------------- /src/minisat-cpp/mtl/template.mk: -------------------------------------------------------------------------------- 1 | ## 2 | ## Template makefile for Standard, Profile, Debug, Release, and Release-static versions 3 | ## 4 | ## eg: "make rs" for a statically linked release version. 5 | ## "make d" for a debug version (no optimizations). 6 | ## "make" for the standard version (optimized, but with debug information and assertions active) 7 | 8 | PWD = $(shell pwd) 9 | EXEC ?= $(notdir $(PWD)) 10 | 11 | CSRCS = $(wildcard $(PWD)/*.cc) 12 | DSRCS = $(foreach dir, $(DEPDIR), $(filter-out $(MROOT)/$(dir)/Main.cc, $(wildcard $(MROOT)/$(dir)/*.cc))) 13 | CHDRS = $(wildcard $(PWD)/*.h) 14 | COBJS = $(CSRCS:.cc=.o) $(DSRCS:.cc=.o) 15 | 16 | PCOBJS = $(addsuffix p, $(COBJS)) 17 | DCOBJS = $(addsuffix d, $(COBJS)) 18 | RCOBJS = $(addsuffix r, $(COBJS)) 19 | 20 | 21 | CXX ?= g++ 22 | CFLAGS ?= -Wall -Wno-parentheses 23 | LFLAGS ?= -Wall 24 | 25 | COPTIMIZE ?= -O3 26 | 27 | CFLAGS += -I$(MROOT) -D __STDC_LIMIT_MACROS -D __STDC_FORMAT_MACROS 28 | LFLAGS += -lz 29 | 30 | .PHONY : s p d r rs clean 31 | 32 | s: $(EXEC) 33 | p: $(EXEC)_profile 34 | d: $(EXEC)_debug 35 | r: $(EXEC)_release 36 | rs: $(EXEC)_static 37 | 38 | libs: lib$(LIB)_standard.a 39 | libp: lib$(LIB)_profile.a 40 | libd: lib$(LIB)_debug.a 41 | libr: lib$(LIB)_release.a 42 | 43 | ## Compile options 44 | %.o: CFLAGS +=$(COPTIMIZE) -g -D DEBUG 45 | %.op: CFLAGS +=$(COPTIMIZE) -pg -g -D NDEBUG 46 | %.od: CFLAGS +=-O0 -g -D DEBUG 47 | %.or: CFLAGS +=$(COPTIMIZE) -g -D NDEBUG 48 | 49 | ## Link options 50 | $(EXEC): LFLAGS += -g 51 | $(EXEC)_profile: LFLAGS += -g -pg 52 | $(EXEC)_debug: LFLAGS += -g 53 | #$(EXEC)_release: LFLAGS += ... 54 | $(EXEC)_static: LFLAGS += --static 55 | 56 | ## Dependencies 57 | $(EXEC): $(COBJS) 58 | $(EXEC)_profile: $(PCOBJS) 59 | $(EXEC)_debug: $(DCOBJS) 60 | $(EXEC)_release: $(RCOBJS) 61 | $(EXEC)_static: $(RCOBJS) 62 | 63 | lib$(LIB)_standard.a: $(filter-out */Main.o, $(COBJS)) 64 | lib$(LIB)_profile.a: $(filter-out */Main.op, $(PCOBJS)) 65 | lib$(LIB)_debug.a: $(filter-out */Main.od, $(DCOBJS)) 66 | lib$(LIB)_release.a: $(filter-out */Main.or, $(RCOBJS)) 67 | 68 | 69 | ## Build rule 70 | %.o %.op %.od %.or: %.cc 71 | @echo Compiling: $(subst $(MROOT)/,,$@) 72 | @$(CXX) $(CFLAGS) -c -o $@ $< 73 | 74 | ## Linking rules (standard/profile/debug/release) 75 | $(EXEC) $(EXEC)_profile $(EXEC)_debug $(EXEC)_release $(EXEC)_static: 76 | @echo Linking: "$@ ( $(foreach f,$^,$(subst $(MROOT)/,,$f)) )" 77 | @$(CXX) $^ $(LFLAGS) -o $@ 78 | 79 | ## Library rules (standard/profile/debug/release) 80 | lib$(LIB)_standard.a lib$(LIB)_profile.a lib$(LIB)_release.a lib$(LIB)_debug.a: 81 | @echo Making library: "$@ ( $(foreach f,$^,$(subst $(MROOT)/,,$f)) )" 82 | @$(AR) -rcsv $@ $^ 83 | 84 | ## Library Soft Link rule: 85 | libs libp libd libr: 86 | @echo "Making Soft Link: $^ -> lib$(LIB).a" 87 | @ln -sf $^ lib$(LIB).a 88 | 89 | ## Clean rule 90 | clean: 91 | @rm -f $(EXEC) $(EXEC)_profile $(EXEC)_debug $(EXEC)_release $(EXEC)_static \ 92 | $(COBJS) $(PCOBJS) $(DCOBJS) $(RCOBJS) *.core depend.mk 93 | 94 | ## Make dependencies 95 | depend.mk: $(CSRCS) $(CHDRS) 96 | @echo Making dependencies 97 | @$(CXX) $(CFLAGS) -I$(MROOT) \ 98 | $(CSRCS) -MM | sed 's|\(.*\):|$(PWD)/\1 $(PWD)/\1r $(PWD)/\1d $(PWD)/\1p:|' > depend.mk 99 | @for dir in $(DEPDIR); do \ 100 | if [ -r $(MROOT)/$${dir}/depend.mk ]; then \ 101 | echo Depends on: $${dir}; \ 102 | cat $(MROOT)/$${dir}/depend.mk >> depend.mk; \ 103 | fi; \ 104 | done 105 | 106 | -include $(MROOT)/mtl/config.mk 107 | -include depend.mk 108 | -------------------------------------------------------------------------------- /src/minisat-cpp/simp/Main.cc: -------------------------------------------------------------------------------- 1 | /*****************************************************************************************[Main.cc] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | 27 | #include "utils/System.h" 28 | #include "utils/ParseUtils.h" 29 | #include "utils/Options.h" 30 | #include "core/Dimacs.h" 31 | #include "simp/SimpSolver.h" 32 | 33 | using namespace Minisat; 34 | 35 | //================================================================================================= 36 | 37 | 38 | void printStats(Solver& solver) 39 | { 40 | double cpu_time = cpuTime(); 41 | double mem_used = memUsedPeak(); 42 | printf("restarts : %lu\n", solver.starts); 43 | printf("conflicts : %-12lu (%.0f /sec)\n", solver.conflicts , solver.conflicts /cpu_time); 44 | printf("decisions : %-12lu (%4.2f %% random) (%.0f /sec)\n", solver.decisions, (float)solver.rnd_decisions*100 / (float)solver.decisions, solver.decisions /cpu_time); 45 | printf("propagations : %-12lu (%.0f /sec)\n", solver.propagations, solver.propagations/cpu_time); 46 | printf("conflict literals : %-12lu (%4.2f %% deleted)\n", solver.tot_literals, (solver.max_literals - solver.tot_literals)*100 / (double)solver.max_literals); 47 | if (mem_used != 0) printf("Memory used : %.2f MB\n", mem_used); 48 | printf("CPU time : %g s\n", cpu_time); 49 | } 50 | 51 | 52 | static Solver* solver; 53 | // Terminate by notifying the solver and back out gracefully. This is mainly to have a test-case 54 | // for this feature of the Solver as it may take longer than an immediate call to '_exit()'. 55 | static void SIGINT_interrupt(int signum) { solver->interrupt(); } 56 | 57 | // Note that '_exit()' rather than 'exit()' has to be used. The reason is that 'exit()' calls 58 | // destructors and may cause deadlocks if a malloc/free function happens to be running (these 59 | // functions are guarded by locks for multithreaded use). 60 | static void SIGINT_exit(int signum) { 61 | printf("\n"); printf("*** INTERRUPTED ***\n"); 62 | if (solver->verbosity > 0){ 63 | printStats(*solver); 64 | printf("\n"); printf("*** INTERRUPTED ***\n"); } 65 | _exit(1); } 66 | 67 | 68 | //================================================================================================= 69 | // Main: 70 | 71 | int main(int argc, char** argv) 72 | { 73 | try { 74 | setUsageHelp("USAGE: %s [options] \n\n where input may be either in plain or gzipped DIMACS.\n"); 75 | // printf("This is MiniSat 2.0 beta\n"); 76 | 77 | #if defined(__linux__) 78 | fpu_control_t oldcw, newcw; 79 | _FPU_GETCW(oldcw); newcw = (oldcw & ~_FPU_EXTENDED) | _FPU_DOUBLE; _FPU_SETCW(newcw); 80 | printf("WARNING: for repeatability, setting FPU to use double precision\n"); 81 | #endif 82 | // Extra options: 83 | // 84 | IntOption verb ("MAIN", "verb", "Verbosity level (0=silent, 1=some, 2=more).", 1, IntRange(0, 2)); 85 | BoolOption pre ("MAIN", "pre", "Completely turn on/off any preprocessing.", true); 86 | StringOption dimacs ("MAIN", "dimacs", "If given, stop after preprocessing and write the result to this file."); 87 | IntOption cpu_lim("MAIN", "cpu-lim","Limit on CPU time allowed in seconds.\n", INT32_MAX, IntRange(0, INT32_MAX)); 88 | IntOption mem_lim("MAIN", "mem-lim","Limit on memory usage in megabytes.\n", INT32_MAX, IntRange(0, INT32_MAX)); 89 | 90 | parseOptions(argc, argv, true); 91 | 92 | SimpSolver S; 93 | double initial_time = cpuTime(); 94 | 95 | if (!pre) S.eliminate(true); 96 | 97 | S.verbosity = verb; 98 | 99 | solver = &S; 100 | // Use signal handlers that forcibly quit until the solver will be able to respond to 101 | // interrupts: 102 | signal(SIGINT, SIGINT_exit); 103 | signal(SIGXCPU,SIGINT_exit); 104 | 105 | // Set limit on CPU-time: 106 | if (cpu_lim != INT32_MAX){ 107 | rlimit rl; 108 | getrlimit(RLIMIT_CPU, &rl); 109 | if (rl.rlim_max == RLIM_INFINITY || (rlim_t)cpu_lim < rl.rlim_max){ 110 | rl.rlim_cur = cpu_lim; 111 | if (setrlimit(RLIMIT_CPU, &rl) == -1) 112 | printf("WARNING! Could not set resource limit: CPU-time.\n"); 113 | } } 114 | 115 | // Set limit on virtual memory: 116 | if (mem_lim != INT32_MAX){ 117 | rlim_t new_mem_lim = (rlim_t)mem_lim * 1024*1024; 118 | rlimit rl; 119 | getrlimit(RLIMIT_AS, &rl); 120 | if (rl.rlim_max == RLIM_INFINITY || new_mem_lim < rl.rlim_max){ 121 | rl.rlim_cur = new_mem_lim; 122 | if (setrlimit(RLIMIT_AS, &rl) == -1) 123 | printf("WARNING! Could not set resource limit: Virtual memory.\n"); 124 | } } 125 | 126 | if (argc == 1) 127 | printf("Reading from standard input... Use '--help' for help.\n"); 128 | 129 | gzFile in = (argc == 1) ? gzdopen(0, "rb") : gzopen(argv[1], "rb"); 130 | if (in == NULL) 131 | printf("ERROR! Could not open file: %s\n", argc == 1 ? "" : argv[1]), exit(1); 132 | 133 | if (S.verbosity > 0){ 134 | printf("============================[ Problem Statistics ]=============================\n"); 135 | printf("| |\n"); } 136 | 137 | parse_DIMACS(in, S); 138 | gzclose(in); 139 | FILE* res = (argc >= 3) ? fopen(argv[2], "wb") : NULL; 140 | 141 | if (S.verbosity > 0){ 142 | printf("| Number of variables: %12d |\n", S.nVars()); 143 | printf("| Number of clauses: %12d |\n", S.nClauses()); } 144 | 145 | double parsed_time = cpuTime(); 146 | if (S.verbosity > 0) 147 | printf("| Parse time: %12.2f s |\n", parsed_time - initial_time); 148 | 149 | // Change to signal-handlers that will only notify the solver and allow it to terminate 150 | // voluntarily: 151 | signal(SIGINT, SIGINT_interrupt); 152 | signal(SIGXCPU,SIGINT_interrupt); 153 | 154 | S.eliminate(true); 155 | double simplified_time = cpuTime(); 156 | if (S.verbosity > 0){ 157 | printf("| Simplification time: %12.2f s |\n", simplified_time - parsed_time); 158 | printf("| |\n"); } 159 | 160 | if (!S.okay()){ 161 | if (res != NULL) fprintf(res, "UNSAT\n"), fclose(res); 162 | if (S.verbosity > 0){ 163 | printf("===============================================================================\n"); 164 | printf("Solved by simplification\n"); 165 | printStats(S); 166 | printf("\n"); } 167 | printf("UNSATISFIABLE\n"); 168 | exit(20); 169 | } 170 | 171 | if (dimacs){ 172 | if (S.verbosity > 0) 173 | printf("==============================[ Writing DIMACS ]===============================\n"); 174 | S.toDimacs((const char*)dimacs); 175 | if (S.verbosity > 0) 176 | printStats(S); 177 | exit(0); 178 | } 179 | 180 | vec dummy; 181 | lbool ret = S.solveLimited(dummy); 182 | 183 | if (S.verbosity > 0){ 184 | printStats(S); 185 | printf("\n"); } 186 | printf(ret == l_True ? "SATISFIABLE\n" : ret == l_False ? "UNSATISFIABLE\n" : "INDETERMINATE\n"); 187 | if (res != NULL){ 188 | if (ret == l_True){ 189 | fprintf(res, "SAT\n"); 190 | for (int i = 0; i < S.nVars(); i++) 191 | if (S.model[i] != l_Undef) 192 | fprintf(res, "%s%s%d", (i==0)?"":" ", (S.model[i]==l_True)?"":"-", i+1); 193 | fprintf(res, " 0\n"); 194 | }else if (ret == l_False) 195 | fprintf(res, "UNSAT\n"); 196 | else 197 | fprintf(res, "INDET\n"); 198 | fclose(res); 199 | } 200 | 201 | #ifdef NDEBUG 202 | exit(ret == l_True ? 10 : ret == l_False ? 20 : 0); // (faster than "return", which will invoke the destructor for 'Solver') 203 | #else 204 | return (ret == l_True ? 10 : ret == l_False ? 20 : 0); 205 | #endif 206 | } catch (OutOfMemoryException&){ 207 | printf("===============================================================================\n"); 208 | printf("INDETERMINATE\n"); 209 | exit(0); 210 | } 211 | } 212 | -------------------------------------------------------------------------------- /src/minisat-cpp/simp/Makefile: -------------------------------------------------------------------------------- 1 | EXEC = minisat 2 | DEPDIR = mtl utils core 3 | 4 | include $(MROOT)/mtl/template.mk 5 | -------------------------------------------------------------------------------- /src/minisat-cpp/simp/SimpSolver.cc: -------------------------------------------------------------------------------- 1 | /***********************************************************************************[SimpSolver.cc] 2 | Copyright (c) 2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #include "mtl/Sort.h" 22 | #include "simp/SimpSolver.h" 23 | #include "utils/System.h" 24 | 25 | using namespace Minisat; 26 | 27 | //================================================================================================= 28 | // Options: 29 | 30 | 31 | static const char* _cat = "SIMP"; 32 | 33 | static BoolOption opt_use_asymm (_cat, "asymm", "Shrink clauses by asymmetric branching.", false); 34 | static BoolOption opt_use_rcheck (_cat, "rcheck", "Check if a clause is already implied. (costly)", false); 35 | static BoolOption opt_use_elim (_cat, "elim", "Perform variable elimination.", true); 36 | static IntOption opt_grow (_cat, "grow", "Allow a variable elimination step to grow by a number of clauses.", 0); 37 | static IntOption opt_clause_lim (_cat, "cl-lim", "Variables are not eliminated if it produces a resolvent with a length above this limit. -1 means no limit", 20, IntRange(-1, INT32_MAX)); 38 | static IntOption opt_subsumption_lim (_cat, "sub-lim", "Do not check if subsumption against a clause larger than this. -1 means no limit.", 1000, IntRange(-1, INT32_MAX)); 39 | static DoubleOption opt_simp_garbage_frac(_cat, "simp-gc-frac", "The fraction of wasted memory allowed before a garbage collection is triggered during simplification.", 0.5, DoubleRange(0, false, HUGE_VAL, false)); 40 | 41 | 42 | //================================================================================================= 43 | // Constructor/Destructor: 44 | 45 | 46 | SimpSolver::SimpSolver() : 47 | grow (opt_grow) 48 | , clause_lim (opt_clause_lim) 49 | , subsumption_lim (opt_subsumption_lim) 50 | , simp_garbage_frac (opt_simp_garbage_frac) 51 | , use_asymm (opt_use_asymm) 52 | , use_rcheck (opt_use_rcheck) 53 | , use_elim (opt_use_elim) 54 | , merges (0) 55 | , asymm_lits (0) 56 | , eliminated_vars (0) 57 | , elimorder (1) 58 | , use_simplification (true) 59 | , occurs (ClauseDeleted(ca)) 60 | , elim_heap (ElimLt(n_occ)) 61 | , bwdsub_assigns (0) 62 | , n_touched (0) 63 | { 64 | vec dummy(1,lit_Undef); 65 | ca.extra_clause_field = true; // NOTE: must happen before allocating the dummy clause below. 66 | bwdsub_tmpunit = ca.alloc(dummy); 67 | remove_satisfied = false; 68 | } 69 | 70 | 71 | SimpSolver::~SimpSolver() 72 | { 73 | } 74 | 75 | 76 | Var SimpSolver::newVar(bool sign, bool dvar) { 77 | Var v = Solver::newVar(sign, dvar); 78 | 79 | frozen .push((char)false); 80 | eliminated.push((char)false); 81 | 82 | if (use_simplification){ 83 | n_occ .push(0); 84 | n_occ .push(0); 85 | occurs .init(v); 86 | touched .push(0); 87 | elim_heap .insert(v); 88 | } 89 | return v; } 90 | 91 | 92 | 93 | lbool SimpSolver::solve_(bool do_simp, bool turn_off_simp) 94 | { 95 | vec extra_frozen; 96 | lbool result = l_True; 97 | 98 | do_simp &= use_simplification; 99 | 100 | if (do_simp){ 101 | // Assumptions must be temporarily frozen to run variable elimination: 102 | for (int i = 0; i < assumptions.size(); i++){ 103 | Var v = var(assumptions[i]); 104 | 105 | // If an assumption has been eliminated, remember it. 106 | assert(!isEliminated(v)); 107 | 108 | if (!frozen[v]){ 109 | // Freeze and store. 110 | setFrozen(v, true); 111 | extra_frozen.push(v); 112 | } } 113 | 114 | result = lbool(eliminate(turn_off_simp)); 115 | } 116 | 117 | if (result == l_True) 118 | result = Solver::solve_(); 119 | else if (verbosity >= 1) 120 | printf("===============================================================================\n"); 121 | 122 | if (result == l_True) 123 | extendModel(); 124 | 125 | if (do_simp) 126 | // Unfreeze the assumptions that were frozen: 127 | for (int i = 0; i < extra_frozen.size(); i++) 128 | setFrozen(extra_frozen[i], false); 129 | 130 | return result; 131 | } 132 | 133 | 134 | 135 | bool SimpSolver::addClause_(vec& ps) 136 | { 137 | #ifndef NDEBUG 138 | for (int i = 0; i < ps.size(); i++) 139 | assert(!isEliminated(var(ps[i]))); 140 | #endif 141 | 142 | int nclauses = clauses.size(); 143 | 144 | if (use_rcheck && implied(ps)) 145 | return true; 146 | 147 | if (!Solver::addClause_(ps)) 148 | return false; 149 | 150 | if (use_simplification && clauses.size() == nclauses + 1){ 151 | CRef cr = clauses.last(); 152 | const Clause& c = ca[cr]; 153 | 154 | // NOTE: the clause is added to the queue immediately and then 155 | // again during 'gatherTouchedClauses()'. If nothing happens 156 | // in between, it will only be checked once. Otherwise, it may 157 | // be checked twice unnecessarily. This is an unfortunate 158 | // consequence of how backward subsumption is used to mimic 159 | // forward subsumption. 160 | subsumption_queue.insert(cr); 161 | for (int i = 0; i < c.size(); i++){ 162 | occurs[var(c[i])].push(cr); 163 | n_occ[toInt(c[i])]++; 164 | touched[var(c[i])] = 1; 165 | n_touched++; 166 | if (elim_heap.inHeap(var(c[i]))) 167 | elim_heap.increase(var(c[i])); 168 | } 169 | } 170 | 171 | return true; 172 | } 173 | 174 | 175 | void SimpSolver::removeClause(CRef cr) 176 | { 177 | const Clause& c = ca[cr]; 178 | 179 | if (use_simplification) 180 | for (int i = 0; i < c.size(); i++){ 181 | n_occ[toInt(c[i])]--; 182 | updateElimHeap(var(c[i])); 183 | occurs.smudge(var(c[i])); 184 | } 185 | 186 | Solver::removeClause(cr); 187 | } 188 | 189 | 190 | bool SimpSolver::strengthenClause(CRef cr, Lit l) 191 | { 192 | Clause& c = ca[cr]; 193 | assert(decisionLevel() == 0); 194 | assert(use_simplification); 195 | 196 | // FIX: this is too inefficient but would be nice to have (properly implemented) 197 | // if (!find(subsumption_queue, &c)) 198 | subsumption_queue.insert(cr); 199 | 200 | if (c.size() == 2){ 201 | removeClause(cr); 202 | c.strengthen(l); 203 | }else{ 204 | detachClause(cr, true); 205 | c.strengthen(l); 206 | attachClause(cr); 207 | remove(occurs[var(l)], cr); 208 | n_occ[toInt(l)]--; 209 | updateElimHeap(var(l)); 210 | } 211 | 212 | return c.size() == 1 ? enqueue(c[0]) && propagate() == CRef_Undef : true; 213 | } 214 | 215 | 216 | // Returns FALSE if clause is always satisfied ('out_clause' should not be used). 217 | bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, vec& out_clause) 218 | { 219 | merges++; 220 | out_clause.clear(); 221 | 222 | bool ps_smallest = _ps.size() < _qs.size(); 223 | const Clause& ps = ps_smallest ? _qs : _ps; 224 | const Clause& qs = ps_smallest ? _ps : _qs; 225 | 226 | for (int i = 0; i < qs.size(); i++){ 227 | if (var(qs[i]) != v){ 228 | for (int j = 0; j < ps.size(); j++) 229 | if (var(ps[j]) == var(qs[i])) 230 | if (ps[j] == ~qs[i]) 231 | return false; 232 | else 233 | goto next; 234 | out_clause.push(qs[i]); 235 | } 236 | next:; 237 | } 238 | 239 | for (int i = 0; i < ps.size(); i++) 240 | if (var(ps[i]) != v) 241 | out_clause.push(ps[i]); 242 | 243 | return true; 244 | } 245 | 246 | 247 | // Returns FALSE if clause is always satisfied. 248 | bool SimpSolver::merge(const Clause& _ps, const Clause& _qs, Var v, int& size) 249 | { 250 | merges++; 251 | 252 | bool ps_smallest = _ps.size() < _qs.size(); 253 | const Clause& ps = ps_smallest ? _qs : _ps; 254 | const Clause& qs = ps_smallest ? _ps : _qs; 255 | const Lit* __ps = (const Lit*)ps; 256 | const Lit* __qs = (const Lit*)qs; 257 | 258 | size = ps.size()-1; 259 | 260 | for (int i = 0; i < qs.size(); i++){ 261 | if (var(__qs[i]) != v){ 262 | for (int j = 0; j < ps.size(); j++) 263 | if (var(__ps[j]) == var(__qs[i])) 264 | if (__ps[j] == ~__qs[i]) 265 | return false; 266 | else 267 | goto next; 268 | size++; 269 | } 270 | next:; 271 | } 272 | 273 | return true; 274 | } 275 | 276 | 277 | void SimpSolver::gatherTouchedClauses() 278 | { 279 | if (n_touched == 0) return; 280 | 281 | int i,j; 282 | for (i = j = 0; i < subsumption_queue.size(); i++) 283 | if (ca[subsumption_queue[i]].mark() == 0) 284 | ca[subsumption_queue[i]].mark(2); 285 | 286 | for (i = 0; i < touched.size(); i++) 287 | if (touched[i]){ 288 | const vec& cs = occurs.lookup(i); 289 | for (j = 0; j < cs.size(); j++) 290 | if (ca[cs[j]].mark() == 0){ 291 | subsumption_queue.insert(cs[j]); 292 | ca[cs[j]].mark(2); 293 | } 294 | touched[i] = 0; 295 | } 296 | 297 | for (i = 0; i < subsumption_queue.size(); i++) 298 | if (ca[subsumption_queue[i]].mark() == 2) 299 | ca[subsumption_queue[i]].mark(0); 300 | 301 | n_touched = 0; 302 | } 303 | 304 | 305 | bool SimpSolver::implied(const vec& c) 306 | { 307 | assert(decisionLevel() == 0); 308 | 309 | trail_lim.push(trail.size()); 310 | for (int i = 0; i < c.size(); i++) 311 | if (value(c[i]) == l_True){ 312 | cancelUntil(0); 313 | return false; 314 | }else if (value(c[i]) != l_False){ 315 | assert(value(c[i]) == l_Undef); 316 | uncheckedEnqueue(~c[i]); 317 | } 318 | 319 | bool result = propagate() != CRef_Undef; 320 | cancelUntil(0); 321 | return result; 322 | } 323 | 324 | 325 | // Backward subsumption + backward subsumption resolution 326 | bool SimpSolver::backwardSubsumptionCheck(bool verbose) 327 | { 328 | int cnt = 0; 329 | int subsumed = 0; 330 | int deleted_literals = 0; 331 | assert(decisionLevel() == 0); 332 | 333 | while (subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()){ 334 | 335 | // Empty subsumption queue and return immediately on user-interrupt: 336 | if (asynch_interrupt){ 337 | subsumption_queue.clear(); 338 | bwdsub_assigns = trail.size(); 339 | break; } 340 | 341 | // Check top-level assignments by creating a dummy clause and placing it in the queue: 342 | if (subsumption_queue.size() == 0 && bwdsub_assigns < trail.size()){ 343 | Lit l = trail[bwdsub_assigns++]; 344 | ca[bwdsub_tmpunit][0] = l; 345 | ca[bwdsub_tmpunit].calcAbstraction(); 346 | subsumption_queue.insert(bwdsub_tmpunit); } 347 | 348 | CRef cr = subsumption_queue.peek(); subsumption_queue.pop(); 349 | Clause& c = ca[cr]; 350 | 351 | if (c.mark()) continue; 352 | 353 | if (verbose && verbosity >= 2 && cnt++ % 1000 == 0) 354 | printf("subsumption left: %10d (%10d subsumed, %10d deleted literals)\r", subsumption_queue.size(), subsumed, deleted_literals); 355 | 356 | assert(c.size() > 1 || value(c[0]) == l_True); // Unit-clauses should have been propagated before this point. 357 | 358 | // Find best variable to scan: 359 | Var best = var(c[0]); 360 | for (int i = 1; i < c.size(); i++) 361 | if (occurs[var(c[i])].size() < occurs[best].size()) 362 | best = var(c[i]); 363 | 364 | // Search all candidates: 365 | vec& _cs = occurs.lookup(best); 366 | CRef* cs = (CRef*)_cs; 367 | 368 | for (int j = 0; j < _cs.size(); j++) 369 | if (c.mark()) 370 | break; 371 | else if (!ca[cs[j]].mark() && cs[j] != cr && (subsumption_lim == -1 || ca[cs[j]].size() < subsumption_lim)){ 372 | Lit l = c.subsumes(ca[cs[j]]); 373 | 374 | if (l == lit_Undef) 375 | subsumed++, removeClause(cs[j]); 376 | else if (l != lit_Error){ 377 | deleted_literals++; 378 | 379 | if (!strengthenClause(cs[j], ~l)) 380 | return false; 381 | 382 | // Did current candidate get deleted from cs? Then check candidate at index j again: 383 | if (var(l) == best) 384 | j--; 385 | } 386 | } 387 | } 388 | 389 | return true; 390 | } 391 | 392 | 393 | bool SimpSolver::asymm(Var v, CRef cr) 394 | { 395 | Clause& c = ca[cr]; 396 | assert(decisionLevel() == 0); 397 | 398 | if (c.mark() || satisfied(c)) return true; 399 | 400 | trail_lim.push(trail.size()); 401 | Lit l = lit_Undef; 402 | for (int i = 0; i < c.size(); i++) 403 | if (var(c[i]) != v && value(c[i]) != l_False) 404 | uncheckedEnqueue(~c[i]); 405 | else 406 | l = c[i]; 407 | 408 | if (propagate() != CRef_Undef){ 409 | cancelUntil(0); 410 | asymm_lits++; 411 | if (!strengthenClause(cr, l)) 412 | return false; 413 | }else 414 | cancelUntil(0); 415 | 416 | return true; 417 | } 418 | 419 | 420 | bool SimpSolver::asymmVar(Var v) 421 | { 422 | assert(use_simplification); 423 | 424 | const vec& cls = occurs.lookup(v); 425 | 426 | if (value(v) != l_Undef || cls.size() == 0) 427 | return true; 428 | 429 | for (int i = 0; i < cls.size(); i++) 430 | if (!asymm(v, cls[i])) 431 | return false; 432 | 433 | return backwardSubsumptionCheck(); 434 | } 435 | 436 | 437 | static void mkElimClause(vec& elimclauses, Lit x) 438 | { 439 | elimclauses.push(toInt(x)); 440 | elimclauses.push(1); 441 | } 442 | 443 | 444 | static void mkElimClause(vec& elimclauses, Var v, Clause& c) 445 | { 446 | int first = elimclauses.size(); 447 | int v_pos = -1; 448 | 449 | // Copy clause to elimclauses-vector. Remember position where the 450 | // variable 'v' occurs: 451 | for (int i = 0; i < c.size(); i++){ 452 | elimclauses.push(toInt(c[i])); 453 | if (var(c[i]) == v) 454 | v_pos = i + first; 455 | } 456 | assert(v_pos != -1); 457 | 458 | // Swap the first literal with the 'v' literal, so that the literal 459 | // containing 'v' will occur first in the clause: 460 | uint32_t tmp = elimclauses[v_pos]; 461 | elimclauses[v_pos] = elimclauses[first]; 462 | elimclauses[first] = tmp; 463 | 464 | // Store the length of the clause last: 465 | elimclauses.push(c.size()); 466 | } 467 | 468 | 469 | 470 | bool SimpSolver::eliminateVar(Var v) 471 | { 472 | assert(!frozen[v]); 473 | assert(!isEliminated(v)); 474 | assert(value(v) == l_Undef); 475 | 476 | // Split the occurrences into positive and negative: 477 | // 478 | const vec& cls = occurs.lookup(v); 479 | vec pos, neg; 480 | for (int i = 0; i < cls.size(); i++) 481 | (find(ca[cls[i]], mkLit(v)) ? pos : neg).push(cls[i]); 482 | 483 | // Check wether the increase in number of clauses stays within the allowed ('grow'). Moreover, no 484 | // clause must exceed the limit on the maximal clause size (if it is set): 485 | // 486 | int cnt = 0; 487 | int clause_size = 0; 488 | 489 | for (int i = 0; i < pos.size(); i++) 490 | for (int j = 0; j < neg.size(); j++) 491 | if (merge(ca[pos[i]], ca[neg[j]], v, clause_size) && 492 | (++cnt > cls.size() + grow || (clause_lim != -1 && clause_size > clause_lim))) 493 | return true; 494 | 495 | // Delete and store old clauses: 496 | eliminated[v] = true; 497 | setDecisionVar(v, false); 498 | eliminated_vars++; 499 | 500 | if (pos.size() > neg.size()){ 501 | for (int i = 0; i < neg.size(); i++) 502 | mkElimClause(elimclauses, v, ca[neg[i]]); 503 | mkElimClause(elimclauses, mkLit(v)); 504 | }else{ 505 | for (int i = 0; i < pos.size(); i++) 506 | mkElimClause(elimclauses, v, ca[pos[i]]); 507 | mkElimClause(elimclauses, ~mkLit(v)); 508 | } 509 | 510 | for (int i = 0; i < cls.size(); i++) 511 | removeClause(cls[i]); 512 | 513 | // Produce clauses in cross product: 514 | vec& resolvent = add_tmp; 515 | for (int i = 0; i < pos.size(); i++) 516 | for (int j = 0; j < neg.size(); j++) 517 | if (merge(ca[pos[i]], ca[neg[j]], v, resolvent) && !addClause_(resolvent)) 518 | return false; 519 | 520 | // Free occurs list for this variable: 521 | occurs[v].clear(true); 522 | 523 | // Free watchers lists for this variable, if possible: 524 | if (watches[ mkLit(v)].size() == 0) watches[ mkLit(v)].clear(true); 525 | if (watches[~mkLit(v)].size() == 0) watches[~mkLit(v)].clear(true); 526 | 527 | return backwardSubsumptionCheck(); 528 | } 529 | 530 | 531 | bool SimpSolver::substitute(Var v, Lit x) 532 | { 533 | assert(!frozen[v]); 534 | assert(!isEliminated(v)); 535 | assert(value(v) == l_Undef); 536 | 537 | if (!ok) return false; 538 | 539 | eliminated[v] = true; 540 | setDecisionVar(v, false); 541 | const vec& cls = occurs.lookup(v); 542 | 543 | vec& subst_clause = add_tmp; 544 | for (int i = 0; i < cls.size(); i++){ 545 | Clause& c = ca[cls[i]]; 546 | 547 | subst_clause.clear(); 548 | for (int j = 0; j < c.size(); j++){ 549 | Lit p = c[j]; 550 | subst_clause.push(var(p) == v ? x ^ sign(p) : p); 551 | } 552 | 553 | removeClause(cls[i]); 554 | 555 | if (!addClause_(subst_clause)) 556 | return ok = false; 557 | } 558 | 559 | return true; 560 | } 561 | 562 | 563 | void SimpSolver::extendModel() 564 | { 565 | int i, j; 566 | Lit x; 567 | 568 | for (i = elimclauses.size()-1; i > 0; i -= j){ 569 | for (j = elimclauses[i--]; j > 1; j--, i--) 570 | if (modelValue(toLit(elimclauses[i])) != l_False) 571 | goto next; 572 | 573 | x = toLit(elimclauses[i]); 574 | model[var(x)] = lbool(!sign(x)); 575 | next:; 576 | } 577 | } 578 | 579 | 580 | bool SimpSolver::eliminate(bool turn_off_elim) 581 | { 582 | if (!simplify()) 583 | return false; 584 | else if (!use_simplification) 585 | return true; 586 | 587 | // Main simplification loop: 588 | // 589 | while (n_touched > 0 || bwdsub_assigns < trail.size() || elim_heap.size() > 0){ 590 | 591 | gatherTouchedClauses(); 592 | // printf(" ## (time = %6.2f s) BWD-SUB: queue = %d, trail = %d\n", cpuTime(), subsumption_queue.size(), trail.size() - bwdsub_assigns); 593 | if ((subsumption_queue.size() > 0 || bwdsub_assigns < trail.size()) && 594 | !backwardSubsumptionCheck(true)){ 595 | ok = false; goto cleanup; } 596 | 597 | // Empty elim_heap and return immediately on user-interrupt: 598 | if (asynch_interrupt){ 599 | assert(bwdsub_assigns == trail.size()); 600 | assert(subsumption_queue.size() == 0); 601 | assert(n_touched == 0); 602 | elim_heap.clear(); 603 | goto cleanup; } 604 | 605 | // printf(" ## (time = %6.2f s) ELIM: vars = %d\n", cpuTime(), elim_heap.size()); 606 | for (int cnt = 0; !elim_heap.empty(); cnt++){ 607 | Var elim = elim_heap.removeMin(); 608 | 609 | if (asynch_interrupt) break; 610 | 611 | if (isEliminated(elim) || value(elim) != l_Undef) continue; 612 | 613 | if (verbosity >= 2 && cnt % 100 == 0) 614 | printf("elimination left: %10d\r", elim_heap.size()); 615 | 616 | if (use_asymm){ 617 | // Temporarily freeze variable. Otherwise, it would immediately end up on the queue again: 618 | bool was_frozen = frozen[elim]; 619 | frozen[elim] = true; 620 | if (!asymmVar(elim)){ 621 | ok = false; goto cleanup; } 622 | frozen[elim] = was_frozen; } 623 | 624 | // At this point, the variable may have been set by assymetric branching, so check it 625 | // again. Also, don't eliminate frozen variables: 626 | if (use_elim && value(elim) == l_Undef && !frozen[elim] && !eliminateVar(elim)){ 627 | ok = false; goto cleanup; } 628 | 629 | checkGarbage(simp_garbage_frac); 630 | } 631 | 632 | assert(subsumption_queue.size() == 0); 633 | } 634 | cleanup: 635 | 636 | // If no more simplification is needed, free all simplification-related data structures: 637 | if (turn_off_elim){ 638 | touched .clear(true); 639 | occurs .clear(true); 640 | n_occ .clear(true); 641 | elim_heap.clear(true); 642 | subsumption_queue.clear(true); 643 | 644 | use_simplification = false; 645 | remove_satisfied = true; 646 | ca.extra_clause_field = false; 647 | 648 | // Force full cleanup (this is safe and desirable since it only happens once): 649 | rebuildOrderHeap(); 650 | garbageCollect(); 651 | }else{ 652 | // Cheaper cleanup: 653 | cleanUpClauses(); // TODO: can we make 'cleanUpClauses()' not be linear in the problem size somehow? 654 | checkGarbage(); 655 | } 656 | 657 | if (verbosity >= 1 && elimclauses.size() > 0) 658 | printf("| Eliminated clauses: %10.2f Mb |\n", 659 | double(elimclauses.size() * sizeof(uint32_t)) / (1024*1024)); 660 | 661 | return ok; 662 | } 663 | 664 | 665 | void SimpSolver::cleanUpClauses() 666 | { 667 | occurs.cleanAll(); 668 | int i,j; 669 | for (i = j = 0; i < clauses.size(); i++) 670 | if (ca[clauses[i]].mark() == 0) 671 | clauses[j++] = clauses[i]; 672 | clauses.shrink(i - j); 673 | } 674 | 675 | 676 | //================================================================================================= 677 | // Garbage Collection methods: 678 | 679 | 680 | void SimpSolver::relocAll(ClauseAllocator& to) 681 | { 682 | if (!use_simplification) return; 683 | 684 | // All occurs lists: 685 | // 686 | for (int i = 0; i < nVars(); i++){ 687 | vec& cs = occurs[i]; 688 | for (int j = 0; j < cs.size(); j++) 689 | ca.reloc(cs[j], to); 690 | } 691 | 692 | // Subsumption queue: 693 | // 694 | for (int i = 0; i < subsumption_queue.size(); i++) 695 | ca.reloc(subsumption_queue[i], to); 696 | 697 | // Temporary clause: 698 | // 699 | ca.reloc(bwdsub_tmpunit, to); 700 | } 701 | 702 | 703 | void SimpSolver::garbageCollect() 704 | { 705 | // Initialize the next region to a size corresponding to the estimated utilization degree. This 706 | // is not precise but should avoid some unnecessary reallocations for the new region: 707 | ClauseAllocator to(ca.size() - ca.wasted()); 708 | 709 | cleanUpClauses(); 710 | to.extra_clause_field = ca.extra_clause_field; // NOTE: this is important to keep (or lose) the extra fields. 711 | relocAll(to); 712 | Solver::relocAll(to); 713 | if (verbosity >= 2) 714 | printf("| Garbage collection: %12d bytes => %12d bytes |\n", 715 | ca.size()*ClauseAllocator::Unit_Size, to.size()*ClauseAllocator::Unit_Size); 716 | to.moveTo(ca); 717 | } 718 | -------------------------------------------------------------------------------- /src/minisat-cpp/simp/SimpSolver.h: -------------------------------------------------------------------------------- 1 | /************************************************************************************[SimpSolver.h] 2 | Copyright (c) 2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_SimpSolver_h 22 | #define Minisat_SimpSolver_h 23 | 24 | #include "mtl/Queue.h" 25 | #include "core/Solver.h" 26 | 27 | 28 | namespace Minisat { 29 | 30 | //================================================================================================= 31 | 32 | 33 | class SimpSolver : public Solver { 34 | public: 35 | // Constructor/Destructor: 36 | // 37 | SimpSolver(); 38 | ~SimpSolver(); 39 | 40 | // Problem specification: 41 | // 42 | Var newVar (bool polarity = true, bool dvar = true); 43 | bool addClause (const vec& ps); 44 | bool addEmptyClause(); // Add the empty clause to the solver. 45 | bool addClause (Lit p); // Add a unit clause to the solver. 46 | bool addClause (Lit p, Lit q); // Add a binary clause to the solver. 47 | bool addClause (Lit p, Lit q, Lit r); // Add a ternary clause to the solver. 48 | bool addClause_( vec& ps); 49 | bool substitute(Var v, Lit x); // Replace all occurences of v with x (may cause a contradiction). 50 | 51 | // Variable mode: 52 | // 53 | void setFrozen (Var v, bool b); // If a variable is frozen it will not be eliminated. 54 | bool isEliminated(Var v) const; 55 | 56 | // Solving: 57 | // 58 | bool solve (const vec& assumps, bool do_simp = true, bool turn_off_simp = false); 59 | lbool solveLimited(const vec& assumps, bool do_simp = true, bool turn_off_simp = false); 60 | bool solve ( bool do_simp = true, bool turn_off_simp = false); 61 | bool solve (Lit p , bool do_simp = true, bool turn_off_simp = false); 62 | bool solve (Lit p, Lit q, bool do_simp = true, bool turn_off_simp = false); 63 | bool solve (Lit p, Lit q, Lit r, bool do_simp = true, bool turn_off_simp = false); 64 | bool eliminate (bool turn_off_elim = false); // Perform variable elimination based simplification. 65 | 66 | // Memory managment: 67 | // 68 | virtual void garbageCollect(); 69 | 70 | 71 | // Generate a (possibly simplified) DIMACS file: 72 | // 73 | #if 0 74 | void toDimacs (const char* file, const vec& assumps); 75 | void toDimacs (const char* file); 76 | void toDimacs (const char* file, Lit p); 77 | void toDimacs (const char* file, Lit p, Lit q); 78 | void toDimacs (const char* file, Lit p, Lit q, Lit r); 79 | #endif 80 | 81 | // Mode of operation: 82 | // 83 | int grow; // Allow a variable elimination step to grow by a number of clauses (default to zero). 84 | int clause_lim; // Variables are not eliminated if it produces a resolvent with a length above this limit. 85 | // -1 means no limit. 86 | int subsumption_lim; // Do not check if subsumption against a clause larger than this. -1 means no limit. 87 | double simp_garbage_frac; // A different limit for when to issue a GC during simplification (Also see 'garbage_frac'). 88 | 89 | bool use_asymm; // Shrink clauses by asymmetric branching. 90 | bool use_rcheck; // Check if a clause is already implied. Prett costly, and subsumes subsumptions :) 91 | bool use_elim; // Perform variable elimination. 92 | 93 | // Statistics: 94 | // 95 | int merges; 96 | int asymm_lits; 97 | int eliminated_vars; 98 | 99 | protected: 100 | 101 | // Helper structures: 102 | // 103 | struct ElimLt { 104 | const vec& n_occ; 105 | explicit ElimLt(const vec& no) : n_occ(no) {} 106 | 107 | // TODO: are 64-bit operations here noticably bad on 32-bit platforms? Could use a saturating 108 | // 32-bit implementation instead then, but this will have to do for now. 109 | uint64_t cost (Var x) const { return (uint64_t)n_occ[toInt(mkLit(x))] * (uint64_t)n_occ[toInt(~mkLit(x))]; } 110 | bool operator()(Var x, Var y) const { return cost(x) < cost(y); } 111 | 112 | // TODO: investigate this order alternative more. 113 | // bool operator()(Var x, Var y) const { 114 | // int c_x = cost(x); 115 | // int c_y = cost(y); 116 | // return c_x < c_y || c_x == c_y && x < y; } 117 | }; 118 | 119 | struct ClauseDeleted { 120 | const ClauseAllocator& ca; 121 | explicit ClauseDeleted(const ClauseAllocator& _ca) : ca(_ca) {} 122 | bool operator()(const CRef& cr) const { return ca[cr].mark() == 1; } }; 123 | 124 | // Solver state: 125 | // 126 | int elimorder; 127 | bool use_simplification; 128 | vec elimclauses; 129 | vec touched; 130 | OccLists, ClauseDeleted> 131 | occurs; 132 | vec n_occ; 133 | Heap elim_heap; 134 | Queue subsumption_queue; 135 | vec frozen; 136 | vec eliminated; 137 | int bwdsub_assigns; 138 | int n_touched; 139 | 140 | // Temporaries: 141 | // 142 | CRef bwdsub_tmpunit; 143 | 144 | // Main internal methods: 145 | // 146 | lbool solve_ (bool do_simp = true, bool turn_off_simp = false); 147 | bool asymm (Var v, CRef cr); 148 | bool asymmVar (Var v); 149 | void updateElimHeap (Var v); 150 | void gatherTouchedClauses (); 151 | bool merge (const Clause& _ps, const Clause& _qs, Var v, vec& out_clause); 152 | bool merge (const Clause& _ps, const Clause& _qs, Var v, int& size); 153 | bool backwardSubsumptionCheck (bool verbose = false); 154 | bool eliminateVar (Var v); 155 | void extendModel (); 156 | 157 | void removeClause (CRef cr); 158 | bool strengthenClause (CRef cr, Lit l); 159 | void cleanUpClauses (); 160 | bool implied (const vec& c); 161 | void relocAll (ClauseAllocator& to); 162 | }; 163 | 164 | 165 | //================================================================================================= 166 | // Implementation of inline methods: 167 | 168 | 169 | inline bool SimpSolver::isEliminated (Var v) const { return eliminated[v]; } 170 | inline void SimpSolver::updateElimHeap(Var v) { 171 | assert(use_simplification); 172 | // if (!frozen[v] && !isEliminated(v) && value(v) == l_Undef) 173 | if (elim_heap.inHeap(v) || (!frozen[v] && !isEliminated(v) && value(v) == l_Undef)) 174 | elim_heap.update(v); } 175 | 176 | 177 | inline bool SimpSolver::addClause (const vec& ps) { ps.copyTo(add_tmp); return addClause_(add_tmp); } 178 | inline bool SimpSolver::addEmptyClause() { add_tmp.clear(); return addClause_(add_tmp); } 179 | inline bool SimpSolver::addClause (Lit p) { add_tmp.clear(); add_tmp.push(p); return addClause_(add_tmp); } 180 | inline bool SimpSolver::addClause (Lit p, Lit q) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); return addClause_(add_tmp); } 181 | inline bool SimpSolver::addClause (Lit p, Lit q, Lit r) { add_tmp.clear(); add_tmp.push(p); add_tmp.push(q); add_tmp.push(r); return addClause_(add_tmp); } 182 | inline void SimpSolver::setFrozen (Var v, bool b) { frozen[v] = (char)b; if (use_simplification && !b) { updateElimHeap(v); } } 183 | 184 | inline bool SimpSolver::solve ( bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); return solve_(do_simp, turn_off_simp) == l_True; } 185 | inline bool SimpSolver::solve (Lit p , bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); return solve_(do_simp, turn_off_simp) == l_True; } 186 | inline bool SimpSolver::solve (Lit p, Lit q, bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); return solve_(do_simp, turn_off_simp) == l_True; } 187 | inline bool SimpSolver::solve (Lit p, Lit q, Lit r, bool do_simp, bool turn_off_simp) { budgetOff(); assumptions.clear(); assumptions.push(p); assumptions.push(q); assumptions.push(r); return solve_(do_simp, turn_off_simp) == l_True; } 188 | inline bool SimpSolver::solve (const vec& assumps, bool do_simp, bool turn_off_simp){ 189 | budgetOff(); assumps.copyTo(assumptions); return solve_(do_simp, turn_off_simp) == l_True; } 190 | 191 | inline lbool SimpSolver::solveLimited (const vec& assumps, bool do_simp, bool turn_off_simp){ 192 | assumps.copyTo(assumptions); return solve_(do_simp, turn_off_simp); } 193 | 194 | //================================================================================================= 195 | } 196 | 197 | #endif 198 | -------------------------------------------------------------------------------- /src/minisat-cpp/utils/.clangd: -------------------------------------------------------------------------------- 1 | CompileFlags: 2 | Add: [--std=c++11, -I, ..] 3 | -------------------------------------------------------------------------------- /src/minisat-cpp/utils/Makefile: -------------------------------------------------------------------------------- 1 | EXEC = system_test 2 | DEPDIR = mtl 3 | 4 | include $(MROOT)/mtl/template.mk 5 | -------------------------------------------------------------------------------- /src/minisat-cpp/utils/Options.cc: -------------------------------------------------------------------------------- 1 | /**************************************************************************************[Options.cc] 2 | Copyright (c) 2008-2010, Niklas Sorensson 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 5 | associated documentation files (the "Software"), to deal in the Software without restriction, 6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 7 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or 11 | substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 14 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 16 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 17 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | **************************************************************************************************/ 19 | 20 | #include "mtl/Sort.h" 21 | #include "utils/Options.h" 22 | #include "utils/ParseUtils.h" 23 | 24 | using namespace Minisat; 25 | 26 | void Minisat::parseOptions(int& argc, char** argv, bool strict) 27 | { 28 | int i, j; 29 | for (i = j = 1; i < argc; i++){ 30 | const char* str = argv[i]; 31 | if (match(str, "--") && match(str, Option::getHelpPrefixString()) && match(str, "help")){ 32 | if (*str == '\0') 33 | printUsageAndExit(argc, argv); 34 | else if (match(str, "-verb")) 35 | printUsageAndExit(argc, argv, true); 36 | } else { 37 | bool parsed_ok = false; 38 | 39 | for (int k = 0; !parsed_ok && k < Option::getOptionList().size(); k++){ 40 | parsed_ok = Option::getOptionList()[k]->parse(argv[i]); 41 | 42 | // fprintf(stderr, "checking %d: %s against flag <%s> (%s)\n", i, argv[i], Option::getOptionList()[k]->name, parsed_ok ? "ok" : "skip"); 43 | } 44 | 45 | if (!parsed_ok) 46 | if (strict && match(argv[i], "-")) 47 | fprintf(stderr, "ERROR! Unknown flag \"%s\". Use '--%shelp' for help.\n", argv[i], Option::getHelpPrefixString()), exit(1); 48 | else 49 | argv[j++] = argv[i]; 50 | } 51 | } 52 | 53 | argc -= (i - j); 54 | } 55 | 56 | 57 | void Minisat::setUsageHelp (const char* str){ Option::getUsageString() = str; } 58 | void Minisat::setHelpPrefixStr (const char* str){ Option::getHelpPrefixString() = str; } 59 | void Minisat::printUsageAndExit (int argc, char** argv, bool verbose) 60 | { 61 | const char* usage = Option::getUsageString(); 62 | if (usage != NULL) 63 | fprintf(stderr, usage, argv[0]); 64 | 65 | sort(Option::getOptionList(), Option::OptionLt()); 66 | 67 | const char* prev_cat = NULL; 68 | const char* prev_type = NULL; 69 | 70 | for (int i = 0; i < Option::getOptionList().size(); i++){ 71 | const char* cat = Option::getOptionList()[i]->category; 72 | const char* type = Option::getOptionList()[i]->type_name; 73 | 74 | if (cat != prev_cat) 75 | fprintf(stderr, "\n%s OPTIONS:\n\n", cat); 76 | else if (type != prev_type) 77 | fprintf(stderr, "\n"); 78 | 79 | Option::getOptionList()[i]->help(verbose); 80 | 81 | prev_cat = Option::getOptionList()[i]->category; 82 | prev_type = Option::getOptionList()[i]->type_name; 83 | } 84 | 85 | fprintf(stderr, "\nHELP OPTIONS:\n\n"); 86 | fprintf(stderr, " --%shelp Print help message.\n", Option::getHelpPrefixString()); 87 | fprintf(stderr, " --%shelp-verb Print verbose help message.\n", Option::getHelpPrefixString()); 88 | fprintf(stderr, "\n"); 89 | exit(0); 90 | } 91 | 92 | -------------------------------------------------------------------------------- /src/minisat-cpp/utils/Options.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************************[Options.h] 2 | Copyright (c) 2008-2010, Niklas Sorensson 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 5 | associated documentation files (the "Software"), to deal in the Software without restriction, 6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 7 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or 11 | substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 14 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 16 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 17 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | **************************************************************************************************/ 19 | 20 | #ifndef Minisat_Options_h 21 | #define Minisat_Options_h 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "mtl/IntTypes.h" 29 | #include "mtl/Vec.h" 30 | #include "utils/ParseUtils.h" 31 | 32 | namespace Minisat { 33 | 34 | //================================================================================================== 35 | // Top-level option parse/help functions: 36 | 37 | 38 | extern void parseOptions (int& argc, char** argv, bool strict = false); 39 | extern void printUsageAndExit(int argc, char** argv, bool verbose = false); 40 | extern void setUsageHelp (const char* str); 41 | extern void setHelpPrefixStr (const char* str); 42 | 43 | 44 | //================================================================================================== 45 | // Options is an abstract class that gives the interface for all types options: 46 | 47 | 48 | class Option 49 | { 50 | protected: 51 | const char* name; 52 | const char* description; 53 | const char* category; 54 | const char* type_name; 55 | 56 | static vec& getOptionList () { static vec options; return options; } 57 | static const char*& getUsageString() { static const char* usage_str; return usage_str; } 58 | static const char*& getHelpPrefixString() { static const char* help_prefix_str = ""; return help_prefix_str; } 59 | 60 | struct OptionLt { 61 | bool operator()(const Option* x, const Option* y) { 62 | int test1 = strcmp(x->category, y->category); 63 | return test1 < 0 || (test1 == 0 && strcmp(x->type_name, y->type_name) < 0); 64 | } 65 | }; 66 | 67 | Option(const char* name_, 68 | const char* desc_, 69 | const char* cate_, 70 | const char* type_) : 71 | name (name_) 72 | , description(desc_) 73 | , category (cate_) 74 | , type_name (type_) 75 | { 76 | getOptionList().push(this); 77 | } 78 | 79 | public: 80 | virtual ~Option() {} 81 | 82 | virtual bool parse (const char* str) = 0; 83 | virtual void help (bool verbose = false) = 0; 84 | 85 | friend void parseOptions (int& argc, char** argv, bool strict); 86 | friend void printUsageAndExit (int argc, char** argv, bool verbose); 87 | friend void setUsageHelp (const char* str); 88 | friend void setHelpPrefixStr (const char* str); 89 | }; 90 | 91 | 92 | //================================================================================================== 93 | // Range classes with specialization for floating types: 94 | 95 | 96 | struct IntRange { 97 | int begin; 98 | int end; 99 | IntRange(int b, int e) : begin(b), end(e) {} 100 | }; 101 | 102 | struct Int64Range { 103 | int64_t begin; 104 | int64_t end; 105 | Int64Range(int64_t b, int64_t e) : begin(b), end(e) {} 106 | }; 107 | 108 | struct DoubleRange { 109 | double begin; 110 | double end; 111 | bool begin_inclusive; 112 | bool end_inclusive; 113 | DoubleRange(double b, bool binc, double e, bool einc) : begin(b), end(e), begin_inclusive(binc), end_inclusive(einc) {} 114 | }; 115 | 116 | 117 | //================================================================================================== 118 | // Double options: 119 | 120 | 121 | class DoubleOption : public Option 122 | { 123 | protected: 124 | DoubleRange range; 125 | double value; 126 | 127 | public: 128 | DoubleOption(const char* c, const char* n, const char* d, double def = double(), DoubleRange r = DoubleRange(-HUGE_VAL, false, HUGE_VAL, false)) 129 | : Option(n, d, c, ""), range(r), value(def) { 130 | // FIXME: set LC_NUMERIC to "C" to make sure that strtof/strtod parses decimal point correctly. 131 | } 132 | 133 | operator double (void) const { return value; } 134 | operator double& (void) { return value; } 135 | DoubleOption& operator=(double x) { value = x; return *this; } 136 | 137 | virtual bool parse(const char* str){ 138 | const char* span = str; 139 | 140 | if (!match(span, "-") || !match(span, name) || !match(span, "=")) 141 | return false; 142 | 143 | char* end; 144 | double tmp = strtod(span, &end); 145 | 146 | if (end == NULL) 147 | return false; 148 | else if (tmp >= range.end && (!range.end_inclusive || tmp != range.end)){ 149 | fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); 150 | exit(1); 151 | }else if (tmp <= range.begin && (!range.begin_inclusive || tmp != range.begin)){ 152 | fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); 153 | exit(1); } 154 | 155 | value = tmp; 156 | // fprintf(stderr, "READ VALUE: %g\n", value); 157 | 158 | return true; 159 | } 160 | 161 | virtual void help (bool verbose = false){ 162 | fprintf(stderr, " -%-12s = %-8s %c%4.2g .. %4.2g%c (default: %g)\n", 163 | name, type_name, 164 | range.begin_inclusive ? '[' : '(', 165 | range.begin, 166 | range.end, 167 | range.end_inclusive ? ']' : ')', 168 | value); 169 | if (verbose){ 170 | fprintf(stderr, "\n %s\n", description); 171 | fprintf(stderr, "\n"); 172 | } 173 | } 174 | }; 175 | 176 | 177 | //================================================================================================== 178 | // Int options: 179 | 180 | 181 | class IntOption : public Option 182 | { 183 | protected: 184 | IntRange range; 185 | int32_t value; 186 | 187 | public: 188 | IntOption(const char* c, const char* n, const char* d, int32_t def = int32_t(), IntRange r = IntRange(INT32_MIN, INT32_MAX)) 189 | : Option(n, d, c, ""), range(r), value(def) {} 190 | 191 | operator int32_t (void) const { return value; } 192 | operator int32_t& (void) { return value; } 193 | IntOption& operator= (int32_t x) { value = x; return *this; } 194 | 195 | virtual bool parse(const char* str){ 196 | const char* span = str; 197 | 198 | if (!match(span, "-") || !match(span, name) || !match(span, "=")) 199 | return false; 200 | 201 | char* end; 202 | int32_t tmp = strtol(span, &end, 10); 203 | 204 | if (end == NULL) 205 | return false; 206 | else if (tmp > range.end){ 207 | fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); 208 | exit(1); 209 | }else if (tmp < range.begin){ 210 | fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); 211 | exit(1); } 212 | 213 | value = tmp; 214 | 215 | return true; 216 | } 217 | 218 | virtual void help (bool verbose = false){ 219 | fprintf(stderr, " -%-12s = %-8s [", name, type_name); 220 | if (range.begin == INT32_MIN) 221 | fprintf(stderr, "imin"); 222 | else 223 | fprintf(stderr, "%4d", range.begin); 224 | 225 | fprintf(stderr, " .. "); 226 | if (range.end == INT32_MAX) 227 | fprintf(stderr, "imax"); 228 | else 229 | fprintf(stderr, "%4d", range.end); 230 | 231 | fprintf(stderr, "] (default: %d)\n", value); 232 | if (verbose){ 233 | fprintf(stderr, "\n %s\n", description); 234 | fprintf(stderr, "\n"); 235 | } 236 | } 237 | }; 238 | 239 | 240 | // Leave this out for visual C++ until Microsoft implements C99 and gets support for strtoll. 241 | #ifndef _MSC_VER 242 | 243 | class Int64Option : public Option 244 | { 245 | protected: 246 | Int64Range range; 247 | int64_t value; 248 | 249 | public: 250 | Int64Option(const char* c, const char* n, const char* d, int64_t def = int64_t(), Int64Range r = Int64Range(INT64_MIN, INT64_MAX)) 251 | : Option(n, d, c, ""), range(r), value(def) {} 252 | 253 | operator int64_t (void) const { return value; } 254 | operator int64_t& (void) { return value; } 255 | Int64Option& operator= (int64_t x) { value = x; return *this; } 256 | 257 | virtual bool parse(const char* str){ 258 | const char* span = str; 259 | 260 | if (!match(span, "-") || !match(span, name) || !match(span, "=")) 261 | return false; 262 | 263 | char* end; 264 | int64_t tmp = strtoll(span, &end, 10); 265 | 266 | if (end == NULL) 267 | return false; 268 | else if (tmp > range.end){ 269 | fprintf(stderr, "ERROR! value <%s> is too large for option \"%s\".\n", span, name); 270 | exit(1); 271 | }else if (tmp < range.begin){ 272 | fprintf(stderr, "ERROR! value <%s> is too small for option \"%s\".\n", span, name); 273 | exit(1); } 274 | 275 | value = tmp; 276 | 277 | return true; 278 | } 279 | 280 | virtual void help (bool verbose = false){ 281 | fprintf(stderr, " -%-12s = %-8s [", name, type_name); 282 | if (range.begin == INT64_MIN) 283 | fprintf(stderr, "imin"); 284 | else 285 | fprintf(stderr, "%4ld" , range.begin); 286 | 287 | fprintf(stderr, " .. "); 288 | if (range.end == INT64_MAX) 289 | fprintf(stderr, "imax"); 290 | else 291 | fprintf(stderr, "%4ld" , range.end); 292 | 293 | fprintf(stderr, "] (default: %ld)\n", value); 294 | if (verbose){ 295 | fprintf(stderr, "\n %s\n", description); 296 | fprintf(stderr, "\n"); 297 | } 298 | } 299 | }; 300 | #endif 301 | 302 | //================================================================================================== 303 | // String option: 304 | 305 | 306 | class StringOption : public Option 307 | { 308 | const char* value; 309 | public: 310 | StringOption(const char* c, const char* n, const char* d, const char* def = NULL) 311 | : Option(n, d, c, ""), value(def) {} 312 | 313 | operator const char* (void) const { return value; } 314 | operator const char*& (void) { return value; } 315 | StringOption& operator= (const char* x) { value = x; return *this; } 316 | 317 | virtual bool parse(const char* str){ 318 | const char* span = str; 319 | 320 | if (!match(span, "-") || !match(span, name) || !match(span, "=")) 321 | return false; 322 | 323 | value = span; 324 | return true; 325 | } 326 | 327 | virtual void help (bool verbose = false){ 328 | fprintf(stderr, " -%-10s = %8s\n", name, type_name); 329 | if (verbose){ 330 | fprintf(stderr, "\n %s\n", description); 331 | fprintf(stderr, "\n"); 332 | } 333 | } 334 | }; 335 | 336 | 337 | //================================================================================================== 338 | // Bool option: 339 | 340 | 341 | class BoolOption : public Option 342 | { 343 | bool value; 344 | 345 | public: 346 | BoolOption(const char* c, const char* n, const char* d, bool v) 347 | : Option(n, d, c, ""), value(v) {} 348 | 349 | operator bool (void) const { return value; } 350 | operator bool& (void) { return value; } 351 | BoolOption& operator=(bool b) { value = b; return *this; } 352 | 353 | virtual bool parse(const char* str){ 354 | const char* span = str; 355 | 356 | if (match(span, "-")){ 357 | bool b = !match(span, "no-"); 358 | 359 | if (strcmp(span, name) == 0){ 360 | value = b; 361 | return true; } 362 | } 363 | 364 | return false; 365 | } 366 | 367 | virtual void help (bool verbose = false){ 368 | 369 | fprintf(stderr, " -%s, -no-%s", name, name); 370 | 371 | for (uint32_t i = 0; i < 32 - strlen(name)*2; i++) 372 | fprintf(stderr, " "); 373 | 374 | fprintf(stderr, " "); 375 | fprintf(stderr, "(default: %s)\n", value ? "on" : "off"); 376 | if (verbose){ 377 | fprintf(stderr, "\n %s\n", description); 378 | fprintf(stderr, "\n"); 379 | } 380 | } 381 | }; 382 | 383 | //================================================================================================= 384 | } 385 | 386 | #endif 387 | -------------------------------------------------------------------------------- /src/minisat-cpp/utils/ParseUtils.h: -------------------------------------------------------------------------------- 1 | /************************************************************************************[ParseUtils.h] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_ParseUtils_h 22 | #define Minisat_ParseUtils_h 23 | 24 | #include 25 | #include 26 | 27 | 28 | namespace Minisat { 29 | 30 | 31 | //------------------------------------------------------------------------------------------------- 32 | // End-of-file detection functions for StreamBuffer and char*: 33 | 34 | static inline bool isEof(const char* in) { return *in == '\0'; } 35 | 36 | //------------------------------------------------------------------------------------------------- 37 | // Generic parse functions parametrized over the input-stream type. 38 | 39 | 40 | template 41 | static void skipWhitespace(B& in) { 42 | while ((*in >= 9 && *in <= 13) || *in == 32) 43 | ++in; } 44 | 45 | 46 | template 47 | static void skipLine(B& in) { 48 | for (;;){ 49 | if (isEof(in)) return; 50 | if (*in == '\n') { ++in; return; } 51 | ++in; } } 52 | 53 | 54 | template 55 | static int parseInt(B& in) { 56 | int val = 0; 57 | bool neg = false; 58 | skipWhitespace(in); 59 | if (*in == '-') neg = true, ++in; 60 | else if (*in == '+') ++in; 61 | if (*in < '0' || *in > '9') fprintf(stderr, "PARSE ERROR! Unexpected char: %c\n", *in), exit(3); 62 | while (*in >= '0' && *in <= '9') 63 | val = val*10 + (*in - '0'), 64 | ++in; 65 | return neg ? -val : val; } 66 | 67 | 68 | // String matching: in case of a match the input iterator will be advanced the corresponding 69 | // number of characters. 70 | template 71 | static bool match(B& in, const char* str) { 72 | int i; 73 | for (i = 0; str[i] != '\0'; i++) 74 | if (in[i] != str[i]) 75 | return false; 76 | 77 | in += i; 78 | 79 | return true; 80 | } 81 | 82 | // String matching: consumes characters eagerly, but does not require random access iterator. 83 | template 84 | static bool eagerMatch(B& in, const char* str) { 85 | for (; *str != '\0'; ++str, ++in) 86 | if (*str != *in) 87 | return false; 88 | return true; } 89 | 90 | 91 | //================================================================================================= 92 | } 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /src/minisat-cpp/utils/System.cc: -------------------------------------------------------------------------------- 1 | /***************************************************************************************[System.cc] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #include "utils/System.h" 22 | 23 | #if defined(__linux__) 24 | 25 | #include 26 | #include 27 | 28 | using namespace Minisat; 29 | 30 | // TODO: split the memory reading functions into two: one for reading high-watermark of RSS, and 31 | // one for reading the current virtual memory size. 32 | 33 | static inline int memReadStat(int field) 34 | { 35 | char name[256]; 36 | pid_t pid = getpid(); 37 | int value; 38 | 39 | sprintf(name, "/proc/%d/statm", pid); 40 | FILE* in = fopen(name, "rb"); 41 | if (in == NULL) return 0; 42 | 43 | for (; field >= 0; field--) 44 | if (fscanf(in, "%d", &value) != 1) 45 | printf("ERROR! Failed to parse memory statistics from \"/proc\".\n"), exit(1); 46 | fclose(in); 47 | return value; 48 | } 49 | 50 | 51 | static inline int memReadPeak(void) 52 | { 53 | char name[256]; 54 | pid_t pid = getpid(); 55 | 56 | sprintf(name, "/proc/%d/status", pid); 57 | FILE* in = fopen(name, "rb"); 58 | if (in == NULL) return 0; 59 | 60 | // Find the correct line, beginning with "VmPeak:": 61 | int peak_kb = 0; 62 | while (!feof(in) && fscanf(in, "VmPeak: %d kB", &peak_kb) != 1) 63 | while (!feof(in) && fgetc(in) != '\n') 64 | ; 65 | fclose(in); 66 | 67 | return peak_kb; 68 | } 69 | 70 | double Minisat::memUsed() { return (double)memReadStat(0) * (double)getpagesize() / (1024*1024); } 71 | double Minisat::memUsedPeak() { 72 | double peak = memReadPeak() / 1024; 73 | return peak == 0 ? memUsed() : peak; } 74 | 75 | #elif defined(__FreeBSD__) 76 | 77 | double Minisat::memUsed(void) { 78 | struct rusage ru; 79 | getrusage(RUSAGE_SELF, &ru); 80 | return (double)ru.ru_maxrss / 1024; } 81 | double MiniSat::memUsedPeak(void) { return memUsed(); } 82 | 83 | 84 | #elif defined(__APPLE__) 85 | #include 86 | 87 | double Minisat::memUsed(void) { 88 | malloc_statistics_t t; 89 | malloc_zone_statistics(NULL, &t); 90 | return (double)t.max_size_in_use / (1024*1024); } 91 | 92 | #else 93 | double Minisat::memUsed() { 94 | return 0; } 95 | #endif 96 | -------------------------------------------------------------------------------- /src/minisat-cpp/utils/System.h: -------------------------------------------------------------------------------- 1 | /****************************************************************************************[System.h] 2 | Copyright (c) 2003-2006, Niklas Een, Niklas Sorensson 3 | Copyright (c) 2007-2010, Niklas Sorensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 6 | associated documentation files (the "Software"), to deal in the Software without restriction, 7 | including without limitation the rights to use, copy, modify, merge, publish, distribute, 8 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all copies or 12 | substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 15 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 18 | OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | **************************************************************************************************/ 20 | 21 | #ifndef Minisat_System_h 22 | #define Minisat_System_h 23 | 24 | #if defined(__linux__) 25 | #include 26 | #endif 27 | 28 | #include "mtl/IntTypes.h" 29 | 30 | //------------------------------------------------------------------------------------------------- 31 | 32 | namespace Minisat { 33 | 34 | static inline double cpuTime(void); // CPU-time in seconds. 35 | extern double memUsed(); // Memory in mega bytes (returns 0 for unsupported architectures). 36 | extern double memUsedPeak(); // Peak-memory in mega bytes (returns 0 for unsupported architectures). 37 | 38 | } 39 | 40 | //------------------------------------------------------------------------------------------------- 41 | // Implementation of inline functions: 42 | 43 | #if defined(_MSC_VER) || defined(__MINGW32__) 44 | #include 45 | 46 | static inline double Minisat::cpuTime(void) { return (double)clock() / CLOCKS_PER_SEC; } 47 | 48 | #else 49 | #include 50 | #include 51 | #include 52 | 53 | static inline double Minisat::cpuTime(void) { 54 | struct rusage ru; 55 | getrusage(RUSAGE_SELF, &ru); 56 | return (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec / 1000000; } 57 | 58 | #endif 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /src/minisat.ml: -------------------------------------------------------------------------------- 1 | (* This file is free software. See file "license" for more details. *) 2 | 3 | type t 4 | type 'a printer = Format.formatter -> 'a -> unit 5 | 6 | module Lit = struct 7 | type t = int 8 | 9 | let[@inline] make n = 10 | assert (n > 0); 11 | n + n + 1 12 | 13 | let[@inline] neg n = n lxor 1 14 | let[@inline] abs n = n land (max_int - 1) 15 | let equal : t -> t -> bool = ( = ) 16 | let compare : t -> t -> int = compare 17 | let[@inline] hash (x : t) : int = Hashtbl.hash x 18 | 19 | let[@inline] apply_sign sign t = 20 | if sign then 21 | t 22 | else 23 | neg t 24 | 25 | let[@inline] sign n = 26 | if n land 1 = 1 then 27 | true 28 | else 29 | false 30 | 31 | let[@inline] to_int n = n lsr 1 32 | 33 | let to_string x = 34 | (if sign x then 35 | "" 36 | else 37 | "-") 38 | ^ string_of_int (to_int x) 39 | 40 | let pp out x = Format.pp_print_string out (to_string x) 41 | end 42 | 43 | type assumptions = Lit.t array 44 | 45 | module Raw = struct 46 | external create : unit -> t = "caml_minisat_new" 47 | external delete : t -> unit = "caml_minisat_delete" 48 | 49 | external ensure_var : t -> Lit.t -> unit = "caml_minisat_ensure_var" 50 | [@@noalloc] 51 | 52 | external add_clause_a : t -> Lit.t array -> bool = "caml_minisat_add_clause_a" 53 | [@@noalloc] 54 | 55 | external simplify : t -> bool = "caml_minisat_simplify" [@@noalloc] 56 | external solve : t -> Lit.t array -> bool = "caml_minisat_solve" 57 | external nvars : t -> int = "caml_minisat_nvars" [@@noalloc] 58 | external nclauses : t -> int = "caml_minisat_nclauses" [@@noalloc] 59 | external nconflicts : t -> int = "caml_minisat_nconflicts" [@@noalloc] 60 | external value : t -> Lit.t -> int = "caml_minisat_value" [@@noalloc] 61 | 62 | external value_level_0 : t -> Lit.t -> int = "caml_minisat_value_level_0" 63 | [@@noalloc] 64 | 65 | external set_verbose : t -> int -> unit = "caml_minisat_set_verbose" 66 | external okay : t -> bool = "caml_minisat_okay" [@@noalloc] 67 | external core : t -> Lit.t array = "caml_minisat_core" 68 | external to_dimacs : t -> string -> unit = "caml_minisat_to_dimacs" 69 | external interrupt : t -> unit = "caml_minisat_interrupt" [@@noalloc] 70 | 71 | external clear_interrupt : t -> unit = "caml_minisat_clear_interrupt" 72 | [@@noalloc] 73 | end 74 | 75 | let create () = 76 | let s = Raw.create () in 77 | Gc.finalise Raw.delete s; 78 | s 79 | 80 | exception Unsat 81 | 82 | let okay = Raw.okay 83 | let check_ret_ b = if not b then raise Unsat 84 | let ensure_lit_exists s l = Raw.ensure_var s l 85 | let add_clause_a s a = Raw.add_clause_a s a |> check_ret_ 86 | let add_clause_l s lits = add_clause_a s (Array.of_list lits) 87 | 88 | let pp_clause out l = 89 | Format.fprintf out "[@["; 90 | let first = ref true in 91 | List.iter 92 | (fun x -> 93 | if !first then 94 | first := false 95 | else 96 | Format.fprintf out ",@ "; 97 | Lit.pp out x) 98 | l; 99 | Format.fprintf out "@]]" 100 | 101 | let simplify s = Raw.simplify s |> check_ret_ 102 | let solve ?(assumptions = [||]) s = Raw.solve s assumptions |> check_ret_ 103 | let unsat_core = Raw.core 104 | 105 | type value = 106 | | V_undef 107 | | V_true 108 | | V_false 109 | 110 | let string_of_value = function 111 | | V_undef -> "undef" 112 | | V_true -> "true" 113 | | V_false -> "false" 114 | 115 | let pp_value out x = Format.pp_print_string out (string_of_value x) 116 | 117 | let[@inline] conv_value_ = function 118 | | 1 -> V_true 119 | | 0 -> V_undef 120 | | -1 -> V_false 121 | | _ -> assert false 122 | 123 | let[@inline] value s lit = conv_value_ (Raw.value s lit) 124 | let[@inline] value_at_level_0 s lit = conv_value_ (Raw.value_level_0 s lit) 125 | let set_verbose = Raw.set_verbose 126 | let interrupt = Raw.interrupt 127 | let clear_interrupt = Raw.clear_interrupt 128 | let n_clauses = Raw.nclauses 129 | let n_vars = Raw.nvars 130 | let n_conflicts = Raw.nconflicts 131 | 132 | module Debug = struct 133 | let to_dimacs_file = Raw.to_dimacs 134 | end 135 | -------------------------------------------------------------------------------- /src/minisat.mli: -------------------------------------------------------------------------------- 1 | (** Bindings to Minisat. *) 2 | 3 | (* This file is free software. See file "license" for more details. *) 4 | 5 | type t 6 | (** An instance of minisat (stateful) *) 7 | 8 | type 'a printer = Format.formatter -> 'a -> unit 9 | 10 | module Lit : sig 11 | type t = private int 12 | (** Some representation of literals that will be accepted by minisat. 13 | {b NOTE} the representation used by minisat is not based on sign 14 | but parity. Do not try to encode negative literals as negative 15 | integers. *) 16 | 17 | val equal : t -> t -> bool 18 | (** @since 0.6 *) 19 | 20 | val compare : t -> t -> int 21 | (** @since 0.6 *) 22 | 23 | val hash : t -> int 24 | (** @since 0.6 *) 25 | 26 | val make : int -> t 27 | (** [make n] creates the literal whose index is [n]. 28 | {b NOTE} [n] must be strictly positive. Use {!neg} to obtain 29 | the negation of a literal. *) 30 | 31 | val neg : t -> t 32 | (** Negation of a literal. 33 | Invariant: [neg (neg x) = x] *) 34 | 35 | val abs : t -> t 36 | (** Absolute value (removes negation if any). *) 37 | 38 | val apply_sign : bool -> t -> t 39 | (** [apply_sign true lit] is [lit]; [apply_sign false lit] is [neg lit] 40 | @since 0.6 *) 41 | 42 | val sign : t -> bool 43 | (** Sign: [true] if the literal is positive, [false] for a negated literal. 44 | Invariants: 45 | [sign (abs x) = true] 46 | [sign (neg x) = not (sign x)] 47 | *) 48 | 49 | val to_int : t -> int 50 | val to_string : t -> string 51 | val pp : t printer 52 | end 53 | 54 | type assumptions = Lit.t array 55 | 56 | val create : unit -> t 57 | (** Create a fresh solver state. *) 58 | 59 | val okay : t -> bool 60 | (** [true] if the solver isn't known to be in an unsat state 61 | @since 0.6 *) 62 | 63 | exception Unsat 64 | 65 | val ensure_lit_exists : t -> Lit.t -> unit 66 | (** Make sure the solver decides this literal. 67 | @since 0.6 *) 68 | 69 | val add_clause_l : t -> Lit.t list -> unit 70 | (** Add a clause (as a list of literals) to the solver state. 71 | 72 | @raise Unsat if the problem is unsat. *) 73 | 74 | val add_clause_a : t -> Lit.t array -> unit 75 | (** Add a clause (as an array of literals) to the solver state. 76 | 77 | @raise Unsat if the problem is unsat. *) 78 | 79 | val pp_clause : Lit.t list printer 80 | 81 | val simplify : t -> unit 82 | (** Perform simplifications on the solver state. Speeds up later manipulations 83 | on the solver state, e.g. calls to [solve]. 84 | 85 | @raise Unsat if the problem is unsat. *) 86 | 87 | val solve : ?assumptions:assumptions -> t -> unit 88 | (** Check whether the current solver state is satisfiable, additionally assuming 89 | that the literals provided in [assumptions] are assigned to true. After 90 | [solve] terminates (raising [Unsat] or not), the solver state is unchanged: 91 | the literals in [assumptions] are only considered to be true for the duration 92 | of the query. 93 | 94 | @raise Unsat if the problem is unsat. *) 95 | 96 | type value = 97 | | V_undef 98 | | V_true 99 | | V_false 100 | 101 | val string_of_value : value -> string 102 | (** @since 0.5 *) 103 | 104 | val pp_value : value printer 105 | (** @since 0.5 *) 106 | 107 | val value : t -> Lit.t -> value 108 | (** Returns the assignation of a literal in the solver state. 109 | This must only be called after a call to {!solve} that returned successfully 110 | without raising {!Unsat}. *) 111 | 112 | val value_at_level_0 : t -> Lit.t -> value 113 | (** Returns the assignment level for this literal at level 0, if assigned 114 | there, or [V_undef]. 115 | If [lit] is not assigned at level 0, this returns [V_undef] even when the 116 | literal has a value in the current model. 117 | @since 0.6 *) 118 | 119 | val unsat_core : t -> Lit.t array 120 | (** Returns the subset of assumptions of a solver that returned "unsat" 121 | when called with [solve ~assumptions s]. 122 | @since 0.6 123 | *) 124 | 125 | val set_verbose : t -> int -> unit 126 | (** Verbose mode. *) 127 | 128 | val interrupt : t -> unit 129 | (** Interrupt the solver, typically from another thread. 130 | @since 0.6 *) 131 | 132 | val clear_interrupt : t -> unit 133 | (** Clear interrupt flag so that we can use the solver again. 134 | @since 0.6 *) 135 | 136 | val n_clauses : t -> int 137 | (** @since 0.6 *) 138 | 139 | val n_vars : t -> int 140 | (** @since 0.6 *) 141 | 142 | val n_conflicts : t -> int 143 | (** @since 0.6 *) 144 | 145 | module Debug : sig 146 | val to_dimacs_file : t -> string -> unit 147 | (** [to_dimacs_file solver path] writes the solver's set of clauses into the 148 | file at [path]. 149 | @since 0.6 *) 150 | end 151 | -------------------------------------------------------------------------------- /tests/dune: -------------------------------------------------------------------------------- 1 | 2 | (executables 3 | (names test1 phole) 4 | (libraries minisat)) 5 | 6 | (rule 7 | (alias runtest) 8 | (action (run ./test1.exe))) 9 | 10 | (rule 11 | (alias runtest) 12 | (action (run ./phole.exe 6))) 13 | -------------------------------------------------------------------------------- /tests/icnf/dune: -------------------------------------------------------------------------------- 1 | 2 | (rule 3 | (targets regression1.icnf.out) 4 | (deps regression1.icnf) 5 | (action (with-stdout-to %{targets} 6 | (run ../../examples/icnf-solve/icnf_solve.exe %{deps})))) 7 | 8 | 9 | (rule 10 | (alias runtest) 11 | (action (diff regression1.icnf.expected regression1.icnf.out))) 12 | 13 | 14 | (rule 15 | (targets regression2.icnf.out) 16 | (deps regression2.icnf) 17 | (action (with-stdout-to %{targets} 18 | (run ../../examples/icnf-solve/icnf_solve.exe %{deps})))) 19 | 20 | 21 | (rule 22 | (alias runtest) 23 | (action (diff regression2.icnf.expected regression2.icnf.out))) 24 | -------------------------------------------------------------------------------- /tests/icnf/regression1.icnf.expected: -------------------------------------------------------------------------------- 1 | c process "regression1.icnf" with minisat 2 | SAT 3 | SAT 4 | UNSAT 5 | SAT 6 | UNSAT 7 | SAT 8 | UNSAT 9 | SAT 10 | UNSAT 11 | SAT 12 | UNSAT 13 | SAT 14 | UNSAT 15 | SAT 16 | UNSAT 17 | SAT 18 | UNSAT 19 | SAT 20 | UNSAT 21 | SAT 22 | UNSAT 23 | SAT 24 | SAT 25 | UNSAT 26 | SAT 27 | UNSAT 28 | SAT 29 | SAT 30 | UNSAT 31 | SAT 32 | SAT 33 | UNSAT 34 | SAT 35 | SAT 36 | UNSAT 37 | SAT 38 | UNSAT 39 | SAT 40 | SAT 41 | UNSAT 42 | SAT 43 | UNSAT 44 | SAT 45 | UNSAT 46 | SAT 47 | UNSAT 48 | SAT 49 | UNSAT 50 | SAT 51 | UNSAT 52 | SAT 53 | UNSAT 54 | SAT 55 | UNSAT 56 | SAT 57 | UNSAT 58 | SAT 59 | UNSAT 60 | SAT 61 | UNSAT 62 | SAT 63 | UNSAT 64 | SAT 65 | UNSAT 66 | SAT 67 | UNSAT 68 | SAT 69 | UNSAT 70 | SAT 71 | UNSAT 72 | SAT 73 | SAT 74 | UNSAT 75 | SAT 76 | UNSAT 77 | SAT 78 | SAT 79 | UNSAT 80 | SAT 81 | UNSAT 82 | SAT 83 | UNSAT 84 | SAT 85 | UNSAT 86 | SAT 87 | UNSAT 88 | SAT 89 | UNSAT 90 | SAT 91 | UNSAT 92 | SAT 93 | UNSAT 94 | SAT 95 | UNSAT 96 | SAT 97 | SAT 98 | UNSAT 99 | SAT 100 | UNSAT 101 | SAT 102 | UNSAT 103 | SAT 104 | UNSAT 105 | SAT 106 | UNSAT 107 | SAT 108 | UNSAT 109 | SAT 110 | UNSAT 111 | SAT 112 | SAT 113 | UNSAT 114 | SAT 115 | UNSAT 116 | SAT 117 | UNSAT 118 | SAT 119 | UNSAT 120 | SAT 121 | UNSAT 122 | SAT 123 | UNSAT 124 | SAT 125 | UNSAT 126 | SAT 127 | UNSAT 128 | SAT 129 | UNSAT 130 | SAT 131 | UNSAT 132 | SAT 133 | UNSAT 134 | SAT 135 | SAT 136 | UNSAT 137 | SAT 138 | UNSAT 139 | SAT 140 | UNSAT 141 | SAT 142 | UNSAT 143 | SAT 144 | UNSAT 145 | SAT 146 | UNSAT 147 | SAT 148 | UNSAT 149 | SAT 150 | SAT 151 | UNSAT 152 | SAT 153 | UNSAT 154 | SAT 155 | SAT 156 | UNSAT 157 | SAT 158 | UNSAT 159 | SAT 160 | UNSAT 161 | SAT 162 | UNSAT 163 | SAT 164 | UNSAT 165 | SAT 166 | UNSAT 167 | SAT 168 | UNSAT 169 | SAT 170 | SAT 171 | UNSAT 172 | SAT 173 | UNSAT 174 | SAT 175 | UNSAT 176 | SAT 177 | SAT 178 | UNSAT 179 | SAT 180 | UNSAT 181 | SAT 182 | SAT 183 | UNSAT 184 | SAT 185 | UNSAT 186 | SAT 187 | UNSAT 188 | SAT 189 | UNSAT 190 | SAT 191 | UNSAT 192 | SAT 193 | UNSAT 194 | SAT 195 | UNSAT 196 | SAT 197 | SAT 198 | SAT 199 | UNSAT 200 | SAT 201 | UNSAT 202 | SAT 203 | UNSAT 204 | SAT 205 | UNSAT 206 | SAT 207 | SAT 208 | UNSAT 209 | SAT 210 | UNSAT 211 | SAT 212 | UNSAT 213 | SAT 214 | UNSAT 215 | SAT 216 | UNSAT 217 | SAT 218 | UNSAT 219 | SAT 220 | UNSAT 221 | SAT 222 | UNSAT 223 | SAT 224 | UNSAT 225 | SAT 226 | UNSAT 227 | SAT 228 | UNSAT 229 | SAT 230 | UNSAT 231 | SAT 232 | UNSAT 233 | SAT 234 | UNSAT 235 | SAT 236 | UNSAT 237 | SAT 238 | SAT 239 | UNSAT 240 | SAT 241 | UNSAT 242 | SAT 243 | UNSAT 244 | SAT 245 | SAT 246 | UNSAT 247 | SAT 248 | UNSAT 249 | SAT 250 | UNSAT 251 | SAT 252 | UNSAT 253 | SAT 254 | UNSAT 255 | SAT 256 | UNSAT 257 | SAT 258 | UNSAT 259 | SAT 260 | UNSAT 261 | SAT 262 | UNSAT 263 | SAT 264 | UNSAT 265 | SAT 266 | SAT 267 | UNSAT 268 | SAT 269 | UNSAT 270 | SAT 271 | SAT 272 | UNSAT 273 | SAT 274 | UNSAT 275 | SAT 276 | SAT 277 | UNSAT 278 | SAT 279 | UNSAT 280 | SAT 281 | UNSAT 282 | SAT 283 | UNSAT 284 | SAT 285 | UNSAT 286 | SAT 287 | UNSAT 288 | SAT 289 | UNSAT 290 | SAT 291 | UNSAT 292 | SAT 293 | SAT 294 | UNSAT 295 | SAT 296 | UNSAT 297 | SAT 298 | UNSAT 299 | SAT 300 | UNSAT 301 | SAT 302 | UNSAT 303 | SAT 304 | SAT 305 | UNSAT 306 | SAT 307 | UNSAT 308 | SAT 309 | SAT 310 | UNSAT 311 | SAT 312 | UNSAT 313 | SAT 314 | SAT 315 | UNSAT 316 | SAT 317 | UNSAT 318 | SAT 319 | UNSAT 320 | SAT 321 | UNSAT 322 | SAT 323 | SAT 324 | UNSAT 325 | SAT 326 | UNSAT 327 | SAT 328 | UNSAT 329 | SAT 330 | UNSAT 331 | SAT 332 | SAT 333 | UNSAT 334 | SAT 335 | UNSAT 336 | SAT 337 | UNSAT 338 | SAT 339 | UNSAT 340 | SAT 341 | SAT 342 | UNSAT 343 | SAT 344 | UNSAT 345 | SAT 346 | UNSAT 347 | SAT 348 | UNSAT 349 | SAT 350 | UNSAT 351 | SAT 352 | UNSAT 353 | SAT 354 | UNSAT 355 | SAT 356 | UNSAT 357 | SAT 358 | UNSAT 359 | SAT 360 | SAT 361 | UNSAT 362 | SAT 363 | UNSAT 364 | SAT 365 | UNSAT 366 | SAT 367 | UNSAT 368 | SAT 369 | SAT 370 | SAT 371 | SAT 372 | UNSAT 373 | SAT 374 | UNSAT 375 | SAT 376 | UNSAT 377 | SAT 378 | SAT 379 | UNSAT 380 | SAT 381 | UNSAT 382 | SAT 383 | SAT 384 | UNSAT 385 | SAT 386 | UNSAT 387 | SAT 388 | UNSAT 389 | SAT 390 | UNSAT 391 | SAT 392 | UNSAT 393 | SAT 394 | SAT 395 | UNSAT 396 | SAT 397 | UNSAT 398 | SAT 399 | UNSAT 400 | SAT 401 | UNSAT 402 | SAT 403 | UNSAT 404 | SAT 405 | SAT 406 | UNSAT 407 | SAT 408 | UNSAT 409 | SAT 410 | UNSAT 411 | SAT 412 | SAT 413 | UNSAT 414 | SAT 415 | SAT 416 | UNSAT 417 | SAT 418 | SAT 419 | UNSAT 420 | SAT 421 | UNSAT 422 | SAT 423 | UNSAT 424 | SAT 425 | UNSAT 426 | SAT 427 | UNSAT 428 | SAT 429 | SAT 430 | UNSAT 431 | SAT 432 | UNSAT 433 | SAT 434 | UNSAT 435 | SAT 436 | UNSAT 437 | SAT 438 | UNSAT 439 | SAT 440 | UNSAT 441 | SAT 442 | UNSAT 443 | SAT 444 | UNSAT 445 | SAT 446 | UNSAT 447 | SAT 448 | UNSAT 449 | SAT 450 | UNSAT 451 | SAT 452 | UNSAT 453 | SAT 454 | UNSAT 455 | SAT 456 | UNSAT 457 | SAT 458 | UNSAT 459 | SAT 460 | UNSAT 461 | SAT 462 | UNSAT 463 | SAT 464 | SAT 465 | SAT 466 | SAT 467 | SAT 468 | SAT 469 | UNSAT 470 | SAT 471 | UNSAT 472 | SAT 473 | UNSAT 474 | SAT 475 | c done for "regression1.icnf" with minisat 476 | -------------------------------------------------------------------------------- /tests/icnf/regression2.icnf.expected: -------------------------------------------------------------------------------- 1 | c process "regression2.icnf" with minisat 2 | SAT 3 | SAT 4 | UNSAT 5 | SAT 6 | UNSAT 7 | SAT 8 | UNSAT 9 | SAT 10 | UNSAT 11 | SAT 12 | UNSAT 13 | SAT 14 | UNSAT 15 | SAT 16 | SAT 17 | UNSAT 18 | SAT 19 | UNSAT 20 | SAT 21 | UNSAT 22 | SAT 23 | UNSAT 24 | SAT 25 | UNSAT 26 | SAT 27 | SAT 28 | UNSAT 29 | SAT 30 | UNSAT 31 | SAT 32 | UNSAT 33 | SAT 34 | UNSAT 35 | SAT 36 | SAT 37 | UNSAT 38 | SAT 39 | UNSAT 40 | SAT 41 | UNSAT 42 | SAT 43 | UNSAT 44 | SAT 45 | UNSAT 46 | SAT 47 | UNSAT 48 | SAT 49 | UNSAT 50 | SAT 51 | SAT 52 | UNSAT 53 | SAT 54 | UNSAT 55 | SAT 56 | UNSAT 57 | SAT 58 | UNSAT 59 | SAT 60 | UNSAT 61 | SAT 62 | SAT 63 | UNSAT 64 | SAT 65 | UNSAT 66 | SAT 67 | UNSAT 68 | SAT 69 | UNSAT 70 | SAT 71 | UNSAT 72 | SAT 73 | UNSAT 74 | SAT 75 | UNSAT 76 | SAT 77 | UNSAT 78 | SAT 79 | UNSAT 80 | SAT 81 | UNSAT 82 | SAT 83 | SAT 84 | UNSAT 85 | SAT 86 | UNSAT 87 | SAT 88 | UNSAT 89 | SAT 90 | UNSAT 91 | SAT 92 | UNSAT 93 | SAT 94 | UNSAT 95 | SAT 96 | UNSAT 97 | SAT 98 | UNSAT 99 | SAT 100 | SAT 101 | UNSAT 102 | SAT 103 | UNSAT 104 | SAT 105 | UNSAT 106 | SAT 107 | SAT 108 | UNSAT 109 | SAT 110 | UNSAT 111 | SAT 112 | UNSAT 113 | SAT 114 | UNSAT 115 | SAT 116 | UNSAT 117 | SAT 118 | UNSAT 119 | SAT 120 | UNSAT 121 | SAT 122 | SAT 123 | SAT 124 | UNSAT 125 | SAT 126 | SAT 127 | UNSAT 128 | SAT 129 | SAT 130 | SAT 131 | SAT 132 | SAT 133 | SAT 134 | UNSAT 135 | SAT 136 | UNSAT 137 | SAT 138 | UNSAT 139 | SAT 140 | UNSAT 141 | SAT 142 | UNSAT 143 | SAT 144 | UNSAT 145 | SAT 146 | UNSAT 147 | SAT 148 | UNSAT 149 | SAT 150 | UNSAT 151 | SAT 152 | UNSAT 153 | SAT 154 | UNSAT 155 | SAT 156 | UNSAT 157 | SAT 158 | UNSAT 159 | SAT 160 | UNSAT 161 | SAT 162 | UNSAT 163 | SAT 164 | UNSAT 165 | SAT 166 | UNSAT 167 | SAT 168 | UNSAT 169 | SAT 170 | SAT 171 | SAT 172 | UNSAT 173 | SAT 174 | UNSAT 175 | SAT 176 | UNSAT 177 | SAT 178 | UNSAT 179 | SAT 180 | SAT 181 | UNSAT 182 | SAT 183 | UNSAT 184 | SAT 185 | UNSAT 186 | SAT 187 | UNSAT 188 | SAT 189 | UNSAT 190 | SAT 191 | UNSAT 192 | SAT 193 | UNSAT 194 | SAT 195 | UNSAT 196 | SAT 197 | UNSAT 198 | SAT 199 | SAT 200 | UNSAT 201 | SAT 202 | UNSAT 203 | SAT 204 | UNSAT 205 | SAT 206 | UNSAT 207 | SAT 208 | UNSAT 209 | SAT 210 | UNSAT 211 | SAT 212 | SAT 213 | UNSAT 214 | SAT 215 | UNSAT 216 | SAT 217 | UNSAT 218 | SAT 219 | UNSAT 220 | SAT 221 | UNSAT 222 | SAT 223 | UNSAT 224 | SAT 225 | UNSAT 226 | SAT 227 | SAT 228 | SAT 229 | SAT 230 | SAT 231 | SAT 232 | SAT 233 | SAT 234 | UNSAT 235 | SAT 236 | UNSAT 237 | SAT 238 | UNSAT 239 | SAT 240 | UNSAT 241 | SAT 242 | UNSAT 243 | SAT 244 | UNSAT 245 | SAT 246 | UNSAT 247 | SAT 248 | UNSAT 249 | SAT 250 | SAT 251 | c done for "regression2.icnf" with minisat 252 | -------------------------------------------------------------------------------- /tests/phole.ml: -------------------------------------------------------------------------------- 1 | module M = Minisat 2 | 3 | let solve_for (n : int) : bool = 4 | let solver = M.create () in 5 | 6 | (* literal allocator *) 7 | let mklit = 8 | let lits = Hashtbl.create 32 in 9 | let n_ = ref 1 in 10 | fun ~p ~h : M.Lit.t -> 11 | try Hashtbl.find lits (p, h) 12 | with Not_found -> 13 | let lit = M.Lit.make !n_ in 14 | incr n_; 15 | Hashtbl.add lits (p, h) lit; 16 | lit 17 | in 18 | 19 | try 20 | (* each pigeon must be somewhere *) 21 | for p = 1 to n + 1 do 22 | let somewhere = Array.init n (fun h -> mklit ~p ~h:(h + 1)) in 23 | M.add_clause_a solver somewhere 24 | done; 25 | 26 | (* no collision *) 27 | for h = 1 to n do 28 | for p1 = 1 to n + 1 do 29 | for p2 = 1 to p1 - 1 do 30 | let c = [ M.Lit.neg (mklit ~p:p1 ~h); M.Lit.neg (mklit ~p:p2 ~h) ] in 31 | M.add_clause_l solver c 32 | done 33 | done 34 | done; 35 | 36 | M.solve solver; 37 | true 38 | with M.Unsat -> false 39 | 40 | let () = 41 | let n = int_of_string Sys.argv.(1) in 42 | let sat = solve_for n in 43 | assert (not sat) 44 | -------------------------------------------------------------------------------- /tests/test1.ml: -------------------------------------------------------------------------------- 1 | print_endline "test1..." 2 | 3 | let s = Minisat.create () 4 | let l1 = Minisat.Lit.make 1 5 | let l2 = Minisat.Lit.make 2 6 | let l3 = Minisat.Lit.make 3;; 7 | 8 | l1;; 9 | Minisat.Lit.neg l1;; 10 | Minisat.Lit.neg l2;; 11 | l1, Minisat.Lit.neg l1, l2, Minisat.Lit.neg l2 12 | 13 | let () = 14 | Minisat.add_clause_l s [ l1; Minisat.Lit.neg l2 ]; 15 | Minisat.add_clause_l s [ Minisat.Lit.neg l1; l2 ]; 16 | Minisat.add_clause_l s [ Minisat.Lit.neg l1; Minisat.Lit.neg l3 ]; 17 | Minisat.add_clause_l s [ l1; Minisat.Lit.neg l3 ]; 18 | Minisat.solve s 19 | ;; 20 | 21 | Minisat.value s l1;; 22 | Minisat.value s l2 23 | 24 | let () = 25 | print_endline "should succeed..."; 26 | Minisat.solve s; 27 | (* should not fail *) 28 | print_endline "ok!" 29 | 30 | let () = 31 | print_endline "should fail..."; 32 | try 33 | Minisat.solve ~assumptions:[| l3 |] s; 34 | assert false 35 | with Minisat.Unsat -> 36 | print_endline "ok!"; 37 | 38 | print_endline "should succeed..."; 39 | let confl = Minisat.unsat_core s in 40 | Printf.printf "core has size %d\n" (Array.length confl); 41 | Array.iter 42 | (fun l -> Printf.printf "core contains %s\n" (Minisat.Lit.to_string l)) 43 | confl; 44 | assert (confl = [| l3 |]); 45 | print_endline "ok..."; 46 | () 47 | 48 | (* should fail *) 49 | 50 | let () = 51 | print_endline "should succeed..."; 52 | Minisat.solve s 53 | ;; 54 | 55 | (* should not fail *) 56 | l3, Minisat.value s l3, Minisat.value s (Minisat.Lit.neg l3);; 57 | assert (Minisat.value s l3 = Minisat.V_false);; 58 | assert (Minisat.value s (Minisat.Lit.neg l3) = Minisat.V_true);; 59 | print_endline "ok!";; 60 | print_endline "should succeed..." 61 | 62 | let l2000 = Minisat.Lit.make 2000;; 63 | 64 | assert (Minisat.value s l2000 = Minisat.V_undef);; 65 | assert (Minisat.value s (Minisat.Lit.neg l2000) = Minisat.V_undef);; 66 | print_endline "ok!" 67 | --------------------------------------------------------------------------------