Git Product home page Git Product logo

msat's Introduction

MSAT Build Status

MSAT is an OCaml library that features a modular SAT-solver and some extensions (including SMT), derived from Alt-Ergo Zero.

It was presented at ICFP 2017, using a poster

COPYRIGHT

This program is distributed under the Apache Software License version 2.0. See the enclosed file LICENSE.

Documentation

See https://gbury.github.io/mSAT/

INSTALLATION

Via opam

Once the package is on opam, just opam install msat. For the development version, use:

opam pin add msat https://github.com/Gbury/mSAT.git

Manual installation

You will need dune and iter. The command is:

$ make install

USAGE

Generic SAT/SMT Solver

A modular implementation of the SMT algorithm can be found in the Msat.Solver module, as a functor which takes two modules :

  • A representation of formulas (which implements the Formula_intf.S signature)

  • A theory (which implements the Theory_intf.S signature) to check consistence of assertions.

  • A dummy empty module to ensure generativity of the solver (solver modules heavily relies on side effects to their internal state)

Sat Solver

A ready-to-use SAT solver is available in the Msat_sat module using the msat.sat library. It can be loaded as shown in the following code :

# #require "msat";;
# #require "msat.sat";;
# #print_depth 0;; (* do not print details *)

Then we can create a solver and create some boolean variables:

module Sat = Msat_sat
module E = Sat.Int_lit (* expressions *)

let solver = Sat.create()

(* We create here two distinct atoms *)
let a = E.fresh ()    (* A 'new_atom' is always distinct from any other atom *)
let b = E.make 1      (* Atoms can be created from integers *)

We can try and check the satisfiability of some clauses โ€” here, the clause a or b. Sat.assume adds a list of clauses to the solver. Calling Sat.solve will check the satisfiability of the current set of clauses, here "Sat".

# a <> b;;
- : bool = true
# Sat.assume solver [[a; b]] ();;
- : unit = ()
# let res = Sat.solve solver;;
val res : Sat.res = Sat.Sat ...

The Sat solver has an incremental mutable state, so we still have the clause a or b in our assumptions. We add not a and not b to the state, and get "Unsat".

# Sat.assume solver [[E.neg a]; [E.neg b]] () ;;
- : unit = ()
# let res = Sat.solve solver ;;
val res : Sat.res = Sat.Unsat ...

Formulas API

Writing clauses by hand can be tedious and error-prone. The functor Msat_tseitin.Make in the library msat.tseitin proposes a formula AST (parametrized by atoms) and a function to convert these formulas into clauses:

# #require "msat.tseitin";;
(* Module initialization *)
module F = Msat_tseitin.Make(E)

let solver = Sat.create ()

(* We create here two distinct atoms *)
let a = E.fresh ()    (* A fresh atom is always distinct from any other atom *)
let b = E.make 1      (* Atoms can be created from integers *)

(* Let's create some formulas *)
let p = F.make_atom a
let q = F.make_atom b
let r = F.make_and [p; q]
let s = F.make_or [F.make_not p; F.make_not q]

We can try and check the satisfiability of the given formulas, by turning it into clauses using make_cnf:

# Sat.assume solver (F.make_cnf r) ();;
- : unit = ()
# Sat.solve solver;;
- : Sat.res = Sat.Sat ...
# Sat.assume solver (F.make_cnf s) ();;
- : unit = ()
# Sat.solve solver ;;
- : Sat.res = Sat.Unsat ...

CDCL(T): a Sudoku solver as an example

The directory src/sudoku/ contains a simple Sudoku solver that uses the interface Msat.Make_cdcl_t. In essence, it implements the logical theory CDCL(Sudoku). The script sudoku_solve.sh compiles and runs the solver, as does dune exec src/sudoku/sudoku_solve.exe.

It's able to parse sudoku grids denoted as 81 integers (see tests/sudoku/sudoku.txt for example).

Here is a sample grid and the output from the solver (in roughly .5s):

$ echo '..............3.85..1.2.......5.7.....4...1...9.......5......73..2.1........4...9' > sudoku.txt
$ dune exec src/sudoku/sudoku_solve.exe -- sudoku.txt
...
#########################
solve grid:
  .........
  .....3.85
  ..1.2....
  ...5.7...
  ..4...1..
  .9.......
  5......73
  ..2.1....
  ....4...9
  
...
  987654321
  246173985
  351928746
  128537694
  634892157
  795461832
  519286473
  472319568
  863745219
  
###################
...

msat's People

Contributors

aspiwack avatar c-cube avatar gasche avatar gbury avatar jrrk2 avatar rixed avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

msat's Issues

How to get non-deterministic solutions?

I want to use mSAT to solve (a lot of) quite small CNFs (~40 variables), but I want to get non-deterministic solutions (e.g. a uniform pick from the set of solutions). Could I (easily) do that with this library? I appreciate all suggestions :).

design clean API for theories

instead of exposing dirty St:

  • simplify the internals by removing Solver_types.mli
  • have a submodule for each type in Solver_types.ml
  • expose only a carefully chosen part of each module outside of Msat

assert failure

Fatal error: exception File "src/core/internal.ml", line 676, characters 16-22: Assertion failed

  • msat at 66707b5,
  • smbc at 001b56ebb46.

run ./smbc.native --debug 1 examples/long_rev_sum5.lisp --max-depth 1010
(around 6s environ)

vec.get error

using https://github.com/c-cube/sidekick at commit 0b283a384d4f276e2128c1eeb0817b7f8cf17636 the following error is raised within msat:

./sidekick tests/sat/typed_v3l60005.cvc.smt2 --bt
invalid argument:
vec.get
Raised at file "pervasives.ml", line 33, characters 20-45
Called from file "src/core/Vec.ml" (inlined), line 54, characters 29-50
Called from file "src/core/Internal.ml", line 1413, characters 16-40
Called from file "src/core/Internal.ml", line 1503, characters 13-29
Called from file "src/core/Internal.ml", line 1562, characters 10-40
Called from file "src/core/Internal.ml", line 1578, characters 6-22
Called from file "src/core/Internal.ml" (inlined), line 1582, characters 50-67
Called from file "src/core/Internal.ml", line 2035, characters 16-32
Called from file "src/core/Internal.ml", line 2162, characters 6-15
Called from file "src/msat-solver/Sidekick_msat_solver.ml", line 607, characters 12-55
Called from file "src/smtlib/Process.ml", line 155, characters 4-44
Called from file "src/smtlib/Process.ml", line 229, characters 6-130
Called from file "src/core/CCResult.ml", line 239, characters 22-30
Called from file "list.ml", line 100, characters 12-15
Called from file "src/core/CCResult.ml", line 238, characters 4-125
Called from file "src/main/main.ml", line 184, characters 15-21

assertion failure

with zipperposition e0d2d2e4ce4e695eb044393642d53fcf6318235f :

./zipperposition.native examples/ind/tree3_easy.zf -bt     
File "src/core/res.ml", line 203, characters 6-12: Assertion failed
Raised at file "src/core/res.ml" (inlined), line 203, characters 6-47
Called from file "src/core/res.ml", line 261, characters 19-27
Called from file "src/prover/sat_solver.ml", line 227, characters 4-19
Called from file "src/core/CCFun.ml" (inlined), line 18, characters 22-27
Called from file "src/prover_calculi/avatar.ml", line 240, characters 19-73
Called from file "list.ml", line 82, characters 20-23
Called from file "src/prover_calculi/avatar.ml", line 240, characters 10-87
Called from file "src/prover/simplM.ml", line 24, characters 19-22
Called from file "src/prover/simplM.ml", line 24, characters 19-22
Called from file "src/prover/simplM.ml", line 24, characters 19-22
Called from file "src/prover/simplM.ml", line 24, characters 19-22
Called from file "src/prover/env.ml", line 410, characters 18-21
Called from file "src/prover/simplM.ml", line 24, characters 19-22
Called from file "src/prover/env.ml", line 553, characters 10-171
Called from file "src/prover/env.ml", line 410, characters 18-21
Called from file "src/prover/env.ml", line 569, characters 28-43
Called from file "set.ml", line 344, characters 34-55
Called from file "set.ml", line 344, characters 39-54
Called from file "set.ml", line 344, characters 39-54
Called from file "src/prover/env.ml", line 567, characters 6-746
Called from file "src/prover/saturate.ml", line 131, characters 55-78
Called from file "src/prover/saturate.ml", line 185, characters 23-56
Called from file "src/prover_phases/phases_impl.ml", line 301, characters 11-63
Called from file "src/prover_phases/phases.ml", line 116, characters 8-12
Called from file "src/prover_phases/phases.ml", line 116, characters 8-12
Called from file "src/prover_phases/phases.ml", line 116, characters 8-12
Called from file "src/prover_phases/phases.ml", line 116, characters 8-12
Called from file "src/prover_phases/phases.ml", line 208, characters 4-8

