diff --git a/COPYING b/COPYING
new file mode 100644
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,27 @@
+Copyright 2010-2012 Masahiro Sakai. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   1. Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+   2. Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+   3. The name of the author may not be used to endorse or promote
+      products derived from this software without specific prior
+      written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
new file mode 100644
--- /dev/null
+++ b/README.md
@@ -0,0 +1,83 @@
+toysolver
+=========
+
+Installation
+------------
+
+* unpack
+* cd toysolver
+* cabal install
+
+Usage
+-----
+
+This package includes several commands.
+
+### toysolver
+
+Arithmetic solver for the following problems:
+
+* Mixed Integer Liner Programming (MILP or MIP)
+* LA(Q), LA(Z) (NOT IMPLEMENTED YET)
+
+Usage: toysolver [OPTION...] file.lp
+
+    -h  --help           show help
+    -v  --version        show version number
+        --solver=SOLVER  mip (default), omega-test, cooper, old-mip
+
+### toysat
+
+SAT-based solver for the following problems:
+
+* SAT
+* PB
+    * Pseudo Boolean Satisfaction (PBS)
+    * Pseudo Boolean Optimization (PBO)
+    * Weighted Boolean Optimization (WBO)
+* Max-SAT
+* Integer Programming (all variables must be bounded)
+
+Usage:
+
+    toysat [file.cnf||-]
+    toysat --pb [file.opb|-]
+    toysat --wbo [file.wbo|-]
+    toysat --maxsat [file.cnf|file.wcnf|-]
+    toysat --lp [file.lp|-]
+
+### lp2yices
+
+Converter from LP file to Yices input file.
+
+Usage: lp2yice [file.lp|-]
+
+    -h  --help      show help
+        --optimize  output optimiality condition which uses quantifiers
+        --no-check  do not output "(check)"
+
+### cnf2lp
+
+Converter from DIMACS .cnf file to .lp file.
+
+Usage: cnf2lp [file.cnf|-]
+
+### maxsat2lp
+
+Converter from .cnf/.wcnf file to .lp file.
+
+Usage: maxsat2lp [file.cnf|file.wcnf|-]
+
+### pb2lp
+
+Converter from .opb/.wbo file to .lp file.
+
+Usage: pb2lp [--wbo] [file.opb|file.wbo|-]
+
+TODO
+----
+
+* Gröbner basis
+* Cylindrical algebraic decomposition
+* Local search
+* Suvery propagation
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,4 @@
+#! /usr/bin/env runhaskell
+
+> import Distribution.Simple
+> main = defaultMain
diff --git a/samples/gcnf/example.gcnf b/samples/gcnf/example.gcnf
new file mode 100644
--- /dev/null
+++ b/samples/gcnf/example.gcnf
@@ -0,0 +1,19 @@
+c http://www.satcompetition.org/2011/rules.pdf
+c
+c Example of group oriented CNF
+c
+c Represents the following formula
+c D = {x1 or x2 or x3}
+c G1 = {x1 -> x2, x2 -> x3}
+c G2 = {x3}
+c G3 = {x3 -> x2, -x2 or -x3}
+c G4 = {x2 -> x3}
+c
+p gcnf 5 7 4
+{0} 1 2 3 0
+{1} -1 2 0
+{1} -2 3 0
+{2} -3 0
+{3} 2 -3 0
+{3} -2 -3 0
+{4} -2 3 0
diff --git a/samples/lp/Sudoku.lp b/samples/lp/Sudoku.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/Sudoku.lp
@@ -0,0 +1,2848 @@
+\ glpsol -m Sudoku.mod -d Sudoku.dat --wlp Sudoku.lp
+\* Problem: Sudoku *\
+
+Minimize
+ obj: 0 Ans(1,1,1)
+
+Subject To
+ GIVEN(1,1,1): - Ans(1,1,1) <= -1
+ GIVEN(1,1,2): - Ans(1,1,2) <= -0
+ GIVEN(1,1,3): - Ans(1,1,3) <= -0
+ GIVEN(1,1,4): - Ans(1,1,4) <= -0
+ GIVEN(1,1,5): - Ans(1,1,5) <= -0
+ GIVEN(1,1,6): - Ans(1,1,6) <= -0
+ GIVEN(1,1,7): - Ans(1,1,7) <= -0
+ GIVEN(1,1,8): - Ans(1,1,8) <= -0
+ GIVEN(1,1,9): - Ans(1,1,9) <= -0
+ GIVEN(1,2,1): - Ans(1,2,1) <= -0
+ GIVEN(1,2,2): - Ans(1,2,2) <= -0
+ GIVEN(1,2,3): - Ans(1,2,3) <= -0
+ GIVEN(1,2,4): - Ans(1,2,4) <= -0
+ GIVEN(1,2,5): - Ans(1,2,5) <= -0
+ GIVEN(1,2,6): - Ans(1,2,6) <= -0
+ GIVEN(1,2,7): - Ans(1,2,7) <= -0
+ GIVEN(1,2,8): - Ans(1,2,8) <= -0
+ GIVEN(1,2,9): - Ans(1,2,9) <= -0
+ GIVEN(1,3,1): - Ans(1,3,1) <= -0
+ GIVEN(1,3,2): - Ans(1,3,2) <= -0
+ GIVEN(1,3,3): - Ans(1,3,3) <= -0
+ GIVEN(1,3,4): - Ans(1,3,4) <= -0
+ GIVEN(1,3,5): - Ans(1,3,5) <= -0
+ GIVEN(1,3,6): - Ans(1,3,6) <= -0
+ GIVEN(1,3,7): - Ans(1,3,7) <= -0
+ GIVEN(1,3,8): - Ans(1,3,8) <= -0
+ GIVEN(1,3,9): - Ans(1,3,9) <= -0
+ GIVEN(1,4,1): - Ans(1,4,1) <= -0
+ GIVEN(1,4,2): - Ans(1,4,2) <= -1
+ GIVEN(1,4,3): - Ans(1,4,3) <= -0
+ GIVEN(1,4,4): - Ans(1,4,4) <= -0
+ GIVEN(1,4,5): - Ans(1,4,5) <= -0
+ GIVEN(1,4,6): - Ans(1,4,6) <= -0
+ GIVEN(1,4,7): - Ans(1,4,7) <= -0
+ GIVEN(1,4,8): - Ans(1,4,8) <= -0
+ GIVEN(1,4,9): - Ans(1,4,9) <= -0
+ GIVEN(1,5,1): - Ans(1,5,1) <= -0
+ GIVEN(1,5,2): - Ans(1,5,2) <= -0
+ GIVEN(1,5,3): - Ans(1,5,3) <= -0
+ GIVEN(1,5,4): - Ans(1,5,4) <= -0
+ GIVEN(1,5,5): - Ans(1,5,5) <= -0
+ GIVEN(1,5,6): - Ans(1,5,6) <= -0
+ GIVEN(1,5,7): - Ans(1,5,7) <= -0
+ GIVEN(1,5,8): - Ans(1,5,8) <= -0
+ GIVEN(1,5,9): - Ans(1,5,9) <= -0
+ GIVEN(1,6,1): - Ans(1,6,1) <= -0
+ GIVEN(1,6,2): - Ans(1,6,2) <= -0
+ GIVEN(1,6,3): - Ans(1,6,3) <= -0
+ GIVEN(1,6,4): - Ans(1,6,4) <= -0
+ GIVEN(1,6,5): - Ans(1,6,5) <= -0
+ GIVEN(1,6,6): - Ans(1,6,6) <= -0
+ GIVEN(1,6,7): - Ans(1,6,7) <= -0
+ GIVEN(1,6,8): - Ans(1,6,8) <= -0
+ GIVEN(1,6,9): - Ans(1,6,9) <= -0
+ GIVEN(1,7,1): - Ans(1,7,1) <= -0
+ GIVEN(1,7,2): - Ans(1,7,2) <= -0
+ GIVEN(1,7,3): - Ans(1,7,3) <= -1
+ GIVEN(1,7,4): - Ans(1,7,4) <= -0
+ GIVEN(1,7,5): - Ans(1,7,5) <= -0
+ GIVEN(1,7,6): - Ans(1,7,6) <= -0
+ GIVEN(1,7,7): - Ans(1,7,7) <= -0
+ GIVEN(1,7,8): - Ans(1,7,8) <= -0
+ GIVEN(1,7,9): - Ans(1,7,9) <= -0
+ GIVEN(1,8,1): - Ans(1,8,1) <= -0
+ GIVEN(1,8,2): - Ans(1,8,2) <= -0
+ GIVEN(1,8,3): - Ans(1,8,3) <= -0
+ GIVEN(1,8,4): - Ans(1,8,4) <= -0
+ GIVEN(1,8,5): - Ans(1,8,5) <= -0
+ GIVEN(1,8,6): - Ans(1,8,6) <= -0
+ GIVEN(1,8,7): - Ans(1,8,7) <= -0
+ GIVEN(1,8,8): - Ans(1,8,8) <= -0
+ GIVEN(1,8,9): - Ans(1,8,9) <= -0
+ GIVEN(1,9,1): - Ans(1,9,1) <= -0
+ GIVEN(1,9,2): - Ans(1,9,2) <= -0
+ GIVEN(1,9,3): - Ans(1,9,3) <= -0
+ GIVEN(1,9,4): - Ans(1,9,4) <= -0
+ GIVEN(1,9,5): - Ans(1,9,5) <= -0
+ GIVEN(1,9,6): - Ans(1,9,6) <= -0
+ GIVEN(1,9,7): - Ans(1,9,7) <= -0
+ GIVEN(1,9,8): - Ans(1,9,8) <= -0
+ GIVEN(1,9,9): - Ans(1,9,9) <= -0
+ GIVEN(2,1,1): - Ans(2,1,1) <= -0
+ GIVEN(2,1,2): - Ans(2,1,2) <= -0
+ GIVEN(2,1,3): - Ans(2,1,3) <= -0
+ GIVEN(2,1,4): - Ans(2,1,4) <= -0
+ GIVEN(2,1,5): - Ans(2,1,5) <= -0
+ GIVEN(2,1,6): - Ans(2,1,6) <= -0
+ GIVEN(2,1,7): - Ans(2,1,7) <= -0
+ GIVEN(2,1,8): - Ans(2,1,8) <= -0
+ GIVEN(2,1,9): - Ans(2,1,9) <= -0
+ GIVEN(2,2,1): - Ans(2,2,1) <= -0
+ GIVEN(2,2,2): - Ans(2,2,2) <= -1
+ GIVEN(2,2,3): - Ans(2,2,3) <= -0
+ GIVEN(2,2,4): - Ans(2,2,4) <= -0
+ GIVEN(2,2,5): - Ans(2,2,5) <= -0
+ GIVEN(2,2,6): - Ans(2,2,6) <= -0
+ GIVEN(2,2,7): - Ans(2,2,7) <= -0
+ GIVEN(2,2,8): - Ans(2,2,8) <= -0
+ GIVEN(2,2,9): - Ans(2,2,9) <= -0
+ GIVEN(2,3,1): - Ans(2,3,1) <= -0
+ GIVEN(2,3,2): - Ans(2,3,2) <= -0
+ GIVEN(2,3,3): - Ans(2,3,3) <= -0
+ GIVEN(2,3,4): - Ans(2,3,4) <= -0
+ GIVEN(2,3,5): - Ans(2,3,5) <= -0
+ GIVEN(2,3,6): - Ans(2,3,6) <= -0
+ GIVEN(2,3,7): - Ans(2,3,7) <= -0
+ GIVEN(2,3,8): - Ans(2,3,8) <= -0
+ GIVEN(2,3,9): - Ans(2,3,9) <= -0
+ GIVEN(2,4,1): - Ans(2,4,1) <= -0
+ GIVEN(2,4,2): - Ans(2,4,2) <= -0
+ GIVEN(2,4,3): - Ans(2,4,3) <= -0
+ GIVEN(2,4,4): - Ans(2,4,4) <= -0
+ GIVEN(2,4,5): - Ans(2,4,5) <= -0
+ GIVEN(2,4,6): - Ans(2,4,6) <= -0
+ GIVEN(2,4,7): - Ans(2,4,7) <= -0
+ GIVEN(2,4,8): - Ans(2,4,8) <= -0
+ GIVEN(2,4,9): - Ans(2,4,9) <= -0
+ GIVEN(2,5,1): - Ans(2,5,1) <= -0
+ GIVEN(2,5,2): - Ans(2,5,2) <= -0
+ GIVEN(2,5,3): - Ans(2,5,3) <= -1
+ GIVEN(2,5,4): - Ans(2,5,4) <= -0
+ GIVEN(2,5,5): - Ans(2,5,5) <= -0
+ GIVEN(2,5,6): - Ans(2,5,6) <= -0
+ GIVEN(2,5,7): - Ans(2,5,7) <= -0
+ GIVEN(2,5,8): - Ans(2,5,8) <= -0
+ GIVEN(2,5,9): - Ans(2,5,9) <= -0
+ GIVEN(2,6,1): - Ans(2,6,1) <= -0
+ GIVEN(2,6,2): - Ans(2,6,2) <= -0
+ GIVEN(2,6,3): - Ans(2,6,3) <= -0
+ GIVEN(2,6,4): - Ans(2,6,4) <= -0
+ GIVEN(2,6,5): - Ans(2,6,5) <= -0
+ GIVEN(2,6,6): - Ans(2,6,6) <= -0
+ GIVEN(2,6,7): - Ans(2,6,7) <= -0
+ GIVEN(2,6,8): - Ans(2,6,8) <= -0
+ GIVEN(2,6,9): - Ans(2,6,9) <= -0
+ GIVEN(2,7,1): - Ans(2,7,1) <= -0
+ GIVEN(2,7,2): - Ans(2,7,2) <= -0
+ GIVEN(2,7,3): - Ans(2,7,3) <= -0
+ GIVEN(2,7,4): - Ans(2,7,4) <= -0
+ GIVEN(2,7,5): - Ans(2,7,5) <= -0
+ GIVEN(2,7,6): - Ans(2,7,6) <= -0
+ GIVEN(2,7,7): - Ans(2,7,7) <= -0
+ GIVEN(2,7,8): - Ans(2,7,8) <= -0
+ GIVEN(2,7,9): - Ans(2,7,9) <= -0
+ GIVEN(2,8,1): - Ans(2,8,1) <= -0
+ GIVEN(2,8,2): - Ans(2,8,2) <= -0
+ GIVEN(2,8,3): - Ans(2,8,3) <= -0
+ GIVEN(2,8,4): - Ans(2,8,4) <= -1
+ GIVEN(2,8,5): - Ans(2,8,5) <= -0
+ GIVEN(2,8,6): - Ans(2,8,6) <= -0
+ GIVEN(2,8,7): - Ans(2,8,7) <= -0
+ GIVEN(2,8,8): - Ans(2,8,8) <= -0
+ GIVEN(2,8,9): - Ans(2,8,9) <= -0
+ GIVEN(2,9,1): - Ans(2,9,1) <= -0
+ GIVEN(2,9,2): - Ans(2,9,2) <= -0
+ GIVEN(2,9,3): - Ans(2,9,3) <= -0
+ GIVEN(2,9,4): - Ans(2,9,4) <= -0
+ GIVEN(2,9,5): - Ans(2,9,5) <= -0
+ GIVEN(2,9,6): - Ans(2,9,6) <= -0
+ GIVEN(2,9,7): - Ans(2,9,7) <= -0
+ GIVEN(2,9,8): - Ans(2,9,8) <= -0
+ GIVEN(2,9,9): - Ans(2,9,9) <= -0
+ GIVEN(3,1,1): - Ans(3,1,1) <= -0
+ GIVEN(3,1,2): - Ans(3,1,2) <= -0
+ GIVEN(3,1,3): - Ans(3,1,3) <= -0
+ GIVEN(3,1,4): - Ans(3,1,4) <= -0
+ GIVEN(3,1,5): - Ans(3,1,5) <= -0
+ GIVEN(3,1,6): - Ans(3,1,6) <= -0
+ GIVEN(3,1,7): - Ans(3,1,7) <= -0
+ GIVEN(3,1,8): - Ans(3,1,8) <= -0
+ GIVEN(3,1,9): - Ans(3,1,9) <= -0
+ GIVEN(3,2,1): - Ans(3,2,1) <= -0
+ GIVEN(3,2,2): - Ans(3,2,2) <= -0
+ GIVEN(3,2,3): - Ans(3,2,3) <= -0
+ GIVEN(3,2,4): - Ans(3,2,4) <= -0
+ GIVEN(3,2,5): - Ans(3,2,5) <= -0
+ GIVEN(3,2,6): - Ans(3,2,6) <= -0
+ GIVEN(3,2,7): - Ans(3,2,7) <= -0
+ GIVEN(3,2,8): - Ans(3,2,8) <= -0
+ GIVEN(3,2,9): - Ans(3,2,9) <= -0
+ GIVEN(3,3,1): - Ans(3,3,1) <= -0
+ GIVEN(3,3,2): - Ans(3,3,2) <= -0
+ GIVEN(3,3,3): - Ans(3,3,3) <= -1
+ GIVEN(3,3,4): - Ans(3,3,4) <= -0
+ GIVEN(3,3,5): - Ans(3,3,5) <= -0
+ GIVEN(3,3,6): - Ans(3,3,6) <= -0
+ GIVEN(3,3,7): - Ans(3,3,7) <= -0
+ GIVEN(3,3,8): - Ans(3,3,8) <= -0
+ GIVEN(3,3,9): - Ans(3,3,9) <= -0
+ GIVEN(3,4,1): - Ans(3,4,1) <= -0
+ GIVEN(3,4,2): - Ans(3,4,2) <= -0
+ GIVEN(3,4,3): - Ans(3,4,3) <= -0
+ GIVEN(3,4,4): - Ans(3,4,4) <= -0
+ GIVEN(3,4,5): - Ans(3,4,5) <= -0
+ GIVEN(3,4,6): - Ans(3,4,6) <= -0
+ GIVEN(3,4,7): - Ans(3,4,7) <= -0
+ GIVEN(3,4,8): - Ans(3,4,8) <= -0
+ GIVEN(3,4,9): - Ans(3,4,9) <= -0
+ GIVEN(3,5,1): - Ans(3,5,1) <= -0
+ GIVEN(3,5,2): - Ans(3,5,2) <= -0
+ GIVEN(3,5,3): - Ans(3,5,3) <= -0
+ GIVEN(3,5,4): - Ans(3,5,4) <= -0
+ GIVEN(3,5,5): - Ans(3,5,5) <= -0
+ GIVEN(3,5,6): - Ans(3,5,6) <= -0
+ GIVEN(3,5,7): - Ans(3,5,7) <= -0
+ GIVEN(3,5,8): - Ans(3,5,8) <= -0
+ GIVEN(3,5,9): - Ans(3,5,9) <= -0
+ GIVEN(3,6,1): - Ans(3,6,1) <= -0
+ GIVEN(3,6,2): - Ans(3,6,2) <= -0
+ GIVEN(3,6,3): - Ans(3,6,3) <= -0
+ GIVEN(3,6,4): - Ans(3,6,4) <= -1
+ GIVEN(3,6,5): - Ans(3,6,5) <= -0
+ GIVEN(3,6,6): - Ans(3,6,6) <= -0
+ GIVEN(3,6,7): - Ans(3,6,7) <= -0
+ GIVEN(3,6,8): - Ans(3,6,8) <= -0
+ GIVEN(3,6,9): - Ans(3,6,9) <= -0
+ GIVEN(3,7,1): - Ans(3,7,1) <= -0
+ GIVEN(3,7,2): - Ans(3,7,2) <= -0
+ GIVEN(3,7,3): - Ans(3,7,3) <= -0
+ GIVEN(3,7,4): - Ans(3,7,4) <= -0
+ GIVEN(3,7,5): - Ans(3,7,5) <= -0
+ GIVEN(3,7,6): - Ans(3,7,6) <= -0
+ GIVEN(3,7,7): - Ans(3,7,7) <= -0
+ GIVEN(3,7,8): - Ans(3,7,8) <= -0
+ GIVEN(3,7,9): - Ans(3,7,9) <= -0
+ GIVEN(3,8,1): - Ans(3,8,1) <= -0
+ GIVEN(3,8,2): - Ans(3,8,2) <= -0
+ GIVEN(3,8,3): - Ans(3,8,3) <= -0
+ GIVEN(3,8,4): - Ans(3,8,4) <= -0
+ GIVEN(3,8,5): - Ans(3,8,5) <= -0
+ GIVEN(3,8,6): - Ans(3,8,6) <= -0
+ GIVEN(3,8,7): - Ans(3,8,7) <= -0
+ GIVEN(3,8,8): - Ans(3,8,8) <= -0
+ GIVEN(3,8,9): - Ans(3,8,9) <= -0
+ GIVEN(3,9,1): - Ans(3,9,1) <= -0
+ GIVEN(3,9,2): - Ans(3,9,2) <= -0
+ GIVEN(3,9,3): - Ans(3,9,3) <= -0
+ GIVEN(3,9,4): - Ans(3,9,4) <= -0
+ GIVEN(3,9,5): - Ans(3,9,5) <= -1
+ GIVEN(3,9,6): - Ans(3,9,6) <= -0
+ GIVEN(3,9,7): - Ans(3,9,7) <= -0
+ GIVEN(3,9,8): - Ans(3,9,8) <= -0
+ GIVEN(3,9,9): - Ans(3,9,9) <= -0
+ GIVEN(4,1,1): - Ans(4,1,1) <= -0
+ GIVEN(4,1,2): - Ans(4,1,2) <= -0
+ GIVEN(4,1,3): - Ans(4,1,3) <= -0
+ GIVEN(4,1,4): - Ans(4,1,4) <= -0
+ GIVEN(4,1,5): - Ans(4,1,5) <= -0
+ GIVEN(4,1,6): - Ans(4,1,6) <= -1
+ GIVEN(4,1,7): - Ans(4,1,7) <= -0
+ GIVEN(4,1,8): - Ans(4,1,8) <= -0
+ GIVEN(4,1,9): - Ans(4,1,9) <= -0
+ GIVEN(4,2,1): - Ans(4,2,1) <= -0
+ GIVEN(4,2,2): - Ans(4,2,2) <= -0
+ GIVEN(4,2,3): - Ans(4,2,3) <= -0
+ GIVEN(4,2,4): - Ans(4,2,4) <= -0
+ GIVEN(4,2,5): - Ans(4,2,5) <= -0
+ GIVEN(4,2,6): - Ans(4,2,6) <= -0
+ GIVEN(4,2,7): - Ans(4,2,7) <= -0
+ GIVEN(4,2,8): - Ans(4,2,8) <= -0
+ GIVEN(4,2,9): - Ans(4,2,9) <= -0
+ GIVEN(4,3,1): - Ans(4,3,1) <= -0
+ GIVEN(4,3,2): - Ans(4,3,2) <= -0
+ GIVEN(4,3,3): - Ans(4,3,3) <= -0
+ GIVEN(4,3,4): - Ans(4,3,4) <= -0
+ GIVEN(4,3,5): - Ans(4,3,5) <= -0
+ GIVEN(4,3,6): - Ans(4,3,6) <= -0
+ GIVEN(4,3,7): - Ans(4,3,7) <= -0
+ GIVEN(4,3,8): - Ans(4,3,8) <= -0
+ GIVEN(4,3,9): - Ans(4,3,9) <= -0
+ GIVEN(4,4,1): - Ans(4,4,1) <= -0
+ GIVEN(4,4,2): - Ans(4,4,2) <= -0
+ GIVEN(4,4,3): - Ans(4,4,3) <= -0
+ GIVEN(4,4,4): - Ans(4,4,4) <= -1
+ GIVEN(4,4,5): - Ans(4,4,5) <= -0
+ GIVEN(4,4,6): - Ans(4,4,6) <= -0
+ GIVEN(4,4,7): - Ans(4,4,7) <= -0
+ GIVEN(4,4,8): - Ans(4,4,8) <= -0
+ GIVEN(4,4,9): - Ans(4,4,9) <= -0
+ GIVEN(4,5,1): - Ans(4,5,1) <= -0
+ GIVEN(4,5,2): - Ans(4,5,2) <= -0
+ GIVEN(4,5,3): - Ans(4,5,3) <= -0
+ GIVEN(4,5,4): - Ans(4,5,4) <= -0
+ GIVEN(4,5,5): - Ans(4,5,5) <= -0
+ GIVEN(4,5,6): - Ans(4,5,6) <= -0
+ GIVEN(4,5,7): - Ans(4,5,7) <= -0
+ GIVEN(4,5,8): - Ans(4,5,8) <= -0
+ GIVEN(4,5,9): - Ans(4,5,9) <= -0
+ GIVEN(4,6,1): - Ans(4,6,1) <= -0
+ GIVEN(4,6,2): - Ans(4,6,2) <= -0
+ GIVEN(4,6,3): - Ans(4,6,3) <= -0
+ GIVEN(4,6,4): - Ans(4,6,4) <= -0
+ GIVEN(4,6,5): - Ans(4,6,5) <= -0
+ GIVEN(4,6,6): - Ans(4,6,6) <= -0
+ GIVEN(4,6,7): - Ans(4,6,7) <= -0
+ GIVEN(4,6,8): - Ans(4,6,8) <= -0
+ GIVEN(4,6,9): - Ans(4,6,9) <= -0
+ GIVEN(4,7,1): - Ans(4,7,1) <= -0
+ GIVEN(4,7,2): - Ans(4,7,2) <= -0
+ GIVEN(4,7,3): - Ans(4,7,3) <= -0
+ GIVEN(4,7,4): - Ans(4,7,4) <= -0
+ GIVEN(4,7,5): - Ans(4,7,5) <= -1
+ GIVEN(4,7,6): - Ans(4,7,6) <= -0
+ GIVEN(4,7,7): - Ans(4,7,7) <= -0
+ GIVEN(4,7,8): - Ans(4,7,8) <= -0
+ GIVEN(4,7,9): - Ans(4,7,9) <= -0
+ GIVEN(4,8,1): - Ans(4,8,1) <= -0
+ GIVEN(4,8,2): - Ans(4,8,2) <= -0
+ GIVEN(4,8,3): - Ans(4,8,3) <= -0
+ GIVEN(4,8,4): - Ans(4,8,4) <= -0
+ GIVEN(4,8,5): - Ans(4,8,5) <= -0
+ GIVEN(4,8,6): - Ans(4,8,6) <= -0
+ GIVEN(4,8,7): - Ans(4,8,7) <= -0
+ GIVEN(4,8,8): - Ans(4,8,8) <= -0
+ GIVEN(4,8,9): - Ans(4,8,9) <= -0
+ GIVEN(4,9,1): - Ans(4,9,1) <= -0
+ GIVEN(4,9,2): - Ans(4,9,2) <= -0
+ GIVEN(4,9,3): - Ans(4,9,3) <= -0
+ GIVEN(4,9,4): - Ans(4,9,4) <= -0
+ GIVEN(4,9,5): - Ans(4,9,5) <= -0
+ GIVEN(4,9,6): - Ans(4,9,6) <= -0
+ GIVEN(4,9,7): - Ans(4,9,7) <= -0
+ GIVEN(4,9,8): - Ans(4,9,8) <= -0
+ GIVEN(4,9,9): - Ans(4,9,9) <= -0
+ GIVEN(5,1,1): - Ans(5,1,1) <= -0
+ GIVEN(5,1,2): - Ans(5,1,2) <= -0
+ GIVEN(5,1,3): - Ans(5,1,3) <= -0
+ GIVEN(5,1,4): - Ans(5,1,4) <= -0
+ GIVEN(5,1,5): - Ans(5,1,5) <= -0
+ GIVEN(5,1,6): - Ans(5,1,6) <= -0
+ GIVEN(5,1,7): - Ans(5,1,7) <= -0
+ GIVEN(5,1,8): - Ans(5,1,8) <= -0
+ GIVEN(5,1,9): - Ans(5,1,9) <= -0
+ GIVEN(5,2,1): - Ans(5,2,1) <= -0
+ GIVEN(5,2,2): - Ans(5,2,2) <= -0
+ GIVEN(5,2,3): - Ans(5,2,3) <= -0
+ GIVEN(5,2,4): - Ans(5,2,4) <= -0
+ GIVEN(5,2,5): - Ans(5,2,5) <= -0
+ GIVEN(5,2,6): - Ans(5,2,6) <= -0
+ GIVEN(5,2,7): - Ans(5,2,7) <= -1
+ GIVEN(5,2,8): - Ans(5,2,8) <= -0
+ GIVEN(5,2,9): - Ans(5,2,9) <= -0
+ GIVEN(5,3,1): - Ans(5,3,1) <= -0
+ GIVEN(5,3,2): - Ans(5,3,2) <= -0
+ GIVEN(5,3,3): - Ans(5,3,3) <= -0
+ GIVEN(5,3,4): - Ans(5,3,4) <= -0
+ GIVEN(5,3,5): - Ans(5,3,5) <= -0
+ GIVEN(5,3,6): - Ans(5,3,6) <= -0
+ GIVEN(5,3,7): - Ans(5,3,7) <= -0
+ GIVEN(5,3,8): - Ans(5,3,8) <= -0
+ GIVEN(5,3,9): - Ans(5,3,9) <= -0
+ GIVEN(5,4,1): - Ans(5,4,1) <= -0
+ GIVEN(5,4,2): - Ans(5,4,2) <= -0
+ GIVEN(5,4,3): - Ans(5,4,3) <= -0
+ GIVEN(5,4,4): - Ans(5,4,4) <= -0
+ GIVEN(5,4,5): - Ans(5,4,5) <= -0
+ GIVEN(5,4,6): - Ans(5,4,6) <= -0
+ GIVEN(5,4,7): - Ans(5,4,7) <= -0
+ GIVEN(5,4,8): - Ans(5,4,8) <= -0
+ GIVEN(5,4,9): - Ans(5,4,9) <= -0
+ GIVEN(5,5,1): - Ans(5,5,1) <= -0
+ GIVEN(5,5,2): - Ans(5,5,2) <= -0
+ GIVEN(5,5,3): - Ans(5,5,3) <= -0
+ GIVEN(5,5,4): - Ans(5,5,4) <= -0
+ GIVEN(5,5,5): - Ans(5,5,5) <= -1
+ GIVEN(5,5,6): - Ans(5,5,6) <= -0
+ GIVEN(5,5,7): - Ans(5,5,7) <= -0
+ GIVEN(5,5,8): - Ans(5,5,8) <= -0
+ GIVEN(5,5,9): - Ans(5,5,9) <= -0
+ GIVEN(5,6,1): - Ans(5,6,1) <= -0
+ GIVEN(5,6,2): - Ans(5,6,2) <= -0
+ GIVEN(5,6,3): - Ans(5,6,3) <= -0
+ GIVEN(5,6,4): - Ans(5,6,4) <= -0
+ GIVEN(5,6,5): - Ans(5,6,5) <= -0
+ GIVEN(5,6,6): - Ans(5,6,6) <= -0
+ GIVEN(5,6,7): - Ans(5,6,7) <= -0
+ GIVEN(5,6,8): - Ans(5,6,8) <= -0
+ GIVEN(5,6,9): - Ans(5,6,9) <= -0
+ GIVEN(5,7,1): - Ans(5,7,1) <= -0
+ GIVEN(5,7,2): - Ans(5,7,2) <= -0
+ GIVEN(5,7,3): - Ans(5,7,3) <= -0
+ GIVEN(5,7,4): - Ans(5,7,4) <= -0
+ GIVEN(5,7,5): - Ans(5,7,5) <= -0
+ GIVEN(5,7,6): - Ans(5,7,6) <= -0
+ GIVEN(5,7,7): - Ans(5,7,7) <= -0
+ GIVEN(5,7,8): - Ans(5,7,8) <= -0
+ GIVEN(5,7,9): - Ans(5,7,9) <= -0
+ GIVEN(5,8,1): - Ans(5,8,1) <= -0
+ GIVEN(5,8,2): - Ans(5,8,2) <= -0
+ GIVEN(5,8,3): - Ans(5,8,3) <= -0
+ GIVEN(5,8,4): - Ans(5,8,4) <= -0
+ GIVEN(5,8,5): - Ans(5,8,5) <= -0
+ GIVEN(5,8,6): - Ans(5,8,6) <= -1
+ GIVEN(5,8,7): - Ans(5,8,7) <= -0
+ GIVEN(5,8,8): - Ans(5,8,8) <= -0
+ GIVEN(5,8,9): - Ans(5,8,9) <= -0
+ GIVEN(5,9,1): - Ans(5,9,1) <= -0
+ GIVEN(5,9,2): - Ans(5,9,2) <= -0
+ GIVEN(5,9,3): - Ans(5,9,3) <= -0
+ GIVEN(5,9,4): - Ans(5,9,4) <= -0
+ GIVEN(5,9,5): - Ans(5,9,5) <= -0
+ GIVEN(5,9,6): - Ans(5,9,6) <= -0
+ GIVEN(5,9,7): - Ans(5,9,7) <= -0
+ GIVEN(5,9,8): - Ans(5,9,8) <= -0
+ GIVEN(5,9,9): - Ans(5,9,9) <= -0
+ GIVEN(6,1,1): - Ans(6,1,1) <= -0
+ GIVEN(6,1,2): - Ans(6,1,2) <= -0
+ GIVEN(6,1,3): - Ans(6,1,3) <= -0
+ GIVEN(6,1,4): - Ans(6,1,4) <= -0
+ GIVEN(6,1,5): - Ans(6,1,5) <= -0
+ GIVEN(6,1,6): - Ans(6,1,6) <= -0
+ GIVEN(6,1,7): - Ans(6,1,7) <= -0
+ GIVEN(6,1,8): - Ans(6,1,8) <= -0
+ GIVEN(6,1,9): - Ans(6,1,9) <= -0
+ GIVEN(6,2,1): - Ans(6,2,1) <= -0
+ GIVEN(6,2,2): - Ans(6,2,2) <= -0
+ GIVEN(6,2,3): - Ans(6,2,3) <= -0
+ GIVEN(6,2,4): - Ans(6,2,4) <= -0
+ GIVEN(6,2,5): - Ans(6,2,5) <= -0
+ GIVEN(6,2,6): - Ans(6,2,6) <= -0
+ GIVEN(6,2,7): - Ans(6,2,7) <= -0
+ GIVEN(6,2,8): - Ans(6,2,8) <= -0
+ GIVEN(6,2,9): - Ans(6,2,9) <= -0
+ GIVEN(6,3,1): - Ans(6,3,1) <= -0
+ GIVEN(6,3,2): - Ans(6,3,2) <= -0
+ GIVEN(6,3,3): - Ans(6,3,3) <= -0
+ GIVEN(6,3,4): - Ans(6,3,4) <= -0
+ GIVEN(6,3,5): - Ans(6,3,5) <= -0
+ GIVEN(6,3,6): - Ans(6,3,6) <= -0
+ GIVEN(6,3,7): - Ans(6,3,7) <= -0
+ GIVEN(6,3,8): - Ans(6,3,8) <= -1
+ GIVEN(6,3,9): - Ans(6,3,9) <= -0
+ GIVEN(6,4,1): - Ans(6,4,1) <= -0
+ GIVEN(6,4,2): - Ans(6,4,2) <= -0
+ GIVEN(6,4,3): - Ans(6,4,3) <= -0
+ GIVEN(6,4,4): - Ans(6,4,4) <= -0
+ GIVEN(6,4,5): - Ans(6,4,5) <= -0
+ GIVEN(6,4,6): - Ans(6,4,6) <= -0
+ GIVEN(6,4,7): - Ans(6,4,7) <= -0
+ GIVEN(6,4,8): - Ans(6,4,8) <= -0
+ GIVEN(6,4,9): - Ans(6,4,9) <= -0
+ GIVEN(6,5,1): - Ans(6,5,1) <= -0
+ GIVEN(6,5,2): - Ans(6,5,2) <= -0
+ GIVEN(6,5,3): - Ans(6,5,3) <= -0
+ GIVEN(6,5,4): - Ans(6,5,4) <= -0
+ GIVEN(6,5,5): - Ans(6,5,5) <= -0
+ GIVEN(6,5,6): - Ans(6,5,6) <= -0
+ GIVEN(6,5,7): - Ans(6,5,7) <= -0
+ GIVEN(6,5,8): - Ans(6,5,8) <= -0
+ GIVEN(6,5,9): - Ans(6,5,9) <= -0
+ GIVEN(6,6,1): - Ans(6,6,1) <= -0
+ GIVEN(6,6,2): - Ans(6,6,2) <= -0
+ GIVEN(6,6,3): - Ans(6,6,3) <= -0
+ GIVEN(6,6,4): - Ans(6,6,4) <= -0
+ GIVEN(6,6,5): - Ans(6,6,5) <= -0
+ GIVEN(6,6,6): - Ans(6,6,6) <= -1
+ GIVEN(6,6,7): - Ans(6,6,7) <= -0
+ GIVEN(6,6,8): - Ans(6,6,8) <= -0
+ GIVEN(6,6,9): - Ans(6,6,9) <= -0
+ GIVEN(6,7,1): - Ans(6,7,1) <= -0
+ GIVEN(6,7,2): - Ans(6,7,2) <= -0
+ GIVEN(6,7,3): - Ans(6,7,3) <= -0
+ GIVEN(6,7,4): - Ans(6,7,4) <= -0
+ GIVEN(6,7,5): - Ans(6,7,5) <= -0
+ GIVEN(6,7,6): - Ans(6,7,6) <= -0
+ GIVEN(6,7,7): - Ans(6,7,7) <= -0
+ GIVEN(6,7,8): - Ans(6,7,8) <= -0
+ GIVEN(6,7,9): - Ans(6,7,9) <= -0
+ GIVEN(6,8,1): - Ans(6,8,1) <= -0
+ GIVEN(6,8,2): - Ans(6,8,2) <= -0
+ GIVEN(6,8,3): - Ans(6,8,3) <= -0
+ GIVEN(6,8,4): - Ans(6,8,4) <= -0
+ GIVEN(6,8,5): - Ans(6,8,5) <= -0
+ GIVEN(6,8,6): - Ans(6,8,6) <= -0
+ GIVEN(6,8,7): - Ans(6,8,7) <= -0
+ GIVEN(6,8,8): - Ans(6,8,8) <= -0
+ GIVEN(6,8,9): - Ans(6,8,9) <= -0
+ GIVEN(6,9,1): - Ans(6,9,1) <= -0
+ GIVEN(6,9,2): - Ans(6,9,2) <= -0
+ GIVEN(6,9,3): - Ans(6,9,3) <= -0
+ GIVEN(6,9,4): - Ans(6,9,4) <= -0
+ GIVEN(6,9,5): - Ans(6,9,5) <= -0
+ GIVEN(6,9,6): - Ans(6,9,6) <= -0
+ GIVEN(6,9,7): - Ans(6,9,7) <= -1
+ GIVEN(6,9,8): - Ans(6,9,8) <= -0
+ GIVEN(6,9,9): - Ans(6,9,9) <= -0
+ GIVEN(7,1,1): - Ans(7,1,1) <= -0
+ GIVEN(7,1,2): - Ans(7,1,2) <= -0
+ GIVEN(7,1,3): - Ans(7,1,3) <= -0
+ GIVEN(7,1,4): - Ans(7,1,4) <= -0
+ GIVEN(7,1,5): - Ans(7,1,5) <= -0
+ GIVEN(7,1,6): - Ans(7,1,6) <= -0
+ GIVEN(7,1,7): - Ans(7,1,7) <= -0
+ GIVEN(7,1,8): - Ans(7,1,8) <= -1
+ GIVEN(7,1,9): - Ans(7,1,9) <= -0
+ GIVEN(7,2,1): - Ans(7,2,1) <= -0
+ GIVEN(7,2,2): - Ans(7,2,2) <= -0
+ GIVEN(7,2,3): - Ans(7,2,3) <= -0
+ GIVEN(7,2,4): - Ans(7,2,4) <= -0
+ GIVEN(7,2,5): - Ans(7,2,5) <= -0
+ GIVEN(7,2,6): - Ans(7,2,6) <= -0
+ GIVEN(7,2,7): - Ans(7,2,7) <= -0
+ GIVEN(7,2,8): - Ans(7,2,8) <= -0
+ GIVEN(7,2,9): - Ans(7,2,9) <= -0
+ GIVEN(7,3,1): - Ans(7,3,1) <= -0
+ GIVEN(7,3,2): - Ans(7,3,2) <= -0
+ GIVEN(7,3,3): - Ans(7,3,3) <= -0
+ GIVEN(7,3,4): - Ans(7,3,4) <= -0
+ GIVEN(7,3,5): - Ans(7,3,5) <= -0
+ GIVEN(7,3,6): - Ans(7,3,6) <= -0
+ GIVEN(7,3,7): - Ans(7,3,7) <= -0
+ GIVEN(7,3,8): - Ans(7,3,8) <= -0
+ GIVEN(7,3,9): - Ans(7,3,9) <= -0
+ GIVEN(7,4,1): - Ans(7,4,1) <= -0
+ GIVEN(7,4,2): - Ans(7,4,2) <= -0
+ GIVEN(7,4,3): - Ans(7,4,3) <= -0
+ GIVEN(7,4,4): - Ans(7,4,4) <= -0
+ GIVEN(7,4,5): - Ans(7,4,5) <= -0
+ GIVEN(7,4,6): - Ans(7,4,6) <= -0
+ GIVEN(7,4,7): - Ans(7,4,7) <= -0
+ GIVEN(7,4,8): - Ans(7,4,8) <= -0
+ GIVEN(7,4,9): - Ans(7,4,9) <= -1
+ GIVEN(7,5,1): - Ans(7,5,1) <= -0
+ GIVEN(7,5,2): - Ans(7,5,2) <= -0
+ GIVEN(7,5,3): - Ans(7,5,3) <= -0
+ GIVEN(7,5,4): - Ans(7,5,4) <= -0
+ GIVEN(7,5,5): - Ans(7,5,5) <= -0
+ GIVEN(7,5,6): - Ans(7,5,6) <= -0
+ GIVEN(7,5,7): - Ans(7,5,7) <= -0
+ GIVEN(7,5,8): - Ans(7,5,8) <= -0
+ GIVEN(7,5,9): - Ans(7,5,9) <= -0
+ GIVEN(7,6,1): - Ans(7,6,1) <= -0
+ GIVEN(7,6,2): - Ans(7,6,2) <= -0
+ GIVEN(7,6,3): - Ans(7,6,3) <= -0
+ GIVEN(7,6,4): - Ans(7,6,4) <= -0
+ GIVEN(7,6,5): - Ans(7,6,5) <= -0
+ GIVEN(7,6,6): - Ans(7,6,6) <= -0
+ GIVEN(7,6,7): - Ans(7,6,7) <= -0
+ GIVEN(7,6,8): - Ans(7,6,8) <= -0
+ GIVEN(7,6,9): - Ans(7,6,9) <= -0
+ GIVEN(7,7,1): - Ans(7,7,1) <= -0
+ GIVEN(7,7,2): - Ans(7,7,2) <= -0
+ GIVEN(7,7,3): - Ans(7,7,3) <= -0
+ GIVEN(7,7,4): - Ans(7,7,4) <= -0
+ GIVEN(7,7,5): - Ans(7,7,5) <= -0
+ GIVEN(7,7,6): - Ans(7,7,6) <= -0
+ GIVEN(7,7,7): - Ans(7,7,7) <= -1
+ GIVEN(7,7,8): - Ans(7,7,8) <= -0
+ GIVEN(7,7,9): - Ans(7,7,9) <= -0
+ GIVEN(7,8,1): - Ans(7,8,1) <= -0
+ GIVEN(7,8,2): - Ans(7,8,2) <= -0
+ GIVEN(7,8,3): - Ans(7,8,3) <= -0
+ GIVEN(7,8,4): - Ans(7,8,4) <= -0
+ GIVEN(7,8,5): - Ans(7,8,5) <= -0
+ GIVEN(7,8,6): - Ans(7,8,6) <= -0
+ GIVEN(7,8,7): - Ans(7,8,7) <= -0
+ GIVEN(7,8,8): - Ans(7,8,8) <= -0
+ GIVEN(7,8,9): - Ans(7,8,9) <= -0
+ GIVEN(7,9,1): - Ans(7,9,1) <= -0
+ GIVEN(7,9,2): - Ans(7,9,2) <= -0
+ GIVEN(7,9,3): - Ans(7,9,3) <= -0
+ GIVEN(7,9,4): - Ans(7,9,4) <= -0
+ GIVEN(7,9,5): - Ans(7,9,5) <= -0
+ GIVEN(7,9,6): - Ans(7,9,6) <= -0
+ GIVEN(7,9,7): - Ans(7,9,7) <= -0
+ GIVEN(7,9,8): - Ans(7,9,8) <= -0
+ GIVEN(7,9,9): - Ans(7,9,9) <= -0
+ GIVEN(8,1,1): - Ans(8,1,1) <= -0
+ GIVEN(8,1,2): - Ans(8,1,2) <= -0
+ GIVEN(8,1,3): - Ans(8,1,3) <= -0
+ GIVEN(8,1,4): - Ans(8,1,4) <= -0
+ GIVEN(8,1,5): - Ans(8,1,5) <= -0
+ GIVEN(8,1,6): - Ans(8,1,6) <= -0
+ GIVEN(8,1,7): - Ans(8,1,7) <= -0
+ GIVEN(8,1,8): - Ans(8,1,8) <= -0
+ GIVEN(8,1,9): - Ans(8,1,9) <= -0
+ GIVEN(8,2,1): - Ans(8,2,1) <= -0
+ GIVEN(8,2,2): - Ans(8,2,2) <= -0
+ GIVEN(8,2,3): - Ans(8,2,3) <= -0
+ GIVEN(8,2,4): - Ans(8,2,4) <= -0
+ GIVEN(8,2,5): - Ans(8,2,5) <= -0
+ GIVEN(8,2,6): - Ans(8,2,6) <= -0
+ GIVEN(8,2,7): - Ans(8,2,7) <= -0
+ GIVEN(8,2,8): - Ans(8,2,8) <= -0
+ GIVEN(8,2,9): - Ans(8,2,9) <= -1
+ GIVEN(8,3,1): - Ans(8,3,1) <= -0
+ GIVEN(8,3,2): - Ans(8,3,2) <= -0
+ GIVEN(8,3,3): - Ans(8,3,3) <= -0
+ GIVEN(8,3,4): - Ans(8,3,4) <= -0
+ GIVEN(8,3,5): - Ans(8,3,5) <= -0
+ GIVEN(8,3,6): - Ans(8,3,6) <= -0
+ GIVEN(8,3,7): - Ans(8,3,7) <= -0
+ GIVEN(8,3,8): - Ans(8,3,8) <= -0
+ GIVEN(8,3,9): - Ans(8,3,9) <= -0
+ GIVEN(8,4,1): - Ans(8,4,1) <= -0
+ GIVEN(8,4,2): - Ans(8,4,2) <= -0
+ GIVEN(8,4,3): - Ans(8,4,3) <= -0
+ GIVEN(8,4,4): - Ans(8,4,4) <= -0
+ GIVEN(8,4,5): - Ans(8,4,5) <= -0
+ GIVEN(8,4,6): - Ans(8,4,6) <= -0
+ GIVEN(8,4,7): - Ans(8,4,7) <= -0
+ GIVEN(8,4,8): - Ans(8,4,8) <= -0
+ GIVEN(8,4,9): - Ans(8,4,9) <= -0
+ GIVEN(8,5,1): - Ans(8,5,1) <= -1
+ GIVEN(8,5,2): - Ans(8,5,2) <= -0
+ GIVEN(8,5,3): - Ans(8,5,3) <= -0
+ GIVEN(8,5,4): - Ans(8,5,4) <= -0
+ GIVEN(8,5,5): - Ans(8,5,5) <= -0
+ GIVEN(8,5,6): - Ans(8,5,6) <= -0
+ GIVEN(8,5,7): - Ans(8,5,7) <= -0
+ GIVEN(8,5,8): - Ans(8,5,8) <= -0
+ GIVEN(8,5,9): - Ans(8,5,9) <= -0
+ GIVEN(8,6,1): - Ans(8,6,1) <= -0
+ GIVEN(8,6,2): - Ans(8,6,2) <= -0
+ GIVEN(8,6,3): - Ans(8,6,3) <= -0
+ GIVEN(8,6,4): - Ans(8,6,4) <= -0
+ GIVEN(8,6,5): - Ans(8,6,5) <= -0
+ GIVEN(8,6,6): - Ans(8,6,6) <= -0
+ GIVEN(8,6,7): - Ans(8,6,7) <= -0
+ GIVEN(8,6,8): - Ans(8,6,8) <= -0
+ GIVEN(8,6,9): - Ans(8,6,9) <= -0
+ GIVEN(8,7,1): - Ans(8,7,1) <= -0
+ GIVEN(8,7,2): - Ans(8,7,2) <= -0
+ GIVEN(8,7,3): - Ans(8,7,3) <= -0
+ GIVEN(8,7,4): - Ans(8,7,4) <= -0
+ GIVEN(8,7,5): - Ans(8,7,5) <= -0
+ GIVEN(8,7,6): - Ans(8,7,6) <= -0
+ GIVEN(8,7,7): - Ans(8,7,7) <= -0
+ GIVEN(8,7,8): - Ans(8,7,8) <= -0
+ GIVEN(8,7,9): - Ans(8,7,9) <= -0
+ GIVEN(8,8,1): - Ans(8,8,1) <= -0
+ GIVEN(8,8,2): - Ans(8,8,2) <= -0
+ GIVEN(8,8,3): - Ans(8,8,3) <= -0
+ GIVEN(8,8,4): - Ans(8,8,4) <= -0
+ GIVEN(8,8,5): - Ans(8,8,5) <= -0
+ GIVEN(8,8,6): - Ans(8,8,6) <= -0
+ GIVEN(8,8,7): - Ans(8,8,7) <= -0
+ GIVEN(8,8,8): - Ans(8,8,8) <= -1
+ GIVEN(8,8,9): - Ans(8,8,9) <= -0
+ GIVEN(8,9,1): - Ans(8,9,1) <= -0
+ GIVEN(8,9,2): - Ans(8,9,2) <= -0
+ GIVEN(8,9,3): - Ans(8,9,3) <= -0
+ GIVEN(8,9,4): - Ans(8,9,4) <= -0
+ GIVEN(8,9,5): - Ans(8,9,5) <= -0
+ GIVEN(8,9,6): - Ans(8,9,6) <= -0
+ GIVEN(8,9,7): - Ans(8,9,7) <= -0
+ GIVEN(8,9,8): - Ans(8,9,8) <= -0
+ GIVEN(8,9,9): - Ans(8,9,9) <= -0
+ GIVEN(9,1,1): - Ans(9,1,1) <= -0
+ GIVEN(9,1,2): - Ans(9,1,2) <= -0
+ GIVEN(9,1,3): - Ans(9,1,3) <= -0
+ GIVEN(9,1,4): - Ans(9,1,4) <= -0
+ GIVEN(9,1,5): - Ans(9,1,5) <= -0
+ GIVEN(9,1,6): - Ans(9,1,6) <= -0
+ GIVEN(9,1,7): - Ans(9,1,7) <= -0
+ GIVEN(9,1,8): - Ans(9,1,8) <= -0
+ GIVEN(9,1,9): - Ans(9,1,9) <= -0
+ GIVEN(9,2,1): - Ans(9,2,1) <= -0
+ GIVEN(9,2,2): - Ans(9,2,2) <= -0
+ GIVEN(9,2,3): - Ans(9,2,3) <= -0
+ GIVEN(9,2,4): - Ans(9,2,4) <= -0
+ GIVEN(9,2,5): - Ans(9,2,5) <= -0
+ GIVEN(9,2,6): - Ans(9,2,6) <= -0
+ GIVEN(9,2,7): - Ans(9,2,7) <= -0
+ GIVEN(9,2,8): - Ans(9,2,8) <= -0
+ GIVEN(9,2,9): - Ans(9,2,9) <= -0
+ GIVEN(9,3,1): - Ans(9,3,1) <= -1
+ GIVEN(9,3,2): - Ans(9,3,2) <= -0
+ GIVEN(9,3,3): - Ans(9,3,3) <= -0
+ GIVEN(9,3,4): - Ans(9,3,4) <= -0
+ GIVEN(9,3,5): - Ans(9,3,5) <= -0
+ GIVEN(9,3,6): - Ans(9,3,6) <= -0
+ GIVEN(9,3,7): - Ans(9,3,7) <= -0
+ GIVEN(9,3,8): - Ans(9,3,8) <= -0
+ GIVEN(9,3,9): - Ans(9,3,9) <= -0
+ GIVEN(9,4,1): - Ans(9,4,1) <= -0
+ GIVEN(9,4,2): - Ans(9,4,2) <= -0
+ GIVEN(9,4,3): - Ans(9,4,3) <= -0
+ GIVEN(9,4,4): - Ans(9,4,4) <= -0
+ GIVEN(9,4,5): - Ans(9,4,5) <= -0
+ GIVEN(9,4,6): - Ans(9,4,6) <= -0
+ GIVEN(9,4,7): - Ans(9,4,7) <= -0
+ GIVEN(9,4,8): - Ans(9,4,8) <= -0
+ GIVEN(9,4,9): - Ans(9,4,9) <= -0
+ GIVEN(9,5,1): - Ans(9,5,1) <= -0
+ GIVEN(9,5,2): - Ans(9,5,2) <= -0
+ GIVEN(9,5,3): - Ans(9,5,3) <= -0
+ GIVEN(9,5,4): - Ans(9,5,4) <= -0
+ GIVEN(9,5,5): - Ans(9,5,5) <= -0
+ GIVEN(9,5,6): - Ans(9,5,6) <= -0
+ GIVEN(9,5,7): - Ans(9,5,7) <= -0
+ GIVEN(9,5,8): - Ans(9,5,8) <= -0
+ GIVEN(9,5,9): - Ans(9,5,9) <= -0
+ GIVEN(9,6,1): - Ans(9,6,1) <= -0
+ GIVEN(9,6,2): - Ans(9,6,2) <= -1
+ GIVEN(9,6,3): - Ans(9,6,3) <= -0
+ GIVEN(9,6,4): - Ans(9,6,4) <= -0
+ GIVEN(9,6,5): - Ans(9,6,5) <= -0
+ GIVEN(9,6,6): - Ans(9,6,6) <= -0
+ GIVEN(9,6,7): - Ans(9,6,7) <= -0
+ GIVEN(9,6,8): - Ans(9,6,8) <= -0
+ GIVEN(9,6,9): - Ans(9,6,9) <= -0
+ GIVEN(9,7,1): - Ans(9,7,1) <= -0
+ GIVEN(9,7,2): - Ans(9,7,2) <= -0
+ GIVEN(9,7,3): - Ans(9,7,3) <= -0
+ GIVEN(9,7,4): - Ans(9,7,4) <= -0
+ GIVEN(9,7,5): - Ans(9,7,5) <= -0
+ GIVEN(9,7,6): - Ans(9,7,6) <= -0
+ GIVEN(9,7,7): - Ans(9,7,7) <= -0
+ GIVEN(9,7,8): - Ans(9,7,8) <= -0
+ GIVEN(9,7,9): - Ans(9,7,9) <= -0
+ GIVEN(9,8,1): - Ans(9,8,1) <= -0
+ GIVEN(9,8,2): - Ans(9,8,2) <= -0
+ GIVEN(9,8,3): - Ans(9,8,3) <= -0
+ GIVEN(9,8,4): - Ans(9,8,4) <= -0
+ GIVEN(9,8,5): - Ans(9,8,5) <= -0
+ GIVEN(9,8,6): - Ans(9,8,6) <= -0
+ GIVEN(9,8,7): - Ans(9,8,7) <= -0
+ GIVEN(9,8,8): - Ans(9,8,8) <= -0
+ GIVEN(9,8,9): - Ans(9,8,9) <= -0
+ GIVEN(9,9,1): - Ans(9,9,1) <= -0
+ GIVEN(9,9,2): - Ans(9,9,2) <= -0
+ GIVEN(9,9,3): - Ans(9,9,3) <= -0
+ GIVEN(9,9,4): - Ans(9,9,4) <= -1
+ GIVEN(9,9,5): - Ans(9,9,5) <= -0
+ GIVEN(9,9,6): - Ans(9,9,6) <= -0
+ GIVEN(9,9,7): - Ans(9,9,7) <= -0
+ GIVEN(9,9,8): - Ans(9,9,8) <= -0
+ GIVEN(9,9,9): - Ans(9,9,9) <= -0
+ FILLED(1,1): + Ans(1,1,1) + Ans(1,1,2) + Ans(1,1,3) + Ans(1,1,4)
+ + Ans(1,1,5) + Ans(1,1,6) + Ans(1,1,7) + Ans(1,1,8) + Ans(1,1,9) = 1
+ FILLED(1,2): + Ans(1,2,1) + Ans(1,2,2) + Ans(1,2,3) + Ans(1,2,4)
+ + Ans(1,2,5) + Ans(1,2,6) + Ans(1,2,7) + Ans(1,2,8) + Ans(1,2,9) = 1
+ FILLED(1,3): + Ans(1,3,1) + Ans(1,3,2) + Ans(1,3,3) + Ans(1,3,4)
+ + Ans(1,3,5) + Ans(1,3,6) + Ans(1,3,7) + Ans(1,3,8) + Ans(1,3,9) = 1
+ FILLED(1,4): + Ans(1,4,1) + Ans(1,4,2) + Ans(1,4,3) + Ans(1,4,4)
+ + Ans(1,4,5) + Ans(1,4,6) + Ans(1,4,7) + Ans(1,4,8) + Ans(1,4,9) = 1
+ FILLED(1,5): + Ans(1,5,1) + Ans(1,5,2) + Ans(1,5,3) + Ans(1,5,4)
+ + Ans(1,5,5) + Ans(1,5,6) + Ans(1,5,7) + Ans(1,5,8) + Ans(1,5,9) = 1
+ FILLED(1,6): + Ans(1,6,1) + Ans(1,6,2) + Ans(1,6,3) + Ans(1,6,4)
+ + Ans(1,6,5) + Ans(1,6,6) + Ans(1,6,7) + Ans(1,6,8) + Ans(1,6,9) = 1
+ FILLED(1,7): + Ans(1,7,1) + Ans(1,7,2) + Ans(1,7,3) + Ans(1,7,4)
+ + Ans(1,7,5) + Ans(1,7,6) + Ans(1,7,7) + Ans(1,7,8) + Ans(1,7,9) = 1
+ FILLED(1,8): + Ans(1,8,1) + Ans(1,8,2) + Ans(1,8,3) + Ans(1,8,4)
+ + Ans(1,8,5) + Ans(1,8,6) + Ans(1,8,7) + Ans(1,8,8) + Ans(1,8,9) = 1
+ FILLED(1,9): + Ans(1,9,1) + Ans(1,9,2) + Ans(1,9,3) + Ans(1,9,4)
+ + Ans(1,9,5) + Ans(1,9,6) + Ans(1,9,7) + Ans(1,9,8) + Ans(1,9,9) = 1
+ FILLED(2,1): + Ans(2,1,1) + Ans(2,1,2) + Ans(2,1,3) + Ans(2,1,4)
+ + Ans(2,1,5) + Ans(2,1,6) + Ans(2,1,7) + Ans(2,1,8) + Ans(2,1,9) = 1
+ FILLED(2,2): + Ans(2,2,1) + Ans(2,2,2) + Ans(2,2,3) + Ans(2,2,4)
+ + Ans(2,2,5) + Ans(2,2,6) + Ans(2,2,7) + Ans(2,2,8) + Ans(2,2,9) = 1
+ FILLED(2,3): + Ans(2,3,1) + Ans(2,3,2) + Ans(2,3,3) + Ans(2,3,4)
+ + Ans(2,3,5) + Ans(2,3,6) + Ans(2,3,7) + Ans(2,3,8) + Ans(2,3,9) = 1
+ FILLED(2,4): + Ans(2,4,1) + Ans(2,4,2) + Ans(2,4,3) + Ans(2,4,4)
+ + Ans(2,4,5) + Ans(2,4,6) + Ans(2,4,7) + Ans(2,4,8) + Ans(2,4,9) = 1
+ FILLED(2,5): + Ans(2,5,1) + Ans(2,5,2) + Ans(2,5,3) + Ans(2,5,4)
+ + Ans(2,5,5) + Ans(2,5,6) + Ans(2,5,7) + Ans(2,5,8) + Ans(2,5,9) = 1
+ FILLED(2,6): + Ans(2,6,1) + Ans(2,6,2) + Ans(2,6,3) + Ans(2,6,4)
+ + Ans(2,6,5) + Ans(2,6,6) + Ans(2,6,7) + Ans(2,6,8) + Ans(2,6,9) = 1
+ FILLED(2,7): + Ans(2,7,1) + Ans(2,7,2) + Ans(2,7,3) + Ans(2,7,4)
+ + Ans(2,7,5) + Ans(2,7,6) + Ans(2,7,7) + Ans(2,7,8) + Ans(2,7,9) = 1
+ FILLED(2,8): + Ans(2,8,1) + Ans(2,8,2) + Ans(2,8,3) + Ans(2,8,4)
+ + Ans(2,8,5) + Ans(2,8,6) + Ans(2,8,7) + Ans(2,8,8) + Ans(2,8,9) = 1
+ FILLED(2,9): + Ans(2,9,1) + Ans(2,9,2) + Ans(2,9,3) + Ans(2,9,4)
+ + Ans(2,9,5) + Ans(2,9,6) + Ans(2,9,7) + Ans(2,9,8) + Ans(2,9,9) = 1
+ FILLED(3,1): + Ans(3,1,1) + Ans(3,1,2) + Ans(3,1,3) + Ans(3,1,4)
+ + Ans(3,1,5) + Ans(3,1,6) + Ans(3,1,7) + Ans(3,1,8) + Ans(3,1,9) = 1
+ FILLED(3,2): + Ans(3,2,1) + Ans(3,2,2) + Ans(3,2,3) + Ans(3,2,4)
+ + Ans(3,2,5) + Ans(3,2,6) + Ans(3,2,7) + Ans(3,2,8) + Ans(3,2,9) = 1
+ FILLED(3,3): + Ans(3,3,1) + Ans(3,3,2) + Ans(3,3,3) + Ans(3,3,4)
+ + Ans(3,3,5) + Ans(3,3,6) + Ans(3,3,7) + Ans(3,3,8) + Ans(3,3,9) = 1
+ FILLED(3,4): + Ans(3,4,1) + Ans(3,4,2) + Ans(3,4,3) + Ans(3,4,4)
+ + Ans(3,4,5) + Ans(3,4,6) + Ans(3,4,7) + Ans(3,4,8) + Ans(3,4,9) = 1
+ FILLED(3,5): + Ans(3,5,1) + Ans(3,5,2) + Ans(3,5,3) + Ans(3,5,4)
+ + Ans(3,5,5) + Ans(3,5,6) + Ans(3,5,7) + Ans(3,5,8) + Ans(3,5,9) = 1
+ FILLED(3,6): + Ans(3,6,1) + Ans(3,6,2) + Ans(3,6,3) + Ans(3,6,4)
+ + Ans(3,6,5) + Ans(3,6,6) + Ans(3,6,7) + Ans(3,6,8) + Ans(3,6,9) = 1
+ FILLED(3,7): + Ans(3,7,1) + Ans(3,7,2) + Ans(3,7,3) + Ans(3,7,4)
+ + Ans(3,7,5) + Ans(3,7,6) + Ans(3,7,7) + Ans(3,7,8) + Ans(3,7,9) = 1
+ FILLED(3,8): + Ans(3,8,1) + Ans(3,8,2) + Ans(3,8,3) + Ans(3,8,4)
+ + Ans(3,8,5) + Ans(3,8,6) + Ans(3,8,7) + Ans(3,8,8) + Ans(3,8,9) = 1
+ FILLED(3,9): + Ans(3,9,1) + Ans(3,9,2) + Ans(3,9,3) + Ans(3,9,4)
+ + Ans(3,9,5) + Ans(3,9,6) + Ans(3,9,7) + Ans(3,9,8) + Ans(3,9,9) = 1
+ FILLED(4,1): + Ans(4,1,1) + Ans(4,1,2) + Ans(4,1,3) + Ans(4,1,4)
+ + Ans(4,1,5) + Ans(4,1,6) + Ans(4,1,7) + Ans(4,1,8) + Ans(4,1,9) = 1
+ FILLED(4,2): + Ans(4,2,1) + Ans(4,2,2) + Ans(4,2,3) + Ans(4,2,4)
+ + Ans(4,2,5) + Ans(4,2,6) + Ans(4,2,7) + Ans(4,2,8) + Ans(4,2,9) = 1
+ FILLED(4,3): + Ans(4,3,1) + Ans(4,3,2) + Ans(4,3,3) + Ans(4,3,4)
+ + Ans(4,3,5) + Ans(4,3,6) + Ans(4,3,7) + Ans(4,3,8) + Ans(4,3,9) = 1
+ FILLED(4,4): + Ans(4,4,1) + Ans(4,4,2) + Ans(4,4,3) + Ans(4,4,4)
+ + Ans(4,4,5) + Ans(4,4,6) + Ans(4,4,7) + Ans(4,4,8) + Ans(4,4,9) = 1
+ FILLED(4,5): + Ans(4,5,1) + Ans(4,5,2) + Ans(4,5,3) + Ans(4,5,4)
+ + Ans(4,5,5) + Ans(4,5,6) + Ans(4,5,7) + Ans(4,5,8) + Ans(4,5,9) = 1
+ FILLED(4,6): + Ans(4,6,1) + Ans(4,6,2) + Ans(4,6,3) + Ans(4,6,4)
+ + Ans(4,6,5) + Ans(4,6,6) + Ans(4,6,7) + Ans(4,6,8) + Ans(4,6,9) = 1
+ FILLED(4,7): + Ans(4,7,1) + Ans(4,7,2) + Ans(4,7,3) + Ans(4,7,4)
+ + Ans(4,7,5) + Ans(4,7,6) + Ans(4,7,7) + Ans(4,7,8) + Ans(4,7,9) = 1
+ FILLED(4,8): + Ans(4,8,1) + Ans(4,8,2) + Ans(4,8,3) + Ans(4,8,4)
+ + Ans(4,8,5) + Ans(4,8,6) + Ans(4,8,7) + Ans(4,8,8) + Ans(4,8,9) = 1
+ FILLED(4,9): + Ans(4,9,1) + Ans(4,9,2) + Ans(4,9,3) + Ans(4,9,4)
+ + Ans(4,9,5) + Ans(4,9,6) + Ans(4,9,7) + Ans(4,9,8) + Ans(4,9,9) = 1
+ FILLED(5,1): + Ans(5,1,1) + Ans(5,1,2) + Ans(5,1,3) + Ans(5,1,4)
+ + Ans(5,1,5) + Ans(5,1,6) + Ans(5,1,7) + Ans(5,1,8) + Ans(5,1,9) = 1
+ FILLED(5,2): + Ans(5,2,1) + Ans(5,2,2) + Ans(5,2,3) + Ans(5,2,4)
+ + Ans(5,2,5) + Ans(5,2,6) + Ans(5,2,7) + Ans(5,2,8) + Ans(5,2,9) = 1
+ FILLED(5,3): + Ans(5,3,1) + Ans(5,3,2) + Ans(5,3,3) + Ans(5,3,4)
+ + Ans(5,3,5) + Ans(5,3,6) + Ans(5,3,7) + Ans(5,3,8) + Ans(5,3,9) = 1
+ FILLED(5,4): + Ans(5,4,1) + Ans(5,4,2) + Ans(5,4,3) + Ans(5,4,4)
+ + Ans(5,4,5) + Ans(5,4,6) + Ans(5,4,7) + Ans(5,4,8) + Ans(5,4,9) = 1
+ FILLED(5,5): + Ans(5,5,1) + Ans(5,5,2) + Ans(5,5,3) + Ans(5,5,4)
+ + Ans(5,5,5) + Ans(5,5,6) + Ans(5,5,7) + Ans(5,5,8) + Ans(5,5,9) = 1
+ FILLED(5,6): + Ans(5,6,1) + Ans(5,6,2) + Ans(5,6,3) + Ans(5,6,4)
+ + Ans(5,6,5) + Ans(5,6,6) + Ans(5,6,7) + Ans(5,6,8) + Ans(5,6,9) = 1
+ FILLED(5,7): + Ans(5,7,1) + Ans(5,7,2) + Ans(5,7,3) + Ans(5,7,4)
+ + Ans(5,7,5) + Ans(5,7,6) + Ans(5,7,7) + Ans(5,7,8) + Ans(5,7,9) = 1
+ FILLED(5,8): + Ans(5,8,1) + Ans(5,8,2) + Ans(5,8,3) + Ans(5,8,4)
+ + Ans(5,8,5) + Ans(5,8,6) + Ans(5,8,7) + Ans(5,8,8) + Ans(5,8,9) = 1
+ FILLED(5,9): + Ans(5,9,1) + Ans(5,9,2) + Ans(5,9,3) + Ans(5,9,4)
+ + Ans(5,9,5) + Ans(5,9,6) + Ans(5,9,7) + Ans(5,9,8) + Ans(5,9,9) = 1
+ FILLED(6,1): + Ans(6,1,1) + Ans(6,1,2) + Ans(6,1,3) + Ans(6,1,4)
+ + Ans(6,1,5) + Ans(6,1,6) + Ans(6,1,7) + Ans(6,1,8) + Ans(6,1,9) = 1
+ FILLED(6,2): + Ans(6,2,1) + Ans(6,2,2) + Ans(6,2,3) + Ans(6,2,4)
+ + Ans(6,2,5) + Ans(6,2,6) + Ans(6,2,7) + Ans(6,2,8) + Ans(6,2,9) = 1
+ FILLED(6,3): + Ans(6,3,1) + Ans(6,3,2) + Ans(6,3,3) + Ans(6,3,4)
+ + Ans(6,3,5) + Ans(6,3,6) + Ans(6,3,7) + Ans(6,3,8) + Ans(6,3,9) = 1
+ FILLED(6,4): + Ans(6,4,1) + Ans(6,4,2) + Ans(6,4,3) + Ans(6,4,4)
+ + Ans(6,4,5) + Ans(6,4,6) + Ans(6,4,7) + Ans(6,4,8) + Ans(6,4,9) = 1
+ FILLED(6,5): + Ans(6,5,1) + Ans(6,5,2) + Ans(6,5,3) + Ans(6,5,4)
+ + Ans(6,5,5) + Ans(6,5,6) + Ans(6,5,7) + Ans(6,5,8) + Ans(6,5,9) = 1
+ FILLED(6,6): + Ans(6,6,1) + Ans(6,6,2) + Ans(6,6,3) + Ans(6,6,4)
+ + Ans(6,6,5) + Ans(6,6,6) + Ans(6,6,7) + Ans(6,6,8) + Ans(6,6,9) = 1
+ FILLED(6,7): + Ans(6,7,1) + Ans(6,7,2) + Ans(6,7,3) + Ans(6,7,4)
+ + Ans(6,7,5) + Ans(6,7,6) + Ans(6,7,7) + Ans(6,7,8) + Ans(6,7,9) = 1
+ FILLED(6,8): + Ans(6,8,1) + Ans(6,8,2) + Ans(6,8,3) + Ans(6,8,4)
+ + Ans(6,8,5) + Ans(6,8,6) + Ans(6,8,7) + Ans(6,8,8) + Ans(6,8,9) = 1
+ FILLED(6,9): + Ans(6,9,1) + Ans(6,9,2) + Ans(6,9,3) + Ans(6,9,4)
+ + Ans(6,9,5) + Ans(6,9,6) + Ans(6,9,7) + Ans(6,9,8) + Ans(6,9,9) = 1
+ FILLED(7,1): + Ans(7,1,1) + Ans(7,1,2) + Ans(7,1,3) + Ans(7,1,4)
+ + Ans(7,1,5) + Ans(7,1,6) + Ans(7,1,7) + Ans(7,1,8) + Ans(7,1,9) = 1
+ FILLED(7,2): + Ans(7,2,1) + Ans(7,2,2) + Ans(7,2,3) + Ans(7,2,4)
+ + Ans(7,2,5) + Ans(7,2,6) + Ans(7,2,7) + Ans(7,2,8) + Ans(7,2,9) = 1
+ FILLED(7,3): + Ans(7,3,1) + Ans(7,3,2) + Ans(7,3,3) + Ans(7,3,4)
+ + Ans(7,3,5) + Ans(7,3,6) + Ans(7,3,7) + Ans(7,3,8) + Ans(7,3,9) = 1
+ FILLED(7,4): + Ans(7,4,1) + Ans(7,4,2) + Ans(7,4,3) + Ans(7,4,4)
+ + Ans(7,4,5) + Ans(7,4,6) + Ans(7,4,7) + Ans(7,4,8) + Ans(7,4,9) = 1
+ FILLED(7,5): + Ans(7,5,1) + Ans(7,5,2) + Ans(7,5,3) + Ans(7,5,4)
+ + Ans(7,5,5) + Ans(7,5,6) + Ans(7,5,7) + Ans(7,5,8) + Ans(7,5,9) = 1
+ FILLED(7,6): + Ans(7,6,1) + Ans(7,6,2) + Ans(7,6,3) + Ans(7,6,4)
+ + Ans(7,6,5) + Ans(7,6,6) + Ans(7,6,7) + Ans(7,6,8) + Ans(7,6,9) = 1
+ FILLED(7,7): + Ans(7,7,1) + Ans(7,7,2) + Ans(7,7,3) + Ans(7,7,4)
+ + Ans(7,7,5) + Ans(7,7,6) + Ans(7,7,7) + Ans(7,7,8) + Ans(7,7,9) = 1
+ FILLED(7,8): + Ans(7,8,1) + Ans(7,8,2) + Ans(7,8,3) + Ans(7,8,4)
+ + Ans(7,8,5) + Ans(7,8,6) + Ans(7,8,7) + Ans(7,8,8) + Ans(7,8,9) = 1
+ FILLED(7,9): + Ans(7,9,1) + Ans(7,9,2) + Ans(7,9,3) + Ans(7,9,4)
+ + Ans(7,9,5) + Ans(7,9,6) + Ans(7,9,7) + Ans(7,9,8) + Ans(7,9,9) = 1
+ FILLED(8,1): + Ans(8,1,1) + Ans(8,1,2) + Ans(8,1,3) + Ans(8,1,4)
+ + Ans(8,1,5) + Ans(8,1,6) + Ans(8,1,7) + Ans(8,1,8) + Ans(8,1,9) = 1
+ FILLED(8,2): + Ans(8,2,1) + Ans(8,2,2) + Ans(8,2,3) + Ans(8,2,4)
+ + Ans(8,2,5) + Ans(8,2,6) + Ans(8,2,7) + Ans(8,2,8) + Ans(8,2,9) = 1
+ FILLED(8,3): + Ans(8,3,1) + Ans(8,3,2) + Ans(8,3,3) + Ans(8,3,4)
+ + Ans(8,3,5) + Ans(8,3,6) + Ans(8,3,7) + Ans(8,3,8) + Ans(8,3,9) = 1
+ FILLED(8,4): + Ans(8,4,1) + Ans(8,4,2) + Ans(8,4,3) + Ans(8,4,4)
+ + Ans(8,4,5) + Ans(8,4,6) + Ans(8,4,7) + Ans(8,4,8) + Ans(8,4,9) = 1
+ FILLED(8,5): + Ans(8,5,1) + Ans(8,5,2) + Ans(8,5,3) + Ans(8,5,4)
+ + Ans(8,5,5) + Ans(8,5,6) + Ans(8,5,7) + Ans(8,5,8) + Ans(8,5,9) = 1
+ FILLED(8,6): + Ans(8,6,1) + Ans(8,6,2) + Ans(8,6,3) + Ans(8,6,4)
+ + Ans(8,6,5) + Ans(8,6,6) + Ans(8,6,7) + Ans(8,6,8) + Ans(8,6,9) = 1
+ FILLED(8,7): + Ans(8,7,1) + Ans(8,7,2) + Ans(8,7,3) + Ans(8,7,4)
+ + Ans(8,7,5) + Ans(8,7,6) + Ans(8,7,7) + Ans(8,7,8) + Ans(8,7,9) = 1
+ FILLED(8,8): + Ans(8,8,1) + Ans(8,8,2) + Ans(8,8,3) + Ans(8,8,4)
+ + Ans(8,8,5) + Ans(8,8,6) + Ans(8,8,7) + Ans(8,8,8) + Ans(8,8,9) = 1
+ FILLED(8,9): + Ans(8,9,1) + Ans(8,9,2) + Ans(8,9,3) + Ans(8,9,4)
+ + Ans(8,9,5) + Ans(8,9,6) + Ans(8,9,7) + Ans(8,9,8) + Ans(8,9,9) = 1
+ FILLED(9,1): + Ans(9,1,1) + Ans(9,1,2) + Ans(9,1,3) + Ans(9,1,4)
+ + Ans(9,1,5) + Ans(9,1,6) + Ans(9,1,7) + Ans(9,1,8) + Ans(9,1,9) = 1
+ FILLED(9,2): + Ans(9,2,1) + Ans(9,2,2) + Ans(9,2,3) + Ans(9,2,4)
+ + Ans(9,2,5) + Ans(9,2,6) + Ans(9,2,7) + Ans(9,2,8) + Ans(9,2,9) = 1
+ FILLED(9,3): + Ans(9,3,1) + Ans(9,3,2) + Ans(9,3,3) + Ans(9,3,4)
+ + Ans(9,3,5) + Ans(9,3,6) + Ans(9,3,7) + Ans(9,3,8) + Ans(9,3,9) = 1
+ FILLED(9,4): + Ans(9,4,1) + Ans(9,4,2) + Ans(9,4,3) + Ans(9,4,4)
+ + Ans(9,4,5) + Ans(9,4,6) + Ans(9,4,7) + Ans(9,4,8) + Ans(9,4,9) = 1
+ FILLED(9,5): + Ans(9,5,1) + Ans(9,5,2) + Ans(9,5,3) + Ans(9,5,4)
+ + Ans(9,5,5) + Ans(9,5,6) + Ans(9,5,7) + Ans(9,5,8) + Ans(9,5,9) = 1
+ FILLED(9,6): + Ans(9,6,1) + Ans(9,6,2) + Ans(9,6,3) + Ans(9,6,4)
+ + Ans(9,6,5) + Ans(9,6,6) + Ans(9,6,7) + Ans(9,6,8) + Ans(9,6,9) = 1
+ FILLED(9,7): + Ans(9,7,1) + Ans(9,7,2) + Ans(9,7,3) + Ans(9,7,4)
+ + Ans(9,7,5) + Ans(9,7,6) + Ans(9,7,7) + Ans(9,7,8) + Ans(9,7,9) = 1
+ FILLED(9,8): + Ans(9,8,1) + Ans(9,8,2) + Ans(9,8,3) + Ans(9,8,4)
+ + Ans(9,8,5) + Ans(9,8,6) + Ans(9,8,7) + Ans(9,8,8) + Ans(9,8,9) = 1
+ FILLED(9,9): + Ans(9,9,1) + Ans(9,9,2) + Ans(9,9,3) + Ans(9,9,4)
+ + Ans(9,9,5) + Ans(9,9,6) + Ans(9,9,7) + Ans(9,9,8) + Ans(9,9,9) = 1
+ COL(1,1): + Ans(1,1,1) + Ans(1,2,1) + Ans(1,3,1) + Ans(1,4,1)
+ + Ans(1,5,1) + Ans(1,6,1) + Ans(1,7,1) + Ans(1,8,1) + Ans(1,9,1) = 1
+ COL(1,2): + Ans(2,1,1) + Ans(2,2,1) + Ans(2,3,1) + Ans(2,4,1)
+ + Ans(2,5,1) + Ans(2,6,1) + Ans(2,7,1) + Ans(2,8,1) + Ans(2,9,1) = 1
+ COL(1,3): + Ans(3,1,1) + Ans(3,2,1) + Ans(3,3,1) + Ans(3,4,1)
+ + Ans(3,5,1) + Ans(3,6,1) + Ans(3,7,1) + Ans(3,8,1) + Ans(3,9,1) = 1
+ COL(1,4): + Ans(4,1,1) + Ans(4,2,1) + Ans(4,3,1) + Ans(4,4,1)
+ + Ans(4,5,1) + Ans(4,6,1) + Ans(4,7,1) + Ans(4,8,1) + Ans(4,9,1) = 1
+ COL(1,5): + Ans(5,1,1) + Ans(5,2,1) + Ans(5,3,1) + Ans(5,4,1)
+ + Ans(5,5,1) + Ans(5,6,1) + Ans(5,7,1) + Ans(5,8,1) + Ans(5,9,1) = 1
+ COL(1,6): + Ans(6,1,1) + Ans(6,2,1) + Ans(6,3,1) + Ans(6,4,1)
+ + Ans(6,5,1) + Ans(6,6,1) + Ans(6,7,1) + Ans(6,8,1) + Ans(6,9,1) = 1
+ COL(1,7): + Ans(7,1,1) + Ans(7,2,1) + Ans(7,3,1) + Ans(7,4,1)
+ + Ans(7,5,1) + Ans(7,6,1) + Ans(7,7,1) + Ans(7,8,1) + Ans(7,9,1) = 1
+ COL(1,8): + Ans(8,1,1) + Ans(8,2,1) + Ans(8,3,1) + Ans(8,4,1)
+ + Ans(8,5,1) + Ans(8,6,1) + Ans(8,7,1) + Ans(8,8,1) + Ans(8,9,1) = 1
+ COL(1,9): + Ans(9,1,1) + Ans(9,2,1) + Ans(9,3,1) + Ans(9,4,1)
+ + Ans(9,5,1) + Ans(9,6,1) + Ans(9,7,1) + Ans(9,8,1) + Ans(9,9,1) = 1
+ COL(2,1): + Ans(1,1,2) + Ans(1,2,2) + Ans(1,3,2) + Ans(1,4,2)
+ + Ans(1,5,2) + Ans(1,6,2) + Ans(1,7,2) + Ans(1,8,2) + Ans(1,9,2) = 1
+ COL(2,2): + Ans(2,1,2) + Ans(2,2,2) + Ans(2,3,2) + Ans(2,4,2)
+ + Ans(2,5,2) + Ans(2,6,2) + Ans(2,7,2) + Ans(2,8,2) + Ans(2,9,2) = 1
+ COL(2,3): + Ans(3,1,2) + Ans(3,2,2) + Ans(3,3,2) + Ans(3,4,2)
+ + Ans(3,5,2) + Ans(3,6,2) + Ans(3,7,2) + Ans(3,8,2) + Ans(3,9,2) = 1
+ COL(2,4): + Ans(4,1,2) + Ans(4,2,2) + Ans(4,3,2) + Ans(4,4,2)
+ + Ans(4,5,2) + Ans(4,6,2) + Ans(4,7,2) + Ans(4,8,2) + Ans(4,9,2) = 1
+ COL(2,5): + Ans(5,1,2) + Ans(5,2,2) + Ans(5,3,2) + Ans(5,4,2)
+ + Ans(5,5,2) + Ans(5,6,2) + Ans(5,7,2) + Ans(5,8,2) + Ans(5,9,2) = 1
+ COL(2,6): + Ans(6,1,2) + Ans(6,2,2) + Ans(6,3,2) + Ans(6,4,2)
+ + Ans(6,5,2) + Ans(6,6,2) + Ans(6,7,2) + Ans(6,8,2) + Ans(6,9,2) = 1
+ COL(2,7): + Ans(7,1,2) + Ans(7,2,2) + Ans(7,3,2) + Ans(7,4,2)
+ + Ans(7,5,2) + Ans(7,6,2) + Ans(7,7,2) + Ans(7,8,2) + Ans(7,9,2) = 1
+ COL(2,8): + Ans(8,1,2) + Ans(8,2,2) + Ans(8,3,2) + Ans(8,4,2)
+ + Ans(8,5,2) + Ans(8,6,2) + Ans(8,7,2) + Ans(8,8,2) + Ans(8,9,2) = 1
+ COL(2,9): + Ans(9,1,2) + Ans(9,2,2) + Ans(9,3,2) + Ans(9,4,2)
+ + Ans(9,5,2) + Ans(9,6,2) + Ans(9,7,2) + Ans(9,8,2) + Ans(9,9,2) = 1
+ COL(3,1): + Ans(1,1,3) + Ans(1,2,3) + Ans(1,3,3) + Ans(1,4,3)
+ + Ans(1,5,3) + Ans(1,6,3) + Ans(1,7,3) + Ans(1,8,3) + Ans(1,9,3) = 1
+ COL(3,2): + Ans(2,1,3) + Ans(2,2,3) + Ans(2,3,3) + Ans(2,4,3)
+ + Ans(2,5,3) + Ans(2,6,3) + Ans(2,7,3) + Ans(2,8,3) + Ans(2,9,3) = 1
+ COL(3,3): + Ans(3,1,3) + Ans(3,2,3) + Ans(3,3,3) + Ans(3,4,3)
+ + Ans(3,5,3) + Ans(3,6,3) + Ans(3,7,3) + Ans(3,8,3) + Ans(3,9,3) = 1
+ COL(3,4): + Ans(4,1,3) + Ans(4,2,3) + Ans(4,3,3) + Ans(4,4,3)
+ + Ans(4,5,3) + Ans(4,6,3) + Ans(4,7,3) + Ans(4,8,3) + Ans(4,9,3) = 1
+ COL(3,5): + Ans(5,1,3) + Ans(5,2,3) + Ans(5,3,3) + Ans(5,4,3)
+ + Ans(5,5,3) + Ans(5,6,3) + Ans(5,7,3) + Ans(5,8,3) + Ans(5,9,3) = 1
+ COL(3,6): + Ans(6,1,3) + Ans(6,2,3) + Ans(6,3,3) + Ans(6,4,3)
+ + Ans(6,5,3) + Ans(6,6,3) + Ans(6,7,3) + Ans(6,8,3) + Ans(6,9,3) = 1
+ COL(3,7): + Ans(7,1,3) + Ans(7,2,3) + Ans(7,3,3) + Ans(7,4,3)
+ + Ans(7,5,3) + Ans(7,6,3) + Ans(7,7,3) + Ans(7,8,3) + Ans(7,9,3) = 1
+ COL(3,8): + Ans(8,1,3) + Ans(8,2,3) + Ans(8,3,3) + Ans(8,4,3)
+ + Ans(8,5,3) + Ans(8,6,3) + Ans(8,7,3) + Ans(8,8,3) + Ans(8,9,3) = 1
+ COL(3,9): + Ans(9,1,3) + Ans(9,2,3) + Ans(9,3,3) + Ans(9,4,3)
+ + Ans(9,5,3) + Ans(9,6,3) + Ans(9,7,3) + Ans(9,8,3) + Ans(9,9,3) = 1
+ COL(4,1): + Ans(1,1,4) + Ans(1,2,4) + Ans(1,3,4) + Ans(1,4,4)
+ + Ans(1,5,4) + Ans(1,6,4) + Ans(1,7,4) + Ans(1,8,4) + Ans(1,9,4) = 1
+ COL(4,2): + Ans(2,1,4) + Ans(2,2,4) + Ans(2,3,4) + Ans(2,4,4)
+ + Ans(2,5,4) + Ans(2,6,4) + Ans(2,7,4) + Ans(2,8,4) + Ans(2,9,4) = 1
+ COL(4,3): + Ans(3,1,4) + Ans(3,2,4) + Ans(3,3,4) + Ans(3,4,4)
+ + Ans(3,5,4) + Ans(3,6,4) + Ans(3,7,4) + Ans(3,8,4) + Ans(3,9,4) = 1
+ COL(4,4): + Ans(4,1,4) + Ans(4,2,4) + Ans(4,3,4) + Ans(4,4,4)
+ + Ans(4,5,4) + Ans(4,6,4) + Ans(4,7,4) + Ans(4,8,4) + Ans(4,9,4) = 1
+ COL(4,5): + Ans(5,1,4) + Ans(5,2,4) + Ans(5,3,4) + Ans(5,4,4)
+ + Ans(5,5,4) + Ans(5,6,4) + Ans(5,7,4) + Ans(5,8,4) + Ans(5,9,4) = 1
+ COL(4,6): + Ans(6,1,4) + Ans(6,2,4) + Ans(6,3,4) + Ans(6,4,4)
+ + Ans(6,5,4) + Ans(6,6,4) + Ans(6,7,4) + Ans(6,8,4) + Ans(6,9,4) = 1
+ COL(4,7): + Ans(7,1,4) + Ans(7,2,4) + Ans(7,3,4) + Ans(7,4,4)
+ + Ans(7,5,4) + Ans(7,6,4) + Ans(7,7,4) + Ans(7,8,4) + Ans(7,9,4) = 1
+ COL(4,8): + Ans(8,1,4) + Ans(8,2,4) + Ans(8,3,4) + Ans(8,4,4)
+ + Ans(8,5,4) + Ans(8,6,4) + Ans(8,7,4) + Ans(8,8,4) + Ans(8,9,4) = 1
+ COL(4,9): + Ans(9,1,4) + Ans(9,2,4) + Ans(9,3,4) + Ans(9,4,4)
+ + Ans(9,5,4) + Ans(9,6,4) + Ans(9,7,4) + Ans(9,8,4) + Ans(9,9,4) = 1
+ COL(5,1): + Ans(1,1,5) + Ans(1,2,5) + Ans(1,3,5) + Ans(1,4,5)
+ + Ans(1,5,5) + Ans(1,6,5) + Ans(1,7,5) + Ans(1,8,5) + Ans(1,9,5) = 1
+ COL(5,2): + Ans(2,1,5) + Ans(2,2,5) + Ans(2,3,5) + Ans(2,4,5)
+ + Ans(2,5,5) + Ans(2,6,5) + Ans(2,7,5) + Ans(2,8,5) + Ans(2,9,5) = 1
+ COL(5,3): + Ans(3,1,5) + Ans(3,2,5) + Ans(3,3,5) + Ans(3,4,5)
+ + Ans(3,5,5) + Ans(3,6,5) + Ans(3,7,5) + Ans(3,8,5) + Ans(3,9,5) = 1
+ COL(5,4): + Ans(4,1,5) + Ans(4,2,5) + Ans(4,3,5) + Ans(4,4,5)
+ + Ans(4,5,5) + Ans(4,6,5) + Ans(4,7,5) + Ans(4,8,5) + Ans(4,9,5) = 1
+ COL(5,5): + Ans(5,1,5) + Ans(5,2,5) + Ans(5,3,5) + Ans(5,4,5)
+ + Ans(5,5,5) + Ans(5,6,5) + Ans(5,7,5) + Ans(5,8,5) + Ans(5,9,5) = 1
+ COL(5,6): + Ans(6,1,5) + Ans(6,2,5) + Ans(6,3,5) + Ans(6,4,5)
+ + Ans(6,5,5) + Ans(6,6,5) + Ans(6,7,5) + Ans(6,8,5) + Ans(6,9,5) = 1
+ COL(5,7): + Ans(7,1,5) + Ans(7,2,5) + Ans(7,3,5) + Ans(7,4,5)
+ + Ans(7,5,5) + Ans(7,6,5) + Ans(7,7,5) + Ans(7,8,5) + Ans(7,9,5) = 1
+ COL(5,8): + Ans(8,1,5) + Ans(8,2,5) + Ans(8,3,5) + Ans(8,4,5)
+ + Ans(8,5,5) + Ans(8,6,5) + Ans(8,7,5) + Ans(8,8,5) + Ans(8,9,5) = 1
+ COL(5,9): + Ans(9,1,5) + Ans(9,2,5) + Ans(9,3,5) + Ans(9,4,5)
+ + Ans(9,5,5) + Ans(9,6,5) + Ans(9,7,5) + Ans(9,8,5) + Ans(9,9,5) = 1
+ COL(6,1): + Ans(1,1,6) + Ans(1,2,6) + Ans(1,3,6) + Ans(1,4,6)
+ + Ans(1,5,6) + Ans(1,6,6) + Ans(1,7,6) + Ans(1,8,6) + Ans(1,9,6) = 1
+ COL(6,2): + Ans(2,1,6) + Ans(2,2,6) + Ans(2,3,6) + Ans(2,4,6)
+ + Ans(2,5,6) + Ans(2,6,6) + Ans(2,7,6) + Ans(2,8,6) + Ans(2,9,6) = 1
+ COL(6,3): + Ans(3,1,6) + Ans(3,2,6) + Ans(3,3,6) + Ans(3,4,6)
+ + Ans(3,5,6) + Ans(3,6,6) + Ans(3,7,6) + Ans(3,8,6) + Ans(3,9,6) = 1
+ COL(6,4): + Ans(4,1,6) + Ans(4,2,6) + Ans(4,3,6) + Ans(4,4,6)
+ + Ans(4,5,6) + Ans(4,6,6) + Ans(4,7,6) + Ans(4,8,6) + Ans(4,9,6) = 1
+ COL(6,5): + Ans(5,1,6) + Ans(5,2,6) + Ans(5,3,6) + Ans(5,4,6)
+ + Ans(5,5,6) + Ans(5,6,6) + Ans(5,7,6) + Ans(5,8,6) + Ans(5,9,6) = 1
+ COL(6,6): + Ans(6,1,6) + Ans(6,2,6) + Ans(6,3,6) + Ans(6,4,6)
+ + Ans(6,5,6) + Ans(6,6,6) + Ans(6,7,6) + Ans(6,8,6) + Ans(6,9,6) = 1
+ COL(6,7): + Ans(7,1,6) + Ans(7,2,6) + Ans(7,3,6) + Ans(7,4,6)
+ + Ans(7,5,6) + Ans(7,6,6) + Ans(7,7,6) + Ans(7,8,6) + Ans(7,9,6) = 1
+ COL(6,8): + Ans(8,1,6) + Ans(8,2,6) + Ans(8,3,6) + Ans(8,4,6)
+ + Ans(8,5,6) + Ans(8,6,6) + Ans(8,7,6) + Ans(8,8,6) + Ans(8,9,6) = 1
+ COL(6,9): + Ans(9,1,6) + Ans(9,2,6) + Ans(9,3,6) + Ans(9,4,6)
+ + Ans(9,5,6) + Ans(9,6,6) + Ans(9,7,6) + Ans(9,8,6) + Ans(9,9,6) = 1
+ COL(7,1): + Ans(1,1,7) + Ans(1,2,7) + Ans(1,3,7) + Ans(1,4,7)
+ + Ans(1,5,7) + Ans(1,6,7) + Ans(1,7,7) + Ans(1,8,7) + Ans(1,9,7) = 1
+ COL(7,2): + Ans(2,1,7) + Ans(2,2,7) + Ans(2,3,7) + Ans(2,4,7)
+ + Ans(2,5,7) + Ans(2,6,7) + Ans(2,7,7) + Ans(2,8,7) + Ans(2,9,7) = 1
+ COL(7,3): + Ans(3,1,7) + Ans(3,2,7) + Ans(3,3,7) + Ans(3,4,7)
+ + Ans(3,5,7) + Ans(3,6,7) + Ans(3,7,7) + Ans(3,8,7) + Ans(3,9,7) = 1
+ COL(7,4): + Ans(4,1,7) + Ans(4,2,7) + Ans(4,3,7) + Ans(4,4,7)
+ + Ans(4,5,7) + Ans(4,6,7) + Ans(4,7,7) + Ans(4,8,7) + Ans(4,9,7) = 1
+ COL(7,5): + Ans(5,1,7) + Ans(5,2,7) + Ans(5,3,7) + Ans(5,4,7)
+ + Ans(5,5,7) + Ans(5,6,7) + Ans(5,7,7) + Ans(5,8,7) + Ans(5,9,7) = 1
+ COL(7,6): + Ans(6,1,7) + Ans(6,2,7) + Ans(6,3,7) + Ans(6,4,7)
+ + Ans(6,5,7) + Ans(6,6,7) + Ans(6,7,7) + Ans(6,8,7) + Ans(6,9,7) = 1
+ COL(7,7): + Ans(7,1,7) + Ans(7,2,7) + Ans(7,3,7) + Ans(7,4,7)
+ + Ans(7,5,7) + Ans(7,6,7) + Ans(7,7,7) + Ans(7,8,7) + Ans(7,9,7) = 1
+ COL(7,8): + Ans(8,1,7) + Ans(8,2,7) + Ans(8,3,7) + Ans(8,4,7)
+ + Ans(8,5,7) + Ans(8,6,7) + Ans(8,7,7) + Ans(8,8,7) + Ans(8,9,7) = 1
+ COL(7,9): + Ans(9,1,7) + Ans(9,2,7) + Ans(9,3,7) + Ans(9,4,7)
+ + Ans(9,5,7) + Ans(9,6,7) + Ans(9,7,7) + Ans(9,8,7) + Ans(9,9,7) = 1
+ COL(8,1): + Ans(1,1,8) + Ans(1,2,8) + Ans(1,3,8) + Ans(1,4,8)
+ + Ans(1,5,8) + Ans(1,6,8) + Ans(1,7,8) + Ans(1,8,8) + Ans(1,9,8) = 1
+ COL(8,2): + Ans(2,1,8) + Ans(2,2,8) + Ans(2,3,8) + Ans(2,4,8)
+ + Ans(2,5,8) + Ans(2,6,8) + Ans(2,7,8) + Ans(2,8,8) + Ans(2,9,8) = 1
+ COL(8,3): + Ans(3,1,8) + Ans(3,2,8) + Ans(3,3,8) + Ans(3,4,8)
+ + Ans(3,5,8) + Ans(3,6,8) + Ans(3,7,8) + Ans(3,8,8) + Ans(3,9,8) = 1
+ COL(8,4): + Ans(4,1,8) + Ans(4,2,8) + Ans(4,3,8) + Ans(4,4,8)
+ + Ans(4,5,8) + Ans(4,6,8) + Ans(4,7,8) + Ans(4,8,8) + Ans(4,9,8) = 1
+ COL(8,5): + Ans(5,1,8) + Ans(5,2,8) + Ans(5,3,8) + Ans(5,4,8)
+ + Ans(5,5,8) + Ans(5,6,8) + Ans(5,7,8) + Ans(5,8,8) + Ans(5,9,8) = 1
+ COL(8,6): + Ans(6,1,8) + Ans(6,2,8) + Ans(6,3,8) + Ans(6,4,8)
+ + Ans(6,5,8) + Ans(6,6,8) + Ans(6,7,8) + Ans(6,8,8) + Ans(6,9,8) = 1
+ COL(8,7): + Ans(7,1,8) + Ans(7,2,8) + Ans(7,3,8) + Ans(7,4,8)
+ + Ans(7,5,8) + Ans(7,6,8) + Ans(7,7,8) + Ans(7,8,8) + Ans(7,9,8) = 1
+ COL(8,8): + Ans(8,1,8) + Ans(8,2,8) + Ans(8,3,8) + Ans(8,4,8)
+ + Ans(8,5,8) + Ans(8,6,8) + Ans(8,7,8) + Ans(8,8,8) + Ans(8,9,8) = 1
+ COL(8,9): + Ans(9,1,8) + Ans(9,2,8) + Ans(9,3,8) + Ans(9,4,8)
+ + Ans(9,5,8) + Ans(9,6,8) + Ans(9,7,8) + Ans(9,8,8) + Ans(9,9,8) = 1
+ COL(9,1): + Ans(1,1,9) + Ans(1,2,9) + Ans(1,3,9) + Ans(1,4,9)
+ + Ans(1,5,9) + Ans(1,6,9) + Ans(1,7,9) + Ans(1,8,9) + Ans(1,9,9) = 1
+ COL(9,2): + Ans(2,1,9) + Ans(2,2,9) + Ans(2,3,9) + Ans(2,4,9)
+ + Ans(2,5,9) + Ans(2,6,9) + Ans(2,7,9) + Ans(2,8,9) + Ans(2,9,9) = 1
+ COL(9,3): + Ans(3,1,9) + Ans(3,2,9) + Ans(3,3,9) + Ans(3,4,9)
+ + Ans(3,5,9) + Ans(3,6,9) + Ans(3,7,9) + Ans(3,8,9) + Ans(3,9,9) = 1
+ COL(9,4): + Ans(4,1,9) + Ans(4,2,9) + Ans(4,3,9) + Ans(4,4,9)
+ + Ans(4,5,9) + Ans(4,6,9) + Ans(4,7,9) + Ans(4,8,9) + Ans(4,9,9) = 1
+ COL(9,5): + Ans(5,1,9) + Ans(5,2,9) + Ans(5,3,9) + Ans(5,4,9)
+ + Ans(5,5,9) + Ans(5,6,9) + Ans(5,7,9) + Ans(5,8,9) + Ans(5,9,9) = 1
+ COL(9,6): + Ans(6,1,9) + Ans(6,2,9) + Ans(6,3,9) + Ans(6,4,9)
+ + Ans(6,5,9) + Ans(6,6,9) + Ans(6,7,9) + Ans(6,8,9) + Ans(6,9,9) = 1
+ COL(9,7): + Ans(7,1,9) + Ans(7,2,9) + Ans(7,3,9) + Ans(7,4,9)
+ + Ans(7,5,9) + Ans(7,6,9) + Ans(7,7,9) + Ans(7,8,9) + Ans(7,9,9) = 1
+ COL(9,8): + Ans(8,1,9) + Ans(8,2,9) + Ans(8,3,9) + Ans(8,4,9)
+ + Ans(8,5,9) + Ans(8,6,9) + Ans(8,7,9) + Ans(8,8,9) + Ans(8,9,9) = 1
+ COL(9,9): + Ans(9,1,9) + Ans(9,2,9) + Ans(9,3,9) + Ans(9,4,9)
+ + Ans(9,5,9) + Ans(9,6,9) + Ans(9,7,9) + Ans(9,8,9) + Ans(9,9,9) = 1
+ ROW(1,1): + Ans(1,1,1) + Ans(2,1,1) + Ans(3,1,1) + Ans(4,1,1)
+ + Ans(5,1,1) + Ans(6,1,1) + Ans(7,1,1) + Ans(8,1,1) + Ans(9,1,1) = 1
+ ROW(1,2): + Ans(1,2,1) + Ans(2,2,1) + Ans(3,2,1) + Ans(4,2,1)
+ + Ans(5,2,1) + Ans(6,2,1) + Ans(7,2,1) + Ans(8,2,1) + Ans(9,2,1) = 1
+ ROW(1,3): + Ans(1,3,1) + Ans(2,3,1) + Ans(3,3,1) + Ans(4,3,1)
+ + Ans(5,3,1) + Ans(6,3,1) + Ans(7,3,1) + Ans(8,3,1) + Ans(9,3,1) = 1
+ ROW(1,4): + Ans(1,4,1) + Ans(2,4,1) + Ans(3,4,1) + Ans(4,4,1)
+ + Ans(5,4,1) + Ans(6,4,1) + Ans(7,4,1) + Ans(8,4,1) + Ans(9,4,1) = 1
+ ROW(1,5): + Ans(1,5,1) + Ans(2,5,1) + Ans(3,5,1) + Ans(4,5,1)
+ + Ans(5,5,1) + Ans(6,5,1) + Ans(7,5,1) + Ans(8,5,1) + Ans(9,5,1) = 1
+ ROW(1,6): + Ans(1,6,1) + Ans(2,6,1) + Ans(3,6,1) + Ans(4,6,1)
+ + Ans(5,6,1) + Ans(6,6,1) + Ans(7,6,1) + Ans(8,6,1) + Ans(9,6,1) = 1
+ ROW(1,7): + Ans(1,7,1) + Ans(2,7,1) + Ans(3,7,1) + Ans(4,7,1)
+ + Ans(5,7,1) + Ans(6,7,1) + Ans(7,7,1) + Ans(8,7,1) + Ans(9,7,1) = 1
+ ROW(1,8): + Ans(1,8,1) + Ans(2,8,1) + Ans(3,8,1) + Ans(4,8,1)
+ + Ans(5,8,1) + Ans(6,8,1) + Ans(7,8,1) + Ans(8,8,1) + Ans(9,8,1) = 1
+ ROW(1,9): + Ans(1,9,1) + Ans(2,9,1) + Ans(3,9,1) + Ans(4,9,1)
+ + Ans(5,9,1) + Ans(6,9,1) + Ans(7,9,1) + Ans(8,9,1) + Ans(9,9,1) = 1
+ ROW(2,1): + Ans(1,1,2) + Ans(2,1,2) + Ans(3,1,2) + Ans(4,1,2)
+ + Ans(5,1,2) + Ans(6,1,2) + Ans(7,1,2) + Ans(8,1,2) + Ans(9,1,2) = 1
+ ROW(2,2): + Ans(1,2,2) + Ans(2,2,2) + Ans(3,2,2) + Ans(4,2,2)
+ + Ans(5,2,2) + Ans(6,2,2) + Ans(7,2,2) + Ans(8,2,2) + Ans(9,2,2) = 1
+ ROW(2,3): + Ans(1,3,2) + Ans(2,3,2) + Ans(3,3,2) + Ans(4,3,2)
+ + Ans(5,3,2) + Ans(6,3,2) + Ans(7,3,2) + Ans(8,3,2) + Ans(9,3,2) = 1
+ ROW(2,4): + Ans(1,4,2) + Ans(2,4,2) + Ans(3,4,2) + Ans(4,4,2)
+ + Ans(5,4,2) + Ans(6,4,2) + Ans(7,4,2) + Ans(8,4,2) + Ans(9,4,2) = 1
+ ROW(2,5): + Ans(1,5,2) + Ans(2,5,2) + Ans(3,5,2) + Ans(4,5,2)
+ + Ans(5,5,2) + Ans(6,5,2) + Ans(7,5,2) + Ans(8,5,2) + Ans(9,5,2) = 1
+ ROW(2,6): + Ans(1,6,2) + Ans(2,6,2) + Ans(3,6,2) + Ans(4,6,2)
+ + Ans(5,6,2) + Ans(6,6,2) + Ans(7,6,2) + Ans(8,6,2) + Ans(9,6,2) = 1
+ ROW(2,7): + Ans(1,7,2) + Ans(2,7,2) + Ans(3,7,2) + Ans(4,7,2)
+ + Ans(5,7,2) + Ans(6,7,2) + Ans(7,7,2) + Ans(8,7,2) + Ans(9,7,2) = 1
+ ROW(2,8): + Ans(1,8,2) + Ans(2,8,2) + Ans(3,8,2) + Ans(4,8,2)
+ + Ans(5,8,2) + Ans(6,8,2) + Ans(7,8,2) + Ans(8,8,2) + Ans(9,8,2) = 1
+ ROW(2,9): + Ans(1,9,2) + Ans(2,9,2) + Ans(3,9,2) + Ans(4,9,2)
+ + Ans(5,9,2) + Ans(6,9,2) + Ans(7,9,2) + Ans(8,9,2) + Ans(9,9,2) = 1
+ ROW(3,1): + Ans(1,1,3) + Ans(2,1,3) + Ans(3,1,3) + Ans(4,1,3)
+ + Ans(5,1,3) + Ans(6,1,3) + Ans(7,1,3) + Ans(8,1,3) + Ans(9,1,3) = 1
+ ROW(3,2): + Ans(1,2,3) + Ans(2,2,3) + Ans(3,2,3) + Ans(4,2,3)
+ + Ans(5,2,3) + Ans(6,2,3) + Ans(7,2,3) + Ans(8,2,3) + Ans(9,2,3) = 1
+ ROW(3,3): + Ans(1,3,3) + Ans(2,3,3) + Ans(3,3,3) + Ans(4,3,3)
+ + Ans(5,3,3) + Ans(6,3,3) + Ans(7,3,3) + Ans(8,3,3) + Ans(9,3,3) = 1
+ ROW(3,4): + Ans(1,4,3) + Ans(2,4,3) + Ans(3,4,3) + Ans(4,4,3)
+ + Ans(5,4,3) + Ans(6,4,3) + Ans(7,4,3) + Ans(8,4,3) + Ans(9,4,3) = 1
+ ROW(3,5): + Ans(1,5,3) + Ans(2,5,3) + Ans(3,5,3) + Ans(4,5,3)
+ + Ans(5,5,3) + Ans(6,5,3) + Ans(7,5,3) + Ans(8,5,3) + Ans(9,5,3) = 1
+ ROW(3,6): + Ans(1,6,3) + Ans(2,6,3) + Ans(3,6,3) + Ans(4,6,3)
+ + Ans(5,6,3) + Ans(6,6,3) + Ans(7,6,3) + Ans(8,6,3) + Ans(9,6,3) = 1
+ ROW(3,7): + Ans(1,7,3) + Ans(2,7,3) + Ans(3,7,3) + Ans(4,7,3)
+ + Ans(5,7,3) + Ans(6,7,3) + Ans(7,7,3) + Ans(8,7,3) + Ans(9,7,3) = 1
+ ROW(3,8): + Ans(1,8,3) + Ans(2,8,3) + Ans(3,8,3) + Ans(4,8,3)
+ + Ans(5,8,3) + Ans(6,8,3) + Ans(7,8,3) + Ans(8,8,3) + Ans(9,8,3) = 1
+ ROW(3,9): + Ans(1,9,3) + Ans(2,9,3) + Ans(3,9,3) + Ans(4,9,3)
+ + Ans(5,9,3) + Ans(6,9,3) + Ans(7,9,3) + Ans(8,9,3) + Ans(9,9,3) = 1
+ ROW(4,1): + Ans(1,1,4) + Ans(2,1,4) + Ans(3,1,4) + Ans(4,1,4)
+ + Ans(5,1,4) + Ans(6,1,4) + Ans(7,1,4) + Ans(8,1,4) + Ans(9,1,4) = 1
+ ROW(4,2): + Ans(1,2,4) + Ans(2,2,4) + Ans(3,2,4) + Ans(4,2,4)
+ + Ans(5,2,4) + Ans(6,2,4) + Ans(7,2,4) + Ans(8,2,4) + Ans(9,2,4) = 1
+ ROW(4,3): + Ans(1,3,4) + Ans(2,3,4) + Ans(3,3,4) + Ans(4,3,4)
+ + Ans(5,3,4) + Ans(6,3,4) + Ans(7,3,4) + Ans(8,3,4) + Ans(9,3,4) = 1
+ ROW(4,4): + Ans(1,4,4) + Ans(2,4,4) + Ans(3,4,4) + Ans(4,4,4)
+ + Ans(5,4,4) + Ans(6,4,4) + Ans(7,4,4) + Ans(8,4,4) + Ans(9,4,4) = 1
+ ROW(4,5): + Ans(1,5,4) + Ans(2,5,4) + Ans(3,5,4) + Ans(4,5,4)
+ + Ans(5,5,4) + Ans(6,5,4) + Ans(7,5,4) + Ans(8,5,4) + Ans(9,5,4) = 1
+ ROW(4,6): + Ans(1,6,4) + Ans(2,6,4) + Ans(3,6,4) + Ans(4,6,4)
+ + Ans(5,6,4) + Ans(6,6,4) + Ans(7,6,4) + Ans(8,6,4) + Ans(9,6,4) = 1
+ ROW(4,7): + Ans(1,7,4) + Ans(2,7,4) + Ans(3,7,4) + Ans(4,7,4)
+ + Ans(5,7,4) + Ans(6,7,4) + Ans(7,7,4) + Ans(8,7,4) + Ans(9,7,4) = 1
+ ROW(4,8): + Ans(1,8,4) + Ans(2,8,4) + Ans(3,8,4) + Ans(4,8,4)
+ + Ans(5,8,4) + Ans(6,8,4) + Ans(7,8,4) + Ans(8,8,4) + Ans(9,8,4) = 1
+ ROW(4,9): + Ans(1,9,4) + Ans(2,9,4) + Ans(3,9,4) + Ans(4,9,4)
+ + Ans(5,9,4) + Ans(6,9,4) + Ans(7,9,4) + Ans(8,9,4) + Ans(9,9,4) = 1
+ ROW(5,1): + Ans(1,1,5) + Ans(2,1,5) + Ans(3,1,5) + Ans(4,1,5)
+ + Ans(5,1,5) + Ans(6,1,5) + Ans(7,1,5) + Ans(8,1,5) + Ans(9,1,5) = 1
+ ROW(5,2): + Ans(1,2,5) + Ans(2,2,5) + Ans(3,2,5) + Ans(4,2,5)
+ + Ans(5,2,5) + Ans(6,2,5) + Ans(7,2,5) + Ans(8,2,5) + Ans(9,2,5) = 1
+ ROW(5,3): + Ans(1,3,5) + Ans(2,3,5) + Ans(3,3,5) + Ans(4,3,5)
+ + Ans(5,3,5) + Ans(6,3,5) + Ans(7,3,5) + Ans(8,3,5) + Ans(9,3,5) = 1
+ ROW(5,4): + Ans(1,4,5) + Ans(2,4,5) + Ans(3,4,5) + Ans(4,4,5)
+ + Ans(5,4,5) + Ans(6,4,5) + Ans(7,4,5) + Ans(8,4,5) + Ans(9,4,5) = 1
+ ROW(5,5): + Ans(1,5,5) + Ans(2,5,5) + Ans(3,5,5) + Ans(4,5,5)
+ + Ans(5,5,5) + Ans(6,5,5) + Ans(7,5,5) + Ans(8,5,5) + Ans(9,5,5) = 1
+ ROW(5,6): + Ans(1,6,5) + Ans(2,6,5) + Ans(3,6,5) + Ans(4,6,5)
+ + Ans(5,6,5) + Ans(6,6,5) + Ans(7,6,5) + Ans(8,6,5) + Ans(9,6,5) = 1
+ ROW(5,7): + Ans(1,7,5) + Ans(2,7,5) + Ans(3,7,5) + Ans(4,7,5)
+ + Ans(5,7,5) + Ans(6,7,5) + Ans(7,7,5) + Ans(8,7,5) + Ans(9,7,5) = 1
+ ROW(5,8): + Ans(1,8,5) + Ans(2,8,5) + Ans(3,8,5) + Ans(4,8,5)
+ + Ans(5,8,5) + Ans(6,8,5) + Ans(7,8,5) + Ans(8,8,5) + Ans(9,8,5) = 1
+ ROW(5,9): + Ans(1,9,5) + Ans(2,9,5) + Ans(3,9,5) + Ans(4,9,5)
+ + Ans(5,9,5) + Ans(6,9,5) + Ans(7,9,5) + Ans(8,9,5) + Ans(9,9,5) = 1
+ ROW(6,1): + Ans(1,1,6) + Ans(2,1,6) + Ans(3,1,6) + Ans(4,1,6)
+ + Ans(5,1,6) + Ans(6,1,6) + Ans(7,1,6) + Ans(8,1,6) + Ans(9,1,6) = 1
+ ROW(6,2): + Ans(1,2,6) + Ans(2,2,6) + Ans(3,2,6) + Ans(4,2,6)
+ + Ans(5,2,6) + Ans(6,2,6) + Ans(7,2,6) + Ans(8,2,6) + Ans(9,2,6) = 1
+ ROW(6,3): + Ans(1,3,6) + Ans(2,3,6) + Ans(3,3,6) + Ans(4,3,6)
+ + Ans(5,3,6) + Ans(6,3,6) + Ans(7,3,6) + Ans(8,3,6) + Ans(9,3,6) = 1
+ ROW(6,4): + Ans(1,4,6) + Ans(2,4,6) + Ans(3,4,6) + Ans(4,4,6)
+ + Ans(5,4,6) + Ans(6,4,6) + Ans(7,4,6) + Ans(8,4,6) + Ans(9,4,6) = 1
+ ROW(6,5): + Ans(1,5,6) + Ans(2,5,6) + Ans(3,5,6) + Ans(4,5,6)
+ + Ans(5,5,6) + Ans(6,5,6) + Ans(7,5,6) + Ans(8,5,6) + Ans(9,5,6) = 1
+ ROW(6,6): + Ans(1,6,6) + Ans(2,6,6) + Ans(3,6,6) + Ans(4,6,6)
+ + Ans(5,6,6) + Ans(6,6,6) + Ans(7,6,6) + Ans(8,6,6) + Ans(9,6,6) = 1
+ ROW(6,7): + Ans(1,7,6) + Ans(2,7,6) + Ans(3,7,6) + Ans(4,7,6)
+ + Ans(5,7,6) + Ans(6,7,6) + Ans(7,7,6) + Ans(8,7,6) + Ans(9,7,6) = 1
+ ROW(6,8): + Ans(1,8,6) + Ans(2,8,6) + Ans(3,8,6) + Ans(4,8,6)
+ + Ans(5,8,6) + Ans(6,8,6) + Ans(7,8,6) + Ans(8,8,6) + Ans(9,8,6) = 1
+ ROW(6,9): + Ans(1,9,6) + Ans(2,9,6) + Ans(3,9,6) + Ans(4,9,6)
+ + Ans(5,9,6) + Ans(6,9,6) + Ans(7,9,6) + Ans(8,9,6) + Ans(9,9,6) = 1
+ ROW(7,1): + Ans(1,1,7) + Ans(2,1,7) + Ans(3,1,7) + Ans(4,1,7)
+ + Ans(5,1,7) + Ans(6,1,7) + Ans(7,1,7) + Ans(8,1,7) + Ans(9,1,7) = 1
+ ROW(7,2): + Ans(1,2,7) + Ans(2,2,7) + Ans(3,2,7) + Ans(4,2,7)
+ + Ans(5,2,7) + Ans(6,2,7) + Ans(7,2,7) + Ans(8,2,7) + Ans(9,2,7) = 1
+ ROW(7,3): + Ans(1,3,7) + Ans(2,3,7) + Ans(3,3,7) + Ans(4,3,7)
+ + Ans(5,3,7) + Ans(6,3,7) + Ans(7,3,7) + Ans(8,3,7) + Ans(9,3,7) = 1
+ ROW(7,4): + Ans(1,4,7) + Ans(2,4,7) + Ans(3,4,7) + Ans(4,4,7)
+ + Ans(5,4,7) + Ans(6,4,7) + Ans(7,4,7) + Ans(8,4,7) + Ans(9,4,7) = 1
+ ROW(7,5): + Ans(1,5,7) + Ans(2,5,7) + Ans(3,5,7) + Ans(4,5,7)
+ + Ans(5,5,7) + Ans(6,5,7) + Ans(7,5,7) + Ans(8,5,7) + Ans(9,5,7) = 1
+ ROW(7,6): + Ans(1,6,7) + Ans(2,6,7) + Ans(3,6,7) + Ans(4,6,7)
+ + Ans(5,6,7) + Ans(6,6,7) + Ans(7,6,7) + Ans(8,6,7) + Ans(9,6,7) = 1
+ ROW(7,7): + Ans(1,7,7) + Ans(2,7,7) + Ans(3,7,7) + Ans(4,7,7)
+ + Ans(5,7,7) + Ans(6,7,7) + Ans(7,7,7) + Ans(8,7,7) + Ans(9,7,7) = 1
+ ROW(7,8): + Ans(1,8,7) + Ans(2,8,7) + Ans(3,8,7) + Ans(4,8,7)
+ + Ans(5,8,7) + Ans(6,8,7) + Ans(7,8,7) + Ans(8,8,7) + Ans(9,8,7) = 1
+ ROW(7,9): + Ans(1,9,7) + Ans(2,9,7) + Ans(3,9,7) + Ans(4,9,7)
+ + Ans(5,9,7) + Ans(6,9,7) + Ans(7,9,7) + Ans(8,9,7) + Ans(9,9,7) = 1
+ ROW(8,1): + Ans(1,1,8) + Ans(2,1,8) + Ans(3,1,8) + Ans(4,1,8)
+ + Ans(5,1,8) + Ans(6,1,8) + Ans(7,1,8) + Ans(8,1,8) + Ans(9,1,8) = 1
+ ROW(8,2): + Ans(1,2,8) + Ans(2,2,8) + Ans(3,2,8) + Ans(4,2,8)
+ + Ans(5,2,8) + Ans(6,2,8) + Ans(7,2,8) + Ans(8,2,8) + Ans(9,2,8) = 1
+ ROW(8,3): + Ans(1,3,8) + Ans(2,3,8) + Ans(3,3,8) + Ans(4,3,8)
+ + Ans(5,3,8) + Ans(6,3,8) + Ans(7,3,8) + Ans(8,3,8) + Ans(9,3,8) = 1
+ ROW(8,4): + Ans(1,4,8) + Ans(2,4,8) + Ans(3,4,8) + Ans(4,4,8)
+ + Ans(5,4,8) + Ans(6,4,8) + Ans(7,4,8) + Ans(8,4,8) + Ans(9,4,8) = 1
+ ROW(8,5): + Ans(1,5,8) + Ans(2,5,8) + Ans(3,5,8) + Ans(4,5,8)
+ + Ans(5,5,8) + Ans(6,5,8) + Ans(7,5,8) + Ans(8,5,8) + Ans(9,5,8) = 1
+ ROW(8,6): + Ans(1,6,8) + Ans(2,6,8) + Ans(3,6,8) + Ans(4,6,8)
+ + Ans(5,6,8) + Ans(6,6,8) + Ans(7,6,8) + Ans(8,6,8) + Ans(9,6,8) = 1
+ ROW(8,7): + Ans(1,7,8) + Ans(2,7,8) + Ans(3,7,8) + Ans(4,7,8)
+ + Ans(5,7,8) + Ans(6,7,8) + Ans(7,7,8) + Ans(8,7,8) + Ans(9,7,8) = 1
+ ROW(8,8): + Ans(1,8,8) + Ans(2,8,8) + Ans(3,8,8) + Ans(4,8,8)
+ + Ans(5,8,8) + Ans(6,8,8) + Ans(7,8,8) + Ans(8,8,8) + Ans(9,8,8) = 1
+ ROW(8,9): + Ans(1,9,8) + Ans(2,9,8) + Ans(3,9,8) + Ans(4,9,8)
+ + Ans(5,9,8) + Ans(6,9,8) + Ans(7,9,8) + Ans(8,9,8) + Ans(9,9,8) = 1
+ ROW(9,1): + Ans(1,1,9) + Ans(2,1,9) + Ans(3,1,9) + Ans(4,1,9)
+ + Ans(5,1,9) + Ans(6,1,9) + Ans(7,1,9) + Ans(8,1,9) + Ans(9,1,9) = 1
+ ROW(9,2): + Ans(1,2,9) + Ans(2,2,9) + Ans(3,2,9) + Ans(4,2,9)
+ + Ans(5,2,9) + Ans(6,2,9) + Ans(7,2,9) + Ans(8,2,9) + Ans(9,2,9) = 1
+ ROW(9,3): + Ans(1,3,9) + Ans(2,3,9) + Ans(3,3,9) + Ans(4,3,9)
+ + Ans(5,3,9) + Ans(6,3,9) + Ans(7,3,9) + Ans(8,3,9) + Ans(9,3,9) = 1
+ ROW(9,4): + Ans(1,4,9) + Ans(2,4,9) + Ans(3,4,9) + Ans(4,4,9)
+ + Ans(5,4,9) + Ans(6,4,9) + Ans(7,4,9) + Ans(8,4,9) + Ans(9,4,9) = 1
+ ROW(9,5): + Ans(1,5,9) + Ans(2,5,9) + Ans(3,5,9) + Ans(4,5,9)
+ + Ans(5,5,9) + Ans(6,5,9) + Ans(7,5,9) + Ans(8,5,9) + Ans(9,5,9) = 1
+ ROW(9,6): + Ans(1,6,9) + Ans(2,6,9) + Ans(3,6,9) + Ans(4,6,9)
+ + Ans(5,6,9) + Ans(6,6,9) + Ans(7,6,9) + Ans(8,6,9) + Ans(9,6,9) = 1
+ ROW(9,7): + Ans(1,7,9) + Ans(2,7,9) + Ans(3,7,9) + Ans(4,7,9)
+ + Ans(5,7,9) + Ans(6,7,9) + Ans(7,7,9) + Ans(8,7,9) + Ans(9,7,9) = 1
+ ROW(9,8): + Ans(1,8,9) + Ans(2,8,9) + Ans(3,8,9) + Ans(4,8,9)
+ + Ans(5,8,9) + Ans(6,8,9) + Ans(7,8,9) + Ans(8,8,9) + Ans(9,8,9) = 1
+ ROW(9,9): + Ans(1,9,9) + Ans(2,9,9) + Ans(3,9,9) + Ans(4,9,9)
+ + Ans(5,9,9) + Ans(6,9,9) + Ans(7,9,9) + Ans(8,9,9) + Ans(9,9,9) = 1
+ BLOCK(1,0,0): + Ans(1,1,1) + Ans(1,2,1) + Ans(1,3,1) + Ans(2,1,1)
+ + Ans(2,2,1) + Ans(2,3,1) + Ans(3,1,1) + Ans(3,2,1) + Ans(3,3,1) = 1
+ BLOCK(1,0,1): + Ans(1,4,1) + Ans(1,5,1) + Ans(1,6,1) + Ans(2,4,1)
+ + Ans(2,5,1) + Ans(2,6,1) + Ans(3,4,1) + Ans(3,5,1) + Ans(3,6,1) = 1
+ BLOCK(1,0,2): + Ans(1,7,1) + Ans(1,8,1) + Ans(1,9,1) + Ans(2,7,1)
+ + Ans(2,8,1) + Ans(2,9,1) + Ans(3,7,1) + Ans(3,8,1) + Ans(3,9,1) = 1
+ BLOCK(1,1,0): + Ans(4,1,1) + Ans(4,2,1) + Ans(4,3,1) + Ans(5,1,1)
+ + Ans(5,2,1) + Ans(5,3,1) + Ans(6,1,1) + Ans(6,2,1) + Ans(6,3,1) = 1
+ BLOCK(1,1,1): + Ans(4,4,1) + Ans(4,5,1) + Ans(4,6,1) + Ans(5,4,1)
+ + Ans(5,5,1) + Ans(5,6,1) + Ans(6,4,1) + Ans(6,5,1) + Ans(6,6,1) = 1
+ BLOCK(1,1,2): + Ans(4,7,1) + Ans(4,8,1) + Ans(4,9,1) + Ans(5,7,1)
+ + Ans(5,8,1) + Ans(5,9,1) + Ans(6,7,1) + Ans(6,8,1) + Ans(6,9,1) = 1
+ BLOCK(1,2,0): + Ans(7,1,1) + Ans(7,2,1) + Ans(7,3,1) + Ans(8,1,1)
+ + Ans(8,2,1) + Ans(8,3,1) + Ans(9,1,1) + Ans(9,2,1) + Ans(9,3,1) = 1
+ BLOCK(1,2,1): + Ans(7,4,1) + Ans(7,5,1) + Ans(7,6,1) + Ans(8,4,1)
+ + Ans(8,5,1) + Ans(8,6,1) + Ans(9,4,1) + Ans(9,5,1) + Ans(9,6,1) = 1
+ BLOCK(1,2,2): + Ans(7,7,1) + Ans(7,8,1) + Ans(7,9,1) + Ans(8,7,1)
+ + Ans(8,8,1) + Ans(8,9,1) + Ans(9,7,1) + Ans(9,8,1) + Ans(9,9,1) = 1
+ BLOCK(2,0,0): + Ans(1,1,2) + Ans(1,2,2) + Ans(1,3,2) + Ans(2,1,2)
+ + Ans(2,2,2) + Ans(2,3,2) + Ans(3,1,2) + Ans(3,2,2) + Ans(3,3,2) = 1
+ BLOCK(2,0,1): + Ans(1,4,2) + Ans(1,5,2) + Ans(1,6,2) + Ans(2,4,2)
+ + Ans(2,5,2) + Ans(2,6,2) + Ans(3,4,2) + Ans(3,5,2) + Ans(3,6,2) = 1
+ BLOCK(2,0,2): + Ans(1,7,2) + Ans(1,8,2) + Ans(1,9,2) + Ans(2,7,2)
+ + Ans(2,8,2) + Ans(2,9,2) + Ans(3,7,2) + Ans(3,8,2) + Ans(3,9,2) = 1
+ BLOCK(2,1,0): + Ans(4,1,2) + Ans(4,2,2) + Ans(4,3,2) + Ans(5,1,2)
+ + Ans(5,2,2) + Ans(5,3,2) + Ans(6,1,2) + Ans(6,2,2) + Ans(6,3,2) = 1
+ BLOCK(2,1,1): + Ans(4,4,2) + Ans(4,5,2) + Ans(4,6,2) + Ans(5,4,2)
+ + Ans(5,5,2) + Ans(5,6,2) + Ans(6,4,2) + Ans(6,5,2) + Ans(6,6,2) = 1
+ BLOCK(2,1,2): + Ans(4,7,2) + Ans(4,8,2) + Ans(4,9,2) + Ans(5,7,2)
+ + Ans(5,8,2) + Ans(5,9,2) + Ans(6,7,2) + Ans(6,8,2) + Ans(6,9,2) = 1
+ BLOCK(2,2,0): + Ans(7,1,2) + Ans(7,2,2) + Ans(7,3,2) + Ans(8,1,2)
+ + Ans(8,2,2) + Ans(8,3,2) + Ans(9,1,2) + Ans(9,2,2) + Ans(9,3,2) = 1
+ BLOCK(2,2,1): + Ans(7,4,2) + Ans(7,5,2) + Ans(7,6,2) + Ans(8,4,2)
+ + Ans(8,5,2) + Ans(8,6,2) + Ans(9,4,2) + Ans(9,5,2) + Ans(9,6,2) = 1
+ BLOCK(2,2,2): + Ans(7,7,2) + Ans(7,8,2) + Ans(7,9,2) + Ans(8,7,2)
+ + Ans(8,8,2) + Ans(8,9,2) + Ans(9,7,2) + Ans(9,8,2) + Ans(9,9,2) = 1
+ BLOCK(3,0,0): + Ans(1,1,3) + Ans(1,2,3) + Ans(1,3,3) + Ans(2,1,3)
+ + Ans(2,2,3) + Ans(2,3,3) + Ans(3,1,3) + Ans(3,2,3) + Ans(3,3,3) = 1
+ BLOCK(3,0,1): + Ans(1,4,3) + Ans(1,5,3) + Ans(1,6,3) + Ans(2,4,3)
+ + Ans(2,5,3) + Ans(2,6,3) + Ans(3,4,3) + Ans(3,5,3) + Ans(3,6,3) = 1
+ BLOCK(3,0,2): + Ans(1,7,3) + Ans(1,8,3) + Ans(1,9,3) + Ans(2,7,3)
+ + Ans(2,8,3) + Ans(2,9,3) + Ans(3,7,3) + Ans(3,8,3) + Ans(3,9,3) = 1
+ BLOCK(3,1,0): + Ans(4,1,3) + Ans(4,2,3) + Ans(4,3,3) + Ans(5,1,3)
+ + Ans(5,2,3) + Ans(5,3,3) + Ans(6,1,3) + Ans(6,2,3) + Ans(6,3,3) = 1
+ BLOCK(3,1,1): + Ans(4,4,3) + Ans(4,5,3) + Ans(4,6,3) + Ans(5,4,3)
+ + Ans(5,5,3) + Ans(5,6,3) + Ans(6,4,3) + Ans(6,5,3) + Ans(6,6,3) = 1
+ BLOCK(3,1,2): + Ans(4,7,3) + Ans(4,8,3) + Ans(4,9,3) + Ans(5,7,3)
+ + Ans(5,8,3) + Ans(5,9,3) + Ans(6,7,3) + Ans(6,8,3) + Ans(6,9,3) = 1
+ BLOCK(3,2,0): + Ans(7,1,3) + Ans(7,2,3) + Ans(7,3,3) + Ans(8,1,3)
+ + Ans(8,2,3) + Ans(8,3,3) + Ans(9,1,3) + Ans(9,2,3) + Ans(9,3,3) = 1
+ BLOCK(3,2,1): + Ans(7,4,3) + Ans(7,5,3) + Ans(7,6,3) + Ans(8,4,3)
+ + Ans(8,5,3) + Ans(8,6,3) + Ans(9,4,3) + Ans(9,5,3) + Ans(9,6,3) = 1
+ BLOCK(3,2,2): + Ans(7,7,3) + Ans(7,8,3) + Ans(7,9,3) + Ans(8,7,3)
+ + Ans(8,8,3) + Ans(8,9,3) + Ans(9,7,3) + Ans(9,8,3) + Ans(9,9,3) = 1
+ BLOCK(4,0,0): + Ans(1,1,4) + Ans(1,2,4) + Ans(1,3,4) + Ans(2,1,4)
+ + Ans(2,2,4) + Ans(2,3,4) + Ans(3,1,4) + Ans(3,2,4) + Ans(3,3,4) = 1
+ BLOCK(4,0,1): + Ans(1,4,4) + Ans(1,5,4) + Ans(1,6,4) + Ans(2,4,4)
+ + Ans(2,5,4) + Ans(2,6,4) + Ans(3,4,4) + Ans(3,5,4) + Ans(3,6,4) = 1
+ BLOCK(4,0,2): + Ans(1,7,4) + Ans(1,8,4) + Ans(1,9,4) + Ans(2,7,4)
+ + Ans(2,8,4) + Ans(2,9,4) + Ans(3,7,4) + Ans(3,8,4) + Ans(3,9,4) = 1
+ BLOCK(4,1,0): + Ans(4,1,4) + Ans(4,2,4) + Ans(4,3,4) + Ans(5,1,4)
+ + Ans(5,2,4) + Ans(5,3,4) + Ans(6,1,4) + Ans(6,2,4) + Ans(6,3,4) = 1
+ BLOCK(4,1,1): + Ans(4,4,4) + Ans(4,5,4) + Ans(4,6,4) + Ans(5,4,4)
+ + Ans(5,5,4) + Ans(5,6,4) + Ans(6,4,4) + Ans(6,5,4) + Ans(6,6,4) = 1
+ BLOCK(4,1,2): + Ans(4,7,4) + Ans(4,8,4) + Ans(4,9,4) + Ans(5,7,4)
+ + Ans(5,8,4) + Ans(5,9,4) + Ans(6,7,4) + Ans(6,8,4) + Ans(6,9,4) = 1
+ BLOCK(4,2,0): + Ans(7,1,4) + Ans(7,2,4) + Ans(7,3,4) + Ans(8,1,4)
+ + Ans(8,2,4) + Ans(8,3,4) + Ans(9,1,4) + Ans(9,2,4) + Ans(9,3,4) = 1
+ BLOCK(4,2,1): + Ans(7,4,4) + Ans(7,5,4) + Ans(7,6,4) + Ans(8,4,4)
+ + Ans(8,5,4) + Ans(8,6,4) + Ans(9,4,4) + Ans(9,5,4) + Ans(9,6,4) = 1
+ BLOCK(4,2,2): + Ans(7,7,4) + Ans(7,8,4) + Ans(7,9,4) + Ans(8,7,4)
+ + Ans(8,8,4) + Ans(8,9,4) + Ans(9,7,4) + Ans(9,8,4) + Ans(9,9,4) = 1
+ BLOCK(5,0,0): + Ans(1,1,5) + Ans(1,2,5) + Ans(1,3,5) + Ans(2,1,5)
+ + Ans(2,2,5) + Ans(2,3,5) + Ans(3,1,5) + Ans(3,2,5) + Ans(3,3,5) = 1
+ BLOCK(5,0,1): + Ans(1,4,5) + Ans(1,5,5) + Ans(1,6,5) + Ans(2,4,5)
+ + Ans(2,5,5) + Ans(2,6,5) + Ans(3,4,5) + Ans(3,5,5) + Ans(3,6,5) = 1
+ BLOCK(5,0,2): + Ans(1,7,5) + Ans(1,8,5) + Ans(1,9,5) + Ans(2,7,5)
+ + Ans(2,8,5) + Ans(2,9,5) + Ans(3,7,5) + Ans(3,8,5) + Ans(3,9,5) = 1
+ BLOCK(5,1,0): + Ans(4,1,5) + Ans(4,2,5) + Ans(4,3,5) + Ans(5,1,5)
+ + Ans(5,2,5) + Ans(5,3,5) + Ans(6,1,5) + Ans(6,2,5) + Ans(6,3,5) = 1
+ BLOCK(5,1,1): + Ans(4,4,5) + Ans(4,5,5) + Ans(4,6,5) + Ans(5,4,5)
+ + Ans(5,5,5) + Ans(5,6,5) + Ans(6,4,5) + Ans(6,5,5) + Ans(6,6,5) = 1
+ BLOCK(5,1,2): + Ans(4,7,5) + Ans(4,8,5) + Ans(4,9,5) + Ans(5,7,5)
+ + Ans(5,8,5) + Ans(5,9,5) + Ans(6,7,5) + Ans(6,8,5) + Ans(6,9,5) = 1
+ BLOCK(5,2,0): + Ans(7,1,5) + Ans(7,2,5) + Ans(7,3,5) + Ans(8,1,5)
+ + Ans(8,2,5) + Ans(8,3,5) + Ans(9,1,5) + Ans(9,2,5) + Ans(9,3,5) = 1
+ BLOCK(5,2,1): + Ans(7,4,5) + Ans(7,5,5) + Ans(7,6,5) + Ans(8,4,5)
+ + Ans(8,5,5) + Ans(8,6,5) + Ans(9,4,5) + Ans(9,5,5) + Ans(9,6,5) = 1
+ BLOCK(5,2,2): + Ans(7,7,5) + Ans(7,8,5) + Ans(7,9,5) + Ans(8,7,5)
+ + Ans(8,8,5) + Ans(8,9,5) + Ans(9,7,5) + Ans(9,8,5) + Ans(9,9,5) = 1
+ BLOCK(6,0,0): + Ans(1,1,6) + Ans(1,2,6) + Ans(1,3,6) + Ans(2,1,6)
+ + Ans(2,2,6) + Ans(2,3,6) + Ans(3,1,6) + Ans(3,2,6) + Ans(3,3,6) = 1
+ BLOCK(6,0,1): + Ans(1,4,6) + Ans(1,5,6) + Ans(1,6,6) + Ans(2,4,6)
+ + Ans(2,5,6) + Ans(2,6,6) + Ans(3,4,6) + Ans(3,5,6) + Ans(3,6,6) = 1
+ BLOCK(6,0,2): + Ans(1,7,6) + Ans(1,8,6) + Ans(1,9,6) + Ans(2,7,6)
+ + Ans(2,8,6) + Ans(2,9,6) + Ans(3,7,6) + Ans(3,8,6) + Ans(3,9,6) = 1
+ BLOCK(6,1,0): + Ans(4,1,6) + Ans(4,2,6) + Ans(4,3,6) + Ans(5,1,6)
+ + Ans(5,2,6) + Ans(5,3,6) + Ans(6,1,6) + Ans(6,2,6) + Ans(6,3,6) = 1
+ BLOCK(6,1,1): + Ans(4,4,6) + Ans(4,5,6) + Ans(4,6,6) + Ans(5,4,6)
+ + Ans(5,5,6) + Ans(5,6,6) + Ans(6,4,6) + Ans(6,5,6) + Ans(6,6,6) = 1
+ BLOCK(6,1,2): + Ans(4,7,6) + Ans(4,8,6) + Ans(4,9,6) + Ans(5,7,6)
+ + Ans(5,8,6) + Ans(5,9,6) + Ans(6,7,6) + Ans(6,8,6) + Ans(6,9,6) = 1
+ BLOCK(6,2,0): + Ans(7,1,6) + Ans(7,2,6) + Ans(7,3,6) + Ans(8,1,6)
+ + Ans(8,2,6) + Ans(8,3,6) + Ans(9,1,6) + Ans(9,2,6) + Ans(9,3,6) = 1
+ BLOCK(6,2,1): + Ans(7,4,6) + Ans(7,5,6) + Ans(7,6,6) + Ans(8,4,6)
+ + Ans(8,5,6) + Ans(8,6,6) + Ans(9,4,6) + Ans(9,5,6) + Ans(9,6,6) = 1
+ BLOCK(6,2,2): + Ans(7,7,6) + Ans(7,8,6) + Ans(7,9,6) + Ans(8,7,6)
+ + Ans(8,8,6) + Ans(8,9,6) + Ans(9,7,6) + Ans(9,8,6) + Ans(9,9,6) = 1
+ BLOCK(7,0,0): + Ans(1,1,7) + Ans(1,2,7) + Ans(1,3,7) + Ans(2,1,7)
+ + Ans(2,2,7) + Ans(2,3,7) + Ans(3,1,7) + Ans(3,2,7) + Ans(3,3,7) = 1
+ BLOCK(7,0,1): + Ans(1,4,7) + Ans(1,5,7) + Ans(1,6,7) + Ans(2,4,7)
+ + Ans(2,5,7) + Ans(2,6,7) + Ans(3,4,7) + Ans(3,5,7) + Ans(3,6,7) = 1
+ BLOCK(7,0,2): + Ans(1,7,7) + Ans(1,8,7) + Ans(1,9,7) + Ans(2,7,7)
+ + Ans(2,8,7) + Ans(2,9,7) + Ans(3,7,7) + Ans(3,8,7) + Ans(3,9,7) = 1
+ BLOCK(7,1,0): + Ans(4,1,7) + Ans(4,2,7) + Ans(4,3,7) + Ans(5,1,7)
+ + Ans(5,2,7) + Ans(5,3,7) + Ans(6,1,7) + Ans(6,2,7) + Ans(6,3,7) = 1
+ BLOCK(7,1,1): + Ans(4,4,7) + Ans(4,5,7) + Ans(4,6,7) + Ans(5,4,7)
+ + Ans(5,5,7) + Ans(5,6,7) + Ans(6,4,7) + Ans(6,5,7) + Ans(6,6,7) = 1
+ BLOCK(7,1,2): + Ans(4,7,7) + Ans(4,8,7) + Ans(4,9,7) + Ans(5,7,7)
+ + Ans(5,8,7) + Ans(5,9,7) + Ans(6,7,7) + Ans(6,8,7) + Ans(6,9,7) = 1
+ BLOCK(7,2,0): + Ans(7,1,7) + Ans(7,2,7) + Ans(7,3,7) + Ans(8,1,7)
+ + Ans(8,2,7) + Ans(8,3,7) + Ans(9,1,7) + Ans(9,2,7) + Ans(9,3,7) = 1
+ BLOCK(7,2,1): + Ans(7,4,7) + Ans(7,5,7) + Ans(7,6,7) + Ans(8,4,7)
+ + Ans(8,5,7) + Ans(8,6,7) + Ans(9,4,7) + Ans(9,5,7) + Ans(9,6,7) = 1
+ BLOCK(7,2,2): + Ans(7,7,7) + Ans(7,8,7) + Ans(7,9,7) + Ans(8,7,7)
+ + Ans(8,8,7) + Ans(8,9,7) + Ans(9,7,7) + Ans(9,8,7) + Ans(9,9,7) = 1
+ BLOCK(8,0,0): + Ans(1,1,8) + Ans(1,2,8) + Ans(1,3,8) + Ans(2,1,8)
+ + Ans(2,2,8) + Ans(2,3,8) + Ans(3,1,8) + Ans(3,2,8) + Ans(3,3,8) = 1
+ BLOCK(8,0,1): + Ans(1,4,8) + Ans(1,5,8) + Ans(1,6,8) + Ans(2,4,8)
+ + Ans(2,5,8) + Ans(2,6,8) + Ans(3,4,8) + Ans(3,5,8) + Ans(3,6,8) = 1
+ BLOCK(8,0,2): + Ans(1,7,8) + Ans(1,8,8) + Ans(1,9,8) + Ans(2,7,8)
+ + Ans(2,8,8) + Ans(2,9,8) + Ans(3,7,8) + Ans(3,8,8) + Ans(3,9,8) = 1
+ BLOCK(8,1,0): + Ans(4,1,8) + Ans(4,2,8) + Ans(4,3,8) + Ans(5,1,8)
+ + Ans(5,2,8) + Ans(5,3,8) + Ans(6,1,8) + Ans(6,2,8) + Ans(6,3,8) = 1
+ BLOCK(8,1,1): + Ans(4,4,8) + Ans(4,5,8) + Ans(4,6,8) + Ans(5,4,8)
+ + Ans(5,5,8) + Ans(5,6,8) + Ans(6,4,8) + Ans(6,5,8) + Ans(6,6,8) = 1
+ BLOCK(8,1,2): + Ans(4,7,8) + Ans(4,8,8) + Ans(4,9,8) + Ans(5,7,8)
+ + Ans(5,8,8) + Ans(5,9,8) + Ans(6,7,8) + Ans(6,8,8) + Ans(6,9,8) = 1
+ BLOCK(8,2,0): + Ans(7,1,8) + Ans(7,2,8) + Ans(7,3,8) + Ans(8,1,8)
+ + Ans(8,2,8) + Ans(8,3,8) + Ans(9,1,8) + Ans(9,2,8) + Ans(9,3,8) = 1
+ BLOCK(8,2,1): + Ans(7,4,8) + Ans(7,5,8) + Ans(7,6,8) + Ans(8,4,8)
+ + Ans(8,5,8) + Ans(8,6,8) + Ans(9,4,8) + Ans(9,5,8) + Ans(9,6,8) = 1
+ BLOCK(8,2,2): + Ans(7,7,8) + Ans(7,8,8) + Ans(7,9,8) + Ans(8,7,8)
+ + Ans(8,8,8) + Ans(8,9,8) + Ans(9,7,8) + Ans(9,8,8) + Ans(9,9,8) = 1
+ BLOCK(9,0,0): + Ans(1,1,9) + Ans(1,2,9) + Ans(1,3,9) + Ans(2,1,9)
+ + Ans(2,2,9) + Ans(2,3,9) + Ans(3,1,9) + Ans(3,2,9) + Ans(3,3,9) = 1
+ BLOCK(9,0,1): + Ans(1,4,9) + Ans(1,5,9) + Ans(1,6,9) + Ans(2,4,9)
+ + Ans(2,5,9) + Ans(2,6,9) + Ans(3,4,9) + Ans(3,5,9) + Ans(3,6,9) = 1
+ BLOCK(9,0,2): + Ans(1,7,9) + Ans(1,8,9) + Ans(1,9,9) + Ans(2,7,9)
+ + Ans(2,8,9) + Ans(2,9,9) + Ans(3,7,9) + Ans(3,8,9) + Ans(3,9,9) = 1
+ BLOCK(9,1,0): + Ans(4,1,9) + Ans(4,2,9) + Ans(4,3,9) + Ans(5,1,9)
+ + Ans(5,2,9) + Ans(5,3,9) + Ans(6,1,9) + Ans(6,2,9) + Ans(6,3,9) = 1
+ BLOCK(9,1,1): + Ans(4,4,9) + Ans(4,5,9) + Ans(4,6,9) + Ans(5,4,9)
+ + Ans(5,5,9) + Ans(5,6,9) + Ans(6,4,9) + Ans(6,5,9) + Ans(6,6,9) = 1
+ BLOCK(9,1,2): + Ans(4,7,9) + Ans(4,8,9) + Ans(4,9,9) + Ans(5,7,9)
+ + Ans(5,8,9) + Ans(5,9,9) + Ans(6,7,9) + Ans(6,8,9) + Ans(6,9,9) = 1
+ BLOCK(9,2,0): + Ans(7,1,9) + Ans(7,2,9) + Ans(7,3,9) + Ans(8,1,9)
+ + Ans(8,2,9) + Ans(8,3,9) + Ans(9,1,9) + Ans(9,2,9) + Ans(9,3,9) = 1
+ BLOCK(9,2,1): + Ans(7,4,9) + Ans(7,5,9) + Ans(7,6,9) + Ans(8,4,9)
+ + Ans(8,5,9) + Ans(8,6,9) + Ans(9,4,9) + Ans(9,5,9) + Ans(9,6,9) = 1
+ BLOCK(9,2,2): + Ans(7,7,9) + Ans(7,8,9) + Ans(7,9,9) + Ans(8,7,9)
+ + Ans(8,8,9) + Ans(8,9,9) + Ans(9,7,9) + Ans(9,8,9) + Ans(9,9,9) = 1
+
+Bounds
+ 0 <= Ans(1,1,1) <= 1
+ 0 <= Ans(1,1,2) <= 1
+ 0 <= Ans(1,1,3) <= 1
+ 0 <= Ans(1,1,4) <= 1
+ 0 <= Ans(1,1,5) <= 1
+ 0 <= Ans(1,1,6) <= 1
+ 0 <= Ans(1,1,7) <= 1
+ 0 <= Ans(1,1,8) <= 1
+ 0 <= Ans(1,1,9) <= 1
+ 0 <= Ans(1,2,1) <= 1
+ 0 <= Ans(1,2,2) <= 1
+ 0 <= Ans(1,2,3) <= 1
+ 0 <= Ans(1,2,4) <= 1
+ 0 <= Ans(1,2,5) <= 1
+ 0 <= Ans(1,2,6) <= 1
+ 0 <= Ans(1,2,7) <= 1
+ 0 <= Ans(1,2,8) <= 1
+ 0 <= Ans(1,2,9) <= 1
+ 0 <= Ans(1,3,1) <= 1
+ 0 <= Ans(1,3,2) <= 1
+ 0 <= Ans(1,3,3) <= 1
+ 0 <= Ans(1,3,4) <= 1
+ 0 <= Ans(1,3,5) <= 1
+ 0 <= Ans(1,3,6) <= 1
+ 0 <= Ans(1,3,7) <= 1
+ 0 <= Ans(1,3,8) <= 1
+ 0 <= Ans(1,3,9) <= 1
+ 0 <= Ans(1,4,1) <= 1
+ 0 <= Ans(1,4,2) <= 1
+ 0 <= Ans(1,4,3) <= 1
+ 0 <= Ans(1,4,4) <= 1
+ 0 <= Ans(1,4,5) <= 1
+ 0 <= Ans(1,4,6) <= 1
+ 0 <= Ans(1,4,7) <= 1
+ 0 <= Ans(1,4,8) <= 1
+ 0 <= Ans(1,4,9) <= 1
+ 0 <= Ans(1,5,1) <= 1
+ 0 <= Ans(1,5,2) <= 1
+ 0 <= Ans(1,5,3) <= 1
+ 0 <= Ans(1,5,4) <= 1
+ 0 <= Ans(1,5,5) <= 1
+ 0 <= Ans(1,5,6) <= 1
+ 0 <= Ans(1,5,7) <= 1
+ 0 <= Ans(1,5,8) <= 1
+ 0 <= Ans(1,5,9) <= 1
+ 0 <= Ans(1,6,1) <= 1
+ 0 <= Ans(1,6,2) <= 1
+ 0 <= Ans(1,6,3) <= 1
+ 0 <= Ans(1,6,4) <= 1
+ 0 <= Ans(1,6,5) <= 1
+ 0 <= Ans(1,6,6) <= 1
+ 0 <= Ans(1,6,7) <= 1
+ 0 <= Ans(1,6,8) <= 1
+ 0 <= Ans(1,6,9) <= 1
+ 0 <= Ans(1,7,1) <= 1
+ 0 <= Ans(1,7,2) <= 1
+ 0 <= Ans(1,7,3) <= 1
+ 0 <= Ans(1,7,4) <= 1
+ 0 <= Ans(1,7,5) <= 1
+ 0 <= Ans(1,7,6) <= 1
+ 0 <= Ans(1,7,7) <= 1
+ 0 <= Ans(1,7,8) <= 1
+ 0 <= Ans(1,7,9) <= 1
+ 0 <= Ans(1,8,1) <= 1
+ 0 <= Ans(1,8,2) <= 1
+ 0 <= Ans(1,8,3) <= 1
+ 0 <= Ans(1,8,4) <= 1
+ 0 <= Ans(1,8,5) <= 1
+ 0 <= Ans(1,8,6) <= 1
+ 0 <= Ans(1,8,7) <= 1
+ 0 <= Ans(1,8,8) <= 1
+ 0 <= Ans(1,8,9) <= 1
+ 0 <= Ans(1,9,1) <= 1
+ 0 <= Ans(1,9,2) <= 1
+ 0 <= Ans(1,9,3) <= 1
+ 0 <= Ans(1,9,4) <= 1
+ 0 <= Ans(1,9,5) <= 1
+ 0 <= Ans(1,9,6) <= 1
+ 0 <= Ans(1,9,7) <= 1
+ 0 <= Ans(1,9,8) <= 1
+ 0 <= Ans(1,9,9) <= 1
+ 0 <= Ans(2,1,1) <= 1
+ 0 <= Ans(2,1,2) <= 1
+ 0 <= Ans(2,1,3) <= 1
+ 0 <= Ans(2,1,4) <= 1
+ 0 <= Ans(2,1,5) <= 1
+ 0 <= Ans(2,1,6) <= 1
+ 0 <= Ans(2,1,7) <= 1
+ 0 <= Ans(2,1,8) <= 1
+ 0 <= Ans(2,1,9) <= 1
+ 0 <= Ans(2,2,1) <= 1
+ 0 <= Ans(2,2,2) <= 1
+ 0 <= Ans(2,2,3) <= 1
+ 0 <= Ans(2,2,4) <= 1
+ 0 <= Ans(2,2,5) <= 1
+ 0 <= Ans(2,2,6) <= 1
+ 0 <= Ans(2,2,7) <= 1
+ 0 <= Ans(2,2,8) <= 1
+ 0 <= Ans(2,2,9) <= 1
+ 0 <= Ans(2,3,1) <= 1
+ 0 <= Ans(2,3,2) <= 1
+ 0 <= Ans(2,3,3) <= 1
+ 0 <= Ans(2,3,4) <= 1
+ 0 <= Ans(2,3,5) <= 1
+ 0 <= Ans(2,3,6) <= 1
+ 0 <= Ans(2,3,7) <= 1
+ 0 <= Ans(2,3,8) <= 1
+ 0 <= Ans(2,3,9) <= 1
+ 0 <= Ans(2,4,1) <= 1
+ 0 <= Ans(2,4,2) <= 1
+ 0 <= Ans(2,4,3) <= 1
+ 0 <= Ans(2,4,4) <= 1
+ 0 <= Ans(2,4,5) <= 1
+ 0 <= Ans(2,4,6) <= 1
+ 0 <= Ans(2,4,7) <= 1
+ 0 <= Ans(2,4,8) <= 1
+ 0 <= Ans(2,4,9) <= 1
+ 0 <= Ans(2,5,1) <= 1
+ 0 <= Ans(2,5,2) <= 1
+ 0 <= Ans(2,5,3) <= 1
+ 0 <= Ans(2,5,4) <= 1
+ 0 <= Ans(2,5,5) <= 1
+ 0 <= Ans(2,5,6) <= 1
+ 0 <= Ans(2,5,7) <= 1
+ 0 <= Ans(2,5,8) <= 1
+ 0 <= Ans(2,5,9) <= 1
+ 0 <= Ans(2,6,1) <= 1
+ 0 <= Ans(2,6,2) <= 1
+ 0 <= Ans(2,6,3) <= 1
+ 0 <= Ans(2,6,4) <= 1
+ 0 <= Ans(2,6,5) <= 1
+ 0 <= Ans(2,6,6) <= 1
+ 0 <= Ans(2,6,7) <= 1
+ 0 <= Ans(2,6,8) <= 1
+ 0 <= Ans(2,6,9) <= 1
+ 0 <= Ans(2,7,1) <= 1
+ 0 <= Ans(2,7,2) <= 1
+ 0 <= Ans(2,7,3) <= 1
+ 0 <= Ans(2,7,4) <= 1
+ 0 <= Ans(2,7,5) <= 1
+ 0 <= Ans(2,7,6) <= 1
+ 0 <= Ans(2,7,7) <= 1
+ 0 <= Ans(2,7,8) <= 1
+ 0 <= Ans(2,7,9) <= 1
+ 0 <= Ans(2,8,1) <= 1
+ 0 <= Ans(2,8,2) <= 1
+ 0 <= Ans(2,8,3) <= 1
+ 0 <= Ans(2,8,4) <= 1
+ 0 <= Ans(2,8,5) <= 1
+ 0 <= Ans(2,8,6) <= 1
+ 0 <= Ans(2,8,7) <= 1
+ 0 <= Ans(2,8,8) <= 1
+ 0 <= Ans(2,8,9) <= 1
+ 0 <= Ans(2,9,1) <= 1
+ 0 <= Ans(2,9,2) <= 1
+ 0 <= Ans(2,9,3) <= 1
+ 0 <= Ans(2,9,4) <= 1
+ 0 <= Ans(2,9,5) <= 1
+ 0 <= Ans(2,9,6) <= 1
+ 0 <= Ans(2,9,7) <= 1
+ 0 <= Ans(2,9,8) <= 1
+ 0 <= Ans(2,9,9) <= 1
+ 0 <= Ans(3,1,1) <= 1
+ 0 <= Ans(3,1,2) <= 1
+ 0 <= Ans(3,1,3) <= 1
+ 0 <= Ans(3,1,4) <= 1
+ 0 <= Ans(3,1,5) <= 1
+ 0 <= Ans(3,1,6) <= 1
+ 0 <= Ans(3,1,7) <= 1
+ 0 <= Ans(3,1,8) <= 1
+ 0 <= Ans(3,1,9) <= 1
+ 0 <= Ans(3,2,1) <= 1
+ 0 <= Ans(3,2,2) <= 1
+ 0 <= Ans(3,2,3) <= 1
+ 0 <= Ans(3,2,4) <= 1
+ 0 <= Ans(3,2,5) <= 1
+ 0 <= Ans(3,2,6) <= 1
+ 0 <= Ans(3,2,7) <= 1
+ 0 <= Ans(3,2,8) <= 1
+ 0 <= Ans(3,2,9) <= 1
+ 0 <= Ans(3,3,1) <= 1
+ 0 <= Ans(3,3,2) <= 1
+ 0 <= Ans(3,3,3) <= 1
+ 0 <= Ans(3,3,4) <= 1
+ 0 <= Ans(3,3,5) <= 1
+ 0 <= Ans(3,3,6) <= 1
+ 0 <= Ans(3,3,7) <= 1
+ 0 <= Ans(3,3,8) <= 1
+ 0 <= Ans(3,3,9) <= 1
+ 0 <= Ans(3,4,1) <= 1
+ 0 <= Ans(3,4,2) <= 1
+ 0 <= Ans(3,4,3) <= 1
+ 0 <= Ans(3,4,4) <= 1
+ 0 <= Ans(3,4,5) <= 1
+ 0 <= Ans(3,4,6) <= 1
+ 0 <= Ans(3,4,7) <= 1
+ 0 <= Ans(3,4,8) <= 1
+ 0 <= Ans(3,4,9) <= 1
+ 0 <= Ans(3,5,1) <= 1
+ 0 <= Ans(3,5,2) <= 1
+ 0 <= Ans(3,5,3) <= 1
+ 0 <= Ans(3,5,4) <= 1
+ 0 <= Ans(3,5,5) <= 1
+ 0 <= Ans(3,5,6) <= 1
+ 0 <= Ans(3,5,7) <= 1
+ 0 <= Ans(3,5,8) <= 1
+ 0 <= Ans(3,5,9) <= 1
+ 0 <= Ans(3,6,1) <= 1
+ 0 <= Ans(3,6,2) <= 1
+ 0 <= Ans(3,6,3) <= 1
+ 0 <= Ans(3,6,4) <= 1
+ 0 <= Ans(3,6,5) <= 1
+ 0 <= Ans(3,6,6) <= 1
+ 0 <= Ans(3,6,7) <= 1
+ 0 <= Ans(3,6,8) <= 1
+ 0 <= Ans(3,6,9) <= 1
+ 0 <= Ans(3,7,1) <= 1
+ 0 <= Ans(3,7,2) <= 1
+ 0 <= Ans(3,7,3) <= 1
+ 0 <= Ans(3,7,4) <= 1
+ 0 <= Ans(3,7,5) <= 1
+ 0 <= Ans(3,7,6) <= 1
+ 0 <= Ans(3,7,7) <= 1
+ 0 <= Ans(3,7,8) <= 1
+ 0 <= Ans(3,7,9) <= 1
+ 0 <= Ans(3,8,1) <= 1
+ 0 <= Ans(3,8,2) <= 1
+ 0 <= Ans(3,8,3) <= 1
+ 0 <= Ans(3,8,4) <= 1
+ 0 <= Ans(3,8,5) <= 1
+ 0 <= Ans(3,8,6) <= 1
+ 0 <= Ans(3,8,7) <= 1
+ 0 <= Ans(3,8,8) <= 1
+ 0 <= Ans(3,8,9) <= 1
+ 0 <= Ans(3,9,1) <= 1
+ 0 <= Ans(3,9,2) <= 1
+ 0 <= Ans(3,9,3) <= 1
+ 0 <= Ans(3,9,4) <= 1
+ 0 <= Ans(3,9,5) <= 1
+ 0 <= Ans(3,9,6) <= 1
+ 0 <= Ans(3,9,7) <= 1
+ 0 <= Ans(3,9,8) <= 1
+ 0 <= Ans(3,9,9) <= 1
+ 0 <= Ans(4,1,1) <= 1
+ 0 <= Ans(4,1,2) <= 1
+ 0 <= Ans(4,1,3) <= 1
+ 0 <= Ans(4,1,4) <= 1
+ 0 <= Ans(4,1,5) <= 1
+ 0 <= Ans(4,1,6) <= 1
+ 0 <= Ans(4,1,7) <= 1
+ 0 <= Ans(4,1,8) <= 1
+ 0 <= Ans(4,1,9) <= 1
+ 0 <= Ans(4,2,1) <= 1
+ 0 <= Ans(4,2,2) <= 1
+ 0 <= Ans(4,2,3) <= 1
+ 0 <= Ans(4,2,4) <= 1
+ 0 <= Ans(4,2,5) <= 1
+ 0 <= Ans(4,2,6) <= 1
+ 0 <= Ans(4,2,7) <= 1
+ 0 <= Ans(4,2,8) <= 1
+ 0 <= Ans(4,2,9) <= 1
+ 0 <= Ans(4,3,1) <= 1
+ 0 <= Ans(4,3,2) <= 1
+ 0 <= Ans(4,3,3) <= 1
+ 0 <= Ans(4,3,4) <= 1
+ 0 <= Ans(4,3,5) <= 1
+ 0 <= Ans(4,3,6) <= 1
+ 0 <= Ans(4,3,7) <= 1
+ 0 <= Ans(4,3,8) <= 1
+ 0 <= Ans(4,3,9) <= 1
+ 0 <= Ans(4,4,1) <= 1
+ 0 <= Ans(4,4,2) <= 1
+ 0 <= Ans(4,4,3) <= 1
+ 0 <= Ans(4,4,4) <= 1
+ 0 <= Ans(4,4,5) <= 1
+ 0 <= Ans(4,4,6) <= 1
+ 0 <= Ans(4,4,7) <= 1
+ 0 <= Ans(4,4,8) <= 1
+ 0 <= Ans(4,4,9) <= 1
+ 0 <= Ans(4,5,1) <= 1
+ 0 <= Ans(4,5,2) <= 1
+ 0 <= Ans(4,5,3) <= 1
+ 0 <= Ans(4,5,4) <= 1
+ 0 <= Ans(4,5,5) <= 1
+ 0 <= Ans(4,5,6) <= 1
+ 0 <= Ans(4,5,7) <= 1
+ 0 <= Ans(4,5,8) <= 1
+ 0 <= Ans(4,5,9) <= 1
+ 0 <= Ans(4,6,1) <= 1
+ 0 <= Ans(4,6,2) <= 1
+ 0 <= Ans(4,6,3) <= 1
+ 0 <= Ans(4,6,4) <= 1
+ 0 <= Ans(4,6,5) <= 1
+ 0 <= Ans(4,6,6) <= 1
+ 0 <= Ans(4,6,7) <= 1
+ 0 <= Ans(4,6,8) <= 1
+ 0 <= Ans(4,6,9) <= 1
+ 0 <= Ans(4,7,1) <= 1
+ 0 <= Ans(4,7,2) <= 1
+ 0 <= Ans(4,7,3) <= 1
+ 0 <= Ans(4,7,4) <= 1
+ 0 <= Ans(4,7,5) <= 1
+ 0 <= Ans(4,7,6) <= 1
+ 0 <= Ans(4,7,7) <= 1
+ 0 <= Ans(4,7,8) <= 1
+ 0 <= Ans(4,7,9) <= 1
+ 0 <= Ans(4,8,1) <= 1
+ 0 <= Ans(4,8,2) <= 1
+ 0 <= Ans(4,8,3) <= 1
+ 0 <= Ans(4,8,4) <= 1
+ 0 <= Ans(4,8,5) <= 1
+ 0 <= Ans(4,8,6) <= 1
+ 0 <= Ans(4,8,7) <= 1
+ 0 <= Ans(4,8,8) <= 1
+ 0 <= Ans(4,8,9) <= 1
+ 0 <= Ans(4,9,1) <= 1
+ 0 <= Ans(4,9,2) <= 1
+ 0 <= Ans(4,9,3) <= 1
+ 0 <= Ans(4,9,4) <= 1
+ 0 <= Ans(4,9,5) <= 1
+ 0 <= Ans(4,9,6) <= 1
+ 0 <= Ans(4,9,7) <= 1
+ 0 <= Ans(4,9,8) <= 1
+ 0 <= Ans(4,9,9) <= 1
+ 0 <= Ans(5,1,1) <= 1
+ 0 <= Ans(5,1,2) <= 1
+ 0 <= Ans(5,1,3) <= 1
+ 0 <= Ans(5,1,4) <= 1
+ 0 <= Ans(5,1,5) <= 1
+ 0 <= Ans(5,1,6) <= 1
+ 0 <= Ans(5,1,7) <= 1
+ 0 <= Ans(5,1,8) <= 1
+ 0 <= Ans(5,1,9) <= 1
+ 0 <= Ans(5,2,1) <= 1
+ 0 <= Ans(5,2,2) <= 1
+ 0 <= Ans(5,2,3) <= 1
+ 0 <= Ans(5,2,4) <= 1
+ 0 <= Ans(5,2,5) <= 1
+ 0 <= Ans(5,2,6) <= 1
+ 0 <= Ans(5,2,7) <= 1
+ 0 <= Ans(5,2,8) <= 1
+ 0 <= Ans(5,2,9) <= 1
+ 0 <= Ans(5,3,1) <= 1
+ 0 <= Ans(5,3,2) <= 1
+ 0 <= Ans(5,3,3) <= 1
+ 0 <= Ans(5,3,4) <= 1
+ 0 <= Ans(5,3,5) <= 1
+ 0 <= Ans(5,3,6) <= 1
+ 0 <= Ans(5,3,7) <= 1
+ 0 <= Ans(5,3,8) <= 1
+ 0 <= Ans(5,3,9) <= 1
+ 0 <= Ans(5,4,1) <= 1
+ 0 <= Ans(5,4,2) <= 1
+ 0 <= Ans(5,4,3) <= 1
+ 0 <= Ans(5,4,4) <= 1
+ 0 <= Ans(5,4,5) <= 1
+ 0 <= Ans(5,4,6) <= 1
+ 0 <= Ans(5,4,7) <= 1
+ 0 <= Ans(5,4,8) <= 1
+ 0 <= Ans(5,4,9) <= 1
+ 0 <= Ans(5,5,1) <= 1
+ 0 <= Ans(5,5,2) <= 1
+ 0 <= Ans(5,5,3) <= 1
+ 0 <= Ans(5,5,4) <= 1
+ 0 <= Ans(5,5,5) <= 1
+ 0 <= Ans(5,5,6) <= 1
+ 0 <= Ans(5,5,7) <= 1
+ 0 <= Ans(5,5,8) <= 1
+ 0 <= Ans(5,5,9) <= 1
+ 0 <= Ans(5,6,1) <= 1
+ 0 <= Ans(5,6,2) <= 1
+ 0 <= Ans(5,6,3) <= 1
+ 0 <= Ans(5,6,4) <= 1
+ 0 <= Ans(5,6,5) <= 1
+ 0 <= Ans(5,6,6) <= 1
+ 0 <= Ans(5,6,7) <= 1
+ 0 <= Ans(5,6,8) <= 1
+ 0 <= Ans(5,6,9) <= 1
+ 0 <= Ans(5,7,1) <= 1
+ 0 <= Ans(5,7,2) <= 1
+ 0 <= Ans(5,7,3) <= 1
+ 0 <= Ans(5,7,4) <= 1
+ 0 <= Ans(5,7,5) <= 1
+ 0 <= Ans(5,7,6) <= 1
+ 0 <= Ans(5,7,7) <= 1
+ 0 <= Ans(5,7,8) <= 1
+ 0 <= Ans(5,7,9) <= 1
+ 0 <= Ans(5,8,1) <= 1
+ 0 <= Ans(5,8,2) <= 1
+ 0 <= Ans(5,8,3) <= 1
+ 0 <= Ans(5,8,4) <= 1
+ 0 <= Ans(5,8,5) <= 1
+ 0 <= Ans(5,8,6) <= 1
+ 0 <= Ans(5,8,7) <= 1
+ 0 <= Ans(5,8,8) <= 1
+ 0 <= Ans(5,8,9) <= 1
+ 0 <= Ans(5,9,1) <= 1
+ 0 <= Ans(5,9,2) <= 1
+ 0 <= Ans(5,9,3) <= 1
+ 0 <= Ans(5,9,4) <= 1
+ 0 <= Ans(5,9,5) <= 1
+ 0 <= Ans(5,9,6) <= 1
+ 0 <= Ans(5,9,7) <= 1
+ 0 <= Ans(5,9,8) <= 1
+ 0 <= Ans(5,9,9) <= 1
+ 0 <= Ans(6,1,1) <= 1
+ 0 <= Ans(6,1,2) <= 1
+ 0 <= Ans(6,1,3) <= 1
+ 0 <= Ans(6,1,4) <= 1
+ 0 <= Ans(6,1,5) <= 1
+ 0 <= Ans(6,1,6) <= 1
+ 0 <= Ans(6,1,7) <= 1
+ 0 <= Ans(6,1,8) <= 1
+ 0 <= Ans(6,1,9) <= 1
+ 0 <= Ans(6,2,1) <= 1
+ 0 <= Ans(6,2,2) <= 1
+ 0 <= Ans(6,2,3) <= 1
+ 0 <= Ans(6,2,4) <= 1
+ 0 <= Ans(6,2,5) <= 1
+ 0 <= Ans(6,2,6) <= 1
+ 0 <= Ans(6,2,7) <= 1
+ 0 <= Ans(6,2,8) <= 1
+ 0 <= Ans(6,2,9) <= 1
+ 0 <= Ans(6,3,1) <= 1
+ 0 <= Ans(6,3,2) <= 1
+ 0 <= Ans(6,3,3) <= 1
+ 0 <= Ans(6,3,4) <= 1
+ 0 <= Ans(6,3,5) <= 1
+ 0 <= Ans(6,3,6) <= 1
+ 0 <= Ans(6,3,7) <= 1
+ 0 <= Ans(6,3,8) <= 1
+ 0 <= Ans(6,3,9) <= 1
+ 0 <= Ans(6,4,1) <= 1
+ 0 <= Ans(6,4,2) <= 1
+ 0 <= Ans(6,4,3) <= 1
+ 0 <= Ans(6,4,4) <= 1
+ 0 <= Ans(6,4,5) <= 1
+ 0 <= Ans(6,4,6) <= 1
+ 0 <= Ans(6,4,7) <= 1
+ 0 <= Ans(6,4,8) <= 1
+ 0 <= Ans(6,4,9) <= 1
+ 0 <= Ans(6,5,1) <= 1
+ 0 <= Ans(6,5,2) <= 1
+ 0 <= Ans(6,5,3) <= 1
+ 0 <= Ans(6,5,4) <= 1
+ 0 <= Ans(6,5,5) <= 1
+ 0 <= Ans(6,5,6) <= 1
+ 0 <= Ans(6,5,7) <= 1
+ 0 <= Ans(6,5,8) <= 1
+ 0 <= Ans(6,5,9) <= 1
+ 0 <= Ans(6,6,1) <= 1
+ 0 <= Ans(6,6,2) <= 1
+ 0 <= Ans(6,6,3) <= 1
+ 0 <= Ans(6,6,4) <= 1
+ 0 <= Ans(6,6,5) <= 1
+ 0 <= Ans(6,6,6) <= 1
+ 0 <= Ans(6,6,7) <= 1
+ 0 <= Ans(6,6,8) <= 1
+ 0 <= Ans(6,6,9) <= 1
+ 0 <= Ans(6,7,1) <= 1
+ 0 <= Ans(6,7,2) <= 1
+ 0 <= Ans(6,7,3) <= 1
+ 0 <= Ans(6,7,4) <= 1
+ 0 <= Ans(6,7,5) <= 1
+ 0 <= Ans(6,7,6) <= 1
+ 0 <= Ans(6,7,7) <= 1
+ 0 <= Ans(6,7,8) <= 1
+ 0 <= Ans(6,7,9) <= 1
+ 0 <= Ans(6,8,1) <= 1
+ 0 <= Ans(6,8,2) <= 1
+ 0 <= Ans(6,8,3) <= 1
+ 0 <= Ans(6,8,4) <= 1
+ 0 <= Ans(6,8,5) <= 1
+ 0 <= Ans(6,8,6) <= 1
+ 0 <= Ans(6,8,7) <= 1
+ 0 <= Ans(6,8,8) <= 1
+ 0 <= Ans(6,8,9) <= 1
+ 0 <= Ans(6,9,1) <= 1
+ 0 <= Ans(6,9,2) <= 1
+ 0 <= Ans(6,9,3) <= 1
+ 0 <= Ans(6,9,4) <= 1
+ 0 <= Ans(6,9,5) <= 1
+ 0 <= Ans(6,9,6) <= 1
+ 0 <= Ans(6,9,7) <= 1
+ 0 <= Ans(6,9,8) <= 1
+ 0 <= Ans(6,9,9) <= 1
+ 0 <= Ans(7,1,1) <= 1
+ 0 <= Ans(7,1,2) <= 1
+ 0 <= Ans(7,1,3) <= 1
+ 0 <= Ans(7,1,4) <= 1
+ 0 <= Ans(7,1,5) <= 1
+ 0 <= Ans(7,1,6) <= 1
+ 0 <= Ans(7,1,7) <= 1
+ 0 <= Ans(7,1,8) <= 1
+ 0 <= Ans(7,1,9) <= 1
+ 0 <= Ans(7,2,1) <= 1
+ 0 <= Ans(7,2,2) <= 1
+ 0 <= Ans(7,2,3) <= 1
+ 0 <= Ans(7,2,4) <= 1
+ 0 <= Ans(7,2,5) <= 1
+ 0 <= Ans(7,2,6) <= 1
+ 0 <= Ans(7,2,7) <= 1
+ 0 <= Ans(7,2,8) <= 1
+ 0 <= Ans(7,2,9) <= 1
+ 0 <= Ans(7,3,1) <= 1
+ 0 <= Ans(7,3,2) <= 1
+ 0 <= Ans(7,3,3) <= 1
+ 0 <= Ans(7,3,4) <= 1
+ 0 <= Ans(7,3,5) <= 1
+ 0 <= Ans(7,3,6) <= 1
+ 0 <= Ans(7,3,7) <= 1
+ 0 <= Ans(7,3,8) <= 1
+ 0 <= Ans(7,3,9) <= 1
+ 0 <= Ans(7,4,1) <= 1
+ 0 <= Ans(7,4,2) <= 1
+ 0 <= Ans(7,4,3) <= 1
+ 0 <= Ans(7,4,4) <= 1
+ 0 <= Ans(7,4,5) <= 1
+ 0 <= Ans(7,4,6) <= 1
+ 0 <= Ans(7,4,7) <= 1
+ 0 <= Ans(7,4,8) <= 1
+ 0 <= Ans(7,4,9) <= 1
+ 0 <= Ans(7,5,1) <= 1
+ 0 <= Ans(7,5,2) <= 1
+ 0 <= Ans(7,5,3) <= 1
+ 0 <= Ans(7,5,4) <= 1
+ 0 <= Ans(7,5,5) <= 1
+ 0 <= Ans(7,5,6) <= 1
+ 0 <= Ans(7,5,7) <= 1
+ 0 <= Ans(7,5,8) <= 1
+ 0 <= Ans(7,5,9) <= 1
+ 0 <= Ans(7,6,1) <= 1
+ 0 <= Ans(7,6,2) <= 1
+ 0 <= Ans(7,6,3) <= 1
+ 0 <= Ans(7,6,4) <= 1
+ 0 <= Ans(7,6,5) <= 1
+ 0 <= Ans(7,6,6) <= 1
+ 0 <= Ans(7,6,7) <= 1
+ 0 <= Ans(7,6,8) <= 1
+ 0 <= Ans(7,6,9) <= 1
+ 0 <= Ans(7,7,1) <= 1
+ 0 <= Ans(7,7,2) <= 1
+ 0 <= Ans(7,7,3) <= 1
+ 0 <= Ans(7,7,4) <= 1
+ 0 <= Ans(7,7,5) <= 1
+ 0 <= Ans(7,7,6) <= 1
+ 0 <= Ans(7,7,7) <= 1
+ 0 <= Ans(7,7,8) <= 1
+ 0 <= Ans(7,7,9) <= 1
+ 0 <= Ans(7,8,1) <= 1
+ 0 <= Ans(7,8,2) <= 1
+ 0 <= Ans(7,8,3) <= 1
+ 0 <= Ans(7,8,4) <= 1
+ 0 <= Ans(7,8,5) <= 1
+ 0 <= Ans(7,8,6) <= 1
+ 0 <= Ans(7,8,7) <= 1
+ 0 <= Ans(7,8,8) <= 1
+ 0 <= Ans(7,8,9) <= 1
+ 0 <= Ans(7,9,1) <= 1
+ 0 <= Ans(7,9,2) <= 1
+ 0 <= Ans(7,9,3) <= 1
+ 0 <= Ans(7,9,4) <= 1
+ 0 <= Ans(7,9,5) <= 1
+ 0 <= Ans(7,9,6) <= 1
+ 0 <= Ans(7,9,7) <= 1
+ 0 <= Ans(7,9,8) <= 1
+ 0 <= Ans(7,9,9) <= 1
+ 0 <= Ans(8,1,1) <= 1
+ 0 <= Ans(8,1,2) <= 1
+ 0 <= Ans(8,1,3) <= 1
+ 0 <= Ans(8,1,4) <= 1
+ 0 <= Ans(8,1,5) <= 1
+ 0 <= Ans(8,1,6) <= 1
+ 0 <= Ans(8,1,7) <= 1
+ 0 <= Ans(8,1,8) <= 1
+ 0 <= Ans(8,1,9) <= 1
+ 0 <= Ans(8,2,1) <= 1
+ 0 <= Ans(8,2,2) <= 1
+ 0 <= Ans(8,2,3) <= 1
+ 0 <= Ans(8,2,4) <= 1
+ 0 <= Ans(8,2,5) <= 1
+ 0 <= Ans(8,2,6) <= 1
+ 0 <= Ans(8,2,7) <= 1
+ 0 <= Ans(8,2,8) <= 1
+ 0 <= Ans(8,2,9) <= 1
+ 0 <= Ans(8,3,1) <= 1
+ 0 <= Ans(8,3,2) <= 1
+ 0 <= Ans(8,3,3) <= 1
+ 0 <= Ans(8,3,4) <= 1
+ 0 <= Ans(8,3,5) <= 1
+ 0 <= Ans(8,3,6) <= 1
+ 0 <= Ans(8,3,7) <= 1
+ 0 <= Ans(8,3,8) <= 1
+ 0 <= Ans(8,3,9) <= 1
+ 0 <= Ans(8,4,1) <= 1
+ 0 <= Ans(8,4,2) <= 1
+ 0 <= Ans(8,4,3) <= 1
+ 0 <= Ans(8,4,4) <= 1
+ 0 <= Ans(8,4,5) <= 1
+ 0 <= Ans(8,4,6) <= 1
+ 0 <= Ans(8,4,7) <= 1
+ 0 <= Ans(8,4,8) <= 1
+ 0 <= Ans(8,4,9) <= 1
+ 0 <= Ans(8,5,1) <= 1
+ 0 <= Ans(8,5,2) <= 1
+ 0 <= Ans(8,5,3) <= 1
+ 0 <= Ans(8,5,4) <= 1
+ 0 <= Ans(8,5,5) <= 1
+ 0 <= Ans(8,5,6) <= 1
+ 0 <= Ans(8,5,7) <= 1
+ 0 <= Ans(8,5,8) <= 1
+ 0 <= Ans(8,5,9) <= 1
+ 0 <= Ans(8,6,1) <= 1
+ 0 <= Ans(8,6,2) <= 1
+ 0 <= Ans(8,6,3) <= 1
+ 0 <= Ans(8,6,4) <= 1
+ 0 <= Ans(8,6,5) <= 1
+ 0 <= Ans(8,6,6) <= 1
+ 0 <= Ans(8,6,7) <= 1
+ 0 <= Ans(8,6,8) <= 1
+ 0 <= Ans(8,6,9) <= 1
+ 0 <= Ans(8,7,1) <= 1
+ 0 <= Ans(8,7,2) <= 1
+ 0 <= Ans(8,7,3) <= 1
+ 0 <= Ans(8,7,4) <= 1
+ 0 <= Ans(8,7,5) <= 1
+ 0 <= Ans(8,7,6) <= 1
+ 0 <= Ans(8,7,7) <= 1
+ 0 <= Ans(8,7,8) <= 1
+ 0 <= Ans(8,7,9) <= 1
+ 0 <= Ans(8,8,1) <= 1
+ 0 <= Ans(8,8,2) <= 1
+ 0 <= Ans(8,8,3) <= 1
+ 0 <= Ans(8,8,4) <= 1
+ 0 <= Ans(8,8,5) <= 1
+ 0 <= Ans(8,8,6) <= 1
+ 0 <= Ans(8,8,7) <= 1
+ 0 <= Ans(8,8,8) <= 1
+ 0 <= Ans(8,8,9) <= 1
+ 0 <= Ans(8,9,1) <= 1
+ 0 <= Ans(8,9,2) <= 1
+ 0 <= Ans(8,9,3) <= 1
+ 0 <= Ans(8,9,4) <= 1
+ 0 <= Ans(8,9,5) <= 1
+ 0 <= Ans(8,9,6) <= 1
+ 0 <= Ans(8,9,7) <= 1
+ 0 <= Ans(8,9,8) <= 1
+ 0 <= Ans(8,9,9) <= 1
+ 0 <= Ans(9,1,1) <= 1
+ 0 <= Ans(9,1,2) <= 1
+ 0 <= Ans(9,1,3) <= 1
+ 0 <= Ans(9,1,4) <= 1
+ 0 <= Ans(9,1,5) <= 1
+ 0 <= Ans(9,1,6) <= 1
+ 0 <= Ans(9,1,7) <= 1
+ 0 <= Ans(9,1,8) <= 1
+ 0 <= Ans(9,1,9) <= 1
+ 0 <= Ans(9,2,1) <= 1
+ 0 <= Ans(9,2,2) <= 1
+ 0 <= Ans(9,2,3) <= 1
+ 0 <= Ans(9,2,4) <= 1
+ 0 <= Ans(9,2,5) <= 1
+ 0 <= Ans(9,2,6) <= 1
+ 0 <= Ans(9,2,7) <= 1
+ 0 <= Ans(9,2,8) <= 1
+ 0 <= Ans(9,2,9) <= 1
+ 0 <= Ans(9,3,1) <= 1
+ 0 <= Ans(9,3,2) <= 1
+ 0 <= Ans(9,3,3) <= 1
+ 0 <= Ans(9,3,4) <= 1
+ 0 <= Ans(9,3,5) <= 1
+ 0 <= Ans(9,3,6) <= 1
+ 0 <= Ans(9,3,7) <= 1
+ 0 <= Ans(9,3,8) <= 1
+ 0 <= Ans(9,3,9) <= 1
+ 0 <= Ans(9,4,1) <= 1
+ 0 <= Ans(9,4,2) <= 1
+ 0 <= Ans(9,4,3) <= 1
+ 0 <= Ans(9,4,4) <= 1
+ 0 <= Ans(9,4,5) <= 1
+ 0 <= Ans(9,4,6) <= 1
+ 0 <= Ans(9,4,7) <= 1
+ 0 <= Ans(9,4,8) <= 1
+ 0 <= Ans(9,4,9) <= 1
+ 0 <= Ans(9,5,1) <= 1
+ 0 <= Ans(9,5,2) <= 1
+ 0 <= Ans(9,5,3) <= 1
+ 0 <= Ans(9,5,4) <= 1
+ 0 <= Ans(9,5,5) <= 1
+ 0 <= Ans(9,5,6) <= 1
+ 0 <= Ans(9,5,7) <= 1
+ 0 <= Ans(9,5,8) <= 1
+ 0 <= Ans(9,5,9) <= 1
+ 0 <= Ans(9,6,1) <= 1
+ 0 <= Ans(9,6,2) <= 1
+ 0 <= Ans(9,6,3) <= 1
+ 0 <= Ans(9,6,4) <= 1
+ 0 <= Ans(9,6,5) <= 1
+ 0 <= Ans(9,6,6) <= 1
+ 0 <= Ans(9,6,7) <= 1
+ 0 <= Ans(9,6,8) <= 1
+ 0 <= Ans(9,6,9) <= 1
+ 0 <= Ans(9,7,1) <= 1
+ 0 <= Ans(9,7,2) <= 1
+ 0 <= Ans(9,7,3) <= 1
+ 0 <= Ans(9,7,4) <= 1
+ 0 <= Ans(9,7,5) <= 1
+ 0 <= Ans(9,7,6) <= 1
+ 0 <= Ans(9,7,7) <= 1
+ 0 <= Ans(9,7,8) <= 1
+ 0 <= Ans(9,7,9) <= 1
+ 0 <= Ans(9,8,1) <= 1
+ 0 <= Ans(9,8,2) <= 1
+ 0 <= Ans(9,8,3) <= 1
+ 0 <= Ans(9,8,4) <= 1
+ 0 <= Ans(9,8,5) <= 1
+ 0 <= Ans(9,8,6) <= 1
+ 0 <= Ans(9,8,7) <= 1
+ 0 <= Ans(9,8,8) <= 1
+ 0 <= Ans(9,8,9) <= 1
+ 0 <= Ans(9,9,1) <= 1
+ 0 <= Ans(9,9,2) <= 1
+ 0 <= Ans(9,9,3) <= 1
+ 0 <= Ans(9,9,4) <= 1
+ 0 <= Ans(9,9,5) <= 1
+ 0 <= Ans(9,9,6) <= 1
+ 0 <= Ans(9,9,7) <= 1
+ 0 <= Ans(9,9,8) <= 1
+ 0 <= Ans(9,9,9) <= 1
+
+Generals
+ Ans(1,1,1)
+ Ans(1,1,2)
+ Ans(1,1,3)
+ Ans(1,1,4)
+ Ans(1,1,5)
+ Ans(1,1,6)
+ Ans(1,1,7)
+ Ans(1,1,8)
+ Ans(1,1,9)
+ Ans(1,2,1)
+ Ans(1,2,2)
+ Ans(1,2,3)
+ Ans(1,2,4)
+ Ans(1,2,5)
+ Ans(1,2,6)
+ Ans(1,2,7)
+ Ans(1,2,8)
+ Ans(1,2,9)
+ Ans(1,3,1)
+ Ans(1,3,2)
+ Ans(1,3,3)
+ Ans(1,3,4)
+ Ans(1,3,5)
+ Ans(1,3,6)
+ Ans(1,3,7)
+ Ans(1,3,8)
+ Ans(1,3,9)
+ Ans(1,4,1)
+ Ans(1,4,2)
+ Ans(1,4,3)
+ Ans(1,4,4)
+ Ans(1,4,5)
+ Ans(1,4,6)
+ Ans(1,4,7)
+ Ans(1,4,8)
+ Ans(1,4,9)
+ Ans(1,5,1)
+ Ans(1,5,2)
+ Ans(1,5,3)
+ Ans(1,5,4)
+ Ans(1,5,5)
+ Ans(1,5,6)
+ Ans(1,5,7)
+ Ans(1,5,8)
+ Ans(1,5,9)
+ Ans(1,6,1)
+ Ans(1,6,2)
+ Ans(1,6,3)
+ Ans(1,6,4)
+ Ans(1,6,5)
+ Ans(1,6,6)
+ Ans(1,6,7)
+ Ans(1,6,8)
+ Ans(1,6,9)
+ Ans(1,7,1)
+ Ans(1,7,2)
+ Ans(1,7,3)
+ Ans(1,7,4)
+ Ans(1,7,5)
+ Ans(1,7,6)
+ Ans(1,7,7)
+ Ans(1,7,8)
+ Ans(1,7,9)
+ Ans(1,8,1)
+ Ans(1,8,2)
+ Ans(1,8,3)
+ Ans(1,8,4)
+ Ans(1,8,5)
+ Ans(1,8,6)
+ Ans(1,8,7)
+ Ans(1,8,8)
+ Ans(1,8,9)
+ Ans(1,9,1)
+ Ans(1,9,2)
+ Ans(1,9,3)
+ Ans(1,9,4)
+ Ans(1,9,5)
+ Ans(1,9,6)
+ Ans(1,9,7)
+ Ans(1,9,8)
+ Ans(1,9,9)
+ Ans(2,1,1)
+ Ans(2,1,2)
+ Ans(2,1,3)
+ Ans(2,1,4)
+ Ans(2,1,5)
+ Ans(2,1,6)
+ Ans(2,1,7)
+ Ans(2,1,8)
+ Ans(2,1,9)
+ Ans(2,2,1)
+ Ans(2,2,2)
+ Ans(2,2,3)
+ Ans(2,2,4)
+ Ans(2,2,5)
+ Ans(2,2,6)
+ Ans(2,2,7)
+ Ans(2,2,8)
+ Ans(2,2,9)
+ Ans(2,3,1)
+ Ans(2,3,2)
+ Ans(2,3,3)
+ Ans(2,3,4)
+ Ans(2,3,5)
+ Ans(2,3,6)
+ Ans(2,3,7)
+ Ans(2,3,8)
+ Ans(2,3,9)
+ Ans(2,4,1)
+ Ans(2,4,2)
+ Ans(2,4,3)
+ Ans(2,4,4)
+ Ans(2,4,5)
+ Ans(2,4,6)
+ Ans(2,4,7)
+ Ans(2,4,8)
+ Ans(2,4,9)
+ Ans(2,5,1)
+ Ans(2,5,2)
+ Ans(2,5,3)
+ Ans(2,5,4)
+ Ans(2,5,5)
+ Ans(2,5,6)
+ Ans(2,5,7)
+ Ans(2,5,8)
+ Ans(2,5,9)
+ Ans(2,6,1)
+ Ans(2,6,2)
+ Ans(2,6,3)
+ Ans(2,6,4)
+ Ans(2,6,5)
+ Ans(2,6,6)
+ Ans(2,6,7)
+ Ans(2,6,8)
+ Ans(2,6,9)
+ Ans(2,7,1)
+ Ans(2,7,2)
+ Ans(2,7,3)
+ Ans(2,7,4)
+ Ans(2,7,5)
+ Ans(2,7,6)
+ Ans(2,7,7)
+ Ans(2,7,8)
+ Ans(2,7,9)
+ Ans(2,8,1)
+ Ans(2,8,2)
+ Ans(2,8,3)
+ Ans(2,8,4)
+ Ans(2,8,5)
+ Ans(2,8,6)
+ Ans(2,8,7)
+ Ans(2,8,8)
+ Ans(2,8,9)
+ Ans(2,9,1)
+ Ans(2,9,2)
+ Ans(2,9,3)
+ Ans(2,9,4)
+ Ans(2,9,5)
+ Ans(2,9,6)
+ Ans(2,9,7)
+ Ans(2,9,8)
+ Ans(2,9,9)
+ Ans(3,1,1)
+ Ans(3,1,2)
+ Ans(3,1,3)
+ Ans(3,1,4)
+ Ans(3,1,5)
+ Ans(3,1,6)
+ Ans(3,1,7)
+ Ans(3,1,8)
+ Ans(3,1,9)
+ Ans(3,2,1)
+ Ans(3,2,2)
+ Ans(3,2,3)
+ Ans(3,2,4)
+ Ans(3,2,5)
+ Ans(3,2,6)
+ Ans(3,2,7)
+ Ans(3,2,8)
+ Ans(3,2,9)
+ Ans(3,3,1)
+ Ans(3,3,2)
+ Ans(3,3,3)
+ Ans(3,3,4)
+ Ans(3,3,5)
+ Ans(3,3,6)
+ Ans(3,3,7)
+ Ans(3,3,8)
+ Ans(3,3,9)
+ Ans(3,4,1)
+ Ans(3,4,2)
+ Ans(3,4,3)
+ Ans(3,4,4)
+ Ans(3,4,5)
+ Ans(3,4,6)
+ Ans(3,4,7)
+ Ans(3,4,8)
+ Ans(3,4,9)
+ Ans(3,5,1)
+ Ans(3,5,2)
+ Ans(3,5,3)
+ Ans(3,5,4)
+ Ans(3,5,5)
+ Ans(3,5,6)
+ Ans(3,5,7)
+ Ans(3,5,8)
+ Ans(3,5,9)
+ Ans(3,6,1)
+ Ans(3,6,2)
+ Ans(3,6,3)
+ Ans(3,6,4)
+ Ans(3,6,5)
+ Ans(3,6,6)
+ Ans(3,6,7)
+ Ans(3,6,8)
+ Ans(3,6,9)
+ Ans(3,7,1)
+ Ans(3,7,2)
+ Ans(3,7,3)
+ Ans(3,7,4)
+ Ans(3,7,5)
+ Ans(3,7,6)
+ Ans(3,7,7)
+ Ans(3,7,8)
+ Ans(3,7,9)
+ Ans(3,8,1)
+ Ans(3,8,2)
+ Ans(3,8,3)
+ Ans(3,8,4)
+ Ans(3,8,5)
+ Ans(3,8,6)
+ Ans(3,8,7)
+ Ans(3,8,8)
+ Ans(3,8,9)
+ Ans(3,9,1)
+ Ans(3,9,2)
+ Ans(3,9,3)
+ Ans(3,9,4)
+ Ans(3,9,5)
+ Ans(3,9,6)
+ Ans(3,9,7)
+ Ans(3,9,8)
+ Ans(3,9,9)
+ Ans(4,1,1)
+ Ans(4,1,2)
+ Ans(4,1,3)
+ Ans(4,1,4)
+ Ans(4,1,5)
+ Ans(4,1,6)
+ Ans(4,1,7)
+ Ans(4,1,8)
+ Ans(4,1,9)
+ Ans(4,2,1)
+ Ans(4,2,2)
+ Ans(4,2,3)
+ Ans(4,2,4)
+ Ans(4,2,5)
+ Ans(4,2,6)
+ Ans(4,2,7)
+ Ans(4,2,8)
+ Ans(4,2,9)
+ Ans(4,3,1)
+ Ans(4,3,2)
+ Ans(4,3,3)
+ Ans(4,3,4)
+ Ans(4,3,5)
+ Ans(4,3,6)
+ Ans(4,3,7)
+ Ans(4,3,8)
+ Ans(4,3,9)
+ Ans(4,4,1)
+ Ans(4,4,2)
+ Ans(4,4,3)
+ Ans(4,4,4)
+ Ans(4,4,5)
+ Ans(4,4,6)
+ Ans(4,4,7)
+ Ans(4,4,8)
+ Ans(4,4,9)
+ Ans(4,5,1)
+ Ans(4,5,2)
+ Ans(4,5,3)
+ Ans(4,5,4)
+ Ans(4,5,5)
+ Ans(4,5,6)
+ Ans(4,5,7)
+ Ans(4,5,8)
+ Ans(4,5,9)
+ Ans(4,6,1)
+ Ans(4,6,2)
+ Ans(4,6,3)
+ Ans(4,6,4)
+ Ans(4,6,5)
+ Ans(4,6,6)
+ Ans(4,6,7)
+ Ans(4,6,8)
+ Ans(4,6,9)
+ Ans(4,7,1)
+ Ans(4,7,2)
+ Ans(4,7,3)
+ Ans(4,7,4)
+ Ans(4,7,5)
+ Ans(4,7,6)
+ Ans(4,7,7)
+ Ans(4,7,8)
+ Ans(4,7,9)
+ Ans(4,8,1)
+ Ans(4,8,2)
+ Ans(4,8,3)
+ Ans(4,8,4)
+ Ans(4,8,5)
+ Ans(4,8,6)
+ Ans(4,8,7)
+ Ans(4,8,8)
+ Ans(4,8,9)
+ Ans(4,9,1)
+ Ans(4,9,2)
+ Ans(4,9,3)
+ Ans(4,9,4)
+ Ans(4,9,5)
+ Ans(4,9,6)
+ Ans(4,9,7)
+ Ans(4,9,8)
+ Ans(4,9,9)
+ Ans(5,1,1)
+ Ans(5,1,2)
+ Ans(5,1,3)
+ Ans(5,1,4)
+ Ans(5,1,5)
+ Ans(5,1,6)
+ Ans(5,1,7)
+ Ans(5,1,8)
+ Ans(5,1,9)
+ Ans(5,2,1)
+ Ans(5,2,2)
+ Ans(5,2,3)
+ Ans(5,2,4)
+ Ans(5,2,5)
+ Ans(5,2,6)
+ Ans(5,2,7)
+ Ans(5,2,8)
+ Ans(5,2,9)
+ Ans(5,3,1)
+ Ans(5,3,2)
+ Ans(5,3,3)
+ Ans(5,3,4)
+ Ans(5,3,5)
+ Ans(5,3,6)
+ Ans(5,3,7)
+ Ans(5,3,8)
+ Ans(5,3,9)
+ Ans(5,4,1)
+ Ans(5,4,2)
+ Ans(5,4,3)
+ Ans(5,4,4)
+ Ans(5,4,5)
+ Ans(5,4,6)
+ Ans(5,4,7)
+ Ans(5,4,8)
+ Ans(5,4,9)
+ Ans(5,5,1)
+ Ans(5,5,2)
+ Ans(5,5,3)
+ Ans(5,5,4)
+ Ans(5,5,5)
+ Ans(5,5,6)
+ Ans(5,5,7)
+ Ans(5,5,8)
+ Ans(5,5,9)
+ Ans(5,6,1)
+ Ans(5,6,2)
+ Ans(5,6,3)
+ Ans(5,6,4)
+ Ans(5,6,5)
+ Ans(5,6,6)
+ Ans(5,6,7)
+ Ans(5,6,8)
+ Ans(5,6,9)
+ Ans(5,7,1)
+ Ans(5,7,2)
+ Ans(5,7,3)
+ Ans(5,7,4)
+ Ans(5,7,5)
+ Ans(5,7,6)
+ Ans(5,7,7)
+ Ans(5,7,8)
+ Ans(5,7,9)
+ Ans(5,8,1)
+ Ans(5,8,2)
+ Ans(5,8,3)
+ Ans(5,8,4)
+ Ans(5,8,5)
+ Ans(5,8,6)
+ Ans(5,8,7)
+ Ans(5,8,8)
+ Ans(5,8,9)
+ Ans(5,9,1)
+ Ans(5,9,2)
+ Ans(5,9,3)
+ Ans(5,9,4)
+ Ans(5,9,5)
+ Ans(5,9,6)
+ Ans(5,9,7)
+ Ans(5,9,8)
+ Ans(5,9,9)
+ Ans(6,1,1)
+ Ans(6,1,2)
+ Ans(6,1,3)
+ Ans(6,1,4)
+ Ans(6,1,5)
+ Ans(6,1,6)
+ Ans(6,1,7)
+ Ans(6,1,8)
+ Ans(6,1,9)
+ Ans(6,2,1)
+ Ans(6,2,2)
+ Ans(6,2,3)
+ Ans(6,2,4)
+ Ans(6,2,5)
+ Ans(6,2,6)
+ Ans(6,2,7)
+ Ans(6,2,8)
+ Ans(6,2,9)
+ Ans(6,3,1)
+ Ans(6,3,2)
+ Ans(6,3,3)
+ Ans(6,3,4)
+ Ans(6,3,5)
+ Ans(6,3,6)
+ Ans(6,3,7)
+ Ans(6,3,8)
+ Ans(6,3,9)
+ Ans(6,4,1)
+ Ans(6,4,2)
+ Ans(6,4,3)
+ Ans(6,4,4)
+ Ans(6,4,5)
+ Ans(6,4,6)
+ Ans(6,4,7)
+ Ans(6,4,8)
+ Ans(6,4,9)
+ Ans(6,5,1)
+ Ans(6,5,2)
+ Ans(6,5,3)
+ Ans(6,5,4)
+ Ans(6,5,5)
+ Ans(6,5,6)
+ Ans(6,5,7)
+ Ans(6,5,8)
+ Ans(6,5,9)
+ Ans(6,6,1)
+ Ans(6,6,2)
+ Ans(6,6,3)
+ Ans(6,6,4)
+ Ans(6,6,5)
+ Ans(6,6,6)
+ Ans(6,6,7)
+ Ans(6,6,8)
+ Ans(6,6,9)
+ Ans(6,7,1)
+ Ans(6,7,2)
+ Ans(6,7,3)
+ Ans(6,7,4)
+ Ans(6,7,5)
+ Ans(6,7,6)
+ Ans(6,7,7)
+ Ans(6,7,8)
+ Ans(6,7,9)
+ Ans(6,8,1)
+ Ans(6,8,2)
+ Ans(6,8,3)
+ Ans(6,8,4)
+ Ans(6,8,5)
+ Ans(6,8,6)
+ Ans(6,8,7)
+ Ans(6,8,8)
+ Ans(6,8,9)
+ Ans(6,9,1)
+ Ans(6,9,2)
+ Ans(6,9,3)
+ Ans(6,9,4)
+ Ans(6,9,5)
+ Ans(6,9,6)
+ Ans(6,9,7)
+ Ans(6,9,8)
+ Ans(6,9,9)
+ Ans(7,1,1)
+ Ans(7,1,2)
+ Ans(7,1,3)
+ Ans(7,1,4)
+ Ans(7,1,5)
+ Ans(7,1,6)
+ Ans(7,1,7)
+ Ans(7,1,8)
+ Ans(7,1,9)
+ Ans(7,2,1)
+ Ans(7,2,2)
+ Ans(7,2,3)
+ Ans(7,2,4)
+ Ans(7,2,5)
+ Ans(7,2,6)
+ Ans(7,2,7)
+ Ans(7,2,8)
+ Ans(7,2,9)
+ Ans(7,3,1)
+ Ans(7,3,2)
+ Ans(7,3,3)
+ Ans(7,3,4)
+ Ans(7,3,5)
+ Ans(7,3,6)
+ Ans(7,3,7)
+ Ans(7,3,8)
+ Ans(7,3,9)
+ Ans(7,4,1)
+ Ans(7,4,2)
+ Ans(7,4,3)
+ Ans(7,4,4)
+ Ans(7,4,5)
+ Ans(7,4,6)
+ Ans(7,4,7)
+ Ans(7,4,8)
+ Ans(7,4,9)
+ Ans(7,5,1)
+ Ans(7,5,2)
+ Ans(7,5,3)
+ Ans(7,5,4)
+ Ans(7,5,5)
+ Ans(7,5,6)
+ Ans(7,5,7)
+ Ans(7,5,8)
+ Ans(7,5,9)
+ Ans(7,6,1)
+ Ans(7,6,2)
+ Ans(7,6,3)
+ Ans(7,6,4)
+ Ans(7,6,5)
+ Ans(7,6,6)
+ Ans(7,6,7)
+ Ans(7,6,8)
+ Ans(7,6,9)
+ Ans(7,7,1)
+ Ans(7,7,2)
+ Ans(7,7,3)
+ Ans(7,7,4)
+ Ans(7,7,5)
+ Ans(7,7,6)
+ Ans(7,7,7)
+ Ans(7,7,8)
+ Ans(7,7,9)
+ Ans(7,8,1)
+ Ans(7,8,2)
+ Ans(7,8,3)
+ Ans(7,8,4)
+ Ans(7,8,5)
+ Ans(7,8,6)
+ Ans(7,8,7)
+ Ans(7,8,8)
+ Ans(7,8,9)
+ Ans(7,9,1)
+ Ans(7,9,2)
+ Ans(7,9,3)
+ Ans(7,9,4)
+ Ans(7,9,5)
+ Ans(7,9,6)
+ Ans(7,9,7)
+ Ans(7,9,8)
+ Ans(7,9,9)
+ Ans(8,1,1)
+ Ans(8,1,2)
+ Ans(8,1,3)
+ Ans(8,1,4)
+ Ans(8,1,5)
+ Ans(8,1,6)
+ Ans(8,1,7)
+ Ans(8,1,8)
+ Ans(8,1,9)
+ Ans(8,2,1)
+ Ans(8,2,2)
+ Ans(8,2,3)
+ Ans(8,2,4)
+ Ans(8,2,5)
+ Ans(8,2,6)
+ Ans(8,2,7)
+ Ans(8,2,8)
+ Ans(8,2,9)
+ Ans(8,3,1)
+ Ans(8,3,2)
+ Ans(8,3,3)
+ Ans(8,3,4)
+ Ans(8,3,5)
+ Ans(8,3,6)
+ Ans(8,3,7)
+ Ans(8,3,8)
+ Ans(8,3,9)
+ Ans(8,4,1)
+ Ans(8,4,2)
+ Ans(8,4,3)
+ Ans(8,4,4)
+ Ans(8,4,5)
+ Ans(8,4,6)
+ Ans(8,4,7)
+ Ans(8,4,8)
+ Ans(8,4,9)
+ Ans(8,5,1)
+ Ans(8,5,2)
+ Ans(8,5,3)
+ Ans(8,5,4)
+ Ans(8,5,5)
+ Ans(8,5,6)
+ Ans(8,5,7)
+ Ans(8,5,8)
+ Ans(8,5,9)
+ Ans(8,6,1)
+ Ans(8,6,2)
+ Ans(8,6,3)
+ Ans(8,6,4)
+ Ans(8,6,5)
+ Ans(8,6,6)
+ Ans(8,6,7)
+ Ans(8,6,8)
+ Ans(8,6,9)
+ Ans(8,7,1)
+ Ans(8,7,2)
+ Ans(8,7,3)
+ Ans(8,7,4)
+ Ans(8,7,5)
+ Ans(8,7,6)
+ Ans(8,7,7)
+ Ans(8,7,8)
+ Ans(8,7,9)
+ Ans(8,8,1)
+ Ans(8,8,2)
+ Ans(8,8,3)
+ Ans(8,8,4)
+ Ans(8,8,5)
+ Ans(8,8,6)
+ Ans(8,8,7)
+ Ans(8,8,8)
+ Ans(8,8,9)
+ Ans(8,9,1)
+ Ans(8,9,2)
+ Ans(8,9,3)
+ Ans(8,9,4)
+ Ans(8,9,5)
+ Ans(8,9,6)
+ Ans(8,9,7)
+ Ans(8,9,8)
+ Ans(8,9,9)
+ Ans(9,1,1)
+ Ans(9,1,2)
+ Ans(9,1,3)
+ Ans(9,1,4)
+ Ans(9,1,5)
+ Ans(9,1,6)
+ Ans(9,1,7)
+ Ans(9,1,8)
+ Ans(9,1,9)
+ Ans(9,2,1)
+ Ans(9,2,2)
+ Ans(9,2,3)
+ Ans(9,2,4)
+ Ans(9,2,5)
+ Ans(9,2,6)
+ Ans(9,2,7)
+ Ans(9,2,8)
+ Ans(9,2,9)
+ Ans(9,3,1)
+ Ans(9,3,2)
+ Ans(9,3,3)
+ Ans(9,3,4)
+ Ans(9,3,5)
+ Ans(9,3,6)
+ Ans(9,3,7)
+ Ans(9,3,8)
+ Ans(9,3,9)
+ Ans(9,4,1)
+ Ans(9,4,2)
+ Ans(9,4,3)
+ Ans(9,4,4)
+ Ans(9,4,5)
+ Ans(9,4,6)
+ Ans(9,4,7)
+ Ans(9,4,8)
+ Ans(9,4,9)
+ Ans(9,5,1)
+ Ans(9,5,2)
+ Ans(9,5,3)
+ Ans(9,5,4)
+ Ans(9,5,5)
+ Ans(9,5,6)
+ Ans(9,5,7)
+ Ans(9,5,8)
+ Ans(9,5,9)
+ Ans(9,6,1)
+ Ans(9,6,2)
+ Ans(9,6,3)
+ Ans(9,6,4)
+ Ans(9,6,5)
+ Ans(9,6,6)
+ Ans(9,6,7)
+ Ans(9,6,8)
+ Ans(9,6,9)
+ Ans(9,7,1)
+ Ans(9,7,2)
+ Ans(9,7,3)
+ Ans(9,7,4)
+ Ans(9,7,5)
+ Ans(9,7,6)
+ Ans(9,7,7)
+ Ans(9,7,8)
+ Ans(9,7,9)
+ Ans(9,8,1)
+ Ans(9,8,2)
+ Ans(9,8,3)
+ Ans(9,8,4)
+ Ans(9,8,5)
+ Ans(9,8,6)
+ Ans(9,8,7)
+ Ans(9,8,8)
+ Ans(9,8,9)
+ Ans(9,9,1)
+ Ans(9,9,2)
+ Ans(9,9,3)
+ Ans(9,9,4)
+ Ans(9,9,5)
+ Ans(9,9,6)
+ Ans(9,9,7)
+ Ans(9,9,8)
+ Ans(9,9,9)
+
+End
diff --git a/samples/lp/branch-and-bound-loop.lp b/samples/lp/branch-and-bound-loop.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/branch-and-bound-loop.lp
@@ -0,0 +1,22 @@
+\ Integrating Simplex with DPLL(T)
+\ by Bruno Dutertre and Leonardo de Moura
+\ 
+\ the constraint 1 <= 3x - 3y <= 2 is not satisfiable if x and y are
+\ integers, but has unbounded real solutions. On this example, a naive
+\ branch-and-bound implementation loops.
+\
+\ Gurobi: OK
+\ SCIP: OK
+\ GLPK: loops
+
+Minimize
+  0 x
+Subject To
+  3 x - 3 y >= 1
+  3 x - 3 y <= 2
+Bounds
+  -inf <= x <= +inf
+  -inf <= y <= +inf
+General
+  x y
+End
diff --git a/samples/lp/conti.lp b/samples/lp/conti.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/conti.lp
@@ -0,0 +1,18 @@
+\ Buchberger Algorithm and Integer Programming
+\ by Pasqualina Conti and Carlo Traverso
+\ http://posso.dm.unipi.it/users/traverso/conti-traverso-ip.ps
+Minimize
+  x1 + x2 + x3 + x4 + x5
+Subject To
+  + 2 x1 + 5 x2 - 3 x3 + 1 x4 - 2 x5 = 214
+  + 1 x1 + 7 x2 + 2 x3 + 3 x4 + 1 x5 = 712
+  + 4 x1 - 2 x2 - 1 x3 - 5 x4 + 3 x5 = 331
+Bounds
+  0 <= x1 <= +inf
+  0 <= x2 <= +inf
+  0 <= x3 <= +inf
+  0 <= x4 <= +inf
+  0 <= x5 <= +inf
+General
+  x1 x2 x3 x4 x5
+End
diff --git a/samples/lp/empty_obj_1.lp b/samples/lp/empty_obj_1.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/empty_obj_1.lp
@@ -0,0 +1,15 @@
+\GLPK: parse error
+\Gurobi: OK
+\CPLEX: OK
+\SCIP: OK
+Maximize
+Subject To
+c1: - x1 + x2 + x3 + 10 x4 <= 20
+c2: x1 - 3 x2 + x3 <= 30
+c3: x2 - 3.5 x4 = 0
+Bounds
+0 <= x1 <= 40
+2 <= x4 <= 3
+General
+x4
+End
diff --git a/samples/lp/empty_obj_2.lp b/samples/lp/empty_obj_2.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/empty_obj_2.lp
@@ -0,0 +1,16 @@
+\GLPK: parse error
+\Gurobi: OK
+\CPLEX: OK
+\SCIP: OK
+Maximize
+obj: 
+Subject To
+c1: - x1 + x2 + x3 + 10 x4 <= 20
+c2: x1 - 3 x2 + x3 <= 30
+c3: x2 - 3.5 x4 = 0
+Bounds
+0 <= x1 <= 40
+2 <= x4 <= 3
+General
+x4
+End
diff --git a/samples/lp/error/const_in_obj.lp b/samples/lp/error/const_in_obj.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/error/const_in_obj.lp
@@ -0,0 +1,22 @@
+\ GLPK: parser error
+\ Gurobi: 2.5 is recognized as variable!
+\ CPLEX: 2.5 is ignored, and warned.
+
+\ gurobi> m.getObjective()
+\ <gurobi.LinExpr: 1.0 x1 + 2.0 x2 + 3.0 x3 + 1.0 x4 + 1.0 2.5>
+\ gurobi> m.getVars()
+\ [<gurobi.Var x1>, <gurobi.Var x2>, <gurobi.Var x3>, <gurobi.Var x4>, <gurobi.Var
+2.5>]
+
+Maximize
+obj: x1 + 2 x2 + 3 x3 + x4 + 2.5
+Subject To
+c1: - x1 + x2 + x3 + 10 x4 <= 20
+c2: x1 - 3 x2 + x3 <= 30
+c3: x2 - 3.5 x4 = 0
+Bounds
+0 <= x1 <= 40
+2 <= x4 <= 3
+General
+x4
+End
diff --git a/samples/lp/error/inconsistent-bound-neg-inf.lp b/samples/lp/error/inconsistent-bound-neg-inf.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/error/inconsistent-bound-neg-inf.lp
@@ -0,0 +1,18 @@
+\...
+Maximize
+ obj: x1 + 2 x2 + 3 x3 + x4
+Subject To
+ c1: - x1 + x2 + x3 + 10 x4 <= 20
+ c2: x1 - 3 x2 + x3 <= 30
+ c3: x2 - 3.5 x4 = 0
+Bounds
+ 0 <= x1 <= -inf
+ 2 <= x4 <= 3
+General
+ x4
+End
+
+\ GLPK: samples/inconsistent-bound-neg-inf.lp:9: invalid use of `-inf' as upper bound
+\ Gurobi: Model is infeasible or unbounded
+\ lpsolve: bound contradicts earlier bounds on line 9
+\ SCIP: infeasible
diff --git a/samples/lp/error/inconsistent-bound-pos-inf.lp b/samples/lp/error/inconsistent-bound-pos-inf.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/error/inconsistent-bound-pos-inf.lp
@@ -0,0 +1,18 @@
+\...
+Maximize
+ obj: x1 + 2 x2 + 3 x3 + x4
+Subject To
+ c1: - x1 + x2 + x3 + 10 x4 <= 20
+ c2: x1 - 3 x2 + x3 <= 30
+ c3: x2 - 3.5 x4 = 0
+Bounds
+ +inf <= x1 <= 40
+ 2 <= x4 <= 3
+General
+ x4
+End
+
+\ GLPK: samples/inconsistent-bound-inf.lp:9: invalid use of `+inf' as lower bound
+\ Gurobi: Model is infeasible or unbounded
+\ lpsolve: Error: bound contradicts earlier bounds on line 9
+\ SCIP: infeasible
diff --git a/samples/lp/glpk-preprocess-bug.lp b/samples/lp/glpk-preprocess-bug.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/glpk-preprocess-bug.lp
@@ -0,0 +1,20 @@
+\ http://lists.gnu.org/archive/html/help-glpk/2010-12/msg00055.html
+\ From:    Andrew Makhorin
+\ Subject: Re: [Help-glpk] Skip preprocessing
+\ Date:	   Thu, 16 Dec 2010 15:16:23 +0300
+
+\ Your instance has a property that lp relaxation to it has no finite
+\ maximum while the integer feasible region is empty (in fact, 1/3 <= x1
+\ - x2 <= 3/4, so no integers x1 and x2 can satisfy this constraint).
+
+Maximize
+  obj: x2
+Subject To
+  c1: 3 x1 - 3 x2 >= 1
+  c2: 4 x1 - 4 x2 <= 3
+Bounds 
+  1 <= x1
+  0 <= x2
+General
+  x1 x2
+End
diff --git a/samples/lp/hoge.lp b/samples/lp/hoge.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/hoge.lp
@@ -0,0 +1,7 @@
+Minimize
+ obj: x1 + x2
+Subject To
+ c1: x1 + 2 x2 + x3 = 3
+General
+ x1 x2 x3
+End
diff --git a/samples/lp/ip-myth-1.lp b/samples/lp/ip-myth-1.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/ip-myth-1.lp
@@ -0,0 +1,12 @@
+\ Myths and Counterexamples in Integer Programming and Combinatorial Optimization
+\ Harvey J. Greenberg
+Maximize
+  21 x1 + 11 x2
+Subject To
+  7 x1 + 4 x2 <= 13
+Bounds
+  0 <= x1
+  0 <= x2
+General
+  x1 x2
+End
diff --git a/samples/lp/ip-myth-13-2.lp b/samples/lp/ip-myth-13-2.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/ip-myth-13-2.lp
@@ -0,0 +1,16 @@
+\ Myths and Counterexamples in Integer Programming and Combinatorial Optimization
+\ Harvey J. Greenberg
+Maximize
+  x1
+Subject To
+  x2 <= 1
+  x3 - 1.41421 x1 + 1.41421 x2 = 0
+Bounds
+  0 <= x1
+  0 <= x2
+  0 <= x3
+General
+  x1 x2 x3
+SOS
+  S2:: x1:1 x2:2 x3:3
+End
diff --git a/samples/lp/ip-myth-22-9.lp b/samples/lp/ip-myth-22-9.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/ip-myth-22-9.lp
@@ -0,0 +1,9 @@
+\ Myths and Counterexamples in Integer Programming and Combinatorial Optimization
+\ Harvey J. Greenberg
+Maximize
+  0 x1
+Subject To
+  + 2 x1 + 2 x2 + 2 x3 + 2 x4 + 2 x5 + 2 x6 + 2 x7 + 2 x8 + 2 x9 = 9
+Binary
+  x1 x2 x3 x4 x5 x6 x7 x8 x9
+End
diff --git a/samples/lp/ip-myth-22-99.lp b/samples/lp/ip-myth-22-99.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/ip-myth-22-99.lp
@@ -0,0 +1,9 @@
+\ Myths and Counterexamples in Integer Programming and Combinatorial Optimization
+\ Harvey J. Greenberg
+Maximize
+  0 x1
+Subject To
+  + 2 x1 + 2 x2 + 2 x3 + 2 x4 + 2 x5 + 2 x6 + 2 x7 + 2 x8 + 2 x9 + 2 x10 + 2 x11 + 2 x12 + 2 x13 + 2 x14 + 2 x15 + 2 x16 + 2 x17 + 2 x18 + 2 x19 + 2 x20 + 2 x21 + 2 x22 + 2 x23 + 2 x24 + 2 x25 + 2 x26 + 2 x27 + 2 x28 + 2 x29 + 2 x30 + 2 x31 + 2 x32 + 2 x33 + 2 x34 + 2 x35 + 2 x36 + 2 x37 + 2 x38 + 2 x39 + 2 x40 + 2 x41 + 2 x42 + 2 x43 + 2 x44 + 2 x45 + 2 x46 + 2 x47 + 2 x48 + 2 x49 + 2 x50 + 2 x51 + 2 x52 + 2 x53 + 2 x54 + 2 x55 + 2 x56 + 2 x57 + 2 x58 + 2 x59 + 2 x60 + 2 x61 + 2 x62 + 2 x63 + 2 x64 + 2 x65 + 2 x66 + 2 x67 + 2 x68 + 2 x69 + 2 x70 + 2 x71 + 2 x72 + 2 x73 + 2 x74 + 2 x75 + 2 x76 + 2 x77 + 2 x78 + 2 x79 + 2 x80 + 2 x81 + 2 x82 + 2 x83 + 2 x84 + 2 x85 + 2 x86 + 2 x87 + 2 x88 + 2 x89 + 2 x90 + 2 x91 + 2 x92 + 2 x93 + 2 x94 + 2 x95 + 2 x96 + 2 x97 + 2 x98 + 2 x99 = 99
+Binary
+  x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 x31 x32 x33 x34 x35 x36 x37 x38 x39 x40 x41 x42 x43 x44 x45 x46 x47 x48 x49 x50 x51 x52 x53 x54 x55 x56 x57 x58 x59 x60 x61 x62 x63 x64 x65 x66 x67 x68 x69 x70 x71 x72 x73 x74 x75 x76 x77 x78 x79 x80 x81 x82 x83 x84 x85 x86 x87 x88 x89 x90 x91 x92 x93 x94 x95 x96 x97 x98 x99
+End
diff --git a/samples/lp/ip-myth-22-999.lp b/samples/lp/ip-myth-22-999.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/ip-myth-22-999.lp
@@ -0,0 +1,9 @@
+\ Myths and Counterexamples in Integer Programming and Combinatorial Optimization
+\ Harvey J. Greenberg
+Maximize
+  0 x1
+Subject To
+  + 2 x1 + 2 x2 + 2 x3 + 2 x4 + 2 x5 + 2 x6 + 2 x7 + 2 x8 + 2 x9 + 2 x10 + 2 x11 + 2 x12 + 2 x13 + 2 x14 + 2 x15 + 2 x16 + 2 x17 + 2 x18 + 2 x19 + 2 x20 + 2 x21 + 2 x22 + 2 x23 + 2 x24 + 2 x25 + 2 x26 + 2 x27 + 2 x28 + 2 x29 + 2 x30 + 2 x31 + 2 x32 + 2 x33 + 2 x34 + 2 x35 + 2 x36 + 2 x37 + 2 x38 + 2 x39 + 2 x40 + 2 x41 + 2 x42 + 2 x43 + 2 x44 + 2 x45 + 2 x46 + 2 x47 + 2 x48 + 2 x49 + 2 x50 + 2 x51 + 2 x52 + 2 x53 + 2 x54 + 2 x55 + 2 x56 + 2 x57 + 2 x58 + 2 x59 + 2 x60 + 2 x61 + 2 x62 + 2 x63 + 2 x64 + 2 x65 + 2 x66 + 2 x67 + 2 x68 + 2 x69 + 2 x70 + 2 x71 + 2 x72 + 2 x73 + 2 x74 + 2 x75 + 2 x76 + 2 x77 + 2 x78 + 2 x79 + 2 x80 + 2 x81 + 2 x82 + 2 x83 + 2 x84 + 2 x85 + 2 x86 + 2 x87 + 2 x88 + 2 x89 + 2 x90 + 2 x91 + 2 x92 + 2 x93 + 2 x94 + 2 x95 + 2 x96 + 2 x97 + 2 x98 + 2 x99 + 2 x100 + 2 x101 + 2 x102 + 2 x103 + 2 x104 + 2 x105 + 2 x106 + 2 x107 + 2 x108 + 2 x109 + 2 x110 + 2 x111 + 2 x112 + 2 x113 + 2 x114 + 2 x115 + 2 x116 + 2 x117 + 2 x118 + 2 x119 + 2 x120 + 2 x121 + 2 x122 + 2 x123 + 2 x124 + 2 x125 + 2 x126 + 2 x127 + 2 x128 + 2 x129 + 2 x130 + 2 x131 + 2 x132 + 2 x133 + 2 x134 + 2 x135 + 2 x136 + 2 x137 + 2 x138 + 2 x139 + 2 x140 + 2 x141 + 2 x142 + 2 x143 + 2 x144 + 2 x145 + 2 x146 + 2 x147 + 2 x148 + 2 x149 + 2 x150 + 2 x151 + 2 x152 + 2 x153 + 2 x154 + 2 x155 + 2 x156 + 2 x157 + 2 x158 + 2 x159 + 2 x160 + 2 x161 + 2 x162 + 2 x163 + 2 x164 + 2 x165 + 2 x166 + 2 x167 + 2 x168 + 2 x169 + 2 x170 + 2 x171 + 2 x172 + 2 x173 + 2 x174 + 2 x175 + 2 x176 + 2 x177 + 2 x178 + 2 x179 + 2 x180 + 2 x181 + 2 x182 + 2 x183 + 2 x184 + 2 x185 + 2 x186 + 2 x187 + 2 x188 + 2 x189 + 2 x190 + 2 x191 + 2 x192 + 2 x193 + 2 x194 + 2 x195 + 2 x196 + 2 x197 + 2 x198 + 2 x199 + 2 x200 + 2 x201 + 2 x202 + 2 x203 + 2 x204 + 2 x205 + 2 x206 + 2 x207 + 2 x208 + 2 x209 + 2 x210 + 2 x211 + 2 x212 + 2 x213 + 2 x214 + 2 x215 + 2 x216 + 2 x217 + 2 x218 + 2 x219 + 2 x220 + 2 x221 + 2 x222 + 2 x223 + 2 x224 + 2 x225 + 2 x226 + 2 x227 + 2 x228 + 2 x229 + 2 x230 + 2 x231 + 2 x232 + 2 x233 + 2 x234 + 2 x235 + 2 x236 + 2 x237 + 2 x238 + 2 x239 + 2 x240 + 2 x241 + 2 x242 + 2 x243 + 2 x244 + 2 x245 + 2 x246 + 2 x247 + 2 x248 + 2 x249 + 2 x250 + 2 x251 + 2 x252 + 2 x253 + 2 x254 + 2 x255 + 2 x256 + 2 x257 + 2 x258 + 2 x259 + 2 x260 + 2 x261 + 2 x262 + 2 x263 + 2 x264 + 2 x265 + 2 x266 + 2 x267 + 2 x268 + 2 x269 + 2 x270 + 2 x271 + 2 x272 + 2 x273 + 2 x274 + 2 x275 + 2 x276 + 2 x277 + 2 x278 + 2 x279 + 2 x280 + 2 x281 + 2 x282 + 2 x283 + 2 x284 + 2 x285 + 2 x286 + 2 x287 + 2 x288 + 2 x289 + 2 x290 + 2 x291 + 2 x292 + 2 x293 + 2 x294 + 2 x295 + 2 x296 + 2 x297 + 2 x298 + 2 x299 + 2 x300 + 2 x301 + 2 x302 + 2 x303 + 2 x304 + 2 x305 + 2 x306 + 2 x307 + 2 x308 + 2 x309 + 2 x310 + 2 x311 + 2 x312 + 2 x313 + 2 x314 + 2 x315 + 2 x316 + 2 x317 + 2 x318 + 2 x319 + 2 x320 + 2 x321 + 2 x322 + 2 x323 + 2 x324 + 2 x325 + 2 x326 + 2 x327 + 2 x328 + 2 x329 + 2 x330 + 2 x331 + 2 x332 + 2 x333 + 2 x334 + 2 x335 + 2 x336 + 2 x337 + 2 x338 + 2 x339 + 2 x340 + 2 x341 + 2 x342 + 2 x343 + 2 x344 + 2 x345 + 2 x346 + 2 x347 + 2 x348 + 2 x349 + 2 x350 + 2 x351 + 2 x352 + 2 x353 + 2 x354 + 2 x355 + 2 x356 + 2 x357 + 2 x358 + 2 x359 + 2 x360 + 2 x361 + 2 x362 + 2 x363 + 2 x364 + 2 x365 + 2 x366 + 2 x367 + 2 x368 + 2 x369 + 2 x370 + 2 x371 + 2 x372 + 2 x373 + 2 x374 + 2 x375 + 2 x376 + 2 x377 + 2 x378 + 2 x379 + 2 x380 + 2 x381 + 2 x382 + 2 x383 + 2 x384 + 2 x385 + 2 x386 + 2 x387 + 2 x388 + 2 x389 + 2 x390 + 2 x391 + 2 x392 + 2 x393 + 2 x394 + 2 x395 + 2 x396 + 2 x397 + 2 x398 + 2 x399 + 2 x400 + 2 x401 + 2 x402 + 2 x403 + 2 x404 + 2 x405 + 2 x406 + 2 x407 + 2 x408 + 2 x409 + 2 x410 + 2 x411 + 2 x412 + 2 x413 + 2 x414 + 2 x415 + 2 x416 + 2 x417 + 2 x418 + 2 x419 + 2 x420 + 2 x421 + 2 x422 + 2 x423 + 2 x424 + 2 x425 + 2 x426 + 2 x427 + 2 x428 + 2 x429 + 2 x430 + 2 x431 + 2 x432 + 2 x433 + 2 x434 + 2 x435 + 2 x436 + 2 x437 + 2 x438 + 2 x439 + 2 x440 + 2 x441 + 2 x442 + 2 x443 + 2 x444 + 2 x445 + 2 x446 + 2 x447 + 2 x448 + 2 x449 + 2 x450 + 2 x451 + 2 x452 + 2 x453 + 2 x454 + 2 x455 + 2 x456 + 2 x457 + 2 x458 + 2 x459 + 2 x460 + 2 x461 + 2 x462 + 2 x463 + 2 x464 + 2 x465 + 2 x466 + 2 x467 + 2 x468 + 2 x469 + 2 x470 + 2 x471 + 2 x472 + 2 x473 + 2 x474 + 2 x475 + 2 x476 + 2 x477 + 2 x478 + 2 x479 + 2 x480 + 2 x481 + 2 x482 + 2 x483 + 2 x484 + 2 x485 + 2 x486 + 2 x487 + 2 x488 + 2 x489 + 2 x490 + 2 x491 + 2 x492 + 2 x493 + 2 x494 + 2 x495 + 2 x496 + 2 x497 + 2 x498 + 2 x499 + 2 x500 + 2 x501 + 2 x502 + 2 x503 + 2 x504 + 2 x505 + 2 x506 + 2 x507 + 2 x508 + 2 x509 + 2 x510 + 2 x511 + 2 x512 + 2 x513 + 2 x514 + 2 x515 + 2 x516 + 2 x517 + 2 x518 + 2 x519 + 2 x520 + 2 x521 + 2 x522 + 2 x523 + 2 x524 + 2 x525 + 2 x526 + 2 x527 + 2 x528 + 2 x529 + 2 x530 + 2 x531 + 2 x532 + 2 x533 + 2 x534 + 2 x535 + 2 x536 + 2 x537 + 2 x538 + 2 x539 + 2 x540 + 2 x541 + 2 x542 + 2 x543 + 2 x544 + 2 x545 + 2 x546 + 2 x547 + 2 x548 + 2 x549 + 2 x550 + 2 x551 + 2 x552 + 2 x553 + 2 x554 + 2 x555 + 2 x556 + 2 x557 + 2 x558 + 2 x559 + 2 x560 + 2 x561 + 2 x562 + 2 x563 + 2 x564 + 2 x565 + 2 x566 + 2 x567 + 2 x568 + 2 x569 + 2 x570 + 2 x571 + 2 x572 + 2 x573 + 2 x574 + 2 x575 + 2 x576 + 2 x577 + 2 x578 + 2 x579 + 2 x580 + 2 x581 + 2 x582 + 2 x583 + 2 x584 + 2 x585 + 2 x586 + 2 x587 + 2 x588 + 2 x589 + 2 x590 + 2 x591 + 2 x592 + 2 x593 + 2 x594 + 2 x595 + 2 x596 + 2 x597 + 2 x598 + 2 x599 + 2 x600 + 2 x601 + 2 x602 + 2 x603 + 2 x604 + 2 x605 + 2 x606 + 2 x607 + 2 x608 + 2 x609 + 2 x610 + 2 x611 + 2 x612 + 2 x613 + 2 x614 + 2 x615 + 2 x616 + 2 x617 + 2 x618 + 2 x619 + 2 x620 + 2 x621 + 2 x622 + 2 x623 + 2 x624 + 2 x625 + 2 x626 + 2 x627 + 2 x628 + 2 x629 + 2 x630 + 2 x631 + 2 x632 + 2 x633 + 2 x634 + 2 x635 + 2 x636 + 2 x637 + 2 x638 + 2 x639 + 2 x640 + 2 x641 + 2 x642 + 2 x643 + 2 x644 + 2 x645 + 2 x646 + 2 x647 + 2 x648 + 2 x649 + 2 x650 + 2 x651 + 2 x652 + 2 x653 + 2 x654 + 2 x655 + 2 x656 + 2 x657 + 2 x658 + 2 x659 + 2 x660 + 2 x661 + 2 x662 + 2 x663 + 2 x664 + 2 x665 + 2 x666 + 2 x667 + 2 x668 + 2 x669 + 2 x670 + 2 x671 + 2 x672 + 2 x673 + 2 x674 + 2 x675 + 2 x676 + 2 x677 + 2 x678 + 2 x679 + 2 x680 + 2 x681 + 2 x682 + 2 x683 + 2 x684 + 2 x685 + 2 x686 + 2 x687 + 2 x688 + 2 x689 + 2 x690 + 2 x691 + 2 x692 + 2 x693 + 2 x694 + 2 x695 + 2 x696 + 2 x697 + 2 x698 + 2 x699 + 2 x700 + 2 x701 + 2 x702 + 2 x703 + 2 x704 + 2 x705 + 2 x706 + 2 x707 + 2 x708 + 2 x709 + 2 x710 + 2 x711 + 2 x712 + 2 x713 + 2 x714 + 2 x715 + 2 x716 + 2 x717 + 2 x718 + 2 x719 + 2 x720 + 2 x721 + 2 x722 + 2 x723 + 2 x724 + 2 x725 + 2 x726 + 2 x727 + 2 x728 + 2 x729 + 2 x730 + 2 x731 + 2 x732 + 2 x733 + 2 x734 + 2 x735 + 2 x736 + 2 x737 + 2 x738 + 2 x739 + 2 x740 + 2 x741 + 2 x742 + 2 x743 + 2 x744 + 2 x745 + 2 x746 + 2 x747 + 2 x748 + 2 x749 + 2 x750 + 2 x751 + 2 x752 + 2 x753 + 2 x754 + 2 x755 + 2 x756 + 2 x757 + 2 x758 + 2 x759 + 2 x760 + 2 x761 + 2 x762 + 2 x763 + 2 x764 + 2 x765 + 2 x766 + 2 x767 + 2 x768 + 2 x769 + 2 x770 + 2 x771 + 2 x772 + 2 x773 + 2 x774 + 2 x775 + 2 x776 + 2 x777 + 2 x778 + 2 x779 + 2 x780 + 2 x781 + 2 x782 + 2 x783 + 2 x784 + 2 x785 + 2 x786 + 2 x787 + 2 x788 + 2 x789 + 2 x790 + 2 x791 + 2 x792 + 2 x793 + 2 x794 + 2 x795 + 2 x796 + 2 x797 + 2 x798 + 2 x799 + 2 x800 + 2 x801 + 2 x802 + 2 x803 + 2 x804 + 2 x805 + 2 x806 + 2 x807 + 2 x808 + 2 x809 + 2 x810 + 2 x811 + 2 x812 + 2 x813 + 2 x814 + 2 x815 + 2 x816 + 2 x817 + 2 x818 + 2 x819 + 2 x820 + 2 x821 + 2 x822 + 2 x823 + 2 x824 + 2 x825 + 2 x826 + 2 x827 + 2 x828 + 2 x829 + 2 x830 + 2 x831 + 2 x832 + 2 x833 + 2 x834 + 2 x835 + 2 x836 + 2 x837 + 2 x838 + 2 x839 + 2 x840 + 2 x841 + 2 x842 + 2 x843 + 2 x844 + 2 x845 + 2 x846 + 2 x847 + 2 x848 + 2 x849 + 2 x850 + 2 x851 + 2 x852 + 2 x853 + 2 x854 + 2 x855 + 2 x856 + 2 x857 + 2 x858 + 2 x859 + 2 x860 + 2 x861 + 2 x862 + 2 x863 + 2 x864 + 2 x865 + 2 x866 + 2 x867 + 2 x868 + 2 x869 + 2 x870 + 2 x871 + 2 x872 + 2 x873 + 2 x874 + 2 x875 + 2 x876 + 2 x877 + 2 x878 + 2 x879 + 2 x880 + 2 x881 + 2 x882 + 2 x883 + 2 x884 + 2 x885 + 2 x886 + 2 x887 + 2 x888 + 2 x889 + 2 x890 + 2 x891 + 2 x892 + 2 x893 + 2 x894 + 2 x895 + 2 x896 + 2 x897 + 2 x898 + 2 x899 + 2 x900 + 2 x901 + 2 x902 + 2 x903 + 2 x904 + 2 x905 + 2 x906 + 2 x907 + 2 x908 + 2 x909 + 2 x910 + 2 x911 + 2 x912 + 2 x913 + 2 x914 + 2 x915 + 2 x916 + 2 x917 + 2 x918 + 2 x919 + 2 x920 + 2 x921 + 2 x922 + 2 x923 + 2 x924 + 2 x925 + 2 x926 + 2 x927 + 2 x928 + 2 x929 + 2 x930 + 2 x931 + 2 x932 + 2 x933 + 2 x934 + 2 x935 + 2 x936 + 2 x937 + 2 x938 + 2 x939 + 2 x940 + 2 x941 + 2 x942 + 2 x943 + 2 x944 + 2 x945 + 2 x946 + 2 x947 + 2 x948 + 2 x949 + 2 x950 + 2 x951 + 2 x952 + 2 x953 + 2 x954 + 2 x955 + 2 x956 + 2 x957 + 2 x958 + 2 x959 + 2 x960 + 2 x961 + 2 x962 + 2 x963 + 2 x964 + 2 x965 + 2 x966 + 2 x967 + 2 x968 + 2 x969 + 2 x970 + 2 x971 + 2 x972 + 2 x973 + 2 x974 + 2 x975 + 2 x976 + 2 x977 + 2 x978 + 2 x979 + 2 x980 + 2 x981 + 2 x982 + 2 x983 + 2 x984 + 2 x985 + 2 x986 + 2 x987 + 2 x988 + 2 x989 + 2 x990 + 2 x991 + 2 x992 + 2 x993 + 2 x994 + 2 x995 + 2 x996 + 2 x997 + 2 x998 + 2 x999 = 999
+Binary
+  x1 x2 x3 x4 x5 x6 x7 x8 x9 x10 x11 x12 x13 x14 x15 x16 x17 x18 x19 x20 x21 x22 x23 x24 x25 x26 x27 x28 x29 x30 x31 x32 x33 x34 x35 x36 x37 x38 x39 x40 x41 x42 x43 x44 x45 x46 x47 x48 x49 x50 x51 x52 x53 x54 x55 x56 x57 x58 x59 x60 x61 x62 x63 x64 x65 x66 x67 x68 x69 x70 x71 x72 x73 x74 x75 x76 x77 x78 x79 x80 x81 x82 x83 x84 x85 x86 x87 x88 x89 x90 x91 x92 x93 x94 x95 x96 x97 x98 x99 x100 x101 x102 x103 x104 x105 x106 x107 x108 x109 x110 x111 x112 x113 x114 x115 x116 x117 x118 x119 x120 x121 x122 x123 x124 x125 x126 x127 x128 x129 x130 x131 x132 x133 x134 x135 x136 x137 x138 x139 x140 x141 x142 x143 x144 x145 x146 x147 x148 x149 x150 x151 x152 x153 x154 x155 x156 x157 x158 x159 x160 x161 x162 x163 x164 x165 x166 x167 x168 x169 x170 x171 x172 x173 x174 x175 x176 x177 x178 x179 x180 x181 x182 x183 x184 x185 x186 x187 x188 x189 x190 x191 x192 x193 x194 x195 x196 x197 x198 x199 x200 x201 x202 x203 x204 x205 x206 x207 x208 x209 x210 x211 x212 x213 x214 x215 x216 x217 x218 x219 x220 x221 x222 x223 x224 x225 x226 x227 x228 x229 x230 x231 x232 x233 x234 x235 x236 x237 x238 x239 x240 x241 x242 x243 x244 x245 x246 x247 x248 x249 x250 x251 x252 x253 x254 x255 x256 x257 x258 x259 x260 x261 x262 x263 x264 x265 x266 x267 x268 x269 x270 x271 x272 x273 x274 x275 x276 x277 x278 x279 x280 x281 x282 x283 x284 x285 x286 x287 x288 x289 x290 x291 x292 x293 x294 x295 x296 x297 x298 x299 x300 x301 x302 x303 x304 x305 x306 x307 x308 x309 x310 x311 x312 x313 x314 x315 x316 x317 x318 x319 x320 x321 x322 x323 x324 x325 x326 x327 x328 x329 x330 x331 x332 x333 x334 x335 x336 x337 x338 x339 x340 x341 x342 x343 x344 x345 x346 x347 x348 x349 x350 x351 x352 x353 x354 x355 x356 x357 x358 x359 x360 x361 x362 x363 x364 x365 x366 x367 x368 x369 x370 x371 x372 x373 x374 x375 x376 x377 x378 x379 x380 x381 x382 x383 x384 x385 x386 x387 x388 x389 x390 x391 x392 x393 x394 x395 x396 x397 x398 x399 x400 x401 x402 x403 x404 x405 x406 x407 x408 x409 x410 x411 x412 x413 x414 x415 x416 x417 x418 x419 x420 x421 x422 x423 x424 x425 x426 x427 x428 x429 x430 x431 x432 x433 x434 x435 x436 x437 x438 x439 x440 x441 x442 x443 x444 x445 x446 x447 x448 x449 x450 x451 x452 x453 x454 x455 x456 x457 x458 x459 x460 x461 x462 x463 x464 x465 x466 x467 x468 x469 x470 x471 x472 x473 x474 x475 x476 x477 x478 x479 x480 x481 x482 x483 x484 x485 x486 x487 x488 x489 x490 x491 x492 x493 x494 x495 x496 x497 x498 x499 x500 x501 x502 x503 x504 x505 x506 x507 x508 x509 x510 x511 x512 x513 x514 x515 x516 x517 x518 x519 x520 x521 x522 x523 x524 x525 x526 x527 x528 x529 x530 x531 x532 x533 x534 x535 x536 x537 x538 x539 x540 x541 x542 x543 x544 x545 x546 x547 x548 x549 x550 x551 x552 x553 x554 x555 x556 x557 x558 x559 x560 x561 x562 x563 x564 x565 x566 x567 x568 x569 x570 x571 x572 x573 x574 x575 x576 x577 x578 x579 x580 x581 x582 x583 x584 x585 x586 x587 x588 x589 x590 x591 x592 x593 x594 x595 x596 x597 x598 x599 x600 x601 x602 x603 x604 x605 x606 x607 x608 x609 x610 x611 x612 x613 x614 x615 x616 x617 x618 x619 x620 x621 x622 x623 x624 x625 x626 x627 x628 x629 x630 x631 x632 x633 x634 x635 x636 x637 x638 x639 x640 x641 x642 x643 x644 x645 x646 x647 x648 x649 x650 x651 x652 x653 x654 x655 x656 x657 x658 x659 x660 x661 x662 x663 x664 x665 x666 x667 x668 x669 x670 x671 x672 x673 x674 x675 x676 x677 x678 x679 x680 x681 x682 x683 x684 x685 x686 x687 x688 x689 x690 x691 x692 x693 x694 x695 x696 x697 x698 x699 x700 x701 x702 x703 x704 x705 x706 x707 x708 x709 x710 x711 x712 x713 x714 x715 x716 x717 x718 x719 x720 x721 x722 x723 x724 x725 x726 x727 x728 x729 x730 x731 x732 x733 x734 x735 x736 x737 x738 x739 x740 x741 x742 x743 x744 x745 x746 x747 x748 x749 x750 x751 x752 x753 x754 x755 x756 x757 x758 x759 x760 x761 x762 x763 x764 x765 x766 x767 x768 x769 x770 x771 x772 x773 x774 x775 x776 x777 x778 x779 x780 x781 x782 x783 x784 x785 x786 x787 x788 x789 x790 x791 x792 x793 x794 x795 x796 x797 x798 x799 x800 x801 x802 x803 x804 x805 x806 x807 x808 x809 x810 x811 x812 x813 x814 x815 x816 x817 x818 x819 x820 x821 x822 x823 x824 x825 x826 x827 x828 x829 x830 x831 x832 x833 x834 x835 x836 x837 x838 x839 x840 x841 x842 x843 x844 x845 x846 x847 x848 x849 x850 x851 x852 x853 x854 x855 x856 x857 x858 x859 x860 x861 x862 x863 x864 x865 x866 x867 x868 x869 x870 x871 x872 x873 x874 x875 x876 x877 x878 x879 x880 x881 x882 x883 x884 x885 x886 x887 x888 x889 x890 x891 x892 x893 x894 x895 x896 x897 x898 x899 x900 x901 x902 x903 x904 x905 x906 x907 x908 x909 x910 x911 x912 x913 x914 x915 x916 x917 x918 x919 x920 x921 x922 x923 x924 x925 x926 x927 x928 x929 x930 x931 x932 x933 x934 x935 x936 x937 x938 x939 x940 x941 x942 x943 x944 x945 x946 x947 x948 x949 x950 x951 x952 x953 x954 x955 x956 x957 x958 x959 x960 x961 x962 x963 x964 x965 x966 x967 x968 x969 x970 x971 x972 x973 x974 x975 x976 x977 x978 x979 x980 x981 x982 x983 x984 x985 x986 x987 x988 x989 x990 x991 x992 x993 x994 x995 x996 x997 x998 x999
+End
diff --git a/samples/lp/test-indicator.lp b/samples/lp/test-indicator.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/test-indicator.lp
@@ -0,0 +1,14 @@
+\ GLPK: error
+\ Gurobi 5.0.1: error
+\ SCIP: OK
+Maximize
+ obj: x1 + 2 x2 + 3 x3 + x4
+Subject To
+ c1: - x1 + x2 + x3 + 10 x4 <= 20
+ c2: x4 = 1 -> x1 - 3 x2 + x3 <= 30
+ c3: x2 - 3.5 x4 = 0
+Bounds
+ 0 <= x1 <= 40
+Binaries
+ x4
+End
diff --git a/samples/lp/test-qcp.lp b/samples/lp/test-qcp.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/test-qcp.lp
@@ -0,0 +1,16 @@
+\ http://www.gurobi.com/documentation/5.0/reference-manual/node746
+\ Gurobi 5.0.1: Ok
+\ SCIP 2.1.1: error
+
+Maximize
+  x + y + z
+Subject To
+  c0: x + y = 1
+  c1: x + 5 y + 2 z <= 10
+  qc0: x + y + [ x ^ 2 - 2 x * y + 3 y ^ 2 ] <= 5
+Bounds
+  0 <= x <= 5
+  z >= 2
+Generals
+  x y z
+End
diff --git a/samples/lp/test-qcp2.lp b/samples/lp/test-qcp2.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/test-qcp2.lp
@@ -0,0 +1,15 @@
+\ Gurobi 5.0.1: Ok
+\ SCIP 2.1.1: error
+
+Maximize
+  x + y + z
+Subject To
+  c0: x + y = 1
+  c1: x + 5 y + 2 z <= 10
+  qc0: x + y + [ x ^ 2 - 2 x * y + 3 y ^ 2 ] / 2 <= 5
+Bounds
+  0 <= x <= 5
+  z >= 2
+Generals
+  x y z
+End
diff --git a/samples/lp/test-qp.lp b/samples/lp/test-qp.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/test-qp.lp
@@ -0,0 +1,8 @@
+\ GLPK: error
+\ Gurobi 5.0.1: Ok
+\ SCIP: okay? but "Quadratic constraint handler does not have LAPACK for eigenvalue computation. Will assume that matrices (with size > 2x2) are indefinite."
+Minimize
+obj: a + b + [ a^2 + 4 a * b + 7 b^2 ] / 2
+Subject To
+c1: a + b >= 10
+End
diff --git a/samples/lp/test.lp b/samples/lp/test.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/test.lp
@@ -0,0 +1,13 @@
+\...
+Maximize
+ obj: x1 + 2 x2 + 3 x3 + x4
+Subject To
+ c1: - x1 + x2 + x3 + 10 x4 <= 20
+ c2: x1 - 3 x2 + x3 <= 30
+ c3: x2 - 3.5 x4 = 0
+Bounds
+ 0 <= x1 <= 40
+ 2 <= x4 <= 3
+General
+ x4
+End
diff --git a/samples/lp/unbounded-ip.lp b/samples/lp/unbounded-ip.lp
new file mode 100644
--- /dev/null
+++ b/samples/lp/unbounded-ip.lp
@@ -0,0 +1,10 @@
+Maximize
+  obj: x + y
+Subject To
+  c1: y - 2 x >= 0
+Bounds 
+  1 <= x
+  0 <= y
+General
+  x y
+End
diff --git a/samples/maxsat/maxsat.cnf b/samples/maxsat/maxsat.cnf
new file mode 100644
--- /dev/null
+++ b/samples/maxsat/maxsat.cnf
@@ -0,0 +1,8 @@
+c
+c comments Max-SAT
+c
+p cnf 3 4
+1 -2 0
+-1 2 -3 0
+-3 2 0
+1 3 0
diff --git a/samples/maxsat/partial-maxsat.wcnf b/samples/maxsat/partial-maxsat.wcnf
new file mode 100644
--- /dev/null
+++ b/samples/maxsat/partial-maxsat.wcnf
@@ -0,0 +1,9 @@
+c
+c comments Partial Max-SAT
+c
+p wcnf 4 5 15
+15 1 -2 4 0
+15 -1 -2 3 0
+1 -2 -4 0
+1 -3 2 0
+1 1 3 0
diff --git a/samples/maxsat/weighted-maxsat.wcnf b/samples/maxsat/weighted-maxsat.wcnf
new file mode 100644
--- /dev/null
+++ b/samples/maxsat/weighted-maxsat.wcnf
@@ -0,0 +1,8 @@
+c
+c comments Weighted Max-SAT
+c
+p wcnf 3 4
+10 1 -2 0
+3 -1 2 -3 0
+8 -3 2 0
+5 1 3 0
diff --git a/samples/maxsat/weighted-partial-maxsat.wcnf b/samples/maxsat/weighted-partial-maxsat.wcnf
new file mode 100644
--- /dev/null
+++ b/samples/maxsat/weighted-partial-maxsat.wcnf
@@ -0,0 +1,9 @@
+c
+c comments Weigthed Partial Max-SAT
+c
+p wcnf 4 5 16
+16 1 -2 4 0
+16 -1 -2 3 0
+8 -2 -4 0
+4 -3 2 0
+3 1 3 0
diff --git a/samples/pbo/example-lin.opb b/samples/pbo/example-lin.opb
new file mode 100644
--- /dev/null
+++ b/samples/pbo/example-lin.opb
@@ -0,0 +1,10 @@
+* #variable= 5 #constraint= 4
+*
+* this is a dummy instance
+*
+min: 1 x2 -1 x3 ;
+1 x1 +4 x2 -2 x5 >= 2;
+-1 x1 +4 x2 -2 x5 >= +3;
+12345678901234567890 x4 +4 x3 >= 10;
+* an equality constraint
+2 x2 +3 x4 +2 x1 +3 x5 = 5;
diff --git a/samples/pbo/example-nlc-1.opb b/samples/pbo/example-nlc-1.opb
new file mode 100644
--- /dev/null
+++ b/samples/pbo/example-nlc-1.opb
@@ -0,0 +1,9 @@
+* #variable= 5 #constraint= 4 #product= 5 sizeproduct= 13
+*
+* this is a dummy instance
+*
+min: 1 x2 x3 -1 x3 ;
+1 x1 +4 x1 ~x2 -2 x5 >= 2;
+-1 x1 +4 x2 -2 x5 >= 3;
+12345678901234567890 x4 +4 x3 >= 10;
+2 x2 x3 +3 x4 ~x5 +2 ~x1 x2 +3 ~x1 x2 x3 ~x4 ~x5 = 5 ;
diff --git a/samples/pbo/example-nlc-2.opb b/samples/pbo/example-nlc-2.opb
new file mode 100644
--- /dev/null
+++ b/samples/pbo/example-nlc-2.opb
@@ -0,0 +1,16 @@
+* #variable= 6 #constraint= 3 #product= 9 sizeproduct= 18
+*
+* Factorization problem: find the smallest P such that P*Q=N
+* P is a 3 bits number (x3 x2 x1)
+* Q is a 3 bits number (x6 x5 x4)
+* N=35
+* 
+* minimize the value of P
+min: +1 x1 +2 x2 +4 x3 ;
+* P>=2 (to avoid trivial factorization)
++1 x1 +2 x2 +4 x3 >=2;
+* Q>=2 (to avoid trivial factorization)
++1 x4 +2 x5 +4 x6 >=2;
+*
+* P*Q=N
++1 x1 x4 +2 x1 x5 +4 x1 x6 +2 x2 x4 +4 x2 x5 +8 x2 x6 +4 x3 x4 +8 x3 x5 +16 x3 x6 = 35;
diff --git a/samples/pbs/pigeonhole_100_99.opb b/samples/pbs/pigeonhole_100_99.opb
new file mode 100644
--- /dev/null
+++ b/samples/pbs/pigeonhole_100_99.opb
@@ -0,0 +1,200 @@
+* #variable= 9900 #constraint= 199
++1 x1 +1 x2 +1 x3 +1 x4 +1 x5 +1 x6 +1 x7 +1 x8 +1 x9 +1 x10 +1 x11 +1 x12 +1 x13 +1 x14 +1 x15 +1 x16 +1 x17 +1 x18 +1 x19 +1 x20 +1 x21 +1 x22 +1 x23 +1 x24 +1 x25 +1 x26 +1 x27 +1 x28 +1 x29 +1 x30 +1 x31 +1 x32 +1 x33 +1 x34 +1 x35 +1 x36 +1 x37 +1 x38 +1 x39 +1 x40 +1 x41 +1 x42 +1 x43 +1 x44 +1 x45 +1 x46 +1 x47 +1 x48 +1 x49 +1 x50 +1 x51 +1 x52 +1 x53 +1 x54 +1 x55 +1 x56 +1 x57 +1 x58 +1 x59 +1 x60 +1 x61 +1 x62 +1 x63 +1 x64 +1 x65 +1 x66 +1 x67 +1 x68 +1 x69 +1 x70 +1 x71 +1 x72 +1 x73 +1 x74 +1 x75 +1 x76 +1 x77 +1 x78 +1 x79 +1 x80 +1 x81 +1 x82 +1 x83 +1 x84 +1 x85 +1 x86 +1 x87 +1 x88 +1 x89 +1 x90 +1 x91 +1 x92 +1 x93 +1 x94 +1 x95 +1 x96 +1 x97 +1 x98 +1 x99 >= 1;
++1 x100 +1 x101 +1 x102 +1 x103 +1 x104 +1 x105 +1 x106 +1 x107 +1 x108 +1 x109 +1 x110 +1 x111 +1 x112 +1 x113 +1 x114 +1 x115 +1 x116 +1 x117 +1 x118 +1 x119 +1 x120 +1 x121 +1 x122 +1 x123 +1 x124 +1 x125 +1 x126 +1 x127 +1 x128 +1 x129 +1 x130 +1 x131 +1 x132 +1 x133 +1 x134 +1 x135 +1 x136 +1 x137 +1 x138 +1 x139 +1 x140 +1 x141 +1 x142 +1 x143 +1 x144 +1 x145 +1 x146 +1 x147 +1 x148 +1 x149 +1 x150 +1 x151 +1 x152 +1 x153 +1 x154 +1 x155 +1 x156 +1 x157 +1 x158 +1 x159 +1 x160 +1 x161 +1 x162 +1 x163 +1 x164 +1 x165 +1 x166 +1 x167 +1 x168 +1 x169 +1 x170 +1 x171 +1 x172 +1 x173 +1 x174 +1 x175 +1 x176 +1 x177 +1 x178 +1 x179 +1 x180 +1 x181 +1 x182 +1 x183 +1 x184 +1 x185 +1 x186 +1 x187 +1 x188 +1 x189 +1 x190 +1 x191 +1 x192 +1 x193 +1 x194 +1 x195 +1 x196 +1 x197 +1 x198 >= 1;
++1 x199 +1 x200 +1 x201 +1 x202 +1 x203 +1 x204 +1 x205 +1 x206 +1 x207 +1 x208 +1 x209 +1 x210 +1 x211 +1 x212 +1 x213 +1 x214 +1 x215 +1 x216 +1 x217 +1 x218 +1 x219 +1 x220 +1 x221 +1 x222 +1 x223 +1 x224 +1 x225 +1 x226 +1 x227 +1 x228 +1 x229 +1 x230 +1 x231 +1 x232 +1 x233 +1 x234 +1 x235 +1 x236 +1 x237 +1 x238 +1 x239 +1 x240 +1 x241 +1 x242 +1 x243 +1 x244 +1 x245 +1 x246 +1 x247 +1 x248 +1 x249 +1 x250 +1 x251 +1 x252 +1 x253 +1 x254 +1 x255 +1 x256 +1 x257 +1 x258 +1 x259 +1 x260 +1 x261 +1 x262 +1 x263 +1 x264 +1 x265 +1 x266 +1 x267 +1 x268 +1 x269 +1 x270 +1 x271 +1 x272 +1 x273 +1 x274 +1 x275 +1 x276 +1 x277 +1 x278 +1 x279 +1 x280 +1 x281 +1 x282 +1 x283 +1 x284 +1 x285 +1 x286 +1 x287 +1 x288 +1 x289 +1 x290 +1 x291 +1 x292 +1 x293 +1 x294 +1 x295 +1 x296 +1 x297 >= 1;
++1 x298 +1 x299 +1 x300 +1 x301 +1 x302 +1 x303 +1 x304 +1 x305 +1 x306 +1 x307 +1 x308 +1 x309 +1 x310 +1 x311 +1 x312 +1 x313 +1 x314 +1 x315 +1 x316 +1 x317 +1 x318 +1 x319 +1 x320 +1 x321 +1 x322 +1 x323 +1 x324 +1 x325 +1 x326 +1 x327 +1 x328 +1 x329 +1 x330 +1 x331 +1 x332 +1 x333 +1 x334 +1 x335 +1 x336 +1 x337 +1 x338 +1 x339 +1 x340 +1 x341 +1 x342 +1 x343 +1 x344 +1 x345 +1 x346 +1 x347 +1 x348 +1 x349 +1 x350 +1 x351 +1 x352 +1 x353 +1 x354 +1 x355 +1 x356 +1 x357 +1 x358 +1 x359 +1 x360 +1 x361 +1 x362 +1 x363 +1 x364 +1 x365 +1 x366 +1 x367 +1 x368 +1 x369 +1 x370 +1 x371 +1 x372 +1 x373 +1 x374 +1 x375 +1 x376 +1 x377 +1 x378 +1 x379 +1 x380 +1 x381 +1 x382 +1 x383 +1 x384 +1 x385 +1 x386 +1 x387 +1 x388 +1 x389 +1 x390 +1 x391 +1 x392 +1 x393 +1 x394 +1 x395 +1 x396 >= 1;
++1 x397 +1 x398 +1 x399 +1 x400 +1 x401 +1 x402 +1 x403 +1 x404 +1 x405 +1 x406 +1 x407 +1 x408 +1 x409 +1 x410 +1 x411 +1 x412 +1 x413 +1 x414 +1 x415 +1 x416 +1 x417 +1 x418 +1 x419 +1 x420 +1 x421 +1 x422 +1 x423 +1 x424 +1 x425 +1 x426 +1 x427 +1 x428 +1 x429 +1 x430 +1 x431 +1 x432 +1 x433 +1 x434 +1 x435 +1 x436 +1 x437 +1 x438 +1 x439 +1 x440 +1 x441 +1 x442 +1 x443 +1 x444 +1 x445 +1 x446 +1 x447 +1 x448 +1 x449 +1 x450 +1 x451 +1 x452 +1 x453 +1 x454 +1 x455 +1 x456 +1 x457 +1 x458 +1 x459 +1 x460 +1 x461 +1 x462 +1 x463 +1 x464 +1 x465 +1 x466 +1 x467 +1 x468 +1 x469 +1 x470 +1 x471 +1 x472 +1 x473 +1 x474 +1 x475 +1 x476 +1 x477 +1 x478 +1 x479 +1 x480 +1 x481 +1 x482 +1 x483 +1 x484 +1 x485 +1 x486 +1 x487 +1 x488 +1 x489 +1 x490 +1 x491 +1 x492 +1 x493 +1 x494 +1 x495 >= 1;
++1 x496 +1 x497 +1 x498 +1 x499 +1 x500 +1 x501 +1 x502 +1 x503 +1 x504 +1 x505 +1 x506 +1 x507 +1 x508 +1 x509 +1 x510 +1 x511 +1 x512 +1 x513 +1 x514 +1 x515 +1 x516 +1 x517 +1 x518 +1 x519 +1 x520 +1 x521 +1 x522 +1 x523 +1 x524 +1 x525 +1 x526 +1 x527 +1 x528 +1 x529 +1 x530 +1 x531 +1 x532 +1 x533 +1 x534 +1 x535 +1 x536 +1 x537 +1 x538 +1 x539 +1 x540 +1 x541 +1 x542 +1 x543 +1 x544 +1 x545 +1 x546 +1 x547 +1 x548 +1 x549 +1 x550 +1 x551 +1 x552 +1 x553 +1 x554 +1 x555 +1 x556 +1 x557 +1 x558 +1 x559 +1 x560 +1 x561 +1 x562 +1 x563 +1 x564 +1 x565 +1 x566 +1 x567 +1 x568 +1 x569 +1 x570 +1 x571 +1 x572 +1 x573 +1 x574 +1 x575 +1 x576 +1 x577 +1 x578 +1 x579 +1 x580 +1 x581 +1 x582 +1 x583 +1 x584 +1 x585 +1 x586 +1 x587 +1 x588 +1 x589 +1 x590 +1 x591 +1 x592 +1 x593 +1 x594 >= 1;
++1 x595 +1 x596 +1 x597 +1 x598 +1 x599 +1 x600 +1 x601 +1 x602 +1 x603 +1 x604 +1 x605 +1 x606 +1 x607 +1 x608 +1 x609 +1 x610 +1 x611 +1 x612 +1 x613 +1 x614 +1 x615 +1 x616 +1 x617 +1 x618 +1 x619 +1 x620 +1 x621 +1 x622 +1 x623 +1 x624 +1 x625 +1 x626 +1 x627 +1 x628 +1 x629 +1 x630 +1 x631 +1 x632 +1 x633 +1 x634 +1 x635 +1 x636 +1 x637 +1 x638 +1 x639 +1 x640 +1 x641 +1 x642 +1 x643 +1 x644 +1 x645 +1 x646 +1 x647 +1 x648 +1 x649 +1 x650 +1 x651 +1 x652 +1 x653 +1 x654 +1 x655 +1 x656 +1 x657 +1 x658 +1 x659 +1 x660 +1 x661 +1 x662 +1 x663 +1 x664 +1 x665 +1 x666 +1 x667 +1 x668 +1 x669 +1 x670 +1 x671 +1 x672 +1 x673 +1 x674 +1 x675 +1 x676 +1 x677 +1 x678 +1 x679 +1 x680 +1 x681 +1 x682 +1 x683 +1 x684 +1 x685 +1 x686 +1 x687 +1 x688 +1 x689 +1 x690 +1 x691 +1 x692 +1 x693 >= 1;
++1 x694 +1 x695 +1 x696 +1 x697 +1 x698 +1 x699 +1 x700 +1 x701 +1 x702 +1 x703 +1 x704 +1 x705 +1 x706 +1 x707 +1 x708 +1 x709 +1 x710 +1 x711 +1 x712 +1 x713 +1 x714 +1 x715 +1 x716 +1 x717 +1 x718 +1 x719 +1 x720 +1 x721 +1 x722 +1 x723 +1 x724 +1 x725 +1 x726 +1 x727 +1 x728 +1 x729 +1 x730 +1 x731 +1 x732 +1 x733 +1 x734 +1 x735 +1 x736 +1 x737 +1 x738 +1 x739 +1 x740 +1 x741 +1 x742 +1 x743 +1 x744 +1 x745 +1 x746 +1 x747 +1 x748 +1 x749 +1 x750 +1 x751 +1 x752 +1 x753 +1 x754 +1 x755 +1 x756 +1 x757 +1 x758 +1 x759 +1 x760 +1 x761 +1 x762 +1 x763 +1 x764 +1 x765 +1 x766 +1 x767 +1 x768 +1 x769 +1 x770 +1 x771 +1 x772 +1 x773 +1 x774 +1 x775 +1 x776 +1 x777 +1 x778 +1 x779 +1 x780 +1 x781 +1 x782 +1 x783 +1 x784 +1 x785 +1 x786 +1 x787 +1 x788 +1 x789 +1 x790 +1 x791 +1 x792 >= 1;
++1 x793 +1 x794 +1 x795 +1 x796 +1 x797 +1 x798 +1 x799 +1 x800 +1 x801 +1 x802 +1 x803 +1 x804 +1 x805 +1 x806 +1 x807 +1 x808 +1 x809 +1 x810 +1 x811 +1 x812 +1 x813 +1 x814 +1 x815 +1 x816 +1 x817 +1 x818 +1 x819 +1 x820 +1 x821 +1 x822 +1 x823 +1 x824 +1 x825 +1 x826 +1 x827 +1 x828 +1 x829 +1 x830 +1 x831 +1 x832 +1 x833 +1 x834 +1 x835 +1 x836 +1 x837 +1 x838 +1 x839 +1 x840 +1 x841 +1 x842 +1 x843 +1 x844 +1 x845 +1 x846 +1 x847 +1 x848 +1 x849 +1 x850 +1 x851 +1 x852 +1 x853 +1 x854 +1 x855 +1 x856 +1 x857 +1 x858 +1 x859 +1 x860 +1 x861 +1 x862 +1 x863 +1 x864 +1 x865 +1 x866 +1 x867 +1 x868 +1 x869 +1 x870 +1 x871 +1 x872 +1 x873 +1 x874 +1 x875 +1 x876 +1 x877 +1 x878 +1 x879 +1 x880 +1 x881 +1 x882 +1 x883 +1 x884 +1 x885 +1 x886 +1 x887 +1 x888 +1 x889 +1 x890 +1 x891 >= 1;
++1 x892 +1 x893 +1 x894 +1 x895 +1 x896 +1 x897 +1 x898 +1 x899 +1 x900 +1 x901 +1 x902 +1 x903 +1 x904 +1 x905 +1 x906 +1 x907 +1 x908 +1 x909 +1 x910 +1 x911 +1 x912 +1 x913 +1 x914 +1 x915 +1 x916 +1 x917 +1 x918 +1 x919 +1 x920 +1 x921 +1 x922 +1 x923 +1 x924 +1 x925 +1 x926 +1 x927 +1 x928 +1 x929 +1 x930 +1 x931 +1 x932 +1 x933 +1 x934 +1 x935 +1 x936 +1 x937 +1 x938 +1 x939 +1 x940 +1 x941 +1 x942 +1 x943 +1 x944 +1 x945 +1 x946 +1 x947 +1 x948 +1 x949 +1 x950 +1 x951 +1 x952 +1 x953 +1 x954 +1 x955 +1 x956 +1 x957 +1 x958 +1 x959 +1 x960 +1 x961 +1 x962 +1 x963 +1 x964 +1 x965 +1 x966 +1 x967 +1 x968 +1 x969 +1 x970 +1 x971 +1 x972 +1 x973 +1 x974 +1 x975 +1 x976 +1 x977 +1 x978 +1 x979 +1 x980 +1 x981 +1 x982 +1 x983 +1 x984 +1 x985 +1 x986 +1 x987 +1 x988 +1 x989 +1 x990 >= 1;
++1 x991 +1 x992 +1 x993 +1 x994 +1 x995 +1 x996 +1 x997 +1 x998 +1 x999 +1 x1000 +1 x1001 +1 x1002 +1 x1003 +1 x1004 +1 x1005 +1 x1006 +1 x1007 +1 x1008 +1 x1009 +1 x1010 +1 x1011 +1 x1012 +1 x1013 +1 x1014 +1 x1015 +1 x1016 +1 x1017 +1 x1018 +1 x1019 +1 x1020 +1 x1021 +1 x1022 +1 x1023 +1 x1024 +1 x1025 +1 x1026 +1 x1027 +1 x1028 +1 x1029 +1 x1030 +1 x1031 +1 x1032 +1 x1033 +1 x1034 +1 x1035 +1 x1036 +1 x1037 +1 x1038 +1 x1039 +1 x1040 +1 x1041 +1 x1042 +1 x1043 +1 x1044 +1 x1045 +1 x1046 +1 x1047 +1 x1048 +1 x1049 +1 x1050 +1 x1051 +1 x1052 +1 x1053 +1 x1054 +1 x1055 +1 x1056 +1 x1057 +1 x1058 +1 x1059 +1 x1060 +1 x1061 +1 x1062 +1 x1063 +1 x1064 +1 x1065 +1 x1066 +1 x1067 +1 x1068 +1 x1069 +1 x1070 +1 x1071 +1 x1072 +1 x1073 +1 x1074 +1 x1075 +1 x1076 +1 x1077 +1 x1078 +1 x1079 +1 x1080 +1 x1081 +1 x1082 +1 x1083 +1 x1084 +1 x1085 +1 x1086 +1 x1087 +1 x1088 +1 x1089 >= 1;
++1 x1090 +1 x1091 +1 x1092 +1 x1093 +1 x1094 +1 x1095 +1 x1096 +1 x1097 +1 x1098 +1 x1099 +1 x1100 +1 x1101 +1 x1102 +1 x1103 +1 x1104 +1 x1105 +1 x1106 +1 x1107 +1 x1108 +1 x1109 +1 x1110 +1 x1111 +1 x1112 +1 x1113 +1 x1114 +1 x1115 +1 x1116 +1 x1117 +1 x1118 +1 x1119 +1 x1120 +1 x1121 +1 x1122 +1 x1123 +1 x1124 +1 x1125 +1 x1126 +1 x1127 +1 x1128 +1 x1129 +1 x1130 +1 x1131 +1 x1132 +1 x1133 +1 x1134 +1 x1135 +1 x1136 +1 x1137 +1 x1138 +1 x1139 +1 x1140 +1 x1141 +1 x1142 +1 x1143 +1 x1144 +1 x1145 +1 x1146 +1 x1147 +1 x1148 +1 x1149 +1 x1150 +1 x1151 +1 x1152 +1 x1153 +1 x1154 +1 x1155 +1 x1156 +1 x1157 +1 x1158 +1 x1159 +1 x1160 +1 x1161 +1 x1162 +1 x1163 +1 x1164 +1 x1165 +1 x1166 +1 x1167 +1 x1168 +1 x1169 +1 x1170 +1 x1171 +1 x1172 +1 x1173 +1 x1174 +1 x1175 +1 x1176 +1 x1177 +1 x1178 +1 x1179 +1 x1180 +1 x1181 +1 x1182 +1 x1183 +1 x1184 +1 x1185 +1 x1186 +1 x1187 +1 x1188 >= 1;
++1 x1189 +1 x1190 +1 x1191 +1 x1192 +1 x1193 +1 x1194 +1 x1195 +1 x1196 +1 x1197 +1 x1198 +1 x1199 +1 x1200 +1 x1201 +1 x1202 +1 x1203 +1 x1204 +1 x1205 +1 x1206 +1 x1207 +1 x1208 +1 x1209 +1 x1210 +1 x1211 +1 x1212 +1 x1213 +1 x1214 +1 x1215 +1 x1216 +1 x1217 +1 x1218 +1 x1219 +1 x1220 +1 x1221 +1 x1222 +1 x1223 +1 x1224 +1 x1225 +1 x1226 +1 x1227 +1 x1228 +1 x1229 +1 x1230 +1 x1231 +1 x1232 +1 x1233 +1 x1234 +1 x1235 +1 x1236 +1 x1237 +1 x1238 +1 x1239 +1 x1240 +1 x1241 +1 x1242 +1 x1243 +1 x1244 +1 x1245 +1 x1246 +1 x1247 +1 x1248 +1 x1249 +1 x1250 +1 x1251 +1 x1252 +1 x1253 +1 x1254 +1 x1255 +1 x1256 +1 x1257 +1 x1258 +1 x1259 +1 x1260 +1 x1261 +1 x1262 +1 x1263 +1 x1264 +1 x1265 +1 x1266 +1 x1267 +1 x1268 +1 x1269 +1 x1270 +1 x1271 +1 x1272 +1 x1273 +1 x1274 +1 x1275 +1 x1276 +1 x1277 +1 x1278 +1 x1279 +1 x1280 +1 x1281 +1 x1282 +1 x1283 +1 x1284 +1 x1285 +1 x1286 +1 x1287 >= 1;
++1 x1288 +1 x1289 +1 x1290 +1 x1291 +1 x1292 +1 x1293 +1 x1294 +1 x1295 +1 x1296 +1 x1297 +1 x1298 +1 x1299 +1 x1300 +1 x1301 +1 x1302 +1 x1303 +1 x1304 +1 x1305 +1 x1306 +1 x1307 +1 x1308 +1 x1309 +1 x1310 +1 x1311 +1 x1312 +1 x1313 +1 x1314 +1 x1315 +1 x1316 +1 x1317 +1 x1318 +1 x1319 +1 x1320 +1 x1321 +1 x1322 +1 x1323 +1 x1324 +1 x1325 +1 x1326 +1 x1327 +1 x1328 +1 x1329 +1 x1330 +1 x1331 +1 x1332 +1 x1333 +1 x1334 +1 x1335 +1 x1336 +1 x1337 +1 x1338 +1 x1339 +1 x1340 +1 x1341 +1 x1342 +1 x1343 +1 x1344 +1 x1345 +1 x1346 +1 x1347 +1 x1348 +1 x1349 +1 x1350 +1 x1351 +1 x1352 +1 x1353 +1 x1354 +1 x1355 +1 x1356 +1 x1357 +1 x1358 +1 x1359 +1 x1360 +1 x1361 +1 x1362 +1 x1363 +1 x1364 +1 x1365 +1 x1366 +1 x1367 +1 x1368 +1 x1369 +1 x1370 +1 x1371 +1 x1372 +1 x1373 +1 x1374 +1 x1375 +1 x1376 +1 x1377 +1 x1378 +1 x1379 +1 x1380 +1 x1381 +1 x1382 +1 x1383 +1 x1384 +1 x1385 +1 x1386 >= 1;
++1 x1387 +1 x1388 +1 x1389 +1 x1390 +1 x1391 +1 x1392 +1 x1393 +1 x1394 +1 x1395 +1 x1396 +1 x1397 +1 x1398 +1 x1399 +1 x1400 +1 x1401 +1 x1402 +1 x1403 +1 x1404 +1 x1405 +1 x1406 +1 x1407 +1 x1408 +1 x1409 +1 x1410 +1 x1411 +1 x1412 +1 x1413 +1 x1414 +1 x1415 +1 x1416 +1 x1417 +1 x1418 +1 x1419 +1 x1420 +1 x1421 +1 x1422 +1 x1423 +1 x1424 +1 x1425 +1 x1426 +1 x1427 +1 x1428 +1 x1429 +1 x1430 +1 x1431 +1 x1432 +1 x1433 +1 x1434 +1 x1435 +1 x1436 +1 x1437 +1 x1438 +1 x1439 +1 x1440 +1 x1441 +1 x1442 +1 x1443 +1 x1444 +1 x1445 +1 x1446 +1 x1447 +1 x1448 +1 x1449 +1 x1450 +1 x1451 +1 x1452 +1 x1453 +1 x1454 +1 x1455 +1 x1456 +1 x1457 +1 x1458 +1 x1459 +1 x1460 +1 x1461 +1 x1462 +1 x1463 +1 x1464 +1 x1465 +1 x1466 +1 x1467 +1 x1468 +1 x1469 +1 x1470 +1 x1471 +1 x1472 +1 x1473 +1 x1474 +1 x1475 +1 x1476 +1 x1477 +1 x1478 +1 x1479 +1 x1480 +1 x1481 +1 x1482 +1 x1483 +1 x1484 +1 x1485 >= 1;
++1 x1486 +1 x1487 +1 x1488 +1 x1489 +1 x1490 +1 x1491 +1 x1492 +1 x1493 +1 x1494 +1 x1495 +1 x1496 +1 x1497 +1 x1498 +1 x1499 +1 x1500 +1 x1501 +1 x1502 +1 x1503 +1 x1504 +1 x1505 +1 x1506 +1 x1507 +1 x1508 +1 x1509 +1 x1510 +1 x1511 +1 x1512 +1 x1513 +1 x1514 +1 x1515 +1 x1516 +1 x1517 +1 x1518 +1 x1519 +1 x1520 +1 x1521 +1 x1522 +1 x1523 +1 x1524 +1 x1525 +1 x1526 +1 x1527 +1 x1528 +1 x1529 +1 x1530 +1 x1531 +1 x1532 +1 x1533 +1 x1534 +1 x1535 +1 x1536 +1 x1537 +1 x1538 +1 x1539 +1 x1540 +1 x1541 +1 x1542 +1 x1543 +1 x1544 +1 x1545 +1 x1546 +1 x1547 +1 x1548 +1 x1549 +1 x1550 +1 x1551 +1 x1552 +1 x1553 +1 x1554 +1 x1555 +1 x1556 +1 x1557 +1 x1558 +1 x1559 +1 x1560 +1 x1561 +1 x1562 +1 x1563 +1 x1564 +1 x1565 +1 x1566 +1 x1567 +1 x1568 +1 x1569 +1 x1570 +1 x1571 +1 x1572 +1 x1573 +1 x1574 +1 x1575 +1 x1576 +1 x1577 +1 x1578 +1 x1579 +1 x1580 +1 x1581 +1 x1582 +1 x1583 +1 x1584 >= 1;
++1 x1585 +1 x1586 +1 x1587 +1 x1588 +1 x1589 +1 x1590 +1 x1591 +1 x1592 +1 x1593 +1 x1594 +1 x1595 +1 x1596 +1 x1597 +1 x1598 +1 x1599 +1 x1600 +1 x1601 +1 x1602 +1 x1603 +1 x1604 +1 x1605 +1 x1606 +1 x1607 +1 x1608 +1 x1609 +1 x1610 +1 x1611 +1 x1612 +1 x1613 +1 x1614 +1 x1615 +1 x1616 +1 x1617 +1 x1618 +1 x1619 +1 x1620 +1 x1621 +1 x1622 +1 x1623 +1 x1624 +1 x1625 +1 x1626 +1 x1627 +1 x1628 +1 x1629 +1 x1630 +1 x1631 +1 x1632 +1 x1633 +1 x1634 +1 x1635 +1 x1636 +1 x1637 +1 x1638 +1 x1639 +1 x1640 +1 x1641 +1 x1642 +1 x1643 +1 x1644 +1 x1645 +1 x1646 +1 x1647 +1 x1648 +1 x1649 +1 x1650 +1 x1651 +1 x1652 +1 x1653 +1 x1654 +1 x1655 +1 x1656 +1 x1657 +1 x1658 +1 x1659 +1 x1660 +1 x1661 +1 x1662 +1 x1663 +1 x1664 +1 x1665 +1 x1666 +1 x1667 +1 x1668 +1 x1669 +1 x1670 +1 x1671 +1 x1672 +1 x1673 +1 x1674 +1 x1675 +1 x1676 +1 x1677 +1 x1678 +1 x1679 +1 x1680 +1 x1681 +1 x1682 +1 x1683 >= 1;
++1 x1684 +1 x1685 +1 x1686 +1 x1687 +1 x1688 +1 x1689 +1 x1690 +1 x1691 +1 x1692 +1 x1693 +1 x1694 +1 x1695 +1 x1696 +1 x1697 +1 x1698 +1 x1699 +1 x1700 +1 x1701 +1 x1702 +1 x1703 +1 x1704 +1 x1705 +1 x1706 +1 x1707 +1 x1708 +1 x1709 +1 x1710 +1 x1711 +1 x1712 +1 x1713 +1 x1714 +1 x1715 +1 x1716 +1 x1717 +1 x1718 +1 x1719 +1 x1720 +1 x1721 +1 x1722 +1 x1723 +1 x1724 +1 x1725 +1 x1726 +1 x1727 +1 x1728 +1 x1729 +1 x1730 +1 x1731 +1 x1732 +1 x1733 +1 x1734 +1 x1735 +1 x1736 +1 x1737 +1 x1738 +1 x1739 +1 x1740 +1 x1741 +1 x1742 +1 x1743 +1 x1744 +1 x1745 +1 x1746 +1 x1747 +1 x1748 +1 x1749 +1 x1750 +1 x1751 +1 x1752 +1 x1753 +1 x1754 +1 x1755 +1 x1756 +1 x1757 +1 x1758 +1 x1759 +1 x1760 +1 x1761 +1 x1762 +1 x1763 +1 x1764 +1 x1765 +1 x1766 +1 x1767 +1 x1768 +1 x1769 +1 x1770 +1 x1771 +1 x1772 +1 x1773 +1 x1774 +1 x1775 +1 x1776 +1 x1777 +1 x1778 +1 x1779 +1 x1780 +1 x1781 +1 x1782 >= 1;
++1 x1783 +1 x1784 +1 x1785 +1 x1786 +1 x1787 +1 x1788 +1 x1789 +1 x1790 +1 x1791 +1 x1792 +1 x1793 +1 x1794 +1 x1795 +1 x1796 +1 x1797 +1 x1798 +1 x1799 +1 x1800 +1 x1801 +1 x1802 +1 x1803 +1 x1804 +1 x1805 +1 x1806 +1 x1807 +1 x1808 +1 x1809 +1 x1810 +1 x1811 +1 x1812 +1 x1813 +1 x1814 +1 x1815 +1 x1816 +1 x1817 +1 x1818 +1 x1819 +1 x1820 +1 x1821 +1 x1822 +1 x1823 +1 x1824 +1 x1825 +1 x1826 +1 x1827 +1 x1828 +1 x1829 +1 x1830 +1 x1831 +1 x1832 +1 x1833 +1 x1834 +1 x1835 +1 x1836 +1 x1837 +1 x1838 +1 x1839 +1 x1840 +1 x1841 +1 x1842 +1 x1843 +1 x1844 +1 x1845 +1 x1846 +1 x1847 +1 x1848 +1 x1849 +1 x1850 +1 x1851 +1 x1852 +1 x1853 +1 x1854 +1 x1855 +1 x1856 +1 x1857 +1 x1858 +1 x1859 +1 x1860 +1 x1861 +1 x1862 +1 x1863 +1 x1864 +1 x1865 +1 x1866 +1 x1867 +1 x1868 +1 x1869 +1 x1870 +1 x1871 +1 x1872 +1 x1873 +1 x1874 +1 x1875 +1 x1876 +1 x1877 +1 x1878 +1 x1879 +1 x1880 +1 x1881 >= 1;
++1 x1882 +1 x1883 +1 x1884 +1 x1885 +1 x1886 +1 x1887 +1 x1888 +1 x1889 +1 x1890 +1 x1891 +1 x1892 +1 x1893 +1 x1894 +1 x1895 +1 x1896 +1 x1897 +1 x1898 +1 x1899 +1 x1900 +1 x1901 +1 x1902 +1 x1903 +1 x1904 +1 x1905 +1 x1906 +1 x1907 +1 x1908 +1 x1909 +1 x1910 +1 x1911 +1 x1912 +1 x1913 +1 x1914 +1 x1915 +1 x1916 +1 x1917 +1 x1918 +1 x1919 +1 x1920 +1 x1921 +1 x1922 +1 x1923 +1 x1924 +1 x1925 +1 x1926 +1 x1927 +1 x1928 +1 x1929 +1 x1930 +1 x1931 +1 x1932 +1 x1933 +1 x1934 +1 x1935 +1 x1936 +1 x1937 +1 x1938 +1 x1939 +1 x1940 +1 x1941 +1 x1942 +1 x1943 +1 x1944 +1 x1945 +1 x1946 +1 x1947 +1 x1948 +1 x1949 +1 x1950 +1 x1951 +1 x1952 +1 x1953 +1 x1954 +1 x1955 +1 x1956 +1 x1957 +1 x1958 +1 x1959 +1 x1960 +1 x1961 +1 x1962 +1 x1963 +1 x1964 +1 x1965 +1 x1966 +1 x1967 +1 x1968 +1 x1969 +1 x1970 +1 x1971 +1 x1972 +1 x1973 +1 x1974 +1 x1975 +1 x1976 +1 x1977 +1 x1978 +1 x1979 +1 x1980 >= 1;
++1 x1981 +1 x1982 +1 x1983 +1 x1984 +1 x1985 +1 x1986 +1 x1987 +1 x1988 +1 x1989 +1 x1990 +1 x1991 +1 x1992 +1 x1993 +1 x1994 +1 x1995 +1 x1996 +1 x1997 +1 x1998 +1 x1999 +1 x2000 +1 x2001 +1 x2002 +1 x2003 +1 x2004 +1 x2005 +1 x2006 +1 x2007 +1 x2008 +1 x2009 +1 x2010 +1 x2011 +1 x2012 +1 x2013 +1 x2014 +1 x2015 +1 x2016 +1 x2017 +1 x2018 +1 x2019 +1 x2020 +1 x2021 +1 x2022 +1 x2023 +1 x2024 +1 x2025 +1 x2026 +1 x2027 +1 x2028 +1 x2029 +1 x2030 +1 x2031 +1 x2032 +1 x2033 +1 x2034 +1 x2035 +1 x2036 +1 x2037 +1 x2038 +1 x2039 +1 x2040 +1 x2041 +1 x2042 +1 x2043 +1 x2044 +1 x2045 +1 x2046 +1 x2047 +1 x2048 +1 x2049 +1 x2050 +1 x2051 +1 x2052 +1 x2053 +1 x2054 +1 x2055 +1 x2056 +1 x2057 +1 x2058 +1 x2059 +1 x2060 +1 x2061 +1 x2062 +1 x2063 +1 x2064 +1 x2065 +1 x2066 +1 x2067 +1 x2068 +1 x2069 +1 x2070 +1 x2071 +1 x2072 +1 x2073 +1 x2074 +1 x2075 +1 x2076 +1 x2077 +1 x2078 +1 x2079 >= 1;
++1 x2080 +1 x2081 +1 x2082 +1 x2083 +1 x2084 +1 x2085 +1 x2086 +1 x2087 +1 x2088 +1 x2089 +1 x2090 +1 x2091 +1 x2092 +1 x2093 +1 x2094 +1 x2095 +1 x2096 +1 x2097 +1 x2098 +1 x2099 +1 x2100 +1 x2101 +1 x2102 +1 x2103 +1 x2104 +1 x2105 +1 x2106 +1 x2107 +1 x2108 +1 x2109 +1 x2110 +1 x2111 +1 x2112 +1 x2113 +1 x2114 +1 x2115 +1 x2116 +1 x2117 +1 x2118 +1 x2119 +1 x2120 +1 x2121 +1 x2122 +1 x2123 +1 x2124 +1 x2125 +1 x2126 +1 x2127 +1 x2128 +1 x2129 +1 x2130 +1 x2131 +1 x2132 +1 x2133 +1 x2134 +1 x2135 +1 x2136 +1 x2137 +1 x2138 +1 x2139 +1 x2140 +1 x2141 +1 x2142 +1 x2143 +1 x2144 +1 x2145 +1 x2146 +1 x2147 +1 x2148 +1 x2149 +1 x2150 +1 x2151 +1 x2152 +1 x2153 +1 x2154 +1 x2155 +1 x2156 +1 x2157 +1 x2158 +1 x2159 +1 x2160 +1 x2161 +1 x2162 +1 x2163 +1 x2164 +1 x2165 +1 x2166 +1 x2167 +1 x2168 +1 x2169 +1 x2170 +1 x2171 +1 x2172 +1 x2173 +1 x2174 +1 x2175 +1 x2176 +1 x2177 +1 x2178 >= 1;
++1 x2179 +1 x2180 +1 x2181 +1 x2182 +1 x2183 +1 x2184 +1 x2185 +1 x2186 +1 x2187 +1 x2188 +1 x2189 +1 x2190 +1 x2191 +1 x2192 +1 x2193 +1 x2194 +1 x2195 +1 x2196 +1 x2197 +1 x2198 +1 x2199 +1 x2200 +1 x2201 +1 x2202 +1 x2203 +1 x2204 +1 x2205 +1 x2206 +1 x2207 +1 x2208 +1 x2209 +1 x2210 +1 x2211 +1 x2212 +1 x2213 +1 x2214 +1 x2215 +1 x2216 +1 x2217 +1 x2218 +1 x2219 +1 x2220 +1 x2221 +1 x2222 +1 x2223 +1 x2224 +1 x2225 +1 x2226 +1 x2227 +1 x2228 +1 x2229 +1 x2230 +1 x2231 +1 x2232 +1 x2233 +1 x2234 +1 x2235 +1 x2236 +1 x2237 +1 x2238 +1 x2239 +1 x2240 +1 x2241 +1 x2242 +1 x2243 +1 x2244 +1 x2245 +1 x2246 +1 x2247 +1 x2248 +1 x2249 +1 x2250 +1 x2251 +1 x2252 +1 x2253 +1 x2254 +1 x2255 +1 x2256 +1 x2257 +1 x2258 +1 x2259 +1 x2260 +1 x2261 +1 x2262 +1 x2263 +1 x2264 +1 x2265 +1 x2266 +1 x2267 +1 x2268 +1 x2269 +1 x2270 +1 x2271 +1 x2272 +1 x2273 +1 x2274 +1 x2275 +1 x2276 +1 x2277 >= 1;
++1 x2278 +1 x2279 +1 x2280 +1 x2281 +1 x2282 +1 x2283 +1 x2284 +1 x2285 +1 x2286 +1 x2287 +1 x2288 +1 x2289 +1 x2290 +1 x2291 +1 x2292 +1 x2293 +1 x2294 +1 x2295 +1 x2296 +1 x2297 +1 x2298 +1 x2299 +1 x2300 +1 x2301 +1 x2302 +1 x2303 +1 x2304 +1 x2305 +1 x2306 +1 x2307 +1 x2308 +1 x2309 +1 x2310 +1 x2311 +1 x2312 +1 x2313 +1 x2314 +1 x2315 +1 x2316 +1 x2317 +1 x2318 +1 x2319 +1 x2320 +1 x2321 +1 x2322 +1 x2323 +1 x2324 +1 x2325 +1 x2326 +1 x2327 +1 x2328 +1 x2329 +1 x2330 +1 x2331 +1 x2332 +1 x2333 +1 x2334 +1 x2335 +1 x2336 +1 x2337 +1 x2338 +1 x2339 +1 x2340 +1 x2341 +1 x2342 +1 x2343 +1 x2344 +1 x2345 +1 x2346 +1 x2347 +1 x2348 +1 x2349 +1 x2350 +1 x2351 +1 x2352 +1 x2353 +1 x2354 +1 x2355 +1 x2356 +1 x2357 +1 x2358 +1 x2359 +1 x2360 +1 x2361 +1 x2362 +1 x2363 +1 x2364 +1 x2365 +1 x2366 +1 x2367 +1 x2368 +1 x2369 +1 x2370 +1 x2371 +1 x2372 +1 x2373 +1 x2374 +1 x2375 +1 x2376 >= 1;
++1 x2377 +1 x2378 +1 x2379 +1 x2380 +1 x2381 +1 x2382 +1 x2383 +1 x2384 +1 x2385 +1 x2386 +1 x2387 +1 x2388 +1 x2389 +1 x2390 +1 x2391 +1 x2392 +1 x2393 +1 x2394 +1 x2395 +1 x2396 +1 x2397 +1 x2398 +1 x2399 +1 x2400 +1 x2401 +1 x2402 +1 x2403 +1 x2404 +1 x2405 +1 x2406 +1 x2407 +1 x2408 +1 x2409 +1 x2410 +1 x2411 +1 x2412 +1 x2413 +1 x2414 +1 x2415 +1 x2416 +1 x2417 +1 x2418 +1 x2419 +1 x2420 +1 x2421 +1 x2422 +1 x2423 +1 x2424 +1 x2425 +1 x2426 +1 x2427 +1 x2428 +1 x2429 +1 x2430 +1 x2431 +1 x2432 +1 x2433 +1 x2434 +1 x2435 +1 x2436 +1 x2437 +1 x2438 +1 x2439 +1 x2440 +1 x2441 +1 x2442 +1 x2443 +1 x2444 +1 x2445 +1 x2446 +1 x2447 +1 x2448 +1 x2449 +1 x2450 +1 x2451 +1 x2452 +1 x2453 +1 x2454 +1 x2455 +1 x2456 +1 x2457 +1 x2458 +1 x2459 +1 x2460 +1 x2461 +1 x2462 +1 x2463 +1 x2464 +1 x2465 +1 x2466 +1 x2467 +1 x2468 +1 x2469 +1 x2470 +1 x2471 +1 x2472 +1 x2473 +1 x2474 +1 x2475 >= 1;
++1 x2476 +1 x2477 +1 x2478 +1 x2479 +1 x2480 +1 x2481 +1 x2482 +1 x2483 +1 x2484 +1 x2485 +1 x2486 +1 x2487 +1 x2488 +1 x2489 +1 x2490 +1 x2491 +1 x2492 +1 x2493 +1 x2494 +1 x2495 +1 x2496 +1 x2497 +1 x2498 +1 x2499 +1 x2500 +1 x2501 +1 x2502 +1 x2503 +1 x2504 +1 x2505 +1 x2506 +1 x2507 +1 x2508 +1 x2509 +1 x2510 +1 x2511 +1 x2512 +1 x2513 +1 x2514 +1 x2515 +1 x2516 +1 x2517 +1 x2518 +1 x2519 +1 x2520 +1 x2521 +1 x2522 +1 x2523 +1 x2524 +1 x2525 +1 x2526 +1 x2527 +1 x2528 +1 x2529 +1 x2530 +1 x2531 +1 x2532 +1 x2533 +1 x2534 +1 x2535 +1 x2536 +1 x2537 +1 x2538 +1 x2539 +1 x2540 +1 x2541 +1 x2542 +1 x2543 +1 x2544 +1 x2545 +1 x2546 +1 x2547 +1 x2548 +1 x2549 +1 x2550 +1 x2551 +1 x2552 +1 x2553 +1 x2554 +1 x2555 +1 x2556 +1 x2557 +1 x2558 +1 x2559 +1 x2560 +1 x2561 +1 x2562 +1 x2563 +1 x2564 +1 x2565 +1 x2566 +1 x2567 +1 x2568 +1 x2569 +1 x2570 +1 x2571 +1 x2572 +1 x2573 +1 x2574 >= 1;
++1 x2575 +1 x2576 +1 x2577 +1 x2578 +1 x2579 +1 x2580 +1 x2581 +1 x2582 +1 x2583 +1 x2584 +1 x2585 +1 x2586 +1 x2587 +1 x2588 +1 x2589 +1 x2590 +1 x2591 +1 x2592 +1 x2593 +1 x2594 +1 x2595 +1 x2596 +1 x2597 +1 x2598 +1 x2599 +1 x2600 +1 x2601 +1 x2602 +1 x2603 +1 x2604 +1 x2605 +1 x2606 +1 x2607 +1 x2608 +1 x2609 +1 x2610 +1 x2611 +1 x2612 +1 x2613 +1 x2614 +1 x2615 +1 x2616 +1 x2617 +1 x2618 +1 x2619 +1 x2620 +1 x2621 +1 x2622 +1 x2623 +1 x2624 +1 x2625 +1 x2626 +1 x2627 +1 x2628 +1 x2629 +1 x2630 +1 x2631 +1 x2632 +1 x2633 +1 x2634 +1 x2635 +1 x2636 +1 x2637 +1 x2638 +1 x2639 +1 x2640 +1 x2641 +1 x2642 +1 x2643 +1 x2644 +1 x2645 +1 x2646 +1 x2647 +1 x2648 +1 x2649 +1 x2650 +1 x2651 +1 x2652 +1 x2653 +1 x2654 +1 x2655 +1 x2656 +1 x2657 +1 x2658 +1 x2659 +1 x2660 +1 x2661 +1 x2662 +1 x2663 +1 x2664 +1 x2665 +1 x2666 +1 x2667 +1 x2668 +1 x2669 +1 x2670 +1 x2671 +1 x2672 +1 x2673 >= 1;
++1 x2674 +1 x2675 +1 x2676 +1 x2677 +1 x2678 +1 x2679 +1 x2680 +1 x2681 +1 x2682 +1 x2683 +1 x2684 +1 x2685 +1 x2686 +1 x2687 +1 x2688 +1 x2689 +1 x2690 +1 x2691 +1 x2692 +1 x2693 +1 x2694 +1 x2695 +1 x2696 +1 x2697 +1 x2698 +1 x2699 +1 x2700 +1 x2701 +1 x2702 +1 x2703 +1 x2704 +1 x2705 +1 x2706 +1 x2707 +1 x2708 +1 x2709 +1 x2710 +1 x2711 +1 x2712 +1 x2713 +1 x2714 +1 x2715 +1 x2716 +1 x2717 +1 x2718 +1 x2719 +1 x2720 +1 x2721 +1 x2722 +1 x2723 +1 x2724 +1 x2725 +1 x2726 +1 x2727 +1 x2728 +1 x2729 +1 x2730 +1 x2731 +1 x2732 +1 x2733 +1 x2734 +1 x2735 +1 x2736 +1 x2737 +1 x2738 +1 x2739 +1 x2740 +1 x2741 +1 x2742 +1 x2743 +1 x2744 +1 x2745 +1 x2746 +1 x2747 +1 x2748 +1 x2749 +1 x2750 +1 x2751 +1 x2752 +1 x2753 +1 x2754 +1 x2755 +1 x2756 +1 x2757 +1 x2758 +1 x2759 +1 x2760 +1 x2761 +1 x2762 +1 x2763 +1 x2764 +1 x2765 +1 x2766 +1 x2767 +1 x2768 +1 x2769 +1 x2770 +1 x2771 +1 x2772 >= 1;
++1 x2773 +1 x2774 +1 x2775 +1 x2776 +1 x2777 +1 x2778 +1 x2779 +1 x2780 +1 x2781 +1 x2782 +1 x2783 +1 x2784 +1 x2785 +1 x2786 +1 x2787 +1 x2788 +1 x2789 +1 x2790 +1 x2791 +1 x2792 +1 x2793 +1 x2794 +1 x2795 +1 x2796 +1 x2797 +1 x2798 +1 x2799 +1 x2800 +1 x2801 +1 x2802 +1 x2803 +1 x2804 +1 x2805 +1 x2806 +1 x2807 +1 x2808 +1 x2809 +1 x2810 +1 x2811 +1 x2812 +1 x2813 +1 x2814 +1 x2815 +1 x2816 +1 x2817 +1 x2818 +1 x2819 +1 x2820 +1 x2821 +1 x2822 +1 x2823 +1 x2824 +1 x2825 +1 x2826 +1 x2827 +1 x2828 +1 x2829 +1 x2830 +1 x2831 +1 x2832 +1 x2833 +1 x2834 +1 x2835 +1 x2836 +1 x2837 +1 x2838 +1 x2839 +1 x2840 +1 x2841 +1 x2842 +1 x2843 +1 x2844 +1 x2845 +1 x2846 +1 x2847 +1 x2848 +1 x2849 +1 x2850 +1 x2851 +1 x2852 +1 x2853 +1 x2854 +1 x2855 +1 x2856 +1 x2857 +1 x2858 +1 x2859 +1 x2860 +1 x2861 +1 x2862 +1 x2863 +1 x2864 +1 x2865 +1 x2866 +1 x2867 +1 x2868 +1 x2869 +1 x2870 +1 x2871 >= 1;
++1 x2872 +1 x2873 +1 x2874 +1 x2875 +1 x2876 +1 x2877 +1 x2878 +1 x2879 +1 x2880 +1 x2881 +1 x2882 +1 x2883 +1 x2884 +1 x2885 +1 x2886 +1 x2887 +1 x2888 +1 x2889 +1 x2890 +1 x2891 +1 x2892 +1 x2893 +1 x2894 +1 x2895 +1 x2896 +1 x2897 +1 x2898 +1 x2899 +1 x2900 +1 x2901 +1 x2902 +1 x2903 +1 x2904 +1 x2905 +1 x2906 +1 x2907 +1 x2908 +1 x2909 +1 x2910 +1 x2911 +1 x2912 +1 x2913 +1 x2914 +1 x2915 +1 x2916 +1 x2917 +1 x2918 +1 x2919 +1 x2920 +1 x2921 +1 x2922 +1 x2923 +1 x2924 +1 x2925 +1 x2926 +1 x2927 +1 x2928 +1 x2929 +1 x2930 +1 x2931 +1 x2932 +1 x2933 +1 x2934 +1 x2935 +1 x2936 +1 x2937 +1 x2938 +1 x2939 +1 x2940 +1 x2941 +1 x2942 +1 x2943 +1 x2944 +1 x2945 +1 x2946 +1 x2947 +1 x2948 +1 x2949 +1 x2950 +1 x2951 +1 x2952 +1 x2953 +1 x2954 +1 x2955 +1 x2956 +1 x2957 +1 x2958 +1 x2959 +1 x2960 +1 x2961 +1 x2962 +1 x2963 +1 x2964 +1 x2965 +1 x2966 +1 x2967 +1 x2968 +1 x2969 +1 x2970 >= 1;
++1 x2971 +1 x2972 +1 x2973 +1 x2974 +1 x2975 +1 x2976 +1 x2977 +1 x2978 +1 x2979 +1 x2980 +1 x2981 +1 x2982 +1 x2983 +1 x2984 +1 x2985 +1 x2986 +1 x2987 +1 x2988 +1 x2989 +1 x2990 +1 x2991 +1 x2992 +1 x2993 +1 x2994 +1 x2995 +1 x2996 +1 x2997 +1 x2998 +1 x2999 +1 x3000 +1 x3001 +1 x3002 +1 x3003 +1 x3004 +1 x3005 +1 x3006 +1 x3007 +1 x3008 +1 x3009 +1 x3010 +1 x3011 +1 x3012 +1 x3013 +1 x3014 +1 x3015 +1 x3016 +1 x3017 +1 x3018 +1 x3019 +1 x3020 +1 x3021 +1 x3022 +1 x3023 +1 x3024 +1 x3025 +1 x3026 +1 x3027 +1 x3028 +1 x3029 +1 x3030 +1 x3031 +1 x3032 +1 x3033 +1 x3034 +1 x3035 +1 x3036 +1 x3037 +1 x3038 +1 x3039 +1 x3040 +1 x3041 +1 x3042 +1 x3043 +1 x3044 +1 x3045 +1 x3046 +1 x3047 +1 x3048 +1 x3049 +1 x3050 +1 x3051 +1 x3052 +1 x3053 +1 x3054 +1 x3055 +1 x3056 +1 x3057 +1 x3058 +1 x3059 +1 x3060 +1 x3061 +1 x3062 +1 x3063 +1 x3064 +1 x3065 +1 x3066 +1 x3067 +1 x3068 +1 x3069 >= 1;
++1 x3070 +1 x3071 +1 x3072 +1 x3073 +1 x3074 +1 x3075 +1 x3076 +1 x3077 +1 x3078 +1 x3079 +1 x3080 +1 x3081 +1 x3082 +1 x3083 +1 x3084 +1 x3085 +1 x3086 +1 x3087 +1 x3088 +1 x3089 +1 x3090 +1 x3091 +1 x3092 +1 x3093 +1 x3094 +1 x3095 +1 x3096 +1 x3097 +1 x3098 +1 x3099 +1 x3100 +1 x3101 +1 x3102 +1 x3103 +1 x3104 +1 x3105 +1 x3106 +1 x3107 +1 x3108 +1 x3109 +1 x3110 +1 x3111 +1 x3112 +1 x3113 +1 x3114 +1 x3115 +1 x3116 +1 x3117 +1 x3118 +1 x3119 +1 x3120 +1 x3121 +1 x3122 +1 x3123 +1 x3124 +1 x3125 +1 x3126 +1 x3127 +1 x3128 +1 x3129 +1 x3130 +1 x3131 +1 x3132 +1 x3133 +1 x3134 +1 x3135 +1 x3136 +1 x3137 +1 x3138 +1 x3139 +1 x3140 +1 x3141 +1 x3142 +1 x3143 +1 x3144 +1 x3145 +1 x3146 +1 x3147 +1 x3148 +1 x3149 +1 x3150 +1 x3151 +1 x3152 +1 x3153 +1 x3154 +1 x3155 +1 x3156 +1 x3157 +1 x3158 +1 x3159 +1 x3160 +1 x3161 +1 x3162 +1 x3163 +1 x3164 +1 x3165 +1 x3166 +1 x3167 +1 x3168 >= 1;
++1 x3169 +1 x3170 +1 x3171 +1 x3172 +1 x3173 +1 x3174 +1 x3175 +1 x3176 +1 x3177 +1 x3178 +1 x3179 +1 x3180 +1 x3181 +1 x3182 +1 x3183 +1 x3184 +1 x3185 +1 x3186 +1 x3187 +1 x3188 +1 x3189 +1 x3190 +1 x3191 +1 x3192 +1 x3193 +1 x3194 +1 x3195 +1 x3196 +1 x3197 +1 x3198 +1 x3199 +1 x3200 +1 x3201 +1 x3202 +1 x3203 +1 x3204 +1 x3205 +1 x3206 +1 x3207 +1 x3208 +1 x3209 +1 x3210 +1 x3211 +1 x3212 +1 x3213 +1 x3214 +1 x3215 +1 x3216 +1 x3217 +1 x3218 +1 x3219 +1 x3220 +1 x3221 +1 x3222 +1 x3223 +1 x3224 +1 x3225 +1 x3226 +1 x3227 +1 x3228 +1 x3229 +1 x3230 +1 x3231 +1 x3232 +1 x3233 +1 x3234 +1 x3235 +1 x3236 +1 x3237 +1 x3238 +1 x3239 +1 x3240 +1 x3241 +1 x3242 +1 x3243 +1 x3244 +1 x3245 +1 x3246 +1 x3247 +1 x3248 +1 x3249 +1 x3250 +1 x3251 +1 x3252 +1 x3253 +1 x3254 +1 x3255 +1 x3256 +1 x3257 +1 x3258 +1 x3259 +1 x3260 +1 x3261 +1 x3262 +1 x3263 +1 x3264 +1 x3265 +1 x3266 +1 x3267 >= 1;
++1 x3268 +1 x3269 +1 x3270 +1 x3271 +1 x3272 +1 x3273 +1 x3274 +1 x3275 +1 x3276 +1 x3277 +1 x3278 +1 x3279 +1 x3280 +1 x3281 +1 x3282 +1 x3283 +1 x3284 +1 x3285 +1 x3286 +1 x3287 +1 x3288 +1 x3289 +1 x3290 +1 x3291 +1 x3292 +1 x3293 +1 x3294 +1 x3295 +1 x3296 +1 x3297 +1 x3298 +1 x3299 +1 x3300 +1 x3301 +1 x3302 +1 x3303 +1 x3304 +1 x3305 +1 x3306 +1 x3307 +1 x3308 +1 x3309 +1 x3310 +1 x3311 +1 x3312 +1 x3313 +1 x3314 +1 x3315 +1 x3316 +1 x3317 +1 x3318 +1 x3319 +1 x3320 +1 x3321 +1 x3322 +1 x3323 +1 x3324 +1 x3325 +1 x3326 +1 x3327 +1 x3328 +1 x3329 +1 x3330 +1 x3331 +1 x3332 +1 x3333 +1 x3334 +1 x3335 +1 x3336 +1 x3337 +1 x3338 +1 x3339 +1 x3340 +1 x3341 +1 x3342 +1 x3343 +1 x3344 +1 x3345 +1 x3346 +1 x3347 +1 x3348 +1 x3349 +1 x3350 +1 x3351 +1 x3352 +1 x3353 +1 x3354 +1 x3355 +1 x3356 +1 x3357 +1 x3358 +1 x3359 +1 x3360 +1 x3361 +1 x3362 +1 x3363 +1 x3364 +1 x3365 +1 x3366 >= 1;
++1 x3367 +1 x3368 +1 x3369 +1 x3370 +1 x3371 +1 x3372 +1 x3373 +1 x3374 +1 x3375 +1 x3376 +1 x3377 +1 x3378 +1 x3379 +1 x3380 +1 x3381 +1 x3382 +1 x3383 +1 x3384 +1 x3385 +1 x3386 +1 x3387 +1 x3388 +1 x3389 +1 x3390 +1 x3391 +1 x3392 +1 x3393 +1 x3394 +1 x3395 +1 x3396 +1 x3397 +1 x3398 +1 x3399 +1 x3400 +1 x3401 +1 x3402 +1 x3403 +1 x3404 +1 x3405 +1 x3406 +1 x3407 +1 x3408 +1 x3409 +1 x3410 +1 x3411 +1 x3412 +1 x3413 +1 x3414 +1 x3415 +1 x3416 +1 x3417 +1 x3418 +1 x3419 +1 x3420 +1 x3421 +1 x3422 +1 x3423 +1 x3424 +1 x3425 +1 x3426 +1 x3427 +1 x3428 +1 x3429 +1 x3430 +1 x3431 +1 x3432 +1 x3433 +1 x3434 +1 x3435 +1 x3436 +1 x3437 +1 x3438 +1 x3439 +1 x3440 +1 x3441 +1 x3442 +1 x3443 +1 x3444 +1 x3445 +1 x3446 +1 x3447 +1 x3448 +1 x3449 +1 x3450 +1 x3451 +1 x3452 +1 x3453 +1 x3454 +1 x3455 +1 x3456 +1 x3457 +1 x3458 +1 x3459 +1 x3460 +1 x3461 +1 x3462 +1 x3463 +1 x3464 +1 x3465 >= 1;
++1 x3466 +1 x3467 +1 x3468 +1 x3469 +1 x3470 +1 x3471 +1 x3472 +1 x3473 +1 x3474 +1 x3475 +1 x3476 +1 x3477 +1 x3478 +1 x3479 +1 x3480 +1 x3481 +1 x3482 +1 x3483 +1 x3484 +1 x3485 +1 x3486 +1 x3487 +1 x3488 +1 x3489 +1 x3490 +1 x3491 +1 x3492 +1 x3493 +1 x3494 +1 x3495 +1 x3496 +1 x3497 +1 x3498 +1 x3499 +1 x3500 +1 x3501 +1 x3502 +1 x3503 +1 x3504 +1 x3505 +1 x3506 +1 x3507 +1 x3508 +1 x3509 +1 x3510 +1 x3511 +1 x3512 +1 x3513 +1 x3514 +1 x3515 +1 x3516 +1 x3517 +1 x3518 +1 x3519 +1 x3520 +1 x3521 +1 x3522 +1 x3523 +1 x3524 +1 x3525 +1 x3526 +1 x3527 +1 x3528 +1 x3529 +1 x3530 +1 x3531 +1 x3532 +1 x3533 +1 x3534 +1 x3535 +1 x3536 +1 x3537 +1 x3538 +1 x3539 +1 x3540 +1 x3541 +1 x3542 +1 x3543 +1 x3544 +1 x3545 +1 x3546 +1 x3547 +1 x3548 +1 x3549 +1 x3550 +1 x3551 +1 x3552 +1 x3553 +1 x3554 +1 x3555 +1 x3556 +1 x3557 +1 x3558 +1 x3559 +1 x3560 +1 x3561 +1 x3562 +1 x3563 +1 x3564 >= 1;
++1 x3565 +1 x3566 +1 x3567 +1 x3568 +1 x3569 +1 x3570 +1 x3571 +1 x3572 +1 x3573 +1 x3574 +1 x3575 +1 x3576 +1 x3577 +1 x3578 +1 x3579 +1 x3580 +1 x3581 +1 x3582 +1 x3583 +1 x3584 +1 x3585 +1 x3586 +1 x3587 +1 x3588 +1 x3589 +1 x3590 +1 x3591 +1 x3592 +1 x3593 +1 x3594 +1 x3595 +1 x3596 +1 x3597 +1 x3598 +1 x3599 +1 x3600 +1 x3601 +1 x3602 +1 x3603 +1 x3604 +1 x3605 +1 x3606 +1 x3607 +1 x3608 +1 x3609 +1 x3610 +1 x3611 +1 x3612 +1 x3613 +1 x3614 +1 x3615 +1 x3616 +1 x3617 +1 x3618 +1 x3619 +1 x3620 +1 x3621 +1 x3622 +1 x3623 +1 x3624 +1 x3625 +1 x3626 +1 x3627 +1 x3628 +1 x3629 +1 x3630 +1 x3631 +1 x3632 +1 x3633 +1 x3634 +1 x3635 +1 x3636 +1 x3637 +1 x3638 +1 x3639 +1 x3640 +1 x3641 +1 x3642 +1 x3643 +1 x3644 +1 x3645 +1 x3646 +1 x3647 +1 x3648 +1 x3649 +1 x3650 +1 x3651 +1 x3652 +1 x3653 +1 x3654 +1 x3655 +1 x3656 +1 x3657 +1 x3658 +1 x3659 +1 x3660 +1 x3661 +1 x3662 +1 x3663 >= 1;
++1 x3664 +1 x3665 +1 x3666 +1 x3667 +1 x3668 +1 x3669 +1 x3670 +1 x3671 +1 x3672 +1 x3673 +1 x3674 +1 x3675 +1 x3676 +1 x3677 +1 x3678 +1 x3679 +1 x3680 +1 x3681 +1 x3682 +1 x3683 +1 x3684 +1 x3685 +1 x3686 +1 x3687 +1 x3688 +1 x3689 +1 x3690 +1 x3691 +1 x3692 +1 x3693 +1 x3694 +1 x3695 +1 x3696 +1 x3697 +1 x3698 +1 x3699 +1 x3700 +1 x3701 +1 x3702 +1 x3703 +1 x3704 +1 x3705 +1 x3706 +1 x3707 +1 x3708 +1 x3709 +1 x3710 +1 x3711 +1 x3712 +1 x3713 +1 x3714 +1 x3715 +1 x3716 +1 x3717 +1 x3718 +1 x3719 +1 x3720 +1 x3721 +1 x3722 +1 x3723 +1 x3724 +1 x3725 +1 x3726 +1 x3727 +1 x3728 +1 x3729 +1 x3730 +1 x3731 +1 x3732 +1 x3733 +1 x3734 +1 x3735 +1 x3736 +1 x3737 +1 x3738 +1 x3739 +1 x3740 +1 x3741 +1 x3742 +1 x3743 +1 x3744 +1 x3745 +1 x3746 +1 x3747 +1 x3748 +1 x3749 +1 x3750 +1 x3751 +1 x3752 +1 x3753 +1 x3754 +1 x3755 +1 x3756 +1 x3757 +1 x3758 +1 x3759 +1 x3760 +1 x3761 +1 x3762 >= 1;
++1 x3763 +1 x3764 +1 x3765 +1 x3766 +1 x3767 +1 x3768 +1 x3769 +1 x3770 +1 x3771 +1 x3772 +1 x3773 +1 x3774 +1 x3775 +1 x3776 +1 x3777 +1 x3778 +1 x3779 +1 x3780 +1 x3781 +1 x3782 +1 x3783 +1 x3784 +1 x3785 +1 x3786 +1 x3787 +1 x3788 +1 x3789 +1 x3790 +1 x3791 +1 x3792 +1 x3793 +1 x3794 +1 x3795 +1 x3796 +1 x3797 +1 x3798 +1 x3799 +1 x3800 +1 x3801 +1 x3802 +1 x3803 +1 x3804 +1 x3805 +1 x3806 +1 x3807 +1 x3808 +1 x3809 +1 x3810 +1 x3811 +1 x3812 +1 x3813 +1 x3814 +1 x3815 +1 x3816 +1 x3817 +1 x3818 +1 x3819 +1 x3820 +1 x3821 +1 x3822 +1 x3823 +1 x3824 +1 x3825 +1 x3826 +1 x3827 +1 x3828 +1 x3829 +1 x3830 +1 x3831 +1 x3832 +1 x3833 +1 x3834 +1 x3835 +1 x3836 +1 x3837 +1 x3838 +1 x3839 +1 x3840 +1 x3841 +1 x3842 +1 x3843 +1 x3844 +1 x3845 +1 x3846 +1 x3847 +1 x3848 +1 x3849 +1 x3850 +1 x3851 +1 x3852 +1 x3853 +1 x3854 +1 x3855 +1 x3856 +1 x3857 +1 x3858 +1 x3859 +1 x3860 +1 x3861 >= 1;
++1 x3862 +1 x3863 +1 x3864 +1 x3865 +1 x3866 +1 x3867 +1 x3868 +1 x3869 +1 x3870 +1 x3871 +1 x3872 +1 x3873 +1 x3874 +1 x3875 +1 x3876 +1 x3877 +1 x3878 +1 x3879 +1 x3880 +1 x3881 +1 x3882 +1 x3883 +1 x3884 +1 x3885 +1 x3886 +1 x3887 +1 x3888 +1 x3889 +1 x3890 +1 x3891 +1 x3892 +1 x3893 +1 x3894 +1 x3895 +1 x3896 +1 x3897 +1 x3898 +1 x3899 +1 x3900 +1 x3901 +1 x3902 +1 x3903 +1 x3904 +1 x3905 +1 x3906 +1 x3907 +1 x3908 +1 x3909 +1 x3910 +1 x3911 +1 x3912 +1 x3913 +1 x3914 +1 x3915 +1 x3916 +1 x3917 +1 x3918 +1 x3919 +1 x3920 +1 x3921 +1 x3922 +1 x3923 +1 x3924 +1 x3925 +1 x3926 +1 x3927 +1 x3928 +1 x3929 +1 x3930 +1 x3931 +1 x3932 +1 x3933 +1 x3934 +1 x3935 +1 x3936 +1 x3937 +1 x3938 +1 x3939 +1 x3940 +1 x3941 +1 x3942 +1 x3943 +1 x3944 +1 x3945 +1 x3946 +1 x3947 +1 x3948 +1 x3949 +1 x3950 +1 x3951 +1 x3952 +1 x3953 +1 x3954 +1 x3955 +1 x3956 +1 x3957 +1 x3958 +1 x3959 +1 x3960 >= 1;
++1 x3961 +1 x3962 +1 x3963 +1 x3964 +1 x3965 +1 x3966 +1 x3967 +1 x3968 +1 x3969 +1 x3970 +1 x3971 +1 x3972 +1 x3973 +1 x3974 +1 x3975 +1 x3976 +1 x3977 +1 x3978 +1 x3979 +1 x3980 +1 x3981 +1 x3982 +1 x3983 +1 x3984 +1 x3985 +1 x3986 +1 x3987 +1 x3988 +1 x3989 +1 x3990 +1 x3991 +1 x3992 +1 x3993 +1 x3994 +1 x3995 +1 x3996 +1 x3997 +1 x3998 +1 x3999 +1 x4000 +1 x4001 +1 x4002 +1 x4003 +1 x4004 +1 x4005 +1 x4006 +1 x4007 +1 x4008 +1 x4009 +1 x4010 +1 x4011 +1 x4012 +1 x4013 +1 x4014 +1 x4015 +1 x4016 +1 x4017 +1 x4018 +1 x4019 +1 x4020 +1 x4021 +1 x4022 +1 x4023 +1 x4024 +1 x4025 +1 x4026 +1 x4027 +1 x4028 +1 x4029 +1 x4030 +1 x4031 +1 x4032 +1 x4033 +1 x4034 +1 x4035 +1 x4036 +1 x4037 +1 x4038 +1 x4039 +1 x4040 +1 x4041 +1 x4042 +1 x4043 +1 x4044 +1 x4045 +1 x4046 +1 x4047 +1 x4048 +1 x4049 +1 x4050 +1 x4051 +1 x4052 +1 x4053 +1 x4054 +1 x4055 +1 x4056 +1 x4057 +1 x4058 +1 x4059 >= 1;
++1 x4060 +1 x4061 +1 x4062 +1 x4063 +1 x4064 +1 x4065 +1 x4066 +1 x4067 +1 x4068 +1 x4069 +1 x4070 +1 x4071 +1 x4072 +1 x4073 +1 x4074 +1 x4075 +1 x4076 +1 x4077 +1 x4078 +1 x4079 +1 x4080 +1 x4081 +1 x4082 +1 x4083 +1 x4084 +1 x4085 +1 x4086 +1 x4087 +1 x4088 +1 x4089 +1 x4090 +1 x4091 +1 x4092 +1 x4093 +1 x4094 +1 x4095 +1 x4096 +1 x4097 +1 x4098 +1 x4099 +1 x4100 +1 x4101 +1 x4102 +1 x4103 +1 x4104 +1 x4105 +1 x4106 +1 x4107 +1 x4108 +1 x4109 +1 x4110 +1 x4111 +1 x4112 +1 x4113 +1 x4114 +1 x4115 +1 x4116 +1 x4117 +1 x4118 +1 x4119 +1 x4120 +1 x4121 +1 x4122 +1 x4123 +1 x4124 +1 x4125 +1 x4126 +1 x4127 +1 x4128 +1 x4129 +1 x4130 +1 x4131 +1 x4132 +1 x4133 +1 x4134 +1 x4135 +1 x4136 +1 x4137 +1 x4138 +1 x4139 +1 x4140 +1 x4141 +1 x4142 +1 x4143 +1 x4144 +1 x4145 +1 x4146 +1 x4147 +1 x4148 +1 x4149 +1 x4150 +1 x4151 +1 x4152 +1 x4153 +1 x4154 +1 x4155 +1 x4156 +1 x4157 +1 x4158 >= 1;
++1 x4159 +1 x4160 +1 x4161 +1 x4162 +1 x4163 +1 x4164 +1 x4165 +1 x4166 +1 x4167 +1 x4168 +1 x4169 +1 x4170 +1 x4171 +1 x4172 +1 x4173 +1 x4174 +1 x4175 +1 x4176 +1 x4177 +1 x4178 +1 x4179 +1 x4180 +1 x4181 +1 x4182 +1 x4183 +1 x4184 +1 x4185 +1 x4186 +1 x4187 +1 x4188 +1 x4189 +1 x4190 +1 x4191 +1 x4192 +1 x4193 +1 x4194 +1 x4195 +1 x4196 +1 x4197 +1 x4198 +1 x4199 +1 x4200 +1 x4201 +1 x4202 +1 x4203 +1 x4204 +1 x4205 +1 x4206 +1 x4207 +1 x4208 +1 x4209 +1 x4210 +1 x4211 +1 x4212 +1 x4213 +1 x4214 +1 x4215 +1 x4216 +1 x4217 +1 x4218 +1 x4219 +1 x4220 +1 x4221 +1 x4222 +1 x4223 +1 x4224 +1 x4225 +1 x4226 +1 x4227 +1 x4228 +1 x4229 +1 x4230 +1 x4231 +1 x4232 +1 x4233 +1 x4234 +1 x4235 +1 x4236 +1 x4237 +1 x4238 +1 x4239 +1 x4240 +1 x4241 +1 x4242 +1 x4243 +1 x4244 +1 x4245 +1 x4246 +1 x4247 +1 x4248 +1 x4249 +1 x4250 +1 x4251 +1 x4252 +1 x4253 +1 x4254 +1 x4255 +1 x4256 +1 x4257 >= 1;
++1 x4258 +1 x4259 +1 x4260 +1 x4261 +1 x4262 +1 x4263 +1 x4264 +1 x4265 +1 x4266 +1 x4267 +1 x4268 +1 x4269 +1 x4270 +1 x4271 +1 x4272 +1 x4273 +1 x4274 +1 x4275 +1 x4276 +1 x4277 +1 x4278 +1 x4279 +1 x4280 +1 x4281 +1 x4282 +1 x4283 +1 x4284 +1 x4285 +1 x4286 +1 x4287 +1 x4288 +1 x4289 +1 x4290 +1 x4291 +1 x4292 +1 x4293 +1 x4294 +1 x4295 +1 x4296 +1 x4297 +1 x4298 +1 x4299 +1 x4300 +1 x4301 +1 x4302 +1 x4303 +1 x4304 +1 x4305 +1 x4306 +1 x4307 +1 x4308 +1 x4309 +1 x4310 +1 x4311 +1 x4312 +1 x4313 +1 x4314 +1 x4315 +1 x4316 +1 x4317 +1 x4318 +1 x4319 +1 x4320 +1 x4321 +1 x4322 +1 x4323 +1 x4324 +1 x4325 +1 x4326 +1 x4327 +1 x4328 +1 x4329 +1 x4330 +1 x4331 +1 x4332 +1 x4333 +1 x4334 +1 x4335 +1 x4336 +1 x4337 +1 x4338 +1 x4339 +1 x4340 +1 x4341 +1 x4342 +1 x4343 +1 x4344 +1 x4345 +1 x4346 +1 x4347 +1 x4348 +1 x4349 +1 x4350 +1 x4351 +1 x4352 +1 x4353 +1 x4354 +1 x4355 +1 x4356 >= 1;
++1 x4357 +1 x4358 +1 x4359 +1 x4360 +1 x4361 +1 x4362 +1 x4363 +1 x4364 +1 x4365 +1 x4366 +1 x4367 +1 x4368 +1 x4369 +1 x4370 +1 x4371 +1 x4372 +1 x4373 +1 x4374 +1 x4375 +1 x4376 +1 x4377 +1 x4378 +1 x4379 +1 x4380 +1 x4381 +1 x4382 +1 x4383 +1 x4384 +1 x4385 +1 x4386 +1 x4387 +1 x4388 +1 x4389 +1 x4390 +1 x4391 +1 x4392 +1 x4393 +1 x4394 +1 x4395 +1 x4396 +1 x4397 +1 x4398 +1 x4399 +1 x4400 +1 x4401 +1 x4402 +1 x4403 +1 x4404 +1 x4405 +1 x4406 +1 x4407 +1 x4408 +1 x4409 +1 x4410 +1 x4411 +1 x4412 +1 x4413 +1 x4414 +1 x4415 +1 x4416 +1 x4417 +1 x4418 +1 x4419 +1 x4420 +1 x4421 +1 x4422 +1 x4423 +1 x4424 +1 x4425 +1 x4426 +1 x4427 +1 x4428 +1 x4429 +1 x4430 +1 x4431 +1 x4432 +1 x4433 +1 x4434 +1 x4435 +1 x4436 +1 x4437 +1 x4438 +1 x4439 +1 x4440 +1 x4441 +1 x4442 +1 x4443 +1 x4444 +1 x4445 +1 x4446 +1 x4447 +1 x4448 +1 x4449 +1 x4450 +1 x4451 +1 x4452 +1 x4453 +1 x4454 +1 x4455 >= 1;
++1 x4456 +1 x4457 +1 x4458 +1 x4459 +1 x4460 +1 x4461 +1 x4462 +1 x4463 +1 x4464 +1 x4465 +1 x4466 +1 x4467 +1 x4468 +1 x4469 +1 x4470 +1 x4471 +1 x4472 +1 x4473 +1 x4474 +1 x4475 +1 x4476 +1 x4477 +1 x4478 +1 x4479 +1 x4480 +1 x4481 +1 x4482 +1 x4483 +1 x4484 +1 x4485 +1 x4486 +1 x4487 +1 x4488 +1 x4489 +1 x4490 +1 x4491 +1 x4492 +1 x4493 +1 x4494 +1 x4495 +1 x4496 +1 x4497 +1 x4498 +1 x4499 +1 x4500 +1 x4501 +1 x4502 +1 x4503 +1 x4504 +1 x4505 +1 x4506 +1 x4507 +1 x4508 +1 x4509 +1 x4510 +1 x4511 +1 x4512 +1 x4513 +1 x4514 +1 x4515 +1 x4516 +1 x4517 +1 x4518 +1 x4519 +1 x4520 +1 x4521 +1 x4522 +1 x4523 +1 x4524 +1 x4525 +1 x4526 +1 x4527 +1 x4528 +1 x4529 +1 x4530 +1 x4531 +1 x4532 +1 x4533 +1 x4534 +1 x4535 +1 x4536 +1 x4537 +1 x4538 +1 x4539 +1 x4540 +1 x4541 +1 x4542 +1 x4543 +1 x4544 +1 x4545 +1 x4546 +1 x4547 +1 x4548 +1 x4549 +1 x4550 +1 x4551 +1 x4552 +1 x4553 +1 x4554 >= 1;
++1 x4555 +1 x4556 +1 x4557 +1 x4558 +1 x4559 +1 x4560 +1 x4561 +1 x4562 +1 x4563 +1 x4564 +1 x4565 +1 x4566 +1 x4567 +1 x4568 +1 x4569 +1 x4570 +1 x4571 +1 x4572 +1 x4573 +1 x4574 +1 x4575 +1 x4576 +1 x4577 +1 x4578 +1 x4579 +1 x4580 +1 x4581 +1 x4582 +1 x4583 +1 x4584 +1 x4585 +1 x4586 +1 x4587 +1 x4588 +1 x4589 +1 x4590 +1 x4591 +1 x4592 +1 x4593 +1 x4594 +1 x4595 +1 x4596 +1 x4597 +1 x4598 +1 x4599 +1 x4600 +1 x4601 +1 x4602 +1 x4603 +1 x4604 +1 x4605 +1 x4606 +1 x4607 +1 x4608 +1 x4609 +1 x4610 +1 x4611 +1 x4612 +1 x4613 +1 x4614 +1 x4615 +1 x4616 +1 x4617 +1 x4618 +1 x4619 +1 x4620 +1 x4621 +1 x4622 +1 x4623 +1 x4624 +1 x4625 +1 x4626 +1 x4627 +1 x4628 +1 x4629 +1 x4630 +1 x4631 +1 x4632 +1 x4633 +1 x4634 +1 x4635 +1 x4636 +1 x4637 +1 x4638 +1 x4639 +1 x4640 +1 x4641 +1 x4642 +1 x4643 +1 x4644 +1 x4645 +1 x4646 +1 x4647 +1 x4648 +1 x4649 +1 x4650 +1 x4651 +1 x4652 +1 x4653 >= 1;
++1 x4654 +1 x4655 +1 x4656 +1 x4657 +1 x4658 +1 x4659 +1 x4660 +1 x4661 +1 x4662 +1 x4663 +1 x4664 +1 x4665 +1 x4666 +1 x4667 +1 x4668 +1 x4669 +1 x4670 +1 x4671 +1 x4672 +1 x4673 +1 x4674 +1 x4675 +1 x4676 +1 x4677 +1 x4678 +1 x4679 +1 x4680 +1 x4681 +1 x4682 +1 x4683 +1 x4684 +1 x4685 +1 x4686 +1 x4687 +1 x4688 +1 x4689 +1 x4690 +1 x4691 +1 x4692 +1 x4693 +1 x4694 +1 x4695 +1 x4696 +1 x4697 +1 x4698 +1 x4699 +1 x4700 +1 x4701 +1 x4702 +1 x4703 +1 x4704 +1 x4705 +1 x4706 +1 x4707 +1 x4708 +1 x4709 +1 x4710 +1 x4711 +1 x4712 +1 x4713 +1 x4714 +1 x4715 +1 x4716 +1 x4717 +1 x4718 +1 x4719 +1 x4720 +1 x4721 +1 x4722 +1 x4723 +1 x4724 +1 x4725 +1 x4726 +1 x4727 +1 x4728 +1 x4729 +1 x4730 +1 x4731 +1 x4732 +1 x4733 +1 x4734 +1 x4735 +1 x4736 +1 x4737 +1 x4738 +1 x4739 +1 x4740 +1 x4741 +1 x4742 +1 x4743 +1 x4744 +1 x4745 +1 x4746 +1 x4747 +1 x4748 +1 x4749 +1 x4750 +1 x4751 +1 x4752 >= 1;
++1 x4753 +1 x4754 +1 x4755 +1 x4756 +1 x4757 +1 x4758 +1 x4759 +1 x4760 +1 x4761 +1 x4762 +1 x4763 +1 x4764 +1 x4765 +1 x4766 +1 x4767 +1 x4768 +1 x4769 +1 x4770 +1 x4771 +1 x4772 +1 x4773 +1 x4774 +1 x4775 +1 x4776 +1 x4777 +1 x4778 +1 x4779 +1 x4780 +1 x4781 +1 x4782 +1 x4783 +1 x4784 +1 x4785 +1 x4786 +1 x4787 +1 x4788 +1 x4789 +1 x4790 +1 x4791 +1 x4792 +1 x4793 +1 x4794 +1 x4795 +1 x4796 +1 x4797 +1 x4798 +1 x4799 +1 x4800 +1 x4801 +1 x4802 +1 x4803 +1 x4804 +1 x4805 +1 x4806 +1 x4807 +1 x4808 +1 x4809 +1 x4810 +1 x4811 +1 x4812 +1 x4813 +1 x4814 +1 x4815 +1 x4816 +1 x4817 +1 x4818 +1 x4819 +1 x4820 +1 x4821 +1 x4822 +1 x4823 +1 x4824 +1 x4825 +1 x4826 +1 x4827 +1 x4828 +1 x4829 +1 x4830 +1 x4831 +1 x4832 +1 x4833 +1 x4834 +1 x4835 +1 x4836 +1 x4837 +1 x4838 +1 x4839 +1 x4840 +1 x4841 +1 x4842 +1 x4843 +1 x4844 +1 x4845 +1 x4846 +1 x4847 +1 x4848 +1 x4849 +1 x4850 +1 x4851 >= 1;
++1 x4852 +1 x4853 +1 x4854 +1 x4855 +1 x4856 +1 x4857 +1 x4858 +1 x4859 +1 x4860 +1 x4861 +1 x4862 +1 x4863 +1 x4864 +1 x4865 +1 x4866 +1 x4867 +1 x4868 +1 x4869 +1 x4870 +1 x4871 +1 x4872 +1 x4873 +1 x4874 +1 x4875 +1 x4876 +1 x4877 +1 x4878 +1 x4879 +1 x4880 +1 x4881 +1 x4882 +1 x4883 +1 x4884 +1 x4885 +1 x4886 +1 x4887 +1 x4888 +1 x4889 +1 x4890 +1 x4891 +1 x4892 +1 x4893 +1 x4894 +1 x4895 +1 x4896 +1 x4897 +1 x4898 +1 x4899 +1 x4900 +1 x4901 +1 x4902 +1 x4903 +1 x4904 +1 x4905 +1 x4906 +1 x4907 +1 x4908 +1 x4909 +1 x4910 +1 x4911 +1 x4912 +1 x4913 +1 x4914 +1 x4915 +1 x4916 +1 x4917 +1 x4918 +1 x4919 +1 x4920 +1 x4921 +1 x4922 +1 x4923 +1 x4924 +1 x4925 +1 x4926 +1 x4927 +1 x4928 +1 x4929 +1 x4930 +1 x4931 +1 x4932 +1 x4933 +1 x4934 +1 x4935 +1 x4936 +1 x4937 +1 x4938 +1 x4939 +1 x4940 +1 x4941 +1 x4942 +1 x4943 +1 x4944 +1 x4945 +1 x4946 +1 x4947 +1 x4948 +1 x4949 +1 x4950 >= 1;
++1 x4951 +1 x4952 +1 x4953 +1 x4954 +1 x4955 +1 x4956 +1 x4957 +1 x4958 +1 x4959 +1 x4960 +1 x4961 +1 x4962 +1 x4963 +1 x4964 +1 x4965 +1 x4966 +1 x4967 +1 x4968 +1 x4969 +1 x4970 +1 x4971 +1 x4972 +1 x4973 +1 x4974 +1 x4975 +1 x4976 +1 x4977 +1 x4978 +1 x4979 +1 x4980 +1 x4981 +1 x4982 +1 x4983 +1 x4984 +1 x4985 +1 x4986 +1 x4987 +1 x4988 +1 x4989 +1 x4990 +1 x4991 +1 x4992 +1 x4993 +1 x4994 +1 x4995 +1 x4996 +1 x4997 +1 x4998 +1 x4999 +1 x5000 +1 x5001 +1 x5002 +1 x5003 +1 x5004 +1 x5005 +1 x5006 +1 x5007 +1 x5008 +1 x5009 +1 x5010 +1 x5011 +1 x5012 +1 x5013 +1 x5014 +1 x5015 +1 x5016 +1 x5017 +1 x5018 +1 x5019 +1 x5020 +1 x5021 +1 x5022 +1 x5023 +1 x5024 +1 x5025 +1 x5026 +1 x5027 +1 x5028 +1 x5029 +1 x5030 +1 x5031 +1 x5032 +1 x5033 +1 x5034 +1 x5035 +1 x5036 +1 x5037 +1 x5038 +1 x5039 +1 x5040 +1 x5041 +1 x5042 +1 x5043 +1 x5044 +1 x5045 +1 x5046 +1 x5047 +1 x5048 +1 x5049 >= 1;
++1 x5050 +1 x5051 +1 x5052 +1 x5053 +1 x5054 +1 x5055 +1 x5056 +1 x5057 +1 x5058 +1 x5059 +1 x5060 +1 x5061 +1 x5062 +1 x5063 +1 x5064 +1 x5065 +1 x5066 +1 x5067 +1 x5068 +1 x5069 +1 x5070 +1 x5071 +1 x5072 +1 x5073 +1 x5074 +1 x5075 +1 x5076 +1 x5077 +1 x5078 +1 x5079 +1 x5080 +1 x5081 +1 x5082 +1 x5083 +1 x5084 +1 x5085 +1 x5086 +1 x5087 +1 x5088 +1 x5089 +1 x5090 +1 x5091 +1 x5092 +1 x5093 +1 x5094 +1 x5095 +1 x5096 +1 x5097 +1 x5098 +1 x5099 +1 x5100 +1 x5101 +1 x5102 +1 x5103 +1 x5104 +1 x5105 +1 x5106 +1 x5107 +1 x5108 +1 x5109 +1 x5110 +1 x5111 +1 x5112 +1 x5113 +1 x5114 +1 x5115 +1 x5116 +1 x5117 +1 x5118 +1 x5119 +1 x5120 +1 x5121 +1 x5122 +1 x5123 +1 x5124 +1 x5125 +1 x5126 +1 x5127 +1 x5128 +1 x5129 +1 x5130 +1 x5131 +1 x5132 +1 x5133 +1 x5134 +1 x5135 +1 x5136 +1 x5137 +1 x5138 +1 x5139 +1 x5140 +1 x5141 +1 x5142 +1 x5143 +1 x5144 +1 x5145 +1 x5146 +1 x5147 +1 x5148 >= 1;
++1 x5149 +1 x5150 +1 x5151 +1 x5152 +1 x5153 +1 x5154 +1 x5155 +1 x5156 +1 x5157 +1 x5158 +1 x5159 +1 x5160 +1 x5161 +1 x5162 +1 x5163 +1 x5164 +1 x5165 +1 x5166 +1 x5167 +1 x5168 +1 x5169 +1 x5170 +1 x5171 +1 x5172 +1 x5173 +1 x5174 +1 x5175 +1 x5176 +1 x5177 +1 x5178 +1 x5179 +1 x5180 +1 x5181 +1 x5182 +1 x5183 +1 x5184 +1 x5185 +1 x5186 +1 x5187 +1 x5188 +1 x5189 +1 x5190 +1 x5191 +1 x5192 +1 x5193 +1 x5194 +1 x5195 +1 x5196 +1 x5197 +1 x5198 +1 x5199 +1 x5200 +1 x5201 +1 x5202 +1 x5203 +1 x5204 +1 x5205 +1 x5206 +1 x5207 +1 x5208 +1 x5209 +1 x5210 +1 x5211 +1 x5212 +1 x5213 +1 x5214 +1 x5215 +1 x5216 +1 x5217 +1 x5218 +1 x5219 +1 x5220 +1 x5221 +1 x5222 +1 x5223 +1 x5224 +1 x5225 +1 x5226 +1 x5227 +1 x5228 +1 x5229 +1 x5230 +1 x5231 +1 x5232 +1 x5233 +1 x5234 +1 x5235 +1 x5236 +1 x5237 +1 x5238 +1 x5239 +1 x5240 +1 x5241 +1 x5242 +1 x5243 +1 x5244 +1 x5245 +1 x5246 +1 x5247 >= 1;
++1 x5248 +1 x5249 +1 x5250 +1 x5251 +1 x5252 +1 x5253 +1 x5254 +1 x5255 +1 x5256 +1 x5257 +1 x5258 +1 x5259 +1 x5260 +1 x5261 +1 x5262 +1 x5263 +1 x5264 +1 x5265 +1 x5266 +1 x5267 +1 x5268 +1 x5269 +1 x5270 +1 x5271 +1 x5272 +1 x5273 +1 x5274 +1 x5275 +1 x5276 +1 x5277 +1 x5278 +1 x5279 +1 x5280 +1 x5281 +1 x5282 +1 x5283 +1 x5284 +1 x5285 +1 x5286 +1 x5287 +1 x5288 +1 x5289 +1 x5290 +1 x5291 +1 x5292 +1 x5293 +1 x5294 +1 x5295 +1 x5296 +1 x5297 +1 x5298 +1 x5299 +1 x5300 +1 x5301 +1 x5302 +1 x5303 +1 x5304 +1 x5305 +1 x5306 +1 x5307 +1 x5308 +1 x5309 +1 x5310 +1 x5311 +1 x5312 +1 x5313 +1 x5314 +1 x5315 +1 x5316 +1 x5317 +1 x5318 +1 x5319 +1 x5320 +1 x5321 +1 x5322 +1 x5323 +1 x5324 +1 x5325 +1 x5326 +1 x5327 +1 x5328 +1 x5329 +1 x5330 +1 x5331 +1 x5332 +1 x5333 +1 x5334 +1 x5335 +1 x5336 +1 x5337 +1 x5338 +1 x5339 +1 x5340 +1 x5341 +1 x5342 +1 x5343 +1 x5344 +1 x5345 +1 x5346 >= 1;
++1 x5347 +1 x5348 +1 x5349 +1 x5350 +1 x5351 +1 x5352 +1 x5353 +1 x5354 +1 x5355 +1 x5356 +1 x5357 +1 x5358 +1 x5359 +1 x5360 +1 x5361 +1 x5362 +1 x5363 +1 x5364 +1 x5365 +1 x5366 +1 x5367 +1 x5368 +1 x5369 +1 x5370 +1 x5371 +1 x5372 +1 x5373 +1 x5374 +1 x5375 +1 x5376 +1 x5377 +1 x5378 +1 x5379 +1 x5380 +1 x5381 +1 x5382 +1 x5383 +1 x5384 +1 x5385 +1 x5386 +1 x5387 +1 x5388 +1 x5389 +1 x5390 +1 x5391 +1 x5392 +1 x5393 +1 x5394 +1 x5395 +1 x5396 +1 x5397 +1 x5398 +1 x5399 +1 x5400 +1 x5401 +1 x5402 +1 x5403 +1 x5404 +1 x5405 +1 x5406 +1 x5407 +1 x5408 +1 x5409 +1 x5410 +1 x5411 +1 x5412 +1 x5413 +1 x5414 +1 x5415 +1 x5416 +1 x5417 +1 x5418 +1 x5419 +1 x5420 +1 x5421 +1 x5422 +1 x5423 +1 x5424 +1 x5425 +1 x5426 +1 x5427 +1 x5428 +1 x5429 +1 x5430 +1 x5431 +1 x5432 +1 x5433 +1 x5434 +1 x5435 +1 x5436 +1 x5437 +1 x5438 +1 x5439 +1 x5440 +1 x5441 +1 x5442 +1 x5443 +1 x5444 +1 x5445 >= 1;
++1 x5446 +1 x5447 +1 x5448 +1 x5449 +1 x5450 +1 x5451 +1 x5452 +1 x5453 +1 x5454 +1 x5455 +1 x5456 +1 x5457 +1 x5458 +1 x5459 +1 x5460 +1 x5461 +1 x5462 +1 x5463 +1 x5464 +1 x5465 +1 x5466 +1 x5467 +1 x5468 +1 x5469 +1 x5470 +1 x5471 +1 x5472 +1 x5473 +1 x5474 +1 x5475 +1 x5476 +1 x5477 +1 x5478 +1 x5479 +1 x5480 +1 x5481 +1 x5482 +1 x5483 +1 x5484 +1 x5485 +1 x5486 +1 x5487 +1 x5488 +1 x5489 +1 x5490 +1 x5491 +1 x5492 +1 x5493 +1 x5494 +1 x5495 +1 x5496 +1 x5497 +1 x5498 +1 x5499 +1 x5500 +1 x5501 +1 x5502 +1 x5503 +1 x5504 +1 x5505 +1 x5506 +1 x5507 +1 x5508 +1 x5509 +1 x5510 +1 x5511 +1 x5512 +1 x5513 +1 x5514 +1 x5515 +1 x5516 +1 x5517 +1 x5518 +1 x5519 +1 x5520 +1 x5521 +1 x5522 +1 x5523 +1 x5524 +1 x5525 +1 x5526 +1 x5527 +1 x5528 +1 x5529 +1 x5530 +1 x5531 +1 x5532 +1 x5533 +1 x5534 +1 x5535 +1 x5536 +1 x5537 +1 x5538 +1 x5539 +1 x5540 +1 x5541 +1 x5542 +1 x5543 +1 x5544 >= 1;
++1 x5545 +1 x5546 +1 x5547 +1 x5548 +1 x5549 +1 x5550 +1 x5551 +1 x5552 +1 x5553 +1 x5554 +1 x5555 +1 x5556 +1 x5557 +1 x5558 +1 x5559 +1 x5560 +1 x5561 +1 x5562 +1 x5563 +1 x5564 +1 x5565 +1 x5566 +1 x5567 +1 x5568 +1 x5569 +1 x5570 +1 x5571 +1 x5572 +1 x5573 +1 x5574 +1 x5575 +1 x5576 +1 x5577 +1 x5578 +1 x5579 +1 x5580 +1 x5581 +1 x5582 +1 x5583 +1 x5584 +1 x5585 +1 x5586 +1 x5587 +1 x5588 +1 x5589 +1 x5590 +1 x5591 +1 x5592 +1 x5593 +1 x5594 +1 x5595 +1 x5596 +1 x5597 +1 x5598 +1 x5599 +1 x5600 +1 x5601 +1 x5602 +1 x5603 +1 x5604 +1 x5605 +1 x5606 +1 x5607 +1 x5608 +1 x5609 +1 x5610 +1 x5611 +1 x5612 +1 x5613 +1 x5614 +1 x5615 +1 x5616 +1 x5617 +1 x5618 +1 x5619 +1 x5620 +1 x5621 +1 x5622 +1 x5623 +1 x5624 +1 x5625 +1 x5626 +1 x5627 +1 x5628 +1 x5629 +1 x5630 +1 x5631 +1 x5632 +1 x5633 +1 x5634 +1 x5635 +1 x5636 +1 x5637 +1 x5638 +1 x5639 +1 x5640 +1 x5641 +1 x5642 +1 x5643 >= 1;
++1 x5644 +1 x5645 +1 x5646 +1 x5647 +1 x5648 +1 x5649 +1 x5650 +1 x5651 +1 x5652 +1 x5653 +1 x5654 +1 x5655 +1 x5656 +1 x5657 +1 x5658 +1 x5659 +1 x5660 +1 x5661 +1 x5662 +1 x5663 +1 x5664 +1 x5665 +1 x5666 +1 x5667 +1 x5668 +1 x5669 +1 x5670 +1 x5671 +1 x5672 +1 x5673 +1 x5674 +1 x5675 +1 x5676 +1 x5677 +1 x5678 +1 x5679 +1 x5680 +1 x5681 +1 x5682 +1 x5683 +1 x5684 +1 x5685 +1 x5686 +1 x5687 +1 x5688 +1 x5689 +1 x5690 +1 x5691 +1 x5692 +1 x5693 +1 x5694 +1 x5695 +1 x5696 +1 x5697 +1 x5698 +1 x5699 +1 x5700 +1 x5701 +1 x5702 +1 x5703 +1 x5704 +1 x5705 +1 x5706 +1 x5707 +1 x5708 +1 x5709 +1 x5710 +1 x5711 +1 x5712 +1 x5713 +1 x5714 +1 x5715 +1 x5716 +1 x5717 +1 x5718 +1 x5719 +1 x5720 +1 x5721 +1 x5722 +1 x5723 +1 x5724 +1 x5725 +1 x5726 +1 x5727 +1 x5728 +1 x5729 +1 x5730 +1 x5731 +1 x5732 +1 x5733 +1 x5734 +1 x5735 +1 x5736 +1 x5737 +1 x5738 +1 x5739 +1 x5740 +1 x5741 +1 x5742 >= 1;
++1 x5743 +1 x5744 +1 x5745 +1 x5746 +1 x5747 +1 x5748 +1 x5749 +1 x5750 +1 x5751 +1 x5752 +1 x5753 +1 x5754 +1 x5755 +1 x5756 +1 x5757 +1 x5758 +1 x5759 +1 x5760 +1 x5761 +1 x5762 +1 x5763 +1 x5764 +1 x5765 +1 x5766 +1 x5767 +1 x5768 +1 x5769 +1 x5770 +1 x5771 +1 x5772 +1 x5773 +1 x5774 +1 x5775 +1 x5776 +1 x5777 +1 x5778 +1 x5779 +1 x5780 +1 x5781 +1 x5782 +1 x5783 +1 x5784 +1 x5785 +1 x5786 +1 x5787 +1 x5788 +1 x5789 +1 x5790 +1 x5791 +1 x5792 +1 x5793 +1 x5794 +1 x5795 +1 x5796 +1 x5797 +1 x5798 +1 x5799 +1 x5800 +1 x5801 +1 x5802 +1 x5803 +1 x5804 +1 x5805 +1 x5806 +1 x5807 +1 x5808 +1 x5809 +1 x5810 +1 x5811 +1 x5812 +1 x5813 +1 x5814 +1 x5815 +1 x5816 +1 x5817 +1 x5818 +1 x5819 +1 x5820 +1 x5821 +1 x5822 +1 x5823 +1 x5824 +1 x5825 +1 x5826 +1 x5827 +1 x5828 +1 x5829 +1 x5830 +1 x5831 +1 x5832 +1 x5833 +1 x5834 +1 x5835 +1 x5836 +1 x5837 +1 x5838 +1 x5839 +1 x5840 +1 x5841 >= 1;
++1 x5842 +1 x5843 +1 x5844 +1 x5845 +1 x5846 +1 x5847 +1 x5848 +1 x5849 +1 x5850 +1 x5851 +1 x5852 +1 x5853 +1 x5854 +1 x5855 +1 x5856 +1 x5857 +1 x5858 +1 x5859 +1 x5860 +1 x5861 +1 x5862 +1 x5863 +1 x5864 +1 x5865 +1 x5866 +1 x5867 +1 x5868 +1 x5869 +1 x5870 +1 x5871 +1 x5872 +1 x5873 +1 x5874 +1 x5875 +1 x5876 +1 x5877 +1 x5878 +1 x5879 +1 x5880 +1 x5881 +1 x5882 +1 x5883 +1 x5884 +1 x5885 +1 x5886 +1 x5887 +1 x5888 +1 x5889 +1 x5890 +1 x5891 +1 x5892 +1 x5893 +1 x5894 +1 x5895 +1 x5896 +1 x5897 +1 x5898 +1 x5899 +1 x5900 +1 x5901 +1 x5902 +1 x5903 +1 x5904 +1 x5905 +1 x5906 +1 x5907 +1 x5908 +1 x5909 +1 x5910 +1 x5911 +1 x5912 +1 x5913 +1 x5914 +1 x5915 +1 x5916 +1 x5917 +1 x5918 +1 x5919 +1 x5920 +1 x5921 +1 x5922 +1 x5923 +1 x5924 +1 x5925 +1 x5926 +1 x5927 +1 x5928 +1 x5929 +1 x5930 +1 x5931 +1 x5932 +1 x5933 +1 x5934 +1 x5935 +1 x5936 +1 x5937 +1 x5938 +1 x5939 +1 x5940 >= 1;
++1 x5941 +1 x5942 +1 x5943 +1 x5944 +1 x5945 +1 x5946 +1 x5947 +1 x5948 +1 x5949 +1 x5950 +1 x5951 +1 x5952 +1 x5953 +1 x5954 +1 x5955 +1 x5956 +1 x5957 +1 x5958 +1 x5959 +1 x5960 +1 x5961 +1 x5962 +1 x5963 +1 x5964 +1 x5965 +1 x5966 +1 x5967 +1 x5968 +1 x5969 +1 x5970 +1 x5971 +1 x5972 +1 x5973 +1 x5974 +1 x5975 +1 x5976 +1 x5977 +1 x5978 +1 x5979 +1 x5980 +1 x5981 +1 x5982 +1 x5983 +1 x5984 +1 x5985 +1 x5986 +1 x5987 +1 x5988 +1 x5989 +1 x5990 +1 x5991 +1 x5992 +1 x5993 +1 x5994 +1 x5995 +1 x5996 +1 x5997 +1 x5998 +1 x5999 +1 x6000 +1 x6001 +1 x6002 +1 x6003 +1 x6004 +1 x6005 +1 x6006 +1 x6007 +1 x6008 +1 x6009 +1 x6010 +1 x6011 +1 x6012 +1 x6013 +1 x6014 +1 x6015 +1 x6016 +1 x6017 +1 x6018 +1 x6019 +1 x6020 +1 x6021 +1 x6022 +1 x6023 +1 x6024 +1 x6025 +1 x6026 +1 x6027 +1 x6028 +1 x6029 +1 x6030 +1 x6031 +1 x6032 +1 x6033 +1 x6034 +1 x6035 +1 x6036 +1 x6037 +1 x6038 +1 x6039 >= 1;
++1 x6040 +1 x6041 +1 x6042 +1 x6043 +1 x6044 +1 x6045 +1 x6046 +1 x6047 +1 x6048 +1 x6049 +1 x6050 +1 x6051 +1 x6052 +1 x6053 +1 x6054 +1 x6055 +1 x6056 +1 x6057 +1 x6058 +1 x6059 +1 x6060 +1 x6061 +1 x6062 +1 x6063 +1 x6064 +1 x6065 +1 x6066 +1 x6067 +1 x6068 +1 x6069 +1 x6070 +1 x6071 +1 x6072 +1 x6073 +1 x6074 +1 x6075 +1 x6076 +1 x6077 +1 x6078 +1 x6079 +1 x6080 +1 x6081 +1 x6082 +1 x6083 +1 x6084 +1 x6085 +1 x6086 +1 x6087 +1 x6088 +1 x6089 +1 x6090 +1 x6091 +1 x6092 +1 x6093 +1 x6094 +1 x6095 +1 x6096 +1 x6097 +1 x6098 +1 x6099 +1 x6100 +1 x6101 +1 x6102 +1 x6103 +1 x6104 +1 x6105 +1 x6106 +1 x6107 +1 x6108 +1 x6109 +1 x6110 +1 x6111 +1 x6112 +1 x6113 +1 x6114 +1 x6115 +1 x6116 +1 x6117 +1 x6118 +1 x6119 +1 x6120 +1 x6121 +1 x6122 +1 x6123 +1 x6124 +1 x6125 +1 x6126 +1 x6127 +1 x6128 +1 x6129 +1 x6130 +1 x6131 +1 x6132 +1 x6133 +1 x6134 +1 x6135 +1 x6136 +1 x6137 +1 x6138 >= 1;
++1 x6139 +1 x6140 +1 x6141 +1 x6142 +1 x6143 +1 x6144 +1 x6145 +1 x6146 +1 x6147 +1 x6148 +1 x6149 +1 x6150 +1 x6151 +1 x6152 +1 x6153 +1 x6154 +1 x6155 +1 x6156 +1 x6157 +1 x6158 +1 x6159 +1 x6160 +1 x6161 +1 x6162 +1 x6163 +1 x6164 +1 x6165 +1 x6166 +1 x6167 +1 x6168 +1 x6169 +1 x6170 +1 x6171 +1 x6172 +1 x6173 +1 x6174 +1 x6175 +1 x6176 +1 x6177 +1 x6178 +1 x6179 +1 x6180 +1 x6181 +1 x6182 +1 x6183 +1 x6184 +1 x6185 +1 x6186 +1 x6187 +1 x6188 +1 x6189 +1 x6190 +1 x6191 +1 x6192 +1 x6193 +1 x6194 +1 x6195 +1 x6196 +1 x6197 +1 x6198 +1 x6199 +1 x6200 +1 x6201 +1 x6202 +1 x6203 +1 x6204 +1 x6205 +1 x6206 +1 x6207 +1 x6208 +1 x6209 +1 x6210 +1 x6211 +1 x6212 +1 x6213 +1 x6214 +1 x6215 +1 x6216 +1 x6217 +1 x6218 +1 x6219 +1 x6220 +1 x6221 +1 x6222 +1 x6223 +1 x6224 +1 x6225 +1 x6226 +1 x6227 +1 x6228 +1 x6229 +1 x6230 +1 x6231 +1 x6232 +1 x6233 +1 x6234 +1 x6235 +1 x6236 +1 x6237 >= 1;
++1 x6238 +1 x6239 +1 x6240 +1 x6241 +1 x6242 +1 x6243 +1 x6244 +1 x6245 +1 x6246 +1 x6247 +1 x6248 +1 x6249 +1 x6250 +1 x6251 +1 x6252 +1 x6253 +1 x6254 +1 x6255 +1 x6256 +1 x6257 +1 x6258 +1 x6259 +1 x6260 +1 x6261 +1 x6262 +1 x6263 +1 x6264 +1 x6265 +1 x6266 +1 x6267 +1 x6268 +1 x6269 +1 x6270 +1 x6271 +1 x6272 +1 x6273 +1 x6274 +1 x6275 +1 x6276 +1 x6277 +1 x6278 +1 x6279 +1 x6280 +1 x6281 +1 x6282 +1 x6283 +1 x6284 +1 x6285 +1 x6286 +1 x6287 +1 x6288 +1 x6289 +1 x6290 +1 x6291 +1 x6292 +1 x6293 +1 x6294 +1 x6295 +1 x6296 +1 x6297 +1 x6298 +1 x6299 +1 x6300 +1 x6301 +1 x6302 +1 x6303 +1 x6304 +1 x6305 +1 x6306 +1 x6307 +1 x6308 +1 x6309 +1 x6310 +1 x6311 +1 x6312 +1 x6313 +1 x6314 +1 x6315 +1 x6316 +1 x6317 +1 x6318 +1 x6319 +1 x6320 +1 x6321 +1 x6322 +1 x6323 +1 x6324 +1 x6325 +1 x6326 +1 x6327 +1 x6328 +1 x6329 +1 x6330 +1 x6331 +1 x6332 +1 x6333 +1 x6334 +1 x6335 +1 x6336 >= 1;
++1 x6337 +1 x6338 +1 x6339 +1 x6340 +1 x6341 +1 x6342 +1 x6343 +1 x6344 +1 x6345 +1 x6346 +1 x6347 +1 x6348 +1 x6349 +1 x6350 +1 x6351 +1 x6352 +1 x6353 +1 x6354 +1 x6355 +1 x6356 +1 x6357 +1 x6358 +1 x6359 +1 x6360 +1 x6361 +1 x6362 +1 x6363 +1 x6364 +1 x6365 +1 x6366 +1 x6367 +1 x6368 +1 x6369 +1 x6370 +1 x6371 +1 x6372 +1 x6373 +1 x6374 +1 x6375 +1 x6376 +1 x6377 +1 x6378 +1 x6379 +1 x6380 +1 x6381 +1 x6382 +1 x6383 +1 x6384 +1 x6385 +1 x6386 +1 x6387 +1 x6388 +1 x6389 +1 x6390 +1 x6391 +1 x6392 +1 x6393 +1 x6394 +1 x6395 +1 x6396 +1 x6397 +1 x6398 +1 x6399 +1 x6400 +1 x6401 +1 x6402 +1 x6403 +1 x6404 +1 x6405 +1 x6406 +1 x6407 +1 x6408 +1 x6409 +1 x6410 +1 x6411 +1 x6412 +1 x6413 +1 x6414 +1 x6415 +1 x6416 +1 x6417 +1 x6418 +1 x6419 +1 x6420 +1 x6421 +1 x6422 +1 x6423 +1 x6424 +1 x6425 +1 x6426 +1 x6427 +1 x6428 +1 x6429 +1 x6430 +1 x6431 +1 x6432 +1 x6433 +1 x6434 +1 x6435 >= 1;
++1 x6436 +1 x6437 +1 x6438 +1 x6439 +1 x6440 +1 x6441 +1 x6442 +1 x6443 +1 x6444 +1 x6445 +1 x6446 +1 x6447 +1 x6448 +1 x6449 +1 x6450 +1 x6451 +1 x6452 +1 x6453 +1 x6454 +1 x6455 +1 x6456 +1 x6457 +1 x6458 +1 x6459 +1 x6460 +1 x6461 +1 x6462 +1 x6463 +1 x6464 +1 x6465 +1 x6466 +1 x6467 +1 x6468 +1 x6469 +1 x6470 +1 x6471 +1 x6472 +1 x6473 +1 x6474 +1 x6475 +1 x6476 +1 x6477 +1 x6478 +1 x6479 +1 x6480 +1 x6481 +1 x6482 +1 x6483 +1 x6484 +1 x6485 +1 x6486 +1 x6487 +1 x6488 +1 x6489 +1 x6490 +1 x6491 +1 x6492 +1 x6493 +1 x6494 +1 x6495 +1 x6496 +1 x6497 +1 x6498 +1 x6499 +1 x6500 +1 x6501 +1 x6502 +1 x6503 +1 x6504 +1 x6505 +1 x6506 +1 x6507 +1 x6508 +1 x6509 +1 x6510 +1 x6511 +1 x6512 +1 x6513 +1 x6514 +1 x6515 +1 x6516 +1 x6517 +1 x6518 +1 x6519 +1 x6520 +1 x6521 +1 x6522 +1 x6523 +1 x6524 +1 x6525 +1 x6526 +1 x6527 +1 x6528 +1 x6529 +1 x6530 +1 x6531 +1 x6532 +1 x6533 +1 x6534 >= 1;
++1 x6535 +1 x6536 +1 x6537 +1 x6538 +1 x6539 +1 x6540 +1 x6541 +1 x6542 +1 x6543 +1 x6544 +1 x6545 +1 x6546 +1 x6547 +1 x6548 +1 x6549 +1 x6550 +1 x6551 +1 x6552 +1 x6553 +1 x6554 +1 x6555 +1 x6556 +1 x6557 +1 x6558 +1 x6559 +1 x6560 +1 x6561 +1 x6562 +1 x6563 +1 x6564 +1 x6565 +1 x6566 +1 x6567 +1 x6568 +1 x6569 +1 x6570 +1 x6571 +1 x6572 +1 x6573 +1 x6574 +1 x6575 +1 x6576 +1 x6577 +1 x6578 +1 x6579 +1 x6580 +1 x6581 +1 x6582 +1 x6583 +1 x6584 +1 x6585 +1 x6586 +1 x6587 +1 x6588 +1 x6589 +1 x6590 +1 x6591 +1 x6592 +1 x6593 +1 x6594 +1 x6595 +1 x6596 +1 x6597 +1 x6598 +1 x6599 +1 x6600 +1 x6601 +1 x6602 +1 x6603 +1 x6604 +1 x6605 +1 x6606 +1 x6607 +1 x6608 +1 x6609 +1 x6610 +1 x6611 +1 x6612 +1 x6613 +1 x6614 +1 x6615 +1 x6616 +1 x6617 +1 x6618 +1 x6619 +1 x6620 +1 x6621 +1 x6622 +1 x6623 +1 x6624 +1 x6625 +1 x6626 +1 x6627 +1 x6628 +1 x6629 +1 x6630 +1 x6631 +1 x6632 +1 x6633 >= 1;
++1 x6634 +1 x6635 +1 x6636 +1 x6637 +1 x6638 +1 x6639 +1 x6640 +1 x6641 +1 x6642 +1 x6643 +1 x6644 +1 x6645 +1 x6646 +1 x6647 +1 x6648 +1 x6649 +1 x6650 +1 x6651 +1 x6652 +1 x6653 +1 x6654 +1 x6655 +1 x6656 +1 x6657 +1 x6658 +1 x6659 +1 x6660 +1 x6661 +1 x6662 +1 x6663 +1 x6664 +1 x6665 +1 x6666 +1 x6667 +1 x6668 +1 x6669 +1 x6670 +1 x6671 +1 x6672 +1 x6673 +1 x6674 +1 x6675 +1 x6676 +1 x6677 +1 x6678 +1 x6679 +1 x6680 +1 x6681 +1 x6682 +1 x6683 +1 x6684 +1 x6685 +1 x6686 +1 x6687 +1 x6688 +1 x6689 +1 x6690 +1 x6691 +1 x6692 +1 x6693 +1 x6694 +1 x6695 +1 x6696 +1 x6697 +1 x6698 +1 x6699 +1 x6700 +1 x6701 +1 x6702 +1 x6703 +1 x6704 +1 x6705 +1 x6706 +1 x6707 +1 x6708 +1 x6709 +1 x6710 +1 x6711 +1 x6712 +1 x6713 +1 x6714 +1 x6715 +1 x6716 +1 x6717 +1 x6718 +1 x6719 +1 x6720 +1 x6721 +1 x6722 +1 x6723 +1 x6724 +1 x6725 +1 x6726 +1 x6727 +1 x6728 +1 x6729 +1 x6730 +1 x6731 +1 x6732 >= 1;
++1 x6733 +1 x6734 +1 x6735 +1 x6736 +1 x6737 +1 x6738 +1 x6739 +1 x6740 +1 x6741 +1 x6742 +1 x6743 +1 x6744 +1 x6745 +1 x6746 +1 x6747 +1 x6748 +1 x6749 +1 x6750 +1 x6751 +1 x6752 +1 x6753 +1 x6754 +1 x6755 +1 x6756 +1 x6757 +1 x6758 +1 x6759 +1 x6760 +1 x6761 +1 x6762 +1 x6763 +1 x6764 +1 x6765 +1 x6766 +1 x6767 +1 x6768 +1 x6769 +1 x6770 +1 x6771 +1 x6772 +1 x6773 +1 x6774 +1 x6775 +1 x6776 +1 x6777 +1 x6778 +1 x6779 +1 x6780 +1 x6781 +1 x6782 +1 x6783 +1 x6784 +1 x6785 +1 x6786 +1 x6787 +1 x6788 +1 x6789 +1 x6790 +1 x6791 +1 x6792 +1 x6793 +1 x6794 +1 x6795 +1 x6796 +1 x6797 +1 x6798 +1 x6799 +1 x6800 +1 x6801 +1 x6802 +1 x6803 +1 x6804 +1 x6805 +1 x6806 +1 x6807 +1 x6808 +1 x6809 +1 x6810 +1 x6811 +1 x6812 +1 x6813 +1 x6814 +1 x6815 +1 x6816 +1 x6817 +1 x6818 +1 x6819 +1 x6820 +1 x6821 +1 x6822 +1 x6823 +1 x6824 +1 x6825 +1 x6826 +1 x6827 +1 x6828 +1 x6829 +1 x6830 +1 x6831 >= 1;
++1 x6832 +1 x6833 +1 x6834 +1 x6835 +1 x6836 +1 x6837 +1 x6838 +1 x6839 +1 x6840 +1 x6841 +1 x6842 +1 x6843 +1 x6844 +1 x6845 +1 x6846 +1 x6847 +1 x6848 +1 x6849 +1 x6850 +1 x6851 +1 x6852 +1 x6853 +1 x6854 +1 x6855 +1 x6856 +1 x6857 +1 x6858 +1 x6859 +1 x6860 +1 x6861 +1 x6862 +1 x6863 +1 x6864 +1 x6865 +1 x6866 +1 x6867 +1 x6868 +1 x6869 +1 x6870 +1 x6871 +1 x6872 +1 x6873 +1 x6874 +1 x6875 +1 x6876 +1 x6877 +1 x6878 +1 x6879 +1 x6880 +1 x6881 +1 x6882 +1 x6883 +1 x6884 +1 x6885 +1 x6886 +1 x6887 +1 x6888 +1 x6889 +1 x6890 +1 x6891 +1 x6892 +1 x6893 +1 x6894 +1 x6895 +1 x6896 +1 x6897 +1 x6898 +1 x6899 +1 x6900 +1 x6901 +1 x6902 +1 x6903 +1 x6904 +1 x6905 +1 x6906 +1 x6907 +1 x6908 +1 x6909 +1 x6910 +1 x6911 +1 x6912 +1 x6913 +1 x6914 +1 x6915 +1 x6916 +1 x6917 +1 x6918 +1 x6919 +1 x6920 +1 x6921 +1 x6922 +1 x6923 +1 x6924 +1 x6925 +1 x6926 +1 x6927 +1 x6928 +1 x6929 +1 x6930 >= 1;
++1 x6931 +1 x6932 +1 x6933 +1 x6934 +1 x6935 +1 x6936 +1 x6937 +1 x6938 +1 x6939 +1 x6940 +1 x6941 +1 x6942 +1 x6943 +1 x6944 +1 x6945 +1 x6946 +1 x6947 +1 x6948 +1 x6949 +1 x6950 +1 x6951 +1 x6952 +1 x6953 +1 x6954 +1 x6955 +1 x6956 +1 x6957 +1 x6958 +1 x6959 +1 x6960 +1 x6961 +1 x6962 +1 x6963 +1 x6964 +1 x6965 +1 x6966 +1 x6967 +1 x6968 +1 x6969 +1 x6970 +1 x6971 +1 x6972 +1 x6973 +1 x6974 +1 x6975 +1 x6976 +1 x6977 +1 x6978 +1 x6979 +1 x6980 +1 x6981 +1 x6982 +1 x6983 +1 x6984 +1 x6985 +1 x6986 +1 x6987 +1 x6988 +1 x6989 +1 x6990 +1 x6991 +1 x6992 +1 x6993 +1 x6994 +1 x6995 +1 x6996 +1 x6997 +1 x6998 +1 x6999 +1 x7000 +1 x7001 +1 x7002 +1 x7003 +1 x7004 +1 x7005 +1 x7006 +1 x7007 +1 x7008 +1 x7009 +1 x7010 +1 x7011 +1 x7012 +1 x7013 +1 x7014 +1 x7015 +1 x7016 +1 x7017 +1 x7018 +1 x7019 +1 x7020 +1 x7021 +1 x7022 +1 x7023 +1 x7024 +1 x7025 +1 x7026 +1 x7027 +1 x7028 +1 x7029 >= 1;
++1 x7030 +1 x7031 +1 x7032 +1 x7033 +1 x7034 +1 x7035 +1 x7036 +1 x7037 +1 x7038 +1 x7039 +1 x7040 +1 x7041 +1 x7042 +1 x7043 +1 x7044 +1 x7045 +1 x7046 +1 x7047 +1 x7048 +1 x7049 +1 x7050 +1 x7051 +1 x7052 +1 x7053 +1 x7054 +1 x7055 +1 x7056 +1 x7057 +1 x7058 +1 x7059 +1 x7060 +1 x7061 +1 x7062 +1 x7063 +1 x7064 +1 x7065 +1 x7066 +1 x7067 +1 x7068 +1 x7069 +1 x7070 +1 x7071 +1 x7072 +1 x7073 +1 x7074 +1 x7075 +1 x7076 +1 x7077 +1 x7078 +1 x7079 +1 x7080 +1 x7081 +1 x7082 +1 x7083 +1 x7084 +1 x7085 +1 x7086 +1 x7087 +1 x7088 +1 x7089 +1 x7090 +1 x7091 +1 x7092 +1 x7093 +1 x7094 +1 x7095 +1 x7096 +1 x7097 +1 x7098 +1 x7099 +1 x7100 +1 x7101 +1 x7102 +1 x7103 +1 x7104 +1 x7105 +1 x7106 +1 x7107 +1 x7108 +1 x7109 +1 x7110 +1 x7111 +1 x7112 +1 x7113 +1 x7114 +1 x7115 +1 x7116 +1 x7117 +1 x7118 +1 x7119 +1 x7120 +1 x7121 +1 x7122 +1 x7123 +1 x7124 +1 x7125 +1 x7126 +1 x7127 +1 x7128 >= 1;
++1 x7129 +1 x7130 +1 x7131 +1 x7132 +1 x7133 +1 x7134 +1 x7135 +1 x7136 +1 x7137 +1 x7138 +1 x7139 +1 x7140 +1 x7141 +1 x7142 +1 x7143 +1 x7144 +1 x7145 +1 x7146 +1 x7147 +1 x7148 +1 x7149 +1 x7150 +1 x7151 +1 x7152 +1 x7153 +1 x7154 +1 x7155 +1 x7156 +1 x7157 +1 x7158 +1 x7159 +1 x7160 +1 x7161 +1 x7162 +1 x7163 +1 x7164 +1 x7165 +1 x7166 +1 x7167 +1 x7168 +1 x7169 +1 x7170 +1 x7171 +1 x7172 +1 x7173 +1 x7174 +1 x7175 +1 x7176 +1 x7177 +1 x7178 +1 x7179 +1 x7180 +1 x7181 +1 x7182 +1 x7183 +1 x7184 +1 x7185 +1 x7186 +1 x7187 +1 x7188 +1 x7189 +1 x7190 +1 x7191 +1 x7192 +1 x7193 +1 x7194 +1 x7195 +1 x7196 +1 x7197 +1 x7198 +1 x7199 +1 x7200 +1 x7201 +1 x7202 +1 x7203 +1 x7204 +1 x7205 +1 x7206 +1 x7207 +1 x7208 +1 x7209 +1 x7210 +1 x7211 +1 x7212 +1 x7213 +1 x7214 +1 x7215 +1 x7216 +1 x7217 +1 x7218 +1 x7219 +1 x7220 +1 x7221 +1 x7222 +1 x7223 +1 x7224 +1 x7225 +1 x7226 +1 x7227 >= 1;
++1 x7228 +1 x7229 +1 x7230 +1 x7231 +1 x7232 +1 x7233 +1 x7234 +1 x7235 +1 x7236 +1 x7237 +1 x7238 +1 x7239 +1 x7240 +1 x7241 +1 x7242 +1 x7243 +1 x7244 +1 x7245 +1 x7246 +1 x7247 +1 x7248 +1 x7249 +1 x7250 +1 x7251 +1 x7252 +1 x7253 +1 x7254 +1 x7255 +1 x7256 +1 x7257 +1 x7258 +1 x7259 +1 x7260 +1 x7261 +1 x7262 +1 x7263 +1 x7264 +1 x7265 +1 x7266 +1 x7267 +1 x7268 +1 x7269 +1 x7270 +1 x7271 +1 x7272 +1 x7273 +1 x7274 +1 x7275 +1 x7276 +1 x7277 +1 x7278 +1 x7279 +1 x7280 +1 x7281 +1 x7282 +1 x7283 +1 x7284 +1 x7285 +1 x7286 +1 x7287 +1 x7288 +1 x7289 +1 x7290 +1 x7291 +1 x7292 +1 x7293 +1 x7294 +1 x7295 +1 x7296 +1 x7297 +1 x7298 +1 x7299 +1 x7300 +1 x7301 +1 x7302 +1 x7303 +1 x7304 +1 x7305 +1 x7306 +1 x7307 +1 x7308 +1 x7309 +1 x7310 +1 x7311 +1 x7312 +1 x7313 +1 x7314 +1 x7315 +1 x7316 +1 x7317 +1 x7318 +1 x7319 +1 x7320 +1 x7321 +1 x7322 +1 x7323 +1 x7324 +1 x7325 +1 x7326 >= 1;
++1 x7327 +1 x7328 +1 x7329 +1 x7330 +1 x7331 +1 x7332 +1 x7333 +1 x7334 +1 x7335 +1 x7336 +1 x7337 +1 x7338 +1 x7339 +1 x7340 +1 x7341 +1 x7342 +1 x7343 +1 x7344 +1 x7345 +1 x7346 +1 x7347 +1 x7348 +1 x7349 +1 x7350 +1 x7351 +1 x7352 +1 x7353 +1 x7354 +1 x7355 +1 x7356 +1 x7357 +1 x7358 +1 x7359 +1 x7360 +1 x7361 +1 x7362 +1 x7363 +1 x7364 +1 x7365 +1 x7366 +1 x7367 +1 x7368 +1 x7369 +1 x7370 +1 x7371 +1 x7372 +1 x7373 +1 x7374 +1 x7375 +1 x7376 +1 x7377 +1 x7378 +1 x7379 +1 x7380 +1 x7381 +1 x7382 +1 x7383 +1 x7384 +1 x7385 +1 x7386 +1 x7387 +1 x7388 +1 x7389 +1 x7390 +1 x7391 +1 x7392 +1 x7393 +1 x7394 +1 x7395 +1 x7396 +1 x7397 +1 x7398 +1 x7399 +1 x7400 +1 x7401 +1 x7402 +1 x7403 +1 x7404 +1 x7405 +1 x7406 +1 x7407 +1 x7408 +1 x7409 +1 x7410 +1 x7411 +1 x7412 +1 x7413 +1 x7414 +1 x7415 +1 x7416 +1 x7417 +1 x7418 +1 x7419 +1 x7420 +1 x7421 +1 x7422 +1 x7423 +1 x7424 +1 x7425 >= 1;
++1 x7426 +1 x7427 +1 x7428 +1 x7429 +1 x7430 +1 x7431 +1 x7432 +1 x7433 +1 x7434 +1 x7435 +1 x7436 +1 x7437 +1 x7438 +1 x7439 +1 x7440 +1 x7441 +1 x7442 +1 x7443 +1 x7444 +1 x7445 +1 x7446 +1 x7447 +1 x7448 +1 x7449 +1 x7450 +1 x7451 +1 x7452 +1 x7453 +1 x7454 +1 x7455 +1 x7456 +1 x7457 +1 x7458 +1 x7459 +1 x7460 +1 x7461 +1 x7462 +1 x7463 +1 x7464 +1 x7465 +1 x7466 +1 x7467 +1 x7468 +1 x7469 +1 x7470 +1 x7471 +1 x7472 +1 x7473 +1 x7474 +1 x7475 +1 x7476 +1 x7477 +1 x7478 +1 x7479 +1 x7480 +1 x7481 +1 x7482 +1 x7483 +1 x7484 +1 x7485 +1 x7486 +1 x7487 +1 x7488 +1 x7489 +1 x7490 +1 x7491 +1 x7492 +1 x7493 +1 x7494 +1 x7495 +1 x7496 +1 x7497 +1 x7498 +1 x7499 +1 x7500 +1 x7501 +1 x7502 +1 x7503 +1 x7504 +1 x7505 +1 x7506 +1 x7507 +1 x7508 +1 x7509 +1 x7510 +1 x7511 +1 x7512 +1 x7513 +1 x7514 +1 x7515 +1 x7516 +1 x7517 +1 x7518 +1 x7519 +1 x7520 +1 x7521 +1 x7522 +1 x7523 +1 x7524 >= 1;
++1 x7525 +1 x7526 +1 x7527 +1 x7528 +1 x7529 +1 x7530 +1 x7531 +1 x7532 +1 x7533 +1 x7534 +1 x7535 +1 x7536 +1 x7537 +1 x7538 +1 x7539 +1 x7540 +1 x7541 +1 x7542 +1 x7543 +1 x7544 +1 x7545 +1 x7546 +1 x7547 +1 x7548 +1 x7549 +1 x7550 +1 x7551 +1 x7552 +1 x7553 +1 x7554 +1 x7555 +1 x7556 +1 x7557 +1 x7558 +1 x7559 +1 x7560 +1 x7561 +1 x7562 +1 x7563 +1 x7564 +1 x7565 +1 x7566 +1 x7567 +1 x7568 +1 x7569 +1 x7570 +1 x7571 +1 x7572 +1 x7573 +1 x7574 +1 x7575 +1 x7576 +1 x7577 +1 x7578 +1 x7579 +1 x7580 +1 x7581 +1 x7582 +1 x7583 +1 x7584 +1 x7585 +1 x7586 +1 x7587 +1 x7588 +1 x7589 +1 x7590 +1 x7591 +1 x7592 +1 x7593 +1 x7594 +1 x7595 +1 x7596 +1 x7597 +1 x7598 +1 x7599 +1 x7600 +1 x7601 +1 x7602 +1 x7603 +1 x7604 +1 x7605 +1 x7606 +1 x7607 +1 x7608 +1 x7609 +1 x7610 +1 x7611 +1 x7612 +1 x7613 +1 x7614 +1 x7615 +1 x7616 +1 x7617 +1 x7618 +1 x7619 +1 x7620 +1 x7621 +1 x7622 +1 x7623 >= 1;
++1 x7624 +1 x7625 +1 x7626 +1 x7627 +1 x7628 +1 x7629 +1 x7630 +1 x7631 +1 x7632 +1 x7633 +1 x7634 +1 x7635 +1 x7636 +1 x7637 +1 x7638 +1 x7639 +1 x7640 +1 x7641 +1 x7642 +1 x7643 +1 x7644 +1 x7645 +1 x7646 +1 x7647 +1 x7648 +1 x7649 +1 x7650 +1 x7651 +1 x7652 +1 x7653 +1 x7654 +1 x7655 +1 x7656 +1 x7657 +1 x7658 +1 x7659 +1 x7660 +1 x7661 +1 x7662 +1 x7663 +1 x7664 +1 x7665 +1 x7666 +1 x7667 +1 x7668 +1 x7669 +1 x7670 +1 x7671 +1 x7672 +1 x7673 +1 x7674 +1 x7675 +1 x7676 +1 x7677 +1 x7678 +1 x7679 +1 x7680 +1 x7681 +1 x7682 +1 x7683 +1 x7684 +1 x7685 +1 x7686 +1 x7687 +1 x7688 +1 x7689 +1 x7690 +1 x7691 +1 x7692 +1 x7693 +1 x7694 +1 x7695 +1 x7696 +1 x7697 +1 x7698 +1 x7699 +1 x7700 +1 x7701 +1 x7702 +1 x7703 +1 x7704 +1 x7705 +1 x7706 +1 x7707 +1 x7708 +1 x7709 +1 x7710 +1 x7711 +1 x7712 +1 x7713 +1 x7714 +1 x7715 +1 x7716 +1 x7717 +1 x7718 +1 x7719 +1 x7720 +1 x7721 +1 x7722 >= 1;
++1 x7723 +1 x7724 +1 x7725 +1 x7726 +1 x7727 +1 x7728 +1 x7729 +1 x7730 +1 x7731 +1 x7732 +1 x7733 +1 x7734 +1 x7735 +1 x7736 +1 x7737 +1 x7738 +1 x7739 +1 x7740 +1 x7741 +1 x7742 +1 x7743 +1 x7744 +1 x7745 +1 x7746 +1 x7747 +1 x7748 +1 x7749 +1 x7750 +1 x7751 +1 x7752 +1 x7753 +1 x7754 +1 x7755 +1 x7756 +1 x7757 +1 x7758 +1 x7759 +1 x7760 +1 x7761 +1 x7762 +1 x7763 +1 x7764 +1 x7765 +1 x7766 +1 x7767 +1 x7768 +1 x7769 +1 x7770 +1 x7771 +1 x7772 +1 x7773 +1 x7774 +1 x7775 +1 x7776 +1 x7777 +1 x7778 +1 x7779 +1 x7780 +1 x7781 +1 x7782 +1 x7783 +1 x7784 +1 x7785 +1 x7786 +1 x7787 +1 x7788 +1 x7789 +1 x7790 +1 x7791 +1 x7792 +1 x7793 +1 x7794 +1 x7795 +1 x7796 +1 x7797 +1 x7798 +1 x7799 +1 x7800 +1 x7801 +1 x7802 +1 x7803 +1 x7804 +1 x7805 +1 x7806 +1 x7807 +1 x7808 +1 x7809 +1 x7810 +1 x7811 +1 x7812 +1 x7813 +1 x7814 +1 x7815 +1 x7816 +1 x7817 +1 x7818 +1 x7819 +1 x7820 +1 x7821 >= 1;
++1 x7822 +1 x7823 +1 x7824 +1 x7825 +1 x7826 +1 x7827 +1 x7828 +1 x7829 +1 x7830 +1 x7831 +1 x7832 +1 x7833 +1 x7834 +1 x7835 +1 x7836 +1 x7837 +1 x7838 +1 x7839 +1 x7840 +1 x7841 +1 x7842 +1 x7843 +1 x7844 +1 x7845 +1 x7846 +1 x7847 +1 x7848 +1 x7849 +1 x7850 +1 x7851 +1 x7852 +1 x7853 +1 x7854 +1 x7855 +1 x7856 +1 x7857 +1 x7858 +1 x7859 +1 x7860 +1 x7861 +1 x7862 +1 x7863 +1 x7864 +1 x7865 +1 x7866 +1 x7867 +1 x7868 +1 x7869 +1 x7870 +1 x7871 +1 x7872 +1 x7873 +1 x7874 +1 x7875 +1 x7876 +1 x7877 +1 x7878 +1 x7879 +1 x7880 +1 x7881 +1 x7882 +1 x7883 +1 x7884 +1 x7885 +1 x7886 +1 x7887 +1 x7888 +1 x7889 +1 x7890 +1 x7891 +1 x7892 +1 x7893 +1 x7894 +1 x7895 +1 x7896 +1 x7897 +1 x7898 +1 x7899 +1 x7900 +1 x7901 +1 x7902 +1 x7903 +1 x7904 +1 x7905 +1 x7906 +1 x7907 +1 x7908 +1 x7909 +1 x7910 +1 x7911 +1 x7912 +1 x7913 +1 x7914 +1 x7915 +1 x7916 +1 x7917 +1 x7918 +1 x7919 +1 x7920 >= 1;
++1 x7921 +1 x7922 +1 x7923 +1 x7924 +1 x7925 +1 x7926 +1 x7927 +1 x7928 +1 x7929 +1 x7930 +1 x7931 +1 x7932 +1 x7933 +1 x7934 +1 x7935 +1 x7936 +1 x7937 +1 x7938 +1 x7939 +1 x7940 +1 x7941 +1 x7942 +1 x7943 +1 x7944 +1 x7945 +1 x7946 +1 x7947 +1 x7948 +1 x7949 +1 x7950 +1 x7951 +1 x7952 +1 x7953 +1 x7954 +1 x7955 +1 x7956 +1 x7957 +1 x7958 +1 x7959 +1 x7960 +1 x7961 +1 x7962 +1 x7963 +1 x7964 +1 x7965 +1 x7966 +1 x7967 +1 x7968 +1 x7969 +1 x7970 +1 x7971 +1 x7972 +1 x7973 +1 x7974 +1 x7975 +1 x7976 +1 x7977 +1 x7978 +1 x7979 +1 x7980 +1 x7981 +1 x7982 +1 x7983 +1 x7984 +1 x7985 +1 x7986 +1 x7987 +1 x7988 +1 x7989 +1 x7990 +1 x7991 +1 x7992 +1 x7993 +1 x7994 +1 x7995 +1 x7996 +1 x7997 +1 x7998 +1 x7999 +1 x8000 +1 x8001 +1 x8002 +1 x8003 +1 x8004 +1 x8005 +1 x8006 +1 x8007 +1 x8008 +1 x8009 +1 x8010 +1 x8011 +1 x8012 +1 x8013 +1 x8014 +1 x8015 +1 x8016 +1 x8017 +1 x8018 +1 x8019 >= 1;
++1 x8020 +1 x8021 +1 x8022 +1 x8023 +1 x8024 +1 x8025 +1 x8026 +1 x8027 +1 x8028 +1 x8029 +1 x8030 +1 x8031 +1 x8032 +1 x8033 +1 x8034 +1 x8035 +1 x8036 +1 x8037 +1 x8038 +1 x8039 +1 x8040 +1 x8041 +1 x8042 +1 x8043 +1 x8044 +1 x8045 +1 x8046 +1 x8047 +1 x8048 +1 x8049 +1 x8050 +1 x8051 +1 x8052 +1 x8053 +1 x8054 +1 x8055 +1 x8056 +1 x8057 +1 x8058 +1 x8059 +1 x8060 +1 x8061 +1 x8062 +1 x8063 +1 x8064 +1 x8065 +1 x8066 +1 x8067 +1 x8068 +1 x8069 +1 x8070 +1 x8071 +1 x8072 +1 x8073 +1 x8074 +1 x8075 +1 x8076 +1 x8077 +1 x8078 +1 x8079 +1 x8080 +1 x8081 +1 x8082 +1 x8083 +1 x8084 +1 x8085 +1 x8086 +1 x8087 +1 x8088 +1 x8089 +1 x8090 +1 x8091 +1 x8092 +1 x8093 +1 x8094 +1 x8095 +1 x8096 +1 x8097 +1 x8098 +1 x8099 +1 x8100 +1 x8101 +1 x8102 +1 x8103 +1 x8104 +1 x8105 +1 x8106 +1 x8107 +1 x8108 +1 x8109 +1 x8110 +1 x8111 +1 x8112 +1 x8113 +1 x8114 +1 x8115 +1 x8116 +1 x8117 +1 x8118 >= 1;
++1 x8119 +1 x8120 +1 x8121 +1 x8122 +1 x8123 +1 x8124 +1 x8125 +1 x8126 +1 x8127 +1 x8128 +1 x8129 +1 x8130 +1 x8131 +1 x8132 +1 x8133 +1 x8134 +1 x8135 +1 x8136 +1 x8137 +1 x8138 +1 x8139 +1 x8140 +1 x8141 +1 x8142 +1 x8143 +1 x8144 +1 x8145 +1 x8146 +1 x8147 +1 x8148 +1 x8149 +1 x8150 +1 x8151 +1 x8152 +1 x8153 +1 x8154 +1 x8155 +1 x8156 +1 x8157 +1 x8158 +1 x8159 +1 x8160 +1 x8161 +1 x8162 +1 x8163 +1 x8164 +1 x8165 +1 x8166 +1 x8167 +1 x8168 +1 x8169 +1 x8170 +1 x8171 +1 x8172 +1 x8173 +1 x8174 +1 x8175 +1 x8176 +1 x8177 +1 x8178 +1 x8179 +1 x8180 +1 x8181 +1 x8182 +1 x8183 +1 x8184 +1 x8185 +1 x8186 +1 x8187 +1 x8188 +1 x8189 +1 x8190 +1 x8191 +1 x8192 +1 x8193 +1 x8194 +1 x8195 +1 x8196 +1 x8197 +1 x8198 +1 x8199 +1 x8200 +1 x8201 +1 x8202 +1 x8203 +1 x8204 +1 x8205 +1 x8206 +1 x8207 +1 x8208 +1 x8209 +1 x8210 +1 x8211 +1 x8212 +1 x8213 +1 x8214 +1 x8215 +1 x8216 +1 x8217 >= 1;
++1 x8218 +1 x8219 +1 x8220 +1 x8221 +1 x8222 +1 x8223 +1 x8224 +1 x8225 +1 x8226 +1 x8227 +1 x8228 +1 x8229 +1 x8230 +1 x8231 +1 x8232 +1 x8233 +1 x8234 +1 x8235 +1 x8236 +1 x8237 +1 x8238 +1 x8239 +1 x8240 +1 x8241 +1 x8242 +1 x8243 +1 x8244 +1 x8245 +1 x8246 +1 x8247 +1 x8248 +1 x8249 +1 x8250 +1 x8251 +1 x8252 +1 x8253 +1 x8254 +1 x8255 +1 x8256 +1 x8257 +1 x8258 +1 x8259 +1 x8260 +1 x8261 +1 x8262 +1 x8263 +1 x8264 +1 x8265 +1 x8266 +1 x8267 +1 x8268 +1 x8269 +1 x8270 +1 x8271 +1 x8272 +1 x8273 +1 x8274 +1 x8275 +1 x8276 +1 x8277 +1 x8278 +1 x8279 +1 x8280 +1 x8281 +1 x8282 +1 x8283 +1 x8284 +1 x8285 +1 x8286 +1 x8287 +1 x8288 +1 x8289 +1 x8290 +1 x8291 +1 x8292 +1 x8293 +1 x8294 +1 x8295 +1 x8296 +1 x8297 +1 x8298 +1 x8299 +1 x8300 +1 x8301 +1 x8302 +1 x8303 +1 x8304 +1 x8305 +1 x8306 +1 x8307 +1 x8308 +1 x8309 +1 x8310 +1 x8311 +1 x8312 +1 x8313 +1 x8314 +1 x8315 +1 x8316 >= 1;
++1 x8317 +1 x8318 +1 x8319 +1 x8320 +1 x8321 +1 x8322 +1 x8323 +1 x8324 +1 x8325 +1 x8326 +1 x8327 +1 x8328 +1 x8329 +1 x8330 +1 x8331 +1 x8332 +1 x8333 +1 x8334 +1 x8335 +1 x8336 +1 x8337 +1 x8338 +1 x8339 +1 x8340 +1 x8341 +1 x8342 +1 x8343 +1 x8344 +1 x8345 +1 x8346 +1 x8347 +1 x8348 +1 x8349 +1 x8350 +1 x8351 +1 x8352 +1 x8353 +1 x8354 +1 x8355 +1 x8356 +1 x8357 +1 x8358 +1 x8359 +1 x8360 +1 x8361 +1 x8362 +1 x8363 +1 x8364 +1 x8365 +1 x8366 +1 x8367 +1 x8368 +1 x8369 +1 x8370 +1 x8371 +1 x8372 +1 x8373 +1 x8374 +1 x8375 +1 x8376 +1 x8377 +1 x8378 +1 x8379 +1 x8380 +1 x8381 +1 x8382 +1 x8383 +1 x8384 +1 x8385 +1 x8386 +1 x8387 +1 x8388 +1 x8389 +1 x8390 +1 x8391 +1 x8392 +1 x8393 +1 x8394 +1 x8395 +1 x8396 +1 x8397 +1 x8398 +1 x8399 +1 x8400 +1 x8401 +1 x8402 +1 x8403 +1 x8404 +1 x8405 +1 x8406 +1 x8407 +1 x8408 +1 x8409 +1 x8410 +1 x8411 +1 x8412 +1 x8413 +1 x8414 +1 x8415 >= 1;
++1 x8416 +1 x8417 +1 x8418 +1 x8419 +1 x8420 +1 x8421 +1 x8422 +1 x8423 +1 x8424 +1 x8425 +1 x8426 +1 x8427 +1 x8428 +1 x8429 +1 x8430 +1 x8431 +1 x8432 +1 x8433 +1 x8434 +1 x8435 +1 x8436 +1 x8437 +1 x8438 +1 x8439 +1 x8440 +1 x8441 +1 x8442 +1 x8443 +1 x8444 +1 x8445 +1 x8446 +1 x8447 +1 x8448 +1 x8449 +1 x8450 +1 x8451 +1 x8452 +1 x8453 +1 x8454 +1 x8455 +1 x8456 +1 x8457 +1 x8458 +1 x8459 +1 x8460 +1 x8461 +1 x8462 +1 x8463 +1 x8464 +1 x8465 +1 x8466 +1 x8467 +1 x8468 +1 x8469 +1 x8470 +1 x8471 +1 x8472 +1 x8473 +1 x8474 +1 x8475 +1 x8476 +1 x8477 +1 x8478 +1 x8479 +1 x8480 +1 x8481 +1 x8482 +1 x8483 +1 x8484 +1 x8485 +1 x8486 +1 x8487 +1 x8488 +1 x8489 +1 x8490 +1 x8491 +1 x8492 +1 x8493 +1 x8494 +1 x8495 +1 x8496 +1 x8497 +1 x8498 +1 x8499 +1 x8500 +1 x8501 +1 x8502 +1 x8503 +1 x8504 +1 x8505 +1 x8506 +1 x8507 +1 x8508 +1 x8509 +1 x8510 +1 x8511 +1 x8512 +1 x8513 +1 x8514 >= 1;
++1 x8515 +1 x8516 +1 x8517 +1 x8518 +1 x8519 +1 x8520 +1 x8521 +1 x8522 +1 x8523 +1 x8524 +1 x8525 +1 x8526 +1 x8527 +1 x8528 +1 x8529 +1 x8530 +1 x8531 +1 x8532 +1 x8533 +1 x8534 +1 x8535 +1 x8536 +1 x8537 +1 x8538 +1 x8539 +1 x8540 +1 x8541 +1 x8542 +1 x8543 +1 x8544 +1 x8545 +1 x8546 +1 x8547 +1 x8548 +1 x8549 +1 x8550 +1 x8551 +1 x8552 +1 x8553 +1 x8554 +1 x8555 +1 x8556 +1 x8557 +1 x8558 +1 x8559 +1 x8560 +1 x8561 +1 x8562 +1 x8563 +1 x8564 +1 x8565 +1 x8566 +1 x8567 +1 x8568 +1 x8569 +1 x8570 +1 x8571 +1 x8572 +1 x8573 +1 x8574 +1 x8575 +1 x8576 +1 x8577 +1 x8578 +1 x8579 +1 x8580 +1 x8581 +1 x8582 +1 x8583 +1 x8584 +1 x8585 +1 x8586 +1 x8587 +1 x8588 +1 x8589 +1 x8590 +1 x8591 +1 x8592 +1 x8593 +1 x8594 +1 x8595 +1 x8596 +1 x8597 +1 x8598 +1 x8599 +1 x8600 +1 x8601 +1 x8602 +1 x8603 +1 x8604 +1 x8605 +1 x8606 +1 x8607 +1 x8608 +1 x8609 +1 x8610 +1 x8611 +1 x8612 +1 x8613 >= 1;
++1 x8614 +1 x8615 +1 x8616 +1 x8617 +1 x8618 +1 x8619 +1 x8620 +1 x8621 +1 x8622 +1 x8623 +1 x8624 +1 x8625 +1 x8626 +1 x8627 +1 x8628 +1 x8629 +1 x8630 +1 x8631 +1 x8632 +1 x8633 +1 x8634 +1 x8635 +1 x8636 +1 x8637 +1 x8638 +1 x8639 +1 x8640 +1 x8641 +1 x8642 +1 x8643 +1 x8644 +1 x8645 +1 x8646 +1 x8647 +1 x8648 +1 x8649 +1 x8650 +1 x8651 +1 x8652 +1 x8653 +1 x8654 +1 x8655 +1 x8656 +1 x8657 +1 x8658 +1 x8659 +1 x8660 +1 x8661 +1 x8662 +1 x8663 +1 x8664 +1 x8665 +1 x8666 +1 x8667 +1 x8668 +1 x8669 +1 x8670 +1 x8671 +1 x8672 +1 x8673 +1 x8674 +1 x8675 +1 x8676 +1 x8677 +1 x8678 +1 x8679 +1 x8680 +1 x8681 +1 x8682 +1 x8683 +1 x8684 +1 x8685 +1 x8686 +1 x8687 +1 x8688 +1 x8689 +1 x8690 +1 x8691 +1 x8692 +1 x8693 +1 x8694 +1 x8695 +1 x8696 +1 x8697 +1 x8698 +1 x8699 +1 x8700 +1 x8701 +1 x8702 +1 x8703 +1 x8704 +1 x8705 +1 x8706 +1 x8707 +1 x8708 +1 x8709 +1 x8710 +1 x8711 +1 x8712 >= 1;
++1 x8713 +1 x8714 +1 x8715 +1 x8716 +1 x8717 +1 x8718 +1 x8719 +1 x8720 +1 x8721 +1 x8722 +1 x8723 +1 x8724 +1 x8725 +1 x8726 +1 x8727 +1 x8728 +1 x8729 +1 x8730 +1 x8731 +1 x8732 +1 x8733 +1 x8734 +1 x8735 +1 x8736 +1 x8737 +1 x8738 +1 x8739 +1 x8740 +1 x8741 +1 x8742 +1 x8743 +1 x8744 +1 x8745 +1 x8746 +1 x8747 +1 x8748 +1 x8749 +1 x8750 +1 x8751 +1 x8752 +1 x8753 +1 x8754 +1 x8755 +1 x8756 +1 x8757 +1 x8758 +1 x8759 +1 x8760 +1 x8761 +1 x8762 +1 x8763 +1 x8764 +1 x8765 +1 x8766 +1 x8767 +1 x8768 +1 x8769 +1 x8770 +1 x8771 +1 x8772 +1 x8773 +1 x8774 +1 x8775 +1 x8776 +1 x8777 +1 x8778 +1 x8779 +1 x8780 +1 x8781 +1 x8782 +1 x8783 +1 x8784 +1 x8785 +1 x8786 +1 x8787 +1 x8788 +1 x8789 +1 x8790 +1 x8791 +1 x8792 +1 x8793 +1 x8794 +1 x8795 +1 x8796 +1 x8797 +1 x8798 +1 x8799 +1 x8800 +1 x8801 +1 x8802 +1 x8803 +1 x8804 +1 x8805 +1 x8806 +1 x8807 +1 x8808 +1 x8809 +1 x8810 +1 x8811 >= 1;
++1 x8812 +1 x8813 +1 x8814 +1 x8815 +1 x8816 +1 x8817 +1 x8818 +1 x8819 +1 x8820 +1 x8821 +1 x8822 +1 x8823 +1 x8824 +1 x8825 +1 x8826 +1 x8827 +1 x8828 +1 x8829 +1 x8830 +1 x8831 +1 x8832 +1 x8833 +1 x8834 +1 x8835 +1 x8836 +1 x8837 +1 x8838 +1 x8839 +1 x8840 +1 x8841 +1 x8842 +1 x8843 +1 x8844 +1 x8845 +1 x8846 +1 x8847 +1 x8848 +1 x8849 +1 x8850 +1 x8851 +1 x8852 +1 x8853 +1 x8854 +1 x8855 +1 x8856 +1 x8857 +1 x8858 +1 x8859 +1 x8860 +1 x8861 +1 x8862 +1 x8863 +1 x8864 +1 x8865 +1 x8866 +1 x8867 +1 x8868 +1 x8869 +1 x8870 +1 x8871 +1 x8872 +1 x8873 +1 x8874 +1 x8875 +1 x8876 +1 x8877 +1 x8878 +1 x8879 +1 x8880 +1 x8881 +1 x8882 +1 x8883 +1 x8884 +1 x8885 +1 x8886 +1 x8887 +1 x8888 +1 x8889 +1 x8890 +1 x8891 +1 x8892 +1 x8893 +1 x8894 +1 x8895 +1 x8896 +1 x8897 +1 x8898 +1 x8899 +1 x8900 +1 x8901 +1 x8902 +1 x8903 +1 x8904 +1 x8905 +1 x8906 +1 x8907 +1 x8908 +1 x8909 +1 x8910 >= 1;
++1 x8911 +1 x8912 +1 x8913 +1 x8914 +1 x8915 +1 x8916 +1 x8917 +1 x8918 +1 x8919 +1 x8920 +1 x8921 +1 x8922 +1 x8923 +1 x8924 +1 x8925 +1 x8926 +1 x8927 +1 x8928 +1 x8929 +1 x8930 +1 x8931 +1 x8932 +1 x8933 +1 x8934 +1 x8935 +1 x8936 +1 x8937 +1 x8938 +1 x8939 +1 x8940 +1 x8941 +1 x8942 +1 x8943 +1 x8944 +1 x8945 +1 x8946 +1 x8947 +1 x8948 +1 x8949 +1 x8950 +1 x8951 +1 x8952 +1 x8953 +1 x8954 +1 x8955 +1 x8956 +1 x8957 +1 x8958 +1 x8959 +1 x8960 +1 x8961 +1 x8962 +1 x8963 +1 x8964 +1 x8965 +1 x8966 +1 x8967 +1 x8968 +1 x8969 +1 x8970 +1 x8971 +1 x8972 +1 x8973 +1 x8974 +1 x8975 +1 x8976 +1 x8977 +1 x8978 +1 x8979 +1 x8980 +1 x8981 +1 x8982 +1 x8983 +1 x8984 +1 x8985 +1 x8986 +1 x8987 +1 x8988 +1 x8989 +1 x8990 +1 x8991 +1 x8992 +1 x8993 +1 x8994 +1 x8995 +1 x8996 +1 x8997 +1 x8998 +1 x8999 +1 x9000 +1 x9001 +1 x9002 +1 x9003 +1 x9004 +1 x9005 +1 x9006 +1 x9007 +1 x9008 +1 x9009 >= 1;
++1 x9010 +1 x9011 +1 x9012 +1 x9013 +1 x9014 +1 x9015 +1 x9016 +1 x9017 +1 x9018 +1 x9019 +1 x9020 +1 x9021 +1 x9022 +1 x9023 +1 x9024 +1 x9025 +1 x9026 +1 x9027 +1 x9028 +1 x9029 +1 x9030 +1 x9031 +1 x9032 +1 x9033 +1 x9034 +1 x9035 +1 x9036 +1 x9037 +1 x9038 +1 x9039 +1 x9040 +1 x9041 +1 x9042 +1 x9043 +1 x9044 +1 x9045 +1 x9046 +1 x9047 +1 x9048 +1 x9049 +1 x9050 +1 x9051 +1 x9052 +1 x9053 +1 x9054 +1 x9055 +1 x9056 +1 x9057 +1 x9058 +1 x9059 +1 x9060 +1 x9061 +1 x9062 +1 x9063 +1 x9064 +1 x9065 +1 x9066 +1 x9067 +1 x9068 +1 x9069 +1 x9070 +1 x9071 +1 x9072 +1 x9073 +1 x9074 +1 x9075 +1 x9076 +1 x9077 +1 x9078 +1 x9079 +1 x9080 +1 x9081 +1 x9082 +1 x9083 +1 x9084 +1 x9085 +1 x9086 +1 x9087 +1 x9088 +1 x9089 +1 x9090 +1 x9091 +1 x9092 +1 x9093 +1 x9094 +1 x9095 +1 x9096 +1 x9097 +1 x9098 +1 x9099 +1 x9100 +1 x9101 +1 x9102 +1 x9103 +1 x9104 +1 x9105 +1 x9106 +1 x9107 +1 x9108 >= 1;
++1 x9109 +1 x9110 +1 x9111 +1 x9112 +1 x9113 +1 x9114 +1 x9115 +1 x9116 +1 x9117 +1 x9118 +1 x9119 +1 x9120 +1 x9121 +1 x9122 +1 x9123 +1 x9124 +1 x9125 +1 x9126 +1 x9127 +1 x9128 +1 x9129 +1 x9130 +1 x9131 +1 x9132 +1 x9133 +1 x9134 +1 x9135 +1 x9136 +1 x9137 +1 x9138 +1 x9139 +1 x9140 +1 x9141 +1 x9142 +1 x9143 +1 x9144 +1 x9145 +1 x9146 +1 x9147 +1 x9148 +1 x9149 +1 x9150 +1 x9151 +1 x9152 +1 x9153 +1 x9154 +1 x9155 +1 x9156 +1 x9157 +1 x9158 +1 x9159 +1 x9160 +1 x9161 +1 x9162 +1 x9163 +1 x9164 +1 x9165 +1 x9166 +1 x9167 +1 x9168 +1 x9169 +1 x9170 +1 x9171 +1 x9172 +1 x9173 +1 x9174 +1 x9175 +1 x9176 +1 x9177 +1 x9178 +1 x9179 +1 x9180 +1 x9181 +1 x9182 +1 x9183 +1 x9184 +1 x9185 +1 x9186 +1 x9187 +1 x9188 +1 x9189 +1 x9190 +1 x9191 +1 x9192 +1 x9193 +1 x9194 +1 x9195 +1 x9196 +1 x9197 +1 x9198 +1 x9199 +1 x9200 +1 x9201 +1 x9202 +1 x9203 +1 x9204 +1 x9205 +1 x9206 +1 x9207 >= 1;
++1 x9208 +1 x9209 +1 x9210 +1 x9211 +1 x9212 +1 x9213 +1 x9214 +1 x9215 +1 x9216 +1 x9217 +1 x9218 +1 x9219 +1 x9220 +1 x9221 +1 x9222 +1 x9223 +1 x9224 +1 x9225 +1 x9226 +1 x9227 +1 x9228 +1 x9229 +1 x9230 +1 x9231 +1 x9232 +1 x9233 +1 x9234 +1 x9235 +1 x9236 +1 x9237 +1 x9238 +1 x9239 +1 x9240 +1 x9241 +1 x9242 +1 x9243 +1 x9244 +1 x9245 +1 x9246 +1 x9247 +1 x9248 +1 x9249 +1 x9250 +1 x9251 +1 x9252 +1 x9253 +1 x9254 +1 x9255 +1 x9256 +1 x9257 +1 x9258 +1 x9259 +1 x9260 +1 x9261 +1 x9262 +1 x9263 +1 x9264 +1 x9265 +1 x9266 +1 x9267 +1 x9268 +1 x9269 +1 x9270 +1 x9271 +1 x9272 +1 x9273 +1 x9274 +1 x9275 +1 x9276 +1 x9277 +1 x9278 +1 x9279 +1 x9280 +1 x9281 +1 x9282 +1 x9283 +1 x9284 +1 x9285 +1 x9286 +1 x9287 +1 x9288 +1 x9289 +1 x9290 +1 x9291 +1 x9292 +1 x9293 +1 x9294 +1 x9295 +1 x9296 +1 x9297 +1 x9298 +1 x9299 +1 x9300 +1 x9301 +1 x9302 +1 x9303 +1 x9304 +1 x9305 +1 x9306 >= 1;
++1 x9307 +1 x9308 +1 x9309 +1 x9310 +1 x9311 +1 x9312 +1 x9313 +1 x9314 +1 x9315 +1 x9316 +1 x9317 +1 x9318 +1 x9319 +1 x9320 +1 x9321 +1 x9322 +1 x9323 +1 x9324 +1 x9325 +1 x9326 +1 x9327 +1 x9328 +1 x9329 +1 x9330 +1 x9331 +1 x9332 +1 x9333 +1 x9334 +1 x9335 +1 x9336 +1 x9337 +1 x9338 +1 x9339 +1 x9340 +1 x9341 +1 x9342 +1 x9343 +1 x9344 +1 x9345 +1 x9346 +1 x9347 +1 x9348 +1 x9349 +1 x9350 +1 x9351 +1 x9352 +1 x9353 +1 x9354 +1 x9355 +1 x9356 +1 x9357 +1 x9358 +1 x9359 +1 x9360 +1 x9361 +1 x9362 +1 x9363 +1 x9364 +1 x9365 +1 x9366 +1 x9367 +1 x9368 +1 x9369 +1 x9370 +1 x9371 +1 x9372 +1 x9373 +1 x9374 +1 x9375 +1 x9376 +1 x9377 +1 x9378 +1 x9379 +1 x9380 +1 x9381 +1 x9382 +1 x9383 +1 x9384 +1 x9385 +1 x9386 +1 x9387 +1 x9388 +1 x9389 +1 x9390 +1 x9391 +1 x9392 +1 x9393 +1 x9394 +1 x9395 +1 x9396 +1 x9397 +1 x9398 +1 x9399 +1 x9400 +1 x9401 +1 x9402 +1 x9403 +1 x9404 +1 x9405 >= 1;
++1 x9406 +1 x9407 +1 x9408 +1 x9409 +1 x9410 +1 x9411 +1 x9412 +1 x9413 +1 x9414 +1 x9415 +1 x9416 +1 x9417 +1 x9418 +1 x9419 +1 x9420 +1 x9421 +1 x9422 +1 x9423 +1 x9424 +1 x9425 +1 x9426 +1 x9427 +1 x9428 +1 x9429 +1 x9430 +1 x9431 +1 x9432 +1 x9433 +1 x9434 +1 x9435 +1 x9436 +1 x9437 +1 x9438 +1 x9439 +1 x9440 +1 x9441 +1 x9442 +1 x9443 +1 x9444 +1 x9445 +1 x9446 +1 x9447 +1 x9448 +1 x9449 +1 x9450 +1 x9451 +1 x9452 +1 x9453 +1 x9454 +1 x9455 +1 x9456 +1 x9457 +1 x9458 +1 x9459 +1 x9460 +1 x9461 +1 x9462 +1 x9463 +1 x9464 +1 x9465 +1 x9466 +1 x9467 +1 x9468 +1 x9469 +1 x9470 +1 x9471 +1 x9472 +1 x9473 +1 x9474 +1 x9475 +1 x9476 +1 x9477 +1 x9478 +1 x9479 +1 x9480 +1 x9481 +1 x9482 +1 x9483 +1 x9484 +1 x9485 +1 x9486 +1 x9487 +1 x9488 +1 x9489 +1 x9490 +1 x9491 +1 x9492 +1 x9493 +1 x9494 +1 x9495 +1 x9496 +1 x9497 +1 x9498 +1 x9499 +1 x9500 +1 x9501 +1 x9502 +1 x9503 +1 x9504 >= 1;
++1 x9505 +1 x9506 +1 x9507 +1 x9508 +1 x9509 +1 x9510 +1 x9511 +1 x9512 +1 x9513 +1 x9514 +1 x9515 +1 x9516 +1 x9517 +1 x9518 +1 x9519 +1 x9520 +1 x9521 +1 x9522 +1 x9523 +1 x9524 +1 x9525 +1 x9526 +1 x9527 +1 x9528 +1 x9529 +1 x9530 +1 x9531 +1 x9532 +1 x9533 +1 x9534 +1 x9535 +1 x9536 +1 x9537 +1 x9538 +1 x9539 +1 x9540 +1 x9541 +1 x9542 +1 x9543 +1 x9544 +1 x9545 +1 x9546 +1 x9547 +1 x9548 +1 x9549 +1 x9550 +1 x9551 +1 x9552 +1 x9553 +1 x9554 +1 x9555 +1 x9556 +1 x9557 +1 x9558 +1 x9559 +1 x9560 +1 x9561 +1 x9562 +1 x9563 +1 x9564 +1 x9565 +1 x9566 +1 x9567 +1 x9568 +1 x9569 +1 x9570 +1 x9571 +1 x9572 +1 x9573 +1 x9574 +1 x9575 +1 x9576 +1 x9577 +1 x9578 +1 x9579 +1 x9580 +1 x9581 +1 x9582 +1 x9583 +1 x9584 +1 x9585 +1 x9586 +1 x9587 +1 x9588 +1 x9589 +1 x9590 +1 x9591 +1 x9592 +1 x9593 +1 x9594 +1 x9595 +1 x9596 +1 x9597 +1 x9598 +1 x9599 +1 x9600 +1 x9601 +1 x9602 +1 x9603 >= 1;
++1 x9604 +1 x9605 +1 x9606 +1 x9607 +1 x9608 +1 x9609 +1 x9610 +1 x9611 +1 x9612 +1 x9613 +1 x9614 +1 x9615 +1 x9616 +1 x9617 +1 x9618 +1 x9619 +1 x9620 +1 x9621 +1 x9622 +1 x9623 +1 x9624 +1 x9625 +1 x9626 +1 x9627 +1 x9628 +1 x9629 +1 x9630 +1 x9631 +1 x9632 +1 x9633 +1 x9634 +1 x9635 +1 x9636 +1 x9637 +1 x9638 +1 x9639 +1 x9640 +1 x9641 +1 x9642 +1 x9643 +1 x9644 +1 x9645 +1 x9646 +1 x9647 +1 x9648 +1 x9649 +1 x9650 +1 x9651 +1 x9652 +1 x9653 +1 x9654 +1 x9655 +1 x9656 +1 x9657 +1 x9658 +1 x9659 +1 x9660 +1 x9661 +1 x9662 +1 x9663 +1 x9664 +1 x9665 +1 x9666 +1 x9667 +1 x9668 +1 x9669 +1 x9670 +1 x9671 +1 x9672 +1 x9673 +1 x9674 +1 x9675 +1 x9676 +1 x9677 +1 x9678 +1 x9679 +1 x9680 +1 x9681 +1 x9682 +1 x9683 +1 x9684 +1 x9685 +1 x9686 +1 x9687 +1 x9688 +1 x9689 +1 x9690 +1 x9691 +1 x9692 +1 x9693 +1 x9694 +1 x9695 +1 x9696 +1 x9697 +1 x9698 +1 x9699 +1 x9700 +1 x9701 +1 x9702 >= 1;
++1 x9703 +1 x9704 +1 x9705 +1 x9706 +1 x9707 +1 x9708 +1 x9709 +1 x9710 +1 x9711 +1 x9712 +1 x9713 +1 x9714 +1 x9715 +1 x9716 +1 x9717 +1 x9718 +1 x9719 +1 x9720 +1 x9721 +1 x9722 +1 x9723 +1 x9724 +1 x9725 +1 x9726 +1 x9727 +1 x9728 +1 x9729 +1 x9730 +1 x9731 +1 x9732 +1 x9733 +1 x9734 +1 x9735 +1 x9736 +1 x9737 +1 x9738 +1 x9739 +1 x9740 +1 x9741 +1 x9742 +1 x9743 +1 x9744 +1 x9745 +1 x9746 +1 x9747 +1 x9748 +1 x9749 +1 x9750 +1 x9751 +1 x9752 +1 x9753 +1 x9754 +1 x9755 +1 x9756 +1 x9757 +1 x9758 +1 x9759 +1 x9760 +1 x9761 +1 x9762 +1 x9763 +1 x9764 +1 x9765 +1 x9766 +1 x9767 +1 x9768 +1 x9769 +1 x9770 +1 x9771 +1 x9772 +1 x9773 +1 x9774 +1 x9775 +1 x9776 +1 x9777 +1 x9778 +1 x9779 +1 x9780 +1 x9781 +1 x9782 +1 x9783 +1 x9784 +1 x9785 +1 x9786 +1 x9787 +1 x9788 +1 x9789 +1 x9790 +1 x9791 +1 x9792 +1 x9793 +1 x9794 +1 x9795 +1 x9796 +1 x9797 +1 x9798 +1 x9799 +1 x9800 +1 x9801 >= 1;
++1 x9802 +1 x9803 +1 x9804 +1 x9805 +1 x9806 +1 x9807 +1 x9808 +1 x9809 +1 x9810 +1 x9811 +1 x9812 +1 x9813 +1 x9814 +1 x9815 +1 x9816 +1 x9817 +1 x9818 +1 x9819 +1 x9820 +1 x9821 +1 x9822 +1 x9823 +1 x9824 +1 x9825 +1 x9826 +1 x9827 +1 x9828 +1 x9829 +1 x9830 +1 x9831 +1 x9832 +1 x9833 +1 x9834 +1 x9835 +1 x9836 +1 x9837 +1 x9838 +1 x9839 +1 x9840 +1 x9841 +1 x9842 +1 x9843 +1 x9844 +1 x9845 +1 x9846 +1 x9847 +1 x9848 +1 x9849 +1 x9850 +1 x9851 +1 x9852 +1 x9853 +1 x9854 +1 x9855 +1 x9856 +1 x9857 +1 x9858 +1 x9859 +1 x9860 +1 x9861 +1 x9862 +1 x9863 +1 x9864 +1 x9865 +1 x9866 +1 x9867 +1 x9868 +1 x9869 +1 x9870 +1 x9871 +1 x9872 +1 x9873 +1 x9874 +1 x9875 +1 x9876 +1 x9877 +1 x9878 +1 x9879 +1 x9880 +1 x9881 +1 x9882 +1 x9883 +1 x9884 +1 x9885 +1 x9886 +1 x9887 +1 x9888 +1 x9889 +1 x9890 +1 x9891 +1 x9892 +1 x9893 +1 x9894 +1 x9895 +1 x9896 +1 x9897 +1 x9898 +1 x9899 +1 x9900 >= 1;
+-1 x1 -1 x100 -1 x199 -1 x298 -1 x397 -1 x496 -1 x595 -1 x694 -1 x793 -1 x892 -1 x991 -1 x1090 -1 x1189 -1 x1288 -1 x1387 -1 x1486 -1 x1585 -1 x1684 -1 x1783 -1 x1882 -1 x1981 -1 x2080 -1 x2179 -1 x2278 -1 x2377 -1 x2476 -1 x2575 -1 x2674 -1 x2773 -1 x2872 -1 x2971 -1 x3070 -1 x3169 -1 x3268 -1 x3367 -1 x3466 -1 x3565 -1 x3664 -1 x3763 -1 x3862 -1 x3961 -1 x4060 -1 x4159 -1 x4258 -1 x4357 -1 x4456 -1 x4555 -1 x4654 -1 x4753 -1 x4852 -1 x4951 -1 x5050 -1 x5149 -1 x5248 -1 x5347 -1 x5446 -1 x5545 -1 x5644 -1 x5743 -1 x5842 -1 x5941 -1 x6040 -1 x6139 -1 x6238 -1 x6337 -1 x6436 -1 x6535 -1 x6634 -1 x6733 -1 x6832 -1 x6931 -1 x7030 -1 x7129 -1 x7228 -1 x7327 -1 x7426 -1 x7525 -1 x7624 -1 x7723 -1 x7822 -1 x7921 -1 x8020 -1 x8119 -1 x8218 -1 x8317 -1 x8416 -1 x8515 -1 x8614 -1 x8713 -1 x8812 -1 x8911 -1 x9010 -1 x9109 -1 x9208 -1 x9307 -1 x9406 -1 x9505 -1 x9604 -1 x9703 -1 x9802 >= -1;
+-1 x2 -1 x101 -1 x200 -1 x299 -1 x398 -1 x497 -1 x596 -1 x695 -1 x794 -1 x893 -1 x992 -1 x1091 -1 x1190 -1 x1289 -1 x1388 -1 x1487 -1 x1586 -1 x1685 -1 x1784 -1 x1883 -1 x1982 -1 x2081 -1 x2180 -1 x2279 -1 x2378 -1 x2477 -1 x2576 -1 x2675 -1 x2774 -1 x2873 -1 x2972 -1 x3071 -1 x3170 -1 x3269 -1 x3368 -1 x3467 -1 x3566 -1 x3665 -1 x3764 -1 x3863 -1 x3962 -1 x4061 -1 x4160 -1 x4259 -1 x4358 -1 x4457 -1 x4556 -1 x4655 -1 x4754 -1 x4853 -1 x4952 -1 x5051 -1 x5150 -1 x5249 -1 x5348 -1 x5447 -1 x5546 -1 x5645 -1 x5744 -1 x5843 -1 x5942 -1 x6041 -1 x6140 -1 x6239 -1 x6338 -1 x6437 -1 x6536 -1 x6635 -1 x6734 -1 x6833 -1 x6932 -1 x7031 -1 x7130 -1 x7229 -1 x7328 -1 x7427 -1 x7526 -1 x7625 -1 x7724 -1 x7823 -1 x7922 -1 x8021 -1 x8120 -1 x8219 -1 x8318 -1 x8417 -1 x8516 -1 x8615 -1 x8714 -1 x8813 -1 x8912 -1 x9011 -1 x9110 -1 x9209 -1 x9308 -1 x9407 -1 x9506 -1 x9605 -1 x9704 -1 x9803 >= -1;
+-1 x3 -1 x102 -1 x201 -1 x300 -1 x399 -1 x498 -1 x597 -1 x696 -1 x795 -1 x894 -1 x993 -1 x1092 -1 x1191 -1 x1290 -1 x1389 -1 x1488 -1 x1587 -1 x1686 -1 x1785 -1 x1884 -1 x1983 -1 x2082 -1 x2181 -1 x2280 -1 x2379 -1 x2478 -1 x2577 -1 x2676 -1 x2775 -1 x2874 -1 x2973 -1 x3072 -1 x3171 -1 x3270 -1 x3369 -1 x3468 -1 x3567 -1 x3666 -1 x3765 -1 x3864 -1 x3963 -1 x4062 -1 x4161 -1 x4260 -1 x4359 -1 x4458 -1 x4557 -1 x4656 -1 x4755 -1 x4854 -1 x4953 -1 x5052 -1 x5151 -1 x5250 -1 x5349 -1 x5448 -1 x5547 -1 x5646 -1 x5745 -1 x5844 -1 x5943 -1 x6042 -1 x6141 -1 x6240 -1 x6339 -1 x6438 -1 x6537 -1 x6636 -1 x6735 -1 x6834 -1 x6933 -1 x7032 -1 x7131 -1 x7230 -1 x7329 -1 x7428 -1 x7527 -1 x7626 -1 x7725 -1 x7824 -1 x7923 -1 x8022 -1 x8121 -1 x8220 -1 x8319 -1 x8418 -1 x8517 -1 x8616 -1 x8715 -1 x8814 -1 x8913 -1 x9012 -1 x9111 -1 x9210 -1 x9309 -1 x9408 -1 x9507 -1 x9606 -1 x9705 -1 x9804 >= -1;
+-1 x4 -1 x103 -1 x202 -1 x301 -1 x400 -1 x499 -1 x598 -1 x697 -1 x796 -1 x895 -1 x994 -1 x1093 -1 x1192 -1 x1291 -1 x1390 -1 x1489 -1 x1588 -1 x1687 -1 x1786 -1 x1885 -1 x1984 -1 x2083 -1 x2182 -1 x2281 -1 x2380 -1 x2479 -1 x2578 -1 x2677 -1 x2776 -1 x2875 -1 x2974 -1 x3073 -1 x3172 -1 x3271 -1 x3370 -1 x3469 -1 x3568 -1 x3667 -1 x3766 -1 x3865 -1 x3964 -1 x4063 -1 x4162 -1 x4261 -1 x4360 -1 x4459 -1 x4558 -1 x4657 -1 x4756 -1 x4855 -1 x4954 -1 x5053 -1 x5152 -1 x5251 -1 x5350 -1 x5449 -1 x5548 -1 x5647 -1 x5746 -1 x5845 -1 x5944 -1 x6043 -1 x6142 -1 x6241 -1 x6340 -1 x6439 -1 x6538 -1 x6637 -1 x6736 -1 x6835 -1 x6934 -1 x7033 -1 x7132 -1 x7231 -1 x7330 -1 x7429 -1 x7528 -1 x7627 -1 x7726 -1 x7825 -1 x7924 -1 x8023 -1 x8122 -1 x8221 -1 x8320 -1 x8419 -1 x8518 -1 x8617 -1 x8716 -1 x8815 -1 x8914 -1 x9013 -1 x9112 -1 x9211 -1 x9310 -1 x9409 -1 x9508 -1 x9607 -1 x9706 -1 x9805 >= -1;
+-1 x5 -1 x104 -1 x203 -1 x302 -1 x401 -1 x500 -1 x599 -1 x698 -1 x797 -1 x896 -1 x995 -1 x1094 -1 x1193 -1 x1292 -1 x1391 -1 x1490 -1 x1589 -1 x1688 -1 x1787 -1 x1886 -1 x1985 -1 x2084 -1 x2183 -1 x2282 -1 x2381 -1 x2480 -1 x2579 -1 x2678 -1 x2777 -1 x2876 -1 x2975 -1 x3074 -1 x3173 -1 x3272 -1 x3371 -1 x3470 -1 x3569 -1 x3668 -1 x3767 -1 x3866 -1 x3965 -1 x4064 -1 x4163 -1 x4262 -1 x4361 -1 x4460 -1 x4559 -1 x4658 -1 x4757 -1 x4856 -1 x4955 -1 x5054 -1 x5153 -1 x5252 -1 x5351 -1 x5450 -1 x5549 -1 x5648 -1 x5747 -1 x5846 -1 x5945 -1 x6044 -1 x6143 -1 x6242 -1 x6341 -1 x6440 -1 x6539 -1 x6638 -1 x6737 -1 x6836 -1 x6935 -1 x7034 -1 x7133 -1 x7232 -1 x7331 -1 x7430 -1 x7529 -1 x7628 -1 x7727 -1 x7826 -1 x7925 -1 x8024 -1 x8123 -1 x8222 -1 x8321 -1 x8420 -1 x8519 -1 x8618 -1 x8717 -1 x8816 -1 x8915 -1 x9014 -1 x9113 -1 x9212 -1 x9311 -1 x9410 -1 x9509 -1 x9608 -1 x9707 -1 x9806 >= -1;
+-1 x6 -1 x105 -1 x204 -1 x303 -1 x402 -1 x501 -1 x600 -1 x699 -1 x798 -1 x897 -1 x996 -1 x1095 -1 x1194 -1 x1293 -1 x1392 -1 x1491 -1 x1590 -1 x1689 -1 x1788 -1 x1887 -1 x1986 -1 x2085 -1 x2184 -1 x2283 -1 x2382 -1 x2481 -1 x2580 -1 x2679 -1 x2778 -1 x2877 -1 x2976 -1 x3075 -1 x3174 -1 x3273 -1 x3372 -1 x3471 -1 x3570 -1 x3669 -1 x3768 -1 x3867 -1 x3966 -1 x4065 -1 x4164 -1 x4263 -1 x4362 -1 x4461 -1 x4560 -1 x4659 -1 x4758 -1 x4857 -1 x4956 -1 x5055 -1 x5154 -1 x5253 -1 x5352 -1 x5451 -1 x5550 -1 x5649 -1 x5748 -1 x5847 -1 x5946 -1 x6045 -1 x6144 -1 x6243 -1 x6342 -1 x6441 -1 x6540 -1 x6639 -1 x6738 -1 x6837 -1 x6936 -1 x7035 -1 x7134 -1 x7233 -1 x7332 -1 x7431 -1 x7530 -1 x7629 -1 x7728 -1 x7827 -1 x7926 -1 x8025 -1 x8124 -1 x8223 -1 x8322 -1 x8421 -1 x8520 -1 x8619 -1 x8718 -1 x8817 -1 x8916 -1 x9015 -1 x9114 -1 x9213 -1 x9312 -1 x9411 -1 x9510 -1 x9609 -1 x9708 -1 x9807 >= -1;
+-1 x7 -1 x106 -1 x205 -1 x304 -1 x403 -1 x502 -1 x601 -1 x700 -1 x799 -1 x898 -1 x997 -1 x1096 -1 x1195 -1 x1294 -1 x1393 -1 x1492 -1 x1591 -1 x1690 -1 x1789 -1 x1888 -1 x1987 -1 x2086 -1 x2185 -1 x2284 -1 x2383 -1 x2482 -1 x2581 -1 x2680 -1 x2779 -1 x2878 -1 x2977 -1 x3076 -1 x3175 -1 x3274 -1 x3373 -1 x3472 -1 x3571 -1 x3670 -1 x3769 -1 x3868 -1 x3967 -1 x4066 -1 x4165 -1 x4264 -1 x4363 -1 x4462 -1 x4561 -1 x4660 -1 x4759 -1 x4858 -1 x4957 -1 x5056 -1 x5155 -1 x5254 -1 x5353 -1 x5452 -1 x5551 -1 x5650 -1 x5749 -1 x5848 -1 x5947 -1 x6046 -1 x6145 -1 x6244 -1 x6343 -1 x6442 -1 x6541 -1 x6640 -1 x6739 -1 x6838 -1 x6937 -1 x7036 -1 x7135 -1 x7234 -1 x7333 -1 x7432 -1 x7531 -1 x7630 -1 x7729 -1 x7828 -1 x7927 -1 x8026 -1 x8125 -1 x8224 -1 x8323 -1 x8422 -1 x8521 -1 x8620 -1 x8719 -1 x8818 -1 x8917 -1 x9016 -1 x9115 -1 x9214 -1 x9313 -1 x9412 -1 x9511 -1 x9610 -1 x9709 -1 x9808 >= -1;
+-1 x8 -1 x107 -1 x206 -1 x305 -1 x404 -1 x503 -1 x602 -1 x701 -1 x800 -1 x899 -1 x998 -1 x1097 -1 x1196 -1 x1295 -1 x1394 -1 x1493 -1 x1592 -1 x1691 -1 x1790 -1 x1889 -1 x1988 -1 x2087 -1 x2186 -1 x2285 -1 x2384 -1 x2483 -1 x2582 -1 x2681 -1 x2780 -1 x2879 -1 x2978 -1 x3077 -1 x3176 -1 x3275 -1 x3374 -1 x3473 -1 x3572 -1 x3671 -1 x3770 -1 x3869 -1 x3968 -1 x4067 -1 x4166 -1 x4265 -1 x4364 -1 x4463 -1 x4562 -1 x4661 -1 x4760 -1 x4859 -1 x4958 -1 x5057 -1 x5156 -1 x5255 -1 x5354 -1 x5453 -1 x5552 -1 x5651 -1 x5750 -1 x5849 -1 x5948 -1 x6047 -1 x6146 -1 x6245 -1 x6344 -1 x6443 -1 x6542 -1 x6641 -1 x6740 -1 x6839 -1 x6938 -1 x7037 -1 x7136 -1 x7235 -1 x7334 -1 x7433 -1 x7532 -1 x7631 -1 x7730 -1 x7829 -1 x7928 -1 x8027 -1 x8126 -1 x8225 -1 x8324 -1 x8423 -1 x8522 -1 x8621 -1 x8720 -1 x8819 -1 x8918 -1 x9017 -1 x9116 -1 x9215 -1 x9314 -1 x9413 -1 x9512 -1 x9611 -1 x9710 -1 x9809 >= -1;
+-1 x9 -1 x108 -1 x207 -1 x306 -1 x405 -1 x504 -1 x603 -1 x702 -1 x801 -1 x900 -1 x999 -1 x1098 -1 x1197 -1 x1296 -1 x1395 -1 x1494 -1 x1593 -1 x1692 -1 x1791 -1 x1890 -1 x1989 -1 x2088 -1 x2187 -1 x2286 -1 x2385 -1 x2484 -1 x2583 -1 x2682 -1 x2781 -1 x2880 -1 x2979 -1 x3078 -1 x3177 -1 x3276 -1 x3375 -1 x3474 -1 x3573 -1 x3672 -1 x3771 -1 x3870 -1 x3969 -1 x4068 -1 x4167 -1 x4266 -1 x4365 -1 x4464 -1 x4563 -1 x4662 -1 x4761 -1 x4860 -1 x4959 -1 x5058 -1 x5157 -1 x5256 -1 x5355 -1 x5454 -1 x5553 -1 x5652 -1 x5751 -1 x5850 -1 x5949 -1 x6048 -1 x6147 -1 x6246 -1 x6345 -1 x6444 -1 x6543 -1 x6642 -1 x6741 -1 x6840 -1 x6939 -1 x7038 -1 x7137 -1 x7236 -1 x7335 -1 x7434 -1 x7533 -1 x7632 -1 x7731 -1 x7830 -1 x7929 -1 x8028 -1 x8127 -1 x8226 -1 x8325 -1 x8424 -1 x8523 -1 x8622 -1 x8721 -1 x8820 -1 x8919 -1 x9018 -1 x9117 -1 x9216 -1 x9315 -1 x9414 -1 x9513 -1 x9612 -1 x9711 -1 x9810 >= -1;
+-1 x10 -1 x109 -1 x208 -1 x307 -1 x406 -1 x505 -1 x604 -1 x703 -1 x802 -1 x901 -1 x1000 -1 x1099 -1 x1198 -1 x1297 -1 x1396 -1 x1495 -1 x1594 -1 x1693 -1 x1792 -1 x1891 -1 x1990 -1 x2089 -1 x2188 -1 x2287 -1 x2386 -1 x2485 -1 x2584 -1 x2683 -1 x2782 -1 x2881 -1 x2980 -1 x3079 -1 x3178 -1 x3277 -1 x3376 -1 x3475 -1 x3574 -1 x3673 -1 x3772 -1 x3871 -1 x3970 -1 x4069 -1 x4168 -1 x4267 -1 x4366 -1 x4465 -1 x4564 -1 x4663 -1 x4762 -1 x4861 -1 x4960 -1 x5059 -1 x5158 -1 x5257 -1 x5356 -1 x5455 -1 x5554 -1 x5653 -1 x5752 -1 x5851 -1 x5950 -1 x6049 -1 x6148 -1 x6247 -1 x6346 -1 x6445 -1 x6544 -1 x6643 -1 x6742 -1 x6841 -1 x6940 -1 x7039 -1 x7138 -1 x7237 -1 x7336 -1 x7435 -1 x7534 -1 x7633 -1 x7732 -1 x7831 -1 x7930 -1 x8029 -1 x8128 -1 x8227 -1 x8326 -1 x8425 -1 x8524 -1 x8623 -1 x8722 -1 x8821 -1 x8920 -1 x9019 -1 x9118 -1 x9217 -1 x9316 -1 x9415 -1 x9514 -1 x9613 -1 x9712 -1 x9811 >= -1;
+-1 x11 -1 x110 -1 x209 -1 x308 -1 x407 -1 x506 -1 x605 -1 x704 -1 x803 -1 x902 -1 x1001 -1 x1100 -1 x1199 -1 x1298 -1 x1397 -1 x1496 -1 x1595 -1 x1694 -1 x1793 -1 x1892 -1 x1991 -1 x2090 -1 x2189 -1 x2288 -1 x2387 -1 x2486 -1 x2585 -1 x2684 -1 x2783 -1 x2882 -1 x2981 -1 x3080 -1 x3179 -1 x3278 -1 x3377 -1 x3476 -1 x3575 -1 x3674 -1 x3773 -1 x3872 -1 x3971 -1 x4070 -1 x4169 -1 x4268 -1 x4367 -1 x4466 -1 x4565 -1 x4664 -1 x4763 -1 x4862 -1 x4961 -1 x5060 -1 x5159 -1 x5258 -1 x5357 -1 x5456 -1 x5555 -1 x5654 -1 x5753 -1 x5852 -1 x5951 -1 x6050 -1 x6149 -1 x6248 -1 x6347 -1 x6446 -1 x6545 -1 x6644 -1 x6743 -1 x6842 -1 x6941 -1 x7040 -1 x7139 -1 x7238 -1 x7337 -1 x7436 -1 x7535 -1 x7634 -1 x7733 -1 x7832 -1 x7931 -1 x8030 -1 x8129 -1 x8228 -1 x8327 -1 x8426 -1 x8525 -1 x8624 -1 x8723 -1 x8822 -1 x8921 -1 x9020 -1 x9119 -1 x9218 -1 x9317 -1 x9416 -1 x9515 -1 x9614 -1 x9713 -1 x9812 >= -1;
+-1 x12 -1 x111 -1 x210 -1 x309 -1 x408 -1 x507 -1 x606 -1 x705 -1 x804 -1 x903 -1 x1002 -1 x1101 -1 x1200 -1 x1299 -1 x1398 -1 x1497 -1 x1596 -1 x1695 -1 x1794 -1 x1893 -1 x1992 -1 x2091 -1 x2190 -1 x2289 -1 x2388 -1 x2487 -1 x2586 -1 x2685 -1 x2784 -1 x2883 -1 x2982 -1 x3081 -1 x3180 -1 x3279 -1 x3378 -1 x3477 -1 x3576 -1 x3675 -1 x3774 -1 x3873 -1 x3972 -1 x4071 -1 x4170 -1 x4269 -1 x4368 -1 x4467 -1 x4566 -1 x4665 -1 x4764 -1 x4863 -1 x4962 -1 x5061 -1 x5160 -1 x5259 -1 x5358 -1 x5457 -1 x5556 -1 x5655 -1 x5754 -1 x5853 -1 x5952 -1 x6051 -1 x6150 -1 x6249 -1 x6348 -1 x6447 -1 x6546 -1 x6645 -1 x6744 -1 x6843 -1 x6942 -1 x7041 -1 x7140 -1 x7239 -1 x7338 -1 x7437 -1 x7536 -1 x7635 -1 x7734 -1 x7833 -1 x7932 -1 x8031 -1 x8130 -1 x8229 -1 x8328 -1 x8427 -1 x8526 -1 x8625 -1 x8724 -1 x8823 -1 x8922 -1 x9021 -1 x9120 -1 x9219 -1 x9318 -1 x9417 -1 x9516 -1 x9615 -1 x9714 -1 x9813 >= -1;
+-1 x13 -1 x112 -1 x211 -1 x310 -1 x409 -1 x508 -1 x607 -1 x706 -1 x805 -1 x904 -1 x1003 -1 x1102 -1 x1201 -1 x1300 -1 x1399 -1 x1498 -1 x1597 -1 x1696 -1 x1795 -1 x1894 -1 x1993 -1 x2092 -1 x2191 -1 x2290 -1 x2389 -1 x2488 -1 x2587 -1 x2686 -1 x2785 -1 x2884 -1 x2983 -1 x3082 -1 x3181 -1 x3280 -1 x3379 -1 x3478 -1 x3577 -1 x3676 -1 x3775 -1 x3874 -1 x3973 -1 x4072 -1 x4171 -1 x4270 -1 x4369 -1 x4468 -1 x4567 -1 x4666 -1 x4765 -1 x4864 -1 x4963 -1 x5062 -1 x5161 -1 x5260 -1 x5359 -1 x5458 -1 x5557 -1 x5656 -1 x5755 -1 x5854 -1 x5953 -1 x6052 -1 x6151 -1 x6250 -1 x6349 -1 x6448 -1 x6547 -1 x6646 -1 x6745 -1 x6844 -1 x6943 -1 x7042 -1 x7141 -1 x7240 -1 x7339 -1 x7438 -1 x7537 -1 x7636 -1 x7735 -1 x7834 -1 x7933 -1 x8032 -1 x8131 -1 x8230 -1 x8329 -1 x8428 -1 x8527 -1 x8626 -1 x8725 -1 x8824 -1 x8923 -1 x9022 -1 x9121 -1 x9220 -1 x9319 -1 x9418 -1 x9517 -1 x9616 -1 x9715 -1 x9814 >= -1;
+-1 x14 -1 x113 -1 x212 -1 x311 -1 x410 -1 x509 -1 x608 -1 x707 -1 x806 -1 x905 -1 x1004 -1 x1103 -1 x1202 -1 x1301 -1 x1400 -1 x1499 -1 x1598 -1 x1697 -1 x1796 -1 x1895 -1 x1994 -1 x2093 -1 x2192 -1 x2291 -1 x2390 -1 x2489 -1 x2588 -1 x2687 -1 x2786 -1 x2885 -1 x2984 -1 x3083 -1 x3182 -1 x3281 -1 x3380 -1 x3479 -1 x3578 -1 x3677 -1 x3776 -1 x3875 -1 x3974 -1 x4073 -1 x4172 -1 x4271 -1 x4370 -1 x4469 -1 x4568 -1 x4667 -1 x4766 -1 x4865 -1 x4964 -1 x5063 -1 x5162 -1 x5261 -1 x5360 -1 x5459 -1 x5558 -1 x5657 -1 x5756 -1 x5855 -1 x5954 -1 x6053 -1 x6152 -1 x6251 -1 x6350 -1 x6449 -1 x6548 -1 x6647 -1 x6746 -1 x6845 -1 x6944 -1 x7043 -1 x7142 -1 x7241 -1 x7340 -1 x7439 -1 x7538 -1 x7637 -1 x7736 -1 x7835 -1 x7934 -1 x8033 -1 x8132 -1 x8231 -1 x8330 -1 x8429 -1 x8528 -1 x8627 -1 x8726 -1 x8825 -1 x8924 -1 x9023 -1 x9122 -1 x9221 -1 x9320 -1 x9419 -1 x9518 -1 x9617 -1 x9716 -1 x9815 >= -1;
+-1 x15 -1 x114 -1 x213 -1 x312 -1 x411 -1 x510 -1 x609 -1 x708 -1 x807 -1 x906 -1 x1005 -1 x1104 -1 x1203 -1 x1302 -1 x1401 -1 x1500 -1 x1599 -1 x1698 -1 x1797 -1 x1896 -1 x1995 -1 x2094 -1 x2193 -1 x2292 -1 x2391 -1 x2490 -1 x2589 -1 x2688 -1 x2787 -1 x2886 -1 x2985 -1 x3084 -1 x3183 -1 x3282 -1 x3381 -1 x3480 -1 x3579 -1 x3678 -1 x3777 -1 x3876 -1 x3975 -1 x4074 -1 x4173 -1 x4272 -1 x4371 -1 x4470 -1 x4569 -1 x4668 -1 x4767 -1 x4866 -1 x4965 -1 x5064 -1 x5163 -1 x5262 -1 x5361 -1 x5460 -1 x5559 -1 x5658 -1 x5757 -1 x5856 -1 x5955 -1 x6054 -1 x6153 -1 x6252 -1 x6351 -1 x6450 -1 x6549 -1 x6648 -1 x6747 -1 x6846 -1 x6945 -1 x7044 -1 x7143 -1 x7242 -1 x7341 -1 x7440 -1 x7539 -1 x7638 -1 x7737 -1 x7836 -1 x7935 -1 x8034 -1 x8133 -1 x8232 -1 x8331 -1 x8430 -1 x8529 -1 x8628 -1 x8727 -1 x8826 -1 x8925 -1 x9024 -1 x9123 -1 x9222 -1 x9321 -1 x9420 -1 x9519 -1 x9618 -1 x9717 -1 x9816 >= -1;
+-1 x16 -1 x115 -1 x214 -1 x313 -1 x412 -1 x511 -1 x610 -1 x709 -1 x808 -1 x907 -1 x1006 -1 x1105 -1 x1204 -1 x1303 -1 x1402 -1 x1501 -1 x1600 -1 x1699 -1 x1798 -1 x1897 -1 x1996 -1 x2095 -1 x2194 -1 x2293 -1 x2392 -1 x2491 -1 x2590 -1 x2689 -1 x2788 -1 x2887 -1 x2986 -1 x3085 -1 x3184 -1 x3283 -1 x3382 -1 x3481 -1 x3580 -1 x3679 -1 x3778 -1 x3877 -1 x3976 -1 x4075 -1 x4174 -1 x4273 -1 x4372 -1 x4471 -1 x4570 -1 x4669 -1 x4768 -1 x4867 -1 x4966 -1 x5065 -1 x5164 -1 x5263 -1 x5362 -1 x5461 -1 x5560 -1 x5659 -1 x5758 -1 x5857 -1 x5956 -1 x6055 -1 x6154 -1 x6253 -1 x6352 -1 x6451 -1 x6550 -1 x6649 -1 x6748 -1 x6847 -1 x6946 -1 x7045 -1 x7144 -1 x7243 -1 x7342 -1 x7441 -1 x7540 -1 x7639 -1 x7738 -1 x7837 -1 x7936 -1 x8035 -1 x8134 -1 x8233 -1 x8332 -1 x8431 -1 x8530 -1 x8629 -1 x8728 -1 x8827 -1 x8926 -1 x9025 -1 x9124 -1 x9223 -1 x9322 -1 x9421 -1 x9520 -1 x9619 -1 x9718 -1 x9817 >= -1;
+-1 x17 -1 x116 -1 x215 -1 x314 -1 x413 -1 x512 -1 x611 -1 x710 -1 x809 -1 x908 -1 x1007 -1 x1106 -1 x1205 -1 x1304 -1 x1403 -1 x1502 -1 x1601 -1 x1700 -1 x1799 -1 x1898 -1 x1997 -1 x2096 -1 x2195 -1 x2294 -1 x2393 -1 x2492 -1 x2591 -1 x2690 -1 x2789 -1 x2888 -1 x2987 -1 x3086 -1 x3185 -1 x3284 -1 x3383 -1 x3482 -1 x3581 -1 x3680 -1 x3779 -1 x3878 -1 x3977 -1 x4076 -1 x4175 -1 x4274 -1 x4373 -1 x4472 -1 x4571 -1 x4670 -1 x4769 -1 x4868 -1 x4967 -1 x5066 -1 x5165 -1 x5264 -1 x5363 -1 x5462 -1 x5561 -1 x5660 -1 x5759 -1 x5858 -1 x5957 -1 x6056 -1 x6155 -1 x6254 -1 x6353 -1 x6452 -1 x6551 -1 x6650 -1 x6749 -1 x6848 -1 x6947 -1 x7046 -1 x7145 -1 x7244 -1 x7343 -1 x7442 -1 x7541 -1 x7640 -1 x7739 -1 x7838 -1 x7937 -1 x8036 -1 x8135 -1 x8234 -1 x8333 -1 x8432 -1 x8531 -1 x8630 -1 x8729 -1 x8828 -1 x8927 -1 x9026 -1 x9125 -1 x9224 -1 x9323 -1 x9422 -1 x9521 -1 x9620 -1 x9719 -1 x9818 >= -1;
+-1 x18 -1 x117 -1 x216 -1 x315 -1 x414 -1 x513 -1 x612 -1 x711 -1 x810 -1 x909 -1 x1008 -1 x1107 -1 x1206 -1 x1305 -1 x1404 -1 x1503 -1 x1602 -1 x1701 -1 x1800 -1 x1899 -1 x1998 -1 x2097 -1 x2196 -1 x2295 -1 x2394 -1 x2493 -1 x2592 -1 x2691 -1 x2790 -1 x2889 -1 x2988 -1 x3087 -1 x3186 -1 x3285 -1 x3384 -1 x3483 -1 x3582 -1 x3681 -1 x3780 -1 x3879 -1 x3978 -1 x4077 -1 x4176 -1 x4275 -1 x4374 -1 x4473 -1 x4572 -1 x4671 -1 x4770 -1 x4869 -1 x4968 -1 x5067 -1 x5166 -1 x5265 -1 x5364 -1 x5463 -1 x5562 -1 x5661 -1 x5760 -1 x5859 -1 x5958 -1 x6057 -1 x6156 -1 x6255 -1 x6354 -1 x6453 -1 x6552 -1 x6651 -1 x6750 -1 x6849 -1 x6948 -1 x7047 -1 x7146 -1 x7245 -1 x7344 -1 x7443 -1 x7542 -1 x7641 -1 x7740 -1 x7839 -1 x7938 -1 x8037 -1 x8136 -1 x8235 -1 x8334 -1 x8433 -1 x8532 -1 x8631 -1 x8730 -1 x8829 -1 x8928 -1 x9027 -1 x9126 -1 x9225 -1 x9324 -1 x9423 -1 x9522 -1 x9621 -1 x9720 -1 x9819 >= -1;
+-1 x19 -1 x118 -1 x217 -1 x316 -1 x415 -1 x514 -1 x613 -1 x712 -1 x811 -1 x910 -1 x1009 -1 x1108 -1 x1207 -1 x1306 -1 x1405 -1 x1504 -1 x1603 -1 x1702 -1 x1801 -1 x1900 -1 x1999 -1 x2098 -1 x2197 -1 x2296 -1 x2395 -1 x2494 -1 x2593 -1 x2692 -1 x2791 -1 x2890 -1 x2989 -1 x3088 -1 x3187 -1 x3286 -1 x3385 -1 x3484 -1 x3583 -1 x3682 -1 x3781 -1 x3880 -1 x3979 -1 x4078 -1 x4177 -1 x4276 -1 x4375 -1 x4474 -1 x4573 -1 x4672 -1 x4771 -1 x4870 -1 x4969 -1 x5068 -1 x5167 -1 x5266 -1 x5365 -1 x5464 -1 x5563 -1 x5662 -1 x5761 -1 x5860 -1 x5959 -1 x6058 -1 x6157 -1 x6256 -1 x6355 -1 x6454 -1 x6553 -1 x6652 -1 x6751 -1 x6850 -1 x6949 -1 x7048 -1 x7147 -1 x7246 -1 x7345 -1 x7444 -1 x7543 -1 x7642 -1 x7741 -1 x7840 -1 x7939 -1 x8038 -1 x8137 -1 x8236 -1 x8335 -1 x8434 -1 x8533 -1 x8632 -1 x8731 -1 x8830 -1 x8929 -1 x9028 -1 x9127 -1 x9226 -1 x9325 -1 x9424 -1 x9523 -1 x9622 -1 x9721 -1 x9820 >= -1;
+-1 x20 -1 x119 -1 x218 -1 x317 -1 x416 -1 x515 -1 x614 -1 x713 -1 x812 -1 x911 -1 x1010 -1 x1109 -1 x1208 -1 x1307 -1 x1406 -1 x1505 -1 x1604 -1 x1703 -1 x1802 -1 x1901 -1 x2000 -1 x2099 -1 x2198 -1 x2297 -1 x2396 -1 x2495 -1 x2594 -1 x2693 -1 x2792 -1 x2891 -1 x2990 -1 x3089 -1 x3188 -1 x3287 -1 x3386 -1 x3485 -1 x3584 -1 x3683 -1 x3782 -1 x3881 -1 x3980 -1 x4079 -1 x4178 -1 x4277 -1 x4376 -1 x4475 -1 x4574 -1 x4673 -1 x4772 -1 x4871 -1 x4970 -1 x5069 -1 x5168 -1 x5267 -1 x5366 -1 x5465 -1 x5564 -1 x5663 -1 x5762 -1 x5861 -1 x5960 -1 x6059 -1 x6158 -1 x6257 -1 x6356 -1 x6455 -1 x6554 -1 x6653 -1 x6752 -1 x6851 -1 x6950 -1 x7049 -1 x7148 -1 x7247 -1 x7346 -1 x7445 -1 x7544 -1 x7643 -1 x7742 -1 x7841 -1 x7940 -1 x8039 -1 x8138 -1 x8237 -1 x8336 -1 x8435 -1 x8534 -1 x8633 -1 x8732 -1 x8831 -1 x8930 -1 x9029 -1 x9128 -1 x9227 -1 x9326 -1 x9425 -1 x9524 -1 x9623 -1 x9722 -1 x9821 >= -1;
+-1 x21 -1 x120 -1 x219 -1 x318 -1 x417 -1 x516 -1 x615 -1 x714 -1 x813 -1 x912 -1 x1011 -1 x1110 -1 x1209 -1 x1308 -1 x1407 -1 x1506 -1 x1605 -1 x1704 -1 x1803 -1 x1902 -1 x2001 -1 x2100 -1 x2199 -1 x2298 -1 x2397 -1 x2496 -1 x2595 -1 x2694 -1 x2793 -1 x2892 -1 x2991 -1 x3090 -1 x3189 -1 x3288 -1 x3387 -1 x3486 -1 x3585 -1 x3684 -1 x3783 -1 x3882 -1 x3981 -1 x4080 -1 x4179 -1 x4278 -1 x4377 -1 x4476 -1 x4575 -1 x4674 -1 x4773 -1 x4872 -1 x4971 -1 x5070 -1 x5169 -1 x5268 -1 x5367 -1 x5466 -1 x5565 -1 x5664 -1 x5763 -1 x5862 -1 x5961 -1 x6060 -1 x6159 -1 x6258 -1 x6357 -1 x6456 -1 x6555 -1 x6654 -1 x6753 -1 x6852 -1 x6951 -1 x7050 -1 x7149 -1 x7248 -1 x7347 -1 x7446 -1 x7545 -1 x7644 -1 x7743 -1 x7842 -1 x7941 -1 x8040 -1 x8139 -1 x8238 -1 x8337 -1 x8436 -1 x8535 -1 x8634 -1 x8733 -1 x8832 -1 x8931 -1 x9030 -1 x9129 -1 x9228 -1 x9327 -1 x9426 -1 x9525 -1 x9624 -1 x9723 -1 x9822 >= -1;
+-1 x22 -1 x121 -1 x220 -1 x319 -1 x418 -1 x517 -1 x616 -1 x715 -1 x814 -1 x913 -1 x1012 -1 x1111 -1 x1210 -1 x1309 -1 x1408 -1 x1507 -1 x1606 -1 x1705 -1 x1804 -1 x1903 -1 x2002 -1 x2101 -1 x2200 -1 x2299 -1 x2398 -1 x2497 -1 x2596 -1 x2695 -1 x2794 -1 x2893 -1 x2992 -1 x3091 -1 x3190 -1 x3289 -1 x3388 -1 x3487 -1 x3586 -1 x3685 -1 x3784 -1 x3883 -1 x3982 -1 x4081 -1 x4180 -1 x4279 -1 x4378 -1 x4477 -1 x4576 -1 x4675 -1 x4774 -1 x4873 -1 x4972 -1 x5071 -1 x5170 -1 x5269 -1 x5368 -1 x5467 -1 x5566 -1 x5665 -1 x5764 -1 x5863 -1 x5962 -1 x6061 -1 x6160 -1 x6259 -1 x6358 -1 x6457 -1 x6556 -1 x6655 -1 x6754 -1 x6853 -1 x6952 -1 x7051 -1 x7150 -1 x7249 -1 x7348 -1 x7447 -1 x7546 -1 x7645 -1 x7744 -1 x7843 -1 x7942 -1 x8041 -1 x8140 -1 x8239 -1 x8338 -1 x8437 -1 x8536 -1 x8635 -1 x8734 -1 x8833 -1 x8932 -1 x9031 -1 x9130 -1 x9229 -1 x9328 -1 x9427 -1 x9526 -1 x9625 -1 x9724 -1 x9823 >= -1;
+-1 x23 -1 x122 -1 x221 -1 x320 -1 x419 -1 x518 -1 x617 -1 x716 -1 x815 -1 x914 -1 x1013 -1 x1112 -1 x1211 -1 x1310 -1 x1409 -1 x1508 -1 x1607 -1 x1706 -1 x1805 -1 x1904 -1 x2003 -1 x2102 -1 x2201 -1 x2300 -1 x2399 -1 x2498 -1 x2597 -1 x2696 -1 x2795 -1 x2894 -1 x2993 -1 x3092 -1 x3191 -1 x3290 -1 x3389 -1 x3488 -1 x3587 -1 x3686 -1 x3785 -1 x3884 -1 x3983 -1 x4082 -1 x4181 -1 x4280 -1 x4379 -1 x4478 -1 x4577 -1 x4676 -1 x4775 -1 x4874 -1 x4973 -1 x5072 -1 x5171 -1 x5270 -1 x5369 -1 x5468 -1 x5567 -1 x5666 -1 x5765 -1 x5864 -1 x5963 -1 x6062 -1 x6161 -1 x6260 -1 x6359 -1 x6458 -1 x6557 -1 x6656 -1 x6755 -1 x6854 -1 x6953 -1 x7052 -1 x7151 -1 x7250 -1 x7349 -1 x7448 -1 x7547 -1 x7646 -1 x7745 -1 x7844 -1 x7943 -1 x8042 -1 x8141 -1 x8240 -1 x8339 -1 x8438 -1 x8537 -1 x8636 -1 x8735 -1 x8834 -1 x8933 -1 x9032 -1 x9131 -1 x9230 -1 x9329 -1 x9428 -1 x9527 -1 x9626 -1 x9725 -1 x9824 >= -1;
+-1 x24 -1 x123 -1 x222 -1 x321 -1 x420 -1 x519 -1 x618 -1 x717 -1 x816 -1 x915 -1 x1014 -1 x1113 -1 x1212 -1 x1311 -1 x1410 -1 x1509 -1 x1608 -1 x1707 -1 x1806 -1 x1905 -1 x2004 -1 x2103 -1 x2202 -1 x2301 -1 x2400 -1 x2499 -1 x2598 -1 x2697 -1 x2796 -1 x2895 -1 x2994 -1 x3093 -1 x3192 -1 x3291 -1 x3390 -1 x3489 -1 x3588 -1 x3687 -1 x3786 -1 x3885 -1 x3984 -1 x4083 -1 x4182 -1 x4281 -1 x4380 -1 x4479 -1 x4578 -1 x4677 -1 x4776 -1 x4875 -1 x4974 -1 x5073 -1 x5172 -1 x5271 -1 x5370 -1 x5469 -1 x5568 -1 x5667 -1 x5766 -1 x5865 -1 x5964 -1 x6063 -1 x6162 -1 x6261 -1 x6360 -1 x6459 -1 x6558 -1 x6657 -1 x6756 -1 x6855 -1 x6954 -1 x7053 -1 x7152 -1 x7251 -1 x7350 -1 x7449 -1 x7548 -1 x7647 -1 x7746 -1 x7845 -1 x7944 -1 x8043 -1 x8142 -1 x8241 -1 x8340 -1 x8439 -1 x8538 -1 x8637 -1 x8736 -1 x8835 -1 x8934 -1 x9033 -1 x9132 -1 x9231 -1 x9330 -1 x9429 -1 x9528 -1 x9627 -1 x9726 -1 x9825 >= -1;
+-1 x25 -1 x124 -1 x223 -1 x322 -1 x421 -1 x520 -1 x619 -1 x718 -1 x817 -1 x916 -1 x1015 -1 x1114 -1 x1213 -1 x1312 -1 x1411 -1 x1510 -1 x1609 -1 x1708 -1 x1807 -1 x1906 -1 x2005 -1 x2104 -1 x2203 -1 x2302 -1 x2401 -1 x2500 -1 x2599 -1 x2698 -1 x2797 -1 x2896 -1 x2995 -1 x3094 -1 x3193 -1 x3292 -1 x3391 -1 x3490 -1 x3589 -1 x3688 -1 x3787 -1 x3886 -1 x3985 -1 x4084 -1 x4183 -1 x4282 -1 x4381 -1 x4480 -1 x4579 -1 x4678 -1 x4777 -1 x4876 -1 x4975 -1 x5074 -1 x5173 -1 x5272 -1 x5371 -1 x5470 -1 x5569 -1 x5668 -1 x5767 -1 x5866 -1 x5965 -1 x6064 -1 x6163 -1 x6262 -1 x6361 -1 x6460 -1 x6559 -1 x6658 -1 x6757 -1 x6856 -1 x6955 -1 x7054 -1 x7153 -1 x7252 -1 x7351 -1 x7450 -1 x7549 -1 x7648 -1 x7747 -1 x7846 -1 x7945 -1 x8044 -1 x8143 -1 x8242 -1 x8341 -1 x8440 -1 x8539 -1 x8638 -1 x8737 -1 x8836 -1 x8935 -1 x9034 -1 x9133 -1 x9232 -1 x9331 -1 x9430 -1 x9529 -1 x9628 -1 x9727 -1 x9826 >= -1;
+-1 x26 -1 x125 -1 x224 -1 x323 -1 x422 -1 x521 -1 x620 -1 x719 -1 x818 -1 x917 -1 x1016 -1 x1115 -1 x1214 -1 x1313 -1 x1412 -1 x1511 -1 x1610 -1 x1709 -1 x1808 -1 x1907 -1 x2006 -1 x2105 -1 x2204 -1 x2303 -1 x2402 -1 x2501 -1 x2600 -1 x2699 -1 x2798 -1 x2897 -1 x2996 -1 x3095 -1 x3194 -1 x3293 -1 x3392 -1 x3491 -1 x3590 -1 x3689 -1 x3788 -1 x3887 -1 x3986 -1 x4085 -1 x4184 -1 x4283 -1 x4382 -1 x4481 -1 x4580 -1 x4679 -1 x4778 -1 x4877 -1 x4976 -1 x5075 -1 x5174 -1 x5273 -1 x5372 -1 x5471 -1 x5570 -1 x5669 -1 x5768 -1 x5867 -1 x5966 -1 x6065 -1 x6164 -1 x6263 -1 x6362 -1 x6461 -1 x6560 -1 x6659 -1 x6758 -1 x6857 -1 x6956 -1 x7055 -1 x7154 -1 x7253 -1 x7352 -1 x7451 -1 x7550 -1 x7649 -1 x7748 -1 x7847 -1 x7946 -1 x8045 -1 x8144 -1 x8243 -1 x8342 -1 x8441 -1 x8540 -1 x8639 -1 x8738 -1 x8837 -1 x8936 -1 x9035 -1 x9134 -1 x9233 -1 x9332 -1 x9431 -1 x9530 -1 x9629 -1 x9728 -1 x9827 >= -1;
+-1 x27 -1 x126 -1 x225 -1 x324 -1 x423 -1 x522 -1 x621 -1 x720 -1 x819 -1 x918 -1 x1017 -1 x1116 -1 x1215 -1 x1314 -1 x1413 -1 x1512 -1 x1611 -1 x1710 -1 x1809 -1 x1908 -1 x2007 -1 x2106 -1 x2205 -1 x2304 -1 x2403 -1 x2502 -1 x2601 -1 x2700 -1 x2799 -1 x2898 -1 x2997 -1 x3096 -1 x3195 -1 x3294 -1 x3393 -1 x3492 -1 x3591 -1 x3690 -1 x3789 -1 x3888 -1 x3987 -1 x4086 -1 x4185 -1 x4284 -1 x4383 -1 x4482 -1 x4581 -1 x4680 -1 x4779 -1 x4878 -1 x4977 -1 x5076 -1 x5175 -1 x5274 -1 x5373 -1 x5472 -1 x5571 -1 x5670 -1 x5769 -1 x5868 -1 x5967 -1 x6066 -1 x6165 -1 x6264 -1 x6363 -1 x6462 -1 x6561 -1 x6660 -1 x6759 -1 x6858 -1 x6957 -1 x7056 -1 x7155 -1 x7254 -1 x7353 -1 x7452 -1 x7551 -1 x7650 -1 x7749 -1 x7848 -1 x7947 -1 x8046 -1 x8145 -1 x8244 -1 x8343 -1 x8442 -1 x8541 -1 x8640 -1 x8739 -1 x8838 -1 x8937 -1 x9036 -1 x9135 -1 x9234 -1 x9333 -1 x9432 -1 x9531 -1 x9630 -1 x9729 -1 x9828 >= -1;
+-1 x28 -1 x127 -1 x226 -1 x325 -1 x424 -1 x523 -1 x622 -1 x721 -1 x820 -1 x919 -1 x1018 -1 x1117 -1 x1216 -1 x1315 -1 x1414 -1 x1513 -1 x1612 -1 x1711 -1 x1810 -1 x1909 -1 x2008 -1 x2107 -1 x2206 -1 x2305 -1 x2404 -1 x2503 -1 x2602 -1 x2701 -1 x2800 -1 x2899 -1 x2998 -1 x3097 -1 x3196 -1 x3295 -1 x3394 -1 x3493 -1 x3592 -1 x3691 -1 x3790 -1 x3889 -1 x3988 -1 x4087 -1 x4186 -1 x4285 -1 x4384 -1 x4483 -1 x4582 -1 x4681 -1 x4780 -1 x4879 -1 x4978 -1 x5077 -1 x5176 -1 x5275 -1 x5374 -1 x5473 -1 x5572 -1 x5671 -1 x5770 -1 x5869 -1 x5968 -1 x6067 -1 x6166 -1 x6265 -1 x6364 -1 x6463 -1 x6562 -1 x6661 -1 x6760 -1 x6859 -1 x6958 -1 x7057 -1 x7156 -1 x7255 -1 x7354 -1 x7453 -1 x7552 -1 x7651 -1 x7750 -1 x7849 -1 x7948 -1 x8047 -1 x8146 -1 x8245 -1 x8344 -1 x8443 -1 x8542 -1 x8641 -1 x8740 -1 x8839 -1 x8938 -1 x9037 -1 x9136 -1 x9235 -1 x9334 -1 x9433 -1 x9532 -1 x9631 -1 x9730 -1 x9829 >= -1;
+-1 x29 -1 x128 -1 x227 -1 x326 -1 x425 -1 x524 -1 x623 -1 x722 -1 x821 -1 x920 -1 x1019 -1 x1118 -1 x1217 -1 x1316 -1 x1415 -1 x1514 -1 x1613 -1 x1712 -1 x1811 -1 x1910 -1 x2009 -1 x2108 -1 x2207 -1 x2306 -1 x2405 -1 x2504 -1 x2603 -1 x2702 -1 x2801 -1 x2900 -1 x2999 -1 x3098 -1 x3197 -1 x3296 -1 x3395 -1 x3494 -1 x3593 -1 x3692 -1 x3791 -1 x3890 -1 x3989 -1 x4088 -1 x4187 -1 x4286 -1 x4385 -1 x4484 -1 x4583 -1 x4682 -1 x4781 -1 x4880 -1 x4979 -1 x5078 -1 x5177 -1 x5276 -1 x5375 -1 x5474 -1 x5573 -1 x5672 -1 x5771 -1 x5870 -1 x5969 -1 x6068 -1 x6167 -1 x6266 -1 x6365 -1 x6464 -1 x6563 -1 x6662 -1 x6761 -1 x6860 -1 x6959 -1 x7058 -1 x7157 -1 x7256 -1 x7355 -1 x7454 -1 x7553 -1 x7652 -1 x7751 -1 x7850 -1 x7949 -1 x8048 -1 x8147 -1 x8246 -1 x8345 -1 x8444 -1 x8543 -1 x8642 -1 x8741 -1 x8840 -1 x8939 -1 x9038 -1 x9137 -1 x9236 -1 x9335 -1 x9434 -1 x9533 -1 x9632 -1 x9731 -1 x9830 >= -1;
+-1 x30 -1 x129 -1 x228 -1 x327 -1 x426 -1 x525 -1 x624 -1 x723 -1 x822 -1 x921 -1 x1020 -1 x1119 -1 x1218 -1 x1317 -1 x1416 -1 x1515 -1 x1614 -1 x1713 -1 x1812 -1 x1911 -1 x2010 -1 x2109 -1 x2208 -1 x2307 -1 x2406 -1 x2505 -1 x2604 -1 x2703 -1 x2802 -1 x2901 -1 x3000 -1 x3099 -1 x3198 -1 x3297 -1 x3396 -1 x3495 -1 x3594 -1 x3693 -1 x3792 -1 x3891 -1 x3990 -1 x4089 -1 x4188 -1 x4287 -1 x4386 -1 x4485 -1 x4584 -1 x4683 -1 x4782 -1 x4881 -1 x4980 -1 x5079 -1 x5178 -1 x5277 -1 x5376 -1 x5475 -1 x5574 -1 x5673 -1 x5772 -1 x5871 -1 x5970 -1 x6069 -1 x6168 -1 x6267 -1 x6366 -1 x6465 -1 x6564 -1 x6663 -1 x6762 -1 x6861 -1 x6960 -1 x7059 -1 x7158 -1 x7257 -1 x7356 -1 x7455 -1 x7554 -1 x7653 -1 x7752 -1 x7851 -1 x7950 -1 x8049 -1 x8148 -1 x8247 -1 x8346 -1 x8445 -1 x8544 -1 x8643 -1 x8742 -1 x8841 -1 x8940 -1 x9039 -1 x9138 -1 x9237 -1 x9336 -1 x9435 -1 x9534 -1 x9633 -1 x9732 -1 x9831 >= -1;
+-1 x31 -1 x130 -1 x229 -1 x328 -1 x427 -1 x526 -1 x625 -1 x724 -1 x823 -1 x922 -1 x1021 -1 x1120 -1 x1219 -1 x1318 -1 x1417 -1 x1516 -1 x1615 -1 x1714 -1 x1813 -1 x1912 -1 x2011 -1 x2110 -1 x2209 -1 x2308 -1 x2407 -1 x2506 -1 x2605 -1 x2704 -1 x2803 -1 x2902 -1 x3001 -1 x3100 -1 x3199 -1 x3298 -1 x3397 -1 x3496 -1 x3595 -1 x3694 -1 x3793 -1 x3892 -1 x3991 -1 x4090 -1 x4189 -1 x4288 -1 x4387 -1 x4486 -1 x4585 -1 x4684 -1 x4783 -1 x4882 -1 x4981 -1 x5080 -1 x5179 -1 x5278 -1 x5377 -1 x5476 -1 x5575 -1 x5674 -1 x5773 -1 x5872 -1 x5971 -1 x6070 -1 x6169 -1 x6268 -1 x6367 -1 x6466 -1 x6565 -1 x6664 -1 x6763 -1 x6862 -1 x6961 -1 x7060 -1 x7159 -1 x7258 -1 x7357 -1 x7456 -1 x7555 -1 x7654 -1 x7753 -1 x7852 -1 x7951 -1 x8050 -1 x8149 -1 x8248 -1 x8347 -1 x8446 -1 x8545 -1 x8644 -1 x8743 -1 x8842 -1 x8941 -1 x9040 -1 x9139 -1 x9238 -1 x9337 -1 x9436 -1 x9535 -1 x9634 -1 x9733 -1 x9832 >= -1;
+-1 x32 -1 x131 -1 x230 -1 x329 -1 x428 -1 x527 -1 x626 -1 x725 -1 x824 -1 x923 -1 x1022 -1 x1121 -1 x1220 -1 x1319 -1 x1418 -1 x1517 -1 x1616 -1 x1715 -1 x1814 -1 x1913 -1 x2012 -1 x2111 -1 x2210 -1 x2309 -1 x2408 -1 x2507 -1 x2606 -1 x2705 -1 x2804 -1 x2903 -1 x3002 -1 x3101 -1 x3200 -1 x3299 -1 x3398 -1 x3497 -1 x3596 -1 x3695 -1 x3794 -1 x3893 -1 x3992 -1 x4091 -1 x4190 -1 x4289 -1 x4388 -1 x4487 -1 x4586 -1 x4685 -1 x4784 -1 x4883 -1 x4982 -1 x5081 -1 x5180 -1 x5279 -1 x5378 -1 x5477 -1 x5576 -1 x5675 -1 x5774 -1 x5873 -1 x5972 -1 x6071 -1 x6170 -1 x6269 -1 x6368 -1 x6467 -1 x6566 -1 x6665 -1 x6764 -1 x6863 -1 x6962 -1 x7061 -1 x7160 -1 x7259 -1 x7358 -1 x7457 -1 x7556 -1 x7655 -1 x7754 -1 x7853 -1 x7952 -1 x8051 -1 x8150 -1 x8249 -1 x8348 -1 x8447 -1 x8546 -1 x8645 -1 x8744 -1 x8843 -1 x8942 -1 x9041 -1 x9140 -1 x9239 -1 x9338 -1 x9437 -1 x9536 -1 x9635 -1 x9734 -1 x9833 >= -1;
+-1 x33 -1 x132 -1 x231 -1 x330 -1 x429 -1 x528 -1 x627 -1 x726 -1 x825 -1 x924 -1 x1023 -1 x1122 -1 x1221 -1 x1320 -1 x1419 -1 x1518 -1 x1617 -1 x1716 -1 x1815 -1 x1914 -1 x2013 -1 x2112 -1 x2211 -1 x2310 -1 x2409 -1 x2508 -1 x2607 -1 x2706 -1 x2805 -1 x2904 -1 x3003 -1 x3102 -1 x3201 -1 x3300 -1 x3399 -1 x3498 -1 x3597 -1 x3696 -1 x3795 -1 x3894 -1 x3993 -1 x4092 -1 x4191 -1 x4290 -1 x4389 -1 x4488 -1 x4587 -1 x4686 -1 x4785 -1 x4884 -1 x4983 -1 x5082 -1 x5181 -1 x5280 -1 x5379 -1 x5478 -1 x5577 -1 x5676 -1 x5775 -1 x5874 -1 x5973 -1 x6072 -1 x6171 -1 x6270 -1 x6369 -1 x6468 -1 x6567 -1 x6666 -1 x6765 -1 x6864 -1 x6963 -1 x7062 -1 x7161 -1 x7260 -1 x7359 -1 x7458 -1 x7557 -1 x7656 -1 x7755 -1 x7854 -1 x7953 -1 x8052 -1 x8151 -1 x8250 -1 x8349 -1 x8448 -1 x8547 -1 x8646 -1 x8745 -1 x8844 -1 x8943 -1 x9042 -1 x9141 -1 x9240 -1 x9339 -1 x9438 -1 x9537 -1 x9636 -1 x9735 -1 x9834 >= -1;
+-1 x34 -1 x133 -1 x232 -1 x331 -1 x430 -1 x529 -1 x628 -1 x727 -1 x826 -1 x925 -1 x1024 -1 x1123 -1 x1222 -1 x1321 -1 x1420 -1 x1519 -1 x1618 -1 x1717 -1 x1816 -1 x1915 -1 x2014 -1 x2113 -1 x2212 -1 x2311 -1 x2410 -1 x2509 -1 x2608 -1 x2707 -1 x2806 -1 x2905 -1 x3004 -1 x3103 -1 x3202 -1 x3301 -1 x3400 -1 x3499 -1 x3598 -1 x3697 -1 x3796 -1 x3895 -1 x3994 -1 x4093 -1 x4192 -1 x4291 -1 x4390 -1 x4489 -1 x4588 -1 x4687 -1 x4786 -1 x4885 -1 x4984 -1 x5083 -1 x5182 -1 x5281 -1 x5380 -1 x5479 -1 x5578 -1 x5677 -1 x5776 -1 x5875 -1 x5974 -1 x6073 -1 x6172 -1 x6271 -1 x6370 -1 x6469 -1 x6568 -1 x6667 -1 x6766 -1 x6865 -1 x6964 -1 x7063 -1 x7162 -1 x7261 -1 x7360 -1 x7459 -1 x7558 -1 x7657 -1 x7756 -1 x7855 -1 x7954 -1 x8053 -1 x8152 -1 x8251 -1 x8350 -1 x8449 -1 x8548 -1 x8647 -1 x8746 -1 x8845 -1 x8944 -1 x9043 -1 x9142 -1 x9241 -1 x9340 -1 x9439 -1 x9538 -1 x9637 -1 x9736 -1 x9835 >= -1;
+-1 x35 -1 x134 -1 x233 -1 x332 -1 x431 -1 x530 -1 x629 -1 x728 -1 x827 -1 x926 -1 x1025 -1 x1124 -1 x1223 -1 x1322 -1 x1421 -1 x1520 -1 x1619 -1 x1718 -1 x1817 -1 x1916 -1 x2015 -1 x2114 -1 x2213 -1 x2312 -1 x2411 -1 x2510 -1 x2609 -1 x2708 -1 x2807 -1 x2906 -1 x3005 -1 x3104 -1 x3203 -1 x3302 -1 x3401 -1 x3500 -1 x3599 -1 x3698 -1 x3797 -1 x3896 -1 x3995 -1 x4094 -1 x4193 -1 x4292 -1 x4391 -1 x4490 -1 x4589 -1 x4688 -1 x4787 -1 x4886 -1 x4985 -1 x5084 -1 x5183 -1 x5282 -1 x5381 -1 x5480 -1 x5579 -1 x5678 -1 x5777 -1 x5876 -1 x5975 -1 x6074 -1 x6173 -1 x6272 -1 x6371 -1 x6470 -1 x6569 -1 x6668 -1 x6767 -1 x6866 -1 x6965 -1 x7064 -1 x7163 -1 x7262 -1 x7361 -1 x7460 -1 x7559 -1 x7658 -1 x7757 -1 x7856 -1 x7955 -1 x8054 -1 x8153 -1 x8252 -1 x8351 -1 x8450 -1 x8549 -1 x8648 -1 x8747 -1 x8846 -1 x8945 -1 x9044 -1 x9143 -1 x9242 -1 x9341 -1 x9440 -1 x9539 -1 x9638 -1 x9737 -1 x9836 >= -1;
+-1 x36 -1 x135 -1 x234 -1 x333 -1 x432 -1 x531 -1 x630 -1 x729 -1 x828 -1 x927 -1 x1026 -1 x1125 -1 x1224 -1 x1323 -1 x1422 -1 x1521 -1 x1620 -1 x1719 -1 x1818 -1 x1917 -1 x2016 -1 x2115 -1 x2214 -1 x2313 -1 x2412 -1 x2511 -1 x2610 -1 x2709 -1 x2808 -1 x2907 -1 x3006 -1 x3105 -1 x3204 -1 x3303 -1 x3402 -1 x3501 -1 x3600 -1 x3699 -1 x3798 -1 x3897 -1 x3996 -1 x4095 -1 x4194 -1 x4293 -1 x4392 -1 x4491 -1 x4590 -1 x4689 -1 x4788 -1 x4887 -1 x4986 -1 x5085 -1 x5184 -1 x5283 -1 x5382 -1 x5481 -1 x5580 -1 x5679 -1 x5778 -1 x5877 -1 x5976 -1 x6075 -1 x6174 -1 x6273 -1 x6372 -1 x6471 -1 x6570 -1 x6669 -1 x6768 -1 x6867 -1 x6966 -1 x7065 -1 x7164 -1 x7263 -1 x7362 -1 x7461 -1 x7560 -1 x7659 -1 x7758 -1 x7857 -1 x7956 -1 x8055 -1 x8154 -1 x8253 -1 x8352 -1 x8451 -1 x8550 -1 x8649 -1 x8748 -1 x8847 -1 x8946 -1 x9045 -1 x9144 -1 x9243 -1 x9342 -1 x9441 -1 x9540 -1 x9639 -1 x9738 -1 x9837 >= -1;
+-1 x37 -1 x136 -1 x235 -1 x334 -1 x433 -1 x532 -1 x631 -1 x730 -1 x829 -1 x928 -1 x1027 -1 x1126 -1 x1225 -1 x1324 -1 x1423 -1 x1522 -1 x1621 -1 x1720 -1 x1819 -1 x1918 -1 x2017 -1 x2116 -1 x2215 -1 x2314 -1 x2413 -1 x2512 -1 x2611 -1 x2710 -1 x2809 -1 x2908 -1 x3007 -1 x3106 -1 x3205 -1 x3304 -1 x3403 -1 x3502 -1 x3601 -1 x3700 -1 x3799 -1 x3898 -1 x3997 -1 x4096 -1 x4195 -1 x4294 -1 x4393 -1 x4492 -1 x4591 -1 x4690 -1 x4789 -1 x4888 -1 x4987 -1 x5086 -1 x5185 -1 x5284 -1 x5383 -1 x5482 -1 x5581 -1 x5680 -1 x5779 -1 x5878 -1 x5977 -1 x6076 -1 x6175 -1 x6274 -1 x6373 -1 x6472 -1 x6571 -1 x6670 -1 x6769 -1 x6868 -1 x6967 -1 x7066 -1 x7165 -1 x7264 -1 x7363 -1 x7462 -1 x7561 -1 x7660 -1 x7759 -1 x7858 -1 x7957 -1 x8056 -1 x8155 -1 x8254 -1 x8353 -1 x8452 -1 x8551 -1 x8650 -1 x8749 -1 x8848 -1 x8947 -1 x9046 -1 x9145 -1 x9244 -1 x9343 -1 x9442 -1 x9541 -1 x9640 -1 x9739 -1 x9838 >= -1;
+-1 x38 -1 x137 -1 x236 -1 x335 -1 x434 -1 x533 -1 x632 -1 x731 -1 x830 -1 x929 -1 x1028 -1 x1127 -1 x1226 -1 x1325 -1 x1424 -1 x1523 -1 x1622 -1 x1721 -1 x1820 -1 x1919 -1 x2018 -1 x2117 -1 x2216 -1 x2315 -1 x2414 -1 x2513 -1 x2612 -1 x2711 -1 x2810 -1 x2909 -1 x3008 -1 x3107 -1 x3206 -1 x3305 -1 x3404 -1 x3503 -1 x3602 -1 x3701 -1 x3800 -1 x3899 -1 x3998 -1 x4097 -1 x4196 -1 x4295 -1 x4394 -1 x4493 -1 x4592 -1 x4691 -1 x4790 -1 x4889 -1 x4988 -1 x5087 -1 x5186 -1 x5285 -1 x5384 -1 x5483 -1 x5582 -1 x5681 -1 x5780 -1 x5879 -1 x5978 -1 x6077 -1 x6176 -1 x6275 -1 x6374 -1 x6473 -1 x6572 -1 x6671 -1 x6770 -1 x6869 -1 x6968 -1 x7067 -1 x7166 -1 x7265 -1 x7364 -1 x7463 -1 x7562 -1 x7661 -1 x7760 -1 x7859 -1 x7958 -1 x8057 -1 x8156 -1 x8255 -1 x8354 -1 x8453 -1 x8552 -1 x8651 -1 x8750 -1 x8849 -1 x8948 -1 x9047 -1 x9146 -1 x9245 -1 x9344 -1 x9443 -1 x9542 -1 x9641 -1 x9740 -1 x9839 >= -1;
+-1 x39 -1 x138 -1 x237 -1 x336 -1 x435 -1 x534 -1 x633 -1 x732 -1 x831 -1 x930 -1 x1029 -1 x1128 -1 x1227 -1 x1326 -1 x1425 -1 x1524 -1 x1623 -1 x1722 -1 x1821 -1 x1920 -1 x2019 -1 x2118 -1 x2217 -1 x2316 -1 x2415 -1 x2514 -1 x2613 -1 x2712 -1 x2811 -1 x2910 -1 x3009 -1 x3108 -1 x3207 -1 x3306 -1 x3405 -1 x3504 -1 x3603 -1 x3702 -1 x3801 -1 x3900 -1 x3999 -1 x4098 -1 x4197 -1 x4296 -1 x4395 -1 x4494 -1 x4593 -1 x4692 -1 x4791 -1 x4890 -1 x4989 -1 x5088 -1 x5187 -1 x5286 -1 x5385 -1 x5484 -1 x5583 -1 x5682 -1 x5781 -1 x5880 -1 x5979 -1 x6078 -1 x6177 -1 x6276 -1 x6375 -1 x6474 -1 x6573 -1 x6672 -1 x6771 -1 x6870 -1 x6969 -1 x7068 -1 x7167 -1 x7266 -1 x7365 -1 x7464 -1 x7563 -1 x7662 -1 x7761 -1 x7860 -1 x7959 -1 x8058 -1 x8157 -1 x8256 -1 x8355 -1 x8454 -1 x8553 -1 x8652 -1 x8751 -1 x8850 -1 x8949 -1 x9048 -1 x9147 -1 x9246 -1 x9345 -1 x9444 -1 x9543 -1 x9642 -1 x9741 -1 x9840 >= -1;
+-1 x40 -1 x139 -1 x238 -1 x337 -1 x436 -1 x535 -1 x634 -1 x733 -1 x832 -1 x931 -1 x1030 -1 x1129 -1 x1228 -1 x1327 -1 x1426 -1 x1525 -1 x1624 -1 x1723 -1 x1822 -1 x1921 -1 x2020 -1 x2119 -1 x2218 -1 x2317 -1 x2416 -1 x2515 -1 x2614 -1 x2713 -1 x2812 -1 x2911 -1 x3010 -1 x3109 -1 x3208 -1 x3307 -1 x3406 -1 x3505 -1 x3604 -1 x3703 -1 x3802 -1 x3901 -1 x4000 -1 x4099 -1 x4198 -1 x4297 -1 x4396 -1 x4495 -1 x4594 -1 x4693 -1 x4792 -1 x4891 -1 x4990 -1 x5089 -1 x5188 -1 x5287 -1 x5386 -1 x5485 -1 x5584 -1 x5683 -1 x5782 -1 x5881 -1 x5980 -1 x6079 -1 x6178 -1 x6277 -1 x6376 -1 x6475 -1 x6574 -1 x6673 -1 x6772 -1 x6871 -1 x6970 -1 x7069 -1 x7168 -1 x7267 -1 x7366 -1 x7465 -1 x7564 -1 x7663 -1 x7762 -1 x7861 -1 x7960 -1 x8059 -1 x8158 -1 x8257 -1 x8356 -1 x8455 -1 x8554 -1 x8653 -1 x8752 -1 x8851 -1 x8950 -1 x9049 -1 x9148 -1 x9247 -1 x9346 -1 x9445 -1 x9544 -1 x9643 -1 x9742 -1 x9841 >= -1;
+-1 x41 -1 x140 -1 x239 -1 x338 -1 x437 -1 x536 -1 x635 -1 x734 -1 x833 -1 x932 -1 x1031 -1 x1130 -1 x1229 -1 x1328 -1 x1427 -1 x1526 -1 x1625 -1 x1724 -1 x1823 -1 x1922 -1 x2021 -1 x2120 -1 x2219 -1 x2318 -1 x2417 -1 x2516 -1 x2615 -1 x2714 -1 x2813 -1 x2912 -1 x3011 -1 x3110 -1 x3209 -1 x3308 -1 x3407 -1 x3506 -1 x3605 -1 x3704 -1 x3803 -1 x3902 -1 x4001 -1 x4100 -1 x4199 -1 x4298 -1 x4397 -1 x4496 -1 x4595 -1 x4694 -1 x4793 -1 x4892 -1 x4991 -1 x5090 -1 x5189 -1 x5288 -1 x5387 -1 x5486 -1 x5585 -1 x5684 -1 x5783 -1 x5882 -1 x5981 -1 x6080 -1 x6179 -1 x6278 -1 x6377 -1 x6476 -1 x6575 -1 x6674 -1 x6773 -1 x6872 -1 x6971 -1 x7070 -1 x7169 -1 x7268 -1 x7367 -1 x7466 -1 x7565 -1 x7664 -1 x7763 -1 x7862 -1 x7961 -1 x8060 -1 x8159 -1 x8258 -1 x8357 -1 x8456 -1 x8555 -1 x8654 -1 x8753 -1 x8852 -1 x8951 -1 x9050 -1 x9149 -1 x9248 -1 x9347 -1 x9446 -1 x9545 -1 x9644 -1 x9743 -1 x9842 >= -1;
+-1 x42 -1 x141 -1 x240 -1 x339 -1 x438 -1 x537 -1 x636 -1 x735 -1 x834 -1 x933 -1 x1032 -1 x1131 -1 x1230 -1 x1329 -1 x1428 -1 x1527 -1 x1626 -1 x1725 -1 x1824 -1 x1923 -1 x2022 -1 x2121 -1 x2220 -1 x2319 -1 x2418 -1 x2517 -1 x2616 -1 x2715 -1 x2814 -1 x2913 -1 x3012 -1 x3111 -1 x3210 -1 x3309 -1 x3408 -1 x3507 -1 x3606 -1 x3705 -1 x3804 -1 x3903 -1 x4002 -1 x4101 -1 x4200 -1 x4299 -1 x4398 -1 x4497 -1 x4596 -1 x4695 -1 x4794 -1 x4893 -1 x4992 -1 x5091 -1 x5190 -1 x5289 -1 x5388 -1 x5487 -1 x5586 -1 x5685 -1 x5784 -1 x5883 -1 x5982 -1 x6081 -1 x6180 -1 x6279 -1 x6378 -1 x6477 -1 x6576 -1 x6675 -1 x6774 -1 x6873 -1 x6972 -1 x7071 -1 x7170 -1 x7269 -1 x7368 -1 x7467 -1 x7566 -1 x7665 -1 x7764 -1 x7863 -1 x7962 -1 x8061 -1 x8160 -1 x8259 -1 x8358 -1 x8457 -1 x8556 -1 x8655 -1 x8754 -1 x8853 -1 x8952 -1 x9051 -1 x9150 -1 x9249 -1 x9348 -1 x9447 -1 x9546 -1 x9645 -1 x9744 -1 x9843 >= -1;
+-1 x43 -1 x142 -1 x241 -1 x340 -1 x439 -1 x538 -1 x637 -1 x736 -1 x835 -1 x934 -1 x1033 -1 x1132 -1 x1231 -1 x1330 -1 x1429 -1 x1528 -1 x1627 -1 x1726 -1 x1825 -1 x1924 -1 x2023 -1 x2122 -1 x2221 -1 x2320 -1 x2419 -1 x2518 -1 x2617 -1 x2716 -1 x2815 -1 x2914 -1 x3013 -1 x3112 -1 x3211 -1 x3310 -1 x3409 -1 x3508 -1 x3607 -1 x3706 -1 x3805 -1 x3904 -1 x4003 -1 x4102 -1 x4201 -1 x4300 -1 x4399 -1 x4498 -1 x4597 -1 x4696 -1 x4795 -1 x4894 -1 x4993 -1 x5092 -1 x5191 -1 x5290 -1 x5389 -1 x5488 -1 x5587 -1 x5686 -1 x5785 -1 x5884 -1 x5983 -1 x6082 -1 x6181 -1 x6280 -1 x6379 -1 x6478 -1 x6577 -1 x6676 -1 x6775 -1 x6874 -1 x6973 -1 x7072 -1 x7171 -1 x7270 -1 x7369 -1 x7468 -1 x7567 -1 x7666 -1 x7765 -1 x7864 -1 x7963 -1 x8062 -1 x8161 -1 x8260 -1 x8359 -1 x8458 -1 x8557 -1 x8656 -1 x8755 -1 x8854 -1 x8953 -1 x9052 -1 x9151 -1 x9250 -1 x9349 -1 x9448 -1 x9547 -1 x9646 -1 x9745 -1 x9844 >= -1;
+-1 x44 -1 x143 -1 x242 -1 x341 -1 x440 -1 x539 -1 x638 -1 x737 -1 x836 -1 x935 -1 x1034 -1 x1133 -1 x1232 -1 x1331 -1 x1430 -1 x1529 -1 x1628 -1 x1727 -1 x1826 -1 x1925 -1 x2024 -1 x2123 -1 x2222 -1 x2321 -1 x2420 -1 x2519 -1 x2618 -1 x2717 -1 x2816 -1 x2915 -1 x3014 -1 x3113 -1 x3212 -1 x3311 -1 x3410 -1 x3509 -1 x3608 -1 x3707 -1 x3806 -1 x3905 -1 x4004 -1 x4103 -1 x4202 -1 x4301 -1 x4400 -1 x4499 -1 x4598 -1 x4697 -1 x4796 -1 x4895 -1 x4994 -1 x5093 -1 x5192 -1 x5291 -1 x5390 -1 x5489 -1 x5588 -1 x5687 -1 x5786 -1 x5885 -1 x5984 -1 x6083 -1 x6182 -1 x6281 -1 x6380 -1 x6479 -1 x6578 -1 x6677 -1 x6776 -1 x6875 -1 x6974 -1 x7073 -1 x7172 -1 x7271 -1 x7370 -1 x7469 -1 x7568 -1 x7667 -1 x7766 -1 x7865 -1 x7964 -1 x8063 -1 x8162 -1 x8261 -1 x8360 -1 x8459 -1 x8558 -1 x8657 -1 x8756 -1 x8855 -1 x8954 -1 x9053 -1 x9152 -1 x9251 -1 x9350 -1 x9449 -1 x9548 -1 x9647 -1 x9746 -1 x9845 >= -1;
+-1 x45 -1 x144 -1 x243 -1 x342 -1 x441 -1 x540 -1 x639 -1 x738 -1 x837 -1 x936 -1 x1035 -1 x1134 -1 x1233 -1 x1332 -1 x1431 -1 x1530 -1 x1629 -1 x1728 -1 x1827 -1 x1926 -1 x2025 -1 x2124 -1 x2223 -1 x2322 -1 x2421 -1 x2520 -1 x2619 -1 x2718 -1 x2817 -1 x2916 -1 x3015 -1 x3114 -1 x3213 -1 x3312 -1 x3411 -1 x3510 -1 x3609 -1 x3708 -1 x3807 -1 x3906 -1 x4005 -1 x4104 -1 x4203 -1 x4302 -1 x4401 -1 x4500 -1 x4599 -1 x4698 -1 x4797 -1 x4896 -1 x4995 -1 x5094 -1 x5193 -1 x5292 -1 x5391 -1 x5490 -1 x5589 -1 x5688 -1 x5787 -1 x5886 -1 x5985 -1 x6084 -1 x6183 -1 x6282 -1 x6381 -1 x6480 -1 x6579 -1 x6678 -1 x6777 -1 x6876 -1 x6975 -1 x7074 -1 x7173 -1 x7272 -1 x7371 -1 x7470 -1 x7569 -1 x7668 -1 x7767 -1 x7866 -1 x7965 -1 x8064 -1 x8163 -1 x8262 -1 x8361 -1 x8460 -1 x8559 -1 x8658 -1 x8757 -1 x8856 -1 x8955 -1 x9054 -1 x9153 -1 x9252 -1 x9351 -1 x9450 -1 x9549 -1 x9648 -1 x9747 -1 x9846 >= -1;
+-1 x46 -1 x145 -1 x244 -1 x343 -1 x442 -1 x541 -1 x640 -1 x739 -1 x838 -1 x937 -1 x1036 -1 x1135 -1 x1234 -1 x1333 -1 x1432 -1 x1531 -1 x1630 -1 x1729 -1 x1828 -1 x1927 -1 x2026 -1 x2125 -1 x2224 -1 x2323 -1 x2422 -1 x2521 -1 x2620 -1 x2719 -1 x2818 -1 x2917 -1 x3016 -1 x3115 -1 x3214 -1 x3313 -1 x3412 -1 x3511 -1 x3610 -1 x3709 -1 x3808 -1 x3907 -1 x4006 -1 x4105 -1 x4204 -1 x4303 -1 x4402 -1 x4501 -1 x4600 -1 x4699 -1 x4798 -1 x4897 -1 x4996 -1 x5095 -1 x5194 -1 x5293 -1 x5392 -1 x5491 -1 x5590 -1 x5689 -1 x5788 -1 x5887 -1 x5986 -1 x6085 -1 x6184 -1 x6283 -1 x6382 -1 x6481 -1 x6580 -1 x6679 -1 x6778 -1 x6877 -1 x6976 -1 x7075 -1 x7174 -1 x7273 -1 x7372 -1 x7471 -1 x7570 -1 x7669 -1 x7768 -1 x7867 -1 x7966 -1 x8065 -1 x8164 -1 x8263 -1 x8362 -1 x8461 -1 x8560 -1 x8659 -1 x8758 -1 x8857 -1 x8956 -1 x9055 -1 x9154 -1 x9253 -1 x9352 -1 x9451 -1 x9550 -1 x9649 -1 x9748 -1 x9847 >= -1;
+-1 x47 -1 x146 -1 x245 -1 x344 -1 x443 -1 x542 -1 x641 -1 x740 -1 x839 -1 x938 -1 x1037 -1 x1136 -1 x1235 -1 x1334 -1 x1433 -1 x1532 -1 x1631 -1 x1730 -1 x1829 -1 x1928 -1 x2027 -1 x2126 -1 x2225 -1 x2324 -1 x2423 -1 x2522 -1 x2621 -1 x2720 -1 x2819 -1 x2918 -1 x3017 -1 x3116 -1 x3215 -1 x3314 -1 x3413 -1 x3512 -1 x3611 -1 x3710 -1 x3809 -1 x3908 -1 x4007 -1 x4106 -1 x4205 -1 x4304 -1 x4403 -1 x4502 -1 x4601 -1 x4700 -1 x4799 -1 x4898 -1 x4997 -1 x5096 -1 x5195 -1 x5294 -1 x5393 -1 x5492 -1 x5591 -1 x5690 -1 x5789 -1 x5888 -1 x5987 -1 x6086 -1 x6185 -1 x6284 -1 x6383 -1 x6482 -1 x6581 -1 x6680 -1 x6779 -1 x6878 -1 x6977 -1 x7076 -1 x7175 -1 x7274 -1 x7373 -1 x7472 -1 x7571 -1 x7670 -1 x7769 -1 x7868 -1 x7967 -1 x8066 -1 x8165 -1 x8264 -1 x8363 -1 x8462 -1 x8561 -1 x8660 -1 x8759 -1 x8858 -1 x8957 -1 x9056 -1 x9155 -1 x9254 -1 x9353 -1 x9452 -1 x9551 -1 x9650 -1 x9749 -1 x9848 >= -1;
+-1 x48 -1 x147 -1 x246 -1 x345 -1 x444 -1 x543 -1 x642 -1 x741 -1 x840 -1 x939 -1 x1038 -1 x1137 -1 x1236 -1 x1335 -1 x1434 -1 x1533 -1 x1632 -1 x1731 -1 x1830 -1 x1929 -1 x2028 -1 x2127 -1 x2226 -1 x2325 -1 x2424 -1 x2523 -1 x2622 -1 x2721 -1 x2820 -1 x2919 -1 x3018 -1 x3117 -1 x3216 -1 x3315 -1 x3414 -1 x3513 -1 x3612 -1 x3711 -1 x3810 -1 x3909 -1 x4008 -1 x4107 -1 x4206 -1 x4305 -1 x4404 -1 x4503 -1 x4602 -1 x4701 -1 x4800 -1 x4899 -1 x4998 -1 x5097 -1 x5196 -1 x5295 -1 x5394 -1 x5493 -1 x5592 -1 x5691 -1 x5790 -1 x5889 -1 x5988 -1 x6087 -1 x6186 -1 x6285 -1 x6384 -1 x6483 -1 x6582 -1 x6681 -1 x6780 -1 x6879 -1 x6978 -1 x7077 -1 x7176 -1 x7275 -1 x7374 -1 x7473 -1 x7572 -1 x7671 -1 x7770 -1 x7869 -1 x7968 -1 x8067 -1 x8166 -1 x8265 -1 x8364 -1 x8463 -1 x8562 -1 x8661 -1 x8760 -1 x8859 -1 x8958 -1 x9057 -1 x9156 -1 x9255 -1 x9354 -1 x9453 -1 x9552 -1 x9651 -1 x9750 -1 x9849 >= -1;
+-1 x49 -1 x148 -1 x247 -1 x346 -1 x445 -1 x544 -1 x643 -1 x742 -1 x841 -1 x940 -1 x1039 -1 x1138 -1 x1237 -1 x1336 -1 x1435 -1 x1534 -1 x1633 -1 x1732 -1 x1831 -1 x1930 -1 x2029 -1 x2128 -1 x2227 -1 x2326 -1 x2425 -1 x2524 -1 x2623 -1 x2722 -1 x2821 -1 x2920 -1 x3019 -1 x3118 -1 x3217 -1 x3316 -1 x3415 -1 x3514 -1 x3613 -1 x3712 -1 x3811 -1 x3910 -1 x4009 -1 x4108 -1 x4207 -1 x4306 -1 x4405 -1 x4504 -1 x4603 -1 x4702 -1 x4801 -1 x4900 -1 x4999 -1 x5098 -1 x5197 -1 x5296 -1 x5395 -1 x5494 -1 x5593 -1 x5692 -1 x5791 -1 x5890 -1 x5989 -1 x6088 -1 x6187 -1 x6286 -1 x6385 -1 x6484 -1 x6583 -1 x6682 -1 x6781 -1 x6880 -1 x6979 -1 x7078 -1 x7177 -1 x7276 -1 x7375 -1 x7474 -1 x7573 -1 x7672 -1 x7771 -1 x7870 -1 x7969 -1 x8068 -1 x8167 -1 x8266 -1 x8365 -1 x8464 -1 x8563 -1 x8662 -1 x8761 -1 x8860 -1 x8959 -1 x9058 -1 x9157 -1 x9256 -1 x9355 -1 x9454 -1 x9553 -1 x9652 -1 x9751 -1 x9850 >= -1;
+-1 x50 -1 x149 -1 x248 -1 x347 -1 x446 -1 x545 -1 x644 -1 x743 -1 x842 -1 x941 -1 x1040 -1 x1139 -1 x1238 -1 x1337 -1 x1436 -1 x1535 -1 x1634 -1 x1733 -1 x1832 -1 x1931 -1 x2030 -1 x2129 -1 x2228 -1 x2327 -1 x2426 -1 x2525 -1 x2624 -1 x2723 -1 x2822 -1 x2921 -1 x3020 -1 x3119 -1 x3218 -1 x3317 -1 x3416 -1 x3515 -1 x3614 -1 x3713 -1 x3812 -1 x3911 -1 x4010 -1 x4109 -1 x4208 -1 x4307 -1 x4406 -1 x4505 -1 x4604 -1 x4703 -1 x4802 -1 x4901 -1 x5000 -1 x5099 -1 x5198 -1 x5297 -1 x5396 -1 x5495 -1 x5594 -1 x5693 -1 x5792 -1 x5891 -1 x5990 -1 x6089 -1 x6188 -1 x6287 -1 x6386 -1 x6485 -1 x6584 -1 x6683 -1 x6782 -1 x6881 -1 x6980 -1 x7079 -1 x7178 -1 x7277 -1 x7376 -1 x7475 -1 x7574 -1 x7673 -1 x7772 -1 x7871 -1 x7970 -1 x8069 -1 x8168 -1 x8267 -1 x8366 -1 x8465 -1 x8564 -1 x8663 -1 x8762 -1 x8861 -1 x8960 -1 x9059 -1 x9158 -1 x9257 -1 x9356 -1 x9455 -1 x9554 -1 x9653 -1 x9752 -1 x9851 >= -1;
+-1 x51 -1 x150 -1 x249 -1 x348 -1 x447 -1 x546 -1 x645 -1 x744 -1 x843 -1 x942 -1 x1041 -1 x1140 -1 x1239 -1 x1338 -1 x1437 -1 x1536 -1 x1635 -1 x1734 -1 x1833 -1 x1932 -1 x2031 -1 x2130 -1 x2229 -1 x2328 -1 x2427 -1 x2526 -1 x2625 -1 x2724 -1 x2823 -1 x2922 -1 x3021 -1 x3120 -1 x3219 -1 x3318 -1 x3417 -1 x3516 -1 x3615 -1 x3714 -1 x3813 -1 x3912 -1 x4011 -1 x4110 -1 x4209 -1 x4308 -1 x4407 -1 x4506 -1 x4605 -1 x4704 -1 x4803 -1 x4902 -1 x5001 -1 x5100 -1 x5199 -1 x5298 -1 x5397 -1 x5496 -1 x5595 -1 x5694 -1 x5793 -1 x5892 -1 x5991 -1 x6090 -1 x6189 -1 x6288 -1 x6387 -1 x6486 -1 x6585 -1 x6684 -1 x6783 -1 x6882 -1 x6981 -1 x7080 -1 x7179 -1 x7278 -1 x7377 -1 x7476 -1 x7575 -1 x7674 -1 x7773 -1 x7872 -1 x7971 -1 x8070 -1 x8169 -1 x8268 -1 x8367 -1 x8466 -1 x8565 -1 x8664 -1 x8763 -1 x8862 -1 x8961 -1 x9060 -1 x9159 -1 x9258 -1 x9357 -1 x9456 -1 x9555 -1 x9654 -1 x9753 -1 x9852 >= -1;
+-1 x52 -1 x151 -1 x250 -1 x349 -1 x448 -1 x547 -1 x646 -1 x745 -1 x844 -1 x943 -1 x1042 -1 x1141 -1 x1240 -1 x1339 -1 x1438 -1 x1537 -1 x1636 -1 x1735 -1 x1834 -1 x1933 -1 x2032 -1 x2131 -1 x2230 -1 x2329 -1 x2428 -1 x2527 -1 x2626 -1 x2725 -1 x2824 -1 x2923 -1 x3022 -1 x3121 -1 x3220 -1 x3319 -1 x3418 -1 x3517 -1 x3616 -1 x3715 -1 x3814 -1 x3913 -1 x4012 -1 x4111 -1 x4210 -1 x4309 -1 x4408 -1 x4507 -1 x4606 -1 x4705 -1 x4804 -1 x4903 -1 x5002 -1 x5101 -1 x5200 -1 x5299 -1 x5398 -1 x5497 -1 x5596 -1 x5695 -1 x5794 -1 x5893 -1 x5992 -1 x6091 -1 x6190 -1 x6289 -1 x6388 -1 x6487 -1 x6586 -1 x6685 -1 x6784 -1 x6883 -1 x6982 -1 x7081 -1 x7180 -1 x7279 -1 x7378 -1 x7477 -1 x7576 -1 x7675 -1 x7774 -1 x7873 -1 x7972 -1 x8071 -1 x8170 -1 x8269 -1 x8368 -1 x8467 -1 x8566 -1 x8665 -1 x8764 -1 x8863 -1 x8962 -1 x9061 -1 x9160 -1 x9259 -1 x9358 -1 x9457 -1 x9556 -1 x9655 -1 x9754 -1 x9853 >= -1;
+-1 x53 -1 x152 -1 x251 -1 x350 -1 x449 -1 x548 -1 x647 -1 x746 -1 x845 -1 x944 -1 x1043 -1 x1142 -1 x1241 -1 x1340 -1 x1439 -1 x1538 -1 x1637 -1 x1736 -1 x1835 -1 x1934 -1 x2033 -1 x2132 -1 x2231 -1 x2330 -1 x2429 -1 x2528 -1 x2627 -1 x2726 -1 x2825 -1 x2924 -1 x3023 -1 x3122 -1 x3221 -1 x3320 -1 x3419 -1 x3518 -1 x3617 -1 x3716 -1 x3815 -1 x3914 -1 x4013 -1 x4112 -1 x4211 -1 x4310 -1 x4409 -1 x4508 -1 x4607 -1 x4706 -1 x4805 -1 x4904 -1 x5003 -1 x5102 -1 x5201 -1 x5300 -1 x5399 -1 x5498 -1 x5597 -1 x5696 -1 x5795 -1 x5894 -1 x5993 -1 x6092 -1 x6191 -1 x6290 -1 x6389 -1 x6488 -1 x6587 -1 x6686 -1 x6785 -1 x6884 -1 x6983 -1 x7082 -1 x7181 -1 x7280 -1 x7379 -1 x7478 -1 x7577 -1 x7676 -1 x7775 -1 x7874 -1 x7973 -1 x8072 -1 x8171 -1 x8270 -1 x8369 -1 x8468 -1 x8567 -1 x8666 -1 x8765 -1 x8864 -1 x8963 -1 x9062 -1 x9161 -1 x9260 -1 x9359 -1 x9458 -1 x9557 -1 x9656 -1 x9755 -1 x9854 >= -1;
+-1 x54 -1 x153 -1 x252 -1 x351 -1 x450 -1 x549 -1 x648 -1 x747 -1 x846 -1 x945 -1 x1044 -1 x1143 -1 x1242 -1 x1341 -1 x1440 -1 x1539 -1 x1638 -1 x1737 -1 x1836 -1 x1935 -1 x2034 -1 x2133 -1 x2232 -1 x2331 -1 x2430 -1 x2529 -1 x2628 -1 x2727 -1 x2826 -1 x2925 -1 x3024 -1 x3123 -1 x3222 -1 x3321 -1 x3420 -1 x3519 -1 x3618 -1 x3717 -1 x3816 -1 x3915 -1 x4014 -1 x4113 -1 x4212 -1 x4311 -1 x4410 -1 x4509 -1 x4608 -1 x4707 -1 x4806 -1 x4905 -1 x5004 -1 x5103 -1 x5202 -1 x5301 -1 x5400 -1 x5499 -1 x5598 -1 x5697 -1 x5796 -1 x5895 -1 x5994 -1 x6093 -1 x6192 -1 x6291 -1 x6390 -1 x6489 -1 x6588 -1 x6687 -1 x6786 -1 x6885 -1 x6984 -1 x7083 -1 x7182 -1 x7281 -1 x7380 -1 x7479 -1 x7578 -1 x7677 -1 x7776 -1 x7875 -1 x7974 -1 x8073 -1 x8172 -1 x8271 -1 x8370 -1 x8469 -1 x8568 -1 x8667 -1 x8766 -1 x8865 -1 x8964 -1 x9063 -1 x9162 -1 x9261 -1 x9360 -1 x9459 -1 x9558 -1 x9657 -1 x9756 -1 x9855 >= -1;
+-1 x55 -1 x154 -1 x253 -1 x352 -1 x451 -1 x550 -1 x649 -1 x748 -1 x847 -1 x946 -1 x1045 -1 x1144 -1 x1243 -1 x1342 -1 x1441 -1 x1540 -1 x1639 -1 x1738 -1 x1837 -1 x1936 -1 x2035 -1 x2134 -1 x2233 -1 x2332 -1 x2431 -1 x2530 -1 x2629 -1 x2728 -1 x2827 -1 x2926 -1 x3025 -1 x3124 -1 x3223 -1 x3322 -1 x3421 -1 x3520 -1 x3619 -1 x3718 -1 x3817 -1 x3916 -1 x4015 -1 x4114 -1 x4213 -1 x4312 -1 x4411 -1 x4510 -1 x4609 -1 x4708 -1 x4807 -1 x4906 -1 x5005 -1 x5104 -1 x5203 -1 x5302 -1 x5401 -1 x5500 -1 x5599 -1 x5698 -1 x5797 -1 x5896 -1 x5995 -1 x6094 -1 x6193 -1 x6292 -1 x6391 -1 x6490 -1 x6589 -1 x6688 -1 x6787 -1 x6886 -1 x6985 -1 x7084 -1 x7183 -1 x7282 -1 x7381 -1 x7480 -1 x7579 -1 x7678 -1 x7777 -1 x7876 -1 x7975 -1 x8074 -1 x8173 -1 x8272 -1 x8371 -1 x8470 -1 x8569 -1 x8668 -1 x8767 -1 x8866 -1 x8965 -1 x9064 -1 x9163 -1 x9262 -1 x9361 -1 x9460 -1 x9559 -1 x9658 -1 x9757 -1 x9856 >= -1;
+-1 x56 -1 x155 -1 x254 -1 x353 -1 x452 -1 x551 -1 x650 -1 x749 -1 x848 -1 x947 -1 x1046 -1 x1145 -1 x1244 -1 x1343 -1 x1442 -1 x1541 -1 x1640 -1 x1739 -1 x1838 -1 x1937 -1 x2036 -1 x2135 -1 x2234 -1 x2333 -1 x2432 -1 x2531 -1 x2630 -1 x2729 -1 x2828 -1 x2927 -1 x3026 -1 x3125 -1 x3224 -1 x3323 -1 x3422 -1 x3521 -1 x3620 -1 x3719 -1 x3818 -1 x3917 -1 x4016 -1 x4115 -1 x4214 -1 x4313 -1 x4412 -1 x4511 -1 x4610 -1 x4709 -1 x4808 -1 x4907 -1 x5006 -1 x5105 -1 x5204 -1 x5303 -1 x5402 -1 x5501 -1 x5600 -1 x5699 -1 x5798 -1 x5897 -1 x5996 -1 x6095 -1 x6194 -1 x6293 -1 x6392 -1 x6491 -1 x6590 -1 x6689 -1 x6788 -1 x6887 -1 x6986 -1 x7085 -1 x7184 -1 x7283 -1 x7382 -1 x7481 -1 x7580 -1 x7679 -1 x7778 -1 x7877 -1 x7976 -1 x8075 -1 x8174 -1 x8273 -1 x8372 -1 x8471 -1 x8570 -1 x8669 -1 x8768 -1 x8867 -1 x8966 -1 x9065 -1 x9164 -1 x9263 -1 x9362 -1 x9461 -1 x9560 -1 x9659 -1 x9758 -1 x9857 >= -1;
+-1 x57 -1 x156 -1 x255 -1 x354 -1 x453 -1 x552 -1 x651 -1 x750 -1 x849 -1 x948 -1 x1047 -1 x1146 -1 x1245 -1 x1344 -1 x1443 -1 x1542 -1 x1641 -1 x1740 -1 x1839 -1 x1938 -1 x2037 -1 x2136 -1 x2235 -1 x2334 -1 x2433 -1 x2532 -1 x2631 -1 x2730 -1 x2829 -1 x2928 -1 x3027 -1 x3126 -1 x3225 -1 x3324 -1 x3423 -1 x3522 -1 x3621 -1 x3720 -1 x3819 -1 x3918 -1 x4017 -1 x4116 -1 x4215 -1 x4314 -1 x4413 -1 x4512 -1 x4611 -1 x4710 -1 x4809 -1 x4908 -1 x5007 -1 x5106 -1 x5205 -1 x5304 -1 x5403 -1 x5502 -1 x5601 -1 x5700 -1 x5799 -1 x5898 -1 x5997 -1 x6096 -1 x6195 -1 x6294 -1 x6393 -1 x6492 -1 x6591 -1 x6690 -1 x6789 -1 x6888 -1 x6987 -1 x7086 -1 x7185 -1 x7284 -1 x7383 -1 x7482 -1 x7581 -1 x7680 -1 x7779 -1 x7878 -1 x7977 -1 x8076 -1 x8175 -1 x8274 -1 x8373 -1 x8472 -1 x8571 -1 x8670 -1 x8769 -1 x8868 -1 x8967 -1 x9066 -1 x9165 -1 x9264 -1 x9363 -1 x9462 -1 x9561 -1 x9660 -1 x9759 -1 x9858 >= -1;
+-1 x58 -1 x157 -1 x256 -1 x355 -1 x454 -1 x553 -1 x652 -1 x751 -1 x850 -1 x949 -1 x1048 -1 x1147 -1 x1246 -1 x1345 -1 x1444 -1 x1543 -1 x1642 -1 x1741 -1 x1840 -1 x1939 -1 x2038 -1 x2137 -1 x2236 -1 x2335 -1 x2434 -1 x2533 -1 x2632 -1 x2731 -1 x2830 -1 x2929 -1 x3028 -1 x3127 -1 x3226 -1 x3325 -1 x3424 -1 x3523 -1 x3622 -1 x3721 -1 x3820 -1 x3919 -1 x4018 -1 x4117 -1 x4216 -1 x4315 -1 x4414 -1 x4513 -1 x4612 -1 x4711 -1 x4810 -1 x4909 -1 x5008 -1 x5107 -1 x5206 -1 x5305 -1 x5404 -1 x5503 -1 x5602 -1 x5701 -1 x5800 -1 x5899 -1 x5998 -1 x6097 -1 x6196 -1 x6295 -1 x6394 -1 x6493 -1 x6592 -1 x6691 -1 x6790 -1 x6889 -1 x6988 -1 x7087 -1 x7186 -1 x7285 -1 x7384 -1 x7483 -1 x7582 -1 x7681 -1 x7780 -1 x7879 -1 x7978 -1 x8077 -1 x8176 -1 x8275 -1 x8374 -1 x8473 -1 x8572 -1 x8671 -1 x8770 -1 x8869 -1 x8968 -1 x9067 -1 x9166 -1 x9265 -1 x9364 -1 x9463 -1 x9562 -1 x9661 -1 x9760 -1 x9859 >= -1;
+-1 x59 -1 x158 -1 x257 -1 x356 -1 x455 -1 x554 -1 x653 -1 x752 -1 x851 -1 x950 -1 x1049 -1 x1148 -1 x1247 -1 x1346 -1 x1445 -1 x1544 -1 x1643 -1 x1742 -1 x1841 -1 x1940 -1 x2039 -1 x2138 -1 x2237 -1 x2336 -1 x2435 -1 x2534 -1 x2633 -1 x2732 -1 x2831 -1 x2930 -1 x3029 -1 x3128 -1 x3227 -1 x3326 -1 x3425 -1 x3524 -1 x3623 -1 x3722 -1 x3821 -1 x3920 -1 x4019 -1 x4118 -1 x4217 -1 x4316 -1 x4415 -1 x4514 -1 x4613 -1 x4712 -1 x4811 -1 x4910 -1 x5009 -1 x5108 -1 x5207 -1 x5306 -1 x5405 -1 x5504 -1 x5603 -1 x5702 -1 x5801 -1 x5900 -1 x5999 -1 x6098 -1 x6197 -1 x6296 -1 x6395 -1 x6494 -1 x6593 -1 x6692 -1 x6791 -1 x6890 -1 x6989 -1 x7088 -1 x7187 -1 x7286 -1 x7385 -1 x7484 -1 x7583 -1 x7682 -1 x7781 -1 x7880 -1 x7979 -1 x8078 -1 x8177 -1 x8276 -1 x8375 -1 x8474 -1 x8573 -1 x8672 -1 x8771 -1 x8870 -1 x8969 -1 x9068 -1 x9167 -1 x9266 -1 x9365 -1 x9464 -1 x9563 -1 x9662 -1 x9761 -1 x9860 >= -1;
+-1 x60 -1 x159 -1 x258 -1 x357 -1 x456 -1 x555 -1 x654 -1 x753 -1 x852 -1 x951 -1 x1050 -1 x1149 -1 x1248 -1 x1347 -1 x1446 -1 x1545 -1 x1644 -1 x1743 -1 x1842 -1 x1941 -1 x2040 -1 x2139 -1 x2238 -1 x2337 -1 x2436 -1 x2535 -1 x2634 -1 x2733 -1 x2832 -1 x2931 -1 x3030 -1 x3129 -1 x3228 -1 x3327 -1 x3426 -1 x3525 -1 x3624 -1 x3723 -1 x3822 -1 x3921 -1 x4020 -1 x4119 -1 x4218 -1 x4317 -1 x4416 -1 x4515 -1 x4614 -1 x4713 -1 x4812 -1 x4911 -1 x5010 -1 x5109 -1 x5208 -1 x5307 -1 x5406 -1 x5505 -1 x5604 -1 x5703 -1 x5802 -1 x5901 -1 x6000 -1 x6099 -1 x6198 -1 x6297 -1 x6396 -1 x6495 -1 x6594 -1 x6693 -1 x6792 -1 x6891 -1 x6990 -1 x7089 -1 x7188 -1 x7287 -1 x7386 -1 x7485 -1 x7584 -1 x7683 -1 x7782 -1 x7881 -1 x7980 -1 x8079 -1 x8178 -1 x8277 -1 x8376 -1 x8475 -1 x8574 -1 x8673 -1 x8772 -1 x8871 -1 x8970 -1 x9069 -1 x9168 -1 x9267 -1 x9366 -1 x9465 -1 x9564 -1 x9663 -1 x9762 -1 x9861 >= -1;
+-1 x61 -1 x160 -1 x259 -1 x358 -1 x457 -1 x556 -1 x655 -1 x754 -1 x853 -1 x952 -1 x1051 -1 x1150 -1 x1249 -1 x1348 -1 x1447 -1 x1546 -1 x1645 -1 x1744 -1 x1843 -1 x1942 -1 x2041 -1 x2140 -1 x2239 -1 x2338 -1 x2437 -1 x2536 -1 x2635 -1 x2734 -1 x2833 -1 x2932 -1 x3031 -1 x3130 -1 x3229 -1 x3328 -1 x3427 -1 x3526 -1 x3625 -1 x3724 -1 x3823 -1 x3922 -1 x4021 -1 x4120 -1 x4219 -1 x4318 -1 x4417 -1 x4516 -1 x4615 -1 x4714 -1 x4813 -1 x4912 -1 x5011 -1 x5110 -1 x5209 -1 x5308 -1 x5407 -1 x5506 -1 x5605 -1 x5704 -1 x5803 -1 x5902 -1 x6001 -1 x6100 -1 x6199 -1 x6298 -1 x6397 -1 x6496 -1 x6595 -1 x6694 -1 x6793 -1 x6892 -1 x6991 -1 x7090 -1 x7189 -1 x7288 -1 x7387 -1 x7486 -1 x7585 -1 x7684 -1 x7783 -1 x7882 -1 x7981 -1 x8080 -1 x8179 -1 x8278 -1 x8377 -1 x8476 -1 x8575 -1 x8674 -1 x8773 -1 x8872 -1 x8971 -1 x9070 -1 x9169 -1 x9268 -1 x9367 -1 x9466 -1 x9565 -1 x9664 -1 x9763 -1 x9862 >= -1;
+-1 x62 -1 x161 -1 x260 -1 x359 -1 x458 -1 x557 -1 x656 -1 x755 -1 x854 -1 x953 -1 x1052 -1 x1151 -1 x1250 -1 x1349 -1 x1448 -1 x1547 -1 x1646 -1 x1745 -1 x1844 -1 x1943 -1 x2042 -1 x2141 -1 x2240 -1 x2339 -1 x2438 -1 x2537 -1 x2636 -1 x2735 -1 x2834 -1 x2933 -1 x3032 -1 x3131 -1 x3230 -1 x3329 -1 x3428 -1 x3527 -1 x3626 -1 x3725 -1 x3824 -1 x3923 -1 x4022 -1 x4121 -1 x4220 -1 x4319 -1 x4418 -1 x4517 -1 x4616 -1 x4715 -1 x4814 -1 x4913 -1 x5012 -1 x5111 -1 x5210 -1 x5309 -1 x5408 -1 x5507 -1 x5606 -1 x5705 -1 x5804 -1 x5903 -1 x6002 -1 x6101 -1 x6200 -1 x6299 -1 x6398 -1 x6497 -1 x6596 -1 x6695 -1 x6794 -1 x6893 -1 x6992 -1 x7091 -1 x7190 -1 x7289 -1 x7388 -1 x7487 -1 x7586 -1 x7685 -1 x7784 -1 x7883 -1 x7982 -1 x8081 -1 x8180 -1 x8279 -1 x8378 -1 x8477 -1 x8576 -1 x8675 -1 x8774 -1 x8873 -1 x8972 -1 x9071 -1 x9170 -1 x9269 -1 x9368 -1 x9467 -1 x9566 -1 x9665 -1 x9764 -1 x9863 >= -1;
+-1 x63 -1 x162 -1 x261 -1 x360 -1 x459 -1 x558 -1 x657 -1 x756 -1 x855 -1 x954 -1 x1053 -1 x1152 -1 x1251 -1 x1350 -1 x1449 -1 x1548 -1 x1647 -1 x1746 -1 x1845 -1 x1944 -1 x2043 -1 x2142 -1 x2241 -1 x2340 -1 x2439 -1 x2538 -1 x2637 -1 x2736 -1 x2835 -1 x2934 -1 x3033 -1 x3132 -1 x3231 -1 x3330 -1 x3429 -1 x3528 -1 x3627 -1 x3726 -1 x3825 -1 x3924 -1 x4023 -1 x4122 -1 x4221 -1 x4320 -1 x4419 -1 x4518 -1 x4617 -1 x4716 -1 x4815 -1 x4914 -1 x5013 -1 x5112 -1 x5211 -1 x5310 -1 x5409 -1 x5508 -1 x5607 -1 x5706 -1 x5805 -1 x5904 -1 x6003 -1 x6102 -1 x6201 -1 x6300 -1 x6399 -1 x6498 -1 x6597 -1 x6696 -1 x6795 -1 x6894 -1 x6993 -1 x7092 -1 x7191 -1 x7290 -1 x7389 -1 x7488 -1 x7587 -1 x7686 -1 x7785 -1 x7884 -1 x7983 -1 x8082 -1 x8181 -1 x8280 -1 x8379 -1 x8478 -1 x8577 -1 x8676 -1 x8775 -1 x8874 -1 x8973 -1 x9072 -1 x9171 -1 x9270 -1 x9369 -1 x9468 -1 x9567 -1 x9666 -1 x9765 -1 x9864 >= -1;
+-1 x64 -1 x163 -1 x262 -1 x361 -1 x460 -1 x559 -1 x658 -1 x757 -1 x856 -1 x955 -1 x1054 -1 x1153 -1 x1252 -1 x1351 -1 x1450 -1 x1549 -1 x1648 -1 x1747 -1 x1846 -1 x1945 -1 x2044 -1 x2143 -1 x2242 -1 x2341 -1 x2440 -1 x2539 -1 x2638 -1 x2737 -1 x2836 -1 x2935 -1 x3034 -1 x3133 -1 x3232 -1 x3331 -1 x3430 -1 x3529 -1 x3628 -1 x3727 -1 x3826 -1 x3925 -1 x4024 -1 x4123 -1 x4222 -1 x4321 -1 x4420 -1 x4519 -1 x4618 -1 x4717 -1 x4816 -1 x4915 -1 x5014 -1 x5113 -1 x5212 -1 x5311 -1 x5410 -1 x5509 -1 x5608 -1 x5707 -1 x5806 -1 x5905 -1 x6004 -1 x6103 -1 x6202 -1 x6301 -1 x6400 -1 x6499 -1 x6598 -1 x6697 -1 x6796 -1 x6895 -1 x6994 -1 x7093 -1 x7192 -1 x7291 -1 x7390 -1 x7489 -1 x7588 -1 x7687 -1 x7786 -1 x7885 -1 x7984 -1 x8083 -1 x8182 -1 x8281 -1 x8380 -1 x8479 -1 x8578 -1 x8677 -1 x8776 -1 x8875 -1 x8974 -1 x9073 -1 x9172 -1 x9271 -1 x9370 -1 x9469 -1 x9568 -1 x9667 -1 x9766 -1 x9865 >= -1;
+-1 x65 -1 x164 -1 x263 -1 x362 -1 x461 -1 x560 -1 x659 -1 x758 -1 x857 -1 x956 -1 x1055 -1 x1154 -1 x1253 -1 x1352 -1 x1451 -1 x1550 -1 x1649 -1 x1748 -1 x1847 -1 x1946 -1 x2045 -1 x2144 -1 x2243 -1 x2342 -1 x2441 -1 x2540 -1 x2639 -1 x2738 -1 x2837 -1 x2936 -1 x3035 -1 x3134 -1 x3233 -1 x3332 -1 x3431 -1 x3530 -1 x3629 -1 x3728 -1 x3827 -1 x3926 -1 x4025 -1 x4124 -1 x4223 -1 x4322 -1 x4421 -1 x4520 -1 x4619 -1 x4718 -1 x4817 -1 x4916 -1 x5015 -1 x5114 -1 x5213 -1 x5312 -1 x5411 -1 x5510 -1 x5609 -1 x5708 -1 x5807 -1 x5906 -1 x6005 -1 x6104 -1 x6203 -1 x6302 -1 x6401 -1 x6500 -1 x6599 -1 x6698 -1 x6797 -1 x6896 -1 x6995 -1 x7094 -1 x7193 -1 x7292 -1 x7391 -1 x7490 -1 x7589 -1 x7688 -1 x7787 -1 x7886 -1 x7985 -1 x8084 -1 x8183 -1 x8282 -1 x8381 -1 x8480 -1 x8579 -1 x8678 -1 x8777 -1 x8876 -1 x8975 -1 x9074 -1 x9173 -1 x9272 -1 x9371 -1 x9470 -1 x9569 -1 x9668 -1 x9767 -1 x9866 >= -1;
+-1 x66 -1 x165 -1 x264 -1 x363 -1 x462 -1 x561 -1 x660 -1 x759 -1 x858 -1 x957 -1 x1056 -1 x1155 -1 x1254 -1 x1353 -1 x1452 -1 x1551 -1 x1650 -1 x1749 -1 x1848 -1 x1947 -1 x2046 -1 x2145 -1 x2244 -1 x2343 -1 x2442 -1 x2541 -1 x2640 -1 x2739 -1 x2838 -1 x2937 -1 x3036 -1 x3135 -1 x3234 -1 x3333 -1 x3432 -1 x3531 -1 x3630 -1 x3729 -1 x3828 -1 x3927 -1 x4026 -1 x4125 -1 x4224 -1 x4323 -1 x4422 -1 x4521 -1 x4620 -1 x4719 -1 x4818 -1 x4917 -1 x5016 -1 x5115 -1 x5214 -1 x5313 -1 x5412 -1 x5511 -1 x5610 -1 x5709 -1 x5808 -1 x5907 -1 x6006 -1 x6105 -1 x6204 -1 x6303 -1 x6402 -1 x6501 -1 x6600 -1 x6699 -1 x6798 -1 x6897 -1 x6996 -1 x7095 -1 x7194 -1 x7293 -1 x7392 -1 x7491 -1 x7590 -1 x7689 -1 x7788 -1 x7887 -1 x7986 -1 x8085 -1 x8184 -1 x8283 -1 x8382 -1 x8481 -1 x8580 -1 x8679 -1 x8778 -1 x8877 -1 x8976 -1 x9075 -1 x9174 -1 x9273 -1 x9372 -1 x9471 -1 x9570 -1 x9669 -1 x9768 -1 x9867 >= -1;
+-1 x67 -1 x166 -1 x265 -1 x364 -1 x463 -1 x562 -1 x661 -1 x760 -1 x859 -1 x958 -1 x1057 -1 x1156 -1 x1255 -1 x1354 -1 x1453 -1 x1552 -1 x1651 -1 x1750 -1 x1849 -1 x1948 -1 x2047 -1 x2146 -1 x2245 -1 x2344 -1 x2443 -1 x2542 -1 x2641 -1 x2740 -1 x2839 -1 x2938 -1 x3037 -1 x3136 -1 x3235 -1 x3334 -1 x3433 -1 x3532 -1 x3631 -1 x3730 -1 x3829 -1 x3928 -1 x4027 -1 x4126 -1 x4225 -1 x4324 -1 x4423 -1 x4522 -1 x4621 -1 x4720 -1 x4819 -1 x4918 -1 x5017 -1 x5116 -1 x5215 -1 x5314 -1 x5413 -1 x5512 -1 x5611 -1 x5710 -1 x5809 -1 x5908 -1 x6007 -1 x6106 -1 x6205 -1 x6304 -1 x6403 -1 x6502 -1 x6601 -1 x6700 -1 x6799 -1 x6898 -1 x6997 -1 x7096 -1 x7195 -1 x7294 -1 x7393 -1 x7492 -1 x7591 -1 x7690 -1 x7789 -1 x7888 -1 x7987 -1 x8086 -1 x8185 -1 x8284 -1 x8383 -1 x8482 -1 x8581 -1 x8680 -1 x8779 -1 x8878 -1 x8977 -1 x9076 -1 x9175 -1 x9274 -1 x9373 -1 x9472 -1 x9571 -1 x9670 -1 x9769 -1 x9868 >= -1;
+-1 x68 -1 x167 -1 x266 -1 x365 -1 x464 -1 x563 -1 x662 -1 x761 -1 x860 -1 x959 -1 x1058 -1 x1157 -1 x1256 -1 x1355 -1 x1454 -1 x1553 -1 x1652 -1 x1751 -1 x1850 -1 x1949 -1 x2048 -1 x2147 -1 x2246 -1 x2345 -1 x2444 -1 x2543 -1 x2642 -1 x2741 -1 x2840 -1 x2939 -1 x3038 -1 x3137 -1 x3236 -1 x3335 -1 x3434 -1 x3533 -1 x3632 -1 x3731 -1 x3830 -1 x3929 -1 x4028 -1 x4127 -1 x4226 -1 x4325 -1 x4424 -1 x4523 -1 x4622 -1 x4721 -1 x4820 -1 x4919 -1 x5018 -1 x5117 -1 x5216 -1 x5315 -1 x5414 -1 x5513 -1 x5612 -1 x5711 -1 x5810 -1 x5909 -1 x6008 -1 x6107 -1 x6206 -1 x6305 -1 x6404 -1 x6503 -1 x6602 -1 x6701 -1 x6800 -1 x6899 -1 x6998 -1 x7097 -1 x7196 -1 x7295 -1 x7394 -1 x7493 -1 x7592 -1 x7691 -1 x7790 -1 x7889 -1 x7988 -1 x8087 -1 x8186 -1 x8285 -1 x8384 -1 x8483 -1 x8582 -1 x8681 -1 x8780 -1 x8879 -1 x8978 -1 x9077 -1 x9176 -1 x9275 -1 x9374 -1 x9473 -1 x9572 -1 x9671 -1 x9770 -1 x9869 >= -1;
+-1 x69 -1 x168 -1 x267 -1 x366 -1 x465 -1 x564 -1 x663 -1 x762 -1 x861 -1 x960 -1 x1059 -1 x1158 -1 x1257 -1 x1356 -1 x1455 -1 x1554 -1 x1653 -1 x1752 -1 x1851 -1 x1950 -1 x2049 -1 x2148 -1 x2247 -1 x2346 -1 x2445 -1 x2544 -1 x2643 -1 x2742 -1 x2841 -1 x2940 -1 x3039 -1 x3138 -1 x3237 -1 x3336 -1 x3435 -1 x3534 -1 x3633 -1 x3732 -1 x3831 -1 x3930 -1 x4029 -1 x4128 -1 x4227 -1 x4326 -1 x4425 -1 x4524 -1 x4623 -1 x4722 -1 x4821 -1 x4920 -1 x5019 -1 x5118 -1 x5217 -1 x5316 -1 x5415 -1 x5514 -1 x5613 -1 x5712 -1 x5811 -1 x5910 -1 x6009 -1 x6108 -1 x6207 -1 x6306 -1 x6405 -1 x6504 -1 x6603 -1 x6702 -1 x6801 -1 x6900 -1 x6999 -1 x7098 -1 x7197 -1 x7296 -1 x7395 -1 x7494 -1 x7593 -1 x7692 -1 x7791 -1 x7890 -1 x7989 -1 x8088 -1 x8187 -1 x8286 -1 x8385 -1 x8484 -1 x8583 -1 x8682 -1 x8781 -1 x8880 -1 x8979 -1 x9078 -1 x9177 -1 x9276 -1 x9375 -1 x9474 -1 x9573 -1 x9672 -1 x9771 -1 x9870 >= -1;
+-1 x70 -1 x169 -1 x268 -1 x367 -1 x466 -1 x565 -1 x664 -1 x763 -1 x862 -1 x961 -1 x1060 -1 x1159 -1 x1258 -1 x1357 -1 x1456 -1 x1555 -1 x1654 -1 x1753 -1 x1852 -1 x1951 -1 x2050 -1 x2149 -1 x2248 -1 x2347 -1 x2446 -1 x2545 -1 x2644 -1 x2743 -1 x2842 -1 x2941 -1 x3040 -1 x3139 -1 x3238 -1 x3337 -1 x3436 -1 x3535 -1 x3634 -1 x3733 -1 x3832 -1 x3931 -1 x4030 -1 x4129 -1 x4228 -1 x4327 -1 x4426 -1 x4525 -1 x4624 -1 x4723 -1 x4822 -1 x4921 -1 x5020 -1 x5119 -1 x5218 -1 x5317 -1 x5416 -1 x5515 -1 x5614 -1 x5713 -1 x5812 -1 x5911 -1 x6010 -1 x6109 -1 x6208 -1 x6307 -1 x6406 -1 x6505 -1 x6604 -1 x6703 -1 x6802 -1 x6901 -1 x7000 -1 x7099 -1 x7198 -1 x7297 -1 x7396 -1 x7495 -1 x7594 -1 x7693 -1 x7792 -1 x7891 -1 x7990 -1 x8089 -1 x8188 -1 x8287 -1 x8386 -1 x8485 -1 x8584 -1 x8683 -1 x8782 -1 x8881 -1 x8980 -1 x9079 -1 x9178 -1 x9277 -1 x9376 -1 x9475 -1 x9574 -1 x9673 -1 x9772 -1 x9871 >= -1;
+-1 x71 -1 x170 -1 x269 -1 x368 -1 x467 -1 x566 -1 x665 -1 x764 -1 x863 -1 x962 -1 x1061 -1 x1160 -1 x1259 -1 x1358 -1 x1457 -1 x1556 -1 x1655 -1 x1754 -1 x1853 -1 x1952 -1 x2051 -1 x2150 -1 x2249 -1 x2348 -1 x2447 -1 x2546 -1 x2645 -1 x2744 -1 x2843 -1 x2942 -1 x3041 -1 x3140 -1 x3239 -1 x3338 -1 x3437 -1 x3536 -1 x3635 -1 x3734 -1 x3833 -1 x3932 -1 x4031 -1 x4130 -1 x4229 -1 x4328 -1 x4427 -1 x4526 -1 x4625 -1 x4724 -1 x4823 -1 x4922 -1 x5021 -1 x5120 -1 x5219 -1 x5318 -1 x5417 -1 x5516 -1 x5615 -1 x5714 -1 x5813 -1 x5912 -1 x6011 -1 x6110 -1 x6209 -1 x6308 -1 x6407 -1 x6506 -1 x6605 -1 x6704 -1 x6803 -1 x6902 -1 x7001 -1 x7100 -1 x7199 -1 x7298 -1 x7397 -1 x7496 -1 x7595 -1 x7694 -1 x7793 -1 x7892 -1 x7991 -1 x8090 -1 x8189 -1 x8288 -1 x8387 -1 x8486 -1 x8585 -1 x8684 -1 x8783 -1 x8882 -1 x8981 -1 x9080 -1 x9179 -1 x9278 -1 x9377 -1 x9476 -1 x9575 -1 x9674 -1 x9773 -1 x9872 >= -1;
+-1 x72 -1 x171 -1 x270 -1 x369 -1 x468 -1 x567 -1 x666 -1 x765 -1 x864 -1 x963 -1 x1062 -1 x1161 -1 x1260 -1 x1359 -1 x1458 -1 x1557 -1 x1656 -1 x1755 -1 x1854 -1 x1953 -1 x2052 -1 x2151 -1 x2250 -1 x2349 -1 x2448 -1 x2547 -1 x2646 -1 x2745 -1 x2844 -1 x2943 -1 x3042 -1 x3141 -1 x3240 -1 x3339 -1 x3438 -1 x3537 -1 x3636 -1 x3735 -1 x3834 -1 x3933 -1 x4032 -1 x4131 -1 x4230 -1 x4329 -1 x4428 -1 x4527 -1 x4626 -1 x4725 -1 x4824 -1 x4923 -1 x5022 -1 x5121 -1 x5220 -1 x5319 -1 x5418 -1 x5517 -1 x5616 -1 x5715 -1 x5814 -1 x5913 -1 x6012 -1 x6111 -1 x6210 -1 x6309 -1 x6408 -1 x6507 -1 x6606 -1 x6705 -1 x6804 -1 x6903 -1 x7002 -1 x7101 -1 x7200 -1 x7299 -1 x7398 -1 x7497 -1 x7596 -1 x7695 -1 x7794 -1 x7893 -1 x7992 -1 x8091 -1 x8190 -1 x8289 -1 x8388 -1 x8487 -1 x8586 -1 x8685 -1 x8784 -1 x8883 -1 x8982 -1 x9081 -1 x9180 -1 x9279 -1 x9378 -1 x9477 -1 x9576 -1 x9675 -1 x9774 -1 x9873 >= -1;
+-1 x73 -1 x172 -1 x271 -1 x370 -1 x469 -1 x568 -1 x667 -1 x766 -1 x865 -1 x964 -1 x1063 -1 x1162 -1 x1261 -1 x1360 -1 x1459 -1 x1558 -1 x1657 -1 x1756 -1 x1855 -1 x1954 -1 x2053 -1 x2152 -1 x2251 -1 x2350 -1 x2449 -1 x2548 -1 x2647 -1 x2746 -1 x2845 -1 x2944 -1 x3043 -1 x3142 -1 x3241 -1 x3340 -1 x3439 -1 x3538 -1 x3637 -1 x3736 -1 x3835 -1 x3934 -1 x4033 -1 x4132 -1 x4231 -1 x4330 -1 x4429 -1 x4528 -1 x4627 -1 x4726 -1 x4825 -1 x4924 -1 x5023 -1 x5122 -1 x5221 -1 x5320 -1 x5419 -1 x5518 -1 x5617 -1 x5716 -1 x5815 -1 x5914 -1 x6013 -1 x6112 -1 x6211 -1 x6310 -1 x6409 -1 x6508 -1 x6607 -1 x6706 -1 x6805 -1 x6904 -1 x7003 -1 x7102 -1 x7201 -1 x7300 -1 x7399 -1 x7498 -1 x7597 -1 x7696 -1 x7795 -1 x7894 -1 x7993 -1 x8092 -1 x8191 -1 x8290 -1 x8389 -1 x8488 -1 x8587 -1 x8686 -1 x8785 -1 x8884 -1 x8983 -1 x9082 -1 x9181 -1 x9280 -1 x9379 -1 x9478 -1 x9577 -1 x9676 -1 x9775 -1 x9874 >= -1;
+-1 x74 -1 x173 -1 x272 -1 x371 -1 x470 -1 x569 -1 x668 -1 x767 -1 x866 -1 x965 -1 x1064 -1 x1163 -1 x1262 -1 x1361 -1 x1460 -1 x1559 -1 x1658 -1 x1757 -1 x1856 -1 x1955 -1 x2054 -1 x2153 -1 x2252 -1 x2351 -1 x2450 -1 x2549 -1 x2648 -1 x2747 -1 x2846 -1 x2945 -1 x3044 -1 x3143 -1 x3242 -1 x3341 -1 x3440 -1 x3539 -1 x3638 -1 x3737 -1 x3836 -1 x3935 -1 x4034 -1 x4133 -1 x4232 -1 x4331 -1 x4430 -1 x4529 -1 x4628 -1 x4727 -1 x4826 -1 x4925 -1 x5024 -1 x5123 -1 x5222 -1 x5321 -1 x5420 -1 x5519 -1 x5618 -1 x5717 -1 x5816 -1 x5915 -1 x6014 -1 x6113 -1 x6212 -1 x6311 -1 x6410 -1 x6509 -1 x6608 -1 x6707 -1 x6806 -1 x6905 -1 x7004 -1 x7103 -1 x7202 -1 x7301 -1 x7400 -1 x7499 -1 x7598 -1 x7697 -1 x7796 -1 x7895 -1 x7994 -1 x8093 -1 x8192 -1 x8291 -1 x8390 -1 x8489 -1 x8588 -1 x8687 -1 x8786 -1 x8885 -1 x8984 -1 x9083 -1 x9182 -1 x9281 -1 x9380 -1 x9479 -1 x9578 -1 x9677 -1 x9776 -1 x9875 >= -1;
+-1 x75 -1 x174 -1 x273 -1 x372 -1 x471 -1 x570 -1 x669 -1 x768 -1 x867 -1 x966 -1 x1065 -1 x1164 -1 x1263 -1 x1362 -1 x1461 -1 x1560 -1 x1659 -1 x1758 -1 x1857 -1 x1956 -1 x2055 -1 x2154 -1 x2253 -1 x2352 -1 x2451 -1 x2550 -1 x2649 -1 x2748 -1 x2847 -1 x2946 -1 x3045 -1 x3144 -1 x3243 -1 x3342 -1 x3441 -1 x3540 -1 x3639 -1 x3738 -1 x3837 -1 x3936 -1 x4035 -1 x4134 -1 x4233 -1 x4332 -1 x4431 -1 x4530 -1 x4629 -1 x4728 -1 x4827 -1 x4926 -1 x5025 -1 x5124 -1 x5223 -1 x5322 -1 x5421 -1 x5520 -1 x5619 -1 x5718 -1 x5817 -1 x5916 -1 x6015 -1 x6114 -1 x6213 -1 x6312 -1 x6411 -1 x6510 -1 x6609 -1 x6708 -1 x6807 -1 x6906 -1 x7005 -1 x7104 -1 x7203 -1 x7302 -1 x7401 -1 x7500 -1 x7599 -1 x7698 -1 x7797 -1 x7896 -1 x7995 -1 x8094 -1 x8193 -1 x8292 -1 x8391 -1 x8490 -1 x8589 -1 x8688 -1 x8787 -1 x8886 -1 x8985 -1 x9084 -1 x9183 -1 x9282 -1 x9381 -1 x9480 -1 x9579 -1 x9678 -1 x9777 -1 x9876 >= -1;
+-1 x76 -1 x175 -1 x274 -1 x373 -1 x472 -1 x571 -1 x670 -1 x769 -1 x868 -1 x967 -1 x1066 -1 x1165 -1 x1264 -1 x1363 -1 x1462 -1 x1561 -1 x1660 -1 x1759 -1 x1858 -1 x1957 -1 x2056 -1 x2155 -1 x2254 -1 x2353 -1 x2452 -1 x2551 -1 x2650 -1 x2749 -1 x2848 -1 x2947 -1 x3046 -1 x3145 -1 x3244 -1 x3343 -1 x3442 -1 x3541 -1 x3640 -1 x3739 -1 x3838 -1 x3937 -1 x4036 -1 x4135 -1 x4234 -1 x4333 -1 x4432 -1 x4531 -1 x4630 -1 x4729 -1 x4828 -1 x4927 -1 x5026 -1 x5125 -1 x5224 -1 x5323 -1 x5422 -1 x5521 -1 x5620 -1 x5719 -1 x5818 -1 x5917 -1 x6016 -1 x6115 -1 x6214 -1 x6313 -1 x6412 -1 x6511 -1 x6610 -1 x6709 -1 x6808 -1 x6907 -1 x7006 -1 x7105 -1 x7204 -1 x7303 -1 x7402 -1 x7501 -1 x7600 -1 x7699 -1 x7798 -1 x7897 -1 x7996 -1 x8095 -1 x8194 -1 x8293 -1 x8392 -1 x8491 -1 x8590 -1 x8689 -1 x8788 -1 x8887 -1 x8986 -1 x9085 -1 x9184 -1 x9283 -1 x9382 -1 x9481 -1 x9580 -1 x9679 -1 x9778 -1 x9877 >= -1;
+-1 x77 -1 x176 -1 x275 -1 x374 -1 x473 -1 x572 -1 x671 -1 x770 -1 x869 -1 x968 -1 x1067 -1 x1166 -1 x1265 -1 x1364 -1 x1463 -1 x1562 -1 x1661 -1 x1760 -1 x1859 -1 x1958 -1 x2057 -1 x2156 -1 x2255 -1 x2354 -1 x2453 -1 x2552 -1 x2651 -1 x2750 -1 x2849 -1 x2948 -1 x3047 -1 x3146 -1 x3245 -1 x3344 -1 x3443 -1 x3542 -1 x3641 -1 x3740 -1 x3839 -1 x3938 -1 x4037 -1 x4136 -1 x4235 -1 x4334 -1 x4433 -1 x4532 -1 x4631 -1 x4730 -1 x4829 -1 x4928 -1 x5027 -1 x5126 -1 x5225 -1 x5324 -1 x5423 -1 x5522 -1 x5621 -1 x5720 -1 x5819 -1 x5918 -1 x6017 -1 x6116 -1 x6215 -1 x6314 -1 x6413 -1 x6512 -1 x6611 -1 x6710 -1 x6809 -1 x6908 -1 x7007 -1 x7106 -1 x7205 -1 x7304 -1 x7403 -1 x7502 -1 x7601 -1 x7700 -1 x7799 -1 x7898 -1 x7997 -1 x8096 -1 x8195 -1 x8294 -1 x8393 -1 x8492 -1 x8591 -1 x8690 -1 x8789 -1 x8888 -1 x8987 -1 x9086 -1 x9185 -1 x9284 -1 x9383 -1 x9482 -1 x9581 -1 x9680 -1 x9779 -1 x9878 >= -1;
+-1 x78 -1 x177 -1 x276 -1 x375 -1 x474 -1 x573 -1 x672 -1 x771 -1 x870 -1 x969 -1 x1068 -1 x1167 -1 x1266 -1 x1365 -1 x1464 -1 x1563 -1 x1662 -1 x1761 -1 x1860 -1 x1959 -1 x2058 -1 x2157 -1 x2256 -1 x2355 -1 x2454 -1 x2553 -1 x2652 -1 x2751 -1 x2850 -1 x2949 -1 x3048 -1 x3147 -1 x3246 -1 x3345 -1 x3444 -1 x3543 -1 x3642 -1 x3741 -1 x3840 -1 x3939 -1 x4038 -1 x4137 -1 x4236 -1 x4335 -1 x4434 -1 x4533 -1 x4632 -1 x4731 -1 x4830 -1 x4929 -1 x5028 -1 x5127 -1 x5226 -1 x5325 -1 x5424 -1 x5523 -1 x5622 -1 x5721 -1 x5820 -1 x5919 -1 x6018 -1 x6117 -1 x6216 -1 x6315 -1 x6414 -1 x6513 -1 x6612 -1 x6711 -1 x6810 -1 x6909 -1 x7008 -1 x7107 -1 x7206 -1 x7305 -1 x7404 -1 x7503 -1 x7602 -1 x7701 -1 x7800 -1 x7899 -1 x7998 -1 x8097 -1 x8196 -1 x8295 -1 x8394 -1 x8493 -1 x8592 -1 x8691 -1 x8790 -1 x8889 -1 x8988 -1 x9087 -1 x9186 -1 x9285 -1 x9384 -1 x9483 -1 x9582 -1 x9681 -1 x9780 -1 x9879 >= -1;
+-1 x79 -1 x178 -1 x277 -1 x376 -1 x475 -1 x574 -1 x673 -1 x772 -1 x871 -1 x970 -1 x1069 -1 x1168 -1 x1267 -1 x1366 -1 x1465 -1 x1564 -1 x1663 -1 x1762 -1 x1861 -1 x1960 -1 x2059 -1 x2158 -1 x2257 -1 x2356 -1 x2455 -1 x2554 -1 x2653 -1 x2752 -1 x2851 -1 x2950 -1 x3049 -1 x3148 -1 x3247 -1 x3346 -1 x3445 -1 x3544 -1 x3643 -1 x3742 -1 x3841 -1 x3940 -1 x4039 -1 x4138 -1 x4237 -1 x4336 -1 x4435 -1 x4534 -1 x4633 -1 x4732 -1 x4831 -1 x4930 -1 x5029 -1 x5128 -1 x5227 -1 x5326 -1 x5425 -1 x5524 -1 x5623 -1 x5722 -1 x5821 -1 x5920 -1 x6019 -1 x6118 -1 x6217 -1 x6316 -1 x6415 -1 x6514 -1 x6613 -1 x6712 -1 x6811 -1 x6910 -1 x7009 -1 x7108 -1 x7207 -1 x7306 -1 x7405 -1 x7504 -1 x7603 -1 x7702 -1 x7801 -1 x7900 -1 x7999 -1 x8098 -1 x8197 -1 x8296 -1 x8395 -1 x8494 -1 x8593 -1 x8692 -1 x8791 -1 x8890 -1 x8989 -1 x9088 -1 x9187 -1 x9286 -1 x9385 -1 x9484 -1 x9583 -1 x9682 -1 x9781 -1 x9880 >= -1;
+-1 x80 -1 x179 -1 x278 -1 x377 -1 x476 -1 x575 -1 x674 -1 x773 -1 x872 -1 x971 -1 x1070 -1 x1169 -1 x1268 -1 x1367 -1 x1466 -1 x1565 -1 x1664 -1 x1763 -1 x1862 -1 x1961 -1 x2060 -1 x2159 -1 x2258 -1 x2357 -1 x2456 -1 x2555 -1 x2654 -1 x2753 -1 x2852 -1 x2951 -1 x3050 -1 x3149 -1 x3248 -1 x3347 -1 x3446 -1 x3545 -1 x3644 -1 x3743 -1 x3842 -1 x3941 -1 x4040 -1 x4139 -1 x4238 -1 x4337 -1 x4436 -1 x4535 -1 x4634 -1 x4733 -1 x4832 -1 x4931 -1 x5030 -1 x5129 -1 x5228 -1 x5327 -1 x5426 -1 x5525 -1 x5624 -1 x5723 -1 x5822 -1 x5921 -1 x6020 -1 x6119 -1 x6218 -1 x6317 -1 x6416 -1 x6515 -1 x6614 -1 x6713 -1 x6812 -1 x6911 -1 x7010 -1 x7109 -1 x7208 -1 x7307 -1 x7406 -1 x7505 -1 x7604 -1 x7703 -1 x7802 -1 x7901 -1 x8000 -1 x8099 -1 x8198 -1 x8297 -1 x8396 -1 x8495 -1 x8594 -1 x8693 -1 x8792 -1 x8891 -1 x8990 -1 x9089 -1 x9188 -1 x9287 -1 x9386 -1 x9485 -1 x9584 -1 x9683 -1 x9782 -1 x9881 >= -1;
+-1 x81 -1 x180 -1 x279 -1 x378 -1 x477 -1 x576 -1 x675 -1 x774 -1 x873 -1 x972 -1 x1071 -1 x1170 -1 x1269 -1 x1368 -1 x1467 -1 x1566 -1 x1665 -1 x1764 -1 x1863 -1 x1962 -1 x2061 -1 x2160 -1 x2259 -1 x2358 -1 x2457 -1 x2556 -1 x2655 -1 x2754 -1 x2853 -1 x2952 -1 x3051 -1 x3150 -1 x3249 -1 x3348 -1 x3447 -1 x3546 -1 x3645 -1 x3744 -1 x3843 -1 x3942 -1 x4041 -1 x4140 -1 x4239 -1 x4338 -1 x4437 -1 x4536 -1 x4635 -1 x4734 -1 x4833 -1 x4932 -1 x5031 -1 x5130 -1 x5229 -1 x5328 -1 x5427 -1 x5526 -1 x5625 -1 x5724 -1 x5823 -1 x5922 -1 x6021 -1 x6120 -1 x6219 -1 x6318 -1 x6417 -1 x6516 -1 x6615 -1 x6714 -1 x6813 -1 x6912 -1 x7011 -1 x7110 -1 x7209 -1 x7308 -1 x7407 -1 x7506 -1 x7605 -1 x7704 -1 x7803 -1 x7902 -1 x8001 -1 x8100 -1 x8199 -1 x8298 -1 x8397 -1 x8496 -1 x8595 -1 x8694 -1 x8793 -1 x8892 -1 x8991 -1 x9090 -1 x9189 -1 x9288 -1 x9387 -1 x9486 -1 x9585 -1 x9684 -1 x9783 -1 x9882 >= -1;
+-1 x82 -1 x181 -1 x280 -1 x379 -1 x478 -1 x577 -1 x676 -1 x775 -1 x874 -1 x973 -1 x1072 -1 x1171 -1 x1270 -1 x1369 -1 x1468 -1 x1567 -1 x1666 -1 x1765 -1 x1864 -1 x1963 -1 x2062 -1 x2161 -1 x2260 -1 x2359 -1 x2458 -1 x2557 -1 x2656 -1 x2755 -1 x2854 -1 x2953 -1 x3052 -1 x3151 -1 x3250 -1 x3349 -1 x3448 -1 x3547 -1 x3646 -1 x3745 -1 x3844 -1 x3943 -1 x4042 -1 x4141 -1 x4240 -1 x4339 -1 x4438 -1 x4537 -1 x4636 -1 x4735 -1 x4834 -1 x4933 -1 x5032 -1 x5131 -1 x5230 -1 x5329 -1 x5428 -1 x5527 -1 x5626 -1 x5725 -1 x5824 -1 x5923 -1 x6022 -1 x6121 -1 x6220 -1 x6319 -1 x6418 -1 x6517 -1 x6616 -1 x6715 -1 x6814 -1 x6913 -1 x7012 -1 x7111 -1 x7210 -1 x7309 -1 x7408 -1 x7507 -1 x7606 -1 x7705 -1 x7804 -1 x7903 -1 x8002 -1 x8101 -1 x8200 -1 x8299 -1 x8398 -1 x8497 -1 x8596 -1 x8695 -1 x8794 -1 x8893 -1 x8992 -1 x9091 -1 x9190 -1 x9289 -1 x9388 -1 x9487 -1 x9586 -1 x9685 -1 x9784 -1 x9883 >= -1;
+-1 x83 -1 x182 -1 x281 -1 x380 -1 x479 -1 x578 -1 x677 -1 x776 -1 x875 -1 x974 -1 x1073 -1 x1172 -1 x1271 -1 x1370 -1 x1469 -1 x1568 -1 x1667 -1 x1766 -1 x1865 -1 x1964 -1 x2063 -1 x2162 -1 x2261 -1 x2360 -1 x2459 -1 x2558 -1 x2657 -1 x2756 -1 x2855 -1 x2954 -1 x3053 -1 x3152 -1 x3251 -1 x3350 -1 x3449 -1 x3548 -1 x3647 -1 x3746 -1 x3845 -1 x3944 -1 x4043 -1 x4142 -1 x4241 -1 x4340 -1 x4439 -1 x4538 -1 x4637 -1 x4736 -1 x4835 -1 x4934 -1 x5033 -1 x5132 -1 x5231 -1 x5330 -1 x5429 -1 x5528 -1 x5627 -1 x5726 -1 x5825 -1 x5924 -1 x6023 -1 x6122 -1 x6221 -1 x6320 -1 x6419 -1 x6518 -1 x6617 -1 x6716 -1 x6815 -1 x6914 -1 x7013 -1 x7112 -1 x7211 -1 x7310 -1 x7409 -1 x7508 -1 x7607 -1 x7706 -1 x7805 -1 x7904 -1 x8003 -1 x8102 -1 x8201 -1 x8300 -1 x8399 -1 x8498 -1 x8597 -1 x8696 -1 x8795 -1 x8894 -1 x8993 -1 x9092 -1 x9191 -1 x9290 -1 x9389 -1 x9488 -1 x9587 -1 x9686 -1 x9785 -1 x9884 >= -1;
+-1 x84 -1 x183 -1 x282 -1 x381 -1 x480 -1 x579 -1 x678 -1 x777 -1 x876 -1 x975 -1 x1074 -1 x1173 -1 x1272 -1 x1371 -1 x1470 -1 x1569 -1 x1668 -1 x1767 -1 x1866 -1 x1965 -1 x2064 -1 x2163 -1 x2262 -1 x2361 -1 x2460 -1 x2559 -1 x2658 -1 x2757 -1 x2856 -1 x2955 -1 x3054 -1 x3153 -1 x3252 -1 x3351 -1 x3450 -1 x3549 -1 x3648 -1 x3747 -1 x3846 -1 x3945 -1 x4044 -1 x4143 -1 x4242 -1 x4341 -1 x4440 -1 x4539 -1 x4638 -1 x4737 -1 x4836 -1 x4935 -1 x5034 -1 x5133 -1 x5232 -1 x5331 -1 x5430 -1 x5529 -1 x5628 -1 x5727 -1 x5826 -1 x5925 -1 x6024 -1 x6123 -1 x6222 -1 x6321 -1 x6420 -1 x6519 -1 x6618 -1 x6717 -1 x6816 -1 x6915 -1 x7014 -1 x7113 -1 x7212 -1 x7311 -1 x7410 -1 x7509 -1 x7608 -1 x7707 -1 x7806 -1 x7905 -1 x8004 -1 x8103 -1 x8202 -1 x8301 -1 x8400 -1 x8499 -1 x8598 -1 x8697 -1 x8796 -1 x8895 -1 x8994 -1 x9093 -1 x9192 -1 x9291 -1 x9390 -1 x9489 -1 x9588 -1 x9687 -1 x9786 -1 x9885 >= -1;
+-1 x85 -1 x184 -1 x283 -1 x382 -1 x481 -1 x580 -1 x679 -1 x778 -1 x877 -1 x976 -1 x1075 -1 x1174 -1 x1273 -1 x1372 -1 x1471 -1 x1570 -1 x1669 -1 x1768 -1 x1867 -1 x1966 -1 x2065 -1 x2164 -1 x2263 -1 x2362 -1 x2461 -1 x2560 -1 x2659 -1 x2758 -1 x2857 -1 x2956 -1 x3055 -1 x3154 -1 x3253 -1 x3352 -1 x3451 -1 x3550 -1 x3649 -1 x3748 -1 x3847 -1 x3946 -1 x4045 -1 x4144 -1 x4243 -1 x4342 -1 x4441 -1 x4540 -1 x4639 -1 x4738 -1 x4837 -1 x4936 -1 x5035 -1 x5134 -1 x5233 -1 x5332 -1 x5431 -1 x5530 -1 x5629 -1 x5728 -1 x5827 -1 x5926 -1 x6025 -1 x6124 -1 x6223 -1 x6322 -1 x6421 -1 x6520 -1 x6619 -1 x6718 -1 x6817 -1 x6916 -1 x7015 -1 x7114 -1 x7213 -1 x7312 -1 x7411 -1 x7510 -1 x7609 -1 x7708 -1 x7807 -1 x7906 -1 x8005 -1 x8104 -1 x8203 -1 x8302 -1 x8401 -1 x8500 -1 x8599 -1 x8698 -1 x8797 -1 x8896 -1 x8995 -1 x9094 -1 x9193 -1 x9292 -1 x9391 -1 x9490 -1 x9589 -1 x9688 -1 x9787 -1 x9886 >= -1;
+-1 x86 -1 x185 -1 x284 -1 x383 -1 x482 -1 x581 -1 x680 -1 x779 -1 x878 -1 x977 -1 x1076 -1 x1175 -1 x1274 -1 x1373 -1 x1472 -1 x1571 -1 x1670 -1 x1769 -1 x1868 -1 x1967 -1 x2066 -1 x2165 -1 x2264 -1 x2363 -1 x2462 -1 x2561 -1 x2660 -1 x2759 -1 x2858 -1 x2957 -1 x3056 -1 x3155 -1 x3254 -1 x3353 -1 x3452 -1 x3551 -1 x3650 -1 x3749 -1 x3848 -1 x3947 -1 x4046 -1 x4145 -1 x4244 -1 x4343 -1 x4442 -1 x4541 -1 x4640 -1 x4739 -1 x4838 -1 x4937 -1 x5036 -1 x5135 -1 x5234 -1 x5333 -1 x5432 -1 x5531 -1 x5630 -1 x5729 -1 x5828 -1 x5927 -1 x6026 -1 x6125 -1 x6224 -1 x6323 -1 x6422 -1 x6521 -1 x6620 -1 x6719 -1 x6818 -1 x6917 -1 x7016 -1 x7115 -1 x7214 -1 x7313 -1 x7412 -1 x7511 -1 x7610 -1 x7709 -1 x7808 -1 x7907 -1 x8006 -1 x8105 -1 x8204 -1 x8303 -1 x8402 -1 x8501 -1 x8600 -1 x8699 -1 x8798 -1 x8897 -1 x8996 -1 x9095 -1 x9194 -1 x9293 -1 x9392 -1 x9491 -1 x9590 -1 x9689 -1 x9788 -1 x9887 >= -1;
+-1 x87 -1 x186 -1 x285 -1 x384 -1 x483 -1 x582 -1 x681 -1 x780 -1 x879 -1 x978 -1 x1077 -1 x1176 -1 x1275 -1 x1374 -1 x1473 -1 x1572 -1 x1671 -1 x1770 -1 x1869 -1 x1968 -1 x2067 -1 x2166 -1 x2265 -1 x2364 -1 x2463 -1 x2562 -1 x2661 -1 x2760 -1 x2859 -1 x2958 -1 x3057 -1 x3156 -1 x3255 -1 x3354 -1 x3453 -1 x3552 -1 x3651 -1 x3750 -1 x3849 -1 x3948 -1 x4047 -1 x4146 -1 x4245 -1 x4344 -1 x4443 -1 x4542 -1 x4641 -1 x4740 -1 x4839 -1 x4938 -1 x5037 -1 x5136 -1 x5235 -1 x5334 -1 x5433 -1 x5532 -1 x5631 -1 x5730 -1 x5829 -1 x5928 -1 x6027 -1 x6126 -1 x6225 -1 x6324 -1 x6423 -1 x6522 -1 x6621 -1 x6720 -1 x6819 -1 x6918 -1 x7017 -1 x7116 -1 x7215 -1 x7314 -1 x7413 -1 x7512 -1 x7611 -1 x7710 -1 x7809 -1 x7908 -1 x8007 -1 x8106 -1 x8205 -1 x8304 -1 x8403 -1 x8502 -1 x8601 -1 x8700 -1 x8799 -1 x8898 -1 x8997 -1 x9096 -1 x9195 -1 x9294 -1 x9393 -1 x9492 -1 x9591 -1 x9690 -1 x9789 -1 x9888 >= -1;
+-1 x88 -1 x187 -1 x286 -1 x385 -1 x484 -1 x583 -1 x682 -1 x781 -1 x880 -1 x979 -1 x1078 -1 x1177 -1 x1276 -1 x1375 -1 x1474 -1 x1573 -1 x1672 -1 x1771 -1 x1870 -1 x1969 -1 x2068 -1 x2167 -1 x2266 -1 x2365 -1 x2464 -1 x2563 -1 x2662 -1 x2761 -1 x2860 -1 x2959 -1 x3058 -1 x3157 -1 x3256 -1 x3355 -1 x3454 -1 x3553 -1 x3652 -1 x3751 -1 x3850 -1 x3949 -1 x4048 -1 x4147 -1 x4246 -1 x4345 -1 x4444 -1 x4543 -1 x4642 -1 x4741 -1 x4840 -1 x4939 -1 x5038 -1 x5137 -1 x5236 -1 x5335 -1 x5434 -1 x5533 -1 x5632 -1 x5731 -1 x5830 -1 x5929 -1 x6028 -1 x6127 -1 x6226 -1 x6325 -1 x6424 -1 x6523 -1 x6622 -1 x6721 -1 x6820 -1 x6919 -1 x7018 -1 x7117 -1 x7216 -1 x7315 -1 x7414 -1 x7513 -1 x7612 -1 x7711 -1 x7810 -1 x7909 -1 x8008 -1 x8107 -1 x8206 -1 x8305 -1 x8404 -1 x8503 -1 x8602 -1 x8701 -1 x8800 -1 x8899 -1 x8998 -1 x9097 -1 x9196 -1 x9295 -1 x9394 -1 x9493 -1 x9592 -1 x9691 -1 x9790 -1 x9889 >= -1;
+-1 x89 -1 x188 -1 x287 -1 x386 -1 x485 -1 x584 -1 x683 -1 x782 -1 x881 -1 x980 -1 x1079 -1 x1178 -1 x1277 -1 x1376 -1 x1475 -1 x1574 -1 x1673 -1 x1772 -1 x1871 -1 x1970 -1 x2069 -1 x2168 -1 x2267 -1 x2366 -1 x2465 -1 x2564 -1 x2663 -1 x2762 -1 x2861 -1 x2960 -1 x3059 -1 x3158 -1 x3257 -1 x3356 -1 x3455 -1 x3554 -1 x3653 -1 x3752 -1 x3851 -1 x3950 -1 x4049 -1 x4148 -1 x4247 -1 x4346 -1 x4445 -1 x4544 -1 x4643 -1 x4742 -1 x4841 -1 x4940 -1 x5039 -1 x5138 -1 x5237 -1 x5336 -1 x5435 -1 x5534 -1 x5633 -1 x5732 -1 x5831 -1 x5930 -1 x6029 -1 x6128 -1 x6227 -1 x6326 -1 x6425 -1 x6524 -1 x6623 -1 x6722 -1 x6821 -1 x6920 -1 x7019 -1 x7118 -1 x7217 -1 x7316 -1 x7415 -1 x7514 -1 x7613 -1 x7712 -1 x7811 -1 x7910 -1 x8009 -1 x8108 -1 x8207 -1 x8306 -1 x8405 -1 x8504 -1 x8603 -1 x8702 -1 x8801 -1 x8900 -1 x8999 -1 x9098 -1 x9197 -1 x9296 -1 x9395 -1 x9494 -1 x9593 -1 x9692 -1 x9791 -1 x9890 >= -1;
+-1 x90 -1 x189 -1 x288 -1 x387 -1 x486 -1 x585 -1 x684 -1 x783 -1 x882 -1 x981 -1 x1080 -1 x1179 -1 x1278 -1 x1377 -1 x1476 -1 x1575 -1 x1674 -1 x1773 -1 x1872 -1 x1971 -1 x2070 -1 x2169 -1 x2268 -1 x2367 -1 x2466 -1 x2565 -1 x2664 -1 x2763 -1 x2862 -1 x2961 -1 x3060 -1 x3159 -1 x3258 -1 x3357 -1 x3456 -1 x3555 -1 x3654 -1 x3753 -1 x3852 -1 x3951 -1 x4050 -1 x4149 -1 x4248 -1 x4347 -1 x4446 -1 x4545 -1 x4644 -1 x4743 -1 x4842 -1 x4941 -1 x5040 -1 x5139 -1 x5238 -1 x5337 -1 x5436 -1 x5535 -1 x5634 -1 x5733 -1 x5832 -1 x5931 -1 x6030 -1 x6129 -1 x6228 -1 x6327 -1 x6426 -1 x6525 -1 x6624 -1 x6723 -1 x6822 -1 x6921 -1 x7020 -1 x7119 -1 x7218 -1 x7317 -1 x7416 -1 x7515 -1 x7614 -1 x7713 -1 x7812 -1 x7911 -1 x8010 -1 x8109 -1 x8208 -1 x8307 -1 x8406 -1 x8505 -1 x8604 -1 x8703 -1 x8802 -1 x8901 -1 x9000 -1 x9099 -1 x9198 -1 x9297 -1 x9396 -1 x9495 -1 x9594 -1 x9693 -1 x9792 -1 x9891 >= -1;
+-1 x91 -1 x190 -1 x289 -1 x388 -1 x487 -1 x586 -1 x685 -1 x784 -1 x883 -1 x982 -1 x1081 -1 x1180 -1 x1279 -1 x1378 -1 x1477 -1 x1576 -1 x1675 -1 x1774 -1 x1873 -1 x1972 -1 x2071 -1 x2170 -1 x2269 -1 x2368 -1 x2467 -1 x2566 -1 x2665 -1 x2764 -1 x2863 -1 x2962 -1 x3061 -1 x3160 -1 x3259 -1 x3358 -1 x3457 -1 x3556 -1 x3655 -1 x3754 -1 x3853 -1 x3952 -1 x4051 -1 x4150 -1 x4249 -1 x4348 -1 x4447 -1 x4546 -1 x4645 -1 x4744 -1 x4843 -1 x4942 -1 x5041 -1 x5140 -1 x5239 -1 x5338 -1 x5437 -1 x5536 -1 x5635 -1 x5734 -1 x5833 -1 x5932 -1 x6031 -1 x6130 -1 x6229 -1 x6328 -1 x6427 -1 x6526 -1 x6625 -1 x6724 -1 x6823 -1 x6922 -1 x7021 -1 x7120 -1 x7219 -1 x7318 -1 x7417 -1 x7516 -1 x7615 -1 x7714 -1 x7813 -1 x7912 -1 x8011 -1 x8110 -1 x8209 -1 x8308 -1 x8407 -1 x8506 -1 x8605 -1 x8704 -1 x8803 -1 x8902 -1 x9001 -1 x9100 -1 x9199 -1 x9298 -1 x9397 -1 x9496 -1 x9595 -1 x9694 -1 x9793 -1 x9892 >= -1;
+-1 x92 -1 x191 -1 x290 -1 x389 -1 x488 -1 x587 -1 x686 -1 x785 -1 x884 -1 x983 -1 x1082 -1 x1181 -1 x1280 -1 x1379 -1 x1478 -1 x1577 -1 x1676 -1 x1775 -1 x1874 -1 x1973 -1 x2072 -1 x2171 -1 x2270 -1 x2369 -1 x2468 -1 x2567 -1 x2666 -1 x2765 -1 x2864 -1 x2963 -1 x3062 -1 x3161 -1 x3260 -1 x3359 -1 x3458 -1 x3557 -1 x3656 -1 x3755 -1 x3854 -1 x3953 -1 x4052 -1 x4151 -1 x4250 -1 x4349 -1 x4448 -1 x4547 -1 x4646 -1 x4745 -1 x4844 -1 x4943 -1 x5042 -1 x5141 -1 x5240 -1 x5339 -1 x5438 -1 x5537 -1 x5636 -1 x5735 -1 x5834 -1 x5933 -1 x6032 -1 x6131 -1 x6230 -1 x6329 -1 x6428 -1 x6527 -1 x6626 -1 x6725 -1 x6824 -1 x6923 -1 x7022 -1 x7121 -1 x7220 -1 x7319 -1 x7418 -1 x7517 -1 x7616 -1 x7715 -1 x7814 -1 x7913 -1 x8012 -1 x8111 -1 x8210 -1 x8309 -1 x8408 -1 x8507 -1 x8606 -1 x8705 -1 x8804 -1 x8903 -1 x9002 -1 x9101 -1 x9200 -1 x9299 -1 x9398 -1 x9497 -1 x9596 -1 x9695 -1 x9794 -1 x9893 >= -1;
+-1 x93 -1 x192 -1 x291 -1 x390 -1 x489 -1 x588 -1 x687 -1 x786 -1 x885 -1 x984 -1 x1083 -1 x1182 -1 x1281 -1 x1380 -1 x1479 -1 x1578 -1 x1677 -1 x1776 -1 x1875 -1 x1974 -1 x2073 -1 x2172 -1 x2271 -1 x2370 -1 x2469 -1 x2568 -1 x2667 -1 x2766 -1 x2865 -1 x2964 -1 x3063 -1 x3162 -1 x3261 -1 x3360 -1 x3459 -1 x3558 -1 x3657 -1 x3756 -1 x3855 -1 x3954 -1 x4053 -1 x4152 -1 x4251 -1 x4350 -1 x4449 -1 x4548 -1 x4647 -1 x4746 -1 x4845 -1 x4944 -1 x5043 -1 x5142 -1 x5241 -1 x5340 -1 x5439 -1 x5538 -1 x5637 -1 x5736 -1 x5835 -1 x5934 -1 x6033 -1 x6132 -1 x6231 -1 x6330 -1 x6429 -1 x6528 -1 x6627 -1 x6726 -1 x6825 -1 x6924 -1 x7023 -1 x7122 -1 x7221 -1 x7320 -1 x7419 -1 x7518 -1 x7617 -1 x7716 -1 x7815 -1 x7914 -1 x8013 -1 x8112 -1 x8211 -1 x8310 -1 x8409 -1 x8508 -1 x8607 -1 x8706 -1 x8805 -1 x8904 -1 x9003 -1 x9102 -1 x9201 -1 x9300 -1 x9399 -1 x9498 -1 x9597 -1 x9696 -1 x9795 -1 x9894 >= -1;
+-1 x94 -1 x193 -1 x292 -1 x391 -1 x490 -1 x589 -1 x688 -1 x787 -1 x886 -1 x985 -1 x1084 -1 x1183 -1 x1282 -1 x1381 -1 x1480 -1 x1579 -1 x1678 -1 x1777 -1 x1876 -1 x1975 -1 x2074 -1 x2173 -1 x2272 -1 x2371 -1 x2470 -1 x2569 -1 x2668 -1 x2767 -1 x2866 -1 x2965 -1 x3064 -1 x3163 -1 x3262 -1 x3361 -1 x3460 -1 x3559 -1 x3658 -1 x3757 -1 x3856 -1 x3955 -1 x4054 -1 x4153 -1 x4252 -1 x4351 -1 x4450 -1 x4549 -1 x4648 -1 x4747 -1 x4846 -1 x4945 -1 x5044 -1 x5143 -1 x5242 -1 x5341 -1 x5440 -1 x5539 -1 x5638 -1 x5737 -1 x5836 -1 x5935 -1 x6034 -1 x6133 -1 x6232 -1 x6331 -1 x6430 -1 x6529 -1 x6628 -1 x6727 -1 x6826 -1 x6925 -1 x7024 -1 x7123 -1 x7222 -1 x7321 -1 x7420 -1 x7519 -1 x7618 -1 x7717 -1 x7816 -1 x7915 -1 x8014 -1 x8113 -1 x8212 -1 x8311 -1 x8410 -1 x8509 -1 x8608 -1 x8707 -1 x8806 -1 x8905 -1 x9004 -1 x9103 -1 x9202 -1 x9301 -1 x9400 -1 x9499 -1 x9598 -1 x9697 -1 x9796 -1 x9895 >= -1;
+-1 x95 -1 x194 -1 x293 -1 x392 -1 x491 -1 x590 -1 x689 -1 x788 -1 x887 -1 x986 -1 x1085 -1 x1184 -1 x1283 -1 x1382 -1 x1481 -1 x1580 -1 x1679 -1 x1778 -1 x1877 -1 x1976 -1 x2075 -1 x2174 -1 x2273 -1 x2372 -1 x2471 -1 x2570 -1 x2669 -1 x2768 -1 x2867 -1 x2966 -1 x3065 -1 x3164 -1 x3263 -1 x3362 -1 x3461 -1 x3560 -1 x3659 -1 x3758 -1 x3857 -1 x3956 -1 x4055 -1 x4154 -1 x4253 -1 x4352 -1 x4451 -1 x4550 -1 x4649 -1 x4748 -1 x4847 -1 x4946 -1 x5045 -1 x5144 -1 x5243 -1 x5342 -1 x5441 -1 x5540 -1 x5639 -1 x5738 -1 x5837 -1 x5936 -1 x6035 -1 x6134 -1 x6233 -1 x6332 -1 x6431 -1 x6530 -1 x6629 -1 x6728 -1 x6827 -1 x6926 -1 x7025 -1 x7124 -1 x7223 -1 x7322 -1 x7421 -1 x7520 -1 x7619 -1 x7718 -1 x7817 -1 x7916 -1 x8015 -1 x8114 -1 x8213 -1 x8312 -1 x8411 -1 x8510 -1 x8609 -1 x8708 -1 x8807 -1 x8906 -1 x9005 -1 x9104 -1 x9203 -1 x9302 -1 x9401 -1 x9500 -1 x9599 -1 x9698 -1 x9797 -1 x9896 >= -1;
+-1 x96 -1 x195 -1 x294 -1 x393 -1 x492 -1 x591 -1 x690 -1 x789 -1 x888 -1 x987 -1 x1086 -1 x1185 -1 x1284 -1 x1383 -1 x1482 -1 x1581 -1 x1680 -1 x1779 -1 x1878 -1 x1977 -1 x2076 -1 x2175 -1 x2274 -1 x2373 -1 x2472 -1 x2571 -1 x2670 -1 x2769 -1 x2868 -1 x2967 -1 x3066 -1 x3165 -1 x3264 -1 x3363 -1 x3462 -1 x3561 -1 x3660 -1 x3759 -1 x3858 -1 x3957 -1 x4056 -1 x4155 -1 x4254 -1 x4353 -1 x4452 -1 x4551 -1 x4650 -1 x4749 -1 x4848 -1 x4947 -1 x5046 -1 x5145 -1 x5244 -1 x5343 -1 x5442 -1 x5541 -1 x5640 -1 x5739 -1 x5838 -1 x5937 -1 x6036 -1 x6135 -1 x6234 -1 x6333 -1 x6432 -1 x6531 -1 x6630 -1 x6729 -1 x6828 -1 x6927 -1 x7026 -1 x7125 -1 x7224 -1 x7323 -1 x7422 -1 x7521 -1 x7620 -1 x7719 -1 x7818 -1 x7917 -1 x8016 -1 x8115 -1 x8214 -1 x8313 -1 x8412 -1 x8511 -1 x8610 -1 x8709 -1 x8808 -1 x8907 -1 x9006 -1 x9105 -1 x9204 -1 x9303 -1 x9402 -1 x9501 -1 x9600 -1 x9699 -1 x9798 -1 x9897 >= -1;
+-1 x97 -1 x196 -1 x295 -1 x394 -1 x493 -1 x592 -1 x691 -1 x790 -1 x889 -1 x988 -1 x1087 -1 x1186 -1 x1285 -1 x1384 -1 x1483 -1 x1582 -1 x1681 -1 x1780 -1 x1879 -1 x1978 -1 x2077 -1 x2176 -1 x2275 -1 x2374 -1 x2473 -1 x2572 -1 x2671 -1 x2770 -1 x2869 -1 x2968 -1 x3067 -1 x3166 -1 x3265 -1 x3364 -1 x3463 -1 x3562 -1 x3661 -1 x3760 -1 x3859 -1 x3958 -1 x4057 -1 x4156 -1 x4255 -1 x4354 -1 x4453 -1 x4552 -1 x4651 -1 x4750 -1 x4849 -1 x4948 -1 x5047 -1 x5146 -1 x5245 -1 x5344 -1 x5443 -1 x5542 -1 x5641 -1 x5740 -1 x5839 -1 x5938 -1 x6037 -1 x6136 -1 x6235 -1 x6334 -1 x6433 -1 x6532 -1 x6631 -1 x6730 -1 x6829 -1 x6928 -1 x7027 -1 x7126 -1 x7225 -1 x7324 -1 x7423 -1 x7522 -1 x7621 -1 x7720 -1 x7819 -1 x7918 -1 x8017 -1 x8116 -1 x8215 -1 x8314 -1 x8413 -1 x8512 -1 x8611 -1 x8710 -1 x8809 -1 x8908 -1 x9007 -1 x9106 -1 x9205 -1 x9304 -1 x9403 -1 x9502 -1 x9601 -1 x9700 -1 x9799 -1 x9898 >= -1;
+-1 x98 -1 x197 -1 x296 -1 x395 -1 x494 -1 x593 -1 x692 -1 x791 -1 x890 -1 x989 -1 x1088 -1 x1187 -1 x1286 -1 x1385 -1 x1484 -1 x1583 -1 x1682 -1 x1781 -1 x1880 -1 x1979 -1 x2078 -1 x2177 -1 x2276 -1 x2375 -1 x2474 -1 x2573 -1 x2672 -1 x2771 -1 x2870 -1 x2969 -1 x3068 -1 x3167 -1 x3266 -1 x3365 -1 x3464 -1 x3563 -1 x3662 -1 x3761 -1 x3860 -1 x3959 -1 x4058 -1 x4157 -1 x4256 -1 x4355 -1 x4454 -1 x4553 -1 x4652 -1 x4751 -1 x4850 -1 x4949 -1 x5048 -1 x5147 -1 x5246 -1 x5345 -1 x5444 -1 x5543 -1 x5642 -1 x5741 -1 x5840 -1 x5939 -1 x6038 -1 x6137 -1 x6236 -1 x6335 -1 x6434 -1 x6533 -1 x6632 -1 x6731 -1 x6830 -1 x6929 -1 x7028 -1 x7127 -1 x7226 -1 x7325 -1 x7424 -1 x7523 -1 x7622 -1 x7721 -1 x7820 -1 x7919 -1 x8018 -1 x8117 -1 x8216 -1 x8315 -1 x8414 -1 x8513 -1 x8612 -1 x8711 -1 x8810 -1 x8909 -1 x9008 -1 x9107 -1 x9206 -1 x9305 -1 x9404 -1 x9503 -1 x9602 -1 x9701 -1 x9800 -1 x9899 >= -1;
+-1 x99 -1 x198 -1 x297 -1 x396 -1 x495 -1 x594 -1 x693 -1 x792 -1 x891 -1 x990 -1 x1089 -1 x1188 -1 x1287 -1 x1386 -1 x1485 -1 x1584 -1 x1683 -1 x1782 -1 x1881 -1 x1980 -1 x2079 -1 x2178 -1 x2277 -1 x2376 -1 x2475 -1 x2574 -1 x2673 -1 x2772 -1 x2871 -1 x2970 -1 x3069 -1 x3168 -1 x3267 -1 x3366 -1 x3465 -1 x3564 -1 x3663 -1 x3762 -1 x3861 -1 x3960 -1 x4059 -1 x4158 -1 x4257 -1 x4356 -1 x4455 -1 x4554 -1 x4653 -1 x4752 -1 x4851 -1 x4950 -1 x5049 -1 x5148 -1 x5247 -1 x5346 -1 x5445 -1 x5544 -1 x5643 -1 x5742 -1 x5841 -1 x5940 -1 x6039 -1 x6138 -1 x6237 -1 x6336 -1 x6435 -1 x6534 -1 x6633 -1 x6732 -1 x6831 -1 x6930 -1 x7029 -1 x7128 -1 x7227 -1 x7326 -1 x7425 -1 x7524 -1 x7623 -1 x7722 -1 x7821 -1 x7920 -1 x8019 -1 x8118 -1 x8217 -1 x8316 -1 x8415 -1 x8514 -1 x8613 -1 x8712 -1 x8811 -1 x8910 -1 x9009 -1 x9108 -1 x9207 -1 x9306 -1 x9405 -1 x9504 -1 x9603 -1 x9702 -1 x9801 -1 x9900 >= -1;
diff --git a/samples/pbs/pigeonhole_10_9.opb b/samples/pbs/pigeonhole_10_9.opb
new file mode 100644
--- /dev/null
+++ b/samples/pbs/pigeonhole_10_9.opb
@@ -0,0 +1,20 @@
+* #variable= 90 #constraint= 19
++1 x1 +1 x2 +1 x3 +1 x4 +1 x5 +1 x6 +1 x7 +1 x8 +1 x9 >= 1;
++1 x10 +1 x11 +1 x12 +1 x13 +1 x14 +1 x15 +1 x16 +1 x17 +1 x18 >= 1;
++1 x19 +1 x20 +1 x21 +1 x22 +1 x23 +1 x24 +1 x25 +1 x26 +1 x27 >= 1;
++1 x28 +1 x29 +1 x30 +1 x31 +1 x32 +1 x33 +1 x34 +1 x35 +1 x36 >= 1;
++1 x37 +1 x38 +1 x39 +1 x40 +1 x41 +1 x42 +1 x43 +1 x44 +1 x45 >= 1;
++1 x46 +1 x47 +1 x48 +1 x49 +1 x50 +1 x51 +1 x52 +1 x53 +1 x54 >= 1;
++1 x55 +1 x56 +1 x57 +1 x58 +1 x59 +1 x60 +1 x61 +1 x62 +1 x63 >= 1;
++1 x64 +1 x65 +1 x66 +1 x67 +1 x68 +1 x69 +1 x70 +1 x71 +1 x72 >= 1;
++1 x73 +1 x74 +1 x75 +1 x76 +1 x77 +1 x78 +1 x79 +1 x80 +1 x81 >= 1;
++1 x82 +1 x83 +1 x84 +1 x85 +1 x86 +1 x87 +1 x88 +1 x89 +1 x90 >= 1;
+-1 x1 -1 x10 -1 x19 -1 x28 -1 x37 -1 x46 -1 x55 -1 x64 -1 x73 -1 x82 >= -1;
+-1 x2 -1 x11 -1 x20 -1 x29 -1 x38 -1 x47 -1 x56 -1 x65 -1 x74 -1 x83 >= -1;
+-1 x3 -1 x12 -1 x21 -1 x30 -1 x39 -1 x48 -1 x57 -1 x66 -1 x75 -1 x84 >= -1;
+-1 x4 -1 x13 -1 x22 -1 x31 -1 x40 -1 x49 -1 x58 -1 x67 -1 x76 -1 x85 >= -1;
+-1 x5 -1 x14 -1 x23 -1 x32 -1 x41 -1 x50 -1 x59 -1 x68 -1 x77 -1 x86 >= -1;
+-1 x6 -1 x15 -1 x24 -1 x33 -1 x42 -1 x51 -1 x60 -1 x69 -1 x78 -1 x87 >= -1;
+-1 x7 -1 x16 -1 x25 -1 x34 -1 x43 -1 x52 -1 x61 -1 x70 -1 x79 -1 x88 >= -1;
+-1 x8 -1 x17 -1 x26 -1 x35 -1 x44 -1 x53 -1 x62 -1 x71 -1 x80 -1 x89 >= -1;
+-1 x9 -1 x18 -1 x27 -1 x36 -1 x45 -1 x54 -1 x63 -1 x72 -1 x81 -1 x90 >= -1;
diff --git a/samples/pbs/pigeonhole_15_14.opb b/samples/pbs/pigeonhole_15_14.opb
new file mode 100644
--- /dev/null
+++ b/samples/pbs/pigeonhole_15_14.opb
@@ -0,0 +1,30 @@
+* #variable= 210 #constraint= 29
++1 x1 +1 x2 +1 x3 +1 x4 +1 x5 +1 x6 +1 x7 +1 x8 +1 x9 +1 x10 +1 x11 +1 x12 +1 x13 +1 x14 >= 1;
++1 x15 +1 x16 +1 x17 +1 x18 +1 x19 +1 x20 +1 x21 +1 x22 +1 x23 +1 x24 +1 x25 +1 x26 +1 x27 +1 x28 >= 1;
++1 x29 +1 x30 +1 x31 +1 x32 +1 x33 +1 x34 +1 x35 +1 x36 +1 x37 +1 x38 +1 x39 +1 x40 +1 x41 +1 x42 >= 1;
++1 x43 +1 x44 +1 x45 +1 x46 +1 x47 +1 x48 +1 x49 +1 x50 +1 x51 +1 x52 +1 x53 +1 x54 +1 x55 +1 x56 >= 1;
++1 x57 +1 x58 +1 x59 +1 x60 +1 x61 +1 x62 +1 x63 +1 x64 +1 x65 +1 x66 +1 x67 +1 x68 +1 x69 +1 x70 >= 1;
++1 x71 +1 x72 +1 x73 +1 x74 +1 x75 +1 x76 +1 x77 +1 x78 +1 x79 +1 x80 +1 x81 +1 x82 +1 x83 +1 x84 >= 1;
++1 x85 +1 x86 +1 x87 +1 x88 +1 x89 +1 x90 +1 x91 +1 x92 +1 x93 +1 x94 +1 x95 +1 x96 +1 x97 +1 x98 >= 1;
++1 x99 +1 x100 +1 x101 +1 x102 +1 x103 +1 x104 +1 x105 +1 x106 +1 x107 +1 x108 +1 x109 +1 x110 +1 x111 +1 x112 >= 1;
++1 x113 +1 x114 +1 x115 +1 x116 +1 x117 +1 x118 +1 x119 +1 x120 +1 x121 +1 x122 +1 x123 +1 x124 +1 x125 +1 x126 >= 1;
++1 x127 +1 x128 +1 x129 +1 x130 +1 x131 +1 x132 +1 x133 +1 x134 +1 x135 +1 x136 +1 x137 +1 x138 +1 x139 +1 x140 >= 1;
++1 x141 +1 x142 +1 x143 +1 x144 +1 x145 +1 x146 +1 x147 +1 x148 +1 x149 +1 x150 +1 x151 +1 x152 +1 x153 +1 x154 >= 1;
++1 x155 +1 x156 +1 x157 +1 x158 +1 x159 +1 x160 +1 x161 +1 x162 +1 x163 +1 x164 +1 x165 +1 x166 +1 x167 +1 x168 >= 1;
++1 x169 +1 x170 +1 x171 +1 x172 +1 x173 +1 x174 +1 x175 +1 x176 +1 x177 +1 x178 +1 x179 +1 x180 +1 x181 +1 x182 >= 1;
++1 x183 +1 x184 +1 x185 +1 x186 +1 x187 +1 x188 +1 x189 +1 x190 +1 x191 +1 x192 +1 x193 +1 x194 +1 x195 +1 x196 >= 1;
++1 x197 +1 x198 +1 x199 +1 x200 +1 x201 +1 x202 +1 x203 +1 x204 +1 x205 +1 x206 +1 x207 +1 x208 +1 x209 +1 x210 >= 1;
+-1 x1 -1 x15 -1 x29 -1 x43 -1 x57 -1 x71 -1 x85 -1 x99 -1 x113 -1 x127 -1 x141 -1 x155 -1 x169 -1 x183 -1 x197 >= -1;
+-1 x2 -1 x16 -1 x30 -1 x44 -1 x58 -1 x72 -1 x86 -1 x100 -1 x114 -1 x128 -1 x142 -1 x156 -1 x170 -1 x184 -1 x198 >= -1;
+-1 x3 -1 x17 -1 x31 -1 x45 -1 x59 -1 x73 -1 x87 -1 x101 -1 x115 -1 x129 -1 x143 -1 x157 -1 x171 -1 x185 -1 x199 >= -1;
+-1 x4 -1 x18 -1 x32 -1 x46 -1 x60 -1 x74 -1 x88 -1 x102 -1 x116 -1 x130 -1 x144 -1 x158 -1 x172 -1 x186 -1 x200 >= -1;
+-1 x5 -1 x19 -1 x33 -1 x47 -1 x61 -1 x75 -1 x89 -1 x103 -1 x117 -1 x131 -1 x145 -1 x159 -1 x173 -1 x187 -1 x201 >= -1;
+-1 x6 -1 x20 -1 x34 -1 x48 -1 x62 -1 x76 -1 x90 -1 x104 -1 x118 -1 x132 -1 x146 -1 x160 -1 x174 -1 x188 -1 x202 >= -1;
+-1 x7 -1 x21 -1 x35 -1 x49 -1 x63 -1 x77 -1 x91 -1 x105 -1 x119 -1 x133 -1 x147 -1 x161 -1 x175 -1 x189 -1 x203 >= -1;
+-1 x8 -1 x22 -1 x36 -1 x50 -1 x64 -1 x78 -1 x92 -1 x106 -1 x120 -1 x134 -1 x148 -1 x162 -1 x176 -1 x190 -1 x204 >= -1;
+-1 x9 -1 x23 -1 x37 -1 x51 -1 x65 -1 x79 -1 x93 -1 x107 -1 x121 -1 x135 -1 x149 -1 x163 -1 x177 -1 x191 -1 x205 >= -1;
+-1 x10 -1 x24 -1 x38 -1 x52 -1 x66 -1 x80 -1 x94 -1 x108 -1 x122 -1 x136 -1 x150 -1 x164 -1 x178 -1 x192 -1 x206 >= -1;
+-1 x11 -1 x25 -1 x39 -1 x53 -1 x67 -1 x81 -1 x95 -1 x109 -1 x123 -1 x137 -1 x151 -1 x165 -1 x179 -1 x193 -1 x207 >= -1;
+-1 x12 -1 x26 -1 x40 -1 x54 -1 x68 -1 x82 -1 x96 -1 x110 -1 x124 -1 x138 -1 x152 -1 x166 -1 x180 -1 x194 -1 x208 >= -1;
+-1 x13 -1 x27 -1 x41 -1 x55 -1 x69 -1 x83 -1 x97 -1 x111 -1 x125 -1 x139 -1 x153 -1 x167 -1 x181 -1 x195 -1 x209 >= -1;
+-1 x14 -1 x28 -1 x42 -1 x56 -1 x70 -1 x84 -1 x98 -1 x112 -1 x126 -1 x140 -1 x154 -1 x168 -1 x182 -1 x196 -1 x210 >= -1;
diff --git a/samples/pbs/pigeonhole_5_4.opb b/samples/pbs/pigeonhole_5_4.opb
new file mode 100644
--- /dev/null
+++ b/samples/pbs/pigeonhole_5_4.opb
@@ -0,0 +1,10 @@
+* #variable= 20 #constraint= 9
++1 x1 +1 x2 +1 x3 +1 x4 >= 1;
++1 x5 +1 x6 +1 x7 +1 x8 >= 1;
++1 x9 +1 x10 +1 x11 +1 x12 >= 1;
++1 x13 +1 x14 +1 x15 +1 x16 >= 1;
++1 x17 +1 x18 +1 x19 +1 x20 >= 1;
+-1 x1 -1 x5 -1 x9 -1 x13 -1 x17 >= -1;
+-1 x2 -1 x6 -1 x10 -1 x14 -1 x18 >= -1;
+-1 x3 -1 x7 -1 x11 -1 x15 -1 x19 >= -1;
+-1 x4 -1 x8 -1 x12 -1 x16 -1 x20 >= -1;
diff --git a/samples/qbf/example1.qdimacs b/samples/qbf/example1.qdimacs
new file mode 100644
--- /dev/null
+++ b/samples/qbf/example1.qdimacs
@@ -0,0 +1,5 @@
+c http://www.qbflib.org/qdimacs.html
+p cnf 4 2
+e 1 2 3 4 0
+-1 2 0
+2 -3 -4 0
diff --git a/samples/sat/empty.cnf b/samples/sat/empty.cnf
new file mode 100644
--- /dev/null
+++ b/samples/sat/empty.cnf
@@ -0,0 +1,1 @@
+p cnf 0 0
diff --git a/samples/sdp/example1.dat b/samples/sdp/example1.dat
new file mode 100644
--- /dev/null
+++ b/samples/sdp/example1.dat
@@ -0,0 +1,9 @@
+"Example 1: mDim = 3, nBLOCK = 1, {2}"
+   3  =  mDIM
+   1  =  nBLOCK
+   2  = bLOCKsTRUCT
+{48, -8, 20}
+{ {-11,  0}, { 0, 23} }
+{ { 10,  4}, { 4,  0} }
+{ {  0,  0}, { 0, -8} }
+{ {  0, -8}, {-8, -2} }
diff --git a/samples/sdp/example1.dat-s b/samples/sdp/example1.dat-s
new file mode 100644
--- /dev/null
+++ b/samples/sdp/example1.dat-s
@@ -0,0 +1,12 @@
+"Example 1: mDim = 3, nBLOCK = 1, {2}"
+   3  =  mDIM
+   1  =  nBLOCK
+   2  = bLOCKsTRUCT
+48, -8, 20
+0 1 1 1 -11
+0 1 2 2 23
+1 1 1 1 10
+1 1 1 2 4
+2 1 2 2 -8
+3 1 1 2 -8
+3 1 2 2 -2
diff --git a/samples/sdp/example2.dat b/samples/sdp/example2.dat
new file mode 100644
--- /dev/null
+++ b/samples/sdp/example2.dat
@@ -0,0 +1,54 @@
+*Example 2:
+*mDim = 5, nBLOCK = 3, {2,3,-2}
+   5  =  mDIM
+   3  =  nBLOCK
+   2    3   -2   = bLOCKsTRUCT
+{1.1, -10, 6.6 , 19 , 4.1}
+{
+{ { -1.4, -3.2 },
+  { -3.2,-28   }   }
+{ { 15,  -12,    2.1 },
+  {-12,   16,   -3.8 },
+  {  2.1, -3.8, 15   }   }
+  {  1.8, -4.0 }
+}
+{
+{ {  0.5,  5.2 },
+  {  5.2, -5.3 }   }
+{ {  7.8, -2.4,  6.0 },
+  { -2.4,  4.2,  6.5 },
+  {  6.0,  6.5,  2.1 }   }
+  { -4.5, -3.5 }
+}
+{
+{ { 1.7,  7.0 },
+  { 7.0, -9.3 }   }
+{ {-1.9, -0.9, -1.3 },
+  {-0.9, -0.8, -2.1 },
+  {-1.3, -2.1,  4.0 }   }
+  {-0.2, -3.7 }
+}
+{
+{ { 6.3, -7.5 },
+  {-7.5, -3.3 }   }
+{ { 0.2,  8.8,  5.4 },
+  { 8.8,  3.4, -0.4 },
+  { 5.4, -0.4,  7.5 }   }
+  {-3.3, -4.0 }
+}
+{
+{ { -2.4, -2.5 },
+  { -2.5, -2.9 }   }
+{ {  3.4, -3.2, -4.5 },
+  { -3.2,  3.0, -4.8 },
+  { -4.5, -4.8,  3.6 }   }
+  {  4.8 , 9.7 }
+}
+{
+{ { -6.5, -5.4 },
+  { -5.4, -6.6 }   }
+{ {  6.7, -7.2, -3.6 },
+  { -7.2,  7.3, -3.0 },
+  { -3.6, -3.0, -1.4 }   }
+  {  6.1, -1.5 }
+}
diff --git a/samples/smt/QF_ABV.smt2 b/samples/smt/QF_ABV.smt2
new file mode 100644
--- /dev/null
+++ b/samples/smt/QF_ABV.smt2
@@ -0,0 +1,20 @@
+(set-logic QF_ABV)
+(declare-fun x () (_ BitVec 32))
+(declare-fun y () (_ BitVec 16))
+(declare-fun z () (_ BitVec 20))
+(declare-fun A () (Array (_ BitVec 16) (_ BitVec 32)))
+(assert
+  (let ((c1 (= ((_ sign_extend 12) z) (select A y)))
+        (A2 (store A ((_ extract 15 0) x) x)))
+    (let ((c2 (= A A2)))
+      (let ((c3
+        (bvslt (concat z (_ bv5 12))
+               (bvand (bvor (bvxor (bvnot x)
+                                   (select A2 ((_ zero_extend 12) #b1111)))
+                            (concat #xAF02 y))
+                      (concat ((_ extract 15 0)
+                               (bvmul x (select (store A y x) #x35FB)))
+                              (bvashr (_ bv42 16) #x0001))))))
+        (and c1 (xor c2 c3))))))
+(check-sat)
+(exit)
diff --git a/samples/smt/QF_AUFLIA.smt2 b/samples/smt/QF_AUFLIA.smt2
new file mode 100644
--- /dev/null
+++ b/samples/smt/QF_AUFLIA.smt2
@@ -0,0 +1,15 @@
+(set-logic QF_AUFLIA)
+(declare-fun A () (Array Int Int))
+(declare-fun x () Int)
+(declare-fun y () Int)
+(declare-fun P () Bool)
+(declare-sort U 0)
+(declare-fun f (U) (Array Int Int))
+(declare-fun c () U)
+(assert
+  (let ((fc (f c)))
+    (and
+      (=> (= A (store fc x 5)) (> (+ (select fc y) (* 4 x)) 0))
+      (= P (< (select A (+ 3 y)) (* (- 2) x))))))
+(check-sat)
+(exit)
diff --git a/samples/smt/QF_BV.smt2 b/samples/smt/QF_BV.smt2
new file mode 100644
--- /dev/null
+++ b/samples/smt/QF_BV.smt2
@@ -0,0 +1,16 @@
+(set-logic QF_BV)
+(declare-fun x () (_ BitVec 32))
+(declare-fun y () (_ BitVec 16))
+(declare-fun z () (_ BitVec 20))
+(assert
+  (let ((c1 (= x ((_ sign_extend 12) z))))
+    (let ((c2 (= y ((_ extract 18 3) x))))
+      (let ((c3
+              (bvslt (concat z (_ bv5 12))
+                     (bvand (bvor (bvxor (bvnot x) ((_ zero_extend 28) #b1111))
+                                  (concat #xAF02 y))
+                            (concat (bvmul ((_ extract 31 16) x) y)
+                                    (bvashr (_ bv42 16) #x0001))))))
+        (and c1 (xor c2 c3))))))
+(check-sat)
+(exit)
diff --git a/samples/smt/QF_LIA.smt2 b/samples/smt/QF_LIA.smt2
new file mode 100644
--- /dev/null
+++ b/samples/smt/QF_LIA.smt2
@@ -0,0 +1,12 @@
+(set-logic QF_LIA)
+(declare-fun x () Int)
+(declare-fun y () Int)
+(declare-fun A () Bool)
+(assert
+  (let ((i1 (ite A (<= (+ (* 2 x) (* (- 1) y)) (- 4))
+                   (= (* y 5) (- 2 x)))))
+    (and
+      i1
+      (or (> x y) (= A (< (* 3 x) (+ (- 1) (* 1 (+ x y)))))))))
+(check-sat)
+(exit)
diff --git a/samples/smt/QF_LRA.smt2 b/samples/smt/QF_LRA.smt2
new file mode 100644
--- /dev/null
+++ b/samples/smt/QF_LRA.smt2
@@ -0,0 +1,12 @@
+(set-logic QF_LRA)
+(declare-fun x () Real)
+(declare-fun y () Real)
+(declare-fun A () Bool)
+(assert
+  (let ((i1 (ite A (<= (+ (* 2.0 x) (* (/ 1 3) y)) (- 4))
+                   (= (* y 1.5) (- 2 x)))))
+    (and
+      i1
+      (or (> x y) (= A (< (* 3 x) (+ (- 1) (* (/ 1 5) (+ x y)))))))))
+(check-sat)
+(exit)
diff --git a/samples/smt/QF_LRA_2.smt2 b/samples/smt/QF_LRA_2.smt2
new file mode 100644
--- /dev/null
+++ b/samples/smt/QF_LRA_2.smt2
@@ -0,0 +1,39 @@
+(set-option :print-success true)
+(set-logic QF_LRA)
+(declare-fun c0 () Bool)
+(declare-fun E0 () Bool)
+(declare-fun f0 () Bool)
+(declare-fun f1 () Bool)
+(push 1)
+(assert
+  (let ((.def_10 (not f0)))
+    (let ((.def_9 (not c0)))
+      (let ((.def_11 (or .def_9 .def_10)))
+        (let ((.def_7 (not f1)))
+          (let ((.def_8 (or c0 .def_7)))
+            (let ((.def_12 (and .def_8 .def_11)))
+  .def_12
+)))))))
+(check-sat)
+(pop 1)
+(declare-fun f2 () Bool)
+(declare-fun f3 () Bool)
+(declare-fun f4 () Bool)
+(declare-fun c1 () Bool)
+(declare-fun E1 () Bool)
+(assert
+  (let ((.def_23 (not f2)))
+    (let ((.def_20 (= c0 c1)))
+      (let ((.def_22 (or E0 .def_20)))
+        (let ((.def_24 (or .def_22 .def_23)))
+          (let ((.def_18 (not f4)))
+            (let ((.def_19 (or c1 .def_18)))
+              (let ((.def_25 (and .def_19 .def_24)))
+  .def_25
+))))))))
+(push 1)
+(check-sat)
+(assert (and f1 (not f1)))
+(check-sat)
+(pop 1)
+(exit)
diff --git a/samples/smt/QF_UF.smt2 b/samples/smt/QF_UF.smt2
new file mode 100644
--- /dev/null
+++ b/samples/smt/QF_UF.smt2
@@ -0,0 +1,14 @@
+(set-logic QF_UF)
+(set-info :status sat)
+(declare-sort U 0)
+(declare-fun f (U) U)
+(declare-fun g (U) U)
+(declare-fun A () Bool)
+(declare-fun x () U)
+(declare-fun y () U)
+(assert
+(let ((fx (f x))
+      (cls1 (or A (= x y))))
+  (and cls1 (distinct fx (g y)))))
+(check-sat)
+(exit)
diff --git a/samples/wbo/example-lin.wbo b/samples/wbo/example-lin.wbo
new file mode 100644
--- /dev/null
+++ b/samples/wbo/example-lin.wbo
@@ -0,0 +1,6 @@
+* #variable= 5 #constraint= 4 #soft= 4 mincost= 2 maxcost= 5 sumcost= 14
+soft: 15 ;
+[2] 1 x1 +4 x2 -2 x5 >= 2;
+[3] -1 x1 +4 x2 -2 x5 >= +3;
+[4] 12345678901234567890 x4 +4 x3 >= 10;
+[5] 2 x2 +3 x4 +2 x1 +3 x5 = 5;
diff --git a/samples/wbo/example1.wbo b/samples/wbo/example1.wbo
new file mode 100644
--- /dev/null
+++ b/samples/wbo/example1.wbo
@@ -0,0 +1,4 @@
+* #variable= 1 #constraint= 2 #soft= 2 mincost= 2 maxcost= 3 sumcost= 5
+soft: 6 ;
+[2] +1 x1 >= 1 ;
+[3] -1 x1 >= 0 ;
diff --git a/samples/wbo/example2.wbo b/samples/wbo/example2.wbo
new file mode 100644
--- /dev/null
+++ b/samples/wbo/example2.wbo
@@ -0,0 +1,5 @@
+* #variable= 2 #constraint= 3 #soft= 2 mincost= 2 maxcost= 3 sumcost= 5
+soft: 6 ;
+[2] +1 x1 >= 1 ;
+[3] +1 x2 >= 1 ;
+-1 x1 -1 x2 >= -1 ;
diff --git a/samples/wbo/example3.wbo b/samples/wbo/example3.wbo
new file mode 100644
--- /dev/null
+++ b/samples/wbo/example3.wbo
@@ -0,0 +1,8 @@
+* #variable= 4 #constraint= 6 #soft= 4 mincost= 2 maxcost= 5 sumcost= 14
+soft: 6 ;
+[2] +1 x1 >= 1;
+[3] +1 x2 >= 1;
+[4] +1 x3 >= 1;
+[5] +1 x4 >= 1;
+-1 x1 -1 x2 >= -1 ;
+-1 x3 -1 x4 >= -1 ;
diff --git a/src/BenchmarkSATLIB.hs b/src/BenchmarkSATLIB.hs
new file mode 100644
--- /dev/null
+++ b/src/BenchmarkSATLIB.hs
@@ -0,0 +1,39 @@
+module Main where
+
+import Control.Monad
+import Data.Array.IArray
+import Text.Printf
+import Criterion.Main
+import qualified Language.CNF.Parse.ParseDIMACS as DIMACS
+import qualified SAT
+
+solve :: FilePath -> IO ()
+solve fname = do
+  ret <- DIMACS.parseFile fname
+  case ret of
+    Left err  -> error $ show err
+    Right cnf -> do
+      solver <- SAT.newSolver
+      SAT.setRandomFreq solver 0
+      _ <- replicateM (DIMACS.numVars cnf) (SAT.newVar solver)
+      forM_ (DIMACS.clauses cnf) $ \clause ->
+        SAT.addClause solver (elems clause)
+      SAT.solve solver
+      return ()
+
+main :: IO ()
+main = do
+  Criterion.Main.defaultMain
+    [ bgroup "uf250-1065"
+        [ bench fname (solve path)
+        | i <- [(1::Int)..100]
+        , let fname = printf "uf250-0%d.cnf" i
+        , let path = "benchmarks/UF250.1065.100/" ++ fname
+        ]
+    , bgroup "uuf250-1065"
+        [ bench fname (solve path)
+        | i <- [(1::Int)..100]
+        , let fname = printf "uuf250-0%d.cnf" i
+        , let path = "benchmarks/UUF250.1065.100/" ++ fname
+        ]
+    ]
diff --git a/src/BoundsInference.hs b/src/BoundsInference.hs
new file mode 100644
--- /dev/null
+++ b/src/BoundsInference.hs
@@ -0,0 +1,85 @@
+{-# LANGUAGE ScopedTypeVariables, BangPatterns #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  BoundsInference
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (ScopedTypeVariables, BangPatterns)
+--
+-- Tightening variable bounds by constraint propagation.
+-- 
+-----------------------------------------------------------------------------
+module BoundsInference
+  ( BoundsEnv
+  , inferBounds
+  , LA.computeInterval
+  ) where
+
+import Control.Monad
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+
+import Data.Expr
+import Data.Formula
+import Data.Linear
+import Data.Interval
+import Data.LA (BoundsEnv)
+import qualified Data.LA as LA
+import Util (isInteger)
+
+type C r = (RelOp, LA.Expr r)
+
+-- | tightening variable bounds by constraint propagation.
+inferBounds :: forall r. (RealFrac r)
+  => LA.BoundsEnv r -- ^ initial bounds
+  -> [LA.Atom r]    -- ^ constraints
+  -> VarSet         -- ^ integral variables
+  -> Int            -- ^ limit of iterations
+  -> LA.BoundsEnv r
+inferBounds bounds constraints ivs limit = loop 0 bounds
+  where
+    cs :: VarMap [C r]
+    cs = IM.fromListWith (++) $ do
+      LA.Atom lhs op rhs <- constraints
+      let m = LA.coeffMap (lhs .-. rhs)
+      (v,c) <- IM.toList m
+      guard $ v /= LA.unitVar
+      let op' = if c < 0 then flipOp op else op
+          rhs' = (-1/c) .*. LA.fromCoeffMap (IM.delete v m)
+      return (v, [(op', rhs')])
+
+    loop  :: Int -> LA.BoundsEnv r -> LA.BoundsEnv r
+    loop !i b = if (limit>=0 && i>=limit) || b==b' then b else loop (i+1) b'
+      where
+        b' = refine b
+
+    refine :: LA.BoundsEnv r -> LA.BoundsEnv r
+    refine b = IM.mapWithKey (\v i -> tighten v $ f b (IM.findWithDefault [] v cs) i) b
+
+    -- tighten bounds of integer variables
+    tighten :: Var -> Interval r -> Interval r
+    tighten v x =
+      if v `IS.notMember` ivs
+        then x
+        else tightenToInteger x
+
+f :: (Real r, Fractional r) => LA.BoundsEnv r -> [C r] -> Interval r -> Interval r
+f b cs i = foldr intersection i $ do
+  (op, rhs) <- cs
+  let i' = LA.computeInterval b rhs
+      lb = lowerBound i'
+      ub = upperBound i'
+  case op of
+    Eql -> return i'
+    Le -> return $ interval Nothing ub
+    Ge -> return $ interval lb Nothing
+    Lt -> return $ interval Nothing (strict ub)
+    Gt -> return $ interval (strict lb) Nothing
+    NEq -> []
+
+strict :: EndPoint r -> EndPoint r
+strict Nothing = Nothing
+strict (Just (_,val)) = Just (False,val)
diff --git a/src/CongruenceClosure.hs b/src/CongruenceClosure.hs
new file mode 100644
--- /dev/null
+++ b/src/CongruenceClosure.hs
@@ -0,0 +1,203 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  CongruenceClosure
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- References:
+--
+-- * R. Nieuwenhuis and A. Oliveras, "Fast congruence closure and extensions,"
+--   Information and Computation, vol. 205, no. 4, pp. 557-580, Apr. 2007.
+--   <http://www.lsi.upc.edu/~oliveras/espai/papers/IC.pdf>
+--
+-----------------------------------------------------------------------------
+module CongruenceClosure
+  ( Solver
+  , Var
+  , FlatTerm (..)
+  , newSolver
+  , newVar
+  , merge
+  , areCongruent
+  ) where
+
+import Prelude hiding (lookup)
+
+import Control.Monad
+import Data.IORef
+import Data.Maybe
+import qualified Data.IntMap as IM
+
+type Var = Int
+
+data FlatTerm
+  = FTConst Var
+  | FTApp Var Var
+  deriving (Ord, Eq, Show)
+
+type Eqn1 = (FlatTerm, Var)
+type PendingEqn = Either (Var,Var) (Eqn1, Eqn1)
+
+data Solver
+  = Solver
+  { svVarCounter           :: IORef Int
+  , svPending              :: IORef [PendingEqn]
+  , svRepresentativeTable  :: IORef (IM.IntMap Var) -- 本当は配列が良い
+  , svClassList            :: IORef (IM.IntMap [Var])
+  , svUseList              :: IORef (IM.IntMap [Eqn1])
+  , svLookupTable          :: IORef (IM.IntMap (IM.IntMap Eqn1))
+  }
+
+newSolver :: IO Solver
+newSolver = do
+  vcnt     <- newIORef 0
+  pending  <- newIORef []
+  rep      <- newIORef IM.empty
+  classes  <- newIORef IM.empty
+  useList  <- newIORef IM.empty
+  lookup   <- newIORef IM.empty
+  return $
+    Solver
+    { svVarCounter          = vcnt
+    , svPending             = pending
+    , svRepresentativeTable = rep
+    , svClassList           = classes
+    , svUseList             = useList
+    , svLookupTable         = lookup
+    }
+
+newVar :: Solver -> IO Var
+newVar solver = do
+  v <- readIORef (svVarCounter solver)
+  writeIORef (svVarCounter solver) $! v + 1
+  modifyIORef (svRepresentativeTable solver) (IM.insert v v)
+  modifyIORef (svClassList solver) (IM.insert v [v])
+  modifyIORef (svUseList solver) (IM.insert v [])
+  return v
+
+merge :: Solver -> (FlatTerm, Var) -> IO ()
+merge solver (s, a) = do
+  case s of
+    FTConst c -> do
+      addToPending solver (Left (c, a))
+      propagate solver
+    FTApp a1 a2 -> do
+      a1' <- getRepresentative solver a1
+      a2' <- getRepresentative solver a2
+      ret <- lookup solver a1' a2'
+      case ret of
+        Just (FTApp b1 b2, b) -> do
+          addToPending solver $ Right ((FTApp a1 a2, a), (FTApp b1 b2, b))
+          propagate solver
+        Nothing -> do
+          setLookup solver a1' a2' (FTApp a1 a2, a)
+          modifyIORef (svUseList solver) $
+            IM.alter (Just . ((FTApp a1 a2, a) :) . fromMaybe []) a1' .
+            IM.alter (Just . ((FTApp a1 a2, a) :) . fromMaybe []) a2'
+
+propagate :: Solver -> IO ()
+propagate solver = go
+  where
+    go = do
+      ps <- readIORef (svPending solver)
+      case ps of
+        [] -> return ()
+        (p:ps') -> do
+          writeIORef (svPending solver) ps'
+          processEqn p
+          go
+
+    processEqn p = do
+      let (a,b) = case p of
+                    Left (a,b) -> (a,b)
+                    Right ((_, a), (_, b)) -> (a,b)
+      a' <- getRepresentative solver a
+      b' <- getRepresentative solver b
+      if a' == b'
+        then return ()
+        else do
+          clist <- readIORef (svClassList  solver)
+          let classA = clist IM.! a'
+              classB = clist IM.! b'
+          if length classA < length classB
+            then update a' b' classA classB
+            else update b' a' classB classA
+
+    update a' b' classA classB = do
+      modifyIORef (svRepresentativeTable solver) $ 
+        IM.union (IM.fromList [(c,b') | c <- classA])
+      modifyIORef (svClassList solver) $
+        IM.insert b' (classA ++ classB) . IM.delete a'
+
+      useList <- readIORef (svUseList solver)
+      forM_ (useList IM.! a') $ \(FTApp c1 c2, c) -> do -- FIXME: not exhaustive
+        c1' <- getRepresentative solver c1
+        c2' <- getRepresentative solver c2
+        ret <- lookup solver c1' c2'
+        case ret of
+          Just (FTApp d1 d2, d) -> do -- FIXME: not exhaustive
+            addToPending solver $ Right ((FTApp c1 c2, c), (FTApp d1 d2, d))
+          Nothing -> do
+            return ()
+      writeIORef (svUseList solver) $ IM.delete a' useList        
+
+areCongruent :: Solver -> FlatTerm -> FlatTerm -> IO Bool
+areCongruent solver t1 t2 = do
+  u1 <- normalize solver t1
+  u2 <- normalize solver t2
+  return $ u1 == u2
+
+normalize :: Solver -> FlatTerm -> IO FlatTerm
+normalize solver (FTConst c) = liftM FTConst $ getRepresentative solver c
+normalize solver (FTApp t1 t2) = do
+  u1 <- getRepresentative solver t1
+  u2 <- getRepresentative solver t2
+  ret <- lookup solver u1 u2
+  case ret of
+    Just (FTApp _ _, a) -> liftM FTConst $ getRepresentative solver a
+    Nothing -> return $ FTApp u1 u2
+
+{--------------------------------------------------------------------
+  Helper funcions
+--------------------------------------------------------------------}
+
+lookup :: Solver -> Var -> Var -> IO (Maybe Eqn1)
+lookup solver c1 c2 = do
+  tbl <- readIORef $ svLookupTable solver
+  return $ do
+     m <- IM.lookup c1 tbl
+     IM.lookup c2 m
+
+setLookup :: Solver -> Var -> Var -> Eqn1 -> IO ()
+setLookup solver a1 a2 eqn = do
+  modifyIORef (svLookupTable solver) $
+    IM.insertWith IM.union a1 (IM.singleton a2 eqn)
+
+addToPending :: Solver -> PendingEqn -> IO ()
+addToPending solver eqn = modifyIORef (svPending solver) (eqn :)
+
+getRepresentative :: Solver -> Var -> IO Var
+getRepresentative solver c = do
+  m <- readIORef $ svRepresentativeTable solver
+  return $ m IM.! c
+
+{--------------------------------------------------------------------
+  Test
+--------------------------------------------------------------------}
+
+test = do
+  solver <- newSolver
+  a <- newVar solver
+  b <- newVar solver
+  c <- newVar solver
+  d <- newVar solver
+  merge solver (FTConst a, c)
+  print =<< areCongruent solver (FTApp a b) (FTApp c d) -- False
+  merge solver (FTConst b, d)
+  print =<< areCongruent solver (FTApp a b) (FTApp c d) -- True
+
diff --git a/src/ContiTraverso.hs b/src/ContiTraverso.hs
new file mode 100644
--- /dev/null
+++ b/src/ContiTraverso.hs
@@ -0,0 +1,114 @@
+{-
+http://posso.dm.unipi.it/users/traverso/conti-traverso-ip.ps
+http://madscientist.jp/~ikegami/articles/IntroSequencePolynomial.html
+http://www.kurims.kyoto-u.ac.jp/~kyodo/kokyuroku/contents/pdf/1295-27.pdf
+-}
+module ContiTraverso where
+
+import Data.Function
+import Data.Monoid
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+
+import qualified Data.LA as LA
+import Data.Expr (Variables (..))
+import Data.Polynomial
+import Data.Polynomial.GBase
+
+type Var = Int
+
+type Model = IM.IntMap Integer
+
+solve :: MonomialOrder Var -> [Var] -> [(LA.Expr Integer, Integer)] -> LA.Expr Integer -> Maybe Model
+solve cmp vs cs obj = 
+  if IM.keysSet (IM.filter (/= 0) m) `IS.isSubsetOf` vs'
+    then Just $ IM.filterWithKey (\y _ -> y `IS.member` vs') m
+    else Nothing
+
+  where
+    vs' :: IS.IntSet
+    vs' = IS.fromList vs
+
+    v2 :: Var
+    v2 = if null vs then 0 else maximum vs + 1
+
+    vs2 :: [Var]
+    vs2 = [v2 .. v2 + length cs - 1]
+
+    vs2' :: IS.IntSet
+    vs2' = IS.fromList vs2
+
+    t :: Var
+    t = v2 + length cs
+
+    cmp2 :: MonomialOrder Var
+    cmp2 = elimOrdering (IS.fromList vs2) `mappend` elimOrdering (IS.singleton t) `mappend` costOrdering obj `mappend` cmp
+
+    gbase :: [Polynomial Rational Var]
+    gbase = buchberger cmp2 (product (map var (t:vs2)) - 1 : phi)
+      where
+        phi = do
+          xj <- vs
+          let aj = [(yi, aij) | (yi,(ai,_)) <- zip vs2 cs, let aij = LA.coeff xj ai]
+          return $  product [var yi ^ aij    | (yi, aij) <- aj, aij > 0]
+                  - product [var yi ^ (-aij) | (yi, aij) <- aj, aij < 0] * var xj
+
+    yb = product [var yi ^ bi | ((_,bi),yi) <- zip cs vs2]
+
+    [(_,z)] = terms (reduce cmp2 yb gbase)
+
+    m = mkModel (vs++vs2++[t]) z
+
+mkModel :: [Var] -> MonicMonomial Var -> Model
+mkModel vs xs = mmToIntMap xs `IM.union` IM.fromList [(x, 0) | x <- vs] 
+-- IM.union is left-biased
+
+costOrdering :: LA.Expr Integer -> MonomialOrder Var
+costOrdering obj = compare `on` f
+  where
+    vs = vars obj
+    f xs = LA.evalExpr (mkModel (IS.toList vs) xs) obj
+
+elimOrdering :: IS.IntSet -> MonomialOrder Var
+elimOrdering xs = compare `on` f
+  where
+    f ys = not (IS.null (xs `IS.intersection` IM.keysSet (mmToIntMap ys)))
+
+-- http://madscientist.jp/~ikegami/articles/IntroSequencePolynomial.html
+-- optimum is (3,2,0)
+test_ikegami = solve grlex vs cs obj
+  where
+    [x,y,z] = vs
+    vs = [1..3]
+    cs = [ (LA.fromTerms [(2,x),(2,y),(2,z)], 10)
+         , (LA.fromTerms [(3,x),(1,y),(1,z)], 11)
+         ]
+    obj = LA.fromTerms [(1,x),(2,y),(3,z)]
+
+-- http://posso.dm.unipi.it/users/traverso/conti-traverso-ip.ps
+-- optimum is (39, 75, 1, 8, 122)
+test_1 = solve grlex vs cs obj
+  where
+    [x1,x2,x3,x4,x5] = vs
+    vs = [1..5]
+    cs = [ (LA.fromTerms [(2, x1), ( 5, x2), (-3, x3), ( 1,x4), (-2, x5)], 214)
+         , (LA.fromTerms [(1, x1), ( 7, x2), ( 2, x3), ( 3,x4), ( 1, x5)], 712)
+         , (LA.fromTerms [(4, x1), (-2, x2), (-1, x3), (-5,x4), ( 3, x5)], 331)
+         ]
+    obj = LA.fromTerms [(1,x1),(1,x2),(1,x3),(1,x4),(1,x5)]
+
+-- optimum is (0,2,2)
+test_2 = solve grlex vs cs obj
+  where
+    [x1,x2,x3] = vs
+    vs = [1..3]
+    cs = [ (LA.fromTerms [(2, x1), (3, x2), (-1, x3)], 4) ]
+    obj = LA.fromTerms [(2,x1),(1,x2)]
+
+-- infeasible
+test_3 = solve grlex vs cs obj
+  where
+    [x1,x2,x3] = vs
+    vs = [1..3]
+    cs = [ (LA.fromTerms [(2, x1), (2, x2), (2, x3)], 3) ]
+    obj = LA.fromTerms [(1,x1)]
diff --git a/src/Converter/CNF2LP.hs b/src/Converter/CNF2LP.hs
new file mode 100644
--- /dev/null
+++ b/src/Converter/CNF2LP.hs
@@ -0,0 +1,71 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Converter.CNF2LP
+-- Copyright   :  (c) Masahiro Sakai 2011-2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+module Converter.CNF2LP
+  ( ObjType (..)
+  , convert 
+  ) where
+
+import Data.Array.IArray
+import qualified Data.Set as Set
+import qualified Data.Map as Map
+import Data.OptDir
+import qualified Text.LPFile as LPFile
+import qualified Language.CNF.Parse.ParseDIMACS as DIMACS
+import qualified SAT.Types as SAT
+import Converter.ObjType
+
+convert :: ObjType -> DIMACS.CNF -> (LPFile.LP, Map.Map LPFile.Var Rational -> SAT.Model)
+convert objType cnf = (lp, mtrans)
+  where
+    lp = LPFile.LP
+      { LPFile.variables = Set.fromList vs
+      , LPFile.dir = dir
+      , LPFile.objectiveFunction = (Nothing, obj)
+      , LPFile.constraints = cs
+      , LPFile.bounds = Map.empty
+      , LPFile.integerVariables = Set.empty
+      , LPFile.binaryVariables = Set.fromList vs
+      , LPFile.semiContinuousVariables = Set.empty
+      , LPFile.sos = []
+      }
+    mtrans m =
+      array (1, DIMACS.numVars cnf)
+        [　(i, val)
+        | i <- [1 .. DIMACS.numVars cnf]
+        , let val =
+                case m Map.! ("x" ++ show i) of
+                  0 -> False
+                  1 -> True
+                  v0 -> error (show v0 ++ " is neither 0 nor 1")
+        ]
+  
+    dir = if objType == ObjMaxZero then OptMin else OptMax
+    obj = if objType == ObjNone then [LPFile.Term 0 (take 1 vs)] else [LPFile.Term 1 [v] | v <- vs]
+    vs = if DIMACS.numVars cnf == 0
+         then ["x0"]
+         else ["x" ++ show i | i <- [1 .. DIMACS.numVars cnf]]
+    cs = do
+      cl <- DIMACS.clauses cnf      
+      let (lhs,n) = foldr f ([], 0) (elems cl)
+      return $ LPFile.Constraint
+        { LPFile.constrType      = LPFile.NormalConstraint
+        , LPFile.constrLabel     = Nothing
+        , LPFile.constrIndicator = Nothing
+        , LPFile.constrBody      = (lhs, LPFile.Ge, fromIntegral $ 1 - n)
+        }
+    f :: Int -> (LPFile.Expr,Integer) -> (LPFile.Expr,Integer)
+    f lit (es,n) =
+      if lit > 0
+      then (LPFile.Term 1 [v] : es, n)
+      else (LPFile.Term (-1) [v] : es, n+1)
+      where v = "x" ++ show (abs lit)
diff --git a/src/Converter/MaxSAT2LP.hs b/src/Converter/MaxSAT2LP.hs
new file mode 100644
--- /dev/null
+++ b/src/Converter/MaxSAT2LP.hs
@@ -0,0 +1,77 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Converter.MaxSAT2LP
+-- Copyright   :  (c) Masahiro Sakai 2011-2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+module Converter.MaxSAT2LP
+  ( convert
+  ) where
+
+import Data.Array.IArray
+import qualified Data.Set as Set
+import qualified Data.Map as Map
+import qualified Text.LPFile as LPFile
+import qualified Text.MaxSAT as MaxSAT
+import SAT.Types
+
+convert :: MaxSAT.WCNF -> (LPFile.LP, Map.Map LPFile.Var Rational -> Model)
+convert (nvar, top, ls) = (lp, mtrans)
+  where
+    lp = LPFile.LP
+      { LPFile.variables = Set.fromList vs
+      , LPFile.dir = LPFile.OptMin
+      , LPFile.objectiveFunction = (Nothing, obj)
+      , LPFile.constraints = cs
+      , LPFile.bounds = Map.empty
+      , LPFile.integerVariables = Set.empty
+      , LPFile.binaryVariables = Set.fromList vs
+      , LPFile.semiContinuousVariables = Set.empty
+      , LPFile.sos = []
+      }
+    mtrans m =
+      array (1, nvar)
+        [　(i, val)
+        | i <- [1 .. nvar]
+        , let val =
+                case m Map.! ("x" ++ show i) of
+                  0  -> False
+                  1  -> True
+                  v0 -> error (show v0 ++ " is neither 0 nor 1")
+        ]
+
+    obj = [ LPFile.Term (fromIntegral w) [v] | (v,(w,_)) <- zs, w < top ]
+    vs = [ "x" ++ show n | n <- [(1::Int)..nvar]] ++ 
+         [ z | (z,(w,_)) <- zs, w /= top ]
+    cs = [h (z,(w,xs)) | (z,(w,xs)) <- zs]
+      where
+        h (z,(w,xs)) = LPFile.Constraint
+          { LPFile.constrType      = LPFile.NormalConstraint
+          , LPFile.constrLabel     = Nothing
+          , LPFile.constrIndicator = Nothing
+          , LPFile.constrBody      = 
+              case f xs of
+                (s,n)
+                  | w>=top    -> (g s, LPFile.Ge, fromIntegral (1 - n)) -- hard constraint
+                  | otherwise -> (LPFile.Term 1 [z] : g s, LPFile.Ge, fromIntegral (1 - n)) -- soft constraint
+          }
+
+    zs = zip (map (\x -> "z" ++ show x) [(1::Int)..]) ls
+
+    f :: [Lit] -> (Map.Map Var Int, Int)
+    f = foldr phi (Map.empty,0)
+      where        
+        phi lit (s,m)
+         | lit >= 0  = (Map.insertWith (+) (abs lit) 1 s, m)
+         | otherwise = (Map.insertWith (+) (abs lit) (-1) s, m+1)
+
+    g :: Map.Map Var Int -> [LPFile.Term]
+    g m = do
+      (v,c) <- Map.toList m
+      return (LPFile.Term (fromIntegral c) ["x" ++ show v])
diff --git a/src/Converter/ObjType.hs b/src/Converter/ObjType.hs
new file mode 100644
--- /dev/null
+++ b/src/Converter/ObjType.hs
@@ -0,0 +1,18 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Converter.ObjType
+-- Copyright   :  (c) Masahiro Sakai 2011-2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+module Converter.ObjType
+  ( ObjType (..)
+  ) where
+
+data ObjType = ObjNone | ObjMaxOne | ObjMaxZero
+  deriving Eq
diff --git a/src/Converter/PB2LP.hs b/src/Converter/PB2LP.hs
new file mode 100644
--- /dev/null
+++ b/src/Converter/PB2LP.hs
@@ -0,0 +1,208 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Converter.PB2LP
+-- Copyright   :  (c) Masahiro Sakai 2011-2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+module Converter.PB2LP
+  ( ObjType (..)
+  , convert
+  , convertWBO
+  ) where
+
+import Data.Array.IArray
+import Data.List
+import Data.Maybe
+import qualified Data.IntSet as IS
+import qualified Data.Set as Set
+import qualified Data.Map as Map
+import qualified Text.PBFile as PBFile
+import qualified Text.LPFile as LPFile
+import qualified SAT.Types as SAT
+import Converter.ObjType
+
+convert :: ObjType -> PBFile.Formula -> (LPFile.LP, Map.Map LPFile.Var Rational -> SAT.Model)
+convert objType formula@(obj, cs) = (lp, mtrans (PBFile.pbNumVars formula))
+  where
+    lp = LPFile.LP
+      { LPFile.variables = vs2
+      , LPFile.dir = dir
+      , LPFile.objectiveFunction = (Nothing, obj2)
+      , LPFile.constraints = cs2
+      , LPFile.bounds = Map.empty
+      , LPFile.integerVariables = Set.empty
+      , LPFile.binaryVariables = vs2
+      , LPFile.semiContinuousVariables = Set.empty
+      , LPFile.sos = []
+      }
+
+    vs1 = collectVariables formula
+    vs2 = (Set.fromList . map convVar . IS.toList) $ vs1
+
+    (dir,obj2) =
+      case obj of
+        Just obj' -> (LPFile.OptMin, convExpr obj')
+        Nothing ->
+          case objType of
+            ObjNone    -> (LPFile.OptMin, [LPFile.Term 0 (take 1 (Set.toList vs2 ++ ["x0"]))])
+            ObjMaxOne  -> (LPFile.OptMax, [LPFile.Term 1 [v] | v <- Set.toList vs2])
+            ObjMaxZero -> (LPFile.OptMin, [LPFile.Term 1 [v] | v <- Set.toList vs2])
+    cs2 = do
+      (lhs,op,rhs) <- cs
+      let op2 = case op of
+                  PBFile.Ge -> LPFile.Ge
+                  PBFile.Eq -> LPFile.Eql
+          lhs2 = convExpr lhs
+          lhs3a = [t | t@(LPFile.Term _ (_:_)) <- lhs2]
+          lhs3b = sum [c | LPFile.Term c [] <- lhs2]
+      return $ LPFile.Constraint
+        { LPFile.constrType      = LPFile.NormalConstraint
+        , LPFile.constrLabel     = Nothing
+        , LPFile.constrIndicator = Nothing
+        , LPFile.constrBody      = (lhs3a, op2, fromIntegral rhs - lhs3b)
+        }
+
+convExpr :: PBFile.Sum -> LPFile.Expr
+convExpr = concatMap g2
+  where
+    g2 :: PBFile.WeightedTerm -> LPFile.Expr
+    g2 (w, tm) = foldl' prodE [LPFile.Term (fromIntegral w) []] (map g3 tm)
+
+    g3 :: PBFile.Lit -> LPFile.Expr
+    g3 x
+      | x > 0     = [LPFile.Term 1 [convVar x]]
+      | otherwise = [LPFile.Term 1 [], LPFile.Term (-1) [convVar (abs x)]]
+
+    prodE :: LPFile.Expr -> LPFile.Expr -> LPFile.Expr
+    prodE e1 e2 = [prodT t1 t2 | t1 <- e1, t2 <- e2]
+
+    prodT :: LPFile.Term -> LPFile.Term -> LPFile.Term
+    prodT (LPFile.Term c1 vs1) (LPFile.Term c2 vs2) = LPFile.Term (c1*c2) (vs1++vs2)
+
+convVar :: PBFile.Var -> LPFile.Var
+convVar x = ("x" ++ show x)
+
+collectVariables :: PBFile.Formula -> IS.IntSet
+collectVariables (obj, cs) = IS.unions $ maybe IS.empty f obj : [f s | (s,_,_) <- cs]
+  where
+    f :: PBFile.Sum -> IS.IntSet
+    f xs = IS.fromList $ do
+      (_,ts) <- xs
+      lit <- ts
+      return $ abs lit
+
+convertWBO :: Bool -> PBFile.SoftFormula -> (LPFile.LP, Map.Map LPFile.Var Rational -> SAT.Model)
+convertWBO useIndicator formula@(top, cs) = (lp, mtrans (PBFile.wboNumVars formula))
+  where
+    lp = LPFile.LP
+      { LPFile.variables = vs2
+      , LPFile.dir = LPFile.OptMin
+      , LPFile.objectiveFunction = (Nothing, obj2)
+      , LPFile.constraints = topConstr ++ map snd cs2
+      , LPFile.bounds = Map.empty
+      , LPFile.integerVariables = Set.empty
+      , LPFile.binaryVariables = vs2
+      , LPFile.semiContinuousVariables = Set.empty
+      , LPFile.sos = []
+      }
+
+    vs1 = collectVariablesWBO formula
+    vs2 = ((Set.fromList . map convVar . IS.toList) $ vs1) `Set.union` vs3
+    vs3 = Set.fromList [v | (ts, _) <- cs2, (_, v) <- ts]
+
+    obj2 = [LPFile.Term (fromIntegral w) [v] | (ts, _) <- cs2, (w, v) <- ts]
+
+    topConstr :: [LPFile.Constraint]
+    topConstr = 
+     case top of
+       Nothing -> []
+       Just t ->
+          [ LPFile.Constraint
+            { LPFile.constrType      = LPFile.NormalConstraint
+            , LPFile.constrLabel     = Nothing
+            , LPFile.constrIndicator = Nothing
+            , LPFile.constrBody      = (obj2, LPFile.Le, fromInteger t - 1)
+            }
+          ]
+
+    cs2 :: [([(Integer, LPFile.Var)], LPFile.Constraint)]
+    cs2 = do
+      (n, (w, (lhs,op,rhs))) <- zip [(0::Int)..] cs
+      let 
+          lhs2 = convExpr lhs
+          lhs3 = [t | t@(LPFile.Term _ (_:_)) <- lhs2]
+          rhs3 = fromIntegral rhs - sum [c | LPFile.Term c [] <- lhs2]
+          v = "r" ++ show n
+          (ts,ind) =
+            case w of
+              Nothing -> ([], Nothing)
+              Just w2 -> ([(w2, v)], Just (v,0))
+      if isNothing w || useIndicator then do
+         let op2 =
+               case op of
+                 PBFile.Ge -> LPFile.Ge
+                 PBFile.Eq -> LPFile.Eql
+             c = LPFile.Constraint
+                 { LPFile.constrType      = LPFile.NormalConstraint
+                 , LPFile.constrLabel     = Nothing
+                 , LPFile.constrIndicator = ind
+                 , LPFile.constrBody      = (lhs3, op2, rhs3)
+                 }
+         return (ts, c)
+       else do
+         let (lhsGE,rhsGE) = relaxGE v (lhs3,rhs3)
+             c1 = LPFile.Constraint
+                  { LPFile.constrType      = LPFile.NormalConstraint
+                  , LPFile.constrLabel     = Nothing
+                  , LPFile.constrIndicator = Nothing
+                  , LPFile.constrBody      = (lhsGE, LPFile.Ge, rhsGE)
+                  }
+         case op of
+           PBFile.Ge -> do
+             return (ts, c1)
+           PBFile.Eq -> do
+             let (lhsLE,rhsLE) = relaxLE v (lhs3,rhs3)
+                 c2 = LPFile.Constraint
+                      { LPFile.constrType      = LPFile.NormalConstraint
+                      , LPFile.constrLabel     = Nothing
+                      , LPFile.constrIndicator = Nothing
+                      , LPFile.constrBody      = (lhsLE, LPFile.Le, rhsLE)
+                      }
+             [ (ts, c1), ([], c2) ]
+
+relaxGE :: LPFile.Var -> (LPFile.Expr, Rational) -> (LPFile.Expr, Rational)
+relaxGE v (lhs, rhs) = (LPFile.Term (rhs - lhs_lb) [v] : lhs, rhs)
+  where
+    lhs_lb = sum [min c 0 | LPFile.Term c _ <- lhs]
+
+relaxLE :: LPFile.Var -> (LPFile.Expr, Rational) -> (LPFile.Expr, Rational)
+relaxLE v (lhs, rhs) = (LPFile.Term (rhs - lhs_ub) [v] : lhs, rhs)
+  where
+    lhs_ub = sum [max c 0 | LPFile.Term c _ <- lhs]
+
+collectVariablesWBO :: PBFile.SoftFormula -> IS.IntSet
+collectVariablesWBO (_top, cs) = IS.unions [f s | (_,(s,_,_)) <- cs]
+  where
+    f :: PBFile.Sum -> IS.IntSet
+    f xs = IS.fromList $ do
+      (_,ts) <- xs
+      lit <- ts
+      return $ abs lit
+
+mtrans :: Int -> Map.Map LPFile.Var Rational -> SAT.Model
+mtrans nvar m =
+  array (1, nvar)
+    [　(i, val)
+    | i <- [1 .. nvar]
+    , let val =
+            case m Map.! (convVar i) of
+              0  -> False
+              1  -> True
+              v0 -> error (show v0 ++ " is neither 0 nor 1")
+    ]
diff --git a/src/Cooper.hs b/src/Cooper.hs
new file mode 100644
--- /dev/null
+++ b/src/Cooper.hs
@@ -0,0 +1,449 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Cooper
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- Naive implementation of Cooper's algorithm
+--
+-- Reference:
+-- 
+-- * <http://hagi.is.s.u-tokyo.ac.jp/pub/staff/hagiya/kougiroku/ronri/5.txt>
+-- 
+-- * <http://www.cs.cmu.edu/~emc/spring06/home1_files/Presburger%20Arithmetic.ppt>
+-- 
+-- See also:
+--
+-- * <http://hackage.haskell.org/package/presburger>
+--
+-----------------------------------------------------------------------------
+module Cooper
+    ( module Data.Expr
+    , module Data.Formula
+    , ExprZ
+    , Lit (..)
+    , Formula' (..)
+    , eliminateQuantifiers
+    , solve
+    , solveQFLA
+    , Model
+    ) where
+
+import Control.Monad
+import Data.List
+import Data.Maybe
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+
+import Data.Expr
+import Data.Formula
+import Data.Linear
+import qualified Data.LA as LA
+import qualified FourierMotzkin as FM
+import qualified Data.Interval as Interval
+
+-- ---------------------------------------------------------------------------
+
+-- | Linear arithmetic expression over integers.
+type ExprZ = LA.Expr Integer
+
+atomZ :: RelOp -> Expr Rational -> Expr Rational -> Maybe Formula'
+atomZ op a b = do
+  (e1,c1) <- FM.termR a
+  (e2,c2) <- FM.termR b
+  let a' = c2 .*. e1
+      b' = c1 .*. e2
+  case op of
+    Le -> return $ Lit $ a' `leZ` b'
+    Lt -> return $ Lit $ a' `ltZ` b'
+    Ge -> return $ Lit $ a' `geZ` b'
+    Gt -> return $ Lit $ a' `gtZ` b'
+    Eql -> return $ eqZ a' b'
+    NEq -> liftM notB (atomZ Eql a b)
+
+leZ, ltZ, geZ, gtZ :: ExprZ -> ExprZ -> Lit
+leZ e1 e2 = e1 `ltZ` (e2 .+. LA.constant 1)
+ltZ e1 e2 = Pos $ (e2 .-. e1)
+geZ = flip leZ
+gtZ = flip gtZ
+
+eqZ :: ExprZ -> ExprZ -> Formula'
+eqZ e1 e2 = Lit (e1 `leZ` e2) .&&. Lit (e1 `geZ` e2)
+
+-- | Literal
+-- 
+-- * @Pos e@ means @e > 0@
+-- 
+-- * @Divisible True d e@ means @e@ can be divided by @d@ (i.e. @d|e@)
+-- 
+-- * @Divisible False d e@ means @e@ can not be divided by @d@ (i.e. @¬(d|e)@)
+data Lit
+    = Pos ExprZ
+    | Divisible Bool Integer ExprZ
+    deriving (Show, Eq, Ord)
+
+instance Variables Lit where
+  vars (Pos t) = vars t
+  vars (Divisible _ _ t) = vars t
+
+instance Complement Lit where
+  notB (Pos e) = e `leZ` LA.constant 0
+  notB (Divisible b c e) = Divisible (not b) c e
+
+-- | quantifier-free negation normal form
+data Formula'
+    = T'
+    | F'
+    | And' Formula' Formula'
+    | Or' Formula' Formula'
+    | Lit Lit
+    deriving (Show, Eq, Ord)
+
+instance Complement Formula' where
+  notB T' = F'
+  notB F' = T'
+  notB (And' a b) = Or' (notB a) (notB b)
+  notB (Or' a b) = And' (notB a) (notB b)
+  notB (Lit lit) = Lit (notB lit)
+
+instance Lattice Formula' where
+  top    = T'
+  bottom = F'
+  meet   = And'
+  join   = Or'
+
+instance Boolean Formula'
+
+subst1 :: Var -> ExprZ -> Formula' -> Formula'
+subst1 x e = go
+  where
+    go T' = T'
+    go F' = F'
+    go (And' a b) = And' (go a) (go b)
+    go (Or' a b) = Or' (go a) (go b)
+    go (Lit (Divisible b c e1)) = Lit $ Divisible b c $ LA.applySubst1 x e e1
+    go (Lit (Pos e1)) = Lit $ Pos $ LA.applySubst1 x e e1
+
+simplify :: Formula' -> Formula'
+simplify T' = T'
+simplify F' = F'
+simplify (And' a b) =
+  case (simplify a, simplify b) of
+    (T', b') -> b'
+    (a', T') -> a'
+    (F', _) -> false
+    (_, F') -> false
+    (a',b') -> a' .&&. b'
+simplify (Or' a b) =
+  case (simplify a, simplify b) of
+    (F', b') -> b'
+    (a', F') -> a'
+    (T', _) -> true
+    (_, T') -> true
+    (a',b') -> a' .||. b'
+simplify (Lit lit) = simplifyLit lit
+
+simplifyLit :: Lit -> Formula'
+simplifyLit lit@(Pos e) =
+  case LA.asConst e of
+    Just c -> if c > 0 then true else false
+    Nothing ->
+      -- e > 0  <=>  e - 1 >= 0
+      -- <=>  LA.mapCoeff (`div` d) (e - 1) >= 0
+      -- <=>  LA.mapCoeff (`div` d) (e - 1) + 1 > 0
+      Lit $ Pos $ LA.mapCoeff (`div` d) (e .-. LA.constant 1) .+. LA.constant 1
+  where
+    d = if null cs then 1 else abs $ foldl1' gcd cs
+    cs = [c | (c,x) <- LA.terms e, x /= LA.unitVar]
+simplifyLit lit@(Divisible b c e)
+  | LA.coeff LA.unitVar e `mod` d /= 0 = if b then false else true
+  | c' == 1   = if b then true else false
+  | d  == 1   = Lit lit
+  | otherwise = Lit $ Divisible b c' e'
+  where
+    d  = abs $ foldl' gcd c [c | (c,x) <- LA.terms e, x /= LA.unitVar]
+    c' = c `div` d
+    e' = LA.mapCoeff (`div` d) e
+
+-- ---------------------------------------------------------------------------
+
+data Witness = WCase1 Integer ExprZ | WCase2 Integer Integer Integer [ExprZ]
+
+eliminateZ :: Var -> Formula' -> Formula'
+eliminateZ x formula = simplify $ orB $ map fst $ eliminateZ' x formula
+
+eliminateZ' :: Var -> Formula' -> [(Formula', Witness)]
+eliminateZ' x formula = case1 ++ case2
+  where
+    -- xの係数の最小公倍数
+    c :: Integer
+    c = f formula
+      where
+         f :: Formula' -> Integer
+         f T' = 1
+         f F' = 1
+         f (And' a b) = lcm (f a) (f b)
+         f (Or' a b) = lcm (f a) (f b)
+         f (Lit (Pos e)) = fromMaybe 1 (LA.lookupCoeff x e)
+         f (Lit (Divisible _ _ e)) = fromMaybe 1 (LA.lookupCoeff x e)
+    
+    -- 式をスケールしてxの係数の絶対値をcへと変換し、その後cxをxで置き換え、
+    -- xがcで割り切れるという制約を追加した論理式
+    formula1 :: Formula'
+    formula1 = simplify $ f formula .&&. Lit (Divisible True c (LA.var x))
+      where
+        f :: Formula' -> Formula'
+        f T' = T'
+        f F' = F'
+        f (And' a b) = f a .&&. f b
+        f (Or' a b) = f a .||. f b
+        f lit@(Lit (Pos e)) =
+          case LA.lookupCoeff x e of
+            Nothing -> lit
+            Just a ->
+              let s = abs (c `div` a)
+              in Lit $ Pos $ g s e
+        f lit@(Lit (Divisible b d e)) =
+          case LA.lookupCoeff x e of
+            Nothing -> lit
+            Just a ->
+              let s = abs (c `div` a)
+              in Lit $ Divisible b (s*d) $ g s e
+
+        g :: Integer -> ExprZ -> ExprZ
+        g s = LA.mapCoeffWithVar (\c' x' -> if x==x' then signum c' else s*c')
+
+    -- d|x+t という形の論理式の d の最小公倍数
+    delta :: Integer
+    delta = f formula1
+      where
+        f :: Formula' -> Integer
+        f T' = 1
+        f F' = 1
+        f (And' a b) = lcm (f a) (f b)
+        f (Or' a b)  = lcm (f a) (f b)
+        f (Lit (Divisible _ d _)) = d
+        f (Lit (Pos _)) = 1
+
+    -- ts = {t | t < x は formula1 に現れる原子論理式}
+    ts :: [ExprZ]
+    ts = f formula1
+      where
+        f :: Formula' -> [ExprZ]
+        f T' = []
+        f F' = []
+        f (And' a b) = f a ++ f b
+        f (Or' a b) = f a ++ f b
+        f (Lit (Divisible _ _ _)) = []
+        f (Lit (Pos e)) =
+          case LA.extractMaybe x e of
+            Nothing -> []
+            Just (1, e')  -> [lnegate e'] -- Pos e <=> (x + e' > 0) <=> (-e' < x)
+            Just (-1, e') -> [] -- Pos e <=> (-x + e' > 0) <=> (x < e')
+            _ -> error "should not happen"
+
+    -- formula1を真にする最小のxが存在する場合
+    case1 :: [(Formula', Witness)]
+    case1 = [ (subst1 x e formula1, WCase1 c e)
+            | j <- [1..delta], t <- ts, let e = t .+. LA.constant j ]
+
+    -- formula1のなかの x < t を真に t < x を偽に置き換えた論理式
+    formula2 :: Formula'
+    formula2 = simplify $ f formula1
+      where        
+        f :: Formula' -> Formula'
+        f T' = T'
+        f F' = F'
+        f (And' a b) = f a .&&. f b
+        f (Or' a b) = f a .||. f b
+        f lit@(Lit (Pos e)) =
+          case LA.lookupCoeff x e of
+            Nothing -> lit
+            Just 1    -> F' -- Pos e <=> ( x + e' > 0) <=> -e' < x
+            Just (-1) -> T' -- Pos e <=> (-x + e' > 0) <=>  x  < e'
+            _ -> error "should not happen"
+        f lit@(Lit (Divisible _ _ _)) = lit
+
+    -- us = {u | x < u は formula1 に現れる原子論理式}
+    us :: [ExprZ]
+    us = f formula1
+      where
+        f :: Formula' -> [ExprZ]
+        f T' = []
+        f F' = []
+        f (And' a b) = f a ++ f b
+        f (Or' a b) = f a ++ f b
+        f (Lit (Pos e)) =
+          case LA.extractMaybe x e of
+            Nothing -> []
+            Just (1, e')  -> []   -- Pos e <=> ( x + e' > 0) <=> -e' < x
+            Just (-1, e') -> [e'] -- Pos e <=> (-x + e' > 0) <=>  x  < e'
+            _ -> error "should not happen"
+        f (Lit (Divisible _ _ _)) = []
+
+    -- formula1を真にする最小のxが存在しない場合
+    case2 :: [(Formula', Witness)]
+    case2 = [(subst1 x (LA.constant j) formula2, WCase2 c j delta us) | j <- [1..delta]]
+
+evalWitness :: Model Integer -> Witness -> Integer
+evalWitness model (WCase1 c e) = LA.evalExpr model e `div` c
+evalWitness model (WCase2 c j delta us)
+  | null us'  = j `div` c
+  | otherwise = (j + (((u - delta - 1) `div` delta) * delta)) `div` c
+  where
+    us' = map (LA.evalExpr model) us
+    u = minimum us'
+
+-- ---------------------------------------------------------------------------
+
+-- | eliminate quantifiers and returns equivalent quantifier-free formula.
+eliminateQuantifiers :: Formula Rational -> Maybe Formula'
+eliminateQuantifiers = f
+  where
+    f T = return T'
+    f F = return F'
+    f (Atom (Rel e1 op e2)) = atomZ op e1 e2
+    f (And a b) = liftM2 (.&&.) (f a) (f b)
+    f (Or a b) = liftM2 (.||.) (f a) (f b)
+    f (Not a) = f (pushNot a)
+    f (Imply a b) = f $ Or (Not a) b
+    f (Equiv a b) = f $ And (Imply a b) (Imply b a)
+    f (Forall x body) = liftM notB $ f $ Exists x $ pushNot body
+    f (Exists x body) = liftM (eliminateZ x) (f body)
+
+-- ---------------------------------------------------------------------------
+
+-- | solve a formula and returns assignment of outer-most existential quantified
+-- variables.
+solve :: Formula Rational -> SatResult Integer
+solve formula =
+  case eliminateQuantifiers formula of
+    Nothing -> Unknown
+    Just formula' ->
+       case solve' vs formula' of
+         Nothing -> Unsat
+         Just m -> Sat m
+  where
+    vs = IS.toList (vars formula)
+
+solve' :: [Var] -> Formula' -> Maybe (Model Integer)
+solve' vs formula = go vs (simplify formula)
+  where
+    go [] T' = return IM.empty
+    go [] _ = mzero
+    go (v:vs) formula = do
+      let xs = eliminateZ' v formula
+      msum $ flip map xs $ \(formula', witness) -> do
+        model <- go vs (simplify formula')
+        let val = evalWitness model witness 
+        return $ IM.insert v val model
+
+-- ---------------------------------------------------------------------------
+
+-- | solve a (open) quantifier-free formula
+solveQFLA :: [LA.Atom Rational] -> VarSet -> Maybe (Model Rational)
+solveQFLA cs ivs = msum [ FM.simplify xs >>= go (IS.toList rvs) | xs <- unDNF dnf ]
+  where
+    vs  = vars cs
+    rvs = vs `IS.difference` ivs
+    dnf = FM.constraintsToDNF cs
+
+    go :: [Var] -> [FM.Lit] -> Maybe (Model Rational)
+    go [] xs = fmap (fmap fromIntegral) $ solve' (IS.toList ivs) (foldr And' T' (map f xs))
+    go (v:vs) ys = msum (map f (unDNF (FM.boundConditions bnd)))
+      where
+        (bnd, rest) = FM.collectBounds v ys
+        f zs = do
+          model <- go vs (zs ++ rest)
+          val <- Interval.pickup (FM.evalBounds model bnd)
+          return $ IM.insert v val model
+
+    f :: FM.Lit -> Formula'
+    f (FM.Nonneg e) = Lit $ e `geZ` (LA.constant 0)
+    f (FM.Pos e)    = Lit $ e `gtZ` (LA.constant 0)
+
+-- ---------------------------------------------------------------------------
+
+{-
+7x + 12y + 31z = 17
+3x + 5y + 14z = 7
+1 ≤ x ≤ 40
+-50 ≤ y ≤ 50
+
+satisfiable in R
+but unsatisfiable in Z
+-}
+test1 :: Formula Rational
+test1 = c1 .&&. c2 .&&. c3 .&&. c4
+  where
+    x = Var 0
+    y = Var 1
+    z = Var 2
+    c1 = 7*x + 12*y + 31*z .==. 17
+    c2 = 3*x + 5*y + 14*z .==. 7
+    c3 = 1 .<=. x .&&. x .<=. 40
+    c4 = (-50) .<=. y .&&. y .<=. 50
+
+test1' :: Formula Rational
+test1' = Exists 0 $ Exists 1 $ Exists 2 $ test1
+
+{-
+27 ≤ 11x+13y ≤ 45
+-10 ≤ 7x-9y ≤ 4
+
+satisfiable in R
+but unsatisfiable in Z
+-}
+test2 :: Formula Rational
+test2 = c1 .&&. c2
+  where
+    x = Var 0
+    y = Var 1
+    t1 = 11*x + 13*y
+    t2 = 7*x - 9*y
+    c1 = 27 .<=. t1 .&&. t1 .<=. 45
+    c2 = (-10) .<=. t2 .&&. t2 .<=. 4
+
+test2' :: Formula Rational
+test2' = Exists 0 $ Exists 1 $ test2
+
+testHagiya :: Formula'
+testHagiya = eliminateZ 1 $ c1 .&&. c2 .&&. c3
+  where
+    [x,y,z] = map LA.var [1..3]
+    c1 = Lit $ x `ltZ` (y .+. y)   -- x < y+y
+    c2 = Lit $ z `ltZ` x           -- z < x
+    c3 = Lit $ Divisible True 3 x  -- 3 | x
+
+{-
+Or' (And' (Lit (Pos (Expr {coeffMap = fromList [(-1,-1),(2,2),(3,-1)]}))) (Lit (Divisible True 3 (Expr {coeffMap = fromList [(-1,1),(3,1)]}))))
+    (Or' (And' (Lit (Pos (Expr {coeffMap = fromList [(-1,-2),(2,2),(3,-1)]}))) (Lit (Divisible True 3 (Expr {coeffMap = fromList [(-1,2),(3,1)]}))))
+         (And' (Lit (Pos (Expr {coeffMap = fromList [(-1,-3),(2,2),(3,-1)]}))) (Lit (Divisible True 3 (Expr {coeffMap = fromList [(-1,3),(3,1)]})))))
+
+(2y-z >  0 && 3|z+1) ||
+(2y-z > -2 && 3|z+2) ||
+(2y-z > -3 && 3|z+3) ||
+-}
+
+test3 :: Formula'
+test3 = eliminateZ 1 (andB [p1,p2,p3,p4])
+  where
+    x = LA.var 0
+    y = LA.var 1
+    p1 = Lit $ Pos y
+    p2 = Lit $ Pos (y .-. 2 .*. x)
+    p3 = Lit $ Pos (x .+. LA.constant 2 .-. y)
+    p4 = Lit $ Divisible True 2 y
+
+{-
+∃ y. 0 < y ∧ 2x<y ∧ y < x+2 ∧ 2|y
+⇔
+(2x < 2 ∧ 0 < x) ∨ (0 < 2x+2 ∧ x < 0)
+-}
+
+-- ---------------------------------------------------------------------------
diff --git a/src/Data/AlgebraicNumber.hs b/src/Data/AlgebraicNumber.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/AlgebraicNumber.hs
@@ -0,0 +1,277 @@
+{-# LANGUAGE Rank2Types #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.AlgebraicNumber
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (Rank2Types)
+--
+-- Algebraic nubmers (work in progress).
+--
+-- Reference:
+--
+-- * <http://www.dpmms.cam.ac.uk/~wtg10/galois.html>
+-- 
+-----------------------------------------------------------------------------
+module Data.AlgebraicNumber
+  (
+  -- * Algebraic real type
+    AReal
+
+  -- * Construction
+  , realRoots
+
+  -- * Properties
+  , minimalPolynomial
+  , deg
+  , isRational
+  , isAlgebraicInteger
+  , height
+
+  -- * Real-like functions
+  , toRational'
+
+  -- * RealFrac-like functions
+  , properFraction'
+  , truncate'
+  , round'
+  , ceiling'
+  , floor'
+
+  -- * Misc
+  , simpARealPoly  
+  ) where
+
+import Control.Exception (assert)
+import Control.Monad
+import Data.List
+import Data.Ratio
+
+import Data.Polynomial hiding (deg)
+import qualified Data.Polynomial as P
+import qualified Data.Polynomial.Sturm as Sturm
+import qualified Data.Polynomial.FactorZ as FactorZ
+import Data.Interval (Interval, (<!), (>!))
+import qualified Data.Interval as Interval
+import Data.AlgebraicNumber.Root
+
+{--------------------------------------------------------------------
+  Algebraic numbers
+
+以下の代数的実数の場合にはスツルムの定理による根の分離で色々できているけど、
+一般の代数的数の場合にどうすれば良いかはまだちゃんと理解できていない。
+なので、一旦色々削除した。
+--------------------------------------------------------------------}
+
+{--------------------------------------------------------------------
+  Algebraic reals
+--------------------------------------------------------------------}
+
+data AReal = RealRoot (UPolynomial Rational) (Interval Rational)
+  deriving Show
+
+-- | Real roots of the rational coefficient polynomial.
+realRoots :: UPolynomial Rational -> [AReal]
+realRoots p = sort $ do
+  q <- factor' p 
+  i <- Sturm.separate q
+  return $ RealRoot q i
+
+factor' :: UPolynomial Rational -> [UPolynomial Rational]
+factor' p = do
+  q <- FactorZ.factor $ toZ p
+  guard $ P.deg q > 0
+  let (c,_) = leadingTerm grlex q
+  return $ mapCoeff (% c) q
+
+realRoot :: UPolynomial Rational -> Interval Rational -> AReal
+realRoot p i = 
+  case [q | q <- factor' p, Sturm.numRoots q i == 1] of
+    p2:_ -> RealRoot p2 i
+    []   -> error "Data.AlgebraicNumber.realRoot: invalid interval"
+
+-- p must be already factored.
+realRoot2 :: UPolynomial Rational -> Interval Rational -> AReal
+realRoot2 p i = RealRoot (normalizePoly p) i
+
+normalizePoly :: UPolynomial Rational -> UPolynomial Rational
+normalizePoly p = mapCoeff f p
+  where
+    (c,_) = leadingTerm grlex p
+    f x = x / c
+
+minimalPolynomial :: AReal -> UPolynomial Rational
+minimalPolynomial (RealRoot p _) = p
+
+isZero :: AReal -> Bool
+isZero (RealRoot p i) = 0 `Interval.member` i && 0 `isRootOf` p
+
+instance Eq AReal where
+  a == b = (compare a b == EQ)
+
+instance Ord AReal where
+  compare a@(RealRoot _ i1) b@(RealRoot _ i2)
+    | i1 >! i2 = GT
+    | i1 <! i2 = LT
+    | isZero c = EQ
+    | Sturm.numRoots p ipos == 1 = GT
+    | otherwise = assert (Sturm.numRoots p ineg == 1) LT
+    where
+      c@(RealRoot p i3) = a - b
+      ipos = Interval.intersection i3 (Interval.interval (Just (False,0)) Nothing)
+      ineg = Interval.intersection i3 (Interval.interval Nothing (Just (False,0)))
+
+instance Num AReal where
+  RealRoot p1 i1 + RealRoot p2 i2 = realRoot p3 i3
+    where
+      p3 = rootAdd p1 p2
+      i3 = go i1 i2 (Sturm.separate p3)
+
+      go i1 i2 is3 =
+        case [i5 | i3 <- is3, let i5 = Interval.intersection i3 i4, Sturm.numRoots p3 i5 > 0] of
+          [] -> error "AReal.+: should not happen"
+          [i5] -> i5
+          is5 ->
+            go (Sturm.narrow p1 i1 (Interval.size i1 / 2))
+               (Sturm.narrow p2 i2 (Interval.size i2 / 2))
+               [Sturm.narrow p3 i5 (Interval.size i5 / 2) | i5 <- is5]
+        where
+          i4 = i1 + i2
+
+  RealRoot p1 i1 * RealRoot p2 i2 = realRoot p3 i3
+    where
+      p3 = rootMul p1 p2
+      i3 = go i1 i2 (Sturm.separate p3)
+
+      go i1 i2 is3 =
+        case [i5 | i3 <- is3, let i5 = Interval.intersection i3 i4, Sturm.numRoots p3 i5 > 0] of
+          [] -> error "AReal.*: should not happen"
+          [i5] -> i5
+          is5 ->
+            go (Sturm.narrow p1 i1 (Interval.size i1 / 2))
+               (Sturm.narrow p2 i2 (Interval.size i2 / 2))
+               [Sturm.narrow p3 i5 (Interval.size i5 / 2) | i5 <- is5]
+        where
+          i4 = i1 * i2
+
+  negate (RealRoot p i) = realRoot2 (rootNegate p) (-i)
+
+  abs a =
+    case compare 0 a of
+      EQ -> fromInteger 0
+      LT -> a
+      GT -> negate a
+
+  signum a = fromInteger $
+    case compare 0 a of
+      EQ -> 0
+      LT -> 1
+      GT -> -1
+
+  fromInteger i = RealRoot (x - constant (fromInteger i)) (Interval.singleton (fromInteger i))
+    where
+      x = var ()
+
+instance Fractional AReal where
+  fromRational r = RealRoot (x - constant r) (Interval.singleton r)
+    where
+      x = var ()
+
+  recip a@(RealRoot p i)
+    | isZero a  = error "AReal.recip: zero division"
+    | otherwise = realRoot2 (rootRecip p) (recip i)
+
+toRational' :: AReal -> Rational -> Rational
+toRational' (RealRoot p i) epsilon = Sturm.approx p i epsilon
+
+-- | Same as 'properFraction'.
+properFraction' :: Integral b => AReal -> (b, AReal)
+properFraction' x =
+  case compare x 0 of
+    EQ -> (0, 0)
+    GT -> (fromInteger floor_x, x - fromInteger floor_x)
+    LT -> (fromInteger ceiling_x, x - fromInteger ceiling_x)
+  where
+    floor_x   = floor' x
+    ceiling_x = ceiling' x
+
+-- | Same as 'truncate'.
+truncate' :: Integral b => AReal -> b
+truncate' = fst . properFraction'
+
+-- | Same as 'round'.
+round' :: Integral b => AReal -> b
+round' x = 
+  case signum (abs r - 0.5) of
+    -1 -> n
+    0  -> if even n then n else m
+    1  -> m
+    _  -> error "round default defn: Bad value"
+  where
+    (n,r) = properFraction' x
+    m = if r < 0 then n - 1 else n + 1
+
+-- | Same as 'ceiling'.
+ceiling' :: Integral b => AReal -> b
+ceiling' (RealRoot p i) =
+  if Sturm.numRoots' chain (Interval.intersection i2 i3) > 1
+    then fromInteger ceiling_lb
+    else fromInteger ceiling_ub
+  where
+    chain = Sturm.sturmChain p
+    i2 = Sturm.narrow' chain i (1/2)
+    Just (inLB, lb) = Interval.lowerBound i2
+    Just (inUB, ub) = Interval.upperBound i2
+    ceiling_lb = ceiling lb
+    ceiling_ub = ceiling ub
+    i3 = Interval.interval Nothing (Just (True, fromInteger ceiling_lb))
+
+-- | Same as 'floor'.
+floor' :: Integral b => AReal -> b
+floor' (RealRoot p i) =
+  if Sturm.numRoots' chain (Interval.intersection i2 i3) > 1
+    then fromInteger floor_ub
+    else fromInteger floor_lb
+  where
+    chain = Sturm.sturmChain p
+    i2 = Sturm.narrow' chain i (1/2)
+    Just (inLB, lb) = Interval.lowerBound i2
+    Just (inUB, ub) = Interval.upperBound i2
+    floor_lb = floor lb
+    floor_ub = floor ub
+    i3 = Interval.interval (Just (True, fromInteger floor_ub)) Nothing
+
+{--------------------------------------------------------------------
+  Properties
+--------------------------------------------------------------------}
+
+deg :: AReal -> Integer
+deg (RealRoot p _) = P.deg p
+
+isRational :: AReal -> Bool
+isRational x = deg x == 1
+
+isAlgebraicInteger :: AReal -> Bool
+isAlgebraicInteger x = cn * fromIntegral d == 1
+  where
+    p = minimalPolynomial x
+    d = foldl' lcm 1 [denominator c | (c,_) <- terms p]
+    (cn,_) = leadingTerm grlex p
+
+height :: AReal -> Integer
+height x = maximum [ assert (denominator c' == 1) (abs (numerator c'))
+                   | (c,_) <- terms p, let c' = c * fromInteger d ]
+  where
+    p = minimalPolynomial x
+    d = foldl' lcm 1 [denominator c | (c,_) <- terms p]
+
+{--------------------------------------------------------------------
+  Manipulation of polynomials
+--------------------------------------------------------------------}
+
+-- 代数的数を係数とする多項式の根を、有理数係数多項式の根として表す
+simpARealPoly :: UPolynomial AReal -> UPolynomial Rational
+simpARealPoly p = rootSimpPoly (\(RealRoot q _) -> q) p
diff --git a/src/Data/AlgebraicNumber/RealInstance.hs b/src/Data/AlgebraicNumber/RealInstance.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/AlgebraicNumber/RealInstance.hs
@@ -0,0 +1,20 @@
+module Data.AlgebraicNumber.RealInstance where
+
+import Data.Polynomial as P
+import Data.AlgebraicNumber
+
+instance Real AReal where
+  toRational x
+    | Data.AlgebraicNumber.deg x == 1 =
+        let p = minimalPolynomial x
+            a = P.coeff (P.mmVar ()) p
+            b = P.coeff P.mmOne p
+        in - b / a
+    | otherwise  = error "toRational: proper algebraic number"
+
+instance RealFrac AReal where
+  properFraction = properFraction'
+  truncate       = truncate'
+  round          = round'
+  ceiling        = ceiling'
+  floor          = floor'
diff --git a/src/Data/AlgebraicNumber/Root.hs b/src/Data/AlgebraicNumber/Root.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/AlgebraicNumber/Root.hs
@@ -0,0 +1,117 @@
+{-# LANGUAGE Rank2Types #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.AlgebraicNumber.Root
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (Rank2Types)
+--
+-- Algebraic nubmers (work in progress).
+--
+-- Reference:
+--
+-- * <http://www.dpmms.cam.ac.uk/~wtg10/galois.html>
+-- 
+-----------------------------------------------------------------------------
+module Data.AlgebraicNumber.Root where
+
+import Data.List
+import Data.Maybe
+import qualified Data.Map as Map
+import qualified Data.Set as Set
+
+import Data.Polynomial
+import Data.Polynomial.GBase
+
+type Var = Int
+
+{--------------------------------------------------------------------
+  Manipulation of polynomials
+--------------------------------------------------------------------}
+
+rootAdd :: UPolynomial Rational -> UPolynomial Rational -> UPolynomial Rational
+rootAdd p1 p2 = lift2 (+) p1 p2
+
+rootSub :: UPolynomial Rational -> UPolynomial Rational -> UPolynomial Rational
+rootSub p1 p2 = lift2 (flip subtract) p1 p2
+
+rootMul :: UPolynomial Rational -> UPolynomial Rational -> UPolynomial Rational
+rootMul p1 p2 = lift2 (*) p1 p2
+
+rootNegate :: UPolynomial Rational -> UPolynomial Rational
+rootNegate p = fromTerms [(if (d - mmDegree xs) `mod` 2 == 0 then c else -c, xs) | (c, xs) <- terms p]
+  where
+    d = deg p
+
+rootScale :: Rational -> UPolynomial Rational -> UPolynomial Rational
+rootScale r p = fromTerms [(r^(d - mmDegree xs) * c, xs) | (c, xs) <- terms p]
+  where
+    d = deg p
+
+rootRecip :: UPolynomial Rational -> UPolynomial Rational
+rootRecip p = fromTerms [(c, mmFromList [((), d - mmDegree xs)]) | (c, xs) <- terms p]
+  where
+    d = deg p
+
+-- 代数的数を係数とする多項式の根を、有理数係数多項式の根として表す
+rootSimpPoly :: (a -> UPolynomial Rational) -> UPolynomial a -> UPolynomial Rational
+rootSimpPoly f p = findPoly (var 0) ps
+  where
+    ys :: [(UPolynomial Rational, Var)]
+    ys = zip (Set.toAscList $ Set.fromList [f c | (c, _) <- terms p]) [1..]
+
+    m :: Map.Map (UPolynomial Rational) Var
+    m = Map.fromDistinctAscList ys
+
+    p' :: Polynomial Rational Var
+    p' = eval (\() -> var 0) (mapCoeff (\c -> var (m Map.! (f c))) p)
+
+    ps :: [Polynomial Rational Var]
+    ps = p' : [mapVar (\() -> x) q | (q, x) <- ys]
+
+lift2 :: (forall a. Num a => a -> a -> a)
+      -> UPolynomial Rational -> UPolynomial Rational -> UPolynomial Rational
+lift2 f p1 p2 = findPoly f_a_b gbase
+  where
+    a, b :: Var
+    a = 0
+    b = 1
+
+    f_a_b :: Polynomial Rational Var
+    f_a_b = f (var a) (var b)
+
+    gbase :: [Polynomial Rational Var]
+    gbase = [ mapVar (\() -> a) p1, mapVar (\() -> b) p2 ]              
+
+-- ps のもとで c を根とする多項式を求める
+findPoly :: Polynomial Rational Var -> [Polynomial Rational Var] -> UPolynomial Rational
+findPoly c ps = fromTerms [(coeff, mmFromList [((), n)]) | (n,coeff) <- zip [0..] coeffs]
+  where  
+    vn :: Var
+    vn = if Set.null vs then 0 else Set.findMax vs + 1
+      where
+        vs = Set.fromList [x | p <- (c:ps), (_,xs) <- terms p, (x,_) <- mmToList xs]
+
+    coeffs :: [Rational]
+    coeffs = head $ catMaybes $ [isLinearlyDependent cs2 | cs2 <- inits cs]
+      where
+        cmp = grlex
+        ps' = buchberger cmp ps
+        cs  = iterate (\p -> reduce cmp (c * p) ps') 1
+
+    isLinearlyDependent :: [Polynomial Rational Var] -> Maybe [Rational]
+    isLinearlyDependent cs = if any (0/=) sol then Just sol else Nothing
+      where
+        cs2 = zip [vn..] cs
+        sol = map (\(l,_) -> eval (\_ -> 1) $ reduce cmp2 (var l) gbase2) cs2
+        cmp2   = grlex
+        gbase2 = buchberger cmp2 es
+        es = Map.elems $ Map.fromListWith (+) $ do
+          (n,xs) <- terms $ sum [var ln * cn | (ln,cn) <- cs2]
+          let xs' = mmToList xs
+              ys = mmFromList [(x,m) | (x,m) <- xs', x < vn]
+              zs = mmFromList [(x,m) | (x,m) <- xs', x >= vn]
+          return (ys, fromMonomial (n,zs))
diff --git a/src/Data/Delta.hs b/src/Data/Delta.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Delta.hs
@@ -0,0 +1,91 @@
+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Delta
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (FlexibleInstances, MultiParamTypeClasses)
+--
+-- Augmenting number types with infinitesimal parameter δ.
+--
+-- Reference:
+-- 
+-- * Bruno Dutertre and Leonardo de Moura,
+--   \"/A Fast Linear-Arithmetic Solver for DPLL(T)/\",
+--   Computer Aided Verification In Computer Aided Verification, Vol. 4144
+--   (2006), pp. 81-94.
+--   <http://dx.doi.org/10.1007/11817963_11>
+--   <http://yices.csl.sri.com/cav06.pdf>
+--
+-----------------------------------------------------------------------------
+
+module Data.Delta
+  (
+  -- * The Delta type
+    Delta (..)
+
+  -- * Construction
+  , fromReal
+  , delta
+
+  -- * Query
+  , realPart
+  , deltaPart
+
+  -- * Relationship with integers
+  , floor'
+  , ceiling'
+  , isInteger'
+  ) where
+
+import Data.Linear
+import Util (isInteger)
+
+-- | @Delta r k@ represents r + kδ for symbolic infinitesimal parameter δ.
+data Delta r = Delta !r !r deriving (Ord, Eq, Show)
+
+-- | symbolic infinitesimal parameter δ.
+delta :: Num r => Delta r
+delta = Delta 0 1
+
+-- | Conversion from a base @r@ value to @Delta r@.
+fromReal :: Num r => r -> Delta r
+fromReal x = Delta x 0
+
+-- | Extracts the real part..
+realPart :: Delta r -> r
+realPart (Delta r _) = r
+
+-- | Extracts the δ part..
+deltaPart :: Delta r -> r
+deltaPart (Delta _ k) = k
+
+instance Num r => Module r (Delta r) where
+  Delta r1 k1 .+. Delta r2 k2 = Delta (r1+r2) (k1+k2)
+  c .*. Delta r k = Delta (c*r) (c*k)
+  lzero = Delta 0 0
+
+instance Fractional r => Linear r (Delta r)
+
+-- | 'Delta' version of 'floor'.
+-- @'floor'' x@ returns the greatest integer not greater than @x@
+floor' :: (RealFrac r, Integral a) => Delta r -> a
+floor' (Delta r k) = fromInteger $ if r2==r && k < 0 then i-1 else i
+  where
+    i = floor r
+    r2 = fromInteger i
+
+-- | 'Delta' version of 'ceiling'.
+-- @'ceiling'' x@ returns the least integer not less than @x@
+ceiling' :: (RealFrac r, Integral a) => Delta r -> a
+ceiling' (Delta r k) = fromInteger $ if r2==r && k > 0 then i+1 else i
+  where
+    i = ceiling r
+    r2 = fromInteger i
+
+-- | Is this a integer?
+isInteger' :: RealFrac r => Delta r -> Bool
+isInteger' (Delta r k) = isInteger r && k == 0
diff --git a/src/Data/Expr.hs b/src/Data/Expr.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Expr.hs
@@ -0,0 +1,118 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Expr
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- Arithmetic expressions (not limited to linear ones).
+-- 
+-----------------------------------------------------------------------------
+module Data.Expr
+  ( Var
+  , VarSet
+  , VarMap
+  , Variables (..)
+  , Model
+  , Expr (..)
+  , var
+  , eval
+
+  -- FIXME: どこか違うモジュールへ?
+  , SatResult (..)
+  , OptResult (..)
+  ) where
+
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+import Data.Ratio
+
+-- ---------------------------------------------------------------------------
+
+-- | Variables are represented as non-negative integers
+type Var = Int
+
+-- | Set of variables
+type VarSet = IS.IntSet
+
+-- | Map from variables
+type VarMap = IM.IntMap
+
+-- | collecting free variables
+class Variables a where
+  vars :: a -> VarSet
+
+instance Variables a => Variables [a] where
+  vars = IS.unions . map vars
+
+-- | A @Model@ is a map from variables to values.
+type Model r = VarMap r
+
+-- ---------------------------------------------------------------------------
+
+-- | Arithmetic expressions
+data Expr r
+  = Const r
+  | Var Var
+  | Expr r :+: Expr r
+  | Expr r :*: Expr r
+  | Expr r :/: Expr r
+  deriving (Eq, Ord, Show)
+
+instance Num r => Num (Expr r) where
+  a + b = a :+: b
+  a * b = a :*: b
+  a - b = a + negate b
+  negate a = Const (-1) :*: a
+  abs a = a
+  signum _ = 1
+  fromInteger = Const . fromInteger
+
+instance Fractional r => Fractional (Expr r) where
+  a / b = a :/: b
+  fromRational x = fromInteger (numerator x) / fromInteger (denominator x)
+
+instance Functor Expr where
+  fmap f = g
+    where
+      g (Const c) = Const (f c)
+      g (Var v)   = Var v
+      g (a :+: b) = g a :+: g b
+      g (a :*: b) = g a :*: g b
+      g (a :/: b) = g a :/: g b
+
+instance Variables (Expr r) where
+  vars (Const _) = IS.empty
+  vars (Var v)   = IS.singleton v
+  vars (a :+: b) = vars a `IS.union` vars b
+  vars (a :*: b) = vars a `IS.union` vars b
+  vars (a :/: b) = vars a `IS.union` vars b
+
+-- | single variable expression
+var :: Var -> Expr r
+var = Var
+
+-- | evaluate an 'Expr' with respect to a 'Model'
+eval :: Fractional r => Model r -> Expr r -> r
+eval m = f
+  where
+    f (Const x) = x
+    f (Var v) = m IM.! v
+    f (a :+: b) = f a + f b
+    f (a :*: b) = f a * f b
+    f (a :/: b) = f a / f b
+
+-- ---------------------------------------------------------------------------
+
+-- | results of satisfiability checking
+data SatResult r = Unknown | Unsat | Sat (Model r)
+  deriving (Show, Eq, Ord)
+
+-- | results of optimization
+data OptResult r = OptUnknown | OptUnsat | Unbounded | Optimum r (Model r)
+  deriving (Show, Eq, Ord)
+
+-- ---------------------------------------------------------------------------
diff --git a/src/Data/Formula.hs b/src/Data/Formula.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Formula.hs
@@ -0,0 +1,195 @@
+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Formula
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (MultiParamTypeClasses, FunctionalDependencies)
+--
+-- Formula of first order logic.
+-- 
+-----------------------------------------------------------------------------
+module Data.Formula
+  (
+  -- * Overloaded operations for formula.
+    module Data.Lattice
+
+  -- * Relational operators
+  , RelOp (..)
+  , Rel (..)
+  , (.<.), (.<=.), (.>=.), (.>.), (.==.), (./=.)
+  , flipOp
+  , negOp
+  , showOp
+
+  -- * Concrete formula
+  , Atom (..)
+  , Formula (..)
+  , pushNot
+  , DNF (..)
+  ) where
+
+import qualified Data.IntSet as IS
+import Data.Expr
+import Data.Lattice
+
+-- ---------------------------------------------------------------------------
+
+infix 4 .<., .<=., .>=., .>., .==., ./=.
+
+-- ---------------------------------------------------------------------------
+
+-- | relational operators
+data RelOp = Lt | Le | Ge | Gt | Eql | NEq
+    deriving (Show, Eq, Ord)
+
+-- | type class for constructing relational formula
+class Rel e r | r -> e where
+  rel :: RelOp -> e -> e -> r
+
+-- | constructing relational formula
+(.<.) :: Rel e r => e -> e -> r
+a .<. b  = rel Lt  a b
+
+-- | constructing relational formula
+(.<=.) :: Rel e r => e -> e -> r
+a .<=. b = rel Le  a b
+
+-- | constructing relational formula
+(.>.) :: Rel e r => e -> e -> r
+a .>. b  = rel Gt  a b
+
+-- | constructing relational formula
+(.>=.) :: Rel e r => e -> e -> r
+a .>=. b = rel Ge  a b
+
+-- | constructing relational formula
+(.==.) :: Rel e r => e -> e -> r
+a .==. b = rel Eql a b
+
+-- | constructing relational formula
+(./=.) :: Rel e r => e -> e -> r
+a ./=. b = rel NEq a b
+
+-- | flipping relational operator
+--
+-- @rel (flipOp op) a b@ is equivalent to @rel op b a@
+flipOp :: RelOp -> RelOp 
+flipOp Le = Ge
+flipOp Ge = Le
+flipOp Lt = Gt
+flipOp Gt = Lt
+flipOp Eql = Eql
+flipOp NEq = NEq
+
+-- | negating relational operator
+--
+-- @rel (negOp op) a b@ is equivalent to @notB (rel op a b)@
+negOp :: RelOp -> RelOp
+negOp Lt = Ge
+negOp Le = Gt
+negOp Ge = Lt
+negOp Gt = Le
+negOp Eql = NEq
+negOp NEq = Eql
+
+-- | operator symbol
+showOp :: RelOp -> String
+showOp Lt = "<"
+showOp Le = "<="
+showOp Ge = ">="
+showOp Gt = ">"
+showOp Eql = "="
+showOp NEq = "/="
+
+-- ---------------------------------------------------------------------------
+
+-- | Atomic formula
+data Atom c = Rel (Expr c) RelOp (Expr c)
+    deriving (Show, Eq, Ord)
+
+instance Complement (Atom c) where
+  notB (Rel lhs op rhs) = Rel lhs (negOp op) rhs
+
+instance Variables (Atom c) where
+  vars (Rel a _ b) = vars a `IS.union` vars b
+
+instance Rel (Expr c) (Atom c) where
+  rel op a b = Rel a op b
+
+-- ---------------------------------------------------------------------------
+
+-- | formulas of first order logic
+data Formula c
+    = T
+    | F
+    | Atom (Atom c)
+    | And (Formula c) (Formula c)
+    | Or (Formula c) (Formula c)
+    | Not (Formula c)
+    | Imply (Formula c) (Formula c)
+    | Equiv (Formula c) (Formula c)
+    | Forall Var (Formula c)
+    | Exists Var (Formula c)
+    deriving (Show, Eq, Ord)
+
+instance Variables (Formula c) where
+  vars T = IS.empty
+  vars F = IS.empty
+  vars (Atom atom) = vars atom
+  vars (And a b) = vars a `IS.union` vars b
+  vars (Or a b) = vars a `IS.union` vars b
+  vars (Not a) = vars a
+  vars (Imply a b) = vars a `IS.union` vars b
+  vars (Equiv a b) = vars a `IS.union` vars b
+  vars (Forall v a) = IS.delete v (vars a)
+  vars (Exists v a) = IS.delete v (vars a)
+
+instance Complement (Formula c) where
+  notB = Not
+
+instance Lattice (Formula c) where
+  top    = T
+  bottom = F
+  meet   = And
+  join   = Or
+
+instance Boolean (Formula c) where
+  (.=>.)  = Imply
+  (.<=>.) = Equiv
+
+instance Rel (Expr c) (Formula c) where
+  rel op a b = Atom $ rel op a b
+
+-- | convert a formula into negation normal form
+pushNot :: Formula c -> Formula c
+pushNot T = F
+pushNot F = T
+pushNot (Atom (Rel a op b)) = Atom $ Rel a (negOp op) b
+pushNot (And a b) = Or (pushNot a) (pushNot b)
+pushNot (Or a b) = And (pushNot a) (pushNot b)
+pushNot (Not a) = a
+pushNot (Imply a b) = And a (pushNot b)
+pushNot (Equiv a b) = Or (And a (pushNot b)) (And b (pushNot a))
+pushNot (Forall v a) = Exists v (pushNot a)
+pushNot (Exists v a) = Forall v (pushNot a)
+
+-- | Disjunctive normal form
+newtype DNF lit
+  = DNF
+  { unDNF :: [[lit]] -- ^ list of conjunction of literals
+  } deriving (Show)
+
+instance Complement lit => Complement (DNF lit) where
+  notB (DNF xs) = DNF . sequence . map (map notB) $ xs
+
+instance Complement lit => Lattice (DNF lit) where
+  top    = DNF [[]]
+  bottom = DNF []
+  DNF xs `meet` DNF ys = DNF [x++y | x<-xs, y<-ys]
+  DNF xs `join` DNF ys = DNF (xs++ys)
+
+instance Complement lit => Boolean (DNF lit)
diff --git a/src/Data/IndexedPriorityQueue.hs b/src/Data/IndexedPriorityQueue.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/IndexedPriorityQueue.hs
@@ -0,0 +1,297 @@
+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, BangPatterns, DoAndIfThenElse, TypeSynonymInstances #-}
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.IndexedPriorityQueue
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (MultiParamTypeClasses, FlexibleInstances, BangPatterns, DoAndIfThenElse, TypeSynonymInstances)
+--
+-- Priority queue implemented as array-based binary heap.
+--
+-----------------------------------------------------------------------------
+module Data.IndexedPriorityQueue
+  (
+  -- * PriorityQueue type
+    PriorityQueue
+  , Value
+  , Index
+
+  -- * Constructors
+  , newPriorityQueue
+  , newPriorityQueueBy
+  , NewFifo (..)
+
+  -- * Operators
+  , getElems
+  , clear
+  , clone
+  , Enqueue (..)
+  , Dequeue (..)
+  , QueueSize (..)
+  , member
+  , update
+  , getHeapArray
+  ) where
+
+import Control.Monad
+import Data.Ix
+import qualified Data.Array.Base as A
+import qualified Data.Array.IO as A
+import Data.IORef
+import Data.Queue.Classes
+
+type Index = Int
+type Value = Int
+
+-- | Priority queue implemented as array-based binary heap.
+data PriorityQueue
+  = PriorityQueue
+  { lt 　:: !(Value -> Value -> IO Bool)
+  , heap :: !(IORef (Int, A.IOUArray Index Value))
+  , table  :: !(IORef (A.IOUArray Value Index))
+  }
+
+-- | Build a priority queue with default ordering ('(<)' of 'Ord' class)
+newPriorityQueue :: IO PriorityQueue
+newPriorityQueue = newPriorityQueueBy (\a b -> return (a < b))
+
+-- | Build a priority queue with a given /less than/ operator.
+newPriorityQueueBy :: (Value -> Value -> IO Bool) -> IO (PriorityQueue)
+newPriorityQueueBy cmp = do
+  h <- A.newArray_ (0,-1)
+  ref <- newIORef (0,h)
+  idx <- A.newArray_ (0,-1)
+  ref2 <- newIORef idx
+  return $ PriorityQueue{ lt = cmp, heap = ref, table =ref2 }
+
+-- | Return a list of all the elements of a priority queue. (not sorted)
+getElems :: PriorityQueue -> IO [Value]
+getElems q = do
+  (n,arr) <- readIORef (heap q)
+  forM [0..n-1] $ \i -> A.readArray arr i
+
+-- | Remove all elements from a priority queue.
+clear :: PriorityQueue -> IO ()
+clear q = do
+  (_,arr) <- readIORef (heap q)
+  writeIORef (heap q) (0,arr)
+
+  idx <- readIORef (table q)
+  (!lb,!ub) <- A.getBounds idx
+  let go i
+        | i > ub    = return ()
+        | otherwise = A.unsafeWrite idx i (-1) >> go (i+1)
+  go lb
+
+-- | Create a copy of a priority queue.
+clone :: PriorityQueue -> IO PriorityQueue
+clone q = do
+  (n,arr) <- readIORef (heap q)
+  arr' <- cloneArray arr
+  ref <- newIORef (n,arr')
+
+  idx <- readIORef (table q)
+  idx' <- cloneArray idx
+  ref2 <- newIORef idx'
+
+  return $ PriorityQueue{ lt = lt q, heap = ref, table = ref2 }
+
+instance Enqueue (PriorityQueue) IO Value where
+  enqueue q val = do
+    m <- member q val
+    unless m $ do
+      (n,arr) <- readIORef (heap q)  
+      c <- liftM rangeSize $ A.getBounds arr
+      if (n+1 < c)
+        then do
+          A.unsafeWrite arr n val
+          writeIORef (heap q) (n+1,arr)
+        else do
+          let c' = max 2 (c * 3 `div` 2)
+          arr' <- A.newArray_ (0, c'-1)
+          copyTo arr arr' (0, n-1)
+          A.unsafeWrite arr' n val
+          writeIORef (heap q) (n+1,arr')
+
+      idx <- readIORef (table q)
+      c2 <- liftM rangeSize $ A.getBounds idx
+      if val < c2
+        then A.unsafeWrite idx val n
+        else do
+          let c2' = max 2 (c2 * 3 `div` 2)
+          idx' <- A.newArray_ (0, c2'-1)
+          copyTo idx idx' (0, c2-1)
+          forM_ [c2..c2'-1] $ \i -> A.unsafeWrite idx' i (-1)
+          A.unsafeWrite idx' val n
+          writeIORef (table q) idx'
+  
+      up q n
+
+instance Dequeue (PriorityQueue) IO Value where
+  dequeue q = do
+    (n,arr) <- readIORef (heap q)
+    idx <- readIORef (table q)
+    case n of
+      0 -> do
+        return Nothing
+      _ -> do
+        val <- A.readArray arr 0
+        A.unsafeWrite idx val (-1)
+        writeIORef (heap q) (n-1, arr)
+        when (n > 1) $ do
+          val1 <- A.readArray arr (n-1)
+          A.unsafeWrite arr 0 val1
+          A.unsafeWrite idx val1 0
+          down q 0
+        return (Just val)
+
+  dequeueBatch q = go []
+    where
+      go xs = do
+        r <- dequeue q
+        case r of
+          Nothing -> return (reverse xs)
+          Just x -> go (x:xs)
+
+instance QueueSize (PriorityQueue) IO where
+  queueSize q = do
+    (n,_) <- readIORef (heap q)
+    return n
+
+member :: PriorityQueue -> Value -> IO Bool
+member q v = do
+  idx <- readIORef (table q)
+  r <- A.getBounds idx
+  if not (inRange r v) then
+    return False
+  else do
+    i <- A.unsafeRead idx v
+    return $! i /= -1
+
+update :: PriorityQueue -> Value -> IO ()
+update q v = do
+  idx <- readIORef (table q)
+  i <- A.readArray idx v
+  unless (i == -1) $ do
+    up q i
+    down q i
+
+up :: PriorityQueue -> Index -> IO ()
+up q !i = do
+  (_,arr) <- readIORef (heap q)
+  idx <- readIORef (table q)
+  val <- A.readArray arr i
+  let loop 0 = return 0
+      loop j = do
+        let p = parent j
+        val_p <- A.readArray arr p
+        b <- lt q val val_p
+        if b
+          then do
+            A.unsafeWrite arr j val_p
+            A.unsafeWrite idx val_p j
+            loop p
+          else return j
+  j <- loop i
+  A.unsafeWrite arr j val
+  A.unsafeWrite idx val j
+
+down :: PriorityQueue -> Index -> IO ()
+down q !i = do
+  (!n,arr) <- readIORef (heap q)
+  idx <- readIORef (table q)
+  val <- A.readArray arr i
+  let loop !j = do
+        let !l = left j
+            !r = right j
+        if l >= n
+         then return j
+         else do
+           child <- do
+             if r >= n
+              then return l
+              else do
+                val_l <- A.readArray arr l
+                val_r <- A.readArray arr r
+                b <- lt q val_r val_l
+                if b
+                  then return r
+                  else return l
+           val_child <- A.readArray arr child
+           b <- lt q val_child val
+           if not b
+             then return j
+             else do
+               A.unsafeWrite arr j val_child
+               A.unsafeWrite idx val_child j
+               loop child
+  j <- loop i
+  A.unsafeWrite arr j val
+  A.unsafeWrite idx val j
+
+-- | Get the internal representation of a given priority queue.
+getHeapArray :: PriorityQueue -> IO (A.IOUArray Index Value)
+getHeapArray q = liftM snd $ readIORef (heap q)
+
+{--------------------------------------------------------------------
+  Index "traversal" functions
+--------------------------------------------------------------------}
+
+{-# INLINE left #-}
+left :: Index -> Index
+left i = i*2 + 1
+
+{-# INLINE right #-}
+right :: Index -> Index
+right i = (i+1)*2;
+
+{-# INLINE parent #-}
+parent :: Index -> Index
+parent i = (i-1) `div` 2
+
+{--------------------------------------------------------------------
+  utility
+--------------------------------------------------------------------}
+
+cloneArray :: (A.MArray a e m) => a Index e -> m (a Index e)
+cloneArray arr = do
+  b <- A.getBounds arr
+  arr' <- A.newArray_ b
+  copyTo arr arr' b
+  return arr'
+
+copyTo :: (A.MArray a e m) => a Index e -> a Index e -> (Index,Index) -> m ()
+copyTo fromArr toArr b = do
+  forM_ (range b) $ \i -> do
+    val_i <- A.readArray fromArr i
+    A.unsafeWrite toArr i val_i
+
+{--------------------------------------------------------------------
+  test
+--------------------------------------------------------------------}
+
+{-
+checkHeapProperty :: String -> PriorityQueue -> IO ()
+checkHeapProperty str q = do 
+  (n,arr) <- readIORef (heap q)
+  let go i = do
+        val <- A.readArray arr i
+        forM_ [left i, right i] $ \j ->
+          when (j < n) $ do
+            val2 <- A.readArray arr j
+            b <- lt q val2 val
+            when b $ do
+              error (str ++ ": invalid heap " ++ show j)
+            go j
+  when (n > 0) $ go 0
+
+  idx <- readIORef (table q)
+  forM_ [0..n-1] $ \i -> do
+    v <- A.readArray arr i
+    i' <- A.readArray idx v
+    when (i /= i') $ error $ str ++ ": invalid index " ++ show (i,v,i')
+-}
diff --git a/src/Data/Interval.hs b/src/Data/Interval.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Interval.hs
@@ -0,0 +1,481 @@
+{-# LANGUAGE ScopedTypeVariables, FlexibleInstances, MultiParamTypeClasses, DeriveDataTypeable #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Interval
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (ScopedTypeVariables, FlexibleInstances, MultiParamTypeClasses, DeriveDataTypeable)
+--
+-- Interval datatype.
+-- 
+-----------------------------------------------------------------------------
+module Data.Interval
+  (
+  -- * Interval type
+    Interval
+  , EndPoint
+
+  -- * Construction
+  , interval
+  , closedInterval
+  , openInterval
+  , univ
+  , empty
+  , singleton
+
+  -- * Query
+  , null
+  , member
+  , notMember
+  , isSubsetOf
+  , isProperSubsetOf
+  , lowerBound
+  , upperBound
+  , size
+
+  -- * Comparison
+  , (<!), (<=!), (==!), (>=!), (>!)
+  , (<?), (<=?), (==?), (>=?), (>?)
+
+  -- * Combine
+  , intersection
+  , join
+
+  -- * Operations
+  , pickup
+  , tightenToInteger
+  ) where
+
+import Control.Monad hiding (join)
+import Data.List hiding (null)
+import Data.Maybe
+import Data.Monoid
+import Data.Linear
+import Data.Lattice
+import Data.Typeable
+import Util (combineMaybe, isInteger)
+import Prelude hiding (null)
+
+-- | Interval
+data Interval r
+  = Empty
+  | Interval (EndPoint r) (EndPoint r)
+  deriving (Eq, Typeable)  
+
+-- | Lower bound of the interval
+lowerBound :: Num r => Interval r -> EndPoint r
+lowerBound Empty = Just (False,0)
+lowerBound (Interval lb _) = lb
+
+-- | Upper bound of the interval
+upperBound :: Num r => Interval r -> EndPoint r
+upperBound Empty = Just (False,0)
+upperBound (Interval _ ub) = ub
+
+-- | Endpoint
+-- 
+-- > (isInclusive, value)
+type EndPoint r = Maybe (Bool, r)
+
+instance (Ord r, Num r) => Lattice (Interval r) where
+  top    = univ
+  bottom = empty
+  join   = join'
+  meet   = intersection
+
+instance (Num r, Show r) => Show (Interval r) where
+  showsPrec p x  = showParen (p > appPrec) $
+    showString "interval " .
+    showsPrec appPrec1 (lowerBound x) .
+    showChar ' ' . 
+    showsPrec appPrec1 (upperBound x)
+
+-- | smart constructor for 'Interval'
+interval
+  :: (Ord r, Num r)
+  => EndPoint r -- ^ lower bound
+  -> EndPoint r -- ^ upper bound
+  -> Interval r
+interval lb@(Just (in1,x1)) ub@(Just (in2,x2)) =
+  case x1 `compare` x2 of
+    GT -> empty
+    LT -> Interval lb ub
+    EQ -> if in1 && in2 then Interval lb ub else empty
+interval lb ub = Interval lb ub
+
+-- | closed set [@l, @u]
+closedInterval
+  :: (Ord r, Num r)
+  => r -- ^ lower bound @l@
+  -> r -- ^ upper bound @u@
+  -> Interval r
+closedInterval lb ub = interval (Just (True, lb)) (Just (True, ub))
+
+-- | open set (@l, @u)
+openInterval
+  :: (Ord r, Num r)
+  => r -- ^ lower bound @l@
+  -> r -- ^ upper bound @u@
+  -> Interval r
+openInterval lb ub = interval (Just (False, lb)) (Just (False, ub))
+
+-- | universal set (-∞, ∞)
+univ :: (Num r, Ord r) => Interval r
+univ = interval Nothing Nothing
+
+-- | empty (contradicting) interval
+empty :: Num r => Interval r
+empty = Empty
+
+-- | singleton set \[x,x\]
+singleton :: (Num r, Ord r) => r -> Interval r
+singleton x = interval (Just (True, x)) (Just (True, x))
+
+-- | intersection (greatest lower bounds) of two intervals
+intersection :: forall r. (Ord r, Num r) => Interval r -> Interval r -> Interval r
+intersection (Interval l1 u1) (Interval l2 u2) = interval (maxLB l1 l2) (minUB u1 u2)
+  where
+    maxLB :: EndPoint r -> EndPoint r -> EndPoint r
+    maxLB = combineMaybe $ \(in1,x1) (in2,x2) ->
+      ( case x1 `compare` x2 of
+          EQ -> in1 && in2
+          LT -> in2
+          GT -> in1
+      , max x1 x2
+      )
+    minUB :: EndPoint r -> EndPoint r -> EndPoint r
+    minUB = combineMaybe $ \(in1,x1) (in2,x2) ->
+      ( case x1 `compare` x2 of
+          EQ -> in1 && in2
+          LT -> in1
+          GT -> in2
+      , min x1 x2
+      )
+intersection _ _ = empty
+
+-- | join (least upperbound) of two intervals.
+join' :: forall r. (Ord r, Num r) => Interval r -> Interval r -> Interval r
+join' Empty x2 = x2
+join' x1 Empty = x1
+join' (Interval l1 u1) (Interval l2 u2) = interval (minLB l1 l2) (maxUB u1 u2)
+  where
+    maxUB :: EndPoint r -> EndPoint r -> EndPoint r
+    maxUB u1 u2 = do
+      (in1,x1) <- u1
+      (in2,x2) <- u2
+      return $
+        ( case x1 `compare` x2 of
+          EQ -> in1 || in2
+          LT -> in2
+          GT -> in1
+        , max x1 x2
+        )
+    minLB :: EndPoint r -> EndPoint r -> EndPoint r
+    minLB l1 l2 = do
+      (in1,x1) <- l1
+      (in2,x2) <- l2
+      return $
+        ( case x1 `compare` x2 of
+          EQ -> in1 || in2
+          LT -> in1
+          GT -> in2
+        , min x1 x2
+        )
+
+-- | Is the interval empty?
+null :: Ord r => Interval r -> Bool
+null Empty = True
+null _ = False
+
+-- | Is the element in the interval?
+member :: Ord r => r -> Interval r -> Bool
+member _ Empty = False
+member x (Interval lb ub) = testLB x lb && testUB x ub
+  where
+    testLB x Nothing = True
+    testLB x (Just (in1,x1)) = if in1 then x1 <= x else x1 < x
+    testUB x Nothing = True
+    testUB x (Just (in2,x2)) = if in2 then x <= x2 else x < x2
+
+-- | Is the element not in the interval?
+notMember :: Ord r => r -> Interval r -> Bool
+notMember a i = not $ member a i
+
+-- | Is this a subset?
+-- @(i1 `isSubsetOf` i2)@ tells whether @i1@ is a subset of @i2@.
+isSubsetOf :: Ord r => Interval r -> Interval r -> Bool
+isSubsetOf Empty _ = True
+isSubsetOf _ Empty = False
+isSubsetOf (Interval lb1 ub1) (Interval lb2 ub2) = testLB lb1 lb2 && testUB ub1 ub2
+  where
+    testLB _ Nothing = True
+    testLB (Just (in1,x1)) (Just (in2,x2)) =
+      case x1 `compare` x2 of
+        GT -> True
+        LT -> False
+        EQ -> not in1 || in2 -- in1 => in2
+    testLB Nothing _ = False
+
+    testUB _ Nothing = True
+    testUB (Just (in1,x1)) (Just (in2,x2)) =
+      case x1 `compare` x2 of
+        LT -> True
+        GT -> False
+        EQ -> not in1 || in2 -- in1 => in2
+    testUB Nothing _ = False
+
+-- | Is this a proper subset? (ie. a subset but not equal).
+isProperSubsetOf :: Ord r => Interval r -> Interval r -> Bool
+isProperSubsetOf i1 i2 = i1 /= i2 && i1 `isSubsetOf` i2
+
+-- | Size of a interval. Size of an unbounded interval is @undefined@.
+size :: (Num r, Ord r) => Interval r -> r
+size Empty = 0
+size (Interval (Just (_,l)) (Just (_,u))) = u - l
+size _ = error "Data.Interval.size: unbounded interval"
+
+-- | pick up an element from the interval if the interval is not empty.
+pickup :: (Real r, Fractional r) => Interval r -> Maybe r
+pickup Empty = Nothing
+pickup (Interval Nothing Nothing) = Just 0
+pickup (Interval (Just (in1,x1)) Nothing) = Just $ if in1 then x1 else x1+1
+pickup (Interval Nothing (Just (in2,x2))) = Just $ if in2 then x2 else x2-1
+pickup (Interval (Just (in1,x1)) (Just (in2,x2))) =
+  case x1 `compare` x2 of
+    GT -> Nothing
+    LT -> Just $ (x1+x2) / 2
+    EQ -> if in1 && in2 then Just x1 else Nothing
+
+-- | tightening intervals by ceiling lower bounds and flooring upper bounds.
+tightenToInteger :: forall r. (RealFrac r) => Interval r -> Interval r
+tightenToInteger Empty = Empty
+tightenToInteger (Interval lb ub) = interval (fmap tightenLB lb) (fmap tightenUB ub)
+  where
+    tightenLB (incl,lb) =
+      ( True
+      , if isInteger lb && not incl
+        then lb + 1
+        else fromIntegral (ceiling lb :: Integer)
+      )
+    tightenUB (incl,ub) =
+      ( True
+      , if isInteger ub && not incl
+        then ub - 1
+        else fromIntegral (floor ub :: Integer)
+      )
+
+-- | For all @x@ in @X@, @y@ in @Y@. @x '<' y@
+(<!) :: Real r => Interval r -> Interval r -> Bool
+a <! b
+  | null a = True
+  | null b = True
+  | otherwise =
+    case upperBound a of
+      Nothing -> False
+      Just (in1,ub1) ->
+        case lowerBound b of
+          Nothing -> False
+          Just (in2,lb2) ->
+            ub1 < lb2 || (ub1==lb2 && not (in1 && in2))
+
+-- | For all @x@ in @X@, @y@ in @Y@. @x '<=' y@
+(<=!) :: Real r => Interval r -> Interval r -> Bool
+a <=! b
+  | null a = True
+  | null b = True
+  | otherwise =
+    case upperBound a of
+      Nothing -> False
+      Just (in1,ub1) ->
+        case lowerBound b of
+          Nothing -> False
+          Just (in2,lb2) ->
+            ub1 <= lb2
+
+-- | For all @x@ in @X@, @y@ in @Y@. @x '==' y@
+(==!) :: Real r => Interval r -> Interval r -> Bool
+a ==! b = a <=! b && a >=! b
+
+-- | For all @x@ in @X@, @y@ in @Y@. @x '>=' y@
+(>=!) :: Real r => Interval r -> Interval r -> Bool
+(>=!) = flip (<=!)
+
+-- | For all @x@ in @X@, @y@ in @Y@. @x '>' y@
+(>!) :: Real r => Interval r -> Interval r -> Bool
+(>!) = flip (<!)
+
+-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '<' y@?
+(<?) :: Real r => Interval r -> Interval r -> Bool
+a <? b
+  | null a = False
+  | null b = False
+  | otherwise =
+    case lowerBound a of
+      Nothing -> True
+      Just (in1,lb) ->
+        case upperBound b of
+          Nothing -> True
+          Just (in2,ub) -> lb < ub
+
+-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '<=' y@?
+(<=?) :: Real r => Interval r -> Interval r -> Bool
+a <=? b
+  | null a = False
+  | null b = False
+  | otherwise =
+    case lowerBound a of
+      Nothing -> True
+      Just (in1,lb) ->
+        case upperBound b of
+          Nothing -> True
+          Just (in2,ub) ->
+            lb < ub || (lb==ub && in1 && in2)
+
+-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '==' y@?
+(==?) :: Real r => Interval r -> Interval r -> Bool
+a ==? b = not $ null $ intersection a b
+
+-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '>=' y@?
+(>=?) :: Real r => Interval r -> Interval r -> Bool
+(>=?) = flip (<=?)
+
+-- | Does there exist an @x@ in @X@, @y@ in @Y@ such that @x '>' y@?
+(>?) :: Real r => Interval r -> Interval r -> Bool
+(>?) = flip (<?)
+
+-- | Interval airthmetics.
+-- Note that this instance does not satisfy algebraic laws of linear spaces.
+instance Real r => Module r (Interval r) where
+  lzero = singleton 0
+
+  Interval lb1 ub1 .+. Interval lb2 ub2 = interval (f lb1 lb2) (f ub1 ub2)
+    where
+      f = liftM2 $ \(in1,x1) (in2,x2) -> (in1 && in2, x1 + x2)
+  _ .+. _ = Empty
+
+  _ .*. Empty = Empty
+  c .*. Interval lb ub =
+    case compare c 0 of
+      EQ -> singleton 0
+      LT -> interval (f ub) (f lb)
+      GT -> interval (f lb) (f ub)
+    where
+      f Nothing = Nothing
+      f (Just (incl,val)) = Just (incl, c * val)
+
+instance (Real r, Fractional r) => Linear r (Interval r)
+
+appPrec, appPrec1 :: Int
+appPrec = 10
+appPrec1 = appPrec + 1
+
+
+instance forall r. (Real r, Fractional r) => Num (Interval r) where
+  a + b = a .+. b
+  a - b = a .-. b
+  negate a = (-1) .*. a
+  fromInteger i = singleton (fromInteger i)
+
+  abs x = ((x `intersection` nonneg) `join` (negate x `intersection` nonneg))
+    where
+      nonneg = interval (Just (True,0)) Nothing
+
+  signum x = zero `join` pos `join` neg
+    where
+      zero = if member 0 x then singleton 0 else empty
+      pos = if null $ intersection (interval (Just (False,0)) Nothing) x
+            then empty
+            else singleton 1
+      neg = if null $ intersection (interval Nothing (Just (False,0))) x
+            then empty
+            else singleton (-1)
+
+  Interval lb1 ub1 * Interval lb2 ub2 = interval lb3 ub3
+    where
+      xs = [ mulInf' x1 x2
+           | x1 <- [lbToInf lb1, ubToInf ub1]
+           , x2 <- [lbToInf lb2, ubToInf ub2]
+           ]
+      ub3 = infToUB $ maximumBy cmpUB xs
+      lb3 = infToLB $ minimumBy cmpLB xs
+  _ * _ = Empty
+
+instance forall r. (Real r, Fractional r) => Fractional (Interval r) where
+  fromRational r = singleton (fromRational r)
+  recip Empty = Empty
+  recip i | 0 `member` i = univ -- should be error?
+  recip (Interval lb ub) = interval lb3 ub3
+    where
+      ub3 = infToUB $ maximumBy cmpUB xs
+      lb3 = infToLB $ minimumBy cmpLB xs
+      xs = [recipLB (lbToInf lb), recipUB (ubToInf ub)]
+
+data Inf r = NegInf | Finite !r | PosInf
+  deriving (Ord, Eq)
+
+cmpUB, cmpLB :: Real r => (Bool, Inf r) -> (Bool, Inf r) -> Ordering
+cmpUB (in1,x1) (in2,x2) = compare x1 x2 `mappend` compare in1 in2
+cmpLB (in1,x1) (in2,x2) = compare x1 x2 `mappend` flip compare in1 in2
+
+negateInf :: Num r => Inf r -> Inf r
+negateInf NegInf = PosInf
+negateInf PosInf = NegInf
+negateInf (Finite x) = Finite (negate x)
+
+mulInf' :: (Num r, Ord r) => (Bool, Inf r) -> (Bool, Inf r) -> (Bool, Inf r)
+mulInf' (True, Finite 0) _ = (True, Finite 0)
+mulInf' _ (True, Finite 0) = (True, Finite 0)
+mulInf' (in1,x1) (in2,x2) = (in1 && in2, mulInf x1 x2)
+
+mulInf :: (Num r, Ord r) => Inf r -> Inf r -> Inf r
+mulInf (Finite x1) (Finite x2) = Finite (x1 * x2)
+mulInf inf (Finite x2) =
+  case compare x2 0 of
+    EQ -> Finite 0
+    GT -> inf
+    LT -> negateInf inf
+mulInf (Finite x1) inf =
+  case compare x1 0 of
+    EQ -> Finite 0
+    GT -> inf
+    LT -> negateInf inf
+mulInf PosInf PosInf = PosInf
+mulInf PosInf NegInf = NegInf
+mulInf NegInf PosInf = NegInf
+mulInf NegInf NegInf = PosInf
+
+recipLB :: (Fractional r, Ord r) => (Bool, Inf r) -> (Bool, Inf r)
+recipLB (_, Finite 0) = (False, PosInf)
+recipLB (in1, x1) = (in1, recipInf x1)
+
+recipUB :: (Fractional r, Ord r) => (Bool, Inf r) -> (Bool, Inf r)
+recipUB (_, Finite 0) = (False, NegInf)
+recipUB (in1, x1) = (in1, recipInf x1)
+
+recipInf :: (Fractional r, Ord r) => Inf r -> Inf r
+recipInf PosInf = Finite 0
+recipInf NegInf = Finite 0
+recipInf (Finite x) = Finite (1/x)
+
+lbToInf :: Num r => EndPoint r -> (Bool, Inf r)
+lbToInf Nothing = (False, NegInf)
+lbToInf (Just (in1,x1)) = (in1, Finite x1)
+
+ubToInf :: Num r => EndPoint r -> (Bool, Inf r)
+ubToInf Nothing = (False, PosInf)
+ubToInf (Just (in1,x1)) = (in1, Finite x1)
+
+infToLB :: Num r => (Bool, Inf r) -> EndPoint r
+infToLB (in1, Finite x)  = Just (in1, x)
+infToLB (False, NegInf)  = Nothing
+infToLB (_, PosInf)      = error "infToLB: should not happen"
+infToLB (True, NegInf)   = error "infToLB: should not happen"
+
+infToUB :: Num r => (Bool, Inf r) -> EndPoint r
+infToUB (in1, Finite x)  = Just (in1, x)
+infToUB (False, PosInf)  = Nothing
+infToUB (_, NegInf)      = error "infToUB: should not happen"
+infToUB (True, PosInf)   = error "infToUB: should not happen"
diff --git a/src/Data/LA.hs b/src/Data/LA.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/LA.hs
@@ -0,0 +1,308 @@
+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.LA
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (MultiParamTypeClasses, FlexibleInstances)
+--
+-- Some definition for Theory of Linear Arithmetics.
+-- 
+-----------------------------------------------------------------------------
+module Data.LA
+  ( module Data.Linear
+
+  -- * Expression of linear arithmetics
+  , Expr
+
+  -- ** Conversion
+  , var
+  , constant
+  , terms
+  , fromTerms
+  , coeffMap
+  , fromCoeffMap
+  , unitVar
+  , asConst
+
+  -- ** Query
+  , coeff
+  , lookupCoeff
+  , extract
+  , extractMaybe  
+
+  -- ** Operations
+  , mapCoeff
+  , mapCoeffWithVar
+  , evalExpr
+  , evalLinear
+  , lift1
+  , applySubst
+  , applySubst1
+  , showExpr
+
+  -- * Atomic formula of linear arithmetics
+  , Atom (..)
+  , showAtom
+  , solveFor
+
+  -- * misc
+  , BoundsEnv
+  , computeInterval
+  , compileExpr
+  , compileAtom
+  ) where
+
+import Control.Monad
+import Control.DeepSeq
+import Data.List
+import Data.Maybe
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+import qualified Data.Expr as Expr
+import Data.Expr (Var, VarMap, VarSet, Variables, Model)
+import qualified Data.Formula as Formula
+import Data.Linear
+import Data.Interval
+
+-----------------------------------------------------------------------------
+
+-- | Linear combination of variables and constants.
+-- Non-negative keys are used for variables's coefficients.
+-- key 'unitVar' is used for constants.
+newtype Expr r
+  = Expr
+  { -- | a mapping from variables to coefficients
+    coeffMap :: IM.IntMap r
+  } deriving (Eq, Ord)
+
+-- | Create a @Expr@ from a mapping from variables to coefficients.
+fromCoeffMap :: (Num r, Eq r) => IM.IntMap r -> Expr r
+fromCoeffMap m = normalizeExpr (Expr m)
+
+-- | terms contained in the expression.
+terms :: Expr r -> [(r,Var)]
+terms (Expr m) = [(c,v) | (v,c) <- IM.toList m]
+
+-- | Create a @Expr@ from a list of terms.
+fromTerms :: (Num r, Eq r) => [(r,Var)] -> Expr r
+fromTerms ts = fromCoeffMap $ IM.fromListWith (+) [(x,c) | (c,x) <- ts]
+
+instance Variables (Expr r) where
+  vars (Expr m) = IS.delete unitVar (IM.keysSet m)
+
+instance Show r => Show (Expr r) where
+  showsPrec d m  = showParen (d > 10) $
+    showString "fromTerms " . shows (terms m)
+
+instance (Num r, Eq r, Read r) => Read (Expr r) where
+  readsPrec p = readParen (p > 10) $ \ r -> do
+    ("fromTerms",s) <- lex r
+    (xs,t) <- reads s
+    return (fromTerms xs, t)
+
+instance NFData r => NFData (Expr r) where
+  rnf (Expr m) = rnf m
+
+-- | Special variable that should always be evaluated to 1.
+unitVar :: Var
+unitVar = -1
+
+asConst :: Num r => Expr r -> Maybe r
+asConst (Expr m) =
+  case IM.toList m of
+    [] -> Just 0
+    [(v,x)] | v==unitVar -> Just x
+    _ -> Nothing
+
+normalizeExpr :: (Num r, Eq r) => Expr r -> Expr r
+normalizeExpr (Expr t) = Expr $ IM.filter (0/=) t
+
+-- | variable
+var :: Num r => Var -> Expr r
+var v = Expr $ IM.singleton v 1
+
+-- | constant
+constant :: (Num r, Eq r) => r -> Expr r
+constant c = normalizeExpr $ Expr $ IM.singleton unitVar c
+
+-- | map coefficients.
+mapCoeff :: (Num b, Eq b) => (a -> b) -> Expr a -> Expr b
+mapCoeff f (Expr t) = Expr $ IM.mapMaybe g t
+  where
+    g c = if c' == 0 then Nothing else Just c'
+      where c' = f c
+
+-- | map coefficients.
+mapCoeffWithVar :: (Num b, Eq b) => (a -> Var -> b) -> Expr a -> Expr b
+mapCoeffWithVar f (Expr t) = Expr $ IM.mapMaybeWithKey g t
+  where
+    g v c = if c' == 0 then Nothing else Just c'
+      where c' = f c v
+
+instance (Num r, Eq r) => Module r (Expr r) where
+  Expr t .+. e2 | IM.null t = e2
+  e1 .+. Expr t | IM.null t = e1
+  e1 .+. e2 = normalizeExpr $ plus e1 e2
+  1 .*. e = e
+  0 .*. e = lzero
+  c .*. e = mapCoeff (c*) e
+  lzero = Expr $ IM.empty
+
+instance (Fractional r, Eq r) => Linear r (Expr r)
+
+plus :: Num r => Expr r -> Expr r -> Expr r
+plus (Expr t1) (Expr t2) = Expr $ IM.unionWith (+) t1 t2
+
+-- | evaluate the expression under the model.
+evalExpr :: Num r => Model r -> Expr r -> r
+evalExpr m (Expr t) = sum [(m' IM.! v) * c | (v,c) <- IM.toList t]
+  where m' = IM.insert unitVar 1 m
+
+-- | evaluate the expression under the model.
+evalLinear :: Linear r a => Model a -> a -> Expr r -> a
+evalLinear m u (Expr t) = lsum [c .*. (m' IM.! v) | (v,c) <- IM.toList t]
+  where m' = IM.insert unitVar u m
+
+lift1 :: Linear r x => x -> (Var -> x) -> Expr r -> x
+lift1 unit f (Expr t) = lsum [c .*. (g v) | (v,c) <- IM.toList t]
+  where
+    g v
+      | v==unitVar = unit
+      | otherwise   = f v
+
+applySubst :: (Num r, Eq r) => VarMap (Expr r) -> Expr r -> Expr r
+applySubst s (Expr m) = lsum (map f (IM.toList m))
+  where
+    f (v,c) = c .*. (
+      case IM.lookup v s of
+        Just tm -> tm
+        Nothing -> var v)
+
+-- | applySubst1 x e e1 == e1[e/x]
+applySubst1 :: (Num r, Eq r) => Var -> Expr r -> Expr r -> Expr r
+applySubst1 x e e1 =
+  case extractMaybe x e1 of
+    Nothing -> e1
+    Just (c,e2) -> c .*. e .+. e2
+
+-- | lookup a coefficient of the variable.
+-- @
+--   coeff v e == fst (extract v e)
+-- @
+coeff :: Num r => Var -> Expr r -> r
+coeff v (Expr m) = IM.findWithDefault 0 v m
+
+-- | lookup a coefficient of the variable.
+-- It returns @Nothing@ if the expression does not contain @v@.
+-- @
+--   lookupCoeff v e == fmap fst (extractMaybe v e)
+-- @
+lookupCoeff :: Num r => Var -> Expr r -> Maybe r
+lookupCoeff v (Expr m) = IM.lookup v m  
+
+-- | @extract v e@ returns @(c, e')@ such that @e == c .*. v .+. e'@
+extract :: Num r => Var -> Expr r -> (r, Expr r)
+extract v (Expr m) = (IM.findWithDefault 0 v m, Expr (IM.delete v m))
+{-
+-- Alternative implementation which may be faster but allocte more memory
+extract v (Expr m) = 
+  case IM.updateLookupWithKey (\_ _ -> Nothing) v m of
+    (Nothing, _) -> (0, Expr m)
+    (Just c, m2) -> (c, Expr m2)
+-}
+
+-- | @extractMaybe v e@ returns @Just (c, e')@ such that @e == c .*. v .+. e'@
+-- if @e@ contains v, and returns @Nothing@ otherwise.
+extractMaybe :: Num r => Var -> Expr r -> Maybe (r, Expr r)
+extractMaybe v (Expr m) =
+  case IM.lookup v m of
+    Nothing -> Nothing
+    Just c -> Just (c, Expr (IM.delete v m))
+{-
+-- Alternative implementation which may be faster but allocte more memory
+extractMaybe v (Expr m) =
+  case IM.updateLookupWithKey (\_ _ -> Nothing) v m of
+    (Nothing, _) -> Nothing
+    (Just c, m2) -> Just (c, Expr m2)
+-}
+
+showExpr :: (Num r, Eq r, Show r) => Expr r -> String
+showExpr = showExprWith f
+  where
+    f x = "x" ++ show x
+
+showExprWith :: (Num r, Show r, Eq r) => (Var -> String) -> Expr r -> String
+showExprWith env (Expr m) = foldr (.) id xs ""
+  where
+    xs = intersperse (showString " + ") ts
+    ts = [if c==1
+            then showString (env x)
+            else showsPrec 8 c . showString "*" . showString (env x)
+          | (x,c) <- IM.toList m, x /= unitVar] ++
+         [showsPrec 7 c | c <- maybeToList (IM.lookup unitVar m)]
+
+-----------------------------------------------------------------------------
+
+-- | Atomic Formula of Linear Arithmetics
+data Atom r = Atom (Expr r) Formula.RelOp (Expr r)
+    deriving (Show, Eq, Ord)
+
+instance Formula.Complement (Atom r) where
+  notB (Atom  lhs op rhs) = Atom lhs (Formula.negOp op) rhs
+
+instance Variables (Atom r) where
+  vars (Atom a _ b) = Expr.vars a `IS.union` Expr.vars b
+
+instance Formula.Rel (Expr r) (Atom r) where
+  rel op a b = Atom a op b
+
+showAtom :: (Num r, Eq r, Show r) => Atom r -> String
+showAtom (Atom lhs op rhs) = showExpr lhs ++ Formula.showOp op ++ showExpr rhs
+
+-- | Solve linear (in)equation for the given variable.
+--
+-- @solveFor a v@ returns @Just (op, e)@ such that @Atom v op e@
+-- is equivalent to @a@.
+solveFor :: (Real r, Fractional r) => Atom r -> Var -> Maybe (Formula.RelOp, Expr r)
+solveFor (Atom lhs op rhs) v = do
+  (c,e) <- extractMaybe v (lhs .-. rhs)
+  return ( if c < 0 then Formula.flipOp op else op
+         , (1/c) .*. lnegate e
+         )
+
+-----------------------------------------------------------------------------
+
+type BoundsEnv r = Expr.VarMap (Interval r)
+
+-- | compute bounds for a @Expr@ with respect to @BoundsEnv@.
+computeInterval :: (Real r, Fractional r) => BoundsEnv r -> Expr r -> Interval r
+computeInterval b = lift1 (singleton 1) (b IM.!)
+
+-----------------------------------------------------------------------------
+
+compileExpr :: (Real r, Fractional r) => Expr.Expr r -> Maybe (Expr r)
+compileExpr (Expr.Const c) = return (constant c)
+compileExpr (Expr.Var c) = return (var c)
+compileExpr (a Expr.:+: b) = liftM2 (.+.) (compileExpr a) (compileExpr b)
+compileExpr (a Expr.:*: b) = do
+  x <- compileExpr a
+  y <- compileExpr b
+  msum [ do{ c <- asConst x; return (c .*. y) }
+       , do{ c <- asConst y; return (c .*. x) }
+       ]
+compileExpr (a Expr.:/: b) = do
+  x <- compileExpr a
+  c <- asConst =<< compileExpr b
+  return $ (1/c) .*. x
+
+compileAtom :: (Real r, Fractional r) => Formula.Atom r -> Maybe (Atom r)
+compileAtom (Formula.Rel a op b) = do
+  a' <- compileExpr a
+  b' <- compileExpr b
+  return $ Atom a' op b'
+
+-----------------------------------------------------------------------------
diff --git a/src/Data/LBool.hs b/src/Data/LBool.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/LBool.hs
@@ -0,0 +1,84 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.LBool
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- Lifted boolean type.
+-- 
+-----------------------------------------------------------------------------
+module Data.LBool
+  ( LBool
+  , lTrue
+  , lFalse
+  , lUndef
+  , lnot
+  , liftBool
+  , unliftBool
+  ) where
+
+import Data.Int
+
+-- | Lifted Bool type. It has three values 'lTrue', 'lFalse', 'lUndef'.
+newtype LBool = LBool Int8 deriving Eq
+
+-- | lifted true value
+{-# INLINE lTrue #-}
+lTrue :: LBool
+lTrue = LBool 1
+
+-- | lifted false value
+{-# INLINE lFalse #-}
+lFalse :: LBool
+lFalse = LBool (-1)
+
+-- | undefined truth value
+{-# INLINE lUndef #-}
+lUndef :: LBool
+lUndef = LBool 0
+
+-- |
+-- @
+--   lnot lTrue == lFalse
+--   lnot lFalse == lTrue
+--   lnot lUndef == lUndef
+-- @
+{-# INLINE lnot #-}
+lnot :: LBool -> LBool
+lnot x
+  | x == lTrue  = lFalse
+  | x == lFalse = lTrue
+  | otherwise   = lUndef
+
+-- |
+-- @
+--   liftBool True == lTrue
+--   liftBool False == lFalse
+-- @
+{-# INLINE liftBool #-}
+liftBool :: Bool -> LBool
+liftBool True  = lTrue
+liftBool False = lFalse
+
+-- |
+-- @
+--   unliftBool lTrue == Just True
+--   unliftBool lFalse == Just False
+--   unliftBool lUndef == Nothing
+-- @
+{-# INLINE unliftBool #-}
+unliftBool :: LBool -> Maybe Bool
+unliftBool x
+  | x == lTrue  = Just True
+  | x == lFalse = Just False
+  | otherwise   = Nothing
+
+instance Show LBool where
+  show x
+    | x == lTrue  = "lTrue"
+    | x == lFalse = "lFalse"
+    | otherwise   = "lUndef"
diff --git a/src/Data/Lattice.hs b/src/Data/Lattice.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Lattice.hs
@@ -0,0 +1,90 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Lattice
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- Type classes for lattices and boolean algebras.
+-- 
+-----------------------------------------------------------------------------
+module Data.Lattice
+  (
+  -- * Lattice
+    Lattice (..)
+  
+  -- * Boolean algebra
+  , Complement (..)
+  , Boolean (..)
+  , true
+  , false
+  , (.&&.)
+  , (.||.)
+  , andB
+  , orB
+  ) where
+
+infixr 3 .&&.
+infixr 2 .||.
+infix 1 .=>., .<=>.
+
+-- | Type class for lattice.
+class Lattice a where
+  -- | top element
+  top :: a
+
+  -- | bottom element
+  bottom :: a
+
+  -- | join
+  join :: a -> a -> a
+
+  -- | meet
+  meet :: a -> a -> a
+
+  -- | n-ary join
+  joinL :: [a] -> a
+
+  -- | n-ary meet
+  meetL :: [a] -> a
+
+  joinL = foldr join bottom
+  meetL = foldr meet top
+
+-- | types that can be negated.
+class Complement a where
+  notB :: a -> a
+
+-- | types that can be combined with boolean operations.
+class (Lattice a, Complement a) => Boolean a where
+  (.=>.), (.<=>.) :: a -> a -> a
+  x .=>. y = notB x .||. y
+  x .<=>. y = (x .=>. y) .&&. (y .=>. x)
+
+-- | alias of 'top'
+true :: Boolean a => a
+true = top
+
+-- | alias of 'bottom'
+false :: Boolean a => a
+false = bottom
+
+-- | alias of 'meet'
+(.&&.) :: Boolean a => a -> a -> a
+(.&&.) = meet
+
+-- | alias of 'join'
+(.||.) :: Boolean a => a -> a -> a
+(.||.) = join
+
+-- | alias of 'meetL'
+andB :: Boolean a => [a] -> a
+andB = meetL
+
+-- | alias of 'joinL'
+orB :: Boolean a => [a] -> a
+orB = joinL
diff --git a/src/Data/Linear.hs b/src/Data/Linear.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Linear.hs
@@ -0,0 +1,72 @@
+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Linear
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (MultiParamTypeClasses, FunctionalDependencies)
+--
+-- Type class of linear spaces.
+-- 
+-----------------------------------------------------------------------------
+
+module Data.Linear
+  ( Module (..)
+  , Linear (..)
+  ) where
+
+import Data.Ratio
+
+infixl 6 .+., .-.
+infixl 7 .*., ./.
+
+-- | The class of R-modules.
+class Num r => Module r a | a -> r where
+  (.*.) :: r -> a -> a
+  -- ^ scalar multiplication
+
+  (.+.) :: a -> a -> a
+  -- ^ addition
+
+  lzero :: a
+  -- ^ identity of '(.+.)'
+
+  -- | negation
+  lnegate :: a -> a
+  lnegate x = (-1) .*. x
+
+  -- | subtraction
+  (.-.) :: a -> a -> a
+  a .-. b = a .+. lnegate b
+
+  lsum :: [a] -> a
+  lsum = foldr (.+.) lzero
+
+-- | The class of linear spaces.
+class (Module k a, Fractional k) => Linear k a | a -> k where
+  -- | division
+  (./.) :: a -> k -> a
+  a ./. b = (1/b) .*. a
+
+instance Integral a => Module (Ratio a) (Ratio a) where
+  (.*.) = (*)
+  (.+.) = (+)
+  lzero = 0
+
+instance Integral a => Linear (Ratio a) (Ratio a)
+
+instance Module Integer Integer where
+  (.*.) = (*)
+  (.+.) = (+)
+  lzero = 0
+
+instance Module Double Double where
+  (.*.) = (*)
+  (.+.) = (+)
+  lzero = 0
+
+instance Linear Double Double
diff --git a/src/Data/Polyhedron.hs b/src/Data/Polyhedron.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Polyhedron.hs
@@ -0,0 +1,140 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Polyhedron
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- Affine subspaces that are characterized by a set of linear (in)equalities.
+-- 
+-----------------------------------------------------------------------------
+module Data.Polyhedron
+  ( Polyhedron
+  , univ
+  , empty
+  , intersection
+  , fromConstraints
+  , toConstraints
+  ) where
+
+import Data.List
+import Data.Ratio
+import qualified Data.IntSet as IS
+import qualified Data.Map as Map
+import Prelude hiding (null)
+
+import qualified Data.Interval as Interval
+import Data.Expr (Variables (..))
+import Data.Formula (RelOp (..), flipOp)
+import qualified Data.LA as LA
+import Data.Linear
+import Data.Lattice
+
+type ExprR = LA.Expr Rational
+type ExprZ = LA.Expr Integer
+
+type AtomR = LA.Atom Rational
+
+type IntervalR = Interval.Interval Rational
+
+-- | Intersection of half-spaces
+data Polyhedron
+  = Polyhedron (Map.Map ExprZ IntervalR)
+  | Empty
+  deriving (Eq)
+
+instance Variables Polyhedron where
+  vars (Polyhedron m) = IS.unions [vars e | e <- Map.keys m]
+  vars Empty = IS.empty
+
+instance Lattice Polyhedron where
+  top    = univ
+  bottom = empty
+  meet   = intersection
+  join Empty b = b
+  join a Empty = a
+  join (Polyhedron m1) (Polyhedron m2) =
+    normalize $ Polyhedron (Map.intersectionWith Interval.join m1 m2)
+
+normalize :: Polyhedron -> Polyhedron
+normalize (Polyhedron m) | any Interval.null (Map.elems m) = Empty
+normalize p = p
+
+-- | universe
+univ :: Polyhedron
+univ = Polyhedron Map.empty
+
+-- | empty space
+empty :: Polyhedron
+empty = Empty
+
+-- | intersection of 
+intersection :: Polyhedron -> Polyhedron -> Polyhedron
+intersection (Polyhedron m1) (Polyhedron m2) =
+  normalize $ Polyhedron (Map.unionWith Interval.intersection m1 m2)
+intersection _ _ = Empty
+
+-- | Create a set of 'Polyhedron's that are characterized by a given
+-- set of linear (in)equalities.
+fromConstraints :: [AtomR] -> [Polyhedron]
+fromConstraints cs = 
+  map (foldl' intersection univ) $ transpose $ map fromAtom cs
+
+fromAtom :: AtomR  -> [Polyhedron]
+fromAtom (LA.Atom lhs NEq rhs) =
+  fromAtom (LA.Atom lhs Lt rhs) ++ fromAtom (LA.Atom lhs Gt rhs)
+fromAtom (LA.Atom lhs op rhs) =
+  case LA.extract LA.unitVar (lhs .-. rhs) of
+    (c, e1) ->
+      case toRat e1 of
+        (lhs1, d) ->
+          let rhs1 = - c * fromIntegral d
+              (lhs2,op2,rhs2) =
+                if p lhs1
+                then (lnegate lhs1, flipOp op, - rhs1)
+                else (lhs1, op, rhs1)
+              ival =
+                case op of
+                  Lt  -> Interval.interval Nothing (Just (False, rhs2))
+                  Le  -> Interval.interval Nothing (Just (True, rhs2))
+                  Ge  -> Interval.interval (Just (True, rhs2)) Nothing
+                  Gt  -> Interval.interval (Just (False, rhs2)) Nothing
+                  Eql -> Interval.singleton rhs2
+                  NEq -> error "should not happen"
+          in filter (Empty /=) [normalize $ Polyhedron (Map.singleton lhs2 ival)]
+
+-- | Convert the polyhedron to a list of linear (in)equalities.
+toConstraints :: Polyhedron -> [AtomR]
+toConstraints Empty = [LA.Atom (LA.constant 0) Lt (LA.constant 0)]
+toConstraints (Polyhedron m) = do
+  (e, ival) <- Map.toList m
+  let e' = LA.mapCoeff fromIntegral e
+      xs = case Interval.lowerBound ival of
+             Nothing -> []
+             Just (True,c)  -> [LA.Atom (LA.constant c) Le e']
+             Just (False,c) -> [LA.Atom (LA.constant c) Lt e']
+      ys = case Interval.upperBound ival of
+             Nothing -> []
+             Just (True,c)  -> [LA.Atom e' Le (LA.constant c)]
+             Just (False,c) -> [LA.Atom e' Lt (LA.constant c)]
+  xs ++ ys
+
+p :: ExprZ -> Bool
+p e =
+  case LA.terms e of
+    (c,_):_ | c < 0 -> True
+    _ -> False
+
+-- | (t,c) represents t/c, and c must be >0.
+type Rat = (ExprZ, Integer)
+
+toRat :: ExprR -> Rat
+toRat e = (LA.mapCoeff f e, d)
+  where
+    f :: Rational -> Integer
+    f x = round (x * fromIntegral d)
+    d :: Integer
+    d = foldl' lcm 1 [denominator c | (c,_) <- LA.terms e]
diff --git a/src/Data/Polynomial.hs b/src/Data/Polynomial.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Polynomial.hs
@@ -0,0 +1,518 @@
+{-# LANGUAGE ScopedTypeVariables, FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Polynomial
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (ScopedTypeVariables, FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances)
+--
+-- Polynomials
+--
+-- References:
+--
+-- * Monomial order <http://en.wikipedia.org/wiki/Monomial_order>
+-- 
+-- * Gröbner basis <http://en.wikipedia.org/wiki/Gr%C3%B6bner_basis>
+--
+-- * グレブナー基底 <http://d.hatena.ne.jp/keyword/%A5%B0%A5%EC%A5%D6%A5%CA%A1%BC%B4%F0%C4%EC>
+--
+-- * Gröbner Bases and Buchberger’s Algorithm <http://math.rice.edu/~cbruun/vigre/vigreHW6.pdf>
+--
+-- * Polynomial class for Ruby <http://www.math.kobe-u.ac.jp/~kodama/tips-RubyPoly.html>
+--
+-- * Docon <http://www.haskell.org/docon/>
+--
+-- * constructive-algebra package <http://hackage.haskell.org/package/constructive-algebra>
+-- 
+-----------------------------------------------------------------------------
+module Data.Polynomial
+  (
+  -- * Polynomial type
+    Polynomial
+  , UPolynomial
+
+  -- * Conversion
+  , var
+  , constant
+  , terms
+  , fromTerms
+  , coeffMap
+  , fromCoeffMap
+  , fromMonomial
+
+  -- * Query
+  , leadingTerm
+  , deg
+  , coeff
+  , lookupCoeff
+
+  -- * Operations
+  , deriv
+  , integral
+  , eval
+  , evalM
+  , subst
+  , isRootOf
+  , mapVar
+  , mapCoeff
+  , toMonic
+  , toZ
+  , polyDiv
+  , polyMod
+  , polyDivMod
+  , polyGCD
+  , polyLCM
+  , polyMDivMod
+  , reduce
+
+  -- * Monomial
+  , Monomial
+  , monomialDegree
+  , monomialProd
+  , monomialDivisible
+  , monomialDiv
+  , monomialDeriv
+  , monomialIntegral
+
+  -- * Monic monomial
+  , MonicMonomial
+  , mmVar
+  , mmOne
+  , mmFromList
+  , mmToList
+  , mmToIntMap
+  , mmDegree
+  , mmProd
+  , mmDivisible
+  , mmDiv
+  , mmDeriv
+  , mmIntegral
+  , mmLCM
+  , mmGCD
+  , mmMapVar
+
+  -- * Monomial order
+  , MonomialOrder
+  , lex
+  , revlex
+  , grlex
+  , grevlex
+
+  -- * Utility functions
+  , render
+  , renderWith
+  , RenderCoeff (..)
+  , RenderVar (..)
+  ) where
+
+import Prelude hiding (lex)
+import Control.Monad
+import Data.Function
+import Data.List
+import Data.Monoid
+import Data.Ratio
+import qualified Data.Map as Map
+import qualified Data.Set as Set
+import qualified Data.IntMap as IM
+
+import Data.Linear
+
+{--------------------------------------------------------------------
+  Polynomial type
+--------------------------------------------------------------------}
+
+-- | Polynomial over commutative ring r
+newtype Polynomial k v = Polynomial{ coeffMap :: Map.Map (MonicMonomial v) k }
+  deriving (Eq, Ord)
+
+-- | Univalent polynomials over commutative ring r
+type UPolynomial r = Polynomial r ()
+
+instance (Eq k, Num k, Ord v, Show v) => Num (Polynomial k v) where
+  Polynomial m1 + Polynomial m2 = normalize $ Polynomial $ Map.unionWith (+) m1 m2
+  Polynomial m1 * Polynomial m2 = normalize $ Polynomial $ Map.fromListWith (+)
+      [ (xs1 `mmProd` xs2, c1*c2)
+      | (xs1,c1) <- Map.toList m1, (xs2,c2) <- Map.toList m2
+      ]
+  negate (Polynomial m) = Polynomial $ Map.map negate m
+  abs x = x    -- OK?
+  signum x = 1 -- OK?
+  fromInteger x = constant (fromInteger x)
+
+instance (Eq k, Num k, Ord v, Show v) => Module k (Polynomial k v) where
+  k .*. p = constant k * p
+  p .+. q = p + q
+  lzero = 0
+
+instance (Eq k, Fractional k, Ord v, Show v) => Linear k (Polynomial k v)
+
+instance (Show v, Ord v, Show k) => Show (Polynomial k v) where
+  showsPrec d p  = showParen (d > 10) $
+    showString "fromTerms " . shows (terms p)
+
+normalize :: (Eq k, Num k, Ord v) => Polynomial k v -> Polynomial k v
+normalize (Polynomial m) = Polynomial (Map.filter (0/=) m)
+
+-- | construct a polynomial from a variable
+var :: (Eq k, Num k, Ord v) => v -> Polynomial k v
+var x = fromMonomial (1, mmVar x)
+
+-- | construct a polynomial from a constant
+constant :: (Eq k, Num k, Ord v) => k -> Polynomial k v
+constant c = fromMonomial (c, mmOne)
+
+-- | construct a polynomial from a list of monomials
+fromTerms :: (Eq k, Num k, Ord v) => [Monomial k v] -> Polynomial k v
+fromTerms = normalize . Polynomial . Map.fromListWith (+) . map (\(c,xs) -> (xs,c))
+
+fromCoeffMap :: (Eq k, Num k, Ord v) => Map.Map (MonicMonomial v) k -> Polynomial k v
+fromCoeffMap m = normalize $ Polynomial m
+
+-- | construct a polynomial from a monomial
+fromMonomial :: (Eq k, Num k, Ord v) => Monomial k v -> Polynomial k v
+fromMonomial (c,xs) = normalize $ Polynomial $ Map.singleton xs c
+
+-- | list of monomials
+terms :: Polynomial k v -> [Monomial k v]
+terms (Polynomial m) = [(c,xs) | (xs,c) <- Map.toList m]
+
+-- | leading term with respect to a given monomial order
+leadingTerm :: (Eq k, Num k, Ord v) => MonomialOrder v -> Polynomial k v -> Monomial k v
+leadingTerm cmp p =
+  case terms p of
+    [] -> (0, mmOne) -- should be error?
+    ms -> maximumBy (cmp `on` snd) ms
+
+-- | total degree of a given polynomial
+deg :: Polynomial k v -> Integer
+deg = maximum . (0:) . map monomialDegree . terms
+
+coeff :: (Num k, Ord v) => MonicMonomial v -> Polynomial k v -> k
+coeff xs (Polynomial m) = Map.findWithDefault 0 xs m
+
+lookupCoeff :: Ord v => MonicMonomial v -> Polynomial k v -> Maybe k
+lookupCoeff xs (Polynomial m) = Map.lookup xs m
+
+-- | Formal derivative of polynomials
+deriv :: (Eq k, Num k, Ord v, Show v) => Polynomial k v -> v -> Polynomial k v
+deriv p x = sum [fromMonomial (monomialDeriv m x) | m <- terms p]
+
+-- | Formal integral of polynomials
+integral :: (Eq k, Fractional k, Ord v, Show v) => Polynomial k v -> v -> Polynomial k v
+integral p x = sum [fromMonomial (monomialIntegral m x) | m <- terms p]
+
+-- | Evaluation
+eval :: (Num k, Ord v) => (v -> k) -> Polynomial k v -> k
+eval env p = sum [c * product [(env x) ^ e | (x,e) <- mmToList xs] | (c,xs) <- terms p]
+
+-- | Monadic evaluation
+evalM :: (Num k, Ord v, Monad m) => (v -> m k) -> Polynomial k v -> m k
+evalM env p = do
+  liftM sum $ forM (terms p) $ \(c,xs) -> do
+    rs <- mapM (\(x,e) -> liftM (^ e) (env x)) (mmToList xs)
+    return (c * product rs)
+
+-- | Substitution or bind
+subst :: (Num k, Eq k, Ord v1, Ord v2, Show v2) => Polynomial k v1 -> (v1 -> Polynomial k v2) -> Polynomial k v2
+subst p s =
+  sum [constant c * product [(s x)^e | (x,e) <- mmToList xs] | (c, xs) <- terms p]
+
+isRootOf :: (Num k, Eq k) => k -> UPolynomial k -> Bool
+isRootOf x p = eval (\_ -> x) p == 0
+
+mapVar :: (Num k, Eq k, Ord v1, Ord v2) => (v1 -> v2) -> Polynomial k v1 -> Polynomial k v2
+mapVar f (Polynomial m) = normalize $ Polynomial $ Map.mapKeysWith (+) (mmMapVar f) m
+
+mapCoeff :: (Eq k1, Num k1, Ord v) => (k -> k1) -> Polynomial k v -> Polynomial k1 v
+mapCoeff f (Polynomial m) = normalize $ Polynomial $ Map.map f m
+
+toMonic :: (Real r, Fractional r, Ord v) => Polynomial r v -> Polynomial r v
+toMonic p
+  | c == 0 = p
+  | otherwise = mapCoeff (/c) p
+  where
+    (c,_) = leadingTerm grlex p
+
+toZ :: (Real r, Ord v) => Polynomial r v -> Polynomial Integer v
+toZ p = fromTerms [(numerator (c * fromInteger s), xs) | (c,xs) <- ts]
+  where
+    ts = [(toRational c, xs) | (c,xs) <- terms p]
+    s = foldl' lcm  1 (map (denominator . fst) ts)
+
+-- | Multivariate division algorithm
+polyMDivMod
+  :: forall k v. (Eq k, Fractional k, Ord v, Show v)
+  => MonomialOrder v -> Polynomial k v -> [Polynomial k v] -> ([Polynomial k v], Polynomial k v)
+polyMDivMod cmp p fs = go IM.empty p
+  where
+    ls = [(leadingTerm cmp f, f) | f <- fs]
+
+    go :: IM.IntMap (Polynomial k v) -> Polynomial k v -> ([Polynomial k v], Polynomial k v)
+    go qs g =
+      case xs of
+        [] -> ([IM.findWithDefault 0 i qs | i <- [0 .. length fs - 1]], g)
+        (i, b, g') : _ -> go (IM.insertWith (+) i b qs) g'
+      where
+        ms = sortBy (flip cmp `on` snd) (terms g)
+        xs = do
+          (i,(a,f)) <- zip [0..] ls
+          h <- ms
+          guard $ monomialDivisible h a
+          let b = fromMonomial $ monomialDiv h a
+          return (i, b, g - b * f)
+
+-- | Multivariate division algorithm
+reduce
+  :: (Eq k, Fractional k, Ord v, Show v)
+  => MonomialOrder v -> Polynomial k v -> [Polynomial k v] -> Polynomial k v
+reduce cmp p fs = go p
+  where
+    ls = [(leadingTerm cmp f, f) | f <- fs]
+    go g = if null xs then g else go (head xs)
+      where
+        ms = sortBy (flip cmp `on` snd) (terms g)
+        xs = do
+          (a,f) <- ls
+          h <- ms
+          guard $ monomialDivisible h a
+          return (g - fromMonomial (monomialDiv h a) * f)
+
+{--------------------------------------------------------------------
+  Rendering
+--------------------------------------------------------------------}
+
+render
+  :: (Eq k, Ord k, Num k, Ord v, RenderCoeff k, RenderVar v)
+  => Polynomial k v -> String
+render = renderWith renderVar
+
+renderWith
+  :: (Eq k, Ord k, Num k, Ord v, RenderCoeff k)
+  => (Int -> v -> ShowS)
+  -> Polynomial k v -> String
+renderWith s2 p =
+  case sortBy (flip grlex `on` snd) $ terms p of
+    [] -> "0"
+    (c,xs):ts -> f c xs ++ concat [if isNegativeCoeff c then " - " ++ (f (-c) xs) else " + " ++ f c xs | (c,xs) <- ts]
+  where
+    f c xs = (intercalate "*" ([renderCoeff 8 c "" | c /= 1 || null (mmToList xs)] ++ [g x e | (x,e) <- mmToList xs]))
+    g x 1 = s2 8 x ""
+    g x n = s2 9 x "" ++ "^" ++ show n
+
+class RenderCoeff a where
+  renderCoeff :: Int -> a -> ShowS
+  isNegativeCoeff :: a -> Bool
+
+instance RenderCoeff Integer where
+  renderCoeff = showsPrec
+  isNegativeCoeff = (0>)
+
+instance RenderCoeff Rational where
+  renderCoeff p r
+    | denominator r == 1 = showsPrec p (numerator r)
+    | otherwise = 
+        showParen (p > ratioPrec) $
+        showsPrec ratioPrec1 (numerator r) .
+        showString "/" .
+        showsPrec ratioPrec1 (denominator r)
+    where
+      ratioPrec, ratioPrec1 :: Int
+      ratioPrec  = 7  -- Precedence of '/'
+      ratioPrec1 = ratioPrec + 1
+  isNegativeCoeff = (0>)
+
+class RenderVar v where
+  renderVar :: Int -> v -> ShowS
+
+instance RenderVar Int where
+  renderVar prec n = showChar 'x' . showsPrec 0 n
+
+instance RenderVar () where
+  renderVar prec n = showChar 'x'
+
+{--------------------------------------------------------------------
+  Univalent polynomials
+--------------------------------------------------------------------}
+
+-- | division of univalent polynomials
+polyDiv :: (Eq k, Fractional k) => UPolynomial k -> UPolynomial k -> UPolynomial k
+polyDiv f1 f2 = fst (polyDivMod f1 f2)
+
+-- | division of univalent polynomials
+polyMod :: (Eq k, Fractional k) => UPolynomial k -> UPolynomial k -> UPolynomial k
+polyMod f1 f2 = snd (polyDivMod f1 f2)
+
+-- | division of univalent polynomials
+polyDivMod :: (Eq k, Fractional k) => UPolynomial k -> UPolynomial k -> (UPolynomial k, UPolynomial k)
+polyDivMod f1 f2 = go f1
+  where
+    m2 = leadingTerm lex f2
+    go 0 = (0,0)
+    go f1
+      | m1 `monomialDivisible` m2 =
+          case go (f1 - fromMonomial (m1 `monomialDiv` m2) * f2) of
+            (q,r) -> (q + fromMonomial (m1 `monomialDiv` m2), r)
+      | otherwise = (0, f1)
+      where
+        m1 = leadingTerm lex f1
+
+scaleLeadingTermToMonic :: (Eq k, Fractional k) => UPolynomial k -> UPolynomial k
+scaleLeadingTermToMonic f = if c==0 then f else constant (1/c) * f
+  where
+    (c,_) = leadingTerm lex f
+
+-- | GCD of univalent polynomials
+polyGCD :: (Eq k, Fractional k) => UPolynomial k -> UPolynomial k -> UPolynomial k
+polyGCD f1 0  = scaleLeadingTermToMonic f1
+polyGCD f1 f2 = polyGCD f2 (f1 `polyMod` f2)
+
+-- | LCM of univalent polynomials
+polyLCM :: (Eq k, Fractional k) => UPolynomial k -> UPolynomial k -> UPolynomial k
+polyLCM _ 0 = 0
+polyLCM 0 _ = 0
+polyLCM f1 f2 = scaleLeadingTermToMonic $ (f1 `polyMod` (polyGCD f1 f2)) * f2    
+
+{--------------------------------------------------------------------
+  Monomial
+--------------------------------------------------------------------}
+
+type Monomial k v = (k, MonicMonomial v)
+
+monomialDegree :: Monomial k v -> Integer
+monomialDegree (_,xs) = mmDegree xs
+
+monomialProd :: (Num k, Ord v) => Monomial k v -> Monomial k v -> Monomial k v
+monomialProd (c1,xs1) (c2,xs2) = (c1*c2, xs1 `mmProd` xs2)
+
+monomialDivisible :: (Fractional k, Ord v) => Monomial k v -> Monomial k v -> Bool
+monomialDivisible (c1,xs1) (c2,xs2) = mmDivisible xs1 xs2
+
+monomialDiv :: (Fractional k, Ord v) => Monomial k v -> Monomial k v -> Monomial k v
+monomialDiv (c1,xs1) (c2,xs2) = (c1 / c2, xs1 `mmDiv` xs2)
+
+monomialDeriv :: (Eq k, Num k, Ord v) => Monomial k v -> v -> Monomial k v
+monomialDeriv (c,xs) x =
+  case mmDeriv xs x of
+    (s,ys) -> (c * fromIntegral s, ys)
+
+monomialIntegral :: (Eq k, Fractional k, Ord v) => Monomial k v -> v -> Monomial k v
+monomialIntegral (c,xs) x =
+  case mmIntegral xs x of
+    (s,ys) -> (c * fromRational s, ys)
+
+{--------------------------------------------------------------------
+  Monic Monomial
+--------------------------------------------------------------------}
+
+-- 本当は変数の型に応じて type family で表現を変えたい
+
+-- | Monic monomials
+newtype MonicMonomial v = MonicMonomial (Map.Map v Integer)
+  deriving (Eq, Ord)
+
+instance (Ord v, Show v) => Show (MonicMonomial v) where
+  showsPrec d m  = showParen (d > 10) $
+    showString "mmFromList " . shows (mmToList m)
+
+mmDegree :: MonicMonomial v -> Integer
+mmDegree (MonicMonomial m) = sum $ Map.elems m
+
+mmVar :: Ord v => v -> MonicMonomial v
+mmVar x = MonicMonomial $ Map.singleton x 1
+
+mmOne :: MonicMonomial v
+mmOne = MonicMonomial $ Map.empty
+
+mmFromList :: Ord v => [(v, Integer)] -> MonicMonomial v
+mmFromList xs
+  | any (\(x,e) -> 0>e) xs = error "mmFromList: negative exponent"
+  | otherwise = MonicMonomial $ Map.fromListWith (+) [(x,e) | (x,e) <- xs, e > 0]
+
+mmToList :: Ord v => MonicMonomial v -> [(v, Integer)]
+mmToList (MonicMonomial m) = Map.toAscList m
+
+mmToIntMap :: MonicMonomial Int -> IM.IntMap Integer
+mmToIntMap (MonicMonomial m) = IM.fromDistinctAscList $ Map.toAscList m
+
+mmProd :: Ord v => MonicMonomial v -> MonicMonomial v -> MonicMonomial v
+mmProd (MonicMonomial xs1) (MonicMonomial xs2) = MonicMonomial $ Map.unionWith (+) xs1 xs2
+
+mmDivisible :: Ord v => MonicMonomial v -> MonicMonomial v -> Bool
+mmDivisible (MonicMonomial xs1) (MonicMonomial xs2) = Map.isSubmapOfBy (<=) xs2 xs1
+
+mmDiv :: Ord v => MonicMonomial v -> MonicMonomial v -> MonicMonomial v
+mmDiv (MonicMonomial xs1) (MonicMonomial xs2) = MonicMonomial $ Map.differenceWith f xs1 xs2
+  where
+    f m n
+      | m <= n    = Nothing
+      | otherwise = Just (m - n)
+
+mmDeriv :: Ord v => MonicMonomial v -> v -> (Integer, MonicMonomial v)
+mmDeriv (MonicMonomial xs) x
+  | n==0      = (0, mmOne)
+  | otherwise = (n, MonicMonomial $ Map.update f x xs)
+  where
+    n = Map.findWithDefault 0 x xs
+    f m
+      | m <= 1    = Nothing
+      | otherwise = Just $! m - 1
+
+mmIntegral :: Ord v => MonicMonomial v -> v -> (Rational, MonicMonomial v)
+mmIntegral (MonicMonomial xs) x =
+  (1 % fromIntegral (n + 1), MonicMonomial $ Map.insert x (n+1) xs)
+  where
+    n = Map.findWithDefault 0 x xs
+
+mmLCM :: Ord v => MonicMonomial v -> MonicMonomial v -> MonicMonomial v
+mmLCM (MonicMonomial m1) (MonicMonomial m2) = MonicMonomial $ Map.unionWith max m1 m2
+
+mmGCD :: Ord v => MonicMonomial v -> MonicMonomial v -> MonicMonomial v
+mmGCD (MonicMonomial m1) (MonicMonomial m2) = MonicMonomial $ Map.intersectionWith min m1 m2
+
+mmMapVar :: (Ord v1, Ord v2) => (v1 -> v2) -> MonicMonomial v1 -> MonicMonomial v2
+mmMapVar f (MonicMonomial m) = MonicMonomial $ Map.mapKeysWith (+) f m
+
+{--------------------------------------------------------------------
+  Monomial Order
+--------------------------------------------------------------------}
+
+type MonomialOrder v = MonicMonomial v -> MonicMonomial v -> Ordering
+
+-- | Lexicographic order
+lex :: Ord v => MonomialOrder v
+lex xs1 xs2 = go (mmToList xs1) (mmToList xs2)
+  where
+    go [] [] = EQ
+    go [] _  = LT -- = cmpare 0 n2
+    go _ []  = GT -- = cmpare n1 0
+    go ((x1,n1):xs1) ((x2,n2):xs2) =
+      case compare x1 x2 of
+        LT -> GT -- = compare n1 0
+        GT -> LT -- = compare 0 n2
+        EQ -> compare n1 n2 `mappend` go xs1 xs2
+
+-- | Reverse lexicographic order
+-- Note that revlex is NOT a monomial order.
+revlex :: Ord v => MonicMonomial v -> MonicMonomial v -> Ordering
+revlex xs1 xs2 = go (reverse (mmToList xs1)) (reverse (mmToList xs2))
+  where
+    go [] [] = EQ
+    go [] _  = GT -- = cmp 0 n2
+    go _ []  = LT -- = cmp n1 0
+    go ((x1,n1):xs1) ((x2,n2):xs2) =
+      case compare x1 x2 of
+        LT -> GT -- = cmp 0 n2
+        GT -> LT -- = cmp n1 0
+        EQ -> cmp n1 n2 `mappend` go xs1 xs2
+    cmp n1 n2 = compare n2 n1
+
+-- | graded lexicographic order
+grlex :: Ord v => MonomialOrder v
+grlex = (compare `on` mmDegree) `mappend` lex
+
+-- | graded reverse lexicographic order
+grevlex :: Ord v => MonomialOrder v
+grevlex = (compare `on` mmDegree) `mappend` revlex
diff --git a/src/Data/Polynomial/FactorZ.hs b/src/Data/Polynomial/FactorZ.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Polynomial/FactorZ.hs
@@ -0,0 +1,106 @@
+{-# LANGUAGE BangPatterns #-}
+-- http://en.wikipedia.org/wiki/Polynomial_factorization
+-- Kronecker's method
+module Data.Polynomial.FactorZ
+  ( factor
+  ) where
+
+import Data.List
+import Data.Numbers.Primes (primes)
+import Data.Polynomial
+import qualified Data.Polynomial.Lagrange as Lagrange
+import Util (isInteger)
+
+factor :: UPolynomial Integer -> [UPolynomial Integer]
+factor p = normalize $ factor' p
+
+normalize :: [UPolynomial Integer] -> [UPolynomial Integer]
+normalize ps = [constant c | let c = product $ map fst xs, c /= 1] ++ sort (map snd xs)
+  where
+    xs = map f ps
+
+    f :: UPolynomial Integer -> (Integer, UPolynomial Integer)
+    f q = case [c | (c,_) <- terms q] of
+            [] -> (1,q)
+            (c:cs) ->
+              let d :: Integer
+                  d = foldl' gcd c cs
+                  q2 = mapCoeff (`div` d) q
+              in if fst (leadingTerm grlex q2) < 0
+                 then (-d,q2)
+                 else (d,q2)
+
+factor' :: UPolynomial Integer -> [UPolynomial Integer]
+factor' 0 = [0]
+factor' 1 = []
+factor' p | deg p == 0 = [p]
+factor' p =
+  case factor2 p of
+    Nothing -> [p]
+    Just qs -> concatMap factor' qs
+
+factor2 :: UPolynomial Integer -> Maybe [UPolynomial Integer]
+factor2 p | p == var () = Nothing
+factor2 p =
+  case find (\(_,yi) -> yi==0) vs of
+    Just (xi,_) ->
+      let q1 = x - constant xi
+          q2 = p' `polyDiv` mapCoeff fromInteger q1
+      in Just [q1, toZ q2]
+    Nothing ->
+      let qs = map Lagrange.interpolation $
+                  sequence [[(fromInteger xi, fromInteger z) | z <- factors yi] | (xi,yi) <- vs]
+          zs = [ (q1,q2)
+               | q1 <- qs, deg q1 > 0, isUPolyZ q1
+               , let (q2,r) = p' `polyDivMod` q1
+               , r == 0, deg q2 > 0, isUPolyZ q2
+               ]
+      in case zs of
+           [] -> Nothing
+           (q1,q2):_ -> Just [toZ q1, toZ q2]
+  where
+    n = (deg p `div` 2)
+    xs = take (fromIntegral n + 1) xvalues
+    vs = [(x, eval (\() -> x) p) | x <- xs]
+    x = var ()
+    p' :: UPolynomial Rational
+    p' = mapCoeff fromInteger p
+
+isUPolyZ :: UPolynomial Rational -> Bool
+isUPolyZ p = and [isInteger c | (c,_) <- terms p]
+
+-- [0, 1, -1, 2, -2, 3, -3 ..]
+xvalues :: [Integer]
+xvalues = 0 : interleave [1,2..] [-1,-2..]
+
+interleave :: [a] -> [a] -> [a]
+interleave xs [] = xs
+interleave [] ys     = ys
+interleave (x:xs) ys = x : interleave ys xs
+
+factors :: Integer -> [Integer]
+factors 0 = []
+factors x = xs ++ map negate xs
+  where
+    ps = primeFactors (abs x)
+    xs = map product $ sequence [[p^i | i <- [0..n]] | (p,n) <- ps]
+
+primeFactors :: Integer -> [(Integer,Integer)]
+primeFactors 0 = []
+primeFactors n = f primes n
+  where
+    f :: [Integer] -> Integer -> [(Integer,Integer)]
+    f !_ 1 = []
+    f (p:ps) n
+      | p*p > n   = [(n,1)]
+      | otherwise =
+          case g p n of
+            (m,n') -> [(p,m) | m /= 0] ++ f ps n'
+
+    g :: Integer -> Integer -> (Integer, Integer)
+    g p = go 0
+      where
+        go !m !n
+          | n `mod` p == 0 = go (m+1) (n `div` p)
+          | otherwise = (m, n)
+          
diff --git a/src/Data/Polynomial/GBase.hs b/src/Data/Polynomial/GBase.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Polynomial/GBase.hs
@@ -0,0 +1,128 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Polynomial.GBase
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+-- 
+-- Gröbner basis
+--
+-- References:
+--
+-- * Monomial order <http://en.wikipedia.org/wiki/Monomial_order>
+-- 
+-- * Gröbner basis <http://en.wikipedia.org/wiki/Gr%C3%B6bner_basis>
+--
+-- * グレブナー基底 <http://d.hatena.ne.jp/keyword/%A5%B0%A5%EC%A5%D6%A5%CA%A1%BC%B4%F0%C4%EC>
+--
+-- * Gröbner Bases and Buchberger’s Algorithm <http://math.rice.edu/~cbruun/vigre/vigreHW6.pdf>
+--
+-- * Polynomial class for Ruby <http://www.math.kobe-u.ac.jp/~kodama/tips-RubyPoly.html>
+--
+-- * Docon <http://www.haskell.org/docon/>
+--
+-- * constructive-algebra package <http://hackage.haskell.org/package/constructive-algebra>
+-- 
+-----------------------------------------------------------------------------
+
+module Data.Polynomial.GBase
+  (
+  -- * Gröbner basis
+    buchberger
+  , spolynomial
+  , reduceGBase
+  ) where
+
+import qualified Data.Set as Set
+import qualified Data.Heap as H -- http://hackage.haskell.org/package/heaps
+import Data.Polynomial
+
+{-
+data Strategy
+  = NormalStrategy
+  | SugarStrategy
+  deriving (Eq, Ord, Show, Read, Bounded, Enum)
+-}
+
+spolynomial
+  :: (Eq k, Fractional k, Ord v, Show v)
+  => MonomialOrder v -> Polynomial k v -> Polynomial k v -> Polynomial k v
+spolynomial cmp f g =
+      fromMonomial ((1,xs) `monomialDiv` (c1,xs1)) * f
+    - fromMonomial ((1,xs) `monomialDiv` (c2,xs2)) * g
+  where
+    xs = mmLCM xs1 xs2
+    (c1, xs1) = leadingTerm cmp f
+    (c2, xs2) = leadingTerm cmp g
+
+buchberger
+  :: forall k v. (Eq k, Fractional k, Ord k, Ord v, Show v)
+  => MonomialOrder v -> [Polynomial k v] -> [Polynomial k v]
+buchberger cmp fs = reduceGBase cmp $ go fs (H.fromList [item cmp fi fj | (fi,fj) <- pairs fs, checkGCD fi fj])
+  where
+    go :: [Polynomial k v] -> H.Heap (Item k v) -> [Polynomial k v]
+    go gs h | H.null h = gs
+    go gs h
+      | r == 0    = go gs h'
+      | otherwise = go (r:gs) (H.union h' (H.fromList [item cmp r g | g <- gs, checkGCD fi fj]))
+      where
+        Just (i, h') = H.viewMin h
+        fi = iFst i
+        fj = iSnd i
+        spoly = spolynomial cmp fi fj
+        r = reduce cmp spoly gs
+
+    -- gcdが1となる組は選ばなくて良い
+    checkGCD fi fj = mmGCD mm1 mm2 /= mmOne
+      where
+        (_, mm1) = leadingTerm cmp fi
+        (_, mm2) = leadingTerm cmp fj
+
+reduceGBase
+  :: forall k v. (Eq k, Ord k, Fractional k, Ord v, Show v)
+  => MonomialOrder v -> [Polynomial k v] -> [Polynomial k v]
+reduceGBase cmp ps = Set.toList $ Set.fromList $ go ps []
+  where
+    go [] qs = qs
+    go (p:ps) qs
+      | q == 0    = go ps qs
+      | otherwise = go ps (constant (1/c) * q : qs)
+      where
+        q = reduce cmp p (ps++qs)
+        (c,_) = leadingTerm cmp q
+
+{--------------------------------------------------------------------
+  Item
+--------------------------------------------------------------------}
+
+data Item k v
+  = Item
+  { iFst :: Polynomial k v
+  , iSnd :: Polynomial k v
+  , iCmp :: MonomialOrder v
+  , iLCM :: MonicMonomial v
+  }
+
+item :: (Eq k, Num k, Ord v) => MonomialOrder v -> Polynomial k v -> Polynomial k v -> Item k v
+item cmp f g = Item f g cmp (mmLCM mm1 mm2)
+  where
+    (_, mm1) = leadingTerm cmp f
+    (_, mm2) = leadingTerm cmp g
+
+instance Ord v => Ord (Item k v) where
+  a `compare` b = iCmp a (iLCM a) (iLCM b)
+
+instance Ord v => Eq (Item k v) where
+  a == b = compare a b == EQ
+
+{--------------------------------------------------------------------
+  Utilities
+--------------------------------------------------------------------}
+
+pairs :: [a] -> [(a,a)]
+pairs [] = []
+pairs (x:xs) = [(x,y) | y <- xs] ++ pairs xs
diff --git a/src/Data/Polynomial/Graeffe.hs b/src/Data/Polynomial/Graeffe.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Polynomial/Graeffe.hs
@@ -0,0 +1,75 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Polynomial.Graeffe
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+-- 
+-- Graeffe's Method
+--
+-- Reference:
+-- 
+-- * <http://mathworld.wolfram.com/GraeffesMethod.html>
+-- 
+-- * <http://en.wikipedia.org/wiki/Graeffe's_method>
+-- 
+-----------------------------------------------------------------------------
+
+module Data.Polynomial.Graeffe
+  ( NthRoot (..)
+  , graeffesMethod
+  ) where
+
+import Control.Exception
+import qualified Data.IntMap as IM
+import Data.Polynomial
+
+data NthRoot = NthRoot !Integer !Rational
+  deriving (Show)
+
+graeffesMethod :: UPolynomial Rational -> Int -> [NthRoot]
+graeffesMethod p v = xs !! (v - 1)
+  where
+    xs = map (uncurry g) $ zip [1..] (tail $ iterate f $ toMonic p)
+
+    n = deg p
+
+    g :: Int -> UPolynomial Rational -> [NthRoot]
+    g v p = do
+      i <- [1::Int .. fromInteger n]
+      let yi = if i == 1 then - (b i) else - (b i / b (i-1))
+      return $ NthRoot (2 ^ fromIntegral v) yi
+      where
+        bs = IM.fromList [(fromInteger i, b) | (b,ys) <- terms p, let i = n - mmDegree ys, i /= 0]
+        b i = IM.findWithDefault 0 i bs
+
+f :: UPolynomial Rational -> UPolynomial Rational
+f p = (-1) ^ (deg p) *
+      fromTerms [ (c, mmFromList [assert (e `mod` 2 == 0) (x, e `div` 2) | (x,e) <- mmToList xs])
+                | (c,xs) <- terms (p * subst p (\_ -> - var ())) ]
+
+f' :: UPolynomial Rational -> UPolynomial Rational
+f' p = fromTerms [(b k, mmFromList [((), n - k)]) | k <- [0..n]]
+  where
+    n = deg p
+
+    a :: Integer -> Rational
+    a k
+      | n >= k    = coeff (mmFromList [((), n - k)]) p
+      | otherwise = 0
+
+    b :: Integer -> Rational
+    b k = (-1)^k * (a k)^2 + 2 * sum [(-1)^j * (a j) * (a (2*k-j)) | j <- [0..k-1]]
+
+test v = graeffesMethod p v
+  where
+    x = var ()
+    p = x^2 - 2
+
+test2 v = graeffesMethod p v
+ where
+    x = var ()
+    p = x^5 - 3*x - 1
diff --git a/src/Data/Polynomial/Lagrange.hs b/src/Data/Polynomial/Lagrange.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Polynomial/Lagrange.hs
@@ -0,0 +1,13 @@
+-- http://en.wikipedia.org/wiki/Lagrange_polynomial
+module Data.Polynomial.Lagrange
+  ( interpolation
+  ) where
+
+import Data.Polynomial
+
+interpolation :: (Eq k, Fractional k) => [(k,k)] -> UPolynomial k
+interpolation zs = sum $ do
+  (xj,yj) <- zs
+  let lj x = product [constant (1 / (xj - xm)) * (x - constant xm) | (xm,_) <- zs, xj /= xm]
+  let x = var ()
+  return $ constant yj * lj x
diff --git a/src/Data/Polynomial/Sturm.hs b/src/Data/Polynomial/Sturm.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Polynomial/Sturm.hs
@@ -0,0 +1,158 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Polynomial.Sturm
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+-- 
+-- Reference:
+-- 
+-- * \"/Sturm's theorem/.\" Wikipedia, The Free Encyclopedia. Wikimedia Foundation, Inc.
+--   2012-06-23. <http://en.wikipedia.org/wiki/Sturm%27s_theorem>
+-- 
+-- * Weisstein, Eric W. \"/Sturm Function/.\" From MathWorld--A Wolfram Web Resource.
+--   <http://mathworld.wolfram.com/SturmFunction.html>
+-- 
+-----------------------------------------------------------------------------
+
+module Data.Polynomial.Sturm
+  ( SturmChain
+  , sturmChain
+  , numRoots
+  , numRoots'
+  , separate
+  , separate'
+  , narrow
+  , narrow'
+  , approx
+  , approx'
+  ) where
+
+import Data.Maybe
+import Data.Polynomial
+import qualified Data.Interval as Interval
+import Data.Interval (Interval)
+
+-- | Sturm's chain (Sturm's sequence)
+type SturmChain = [UPolynomial Rational]
+
+-- | Sturm's sequence of a polynomial
+sturmChain :: UPolynomial Rational -> SturmChain
+sturmChain p = p0 : p1 : go p0 p1
+  where
+    x = ()
+    p0 = p
+    p1 = deriv p x
+    go p q = if r==0 then [] else r : go q r
+      where
+        r = - (p `polyMod` q)
+
+-- | The number of distinct real roots of @p@ in a given interval
+numRoots
+  :: UPolynomial Rational
+  -> Interval Rational
+  -> Int
+numRoots p ival = numRoots' (sturmChain p) ival
+
+-- | The number of distinct real roots of @p@ in a given interval.
+-- This function takes @p@'s sturm chain instead of @p@ itself.
+numRoots'
+  :: SturmChain
+  -> Interval Rational
+  -> Int
+numRoots' chain@(p:_) ival
+  | Interval.null ival2 = 0
+  | otherwise =
+      case (Interval.lowerBound ival2, Interval.upperBound ival2) of
+        (Just (in1,lb), Just (in2,ub)) ->
+          (if lb==ub then 0 else (n lb - n ub)) +
+          (if in1 && isRootOf lb p then 1 else 0) +
+          (if not in2 && isRootOf ub p then -1 else 0)
+        _ -> error "numRoots'': should not happen"
+  where
+    ival2 = boundInterval p ival
+    n x = countSignChanges [eval (\() -> x) q | q <- chain]
+
+countSignChanges :: [Rational] -> Int
+countSignChanges rs = countChanges xs
+  where
+    xs :: [Bool]
+    xs = map (0<) . filter (0/=) $ rs
+
+countChanges :: Eq a => [a] -> Int
+countChanges [] = 0
+countChanges (x:xs) = go x xs 0
+  where
+    go x [] r = r
+    go x1 (x2:xs) r
+      | x1==x2    = go x1 xs r
+      | otherwise = go x2 xs (r+1)
+
+-- | Closed interval that contains all real roots of a given polynomial.
+-- 根の限界
+-- <http://aozoragakuen.sakura.ne.jp/taiwa/taiwaNch02/node26.html>
+bounds :: UPolynomial Rational -> (Rational, Rational)
+bounds p = (-m, m)
+  where
+    m = if p==0
+        then 0
+        else max 1 (sum [abs (c/s) | (c,_) <- terms p] - 1)
+    (s,_) = leadingTerm grlex p
+
+boundInterval :: UPolynomial Rational -> Interval Rational -> Interval Rational
+boundInterval p ival = Interval.intersection ival (Interval.closedInterval lb ub)
+  where
+    (lb,ub) = bounds p
+
+-- | Disjoint intervals each of which contains exactly one real roots of the given polynoimal @p@.
+-- The intervals can be further narrowed by 'narrow' or 'narrow''.
+separate :: UPolynomial Rational -> [Interval Rational]
+separate p = separate' (sturmChain p)
+
+-- | Disjoint intervals each of which contains exactly one real roots of the given polynoimal @p@.
+-- The intervals can be further narrowed by 'narrow' or 'narrow''.
+-- This function takes @p@'s sturm chain instead of @p@ itself.
+separate' :: SturmChain -> [Interval Rational]
+separate' chain@(p:_) = f (bounds p)
+  where
+    n x = countSignChanges [eval (\() -> x) q | q <- chain]
+
+    f (lb,ub) =
+      if lb `isRootOf` p
+      then Interval.singleton lb : g (lb,ub)
+      else g (lb,ub)
+    
+    g (lb,ub) =
+      case n lb - n ub of
+        0 -> []
+        1 -> [Interval.interval (Just (False, lb)) (Just (True, ub))]
+        _ -> g (lb, mid) ++ g (mid, ub)
+      where
+        mid = (lb + ub) / 2
+
+narrow :: UPolynomial Rational -> Interval Rational -> Rational -> Interval Rational
+narrow p ival size = narrow' (sturmChain p) ival size
+
+narrow' :: SturmChain -> Interval Rational -> Rational -> Interval Rational
+narrow' chain@(p:_) ival size = go (boundInterval p ival)
+  where
+    go ival
+      | s < size = ival
+      | numRoots' chain ivalL > 0 = go ivalL
+      | otherwise = go ivalR -- numRoots' chain ivalR > 0
+      where
+        (_,lb) = fromJust $ Interval.lowerBound ival
+        (_,ub) = fromJust $ Interval.upperBound ival
+        s = ub - lb
+        mid = (lb + ub) / 2
+        ivalL = Interval.interval (Interval.lowerBound ival) (Just (True,mid))
+        ivalR = Interval.interval (Just (False,mid)) (Interval.upperBound ival)
+
+approx :: UPolynomial Rational -> Interval Rational -> Rational -> Rational
+approx p = approx' (sturmChain p)
+
+approx' :: SturmChain -> Interval Rational -> Rational -> Rational
+approx' chain ival epsilon = fromJust $ Interval.pickup $ narrow' chain ival epsilon
diff --git a/src/Data/SeqQueue.hs b/src/Data/SeqQueue.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/SeqQueue.hs
@@ -0,0 +1,67 @@
+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.SeqQueue
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (FlexibleInstances, MultiParamTypeClasses)
+--
+-- Queue implemented using IORef and Sequence.
+-- 
+-----------------------------------------------------------------------------
+module Data.SeqQueue
+  (
+  -- * SeqQueue type
+    SeqQueue
+
+  -- * Constructors
+  , NewFifo (..)
+
+  -- * Operators  
+  , Enqueue (..)
+  , Dequeue (..)
+  , QueueSize (..)
+  , clear
+  ) where
+
+import Data.IORef
+import Data.Queue
+import Data.Foldable
+import qualified Data.Sequence as Seq
+
+newtype SeqQueue a = SeqQueue (IORef (Seq.Seq a))
+
+instance NewFifo (SeqQueue a) IO where
+  newFifo = do
+    ref <- newIORef Seq.empty
+    return (SeqQueue ref)
+
+instance Enqueue (SeqQueue a) IO a where
+  enqueue (SeqQueue ref) val = do
+    modifyIORef ref (Seq.|> val)
+
+instance Dequeue (SeqQueue a) IO a where
+  dequeue (SeqQueue ref) = do
+    s <- readIORef ref
+    case Seq.viewl s of
+      Seq.EmptyL -> return Nothing
+      val Seq.:< s' -> do
+        writeIORef ref s'
+        return (Just val)
+
+  dequeueBatch (SeqQueue ref) = do
+    s <- readIORef ref
+    writeIORef ref Seq.empty
+    return (toList s)
+
+instance QueueSize (SeqQueue a) IO where
+  queueSize (SeqQueue ref) = do
+    s <- readIORef ref
+    return $! Seq.length s
+
+clear :: SeqQueue a -> IO ()
+clear (SeqQueue ref) = do
+  writeIORef ref Seq.empty
diff --git a/src/FourierMotzkin.hs b/src/FourierMotzkin.hs
new file mode 100644
--- /dev/null
+++ b/src/FourierMotzkin.hs
@@ -0,0 +1,301 @@
+{-# OPTIONS_GHC -Wall #-}
+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  FourierMotzkin
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (MultiParamTypeClasses, FunctionalDependencies)
+--
+-- Naïve implementation of Fourier-Motzkin Variable Elimination
+-- 
+-- Reference:
+--
+-- * <http://users.cecs.anu.edu.au/~michaeln/pubs/arithmetic-dps.pdf>
+--
+-----------------------------------------------------------------------------
+module FourierMotzkin
+    ( module Data.Expr
+    , module Data.Formula
+    , Lit (..)
+    , eliminateQuantifiers
+    , solve
+
+    -- FIXME
+    , termR
+    , Rat
+    , collectBounds
+    , boundConditions
+    , evalBounds
+    , simplify
+    , constraintsToDNF
+    ) where
+
+import Control.Monad
+import Data.List
+import Data.Maybe
+import Data.Ratio
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+
+import Data.Expr
+import Data.Formula
+import Data.Linear
+import qualified Data.LA as LA
+import qualified Data.Interval as Interval
+
+-- ---------------------------------------------------------------------------
+
+type ExprZ = LA.Expr Integer
+
+-- | (t,c) represents t/c, and c must be >0.
+type Rat = (ExprZ, Integer)
+
+evalRat :: Model Rational -> Rat -> Rational
+evalRat model (e, d) = LA.lift1 1 (model IM.!) (LA.mapCoeff fromIntegral e) / (fromIntegral d)
+
+-- | Literal
+data Lit = Nonneg ExprZ | Pos ExprZ deriving (Show, Eq, Ord)
+
+instance Variables Lit where
+  vars (Pos t) = vars t
+  vars (Nonneg t) = vars t
+
+instance Complement Lit where
+  notB (Pos t) = Nonneg (lnegate t)
+  notB (Nonneg t) = Pos (lnegate t)
+
+-- 制約集合の単純化
+-- It returns Nothing when a inconsistency is detected.
+simplify :: [Lit] -> Maybe [Lit]
+simplify = fmap concat . mapM f
+  where
+    f :: Lit -> Maybe [Lit]
+    f lit@(Pos e) =
+      case LA.asConst e of
+        Just x -> guard (x > 0) >> return []
+        Nothing -> return [lit]
+    f lit@(Nonneg e) =
+      case LA.asConst e of
+        Just x -> guard (x >= 0) >> return []
+        Nothing -> return [lit]
+
+-- ---------------------------------------------------------------------------
+
+atomR :: RelOp -> Expr Rational -> Expr Rational -> Maybe (DNF Lit)
+atomR op a b = do
+  a' <- termR a
+  b' <- termR b
+  return $ case op of
+    Le -> DNF [[a' `leR` b']]
+    Lt -> DNF [[a' `ltR` b']]
+    Ge -> DNF [[a' `geR` b']]
+    Gt -> DNF [[a' `gtR` b']]
+    Eql -> DNF [[a' `leR` b', a' `geR` b']]
+    NEq -> DNF [[a' `ltR` b'], [a' `gtR` b']]
+
+termR :: Expr Rational -> Maybe Rat
+termR (Const c) = return (LA.constant (numerator c), denominator c)
+termR (Var v) = return (LA.var v, 1)
+termR (a :+: b) = do
+  (t1,c1) <- termR a
+  (t2,c2) <- termR b
+  return (c2 .*. t1 .+. c1 .*. t2, c1*c2)
+termR (a :*: b) = do
+  (t1,c1) <- termR a
+  (t2,c2) <- termR b
+  msum [ do{ c <- LA.asConst t1; return (c .*. t2, c1*c2) }
+       , do{ c <- LA.asConst t2; return (c .*. t1, c1*c2) }
+       ]
+termR (a :/: b) = do
+  (t1,c1) <- termR a
+  (t2,c2) <- termR b
+  c3 <- LA.asConst t2
+  guard $ c3 /= 0
+  return (c2 .*. t1, c1*c3)
+
+leR, ltR, geR, gtR :: Rat -> Rat -> Lit
+leR (e1,c) (e2,d) = Nonneg $ normalizeExprR $ c .*. e2 .-. d .*. e1
+ltR (e1,c) (e2,d) = Pos $ normalizeExprR $ c .*. e2 .-. d .*. e1
+geR = flip leR
+gtR = flip gtR
+
+normalizeExprR :: ExprZ -> ExprZ
+normalizeExprR e = LA.mapCoeff (`div` d) e
+  where d = abs $ gcd' $ map fst $ LA.terms e
+
+-- ---------------------------------------------------------------------------
+
+{-
+(ls1,ls2,us1,us2) represents
+{ x | ∀(M,c)∈ls1. M/c≤x, ∀(M,c)∈ls2. M/c<x, ∀(M,c)∈us1. x≤M/c, ∀(M,c)∈us2. x<M/c }
+-}
+type BoundsR = ([Rat], [Rat], [Rat], [Rat])
+
+eliminate :: Var -> [Lit] -> DNF Lit
+eliminate v xs = DNF [rest] .&&. boundConditions bnd
+  where
+    (bnd, rest) = collectBounds v xs
+
+collectBounds :: Var -> [Lit] -> (BoundsR, [Lit])
+collectBounds v = foldr phi (([],[],[],[]),[])
+  where
+    phi :: Lit -> (BoundsR, [Lit]) -> (BoundsR, [Lit])
+    phi lit@(Nonneg t) x = f False lit t x
+    phi lit@(Pos t) x = f True lit t x
+
+    f :: Bool -> Lit -> ExprZ -> (BoundsR, [Lit]) -> (BoundsR, [Lit])
+    f strict lit t (bnd@(ls1,ls2,us1,us2), xs) =
+      case LA.extract v t of
+        (c,t') ->
+          case c `compare` 0 of
+            EQ -> (bnd, lit : xs)
+            GT ->
+              if strict
+              then ((ls1, (lnegate t', c) : ls2, us1, us2), xs) -- 0 < cx + M ⇔ -M/c <  x
+              else (((lnegate t', c) : ls1, ls2, us1, us2), xs) -- 0 ≤ cx + M ⇔ -M/c ≤ x
+            LT ->
+              if strict
+              then ((ls1, ls2, us1, (t', negate c) : us2), xs) -- 0 < cx + M ⇔ x < M/-c
+              else ((ls1, ls2, (t', negate c) : us1, us2), xs) -- 0 ≤ cx + M ⇔ x ≤ M/-c
+
+boundConditions :: BoundsR -> DNF Lit
+boundConditions  (ls1, ls2, us1, us2) = DNF $ maybeToList $ simplify $ 
+  [ x `leR` y | x <- ls1, y <- us1 ] ++
+  [ x `ltR` y | x <- ls1, y <- us2 ] ++ 
+  [ x `ltR` y | x <- ls2, y <- us1 ] ++
+  [ x `ltR` y | x <- ls2, y <- us2 ]
+
+eliminateQuantifiers :: Formula Rational -> Maybe (DNF Lit)
+eliminateQuantifiers = f
+  where
+    f T = return true
+    f F = return false
+    f (Atom (Rel a op b)) = atomR op a b
+    f (And a b) = liftM2 (.&&.) (f a) (f b)
+    f (Or a b) = liftM2 (.||.) (f a) (f b)
+    f (Not a) = f (pushNot a)
+    f (Imply a b) = f (Or (Not a) b)
+    f (Equiv a b) = f (And (Imply a b) (Imply b a))
+    f (Forall v a) = do
+      dnf <- f (Exists v (pushNot a))
+      return (notB dnf)
+    f (Exists v a) = do
+      dnf <- f a
+      return $ orB [eliminate v xs | xs <- unDNF dnf]
+
+solve :: Formula Rational -> SatResult Rational
+solve formula =
+  case eliminateQuantifiers formula of
+    Nothing -> Unknown
+    Just dnf ->
+      case msum [solve' vs xs | xs <- unDNF dnf] of
+        Nothing -> Unsat
+        Just m -> Sat m
+  where
+    vs = IS.toList (vars formula)
+
+solve' :: [Var] -> [Lit] -> Maybe (Model Rational)
+solve' vs xs = simplify xs >>= go vs
+  where
+    go [] [] = return IM.empty
+    go [] _ = mzero
+    go (v:vs) ys = msum (map f (unDNF (boundConditions bnd)))
+      where
+        (bnd, rest) = collectBounds v ys
+        f zs = do
+          model <- go vs (zs ++ rest)
+          val <- Interval.pickup (evalBounds model bnd)
+          return $ IM.insert v val model
+
+evalBounds :: Model Rational -> BoundsR -> Interval.Interval Rational
+evalBounds model (ls1,ls2,us1,us2) =
+  foldl' Interval.intersection Interval.univ $ 
+    [ Interval.interval (Just (True, evalRat model x)) Nothing  | x <- ls1 ] ++
+    [ Interval.interval (Just (False, evalRat model x)) Nothing | x <- ls2 ] ++
+    [ Interval.interval Nothing (Just (True, evalRat model x))  | x <- us1 ] ++
+    [ Interval.interval Nothing (Just (False, evalRat model x)) | x <- us2 ]
+
+-- ---------------------------------------------------------------------------
+
+constraintsToDNF :: [LA.Atom Rational] -> DNF Lit
+constraintsToDNF = andB . map constraintToDNF
+
+constraintToDNF :: LA.Atom Rational -> DNF Lit
+constraintToDNF (LA.Atom a op b) = DNF $
+  case op of
+    Eql -> [[Nonneg c, Nonneg (lnegate c)]]
+    NEq -> [[Pos c], [Pos (lnegate c)]]
+    Ge  -> [[Nonneg c]]
+    Le  -> [[Nonneg (lnegate c)]]
+    Gt  -> [[Pos c]]
+    Lt  -> [[Pos (lnegate c)]]
+  where
+    c = normalize (a .-. b)
+
+    normalize :: LA.Expr Rational -> ExprZ
+    normalize e = LA.mapCoeff (round . (*c)) e
+      where
+        c = fromIntegral $ foldl' lcm 1 ds
+        ds = [denominator c | (c,v) <- LA.terms e]
+
+-- ---------------------------------------------------------------------------
+
+gcd' :: [Integer] -> Integer
+gcd' [] = 1
+gcd' xs = foldl1' gcd xs
+
+-- ---------------------------------------------------------------------------
+
+{-
+7x + 12y + 31z = 17
+3x + 5y + 14z = 7
+1 ≤ x ≤ 40
+-50 ≤ y ≤ 50
+
+satisfiable in R
+but unsatisfiable in Z
+-}
+test1 :: Formula Rational
+test1 = c1 .&&. c2 .&&. c3 .&&. c4
+  where
+    x = Var 0
+    y = Var 1
+    z = Var 2
+    c1 = 7*x + 12*y + 31*z .==. 17
+    c2 = 3*x + 5*y + 14*z .==. 7
+    c3 = 1 .<=. x .&&. x .<=. 40
+    c4 = (-50) .<=. y .&&. y .<=. 50
+
+test1' :: [LA.Atom Rational]
+test1' = [c1, c2] ++ c3 ++ c4
+  where
+    x = LA.var 0
+    y = LA.var 1
+    z = LA.var 2
+    c1 = 7.*.x .+. 12.*.y .+. 31.*.z .==. LA.constant 17
+    c2 = 3.*.x .+. 5.*.y .+. 14.*.z .==. LA.constant 7
+    c3 = [LA.constant 1 .<=. x, x .<=. LA.constant 40]
+    c4 = [LA.constant (-50) .<=. y, y .<=. LA.constant 50]
+
+{-
+27 ≤ 11x+13y ≤ 45
+-10 ≤ 7x-9y ≤ 4
+
+satisfiable in R
+but unsatisfiable in Z
+-}
+test2 :: Formula Rational
+test2 = c1 .&&. c2
+  where
+    x = Var 0
+    y = Var 1
+    t1 = 11*x + 13*y
+    t2 = 7*x - 9*y
+    c1 = 27 .<=. t1 .&&. t1 .<=. 45
+    c2 = (-10) .<=. t2 .&&. t2 .<=. 4
+
+-- ---------------------------------------------------------------------------
diff --git a/src/LPSolver.hs b/src/LPSolver.hs
new file mode 100644
--- /dev/null
+++ b/src/LPSolver.hs
@@ -0,0 +1,250 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  LPSolver
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (ScopedTypeVariables)
+--
+-- Naïve implementation of Simplex method
+-- 
+-- Reference:
+--
+-- * <http://www.math.cuhk.edu.hk/~wei/lpch3.pdf>
+--
+-----------------------------------------------------------------------------
+
+module LPSolver where
+
+import Control.Monad
+import Control.Monad.State
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+import Data.OptDir
+
+import Data.Expr
+import Data.Formula
+import Data.Linear
+import qualified Data.LA as LA
+import qualified Data.Interval as Interval
+import qualified Simplex
+import qualified BoundsInference as BI
+
+-- ---------------------------------------------------------------------------
+-- LP Monad
+
+type Solver r = (Var, Simplex.Tableau r, VarSet, VarMap (LA.Expr r))
+type LP r = State (Solver r)
+
+emptySolver :: VarSet -> Solver r
+emptySolver vs = (1 + maximum ((-1) : IS.toList vs), IM.empty, IS.empty, IM.empty)
+
+gensym :: LP r Var
+gensym = do
+  (x,tbl,avs,defs) <- get
+  put (x+1,tbl,avs,defs)
+  return x
+
+getTableau :: LP r (Simplex.Tableau r)
+getTableau = do
+  (_,tbl,_,_) <- get
+  return tbl
+
+putTableau :: Simplex.Tableau r -> LP r ()
+putTableau tbl = do
+  (x,_,avs,defs) <- get
+  put (x,tbl,avs,defs)
+
+addArtificialVariable :: Var -> LP r ()
+addArtificialVariable v = do
+  (x,tbl,avs,defs) <- get
+  put (x, tbl, IS.insert v avs, defs)
+
+getArtificialVariables :: LP r VarSet
+getArtificialVariables = do
+  (_,_,avs,_) <- get
+  return avs
+
+clearArtificialVariables :: LP r ()
+clearArtificialVariables = do
+  (x,tbl,_,defs) <- get
+  put (x, tbl, IS.empty, defs)
+
+define :: Var -> LA.Expr r -> LP r ()
+define v e = do
+  (x,tbl,avs,defs) <- get
+  put (x,tbl,avs, IM.insert v e defs)
+
+getDefs :: LP r (VarMap (LA.Expr r))
+getDefs = do
+  (_,_,_,defs) <- get
+  return defs
+
+-- ---------------------------------------------------------------------------
+
+addConstraint :: Real r => LA.Atom r -> LP r ()
+addConstraint c = do
+  c <- expandDefs' c
+  let (e, rop, b) = normalizeConstraint c
+  tbl <- getTableau
+  case rop of
+    -- x≥b で b≤0 なら追加しない。ad hoc なので一般化したい。
+    Ge | isSingleVar e && b<=0 -> return ()
+
+    Le -> do
+      v <- gensym -- slack variable
+      putTableau $ Simplex.setRow v tbl (LA.coeffMap e, b)
+    Ge -> do
+      v1 <- gensym -- surplus variable
+      v2 <- gensym -- artificial variable
+      putTableau $ Simplex.setRow v2 tbl (LA.coeffMap (e .-. LA.var v1), b)
+      addArtificialVariable v2
+    Eql -> do
+      v <- gensym -- artificial variable
+      putTableau $ Simplex.setRow v tbl (LA.coeffMap e, b)
+      addArtificialVariable v
+    _ -> error $ "addConstraint does not support " ++ show rop
+  where
+    isSingleVar e =
+      case LA.terms e of
+        [(1,_)] -> True
+        _ -> False
+
+addConstraint2 :: Real r => LA.Atom r -> LP r ()
+addConstraint2 c = do
+  (LA.Atom lhs rop rhs) <- expandDefs' c
+  let
+    (b', e) = LA.extract LA.unitVar (lhs .-. rhs)
+    b = - b'
+  tbl <- getTableau
+  case rop of
+    Le -> f e b
+    Ge -> f (lnegate e) (negate b)
+    Eql -> do
+      f e b
+      f (lnegate e) (negate b)
+    _ -> error $ "addConstraint does not support " ++ show rop
+  where
+    -- -x≤b で -b≤0 なら追加しない。ad hoc なので一般化したい。
+    f e b  | isSingleNegatedVar e && -b <= 0 = return ()
+    f e b = do
+      tbl <- getTableau
+      v <- gensym -- slack variable
+      putTableau $ Simplex.setRow v tbl (LA.coeffMap e, b)
+
+    isSingleNegatedVar e =
+      case LA.terms e of
+        [(-1,_)] -> True
+        _ -> False
+
+expandDefs :: (Num r, Eq r) => LA.Expr r -> LP r (LA.Expr r)
+expandDefs e = do
+  defs <- getDefs
+  return $ LA.applySubst defs e
+
+expandDefs' :: (Num r, Eq r) => LA.Atom r -> LP r (LA.Atom r)
+expandDefs' (LA.Atom lhs op rhs) = do
+  lhs' <- expandDefs lhs
+  rhs' <- expandDefs rhs
+  return $ LA.Atom lhs' op rhs'
+
+tableau :: (RealFrac r) => [LA.Atom r] -> LP r ()
+tableau cs = do
+  let (nonnegVars, cs') = collectNonnegVars cs IS.empty
+      fvs = vars cs `IS.difference` nonnegVars
+  forM_ (IS.toList fvs) $ \v -> do
+    v1 <- gensym
+    v2 <- gensym
+    define v (LA.var v1 .-. LA.var v2)
+  mapM_ addConstraint cs'
+
+getModel :: Fractional r => VarSet -> LP r (Model r)
+getModel vs = do
+  tbl <- getTableau
+  defs <- getDefs
+  let bs = IM.map snd (IM.delete Simplex.objRow tbl)
+      vs' = vs `IS.union` IS.fromList [v | e <- IM.elems defs, v <- IS.toList (vars e)]
+      -- Note that IM.union is left-biased
+      m0 = bs `IM.union` IM.fromList [(v,0) | v <- IS.toList vs']
+  return $ IM.filterWithKey (\k _ -> k `IS.member` vs) $ IM.map (LA.evalExpr m0) defs `IM.union` m0
+
+phaseI :: (Fractional r, Real r) => LP r Bool
+phaseI = do
+  tbl <- getTableau
+  avs <- getArtificialVariables
+  let (ret, tbl') = Simplex.phaseI tbl avs
+  putTableau tbl'
+  when ret clearArtificialVariables
+  return ret
+
+simplex :: (Fractional r, Real r) => OptDir -> LA.Expr r -> LP r Bool
+simplex optdir obj = do
+  tbl <- getTableau
+  defs <- getDefs
+  let (ret, tbl') = Simplex.simplex optdir (Simplex.setObjFun tbl (LA.applySubst defs obj))
+  putTableau tbl'
+  return ret
+
+dualSimplex :: (Fractional r, Real r) => OptDir -> LA.Expr r -> LP r Bool
+dualSimplex optdir obj = do
+  tbl <- getTableau
+  defs <- getDefs
+  let (ret, tbl') = Simplex.dualSimplex optdir (Simplex.setObjFun tbl (LA.applySubst defs obj))
+  putTableau tbl'
+  return ret
+
+-- ---------------------------------------------------------------------------
+
+normalizeConstraint :: forall r. Real r => LA.Atom r -> (LA.Expr r, RelOp, r)
+normalizeConstraint (LA.Atom a op b)
+  | rhs < 0   = (lnegate lhs, flipOp op, negate rhs)
+  | otherwise = (lhs, op, rhs)
+  where
+    (c, lhs) = LA.extract LA.unitVar (a .-. b)
+    rhs = - c
+
+collectNonnegVars :: forall r. (RealFrac r) => [LA.Atom r] -> VarSet -> (VarSet, [LA.Atom r])
+collectNonnegVars cs ivs = (nonnegVars, cs)
+  where
+    vs = vars cs
+    bounds = BI.inferBounds initialBounds cs ivs 1000
+      where
+        initialBounds = IM.fromList [(v, Interval.univ) | v <- IS.toList vs]
+    nonnegVars = IS.filter f vs
+      where
+        f v = case Interval.lowerBound (bounds IM.! v) of
+                Just (_, lb) | 0 <= lb -> True
+                _ -> False
+
+    isTriviallyTrue :: LA.Atom r -> Bool
+    isTriviallyTrue (LA.Atom a op b) =
+      case op of
+        Le ->
+          case ub of
+            Nothing -> False
+            Just (_, val) -> val <= 0
+        Ge ->
+          case lb of
+            Nothing -> False
+            Just (_, val) -> val >= 0
+        Lt ->
+          case ub of
+            Nothing -> False
+            Just (incl, val) -> val < 0 || (not incl && val <= 0)
+        Gt ->
+          case lb of
+            Nothing -> False
+            Just (incl, val) -> val > 0 || (not incl && val >= 0)
+        Eql -> isTriviallyTrue (LA.Atom c Le lzero) && isTriviallyTrue (LA.Atom c Ge lzero)
+        NEq -> isTriviallyTrue (LA.Atom c Lt lzero) && isTriviallyTrue (LA.Atom c Gt lzero)
+      where
+        c = a .-. b
+        i = LA.computeInterval bounds c
+        lb = Interval.lowerBound i
+        ub = Interval.upperBound i
+
+-- ---------------------------------------------------------------------------
diff --git a/src/LPSolverHL.hs b/src/LPSolverHL.hs
new file mode 100644
--- /dev/null
+++ b/src/LPSolverHL.hs
@@ -0,0 +1,288 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  LPSolverHL
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (ScopedTypeVariables)
+--
+-- High-Level API for LPSolver.hs
+--
+-----------------------------------------------------------------------------
+
+module LPSolverHL
+  ( module Data.Expr
+  , module Data.Formula
+  , minimize
+  , maximize
+  , optimize
+  , solve
+  ) where
+
+import Control.Monad.State
+import Data.Maybe (fromMaybe)
+import Data.Ratio
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+import Data.OptDir
+
+import Data.Expr
+import Data.Formula
+import qualified Data.LA as LA
+import qualified Simplex
+import LPSolver
+
+-- ---------------------------------------------------------------------------
+
+maximize :: (RealFrac r) => Expr r -> [Atom r] -> OptResult r
+maximize = optimize OptMax
+
+minimize :: (RealFrac r) => Expr r -> [Atom r] -> OptResult r
+minimize = optimize OptMin
+
+optimize :: (RealFrac r) => OptDir -> Expr r -> [Atom r] -> OptResult r
+optimize optdir obj2 cs2 = fromMaybe OptUnknown $ do
+  obj <- LA.compileExpr obj2  
+  cs <- mapM LA.compileAtom cs2
+  return (optimize' optdir obj cs)
+
+solve :: (RealFrac r) => [Atom r] -> SatResult r
+solve cs2 = fromMaybe Unknown $ do
+  cs <- mapM LA.compileAtom cs2
+  return (solve' cs)
+
+-- ---------------------------------------------------------------------------
+
+solve' :: (RealFrac r) => [LA.Atom r] -> SatResult r
+solve' cs =
+  flip evalState (emptySolver vs) $ do
+    tableau cs
+    ret <- phaseI
+    if not ret
+      then return Unsat
+      else do
+        m <- getModel vs
+        return (Sat m)
+  where
+    vs = vars cs
+
+optimize' :: (RealFrac r) => OptDir -> LA.Expr r -> [LA.Atom r] -> OptResult r
+optimize' optdir obj cs =
+  flip evalState (emptySolver vs) $ do
+    tableau cs
+    ret <- phaseI
+    if not ret
+      then return OptUnsat
+      else do
+        ret2 <- simplex optdir obj
+        if not ret2
+          then return Unbounded
+          else do
+             m <- getModel vs
+             tbl <- getTableau 
+             return $ Optimum (Simplex.currentObjValue tbl) m
+  where
+    vs = vars cs `IS.union` vars obj
+
+-- ---------------------------------------------------------------------------
+-- Test cases
+
+example_3_2 :: (Expr Rational, [Atom Rational])
+example_3_2 = (obj, cond)
+  where
+    x1 = var 1
+    x2 = var 2
+    x3 = var 3
+    obj = 3*x1 + 2*x2 + 3*x3
+    cond = [ 2*x1 +   x2 +   x3 .<=. 2
+           ,   x1 + 2*x2 + 3*x3 .<=. 5
+           , 2*x1 + 2*x2 +   x3 .<=. 6
+           , x1 .>=. 0
+           , x2 .>=. 0
+           , x3 .>=. 0
+           ]
+
+test_3_2 :: Bool
+test_3_2 =
+  uncurry maximize example_3_2 == 
+  Optimum (27 % 5) (IM.fromList [(1,1 % 5),(2,0 % 1),(3,8 % 5)])
+
+example_3_5 :: (Expr Rational, [Atom Rational])
+example_3_5 = (obj, cond)
+  where
+    x1 = var 1
+    x2 = var 2
+    x3 = var 3
+    x4 = var 4
+    x5 = var 5
+    obj = -2*x1 + 4*x2 + 7*x3 + x4 + 5*x5
+    cond = [ -x1 +   x2 + 2*x3 +   x4 + 2*x5 .==. 7
+           , -x1 + 2*x2 + 3*x3 +   x4 +   x5 .==. 6
+           , -x1 +   x2 +   x3 + 2*x4 +   x5 .==. 4
+           , x2 .>=. 0
+           , x3 .>=. 0
+           , x4 .>=. 0
+           , x5 .>=. 0
+           ]
+
+test_3_5 :: Bool
+test_3_5 =
+  uncurry minimize example_3_5 ==
+  Optimum (19 % 1) (IM.fromList [(1,(-1) % 1),(2,0 % 1),(3,1 % 1),(4,0 % 1),(5,2 % 1)]) 
+
+example_4_1 :: (Expr Rational, [Atom Rational])
+example_4_1 = (obj, cond)
+  where
+    x1 = var 1
+    x2 = var 2
+    obj = 2*x1 + x2
+    cond = [ -x1 + x2 .>=. 2
+           ,  x1 + x2 .<=. 1
+           , x1 .>=. 0
+           , x2 .>=. 0
+           ]
+
+test_4_1 :: Bool
+test_4_1 =
+  uncurry maximize example_4_1 ==
+  OptUnsat
+
+example_4_2 :: (Expr Rational, [Atom Rational])
+example_4_2 = (obj, cond)
+  where
+    x1 = var 1
+    x2 = var 2
+    obj = 2*x1 + x2
+    cond = [ - x1 - x2 .<=. 10
+           , 2*x1 - x2 .<=. 40
+           , x1 .>=. 0
+           , x2 .>=. 0
+           ]
+
+test_4_2 :: Bool
+test_4_2 =
+  uncurry maximize example_4_2 ==
+  Unbounded
+
+example_4_3 :: (Expr Rational, [Atom Rational])
+example_4_3 = (obj, cond)
+  where
+    x1 = var 1
+    x2 = var 2
+    obj = 6*x1 - 2*x2
+    cond = [ 2*x1 - x2 .<=. 2
+           , x1 .<=. 4
+           , x1 .>=. 0
+           , x2 .>=. 0
+           ]
+
+test_4_3 :: Bool
+test_4_3 =
+  uncurry maximize example_4_3 ==
+  Optimum (12 % 1) (IM.fromList [(1,4 % 1),(2,6 % 1)])
+
+example_4_5 :: (Expr Rational, [Atom Rational])
+example_4_5 = (obj, cond)
+  where
+    x1 = var 1
+    x2 = var 2
+    obj = 2*x1 + x2
+    cond = [ 4*x1 + 3*x2 .<=. 12
+           , 4*x1 +   x2 .<=. 8
+           , 4*x1 -   x2 .<=. 8
+           , x1 .>=. 0
+           , x2 .>=. 0
+           ]
+
+test_4_5 :: Bool
+test_4_5 =
+  uncurry maximize example_4_5 ==
+  Optimum (5 % 1) (IM.fromList [(1,3 % 2),(2,2 % 1)])
+
+example_4_6 :: (Expr Rational, [Atom Rational])
+example_4_6 = (obj, cond)
+  where
+    x1 = var 1
+    x2 = var 2
+    x3 = var 3
+    x4 = var 4
+    obj = 20*x1 + (1/2)*x2 - 6*x3 + (3/4)*x4
+    cond = [    x1 .<=. 2
+           ,  8*x1 -       x2 + 9*x3 + (1/4)*x4 .<=. 16
+           , 12*x1 - (1/2)*x2 + 3*x3 + (1/2)*x4 .<=. 24
+           , x2 .<=. 1
+           , x1 .>=. 0
+           , x2 .>=. 0
+           , x3 .>=. 0
+           , x4 .>=. 0
+           ]
+
+test_4_6 :: Bool
+test_4_6 =
+  uncurry maximize example_4_6 ==
+  Optimum (165 % 4) (IM.fromList [(1,2 % 1),(2,1 % 1),(3,0 % 1),(4,1 % 1)])
+
+example_4_7 :: (Expr Rational, [Atom Rational])
+example_4_7 = (obj, cond)
+  where
+    x1 = var 1
+    x2 = var 2
+    x3 = var 3
+    x4 = var 4
+    obj = x1 + 1.5*x2 + 5*x3 + 2*x4
+    cond = [ 3*x1 + 2*x2 +   x3 + 4*x4 .<=. 6
+           , 2*x1 +   x2 + 5*x3 +   x4 .<=. 4
+           , 2*x1 + 6*x2 - 4*x3 + 8*x4 .==. 0
+           ,   x1 + 3*x2 - 2*x3 + 4*x4 .==. 0
+           , x1 .>=. 0
+           , x2 .>=. 0
+           , x3 .>=. 0
+           , x4 .>=. 0
+           ]
+
+test_4_7 :: Bool
+test_4_7 =
+  uncurry maximize example_4_7 ==
+  Optimum (48 % 11) (IM.fromList [(1,0 % 1),(2,0 % 1),(3,8 % 11),(4,4 % 11)])
+
+-- 退化して巡回の起こるKuhnの7変数3制約の例
+kuhn_7_3 :: (Expr Rational, [Atom Rational])
+kuhn_7_3 = (obj, cond)
+  where
+    [x1,x2,x3,x4,x5,x6,x7] = map var [1..7]
+    obj = -2*x4-3*x5+x6+12*x7
+    cond = [ x1 - 2*x4 - 9*x5 + x6 + 9*x7 .==. 0
+           , x2 + (1/3)*x4 + x5 - (1/3)*x6 - 2*x7 .==. 0
+           , x3 + 2*x4 + 3*x5 - x6 - 12*x7 .==. 2
+           , x1 .>=. 0
+           , x2 .>=. 0
+           , x3 .>=. 0
+           , x4 .>=. 0
+           , x5 .>=. 0
+           , x6 .>=. 0
+           , x7 .>=. 0
+           ]
+
+test_kuhn_7_3 :: Bool
+test_kuhn_7_3 =
+  uncurry minimize kuhn_7_3 ==
+  Optimum ((-2) % 1) (IM.fromList [(1,2 % 1),(2,0 % 1),(3,0 % 1),(4,2 % 1),(5,0 % 1),(6,2 % 1),(7,0 % 1)])
+
+testAll :: Bool
+testAll = and
+  [ test_3_2
+  , test_3_5
+  , test_4_1
+  , test_4_2
+  , test_4_3
+  , test_4_5
+  , test_4_6
+  , test_4_7
+  , test_kuhn_7_3
+  ]
+
+-- ---------------------------------------------------------------------------
diff --git a/src/MIPSolver2.hs b/src/MIPSolver2.hs
new file mode 100644
--- /dev/null
+++ b/src/MIPSolver2.hs
@@ -0,0 +1,480 @@
+{-# LANGUAGE ScopedTypeVariables, Rank2Types #-}
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  MIPSolver2
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable
+--
+-- Naïve implementation of MIP solver based on Simplex2 module
+-- 
+-- Reference:
+--
+-- * <http://www.math.cuhk.edu.hk/~wei/lpch3.pdf>
+-- 
+-- * Ralph E. Gomory.
+--   \"An Algorithm for the Mixed Integer Problem\", Technical Report
+--   RM-2597, 1960, The Rand Corporation, Santa Monica, CA.
+--   <http://www.rand.org/pubs/research_memoranda/RM2597.html>
+--
+-- * Ralph E. Gomory.
+--   \"Outline of an algorithm for integer solutions to linear programs\".
+--   Bull. Amer. Math. Soc., Vol. 64, No. 5. (1958), pp. 275-278.
+--   <http://projecteuclid.org/euclid.bams/1183522679>
+-- 
+-- * R. C. Daniel and Martyn Jeffreys.
+--   \"Unboundedness in Integer and Discrete Programming L.P. Relaxations\"
+--   The Journal of the Operational Research Society, Vol. 30, No. 12. (1979)
+--   <http://www.jstor.org/stable/3009435>
+-- 
+-----------------------------------------------------------------------------
+module MIPSolver2
+  (
+  -- * The @Solver@ type
+    Solver
+  , newSolver
+
+  -- * Solving
+  , optimize
+
+  -- * Extract results
+  , model
+  , getObjValue
+
+  -- * Configulation
+  , setNThread
+  , setLogger
+  , setShowRational
+  ) where
+
+import Prelude hiding (log)
+
+import Control.Monad
+import Control.Exception
+import Control.Concurrent
+import Control.Concurrent.STM
+import Data.List
+import Data.OptDir
+import Data.Ord
+import Data.IORef
+import Data.Maybe
+import qualified Data.IntSet as IS
+import qualified Data.IntMap as IM
+import qualified Data.Map as Map
+import qualified Data.Sequence as Seq
+import qualified Data.Foldable as F
+import System.CPUTime
+import Text.Printf
+
+import qualified Data.LA as LA
+import Data.Formula ((.<=.), (.>=.), (.==.))
+import qualified Simplex2
+import Simplex2 (OptResult (..), Var, Model)
+import qualified OmegaTest
+import Data.Linear
+import Util (isInteger, fracPart)
+
+data Solver
+  = MIP
+  { mipRootLP :: Simplex2.Solver
+  , mipIVs    :: IS.IntSet
+  , mipBest   :: TVar (Maybe Node)
+
+  , mipNThread :: IORef Int
+  , mipLogger  :: IORef (Maybe (String -> IO ()))
+  , mipShowRational :: IORef Bool
+  }
+
+data Node =
+  Node
+  { ndLP    :: Simplex2.Solver
+  , ndDepth :: {-# UNPACK #-} !Int
+  , ndValue :: Rational
+  }
+
+newSolver :: Simplex2.Solver -> IS.IntSet -> IO Solver
+newSolver lp ivs = do
+  lp2 <- Simplex2.cloneSolver lp
+
+  forM_ (IS.toList ivs) $ \v -> do
+    lb <- Simplex2.getLB lp2 v
+    case lb of
+      Just l | not (isInteger l) ->
+        Simplex2.assertLower lp2 v (fromInteger (ceiling l))
+      _ -> return ()
+    ub <- Simplex2.getUB lp2 v
+    case ub of
+      Just u | not (isInteger u) ->
+        Simplex2.assertLower lp2 v (fromInteger (floor u))
+      _ -> return ()
+
+  bestRef <- newTVarIO Nothing
+
+  nthreadRef <- newIORef 0
+  logRef  <- newIORef Nothing
+  showRef <- newIORef False
+
+  return $
+    MIP
+    { mipRootLP = lp2
+    , mipIVs    = ivs
+    , mipBest   = bestRef
+
+    , mipNThread = nthreadRef
+    , mipLogger = logRef
+    , mipShowRational = showRef
+    }
+
+optimize :: Solver -> (Model -> Rational -> IO ()) -> IO OptResult
+optimize solver update = do
+  let lp = mipRootLP solver
+  log solver "MIP: Solving LP relaxation..."
+  ret <- Simplex2.check lp
+  if not ret
+  then return Unsat
+  else do
+    s0 <- showValue solver =<< Simplex2.getObjValue lp
+    log solver (printf "MIP: LP relaxation is satisfiable with obj = %s" s0)
+    log solver "MIP: Optimizing LP relaxation"
+    ret2 <- Simplex2.optimize lp Simplex2.defaultOptions
+    case ret2 of
+      Unsat -> error "should not happen"
+      Unbounded -> do
+        log solver "MIP: LP relaxation is unbounded"
+        let ivs = mipIVs solver
+        if IS.null ivs
+          then return Unbounded
+          else do
+            {-
+              Fallback to Fourier-Motzkin + OmegaTest
+              * In general, original problem may have optimal
+                solution even though LP relaxiation is unbounded.
+              * But if restricted to rational numbers, the
+                original problem is unbounded or unsatisfiable
+                when LP relaxation is unbounded.
+            -}
+            log solver "MIP: falling back to Fourier-Motzkin + OmegaTest"
+            t <- Simplex2.getTableau lp
+            let ds = [LA.var v .==. def | (v, def) <- IM.toList t]
+            n <- Simplex2.nVars lp
+            bs <- liftM concat $ forM [0..n-1] $ \v -> do
+              lb <- Simplex2.getLB lp v
+              ub <- Simplex2.getUB lp v
+              return $ [LA.var v .>=. LA.constant (fromJust lb) | isJust lb] ++
+                       [LA.var v .<=. LA.constant (fromJust ub) | isJust ub]
+            case OmegaTest.solveQFLA (bs ++ ds) ivs of
+              Just _ -> return Unbounded
+              Nothing -> return Unsat  
+      Optimum -> do
+        s0 <- showValue solver =<< Simplex2.getObjValue lp
+        log solver $ "MIP: LP relaxation optimum is " ++ s0
+        log solver "MIP: Integer optimization begins..."
+        Simplex2.clearLogger lp
+        branchAndBound solver update
+        m <- readTVarIO (mipBest solver)
+        case m of
+          Nothing -> return Unsat
+          Just _ -> return Optimum
+
+branchAndBound :: Solver -> (Model -> Rational -> IO ()) -> IO ()
+branchAndBound solver update = do
+  dir <- Simplex2.getOptDir (mipRootLP solver)
+  rootVal <- Simplex2.getObjValue (mipRootLP solver)
+  let root = Node{ ndLP = mipRootLP solver, ndDepth = 0, ndValue = rootVal }
+
+  pool <- newTVarIO (Seq.singleton root)
+  activeThreads <- newTVarIO (Map.empty)
+  visitedNodes <- newTVarIO 0
+
+  let addNode :: Node -> STM ()
+      addNode nd = do
+        modifyTVar pool (Seq.|> nd)
+
+      pickNode :: IO (Maybe Node)
+      pickNode = do
+        self <- myThreadId
+        atomically $ modifyTVar activeThreads (Map.delete self)
+        atomically $ do
+          s <- readTVar pool
+          case Seq.viewl s of
+            nd Seq.:< s2 -> do
+              writeTVar pool s2
+              modifyTVar activeThreads (Map.insert self nd)
+              return (Just nd)
+            Seq.EmptyL -> do
+              ths <- readTVar activeThreads
+              if Map.null ths
+                then return Nothing
+                else retry
+
+      updateBest :: Node -> IO ()
+      updateBest node = do
+        let lp = ndLP node
+        m <- Simplex2.model lp
+        ret <- atomically $ do
+          old <- readTVar (mipBest solver)
+          case old of
+            Nothing -> do
+              writeTVar (mipBest solver) (Just node)
+              return True
+            Just best -> do
+              let isBetter = if dir==OptMin then ndValue node < ndValue best else ndValue node > ndValue best
+              when isBetter $ writeTVar (mipBest solver) (Just node)
+              return isBetter
+        when ret $ update m (ndValue node) -- 複数スレッドからupdateが同時に呼ばれてまずい可能性がある
+
+      processNode :: Node -> IO ()
+      processNode node = do
+        let lp = ndLP node
+        lim <- liftM (fmap ndValue) $ readTVarIO (mipBest solver)
+        ret <- Simplex2.dualSimplex lp Simplex2.defaultOptions{ Simplex2.objLimit = lim }
+
+        case ret of
+          Unbounded -> error "should not happen"
+          Unsat ->  return ()
+          ObjLimit -> return ()
+          Optimum -> do
+            val <- Simplex2.getObjValue lp
+            p <- prune solver val
+            unless p $ do
+              xs <- violated node (mipIVs solver)
+              case xs of
+                [] -> updateBest (node { ndValue = val })
+                _ -> do
+                  r <- if ndDepth node `mod` 100 /= 0
+                       then return Nothing
+                       else liftM listToMaybe $ filterM (canDeriveGomoryCut lp) $ map fst xs
+                  case r of
+                    Nothing -> do -- branch
+                      let (v0,val0) = fst $ maximumBy (comparing snd)
+                                      [((v,val), abs (fromInteger (round val) - val)) | (v,val) <- xs]
+                      let lp1 = lp
+                      lp2 <- Simplex2.cloneSolver lp
+                      Simplex2.assertAtom lp1 (LA.var v0 .<=. LA.constant (fromInteger (floor val0)))
+                      Simplex2.assertAtom lp2 (LA.var v0 .>=. LA.constant (fromInteger (ceiling val0)))
+                      atomically $ do
+                        addNode $ Node lp1 (ndDepth node + 1) val
+                        addNode $ Node lp2 (ndDepth node + 1) val
+                        modifyTVar visitedNodes (+1)
+                    Just v -> do -- cut
+                      atom <- deriveGomoryCut lp (mipIVs solver) v
+                      Simplex2.assertAtom lp atom
+                      atomically $ do
+                        addNode $ Node lp (ndDepth node + 1) val
+
+  let isCompleted = do
+        nodes <- readTVar pool
+        threads <- readTVar activeThreads
+        return $ Seq.null nodes && Map.null threads
+
+  -- fork worker threads
+  nthreads <- do
+    n <- readIORef (mipNThread solver)
+    if n >= 1
+      then return n
+      else return 1 -- getNumCapabilities -- base-4.4.0.0以降にしか存在しない
+
+  let child = do
+        m <- pickNode
+        case m of
+          Nothing -> return ()
+          Just node -> processNode node >> child
+
+  log solver $ printf "MIP: forking %d worker threads..." nthreads
+  start <- getCPUTime
+  ex <- newEmptyTMVarIO
+  threads <- replicateM nthreads $ do
+    mask $ \restore -> forkIO $ do
+      ret <- try (restore child)
+      case ret of
+        Left e -> atomically (putTMVar ex e)
+        Right _ -> return ()
+
+  th <- forkIO $ do
+    let loop = do
+          (nodes, visited::Int) <- atomically $ do
+            nodes   <- readTVar pool
+            athreads <- readTVar activeThreads
+            visited <- readTVar visitedNodes
+            return (Seq.fromList (Map.elems athreads) Seq.>< nodes, visited)
+          if Seq.null nodes
+            then return ()
+            else do
+              now <- getCPUTime
+              let spent = (now - start) `div` 10^(12::Int)
+
+              let vs = map ndValue (F.toList nodes)
+                  dualBound =
+                    case dir of
+                      OptMin -> minimum vs
+                      OptMax -> maximum vs
+
+              primalBound <- do
+                x <- readTVarIO (mipBest solver)
+                return $ case x of
+                  Nothing -> Nothing
+                  Just node -> Just (ndValue node)
+
+              (p,g) <- case primalBound of
+                     Nothing -> return ("not yet found", "--")
+                     Just val -> do
+                       p <- showValue solver val
+                       let g = if val == 0
+                               then "inf"
+                               else printf "%.2f%%" (fromRational (abs (dualBound - val) * 100 / abs val) :: Double)
+                       return (p, g)
+              d <- showValue solver dualBound
+ 
+              let range =
+                    case dir of
+                      OptMin -> p ++ " >= " ++ d
+                      OptMax -> p ++ " <= " ++ d
+
+              log solver $ printf "time = %d sec; active nodes = %d; visited nodes = %d; %s; gap = %s" spent (Seq.length nodes) visited range g
+              threadDelay (2*1000*1000) -- 2s
+              loop
+    loop
+
+  -- join
+  let wait = isCompleted >>= guard >> return Nothing
+  let loop :: (forall a. IO a -> IO a) -> IO ()
+      loop restore = do
+        ret <- try $ restore $ atomically $ wait `orElse` (liftM Just (readTMVar ex))
+        case ret of
+          Right Nothing  -> return ()
+          Right (Just (e::SomeException)) -> do
+            mapM_ (\t -> throwTo t e) (th:threads)
+            throwIO e
+          Left (e::SomeException) -> do
+            mapM_ (\t -> throwTo t e) (th:threads)
+            throwIO e
+  mask loop
+
+model :: Solver -> IO Model
+model solver = do
+  m <- readTVarIO (mipBest solver)
+  case m of
+    Nothing -> error "no model"
+    Just node -> Simplex2.model (ndLP node)
+
+getObjValue :: Solver -> IO Rational
+getObjValue solver = do
+  m <- readTVarIO (mipBest solver)
+  case m of
+    Nothing -> error "no model"
+    Just node -> return $ ndValue node
+
+violated :: Node -> IS.IntSet -> IO [(Var, Rational)]
+violated node ivs = do
+  m <- Simplex2.model (ndLP node)
+  let p (v,val) = v `IS.member` ivs && not (isInteger val)
+  return $ filter p (IM.toList m)
+
+prune :: Solver -> Rational -> IO Bool
+prune solver lb = do
+  b <- readTVarIO (mipBest solver)
+  case b of
+    Nothing -> return False
+    Just node -> do
+      dir <- Simplex2.getOptDir (mipRootLP solver)
+      return $ if dir==OptMin then ndValue node <= lb else ndValue node >= lb
+
+showValue :: Solver -> Rational -> IO String
+showValue solver v = do
+  printRat <- readIORef (mipShowRational solver)
+  return $ Simplex2.showValue printRat v
+
+setShowRational :: Solver -> Bool -> IO ()
+setShowRational solver = writeIORef (mipShowRational solver)
+
+setNThread :: Solver -> Int -> IO ()
+setNThread solver = writeIORef (mipNThread solver)
+
+{--------------------------------------------------------------------
+  Logging
+--------------------------------------------------------------------}
+
+-- | set callback function for receiving messages.
+setLogger :: Solver -> (String -> IO ()) -> IO ()
+setLogger solver logger = do
+  writeIORef (mipLogger solver) (Just logger)
+
+log :: Solver -> String -> IO ()
+log solver msg = logIO solver (return msg)
+
+logIO :: Solver -> IO String -> IO ()
+logIO solver action = do
+  m <- readIORef (mipLogger solver)
+  case m of
+    Nothing -> return ()
+    Just logger -> action >>= logger
+
+{--------------------------------------------------------------------
+  GomoryCut
+--------------------------------------------------------------------}
+
+deriveGomoryCut :: Simplex2.Solver -> IS.IntSet -> Var -> IO (LA.Atom Rational)
+deriveGomoryCut lp ivs xi = do
+  v0 <- Simplex2.getValue lp xi
+  let f0 = fracPart v0
+  assert (0 < f0 && f0 < 1) $ return ()
+
+  row <- Simplex2.getRow lp xi
+
+  -- remove fixed variables
+  let p (_,xj) = do
+        lb <- Simplex2.getLB lp xj
+        ub <- Simplex2.getUB lp xj
+        case (lb,ub) of
+          (Just l, Just u) -> return (l < u)
+          _ -> return True
+  ns <- filterM p $ LA.terms row
+
+  js <- flip filterM ns $ \(_, xj) -> do
+    vj <- Simplex2.getValue lp xj
+    lb <- Simplex2.getLB lp xj
+    return $ Just vj == lb
+  ks <- flip filterM ns $ \(_, xj) -> do
+    vj <- Simplex2.getValue lp xj
+    ub <- Simplex2.getUB lp xj
+    return $ Just vj == ub
+
+  xs1 <- forM js $ \(aij, xj) -> do
+    let fj = fracPart aij
+    Just lj <- Simplex2.getLB lp xj
+    let c = if xj `IS.member` ivs
+            then (if fj <= 1 - f0 then fj  / (1 - f0) else ((1 - fj) / f0))
+            else (if aij > 0      then aij / (1 - f0) else (-aij     / f0))
+    return $ c .*. (LA.var xj .-. LA.constant lj)
+  xs2 <- forM ks $ \(aij, xj) -> do
+    let fj = fracPart aij
+    Just uj <- Simplex2.getUB lp xj
+    let c = if xj `IS.member` ivs
+            then (if fj <= f0 then fj  / f0 else ((1 - fj) / (1 - f0)))
+            else (if aij > 0  then aij / f0 else (-aij     / (1 - f0)))
+    return $ c .*. (LA.constant uj .-. LA.var xj)
+
+  return $ lsum xs1 .+. lsum xs2 .>=. LA.constant 1
+
+-- TODO: Simplex2をδに対応させたら、xi, xj がδを含まない有理数であるという条件も必要
+canDeriveGomoryCut :: Simplex2.Solver -> Var -> IO Bool
+canDeriveGomoryCut lp xi = do
+  b <- Simplex2.isBasicVariable lp xi
+  if not b
+    then return False
+    else do
+      val <- Simplex2.getValue lp xi
+      if isInteger val
+        then return False
+        else do
+          row <- Simplex2.getRow lp xi
+          ys <- forM (LA.terms row) $ \(_,xj) -> do
+            vj <- Simplex2.getValue lp xj
+            lb <- Simplex2.getLB lp xj
+            ub <- Simplex2.getUB lp xj
+            return $ Just vj == lb || Just vj == ub
+          return (and ys)
diff --git a/src/MIPSolverHL.hs b/src/MIPSolverHL.hs
new file mode 100644
--- /dev/null
+++ b/src/MIPSolverHL.hs
@@ -0,0 +1,300 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  MIPSolverHL
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+--
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (ScopedTypeVariables)
+--
+-- References:
+-- 
+-- * [Gomory1960]
+--   Ralph E. Gomory.
+--   An Algorithm for the Mixed Integer Problem, Technical Report
+--   RM-2597, 1960, The Rand Corporation, Santa Monica, CA.
+--   <http://www.rand.org/pubs/research_memoranda/RM2597.html>
+--
+-- * [Gomory1958]
+--   Ralph E. Gomory.
+--   Outline of an algorithm for integer solutions to linear programs.
+--   Bull. Amer. Math. Soc., Vol. 64, No. 5. (1958), pp. 275-278.
+--   <http://projecteuclid.org/euclid.bams/1183522679>
+-----------------------------------------------------------------------------
+
+module MIPSolverHL
+  ( module Data.Expr
+  , module Data.Formula
+  , module Data.OptDir
+  , minimize
+  , maximize
+  , optimize
+--  , solve
+  ) where
+
+import Control.Exception
+import Control.Monad.State
+import Data.Ord
+import Data.Maybe
+import Data.List (maximumBy)
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+import Data.Ratio
+import Data.OptDir
+
+import Data.Expr
+import Data.Formula
+import Data.Linear
+import qualified Data.LA as LA
+import qualified Simplex
+import Util (isInteger, fracPart)
+import LPSolver
+import qualified OmegaTest
+
+-- ---------------------------------------------------------------------------
+
+maximize :: RealFrac r => Expr r -> [Atom r] -> VarSet -> OptResult r
+maximize = optimize OptMax
+
+minimize :: RealFrac r => Expr r -> [Atom r] -> VarSet -> OptResult r
+minimize = optimize OptMin
+
+optimize :: RealFrac r => OptDir -> Expr r -> [Atom r] -> VarSet -> OptResult r
+optimize optdir obj2 cs2 ivs = fromMaybe OptUnknown $ do
+  obj <- LA.compileExpr obj2  
+  cs <- mapM LA.compileAtom cs2
+  return (optimize' optdir obj cs ivs)
+
+{-
+solve :: RealFrac r => [Atom r] -> VarSet -> SatResult r
+solve cs2 ivs = fromMaybe Unknown $ do
+  cs <- mapM compileAtom cs2
+  return (solve' cs ivs)
+-}
+
+-- ---------------------------------------------------------------------------
+
+data Node r
+  = Node
+  { ndSolver :: LPSolver.Solver r
+  , ndDepth  :: {-# UNPACK #-} !Int
+--  , ndCutSlackVariables :: VarSet
+  }
+
+ndTableau :: Node r  -> Simplex.Tableau r
+ndTableau node = evalState getTableau (ndSolver node)
+
+ndLowerBound :: (Num r, Eq r) => Node r -> r
+ndLowerBound node = evalState (liftM Simplex.currentObjValue getTableau) (ndSolver node)
+
+data Err = ErrUnbounded | ErrUnsat deriving (Ord, Eq, Show, Enum, Bounded)
+
+optimize' :: RealFrac r => OptDir -> LA.Expr r -> [LA.Atom r] -> VarSet -> OptResult r
+optimize' optdir obj cs ivs = 
+  case mkInitialNode optdir obj cs ivs of
+    Left err ->
+      case err of
+        ErrUnsat -> OptUnsat
+        ErrUnbounded ->
+          if IS.null ivs
+          then Unbounded
+          else
+            {-
+               Fallback to Fourier-Motzkin + OmegaTest
+               * In general, original problem may have optimal
+                 solution even though LP relaxiation is unbounded.
+               * But if restricted to rational numbers, the
+                 original problem is unbounded or unsatisfiable
+                 when LP relaxation is unbounded.
+            -}
+            case OmegaTest.solveQFLA (map conv cs) ivs of
+              Nothing -> OptUnsat
+              Just _ -> Unbounded        
+    Right (node0, ivs2) -> 
+      case traverse optdir obj ivs2 node0 of
+        Left ErrUnbounded -> error "shoud not happen"
+        Left ErrUnsat -> OptUnsat
+        Right node -> flip evalState (ndSolver node) $ do
+          tbl <- getTableau
+          model <- getModel vs
+          return $ Optimum (Simplex.currentObjValue tbl) model
+  where
+    vs = vars cs `IS.union` vars obj
+
+tableau' :: (RealFrac r) => [LA.Atom r] -> VarSet -> LP r VarSet
+tableau' cs ivs = do
+  let (nonnegVars, cs') = collectNonnegVars cs ivs
+      fvs = vars cs `IS.difference` nonnegVars
+  ivs2 <- liftM IS.unions $ forM (IS.toList fvs) $ \v -> do
+    v1 <- gensym
+    v2 <- gensym
+    define v (LA.var v1 .-. LA.var v2)
+    return $ if v `IS.member` ivs then IS.fromList [v1,v2] else IS.empty
+  mapM_ addConstraint cs'
+  return ivs2
+
+conv :: RealFrac r => LA.Atom r -> LA.Atom Rational
+conv (LA.Atom a op b) = LA.Atom (f a) op (f b)
+  where
+    f = LA.mapCoeff toRational
+
+mkInitialNode :: RealFrac r => OptDir -> LA.Expr r -> [LA.Atom r] -> VarSet -> Either Err (Node r, VarSet)
+mkInitialNode optdir obj cs ivs =
+  flip evalState (emptySolver vs) $ do
+    ivs2 <- tableau' cs ivs
+    ret <- phaseI
+    if not ret
+      then return (Left ErrUnsat)
+      else do
+        ret2 <- simplex optdir obj
+        if ret2
+          then do
+            solver <- get
+            return $ Right $
+              ( Node{ ndSolver = solver
+                    , ndDepth = 0
+--                    , ndCutSlackVariables = IS.empty
+                    }
+              , ivs `IS.union` ivs2
+              )
+          else return (Left ErrUnbounded)
+  where
+    vs = vars cs `IS.union` vars obj
+
+isStrictlyBetter :: RealFrac r => OptDir -> r -> r -> Bool
+isStrictlyBetter optdir = if optdir==OptMin then (<) else (>)
+
+traverse :: forall r. RealFrac r => OptDir -> LA.Expr r -> VarSet -> Node r -> Either Err (Node r)
+traverse optdir obj ivs node0 = loop [node0] Nothing
+  where
+    loop :: [Node r] -> Maybe (Node r) -> Either Err (Node r)
+    loop [] (Just best) = Right best
+    loop [] Nothing = Left ErrUnsat
+    loop (n:ns) Nothing =
+      case children n of
+        Nothing -> loop ns (Just n)
+        Just cs -> loop (cs++ns) Nothing
+    loop (n:ns) (Just best)
+      | isStrictlyBetter optdir (ndLowerBound n) (ndLowerBound best) =
+          case children n of
+            Nothing -> loop ns (Just n)
+            Just cs -> loop (cs++ns) (Just best)
+      | otherwise = loop ns (Just best)
+
+    reopt :: Solver r -> Maybe (Solver r)
+    reopt s = flip evalState s $ do
+      ret <- dualSimplex optdir obj
+      if ret
+        then liftM Just get
+        else return Nothing
+
+    children :: Node r -> Maybe [Node r]
+    children node
+      | null xs = Nothing -- no violation
+      | ndDepth node `mod` 100 == 0 = -- cut
+          let
+            (f0, m0) = maximumBy (comparing fst) [(fracPart val, m) | (_,m,val) <- xs]
+            sv = flip execState (ndSolver node) $ do
+                   s <- gensym
+                   let g j x = assert (a >= 0) a
+                         where
+                           a | j `IS.member` ivs =
+                                if fracPart x <= f0
+                                then fracPart x
+                                else (f0 / (f0 - 1)) * (fracPart x - 1)
+                                     -- [Gomory1960] では (f0 / (1 - f0)) * (fracPart x - 1) としているが、
+                                     -- これは誤り
+                             | otherwise =
+                                if x >= 0
+                                then x
+                                else (f0 / (f0 - 1)) * x
+                   putTableau $ IM.insert s (IM.mapWithKey (\j x -> negate (g j x)) m0, negate f0) tbl
+          in Just $ [node{ ndSolver = sv2, ndDepth = ndDepth node + 1 } | sv2 <- maybeToList (reopt sv)]
+      | otherwise = -- branch
+          let (v0, val0) = snd $ maximumBy (comparing fst) [(fracPart val, (v, val)) | (v,_,val) <- xs]
+              cs = [ LA.Atom (LA.var v0) Ge (LA.constant (fromIntegral (ceiling val0 :: Integer)))
+                   , LA.Atom (LA.var v0) Le (LA.constant (fromIntegral (floor val0 :: Integer)))
+                   ]
+              svs = [execState (addConstraint2 c) (ndSolver node) | c <- cs]
+          in Just $ [node{ ndSolver = sv, ndDepth = ndDepth node + 1 } | Just sv <- map reopt svs]
+        
+      where
+        tbl :: Simplex.Tableau r
+        tbl = ndTableau node
+
+        xs :: [(Var, VarMap r, r)]
+        xs = [ (v, m, val)
+             | v <- IS.toList ivs
+             , Just (m, val) <- return (IM.lookup v tbl)
+             , not (isInteger val)
+             ]
+
+-- ---------------------------------------------------------------------------
+
+example1 = (optdir, obj, cs, ivs)
+  where
+    optdir = OptMax
+    x1 = LA.var 1
+    x2 = LA.var 2
+    x3 = LA.var 3
+    x4 = LA.var 4
+    obj = x1 .+. 2 .*. x2 .+. 3 .*. x3 .+. x4
+    cs =
+      [ LA.Atom ((-1) .*. x1 .+. x2 .+. x3 .+. 10.*.x4) Le (LA.constant 20)
+      , LA.Atom (x1 .-. 3 .*. x2 .+. x3) Le (LA.constant 30)
+      , LA.Atom (x2 .-. 3.5 .*. x4) Eql (LA.constant 0)
+      , LA.Atom (LA.constant 0) Le x1
+      , LA.Atom x1 Le (LA.constant 40)
+      , LA.Atom (LA.constant 0) Le x2
+      , LA.Atom (LA.constant 0) Le x3
+      , LA.Atom (LA.constant 2) Le x4
+      , LA.Atom x4 Le (LA.constant 3)
+      ]
+    ivs = IS.singleton 4
+
+test1 :: Bool
+test1 = result==expected
+  where
+    (optdir, obj, cs, ivs) = example1
+    result, expected :: OptResult Rational
+    result = optimize' optdir obj cs ivs
+    expected = Optimum (245 % 2) (IM.fromList [(1,40 % 1),(2,21 % 2),(3,39 % 2),(4,3 % 1)])
+
+test1' :: Bool
+test1' = result==expected
+  where
+    (optdir, obj, cs, ivs) = example1
+    f OptMin = OptMax
+    f OptMax = OptMin
+    result, expected :: OptResult Rational
+    result = optimize' (f optdir) (lnegate obj) cs ivs
+    expected = Optimum (-245 % 2) (IM.fromList [(1,40 % 1),(2,21 % 2),(3,39 % 2),(4,3 % 1)])
+
+-- 『数理計画法の基礎』(坂和 正敏) p.109 例 3.8
+example2 = (optdir, obj, cs, ivs)
+  where
+    optdir = OptMin
+    [x1,x2,x3] = map LA.var [1..3]
+    obj = (-1) .*. x1 .-. 3 .*. x2 .-. 5 .*. x3
+    cs =
+      [ LA.Atom (3 .*. x1 .+. 4 .*. x2) Le (LA.constant 10)
+      , LA.Atom (2 .*. x1 .+. x2 .+. x3) Le (LA.constant 7)
+      , LA.Atom (3.*.x1 .+. x2 .+. 4 .*. x3) Eql (LA.constant 12)
+      , LA.Atom (LA.constant 0) Le x1
+      , LA.Atom (LA.constant 0) Le x2
+      , LA.Atom (LA.constant 0) Le x3
+      ]
+    ivs = IS.fromList [1,2]
+
+test2 :: Bool
+test2 = result == expected
+  where
+    result, expected :: OptResult Rational
+    result = optimize' optdir obj cs ivs
+    expected = Optimum ((-37) % 2) (IM.fromList [(1,0 % 1),(2,2 % 1),(3,5 % 2)])
+    (optdir, obj, cs, ivs) = example2
+
+-- ---------------------------------------------------------------------------
diff --git a/src/OmegaTest.hs b/src/OmegaTest.hs
new file mode 100644
--- /dev/null
+++ b/src/OmegaTest.hs
@@ -0,0 +1,310 @@
+{-# OPTIONS_GHC -Wall #-}
+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  OmegaTest
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (MultiParamTypeClasses, FunctionalDependencies)
+--
+-- (incomplete) implementation of Omega Test
+--
+-- References:
+--
+-- * William Pugh. The Omega test: a fast and practical integer
+--   programming algorithm for dependence analysis. In Proceedings of
+--   the 1991 ACM/IEEE conference on Supercomputing (1991), pp. 4-13.
+--
+-- * <http://users.cecs.anu.edu.au/~michaeln/pubs/arithmetic-dps.pdf>
+--
+-- See also:
+--
+-- * <http://hackage.haskell.org/package/Omega>
+--
+-----------------------------------------------------------------------------
+module OmegaTest
+    ( module Data.Expr
+    , module Data.Formula
+    , Lit (..)
+    , eliminateQuantifiers
+    , solve
+    , solveQFLA
+    ) where
+
+import Control.Monad
+import Data.List
+import Data.Maybe
+import Data.Ratio
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+
+import Data.Expr
+import Data.Formula
+import Data.Linear
+import qualified Data.LA as LA
+import qualified Data.Interval as Interval
+import Util (combineMaybe)
+import qualified FourierMotzkin as FM
+import FourierMotzkin (Lit (..), Rat (..))
+
+-- ---------------------------------------------------------------------------
+
+type ExprZ = LA.Expr Integer
+
+-- 制約集合の単純化
+-- It returns Nothing when a inconsistency is detected.
+simplify :: [Lit] -> Maybe [Lit]
+simplify = fmap concat . mapM f
+  where
+    f :: Lit -> Maybe [Lit]
+    f lit@(Pos e) =
+      case LA.asConst e of
+        Just x -> guard (x > 0) >> return []
+        Nothing -> return [lit]
+    f lit@(Nonneg e) =
+      case LA.asConst e of
+        Just x -> guard (x >= 0) >> return []
+        Nothing -> return [lit]
+
+-- ---------------------------------------------------------------------------
+
+atomZ :: RelOp -> Expr Rational -> Expr Rational -> Maybe (DNF Lit)
+atomZ op a b = do
+  (e1,c1) <- FM.termR a
+  (e2,c2) <- FM.termR b
+  let a' = c2 .*. e1
+      b' = c1 .*. e2
+  return $ case op of
+    Le -> DNF [[a' `leZ` b']]
+    Lt -> DNF [[a' `ltZ` b']]
+    Ge -> DNF [[a' `geZ` b']]
+    Gt -> DNF [[a' `gtZ` b']]
+    Eql -> eqZ a' b'
+    NEq -> DNF [[a' `ltZ` b'], [a' `gtZ` b']]
+
+leZ, ltZ, geZ, gtZ :: ExprZ -> ExprZ -> Lit
+-- Note that constants may be floored by division
+leZ e1 e2 = Nonneg (LA.mapCoeff (`div` d) e)
+  where
+    e = e2 .-. e1
+    d = abs $ gcd' [c | (c,v) <- LA.terms e, v /= LA.unitVar]
+ltZ e1 e2 = (e1 .+. LA.constant 1) `leZ` e2
+geZ = flip leZ
+gtZ = flip gtZ
+
+eqZ :: ExprZ -> ExprZ -> (DNF Lit)
+eqZ e1 e2
+  = if LA.coeff LA.unitVar e3 `mod` d == 0
+    then DNF [[Nonneg e, Nonneg (lnegate e)]]
+    else false
+  where
+    e = LA.mapCoeff (`div` d) e3
+    e3 = e1 .-. e2
+    d = abs $ gcd' [c | (c,v) <- LA.terms e3, v /= LA.unitVar]
+
+-- ---------------------------------------------------------------------------
+
+{-
+(ls,us) represents
+{ x | ∀(M,c)∈ls. M/c≤x, ∀(M,c)∈us. x≤M/c }
+-}
+type BoundsZ = ([Rat],[Rat])
+
+eliminate :: Var -> [Lit] -> DNF Lit
+eliminate v xs = DNF [rest] .&&. boundConditionsZ bnd
+   where
+     (bnd,rest) = collectBoundsZ v xs
+
+collectBoundsZ :: Var -> [Lit] -> (BoundsZ,[Lit])
+collectBoundsZ v = foldr phi (([],[]),[])
+  where
+    phi :: Lit -> (BoundsZ,[Lit]) -> (BoundsZ,[Lit])
+    phi (Pos t) x = phi (Nonneg (t .-. LA.constant 1)) x
+    phi lit@(Nonneg t) ((ls,us),xs) =
+      case LA.extract v t of
+        (c,t') -> 
+          case c `compare` 0 of
+            EQ -> ((ls, us), lit : xs)
+            GT -> (((lnegate t', c) : ls, us), xs) -- 0 ≤ cx + M ⇔ -M/c ≤ x
+            LT -> ((ls, (t', negate c) : us), xs)   -- 0 ≤ cx + M ⇔ x ≤ M/-c
+
+boundConditionsZ :: BoundsZ -> DNF Lit
+boundConditionsZ (ls,us) = DNF $ catMaybes $ map simplify $
+  if isExact (ls,us)
+    then [cond1]
+    else cond1 : cond2
+  where
+     cond1 =
+       [ LA.constant ((a-1)*(b-1)) `leZ` (a .*. d .-. b .*. c)
+       | (c,a)<-ls , (d,b)<-us ]
+     cond2 = 
+       [ [(a' .*. c) `leZ` (a .*. val) | (c,a)<-ls] ++
+         [(b .*. val) `geZ` (a' .*. d) | (d,b)<-us]
+       | not (null us)
+       , let m = maximum [b | (_,b)<-us]
+       ,  (c',a') <- ls
+       , k <- [0 .. (m*a'-a'-m) `div` m]
+       , let val = c' .+. LA.constant k
+       -- x = val / a'
+       -- c / a ≤ x ⇔ c / a ≤ val / a' ⇔ a' c ≤ a val
+       -- x ≤ d / b ⇔ val / a' ≤ d / b ⇔ b val ≤ a' d
+       ]
+
+isExact :: BoundsZ -> Bool
+isExact (ls,us) = and [a==1 || b==1 | (c,a)<-ls , (d,b)<-us]
+
+eliminateQuantifiers :: Formula Rational -> Maybe (DNF Lit)
+eliminateQuantifiers = f
+  where
+    f T = return true
+    f F = return false
+    f (Atom (Rel a op b)) = atomZ op a b
+    f (And a b) = liftM2 (.&&.) (f a) (f b)
+    f (Or a b) = liftM2 (.||.) (f a) (f b)
+    f (Not a) = f (pushNot a)
+    f (Imply a b) = f (Or (Not a) b)
+    f (Equiv a b) = f (And (Imply a b) (Imply b a))
+    f (Forall v a) = do
+      dnf <- f (Exists v (pushNot a))
+      return $ notB dnf
+    f (Exists v a) = do
+      dnf <- f a
+      return $ orB [eliminate v xs | xs <- unDNF dnf]
+
+solve :: Formula Rational -> SatResult Integer
+solve formula =
+  case eliminateQuantifiers formula of
+    Nothing -> Unknown
+    Just dnf ->
+      case msum [solve' vs xs | xs <- unDNF dnf] of
+        Nothing -> Unsat
+        Just m -> Sat m
+  where
+    vs = IS.toList (vars formula)
+
+solve' :: [Var] -> [Lit] -> Maybe (Model Integer)
+solve' vs xs = simplify xs >>= go vs
+  where
+    go :: [Var] -> [Lit] -> Maybe (Model Integer)
+    go [] [] = return IM.empty
+    go [] _ = mzero
+    go vs ys = msum (map f (unDNF (boundConditionsZ bnd)))
+      where
+        (v,vs',bnd,rest) = chooseVariable vs ys
+        f zs = do
+          model <- go vs' (zs ++ rest)
+          val <- pickupZ (evalBoundsZ model bnd)
+          return $ IM.insert v val model
+
+chooseVariable :: [Var] -> [Lit] -> (Var, [Var], BoundsZ, [Lit])
+chooseVariable vs xs = head $ [e | e@(_,_,bnd,_) <- table, isExact bnd] ++ table
+  where
+    table = [ (v, vs', bnd, rest)
+            | (v,vs') <- pickup vs, let (bnd, rest) = collectBoundsZ v xs
+            ]
+
+evalBoundsZ :: Model Integer -> BoundsZ -> IntervalZ
+evalBoundsZ model (ls,us) =
+  foldl' intersectZ univZ $ 
+    [ (Just (ceiling (LA.evalExpr model x % c)), Nothing) | (x,c) <- ls ] ++ 
+    [ (Nothing, Just (floor (LA.evalExpr model x % c))) | (x,c) <- us ]
+
+-- ---------------------------------------------------------------------------
+
+type IntervalZ = (Maybe Integer, Maybe Integer)
+
+univZ :: IntervalZ
+univZ = (Nothing, Nothing)
+
+intersectZ :: IntervalZ -> IntervalZ -> IntervalZ
+intersectZ (l1,u1) (l2,u2) = (combineMaybe max l1 l2, combineMaybe min u1 u2)
+
+pickupZ :: IntervalZ -> Maybe Integer
+pickupZ (Nothing,Nothing) = return 0
+pickupZ (Just x, Nothing) = return x
+pickupZ (Nothing, Just x) = return x
+pickupZ (Just x, Just y) = if x <= y then return x else mzero 
+
+-- ---------------------------------------------------------------------------
+
+solveQFLA :: [LA.Atom Rational] -> VarSet -> Maybe (Model Rational)
+solveQFLA cs ivs = msum [ FM.simplify xs >>= go (IS.toList rvs) | xs <- unDNF dnf ]
+  where
+    vs  = vars cs
+    rvs = vs `IS.difference` ivs
+    dnf = FM.constraintsToDNF cs
+
+    go :: [Var] -> [Lit] -> Maybe (Model Rational)
+    go [] xs = fmap (fmap fromIntegral) $ solve' (IS.toList ivs) xs
+    go (v:vs) ys = msum (map f (unDNF (FM.boundConditions bnd)))
+      where
+        (bnd, rest) = FM.collectBounds v ys
+        f zs = do
+          model <- go vs (zs ++ rest)
+          val <- Interval.pickup (FM.evalBounds model bnd)
+          return $ IM.insert v val model
+
+-- ---------------------------------------------------------------------------
+
+gcd' :: [Integer] -> Integer
+gcd' [] = 1
+gcd' xs = foldl1' gcd xs
+
+pickup :: [a] -> [(a,[a])]
+pickup [] = []
+pickup (x:xs) = (x,xs) : [(y,x:ys) | (y,ys) <- pickup xs]
+
+-- ---------------------------------------------------------------------------
+
+{-
+7x + 12y + 31z = 17
+3x + 5y + 14z = 7
+1 ≤ x ≤ 40
+-50 ≤ y ≤ 50
+
+satisfiable in R
+but unsatisfiable in Z
+-}
+test1 :: Formula Rational
+test1 = c1 .&&. c2 .&&. c3 .&&. c4
+  where
+    x = Var 0
+    y = Var 1
+    z = Var 2
+    c1 = 7*x + 12*y + 31*z .==. 17
+    c2 = 3*x + 5*y + 14*z .==. 7
+    c3 = 1 .<=. x .&&. x .<=. 40
+    c4 = (-50) .<=. y .&&. y .<=. 50
+
+test1' :: [LA.Atom Rational]
+test1' = [c1, c2] ++ c3 ++ c4
+  where
+    x = LA.var 0
+    y = LA.var 1
+    z = LA.var 2
+    c1 = 7.*.x .+. 12.*.y .+. 31.*.z .==. LA.constant 17
+    c2 = 3.*.x .+. 5.*.y .+. 14.*.z .==. LA.constant 7
+    c3 = [LA.constant 1 .<=. x, x .<=. LA.constant 40]
+    c4 = [LA.constant (-50) .<=. y, y .<=. LA.constant 50]
+
+{-
+27 ≤ 11x+13y ≤ 45
+-10 ≤ 7x-9y ≤ 4
+
+satisfiable in R
+but unsatisfiable in Z
+-}
+test2 :: Formula Rational
+test2 = c1 .&&. c2
+  where
+    x = Var 0
+    y = Var 1
+    t1 = 11*x + 13*y
+    t2 = 7*x - 9*y
+    c1 = 27 .<=. t1 .&&. t1 .<=. 45
+    c2 = (-10) .<=. t2 .&&. t2 .<=. 4
+
+-- ---------------------------------------------------------------------------
diff --git a/src/SAT.hs b/src/SAT.hs
new file mode 100644
--- /dev/null
+++ b/src/SAT.hs
@@ -0,0 +1,2196 @@
+{-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}
+{-# LANGUAGE BangPatterns, DoAndIfThenElse, DoRec, ScopedTypeVariables, CPP #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  SAT
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (BangPatterns, DoAndIfThenElse, DoRec, ScopedTypeVariables, CPP)
+--
+-- A CDCL SAT solver.
+--
+-- It follows the design of MiniSat and SAT4J.
+--
+-- See also:
+--
+-- * <http://hackage.haskell.org/package/funsat>
+--
+-- * <http://hackage.haskell.org/package/incremental-sat-solver>
+--
+-----------------------------------------------------------------------------
+module SAT
+  (
+  -- * The @Solver@ type
+    Solver
+  , newSolver
+
+  -- * Basic data structures
+  , Var
+  , Lit
+  , literal
+  , litNot
+  , litVar
+  , litPolarity
+  , Clause
+
+  -- * Problem specification
+  , newVar
+  , addClause
+  , addAtLeast
+  , addAtMost
+  , addExactly
+  , addPBAtLeast
+  , addPBAtMost
+  , addPBExactly
+  , addPBAtLeastSoft
+  , addPBAtMostSoft
+  , addPBExactlySoft
+
+  -- * Solving
+  , solve
+  , solveWith
+
+  -- * Extract results
+  , Model
+  , model
+
+  -- * Solver configulation
+  , RestartStrategy (..)
+  , setRestartStrategy
+  , defaultRestartStrategy
+  , setRestartFirst
+  , defaultRestartFirst
+  , setRestartInc
+  , defaultRestartInc
+  , setLearntSizeInc
+  , defaultLearntSizeInc
+  , setCCMin
+  , defaultCCMin
+  , LearningStrategy (..)
+  , setLearningStrategy
+  , defaultLearningStrategy
+  , setVarPolarity
+  , setLogger
+  , setCheckModel
+  , setRandomFreq
+  , defaultRandomFreq
+  , setRandomSeed
+
+  -- * Read state
+  , nVars
+  , nAssigns
+  , nClauses
+  , nLearnt
+
+  -- * Internal API
+  , varBumpActivity
+  , varDecayActivity
+  ) where
+
+import Prelude hiding (log)
+import Control.Monad
+import Control.Exception
+#if MIN_VERSION_array(0,4,0)
+import Data.Array.IO hiding (unsafeFreeze)
+import Data.Array.Unsafe (unsafeFreeze)
+#else
+import Data.Array.IO
+#endif
+import Data.Array.Base (unsafeRead, unsafeWrite)
+import Data.IORef
+import Data.List
+import Data.Maybe
+import Data.Ord
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+import qualified Data.Set as Set
+import qualified Data.IndexedPriorityQueue as PQ
+import qualified Data.SeqQueue as SQ
+import System.CPUTime
+import qualified System.Random as Rand
+import Text.Printf
+
+import Data.LBool
+import SAT.Types
+
+{--------------------------------------------------------------------
+  internal data structures
+--------------------------------------------------------------------}
+
+type Level = Int
+
+levelRoot :: Level
+levelRoot = -1
+
+data Assignment
+  = Assignment
+  { aValue  :: !Bool
+  , aLevel  :: {-# UNPACK #-} !Level
+  , aReason :: !(Maybe SomeConstraint)
+  , aBacktrackCBs :: !(IORef [IO ()])
+  }
+
+data VarData
+  = VarData
+  { vdAssignment :: !(IORef (Maybe Assignment))
+  , vdPolarity   :: !(IORef Bool)
+  , vdPosLitData :: !LitData
+  , vdNegLitData :: !LitData
+  , vdActivity   :: !(IORef VarActivity)
+  }
+
+newtype LitData
+  = LitData
+  { -- | will be invoked when this literal is falsified
+    ldWatches :: IORef [SomeConstraint]
+  }
+
+newVarData :: IO VarData
+newVarData = do
+  ainfo <- newIORef Nothing
+  polarity <- newIORef True
+  pos <- newLitData
+  neg <- newLitData
+  activity <- newIORef 0
+  return $ VarData ainfo polarity pos neg activity
+
+newLitData :: IO LitData
+newLitData = do
+  ws <- newIORef []
+  return $ LitData ws
+
+varData :: Solver -> Var -> IO VarData
+varData s !v = do
+  a <- readIORef (svVarData s)
+  unsafeRead a (v-1)
+
+litData :: Solver -> Lit -> IO LitData
+litData s !l =
+  -- litVar による heap allocation を避けるために、
+  -- litPolarityによる分岐後にvarDataを呼ぶ。
+  if litPolarity l
+    then do
+      vd <- varData s l
+      return $ vdPosLitData vd
+    else do
+      vd <- varData s (negate l)
+      return $ vdNegLitData vd
+
+{-# INLINE varValue #-}
+varValue :: Solver -> Var -> IO LBool
+varValue s !v = do
+  vd <- varData s v
+  m <- readIORef (vdAssignment vd)
+  case m of
+    Nothing -> return lUndef
+    Just x -> return $! (liftBool $! aValue x)
+
+{-# INLINE litValue #-}
+litValue :: Solver -> Lit -> IO LBool
+litValue s !l = do
+  -- litVar による heap allocation を避けるために、
+  -- litPolarityによる分岐後にvarDataを呼ぶ。
+  if litPolarity l
+    then varValue s l
+    else do
+      m <- varValue s (negate l)
+      return $! lnot m
+
+varLevel :: Solver -> Var -> IO Level
+varLevel s !v = do
+  vd <- varData s v
+  m <- readIORef (vdAssignment vd)
+  case m of
+    Nothing -> error ("varLevel: unassigned var " ++ show v)
+    Just a -> return (aLevel a)
+
+litLevel :: Solver -> Lit -> IO Level
+litLevel s l = varLevel s (litVar l)
+
+varReason :: Solver -> Var -> IO (Maybe SomeConstraint)
+varReason s !v = do
+  vd <- varData s v
+  m <- readIORef (vdAssignment vd)
+  case m of
+    Nothing -> error ("varReason: unassigned var " ++ show v)
+    Just a -> return (aReason a)
+
+-- | Solver instance
+data Solver
+  = Solver
+  { svOk           :: !(IORef Bool)
+  , svVarQueue     :: !PQ.PriorityQueue
+  , svTrail        :: !(IORef [Lit])
+  , svVarCounter   :: !(IORef Int)
+  , svVarData      :: !(IORef (IOArray Int VarData))
+  , svClauseDB     :: !(IORef [SomeConstraint])
+  , svLearntDB     :: !(IORef (Int,[SomeConstraint]))
+  , svAssumptions  :: !(IORef (IOUArray Int Lit))
+  , svLevel        :: !(IORef Level)
+  , svBCPQueue     :: !(SQ.SeqQueue Lit)
+  , svModel        :: !(IORef (Maybe Model))
+  , svNDecision    :: !(IORef Int)
+  , svNRandomDecision :: !(IORef Int)
+  , svNConflict    :: !(IORef Int)
+  , svNRestart     :: !(IORef Int)
+  , svNAssigns     :: !(IORef Int)
+
+  -- | Inverse of the variable activity decay factor. (default 1 / 0.95)
+  , svVarDecay     :: !(IORef Double)
+
+  -- | Amount to bump next variable with.
+  , svVarInc       :: !(IORef Double)
+
+  -- | Inverse of the clause activity decay factor. (1 / 0.999)
+  , svClaDecay     :: !(IORef Double)
+
+  -- | Amount to bump next clause with.
+  , svClaInc       :: !(IORef Double)
+
+  , svRestartStrategy :: !(IORef RestartStrategy)
+
+  -- | The initial restart limit. (default 100)
+  , svRestartFirst :: !(IORef Int)
+
+  -- | The factor with which the restart limit is multiplied in each restart. (default 1.5)
+  , svRestartInc :: !(IORef Double)
+
+  -- | The limit for learnt clauses is multiplied with this factor periodically. (default 1.1)
+  , svLearntSizeInc :: !(IORef Double)
+
+  , svLearntLim :: !(IORef Int)
+
+  -- | Controls conflict clause minimization (0=none, 1=local, 2=recursive)
+  , svCCMin :: !(IORef Int)
+
+  , svLearningStrategy :: !(IORef LearningStrategy)
+
+  , svLogger :: !(IORef (Maybe (String -> IO ())))
+
+  , svCheckModel :: !(IORef Bool)
+
+  , svRandomFreq :: !(IORef Double)
+  , svRandomGen  :: !(IORef Rand.StdGen)
+  }
+
+markBad :: Solver -> IO ()
+markBad solver = writeIORef (svOk solver) False
+
+bcpEnqueue :: Solver -> Lit -> IO ()
+bcpEnqueue solver l = SQ.enqueue (svBCPQueue solver) l
+
+bcpDequeue :: Solver -> IO (Maybe Lit)
+bcpDequeue solver = SQ.dequeue (svBCPQueue solver)
+
+assignBy :: Constraint c => Solver -> Lit -> c -> IO Bool
+assignBy solver lit c = assign_ solver lit (Just (toConstraint c))
+
+assign :: Solver -> Lit -> IO Bool
+assign solver lit = assign_ solver lit Nothing
+
+assign_ :: Solver -> Lit -> Maybe SomeConstraint -> IO Bool
+assign_ solver !lit reason = assert (validLit lit) $ do
+  vd <- varData solver (litVar lit)
+  m <- readIORef (vdAssignment vd)
+  case m of
+    Just a -> return $ litPolarity lit == aValue a
+    Nothing -> do
+      lv <- readIORef (svLevel solver)
+      bt <- newIORef []
+
+      writeIORef (vdAssignment vd) $ Just $
+        Assignment
+        { aValue  = litPolarity lit
+        , aLevel  = lv
+        , aReason = reason
+        , aBacktrackCBs = bt
+        }
+
+      modifyIORef (svTrail solver) (lit:)
+      modifyIORef' (svNAssigns solver) (+1)
+      bcpEnqueue solver lit
+
+      when debugMode $ logIO solver $ do
+        let r = case reason of
+                  Nothing -> ""
+                  Just _ -> " by propagation"
+        return $ printf "assign(level=%d): %d%s" lv lit r
+
+      return True
+
+unassign :: Solver -> Var -> IO ()
+unassign solver !v = assert (validVar v) $ do
+  vd <- varData solver v
+  m <- readIORef (vdAssignment vd)
+  case m of
+    Nothing -> error "unassign: should not happen"
+    Just a -> do
+      writeIORef (vdPolarity vd) (aValue a)
+      readIORef (aBacktrackCBs a) >>= sequence_
+  writeIORef (vdAssignment vd) Nothing
+  modifyIORef' (svNAssigns solver) (subtract 1)
+  PQ.enqueue (svVarQueue solver) v
+
+addBacktrackCB :: Solver -> Var -> IO () -> IO ()
+addBacktrackCB solver !v callback = do
+  vd <- varData solver v
+  m <- readIORef (vdAssignment vd)
+  case m of
+    Nothing -> error "addBacktrackCB: should not happen"
+    Just a -> modifyIORef (aBacktrackCBs a) (callback :)
+
+-- | Register the constraint to be notified when the literal becames false.
+watch :: Constraint c => Solver -> Lit -> c -> IO ()
+watch solver !lit c = do
+  when debugMode $ do
+    lits <- watchedLiterals solver c
+    unless (lit `elem` lits) $ error "watch: should not happen"
+  ld <- litData solver lit
+  modifyIORef (ldWatches ld) (toConstraint c : )
+
+-- | Returns list of constraints that are watching the literal.
+watches :: Solver -> Lit -> IO [SomeConstraint]
+watches solver !lit = do
+  ld <- litData solver lit
+  readIORef (ldWatches ld)
+
+addToDB :: Constraint c => Solver -> c -> IO ()
+addToDB solver c = do
+  modifyIORef (svClauseDB solver) (toConstraint c : )
+  when debugMode $ logIO solver $ do
+    str <- showConstraint solver c
+    return $ printf "constraint %s is added" str
+  sanityCheck solver
+
+addToLearntDB :: Constraint c => Solver -> c -> IO ()
+addToLearntDB solver c = do
+  modifyIORef (svLearntDB solver) $ \(n,xs) -> (n+1, toConstraint c : xs)
+  when debugMode $ logIO solver $ do
+    str <- showConstraint solver c
+    return $ printf "constraint %s is added" str
+  sanityCheck solver
+
+reduceDB :: Solver -> IO ()
+reduceDB solver = do
+  (n,cs) <- readIORef (svLearntDB solver)
+
+  xs <- forM cs $ \c -> do
+    p <- constrIsProtected solver c
+    actval <- constrActivity solver c
+    return (c, (p, actval))
+
+  -- Note that False <= True
+  let ys = sortBy (comparing snd) xs
+      (zs,ws) = splitAt (length ys `div` 2) ys
+
+  let loop [] ret = return ret
+      loop ((c,(isShort,_)) : rest) ret = do
+        flag <- if isShort
+                then return True
+                else isLocked solver c
+        if flag
+          then loop rest (c:ret)
+          else do
+            detach solver c
+            loop rest ret
+  zs2 <- loop zs []
+
+  let cs2 = zs2 ++ map fst ws
+      n2 = length cs2
+
+  log solver $ printf "learnt constraints deletion: %d -> %d" n n2
+  writeIORef (svLearntDB solver) (n2,cs2)
+
+type VarActivity = Double
+
+varActivity :: Solver -> Var -> IO VarActivity
+varActivity solver !v = do
+  vd <- varData solver v
+  readIORef (vdActivity vd)
+
+varDecayActivity :: Solver -> IO ()
+varDecayActivity solver = do
+  d <- readIORef (svVarDecay solver)
+  modifyIORef' (svVarInc solver) (d*)
+
+varBumpActivity :: Solver -> Var -> IO ()
+varBumpActivity solver !v = do
+  inc <- readIORef (svVarInc solver)
+  vd <- varData solver v
+  modifyIORef' (vdActivity vd) (+inc)
+  PQ.update (svVarQueue solver) v
+  aval <- readIORef (vdActivity vd)
+  when (aval > 1e20) $
+    -- Rescale
+    varRescaleAllActivity solver
+
+varRescaleAllActivity :: Solver -> IO ()
+varRescaleAllActivity solver = do
+  vs <- variables solver
+  forM_ vs $ \v -> do
+    vd <- varData solver v
+    modifyIORef' (vdActivity vd) (* 1e-20)
+  modifyIORef' (svVarInc solver) (* 1e-20)
+
+variables :: Solver -> IO [Var]
+variables solver = do
+  n <- nVars solver
+  return [1 .. n]
+
+-- | number of variables of the problem.
+nVars :: Solver -> IO Int
+nVars solver = do
+  vcnt <- readIORef (svVarCounter solver)
+  return $! (vcnt-1)
+
+-- | number of assigned variables.
+nAssigns :: Solver -> IO Int
+nAssigns solver = readIORef (svNAssigns solver)
+
+-- | number of clauses.
+nClauses :: Solver -> IO Int
+nClauses solver = do
+  xs <- readIORef (svClauseDB solver)
+  return $ length xs
+
+-- | number of learnt constrints.
+nLearnt :: Solver -> IO Int
+nLearnt solver = do
+  (n,_) <- readIORef (svLearntDB solver)
+  return n
+
+learntConstraints :: Solver -> IO [SomeConstraint]
+learntConstraints solver = do
+  (_,cs) <- readIORef (svLearntDB solver)
+  return cs
+
+{--------------------------------------------------------------------
+  Solver
+--------------------------------------------------------------------}
+
+-- | Create a new Solver instance.
+newSolver :: IO Solver
+newSolver = do
+ rec
+  ok   <- newIORef True
+  vcnt <- newIORef 1
+  trail <- newIORef []
+  vars <- newIORef =<< newArray_ (1,0)
+  vqueue <- PQ.newPriorityQueueBy (ltVar solver)
+  db  <- newIORef []
+  db2 <- newIORef (0,[])
+  as  <- newIORef =<< newArray_ (0,-1)
+  lv  <- newIORef levelRoot
+  q   <- SQ.newFifo
+  m   <- newIORef Nothing
+  ndecision <- newIORef 0
+  nranddec  <- newIORef 0
+  nconflict <- newIORef 0
+  nrestart  <- newIORef 0
+  nassigns  <- newIORef 0
+
+  claDecay <- newIORef (1 / 0.999)
+  claInc   <- newIORef 1
+  varDecay <- newIORef (1 / 0.95)
+  varInc   <- newIORef 1
+  restartStrat <- newIORef defaultRestartStrategy
+  restartFirst <- newIORef defaultRestartFirst
+  restartInc <- newIORef defaultRestartInc
+  learning <- newIORef defaultLearningStrategy
+  learntSizeInc <- newIORef defaultLearntSizeInc
+  ccMin <- newIORef defaultCCMin
+  checkModel <- newIORef False
+
+  learntLim <- newIORef undefined
+
+  logger <- newIORef Nothing
+
+  randfreq <- newIORef defaultRandomFreq
+  randgen  <- newIORef =<< Rand.newStdGen
+
+  let solver =
+        Solver
+        { svOk = ok
+        , svVarCounter = vcnt
+        , svVarQueue   = vqueue
+        , svTrail      = trail
+        , svVarData    = vars
+        , svClauseDB   = db
+        , svLearntDB   = db2
+        , svAssumptions = as
+        , svLevel      = lv
+        , svBCPQueue   = q
+        , svModel      = m
+        , svNDecision  = ndecision
+        , svNRandomDecision = nranddec
+        , svNConflict  = nconflict
+        , svNRestart   = nrestart
+        , svNAssigns   = nassigns
+        , svVarDecay   = varDecay
+        , svVarInc     = varInc
+        , svClaDecay   = claDecay
+        , svClaInc     = claInc
+        , svRestartStrategy = restartStrat
+        , svRestartFirst = restartFirst
+        , svRestartInc   = restartInc
+        , svLearningStrategy = learning
+        , svLearntSizeInc = learntSizeInc
+        , svCCMin = ccMin
+        , svLearntLim = learntLim
+        , svLogger = logger
+        , svCheckModel = checkModel
+        , svRandomFreq = randfreq
+        , svRandomGen  = randgen
+        }
+ return solver
+
+ltVar :: Solver -> Var -> Var -> IO Bool
+ltVar solver v1 v2 = do
+  a1 <- varActivity solver v1
+  a2 <- varActivity solver v2
+  return $! a1 > a2
+
+{--------------------------------------------------------------------
+  Problem specification
+--------------------------------------------------------------------}
+
+-- |Add a new variable
+newVar :: Solver -> IO Var
+newVar s = do
+  v <- readIORef (svVarCounter s)
+  writeIORef (svVarCounter s) (v+1)
+  vd <- newVarData
+
+  a <- readIORef (svVarData s)
+  (_,ub) <- getBounds a
+  if v <= ub
+    then writeArray a v vd
+    else do
+      let ub' = max 2 (ub * 3 `div` 2)
+      a' <- newArray_ (1,ub')
+      forM_ [1..ub] $ \v2 -> do
+        vd2 <- readArray a v2
+        writeArray a' v2 vd2
+      writeArray a' v vd
+      writeIORef (svVarData s) a'
+
+  PQ.enqueue (svVarQueue s) v
+  return v
+
+-- |Add a clause to the solver.
+addClause :: Solver -> Clause -> IO ()
+addClause solver lits = do
+  d <- readIORef (svLevel solver)
+  assert (d == levelRoot) $ return ()
+
+  lits2 <- instantiateClause solver lits
+  case normalizeClause =<< lits2 of
+    Nothing -> return ()
+    Just [] -> markBad solver
+    Just [lit] -> do
+      ret <- assign solver lit
+      assert ret $ return ()
+      ret2 <- deduce solver
+      case ret2 of
+        Nothing -> return ()
+        Just _ -> markBad solver
+    Just lits3 -> do
+      clause <- newClauseData lits3 False
+      attach solver clause
+      addToDB solver clause
+
+-- | Add a cardinality constraints /atleast({l1,l2,..},n)/.
+addAtLeast :: Solver -- ^ The 'Solver' argument.
+           -> [Lit]  -- ^ set of literals /{l1,l2,..}/ (duplicated elements are ignored)
+           -> Int    -- ^ /n/.
+           -> IO ()
+addAtLeast solver lits n = do
+  d <- readIORef (svLevel solver)
+  assert (d == levelRoot) $ return ()
+
+  (lits',n') <- liftM normalizeAtLeast $ instantiateAtLeast solver (lits,n)
+  let len = length lits'
+
+  if n' <= 0 then return ()
+    else if n' > len then markBad solver
+    else if n' == 1 then addClause solver lits'
+    else if n' == len then do
+      forM_ lits' $ \l -> do
+        ret <- assign solver l
+        assert ret $ return ()
+        ret2 <- deduce solver
+        case ret2 of
+          Nothing -> return ()
+          Just _ -> markBad solver
+    else do
+      c <- newAtLeastData lits' n' False
+      attach solver c
+      addToDB solver c
+
+-- | Add a cardinality constraints /atmost({l1,l2,..},n)/.
+addAtMost :: Solver -- ^ The 'Solver' argument
+          -> [Lit]  -- ^ set of literals /{l1,l2,..}/ (duplicated elements are ignored)
+          -> Int    -- ^ /n/
+          -> IO ()
+addAtMost solver lits n = addAtLeast solver lits' (len-n)
+  where
+    len   = length lits
+    lits' = map litNot lits
+
+-- | Add a cardinality constraints /exactly({l1,l2,..},n)/.
+addExactly :: Solver -- ^ The 'Solver' argument
+           -> [Lit]  -- ^ set of literals /{l1,l2,..}/ (duplicated elements are ignored)
+           -> Int    -- ^ /n/
+           -> IO ()
+addExactly solver lits n = do
+  addAtLeast solver lits n
+  addAtMost solver lits n
+
+-- | Add a pseudo boolean constraints /c1*l1 + c2*l2 + … ≥ n/.
+addPBAtLeast :: Solver          -- ^ The 'Solver' argument.
+             -> [(Integer,Lit)] -- ^ set of terms @[(c1,l1),(c2,l2),…]@
+             -> Integer         -- ^ /n/
+             -> IO ()
+addPBAtLeast solver ts n = do
+  d <- readIORef (svLevel solver)
+  assert (d == levelRoot) $ return ()
+
+  (ts',degree) <- liftM normalizePBAtLeast $ instantiatePB solver (ts,n)
+  let cs = map fst ts'
+      slack = sum cs - degree
+
+  if degree <= 0 then return ()
+    else if slack < 0 then markBad solver
+    else if Set.size (Set.fromList cs) == 1 then do
+      let c = head cs
+      addAtLeast solver (map snd ts') (fromInteger ((degree+c-1) `div` c))
+    else do
+      c <- newPBAtLeastData ts' degree False
+      attach solver c
+      addToDB solver c
+      ret <- pbPropagate solver c
+      if not ret
+       then do
+         markBad solver
+       else do
+         ret2 <- deduce solver
+         case ret2 of
+           Nothing -> return ()
+           Just _ -> markBad solver
+
+-- | Add a pseudo boolean constraints /c1*l1 + c2*l2 + … ≤ n/.
+addPBAtMost :: Solver          -- ^ The 'Solver' argument.
+            -> [(Integer,Lit)] -- ^ list of @[(c1,l1),(c2,l2),…]@
+            -> Integer         -- ^ /n/
+            -> IO ()
+addPBAtMost solver ts n = addPBAtLeast solver [(-c,l) | (c,l) <- ts] (negate n)
+
+-- | Add a pseudo boolean constraints /c1*l1 + c2*l2 + … = n/.
+addPBExactly :: Solver          -- ^ The 'Solver' argument.
+             -> [(Integer,Lit)] -- ^ list of terms @[(c1,l1),(c2,l2),…]@
+             -> Integer         -- ^ /n/
+             -> IO ()
+addPBExactly solver ts n = do
+  (ts2,n2) <- liftM normalizePBExactly $ instantiatePB solver (ts,n)
+  addPBAtLeast solver ts2 n2
+  addPBAtMost solver ts2 n2
+
+-- | Add a soft pseudo boolean constraints /lit ⇒ c1*l1 + c2*l2 + … ≥ n/.
+addPBAtLeastSoft
+  :: Solver          -- ^ The 'Solver' argument.
+  -> Lit             -- ^ indicator @lit@
+  -> [(Integer,Lit)] -- ^ set of terms @[(c1,l1),(c2,l2),…]@
+  -> Integer         -- ^ /n/
+  -> IO ()
+addPBAtLeastSoft solver sel lhs rhs = do
+  (lhs', rhs') <- liftM normalizePBAtLeast $ instantiatePB solver (lhs,rhs)
+  addPBAtLeast solver ((rhs', litNot sel) : lhs') rhs'
+
+-- | Add a soft pseudo boolean constraints /lit ⇒ c1*l1 + c2*l2 + … ≤ n/.
+addPBAtMostSoft
+  :: Solver          -- ^ The 'Solver' argument.
+  -> Lit             -- ^ indicator @lit@
+  -> [(Integer,Lit)] -- ^ set of terms @[(c1,l1),(c2,l2),…]@
+  -> Integer         -- ^ /n/
+  -> IO ()
+addPBAtMostSoft solver sel lhs rhs =
+  addPBAtLeastSoft solver sel [(negate c, lit) | (c,lit) <- lhs] (negate rhs)
+
+-- | Add a soft pseudo boolean constraints /lit ⇒ c1*l1 + c2*l2 + … = n/.
+addPBExactlySoft
+  :: Solver          -- ^ The 'Solver' argument.
+  -> Lit             -- ^ indicator @lit@
+  -> [(Integer,Lit)] -- ^ set of terms @[(c1,l1),(c2,l2),…]@
+  -> Integer         -- ^ /n/
+  -> IO ()
+addPBExactlySoft solver sel lhs rhs = do
+  (lhs2, rhs2) <- liftM normalizePBExactly $ instantiatePB solver (lhs,rhs)
+  addPBAtLeastSoft solver sel lhs2 rhs2
+  addPBAtMostSoft solver sel lhs2 rhs2
+
+{--------------------------------------------------------------------
+  Problem solving
+--------------------------------------------------------------------}
+
+-- | Solve constraints.
+-- Returns 'True' if the problem is SATISFIABLE.
+-- Returns 'False' if the problem is UNSATISFIABLE.
+solve :: Solver -> IO Bool
+solve solver = do
+  as <- newArray_ (0,-1)
+  writeIORef (svAssumptions solver) as
+  solve_ solver
+
+-- | Solve constraints under assuptions.
+-- Returns 'True' if the problem is SATISFIABLE.
+-- Returns 'False' if the problem is UNSATISFIABLE.
+solveWith :: Solver
+          -> [Lit]    -- ^ Assumptions
+          -> IO Bool
+solveWith solver ls = do
+  as <- newListArray (0, length ls -1) ls
+  writeIORef (svAssumptions solver) as
+  solve_ solver
+
+solve_ :: Solver -> IO Bool
+solve_ solver = do
+  log solver "Solving starts ..."
+  writeIORef (svModel solver) Nothing
+
+  ok <- readIORef (svOk solver)
+  if not ok
+    then return False
+    else do
+      when debugMode $ dumpVarActivity solver
+      d <- readIORef (svLevel solver)
+      assert (d == levelRoot) $ return ()
+
+      restartStrategy <- readIORef (svRestartStrategy solver)
+      restartFirst  <- readIORef (svRestartFirst solver)
+      restartInc    <- readIORef (svRestartInc solver)
+      let restartSeq = mkRestartSeq restartStrategy restartFirst restartInc
+
+      learntSizeInc <- readIORef (svLearntSizeInc solver)
+      nc <- nClauses solver
+      nv <- nVars solver
+      let learntSizeSeq   = iterate (ceiling . (learntSizeInc*) . fromIntegral) (max ((nc + nv) `div` 3) 16)
+      let learntSizeAdjSeq = iterate (\x -> (x * 3) `div` 2) (100::Int)
+      nextLearntSize    <- gen learntSizeSeq
+      nextLearntSizeAdj <- gen learntSizeAdjSeq
+
+      learntSizeAdjCnt <- newIORef undefined
+      let learntSizeAdj = do
+            size <- nextLearntSize
+            adj <- nextLearntSizeAdj
+            writeIORef (svLearntLim solver) size
+            writeIORef learntSizeAdjCnt adj
+          onConflict = do
+            cnt <- readIORef learntSizeAdjCnt
+            if (cnt==0)
+            then learntSizeAdj
+            else writeIORef (learntSizeAdjCnt) $! cnt-1
+
+      learntSizeAdj
+
+      let loop [] = error "solve_: should not happen"
+          loop (conflict_lim:rs) = do
+            ret <- search solver conflict_lim onConflict
+            case ret of
+              Just x -> return x
+              Nothing -> do
+                modifyIORef' (svNRestart solver) (+1)
+                backtrackTo solver levelRoot
+                loop rs
+
+      start <- getCPUTime
+      result <- loop restartSeq
+      end <- getCPUTime
+
+      when result $ do
+        checkModel <- readIORef (svCheckModel solver)
+        when checkModel $ checkSatisfied solver
+        constructModel solver
+
+      backtrackTo solver levelRoot
+
+      when debugMode $ dumpVarActivity solver
+      when debugMode $ dumpClaActivity solver
+      (log solver . printf "solving time = %.3fs") (fromIntegral (end - start) / 10^(12::Int) :: Double)
+      (log solver . printf "#decision = %d") =<< readIORef (svNDecision solver)
+      (log solver . printf "#random_decision = %d") =<< readIORef (svNRandomDecision solver)
+      (log solver . printf "#conflict = %d") =<< readIORef (svNConflict solver)
+      (log solver . printf "#restart = %d")  =<< readIORef (svNRestart solver)
+
+      return result
+
+search :: Solver -> Int -> IO () -> IO (Maybe Bool)
+search solver !conflict_lim onConflict = loop 0
+  where
+    loop :: Int -> IO (Maybe Bool)
+    loop !c = do
+      sanityCheck solver
+      conflict <- deduce solver
+      sanityCheck solver
+
+      case conflict of
+        Nothing -> do
+          n <- nLearnt solver
+          m <- nAssigns solver
+          learnt_lim <- readIORef (svLearntLim solver)
+          when (learnt_lim >= 0 && n - m > learnt_lim) $ reduceDB solver
+
+          r <- pickAssumption
+          case r of
+            Nothing -> return (Just False)
+            Just lit
+              | lit /= litUndef -> decide solver lit >> loop c
+              | otherwise -> do
+                  lit2 <- pickBranchLit solver
+                  if lit2 == litUndef
+                    then return (Just True)
+                    else decide solver lit2 >> loop c
+
+        Just constr -> do
+          varDecayActivity solver
+          constrDecayActivity solver
+          onConflict
+
+          modifyIORef' (svNConflict solver) (+1)
+          d <- readIORef (svLevel solver)
+
+          when debugMode $ logIO solver $ do
+            str <- showConstraint solver constr
+            return $ printf "conflict(level=%d): %s" d str
+
+          if d == levelRoot
+            then return (Just False)
+            else if conflict_lim >= 0 && c+1 >= conflict_lim then
+              return Nothing
+            else do
+              b <- handleConflict constr
+              if b
+                then loop (c+1)
+                else markBad solver >> return (Just False)
+
+    pickAssumption :: IO (Maybe Lit)
+    pickAssumption = do
+      !as <- readIORef (svAssumptions solver)
+      !b <- getBounds as
+      let go = do
+              d <- readIORef (svLevel solver)
+              if not (inRange b (d+1))
+                then return (Just litUndef)
+                else do
+                  l <- readArray as (d+1)
+                  val <- litValue solver l
+                  if val == lTrue then do
+                     -- dummy decision level
+                     modifyIORef' (svLevel solver) (+1)
+                     go
+                   else if val == lFalse then
+                     -- conflict with assumption
+                     return Nothing
+                   else
+                     return (Just l)
+      go
+
+    handleConflict :: SomeConstraint -> IO Bool
+    handleConflict constr = do
+      strat <- readIORef (svLearningStrategy solver)
+      case strat of
+        LearningClause -> do
+          (learntClause, level) <- analyzeConflict solver constr
+          backtrackTo solver level
+          case learntClause of
+            [] -> error "search(LearningClause): should not happen"
+            [lit] -> do
+              ret <- assign solver lit
+              assert ret $ return ()
+              return ()
+            lit:_ -> do
+              cl <- newClauseData learntClause True
+              attach solver cl
+              addToLearntDB solver cl
+              assignBy solver lit cl
+              constrBumpActivity solver cl
+          return True
+        LearningHybrid -> do
+          (learntClause, level, pb) <- analyzeConflictHybrid solver constr
+          level2 <- pbBacktrackLevel solver pb
+          let level3 = min level level2
+
+          pbdata <- newPBAtLeastData (fst pb) (snd pb) True
+          attach solver pbdata
+          addToLearntDB solver pbdata
+
+          backtrackTo solver level3
+          slack <- readIORef (pbSlack pbdata)
+          if slack < 0
+            then do
+              if level3 == levelRoot
+               then return False
+               else handleConflict (toConstraint pbdata)
+            else do
+              case learntClause of
+                [] -> error "search(LearningHybrid): should not happen"
+                [lit] -> do
+                  ret <- assign solver lit
+                  assert ret $ return ()
+                  return ()
+                lit:_ -> do
+                  cl <- newClauseData learntClause True
+                  attach solver cl
+                  addToLearntDB solver cl
+                  when (level3 == level) $ do
+                    assignBy solver lit cl
+                    constrBumpActivity solver cl
+              pbPropagate solver pbdata
+              return True
+
+-- | After 'solve' returns True, it returns the model.
+model :: Solver -> IO Model
+model solver = do
+  m <- readIORef (svModel solver)
+  return (fromJust m)
+
+{--------------------------------------------------------------------
+  Parameter settings.
+--------------------------------------------------------------------}
+
+setRestartStrategy :: Solver -> RestartStrategy -> IO ()
+setRestartStrategy solver s = writeIORef (svRestartStrategy solver) s
+
+-- | default value for @RestartStrategy@.
+defaultRestartStrategy :: RestartStrategy
+defaultRestartStrategy = MiniSATRestarts
+
+-- | The initial restart limit. (default 100)
+-- Negative value is used to disable restart.
+setRestartFirst :: Solver -> Int -> IO ()
+setRestartFirst solver !n = writeIORef (svRestartFirst solver) n
+
+-- | default value for @RestartFirst@.
+defaultRestartFirst :: Int
+defaultRestartFirst = 100
+
+-- | The factor with which the restart limit is multiplied in each restart. (default 1.5)
+setRestartInc :: Solver -> Double -> IO ()
+setRestartInc solver !r = writeIORef (svRestartInc solver) r
+
+-- | default value for @RestartInc@.
+defaultRestartInc :: Double
+defaultRestartInc = 1.5
+
+data LearningStrategy
+  = LearningClause
+  | LearningHybrid
+
+setLearningStrategy :: Solver -> LearningStrategy -> IO ()
+setLearningStrategy solver l = writeIORef (svLearningStrategy solver) $! l
+
+defaultLearningStrategy :: LearningStrategy
+defaultLearningStrategy = LearningClause
+
+-- | The limit for learnt clauses is multiplied with this factor each restart. (default 1.1)
+setLearntSizeInc :: Solver -> Double -> IO ()
+setLearntSizeInc solver !r = writeIORef (svLearntSizeInc solver) r
+
+-- | default value for @LearntSizeInc@.
+defaultLearntSizeInc :: Double
+defaultLearntSizeInc = 1.1
+
+-- | The limit for learnt clauses is multiplied with this factor each restart. (default 1.1)
+setCCMin :: Solver -> Int -> IO ()
+setCCMin solver !v = writeIORef (svCCMin solver) v
+
+-- | default value for @CCMin@.
+defaultCCMin :: Int
+defaultCCMin = 2
+
+-- | The default polarity of a variable.
+setVarPolarity :: Solver -> Var -> Bool -> IO ()
+setVarPolarity solver v val = do
+  vd <- varData solver v
+  writeIORef (vdPolarity vd) val
+
+setCheckModel :: Solver -> Bool -> IO ()
+setCheckModel solver flag = do
+  writeIORef (svCheckModel solver) flag
+
+-- | The frequency with which the decision heuristic tries to choose a random variable
+setRandomFreq :: Solver -> Double -> IO ()
+setRandomFreq solver r = do
+  writeIORef (svRandomFreq solver) r
+
+defaultRandomFreq :: Double
+defaultRandomFreq = 0.005
+
+-- | Used by the random variable selection
+setRandomSeed :: Solver -> Int -> IO ()
+setRandomSeed solver seed = do
+  writeIORef (svRandomGen solver) (Rand.mkStdGen seed)
+
+{--------------------------------------------------------------------
+  API for implementation of @solve@
+--------------------------------------------------------------------}
+
+pickBranchLit :: Solver -> IO Lit
+pickBranchLit !solver = do
+  let vqueue = svVarQueue solver
+
+  -- Random decision
+  let withRandGen :: (Rand.StdGen -> (a, Rand.StdGen)) -> IO a
+      withRandGen f = do
+        randgen  <- readIORef (svRandomGen solver)
+        let (r, randgen') = f randgen
+        writeIORef (svRandomGen solver) randgen'
+        return r
+  !randfreq <- readIORef (svRandomFreq solver)
+  !size <- PQ.queueSize vqueue
+  !r <- withRandGen Rand.random
+  var <-
+    if (r < randfreq && size >= 2)
+    then do
+      a <- PQ.getHeapArray vqueue
+      i <- withRandGen $ Rand.randomR (0, size-1)
+      var <- readArray a i
+      val <- varValue solver var
+      if val == lUndef
+       then do
+         modifyIORef' (svNRandomDecision solver) (1+)
+         return var
+       else return litUndef
+    else
+      return litUndef
+
+  -- Activity based decision
+  let loop :: IO Var
+      loop = do
+        m <- PQ.dequeue vqueue
+        case m of
+          Nothing -> return litUndef
+          Just var -> do
+            val <- varValue solver var
+            if val /= lUndef
+              then loop
+              else return var
+  var <-
+    if var==litUndef
+    then loop
+    else return var
+
+  if var==litUndef
+    then return litUndef
+    else do
+      vd <- varData solver var
+      -- TODO: random polarity
+      p <- readIORef (vdPolarity vd)
+      return $! literal var p
+
+decide :: Solver -> Lit -> IO ()
+decide solver !lit = do
+  modifyIORef' (svNDecision solver) (+1)
+  modifyIORef' (svLevel solver) (+1)
+  when debugMode $ do
+    val <- litValue solver lit
+    when (val /= lUndef) $ error "decide: should not happen"
+  assign solver lit
+  return ()
+
+deduce :: Solver -> IO (Maybe SomeConstraint)
+deduce solver = loop
+  where
+    loop :: IO (Maybe SomeConstraint)
+    loop = do
+      r <- bcpDequeue solver
+      case r of
+        Nothing -> return Nothing
+        Just lit -> do
+          ret <- processLit lit
+          case ret of
+            Just _ -> return ret
+            Nothing -> loop
+
+    processLit :: Lit -> IO (Maybe SomeConstraint)
+    processLit !lit = do
+      let lit2 = litNot lit
+      ld <- litData solver lit2
+      let wsref = ldWatches ld
+      let loop2 [] = return Nothing
+          loop2 (w:ws) = do
+            ok <- propagate solver w lit2
+            if ok
+              then loop2 ws
+              else do
+                modifyIORef wsref (++ws)
+                return (Just w)
+      ws <- readIORef wsref
+      writeIORef wsref []
+      loop2 ws
+
+analyzeConflict :: Constraint c => Solver -> c -> IO (Clause, Level)
+analyzeConflict solver constr = do
+  d <- readIORef (svLevel solver)
+
+  let split :: [Lit] -> IO (LitSet, LitSet)
+      split = go (IS.empty, IS.empty)
+        where
+          go (xs,ys) [] = return (xs,ys)
+          go (xs,ys) (l:ls) = do
+            lv <- litLevel solver l
+            if lv == levelRoot then
+                go (xs,ys) ls
+              else if lv >= d then
+                go (IS.insert l xs, ys) ls
+              else
+                go (xs, IS.insert l ys) ls
+
+  let loop :: LitSet -> LitSet -> IO LitSet
+      loop lits1 lits2
+        | sz==1 = do
+            return $ lits1 `IS.union` lits2
+        | sz>=2 = do
+            ret <- popTrail solver
+            case ret of
+              Nothing -> do
+                error $ printf "analyzeConflict: should not happen: empty trail: loop %s %s"
+                               (show lits1) (show lits2)
+              Just l -> do
+                if litNot l `IS.notMember` lits1
+                 then do
+                   unassign solver (litVar l)
+                   loop lits1 lits2
+                 else do
+                  m <- varReason solver (litVar l)
+                  case m of
+                    Nothing -> error "analyzeConflict: should not happen"
+                    Just constr2 -> do
+                      constrBumpActivity solver constr2
+                      xs <- reasonOf solver constr2 (Just l)
+                      forM_ xs $ \lit -> varBumpActivity solver (litVar lit)
+                      unassign solver (litVar l)
+                      (ys,zs) <- split xs
+                      loop (IS.delete (litNot l) lits1 `IS.union` ys)
+                           (lits2 `IS.union` zs)
+        | otherwise = error "analyzeConflict: should not happen: reason of current level is empty"
+        where
+          sz = IS.size lits1
+
+  constrBumpActivity solver constr
+  conflictClause <- reasonOf solver constr Nothing
+  forM_ conflictClause $ \lit -> varBumpActivity solver (litVar lit)
+  (ys,zs) <- split conflictClause
+  lits <- loop ys zs
+
+  lits2 <- minimizeConflictClause solver lits
+
+  xs <- liftM (sortBy (flip (comparing snd))) $
+    forM (IS.toList lits2) $ \l -> do
+      lv <- litLevel solver l
+      return (l,lv)
+
+  let level = case xs of
+                [] -> error "analyzeConflict: should not happen"
+                [_] -> levelRoot
+                _:(_,lv):_ -> lv
+  return (map fst xs, level)
+
+analyzeConflictHybrid :: Constraint c => Solver -> c -> IO (Clause, Level, ([(Integer,Lit)], Integer))
+analyzeConflictHybrid solver constr = do
+  d <- readIORef (svLevel solver)
+
+  let split :: [Lit] -> IO (LitSet, LitSet)
+      split = go (IS.empty, IS.empty)
+        where
+          go (xs,ys) [] = return (xs,ys)
+          go (xs,ys) (l:ls) = do
+            lv <- litLevel solver l
+            if lv == levelRoot then
+                go (xs,ys) ls
+              else if lv >= d then
+                go (IS.insert l xs, ys) ls
+              else
+                go (xs, IS.insert l ys) ls
+
+  let loop :: LitSet -> LitSet -> ([(Integer,Lit)],Integer) -> IO (LitSet, ([(Integer,Lit)],Integer))
+      loop lits1 lits2 pb
+        | sz==1 = do
+            return $ (lits1 `IS.union` lits2, pb)
+        | sz>=2 = do
+            ret <- popTrail solver
+            case ret of
+              Nothing -> do
+                error $ printf "analyzeConflictHybrid: should not happen: empty trail: loop %s %s"
+                               (show lits1) (show lits2)
+              Just l -> do
+                m <- varReason solver (litVar l)
+                case m of
+                  Nothing -> error "analyzeConflictHybrid: should not happen"
+                  Just constr2 -> do
+                    xs <- reasonOf solver constr2 (Just l)
+                    (lits1',lits2') <-
+                      if litNot l `IS.notMember` lits1
+                      then return (lits1,lits2)
+                      else do
+                        constrBumpActivity solver constr2
+                        forM_ xs $ \lit -> varBumpActivity solver (litVar lit)
+                        (ys,zs) <- split xs
+                        return  (IS.delete (litNot l) lits1 `IS.union` ys, lits2 `IS.union` zs)
+
+                    pb2 <- toPBAtLeast solver constr2
+                    o <- pbOverSAT solver pb2
+                    let pb3 = if o then ([(1,l2) | l2 <- l:xs],1) else pb2
+                    let pb' =
+                           if any (\(_,l2) -> litNot l == l2) (fst pb)
+                           then cutResolve pb pb3 (litVar l)
+                           else pb
+
+                    unassign solver (litVar l)
+                    loop lits1' lits2' pb'
+
+        | otherwise = error "analyzeConflictHybrid: should not happen: reason of current level is empty"
+        where
+          sz = IS.size lits1
+
+  constrBumpActivity solver constr
+  conflictClause <- reasonOf solver constr Nothing
+  pbConfl <- toPBAtLeast solver constr
+  forM_ conflictClause $ \lit -> varBumpActivity solver (litVar lit)
+  (ys,zs) <- split conflictClause
+  (lits, pb) <- loop ys zs pbConfl
+
+  lits2 <- minimizeConflictClause solver lits
+
+  xs <- liftM (sortBy (flip (comparing snd))) $
+    forM (IS.toList lits2) $ \l -> do
+      lv <- litLevel solver l
+      return (l,lv)
+
+  let level = case xs of
+                [] -> error "analyzeConflict: should not happen"
+                [_] -> levelRoot
+                _:(_,lv):_ -> lv
+  return (map fst xs, level, pb)
+
+pbBacktrackLevel :: Solver -> ([(Integer,Lit)],Integer) -> IO Level
+pbBacktrackLevel _ ([], rhs) = assert (rhs > 0) $ return levelRoot
+pbBacktrackLevel solver (lhs, rhs) = do
+  let go lvs lhs' s = 
+        case IS.minView lvs of
+          Nothing -> error "pbBacktrackLevel: should not happen"
+          Just (lv2, lvs2) -> do
+            let s2   = s - sum [c | (c,_,lv3) <- lhs', Just lv2 == lv3]
+                lhs2 = [x | x@(_,_,lv3) <- lhs', Just lv2 /= lv3]
+            if s2 < 0 then
+              return lv2 -- conflict
+            else if takeWhile (\(c,_,_) -> c > s) lhs2 /= [] then
+              return lv2 --unit
+            else
+              go lvs2 lhs2 s2
+
+  lhs' <- forM (sortBy (flip (comparing fst)) lhs) $ \(c, lit) -> do
+    v <- litValue solver lit
+    if v /= lFalse
+      then return (c, lit, Nothing)
+      else do
+        lv <- litLevel solver lit
+        return (c, lit, Just lv)
+
+  let lvs = IS.fromList [lv | (_,_,Just lv) <- lhs']
+      s0 = sum [c | (c,_) <- lhs] - rhs
+  go lvs lhs' s0
+
+minimizeConflictClause :: Solver -> LitSet -> IO LitSet
+minimizeConflictClause solver lits = do
+  ccmin <- readIORef (svCCMin solver)
+  if ccmin >= 2 then
+     minimizeConflictClauseRecursive solver lits
+   else if ccmin >= 1 then
+     minimizeConflictClauseLocal solver lits
+   else
+     return lits
+
+minimizeConflictClauseLocal :: Solver -> LitSet -> IO LitSet
+minimizeConflictClauseLocal solver lits = do
+  let xs = IS.toAscList lits
+  ys <- filterM (liftM not . isRedundant) xs
+  when debugMode $ do
+    log solver "minimizeConflictClauseLocal:"
+    log solver $ show xs
+    log solver $ show ys
+  return $ IS.fromAscList $ ys
+
+  where
+    isRedundant :: Lit -> IO Bool
+    isRedundant lit = do
+      c <- varReason solver (litVar lit)
+      case c of
+        Nothing -> return False
+        Just c2 -> do
+          ls <- reasonOf solver c2 (Just (litNot lit))
+          allM test ls
+
+    test :: Lit -> IO Bool
+    test lit = do
+      lv <- litLevel solver lit
+      return $ lv == levelRoot || lit `IS.member` lits
+
+minimizeConflictClauseRecursive :: Solver -> LitSet -> IO LitSet
+minimizeConflictClauseRecursive solver lits = do
+  let
+    isRedundant :: Lit -> IO Bool
+    isRedundant lit = do
+      c <- varReason solver (litVar lit)
+      case c of
+        Nothing -> return False
+        Just c2 -> do
+          ls <- reasonOf solver c2 (Just (litNot lit))
+          go ls IS.empty
+
+    go :: [Lit] -> IS.IntSet -> IO Bool
+    go [] _ = return True
+    go (lit : ls) seen = do
+      lv <- litLevel solver lit
+      if lv == levelRoot || lit `IS.member` lits || lit `IS.member` seen
+        then go ls seen
+        else do
+          c <- varReason solver (litVar lit)
+          case c of
+            Nothing -> return False
+            Just c2 -> do
+              ls2 <- reasonOf solver c2 (Just (litNot lit))
+              go (ls2 ++ ls) (IS.insert lit seen)
+
+  let xs = IS.toAscList lits
+  ys <- filterM (liftM not . isRedundant) xs
+  when debugMode $ do
+    log solver "minimizeConflictClauseRecursive:"
+    log solver $ show xs
+    log solver $ show ys
+  return $ IS.fromAscList $ ys
+
+popTrail :: Solver -> IO (Maybe Lit)
+popTrail solver = do
+  m <- readIORef (svTrail solver)
+  case m of
+    []   -> return Nothing
+    l:ls -> do
+      writeIORef (svTrail solver) ls
+      return $ Just l
+
+-- | Revert to the state at given level
+-- (keeping all assignment at @level@ but not beyond).
+backtrackTo :: Solver -> Int -> IO ()
+backtrackTo solver level = do
+  when debugMode $ log solver $ printf "backtrackTo: %d" level
+  writeIORef (svTrail solver) =<< loop =<< readIORef (svTrail solver)
+  SQ.clear (svBCPQueue solver)
+  writeIORef (svLevel solver) level
+  where
+    loop :: [Lit] -> IO [Lit]
+    loop [] = return []
+    loop lls@(l:ls) = do
+      lv <- litLevel solver l
+      if lv <= level
+        then return lls
+        else unassign solver (litVar l) >> loop ls
+
+constructModel :: Solver -> IO ()
+constructModel solver = do
+  n <- nVars solver
+  (marr::IOUArray Var Bool) <- newArray_ (1,n)
+  forM_ [1..n] $ \v -> do
+    vd <- varData solver v
+    a <- readIORef (vdAssignment vd)
+    writeArray marr v (aValue (fromJust a))
+  m <- unsafeFreeze marr
+  writeIORef (svModel solver) (Just m)
+
+constrDecayActivity :: Solver -> IO ()
+constrDecayActivity solver = do
+  d <- readIORef (svClaDecay solver)
+  modifyIORef' (svClaInc solver) (d*)
+
+constrRescaleAllActivity :: Solver -> IO ()
+constrRescaleAllActivity solver = do
+  xs <- learntConstraints solver
+  forM_ xs $ \c -> constrRescaleActivity solver c
+  modifyIORef' (svClaInc solver) (* 1e-20)
+
+{--------------------------------------------------------------------
+  constraint implementation
+--------------------------------------------------------------------}
+
+class Constraint a where
+  toConstraint :: a -> SomeConstraint
+
+  showConstraint :: Solver -> a -> IO String
+
+  attach :: Solver -> a -> IO ()
+
+  watchedLiterals :: Solver -> a -> IO [Lit]
+
+  -- | invoked with the watched literal when the literal is falsified.
+  -- 'watch' で 'toConstraint' を呼び出して heap allocation が発生するのを
+  -- 避けるために、元の 'SomeConstraint' も渡しておく。
+  basicPropagate :: Solver -> SomeConstraint -> a -> Lit -> IO Bool
+
+  -- | deduce a clause C∨l from the constraint and return C.
+  -- C and l should be false and true respectively under the current
+  -- assignment.
+  basicReasonOf :: Solver -> a -> Maybe Lit -> IO Clause
+
+  toPBAtLeast :: Solver -> a -> IO ([(Integer,Lit)], Integer)
+
+  isSatisfied :: Solver -> a -> IO Bool
+
+  constrIsProtected :: Solver -> a -> IO Bool
+  constrIsProtected _ _ = return False
+
+  constrActivity :: Solver -> a -> IO Double
+
+  constrBumpActivity :: Solver -> a -> IO ()
+  constrBumpActivity _ _ = return ()
+
+  constrRescaleActivity :: Solver -> a -> IO ()
+  constrRescaleActivity _ _ = return ()
+
+detach :: Constraint a => Solver -> a -> IO ()
+detach solver c = do
+  let c2 = toConstraint c
+  lits <- watchedLiterals solver c
+  forM_ lits $ \lit -> do
+    ld <- litData solver lit
+    modifyIORef' (ldWatches ld) (delete c2)
+
+-- | invoked with the watched literal when the literal is falsified.
+propagate :: Solver -> SomeConstraint -> Lit -> IO Bool
+propagate solver c l = basicPropagate solver c c l
+
+-- | deduce a clause C∨l from the constraint and return C.
+-- C and l should be false and true respectively under the current
+-- assignment.
+reasonOf :: Constraint a => Solver -> a -> Maybe Lit -> IO Clause
+reasonOf solver c x = do
+  when debugMode $
+    case x of
+      Nothing -> return ()
+      Just lit -> do
+        val <- litValue solver lit
+        unless (lTrue == val) $ do
+          str <- showConstraint solver c
+          error (printf "reasonOf: value of literal %d should be True but %s (basicReasonOf %s %s)" lit (show val) str (show x))
+  cl <- basicReasonOf solver c x
+  when debugMode $ do
+    forM_ cl $ \lit -> do
+      val <- litValue solver lit
+      unless (lFalse == val) $ do
+        str <- showConstraint solver c
+        error (printf "reasonOf: value of literal %d should be False but %s (basicReasonOf %s %s)" lit (show val) str (show x))
+  return cl
+
+isLocked :: Solver -> SomeConstraint -> IO Bool
+isLocked solver c = anyM p =<< watchedLiterals solver c
+  where
+    p :: Lit -> IO Bool
+    p lit = do
+      val <- litValue solver lit
+      if val /= lTrue
+        then return False
+        else do
+          m <- varReason solver (litVar lit)
+          case m of
+            Nothing -> return False
+            Just c2 -> return $! c == c2
+
+data SomeConstraint
+  = ConstrClause !ClauseData
+  | ConstrAtLeast !AtLeastData
+  | ConstrPBAtLeast !PBAtLeastData
+  deriving Eq
+
+instance Constraint SomeConstraint where
+  toConstraint = id
+
+  showConstraint s (ConstrClause c)    = showConstraint s c
+  showConstraint s (ConstrAtLeast c)   = showConstraint s c
+  showConstraint s (ConstrPBAtLeast c) = showConstraint s c
+
+  attach s (ConstrClause c)    = attach s c
+  attach s (ConstrAtLeast c)   = attach s c
+  attach s (ConstrPBAtLeast c) = attach s c
+
+  watchedLiterals s (ConstrClause c)    = watchedLiterals s c
+  watchedLiterals s (ConstrAtLeast c)   = watchedLiterals s c
+  watchedLiterals s (ConstrPBAtLeast c) = watchedLiterals s c
+
+  basicPropagate s this (ConstrClause c)  lit   = basicPropagate s this c lit
+  basicPropagate s this (ConstrAtLeast c) lit   = basicPropagate s this c lit
+  basicPropagate s this (ConstrPBAtLeast c) lit = basicPropagate s this c lit
+
+  basicReasonOf s (ConstrClause c)  l   = basicReasonOf s c l
+  basicReasonOf s (ConstrAtLeast c) l   = basicReasonOf s c l
+  basicReasonOf s (ConstrPBAtLeast c) l = basicReasonOf s c l
+
+  toPBAtLeast s (ConstrClause c)    = toPBAtLeast s c
+  toPBAtLeast s (ConstrAtLeast c)   = toPBAtLeast s c
+  toPBAtLeast s (ConstrPBAtLeast c) = toPBAtLeast s c
+
+  isSatisfied s (ConstrClause c)    = isSatisfied s c
+  isSatisfied s (ConstrAtLeast c)   = isSatisfied s c
+  isSatisfied s (ConstrPBAtLeast c) = isSatisfied s c
+
+  constrIsProtected s (ConstrClause c)    = constrIsProtected s c
+  constrIsProtected s (ConstrAtLeast c)   = constrIsProtected s c
+  constrIsProtected s (ConstrPBAtLeast c) = constrIsProtected s c
+
+  constrActivity s (ConstrClause c)    = constrActivity s c
+  constrActivity s (ConstrAtLeast c)   = constrActivity s c
+  constrActivity s (ConstrPBAtLeast c) = constrActivity s c
+
+  constrBumpActivity s (ConstrClause c)    = constrBumpActivity s c
+  constrBumpActivity s (ConstrAtLeast c)   = constrBumpActivity s c
+  constrBumpActivity s (ConstrPBAtLeast c) = constrBumpActivity s c
+
+  constrRescaleActivity s (ConstrClause c)    = constrRescaleActivity s c
+  constrRescaleActivity s (ConstrAtLeast c)   = constrRescaleActivity s c
+  constrRescaleActivity s (ConstrPBAtLeast c) = constrRescaleActivity s c
+
+{--------------------------------------------------------------------
+  Clause
+--------------------------------------------------------------------}
+
+data ClauseData
+  = ClauseData
+  { claLits :: !(IOUArray Int Lit)
+  , claActivity :: !(IORef Double)
+  }
+
+instance Eq ClauseData where
+  c1 == c2 = claActivity c1 == claActivity c2
+
+newClauseData :: Clause -> Bool -> IO ClauseData
+newClauseData ls learnt = do
+  let size = length ls
+  a <- newListArray (0, size-1) ls
+  act <- newIORef $! (if learnt then 0 else -1)
+  return (ClauseData a act)
+
+instance Constraint ClauseData where
+  toConstraint = ConstrClause
+
+  showConstraint _ this = do
+    lits <- getElems (claLits this)
+    return (show lits)
+
+  attach solver this = do
+    lits <- getElems (claLits this)
+    case lits of
+      l1:l2:_ -> do
+        watch solver l1 this
+        watch solver l2 this
+      _ -> return ()
+
+  watchedLiterals _ this = do
+    lits <- getElems (claLits this)
+    case lits of
+      l1:l2:_ -> return [l1, l2]
+      _ -> return []
+
+  basicPropagate !s this this2 !falsifiedLit = do
+    preprocess
+
+    !lit0 <- unsafeRead a 0
+    !val0 <- litValue s lit0
+    if val0 == lTrue
+      then do
+        watch s falsifiedLit this
+        return True
+      else do
+        (!lb,!ub) <- getBounds a
+        assert (lb==0) $ return ()
+        i <- findForWatch 2 ub
+        case i of
+          -1 -> do
+            when debugMode $ logIO s $ do
+               str <- showConstraint s this
+               return $ printf "basicPropagate: %s is unit" str
+            watch s falsifiedLit this
+            assignBy s lit0 this
+          _  -> do
+            !lit1 <- unsafeRead a 1
+            !liti <- unsafeRead a i
+            unsafeWrite a 1 liti
+            unsafeWrite a i lit1
+            watch s liti this
+            return True
+
+    where
+      a = claLits this2
+
+      preprocess :: IO ()
+      preprocess = do
+        !l0 <- unsafeRead a 0
+        !l1 <- unsafeRead a 1
+        assert (l0==falsifiedLit || l1==falsifiedLit) $ return ()
+        when (l0==falsifiedLit) $ do
+          unsafeWrite a 0 l1
+          unsafeWrite a 1 l0
+
+      -- Maybe を heap allocation するのを避けるために、
+      -- 見つからなかったときは -1 を返すことに。
+      findForWatch :: Int -> Int -> IO Int
+      findForWatch i end | i > end = return (-1)
+      findForWatch i end = do
+        val <- litValue s =<< unsafeRead a i
+        if val /= lFalse
+          then return i
+          else findForWatch (i+1) end
+
+  basicReasonOf _ this l = do
+    lits <- getElems (claLits this)
+    case l of
+      Nothing -> return lits
+      Just lit -> do
+        assert (lit == head lits) $ return ()
+        return $ tail lits
+
+  toPBAtLeast _ (ClauseData a _) = do
+    lits <- getElems a
+    return ([(1,l) | l <- lits], 1)
+
+  isSatisfied solver this = do
+    lits <- getElems (claLits this)
+    vals <- mapM (litValue solver) lits
+    return $ lTrue `elem` vals
+
+  constrIsProtected _ this = do
+    size <- liftM rangeSize (getBounds (claLits this))
+    return $! size <= 2
+
+  constrActivity _ this = do
+    let act = claActivity this
+    readIORef act
+
+  constrBumpActivity solver this = do
+    let act = claActivity this
+    aval <- readIORef act
+    when (aval >= 0) $ do -- learnt clause
+      inc <- readIORef (svClaInc solver)
+      let aval2 = aval+inc
+      writeIORef act $! aval2
+      when (aval2 > 1e20) $
+        -- Rescale
+        constrRescaleAllActivity solver
+
+  constrRescaleActivity _ this = do
+    let act = claActivity this
+    aval <- readIORef act
+    when (aval >= 0) $ writeIORef act $! (aval * 1e-20)
+
+instantiateClause :: Solver -> Clause -> IO (Maybe Clause)
+instantiateClause solver = loop []
+  where
+    loop :: [Lit] -> [Lit] -> IO (Maybe Clause)
+    loop ret [] = return $ Just ret
+    loop ret (l:ls) = do
+      val <- litValue solver l
+      if val==lTrue then
+         return Nothing
+       else if val==lFalse then
+         loop ret ls
+       else
+         loop (l : ret) ls
+
+{--------------------------------------------------------------------
+  Cardinality Constraint
+--------------------------------------------------------------------}
+
+data AtLeastData
+  = AtLeastData
+  { atLeastLits :: IOUArray Int Lit
+  , atLeastNum :: !Int
+  , atLeastActivity :: !(IORef Double)
+  }
+  deriving Eq
+
+newAtLeastData :: [Lit] -> Int -> Bool -> IO AtLeastData
+newAtLeastData ls n learnt = do
+  let size = length ls
+  a <- newListArray (0, size-1) ls
+  act <- newIORef $! (if learnt then 0 else -1)
+  return (AtLeastData a n act)
+
+instance Constraint AtLeastData where
+  toConstraint = ConstrAtLeast
+
+  showConstraint _ this = do
+    lits <- getElems (atLeastLits this)
+    return $ show lits ++ " >= " ++ show (atLeastNum this)
+
+  attach solver this = do
+    lits <- getElems (atLeastLits this)
+    let n = atLeastNum this
+    let ws = if length lits > n then take (n+1) lits else []
+    forM_ ws $ \l -> watch solver l this
+
+  watchedLiterals _ this = do
+    lits <- getElems (atLeastLits this)
+    let n = atLeastNum this
+    let ws = if length lits > n then take (n+1) lits else []
+    return ws
+
+  basicPropagate s this this2 falsifiedLit = do
+    preprocess
+
+    when debugMode $ do
+      litn <- readArray a n
+      unless (litn == falsifiedLit) $ error "AtLeastData.basicPropagate: should not happen"
+
+    (lb,ub) <- getBounds a
+    assert (lb==0) $ return ()
+    ret <- findForWatch (n+1) ub
+    case ret of
+      Nothing -> do
+        when debugMode $ logIO s $ do
+          str <- showConstraint s this
+          return $ printf "basicPropagate: %s is unit" str
+        watch s falsifiedLit this
+        let loop :: Int -> IO Bool
+            loop i
+              | i >= n = return True
+              | otherwise = do
+                  liti <- readArray a i
+                  ret2 <- assignBy s liti this
+                  if ret2
+                    then loop (i+1)
+                    else return False
+        loop 0
+      Just i  -> do
+        liti <- readArray a i
+        litn <- readArray a n
+        writeArray a i litn
+        writeArray a n liti
+        watch s liti this
+        return True
+
+    where
+      a = atLeastLits this2
+      n = atLeastNum this2
+
+      preprocess :: IO ()
+      preprocess = loop 0
+        where
+          loop :: Int -> IO ()
+          loop i
+            | i >= n = return ()
+            | otherwise = do
+              li <- readArray a i
+              if (li /= falsifiedLit)
+                then loop (i+1)
+                else do
+                  ln <- readArray a n
+                  writeArray a n li
+                  writeArray a i ln
+
+      findForWatch :: Int -> Int -> IO (Maybe Int)
+      findForWatch i end | i > end = return Nothing
+      findForWatch i end = do
+        val <- litValue s =<< readArray a i
+        if val /= lFalse
+          then return (Just i)
+          else findForWatch (i+1) end
+
+  basicReasonOf s this concl = do
+    lits <- getElems (atLeastLits this)
+    let n = atLeastNum this
+    case concl of
+      Nothing -> do
+        let f :: [Lit] -> IO Lit
+            f [] = error "AtLeastData.basicReasonOf: should not happen"
+            f (l:ls) = do
+              val <- litValue s l
+              if val == lFalse
+                then return l
+                else f ls
+        lit <- f (take n lits)
+        return $ lit : drop n lits
+      Just lit -> do
+        assert (lit `elem` take n lits) $ return ()
+        return $ drop n lits
+
+  toPBAtLeast _ this = do
+    lits <- getElems (atLeastLits this)
+    return ([(1,l) | l <- lits], fromIntegral (atLeastNum this))
+
+  isSatisfied solver this = do
+    lits <- getElems (atLeastLits this)
+    vals <- mapM (litValue solver) lits
+    return $ length [v | v <- vals, v == lTrue] >= atLeastNum this
+
+  constrActivity _ this = do
+    let act = atLeastActivity this
+    readIORef act
+
+  constrBumpActivity solver this = do
+    let act = atLeastActivity this
+    aval <- readIORef act
+    when (aval >= 0) $ do -- learnt clause
+      inc <- readIORef (svClaInc solver)
+      let aval2 = aval+inc
+      writeIORef act $! aval2
+      when (aval2 > 1e20) $
+        -- Rescale
+        constrRescaleAllActivity solver
+
+  constrRescaleActivity _ this = do
+    let act = atLeastActivity this
+    aval <- readIORef act
+    when (aval >= 0) $ writeIORef act $! (aval * 1e-20)
+
+instantiateAtLeast :: Solver -> ([Lit],Int) -> IO ([Lit],Int)
+instantiateAtLeast solver (xs,n) = loop ([],n) xs
+  where
+    loop :: ([Lit],Int) -> [Lit] -> IO ([Lit],Int)
+    loop ret [] = return ret
+    loop (ys,m) (l:ls) = do
+      val <- litValue solver l
+      if val == lTrue then
+         loop (ys, m-1) ls
+       else if val == lFalse then
+         loop (ys, m) ls
+       else
+         loop (l:ys, m) ls
+
+{--------------------------------------------------------------------
+  Pseudo Boolean Constraint
+--------------------------------------------------------------------}
+
+data PBAtLeastData
+  = PBAtLeastData
+  { pbTerms  :: !(LitMap Integer)
+  , pbDegree :: !Integer
+  , pbSlack  :: !(IORef Integer)
+  , pbActivity :: !(IORef Double)
+  , pbReasons :: !(IORef (LitMap [(Lit, Integer)]))
+  }
+  deriving Eq
+
+newPBAtLeastData :: [(Integer,Lit)] -> Integer -> Bool -> IO PBAtLeastData
+newPBAtLeastData ts degree learnt = do
+  let slack = sum (map fst ts) - degree
+      m = IM.fromList [(l,c) | (c,l) <- ts]
+  s <- newIORef slack
+  act <- newIORef $! (if learnt then 0 else -1)
+  rs <- newIORef IM.empty
+  return (PBAtLeastData m degree s act rs)
+
+instance Constraint PBAtLeastData where
+  toConstraint = ConstrPBAtLeast
+
+  showConstraint _ this = do
+    return $ show [(c,l) | (l,c) <- IM.toList (pbTerms this)] ++ " >= " ++ show (pbDegree this)
+
+  attach solver this = do
+    forM_ (IM.keys (pbTerms this)) $ \l -> watch solver l this
+    cs <- forM (IM.toList (pbTerms this)) $ \(l,c) -> do
+      v <- litValue solver l
+      if v == lFalse
+        then do
+          addBacktrackCB solver (litVar l) $ modifyIORef' (pbSlack this) (+ c)
+          return 0
+        else return c
+    writeIORef (pbSlack this) $! sum cs - pbDegree this
+
+  watchedLiterals _ this = do
+    return $ IM.keys $ pbTerms this
+
+  basicPropagate solver this this2 falsifiedLit = do
+    watch solver falsifiedLit this
+    let c = pbTerms this2 IM.! falsifiedLit
+    let slack = pbSlack this2
+    modifyIORef' slack (subtract c)
+    addBacktrackCB solver (litVar falsifiedLit) $ modifyIORef' slack (+ c)
+    pbPropagate solver this2
+
+  basicReasonOf solver this l = do
+    let m = pbTerms this
+    xs <-
+      case l of
+        Just lit -> do
+          -- 保存しておいたものを使わないと、
+          -- その後に割り当てられたものを含んでしまってまずいことがある。
+          rs <- readIORef (pbReasons this)
+          return $ sortBy (flip (comparing snd)) $ (rs IM.! lit)
+        Nothing -> do
+          -- 直接のコンフリクトの場合には現在のもので大丈夫なはず
+          tmp <- filterM (\(lit,_) -> liftM (lFalse ==) (litValue solver lit)) (IM.toList m)
+          return $ sortBy (flip (comparing snd)) $ tmp
+    let max_slack = sum (map snd $ IM.toList m) - pbDegree this
+    case l of
+      Nothing -> return $ f max_slack xs
+      Just lit -> return $ f (max_slack - (m IM.! lit)) xs
+    where
+      f :: Integer -> [(Lit,Integer)] -> [Lit]
+      f s xs = go s xs []
+
+      go :: Integer -> [(Lit,Integer)] -> [Lit] -> [Lit]
+      go s _ ret | s < 0 = ret
+      go _ [] _ = error "PBAtLeastData.basicReasonOf: should not happen"
+      go s ((lit,c):xs) ret = go (s - c) xs (lit:ret)
+
+  toPBAtLeast _ this = do
+    return ([(c,l) | (l,c) <- IM.toList (pbTerms this)], pbDegree this)
+
+  isSatisfied solver this = do
+    xs <- forM (IM.toList (pbTerms this)) $ \(l,c) -> do
+      v <- litValue solver l
+      if v == lTrue
+        then return c
+        else return 0
+    return $ sum xs >= pbDegree this
+
+  constrActivity _ this = do
+    let act = pbActivity this
+    readIORef act
+
+  constrBumpActivity solver this = do
+    let act = pbActivity this
+    aval <- readIORef act
+    when (aval >= 0) $ do -- learnt clause
+      inc <- readIORef (svClaInc solver)
+      let aval2 = aval+inc
+      writeIORef act $! aval2
+      when (aval2 > 1e20) $
+        -- Rescale
+        constrRescaleAllActivity solver
+
+  constrRescaleActivity _ this = do
+    let act = pbActivity this
+    aval <- readIORef act
+    when (aval >= 0) $ writeIORef act $! (aval * 1e-20)
+
+instantiatePB :: Solver -> ([(Integer,Lit)],Integer) -> IO ([(Integer,Lit)],Integer)
+instantiatePB solver (xs,n) = loop ([],n) xs
+  where
+    loop :: ([(Integer,Lit)],Integer) -> [(Integer,Lit)] -> IO ([(Integer,Lit)],Integer)
+    loop ret [] = return ret
+    loop (ys,m) ((c,l):ts) = do
+      val <- litValue solver l
+      if val == lTrue then
+         loop (ys, m-c) ts
+       else if val == lFalse then
+         loop (ys, m) ts
+       else
+         loop ((c,l):ys, m) ts
+
+pbPropagate :: Solver -> PBAtLeastData -> IO Bool
+pbPropagate solver this = do
+  let slack = pbSlack this
+  s <- readIORef slack
+  if s < 0
+    then return False
+    else do
+      ref <- newIORef Nothing
+      let m = do
+            x <- readIORef ref
+            case x of
+              Just r -> return r
+              Nothing -> do
+                let isFalse (l,_) = liftM (lFalse==) (litValue solver l)
+                r <- filterM isFalse $ IM.toAscList $ pbTerms this
+                writeIORef ref (Just r)
+                return r
+
+      forM_ (IM.toList (pbTerms this)) $ \(l1,c1) -> do
+        when (c1 > s) $ do
+          v <- litValue solver l1
+          when (v == lUndef) $ do
+            -- あとでbasicReasonOfで使うために、
+            -- その時点でfalseになっているリテラルを保存しておく
+            r <- m
+            modifyIORef (pbReasons this) (IM.insert l1 r)
+
+            assignBy solver l1 this
+            constrBumpActivity solver this
+            return ()
+
+      return True
+
+pbOverSAT :: Solver -> ([(Integer,Lit)],Integer) -> IO Bool
+pbOverSAT solver (lhs, rhs) = do
+  ss <- forM lhs $ \(c,l) -> do
+    v <- litValue solver l
+    if v /= lFalse
+      then return c
+      else return 0
+  return $! sum ss > rhs
+
+{--------------------------------------------------------------------
+  Restart strategy
+--------------------------------------------------------------------}
+
+data RestartStrategy = MiniSATRestarts | ArminRestarts | LubyRestarts
+  deriving (Show, Eq, Ord)
+
+mkRestartSeq :: RestartStrategy -> Int -> Double -> [Int]
+mkRestartSeq MiniSATRestarts = miniSatRestartSeq
+mkRestartSeq ArminRestarts   = arminRestartSeq
+mkRestartSeq LubyRestarts    = lubyRestartSeq
+
+miniSatRestartSeq :: Int -> Double -> [Int]
+miniSatRestartSeq start inc = iterate (ceiling . (inc *) . fromIntegral) start
+
+{-
+miniSatRestartSeq :: Int -> Double -> [Int]
+miniSatRestartSeq start inc = map round $ iterate (inc*) (fromIntegral start)
+-}
+
+arminRestartSeq :: Int -> Double -> [Int]
+arminRestartSeq start inc = go (fromIntegral start) (fromIntegral start)
+  where  
+    go !inner !outer = round inner : go inner' outer'
+      where
+        (inner',outer') = 
+          if inner >= outer
+          then (fromIntegral start, outer * inc)
+          else (inner * inc, outer)
+
+lubyRestartSeq :: Int -> Double -> [Int]
+lubyRestartSeq start inc = map (ceiling . (fromIntegral start *) . luby inc) [0..]
+
+{-
+  Finite subsequences of the Luby-sequence:
+
+  0: 1
+  1: 1 1 2
+  2: 1 1 2 1 1 2 4
+  3: 1 1 2 1 1 2 4 1 1 2 1 1 2 4 8
+  ...
+
+
+-}
+luby :: Double -> Integer -> Double
+luby y x = go2 size1 sequ1 x
+  where
+    -- Find the finite subsequence that contains index 'x', and the
+    -- size of that subsequence:
+    (size1, sequ1) = go 1 0
+
+    go :: Integer -> Integer -> (Integer, Integer)
+    go size sequ
+      | size < x+1 = go (2*size+1) (sequ+1)
+      | otherwise  = (size, sequ)
+
+    go2 :: Integer -> Integer -> Integer -> Double
+    go2 size sequ x2
+      | size-1 /= x2 = let size' = (size-1) `div` 2 in go2 size' (sequ - 1) (x2 `mod` size')
+      | otherwise = y ^ sequ
+
+
+{--------------------------------------------------------------------
+  utility
+--------------------------------------------------------------------}
+
+allM :: Monad m => (a -> m Bool) -> [a] -> m Bool
+allM p = go
+  where
+    go [] = return True
+    go (x:xs) = do
+      b <- p x
+      if b
+        then go xs
+        else return False
+
+anyM :: Monad m => (a -> m Bool) -> [a] -> m Bool
+anyM p = go
+  where
+    go [] = return False
+    go (x:xs) = do
+      b <- p x
+      if b
+        then return True
+        else go xs
+
+modifyIORef' :: IORef a -> (a -> a) -> IO ()
+modifyIORef' ref f = do
+  x <- readIORef ref
+  writeIORef ref $! f x
+
+gen :: [a] -> IO (IO a)
+gen xs = do
+  ref <- newIORef xs
+  return $ do
+    (y:ys) <- readIORef ref
+    writeIORef ref ys
+    return y
+
+{--------------------------------------------------------------------
+  debug
+--------------------------------------------------------------------}
+
+debugMode :: Bool
+debugMode = False
+
+checkSatisfied :: Solver -> IO ()
+checkSatisfied solver = do
+  cls <- readIORef (svClauseDB solver)
+  forM_ cls $ \c -> do
+    b <- isSatisfied solver c
+    unless b $ do
+      s <- showConstraint solver c
+      log solver $ "BUG: " ++ s ++ " is violated"
+
+sanityCheck :: Solver -> IO ()
+sanityCheck _ | not debugMode = return ()
+sanityCheck solver = do
+  cls <- readIORef (svClauseDB solver)
+  forM_ cls $ \constr -> do
+    lits <- watchedLiterals solver constr
+    forM_ lits $ \l -> do
+      ws <- watches solver l
+      unless (constr `elem` ws) $ error $ printf "sanityCheck:A:%s" (show lits)
+
+  vs <- variables solver
+  let lits = [l | v <- vs, l <- [literal v True, literal v False]]
+  forM_ lits $ \l -> do
+    cs <- watches solver l
+    forM_ cs $ \constr -> do
+      lits2 <- watchedLiterals solver constr
+      unless (l `elem` lits2) $ do
+        error $ printf "sanityCheck:C:%d %s" l (show lits2)
+
+dumpVarActivity :: Solver -> IO ()
+dumpVarActivity solver = do
+  log solver "Variable activity:"
+  vs <- variables solver
+  forM_ vs $ \v -> do
+    activity <- varActivity solver v
+    log solver $ printf "activity(%d) = %d" v activity
+
+dumpClaActivity :: Solver -> IO ()
+dumpClaActivity solver = do
+  log solver "Learnt clause activity:"
+  xs <- learntConstraints solver
+  forM_ xs $ \c -> do
+    s <- showConstraint solver c
+    aval <- constrActivity solver c
+    log solver $ printf "activity(%s) = %f" s aval
+
+-- | set callback function for receiving messages.
+setLogger :: Solver -> (String -> IO ()) -> IO ()
+setLogger solver logger = do
+  writeIORef (svLogger solver) (Just logger)
+
+log :: Solver -> String -> IO ()
+log solver msg = logIO solver (return msg)
+
+logIO :: Solver -> IO String -> IO ()
+logIO solver action = do
+  m <- readIORef (svLogger solver)
+  case m of
+    Nothing -> return ()
+    Just logger -> action >>= logger
diff --git a/src/SAT/Integer.hs b/src/SAT/Integer.hs
new file mode 100644
--- /dev/null
+++ b/src/SAT/Integer.hs
@@ -0,0 +1,61 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+module SAT.Integer where
+
+import Control.Monad
+import Data.Array.IArray
+import Text.Printf
+import SAT
+import Data.Linear
+
+data Expr = Expr [(Integer, SAT.Lit)] Integer
+
+newVar :: SAT.Solver -> Integer -> Integer -> IO Expr
+newVar solver lo hi = do
+  when (lo > hi) $ error $ printf "SAT.Integer.newVar: inconsistent bounds given [%d, %d]" lo hi
+  let hi' = hi - lo
+      bitWidth = head $ [w | w <- [1..], let mx = 2 ^ w - 1, hi' <= mx]
+  vs <- replicateM bitWidth (SAT.newVar solver)
+  let xs = zip (iterate (2*) 1) vs
+  SAT.addPBAtMost solver xs hi'
+  return $ Expr xs lo
+
+constant :: Integer -> Expr
+constant c = Expr [] c
+
+instance Module Integer Expr where
+  n .*. Expr xs c = Expr [(n*m,lit) | (m,lit) <- xs] (n*c)
+  Expr xs1 c1 .+. Expr xs2 c2 = Expr (xs1++xs2) (c1+c2)
+  lzero = Expr [] 0
+
+addLe :: SAT.Solver -> Expr -> Expr -> IO ()
+addLe solver lhs rhs = do
+  let Expr xs c = lhs .-. rhs
+  SAT.addPBAtMost solver xs (-c)
+
+addGe :: SAT.Solver -> Expr -> Expr -> IO ()
+addGe solver lhs rhs = do
+  let Expr xs c = lhs .-. rhs
+  SAT.addPBAtLeast solver xs (-c)
+
+addEq :: SAT.Solver -> Expr -> Expr -> IO ()
+addEq solver lhs rhs = do
+  let Expr xs c = lhs .-. rhs
+  SAT.addPBExactly solver xs (-c)
+
+addLeSoft :: SAT.Solver -> SAT.Lit -> Expr -> Expr -> IO ()
+addLeSoft solver ind lhs rhs = do
+  let Expr xs c = lhs .-. rhs
+  SAT.addPBAtMostSoft solver ind xs (-c)
+
+addGeSoft :: SAT.Solver -> SAT.Lit -> Expr -> Expr -> IO ()
+addGeSoft solver ind lhs rhs = do
+  let Expr xs c = lhs .-. rhs
+  SAT.addPBAtLeastSoft solver ind xs (-c)
+
+addEqSoft :: SAT.Solver -> SAT.Lit -> Expr -> Expr -> IO ()
+addEqSoft solver ind lhs rhs = do
+  let Expr xs c = lhs .-. rhs
+  SAT.addPBExactlySoft solver ind xs (-c)
+
+eval :: SAT.Model -> Expr -> Integer
+eval m (Expr ts c) = sum [if m ! SAT.litVar lit == SAT.litPolarity lit then n else 0 | (n,lit) <- ts] + c
diff --git a/src/SAT/Printer.hs b/src/SAT/Printer.hs
new file mode 100644
--- /dev/null
+++ b/src/SAT/Printer.hs
@@ -0,0 +1,75 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  SAT.Printer
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- Printing utilities.
+--
+-----------------------------------------------------------------------------
+module SAT.Printer
+  ( satPrintModel
+  , maxsatPrintModel
+  , pbPrintModel
+  ) where
+
+import Control.Monad
+import Data.Array.IArray
+import Data.List
+import System.IO
+import SAT.Types
+
+-- | Print a 'Model' in a way specified for SAT Competition.
+-- See <http://www.satcompetition.org/2011/rules.pdf> for details.
+satPrintModel :: Handle -> Model -> Int -> IO ()
+satPrintModel h m n = do
+  let as = if n > 0
+           then takeWhile (\(v,_) -> v <= n) $ assocs m
+           else assocs m
+  forM_ (split 10 as) $ \xs -> do
+    hPutStr h "v"
+    forM_ xs $ \(var,val) -> hPutStr h (' ': show (literal var val))
+    hPutStrLn h ""
+  hPutStrLn h "v 0"
+  hFlush h
+
+-- | Print a 'Model' in a way specified for Max-SAT Evaluation.
+-- See <http://maxsat.ia.udl.cat/requirements/> for details.
+maxsatPrintModel :: Handle -> Model -> Int -> IO ()
+maxsatPrintModel h m n = do
+  let as = if n > 0
+           then takeWhile (\(v,_) -> v <= n) $ assocs m
+           else assocs m
+  forM_ (split 10 as) $ \xs -> do
+    hPutStr h "v"
+    forM_ xs $ \(var,val) -> hPutStr h (' ' : show (literal var val))
+    hPutStrLn h ""
+  -- no terminating 0 is necessary
+  hFlush stdout
+
+-- | Print a 'Model' in a way specified for Pseudo-Boolean Competition.
+-- See <http://www.cril.univ-artois.fr/PB12/format.pdf> for details.
+pbPrintModel :: Handle -> Model -> Int -> IO ()
+pbPrintModel h m n = do
+  let as = if n > 0
+           then takeWhile (\(v,_) -> v <= n) $ assocs m
+           else assocs m
+  forM_ (split 10 as) $ \xs -> do
+    hPutStr h "v"
+    forM_ xs $ \(var,val) -> hPutStr h (" " ++ (if val then "" else "-") ++ "x" ++ show var)
+    hPutStrLn h ""
+  hFlush stdout
+
+-- ------------------------------------------------------------------------
+
+split :: Int -> [a] -> [[a]]
+split n = go
+  where
+    go [] = []
+    go xs =
+      case splitAt n xs of
+        (ys, zs) -> ys : go zs
diff --git a/src/SAT/TheorySolver.hs b/src/SAT/TheorySolver.hs
new file mode 100644
--- /dev/null
+++ b/src/SAT/TheorySolver.hs
@@ -0,0 +1,25 @@
+module SAT.TheorySolver
+  ( TheorySolver (..)
+  , emptyTheory
+  ) where
+
+import SAT.Types
+
+data TheorySolver =
+  TheorySolver
+  { thAssertLit :: (Lit -> IO Bool) -> Lit -> IO Bool
+  , thCheck     :: (Lit -> IO Bool) -> IO Bool
+  , thExplain   :: IO [Lit]
+  , thPushBacktrackPoint :: IO ()
+  , thPopBacktrackPoint  :: IO ()
+  }
+
+emptyTheory :: TheorySolver
+emptyTheory =
+  TheorySolver
+  { thAssertLit = \propagate lit -> return True
+  , thCheck = \propagate -> return True
+  , thExplain = error "should not happen"
+  , thPushBacktrackPoint = return ()
+  , thPopBacktrackPoint  = return ()
+  }
diff --git a/src/SAT/TseitinEncoder.hs b/src/SAT/TseitinEncoder.hs
new file mode 100644
--- /dev/null
+++ b/src/SAT/TseitinEncoder.hs
@@ -0,0 +1,200 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  SAT.TseitinEncoder
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+-- 
+-- Tseitin encoding
+--
+-- TODO:
+-- 
+-- * reduce variables.
+--
+-- References:
+--
+-- * [Tse83] G. Tseitin. On the complexity of derivation in propositional
+--   calculus. Automation of Reasoning: Classical Papers in Computational
+--   Logic, 2:466-483, 1983. Springer-Verlag. 
+--
+-- * [For60] R. Fortet. Application de l'algèbre de Boole en rechercheop
+--   opérationelle. Revue Française de Recherche Opérationelle, 4:17-26,
+--   1960. 
+--
+-- * [BM84a] E. Balas and J. B. Mazzola. Nonlinear 0-1 programming:
+--   I. Linearization techniques. Mathematical Programming, 30(1):1-21,
+--   1984.
+-- 
+-- * [BM84b] E. Balas and J. B. Mazzola. Nonlinear 0-1 programming:
+--   II. Dominance relations and algorithms. Mathematical Programming,
+--   30(1):22-45, 1984.
+-----------------------------------------------------------------------------
+module SAT.TseitinEncoder
+  (
+  -- * The @Encoder@ type
+    Encoder
+  , newEncoder
+  , setUsePB
+
+  -- * Encoding of boolean formula
+  , Formula (..)
+  , addFormula
+  , encodeConj
+  , encodeDisj
+  ) where
+
+import Control.Monad
+import Data.IORef
+import qualified Data.Map as Map
+import qualified Data.IntSet as IS
+import qualified SAT as SAT
+
+-- | Arbitrary formula not restricted to CNF
+data Formula
+  = Var SAT.Var
+  | And [Formula]
+  | Or [Formula]
+  | Not Formula
+  | Imply Formula Formula
+  | Equiv Formula Formula
+  deriving (Show, Eq, Ord)
+
+-- | Encoder instance
+data Encoder =
+  Encoder
+  { encSolver    :: SAT.Solver
+  , encUsePB     :: IORef Bool
+  , encConjTable :: !(IORef (Map.Map IS.IntSet SAT.Lit))
+  }
+
+-- | Create a @Encoder@ instance.
+newEncoder :: SAT.Solver -> IO Encoder
+newEncoder solver = do
+  usePBRef <- newIORef False
+  table <- newIORef Map.empty
+  return $
+    Encoder
+    { encSolver = solver
+    , encUsePB  = usePBRef
+    , encConjTable = table
+    }
+
+-- | Use /pseudo boolean constraints/ or use only /clauses/.
+setUsePB :: Encoder -> Bool -> IO ()
+setUsePB encoder usePB = writeIORef (encUsePB encoder) usePB
+
+-- | Assert a given formula to underlying SAT solver by using
+-- Tseitin encoding.
+addFormula :: Encoder -> Formula -> IO ()
+addFormula encoder formula = do
+  let solver = encSolver encoder
+  case formula of
+    And xs -> mapM_ (addFormula encoder) xs
+    Equiv a b -> do
+      lit1 <- encodeToLit encoder a
+      lit2 <- encodeToLit encoder b
+      SAT.addClause solver [SAT.litNot lit1, lit2] -- a→b
+      SAT.addClause solver [SAT.litNot lit2, lit1] -- b→a
+    Not (Not a)     -> addFormula encoder a
+    Not (Or xs)     -> addFormula encoder (And (map Not xs))
+    Not (Imply a b) -> addFormula encoder (And [a, Not b])
+    Not (Equiv a b) -> do
+      lit1 <- encodeToLit encoder a
+      lit2 <- encodeToLit encoder b
+      SAT.addClause solver [lit1, lit2] -- a ∨ b
+      SAT.addClause solver [SAT.litNot lit1, SAT.litNot lit2] -- ¬a ∨ ¬b
+    _ -> do
+      c <- encodeToClause encoder formula
+      SAT.addClause solver c
+
+encodeToClause :: Encoder -> Formula -> IO SAT.Clause
+encodeToClause encoder formula =
+  case formula of
+    And [x] -> encodeToClause encoder x
+    Or xs -> do
+      cs <- mapM (encodeToClause encoder) xs
+      return $ concat cs
+    Not (Not x)  -> encodeToClause encoder x
+    Not (And xs) -> do
+      encodeToClause encoder (Or (map Not xs))
+    Imply a b -> do
+      encodeToClause encoder (Or [Not a, b])
+    _ -> do
+      l <- encodeToLit encoder formula
+      return [l]
+
+encodeToLit :: Encoder -> Formula -> IO SAT.Lit
+encodeToLit encoder formula = do
+  let solver = encSolver encoder
+  case formula of
+    Var v -> return v
+    And xs -> do
+      v <- SAT.newVar solver
+      ls <- mapM (encodeToLit encoder) xs
+      addIsConjOf encoder v ls
+      return v
+    Or xs -> do
+      v <- SAT.newVar solver
+      ls <- mapM (encodeToLit encoder) xs
+      addIsDisjOf encoder v ls
+      return v
+    Not x -> do
+      lit <- encodeToLit encoder x
+      return $ SAT.litNot lit
+    Imply x y -> do
+      encodeToLit encoder (Or [Not x, y])
+    Equiv x y -> do
+      lit1 <- encodeToLit encoder x
+      lit2 <- encodeToLit encoder y
+      encodeToLit encoder $
+        And [ Imply (Var lit1) (Var lit2)
+            , Imply (Var lit2) (Var lit1)
+            ]
+        -- Varにリテラルを渡しているのは少し気持ち悪い
+
+-- | Return an literal which is equivalent to a given conjunction.
+encodeConj :: Encoder -> [SAT.Lit] -> IO SAT.Lit
+encodeConj _ [l] =  return l
+encodeConj encoder ls =  do
+  let ls2 = IS.fromList ls
+  table <- readIORef (encConjTable encoder)
+  case Map.lookup ls2 table of
+    Just l -> return l
+    Nothing -> do
+      let sat = encSolver encoder
+      v <- SAT.newVar sat
+      addIsConjOf encoder v ls
+      writeIORef (encConjTable encoder) (Map.insert ls2 v table)
+      return v
+
+-- | Return an literal which is equivalent to a given disjunction.
+encodeDisj :: Encoder -> [SAT.Lit] -> IO SAT.Lit
+encodeDisj _ [l] =  return l
+encodeDisj encoder ls = do
+  -- ¬l ⇔ ¬(¬l1 ∧ … ∧ ¬ln) ⇔ (l1 ∨ … ∨ ln)
+  l <- encodeConj encoder [SAT.litNot li | li <- ls]
+  return $ SAT.litNot l
+
+addIsConjOf :: Encoder -> SAT.Lit -> [SAT.Lit] -> IO ()
+addIsConjOf encoder l ls = do
+  let solver = encSolver encoder
+  usePB <- readIORef (encUsePB encoder)
+  if usePB
+   then do
+     -- ∀i.(l → li) ⇔ Σli >= n*l ⇔ Σli - n*l >= 0
+     let n = length ls
+     SAT.addPBAtLeast solver ((- fromIntegral n, l) : [(1,li) | li <- ls]) 0
+   else do
+     forM_ ls $ \li -> do
+       -- (l → li)  ⇔  (¬l ∨ li)
+       SAT.addClause solver [SAT.litNot l, li]
+  -- ((l1 ∧ l2 ∧ … ∧ ln) → l)  ⇔  (¬l1 ∨ ¬l2 ∨ … ∨ ¬ln ∨ l)
+  SAT.addClause solver (l : map SAT.litNot ls)
+
+addIsDisjOf :: Encoder -> SAT.Lit -> [SAT.Lit] -> IO ()
+addIsDisjOf encoder l ls =
+  addIsConjOf encoder (SAT.litNot l) [SAT.litNot li | li <- ls]
diff --git a/src/SAT/Types.hs b/src/SAT/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/SAT/Types.hs
@@ -0,0 +1,252 @@
+{-# LANGUAGE BangPatterns #-}
+module SAT.Types
+  (
+  -- * Variable
+    Var
+  , VarMap
+  , validVar
+
+  -- * Model
+  , Model
+
+  -- * Literal
+  , Lit
+  , LitSet
+  , LitMap
+  , litUndef
+  , validLit
+  , literal
+  , litNot
+  , litVar
+  , litPolarity
+  , evalLit
+
+  -- * Clause
+  , Clause
+  , normalizeClause
+
+  -- * Cardinality Constraint
+  , normalizeAtLeast
+
+  -- * Pseudo Boolean Constraint
+  , normalizePBAtLeast
+  , normalizePBExactly
+  , cutResolve
+  , cardinalityReduction
+  , negatePBAtLeast
+  , pbEval
+  , pbLowerBound
+  , pbUpperBound
+  ) where
+
+import Control.Monad
+import Control.Exception
+import Data.Array.Unboxed
+import Data.Ord
+import Data.List
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+import qualified Data.Set as Set
+
+-- | Variable is represented as positive integers (DIMACS format).
+type Var = Int
+
+type VarMap = IM.IntMap
+
+{-# INLINE validVar #-}
+validVar :: Var -> Bool
+validVar v = v > 0
+
+-- | A model is represented as a mapping from variables to its values.
+type Model = UArray Var Bool
+
+-- | Positive (resp. negative) literals are represented as positive (resp.
+-- negative) integers. (DIMACS format).
+type Lit = Int
+
+{-# INLINE litUndef #-}
+litUndef :: Lit
+litUndef = 0
+
+type LitSet = IS.IntSet
+type LitMap = IM.IntMap
+
+{-# INLINE validLit #-}
+validLit :: Lit -> Bool
+validLit l = l /= 0
+
+{-# INLINE literal #-}
+-- | Construct a literal from a variable and its polarity.
+-- 'True' (resp 'False') means positive (resp. negative) literal.
+literal :: Var  -- ^ variable
+        -> Bool -- ^ polarity
+        -> Lit
+literal v polarity =
+  assert (validVar v) $ if polarity then v else litNot v
+
+{-# INLINE litNot #-}
+-- | Negation of the 'Lit'.
+litNot :: Lit -> Lit
+litNot l = assert (validLit l) $ negate l
+
+{-# INLINE litVar #-}
+-- | Underlying variable of the 'Lit'
+litVar :: Lit -> Var
+litVar l = assert (validLit l) $ abs l
+
+{-# INLINE litPolarity #-}
+-- | Polarity of the 'Lit'.
+-- 'True' means positive literal and 'False' means negative literal.
+litPolarity :: Lit -> Bool
+litPolarity l = assert (validLit l) $ l > 0
+
+{-# INLINE evalLit #-}
+evalLit :: Model -> Lit -> Bool
+evalLit m l = if l > 0 then m ! l else not (m ! abs l)
+
+-- | Disjunction of 'Lit'.
+type Clause = [Lit]
+
+-- | Normalizing clause
+--
+-- 'Nothing' if the clause is trivially true.
+normalizeClause :: Clause -> Maybe Clause
+normalizeClause lits = assert (IS.size ys `mod` 2 == 0) $
+  if IS.null ys
+    then Just (IS.toList xs)
+    else Nothing
+  where
+    xs = IS.fromList lits
+    ys = xs `IS.intersection` (IS.map litNot xs)
+
+normalizeAtLeast :: ([Lit],Int) -> ([Lit],Int)
+normalizeAtLeast (lits,n) = assert (IS.size ys `mod` 2 == 0) $
+   (IS.toList lits', n')
+   where
+     xs = IS.fromList lits
+     ys = xs `IS.intersection` (IS.map litNot xs)
+     lits' = xs `IS.difference` ys
+     n' = n - (IS.size ys `div` 2)
+
+-- | normalizing PB constraint of the form /c1 x1 + c2 cn ... cn xn >= b/.
+normalizePBAtLeast :: ([(Integer,Lit)], Integer) -> ([(Integer,Lit)], Integer)
+normalizePBAtLeast a =
+　case step2 $ step1 $ a of
+    (xs,n)
+      | n > 0     -> step3 (saturate n xs, n)
+      | otherwise -> ([], 0) -- trivially true
+  where
+    -- 同じ変数が複数回現れないように、一度全部 @v@ に統一。
+    step1 :: ([(Integer,Lit)], Integer) -> ([(Integer,Lit)], Integer)
+    step1 (xs,n) =
+      case loop (IM.empty,n) xs of
+        (ys,n') -> ([(c,v) | (v,c) <- IM.toList ys], n')
+      where
+        loop :: (VarMap Integer, Integer) -> [(Integer,Lit)] -> (VarMap Integer, Integer)
+        loop (ys,m) [] = (ys,m)
+        loop (ys,m) ((c,l):zs) =
+          if litPolarity l
+            then loop (IM.insertWith (+) l c ys, m) zs
+            else loop (IM.insertWith (+) (litNot l) (negate c) ys, m-c) zs
+
+    -- 係数が0のものも取り除き、係数が負のリテラルを反転することで、
+    -- 係数が正になるようにする。
+    step2 :: ([(Integer,Lit)], Integer) -> ([(Integer,Lit)], Integer)
+    step2 (xs,n) = loop ([],n) xs
+      where
+        loop (ys,m) [] = (ys,m)
+        loop (ys,m) (t@(c,l):zs)
+          | c == 0 = loop (ys,m) zs
+          | c < 0  = loop ((negate c,litNot l):ys, m-c) zs
+          | otherwise = loop (t:ys,m) zs
+
+    -- degree以上の係数はそこで抑える。
+    saturate :: Integer -> [(Integer,Lit)] -> [(Integer,Lit)]
+    saturate n xs = [assert (c>0) (min n c, l) | (c,l) <- xs]
+
+    -- omega test と同様の係数の gcd による単純化
+    step3 :: ([(Integer,Lit)], Integer) -> ([(Integer,Lit)], Integer)
+    step3 ([],n) = ([],n)
+    step3 (xs,n) = ([(c `div` d, l) | (c,l) <- xs], (n+d-1) `div` d)
+      where
+        d = foldl1' gcd [c | (c,_) <- xs]
+
+-- | normalizing PB constraint of the form /c1 x1 + c2 cn ... cn xn = b/.
+normalizePBExactly :: ([(Integer,Lit)], Integer) -> ([(Integer,Lit)], Integer)
+normalizePBExactly a =
+　case step2 $ step1 $ a of
+    (xs,n)
+      | n >= 0    -> step3 (xs, n)
+      | otherwise -> ([], 1) -- false
+  where
+    -- 同じ変数が複数回現れないように、一度全部 @v@ に統一。
+    step1 :: ([(Integer,Lit)], Integer) -> ([(Integer,Lit)], Integer)
+    step1 (xs,n) =
+      case loop (IM.empty,n) xs of
+        (ys,n') -> ([(c,v) | (v,c) <- IM.toList ys], n')
+      where
+        loop :: (VarMap Integer, Integer) -> [(Integer,Lit)] -> (VarMap Integer, Integer)
+        loop (ys,m) [] = (ys,m)
+        loop (ys,m) ((c,l):zs) =
+          if litPolarity l
+            then loop (IM.insertWith (+) l c ys, m) zs
+            else loop (IM.insertWith (+) (litNot l) (negate c) ys, m-c) zs
+
+    -- 係数が0のものも取り除き、係数が負のリテラルを反転することで、
+    -- 係数が正になるようにする。
+    step2 :: ([(Integer,Lit)], Integer) -> ([(Integer,Lit)], Integer)
+    step2 (xs,n) = loop ([],n) xs
+      where
+        loop (ys,m) [] = (ys,m)
+        loop (ys,m) (t@(c,l):zs)
+          | c == 0 = loop (ys,m) zs
+          | c < 0  = loop ((negate c,litNot l):ys, m-c) zs
+          | otherwise = loop (t:ys,m) zs
+
+    -- omega test と同様の係数の gcd による単純化
+    step3 :: ([(Integer,Lit)], Integer) -> ([(Integer,Lit)], Integer)
+    step3 ([],n) = ([],n)
+    step3 (xs,n)
+      | n `mod` d == 0 = ([(c `div` d, l) | (c,l) <- xs], n `div` d)
+      | otherwise      = ([], 1) -- false
+      where
+        d = foldl1' gcd [c | (c,_) <- xs]
+
+cutResolve :: ([(Integer,Lit)],Integer) -> ([(Integer,Lit)],Integer) -> Var -> ([(Integer,Lit)],Integer)
+cutResolve (lhs1,rhs1) (lhs2,rhs2) v = assert (l1 == litNot l2) $ normalizePBAtLeast pb
+  where
+    (c1,l1) = head [(c,l) | (c,l) <- lhs1, litVar l == v]
+    (c2,l2) = head [(c,l) | (c,l) <- lhs2, litVar l == v]
+    g = gcd c1 c2
+    s1 = c2 `div` g
+    s2 = c1 `div` g
+    pb = ([(s1*c,l) | (c,l) <- lhs1] ++ [(s2*c,l) | (c,l) <- lhs2], s1*rhs1 + s2 * rhs2)
+
+cardinalityReduction :: ([(Integer,Lit)],Integer) -> ([Lit],Int)
+cardinalityReduction (lhs,rhs) = (ls, rhs')
+  where
+    rhs' = go1 0 0 (sortBy (flip (comparing fst)) lhs)
+
+    go1 !s !k ((a,_):ts)
+      | s < rhs   = go1 (s+a) (k+1) ts
+      | otherwise = k
+    go1 _ _ [] = error "cardinalityReduction: should not happen"
+
+    ls = go2 (minimum (rhs : map (subtract 1 . fst) lhs)) (sortBy (comparing fst) lhs)
+
+    go2 !guard' ((a,_) : ts)
+      | a - 1 < guard' = go2 (guard' - a) ts
+      | otherwise      = map snd ts
+    go2 _ [] = error "cardinalityReduction: should not happen"
+
+negatePBAtLeast :: ([(Integer, Lit)], Integer) -> ([(Integer, Lit)], Integer)
+negatePBAtLeast (xs, rhs) = ([(-c,lit) | (c,lit)<-xs] , -rhs + 1)
+
+pbEval :: Model -> [(Integer, Lit)] -> Integer
+pbEval m xs = sum [c | (c,lit) <- xs, evalLit m lit]
+
+pbLowerBound :: [(Integer, Lit)] -> Integer
+pbLowerBound xs = sum [if c < 0 then c else 0 | (c,_) <- xs]
+
+pbUpperBound :: [(Integer, Lit)] -> Integer
+pbUpperBound xs = sum [if c > 0 then c else 0 | (c,_) <- xs]
diff --git a/src/Simplex.hs b/src/Simplex.hs
new file mode 100644
--- /dev/null
+++ b/src/Simplex.hs
@@ -0,0 +1,307 @@
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Simplex
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (ScopedTypeVariables)
+--
+-- Naïve implementation of Simplex method
+-- 
+-- Reference:
+--
+-- * <http://www.math.cuhk.edu.hk/~wei/lpch3.pdf>
+--
+-----------------------------------------------------------------------------
+module Simplex
+  ( module Data.OptDir
+  , Tableau
+  , RowIndex
+  , ColIndex
+  , Row
+  , PivotResult
+  , objRow
+  , pivot
+  , lookupRow
+  , setRow
+  , setObjFun
+  , currentObjValue
+  , simplex
+  , dualSimplex
+  , phaseI
+  , toCSV
+  ) where
+
+import Data.Ord
+import Data.List (intersperse, minimumBy, foldl')
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+import Data.OptDir
+import Control.Exception
+
+import Data.Expr
+import Data.Linear
+import qualified Data.LA as LA
+
+-- ---------------------------------------------------------------------------
+
+type Tableau r = VarMap (Row r)
+{-
+tbl ! v == (m, val)
+==>
+var v .+. m .==. constant val
+-}
+
+type RowIndex = Int
+type ColIndex = Int
+type Row r = (VarMap r, r)
+data PivotResult r = PivotUnbounded | PivotFinished | PivotSuccess (Tableau r)
+  deriving (Show, Eq, Ord)
+
+objRow :: RowIndex
+objRow = -1
+
+pivot :: (Fractional r, Eq r) => RowIndex -> ColIndex -> Tableau r -> Tableau r
+{-# INLINE pivot #-}
+{-# SPECIALIZE pivot :: RowIndex -> ColIndex -> Tableau Rational -> Tableau Rational #-}
+{-# SPECIALIZE pivot :: RowIndex -> ColIndex -> Tableau Double -> Tableau Double #-}
+pivot r s tbl =
+    assert (validTableau tbl) $  -- precondition
+    assert (validTableau tbl') $ -- postcondition
+      tbl'
+  where
+    tbl' = IM.insert s row_s $ IM.map f $ IM.delete r $ tbl
+    f orig@(row_i, row_i_val) =
+      case IM.lookup s row_i of
+        Nothing -> orig
+        Just c ->
+          ( IM.filter (0/=) $ IM.unionWith (+) (IM.delete s row_i) (IM.map (negate c *) row_r')
+          , row_i_val - c*row_r_val'
+          )
+    (row_r, row_r_val) = lookupRow r tbl
+    a_rs = row_r IM.! s
+    row_r' = IM.map (/ a_rs) $ IM.insert r 1 $ IM.delete s row_r
+    row_r_val' = row_r_val / a_rs
+    row_s = (row_r', row_r_val')
+
+lookupRow :: RowIndex -> Tableau r -> Row r
+lookupRow r m = m IM.! r
+
+-- 行の基底変数の列が0になるように変形
+normalizeRow :: (Num r, Eq r) => Tableau r -> Row r -> Row r
+normalizeRow a (row0,val0) = obj'
+  where
+    obj' = g $ foldl' f (IM.empty, val0) $ 
+           [ case IM.lookup j a of
+               Nothing -> (IM.singleton j x, 0)
+               Just (row,val) -> (IM.map ((-x)*) (IM.delete j row), -x*val)
+           | (j,x) <- IM.toList row0 ]
+    f (m1,v1) (m2,v2) = (IM.unionWith (+) m1 m2, v1+v2)
+    g (m,v) = (IM.filter (0/=) m, v)
+
+setRow :: (Num r, Eq r) => RowIndex -> Tableau r -> Row r -> Tableau r
+setRow i tbl row = assert (validTableau tbl) $ assert (validTableau tbl') $ tbl'
+  where
+    tbl' = IM.insert i (normalizeRow tbl row) tbl
+
+setObjFun :: (Num r, Eq r) => Tableau r -> LA.Expr r -> Tableau r
+setObjFun tbl e = setRow objRow tbl row
+  where
+    row =
+      case LA.extract LA.unitVar e of
+        (c, e') -> (LA.coeffMap (lnegate e'), c)
+
+copyObjRow :: (Num r, Eq r) => Tableau r -> Tableau r -> Tableau r
+copyObjRow from to =
+  case IM.lookup objRow from of
+    Nothing -> IM.delete objRow to
+    Just row -> setRow objRow to row
+
+currentObjValue :: (Num r, Eq r) => Tableau r -> r
+currentObjValue = snd . lookupRow objRow
+
+validTableau :: Tableau r -> Bool
+validTableau tbl =
+  and [v `IM.notMember` m | (v, (m,_)) <- IM.toList tbl, v /= objRow] &&
+  and [IS.null (IM.keysSet m `IS.intersection` vs) | (m,_) <- IM.elems tbl']
+  where
+    tbl' = IM.delete objRow tbl
+    vs = IM.keysSet tbl' 
+
+isFeasible :: Real r => Tableau r -> Bool
+isFeasible tbl = 
+  and [val >= 0 | (v, (_,val)) <- IM.toList tbl, v /= objRow]
+
+isOptimal :: Real r => OptDir -> Tableau r -> Bool
+isOptimal optdir tbl =
+  and [not (cmp cj) | cj <- IM.elems (fst (lookupRow objRow tbl))]
+  where
+    cmp = case optdir of
+            OptMin -> (0<)
+            OptMax -> (0>)
+
+isImproving :: Real r => OptDir -> Tableau r -> Tableau r -> Bool
+isImproving OptMin from to = currentObjValue to <= currentObjValue from 
+isImproving OptMax from to = currentObjValue to >= currentObjValue from 
+
+-- ---------------------------------------------------------------------------
+-- primal simplex
+
+simplex :: (Real r, Fractional r) => OptDir -> Tableau r -> (Bool, Tableau r)
+{-# SPECIALIZE simplex :: OptDir -> Tableau Rational -> (Bool, Tableau Rational) #-}
+{-# SPECIALIZE simplex :: OptDir -> Tableau Double -> (Bool, Tableau Double) #-}
+simplex optdir = go
+  where
+    go tbl = assert (isFeasible tbl) $
+      case primalPivot optdir tbl of
+        PivotFinished  -> assert (isOptimal optdir tbl) (True, tbl)
+        PivotUnbounded -> (False, tbl)
+        PivotSuccess tbl' -> assert (isImproving optdir tbl tbl') $ go tbl'
+
+primalPivot :: (Real r, Fractional r) => OptDir -> Tableau r -> PivotResult r
+{-# INLINE primalPivot #-}
+primalPivot optdir tbl
+  | null cs   = PivotFinished
+  | null rs   = PivotUnbounded
+  | otherwise = PivotSuccess (pivot r s tbl)
+  where
+    cmp = case optdir of
+            OptMin -> (0<)
+            OptMax -> (0>)
+    cs = [(j,cj) | (j,cj) <- IM.toList (fst (lookupRow objRow tbl)), cmp cj]
+    -- smallest subscript rule
+    s = fst $ head cs
+    -- classical rule
+    --s = fst $ (if optdir==OptMin then maximumBy else minimumBy) (compare `on` snd) cs
+    rs = [ (i, y_i0 / y_is)
+         | (i, (row_i, y_i0)) <- IM.toList tbl, i /= objRow
+         , let y_is = IM.findWithDefault 0 s row_i, y_is > 0
+         ]
+    r = fst $ minimumBy (comparing snd) rs
+
+-- ---------------------------------------------------------------------------
+-- dual simplex
+
+dualSimplex :: (Real r, Fractional r) => OptDir -> Tableau r -> (Bool, Tableau r)
+{-# SPECIALIZE dualSimplex :: OptDir -> Tableau Rational -> (Bool, Tableau Rational) #-}
+{-# SPECIALIZE dualSimplex :: OptDir -> Tableau Double -> (Bool, Tableau Double) #-}
+dualSimplex optdir = go
+  where
+    go tbl = assert (isOptimal optdir tbl) $
+      case dualPivot optdir tbl of
+        PivotFinished  -> assert (isFeasible tbl) $ (True, tbl)
+        PivotUnbounded -> (False, tbl)
+        PivotSuccess tbl' -> assert (isImproving optdir tbl' tbl) $ go tbl'
+
+dualPivot :: (Real r, Fractional r) => OptDir -> Tableau r -> PivotResult r
+{-# INLINE dualPivot #-}
+dualPivot optdir tbl
+  | null rs   = PivotFinished
+  | null cs   = PivotUnbounded
+  | otherwise = PivotSuccess (pivot r s tbl)
+  where
+    rs = [(i, row_i) | (i, (row_i, y_i0)) <- IM.toList tbl, i /= objRow, 0 > y_i0]
+    (r, row_r) = head rs
+    cs = [ (j, if optdir==OptMin then y_0j / y_rj else - y_0j / y_rj)
+         | (j, y_rj) <- IM.toList row_r
+         , y_rj < 0
+         , let y_0j = IM.findWithDefault 0 j obj
+         ]
+    s = fst $ minimumBy (comparing snd) cs
+    (obj,_) = lookupRow objRow tbl
+
+-- ---------------------------------------------------------------------------
+-- phase I of the two-phased method
+
+phaseI :: (Real r, Fractional r) => Tableau r -> VarSet -> (Bool, Tableau r)
+{-# SPECIALIZE phaseI :: Tableau Rational -> VarSet -> (Bool, Tableau Rational) #-}
+{-# SPECIALIZE phaseI :: Tableau Double -> VarSet -> (Bool, Tableau Double) #-}
+phaseI tbl avs
+  | currentObjValue tbl1' /= 0 = (False, tbl1')
+  | otherwise = (True, copyObjRow tbl $ removeArtificialVariables avs $ tbl1')
+  where
+    optdir = OptMax
+    tbl1 = setObjFun tbl $ lnegate $ lsum [LA.var v | v <- IS.toList avs]
+    tbl1' = go tbl1
+    go tbl2
+      | currentObjValue tbl2 == 0 = tbl2
+      | otherwise = 
+        case primalPivot optdir tbl2 of
+          PivotSuccess tbl2' -> assert (isImproving optdir tbl2 tbl2') $ go tbl2'
+          PivotFinished -> assert (isOptimal optdir tbl2) tbl2
+          PivotUnbounded -> error "phaseI: should not happen"
+
+-- post-processing of phaseI
+-- pivotを使ってartificial variablesを基底から除いて、削除
+removeArtificialVariables :: (Real r, Fractional r) => VarSet -> Tableau r -> Tableau r
+removeArtificialVariables avs tbl0 = tbl2
+  where
+    tbl1 = foldl' f (IM.delete objRow tbl0) (IS.toList avs)
+    tbl2 = IM.map (\(row,val) ->  (IM.filterWithKey (\j _ -> j `IS.notMember` avs) row, val)) tbl1
+    f tbl i =
+      case IM.lookup i tbl of
+        Nothing -> tbl
+        Just row ->
+          case [j | (j,c) <- IM.toList (fst row), c /= 0, j `IS.notMember` avs] of
+            [] -> IM.delete i tbl
+            j:_ -> pivot i j tbl
+
+
+-- ---------------------------------------------------------------------------
+
+toCSV :: (Num r, Eq r, Show r) => (r -> String) -> Tableau r -> String
+toCSV showCell tbl = unlines . map (concat . intersperse ",") $ header : body
+  where
+    header :: [String]
+    header = "" : map colName cols ++ [""]
+
+    body :: [[String]]
+    body = [showRow i (Simplex.lookupRow i tbl) | i <- rows]
+
+    rows :: [Simplex.RowIndex]
+    rows = IM.keys (IM.delete Simplex.objRow tbl) ++ [Simplex.objRow]
+
+    cols :: [Simplex.ColIndex]
+    cols = [0..colMax]
+      where
+        colMax = maximum (-1 : [c | (row, _) <- IM.elems tbl, c <- IM.keys row])
+
+    rowName :: RowIndex -> String
+    rowName i = if i==Simplex.objRow then "obj" else "x" ++ show i
+
+    colName :: ColIndex -> String
+    colName j = "x" ++ show j
+
+    showRow i (row, row_val) = rowName i : [showCell (IM.findWithDefault 0 j row') | j <- cols] ++ [showCell row_val]
+      where row' = IM.insert i 1 row
+
+-- ---------------------------------------------------------------------------
+
+-- 退化して巡回の起こるKuhnの7変数3制約の例
+
+kuhn_7_3 :: Tableau Rational
+kuhn_7_3 = IM.fromList
+  [ (1, (IM.fromList [(4,-2), (5,-9), (6,1), (7,9)],       0))
+  , (2, (IM.fromList [(4,1/3), (5,1), (6,-1/3), (7,-2)],   0))
+  , (3, (IM.fromList [(4,2), (5,3), (6,-1), (7,-12)],      2))
+  , (objRow, (IM.fromList [(4,2), (5,3), (6,-1), (7,-12)], 0))
+  ]
+
+test_kuhn_7_3 = simplex OptMin kuhn_7_3
+
+-- from http://www.math.cuhk.edu.hk/~wei/lpch5.pdf
+example_5_7 :: Tableau Rational
+example_5_7 = IM.fromList
+  [ (4, (IM.fromList [(1,-1), (2,-2), (3,-3)], -5))
+  , (5, (IM.fromList [(1,-2), (2,-2), (3,-1)], -6))
+  , (objRow, (IM.fromList [(1,3),(2,4),(3,5)], 0))
+  ]
+
+test_example_5_7 = dualSimplex OptMax example_5_7
+-- optimal value should be -11
+
+-- ---------------------------------------------------------------------------
diff --git a/src/Simplex2.hs b/src/Simplex2.hs
new file mode 100644
--- /dev/null
+++ b/src/Simplex2.hs
@@ -0,0 +1,1014 @@
+{-# LANGUAGE DoAndIfThenElse, TypeSynonymInstances, FlexibleContexts, FlexibleInstances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Simplex2
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (DoAndIfThenElse, TypeSynonymInstances, FlexibleContexts, FlexibleInstances)
+--
+-- Naïve implementation of Simplex method
+-- 
+-- Reference:
+--
+-- * <http://www.math.cuhk.edu.hk/~wei/lpch3.pdf>
+-- 
+-- * Bruno Dutertre and Leonardo de Moura.
+--   A Fast Linear-Arithmetic Solver for DPLL(T).
+--   Computer Aided Verification In Computer Aided Verification, Vol. 4144 (2006), pp. 81-94.
+--   <http://yices.csl.sri.com/cav06.pdf>
+--
+-- * Bruno Dutertre and Leonardo de Moura.
+--   Integrating Simplex with DPLL(T).
+--   CSL Technical Report SRI-CSL-06-01. 2006.
+--   <http://yices.csl.sri.com/sri-csl-06-01.pdf>
+--
+-----------------------------------------------------------------------------
+module Simplex2
+  (
+  -- * The @Solver@ type
+    Solver
+  , GenericSolver
+  , SolverValue (..)
+  , newSolver
+  , cloneSolver
+
+  -- * Problem specification
+  , Var
+  , newVar
+  , RelOp (..)
+  , (.<=.), (.>=.), (.==.), (.<.), (.>.)
+  , Atom (..)
+  , assertAtom
+  , assertAtomEx
+  , assertLower
+  , assertUpper
+  , setObj
+  , OptDir (..)
+  , setOptDir
+  , getOptDir
+
+  -- * Solving
+  , check
+  , Options (..)
+  , defaultOptions
+  , OptResult (..)
+  , optimize
+  , dualSimplex
+
+  -- * Extract results
+  , Model
+  , model
+  , RawModel
+  , rawModel
+  , getValue
+  , getObjValue
+
+  -- * Reading status
+  , getTableau
+  , getRow
+  , getCol
+  , getCoeff
+  , nVars
+  , isBasicVariable
+  , isNonBasicVariable
+  , isFeasible
+  , isOptimal
+  , getLB
+  , getUB
+
+  -- * Configulation
+  , setLogger
+  , clearLogger
+  , PivotStrategy (..)
+  , setPivotStrategy
+
+  -- * Debug
+  , dump
+  ) where
+
+import Prelude hiding (log)
+import Control.Exception
+import Control.Monad
+import Data.Ord
+import Data.IORef
+import Data.List
+import Data.Maybe
+import Data.Ratio
+import qualified Data.Map as Map
+import qualified Data.IntMap as IM
+import Text.Printf
+import Data.OptDir
+import System.CPUTime
+
+import qualified Data.LA as LA
+import Data.LA (Atom (..))
+import qualified Data.Formula as F
+import Data.Formula (RelOp (..), (.<=.), (.>=.), (.==.), (.<.), (.>.))
+import Data.Linear
+import Data.Delta
+import Util (showRational)
+
+{--------------------------------------------------------------------
+  The @Solver@ type
+--------------------------------------------------------------------}
+
+type Var = Int
+
+data GenericSolver v
+  = GenericSolver
+  { svTableau :: !(IORef (IM.IntMap (LA.Expr Rational)))
+  , svLB      :: !(IORef (IM.IntMap v))
+  , svUB      :: !(IORef (IM.IntMap v))
+  , svModel   :: !(IORef (IM.IntMap v))
+  , svVCnt    :: !(IORef Int)
+  , svOk      :: !(IORef Bool)
+  , svOptDir  :: !(IORef OptDir)
+
+  , svDefDB  :: !(IORef (Map.Map (LA.Expr Rational) Var))
+
+  , svLogger :: !(IORef (Maybe (String -> IO ())))
+  , svPivotStrategy :: !(IORef PivotStrategy)
+  , svNPivot  :: !(IORef Int)
+  }
+
+type Solver = GenericSolver Rational
+
+-- special basic variable
+objVar :: Int
+objVar = -1
+
+newSolver :: SolverValue v => IO (GenericSolver v)
+newSolver = do
+  t <- newIORef (IM.singleton objVar lzero)
+  l <- newIORef IM.empty
+  u <- newIORef IM.empty
+  m <- newIORef (IM.singleton objVar lzero)
+  v <- newIORef 0
+  ok <- newIORef True
+  dir <- newIORef OptMin
+  defs <- newIORef Map.empty
+  logger <- newIORef Nothing
+  pivot <- newIORef PivotStrategyBlandRule
+  npivot <- newIORef 0
+  return $
+    GenericSolver
+    { svTableau = t
+    , svLB      = l
+    , svUB      = u
+    , svModel   = m
+    , svVCnt    = v
+    , svOk      = ok
+    , svOptDir  = dir
+    , svDefDB   = defs
+    , svLogger  = logger
+    , svNPivot  = npivot
+    , svPivotStrategy = pivot
+    }
+
+cloneSolver :: GenericSolver v -> IO (GenericSolver v)
+cloneSolver solver = do
+  t      <- newIORef =<< readIORef (svTableau solver)
+  l      <- newIORef =<< readIORef (svLB solver)
+  u      <- newIORef =<< readIORef (svUB solver)
+  m      <- newIORef =<< readIORef (svModel solver)
+  v      <- newIORef =<< readIORef (svVCnt solver)
+  ok     <- newIORef =<< readIORef (svOk solver)
+  dir    <- newIORef =<< readIORef (svOptDir solver)
+  defs   <- newIORef =<< readIORef (svDefDB solver)
+  logger <- newIORef =<< readIORef (svLogger solver)
+  pivot  <- newIORef =<< readIORef (svPivotStrategy solver)
+  npivot <- newIORef =<< readIORef (svNPivot solver)
+  return $
+    GenericSolver
+    { svTableau = t
+    , svLB      = l
+    , svUB      = u
+    , svModel   = m
+    , svVCnt    = v
+    , svOk      = ok
+    , svOptDir  = dir
+    , svDefDB   = defs
+    , svLogger  = logger
+    , svNPivot  = npivot
+    , svPivotStrategy = pivot
+    }  
+
+class (Linear Rational v, Ord v) => SolverValue v where
+  toValue :: Rational -> v
+  showValue :: Bool -> v -> String
+  model :: GenericSolver v -> IO Model
+
+instance SolverValue Rational where
+  toValue = id
+  showValue = showRational
+  model = rawModel
+
+instance SolverValue (Delta Rational) where
+  toValue = fromReal
+  showValue = showDelta
+  model solver = do
+    xs <- variables solver
+    ys <- liftM concat $ forM xs $ \x -> do
+      Delta p q  <- getValue solver x
+      lb <- getLB solver x
+      ub <- getUB solver x
+      return $
+        [(p - c) / (k - q) | Just (Delta c k) <- return lb, c < p, k > q] ++
+        [(d - p) / (q - h) | Just (Delta d h) <- return ub, p < d, q > h]
+    let delta0 :: Rational
+        delta0 = if null ys then 0.1 else minimum ys
+        f :: Delta Rational -> Rational
+        f (Delta r k) = r + k * delta0
+    liftM (IM.map f) $ readIORef (svModel solver)
+
+{-
+Largest coefficient rule: original rule suggested by G. Dantzig.
+Largest increase rule: computationally more expensive in comparison with Largest coefficient, but locally maximizes the progress.
+Steepest edge rule: best pivot rule in practice, an efficient approximate implementation is "Devex".
+Bland’s rule: avoids cycling but one of the slowest rules.
+Random edge rule: Randomized have lead to the current best provable bounds for the number of pivot steps of the simplex method.
+Lexicographic rule: used for avoiding cyclying.
+-}
+data PivotStrategy
+  = PivotStrategyBlandRule
+  | PivotStrategyLargestCoefficient
+--  | PivotStrategySteepestEdge
+  deriving (Eq, Ord, Enum, Show, Read)
+
+setPivotStrategy :: GenericSolver v -> PivotStrategy -> IO ()
+setPivotStrategy solver ps = writeIORef (svPivotStrategy solver) ps
+
+{--------------------------------------------------------------------
+  problem description
+--------------------------------------------------------------------}
+
+newVar :: SolverValue v => GenericSolver v -> IO Var
+newVar solver = do
+  v <- readIORef (svVCnt solver)
+  writeIORef (svVCnt solver) $! v+1
+  modifyIORef (svModel solver) (IM.insert v lzero)
+  return v
+
+assertAtom :: Solver -> LA.Atom Rational -> IO ()
+assertAtom solver atom = do
+  (v,op,rhs') <- simplifyAtom solver atom
+  case op of
+    F.Le  -> assertUpper solver v (toValue rhs')
+    F.Ge  -> assertLower solver v (toValue rhs')
+    F.Eql -> do
+      assertLower solver v (toValue rhs')
+      assertUpper solver v (toValue rhs')
+    _ -> error "unsupported"
+  return ()
+
+assertAtomEx :: GenericSolver (Delta Rational) -> LA.Atom Rational -> IO ()
+assertAtomEx solver atom = do
+  (v,op,rhs') <- simplifyAtom solver atom
+  case op of
+    F.Le  -> assertUpper solver v (toValue rhs')
+    F.Ge  -> assertLower solver v (toValue rhs')
+    F.Lt  -> assertUpper solver v (toValue rhs' .-. delta)
+    F.Gt  -> assertLower solver v (toValue rhs' .+. delta)
+    F.Eql -> do
+      assertLower solver v (toValue rhs')
+      assertUpper solver v (toValue rhs')
+  return ()
+
+simplifyAtom :: SolverValue v => GenericSolver v -> LA.Atom Rational -> IO (Var, F.RelOp, Rational)
+simplifyAtom solver (LA.Atom lhs op rhs) = do
+  let (lhs',rhs') =
+        case LA.extract LA.unitVar (lhs .-. rhs) of
+          (n,e) -> (e, -n)
+  case LA.terms lhs' of
+    [(1,v)] -> return (v, op, rhs')
+    [(-1,v)] -> return (v, F.flipOp op, -rhs')
+    _ -> do
+      defs <- readIORef (svDefDB solver)
+      let (c,lhs'') = scale lhs' -- lhs' = lhs'' / c = rhs'
+          rhs'' = c .*. rhs'
+          op''  = if c < 0 then F.flipOp op else op
+      case Map.lookup lhs'' defs of
+        Just v -> do
+          return (v,op'',rhs'')
+        Nothing -> do
+          v <- newVar solver
+          setRow solver v lhs''
+          modifyIORef (svDefDB solver) $ Map.insert lhs'' v
+          return (v,op'',rhs'')
+  where
+    scale :: LA.Expr Rational -> (Rational, LA.Expr Rational)
+    scale e = (c, c .*. e)
+      where
+        c = c1 * c2
+        c1 = fromIntegral $ foldl' lcm 1 [denominator c | (c, _) <- LA.terms e]
+        c2 = signum $ head ([c | (c,x) <- LA.terms e] ++ [1])
+
+assertLower :: SolverValue v => GenericSolver v -> Var -> v -> IO ()
+assertLower solver x l = do
+  l0 <- getLB solver x
+  u0 <- getUB solver x
+  case (l0,u0) of 
+    (Just l0', _) | l <= l0' -> return ()
+    (_, Just u0') | u0' < l -> markBad solver
+    _ -> do
+      modifyIORef (svLB solver) (IM.insert x l)
+      b <- isNonBasicVariable solver x
+      v <- getValue solver x
+      when (b && not (l <= v)) $ update solver x l
+      checkNBFeasibility solver
+
+assertUpper :: SolverValue v => GenericSolver v -> Var -> v -> IO ()
+assertUpper solver x u = do
+  l0 <- getLB solver x
+  u0 <- getUB solver x
+  case (l0,u0) of 
+    (_, Just u0') | u0' <= u -> return ()
+    (Just l0', _) | u < l0' -> markBad solver
+    _ -> do
+      modifyIORef (svUB solver) (IM.insert x u)
+      b <- isNonBasicVariable solver x
+      v <- getValue solver x
+      when (b && not (v <= u)) $ update solver x u
+      checkNBFeasibility solver
+
+-- FIXME: 式に定数項が含まれる可能性を考えるとこれじゃまずい?
+setObj :: SolverValue v => GenericSolver v -> LA.Expr Rational -> IO ()
+setObj solver e = setRow solver objVar e
+
+setRow :: SolverValue v => GenericSolver v -> Var -> LA.Expr Rational -> IO ()
+setRow solver v e = do
+  modifyIORef (svTableau solver) $ \t ->
+    IM.insert v (LA.applySubst t e) t
+  modifyIORef (svModel solver) $ \m -> 
+    IM.insert v (LA.evalLinear m (toValue 1) e) m  
+
+setOptDir :: GenericSolver v -> OptDir -> IO ()
+setOptDir solver dir = writeIORef (svOptDir solver) dir
+
+getOptDir :: GenericSolver v -> IO OptDir
+getOptDir solver = readIORef (svOptDir solver)
+
+{--------------------------------------------------------------------
+  Status
+--------------------------------------------------------------------}
+
+nVars :: GenericSolver v -> IO Int
+nVars solver = readIORef (svVCnt solver)
+
+isBasicVariable :: GenericSolver v -> Var -> IO Bool
+isBasicVariable solver v = do
+  t <- readIORef (svTableau solver)
+  return $ v `IM.member` t
+
+isNonBasicVariable  :: GenericSolver v -> Var -> IO Bool
+isNonBasicVariable solver x = liftM not (isBasicVariable solver x)
+
+isFeasible :: SolverValue v => GenericSolver v -> IO Bool
+isFeasible solver = do
+  xs <- variables solver
+  liftM and $ forM xs $ \x -> do
+    v <- getValue solver x
+    l <- getLB solver x
+    u <- getUB solver x
+    return (testLB l v && testUB u v)
+
+isOptimal :: SolverValue v => GenericSolver v -> IO Bool
+isOptimal solver = do
+  obj <- getRow solver objVar
+  ret <- selectEnteringVariable solver
+  return $! isNothing ret
+
+{--------------------------------------------------------------------
+  Satisfiability solving
+--------------------------------------------------------------------}
+
+check :: SolverValue v => GenericSolver v -> IO Bool
+check solver = do
+  let
+    loop :: IO Bool
+    loop = do
+      m <- selectViolatingBasicVariable solver
+
+      case m of
+        Nothing -> return True
+        Just xi  -> do
+          li <- getLB solver xi
+          ui <- getUB solver xi
+          isLBViolated <- do
+            vi <- getValue solver xi
+            return $ not (testLB li vi)
+          let q = if isLBViolated
+                  then -- select the smallest non-basic variable xj such that
+                       -- (aij > 0 and β(xj) < uj) or (aij < 0 and β(xj) > lj)
+                       canIncrease solver
+                  else -- select the smallest non-basic variable xj such that
+                       -- (aij < 0 and β(xj) < uj) or (aij > 0 and β(xj) > lj)
+                       canDecrease solver
+          xi_def <- getRow solver xi
+          r <- liftM (fmap snd) $ findM q (LA.terms xi_def)              
+          case r of
+            Nothing -> markBad solver >> return False
+            Just xj -> do
+              pivotAndUpdate solver xi xj (fromJust (if isLBViolated then li else ui))
+              loop
+
+  ok <- readIORef (svOk solver)
+  if not ok
+  then return False
+  else do
+    log solver "check"
+    result <- recordTime solver loop
+    when result $ checkFeasibility solver
+    return result
+
+selectViolatingBasicVariable :: SolverValue v => GenericSolver v -> IO (Maybe Var)
+selectViolatingBasicVariable solver = do
+  let
+    p :: Var -> IO Bool
+    p x | x == objVar = return False
+    p xi = do
+      li <- getLB solver xi
+      ui <- getUB solver xi
+      vi <- getValue solver xi
+      return $ not (testLB li vi) || not (testUB ui vi)
+  vs <- basicVariables solver
+
+  ps <- readIORef (svPivotStrategy solver)
+  case ps of
+    PivotStrategyBlandRule ->
+      findM p vs
+    PivotStrategyLargestCoefficient -> do
+      xs <- filterM p vs
+      case xs of
+        [] -> return Nothing
+        _ -> do
+          xs2 <- forM xs $ \xi -> do
+              vi <- getValue solver xi
+              li <- getLB solver xi
+              ui <- getUB solver xi
+              if not (testLB li vi)
+                then return (xi, fromJust li .-. vi)
+                else return (xi, vi .-. fromJust ui)
+          return $ Just $ fst $ maximumBy (comparing snd) xs2
+
+{--------------------------------------------------------------------
+  Optimization
+--------------------------------------------------------------------}
+
+-- | results of optimization
+data OptResult = Optimum | Unsat | Unbounded | ObjLimit
+  deriving (Show, Eq, Ord)
+
+data Options
+  = Options
+  { objLimit :: Maybe Rational
+  }
+  deriving (Show, Eq, Ord)
+
+defaultOptions :: Options
+defaultOptions
+  = Options
+  { objLimit = Nothing
+  }
+
+optimize :: Solver -> Options -> IO OptResult
+optimize solver opt = do
+  ret <- do
+    is_fea <- isFeasible solver
+    if is_fea then return True else check solver
+  if not ret
+    then return Unsat -- unsat
+    else do
+      log solver "optimize"
+      result <- recordTime solver loop
+      when (result == Optimum) $ checkOptimality solver
+      return result
+  where
+    loop :: IO OptResult
+    loop = do
+      checkFeasibility solver
+      ret <- selectEnteringVariable solver
+      case ret of
+       Nothing -> return Optimum
+       Just (c,xj) -> do
+         dir <- getOptDir solver
+         r <- if dir==OptMin
+              then if c > 0
+                then decreaseNB solver xj -- xj を小さくして目的関数を小さくする
+                else increaseNB solver xj -- xj を大きくして目的関数を小さくする
+              else if c > 0
+                then increaseNB solver xj -- xj を大きくして目的関数を大きくする
+                else decreaseNB solver xj -- xj を小さくして目的関数を大きくする
+         if r
+           then loop
+           else return Unbounded
+
+selectEnteringVariable :: SolverValue v => GenericSolver v -> IO (Maybe (Rational, Var))
+selectEnteringVariable solver = do
+  ps <- readIORef (svPivotStrategy solver)
+  obj_def <- getRow solver objVar
+  case ps of
+    PivotStrategyBlandRule ->
+      findM canEnter (LA.terms obj_def)
+    PivotStrategyLargestCoefficient -> do
+      ts <- filterM canEnter (LA.terms obj_def)
+      case ts of
+        [] -> return Nothing
+        _ -> return $ Just $ snd $ maximumBy (comparing fst) [(abs c, (c,xj)) | (c,xj) <- ts]
+  where
+    canEnter :: (Rational, Var) -> IO Bool
+    canEnter (_,xj) | xj == LA.unitVar = return False
+    canEnter (c,xj) = do
+      dir <- getOptDir solver
+      if dir==OptMin
+       then canDecrease solver (c,xj)
+       else canIncrease solver (c,xj)
+
+canIncrease :: SolverValue v => GenericSolver v -> (Rational,Var) -> IO Bool
+canIncrease solver (a,x) =
+  case compare a 0 of
+    EQ -> return False
+    GT -> canIncrease1 solver x
+    LT -> canDecrease1 solver x
+
+canDecrease :: SolverValue v => GenericSolver v -> (Rational,Var) -> IO Bool
+canDecrease solver (a,x) =
+  case compare a 0 of
+    EQ -> return False
+    GT -> canDecrease1 solver x
+    LT -> canIncrease1 solver x
+
+canIncrease1 :: SolverValue v => GenericSolver v -> Var -> IO Bool
+canIncrease1 solver x = do
+  u <- getUB solver x
+  v <- getValue solver x
+  case u of
+    Nothing -> return True
+    Just uv -> return $! (v < uv)
+
+canDecrease1 :: SolverValue v => GenericSolver v -> Var -> IO Bool
+canDecrease1 solver x = do
+  l <- getLB solver x
+  v <- getValue solver x
+  case l of
+    Nothing -> return True
+    Just lv -> return $! (lv < v)
+
+-- | feasibility を保ちつつ non-basic variable xj の値を大きくする
+increaseNB :: Solver -> Var -> IO Bool
+increaseNB solver xj = do
+  col <- getCol solver xj
+
+  -- Upper bounds of θ
+  -- NOTE: xj 自体の上限も考慮するのに注意
+  ubs <- liftM concat $ forM ((xj,1) : IM.toList col) $ \(xi,aij) -> do
+    v1 <- getValue solver xi
+    li <- getLB solver xi
+    ui <- getUB solver xi
+    return [ assert (theta >= lzero) ((xi,v2), theta)
+           | Just v2 <- [ui | aij > 0] ++ [li | aij < 0]
+           , let theta = (v2 .-. v1) ./. aij ]
+
+  -- β(xj) := β(xj) + θ なので θ を大きく
+  case ubs of
+    [] -> return False -- unbounded
+    _ -> do
+      let (xi, v) = fst $ minimumBy (comparing snd) ubs
+      pivotAndUpdate solver xi xj v
+      return True
+
+-- | feasibility を保ちつつ non-basic variable xj の値を小さくする
+decreaseNB :: Solver -> Var -> IO Bool
+decreaseNB solver xj = do
+  col <- getCol solver xj
+
+  -- Lower bounds of θ
+  -- NOTE: xj 自体の下限も考慮するのに注意
+  lbs <- liftM concat $ forM ((xj,1) : IM.toList col) $ \(xi,aij) -> do
+    v1 <- getValue solver xi
+    li <- getLB solver xi
+    ui <- getUB solver xi
+    return [ assert (theta <= lzero) ((xi,v2), theta)
+           | Just v2 <- [li | aij > 0] ++ [ui | aij < 0]
+           , let theta = (v2 .-. v1) ./. aij ]
+
+  -- β(xj) := β(xj) + θ なので θ を小さく
+  case lbs of
+    [] -> return False -- unbounded
+    _ -> do
+      let (xi, v) = fst $ maximumBy (comparing snd) lbs
+      pivotAndUpdate solver xi xj v
+      return True
+
+dualSimplex :: Solver -> Options -> IO OptResult
+dualSimplex solver opt = do
+  let
+    loop :: IO OptResult
+    loop = do
+      checkOptimality solver
+
+      p <- prune solver opt
+      if p
+        then return ObjLimit
+        else do
+          m <- selectViolatingBasicVariable solver
+          case m of
+            Nothing -> return Optimum
+            Just xi  -> do
+              xi_def  <- getRow solver xi
+              li <- getLB solver xi
+              ui <- getUB solver xi
+              isLBViolated <- do
+                vi <- getValue solver xi
+                return $ not (testLB li vi)
+              r <- dualRTest solver xi_def isLBViolated
+              case r of
+                Nothing -> markBad solver >> return Unsat -- dual unbounded
+                Just xj -> do
+                  pivotAndUpdate solver xi xj (fromJust (if isLBViolated then li else ui))
+                  loop
+
+  ok <- readIORef (svOk solver)
+  if not ok
+  then return Unsat
+  else do
+    log solver "dual simplex"
+    result <- recordTime solver loop
+    when (result == Optimum) $ checkFeasibility solver
+    return result
+
+dualRTest :: Solver -> LA.Expr Rational -> Bool -> IO (Maybe Var)
+dualRTest solver row isLBViolated = do
+  -- normalize to the cases of minimization
+  obj_def <- do
+    def <- getRow solver objVar
+    dir <- getOptDir solver
+    return $
+      case dir of
+        OptMin -> def
+        OptMax -> lnegate def
+  -- normalize to the cases of lower bound violation
+  let xi_def =
+       if isLBViolated
+       then row
+       else lnegate row
+  ws <- do
+    -- select non-basic variable xj such that
+    -- (aij > 0 and β(xj) < uj) or (aij < 0 and β(xj) > lj)
+    liftM concat $ forM (LA.terms xi_def) $ \(aij, xj) -> do
+      b <- canIncrease solver (aij, xj)
+      if b
+      then do
+        let cj = LA.coeff xj obj_def
+        let ratio = cj / aij
+        return [(xj, ratio) | ratio >= 0]
+      else
+        return []
+  case ws of
+    [] -> return Nothing
+    _ -> return $ Just $ fst $ minimumBy (comparing snd) ws
+
+prune :: Solver -> Options -> IO Bool
+prune solver opt =
+  case objLimit opt of
+    Nothing -> return False
+    Just lim -> do    
+      o <- getObjValue solver
+      dir <- getOptDir solver
+      case dir of
+        OptMin -> return $! (lim <= o)
+        OptMax -> return $! (lim >= o)
+
+{--------------------------------------------------------------------
+  Extract results
+--------------------------------------------------------------------}
+
+type RawModel v = IM.IntMap v
+
+rawModel :: GenericSolver v -> IO (RawModel v)
+rawModel solver = do
+  xs <- variables solver
+  liftM IM.fromList $ forM xs $ \x -> do
+    val <- getValue solver x
+    return (x,val)
+
+getObjValue :: GenericSolver v -> IO v
+getObjValue solver = getValue solver objVar  
+
+type Model = IM.IntMap Rational
+  
+{--------------------------------------------------------------------
+  major function
+--------------------------------------------------------------------}
+
+update :: SolverValue v => GenericSolver v -> Var -> v -> IO ()
+update solver xj v = do
+  -- log solver $ printf "before update x%d (%s)" xj (show v)
+  -- dump solver
+
+  v0 <- getValue solver xj
+  let diff = v .-. v0
+
+  aj <- getCol solver xj
+  modifyIORef (svModel solver) $ \m ->
+    let m2 = IM.map (\aij -> aij .*. diff) aj
+    in IM.insert xj v $ IM.unionWith (.+.) m2 m
+
+  -- log solver $ printf "after update x%d (%s)" xj (show v)
+  -- dump solver
+
+pivot :: SolverValue v => GenericSolver v -> Var -> Var -> IO ()
+pivot solver xi xj = do
+  modifyIORef' (svNPivot solver) (+1)
+  modifyIORef' (svTableau solver) $ \defs ->
+    case LA.solveFor (LA.Atom (LA.var xi) F.Eql (defs IM.! xi)) xj of
+      Just (F.Eql, xj_def) ->
+        IM.insert xj xj_def . IM.map (LA.applySubst1 xj xj_def) . IM.delete xi $ defs
+      _ -> error "pivot: should not happen"
+
+pivotAndUpdate :: SolverValue v => GenericSolver v -> Var -> Var -> v -> IO ()
+pivotAndUpdate solver xi xj v | xi == xj = update solver xi v -- xi = xj is non-basic variable
+pivotAndUpdate solver xi xj v = do
+  -- xi is basic variable
+  -- xj is non-basic varaible
+
+  -- log solver $ printf "before pivotAndUpdate x%d x%d (%s)" xi xj (show v)
+  -- dump solver
+
+  m <- readIORef (svModel solver)
+
+  aj <- getCol solver xj
+  let aij = aj IM.! xi
+  let theta = (v .-. (m IM.! xi)) ./. aij
+
+  let m' = IM.fromList $
+           [(xi, v), (xj, (m IM.! xj) .+. theta)] ++
+           [(xk, (m IM.! xk) .+. (akj .*. theta)) | (xk, akj) <- IM.toList aj, xk /= xi]
+  writeIORef (svModel solver) (IM.union m' m) -- note that 'IM.union' is left biased.
+
+  pivot solver xi xj
+
+  -- log solver $ printf "after pivotAndUpdate x%d x%d (%s)" xi xj (show v)
+  -- dump solver
+
+getLB :: GenericSolver v -> Var -> IO (Maybe v)
+getLB solver x = do
+  lb <- readIORef (svLB solver)
+  return $ IM.lookup x lb
+
+getUB :: GenericSolver v -> Var -> IO (Maybe v)
+getUB solver x = do
+  ub <- readIORef (svUB solver)
+  return $ IM.lookup x ub
+
+getTableau :: GenericSolver v -> IO (IM.IntMap (LA.Expr Rational))
+getTableau solver = do
+  t <- readIORef (svTableau solver)
+  return $ IM.delete objVar t
+
+getValue :: GenericSolver v -> Var -> IO v
+getValue solver x = do
+  m <- readIORef (svModel solver)
+  return $ m IM.! x
+
+getRow :: GenericSolver v -> Var -> IO (LA.Expr Rational)
+getRow solver x = do
+  -- x should be basic variable or 'objVar'
+  t <- readIORef (svTableau solver)
+  return $! (t IM.! x)
+
+-- aijが非ゼロの列も全部探しているのは効率が悪い
+getCol :: SolverValue v => GenericSolver v -> Var -> IO (IM.IntMap Rational)
+getCol solver xj = do
+  t <- readIORef (svTableau solver)
+  return $ IM.mapMaybe (LA.lookupCoeff xj) t
+
+getCoeff :: GenericSolver v -> Var -> Var -> IO Rational
+getCoeff solver xi xj = do
+  xi_def <- getRow solver xi
+  return $! LA.coeff xj xi_def
+
+markBad :: GenericSolver v -> IO ()
+markBad solver = writeIORef (svOk solver) False
+
+{--------------------------------------------------------------------
+  utility
+--------------------------------------------------------------------}
+
+findM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a)
+findM _ [] = return Nothing
+findM p (x:xs) = do
+  r <- p x
+  if r
+  then return (Just x)
+  else findM p xs
+
+testLB :: SolverValue v => Maybe v -> v -> Bool
+testLB Nothing _  = True
+testLB (Just l) x = l <= x
+
+testUB :: SolverValue v => Maybe v -> v -> Bool
+testUB Nothing _  = True
+testUB (Just u) x = x <= u
+
+variables :: GenericSolver v -> IO [Var]
+variables solver = do
+  vcnt <- nVars solver
+  return [0..vcnt-1]
+
+basicVariables :: GenericSolver v -> IO [Var]
+basicVariables solver = do
+  t <- readIORef (svTableau solver)
+  return (IM.keys t)
+
+modifyIORef' :: IORef a -> (a -> a) -> IO ()
+modifyIORef' ref f = do
+  x <- readIORef ref
+  writeIORef ref $! f x
+
+recordTime :: SolverValue v => GenericSolver v -> IO a -> IO a
+recordTime solver act = do
+  dumpSize solver
+  writeIORef (svNPivot solver) 0
+
+  start <- getCPUTime
+  result <- act
+  end <- getCPUTime
+
+  (log solver . printf "time = %.3fs") (fromIntegral (end - start) / 10^(12::Int) :: Double)
+  (log solver . printf "#pivot = %d") =<< readIORef (svNPivot solver)
+  return result
+
+showDelta :: Bool -> Delta Rational -> String
+showDelta asRatio v = 
+  case v of
+    (Delta r k) -> 
+      f r ++
+        case compare k 0 of
+          EQ -> ""
+          GT -> " + " ++ f k ++ " delta"
+          LT -> " - " ++ f (abs k) ++ " delta"
+  where
+    f = showRational asRatio
+
+{--------------------------------------------------------------------
+  Logging
+--------------------------------------------------------------------}
+
+-- | set callback function for receiving messages.
+setLogger :: GenericSolver v -> (String -> IO ()) -> IO ()
+setLogger solver logger = do
+  writeIORef (svLogger solver) (Just logger)
+
+clearLogger :: GenericSolver v -> IO ()
+clearLogger solver = writeIORef (svLogger solver) Nothing
+
+log :: GenericSolver v -> String -> IO ()
+log solver msg = logIO solver (return msg)
+
+logIO :: GenericSolver v -> IO String -> IO ()
+logIO solver action = do
+  m <- readIORef (svLogger solver)
+  case m of
+    Nothing -> return ()
+    Just logger -> action >>= logger
+
+{--------------------------------------------------------------------
+  debug and tests
+--------------------------------------------------------------------}
+
+test4 :: IO ()
+test4 = do
+  solver <- newSolver
+  setLogger solver putStrLn
+  x0 <- newVar solver
+  x1 <- newVar solver
+
+  writeIORef (svTableau solver) (IM.fromList [(x1, LA.var x0)])
+  writeIORef (svLB solver) (IM.fromList [(x0, toValue 0), (x1, toValue 0)])
+  writeIORef (svUB solver) (IM.fromList [(x0, toValue 2), (x1, toValue 3)])
+  setObj solver (LA.fromTerms [(-1, x0)])
+
+  ret <- optimize solver defaultOptions
+  print ret
+  dump solver
+
+test5 :: IO ()
+test5 = do
+  solver <- newSolver
+  setLogger solver putStrLn
+  x0 <- newVar solver
+  x1 <- newVar solver
+
+  writeIORef (svTableau solver) (IM.fromList [(x1, LA.var x0)])
+  writeIORef (svLB solver) (IM.fromList [(x0, toValue 0), (x1, toValue 0)])
+  writeIORef (svUB solver) (IM.fromList [(x0, toValue 2), (x1, toValue 0)])
+  setObj solver (LA.fromTerms [(-1, x0)])
+
+  checkFeasibility solver
+
+  ret <- optimize solver defaultOptions
+  print ret
+  dump solver
+
+test6 :: IO ()
+test6 = do
+  solver <- newSolver
+  setLogger solver putStrLn
+  x0 <- newVar solver
+
+  assertAtom solver (LA.constant 1 .<. LA.var x0)
+  assertAtom solver (LA.constant 2 .>. LA.var x0)
+
+  ret <- check solver
+  print ret
+  dump solver
+
+  m <- model solver
+  print m
+
+dumpSize :: SolverValue v => GenericSolver v -> IO ()
+dumpSize solver = do
+  t <- readIORef (svTableau solver)
+  let nrows = IM.size t - 1 -- -1 is objVar
+  xs <- variables solver
+  let ncols = length xs - nrows
+  let nnz = sum [IM.size $ LA.coeffMap xi_def | (xi,xi_def) <- IM.toList t, xi /= objVar]
+  log solver $ printf "%d rows, %d columns, %d non-zeros" nrows ncols nnz
+
+dump :: SolverValue v => GenericSolver v -> IO ()
+dump solver = do
+  log solver "============="
+
+  log solver "Tableau:"
+  t <- readIORef (svTableau solver)
+  log solver $ printf "obj = %s" (show (t IM.! objVar))
+  forM_ (IM.toList t) $ \(xi, e) -> do
+    when (xi /= objVar) $ log solver $ printf "x%d = %s" xi (show e)
+
+  log solver ""
+
+  log solver "Assignments and Bounds:"
+  objVal <- getValue solver objVar
+  log solver $ printf "beta(obj) = %s" (showValue True objVal)
+  xs <- variables solver 
+  forM_ xs $ \x -> do
+    l <- getLB solver x
+    u <- getUB solver x
+    v <- getValue solver x
+    let f Nothing = "Nothing"
+        f (Just x) = showValue True x
+    log solver $ printf "beta(x%d) = %s; %s <= x%d <= %s" x (showValue True v) (f l) x (f u)
+
+  log solver ""
+  log solver "Status:"
+  is_fea <- isFeasible solver
+  is_opt <- isOptimal solver
+  log solver $ printf "Feasible: %s" (show is_fea)
+  log solver $ printf "Optimal: %s" (show is_opt)
+
+  log solver "============="
+
+checkFeasibility :: SolverValue v => GenericSolver v -> IO ()
+checkFeasibility _ | True = return ()
+checkFeasibility solver = do
+  xs <- variables solver
+  forM_ xs $ \x -> do
+    v <- getValue solver x
+    l <- getLB solver x
+    u <- getUB solver x
+    let f Nothing = "Nothing"
+        f (Just x) = showValue True x
+    unless (testLB l v) $
+      error (printf "(%s) <= x%d is violated; x%d = (%s)" (f l) x x (showValue True v))
+    unless (testUB u v) $
+      error (printf "x%d <= (%s) is violated; x%d = (%s)" x (f u) x (showValue True v))
+    return ()
+
+checkNBFeasibility :: SolverValue v => GenericSolver v -> IO ()
+checkNBFeasibility _ | True = return ()
+checkNBFeasibility solver = do
+  xs <- variables solver
+  forM_ xs $ \x -> do
+    b <- isNonBasicVariable solver x
+    when b $ do
+      v <- getValue solver x
+      l <- getLB solver x
+      u <- getUB solver x
+      let f Nothing = "Nothing"
+          f (Just x) = showValue True x
+      unless (testLB l v) $
+        error (printf "checkNBFeasibility: (%s) <= x%d is violated; x%d = (%s)" (f l) x x (showValue True v))
+      unless (testUB u v) $
+        error (printf "checkNBFeasibility: x%d <= (%s) is violated; x%d = (%s)" x (f u) x (showValue True v))
+
+checkOptimality :: Solver -> IO ()
+checkOptimality _ | True = return ()
+checkOptimality solver = do
+  ret <- selectEnteringVariable solver
+  case ret of
+    Nothing -> return () -- optimal
+    Just (_,x) -> error (printf "checkOptimality: not optimal (x%d can be changed)" x)
diff --git a/src/TestAReal.hs b/src/TestAReal.hs
new file mode 100644
--- /dev/null
+++ b/src/TestAReal.hs
@@ -0,0 +1,215 @@
+{-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-}
+
+import Data.Maybe
+import Data.Ratio
+import Test.HUnit hiding (Test)
+import Test.QuickCheck
+import Test.Framework (Test, defaultMain, testGroup)
+import Test.Framework.TH
+import Test.Framework.Providers.HUnit
+import Test.Framework.Providers.QuickCheck2
+
+import Data.Polynomial hiding (deg)
+import Data.AlgebraicNumber
+import Data.AlgebraicNumber.Root
+import Data.AlgebraicNumber.RealInstance
+
+import Control.Monad
+import Control.Exception
+import System.IO
+
+{--------------------------------------------------------------------
+  sample values
+--------------------------------------------------------------------}
+
+-- ±√2
+sqrt2 :: AReal
+[neg_sqrt2, sqrt2] = realRoots (x^2 - 2)
+  where
+    x = var ()
+
+-- ±√3
+sqrt3 :: AReal
+[neg_sqrt3, sqrt3] = realRoots (x^2 - 3)
+  where
+    x = var ()
+
+{--------------------------------------------------------------------
+  root manipulation
+--------------------------------------------------------------------}
+
+case__rootAdd_sqrt2_sqrt3 = assertBool "" $ abs valP <= 0.0001
+  where
+    x = var ()
+
+    p :: UPolynomial Rational
+    p = rootAdd (x^2 - 2) (x^2 - 3)
+
+    valP :: Double
+    valP = eval (\() -> sqrt 2 + sqrt 3) $ mapCoeff fromRational p
+
+-- bug?
+test_rootAdd = p
+  where
+    x = var ()    
+    p :: UPolynomial Rational
+    p = rootAdd (x^2 - 2) (x^6 + 6*x^3 - 2*x^2 + 9)
+
+case_rootSub_sqrt2_sqrt3 = assertBool "" $ abs valP <= 0.0001
+  where
+    x = var ()
+
+    p :: UPolynomial Rational
+    p = rootSub (x^2 - 2) (x^2 - 3)
+
+    valP :: Double
+    valP = eval (\() -> sqrt 2 - sqrt 3) $ mapCoeff fromRational p
+
+case_rootMul_sqrt2_sqrt3 = assertBool "" $ abs valP <= 0.0001
+  where
+    x = var ()
+
+    p :: UPolynomial Rational
+    p = rootMul (x^2 - 2) (x^2 - 3)
+
+    valP :: Double
+    valP = eval (\() -> sqrt 2 * sqrt 3) $ mapCoeff fromRational p
+
+case_rootNegate_test1 = assertBool "" $ abs valP <= 0.0001
+  where
+    x = var ()
+
+    p :: UPolynomial Rational
+    p = rootNegate (x^3 - 3)
+
+    valP :: Double
+    valP = eval (\() -> - (3 ** (1/3))) $ mapCoeff fromRational p
+
+case_rootNegate_test2 = rootNegate p @?= q
+  where
+    x :: UPolynomial Rational
+    x = var ()
+    p = x^3 - 3
+    q = x^3 + 3
+
+case_rootNegate_test3 = rootNegate p @?= q
+  where
+    x :: UPolynomial Rational
+    x = var ()
+    p = (x-2)*(x-3)*(x-4)
+    q = (x+2)*(x+3)*(x+4)
+
+case_rootScale = rootScale 2 p @?= q
+  where
+    x :: UPolynomial Rational
+    x = var ()
+    p = (x-2)*(x-3)*(x-4)
+    q = (x-4)*(x-6)*(x-8)
+
+case_rootRecip = assertBool "" $ abs valP <= 0.0001
+  where
+    x = var ()
+
+    p :: UPolynomial Rational
+    p = rootRecip (x^3 - 3)
+
+    valP :: Double
+    valP = eval (\() -> 1 / (3 ** (1/3))) $ mapCoeff fromRational p
+
+{--------------------------------------------------------------------
+  algebraic reals
+--------------------------------------------------------------------}
+
+case_realRoots_zero = realRoots (0 :: UPolynomial Rational) @?= []
+
+case_realRoots_nonminimal =
+  realRoots ((x^2 - 1) * (x - 3)) @?= [-1,1,3]
+  where
+    x = var ()
+
+case_realRoots_minus_one = realRoots (x^2 + 1) @?= []
+  where
+    x = var ()
+
+case_realRoots_two = length (realRoots (x^2 - 2)) @?= 2
+  where
+    x = var ()
+
+case_eq = sqrt2*sqrt2 - 2 @?= 0
+
+case_eq_refl = assertBool "" $ sqrt2 == sqrt2
+
+case_diseq_1 = assertBool "" $ sqrt2 /= sqrt3
+
+case_diseq_2 = assertBool "" $ sqrt2 /= neg_sqrt2
+
+case_cmp_1 = assertBool "" $ 0 < sqrt2
+
+case_cmp_2 = assertBool "" $ neg_sqrt2 < 0
+
+case_cmp_3 = assertBool "" $ 0 < neg_sqrt2 * neg_sqrt2
+
+case_cmp_4 = assertBool "" $ neg_sqrt2 * neg_sqrt2 * neg_sqrt2 < 0
+
+case_floor_sqrt2 = floor' sqrt2 @?= 1
+
+case_floor_neg_sqrt2 = floor' neg_sqrt2 @?= -2
+
+case_floor_1 = floor' 1 @?= 1
+
+case_floor_neg_1 = floor' (-1) @?= -1
+
+case_ceiling_sqrt2 = ceiling' sqrt2 @?= 2
+
+case_ceiling_neg_sqrt2 = ceiling' neg_sqrt2 @?= -1
+
+case_ceiling_1 = ceiling' 1 @?= 1
+
+case_ceiling_neg_1 = ceiling' (-1) @?= -1
+
+case_round_sqrt2 = round' sqrt2 @?= 1
+
+case_toRational = toRational r @?= 3/2
+  where
+    x = var ()
+    [r] = realRoots (2*x - 3)
+
+case_toRational_error = do
+  r <- try $ evaluate $ toRational sqrt2
+  case r of
+    Left (e :: SomeException) -> return ()
+    Right _ -> assertFailure "shuold be error"
+
+-- 期待値は Wolfram Alpha で x^3 - Sqrt[2]*x + 3 を調べて Real root の exact form で得た
+case_simpARealPoly = simpARealPoly p @?= q
+  where
+    x :: forall k. (Num k, Eq k) => UPolynomial k
+    x = var ()
+    p = x^3 - constant sqrt2 * x + 3
+    q = x^6 + 6*x^3 - 2*x^2 + 9
+
+case_deg_sqrt2 = deg sqrt2 @?= 2
+
+case_deg_neg_sqrt2 = deg neg_sqrt2 @?= 2
+
+case_deg_sqrt2_minus_sqrt2 = deg (sqrt2 - sqrt2) @?= 1
+
+case_deg_sqrt2_times_sqrt2 = deg (sqrt2 * sqrt2) @?= 1
+
+case_isAlgebraicInteger_sqrt2 = isAlgebraicInteger sqrt2 @?= True
+
+case_isAlgebraicInteger_neg_sqrt2 = isAlgebraicInteger neg_sqrt2 @?= True
+
+case_isAlgebraicInteger_one_half = isAlgebraicInteger (1/2) @?= False
+
+case_isAlgebraicInteger_one_sqrt2 = isAlgebraicInteger (1 / sqrt2) @?= False
+
+case_height_sqrt2 = height sqrt2 @?= 2
+
+case_height_10 = height 10 @?= 10
+
+------------------------------------------------------------------------
+-- Test harness
+
+main :: IO ()
+main = $(defaultMainGenerator)
diff --git a/src/TestAReal2.hs b/src/TestAReal2.hs
new file mode 100644
--- /dev/null
+++ b/src/TestAReal2.hs
@@ -0,0 +1,87 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+import Data.Maybe
+import Data.Ratio
+import Test.HUnit hiding (Test)
+import Test.QuickCheck
+import Test.Framework (Test, defaultMain, testGroup)
+import Test.Framework.TH
+import Test.Framework.Providers.HUnit
+import Test.Framework.Providers.QuickCheck2
+
+import Data.Polynomial
+import Data.AlgebraicNumber
+
+import Control.Monad
+import System.IO
+
+{--------------------------------------------------------------------
+  Num
+--------------------------------------------------------------------}
+
+prop_add_comm =
+  forAll areals $ \a ->
+  forAll areals $ \b ->
+    a + b == b + a
+
+prop_add_assoc =
+  forAll areals $ \a ->
+  forAll areals $ \b ->
+  forAll areals $ \c ->
+    a + (b + c) == (a + b) + c
+
+prop_add_unitL =
+  forAll areals $ \a ->
+    0 + a == a
+
+prop_add_unitR =
+  forAll areals $ \a ->
+    a + 0 == a
+
+prop_mult_comm =
+  forAll areals $ \a ->
+  forAll areals $ \b ->
+    a * b == b * a
+
+prop_mult_assoc =
+  forAll areals $ \a ->
+  forAll areals $ \b ->
+  forAll areals $ \c ->
+    a * (b * c) == (a * b) * c
+
+prop_mult_unitL =
+  forAll areals $ \a ->
+    1 * a == a
+
+prop_mult_unitR =
+  forAll areals $ \a ->
+    a * 1 == a
+
+prop_mult_dist =
+  forAll areals $ \a ->
+  forAll areals $ \b ->
+  forAll areals $ \c ->
+    a * (b + c) == a * b + a * c
+
+prop_mult_zero = 
+  forAll areals $ \a ->
+    0 * a ==  0
+
+{--------------------------------------------------------------------
+  Generators
+--------------------------------------------------------------------}
+
+areals :: Gen AReal
+areals = oneof $ map return $ samples
+
+samples :: [AReal]
+samples = [0, 1, -1, 2, -2] ++ concatMap realRoots ps
+  where
+    x = var ()
+    ps = [x^2 - 2, x^2 - 3 {- , x^3 - 2, x^6 + 6*x^3 - 2*x^2 + 9 -}]
+
+------------------------------------------------------------------------
+-- Test harness
+
+main :: IO ()
+main = $(defaultMainGenerator)
diff --git a/src/TestInterval.hs b/src/TestInterval.hs
new file mode 100644
--- /dev/null
+++ b/src/TestInterval.hs
@@ -0,0 +1,469 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+import Data.Maybe
+import Data.Ratio
+import Test.HUnit hiding (Test)
+import Test.QuickCheck
+import Test.Framework (Test, defaultMain, testGroup)
+import Test.Framework.TH
+import Test.Framework.Providers.HUnit
+import Test.Framework.Providers.QuickCheck2
+
+import Data.Linear
+import Data.Interval (Interval, (<!), (<=!), (==!), (>=!), (>!), (<?), (<=?), (==?), (>=?), (>?))
+import qualified Data.Interval as Interval
+
+{--------------------------------------------------------------------
+  empty
+--------------------------------------------------------------------}
+
+prop_empty_is_bottom =
+  forAll intervals $ \a ->
+    Interval.isSubsetOf Interval.empty a
+
+prop_null_empty =
+  forAll intervals $ \a ->
+    Interval.null a == (a == Interval.empty)
+
+case_null_empty =
+  Interval.null (Interval.empty :: Interval Rational) @?= True
+
+{--------------------------------------------------------------------
+  univ
+--------------------------------------------------------------------}
+
+prop_univ_is_top =
+  forAll intervals $ \a ->
+    Interval.isSubsetOf a Interval.univ
+
+case_nonnull_top =
+  Interval.null (Interval.univ :: Interval Rational) @?= False
+
+{--------------------------------------------------------------------
+  singleton
+--------------------------------------------------------------------}
+
+prop_singleton_member =
+  forAll arbitrary $ \r ->
+    Interval.member (r::Rational) (Interval.singleton r)
+
+prop_singleton_member_intersection =
+  forAll intervals $ \a ->
+  forAll arbitrary $ \r ->
+    let b = Interval.singleton r
+    in Interval.member (r::Rational) a
+       ==> Interval.intersection a b == b
+
+prop_singleton_nonnull =
+  forAll arbitrary $ \r1 ->
+    not $ Interval.null $ Interval.singleton (r1::Rational)
+
+prop_distinct_singleton_intersection =
+  forAll arbitrary $ \r1 ->
+  forAll arbitrary $ \r2 ->
+    (r1::Rational) /= r2 ==>
+      Interval.intersection (Interval.singleton r1) (Interval.singleton r2)
+      == Interval.empty
+
+{--------------------------------------------------------------------
+  Intersection
+--------------------------------------------------------------------}
+
+prop_intersection_comm =
+  forAll intervals $ \a ->
+  forAll intervals $ \b ->
+    Interval.intersection a b == Interval.intersection b a
+
+prop_intersection_assoc =
+  forAll intervals $ \a ->
+  forAll intervals $ \b ->
+  forAll intervals $ \c ->
+    Interval.intersection a (Interval.intersection b c) ==
+    Interval.intersection (Interval.intersection a b) c
+
+prop_intersection_unitL =
+  forAll intervals $ \a ->
+    Interval.intersection Interval.univ a == a
+
+prop_intersection_unitR =
+  forAll intervals $ \a ->
+    Interval.intersection a Interval.univ == a
+
+prop_intersection_empty =
+  forAll intervals $ \a ->
+    Interval.intersection a Interval.empty == Interval.empty
+
+prop_intersection_isSubsetOf =
+  forAll intervals $ \a ->
+  forAll intervals $ \b ->
+    Interval.isSubsetOf (Interval.intersection a b) a
+
+prop_intersection_isSubsetOf_equiv =
+  forAll intervals $ \a ->
+  forAll intervals $ \b ->
+    (Interval.intersection a b == a)
+    == Interval.isSubsetOf a b
+
+{--------------------------------------------------------------------
+  Join
+--------------------------------------------------------------------}
+
+prop_join_comm =
+  forAll intervals $ \a ->
+  forAll intervals $ \b ->
+    Interval.join a b == Interval.join b a
+
+prop_join_assoc =
+  forAll intervals $ \a ->
+  forAll intervals $ \b ->
+  forAll intervals $ \c ->
+    Interval.join a (Interval.join b c) ==
+    Interval.join (Interval.join a b) c
+
+prop_join_unitL =
+  forAll intervals $ \a ->
+    Interval.join Interval.empty a == a
+
+prop_join_unitR =
+  forAll intervals $ \a ->
+    Interval.join a Interval.empty == a
+
+prop_join_univ =
+  forAll intervals $ \a ->
+    Interval.join a Interval.univ == Interval.univ
+
+prop_join_isSubsetOf =
+  forAll intervals $ \a ->
+  forAll intervals $ \b ->
+    Interval.isSubsetOf a (Interval.join a b)
+
+prop_join_isSubsetOf_equiv =
+  forAll intervals $ \a ->
+  forAll intervals $ \b ->
+    (Interval.join a b == b)
+    == Interval.isSubsetOf a b
+
+{--------------------------------------------------------------------
+  member
+--------------------------------------------------------------------}
+
+prop_member_isSubsetOf =
+  forAll arbitrary $ \r ->
+  forAll intervals $ \a ->
+    Interval.member r a == Interval.isSubsetOf (Interval.singleton r) a
+
+{--------------------------------------------------------------------
+  isSubsetOf
+--------------------------------------------------------------------}
+
+prop_isSubsetOf_refl =
+  forAll intervals $ \a ->
+    Interval.isSubsetOf a a
+
+prop_isSubsetOf_trans =
+  forAll intervals $ \a ->
+  forAll intervals $ \b ->
+  forAll intervals $ \c ->
+    Interval.isSubsetOf a b && Interval.isSubsetOf b c
+    ==> Interval.isSubsetOf a c
+
+-- prop_isSubsetOf_antisym =
+--   forAll intervals $ \a ->
+--   forAll intervals $ \b ->
+--     Interval.isSubsetOf a b && Interval.isSubsetOf b a
+--     ==> a == b
+
+{--------------------------------------------------------------------
+  pickup
+--------------------------------------------------------------------}
+
+prop_pickup_member_null =
+  forAll intervals $ \a ->
+    case Interval.pickup a of
+      Nothing -> Interval.null a
+      Just x -> Interval.member x a
+
+case_pickup_empty =
+  Interval.pickup (Interval.empty :: Interval Rational) @?= Nothing
+
+case_pickup_univ =
+  isJust (Interval.pickup (Interval.univ :: Interval Rational)) @?= True
+
+{--------------------------------------------------------------------
+  Comparison
+--------------------------------------------------------------------}
+
+case_lt_all_1 = (a <! b) @?= False
+  where
+    a, b :: Interval Rational
+    a = Interval.interval Nothing (Just (True,0))
+    b = Interval.interval (Just (True,0)) Nothing
+
+case_lt_all_2 = (a <! b) @?= True
+  where
+    a, b :: Interval Rational
+    a = Interval.interval Nothing (Just (False,0))
+    b = Interval.interval (Just (True,0)) Nothing
+
+case_lt_all_3 = (a <! b) @?= True
+  where
+    a, b :: Interval Rational
+    a = Interval.interval Nothing (Just (True,0))
+    b = Interval.interval (Just (False,0)) Nothing
+
+case_lt_all_4 = (a <! b) @?= False
+  where
+    a, b :: Interval Rational
+    a = Interval.interval (Just (True,0)) Nothing
+    b = Interval.interval (Just (True,1)) Nothing
+
+case_lt_some_1 = (a <? b) @?= False
+  where
+    a, b :: Interval Rational
+    a = Interval.interval (Just (True,0)) Nothing
+    b = Interval.interval Nothing (Just (True,0))
+
+case_lt_some_2 = (a <? b) @?= False
+  where
+    a, b :: Interval Rational
+    a = Interval.interval (Just (False,0)) Nothing
+    b = Interval.interval Nothing (Just (True,0))
+
+case_lt_some_3 = (a <? b) @?= False
+  where
+    a, b :: Interval Rational
+    a = Interval.interval (Just (True,0)) Nothing
+    b = Interval.interval Nothing (Just (False,0))
+
+case_lt_some_4 = (a <! b) @?= False
+  where
+    a, b :: Interval Rational
+    a = Interval.interval (Just (True,0)) Nothing
+    b = Interval.interval (Just (True,1)) Nothing
+
+case_le_some_1 = (a <=? b) @?= True
+  where
+    a, b :: Interval Rational
+    a = Interval.interval (Just (True,0)) Nothing
+    b = Interval.interval Nothing (Just (True,0))
+
+case_le_some_2 = (a <=? b) @?= False
+  where
+    a, b :: Interval Rational
+    a = Interval.interval (Just (False,0)) Nothing
+    b = Interval.interval Nothing (Just (True,0))
+
+case_le_some_3 = (a <=? b) @?= False
+  where
+    a, b :: Interval Rational
+    a = Interval.interval (Just (True,0)) Nothing
+    b = Interval.interval Nothing (Just (False,0))
+
+prop_lt_all_not_refl =
+  forAll intervals $ \a -> not (Interval.null a) ==> not (a <! a)
+
+prop_le_some_refl =
+  forAll intervals $ \a -> not (Interval.null a) ==> a <=? a
+
+prop_lt_all_singleton =
+  forAll arbitrary $ \a ->
+  forAll arbitrary $ \b ->
+    (a::Rational) < b ==> Interval.singleton a <! Interval.singleton b
+
+prop_lt_all_singleton_2 =
+  forAll arbitrary $ \a ->
+    not $ Interval.singleton (a::Rational) <! Interval.singleton a
+
+prop_le_all_singleton =
+  forAll arbitrary $ \a ->
+  forAll arbitrary $ \b ->
+    (a::Rational) <= b ==> Interval.singleton a <=! Interval.singleton b
+
+prop_le_all_singleton_2 =
+  forAll arbitrary $ \a ->
+    Interval.singleton (a::Rational) <=! Interval.singleton a
+
+prop_lt_some_singleton =
+  forAll arbitrary $ \a ->
+  forAll arbitrary $ \b ->
+    (a::Rational) < b ==> Interval.singleton a <? Interval.singleton b
+
+prop_lt_some_singleton_2 =
+  forAll arbitrary $ \a ->
+    not $ Interval.singleton (a::Rational) <? Interval.singleton a
+
+prop_le_some_singleton =
+  forAll arbitrary $ \a ->
+  forAll arbitrary $ \b ->
+    (a::Rational) <= b ==> Interval.singleton a <=? Interval.singleton b
+
+prop_le_some_singleton_2 =
+  forAll arbitrary $ \a ->
+    Interval.singleton (a::Rational) <=? Interval.singleton a
+
+{--------------------------------------------------------------------
+  Num
+--------------------------------------------------------------------}
+
+prop_scale_empty =
+  forAll arbitrary $ \r ->
+    (r::Rational) .*. Interval.empty == Interval.empty
+
+prop_add_comm =
+  forAll intervals $ \a ->
+  forAll intervals $ \b ->
+    a + b == b + a
+
+prop_add_assoc =
+  forAll intervals $ \a ->
+  forAll intervals $ \b ->
+  forAll intervals $ \c ->
+    a + (b + c) == (a + b) + c
+
+prop_add_unitL =
+  forAll intervals $ \a ->
+    Interval.singleton 0 + a == a
+
+prop_add_unitR =
+  forAll intervals $ \a ->
+    a + Interval.singleton 0 == a
+
+prop_add_member =
+  forAll intervals $ \a ->
+  forAll intervals $ \b ->
+    and [ (x+y) `Interval.member` (a+b)
+        | x <- maybeToList $ Interval.pickup a
+        , y <- maybeToList $ Interval.pickup b
+        ]
+
+prop_mult_comm =
+  forAll intervals $ \a ->
+  forAll intervals $ \b ->
+    a * b == b * a
+
+prop_mult_assoc =
+  forAll intervals $ \a ->
+  forAll intervals $ \b ->
+  forAll intervals $ \c ->
+    a * (b * c) == (a * b) * c
+
+prop_mult_unitL =
+  forAll intervals $ \a ->
+    Interval.singleton 1 * a == a
+
+prop_mult_unitR =
+  forAll intervals $ \a ->
+    a * Interval.singleton 1 == a
+
+prop_mult_dist =
+  forAll intervals $ \a ->
+  forAll intervals $ \b ->
+  forAll intervals $ \c ->
+    (a * (b + c)) `Interval.isSubsetOf` (a * b + a * c)
+
+prop_mult_singleton =
+  forAll arbitrary $ \r ->
+  forAll intervals $ \a ->
+    Interval.singleton r * a == r .*. a
+
+prop_mult_empty =
+  forAll intervals $ \a ->
+    Interval.empty * a == Interval.empty
+
+prop_mult_zero = 
+  forAll intervals $ \a ->
+    not (Interval.null a) ==> Interval.singleton 0 * a ==  Interval.singleton 0
+
+prop_mult_member =
+  forAll intervals $ \a ->
+  forAll intervals $ \b ->
+    and [ (x*y) `Interval.member` (a*b)
+        | x <- maybeToList $ Interval.pickup a
+        , y <- maybeToList $ Interval.pickup b
+        ]
+
+case_mult_test1 = ival1 * ival2 @?= ival3
+  where
+    ival1 = Interval.interval (Just (True,1)) (Just (True,2))
+    ival2 = Interval.interval (Just (True,1)) (Just (True,2))
+    ival3 = Interval.interval (Just (True,1)) (Just (True,4))
+
+case_mult_test2 = ival1 * ival2 @?= ival3
+  where
+    ival1 = Interval.interval (Just (True,1)) (Just (True,2))
+    ival2 = Interval.interval (Just (False,1)) (Just (False,2))
+    ival3 = Interval.interval (Just (False,1)) (Just (False,4))
+
+case_mult_test3 = ival1 * ival2 @?= ival3
+  where
+    ival1 = Interval.interval (Just (False,1)) (Just (False,2))
+    ival2 = Interval.interval (Just (False,1)) (Just (False,2))
+    ival3 = Interval.interval (Just (False,1)) (Just (False,4))
+
+case_mult_test4 = ival1 * ival2 @?= ival3
+  where
+    ival1 = Interval.interval (Just (False,2)) Nothing
+    ival2 = Interval.interval (Just (False,3)) Nothing
+    ival3 = Interval.interval (Just (False,6)) Nothing
+
+case_mult_test5 = ival1 * ival2 @?= ival3
+  where
+    ival1 = Interval.interval Nothing (Just (False,-3))
+    ival2 = Interval.interval Nothing (Just (False,-2))
+    ival3 = Interval.interval (Just (False,6)) Nothing
+
+case_mult_test6 = ival1 * ival2 @?= ival3
+  where
+    ival1 = Interval.interval (Just (False,2)) Nothing
+    ival2 = Interval.interval Nothing (Just (False,-2))
+    ival3 = Interval.interval Nothing (Just (False,-4))
+
+{--------------------------------------------------------------------
+  Fractional
+--------------------------------------------------------------------}
+
+prop_recip_singleton =
+  forAll arbitrary $ \r ->
+    let n = fromIntegral (numerator r)
+        d = fromIntegral (denominator r)
+    in Interval.singleton n / Interval.singleton d == Interval.singleton (r::Rational)
+
+case_recip_pos =
+  recip pos @?= pos
+
+case_recip_neg =
+  recip neg @?= neg
+
+case_recip_test1 = recip i1 @?= i2
+  where
+    i1, i2 :: Interval Rational
+    i1 = Interval.interval (Just (True,2)) Nothing
+    i2 = Interval.interval (Just (False,0)) (Just (True,1/2))
+
+{--------------------------------------------------------------------
+  Generators
+--------------------------------------------------------------------}
+
+intervals :: Gen (Interval Rational)
+intervals = do
+  lb <- arbitrary
+  ub <- arbitrary
+  return $ Interval.interval lb ub
+
+pos :: Interval Rational
+pos = Interval.interval (Just (False,0)) Nothing
+
+neg :: Interval Rational
+neg = Interval.interval Nothing (Just (False,0))
+
+nonpos :: Interval Rational
+nonpos = Interval.interval Nothing (Just (True,0))
+
+nonneg :: Interval Rational
+nonneg = Interval.interval (Just (True,0)) Nothing
+
+------------------------------------------------------------------------
+-- Test harness
+
+main :: IO ()
+main = $(defaultMainGenerator)
diff --git a/src/TestLPFile.hs b/src/TestLPFile.hs
new file mode 100644
--- /dev/null
+++ b/src/TestLPFile.hs
@@ -0,0 +1,66 @@
+{-# LANGUAGE TemplateHaskell #-}
+module Main (main) where
+
+import Control.Monad
+import Data.List
+import Data.Maybe
+import Test.HUnit hiding (Test)
+import Test.Framework (Test, defaultMain, testGroup)
+import Test.Framework.TH
+import Test.Framework.Providers.HUnit
+import Text.LPFile
+
+case_testdata       = checkString "testdata" testdata
+case_test_indicator = checkFile "samples/lp/test-indicator.lp"
+case_test_qcp       = checkFile "samples/lp/test-qcp.lp"
+case_test_qcp2      = checkFile "samples/lp/test-qcp2.lp"
+case_test_qp        = checkFile "samples/lp/test-qp.lp"
+case_empty_obj_1    = checkFile "samples/lp/empty_obj_1.lp"
+case_empty_obj_2    = checkFile "samples/lp/empty_obj_2.lp"  
+
+------------------------------------------------------------------------
+-- Sample data
+
+testdata :: String
+testdata = unlines
+  [ "Maximize"
+  , " obj: x1 + 2 x2 + 3 x3 + x4"
+  , "Subject To"
+  , " c1: - x1 + x2 + x3 + 10 x4 <= 20"
+  , " c2: x1 - 3 x2 + x3 <= 30"
+  , " c3: x2 - 3.5 x4 = 0"
+  , "Bounds"
+  , " 0 <= x1 <= 40"
+  , " 2 <= x4 <= 3"
+  , "General"
+  , " x4"
+  , "End"
+  ]
+
+------------------------------------------------------------------------
+-- Utilities
+
+checkFile :: FilePath -> IO ()
+checkFile fname = do
+  r <- parseFile fname
+  case r of
+    Left err -> assertFailure $ show err
+    Right lp ->
+      case render lp of
+        Nothing -> assertFailure "render failure"
+        Just _ -> return ()
+
+checkString :: String -> String -> IO ()
+checkString name str = do
+  case parseString name str of
+    Left err -> assertFailure $ show err
+    Right lp ->
+      case render lp of
+        Nothing -> assertFailure "render failure"
+        Just _ -> return ()
+
+------------------------------------------------------------------------
+-- Test harness
+
+main :: IO ()
+main = $(defaultMainGenerator)
diff --git a/src/TestMIPSolver2.hs b/src/TestMIPSolver2.hs
new file mode 100644
--- /dev/null
+++ b/src/TestMIPSolver2.hs
@@ -0,0 +1,125 @@
+{-# LANGUAGE TemplateHaskell #-}
+module Main (main) where
+
+import Control.Monad
+import Data.List
+import Data.Ratio
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+import Test.HUnit hiding (Test)
+import Test.Framework (Test, defaultMain, testGroup)
+import Test.Framework.TH
+import Test.Framework.Providers.HUnit
+import Text.Printf
+
+import Data.Linear
+import Simplex2
+import MIPSolver2
+import qualified Data.LA as LA
+
+------------------------------------------------------------------------
+
+example1 :: (OptDir, LA.Expr Rational, [Atom Rational], IS.IntSet)
+example1 = (optdir, obj, cs, ivs)
+  where
+    optdir = OptMax
+    x1 = LA.var 1
+    x2 = LA.var 2
+    x3 = LA.var 3
+    x4 = LA.var 4
+    obj = x1 .+. 2 .*. x2 .+. 3 .*. x3 .+. x4
+    cs =
+      [ LA.Atom ((-1) .*. x1 .+. x2 .+. x3 .+. 10.*.x4) Le (LA.constant 20)
+      , LA.Atom (x1 .-. 3 .*. x2 .+. x3) Le (LA.constant 30)
+      , LA.Atom (x2 .-. 3.5 .*. x4) Eql (LA.constant 0)
+      , LA.Atom (LA.constant 0) Le x1
+      , LA.Atom x1 Le (LA.constant 40)
+      , LA.Atom (LA.constant 0) Le x2
+      , LA.Atom (LA.constant 0) Le x3
+      , LA.Atom (LA.constant 2) Le x4
+      , LA.Atom x4 Le (LA.constant 3)
+      ]
+    ivs = IS.singleton 4
+
+case_test1 = do
+  let (optdir, obj, cs, ivs) = example1
+  lp <- Simplex2.newSolver
+  replicateM 5 (Simplex2.newVar lp)
+  setOptDir lp optdir
+  setObj lp obj
+  mapM_ (Simplex2.assertAtom lp) cs
+  mip <- MIPSolver2.newSolver lp ivs
+  ret <- MIPSolver2.optimize mip (\_ _ -> return ())
+  
+  ret @?= Simplex2.Optimum
+
+  m <- MIPSolver2.model mip
+  forM_ [(1,40 % 1),(2,21 % 2),(3,39 % 2),(4,3 % 1)] $ \(var, val) ->
+    m IM.! var @?= val
+
+  v <- MIPSolver2.getObjValue mip
+  v @?= (245 % 2)
+
+case_test1' = do
+  let (optdir, obj, cs, ivs) = example1
+  lp <- Simplex2.newSolver
+  replicateM 5 (Simplex2.newVar lp)
+  setOptDir lp (f optdir)
+  setObj lp (lnegate obj)
+  mapM_ (Simplex2.assertAtom lp) cs
+  mip <- MIPSolver2.newSolver lp ivs
+  ret <- MIPSolver2.optimize mip (\_ _ -> return ())
+  
+  ret @?= Simplex2.Optimum
+
+  m <- MIPSolver2.model mip
+  forM_ [(1,40 % 1),(2,21 % 2),(3,39 % 2),(4,3 % 1)] $ \(var, val) ->
+    m IM.! var @?= val
+
+  v <- MIPSolver2.getObjValue mip
+  v @?= (- 245 % 2)
+
+  where
+    f OptMin = OptMax
+    f OptMax = OptMin
+
+-- 『数理計画法の基礎』(坂和 正敏) p.109 例 3.8
+example2 = (optdir, obj, cs, ivs)
+  where
+    optdir = OptMin
+    [x1,x2,x3] = map LA.var [1..3]
+    obj = (-1) .*. x1 .-. 3 .*. x2 .-. 5 .*. x3
+    cs =
+      [ LA.Atom (3 .*. x1 .+. 4 .*. x2) Le (LA.constant 10)
+      , LA.Atom (2 .*. x1 .+. x2 .+. x3) Le (LA.constant 7)
+      , LA.Atom (3.*.x1 .+. x2 .+. 4 .*. x3) Eql (LA.constant 12)
+      , LA.Atom (LA.constant 0) Le x1
+      , LA.Atom (LA.constant 0) Le x2
+      , LA.Atom (LA.constant 0) Le x3
+      ]
+    ivs = IS.fromList [1,2]
+
+case_test2 = do
+  let (optdir, obj, cs, ivs) = example2
+  lp <- Simplex2.newSolver
+  replicateM 4 (Simplex2.newVar lp)
+  setOptDir lp optdir
+  setObj lp obj
+  mapM_ (Simplex2.assertAtom lp) cs
+  mip <- MIPSolver2.newSolver lp ivs
+  ret <- MIPSolver2.optimize mip (\_ _ -> return ())
+  
+  ret @?= Simplex2.Optimum
+
+  m <- MIPSolver2.model mip
+  forM_ [(1,0 % 1),(2,2 % 1),(3,5 % 2)] $ \(var, val) ->
+    m IM.! var @?= val
+
+  v <- MIPSolver2.getObjValue mip
+  v @?= (- 37 % 2)
+
+------------------------------------------------------------------------
+-- Test harness
+
+main :: IO ()
+main = $(defaultMainGenerator)
diff --git a/src/TestPBFile.hs b/src/TestPBFile.hs
new file mode 100644
--- /dev/null
+++ b/src/TestPBFile.hs
@@ -0,0 +1,146 @@
+{-# LANGUAGE TemplateHaskell #-}
+module Main (main) where
+
+import Control.Monad
+import Data.List
+import Data.Maybe
+import Test.HUnit hiding (Test)
+import Test.Framework (Test, defaultMain, testGroup)
+import Test.Framework.TH
+import Test.Framework.Providers.HUnit
+import Text.PBFile
+
+case_exampleLIN  = checkOPBString "exampleLIN"  exampleLIN
+case_exampleNLC1 = checkOPBString "exampleNLC1" exampleNLC1
+case_exampleNLC2 = checkOPBString "exampleNLC2" exampleNLC2
+case_exampleWBO1 = checkWBOString "exampleWBO1" exampleWBO1
+case_exampleWBO2 = checkWBOString "exampleWBO2" exampleWBO2
+case_exampleWBO3 = checkWBOString "exampleWBO3" exampleWBO3
+
+------------------------------------------------------------------------
+-- Sample data
+
+exampleLIN :: String
+exampleLIN = unlines
+  [ "* #variable= 5 #constraint= 4"
+  , "*"
+  , "* this is a dummy instance"
+  , "*"
+  , "min: 1 x2 -1 x3 ;"
+  , "1 x1 +4 x2 -2 x5 >= 2;"
+  , "-1 x1 +4 x2 -2 x5 >= +3;"
+  , "12345678901234567890 x4 +4 x3 >= 10;"
+  , "* an equality constraint"
+  , "2 x2 +3 x4 +2 x1 +3 x5 = 5;"
+  ]
+
+exampleNLC1 :: String
+exampleNLC1 = unlines
+  [ "* #variable= 5 #constraint= 4 #product= 5 sizeproduct= 13"
+  , "*"
+  , "* this is a dummy instance"
+  , "*"
+  , "min: 1 x2 x3 -1 x3 ;"
+  , "1 x1 +4 x1 ~x2 -2 x5 >= 2;"
+  , "-1 x1 +4 x2 -2 x5 >= 3;"
+  , "12345678901234567890 x4 +4 x3 >= 10;"
+  , "2 x2 x3 +3 x4 ~x5 +2 ~x1 x2 +3 ~x1 x2 x3 ~x4 ~x5 = 5 ;"
+  ]
+
+exampleNLC2 :: String
+exampleNLC2 = unlines
+  [ "* #variable= 6 #constraint= 3 #product= 9 sizeproduct= 18"
+  , "*"
+  , "* Factorization problem: find the smallest P such that P*Q=N"
+  , "* P is a 3 bits number (x3 x2 x1)"
+  , "* Q is a 3 bits number (x6 x5 x4)"
+  , "* N=35"
+  , "* "
+  , "* minimize the value of P"
+  , "min: +1 x1 +2 x2 +4 x3 ;"
+  , "* P>=2 (to avoid trivial factorization)"
+  , "+1 x1 +2 x2 +4 x3 >=2;"
+  , "* Q>=2 (to avoid trivial factorization)"
+  , "+1 x4 +2 x5 +4 x6 >=2;"
+  , "*"
+  , "* P*Q=N"
+  , "+1 x1 x4 +2 x1 x5 +4 x1 x6 +2 x2 x4 +4 x2 x5 +8 x2 x6 +4 x3 x4 +8 x3 x5 +16 x3 x6 = 35;"
+  ]
+
+exampleWBO1 :: String
+exampleWBO1 = unlines $
+  [ "* #variable= 1 #constraint= 2 #soft= 2 mincost= 2 maxcost= 3 sumcost= 5"
+  , "soft: 6 ;"
+  , "[2] +1 x1 >= 1 ;"
+  , "[3] -1 x1 >= 0 ;"
+  ]
+
+exampleWBO2 :: String
+exampleWBO2 = unlines $
+  [ "* #variable= 2 #constraint= 3 #soft= 2 mincost= 2 maxcost= 3 sumcost= 5"
+  , "soft: 6 ;"
+  , "[2] +1 x1 >= 1 ;"
+  , "[3] +1 x2 >= 1 ;"
+  , "-1 x1 -1 x2 >= -1 ;"
+  ]
+
+exampleWBO3 :: String
+exampleWBO3 = unlines $
+  [ "* #variable= 4 #constraint= 6 #soft= 4 mincost= 2 maxcost= 5 sumcost= 14"
+  , "soft: 6 ;"
+  , "[2] +1 x1 >= 1;"
+  , "[3] +1 x2 >= 1;"
+  , "[4] +1 x3 >= 1;"
+  , "[5] +1 x4 >= 1;"
+  , "-1 x1 -1 x2 >= -1 ;"
+  , "-1 x3 -1 x4 >= -1 ;"
+  ]
+
+------------------------------------------------------------------------
+-- Utilities
+
+checkOPBFile :: FilePath -> IO ()
+checkOPBFile fname = do
+  r <- parseOPBFile fname
+  case r of
+    Left err -> assertFailure $ show err
+    Right _  -> return ()
+
+checkOPBString :: String -> String -> IO ()
+checkOPBString name str = do
+  case parseOPBString name str of
+    Left err -> assertFailure $ show err
+    Right _  -> return ()
+
+checkWBOFile :: FilePath -> IO ()
+checkWBOFile fname = do
+  r <- parseWBOFile fname
+  case r of
+    Left err -> assertFailure $ show err
+    Right _  -> return ()
+
+checkWBOString :: String -> String -> IO ()
+checkWBOString name str = do
+  case parseWBOString name str of
+    Left err -> assertFailure $ show err
+    Right _  -> return ()
+
+testOPB :: String -> Bool
+testOPB s = sf == sf2
+  where
+    Right sf  = parseOPBString "-" s
+    s2 = showOPB sf ""
+    Right sf2 = parseOPBString "-" s2
+
+testWBO :: String -> Bool
+testWBO s = sf == sf2
+  where
+    Right sf  = parseWBOString "-" s
+    s2 = showWBO sf ""
+    Right sf2 = parseWBOString "-" s2
+
+------------------------------------------------------------------------
+-- Test harness
+
+main :: IO ()
+main = $(defaultMainGenerator)
diff --git a/src/TestPolynomial.hs b/src/TestPolynomial.hs
new file mode 100644
--- /dev/null
+++ b/src/TestPolynomial.hs
@@ -0,0 +1,543 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+import Prelude hiding (lex)
+import Control.Monad
+import Data.List
+import Data.Ratio
+import qualified Data.Set as Set
+import qualified Data.Map as Map
+import Test.HUnit hiding (Test)
+import Test.QuickCheck
+import Test.Framework (Test, defaultMain, testGroup)
+import Test.Framework.TH
+import Test.Framework.Providers.HUnit
+import Test.Framework.Providers.QuickCheck2
+
+import Data.Polynomial
+import Data.Polynomial.GBase
+import Data.Polynomial.Sturm
+import qualified Data.Polynomial.Lagrange as Lagrange
+import qualified Data.Interval as Interval
+
+{--------------------------------------------------------------------
+  Polynomial type
+--------------------------------------------------------------------}
+
+prop_plus_comm = 
+  forAll polynomials $ \a ->
+  forAll polynomials $ \b ->
+    a + b == b + a
+
+prop_plus_assoc = 
+  forAll polynomials $ \a ->
+  forAll polynomials $ \b ->
+  forAll polynomials $ \c ->
+    a + (b + c) == (a + b) + c
+
+prop_plus_unitL = 
+  forAll polynomials $ \a ->
+    constant 0 + a == a
+
+prop_plus_unitR = 
+  forAll polynomials $ \a ->
+    a + constant 0 == a
+
+prop_prod_comm = 
+  forAll polynomials $ \a ->
+  forAll polynomials $ \b ->
+    a * b == b * a
+
+prop_prod_assoc = 
+  forAll polynomials $ \a ->
+  forAll polynomials $ \b ->
+  forAll polynomials $ \c ->
+    a * (b * c) == (a * b) * c
+
+prop_prod_unitL = 
+  forAll polynomials $ \a ->
+    constant 1 * a == a
+
+prop_prod_unitR = 
+  forAll polynomials $ \a ->
+    a * constant 1 == a
+
+prop_distL = 
+  forAll polynomials $ \a ->
+  forAll polynomials $ \b ->
+  forAll polynomials $ \c ->
+    a * (b + c) == a * b + a * c
+
+prop_distR = 
+  forAll polynomials $ \a ->
+  forAll polynomials $ \b ->
+  forAll polynomials $ \c ->
+    (b + c) * a == b * a + c * a
+
+prop_negate =
+  forAll polynomials $ \a ->
+    a + negate a == 0
+
+prop_negate_involution =
+  forAll polynomials $ \a ->
+    negate (negate a) == a
+
+prop_polyMDivMod =
+  forAll polynomials $ \g ->
+    forAll (replicateM 3 polynomials) $ \fs ->
+      all (0/=) fs ==>
+        let (qs, r) = polyMDivMod lex g fs
+        in sum (zipWith (*) fs qs) + r == g
+
+{--------------------------------------------------------------------
+  Univalent polynomials
+--------------------------------------------------------------------}
+
+prop_polyDivMod =
+  forAll upolynomials $ \a ->
+  forAll upolynomials $ \b ->
+    b /= 0 ==> 
+      let (q,r) = polyDivMod a b
+      in a == q*b + r && (r==0 || deg b > deg r)
+
+case_polyDivMod_1 =  g*q + r @?= f
+  where
+    x :: UPolynomial Rational
+    x = var ()
+    f = x^3 + x^2 + x
+    g = x^2 + 1
+    (q,r) = f `polyDivMod` g
+
+prop_polyGCD_divisible =
+  forAll upolynomials $ \a ->
+  forAll upolynomials $ \b ->
+    let c = polyGCD a b
+    in a `polyMod` c == 0 && b `polyMod` c == 0
+
+prop_polyGCD_comm = 
+  forAll upolynomials $ \a ->
+  forAll upolynomials $ \b ->
+    polyGCD a b == polyGCD b a
+
+case_polyGCD_1 = polyGCD f1 f2 @?= 1
+  where 
+    x :: UPolynomial Rational
+    x = var ()
+    f1 = x^3 + x^2 + x
+    f2 = x^2 + 1
+
+prop_polyLCM_divisible =
+  forAll upolynomials $ \a ->
+  forAll upolynomials $ \b ->
+    (a /= 0 && b /= 0) ==>
+      let c = polyLCM a b
+      in c `polyMod` a == 0 && c `polyMod` b == 0
+
+prop_polyLCM_comm = 
+  forAll upolynomials $ \a ->
+  forAll upolynomials $ \b ->
+    polyLCM a b == polyLCM b a
+
+prop_deriv_integral =
+  forAll upolynomials $ \a ->
+    deriv (integral a x) x == a
+  where
+    x = ()
+
+prop_integral_deriv =
+  forAll upolynomials $ \a ->
+    deg (integral (deriv a x) x - a) == 0
+  where
+    x = ()
+
+{--------------------------------------------------------------------
+  Monomial
+--------------------------------------------------------------------}
+
+{--------------------------------------------------------------------
+  Monic Monomial
+--------------------------------------------------------------------}
+
+prop_mmDegreeOfProduct =
+  forAll monicMonomials $ \a -> 
+  forAll monicMonomials $ \b -> 
+    mmDegree (a `mmProd` b) == mmDegree a + mmDegree b
+
+prop_mmDegreeOfOne =
+  mmDegree mmOne == 0
+
+prop_mmProd_unitL = 
+  forAll monicMonomials $ \a -> 
+    mmOne `mmProd` a == a
+
+prop_mmProd_unitR = 
+  forAll monicMonomials $ \a -> 
+    a `mmProd` mmOne == a
+
+prop_mmProd_comm = 
+  forAll monicMonomials $ \a -> 
+  forAll monicMonomials $ \b -> 
+    a `mmProd` b == b `mmProd` a
+
+prop_mmProd_assoc = 
+  forAll monicMonomials $ \a ->
+  forAll monicMonomials $ \b ->
+  forAll monicMonomials $ \c ->
+    a `mmProd` (b `mmProd` c) == (a `mmProd` b) `mmProd` c
+
+prop_mmProd_Divisible = 
+  forAll monicMonomials $ \a -> 
+  forAll monicMonomials $ \b -> 
+    let c = a `mmProd` b
+    in mmDivisible c a && mmDivisible c b
+
+prop_mmProd_Div = 
+  forAll monicMonomials $ \a -> 
+  forAll monicMonomials $ \b -> 
+    let c = a `mmProd` b
+    in c `mmDiv` a == b && c `mmDiv` b == a
+
+case_mmDeriv = mmDeriv p 1 @?= (2, q)
+  where
+    p = mmFromList [(1,2),(2,4)]
+    q = mmFromList [(1,1),(2,4)]
+
+-- lcm (x1^2 * x2^4) (x1^3 * x2^1) = x1^3 * x2^4
+case_mmLCM = mmLCM p1 p2 @?= mmFromList [(1,3),(2,4)]
+  where
+    p1 = mmFromList [(1,2),(2,4)]
+    p2 = mmFromList [(1,3),(2,1)]
+
+-- gcd (x1^2 * x2^4) (x2^1 * x3^2) = x2
+case_mmGCD = mmGCD p1 p2 @?= mmFromList [(2,1)]
+  where
+    p1 = mmFromList [(1,2),(2,4)]
+    p2 = mmFromList [(2,1),(3,2)]
+
+prop_mmLCM_divisible = 
+  forAll monicMonomials $ \a -> 
+  forAll monicMonomials $ \b -> 
+    let c = mmLCM a b
+    in c `mmDivisible` a && c `mmDivisible` b
+
+prop_mmGCD_divisible = 
+  forAll monicMonomials $ \a -> 
+  forAll monicMonomials $ \b -> 
+    let c = mmGCD a b
+    in a `mmDivisible` c && b `mmDivisible` c
+
+{--------------------------------------------------------------------
+  Monomial Order
+--------------------------------------------------------------------}
+
+-- http://en.wikipedia.org/wiki/Monomial_order
+case_lex = sortBy lex [a,b,c,d] @?= [b,a,d,c]
+  where
+    x = 1
+    y = 2
+    z = 3
+    a = mmFromList [(x,1),(y,2),(z,1)]
+    b = mmFromList [(z,2)]
+    c = mmFromList [(x,3)]
+    d = mmFromList [(x,2),(z,2)]
+
+-- http://en.wikipedia.org/wiki/Monomial_order
+case_grlex = sortBy grlex [a,b,c,d] @?= [b,c,a,d]
+  where
+    x = 1
+    y = 2
+    z = 3
+    a = mmFromList [(x,1),(y,2),(z,1)]
+    b = mmFromList [(z,2)]
+    c = mmFromList [(x,3)]
+    d = mmFromList [(x,2),(z,2)]
+
+-- http://en.wikipedia.org/wiki/Monomial_order
+case_grevlex = sortBy grevlex [a,b,c,d] @?= [b,c,d,a]
+  where
+    x = 1
+    y = 2
+    z = 3
+    a = mmFromList [(x,1),(y,2),(z,1)]
+    b = mmFromList [(z,2)]
+    c = mmFromList [(x,3)]
+    d = mmFromList [(x,2),(z,2)]
+
+prop_refl_lex     = propRefl lex
+prop_refl_grlex   = propRefl grlex
+prop_refl_grevlex = propRefl grevlex
+
+prop_trans_lex     = propTrans lex
+prop_trans_grlex   = propTrans grlex
+prop_trans_grevlex = propTrans grevlex
+
+prop_sym_lex     = propSym lex
+prop_sym_grlex   = propSym grlex
+prop_sym_grevlex = propSym grevlex
+
+prop_monomial_order_property1_lex     = monomialOrderProp1 lex
+prop_monomial_order_property1_grlex   = monomialOrderProp1 grlex
+prop_monomial_order_property1_grevlex = monomialOrderProp1 grevlex
+
+prop_monomial_order_property2_lex     = monomialOrderProp2 lex
+prop_monomial_order_property2_grlex   = monomialOrderProp2 grlex
+prop_monomial_order_property2_grevlex = monomialOrderProp2 grevlex
+
+propRefl cmp =
+  forAll monicMonomials $ \a -> cmp a a == EQ
+
+propTrans cmp =
+  forAll monicMonomials $ \a ->
+  forAll monicMonomials $ \b ->
+    cmp a b == LT ==>
+      forAll monicMonomials $ \c ->
+        cmp b c == LT ==> cmp a c == LT
+
+propSym cmp =
+  forAll monicMonomials $ \a ->
+  forAll monicMonomials $ \b ->
+    cmp a b == flipOrdering (cmp b a)
+  where
+    flipOrdering EQ = EQ
+    flipOrdering LT = GT
+    flipOrdering GT = LT
+
+monomialOrderProp1 cmp =
+  forAll monicMonomials $ \a ->
+  forAll monicMonomials $ \b ->
+    let r = cmp a b
+    in cmp a b /= EQ ==>
+         forAll monicMonomials $ \c ->
+           cmp (a `mmProd` c) (b `mmProd` c) == r
+
+monomialOrderProp2 cmp =
+  forAll monicMonomials $ \a ->
+    a /= mmOne ==> cmp mmOne a == LT
+
+{--------------------------------------------------------------------
+  Gröbner basis
+--------------------------------------------------------------------}
+
+-- http://math.rice.edu/~cbruun/vigre/vigreHW6.pdf
+-- Example 1
+case_spolynomial = spolynomial grlex f g @?= - x^3*y^3 - constant (1/3) * y^3 + x^2
+  where
+    x = var 1
+    y = var 2
+    f, g :: Polynomial Rational Int
+    f = x^3*y^2 - x^2*y^3 + x
+    g = 3*x^4*y + y^2
+
+
+-- http://math.rice.edu/~cbruun/vigre/vigreHW6.pdf
+-- Exercise 1
+case_buchberger1 = Set.fromList gbase @?= Set.fromList expected
+  where
+    gbase = buchberger lex [x^2-y, x^3-z]
+    expected = [y^3 - z^2, x^2 - y, x*z - y^2, x*y - z]
+
+    x :: Polynomial Rational Int
+    x = var 1
+    y = var 2
+    z = var 3
+
+-- http://math.rice.edu/~cbruun/vigre/vigreHW6.pdf
+-- Exercise 2
+case_buchberger2 = Set.fromList gbase @?= Set.fromList expected
+  where
+    gbase = buchberger grlex [x^3-2*x*y, x^2*y-2*y^2+x]
+    expected = [x^2, x*y, y^2 - constant (1/2) * x]
+
+    x :: Polynomial Rational Int
+    x = var 1
+    y = var 2
+
+-- http://www.iisdavinci.it/jeometry/buchberger.html
+case_buchberger3 = Set.fromList gbase @?= Set.fromList expected
+  where
+    gbase = buchberger lex [x^2+2*x*y^2, x*y+2*y^3-1]
+    expected = [x, y^3 - constant (1/2)]
+    x :: Polynomial Rational Int
+    x = var 1
+    y = var 2
+
+-- http://www.orcca.on.ca/~reid/NewWeb/DetResDes/node4.html
+-- 時間がかかるので自動実行されるテストケースには含めていない
+test_buchberger4 = Set.fromList gbase @?= Set.fromList expected                   
+  where
+    x :: Polynomial Rational Int
+    x = var 1
+    y = var 2
+    z = var 3
+
+    gbase = buchberger lex [x^2+y*z-2, x*z+y^2-3, x*y+z^2-5]
+
+    expected = reduceGBase lex $
+      [ 8*z^8-100*z^6+438*z^4-760*z^2+361
+      , 361*y+8*z^7+52*z^5-740*z^3+1425*z
+      , 361*x-88*z^7+872*z^5-2690*z^3+2375*z
+      ]
+{-
+Risa/Asir での結果
+
+load("gr");
+gr([x^2+y*z-2, x*z+y^2-3, x*y+z^2-5],[x,y,z], 2);
+
+[8*z^8-100*z^6+438*z^4-760*z^2+361,
+361*y+8*z^7+52*z^5-740*z^3+1425*z,
+361*x-88*z^7+872*z^5-2690*z^3+2375*z]
+-}
+
+-- Seven Trees in One
+-- http://arxiv.org/abs/math/9405205
+case_Seven_Trees_in_One = reduce lex (x^7 - x) gbase @?= 0
+  where
+    x :: Polynomial Rational Int
+    x = var 1
+    gbase = buchberger lex [x-(x^2 + 1)]
+
+-- Non-linear loop invariant generation using Gröbner bases
+-- http://portal.acm.org/citation.cfm?id=964028
+-- http://www-step.stanford.edu/papers/popl04.pdf
+-- Example 3
+-- Consider again the ideal from Example 2; I = {f : x^2-y, g : y-z, h
+-- : x+z}.  The Gröbner basis for I is G = {f' : z^2-z, g : y-z, h :
+-- x+z}. With this basis, every reduction of p : x^2 - y^2 will yield
+-- a normal form 0.
+case_sankaranarayanan04nonlinear = do
+  Set.fromList gbase @?= Set.fromList [f', g, h]
+  reduce lex (x^2 - y^2) gbase @?= 0
+  where
+    x :: Polynomial Rational Int
+    x = var 1
+    y = var 2
+    z = var 3
+    f = x^2 - y
+    g = y - z
+    h = x + z
+    f' = z^2 - z
+    gbase = buchberger lex [f, g, h]
+
+{--------------------------------------------------------------------
+  Generators
+--------------------------------------------------------------------}
+
+monicMonomials :: Gen (MonicMonomial Int)
+monicMonomials = do
+  size <- choose (0, 3)
+  xs <- replicateM size $ do
+    v <- choose (-5, 5)
+    e <- liftM ((+1) . abs) arbitrary
+    return $ mmFromList [(v,e)]
+  return $ foldl mmProd mmOne xs
+
+monomials :: Gen (Monomial Rational Int)
+monomials = do
+  m <- monicMonomials
+  c <- arbitrary
+  return (c,m)
+
+polynomials :: Gen (Polynomial Rational Int)
+polynomials = do
+  size <- choose (0, 5)
+  xs <- replicateM size monomials
+  return $ sum $ map fromMonomial xs 
+
+umonicMonomials :: Gen (MonicMonomial ())
+umonicMonomials = do
+  size <- choose (0, 3)
+  xs <- replicateM size $ do
+    e <- choose (1, 4)
+    return $ mmFromList [((),e)]
+  return $ foldl mmProd mmOne xs
+
+umonomials :: Gen (Monomial Rational ())
+umonomials = do
+  m <- umonicMonomials
+  c <- arbitrary
+  return (c,m)
+
+upolynomials :: Gen (UPolynomial Rational)
+upolynomials = do
+  size <- choose (0, 5)
+  xs <- replicateM size umonomials
+  return $ sum $ map fromMonomial xs 
+
+------------------------------------------------------------------------
+
+-- http://mathworld.wolfram.com/SturmFunction.html
+case_sturmChain = sturmChain p0 @?= chain
+  where
+    x = var ()
+    p0 = x^5 - 3*x - 1
+    p1 = 5*x^4 - 3
+    p2 = constant (1/5) * (12*x + 5)
+    p3 = constant (59083 / 20736)
+    chain = [p0, p1, p2, p3]
+
+-- http://mathworld.wolfram.com/SturmFunction.html
+case_numRoots_1 =
+  sequence_
+  [ numRoots p (Interval.closedInterval (-2) 0)        @?= 2
+  , numRoots p (Interval.closedInterval 0 2)           @?= 1
+  , numRoots p (Interval.closedInterval (-1.5) (-1.0)) @?= 1
+  , numRoots p (Interval.closedInterval (-0.5) 0)      @?= 1
+  , numRoots p (Interval.closedInterval 1 (1.5))       @?= 1
+  ]
+  where
+    x = var ()
+    p = x^5 - 3*x - 1
+
+-- check interpretation of intervals
+case_numRoots_2 =
+  sequence_
+  [ numRoots p (Interval.interval (Just (False,2)) (Just (True,3)))  @?= 0
+  , numRoots p (Interval.interval (Just (True,2))  (Just (True,3)))  @?= 1
+  , numRoots p (Interval.interval (Just (False,1)) (Just (False,2))) @?= 0
+  , numRoots p (Interval.interval (Just (False,1)) (Just (True,2)))  @?= 1
+  ]
+  where
+    x = var ()
+    p = x^2 - 4
+
+case_separate = do
+  forM_ (zip vals intervals) $ \(v,ival) -> do
+    Interval.member v ival @?= True
+    forM_ (filter (v/=) vals) $ \v2 -> do
+      Interval.member v2 ival @?= False
+  where
+    x = var ()
+    p = x^5 - 3*x - 1
+    intervals = separate p
+    vals = [-1.21465, -0.334734, 1.38879]
+
+------------------------------------------------------------------------
+
+-- http://en.wikipedia.org/wiki/Lagrange_polynomial
+case_Lagrange_interpolation_1 = p @?= q
+  where
+    x :: UPolynomial Rational
+    x = var ()
+    p = Lagrange.interpolation
+        [ (1, 1)
+        , (2, 4)
+        , (3, 9)
+        ]
+    q = x^2
+
+-- http://en.wikipedia.org/wiki/Lagrange_polynomial
+case_Lagrange_interpolation_2 = p @?= q
+  where
+    x :: UPolynomial Rational
+    x = var ()
+    p = Lagrange.interpolation
+        [ (1, 1)
+        , (2, 8)
+        , (3, 27)
+        ]
+    q = 6*x^2 - 11*x + 6
+
+------------------------------------------------------------------------
+-- Test harness
+
+main :: IO ()
+main = $(defaultMainGenerator)
diff --git a/src/TestSAT.hs b/src/TestSAT.hs
new file mode 100644
--- /dev/null
+++ b/src/TestSAT.hs
@@ -0,0 +1,475 @@
+{-# LANGUAGE TemplateHaskell #-}
+module Main (main) where
+
+import Control.Monad
+import Data.List
+import Test.HUnit hiding (Test)
+import Test.Framework (Test, defaultMain, testGroup)
+import Test.Framework.TH
+import Test.Framework.Providers.HUnit
+import SAT
+import SAT.Types
+import qualified SAT.TseitinEncoder as Tseitin
+import SAT.TseitinEncoder (Formula (..))
+
+-- should be SAT
+case_solve_SAT :: IO ()
+case_solve_SAT = do
+  solver <- newSolver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  addClause solver [literal x1 True,  literal x2 True]  -- x1 or x2
+  addClause solver [literal x1 True,  literal x2 False] -- x1 or not x2
+  addClause solver [literal x1 False, literal x2 False] -- not x1 or not x2
+  ret <- solve solver
+  ret @?= True
+
+-- shuld be UNSAT
+case_solve_UNSAT :: IO ()
+case_solve_UNSAT = do
+  solver <- newSolver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  addClause solver [literal x1 True,  literal x2 True]  -- x1 or x2
+  addClause solver [literal x1 False, literal x2 True]  -- not x1 or x2
+  addClause solver [literal x1 True,  literal x2 False] -- x1 or not x2
+  addClause solver [literal x1 False, literal x2 False] -- not x2 or not x2
+  ret <- solve solver
+  ret @?= False
+
+-- top level でいきなり矛盾
+case_root_inconsistent :: IO ()
+case_root_inconsistent = do
+  solver <- newSolver
+  x1 <- newVar solver
+  addClause solver [literal x1 True]
+  addClause solver [literal x1 False]
+  ret <- solve solver -- unsat
+  ret @?= False
+
+-- incremental に制約を追加
+case_incremental_solving :: IO ()
+case_incremental_solving = do
+  solver <- newSolver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  addClause solver [literal x1 True,  literal x2 True]  -- x1 or x2
+  addClause solver [literal x1 True,  literal x2 False] -- x1 or not x2
+  addClause solver [literal x1 False, literal x2 False] -- not x1 or not x2
+  ret <- solve solver -- sat
+  ret @?= True
+
+  addClause solver [literal x1 False, literal x2 True]  -- not x1 or x2
+  ret <- solve solver -- unsat
+  ret @?= False
+
+-- 制約なし
+case_empty_constraint :: IO ()
+case_empty_constraint = do
+  solver <- newSolver
+  ret <- solve solver
+  ret @?= True
+
+-- 空の節
+case_empty_claue :: IO ()
+case_empty_claue = do
+  solver <- newSolver
+  addClause solver []
+  ret <- solve solver
+  ret @?= False
+
+-- 自明に真な節
+case_excluded_middle_claue :: IO ()
+case_excluded_middle_claue = do
+  solver <- newSolver
+  x1 <- newVar solver
+  addClause solver [x1, -x1] -- x1 or not x1
+  ret <- solve solver
+  ret @?= True
+
+-- 冗長な節
+case_redundant_clause :: IO ()
+case_redundant_clause = do
+  solver <- newSolver
+  x1 <- newVar solver
+  addClause solver [x1,x1] -- x1 or x1
+  ret <- solve solver
+  ret @?= True
+
+case_instantiateClause :: IO ()
+case_instantiateClause = do
+  solver <- newSolver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  addClause solver [x1]
+  addClause solver [x1,x2]
+  addClause solver [-x1,x2]
+  ret <- solve solver
+  ret @?= True
+
+case_instantiateAtLeast :: IO ()
+case_instantiateAtLeast = do
+  solver <- newSolver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  x3 <- newVar solver
+  x4 <- newVar solver
+  addClause solver [x1]
+
+  addAtLeast solver [x1,x2,x3,x4] 2
+  ret <- solve solver
+  ret @?= True
+
+  addAtLeast solver [-x1,-x2,-x3,-x4] 2
+  ret <- solve solver
+  ret @?= True
+
+case_inconsistent_AtLeast :: IO ()
+case_inconsistent_AtLeast = do
+  solver <- newSolver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  addAtLeast solver [x1,x2] 3
+  ret <- solve solver -- unsat
+  ret @?= False
+
+case_trivial_AtLeast :: IO ()
+case_trivial_AtLeast = do
+  solver <- newSolver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  addAtLeast solver [x1,x2] 0
+  ret <- solve solver
+  ret @?= True
+
+  solver <- newSolver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  addAtLeast solver [x1,x2] (-1)
+  ret <- solve solver
+  ret @?= True
+
+case_AtLeast_1 :: IO ()
+case_AtLeast_1 = do
+  solver <- newSolver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  x3 <- newVar solver
+  addAtLeast solver [x1,x2,x3] 2
+  addAtLeast solver [-x1,-x2,-x3] 2
+  ret <- solve solver -- unsat
+  ret @?= False
+
+case_AtLeast_2 :: IO ()
+case_AtLeast_2 = do
+  solver <- newSolver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  x3 <- newVar solver
+  x4 <- newVar solver
+  addAtLeast solver [x1,x2,x3,x4] 2
+  addClause solver [-x1,-x2]
+  addClause solver [-x1,-x3]
+  ret <- solve solver
+  ret @?= True
+
+case_AtLeast_3 :: IO ()
+case_AtLeast_3 = do
+  forM_ [(-1) .. 3] $ \n -> do
+    solver <- newSolver
+    x1 <- newVar solver
+    x2 <- newVar solver
+    addAtLeast solver [x1,x2] n
+    ret <- solve solver
+    assertEqual ("case_AtLeast3_" ++ show n) (n <= 2) ret
+
+-- from http://www.cril.univ-artois.fr/PB11/format.pdf
+case_PB_sample1 :: IO ()
+case_PB_sample1 = do
+  solver <- newSolver
+
+  x1 <- newVar solver
+  x2 <- newVar solver
+  x3 <- newVar solver
+  x4 <- newVar solver
+  x5 <- newVar solver
+
+  addPBAtLeast solver [(1,x1),(4,x2),(-2,x5)] 2
+  addPBAtLeast solver [(-1,x1),(4,x2),(-2,x5)] 3
+  addPBAtLeast solver [(12345678901234567890,x4),(4,x3)] 10
+  addPBExactly solver [(2,x2),(3,x4),(2,x1),(3,x5)] 5
+
+  ret <- solve solver
+  ret @?= True
+
+-- 一部の変数を否定に置き換えたもの
+case_PB_sample1' :: IO ()
+case_PB_sample1' = do
+  solver <- newSolver
+
+  x1 <- newVar solver
+  x2 <- newVar solver
+  x3 <- newVar solver
+  x4 <- newVar solver
+  x5 <- newVar solver
+
+  addPBAtLeast solver [(1,x1),(4,-x2),(-2,x5)] 2
+  addPBAtLeast solver [(-1,x1),(4,-x2),(-2,x5)] 3
+  addPBAtLeast solver [(12345678901234567890,-x4),(4,x3)] 10
+  addPBExactly solver [(2,-x2),(3,-x4),(2,x1),(3,x5)] 5
+
+  ret <- solve solver
+  ret @?= True
+
+-- いきなり矛盾したPB制約
+case_root_inconsistent_PB :: IO ()
+case_root_inconsistent_PB = do
+  solver <- newSolver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  addPBAtLeast solver [(2,x1),(3,x2)] 6
+  ret <- solve solver
+  ret @?= False
+
+case_pb_propagate :: IO ()
+case_pb_propagate = do
+  solver <- newSolver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  addPBAtLeast solver [(1,x1),(3,x2)] 3
+  addClause solver [-x1]
+  ret <- solve solver
+  ret @?= True
+
+case_solveWith_1 :: IO ()
+case_solveWith_1 = do
+  solver <- newSolver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  x3 <- newVar solver
+  addClause solver [x1, x2]       -- x1 or x2
+  addClause solver [x1, -x2]      -- x1 or not x2
+  addClause solver [-x1, -x2]     -- not x1 or not x2
+  addClause solver [-x3, -x1, x2] -- not x3 or not x1 or x2
+
+  ret <- solve solver -- sat
+  ret @?= True
+
+  ret <- solveWith solver [x3] -- unsat
+  ret @?= False
+
+  ret <- solve solver -- sat
+  ret @?= True
+
+case_solveWith_2 :: IO ()
+case_solveWith_2 = do
+  solver <- newSolver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  addClause solver [-x1, x2] -- -x1 or x2
+  addClause solver [x1]      -- x1
+
+  ret <- solveWith solver [x2]
+  ret @?= True
+
+  ret <- solveWith solver [-x2]
+  ret @?= False
+
+------------------------------------------------------------------------
+
+-- -4*(not x1) + 3*x1 + 10*(not x2) >= 3
+-- ⇔ -4*(1 - x1) + 3*x1 + 10*(not x2) >= 3
+-- ⇔ -4 + 4*x1 + 3*x1 + 10*(not x2) >= 3
+-- ⇔ 7*x1 + 10*(not x2) >= 7
+-- ⇔ 7*x1 + 7*(not x2) >= 7
+-- ⇔ x1 + (not x2) >= 1
+case_normalizePBAtLeast :: Assertion
+case_normalizePBAtLeast = (sort lhs, rhs) @?= (sort [(1,x1),(1,-x2)], 1)
+  where
+    x1 = 1
+    x2 = 2
+    (lhs,rhs) = normalizePBAtLeast ([(-4,-x1),(3,x1),(10,-x2)], 3)
+
+case_normalizePBExactly_1 :: Assertion
+case_normalizePBExactly_1 = (sort lhs, rhs) @?= (sort [(3,x1),(2,x2)], 1)
+  where
+    x1 = 1
+    x2 = 2
+    (lhs,rhs) = normalizePBExactly ([(6,x1),(4,x2)], 2)
+
+case_normalizePBExactly_2 :: Assertion
+case_normalizePBExactly_2 = (sort lhs, rhs) @?= ([], 1)
+  where
+    x1 = 1
+    x2 = 2
+    x3 = 3
+    (lhs,rhs) = normalizePBExactly ([(2,x1),(2,x2),(2,x3)], 3)
+
+case_cutResolve_1 :: Assertion
+case_cutResolve_1 = (sort lhs, rhs) @?= (sort [(1,x3),(1,x4)], 1)
+  where
+    x1 = 1
+    x2 = 2
+    x3 = 3
+    x4 = 4
+    pb1 = ([(1,x1), (1,x2), (1,x3)], 1)
+    pb2 = ([(2,-x1), (2,-x2), (1,x4)], 3)
+    (lhs,rhs) = cutResolve pb1 pb2 x1
+
+case_cutResolve_2 :: Assertion
+case_cutResolve_2 = (sort lhs, rhs) @?= (sort [(3,x1),(2,-x2),(2,x4)], 3)
+  where
+    x1 = 1
+    x2 = 2
+    x3 = 3
+    x4 = 4
+    pb1 = ([(3,x1), (2,-x2), (1,x3), (1,x4)], 3)
+    pb2 = ([(1,-x3), (1,x4)], 1)
+    (lhs,rhs) = cutResolve pb1 pb2 x3
+
+case_cardinalityReduction :: Assertion
+case_cardinalityReduction = (sort lhs, rhs) @?= ([1,2,3,4,5],4)
+  where
+    (lhs, rhs) = cardinalityReduction ([(6,1),(5,2),(4,3),(3,4),(2,5),(1,6)], 17)
+
+-- from "Pueblo: A Hybrid Pseudo-Boolean SAT Solver"
+-- clauseがunitになるレベルで、PB制約が違反状態のままという例。
+case_hybridLearning_1 :: IO ()
+case_hybridLearning_1 = do
+  solver <- newSolver
+  [x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11] <- replicateM 11 (newVar solver)
+
+  addClause solver [x11, x10, x9] -- C1
+  addClause solver [x8, x7, x6]   -- C2
+  addClause solver [x5, x4, x3]   -- C3
+  addAtLeast solver [-x2, -x5, -x8, -x11] 3 -- C4
+  addAtLeast solver [-x1, -x4, -x7, -x10] 3 -- C5
+
+  replicateM 3 (varBumpActivity solver x3)
+  setVarPolarity solver x3 False
+
+  replicateM 2 (varBumpActivity solver x6)
+  setVarPolarity solver x6 False
+
+  replicateM 1 (varBumpActivity solver x9)
+  setVarPolarity solver x9 False
+
+  setVarPolarity solver x1 True
+
+  setLearningStrategy solver LearningHybrid
+  ret <- solve solver
+  ret @?= True
+
+-- from "Pueblo: A Hybrid Pseudo-Boolean SAT Solver"
+-- clauseがunitになるレベルで、PB制約が違反状態のままという例。
+-- さらに、学習したPB制約はunitにはならない。
+case_hybridLearning_2 :: IO ()
+case_hybridLearning_2 = do
+  solver <- newSolver
+  [x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12] <- replicateM 12 (newVar solver)
+
+  addClause solver [x11, x10, x9] -- C1
+  addClause solver [x8, x7, x6]   -- C2
+  addClause solver [x5, x4, x3]   -- C3
+  addAtLeast solver [-x2, -x5, -x8, -x11] 3 -- C4
+  addAtLeast solver [-x1, -x4, -x7, -x10] 3 -- C5
+
+  addClause solver [x12, -x3]
+  addClause solver [x12, -x6]
+  addClause solver [x12, -x9]
+
+  varBumpActivity solver x12
+  setVarPolarity solver x12 False
+
+  setLearningStrategy solver LearningHybrid
+  ret <- solve solver
+  ret @?= True
+
+-- regression test for the bug triggered by normalized-blast-floppy1-8.ucl.opb.bz2
+case_addPBAtLeast_regression :: IO ()
+case_addPBAtLeast_regression = do
+  solver <- newSolver
+  [x1,x2,x3,x4] <- replicateM 4 (newVar solver)
+  addClause solver [-x1]
+  addClause solver [-x2, -x3]
+  addClause solver [-x2, -x4]
+  addPBAtLeast solver [(1,x1),(2,x2),(1,x3),(1,x4)] 3
+  ret <- solve solver
+  ret @?= False
+
+------------------------------------------------------------------------
+
+case_addFormula = do
+  solver <- newSolver
+  enc <- Tseitin.newEncoder solver
+
+  [x1,x2,x3,x4,x5] <- replicateM 5 $ liftM Var $ newVar solver
+  Tseitin.addFormula enc $ Or [Imply x1 (And [x3,x4]), Imply x2 (And [x3,x5])]
+  -- x6 = x3 ∧ x4
+  -- x7 = x3 ∧ x5
+  Tseitin.addFormula enc $ Or [x1, x2]
+  Tseitin.addFormula enc $ Imply x4 (Not x5)
+  ret <- solve solver
+  ret @?= True
+
+  Tseitin.addFormula enc $ Equiv x2 x4
+  ret <- solve solver
+  ret @?= True
+
+  Tseitin.addFormula enc $ Equiv x1 x5
+  ret <- solve solver
+  ret @?= True
+
+  Tseitin.addFormula enc $ Imply (Not x1) (And [x3,x5])
+  ret <- solve solver
+  ret @?= True
+
+  Tseitin.addFormula enc $ Imply (Not x2) (And [x3,x4])
+  ret <- solve solver
+  ret @?= False
+
+case_encodeConj = do
+  solver <- newSolver
+  enc <- Tseitin.newEncoder solver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  x3 <- Tseitin.encodeConj enc [x1,x2]
+
+  ret <- solveWith solver [x3]
+  ret @?= True
+  m <- model solver
+  evalLit m x1 @?= True
+  evalLit m x2 @?= True
+  evalLit m x3 @?= True
+
+  ret <- solveWith solver [-x3]
+  ret @?= True
+  m <- model solver
+  (evalLit m x1 && evalLit m x2) @?= False
+  evalLit m x3 @?= False
+
+case_encodeDisj = do
+  solver <- newSolver
+  enc <- Tseitin.newEncoder solver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  x3 <- Tseitin.encodeDisj enc [x1,x2]
+
+  ret <- solveWith solver [x3]
+  ret @?= True
+  m <- model solver
+  (evalLit m x1 || evalLit m x2) @?= True
+  evalLit m x3 @?= True
+
+  ret <- solveWith solver [-x3]
+  ret @?= True
+  m <- model solver
+  evalLit m x1 @?= False
+  evalLit m x2 @?= False
+  evalLit m x3 @?= False
+
+------------------------------------------------------------------------
+-- Test harness
+
+main :: IO ()
+main = $(defaultMainGenerator)
diff --git a/src/TestSimplex2.hs b/src/TestSimplex2.hs
new file mode 100644
--- /dev/null
+++ b/src/TestSimplex2.hs
@@ -0,0 +1,409 @@
+{-# LANGUAGE TemplateHaskell #-}
+module Main (main) where
+
+import Control.Monad
+import Data.List
+import Data.Ratio
+import Test.HUnit hiding (Test)
+import Test.Framework (Test, defaultMain, testGroup)
+import Test.Framework.TH
+import Test.Framework.Providers.HUnit
+import Text.Printf
+
+import Data.Linear
+import Simplex2
+import qualified Data.LA as LA
+
+case_test1 :: IO ()
+case_test1 = do
+  solver <- newSolver
+  x <- newVar solver
+  y <- newVar solver
+  z <- newVar solver
+  assertAtom solver (LA.fromTerms [(7,x), (12,y), (31,z)] .==. LA.constant 17)
+  assertAtom solver (LA.fromTerms [(3,x), (5,y), (14,z)]  .==. LA.constant 7)
+  assertAtom solver (LA.var x .>=. LA.constant 1)
+  assertAtom solver (LA.var x .<=. LA.constant 40)
+  assertAtom solver (LA.var y .>=. LA.constant (-50))
+  assertAtom solver (LA.var y .<=. LA.constant 50)
+
+  ret <- check solver
+  ret @?= True
+
+  vx <- getValue solver x
+  vy <- getValue solver y
+  vz <- getValue solver z
+  7*vx + 12*vy + 31*vz @?= 17
+  3*vx + 5*vy + 14*vz @?= 7
+  assertBool (printf "vx should be >=1 but %s"   (show vx)) $ vx >= 1
+  assertBool (printf "vx should be <=40 but %s"  (show vx)) $ vx <= 40
+  assertBool (printf "vx should be >=-50 but %s" (show vy)) $ vy >= -50
+  assertBool (printf "vx should be <=50 but %s"  (show vy)) $ vy <= 50
+
+case_test2 :: IO ()
+case_test2 = do
+  solver <- newSolver
+  x <- newVar solver
+  y <- newVar solver
+  assertAtom solver (LA.fromTerms [(11,x), (13,y)] .>=. LA.constant 27)
+  assertAtom solver (LA.fromTerms [(11,x), (13,y)] .<=. LA.constant 45)
+  assertAtom solver (LA.fromTerms [(7,x), (-9,y)] .>=. LA.constant (-10))
+  assertAtom solver (LA.fromTerms [(7,x), (-9,y)] .<=. LA.constant 4)
+
+  ret <- check solver
+  ret @?= True
+
+  vx <- getValue solver x
+  vy <- getValue solver y
+  let v1 = 11*vx + 13*vy
+      v2 = 7*vx - 9*vy
+  assertBool (printf "11*vx + 13*vy should be >=27 but %s" (show v1)) $ 27 <= v1
+  assertBool (printf "11*vx + 13*vy should be <=45 but %s" (show v1)) $ v1 <= 45
+  assertBool (printf "7*vx - 9*vy should be >=-10 but %s" (show v2)) $ -10 <= v2
+  assertBool (printf "7*vx - 9*vy should be >=-10 but %s" (show v2)) $ v2 <= 4
+
+
+{-
+Minimize
+ obj: - x1 - 2 x2 - 3 x3 - x4
+Subject To
+ c1: - x1 + x2 + x3 + 10 x4 <= 20
+ c2: x1 - 3 x2 + x3 <= 30
+ c3: x2 - 3.5 x4 = 0
+Bounds
+ 0 <= x1 <= 40
+ 2 <= x4 <= 3
+End
+-}
+case_test3 :: IO ()
+case_test3 = do
+  solver <- newSolver
+
+  _ <- newVar solver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  x3 <- newVar solver
+  x4 <- newVar solver
+
+  setObj solver (LA.fromTerms [(-1,x1), (-2,x2), (-3,x3), (-1,x4)])
+
+  assertAtom solver (LA.fromTerms [(-1,x1), (1,x2), (1,x3), (10,x4)] .<=. LA.constant 20)
+  assertAtom solver (LA.fromTerms [(1,x1), (-3,x2), (1,x3)] .<=. LA.constant 30)
+  assertAtom solver (LA.fromTerms [(1,x2), (-3.5,x4)] .==. LA.constant 0)
+
+  assertAtom solver (LA.fromTerms [(1,x1)] .>=. LA.constant 0)
+  assertAtom solver (LA.fromTerms [(1,x1)] .<=. LA.constant 40)
+  assertAtom solver (LA.fromTerms [(1,x2)] .>=. LA.constant 0)
+  assertAtom solver (LA.fromTerms [(1,x3)] .>=. LA.constant 0)
+  assertAtom solver (LA.fromTerms [(1,x4)] .>=. LA.constant 2)
+  assertAtom solver (LA.fromTerms [(1,x4)] .<=. LA.constant 3)
+
+  ret1 <- check solver
+  ret1 @?= True
+
+  ret2 <- optimize solver defaultOptions
+  ret2 @?= Optimum
+
+{-
+http://www.math.cuhk.edu.hk/~wei/lpch5.pdf
+example 5.7
+
+minimize 3 x1 + 4 x2 + 5 x3
+subject to 
+1 x1 + 2 x2 + 3 x3 >= 5
+2 x1 + 2 x2 + 1 x3 >= 6
+
+optimal value is 11
+-}
+case_test6 :: IO ()
+case_test6 = do
+  solver <- newSolver
+
+  _  <- newVar solver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  x3 <- newVar solver
+
+  assertLower solver x1 0
+  assertLower solver x2 0
+  assertLower solver x3 0
+  assertAtom solver (LA.fromTerms [(1,x1),(2,x2),(3,x3)] .>=. LA.constant 5)
+  assertAtom solver (LA.fromTerms [(2,x1),(2,x2),(1,x3)] .>=. LA.constant 6)
+
+  setObj solver (LA.fromTerms [(3,x1),(4,x2),(5,x3)])
+  setOptDir solver OptMin
+  b <- isOptimal solver
+  assertBool "should be optimal" $ b
+
+  ret <- dualSimplex solver defaultOptions
+  ret @?= Optimum
+
+  val <- getObjValue solver
+  val @?= 11
+
+{-
+http://www.math.cuhk.edu.hk/~wei/lpch5.pdf
+example 5.7
+
+maximize -3 x1 -4 x2 -5 x3
+subject to 
+-1 x1 -2 x2 -3 x3 <= -5
+-2 x1 -2 x2 -1 x3 <= -6
+
+optimal value should be -11
+-}
+case_test7 :: IO ()
+case_test7 = do
+  solver <- newSolver
+
+  _  <- newVar solver
+  x1 <- newVar solver
+  x2 <- newVar solver
+  x3 <- newVar solver
+
+  assertLower solver x1 0
+  assertLower solver x2 0
+  assertLower solver x3 0
+  assertAtom solver (LA.fromTerms [(-1,x1),(-2,x2),(-3,x3)] .<=. LA.constant (-5))
+  assertAtom solver (LA.fromTerms [(-2,x1),(-2,x2),(-1,x3)] .<=. LA.constant (-6))
+
+  setObj solver (LA.fromTerms [(-3,x1),(-4,x2),(-5,x3)])
+  setOptDir solver OptMax
+  b <- isOptimal solver
+  assertBool "should be optimal" $ b
+
+  ret <- dualSimplex solver defaultOptions
+  ret @?= Optimum
+
+  val <- getObjValue solver
+  val @?= -11
+
+case_AssertAtom :: IO ()
+case_AssertAtom = do
+  solver <- newSolver
+  x0 <- newVar solver
+  assertAtom solver (LA.constant 1 .<=. LA.var x0)
+  ret <- getLB solver x0
+  ret @?= Just 1
+
+  solver <- newSolver
+  x0 <- newVar solver
+  assertAtom solver (LA.var x0 .>=. LA.constant 1)
+  ret <- getLB solver x0
+  ret @?= Just 1
+
+  solver <- newSolver
+  x0 <- newVar solver
+  assertAtom solver (LA.constant 1 .>=. LA.var x0)
+  ret <- getUB solver x0
+  ret @?= Just 1
+
+  solver <- newSolver
+  x0 <- newVar solver
+  assertAtom solver (LA.var x0 .<=. LA.constant 1)
+  ret <- getUB solver x0
+  ret @?= Just 1
+
+------------------------------------------------------------------------
+
+case_example_3_2 = do
+  solver <- newSolver
+  [x1,x2,x3] <- replicateM 3 (newVar solver)
+  setOptDir solver OptMax
+  setObj solver $ LA.fromTerms [(3,x1), (2,x2), (3,x3)]
+  mapM_ (assertAtom solver) $
+    [ LA.fromTerms [(2,x1), (1,x2), (1,x3)] .<=. LA.constant 2
+    , LA.fromTerms [(1,x1), (2,x2), (3,x3)] .<=. LA.constant 5
+    , LA.fromTerms [(2,x1), (2,x2), (1,x3)] .<=. LA.constant 6
+    , LA.var x1 .>=. LA.constant 0
+    , LA.var x2 .>=. LA.constant 0
+    , LA.var x3 .>=. LA.constant 0
+    ]
+
+  ret <- optimize solver defaultOptions
+  ret @?= Optimum
+  val <- getObjValue solver
+  val @?= 27/5
+
+  forM_ [(x1,1/5),(x2,0),(x3,8/5)] $ \(var,expected) -> do
+    val <- getValue solver var
+    val @?= expected
+
+case_example_3_5 = do
+  solver <- newSolver
+  [x1,x2,x3,x4,x5] <- replicateM 5 (newVar solver)
+  setOptDir solver OptMin
+  setObj solver $ LA.fromTerms [(-2,x1), (4,x2), (7,x3), (1,x4), (5,x5)]
+  mapM_ (assertAtom solver) $
+    [ LA.fromTerms [(-1,x1), (1,x2), (2,x3), (1,x4), (2,x5)] .==. LA.constant 7
+    , LA.fromTerms [(-1,x1), (2,x2), (3,x3), (1,x4), (1,x5)] .==. LA.constant 6
+    , LA.fromTerms [(-1,x1), (1,x2), (1,x3), (2,x4), (1,x5)] .==. LA.constant 4
+    , LA.var x2 .>=. LA.constant 0
+    , LA.var x3 .>=. LA.constant 0
+    , LA.var x4 .>=. LA.constant 0
+    , LA.var x5 .>=. LA.constant 0
+    ]
+
+  ret <- optimize solver defaultOptions
+  ret @?= Optimum
+  val <- getObjValue solver
+  val @?= 19
+
+  forM_ [(x1,-1),(x2,0),(x3,1),(x4,0),(x5,2)] $ \(var,expected) -> do
+    val <- getValue solver var
+    val @?= expected
+
+case_example_4_1 = do
+  solver <- newSolver
+  [x1,x2] <- replicateM 2 (newVar solver)
+  setOptDir solver OptMin
+  setObj solver $ LA.fromTerms [(2,x1), (1,x2)]
+  mapM_ (assertAtom solver) $
+    [ LA.fromTerms [(-1,x1), (1,x2)] .>=. LA.constant 2
+    , LA.fromTerms [( 1,x1), (1,x2)] .<=. LA.constant 1
+    , LA.var x1 .>=. LA.constant 0
+    , LA.var x2 .>=. LA.constant 0
+    ]
+  ret <- optimize solver defaultOptions
+  ret @?= Unsat
+
+case_example_4_2 = do
+  solver <- newSolver
+  [x1,x2] <- replicateM 2 (newVar solver)
+  setOptDir solver OptMax
+  setObj solver $ LA.fromTerms [(2,x1), (1,x2)]
+  mapM_ (assertAtom solver) $
+    [ LA.fromTerms [(-1,x1), (-1,x2)] .<=. LA.constant 10
+    , LA.fromTerms [( 2,x1), (-1,x2)] .<=. LA.constant 40
+    , LA.var x1 .>=. LA.constant 0
+    , LA.var x2 .>=. LA.constant 0
+    ]
+  ret <- optimize solver defaultOptions
+  ret @?= Unbounded
+
+case_example_4_3 = do
+  solver <- newSolver
+  [x1,x2] <- replicateM 2 (newVar solver)
+  setOptDir solver OptMax
+  setObj solver $ LA.fromTerms [(6,x1), (-2,x2)]
+  mapM_ (assertAtom solver) $
+    [ LA.fromTerms [(2,x1), (-1,x2)] .<=. LA.constant 2
+    , LA.var x1 .<=. LA.constant 4
+    , LA.var x1 .>=. LA.constant 0
+    , LA.var x2 .>=. LA.constant 0
+    ]
+
+  ret <- optimize solver defaultOptions
+  ret @?= Optimum
+  val <- getObjValue solver
+  val @?= 12
+
+  forM_ [(x1,4),(x2,6)] $ \(var,expected) -> do
+    val <- getValue solver var
+    val @?= expected
+
+case_example_4_5 = do
+  solver <- newSolver
+  [x1,x2] <- replicateM 2 (newVar solver)
+  setOptDir solver OptMax
+  setObj solver $ LA.fromTerms [(2,x1), (1,x2)]
+  mapM_ (assertAtom solver) $
+    [ LA.fromTerms [(4,x1), ( 3,x2)] .<=. LA.constant 12
+    , LA.fromTerms [(4,x1), ( 1,x2)] .<=. LA.constant 8
+    , LA.fromTerms [(4,x1), (-1,x2)] .<=. LA.constant 8
+    , LA.var x1 .>=. LA.constant 0
+    , LA.var x2 .>=. LA.constant 0
+    ]
+
+  ret <- optimize solver defaultOptions
+  ret @?= Optimum
+  val <- getObjValue solver
+  val @?= 5
+
+  forM_ [(x1,3/2),(x2,2)] $ \(var,expected) -> do
+    val <- getValue solver var
+    val @?= expected
+
+case_example_4_6 = do
+  solver <- newSolver
+  [x1,x2,x3,x4] <- replicateM 4 (newVar solver)
+  setOptDir solver OptMax
+  setObj solver $ LA.fromTerms [(20,x1), (1/2,x2), (-6,x3), (3/4,x4)]
+  mapM_ (assertAtom solver) $
+    [ LA.var x1 .<=. LA.constant 2
+    , LA.fromTerms [( 8,x1), (  -1,x2), (9,x3), (1/4, x4)] .<=. LA.constant 16
+    , LA.fromTerms [(12,x1), (-1/2,x2), (3,x3), (1/2, x4)] .<=. LA.constant 24
+    , LA.var x2 .<=. LA.constant 1
+    , LA.var x1 .>=. LA.constant 0
+    , LA.var x2 .>=. LA.constant 0
+    , LA.var x3 .>=. LA.constant 0
+    , LA.var x4 .>=. LA.constant 0
+    ]
+
+  ret <- optimize solver defaultOptions
+  ret @?= Optimum
+  val <- getObjValue solver
+  val @?= 165/4
+
+  forM_ [(x1,2),(x2,1),(x3,0),(x4,1)] $ \(var,expected) -> do
+    val <- getValue solver var
+    val @?= expected
+
+case_example_4_7 = do
+  solver <- newSolver
+  [x1,x2,x3,x4] <- replicateM 4 (newVar solver)
+  setOptDir solver OptMax
+  setObj solver $ LA.fromTerms [(1,x1), (1.5,x2), (5,x3), (2,x4)]
+  mapM_ (assertAtom solver) $
+    [ LA.fromTerms [(3,x1), (2,x2), ( 1,x3), (4,x4)] .<=. LA.constant 6
+    , LA.fromTerms [(2,x1), (1,x2), ( 5,x3), (1,x4)] .<=. LA.constant 4
+    , LA.fromTerms [(2,x1), (6,x2), (-4,x3), (8,x4)] .==. LA.constant 0
+    , LA.fromTerms [(1,x1), (3,x2), (-2,x3), (4,x4)] .==. LA.constant 0
+    , LA.var x1 .>=. LA.constant 0
+    , LA.var x2 .>=. LA.constant 0
+    , LA.var x3 .>=. LA.constant 0
+    , LA.var x4 .>=. LA.constant 0
+    ]
+
+  ret <- optimize solver defaultOptions
+  ret @?= Optimum
+  val <- getObjValue solver
+  val @?= 48/11
+
+  forM_ [(x1,0),(x2,0),(x3,8/11),(x4,4/11)] $ \(var,expected) -> do
+    val <- getValue solver var
+    val @?= expected
+
+-- 退化して巡回の起こるKuhnの7変数3制約の例
+case_kuhn_7_3 = do
+  solver <- newSolver
+  [x1,x2,x3,x4,x5,x6,x7] <- replicateM 7 (newVar solver)
+  setOptDir solver OptMin
+  setObj solver $ LA.fromTerms [(-2,x4),(-3,x5),(1,x6),(12,x7)]
+  mapM_ (assertAtom solver) $
+    [ LA.fromTerms [(1,x1), ( -2,x4), (-9,x5), (   1,x6), (  9,x7)] .==. LA.constant 0
+    , LA.fromTerms [(1,x2), (1/3,x4), ( 1,x5), (-1/3,x6), ( -2,x7)] .==. LA.constant 0
+    , LA.fromTerms [(1,x3), (  2,x4), ( 3,x5), (  -1,x6), (-12,x7)] .==. LA.constant 2
+    , LA.var x1 .>=. LA.constant 0
+    , LA.var x2 .>=. LA.constant 0
+    , LA.var x3 .>=. LA.constant 0
+    , LA.var x4 .>=. LA.constant 0
+    , LA.var x5 .>=. LA.constant 0
+    , LA.var x6 .>=. LA.constant 0
+    , LA.var x7 .>=. LA.constant 0
+    ]
+
+  ret <- optimize solver defaultOptions
+  ret @?= Optimum
+  val <- getObjValue solver
+  val @?= -2
+
+  forM_ [(x1,2),(x2,0),(x3,0),(x4,2),(x5,0),(x6,2),(x7,0)] $ \(var,expected) -> do
+    val <- getValue solver var
+    val @?= expected
+
+------------------------------------------------------------------------
+-- Test harness
+
+main :: IO ()
+main = $(defaultMainGenerator)
diff --git a/src/Text/LPFile.hs b/src/Text/LPFile.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/LPFile.hs
@@ -0,0 +1,677 @@
+{-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Text.LPFile
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- A CPLEX .lp format parser library.
+-- 
+-- References:
+-- 
+-- * <http://publib.boulder.ibm.com/infocenter/cosinfoc/v12r2/index.jsp?topic=/ilog.odms.cplex.help/Content/Optimization/Documentation/CPLEX/_pubskel/CPLEX880.html>
+-- 
+-- * <http://www.gurobi.com/doc/45/refman/node589.html>
+-- 
+-- * <http://lpsolve.sourceforge.net/5.5/CPLEX-format.htm>
+--
+-----------------------------------------------------------------------------
+module Text.LPFile
+  ( LP (..)
+  , Expr
+  , Term (..)
+  , OptDir (..)
+  , ObjectiveFunction
+  , ConstraintType (..)
+  , Constraint (..)
+  , Bounds
+  , Label
+  , Var
+  , BoundExpr (..)
+  , RelOp (..)
+  , SOSType (..)
+  , SOS
+  , defaultBounds
+  , defaultLB
+  , defaultUB
+  , getBounds
+  , parseString
+  , parseFile
+  , render
+  ) where
+
+import Control.Monad
+import Control.Monad.Writer
+import Data.Char
+import Data.List
+import Data.Maybe
+import Data.Ratio
+import qualified Data.Map as Map
+import qualified Data.Set as Set
+import Data.OptDir
+import Text.ParserCombinators.Parsec hiding (label)
+
+import Util (combineMaybe)
+
+-- ---------------------------------------------------------------------------
+
+-- | Problem
+data LP
+  = LP
+  { variables :: Set.Set Var
+  , dir :: OptDir
+  , objectiveFunction :: ObjectiveFunction
+  , constraints :: [Constraint]
+  , bounds :: Map.Map Var Bounds
+  , integerVariables :: Set.Set Var
+  , binaryVariables :: Set.Set Var
+  , semiContinuousVariables :: Set.Set Var
+  , sos :: [SOS]
+  }
+  deriving (Show, Eq, Ord)
+
+-- | expressions
+type Expr = [Term]
+
+-- | terms
+data Term = Term Rational [Var]
+  deriving (Eq, Ord, Show)
+
+-- | objective function
+type ObjectiveFunction = (Maybe Label, Expr)
+
+data ConstraintType
+  = NormalConstraint
+  | LazyConstraint
+  | UserDefinedCut
+  deriving (Eq, Ord, Bounded, Enum, Show)
+
+-- | constraint
+data Constraint
+  = Constraint
+  { constrType      :: ConstraintType
+  , constrLabel     :: Maybe Label
+  , constrIndicator :: Maybe (Var, Rational)
+  , constrBody      :: (Expr, RelOp, Rational)
+  }
+  deriving (Eq, Ord, Show)
+
+-- | type for representing lower/upper bound of variables
+type Bounds = (BoundExpr, BoundExpr)
+
+-- | label
+type Label = String
+
+-- | variable
+type Var = String
+
+-- | type for representing lower/upper bound of variables
+data BoundExpr = NegInf | Finite Rational | PosInf
+    deriving (Eq, Ord, Show)
+
+-- | relational operators
+data RelOp = Le | Ge | Eql
+    deriving (Eq, Ord, Enum, Show)
+
+-- | types of SOS (special ordered sets) constraints
+data SOSType
+  = S1 -- ^ Type 1 SOS constraint
+  | S2 -- ^ Type 2 SOS constraint
+    deriving (Eq, Ord, Enum, Show, Read)
+
+-- | SOS (special ordered sets) constraints
+type SOS = (Maybe Label, SOSType, [(Var, Rational)])
+
+class Variables a where
+  vars :: a -> Set.Set Var
+
+instance Variables a => Variables [a] where
+  vars = Set.unions . map vars
+
+instance Variables LP where
+  vars = variables
+
+instance Variables Term where
+  vars (Term _ xs) = Set.fromList xs
+
+instance Variables Constraint where
+  vars Constraint{ constrIndicator = ind, constrBody = (lhs, _, _) } =
+    vars lhs `Set.union` vs2
+    where
+      vs2 = maybe Set.empty (Set.singleton . fst) ind
+
+-- | default bounds
+defaultBounds :: Bounds
+defaultBounds = (defaultLB, defaultUB)
+
+-- | default lower bound (0)
+defaultLB :: BoundExpr
+defaultLB = Finite 0
+
+-- | default upper bound (+∞)
+defaultUB :: BoundExpr
+defaultUB = PosInf
+
+-- | lookuping bounds for a variable
+getBounds :: LP -> Var -> Bounds
+getBounds lp v = Map.findWithDefault defaultBounds v (bounds lp)
+
+intersectBounds :: Bounds -> Bounds -> Bounds
+intersectBounds (lb1,ub1) (lb2,ub2) = (max lb1 lb2, min ub1 ub2)
+
+-- ---------------------------------------------------------------------------
+
+-- | Parse a string containing LP file data.
+-- The source name is only | used in error messages and may be the empty string.
+parseString :: SourceName -> String -> Either ParseError LP
+parseString = parse lpfile
+
+-- | Parse a file containing LP file data.
+parseFile :: FilePath -> IO (Either ParseError LP)
+parseFile = parseFromFile lpfile
+
+-- ---------------------------------------------------------------------------
+
+char' :: Char -> Parser Char
+char' c = (char c <|> char (toUpper c)) <?> show c
+
+string' :: String -> Parser ()
+string' s = mapM_ char' s <?> show s
+
+sep :: Parser ()
+sep = skipMany ((comment >> return ()) <|> (space >> return ()))
+
+comment :: Parser String
+comment = do
+  char '\\'
+  manyTill anyChar (try newline)
+
+tok :: Parser a -> Parser a
+tok p = do
+  x <- p
+  sep
+  return x
+
+ident :: Parser String
+ident = tok $ do
+  x <- letter <|> oneOf syms1 
+  xs <- many (alphaNum <|> oneOf syms2)
+  let s = x:xs 
+  guard $ map toLower s `Set.notMember` reserved
+  return s
+  where
+    syms1 = "!\"#$%&()/,;?@_`'{}|~"
+    syms2 = '.' : syms1
+
+label :: Parser Label
+label = do
+  name <- ident
+  tok $ char ':'
+  return name
+
+reserved :: Set.Set String
+reserved = Set.fromList
+  [ "bound", "bounds"
+  , "gen", "general", "generals"
+  , "bin", "binary", "binaries"
+  , "semi", "semi-continuous", "semis"
+  , "sos"
+  , "end"
+  , "subject"
+  ]
+
+-- ---------------------------------------------------------------------------
+
+lpfile :: Parser LP
+lpfile = do
+  sep
+  (flag, obj) <- problem
+
+  cs <- liftM concat $ many $ msum $
+    [ constraintSection
+    , lazyConstraintsSection
+    , userCutsSection
+    ]
+
+  bnds <- option Map.empty (try boundsSection)
+  xs <- many (liftM Left generalSection <|> liftM Right binarySection)
+  let ints = Set.fromList $ concat [x | Left  x <- xs]
+      bins = Set.fromList $ concat [x | Right x <- xs]
+  bnds <- return $ Map.unionWith intersectBounds
+            bnds (Map.fromAscList [(v, (Finite 0, Finite 1)) | v <- Set.toAscList bins])
+  scs <- liftM Set.fromList $ option [] (try semiSection)
+
+  ss <- option [] (try sosSection)
+  end
+  let vs = Set.unions $ map vars cs ++
+           [ Map.keysSet bnds
+           , ints
+           , bins
+           , scs
+           , vars (snd obj)
+           ] ++
+           [Set.fromList (map fst xs) | (_,_,xs) <- ss]
+  return $ LP vs flag obj cs bnds ints bins scs ss
+
+problem :: Parser (OptDir, ObjectiveFunction)
+problem = do
+  flag <-  (try minimize >> return OptMin)
+       <|> (try maximize >> return OptMax)
+  name <- optionMaybe (try label)
+  obj <- expr
+  return (flag, (name, obj))
+
+minimize, maximize :: Parser ()
+minimize = tok $ string' "min" >> optional (string' "imize")
+maximize = tok $ string' "max" >> optional (string' "imize")
+
+end :: Parser ()
+end = tok $ string' "end"
+
+-- ---------------------------------------------------------------------------
+
+constraintSection :: Parser [Constraint]
+constraintSection = subjectTo >> many (try (constraint NormalConstraint))
+
+subjectTo :: Parser ()
+subjectTo = msum
+  [ try $ tok (string' "subject") >> tok (string' "to")
+  , try $ tok (string' "such") >> tok (string' "that")
+  , try $ tok (string' "st")
+  , try $ tok (string' "s") >> optional (tok (char '.')) >> tok (string' "t")
+        >> tok (char '.') >> return ()
+  ]
+
+constraint :: ConstraintType -> Parser Constraint
+constraint t = do
+  name <- optionMaybe (try label)
+
+  g <- optionMaybe $ try $ do
+    var <- ident
+    tok (char '=')
+    val <- tok ((char '0' >> return 0) <|> (char '1' >> return 1))
+    tok $ string "->"
+    return (var, val)
+
+  -- It seems that CPLEX allows empty lhs, but GLPK rejects it.
+  e <- expr
+  op <- relOp
+  s <- option 1 sign
+  rhs <- number
+  return $ Constraint
+    { constrType      = t
+    , constrLabel     = name
+    , constrIndicator = g
+    , constrBody      = (e, op, s*rhs)
+    }
+
+relOp :: Parser RelOp
+relOp = tok $ msum
+  [ char '<' >> optional (char '=') >> return Le
+  , char '>' >> optional (char '=') >> return Ge
+  , char '=' >> msum [ char '<' >> return Le
+                     , char '>' >> return Ge
+                     , return Eql
+                     ]
+  ]
+
+lazyConstraintsSection :: Parser [Constraint]
+lazyConstraintsSection = do
+  tok $ string' "lazy"
+  tok $ string' "constraints"
+  many $ try $ constraint LazyConstraint
+
+userCutsSection :: Parser [Constraint]
+userCutsSection = do
+  tok $ string' "user"
+  tok $ string' "cuts"
+  many $ try $ constraint $ UserDefinedCut
+
+type Bounds2 = (Maybe BoundExpr, Maybe BoundExpr)
+
+boundsSection :: Parser (Map.Map Var Bounds)
+boundsSection = do
+  tok $ string' "bound" >> optional (char' 's')
+  liftM (Map.map g . Map.fromListWith f) $ many (try bound)
+  where
+    f (lb1,ub1) (lb2,ub2) = (combineMaybe max lb1 lb2, combineMaybe min ub1 ub2)
+    g (lb, ub) = ( fromMaybe defaultLB lb
+                 , fromMaybe defaultUB ub
+                 )
+
+bound :: Parser (Var, Bounds2)
+bound = msum
+  [ try $ do
+      v <- try ident
+      msum
+        [ do
+            op <- relOp
+            b <- boundExpr
+            return
+              ( v
+              , case op of
+                  Le -> (Nothing, Just b)
+                  Ge -> (Just b, Nothing)
+                  Eql -> (Just b, Just b)
+              )
+        , do
+            tok $ string' "free"
+            return (v, (Just NegInf, Just PosInf))
+        ]
+  , do
+      b1 <- liftM Just boundExpr
+      op1 <- relOp
+      guard $ op1 == Le
+      v <- ident
+      b2 <- option Nothing $ do
+        op2 <- relOp
+        guard $ op2 == Le
+        liftM Just boundExpr
+      return (v, (b1, b2))
+  ]
+
+boundExpr :: Parser BoundExpr
+boundExpr = msum 
+  [ try (tok (char '+') >> inf >> return PosInf)
+  , try (tok (char '-') >> inf >> return NegInf)
+  , do
+      s <- option 1 sign
+      x <- number
+      return $ Finite (s*x)
+  ]
+
+inf :: Parser ()
+inf = tok (string "inf" >> optional (string "inity"))
+
+-- ---------------------------------------------------------------------------
+
+generalSection :: Parser [Var]
+generalSection = do
+  tok $ string' "gen" >> optional (string' "eral" >> optional (string' "s"))
+  many (try ident)
+
+binarySection :: Parser [Var]
+binarySection = do
+  tok $ string' "bin" >> optional (string' "ar" >> (string' "y" <|> string' "ies"))
+  many (try ident)
+
+semiSection :: Parser [Var]
+semiSection = do
+  tok $ string' "semi" >> optional (string' "-continuous" <|> string' "s")
+  many (try ident)
+
+sosSection :: Parser [SOS]
+sosSection = do
+  tok $ string' "sos"
+  many $ try $ do
+    (l,t) <- try (do{ l <- label; t <- typ; return (Just l, t) })
+          <|> (do{ t <- typ; return (Nothing, t) })
+    xs <- many $ try $ do
+      v <- ident
+      tok $ char ':'
+      w <- number
+      return (v,w)
+    return (l,t,xs)
+  where
+    typ = do
+      t <- tok $ (char' 's' >> ((char '1' >> return S1) <|> (char '2' >> return S2)))
+      tok (string "::")
+      return t
+
+-- ---------------------------------------------------------------------------
+
+expr :: Parser Expr
+expr = try expr1 <|> return []
+  where
+    expr1 :: Parser Expr
+    expr1 = do
+      t <- term True
+      ts <- many (term False)
+      return $ concat (t : ts)
+
+sign :: Num a => Parser a
+sign = tok ((char '+' >> return 1) <|> (char '-' >> return (-1)))
+
+term :: Bool -> Parser Expr
+term flag = do
+  s <- if flag then optionMaybe sign else liftM Just sign
+  c <- optionMaybe number
+  e <- liftM (\s -> [Term 1 [s]]) ident <|> qexpr
+  return $ case combineMaybe (*) s c of
+    Nothing -> e
+    Just d -> [Term (d*c) vs | Term c vs <- e]
+
+qexpr :: Parser Expr
+qexpr = do
+  tok (char '[')
+  t <- qterm True
+  ts <- many (qterm False)
+  tok (char ']')
+  -- Gurobi allows ommiting "/2"
+  (do mapM_ (tok . char) "/2"
+      return [Term (r / 2) vs | Term r vs <- t:ts])
+   <|> return (t:ts)
+
+qterm :: Bool -> Parser Term
+qterm flag = do
+  s <- if flag then optionMaybe sign else liftM Just sign
+  c <- optionMaybe number
+  es <- qfactor `chainl1`  (tok (char '*') >> return (++))
+  return $ case combineMaybe (*) s c of
+    Nothing -> Term 1 es
+    Just d -> Term d es
+
+qfactor :: Parser [Var]
+qfactor = do
+  v <- ident
+  msum [ tok (char '^') >> tok (char '2') >> return [v,v]
+       , return [v]
+       ]
+
+number :: Parser Rational
+number = tok $ do
+  b <- (do{ x <- nat; y <- option 0 frac; return (fromInteger x + y) })
+    <|> frac
+  c <- option 0 e
+  return (b*10^^c)
+  where
+    digits = many1 digit
+
+    nat :: Parser Integer
+    nat = liftM read digits
+
+    frac :: Parser Rational
+    frac = do
+      char '.'
+      s <- digits
+      return (read s % 10^(length s))
+
+    e :: Parser Integer
+    e = do
+      oneOf "eE"
+      f <- msum [ char '+' >> return id
+                , char '-' >> return negate
+                , return id
+                ]
+      liftM f nat
+
+-- ---------------------------------------------------------------------------
+
+-- | Render a problem into a string.
+render :: LP -> Maybe String
+render lp = fmap ($ "") $ execWriterT (render' lp)
+
+render' :: LP -> WriterT ShowS Maybe ()
+render' lp = do
+  tell $ showString $
+    case dir lp of
+      OptMin -> "MINIMIZE"
+      OptMax -> "MAXIMIZE"
+  tell $ showChar '\n'
+
+  let (l, obj) = objectiveFunction lp
+  renderLabel l
+  renderExpr True obj
+  tell $ showChar '\n'
+
+  tell $ showString "SUBJECT TO\n"
+  forM_ (constraints lp) $ \c -> do
+    when (constrType c == NormalConstraint) $ do
+      renderConstraint c
+      tell $ showChar '\n'
+
+  let lcs = [c | c <- constraints lp, constrType c == LazyConstraint]
+  unless (null lcs) $ do
+    tell $ showString "LAZY CONSTRAINTS\n"
+    forM_ lcs $ \c -> do
+      renderConstraint c
+      tell $ showChar '\n'
+
+  let cuts = [c | c <- constraints lp, constrType c == UserDefinedCut]
+  unless (null cuts) $ do
+    tell $ showString "USER CUTS\n"
+    forM_ cuts $ \c -> do
+      renderConstraint c
+      tell $ showChar '\n'
+
+  tell $ showString "BOUNDS\n"
+  forM_ (Map.toAscList (bounds lp)) $ \(v, b@(lb,ub)) -> do
+    renderBoundExpr lb
+    tell $ showString " <= "
+    tell $ showString v
+    tell $ showString " <= "
+    renderBoundExpr ub
+    tell $ showChar '\n'
+
+  unless (Set.null (integerVariables lp)) $ do
+    tell $ showString "GENERALS\n"
+    renderVariableList $ Set.toList $ integerVariables lp
+
+  unless (Set.null (binaryVariables lp)) $ do
+    tell $ showString "BINARIES\n"
+    renderVariableList $ Set.toList $ binaryVariables lp
+
+  unless (Set.null (semiContinuousVariables lp)) $ do
+    tell $ showString "SEMI-CONTINUOUS\n"
+    renderVariableList $ Set.toList $ semiContinuousVariables lp
+
+  unless (null (sos lp)) $ do
+    tell $ showString "SOS\n"
+    forM_ (sos lp) $ \(l, typ, xs) -> do
+      renderLabel l
+      tell $ shows typ
+      tell $ showString " ::"
+      forM_ xs $ \(v, r) -> do
+        tell $ showString "  "
+        tell $ showString v
+        tell $ showString " : "
+        tell $ showValue r
+      tell $ showChar '\n'
+
+  tell $ showString "END\n"
+
+-- FIXME: Gurobi は quadratic term が最後に一つある形式でないとダメっぽい
+renderExpr :: Bool -> Expr -> WriterT ShowS Maybe ()
+renderExpr isObj e = fill 80 (ts1 ++ ts2)
+  where
+    (ts,qts) = partition isLin e 
+    isLin (Term _ [])  = True
+    isLin (Term _ [_]) = True
+    isLin _ = False
+
+    ts1 = map f ts
+    ts2
+      | null qts  = []
+      | otherwise =
+        -- マイナスで始めるとSCIP 2.1.1 は「cannot have '-' in front of quadratic part ('[')」というエラーを出す
+        ["+ ["] ++ map g qts ++ [if isObj then "] / 2" else "]"]
+
+    f :: Term -> String
+    f (Term c [])  = showConstTerm c ""
+    f (Term c [v]) = showCoeff c v
+    f _ = error "should not happen"
+
+    g :: Term -> String
+    g (Term c vs) = 
+      (if isObj then showCoeff (2*c) else showCoeff c)
+      (intercalate " * " vs)
+
+showValue :: Rational -> ShowS
+showValue c =
+  if denominator c == 1
+    then shows (numerator c)
+    else shows (fromRational c :: Double)
+
+showCoeff :: Rational -> ShowS
+showCoeff c = s . v
+  where
+    c' = abs c
+    s = showString (if c >= 0 then "+ " else "- ")
+    v = (if c' /= 1 then showValue c' . showChar ' ' else id)
+
+showConstTerm :: Rational -> ShowS
+showConstTerm c = s . v
+  where
+    s = showString (if c >= 0 then "+ " else "- ")
+    v = showValue (abs c)
+
+renderLabel :: Maybe Label -> WriterT ShowS Maybe ()
+renderLabel l =
+  case l of
+    Nothing -> return ()
+    Just s -> tell $ showString s . showString ": "
+
+renderOp :: RelOp -> WriterT ShowS Maybe ()
+renderOp Le = tell $ showString "<="
+renderOp Ge = tell $ showString ">="
+renderOp Eql = tell $ showString "="
+
+renderConstraint :: Constraint -> WriterT ShowS Maybe ()
+renderConstraint c@Constraint{ constrBody = (e,op,val) }  = do
+  renderLabel (constrLabel c)
+  case constrIndicator c of
+    Nothing -> return ()
+    Just (v,val) -> do
+      tell $ showString v . showString " = "
+      tell $ showValue val
+      tell $ showString " -> "
+
+  renderExpr False e
+  tell $ showChar ' '
+  renderOp op
+  tell $ showChar ' '
+  tell $ showValue val
+
+renderBoundExpr :: BoundExpr -> WriterT ShowS Maybe ()
+renderBoundExpr (Finite r) = tell $ showValue r
+renderBoundExpr NegInf = tell $ showString "-inf"
+renderBoundExpr PosInf = tell $ showString "+inf"
+
+renderVariableList :: [Var] -> WriterT ShowS Maybe ()
+renderVariableList vs = fill 80 vs >> tell (showChar '\n')
+
+fill :: Int -> [String] -> WriterT ShowS Maybe ()
+fill width xs = go xs 0
+  where
+    go [] _ = return ()
+    go (x:xs) 0 = tell (showString x) >> go xs (length x)
+    go (x:xs) w =
+      if w + 1 + length x <= width
+        then tell (showChar ' ' . showString x) >> go xs (w + 1 + length x)
+        else tell (showChar '\n') >> go (x:xs) 0
+
+-- ---------------------------------------------------------------------------
+
+compileExpr :: Expr -> Maybe (Map.Map Var Rational)
+compileExpr e = do
+  xs <- forM e $ \(Term c vs) ->
+    case vs of
+      [v] -> return (v, c)
+      _ -> mzero
+  return (Map.fromList xs)
+
+-- ---------------------------------------------------------------------------
diff --git a/src/Text/MaxSAT.hs b/src/Text/MaxSAT.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/MaxSAT.hs
@@ -0,0 +1,78 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Text.MaxSAT
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+-- 
+-- References:
+-- 
+-- * <http://maxsat.ia.udl.cat/requirements/>
+--
+-- TODO:
+--
+-- * Error handling
+--
+-----------------------------------------------------------------------------
+module Text.MaxSAT
+  (
+    WCNF
+  , WeightedClause
+  , Weight
+
+  -- * Parsing .cnf/.wcnf files
+  , parseWCNFString
+  , parseWCNFFile
+  ) where
+
+import qualified SAT.Types as SAT
+
+type WCNF = (Int, Weight, [WeightedClause])
+
+type WeightedClause = (Weight, SAT.Clause)
+
+-- | should be able to represent 2^63
+type Weight = Integer
+
+parseWCNFString :: String -> WCNF
+parseWCNFString s =
+  case words l of
+    (["p","wcnf", nvar, _nclause, top]) ->
+      (read nvar, read top, map parseWCNFLine ls)
+    (["p","wcnf", nvar, _nclause]) ->
+      (read nvar, 2^(63::Int), map parseWCNFLine ls)
+    (["p","cnf", nvar, _nclause]) ->
+      (read nvar, 2, map parseCNFLine ls)
+    _ -> error "parse error"
+  where
+    (l:ls) = filter (not . isComment) (lines s)
+
+parseWCNFFile :: FilePath -> IO WCNF
+parseWCNFFile filename = do
+  s <- readFile filename
+  return $! parseWCNFString s
+
+isComment :: String -> Bool
+isComment ('c':_) = True
+isComment _ = False
+
+parseWCNFLine :: String -> WeightedClause
+parseWCNFLine s =
+  case map read (words s) of
+    (w:xs) ->
+        let ys = map fromIntegral $ init xs
+        in seq w $ seqList ys $ (w, ys)
+    _ -> error "parse error"
+
+parseCNFLine :: String -> WeightedClause
+parseCNFLine s = seq xs $ seqList xs $ (1, xs)
+  where
+    xs = init (map read (words s))
+
+seqList :: [a] -> b -> b
+seqList [] b = b
+seqList (x:xs) b = seq x $ seqList xs b
diff --git a/src/Text/PBFile.hs b/src/Text/PBFile.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/PBFile.hs
@@ -0,0 +1,385 @@
+{-# LANGUAGE BangPatterns #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Text.PBFile
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Portability :  portable
+--
+-- A parser library for .opb file and .wbo files used by PB Competition.
+-- 
+-- References:
+--
+-- * Input/Output Format and Solver Requirements for the Competitions of
+--   Pseudo-Boolean Solvers
+--   <http://www.cril.univ-artois.fr/PB11/format.pdf>
+--
+-----------------------------------------------------------------------------
+
+module Text.PBFile
+  (
+  -- * Abstract Syntax
+    Formula
+  , Constraint
+  , Op (..)
+  , SoftFormula
+  , SoftConstraint
+  , Sum
+  , WeightedTerm
+  , Term
+  , Lit (..)
+  , Var
+
+  -- * Parsing .opb files
+  , parseOPBString
+  , parseOPBFile
+
+  -- * Parsing .wbo files
+  , parseWBOString
+  , parseWBOFile
+
+  -- * Show .opb files
+  , showOPB
+
+  -- * Show .wbo files
+  , showWBO
+
+  -- * Utility
+  , pbNumVars
+  , wboNumVars
+  ) where
+
+import Prelude hiding (sum)
+import Control.Monad
+import Data.Maybe
+import Data.List hiding (sum)
+import Text.ParserCombinators.Parsec
+import Data.Word
+import Control.Exception (assert)
+import Text.Printf
+
+-- | Pair of /objective function/ and a list of constraints.
+type Formula = (Maybe Sum, [Constraint])
+
+-- | Lhs, relational operator and rhs.
+type Constraint = (Sum, Op, Integer)
+
+-- | Relational operators
+data Op
+  = Ge -- ^ /greater than or equal/
+  | Eq -- ^ /equal/
+  deriving (Eq, Ord, Show, Enum, Bounded)
+
+-- | A pair of /top cost/ and a list of soft constraints.
+type SoftFormula = (Maybe Integer, [SoftConstraint])
+
+-- | A pair of weight and constraint.
+type SoftConstraint = (Maybe Integer, Constraint)
+
+-- | Sum of 'WeightedTerm'
+type Sum = [WeightedTerm]
+
+-- | Coefficient and 'Term'
+type WeightedTerm = (Integer, Term)
+
+-- | List of variables interpreted as products
+type Term = [Lit]
+
+-- | Positive (resp. negative) literal is represented as a positive (resp. negative) integer.
+type Lit = Int
+
+-- | Variable are repserented positive integer.
+type Var = Int
+
+-- <formula>::= <sequence_of_comments> [<objective>] <sequence_of_comments_or_constraints>
+formula :: Parser Formula
+formula = do
+  sequence_of_comments
+  obj <- optionMaybe objective
+  cs <- sequence_of_comments_or_constraints
+  return (obj, cs)
+
+-- <sequence_of_comments>::= <comment> [<sequence_of_comments>]
+sequence_of_comments :: Parser ()
+sequence_of_comments = skipMany1 comment
+
+-- <comment>::= "*" <any_sequence_of_characters_other_than_EOL> <EOL>
+comment :: Parser ()
+comment = do
+  _ <- char '*' 
+  _ <- manyTill anyChar eol
+  return ()
+
+-- <sequence_of_comments_or_constraints>::= <comment_or_constraint> [<sequence_of_comments_or_constraints>]
+sequence_of_comments_or_constraints :: Parser [Constraint]
+sequence_of_comments_or_constraints = do
+  xs <- many1 comment_or_constraint
+  return $ catMaybes xs
+
+-- <comment_or_constraint>::= <comment>|<constraint>
+comment_or_constraint :: Parser (Maybe Constraint)
+comment_or_constraint =
+  (comment >> return Nothing) <|> (liftM Just constraint)
+
+-- <objective>::= "min:" <zeroOrMoreSpace> <sum> ";"
+objective :: Parser Sum
+objective = do
+  _ <- string "min:"
+  zeroOrMoreSpace
+  obj <- sum
+  _ <- char ';'
+  eol
+  return obj
+
+-- <constraint>::= <sum> <relational_operator> <zeroOrMoreSpace> <integer> <zeroOrMoreSpace> ";"
+constraint :: Parser Constraint
+constraint = do
+  lhs <- sum
+  op <- relational_operator
+  zeroOrMoreSpace
+  rhs <- integer
+  zeroOrMoreSpace
+  semi
+  return (lhs, op, rhs)
+
+-- <sum>::= <weightedterm> | <weightedterm> <sum>
+sum :: Parser Sum
+sum = many1 weightedterm
+
+-- <weightedterm>::= <integer> <oneOrMoreSpace> <term> <oneOrMoreSpace>
+weightedterm :: Parser WeightedTerm
+weightedterm = do
+  w <- integer
+  oneOrMoreSpace
+  t <- term
+  oneOrMoreSpace
+  return (w,t)
+
+-- <integer>::= <unsigned_integer> | "+" <unsigned_integer> | "-" <unsigned_integer>
+integer :: Parser Integer
+integer = msum
+  [ unsigned_integer
+  , char '+' >> unsigned_integer
+  , char '-' >> liftM negate unsigned_integer
+  ]
+
+-- <unsigned_integer>::= <digit> | <digit><unsigned_integer>
+unsigned_integer :: Parser Integer
+unsigned_integer = do
+  ds <- many1 digit
+  return $! readUnsignedInteger ds
+
+-- | 'read' allocate too many intermediate 'Integer'.
+-- Therefore we use this optimized implementation instead.
+-- Many intermediate values in this implementation will be optimized
+-- away by worker-wrapper transformation and unboxing.
+readUnsignedInteger :: String -> Integer 
+readUnsignedInteger str = assert (result == read str) $ result
+  where
+    result :: Integer
+    result = go 0 str
+
+    lim :: Word
+    lim = maxBound `div` 10
+  
+    go :: Integer -> [Char] -> Integer 
+    go !r [] = r
+    go !r ds =
+      case go2 0 1 ds of
+        (r2,b,ds2) -> go (r * fromIntegral b + fromIntegral r2) ds2
+
+    go2 :: Word -> Word -> [Char] -> (Word, Word, [Char])
+    go2 !r !b dds | assert (b > r) (b > lim) = (r,b,dds)
+    go2 !r !b []     = (r, b, [])
+    go2 !r !b (d:ds) = go2 (r*10 + charToWord d) (b*10) ds
+
+    charToWord :: Char -> Word
+    charToWord '0' = 0
+    charToWord '1' = 1
+    charToWord '2' = 2
+    charToWord '3' = 3
+    charToWord '4' = 4
+    charToWord '5' = 5
+    charToWord '6' = 6
+    charToWord '7' = 7
+    charToWord '8' = 8
+    charToWord '9' = 9
+
+-- <relational_operator>::= ">=" | "="
+relational_operator :: Parser Op
+relational_operator = (string ">=" >> return Ge) <|> (string "=" >> return Eq)
+
+-- <variablename>::= "x" <unsigned_integer>
+variablename :: Parser Var
+variablename = do
+  _ <- char 'x'
+  i <- unsigned_integer
+  return $! fromIntegral i
+
+-- <oneOrMoreSpace>::= " " [<oneOrMoreSpace>]
+oneOrMoreSpace :: Parser ()
+oneOrMoreSpace  = skipMany1 (char ' ')
+
+-- <zeroOrMoreSpace>::= [" " <zeroOrMoreSpace>]
+zeroOrMoreSpace :: Parser ()
+zeroOrMoreSpace = skipMany (char ' ')
+
+eol :: Parser ()
+eol = char '\n' >> return ()
+
+semi :: Parser ()
+semi = char ';' >> eol
+
+{-
+For linear pseudo-Boolean instances, <term> is defined as
+<term>::=<variablename>
+
+For non-linear instances, <term> is defined as
+<term>::= <oneOrMoreLiterals>
+-}
+term :: Parser Term
+term = oneOrMoreLiterals
+
+-- <oneOrMoreLiterals>::= <literal> | <literal> <oneOrMoreSpace> <oneOrMoreLiterals>
+oneOrMoreLiterals :: Parser [Lit]
+oneOrMoreLiterals = do
+  l <- literal
+  mplus (try $ oneOrMoreSpace >> liftM (l:) (oneOrMoreLiterals)) (return [l])
+-- Note that we cannot use sepBy1.
+-- In "p `sepBy1` q", p should success whenever q success.
+-- But it's not the case here.
+
+-- <literal>::= <variablename> | "~"<variablename>
+literal :: Parser Lit
+literal = variablename <|> (char '~' >> liftM negate variablename)
+
+-- | Parse a .opb file containing pseudo boolean problem.
+parseOPBString :: SourceName -> String -> Either ParseError Formula
+parseOPBString = parse formula
+
+-- | Parse a .opb format string containing pseudo boolean problem.
+parseOPBFile :: FilePath -> IO (Either ParseError Formula)
+parseOPBFile = parseFromFile formula
+
+
+-- <softformula>::= <sequence_of_comments> <softheader> <sequence_of_comments_or_constraints>
+softformula :: Parser SoftFormula
+softformula = do
+  sequence_of_comments
+  top <- softheader
+  cs <- wbo_sequence_of_comments_or_constraints
+  return (top, cs)
+
+-- <softheader>::= "soft:" [<unsigned_integer>] ";"
+softheader :: Parser (Maybe Integer)
+softheader = do
+  _ <- string "soft:"
+  zeroOrMoreSpace -- XXX
+  top <- optionMaybe unsigned_integer
+  zeroOrMoreSpace -- XXX
+  semi
+  return top
+
+-- <sequence_of_comments_or_constraints>::= <comment_or_constraint> [<sequence_of_comments_or_constraints>]
+wbo_sequence_of_comments_or_constraints :: Parser [SoftConstraint]
+wbo_sequence_of_comments_or_constraints = do
+  xs <- many1 wbo_comment_or_constraint
+  return $ catMaybes xs
+
+-- <comment_or_constraint>::= <comment>|<constraint>|<softconstraint>
+wbo_comment_or_constraint :: Parser (Maybe SoftConstraint)
+wbo_comment_or_constraint = (comment >> return Nothing) <|> m
+  where
+    m = liftM Just $ (constraint >>= \c -> return (Nothing, c)) <|> softconstraint
+
+-- <softconstraint>::= "[" <zeroOrMoreSpace> <unsigned_integer> <zeroOrMoreSpace> "]" <constraint>
+softconstraint :: Parser SoftConstraint
+softconstraint = do
+  _ <- char '['
+  zeroOrMoreSpace
+  cost <- unsigned_integer
+  zeroOrMoreSpace
+  _ <- char ']'
+  zeroOrMoreSpace -- XXX
+  c <- constraint
+  return (Just cost, c)
+
+-- | Parse a .wbo file containing weighted boolean optimization problem.
+parseWBOString :: SourceName -> String -> Either ParseError SoftFormula
+parseWBOString = parse softformula
+
+-- | Parse a .wbo format string containing weighted boolean optimization problem.
+parseWBOFile :: FilePath -> IO (Either ParseError SoftFormula)
+parseWBOFile = parseFromFile softformula
+
+
+showOPB :: Formula -> ShowS
+showOPB opb@(obj, cs) = (size . part1 . part2)
+  where
+    nv = pbNumVars opb
+    nc = length cs
+    size = showString (printf "* #variable= %d #constraint= %d\n" nv nc)
+    part1 = 
+      case obj of
+        Nothing -> id
+        Just o -> showString "min: " . showSum o . showString ";\n"
+    part2 = foldr (.) id (map showConstraint cs)
+
+showWBO :: SoftFormula -> ShowS
+showWBO wbo@(top, cs) = size . part1 . part2
+  where
+    nv = wboNumVars wbo
+    nc = length cs
+    size = showString (printf "* #variable= %d #constraint= %d\n" nv nc)
+    part1 = 
+      case top of
+        Nothing -> showString "soft: "
+        Just t -> showString "soft: " . showsPrec 0 t . showString ";\n"
+    part2 = foldr (.) id (map showSoftConstraint cs)
+
+showSum :: Sum -> ShowS
+showSum = foldr (.) id . map showWeightedTerm
+
+showWeightedTerm :: WeightedTerm -> ShowS
+showWeightedTerm (c, lits) = foldr (\f g -> f . showChar ' ' . g) id (x:xs)
+  where
+    x = if c >= 0 then showChar '+' . showsPrec 0 c else showsPrec 0 c
+    xs = map showLit lits
+
+showLit :: Lit -> ShowS
+showLit lit =   if lit > 0 then v else showChar '~' . v
+  where
+    v = showChar 'x' . showsPrec 0 (abs lit)
+
+showConstraint :: Constraint -> ShowS
+showConstraint (lhs, op, rhs) =
+  showSum lhs . f op .  showChar ' ' . showsPrec 0 rhs . showString ";\n"
+  where
+    f Eq = showString "="
+    f Ge = showString ">="
+
+showSoftConstraint :: SoftConstraint -> ShowS
+showSoftConstraint (cost, constr) =
+  case cost of
+    Nothing -> showConstraint constr
+    Just c -> showChar '[' . showsPrec 0 c . showChar ']' . showChar ' ' . showConstraint constr
+
+pbNumVars :: Formula -> Int
+pbNumVars (m, cs) = maximum (0 : vs)
+  where
+    vs = do
+      s <- maybeToList m ++ [s | (s,_,_) <- cs]
+      (_, tm) <- s
+      lit <- tm
+      return $ abs lit
+
+wboNumVars :: SoftFormula -> Int
+wboNumVars (_, cs) = maximum vs
+  where
+    vs = do
+      s <- [s | (_, (s,_,_)) <- cs]
+      (_, tm) <- s
+      lit <- tm
+      return $ abs lit
diff --git a/src/Text/SDPFile.hs b/src/Text/SDPFile.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/SDPFile.hs
@@ -0,0 +1,399 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Text.SDPFile
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- References:
+--
+-- * SDPA (Semidefinite Programming Algorithm) User's Manual
+--   <http://sdpa.indsys.chuo-u.ac.jp/~fujisawa/sdpa_doc.pdf>
+--
+-- * <http://euler.nmt.edu/~brian/sdplib/FORMAT>
+--
+-----------------------------------------------------------------------------
+module Text.SDPFile
+  ( -- * The problem type
+    Problem (..)
+  , Matrix
+  , Block
+  , mDim
+  , nBlock
+  , blockElem
+
+    -- * Construction
+  , DenseMatrix
+  , DenseBlock
+  , denseMatrix
+  , denseBlock
+  , diagBlock
+  
+    -- * Rendering
+  , render
+  , renderSparse
+
+    -- * Parsing
+  , parseDataString
+  , parseDataFile
+  , parseSparseDataString
+  , parseSparseDataFile
+  ) where
+
+import Control.Monad
+import Data.List (intersperse)
+import Data.Ratio
+import qualified Data.Map as Map
+import qualified Data.IntMap as IM
+import Text.ParserCombinators.Parsec
+
+-- ---------------------------------------------------------------------------
+-- problem description
+-- ---------------------------------------------------------------------------
+
+data Problem
+  = Problem
+  { blockStruct :: [Int]      -- ^ the block strcuture vector (bLOCKsTRUCT)
+  , costs       :: [Rational] -- ^ Constant Vector
+  , matrices    :: [Matrix]   -- ^ Constraint Matrices
+  }
+  deriving (Show, Ord, Eq)
+
+type Matrix = [Block]
+
+type Block = Map.Map (Int,Int) Rational
+
+-- | the number of primal variables (mDim)
+mDim :: Problem -> Int
+mDim prob = length (matrices prob) - 1
+
+-- | the number of blocks (nBLOCK)
+nBlock :: Problem -> Int
+nBlock prob = length (blockStruct prob)
+
+blockElem :: Int -> Int -> Block -> Rational
+blockElem i j b = Map.findWithDefault 0 (i,j) b
+
+-- ---------------------------------------------------------------------------
+-- construction
+-- ---------------------------------------------------------------------------
+
+type DenseMatrix = [DenseBlock]
+
+type DenseBlock = [[Rational]]
+
+denseBlock :: DenseBlock -> Block
+denseBlock xxs = Map.fromList [((i,j),x) | (i,xs) <- zip [1..] xxs, (j,x) <- zip [1..] xs, x /= 0]
+
+denseMatrix :: DenseMatrix -> Matrix
+denseMatrix = map denseBlock
+
+diagBlock :: [Rational] -> Block
+diagBlock xs = Map.fromList [((i,i),x) | (i,x) <- zip [1..] xs]
+
+-- ---------------------------------------------------------------------------
+-- parsing
+-- ---------------------------------------------------------------------------
+
+-- | Parse a SDPA format (.dat) string.
+parseDataString :: SourceName -> String -> Either ParseError Problem
+parseDataString = parse pDataFile
+
+-- | Parse a SDPA format file (.dat).
+parseDataFile :: FilePath -> IO (Either ParseError Problem)
+parseDataFile = parseFromFile pDataFile
+
+-- | Parse a SDPA sparse format (.dat-s) string.
+parseSparseDataString :: SourceName -> String -> Either ParseError Problem
+parseSparseDataString = parse pSparseDataFile
+
+-- | Parse a SDPA sparse format file (.dat-s).
+parseSparseDataFile :: FilePath -> IO (Either ParseError Problem)
+parseSparseDataFile = parseFromFile pSparseDataFile
+
+pDataFile :: Parser Problem
+pDataFile = do
+  _ <- many pComment
+  m  <- nat_line -- mDim
+  _n <- nat_line -- nBlock
+  bs <- pBlockStruct -- bLOCKsTRUCT
+  cs <- pCosts
+  ms <- pDenseMatrices (fromIntegral m) bs
+  return $
+    Problem
+    { blockStruct = bs
+    , costs       = cs
+    , matrices    = ms
+    }
+
+pSparseDataFile :: Parser Problem
+pSparseDataFile = do
+  _ <- many pComment
+  m  <- nat_line -- mDim
+  _n <- nat_line -- nBlock
+  bs <- pBlockStruct -- bLOCKsTRUCT
+  cs <- pCosts
+  ms <- pSparseMatrices (fromIntegral m) bs
+  return $
+    Problem
+    { blockStruct = bs
+    , costs       = cs
+    , matrices    = ms
+    }
+
+pComment :: Parser String
+pComment = do
+  c <- oneOf "*\""
+  cs <- manyTill anyChar newline
+  return (c:cs)
+
+pBlockStruct :: Parser [Int]
+pBlockStruct = do
+  optional sep
+  let int' = int >>= \i -> optional sep >> return i
+  xs <- many int'
+  _ <- manyTill anyChar newline
+  return $ map fromIntegral xs 
+  where
+    sep = many1 (oneOf " \t(){},")
+
+pCosts :: Parser [Rational]
+pCosts = do
+  let sep = many1 (oneOf " \t(){},")
+      real' = real >>= \r -> optional sep >> return r
+  optional sep
+  cs <- many real'
+  _ <- newline
+  return cs
+
+pDenseMatrices :: Int -> [Int] -> Parser [Matrix]
+pDenseMatrices m bs = optional sep >> replicateM (fromIntegral m + 1) pDenceMatrix
+  where
+    sep = many1 (space <|> oneOf "(){},")
+    real' = real >>= \r -> optional sep >> return r
+    pDenceMatrix = forM bs $ \b ->
+      if b >= 0
+      then do
+        xs <- replicateM b (replicateM b real')
+        return $ denseBlock xs
+      else do
+        xs <- replicateM (abs b) real'
+        return $ diagBlock xs
+
+pSparseMatrices :: Int -> [Int] -> Parser [Matrix]
+pSparseMatrices m bs = do
+  xs <- many pLine
+  let t = IM.unionsWith (IM.unionWith Map.union)
+            [ IM.singleton matno (IM.singleton blkno (Map.fromList [((i,j),e),((j,i),e)]))
+            | (matno,blkno,i,j,e) <- xs ]
+  return $
+    [ [IM.findWithDefault Map.empty blkno mat | blkno <- [1 .. length bs]]
+    | matno <- [0..m], let mat = IM.findWithDefault IM.empty matno t
+    ]
+
+  where
+    sep = many1 (oneOf " \t") >> return ()
+    pLine = do
+      optional sep
+      matno <- nat
+      sep
+      blkno <- nat
+      sep
+      i <- nat
+      sep
+      j <- nat
+      sep
+      e <- real
+      optional sep
+      _ <- newline
+      return (fromIntegral matno, fromIntegral blkno, fromIntegral i, fromIntegral j, e)
+
+nat_line :: Parser Integer
+nat_line = do
+  spaces
+  n <- nat
+  _ <- manyTill anyChar newline
+  return n
+
+nat :: Parser Integer
+nat = do
+  ds <- many1 digit
+  return $! read ds
+
+int :: Parser Integer
+int = do
+  s <- option 1 sign
+  n <- nat
+  return $! s * n
+
+real :: Parser Rational
+real = do
+  s <- option 1 sign 
+  b <- (do{ x <- nat; y <- option 0 frac; return (fromInteger x + y) })
+    <|> frac
+  c <- option 0 e
+  return (s * b*10^^c)
+  where
+    digits = many1 digit
+
+    frac :: Parser Rational
+    frac = do
+      _ <- char '.'
+      s <- digits
+      return (read s % 10^(length s))
+
+    e :: Parser Integer
+    e = do
+      _ <- oneOf "eE"
+      f <- msum [ char '+' >> return id
+                , char '-' >> return negate
+                , return id
+                ]
+      liftM f nat
+
+sign :: Num a => Parser a
+sign = (char '+' >> return 1) <|> (char '-' >> return (-1))
+
+-- ---------------------------------------------------------------------------
+-- rendering
+-- ---------------------------------------------------------------------------
+
+render :: Problem -> ShowS
+render = renderImpl False
+
+renderSparse :: Problem -> ShowS
+renderSparse = renderImpl True
+
+renderImpl :: Bool -> Problem -> ShowS
+renderImpl sparse prob =
+  -- mDim
+  shows (mDim prob) . showString " = mDIM\n" .
+
+  -- nBlock
+  shows (nBlock prob) . showString " = nBlock\n" .
+
+  -- blockStruct
+  showChar '(' .
+    sepByS [shows i | i <- blockStruct prob] (showString ", ") .
+    showChar ')' .
+    showString " = bLOCKsTRUCT\n" .
+
+  -- costs
+  showChar '(' .
+    sepByS [showRat c | c <- costs prob] (showString ", ") .
+    showString ")\n" .
+
+  -- matrices
+  if sparse
+    then concatS [renderSparseMatrix matno m | (matno, m) <- zip [0..] (matrices prob)]
+    else concatS $ map renderDenseMatrix (matrices prob)
+
+  where
+    renderSparseMatrix :: Int -> Matrix -> ShowS
+    renderSparseMatrix matno m =
+      concatS [ shows matno . showChar ' ' .
+                shows blkno . showChar ' ' .
+                shows i . showChar ' ' .
+                shows j . showChar ' ' .
+                showRat e . showChar '\n'
+              | (blkno, blk) <- zip [(1::Int)..] m, ((i,j),e) <- Map.toList blk, i <= j ]
+
+    renderDenseMatrix :: Matrix -> ShowS
+    renderDenseMatrix m = 
+      showString "{\n" .
+      concatS [renderDenseBlock b s . showString "\n" | (b,s) <- zip m (blockStruct prob)] .
+      showString "}\n"
+
+    renderDenseBlock :: Block -> Int -> ShowS
+    renderDenseBlock b s
+      | s < 0 =
+          showString "  " . renderVec [blockElem i i b | i <- [1 .. abs s]]
+      | otherwise = 
+          showString "  { " .
+          sepByS [renderRow i | i <- [1..s]] (showString ", ") .     
+          showString " }"
+      where
+        renderRow i = renderVec [blockElem i j b | j <- [1..s]]
+
+renderVec :: [Rational] -> ShowS
+renderVec xs =
+  showChar '{' .
+  sepByS (map showRat xs) (showString ", ") .
+  showChar '}'
+
+showRat :: Rational -> ShowS
+showRat r
+  | denominator r == 1 = shows (numerator r)
+  | otherwise = shows (fromRational r :: Double)
+
+concatS :: [ShowS] -> ShowS
+concatS = foldr (.) id
+
+sepByS :: [ShowS] -> ShowS -> ShowS
+sepByS xs sep = concatS $ intersperse sep xs
+
+-- ---------------------------------------------------------------------------
+-- samples
+-- ---------------------------------------------------------------------------
+
+{-
+example1 :: Problem
+example1
+  = Problem
+  { blockStruct = [2]
+  , costs       = [48, -8, 20]
+  , matrices    = map denseMatrix [f0,f1,f2,f3]
+  }
+  where
+    f0 = [[[-11,0], [0,23]]]
+    f1 = [[[10,4],  [4,0]]]
+    f2 = [[[0,0],  [0,-8]]]
+    f3 = [[[0,-8], [-8,-2]]]
+
+example2 :: Problem
+example2
+  = Problem
+  { blockStruct = [2,3,-2]
+  , costs       = [1.1, -10, 6.6, 19, 4.1]
+  , matrices    = map denseMatrix [f0,f1,f5]
+  }
+  where
+    f0 = [ [[-1.4, -3.2], [-3.2, -28]]
+         , [[15, -12, 2.1], [-12, 16, -3.8], [2.1, -3.8, 15]] 
+         , [[1.8, 0], [0, -4.0]] 
+         ]
+    f1 = [ [[0.5, 5.2], [5.2,-5.3]]
+         , [[7.8, -2.4, 6.0], [-2.4, 4.2, 6.5], [6.0, 6.5, 2.1]] 
+         , [[-4.5, 0], [0, -3.5]]
+         ]
+    f5 = [ [[-6.5, -5.4], [-5.4, -6.6]]
+         , [[6.7, -7.2, -3.6], [-7.2, 7.3, -3.0], [-3.6, -3.0, -1.4]] 
+         , [[6.1, 0],[0, -1.5]] 
+         ]
+
+tests = [test1, test2, test3, test4]
+
+test1 = example1 == example1b
+  where
+    s = render example1 ""
+    Right example1b = parse pDataFile "" s
+
+test2 = example1 == example1b
+  where
+    s = renderSparse example1 ""
+    Right example1b = parse pSparseDataFile "" s
+
+test3 = example2 == example2b
+  where
+    s = render example2 ""
+    Right example2b = parse pDataFile "" s
+
+test4 = example2 == example2b
+  where
+    s = renderSparse example2 ""
+    Right example2b = parse pSparseDataFile "" s
+-}
diff --git a/src/TseitinEncode.hs b/src/TseitinEncode.hs
new file mode 100644
--- /dev/null
+++ b/src/TseitinEncode.hs
@@ -0,0 +1,117 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  TseitingEncoding
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (GeneralizedNewtypeDeriving)
+-- 
+-----------------------------------------------------------------------------
+module TseitingEncoding
+  ( Var
+  , Lit
+  , Clause
+  , CNF
+  , Formula
+  , CNFGenMonad (..)
+  , emitFormula
+  , CNFGen
+  , runCNFGen
+  , execCNFGen
+  , evalCNFGen
+  ) where
+
+import Control.Monad
+import Control.Monad.RWS
+
+type Var = Int
+data Lit = Pos Var | Neg Var deriving (Show, Eq, Ord)
+type Clause = [Lit]
+type CNF = [Clause]
+
+data Formula
+  = Var Var
+  | And [Formula]
+  | Or [Formula]
+  | Not Formula
+  | Imply Formula Formula
+  deriving (Show, Eq, Ord)
+
+class Monad m => CNFGenMonad m where
+  newVar :: m Var
+  emitClause :: Clause -> m ()
+
+emitFormula :: CNFGenMonad m => Formula -> m ()
+emitFormula x = do
+  v <- enc x
+  emitClause [Pos v]
+
+enc :: CNFGenMonad m => Formula -> m Var
+enc (Var v) = return v
+enc (And xs) = do
+  v <- newVar
+  vs <- mapM enc xs
+  forM vs $ \v2 -> emitClause [Neg v, Pos v2]
+  emitClause (Pos v : map Neg vs)
+  return v
+enc (Or xs) = do
+  v <- newVar
+  vs <- mapM enc xs
+  forM vs $ \v2 -> emitClause [Pos v, Neg v2]
+  emitClause (Neg v : map Pos vs)
+  return v
+enc (Not x) = do
+  v <- newVar
+  v2 <- enc x
+  emitClause [Pos v, Pos v2]
+  emitClause [Neg v, Neg v2]
+  return v
+enc (Imply x y) = enc (Or [Not x, y])
+
+newtype CNFGen a = CNFGen (RWS () (Endo [Clause]) Int a)
+  deriving Monad
+
+instance CNFGenMonad CNFGen where
+  newVar = CNFGen $ do
+    cnt <- get
+    put (cnt+1)
+    return cnt
+  emitClause cl = CNFGen (tell (Endo (cl:)))
+
+runCNFGen :: CNFGen x -> (x, Int, CNF)
+runCNFGen (CNFGen m) =
+  case runRWS m () 0 of
+    (x, cnt, f) -> (x, cnt, appEndo f [])
+
+execCNFGen :: CNFGen x -> (Int, CNF)
+execCNFGen m =
+  case runCNFGen m of
+    (_,cnt,cnf) -> (cnt,cnf)
+
+evalCNFGen :: CNFGen x -> (x, CNF)
+evalCNFGen m = 
+  case runCNFGen m of
+    (x,_,cnf) -> (x,cnf)
+
+test :: (Int, CNF)
+test = execCNFGen $ do
+  x <- newVar
+  y <- newVar
+  z <- newVar
+  emitFormula $ And [Or [Var x, Var y] , Var z]
+{-
+=>
+(5
+, [ [Pos 4,Neg 0]
+  , [Pos 4,Neg 1]
+  , [Neg 4,Pos 0,Pos 1]
+  , [Neg 3,Pos 4]
+  , [Neg 3,Pos 2]
+  , [Pos 3,Neg 4,Neg 2]
+  , [Pos 3]
+  ]
+)
+-}
diff --git a/src/Util.hs b/src/Util.hs
new file mode 100644
--- /dev/null
+++ b/src/Util.hs
@@ -0,0 +1,64 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Util
+-- Copyright   :  (c) Masahiro Sakai 2011-2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- Some utility functions.
+-- 
+-----------------------------------------------------------------------------
+
+module Util where
+
+import Data.Ratio
+
+-- | Combining two @Maybe@ values using given function.
+combineMaybe :: (a -> a -> a) -> Maybe a -> Maybe a -> Maybe a
+combineMaybe _ Nothing y = y
+combineMaybe _ x Nothing = x
+combineMaybe f (Just x) (Just y) = Just (f x y)
+
+-- | is the number integral?
+--
+-- @
+--    isInteger x = fromInteger (round x) == x
+-- @
+isInteger :: RealFrac a => a -> Bool
+isInteger x = fromInteger (round x) == x
+
+-- | fractional part
+-- 
+-- @
+--   fracPart x = x - fromInteger (floor x)
+-- @
+fracPart :: RealFrac a => a -> a
+fracPart x = x - fromInteger (floor x)
+
+showRational :: Bool -> Rational -> String
+showRational asRatio v
+  | denominator v == 1 = show (numerator v)
+  | asRatio            = show (numerator v) ++ "/" ++ show (denominator v)
+  | otherwise          = show (fromRational v :: Double)
+
+
+{-# INLINE revSequence #-}
+revSequence :: Monad m => [m a] -> m [a]
+revSequence = go []
+  where
+    go xs [] = return xs
+    go xs (m:ms) = do
+      x <- m
+      go (x:xs) ms
+
+{-# INLINE revMapM #-}
+revMapM :: Monad m => (a -> m b) -> ([a] -> m [b])
+revMapM f = revSequence . map f
+
+{-# INLINE revForM #-}
+revForM :: Monad m => [a] -> (a -> m b) -> m [b]
+revForM = flip revMapM
diff --git a/src/Version.hs b/src/Version.hs
new file mode 100644
--- /dev/null
+++ b/src/Version.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE CPP #-}
+module Version where
+
+import Data.List
+import Data.Version
+
+version :: Version
+version
+  = Version
+  { versionBranch = [0,0,1]
+  , versionTags   = []
+  }
+
+packageVersions :: [(String, String)]
+packageVersions = sort $ tail
+  [ (undefined, undefined) -- dummy
+#ifdef VERSION_OptDir
+  , ("OptDir",       VERSION_OptDir       )
+#endif
+#ifdef VERSION_array
+  , ("array",        VERSION_array        )
+#endif
+#ifdef VERSION_base
+  , ("base",         VERSION_base         )
+#endif
+#ifdef VERSION_bytestring
+  , ("bytestring",   VERSION_bytestring   )
+#endif
+#ifdef VERSION_containers
+  , ("containers",   VERSION_containers   )
+#endif
+#ifdef VERSION_deepseq
+  , ("deepseq",      VERSION_deepseq      )
+#endif
+#ifdef VERSION_mtl
+  , ("mtl",          VERSION_mtl          )
+#endif
+#ifdef VERSION_old_locale
+  , ("old_locale",   VERSION_old_locale   )
+#endif
+#ifdef VERSION_parse_dimacs
+  , ("parse_dimacs", VERSION_parse_dimacs )
+#endif
+#ifdef VERSION_parsec
+  , ("parsec",       VERSION_parsec       )
+#endif
+#ifdef VERSION_queue
+  , ("queue",        VERSION_queue        )
+#endif
+#ifdef VERSION_stm
+  , ("stm",          VERSION_stm         )
+#endif
+#ifdef VERSION_time
+  , ("time",         VERSION_time         )
+#endif
+  ]
diff --git a/src/Wang.hs b/src/Wang.hs
new file mode 100644
--- /dev/null
+++ b/src/Wang.hs
@@ -0,0 +1,46 @@
+import Control.Monad (guard,msum)
+import Data.List (intersect)
+import Data.Maybe (isJust, listToMaybe)
+
+data Formula x
+    = Atom x
+    | Not   !(Formula x)
+    | Imply !(Formula x) !(Formula x)
+    | And   !(Formula x) !(Formula x)
+    | Or    !(Formula x) !(Formula x)
+    deriving Eq
+
+type Sequent x = ([Formula x], [Formula x])
+
+isValid :: Eq x => Sequent x -> Bool
+isValid = isJust . isValid'
+
+isValid' :: Eq x => Sequent x -> Maybe ()
+isValid' (l,r) =
+    do xs <- listToMaybe $ msum $
+         [ do let i = intersect l r
+              guard $ not $ null i
+              return []
+         , do (Not p, r) <- pick r
+              return [(p:l,r)]
+         , do (Not p, l) <- pick l
+              return [(l,p:r)]
+         , do (Imply p q, r) <- pick r
+              return [(p:l,q:r)]
+         , do (Or p q, r) <- pick r
+              return [(l,p:q:r)]
+         , do (And p q, l) <- pick l
+              return [(p:q:l,r)]
+         , do (Or p q, l)  <- pick l
+              return [(p:l,r), (q:l,r)]
+         , do (And p q, r) <- pick r
+              return [(l,p:r), (l,q:r)]
+         , do (Imply p q, l) <- pick l
+              return [(q:l,r), (l,p:r)]
+         ]
+       mapM_ isValid' xs
+       return ()
+
+pick :: [x] -> [(x,[x])]
+pick []     = []
+pick (x:xs) = (x,xs) : [(y,x:ys) | (y,ys) <- pick xs]
diff --git a/src/cnf2lp.hs b/src/cnf2lp.hs
new file mode 100644
--- /dev/null
+++ b/src/cnf2lp.hs
@@ -0,0 +1,68 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  cnf2lp
+-- Copyright   :  (c) Masahiro Sakai 2011-2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+module Main where
+
+import qualified Data.ByteString.Lazy as BS
+import Data.Char
+import System.IO
+import System.Environment
+import System.Exit
+import System.Console.GetOpt
+
+import qualified Text.LPFile as LPFile
+import qualified Language.CNF.Parse.ParseDIMACS as DIMACS
+
+import Converter.CNF2LP
+
+data Flag
+  = Help
+  | ObjType ObjType
+  deriving Eq
+
+options :: [OptDescr Flag]
+options =
+    [ Option ['h'] ["help"] (NoArg Help)                       "show help"
+    , Option []    ["obj"]  (ReqArg (ObjType . parseObjType) "STRING") "none (default), max-one, max-zero"
+    ]
+  where
+    parseObjType s =
+      case map toLower s of
+        "none"     -> ObjNone
+        "max-one"  -> ObjMaxOne
+        "max-zero" -> ObjMaxZero
+        _          -> error ("unknown obj: " ++ s)
+
+main :: IO ()
+main = do
+  args <- getArgs
+  case getOpt Permute options args of
+    (o,_,[])
+      | Help `elem` o -> putStrLn (usageInfo header options)
+    (o,[fname],[]) -> do
+      ret <- case fname of
+               "-" -> fmap (DIMACS.parseByteString "-") $ BS.hGetContents stdin
+               _   -> DIMACS.parseFile fname
+      case ret of
+        Left err -> hPrint stderr err >> exitFailure
+        Right cnf -> do
+          let objType = last (ObjNone : [t | ObjType t <- o])
+              (lp, _) = convert objType cnf
+          case LPFile.render lp of
+            Nothing -> hPutStrLn stderr "conversion failure" >> exitFailure
+            Just s2 -> putStr s2
+    (_,_,errs) -> do
+      hPutStrLn stderr $ concat errs ++ usageInfo header options
+      exitFailure
+
+header :: String
+header = "Usage: cnf2lp [OPTION]... [file.cnf|-]"
diff --git a/src/lp2yices.hs b/src/lp2yices.hs
new file mode 100644
--- /dev/null
+++ b/src/lp2yices.hs
@@ -0,0 +1,235 @@
+{-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  lp2yices
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+module Main where
+
+import Data.Ord
+import Data.List
+import Data.Ratio
+import qualified Data.Set as Set
+import qualified Data.Map as Map
+import System.Console.GetOpt
+import System.Environment
+import System.Exit
+import System.IO
+import Text.Printf
+import qualified Text.LPFile as LP
+
+type Var = String
+type Env = Map.Map LP.Var Var
+
+concatS :: [ShowS] -> ShowS
+concatS = foldr (.) id
+ 
+unlinesS :: [ShowS] -> ShowS
+unlinesS = concatS . map (. showChar '\n')
+
+list :: [ShowS] -> ShowS
+list xs = showParen True $ concatS (intersperse (showChar ' ') xs)
+
+and' :: [ShowS] -> ShowS
+and' [] = showString "true"
+and' [x] = x
+and' xs = list (showString "and" : xs)
+
+or' :: [ShowS] -> ShowS
+or' [] = showString "false"
+or' [x] = x
+or' xs = list (showString "or" : xs)
+
+not' :: ShowS -> ShowS
+not' x = list [showString "not", x]
+
+expr :: Env -> LP.Expr -> ShowS
+expr env e =
+  case e of
+    [] -> showChar '0'
+    _ -> list (showChar '+' : map f e)
+  where
+    f (LP.Term c []) = num c
+    f (LP.Term c vs) =
+      case xs of
+        [] -> showChar '1'
+        [x] -> x
+        _ -> list (showChar '*' : xs)
+      where
+        xs = [num c | c /= 1] ++ [showString (env Map.! v) | v <- vs]
+
+num :: Rational -> ShowS
+num r
+  | denominator r == 1 = shows (numerator r)
+  | otherwise = shows (numerator r) . showChar '/' . shows (denominator r)
+
+rel :: Bool -> LP.RelOp -> ShowS -> ShowS -> ShowS
+rel True LP.Eql x y = and' [rel False LP.Le x y, rel False LP.Ge x y]
+rel _ LP.Eql x y = list [showString "=", x, y]
+rel _ LP.Le x y = list [showString "<=", x, y]
+rel _ LP.Ge x y = list [showString ">=", x, y]
+
+assert :: ShowS -> ShowS
+assert x = list [showString "assert", x]
+
+constraint :: Bool -> Env -> LP.Constraint -> ShowS
+constraint q env LP.Constraint{ LP.constrIndicator = g, LP.constrBody = (e, op, b) } =
+  case g of 
+    Nothing -> c
+    Just (var,val) ->
+      list [ showString "=>"
+           , rel q LP.Eql (expr env [LP.Term 1 [var]]) (num val)
+           , c
+           ]
+  where
+    c = rel q op (expr env e) (num b)
+
+conditions :: Bool -> Env -> LP.LP -> [ShowS]
+conditions q env lp = bnds ++ bins ++ cs ++ ss
+  where
+    vs = LP.variables lp
+    bins = do
+      v <- Set.toList (LP.binaryVariables lp)
+      let v2 = env Map.! v
+      return $ list [showString "or", rel q LP.Eql (showString v2) (showChar '0'), rel q LP.Eql (showString v2) (showChar '1')]
+    bnds = map bnd (Set.toList vs)
+    bnd v =
+      if v `Set.member` (LP.semiContinuousVariables lp)
+       then or' [list [showString "=", showString v2, num 0], and' (s1 ++ s2)]
+       else and' (s1 ++ s2)
+      where
+        v2 = env Map.! v
+        (lb,ub) = LP.getBounds lp v
+        s1 = case lb of
+               LP.NegInf -> []
+               LP.PosInf -> [showString "false"]
+               LP.Finite x -> [list [showString "<=", num x, showString v2]]
+        s2 = case ub of
+               LP.NegInf -> [showString "false"]
+               LP.PosInf -> []
+               LP.Finite x -> [list [showString "<=", showString v2, num x]]
+    cs = map (constraint q env) (LP.constraints lp)
+    ss = concatMap sos (LP.sos lp)
+    sos (_, typ, xs) = do
+      (x1,x2) <- case typ of
+                    LP.S1 -> pairs $ map fst xs
+                    LP.S2 -> nonAdjacentPairs $ map fst $ sortBy (comparing snd) $ xs
+      return $ not' $ and' [list [showString "/=", showString (env Map.! v), showChar '0']  | v<-[x1,x2]]
+
+pairs :: [a] -> [(a,a)]
+pairs [] = []
+pairs (x:xs) = [(x,x2) | x2 <- xs] ++ pairs xs
+
+nonAdjacentPairs :: [a] -> [(a,a)]
+nonAdjacentPairs (x1:x2:xs) = [(x1,x3) | x3 <- xs] ++ nonAdjacentPairs (x2:xs)
+nonAdjacentPairs _ = []
+
+lp2ys :: LP.LP -> Bool -> Bool -> ShowS
+lp2ys lp optimize check =
+  unlinesS $ defs ++ map assert (conditions False env lp)
+             ++ [ optimalityDef ]
+             ++ [ assert (showString "optimality") | optimize ]
+             ++ [ list [showString "set-evidence!", showString "true"] | check ]
+             ++ [ list [showString "check"] | check ]
+  where
+    vs = LP.variables lp
+    real_vs = vs `Set.difference` int_vs
+    int_vs = LP.integerVariables lp `Set.union` LP.binaryVariables lp
+    ts = [(v, "real")| v <- Set.toList real_vs] ++ [(v, "int") | v <- Set.toList int_vs]
+    obj = snd (LP.objectiveFunction lp)
+    env = Map.fromList [(v, encode v) | v <- Set.toList vs]
+    -- Note that identifiers of LPFile does not contain '-'.
+    -- So that there are no name crash.
+    env2 = Map.fromList [(v, encode v ++ "-2") | v <- Set.toList vs]
+
+    defs = do
+      (v,t) <- ts
+      let v2 = env Map.! v
+      return $ showString $ printf "(define %s::%s) ; %s"  v2 t v
+
+    optimalityDef = list [showString "define", showString "optimality::bool", optimality]
+
+    optimality = list [showString "forall", decl, body]
+      where
+        decl = list [showString $ printf "%s::%s" (env2 Map.! v) t | (v,t) <- ts]
+        body = list [showString "=>"
+                    , and' (conditions True env2 lp)
+                    , list [ showString $ if LP.dir lp == LP.OptMin then "<=" else ">="
+                           , expr env obj, expr env2 obj
+                           ]
+                    ]
+
+encode :: String -> String
+encode s = concatMap f s
+  where
+    -- Note that '[', ']', '\\' does not appear in identifiers of LP file.
+    f '(' = "["
+    f ')' = "]"
+    f c | c `elem` "/\";" = printf "\\x%02d" (fromEnum c :: Int)
+    f c = [c]
+
+data Flag
+    = Help
+    | Optimize
+    | NoCheck
+    deriving Eq
+
+options :: [OptDescr Flag]
+options =
+    [ Option ['h'] ["help"]  (NoArg Help)       "show help"
+    , Option [] ["optimize"] (NoArg Optimize)   "output optimiality condition which uses quantifiers"
+    , Option [] ["no-check"] (NoArg NoCheck)    "do not output \"(check)\""
+    ]
+
+
+main :: IO ()
+main = do
+  args <- getArgs
+  case getOpt Permute options args of
+    (o,_,[])
+      | Help `elem` o    -> putStrLn (usageInfo header options)
+    (o,[fname],[]) -> do
+      ret <- if fname == "-"
+             then fmap (LP.parseString "-") getContents
+             else LP.parseFile fname
+      case ret of
+        Right lp -> putStrLn $ lp2ys lp (Optimize `elem` o) (not (NoCheck `elem` o)) ""
+        Left err -> hPrint stderr err >> exitFailure
+    (_,_,errs) -> do
+        hPutStrLn stderr $ concat errs ++ usageInfo header options
+        exitFailure
+
+header :: String
+header = "Usage: lp2yice [OPTION]... [file.lp|-]"
+
+testFile :: FilePath -> IO ()
+testFile fname = do
+  result <- LP.parseFile fname
+  case result of
+    Right lp -> putStrLn $ lp2ys lp True True ""
+    Left err -> hPrint stderr err
+
+test :: IO ()
+test = putStrLn $ lp2ys testdata True True ""
+
+testdata :: LP.LP
+Right testdata = LP.parseString "test" $ unlines
+  [ "Maximize"
+  , " obj: x1 + 2 x2 + 3 x3 + x4"
+  , "Subject To"
+  , " c1: - x1 + x2 + x3 + 10 x4 <= 20"
+  , " c2: x1 - 3 x2 + x3 <= 30"
+  , " c3: x2 - 3.5 x4 = 0"
+  , "Bounds"
+  , " 0 <= x1 <= 40"
+  , " 2 <= x4 <= 3"
+  , "General"
+  , " x4"
+  , "End"
+  ]
diff --git a/src/maxsat2lp.hs b/src/maxsat2lp.hs
new file mode 100644
--- /dev/null
+++ b/src/maxsat2lp.hs
@@ -0,0 +1,37 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  maxsat2lp
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+
+module Main where
+
+import Control.Monad
+import System.Environment
+import System.Exit
+import System.IO
+import qualified Text.MaxSAT as MaxSAT
+import qualified Text.LPFile as LPFile
+import qualified Converter.MaxSAT2LP as MaxSAT2LP
+
+header :: String
+header = "Usage: maxsat2lp [file.cnf|file.wcnf|-]"
+
+main :: IO ()
+main = do
+  args <- getArgs
+  wcnf <- case args of
+            ["-"]   -> liftM MaxSAT.parseWCNFString getContents
+            [fname] -> MaxSAT.parseWCNFFile fname
+            _ -> hPutStrLn stderr header >> exitFailure
+  let (lp, _) = MaxSAT2LP.convert wcnf
+  case LPFile.render lp of
+    Nothing -> hPutStrLn stderr "conversion failure" >> exitFailure
+    Just s -> putStr s
diff --git a/src/pb2lp.hs b/src/pb2lp.hs
new file mode 100644
--- /dev/null
+++ b/src/pb2lp.hs
@@ -0,0 +1,79 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  pb2lp
+-- Copyright   :  (c) Masahiro Sakai 2011-2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+module Main where
+
+import Control.Monad
+import Data.Char
+import System.Environment
+import System.IO
+import System.Exit
+import System.Console.GetOpt
+import qualified Text.PBFile as PBFile
+import qualified Text.LPFile as LPFile
+import Converter.PB2LP
+
+data Flag
+  = Help
+  | WBO
+  | ObjType ObjType
+  | IndicatorConstraint
+  deriving Eq
+
+options :: [OptDescr Flag]
+options =
+    [ Option ['h'] ["help"] (NoArg Help) "show help"
+    , Option []    ["wbo"]  (NoArg WBO)  "input is .wbo file"
+    , Option []    ["obj"]  (ReqArg (ObjType . parseObjType) "STRING") "objective function for PBS: none (default), max-one, max-zero"
+    , Option []    ["indicator"] (NoArg IndicatorConstraint) "use indicator constraints in output LP file"
+    ]
+  where
+    parseObjType s =
+      case map toLower s of
+        "none"     -> ObjNone
+        "max-one"  -> ObjMaxOne
+        "max-zero" -> ObjMaxZero
+        _          -> error ("unknown obj: " ++ s)
+
+main :: IO ()
+main = do
+  args <- getArgs
+  case getOpt Permute options args of
+    (o,_,[])
+      | Help `elem` o -> putStrLn (usageInfo header options)
+    (o,[fname],[]) -> do
+      let objType = last (ObjNone : [t | ObjType t <- o])
+      (lp, _) <-
+        if WBO `elem` o
+        then do
+          ret <- if fname == "-"
+                 then liftM (PBFile.parseWBOString "-") getContents
+                 else PBFile.parseWBOFile fname
+          case ret of
+            Left err -> hPrint stderr err >> exitFailure
+            Right formula -> return (convertWBO (IndicatorConstraint `elem` o) formula)
+        else do
+          ret <- if fname == "-"
+                 then liftM (PBFile.parseOPBString "-") getContents
+                 else PBFile.parseOPBFile fname
+          case ret of
+            Left err -> hPrint stderr err >> exitFailure
+            Right formula -> return (convert objType formula)
+      case LPFile.render lp of
+        Nothing -> hPutStrLn stderr "conversion failure" >> exitFailure
+        Just s -> putStr s
+    (_,_,errs) -> do
+      hPutStrLn stderr $ concat errs ++ usageInfo header options
+      exitFailure
+
+header :: String
+header = "Usage: pb2lp [OPTION]... [file.opb|file.wbo|-]"
diff --git a/src/pbverify.hs b/src/pbverify.hs
new file mode 100644
--- /dev/null
+++ b/src/pbverify.hs
@@ -0,0 +1,40 @@
+module Main where
+
+import Control.Monad
+import Data.Array.IArray
+import System.Environment
+import Text.Printf
+import qualified Text.PBFile as PBFile
+import SAT.Types
+
+main :: IO ()
+main = do
+  [problemFile, modelFile] <- getArgs
+  Right formula@(obj, cs) <- PBFile.parseOPBFile problemFile
+  model <- liftM readModel (readFile modelFile)
+  forM_ cs $ \c ->
+    unless (eval model c) $
+      printf "violated: %s\n" (show c)
+
+eval :: Model -> PBFile.Constraint -> Bool
+eval m (lhs, op, rhs) = op_v lhs_v rhs
+  where
+    lhs_v = sum [c | (c,lits) <- lhs, all (evalLit m) lits]
+    op_v  = case op of
+              PBFile.Ge -> (>=)
+              PBFile.Eq -> (==)
+
+readModel :: String -> Model
+readModel s = array (1, maximum (0 : map fst ls2)) ls2
+  where
+    ls = lines s
+    ls2 = do
+      l <- ls
+      case l of
+        'v':xs -> do
+          w <- words xs
+          case w of
+            '-':'x':ys -> return (read ys, False)
+            'x':ys -> return (read ys, True)
+        _ -> mzero
+
diff --git a/src/pigeonhole.hs b/src/pigeonhole.hs
new file mode 100644
--- /dev/null
+++ b/src/pigeonhole.hs
@@ -0,0 +1,33 @@
+module Main where
+
+import Data.List
+import System.Environment
+import System.Exit
+import System.IO
+import Text.PBFile as PBFile
+
+pigeonHole :: Integer -> Integer -> Formula
+pigeonHole p h = (Nothing, cs1 ++ cs2)
+  where
+    vs :: [((Integer,Integer), Int)]
+    vs = zip [(i,j) | i<-[1..p], j<-[1..h]] [1..]
+
+    cs1 :: [Constraint]
+    cs1 = [ ([(1,[v]) | j<-[1..h], let Just v = lookup (i,j) vs], PBFile.Ge, 1)
+          | i<-[1..p]
+          ]
+    cs2 :: [Constraint]
+    cs2 = [ ([(-1,[v]) | i<-[1..p], let Just v = lookup (i,j) vs], PBFile.Ge, -1)
+          | j<-[1..h]
+          ]
+
+main :: IO ()
+main = do
+  xs <- getArgs
+  case xs of
+    [p,h] -> do
+      let opb = pigeonHole (read p) (read h)
+      putStr $ showOPB opb ""
+    _ -> do
+      hPutStrLn stderr "Usage: pigeonhole number_of_pigeons number_of_holes"
+      exitFailure
diff --git a/src/toysat.hs b/src/toysat.hs
new file mode 100644
--- /dev/null
+++ b/src/toysat.hs
@@ -0,0 +1,689 @@
+{-# LANGUAGE ScopedTypeVariables, DoAndIfThenElse, CPP #-}
+{-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  toysat
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  non-portable (ScopedTypeVariables)
+--
+-- A toy-level SAT solver based on CDCL.
+--
+-----------------------------------------------------------------------------
+
+module Main where
+
+import Control.Monad
+import Control.Exception
+import Data.Array.IArray
+import qualified Data.ByteString.Lazy as BS
+import qualified Data.Set as Set
+import qualified Data.Map as Map
+import Data.Char
+import Data.IORef
+import Data.List
+import Data.Maybe
+import Data.Ord
+import Data.Ratio
+import Data.Version
+import Data.Time.LocalTime
+import Data.Time.Format
+import System.IO
+import System.Environment
+import System.Exit
+import System.Locale
+import System.Console.GetOpt
+import System.CPUTime
+import System.FilePath
+import System.Timeout
+import qualified System.Info as SysInfo
+import qualified Language.CNF.Parse.ParseDIMACS as DIMACS
+import Text.Printf
+#ifdef __GLASGOW_HASKELL__
+import GHC.Environment (getFullArgs)
+#endif
+#ifdef FORCE_CHAR8
+import GHC.IO.Encoding
+#endif
+
+import Data.Linear
+import qualified SAT
+import qualified SAT.Integer
+import qualified SAT.TseitinEncoder as Tseitin
+import SAT.Types (pbEval, pbLowerBound)
+import SAT.Printer
+import qualified Text.PBFile as PBFile
+import qualified Text.LPFile as LPFile
+import qualified Text.MaxSAT as MaxSAT
+import Version
+import Util (showRational, revMapM, revForM)
+
+-- ------------------------------------------------------------------------
+
+data Mode = ModeHelp | ModeVersion | ModeSAT | ModePB | ModeWBO | ModeMaxSAT | ModeLP
+
+data Options
+  = Options
+  { optMode          :: Maybe Mode
+  , optRestartStrategy :: SAT.RestartStrategy
+  , optRestartFirst  :: Int
+  , optRestartInc    :: Double
+  , optLearningStrategy :: SAT.LearningStrategy
+  , optLearntSizeInc :: Double
+  , optCCMin         :: Int
+  , optRandomFreq    :: Double
+  , optRandomSeed    :: Int
+  , optLinearizerPB  :: Bool
+  , optBinarySearch  :: Bool
+  , optObjFunVarsHeuristics :: Bool
+  , optPrintRational :: Bool
+  , optCheckModel  :: Bool
+  , optTimeout :: Integer
+  }
+
+defaultOptions :: Options
+defaultOptions
+  = Options
+  { optMode          = Nothing
+  , optRestartStrategy = SAT.defaultRestartStrategy
+  , optRestartFirst  = SAT.defaultRestartFirst
+  , optRestartInc    = SAT.defaultRestartInc
+  , optLearningStrategy = SAT.defaultLearningStrategy
+  , optLearntSizeInc = SAT.defaultLearntSizeInc
+  , optCCMin         = SAT.defaultCCMin
+  , optRandomFreq    = SAT.defaultRandomFreq
+  , optRandomSeed    = 0
+  , optLinearizerPB  = False
+  , optBinarySearch   = False
+  , optObjFunVarsHeuristics = True
+  , optPrintRational = False  
+  , optCheckModel = False
+  , optTimeout = 0
+  }
+
+options :: [OptDescr (Options -> Options)]
+options =
+    [ Option ['h'] ["help"]   (NoArg (\opt -> opt{ optMode = Just ModeHelp   })) "show help"
+    , Option [] ["version"]   (NoArg (\opt -> opt{ optMode = Just ModeVersion})) "show version"
+
+    , Option []    ["sat"]    (NoArg (\opt -> opt{ optMode = Just ModeSAT    })) "solve pseudo boolean problems in .cnf file (default)"
+    , Option []    ["pb"]     (NoArg (\opt -> opt{ optMode = Just ModePB     })) "solve pseudo boolean problems in .pb file"
+    , Option []    ["wbo"]    (NoArg (\opt -> opt{ optMode = Just ModeWBO    })) "solve weighted boolean optimization problem in .opb file"
+    , Option []    ["maxsat"] (NoArg (\opt -> opt{ optMode = Just ModeMaxSAT })) "solve MaxSAT problem in .cnf or .wcnf file"
+    , Option []    ["lp"]     (NoArg (\opt -> opt{ optMode = Just ModeLP     })) "solve binary integer programming problem in .lp file"
+
+    , Option [] ["restart"]
+        (ReqArg (\val opt -> opt{ optRestartStrategy = parseRestartStrategy val }) "<str>")
+        "Restart startegy: MiniSAT (default), Armin, Luby."
+    , Option [] ["restart-first"]
+        (ReqArg (\val opt -> opt{ optRestartFirst = read val }) "<integer>")
+        (printf "The initial restart limit. (default %d)" SAT.defaultRestartFirst)
+    , Option [] ["restart-inc"]
+        (ReqArg (\val opt -> opt{ optRestartInc = read val }) "<real>")
+        (printf "The factor with which the restart limit is multiplied in each restart. (default %f)" SAT.defaultRestartInc)
+    , Option [] ["learning"]
+        (ReqArg (\val opt -> opt{ optLearningStrategy = parseLS val }) "<name>")
+        "Leaning scheme: clause (default)"
+    , Option [] ["learnt-size-inc"]
+        (ReqArg (\val opt -> opt{ optLearntSizeInc = read val }) "<real>")
+        (printf "The limit for learnt clauses is multiplied with this factor periodically. (default %f)" SAT.defaultLearntSizeInc)
+    , Option [] ["ccmin"]
+        (ReqArg (\val opt -> opt{ optCCMin = read val }) "<int>")
+        (printf "Conflict clause minimization (0=none, 1=local, 2=recursive; default %d)" SAT.defaultCCMin)
+
+    , Option [] ["random-freq"]
+        (ReqArg (\val opt -> opt{ optRandomFreq = read val }) "<0..1>")
+        (printf "The frequency with which the decision heuristic tries to choose a random variable (default %f)" SAT.defaultRandomFreq)
+    , Option [] ["random-seed"]
+        (ReqArg (\val opt -> opt{ optRandomSeed = read val }) "<int>")
+        "Used by the random variable selection"
+
+    , Option [] ["linearizer-pb"]
+        (NoArg (\opt -> opt{ optLinearizerPB = True }))
+        "Use PB constraint in linearization."
+
+    , Option [] ["search"]
+        (ReqArg (\val opt -> opt{ optBinarySearch = parseSearch val }) "<str>")
+        "Search algorithm used in optimization; linear (default), binary"
+    , Option [] ["objfun-heuristics"]
+        (NoArg (\opt -> opt{ optObjFunVarsHeuristics = True }))
+        "Enable heuristics for polarity/activity of variables in objective function (default)"
+    , Option [] ["no-objfun-heuristics"]
+        (NoArg (\opt -> opt{ optObjFunVarsHeuristics = False }))
+        "Disable heuristics for polarity/activity of variables in objective function"
+
+    , Option [] ["print-rational"]
+        (NoArg (\opt -> opt{ optPrintRational = True }))
+        "print rational numbers instead of decimals"
+
+    , Option [] ["check-model"]
+        (NoArg (\opt -> opt{ optCheckModel = True }))
+        "check model for debug"
+
+    , Option [] ["timeout"]
+        (ReqArg (\val opt -> opt{ optTimeout = read val }) "<int>")
+        "Kill toysat after given number of seconds (default 0 (no limit))"
+    ]
+  where
+    parseRestartStrategy s =
+      case map toLower s of
+        "minisat" -> SAT.MiniSATRestarts
+        "armin" -> SAT.ArminRestarts
+        "luby" -> SAT.LubyRestarts
+        _ -> undefined
+
+    parseSearch s =
+      case map toLower s of
+        "linear" -> False
+        "binary" -> True
+        _ -> undefined
+
+    parseLS "clause" = SAT.LearningClause
+    parseLS "hybrid" = SAT.LearningHybrid
+    parseLS s = error (printf "unknown learning strategy %s" s)
+
+main :: IO ()
+main = do
+#ifdef FORCE_CHAR8
+  setLocaleEncoding char8
+  setForeignEncoding char8
+  setFileSystemEncoding char8
+#endif
+
+  start <- getCPUTime
+  args <- getArgs
+  case getOpt Permute options args of
+    (o,args2,[]) -> do
+      printSysInfo
+#ifdef __GLASGOW_HASKELL__
+      fullArgs <- getFullArgs
+#else
+      let fullArgs = args
+#endif
+      printf "c command line = %s\n" (show fullArgs)
+      let opt = foldl (flip id) defaultOptions o      
+          timelim = optTimeout opt * 10^(6::Int)
+
+      if (timelim > fromIntegral (maxBound :: Int))
+       then do
+         printf "c TIMEOUT is too long"
+         printf "s UNKNOWN"
+         exitFailure
+       else do
+         ret <- timeout (if timelim > 0 then fromIntegral timelim else (-1)) $ do
+            solver <- newSolver opt
+            let mode =
+                  case optMode opt of
+                    Just m  -> m
+                    Nothing ->
+                      case args2 of
+                        [] -> ModeHelp
+                        fname : _ ->
+                          case map toLower (takeExtension fname) of
+                            ".cnf"  -> ModeSAT
+                            ".opb"  -> ModePB
+                            ".wbo"  -> ModeWBO
+                            ".wcnf" -> ModeMaxSAT
+                            ".lp"   -> ModeLP
+                            _ -> ModeSAT
+            case mode of
+              ModeHelp    -> showHelp stdout
+              ModeVersion -> hPutStrLn stdout (showVersion version)
+              ModeSAT     -> mainSAT opt solver args2
+              ModePB      -> mainPB opt solver args2
+              ModeWBO     -> mainWBO opt solver args2
+              ModeMaxSAT  -> mainMaxSAT opt solver args2
+              ModeLP      -> mainLP opt solver args2
+
+         when (isNothing ret) $ do
+           putStrLn "c TIMEOUT"
+           putStrLn "s UNKNOWN"
+         end <- getCPUTime
+         printf "c total time = %.3fs\n" (fromIntegral (end - start) / 10^(12::Int) :: Double)
+         when (isNothing ret) exitFailure
+
+    (_,_,errs) -> do
+      mapM_ putStrLn errs
+      exitFailure
+
+showHelp :: Handle -> IO ()
+showHelp h = hPutStrLn h (usageInfo header options)
+
+header :: String
+header = unlines
+  [ "Usage:"
+  , "  toysat [OPTION]... [file.cnf||-]"
+  , "  toysat [OPTION]... --pb [file.opb|-]"
+  , "  toysat [OPTION]... --wbo [file.wbo|-]"
+  , "  toysat [OPTION]... --maxsat [file.cnf|file.wcnf|-]"
+  , "  toysat [OPTION]... --lp [file.lp|-]"
+  , ""
+  , "Options:"
+  ]
+
+printSysInfo :: IO ()
+printSysInfo = do
+  tm <- getZonedTime
+  hPrintf stdout "c %s\n" (formatTime defaultTimeLocale "%FT%X%z" tm)
+  hPrintf stdout "c arch = %s\n" SysInfo.arch
+  hPrintf stdout "c os = %s\n" SysInfo.os
+  hPrintf stdout "c compiler = %s %s\n" SysInfo.compilerName (showVersion SysInfo.compilerVersion)
+  hPutStrLn stdout "c packages:"
+  forM_ packageVersions $ \(package, ver) -> do
+    hPrintf stdout "c   %s-%s\n" package ver
+
+newSolver :: Options -> IO SAT.Solver
+newSolver opts = do
+  solver <- SAT.newSolver
+  SAT.setRestartStrategy solver (optRestartStrategy opts)
+  SAT.setRestartFirst  solver (optRestartFirst opts)
+  SAT.setRestartInc    solver (optRestartInc opts)
+  SAT.setLearntSizeInc solver (optLearntSizeInc opts)
+  SAT.setCCMin         solver (optCCMin opts)
+  SAT.setRandomFreq    solver (optRandomFreq opts)
+  when (optRandomSeed opts /= 0) $ 
+    SAT.setRandomSeed solver (optRandomSeed opts)
+  SAT.setLearningStrategy solver (optLearningStrategy opts)
+  SAT.setLogger solver $ \str -> do
+    putStr "c "
+    putStrLn str
+    hFlush stdout
+  SAT.setCheckModel solver (optCheckModel opts)
+  return solver
+
+-- ------------------------------------------------------------------------
+
+mainSAT :: Options -> SAT.Solver -> [String] -> IO ()
+mainSAT opt solver args = do
+  ret <- case args of
+           ["-"]   -> fmap (DIMACS.parseByteString "-") $ BS.hGetContents stdin
+           [fname] -> DIMACS.parseFile fname
+           _ -> showHelp stderr >> exitFailure
+  case ret of
+    Left err -> hPrint stderr err >> exitFailure
+    Right cnf -> solveSAT opt solver cnf
+
+solveSAT :: Options -> SAT.Solver -> DIMACS.CNF -> IO ()
+solveSAT _ solver cnf = do
+  printf "c #vars %d\n" (DIMACS.numVars cnf)
+  printf "c #constraints %d\n" (length (DIMACS.clauses cnf))
+  _ <- replicateM (DIMACS.numVars cnf) (SAT.newVar solver)
+  forM_ (DIMACS.clauses cnf) $ \clause ->
+    SAT.addClause solver (elems clause)
+  result <- SAT.solve solver
+  putStrLn $ "s " ++ (if result then "SATISFIABLE" else "UNSATISFIABLE")
+  hFlush stdout
+  when result $ do
+    m <- SAT.model solver
+    satPrintModel stdout m (DIMACS.numVars cnf)
+
+-- ------------------------------------------------------------------------
+
+mainPB :: Options -> SAT.Solver -> [String] -> IO ()
+mainPB opt solver args = do
+  ret <- case args of
+           ["-"]   -> fmap (PBFile.parseOPBString "-") $ hGetContents stdin
+           [fname] -> PBFile.parseOPBFile fname
+           _ -> showHelp stderr >> exitFailure
+  case ret of
+    Left err -> hPrint stderr err >> exitFailure
+    Right formula -> solvePB opt solver formula
+
+solvePB :: Options -> SAT.Solver -> PBFile.Formula -> IO ()
+solvePB opt solver formula@(obj, cs) = do
+  let n = PBFile.pbNumVars formula
+
+  printf "c #vars %d\n" n
+  printf "c #constraints %d\n" (length cs)
+
+  _ <- replicateM n (SAT.newVar solver)
+  enc <- Tseitin.newEncoder solver
+  Tseitin.setUsePB enc (optLinearizerPB opt)
+
+  forM_ cs $ \(lhs, op, rhs) -> do
+    lhs' <- pbConvSum enc lhs
+    case op of
+      PBFile.Ge -> SAT.addPBAtLeast solver lhs' rhs
+      PBFile.Eq -> SAT.addPBExactly solver lhs' rhs
+
+  case obj of
+    Nothing -> do
+      result <- SAT.solve solver
+      putStrLn $ "s " ++ (if result then "SATISFIABLE" else "UNSATISFIABLE")
+      hFlush stdout
+      when result $ do
+        m <- SAT.model solver
+        pbPrintModel stdout m n
+
+    Just obj' -> do
+      obj'' <- pbConvSum enc obj'
+
+      modelRef <- newIORef Nothing
+
+      result <- try $ minimize opt solver obj'' $ \m val -> do
+        writeIORef modelRef (Just m)
+        putStrLn $ "o " ++ show val
+        hFlush stdout
+
+      case result of
+        Right Nothing -> do
+          putStrLn $ "s " ++ "UNSATISFIABLE"
+          hFlush stdout
+        Right (Just m) -> do
+          putStrLn $ "s " ++ "OPTIMUM FOUND"
+          hFlush stdout
+          pbPrintModel stdout m n
+        Left (e :: AsyncException) -> do
+          r <- readIORef modelRef
+          case r of
+            Nothing -> do
+              putStrLn $ "s " ++ "UNKNOWN"
+              hFlush stdout
+            Just m -> do
+              putStrLn $ "s " ++ "SATISFIABLE"
+              pbPrintModel stdout m n
+          throwIO e
+
+pbConvSum :: Tseitin.Encoder -> PBFile.Sum -> IO [(Integer, SAT.Lit)]
+pbConvSum enc = revMapM f
+  where
+    f (w,ls) = do
+      l <- Tseitin.encodeConj enc ls
+      return (w,l)
+
+minimize :: Options -> SAT.Solver -> [(Integer, SAT.Lit)] -> (SAT.Model -> Integer -> IO ()) -> IO (Maybe SAT.Model)
+minimize opt solver obj update = do
+  when (optObjFunVarsHeuristics opt) $ do
+    forM_ obj $ \(c,l) -> do
+      let p = if c > 0 then not (SAT.litPolarity l) else SAT.litPolarity l
+      SAT.setVarPolarity solver (SAT.litVar l) p
+    forM_ (zip [1..] (map snd (sortBy (comparing fst) [(abs c, l) | (c,l) <- obj]))) $ \(n,l) -> do
+      replicateM n $ SAT.varBumpActivity solver (SAT.litVar l)
+
+  result <- SAT.solve solver
+  if not result then
+    return Nothing
+  else if optBinarySearch opt then
+    liftM Just binSearch 
+  else
+    liftM Just linSearch
+
+  where
+   linSearch :: IO SAT.Model
+   linSearch = do
+     m <- SAT.model solver
+     let v = pbEval m obj
+     update m v
+     SAT.addPBAtMost solver obj (v - 1)
+     result <- SAT.solve solver
+     if result
+       then linSearch
+       else return m
+
+   binSearch :: IO SAT.Model
+   binSearch = do
+{-
+     printf "c Binary Search: minimizing %s \n" $ 
+       intercalate " "
+         [c' ++ " " ++ l'
+         | (c,l) <- obj
+         , let c' = if c < 0 then show c else "+" ++ show c
+         , let l' = (if l < 0 then "~" else "") ++ "x" ++ show (SAT.litVar l)
+         ]
+-}
+     m0 <- SAT.model solver
+     let v0 = pbEval m0 obj
+     update m0 v0
+     let ub0 = v0 - 1
+         lb0 = pbLowerBound obj
+     SAT.addPBAtMost solver obj ub0
+
+     let loop lb ub m | ub < lb = return m
+         loop lb ub m = do
+           let mid = (lb + ub) `div` 2
+           printf "c Binary Search: %d <= obj <= %d; guessing obj <= %d\n" lb ub mid
+           sel <- SAT.newVar solver
+           SAT.addPBAtMostSoft solver sel obj mid
+           ret <- SAT.solveWith solver [sel]
+           if ret
+           then do
+             m2 <- SAT.model solver
+             let v = pbEval m2 obj
+             update m2 v
+             -- deactivating temporary constraint
+             -- FIXME: {Í§ñÌíðµ½¢
+             SAT.addClause solver [-sel]
+             let ub' = v - 1
+             printf "c Binary Search: updating upper bound: %d -> %d\n" ub ub'
+             SAT.addPBAtMost solver obj ub'
+             loop lb ub' m2
+           else do
+             -- deactivating temporary constraint
+             -- FIXME: {Í§ñÌíðµ½¢
+             SAT.addClause solver [-sel]
+             let lb' = mid + 1
+             printf "c Binary Search: updating lower bound: %d -> %d\n" lb lb'
+             SAT.addPBAtLeast solver obj lb'
+             loop lb' ub m
+
+     loop lb0 ub0 m0
+
+-- ------------------------------------------------------------------------
+
+mainWBO :: Options -> SAT.Solver -> [String] -> IO ()
+mainWBO opt solver args = do
+  ret <- case args of
+           ["-"]   -> fmap (PBFile.parseWBOString "-") $ hGetContents stdin
+           [fname] -> PBFile.parseWBOFile fname
+           _ -> showHelp stderr >> exitFailure
+  case ret of
+    Left err -> hPrint stderr err >> exitFailure
+    Right formula -> solveWBO opt solver False formula
+
+solveWBO :: Options -> SAT.Solver -> Bool -> PBFile.SoftFormula -> IO ()
+solveWBO opt solver isMaxSat formula@(tco, cs) = do
+  let nvar = PBFile.wboNumVars formula
+  printf "c #vars %d\n" nvar
+  printf "c #constraints %d\n" (length cs)
+
+  _ <- replicateM nvar (SAT.newVar solver)
+  enc <- Tseitin.newEncoder solver
+  Tseitin.setUsePB enc (optLinearizerPB opt)
+
+  obj <- liftM concat $ revForM cs $ \(cost, (lhs, op, rhs)) -> do
+    lhs' <- pbConvSum enc lhs
+    case cost of
+      Nothing -> do
+        case op of
+          PBFile.Ge -> SAT.addPBAtLeast solver lhs' rhs
+          PBFile.Eq -> SAT.addPBExactly solver lhs' rhs
+        return []
+      Just cval -> do
+        sel <- SAT.newVar solver
+        case op of
+          PBFile.Ge -> SAT.addPBAtLeastSoft solver sel lhs' rhs
+          PBFile.Eq -> SAT.addPBExactlySoft solver sel lhs' rhs
+        return [(cval, SAT.litNot sel)]
+
+  case tco of
+    Nothing -> return ()
+    Just c -> SAT.addPBAtMost solver obj (c-1)
+
+  modelRef <- newIORef Nothing
+  result <- try $ minimize opt solver obj $ \m val -> do
+     writeIORef modelRef (Just m)
+     putStrLn $ "o " ++ show val
+     hFlush stdout
+
+  case result of
+    Right Nothing -> do
+      putStrLn $ "s " ++ "UNSATISFIABLE"
+      hFlush stdout
+    Right (Just m) -> do
+      putStrLn $ "s " ++ "OPTIMUM FOUND"
+      hFlush stdout
+      if isMaxSat
+        then maxsatPrintModel stdout m nvar
+        else pbPrintModel stdout m nvar
+    Left (e :: AsyncException) -> do
+      r <- readIORef modelRef
+      case r of
+        Just m | not isMaxSat -> do
+          putStrLn $ "s " ++ "SATISFIABLE"
+          pbPrintModel stdout m nvar
+        _ -> do
+          putStrLn $ "s " ++ "UNKNOWN"
+          hFlush stdout
+      throwIO e
+
+-- ------------------------------------------------------------------------
+
+mainMaxSAT :: Options -> SAT.Solver -> [String] -> IO ()
+mainMaxSAT opt solver args = do
+  s <- case args of
+         ["-"]   -> getContents
+         [fname] -> readFile fname
+         _ -> showHelp stderr  >> exitFailure
+  let wcnf = MaxSAT.parseWCNFString s
+  solveMaxSAT opt solver wcnf
+
+solveMaxSAT :: Options -> SAT.Solver -> MaxSAT.WCNF -> IO ()
+solveMaxSAT opt solver (_, top, cs) = do
+  solveWBO opt solver True
+           ( Nothing
+           , [ (if w >= top then Nothing else Just w
+             , ([(1,[lit]) | lit<-lits], PBFile.Ge, 1))
+             | (w,lits) <- cs
+             ]
+           )
+
+-- ------------------------------------------------------------------------
+
+mainLP :: Options -> SAT.Solver -> [String] -> IO ()
+mainLP opt solver args = do
+  ret <- case args of
+           ["-"]   -> fmap (LPFile.parseString "-") $ hGetContents stdin
+           [fname] -> LPFile.parseFile fname
+           _ -> showHelp stderr >> exitFailure
+  case ret of
+    Left err -> hPrint stderr err >> exitFailure
+    Right lp -> solveLP opt solver lp
+
+solveLP :: Options -> SAT.Solver -> LPFile.LP -> IO ()
+solveLP opt solver lp = do
+  if not (Set.null nivs)
+    then do
+      putStrLn $ "c cannot handle non-integer variables: " ++ intercalate ", " (Set.toList nivs)
+      putStrLn "s UNKNOWN"
+      exitFailure
+    else do
+      putStrLn "c Loading variables and bounds"
+      vmap <- liftM Map.fromList $ revForM (Set.toList ivs) $ \v -> do
+        let (lb,ub) = LPFile.getBounds lp v
+        case (lb,ub) of
+          (LPFile.Finite lb', LPFile.Finite ub') -> do
+            v2 <- SAT.Integer.newVar solver (ceiling lb') (floor ub')
+            return (v,v2)
+          _ -> do
+            putStrLn $ "c cannot handle unbounded variable: " ++ v
+            putStrLn "s UNKNOWN"
+            exitFailure
+
+      putStrLn "c Loading constraints"
+      forM_ (LPFile.constraints lp) $ \c -> do
+        let indicator      = LPFile.constrIndicator c
+            (lhs, op, rhs) = LPFile.constrBody c
+        let d = foldl' lcm 1 (map denominator  (rhs:[r | LPFile.Term r _ <- lhs]))
+            lhs' = lsum [asInteger (r * fromIntegral d) .*. (vmap Map.! asSingleton vs) | LPFile.Term r vs <- lhs]
+            rhs' = asInteger (rhs * fromIntegral d)
+        case indicator of
+          Nothing ->
+            case op of
+              LPFile.Le  -> SAT.Integer.addLe solver lhs' (SAT.Integer.constant rhs')
+              LPFile.Ge  -> SAT.Integer.addGe solver lhs' (SAT.Integer.constant rhs')
+              LPFile.Eql -> SAT.Integer.addEq solver lhs' (SAT.Integer.constant rhs')
+          Just (var, val) -> do
+            let var' = asBin (vmap Map.! var)
+                f sel = do
+                  case op of
+                    LPFile.Le  -> SAT.Integer.addLeSoft solver sel lhs' (SAT.Integer.constant rhs')
+                    LPFile.Ge  -> SAT.Integer.addGeSoft solver sel lhs' (SAT.Integer.constant rhs')
+                    LPFile.Eql -> SAT.Integer.addEqSoft solver sel lhs' (SAT.Integer.constant rhs')
+            case val of
+              1 -> f var'
+              0 -> f (SAT.litNot var')
+              _ -> return ()
+
+      putStrLn "c Loading SOS constraints"
+      forM_ (LPFile.sos lp) $ \(_label, typ, xs) -> do
+        case typ of
+          LPFile.S1 -> SAT.addAtMost solver (map (asBin . (vmap Map.!) . fst) xs) 1
+          LPFile.S2 -> do
+            let ps = nonAdjacentPairs $ map fst $ sortBy (comparing snd) $ xs
+            forM_ ps $ \(x1,x2) -> do
+              SAT.addClause solver [SAT.litNot $ asBin $ vmap Map.! v | v <- [x1,x2]]
+
+      let (_label,obj) = LPFile.objectiveFunction lp      
+          d = foldl' lcm 1 [denominator r | LPFile.Term r _ <- obj] *
+              (if LPFile.dir lp == LPFile.OptMin then 1 else -1)
+          obj2 = lsum [asInteger (r * fromIntegral d) .*. (vmap Map.! (asSingleton vs)) | LPFile.Term r vs <- obj]
+          SAT.Integer.Expr obj3 obj3_c = obj2
+
+      modelRef <- newIORef Nothing
+
+      result <- try $ minimize opt solver obj3 $ \m val -> do
+        writeIORef modelRef (Just m)
+        putStrLn $ "o " ++ showRational (optPrintRational opt) (fromIntegral (val + obj3_c) / fromIntegral d)
+        hFlush stdout
+
+      let printModel :: SAT.Model -> IO ()
+          printModel m = do
+            forM_ (Set.toList ivs) $ \v -> do
+              let val = SAT.Integer.eval m (vmap Map.! v)
+              printf "v %s = %d\n" v val
+            hFlush stdout
+
+      case result of
+        Right Nothing -> do
+          putStrLn $ "s " ++ "UNSATISFIABLE"
+          hFlush stdout
+        Right (Just m) -> do
+          putStrLn $ "s " ++ "OPTIMUM FOUND"
+          hFlush stdout
+          printModel m
+        Left (e :: AsyncException) -> do
+          r <- readIORef modelRef
+          case r of
+            Nothing -> do
+              putStrLn $ "s " ++ "UNKNOWN"
+              hFlush stdout
+            Just m -> do
+              putStrLn $ "s " ++ "SATISFIABLE"
+              printModel m
+          throwIO e
+  where
+    ivs = LPFile.binaryVariables lp `Set.union` LPFile.integerVariables lp
+    nivs = LPFile.variables lp `Set.difference` ivs
+
+    asSingleton :: [a] -> a
+    asSingleton [v] = v
+    asSingleton _ = error "not a singleton"
+
+    asInteger :: Rational -> Integer
+    asInteger r
+      | denominator r /= 1 = error (show r ++ " is not integer")
+      | otherwise = numerator r
+    
+    nonAdjacentPairs :: [a] -> [(a,a)]
+    nonAdjacentPairs (x1:x2:xs) = [(x1,x3) | x3 <- xs] ++ nonAdjacentPairs (x2:xs)
+    nonAdjacentPairs _ = []
+
+    asBin :: SAT.Integer.Expr -> SAT.Lit
+    asBin (SAT.Integer.Expr [(1,lit)] _) = lit
+    asBin _ = error "asBin: failure"
+
+-- ------------------------------------------------------------------------
+
diff --git a/src/toysolver.hs b/src/toysolver.hs
new file mode 100644
--- /dev/null
+++ b/src/toysolver.hs
@@ -0,0 +1,300 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  toysolver
+-- Copyright   :  (c) Masahiro Sakai 2011
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+
+
+module Main where
+
+import Control.Monad
+import Data.Char
+import Data.List
+import Data.Maybe
+import Data.Ratio
+import qualified Data.Version as V
+import qualified Data.Set as Set
+import qualified Data.Map as Map
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+import System.Exit
+import System.Environment
+import System.FilePath
+import System.Console.GetOpt
+import System.IO
+import Text.Printf
+import qualified Language.CNF.Parse.ParseDIMACS as DIMACS
+
+import Data.Expr
+import Data.Formula
+import qualified Data.LA as LA
+import qualified OmegaTest
+import qualified Cooper
+import qualified MIPSolverHL
+import qualified Text.LPFile as LP
+import qualified Text.PBFile as PBFile
+import qualified Text.MaxSAT as MaxSAT
+import qualified Converter.CNF2LP as CNF2LP
+import qualified Converter.PB2LP as PB2LP
+import qualified Converter.MaxSAT2LP as MaxSAT2LP
+import qualified Simplex2
+import qualified MIPSolver2
+import SAT.Printer
+import Version
+import Util
+
+-- ---------------------------------------------------------------------------
+
+data Mode = ModeSAT | ModePB | ModeWBO | ModeMaxSAT | ModeLP
+  deriving (Eq, Ord)
+
+data Flag
+    = Help
+    | Version
+    | Solver String
+    | PrintRational
+    | PivotStrategy String
+    | NThread !Int
+    | Mode !Mode
+    deriving Eq
+
+options :: [OptDescr Flag]
+options =
+    [ Option ['h'] ["help"]    (NoArg Help)            "show help"
+    , Option ['v'] ["version"] (NoArg Version)         "show version number"
+    , Option [] ["solver"] (ReqArg Solver "SOLVER")    "mip (default), omega-test, cooper, old-mip"
+    , Option [] ["print-rational"] (NoArg PrintRational) "print rational numbers instead of decimals"
+    , Option [] ["pivot-strategy"] (ReqArg PivotStrategy "[bland-rule|largest-coefficient]") "pivot strategy for simplex (default: bland-rule)"
+    , Option [] ["threads"] (ReqArg (NThread . read) "INTEGER") "number of threads to use"
+
+    , Option []    ["sat"]    (NoArg (Mode ModeSAT))    "solve pseudo boolean problems in .cnf file"
+    , Option []    ["pb"]     (NoArg (Mode ModePB))     "solve pseudo boolean problems in .pb file"
+    , Option []    ["wbo"]    (NoArg (Mode ModeWBO))    "solve weighted boolean optimization problem in .opb file"
+    , Option []    ["maxsat"] (NoArg (Mode ModeMaxSAT)) "solve MaxSAT problem in .cnf or .wcnf file"
+    , Option []    ["lp"]     (NoArg (Mode ModeLP))     "solve binary integer programming problem in .lp file (default)"
+    ]
+
+header :: String
+header = "Usage: toysolver [OPTION]... file.lp"
+
+-- ---------------------------------------------------------------------------
+
+run
+  :: String
+  -> [Flag]
+  -> LP.LP
+  -> (Map.Map String Rational -> IO ())
+  -> IO ()
+run solver opt lp printModel = do
+  unless (Set.null (LP.semiContinuousVariables lp)) $ do
+    hPutStrLn stderr "semi-continuous variables are not supported."
+    exitFailure  
+  case map toLower solver of
+    s | s `elem` ["omega-test", "cooper"] -> solveByQE
+    s | s `elem` ["old-mip"] -> solveByMIP
+    _ -> solveByMIP2
+  where
+    vs = LP.variables lp
+    vsAssoc = zip (Set.toList vs) [0..]
+    nameToVar = Map.fromList vsAssoc
+    varToName = IM.fromList [(v,name) | (name,v) <- vsAssoc]
+
+    compileE :: LP.Expr -> Expr Rational
+    compileE = foldr (+) (Const 0) . map compileT
+
+    compileT :: LP.Term -> Expr Rational
+    compileT (LP.Term c vs) =
+      foldr (*) (Const c) [Var (nameToVar Map.! v) | v <- vs]
+
+    obj = compileE $ snd $ LP.objectiveFunction lp
+
+    cs1 = do
+      v <- Set.toList vs
+      let v2 = Var (nameToVar Map.! v)
+      let (l,u) = LP.getBounds lp v
+      [Const x .<=. v2 | LP.Finite x <- return l] ++
+        [v2 .<=. Const x | LP.Finite x <- return u]
+    cs2 = do
+      LP.Constraint
+        { LP.constrIndicator = ind
+        , LP.constrBody = (lhs, rel, rhs)
+        } <- LP.constraints lp
+      let rel2 = case rel of
+                  LP.Ge  -> Ge
+                  LP.Le  -> Le
+                  LP.Eql -> Eql
+      case ind of
+        Nothing -> return (Rel (compileE lhs) rel2 (Const rhs))
+        Just _ -> error "indicator constraint is not supported yet"
+    cs3 = do
+      v <- Set.toList (LP.binaryVariables lp)
+      let v' = nameToVar Map.! v
+      [ Const 0 .<=. Var v', Var v' .<=. Const 1 ]
+
+    ivs = f (LP.integerVariables lp) `IS.union` f (LP.binaryVariables lp)
+      where
+        f = IS.fromList . map (nameToVar Map.!) . Set.toList
+
+    solveByQE =
+      case mapM LA.compileAtom (cs1 ++ cs2 ++ cs3) of
+        Nothing -> do
+          putStrLn "s UNKNOWN"
+          exitFailure
+        Just cs ->
+          case f cs ivs of
+            Nothing -> do
+              putStrLn "s UNSATISFIABLE"
+              exitFailure
+            Just m -> do
+              putStrLn $ "o " ++ showValue (Data.Expr.eval m obj)
+              putStrLn "s SATISFIABLE"
+              let m2 = Map.fromAscList [(v, m IM.! (nameToVar Map.! v)) | v <- Set.toList vs]
+              printModel m2
+       where
+         f = case solver of
+               "omega-test" -> OmegaTest.solveQFLA
+               "cooper"     -> Cooper.solveQFLA
+               _ -> error "unknown solver"
+
+    solveByMIP =
+      case MIPSolverHL.optimize (LP.dir lp) obj (cs1 ++ cs2 ++ cs3) ivs of
+        OptUnknown -> do
+          putStrLn "s UNKNOWN"
+          exitFailure
+        OptUnsat -> do
+          putStrLn "s UNSATISFIABLE"
+          exitFailure
+        Unbounded -> do
+          putStrLn "s UNBOUNDED"
+          exitFailure
+        Optimum r m -> do
+          putStrLn $ "o " ++ showValue r
+          putStrLn "s OPTIMUM FOUND"
+          let m2 = Map.fromAscList [(v, m IM.! (nameToVar Map.! v)) | v <- Set.toList vs]
+          printModel m2
+
+    solveByMIP2 = do
+      solver <- Simplex2.newSolver
+
+      let ps = last ("bland-rule" : [s | PivotStrategy s <- opt])
+      case ps of
+        "bland-rule"          -> Simplex2.setPivotStrategy solver Simplex2.PivotStrategyBlandRule
+        "largest-coefficient" -> Simplex2.setPivotStrategy solver Simplex2.PivotStrategyLargestCoefficient
+        _ -> error ("unknown pivot strategy \"" ++ ps ++ "\"")
+
+      let nthreads = last (0 : [n | NThread n <- opt])
+
+      let logger s = putStr "c " >> putStrLn s >> hFlush stdout
+
+      Simplex2.setLogger solver logger
+      replicateM (length vsAssoc) (Simplex2.newVar solver) -- XXX
+      Simplex2.setOptDir solver (LP.dir lp)
+      Simplex2.setObj solver $ fromJust (LA.compileExpr obj)
+      logger "Loading constraints... "
+      forM_ (cs1 ++ cs2 ++ cs3) $ \c -> do
+        Simplex2.assertAtom solver $ fromJust (LA.compileAtom c)
+      logger "Loading constraints finished"
+
+      mip <- MIPSolver2.newSolver solver ivs
+      MIPSolver2.setShowRational mip printRat
+      MIPSolver2.setLogger mip logger
+      MIPSolver2.setNThread mip nthreads
+      let update m val = do
+            putStrLn $ "o " ++ showValue val
+      ret <- MIPSolver2.optimize mip update
+      case ret of
+        Simplex2.Unsat -> do
+          putStrLn "s UNSATISFIABLE"
+          exitFailure
+        Simplex2.Unbounded -> do
+          putStrLn "s UNBOUNDED"
+          exitFailure
+        Simplex2.Optimum -> do
+          m <- MIPSolver2.model mip
+          r <- MIPSolver2.getObjValue mip
+          putStrLn "s OPTIMUM FOUND"
+          let m2 = Map.fromAscList [(v, m IM.! (nameToVar Map.! v)) | v <- Set.toList vs]
+          printModel m2
+
+    printRat :: Bool
+    printRat = PrintRational `elem` opt
+
+    showValue :: Rational -> String
+    showValue = showRational printRat
+
+lpPrintModel :: Handle -> Bool -> Map.Map String Rational -> IO ()
+lpPrintModel h asRat m = do
+  forM_ (Map.toList m) $ \(v, val) -> do
+    printf "v %s = %s\n" v (showRational asRat val)
+
+-- ---------------------------------------------------------------------------
+
+getSolver :: [Flag] -> String
+getSolver xs = last $ "mip" : [s | Solver s <- xs]
+
+main :: IO ()
+main = do
+  args <- getArgs
+  case getOpt Permute options args of
+    (o,_,[])
+      | Help `elem` o    -> putStrLn (usageInfo header options)
+      | Version `elem` o -> putStrLn (V.showVersion version)
+    (o,[fname],[]) -> do
+
+      let mode =
+            case reverse [m | Mode m <- o] of
+              m:_ -> m
+              [] ->
+                case map toLower (takeExtension fname) of
+                  ".cnf"  -> ModeSAT
+                  ".opb"  -> ModePB
+                  ".wbo"  -> ModeWBO
+                  ".wcnf" -> ModeMaxSAT
+                  ".lp"   -> ModeLP
+                  _ -> ModeLP
+
+      case mode of
+        ModeSAT -> do
+          ret <- DIMACS.parseFile fname
+          case ret of
+            Left err -> hPrint stderr err >> exitFailure
+            Right cnf -> do
+              let (lp,mtrans) = CNF2LP.convert CNF2LP.ObjNone cnf
+              run (getSolver o) o lp $ \m -> do
+                satPrintModel stdout (mtrans m) 0
+        ModePB -> do
+          ret <- PBFile.parseOPBFile fname
+          case ret of
+            Left err -> hPrint stderr err >> exitFailure
+            Right pb -> do
+              let (lp,mtrans) = PB2LP.convert PB2LP.ObjNone pb
+              run (getSolver o) o lp $ \m -> do
+                pbPrintModel stdout (mtrans m) 0
+        ModeWBO -> do
+          ret <- PBFile.parseWBOFile fname
+          case ret of
+            Left err -> hPrint stderr err >> exitFailure
+            Right wbo -> do
+              let (lp,mtrans) = PB2LP.convertWBO False wbo
+              run (getSolver o) o lp $ \m -> do
+                pbPrintModel stdout (mtrans m) 0
+        ModeMaxSAT -> do
+          wcnf <- MaxSAT.parseWCNFFile fname
+          let (lp,mtrans) = MaxSAT2LP.convert wcnf
+          run (getSolver o) o lp $ \m -> do
+            maxsatPrintModel stdout (mtrans m) 0
+        ModeLP -> do
+          ret <- LP.parseFile fname
+          case ret of
+            Left err -> hPrint stderr err >> exitFailure
+            Right lp -> do
+              run (getSolver o) o lp $ \m -> do
+                lpPrintModel stdout (PrintRational `elem` o) m
+    (_,_,errs) ->
+        hPutStrLn stderr $ concat errs ++ usageInfo header options
diff --git a/toysolver.cabal b/toysolver.cabal
new file mode 100644
--- /dev/null
+++ b/toysolver.cabal
@@ -0,0 +1,244 @@
+Name:		toysolver
+Version:	0.0.2
+License:	BSD3
+License-File:	COPYING
+Author:		Masahiro Sakai (masahiro.sakai@gmail.com)
+Maintainer:	masahiro.sakai@gmail.com
+Category:	Algorithms
+Cabal-Version:	>= 1.8
+Synopsis:	Assorted decision procedures
+Description:	Toy-level implementation of some decision procedures
+Bug-Reports:	https://github.com/msakai/toysolver/issues
+Extra-Source-Files:
+   README.md
+   COPYING
+   src/TseitinEncode.hs
+   src/CongruenceClosure.hs
+   src/ContiTraverso.hs
+   src/Data/Polynomial.hs
+   src/Data/Polynomial/GBase.hs
+   src/Data/Polynomial/FactorZ.hs
+   src/Data/Polynomial/Graeffe.hs
+   src/Data/Polynomial/Lagrange.hs
+   src/Data/Polynomial/Sturm.hs
+   src/Data/AlgebraicNumber.hs
+   src/Data/AlgebraicNumber/Root.hs
+   src/Data/AlgebraicNumber/RealInstance.hs
+   src/Data/Polyhedron.hs
+   src/Text/SDPFile.hs
+   src/TestAReal2.hs
+   src/pbverify.hs
+   src/pigeonhole.hs
+   src/Wang.hs
+   samples/gcnf/*.gcnf
+   samples/lp/*.lp
+   samples/lp/error/*.lp
+   samples/maxsat/*.cnf
+   samples/maxsat/*.wcnf
+   samples/pbo/*.opb
+   samples/pbs/*.opb
+   samples/sat/*.cnf
+   samples/wbo/*.wbo
+   samples/sdp/*.dat
+   samples/sdp/*.dat-s
+   samples/smt/*.smt2
+   samples/qbf/*.qdimacs
+Build-Type: Simple
+
+Flag ForceChar8
+  Description: set default encoding to char8 (not to use iconv)
+  Default: False
+
+source-repository head
+  type:     git
+  location: git://github.com/msakai/toysolver.git
+
+Executable toysolver
+  Main-is: toysolver.hs
+  HS-Source-Dirs: src
+  Other-Modules:
+     Converter.CNF2LP
+     Converter.ObjType
+     Converter.PB2LP
+     Data.Delta
+     Data.Expr
+     Data.Lattice
+     Data.Formula
+     Data.LA
+     Data.Linear
+     Data.Interval
+     SAT.Printer
+     Text.LPFile
+     Text.PBFile
+     Text.MaxSAT
+     BoundsInference
+     Cooper     
+     FourierMotzkin
+     LPSolver
+     LPSolverHL
+     MIPSolverHL
+     OmegaTest
+     Simplex
+     Simplex2
+     MIPSolver2
+     Util
+     Version
+  Build-Depends: base >=4 && <5, mtl, containers, array, filepath, parsec, OptDir, deepseq, stm >=2.3, parse-dimacs
+  Extensions:
+     BangPatterns
+     ScopedTypeVariables
+     FlexibleInstances
+     MultiParamTypeClasses
+     FunctionalDependencies
+     GeneralizedNewtypeDeriving
+     DoAndIfThenElse
+  if impl(ghc)
+    GHC-Options: -threaded
+  if impl(ghc >= 7)
+    GHC-Options: -rtsopts
+  GHC-Prof-Options: -auto-all
+
+Executable toysat
+  Main-is: toysat.hs
+  HS-Source-Dirs: src
+  Other-Modules:
+     Data.LBool
+     Data.IndexedPriorityQueue
+     Data.SeqQueue
+     Text.LPFile
+     Text.PBFile
+     Text.MaxSAT
+     SAT
+     SAT.Integer
+     SAT.TseitinEncoder
+     SAT.Types
+     SAT.TheorySolver
+     SAT.Printer
+     Version
+  Build-Depends: base >=4 && <5, mtl, containers >= 0.4.2, array, random, parsec, bytestring, filepath, parse-dimacs, queue, OptDir, time, old-locale
+  Extensions:
+     MultiParamTypeClasses
+     FlexibleInstances
+     BangPatterns
+     DoAndIfThenElse
+     CPP
+  if impl(ghc >= 7)
+    GHC-Options: -rtsopts
+  GHC-Prof-Options: -auto-all
+  if flag(ForceChar8) && impl(ghc)
+    Build-Depends: base >=4.5
+    CPP-OPtions: "-DFORCE_CHAR8"
+
+Executable lp2yices
+  Main-is: lp2yices.hs
+  HS-Source-Dirs: src
+  Other-Modules:
+     Text.LPFile
+     Util
+  Build-Depends: base >=4 && <5, mtl, containers, parsec, OptDir
+  Extensions:
+     BangPatterns
+     ScopedTypeVariables
+     FlexibleInstances
+     MultiParamTypeClasses
+     FunctionalDependencies
+     GeneralizedNewtypeDeriving
+
+Executable cnf2lp
+  Main-is: cnf2lp.hs
+  HS-Source-Dirs: src
+  Other-Modules:
+     Text.LPFile
+     Converter.CNF2LP
+     Converter.ObjType
+     Util
+  Build-Depends: base >=4 && <5, mtl, containers, array, parsec, bytestring, parse-dimacs, OptDir
+  Extensions:
+     BangPatterns
+     ScopedTypeVariables
+     FlexibleInstances
+     MultiParamTypeClasses
+     FunctionalDependencies
+     GeneralizedNewtypeDeriving
+
+Executable maxsat2lp
+  Main-is: maxsat2lp.hs
+  HS-Source-Dirs: src
+  Other-Modules:
+     SAT.Types
+     Text.MaxSAT
+     Converter.MaxSAT2LP
+  Build-Depends: base >=4 && <5, mtl, containers, array, parsec, OptDir
+
+Executable pb2lp
+  Main-is: pb2lp.hs
+  HS-Source-Dirs: src
+  Other-Modules:
+     Text.LPFile
+     Text.PBFile
+     Converter.PB2LP
+     Converter.ObjType
+  Build-Depends: base >=4 && <5, mtl, containers, array, parsec, OptDir
+
+Test-suite TestSAT
+  Type:              exitcode-stdio-1.0
+  HS-Source-Dirs:    src
+  Main-is:           TestSAT.hs
+  Build-depends:     base >=4 && <5, array, containers, random, queue, test-framework,test-framework-th,test-framework-hunit,HUnit,OptDir
+  Extensions: TemplateHaskell, DoAndIfThenElse
+
+Test-suite TestSimplex2
+  Type:              exitcode-stdio-1.0
+  HS-Source-Dirs:    src
+  Main-is:           TestSimplex2.hs
+  Build-depends:     base >=4 && <5, containers, deepseq, queue, test-framework,test-framework-th,test-framework-hunit,HUnit,OptDir
+  Extensions: TemplateHaskell, DoAndIfThenElse
+
+Test-suite TestMIPSolver2
+  Type:              exitcode-stdio-1.0
+  HS-Source-Dirs:    src
+  Main-is:           TestMIPSolver2.hs
+  Build-depends:     base >=4 && <5, containers, deepseq, queue, test-framework, test-framework-th, test-framework-hunit, HUnit, OptDir, stm
+  Extensions: TemplateHaskell, DoAndIfThenElse
+
+Test-suite TestPolynomial
+  Type:              exitcode-stdio-1.0
+  HS-Source-Dirs:    src
+  Main-is:           TestPolynomial.hs
+  Build-depends:     base >=4 && <5, containers, heaps, test-framework,test-framework-th,test-framework-hunit,test-framework-quickcheck2,HUnit,QuickCheck >=2 && <3
+  Extensions: TemplateHaskell, DoAndIfThenElse
+
+Test-suite TestInterval
+  Type:              exitcode-stdio-1.0
+  HS-Source-Dirs:    src
+  Main-is:           TestInterval.hs
+  Build-depends:     base >=4 && <5, containers, test-framework,test-framework-th,test-framework-hunit,test-framework-quickcheck2,HUnit,QuickCheck >=2 && <3
+  Extensions: TemplateHaskell, DoAndIfThenElse
+
+Test-suite TestAReal
+  Type:              exitcode-stdio-1.0
+  HS-Source-Dirs:    src
+  Main-is:           TestAReal.hs
+  Build-depends:     base >=4 && <5, containers, heaps, primes, test-framework,test-framework-th,test-framework-hunit,test-framework-quickcheck2,HUnit,QuickCheck >=2 && <3
+  Extensions: TemplateHaskell, DoAndIfThenElse
+
+Test-suite TestLPFile
+  Type:              exitcode-stdio-1.0
+  HS-Source-Dirs:    src
+  Main-is:           TestLPFile.hs
+  Build-depends:     base >=4 && <5, mtl, containers, parsec, OptDir, test-framework,test-framework-th,test-framework-hunit,test-framework-quickcheck2,HUnit,QuickCheck >=2 && <3
+  Extensions: TemplateHaskell, DoAndIfThenElse
+
+Test-suite TestPBFile
+  Type:              exitcode-stdio-1.0
+  HS-Source-Dirs:    src
+  Main-is:           TestPBFile.hs
+  Build-depends:     base >=4 && <5, mtl, containers, parsec, test-framework,test-framework-th,test-framework-hunit,test-framework-quickcheck2,HUnit,QuickCheck >=2 && <3
+  Extensions: TemplateHaskell, DoAndIfThenElse
+
+Benchmark BenchmarkSATLIB
+  type:             exitcode-stdio-1.0
+  hs-source-dirs:   src
+  main-is:          BenchmarkSATLIB.hs
+  build-depends:    base >=4 && <5, array, containers, random, queue, parse-dimacs, criterion
+  Extensions: TemplateHaskell, DoAndIfThenElse
