├── .github
└── workflows
│ ├── haskell-ci.yml
│ └── hlint.yml
├── .gitignore
├── .hlint.yaml
├── .vim.custom
├── AUTHORS.md
├── CHANGELOG.md
├── LICENSE
├── README.md
├── Setup.lhs
├── cabal.haskell-ci
├── cabal.project
├── data
└── dimacs
│ ├── bf
│ ├── bf0432-007.cnf
│ ├── bf1355-075.cnf
│ ├── bf1355-638.cnf
│ ├── bf2670-001.cnf
│ ├── descr.html
│ ├── ssa0432-003.cnf
│ ├── ssa2670-130.cnf
│ ├── ssa2670-141.cnf
│ ├── ssa6288-047.cnf
│ ├── ssa7552-038.cnf
│ ├── ssa7552-158.cnf
│ ├── ssa7552-159.cnf
│ └── ssa7552-160.cnf
│ ├── blocksworld
│ ├── anomaly.cnf
│ ├── bw_large.a.cnf
│ ├── bw_large.b.cnf
│ ├── bw_large.c.cnf
│ ├── descr.html
│ ├── huge.cnf
│ └── medium.cnf
│ ├── bmc
│ ├── bmc-ibm-1.cnf
│ ├── bmc-ibm-2.cnf
│ ├── bmc-ibm-3.cnf
│ ├── bmc-ibm-4.cnf
│ ├── bmc-ibm-5.cnf
│ └── bmc-ibm-7.cnf
│ ├── logistics
│ ├── descr.html
│ ├── logistics.a.cnf
│ ├── logistics.b.cnf
│ ├── logistics.c.cnf
│ └── logistics.d.cnf
│ ├── parity
│ ├── descr
│ ├── par16-1-c.cnf
│ ├── par16-1.cnf
│ ├── par16-2-c.cnf
│ ├── par16-2.cnf
│ ├── par16-3-c.cnf
│ ├── par16-3.cnf
│ ├── par16-4-c.cnf
│ ├── par16-4.cnf
│ ├── par16-5-c.cnf
│ ├── par16-5.cnf
│ ├── par8-1-c.cnf
│ ├── par8-1.cnf
│ ├── par8-2-c.cnf
│ ├── par8-2.cnf
│ ├── par8-3-c.cnf
│ ├── par8-3.cnf
│ ├── par8-4-c.cnf
│ ├── par8-4.cnf
│ ├── par8-5-c.cnf
│ └── par8-5.cnf
│ └── phole
│ ├── descr.html
│ ├── hole6.cnf
│ ├── hole7.cnf
│ └── hole8.cnf
├── ersatz.cabal
├── examples
├── Factor.hs
├── Fish.hs
├── qbf
│ ├── Coloring.hs
│ └── Synthesis.hs
├── regexp-grid
│ ├── Main.hs
│ └── RegexpGrid
│ │ ├── Problem.hs
│ │ ├── Regexp.hs
│ │ └── Types.hs
└── sudoku
│ ├── Main.hs
│ └── Sudoku
│ ├── Cell.hs
│ └── Problem.hs
├── notes
├── SPOILER.html
├── grid.pdf
└── papers.md
├── src
├── Ersatz.hs
└── Ersatz
│ ├── Bit.hs
│ ├── BitChar.hs
│ ├── Bits.hs
│ ├── Codec.hs
│ ├── Counting.hs
│ ├── Equatable.hs
│ ├── Internal
│ ├── Formula.hs
│ ├── Literal.hs
│ ├── Parser.hs
│ └── StableName.hs
│ ├── Orderable.hs
│ ├── Problem.hs
│ ├── Relation.hs
│ ├── Relation
│ ├── ARS.hs
│ ├── Data.hs
│ ├── Op.hs
│ └── Prop.hs
│ ├── Solution.hs
│ ├── Solver.hs
│ ├── Solver
│ ├── Common.hs
│ ├── DepQBF.hs
│ ├── Kissat.hs
│ ├── Lingeling.hs
│ ├── Minisat.hs
│ └── Z3.hs
│ └── Variable.hs
└── tests
├── HUnit.hs
├── Moore.hs
├── Speed.hs
├── Z001.hs
└── properties.hs
/.github/workflows/hlint.yml:
--------------------------------------------------------------------------------
1 | name: HLint
2 | on:
3 | - push
4 | - pull_request
5 | jobs:
6 | hlint:
7 | runs-on: ubuntu-latest
8 |
9 | steps:
10 | - name: Checkout repository
11 | uses: actions/checkout@v4
12 |
13 | - name: 'Set up HLint'
14 | uses: haskell-actions/hlint-setup@v2
15 | with:
16 | version: '3.8'
17 |
18 | - name: 'Run HLint'
19 | uses: haskell-actions/hlint-run@v2
20 | with:
21 | path: src/
22 | fail-on: suggestion
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | dist
2 | dist-newstyle
3 | docs
4 | wiki
5 | TAGS
6 | tags
7 | wip
8 | .DS_Store
9 | .*.swp
10 | .*.swo
11 | *.o
12 | *.p_o
13 | *.hi
14 | *.p_hi
15 | *~
16 | *#
17 | *.prof
18 | *.hp
19 | .stack-work/
20 | cabal-dev
21 | *.chi
22 | *.chs.h
23 | *.dyn_o
24 | *.dyn_hi
25 | .hpc
26 | .hsenv
27 | .cabal-sandbox/
28 | cabal.sandbox.config
29 | *.prof
30 | *.aux
31 | *.hp
32 | *.eventlog
33 | cabal.project.local
34 | cabal.project.local~
35 | .HTF/
36 | .ghc.environment.*
37 |
--------------------------------------------------------------------------------
/.hlint.yaml:
--------------------------------------------------------------------------------
1 | - arguments: [-XCPP, --cpp-define=HLINT, --cpp-ansi]
2 |
3 | - ignore:
4 | name: Use camelCase
5 |
6 | - ignore:
7 | name: Use lambda-case
8 |
9 | - ignore:
10 | name: Use || # We define a different `or`
11 |
12 | - ignore:
13 | name: Use && # We define a different `and`
14 |
15 | - ignore: {name: Hoist not, within: [Ersatz.Bit]} # This is how we define `any`, ya dingus
16 | - ignore: {name: Use infix, within: [Ersatz.Relation.Op]} # We define a different `union` function in this module
17 |
--------------------------------------------------------------------------------
/.vim.custom:
--------------------------------------------------------------------------------
1 | " Add the following to your .vimrc to automatically load this on startup
2 |
3 | " if filereadable(".vim.custom")
4 | " so .vim.custom
5 | " endif
6 |
7 | function StripTrailingWhitespace()
8 | let myline=line(".")
9 | let mycolumn = col(".")
10 | silent %s/ *$//
11 | call cursor(myline, mycolumn)
12 | endfunction
13 |
14 | " enable syntax highlighting
15 | syntax on
16 |
17 | " search for the tags file anywhere between here and /
18 | set tags=TAGS;/
19 |
20 | " highlight tabs and trailing spaces
21 | set listchars=tab:‗‗,trail:‗
22 | set list
23 |
24 | " f2 runs hasktags
25 | map :exec ":!hasktags -x -c --ignore src"
26 |
27 | " strip trailing whitespace before saving
28 | " au BufWritePre *.hs,*.markdown silent! cal StripTrailingWhitespace()
29 |
30 | " rebuild hasktags after saving
31 | au BufWritePost *.hs silent! :exec ":!hasktags -x -c --ignore src"
32 |
--------------------------------------------------------------------------------
/AUTHORS.md:
--------------------------------------------------------------------------------
1 | Authors
2 | =======
3 |
4 | `ersatz` started as a one man project by [Edward Kmett](mailto:ekmett@gmail.com) [@ekmett](https://github.com/ekmett).
5 | However, it then languished for 3 years after Don Stewart [@donsbot](https://github.com/donsbot) released perfectly adequate [bindings for yices](http://hackage.haskell.org/package/yices-painless).
6 |
7 | It was revived by [Johan Kiviniemi](mailto:ersatz@johan.kiviniemi.name) [@ion1](https://github.com/ion1) who got it into a working condition by implementing some missing parts, which inspired the original author into polishing it up and releasing it.
8 |
9 | Eric Mertens [@glguy](https://github.com/glguy) has been pouring code into it ever since then.
10 |
11 | Omission from this page is by no means an attempt to discount your contributions! Thank you for all of your help!
12 |
13 | -Edward Kmett
14 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | next [????.??.??]
2 | -----------------
3 | * Add the `Ersatz.Relation.ARS` module
4 | * Change the type of `buildFrom`:
5 |
6 | ```diff
7 | -buildFrom :: (Ix a, Ix b) => (a -> b -> Bit) -> ((a,b),(a,b)) -> Relation a b
8 | +buildFrom :: (Ix a, Ix b) => ((a,b),(a,b)) -> ((a,b) -> Bit) -> Relation a b
9 | ```
10 | * Add support for `kissat` and the `lingeling` trio (`lingeling`, `plingeling`,
11 | `treengeling`) of SAT solvers.
12 | * Add QBF examples (requires DepQBF solver)
13 | * Replace `test-framework` with `tasty` in the test suite.
14 |
15 | 0.5 [2023.09.08]
16 | ----------------
17 | * The `forall` function in `Ersatz.Variable` has been renamed to
18 | `forall_`, since a future version of GHC will make the use of `forall` as an
19 | identifier an error.
20 | * The types of `decode` and `solveWith` have been slightly less general:
21 |
22 | ```diff
23 | -decode :: MonadPlus f => Solution -> a -> f (Decoded a)
24 | +decode :: Solution -> a -> Maybe (Decoded a)
25 |
26 | -solveWith :: (Monad m, MonadPlus n, HasSAT s, Default s, Codec a) => Solver s m -> StateT s m a -> m (Result, n (Decoded a))
27 | +solveWith :: (Monad m, HasSAT s, Default s, Codec a) => Solver s m -> StateT s m a -> m (Result, Maybe (Decoded a))
28 | ```
29 |
30 | That is, these functions now use `Maybe` instead of an arbitrary `MonadPlus`.
31 | This change came about because:
32 |
33 | 1. Practically all uses of `solveWith` in the wild are already picking `n` to
34 | be `Maybe`, and
35 | 2. The behavior of `decode` and `solveWith` for `MonadPlus` instances besides
36 | `Maybe` could produce surprising results, as this behavior was not well
37 | specified.
38 | * Fix a bug in which `decode` could return inconsistent results with solution
39 | that underconstrain variables. For instance:
40 |
41 | ```hs
42 | do b <- exists
43 | pure [b, not b]
44 | ```
45 |
46 | Previously, this could decode to `[False, False]` (an invalid assignment).
47 | `ersatz` now adopts the convention that unconstrained non-negative `Literal`s
48 | will always be assigned `False`, and unconstrained negative `Literal`s will
49 | always be assigned `True`. This means that the example above would now decode
50 | to `[False, True]`.
51 |
52 | 0.4.13 [2022.11.01]
53 | -------------------
54 | * Make the examples compile with `mtl-2.3.*`.
55 | * Add more documentation to the `Ersatz.Relation.*` modules, the `Variable`
56 | class, and the data types in `Ersatz.Bits`.
57 |
58 | 0.4.12 [2022.08.11]
59 | -------------------
60 | * Add `Equatable` and `Orderable` instances for more base and containers types
61 | * Add solver support for `z3`
62 |
63 | 0.4.11 [2022.05.18]
64 | -------------------
65 | * Allow building with `mtl-2.3.*` and `transformers-0.6.*`.
66 |
67 | 0.4.10 [2021.11.16]
68 | -------------------
69 | * Allow the test suite to build with recent GHCs.
70 | * Drop support for pre-8.0 versions of GHC.
71 |
72 | 0.4.9 [2021.02.17]
73 | ------------------
74 | * Allow building with `lens-5.*`.
75 | * Change to `build-type: Simple`
76 |
77 | 0.4.8 [2020.01.29]
78 | ------------------
79 | * Add `MonadSAT` and `MonadQSAT`
80 | * Achieve forward compatibility with
81 | [GHC proposal 229](https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0229-whitespace-bang-patterns.rst).
82 |
83 | 0.4.7 [2019.06.01]
84 | ------------------
85 | * Add `anyminisat` and `trySolvers`
86 |
87 | 0.4.6 [2019.05.20]
88 | ------------------
89 | * Add support for `cryptominisat5`
90 |
91 | 0.4.5 [2019.05.02]
92 | ------------------
93 | * Allow `ersatz-regexp-grid` to build with `base-4.13` (GHC 8.8).
94 |
95 | 0.4.4 [2018.08.13]
96 | ------------------
97 | * Avoid the use of failable pattern matches in `do`-notation to support
98 | building with GHC 8.6, which enables `MonadFailDesugaring`.
99 |
100 | 0.4.3 [2018.07.03]
101 | ------------------
102 | * Make the test suite compile on GHC 8.6.
103 | * Allow building with `containers-0.6`.
104 |
105 | 0.4.2
106 | -----
107 | * Add `Semigroup` instances for `Clause` and `Formula`.
108 | * Generalize `regular`, `regular_in_degree`, `regular_out_degree`,
109 | `max_in_degree`, `min_in_degree`, `max_out_degree`, and `min_out_degree` to
110 | work over heterogeneous relations.
111 | * Add `buildFrom` to `Ersatz.Relation.Data`.
112 | * Add `difference`, `reflexive_closure`, and `symmetric_closure` to
113 | `Ersatz.Relation.Op`.
114 | * Add `anti_symmetric` and `total` to `Ersatz.Relation.Prop`.
115 |
116 | 0.4.1
117 | -----
118 | * Add a library dependency on the `doctests` test suite
119 |
120 | 0.4
121 | ---
122 | * Performance improvements for CNF printing and parsing
123 | * Add the `Ersatz.Counting`, `Ersatz.Relation`, `Ersatz.Relation.Data`,
124 | `Ersatz.Relation.Prop`, and `Ersatz.Relation.Op` modules
125 | * Eliminate the `Or` constructor from `Bit` towards using AIG
126 | * Fix error in the SAT encoding of the `choose` function
127 | * Revamp `Setup.hs` to use `cabal-doctest`. This makes it build
128 | with `Cabal-2.0`, and makes the `doctest`s work with `cabal new-build` and
129 | sandboxes.
130 |
131 | 0.3.1
132 | -----
133 | * Removed the explicit `Safe` annotations. They can't be maintained by mere mortals. Patches to mark packages upstream as `Trustworthy` will be accepted as needed.
134 |
135 | 0.3
136 | -----
137 | * Unified `Encoding` and `Decoding` into `Codec`
138 | * Unified the `forall` and `exists` implementations into a single `literally`
139 | method in `Variable` class.
140 | * Added `Orderable` type class and instances
141 | * Added `Ersatz.Bits.Bits` for variable-sized bit arithmetic.
142 | * Renamed `Ersatz.Bits.half_adder` to `halfAdder`
143 | * Renamed `Ersatz.Bits.full_adder` to `fullAdder`
144 | * Added new examples
145 | * Dropped `blaze` package dependency in favor of newer `bytestring`
146 | * Significantly shrank the number of "Trustworthy" modules
147 | * Added various generic `V1` instances
148 | * Added `Equatable` instances for `Map` and `IntMap`
149 | * Added `Ersatz.BitChar` module for computing with `Char` and `String`
150 | * Wider version bounds for `transformers` and `mtl`.
151 |
152 | 0.2.6.1
153 | -----
154 | * Exported `Ersatz.Variable.GVariable`
155 |
156 | 0.2.6
157 | -----
158 | * `temporary 1.2` support
159 |
160 | 0.2.5.1
161 | -------
162 | * Slightly faster builds due to dropping the need for `template-haskell`.
163 |
164 | 0.2.5
165 | -----
166 | * Support for GHC 7.8 and `lens` 4.x
167 |
168 | 0.2.3
169 | -----
170 | * SafeHaskell support
171 |
172 | 0.2.2
173 | -----
174 | * Added examples to the documentation.
175 | * Made the examples build as `ersatz-sudoku` and `ersatz-regexp-grid`.
176 |
177 | 0.2.1
178 | -----
179 | * Added `examples/sudoku`, a sudoku solver.
180 |
181 | 0.2.0.1
182 | -------
183 | * Fixed an overly conservative bound on `containers`.
184 |
185 | 0.2
186 | ---
187 | * Converted to `Control.Lens` internally.
188 | * Added `Ersatz.Solver.DepQBF`
189 | * Added a bunch of example dimacs files
190 | * The types now prevent one from applying a solver that does not support QSAT
191 | to a problem that requires it
192 | * Added `examples/regexp-grid`, a program that solves the [regular expression
193 | crossword](http://www.coinheist.com/rubik/a_regular_crossword/grid.pdf)
194 | * Made some optimizations to the formula generation. `regexp-grid` went from
195 | 71737 literals and 427725 clauses to 8618 literals and 172100 clauses and got
196 | much faster
197 | * Based `and` and `or` in `Boolean` on `Foldable`; added `all` and `any`
198 |
199 | 0.1.0.2
200 | -----
201 | * Added correct links to the source repository and issue tracker to the cabal project
202 |
203 | 0.1
204 | ---
205 | * Repository Initialized
206 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright © 2010-2015 Edward Kmett
2 | Copyright © 2014-2015 Eric Mertens
3 | Copyright © 2013 Johan Kiviniemi
4 |
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without
8 | modification, are permitted provided that the following conditions are
9 | met:
10 |
11 | * Redistributions of source code must retain the above copyright
12 | notice, this list of conditions and the following disclaimer.
13 |
14 | * Redistributions in binary form must reproduce the above
15 | copyright notice, this list of conditions and the following
16 | disclaimer in the documentation and/or other materials provided
17 | with the distribution.
18 |
19 | * Neither the name of Edward Kmett nor the names of other
20 | contributors may be used to endorse or promote products derived
21 | from this software without specific prior written permission.
22 |
23 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 |
35 | ----------------------------------------------------------------------
36 |
37 | The puzzle in notes/grid.pdf was also made available to us for
38 | distribution under the BSD3 license. This puzzle was written
39 | for MIT Mystery Hunt 2013 by Dan Gulotta based on an idea by
40 | Palmer Mebane. Copyright © 2013 Dan Gulotta
41 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Ersatz
2 |
3 | [](https://hackage.haskell.org/package/ersatz) [](https://github.com/ekmett/ersatz/actions?query=workflow%3AHaskell-CI)
4 |
5 | Ersatz is a library for generating QSAT (CNF/QBF) problems using a monad. It takes care of generating the normal form, encoding your problem, marshaling the data to an external solver, and parsing and interpreting the result into Haskell types.
6 |
7 | What differentiates Ersatz is the use of observable sharing in the API.
8 |
9 | For instance to define a full adder:
10 |
11 | ```haskell
12 | full_adder :: Bit -> Bit -> Bit -> (Bit, Bit)
13 | full_adder a b cin = (s2, c1 || c2)
14 | where (s1,c1) = half_adder a b
15 | (s2,c2) = half_adder s1 cin
16 |
17 | half_adder :: Bit -> Bit -> (Bit, Bit)
18 | half_adder a b = (a `xor` b, a && b)
19 | ```
20 |
21 | as opposed to the following code in [satchmo](https://hackage.haskell.org/package/satchmo/):
22 |
23 |
24 | ```haskell
25 | full_adder :: Boolean -> Boolean -> Boolean
26 | -> SAT ( Boolean, Boolean )
27 | full_adder a b c = do
28 | let s x y z = sum $ map fromEnum [x,y,z]
29 | r <- fun3 ( \ x y z -> odd $ s x y z ) a b c
30 | d <- fun3 ( \ x y z -> 1 < s x y z ) a b c
31 | return ( r, d )
32 |
33 | half_adder :: Boolean -> Boolean
34 | -> SAT ( Boolean, Boolean )
35 | half_adder a b = do
36 | let s x y = sum $ map fromEnum [x,y]
37 | r <- fun2 ( \ x y -> odd $ s x y ) a b
38 | d <- fun2 ( \ x y -> 1 < s x y ) a b
39 | return ( r, d )
40 | ```
41 |
42 | This enables you to use the a much richer subset of Haskell than the purely monadic meta-language, and it becomes much easier to see that the resulting encoding is correct.
43 |
44 | To allocate fresh existentially or universally quantified variables or to assert that a Bit is true and add the attendant circuit with sharing to the current problem you use the SAT monad.
45 |
46 | ```haskell
47 | verify_currying :: (MonadQSAT s m) => m ()
48 | verify_currying = do
49 | (x::Bit, y::Bit, z::Bit) <- forall_
50 | assert $ ((x && y) ==> z) === (x ==> y ==> z)
51 | ```
52 |
53 | We can then hand that off to a SAT solver, and get back an answer:
54 |
55 | ```haskell
56 | main = solveWith depqbf verify_currying >>= print
57 | ```
58 |
59 | Support is offered for decoding various Haskell datatypes from the
60 | solution provided by the SAT solver.
61 |
62 | # Examples
63 |
64 | Included are a couple of examples included with the distribution.
65 | Neither are as fast as a dedicated solver for their respective
66 | domains, but they showcase how you can solve real world problems
67 | involving 10s or 100s of thousands of variables and constraints
68 | with `ersatz`.
69 |
70 | ## sudoku
71 |
72 | ```
73 | % time ersatz-sudoku
74 | Problem:
75 | ┌───────┬───────┬───────┐
76 | │ 5 3 │ 7 │ │
77 | │ 6 │ 1 9 5 │ │
78 | │ 9 8 │ │ 6 │
79 | ├───────┼───────┼───────┤
80 | │ 8 │ 6 │ 3 │
81 | │ 4 │ 8 3 │ 1 │
82 | │ 7 │ 2 │ 6 │
83 | ├───────┼───────┼───────┤
84 | │ 6 │ │ 2 8 │
85 | │ │ 4 1 9 │ 5 │
86 | │ │ 8 │ 7 9 │
87 | └───────┴───────┴───────┘
88 | Solution:
89 | ┌───────┬───────┬───────┐
90 | │ 5 3 4 │ 6 7 8 │ 9 1 2 │
91 | │ 6 7 2 │ 1 9 5 │ 3 4 8 │
92 | │ 1 9 8 │ 3 4 2 │ 5 6 7 │
93 | ├───────┼───────┼───────┤
94 | │ 8 5 9 │ 7 6 1 │ 4 2 3 │
95 | │ 4 2 6 │ 8 5 3 │ 7 9 1 │
96 | │ 7 1 3 │ 9 2 4 │ 8 5 6 │
97 | ├───────┼───────┼───────┤
98 | │ 9 6 1 │ 5 3 7 │ 2 8 4 │
99 | │ 2 8 7 │ 4 1 9 │ 6 3 5 │
100 | │ 3 4 5 │ 2 8 6 │ 1 7 9 │
101 | └───────┴───────┴───────┘
102 | ersatz-sudoku 1,13s user 0,04s system 99% cpu 1,179 total
103 | ```
104 |
105 | ## regexp-grid
106 |
107 | This solves the [regular crossword puzzle](https://github.com/ekmett/ersatz/raw/master/notes/grid.pdf) from the MIT mystery hunt.
108 |
109 | > % time ersatz-regexp-grid
110 |
111 | [SPOILER](notes/SPOILER.html)
112 |
113 | > ersatz-regexp-grid 2,45s user 0,05s system 99% cpu 2,502 total
114 |
115 | Contact Information
116 | -------------------
117 |
118 | Contributions and bug reports are welcome!
119 |
120 | Please feel free to contact me through github or on the #haskell IRC channel on irc.freenode.net.
121 |
122 | -Edward Kmett
123 |
124 |
--------------------------------------------------------------------------------
/Setup.lhs:
--------------------------------------------------------------------------------
1 | #!/usr/bin/runhaskell
2 | > module Main (main) where
3 |
4 | > import Distribution.Simple
5 |
6 | > main :: IO ()
7 | > main = defaultMain
8 |
--------------------------------------------------------------------------------
/cabal.haskell-ci:
--------------------------------------------------------------------------------
1 | distribution: jammy
2 | no-tests-no-benchmarks: False
3 | unconstrained: False
4 | apt: minisat
5 | copy-fields: all
6 | -- irc-channels: irc.freenode.org#haskell-lens
7 | irc-if-in-origin-repo: True
8 | error-missing-methods: none
9 |
--------------------------------------------------------------------------------
/cabal.project:
--------------------------------------------------------------------------------
1 | packages: .
2 |
3 | package ersatz
4 | flags: +examples
5 |
--------------------------------------------------------------------------------
/data/dimacs/bf/descr.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ekmett/ersatz/ffce5f2f8ab54fda0fb625b2ed67dc395c08e6bc/data/dimacs/bf/descr.html
--------------------------------------------------------------------------------
/data/dimacs/blocksworld/anomaly.cnf:
--------------------------------------------------------------------------------
1 | c satplan version 1.0
2 | c created: Thu Jul 24 14:13:58 PDT 1997
3 | c operators: bw_orig.ops
4 | c facts: anomaly.facts
5 | c goal: 3
6 | c wff: anomaly.cnf
7 | c map: anomaly.map
8 | c type: wff
9 | p cnf 48 261
10 | -1 -3 4 0
11 | -1 -5 6 0
12 | -8 -7 9 0
13 | -8 -5 10 0
14 | -1 -11 -2 0
15 | -8 -13 -10 0
16 | -14 15 0
17 | -11 16 0
18 | -12 17 0
19 | -7 -15 0
20 | -3 -17 0
21 | -1 -12 0
22 | -1 -13 0
23 | -8 -14 0
24 | -8 -11 0
25 | 7 15 0
26 | 3 17 0
27 | 1 2 0
28 | 8 10 0
29 | 11 -16 0
30 | 1 -4 0
31 | 1 -6 0
32 | 8 -9 0
33 | 3 -4 0
34 | 5 -6 0
35 | 7 -9 0
36 | 1 8 0
37 | 14 11 12 13 0
38 | 7 3 5 0
39 | -1 -8 0
40 | -8 -1 0
41 | -14 -11 0
42 | -14 -12 0
43 | -14 -13 0
44 | -11 -14 0
45 | -11 -12 0
46 | -11 -13 0
47 | -12 -14 0
48 | -12 -11 0
49 | -12 -13 0
50 | -13 -14 0
51 | -13 -11 0
52 | -13 -12 0
53 | -7 -3 0
54 | -7 -5 0
55 | -3 -7 0
56 | -3 -5 0
57 | -5 -7 0
58 | -5 -3 0
59 | -1 -14 0
60 | -8 -12 0
61 | -1 -7 0
62 | -8 -3 0
63 | -14 -7 0
64 | -12 -3 0
65 | -13 -5 0
66 | -18 -19 20 0
67 | -18 -21 22 0
68 | -18 -23 24 0
69 | -25 -26 27 0
70 | -25 -21 28 0
71 | -25 -23 29 0
72 | -30 -26 31 0
73 | -30 -19 32 0
74 | -30 -23 33 0
75 | -18 -34 -20 0
76 | -18 -35 -22 0
77 | -18 -36 -24 0
78 | -25 -36 -29 0
79 | -30 -37 -31 0
80 | -30 -36 -33 0
81 | -37 38 0
82 | -34 39 0
83 | -35 40 0
84 | -26 -38 0
85 | -19 -39 0
86 | -21 -40 0
87 | -18 -34 2 0
88 | -18 -35 4 0
89 | -18 -36 6 0
90 | -25 -37 0
91 | -25 -35 0
92 | -30 -37 9 0
93 | -30 -34 0
94 | -30 -36 10 0
95 | -18 15 0
96 | -25 16 0
97 | -30 17 0
98 | -26 15 0
99 | -19 16 0
100 | -21 17 0
101 | 26 -15 38 0
102 | 19 -16 39 0
103 | 21 -17 40 0
104 | 18 -2 20 0
105 | 18 -4 22 0
106 | 18 -6 24 0
107 | 25 29 0
108 | 30 -9 31 0
109 | 30 -10 33 0
110 | 37 15 -38 0
111 | 34 16 -39 0
112 | 35 17 -40 0
113 | 18 2 -20 0
114 | 18 4 -22 0
115 | 18 6 -24 0
116 | 25 -27 0
117 | 25 -28 0
118 | 30 9 -31 0
119 | 30 -32 0
120 | 30 10 -33 0
121 | 19 2 -20 0
122 | 21 4 -22 0
123 | 23 6 -24 0
124 | 26 -27 0
125 | 21 -28 0
126 | 26 9 -31 0
127 | 19 -32 0
128 | 23 10 -33 0
129 | 18 25 30 0
130 | 37 34 35 36 0
131 | 26 19 21 23 0
132 | -18 -25 0
133 | -18 -30 0
134 | -25 -18 0
135 | -25 -30 0
136 | -30 -18 0
137 | -30 -25 0
138 | -37 -34 0
139 | -37 -35 0
140 | -37 -36 0
141 | -34 -37 0
142 | -34 -35 0
143 | -34 -36 0
144 | -35 -37 0
145 | -35 -34 0
146 | -35 -36 0
147 | -36 -37 0
148 | -36 -34 0
149 | -36 -35 0
150 | -26 -19 0
151 | -26 -21 0
152 | -26 -23 0
153 | -19 -26 0
154 | -19 -21 0
155 | -19 -23 0
156 | -21 -26 0
157 | -21 -19 0
158 | -21 -23 0
159 | -23 -26 0
160 | -23 -19 0
161 | -23 -21 0
162 | -18 -37 0
163 | -25 -34 0
164 | -30 -35 0
165 | -18 -26 0
166 | -25 -19 0
167 | -30 -21 0
168 | -37 -26 0
169 | -34 -19 0
170 | -35 -21 0
171 | -36 -23 0
172 | -41 -42 0
173 | -44 -45 0
174 | -44 -43 0
175 | -46 -43 0
176 | -41 -48 0
177 | -41 -47 20 0
178 | -44 -48 29 0
179 | -46 -47 32 0
180 | -46 -48 33 0
181 | -41 38 0
182 | -44 39 0
183 | -46 40 0
184 | -45 38 0
185 | -42 40 0
186 | 45 -38 0
187 | 42 -40 0
188 | 41 -20 0
189 | 41 -22 0
190 | 44 -27 0
191 | 44 -29 0
192 | 46 -32 0
193 | 46 -33 0
194 | 47 39 0
195 | 41 24 0
196 | 44 28 0
197 | 46 31 0
198 | 43 24 0
199 | 42 28 0
200 | 45 31 0
201 | 41 44 46 0
202 | 47 48 0
203 | 45 42 43 0
204 | -41 -44 0
205 | -41 -46 0
206 | -44 -41 0
207 | -44 -46 0
208 | -46 -41 0
209 | -46 -44 0
210 | -47 -48 0
211 | -48 -47 0
212 | -45 -42 0
213 | -45 -43 0
214 | -42 -45 0
215 | -42 -43 0
216 | -43 -45 0
217 | -43 -42 0
218 | -44 -47 0
219 | -41 -45 0
220 | -46 -42 0
221 | -48 -43 0
222 | -4 -9 0
223 | -9 -4 0
224 | -2 -4 0
225 | -2 -6 0
226 | -4 -2 0
227 | -4 -6 0
228 | -6 -2 0
229 | -6 -4 0
230 | -9 -10 0
231 | -10 -9 0
232 | -2 -16 0
233 | -4 -17 0
234 | -9 -15 0
235 | -20 -27 0
236 | -22 -31 0
237 | -27 -20 0
238 | -28 -32 0
239 | -31 -22 0
240 | -32 -28 0
241 | -20 -32 0
242 | -22 -28 0
243 | -27 -31 0
244 | -28 -22 0
245 | -31 -27 0
246 | -32 -20 0
247 | -20 -22 0
248 | -20 -24 0
249 | -22 -20 0
250 | -22 -24 0
251 | -24 -20 0
252 | -24 -22 0
253 | -27 -28 0
254 | -27 -29 0
255 | -28 -27 0
256 | -28 -29 0
257 | -29 -27 0
258 | -29 -28 0
259 | -31 -32 0
260 | -31 -33 0
261 | -32 -31 0
262 | -32 -33 0
263 | -33 -31 0
264 | -33 -32 0
265 | -20 -39 0
266 | -22 -40 0
267 | -27 -38 0
268 | -28 -40 0
269 | -31 -38 0
270 | -32 -39 0
271 |
--------------------------------------------------------------------------------
/data/dimacs/blocksworld/descr.html:
--------------------------------------------------------------------------------
1 | SATLIB - Benchmark Problems
2 |
3 | SAT-encoded Blocks World Planning Problems
4 |
5 | The Blocks World is a very well-known problem domain in AI research.
6 | The general scenario in Blocks World Planning comprises
7 | a number of blocks and a table. The blocks can be piled onto
8 | each other, where the downmost block of a pile is always on the table.
9 | For the benchmark problems, taken from [KS96],
10 | there is only one operator which moves the top block of a
11 | pile to the top of another pile or onto the table.
12 | Given an initial and a goal configuration of blocks, the problem
13 | is to find a sequence of operators which, when applied to
14 | the initial configuration, leads to the goal situation.
15 | Such a sequence is called a (linear) plan.
16 | Blocks can only be moved when they are clear, i.e., no other block is piled
17 | on top of them, and they can be only moved on top of blocks which are clear
18 | or onto the table. If these conditions are satisfied, the move operator
19 | always succeeds.
20 | There is an optimisation and
21 | a decision variant of the Blocks World Planning problem:
22 | In the optimisation variant, the goal is to find a shortest plan,
23 | whereas in the decision variant, the question is to decide whether
24 | a plan of a given length exists.
25 | The two variants are tightly related, as shortest plans can
26 | be found by solving a series of decision problems.
27 | SAT-based approaches to Blocks World Planning typically focus on
28 | the decision variant.
29 |
30 | SAT encoding
31 |
32 | A linear encoding strategy was used for translating Blocks World
33 | instances into CNF formulae.
34 | The encoding is based on the following predicates:
35 |
36 |
37 | - clear(x,t) - block x is clear at time t
38 |
- on(x,y,t) - block x is directly on top of y at time t
39 |
- move(x,y,z,t) - block x is moved from block y
40 | on block z at time t
41 |
42 |
43 |
44 | clear and on are state predicates, while move is an
45 | action predicate. The axioms which specify the problem can be grouped into
46 | 4 categories:
47 |
48 |
49 |
50 | - actions imply their preconditions and effects,
51 |
- exactly one action can be executed at each time t,
52 |
- classical frame conditions which
53 | state that state predicates do not change between
54 | t and t+1 if they are not directly affected by
55 | the action at time t,
56 |
- in move(x,y,z,t), x,y, and z are distinct.
57 |
58 |
59 |
60 | The last group of actions is redundant, but
61 | has been found to be useful for speeding up local search.
62 | For a given blocks world planning instance, instantiating
63 | the predicates listed above gives the propositional variables
64 | over which the axioms can then be formulated as CNF clauses.
65 |
66 |
67 | The SAT encoding used for generating the benchmark problems
68 | relies critically on two important techniques for reducing the
69 | size of the CNF formulae: operator splitting [KMS96] and
70 | simple propositional reductions (unit propagation and subsumption).
71 | Operator splitting replaces a predicate which take three or
72 | more arguments by a number of binary predicates. This
73 | reduces the number of propositional variables
74 | for the given problem from O(kn^3) to O(kn^2) where n is
75 | the number of blocks and k the number of plan steps.
76 | Unit propagation and subsumptions, two well-known
77 | propositional reduction strategies, are used to simplify the formulae
78 | before applying stochastic local search. These reducations can be
79 | computed in polynomial time and eliminate a number of propositional
80 | variables thus efficiently reducing the search space.
81 | Intuitively, these by applying these strategies the
82 | initial and goal states are propagated into the planning structure.
83 | Details on the SAT encoding used to generate the
84 | benchmark problems can be found in [KS96,KMS96].
85 |
86 |
The benchmark instances
87 |
88 |
89 | Our benchmark set contains 7 blocks world planning instances
90 | taken from Henry Kautz' and Bart Selman's SATPLAN distribution.
91 | These instances are described in Table 1;
92 | despite the reductions mentioned above, they are still
93 | very large when compared to other instances of our benchmark suit.
94 | bw_large.c and bw_large.d belong to the hardest problems which can
95 | be solved by state-of-the-art SAT algorithms in reasonable time.
96 |
97 |
98 |
99 |
100 | instance
101 | | blocks | steps
102 | | vars | clauses
103 | |
104 | anomaly | 3 | 3
105 | | 48 | 261
106 | |
107 | medium | 5 | 4
108 | | 116 | 953
109 | |
110 | bw_large.a | 9 | 6
111 | | 459 | 4,675
112 | |
113 | huge | 9 | 6
114 | | 459 | 7,054
115 | |
116 | bw_large.b | 11 | 9
117 | | 1,087 | 13,772
118 | |
119 | bw_large.c | 15 | 14
120 | | 3,016 | 50,457
121 | |
122 | bw_large.d | 19 | 18
123 | | 6,325 | 131,973
124 | |
125 |
126 | Table 1: SAT-encoded Blocks World Planning instances (linear encoding),
127 | contributed by Henry Kautz and Bart Selman (all instances are satisfiable).
128 |
129 |
130 |
131 |
132 |
Bibliography
133 |
134 |
135 |
136 | [KS96]
137 | | Henry Kautz and Bart Selman
138 | Pushing the Envelope: Planning, Propositional Logic, and Stochastic Search.
139 | Proc. AAAI-96, pages 1194--1201, 1996
140 | |
141 | [KMS96]
142 | | Henry Kautz and David McAllester and Bart Selman
143 | Encoding Plans in Propositional Logic.
144 | Proc. KR-96, pages 374--384, 1996
145 | |
146 |
147 |
148 |
149 |
--------------------------------------------------------------------------------
/data/dimacs/logistics/descr.html:
--------------------------------------------------------------------------------
1 | SATLIB - Benchmark Problems
2 |
3 |
4 | SAT-encoded Logistics Planning Problems
5 |
6 | In the logistics planning domain, packages have to be moved
7 | between different locations in different cities.
8 | Within cities, packages are carried by
9 | trucks while between cities they are flown in planes. Both, trucks and
10 | airplanes are of limited capacity.
11 | The problem involves 3 operators (load, unload, move)
12 | and two state predicates (in,at).
13 | The initial and goal state specify locations for
14 | all packages, trucks, and planes;
15 | the plans allow multiple actions to be executed simultaneously,
16 | as long as no conflicts arise from their preconditions and effects.
17 | Like in the Blocks World Plannig problem,
18 | there is an optimisation and a decition variant of
19 | the Logistics Planning problem:
20 | In the optimisation variant, the goal is to find a shortest plan,
21 | whereas in the decision variant, the question is to decide whether
22 | a plan of a given length exists.
23 | Again, the two variants are tightly related, as shortest plans can
24 | be found by solving a series of decision problems.
25 | SAT-based approaches to Logistics Planning typically focus on
26 | the decision variant.
27 |
28 | SAT encoding of Logistics Planning instances
29 |
30 | A state-based encoding strategy was used for translating
31 | Logistics instances into CNF formulae.
32 | In this encoding, only the state predicates are explicitely
33 | represented by propositional variables, whereas
34 | the operators are only implicitly represented by
35 | constraints on transitions of the state predicates.
36 |
37 |
38 | The SAT encoding used for generating the benchmark problems
39 | relies critically on two important techniques for reducing the
40 | size of the CNF formulae: operator splitting [KMS96] and
41 | simple propositional reductions (unit propagation and subsumption).
42 | Operator splitting replaces a predicate which take three or
43 | more arguments by a number of binary predicates. This
44 | reduces the number of propositional variables
45 | for the given problem from O(kn^3) to O(kn^2) where n is
46 | the number of blocks and k the number of plan steps.
47 | Unit propagation and subsumptions, two well-known
48 | propositional reduction strategies, are used to simplify the formulae
49 | before applying stochastic local search. These reducations can be
50 | computed in polynomial time and eliminate a number of propositional
51 | variables thus efficiently reducing the search space.
52 | Intuitively, these by applying these strategies the
53 | initial and goal states are propagated into the planning structure.
54 | Details on the SAT encoding used to generate the
55 | benchmark problems can be found in [KS96,KMS96].
56 |
57 |
58 |
The benchmark instances
59 |
60 |
61 | Our benchmark set contains 7 blocks world planning instances
62 | taken from Henry Kautz' and Bart Selman's SATPLAN distribution.
63 | These instances are described in Table 1;
64 | despite their size they seem to be easier
65 | than the Blocks World Planning instances for local search methods.
66 |
67 |
68 |
69 |
70 | instance
71 | | packages | (parallel) plan steps
72 | | vars | clauses
73 | |
74 | logistics.a | 8 | 11
75 | | 828 | 6,718
76 | |
77 | logistics.b | 5 | 13
78 | | 843 | 7,301
79 | |
80 | logistics.c | 7 | 13
81 | | 1,141 | 10,719
82 | |
83 | logistics.d | 9 | 14
84 | | 4,713 | 21,991
85 | |
86 |
87 |
88 | Table 1: SAT-encoded Logistics Planning instances,
89 | contributed by Henry Kautz and Bart Selman (all instances
90 | are satisfiable).
91 |
92 |
93 |
94 |
Bibliography
95 |
96 |
97 |
98 | [KS96]
99 | | Henry Kautz and Bart Selman
100 | Pushing the Envelope: Planning, Propositional Logic, and Stochastic Search.
101 | Proc. AAAI-96, pages 1194--1201, 1996
102 | |
103 | [KMS96]
104 | | Henry Kautz and David McAllester and Bart Selman
105 | Encoding Plans in Propositional Logic.
106 | Proc. KR-96, pages 374--384, 1996
107 | |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/data/dimacs/parity/descr:
--------------------------------------------------------------------------------
1 | All satisfiable
2 |
--------------------------------------------------------------------------------
/data/dimacs/parity/par8-1-c.cnf:
--------------------------------------------------------------------------------
1 | c FILE: par8-1-c.cnf
2 | c
3 | c SOURCE: James Crawford (jc@research.att.com)
4 | c
5 | c DESCRIPTION: Instance arises from the problem of learning the parity
6 | c function.
7 | c
8 | c parxx-y denotes a parity problem on xx bits. y is simply the
9 | c intance number.
10 | c
11 | c parxx-y-c denotes an instance identical to parxx-y except that
12 | c the instances have been simplified (to create an equivalent
13 | c problem).
14 | c
15 | c NOTE: Satisfiable (checked for 8 and 16 size instances. All
16 | c instances are satisfiable by construction)
17 | c
18 | c NOTE: Number of clauses corrected August 3, 1993
19 | c
20 | c Converted from tableau format Tue Aug 3 09:55:20 EDT 1993
21 | p cnf 64 254
22 | -2 1
23 | 0
24 | -3 -2
25 | 0
26 | -3 -2 -1
27 | 0
28 | 3 2 -1
29 | 0
30 | -3 2 1
31 | 0
32 | 3 -2 1
33 | 0
34 | -4 2
35 | 0
36 | -5 -4
37 | 0
38 | -5 -4 -2
39 | 0
40 | 5 4 -2
41 | 0
42 | -5 4 2
43 | 0
44 | 5 -4 2
45 | 0
46 | -6 4
47 | 0
48 | -7 -6
49 | 0
50 | -7 -6 -4
51 | 0
52 | 7 6 -4
53 | 0
54 | -7 6 4
55 | 0
56 | 7 -6 4
57 | 0
58 | -8 6
59 | 0
60 | -9 -8
61 | 0
62 | -9 -8 -6
63 | 0
64 | 9 8 -6
65 | 0
66 | -9 8 6
67 | 0
68 | 9 -8 6
69 | 0
70 | -10 8
71 | 0
72 | -11 -10
73 | 0
74 | -11 -10 -8
75 | 0
76 | 11 10 -8
77 | 0
78 | -11 10 8
79 | 0
80 | 11 -10 8
81 | 0
82 | -12 10
83 | 0
84 | -13 -12
85 | 0
86 | -13 -12 -10
87 | 0
88 | 13 12 -10
89 | 0
90 | -13 12 10
91 | 0
92 | 13 -12 10
93 | 0
94 | -14 12
95 | 0
96 | -15 -14
97 | 0
98 | -15 -14 -12
99 | 0
100 | 15 14 -12
101 | 0
102 | -15 14 12
103 | 0
104 | 15 -14 12
105 | 0
106 | -16 14
107 | 0
108 | -17 -16
109 | 0
110 | -17 -16 -14
111 | 0
112 | 17 16 -14
113 | 0
114 | -17 16 14
115 | 0
116 | 17 -16 14
117 | 0
118 | -18 16
119 | 0
120 | -19 -18
121 | 0
122 | -19 -18 -16
123 | 0
124 | 19 18 -16
125 | 0
126 | -19 18 16
127 | 0
128 | 19 -18 16
129 | 0
130 | -20 18
131 | 0
132 | -21 -20
133 | 0
134 | -21 -20 -18
135 | 0
136 | 21 20 -18
137 | 0
138 | -21 20 18
139 | 0
140 | 21 -20 18
141 | 0
142 | -22 20
143 | 0
144 | -23 -22
145 | 0
146 | -23 -22 -20
147 | 0
148 | 23 22 -20
149 | 0
150 | -23 22 20
151 | 0
152 | 23 -22 20
153 | 0
154 | -24 22
155 | 0
156 | -25 -24
157 | 0
158 | -25 -24 -22
159 | 0
160 | 25 24 -22
161 | 0
162 | -25 24 22
163 | 0
164 | 25 -24 22
165 | 0
166 | -26 24
167 | 0
168 | -27 -26
169 | 0
170 | -27 -26 -24
171 | 0
172 | 27 26 -24
173 | 0
174 | -27 26 24
175 | 0
176 | 27 -26 24
177 | 0
178 | -28 26
179 | 0
180 | -29 -28
181 | 0
182 | -29 -28 -26
183 | 0
184 | 29 28 -26
185 | 0
186 | -29 28 26
187 | 0
188 | 29 -28 26
189 | 0
190 | 28 -30
191 | 0
192 | -31 -30
193 | 0
194 | -31 -28 -30
195 | 0
196 | 31 -28 30
197 | 0
198 | -31 28 30
199 | 0
200 | 31 28 -30
201 | 0
202 | -33 -32 -3
203 | 0
204 | 33 32 -3
205 | 0
206 | -33 32 3
207 | 0
208 | 33 -32 3
209 | 0
210 | -35 -34 -32
211 | 0
212 | 35 34 -32
213 | 0
214 | -35 34 32
215 | 0
216 | 35 -34 32
217 | 0
218 | -37 -34 36
219 | 0
220 | 37 -34 -36
221 | 0
222 | -37 34 -36
223 | 0
224 | 37 34 36
225 | 0
226 | -39 -38 -5
227 | 0
228 | 39 38 -5
229 | 0
230 | -39 38 5
231 | 0
232 | 39 -38 5
233 | 0
234 | -35 -40 -38
235 | 0
236 | 35 40 -38
237 | 0
238 | -35 40 38
239 | 0
240 | 35 -40 38
241 | 0
242 | -42 -41 -40
243 | 0
244 | 42 41 -40
245 | 0
246 | -42 41 40
247 | 0
248 | 42 -41 40
249 | 0
250 | -36 -41 43
251 | 0
252 | 36 -41 -43
253 | 0
254 | -36 41 -43
255 | 0
256 | 36 41 43
257 | 0
258 | -44 -7 29
259 | 0
260 | 44 -7 -29
261 | 0
262 | 44 7 29
263 | 0
264 | -44 7 -29
265 | 0
266 | -33 -45 -44
267 | 0
268 | 33 45 -44
269 | 0
270 | -33 45 44
271 | 0
272 | 33 -45 44
273 | 0
274 | -37 -36 -45
275 | 0
276 | 37 36 -45
277 | 0
278 | -37 36 45
279 | 0
280 | 37 -36 45
281 | 0
282 | -37 -46 -9
283 | 0
284 | 37 46 -9
285 | 0
286 | -37 46 9
287 | 0
288 | 37 -46 9
289 | 0
290 | -36 -43 -46
291 | 0
292 | 36 43 -46
293 | 0
294 | -36 43 46
295 | 0
296 | 36 -43 46
297 | 0
298 | -39 -47 -11
299 | 0
300 | 39 47 -11
301 | 0
302 | -39 47 11
303 | 0
304 | 39 -47 11
305 | 0
306 | -33 -48 -47
307 | 0
308 | 33 48 -47
309 | 0
310 | -33 48 47
311 | 0
312 | 33 -48 47
313 | 0
314 | -37 -36 -48
315 | 0
316 | 37 36 -48
317 | 0
318 | -37 36 48
319 | 0
320 | 37 -36 48
321 | 0
322 | -39 -49 -13
323 | 0
324 | 39 49 -13
325 | 0
326 | -39 49 13
327 | 0
328 | 39 -49 13
329 | 0
330 | -33 -36 -49
331 | 0
332 | 33 36 -49
333 | 0
334 | -33 36 49
335 | 0
336 | 33 -36 49
337 | 0
338 | -50 -15 29
339 | 0
340 | 50 -15 -29
341 | 0
342 | 50 15 29
343 | 0
344 | -50 15 -29
345 | 0
346 | -35 -37 -50
347 | 0
348 | 35 37 -50
349 | 0
350 | -35 37 50
351 | 0
352 | 35 -37 50
353 | 0
354 | -39 -35 -17
355 | 0
356 | 39 35 -17
357 | 0
358 | -39 35 17
359 | 0
360 | 39 -35 17
361 | 0
362 | -39 -51 -19
363 | 0
364 | 39 51 -19
365 | 0
366 | -39 51 19
367 | 0
368 | 39 -51 19
369 | 0
370 | -35 -52 -51
371 | 0
372 | 35 52 -51
373 | 0
374 | -35 52 51
375 | 0
376 | 35 -52 51
377 | 0
378 | -37 -52 42
379 | 0
380 | 37 -52 -42
381 | 0
382 | -37 52 -42
383 | 0
384 | 37 52 42
385 | 0
386 | -53 -21 29
387 | 0
388 | 53 -21 -29
389 | 0
390 | 53 21 29
391 | 0
392 | -53 21 -29
393 | 0
394 | -33 -54 -53
395 | 0
396 | 33 54 -53
397 | 0
398 | -33 54 53
399 | 0
400 | 33 -54 53
401 | 0
402 | -35 -54 42
403 | 0
404 | 35 -54 -42
405 | 0
406 | -35 54 -42
407 | 0
408 | 35 54 42
409 | 0
410 | -33 -23 42
411 | 0
412 | 33 -23 -42
413 | 0
414 | -33 23 -42
415 | 0
416 | 33 23 42
417 | 0
418 | -55 -25 29
419 | 0
420 | 55 -25 -29
421 | 0
422 | 55 25 29
423 | 0
424 | -55 25 -29
425 | 0
426 | -33 -56 -55
427 | 0
428 | 33 56 -55
429 | 0
430 | -33 56 55
431 | 0
432 | 33 -56 55
433 | 0
434 | -35 -56 36
435 | 0
436 | 35 -56 -36
437 | 0
438 | -35 56 -36
439 | 0
440 | 35 56 36
441 | 0
442 | -39 -57 -27
443 | 0
444 | 39 57 -27
445 | 0
446 | -39 57 27
447 | 0
448 | 39 -57 27
449 | 0
450 | -58 -57 29
451 | 0
452 | 58 -57 -29
453 | 0
454 | 58 57 29
455 | 0
456 | -58 57 -29
457 | 0
458 | -35 -59 -58
459 | 0
460 | 35 59 -58
461 | 0
462 | -35 59 58
463 | 0
464 | 35 -59 58
465 | 0
466 | -37 -59 -36
467 | 0
468 | 37 -59 36
469 | 0
470 | -37 59 36
471 | 0
472 | 37 59 -36
473 | 0
474 | -37 -60 -31
475 | 0
476 | 37 60 -31
477 | 0
478 | -37 60 31
479 | 0
480 | 37 -60 31
481 | 0
482 | -42 -61 -60
483 | 0
484 | 42 61 -60
485 | 0
486 | -42 61 60
487 | 0
488 | 42 -61 60
489 | 0
490 | -36 -61 43
491 | 0
492 | 36 -61 -43
493 | 0
494 | -36 61 -43
495 | 0
496 | 36 61 43
497 | 0
498 | -39 -62 -30
499 | 0
500 | 39 62 -30
501 | 0
502 | -39 62 30
503 | 0
504 | 39 -62 30
505 | 0
506 | -33 -63 -62
507 | 0
508 | 33 63 -62
509 | 0
510 | -33 63 62
511 | 0
512 | 33 -63 62
513 | 0
514 | -42 -64 -63
515 | 0
516 | 42 64 -63
517 | 0
518 | -42 64 63
519 | 0
520 | 42 -64 63
521 | 0
522 | -36 -64 -43
523 | 0
524 | 36 -64 43
525 | 0
526 | -36 64 43
527 | 0
528 | 36 64 -43
529 | 0
530 |
531 |
--------------------------------------------------------------------------------
/data/dimacs/parity/par8-2-c.cnf:
--------------------------------------------------------------------------------
1 | c FILE: par8-2-c.cnf
2 | c
3 | c SOURCE: James Crawford (jc@research.att.com)
4 | c
5 | c DESCRIPTION: Instance arises from the problem of learning the parity
6 | c function.
7 | c
8 | c parxx-y denotes a parity problem on xx bits. y is simply the
9 | c intance number.
10 | c
11 | c parxx-y-c denotes an instance identical to parxx-y except that
12 | c the instances have been simplified (to create an equivalent
13 | c problem).
14 | c
15 | c NOTE: Satisfiable (checked for 8 and 16 size instances. All
16 | c instances are satisfiable by construction)
17 | c
18 | c NOTE: Number of clauses corrected August 3, 1993
19 | c
20 | c Converted from tableau format Tue Aug 3 09:55:26 EDT 1993
21 | p cnf 68 270
22 | -2 1
23 | 0
24 | -3 -2
25 | 0
26 | -3 -2 -1
27 | 0
28 | 3 2 -1
29 | 0
30 | -3 2 1
31 | 0
32 | 3 -2 1
33 | 0
34 | -4 2
35 | 0
36 | -5 -4
37 | 0
38 | -5 -4 -2
39 | 0
40 | 5 4 -2
41 | 0
42 | -5 4 2
43 | 0
44 | 5 -4 2
45 | 0
46 | -6 4
47 | 0
48 | -7 -6
49 | 0
50 | -7 -6 -4
51 | 0
52 | 7 6 -4
53 | 0
54 | -7 6 4
55 | 0
56 | 7 -6 4
57 | 0
58 | -8 6
59 | 0
60 | -9 -8
61 | 0
62 | -9 -8 -6
63 | 0
64 | 9 8 -6
65 | 0
66 | -9 8 6
67 | 0
68 | 9 -8 6
69 | 0
70 | -10 8
71 | 0
72 | -11 -10
73 | 0
74 | -11 -10 -8
75 | 0
76 | 11 10 -8
77 | 0
78 | -11 10 8
79 | 0
80 | 11 -10 8
81 | 0
82 | -12 10
83 | 0
84 | -13 -12
85 | 0
86 | -13 -12 -10
87 | 0
88 | 13 12 -10
89 | 0
90 | -13 12 10
91 | 0
92 | 13 -12 10
93 | 0
94 | -14 12
95 | 0
96 | -15 -14
97 | 0
98 | -15 -14 -12
99 | 0
100 | 15 14 -12
101 | 0
102 | -15 14 12
103 | 0
104 | 15 -14 12
105 | 0
106 | -16 14
107 | 0
108 | -17 -16
109 | 0
110 | -17 -16 -14
111 | 0
112 | 17 16 -14
113 | 0
114 | -17 16 14
115 | 0
116 | 17 -16 14
117 | 0
118 | -18 16
119 | 0
120 | -19 -18
121 | 0
122 | -19 -18 -16
123 | 0
124 | 19 18 -16
125 | 0
126 | -19 18 16
127 | 0
128 | 19 -18 16
129 | 0
130 | -20 18
131 | 0
132 | -21 -20
133 | 0
134 | -21 -20 -18
135 | 0
136 | 21 20 -18
137 | 0
138 | -21 20 18
139 | 0
140 | 21 -20 18
141 | 0
142 | -22 20
143 | 0
144 | -23 -22
145 | 0
146 | -23 -22 -20
147 | 0
148 | 23 22 -20
149 | 0
150 | -23 22 20
151 | 0
152 | 23 -22 20
153 | 0
154 | -24 22
155 | 0
156 | -25 -24
157 | 0
158 | -25 -24 -22
159 | 0
160 | 25 24 -22
161 | 0
162 | -25 24 22
163 | 0
164 | 25 -24 22
165 | 0
166 | -26 24
167 | 0
168 | -27 -26
169 | 0
170 | -27 -26 -24
171 | 0
172 | 27 26 -24
173 | 0
174 | -27 26 24
175 | 0
176 | 27 -26 24
177 | 0
178 | -28 26
179 | 0
180 | -29 -28
181 | 0
182 | -29 -28 -26
183 | 0
184 | 29 28 -26
185 | 0
186 | -29 28 26
187 | 0
188 | 29 -28 26
189 | 0
190 | 28 -30
191 | 0
192 | -31 -30
193 | 0
194 | -31 -28 -30
195 | 0
196 | 31 -28 30
197 | 0
198 | -31 28 30
199 | 0
200 | 31 28 -30
201 | 0
202 | -33 -32 -3
203 | 0
204 | 33 32 -3
205 | 0
206 | -33 32 3
207 | 0
208 | 33 -32 3
209 | 0
210 | -35 -34 -32
211 | 0
212 | 35 34 -32
213 | 0
214 | -35 34 32
215 | 0
216 | 35 -34 32
217 | 0
218 | -37 -36 -34
219 | 0
220 | 37 36 -34
221 | 0
222 | -37 36 34
223 | 0
224 | 37 -36 34
225 | 0
226 | -39 -38 -36
227 | 0
228 | 39 38 -36
229 | 0
230 | -39 38 36
231 | 0
232 | 39 -38 36
233 | 0
234 | -41 -40 -38
235 | 0
236 | 41 40 -38
237 | 0
238 | -41 40 38
239 | 0
240 | 41 -40 38
241 | 0
242 | -43 -40 42
243 | 0
244 | 43 -40 -42
245 | 0
246 | -43 40 -42
247 | 0
248 | 43 40 42
249 | 0
250 | -33 -44 -5
251 | 0
252 | 33 44 -5
253 | 0
254 | -33 44 5
255 | 0
256 | 33 -44 5
257 | 0
258 | -35 -44 -45
259 | 0
260 | 35 -44 45
261 | 0
262 | -35 44 45
263 | 0
264 | 35 44 -45
265 | 0
266 | -33 -46 -7
267 | 0
268 | 33 46 -7
269 | 0
270 | -33 46 7
271 | 0
272 | 33 -46 7
273 | 0
274 | -35 -47 -46
275 | 0
276 | 35 47 -46
277 | 0
278 | -35 47 46
279 | 0
280 | 35 -47 46
281 | 0
282 | -39 -48 -47
283 | 0
284 | 39 48 -47
285 | 0
286 | -39 48 47
287 | 0
288 | 39 -48 47
289 | 0
290 | -43 -48 42
291 | 0
292 | 43 -48 -42
293 | 0
294 | -43 48 -42
295 | 0
296 | 43 48 42
297 | 0
298 | -37 -49 -9
299 | 0
300 | 37 49 -9
301 | 0
302 | -37 49 9
303 | 0
304 | 37 -49 9
305 | 0
306 | -39 -50 -49
307 | 0
308 | 39 50 -49
309 | 0
310 | -39 50 49
311 | 0
312 | 39 -50 49
313 | 0
314 | -45 -50 41
315 | 0
316 | 45 -50 -41
317 | 0
318 | -45 50 -41
319 | 0
320 | 45 50 41
321 | 0
322 | -41 -11 42
323 | 0
324 | 41 -11 -42
325 | 0
326 | -41 11 -42
327 | 0
328 | 41 11 42
329 | 0
330 | -37 -51 -13
331 | 0
332 | 37 51 -13
333 | 0
334 | -37 51 13
335 | 0
336 | 37 -51 13
337 | 0
338 | -41 -51 43
339 | 0
340 | 41 -51 -43
341 | 0
342 | -41 51 -43
343 | 0
344 | 41 51 43
345 | 0
346 | -35 -52 -15
347 | 0
348 | 35 52 -15
349 | 0
350 | -35 52 15
351 | 0
352 | 35 -52 15
353 | 0
354 | -37 -53 -52
355 | 0
356 | 37 53 -52
357 | 0
358 | -37 53 52
359 | 0
360 | 37 -53 52
361 | 0
362 | -39 -53 43
363 | 0
364 | 39 -53 -43
365 | 0
366 | -39 53 -43
367 | 0
368 | 39 53 43
369 | 0
370 | -37 -54 -17
371 | 0
372 | 37 54 -17
373 | 0
374 | -37 54 17
375 | 0
376 | 37 -54 17
377 | 0
378 | -39 -54 -43
379 | 0
380 | 39 -54 43
381 | 0
382 | -39 54 43
383 | 0
384 | 39 54 -43
385 | 0
386 | -33 -55 -19
387 | 0
388 | 33 55 -19
389 | 0
390 | -33 55 19
391 | 0
392 | 33 -55 19
393 | 0
394 | -37 -56 -55
395 | 0
396 | 37 56 -55
397 | 0
398 | -37 56 55
399 | 0
400 | 37 -56 55
401 | 0
402 | -43 -42 -56
403 | 0
404 | 43 42 -56
405 | 0
406 | -43 42 56
407 | 0
408 | 43 -42 56
409 | 0
410 | -35 -57 -21
411 | 0
412 | 35 57 -21
413 | 0
414 | -35 57 21
415 | 0
416 | 35 -57 21
417 | 0
418 | -37 -58 -57
419 | 0
420 | 37 58 -57
421 | 0
422 | -37 58 57
423 | 0
424 | 37 -58 57
425 | 0
426 | -41 -59 -58
427 | 0
428 | 41 59 -58
429 | 0
430 | -41 59 58
431 | 0
432 | 41 -59 58
433 | 0
434 | -43 -59 42
435 | 0
436 | 43 -59 -42
437 | 0
438 | -43 59 -42
439 | 0
440 | 43 59 42
441 | 0
442 | -35 -60 -23
443 | 0
444 | 35 60 -23
445 | 0
446 | -35 60 23
447 | 0
448 | 35 -60 23
449 | 0
450 | -37 -60 -41
451 | 0
452 | 37 -60 41
453 | 0
454 | -37 60 41
455 | 0
456 | 37 60 -41
457 | 0
458 | -33 -61 -25
459 | 0
460 | 33 61 -25
461 | 0
462 | -33 61 25
463 | 0
464 | 33 -61 25
465 | 0
466 | -35 -62 -61
467 | 0
468 | 35 62 -61
469 | 0
470 | -35 62 61
471 | 0
472 | 35 -62 61
473 | 0
474 | -39 -63 -62
475 | 0
476 | 39 63 -62
477 | 0
478 | -39 63 62
479 | 0
480 | 39 -63 62
481 | 0
482 | -41 -64 -63
483 | 0
484 | 41 64 -63
485 | 0
486 | -41 64 63
487 | 0
488 | 41 -64 63
489 | 0
490 | -43 -64 42
491 | 0
492 | 43 -64 -42
493 | 0
494 | -43 64 -42
495 | 0
496 | 43 64 42
497 | 0
498 | -33 -65 -27
499 | 0
500 | 33 65 -27
501 | 0
502 | -33 65 27
503 | 0
504 | 33 -65 27
505 | 0
506 | -35 -66 -65
507 | 0
508 | 35 66 -65
509 | 0
510 | -35 66 65
511 | 0
512 | 35 -66 65
513 | 0
514 | -41 -66 43
515 | 0
516 | 41 -66 -43
517 | 0
518 | -41 66 -43
519 | 0
520 | 41 66 43
521 | 0
522 | -41 -43 -29
523 | 0
524 | 41 43 -29
525 | 0
526 | -41 43 29
527 | 0
528 | 41 -43 29
529 | 0
530 | -33 -31 39
531 | 0
532 | 33 -31 -39
533 | 0
534 | -33 31 -39
535 | 0
536 | 33 31 39
537 | 0
538 | -37 -67 -30
539 | 0
540 | 37 67 -30
541 | 0
542 | -37 67 30
543 | 0
544 | 37 -67 30
545 | 0
546 | -39 -68 -67
547 | 0
548 | 39 68 -67
549 | 0
550 | -39 68 67
551 | 0
552 | 39 -68 67
553 | 0
554 | -45 -68 43
555 | 0
556 | 45 -68 -43
557 | 0
558 | -45 68 -43
559 | 0
560 | 45 68 43
561 | 0
562 |
563 |
--------------------------------------------------------------------------------
/data/dimacs/parity/par8-3-c.cnf:
--------------------------------------------------------------------------------
1 | c FILE: par8-3-c.cnf
2 | c
3 | c SOURCE: James Crawford (jc@research.att.com)
4 | c
5 | c DESCRIPTION: Instance arises from the problem of learning the parity
6 | c function.
7 | c
8 | c parxx-y denotes a parity problem on xx bits. y is simply the
9 | c intance number.
10 | c
11 | c parxx-y-c denotes an instance identical to parxx-y except that
12 | c the instances have been simplified (to create an equivalent
13 | c problem).
14 | c
15 | c NOTE: Satisfiable (checked for 8 and 16 size instances. All
16 | c instances are satisfiable by construction)
17 | c
18 | c NOTE: Number of clauses corrected August 3, 1993
19 | c
20 | c Converted from tableau format Tue Aug 3 09:55:33 EDT 1993
21 | p cnf 75 298
22 | -2 1
23 | 0
24 | -3 -2
25 | 0
26 | -3 -2 -1
27 | 0
28 | 3 2 -1
29 | 0
30 | -3 2 1
31 | 0
32 | 3 -2 1
33 | 0
34 | -4 2
35 | 0
36 | -5 -4
37 | 0
38 | -5 -4 -2
39 | 0
40 | 5 4 -2
41 | 0
42 | -5 4 2
43 | 0
44 | 5 -4 2
45 | 0
46 | -6 4
47 | 0
48 | -7 -6
49 | 0
50 | -7 -6 -4
51 | 0
52 | 7 6 -4
53 | 0
54 | -7 6 4
55 | 0
56 | 7 -6 4
57 | 0
58 | -8 6
59 | 0
60 | -9 -8
61 | 0
62 | -9 -8 -6
63 | 0
64 | 9 8 -6
65 | 0
66 | -9 8 6
67 | 0
68 | 9 -8 6
69 | 0
70 | -10 8
71 | 0
72 | -11 -10
73 | 0
74 | -11 -10 -8
75 | 0
76 | 11 10 -8
77 | 0
78 | -11 10 8
79 | 0
80 | 11 -10 8
81 | 0
82 | -12 10
83 | 0
84 | -13 -12
85 | 0
86 | -13 -12 -10
87 | 0
88 | 13 12 -10
89 | 0
90 | -13 12 10
91 | 0
92 | 13 -12 10
93 | 0
94 | -14 12
95 | 0
96 | -15 -14
97 | 0
98 | -15 -14 -12
99 | 0
100 | 15 14 -12
101 | 0
102 | -15 14 12
103 | 0
104 | 15 -14 12
105 | 0
106 | -16 14
107 | 0
108 | -17 -16
109 | 0
110 | -17 -16 -14
111 | 0
112 | 17 16 -14
113 | 0
114 | -17 16 14
115 | 0
116 | 17 -16 14
117 | 0
118 | -18 16
119 | 0
120 | -19 -18
121 | 0
122 | -19 -18 -16
123 | 0
124 | 19 18 -16
125 | 0
126 | -19 18 16
127 | 0
128 | 19 -18 16
129 | 0
130 | -20 18
131 | 0
132 | -21 -20
133 | 0
134 | -21 -20 -18
135 | 0
136 | 21 20 -18
137 | 0
138 | -21 20 18
139 | 0
140 | 21 -20 18
141 | 0
142 | -22 20
143 | 0
144 | -23 -22
145 | 0
146 | -23 -22 -20
147 | 0
148 | 23 22 -20
149 | 0
150 | -23 22 20
151 | 0
152 | 23 -22 20
153 | 0
154 | -24 22
155 | 0
156 | -25 -24
157 | 0
158 | -25 -24 -22
159 | 0
160 | 25 24 -22
161 | 0
162 | -25 24 22
163 | 0
164 | 25 -24 22
165 | 0
166 | -26 24
167 | 0
168 | -27 -26
169 | 0
170 | -27 -26 -24
171 | 0
172 | 27 26 -24
173 | 0
174 | -27 26 24
175 | 0
176 | 27 -26 24
177 | 0
178 | -28 26
179 | 0
180 | -29 -28
181 | 0
182 | -29 -28 -26
183 | 0
184 | 29 28 -26
185 | 0
186 | -29 28 26
187 | 0
188 | 29 -28 26
189 | 0
190 | 28 -30
191 | 0
192 | -31 -30
193 | 0
194 | -31 -28 -30
195 | 0
196 | 31 -28 30
197 | 0
198 | -31 28 30
199 | 0
200 | 31 28 -30
201 | 0
202 | -33 -32 -3
203 | 0
204 | 33 32 -3
205 | 0
206 | -33 32 3
207 | 0
208 | 33 -32 3
209 | 0
210 | -35 -34 -32
211 | 0
212 | 35 34 -32
213 | 0
214 | -35 34 32
215 | 0
216 | 35 -34 32
217 | 0
218 | -37 -36 -34
219 | 0
220 | 37 36 -34
221 | 0
222 | -37 36 34
223 | 0
224 | 37 -36 34
225 | 0
226 | -38 -36 -27
227 | 0
228 | 38 -36 27
229 | 0
230 | 38 36 -27
231 | 0
232 | -38 36 27
233 | 0
234 | -40 -38 39
235 | 0
236 | 40 -38 -39
237 | 0
238 | -40 38 -39
239 | 0
240 | 40 38 39
241 | 0
242 | -37 -41 -5
243 | 0
244 | 37 41 -5
245 | 0
246 | -37 41 5
247 | 0
248 | 37 -41 5
249 | 0
250 | -43 -42 -41
251 | 0
252 | 43 42 -41
253 | 0
254 | -43 42 41
255 | 0
256 | 43 -42 41
257 | 0
258 | -44 -42 -27
259 | 0
260 | 44 -42 27
261 | 0
262 | 44 42 -27
263 | 0
264 | -44 42 27
265 | 0
266 | -40 -44 39
267 | 0
268 | 40 -44 -39
269 | 0
270 | -40 44 -39
271 | 0
272 | 40 44 39
273 | 0
274 | -33 -45 -7
275 | 0
276 | 33 45 -7
277 | 0
278 | -33 45 7
279 | 0
280 | 33 -45 7
281 | 0
282 | -47 -46 -45
283 | 0
284 | 47 46 -45
285 | 0
286 | -47 46 45
287 | 0
288 | 47 -46 45
289 | 0
290 | -35 -46 40
291 | 0
292 | 35 -46 -40
293 | 0
294 | -35 46 -40
295 | 0
296 | 35 46 40
297 | 0
298 | -37 -48 -9
299 | 0
300 | 37 48 -9
301 | 0
302 | -37 48 9
303 | 0
304 | 37 -48 9
305 | 0
306 | -49 -48 -27
307 | 0
308 | 49 -48 27
309 | 0
310 | 49 48 -27
311 | 0
312 | -49 48 27
313 | 0
314 | -40 -49 39
315 | 0
316 | 40 -49 -39
317 | 0
318 | -40 49 -39
319 | 0
320 | 40 49 39
321 | 0
322 | -35 -50 -11
323 | 0
324 | 35 50 -11
325 | 0
326 | -35 50 11
327 | 0
328 | 35 -50 11
329 | 0
330 | -37 -51 -50
331 | 0
332 | 37 51 -50
333 | 0
334 | -37 51 50
335 | 0
336 | 37 -51 50
337 | 0
338 | -43 -52 -51
339 | 0
340 | 43 52 -51
341 | 0
342 | -43 52 51
343 | 0
344 | 43 -52 51
345 | 0
346 | -52 -27 39
347 | 0
348 | -52 27 -39
349 | 0
350 | 52 -27 -39
351 | 0
352 | 52 27 39
353 | 0
354 | -47 -53 -13
355 | 0
356 | 47 53 -13
357 | 0
358 | -47 53 13
359 | 0
360 | 47 -53 13
361 | 0
362 | -43 -54 -53
363 | 0
364 | 43 54 -53
365 | 0
366 | -43 54 53
367 | 0
368 | 43 -54 53
369 | 0
370 | -54 -40 -27
371 | 0
372 | -54 40 27
373 | 0
374 | 54 40 -27
375 | 0
376 | 54 -40 27
377 | 0
378 | -47 -55 -15
379 | 0
380 | 47 55 -15
381 | 0
382 | -47 55 15
383 | 0
384 | 47 -55 15
385 | 0
386 | -35 -56 -55
387 | 0
388 | 35 56 -55
389 | 0
390 | -35 56 55
391 | 0
392 | 35 -56 55
393 | 0
394 | -37 -57 -56
395 | 0
396 | 37 57 -56
397 | 0
398 | -37 57 56
399 | 0
400 | 37 -57 56
401 | 0
402 | -43 -58 -57
403 | 0
404 | 43 58 -57
405 | 0
406 | -43 58 57
407 | 0
408 | 43 -58 57
409 | 0
410 | -58 -40 -27
411 | 0
412 | -58 40 27
413 | 0
414 | 58 40 -27
415 | 0
416 | 58 -40 27
417 | 0
418 | -33 -59 -17
419 | 0
420 | 33 59 -17
421 | 0
422 | -33 59 17
423 | 0
424 | 33 -59 17
425 | 0
426 | -35 -59 43
427 | 0
428 | 35 -59 -43
429 | 0
430 | -35 59 -43
431 | 0
432 | 35 59 43
433 | 0
434 | -33 -60 -19
435 | 0
436 | 33 60 -19
437 | 0
438 | -33 60 19
439 | 0
440 | 33 -60 19
441 | 0
442 | -35 -61 -60
443 | 0
444 | 35 61 -60
445 | 0
446 | -35 61 60
447 | 0
448 | 35 -61 60
449 | 0
450 | -37 -62 -61
451 | 0
452 | 37 62 -61
453 | 0
454 | -37 62 61
455 | 0
456 | 37 -62 61
457 | 0
458 | -43 -62 -27
459 | 0
460 | 43 -62 27
461 | 0
462 | -43 62 27
463 | 0
464 | 43 62 -27
465 | 0
466 | -33 -63 -21
467 | 0
468 | 33 63 -21
469 | 0
470 | -33 63 21
471 | 0
472 | 33 -63 21
473 | 0
474 | -47 -64 -63
475 | 0
476 | 47 64 -63
477 | 0
478 | -47 64 63
479 | 0
480 | 47 -64 63
481 | 0
482 | -35 -65 -64
483 | 0
484 | 35 65 -64
485 | 0
486 | -35 65 64
487 | 0
488 | 35 -65 64
489 | 0
490 | -37 -66 -65
491 | 0
492 | 37 66 -65
493 | 0
494 | -37 66 65
495 | 0
496 | 37 -66 65
497 | 0
498 | -39 -66 -27
499 | 0
500 | 39 -66 27
501 | 0
502 | 39 66 -27
503 | 0
504 | -39 66 27
505 | 0
506 | -35 -67 -23
507 | 0
508 | 35 67 -23
509 | 0
510 | -35 67 23
511 | 0
512 | 35 -67 23
513 | 0
514 | -37 -67 -27
515 | 0
516 | 37 -67 27
517 | 0
518 | -37 67 27
519 | 0
520 | 37 67 -27
521 | 0
522 | -35 -68 -25
523 | 0
524 | 35 68 -25
525 | 0
526 | -35 68 25
527 | 0
528 | 35 -68 25
529 | 0
530 | -43 -69 -68
531 | 0
532 | 43 69 -68
533 | 0
534 | -43 69 68
535 | 0
536 | 43 -69 68
537 | 0
538 | -40 -69 39
539 | 0
540 | 40 -69 -39
541 | 0
542 | -40 69 -39
543 | 0
544 | 40 69 39
545 | 0
546 | -47 -70 -29
547 | 0
548 | 47 70 -29
549 | 0
550 | -47 70 29
551 | 0
552 | 47 -70 29
553 | 0
554 | -35 -71 -70
555 | 0
556 | 35 71 -70
557 | 0
558 | -35 71 70
559 | 0
560 | 35 -71 70
561 | 0
562 | -43 -71 40
563 | 0
564 | 43 -71 -40
565 | 0
566 | -43 71 -40
567 | 0
568 | 43 71 40
569 | 0
570 | -47 -72 -31
571 | 0
572 | 47 72 -31
573 | 0
574 | -47 72 31
575 | 0
576 | 47 -72 31
577 | 0
578 | -37 -72 39
579 | 0
580 | 37 -72 -39
581 | 0
582 | -37 72 -39
583 | 0
584 | 37 72 39
585 | 0
586 | -47 -73 -30
587 | 0
588 | 47 73 -30
589 | 0
590 | -47 73 30
591 | 0
592 | 47 -73 30
593 | 0
594 | -35 -74 -73
595 | 0
596 | 35 74 -73
597 | 0
598 | -35 74 73
599 | 0
600 | 35 -74 73
601 | 0
602 | -37 -75 -74
603 | 0
604 | 37 75 -74
605 | 0
606 | -37 75 74
607 | 0
608 | 37 -75 74
609 | 0
610 | -43 -75 -39
611 | 0
612 | 43 -75 39
613 | 0
614 | -43 75 39
615 | 0
616 | 43 75 -39
617 | 0
618 |
619 |
--------------------------------------------------------------------------------
/data/dimacs/parity/par8-4-c.cnf:
--------------------------------------------------------------------------------
1 | c FILE: par8-4-c.cnf
2 | c
3 | c SOURCE: James Crawford (jc@research.att.com)
4 | c
5 | c DESCRIPTION: Instance arises from the problem of learning the parity
6 | c function.
7 | c
8 | c parxx-y denotes a parity problem on xx bits. y is simply the
9 | c intance number.
10 | c
11 | c parxx-y-c denotes an instance identical to parxx-y except that
12 | c the instances have been simplified (to create an equivalent
13 | c problem).
14 | c
15 | c NOTE: Satisfiable (checked for 8 and 16 size instances. All
16 | c instances are satisfiable by construction)
17 | c
18 | c NOTE: Number of clauses corrected August 3, 1993
19 | c
20 | c Converted from tableau format Tue Aug 3 09:55:40 EDT 1993
21 | p cnf 67 266
22 | -2 1
23 | 0
24 | -3 -2
25 | 0
26 | -3 -2 -1
27 | 0
28 | 3 2 -1
29 | 0
30 | -3 2 1
31 | 0
32 | 3 -2 1
33 | 0
34 | -4 2
35 | 0
36 | -5 -4
37 | 0
38 | -5 -4 -2
39 | 0
40 | 5 4 -2
41 | 0
42 | -5 4 2
43 | 0
44 | 5 -4 2
45 | 0
46 | -6 4
47 | 0
48 | -7 -6
49 | 0
50 | -7 -6 -4
51 | 0
52 | 7 6 -4
53 | 0
54 | -7 6 4
55 | 0
56 | 7 -6 4
57 | 0
58 | -8 6
59 | 0
60 | -9 -8
61 | 0
62 | -9 -8 -6
63 | 0
64 | 9 8 -6
65 | 0
66 | -9 8 6
67 | 0
68 | 9 -8 6
69 | 0
70 | -10 8
71 | 0
72 | -11 -10
73 | 0
74 | -11 -10 -8
75 | 0
76 | 11 10 -8
77 | 0
78 | -11 10 8
79 | 0
80 | 11 -10 8
81 | 0
82 | -12 10
83 | 0
84 | -13 -12
85 | 0
86 | -13 -12 -10
87 | 0
88 | 13 12 -10
89 | 0
90 | -13 12 10
91 | 0
92 | 13 -12 10
93 | 0
94 | -14 12
95 | 0
96 | -15 -14
97 | 0
98 | -15 -14 -12
99 | 0
100 | 15 14 -12
101 | 0
102 | -15 14 12
103 | 0
104 | 15 -14 12
105 | 0
106 | -16 14
107 | 0
108 | -17 -16
109 | 0
110 | -17 -16 -14
111 | 0
112 | 17 16 -14
113 | 0
114 | -17 16 14
115 | 0
116 | 17 -16 14
117 | 0
118 | -18 16
119 | 0
120 | -19 -18
121 | 0
122 | -19 -18 -16
123 | 0
124 | 19 18 -16
125 | 0
126 | -19 18 16
127 | 0
128 | 19 -18 16
129 | 0
130 | -20 18
131 | 0
132 | -21 -20
133 | 0
134 | -21 -20 -18
135 | 0
136 | 21 20 -18
137 | 0
138 | -21 20 18
139 | 0
140 | 21 -20 18
141 | 0
142 | -22 20
143 | 0
144 | -23 -22
145 | 0
146 | -23 -22 -20
147 | 0
148 | 23 22 -20
149 | 0
150 | -23 22 20
151 | 0
152 | 23 -22 20
153 | 0
154 | -24 22
155 | 0
156 | -25 -24
157 | 0
158 | -25 -24 -22
159 | 0
160 | 25 24 -22
161 | 0
162 | -25 24 22
163 | 0
164 | 25 -24 22
165 | 0
166 | -26 24
167 | 0
168 | -27 -26
169 | 0
170 | -27 -26 -24
171 | 0
172 | 27 26 -24
173 | 0
174 | -27 26 24
175 | 0
176 | 27 -26 24
177 | 0
178 | -28 26
179 | 0
180 | -29 -28
181 | 0
182 | -29 -28 -26
183 | 0
184 | 29 28 -26
185 | 0
186 | -29 28 26
187 | 0
188 | 29 -28 26
189 | 0
190 | 28 -30
191 | 0
192 | -31 -30
193 | 0
194 | -31 -28 -30
195 | 0
196 | 31 -28 30
197 | 0
198 | -31 28 30
199 | 0
200 | 31 28 -30
201 | 0
202 | -33 -32 -3
203 | 0
204 | 33 32 -3
205 | 0
206 | -33 32 3
207 | 0
208 | 33 -32 3
209 | 0
210 | -35 -34 -32
211 | 0
212 | 35 34 -32
213 | 0
214 | -35 34 32
215 | 0
216 | 35 -34 32
217 | 0
218 | -37 -36 -34
219 | 0
220 | 37 36 -34
221 | 0
222 | -37 36 34
223 | 0
224 | 37 -36 34
225 | 0
226 | -35 -38 -5
227 | 0
228 | 35 38 -5
229 | 0
230 | -35 38 5
231 | 0
232 | 35 -38 5
233 | 0
234 | -40 -39 -38
235 | 0
236 | 40 39 -38
237 | 0
238 | -40 39 38
239 | 0
240 | 40 -39 38
241 | 0
242 | -35 -41 -7
243 | 0
244 | 35 41 -7
245 | 0
246 | -35 41 7
247 | 0
248 | 35 -41 7
249 | 0
250 | -37 -42 -41
251 | 0
252 | 37 42 -41
253 | 0
254 | -37 42 41
255 | 0
256 | 37 -42 41
257 | 0
258 | -33 -42 -9
259 | 0
260 | 33 42 -9
261 | 0
262 | -33 42 9
263 | 0
264 | 33 -42 9
265 | 0
266 | -43 -11 42
267 | 0
268 | 43 -11 -42
269 | 0
270 | -43 11 -42
271 | 0
272 | 43 11 42
273 | 0
274 | -33 -44 -13
275 | 0
276 | 33 44 -13
277 | 0
278 | -33 44 13
279 | 0
280 | 33 -44 13
281 | 0
282 | -35 -45 -44
283 | 0
284 | 35 45 -44
285 | 0
286 | -35 45 44
287 | 0
288 | 35 -45 44
289 | 0
290 | -43 -46 -45
291 | 0
292 | 43 46 -45
293 | 0
294 | -43 46 45
295 | 0
296 | 43 -46 45
297 | 0
298 | -39 -36 -46
299 | 0
300 | 39 36 -46
301 | 0
302 | -39 36 46
303 | 0
304 | 39 -36 46
305 | 0
306 | -33 -47 -15
307 | 0
308 | 33 47 -15
309 | 0
310 | -33 47 15
311 | 0
312 | 33 -47 15
313 | 0
314 | -43 -42 -47
315 | 0
316 | 43 42 -47
317 | 0
318 | -43 42 47
319 | 0
320 | 43 -42 47
321 | 0
322 | -33 -48 -17
323 | 0
324 | 33 48 -17
325 | 0
326 | -33 48 17
327 | 0
328 | 33 -48 17
329 | 0
330 | -35 -49 -48
331 | 0
332 | 35 49 -48
333 | 0
334 | -35 49 48
335 | 0
336 | 35 -49 48
337 | 0
338 | -43 -50 -49
339 | 0
340 | 43 50 -49
341 | 0
342 | -43 50 49
343 | 0
344 | 43 -50 49
345 | 0
346 | -40 -51 -50
347 | 0
348 | 40 51 -50
349 | 0
350 | -40 51 50
351 | 0
352 | 40 -51 50
353 | 0
354 | -39 -51 36
355 | 0
356 | 39 -51 -36
357 | 0
358 | -39 51 -36
359 | 0
360 | 39 51 36
361 | 0
362 | -43 -52 -19
363 | 0
364 | 43 52 -19
365 | 0
366 | -43 52 19
367 | 0
368 | 43 -52 19
369 | 0
370 | -40 -52 39
371 | 0
372 | 40 -52 -39
373 | 0
374 | -40 52 -39
375 | 0
376 | 40 52 39
377 | 0
378 | -35 -53 -21
379 | 0
380 | 35 53 -21
381 | 0
382 | -35 53 21
383 | 0
384 | 35 -53 21
385 | 0
386 | -43 -54 -53
387 | 0
388 | 43 54 -53
389 | 0
390 | -43 54 53
391 | 0
392 | 43 -54 53
393 | 0
394 | -40 -55 -54
395 | 0
396 | 40 55 -54
397 | 0
398 | -40 55 54
399 | 0
400 | 40 -55 54
401 | 0
402 | -42 -55 36
403 | 0
404 | 42 -55 -36
405 | 0
406 | -42 55 -36
407 | 0
408 | 42 55 36
409 | 0
410 | -35 -56 -23
411 | 0
412 | 35 56 -23
413 | 0
414 | -35 56 23
415 | 0
416 | 35 -56 23
417 | 0
418 | -43 -56 -42
419 | 0
420 | 43 -56 42
421 | 0
422 | -43 56 42
423 | 0
424 | 43 56 -42
425 | 0
426 | -35 -57 -25
427 | 0
428 | 35 57 -25
429 | 0
430 | -35 57 25
431 | 0
432 | 35 -57 25
433 | 0
434 | -43 -58 -57
435 | 0
436 | 43 58 -57
437 | 0
438 | -43 58 57
439 | 0
440 | 43 -58 57
441 | 0
442 | -37 -42 -58
443 | 0
444 | 37 42 -58
445 | 0
446 | -37 42 58
447 | 0
448 | 37 -42 58
449 | 0
450 | -33 -59 -27
451 | 0
452 | 33 59 -27
453 | 0
454 | -33 59 27
455 | 0
456 | 33 -59 27
457 | 0
458 | -39 -59 42
459 | 0
460 | 39 -59 -42
461 | 0
462 | -39 59 -42
463 | 0
464 | 39 59 42
465 | 0
466 | -43 -60 -29
467 | 0
468 | 43 60 -29
469 | 0
470 | -43 60 29
471 | 0
472 | 43 -60 29
473 | 0
474 | -40 -60 36
475 | 0
476 | 40 -60 -36
477 | 0
478 | -40 60 -36
479 | 0
480 | 40 60 36
481 | 0
482 | -33 -61 -31
483 | 0
484 | 33 61 -31
485 | 0
486 | -33 61 31
487 | 0
488 | 33 -61 31
489 | 0
490 | -43 -62 -61
491 | 0
492 | 43 62 -61
493 | 0
494 | -43 62 61
495 | 0
496 | 43 -62 61
497 | 0
498 | -39 -63 -62
499 | 0
500 | 39 63 -62
501 | 0
502 | -39 63 62
503 | 0
504 | 39 -63 62
505 | 0
506 | -37 -64 -63
507 | 0
508 | 37 64 -63
509 | 0
510 | -37 64 63
511 | 0
512 | 37 -64 63
513 | 0
514 | -42 -64 -36
515 | 0
516 | 42 -64 36
517 | 0
518 | -42 64 36
519 | 0
520 | 42 64 -36
521 | 0
522 | -33 -65 -30
523 | 0
524 | 33 65 -30
525 | 0
526 | -33 65 30
527 | 0
528 | 33 -65 30
529 | 0
530 | -35 -66 -65
531 | 0
532 | 35 66 -65
533 | 0
534 | -35 66 65
535 | 0
536 | 35 -66 65
537 | 0
538 | -43 -67 -66
539 | 0
540 | 43 67 -66
541 | 0
542 | -43 67 66
543 | 0
544 | 43 -67 66
545 | 0
546 | -39 -37 -67
547 | 0
548 | 39 37 -67
549 | 0
550 | -39 37 67
551 | 0
552 | 39 -37 67
553 | 0
554 |
555 |
--------------------------------------------------------------------------------
/data/dimacs/parity/par8-5-c.cnf:
--------------------------------------------------------------------------------
1 | c FILE: par8-5-c.cnf
2 | c
3 | c SOURCE: James Crawford (jc@research.att.com)
4 | c
5 | c DESCRIPTION: Instance arises from the problem of learning the parity
6 | c function.
7 | c
8 | c parxx-y denotes a parity problem on xx bits. y is simply the
9 | c intance number.
10 | c
11 | c parxx-y-c denotes an instance identical to parxx-y except that
12 | c the instances have been simplified (to create an equivalent
13 | c problem).
14 | c
15 | c NOTE: Satisfiable (checked for 8 and 16 size instances. All
16 | c instances are satisfiable by construction)
17 | c
18 | c NOTE: Number of clauses corrected August 3, 1993
19 | c
20 | c Converted from tableau format Tue Aug 3 09:55:47 EDT 1993
21 | p cnf 75 298
22 | -2 1
23 | 0
24 | -3 -2
25 | 0
26 | -3 -2 -1
27 | 0
28 | 3 2 -1
29 | 0
30 | -3 2 1
31 | 0
32 | 3 -2 1
33 | 0
34 | -4 2
35 | 0
36 | -5 -4
37 | 0
38 | -5 -4 -2
39 | 0
40 | 5 4 -2
41 | 0
42 | -5 4 2
43 | 0
44 | 5 -4 2
45 | 0
46 | -6 4
47 | 0
48 | -7 -6
49 | 0
50 | -7 -6 -4
51 | 0
52 | 7 6 -4
53 | 0
54 | -7 6 4
55 | 0
56 | 7 -6 4
57 | 0
58 | -8 6
59 | 0
60 | -9 -8
61 | 0
62 | -9 -8 -6
63 | 0
64 | 9 8 -6
65 | 0
66 | -9 8 6
67 | 0
68 | 9 -8 6
69 | 0
70 | -10 8
71 | 0
72 | -11 -10
73 | 0
74 | -11 -10 -8
75 | 0
76 | 11 10 -8
77 | 0
78 | -11 10 8
79 | 0
80 | 11 -10 8
81 | 0
82 | -12 10
83 | 0
84 | -13 -12
85 | 0
86 | -13 -12 -10
87 | 0
88 | 13 12 -10
89 | 0
90 | -13 12 10
91 | 0
92 | 13 -12 10
93 | 0
94 | -14 12
95 | 0
96 | -15 -14
97 | 0
98 | -15 -14 -12
99 | 0
100 | 15 14 -12
101 | 0
102 | -15 14 12
103 | 0
104 | 15 -14 12
105 | 0
106 | -16 14
107 | 0
108 | -17 -16
109 | 0
110 | -17 -16 -14
111 | 0
112 | 17 16 -14
113 | 0
114 | -17 16 14
115 | 0
116 | 17 -16 14
117 | 0
118 | -18 16
119 | 0
120 | -19 -18
121 | 0
122 | -19 -18 -16
123 | 0
124 | 19 18 -16
125 | 0
126 | -19 18 16
127 | 0
128 | 19 -18 16
129 | 0
130 | -20 18
131 | 0
132 | -21 -20
133 | 0
134 | -21 -20 -18
135 | 0
136 | 21 20 -18
137 | 0
138 | -21 20 18
139 | 0
140 | 21 -20 18
141 | 0
142 | -22 20
143 | 0
144 | -23 -22
145 | 0
146 | -23 -22 -20
147 | 0
148 | 23 22 -20
149 | 0
150 | -23 22 20
151 | 0
152 | 23 -22 20
153 | 0
154 | -24 22
155 | 0
156 | -25 -24
157 | 0
158 | -25 -24 -22
159 | 0
160 | 25 24 -22
161 | 0
162 | -25 24 22
163 | 0
164 | 25 -24 22
165 | 0
166 | -26 24
167 | 0
168 | -27 -26
169 | 0
170 | -27 -26 -24
171 | 0
172 | 27 26 -24
173 | 0
174 | -27 26 24
175 | 0
176 | 27 -26 24
177 | 0
178 | -28 26
179 | 0
180 | -29 -28
181 | 0
182 | -29 -28 -26
183 | 0
184 | 29 28 -26
185 | 0
186 | -29 28 26
187 | 0
188 | 29 -28 26
189 | 0
190 | 28 -30
191 | 0
192 | -31 -30
193 | 0
194 | -31 -28 -30
195 | 0
196 | 31 -28 30
197 | 0
198 | -31 28 30
199 | 0
200 | 31 28 -30
201 | 0
202 | -33 -32 -3
203 | 0
204 | 33 32 -3
205 | 0
206 | -33 32 3
207 | 0
208 | 33 -32 3
209 | 0
210 | -34 -32 -29
211 | 0
212 | 34 -32 29
213 | 0
214 | 34 32 -29
215 | 0
216 | -34 32 29
217 | 0
218 | -36 -34 -35
219 | 0
220 | 36 -34 35
221 | 0
222 | -36 34 35
223 | 0
224 | 36 34 -35
225 | 0
226 | -38 -37 -5
227 | 0
228 | 38 37 -5
229 | 0
230 | -38 37 5
231 | 0
232 | 38 -37 5
233 | 0
234 | -40 -39 -37
235 | 0
236 | 40 39 -37
237 | 0
238 | -40 39 37
239 | 0
240 | 40 -39 37
241 | 0
242 | -42 -41 -39
243 | 0
244 | 42 41 -39
245 | 0
246 | -42 41 39
247 | 0
248 | 42 -41 39
249 | 0
250 | -33 -43 -41
251 | 0
252 | 33 43 -41
253 | 0
254 | -33 43 41
255 | 0
256 | 33 -43 41
257 | 0
258 | -43 -29 36
259 | 0
260 | -43 29 -36
261 | 0
262 | 43 -29 -36
263 | 0
264 | 43 29 36
265 | 0
266 | -38 -44 -7
267 | 0
268 | 38 44 -7
269 | 0
270 | -38 44 7
271 | 0
272 | 38 -44 7
273 | 0
274 | -46 -45 -44
275 | 0
276 | 46 45 -44
277 | 0
278 | -46 45 44
279 | 0
280 | 46 -45 44
281 | 0
282 | -40 -45 29
283 | 0
284 | 40 -45 -29
285 | 0
286 | -40 45 -29
287 | 0
288 | 40 45 29
289 | 0
290 | -38 -47 -9
291 | 0
292 | 38 47 -9
293 | 0
294 | -38 47 9
295 | 0
296 | 38 -47 9
297 | 0
298 | -46 -48 -47
299 | 0
300 | 46 48 -47
301 | 0
302 | -46 48 47
303 | 0
304 | 46 -48 47
305 | 0
306 | -40 -49 -48
307 | 0
308 | 40 49 -48
309 | 0
310 | -40 49 48
311 | 0
312 | 40 -49 48
313 | 0
314 | -42 -50 -49
315 | 0
316 | 42 50 -49
317 | 0
318 | -42 50 49
319 | 0
320 | 42 -50 49
321 | 0
322 | -33 -51 -50
323 | 0
324 | 33 51 -50
325 | 0
326 | -33 51 50
327 | 0
328 | 33 -51 50
329 | 0
330 | -51 -36 -29
331 | 0
332 | -51 36 29
333 | 0
334 | 51 36 -29
335 | 0
336 | 51 -36 29
337 | 0
338 | -38 -52 -11
339 | 0
340 | 38 52 -11
341 | 0
342 | -38 52 11
343 | 0
344 | 38 -52 11
345 | 0
346 | -46 -53 -52
347 | 0
348 | 46 53 -52
349 | 0
350 | -46 53 52
351 | 0
352 | 46 -53 52
353 | 0
354 | -33 -54 -53
355 | 0
356 | 33 54 -53
357 | 0
358 | -33 54 53
359 | 0
360 | 33 -54 53
361 | 0
362 | -54 -29 35
363 | 0
364 | -54 29 -35
365 | 0
366 | 54 -29 -35
367 | 0
368 | 54 29 35
369 | 0
370 | -38 -55 -13
371 | 0
372 | 38 55 -13
373 | 0
374 | -38 55 13
375 | 0
376 | 38 -55 13
377 | 0
378 | -46 -56 -55
379 | 0
380 | 46 56 -55
381 | 0
382 | -46 56 55
383 | 0
384 | 46 -56 55
385 | 0
386 | -40 -57 -56
387 | 0
388 | 40 57 -56
389 | 0
390 | -40 57 56
391 | 0
392 | 40 -57 56
393 | 0
394 | -42 -58 -57
395 | 0
396 | 42 58 -57
397 | 0
398 | -42 58 57
399 | 0
400 | 42 -58 57
401 | 0
402 | -35 -58 -29
403 | 0
404 | 35 -58 29
405 | 0
406 | 35 58 -29
407 | 0
408 | -35 58 29
409 | 0
410 | -46 -59 -15
411 | 0
412 | 46 59 -15
413 | 0
414 | -46 59 15
415 | 0
416 | 46 -59 15
417 | 0
418 | -40 -60 -59
419 | 0
420 | 40 60 -59
421 | 0
422 | -40 60 59
423 | 0
424 | 40 -60 59
425 | 0
426 | -61 -60 -29
427 | 0
428 | 61 -60 29
429 | 0
430 | 61 60 -29
431 | 0
432 | -61 60 29
433 | 0
434 | -36 -61 35
435 | 0
436 | 36 -61 -35
437 | 0
438 | -36 61 -35
439 | 0
440 | 36 61 35
441 | 0
442 | -46 -62 -17
443 | 0
444 | 46 62 -17
445 | 0
446 | -46 62 17
447 | 0
448 | 46 -62 17
449 | 0
450 | -40 -63 -62
451 | 0
452 | 40 63 -62
453 | 0
454 | -40 63 62
455 | 0
456 | 40 -63 62
457 | 0
458 | -64 -63 -29
459 | 0
460 | 64 -63 29
461 | 0
462 | 64 63 -29
463 | 0
464 | -64 63 29
465 | 0
466 | -36 -64 35
467 | 0
468 | 36 -64 -35
469 | 0
470 | -36 64 -35
471 | 0
472 | 36 64 35
473 | 0
474 | -38 -65 -19
475 | 0
476 | 38 65 -19
477 | 0
478 | -38 65 19
479 | 0
480 | 38 -65 19
481 | 0
482 | -42 -65 35
483 | 0
484 | 42 -65 -35
485 | 0
486 | -42 65 -35
487 | 0
488 | 42 65 35
489 | 0
490 | -38 -66 -21
491 | 0
492 | 38 66 -21
493 | 0
494 | -38 66 21
495 | 0
496 | 38 -66 21
497 | 0
498 | -46 -66 29
499 | 0
500 | 46 -66 -29
501 | 0
502 | -46 66 -29
503 | 0
504 | 46 66 29
505 | 0
506 | -46 -67 -23
507 | 0
508 | 46 67 -23
509 | 0
510 | -46 67 23
511 | 0
512 | 46 -67 23
513 | 0
514 | -42 -68 -67
515 | 0
516 | 42 68 -67
517 | 0
518 | -42 68 67
519 | 0
520 | 42 -68 67
521 | 0
522 | -35 -68 -29
523 | 0
524 | 35 -68 29
525 | 0
526 | 35 68 -29
527 | 0
528 | -35 68 29
529 | 0
530 | -35 -25 -29
531 | 0
532 | 35 -25 29
533 | 0
534 | 35 25 -29
535 | 0
536 | -35 25 29
537 | 0
538 | -38 -69 -27
539 | 0
540 | 38 69 -27
541 | 0
542 | -38 69 27
543 | 0
544 | 38 -69 27
545 | 0
546 | -46 -70 -69
547 | 0
548 | 46 70 -69
549 | 0
550 | -46 70 69
551 | 0
552 | 46 -70 69
553 | 0
554 | -42 -71 -70
555 | 0
556 | 42 71 -70
557 | 0
558 | -42 71 70
559 | 0
560 | 42 -71 70
561 | 0
562 | -72 -71 -29
563 | 0
564 | 72 -71 29
565 | 0
566 | 72 71 -29
567 | 0
568 | -72 71 29
569 | 0
570 | -36 -72 -35
571 | 0
572 | 36 -72 35
573 | 0
574 | -36 72 35
575 | 0
576 | 36 72 -35
577 | 0
578 | -40 -42 -31
579 | 0
580 | 40 42 -31
581 | 0
582 | -40 42 31
583 | 0
584 | 40 -42 31
585 | 0
586 | -40 -73 -30
587 | 0
588 | 40 73 -30
589 | 0
590 | -40 73 30
591 | 0
592 | 40 -73 30
593 | 0
594 | -42 -74 -73
595 | 0
596 | 42 74 -73
597 | 0
598 | -42 74 73
599 | 0
600 | 42 -74 73
601 | 0
602 | -33 -75 -74
603 | 0
604 | 33 75 -74
605 | 0
606 | -33 75 74
607 | 0
608 | 33 -75 74
609 | 0
610 | -75 -29 35
611 | 0
612 | -75 29 -35
613 | 0
614 | 75 -29 -35
615 | 0
616 | 75 29 35
617 | 0
618 |
619 |
--------------------------------------------------------------------------------
/data/dimacs/phole/descr.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | SATLIB - Benchmark Problems
4 |
5 |
6 |
7 |
8 |
9 | SAT instances of the Pigeon Hole Problem
10 |
11 |
12 | The Pigeon Hole problem asks whether it is possible to place
13 | n+1 pigeons in n holes without two pigeons being in the
14 | same hole (obviously, it's not possible).
15 |
16 | SAT encoding
17 |
18 | The SAT encoding of this problem is very straightforward. For each
19 | pigeon i we have a variable x_{ij} which means that
20 | pigeon i is placed in hole j. Then we have n+1
21 | clauses which say that a pigeon has to be placed in some hole. Then
22 | for each hole we have a set of clauses ensuring that only one single
23 | pigeon is placed into that hole. This encoding leads to in total
24 | n * (n+1) propositional variables and to (n+1) +
25 | n * (n * (n+1) / 2) clauses.
26 |
27 | Benchmark instances
28 |
29 | There are five instances available at the DIMACS benchmark set which
30 | encode the pigeon hole problem for six to ten holes; details on the
31 | instances are given in Table 1.
32 |
33 |
34 | instance |
35 |
36 | holes |
37 |
38 | vars |
39 |
40 | clauses |
41 |
42 | satisfiable? |
43 |
44 |
45 |
46 | hole6.cnf |
47 |
48 | 6 |
49 |
50 | 42 |
51 |
52 | 133 |
53 |
54 | no |
55 |
56 |
57 |
58 | hole7.cnf |
59 |
60 | 7 |
61 |
62 | 56 |
63 |
64 | 204 |
65 |
66 | no |
67 |
68 |
69 |
70 | hole8.cnf |
71 |
72 | 8 |
73 |
74 | 72 |
75 |
76 | 297 |
77 |
78 | no |
79 |
80 |
81 |
82 | hole9.cnf |
83 |
84 | 9 |
85 |
86 | 90 |
87 |
88 | 415 |
89 |
90 | no |
91 |
92 |
93 |
94 | hole10.cnf |
95 |
96 | 10 |
97 |
98 | 110 |
99 |
100 | 561 |
101 |
102 | no |
103 |
104 |
105 | Table 1: SAT-encodings of the pigeon hole problem
106 |
107 |
108 |
109 |
110 | Acknowledgements
111 |
112 | The instances have originally
113 | been contributed by John Hooker
115 | and are also contained in a collection of SAT instances at the
116 | Forschungsinstitut fü anwendungsorientierte Wissensverarbeitung in
117 | Ulm, Germany.
118 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/data/dimacs/phole/hole6.cnf:
--------------------------------------------------------------------------------
1 | c File: hole6.cnf
2 | c
3 | c SOURCE: John Hooker (jh38+@andrew.cmu.edu)
4 | c
5 | c DESCRIPTION: Pigeon hole problem of placing n (for file holen) pigeons
6 | c in n+1 holes without placing 2 pigeons in the same hole
7 | c
8 | c NOTE: Part of the collection at the Forschungsinstitut fuer
9 | c anwendungsorientierte Wissensverarbeitung in Ulm Germany.
10 | c
11 | c NOTE: Not satisfiable
12 | c
13 | p cnf 42 133
14 | -1 -7 0
15 | -1 -13 0
16 | -1 -19 0
17 | -1 -25 0
18 | -1 -31 0
19 | -1 -37 0
20 | -7 -13 0
21 | -7 -19 0
22 | -7 -25 0
23 | -7 -31 0
24 | -7 -37 0
25 | -13 -19 0
26 | -13 -25 0
27 | -13 -31 0
28 | -13 -37 0
29 | -19 -25 0
30 | -19 -31 0
31 | -19 -37 0
32 | -25 -31 0
33 | -25 -37 0
34 | -31 -37 0
35 | -2 -8 0
36 | -2 -14 0
37 | -2 -20 0
38 | -2 -26 0
39 | -2 -32 0
40 | -2 -38 0
41 | -8 -14 0
42 | -8 -20 0
43 | -8 -26 0
44 | -8 -32 0
45 | -8 -38 0
46 | -14 -20 0
47 | -14 -26 0
48 | -14 -32 0
49 | -14 -38 0
50 | -20 -26 0
51 | -20 -32 0
52 | -20 -38 0
53 | -26 -32 0
54 | -26 -38 0
55 | -32 -38 0
56 | -3 -9 0
57 | -3 -15 0
58 | -3 -21 0
59 | -3 -27 0
60 | -3 -33 0
61 | -3 -39 0
62 | -9 -15 0
63 | -9 -21 0
64 | -9 -27 0
65 | -9 -33 0
66 | -9 -39 0
67 | -15 -21 0
68 | -15 -27 0
69 | -15 -33 0
70 | -15 -39 0
71 | -21 -27 0
72 | -21 -33 0
73 | -21 -39 0
74 | -27 -33 0
75 | -27 -39 0
76 | -33 -39 0
77 | -4 -10 0
78 | -4 -16 0
79 | -4 -22 0
80 | -4 -28 0
81 | -4 -34 0
82 | -4 -40 0
83 | -10 -16 0
84 | -10 -22 0
85 | -10 -28 0
86 | -10 -34 0
87 | -10 -40 0
88 | -16 -22 0
89 | -16 -28 0
90 | -16 -34 0
91 | -16 -40 0
92 | -22 -28 0
93 | -22 -34 0
94 | -22 -40 0
95 | -28 -34 0
96 | -28 -40 0
97 | -34 -40 0
98 | -5 -11 0
99 | -5 -17 0
100 | -5 -23 0
101 | -5 -29 0
102 | -5 -35 0
103 | -5 -41 0
104 | -11 -17 0
105 | -11 -23 0
106 | -11 -29 0
107 | -11 -35 0
108 | -11 -41 0
109 | -17 -23 0
110 | -17 -29 0
111 | -17 -35 0
112 | -17 -41 0
113 | -23 -29 0
114 | -23 -35 0
115 | -23 -41 0
116 | -29 -35 0
117 | -29 -41 0
118 | -35 -41 0
119 | -6 -12 0
120 | -6 -18 0
121 | -6 -24 0
122 | -6 -30 0
123 | -6 -36 0
124 | -6 -42 0
125 | -12 -18 0
126 | -12 -24 0
127 | -12 -30 0
128 | -12 -36 0
129 | -12 -42 0
130 | -18 -24 0
131 | -18 -30 0
132 | -18 -36 0
133 | -18 -42 0
134 | -24 -30 0
135 | -24 -36 0
136 | -24 -42 0
137 | -30 -36 0
138 | -30 -42 0
139 | -36 -42 0
140 | 6 5 4 3 2 1 0
141 | 12 11 10 9 8 7 0
142 | 18 17 16 15 14 13 0
143 | 24 23 22 21 20 19 0
144 | 30 29 28 27 26 25 0
145 | 36 35 34 33 32 31 0
146 | 42 41 40 39 38 37 0
147 |
--------------------------------------------------------------------------------
/data/dimacs/phole/hole7.cnf:
--------------------------------------------------------------------------------
1 | c File: hole7.cnf
2 | c
3 | c SOURCE: John Hooker (jh38+@andrew.cmu.edu)
4 | c
5 | c DESCRIPTION: Pigeon hole problem of placing n (for file holen) pigeons
6 | c in n+1 holes without placing 2 pigeons in the same hole
7 | c
8 | c NOTE: Part of the collection at the Forschungsinstitut fuer
9 | c anwendungsorientierte Wissensverarbeitung in Ulm Germany.
10 | c
11 | c NOTE: Not satisfiable
12 | c
13 | p cnf 56 204
14 | -1 -8 0
15 | -1 -15 0
16 | -1 -22 0
17 | -1 -29 0
18 | -1 -36 0
19 | -1 -43 0
20 | -1 -50 0
21 | -8 -15 0
22 | -8 -22 0
23 | -8 -29 0
24 | -8 -36 0
25 | -8 -43 0
26 | -8 -50 0
27 | -15 -22 0
28 | -15 -29 0
29 | -15 -36 0
30 | -15 -43 0
31 | -15 -50 0
32 | -22 -29 0
33 | -22 -36 0
34 | -22 -43 0
35 | -22 -50 0
36 | -29 -36 0
37 | -29 -43 0
38 | -29 -50 0
39 | -36 -43 0
40 | -36 -50 0
41 | -43 -50 0
42 | -2 -9 0
43 | -2 -16 0
44 | -2 -23 0
45 | -2 -30 0
46 | -2 -37 0
47 | -2 -44 0
48 | -2 -51 0
49 | -9 -16 0
50 | -9 -23 0
51 | -9 -30 0
52 | -9 -37 0
53 | -9 -44 0
54 | -9 -51 0
55 | -16 -23 0
56 | -16 -30 0
57 | -16 -37 0
58 | -16 -44 0
59 | -16 -51 0
60 | -23 -30 0
61 | -23 -37 0
62 | -23 -44 0
63 | -23 -51 0
64 | -30 -37 0
65 | -30 -44 0
66 | -30 -51 0
67 | -37 -44 0
68 | -37 -51 0
69 | -44 -51 0
70 | -3 -10 0
71 | -3 -17 0
72 | -3 -24 0
73 | -3 -31 0
74 | -3 -38 0
75 | -3 -45 0
76 | -3 -52 0
77 | -10 -17 0
78 | -10 -24 0
79 | -10 -31 0
80 | -10 -38 0
81 | -10 -45 0
82 | -10 -52 0
83 | -17 -24 0
84 | -17 -31 0
85 | -17 -38 0
86 | -17 -45 0
87 | -17 -52 0
88 | -24 -31 0
89 | -24 -38 0
90 | -24 -45 0
91 | -24 -52 0
92 | -31 -38 0
93 | -31 -45 0
94 | -31 -52 0
95 | -38 -45 0
96 | -38 -52 0
97 | -45 -52 0
98 | -4 -11 0
99 | -4 -18 0
100 | -4 -25 0
101 | -4 -32 0
102 | -4 -39 0
103 | -4 -46 0
104 | -4 -53 0
105 | -11 -18 0
106 | -11 -25 0
107 | -11 -32 0
108 | -11 -39 0
109 | -11 -46 0
110 | -11 -53 0
111 | -18 -25 0
112 | -18 -32 0
113 | -18 -39 0
114 | -18 -46 0
115 | -18 -53 0
116 | -25 -32 0
117 | -25 -39 0
118 | -25 -46 0
119 | -25 -53 0
120 | -32 -39 0
121 | -32 -46 0
122 | -32 -53 0
123 | -39 -46 0
124 | -39 -53 0
125 | -46 -53 0
126 | -5 -12 0
127 | -5 -19 0
128 | -5 -26 0
129 | -5 -33 0
130 | -5 -40 0
131 | -5 -47 0
132 | -5 -54 0
133 | -12 -19 0
134 | -12 -26 0
135 | -12 -33 0
136 | -12 -40 0
137 | -12 -47 0
138 | -12 -54 0
139 | -19 -26 0
140 | -19 -33 0
141 | -19 -40 0
142 | -19 -47 0
143 | -19 -54 0
144 | -26 -33 0
145 | -26 -40 0
146 | -26 -47 0
147 | -26 -54 0
148 | -33 -40 0
149 | -33 -47 0
150 | -33 -54 0
151 | -40 -47 0
152 | -40 -54 0
153 | -47 -54 0
154 | -6 -13 0
155 | -6 -20 0
156 | -6 -27 0
157 | -6 -34 0
158 | -6 -41 0
159 | -6 -48 0
160 | -6 -55 0
161 | -13 -20 0
162 | -13 -27 0
163 | -13 -34 0
164 | -13 -41 0
165 | -13 -48 0
166 | -13 -55 0
167 | -20 -27 0
168 | -20 -34 0
169 | -20 -41 0
170 | -20 -48 0
171 | -20 -55 0
172 | -27 -34 0
173 | -27 -41 0
174 | -27 -48 0
175 | -27 -55 0
176 | -34 -41 0
177 | -34 -48 0
178 | -34 -55 0
179 | -41 -48 0
180 | -41 -55 0
181 | -48 -55 0
182 | -7 -14 0
183 | -7 -21 0
184 | -7 -28 0
185 | -7 -35 0
186 | -7 -42 0
187 | -7 -49 0
188 | -7 -56 0
189 | -14 -21 0
190 | -14 -28 0
191 | -14 -35 0
192 | -14 -42 0
193 | -14 -49 0
194 | -14 -56 0
195 | -21 -28 0
196 | -21 -35 0
197 | -21 -42 0
198 | -21 -49 0
199 | -21 -56 0
200 | -28 -35 0
201 | -28 -42 0
202 | -28 -49 0
203 | -28 -56 0
204 | -35 -42 0
205 | -35 -49 0
206 | -35 -56 0
207 | -42 -49 0
208 | -42 -56 0
209 | -49 -56 0
210 | 7 6 5 4 3 2 1 0
211 | 14 13 12 11 10 9 8 0
212 | 21 20 19 18 17 16 15 0
213 | 28 27 26 25 24 23 22 0
214 | 35 34 33 32 31 30 29 0
215 | 42 41 40 39 38 37 36 0
216 | 49 48 47 46 45 44 43 0
217 | 56 55 54 53 52 51 50 0
218 |
--------------------------------------------------------------------------------
/data/dimacs/phole/hole8.cnf:
--------------------------------------------------------------------------------
1 | c File: hole8.cnf
2 | c
3 | c SOURCE: John Hooker (jh38+@andrew.cmu.edu)
4 | c
5 | c DESCRIPTION: Pigeon hole problem of placing n (for file holen) pigeons
6 | c in n+1 holes without placing 2 pigeons in the same hole
7 | c
8 | c NOTE: Part of the collection at the Forschungsinstitut fuer
9 | c anwendungsorientierte Wissensverarbeitung in Ulm Germany.
10 | c
11 | c NOTE: Not satisfiable
12 | c
13 | p cnf 72 297
14 | -1 -9 0
15 | -1 -17 0
16 | -1 -25 0
17 | -1 -33 0
18 | -1 -41 0
19 | -1 -49 0
20 | -1 -57 0
21 | -1 -65 0
22 | -9 -17 0
23 | -9 -25 0
24 | -9 -33 0
25 | -9 -41 0
26 | -9 -49 0
27 | -9 -57 0
28 | -9 -65 0
29 | -17 -25 0
30 | -17 -33 0
31 | -17 -41 0
32 | -17 -49 0
33 | -17 -57 0
34 | -17 -65 0
35 | -25 -33 0
36 | -25 -41 0
37 | -25 -49 0
38 | -25 -57 0
39 | -25 -65 0
40 | -33 -41 0
41 | -33 -49 0
42 | -33 -57 0
43 | -33 -65 0
44 | -41 -49 0
45 | -41 -57 0
46 | -41 -65 0
47 | -49 -57 0
48 | -49 -65 0
49 | -57 -65 0
50 | -2 -10 0
51 | -2 -18 0
52 | -2 -26 0
53 | -2 -34 0
54 | -2 -42 0
55 | -2 -50 0
56 | -2 -58 0
57 | -2 -66 0
58 | -10 -18 0
59 | -10 -26 0
60 | -10 -34 0
61 | -10 -42 0
62 | -10 -50 0
63 | -10 -58 0
64 | -10 -66 0
65 | -18 -26 0
66 | -18 -34 0
67 | -18 -42 0
68 | -18 -50 0
69 | -18 -58 0
70 | -18 -66 0
71 | -26 -34 0
72 | -26 -42 0
73 | -26 -50 0
74 | -26 -58 0
75 | -26 -66 0
76 | -34 -42 0
77 | -34 -50 0
78 | -34 -58 0
79 | -34 -66 0
80 | -42 -50 0
81 | -42 -58 0
82 | -42 -66 0
83 | -50 -58 0
84 | -50 -66 0
85 | -58 -66 0
86 | -3 -11 0
87 | -3 -19 0
88 | -3 -27 0
89 | -3 -35 0
90 | -3 -43 0
91 | -3 -51 0
92 | -3 -59 0
93 | -3 -67 0
94 | -11 -19 0
95 | -11 -27 0
96 | -11 -35 0
97 | -11 -43 0
98 | -11 -51 0
99 | -11 -59 0
100 | -11 -67 0
101 | -19 -27 0
102 | -19 -35 0
103 | -19 -43 0
104 | -19 -51 0
105 | -19 -59 0
106 | -19 -67 0
107 | -27 -35 0
108 | -27 -43 0
109 | -27 -51 0
110 | -27 -59 0
111 | -27 -67 0
112 | -35 -43 0
113 | -35 -51 0
114 | -35 -59 0
115 | -35 -67 0
116 | -43 -51 0
117 | -43 -59 0
118 | -43 -67 0
119 | -51 -59 0
120 | -51 -67 0
121 | -59 -67 0
122 | -4 -12 0
123 | -4 -20 0
124 | -4 -28 0
125 | -4 -36 0
126 | -4 -44 0
127 | -4 -52 0
128 | -4 -60 0
129 | -4 -68 0
130 | -12 -20 0
131 | -12 -28 0
132 | -12 -36 0
133 | -12 -44 0
134 | -12 -52 0
135 | -12 -60 0
136 | -12 -68 0
137 | -20 -28 0
138 | -20 -36 0
139 | -20 -44 0
140 | -20 -52 0
141 | -20 -60 0
142 | -20 -68 0
143 | -28 -36 0
144 | -28 -44 0
145 | -28 -52 0
146 | -28 -60 0
147 | -28 -68 0
148 | -36 -44 0
149 | -36 -52 0
150 | -36 -60 0
151 | -36 -68 0
152 | -44 -52 0
153 | -44 -60 0
154 | -44 -68 0
155 | -52 -60 0
156 | -52 -68 0
157 | -60 -68 0
158 | -5 -13 0
159 | -5 -21 0
160 | -5 -29 0
161 | -5 -37 0
162 | -5 -45 0
163 | -5 -53 0
164 | -5 -61 0
165 | -5 -69 0
166 | -13 -21 0
167 | -13 -29 0
168 | -13 -37 0
169 | -13 -45 0
170 | -13 -53 0
171 | -13 -61 0
172 | -13 -69 0
173 | -21 -29 0
174 | -21 -37 0
175 | -21 -45 0
176 | -21 -53 0
177 | -21 -61 0
178 | -21 -69 0
179 | -29 -37 0
180 | -29 -45 0
181 | -29 -53 0
182 | -29 -61 0
183 | -29 -69 0
184 | -37 -45 0
185 | -37 -53 0
186 | -37 -61 0
187 | -37 -69 0
188 | -45 -53 0
189 | -45 -61 0
190 | -45 -69 0
191 | -53 -61 0
192 | -53 -69 0
193 | -61 -69 0
194 | -6 -14 0
195 | -6 -22 0
196 | -6 -30 0
197 | -6 -38 0
198 | -6 -46 0
199 | -6 -54 0
200 | -6 -62 0
201 | -6 -70 0
202 | -14 -22 0
203 | -14 -30 0
204 | -14 -38 0
205 | -14 -46 0
206 | -14 -54 0
207 | -14 -62 0
208 | -14 -70 0
209 | -22 -30 0
210 | -22 -38 0
211 | -22 -46 0
212 | -22 -54 0
213 | -22 -62 0
214 | -22 -70 0
215 | -30 -38 0
216 | -30 -46 0
217 | -30 -54 0
218 | -30 -62 0
219 | -30 -70 0
220 | -38 -46 0
221 | -38 -54 0
222 | -38 -62 0
223 | -38 -70 0
224 | -46 -54 0
225 | -46 -62 0
226 | -46 -70 0
227 | -54 -62 0
228 | -54 -70 0
229 | -62 -70 0
230 | -7 -15 0
231 | -7 -23 0
232 | -7 -31 0
233 | -7 -39 0
234 | -7 -47 0
235 | -7 -55 0
236 | -7 -63 0
237 | -7 -71 0
238 | -15 -23 0
239 | -15 -31 0
240 | -15 -39 0
241 | -15 -47 0
242 | -15 -55 0
243 | -15 -63 0
244 | -15 -71 0
245 | -23 -31 0
246 | -23 -39 0
247 | -23 -47 0
248 | -23 -55 0
249 | -23 -63 0
250 | -23 -71 0
251 | -31 -39 0
252 | -31 -47 0
253 | -31 -55 0
254 | -31 -63 0
255 | -31 -71 0
256 | -39 -47 0
257 | -39 -55 0
258 | -39 -63 0
259 | -39 -71 0
260 | -47 -55 0
261 | -47 -63 0
262 | -47 -71 0
263 | -55 -63 0
264 | -55 -71 0
265 | -63 -71 0
266 | -8 -16 0
267 | -8 -24 0
268 | -8 -32 0
269 | -8 -40 0
270 | -8 -48 0
271 | -8 -56 0
272 | -8 -64 0
273 | -8 -72 0
274 | -16 -24 0
275 | -16 -32 0
276 | -16 -40 0
277 | -16 -48 0
278 | -16 -56 0
279 | -16 -64 0
280 | -16 -72 0
281 | -24 -32 0
282 | -24 -40 0
283 | -24 -48 0
284 | -24 -56 0
285 | -24 -64 0
286 | -24 -72 0
287 | -32 -40 0
288 | -32 -48 0
289 | -32 -56 0
290 | -32 -64 0
291 | -32 -72 0
292 | -40 -48 0
293 | -40 -56 0
294 | -40 -64 0
295 | -40 -72 0
296 | -48 -56 0
297 | -48 -64 0
298 | -48 -72 0
299 | -56 -64 0
300 | -56 -72 0
301 | -64 -72 0
302 | 8 7 6 5 4 3 2 1 0
303 | 16 15 14 13 12 11 10 9 0
304 | 24 23 22 21 20 19 18 17 0
305 | 32 31 30 29 28 27 26 25 0
306 | 40 39 38 37 36 35 34 33 0
307 | 48 47 46 45 44 43 42 41 0
308 | 56 55 54 53 52 51 50 49 0
309 | 64 63 62 61 60 59 58 57 0
310 | 72 71 70 69 68 67 66 65 0
311 |
--------------------------------------------------------------------------------
/examples/Factor.hs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import Ersatz
4 | import Control.Monad
5 |
6 | problem :: MonadSAT s m => m (Bits, Bits, Bits)
7 | problem = do
8 | a <- liftM Bits (replicateM 5 exists)
9 | b <- liftM Bits (replicateM 5 exists)
10 | let c = a * b
11 | assert (a /== encode 1)
12 | assert (b /== encode 1)
13 | assert (c === encode 143)
14 | return (a,b,c)
15 |
16 | main :: IO ()
17 | main = do
18 | putStrLn "Solution:"
19 | (Satisfied, Just (a,b,c)) <- solveWith cryptominisat5 problem
20 | putStrLn (show a ++ " * " ++ show b ++ " = " ++ show c)
21 |
--------------------------------------------------------------------------------
/examples/Fish.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE ScopedTypeVariables #-}
2 |
3 | {-
4 | • There are 5 houses that are each a different colour.
5 | • There is a person of a different nationality in each house.
6 | • The 5 owners drink a certain drink. They each smoke a certain brand of cigarettes and also have a certain pet. No owner has the same pet, smokes the same brand of cigarettes nor drinks the same drink.
7 | • The question is. “Who has the fish?”
8 |
9 | CLUES
10 |
11 | 1. The British man lives in the red house.
12 | 2. The Swedish man has a dog for a pet.
13 | 3. The Danish man drinks tea.
14 | 4. The green house is to the left of the white house.
15 | 5. The owner of the green house drinks coffee.
16 | 6. The person that smokes Pall Mall has a bird.
17 | 7. The owner of the yellow house smokes Dunhill.
18 | 8. The person that lives in the middle house drinks milk.
19 | 9. The Norwegian lives in the first house.
20 | 10. The person that smokes Blend, lives next to the one that has a cat.
21 | 11. The person that has a horse lives next to the one that smokes Dunhill.
22 | 12. The one that smokes Bluemaster drinks beer.
23 | 13. The German smokes Prince.
24 | 14. The Norwegian lives next to a blue house.
25 | 15. The person that smokes Blend, has a neighbour that drinks water.
26 | -}
27 |
28 | module Main where
29 |
30 | import Control.Monad (forM_, mzero, mplus)
31 | import Data.List (tails)
32 | import Data.Map (Map,(!))
33 | import Data.Traversable (sequence)
34 | import Prelude hiding (sequence,(&&),(||),and,or)
35 | import qualified Data.Map as Map
36 |
37 | import Ersatz
38 |
39 | main :: IO ()
40 | main =
41 | do (Satisfied, Just solution) <- solveWith cryptominisat5 puzzle
42 | forM_ people $ \who ->
43 | putStrLn (who ++ ": " ++ unwords (attributesForPerson solution who))
44 |
45 | (Unsatisfied, _ :: IO ()) <- solveWith minisat $
46 | do p <- puzzle
47 | assert (encode solution /== p)
48 |
49 | return ()
50 |
51 | -- | Return a list of the attributes matching a person. Note that
52 | -- the solution is a 'Map' of 'Bool' because we use the completed
53 | -- solution at this point rather than the 'Map' of 'Bit' we have
54 | -- when computing the constraints.
55 | attributesForPerson :: Map (String,String) Bool -> String -> [String]
56 | attributesForPerson solution who
57 | = [ v
58 | | vs <- tail attributes -- skip people
59 | , v <- vs
60 | , solution!key who v
61 | ]
62 |
63 | attributes :: [[String]]
64 | attributes = [people, colors, drinks, cigs, pets, houses]
65 |
66 | people, colors, drinks, cigs, pets, houses :: [String]
67 | people = ["brit" ,"german","swede" ,"dane" ,"norwegian" ]
68 | colors = ["red" ,"yellow","green" ,"blue" ,"white" ]
69 | drinks = ["coffee" ,"beer" ,"milk" ,"tea" ,"water" ]
70 | cigs = ["dunhill","blend" ,"prince","pallmall","bluemaster"]
71 | pets = ["horse" ,"dog" ,"cat" ,"bird" ,"fish" ]
72 | houses = ["one" ,"two" ,"three" ,"four" ,"five" ]
73 |
74 | -- | Construct a map of attribute associations for every combination
75 | -- of attributes.
76 | defineVariables ::
77 | (MonadSAT s m, Variable a) =>
78 | m (Map (String,String) a)
79 | defineVariables
80 | = sequence
81 | $ Map.fromList
82 | [ (key v1 v2, exists)
83 | | xs <- subsequencesN 2 attributes
84 | , [v1,v2] <- sequence xs
85 | ]
86 |
87 | -- Put the two attributes in a canonical ordering for forming a key.
88 | key :: String -> String -> (String,String)
89 | key x y
90 | | x <= y = (x,y)
91 | | otherwise = (y,x)
92 |
93 | -- | Return all subsequences of the given list with the given length.
94 | subsequencesN :: Int -> [a] -> [[a]]
95 | subsequencesN 0 _ = return []
96 | subsequencesN _ [] = mzero
97 | subsequencesN n (x:xs) = keepX `mplus` skipX
98 | where
99 | keepX = fmap (x:) (subsequencesN (n-1) xs)
100 | skipX = subsequencesN n xs
101 |
102 | -- | Add constraints that 1) each attribute is associated with
103 | -- exactly one attribute from each of the other categories, and
104 | -- 2) attribute associations are transitive.
105 | generalConstraints :: Boolean a => Map (String,String) a -> a
106 | generalConstraints v = uniqueness && transitivity
107 | where
108 | uniqueness
109 | = and [ unique a1 a2 &&
110 | unique a2 a1
111 | | [a1,a2] <- subsequencesN 2 attributes
112 | ]
113 |
114 | transitivity
115 | = and [ v!key v1 v2 ==> v!key v2 v3 ==> v!key v1 v3
116 | | xs <- subsequencesN 3 attributes
117 | , [v1,v2,v3] <- sequence xs
118 | ]
119 |
120 | -- each y in ys is associated with exactly one x in xs
121 | unique xs ys
122 | = and [ singleton [ v!key x y | x <- xs ]
123 | | y <- ys
124 | ]
125 |
126 | -- | Returns 'true' if and only if exactly one element in
127 | -- the list is 'true'.
128 | singleton :: Boolean a => [a] -> a
129 | singleton xs = atLeastOne && atMostOne
130 | where
131 | atLeastOne = or xs
132 | atMostOne = and [ y ==> nor ys | y:ys <- tails xs ]
133 |
134 | -- | Return 'true' if and only if the first attribute
135 | -- is associated with a house number directly left of
136 | -- the house number of associated with the second attribute.
137 | leftOf :: Boolean a => Map (String,String) a -> String -> String -> a
138 | leftOf v l r
139 | = or [ v!key l x
140 | && v!key r y
141 | | x:y:_ <- tails houses
142 | ]
143 |
144 | -- | Return 'true' if first attribute is "left of" second attribue
145 | -- or visa versa.
146 | nextTo :: Boolean a => Map (String,String) a -> String -> String -> a
147 | nextTo v a b
148 | = leftOf v a b
149 | || leftOf v b a
150 |
151 |
152 | -- | Check whether a particular assignment of the attribute associations
153 | -- satisfies the clues for this puzzle.
154 | validAssignment :: Boolean a => Map (String,String) a -> a
155 | validAssignment v
156 | = and [ generalConstraints v -- Preamble
157 | , v!key "brit" "red" -- Clue 1
158 | , v!key "swede" "dog" -- Clue 2
159 | , v!key "dane" "tea" -- Clue 3
160 | , leftOf v "green" "white" -- Clue 4
161 | , v!key "green" "coffee" -- Clue 5
162 | , v!key "pallmall" "bird" -- Clue 6
163 | , v!key "yellow" "dunhill" -- Clue 7
164 | , v!key "three" "milk" -- Clue 8
165 | , v!key "norwegian" "one" -- Clue 9
166 | , nextTo v "blend" "cat" -- Clue 10
167 | , nextTo v "horse" "dunhill" -- Clue 11
168 | , v!key "bluemaster" "beer" -- Clue 12
169 | , v!key "german" "prince" -- Clue 13
170 | , nextTo v "norwegian" "blue" -- Clue 14
171 | , nextTo v "blend" "water" -- Clue 15
172 | ]
173 |
174 |
175 | -- | Construct an assignment of attribute associations that satisfies
176 | -- all of the constraints of the puzzle.
177 | puzzle ::
178 | MonadSAT s m =>
179 | m (Map (String,String) Bit)
180 | puzzle =
181 | do v <- defineVariables
182 | assert (validAssignment v)
183 | return v
184 |
--------------------------------------------------------------------------------
/examples/qbf/Coloring.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE CPP #-}
2 | module Main where
3 |
4 | import Prelude hiding (not, (&&), and, or)
5 |
6 | import Ersatz
7 | import Ersatz.Relation
8 | import Ersatz.Counting
9 |
10 | import qualified Data.Array as A
11 | import Data.Array (Array, Ix)
12 |
13 | import Control.Monad.State.Lazy (StateT)
14 |
15 | import Data.List (tails)
16 |
17 | import qualified Data.ByteString.Lazy as B
18 | import qualified Data.ByteString.Lazy.Char8 as C
19 | import Data.Functor.Identity
20 | #if !(MIN_VERSION_base(4,11,0))
21 | import Data.Semigroup (Semigroup(..))
22 | #endif
23 |
24 | import Options.Applicative
25 | import Text.Printf (printf)
26 |
27 |
28 | data Coloring = Coloring Int Int Int
29 |
30 | coloring :: Parser Coloring
31 | coloring = Coloring
32 | <$> argument auto ( metavar "n" <> showDefault <> value 11 <> help "Number of nodes of graph G" )
33 | <*> argument auto ( metavar "c" <> showDefault <> value 3 <> help "G is not c-colorable" )
34 | <*> argument auto ( metavar "k" <> showDefault <> value 3 <> help "G has no complete subgraph with k nodes" )
35 |
36 | -- | default: Grötzsch graph: not 3-colorable and K3-free (11 nodes)
37 | main :: IO ()
38 | main = execParser options >>= run
39 | where options = info (coloring <**> helper) fullDesc
40 |
41 | run :: Coloring -> IO ()
42 | run (Coloring n c k) = do
43 | printf "n = %d, c = %d, k = %d\n" n c k
44 | formulaSize $ problem n c k
45 | solve $ problem n c k
46 |
47 |
48 | solve :: StateT QSAT IO (Relation Int Int) -> IO ()
49 | solve p = do
50 | result <- solveWith depqbf p
51 | case result of
52 | (Satisfied, Just r) -> mapM_ putStrLn [table r, show $ edgesA r]
53 | _ -> putStrLn "unsat"
54 |
55 | -- | @problem n c k@ generates a QBF problem that encodes a graph with @n@ nodes,
56 | -- which is not @c@-colorable and does not contain a complete subgraph with @k@ nodes.
57 | problem :: Monad a => Int -> Int -> Int -> StateT QSAT a (Relation Int Int)
58 | problem n c k = do
59 | r <- symmetric_relation ((0,0),(n-1,n-1))
60 | col <- universally_quantified_relation ((0,0),(n-1,c-1))
61 | assert $ and [
62 | irreflexive r
63 | , not $ has_k k r
64 | , is_coloring col ==> not $ proper col r
65 | ]
66 | return r
67 |
68 |
69 | universally_quantified_relation :: (Ix a, Ix b, MonadQSAT s m)
70 | => ((a,b),(a,b)) -> m (Relation a b)
71 | universally_quantified_relation bnd = do
72 | pairs <- sequence $ do
73 | p <- A.range bnd
74 | return $ do
75 | x <- forall_
76 | return (p,x)
77 | return $ build bnd pairs
78 |
79 | -- | @has_k n r@ encodes the constraint that @r@ has a complete subgraph with @n@ nodes.
80 | has_k :: Ix a => Int -> Relation a a -> Bit
81 | has_k n r = or $ do
82 | xss <- select n $ universe r
83 | return $ and $ do
84 | (x:xs) <- tails xss
85 | y <- xs
86 | return $ r!(x,y)
87 |
88 | -- | select 2 [1..4] = [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
89 | select :: Int -> [a] -> [[a]]
90 | select 0 _ = [[]]
91 | select _ [] = []
92 | select k (x:xs) = map (x:) (select (k-1) xs) ++ select k xs
93 |
94 | -- | Given a relation r with domain a and codomain b, check if r matches every element in a
95 | -- to exactly one element in b.
96 | is_coloring :: Ix a => Relation a a -> Bit
97 | is_coloring c = and $ do
98 | i <- domain c
99 | return $ exactly 1 $ do
100 | j <- codomain c
101 | return $ c!(i,j)
102 |
103 | -- | @proper c r@ encodes the constraint that @c@ is a proper coloring for @r@.
104 | proper :: Ix a => Relation a a -> Relation a a -> Bit
105 | proper col r = and $ do
106 | (p,q) <- indices r
107 | j <- codomain col
108 | return $ r!(p,q) ==> not $ col!(p,j) && col!(q,j)
109 |
110 |
111 | edgesA :: (Ix a, Ix b) => Array (a,b) Bool -> [(a,b)]
112 | edgesA a = [ i | (i, b) <- A.assocs a, b == True]
113 |
114 | formulaSize :: StateT QSAT Identity a -> IO ()
115 | formulaSize p = mapM_ C.putStrLn $ take 2 $ B.split 10 $ qdimacsQSAT p
116 |
--------------------------------------------------------------------------------
/examples/qbf/Synthesis.hs:
--------------------------------------------------------------------------------
1 | -- | An example program that solves a circuit synthesis problem with the Boolean Chain approach,
2 | -- as cited in "Circuit Minimization with QBF-Based Exact Synthesis" by Reichl et al. 2023
3 | -- .
4 |
5 | module Main where
6 |
7 | import Prelude hiding (not, (&&), and, or, product)
8 |
9 | import Ersatz
10 | import Ersatz.Relation
11 | import Ersatz.Counting
12 |
13 | import qualified Data.Array as A
14 | import Data.Array (Array, Ix)
15 |
16 | import Control.Monad.State.Lazy (StateT)
17 | import Control.Monad (guard)
18 |
19 | import Text.Printf (printf)
20 | import Data.List (sortOn)
21 |
22 | import qualified Data.ByteString.Lazy as B
23 | import qualified Data.ByteString.Lazy.Char8 as C
24 | import Data.Functor.Identity
25 |
26 |
27 | -- | AIG where @atmost 2 [1,2,3,4]@ is equivalent to @10@
28 | --
29 | -- Another problem that can be quickly solved is, for example:
30 | -- n = 3, l = 5, m = 1, f xs = [exactly 2 xs]
31 | -- (AIG where @exactly 2 [1,2,3]@ is equivalent to @8@)
32 | main :: IO ()
33 | main = do
34 | let n = 4 -- number of inputs
35 | l = 6 -- number of steps (gates)
36 | m = 1 -- number of outputs
37 | f :: [Bit] -> [Bit]
38 | f xs = [atmost 2 xs]
39 | formulaSize $ problem f n l m
40 | solve $ problem f n l m
41 |
42 |
43 | solve :: StateT QSAT IO (Relation Int Int, Relation Int Int) -> IO ()
44 | solve p = do
45 | result <- solveWith depqbf p
46 | case result of
47 | (Satisfied, Just (s,o)) -> printf "output: %s\nAIG:\n%s%s\n" (show $ map fst $ sortOn snd $ edgesA o) (table s) (show $ edgesA s)
48 | _ -> putStrLn "unsat"
49 |
50 | -- | @problem f n l m@ generates a QBF problem that encodes an AIG graph with @n@ inputs,
51 | -- @l@ gates and @m@ outputs which is equivalent to the boolean function @f@.
52 | problem :: Monad a => ([Bit] -> [Bit]) -> Int -> Int -> Int -> StateT QSAT a (Relation Int Int, Relation Int Int)
53 | problem f n l m = do
54 | s <- relation ((n+1,1),(n+l,n+l)) -- selection variables: (x,y) is in s iff gate x takes gate/input y as an input
55 | assert $ and $ do -- ensure that s is acyclic (DAG)
56 | (i,j) <- indices s
57 | guard (i <= j)
58 | return $ s!(i,j) === false
59 | o <- relation ((1,1),(n+l,m)) -- output variables: (x,y) is in o iff output y is gate/input x
60 | assert $ regular_in_degree 1 o
61 | v <- universally_quantified_relation ((1,1),(1,n)) -- input variables: (1,y) is in v iff input y is true
62 | g <- relation ((1,1),(1,n+l)) -- gate value variables: (1,y) is in g iff gate/input y is true
63 | assert $ and $ do
64 | i <- [1..n]
65 | return $ g!(1,i) === v!(1,i)
66 | assert $ and $ do -- g!(1,y) = nand xs where xs is the list of inputs of y
67 | i <- [n+1..n+l]
68 | let val = not $ and $ do
69 | p <- [1..i-1]
70 | return $ s!(i,p) ==> g!(1,p)
71 | return $ g!(1,i) === val
72 | assert $ f (elems v) === elems (product g o)
73 | return (s,o)
74 |
75 |
76 | universally_quantified_relation :: (Ix a, Ix b, MonadQSAT s m)
77 | => ((a,b),(a,b)) -> m (Relation a b)
78 | universally_quantified_relation bnd = do
79 | pairs <- sequence $ do
80 | p <- A.range bnd
81 | return $ do
82 | x <- forall_
83 | return (p,x)
84 | return $ build bnd pairs
85 |
86 |
87 | edgesA :: (Ix a, Ix b) => Array (a,b) Bool -> [(a,b)]
88 | edgesA a = [ i | (i, True) <- A.assocs a]
89 |
90 | formulaSize :: StateT QSAT Identity a -> IO ()
91 | formulaSize p = mapM_ C.putStrLn $ take 2 $ B.split 10 $ qdimacsQSAT p
92 |
--------------------------------------------------------------------------------
/examples/regexp-grid/Main.hs:
--------------------------------------------------------------------------------
1 | module Main (main) where
2 |
3 | import Control.Monad
4 | import Data.List (intersperse)
5 | import Data.Map (Map)
6 | import qualified Data.Map as Map
7 | import Ersatz
8 |
9 | import RegexpGrid.Problem
10 | import RegexpGrid.Types
11 |
12 | main :: IO ()
13 | main = do
14 | (res, msol) <- solveWith cryptominisat5 problem
15 | when (res /= Satisfied) (fail (show res))
16 | case msol of
17 | Nothing -> fail "Sol was Nothing"
18 | Just sol ->
19 | mapM_ (putStrLn . ($ sol))
20 | [ line 6 P00 P06
21 | , line 5 P10 P17
22 | , line 4 P20 P28
23 | , line 3 P30 P39
24 | , line 2 P40 P4a
25 | , line 1 P50 P5b
26 | , line 0 P60 P6c
27 | , line 1 P70 P7b
28 | , line 2 P80 P8a
29 | , line 3 P90 P99
30 | , line 4 Pa0 Pa8
31 | , line 5 Pb0 Pb7
32 | , line 6 Pc0 Pc6
33 | ]
34 |
35 | line :: Int -> Pos -> Pos -> Map Pos Char -> String
36 | line spaces start end sol =
37 | replicate spaces ' ' ++ intersperse ' ' (map (sol Map.!) [start..end])
38 |
--------------------------------------------------------------------------------
/examples/regexp-grid/RegexpGrid/Problem.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE CPP #-}
2 | {-# LANGUAGE TupleSections #-}
3 | {-# LANGUAGE TemplateHaskell #-}
4 |
5 | -- | Generate an Ersatz problem definition for the regexp grid.
6 |
7 | module RegexpGrid.Problem (problem) where
8 |
9 | import Prelude hiding ((&&), (||), not, and, or, all, any)
10 |
11 | import Control.Applicative
12 | import qualified Control.Monad.Fail as Fail
13 | import Control.Monad (guard)
14 | import Control.Monad.Reader (MonadReader(..), ReaderT(..))
15 | import Control.Monad.RWS.Strict (RWST, evalRWST)
16 | import Control.Monad.Trans (MonadTrans(..))
17 | import Control.Monad.Writer.Strict (MonadWriter(..))
18 | import Control.Lens
19 | import qualified Data.Foldable as F (asum)
20 | import Data.Map (Map)
21 | import qualified Data.Map as Map
22 | #if !(MIN_VERSION_base(4,11,0))
23 | import Data.Semigroup (Semigroup(..))
24 | #endif
25 | import Data.Sequence (Seq)
26 | import qualified Data.Sequence as Seq
27 | import Ersatz
28 |
29 | import RegexpGrid.Regexp
30 | import RegexpGrid.Types
31 |
32 | type ReBit = RWST () ReBitResult ReBitState []
33 |
34 | -- | The state threaded through 'reBit'.
35 | data ReBitState = ReBitState
36 | { _rbsFields :: Seq Field -- ^ The fields against whom to apply the regexp.
37 | , _rbsLastGroup :: Integer -- ^ The latest captured group.
38 | , _rbsGroups :: Map Integer (Seq Field) -- ^ The groups captured so far.
39 | }
40 | deriving Show
41 |
42 | -- | The result value of 'reBit'.
43 | data ReBitResult = ReBitResult
44 | { _rbrCurrentGroup :: Seq Field -- ^ The fields in the current group. Used by backreferences.
45 | , _rbrResultBit :: Bit -- ^ The accumulated result 'Bit'.
46 | }
47 | deriving Show
48 |
49 | makeLenses ''ReBitState
50 | makeLenses ''ReBitResult
51 |
52 | instance Semigroup ReBitResult where
53 | ReBitResult fieldsA bitA <> ReBitResult fieldsB bitB =
54 | ReBitResult (fieldsA <> fieldsB) (bitA && bitB)
55 | {-# INLINE (<>) #-}
56 |
57 | instance Monoid ReBitResult where
58 | mempty = ReBitResult mempty true
59 | {-# INLINE mempty #-}
60 | #if !(MIN_VERSION_base(4,11,0))
61 | mappend = (<>)
62 | {-# INLINE mappend #-}
63 | #endif
64 |
65 | problem :: (Applicative m, Fail.MonadFail m, MonadSAT s m)
66 | => m (Map Pos Field)
67 | problem = do
68 | -- Allocate a literal for each field.
69 | fieldMap <- Map.fromList <$> mapM (\pos -> (pos,) <$> exists) [minBound..]
70 | runReaderT problem' fieldMap
71 | return fieldMap
72 |
73 | problem' :: (Fail.MonadFail m, MonadSAT s m)
74 | => ReaderT (Map Pos Field) m ()
75 | problem' = do
76 | r [P00,P01,P02,P03,P04,P05,P06] ".*H.*H.*"
77 | r [P10,P11,P12,P13,P14,P15,P16,P17] "(DI|NS|TH|OM)*"
78 | r [P20,P21,P22,P23,P24,P25,P26,P27,P28] "F.*[AO].*[AO].*"
79 | r [P30,P31,P32,P33,P34,P35,P36,P37,P38,P39] "(O|RHH|MM)*"
80 | r [P40,P41,P42,P43,P44,P45,P46,P47,P48,P49,P4a] ".*"
81 | r [P50,P51,P52,P53,P54,P55,P56,P57,P58,P59,P5a,P5b] "C*MC(CCC|MM)*"
82 | r [P60,P61,P62,P63,P64,P65,P66,P67,P68,P69,P6a,P6b,P6c] "[^C]*[^R]*III.*"
83 | r [P70,P71,P72,P73,P74,P75,P76,P77,P78,P79,P7a,P7b] "(...?)\\1*"
84 | r [P80,P81,P82,P83,P84,P85,P86,P87,P88,P89,P8a] "([^X]|XCC)*"
85 | r [P90,P91,P92,P93,P94,P95,P96,P97,P98,P99] "(RR|HHH)*.?"
86 | r [Pa0,Pa1,Pa2,Pa3,Pa4,Pa5,Pa6,Pa7,Pa8] "N.*X.X.X.*E"
87 | r [Pb0,Pb1,Pb2,Pb3,Pb4,Pb5,Pb6,Pb7] "R*D*M*"
88 | r [Pc0,Pc1,Pc2,Pc3,Pc4,Pc5,Pc6] ".(C|HH)*"
89 |
90 | r [P00,P10,P20,P30,P40,P50,P60] "(ND|ET|IN)[^X]*"
91 | r [P01,P11,P21,P31,P41,P51,P61,P70] "[CHMNOR]*I[CHMNOR]*"
92 | r [P02,P12,P22,P32,P42,P52,P62,P71,P80] "P+(..)\\1.*"
93 | r [P03,P13,P23,P33,P43,P53,P63,P72,P81,P90] "(E|CR|MN)*"
94 | r [P04,P14,P24,P34,P44,P54,P64,P73,P82,P91,Pa0] "([^MC]|MM|CC)*"
95 | r [P05,P15,P25,P35,P45,P55,P65,P74,P83,P92,Pa1,Pb0] "[AM]*CM(RC)*R?"
96 | r [P06,P16,P26,P36,P46,P56,P66,P75,P84,P93,Pa2,Pb1,Pc0] ".*"
97 | r [P17,P27,P37,P47,P57,P67,P76,P85,P94,Pa3,Pb2,Pc1] ".*PRR.*DDC.*"
98 | r [P28,P38,P48,P58,P68,P77,P86,P95,Pa4,Pb3,Pc2] "(HHX|[^HX])*"
99 | r [P39,P49,P59,P69,P78,P87,P96,Pa5,Pb4,Pc3] "([^EMC]|EM)*"
100 | r [P4a,P5a,P6a,P79,P88,P97,Pa6,Pb5,Pc4] ".*OXR.*"
101 | r [P5b,P6b,P7a,P89,P98,Pa7,Pb6,Pc5] ".*LR.*RL.*"
102 | r [P6c,P7b,P8a,P99,Pa8,Pb7,Pc6] ".*SE.*UE.*"
103 |
104 | r [Pc0,Pb0,Pa0,P90,P80,P70,P60] ".*G.*V.*H.*"
105 | r [Pc1,Pb1,Pa1,P91,P81,P71,P61,P50] "[CR]*"
106 | r [Pc2,Pb2,Pa2,P92,P82,P72,P62,P51,P40] ".*XEXM*"
107 | r [Pc3,Pb3,Pa3,P93,P83,P73,P63,P52,P41,P30] ".*DD.*CCM.*"
108 | r [Pc4,Pb4,Pa4,P94,P84,P74,P64,P53,P42,P31,P20] ".*XHCR.*X.*"
109 | r [Pc5,Pb5,Pa5,P95,P85,P75,P65,P54,P43,P32,P21,P10] ".*(.)(.)(.)(.)\\4\\3\\2\\1.*"
110 | r [Pc6,Pb6,Pa6,P96,P86,P76,P66,P55,P44,P33,P22,P11,P00] ".*(IN|SE|HI)"
111 | r [Pb7,Pa7,P97,P87,P77,P67,P56,P45,P34,P23,P12,P01] "[^C]*MMM[^C]*"
112 | r [Pa8,P98,P88,P78,P68,P57,P46,P35,P24,P13,P02] ".*(.)C\\1X\\1.*"
113 | r [P99,P89,P79,P69,P58,P47,P36,P25,P14,P03] "[CEIMU]*OH[AEMOR]*"
114 | r [P8a,P7a,P6a,P59,P48,P37,P26,P15,P04] "(RX|[^R])*"
115 | r [P7b,P6b,P5a,P49,P38,P27,P16,P05] "[^M]*M[^M]*"
116 | r [P6c,P5b,P4a,P39,P28,P17,P06] "(S|MM|HHH)*"
117 |
118 | r :: (Fail.MonadFail m, MonadSAT s m)
119 | => [Pos] -> String -> ReaderT (Map Pos Field) m ()
120 | r poss regexpStr = do
121 | fieldMap <- ask
122 | let fields = (fieldMap Map.!) <$> Seq.fromList poss
123 |
124 | regexp <- either (fail . show) return
125 | $ parseRegexp "RegexpGrid.Problem" regexpStr
126 |
127 | lift . assert $ runReBit regexp fields
128 |
129 | runReBit :: Regexp -> Seq Field -> Bit
130 | runReBit regexp fields =
131 | or (evalRWST go () initState ^.. folded . _2 . rbrResultBit)
132 | where
133 | initState = ReBitState fields 0 Map.empty
134 |
135 | go = reBit regexp <* endOfFields
136 | -- Make sure all the fields have been consumed.
137 | endOfFields = guard . Seq.null =<< use rbsFields
138 |
139 | reBit :: Regexp -> ReBit ()
140 |
141 | -- The end of the regexp. Nothing to do.
142 | reBit Nil = return ()
143 |
144 | -- Any character. Advance a field, assert just true.
145 | reBit (AnyCharacter next) = do
146 | withNextField $ const true
147 | reBit next
148 |
149 | -- The character c. Advance a field and assert that it matches c.
150 | reBit (Character c next) = do
151 | withNextField $ \f -> f === encode c
152 | reBit next
153 |
154 | -- The character group cs. Advance a field and assert that it matches any one
155 | -- of cs.
156 | reBit (Accept cs next) = do
157 | withNextField $ \f -> any (\c -> f === encode c) cs
158 | reBit next
159 |
160 | -- The character group ^cs. Advance a field and assert that it does not match
161 | -- any of cs.
162 | reBit (Reject cs next) = do
163 | withNextField $ \f -> all (\c -> f /== encode c) cs
164 | reBit next
165 |
166 | -- A choice of regexps. The 'Alternative' sum of all of them.
167 | reBit (Choice res next) = do
168 | F.asum (map reBit res)
169 | reBit next
170 |
171 | -- Capture a group.
172 | reBit (Group re' next) = do
173 | ((), groupResult) <- listen (reBit re')
174 |
175 | -- Allocate a new group ID and add the group to the group map.
176 | gid <- rbsLastGroup <+= 1
177 | rbsGroups . at gid ?= (groupResult ^. rbrCurrentGroup)
178 |
179 | reBit next
180 |
181 | -- Repetition {_,0}: Just skip to the next part of the regexp.
182 | reBit (Repeat _ (Just 0) _ next) =
183 | reBit next
184 |
185 | -- Repetition {0,_}: Branch to the alternatives:
186 | -- • skip to the next part (zero instances)
187 | -- • at least one instance ({1,_}).
188 | reBit (Repeat 0 mj re' next) =
189 | reBit next <|> reBit (Repeat 1 mj re' next)
190 |
191 | -- Repetition {i,j} where i > 0 and j > 0: At least one instance followed by
192 | -- {i−1,j−1}.
193 | reBit (Repeat i mj re' next) = do
194 | reBit re'
195 | reBit (Repeat (i-1) (subtract 1 <$> mj) re' next)
196 |
197 | -- Backreference.
198 | reBit (Backreference n next) = do
199 | -- The fields of the group referred to.
200 | Just refFields <- use (rbsGroups . at n)
201 | -- Advance an equivalent number of fields.
202 | fields <- traverse (const nextField) refFields
203 | -- Assert that the field sequences match each other.
204 | tell $ ReBitResult fields (and (Seq.zipWith (===) refFields fields))
205 | reBit next
206 |
207 | -- Advance a field and build a Bit based on it.
208 | withNextField :: (Field -> Bit) -> ReBit ()
209 | withNextField func = do
210 | f <- nextField
211 | tell $ ReBitResult (Seq.singleton f) (func f)
212 |
213 | -- Advance a field.
214 | nextField :: ReBit Field
215 | nextField = do
216 | -- Pop the first field from the state. Fails if there are none left.
217 | Just (f, fs) <- preuse (rbsFields . _Cons)
218 | rbsFields .= fs
219 | return f
220 |
--------------------------------------------------------------------------------
/examples/regexp-grid/RegexpGrid/Regexp.hs:
--------------------------------------------------------------------------------
1 | -- | A parser for a subset of the regular expression syntax.
2 |
3 | module RegexpGrid.Regexp (Regexp (..), parseRegexp) where
4 |
5 | import Control.Monad
6 | import Data.Char
7 | import Text.Parsec
8 |
9 | data Regexp = Nil
10 | | AnyCharacter Regexp
11 | | Character Char Regexp
12 | | Accept [Char] Regexp
13 | | Reject [Char] Regexp
14 | | Choice [Regexp] Regexp
15 | | Group Regexp Regexp
16 | | Repeat Integer (Maybe Integer) Regexp Regexp
17 | | Backreference Integer Regexp
18 | deriving Show
19 |
20 | type REParser = Parsec String REState (Regexp -> Regexp)
21 | type REState = Integer
22 |
23 | parseRegexp :: SourceName -> String -> Either ParseError Regexp
24 | parseRegexp = runParser (regexp <* eof) 0
25 |
26 | regexp :: Parsec String REState Regexp
27 | regexp = go <$> (items `sepBy` char '|')
28 | where
29 | go [] = Nil
30 | go [re] = re
31 | go res = Choice res Nil
32 |
33 | items :: Parsec String REState Regexp
34 | items = go <$> many (nonModifier >>= modifier)
35 | where
36 | go = ($ Nil) . foldr (.) id
37 |
38 | nonModifier :: REParser
39 | nonModifier = AnyCharacter <$ char '.'
40 | <|> group
41 | <|> characterClass
42 | <|> backreference
43 | <|> Character <$> nonSpecialChar
44 |
45 | group :: REParser
46 | group = Group <$> between (char '(') (char ')') go
47 | where
48 | go = modifyState (+1) *> regexp
49 |
50 | backreference :: REParser
51 | backreference = do
52 | _ <- char '\\'
53 | n <- fromIntegral . digitToInt <$> digit
54 | numGroups <- getState
55 | when (n == 0 || n > numGroups) $ invalid n
56 | return (Backreference n)
57 | where
58 | invalid n = fail ("Invalid backreference: " ++ show n)
59 |
60 | characterClass :: REParser
61 | characterClass = between (char '[') (char ']') go
62 | where
63 | go = Reject <$> (char '^' *> many1 nonSpecialChar)
64 | <|> Accept <$> many1 nonSpecialChar
65 |
66 | nonSpecialChar :: Parsec String u Char
67 | nonSpecialChar = noneOf "\\.[](){}|^$?*+" > "nonspecial"
68 |
69 | modifier :: (Regexp -> Regexp) -> REParser
70 | modifier re = Repeat 0 (Just 1) re' <$ char '?'
71 | <|> Repeat 0 Nothing re' <$ char '*'
72 | <|> Repeat 1 Nothing re' <$ char '+'
73 | <|> pure re
74 | where
75 | re' :: Regexp
76 | re' = re Nil
77 |
78 | {-# ANN module "HLint: ignore Use String" #-}
79 |
--------------------------------------------------------------------------------
/examples/regexp-grid/RegexpGrid/Types.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE TypeFamilies #-}
2 | {-# LANGUAGE DeriveGeneric #-}
3 |
4 | module RegexpGrid.Types
5 | ( Pos (..)
6 | , Field (..)
7 | ) where
8 |
9 | import Data.Char (chr, ord)
10 | import Ersatz
11 | import GHC.Generics
12 |
13 | data Pos = P00|P01|P02|P03|P04|P05|P06
14 | | P10|P11|P12|P13|P14|P15|P16|P17
15 | | P20|P21|P22|P23|P24|P25|P26|P27|P28
16 | | P30|P31|P32|P33|P34|P35|P36|P37|P38|P39
17 | | P40|P41|P42|P43|P44|P45|P46|P47|P48|P49|P4a
18 | | P50|P51|P52|P53|P54|P55|P56|P57|P58|P59|P5a|P5b
19 | | P60|P61|P62|P63|P64|P65|P66|P67|P68|P69|P6a|P6b|P6c
20 | | P70|P71|P72|P73|P74|P75|P76|P77|P78|P79|P7a|P7b
21 | | P80|P81|P82|P83|P84|P85|P86|P87|P88|P89|P8a
22 | | P90|P91|P92|P93|P94|P95|P96|P97|P98|P99
23 | | Pa0|Pa1|Pa2|Pa3|Pa4|Pa5|Pa6|Pa7|Pa8
24 | | Pb0|Pb1|Pb2|Pb3|Pb4|Pb5|Pb6|Pb7
25 | | Pc0|Pc1|Pc2|Pc3|Pc4|Pc5|Pc6
26 | deriving (Eq, Ord, Bounded, Enum, Read, Show)
27 |
28 | -- 5 bits are enough for A–Z. (The subset of the alphabet used by the regexps
29 | -- also requires 5 bits. For simplicity, just use the full alphabet.)
30 | newtype Field = Field Bit5
31 | deriving (Show, Generic)
32 |
33 | instance Boolean Field
34 | instance Variable Field
35 | instance Equatable Field
36 |
37 | instance Codec Field where
38 | type Decoded Field = Char
39 | decode s (Field f) = chr . (+ origin) . fromIntegral <$> decode s f
40 | encode = Field . encode . fromIntegral . subtract origin . ord
41 |
42 | -- Encode 0 as the character preceding A.
43 | origin :: Int
44 | origin = ord 'A' - 1
45 |
--------------------------------------------------------------------------------
/examples/sudoku/Main.hs:
--------------------------------------------------------------------------------
1 | module Main (main) where
2 |
3 | import Prelude hiding ((&&), (||), not, and, or, all, any)
4 |
5 | import Control.Monad
6 | import Data.Array (Array, (!))
7 | import qualified Data.Array as Array
8 | import qualified Data.List as List
9 | import Data.Word
10 | import Ersatz
11 |
12 | import Sudoku.Problem
13 |
14 | main :: IO ()
15 | main = do
16 | putStrLn "Problem:"
17 | putStr (render initValues)
18 |
19 | putStrLn "Solution:"
20 | (res, msol) <- solveWith cryptominisat5 (problem initValues)
21 | when (res /= Satisfied) (fail (show res))
22 | case msol of
23 | Just sol -> putStr (render sol)
24 | _ -> fail ("sol was " ++ show msol)
25 |
26 | initValues :: Array (Word8,Word8) Word8
27 | initValues =
28 | -- From https://en.wikipedia.org/w/index.php?title=Sudoku&oldid=543290082
29 | Array.listArray range
30 | [ 5, 3, 0, 0, 7, 0, 0, 0, 0
31 | , 6, 0, 0, 1, 9, 5, 0, 0, 0
32 | , 0, 9, 8, 0, 0, 0, 0, 6, 0
33 | , 8, 0, 0, 0, 6, 0, 0, 0, 3
34 | , 4, 0, 0, 8, 0, 3, 0, 0, 1
35 | , 7, 0, 0, 0, 2, 0, 0, 0, 6
36 | , 0, 6, 0, 0, 0, 0, 2, 8, 0
37 | , 0, 0, 0, 4, 1, 9, 0, 0, 5
38 | , 0, 0, 0, 0, 8, 0, 0, 7, 9
39 | ]
40 |
41 | render :: Array (Word8,Word8) Word8 -> String
42 | render sol = unlines . renderGroups top divider bottom
43 | $ map (renderLine sol) [0..8]
44 | where
45 | top = bar "┌" "───────" "┬" "┐"
46 | divider = bar "├" "───────" "┼" "┤"
47 | bottom = bar "└" "───────" "┴" "┘"
48 |
49 | bar begin fill middle end =
50 | begin ++ List.intercalate middle (replicate 3 fill) ++ end
51 |
52 | renderLine :: Array (Word8,Word8) Word8 -> Word8 -> String
53 | renderLine sol y = unwords . renderGroups "│" "│" "│"
54 | $ map (\x -> showN (sol ! (y,x))) [0..8]
55 | where
56 | showN n | 1 <= n && n <= 9 = show n
57 | | otherwise = " "
58 |
59 | renderGroups :: a -> a -> a -> [a] -> [a]
60 | renderGroups begin middle end values =
61 | [begin] ++ List.intercalate [middle] (chunks 3 values) ++ [end]
62 | where
63 | chunks n = List.unfoldr $ \xs -> splitAt n xs <$ guard (not (null xs))
64 |
--------------------------------------------------------------------------------
/examples/sudoku/Sudoku/Cell.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE TypeFamilies #-}
2 | {-# LANGUAGE DeriveGeneric #-}
3 |
4 | module Sudoku.Cell (Cell(..)) where
5 |
6 | import Prelude hiding ((&&), (||), not, and, or, all, any)
7 |
8 | import Data.Word
9 | import Ersatz
10 | import GHC.Generics
11 |
12 | newtype Cell = Cell Bit4
13 | deriving (Show, Generic)
14 |
15 | instance Boolean Cell
16 | instance Variable Cell
17 | instance Equatable Cell
18 |
19 | instance Codec Cell where
20 | type Decoded Cell = Word8
21 | decode s (Cell b) = decode s b
22 | encode n | 1 <= n && n <= 9 = Cell (encode n)
23 | | otherwise = error ("Cell encode: invalid value " ++ show n)
24 |
--------------------------------------------------------------------------------
/examples/sudoku/Sudoku/Problem.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE FlexibleContexts #-}
2 | module Sudoku.Problem (problem, range) where
3 |
4 | import Prelude hiding ((&&), (||), not, and, or, all, any)
5 |
6 | import Control.Monad (forM_, replicateM, when)
7 | import Control.Monad.Reader (ReaderT(..), asks)
8 | import Data.Array (Array, (!))
9 | import qualified Data.Array as Array
10 | import Data.Word
11 | import Ersatz
12 |
13 | import Sudoku.Cell
14 |
15 | type Index = (Word8,Word8)
16 |
17 | type Grid = Array Index Cell
18 |
19 | data Env = Env { envCellArray :: Grid -- ^ The puzzle.
20 | , envValues :: [Cell] -- ^ The possible values for any cell.
21 | }
22 | deriving Show
23 |
24 | problem :: (Applicative m, MonadSAT s m)
25 | => Array Index Word8 -> m Grid
26 | problem initValues = do
27 | cellArray <- Array.listArray range
28 | <$> replicateM (Array.rangeSize range) exists
29 |
30 | runReaderT problem' $ Env cellArray (map encode [1..9])
31 |
32 | -- Assert all initial values.
33 | forM_ (Array.assocs initValues) $ \(idx, val) ->
34 | when (1 <= val && val <= 9) $
35 | assert $ (cellArray ! idx) === encode val
36 |
37 | return cellArray
38 |
39 | problem' :: MonadSAT s m => ReaderT Env m ()
40 | problem' = do
41 | legalValues
42 | mapM_ allDifferent (subsquares ++ horizontal ++ vertical)
43 |
44 | -- | Assert that each cell must have one of the legal values.
45 | legalValues :: MonadSAT s m => ReaderT Env m ()
46 | legalValues = mapM_ legalValue . Array.elems =<< asks envCellArray
47 | where
48 | legalValue cell = do
49 | values <- asks envValues
50 | assert $ any (cell ===) values
51 |
52 | -- | Assert that each cell in a group must have a different value.
53 | allDifferent :: MonadSAT s m => [(Word8,Word8)] -> ReaderT Env m ()
54 | allDifferent indices = do
55 | cellArray <- asks envCellArray
56 | let pairs = [ (cellArray ! a, cellArray ! b)
57 | | a <- indices, b <- indices, a /= b
58 | ]
59 | forM_ pairs $ \(cellA, cellB) -> assert (cellA /== cellB)
60 |
61 | -- | The valid index range for the grid.
62 | range :: (Index,Index)
63 | range = ((0,0),(8,8))
64 |
65 | subsquares, horizontal, vertical :: [[Index]]
66 |
67 | -- | The index group for each subsquare.
68 | subsquares = do
69 | sqY <- [0..2]
70 | sqX <- [0..2]
71 | let top = 3*sqY
72 | left = 3*sqX
73 | return [ (y,x) | y <- [top..top+2], x <- [left..left+2] ]
74 |
75 | -- | The index group for each line.
76 | horizontal = do
77 | line <- [0..8]
78 | return [ (line,x) | x <- [0..8] ]
79 |
80 | -- | The index group for each column.
81 | vertical = do
82 | column <- [0..8]
83 | return [ (y,column) | y <- [0..8] ]
84 |
--------------------------------------------------------------------------------
/notes/SPOILER.html:
--------------------------------------------------------------------------------
1 | Spoiler for regexp-grid
2 | N H P E H A S
3 | D I O M O M T H
4 | F O X N X A X P H
5 | M M O M M M M R H H
6 | M C X N M M C R X E M
7 | C M C C C C M M M M M M
8 | H R X R C M I I I H X L S
9 | O R E O R E O R E O R E
10 | V C X C C H H M X C C
11 | R R R R H H H R R U
12 | N C X D X E X L E
13 | R R D D M M M M
14 | G C C H H C C
15 |
16 |
--------------------------------------------------------------------------------
/notes/grid.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ekmett/ersatz/ffce5f2f8ab54fda0fb625b2ed67dc395c08e6bc/notes/grid.pdf
--------------------------------------------------------------------------------
/notes/papers.md:
--------------------------------------------------------------------------------
1 | # _k_-SAT
2 |
3 | * [Randomized Algorithms for 3-SAT](http://www.uni-ulm.de/fileadmin/website_uni_ulm/iui.inst.190/Mitarbeiter/schoenig/randomized_algorithms_for_3-sat.pdf) by Thomas Hofmeister
4 | * [A Full Derandomization of Schöning’s _k_-SAT Algorithm](http://arxiv.org/pdf/1008.4067.pdf) by Robin A. Moser and Dominik Scheder
5 |
6 | # Optimization
7 |
8 | * [Applying Logic Synthesis for Speeding Up SAT](http://minisat.se/downloads/synth_in_sat.pdf) by Niklas Een, Alan Mishchenko and Niklas Sörensson
9 | * [Presentation](http://minisat.se/downloads/SAT07-Een.pdf)
10 | * [Multiple-Valued Logic Minimization for PLA Synthesis](http://www.eecs.berkeley.edu/Pubs/TechRpts/1986/ERL-86-65.pdf) by Richard L. Rudell
11 | * [Automated Synthesis and Optimization of Multilevel Logic Circuits](http://researchrepository.napier.ac.uk/4342/1/Wang.pdf) by Lingli Wang
12 |
--------------------------------------------------------------------------------
/src/Ersatz.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE CPP #-}
2 | --------------------------------------------------------------------
3 | -- |
4 | -- Copyright : © Edward Kmett 2010-2014, Johan Kiviniemi 2013
5 | -- License : BSD3
6 | -- Maintainer: Edward Kmett
7 | -- Stability : experimental
8 | -- Portability: non-portable
9 | --
10 | --------------------------------------------------------------------
11 | module Ersatz
12 | ( module Ersatz.Bit
13 | , module Ersatz.Bits
14 | , module Ersatz.Codec
15 | , module Ersatz.Equatable
16 | , module Ersatz.Orderable
17 | , module Ersatz.Problem
18 | , module Ersatz.Solution
19 | , module Ersatz.Solver
20 | , module Ersatz.Variable
21 | ) where
22 |
23 | import Ersatz.Bit
24 | import Ersatz.Bits
25 | import Ersatz.Codec
26 | import Ersatz.Equatable
27 | import Ersatz.Orderable
28 | import Ersatz.Problem
29 | import Ersatz.Solution
30 | import Ersatz.Solver
31 | import Ersatz.Variable
32 |
33 | #ifdef HLINT
34 | {-# ANN module "HLint: ignore Use import/export shortcut" #-}
35 | #endif
36 |
--------------------------------------------------------------------------------
/src/Ersatz/BitChar.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE TypeFamilies #-}
2 | --------------------------------------------------------------------
3 | -- |
4 | -- Copyright : © Eric Mertens 2010-2014
5 | -- License : BSD3
6 | -- Maintainer: Edward Kmett
7 | -- Stability : experimental
8 | -- Portability: non-portable
9 | --
10 | --------------------------------------------------------------------
11 | module Ersatz.BitChar where
12 |
13 | import Data.Char (chr,ord)
14 | import Control.Monad (replicateM)
15 | import Prelude hiding ((&&))
16 |
17 | import Ersatz.Bit
18 | import Ersatz.Bits
19 | import Ersatz.Codec
20 | import Ersatz.Equatable
21 | import Ersatz.Orderable
22 | import Ersatz.Variable
23 |
24 | -- | List of 'BitChar' intended to be used as the representation for 'String'.
25 | type BitString = [BitChar]
26 |
27 | -- | Encoding of the full range of 'Char' values.
28 | newtype BitChar = BitChar Bits
29 | deriving Show
30 |
31 | instance Codec BitChar where
32 | type Decoded BitChar = Char
33 | encode = BitChar . fromIntegral . ord
34 | decode s (BitChar xs) = fmap (chr . fromIntegral) (decode s xs)
35 |
36 | instance Equatable BitChar where
37 | BitChar xs === BitChar ys = xs === ys
38 | BitChar xs /== BitChar ys = xs /== ys
39 |
40 | instance Orderable BitChar where
41 | BitChar xs BitChar ys = xs ys
42 | BitChar xs <=? BitChar ys = xs <=? ys
43 |
44 | instance Variable BitChar where
45 | literally m =
46 | -- Char upperbound is 0x10ffff, so only set
47 | -- the high bit when the next 4 bits are 0
48 |
49 | do x <- literally m
50 | xs <- replicateM 20 (literally m)
51 |
52 | let x' = x && nor (take 4 xs)
53 | n = Bits (reverse (x':xs)) -- Bits is little endian
54 |
55 | return (BitChar n)
56 |
--------------------------------------------------------------------------------
/src/Ersatz/Codec.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE Rank2Types #-}
2 | {-# LANGUAGE TypeFamilies #-}
3 | --------------------------------------------------------------------
4 | -- |
5 | -- Copyright : © Edward Kmett 2010-2014, Johan Kiviniemi 2013
6 | -- License : BSD3
7 | -- Maintainer: Edward Kmett
8 | -- Stability : experimental
9 | -- Portability: non-portable
10 | --
11 | --------------------------------------------------------------------
12 | module Ersatz.Codec
13 | ( Codec(..)
14 | ) where
15 |
16 | import Control.Applicative
17 | import Control.Monad hiding (mapM)
18 | import Data.Array
19 | import Data.HashMap.Lazy (HashMap)
20 | import Data.IntMap (IntMap)
21 | import Data.Kind
22 | import Data.Map (Map)
23 | import Data.Sequence (Seq)
24 | import Data.Traversable
25 | import Data.Tree (Tree)
26 | import Ersatz.Internal.Literal
27 | import Ersatz.Solution
28 | import Prelude hiding (mapM)
29 |
30 | -- | This class describes data types that can be marshaled to or from a SAT solver.
31 | class Codec a where
32 | type Decoded a :: Type
33 | -- | Return 'Just' a value based on the solution if one can be determined.
34 | -- Otherwise, return 'Nothing'.
35 | decode :: Solution -> a -> Maybe (Decoded a)
36 | encode :: Decoded a -> a
37 |
38 | -- | By convention, the 'decode' implementation will return 'False' for
39 | -- unconstrained non-negative 'Literal's and 'True' for unconstrained negative
40 | -- 'Literal's.
41 | instance Codec Literal where
42 | type Decoded Literal = Bool
43 | decode s a = case solutionLiteral s a of
44 | sol@(Just _) -> sol
45 | Nothing
46 | | i >= 0 -> Just False
47 | | otherwise -> Just True
48 | where
49 | i = literalId a
50 | encode True = literalTrue
51 | encode False = literalFalse
52 |
53 | instance Codec () where
54 | type Decoded () = ()
55 | decode _ () = pure ()
56 | encode () = ()
57 |
58 | instance (Codec a, Codec b) => Codec (a,b) where
59 | type Decoded (a,b) = (Decoded a, Decoded b)
60 | decode s (a,b) = (,) <$> decode s a <*> decode s b
61 | encode (a,b) = (encode a, encode b)
62 |
63 | instance (Codec a, Codec b, Codec c) => Codec (a,b,c) where
64 | type Decoded (a,b,c) = (Decoded a, Decoded b, Decoded c)
65 | decode s (a,b,c) = (,,) <$> decode s a <*> decode s b <*> decode s c
66 | encode (a,b,c) = (encode a, encode b, encode c)
67 |
68 | instance (Codec a, Codec b, Codec c, Codec d) => Codec (a,b,c,d) where
69 | type Decoded (a,b,c,d) = (Decoded a, Decoded b, Decoded c, Decoded d)
70 | decode s (a,b,c,d) = (,,,) <$> decode s a <*> decode s b <*> decode s c <*> decode s d
71 | encode (a,b,c,d) = (encode a, encode b, encode c, encode d)
72 |
73 | instance (Codec a, Codec b, Codec c, Codec d, Codec e) => Codec (a,b,c,d,e) where
74 | type Decoded (a,b,c,d,e) = (Decoded a, Decoded b, Decoded c, Decoded d, Decoded e)
75 | decode s (a,b,c,d,e) = (,,,,) <$> decode s a <*> decode s b <*> decode s c <*> decode s d <*> decode s e
76 | encode (a,b,c,d,e) = (encode a, encode b, encode c, encode d, encode e)
77 |
78 | instance (Codec a, Codec b, Codec c, Codec d, Codec e, Codec f) => Codec (a,b,c,d,e,f) where
79 | type Decoded (a,b,c,d,e,f) = (Decoded a, Decoded b, Decoded c, Decoded d, Decoded e, Decoded f)
80 | decode s (a,b,c,d,e,f) = (,,,,,) <$> decode s a <*> decode s b <*> decode s c <*> decode s d <*> decode s e <*> decode s f
81 | encode (a,b,c,d,e,f) = (encode a, encode b, encode c, encode d, encode e, encode f)
82 |
83 | instance (Codec a, Codec b, Codec c, Codec d, Codec e, Codec f, Codec g) => Codec (a,b,c,d,e,f,g) where
84 | type Decoded (a,b,c,d,e,f,g) = (Decoded a, Decoded b, Decoded c, Decoded d, Decoded e, Decoded f, Decoded g)
85 | decode s (a,b,c,d,e,f,g) = (,,,,,,) <$> decode s a <*> decode s b <*> decode s c <*> decode s d <*> decode s e <*> decode s f <*> decode s g
86 | encode (a,b,c,d,e,f,g) = (encode a, encode b, encode c, encode d, encode e, encode f, encode g)
87 |
88 | instance (Codec a, Codec b, Codec c, Codec d, Codec e, Codec f, Codec g, Codec h) => Codec (a,b,c,d,e,f,g,h) where
89 | type Decoded (a,b,c,d,e,f,g,h) = (Decoded a, Decoded b, Decoded c, Decoded d, Decoded e, Decoded f, Decoded g, Decoded h)
90 | decode s (a,b,c,d,e,f,g,h) = (,,,,,,,) <$> decode s a <*> decode s b <*> decode s c <*> decode s d <*> decode s e <*> decode s f <*> decode s g <*> decode s h
91 | encode (a,b,c,d,e,f,g,h) = (encode a, encode b, encode c, encode d, encode e, encode f, encode g, encode h)
92 |
93 | instance Codec a => Codec [a] where
94 | type Decoded [a] = [Decoded a]
95 | decode = mapM . decode
96 | encode = map encode
97 |
98 | instance (Ix i, Codec e) => Codec (Array i e) where
99 | type Decoded (Array i e) = Array i (Decoded e)
100 | decode = mapM . decode
101 | encode = fmap encode
102 |
103 | instance (Codec a, Codec b) => Codec (Either a b) where
104 | type Decoded (Either a b) = Either (Decoded a) (Decoded b)
105 | decode s (Left a) = Left <$> decode s a
106 | decode s (Right b) = Right <$> decode s b
107 | encode (Left a) = Left (encode a)
108 | encode (Right b) = Right (encode b)
109 |
110 | instance Codec a => Codec (HashMap k a) where
111 | type Decoded (HashMap k a) = HashMap k (Decoded a)
112 | decode = mapM . decode
113 | encode = fmap encode
114 |
115 | instance Codec a => Codec (IntMap a) where
116 | type Decoded (IntMap a) = IntMap (Decoded a)
117 | decode = mapM . decode
118 | encode = fmap encode
119 |
120 | instance Codec a => Codec (Map k a) where
121 | type Decoded (Map k a) = Map k (Decoded a)
122 | decode = mapM . decode
123 | encode = fmap encode
124 |
125 | instance Codec a => Codec (Maybe a) where
126 | type Decoded (Maybe a) = Maybe (Decoded a)
127 | decode = mapM . decode
128 | encode = fmap encode
129 |
130 | instance Codec a => Codec (Seq a) where
131 | type Decoded (Seq a) = Seq (Decoded a)
132 | decode = mapM . decode
133 | encode = fmap encode
134 |
135 | instance Codec a => Codec (Tree a) where
136 | type Decoded (Tree a) = Tree (Decoded a)
137 | decode = mapM . decode
138 | encode = fmap encode
139 |
--------------------------------------------------------------------------------
/src/Ersatz/Counting.hs:
--------------------------------------------------------------------------------
1 | module Ersatz.Counting where
2 |
3 | import Ersatz.Bit
4 | import Ersatz.Bits
5 | import Ersatz.Codec
6 | import Ersatz.Equatable
7 | import Ersatz.Orderable
8 |
9 | exactly :: Int -> [ Bit ] -> Bit
10 | exactly k bs = encode (fromIntegral k) === sumBit bs
11 |
12 | atmost :: Int -> [ Bit ] -> Bit
13 | atmost k bs = encode (fromIntegral k) >=? sumBits bs
14 |
15 | atleast :: Int -> [ Bit ] -> Bit
16 | atleast k bs = encode (fromIntegral k) <=? sumBits bs
17 |
18 |
--------------------------------------------------------------------------------
/src/Ersatz/Equatable.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE TypeFamilies #-}
2 | {-# LANGUAGE TypeOperators #-}
3 | {-# LANGUAGE FlexibleContexts #-}
4 | {-# LANGUAGE DefaultSignatures #-}
5 | {-# LANGUAGE FlexibleInstances #-}
6 | {-# LANGUAGE UndecidableInstances #-}
7 |
8 | {-# OPTIONS_HADDOCK not-home #-}
9 | --------------------------------------------------------------------
10 | -- |
11 | -- Copyright : © Edward Kmett 2010-2014, Johan Kiviniemi 2013
12 | -- License : BSD3
13 | -- Maintainer: Edward Kmett
14 | -- Stability : experimental
15 | -- Portability: non-portable
16 | --
17 | --------------------------------------------------------------------
18 | module Ersatz.Equatable
19 | ( Equatable(..)
20 | , GEquatable(..)
21 | ) where
22 |
23 | import Prelude hiding ((&&),(||),not,and,or,all,any)
24 |
25 | import Ersatz.Bit
26 | import GHC.Generics
27 | import Numeric.Natural
28 | import Data.IntMap (IntMap)
29 | import Data.Foldable (toList)
30 | import Data.Map (Map)
31 | import Data.Int
32 | import Data.Word
33 | import Data.Void
34 | import Data.List.NonEmpty (NonEmpty)
35 | import qualified Data.Map as Map
36 | import qualified Data.IntMap as IntMap
37 | import qualified Data.Sequence as Seq
38 | import qualified Data.Tree as Tree
39 |
40 | infix 4 ===, /==
41 |
42 | -- | Instances for this class for arbitrary types can be automatically derived from 'Generic'.
43 | class Equatable t where
44 | -- | Compare for equality within the SAT problem.
45 | (===) :: t -> t -> Bit
46 | default (===) :: (Generic t, GEquatable (Rep t)) => t -> t -> Bit
47 | a === b = from a ===# from b
48 |
49 | -- | Compare for inequality within the SAT problem.
50 | (/==) :: t -> t -> Bit
51 |
52 | a /== b = not (a === b)
53 |
54 | instance Equatable Bit where
55 | a === b = not (xor a b)
56 | (/==) = xor
57 |
58 | instance (Eq k, Equatable v) => Equatable (Map k v) where
59 | x === y
60 | | Map.keys x == Map.keys y = Map.elems x === Map.elems y
61 | | otherwise = false
62 |
63 | instance Equatable v => Equatable (IntMap v) where
64 | x === y
65 | | IntMap.keys x == IntMap.keys y = IntMap.elems x === IntMap.elems y
66 | | otherwise = false
67 |
68 | instance Equatable v => Equatable (Seq.Seq v) where
69 | x === y
70 | | Seq.length x == Seq.length y = toList x === toList y
71 | | otherwise = false
72 |
73 | -- manually written because ancient GHC didn't have the generics instance
74 | instance Equatable a => Equatable (Tree.Tree a) where
75 | Tree.Node x xs === Tree.Node y ys = x === y && xs === ys
76 |
77 | instance (Equatable a, Equatable b) => Equatable (a,b)
78 | instance (Equatable a, Equatable b, Equatable c) => Equatable (a,b,c)
79 | instance (Equatable a, Equatable b, Equatable c, Equatable d) => Equatable (a,b,c,d)
80 | instance (Equatable a, Equatable b, Equatable c, Equatable d, Equatable e) => Equatable (a,b,c,d,e)
81 | instance (Equatable a, Equatable b, Equatable c, Equatable d, Equatable e, Equatable f) => Equatable (a,b,c,d,e,f)
82 | instance (Equatable a, Equatable b, Equatable c, Equatable d, Equatable e, Equatable f, Equatable g) => Equatable (a,b,c,d,e,f,g)
83 | instance Equatable a => Equatable (Maybe a)
84 | instance Equatable a => Equatable [a]
85 | instance Equatable a => Equatable (NonEmpty a)
86 | instance (Equatable a, Equatable b) => Equatable (Either a b)
87 |
88 | class GEquatable f where
89 | (===#) :: f a -> f a -> Bit
90 |
91 | instance GEquatable U1 where
92 | U1 ===# U1 = true
93 |
94 | instance GEquatable V1 where
95 | x ===# y = x `seq` y `seq` error "GEquatable[V1].===#"
96 |
97 | instance (GEquatable f, GEquatable g) => GEquatable (f :*: g) where
98 | (a :*: b) ===# (c :*: d) = (a ===# c) && (b ===# d)
99 |
100 | instance (GEquatable f, GEquatable g) => GEquatable (f :+: g) where
101 | L1 a ===# L1 b = a ===# b
102 | R1 a ===# R1 b = a ===# b
103 | _ ===# _ = false
104 |
105 | instance GEquatable f => GEquatable (M1 i c f) where
106 | M1 x ===# M1 y = x ===# y
107 |
108 | instance Equatable a => GEquatable (K1 i a) where
109 | K1 a ===# K1 b = a === b
110 |
111 | -- Boring instances that end up being useful when deriving Equatable with Generics
112 |
113 | instance Equatable () where _ === _ = true
114 | instance Equatable Void where x === y = x `seq` y `seq` error "Equatable[Void].==="
115 | instance Equatable Int where x === y = bool (x == y)
116 | instance Equatable Integer where x === y = bool (x == y)
117 | instance Equatable Natural where x === y = bool (x == y)
118 | instance Equatable Word where x === y = bool (x == y)
119 | instance Equatable Word8 where x === y = bool (x == y)
120 | instance Equatable Word16 where x === y = bool (x == y)
121 | instance Equatable Word32 where x === y = bool (x == y)
122 | instance Equatable Word64 where x === y = bool (x == y)
123 | instance Equatable Int8 where x === y = bool (x == y)
124 | instance Equatable Int16 where x === y = bool (x == y)
125 | instance Equatable Int32 where x === y = bool (x == y)
126 | instance Equatable Int64 where x === y = bool (x == y)
127 | instance Equatable Char where x === y = bool (x == y)
128 | instance Equatable Float where x === y = bool (x == y)
129 | instance Equatable Double where x === y = bool (x == y)
130 | instance Equatable Ordering where x === y = bool (x == y)
131 | instance Equatable Bool where x === y = bool (x == y)
132 |
--------------------------------------------------------------------------------
/src/Ersatz/Internal/Literal.hs:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------
2 | -- |
3 | -- Copyright : © Edward Kmett 2010-2014, Johan Kiviniemi 2013
4 | -- License : BSD3
5 | -- Maintainer: Edward Kmett
6 | -- Stability : experimental
7 | -- Portability: non-portable
8 | --
9 | --------------------------------------------------------------------
10 | module Ersatz.Internal.Literal
11 | ( Literal(..)
12 | , negateLiteral
13 | , literalFalse, literalTrue
14 | ) where
15 |
16 | -- | A naked possibly-negated Atom, present in the target 'Ersatz.Solver.Solver'.
17 | --
18 | -- The literals @-1@ and @1@ are dedicated for the constant 'False' and the
19 | -- constant 'True' respectively.
20 | newtype Literal = Literal { literalId :: Int } deriving (Eq,Ord)
21 |
22 | instance Show Literal where
23 | showsPrec i = showsPrec i . literalId
24 | show = show . literalId
25 | showList = showList . map literalId
26 |
27 | negateLiteral :: Literal -> Literal
28 | negateLiteral = Literal . negate . literalId
29 |
30 | -- | The 'False' constant. The literal @-1@ is dedicated for it.
31 | literalFalse :: Literal
32 | literalFalse = Literal (-1)
33 |
34 | -- | The 'True' constant. The literal @1@ is dedicated for it.
35 | literalTrue :: Literal
36 | literalTrue = Literal 1
37 |
--------------------------------------------------------------------------------
/src/Ersatz/Internal/Parser.hs:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------
2 | -- |
3 | -- Copyright : © Edward Kmett 2010-2014, Johan Kiviniemi 2013
4 | -- License : BSD3
5 | -- Maintainer: Edward Kmett
6 | -- Stability : experimental
7 | -- Portability: non-portable
8 | --
9 | -- A trivial, inefficient parser with no support for error reporting.
10 | --------------------------------------------------------------------
11 | module Ersatz.Internal.Parser
12 | ( Parser
13 | , runParser
14 | , sepBy, sepBy1
15 | , token, string
16 | , integer, natural
17 | , eof
18 | , satisfy
19 | ) where
20 |
21 | import Control.Applicative
22 | import Control.Monad (guard)
23 | import Control.Monad.Trans.State
24 | import Data.Char (isDigit)
25 |
26 | type Parser t a = StateT [t] [] a
27 |
28 | runParser :: Parser t a -> [t] -> [a]
29 | runParser = evalStateT
30 |
31 | sepBy :: Parser t a -> Parser t sep -> Parser t [a]
32 | sepBy p sep = sepBy1 p sep <|> pure []
33 |
34 | sepBy1 :: Parser t a -> Parser t sep -> Parser t [a]
35 | sepBy1 p sep = (:) <$> p <*> many (sep *> p)
36 |
37 | token :: Eq t => t -> Parser t t
38 | token t = satisfy (== t)
39 |
40 | string :: Eq t => [t] -> Parser t [t]
41 | string = traverse token
42 |
43 | integer :: (Num i, Read i) => Parser Char i
44 | integer = negation <*> natural
45 |
46 | negation :: Num n => Parser Char (n -> n)
47 | negation = negate <$ token '-'
48 | <|> pure id
49 |
50 | natural :: Read i => Parser Char i
51 | natural = read <$> some (satisfy isDigit)
52 |
53 | eof :: Parser t ()
54 | eof = do
55 | [] <- get
56 | return ()
57 |
58 | satisfy :: (t -> Bool) -> Parser t t
59 | satisfy f = do
60 | (t:ts) <- get
61 | guard (f t)
62 | t <$ put ts
63 |
--------------------------------------------------------------------------------
/src/Ersatz/Internal/StableName.hs:
--------------------------------------------------------------------------------
1 | {-# OPTIONS_HADDOCK not-home #-}
2 | --------------------------------------------------------------------
3 | -- |
4 | -- Copyright : © Edward Kmett 2010-2014, Johan Kiviniemi 2013
5 | -- License : BSD3
6 | -- Maintainer: Edward Kmett
7 | -- Stability : experimental
8 | -- Portability: non-portable
9 | --
10 | --------------------------------------------------------------------
11 | module Ersatz.Internal.StableName
12 | ( StableName
13 | , makeStableName'
14 | ) where
15 |
16 | import System.Mem.StableName (StableName, makeStableName)
17 | import Unsafe.Coerce (unsafeCoerce)
18 |
19 | makeStableName' :: a -> IO (StableName ())
20 | makeStableName' a = a `seq` fmap coerceStableName (makeStableName a)
21 | where
22 | coerceStableName :: StableName a -> StableName ()
23 | coerceStableName = unsafeCoerce
24 |
--------------------------------------------------------------------------------
/src/Ersatz/Orderable.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE CPP #-}
2 | {-# LANGUAGE TypeFamilies #-}
3 | {-# LANGUAGE TypeOperators #-}
4 | {-# LANGUAGE FlexibleContexts #-}
5 | #ifndef HLINT
6 | {-# LANGUAGE DefaultSignatures #-}
7 | #endif
8 | {-# LANGUAGE FlexibleInstances #-}
9 | {-# LANGUAGE UndecidableInstances #-}
10 |
11 | {-# OPTIONS_HADDOCK not-home #-}
12 | --------------------------------------------------------------------
13 | -- |
14 | -- Copyright : © Edward Kmett 2010-2014, Johan Kiviniemi 2013
15 | -- License : BSD3
16 | -- Maintainer: Edward Kmett
17 | -- Stability : experimental
18 | -- Portability: non-portable
19 | --
20 | --------------------------------------------------------------------
21 | module Ersatz.Orderable
22 | ( Orderable(..)
23 | , GOrderable(..)
24 | ) where
25 |
26 | import Prelude hiding ((&&),(||),not,and,or,all,any)
27 |
28 | import Data.Foldable (toList)
29 | import Data.Int
30 | import Data.Void
31 | import Data.Word
32 | import Ersatz.Bit
33 | import Ersatz.Equatable
34 | import GHC.Generics
35 | import Numeric.Natural
36 | import qualified Data.IntMap as IntMap
37 | import qualified Data.Map as Map
38 | import qualified Data.Sequence as Seq
39 | import qualified Data.Tree as Tree
40 |
41 | infix 4 , <=?, >=?, >?
42 |
43 | -- | Instances for this class for arbitrary types can be automatically derived from 'Generic'.
44 | class Equatable t => Orderable t where
45 | -- | Compare for less-than within the SAT problem.
46 | () :: t -> t -> Bit
47 |
48 | -- | Compare for less-than or equal-to within the SAT problem.
49 | (<=?) :: t -> t -> Bit
50 | x <=? y = x === y || x y
51 | #ifndef HLINT
52 | default () :: (Generic t, GOrderable (Rep t)) => t -> t -> Bit
53 | a b = from a # from b
54 | #endif
55 |
56 | -- | Compare for greater-than or equal-to within the SAT problem.
57 | (>=?) :: t -> t -> Bit
58 | x >=? y = y <=? x
59 |
60 | -- | Compare for greater-than within the SAT problem.
61 | (>?) :: t -> t -> Bit
62 | x >? y = y x
63 |
64 |
65 | instance Orderable Bit where
66 | a b = not a && b
67 | a <=? b = not a || b
68 |
69 | -- | Compare by lexicographic order on sorted key-value pairs
70 | instance (Ord k, Orderable v) => Orderable (Map.Map k v) where
71 | x y = assocsLt (Map.assocs x) (Map.assocs y)
72 | x <=? y = assocsLe (Map.assocs x) (Map.assocs y)
73 |
74 | -- | Compare by lexicographic order on sorted key-value pairs
75 | instance Orderable v => Orderable (IntMap.IntMap v) where
76 | x y = assocsLt (IntMap.assocs x) (IntMap.assocs y)
77 | x <=? y = assocsLe (IntMap.assocs x) (IntMap.assocs y)
78 |
79 | assocsLt :: (Ord k, Orderable v) => [(k,v)] -> [(k,v)] -> Bit
80 | assocsLt _ [] = false
81 | assocsLt [] _ = true
82 | assocsLt ((k1,v1):xs) ((k2,v2):ys) =
83 | case compare k1 k2 of
84 | LT -> true
85 | GT -> false
86 | EQ -> v1 v2 || v1 === v2 && assocsLt xs ys
87 |
88 | assocsLe :: (Ord k, Orderable v) => [(k,v)] -> [(k,v)] -> Bit
89 | assocsLe [] _ = true
90 | assocsLe _ [] = false
91 | assocsLe ((k1,v1):xs) ((k2,v2):ys) =
92 | case compare k1 k2 of
93 | LT -> true
94 | GT -> false
95 | EQ -> v1 v2 || v1 === v2 && assocsLe xs ys
96 |
97 | -- | Compare by lexicographic order on elements
98 | instance Orderable v => Orderable (Seq.Seq v) where
99 | x y = toList x toList y
100 | x <=? y = toList x <=? toList y
101 |
102 | -- | Compare by lexicographic order on: root node, list of children
103 | instance Orderable a => Orderable (Tree.Tree a) where
104 | Tree.Node x xs Tree.Node y ys = (x,xs) (y,ys)
105 | Tree.Node x xs <=? Tree.Node y ys = (x,xs) <=? (y,ys)
106 |
107 | instance (Orderable a, Orderable b) => Orderable (a,b)
108 | instance (Orderable a, Orderable b, Orderable c) => Orderable (a,b,c)
109 | instance (Orderable a, Orderable b, Orderable c, Orderable d) => Orderable (a,b,c,d)
110 | instance (Orderable a, Orderable b, Orderable c, Orderable d, Orderable e) => Orderable (a,b,c,d,e)
111 | instance (Orderable a, Orderable b, Orderable c, Orderable d, Orderable e, Orderable f) => Orderable (a,b,c,d,e,f)
112 | instance (Orderable a, Orderable b, Orderable c, Orderable d, Orderable e, Orderable f, Orderable g) => Orderable (a,b,c,d,e,f,g)
113 | instance Orderable a => Orderable (Maybe a)
114 | instance (Orderable a, Orderable b) => Orderable (Either a b)
115 |
116 | -- | Lexicographic order
117 | instance Orderable a => Orderable [a] where
118 | #ifndef HLINT
119 | [] [] = false
120 | x:xs y:ys = x === y && xs ys
121 | || x y
122 | [] _ = true
123 | _ [] = false
124 |
125 | [] <=? _ = true
126 | x:xs <=? y:ys = x === y && xs <=? ys
127 | || x y
128 | _ <=? [] = false
129 | #endif
130 |
131 | class GEquatable f => GOrderable f where
132 | (#) :: f a -> f a -> Bit
133 | (<=?#) :: f a -> f a -> Bit
134 |
135 | instance GOrderable U1 where
136 | U1 # U1 = false
137 | U1 <=?# U1 = true
138 |
139 | instance GOrderable V1 where
140 | x # y = x `seq` y `seq` error "GOrderable[V1].#"
141 | x <=?# y = x `seq` y `seq` error "GOrderable[V1].<=?#"
142 |
143 | instance (GOrderable f, GOrderable g) => GOrderable (f :*: g) where
144 | (a :*: b) # (c :*: d) = (a # c) || (a ===# c && b # d)
145 | (a :*: b) <=?# (c :*: d) = (a # c) || (a ===# c && b <=?# d)
146 |
147 | instance (GOrderable f, GOrderable g) => GOrderable (f :+: g) where
148 | L1 _ # R1 _ = true
149 | L1 a # L1 b = a # b
150 | R1 a # R1 b = a # b
151 | R1 _ # L1 _ = false
152 |
153 | L1 _ <=?# R1 _ = true
154 | L1 a <=?# L1 b = a <=?# b
155 | R1 a <=?# R1 b = a <=?# b
156 | R1 _ <=?# L1 _ = false
157 |
158 | instance GOrderable f => GOrderable (M1 i c f) where
159 | M1 x # M1 y = x # y
160 | M1 x <=?# M1 y = x <=?# y
161 |
162 | instance Orderable a => GOrderable (K1 i a) where
163 | K1 a # K1 b = a b
164 | K1 a <=?# K1 b = a <=? b
165 |
166 | -- Boring instances that end up being useful when deriving Orderable with Generics
167 |
168 | instance Orderable () where _ _ = false
169 | _ <=? _ = true
170 | instance Orderable Void where x y = x `seq` y `seq` error "Orderable[Void]."
171 | x <=? y = x `seq` y `seq` error "Orderable[Void].<=?"
172 | instance Orderable Int where x y = bool (x < y)
173 | x <=? y = bool (x <= y)
174 | instance Orderable Integer where x y = bool (x < y)
175 | x <=? y = bool (x <= y)
176 | instance Orderable Natural where x y = bool (x < y)
177 | x <=? y = bool (x <= y)
178 | instance Orderable Word where x y = bool (x < y)
179 | x <=? y = bool (x <= y)
180 | instance Orderable Word8 where x y = bool (x < y)
181 | x <=? y = bool (x <= y)
182 | instance Orderable Word16 where x y = bool (x < y)
183 | x <=? y = bool (x <= y)
184 | instance Orderable Word32 where x y = bool (x < y)
185 | x <=? y = bool (x <= y)
186 | instance Orderable Word64 where x y = bool (x < y)
187 | x <=? y = bool (x <= y)
188 | instance Orderable Int8 where x y = bool (x < y)
189 | x <=? y = bool (x <= y)
190 | instance Orderable Int16 where x y = bool (x < y)
191 | x <=? y = bool (x <= y)
192 | instance Orderable Int32 where x y = bool (x < y)
193 | x <=? y = bool (x <= y)
194 | instance Orderable Int64 where x y = bool (x < y)
195 | x <=? y = bool (x <= y)
196 | instance Orderable Char where x y = bool (x < y)
197 | x <=? y = bool (x <= y)
198 | instance Orderable Float where x y = bool (x < y)
199 | x <=? y = bool (x <= y)
200 | instance Orderable Double where x y = bool (x < y)
201 | x <=? y = bool (x <= y)
202 | instance Orderable Ordering where x y = bool (x < y)
203 | x <=? y = bool (x <= y)
204 | instance Orderable Bool where x y = bool (x < y)
205 | x <=? y = bool (x <= y)
206 |
--------------------------------------------------------------------------------
/src/Ersatz/Relation.hs:
--------------------------------------------------------------------------------
1 | -- | Copyright: Johannes Waldmann, Antonia Swiridoff
2 | -- License: BSD3
3 | --
4 | -- The type @Relation a b@ represents relations
5 | -- between finite subsets of type @a@ and of type @b@.
6 | --
7 | -- A relation is stored internally as @Array (a,b) Bit@,
8 | -- and some methods of @Data.Array@ are provided for managing indices and elements.
9 | --
10 | -- These are rarely needed, because we provide operations and properties
11 | -- in a point-free style, that is, without reference to individual indices and elements.
12 | --
13 | -- Unless otherwise specified, the size of the generated formulas is linear in \( |A| \cdot |B| \),
14 | -- where \(A\) and \(B\) represent the domain and codomain of the involved relation(s).
15 |
16 |
17 | module Ersatz.Relation
18 | ( module Ersatz.Relation.Data
19 | , module Ersatz.Relation.Op
20 | , module Ersatz.Relation.Prop
21 | , module Ersatz.Relation.ARS
22 | ) where
23 |
24 | import Ersatz.Relation.Data
25 | import Ersatz.Relation.Op
26 | import Ersatz.Relation.Prop
27 | import Ersatz.Relation.ARS
28 |
29 |
--------------------------------------------------------------------------------
/src/Ersatz/Relation/ARS.hs:
--------------------------------------------------------------------------------
1 | module Ersatz.Relation.ARS (
2 | -- * Abstract rewriting
3 | terminating, assert_terminating
4 | , peak, valley
5 | , locally_confluent
6 | , confluent, semiconfluent
7 | , convergent, assert_convergent
8 | , point_symmetric
9 | , relative_to
10 | , connected
11 | , is_nf
12 | , nf_property
13 | , unique_nfs, unique_nfs_reduction
14 | )
15 |
16 | where
17 |
18 | import Prelude hiding ( (&&), not, or, and, all, product )
19 |
20 | import Ersatz.Bit
21 | import Ersatz.Equatable
22 | import Ersatz.Problem ( MonadSAT )
23 |
24 | import Ersatz.Relation.Data
25 | import Ersatz.Relation.Op
26 | import Ersatz.Relation.Prop
27 |
28 | import Data.Ix
29 | import Control.Monad ( guard )
30 |
31 |
32 | -- | Tests if a relation \( R \subseteq A \times A \) is terminating, i.e.,
33 | -- there is no infinite sequence \( x_1, x_2, ... \) with \( x_i \in A \)
34 | -- such that \( (x_i, x_{i+1}) \in R \) holds.
35 | --
36 | -- Formula size: linear in \( |A|^3 \)
37 | terminating :: Ix a => Relation a a -> Bit
38 | terminating r = irreflexive $ transitive_closure r
39 |
40 | -- | Monadic version of 'terminating'.
41 | --
42 | -- Note that @assert_terminating@ cannot be used for expressing non-termination of a relation,
43 | -- only for expressing termination.
44 | --
45 | -- Formula size: linear in \( |A|^3 \)
46 | --
47 | -- ==== __Example__
48 | --
49 | -- @
50 | -- example = do
51 | -- result <- 'Ersatz.Solver.solveWith' 'Ersatz.Solver.Minisat.minisat' $ do
52 | -- r <- 'relation' ((0,0),(2,2))
53 | -- 'Ersatz.Bit.assert' $ 'Ersatz.Counting.atleast' 3 $ 'elems' r
54 | -- 'assert_terminating' r
55 | -- return r
56 | -- case result of
57 | -- (Satisfied, Just r) -> do putStrLn $ 'table' r; return True
58 | -- _ -> return False
59 | -- @
60 | assert_terminating :: (Ix a, MonadSAT s m) => Relation a a -> m ()
61 | assert_terminating r = do
62 | s <- relation $ bounds r
63 | assert $ and [
64 | transitive s
65 | , irreflexive s
66 | , implies r s ]
67 |
68 | -- | Constructs the peak \( R^{-1} \circ S \) of two relations
69 | -- \( R, S \subseteq A \times A \).
70 | --
71 | -- Formula size: linear in \( |A|^3 \)
72 | peak :: Ix a => Relation a a -> Relation a a -> Relation a a
73 | peak r = product (mirror r)
74 |
75 | -- | Constructs the valley \( R \circ S^{-1} \) of two relations
76 | -- \( R, S \subseteq A \times A \).
77 | --
78 | -- Formula size: linear in \( |A|^3 \)
79 | valley :: Ix a => Relation a a -> Relation a a -> Relation a a
80 | valley r s = product r (mirror s)
81 |
82 | -- | Tests if a relation \( R \subseteq A \times A \) is locally confluent, i.e.,
83 | -- \( \forall a,b,c \in A: ((a,b) \in R) \land ((a,c) \in R) \rightarrow \exists d \in A: ((b,d) \in R^*) \land ((c,d)\in R^*) \).
84 | --
85 | -- Formula size: linear in \( |A|^3 \)
86 | locally_confluent :: Ix a => Relation a a -> Bit
87 | locally_confluent r =
88 | let r' = transitive_reflexive_closure r
89 | in implies (peak r r) (valley r' r')
90 |
91 | -- | Tests if a relation \( R \subseteq A \times A \) is confluent, i.e.,
92 | -- \( \forall a,b,c \in A: ((a,b) \in R^*) \land ((a,c) \in R^*) \rightarrow \exists d \in A: ((b,d) \in R^*) \land ((c,d)\in R^*) \).
93 | --
94 | -- Formula size: linear in \( |A|^3 \)
95 | confluent :: Ix a => Relation a a -> Bit
96 | confluent r =
97 | let r' = transitive_reflexive_closure r
98 | in implies (peak r' r') (valley r' r')
99 |
100 | -- | Tests if a relation \( R \subseteq A \times A \) is semi-confluent, i.e.,
101 | -- \( \forall a,b,c \in A: ((a,b) \in R) \land ((a,c) \in R^*) \rightarrow \exists d \in A: ((b,d) \in R^*) \land ((c,d)\in R^*) \).
102 | --
103 | -- @semiconfluent@ is equivalent to 'confluent'.
104 | --
105 | -- Formula size: linear in \( |A|^3 \)
106 | semiconfluent :: Ix a => Relation a a -> Bit
107 | semiconfluent r =
108 | let r' = transitive_reflexive_closure r
109 | in implies (peak r r') (valley r' r')
110 |
111 | -- | Tests if a relation \( R \subseteq A \times A \) is convergent, i.e.,
112 | -- \( R \) is 'terminating' and 'confluent'.
113 | --
114 | -- Formula size: linear in \( |A|^3 \)
115 | convergent :: Ix a => Relation a a -> Bit
116 | convergent r = and [terminating r, locally_confluent r]
117 |
118 | -- | Monadic version of 'convergent'.
119 | --
120 | -- Note that @assert_convergent@ cannot be used for expressing non-convergence of a relation,
121 | -- only for expressing convergence.
122 | --
123 | -- Formula size: linear in \( |A|^3 \)
124 | --
125 | -- ==== __Example__
126 | --
127 | -- @
128 | -- example = do
129 | -- result <- 'Ersatz.Solver.solveWith' 'Ersatz.Solver.Minisat.minisat' $ do
130 | -- r <- 'relation' ((0,0),(3,3))
131 | -- 'Ersatz.Bit.assert' $ 'Ersatz.Counting.exactly' 3 $ 'elems' r
132 | -- 'assert_convergent' r
133 | -- 'Ersatz.Bit.assert' $ 'Ersatz.Bit.not' $ 'transitive' r
134 | -- return r
135 | -- case result of
136 | -- (Satisfied, Just r) -> do putStrLn $ 'table' r; return True
137 | -- _ -> return False
138 | -- @
139 | assert_convergent :: (Ix a, MonadSAT s m) => Relation a a -> m ()
140 | assert_convergent r = do
141 | s <- relation $ bounds r
142 | t <- relation $ bounds r
143 | let u = universe r
144 | i = indices r
145 | assert $ and [
146 | transitive s
147 | , irreflexive s
148 | , implies r s
149 | , all (\x -> is_nf x r ==> t ! (x,x)) u
150 | , all (\(x,y) -> s!(x,y) && t!(y,y) ==> t!(x,y)) i
151 | , nor $ do
152 | (x,y) <- i; z <- u; guard $ y /= z
153 | return $ t ! (x,y) && t ! (x,z) ]
154 |
155 | -- | Tests if the matrix representation (i.e. the array) of a relation
156 | -- \( R \subseteq A \times A \) is point symmetric, i.e., for the matrix representation
157 | -- \( \begin{pmatrix} a_{11} & \dots & a_{1n} \\ \vdots & \ddots & \vdots \\ a_{n1} & \dots & a_{nn} \end{pmatrix} \)
158 | -- holds \( a_{ij} = a_{(n-i+1)(n-j+1)} \).
159 | point_symmetric :: Ix a => Relation a a -> Bit
160 | point_symmetric r
161 | | is_homogeneous r = elems r === reverse (elems r)
162 | | otherwise = error "The domain must equal the codomain!"
163 |
164 | -- | Given two relations \( R, S \subseteq A \times A \),
165 | -- construct \( R \) relative to \( S \) defined by \( R/S = S^* \circ R \circ S^* \).
166 | --
167 | -- Formula size: linear in \( |A|^3 \)
168 | relative_to :: Ix a => Relation a a -> Relation a a -> Relation a a
169 | r `relative_to` s =
170 | let s' = transitive_reflexive_closure s
171 | in foldl1 product [ s', r , s' ]
172 |
173 | -- | Tests if a relation \( R \subseteq A \times A \) is connected,
174 | -- i.e., \( (R \cup R^{-1})^* = A \times A \).
175 | --
176 | -- Formula size: linear in \( |A|^3 \)
177 | connected :: Ix a => Relation a a -> Bit
178 | connected r = complete $ equivalence_closure r
179 |
180 | -- | Given an element \( x \in A \) and a relation \( R \subseteq A \times A \),
181 | -- check if \( x \) is a normal form, i.e., \( \forall y \in A: (x,y) \notin R \).
182 | --
183 | -- Formula size: linear in \( |A| \)
184 | is_nf :: Ix a => a -> Relation a a -> Bit
185 | is_nf x r =
186 | let ((_,b),(_,d)) = bounds r
187 | in nor $ map (r !) $ range ((x,b),(x,d))
188 |
189 | -- | Tests if a relation \( R \subseteq A \times A \) has the normal form property,
190 | -- i.e., \( \forall a,b \in A \) holds: if \(b\) is a normal form and
191 | -- \( (a,b) \in (R \cup R^{-1})^{*} \), then \( (a,b) \in R^{*} \).
192 | --
193 | -- Formula size: linear in \( |A|^3 \)
194 | nf_property :: Ix a => Relation a a -> Bit
195 | nf_property r = and $ do
196 | let trc = transitive_reflexive_closure r
197 | ec = equivalence_closure r
198 | (x,y) <- indices r
199 | return $ and [is_nf y r, ec ! (x,y)] ==> trc ! (x,y)
200 |
201 | -- | Tests if a relation \( R \subseteq A \times A \) has the unique normal form property,
202 | -- i.e., \( \forall a,b \in A \) with \( a \neq b \) holds: if \(a\) and \(b\) are normal forms,
203 | -- then \( (a,b) \notin (R \cup R^{-1})^{*} \).
204 | --
205 | -- Formula size: linear in \( |A|^3 \)
206 | unique_nfs :: Ix a => Relation a a -> Bit
207 | unique_nfs r = and $ do
208 | let ec = equivalence_closure r
209 | (x,y) <- indices r
210 | guard $ x < y
211 | return $ and [is_nf x r, is_nf y r] ==> not $ ec ! (x,y)
212 |
213 | -- | Tests if a relation \( R \subseteq A \times A \) has the unique normal form property
214 | -- with respect to reduction, i.e., \( \forall a,b \in A \) with \( a \neq b \) holds:
215 | -- if \(a\) and \(b\) are normal forms, then \( (a,b) \notin ((R^{*})^{-1} \circ R^{*}) \).
216 | --
217 | -- Formula size: linear in \( |A|^3 \)
218 | unique_nfs_reduction :: Ix a => Relation a a -> Bit
219 | unique_nfs_reduction r = and $ do
220 | let trc = transitive_reflexive_closure r
221 | (x,y) <- indices r
222 | guard $ x < y
223 | return $ and [is_nf x r, is_nf y r] ==> not $ peak trc trc ! (x,y)
224 |
--------------------------------------------------------------------------------
/src/Ersatz/Relation/Data.hs:
--------------------------------------------------------------------------------
1 | {-# language TypeFamilies #-}
2 |
3 | module Ersatz.Relation.Data (
4 | -- * The @Relation@ type
5 | Relation
6 | -- * Construction
7 | , relation, symmetric_relation
8 | , build
9 | , buildFrom, buildFromM
10 | , identity
11 | -- * Components
12 | , bounds, (!), indices, assocs, elems
13 | , domain, codomain, universe
14 | , universeSize
15 | , is_homogeneous
16 | , card
17 | -- * Pretty printing
18 | , table
19 | ) where
20 |
21 | import Prelude hiding ( and, (&&), any )
22 |
23 | import Ersatz.Bit
24 | import Ersatz.Bits ( Bits, sumBit )
25 | import Ersatz.Codec
26 | import Ersatz.Variable (exists)
27 | import Ersatz.Problem (MonadSAT)
28 |
29 | import Control.Monad (guard)
30 | import qualified Data.Array as A
31 | import Data.Array ( Array, Ix )
32 |
33 |
34 | -- | @Relation a b@ represents a binary relation \(R \subseteq A \times B \),
35 | -- where the domain \(A\) is a finite subset of the type @a@,
36 | -- and the codomain \(B\) is a finite subset of the type @b@.
37 | --
38 | -- A relation is stored internally as @Array (a,b) Bit@,
39 | -- so @a@ and @b@ have to be instances of 'Ix',
40 | -- and both \(A\) and \(B\) are intervals.
41 |
42 | newtype Relation a b = Relation (Array (a, b) Bit)
43 |
44 | instance (Ix a, Ix b) => Codec (Relation a b) where
45 | type Decoded (Relation a b) = Array (a, b) Bool
46 | decode s (Relation a) = decode s a
47 | encode a = Relation $ encode a
48 |
49 |
50 | -- | @relation ((amin,bmin),(amax,mbax))@ constructs an indeterminate relation \( R \subseteq A \times B \)
51 | -- where \(A\) is @{amin .. amax}@ and \(B\) is @{bmin .. bmax}@.
52 | relation :: ( Ix a, Ix b, MonadSAT s m ) =>
53 | ((a,b),(a,b))
54 | -> m ( Relation a b )
55 | relation bnd = do
56 | pairs <- sequence $ do
57 | p <- A.range bnd
58 | return $ do
59 | x <- exists
60 | return ( p, x )
61 | return $ build bnd pairs
62 |
63 | -- | Constructs an indeterminate relation \( R \subseteq B \times B \)
64 | -- that is symmetric, i.e., \( \forall x, y \in B: ((x,y) \in R) \rightarrow ((y,x) \in R) \).
65 | symmetric_relation ::
66 | (MonadSAT s m, Ix b) =>
67 | ((b, b), (b, b)) -- ^ Since a symmetric relation must be homogeneous, the domain must equal the codomain.
68 | -- Therefore, given bounds @((p,q),(r,s))@, it must hold that @p=q@ and @r=s@.
69 | -> m (Relation b b)
70 | symmetric_relation bnd = do
71 | pairs <- sequence $ do
72 | (p,q) <- A.range bnd
73 | guard $ p <= q
74 | return $ do
75 | x <- exists
76 | return $ ((p,q), x)
77 | : [ ((q,p), x) | p /= q ]
78 | return $ build bnd $ concat pairs
79 |
80 | -- | Constructs a relation \(R \subseteq A \times B \) from a list.
81 | --
82 | -- ==== __Example__
83 | --
84 | -- @
85 | -- r = build ((0,'a'),(1,'b')) [ ((0,'a'), true), ((0,'b'), false)
86 | -- , ((1,'a'), false), ((1,'b'), true) ]
87 | -- @
88 | build :: ( Ix a, Ix b )
89 | => ((a,b),(a,b))
90 | -> [ ((a,b), Bit ) ] -- ^ A list of tuples, where the first element represents an element
91 | -- \( (x,y) \in A \times B \) and the second element is a positive 'Bit'
92 | -- if \( (x,y) \in R \), or a negative 'Bit' if \( (x,y) \notin R \).
93 | -> Relation a b
94 | build bnd pairs = Relation $ A.array bnd pairs
95 |
96 | -- | Constructs a relation \(R \subseteq A \times B \) from a function.
97 | buildFrom :: (Ix a, Ix b)
98 | => ((a,b),(a,b))
99 | -> ((a,b) -> Bit) -- ^ A function that assigns a 'Bit'-value
100 | -- to each element \( (x,y) \in A \times B \).
101 | -> Relation a b
102 | buildFrom bnd p = build bnd $ flip map (A.range bnd) $ \ i -> (i, p i)
103 |
104 | -- | Constructs an indeterminate relation \(R \subseteq A \times B\) from a function.
105 | buildFromM :: (Ix a, Ix b, MonadSAT s m)
106 | => ((a,b),(a,b))
107 | -> ((a,b) -> m Bit)
108 | -> m (Relation a b)
109 | buildFromM bnd p = do
110 | pairs <- sequence $ do
111 | i <- A.range bnd
112 | return $ do
113 | x <- p i
114 | return (i, x)
115 | return $ build bnd pairs
116 |
117 | -- | Constructs the identity relation \(I = \{ (x,x) ~|~ x \in A \} \subseteq A \times A\).
118 | identity :: (Ix a)
119 | => ((a,a),(a,a)) -- ^ Since the identity relation is homogeneous, the domain must equal the codomain.
120 | -- Therefore, given bounds @((p,q),(r,s))@, it must hold that @p=q@ and @r=s@.
121 | -> Relation a a
122 | identity ((a,b),(c,d))
123 | | (a,c) == (b,d) = buildFrom ((a,b),(c,d)) (\ (i,j) -> bool $ i == j)
124 | | otherwise = error "The domain must equal the codomain!"
125 |
126 |
127 | -- | The bounds of the array that correspond to the matrix representation of the given relation.
128 | --
129 | -- ==== __Example__
130 | --
131 | -- >>> r = build ((0,0),(1,1)) [((0,0), false), ((0,1), true), ((1,0), true), ((1,1), false)]
132 | -- >>> bounds r
133 | -- ((0,0),(1,1))
134 | bounds :: (Ix a, Ix b) => Relation a b -> ((a,b),(a,b))
135 | bounds ( Relation r ) = A.bounds r
136 |
137 | -- | The list of indices, where each index represents an element \( (x,y) \in A \times B \)
138 | -- that may be contained in the given relation \(R \subseteq A \times B \).
139 | --
140 | -- ==== __Example__
141 | --
142 | -- >>> r = build ((0,0),(1,1)) [((0,0), false), ((0,1), true), ((1,0), true), ((1,1), false)]
143 | -- >>> indices r
144 | -- [(0,0),(0,1),(1,0),(1,1)]
145 | indices :: (Ix a, Ix b) => Relation a b -> [(a, b)]
146 | indices ( Relation r ) = A.indices r
147 |
148 | -- | The list of tuples for the given relation \(R \subseteq A \times B \),
149 | -- where the first element represents an element \( (x,y) \in A \times B \)
150 | -- and the second element indicates via a 'Bit' , if \( (x,y) \in R \) or not.
151 | --
152 | -- ==== __Example__
153 | --
154 | -- >>> r = build ((0,0),(1,1)) [((0,0), false), ((0,1), true), ((1,0), true), ((1,1), false)]
155 | -- >>> assocs r
156 | -- [((0,0),Var (-1)),((0,1),Var 1),((1,0),Var 1),((1,1),Var (-1))]
157 | assocs :: (Ix a, Ix b) => Relation a b -> [((a, b), Bit)]
158 | assocs ( Relation r ) = A.assocs r
159 |
160 | -- | The list of elements of the array
161 | -- that correspond to the matrix representation of the given relation.
162 | --
163 | -- ==== __Example__
164 | --
165 | -- >>> r = build ((0,0),(1,1)) [((0,0), false), ((0,1), true), ((1,0), true), ((1,1), false))]
166 | -- >>> elems r
167 | -- [Var (-1),Var 1,Var 1,Var (-1)]
168 | elems :: (Ix a, Ix b) => Relation a b -> [Bit]
169 | elems ( Relation r ) = A.elems r
170 |
171 | -- | The 'Bit'-value for a given element \( (x,y) \in A \times B \)
172 | -- and a given relation \(R \subseteq A \times B \) that indicates
173 | -- if \( (x,y) \in R \) or not.
174 | --
175 | -- ==== __Example__
176 | --
177 | -- >>> r = build ((0,0),(1,1)) [((0,0), false), ((0,1), true), ((1,0), true), ((1,1), false))]
178 | -- >>> r ! (0,0)
179 | -- Var (-1)
180 | -- >>> r ! (0,1)
181 | -- Var 1
182 | (!) :: (Ix a, Ix b) => Relation a b -> (a, b) -> Bit
183 | Relation r ! p = r A.! p
184 |
185 | -- | The domain \(A\) of a relation \(R \subseteq A \times B\).
186 | domain :: (Ix a, Ix b) => Relation a b -> [a]
187 | domain r =
188 | let ((x,_),(x',_)) = bounds r
189 | in A.range (x,x')
190 |
191 | -- | The codomain \(B\) of a relation \(R \subseteq A \times B\).
192 | codomain :: (Ix a, Ix b) => Relation a b -> [b]
193 | codomain r =
194 | let ((_,y),(_,y')) = bounds r
195 | in A.range (y,y')
196 |
197 | -- | The universe \(A\) of a relation \(R \subseteq A \times A\).
198 | universe :: Ix a => Relation a a -> [a]
199 | universe r
200 | | is_homogeneous r = domain r
201 | | otherwise = error "Relation is not homogeneous!"
202 |
203 | -- | The size of the universe \(A\) of a relation \(R \subseteq A \times A\).
204 | universeSize :: Ix a => Relation a a -> Int
205 | universeSize r
206 | | is_homogeneous r =
207 | let ((a,_),(c,_)) = bounds r
208 | in A.rangeSize (a,c)
209 | | otherwise = error "Relation is not homogeneous!"
210 |
211 | -- | Tests if a relation is homogeneous, i.e., if the domain is equal to the codomain.
212 | is_homogeneous :: Ix a => Relation a a -> Bool
213 | is_homogeneous r =
214 | let ((a,b),(c,d)) = bounds r
215 | in (a == b) && (c == d)
216 |
217 | -- | The number of pairs \( (x,y) \in R \) for the given relation
218 | -- \( R \subseteq A \times B \).
219 | card :: (Ix a, Ix b) => Relation a b -> Bits
220 | card = sumBit . elems
221 |
222 | -- | Print a satisfying assignment from a SAT solver, where the assignment is interpreted as a relation.
223 | -- @putStrLn $ table \@ corresponds to the matrix representation of this relation.
224 | table :: (Ix a, Ix b)
225 | => Array (a,b) Bool -> String
226 | table r = unlines $ do
227 | let ((a,b),(c,d)) = A.bounds r
228 | x <- A.range (a,c)
229 | return $ unwords $ do
230 | y <- A.range (b,d)
231 | return $ if r A.! (x,y) then "*" else "."
232 |
--------------------------------------------------------------------------------
/src/Ersatz/Relation/Op.hs:
--------------------------------------------------------------------------------
1 | {-# language FlexibleInstances, MultiParamTypeClasses #-}
2 |
3 | module Ersatz.Relation.Op
4 |
5 | (
6 | -- * Operations
7 | mirror
8 | , union
9 | , complement
10 | , difference
11 | , product, power
12 | , intersection
13 | , reflexive_closure
14 | , symmetric_closure
15 | , transitive_closure
16 | , transitive_reflexive_closure
17 | , equivalence_closure
18 | )
19 |
20 | where
21 |
22 | import Ersatz.Relation.Data
23 |
24 | import Prelude hiding ( (&&), (||), and, or, not, product )
25 | import Ersatz.Bit
26 |
27 | import qualified Data.Array as A
28 | import Data.Ix
29 |
30 | -- | Constructs the converse relation \( R^{-1} \) of a relation
31 | -- \( R \subseteq A \times B \), which is defined by \( R^{-1} = \{ (y,x) ~|~ (x,y) \in R \} \subseteq B \times A \).
32 | mirror :: ( Ix a , Ix b ) => Relation a b -> Relation b a
33 | mirror r =
34 | let ((a,b),(c,d)) = bounds r
35 | in build ((b,a),(d,c)) $ do (x,y) <- indices r ; return ((y,x), r!(x,y))
36 |
37 | -- | Constructs the complement relation \( \overline{R} \)
38 | -- of a relation \( R \subseteq A \times B \), which is defined by
39 | -- \( \overline{R} = \{ (x,y) \in A \times B ~|~ (x,y) \notin R \} \).
40 | complement :: ( Ix a , Ix b ) => Relation a b -> Relation a b
41 | complement r =
42 | build (bounds r) $ do i <- indices r ; return ( i, not $ r!i )
43 |
44 | -- | Constructs the difference \( R \setminus S \) of the relations
45 | -- \(R, S \subseteq A \times B \), that contains all elements that are in \(R\) but not in \(S\), i.e.,
46 | -- \( R \setminus S = \{ (x,y) \in R ~|~ (x,y) \notin S \} \).
47 | difference :: ( Ix a , Ix b )
48 | => Relation a b -> Relation a b -> Relation a b
49 | difference r s =
50 | intersection r $ complement s
51 |
52 | -- | Constructs the union \( R \cup S \) of the relations \( R, S \subseteq A \times B \).
53 | union :: ( Ix a , Ix b )
54 | => Relation a b -> Relation a b -> Relation a b
55 | union r s
56 | | bounds r == bounds s = build ( bounds r ) $ do
57 | i <- indices r
58 | return (i, r!i || s!i)
59 | | otherwise = error "Relations don't have the same bounds!"
60 |
61 | -- | Constructs the composition \( R \circ S \) of the relations
62 | -- \( R \subseteq A \times B \) and \( S \subseteq B \times C \), which is
63 | -- defined by \( R \circ S = \{ (a,c) ~|~ (a,b) \in R \land (b,c) \in S \} \).
64 | --
65 | -- Formula size: linear in \(|A|\cdot|B|\cdot|C|\)
66 | product :: ( Ix a , Ix b, Ix c )
67 | => Relation a b -> Relation b c -> Relation a c
68 | product a b =
69 | let ((ao,al),(au,ar)) = bounds a
70 | ((bo,bl),(bu,br)) = bounds b
71 | bnd = ((ao,bl),(au,br))
72 | in if (al,ar) == (bo,bu)
73 | then build bnd $ do
74 | i@(x,z) <- range bnd
75 | return (i, or $ do
76 | y <- range ( al, ar )
77 | return $ and [ a!(x,y), b!(y,z) ]
78 | )
79 | else error "Codomain of first relation must equal domain of second relation!"
80 |
81 | -- | Constructs the relation \( R^{n} \) that results if a relation
82 | -- \( R \subseteq A \times A \) is composed \(n\) times with itself.
83 | --
84 | -- \( R^{0} \) is the identity relation \( I = \{ (x,x) ~|~ x \in A \} \).
85 | --
86 | -- Formula size: linear in \( |A|^3 \cdot \log n \)
87 | power :: ( Ix a ) => Int -> Relation a a -> Relation a a
88 | power 0 r = identity ( bounds r )
89 | power 1 r = r
90 | power e r =
91 | let (d,m) = divMod e 2
92 | s = power d r
93 | s2 = product s s
94 | in case m of
95 | 0 -> s2
96 | _ -> product s2 r
97 |
98 | -- | Constructs the intersection \( R \cap S \) of the relations \( R, S \subseteq A \times B \).
99 | intersection :: ( Ix a , Ix b )
100 | => Relation a b -> Relation a b
101 | -> Relation a b
102 | intersection r s
103 | | bounds r == bounds s = build ( bounds r ) $ do
104 | i <- indices r
105 | return (i, and [ r!i, s!i ] )
106 | | otherwise = error "Relations don't have the same bounds!"
107 |
108 | -- | Constructs the reflexive closure \( R \cup R^{0} \) of the relation
109 | -- \( R \subseteq A \times A \).
110 | reflexive_closure :: Ix a => Relation a a -> Relation a a
111 | reflexive_closure t =
112 | union t $ identity $ bounds t
113 |
114 | -- | Constructs the symmetric closure \( R \cup R^{-1} \) of the relation
115 | -- \( R \subseteq A \times A \).
116 | symmetric_closure :: Ix a => Relation a a -> Relation a a
117 | symmetric_closure r =
118 | union r $ mirror r
119 |
120 | -- | Constructs the transitive closure \( R^{+} \) of the relation
121 | -- \( R \subseteq A \times A \), which is defined by
122 | -- \( R^{+} = \bigcup^{\infty}_{i = 1} R^{i} \).
123 | --
124 | -- Formula size: linear in \( |A|^3 \)
125 | transitive_closure :: Ix a => Relation a a -> Relation a a
126 | transitive_closure r =
127 | let n = universeSize r
128 | -- @a' ! (0,p,q)@ is true if and only if @r ! (p,q)@ is true
129 | a' = A.listArray ((0,1,1),(n,n,n)) (elems r)
130 | -- @a ! (0,p,q)@ is true if and only if @a' ! (0,p,q)@ is true
131 | a = a' A.// do
132 | -- If x > 0, then @a ! (p,x,q)@ is true if and only if there is a path from p to q via nodes {1,...,x} in r
133 | i@(x,p,q) <- A.range ((1,1,1),(n,n,n))
134 | return (i, a A.! (x-1,p,q) || a A.! (x-1,p,x) && a A.! (x-1,x,q))
135 | in build (bounds r) $ zip (indices r) [a A.! i | i <- A.range ((n,1,1),(n,n,n))]
136 |
137 | -- | Constructs the transitive reflexive closure \( R^{*} \) of the relation
138 | -- \( R \subseteq A \times A \), which is defined by
139 | -- \( R^{*} = \bigcup^{\infty}_{i = 0} R^{i} \).
140 | --
141 | -- Formula size: linear in \( |A|^3 \)
142 | transitive_reflexive_closure :: Ix a => Relation a a -> Relation a a
143 | transitive_reflexive_closure r =
144 | union (transitive_closure r) (identity $ bounds r)
145 |
146 | -- | Constructs the equivalence closure \( (R \cup R^{-1})^* \) of the relation
147 | -- \( R \subseteq A \times A \).
148 | --
149 | -- Formula size: linear in \( |A|^3 \)
150 | equivalence_closure :: Ix a => Relation a a -> Relation a a
151 | equivalence_closure r =
152 | transitive_reflexive_closure $ symmetric_closure r
153 |
--------------------------------------------------------------------------------
/src/Ersatz/Relation/Prop.hs:
--------------------------------------------------------------------------------
1 | {-# OPTIONS_GHC -Wno-orphans #-}
2 | module Ersatz.Relation.Prop
3 |
4 | (
5 | -- * Properties
6 | implies
7 | , symmetric
8 | , anti_symmetric
9 | , transitive
10 | , irreflexive
11 | , reflexive
12 | , regular
13 | , regular_in_degree
14 | , regular_out_degree
15 | , max_in_degree
16 | , min_in_degree
17 | , max_out_degree
18 | , min_out_degree
19 | , empty
20 | , complete
21 | , total
22 | , disjoint
23 | )
24 |
25 | where
26 |
27 | import Prelude hiding ( and, or, not, product )
28 | import Ersatz.Bit
29 | import Ersatz.Relation.Data
30 | import Ersatz.Relation.Op
31 | import Ersatz.Counting
32 | import Ersatz.Equatable
33 |
34 | import Data.Ix
35 |
36 |
37 | instance (Ix a, Ix b) => Equatable (Relation a b) where
38 | r === s = and [implies r s, implies s r]
39 | r /== s = not $ r === s
40 |
41 | -- | Given two relations \( R, S \subseteq A \times B \), check if \(R\) is a subset of \(S\).
42 | implies :: ( Ix a, Ix b )
43 | => Relation a b -> Relation a b -> Bit
44 | implies r s
45 | | bounds r == bounds s = and $ do
46 | i <- indices r
47 | return $ (r ! i) ==> (s ! i)
48 | | otherwise = error "Relations don't have the same bounds!"
49 |
50 | -- | Tests if a relation is empty, i.e., the relation doesn't contain any elements.
51 | empty :: ( Ix a, Ix b )
52 | => Relation a b -> Bit
53 | empty r = and $ do
54 | i <- indices r
55 | return $ not $ r ! i
56 |
57 | -- | Tests if a relation \( R \subseteq A \times B \) is complete,
58 | -- i.e., \(R = A \times B \).
59 | complete :: (Ix a, Ix b) => Relation a b -> Bit
60 | complete r = empty $ complement r
61 |
62 | -- | Tests if a relation \( R \subseteq A \times A \) is strongly connected, i.e.,
63 | -- \( R \cup R^{-1} = A \times A \).
64 | total :: ( Ix a ) => Relation a a -> Bit
65 | total r = complete $ symmetric_closure r
66 |
67 | -- | Tests if two relations are disjoint, i.e.,
68 | -- there is no element that is contained in both relations.
69 | disjoint :: (Ix a, Ix b) => Relation a b -> Relation a b -> Bit
70 | disjoint r s = empty $ intersection r s
71 |
72 | -- | Tests if a relation \( R \subseteq A \times A \) is symmetric,
73 | -- i.e., \( R \cup R^{-1} = R \).
74 | symmetric :: ( Ix a ) => Relation a a -> Bit
75 | symmetric r = implies r ( mirror r )
76 |
77 |
78 | -- | Tests if a relation \( R \subseteq A \times A \) is antisymmetric,
79 | -- i.e., \( R \cap R^{-1} \subseteq R^{0} \).
80 | anti_symmetric :: ( Ix a ) => Relation a a -> Bit
81 | anti_symmetric r = implies (intersection r (mirror r)) (identity (bounds r))
82 |
83 | -- | Tests if a relation \( R \subseteq A \times A \) is irreflexive, i.e.,
84 | -- \( R \cap R^{0} = \emptyset \).
85 | irreflexive :: ( Ix a ) => Relation a a -> Bit
86 | irreflexive r = empty $ intersection (identity $ bounds r) r
87 |
88 | -- | Tests if a relation \( R \subseteq A \times A \) is reflexive, i.e.,
89 | -- \( R^{0} \subseteq R \).
90 | reflexive :: ( Ix a ) => Relation a a -> Bit
91 | reflexive r = implies (identity $ bounds r) r
92 |
93 | -- | Given an 'Int' \( n \) and a relation \( R \subseteq A \times B \), check if
94 | -- \( \forall x \in A: | \{ (x,y) \in R \} | = n \) and
95 | -- \( \forall y \in B: | \{ (x,y) \in R \} | = n \) hold.
96 | regular :: (Ix a, Ix b) => Int -> Relation a b -> Bit
97 |
98 | -- | Given an 'Int' \( n \) and a relation \( R \subseteq A \times B \), check if
99 | -- \( \forall y \in B: | \{ (x,y) \in R \} | = n \) holds.
100 | regular_in_degree :: (Ix a, Ix b) => Int -> Relation a b -> Bit
101 |
102 | -- | Given an 'Int' \( n \) and a relation \( R \subseteq A \times B \), check if
103 | -- \( \forall x \in A: | \{ (x,y) \in R \} | = n \) holds.
104 | regular_out_degree :: (Ix a, Ix b) => Int -> Relation a b -> Bit
105 |
106 | -- | Given an 'Int' \( n \) and a relation \( R \subseteq A \times B \), check if
107 | -- \( \forall y \in B: | \{ (x,y) \in R \} | \leq n \) holds.
108 | max_in_degree :: (Ix a, Ix b) => Int -> Relation a b -> Bit
109 |
110 | -- | Given an 'Int' \( n \) and a relation \( R \subseteq A \times B \), check if
111 | -- \( \forall y \in B: | \{ (x,y) \in R \} | \geq n \) holds.
112 | min_in_degree :: (Ix a, Ix b) => Int -> Relation a b -> Bit
113 |
114 | -- | Given an 'Int' \( n \) and a relation \( R \subseteq A \times B \), check if
115 | -- \( \forall x \in A: | \{ (x,y) \in R \} | \leq n \) holds.
116 | max_out_degree :: (Ix a, Ix b) => Int -> Relation a b -> Bit
117 |
118 | -- | Given an 'Int' \( n \) and a relation \( R \subseteq A \times B \), check if
119 | -- \( \forall x \in A: | \{ (x,y) \in R \} | \geq n \) holds.
120 | min_out_degree :: (Ix a, Ix b) => Int -> Relation a b -> Bit
121 |
122 | regular deg r = and [ regular_in_degree deg r, regular_out_degree deg r ]
123 |
124 | regular_out_degree = out_degree_helper exactly
125 | max_out_degree = out_degree_helper atmost
126 | min_out_degree = out_degree_helper atleast
127 | regular_in_degree deg r = regular_out_degree deg $ mirror r
128 | max_in_degree deg r = max_out_degree deg $ mirror r
129 | min_in_degree deg r = min_out_degree deg $ mirror r
130 |
131 | out_degree_helper ::
132 | (Boolean b, Ix b1, Ix a) =>
133 | (t -> [Bit] -> b) -> t -> Relation a b1 -> b
134 | out_degree_helper f deg r = and $ do
135 | let ((a,b),(c,d)) = bounds r
136 | x <- range ( a , c )
137 | return $ f deg $ do
138 | y <- range (b,d)
139 | return $ r ! (x,y)
140 |
141 | -- | Tests if a relation \( R \subseteq A \times A \) is transitive, i.e.,
142 | -- \( R \circ R = R \).
143 | --
144 | -- Formula size: linear in \( |A|^3 \)
145 | transitive :: ( Ix a )
146 | => Relation a a -> Bit
147 | transitive r = implies (product r r) r
148 |
149 |
--------------------------------------------------------------------------------
/src/Ersatz/Solution.hs:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------
2 | -- |
3 | -- Copyright : © Edward Kmett 2010-2014, Johan Kiviniemi 2013
4 | -- License : BSD3
5 | -- Maintainer: Edward Kmett
6 | -- Stability : experimental
7 | -- Portability: non-portable
8 | --
9 | --------------------------------------------------------------------
10 | module Ersatz.Solution
11 | ( Solution(..), solutionFrom
12 | , Result(..)
13 | , Solver
14 | ) where
15 |
16 | import Control.Lens
17 | import qualified Data.HashMap.Lazy as HashMap
18 | import Data.IntMap (IntMap)
19 | import qualified Data.IntMap.Strict as IntMap
20 | import Data.Ix
21 | import Ersatz.Internal.Literal
22 | import Ersatz.Problem
23 | import System.Mem.StableName (StableName)
24 |
25 | data Solution = Solution
26 | { solutionLiteral :: Literal -> Maybe Bool
27 | -- ^ If a 'Literal' is uniquely assigned to a particular value, this will
28 | -- return 'Just' of that value. If a 'Literal' is unconstrained (i.e., it
29 | -- can be assigned either 'True' or 'False'), this will return 'Nothing'.
30 | , solutionStableName :: StableName () -> Maybe Bool
31 | }
32 |
33 | solutionFrom :: HasSAT s => IntMap Bool -> s -> Solution
34 | solutionFrom litMap qbf = Solution lookupLit lookupSN
35 | where
36 | lookupLit l | i >= 0 = IntMap.lookup i litMap
37 | | otherwise = not <$> IntMap.lookup (-i) litMap
38 | where i = literalId l
39 |
40 | lookupSN sn = lookupLit =<< HashMap.lookup sn snMap
41 |
42 | snMap = qbf^.stableMap
43 |
44 | data Result
45 | = Unsolved
46 | | Unsatisfied
47 | | Satisfied
48 | deriving (Eq,Ord,Ix,Show,Read)
49 |
50 | instance Enum Result where
51 | fromEnum Unsolved = -1
52 | fromEnum Unsatisfied = 0
53 | fromEnum Satisfied = 1
54 |
55 | toEnum (-1) = Unsolved
56 | toEnum 0 = Unsatisfied
57 | toEnum 1 = Satisfied
58 | toEnum _ = error "Enum.toEnum {Ersatz.Solution.Result}: argument of out range"
59 |
60 | instance Bounded Result where
61 | minBound = Unsolved
62 | maxBound = Satisfied
63 |
64 | -- | A @'Solver' s m@ is responsible for invoking a solver and
65 | -- returning a 'Result' and a map of determined results.
66 | --
67 | -- * @s@ is typically 'SAT' or 'QSAT'
68 | --
69 | -- * @m@ is typically 'IO'
70 | type Solver s m = s -> m (Result, IntMap Bool)
71 |
--------------------------------------------------------------------------------
/src/Ersatz/Solver.hs:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------
2 | -- |
3 | -- Copyright : © Edward Kmett 2010-2014, Johan Kiviniemi 2013
4 | -- License : BSD3
5 | -- Maintainer: Edward Kmett
6 | -- Stability : experimental
7 | -- Portability: non-portable
8 | --
9 | --------------------------------------------------------------------
10 | module Ersatz.Solver
11 | ( module Ersatz.Solver.DepQBF
12 | , module Ersatz.Solver.Kissat
13 | , module Ersatz.Solver.Lingeling
14 | , module Ersatz.Solver.Minisat
15 | , module Ersatz.Solver.Z3
16 | , solveWith
17 | ) where
18 |
19 | import Control.Monad.State
20 | import Data.Default
21 | import Ersatz.Codec
22 | import Ersatz.Problem
23 | import Ersatz.Solution
24 | import Ersatz.Solver.DepQBF
25 | import Ersatz.Solver.Kissat
26 | import Ersatz.Solver.Lingeling
27 | import Ersatz.Solver.Minisat
28 | import Ersatz.Solver.Z3
29 |
30 | -- | @'solveWith' solver prob@ solves a SAT problem @prob@ with the given
31 | -- @solver@. It returns a pair consisting of:
32 | --
33 | -- 1. A 'Result' that indicates if @prob@ is satisfiable ('Satisfied'),
34 | -- unsatisfiable ('Unsatisfied'), or if the solver could not determine any
35 | -- results ('Unsolved').
36 | --
37 | -- 2. A 'Decoded' answer that was decoded using the solution to @prob@. Note
38 | -- that this answer is only meaningful if the 'Result' is 'Satisfied' and
39 | -- the answer value is in a 'Just'.
40 | --
41 | -- Here is a small example of how to use 'solveWith':
42 | --
43 | -- @
44 | -- import Ersatz
45 | --
46 | -- main :: IO ()
47 | -- main = do
48 | -- res <- 'solveWith' minisat $ do
49 | -- (b1 :: Bit) <- exists
50 | -- (b2 :: Bit) <- exists
51 | -- assert (b1 === b2)
52 | -- pure [b1, b2]
53 | -- case res of
54 | -- (Satisfied, Just answer) -> print answer
55 | -- _ -> fail "Could not solve problem"
56 | -- @
57 | --
58 | -- Depending on the whims of @minisat@, this program may print either
59 | -- @[False, False]@ or @[True, True]@.
60 | solveWith ::
61 | (Monad m, HasSAT s, Default s, Codec a) =>
62 | Solver s m -> StateT s m a -> m (Result, Maybe (Decoded a))
63 | solveWith solver m = do
64 | (a, problem) <- runStateT m def
65 | (res, litMap) <- solver problem
66 | return (res, decode (solutionFrom litMap problem) a)
67 |
--------------------------------------------------------------------------------
/src/Ersatz/Solver/Common.hs:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------
2 | -- |
3 | -- Copyright : © Edward Kmett 2010-2014, Johan Kiviniemi 2013
4 | -- License : BSD3
5 | -- Maintainer: Edward Kmett
6 | -- Stability : experimental
7 | -- Portability: non-portable
8 | --
9 | --------------------------------------------------------------------
10 | module Ersatz.Solver.Common
11 | ( withTempFiles
12 | , resultOf
13 |
14 | -- * Support for trying many solvers
15 | , trySolvers
16 | , NoSolvers(..)
17 |
18 | , parseSolution5
19 | ) where
20 |
21 | import Control.Exception (Exception(..), throwIO)
22 | import Control.Monad.IO.Class
23 | import Ersatz.Solution
24 | import System.Exit (ExitCode(..))
25 | import System.IO.Error (tryIOError)
26 | import System.IO.Temp (withSystemTempDirectory)
27 | import Data.IntMap (IntMap)
28 | import qualified Data.IntMap.Strict as IntMap
29 |
30 | withTempFiles :: MonadIO m
31 | => FilePath -- ^ Problem file extension including the dot, if any
32 | -> FilePath -- ^ Solution file extension including the dot, if any
33 | -> (FilePath -> FilePath -> IO a) -> m a
34 | withTempFiles problemExt solutionExt f = liftIO $
35 | withSystemTempDirectory "ersatz" $ \dir -> do
36 | let problemPath = dir ++ "/problem" ++ problemExt
37 | solutionPath = dir ++ "/solution" ++ solutionExt
38 |
39 | f problemPath solutionPath
40 |
41 | resultOf :: ExitCode -> Result
42 | resultOf (ExitFailure 10) = Satisfied
43 | resultOf (ExitFailure 20) = Unsatisfied
44 | resultOf _ = Unsolved
45 |
46 | -- | This error is thrown by 'trySolvers' when no solvers are found.
47 | newtype NoSolvers = NoSolvers [IOError] deriving Show
48 |
49 | instance Exception NoSolvers where
50 | displayException _ = "no ersatz solvers were found"
51 |
52 | -- | Try a list of solvers in order. When a solver fails due to
53 | -- a missing executable the next solver will be tried. Throws
54 | -- 'NoSolvers' exception if none of the given solvers were installed.
55 | trySolvers :: [Solver s IO] -> Solver s IO
56 | trySolvers solvers problem = foldr runSolver noSolvers solvers []
57 | where
58 | noSolvers = throwIO . NoSolvers . reverse
59 |
60 | runSolver solver next es =
61 | do res <- tryIOError (solver problem)
62 | case res of
63 | Left e -> next (e:es)
64 | Right x -> return x
65 |
66 | parseSolution5 :: String -> IntMap Bool
67 | parseSolution5 txt = IntMap.fromList [(abs v, v > 0) | v <- vars, v /= 0]
68 | where
69 | vlines = [l | ('v':l) <- lines txt]
70 | vars = map read (foldMap words vlines)
71 |
--------------------------------------------------------------------------------
/src/Ersatz/Solver/DepQBF.hs:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------
2 | -- |
3 | -- Copyright : © Edward Kmett 2010-2014, Johan Kiviniemi 2013
4 | -- License : BSD3
5 | -- Maintainer: Edward Kmett
6 | -- Stability : experimental
7 | -- Portability: non-portable
8 | --
9 | -- is a solver capable of
10 | -- solving quantified boolean formulae ('QBF').
11 | --------------------------------------------------------------------
12 | module Ersatz.Solver.DepQBF
13 | ( depqbf
14 | , depqbfPath
15 | , depqbfPathArgs
16 | ) where
17 |
18 | import Control.Monad.IO.Class
19 | import Data.Version (Version, makeVersion, parseVersion)
20 | import Ersatz.Problem ( QSAT, writeQdimacs' )
21 | import Ersatz.Solution
22 | import Ersatz.Solver.Common
23 | import qualified Data.IntMap as I
24 | import System.Exit (ExitCode(..))
25 | import System.Process (readProcessWithExitCode)
26 | import qualified Text.ParserCombinators.ReadP as P
27 |
28 | -- | This is a 'Solver' for 'QSAT' problems that runs the @depqbf@ solver using
29 | -- the current @PATH@, it tries to run an executable named @depqbf@.
30 | depqbf :: MonadIO m => Solver QSAT m
31 | depqbf = depqbfPath "depqbf"
32 |
33 | parseLiteral :: String -> (Int, Bool)
34 | parseLiteral ('-':xs) = (read xs, False)
35 | parseLiteral xs = (read xs, True)
36 |
37 | -- Parse the QDIMACS output format, which is described in
38 | -- http://www.qbflib.org/qdimacs.html#output
39 | parseOutput :: String -> [(Int, Bool)]
40 | parseOutput out =
41 | case filter (not . comment) $ lines out of
42 | (_preamble:certLines) -> map parseCertLine certLines
43 | [] -> error "QDIMACS output without preamble"
44 | where
45 | comment [] = True
46 | comment ('c' : _) = True
47 | comment _ = False
48 |
49 | parseCertLine :: String -> (Int, Bool)
50 | parseCertLine certLine =
51 | case words certLine of
52 | (_v:lit:_) -> parseLiteral lit
53 | _ -> error $ "Malformed QDIMACS certificate line: " ++ certLine
54 |
55 | -- | This is a 'Solver' for 'QSAT' problems that lets you specify the path to the @depqbf@ executable.
56 | -- This passes different arguments to @depqbf@ depending on its version:
57 | --
58 | -- * If using version 6.03 or later, this passes @[\"--qdo\", \"--no-dynamic-nenofex\"]@.
59 | --
60 | -- * Otherwise, this passes @[\"--qdo\"]@.
61 | depqbfPath :: MonadIO m => FilePath -> Solver QSAT m
62 | depqbfPath path problem = do
63 | ver <- liftIO $ depqbfVersion path
64 | let args | ver >= makeVersion [6,03]
65 | = [ "--qdo", "--no-dynamic-nenofex" ]
66 | | otherwise
67 | = [ "--qdo" ]
68 | depqbfPathArgs path args problem
69 |
70 | -- | This is a 'Solver' for 'QSAT' problems that lets you specify the path to the @depqbf@ executable
71 | -- as well as a list of command line arguments. They will appear after the problem file name.
72 | depqbfPathArgs :: MonadIO m => FilePath -> [String] -> Solver QSAT m
73 | depqbfPathArgs path args problem = liftIO $
74 | withTempFiles ".cnf" "" $ \problemPath _ -> do
75 | writeQdimacs' problemPath problem
76 |
77 | (exit, out, _err) <-
78 | readProcessWithExitCode path (problemPath : args) []
79 |
80 | let result = resultOf exit
81 |
82 | return $ (,) result $
83 | case result of
84 | Satisfied ->
85 | I.fromList $ parseOutput out
86 | _ ->
87 | I.empty
88 |
89 | -- | Query @depqbf@'s 'Version' by invoking @depqbf --version@ and parsing the
90 | -- output. This assumes that the output can be parsed as a valid 'Version' and
91 | -- that @depqbf@ versions increase in a way that is compatible with the
92 | -- 'Ord Version' instance (see 'depqbfPath', which compares 'Version's using
93 | -- ('>=')).
94 | depqbfVersion :: FilePath -> IO Version
95 | depqbfVersion path = do
96 | (exit, out, err) <-
97 | readProcessWithExitCode path ["--version"] []
98 |
99 | let parseError reason =
100 | fail $ unlines
101 | [ "Could not query depqbf version (" ++ reason ++ ")"
102 | , "Standard output:"
103 | , out
104 | , ""
105 | , "Standard error:"
106 | , err
107 | ]
108 |
109 | case exit of
110 | ExitSuccess -> do
111 | -- Should be something like "DepQBF 6.03"
112 | verStrLine <-
113 | case lines err of
114 | line:_ -> pure line
115 | [] -> parseError "no lines of standard error"
116 | -- Should be something like "6.03"
117 | verStr <-
118 | case words verStrLine of
119 | _depQBF:ver:_ -> pure ver
120 | _ -> parseError $ "unexpected version number " ++ verStrLine
121 | -- Convert the string to a full Version
122 | case readEitherP parseVersion verStr of
123 | Left reason -> parseError reason
124 | Right v -> pure v
125 | ExitFailure i ->
126 | parseError $ "exit code " ++ show i ++ ")"
127 |
128 | -- | Like @readEither@ from "Text.Read", but accepting an arbitrary 'P.ReadP'
129 | -- argument instead of requiring a 'Read' constraint.
130 | readEitherP :: P.ReadP a -> String -> Either String a
131 | readEitherP rp s =
132 | case [ x | (x,"") <- P.readP_to_S read' s ] of
133 | [x] -> Right x
134 | [] -> Left "no parse"
135 | _ -> Left "ambiguous parse"
136 | where
137 | read' = do
138 | x <- rp
139 | P.skipSpaces
140 | pure x
141 |
--------------------------------------------------------------------------------
/src/Ersatz/Solver/Kissat.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE OverloadedStrings #-}
2 |
3 | module Ersatz.Solver.Kissat
4 | ( kissat
5 | , kissatPath
6 | ) where
7 |
8 | import Control.Monad.IO.Class
9 | ( MonadIO ( liftIO
10 | )
11 | )
12 | import Ersatz.Problem
13 | ( SAT
14 | , writeDimacs'
15 | )
16 | import Ersatz.Solution
17 | ( Solver
18 | )
19 | import Ersatz.Solver.Common
20 | ( resultOf
21 | , withTempFiles
22 | , parseSolution5
23 | )
24 | import System.Process
25 | ( readProcessWithExitCode
26 | )
27 |
28 |
29 | -- | 'Solver' for 'SAT' problems that tries to invoke the @kissat@ executable
30 | -- from the @PATH@.
31 | kissat :: MonadIO m => Solver SAT m
32 | kissat = kissatPath "kissat"
33 |
34 | -- | 'Solver' for 'SAT' problems that tries to invoke a program that takes
35 | -- @kissat@ compatible arguments.
36 | --
37 | -- The 'FilePath' refers to the path to the executable.
38 | kissatPath :: MonadIO m => FilePath -> Solver SAT m
39 | kissatPath path problem = liftIO $
40 | withTempFiles ".cnf" "" $ \problemPath _ -> do
41 | writeDimacs' problemPath problem
42 |
43 | (exit, out, _err) <-
44 | readProcessWithExitCode path
45 | [problemPath]
46 | []
47 |
48 | let sol = parseSolution5 out
49 |
50 | return (resultOf exit, sol)
51 |
--------------------------------------------------------------------------------
/src/Ersatz/Solver/Lingeling.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE OverloadedStrings #-}
2 |
3 | module Ersatz.Solver.Lingeling
4 | ( lingeling
5 | , plingeling
6 | , treengeling
7 | , lingelingPath
8 | , plingelingPath
9 | , treengelingPath
10 | ) where
11 |
12 | import Control.Monad.IO.Class
13 | ( MonadIO ( liftIO
14 | )
15 | )
16 | import Ersatz.Problem
17 | ( SAT
18 | , writeDimacs'
19 | )
20 | import Ersatz.Solution
21 | ( Solver
22 | )
23 | import Ersatz.Solver.Common
24 | ( resultOf
25 | , withTempFiles
26 | , parseSolution5
27 | )
28 | import System.Process
29 | ( readProcessWithExitCode
30 | )
31 |
32 | -- | 'Solver' for 'SAT' problems that tries to invoke the @lingeling@ executable
33 | -- from the @PATH@.
34 | lingeling :: MonadIO m => Solver SAT m
35 | lingeling = lingelingPath "lingeling"
36 |
37 | -- | 'Solver' for 'SAT' problems that tries to invoke the @plingeling@ executable
38 | -- from the @PATH@.
39 | plingeling :: MonadIO m => Solver SAT m
40 | plingeling = ngelingPath "plingeling"
41 |
42 | -- | 'Solver' for 'SAT' problems that tries to invoke the @treengeling@ executable
43 | -- from the @PATH@.
44 | treengeling :: MonadIO m => Solver SAT m
45 | treengeling = ngelingPath "treengeling"
46 |
47 | -- | 'Solver' for 'SAT' problems that tries to invoke a program that takes
48 | -- @lingeling@ compatible arguments.
49 | --
50 | -- The 'FilePath' refers to the path to the executable.
51 | lingelingPath :: MonadIO m => FilePath -> Solver SAT m
52 | lingelingPath = ngelingPath
53 |
54 | -- | 'Solver' for 'SAT' problems that tries to invoke a program that takes
55 | -- @plingeling@ compatible arguments.
56 | --
57 | -- The 'FilePath' refers to the path to the executable.
58 | plingelingPath :: MonadIO m => FilePath -> Solver SAT m
59 | plingelingPath = ngelingPath
60 |
61 | -- | 'Solver' for 'SAT' problems that tries to invoke a program that takes
62 | -- @treengeling@ compatible arguments.
63 | --
64 | -- The 'FilePath' refers to the path to the executable.
65 | treengelingPath :: MonadIO m => FilePath -> Solver SAT m
66 | treengelingPath = ngelingPath
67 |
68 | -- | 'Solver' for 'SAT' problems that tries to invoke a program that takes
69 | -- @*ngeling@ compatible arguments.
70 | --
71 | -- The 'FilePath' refers to the path to the executable.
72 | ngelingPath :: MonadIO m => FilePath -> Solver SAT m
73 | ngelingPath path problem = liftIO $
74 | withTempFiles ".cnf" "" $ \problemPath _ -> do
75 | writeDimacs' problemPath problem
76 |
77 | (exit, out, _err) <-
78 | readProcessWithExitCode path
79 | [problemPath]
80 | []
81 |
82 | let sol = parseSolution5 out
83 |
84 | return (resultOf exit, sol)
85 |
--------------------------------------------------------------------------------
/src/Ersatz/Solver/Minisat.hs:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------
2 | -- |
3 | -- Copyright : © Edward Kmett 2010-2014, Johan Kiviniemi 2013
4 | -- License : BSD3
5 | -- Maintainer: Edward Kmett
6 | -- Stability : experimental
7 | -- Portability: non-portable
8 | --
9 | --------------------------------------------------------------------
10 |
11 | {-# language OverloadedStrings #-}
12 |
13 | module Ersatz.Solver.Minisat
14 | ( minisat
15 | , cryptominisat
16 | , minisatPath
17 | , cryptominisat5
18 | , cryptominisat5Path
19 | , anyminisat
20 | ) where
21 |
22 | import Control.Exception (IOException, handle)
23 | import Control.Monad.IO.Class
24 | import Data.IntMap (IntMap)
25 | import Ersatz.Problem ( SAT, writeDimacs' )
26 | import Ersatz.Solution
27 | import Ersatz.Solver.Common
28 | import qualified Data.IntMap.Strict as IntMap
29 | import System.Process (readProcessWithExitCode)
30 |
31 | import qualified Data.ByteString.Char8 as B
32 | import qualified Data.List as List ( foldl' )
33 |
34 | -- | Hybrid 'Solver' that tries to use: 'cryptominisat5', 'cryptominisat', and 'minisat'
35 | anyminisat :: Solver SAT IO
36 | anyminisat = trySolvers [cryptominisat5, cryptominisat, minisat]
37 |
38 | -- | 'Solver' for 'SAT' problems that tries to invoke the @minisat@ executable from the @PATH@
39 | minisat :: MonadIO m => Solver SAT m
40 | minisat = minisatPath "minisat"
41 |
42 | -- | 'Solver' for 'SAT' problems that tries to invoke the @cryptominisat@ executable from the @PATH@
43 | cryptominisat :: MonadIO m => Solver SAT m
44 | cryptominisat = minisatPath "cryptominisat"
45 |
46 | -- | 'Solver' for 'SAT' problems that tries to invoke a program that takes @minisat@ compatible arguments.
47 | --
48 | -- The 'FilePath' refers to the path to the executable.
49 | minisatPath :: MonadIO m => FilePath -> Solver SAT m
50 | minisatPath path problem = liftIO $
51 | withTempFiles ".cnf" "" $ \problemPath solutionPath -> do
52 | writeDimacs' problemPath problem
53 |
54 | (exit, _out, _err) <-
55 | readProcessWithExitCode path [problemPath, solutionPath] []
56 |
57 | sol <- parseSolutionFile solutionPath
58 |
59 | return (resultOf exit, sol)
60 |
61 | parseSolutionFile :: FilePath -> IO (IntMap Bool)
62 | parseSolutionFile path = handle handler (parseSolution <$> B.readFile path)
63 | where
64 | handler :: IOException -> IO (IntMap Bool)
65 | handler _ = return IntMap.empty
66 |
67 | parseSolution :: B.ByteString -> IntMap Bool
68 | parseSolution s =
69 | case B.words s of
70 | x : ys | x == "SAT" ->
71 | List.foldl'
72 | ( \ m y -> case B.readInt y of
73 | Just (v,_) -> if 0 == v then m else IntMap.insert (abs v) (v>0) m
74 | Nothing -> error $ "parseSolution: Expected an Int, received " ++ show y
75 | ) IntMap.empty ys
76 | _ -> IntMap.empty -- WRONG (should be Nothing)
77 |
78 | -- | 'Solver' for 'SAT' problems that tries to invoke the @cryptominisat5@ executable from the @PATH@
79 | cryptominisat5 :: MonadIO m => Solver SAT m
80 | cryptominisat5 = cryptominisat5Path "cryptominisat5"
81 |
82 | -- | 'Solver' for 'SAT' problems that tries to invoke a program that takes @cryptominisat5@ compatible arguments.
83 | --
84 | -- The 'FilePath' refers to the path to the executable.
85 | cryptominisat5Path :: MonadIO m => FilePath -> Solver SAT m
86 | cryptominisat5Path path problem = liftIO $
87 | withTempFiles ".cnf" "" $ \problemPath _ -> do
88 | writeDimacs' problemPath problem
89 |
90 | (exit, out, _err) <-
91 | readProcessWithExitCode path [problemPath] []
92 |
93 | let sol = parseSolution5 out
94 |
95 | return (resultOf exit, sol)
96 |
--------------------------------------------------------------------------------
/src/Ersatz/Solver/Z3.hs:
--------------------------------------------------------------------------------
1 | --------------------------------------------------------------------
2 | -- |
3 | -- Copyright : © Edward Kmett 2010-2014, Johan Kiviniemi 2013
4 | -- License : BSD3
5 | -- Maintainer: Edward Kmett
6 | -- Stability : experimental
7 | -- Portability: non-portable
8 | --
9 | --------------------------------------------------------------------
10 | module Ersatz.Solver.Z3
11 | ( z3
12 | , z3Path
13 | ) where
14 |
15 | import Control.Monad.IO.Class
16 | import Ersatz.Problem ( SAT, writeDimacs' )
17 | import Ersatz.Solution
18 | import Ersatz.Solver.Common
19 | import System.Process (readProcessWithExitCode)
20 |
21 | -- | 'Solver' for 'SAT' problems that tries to invoke the @z3@ executable from the @PATH@
22 | z3 :: MonadIO m => Solver SAT m
23 | z3 = z3Path "z3"
24 |
25 | -- | 'Solver' for 'SAT' problems that tries to invoke a program that takes @z3@ compatible arguments.
26 | --
27 | -- The 'FilePath' refers to the path to the executable.
28 | z3Path :: MonadIO m => FilePath -> Solver SAT m
29 | z3Path path problem = liftIO $
30 | withTempFiles ".cnf" "" $ \problemPath _ -> do
31 | writeDimacs' problemPath problem
32 |
33 | (_exit, out, _err) <-
34 | readProcessWithExitCode path ["-dimacs", problemPath] []
35 |
36 | let result = case lines out of
37 | "s SATISFIABLE":_ -> Satisfied
38 | "s UNSATISFIABLE":_ -> Unsatisfied
39 | _ -> Unsolved
40 |
41 | return (result, parseSolution5 out)
42 |
--------------------------------------------------------------------------------
/src/Ersatz/Variable.hs:
--------------------------------------------------------------------------------
1 | {-# LANGUAGE CPP #-}
2 | {-# LANGUAGE TypeOperators #-}
3 | {-# LANGUAGE FlexibleContexts #-}
4 | {-# LANGUAGE DefaultSignatures #-}
5 | {-# LANGUAGE UndecidableInstances #-}
6 | --------------------------------------------------------------------
7 | -- |
8 | -- Copyright : © Edward Kmett 2010-2014, Johan Kiviniemi 2013
9 | -- License : BSD3
10 | -- Maintainer: Edward Kmett
11 | -- Stability : experimental
12 | -- Portability: non-portable
13 | --
14 | --------------------------------------------------------------------
15 | module Ersatz.Variable
16 | ( Variable(..)
17 | #ifndef HLINT
18 | , forall_
19 | #endif
20 | , exists
21 |
22 | , GVariable(..)
23 | , genericLiterally
24 | ) where
25 |
26 | import Control.Monad
27 | import Ersatz.Internal.Literal
28 | import Ersatz.Problem
29 | import GHC.Generics
30 |
31 | exists :: (Variable a, MonadSAT s m) => m a
32 | exists = literally literalExists
33 |
34 | #ifndef HLINT
35 | forall_ :: (Variable a, MonadQSAT s m) => m a
36 | forall_ = literally literalForall
37 | #endif
38 |
39 | class GVariable f where
40 | gliterally :: MonadSAT s m => m Literal -> m (f a)
41 |
42 | instance GVariable U1 where
43 | gliterally _ = return U1
44 |
45 | instance (GVariable f, GVariable g) => GVariable (f :*: g) where
46 | gliterally m = liftM2 (:*:) (gliterally m) (gliterally m)
47 |
48 | instance Variable a => GVariable (K1 i a) where
49 | gliterally = fmap K1 . literally
50 |
51 | instance GVariable f => GVariable (M1 i c f) where
52 | gliterally = fmap M1 . gliterally
53 |
54 | -- | This class describes all types that can be represented
55 | -- by a collection of literals. The class method 'literally'
56 | -- is usually applied to 'literalExists' or 'literalForall',
57 | -- see implementations of 'exists' and 'forall'.
58 | --
59 | -- Instances for this class for product-like types can be automatically derived
60 | -- for any type that is an instance of 'Generic'.
61 | --
62 | -- === __Example usage__
63 | --
64 | -- @
65 | -- {-# language DeriveGeneric, TypeApplications #-}
66 | -- import GHC.Generics
67 | --
68 | -- data T = C Bit Bit deriving Generic
69 | -- instance Variable T
70 | --
71 | -- constraint = do t <- exists @T ; ...
72 | -- @
73 |
74 | class Variable t where
75 | literally :: MonadSAT s m => m Literal -> m t
76 | default literally ::
77 | (MonadSAT s m, Generic t, GVariable (Rep t)) =>
78 | m Literal -> m t
79 | literally = genericLiterally
80 |
81 | genericLiterally ::
82 | (MonadSAT s m, Generic t, GVariable (Rep t)) =>
83 | m Literal -> m t
84 | genericLiterally = fmap to . gliterally
85 |
86 | instance Variable Literal where
87 | literally = id
88 |
89 | instance (Variable a, Variable b) => Variable (a,b)
90 | instance (Variable a, Variable b, Variable c) => Variable (a,b,c)
91 | instance (Variable a, Variable b, Variable c, Variable d) => Variable (a,b,c,d)
92 | instance (Variable a, Variable b, Variable c, Variable d, Variable e) => Variable (a,b,c,d,e)
93 | instance (Variable a, Variable b, Variable c, Variable d, Variable e, Variable f) => Variable (a,b,c,d,e,f)
94 | instance (Variable a, Variable b, Variable c, Variable d, Variable e, Variable f, Variable g) => Variable (a,b,c,d,e,f,g)
95 |
--------------------------------------------------------------------------------
/tests/HUnit.hs:
--------------------------------------------------------------------------------
1 | -- | @HUnit@-based unit tests for @ersatz@.
2 | module Main where
3 |
4 | import Prelude hiding ((||), (&&), not)
5 |
6 | import Data.Default
7 | import qualified Data.IntMap.Strict as IntMap
8 |
9 | import Test.Tasty (TestTree, defaultMain, testGroup)
10 | import Test.Tasty.HUnit (Assertion, (@?=), testCase)
11 |
12 | import Ersatz
13 | import Ersatz.Internal.Literal
14 |
15 | main :: IO ()
16 | main = defaultMain tests
17 |
18 | tests :: TestTree
19 | tests =
20 | testGroup "unit tests"
21 | [ testCase "unconstrained literals" case_unconstrained_literals
22 | ]
23 |
24 | -- A regression test for #60 and #76.
25 | case_unconstrained_literals :: Assertion
26 | case_unconstrained_literals =
27 | decode sol [b1, not b1, b2, not b2, b1 || b2, b1 && b2] @?=
28 | Just [False, True, False, True, False, False]
29 | -- There are other valid answers, but in practice, ersatz will choose this
30 | -- one due to the convention that the Codec Literal instance always
31 | -- assigns non-negative unconstrained Literals to False and negative
32 | -- unconstrained Literals to True.
33 | where
34 | sol = solutionFrom (IntMap.fromList [(1, True)]) (def :: SAT)
35 | b1 = Var $ Literal 2
36 | b2 = Var $ Literal 3
37 |
--------------------------------------------------------------------------------
/tests/Moore.hs:
--------------------------------------------------------------------------------
1 | -- | graphs n nodes of degree <= d and diameter <= k
2 | -- see http://combinatoricswiki.org/wiki/The_Degree_Diameter_Problem_for_General_Graphs
3 |
4 | -- usage: ./Moore d k n [s]
5 | -- d : degree
6 | -- k : diameter
7 | -- n : nodes,
8 | -- s : modulus for symmetry (see periodic_relation below)
9 | -- s smaller => faster (more symmetries) but may lose solutions
10 |
11 | -- test cases: 3 2 10 2 -- petersen graph
12 | -- 5 2 24
13 |
14 |
15 | {-# language FlexibleContexts #-}
16 |
17 | import Prelude hiding ( not, or, and )
18 | import qualified Prelude
19 |
20 | import Ersatz
21 | import Ersatz.Bit
22 | import qualified Ersatz.Relation as R
23 |
24 | import qualified Data.Array as A
25 | import System.Environment (getArgs)
26 | import Control.Monad ( void, when, forM )
27 |
28 | main :: IO ( )
29 | main = do
30 | argv <- getArgs
31 | case argv of
32 | [ d, k, n, s ] ->
33 | void $ mainf ( read d ) (read k) (read n) (read s)
34 | [ d, k, n ] ->
35 | void $ mainf ( read d ) (read k) (read n) (read n)
36 | [] -> void $ mainf 3 2 10 5 -- petersen
37 |
38 | mainf d k n s = do
39 | putStrLn $ unwords [ "degree <=", show d, "diameter <=", show k, "nodes ==", show n, "symmetry ==", show s ]
40 | (s, mg) <- solveWith anyminisat $ moore d k n s
41 | case (s, mg) of
42 | (Satisfied, Just g) -> do putStrLn $ R.table g ; return True
43 | _ -> do return False
44 |
45 | moore ::
46 | MonadSAT s m =>
47 | Int -> Int -> Int -> Int ->
48 | m (R.Relation Int Int)
49 | moore d k n s = do
50 | -- g <- R.symmetric_relation ((0,0),(n-1,n-1))
51 | g <- periodic_relation s ((0,0),(n-1,n-1))
52 | assert $ R.symmetric g
53 | assert $ R.reflexive g
54 | assert $ R.max_in_degree (d+1) g
55 | assert $ R.max_out_degree (d+1) g
56 | let p = R.power k g
57 | assert $ R.complete p
58 | return g
59 |
60 | periodic_relation s bnd = do
61 | r <- R.relation bnd
62 | let normal (x,y) =
63 | if (x >= s Prelude.&& y >= s)
64 | then normal (x-s,y-s) else (x,y)
65 | return $ R.build bnd $ do
66 | i <- A.range bnd
67 | return (i, r R.! normal i)
68 |
69 |
--------------------------------------------------------------------------------
/tests/Speed.hs:
--------------------------------------------------------------------------------
1 | import Ersatz
2 | import Ersatz.Bit
3 | import Ersatz.Variable (exists)
4 |
5 | import System.Environment (getArgs)
6 | import Control.Monad ( forM_, replicateM )
7 |
8 | main :: IO ( )
9 | main = do
10 | argv <- getArgs
11 | case argv of
12 | [ n ] -> mainf ( read n)
13 | [] -> mainf 50000
14 |
15 | mainf n = do
16 | putStrLn $ unwords [ "n", show n ]
17 | (s, mgs) <- solveWith anyminisat $ do
18 | gs <- replicateM n exists
19 | forM_ (zipTail gs) $ \ (x,y) -> assert ( x /== y )
20 | return (gs :: [Bit])
21 | case (s, mgs) of
22 | (Satisfied, Just gs) -> do print $ length $ filter id gs
23 | _ -> do return ()
24 |
25 | zipTail :: [a] -> [(a, a)]
26 | zipTail [] = []
27 | zipTail xss@(_:xs) = zip xss xs
28 |
--------------------------------------------------------------------------------
/tests/Z001.hs:
--------------------------------------------------------------------------------
1 | {-# language KindSignatures, DataKinds, FlexibleContexts #-}
2 | {-# language GeneralizedNewtypeDeriving #-}
3 | {-# language TypeFamilies, ScopedTypeVariables #-}
4 | {-# language UndecidableInstances #-}
5 | {-# language NoMonomorphismRestriction #-}
6 |
7 | import Prelude hiding ( not, and, or, (&&), (||) )
8 |
9 | import Ersatz
10 |
11 | import GHC.TypeLits
12 | import Data.Proxy
13 | import Data.List ( transpose )
14 | import Control.Monad ( replicateM, forM_ )
15 |
16 | main = do
17 | (Satisfied, Just ms) <- solveWith anyminisat $ do
18 | [ Restricted a, Restricted b ]
19 | :: [ Restricted 5 (NBV 3) ] <- replicateM 2 unknown
20 | -- assert $ gt (a^2 * b^2) (b^3 * a^3)
21 | let a2 = a^2 ; b2 = b^2
22 | assert $ gt (a2 * b2) (b2 * b * a * a2)
23 | return [a,b]
24 | forM_ ms print
25 |
26 | unknown_monotone = do
27 | m <- unknown ; assert $ monotone m ; return m
28 |
29 | newtype Restricted d a = Restricted (Matrix d a)
30 |
31 | instance (KnownNat dim, Unknown a, Codec a, Num (Decoded a))
32 | => Unknown (Restricted dim a) where
33 | unknown = do
34 | let d = fromIntegral $ natVal (Proxy :: Proxy dim)
35 | row f = ( encode f : ) <$> replicateM (d-1) unknown
36 | m <- (:) <$> row 1 <*> replicateM (d-2) (row 0)
37 | return $ Restricted $ Matrix
38 | $ m ++ encode [ replicate (d-1) 0 ++ [1] ]
39 |
40 | class Unknown a where
41 | unknown :: MonadSAT s m => m a
42 |
43 | -- | square matrices
44 | --
45 | -- Invariant: @dim >= 2@
46 | newtype Matrix (dim::Nat) a = Matrix [[a]]
47 | deriving ( Show, Equatable, Orderable )
48 |
49 | instance Codec a => Codec (Matrix dim a) where
50 | type Decoded (Matrix dim a) = Matrix dim (Decoded a)
51 | decode s (Matrix xss) = Matrix <$> decode s xss
52 | encode = error "encode not implemented for Matrix"
53 |
54 | instance (KnownNat dim, Unknown a) => Unknown (Matrix dim a) where
55 | unknown = do
56 | let d = fromIntegral $ natVal (Proxy :: Proxy dim)
57 | Matrix <$> replicateM d (replicateM d unknown)
58 |
59 | instance Num a => Num (Matrix dim a) where
60 | Matrix xss + Matrix yss
61 | = Matrix $ zipWith (zipWith (+)) xss yss
62 | Matrix xss * Matrix yss
63 | = Matrix $ for xss $ \ row ->
64 | for (transpose yss) $ \ col ->
65 | sum $ zipWith (*) row col
66 | (-) = error "(-) not implemented for Matrix"
67 | abs = error "abs not implemented for Matrix"
68 | signum = error "signum not implemented for Matrix"
69 | fromInteger = error "fromInteger not implemented for Matrix"
70 |
71 | for = flip map
72 |
73 | topleft (Matrix xss) =
74 | case xss of
75 | ((x:_):_) -> x
76 | _ -> matrixInvariantViolated
77 |
78 | botright (Matrix xss)
79 | | Just (_, xs) <- unsnoc xss
80 | , Just (_, x) <- unsnoc xs
81 | = x
82 | | otherwise
83 | = matrixInvariantViolated
84 |
85 | topright (Matrix xss)
86 | | xs:_ <- xss
87 | , Just (_, x) <- unsnoc xs
88 | = x
89 | | otherwise
90 | = matrixInvariantViolated
91 |
92 | unsnoc :: [a] -> Maybe ([a], a)
93 | unsnoc [] = Nothing
94 | unsnoc (x:xs) = case unsnoc xs of
95 | Nothing -> Just ([], x)
96 | Just (a,b) -> Just (x:a, b)
97 |
98 | matrixInvariantViolated :: a
99 | matrixInvariantViolated = error "Matrix invariant violated"
100 |
101 | monotone m = positive (topleft m) && positive (botright m)
102 |
103 | ge :: Orderable a => Matrix dim a -> Matrix dim a -> Bit
104 | ge (Matrix xss) (Matrix yss) =
105 | and $ zipWith (>=?) (concat xss) (concat yss)
106 |
107 | gt :: Orderable a => Matrix dim a -> Matrix dim a -> Bit
108 | gt a b = ge a b && topright a >? topright b
109 |
110 | -- | NBV = Non-overflowing Bitvector
111 | -- Bitvectors of fixed length, with non-overflowing arithmetics
112 | -- (if overflow occurs, constraint is unsatisfiable)
113 |
114 | newtype NBV ( n :: Nat ) = NBV Bits
115 | deriving ( Show, Equatable, Orderable, HasBits )
116 |
117 | instance KnownNat w => Unknown (NBV w) where
118 | unknown = do
119 | let n = fromIntegral $ natVal (Proxy :: Proxy w)
120 | NBV <$> Bits <$> replicateM n exists
121 |
122 | positive (NBV (Bits bs)) = or bs
123 |
124 | nbv n (Bits bs) =
125 | let (p : re, post) = splitAt n bs
126 | in NBV $ Bits $ Run ( assert (not $ or post) *> return p )
127 | : re
128 |
129 | instance KnownNat n => Num (NBV n) where
130 | fromInteger = encode
131 | NBV a + NBV b =
132 | nbv (fromIntegral (natVal (Proxy :: Proxy n))) $ a + b
133 | NBV a * NBV b =
134 | nbv (fromIntegral (natVal (Proxy :: Proxy n))) $ a * b
135 | (-) = error "(-) not implemented for NBV"
136 | abs = error "abs not implemented for NBV"
137 | signum = error "signum not implemented for NBV"
138 |
139 | instance KnownNat n => Codec (NBV n) where
140 | type Decoded (NBV n) = Integer
141 | decode s (NBV bs) = decode s bs
142 | encode i =
143 | let n = fromIntegral $ natVal (Proxy :: Proxy n)
144 | Bits bs = encode i
145 | (pre, post) = splitAt n bs
146 | in if null post
147 | then NBV (Bits $ take n $ pre ++ repeat false)
148 | else error $ unwords
149 | [ "cannot encode", show i
150 | , "with given bit width", show n
151 | ]
152 |
--------------------------------------------------------------------------------
/tests/properties.hs:
--------------------------------------------------------------------------------
1 | module Main where
2 |
3 | import Prelude hiding ((||),(&&))
4 |
5 | import Test.Framework (Test)
6 | import Test.Framework (defaultMain, testGroup)
7 | import Test.Framework.Providers.HUnit
8 | -- import Test.Framework.Providers.QuickCheck (testProperty)
9 | -- import Test.HUnit hiding (Test)
10 | -- import Test.QuickCheck hiding ((==>))
11 |
12 | import Ersatz
13 |
14 | main :: IO ()
15 | main = defaultMain tests
16 |
17 | ignore :: Functor f => f a -> f ()
18 | ignore = fmap (const ())
19 |
20 | tests :: [Test]
21 | tests =
22 | [ testGroup "sat" $ zipWith (testCase . show) [1 :: Int ..] $
23 | [ -- showSAT (return ()) @?= "p cnf 0 0\n"
24 | -- , showSAT (ignore litExists) @?= "p cnf 1 0\n"
25 | -- , showSAT (ignore litForall) @?= "p cnf 2 0\na 1\n"
26 | -- , showSAT (do x <- forall; y <- exists; assertLits [x,y]) @?= "p cnf 2 1\na 1\ne 2\n1 2 0\n"
27 | ]
28 | ]
29 |
30 | {-
31 | currying_works :: SAT s ()
32 | currying_works = do
33 | x <- forall
34 | y <- forall
35 | z <- forall
36 | assert $ (x && y) ==> z === x ==> y ==> z
37 | -}
38 |
--------------------------------------------------------------------------------