perf: phase saving

  • use a bool flag in the variable to save last phase
  • use false by default (corresponds to this flag being cleared)

Use reflexivity in Coq proofs

Currently coq proof can be quite slow (and even fail to check within reasonable time/memory).
One solution would be to change the structure of coq output from a srie of tactics to the following: write a reflexive function which would compute on a custom data structure (such as a list of resolutions).

function to add a literal

would be nice to have add_lit: lit -> unit that forces the solver to decide on this literal, even if there is no constraint on it yet.

bug

smbc @ f36a3af4bbd1e76bc85b00957224eb7ee9d1db58
msat @ 03dd2f9
OCaml 4.03

doesn't work but should: ./smbc.native --debug 1 -t 60 --check examples/sorted.lisp
almost similar: ./smbc.native --debug 1 -t 60 --check examples/sorted.lisp --depth-step 2

note: this works well ./smbc.native --debug 1 -t 60 --check examples/ty_infer.lisp

perf regression on 0.9

on pigeon/hole9.cnf it's quite clear.

possibly caused by the bitfield for polarity saving that might be erased when we clear the whole bitfield (even though the default polarity might be +, not -)?

Improve performances

Goal

mSAT currently compares quite unfavorably with other available sat solvers (see https://github.com/Gbury/sat-bench/blob/master/problems/pigeon/results ). It would be interesting to study how to improve performances either by:

  • finely tune the flambda options of the compiler to fully profit from the optimizations available
  • identify bottlenecks in the code using the spacetime profiler, and propose modifications to the code

Testing

Test files can be found under the tests directory. Additionally, the https://github.com/Gbury/sat-bench is meant to provide interesting problems on which to test and benchmark the various sat solvers, including mSAT. The problems in the repository should provide good runs on which to profile mSAT.

Current status

The profile branch contains the necessary instrumentation using the landmarks library. A simple make bench in that branch should compile the instrumented binary, and execute it on a reasonably sized problem, which takes about 10s currently.

The current bottleneck is, unsurprisingly, the propagation of atoms. One point of particular interest is why the propagate_in_clause function makes up such a small proportion of the propagate_atom function, and similarly, how the time spent in propagate_in_clause is distributed. In these two cases, the automatic instrumentation of landmarks seems to not be enough to have precise enough information.

Setup Github Actions CI

This repo used to use Travis CI, but since the free service ended, there is no CI anymore.

invalid_argument

with smbc @ 71faccb8e0607c4e05c83ba1041b16be45abd797

./smbc.native --debug 5 --check examples/rev.lisp --depth-step 1 --backtrace

I get

Fatal error: exception Invalid_argument("Sparse_vec.set")
Raised at file "pervasives.ml", line 31, characters 25-45
Called from file "src/util/sparse_vec.ml", line 64, characters 29-57
Called from file "src/core/internal.ml", line 218, characters 6-43
Called from file "src/core/internal.ml", line 420, characters 12-47
Called from file "src/core/internal.ml", line 1145, characters 6-33
Called from file "src/Solver.ml", line 2810, characters 18-41
Called from file "src/smbc.ml", line 55, characters 12-51
Called from file "src/smbc.ml", line 165, characters 2-19

use non generative api

replace generative functors by mere functors (or modules), and provide a type t which wraps the state.

pros:

  • state is more explicit
  • globals are now embedded in t and can be gc'd
  • more customizable: val create: ?size:int -> ?callback:โ€ฆ -> unit -> t
  • easier to copy/(de)serialize if need be
  • easier to integrate in other type t-based APIs
  • more convenient (no local module necessary)

cons:

  • change API

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.