├── .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 | [![Hackage](https://img.shields.io/hackage/v/ersatz.svg)](https://hackage.haskell.org/package/ersatz) [![Build Status](https://github.com/ekmett/ersatz/workflows/Haskell-CI/badge.svg)](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 | 104 | 107 | 110 | 113 | 116 | 119 | 122 |
instance 101 | blocks steps 102 | vars clauses 103 |
anomaly 3 3 105 | 48 261 106 |
medium 5 4 108 | 116 953 109 |
bw_large.a 9 6 111 | 459 4,675 112 |
huge 9 6 114 | 459 7,054 115 |
bw_large.b 11 9 117 | 1,087 13,772 118 |
bw_large.c 15 14 120 | 3,016 50,457 121 |
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 | 141 |
[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 |
[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 | 74 | 77 | 80 | 83 | 86 |
instance 71 | packages (parallel) plan steps 72 | vars clauses 73 |
logistics.a 8 11 75 | 828 6,718 76 |
logistics.b 5 13 78 | 843 7,301 79 |
logistics.c 7 13 81 | 1,141 10,719 82 |
logistics.d 9 14 84 | 4,713 21,991 85 |
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 | 103 |
[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 |
[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 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 |
instance holes vars clauses satisfiable? 
hole6.cnf 42 133 no 
hole7.cnf 56 204 no 
hole8.cnf 72 297 no 
hole9.cnf 90 415 no 
hole10.cnf10 110 561 no 

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 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 -> Bit 47 | 48 | -- | Compare for less-than or equal-to within the SAT problem. 49 | (<=?) :: t -> t -> Bit 50 | x <=? y = x === y || x t -> t -> Bit 53 | a =?) :: 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 Orderable (Map.Map k v) where 71 | x Orderable (IntMap.IntMap v) where 76 | x [(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 [(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 Orderable (Seq.Seq v) where 99 | x Orderable (Tree.Tree a) where 104 | Tree.Node x xs 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 | [] GOrderable f where 132 | ( f a -> Bit 133 | (<=?#) :: f a -> f a -> Bit 134 | 135 | instance GOrderable U1 where 136 | U1 GOrderable (f :*: g) where 144 | (a :*: b) GOrderable (f :+: g) where 148 | L1 _ GOrderable (M1 i c f) where 159 | M1 x GOrderable (K1 i a) where 163 | K1 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 | --------------------------------------------------------------------------------