mirror of
https://github.com/c-cube/sidekick.git
synced 2026-01-30 13:17:28 -05:00
big refactoring
- move to jbuilder - use a functorial heap (with indices embedded in lit/var) - update Vec with optims from mc2 - change semantics of Vec.shrink - use new Log module
This commit is contained in:
parent
fc5a2d4e9d
commit
ac50e10788
63 changed files with 722 additions and 670 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -8,5 +8,6 @@ _build/
|
||||||
*.docdir
|
*.docdir
|
||||||
src/util/log.ml
|
src/util/log.ml
|
||||||
doc/index.html
|
doc/index.html
|
||||||
|
*.exe
|
||||||
msat
|
.merlin
|
||||||
|
*.install
|
||||||
|
|
|
||||||
20
.merlin
20
.merlin
|
|
@ -1,20 +0,0 @@
|
||||||
S src/core
|
|
||||||
S src/solver
|
|
||||||
S src/sat
|
|
||||||
S src/smt
|
|
||||||
S src/mcsat
|
|
||||||
S src/backend
|
|
||||||
S src/util
|
|
||||||
S tests
|
|
||||||
|
|
||||||
B _build/src/
|
|
||||||
B _build/src/core
|
|
||||||
B _build/src/solver
|
|
||||||
B _build/src/sat
|
|
||||||
B _build/src/smt
|
|
||||||
B _build/src/mcsat
|
|
||||||
B _build/src/util
|
|
||||||
B _build/src/backend
|
|
||||||
B _build/tests
|
|
||||||
|
|
||||||
PKG dolmen
|
|
||||||
31
META
31
META
|
|
@ -1,31 +0,0 @@
|
||||||
# meta
|
|
||||||
name="msat"
|
|
||||||
version="dev"
|
|
||||||
description="MSAT is a modular SAT solver, plus extensions"
|
|
||||||
requires=""
|
|
||||||
archive(byte) = "msat.cma"
|
|
||||||
archive(byte, plugin) = "msat.cma"
|
|
||||||
archive(native) = "msat.cmxa"
|
|
||||||
archive(native, plugin) = "msat.cmxs"
|
|
||||||
|
|
||||||
package "sat" (
|
|
||||||
version = "dev"
|
|
||||||
description = "SAT solver instance"
|
|
||||||
requires = "msat"
|
|
||||||
archive(byte) = "msat_sat.cma"
|
|
||||||
archive(byte, plugin) = "msat_sat.cma"
|
|
||||||
archive(native) = "msat_sat.cmxa"
|
|
||||||
archive(native, plugin) = "msat_sat.cmxs"
|
|
||||||
exists_if = "msat_sat.cma"
|
|
||||||
)
|
|
||||||
|
|
||||||
package "smt" (
|
|
||||||
version = "dev"
|
|
||||||
description = "SMT solver instance"
|
|
||||||
requires = "msat"
|
|
||||||
archive(byte) = "msat_smt.cma"
|
|
||||||
archive(byte, plugin) = "msat_smt.cma"
|
|
||||||
archive(native) = "msat_smt.cmxa"
|
|
||||||
archive(native, plugin) = "msat_smt.cmxs"
|
|
||||||
exists_if = "msat_smt.cma"
|
|
||||||
)
|
|
||||||
70
Makefile
70
Makefile
|
|
@ -1,62 +1,68 @@
|
||||||
# copyright (c) 2014, guillaume bury
|
# copyright (c) 2014, guillaume bury
|
||||||
|
# copyright (c) 2017, simon cruanes
|
||||||
|
|
||||||
LOG=build.log
|
|
||||||
COMP=ocamlbuild -log $(LOG) -use-ocamlfind
|
|
||||||
FLAGS=
|
|
||||||
DOC=src/msat.docdir/index.html
|
|
||||||
BIN=main.native
|
BIN=main.native
|
||||||
TEST_BIN=tests/test_api.native
|
TEST_BIN=tests/test_api.native
|
||||||
|
|
||||||
NAME=msat
|
NAME=msat
|
||||||
|
J?=3
|
||||||
|
TIMEOUT?=30
|
||||||
|
TARGETS=src/bin/main.exe
|
||||||
|
OPTS= -j $(J)
|
||||||
|
|
||||||
LIB=$(addprefix $(NAME), .cma .cmxa .cmxs)
|
LIB=$(addprefix $(NAME), .cma .cmxa .cmxs)
|
||||||
|
|
||||||
all: lib test
|
all: lib test
|
||||||
|
|
||||||
lib:
|
build:
|
||||||
$(COMP) $(FLAGS) $(LIB)
|
jbuilder build $(OPTS) @install
|
||||||
|
|
||||||
doc:
|
build-dev:
|
||||||
$(COMP) $(FLAGS) $(DOC)
|
jbuilder build $(OPTS) @install --dev
|
||||||
|
|
||||||
bin:
|
test: build
|
||||||
$(COMP) $(FLAGS) $(BIN)
|
|
||||||
cp $(BIN) $(NAME) && rm $(BIN)
|
|
||||||
|
|
||||||
test_bin:
|
|
||||||
$(COMP) $(FLAGS) $(TEST_BIN)
|
|
||||||
|
|
||||||
test: bin test_bin
|
|
||||||
@echo "run API tests…"
|
@echo "run API tests…"
|
||||||
@./test_api.native
|
jbuilder runtest
|
||||||
@echo "run benchmarks…"
|
@echo "run benchmarks…"
|
||||||
# @/usr/bin/time -f "%e" ./tests/run smt
|
# @/usr/bin/time -f "%e" ./tests/run smt
|
||||||
@/usr/bin/time -f "%e" ./tests/run mcsat
|
@/usr/bin/time -f "%e" ./tests/run mcsat
|
||||||
|
|
||||||
enable_log:
|
enable_log:
|
||||||
cd src/util; ln -sf log_real.ml log.ml
|
cd src/core; ln -sf log_real.ml log.ml
|
||||||
|
|
||||||
disable_log:
|
disable_log:
|
||||||
cd src/util; ln -sf log_dummy.ml log.ml
|
cd src/core; ln -sf log_dummy.ml log.ml
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(COMP) -clean
|
jbuilder clean
|
||||||
rm -rf $(NAME)
|
|
||||||
|
|
||||||
TO_INSTALL_LIB=$(addsuffix .a, $(NAME)) $(addsuffix .cmi, $(NAME))
|
install: build-install
|
||||||
TO_INSTALL=META $(addprefix _build/src/,$(LIB) $(TO_INSTALL_LIB))
|
jbuilder install
|
||||||
|
|
||||||
install: lib
|
|
||||||
ocamlfind install $(NAME) $(TO_INSTALL)
|
|
||||||
if [ -d "$(NAME).docdir" ]; then \
|
|
||||||
mkdir -p $(DOCDIR) ; \
|
|
||||||
cp -v $(NAME).docdir/*.html $(NAME).docdir/*.css $(DOCDIR) ; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
ocamlfind remove $(NAME)
|
jbuilder uninstall
|
||||||
rm -rf $(DOCDIR)
|
|
||||||
|
doc:
|
||||||
|
jbuilder build $(OPTS) @doc
|
||||||
|
|
||||||
|
|
||||||
reinstall: | uninstall install
|
reinstall: | uninstall install
|
||||||
|
|
||||||
|
ocp-indent:
|
||||||
|
@which ocp-indent > /dev/null || { \
|
||||||
|
echo 'ocp-indent not found; please run `opam install ocp-indent`'; \
|
||||||
|
exit 1 ; \
|
||||||
|
}
|
||||||
|
|
||||||
|
reindent: ocp-indent
|
||||||
|
@find src '(' -name '*.ml' -or -name '*.mli' ')' -print0 | xargs -0 echo "reindenting: "
|
||||||
|
@find src '(' -name '*.ml' -or -name '*.mli' ')' -print0 | xargs -0 ocp-indent -i
|
||||||
|
|
||||||
|
WATCH=build-dev
|
||||||
|
watch:
|
||||||
|
while find src/ -print0 | xargs -0 inotifywait -e delete_self -e modify ; do \
|
||||||
|
echo "============ at `date` ==========" ; \
|
||||||
|
make $(WATCH); \
|
||||||
|
done
|
||||||
|
|
||||||
.PHONY: clean doc all bench install uninstall remove reinstall enable_log disable_log bin test
|
.PHONY: clean doc all bench install uninstall remove reinstall enable_log disable_log bin test
|
||||||
|
|
|
||||||
35
_tags
35
_tags
|
|
@ -1,35 +0,0 @@
|
||||||
# colors
|
|
||||||
true: bin_annot, color(always)
|
|
||||||
|
|
||||||
# optimization options
|
|
||||||
true: inline(100), optimize(3), unbox_closures, unbox_closures_factor(20)
|
|
||||||
|
|
||||||
# Include paths
|
|
||||||
<src>: include
|
|
||||||
<src/core>: include
|
|
||||||
<src/solver>: include
|
|
||||||
<src/backend>: include
|
|
||||||
<src/util>: include
|
|
||||||
<src/sat>: include
|
|
||||||
<src/smt>: include
|
|
||||||
<src/mcsat>: include
|
|
||||||
|
|
||||||
# Pack options
|
|
||||||
<src/core/*.cmx>: for-pack(Msat)
|
|
||||||
<src/solver/*.cmx>: for-pack(Msat)
|
|
||||||
<src/backend/*.cmx>: for-pack(Msat)
|
|
||||||
<src/util/*.cmx>: for-pack(Msat)
|
|
||||||
<src/sat/sat.cmx>: for-pack(Msat)
|
|
||||||
<src/sat/expr_sat.cmx>: for-pack(Msat)
|
|
||||||
|
|
||||||
# Testing dependencies
|
|
||||||
<src/main.*>: package(dolmen)
|
|
||||||
<src/util/type.*>: package(dolmen)
|
|
||||||
<src/sat/type_sat.*>: package(dolmen)
|
|
||||||
<src/smt/type_smt.*>: package(dolmen)
|
|
||||||
|
|
||||||
# more warnings
|
|
||||||
<src/**/*.ml>: warn_K, warn_Y, warn_X
|
|
||||||
<src/**/*.ml>: short_paths, safe_string, strict_sequence
|
|
||||||
<src/**/*.cm*>: debug
|
|
||||||
|
|
||||||
|
|
@ -3,26 +3,28 @@ name: "msat"
|
||||||
license: "Apache"
|
license: "Apache"
|
||||||
version: "dev"
|
version: "dev"
|
||||||
author: ["Sylvain Conchon" "Alain Mebsout" "Stephane Lecuyer" "Simon Cruanes" "Guillaume Bury"]
|
author: ["Sylvain Conchon" "Alain Mebsout" "Stephane Lecuyer" "Simon Cruanes" "Guillaume Bury"]
|
||||||
maintainer: ["guillaume.bury@gmail.com" "simon.cruanes@inria.fr"]
|
maintainer: ["guillaume.bury@gmail.com" "simon.cruanes.2007@m4x.org"]
|
||||||
build: [
|
build: [
|
||||||
[make "disable_log"]
|
[make "build"]
|
||||||
[make "lib"]
|
|
||||||
]
|
]
|
||||||
build-doc: [
|
build-doc: [
|
||||||
[make "doc"]
|
[make "doc"]
|
||||||
]
|
]
|
||||||
install: [
|
install: [
|
||||||
[make "DOCDIR=%{msat:doc}%" "install"]
|
[make "install"]
|
||||||
]
|
]
|
||||||
remove: [
|
remove: [
|
||||||
[make "DOCDIR=%{msat:doc}%" "uninstall"]
|
[make "uninstall"]
|
||||||
]
|
]
|
||||||
depends: [
|
depends: [
|
||||||
"ocamlfind" {build}
|
"ocamlfind" {build}
|
||||||
"ocamlbuild" {build}
|
"jbuilder" {build}
|
||||||
|
]
|
||||||
|
depopts: [
|
||||||
|
"dolmen"
|
||||||
]
|
]
|
||||||
available: [
|
available: [
|
||||||
ocaml-version >= "4.00.1"
|
ocaml-version >= "4.03.0"
|
||||||
]
|
]
|
||||||
tags: [ "sat" "smt" ]
|
tags: [ "sat" "smt" ]
|
||||||
homepage: "https://github.com/Gbury/mSAT"
|
homepage: "https://github.com/Gbury/mSAT"
|
||||||
31
msat_solver.opam
Normal file
31
msat_solver.opam
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
opam-version: "1.2"
|
||||||
|
name: "msat"
|
||||||
|
license: "Apache"
|
||||||
|
version: "dev"
|
||||||
|
author: ["Sylvain Conchon" "Alain Mebsout" "Stephane Lecuyer" "Simon Cruanes" "Guillaume Bury"]
|
||||||
|
maintainer: ["guillaume.bury@gmail.com" "simon.cruanes.2007@m4x.org"]
|
||||||
|
build: [
|
||||||
|
[make "build"]
|
||||||
|
]
|
||||||
|
build-doc: [
|
||||||
|
[make "doc"]
|
||||||
|
]
|
||||||
|
install: [
|
||||||
|
[make "install"]
|
||||||
|
]
|
||||||
|
remove: [
|
||||||
|
[make "uninstall"]
|
||||||
|
]
|
||||||
|
depends: [
|
||||||
|
"ocamlfind" {build}
|
||||||
|
"jbuilder" {build}
|
||||||
|
"dolmen"
|
||||||
|
]
|
||||||
|
available: [
|
||||||
|
ocaml-version >= "4.03.0"
|
||||||
|
]
|
||||||
|
tags: [ "sat" "smt" ]
|
||||||
|
homepage: "https://github.com/Gbury/mSAT"
|
||||||
|
dev-repo: "https://github.com/Gbury/mSAT.git"
|
||||||
|
bug-reports: "https://github.com/Gbury/mSAT/issues/"
|
||||||
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
|
|
||||||
(* This file is free software, part of mSAT. See file "LICENSE" for more information. *)
|
|
||||||
|
|
||||||
open Ocamlbuild_plugin;;
|
|
||||||
|
|
||||||
let doc_intro = "src/doc.txt";;
|
|
||||||
|
|
||||||
dispatch begin function
|
|
||||||
| After_rules ->
|
|
||||||
(* Documentation index *)
|
|
||||||
dep ["ocaml"; "doc"; "extension:html"] & [doc_intro] ;
|
|
||||||
flag ["ocaml"; "doc"; "extension:html"]
|
|
||||||
& S [ A "-t"; A "mSAT doc"; A "-intro"; P doc_intro ];
|
|
||||||
| _ -> ()
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
MSAT is free software, using the Apache license, see file LICENSE
|
MSAT is free software, using the Apache license, see file LICENSE
|
||||||
Copyright 2015 Guillaume Bury
|
Copyright 2015 Guillaume Bury
|
||||||
*)
|
*)
|
||||||
|
open Msat
|
||||||
|
|
||||||
module type S = Backend_intf.S
|
module type S = Backend_intf.S
|
||||||
|
|
||||||
|
|
@ -71,8 +72,8 @@ module Make(S : Res.S)(A : Arg with type hyp := S.clause
|
||||||
let resolution fmt goal hyp1 hyp2 atom =
|
let resolution fmt goal hyp1 hyp2 atom =
|
||||||
let a = S.St.(atom.var.pa) in
|
let a = S.St.(atom.var.pa) in
|
||||||
let h1, h2 =
|
let h1, h2 =
|
||||||
if Array_util.exists ((==) a) hyp1.S.St.atoms then hyp1, hyp2
|
if Array.exists ((==) a) hyp1.S.St.atoms then hyp1, hyp2
|
||||||
else (assert (Array_util.exists ((==) a) hyp2.S.St.atoms); hyp2, hyp1)
|
else (assert (Array.exists ((==) a) hyp2.S.St.atoms); hyp2, hyp1)
|
||||||
in
|
in
|
||||||
(** Print some debug info *)
|
(** Print some debug info *)
|
||||||
Format.fprintf fmt
|
Format.fprintf fmt
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ Copyright 2015 Guillaume Bury
|
||||||
This module provides an easy way to produce coq scripts
|
This module provides an easy way to produce coq scripts
|
||||||
corresponding to the resolution proofs output by the
|
corresponding to the resolution proofs output by the
|
||||||
sat solver. *)
|
sat solver. *)
|
||||||
|
open Msat
|
||||||
|
|
||||||
module type S = Backend_intf.S
|
module type S = Backend_intf.S
|
||||||
(** Interface for exporting proofs. *)
|
(** Interface for exporting proofs. *)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ MSAT is free software, using the Apache license, see file LICENSE
|
||||||
Copyright 2015 Guillaume Bury
|
Copyright 2015 Guillaume Bury
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
open Msat
|
||||||
|
|
||||||
module type S = Backend_intf.S
|
module type S = Backend_intf.S
|
||||||
|
|
||||||
module type Arg = sig
|
module type Arg = sig
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ Copyright 2014 Simon Cruanes
|
||||||
Work in progress...
|
Work in progress...
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
open Msat
|
||||||
|
|
||||||
module type S = Backend_intf.S
|
module type S = Backend_intf.S
|
||||||
|
|
||||||
module type Arg = sig
|
module type Arg = sig
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ Copyright 2014 Guillaume Bury
|
||||||
Copyright 2014 Simon Cruanes
|
Copyright 2014 Simon Cruanes
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
open Msat
|
||||||
|
|
||||||
module type S = sig
|
module type S = sig
|
||||||
|
|
||||||
type clause
|
type clause
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ Copyright 2014 Simon Cruanes
|
||||||
iCNF formats.
|
iCNF formats.
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
open Msat
|
||||||
|
|
||||||
module type S = sig
|
module type S = sig
|
||||||
|
|
||||||
type clause
|
type clause
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ Copyright 2014 Guillaume Bury
|
||||||
Copyright 2014 Simon Cruanes
|
Copyright 2014 Simon Cruanes
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
open Msat
|
||||||
|
|
||||||
(** Output interface for the backend *)
|
(** Output interface for the backend *)
|
||||||
module type S = Backend_intf.S
|
module type S = Backend_intf.S
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ Copyright 2014 Simon Cruanes
|
||||||
This module provides functions to export proofs into the dot graph format.
|
This module provides functions to export proofs into the dot graph format.
|
||||||
Graphs in dot format can be used to generates images using the graphviz tool.
|
Graphs in dot format can be used to generates images using the graphviz tool.
|
||||||
*)
|
*)
|
||||||
|
open Msat
|
||||||
|
|
||||||
module type S = Backend_intf.S
|
module type S = Backend_intf.S
|
||||||
(** Interface for exporting proofs. *)
|
(** Interface for exporting proofs. *)
|
||||||
|
|
|
||||||
13
src/backend/jbuild
Normal file
13
src/backend/jbuild
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
; vim:ft=lisp:
|
||||||
|
|
||||||
|
; main binary
|
||||||
|
(library
|
||||||
|
((name msat_backend)
|
||||||
|
(public_name msat.backend)
|
||||||
|
(synopsis "proof backends for msat")
|
||||||
|
(libraries (msat))
|
||||||
|
(flags (:standard -w +a-4-42-44-48-50-58-32-60@8 -color always -safe-string))
|
||||||
|
(ocamlopt_flags (:standard -O3 -bin-annot
|
||||||
|
-unbox-closures -unbox-closures-factor 20))
|
||||||
|
))
|
||||||
|
|
||||||
|
|
@ -31,6 +31,11 @@ type ('clause, 'proof) unsat_state = ('clause, 'proof) Solver_intf.unsat_state =
|
||||||
(** returns a persistent proof of the empty clause from the Unsat result. *)
|
(** returns a persistent proof of the empty clause from the Unsat result. *)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type 'clause export = 'clause Solver_intf.export = {
|
||||||
|
hyps: 'clause Vec.t;
|
||||||
|
history: 'clause Vec.t;
|
||||||
|
local: 'clause Vec.t;
|
||||||
|
}
|
||||||
|
|
||||||
module Make
|
module Make
|
||||||
(St : Solver_types.S)
|
(St : Solver_types.S)
|
||||||
|
|
@ -56,8 +61,9 @@ module Make
|
||||||
|
|
||||||
let pp_all lvl status =
|
let pp_all lvl status =
|
||||||
Log.debugf lvl
|
Log.debugf lvl
|
||||||
"@[<v>%s - Full resume:@,@[<hov 2>Trail:@\n%a@]@,@[<hov 2>Temp:@\n%a@]@,@[<hov 2>Hyps:@\n%a@]@,@[<hov 2>Lemmas:@\n%a@]@,@]@."
|
(fun k -> k
|
||||||
(fun k -> k status
|
"@[<v>%s - Full resume:@,@[<hov 2>Trail:@\n%a@]@,@[<hov 2>Temp:@\n%a@]@,@[<hov 2>Hyps:@\n%a@]@,@[<hov 2>Lemmas:@\n%a@]@,@]@."
|
||||||
|
status
|
||||||
(Vec.print ~sep:"" St.pp) (S.trail ())
|
(Vec.print ~sep:"" St.pp) (S.trail ())
|
||||||
(Vec.print ~sep:"" St.pp_clause) (S.temp ())
|
(Vec.print ~sep:"" St.pp_clause) (S.temp ())
|
||||||
(Vec.print ~sep:"" St.pp_clause) (S.hyps ())
|
(Vec.print ~sep:"" St.pp_clause) (S.hyps ())
|
||||||
|
|
@ -98,7 +104,7 @@ module Make
|
||||||
|
|
||||||
let solve ?(assumptions=[]) () =
|
let solve ?(assumptions=[]) () =
|
||||||
try
|
try
|
||||||
S.pop ();
|
S.pop (); (* FIXME: what?! *)
|
||||||
S.push ();
|
S.push ();
|
||||||
S.local assumptions;
|
S.local assumptions;
|
||||||
S.solve ();
|
S.solve ();
|
||||||
|
|
@ -119,19 +125,9 @@ module Make
|
||||||
let new_lit = S.new_lit
|
let new_lit = S.new_lit
|
||||||
let new_atom = S.new_atom
|
let new_atom = S.new_atom
|
||||||
|
|
||||||
(* Dimacs & iCNF export *)
|
let export () : St.clause export =
|
||||||
module D = Dimacs.Make(St)(struct end)
|
|
||||||
|
|
||||||
let export_dimacs fmt () =
|
|
||||||
let hyps = S.hyps () in
|
let hyps = S.hyps () in
|
||||||
let history = S.history () in
|
let history = S.history () in
|
||||||
let local = S.temp () in
|
let local = S.temp () in
|
||||||
D.export fmt ~hyps ~history ~local
|
{hyps; history; local}
|
||||||
|
|
||||||
let export_icnf fmt () =
|
|
||||||
let hyps = S.hyps () in
|
|
||||||
let history = S.history () in
|
|
||||||
let local = S.temp () in
|
|
||||||
D.export_icnf fmt ~hyps ~history ~local
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
155
src/core/Heap.ml
Normal file
155
src/core/Heap.ml
Normal file
|
|
@ -0,0 +1,155 @@
|
||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Cubicle *)
|
||||||
|
(* Combining model checking algorithms and SMT solvers *)
|
||||||
|
(* *)
|
||||||
|
(* Mohamed Iguernelala *)
|
||||||
|
(* Universite Paris-Sud 11 *)
|
||||||
|
(* *)
|
||||||
|
(* Copyright 2011. This file is distributed under the terms of the *)
|
||||||
|
(* Apache Software License version 2.0 *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
module type RANKED = Heap_intf.RANKED
|
||||||
|
|
||||||
|
module type S = Heap_intf.S
|
||||||
|
|
||||||
|
module Make(Elt : RANKED) = struct
|
||||||
|
type elt = Elt.t
|
||||||
|
|
||||||
|
type t = {
|
||||||
|
heap : elt Vec.t;
|
||||||
|
}
|
||||||
|
|
||||||
|
let _absent_index = -1
|
||||||
|
|
||||||
|
let create () =
|
||||||
|
{ heap = Vec.make_empty Elt.dummy; }
|
||||||
|
|
||||||
|
let[@inline] left i = (i lsl 1) + 1 (* i*2 + 1 *)
|
||||||
|
let[@inline] right i = (i + 1) lsl 1 (* (i+1)*2 *)
|
||||||
|
let[@inline] parent i = (i - 1) asr 1 (* (i-1) / 2 *)
|
||||||
|
|
||||||
|
(*
|
||||||
|
let rec heap_property cmp ({heap=heap} as s) i =
|
||||||
|
i >= (Vec.size heap) ||
|
||||||
|
((i = 0 || not(cmp (Vec. get heap i) (Vec.get heap (parent i))))
|
||||||
|
&& heap_property cmp s (left i) && heap_property cmp s (right i))
|
||||||
|
|
||||||
|
let heap_property cmp s = heap_property cmp s 1
|
||||||
|
*)
|
||||||
|
|
||||||
|
(* [elt] is above or at its expected position. Move it up the heap
|
||||||
|
(towards high indices) to restore the heap property *)
|
||||||
|
let percolate_up {heap} (elt:Elt.t) : unit =
|
||||||
|
let pi = ref (parent (Elt.idx elt)) in
|
||||||
|
let i = ref (Elt.idx elt) in
|
||||||
|
while !i <> 0 && Elt.cmp elt (Vec.get heap !pi) do
|
||||||
|
Vec.set heap !i (Vec.get heap !pi);
|
||||||
|
Elt.set_idx (Vec.get heap !i) !i;
|
||||||
|
i := !pi;
|
||||||
|
pi := parent !i
|
||||||
|
done;
|
||||||
|
Vec.set heap !i elt;
|
||||||
|
Elt.set_idx elt !i
|
||||||
|
|
||||||
|
let percolate_down {heap} (elt:Elt.t): unit =
|
||||||
|
let sz = Vec.size heap in
|
||||||
|
let li = ref (left (Elt.idx elt)) in
|
||||||
|
let ri = ref (right (Elt.idx elt)) in
|
||||||
|
let i = ref (Elt.idx elt) in
|
||||||
|
begin
|
||||||
|
try
|
||||||
|
while !li < sz do
|
||||||
|
let child =
|
||||||
|
if !ri < sz && Elt.cmp (Vec.get heap !ri) (Vec.get heap !li)
|
||||||
|
then !ri
|
||||||
|
else !li
|
||||||
|
in
|
||||||
|
if not (Elt.cmp (Vec.get heap child) elt) then raise Exit;
|
||||||
|
Vec.set heap !i (Vec.get heap child);
|
||||||
|
Elt.set_idx (Vec.get heap !i) !i;
|
||||||
|
i := child;
|
||||||
|
li := left !i;
|
||||||
|
ri := right !i
|
||||||
|
done;
|
||||||
|
with Exit -> ()
|
||||||
|
end;
|
||||||
|
Vec.set heap !i elt;
|
||||||
|
Elt.set_idx elt !i
|
||||||
|
|
||||||
|
let[@inline] in_heap x = Elt.idx x >= 0
|
||||||
|
|
||||||
|
let[@inline] decrease s x = assert (in_heap x); percolate_up s x
|
||||||
|
|
||||||
|
(*
|
||||||
|
let increase cmp s n =
|
||||||
|
assert (in_heap s n); percolate_down cmp s (V.get s.indices n)
|
||||||
|
*)
|
||||||
|
|
||||||
|
let filter s filt =
|
||||||
|
let j = ref 0 in
|
||||||
|
let lim = Vec.size s.heap in
|
||||||
|
for i = 0 to lim - 1 do
|
||||||
|
if filt (Vec.get s.heap i) then (
|
||||||
|
Vec.set s.heap !j (Vec.get s.heap i);
|
||||||
|
Elt.set_idx (Vec.get s.heap i) !j;
|
||||||
|
incr j;
|
||||||
|
) else (
|
||||||
|
Elt.set_idx (Vec.get s.heap i) _absent_index;
|
||||||
|
);
|
||||||
|
done;
|
||||||
|
Vec.shrink s.heap (lim - !j);
|
||||||
|
for i = (lim / 2) - 1 downto 0 do
|
||||||
|
percolate_down s (Vec.get s.heap i)
|
||||||
|
done
|
||||||
|
|
||||||
|
let size s = Vec.size s.heap
|
||||||
|
|
||||||
|
let is_empty s = Vec.is_empty s.heap
|
||||||
|
|
||||||
|
let clear {heap} =
|
||||||
|
Vec.iter (fun e -> Elt.set_idx e _absent_index) heap;
|
||||||
|
Vec.clear heap;
|
||||||
|
()
|
||||||
|
|
||||||
|
let insert s elt =
|
||||||
|
if not (in_heap elt) then (
|
||||||
|
Elt.set_idx elt (Vec.size s.heap);
|
||||||
|
Vec.push s.heap elt;
|
||||||
|
percolate_up s elt;
|
||||||
|
)
|
||||||
|
|
||||||
|
let[@inline] grow_to_at_least s sz =
|
||||||
|
Vec.grow_to_at_least s.heap sz
|
||||||
|
|
||||||
|
(*
|
||||||
|
let update cmp s n =
|
||||||
|
assert (heap_property cmp s);
|
||||||
|
begin
|
||||||
|
if in_heap s n then
|
||||||
|
begin
|
||||||
|
percolate_up cmp s (Vec.get s.indices n);
|
||||||
|
percolate_down cmp s (Vec.get s.indices n)
|
||||||
|
end
|
||||||
|
else insert cmp s n
|
||||||
|
end;
|
||||||
|
assert (heap_property cmp s)
|
||||||
|
*)
|
||||||
|
|
||||||
|
let remove_min ({heap} as s) =
|
||||||
|
if Vec.size heap=0 then raise Not_found;
|
||||||
|
let x = Vec.get heap 0 in
|
||||||
|
Elt.set_idx x _absent_index;
|
||||||
|
let new_hd = Vec.last heap in (* heap.last() *)
|
||||||
|
Vec.set heap 0 new_hd;
|
||||||
|
Elt.set_idx new_hd 0;
|
||||||
|
Vec.pop heap; (* remove last *)
|
||||||
|
(* enforce heap property again *)
|
||||||
|
if Vec.size heap > 1 then (
|
||||||
|
percolate_down s new_hd;
|
||||||
|
);
|
||||||
|
x
|
||||||
|
|
||||||
|
end
|
||||||
18
src/core/Heap.mli
Normal file
18
src/core/Heap.mli
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Cubicle *)
|
||||||
|
(* Combining model checking algorithms and SMT solvers *)
|
||||||
|
(* *)
|
||||||
|
(* Mohamed Iguernelala *)
|
||||||
|
(* Universite Paris-Sud 11 *)
|
||||||
|
(* *)
|
||||||
|
(* Copyright 2011. This file is distributed under the terms of the *)
|
||||||
|
(* Apache Software License version 2.0 *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
module type RANKED = Heap_intf.RANKED
|
||||||
|
|
||||||
|
module type S = Heap_intf.S
|
||||||
|
|
||||||
|
module Make(X : RANKED) : S with type elt = X.t
|
||||||
51
src/core/Heap_intf.ml
Normal file
51
src/core/Heap_intf.ml
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
|
||||||
|
module type RANKED = sig
|
||||||
|
type t
|
||||||
|
val idx: t -> int (** Index in heap. return -1 if never set *)
|
||||||
|
val set_idx : t -> int -> unit (** Update index in heap *)
|
||||||
|
val dummy : t
|
||||||
|
val cmp : t -> t -> bool
|
||||||
|
end
|
||||||
|
|
||||||
|
module type S = sig
|
||||||
|
type elt
|
||||||
|
(** Type of elements *)
|
||||||
|
|
||||||
|
type t
|
||||||
|
(** Heap of {!elt}, whose priority is increased or decreased
|
||||||
|
incrementally (see {!decrease} for instance) *)
|
||||||
|
|
||||||
|
val create : unit -> t
|
||||||
|
(** Create a heap *)
|
||||||
|
|
||||||
|
val decrease : t -> elt -> unit
|
||||||
|
(** [decrease h x] decreases the value associated to [x] within [h] *)
|
||||||
|
|
||||||
|
val in_heap : elt -> bool
|
||||||
|
|
||||||
|
(*val increase : (int -> int -> bool) -> t -> int -> unit*)
|
||||||
|
|
||||||
|
val size : t -> int
|
||||||
|
(** Number of integers within the heap *)
|
||||||
|
|
||||||
|
val is_empty : t -> bool
|
||||||
|
|
||||||
|
val clear : t -> unit
|
||||||
|
(** Clear the content of the heap *)
|
||||||
|
|
||||||
|
val insert : t -> elt -> unit
|
||||||
|
(** Insert a new element into the heap *)
|
||||||
|
|
||||||
|
val grow_to_at_least: t -> int -> unit
|
||||||
|
(** Hint: augment the internal capacity of the heap until it reaches at
|
||||||
|
least the given integer *)
|
||||||
|
|
||||||
|
(*val update : (int -> int -> bool) -> t -> int -> unit*)
|
||||||
|
|
||||||
|
val remove_min : t -> elt
|
||||||
|
(** Remove and return the integer that has the lowest value from the heap
|
||||||
|
@raise Not_found if the heap is empty *)
|
||||||
|
|
||||||
|
val filter : t -> (elt -> bool) -> unit
|
||||||
|
(** Filter out values that don't satisfy the predicate *)
|
||||||
|
end
|
||||||
|
|
@ -11,11 +11,18 @@ module Make
|
||||||
and type proof = St.proof)
|
and type proof = St.proof)
|
||||||
(Dummy: sig end)
|
(Dummy: sig end)
|
||||||
= struct
|
= struct
|
||||||
|
|
||||||
module Proof = Res.Make(St)
|
module Proof = Res.Make(St)
|
||||||
|
|
||||||
open St
|
open St
|
||||||
|
|
||||||
|
module H = Heap.Make(struct
|
||||||
|
type t = St.elt
|
||||||
|
let[@inline] cmp i j = get_elt_weight j < get_elt_weight i (* comparison by weight *)
|
||||||
|
let dummy = elt_of_var St.dummy_var
|
||||||
|
let idx = get_elt_idx
|
||||||
|
let set_idx = set_elt_idx
|
||||||
|
end)
|
||||||
|
|
||||||
exception Sat
|
exception Sat
|
||||||
exception Unsat
|
exception Unsat
|
||||||
exception UndecidedLit
|
exception UndecidedLit
|
||||||
|
|
@ -89,7 +96,7 @@ module Make
|
||||||
(* number of toplevel assignments since last call to [simplify ()] *)
|
(* number of toplevel assignments since last call to [simplify ()] *)
|
||||||
|
|
||||||
|
|
||||||
order : Iheap.t;
|
order : H.t;
|
||||||
(* Heap ordered by variable activity *)
|
(* Heap ordered by variable activity *)
|
||||||
|
|
||||||
var_decay : float;
|
var_decay : float;
|
||||||
|
|
@ -147,7 +154,7 @@ module Make
|
||||||
th_levels = Vec.make 100 Plugin.dummy;
|
th_levels = Vec.make 100 Plugin.dummy;
|
||||||
user_levels = Vec.make 10 (-1);
|
user_levels = Vec.make 10 (-1);
|
||||||
|
|
||||||
order = Iheap.init 0;
|
order = H.create();
|
||||||
|
|
||||||
var_incr = 1.;
|
var_incr = 1.;
|
||||||
clause_incr = 1.;
|
clause_incr = 1.;
|
||||||
|
|
@ -183,9 +190,6 @@ module Make
|
||||||
let decision_level () = Vec.size env.elt_levels
|
let decision_level () = Vec.size env.elt_levels
|
||||||
let base_level () = Vec.size env.user_levels
|
let base_level () = Vec.size env.user_levels
|
||||||
|
|
||||||
let f_weight i j =
|
|
||||||
get_elt_weight (St.get_elt j) < get_elt_weight (St.get_elt i)
|
|
||||||
|
|
||||||
(* Are the assumptions currently unsat ? *)
|
(* Are the assumptions currently unsat ? *)
|
||||||
let is_unsat () =
|
let is_unsat () =
|
||||||
match env.unsat_conflict with
|
match env.unsat_conflict with
|
||||||
|
|
@ -226,14 +230,14 @@ module Make
|
||||||
When we add a variable (which wraps a formula), we also need to add all
|
When we add a variable (which wraps a formula), we also need to add all
|
||||||
its subterms.
|
its subterms.
|
||||||
*)
|
*)
|
||||||
let rec insert_var_order = function
|
let rec insert_var_order (elt:elt) : unit =
|
||||||
| E_lit l ->
|
H.insert env.order elt;
|
||||||
Iheap.insert f_weight env.order l.lid
|
begin match elt with
|
||||||
| E_var v ->
|
| E_lit _ -> ()
|
||||||
Iheap.insert f_weight env.order v.vid;
|
| E_var v -> insert_subterms_order v
|
||||||
insert_subterms_order v
|
end
|
||||||
|
|
||||||
and insert_subterms_order v =
|
and insert_subterms_order (v:St.var) : unit =
|
||||||
iter_sub (fun t -> insert_var_order (elt_of_lit t)) v
|
iter_sub (fun t -> insert_var_order (elt_of_lit t)) v
|
||||||
|
|
||||||
(* Add new litterals/atoms on which to decide on, even if there is no
|
(* Add new litterals/atoms on which to decide on, even if there is no
|
||||||
|
|
@ -269,8 +273,10 @@ module Make
|
||||||
done;
|
done;
|
||||||
env.var_incr <- env.var_incr *. 1e-100;
|
env.var_incr <- env.var_incr *. 1e-100;
|
||||||
end;
|
end;
|
||||||
if Iheap.in_heap env.order v.vid then
|
let elt = elt_of_var v in
|
||||||
Iheap.decrease f_weight env.order v.vid
|
if H.in_heap elt then (
|
||||||
|
H.decrease env.order elt
|
||||||
|
)
|
||||||
|
|
||||||
(* increase activity of literal [l] *)
|
(* increase activity of literal [l] *)
|
||||||
let lit_bump_activity_aux (l:lit): unit =
|
let lit_bump_activity_aux (l:lit): unit =
|
||||||
|
|
@ -281,8 +287,10 @@ module Make
|
||||||
done;
|
done;
|
||||||
env.var_incr <- env.var_incr *. 1e-100;
|
env.var_incr <- env.var_incr *. 1e-100;
|
||||||
end;
|
end;
|
||||||
if Iheap.in_heap env.order l.lid then
|
let elt = elt_of_lit l in
|
||||||
Iheap.decrease f_weight env.order l.lid
|
if H.in_heap elt then (
|
||||||
|
H.decrease env.order elt
|
||||||
|
)
|
||||||
|
|
||||||
(* increase activity of var [v] *)
|
(* increase activity of var [v] *)
|
||||||
let var_bump_activity (v:var): unit =
|
let var_bump_activity (v:var): unit =
|
||||||
|
|
@ -408,7 +416,7 @@ module Make
|
||||||
*)
|
*)
|
||||||
let attach_clause c =
|
let attach_clause c =
|
||||||
assert (not c.attached);
|
assert (not c.attached);
|
||||||
Log.debugf debug "Attaching %a" (fun k -> k St.pp_clause c);
|
Log.debugf debug (fun k -> k "Attaching %a" St.pp_clause c);
|
||||||
Array.iter (fun a -> a.var.used <- a.var.used + 1) c.atoms;
|
Array.iter (fun a -> a.var.used <- a.var.used + 1) c.atoms;
|
||||||
Vec.push c.atoms.(0).neg.watched c;
|
Vec.push c.atoms.(0).neg.watched c;
|
||||||
Vec.push c.atoms.(1).neg.watched c;
|
Vec.push c.atoms.(1).neg.watched c;
|
||||||
|
|
@ -423,9 +431,9 @@ module Make
|
||||||
assert (lvl >= base_level ());
|
assert (lvl >= base_level ());
|
||||||
(* Nothing to do if we try to backtrack to a non-existent level. *)
|
(* Nothing to do if we try to backtrack to a non-existent level. *)
|
||||||
if decision_level () <= lvl then
|
if decision_level () <= lvl then
|
||||||
Log.debugf debug "Already at level <= %d" (fun k -> k lvl)
|
Log.debugf debug (fun k -> k "Already at level <= %d" lvl)
|
||||||
else begin
|
else begin
|
||||||
Log.debugf info "Backtracking to lvl %d" (fun k -> k lvl);
|
Log.debugf info (fun k -> k "Backtracking to lvl %d" lvl);
|
||||||
(* We set the head of the solver and theory queue to what it was. *)
|
(* We set the head of the solver and theory queue to what it was. *)
|
||||||
let head = ref (Vec.get env.elt_levels lvl) in
|
let head = ref (Vec.get env.elt_levels lvl) in
|
||||||
env.elt_head <- !head;
|
env.elt_head <- !head;
|
||||||
|
|
@ -468,17 +476,17 @@ module Make
|
||||||
(* Recover the right theory state. *)
|
(* Recover the right theory state. *)
|
||||||
Plugin.backtrack (Vec.get env.th_levels lvl);
|
Plugin.backtrack (Vec.get env.th_levels lvl);
|
||||||
(* Resize the vectors according to their new size. *)
|
(* Resize the vectors according to their new size. *)
|
||||||
Vec.shrink env.elt_queue ((Vec.size env.elt_queue) - !head);
|
Vec.shrink env.elt_queue !head;
|
||||||
Vec.shrink env.elt_levels ((Vec.size env.elt_levels) - lvl);
|
Vec.shrink env.elt_levels lvl;
|
||||||
Vec.shrink env.th_levels ((Vec.size env.th_levels) - lvl);
|
Vec.shrink env.th_levels lvl;
|
||||||
end;
|
end;
|
||||||
assert (Vec.size env.elt_levels = Vec.size env.th_levels);
|
assert (Vec.size env.elt_levels = Vec.size env.th_levels);
|
||||||
()
|
()
|
||||||
|
|
||||||
(* Unsatisfiability is signaled through an exception, since it can happen
|
(* Unsatisfiability is signaled through an exception, since it can happen
|
||||||
in multiple places (adding new clauses, or solving for instance). *)
|
in multiple places (adding new clauses, or solving for instance). *)
|
||||||
let report_unsat ({atoms=atoms} as confl) : _ =
|
let report_unsat confl : _ =
|
||||||
Log.debugf info "@[Unsat conflict: %a@]" (fun k -> k St.pp_clause confl);
|
Log.debugf info (fun k -> k "@[Unsat conflict: %a@]" St.pp_clause confl);
|
||||||
env.unsat_conflict <- Some confl;
|
env.unsat_conflict <- Some confl;
|
||||||
raise Unsat
|
raise Unsat
|
||||||
|
|
||||||
|
|
@ -492,25 +500,27 @@ module Make
|
||||||
| (Bcp cl) as r ->
|
| (Bcp cl) as r ->
|
||||||
let l, history = partition cl.atoms in
|
let l, history = partition cl.atoms in
|
||||||
begin match l with
|
begin match l with
|
||||||
| [ a ] ->
|
| [_] ->
|
||||||
if history = [] then r
|
if history = [] then (
|
||||||
(* no simplification has been done, so [cl] is actually a clause with only
|
(* no simplification has been done, so [cl] is actually a clause with only
|
||||||
[a], so it is a valid reason for propagating [a]. *)
|
[a], so it is a valid reason for propagating [a]. *)
|
||||||
else begin
|
r
|
||||||
|
) else (
|
||||||
(* Clauses in [history] have been used to simplify [cl] into a clause [tmp_cl]
|
(* Clauses in [history] have been used to simplify [cl] into a clause [tmp_cl]
|
||||||
with only one formula (which is [a]). So we explicitly create that clause
|
with only one formula (which is [a]). So we explicitly create that clause
|
||||||
and set it as the cause for the propagation of [a], that way we can
|
and set it as the cause for the propagation of [a], that way we can
|
||||||
rebuild the whole resolution tree when we want to prove [a]. *)
|
rebuild the whole resolution tree when we want to prove [a]. *)
|
||||||
let c' = make_clause (fresh_lname ()) l (History (cl :: history)) in
|
let c' = make_clause (fresh_lname ()) l (History (cl :: history)) in
|
||||||
Log.debugf debug "Simplified reason: @[<v>%a@,%a@]"
|
Log.debugf debug
|
||||||
(fun k -> k St.pp_clause cl St.pp_clause c');
|
(fun k -> k "Simplified reason: @[<v>%a@,%a@]" St.pp_clause cl St.pp_clause c');
|
||||||
Bcp c'
|
Bcp c'
|
||||||
end
|
)
|
||||||
| _ ->
|
| _ ->
|
||||||
Log.debugf error "@[<v 2>Failed at reason simplification:@,%a@,%a@]"
|
Log.debugf error
|
||||||
(fun k ->
|
(fun k ->
|
||||||
k (Vec.print ~sep:"" St.pp_atom)
|
k "@[<v 2>Failed at reason simplification:@,%a@,%a@]"
|
||||||
(Vec.from_list l (List.length l) St.dummy_atom)
|
(Vec.print ~sep:"" St.pp_atom)
|
||||||
|
(Vec.from_list l St.dummy_atom)
|
||||||
St.pp_clause cl);
|
St.pp_clause cl);
|
||||||
assert false
|
assert false
|
||||||
end
|
end
|
||||||
|
|
@ -520,7 +530,7 @@ module Make
|
||||||
Wrapper function for adding a new propagated formula. *)
|
Wrapper function for adding a new propagated formula. *)
|
||||||
let enqueue_bool a ~level:lvl reason : unit =
|
let enqueue_bool a ~level:lvl reason : unit =
|
||||||
if a.neg.is_true then begin
|
if a.neg.is_true then begin
|
||||||
Log.debugf error "Trying to enqueue a false literal: %a" (fun k->k St.pp_atom a);
|
Log.debugf error (fun k->k "Trying to enqueue a false literal: %a" St.pp_atom a);
|
||||||
assert false
|
assert false
|
||||||
end;
|
end;
|
||||||
assert (not a.is_true && a.var.v_level < 0 &&
|
assert (not a.is_true && a.var.v_level < 0 &&
|
||||||
|
|
@ -533,8 +543,8 @@ module Make
|
||||||
a.var.v_level <- lvl;
|
a.var.v_level <- lvl;
|
||||||
a.var.reason <- Some reason;
|
a.var.reason <- Some reason;
|
||||||
Vec.push env.elt_queue (of_atom a);
|
Vec.push env.elt_queue (of_atom a);
|
||||||
Log.debugf debug "Enqueue (%d): %a"
|
Log.debugf debug
|
||||||
(fun k->k (Vec.size env.elt_queue) pp_atom a)
|
(fun k->k "Enqueue (%d): %a" (Vec.size env.elt_queue) pp_atom a)
|
||||||
|
|
||||||
let enqueue_semantic a terms =
|
let enqueue_semantic a terms =
|
||||||
if a.is_true then ()
|
if a.is_true then ()
|
||||||
|
|
@ -542,24 +552,24 @@ module Make
|
||||||
let l = List.map St.add_term terms in
|
let l = List.map St.add_term terms in
|
||||||
let lvl = List.fold_left (fun acc {l_level; _} ->
|
let lvl = List.fold_left (fun acc {l_level; _} ->
|
||||||
assert (l_level > 0); max acc l_level) 0 l in
|
assert (l_level > 0); max acc l_level) 0 l in
|
||||||
Iheap.grow_to_at_least env.order (St.nb_elt ());
|
H.grow_to_at_least env.order (St.nb_elt ());
|
||||||
enqueue_bool a lvl Semantic
|
enqueue_bool a ~level:lvl Semantic
|
||||||
end
|
end
|
||||||
|
|
||||||
(* MCsat semantic assignment *)
|
(* MCsat semantic assignment *)
|
||||||
let enqueue_assign l value lvl =
|
let enqueue_assign l value lvl =
|
||||||
match l.assigned with
|
match l.assigned with
|
||||||
| Some _ ->
|
| Some _ ->
|
||||||
Log.debugf error "Trying to assign an already assigned literal: %a"
|
Log.debugf error
|
||||||
(fun k -> k St.pp_lit l);
|
(fun k -> k "Trying to assign an already assigned literal: %a" St.pp_lit l);
|
||||||
assert false
|
assert false
|
||||||
| None ->
|
| None ->
|
||||||
assert (l.l_level < 0);
|
assert (l.l_level < 0);
|
||||||
l.assigned <- Some value;
|
l.assigned <- Some value;
|
||||||
l.l_level <- lvl;
|
l.l_level <- lvl;
|
||||||
Vec.push env.elt_queue (of_lit l);
|
Vec.push env.elt_queue (of_lit l);
|
||||||
Log.debugf debug "Enqueue (%d): %a"
|
Log.debugf debug
|
||||||
(fun k -> k (Vec.size env.elt_queue) pp_lit l)
|
(fun k -> k "Enqueue (%d): %a" (Vec.size env.elt_queue) pp_lit l)
|
||||||
|
|
||||||
(* evaluate an atom for MCsat, if it's not assigned
|
(* evaluate an atom for MCsat, if it's not assigned
|
||||||
by boolean propagation/decision *)
|
by boolean propagation/decision *)
|
||||||
|
|
@ -579,16 +589,16 @@ module Make
|
||||||
let backtrack_lvl : atom list -> int * bool = function
|
let backtrack_lvl : atom list -> int * bool = function
|
||||||
| [] | [_] ->
|
| [] | [_] ->
|
||||||
0, true
|
0, true
|
||||||
| a :: b :: r ->
|
| a :: b :: _ ->
|
||||||
assert(a.var.v_level > base_level ());
|
assert(a.var.v_level > base_level ());
|
||||||
if a.var.v_level > b.var.v_level then begin
|
if a.var.v_level > b.var.v_level then (
|
||||||
(* backtrack below [a], so we can propagate [not a] *)
|
(* backtrack below [a], so we can propagate [not a] *)
|
||||||
b.var.v_level, true
|
b.var.v_level, true
|
||||||
end else begin
|
) else (
|
||||||
assert (a.var.v_level = b.var.v_level);
|
assert (a.var.v_level = b.var.v_level);
|
||||||
assert (a.var.v_level >= base_level ());
|
assert (a.var.v_level >= base_level ());
|
||||||
max (a.var.v_level - 1) (base_level ()), false
|
max (a.var.v_level - 1) (base_level ()), false
|
||||||
end
|
)
|
||||||
|
|
||||||
(* result of conflict analysis, containing the learnt clause and some
|
(* result of conflict analysis, containing the learnt clause and some
|
||||||
additional info.
|
additional info.
|
||||||
|
|
@ -624,14 +634,14 @@ module Make
|
||||||
let conflict_level =
|
let conflict_level =
|
||||||
Array.fold_left (fun acc p -> max acc p.var.v_level) 0 c_clause.atoms
|
Array.fold_left (fun acc p -> max acc p.var.v_level) 0 c_clause.atoms
|
||||||
in
|
in
|
||||||
Log.debugf debug "Analyzing conflict (%d): %a"
|
Log.debugf debug
|
||||||
(fun k -> k conflict_level St.pp_clause c_clause);
|
(fun k -> k "Analyzing conflict (%d): %a" conflict_level St.pp_clause c_clause);
|
||||||
while !cond do
|
while !cond do
|
||||||
begin match !c with
|
begin match !c with
|
||||||
| None ->
|
| None ->
|
||||||
Log.debugf debug " skipping resolution for semantic propagation" (fun k->k)
|
Log.debug debug " skipping resolution for semantic propagation"
|
||||||
| Some clause ->
|
| Some clause ->
|
||||||
Log.debugf debug " Resolving clause: %a" (fun k->k St.pp_clause clause);
|
Log.debugf debug (fun k->k" Resolving clause: %a" St.pp_clause clause);
|
||||||
begin match clause.cpremise with
|
begin match clause.cpremise with
|
||||||
| History _ -> clause_bump_activity clause
|
| History _ -> clause_bump_activity clause
|
||||||
| Hyp | Local | Lemma _ -> ()
|
| Hyp | Local | Lemma _ -> ()
|
||||||
|
|
@ -666,7 +676,7 @@ module Make
|
||||||
(* look for the next node to expand *)
|
(* look for the next node to expand *)
|
||||||
while
|
while
|
||||||
let a = Vec.get env.elt_queue !tr_ind in
|
let a = Vec.get env.elt_queue !tr_ind in
|
||||||
Log.debugf debug " looking at: %a" (fun k -> k St.pp a);
|
Log.debugf debug (fun k -> k " looking at: %a" St.pp a);
|
||||||
match a with
|
match a with
|
||||||
| Atom q ->
|
| Atom q ->
|
||||||
(not (q.var.seen = Both)) ||
|
(not (q.var.seen = Both)) ||
|
||||||
|
|
@ -690,7 +700,7 @@ module Make
|
||||||
assert (n > 0);
|
assert (n > 0);
|
||||||
assert (p.var.v_level >= conflict_level);
|
assert (p.var.v_level >= conflict_level);
|
||||||
c := Some cl
|
c := Some cl
|
||||||
| n, _ -> assert false
|
| _ -> assert false
|
||||||
done;
|
done;
|
||||||
List.iter (fun q -> clear q.var) !seen;
|
List.iter (fun q -> clear q.var) !seen;
|
||||||
let l = List.fast_sort (fun p q -> compare q.var.v_level p.var.v_level) !learnt in
|
let l = List.fast_sort (fun p q -> compare q.var.v_level p.var.v_level) !learnt in
|
||||||
|
|
@ -745,12 +755,12 @@ module Make
|
||||||
- report unsat if conflict at level 0
|
- report unsat if conflict at level 0
|
||||||
*)
|
*)
|
||||||
let add_boolean_conflict (confl:clause): unit =
|
let add_boolean_conflict (confl:clause): unit =
|
||||||
Log.debugf info "Boolean conflict: %a" (fun k -> k St.pp_clause confl);
|
Log.debugf info (fun k -> k "Boolean conflict: %a" St.pp_clause confl);
|
||||||
env.next_decision <- None;
|
env.next_decision <- None;
|
||||||
env.conflicts <- env.conflicts + 1;
|
env.conflicts <- env.conflicts + 1;
|
||||||
assert (decision_level() >= base_level ());
|
assert (decision_level() >= base_level ());
|
||||||
if decision_level() = base_level ()
|
if decision_level() = base_level ()
|
||||||
|| Array_util.for_all (fun a -> a.var.v_level <= base_level ()) confl.atoms then
|
|| Array.for_all (fun a -> a.var.v_level <= base_level ()) confl.atoms then
|
||||||
report_unsat confl; (* Top-level conflict *)
|
report_unsat confl; (* Top-level conflict *)
|
||||||
let cr = analyze confl in
|
let cr = analyze confl in
|
||||||
cancel_until (max cr.cr_backtrack_lvl (base_level ()));
|
cancel_until (max cr.cr_backtrack_lvl (base_level ()));
|
||||||
|
|
@ -766,14 +776,14 @@ module Make
|
||||||
(* Add a new clause, simplifying, propagating, and backtracking if
|
(* Add a new clause, simplifying, propagating, and backtracking if
|
||||||
the clause is false in the current trail *)
|
the clause is false in the current trail *)
|
||||||
let add_clause (init:clause) : unit =
|
let add_clause (init:clause) : unit =
|
||||||
Log.debugf debug "Adding clause: @[<hov>%a@]" (fun k -> k St.pp_clause init);
|
Log.debugf debug (fun k -> k "Adding clause: @[<hov>%a@]" St.pp_clause init);
|
||||||
(* Insertion of new lits is done before simplification. Indeed, else a lit in a
|
(* Insertion of new lits is done before simplification. Indeed, else a lit in a
|
||||||
trivial clause could end up being not decided on, which is a bug. *)
|
trivial clause could end up being not decided on, which is a bug. *)
|
||||||
Array.iter (fun x -> insert_var_order (elt_of_var x.var)) init.atoms;
|
Array.iter (fun x -> insert_var_order (elt_of_var x.var)) init.atoms;
|
||||||
let vec = clause_vector init in
|
let vec = clause_vector init in
|
||||||
try
|
try
|
||||||
let c = eliminate_doublons init in
|
let c = eliminate_doublons init in
|
||||||
Log.debugf debug "Doublons eliminated: %a" (fun k -> k St.pp_clause c);
|
Log.debugf debug (fun k -> k "Doublons eliminated: %a" St.pp_clause c);
|
||||||
let atoms, history = partition c.atoms in
|
let atoms, history = partition c.atoms in
|
||||||
let clause =
|
let clause =
|
||||||
if history = []
|
if history = []
|
||||||
|
|
@ -784,7 +794,7 @@ module Make
|
||||||
)
|
)
|
||||||
else make_clause (fresh_name ()) atoms (History (c :: history))
|
else make_clause (fresh_name ()) atoms (History (c :: history))
|
||||||
in
|
in
|
||||||
Log.debugf info "New clause: @[<hov>%a@]" (fun k->k St.pp_clause clause);
|
Log.debugf info (fun k->k "New clause: @[<hov>%a@]" St.pp_clause clause);
|
||||||
match atoms with
|
match atoms with
|
||||||
| [] ->
|
| [] ->
|
||||||
(* Report_unsat will raise, and the current clause will be lost if we do not
|
(* Report_unsat will raise, and the current clause will be lost if we do not
|
||||||
|
|
@ -798,7 +808,7 @@ module Make
|
||||||
(* Since we cannot propagate the atom [a], in order to not lose
|
(* Since we cannot propagate the atom [a], in order to not lose
|
||||||
the information that [a] must be true, we add clause to the list
|
the information that [a] must be true, we add clause to the list
|
||||||
of clauses to add, so that it will be e-examined later. *)
|
of clauses to add, so that it will be e-examined later. *)
|
||||||
Log.debugf debug "Unit clause, adding to clauses to add" (fun k -> k);
|
Log.debug debug "Unit clause, adding to clauses to add";
|
||||||
Stack.push clause env.clauses_to_add;
|
Stack.push clause env.clauses_to_add;
|
||||||
report_unsat clause
|
report_unsat clause
|
||||||
end else if a.is_true then begin
|
end else if a.is_true then begin
|
||||||
|
|
@ -806,12 +816,12 @@ module Make
|
||||||
However it means we can't propagate it at level 0. In order to not lose
|
However it means we can't propagate it at level 0. In order to not lose
|
||||||
that information, we store the clause in a stack of clauses that we will
|
that information, we store the clause in a stack of clauses that we will
|
||||||
add to the solver at the next pop. *)
|
add to the solver at the next pop. *)
|
||||||
Log.debugf debug "Unit clause, adding to root clauses" (fun k -> k);
|
Log.debug debug "Unit clause, adding to root clauses";
|
||||||
assert (0 < a.var.v_level && a.var.v_level <= base_level ());
|
assert (0 < a.var.v_level && a.var.v_level <= base_level ());
|
||||||
Stack.push clause env.clauses_root;
|
Stack.push clause env.clauses_root;
|
||||||
()
|
()
|
||||||
end else begin
|
end else begin
|
||||||
Log.debugf debug "Unit clause, propagating: %a" (fun k->k St.pp_atom a);
|
Log.debugf debug (fun k->k "Unit clause, propagating: %a" St.pp_atom a);
|
||||||
Vec.push vec clause;
|
Vec.push vec clause;
|
||||||
enqueue_bool a ~level:0 (Bcp clause)
|
enqueue_bool a ~level:0 (Bcp clause)
|
||||||
end
|
end
|
||||||
|
|
@ -830,18 +840,18 @@ module Make
|
||||||
if b.neg.is_true && not a.is_true && not a.neg.is_true then begin
|
if b.neg.is_true && not a.is_true && not a.neg.is_true then begin
|
||||||
let lvl = List.fold_left (fun m a -> max m a.var.v_level) 0 atoms in
|
let lvl = List.fold_left (fun m a -> max m a.var.v_level) 0 atoms in
|
||||||
cancel_until (max lvl (base_level ()));
|
cancel_until (max lvl (base_level ()));
|
||||||
enqueue_bool a lvl (Bcp clause)
|
enqueue_bool a ~level:lvl (Bcp clause)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
with Trivial ->
|
with Trivial ->
|
||||||
Vec.push vec init;
|
Vec.push vec init;
|
||||||
Log.debugf info "Trivial clause ignored : @[%a@]" (fun k->k St.pp_clause init)
|
Log.debugf info (fun k->k "Trivial clause ignored : @[%a@]" St.pp_clause init)
|
||||||
|
|
||||||
let flush_clauses () =
|
let flush_clauses () =
|
||||||
if not (Stack.is_empty env.clauses_to_add) then begin
|
if not (Stack.is_empty env.clauses_to_add) then begin
|
||||||
let nbv = St.nb_elt () in
|
let nbv = St.nb_elt () in
|
||||||
let nbc = env.nb_init_clauses + Stack.length env.clauses_to_add in
|
let nbc = env.nb_init_clauses + Stack.length env.clauses_to_add in
|
||||||
Iheap.grow_to_at_least env.order nbv;
|
H.grow_to_at_least env.order nbv;
|
||||||
Vec.grow_to_at_least env.clauses_hyps nbc;
|
Vec.grow_to_at_least env.clauses_hyps nbc;
|
||||||
Vec.grow_to_at_least env.clauses_learnt nbc;
|
Vec.grow_to_at_least env.clauses_learnt nbc;
|
||||||
env.nb_init_clauses <- nbc;
|
env.nb_init_clauses <- nbc;
|
||||||
|
|
@ -894,7 +904,7 @@ module Make
|
||||||
end else begin
|
end else begin
|
||||||
match th_eval first with
|
match th_eval first with
|
||||||
| None -> (* clause is unit, keep the same watches, but propagate *)
|
| None -> (* clause is unit, keep the same watches, but propagate *)
|
||||||
enqueue_bool first (decision_level ()) (Bcp c)
|
enqueue_bool first ~level:(decision_level ()) (Bcp c)
|
||||||
| Some true -> ()
|
| Some true -> ()
|
||||||
| Some false ->
|
| Some false ->
|
||||||
env.elt_head <- Vec.size env.elt_queue;
|
env.elt_head <- Vec.size env.elt_queue;
|
||||||
|
|
@ -942,14 +952,14 @@ module Make
|
||||||
match Vec.get env.elt_queue i with
|
match Vec.get env.elt_queue i with
|
||||||
| Atom a ->
|
| Atom a ->
|
||||||
Plugin_intf.Lit a.lit
|
Plugin_intf.Lit a.lit
|
||||||
| Lit {term; assigned = Some v} ->
|
| Lit {term; assigned = Some v; _} ->
|
||||||
Plugin_intf.Assign (term, v)
|
Plugin_intf.Assign (term, v)
|
||||||
| Lit _ -> assert false
|
| Lit _ -> assert false
|
||||||
|
|
||||||
let slice_push (l:formula list) (lemma:proof): unit =
|
let slice_push (l:formula list) (lemma:proof): unit =
|
||||||
let atoms = List.rev_map create_atom l in
|
let atoms = List.rev_map create_atom l in
|
||||||
let c = make_clause (fresh_tname ()) atoms (Lemma lemma) in
|
let c = make_clause (fresh_tname ()) atoms (Lemma lemma) in
|
||||||
Log.debugf info "Pushing clause %a" (fun k->k St.pp_clause c);
|
Log.debugf info (fun k->k "Pushing clause %a" St.pp_clause c);
|
||||||
Stack.push c env.clauses_to_add
|
Stack.push c env.clauses_to_add
|
||||||
|
|
||||||
let slice_propagate f = function
|
let slice_propagate f = function
|
||||||
|
|
@ -966,9 +976,9 @@ module Make
|
||||||
else if p.neg.is_true then
|
else if p.neg.is_true then
|
||||||
Stack.push c env.clauses_to_add
|
Stack.push c env.clauses_to_add
|
||||||
else begin
|
else begin
|
||||||
Iheap.grow_to_at_least env.order (St.nb_elt ());
|
H.grow_to_at_least env.order (St.nb_elt ());
|
||||||
insert_subterms_order p.var;
|
insert_subterms_order p.var;
|
||||||
enqueue_bool p (decision_level ()) (Bcp c)
|
enqueue_bool p ~level:(decision_level ()) (Bcp c)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise (Invalid_argument "Msat.Internal.slice_propagate")
|
raise (Invalid_argument "Msat.Internal.slice_propagate")
|
||||||
|
|
@ -1007,7 +1017,7 @@ module Make
|
||||||
| Plugin_intf.Unsat (l, p) ->
|
| Plugin_intf.Unsat (l, p) ->
|
||||||
(* conflict *)
|
(* conflict *)
|
||||||
let l = List.rev_map create_atom l in
|
let l = List.rev_map create_atom l in
|
||||||
Iheap.grow_to_at_least env.order (St.nb_elt ());
|
H.grow_to_at_least env.order (St.nb_elt ());
|
||||||
List.iter (fun a -> insert_var_order (elt_of_var a.var)) l;
|
List.iter (fun a -> insert_var_order (elt_of_var a.var)) l;
|
||||||
let c = St.make_clause (St.fresh_tname ()) l (Lemma p) in
|
let c = St.make_clause (St.fresh_tname ()) l (Lemma p) in
|
||||||
Some c
|
Some c
|
||||||
|
|
@ -1057,7 +1067,7 @@ module Make
|
||||||
env.decisions <- env.decisions + 1;
|
env.decisions <- env.decisions + 1;
|
||||||
new_decision_level();
|
new_decision_level();
|
||||||
let current_level = decision_level () in
|
let current_level = decision_level () in
|
||||||
enqueue_bool atom current_level Decision
|
enqueue_bool atom ~level:current_level Decision
|
||||||
| Plugin_intf.Valued (b, l) ->
|
| Plugin_intf.Valued (b, l) ->
|
||||||
let a = if b then atom else atom.neg in
|
let a = if b then atom else atom.neg in
|
||||||
enqueue_semantic a l
|
enqueue_semantic a l
|
||||||
|
|
@ -1069,7 +1079,7 @@ module Make
|
||||||
pick_branch_aux atom
|
pick_branch_aux atom
|
||||||
| None ->
|
| None ->
|
||||||
begin try
|
begin try
|
||||||
begin match St.get_elt (Iheap.remove_min f_weight env.order) with
|
begin match H.remove_min env.order with
|
||||||
| E_lit l ->
|
| E_lit l ->
|
||||||
if l.l_level >= 0 then
|
if l.l_level >= 0 then
|
||||||
pick_branch_lit ()
|
pick_branch_lit ()
|
||||||
|
|
@ -1110,7 +1120,7 @@ module Make
|
||||||
if Vec.size env.elt_queue = St.nb_elt ()
|
if Vec.size env.elt_queue = St.nb_elt ()
|
||||||
then raise Sat;
|
then raise Sat;
|
||||||
if n_of_conflicts > 0 && !conflictC >= n_of_conflicts then begin
|
if n_of_conflicts > 0 && !conflictC >= n_of_conflicts then begin
|
||||||
Log.debugf info "Restarting..." (fun k -> k);
|
Log.debug info "Restarting...";
|
||||||
cancel_until (base_level ());
|
cancel_until (base_level ());
|
||||||
raise Restart
|
raise Restart
|
||||||
end;
|
end;
|
||||||
|
|
@ -1169,7 +1179,7 @@ module Make
|
||||||
| Plugin_intf.Unsat (l, p) ->
|
| Plugin_intf.Unsat (l, p) ->
|
||||||
let atoms = List.rev_map create_atom l in
|
let atoms = List.rev_map create_atom l in
|
||||||
let c = make_clause (fresh_tname ()) atoms (Lemma p) in
|
let c = make_clause (fresh_tname ()) atoms (Lemma p) in
|
||||||
Log.debugf info "Theory conflict clause: %a" (fun k -> k St.pp_clause c);
|
Log.debugf info (fun k -> k "Theory conflict clause: %a" St.pp_clause c);
|
||||||
Stack.push c env.clauses_to_add
|
Stack.push c env.clauses_to_add
|
||||||
end;
|
end;
|
||||||
if Stack.is_empty env.clauses_to_add then raise Sat
|
if Stack.is_empty env.clauses_to_add then raise Sat
|
||||||
|
|
@ -1182,23 +1192,24 @@ module Make
|
||||||
(fun l ->
|
(fun l ->
|
||||||
let atoms = List.rev_map atom l in
|
let atoms = List.rev_map atom l in
|
||||||
let c = make_clause ?tag (fresh_hname ()) atoms Hyp in
|
let c = make_clause ?tag (fresh_hname ()) atoms Hyp in
|
||||||
Log.debugf debug "Assuming clause: @[<hov 2>%a@]" (fun k -> k pp_clause c);
|
Log.debugf debug (fun k -> k "Assuming clause: @[<hov 2>%a@]" pp_clause c);
|
||||||
Stack.push c env.clauses_to_add)
|
Stack.push c env.clauses_to_add)
|
||||||
cnf
|
cnf
|
||||||
|
|
||||||
(* create a factice decision level for local assumptions *)
|
(* create a factice decision level for local assumptions *)
|
||||||
let push (): unit =
|
let push (): unit =
|
||||||
Log.debugf debug "Pushing a new user level" (fun k -> k);
|
Log.debug debug "Pushing a new user level";
|
||||||
cancel_until (base_level ());
|
cancel_until (base_level ());
|
||||||
Log.debugf debug "@[<v>Status:@,@[<hov 2>trail: %d - %d@,%a@]"
|
Log.debugf debug
|
||||||
(fun k -> k env.elt_head env.th_head (Vec.print ~sep:"" St.pp) env.elt_queue);
|
(fun k -> k "@[<v>Status:@,@[<hov 2>trail: %d - %d@,%a@]"
|
||||||
|
env.elt_head env.th_head (Vec.print ~sep:"" St.pp) env.elt_queue);
|
||||||
begin match propagate () with
|
begin match propagate () with
|
||||||
| Some confl ->
|
| Some confl ->
|
||||||
report_unsat confl
|
report_unsat confl
|
||||||
| None ->
|
| None ->
|
||||||
Log.debugf debug "@[<v>Current trail:@,@[<hov>%a@]@]"
|
Log.debugf debug
|
||||||
(fun k -> k (Vec.print ~sep:"" St.pp) env.elt_queue);
|
(fun k -> k "@[<v>Current trail:@,@[<hov>%a@]@]" (Vec.print ~sep:"" St.pp) env.elt_queue);
|
||||||
Log.debugf info "Creating new user level" (fun k -> k);
|
Log.debug info "Creating new user level";
|
||||||
new_decision_level ();
|
new_decision_level ();
|
||||||
Vec.push env.user_levels (Vec.size env.clauses_temp);
|
Vec.push env.user_levels (Vec.size env.clauses_temp);
|
||||||
assert (decision_level () = base_level ())
|
assert (decision_level () = base_level ())
|
||||||
|
|
@ -1207,9 +1218,9 @@ module Make
|
||||||
(* pop the last factice decision level *)
|
(* pop the last factice decision level *)
|
||||||
let pop (): unit =
|
let pop (): unit =
|
||||||
if base_level () = 0 then
|
if base_level () = 0 then
|
||||||
Log.debugf warn "Cannot pop (already at level 0)" (fun k -> k)
|
Log.debug warn "Cannot pop (already at level 0)"
|
||||||
else begin
|
else begin
|
||||||
Log.debugf info "Popping user level" (fun k -> k);
|
Log.debug info "Popping user level";
|
||||||
assert (base_level () > 0);
|
assert (base_level () > 0);
|
||||||
env.unsat_conflict <- None;
|
env.unsat_conflict <- None;
|
||||||
let n = Vec.last env.user_levels in
|
let n = Vec.last env.user_levels in
|
||||||
|
|
@ -1218,7 +1229,7 @@ module Make
|
||||||
Stack.iter (fun c -> Stack.push c env.clauses_to_add) env.clauses_root;
|
Stack.iter (fun c -> Stack.push c env.clauses_to_add) env.clauses_root;
|
||||||
Stack.clear env.clauses_root;
|
Stack.clear env.clauses_root;
|
||||||
(* remove from env.clauses_temp the now invalid caluses. *)
|
(* remove from env.clauses_temp the now invalid caluses. *)
|
||||||
Vec.shrink env.clauses_temp (Vec.size env.clauses_temp - n);
|
Vec.shrink env.clauses_temp n;
|
||||||
assert (Vec.for_all (fun c -> Array.length c.atoms = 1) env.clauses_temp);
|
assert (Vec.for_all (fun c -> Array.length c.atoms = 1) env.clauses_temp);
|
||||||
assert (Vec.for_all (fun c -> c.atoms.(0).var.v_level <= base_level ()) env.clauses_temp);
|
assert (Vec.for_all (fun c -> c.atoms.(0).var.v_level <= base_level ()) env.clauses_temp);
|
||||||
cancel_until (base_level ())
|
cancel_until (base_level ())
|
||||||
|
|
@ -1228,12 +1239,12 @@ module Make
|
||||||
let local l =
|
let local l =
|
||||||
let aux lit =
|
let aux lit =
|
||||||
let a = atom lit in
|
let a = atom lit in
|
||||||
Log.debugf info "Local assumption: @[%a@]" (fun k-> k pp_atom a);
|
Log.debugf info (fun k-> k "Local assumption: @[%a@]" pp_atom a);
|
||||||
assert (decision_level () = base_level ());
|
assert (decision_level () = base_level ());
|
||||||
if a.is_true then ()
|
if a.is_true then ()
|
||||||
else
|
else
|
||||||
let c = make_clause (fresh_hname ()) [a] Local in
|
let c = make_clause (fresh_hname ()) [a] Local in
|
||||||
Log.debugf debug "Temp clause: @[%a@]" (fun k -> k pp_clause c);
|
Log.debugf debug (fun k -> k "Temp clause: @[%a@]" pp_clause c);
|
||||||
Vec.push env.clauses_temp c;
|
Vec.push env.clauses_temp c;
|
||||||
if a.neg.is_true then begin
|
if a.neg.is_true then begin
|
||||||
(* conflict between assumptions: UNSAT *)
|
(* conflict between assumptions: UNSAT *)
|
||||||
|
|
@ -1241,7 +1252,7 @@ module Make
|
||||||
end else begin
|
end else begin
|
||||||
(* Grow the heap, because when the lit is backtracked,
|
(* Grow the heap, because when the lit is backtracked,
|
||||||
it will be added to the heap. *)
|
it will be added to the heap. *)
|
||||||
Iheap.grow_to_at_least env.order (St.nb_elt ());
|
H.grow_to_at_least env.order (St.nb_elt ());
|
||||||
(* make a decision, propagate *)
|
(* make a decision, propagate *)
|
||||||
let level = decision_level() in
|
let level = decision_level() in
|
||||||
enqueue_bool a ~level (Bcp c);
|
enqueue_bool a ~level (Bcp c);
|
||||||
|
|
@ -1250,11 +1261,11 @@ module Make
|
||||||
assert (base_level () > 0);
|
assert (base_level () > 0);
|
||||||
match env.unsat_conflict with
|
match env.unsat_conflict with
|
||||||
| None ->
|
| None ->
|
||||||
Log.debugf info "Adding local assumption" (fun k -> k);
|
Log.debug info "Adding local assumption";
|
||||||
cancel_until (base_level ());
|
cancel_until (base_level ());
|
||||||
List.iter aux l
|
List.iter aux l
|
||||||
| Some _ ->
|
| Some _ ->
|
||||||
Log.debugf warn "Cannot add local assumption (already unsat)" (fun k -> k)
|
Log.debug warn "Cannot add local assumption (already unsat)"
|
||||||
|
|
||||||
(* Check satisfiability *)
|
(* Check satisfiability *)
|
||||||
let check_clause c =
|
let check_clause c =
|
||||||
|
|
@ -1262,10 +1273,10 @@ module Make
|
||||||
if a.is_true then true
|
if a.is_true then true
|
||||||
else if a.neg.is_true then false
|
else if a.neg.is_true then false
|
||||||
else raise UndecidedLit) c.atoms in
|
else raise UndecidedLit) c.atoms in
|
||||||
let res = Array_util.exists (fun x -> x) tmp in
|
let res = Array.exists (fun x -> x) tmp in
|
||||||
if not res then begin
|
if not res then begin
|
||||||
Log.debugf debug "Clause not satisfied: @[<hov>%a@]"
|
Log.debugf debug
|
||||||
(fun k -> k St.pp_clause c);
|
(fun k -> k "Clause not satisfied: @[<hov>%a@]" St.pp_clause c);
|
||||||
false
|
false
|
||||||
end else
|
end else
|
||||||
true
|
true
|
||||||
|
|
|
||||||
|
|
@ -117,31 +117,30 @@ module Make(St : Solver_types.S) = struct
|
||||||
assert St.(a.var.v_level >= 0);
|
assert St.(a.var.v_level >= 0);
|
||||||
match St.(a.var.reason) with
|
match St.(a.var.reason) with
|
||||||
| Some St.Bcp c ->
|
| Some St.Bcp c ->
|
||||||
Log.debugf debug "Analysing: @[%a@ %a@]"
|
Log.debugf debug (fun k->k "Analysing: @[%a@ %a@]" St.pp_atom a St.pp_clause c);
|
||||||
(fun k -> k St.pp_atom a St.pp_clause c);
|
|
||||||
if Array.length c.St.atoms = 1 then begin
|
if Array.length c.St.atoms = 1 then begin
|
||||||
Log.debugf debug "Old reason: @[%a@]" (fun k -> k St.pp_atom a);
|
Log.debugf debug (fun k -> k "Old reason: @[%a@]" St.pp_atom a);
|
||||||
c
|
c
|
||||||
end else begin
|
end else begin
|
||||||
assert (a.St.neg.St.is_true);
|
assert (a.St.neg.St.is_true);
|
||||||
let r = St.History (c :: (Array.fold_left aux [] c.St.atoms)) in
|
let r = St.History (c :: (Array.fold_left aux [] c.St.atoms)) in
|
||||||
let c' = St.make_clause (fresh_pcl_name ()) [a.St.neg] r in
|
let c' = St.make_clause (fresh_pcl_name ()) [a.St.neg] r in
|
||||||
a.St.var.St.reason <- Some St.(Bcp c');
|
a.St.var.St.reason <- Some St.(Bcp c');
|
||||||
Log.debugf debug "New reason: @[%a@ %a@]"
|
Log.debugf debug
|
||||||
(fun k -> k St.pp_atom a St.pp_clause c');
|
(fun k -> k "New reason: @[%a@ %a@]" St.pp_atom a St.pp_clause c');
|
||||||
c'
|
c'
|
||||||
end
|
end
|
||||||
| _ ->
|
| _ ->
|
||||||
Log.debugf error "Error while proving atom %a" (fun k -> k St.pp_atom a);
|
Log.debugf error (fun k -> k "Error while proving atom %a" St.pp_atom a);
|
||||||
raise (Resolution_error "Cannot prove atom")
|
raise (Resolution_error "Cannot prove atom")
|
||||||
|
|
||||||
let prove_unsat conflict =
|
let prove_unsat conflict =
|
||||||
if Array.length conflict.St.atoms = 0 then conflict
|
if Array.length conflict.St.atoms = 0 then conflict
|
||||||
else begin
|
else begin
|
||||||
Log.debugf info "Proving unsat from: @[%a@]" (fun k -> k St.pp_clause conflict);
|
Log.debugf info (fun k -> k "Proving unsat from: @[%a@]" St.pp_clause conflict);
|
||||||
let l = Array.fold_left (fun acc a -> set_atom_proof a :: acc) [] conflict.St.atoms in
|
let l = Array.fold_left (fun acc a -> set_atom_proof a :: acc) [] conflict.St.atoms in
|
||||||
let res = St.make_clause (fresh_pcl_name ()) [] (St.History (conflict :: l)) in
|
let res = St.make_clause (fresh_pcl_name ()) [] (St.History (conflict :: l)) in
|
||||||
Log.debugf info "Proof found: @[%a@]" (fun k -> k St.pp_clause res);
|
Log.debugf info (fun k -> k "Proof found: @[%a@]" St.pp_clause res);
|
||||||
res
|
res
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -166,8 +165,8 @@ module Make(St : Solver_types.S) = struct
|
||||||
|
|
||||||
let rec chain_res (c, cl) = function
|
let rec chain_res (c, cl) = function
|
||||||
| d :: r ->
|
| d :: r ->
|
||||||
Log.debugf debug " Resolving clauses : @[%a@\n%a@]"
|
Log.debugf debug
|
||||||
(fun k -> k St.pp_clause c St.pp_clause d);
|
(fun k -> k " Resolving clauses : @[%a@\n%a@]" St.pp_clause c St.pp_clause d);
|
||||||
let dl = to_list d in
|
let dl = to_list d in
|
||||||
begin match resolve (merge cl dl) with
|
begin match resolve (merge cl dl) with
|
||||||
| [ a ], l ->
|
| [ a ], l ->
|
||||||
|
|
@ -179,15 +178,15 @@ module Make(St : Solver_types.S) = struct
|
||||||
chain_res (new_clause, l) r
|
chain_res (new_clause, l) r
|
||||||
end
|
end
|
||||||
| _ ->
|
| _ ->
|
||||||
Log.debugf error "While resolving clauses:@[<hov>%a@\n%a@]"
|
Log.debugf error
|
||||||
(fun k -> k St.pp_clause c St.pp_clause d);
|
(fun k -> k "While resolving clauses:@[<hov>%a@\n%a@]" St.pp_clause c St.pp_clause d);
|
||||||
raise (Resolution_error "Clause mismatch")
|
raise (Resolution_error "Clause mismatch")
|
||||||
end
|
end
|
||||||
| _ ->
|
| _ ->
|
||||||
raise (Resolution_error "Bad history")
|
raise (Resolution_error "Bad history")
|
||||||
|
|
||||||
let expand conclusion =
|
let expand conclusion =
|
||||||
Log.debugf debug "Expanding : @[%a@]" (fun k -> k St.pp_clause conclusion);
|
Log.debugf debug (fun k -> k "Expanding : @[%a@]" St.pp_clause conclusion);
|
||||||
match conclusion.St.cpremise with
|
match conclusion.St.cpremise with
|
||||||
| St.Lemma l ->
|
| St.Lemma l ->
|
||||||
{conclusion; step = Lemma l; }
|
{conclusion; step = Lemma l; }
|
||||||
|
|
@ -196,7 +195,7 @@ module Make(St : Solver_types.S) = struct
|
||||||
| St.Local ->
|
| St.Local ->
|
||||||
{ conclusion; step = Assumption; }
|
{ conclusion; step = Assumption; }
|
||||||
| St.History [] ->
|
| St.History [] ->
|
||||||
Log.debugf error "Empty history for clause: %a" (fun k -> k St.pp_clause conclusion);
|
Log.debugf error (fun k -> k "Empty history for clause: %a" St.pp_clause conclusion);
|
||||||
raise (Resolution_error "Empty history")
|
raise (Resolution_error "Empty history")
|
||||||
| St.History [ c ] ->
|
| St.History [ c ] ->
|
||||||
let duplicates, res = analyze (list c) in
|
let duplicates, res = analyze (list c) in
|
||||||
|
|
|
||||||
|
|
@ -38,14 +38,22 @@ type ('clause, 'proof) unsat_state = {
|
||||||
}
|
}
|
||||||
(** The type of values returned when the solver reaches an UNSAT state. *)
|
(** The type of values returned when the solver reaches an UNSAT state. *)
|
||||||
|
|
||||||
|
type 'clause export = {
|
||||||
|
hyps: 'clause Vec.t;
|
||||||
|
history: 'clause Vec.t;
|
||||||
|
local: 'clause Vec.t;
|
||||||
|
}
|
||||||
|
(** Export internal state *)
|
||||||
|
|
||||||
(** The external interface implemented by safe solvers, such as the one
|
(** The external interface implemented by safe solvers, such as the one
|
||||||
created by the {!Solver.Make} and {!Mcsolver.Make} functors. *)
|
created by the {!Solver.Make} and {!Mcsolver.Make} functors. *)
|
||||||
module type S = sig
|
module type S = sig
|
||||||
|
|
||||||
(** {2 Internal modules}
|
(** {2 Internal modules}
|
||||||
These are the internal modules used, you should probably not use them
|
These are the internal modules used, you should probably not use them
|
||||||
if you're not familiar with the internals of mSAT. *)
|
if you're not familiar with the internals of mSAT. *)
|
||||||
|
|
||||||
|
(* TODO: replace {!St} with explicit modules (Expr, Var, Lit, Elt,...)
|
||||||
|
with carefully picked interfaces *)
|
||||||
module St : Solver_types.S
|
module St : Solver_types.S
|
||||||
(** WARNING: Very dangerous module that expose the internal representation used
|
(** WARNING: Very dangerous module that expose the internal representation used
|
||||||
by the solver. *)
|
by the solver. *)
|
||||||
|
|
@ -96,14 +104,6 @@ module type S = sig
|
||||||
val get_tag : St.clause -> int option
|
val get_tag : St.clause -> int option
|
||||||
(** Recover tag from a clause, if any *)
|
(** Recover tag from a clause, if any *)
|
||||||
|
|
||||||
val export_dimacs : Format.formatter -> unit -> unit
|
val export : unit -> St.clause export
|
||||||
(** Prints the entire set of clauses in the input problem
|
|
||||||
(including hypothesis, lemmas and local assumptions),
|
|
||||||
in the dimacs format. *)
|
|
||||||
|
|
||||||
val export_icnf : Format.formatter -> unit -> unit
|
|
||||||
(** Export the current problem contents to iCNF format.
|
|
||||||
This function is meant to be used icnrementally, i.e.
|
|
||||||
called for each return value of the solve function. *)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ module McMake (E : Expr_intf.S)(Dummy : sig end) = struct
|
||||||
lid : int;
|
lid : int;
|
||||||
term : term;
|
term : term;
|
||||||
mutable l_level : int;
|
mutable l_level : int;
|
||||||
|
mutable l_idx: int;
|
||||||
mutable l_weight : float;
|
mutable l_weight : float;
|
||||||
mutable assigned : term option;
|
mutable assigned : term option;
|
||||||
}
|
}
|
||||||
|
|
@ -51,7 +52,8 @@ module McMake (E : Expr_intf.S)(Dummy : sig end) = struct
|
||||||
mutable used : int;
|
mutable used : int;
|
||||||
mutable seen : seen;
|
mutable seen : seen;
|
||||||
mutable v_level : int;
|
mutable v_level : int;
|
||||||
mutable v_weight : float;
|
mutable v_idx: int; (** position in heap *)
|
||||||
|
mutable v_weight : float; (** Weight (for the heap), tracking activity *)
|
||||||
mutable v_assignable: lit list option;
|
mutable v_assignable: lit list option;
|
||||||
mutable reason : reason option;
|
mutable reason : reason option;
|
||||||
}
|
}
|
||||||
|
|
@ -101,6 +103,7 @@ module McMake (E : Expr_intf.S)(Dummy : sig end) = struct
|
||||||
seen = Nope;
|
seen = Nope;
|
||||||
v_level = -1;
|
v_level = -1;
|
||||||
v_weight = -1.;
|
v_weight = -1.;
|
||||||
|
v_idx= -1;
|
||||||
v_assignable = None;
|
v_assignable = None;
|
||||||
reason = None;
|
reason = None;
|
||||||
}
|
}
|
||||||
|
|
@ -146,6 +149,7 @@ module McMake (E : Expr_intf.S)(Dummy : sig end) = struct
|
||||||
lid = !cpt_mk_var;
|
lid = !cpt_mk_var;
|
||||||
term = t;
|
term = t;
|
||||||
l_weight = 1.;
|
l_weight = 1.;
|
||||||
|
l_idx= -1;
|
||||||
l_level = -1;
|
l_level = -1;
|
||||||
assigned = None;
|
assigned = None;
|
||||||
} in
|
} in
|
||||||
|
|
@ -168,6 +172,7 @@ module McMake (E : Expr_intf.S)(Dummy : sig end) = struct
|
||||||
used = 0;
|
used = 0;
|
||||||
seen = Nope;
|
seen = Nope;
|
||||||
v_level = -1;
|
v_level = -1;
|
||||||
|
v_idx= -1;
|
||||||
v_weight = 0.;
|
v_weight = 0.;
|
||||||
v_assignable = None;
|
v_assignable = None;
|
||||||
reason = None;
|
reason = None;
|
||||||
|
|
@ -244,18 +249,22 @@ module McMake (E : Expr_intf.S)(Dummy : sig end) = struct
|
||||||
let of_atom a = Atom a
|
let of_atom a = Atom a
|
||||||
|
|
||||||
(* Elements *)
|
(* Elements *)
|
||||||
let elt_of_lit l = E_lit l
|
let[@inline] elt_of_lit l = E_lit l
|
||||||
let elt_of_var v = E_var v
|
let[@inline] elt_of_var v = E_var v
|
||||||
|
|
||||||
let get_elt_id = function
|
let get_elt_id = function
|
||||||
| E_lit l -> l.lid | E_var v -> v.vid
|
| E_lit l -> l.lid | E_var v -> v.vid
|
||||||
let get_elt_level = function
|
let get_elt_level = function
|
||||||
| E_lit l -> l.l_level | E_var v -> v.v_level
|
| E_lit l -> l.l_level | E_var v -> v.v_level
|
||||||
|
let get_elt_idx = function
|
||||||
|
| E_lit l -> l.l_idx | E_var v -> v.v_idx
|
||||||
let get_elt_weight = function
|
let get_elt_weight = function
|
||||||
| E_lit l -> l.l_weight | E_var v -> v.v_weight
|
| E_lit l -> l.l_weight | E_var v -> v.v_weight
|
||||||
|
|
||||||
let set_elt_level e lvl = match e with
|
let set_elt_level e lvl = match e with
|
||||||
| E_lit l -> l.l_level <- lvl | E_var v -> v.v_level <- lvl
|
| E_lit l -> l.l_level <- lvl | E_var v -> v.v_level <- lvl
|
||||||
|
let set_elt_idx e i = match e with
|
||||||
|
| E_lit l -> l.l_idx <- i | E_var v -> v.v_idx <- i
|
||||||
let set_elt_weight e w = match e with
|
let set_elt_weight e w = match e with
|
||||||
| E_lit l -> l.l_weight <- w | E_var v -> v.v_weight <- w
|
| E_lit l -> l.l_weight <- w | E_var v -> v.v_weight <- w
|
||||||
|
|
||||||
|
|
@ -346,11 +355,11 @@ module McMake (E : Expr_intf.S)(Dummy : sig end) = struct
|
||||||
let pp_atoms_vec out vec =
|
let pp_atoms_vec out vec =
|
||||||
Array.iter (fun a -> Format.fprintf out "%a@ " pp_atom a) vec
|
Array.iter (fun a -> Format.fprintf out "%a@ " pp_atom a) vec
|
||||||
|
|
||||||
let pp_clause out {name=name; atoms=arr; cpremise=cp; } =
|
let pp_clause out {name=name; atoms=arr; cpremise=cp;_} =
|
||||||
Format.fprintf out "%s@[<hov>{@[<hov>%a@]}@ cpremise={@[<hov>%a@]}@]"
|
Format.fprintf out "%s@[<hov>{@[<hov>%a@]}@ cpremise={@[<hov>%a@]}@]"
|
||||||
name pp_atoms_vec arr pp_premise cp
|
name pp_atoms_vec arr pp_premise cp
|
||||||
|
|
||||||
let pp_dimacs fmt { atoms; } =
|
let pp_dimacs fmt {atoms;_} =
|
||||||
let aux fmt a =
|
let aux fmt a =
|
||||||
Array.iter (fun p ->
|
Array.iter (fun p ->
|
||||||
Format.fprintf fmt "%s%d "
|
Format.fprintf fmt "%s%d "
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ module type S = sig
|
||||||
lid : int; (** Unique identifier *)
|
lid : int; (** Unique identifier *)
|
||||||
term : term; (** Wrapped term *)
|
term : term; (** Wrapped term *)
|
||||||
mutable l_level : int; (** Decision level of the assignment *)
|
mutable l_level : int; (** Decision level of the assignment *)
|
||||||
|
mutable l_idx: int; (** index in heap *)
|
||||||
mutable l_weight : float; (** Weight (for the heap) *)
|
mutable l_weight : float; (** Weight (for the heap) *)
|
||||||
mutable assigned : term option; (** Assignment *)
|
mutable assigned : term option; (** Assignment *)
|
||||||
}
|
}
|
||||||
|
|
@ -57,6 +58,7 @@ module type S = sig
|
||||||
mutable used : int; (** Number of attached clause that contain the var *)
|
mutable used : int; (** Number of attached clause that contain the var *)
|
||||||
mutable seen : seen; (** Boolean used during propagation *)
|
mutable seen : seen; (** Boolean used during propagation *)
|
||||||
mutable v_level : int; (** Level of decision/propagation *)
|
mutable v_level : int; (** Level of decision/propagation *)
|
||||||
|
mutable v_idx: int; (** rank in variable heap *)
|
||||||
mutable v_weight : float; (** Variable weight (for the heap) *)
|
mutable v_weight : float; (** Variable weight (for the heap) *)
|
||||||
mutable v_assignable: lit list option;
|
mutable v_assignable: lit list option;
|
||||||
(** In mcsat, the list of lits that wraps subterms of the formula wrapped. *)
|
(** In mcsat, the list of lits that wraps subterms of the formula wrapped. *)
|
||||||
|
|
@ -144,8 +146,10 @@ module type S = sig
|
||||||
|
|
||||||
val get_elt_id : elt -> int
|
val get_elt_id : elt -> int
|
||||||
val get_elt_level : elt -> int
|
val get_elt_level : elt -> int
|
||||||
|
val get_elt_idx : elt -> int
|
||||||
val get_elt_weight : elt -> float
|
val get_elt_weight : elt -> float
|
||||||
val set_elt_level : elt -> int -> unit
|
val set_elt_level : elt -> int -> unit
|
||||||
|
val set_elt_idx : elt -> int -> unit
|
||||||
val set_elt_weight : elt -> float -> unit
|
val set_elt_weight : elt -> float -> unit
|
||||||
(** Accessors for elements *)
|
(** Accessors for elements *)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,11 @@
|
||||||
(* *)
|
(* *)
|
||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
type 'a t = { mutable dummy: 'a; mutable data : 'a array; mutable sz : int }
|
type 'a t = {
|
||||||
|
mutable dummy: 'a;
|
||||||
|
mutable data : 'a array;
|
||||||
|
mutable sz : int;
|
||||||
|
}
|
||||||
|
|
||||||
let _size_too_big()=
|
let _size_too_big()=
|
||||||
failwith "Vec: capacity exceeds maximum array size"
|
failwith "Vec: capacity exceeds maximum array size"
|
||||||
|
|
@ -20,7 +24,7 @@ let make capa d =
|
||||||
if capa > Sys.max_array_length then _size_too_big();
|
if capa > Sys.max_array_length then _size_too_big();
|
||||||
{data = Array.make capa d; sz = 0; dummy = d}
|
{data = Array.make capa d; sz = 0; dummy = d}
|
||||||
|
|
||||||
let make_empty d = {data = [||]; sz=0; dummy=d }
|
let[@inline] make_empty d = {data = [||]; sz=0; dummy=d }
|
||||||
|
|
||||||
let init capa f d =
|
let init capa f d =
|
||||||
if capa > Sys.max_array_length then _size_too_big();
|
if capa > Sys.max_array_length then _size_too_big();
|
||||||
|
|
@ -30,10 +34,9 @@ let from_array data sz d =
|
||||||
assert (sz <= Array.length data);
|
assert (sz <= Array.length data);
|
||||||
{data = data; sz = sz; dummy = d}
|
{data = data; sz = sz; dummy = d}
|
||||||
|
|
||||||
let from_list l sz d =
|
let from_list l d =
|
||||||
let l = ref l in
|
let a = Array.of_list l in
|
||||||
let f_init i = match !l with [] -> assert false | e::r -> l := r; e in
|
from_array a (Array.length a) d
|
||||||
{data = Array.init sz f_init; sz = sz; dummy = d}
|
|
||||||
|
|
||||||
let to_list s =
|
let to_list s =
|
||||||
let l = ref [] in
|
let l = ref [] in
|
||||||
|
|
@ -42,20 +45,20 @@ let to_list s =
|
||||||
done;
|
done;
|
||||||
List.rev !l
|
List.rev !l
|
||||||
|
|
||||||
let clear s = s.sz <- 0
|
let[@inline] clear s = s.sz <- 0
|
||||||
|
|
||||||
let shrink t i =
|
let[@inline] shrink t i =
|
||||||
assert (i >= 0);
|
assert (i >= 0);
|
||||||
assert (i<=t.sz);
|
assert (i<=t.sz);
|
||||||
t.sz <- t.sz - i
|
t.sz <- i
|
||||||
|
|
||||||
let pop t =
|
let[@inline] pop t =
|
||||||
if t.sz = 0 then invalid_arg "vec.pop";
|
if t.sz = 0 then invalid_arg "vec.pop";
|
||||||
t.sz <- t.sz - 1
|
t.sz <- t.sz - 1
|
||||||
|
|
||||||
let size t = t.sz
|
let[@inline] size t = t.sz
|
||||||
|
|
||||||
let is_empty t = t.sz = 0
|
let[@inline] is_empty t = t.sz = 0
|
||||||
|
|
||||||
let grow_to_exact t new_capa =
|
let grow_to_exact t new_capa =
|
||||||
assert (new_capa > Array.length t.data);
|
assert (new_capa > Array.length t.data);
|
||||||
|
|
@ -81,33 +84,39 @@ let grow_to_at_least t new_capa =
|
||||||
grow_to_exact t !capa
|
grow_to_exact t !capa
|
||||||
)
|
)
|
||||||
|
|
||||||
let is_full t = Array.length t.data = t.sz
|
let[@inline] is_full t = Array.length t.data = t.sz
|
||||||
|
|
||||||
let push t e =
|
let[@inline] push t e =
|
||||||
if is_full t then grow_to_double_size t;
|
if is_full t then grow_to_double_size t;
|
||||||
t.data.(t.sz) <- e;
|
t.data.(t.sz) <- e;
|
||||||
t.sz <- t.sz + 1
|
t.sz <- t.sz + 1
|
||||||
|
|
||||||
let last t =
|
let[@inline] last t =
|
||||||
if t.sz = 0 then invalid_arg "vec.last";
|
if t.sz = 0 then invalid_arg "vec.last";
|
||||||
t.data.(t.sz - 1)
|
t.data.(t.sz - 1)
|
||||||
|
|
||||||
let get t i =
|
let[@inline] pop_last t =
|
||||||
|
if t.sz = 0 then invalid_arg "vec.pop_last";
|
||||||
|
let x = t.data.(t.sz - 1) in
|
||||||
|
t.sz <- t.sz - 1;
|
||||||
|
x
|
||||||
|
|
||||||
|
let[@inline] get t i =
|
||||||
if i < 0 || i >= t.sz then invalid_arg "vec.get";
|
if i < 0 || i >= t.sz then invalid_arg "vec.get";
|
||||||
Array.unsafe_get t.data i
|
Array.unsafe_get t.data i
|
||||||
|
|
||||||
let set t i v =
|
let[@inline] set t i v =
|
||||||
if i < 0 || i > t.sz then invalid_arg "vec.set";
|
if i < 0 || i > t.sz then invalid_arg "vec.set";
|
||||||
if i = t.sz then
|
if i = t.sz then
|
||||||
push t v
|
push t v
|
||||||
else
|
else
|
||||||
Array.unsafe_set t.data i v
|
Array.unsafe_set t.data i v
|
||||||
|
|
||||||
let copy t =
|
let[@inline] copy t =
|
||||||
let data = Array.copy t.data in
|
let data = Array.copy t.data in
|
||||||
{t with data; }
|
{t with data; }
|
||||||
|
|
||||||
let move_to t t' =
|
let[@inline] move_to t t' =
|
||||||
t'.data <- Array.copy t.data;
|
t'.data <- Array.copy t.data;
|
||||||
t'.sz <- t.sz
|
t'.sz <- t.sz
|
||||||
|
|
||||||
|
|
@ -118,11 +127,17 @@ let remove t e =
|
||||||
for i = !j to t.sz - 2 do t.data.(i) <- t.data.(i+1) done;
|
for i = !j to t.sz - 2 do t.data.(i) <- t.data.(i+1) done;
|
||||||
pop t
|
pop t
|
||||||
|
|
||||||
let fast_remove t i =
|
let[@inline] fast_remove t i =
|
||||||
assert (i < t.sz);
|
assert (i < t.sz);
|
||||||
t.data.(i) <- t.data.(t.sz - 1);
|
t.data.(i) <- t.data.(t.sz - 1);
|
||||||
t.sz <- t.sz - 1
|
t.sz <- t.sz - 1
|
||||||
|
|
||||||
|
let filter_in_place f vec =
|
||||||
|
let i = ref 0 in
|
||||||
|
while !i < size vec do
|
||||||
|
if f (get vec !i) then incr i else fast_remove vec !i
|
||||||
|
done
|
||||||
|
|
||||||
let sort t f =
|
let sort t f =
|
||||||
let sub_arr = Array.sub t.data 0 t.sz in
|
let sub_arr = Array.sub t.data 0 t.sz in
|
||||||
Array.fast_sort f sub_arr;
|
Array.fast_sort f sub_arr;
|
||||||
|
|
@ -130,16 +145,21 @@ let sort t f =
|
||||||
|
|
||||||
let iter f t =
|
let iter f t =
|
||||||
for i = 0 to size t - 1 do
|
for i = 0 to size t - 1 do
|
||||||
f t.data.(i)
|
f (Array.unsafe_get t.data i)
|
||||||
done
|
done
|
||||||
|
|
||||||
|
let append a b =
|
||||||
|
grow_to_at_least a (size a + size b);
|
||||||
|
iter (push a) b
|
||||||
|
|
||||||
let fold f acc t =
|
let fold f acc t =
|
||||||
let rec _fold f acc t i =
|
let rec _fold f acc t i =
|
||||||
if i=t.sz
|
if i=t.sz
|
||||||
then acc
|
then acc
|
||||||
else
|
else (
|
||||||
let acc' = f acc (Array.get t.data i) in
|
let acc' = f acc (Array.unsafe_get t.data i) in
|
||||||
_fold f acc' t (i+1)
|
_fold f acc' t (i+1)
|
||||||
|
)
|
||||||
in _fold f acc t 0
|
in _fold f acc t 0
|
||||||
|
|
||||||
exception ExitVec
|
exception ExitVec
|
||||||
|
|
@ -147,7 +167,7 @@ exception ExitVec
|
||||||
let exists p t =
|
let exists p t =
|
||||||
try
|
try
|
||||||
for i = 0 to t.sz - 1 do
|
for i = 0 to t.sz - 1 do
|
||||||
if p (Array.get t.data i) then raise ExitVec
|
if p (Array.unsafe_get t.data i) then raise ExitVec
|
||||||
done;
|
done;
|
||||||
false
|
false
|
||||||
with ExitVec -> true
|
with ExitVec -> true
|
||||||
|
|
@ -155,7 +175,7 @@ let exists p t =
|
||||||
let for_all p t =
|
let for_all p t =
|
||||||
try
|
try
|
||||||
for i = 0 to t.sz - 1 do
|
for i = 0 to t.sz - 1 do
|
||||||
if not (p (Array.get t.data i)) then raise ExitVec
|
if not (p (Array.unsafe_get t.data i)) then raise ExitVec
|
||||||
done;
|
done;
|
||||||
true
|
true
|
||||||
with ExitVec -> false
|
with ExitVec -> false
|
||||||
|
|
@ -30,8 +30,7 @@ val from_array : 'a array -> int -> 'a -> 'a t
|
||||||
to create a vector. [size] is the length of the slice of [data] that is
|
to create a vector. [size] is the length of the slice of [data] that is
|
||||||
used ([size <= Array.length data] must hold) *)
|
used ([size <= Array.length data] must hold) *)
|
||||||
|
|
||||||
val from_list : 'a list -> int -> 'a -> 'a t
|
val from_list : 'a list -> 'a -> 'a t
|
||||||
(** [from_list l n] takes the [n] first elements of list [l] to make a new vector *)
|
|
||||||
|
|
||||||
val to_list : 'a t -> 'a list
|
val to_list : 'a t -> 'a list
|
||||||
(** Returns the list of elements of the vector *)
|
(** Returns the list of elements of the vector *)
|
||||||
|
|
@ -40,6 +39,8 @@ val clear : 'a t -> unit
|
||||||
(** Set size to 0, doesn't free elements *)
|
(** Set size to 0, doesn't free elements *)
|
||||||
|
|
||||||
val shrink : 'a t -> int -> unit
|
val shrink : 'a t -> int -> unit
|
||||||
|
(** [shrink vec sz] resets size of [vec] to [sz].
|
||||||
|
Assumes [sz >=0 && sz <= size vec] *)
|
||||||
|
|
||||||
val pop : 'a t -> unit
|
val pop : 'a t -> unit
|
||||||
(** Pop last element
|
(** Pop last element
|
||||||
|
|
@ -62,10 +63,17 @@ val is_full : 'a t -> bool
|
||||||
|
|
||||||
val push : 'a t -> 'a -> unit
|
val push : 'a t -> 'a -> unit
|
||||||
|
|
||||||
|
val append : 'a t -> 'a t -> unit
|
||||||
|
(** [append v1 v2] pushes all elements of [v2] into [v1] *)
|
||||||
|
|
||||||
val last : 'a t -> 'a
|
val last : 'a t -> 'a
|
||||||
(** Last element, or
|
(** Last element, or
|
||||||
@raise Invalid_argument if the vector is empty *)
|
@raise Invalid_argument if the vector is empty *)
|
||||||
|
|
||||||
|
val pop_last : 'a t -> 'a
|
||||||
|
(** Combine {!last} and {!pop}: remove last element and return it
|
||||||
|
@raise Invalid_argument if empty *)
|
||||||
|
|
||||||
val get : 'a t -> int -> 'a
|
val get : 'a t -> int -> 'a
|
||||||
(** get the element at the given index, or
|
(** get the element at the given index, or
|
||||||
@raise Invalid_argument if the index is not valid *)
|
@raise Invalid_argument if the index is not valid *)
|
||||||
|
|
@ -88,6 +96,10 @@ val fast_remove : 'a t -> int -> unit
|
||||||
(** Remove element at index [i] without preserving order
|
(** Remove element at index [i] without preserving order
|
||||||
(swap with last element) *)
|
(swap with last element) *)
|
||||||
|
|
||||||
|
val filter_in_place : ('a -> bool) -> 'a t -> unit
|
||||||
|
(** [filter_in_place f v] removes from [v] the elements that do
|
||||||
|
not satisfy [f] *)
|
||||||
|
|
||||||
val sort : 'a t -> ('a -> 'a -> int) -> unit
|
val sort : 'a t -> ('a -> 'a -> int) -> unit
|
||||||
(** Sort in place the array *)
|
(** Sort in place the array *)
|
||||||
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
; vim:ft=lisp:
|
; vim:ft=lisp:
|
||||||
|
|
||||||
(jbuild_version 1)
|
|
||||||
|
|
||||||
; main binary
|
|
||||||
(library
|
(library
|
||||||
((name msat)
|
((name msat)
|
||||||
(public_name msat)
|
(public_name msat)
|
||||||
|
|
@ -12,4 +9,3 @@
|
||||||
(ocamlopt_flags (:standard -O3 -bin-annot
|
(ocamlopt_flags (:standard -O3 -bin-annot
|
||||||
-unbox-closures -unbox-closures-factor 20))
|
-unbox-closures -unbox-closures-factor 20))
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
|
||||||
13
src/main/jbuild
Normal file
13
src/main/jbuild
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
; vim:ft=lisp:
|
||||||
|
|
||||||
|
; main binary
|
||||||
|
(executable
|
||||||
|
((name main)
|
||||||
|
(public_name msat_solver)
|
||||||
|
(package msat_solver)
|
||||||
|
(libraries (msat msat.backend msat.sat msat.smt msat.mcsat dolmen))
|
||||||
|
(flags (:standard -w +a-4-42-44-48-50-58-32-60@8 -color always -safe-string))
|
||||||
|
(ocamlopt_flags (:standard -O3 -color always
|
||||||
|
-unbox-closures -unbox-closures-factor 20))
|
||||||
|
))
|
||||||
|
|
@ -4,6 +4,8 @@ Copyright 2014 Guillaume Bury
|
||||||
Copyright 2014 Simon Cruanes
|
Copyright 2014 Simon Cruanes
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
open Msat
|
||||||
|
|
||||||
exception Incorrect_model
|
exception Incorrect_model
|
||||||
exception Out_of_time
|
exception Out_of_time
|
||||||
exception Out_of_space
|
exception Out_of_space
|
||||||
|
|
@ -26,20 +28,20 @@ end
|
||||||
|
|
||||||
module Make
|
module Make
|
||||||
(S : External.S)
|
(S : External.S)
|
||||||
(T : Type.S with type atom := S.atom)
|
(T : Msat_solver.Type.S with type atom := S.atom)
|
||||||
: sig
|
: sig
|
||||||
val do_task : Dolmen.Statement.t -> unit
|
val do_task : Dolmen.Statement.t -> unit
|
||||||
end = struct
|
end = struct
|
||||||
|
|
||||||
module D = Dot.Make(S.Proof)(Dot.Default(S.Proof))
|
module D = Msat_backend.Dot.Make(S.Proof)(Msat_backend.Dot.Default(S.Proof))
|
||||||
|
|
||||||
let hyps = ref []
|
let hyps = ref []
|
||||||
|
|
||||||
let check_model state =
|
let check_model state =
|
||||||
let check_clause c =
|
let check_clause c =
|
||||||
let l = List.map (function a ->
|
let l = List.map (function a ->
|
||||||
Log.debugf 99 "Checking value of %a"
|
Log.debugf 99
|
||||||
(fun k -> k S.St.pp_atom (S.St.add_atom a));
|
(fun k -> k "Checking value of %a" S.St.pp_atom (S.St.add_atom a));
|
||||||
state.Solver_intf.eval a) c in
|
state.Solver_intf.eval a) c in
|
||||||
List.exists (fun x -> x) l
|
List.exists (fun x -> x) l
|
||||||
in
|
in
|
||||||
|
|
@ -47,7 +49,7 @@ module Make
|
||||||
List.for_all (fun x -> x) l
|
List.for_all (fun x -> x) l
|
||||||
|
|
||||||
let prove ~assumptions =
|
let prove ~assumptions =
|
||||||
let res = S.solve () in
|
let res = S.solve ~assumptions () in
|
||||||
let t = Sys.time () in
|
let t = Sys.time () in
|
||||||
begin match res with
|
begin match res with
|
||||||
| S.Sat state ->
|
| S.Sat state ->
|
||||||
|
|
@ -86,10 +88,10 @@ module Make
|
||||||
hyps := cnf @ !hyps;
|
hyps := cnf @ !hyps;
|
||||||
S.assume cnf
|
S.assume cnf
|
||||||
| Dolmen.Statement.Pack [
|
| Dolmen.Statement.Pack [
|
||||||
{ Dolmen.Statement.descr = Dolmen.Statement.Push 1; };
|
{ Dolmen.Statement.descr = Dolmen.Statement.Push 1;_ };
|
||||||
{ Dolmen.Statement.descr = Dolmen.Statement.Antecedent f; };
|
{ Dolmen.Statement.descr = Dolmen.Statement.Antecedent f;_ };
|
||||||
{ Dolmen.Statement.descr = Dolmen.Statement.Prove; };
|
{ Dolmen.Statement.descr = Dolmen.Statement.Prove;_ };
|
||||||
{ Dolmen.Statement.descr = Dolmen.Statement.Pop 1; };
|
{ Dolmen.Statement.descr = Dolmen.Statement.Pop 1;_ };
|
||||||
] ->
|
] ->
|
||||||
let assumptions = T.assumptions f in
|
let assumptions = T.assumptions f in
|
||||||
prove ~assumptions
|
prove ~assumptions
|
||||||
|
|
@ -103,9 +105,9 @@ module Make
|
||||||
Dolmen.Statement.print s
|
Dolmen.Statement.print s
|
||||||
end
|
end
|
||||||
|
|
||||||
module Sat = Make(Sat.Make(struct end))(Type_sat)
|
module Sat = Make(Msat_sat.Sat.Make(struct end))(Msat_sat.Type_sat)
|
||||||
module Smt = Make(Smt.Make(struct end))(Type_smt)
|
module Smt = Make(Msat_smt.Smt.Make(struct end))(Msat_smt.Type_smt)
|
||||||
module Mcsat = Make(Mcsat.Make(struct end))(Type_smt)
|
module Mcsat = Make(Msat_mcsat.Mcsat.Make(struct end))(Msat_smt.Type_smt)
|
||||||
|
|
||||||
let solver = ref (module Sat : S)
|
let solver = ref (module Sat : S)
|
||||||
let solver_list = [
|
let solver_list = [
|
||||||
|
|
@ -224,8 +226,8 @@ let () =
|
||||||
| Incorrect_model ->
|
| Incorrect_model ->
|
||||||
Format.printf "Internal error : incorrect *sat* model@.";
|
Format.printf "Internal error : incorrect *sat* model@.";
|
||||||
exit 4
|
exit 4
|
||||||
| Type_sat.Typing_error (msg, t)
|
| Msat_sat.Type_sat.Typing_error (msg, t)
|
||||||
| Type_smt.Typing_error (msg, t) ->
|
| Msat_smt.Type_smt.Typing_error (msg, t) ->
|
||||||
let b = Printexc.get_backtrace () in
|
let b = Printexc.get_backtrace () in
|
||||||
let loc = match t.Dolmen.Term.loc with
|
let loc = match t.Dolmen.Term.loc with
|
||||||
| Some l -> l | None -> Dolmen.ParseLocation.mk "<>" 0 0 0 0
|
| Some l -> l | None -> Dolmen.ParseLocation.mk "<>" 0 0 0 0
|
||||||
|
|
@ -106,8 +106,9 @@ module Make(T : Key) = struct
|
||||||
tag = (match mx.tag, my.tag with
|
tag = (match mx.tag, my.tag with
|
||||||
| Some (z, t1), Some (w, t2) ->
|
| Some (z, t1), Some (w, t2) ->
|
||||||
if not (T.equal t1 t2) then begin
|
if not (T.equal t1 t2) then begin
|
||||||
Log.debugf 3 "Tag shenanigan : %a (%a) <> %a (%a)" (fun k ->
|
Log.debugf 3
|
||||||
k T.print t1 T.print z T.print t2 T.print w);
|
(fun k -> k "Tag shenanigan : %a (%a) <> %a (%a)"
|
||||||
|
T.print t1 T.print z T.print t2 T.print w);
|
||||||
raise (Equal (z, w))
|
raise (Equal (z, w))
|
||||||
end else Some (z, t1)
|
end else Some (z, t1)
|
||||||
| Some t, None | None, Some t -> Some t
|
| Some t, None | None, Some t -> Some t
|
||||||
|
|
@ -223,7 +224,7 @@ module Make(T : Key) = struct
|
||||||
| () -> ()
|
| () -> ()
|
||||||
| exception Equal (a, b) ->
|
| exception Equal (a, b) ->
|
||||||
raise (Unsat (a, b, expl t a b))
|
raise (Unsat (a, b, expl t a b))
|
||||||
| exception Same_tag (x, y) ->
|
| exception Same_tag (_, _) ->
|
||||||
add_eq_aux t i j;
|
add_eq_aux t i j;
|
||||||
let res = expl t i j in
|
let res = expl t i j in
|
||||||
raise (Unsat (i, j, res))
|
raise (Unsat (i, j, res))
|
||||||
|
|
|
||||||
13
src/mcsat/jbuild
Normal file
13
src/mcsat/jbuild
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
; vim:ft=lisp:
|
||||||
|
|
||||||
|
(library
|
||||||
|
((name msat_mcsat)
|
||||||
|
(public_name msat.mcsat)
|
||||||
|
(libraries (msat msat.solver msat.smt))
|
||||||
|
(synopsis "mcsat interface")
|
||||||
|
(flags (:standard -w +a-4-42-44-48-50-58-32-60@8 -color always -safe-string -open Msat))
|
||||||
|
(ocamlopt_flags (:standard -O3 -bin-annot
|
||||||
|
-unbox-closures -unbox-closures-factor 20))
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -5,9 +5,9 @@ Copyright 2014 Simon Cruanes
|
||||||
*)
|
*)
|
||||||
|
|
||||||
module Make(Dummy:sig end) =
|
module Make(Dummy:sig end) =
|
||||||
Mcsolver.Make(struct
|
Msat_solver.Mcsolver.Make(struct
|
||||||
type proof = unit
|
type proof = unit
|
||||||
module Term = Expr_smt.Term
|
module Term = Msat_smt.Expr_smt.Term
|
||||||
module Formula = Expr_smt.Atom
|
module Formula = Msat_smt.Expr_smt.Atom
|
||||||
end)(Plugin_mcsat)(struct end)
|
end)(Plugin_mcsat)(struct end)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,5 @@ Copyright 2014 Guillaume Bury
|
||||||
Copyright 2014 Simon Cruanes
|
Copyright 2014 Simon Cruanes
|
||||||
*)
|
*)
|
||||||
|
|
||||||
module Make(Dummy: sig end) : Solver.S with type St.formula = Expr_smt.atom
|
module Make(Dummy: sig end) : Msat_solver.Solver.S with type St.formula = Msat_smt.Expr_smt.atom
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
(* Module initialization *)
|
(* Module initialization *)
|
||||||
|
|
||||||
|
open Msat_smt
|
||||||
|
|
||||||
module E = Eclosure.Make(Expr_smt.Term)
|
module E = Eclosure.Make(Expr_smt.Term)
|
||||||
module H = Backtrack.Hashtbl(Expr_smt.Term)
|
module H = Backtrack.Hashtbl(Expr_smt.Term)
|
||||||
module M = Hashtbl.Make(Expr_smt.Term)
|
module M = Hashtbl.Make(Expr_smt.Term)
|
||||||
|
|
@ -63,7 +65,7 @@ let update_job x ((t, watchees) as job) =
|
||||||
with Not_found ->
|
with Not_found ->
|
||||||
add_job job x;
|
add_job job x;
|
||||||
begin match t with
|
begin match t with
|
||||||
| { Expr_smt.term = Expr_smt.App (f, tys, l) } ->
|
| { Expr_smt.term = Expr_smt.App (f, tys, l);_ } ->
|
||||||
let is_prop = Expr_smt.(Ty.equal t.t_type Ty.prop) in
|
let is_prop = Expr_smt.(Ty.equal t.t_type Ty.prop) in
|
||||||
let t_v = H.find map t in
|
let t_v = H.find map t in
|
||||||
let l' = List.map (H.find map) l in
|
let l' = List.map (H.find map) l in
|
||||||
|
|
@ -72,7 +74,7 @@ let update_job x ((t, watchees) as job) =
|
||||||
let t', u_v = H.find interpretation u in
|
let t', u_v = H.find interpretation u in
|
||||||
if not (Expr_smt.Term.equal t_v u_v) then begin
|
if not (Expr_smt.Term.equal t_v u_v) then begin
|
||||||
match t' with
|
match t' with
|
||||||
| { Expr_smt.term = Expr_smt.App (_, _, r) } when is_prop ->
|
| { Expr_smt.term = Expr_smt.App (_, _, r); _ } when is_prop ->
|
||||||
let eqs = List.map2 (fun a b -> Expr_smt.Atom.neg (Expr_smt.Atom.eq a b)) l r in
|
let eqs = List.map2 (fun a b -> Expr_smt.Atom.neg (Expr_smt.Atom.eq a b)) l r in
|
||||||
if Expr_smt.(Term.equal u_v true_) then begin
|
if Expr_smt.(Term.equal u_v true_) then begin
|
||||||
let res = Expr_smt.Atom.pred t ::
|
let res = Expr_smt.Atom.pred t ::
|
||||||
|
|
@ -83,7 +85,7 @@ let update_job x ((t, watchees) as job) =
|
||||||
Expr_smt.Atom.neg (Expr_smt.Atom.pred t) :: eqs in
|
Expr_smt.Atom.neg (Expr_smt.Atom.pred t) :: eqs in
|
||||||
raise (Absurd res)
|
raise (Absurd res)
|
||||||
end
|
end
|
||||||
| { Expr_smt.term = Expr_smt.App (_, _, r) } ->
|
| { Expr_smt.term = Expr_smt.App (_, _, r); _ } ->
|
||||||
let eqs = List.map2 (fun a b -> Expr_smt.Atom.neg (Expr_smt.Atom.eq a b)) l r in
|
let eqs = List.map2 (fun a b -> Expr_smt.Atom.neg (Expr_smt.Atom.eq a b)) l r in
|
||||||
let res = Expr_smt.Atom.eq t t' :: eqs in
|
let res = Expr_smt.Atom.eq t t' :: eqs in
|
||||||
raise (Absurd res)
|
raise (Absurd res)
|
||||||
|
|
@ -117,25 +119,25 @@ let add_assign t v =
|
||||||
(* Assignemnts *)
|
(* Assignemnts *)
|
||||||
|
|
||||||
let rec iter_aux f = function
|
let rec iter_aux f = function
|
||||||
| { Expr_smt.term = Expr_smt.Var _ } as t ->
|
| { Expr_smt.term = Expr_smt.Var _; _ } as t ->
|
||||||
Log.debugf 10 "Adding %a as assignable" (fun k -> k Expr_smt.Term.print t);
|
Log.debugf 10 (fun k -> k "Adding %a as assignable" Expr_smt.Term.print t);
|
||||||
f t
|
f t
|
||||||
| { Expr_smt.term = Expr_smt.App (_, _, l) } as t ->
|
| { Expr_smt.term = Expr_smt.App (_, _, l); _ } as t ->
|
||||||
if l <> [] then add_watch t (t :: l);
|
if l <> [] then add_watch t (t :: l);
|
||||||
List.iter (iter_aux f) l;
|
List.iter (iter_aux f) l;
|
||||||
Log.debugf 10 "Adding %a as assignable" (fun k -> k Expr_smt.Term.print t);
|
Log.debugf 10 (fun k -> k "Adding %a as assignable" Expr_smt.Term.print t);
|
||||||
f t
|
f t
|
||||||
|
|
||||||
let iter_assignable f = function
|
let iter_assignable f = function
|
||||||
| { Expr_smt.atom = Expr_smt.Pred { Expr_smt.term = Expr_smt.Var _ } } -> ()
|
| { Expr_smt.atom = Expr_smt.Pred { Expr_smt.term = Expr_smt.Var _;_ }; _ } -> ()
|
||||||
| { Expr_smt.atom = Expr_smt.Pred ({ Expr_smt.term = Expr_smt.App (_, _, l) } as t) } ->
|
| { Expr_smt.atom = Expr_smt.Pred ({ Expr_smt.term = Expr_smt.App (_, _, l);_} as t); _ } ->
|
||||||
if l <> [] then add_watch t (t :: l);
|
if l <> [] then add_watch t (t :: l);
|
||||||
List.iter (iter_aux f) l;
|
List.iter (iter_aux f) l;
|
||||||
| { Expr_smt.atom = Expr_smt.Equal (a, b) } ->
|
| { Expr_smt.atom = Expr_smt.Equal (a, b);_ } ->
|
||||||
iter_aux f a; iter_aux f b
|
iter_aux f a; iter_aux f b
|
||||||
|
|
||||||
let eval = function
|
let eval = function
|
||||||
| { Expr_smt.atom = Expr_smt.Pred t } ->
|
| { Expr_smt.atom = Expr_smt.Pred t; _ } ->
|
||||||
begin try
|
begin try
|
||||||
let v = H.find map t in
|
let v = H.find map t in
|
||||||
if Expr_smt.Term.equal v true_ then
|
if Expr_smt.Term.equal v true_ then
|
||||||
|
|
@ -147,7 +149,7 @@ let eval = function
|
||||||
with Not_found ->
|
with Not_found ->
|
||||||
Plugin_intf.Unknown
|
Plugin_intf.Unknown
|
||||||
end
|
end
|
||||||
| { Expr_smt.atom = Expr_smt.Equal (a, b); sign } ->
|
| { Expr_smt.atom = Expr_smt.Equal (a, b); sign; _ } ->
|
||||||
begin try
|
begin try
|
||||||
let v_a = H.find map a in
|
let v_a = H.find map a in
|
||||||
let v_b = H.find map b in
|
let v_b = H.find map b in
|
||||||
|
|
@ -164,7 +166,7 @@ let eval = function
|
||||||
|
|
||||||
let rec chain_eq = function
|
let rec chain_eq = function
|
||||||
| [] | [_] -> []
|
| [] | [_] -> []
|
||||||
| a :: ((b :: r) as l) -> (Expr_smt.Atom.eq a b) :: chain_eq l
|
| a :: ((b :: _) as l) -> (Expr_smt.Atom.eq a b) :: chain_eq l
|
||||||
|
|
||||||
let assume s =
|
let assume s =
|
||||||
let open Plugin_intf in
|
let open Plugin_intf in
|
||||||
|
|
@ -176,11 +178,11 @@ let assume s =
|
||||||
E.add_tag uf t v
|
E.add_tag uf t v
|
||||||
| Lit f ->
|
| Lit f ->
|
||||||
begin match f with
|
begin match f with
|
||||||
| { Expr_smt.atom = Expr_smt.Equal (u, v); sign = true } ->
|
| { Expr_smt.atom = Expr_smt.Equal (u, v); sign = true;_ } ->
|
||||||
E.add_eq uf u v
|
E.add_eq uf u v
|
||||||
| { Expr_smt.atom = Expr_smt.Equal (u, v); sign = false } ->
|
| { Expr_smt.atom = Expr_smt.Equal (u, v); sign = false;_ } ->
|
||||||
E.add_neq uf u v
|
E.add_neq uf u v
|
||||||
| { Expr_smt.atom = Expr_smt.Pred p; sign } ->
|
| { Expr_smt.atom = Expr_smt.Pred p; sign;_ } ->
|
||||||
let v = if sign then true_ else false_ in
|
let v = if sign then true_ else false_ in
|
||||||
add_assign p v
|
add_assign p v
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
# Debug
|
|
||||||
Log
|
|
||||||
|
|
||||||
# Interface definitions
|
|
||||||
Formula_intf
|
|
||||||
Theory_intf
|
|
||||||
Plugin_intf
|
|
||||||
Expr_intf
|
|
||||||
Tseitin_intf
|
|
||||||
Res_intf
|
|
||||||
Solver_intf
|
|
||||||
Solver_types_intf
|
|
||||||
|
|
||||||
# Solver Modules
|
|
||||||
Internal
|
|
||||||
External
|
|
||||||
Solver
|
|
||||||
Mcsolver
|
|
||||||
Solver_types
|
|
||||||
|
|
||||||
# Proofs & Backends
|
|
||||||
Res
|
|
||||||
Backend_intf
|
|
||||||
Dot
|
|
||||||
Coq
|
|
||||||
Dimacs
|
|
||||||
Dedukti
|
|
||||||
|
|
||||||
# Auxiliary modules
|
|
||||||
Tseitin
|
|
||||||
|
|
||||||
# Pure Sat solver
|
|
||||||
Sat
|
|
||||||
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
# Log utilities
|
|
||||||
util/Log
|
|
||||||
|
|
||||||
# Interfaces
|
|
||||||
core/Formula_intf
|
|
||||||
core/Theory_intf
|
|
||||||
core/Plugin_intf
|
|
||||||
core/Expr_intf
|
|
||||||
core/Res_intf
|
|
||||||
core/Solver_types_intf
|
|
||||||
core/Solver_intf
|
|
||||||
solver/Tseitin_intf
|
|
||||||
|
|
||||||
# Main modules
|
|
||||||
core/Res
|
|
||||||
core/Internal
|
|
||||||
core/External
|
|
||||||
core/Solver_types
|
|
||||||
|
|
||||||
solver/Solver
|
|
||||||
solver/Mcsolver
|
|
||||||
solver/Tseitin
|
|
||||||
|
|
||||||
# Backends
|
|
||||||
backend/Dot
|
|
||||||
backend/Coq
|
|
||||||
backend/Dedukti
|
|
||||||
backend/Backend_intf
|
|
||||||
|
|
||||||
# SAT solver frontend
|
|
||||||
sat/Sat
|
|
||||||
#sat/Type_sat
|
|
||||||
|
|
||||||
# SMT solver frontend
|
|
||||||
#smt/Smt
|
|
||||||
#smt/Expr_smt
|
|
||||||
#smt/Type_smt
|
|
||||||
#smt/Unionfind
|
|
||||||
|
|
||||||
# MCsat solver frontend
|
|
||||||
#mcsat/Mcsat
|
|
||||||
#mcsat/Eclosure
|
|
||||||
#mcsat/Plugin_mcsat
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Sat
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
Smt
|
|
||||||
Cc
|
|
||||||
Explanation
|
|
||||||
13
src/sat/jbuild
Normal file
13
src/sat/jbuild
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
; vim:ft=lisp:
|
||||||
|
|
||||||
|
(library
|
||||||
|
((name msat_sat)
|
||||||
|
(public_name msat.sat)
|
||||||
|
(libraries (msat msat.solver))
|
||||||
|
(synopsis "sat interface")
|
||||||
|
(flags (:standard -w +a-4-42-44-48-50-58-32-60@8 -color always -safe-string -open Msat))
|
||||||
|
(ocamlopt_flags (:standard -O3 -bin-annot
|
||||||
|
-unbox-closures -unbox-closures-factor 20))
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -78,5 +78,5 @@ module Expr = struct
|
||||||
end
|
end
|
||||||
|
|
||||||
module Make(Dummy : sig end) =
|
module Make(Dummy : sig end) =
|
||||||
Solver.Make(Expr)(Solver.DummyTheory(Expr))(struct end)
|
Msat_solver.Solver.Make(Expr)(Msat_solver.Solver.DummyTheory(Expr))(struct end)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,6 @@ module Expr : sig
|
||||||
end
|
end
|
||||||
(** The module defining formulas *)
|
(** The module defining formulas *)
|
||||||
|
|
||||||
module Make(Dummy : sig end) : Solver.S with type St.formula = Expr.t
|
module Make(Dummy : sig end) : Msat_solver.Solver.S with type St.formula = Expr.t
|
||||||
(** A functor that can generate as many solvers as needed. *)
|
(** A functor that can generate as many solvers as needed. *)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ Copyright 2014 Simon Cruanes
|
||||||
module Id = Dolmen.Id
|
module Id = Dolmen.Id
|
||||||
module Ast = Dolmen.Term
|
module Ast = Dolmen.Term
|
||||||
module H = Hashtbl.Make(Id)
|
module H = Hashtbl.Make(Id)
|
||||||
module Formula = Tseitin.Make(Sat.Expr)
|
module Formula = Msat_solver.Tseitin.Make(Sat.Expr)
|
||||||
|
|
||||||
(* Exceptions *)
|
(* Exceptions *)
|
||||||
(* ************************************************************************ *)
|
(* ************************************************************************ *)
|
||||||
|
|
@ -33,6 +33,8 @@ let find_id id =
|
||||||
(* Actual parsing *)
|
(* Actual parsing *)
|
||||||
(* ************************************************************************ *)
|
(* ************************************************************************ *)
|
||||||
|
|
||||||
|
[@@@ocaml.warning "-9"]
|
||||||
|
|
||||||
let rec parse = function
|
let rec parse = function
|
||||||
| { Ast.term = Ast.Builtin Ast.True } ->
|
| { Ast.term = Ast.Builtin Ast.True } ->
|
||||||
Formula.f_true
|
Formula.f_true
|
||||||
|
|
@ -59,6 +61,8 @@ let rec parse = function
|
||||||
| t ->
|
| t ->
|
||||||
raise (Typing_error ("Term is not a pure proposition", t))
|
raise (Typing_error ("Term is not a pure proposition", t))
|
||||||
|
|
||||||
|
[@@@ocaml.warning "+9"]
|
||||||
|
|
||||||
(* Exported functions *)
|
(* Exported functions *)
|
||||||
(* ************************************************************************ *)
|
(* ************************************************************************ *)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,5 +8,5 @@ Copyright 2014 Simon Cruanes
|
||||||
This module provides functions to parse terms from the untyped syntax tree
|
This module provides functions to parse terms from the untyped syntax tree
|
||||||
defined in Dolmen, and generate formulas as defined in the Expr_sat module. *)
|
defined in Dolmen, and generate formulas as defined in the Expr_sat module. *)
|
||||||
|
|
||||||
include Type.S with type atom := Sat.Expr.t
|
include Msat_solver.Type.S with type atom := Sat.Expr.t
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ module Print = struct
|
||||||
let rec list f sep fmt = function
|
let rec list f sep fmt = function
|
||||||
| [] -> ()
|
| [] -> ()
|
||||||
| [x] -> f fmt x
|
| [x] -> f fmt x
|
||||||
| x :: ((y :: _) as r) ->
|
| x :: ((_ :: _) as r) ->
|
||||||
Format.fprintf fmt "%a%s" f x sep;
|
Format.fprintf fmt "%a%s" f x sep;
|
||||||
list f sep fmt r
|
list f sep fmt r
|
||||||
|
|
||||||
|
|
@ -521,5 +521,5 @@ module Atom = struct
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
module Formula = Tseitin.Make(Atom)
|
module Formula = Msat_solver.Tseitin.Make(Atom)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -322,5 +322,5 @@ module Atom : sig
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
module Formula : Tseitin.S with type atom = atom
|
module Formula : Msat_solver.Tseitin.S with type atom = atom
|
||||||
|
|
||||||
|
|
|
||||||
13
src/smt/jbuild
Normal file
13
src/smt/jbuild
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
; vim:ft=lisp:
|
||||||
|
|
||||||
|
(library
|
||||||
|
((name msat_smt)
|
||||||
|
(public_name msat.smt)
|
||||||
|
(libraries (msat msat.solver dolmen))
|
||||||
|
(synopsis "smt interface")
|
||||||
|
(flags (:standard -w +a-4-42-44-48-50-58-32-60@8 -color always -safe-string -open Msat))
|
||||||
|
(ocamlopt_flags (:standard -O3 -bin-annot
|
||||||
|
-unbox-closures -unbox-closures-factor 20))
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -4,8 +4,8 @@ Copyright 2014 Guillaume Bury
|
||||||
Copyright 2014 Simon Cruanes
|
Copyright 2014 Simon Cruanes
|
||||||
*)
|
*)
|
||||||
|
|
||||||
module Th = Solver.DummyTheory(Expr_smt.Atom)
|
module Th = Msat_solver.Solver.DummyTheory(Expr_smt.Atom)
|
||||||
|
|
||||||
module Make(Dummy:sig end) =
|
module Make(Dummy:sig end) =
|
||||||
Solver.Make(Expr_smt.Atom)(Th)(struct end)
|
Msat_solver.Solver.Make(Expr_smt.Atom)(Th)(struct end)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,5 @@ Copyright 2014 Guillaume Bury
|
||||||
Copyright 2014 Simon Cruanes
|
Copyright 2014 Simon Cruanes
|
||||||
*)
|
*)
|
||||||
|
|
||||||
module Make(Dummy: sig end) : Solver.S with type St.formula = Expr_smt.atom
|
module Make(Dummy: sig end) : Msat_solver.Solver.S with type St.formula = Expr_smt.atom
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -73,29 +73,29 @@ let find_global name =
|
||||||
(* Symbol declarations *)
|
(* Symbol declarations *)
|
||||||
let decl_ty_cstr id c =
|
let decl_ty_cstr id c =
|
||||||
if H.mem global_env id then
|
if H.mem global_env id then
|
||||||
Log.debugf 0 "Symbol '%a' has already been defined, overwriting previous definition"
|
Log.debugf 0
|
||||||
(fun k -> k Id.print id);
|
(fun k -> k "Symbol '%a' has already been defined, overwriting previous definition" Id.print id);
|
||||||
H.add global_env id (`Ty c);
|
H.add global_env id (`Ty c);
|
||||||
Log.debugf 1 "New type constructor : %a" (fun k -> k Expr.Print.const_ttype c)
|
Log.debugf 1 (fun k -> k "New type constructor : %a" Expr.Print.const_ttype c)
|
||||||
|
|
||||||
let decl_term id c =
|
let decl_term id c =
|
||||||
if H.mem global_env id then
|
if H.mem global_env id then
|
||||||
Log.debugf 0 "Symbol '%a' has already been defined, overwriting previous definition"
|
Log.debugf 0
|
||||||
(fun k -> k Id.print id);
|
(fun k -> k "Symbol '%a' has already been defined, overwriting previous definition" Id.print id);
|
||||||
H.add global_env id (`Term c);
|
H.add global_env id (`Term c);
|
||||||
Log.debugf 1 "New constant : %a" (fun k -> k Expr.Print.const_ty c)
|
Log.debugf 1 (fun k -> k "New constant : %a" Expr.Print.const_ty c)
|
||||||
|
|
||||||
(* Symbol definitions *)
|
(* Symbol definitions *)
|
||||||
let def_ty id args body =
|
let def_ty id args body =
|
||||||
if H.mem global_env id then
|
if H.mem global_env id then
|
||||||
Log.debugf 0 "Symbol '%a' has already been defined, overwriting previous definition"
|
Log.debugf 0
|
||||||
(fun k -> k Id.print id);
|
(fun k -> k "Symbol '%a' has already been defined, overwriting previous definition" Id.print id);
|
||||||
H.add global_env id (`Ty_alias (args, body))
|
H.add global_env id (`Ty_alias (args, body))
|
||||||
|
|
||||||
let def_term id ty_args args body =
|
let def_term id ty_args args body =
|
||||||
if H.mem global_env id then
|
if H.mem global_env id then
|
||||||
Log.debugf 0 "Symbol '%a' has already been defined, overwriting previous definition"
|
Log.debugf 0
|
||||||
(fun k -> k Id.print id);
|
(fun k -> k "Symbol '%a' has already been defined, overwriting previous definition" Id.print id);
|
||||||
H.add global_env id (`Term_alias (ty_args, args, body))
|
H.add global_env id (`Term_alias (ty_args, args, body))
|
||||||
|
|
||||||
(* Local Environment *)
|
(* Local Environment *)
|
||||||
|
|
@ -126,8 +126,8 @@ let add_type_var env id v =
|
||||||
else
|
else
|
||||||
v
|
v
|
||||||
in
|
in
|
||||||
Log.debugf 1 "New binding : %a -> %a"
|
Log.debugf 1
|
||||||
(fun k -> k Id.print id Expr.Print.id_ttype v');
|
(fun k -> k "New binding : %a -> %a" Id.print id Expr.Print.id_ttype v');
|
||||||
v', { env with type_vars = M.add id v' env.type_vars }
|
v', { env with type_vars = M.add id v' env.type_vars }
|
||||||
|
|
||||||
let add_type_vars env l =
|
let add_type_vars env l =
|
||||||
|
|
@ -143,8 +143,8 @@ let add_term_var env id v =
|
||||||
else
|
else
|
||||||
v
|
v
|
||||||
in
|
in
|
||||||
Log.debugf 1 "New binding : %a -> %a"
|
Log.debugf 1
|
||||||
(fun k -> k Id.print id Expr.Print.id_ty v');
|
(fun k -> k "New binding : %a -> %a" Id.print id Expr.Print.id_ty v');
|
||||||
v', { env with term_vars = M.add id v' env.term_vars }
|
v', { env with term_vars = M.add id v' env.term_vars }
|
||||||
|
|
||||||
let find_var env name =
|
let find_var env name =
|
||||||
|
|
@ -159,13 +159,13 @@ let find_var env name =
|
||||||
|
|
||||||
(* Add local bound variables to env *)
|
(* Add local bound variables to env *)
|
||||||
let add_let_term env id t =
|
let add_let_term env id t =
|
||||||
Log.debugf 1 "New let-binding : %s -> %a"
|
Log.debugf 1
|
||||||
(fun k -> k id.Id.name Expr.Print.term t);
|
(fun k -> k "New let-binding : %s -> %a" id.Id.name Expr.Print.term t);
|
||||||
{ env with term_lets = M.add id t env.term_lets }
|
{ env with term_lets = M.add id t env.term_lets }
|
||||||
|
|
||||||
let add_let_prop env id t =
|
let add_let_prop env id t =
|
||||||
Log.debugf 1 "New let-binding : %s -> %a"
|
Log.debugf 1
|
||||||
(fun k -> k id.Id.name Expr.Formula.print t);
|
(fun k -> k "New let-binding : %s -> %a" id.Id.name Expr.Formula.print t);
|
||||||
{ env with prop_lets = M.add id t env.prop_lets }
|
{ env with prop_lets = M.add id t env.prop_lets }
|
||||||
|
|
||||||
let find_let env name =
|
let find_let env name =
|
||||||
|
|
@ -207,13 +207,13 @@ let arity f =
|
||||||
List.length Expr.(f.id_type.fun_vars) +
|
List.length Expr.(f.id_type.fun_vars) +
|
||||||
List.length Expr.(f.id_type.fun_args)
|
List.length Expr.(f.id_type.fun_args)
|
||||||
|
|
||||||
let ty_apply env ast f args =
|
let ty_apply _env ast f args =
|
||||||
try
|
try
|
||||||
Expr.Ty.apply f args
|
Expr.Ty.apply f args
|
||||||
with Expr.Bad_ty_arity _ ->
|
with Expr.Bad_ty_arity _ ->
|
||||||
_bad_arity Expr.(f.id_name) (arity f) ast
|
_bad_arity Expr.(f.id_name) (arity f) ast
|
||||||
|
|
||||||
let term_apply env ast f ty_args t_args =
|
let term_apply _env ast f ty_args t_args =
|
||||||
try
|
try
|
||||||
Expr.Term.apply f ty_args t_args
|
Expr.Term.apply f ty_args t_args
|
||||||
with
|
with
|
||||||
|
|
@ -277,6 +277,8 @@ let infer env s args =
|
||||||
(* Expression parsing *)
|
(* Expression parsing *)
|
||||||
(* ************************************************************************ *)
|
(* ************************************************************************ *)
|
||||||
|
|
||||||
|
[@@@ocaml.warning "-9"]
|
||||||
|
|
||||||
let rec parse_expr (env : env) t =
|
let rec parse_expr (env : env) t =
|
||||||
match t with
|
match t with
|
||||||
(* Base Types *)
|
(* Base Types *)
|
||||||
|
|
@ -582,13 +584,15 @@ let rec parse_fun ty_args t_args env = function
|
||||||
| Formula _ -> _expected "type or term" ast
|
| Formula _ -> _expected "type or term" ast
|
||||||
end
|
end
|
||||||
|
|
||||||
|
[@@@ocaml.warning "+9"]
|
||||||
|
|
||||||
(* High-level parsing functions *)
|
(* High-level parsing functions *)
|
||||||
(* ************************************************************************ *)
|
(* ************************************************************************ *)
|
||||||
|
|
||||||
let decl id t =
|
let decl id t =
|
||||||
let env = empty_env () in
|
let env = empty_env () in
|
||||||
Log.debugf 5 "Typing declaration: %s : %a"
|
Log.debugf 5
|
||||||
(fun k -> k id.Id.name Ast.print t);
|
(fun k -> k "Typing declaration: %s : %a" id.Id.name Ast.print t);
|
||||||
begin match parse_sig env t with
|
begin match parse_sig env t with
|
||||||
| `Ty_cstr n -> decl_ty_cstr id (Expr.Id.ty_fun id.Id.name n)
|
| `Ty_cstr n -> decl_ty_cstr id (Expr.Id.ty_fun id.Id.name n)
|
||||||
| `Fun_ty (vars, args, ret) ->
|
| `Fun_ty (vars, args, ret) ->
|
||||||
|
|
@ -597,8 +601,8 @@ let decl id t =
|
||||||
|
|
||||||
let def id t =
|
let def id t =
|
||||||
let env = empty_env () in
|
let env = empty_env () in
|
||||||
Log.debugf 5 "Typing definition: %s = %a"
|
Log.debugf 5
|
||||||
(fun k -> k id.Id.name Ast.print t);
|
(fun k -> k "Typing definition: %s = %a" id.Id.name Ast.print t);
|
||||||
begin match parse_fun [] [] env t with
|
begin match parse_fun [] [] env t with
|
||||||
| `Ty (ty_args, body) -> def_ty id ty_args body
|
| `Ty (ty_args, body) -> def_ty id ty_args body
|
||||||
| `Term (ty_args, t_args, body) -> def_term id ty_args t_args body
|
| `Term (ty_args, t_args, body) -> def_term id ty_args t_args body
|
||||||
|
|
@ -606,7 +610,7 @@ let def id t =
|
||||||
|
|
||||||
let formula t =
|
let formula t =
|
||||||
let env = empty_env () in
|
let env = empty_env () in
|
||||||
Log.debugf 5 "Typing top-level formula: %a" (fun k -> k Ast.print t);
|
Log.debugf 5 (fun k -> k "Typing top-level formula: %a" Ast.print t);
|
||||||
parse_formula env t
|
parse_formula env t
|
||||||
|
|
||||||
let assumptions t =
|
let assumptions t =
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,5 @@
|
||||||
This module provides functions to parse terms from the untyped syntax tree
|
This module provides functions to parse terms from the untyped syntax tree
|
||||||
defined in Dolmen, and generate formulas as defined in the Expr_smt module. *)
|
defined in Dolmen, and generate formulas as defined in the Expr_smt module. *)
|
||||||
|
|
||||||
include Type.S with type atom := Expr_smt.Atom.t
|
include Msat_solver.Type.S with type atom := Expr_smt.Atom.t
|
||||||
|
|
||||||
|
|
|
||||||
12
src/solver/jbuild
Normal file
12
src/solver/jbuild
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
; vim:ft=lisp:
|
||||||
|
|
||||||
|
(library
|
||||||
|
((name msat_solver)
|
||||||
|
(public_name msat.solver)
|
||||||
|
(libraries (msat dolmen))
|
||||||
|
(synopsis "mcsat solver util")
|
||||||
|
(flags (:standard -w +a-4-42-44-48-50-58-32-60@8 -color always -safe-string -open Msat))
|
||||||
|
(ocamlopt_flags (:standard -O3 -bin-annot
|
||||||
|
-unbox-closures -unbox-closures-factor 20))
|
||||||
|
))
|
||||||
|
|
||||||
|
|
@ -242,7 +242,7 @@ module Make (F : Tseitin_intf.Arg) = struct
|
||||||
(fun (_, acc) f ->
|
(fun (_, acc) f ->
|
||||||
match cnf f with
|
match cnf f with
|
||||||
| _, [] -> assert false
|
| _, [] -> assert false
|
||||||
| cmb, [a] -> Some And, a :: acc
|
| _cmb, [a] -> Some And, a :: acc
|
||||||
| Some And, l ->
|
| Some And, l ->
|
||||||
Some And, l @@ acc
|
Some And, l @@ acc
|
||||||
(* let proxy = mk_proxy () in *)
|
(* let proxy = mk_proxy () in *)
|
||||||
|
|
@ -261,7 +261,7 @@ module Make (F : Tseitin_intf.Arg) = struct
|
||||||
(fun (_, acc) f ->
|
(fun (_, acc) f ->
|
||||||
match cnf f with
|
match cnf f with
|
||||||
| _, [] -> assert false
|
| _, [] -> assert false
|
||||||
| cmb, [a] -> Some Or, a :: acc
|
| _cmb, [a] -> Some Or, a :: acc
|
||||||
| Some Or, l ->
|
| Some Or, l ->
|
||||||
Some Or, l @@ acc
|
Some Or, l @@ acc
|
||||||
(* let proxy = mk_proxy () in *)
|
(* let proxy = mk_proxy () in *)
|
||||||
|
|
|
||||||
|
|
@ -1,143 +0,0 @@
|
||||||
(**************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Cubicle *)
|
|
||||||
(* Combining model checking algorithms and SMT solvers *)
|
|
||||||
(* *)
|
|
||||||
(* Mohamed Iguernelala *)
|
|
||||||
(* Universite Paris-Sud 11 *)
|
|
||||||
(* *)
|
|
||||||
(* Copyright 2011. This file is distributed under the terms of the *)
|
|
||||||
(* Apache Software License version 2.0 *)
|
|
||||||
(* *)
|
|
||||||
(**************************************************************************)
|
|
||||||
|
|
||||||
module V = Sparse_vec
|
|
||||||
|
|
||||||
type t = {heap : int Vec.t; indices : int V.t }
|
|
||||||
|
|
||||||
let _absent_index = -1
|
|
||||||
|
|
||||||
let init sz =
|
|
||||||
{ heap = Vec.init sz (fun i -> i) 0;
|
|
||||||
indices = V.init sz (fun i -> i) _absent_index}
|
|
||||||
|
|
||||||
let left i = (i lsl 1) + 1 (* i*2 + 1 *)
|
|
||||||
let right i = (i + 1) lsl 1 (* (i+1)*2 *)
|
|
||||||
let parent i = (i - 1) asr 1 (* (i-1) / 2 *)
|
|
||||||
|
|
||||||
(*
|
|
||||||
let rec heap_property cmp ({heap=heap} as s) i =
|
|
||||||
i >= (Vec.size heap) ||
|
|
||||||
((i = 0 || not(cmp (Vec. get heap i) (Vec.get heap (parent i))))
|
|
||||||
&& heap_property cmp s (left i) && heap_property cmp s (right i))
|
|
||||||
|
|
||||||
let heap_property cmp s = heap_property cmp s 1
|
|
||||||
*)
|
|
||||||
|
|
||||||
let percolate_up cmp {heap=heap;indices=indices} i =
|
|
||||||
let x = Vec.get heap i in
|
|
||||||
let pi = ref (parent i) in
|
|
||||||
let i = ref i in
|
|
||||||
while !i <> 0 && cmp x (Vec.get heap !pi) do
|
|
||||||
Vec.set heap !i (Vec.get heap !pi);
|
|
||||||
V.set indices (Vec.get heap !i) !i;
|
|
||||||
i := !pi;
|
|
||||||
pi := parent !i
|
|
||||||
done;
|
|
||||||
Vec.set heap !i x;
|
|
||||||
V.set indices x !i
|
|
||||||
|
|
||||||
let percolate_down cmp {heap=heap;indices=indices} i =
|
|
||||||
let x = Vec.get heap i in
|
|
||||||
let sz = Vec.size heap in
|
|
||||||
let li = ref (left i) in
|
|
||||||
let ri = ref (right i) in
|
|
||||||
let i = ref i in
|
|
||||||
(try
|
|
||||||
while !li < sz do
|
|
||||||
let child =
|
|
||||||
if !ri < sz && cmp (Vec.get heap !ri) (Vec.get heap !li) then !ri
|
|
||||||
else !li
|
|
||||||
in
|
|
||||||
if not (cmp (Vec.get heap child) x) then raise Exit;
|
|
||||||
Vec.set heap !i (Vec.get heap child);
|
|
||||||
V.set indices (Vec.get heap !i) !i;
|
|
||||||
i := child;
|
|
||||||
li := left !i;
|
|
||||||
ri := right !i
|
|
||||||
done;
|
|
||||||
with Exit -> ());
|
|
||||||
Vec.set heap !i x;
|
|
||||||
V.set indices x !i
|
|
||||||
|
|
||||||
let in_heap s n = n < V.length s.indices && V.get s.indices n >= 0
|
|
||||||
|
|
||||||
let decrease cmp s n =
|
|
||||||
assert (in_heap s n); percolate_up cmp s (V.get s.indices n)
|
|
||||||
|
|
||||||
(*
|
|
||||||
let increase cmp s n =
|
|
||||||
assert (in_heap s n); percolate_down cmp s (V.get s.indices n)
|
|
||||||
*)
|
|
||||||
|
|
||||||
let filter s filt cmp =
|
|
||||||
let j = ref 0 in
|
|
||||||
let lim = Vec.size s.heap in
|
|
||||||
for i = 0 to lim - 1 do
|
|
||||||
if filt (Vec.get s.heap i) then begin
|
|
||||||
Vec.set s.heap !j (Vec.get s.heap i);
|
|
||||||
V.set s.indices (Vec.get s.heap i) !j;
|
|
||||||
incr j;
|
|
||||||
end
|
|
||||||
else V.set s.indices (Vec.get s.heap i) _absent_index;
|
|
||||||
done;
|
|
||||||
Vec.shrink s.heap (lim - !j);
|
|
||||||
for i = (lim / 2) - 1 downto 0 do
|
|
||||||
percolate_down cmp s i
|
|
||||||
done
|
|
||||||
|
|
||||||
let size s = Vec.size s.heap
|
|
||||||
|
|
||||||
let is_empty s = Vec.is_empty s.heap
|
|
||||||
|
|
||||||
let clear {heap; indices} =
|
|
||||||
Vec.clear heap;
|
|
||||||
V.clear indices;
|
|
||||||
()
|
|
||||||
|
|
||||||
let insert cmp s n =
|
|
||||||
if not (in_heap s n) then
|
|
||||||
begin
|
|
||||||
V.set s.indices n (Vec.size s.heap);
|
|
||||||
Vec.push s.heap n;
|
|
||||||
percolate_up cmp s (V.get s.indices n)
|
|
||||||
end
|
|
||||||
|
|
||||||
let grow_to_at_least s sz =
|
|
||||||
V.resize s.indices sz;
|
|
||||||
Vec.grow_to_at_least s.heap sz
|
|
||||||
|
|
||||||
(*
|
|
||||||
let update cmp s n =
|
|
||||||
assert (heap_property cmp s);
|
|
||||||
begin
|
|
||||||
if in_heap s n then
|
|
||||||
begin
|
|
||||||
percolate_up cmp s (Vec.get s.indices n);
|
|
||||||
percolate_down cmp s (Vec.get s.indices n)
|
|
||||||
end
|
|
||||||
else insert cmp s n
|
|
||||||
end;
|
|
||||||
assert (heap_property cmp s)
|
|
||||||
*)
|
|
||||||
|
|
||||||
let remove_min cmp ({heap=heap; indices=indices} as s) =
|
|
||||||
if Vec.size heap=0 then raise Not_found;
|
|
||||||
let x = Vec.get heap 0 in
|
|
||||||
Vec.set heap 0 (Vec.last heap); (*heap.last()*)
|
|
||||||
V.set indices (Vec.get heap 0) 0;
|
|
||||||
V.set indices x (-1);
|
|
||||||
Vec.pop s.heap;
|
|
||||||
if Vec.size s.heap > 1 then percolate_down cmp s 0;
|
|
||||||
x
|
|
||||||
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
(**************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Cubicle *)
|
|
||||||
(* Combining model checking algorithms and SMT solvers *)
|
|
||||||
(* *)
|
|
||||||
(* Mohamed Iguernelala *)
|
|
||||||
(* Universite Paris-Sud 11 *)
|
|
||||||
(* *)
|
|
||||||
(* Copyright 2011. This file is distributed under the terms of the *)
|
|
||||||
(* Apache Software License version 2.0 *)
|
|
||||||
(* *)
|
|
||||||
(**************************************************************************)
|
|
||||||
|
|
||||||
type t
|
|
||||||
(** Heap of integers, whose priority is increased or decreased
|
|
||||||
incrementally (see {!decrease} for instance) *)
|
|
||||||
|
|
||||||
val init : int -> t
|
|
||||||
(** Create a heap with the given number of values inside.
|
|
||||||
[init len] contains integers from [0] to [len-1]. *)
|
|
||||||
|
|
||||||
val in_heap : t -> int -> bool
|
|
||||||
(** [in_heap h x] returns [true] iff [x] is among the integers that belong to
|
|
||||||
the heap. *)
|
|
||||||
|
|
||||||
val decrease : (int -> int -> bool) -> t -> int -> unit
|
|
||||||
(** [decrease cmp h x] decreases the value associated to [x] within [h],
|
|
||||||
according to the comparison function [cmp] *)
|
|
||||||
|
|
||||||
(*val increase : (int -> int -> bool) -> t -> int -> unit*)
|
|
||||||
|
|
||||||
val size : t -> int
|
|
||||||
(** Number of integers within the heap *)
|
|
||||||
|
|
||||||
val is_empty : t -> bool
|
|
||||||
|
|
||||||
val clear : t -> unit
|
|
||||||
(** Clear the content of the heap *)
|
|
||||||
|
|
||||||
val insert : (int -> int -> bool) -> t -> int -> unit
|
|
||||||
(** Insert a new integer into the heap, according to the given comparison *)
|
|
||||||
|
|
||||||
val grow_to_at_least: t -> int -> unit
|
|
||||||
(** Hint: augment the internal capacity of the heap until it reaches at
|
|
||||||
least the given integer *)
|
|
||||||
|
|
||||||
(*val update : (int -> int -> bool) -> t -> int -> unit*)
|
|
||||||
|
|
||||||
val remove_min : (int -> int -> bool) -> t -> int
|
|
||||||
(** Remove and return the integer that has the lowest value from the heap
|
|
||||||
@raise Not_found if the heap is empty *)
|
|
||||||
|
|
||||||
val filter : t -> (int -> bool) -> (int -> int -> bool) -> unit
|
|
||||||
(** Filter out values that don't satisfy the predicate. A comparison
|
|
||||||
function is used to re-order the heap *)
|
|
||||||
16
tests/jbuild
Normal file
16
tests/jbuild
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
; vim:ft=lisp:
|
||||||
|
|
||||||
|
(executable
|
||||||
|
((name test_api)
|
||||||
|
(libraries (msat msat.backend msat.sat msat.smt msat.mcsat dolmen))
|
||||||
|
(flags (:standard -w +a-4-42-44-48-50-58-32-60@8 -color always -safe-string))
|
||||||
|
(ocamlopt_flags (:standard -O3 -color always
|
||||||
|
-unbox-closures -unbox-closures-factor 20))
|
||||||
|
))
|
||||||
|
|
||||||
|
(alias
|
||||||
|
((name runtest)
|
||||||
|
(deps (test_api.exe))
|
||||||
|
(action (run ${<}))))
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
CURDIR=`dirname $0`
|
CURDIR=`dirname $0`
|
||||||
SOLVER="$CURDIR/../msat"
|
SOLVER="$CURDIR/../msat.exe"
|
||||||
|
|
||||||
solvertest () {
|
solvertest () {
|
||||||
for f in `find -L $1 -type f -name '*.cnf' -o -name '*.smt2'`
|
for f in `find -L $1 -type f -name '*.cnf' -o -name '*.smt2'`
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,11 @@ Copyright 2014 Simon Cruanes
|
||||||
|
|
||||||
(* Tests that require the API *)
|
(* Tests that require the API *)
|
||||||
|
|
||||||
|
open Msat
|
||||||
|
open Msat_sat
|
||||||
|
|
||||||
module F = Sat.Expr
|
module F = Sat.Expr
|
||||||
module T = Tseitin.Make(F)
|
module T = Msat_solver.Tseitin.Make(F)
|
||||||
|
|
||||||
let (|>) x f = f x
|
let (|>) x f = f x
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue