diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,8 @@
 toysolver
 =========
 
+Assorted decision procedures for SAT, Max-SAT, PB, MIP, etc.
+
 Installation
 ------------
 
@@ -75,6 +77,19 @@
 
 * Input formats: lp, mps, cnf, wcnf, opb, wbo
 * Output formats: lp, smt2, ys
+
+### pbconvert
+
+Converter between SAT/PB-related formats
+
+Usage:
+
+    pbconvert -o <outputile> <inputfile>
+
+Supported formats:
+
+* Input formats: cnf, wcnf, opb, wbo
+* Output formats: opb wbo
 
 TODO
 ----
diff --git a/lpconvert/lpconvert.hs b/lpconvert/lpconvert.hs
--- a/lpconvert/lpconvert.hs
+++ b/lpconvert/lpconvert.hs
@@ -27,10 +27,12 @@
 import qualified Text.MPSFile as MPSFile
 import qualified Text.PBFile as PBFile
 import Converter.ObjType
-import qualified Converter.CNF2LP as CNF2LP
 import qualified Converter.LP2SMT as LP2SMT
 import qualified Converter.MaxSAT2LP as MaxSAT2LP
+import qualified Converter.MaxSAT2NLPB as MaxSAT2NLPB
 import qualified Converter.PB2LP as PB2LP
+import qualified Converter.PBSetObj as PBSetObj
+import qualified Converter.SAT2PB as SAT2PB
 import Version
 
 data Flag
@@ -43,6 +45,7 @@
   | Optimize
   | NoCheck
   | NoProduceModel
+  | MaxSATNonLinear
   deriving Eq
 
 options :: [OptDescr Flag]
@@ -50,12 +53,13 @@
     [ Option ['h'] ["help"] (NoArg Help) "show help"
     , Option ['v'] ["version"] (NoArg Version)         "show version number"
     , Option ['o'] [] (ReqArg Output "FILE") "output filename"
-    , Option []    ["max-sat"]  (NoArg AsMaxSAT)  "treat *.cnf file as MAX-SAT problem"
+    , Option []    ["maxsat"]  (NoArg AsMaxSAT)  "treat *.cnf file as MAX-SAT problem"
     , Option []    ["obj"] (ReqArg (ObjType . parseObjType) "STRING") "objective function for SAT/PBS: none (default), max-one, max-zero"
     , Option []    ["indicator"] (NoArg IndicatorConstraint) "use indicator constraints in output LP file"
     , Option []    ["smt-optimize"] (NoArg Optimize)   "output optimiality condition which uses quantifiers"
     , Option []    ["smt-no-check"] (NoArg NoCheck)    "do not output \"(check)\""
     , Option []    ["smt-no-produce-model"] (NoArg NoProduceModel) "do not output \"(set-option :produce-models true)\""    
+    , Option []    ["maxsat-nonlinear"] (NoArg MaxSATNonLinear) "use non-linear formulation of Max-SAT"
     ]
   where
     parseObjType s =
@@ -79,7 +83,6 @@
 
 readLP :: [Flag] -> String -> IO LPFile.LP
 readLP o fname = do
-  let objType = last (ObjNone : [t | ObjType t <- o])
   case map toLower (takeExtension fname) of
     ".cnf"
       | AsMaxSAT `elem` o -> readWCNF
@@ -88,7 +91,8 @@
           case ret of
             Left err -> hPrint stderr err >> exitFailure
             Right cnf -> do
-              let (lp, _) = CNF2LP.convert objType cnf
+              let pb = transformPBFile o $ SAT2PB.convert cnf
+              let (lp, _) = PB2LP.convert pb
               return lp
     ".wcnf" -> readWCNF
     ".opb"  -> do
@@ -96,7 +100,8 @@
       case ret of
         Left err -> hPrint stderr err >> exitFailure
         Right formula -> do
-          let (lp, _) = PB2LP.convert objType formula
+          let pb = transformPBFile o formula
+          let (lp, _) = PB2LP.convert pb
           return lp
     ".wbo"  -> do
       ret <- PBFile.parseWBOFile fname
@@ -122,9 +127,20 @@
       ret <- MaxSAT.parseWCNFFile fname
       case ret of
         Left err -> hPutStrLn stderr err >> exitFailure
-        Right wcnf -> do
-          let (lp, _) = MaxSAT2LP.convert wcnf
-          return lp
+        Right wcnf
+          | MaxSATNonLinear `elem` o -> do
+              let pb = transformPBFile o $ MaxSAT2NLPB.convert wcnf
+                  (lp, _) = PB2LP.convert pb
+              return lp
+          | otherwise -> do
+              let (lp, _) = MaxSAT2LP.convert (IndicatorConstraint `elem` o) wcnf
+              return lp
+
+transformPBFile :: [Flag] -> PBFile.Formula -> PBFile.Formula
+transformPBFile o opb@(Nothing,_) = PBSetObj.setObj objType opb
+  where
+    objType = last (ObjNone : [t | ObjType t <- o])
+transformPBFile _ opb = opb
 
 writeLP :: [Flag] -> LPFile.LP -> IO ()
 writeLP o lp = do
diff --git a/pbconvert/pbconvert.hs b/pbconvert/pbconvert.hs
new file mode 100644
--- /dev/null
+++ b/pbconvert/pbconvert.hs
@@ -0,0 +1,180 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  pbconvert
+-- Copyright   :  (c) Masahiro Sakai 2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+
+module Main where
+
+import Data.Char
+import qualified Data.Version as V
+import System.Environment
+import System.IO
+import System.Exit
+import System.FilePath
+import System.Console.GetOpt
+import qualified Language.CNF.Parse.ParseDIMACS as DIMACS
+
+import qualified Text.LPFile as LPFile
+import qualified Text.MaxSAT as MaxSAT
+import qualified Text.PBFile as PBFile
+import Converter.ObjType
+import qualified Converter.SAT2PB as SAT2PB
+import qualified Converter.LP2SMT as LP2SMT
+import qualified Converter.MaxSAT2WBO as MaxSAT2WBO
+import qualified Converter.MaxSAT2NLPB as MaxSAT2NLPB
+import qualified Converter.PB2LP as PB2LP
+import qualified Converter.PB2LSP as PB2LSP
+import qualified Converter.PB2WBO as PB2WBO
+import qualified Converter.PBSetObj as PBSetObj
+import qualified Converter.PB2SMP as PB2SMP
+import qualified Converter.WBO2PB as WBO2PB
+import Version
+
+data Flag
+  = Help
+  | Version
+  | Output String
+  | AsMaxSAT
+  | ObjType ObjType
+  | IndicatorConstraint
+  | Optimize
+  | NoCheck
+  | NoProduceModel
+  | MaxSATNonLinear
+  deriving Eq
+
+options :: [OptDescr Flag]
+options =
+    [ Option ['h'] ["help"] (NoArg Help) "show help"
+    , Option ['v'] ["version"] (NoArg Version)         "show version number"
+    , Option ['o'] [] (ReqArg Output "FILE") "output filename"
+    , Option []    ["maxsat"]  (NoArg AsMaxSAT)  "treat *.cnf file as MAX-SAT problem"
+    , Option []    ["obj"] (ReqArg (ObjType . parseObjType) "STRING") "objective function for SAT/PBS: none (default), max-one, max-zero"
+    , Option []    ["indicator"] (NoArg IndicatorConstraint) "use indicator constraints in output LP file"
+    , Option []    ["smt-optimize"] (NoArg Optimize)   "output optimiality condition which uses quantifiers"
+    , Option []    ["smt-no-check"] (NoArg NoCheck)    "do not output \"(check)\""
+    , Option []    ["smt-no-produce-model"] (NoArg NoProduceModel) "do not output \"(set-option :produce-models true)\""    
+    , Option []    ["maxsat-nonlinear"] (NoArg MaxSATNonLinear) "use non-linear formulation of Max-SAT"
+    ]
+  where
+    parseObjType s =
+      case map toLower s of
+        "none"     -> ObjNone
+        "max-one"  -> ObjMaxOne
+        "max-zero" -> ObjMaxZero
+        _          -> error ("unknown obj: " ++ s)
+
+header :: String
+header = unlines
+  [ "Usage:"
+  , "    pbconvert -o <outputfile> <inputfile>"
+  , ""
+  , "Supported formats:"
+  , "    input: .cnf .wcnf .opb .wbo"
+  , "    output: .opb .wbo"
+  , ""
+  , "Options:"
+  ]
+
+readPBFile :: [Flag] -> String -> IO (Either PBFile.Formula PBFile.SoftFormula)
+readPBFile o fname = do
+  case map toLower (takeExtension fname) of
+    ".cnf"
+      | AsMaxSAT `elem` o -> readWCNF
+      | otherwise -> do
+          ret <- DIMACS.parseFile fname
+          case ret of
+            Left err  -> hPrint stderr err >> exitFailure
+            Right cnf -> return $ Left $ SAT2PB.convert cnf
+    ".wcnf" -> readWCNF
+    ".opb"  -> do
+      ret <- PBFile.parseOPBFile fname
+      case ret of
+        Left err -> hPrint stderr err >> exitFailure
+        Right opb -> return $ Left opb
+    ".wbo"  -> do
+      ret <- PBFile.parseWBOFile fname
+      case ret of
+        Left err -> hPrint stderr err >> exitFailure
+        Right wbo -> return $ Right wbo
+    ext ->
+      error $ "unknown file extension: " ++ show ext
+  where
+    readWCNF = do
+      ret <- MaxSAT.parseWCNFFile fname
+      case ret of
+        Left err -> hPutStrLn stderr err >> exitFailure
+        Right wcnf
+          | MaxSATNonLinear `elem` o -> return $ Left $ MaxSAT2NLPB.convert wcnf
+          | otherwise -> return $ Right $ MaxSAT2WBO.convert wcnf
+
+transformPBFile :: [Flag] -> Either PBFile.Formula PBFile.SoftFormula -> Either PBFile.Formula PBFile.SoftFormula
+transformPBFile o pb =
+  case pb of
+    Left opb@(Nothing,_) -> Left $ PBSetObj.setObj objType opb
+    _ -> pb
+  where
+    objType = last (ObjNone : [t | ObjType t <- o])
+
+writePBFile :: [Flag] -> Either PBFile.Formula PBFile.SoftFormula -> IO ()
+writePBFile o pb = do
+  let lp2smtOpt =
+        LP2SMT.defaultOptions
+        { LP2SMT.optCheckSAT     = not (NoCheck `elem` o)
+        , LP2SMT.optProduceModel = not (NoProduceModel `elem` o)
+        , LP2SMT.optOptimize     = Optimize `elem` o
+        }
+  case head ([Just fname | Output fname <- o] ++ [Nothing]) of
+    Nothing -> do
+      case pb of
+        Left opb  -> putStr $ PBFile.showOPB opb ""
+        Right wbo -> putStr $ PBFile.showWBO wbo ""
+    Just fname -> do
+      let opb = case pb of
+                  Left opb  -> opb
+                  Right wbo -> fst $ WBO2PB.convert wbo
+          wbo = case pb of
+                  Left opb  -> PB2WBO.convert opb
+                  Right wbo -> wbo
+          lp  = case pb of
+                  Left opb  -> fst $ PB2LP.convert opb
+                  Right wbo -> fst $ PB2LP.convertWBO (IndicatorConstraint `elem` o) wbo
+      case map toLower (takeExtension fname) of
+        ".opb" -> writeFile fname (PBFile.showOPB opb "")
+        ".wbo" -> writeFile fname (PBFile.showWBO wbo "")
+        ".lsp" -> writeFile fname (PB2LSP.convert opb "")
+        ".lp" -> do
+          case LPFile.render lp of
+            Nothing -> hPutStrLn stderr "conversion failure" >> exitFailure
+            Just s -> writeFile fname s
+        ".smp" -> do
+          writeFile fname (PB2SMP.convert False opb "")
+        ".smt2" -> do
+          writeFile fname (LP2SMT.convert lp2smtOpt lp "")
+        ".ys" -> do
+          writeFile fname (LP2SMT.convert lp2smtOpt{ LP2SMT.optLanguage = LP2SMT.YICES } lp "")
+        ext -> do
+          error $ "unknown file extension: " ++ show ext
+          
+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
+      pb <- readPBFile o fname
+      let pb2 = transformPBFile o pb
+      writePBFile o pb2
+    (_,_,errs) -> do
+      hPutStrLn stderr $ concat errs ++ usageInfo header options
+      exitFailure
diff --git a/samples/gcnf/camus.cnf b/samples/gcnf/camus.cnf
new file mode 100644
--- /dev/null
+++ b/samples/gcnf/camus.cnf
@@ -0,0 +1,11 @@
+c http://sun.iwu.edu/~mliffito/publications/jar_liffiton_CAMUS.pdf
+c￼φ= (x1) ∧ (¬x1) ∧ (¬x1∨x2) ∧ (¬x2) ∧ (¬x1∨x3) ∧ (¬x3)
+c MUSes(φ) = {{C1, C2}, {C1, C3, C4}, {C1, C5, C6}}
+c MCSes(φ) = {{C1}, {C2, C3, C5}, {C2, C3, C6}, {C2, C4, C5}, {C2, C4, C6}}
+p cnf 3 6
+1 0
+-1 0
+-1 2 0
+-2 0
+-1 3 0
+-3 0
diff --git a/samples/gcnf/uuf250-01.gcnf b/samples/gcnf/uuf250-01.gcnf
deleted file mode 100644
--- a/samples/gcnf/uuf250-01.gcnf
+++ /dev/null
@@ -1,1073 +0,0 @@
-c This Formular is generated by mcnf
-c
-c    horn? no 
-c    forced? no 
-c    mixed sat? no 
-c    clause length = 3 
-c
-p gcnf 250 1065 9
-{5}  -128 -209 148 0
-{2} 2 196 -115 0
-{3} -66 -189 -241 0
-{7} -84 -132 -93 0
-{5} 214 179 66 0
-{8} 203 132 -237 0
-{2} 164 -13 -172 0
-{0} -157 198 160 0
-{4} -91 -164 235 0
-{0} -70 -116 54 0
-{3} -164 171 -189 0
-{9} 126 -184 211 0
-{1} -19 118 41 0
-{9} 32 105 -33 0
-{6} -141 -108 50 0
-{3} -1 156 -188 0
-{4} 138 -181 142 0
-{5} -191 -247 -220 0
-{3} -101 -207 -88 0
-{0} 68 114 -234 0
-{3} 134 -57 -131 0
-{4} -30 -133 116 0
-{5} -24 -173 92 0
-{3} 226 -4 -224 0
-{8} -190 204 61 0
-{3} 148 205 -174 0
-{3} 213 -56 53 0
-{2} 174 -250 206 0
-{4} 32 219 -112 0
-{1} 203 -222 202 0
-{8} 130 42 226 0
-{7} 222 33 58 0
-{2} 58 35 34 0
-{4} -121 80 245 0
-{0} -231 38 -248 0
-{7} -205 -179 184 0
-{0} -182 -204 -36 0
-{3} 23 35 -181 0
-{3} 82 -168 -59 0
-{8} 103 132 -182 0
-{4} -243 -18 -160 0
-{0} -180 130 95 0
-{9} 111 -140 -107 0
-{7} 19 28 -72 0
-{8} -222 207 -103 0
-{0} 134 -50 -184 0
-{8} 185 155 -11 0
-{1} -102 230 -18 0
-{1} -112 39 242 0
-{9} 154 -87 53 0
-{5} 173 -123 -159 0
-{9} -238 -101 -40 0
-{7} -126 -232 -139 0
-{1} 107 -51 197 0
-{2} -194 -138 -150 0
-{5} 106 -66 -11 0
-{3} -150 -159 -27 0
-{8} -98 -32 138 0
-{9} 144 -32 128 0
-{4} 153 74 -249 0
-{4} -190 -175 -208 0
-{3} -127 88 -38 0
-{6} -59 125 -225 0
-{6} -23 4 181 0
-{2} 12 247 -133 0
-{1} 151 -238 127 0
-{9} 237 -65 -154 0
-{6} -218 -26 -55 0
-{1} 91 -245 169 0
-{8} -81 -156 10 0
-{3} 166 -66 -45 0
-{9} 109 -162 47 0
-{0} -193 153 40 0
-{1} 162 -186 -7 0
-{1} 93 38 -58 0
-{5} -159 -167 -39 0
-{4} -187 68 124 0
-{6} 247 23 212 0
-{8} 49 182 -243 0
-{2} 206 -105 -237 0
-{3} 236 116 154 0
-{5} 236 -6 182 0
-{8} -168 236 35 0
-{0} -186 70 -236 0
-{0} 127 80 103 0
-{4} 100 79 -176 0
-{1} 117 -88 -1 0
-{9} 60 -115 -224 0
-{2} -148 181 -65 0
-{2} -132 235 19 0
-{4} -44 -197 190 0
-{4} -214 67 129 0
-{9} -203 175 -191 0
-{9} -172 166 -115 0
-{8} -176 -180 207 0
-{1} -56 -208 -1 0
-{4} -37 140 -19 0
-{6} -242 -55 58 0
-{7} -116 -153 241 0
-{2} -203 64 -219 0
-{1} -214 64 90 0
-{7} -166 96 155 0
-{8} 68 -2 63 0
-{1} -200 49 196 0
-{0} -230 -232 -148 0
-{8} -81 105 219 0
-{2} 187 -236 -123 0
-{8} -99 237 136 0
-{6} -205 61 -118 0
-{2} -235 -230 128 0
-{9} 38 -9 -124 0
-{9} -34 -116 179 0
-{3} -40 -55 -85 0
-{2} 244 170 6 0
-{4} -7 -54 -236 0
-{6} 153 -223 173 0
-{8} -219 -13 -217 0
-{8} 244 -210 -228 0
-{5} 23 -128 -113 0
-{4} 35 -245 -235 0
-{5} 184 31 143 0
-{2} -207 -24 135 0
-{3} 97 -165 -14 0
-{4} -17 15 26 0
-{2} 61 78 -8 0
-{3} 215 -30 -166 0
-{5} 229 93 -246 0
-{1} -167 -113 80 0
-{5} 78 205 -87 0
-{5} 117 -144 207 0
-{5} -10 153 -84 0
-{7} -147 238 61 0
-{7} -58 -17 -190 0
-{3} 209 -25 -81 0
-{4} -175 244 -57 0
-{1} 185 127 -147 0
-{2} 237 199 -144 0
-{8} 124 148 -10 0
-{7} 190 244 231 0
-{1} -185 214 -101 0
-{7} -237 31 -94 0
-{8} -39 36 -94 0
-{5} -175 206 81 0
-{8} 141 -209 -109 0
-{3} 228 -165 -112 0
-{8} -45 142 238 0
-{3} -34 -64 -71 0
-{1} -60 170 -109 0
-{7} 6 245 87 0
-{5} 12 -93 -231 0
-{8} 80 216 28 0
-{5} -103 137 116 0
-{3} -77 -73 -30 0
-{7} -63 219 -129 0
-{4} -215 -94 86 0
-{3} 81 46 221 0
-{1} 161 -215 -212 0
-{3} -137 -215 48 0
-{4} -50 211 229 0
-{8} 172 74 154 0
-{0} -14 -100 166 0
-{2} 59 -119 -243 0
-{0} 244 -31 -96 0
-{2} 51 -247 205 0
-{9} -90 97 -139 0
-{6} 113 118 -7 0
-{3} 57 -161 -84 0
-{6} 180 -174 -9 0
-{6} -19 16 -202 0
-{1} -39 -134 224 0
-{2} 84 240 195 0
-{7} -55 75 -207 0
-{6} 116 54 60 0
-{0} 80 98 40 0
-{4} -159 109 217 0
-{3} -210 -119 82 0
-{1} -201 -14 174 0
-{6} 43 -19 -100 0
-{1} -126 223 26 0
-{8} -249 163 -205 0
-{9} -58 -4 109 0
-{8} -239 109 -82 0
-{9} 210 -58 -2 0
-{5} 238 -36 117 0
-{1} 109 -199 32 0
-{3} -54 221 -80 0
-{4} 230 99 97 0
-{8} 45 221 169 0
-{9} 191 17 114 0
-{0} -177 -138 -12 0
-{3} 35 -5 145 0
-{3} -102 -147 103 0
-{5} -59 3 84 0
-{7} -56 240 -130 0
-{8} -233 -223 -47 0
-{9} 169 216 -3 0
-{4} -68 -182 67 0
-{3} 34 -189 27 0
-{7} 230 -222 66 0
-{1} 19 123 84 0
-{7} 64 35 231 0
-{5} 236 165 242 0
-{4} 77 -119 -61 0
-{9} -179 215 198 0
-{1} -105 -93 211 0
-{4} -204 221 -112 0
-{3} -244 23 -125 0
-{1} -107 152 78 0
-{1} 144 -183 28 0
-{3} -179 -32 194 0
-{2} 217 174 72 0
-{5} -38 101 -132 0
-{4} -122 193 108 0
-{0} 12 3 -44 0
-{6} 140 -23 -2 0
-{0} 185 -129 145 0
-{5} -116 -245 -102 0
-{0} 203 -29 -131 0
-{7} -172 239 243 0
-{0} -186 -167 109 0
-{9} 158 -184 149 0
-{5} -53 56 100 0
-{6} -92 5 35 0
-{2} -212 -236 250 0
-{4} -42 137 -193 0
-{5} 171 231 127 0
-{5} 176 -85 -122 0
-{5} 32 81 -178 0
-{9} 78 -14 -227 0
-{7} 104 -10 -65 0
-{5} 239 -81 -118 0
-{1} 182 76 -235 0
-{5} -226 -132 54 0
-{8} 145 25 120 0
-{0} 49 205 99 0
-{7} 250 240 -89 0
-{1} 17 37 -65 0
-{9} 226 -66 -47 0
-{6} 136 -112 19 0
-{6} -94 -32 74 0
-{1} 200 144 -65 0
-{9} 27 29 207 0
-{5} 6 112 53 0
-{1} -170 -192 -65 0
-{9} -18 206 8 0
-{8} -158 245 147 0
-{0} 222 34 24 0
-{1} 69 182 -121 0
-{9} -22 -202 -232 0
-{0} -213 -82 173 0
-{6} 78 -176 -151 0
-{7} 245 215 242 0
-{2} -126 -96 243 0
-{6} -164 -220 205 0
-{1} -60 128 162 0
-{0} -237 -126 -20 0
-{1} 105 -144 -165 0
-{0} -158 76 -38 0
-{3} 153 -236 206 0
-{3} 187 -191 247 0
-{5} -192 159 171 0
-{7} 162 -151 -213 0
-{8} 19 155 238 0
-{4} -43 207 -46 0
-{5} 117 250 118 0
-{1} 159 40 -199 0
-{6} 149 -163 -145 0
-{8} 23 7 46 0
-{9} 71 106 56 0
-{0} -43 220 -118 0
-{0} -200 242 6 0
-{6} 143 219 -168 0
-{7} -179 102 -163 0
-{8} -74 183 -82 0
-{1} 248 92 -154 0
-{2} 81 202 229 0
-{1} 92 243 19 0
-{0} 165 -210 199 0
-{3} -54 -8 244 0
-{4} -70 -135 -223 0
-{7} -80 -89 -189 0
-{0} -7 182 -16 0
-{9} 172 53 8 0
-{0} 114 -107 197 0
-{4} -135 -35 -239 0
-{9} -214 -10 137 0
-{7} 136 -131 151 0
-{5} 15 -37 -89 0
-{5} -234 -7 97 0
-{1} 118 191 101 0
-{2} 215 123 185 0
-{2} -230 202 -190 0
-{3} 211 -59 210 0
-{5} 200 -162 116 0
-{1} 158 12 212 0
-{2} -56 229 196 0
-{9} -50 -52 218 0
-{4} 164 -142 -71 0
-{3} 233 -140 159 0
-{3} 119 93 65 0
-{3} 155 -156 -57 0
-{1} 117 -197 180 0
-{1} -97 -100 -2 0
-{3} 165 206 83 0
-{6} -127 173 -110 0
-{0} 20 158 116 0
-{7} -205 -125 -209 0
-{7} -244 -57 -246 0
-{2} -139 -173 21 0
-{9} 89 -150 149 0
-{3} -51 60 -224 0
-{4} -81 -193 195 0
-{2} -208 -209 83 0
-{9} -141 70 -223 0
-{8} 200 -121 99 0
-{6} -207 201 -61 0
-{3} 167 157 -71 0
-{7} 200 78 182 0
-{2} 82 171 -183 0
-{3} 4 -33 -85 0
-{1} -103 87 186 0
-{3} 41 183 169 0
-{0} 84 244 -116 0
-{3} 128 -108 -67 0
-{9} 24 165 181 0
-{6} 94 118 -148 0
-{3} -41 -71 -98 0
-{8} 248 15 -135 0
-{3} 10 -157 -17 0
-{4} -225 241 93 0
-{4} 217 -192 227 0
-{9} 28 -11 78 0
-{5} -16 218 24 0
-{7} 59 -91 -210 0
-{8} 4 141 166 0
-{3} -204 12 -206 0
-{4} 187 153 -186 0
-{1} 23 -43 -124 0
-{8} 100 2 -46 0
-{1} -236 -80 -102 0
-{6} 165 129 159 0
-{5} -45 245 -187 0
-{6} 137 31 -7 0
-{0} 214 -178 200 0
-{4} 222 107 -74 0
-{2} -37 -161 -129 0
-{3} -202 -214 99 0
-{0} 69 3 78 0
-{0} -7 -217 51 0
-{4} 215 -99 96 0
-{5} 124 41 195 0
-{6} -233 -223 206 0
-{1} 233 197 87 0
-{6} -102 33 70 0
-{2} 175 241 162 0
-{1} 86 -202 83 0
-{8} 137 -214 64 0
-{0} -111 -204 197 0
-{8} -23 12 -121 0
-{2} 101 28 -95 0
-{8} -206 57 220 0
-{2} -122 -2 -125 0
-{6} 75 -241 86 0
-{1} -72 185 77 0
-{5} -125 210 -143 0
-{6} 106 36 54 0
-{0} 136 142 -93 0
-{8} -142 -180 214 0
-{4} 44 -22 -60 0
-{0} -235 88 -130 0
-{9} -124 -162 245 0
-{2} 19 -121 156 0
-{2} 84 -23 -191 0
-{7} -173 -43 -163 0
-{3} 151 148 213 0
-{1} -239 147 -180 0
-{4} -247 -92 -36 0
-{9} 163 37 -188 0
-{7} -245 -7 -231 0
-{3} -32 -139 41 0
-{9} -13 -157 211 0
-{6} -107 136 126 0
-{0} -58 201 -115 0
-{2} -184 -48 -205 0
-{7} 57 -237 -80 0
-{9} 160 -243 155 0
-{9} 154 -42 -179 0
-{2} -107 -242 -167 0
-{0} 169 170 -19 0
-{3} -65 -140 -209 0
-{1} 143 146 182 0
-{1} 90 -170 158 0
-{2} -235 54 83 0
-{3} -122 193 239 0
-{8} 112 130 -212 0
-{8} -9 -167 93 0
-{4} -57 54 -28 0
-{2} -55 -56 29 0
-{9} -206 -79 245 0
-{5} -16 -81 -190 0
-{5} 174 160 131 0
-{4} -125 156 -148 0
-{5} -128 174 -25 0
-{8} -209 -16 60 0
-{3} -13 -225 109 0
-{4} 167 -124 168 0
-{7} 142 -16 173 0
-{3} 8 -45 216 0
-{5} 13 160 -41 0
-{6} -101 125 -225 0
-{3} -218 244 -49 0
-{3} 153 -183 204 0
-{4} 117 230 167 0
-{7} -108 24 -27 0
-{7} 149 -198 13 0
-{0} 48 124 -84 0
-{6} -35 -162 58 0
-{2} 110 -103 9 0
-{9} -143 -43 169 0
-{1} -91 -87 -70 0
-{2} 11 -117 244 0
-{6} -141 37 -177 0
-{1} 238 126 -215 0
-{3} 157 103 -27 0
-{3} -133 134 -3 0
-{1} 112 -107 -113 0
-{3} -225 -104 26 0
-{1} 109 -220 -174 0
-{6} 58 -140 -86 0
-{5} 1 97 14 0
-{9} 249 161 -217 0
-{9} 99 -242 33 0
-{3} 172 2 -235 0
-{7} -79 -132 107 0
-{4} 43 -217 -169 0
-{5} -166 218 -128 0
-{8} 63 178 135 0
-{6} 110 224 30 0
-{5} -62 147 -237 0
-{4} -241 -103 -169 0
-{3} 125 -75 -106 0
-{4} 146 20 -112 0
-{2} 59 226 -136 0
-{5} -194 132 -101 0
-{9} 133 -41 -14 0
-{1} 190 74 -247 0
-{8} 230 221 224 0
-{4} -3 -61 -65 0
-{1} 93 15 194 0
-{5} -155 105 117 0
-{0} -146 -127 -35 0
-{3} 170 -173 213 0
-{8} -13 -234 -117 0
-{6} -244 -225 15 0
-{9} -41 151 -185 0
-{6} -196 -2 114 0
-{8} -220 111 -238 0
-{2} 234 134 146 0
-{3} 100 -29 -4 0
-{9} -195 -6 151 0
-{1} -116 109 -9 0
-{7} 45 -58 -61 0
-{4} 195 224 66 0
-{3} 119 174 129 0
-{2} 122 233 100 0
-{0} 30 -227 -120 0
-{1} 238 1 16 0
-{9} 231 229 -46 0
-{7} 188 226 23 0
-{7} -181 247 -216 0
-{9} 233 84 97 0
-{4} 8 41 71 0
-{2} 37 52 56 0
-{0} -227 58 84 0
-{6} 116 48 -95 0
-{4} -58 233 36 0
-{4} 210 11 -116 0
-{8} -107 -103 242 0
-{8} 21 -161 169 0
-{3} 202 25 82 0
-{9} 248 163 65 0
-{7} -108 26 -78 0
-{6} -162 163 -248 0
-{2} -14 -95 92 0
-{2} 218 -151 -26 0
-{1} -132 -195 44 0
-{4} 14 85 -136 0
-{7} -236 219 -105 0
-{8} 164 136 -25 0
-{7} 7 36 124 0
-{2} -163 -216 -15 0
-{7} -66 176 -76 0
-{8} -144 -3 -101 0
-{6} -178 -149 -108 0
-{6} 175 -161 210 0
-{3} -118 106 -11 0
-{8} -124 128 98 0
-{1} -81 -223 117 0
-{9} 154 149 -1 0
-{1} -186 26 66 0
-{4} -190 192 -114 0
-{7} -122 -197 -52 0
-{2} -84 -226 105 0
-{4} 52 61 225 0
-{4} 206 -7 -101 0
-{2} -29 93 -116 0
-{0} 67 -164 135 0
-{8} 1 -217 -5 0
-{0} -180 218 222 0
-{1} 230 -225 -50 0
-{0} 4 -25 45 0
-{8} -57 234 -1 0
-{5} -221 -103 100 0
-{9} 137 234 -109 0
-{8} 20 -227 -202 0
-{3} -103 -247 198 0
-{5} -29 -148 -35 0
-{7} -191 102 18 0
-{6} -52 -195 18 0
-{6} 61 5 -247 0
-{7} 165 -207 -217 0
-{4} -147 -207 27 0
-{5} 100 117 -129 0
-{5} -152 -83 132 0
-{0} -190 53 -121 0
-{2} 156 230 181 0
-{5} 2 -239 -65 0
-{5} -55 -20 -107 0
-{1} -119 -39 -221 0
-{7} -116 147 16 0
-{3} -211 238 -60 0
-{7} 249 -111 141 0
-{2} -54 -193 -81 0
-{2} 49 -245 -5 0
-{8} -233 110 -109 0
-{6} -79 -56 180 0
-{7} -41 196 150 0
-{5} 242 -63 231 0
-{8} 39 22 100 0
-{1} 5 23 204 0
-{2} -55 -100 105 0
-{1} -22 -28 247 0
-{1} -209 200 67 0
-{7} -46 59 62 0
-{5} -239 -107 -125 0
-{5} 242 25 -246 0
-{2} -148 -30 -11 0
-{4} -148 160 -169 0
-{7} 5 145 249 0
-{9} 168 -28 -207 0
-{5} -188 212 -201 0
-{0} -166 205 -239 0
-{3} 145 -246 -100 0
-{3} 3 215 -93 0
-{5} 101 -198 -160 0
-{9} -233 178 -90 0
-{0} -143 -26 -102 0
-{0} -72 -97 -195 0
-{1} -119 -163 -120 0
-{2} 93 13 98 0
-{2} -131 -53 15 0
-{9} -118 129 151 0
-{6} 168 81 199 0
-{7} -17 121 -21 0
-{5} -36 -175 196 0
-{4} -221 57 68 0
-{6} 111 145 -183 0
-{3} 114 -31 24 0
-{4} -170 159 -146 0
-{7} 123 -80 152 0
-{1} -84 -184 -134 0
-{0} -206 30 -55 0
-{8} 81 -154 198 0
-{0} 129 135 248 0
-{4} -2 198 122 0
-{0} 230 101 -18 0
-{4} 25 208 216 0
-{1} -247 176 160 0
-{2} 34 -159 9 0
-{1} -74 184 31 0
-{8} 29 -66 -148 0
-{9} -233 204 -107 0
-{9} 204 -30 -127 0
-{8} -237 8 -65 0
-{7} 79 112 181 0
-{3} 157 -85 83 0
-{1} 204 113 -216 0
-{7} -11 -15 27 0
-{3} 44 114 8 0
-{5} 105 188 -158 0
-{2} -51 204 -48 0
-{7} 145 211 40 0
-{4} -107 -31 -114 0
-{2} -134 212 -105 0
-{1} 188 -174 -151 0
-{4} 58 -9 -151 0
-{5} 33 -37 -119 0
-{4} 172 -3 169 0
-{7} -26 -21 48 0
-{1} -94 -99 -41 0
-{9} 192 1 -7 0
-{6} 250 -138 185 0
-{9} -6 -131 -83 0
-{8} 11 191 -240 0
-{2} -175 -163 -249 0
-{1} -214 -98 193 0
-{9} 120 190 -185 0
-{4} -135 -64 -24 0
-{8} -187 249 -129 0
-{9} 76 -232 112 0
-{3} -17 -161 117 0
-{8} -6 250 246 0
-{5} 85 -188 117 0
-{7} -47 91 -103 0
-{3} -123 -92 142 0
-{1} 3 -183 -249 0
-{2} -175 148 -129 0
-{3} 223 172 119 0
-{9} 194 76 -114 0
-{3} 206 123 -222 0
-{0} -186 -110 -71 0
-{3} -63 152 -110 0
-{5} -122 -44 -119 0
-{3} -14 76 -224 0
-{9} -8 -77 -97 0
-{0} -116 110 63 0
-{9} 148 106 192 0
-{1} 204 -168 -56 0
-{9} -221 173 -13 0
-{4} 168 57 -211 0
-{8} 218 151 245 0
-{3} 70 -234 -143 0
-{1} 24 194 106 0
-{3} 16 -236 -187 0
-{4} 162 97 43 0
-{7} 8 79 228 0
-{9} -39 -179 48 0
-{0} -119 213 -231 0
-{5} -239 57 -232 0
-{0} -161 247 8 0
-{4} 30 -127 197 0
-{7} 72 168 -233 0
-{5} -157 -217 -135 0
-{0} 134 180 233 0
-{9} 27 -14 -64 0
-{9} 153 247 -60 0
-{7} -154 -76 -106 0
-{4} -59 -100 170 0
-{6} 120 -121 -41 0
-{6} -169 13 158 0
-{9} -166 199 120 0
-{4} 164 202 -199 0
-{3} -223 148 -242 0
-{4} 4 211 100 0
-{3} 188 -231 -98 0
-{7} 218 129 -93 0
-{8} -211 18 -93 0
-{2} 51 -10 -78 0
-{1} 22 -155 -130 0
-{7} 207 -135 -172 0
-{7} 199 197 14 0
-{9} 182 -245 -135 0
-{1} -204 181 -32 0
-{2} -18 -237 80 0
-{4} -96 69 193 0
-{1} -98 245 -91 0
-{5} 71 -24 93 0
-{9} 48 -131 194 0
-{8} 29 144 -12 0
-{6} 128 15 -71 0
-{8} 125 58 -238 0
-{7} -84 111 38 0
-{9} 224 168 246 0
-{7} -82 -188 -33 0
-{0} -67 98 242 0
-{8} 34 248 -112 0
-{0} 217 95 59 0
-{4} 56 245 13 0
-{6} 72 129 -245 0
-{2} 82 134 -61 0
-{4} -128 55 -183 0
-{0} -187 42 38 0
-{0} 90 -102 54 0
-{2} -159 224 229 0
-{4} -117 -158 -180 0
-{3} 113 108 5 0
-{6} 239 34 -122 0
-{5} -85 -118 -19 0
-{9} -240 129 -145 0
-{4} -15 149 129 0
-{1} -144 -189 217 0
-{3} 228 -223 97 0
-{7} 16 -84 -242 0
-{0} 206 -212 91 0
-{9} -71 -194 21 0
-{5} 59 -31 37 0
-{6} -89 156 -243 0
-{0} 60 21 75 0
-{2} 14 12 -8 0
-{5} -227 -183 131 0
-{4} -95 -190 -49 0
-{2} -151 -54 -133 0
-{6} -134 49 -157 0
-{4} 6 -114 224 0
-{0} 201 -195 -17 0
-{5} -99 -36 88 0
-{7} 123 -67 105 0
-{7} 142 -94 49 0
-{8} 58 106 234 0
-{3} 22 -18 -86 0
-{2} 201 -245 71 0
-{4} -220 -228 227 0
-{8} -117 31 -212 0
-{9} -177 -140 -59 0
-{2} 229 233 150 0
-{3} 47 -36 103 0
-{4} -239 102 -241 0
-{6} -35 194 208 0
-{9} 199 -37 -180 0
-{9} 140 -176 -123 0
-{6} 148 -36 243 0
-{2} 14 141 227 0
-{1} -182 -141 248 0
-{7} 178 85 144 0
-{5} 247 231 15 0
-{4} 77 -168 -40 0
-{4} -194 -181 -83 0
-{6} -225 116 -79 0
-{4} -80 182 -50 0
-{1} 63 -36 -122 0
-{9} 82 231 -59 0
-{3} -64 -244 157 0
-{9} -86 140 -207 0
-{5} -129 -192 -143 0
-{9} -69 227 216 0
-{6} -83 137 -101 0
-{3} 117 -71 145 0
-{4} 115 -53 199 0
-{5} -32 96 -1 0
-{9} 104 93 -142 0
-{7} 190 116 83 0
-{3} 191 -124 -161 0
-{4} 144 11 -181 0
-{0} -151 113 243 0
-{3} -66 -141 -108 0
-{1} -153 -149 7 0
-{9} -75 -129 137 0
-{1} 113 -107 43 0
-{1} -191 99 237 0
-{8} 199 67 163 0
-{2} -198 -177 -21 0
-{8} 217 -236 88 0
-{2} -136 -84 158 0
-{7} 52 68 -204 0
-{7} -61 200 21 0
-{4} 95 -204 -221 0
-{0} -75 -125 118 0
-{3} 213 113 173 0
-{8} -226 -92 118 0
-{3} -134 -189 67 0
-{3} -198 7 -26 0
-{4} -49 197 57 0
-{1} -5 -72 -146 0
-{0} 226 167 -27 0
-{5} 211 -229 94 0
-{6} -101 -80 -12 0
-{6} 58 -47 -80 0
-{5} 148 -217 -9 0
-{8} 229 -120 -117 0
-{3} 161 -174 191 0
-{8} 10 -51 -154 0
-{6} -155 235 -198 0
-{4} -171 247 127 0
-{9} -130 19 140 0
-{0} -209 -185 -25 0
-{2} -223 -199 -27 0
-{3} -28 124 187 0
-{3} 135 -28 31 0
-{2} -31 88 89 0
-{6} 22 -43 -47 0
-{9} 21 165 -184 0
-{5} -250 69 -27 0
-{4} 221 -177 162 0
-{3} -72 -218 207 0
-{4} 23 -159 83 0
-{3} -54 225 -190 0
-{6} -140 -21 49 0
-{4} -50 -177 -18 0
-{8} 80 -250 172 0
-{2} -77 183 -218 0
-{5} 184 55 -146 0
-{0} -104 181 -188 0
-{2} 243 146 -70 0
-{3} -215 -187 -247 0
-{3} -196 -50 90 0
-{0} -84 143 -146 0
-{4} 147 119 -118 0
-{0} 227 14 -110 0
-{2} 44 238 -153 0
-{6} 197 -69 -176 0
-{4} 127 65 27 0
-{4} 208 190 -162 0
-{1} -39 250 -196 0
-{5} 114 -89 206 0
-{3} 142 75 -148 0
-{0} -202 237 -194 0
-{7} -21 216 -177 0
-{8} 114 -80 -200 0
-{4} -27 91 -84 0
-{1} -63 249 -36 0
-{0} 89 -18 -133 0
-{4} -19 -17 -107 0
-{8} 145 62 -227 0
-{2} -89 -148 -44 0
-{7} -133 -192 -149 0
-{6} -65 240 -233 0
-{4} -88 -40 -245 0
-{1} 92 -129 4 0
-{9} 22 -62 -21 0
-{0} 216 116 -93 0
-{0} 79 100 234 0
-{2} 39 134 44 0
-{1} -226 -170 -157 0
-{1} 104 9 -191 0
-{8} 26 -39 40 0
-{8} 113 232 -174 0
-{6} -101 81 -104 0
-{7} 173 90 101 0
-{0} -208 173 -97 0
-{7} -72 209 -111 0
-{2} -51 -93 108 0
-{2} -248 216 181 0
-{0} -65 -170 212 0
-{7} -102 -161 146 0
-{3} -72 -28 -25 0
-{9} -117 -18 229 0
-{7} -52 163 -79 0
-{8} 94 120 79 0
-{2} 105 116 -227 0
-{4} 67 186 -211 0
-{1} -226 -235 196 0
-{8} -67 -11 23 0
-{6} -55 -85 -197 0
-{9} -200 -245 -76 0
-{6} 109 -61 -127 0
-{2} -248 127 -229 0
-{5} 53 148 -197 0
-{9} 151 -98 -24 0
-{0} -58 180 -158 0
-{0} 74 214 -200 0
-{7} -31 241 172 0
-{4} 26 219 -56 0
-{3} 1 110 -18 0
-{2} 156 19 -89 0
-{9} 112 87 204 0
-{2} -5 151 -59 0
-{6} 34 -149 100 0
-{4} 83 248 220 0
-{6} 31 2 -78 0
-{5} 110 -152 -37 0
-{7} -132 -217 -57 0
-{1} -71 176 79 0
-{0} 31 -98 -75 0
-{4} -60 229 -171 0
-{0} 87 207 112 0
-{1} 30 151 -41 0
-{2} 17 162 109 0
-{6} -172 111 -221 0
-{7} 166 170 -147 0
-{0} -48 143 -201 0
-{6} 233 -46 -122 0
-{2} 207 -149 -124 0
-{3} -188 -166 -65 0
-{3} -76 -77 -96 0
-{0} -216 211 45 0
-{4} 137 -103 -106 0
-{8} 220 -82 -136 0
-{3} 47 -84 -44 0
-{1} -37 67 -32 0
-{1} 33 -5 156 0
-{0} -137 58 127 0
-{0} 229 -36 -84 0
-{5} 243 175 63 0
-{5} 242 -73 -121 0
-{0} 219 237 164 0
-{0} 149 -201 -142 0
-{0} 27 172 243 0
-{9} -90 29 45 0
-{5} 206 57 153 0
-{9} -235 -49 -94 0
-{8} 233 71 108 0
-{9} 82 -122 223 0
-{1} -195 -71 37 0
-{0} -70 179 -159 0
-{6} -79 -240 -38 0
-{7} -79 -121 30 0
-{3} -238 -78 -246 0
-{6} 218 96 48 0
-{8} 107 -154 -199 0
-{8} 4 -205 194 0
-{8} 1 -205 -203 0
-{9} -155 129 -26 0
-{0} -128 57 22 0
-{9} -195 -168 -10 0
-{1} 97 -186 -90 0
-{8} 122 227 171 0
-{6} 22 163 191 0
-{7} -223 191 -85 0
-{0} 100 -59 -63 0
-{3} 245 49 -181 0
-{7} -51 210 -135 0
-{3} -34 55 54 0
-{0} 2 74 -57 0
-{5} 233 168 -230 0
-{9} -40 22 230 0
-{4} 128 -157 27 0
-{8} -154 -161 -114 0
-{0} -74 -136 38 0
-{7} 51 -205 23 0
-{8} -212 40 -71 0
-{2} 9 -138 -83 0
-{6} -95 54 121 0
-{3} -174 -85 140 0
-{0} 66 16 67 0
-{8} -137 -8 105 0
-{7} -133 -206 -3 0
-{3} 175 86 -206 0
-{6} -50 -217 51 0
-{0} 51 244 31 0
-{0} 184 -218 84 0
-{1} -153 58 -237 0
-{3} 56 -198 63 0
-{9} 228 -42 74 0
-{9} 43 -32 245 0
-{3} -150 82 -44 0
-{5} -14 -22 25 0
-{7} 228 -232 -245 0
-{5} -147 -221 29 0
-{7} -222 41 -40 0
-{7} 42 -13 -20 0
-{4} 53 9 161 0
-{6} 125 236 69 0
-{7} -105 -172 32 0
-{5} -142 114 -71 0
-{2} -120 -122 -197 0
-{4} -29 9 -200 0
-{7} 26 210 -193 0
-{5} -155 183 140 0
-{9} 216 -208 -146 0
-{0} -220 -8 98 0
-{9} 109 175 -63 0
-{8} -16 -139 -108 0
-{4} 176 137 -119 0
-{2} -97 39 142 0
-{2} 218 -44 -37 0
-{5} -119 -69 -107 0
-{7} -79 142 109 0
-{3} -123 25 227 0
-{2} 177 -187 -89 0
-{7} -99 -147 -207 0
-{1} -68 81 236 0
-{3} 145 90 3 0
-{1} 93 -149 -127 0
-{0} -120 -67 154 0
-{0} 121 234 -229 0
-{3} -245 186 21 0
-{6} 92 5 -121 0
-{9} 197 -100 -46 0
-{8} -40 -39 -3 0
-{9} 25 -117 -121 0
-{2} -194 -189 175 0
-{3} 246 10 40 0
-{9} 13 50 147 0
-{8} -243 163 105 0
-{6} 132 -131 -218 0
-{5} -241 78 101 0
-{1} -200 -38 -29 0
-{6} -36 -166 183 0
-{8} 248 -216 218 0
-{1} -203 92 204 0
-{9} -83 -84 -165 0
-{4} -202 -197 -244 0
-{7} 112 -221 63 0
-{9} 100 151 -1 0
-{9} 141 -206 -52 0
-{5} 181 -208 -229 0
-{9} 53 93 173 0
-{4} 193 -184 -79 0
-{2} 41 -78 -133 0
-{2} 1 -35 -90 0
-{8} -198 -60 174 0
-{1} 152 207 -157 0
-{8} 183 -196 -163 0
-{8} -244 242 218 0
-{8} 11 32 146 0
-{7} -66 -32 -84 0
-{1} -54 -109 -195 0
-{3} 190 -116 144 0
-{2} -242 -122 86 0
-{3} -71 7 -150 0
-{2} 241 -173 -15 0
-{7} 62 -217 81 0
-{2} 205 -116 130 0
-{7} 193 -209 128 0
-{8} 146 -240 -132 0
-{9} 29 197 161 0
-{9} 15 83 -39 0
-{8} -109 -44 81 0
-{5} 244 85 -7 0
-{9} -246 9 165 0
-{1} 115 -83 67 0
-{1} -98 -141 170 0
-{4} -102 94 -52 0
-{5} -231 -74 -28 0
-{4} 162 191 -149 0
-{9} 197 -183 -35 0
-{4} 102 -56 50 0
-{7} 30 -45 -129 0
-{0} 25 -207 -33 0
-{1} 192 -106 -169 0
-{0} 43 -129 -169 0
-{8} 237 244 182 0
-{4} -72 -44 -168 0
-{5} -158 -150 102 0
-{9} 168 -143 151 0
-{5} -72 26 212 0
-{5} 116 -89 98 0
-{9} 171 -197 156 0
-{4} 233 -54 -181 0
-{5} 129 -161 25 0
-{3} 113 69 -33 0
-{9} 179 -175 224 0
-{3} 138 -143 -46 0
-{6} 75 213 -246 0
-{1} -137 -175 -150 0
-{3} -169 -67 215 0
-{1} 86 69 -199 0
-{3} -159 233 63 0
-{5} -145 101 6 0
-{5} 129 -243 -227 0
-{7} -175 72 -247 0
-{7} 163 -109 207 0
-{4} 31 77 33 0
-{4} -136 175 160 0
-{7} -192 -193 -7 0
-{7} 99 145 232 0
-{9} -233 198 114 0
-{1} 240 -89 -108 0
-{2} -81 -67 -63 0
-{7} 5 149 69 0
-{1} -172 166 -184 0
-{2} 158 -244 -166 0
-{1} -53 -172 -62 0
-{9} 49 25 61 0
-{5} 237 19 -166 0
-{7} 94 202 -148 0
-{9} -246 13 152 0
-{3} -135 -86 -5 0
-{6} -190 -44 -223 0
-{9} -17 -141 6 0
-{2} 165 39 237 0
-{6} 221 -62 -104 0
-{5} -206 107 -223 0
-{9} -159 -243 -13 0
-{8} 118 -9 57 0
diff --git a/samples/gcnf/uuf50-01.gcnf b/samples/gcnf/uuf50-01.gcnf
deleted file mode 100644
--- a/samples/gcnf/uuf50-01.gcnf
+++ /dev/null
@@ -1,226 +0,0 @@
-c This Formular is generated by mcnf
-c
-c    horn? no 
-c    forced? no 
-c    mixed sat? no 
-c    clause length = 3 
-c
-p gcnf 50  218 10
-{1}  18 -8 29 0
-{1} -16 3 18 0
-{1} -36 -11 -30 0
-{1} -50 20 32 0
-{1} -6 9 35 0
-{1} 42 -38 29 0
-{1} 43 -15 10 0
-{1} -48 -47 1 0
-{1} -45 -16 33 0
-{1} 38 42 22 0
-{1} -49 41 -34 0
-{1} 12 17 35 0
-{2} 22 -49 7 0
-{2} -10 -11 -39 0
-{2} -28 -36 -37 0
-{2} -13 -46 -41 0
-{2} 21 -4 9 0
-{2} 12 48 10 0
-{2} 24 23 15 0
-{2} -8 -41 -43 0
-{2} -44 -2 -35 0
-{2} -27 18 31 0
-{2} 47 35 6 0
-{3} -11 -27 41 0
-{3} -33 -47 -45 0
-{3} -16 36 -37 0
-{3} 27 -46 2 0
-{3} 15 -28 10 0
-{3} -38 46 -39 0
-{3} -33 -4 24 0
-{3} -12 -45 50 0
-{3} -32 -21 -15 0
-{3} 8 42 24 0
-{4} 30 -49 4 0
-{4} 45 -9 28 0
-{4} -33 -47 -1 0
-{4} 1 27 -16 0
-{4} -11 -17 -35 0
-{4} -42 -15 45 0
-{4} -19 -27 30 0
-{4} 3 28 12 0
-{4} 48 -11 -33 0
-{4} -6 37 -9 0
-{5} -37 13 -7 0
-{5} -2 26 16 0
-{5} 46 -24 -38 0
-{5} -13 -24 -8 0
-{5} -36 -42 -21 0
-{5} -37 -19 3 0
-{5} -31 -50 35 0
-{5} -7 -26 29 0
-{5} -42 -45 29 0
-{5} 33 25 -6 0
-{6} -45 -5 7 0
-{6} -7 28 -6 0
-{6} -48 31 -11 0
-{6} 32 16 -37 0
-{6} -24 48 1 0
-{6} 18 -46 23 0
-{6} -30 -50 48 0
-{6} -21 39 -2 0
-{6} 24 47 42 0
-{6} -36 30 4 0
-{7} -5 28 -1 0
-{7} -47 32 -42 0
-{7} 16 37 -22 0
-{7} -43 42 -34 0
-{7} -40 39 -20 0
-{7} -49 29 6 0
-{7} -41 -3 39 0
-{7} -16 -12 43 0
-{7} 24 22 3 0
-{7} 47 -45 43 0
-{8} 45 -37 46 0
-{8} -9 26 5 0
-{8} -3 23 -13 0
-{8} 5 -34 13 0
-{8} 12 39 13 0
-{8} 22 50 37 0
-{8} 19 9 46 0
-{8} -24 8 -27 0
-{8} -28 7 21 0
-{8} 8 -25 50 0
-{9} 20 50 4 0
-{9} 27 36 13 0
-{9} 26 31 -25 0
-{9} 39 -44 -32 0
-{9} -20 41 -10 0
-{9} 49 -28 35 0
-{9} 1 44 34 0
-{9} 39 35 -11 0
-{9} -50 -42 -7 0
-{9} -24 7 47 0
-{10} -13 5 -48 0
-{10} -9 -20 -23 0
-{10} 2 17 -19 0
-{10} 11 23 21 0
-{10} -45 30 15 0
-{10} 11 26 -24 0
-{10} 38 33 -13 0
-{10} 44 -27 -7 0
-{10} 41 49 2 0
-{10} -18 12 -37 0
-{10} -2 12 -26 0
-{10} -19 7 32 0
-{10} -22 11 33 0
-{10} 8 12 -20 0
-{10} 16 40 -48 0
-{10} -2 -24 -11 0
-{10} 26 -17 37 0
-{10} -14 -19 46 0
-{10} 5 47 36 0
-{10} -29 -9 19 0
-{10} 32 4 28 0
-{10} -34 20 -46 0
-{10} -4 -36 -13 0
-{10} -15 -37 45 0
-{10} -21 29 23 0
-{10} -6 -40 7 0
-{10} -42 31 -29 0
-{10} -36 24 31 0
-{10} -45 -37 -1 0
-{10} 3 -6 -29 0
-{10} -28 -50 27 0
-{10} 44 26 5 0
-{10} -17 -48 49 0
-{10} 12 -40 -7 0
-{10} -12 31 -48 0
-{10} 27 32 -42 0
-{10} -27 -10 1 0
-{10} 6 -49 10 0
-{10} -24 8 43 0
-{10} 23 31 1 0
-{10} 11 -47 38 0
-{10} -28 26 -13 0
-{10} -40 12 -42 0
-{10} -3 39 46 0
-{10} 17 41 46 0
-{10} 23 21 13 0
-{10} -14 -1 -38 0
-{10} 20 18 6 0
-{10} -50 20 -9 0
-{10} 10 -32 -18 0
-{10} -21 49 -34 0
-{10} 44 23 -35 0
-{10} 40 -19 34 0
-{10} -1 6 -12 0
-{10} 6 -2 -7 0
-{10} 32 -20 34 0
-{10} -12 43 -29 0
-{10} 24 2 -49 0
-{10} 10 -4 40 0
-{10} 11 5 12 0
-{10} -3 47 -31 0
-{10} 43 -23 21 0
-{10} -41 -36 -50 0
-{10} -8 -42 -24 0
-{10} 39 45 7 0
-{10} 7 37 -45 0
-{10} 41 40 8 0
-{10} -50 -10 -8 0
-{10} -5 -39 -14 0
-{10} -22 -24 -43 0
-{10} -36 40 35 0
-{10} 17 49 41 0
-{10} -32 7 24 0
-{10} -30 -8 -9 0
-{10} -41 -13 -10 0
-{10} 31 26 -33 0
-{10} 17 -22 -39 0
-{10} -21 28 3 0
-{10} -14 46 23 0
-{10} 29 16 19 0
-{10} 42 -32 -44 0
-{10} -24 10 23 0
-{10} -1 -32 -21 0
-{10} -8 -44 -39 0
-{10} 39 11 9 0
-{10} 19 14 -46 0
-{10} 46 44 -42 0
-{10} 37 23 -29 0
-{10} 32 25 20 0
-{10} 14 -43 -12 0
-{10} -36 -18 46 0
-{10} 14 -26 -10 0
-{10} -2 -30 5 0
-{10} 6 -18 46 0
-{10} -26 2 -44 0
-{10} 20 -8 -11 0
-{10} -31 3 16 0
-{10} -22 -9 39 0
-{10} -49 44 -42 0
-{10} -45 -44 31 0
-{10} -31 50 -11 0
-{10} -32 -46 2 0
-{10} -6 -7 17 0
-{10} 19 -32 48 0
-{10} 39 20 -10 0
-{10} -22 -37 38 0
-{10} -31 9 -48 0
-{10} 40 12 7 0
-{10} -24 -4 9 0
-{10} -22 49 33 0
-{10} -12 43 10 0
-{10} 25 -30 -10 0
-{10} 46 47 31 0
-{10} 13 27 -7 0
-{10} -45 32 -35 0
-{10} -50 34 9 0
-{10} 2 34 30 0
-{10} 3 16 2 0
-{10} -18 45 -12 0
-{10} 33 37 10 0
-{10} 43 7 -18 0
-{10} -22 44 -19 0
-{10} -31 -27 -42 0
-{10} -3 -40 8 0
-{10} -23 -31 38 0
diff --git a/samples/gcnf/uuf50-01b.gcnf b/samples/gcnf/uuf50-01b.gcnf
deleted file mode 100644
--- a/samples/gcnf/uuf50-01b.gcnf
+++ /dev/null
@@ -1,226 +0,0 @@
-c This Formular is generated by mcnf
-c
-c    horn? no 
-c    forced? no 
-c    mixed sat? no 
-c    clause length = 3 
-c
-p gcnf 50 218 9
-{5}  18 -8 29 0
-{2} -16 3 18 0
-{3} -36 -11 -30 0
-{7} -50 20 32 0
-{5} -6 9 35 0
-{8} 42 -38 29 0
-{2} 43 -15 10 0
-{0} -48 -47 1 0
-{4} -45 -16 33 0
-{0} 38 42 22 0
-{3} -49 41 -34 0
-{9} 12 17 35 0
-{1} 22 -49 7 0
-{9} -10 -11 -39 0
-{6} -28 -36 -37 0
-{3} -13 -46 -41 0
-{4} 21 -4 9 0
-{5} 12 48 10 0
-{3} 24 23 15 0
-{0} -8 -41 -43 0
-{3} -44 -2 -35 0
-{4} -27 18 31 0
-{5} 47 35 6 0
-{3} -11 -27 41 0
-{8} -33 -47 -45 0
-{3} -16 36 -37 0
-{3} 27 -46 2 0
-{2} 15 -28 10 0
-{4} -38 46 -39 0
-{1} -33 -4 24 0
-{8} -12 -45 50 0
-{7} -32 -21 -15 0
-{2} 8 42 24 0
-{4} 30 -49 4 0
-{0} 45 -9 28 0
-{7} -33 -47 -1 0
-{0} 1 27 -16 0
-{3} -11 -17 -35 0
-{3} -42 -15 45 0
-{8} -19 -27 30 0
-{4} 3 28 12 0
-{0} 48 -11 -33 0
-{9} -6 37 -9 0
-{7} -37 13 -7 0
-{8} -2 26 16 0
-{0} 46 -24 -38 0
-{8} -13 -24 -8 0
-{1} -36 -42 -21 0
-{1} -37 -19 3 0
-{9} -31 -50 35 0
-{5} -7 -26 29 0
-{9} -42 -45 29 0
-{7} 33 25 -6 0
-{1} -45 -5 7 0
-{2} -7 28 -6 0
-{5} -48 31 -11 0
-{3} 32 16 -37 0
-{8} -24 48 1 0
-{9} 18 -46 23 0
-{4} -30 -50 48 0
-{4} -21 39 -2 0
-{3} 24 47 42 0
-{6} -36 30 4 0
-{6} -5 28 -1 0
-{2} -47 32 -42 0
-{1} 16 37 -22 0
-{9} -43 42 -34 0
-{6} -40 39 -20 0
-{1} -49 29 6 0
-{8} -41 -3 39 0
-{3} -16 -12 43 0
-{9} 24 22 3 0
-{0} 47 -45 43 0
-{1} 45 -37 46 0
-{1} -9 26 5 0
-{5} -3 23 -13 0
-{4} 5 -34 13 0
-{6} 12 39 13 0
-{8} 22 50 37 0
-{2} 19 9 46 0
-{3} -24 8 -27 0
-{5} -28 7 21 0
-{8} 8 -25 50 0
-{0} 20 50 4 0
-{0} 27 36 13 0
-{4} 26 31 -25 0
-{1} 39 -44 -32 0
-{9} -20 41 -10 0
-{2} 49 -28 35 0
-{2} 1 44 34 0
-{4} 39 35 -11 0
-{4} -50 -42 -7 0
-{9} -24 7 47 0
-{9} -13 5 -48 0
-{8} -9 -20 -23 0
-{1} 2 17 -19 0
-{4} 11 23 21 0
-{6} -45 30 15 0
-{7} 11 26 -24 0
-{2} 38 33 -13 0
-{1} 44 -27 -7 0
-{7} 41 49 2 0
-{8} -18 12 -37 0
-{1} -2 12 -26 0
-{0} -19 7 32 0
-{8} -22 11 33 0
-{2} 8 12 -20 0
-{8} 16 40 -48 0
-{6} -2 -24 -11 0
-{2} 26 -17 37 0
-{9} -14 -19 46 0
-{9} 5 47 36 0
-{3} -29 -9 19 0
-{2} 32 4 28 0
-{4} -34 20 -46 0
-{6} -4 -36 -13 0
-{8} -15 -37 45 0
-{8} -21 29 23 0
-{5} -6 -40 7 0
-{4} -42 31 -29 0
-{5} -36 24 31 0
-{2} -45 -37 -1 0
-{3} 3 -6 -29 0
-{4} -28 -50 27 0
-{2} 44 26 5 0
-{3} -17 -48 49 0
-{5} 12 -40 -7 0
-{1} -12 31 -48 0
-{5} 27 32 -42 0
-{5} -27 -10 1 0
-{5} 6 -49 10 0
-{7} -24 8 43 0
-{7} 23 31 1 0
-{3} 11 -47 38 0
-{4} -28 26 -13 0
-{1} -40 12 -42 0
-{2} -3 39 46 0
-{8} 17 41 46 0
-{7} 23 21 13 0
-{1} -14 -1 -38 0
-{7} 20 18 6 0
-{8} -50 20 -9 0
-{5} 10 -32 -18 0
-{8} -21 49 -34 0
-{3} 44 23 -35 0
-{8} 40 -19 34 0
-{3} -1 6 -12 0
-{1} 6 -2 -7 0
-{7} 32 -20 34 0
-{5} -12 43 -29 0
-{8} 24 2 -49 0
-{5} 10 -4 40 0
-{3} 11 5 12 0
-{7} -3 47 -31 0
-{4} 43 -23 21 0
-{3} -41 -36 -50 0
-{1} -8 -42 -24 0
-{3} 39 45 7 0
-{4} 7 37 -45 0
-{8} 41 40 8 0
-{0} -50 -10 -8 0
-{2} -5 -39 -14 0
-{0} -22 -24 -43 0
-{2} -36 40 35 0
-{9} 17 49 41 0
-{6} -32 7 24 0
-{3} -30 -8 -9 0
-{6} -41 -13 -10 0
-{6} 31 26 -33 0
-{1} 17 -22 -39 0
-{2} -21 28 3 0
-{7} -14 46 23 0
-{6} 29 16 19 0
-{0} 42 -32 -44 0
-{4} -24 10 23 0
-{3} -1 -32 -21 0
-{1} -8 -44 -39 0
-{6} 39 11 9 0
-{1} 19 14 -46 0
-{8} 46 44 -42 0
-{9} 37 23 -29 0
-{8} 32 25 20 0
-{9} 14 -43 -12 0
-{5} -36 -18 46 0
-{1} 14 -26 -10 0
-{3} -2 -30 5 0
-{4} 6 -18 46 0
-{8} -26 2 -44 0
-{9} 20 -8 -11 0
-{0} -31 3 16 0
-{3} -22 -9 39 0
-{3} -49 44 -42 0
-{5} -45 -44 31 0
-{7} -31 50 -11 0
-{8} -32 -46 2 0
-{9} -6 -7 17 0
-{4} 19 -32 48 0
-{3} 39 20 -10 0
-{7} -22 -37 38 0
-{1} -31 9 -48 0
-{7} 40 12 7 0
-{5} -24 -4 9 0
-{4} -22 49 33 0
-{9} -12 43 10 0
-{1} 25 -30 -10 0
-{4} 46 47 31 0
-{3} 13 27 -7 0
-{1} -45 32 -35 0
-{1} -50 34 9 0
-{3} 2 34 30 0
-{2} 3 16 2 0
-{5} -18 45 -12 0
-{4} 33 37 10 0
-{0} 43 7 -18 0
-{6} -22 44 -19 0
-{0} -31 -27 -42 0
-{5} -3 -40 8 0
-{0} -23 -31 38 0
diff --git a/samples/gcnf/uuf50-01c.gcnf b/samples/gcnf/uuf50-01c.gcnf
deleted file mode 100644
--- a/samples/gcnf/uuf50-01c.gcnf
+++ /dev/null
@@ -1,226 +0,0 @@
-c This Formular is generated by mcnf
-c
-c    horn? no 
-c    forced? no 
-c    mixed sat? no 
-c    clause length = 3 
-c
-p gcnf 50 218 20
-{1}   18 -8 29 0
-{12} -16 3 18 0
-{13} -36 -11 -30 0
-{13} -50 20 32 0
-{1}  -6 9 35 0
-{10} 42 -38 29 0
-{7}  43 -15 10 0
-{6}  -48 -47 1 0
-{15} -45 -16 33 0
-{6}  38 42 22 0
-{9}  -49 41 -34 0
-{18} 12 17 35 0
-{15} 22 -49 7 0
-{5}  -10 -11 -39 0
-{20} -28 -36 -37 0
-{0}  -13 -46 -41 0
-{20} 21 -4 9 0
-{12} 12 48 10 0
-{8}  24 23 15 0
-{18} -8 -41 -43 0
-{3}  -44 -2 -35 0
-{9}  -27 18 31 0
-{20} 47 35 6 0
-{8}  -11 -27 41 0
-{16} -33 -47 -45 0
-{4}  -16 36 -37 0
-{13} 27 -46 2 0
-{4}  15 -28 10 0
-{7}  -38 46 -39 0
-{2}  -33 -4 24 0
-{16} -12 -45 50 0
-{14} -32 -21 -15 0
-{7}  8 42 24 0
-{17} 30 -49 4 0
-{5}  45 -9 28 0
-{6}  -33 -47 -1 0
-{14} 1 27 -16 0
-{13} -11 -17 -35 0
-{3}  -42 -15 45 0
-{6}  -19 -27 30 0
-{11} 3 28 12 0
-{13} 48 -11 -33 0
-{15} -6 37 -9 0
-{8}  -37 13 -7 0
-{17} -2 26 16 0
-{5}  46 -24 -38 0
-{8}  -13 -24 -8 0
-{8}  -36 -42 -21 0
-{11} -37 -19 3 0
-{5}  -31 -50 35 0
-{13} -7 -26 29 0
-{15} -42 -45 29 0
-{20} 33 25 -6 0
-{6}  -45 -5 7 0
-{3}  -7 28 -6 0
-{8}  -48 31 -11 0
-{6}  32 16 -37 0
-{4}  -24 48 1 0
-{9}  18 -46 23 0
-{0}  -30 -50 48 0
-{3}  -21 39 -2 0
-{9}  24 47 42 0
-{15} -36 30 4 0
-{20} -5 28 -1 0
-{20} -47 32 -42 0
-{4}  16 37 -22 0
-{5}  -43 42 -34 0
-{20} -40 39 -20 0
-{14} -49 29 6 0
-{16} -41 -3 39 0
-{12} -16 -12 43 0
-{13} 24 22 3 0
-{12} 47 -45 43 0
-{10} 45 -37 46 0
-{5}  -9 26 5 0
-{0}  -3 23 -13 0
-{10} 5 -34 13 0
-{4}  12 39 13 0
-{9}  22 50 37 0
-{0}  19 9 46 0
-{17} -24 8 -27 0
-{4}  -28 7 21 0
-{18} 8 -25 50 0
-{17} 20 50 4 0
-{5}  27 36 13 0
-{10} 26 31 -25 0
-{2}  39 -44 -32 0
-{15} -20 41 -10 0
-{13} 49 -28 35 0
-{18} 1 44 34 0
-{0}  39 35 -11 0
-{4}  -50 -42 -7 0
-{16} -24 7 47 0
-{18} -13 5 -48 0
-{2}  -9 -20 -23 0
-{9}  2 17 -19 0
-{14} 11 23 21 0
-{17} -45 30 15 0
-{20} 11 26 -24 0
-{3}  38 33 -13 0
-{5}  44 -27 -7 0
-{20} 41 49 2 0
-{15} -18 12 -37 0
-{15} -2 12 -26 0
-{14} -19 7 32 0
-{12} -22 11 33 0
-{19} 8 12 -20 0
-{0}  16 40 -48 0
-{6}  -2 -24 -11 0
-{6}  26 -17 37 0
-{12} -14 -19 46 0
-{2}  5 47 36 0
-{8}  -29 -9 19 0
-{4}  32 4 28 0
-{11} -34 20 -46 0
-{4}  -4 -36 -13 0
-{19} -15 -37 45 0
-{6}  -21 29 23 0
-{15} -6 -40 7 0
-{1}  -42 31 -29 0
-{14} -36 24 31 0
-{9}  -45 -37 -1 0
-{8}  3 -6 -29 0
-{0}  -28 -50 27 0
-{4}  44 26 5 0
-{9}  -17 -48 49 0
-{12} 12 -40 -7 0
-{11} -12 31 -48 0
-{3}  27 32 -42 0
-{20} -27 -10 1 0
-{17} 6 -49 10 0
-{14} -24 8 43 0
-{10} 23 31 1 0
-{12} 11 -47 38 0
-{20} -28 26 -13 0
-{11} -40 12 -42 0
-{3}  -3 39 46 0
-{17} 17 41 46 0
-{10} 23 21 13 0
-{17} -14 -1 -38 0
-{16} 20 18 6 0
-{6}  -50 20 -9 0
-{17} 10 -32 -18 0
-{7}  -21 49 -34 0
-{17} 44 23 -35 0
-{0}  40 -19 34 0
-{11} -1 6 -12 0
-{17} 6 -2 -7 0
-{5}  32 -20 34 0
-{9}  -12 43 -29 0
-{10} 24 2 -49 0
-{18} 10 -4 40 0
-{9}  11 5 12 0
-{10} -3 47 -31 0
-{2}  43 -23 21 0
-{19} -41 -36 -50 0
-{1}  -8 -42 -24 0
-{9}  39 45 7 0
-{17} 7 37 -45 0
-{20} 41 40 8 0
-{18} -50 -10 -8 0
-{2}  -5 -39 -14 0
-{17} -22 -24 -43 0
-{17} -36 40 35 0
-{4}  17 49 41 0
-{5}  -32 7 24 0
-{15} -30 -8 -9 0
-{0}  -41 -13 -10 0
-{17} 31 26 -33 0
-{0}  17 -22 -39 0
-{12} -21 28 3 0
-{20} -14 46 23 0
-{18} 29 16 19 0
-{17} 42 -32 -44 0
-{14} -24 10 23 0
-{15} -1 -32 -21 0
-{2}  -8 -44 -39 0
-{7}  39 11 9 0
-{19} 19 14 -46 0
-{9}  46 44 -42 0
-{9}  37 23 -29 0
-{11} 32 25 20 0
-{7}  14 -43 -12 0
-{0}  -36 -18 46 0
-{4}  14 -26 -10 0
-{13} -2 -30 5 0
-{17} 6 -18 46 0
-{2}  -26 2 -44 0
-{6}  20 -8 -11 0
-{8}  -31 3 16 0
-{19} -22 -9 39 0
-{3}  -49 44 -42 0
-{2}  -45 -44 31 0
-{6}  -31 50 -11 0
-{11} -32 -46 2 0
-{8}  -6 -7 17 0
-{6}  19 -32 48 0
-{8}  39 20 -10 0
-{11} -22 -37 38 0
-{3}  -31 9 -48 0
-{1}  40 12 7 0
-{15} -24 -4 9 0
-{1}  -22 49 33 0
-{12} -12 43 10 0
-{12} 25 -30 -10 0
-{2}  46 47 31 0
-{0}  13 27 -7 0
-{19} -45 32 -35 0
-{20} -50 34 9 0
-{0}  2 34 30 0
-{19} 3 16 2 0
-{16} -18 45 -12 0
-{16} 33 37 10 0
-{13} 43 7 -18 0
-{2}  -22 44 -19 0
-{19} -31 -27 -42 0
-{18} -3 -40 8 0
-{11} -23 -31 38 0
diff --git a/samples/maxsat/MML10.wcnf b/samples/maxsat/MML10.wcnf
new file mode 100644
--- /dev/null
+++ b/samples/maxsat/MML10.wcnf
@@ -0,0 +1,8 @@
+c from http://sat.inesc-id.pt/~ruben/talks/sat10-talk.pdf
+p wcnf 3 6 15
+15 1 2 -3 0
+15 -2 3 0
+15 -1 3 0
+5 -3 0
+3 1 2 0
+2 1 3 0
diff --git a/samples/maxsat/file_rwpms_wcnf_L2_V150_C1000_H150_0.wcnf b/samples/maxsat/file_rwpms_wcnf_L2_V150_C1000_H150_0.wcnf
new file mode 100644
--- /dev/null
+++ b/samples/maxsat/file_rwpms_wcnf_L2_V150_C1000_H150_0.wcnf
@@ -0,0 +1,1003 @@
+c Weighted CNF
+c from Selman's wff generator
+p wcnf 150 1000 5278
+5278 123 -121 0
+5278 66 -130 0
+5278 94 88 0
+5278 -150 94 0
+5278 77 138 0
+5278 -32 -77 0
+5278 29 -135 0
+5278 -149 -3 0
+5278 31 51 0
+5278 -81 8 0
+5278 78 115 0
+5278 -61 -57 0
+5278 44 113 0
+5278 39 103 0
+5278 88 -71 0
+5278 74 -126 0
+5278 -27 -91 0
+5278 -99 68 0
+5278 33 -142 0
+5278 -48 -145 0
+5278 107 -83 0
+5278 35 -56 0
+5278 126 98 0
+5278 74 -114 0
+5278 55 118 0
+5278 35 31 0
+5278 23 75 0
+5278 69 89 0
+5278 21 27 0
+5278 83 84 0
+5278 -31 -85 0
+5278 48 -111 0
+5278 -78 -110 0
+5278 140 132 0
+5278 -56 -39 0
+5278 -128 -93 0
+5278 120 20 0
+5278 -103 -80 0
+5278 -15 68 0
+5278 28 -141 0
+5278 101 -117 0
+5278 -98 96 0
+5278 -134 -35 0
+5278 -128 -126 0
+5278 -146 -13 0
+5278 -93 -110 0
+5278 27 19 0
+5278 10 -31 0
+5278 148 -76 0
+5278 -21 3 0
+5278 -37 75 0
+5278 -50 75 0
+5278 -88 110 0
+5278 -70 -74 0
+5278 -92 -4 0
+5278 34 8 0
+5278 -83 -110 0
+5278 -113 -74 0
+5278 148 75 0
+5278 -150 -124 0
+5278 -84 85 0
+5278 -9 -102 0
+5278 105 -97 0
+5278 105 110 0
+5278 -70 145 0
+5278 69 100 0
+5278 -24 43 0
+5278 -16 -57 0
+5278 -141 -75 0
+5278 -26 -49 0
+5278 -146 -149 0
+5278 -109 138 0
+5278 133 129 0
+5278 -78 -90 0
+5278 -133 -81 0
+5278 -137 -82 0
+5278 -7 48 0
+5278 97 -76 0
+5278 74 131 0
+5278 118 -29 0
+5278 7 -119 0
+5278 59 119 0
+5278 50 9 0
+5278 91 -136 0
+5278 -33 -141 0
+5278 66 -141 0
+5278 121 -112 0
+5278 141 -81 0
+5278 -49 -41 0
+5278 -9 117 0
+5278 -125 37 0
+5278 22 109 0
+5278 100 139 0
+5278 129 -104 0
+5278 66 26 0
+5278 106 77 0
+5278 -117 -134 0
+5278 100 110 0
+5278 -147 129 0
+5278 87 149 0
+5278 138 -106 0
+5278 60 -55 0
+5278 81 104 0
+5278 31 -83 0
+5278 -67 3 0
+5278 -113 -7 0
+5278 -135 79 0
+5278 -77 49 0
+5278 5 8 0
+5278 63 -97 0
+5278 50 -69 0
+5278 -2 69 0
+5278 -71 51 0
+5278 -58 25 0
+5278 -103 119 0
+5278 -18 70 0
+5278 -77 -125 0
+5278 -71 -124 0
+5278 43 9 0
+5278 -78 -129 0
+5278 29 -46 0
+5278 -70 24 0
+5278 143 91 0
+5278 10 -146 0
+5278 120 118 0
+5278 92 -56 0
+5278 65 -62 0
+5278 -41 139 0
+5278 34 -22 0
+5278 -46 133 0
+5278 74 -27 0
+5278 22 -81 0
+5278 48 -95 0
+5278 -150 43 0
+5278 105 -150 0
+5278 138 46 0
+5278 -68 -69 0
+5278 51 -99 0
+5278 125 -51 0
+5278 -131 77 0
+5278 21 19 0
+5278 -62 140 0
+5278 -140 10 0
+5278 -73 -149 0
+5278 123 68 0
+5278 69 -17 0
+5278 -74 -43 0
+5278 30 128 0
+5278 -145 -41 0
+5278 -125 -126 0
+6 136 102 0
+8 100 105 0
+2 -22 -91 0
+3 107 39 0
+8 82 -9 0
+1 136 -51 0
+2 -92 120 0
+8 96 -90 0
+10 -41 -32 0
+4 136 37 0
+4 -128 -56 0
+10 -95 7 0
+4 -15 -145 0
+7 -46 -147 0
+2 117 96 0
+2 -35 -85 0
+5 116 -130 0
+4 -17 -129 0
+4 -35 -56 0
+10 62 -44 0
+10 -39 -142 0
+5 139 -56 0
+8 1 125 0
+10 -59 8 0
+4 -138 27 0
+8 -5 84 0
+1 139 78 0
+8 -121 23 0
+10 -14 52 0
+4 -107 -15 0
+5 -140 123 0
+6 130 -104 0
+1 -130 -48 0
+6 131 -119 0
+9 46 41 0
+8 63 -146 0
+7 -47 121 0
+10 -135 -35 0
+6 7 -105 0
+7 -58 94 0
+3 141 -74 0
+9 -42 -45 0
+6 -85 -111 0
+6 107 131 0
+6 101 -2 0
+7 37 118 0
+8 72 -81 0
+1 24 132 0
+1 -55 -39 0
+1 83 77 0
+10 38 -138 0
+1 -118 89 0
+5 91 -3 0
+7 120 62 0
+10 143 48 0
+9 30 -37 0
+4 75 17 0
+1 94 -64 0
+7 -52 40 0
+3 -129 122 0
+4 125 -91 0
+2 -3 -65 0
+9 113 -6 0
+4 -42 -43 0
+7 -59 106 0
+7 -20 149 0
+2 -38 108 0
+4 -79 29 0
+6 -119 -130 0
+7 -45 132 0
+10 -138 127 0
+8 -19 -75 0
+6 -31 119 0
+5 -118 62 0
+4 20 -63 0
+1 91 105 0
+2 85 -148 0
+2 -130 -145 0
+1 -121 -135 0
+2 59 -142 0
+2 -111 -146 0
+1 -58 -112 0
+3 25 -103 0
+7 58 -26 0
+7 -24 54 0
+2 -48 106 0
+6 91 -117 0
+1 -108 74 0
+2 -70 -79 0
+3 41 78 0
+4 31 -79 0
+6 -104 -54 0
+4 -108 50 0
+2 6 -101 0
+9 -67 30 0
+1 -104 34 0
+8 -112 88 0
+1 15 53 0
+4 -131 -97 0
+3 150 -62 0
+7 -112 -43 0
+4 144 135 0
+1 -15 -8 0
+3 -41 27 0
+9 114 -139 0
+4 41 71 0
+4 -17 5 0
+10 -67 17 0
+5 -59 86 0
+4 -70 -58 0
+2 65 -46 0
+7 -73 41 0
+4 30 112 0
+4 -33 38 0
+4 42 -45 0
+1 -61 -39 0
+6 125 131 0
+10 -38 -133 0
+1 29 -30 0
+7 -70 -16 0
+2 127 2 0
+4 39 -109 0
+3 3 124 0
+5 12 -25 0
+5 5 54 0
+1 -37 8 0
+5 37 -52 0
+3 67 2 0
+1 3 74 0
+9 -32 111 0
+5 -84 -10 0
+8 -34 131 0
+2 -34 111 0
+5 -119 74 0
+10 -125 150 0
+1 -2 17 0
+9 90 -136 0
+3 96 17 0
+10 -26 103 0
+4 -83 -56 0
+7 16 -26 0
+2 -99 20 0
+10 -20 101 0
+1 117 47 0
+6 33 -70 0
+4 86 -32 0
+2 134 132 0
+1 37 115 0
+4 141 -69 0
+2 88 -26 0
+8 -126 -124 0
+5 -20 2 0
+6 72 25 0
+10 -57 38 0
+10 -20 138 0
+1 -103 -139 0
+1 57 -145 0
+5 -20 -41 0
+3 -15 80 0
+1 -82 85 0
+3 110 117 0
+8 4 129 0
+9 -116 13 0
+5 1 37 0
+2 32 41 0
+9 81 -5 0
+5 -84 133 0
+1 67 66 0
+2 33 28 0
+5 6 -98 0
+4 110 -138 0
+8 25 48 0
+6 -88 70 0
+4 -74 3 0
+9 136 94 0
+2 -10 40 0
+8 -67 120 0
+1 67 137 0
+2 -125 -81 0
+1 129 5 0
+3 -75 -13 0
+9 16 49 0
+6 142 28 0
+8 67 -132 0
+9 101 120 0
+5 106 -98 0
+9 -29 31 0
+9 35 -135 0
+9 -147 7 0
+2 56 112 0
+10 140 65 0
+2 46 -91 0
+9 60 94 0
+8 -42 59 0
+7 -90 -24 0
+1 -8 149 0
+6 6 40 0
+1 -2 -28 0
+2 93 -6 0
+7 -96 85 0
+6 29 150 0
+5 -59 -115 0
+5 -139 -66 0
+2 65 55 0
+8 -95 -17 0
+4 -44 -87 0
+3 -92 132 0
+6 67 -110 0
+4 110 62 0
+5 26 5 0
+6 70 -139 0
+6 44 -12 0
+3 -28 33 0
+1 120 20 0
+4 -2 32 0
+2 142 -140 0
+6 -52 -28 0
+3 -32 -137 0
+10 -126 103 0
+5 114 -139 0
+4 22 -92 0
+9 112 -121 0
+6 3 -150 0
+3 -140 45 0
+7 -73 -66 0
+2 52 60 0
+3 12 -142 0
+3 -131 55 0
+3 -146 -30 0
+4 1 44 0
+10 -43 102 0
+9 147 92 0
+9 7 41 0
+5 -100 -80 0
+10 -72 133 0
+7 38 54 0
+8 -84 -44 0
+3 -87 -61 0
+2 12 83 0
+2 -25 85 0
+7 -126 -101 0
+8 30 -27 0
+8 10 125 0
+10 -29 -54 0
+9 98 70 0
+1 131 -133 0
+1 66 -26 0
+4 -111 -77 0
+3 28 62 0
+10 88 -50 0
+8 -24 10 0
+7 64 73 0
+9 143 -61 0
+4 -43 -60 0
+9 86 115 0
+5 -42 19 0
+5 -81 146 0
+1 -46 134 0
+7 -144 109 0
+8 32 136 0
+5 -46 -114 0
+7 24 -112 0
+6 76 -94 0
+3 113 139 0
+1 134 13 0
+5 -146 -26 0
+10 134 70 0
+8 55 -114 0
+7 77 -36 0
+1 148 86 0
+10 29 -64 0
+4 53 78 0
+8 90 -94 0
+7 120 -14 0
+3 -83 -119 0
+7 -83 8 0
+8 -43 128 0
+3 -64 -17 0
+10 -81 -4 0
+10 82 117 0
+3 -61 85 0
+8 -99 29 0
+7 148 -100 0
+1 108 -89 0
+1 -47 41 0
+5 -4 91 0
+6 -24 -128 0
+5 148 -109 0
+6 64 -79 0
+3 -61 62 0
+3 -81 20 0
+10 -109 118 0
+9 9 121 0
+8 62 -64 0
+3 41 107 0
+9 -66 -124 0
+3 53 -1 0
+3 -62 -12 0
+7 32 -92 0
+10 -60 3 0
+3 -123 63 0
+6 -127 98 0
+3 55 -43 0
+1 -16 26 0
+3 27 -20 0
+5 -32 6 0
+7 98 110 0
+10 112 -46 0
+7 -109 -4 0
+7 -102 87 0
+10 -129 -8 0
+9 33 74 0
+4 -94 -95 0
+6 101 77 0
+10 37 -89 0
+4 -135 -129 0
+10 132 -52 0
+5 -138 -130 0
+9 -137 64 0
+5 -138 -26 0
+7 120 75 0
+1 -1 93 0
+5 31 22 0
+5 -150 -118 0
+8 19 137 0
+8 -117 -3 0
+4 -67 86 0
+1 -111 -51 0
+10 126 -39 0
+10 132 118 0
+10 139 -49 0
+3 -17 137 0
+6 124 -34 0
+2 37 -16 0
+4 101 17 0
+8 -68 141 0
+6 30 142 0
+1 110 -32 0
+7 -81 -51 0
+2 -37 55 0
+7 -89 -24 0
+7 -39 -143 0
+1 10 -86 0
+1 -77 -43 0
+2 -35 -137 0
+10 -19 -140 0
+4 41 -27 0
+2 -82 27 0
+5 -50 -37 0
+3 -30 75 0
+7 -11 -129 0
+2 21 83 0
+4 70 -10 0
+1 150 139 0
+6 -15 -83 0
+2 -109 53 0
+9 -90 -112 0
+10 37 24 0
+2 -2 122 0
+9 -55 -27 0
+9 36 124 0
+1 113 -99 0
+2 32 -42 0
+5 -94 39 0
+2 1 95 0
+5 -119 -9 0
+2 -130 68 0
+7 94 -69 0
+5 43 70 0
+9 -19 90 0
+9 131 55 0
+2 -94 -39 0
+5 -134 -110 0
+10 118 -64 0
+2 -131 65 0
+7 134 140 0
+10 60 -68 0
+6 -8 -14 0
+8 69 18 0
+5 -56 20 0
+8 -130 -85 0
+5 148 -62 0
+6 127 -28 0
+1 -17 -106 0
+5 24 18 0
+2 32 -131 0
+2 -148 81 0
+4 -101 -65 0
+1 149 -82 0
+4 -144 -73 0
+3 -100 -28 0
+9 133 66 0
+4 84 -46 0
+4 26 56 0
+4 -137 -25 0
+5 90 -19 0
+8 -100 -45 0
+5 117 60 0
+2 87 143 0
+3 59 -75 0
+4 -120 -112 0
+1 17 21 0
+4 -46 -96 0
+8 115 107 0
+1 1 -8 0
+5 68 70 0
+5 62 -67 0
+1 -142 -149 0
+1 -110 -68 0
+3 -89 -126 0
+5 -72 69 0
+8 -25 42 0
+7 -50 -107 0
+10 -26 -28 0
+9 95 -44 0
+2 43 18 0
+1 -86 4 0
+1 130 108 0
+5 -26 128 0
+1 -19 38 0
+4 144 70 0
+7 -97 6 0
+10 -50 -11 0
+8 -29 -24 0
+10 -28 72 0
+3 29 147 0
+3 -124 -146 0
+8 33 31 0
+8 100 95 0
+5 -100 -149 0
+10 -10 64 0
+1 88 -34 0
+5 -105 -140 0
+3 136 -30 0
+8 -25 143 0
+6 -23 -11 0
+8 105 127 0
+3 126 -106 0
+6 20 -143 0
+8 26 -24 0
+5 -14 -42 0
+10 -72 -2 0
+6 145 58 0
+1 -68 87 0
+10 -63 8 0
+4 114 -129 0
+2 -122 -46 0
+10 -70 -12 0
+5 -54 -92 0
+7 94 -39 0
+10 -96 74 0
+9 10 94 0
+4 -102 112 0
+10 90 134 0
+6 30 -139 0
+4 150 37 0
+2 129 115 0
+8 3 -98 0
+1 -21 115 0
+9 -58 146 0
+2 107 63 0
+1 -47 -124 0
+9 112 -17 0
+7 53 59 0
+3 -24 42 0
+7 -139 113 0
+3 77 -84 0
+1 -80 141 0
+10 -53 -69 0
+8 42 41 0
+8 -57 -52 0
+4 -110 -130 0
+8 22 94 0
+4 56 -132 0
+5 -66 -58 0
+7 49 -111 0
+8 29 114 0
+7 5 75 0
+6 127 -39 0
+2 19 11 0
+3 104 78 0
+6 -59 -69 0
+1 -127 109 0
+7 -69 -1 0
+5 115 -26 0
+6 101 -92 0
+10 131 -51 0
+7 62 81 0
+4 9 87 0
+1 5 -16 0
+6 124 12 0
+6 -12 -131 0
+1 -6 -8 0
+5 99 -126 0
+2 -26 -44 0
+4 -125 -115 0
+1 52 126 0
+5 142 -92 0
+5 104 -43 0
+1 -24 147 0
+2 -4 -36 0
+2 11 17 0
+4 -61 109 0
+10 74 -75 0
+5 51 69 0
+9 11 -70 0
+7 -113 -14 0
+3 10 20 0
+5 -56 150 0
+3 -16 -146 0
+4 -104 76 0
+8 1 129 0
+8 -48 34 0
+4 103 100 0
+4 113 -99 0
+3 -119 66 0
+10 -66 -99 0
+4 95 43 0
+9 -118 -75 0
+3 -77 -20 0
+4 113 52 0
+5 72 128 0
+8 -28 -148 0
+5 133 -13 0
+9 102 -90 0
+10 -97 73 0
+9 147 81 0
+9 100 4 0
+4 -55 -95 0
+3 -72 -2 0
+9 149 -137 0
+6 149 -52 0
+4 -141 -87 0
+3 10 56 0
+6 -136 -11 0
+9 -15 112 0
+1 57 -124 0
+2 -126 -44 0
+1 -31 121 0
+6 -22 17 0
+4 -103 -74 0
+5 -130 -100 0
+3 110 -48 0
+2 10 50 0
+9 24 -91 0
+6 -135 121 0
+4 92 -77 0
+8 -93 24 0
+9 98 -74 0
+3 24 -127 0
+1 -24 94 0
+3 -143 2 0
+7 92 -142 0
+9 -112 136 0
+7 63 135 0
+5 9 -141 0
+9 65 -60 0
+5 36 77 0
+4 -20 29 0
+3 30 -40 0
+8 31 -42 0
+3 28 -138 0
+9 -122 -62 0
+2 -53 -147 0
+6 56 -120 0
+4 47 128 0
+10 -6 92 0
+7 132 105 0
+6 147 54 0
+1 -42 51 0
+2 -113 60 0
+10 -56 -81 0
+6 50 -39 0
+4 16 53 0
+1 145 -89 0
+5 -44 64 0
+10 118 144 0
+5 45 29 0
+3 88 -16 0
+9 -96 -5 0
+7 -44 9 0
+3 -61 104 0
+1 42 -137 0
+4 -51 21 0
+2 14 41 0
+8 69 49 0
+9 -65 87 0
+1 92 -106 0
+3 114 98 0
+3 -51 -123 0
+3 110 112 0
+10 132 -4 0
+6 44 -54 0
+2 -103 118 0
+1 54 -118 0
+1 -73 33 0
+5 130 23 0
+1 -145 -140 0
+8 -101 -150 0
+1 -3 141 0
+2 45 -129 0
+9 97 126 0
+10 -94 41 0
+8 73 125 0
+3 -147 -112 0
+1 -101 54 0
+2 -54 60 0
+2 -51 -59 0
+5 -38 -110 0
+4 -86 106 0
+10 146 130 0
+2 -105 -97 0
+7 -58 52 0
+1 105 40 0
+5 100 -43 0
+8 -102 -16 0
+9 -126 37 0
+4 -143 -109 0
+8 89 135 0
+2 -81 -25 0
+6 -76 88 0
+1 128 -57 0
+2 -100 103 0
+1 119 -21 0
+2 58 15 0
+2 124 95 0
+2 -79 93 0
+7 -118 100 0
+3 37 145 0
+9 -52 113 0
+7 65 17 0
+5 -38 -94 0
+7 -109 -133 0
+7 -77 32 0
+3 125 -98 0
+9 -48 -13 0
+7 -7 58 0
+4 20 -39 0
+1 -55 -112 0
+2 55 95 0
+8 -77 31 0
+1 63 88 0
+3 -36 -24 0
+4 36 112 0
+1 -20 116 0
+7 -4 10 0
+2 122 91 0
+10 35 -37 0
+10 -68 -135 0
+10 73 -122 0
+1 146 145 0
+6 107 -59 0
+10 24 25 0
+2 -35 139 0
+6 79 -87 0
+1 124 72 0
+4 56 -37 0
+7 -9 38 0
+8 32 -128 0
+7 -36 108 0
+5 -132 129 0
+5 117 24 0
+1 110 -54 0
+2 -126 81 0
+2 117 -144 0
+3 -31 96 0
+1 73 -12 0
+8 120 -14 0
+7 -143 -104 0
+1 127 -138 0
+9 41 11 0
+4 92 143 0
+1 137 56 0
+2 -2 11 0
+7 23 -130 0
+2 -144 -49 0
+8 -2 -59 0
+8 47 -98 0
+1 -109 85 0
+8 -77 150 0
+7 -56 140 0
+2 -1 10 0
+3 140 -12 0
+7 -60 107 0
+3 16 64 0
+9 -12 -105 0
+8 39 -102 0
+7 101 127 0
+6 117 -108 0
+5 -118 -43 0
+3 -54 -4 0
+1 111 -58 0
+10 122 -64 0
+4 -19 36 0
+2 138 -122 0
+1 -99 51 0
+6 9 -8 0
+2 -50 -22 0
+9 26 -21 0
+3 -79 91 0
+3 5 149 0
+8 -35 135 0
+6 -107 103 0
+4 -4 55 0
+9 -62 -2 0
+3 23 69 0
+5 90 132 0
+7 73 -145 0
+1 -143 101 0
+6 85 30 0
+4 -133 -9 0
+8 -63 -65 0
+7 -66 -135 0
+7 -53 -1 0
+4 133 19 0
+9 -13 78 0
+6 29 -82 0
+2 111 -82 0
+5 -91 100 0
+1 -14 -75 0
+6 59 -64 0
+7 -64 3 0
+1 -22 114 0
+6 42 82 0
+10 13 -72 0
+3 4 -37 0
+6 -136 -144 0
+6 -69 -76 0
+5 -139 97 0
+4 -100 -44 0
+8 7 49 0
+7 -131 -44 0
+1 -115 -2 0
+4 38 33 0
+10 27 -10 0
+10 85 102 0
+6 -49 -12 0
+5 -55 73 0
+6 -121 -124 0
+6 -17 -79 0
+10 -81 -61 0
+10 -93 -11 0
+4 20 -14 0
+6 116 137 0
+6 149 3 0
+7 -76 133 0
+5 -106 -76 0
+1 -5 -91 0
+8 1 -54 0
+9 65 -44 0
+2 57 128 0
+4 114 -67 0
+6 69 -50 0
+2 33 -130 0
+9 -55 36 0
+6 -127 -66 0
+4 120 46 0
+5 -89 -135 0
+2 112 -7 0
+8 73 -55 0
+8 -105 -53 0
+10 -32 -24 0
+5 -60 86 0
+9 2 -138 0
+3 34 -86 0
+4 -70 122 0
+8 -129 135 0
+9 39 -144 0
+8 -46 -27 0
+3 51 -106 0
+5 -42 9 0
+8 147 10 0
+2 96 18 0
+8 140 -117 0
+3 101 -2 0
+8 -145 62 0
+5 -88 -114 0
+7 -70 -131 0
+9 139 -94 0
+3 104 17 0
+6 34 14 0
+10 -131 -109 0
+6 111 -11 0
+1 -72 55 0
+1 -19 -113 0
+5 93 -95 0
+7 39 -52 0
+5 68 -79 0
+9 -93 105 0
+8 63 117 0
+3 -127 75 0
+7 129 -124 0
+8 -87 55 0
+7 -150 133 0
+5 34 -25 0
+1 104 72 0
+1 -26 -30 0
+3 -146 -123 0
+9 48 90 0
+9 64 -79 0
+5 133 -108 0
+4 91 -139 0
+6 -14 -51 0
+7 123 -130 0
+1 -9 132 0
+8 -104 47 0
+4 137 148 0
+6 76 51 0
+5 9 -79 0
+2 68 -62 0
+8 113 -148 0
+10 -127 -61 0
+2 -42 -18 0
+4 -65 116 0
+1 -113 24 0
+3 -75 -2 0
+8 81 -138 0
+7 -50 104 0
+7 -101 -127 0
+7 38 -29 0
+5 -47 -53 0
+9 18 -72 0
+3 96 113 0
+2 -115 116 0
+5 104 135 0
+8 88 121 0
+2 -98 -112 0
+6 140 30 0
+10 -83 -141 0
+1 -62 9 0
+4 122 -100 0
+5 -65 132 0
+4 116 22 0
+9 -143 -36 0
+1 -147 -59 0
+5 89 142 0
+7 -132 19 0
+4 27 -51 0
+10 -150 80 0
+1 -61 64 0
+6 -86 -105 0
+7 141 -22 0
+10 -81 96 0
+8 87 146 0
+10 -15 10 0
+10 61 13 0
+10 -92 124 0
+8 37 -59 0
+7 14 108 0
+6 -130 70 0
diff --git a/samples/wbo/example-lin.wbo b/samples/wbo/example-lin.wbo
deleted file mode 100644
--- a/samples/wbo/example-lin.wbo
+++ /dev/null
@@ -1,6 +0,0 @@
-* #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/src/Algebra/Lattice/Boolean.hs b/src/Algebra/Lattice/Boolean.hs
new file mode 100644
--- /dev/null
+++ b/src/Algebra/Lattice/Boolean.hs
@@ -0,0 +1,66 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Algebra.Lattice.Boolean
+-- Copyright   :  (c) Masahiro Sakai 2012-2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- Type classes for lattices and boolean algebras.
+-- 
+-----------------------------------------------------------------------------
+module Algebra.Lattice.Boolean
+  (
+  -- * Boolean algebra
+    Complement (..)
+  , Boolean (..)
+  , true
+  , false
+  , (.&&.)
+  , (.||.)
+  , andB
+  , orB
+  ) where
+
+import Algebra.Lattice
+
+infixr 3 .&&.
+infixr 2 .||.
+infix 1 .=>., .<=>.
+
+-- | types that can be negated.
+class Complement a where
+  notB :: a -> a
+
+-- | types that can be combined with boolean operations.
+class (BoundedLattice 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 'meets'
+andB :: Boolean a => [a] -> a
+andB = meets
+
+-- | alias of 'joins'
+orB :: Boolean a => [a] -> a
+orB = joins
diff --git a/src/Algorithm/BoundsInference.hs b/src/Algorithm/BoundsInference.hs
--- a/src/Algorithm/BoundsInference.hs
+++ b/src/Algorithm/BoundsInference.hs
@@ -21,13 +21,13 @@
 import Control.Monad
 import qualified Data.IntMap as IM
 import qualified Data.IntSet as IS
+import Data.VectorSpace
 
-import Data.Expr
 import Data.ArithRel
-import Data.Linear
 import Data.Interval
 import Data.LA (BoundsEnv)
 import qualified Data.LA as LA
+import Data.Var
 import Util (isInteger)
 
 type C r = (RelOp, LA.Expr r)
@@ -44,11 +44,11 @@
     cs :: VarMap [C r]
     cs = IM.fromListWith (++) $ do
       Rel lhs op rhs <- constraints
-      let m = LA.coeffMap (lhs .-. rhs)
+      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)
+          rhs' = (-1/c) *^ LA.fromCoeffMap (IM.delete v m)
       return (v, [(op', rhs')])
 
     loop  :: Int -> LA.BoundsEnv r -> LA.BoundsEnv r
@@ -70,16 +70,40 @@
 f b cs i = foldr intersection i $ do
   (op, rhs) <- cs
   let i' = LA.computeInterval b rhs
-      lb = lowerBound i'
-      ub = upperBound i'
+      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
+    Le -> return $ interval (NegInf, False) ub
+    Ge -> return $ interval lb (PosInf, False)
+    Lt -> return $ interval (NegInf, False) (strict ub)
+    Gt -> return $ interval (strict ub) (PosInf, False)
     NEq -> []
 
-strict :: EndPoint r -> EndPoint r
-strict Nothing = Nothing
-strict (Just (_,val)) = Just (False,val)
+strict :: (EndPoint r, Bool) -> (EndPoint r, Bool)
+strict (x, _) = (x, False)
+
+-- | tightening intervals by ceiling lower bounds and flooring upper bounds.
+tightenToInteger :: forall r. (RealFrac r) => Interval r -> Interval r
+tightenToInteger ival = interval lb2 ub2
+  where
+    lb@(x1, in1) = lowerBound' ival
+    ub@(x2, in2) = upperBound' ival
+    lb2 =
+      case x1 of
+        Finite x ->
+          ( if isInteger x && not in1
+            then Finite (x + 1)
+            else Finite (fromInteger (ceiling x))
+          , True
+          )
+        _ -> lb
+    ub2 =
+      case x2 of
+        Finite x ->
+          ( if isInteger x && not in2
+            then Finite (x - 1)
+            else Finite (fromInteger (floor x))
+          , True
+          )
+        _ -> ub
diff --git a/src/Algorithm/CAD.hs b/src/Algorithm/CAD.hs
--- a/src/Algorithm/CAD.hs
+++ b/src/Algorithm/CAD.hs
@@ -63,7 +63,7 @@
 
 import Data.ArithRel
 import qualified Data.AlgebraicNumber as AReal
-import Data.Formula (DNF (..))
+import Data.DNF
 import Data.Polynomial
 
 import Debug.Trace
@@ -409,9 +409,10 @@
 
 solve
   :: forall v. (Ord v, Show v, RenderVar v)
-  => [(Rel (Polynomial Rational v))]
+  => Set.Set v
+  -> [(Rel (Polynomial Rational v))]
   -> Maybe (Model v)
-solve cs0 = solve' (map f cs0)
+solve vs cs0 = solve' vs (map f cs0)
   where
     f (Rel lhs op rhs) = (lhs - rhs, g op)
     g Le  = [Zero, Neg]
@@ -423,12 +424,11 @@
 
 solve'
   :: forall v. (Ord v, Show v, RenderVar v)
-  => [(Polynomial Rational v, [Sign])]
+  => Set.Set v
+  -> [(Polynomial Rational v, [Sign])]
   -> Maybe (Model v)
-solve' cs0 = go vs0 cs0
+solve' vs0 cs0 = go (Set.toList vs0) cs0
   where
-    vs0 = Set.toList $ Set.unions [variables p | (p,_) <- cs0]
-
     go :: [v] -> [(Polynomial Rational v, [Sign])] -> Maybe (Model v)
     go [] cs =
       if and [signOfConst v `elem` ss | (p,ss) <- cs, let v = eval (\_ -> undefined) p]
@@ -504,14 +504,15 @@
     [(conf, _)] = runM $ buildSignConf ps
 
 test1b :: Bool
-test1b = isJust $ solve cs
+test1b = isJust $ solve vs cs
   where
     x = var ()
+    vs = Set.singleton ()
     cs = [x + 1 .>. 0, -2*x + 3 .>. 0, x .>. 0]
 
 test1c :: Bool
 test1c = isJust $ do
-  m <- solve' cs
+  m <- solve' (Set.singleton ()) cs
   guard $ and $ do
     (p, ss) <- cs
     let val = eval (m Map.!) (mapCoeff fromRational p)
@@ -529,9 +530,10 @@
     [(conf, _)] = runM $ buildSignConf ps
 
 test2b :: Bool
-test2b = isNothing $ solve cs
+test2b = isNothing $ solve vs cs
   where
     x = var ()
+    vs = Set.singleton ()
     cs = [x^(2::Int) .<. 0]
 
 test = and [test1b, test1c, test2b]
@@ -564,11 +566,12 @@
     p :: Polynomial Rational Int
     p = a^(2::Int) + b^(2::Int) + c^(2::Int) - 1
 
-test_solve = solve [p .<. 0]
+test_solve = solve vs [p .<. 0]
   where
     a = var 0
     b = var 1
     c = var 2
+    vs = Set.fromList [0,1,2]
     p :: Polynomial Rational Int
     p = a^(2::Int) + b^(2::Int) + c^(2::Int) - 1
 
diff --git a/src/Algorithm/ContiTraverso.hs b/src/Algorithm/ContiTraverso.hs
--- a/src/Algorithm/ContiTraverso.hs
+++ b/src/Algorithm/ContiTraverso.hs
@@ -35,22 +35,22 @@
 import Data.List
 import Data.Monoid
 import Data.Ratio
+import Data.VectorSpace
 
 import Data.ArithRel
-import Data.Linear
 import qualified Data.LA as LA
-import Data.Expr (Var, VarSet, Variables (..), Model)
 import Data.OptDir
 import Data.Polynomial
 import Data.Polynomial.GBase
+import Data.Var
 import qualified Algorithm.LPUtil as LPUtil
 
-solve :: MonomialOrder Var -> OptDir -> LA.Expr Rational -> [LA.Atom Rational] -> Maybe (Model Integer)
-solve cmp dir obj cs = do
-  m <- solve' cmp obj3 cs3
+solve :: MonomialOrder Var -> VarSet -> OptDir -> LA.Expr Rational -> [LA.Atom Rational] -> Maybe (Model Integer)
+solve cmp vs dir obj cs = do
+  m <- solve' cmp vs obj3 cs3
   return . IM.map round . mt . IM.map fromInteger $ m
   where
-    ((obj2,cs2), mt) = LPUtil.toStandardForm (if dir == OptMin then obj else lnegate obj, cs)
+    ((obj2,cs2), mt) = LPUtil.toStandardForm (if dir == OptMin then obj else negateV obj, cs)
     obj3 = LA.mapCoeff g obj2
       where
         g = round . (c*)
@@ -61,8 +61,8 @@
         g = round . (c*)
         c = fromInteger $ foldl' lcm 1 [denominator c | (c,_) <- LA.terms lhs]
 
-solve' :: MonomialOrder Var -> LA.Expr Integer -> [(LA.Expr Integer, Integer)] -> Maybe (Model Integer)
-solve' cmp obj cs
+solve' :: MonomialOrder Var -> VarSet -> LA.Expr Integer -> [(LA.Expr Integer, Integer)] -> Maybe (Model Integer)
+solve' cmp vs' obj cs
   | or [c < 0 | (c,x) <- LA.terms obj, x /= LA.unitVar] = error "all coefficient of cost function should be non-negative"
   | otherwise =
   if IM.keysSet (IM.filter (/= 0) m) `IS.isSubsetOf` vs'
@@ -72,9 +72,6 @@
   where
     vs :: [Var]
     vs = IS.toList vs'
-
-    vs' :: VarSet
-    vs' = vars $ obj : [lhs | (lhs,_) <- cs]
 
     v2 :: Var
     v2 = if IS.null vs' then 0 else IS.findMax vs' + 1
diff --git a/src/Algorithm/Cooper.hs b/src/Algorithm/Cooper.hs
--- a/src/Algorithm/Cooper.hs
+++ b/src/Algorithm/Cooper.hs
@@ -1,5 +1,4 @@
 {-# OPTIONS_GHC -Wall #-}
-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Algorithm.Cooper
@@ -29,416 +28,23 @@
       ExprZ
     , Lit (..)
     , QFFormula (..)
+    , fromLAAtom
     , (.|.)
-    , Model
 
     -- * Projection
     , project
     , projectCases
-    , projectCases'
     , projectCasesN
 
     -- * Quantifier elimination
     , eliminateQuantifiers
 
     -- * Constraint solving
-    , solveFormula
+    , solve
     , solveQFFormula
-    , solveConj
+    , solveFormula
     , solveQFLA
     ) where
 
-import Control.Monad
-import Data.List
-import Data.Maybe
-import qualified Data.IntMap as IM
-import qualified Data.IntSet as IS
-import Data.Ratio
-
-import Data.ArithRel
-import Data.Expr
-import Data.Formula
-import Data.Linear
-import qualified Data.LA as LA
-import qualified Algorithm.FourierMotzkin as FM
-
--- ---------------------------------------------------------------------------
-
--- | Linear arithmetic expression over integers.
-type ExprZ = LA.Expr Integer
-
-atomZ :: RelOp -> Expr Rational -> Expr Rational -> Maybe QFFormula
-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 -> QFFormula
-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 QFFormula
-    = T'
-    | F'
-    | And' QFFormula QFFormula
-    | Or' QFFormula QFFormula
-    | Lit Lit
-    deriving (Show, Eq, Ord)
-
-instance Complement QFFormula 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 QFFormula where
-  top    = T'
-  bottom = F'
-  meet   = And'
-  join   = Or'
-
-instance Boolean QFFormula
-
-instance Variables QFFormula where
-  vars T' = IS.empty
-  vars F' = IS.empty
-  vars (And' a b) = vars a `IS.union` vars b
-  vars (Or' a b)  = vars a `IS.union` vars b
-  vars (Lit l)    = vars l
-
-instance IsRel (LA.Expr Integer) QFFormula where
-  rel op lhs rhs =
-    case op of
-      Le  -> Lit $ leZ lhs rhs
-      Ge  -> Lit $ geZ lhs rhs
-      Lt  -> Lit $ ltZ lhs rhs
-      Gt  -> Lit $ gtZ lhs rhs
-      Eql -> eqZ lhs rhs
-      NEq -> notB $ rel Eql lhs rhs
-
-(.|.) :: Integer -> ExprZ -> QFFormula
-n .|. e = Lit $ Divisible True n e
-
-subst1 :: Var -> ExprZ -> QFFormula -> QFFormula
-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 :: QFFormula -> QFFormula
-simplify (And' a b) = simplify1 $ And' (simplify a) (simplify b)
-simplify (Or' a b)  = simplify1 $ Or' (simplify a) (simplify b)
-simplify formula    = simplify1 formula
-
-simplify1 :: QFFormula -> QFFormula
-simplify1 T' = T'
-simplify1 F' = F'
-simplify1 (And' a b) =
-  case (a, b) of
-    (T', b') -> b'
-    (a', T') -> a'
-    (F', _) -> false
-    (_, F') -> false
-    (a',b') -> a' .&&. b'
-simplify1 (Or' a b) =
-  case (a, b) of
-    (F', b') -> b'
-    (a', F') -> a'
-    (T', _) -> true
-    (_, T') -> true
-    (a',b') -> a' .||. b'
-simplify1 (Lit lit) = simplifyLit lit
-
-simplifyLit :: Lit -> QFFormula
-simplifyLit (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 [c2 | (c2,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]
-
-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'
-
--- ---------------------------------------------------------------------------
-
-project :: Var -> QFFormula -> QFFormula
-project x formula = simplify $ orB [phi | (phi,_) <- projectCases' x formula, phi /= F']
-
-projectCases :: Var -> QFFormula -> [(QFFormula, Model Integer -> Model Integer)]
-projectCases x formula = do
-  (phi, wit) <- projectCases' x formula
-  return (phi, \m -> IM.insert x (evalWitness m wit) m)
-
-projectCases' :: Var -> QFFormula -> [(QFFormula, Witness)]
-projectCases' x formula = [(simplify phi, w) | (phi,w) <- case1 ++ case2]
-  where
-    -- xの係数の最小公倍数
-    c :: Integer
-    c = f formula
-      where
-         f :: QFFormula -> 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 :: QFFormula
-    formula1 = simplify $ f formula .&&. Lit (Divisible True c (LA.var x))
-      where
-        f :: QFFormula -> QFFormula
-        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 :: QFFormula -> 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 :: QFFormula -> [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, _) -> [] -- Pos e <=> (-x + e' > 0) <=> (x < e')
-            _ -> error "should not happen"
-
-    -- formula1を真にする最小のxが存在する場合
-    case1 :: [(QFFormula, 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 :: QFFormula
-    formula2 = simplify $ f formula1
-      where        
-        f :: QFFormula -> QFFormula
-        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 :: QFFormula -> [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, _)   -> []   -- 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 :: [(QFFormula, Witness)]
-    case2 = [(subst1 x (LA.constant j) formula2, WCase2 c j delta us) | j <- [1..delta]]
-
-projectCasesN :: VarSet -> QFFormula -> [(QFFormula, Model Integer -> Model Integer)]
-projectCasesN vs2 = f (IS.toList vs2)
-  where
-    f :: [Var] -> QFFormula -> [(QFFormula, Model Integer -> Model Integer)]
-    f [] formula = return (formula, id)
-    f (v:vs) formula = do
-      (formula2, mt1) <- projectCases v formula
-      (formula3, mt2) <- f vs formula2
-      return (formula3, mt1 . mt2)
-
--- ---------------------------------------------------------------------------
-
--- | eliminate quantifiers and returns equivalent quantifier-free formula.
-eliminateQuantifiers :: Formula (Atom Rational) -> Maybe QFFormula
-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 $ Not body
-    f (Exists x body) = liftM (project x) (f body)
-
--- ---------------------------------------------------------------------------
-
-solveFormula :: Formula (Atom Rational) -> SatResult Integer
-solveFormula formula =
-  case eliminateQuantifiers formula of
-    Nothing -> Unknown
-    Just formula' ->
-       case solveQFFormula formula' of
-         Nothing -> Unsat
-         Just m -> Sat m
-
-solveQFFormula :: QFFormula -> Maybe (Model Integer)
-solveQFFormula formula = listToMaybe $ do
-  (formula2, mt) <- projectCasesN (vars formula) formula
-  case formula2 of
-    T' -> return $ mt IM.empty
-    _  -> mzero
-
--- | solve a (open) quantifier-free formula
-solveConj :: [LA.Atom Rational] -> Maybe (Model Integer)
-solveConj cs = solveQFFormula formula
-  where
-    formula = andB [rel op (f (lhs .-. rhs)) (LA.constant 0) | Rel lhs op rhs <- cs]
-    f e = LA.mapCoeff (round . (s*)) e
-      where
-        s = fromInteger $ foldl' lcm 1 [denominator c | (c,_) <- LA.terms e]
-
--- | solve a (open) quantifier-free formula
-solveQFLA :: [LA.Atom Rational] -> VarSet -> Maybe (Model Rational)
-solveQFLA cs ivs = listToMaybe $ do
-  (cs2, mt) <- FM.projectN rvs cs
-  m <- maybeToList $ solveConj cs2
-  return $ mt $ IM.map fromInteger m
-  where
-    rvs = vars cs `IS.difference` ivs
-
--- ---------------------------------------------------------------------------
-
-testHagiya :: QFFormula
-testHagiya = project 1 $ andB [c1, c2, c3]
-  where
-    [x,y,z] = map LA.var [1..3]
-    c1 = x .<. (y .+. y)
-    c2 = z .<. x
-    c3 = 3 .|. x
-
-{-
-∃ x. 0 < y+y ∧ z<x ∧ 3|x
-⇔
-(2y-z > 0 ∧ 3|z+1) ∨ (2y-z > -2 ∧ 3|z+2) ∨ (2y-z > -3 ∧ 3|z+3)
--}
-
-test3 :: QFFormula
-test3 = project 1 $ andB [p1,p2,p3,p4]
-  where
-    x = LA.var 0
-    y = LA.var 1
-    p1 = LA.constant 0 .<. y
-    p2 = 2 .*. x .<. y
-    p3 = y .<. x .+. LA.constant 2
-    p4 = 2 .|. y
-
-{-
-∃ y. 0 < y ∧ 2x<y ∧ y < x+2 ∧ 2|y
-⇔
-(2x < 2 ∧ 0 < x) ∨ (0 < 2x+2 ∧ x < 0)
--}
-
--- ---------------------------------------------------------------------------
+import Algorithm.Cooper.Core
+import Algorithm.Cooper.FOL
diff --git a/src/Algorithm/Cooper/Core.hs b/src/Algorithm/Cooper/Core.hs
new file mode 100644
--- /dev/null
+++ b/src/Algorithm/Cooper/Core.hs
@@ -0,0 +1,449 @@
+{-# OPTIONS_GHC -Wall #-}
+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Algorithm.Cooper.Core
+-- Copyright   :  (c) Masahiro Sakai 2011-2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable (FlexibleInstances)
+--
+-- 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 Algorithm.Cooper.Core
+    (
+    -- * Language of presburger arithmetics
+      ExprZ
+    , Lit (..)
+    , evalLit
+    , QFFormula (..)
+    , fromLAAtom
+    , (.|.)
+    , evalQFFormula
+
+    -- * Projection
+    , project
+    , projectN
+    , projectCases
+    , projectCasesN
+
+    -- * Constraint solving
+    , solve
+    , solveQFFormula
+    , solveQFLA
+    ) where
+
+import Control.Monad
+import Data.List
+import Data.Maybe
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+import Data.VectorSpace hiding (project)
+
+import Algebra.Lattice
+import Algebra.Lattice.Boolean
+
+import Data.ArithRel
+import qualified Data.LA as LA
+import Data.Var
+import qualified Algorithm.FourierMotzkin as FM
+import qualified Algorithm.FourierMotzkin.Core as FM
+
+-- ---------------------------------------------------------------------------
+
+-- | Linear arithmetic expression over integers.
+type ExprZ = LA.Expr Integer
+
+fromLAAtom :: LA.Atom Rational -> QFFormula
+fromLAAtom (Rel a op b) = rel op a' b'
+  where
+    (e1,c1) = FM.toRat a
+    (e2,c2) = FM.toRat b
+    a' = c2 *^ e1
+    b' = c1 *^ e2
+
+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 -> QFFormula
+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 QFFormula
+    = T'
+    | F'
+    | And' QFFormula QFFormula
+    | Or' QFFormula QFFormula
+    | Lit Lit
+    deriving (Show, Eq, Ord)
+
+instance Complement QFFormula 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 JoinSemiLattice QFFormula where
+  join = Or'
+
+instance MeetSemiLattice QFFormula where
+  meet = And'
+
+instance Lattice QFFormula
+
+instance BoundedJoinSemiLattice QFFormula where
+  bottom = F'
+
+instance BoundedMeetSemiLattice QFFormula where
+  top = T'
+
+instance BoundedLattice QFFormula
+
+instance Boolean QFFormula
+
+instance Variables QFFormula where
+  vars T' = IS.empty
+  vars F' = IS.empty
+  vars (And' a b) = vars a `IS.union` vars b
+  vars (Or' a b)  = vars a `IS.union` vars b
+  vars (Lit l)    = vars l
+
+instance IsRel (LA.Expr Integer) QFFormula where
+  rel op lhs rhs =
+    case op of
+      Le  -> Lit $ leZ lhs rhs
+      Ge  -> Lit $ geZ lhs rhs
+      Lt  -> Lit $ ltZ lhs rhs
+      Gt  -> Lit $ gtZ lhs rhs
+      Eql -> eqZ lhs rhs
+      NEq -> notB $ rel Eql lhs rhs
+
+(.|.) :: Integer -> ExprZ -> QFFormula
+n .|. e = Lit $ Divisible True n e
+
+subst1 :: Var -> ExprZ -> QFFormula -> QFFormula
+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 :: QFFormula -> QFFormula
+simplify (And' a b) = simplify1 $ And' (simplify a) (simplify b)
+simplify (Or' a b)  = simplify1 $ Or' (simplify a) (simplify b)
+simplify formula    = simplify1 formula
+
+simplify1 :: QFFormula -> QFFormula
+simplify1 T' = T'
+simplify1 F' = F'
+simplify1 (And' a b) =
+  case (a, b) of
+    (T', b') -> b'
+    (a', T') -> a'
+    (F', _) -> false
+    (_, F') -> false
+    (a',b') -> a' .&&. b'
+simplify1 (Or' a b) =
+  case (a, b) of
+    (F', b') -> b'
+    (a', F') -> a'
+    (T', _) -> true
+    (_, T') -> true
+    (a',b') -> a' .||. b'
+simplify1 (Lit lit) = simplifyLit lit
+
+simplifyLit :: Lit -> QFFormula
+simplifyLit (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) e1 ^+^ LA.constant 1
+  where
+    e1 = e ^-^ LA.constant 1
+    d  = if null cs then 1 else abs $ foldl1' gcd cs
+    cs = [c | (c,x) <- LA.terms e1, 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 [c2 | (c2,x) <- LA.terms e, x /= LA.unitVar]
+    c' = c `div` d
+    e' = LA.mapCoeff (`div` d) e
+
+evalQFFormula :: Model Integer -> QFFormula -> Bool
+evalQFFormula m = f
+  where
+    f T' = True
+    f F' = False
+    f (And' x1 x2) = f x1 && f x2
+    f (Or'  x1 x2) = f x1 || f x2
+    f (Lit lit)    = evalLit m lit
+
+evalLit :: Model Integer -> Lit -> Bool
+evalLit m (Pos e) = LA.evalExpr m e > 0
+evalLit m (Divisible True n e)  = LA.evalExpr m e `mod` n == 0
+evalLit m (Divisible False n e) = LA.evalExpr m e `mod` n /= 0
+
+-- ---------------------------------------------------------------------------
+
+data Witness = WCase1 Integer ExprZ | WCase2 Integer Integer Integer [ExprZ]
+
+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'
+
+-- ---------------------------------------------------------------------------
+
+project :: Var -> QFFormula -> (QFFormula, Model Integer -> Model Integer)
+project x formula = (formula', mt)
+  where
+    xs = projectCases x formula
+    formula' = simplify $ orB [phi | (phi,_) <- xs, phi /= F']
+    mt m = head $ do
+      (phi, mt') <- xs
+      guard $ evalQFFormula m phi
+      return $ mt' m
+
+projectN :: VarSet -> QFFormula -> (QFFormula, Model Integer -> Model Integer)
+projectN vs2 = f (IS.toList vs2)
+  where
+    f :: [Var] -> QFFormula -> (QFFormula, Model Integer -> Model Integer)
+    f [] formula     = (formula, id)
+    f (v:vs) formula = (formula3, mt1 . mt2)
+      where
+        (formula2, mt1) = project v formula
+        (formula3, mt2) = f vs formula2
+
+projectCases :: Var -> QFFormula -> [(QFFormula, Model Integer -> Model Integer)]
+projectCases x formula = do
+  (phi, wit) <- projectCases' x formula
+  return (phi, \m -> IM.insert x (evalWitness m wit) m)
+
+projectCases' :: Var -> QFFormula -> [(QFFormula, Witness)]
+projectCases' x formula = [(simplify phi, w) | (phi,w) <- case1 ++ case2]
+  where
+    -- xの係数の最小公倍数
+    c :: Integer
+    c = f formula
+      where
+         f :: QFFormula -> 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 :: QFFormula
+    formula1 = simplify $ f formula .&&. Lit (Divisible True c (LA.var x))
+      where
+        f :: QFFormula -> QFFormula
+        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 :: QFFormula -> 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 :: QFFormula -> [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')  -> [negateV e'] -- Pos e <=> (x + e' > 0) <=> (-e' < x)
+            Just (-1, _) -> [] -- Pos e <=> (-x + e' > 0) <=> (x < e')
+            _ -> error "should not happen"
+
+    -- formula1を真にする最小のxが存在する場合
+    case1 :: [(QFFormula, 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 :: QFFormula
+    formula2 = simplify $ f formula1
+      where        
+        f :: QFFormula -> QFFormula
+        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 :: QFFormula -> [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, _)   -> []   -- 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 :: [(QFFormula, Witness)]
+    case2 = [(subst1 x (LA.constant j) formula2, WCase2 c j delta us) | j <- [1..delta]]
+
+projectCasesN :: VarSet -> QFFormula -> [(QFFormula, Model Integer -> Model Integer)]
+projectCasesN vs2 = f (IS.toList vs2)
+  where
+    f :: [Var] -> QFFormula -> [(QFFormula, Model Integer -> Model Integer)]
+    f [] formula = return (formula, id)
+    f (v:vs) formula = do
+      (formula2, mt1) <- projectCases v formula
+      (formula3, mt2) <- f vs formula2
+      return (formula3, mt1 . mt2)
+
+-- ---------------------------------------------------------------------------
+
+solveQFFormula :: VarSet -> QFFormula -> Maybe (Model Integer)
+solveQFFormula vs formula = listToMaybe $ do
+  (formula2, mt) <- projectCasesN vs formula
+  case formula2 of
+    T' -> return $ mt IM.empty
+    _  -> mzero
+
+-- | solve a (open) quantifier-free formula
+solve :: VarSet -> [LA.Atom Rational] -> Maybe (Model Integer)
+solve vs cs = solveQFFormula vs $ andB $ map fromLAAtom cs
+
+-- | solve a (open) quantifier-free formula
+solveQFLA :: VarSet -> [LA.Atom Rational] -> VarSet -> Maybe (Model Rational)
+solveQFLA vs cs ivs = listToMaybe $ do
+  (cs2, mt) <- FM.projectN rvs cs
+  m <- maybeToList $ solve ivs cs2
+  return $ mt $ IM.map fromInteger m
+  where
+    rvs = vs `IS.difference` ivs
+
+-- ---------------------------------------------------------------------------
+
+testHagiya :: QFFormula
+testHagiya = fst $ project 1 $ andB [c1, c2, c3]
+  where
+    [x,y,z] = map LA.var [1..3]
+    c1 = x .<. (y ^+^ y)
+    c2 = z .<. x
+    c3 = 3 .|. x
+
+{-
+∃ x. 0 < y+y ∧ z<x ∧ 3|x
+⇔
+(2y-z > 0 ∧ 3|z+1) ∨ (2y-z > -2 ∧ 3|z+2) ∨ (2y-z > -3 ∧ 3|z+3)
+-}
+
+test3 :: QFFormula
+test3 = fst $ project 1 $ andB [p1,p2,p3,p4]
+  where
+    x = LA.var 0
+    y = LA.var 1
+    p1 = LA.constant 0 .<. y
+    p2 = 2 *^ x .<. y
+    p3 = y .<. x ^+^ LA.constant 2
+    p4 = 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/Algorithm/Cooper/FOL.hs b/src/Algorithm/Cooper/FOL.hs
new file mode 100644
--- /dev/null
+++ b/src/Algorithm/Cooper/FOL.hs
@@ -0,0 +1,54 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Algorithm.Cooper.FOL
+-- Copyright   :  (c) Masahiro Sakai 2011-2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+-- 
+-----------------------------------------------------------------------------
+module Algorithm.Cooper.FOL
+    ( eliminateQuantifiers
+    , solveFormula
+    ) where
+
+import Control.Monad
+
+import Algebra.Lattice.Boolean
+
+import Data.ArithRel
+import qualified Data.FOL.Arith as FOL
+import qualified Data.LA.FOL as LAFOL
+import Data.Var
+
+import Algorithm.Cooper.Core
+
+-- | eliminate quantifiers and returns equivalent quantifier-free formula.
+eliminateQuantifiers :: FOL.Formula (FOL.Atom Rational) -> Maybe QFFormula
+eliminateQuantifiers = f
+  where
+    f FOL.T = return T'
+    f FOL.F = return F'
+    f (FOL.Atom (Rel a op b)) = do
+       a' <- LAFOL.fromFOLExpr a
+       b' <- LAFOL.fromFOLExpr b
+       return $ fromLAAtom (Rel a' op b')
+    f (FOL.And a b) = liftM2 (.&&.) (f a) (f b)
+    f (FOL.Or a b) = liftM2 (.||.) (f a) (f b)
+    f (FOL.Not a) = f (FOL.pushNot a)
+    f (FOL.Imply a b) = f $ FOL.Or (FOL.Not a) b
+    f (FOL.Equiv a b) = f $ FOL.And (FOL.Imply a b) (FOL.Imply b a)
+    f (FOL.Forall x body) = liftM notB $ f $ FOL.Exists x $ FOL.Not body
+    f (FOL.Exists x body) = liftM (fst . project x) (f body)
+
+solveFormula :: VarSet -> FOL.Formula (FOL.Atom Rational) -> FOL.SatResult Integer
+solveFormula vs formula =
+  case eliminateQuantifiers formula of
+    Nothing -> FOL.Unknown
+    Just formula' ->
+       case solveQFFormula vs formula' of
+         Nothing -> FOL.Unsat
+         Just m -> FOL.Sat m
diff --git a/src/Algorithm/FourierMotzkin.hs b/src/Algorithm/FourierMotzkin.hs
--- a/src/Algorithm/FourierMotzkin.hs
+++ b/src/Algorithm/FourierMotzkin.hs
@@ -1,14 +1,13 @@
 {-# OPTIONS_GHC -Wall #-}
-{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Algorithm.FourierMotzkin
--- Copyright   :  (c) Masahiro Sakai 2011
+-- Copyright   :  (c) Masahiro Sakai 2011-2013
 -- License     :  BSD-style
 -- 
 -- Maintainer  :  masahiro.sakai@gmail.com
 -- Stability   :  provisional
--- Portability :  non-portable (MultiParamTypeClasses, FunctionalDependencies)
+-- Portability :  portable
 --
 -- Naïve implementation of Fourier-Motzkin Variable Elimination
 -- 
@@ -22,263 +21,9 @@
     , project
     , projectN
     , eliminateQuantifiers
+    , solveFormula
     , solve
-    , solveConj
-
-    -- Functions for internal use in OmegaTest
-    , termR
-    , Rat
-    , 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.ArithRel
-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 $ atomR' op a' b'
-
-atomR' :: RelOp -> Rat -> Rat -> DNF Lit
-atomR' op a b = 
-  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
-
-litToLAAtom :: Lit -> LA.Atom Rational
-litToLAAtom (Nonneg e) = LA.mapCoeff fromInteger e .>=. LA.constant 0
-litToLAAtom (Pos e)    = LA.mapCoeff fromInteger e .>. LA.constant 0
-
--- ---------------------------------------------------------------------------
-
-{-
-(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])
-
-project :: Var -> [LA.Atom Rational] -> [([LA.Atom Rational], Model Rational -> Model Rational)]
-project v xs = do
-  ys <- unDNF $ constraintsToDNF xs
-  (zs, mt) <- project' v ys
-  return (map litToLAAtom zs, mt)
-
-project' :: Var -> [Lit] -> [([Lit], Model Rational -> Model Rational)]
-project' v xs = do
-  case collectBounds v xs of
-    (bnd, rest) -> do
-      cond <- unDNF $ boundConditions bnd
-      let mt m =
-           case Interval.pickup (evalBounds m bnd) of
-             Nothing  -> error "FourierMotzkin.project: should not happen"
-             Just val -> IM.insert v val m
-      return (rest ++ cond, mt)
-
-projectN :: VarSet -> [LA.Atom Rational] -> [([LA.Atom Rational], Model Rational -> Model Rational)]
-projectN vs xs = do
-  ys <- unDNF $ constraintsToDNF xs
-  (zs, mt) <- projectN' vs ys
-  return (map litToLAAtom zs, mt)
-
-projectN' :: VarSet -> [Lit] -> [([Lit], Model Rational -> Model Rational)]
-projectN' vs2 xs2 = do
-  (zs, mt) <- f (IS.toList vs2) xs2
-  return (zs, mt)
-  where
-    f [] xs     = return (xs, id)
-    f (v:vs) xs = do
-      (ys, mt1) <- project' v xs
-      (zs, mt2) <- f vs ys
-      return (zs, mt1 . mt2)
-
-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 (Atom 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 [DNF $ map fst $ project' v xs | xs <- unDNF dnf]
-
-solve :: Formula (Atom 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)
-
-solveConj :: [LA.Atom Rational] -> Maybe (Model Rational)
-solveConj cs = msum [solve' vs cs2 | cs2 <- unDNF (constraintsToDNF cs)]
-  where
-    vs = IS.toList (vars cs)
-
-solve' :: [Var] -> [Lit] -> Maybe (Model Rational)
-solve' vs xs = listToMaybe $ do
-  (ys,mt) <- projectN' (IS.fromList vs) =<< maybeToList (simplify xs)
-  guard $ Just [] == simplify ys
-  return $ mt IM.empty
-
-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 (Rel lhs op rhs) = DNF $
-  case op of
-    Eql -> [[Nonneg lhs', Nonneg (lnegate lhs')]]
-    NEq -> [[Pos lhs'], [Pos (lnegate lhs')]]
-    Ge  -> [[Nonneg lhs']]
-    Le  -> [[Nonneg (lnegate lhs')]]
-    Gt  -> [[Pos lhs']]
-    Lt  -> [[Pos (lnegate lhs')]]
-  where
-    lhs' = normalize (lhs .-. rhs)
-
-    normalize :: LA.Expr Rational -> ExprZ
-    normalize e = LA.mapCoeff (round . (*c)) e
-      where
-        c = fromIntegral $ foldl' lcm 1 ds
-        ds = [denominator d | (d,_) <- LA.terms e]
-
--- ---------------------------------------------------------------------------
-
-gcd' :: [Integer] -> Integer
-gcd' [] = 1
-gcd' xs = foldl1' gcd xs
-
--- ---------------------------------------------------------------------------
+import Algorithm.FourierMotzkin.Core
+import Algorithm.FourierMotzkin.FOL
diff --git a/src/Algorithm/FourierMotzkin/Core.hs b/src/Algorithm/FourierMotzkin/Core.hs
new file mode 100644
--- /dev/null
+++ b/src/Algorithm/FourierMotzkin/Core.hs
@@ -0,0 +1,229 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Algorithm.FourierMotzkin.Core
+-- Copyright   :  (c) Masahiro Sakai 2011-2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- Naïve implementation of Fourier-Motzkin Variable Elimination
+-- 
+-- Reference:
+--
+-- * <http://users.cecs.anu.edu.au/~michaeln/pubs/arithmetic-dps.pdf>
+--
+-----------------------------------------------------------------------------
+module Algorithm.FourierMotzkin.Core
+    ( ExprZ
+    , Rat
+    , toRat
+    , fromRat
+
+    , Lit (..)
+    , fromLAAtom
+    , toLAAtom
+
+    , project
+    , project'
+    , projectN
+    , projectN'
+    , solve
+    , solve'
+    ) 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.VectorSpace hiding (project)
+
+import Algebra.Lattice.Boolean
+
+import Data.ArithRel
+import Data.DNF
+import qualified Data.LA as LA
+import qualified Data.Interval as Interval
+import Data.Interval (Interval, EndPoint (..), (<=..<), (<..<=), (<..<))
+import Data.Var
+
+-- ---------------------------------------------------------------------------
+
+type ExprZ = LA.Expr Integer
+
+normalizeExprR :: ExprZ -> ExprZ
+normalizeExprR e = LA.mapCoeff (`div` d) e
+  where d = abs $ gcd' $ map fst $ LA.terms e
+
+-- ---------------------------------------------------------------------------
+
+-- | (t,c) represents t/c, and c must be >0.
+type Rat = (ExprZ, Integer)
+
+toRat :: LA.Expr Rational -> Rat
+toRat e = seq m $ (LA.mapCoeff f e, m)
+  where
+    f x = numerator (fromInteger m * x)
+    m = foldl' lcm 1 [denominator c | (c,_) <- LA.terms e]
+
+fromRat :: Rat -> LA.Expr Rational
+fromRat (e,c) = LA.mapCoeff (% c) e
+
+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 (negateV t)
+  notB (Nonneg t) = Pos (negateV 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]
+
+-- ---------------------------------------------------------------------------
+
+fromLAAtom :: LA.Atom Rational -> DNF Lit
+fromLAAtom (Rel a op b) = atomR' op (toRat a) (toRat b)
+
+toLAAtom :: Lit -> LA.Atom Rational
+toLAAtom (Nonneg e) = LA.mapCoeff fromInteger e .>=. LA.constant 0
+toLAAtom (Pos e)    = LA.mapCoeff fromInteger e .>. LA.constant 0
+
+constraintsToDNF :: [LA.Atom Rational] -> DNF Lit
+constraintsToDNF = andB . map fromLAAtom
+
+atomR' :: RelOp -> Rat -> Rat -> DNF Lit
+atomR' op a b = 
+  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]]
+
+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
+
+-- ---------------------------------------------------------------------------
+
+{-
+(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])
+
+project :: Var -> [LA.Atom Rational] -> [([LA.Atom Rational], Model Rational -> Model Rational)]
+project v xs = do
+  ys <- unDNF $ constraintsToDNF xs
+  (zs, mt) <- project' v ys
+  return (map toLAAtom zs, mt)
+
+project' :: Var -> [Lit] -> [([Lit], Model Rational -> Model Rational)]
+project' v xs = do
+  case collectBounds v xs of
+    (bnd, rest) -> do
+      cond <- unDNF $ boundConditions bnd
+      let mt m =
+           case Interval.pickup (evalBounds m bnd) of
+             Nothing  -> error "FourierMotzkin.project: should not happen"
+             Just val -> IM.insert v val m
+      return (rest ++ cond, mt)
+
+projectN :: VarSet -> [LA.Atom Rational] -> [([LA.Atom Rational], Model Rational -> Model Rational)]
+projectN vs xs = do
+  ys <- unDNF $ constraintsToDNF xs
+  (zs, mt) <- projectN' vs ys
+  return (map toLAAtom zs, mt)
+
+projectN' :: VarSet -> [Lit] -> [([Lit], Model Rational -> Model Rational)]
+projectN' vs2 xs2 = do
+  (zs, mt) <- f (IS.toList vs2) xs2
+  return (zs, mt)
+  where
+    f [] xs     = return (xs, id)
+    f (v:vs) xs = do
+      (ys, mt1) <- project' v xs
+      (zs, mt2) <- f vs ys
+      return (zs, mt1 . mt2)
+
+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, (negateV t', c) : ls2, us1, us2), xs) -- 0 < cx + M ⇔ -M/c <  x
+              else (((negateV 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 ]
+
+solve :: VarSet -> [LA.Atom Rational] -> Maybe (Model Rational)
+solve vs cs = msum [solve' vs cs2 | cs2 <- unDNF (constraintsToDNF cs)]
+
+solve' :: VarSet -> [Lit] -> Maybe (Model Rational)
+solve' vs cs = listToMaybe $ do
+  (ys,mt) <- projectN' vs =<< maybeToList (simplify cs)
+  guard $ Just [] == simplify ys
+  return $ mt IM.empty
+
+evalBounds :: Model Rational -> BoundsR -> Interval Rational
+evalBounds model (ls1,ls2,us1,us2) =
+  foldl' Interval.intersection Interval.whole $ 
+    [ Finite (evalRat model x) <=..< PosInf | x <- ls1 ] ++
+    [ Finite (evalRat model x) <..<  PosInf | x <- ls2 ] ++
+    [ NegInf <..<= Finite (evalRat model x) | x <- us1 ] ++
+    [ NegInf <..<  Finite (evalRat model x) | x <- us2 ]
+
+-- ---------------------------------------------------------------------------
+
+gcd' :: [Integer] -> Integer
+gcd' [] = 1
+gcd' xs = foldl1' gcd xs
+
+-- ---------------------------------------------------------------------------
diff --git a/src/Algorithm/FourierMotzkin/FOL.hs b/src/Algorithm/FourierMotzkin/FOL.hs
new file mode 100644
--- /dev/null
+++ b/src/Algorithm/FourierMotzkin/FOL.hs
@@ -0,0 +1,59 @@
+{-# OPTIONS_GHC -Wall #-}
+module Algorithm.FourierMotzkin.FOL
+    ( solveFormula
+    , eliminateQuantifiers
+    , eliminateQuantifiers'
+    )
+    where
+
+import Control.Monad
+import qualified Data.IntSet as IS
+
+import Algebra.Lattice.Boolean
+
+import Data.ArithRel
+import Data.DNF
+import qualified Data.FOL.Arith as FOL
+import qualified Data.LA.FOL as LAFOL
+import Data.Var
+
+import Algorithm.FourierMotzkin.Core
+
+-- ---------------------------------------------------------------------------
+
+solveFormula :: [Var] -> FOL.Formula (FOL.Atom Rational) -> FOL.SatResult Rational
+solveFormula vs formula =
+  case eliminateQuantifiers' formula of
+    Nothing -> FOL.Unknown
+    Just dnf ->
+      case msum [solve' (IS.fromList vs) xs | xs <- unDNF dnf] of
+        Nothing -> FOL.Unsat
+        Just m -> FOL.Sat m
+
+eliminateQuantifiers :: FOL.Formula (FOL.Atom Rational) -> Maybe (FOL.Formula (FOL.Atom Rational))
+eliminateQuantifiers phi = do
+  dnf <- eliminateQuantifiers' phi
+  return $ orB $ map (andB . map (LAFOL.toFOLFormula . toLAAtom)) $ unDNF dnf
+
+eliminateQuantifiers' :: FOL.Formula (FOL.Atom Rational) -> Maybe (DNF Lit)
+eliminateQuantifiers' = f
+  where
+    f FOL.T = return true
+    f FOL.F = return false
+    f (FOL.Atom (Rel a op b)) = do
+       a' <- LAFOL.fromFOLExpr a
+       b' <- LAFOL.fromFOLExpr b
+       return $ fromLAAtom $ Rel a' op b'
+    f (FOL.And a b) = liftM2 (.&&.) (f a) (f b)
+    f (FOL.Or a b) = liftM2 (.||.) (f a) (f b)
+    f (FOL.Not a) = f (FOL.pushNot a)
+    f (FOL.Imply a b) = f (FOL.Or (FOL.Not a) b)
+    f (FOL.Equiv a b) = f (FOL.And (FOL.Imply a b) (FOL.Imply b a))
+    f (FOL.Forall v a) = do
+      dnf <- f (FOL.Exists v (FOL.pushNot a))
+      return (notB dnf)
+    f (FOL.Exists v a) = do
+      dnf <- f a
+      return $ orB [DNF $ map fst $ project' v xs | xs <- unDNF dnf]
+
+-- ---------------------------------------------------------------------------
diff --git a/src/Algorithm/LPSolver.hs b/src/Algorithm/LPSolver.hs
--- a/src/Algorithm/LPSolver.hs
+++ b/src/Algorithm/LPSolver.hs
@@ -25,12 +25,12 @@
 import qualified Data.IntMap as IM
 import qualified Data.IntSet as IS
 import Data.OptDir
+import Data.VectorSpace
 
-import Data.Expr
 import Data.ArithRel
-import Data.Linear
 import qualified Data.LA as LA
 import qualified Data.Interval as Interval
+import Data.Var
 import qualified Algorithm.Simplex as Simplex
 import qualified Algorithm.BoundsInference as BI
 
@@ -101,7 +101,7 @@
     Ge -> do
       v1 <- gensym -- surplus variable
       v2 <- gensym -- artificial variable
-      putTableau $ Simplex.setRow v2 tbl (LA.coeffMap (e .-. LA.var v1), b)
+      putTableau $ Simplex.setRow v2 tbl (LA.coeffMap (e ^-^ LA.var v1), b)
       addArtificialVariable v2
     Eql -> do
       v <- gensym -- artificial variable
@@ -118,14 +118,14 @@
 addConstraint2 c = do
   Rel lhs rop rhs <- expandDefs' c
   let
-    (b', e) = LA.extract LA.unitVar (lhs .-. rhs)
+    (b', e) = LA.extract LA.unitVar (lhs ^-^ rhs)
     b = - b'
   case rop of
     Le -> f e b
-    Ge -> f (lnegate e) (negate b)
+    Ge -> f (negateV e) (negate b)
     Eql -> do
       f e b
-      f (lnegate e) (negate b)
+      f (negateV e) (negate b)
     _ -> error $ "addConstraint does not support " ++ show rop
   where
     -- -x≤b で -b≤0 なら追加しない。ad hoc なので一般化したい。
@@ -158,7 +158,7 @@
   forM_ (IS.toList fvs) $ \v -> do
     v1 <- gensym
     v2 <- gensym
-    define v (LA.var v1 .-. LA.var v2)
+    define v (LA.var v1 ^-^ LA.var v2)
   mapM_ addConstraint cs'
 
 getModel :: Fractional r => VarSet -> LP r (Model r)
@@ -200,10 +200,10 @@
 
 normalizeConstraint :: forall r. Real r => LA.Atom r -> (LA.Expr r, RelOp, r)
 normalizeConstraint (Rel a op b)
-  | rhs < 0   = (lnegate lhs, flipOp op, negate rhs)
+  | rhs < 0   = (negateV lhs, flipOp op, negate rhs)
   | otherwise = (lhs, op, rhs)
   where
-    (c, lhs) = LA.extract LA.unitVar (a .-. b)
+    (c, lhs) = LA.extract LA.unitVar (a ^-^ b)
     rhs = - c
 
 collectNonnegVars :: forall r. (RealFrac r) => [LA.Atom r] -> VarSet -> (VarSet, [LA.Atom r])
@@ -212,11 +212,11 @@
     vs = vars cs
     bounds = BI.inferBounds initialBounds cs ivs 1000
       where
-        initialBounds = IM.fromList [(v, Interval.univ) | v <- IS.toList vs]
+        initialBounds = IM.fromList [(v, Interval.whole) | v <- IS.toList vs]
     nonnegVars = IS.filter f vs
       where
         f v = case Interval.lowerBound (bounds IM.! v) of
-                Just (_, lb) | 0 <= lb -> True
+                Interval.Finite lb | 0 <= lb -> True
                 _ -> False
 
     isTriviallyTrue :: LA.Atom r -> Bool
@@ -224,26 +224,30 @@
       case op of
         Le ->
           case ub of
-            Nothing -> False
-            Just (_, val) -> val <= 0
+            Interval.PosInf -> False
+            Interval.Finite val -> val <= 0
+            Interval.NegInf -> True -- should not happen
         Ge ->
           case lb of
-            Nothing -> False
-            Just (_, val) -> val >= 0
+            Interval.NegInf -> False
+            Interval.Finite val -> val >= 0
+            Interval.PosInf -> True -- should not happen
         Lt ->
           case ub of
-            Nothing -> False
-            Just (incl, val) -> val < 0 || (not incl && val <= 0)
+            Interval.PosInf -> False
+            Interval.Finite val -> val < 0 || (not inUB && val <= 0)
+            Interval.NegInf -> True -- should not happen
         Gt ->
           case lb of
-            Nothing -> False
-            Just (incl, val) -> val > 0 || (not incl && val >= 0)
-        Eql -> isTriviallyTrue (c .<=. lzero) && isTriviallyTrue (c .>=. lzero)
-        NEq -> isTriviallyTrue (c .<. lzero) || isTriviallyTrue (c .>. lzero)
+            Interval.NegInf -> False
+            Interval.Finite val -> val > 0 || (not inLB && val >= 0)
+            Interval.PosInf -> True -- should not happen
+        Eql -> isTriviallyTrue (c .<=. zeroV) && isTriviallyTrue (c .>=. zeroV)
+        NEq -> isTriviallyTrue (c .<. zeroV) || isTriviallyTrue (c .>. zeroV)
       where
-        c = a .-. b
+        c = a ^-^ b
         i = LA.computeInterval bounds c
-        lb = Interval.lowerBound i
-        ub = Interval.upperBound i
+        (lb, inLB) = Interval.lowerBound' i
+        (ub, inUB) = Interval.upperBound' i
 
 -- ---------------------------------------------------------------------------
diff --git a/src/Algorithm/LPSolverHL.hs b/src/Algorithm/LPSolverHL.hs
--- a/src/Algorithm/LPSolverHL.hs
+++ b/src/Algorithm/LPSolverHL.hs
@@ -15,8 +15,7 @@
 -----------------------------------------------------------------------------
 
 module Algorithm.LPSolverHL
-  ( module Data.Expr
-  , module Data.Formula
+  ( OptResult (..)
   , minimize
   , maximize
   , optimize
@@ -24,55 +23,44 @@
   ) 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.VectorSpace
 
-import Data.Expr
 import Data.ArithRel
-import Data.Formula (Atom)
 import qualified Data.LA as LA
+import Data.Var
 import qualified Algorithm.Simplex as Simplex
 import Algorithm.LPSolver
 
 -- ---------------------------------------------------------------------------
 
-maximize :: (RealFrac r) => Expr r -> [Atom r] -> OptResult r
+-- | results of optimization
+data OptResult r = OptUnsat | Unbounded | Optimum r (Model r)
+  deriving (Show, Eq, Ord)
+
+maximize :: (RealFrac r) => LA.Expr r -> [LA.Atom r] -> OptResult r
 maximize = optimize OptMax
 
-minimize :: (RealFrac r) => Expr r -> [Atom r] -> OptResult r
+minimize :: (RealFrac r) => LA.Expr r -> [LA.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 =
+solve :: (RealFrac r) => [LA.Atom r] -> Maybe (Model r)
+solve cs =
   flip evalState (emptySolver vs) $ do
     tableau cs
     ret <- phaseI
     if not ret
-      then return Unsat
+      then return Nothing
       else do
         m <- getModel vs
-        return (Sat m)
+        return (Just m)
   where
     vs = vars cs
 
-optimize' :: (RealFrac r) => OptDir -> LA.Expr r -> [LA.Atom r] -> OptResult r
-optimize' optdir obj 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
@@ -92,19 +80,19 @@
 -- ---------------------------------------------------------------------------
 -- Test cases
 
-example_3_2 :: (Expr Rational, [Atom Rational])
+example_3_2 :: (LA.Expr Rational, [LA.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
+    x1 = LA.var 1
+    x2 = LA.var 2
+    x3 = LA.var 3
+    obj = 3*^x1 ^+^ 2*^x2 ^+^ 3*^x3
+    cond = [ 2*^x1 ^+^    x2 ^+^    x3 .<=. LA.constant 2
+           ,    x1 ^+^ 2*^x2 ^+^ 3*^x3 .<=. LA.constant 5
+           , 2*^x1 ^+^ 2*^x2 ^+^    x3 .<=. LA.constant 6
+           , x1 .>=. LA.constant 0
+           , x2 .>=. LA.constant 0
+           , x3 .>=. LA.constant 0
            ]
 
 test_3_2 :: Bool
@@ -112,22 +100,22 @@
   uncurry maximize example_3_2 == 
   Optimum (27/5) (IM.fromList [(1,1/5),(2,0),(3,8/5)])
 
-example_3_5 :: (Expr Rational, [Atom Rational])
+example_3_5 :: (LA.Expr Rational, [LA.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
+    x1 = LA.var 1
+    x2 = LA.var 2
+    x3 = LA.var 3
+    x4 = LA.var 4
+    x5 = LA.var 5
+    obj = (-2)*^x1 ^+^ 4*^x2 ^+^ 7*^x3 ^+^ x4 ^+^ 5*^x5
+    cond = [ (-1)*^x1 ^+^    x2 ^+^ 2*^x3 ^+^    x4 ^+^ 2*^x5 .==. LA.constant 7
+           , (-1)*^x1 ^+^ 2*^x2 ^+^ 3*^x3 ^+^    x4 ^+^    x5 .==. LA.constant 6
+           , (-1)*^x1 ^+^    x2 ^+^    x3 ^+^ 2*^x4 ^+^    x5 .==. LA.constant 4
+           , x2 .>=. LA.constant 0
+           , x3 .>=. LA.constant 0
+           , x4 .>=. LA.constant 0
+           , x5 .>=. LA.constant 0
            ]
 
 test_3_5 :: Bool
@@ -135,16 +123,16 @@
   uncurry minimize example_3_5 ==
   Optimum 19 (IM.fromList [(1,-1),(2,0),(3,1),(4,0),(5,2)])
 
-example_4_1 :: (Expr Rational, [Atom Rational])
+example_4_1 :: (LA.Expr Rational, [LA.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
+    x1 = LA.var 1
+    x2 = LA.var 2
+    obj = 2*^x1 ^+^ x2
+    cond = [ (-1)*^x1 ^+^ x2 .>=. LA.constant 2
+           ,       x1 ^+^ x2 .<=. LA.constant 1
+           , x1 .>=. LA.constant 0
+           , x2 .>=. LA.constant 0
            ]
 
 test_4_1 :: Bool
@@ -152,16 +140,16 @@
   uncurry maximize example_4_1 ==
   OptUnsat
 
-example_4_2 :: (Expr Rational, [Atom Rational])
+example_4_2 :: (LA.Expr Rational, [LA.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
+    x1 = LA.var 1
+    x2 = LA.var 2
+    obj = 2*^x1 ^+^ x2
+    cond = [ (-1)*^x1 ^-^ x2 .<=. LA.constant 10
+           ,    2*^x1 ^-^ x2 .<=. LA.constant 40
+           , x1 .>=. LA.constant 0
+           , x2 .>=. LA.constant 0
            ]
 
 test_4_2 :: Bool
@@ -169,16 +157,16 @@
   uncurry maximize example_4_2 ==
   Unbounded
 
-example_4_3 :: (Expr Rational, [Atom Rational])
+example_4_3 :: (LA.Expr Rational, [LA.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
+    x1 = LA.var 1
+    x2 = LA.var 2
+    obj = 6*^x1 ^-^ 2*^x2
+    cond = [ 2*^x1 ^-^ x2 .<=. LA.constant 2
+           , x1 .<=. LA.constant 4
+           , x1 .>=. LA.constant 0
+           , x2 .>=. LA.constant 0
            ]
 
 test_4_3 :: Bool
@@ -186,17 +174,17 @@
   uncurry maximize example_4_3 ==
   Optimum 12 (IM.fromList [(1,4),(2,6)])
 
-example_4_5 :: (Expr Rational, [Atom Rational])
+example_4_5 :: (LA.Expr Rational, [LA.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
+    x1 = LA.var 1
+    x2 = LA.var 2
+    obj = 2*^x1 ^+^ x2
+    cond = [ 4*^x1 ^+^ 3*^x2 .<=. LA.constant 12
+           , 4*^x1 ^+^    x2 .<=. LA.constant 8
+           , 4*^x1 ^-^    x2 .<=. LA.constant 8
+           , x1 .>=. LA.constant 0
+           , x2 .>=. LA.constant 0
            ]
 
 test_4_5 :: Bool
@@ -204,22 +192,22 @@
   uncurry maximize example_4_5 ==
   Optimum 5 (IM.fromList [(1,3/2),(2,2)])
 
-example_4_6 :: (Expr Rational, [Atom Rational])
+example_4_6 :: (LA.Expr Rational, [LA.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
+    x1 = LA.var 1
+    x2 = LA.var 2
+    x3 = LA.var 3
+    x4 = LA.var 4
+    obj = 20*^x1 ^+^ (1/2)*^x2 ^-^ 6*^x3 ^+^ (3/4)*^x4
+    cond = [     x1 .<=. LA.constant 2
+           ,  8*^x1 ^-^        x2 ^+^ 9*^x3 ^+^ (1/4)*^x4 .<=. LA.constant 16
+           , 12*^x1 ^-^ (1/2)*^x2 ^+^ 3*^x3 ^+^ (1/2)*^x4 .<=. LA.constant 24
+           , x2 .<=. LA.constant 1
+           , x1 .>=. LA.constant 0
+           , x2 .>=. LA.constant 0
+           , x3 .>=. LA.constant 0
+           , x4 .>=. LA.constant 0
            ]
 
 test_4_6 :: Bool
@@ -227,22 +215,22 @@
   uncurry maximize example_4_6 ==
   Optimum (165/4) (IM.fromList [(1,2),(2,1),(3,0),(4,1)])
 
-example_4_7 :: (Expr Rational, [Atom Rational])
+example_4_7 :: (LA.Expr Rational, [LA.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
+    x1 = LA.var 1
+    x2 = LA.var 2
+    x3 = LA.var 3
+    x4 = LA.var 4
+    obj = x1 ^+^ 1.5*^x2 ^+^ 5*^x3 ^+^ 2*^x4
+    cond = [ 3*^x1 ^+^ 2*^x2 ^+^    x3 ^+^ 4*^x4 .<=. LA.constant 6
+           , 2*^x1 ^+^    x2 ^+^ 5*^x3 ^+^    x4 .<=. LA.constant 4
+           , 2*^x1 ^+^ 6*^x2 ^-^ 4*^x3 ^+^ 8*^x4 .==. LA.constant 0
+           ,    x1 ^+^ 3*^x2 ^-^ 2*^x3 ^+^ 4*^x4 .==. LA.constant 0
+           , x1 .>=. LA.constant 0
+           , x2 .>=. LA.constant 0
+           , x3 .>=. LA.constant 0
+           , x4 .>=. LA.constant 0
            ]
 
 test_4_7 :: Bool
@@ -251,21 +239,21 @@
   Optimum (48/11) (IM.fromList [(1,0),(2,0),(3,81),(4,41)])
 
 -- 退化して巡回の起こるKuhnの7変数3制約の例
-kuhn_7_3 :: (Expr Rational, [Atom Rational])
+kuhn_7_3 :: (LA.Expr Rational, [LA.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
+    [x1,x2,x3,x4,x5,x6,x7] = map LA.var [1..7]
+    obj = (-2)*^x4 ^+^ (-3)*^x5 ^+^ x6 ^+^ 12*^x7
+    cond = [ x1 ^-^     2*^x4 ^-^ 9*^x5 ^+^        x6 ^+^   9*^x7 .==. LA.constant 0
+           , x2 ^+^ (1/3)*^x4 ^+^    x5 ^-^ (1/3)*^x6 ^-^   2*^x7 .==. LA.constant 0
+           , x3 ^+^     2*^x4 ^+^ 3*^x5 ^-^        x6 ^-^  12*^x7 .==. LA.constant 2
+           , x1 .>=. LA.constant 0
+           , x2 .>=. LA.constant 0
+           , x3 .>=. LA.constant 0
+           , x4 .>=. LA.constant 0
+           , x5 .>=. LA.constant 0
+           , x6 .>=. LA.constant 0
+           , x7 .>=. LA.constant 0
            ]
 
 test_kuhn_7_3 :: Bool
diff --git a/src/Algorithm/LPUtil.hs b/src/Algorithm/LPUtil.hs
--- a/src/Algorithm/LPUtil.hs
+++ b/src/Algorithm/LPUtil.hs
@@ -9,12 +9,12 @@
 import qualified Data.IntMap as IM
 import qualified Data.IntSet as IS
 import Data.Maybe
+import Data.VectorSpace
 
-import Data.Expr (Var, VarSet, VarMap, Variables (..), Model (..))
 import Data.ArithRel
-import Data.Linear
 import qualified Data.LA as LA
 import qualified Data.Interval as Interval
+import Data.Var
 import qualified Algorithm.BoundsInference as BI
 
 toStandardForm
@@ -43,7 +43,7 @@
   where
     vs = vars obj `IS.union` vars cs
     v1 = if IS.null vs then 0 else IS.findMax vs + 1
-    initialBounds = IM.fromList [(v, Interval.univ) | v <- IS.toList vs]
+    initialBounds = IM.fromList [(v, Interval.whole) | v <- IS.toList vs]
     bounds = BI.inferBounds initialBounds cs IS.empty 10
 
     gensym :: M Var
@@ -55,35 +55,35 @@
     m = flip evalState v1 $ do
       s <- liftM IM.unions $ forM (IM.toList bounds) $ \(v,i) -> do
         case Interval.lowerBound i of
-          Nothing -> do
+          Interval.NegInf -> do
             v1 <- gensym
             v2 <- gensym
-            return $ IM.singleton v (LA.var v1 .-. LA.var v2)
-          Just (_,lb)
+            return $ IM.singleton v (LA.var v1 ^-^ LA.var v2)
+          Interval.Finite lb
             | lb >= 0   -> return IM.empty
             | otherwise -> do
                 v1 <- gensym
-                return $ IM.singleton v (LA.var v1 .-. LA.constant lb)
+                return $ IM.singleton v (LA.var v1 ^-^ LA.constant lb)
       let obj2 = LA.applySubst s obj
 
       cs2 <- liftM concat $ forM cs $ \(Rel lhs op rhs) -> do
-        case LA.extract LA.unitVar (LA.applySubst s (lhs .-. rhs)) of
+        case LA.extract LA.unitVar (LA.applySubst s (lhs ^-^ rhs)) of
           (c,e) -> do
             let (lhs2,op2,rhs2) =
                   if -c >= 0
                   then (e,op,-c)
-                  else (lnegate e, flipOp op, c)
+                  else (negateV e, flipOp op, c)
             case op2 of
               Eql -> return [(lhs2,rhs2)]
               Le  -> do
                 v <- gensym
-                return [(lhs2 .+. LA.var v, rhs2)]
+                return [(lhs2 ^+^ LA.var v, rhs2)]
               Ge  -> do
                 case LA.terms lhs2 of
                   [(1,_)] | rhs2<=0 -> return []
                   _ -> do
                     v <- gensym
-                    return [(lhs2 .-. LA.var v, rhs2)]
+                    return [(lhs2 ^-^ LA.var v, rhs2)]
               _   -> error $ "LPUtil.toStandardForm: " ++ show op2 ++ " is not supported"
 
       assert (and [isNothing $ LA.lookupCoeff LA.unitVar c | (c,_) <- cs2]) $ return ()
diff --git a/src/Algorithm/MIPSolver2.hs b/src/Algorithm/MIPSolver2.hs
--- a/src/Algorithm/MIPSolver2.hs
+++ b/src/Algorithm/MIPSolver2.hs
@@ -67,6 +67,7 @@
 import qualified Data.Map as Map
 import qualified Data.Sequence as Seq
 import qualified Data.Foldable as F
+import Data.VectorSpace
 import Data.Time
 import System.CPUTime
 import System.Timeout
@@ -76,7 +77,6 @@
 import Data.ArithRel ((.<=.), (.>=.))
 import qualified Algorithm.Simplex2 as Simplex2
 import Algorithm.Simplex2 (OptResult (..), Var, Model)
-import Data.Linear
 import Util (isInteger, fracPart)
 
 data Solver
@@ -459,16 +459,16 @@
     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)
+    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 $ c *^ (LA.constant uj ^-^ LA.var xj)
 
-  return $ lsum xs1 .+. lsum xs2 .>=. LA.constant 1
+  return $ sumV xs1 ^+^ sumV xs2 .>=. LA.constant 1
 
 -- TODO: Simplex2をδに対応させたら、xi, xj がδを含まない有理数であるという条件も必要
 canDeriveGomoryCut :: Simplex2.Solver -> Var -> IO Bool
diff --git a/src/Algorithm/MIPSolverHL.hs b/src/Algorithm/MIPSolverHL.hs
--- a/src/Algorithm/MIPSolverHL.hs
+++ b/src/Algorithm/MIPSolverHL.hs
@@ -26,13 +26,11 @@
 -----------------------------------------------------------------------------
 
 module Algorithm.MIPSolverHL
-  ( module Data.Expr
-  , module Data.Formula
-  , module Data.OptDir
+  ( module Data.OptDir
+  , OptResult (..)
   , minimize
   , maximize
   , optimize
---  , solve
   ) where
 
 import Control.Exception
@@ -42,43 +40,21 @@
 import Data.List (maximumBy)
 import qualified Data.IntMap as IM
 import qualified Data.IntSet as IS
-import Data.Ratio
 import Data.OptDir
+import Data.VectorSpace
 
-import Data.Expr
 import Data.ArithRel
-import Data.Formula (Atom)
-import Data.Linear
+import Data.Var
 import qualified Data.LA as LA
 import qualified Algorithm.Simplex as Simplex
 import qualified Algorithm.LPSolver as LPSolver
 import Algorithm.LPSolver
+import Algorithm.LPSolverHL (OptResult (..))
 import qualified Algorithm.OmegaTest as OmegaTest
 import Util (isInteger, fracPart)
 
 -- ---------------------------------------------------------------------------
 
-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
@@ -94,8 +70,14 @@
 
 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 = 
+maximize :: RealFrac r => LA.Expr r -> [LA.Atom r] -> VarSet -> OptResult r
+maximize = optimize OptMax
+
+minimize :: RealFrac r => LA.Expr r -> [LA.Atom r] -> VarSet -> OptResult r
+minimize = optimize OptMin
+
+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
@@ -112,7 +94,7 @@
                  original problem is unbounded or unsatisfiable
                  when LP relaxation is unbounded.
             -}
-            case OmegaTest.solveQFLA (map conv cs) ivs of
+            case OmegaTest.solveQFLA OmegaTest.defaultOptions (vars cs `IS.union` ivs) (map conv cs) ivs of
               Nothing -> OptUnsat
               Just _ -> Unbounded        
     Right (node0, ivs2) -> 
@@ -133,7 +115,7 @@
   ivs2 <- liftM IS.unions $ forM (IS.toList fvs) $ \v -> do
     v1 <- gensym
     v2 <- gensym
-    define v (LA.var v1 .-. LA.var v2)
+    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
@@ -244,11 +226,11 @@
     x2 = LA.var 2
     x3 = LA.var 3
     x4 = LA.var 4
-    obj = x1 .+. 2 .*. x2 .+. 3 .*. x3 .+. x4
+    obj = x1 ^+^ 2 *^ x2 ^+^ 3 *^ x3 ^+^ x4
     cs =
-      [ (-1) .*. x1 .+. x2 .+. x3 .+. 10.*.x4 .<=. LA.constant 20
-      , x1 .-. 3 .*. x2 .+. x3 .<=. LA.constant 30
-      , x2 .-. 3.5 .*. x4 .==. LA.constant 0
+      [ (-1) *^ x1 ^+^ x2 ^+^ x3 ^+^ 10*^x4 .<=. LA.constant 20
+      , x1 ^-^ 3 *^ x2 ^+^ x3 .<=. LA.constant 30
+      , x2 ^-^ 3.5 *^ x4 .==. LA.constant 0
       , LA.constant 0 .<=. x1
       , x1 .<=. LA.constant 40
       , LA.constant 0 .<=. x2
@@ -263,7 +245,7 @@
   where
     (optdir, obj, cs, ivs) = example1
     result, expected :: OptResult Rational
-    result = optimize' optdir obj cs ivs
+    result = optimize optdir obj cs ivs
     expected = Optimum (245/2) (IM.fromList [(1,40),(2,21/2),(3,39/2),(4,3)])
 
 test1' :: Bool
@@ -273,7 +255,7 @@
     f OptMin = OptMax
     f OptMax = OptMin
     result, expected :: OptResult Rational
-    result = optimize' (f optdir) (lnegate obj) cs ivs
+    result = optimize (f optdir) (negateV obj) cs ivs
     expected = Optimum (-245/2) (IM.fromList [(1,40),(2,21/2),(3,39/2),(4,3)])
 
 -- 『数理計画法の基礎』(坂和 正敏) p.109 例 3.8
@@ -282,11 +264,11 @@
   where
     optdir = OptMin
     [x1,x2,x3] = map LA.var [1..3]
-    obj = (-1) .*. x1 .-. 3 .*. x2 .-. 5 .*. x3
+    obj = (-1) *^ x1 ^-^ 3 *^ x2 ^-^ 5 *^ x3
     cs =
-      [ 3 .*. x1 .+. 4 .*. x2 .<=. LA.constant 10
-      , 2 .*. x1 .+. x2 .+. x3 .<=. LA.constant 7
-      , 3.*.x1 .+. x2 .+. 4 .*. x3 .==. LA.constant 12
+      [ 3 *^ x1 ^+^ 4 *^ x2 .<=. LA.constant 10
+      , 2 *^ x1 ^+^ x2 ^+^ x3 .<=. LA.constant 7
+      , 3*^x1 ^+^ x2 ^+^ 4 *^ x3 .==. LA.constant 12
       , LA.constant 0 .<=. x1
       , LA.constant 0 .<=. x2
       , LA.constant 0 .<=. x3
@@ -297,7 +279,7 @@
 test2 = result == expected
   where
     result, expected :: OptResult Rational
-    result = optimize' optdir obj cs ivs
+    result = optimize optdir obj cs ivs
     expected = Optimum (-37/2) (IM.fromList [(1,0),(2,2),(3,5/2)])
     (optdir, obj, cs, ivs) = example2
 
diff --git a/src/Algorithm/OmegaTest.hs b/src/Algorithm/OmegaTest.hs
--- a/src/Algorithm/OmegaTest.hs
+++ b/src/Algorithm/OmegaTest.hs
@@ -1,5 +1,4 @@
 {-# OPTIONS_GHC -Wall #-}
-{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Algorithm.OmegaTest
@@ -8,7 +7,7 @@
 -- 
 -- Maintainer  :  masahiro.sakai@gmail.com
 -- Stability   :  provisional
--- Portability :  non-portable (MultiParamTypeClasses, FunctionalDependencies)
+-- Portability :  portable
 --
 -- (incomplete) implementation of Omega Test
 --
@@ -29,6 +28,10 @@
     ( Model
     , solve
     , solveQFLA
+    , Options (..)
+    , defaultOptions
+    , checkRealNoCheck
+    , checkRealByFM
     ) where
 
 import Control.Monad
@@ -38,17 +41,41 @@
 import Data.Ratio
 import qualified Data.IntMap as IM
 import qualified Data.IntSet as IS
+import Data.VectorSpace
 
-import Data.Expr
-import Data.Formula
-import Data.Linear
+import Algebra.Lattice.Boolean
+
+import Data.ArithRel
+import Data.DNF
 import qualified Data.LA as LA
+import Data.Var
 import Util (combineMaybe)
 import qualified Algorithm.FourierMotzkin as FM
-import Algorithm.FourierMotzkin (Lit (..), Rat)
+import Algorithm.FourierMotzkin.Core (Lit (..), Rat, toLAAtom)
 
 -- ---------------------------------------------------------------------------
 
+data Options
+  = Options
+  { optCheckReal :: VarSet -> [LA.Atom Rational] -> Bool
+  }
+
+defaultOptions :: Options
+defaultOptions =
+  Options
+  { optCheckReal =
+      -- checkRealNoCheck
+      checkRealByFM
+  }
+
+checkRealNoCheck :: VarSet -> [LA.Atom Rational] -> Bool
+checkRealNoCheck _ _ = True
+
+checkRealByFM :: VarSet -> [LA.Atom Rational] -> Bool
+checkRealByFM vs as = isJust $ FM.solve vs as
+
+-- ---------------------------------------------------------------------------
+
 type ExprZ = LA.Expr Integer
 
 -- 制約集合の単純化
@@ -72,20 +99,20 @@
 -- Note that constants may be floored by division
 leZ e1 e2 = Nonneg (LA.mapCoeff (`div` d) e)
   where
-    e = e2 .-. e1
+    e = e2 ^-^ e1
     d = abs $ gcd' [c | (c,v) <- LA.terms e, v /= LA.unitVar]
-ltZ e1 e2 = (e1 .+. LA.constant 1) `leZ` e2
+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)]]
+    then DNF [[Nonneg e, Nonneg (negateV e)]]
     else false
   where
     e = LA.mapCoeff (`div` d) e3
-    e3 = e1 .-. e2
+    e3 = e1 ^-^ e2
     d = abs $ gcd' [c | (c,v) <- LA.terms e3, v /= LA.unitVar]
 
 -- ---------------------------------------------------------------------------
@@ -100,24 +127,25 @@
 collectBoundsZ v = foldr phi (([],[]),[])
   where
     phi :: Lit -> (BoundsZ,[Lit]) -> (BoundsZ,[Lit])
-    phi (Pos t) x = phi (Nonneg (t .-. LA.constant 1)) x
+    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
+            GT -> (((negateV t', c) : ls, us), xs) -- 0 ≤ cx + M ⇔ -M/c ≤ x
             LT -> ((ls, (t', negate c) : us), xs)   -- 0 ≤ cx + M ⇔ x ≤ M/-c
 
 isExact :: BoundsZ -> Bool
 isExact (ls,us) = and [a==1 || b==1 | (_,a)<-ls , (_,b)<-us]
 
-solve' :: [Var] -> [Lit] -> Maybe (Model Integer)
-solve' vs2 xs = simplify xs >>= go vs2
+solve' :: Options -> [Var] -> [Lit] -> Maybe (Model Integer)
+solve' opt vs2 xs = simplify xs >>= go vs2
   where
     go :: [Var] -> [Lit] -> Maybe (Model Integer)
     go [] [] = return IM.empty
     go [] _  = mzero
+    go vs ys | not (optCheckReal opt (IS.fromList vs) (map toLAAtom ys)) = mzero
     go vs ys =
       if isExact bnd
         then case1
@@ -126,7 +154,7 @@
         (v,vs',bnd@(ls,us),rest) = chooseVariable vs ys
 
         case1 = do
-          let zs = [ LA.constant ((a-1)*(b-1)) `leZ` (a .*. d .-. b .*. c)
+          let zs = [ LA.constant ((a-1)*(b-1)) `leZ` (a *^ d ^-^ b *^ c)
                    | (c,a)<-ls , (d,b)<-us ]
           model <- go vs' =<< simplify (zs ++ rest)
           case pickupZ (evalBoundsZ model bnd) of
@@ -134,7 +162,7 @@
             Just val -> return $ IM.insert v val model
 
         case2 = msum
-          [ do eq <- isZero $ a' .*. LA.var v .-. (c' .+. LA.constant k)
+          [ do eq <- isZero $ a' *^ LA.var v ^-^ (c' ^+^ LA.constant k)
                let (vs'', lits'', mt) = elimEq eq (v:vs') ys
                model <- go vs'' =<< simplify lits''
                return $ mt model
@@ -162,16 +190,16 @@
     then
       case LA.extract xk e of
         (_, e') ->
-          let xk_def = signum ak .*. lnegate e'
+          let xk_def = signum ak *^ negateV e'
           in ( vs
              , [applySubst1Lit xk xk_def lit | lit <- lits]
              , \model -> IM.insert xk (LA.evalExpr model xk_def) model
              )
     else
       let m = abs ak + 1
-          xk_def = (- signum ak * m) .*. LA.var sigma .+.
+          xk_def = (- signum ak * m) *^ LA.var sigma ^+^
                      LA.fromTerms [(signum ak * (a `zmod` m), x) | (a,x) <- LA.terms e, x /= xk]
-          e2 = (- abs ak) .*. LA.var sigma .+. 
+          e2 = (- abs ak) *^ LA.var sigma ^+^ 
                   LA.fromTerms [((floor (a%m + 1/2) + (a `zmod` m)), x) | (a,x) <- LA.terms e, x /= xk]
                -- LA.applySubst1 xk xk_def e を normalize したもの
       in case elimEq e2 (sigma : vs) [applySubst1Lit xk xk_def lit | lit <- lits] of
@@ -218,11 +246,10 @@
 
 -- ---------------------------------------------------------------------------
 
-solve :: [LA.Atom Rational] -> Maybe (Model Integer)
-solve cs = msum [solve' (IS.toList vs) lits | lits <- unDNF dnf]
+solve :: Options -> VarSet -> [LA.Atom Rational] -> Maybe (Model Integer)
+solve opt vs cs = msum [solve' opt (IS.toList vs) lits | lits <- unDNF dnf]
   where
     dnf = andB (map f cs)
-    vs = vars cs
     f (Rel lhs op rhs) =
       case op of
         Lt  -> DNF [[a `ltZ` b]]
@@ -234,20 +261,20 @@
       where
         (e1,c1) = g lhs
         (e2,c2) = g rhs
-        a = c2 .*. e1
-        b = c1 .*. e2
+        a = c2 *^ e1
+        b = c1 *^ e2
     g :: LA.Expr Rational -> (ExprZ, Integer)
     g a = (LA.mapCoeff (\c -> floor (c * fromInteger d)) a, d)
       where
         d = foldl' lcm 1 [denominator c | (c,_) <- LA.terms a]
 
-solveQFLA :: [LA.Atom Rational] -> VarSet -> Maybe (Model Rational)
-solveQFLA cs ivs = listToMaybe $ do
+solveQFLA :: Options -> VarSet -> [LA.Atom Rational] -> VarSet -> Maybe (Model Rational)
+solveQFLA opt vs cs ivs = listToMaybe $ do
   (cs2, mt) <- FM.projectN rvs cs
-  m <- maybeToList $ solve cs2
+  m <- maybeToList $ solve opt ivs cs2
   return $ mt $ IM.map fromInteger m
   where
-    rvs = vars cs `IS.difference` ivs
+    rvs = vs `IS.difference` ivs
 
 -- ---------------------------------------------------------------------------
 
diff --git a/src/Algorithm/OmegaTest/Misc.hs b/src/Algorithm/OmegaTest/Misc.hs
new file mode 100644
--- /dev/null
+++ b/src/Algorithm/OmegaTest/Misc.hs
@@ -0,0 +1,41 @@
+{-# OPTIONS_GHC -Wall #-}
+module Algorithm.OmegaTest.Misc
+  ( checkRealByCAD
+  , checkRealBySimplex
+  ) where
+
+import Control.Monad
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+import Data.Maybe
+import qualified Data.Set as Set
+import System.IO.Unsafe
+
+import qualified Data.LA as LA
+import qualified Data.Polynomial as P
+import Data.Var
+import qualified Algorithm.CAD as CAD
+import qualified Algorithm.Simplex2 as Simplex2
+
+checkRealByCAD :: VarSet -> [LA.Atom Rational] -> Bool
+checkRealByCAD vs as = isJust $ CAD.solve vs2 (map (fmap f) as)
+  where
+    vs2 = Set.fromAscList $ IS.toAscList vs
+
+    f :: LA.Expr Rational -> P.Polynomial Rational Int
+    f t = P.fromTerms [(c, g x) | (c,x) <- LA.terms t]
+
+    g :: Int -> P.MonicMonomial Int
+    g x
+      | x == LA.unitVar = P.mmOne
+      | otherwise       = P.mmVar x
+
+checkRealBySimplex :: VarSet -> [LA.Atom Rational] -> Bool
+checkRealBySimplex vs as = unsafePerformIO $ do
+  solver <- Simplex2.newSolver
+  s <- liftM IM.fromList $ forM (IS.toList vs) $ \v -> do
+    v2 <- Simplex2.newVar solver
+    return (v, LA.var v2)
+  forM_ as $ \a -> do
+    Simplex2.assertAtomEx solver (fmap (LA.applySubst s) a)
+  Simplex2.check solver
diff --git a/src/Algorithm/Simplex.hs b/src/Algorithm/Simplex.hs
--- a/src/Algorithm/Simplex.hs
+++ b/src/Algorithm/Simplex.hs
@@ -41,11 +41,11 @@
 import qualified Data.IntMap as IM
 import qualified Data.IntSet as IS
 import Data.OptDir
+import Data.VectorSpace
 import Control.Exception
 
-import Data.Expr
-import Data.Linear
 import qualified Data.LA as LA
+import Data.Var
 
 -- ---------------------------------------------------------------------------
 
@@ -113,7 +113,7 @@
   where
     row =
       case LA.extract LA.unitVar e of
-        (c, e') -> (LA.coeffMap (lnegate e'), c)
+        (c, e') -> (LA.coeffMap (negateV e'), c)
 
 copyObjRow :: (Num r, Eq r) => Tableau r -> Tableau r -> Tableau r
 copyObjRow from to =
@@ -225,7 +225,7 @@
   | otherwise = (True, copyObjRow tbl $ removeArtificialVariables avs $ tbl1')
   where
     optdir = OptMax
-    tbl1 = setObjFun tbl $ lnegate $ lsum [LA.var v | v <- IS.toList avs]
+    tbl1 = setObjFun tbl $ negateV $ sumV [LA.var v | v <- IS.toList avs]
     tbl1' = go tbl1
     go tbl2
       | currentObjValue tbl2 == 0 = tbl2
diff --git a/src/Algorithm/Simplex2.hs b/src/Algorithm/Simplex2.hs
--- a/src/Algorithm/Simplex2.hs
+++ b/src/Algorithm/Simplex2.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE DoAndIfThenElse, TypeSynonymInstances, FlexibleContexts, FlexibleInstances #-}
+{-# LANGUAGE DoAndIfThenElse, TypeFamilies #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Algorithm.Simplex2
@@ -7,7 +7,7 @@
 -- 
 -- Maintainer  :  masahiro.sakai@gmail.com
 -- Stability   :  provisional
--- Portability :  non-portable (DoAndIfThenElse, TypeSynonymInstances, FlexibleContexts, FlexibleInstances)
+-- Portability :  non-portable (DoAndIfThenElse, TypeFamilies)
 --
 -- Naïve implementation of Simplex method
 -- 
@@ -103,12 +103,12 @@
 import Text.Printf
 import Data.Time
 import Data.OptDir
+import Data.VectorSpace
 import System.CPUTime
 
 import qualified Data.LA as LA
 import Data.LA (Atom (..))
 import Data.ArithRel
-import Data.Linear
 import Data.Delta
 import Util (showRational)
 
@@ -143,10 +143,10 @@
 
 newSolver :: SolverValue v => IO (GenericSolver v)
 newSolver = do
-  t <- newIORef (IM.singleton objVar lzero)
+  t <- newIORef (IM.singleton objVar zeroV)
   l <- newIORef IM.empty
   u <- newIORef IM.empty
-  m <- newIORef (IM.singleton objVar lzero)
+  m <- newIORef (IM.singleton objVar zeroV)
   v <- newIORef 0
   ok <- newIORef True
   dir <- newIORef OptMin
@@ -197,7 +197,7 @@
     , svPivotStrategy = pivot
     }  
 
-class (Linear Rational v, Ord v) => SolverValue v where
+class (VectorSpace v, Scalar v ~ Rational, Ord v) => SolverValue v where
   toValue :: Rational -> v
   showValue :: Bool -> v -> String
   model :: GenericSolver v -> IO Model
@@ -250,7 +250,7 @@
 newVar solver = do
   v <- readIORef (svVCnt solver)
   writeIORef (svVCnt solver) $! v+1
-  modifyIORef (svModel solver) (IM.insert v lzero)
+  modifyIORef (svModel solver) (IM.insert v zeroV)
   return v
 
 assertAtom :: Solver -> LA.Atom Rational -> IO ()
@@ -271,8 +271,8 @@
   case op of
     Le  -> assertUpper solver v (toValue rhs')
     Ge  -> assertLower solver v (toValue rhs')
-    Lt  -> assertUpper solver v (toValue rhs' .-. delta)
-    Gt  -> assertLower solver v (toValue rhs' .+. delta)
+    Lt  -> assertUpper solver v (toValue rhs' ^-^ delta)
+    Gt  -> assertLower solver v (toValue rhs' ^+^ delta)
     Eql -> do
       assertLower solver v (toValue rhs')
       assertUpper solver v (toValue rhs')
@@ -281,7 +281,7 @@
 simplifyAtom :: SolverValue v => GenericSolver v -> LA.Atom Rational -> IO (Var, RelOp, Rational)
 simplifyAtom solver (Rel lhs op rhs) = do
   let (lhs',rhs') =
-        case LA.extract LA.unitVar (lhs .-. rhs) of
+        case LA.extract LA.unitVar (lhs ^-^ rhs) of
           (n,e) -> (e, -n)
   case LA.terms lhs' of
     [(1,v)] -> return (v, op, rhs')
@@ -289,7 +289,7 @@
     _ -> do
       defs <- readIORef (svDefDB solver)
       let (c,lhs'') = scale lhs' -- lhs' = lhs'' / c = rhs'
-          rhs'' = c .*. rhs'
+          rhs'' = c *^ rhs'
           op''  = if c < 0 then flipOp op else op
       case Map.lookup lhs'' defs of
         Just v -> do
@@ -301,7 +301,7 @@
           return (v,op'',rhs'')
   where
     scale :: LA.Expr Rational -> (Rational, LA.Expr Rational)
-    scale e = (c, c .*. e)
+    scale e = (c, c *^ e)
       where
         c = c1 * c2
         c1 = fromIntegral $ foldl' lcm 1 [denominator c | (c, _) <- LA.terms e]
@@ -454,8 +454,8 @@
               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)
+                then return (xi, fromJust li ^-^ vi)
+                else return (xi, vi ^-^ fromJust ui)
           return $ Just $ fst $ maximumBy (comparing snd) xs2
 
 {--------------------------------------------------------------------
@@ -572,9 +572,9 @@
     v1 <- getValue solver xi
     li <- getLB solver xi
     ui <- getUB solver xi
-    return [ assert (theta >= lzero) ((xi,v2), theta)
+    return [ assert (theta >= zeroV) ((xi,v2), theta)
            | Just v2 <- [ui | aij > 0] ++ [li | aij < 0]
-           , let theta = (v2 .-. v1) ./. aij ]
+           , let theta = (v2 ^-^ v1) ^/ aij ]
 
   -- β(xj) := β(xj) + θ なので θ を大きく
   case ubs of
@@ -595,9 +595,9 @@
     v1 <- getValue solver xi
     li <- getLB solver xi
     ui <- getUB solver xi
-    return [ assert (theta <= lzero) ((xi,v2), theta)
+    return [ assert (theta <= zeroV) ((xi,v2), theta)
            | Just v2 <- [li | aij > 0] ++ [ui | aij < 0]
-           , let theta = (v2 .-. v1) ./. aij ]
+           , let theta = (v2 ^-^ v1) ^/ aij ]
 
   -- β(xj) := β(xj) + θ なので θ を小さく
   case lbs of
@@ -653,12 +653,12 @@
     return $
       case dir of
         OptMin -> def
-        OptMax -> lnegate def
+        OptMax -> negateV def
   -- normalize to the cases of lower bound violation
   let xi_def =
        if isLBViolated
        then row
-       else lnegate row
+       else negateV row
   ws <- do
     -- select non-basic variable xj such that
     -- (aij > 0 and β(xj) < uj) or (aij < 0 and β(xj) > lj)
@@ -714,12 +714,12 @@
   -- dump solver
 
   v0 <- getValue solver xj
-  let diff = v .-. v0
+  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
+    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
@@ -746,11 +746,11 @@
 
   aj <- getCol solver xj
   let aij = aj IM.! xi
-  let theta = (v .-. (m IM.! xi)) ./. aij
+  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]
+           [(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
diff --git a/src/Converter/CNF2LP.hs b/src/Converter/CNF2LP.hs
deleted file mode 100644
--- a/src/Converter/CNF2LP.hs
+++ /dev/null
@@ -1,77 +0,0 @@
-{-# 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.varInfo = Map.fromList
-          [ ( v
-            , LPFile.VarInfo
-              { LPFile.varName   = v
-              , LPFile.varType   = LPFile.IntegerVariable
-              , LPFile.varBounds = (LPFile.Finite 0, LPFile.Finite 1)
-              }
-            )
-          | v <- vs
-          ]
-      , 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
--- a/src/Converter/MaxSAT2LP.hs
+++ b/src/Converter/MaxSAT2LP.hs
@@ -14,75 +14,12 @@
   ( 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
-  MaxSAT.WCNF
-  { MaxSAT.numVars = nvar
-  , MaxSAT.topCost = top
-  , MaxSAT.clauses = ls
-  } = (lp, mtrans)
-  where
-    lp = LPFile.LP
-      { LPFile.variables = Set.fromList vs
-      , LPFile.dir = LPFile.OptMin
-      , LPFile.objectiveFunction = (Nothing, obj)
-      , LPFile.constraints = cs
-      , LPFile.varInfo = Map.fromList
-          [ ( v
-            , LPFile.VarInfo
-              { LPFile.varName   = v
-              , LPFile.varType   = LPFile.IntegerVariable
-              , LPFile.varBounds = (LPFile.Finite 0, LPFile.Finite 1)
-              }
-            )
-          | v <- vs
-          ]
-      , 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)
+import qualified Converter.MaxSAT2WBO as MaxSAT2WBO
+import qualified Converter.PB2LP as PB2LP
 
-    g :: Map.Map Var Int -> [LPFile.Term]
-    g m = do
-      (v,c) <- Map.toList m
-      return (LPFile.Term (fromIntegral c) ["x" ++ show v])
+convert :: Bool -> MaxSAT.WCNF -> (LPFile.LP, Map.Map LPFile.Var Rational -> Model)
+convert useIndicator wcnf = PB2LP.convertWBO useIndicator (MaxSAT2WBO.convert wcnf)
diff --git a/src/Converter/MaxSAT2NLPB.hs b/src/Converter/MaxSAT2NLPB.hs
new file mode 100644
--- /dev/null
+++ b/src/Converter/MaxSAT2NLPB.hs
@@ -0,0 +1,28 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Converter.MaxSAT2NLPB
+-- Copyright   :  (c) Masahiro Sakai 2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+module Converter.MaxSAT2NLPB
+  ( convert
+  ) where
+
+import qualified Text.PBFile as PBFile
+import qualified Text.MaxSAT as MaxSAT
+
+convert :: MaxSAT.WCNF -> PBFile.Formula
+convert
+  MaxSAT.WCNF
+  { MaxSAT.topCost = top
+  , MaxSAT.clauses = cs
+  } = (Just obj, cs2)
+  where
+    obj = [(w, [-l | l <- ls]) | (w,ls) <- cs, w /= top]
+    cs2 = [([(1,[l]) | l <- ls], PBFile.Ge, 1) | (w,ls) <- cs, w == top]
diff --git a/src/Converter/MaxSAT2WBO.hs b/src/Converter/MaxSAT2WBO.hs
new file mode 100644
--- /dev/null
+++ b/src/Converter/MaxSAT2WBO.hs
@@ -0,0 +1,32 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Converter.MaxSAT2WBO
+-- Copyright   :  (c) Masahiro Sakai 2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+module Converter.MaxSAT2WBO
+  ( convert
+  ) where
+
+import qualified Text.PBFile as PBFile
+import qualified Text.MaxSAT as MaxSAT
+
+convert :: MaxSAT.WCNF -> PBFile.SoftFormula
+convert
+  MaxSAT.WCNF
+  { MaxSAT.topCost = top
+  , MaxSAT.clauses = cs
+  } = (Nothing, map f cs)
+  where
+    f (w,ls)
+     | w>=top    = (Nothing, p) -- hard constraint
+     | otherwise = (Just w, p)  -- soft constraint
+     where
+       p = ([(1,[l]) | l <- ls], PBFile.Ge, 1)
+
diff --git a/src/Converter/PB2LP.hs b/src/Converter/PB2LP.hs
--- a/src/Converter/PB2LP.hs
+++ b/src/Converter/PB2LP.hs
@@ -11,8 +11,7 @@
 --
 -----------------------------------------------------------------------------
 module Converter.PB2LP
-  ( ObjType (..)
-  , convert
+  ( convert
   , convertWBO
   ) where
 
@@ -25,10 +24,9 @@
 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))
+convert :: PBFile.Formula -> (LPFile.LP, Map.Map LPFile.Var Rational -> SAT.Model)
+convert formula@(obj, cs) = (lp, mtrans (PBFile.pbNumVars formula))
   where
     lp = LPFile.LP
       { LPFile.variables = vs2
@@ -54,11 +52,8 @@
     (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])
+        Nothing   -> (LPFile.OptMin, convExpr [])
+
     cs2 = do
       (lhs,op,rhs) <- cs
       let op2 = case op of
@@ -75,7 +70,8 @@
         }
 
 convExpr :: PBFile.Sum -> LPFile.Expr
-convExpr = concatMap g2
+convExpr [] = [LPFile.Term 0 ["x1"]]
+convExpr s = concatMap g2 s
   where
     g2 :: PBFile.WeightedTerm -> LPFile.Expr
     g2 (w, tm) = foldl' prodE [LPFile.Term (fromIntegral w) []] (map g3 tm)
diff --git a/src/Converter/PB2LSP.hs b/src/Converter/PB2LSP.hs
new file mode 100644
--- /dev/null
+++ b/src/Converter/PB2LSP.hs
@@ -0,0 +1,60 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Converter.PB2LSP
+-- Copyright   :  (c) Masahiro Sakai 2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+module Converter.PB2LSP
+  ( convert
+  ) where
+
+import Data.List
+import qualified Text.PBFile as PBFile
+
+convert :: PBFile.Formula -> ShowS
+convert formula@(obj, cs) =
+  showString "function model() {\n" .
+  decls .
+  constrs .
+  obj2 .
+  showString "}\n"
+  where
+    nv = PBFile.pbNumVars formula
+
+    decls = showString $
+      "  for [i in 1.." ++ show nv ++ "] x[i] <- bool();\n"
+
+    constrs = foldr (.) id
+      [ showString "  constraint " .
+        showString (showSum lhs) .
+        showString op2 .
+        shows rhs .
+        showString ";\n"
+      | (lhs, op, rhs) <- cs
+      , let op2 = case op of
+                    PBFile.Ge -> " >= "
+                    PBFile.Eq -> " == "
+      ]
+
+    sum' :: [String] -> String
+    sum' xs = "sum(" ++ intercalate ", " xs ++ ")"
+
+    showSum = sum' . map showTerm
+
+    showTerm (n,ls) = intercalate "*" $ [show n | n /= 1] ++ [showLit l | l<-ls]
+
+    showLit l =
+      if l < 0
+      then "!x[" ++ show (abs l) ++ "]"
+      else "x[" ++ show l ++ "]"
+
+    obj2 =
+      case obj of
+        Just obj' -> showString "  minimize " . showString (showSum obj') . showString ";\n"
+        Nothing -> id
diff --git a/src/Converter/PB2SMP.hs b/src/Converter/PB2SMP.hs
new file mode 100644
--- /dev/null
+++ b/src/Converter/PB2SMP.hs
@@ -0,0 +1,85 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Converter.PB2SMP
+-- Copyright   :  (c) Masahiro Sakai 2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+module Converter.PB2SMP
+  ( convert
+  ) where
+
+import Data.List
+import qualified Text.PBFile as PBFile
+
+convert :: Bool -> PBFile.Formula -> ShowS
+convert isUnix formula@(obj, cs) =
+  header .
+  decls .
+  showString "\n" .
+  obj2 .
+  showString "\n" .
+  constrs .
+  showString "\n" .
+  actions .
+  footer
+  where
+    nv = PBFile.pbNumVars formula
+
+    header =
+      if isUnix
+      then showString "#include \"simple.h\"\nvoid ufun()\n{\n\n"
+      else id
+    
+    footer =
+      if isUnix
+      then showString "\n}\n"
+      else id
+
+    actions =
+      showString "solve();\n" .
+      showString "x[i].val.print();\n" .
+      showString "cost.val.print();\n"
+
+    decls = showString $
+      "Element i(set=\"1 .. " ++ show nv ++ "\");\n" ++
+      "IntegerVariable x(type=binary, index=i);\n"
+
+    constrs = foldr (.) id
+      [ showString (showSum lhs) .
+        showString op2 .
+        shows rhs .
+        showString ";\n"
+      | (lhs, op, rhs) <- cs
+      , let op2 = case op of
+                    PBFile.Ge -> " >= "
+                    PBFile.Eq -> " == "
+      ]
+
+    showSum :: PBFile.Sum -> String
+    showSum [] = "0"
+    showSum xs = intercalate " + " $ map showTerm xs
+
+    showTerm (n,ls) = intercalate "*" $ showCoeff n ++ [showLit l | l<-ls]
+
+    showCoeff n
+      | n == 1    = []
+      | n < 0     = ["(" ++ show n ++ ")"]
+      | otherwise = [show n]
+
+    showLit l =
+      if l < 0
+      then "(1-x[" ++ show (abs l) ++ "])"
+      else "x[" ++ show l ++ "]"
+
+    obj2 =
+      case obj of
+        Just obj' ->
+          showString "Objective cost(type=minimize);\n" .
+          showString "cost = " . showString (showSum obj') . showString ";\n"
+        Nothing -> id
diff --git a/src/Converter/PB2WBO.hs b/src/Converter/PB2WBO.hs
new file mode 100644
--- /dev/null
+++ b/src/Converter/PB2WBO.hs
@@ -0,0 +1,33 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Converter.PB2WBO
+-- Copyright   :  (c) Masahiro Sakai 2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-- References:
+--
+-- * Improving Unsatisfiability-based Algorithms for Boolean Optimization
+--   <http://sat.inesc-id.pt/~ruben/talks/sat10-talk.pdf>
+--
+-----------------------------------------------------------------------------
+module Converter.PB2WBO (convert) where
+
+import qualified Text.PBFile as PBFile
+
+convert :: PBFile.Formula -> PBFile.SoftFormula
+convert (obj, cs) = (Nothing, cs1 ++ cs2)
+  where
+    cs1 = [(Nothing, c) | c <- cs]
+    cs2 = case obj of
+            Nothing -> []
+            Just e  ->
+              [ if w >= 0
+                then (Just w,       ([(-1,ls)], PBFile.Ge, 0))
+                else (Just (abs w), ([(1,ls)],  PBFile.Ge, 1))
+              | (w,ls) <- e
+              ]
diff --git a/src/Converter/PBSetObj.hs b/src/Converter/PBSetObj.hs
new file mode 100644
--- /dev/null
+++ b/src/Converter/PBSetObj.hs
@@ -0,0 +1,31 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Converter.PBSetObj
+-- Copyright   :  (c) Masahiro Sakai 2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+module Converter.PBSetObj
+  ( ObjType (..)
+  , setObj
+  ) where
+
+import qualified Text.PBFile as PBFile
+import Converter.ObjType
+
+setObj :: ObjType -> PBFile.Formula -> PBFile.Formula
+setObj objType formula@(_, cs) = (Just obj2, cs)
+  where
+    obj2 = genObj objType formula
+
+genObj :: ObjType -> PBFile.Formula -> PBFile.Sum
+genObj objType formula =
+  case objType of
+    ObjNone    -> []
+    ObjMaxOne  -> [(1,[-v]) | v <- [1 .. PBFile.pbNumVars formula]] -- minimize false literals
+    ObjMaxZero -> [(1,[ v]) | v <- [1 .. PBFile.pbNumVars formula]] -- minimize true literals
diff --git a/src/Converter/SAT2LP.hs b/src/Converter/SAT2LP.hs
new file mode 100644
--- /dev/null
+++ b/src/Converter/SAT2LP.hs
@@ -0,0 +1,25 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Converter.SAT2LP
+-- Copyright   :  (c) Masahiro Sakai 2011-2012
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+module Converter.SAT2LP
+  ( convert
+  ) where
+
+import qualified Data.Map as Map
+import qualified Text.LPFile as LPFile
+import qualified Language.CNF.Parse.ParseDIMACS as DIMACS
+import qualified SAT.Types as SAT
+import qualified Converter.PB2LP as PB2LP
+import qualified Converter.SAT2PB as SAT2PB
+
+convert :: DIMACS.CNF -> (LPFile.LP, Map.Map LPFile.Var Rational -> SAT.Model)
+convert cnf = PB2LP.convert (SAT2PB.convert cnf)
diff --git a/src/Converter/SAT2PB.hs b/src/Converter/SAT2PB.hs
new file mode 100644
--- /dev/null
+++ b/src/Converter/SAT2PB.hs
@@ -0,0 +1,24 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Converter.SAT2PB
+-- Copyright   :  (c) Masahiro Sakai 2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+module Converter.SAT2PB
+  ( convert
+  ) where
+
+import Data.Array.IArray
+import qualified Text.PBFile as PBFile
+import qualified Language.CNF.Parse.ParseDIMACS as DIMACS
+
+convert :: DIMACS.CNF -> PBFile.Formula
+convert cnf = (Nothing, map f (DIMACS.clauses cnf))
+  where
+    f clause = ([(1,[l]) | l <- elems clause], PBFile.Ge, 1)
diff --git a/src/Converter/WBO2PB.hs b/src/Converter/WBO2PB.hs
new file mode 100644
--- /dev/null
+++ b/src/Converter/WBO2PB.hs
@@ -0,0 +1,47 @@
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Converter.WBO2PB
+-- Copyright   :  (c) Masahiro Sakai 2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+module Converter.WBO2PB (convert) where
+
+import Data.Array.IArray
+import qualified SAT.Types as SAT
+import qualified Text.PBFile as PBFile
+
+convert :: PBFile.SoftFormula -> (PBFile.Formula, SAT.Model -> SAT.Model)
+convert wbo@(top, cs) = ((Just obj, topConstr ++ concatMap f cm), mtrans)
+  where
+    nv = PBFile.wboNumVars wbo
+
+    cm  = zip [nv+1..] cs
+    obj = [(w, [i]) | (i, (Just w,_)) <- cm]
+
+    f :: (PBFile.Var, PBFile.SoftConstraint) -> [PBFile.Constraint]
+    f (_, (Nothing, c)) = return c
+    f (i, (Just _, c))  = relax i c
+
+    relax :: PBFile.Var -> PBFile.Constraint -> [PBFile.Constraint]
+    relax i (lhs, PBFile.Ge, rhs) = [((d, [i]) : lhs, PBFile.Ge, rhs)]
+      where
+        d = rhs - SAT.pbLowerBound [(c,1) | (c,_) <- lhs]
+    relax i (lhs, PBFile.Eq, rhs) =
+      relax i (lhs, PBFile.Ge, rhs) ++
+      relax i ([(-c,ls) | (c,ls) <- lhs], PBFile.Ge, - rhs)
+
+    topConstr :: [PBFile.Constraint]
+    topConstr = 
+     case top of
+       Nothing -> []
+       Just t -> [([(-c,ls) | (c,ls) <- obj], PBFile.Ge, - (t - 1))]
+
+    mtrans :: SAT.Model -> SAT.Model
+    mtrans m = 
+      array (1, nv) [(x, m ! x) | x <- [1..nv]]
diff --git a/src/Data/AlgebraicNumber.hs b/src/Data/AlgebraicNumber.hs
--- a/src/Data/AlgebraicNumber.hs
+++ b/src/Data/AlgebraicNumber.hs
@@ -47,7 +47,7 @@
 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 Data.Interval (Interval, EndPoint (..), (<=..<), (<..<=), (<..<), (<!), (>!))
 import qualified Data.Interval as Interval
 import Data.AlgebraicNumber.Root
 
@@ -114,8 +114,8 @@
     | 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)))
+      ipos = Interval.intersection i3 (Finite 0 <..< PosInf)
+      ineg = Interval.intersection i3 (NegInf <..< Finite 0)
 
 instance Num AReal where
   RealRoot p1 i1 + RealRoot p2 i2 = realRoot p3 i3
@@ -128,9 +128,9 @@
           [] -> 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]
+            go (Sturm.narrow p1 i1 (Interval.width i1 / 2))
+               (Sturm.narrow p2 i2 (Interval.width i2 / 2))
+               [Sturm.narrow p3 i5 (Interval.width i5 / 2) | i5 <- is5]
         where
           i4 = i1 + i2
 
@@ -144,9 +144,9 @@
           [] -> 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]
+            go (Sturm.narrow p1 i1 (Interval.width i1 / 2))
+               (Sturm.narrow p2 i2 (Interval.width i2 / 2))
+               [Sturm.narrow p3 i5 (Interval.width i5 / 2) | i5 <- is5]
         where
           i4 = i1 * i2
 
@@ -229,32 +229,32 @@
 -- | Same as 'ceiling'.
 ceiling' :: Integral b => AReal -> b
 ceiling' (RealRoot p i) =
-  if Sturm.numRoots' chain (Interval.intersection i2 i3) > 1
+  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
+    (Finite lb, inLB) = Interval.lowerBound' i2
+    (Finite ub, inUB) = Interval.upperBound' i2
     ceiling_lb = ceiling lb
     ceiling_ub = ceiling ub
-    i3 = Interval.interval Nothing (Just (True, fromInteger ceiling_lb))
+    i3 = NegInf <..<= Finite (fromInteger ceiling_lb)
 
 -- | Same as 'floor'.
 floor' :: Integral b => AReal -> b
 floor' (RealRoot p i) =
-  if Sturm.numRoots' chain (Interval.intersection i2 i3) > 1
+  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
+    (Finite lb, inLB) = Interval.lowerBound' i2
+    (Finite ub, inUB) = Interval.upperBound' i2
     floor_lb = floor lb
     floor_ub = floor ub
-    i3 = Interval.interval (Just (True, fromInteger floor_ub)) Nothing
+    i3 = Finite (fromInteger floor_ub) <=..< PosInf
 
 {--------------------------------------------------------------------
   Properties
diff --git a/src/Data/ArithRel.hs b/src/Data/ArithRel.hs
--- a/src/Data/ArithRel.hs
+++ b/src/Data/ArithRel.hs
@@ -29,9 +29,9 @@
   , (.<.), (.<=.), (.>=.), (.>.), (.==.), (./=.)
   ) where
 
+import Algebra.Lattice.Boolean (Complement (..))
 import qualified Data.IntSet as IS
-import Data.Expr (Variables (..))
-import Data.Lattice (Complement (..))
+import Data.Var
 
 infix 4 .<., .<=., .>=., .>., .==., ./=.
 
@@ -126,5 +126,8 @@
 
 instance Variables e => Variables (Rel e) where
   vars (Rel a _ b) = vars a `IS.union` vars b
+
+instance Functor Rel where
+  fmap f (Rel a op b) = Rel (f a) op (f b)
 
 -- ---------------------------------------------------------------------------
diff --git a/src/Data/DNF.hs b/src/Data/DNF.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/DNF.hs
@@ -0,0 +1,46 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.DNF
+-- Copyright   :  (c) Masahiro Sakai 2011-2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- Disjunctive Normal Form
+-- 
+-----------------------------------------------------------------------------
+module Data.DNF
+  ( DNF (..)
+  ) where
+
+import Algebra.Lattice
+import Algebra.Lattice.Boolean
+
+-- | 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 JoinSemiLattice (DNF lit) where
+  DNF xs `join` DNF ys = DNF (xs++ys)
+
+instance MeetSemiLattice (DNF lit) where
+  DNF xs `meet` DNF ys = DNF [x++y | x<-xs, y<-ys]
+
+instance Lattice (DNF lit)
+
+instance BoundedJoinSemiLattice (DNF lit) where
+  bottom = DNF []
+
+instance BoundedMeetSemiLattice (DNF lit) where
+  top = DNF [[]]
+
+instance BoundedLattice (DNF lit)
+
+instance Complement lit => Boolean (DNF lit)
diff --git a/src/Data/Delta.hs b/src/Data/Delta.hs
--- a/src/Data/Delta.hs
+++ b/src/Data/Delta.hs
@@ -1,13 +1,13 @@
-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses #-}
+{-# LANGUAGE TypeFamilies #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Delta
--- Copyright   :  (c) Masahiro Sakai 2011
+-- Copyright   :  (c) Masahiro Sakai 2011-2013
 -- License     :  BSD-style
 -- 
 -- Maintainer  :  masahiro.sakai@gmail.com
 -- Stability   :  provisional
--- Portability :  non-portable (FlexibleInstances, MultiParamTypeClasses)
+-- Portability :  non-portable (TypeFamilies)
 --
 -- Augmenting number types with infinitesimal parameter δ.
 --
@@ -41,7 +41,7 @@
   , isInteger'
   ) where
 
-import Data.Linear
+import Data.VectorSpace
 import Util (isInteger)
 
 -- | @Delta r k@ represents r + kδ for symbolic infinitesimal parameter δ.
@@ -63,12 +63,14 @@
 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 Num r => AdditiveGroup (Delta r) where
+  Delta r1 k1 ^+^ Delta r2 k2 = Delta (r1+r2) (k1+k2)
+  zeroV = Delta 0 0
+  negateV (Delta r k) = Delta (- r) (- k)
 
-instance Fractional r => Linear r (Delta r)
+instance Num r => VectorSpace (Delta r) where
+  type Scalar (Delta r) = r
+  c *^ Delta r k = Delta (c*r) (c*k)
 
 -- | 'Delta' version of 'floor'.
 -- @'floor'' x@ returns the greatest integer not greater than @x@
diff --git a/src/Data/Expr.hs b/src/Data/Expr.hs
deleted file mode 100644
--- a/src/Data/Expr.hs
+++ /dev/null
@@ -1,118 +0,0 @@
------------------------------------------------------------------------------
--- |
--- 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/FOL/Arith.hs b/src/Data/FOL/Arith.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/FOL/Arith.hs
@@ -0,0 +1,112 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.FOL.Arith
+-- Copyright   :  (c) Masahiro Sakai 2011-2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- Arithmetic language (not limited to linear ones).
+-- 
+-----------------------------------------------------------------------------
+module Data.FOL.Arith
+  (
+  -- * Arithmetic expressions
+    Expr (..)
+  , var
+  , evalExpr
+
+  -- * Atomic formula
+  , module Data.ArithRel
+  , Atom (..)
+  , evalAtom
+
+  -- * Arithmetic formula
+  , module Data.FOL.Formula  
+
+  -- * Misc
+  , SatResult (..)
+  ) where
+
+import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
+import Data.Ratio
+
+import Data.ArithRel
+import Data.FOL.Formula
+import Data.Var
+
+-- ---------------------------------------------------------------------------
+
+-- | 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'
+evalExpr :: Fractional r => Model r -> Expr r -> r
+evalExpr 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
+
+-- ---------------------------------------------------------------------------
+
+-- | Atomic formula
+type Atom c = Rel (Expr c)
+
+evalAtom :: (Real r, Fractional r) => Model r -> Atom r -> Bool
+evalAtom m (Rel a op b) = evalOp op (evalExpr m a) (evalExpr m b)
+
+instance IsRel (Expr c) (Formula (Atom c)) where
+  rel op a b = Atom $ rel op a b
+
+-- ---------------------------------------------------------------------------
+
+-- | results of satisfiability checking
+data SatResult r = Unknown | Unsat | Sat (Model r)
+  deriving (Show, Eq, Ord)
+
+-- ---------------------------------------------------------------------------
diff --git a/src/Data/FOL/Formula.hs b/src/Data/FOL/Formula.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/FOL/Formula.hs
@@ -0,0 +1,92 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.FOL.Formula
+-- Copyright   :  (c) Masahiro Sakai 2011-2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-- Formula of first order logic.
+-- 
+-----------------------------------------------------------------------------
+module Data.FOL.Formula
+  (
+  -- * Overloaded operations for formula.
+    module Algebra.Lattice.Boolean
+
+  -- * Concrete formula
+  , Formula (..)
+  , pushNot
+  ) where
+
+import Algebra.Lattice
+import Algebra.Lattice.Boolean
+
+import qualified Data.IntSet as IS
+import Data.Var
+
+-- ---------------------------------------------------------------------------
+
+-- | formulas of first order logic
+data Formula a
+    = T
+    | F
+    | Atom a
+    | And (Formula a) (Formula a)
+    | Or (Formula a) (Formula a)
+    | Not (Formula a)
+    | Imply (Formula a) (Formula a)
+    | Equiv (Formula a) (Formula a)
+    | Forall Var (Formula a)
+    | Exists Var (Formula a)
+    deriving (Show, Eq, Ord)
+
+instance Variables a => Variables (Formula a) where
+  vars T = IS.empty
+  vars F = IS.empty
+  vars (Atom a) = vars a
+  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 a) where
+  notB = Not
+
+instance JoinSemiLattice (Formula c) where
+  join = Or
+
+instance MeetSemiLattice (Formula c) where
+  meet = And
+
+instance Lattice (Formula c)
+
+instance BoundedJoinSemiLattice (Formula c) where
+  bottom = F
+
+instance BoundedMeetSemiLattice (Formula c) where
+  top = T
+
+instance BoundedLattice (Formula c)
+
+instance Boolean (Formula c) where
+  (.=>.)  = Imply
+  (.<=>.) = Equiv
+
+-- | convert a formula into negation normal form
+pushNot :: Complement a => Formula a -> Formula a
+pushNot T = F
+pushNot F = T
+pushNot (Atom a) = Atom $ notB a
+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)
diff --git a/src/Data/Formula.hs b/src/Data/Formula.hs
deleted file mode 100644
--- a/src/Data/Formula.hs
+++ /dev/null
@@ -1,112 +0,0 @@
-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
------------------------------------------------------------------------------
--- |
--- Module      :  Data.Formula
--- Copyright   :  (c) Masahiro Sakai 2011
--- License     :  BSD-style
--- 
--- Maintainer  :  masahiro.sakai@gmail.com
--- Stability   :  provisional
--- Portability :  non-portable (MultiParamTypeClasses, FlexibleInstances)
---
--- Formula of first order logic.
--- 
------------------------------------------------------------------------------
-module Data.Formula
-  (
-  -- * Overloaded operations for formula.
-    module Data.Lattice
-
-  -- * Relational operators
-  , module Data.ArithRel
-
-  -- * Concrete formula
-  , Atom (..)
-  , Formula (..)
-  , pushNot
-  , DNF (..)
-  ) where
-
-import qualified Data.IntSet as IS
-import Data.Expr
-import Data.Lattice
-import Data.ArithRel
-
--- ---------------------------------------------------------------------------
-
--- | Atomic formula
-type Atom c = Rel (Expr c)
-
--- ---------------------------------------------------------------------------
-
--- | formulas of first order logic
-data Formula a
-    = T
-    | F
-    | Atom a
-    | And (Formula a) (Formula a)
-    | Or (Formula a) (Formula a)
-    | Not (Formula a)
-    | Imply (Formula a) (Formula a)
-    | Equiv (Formula a) (Formula a)
-    | Forall Var (Formula a)
-    | Exists Var (Formula a)
-    deriving (Show, Eq, Ord)
-
-instance Variables a => Variables (Formula a) where
-  vars T = IS.empty
-  vars F = IS.empty
-  vars (Atom a) = vars a
-  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 a) where
-  notB = Not
-
-instance Lattice (Formula c) where
-  top    = T
-  bottom = F
-  meet   = And
-  join   = Or
-
-instance Boolean (Formula c) where
-  (.=>.)  = Imply
-  (.<=>.) = Equiv
-
-instance IsRel (Expr c) (Formula (Atom c)) where
-  rel op a b = Atom $ rel op a b
-
--- | convert a formula into negation normal form
-pushNot :: Complement a => Formula a -> Formula a
-pushNot T = F
-pushNot F = T
-pushNot (Atom a) = Atom $ notB a
-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/Interval.hs b/src/Data/Interval.hs
deleted file mode 100644
--- a/src/Data/Interval.hs
+++ /dev/null
@@ -1,481 +0,0 @@
-{-# 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
--- a/src/Data/LA.hs
+++ b/src/Data/LA.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
+{-# LANGUAGE TypeFamilies #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.LA
@@ -7,16 +7,15 @@
 -- 
 -- Maintainer  :  masahiro.sakai@gmail.com
 -- Stability   :  provisional
--- Portability :  non-portable (MultiParamTypeClasses, FlexibleInstances)
+-- Portability :  non-portable (TypeFamilies)
 --
 -- Some definition for Theory of Linear Arithmetics.
 -- 
 -----------------------------------------------------------------------------
 module Data.LA
-  ( module Data.Linear
-
+  (
   -- * Expression of linear arithmetics
-  , Expr
+    Expr
 
   -- ** Conversion
   , var
@@ -53,8 +52,6 @@
   -- * misc
   , BoundsEnv
   , computeInterval
-  , compileExpr
-  , compileAtom
   ) where
 
 import Control.Monad
@@ -63,12 +60,10 @@
 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.ArithRel as ArithRel
-import qualified Data.Formula as Formula
-import Data.Linear
 import Data.Interval
+import Data.Var
+import Data.VectorSpace
 
 -----------------------------------------------------------------------------
 
@@ -145,16 +140,18 @@
     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 (Num r, Eq r) => AdditiveGroup (Expr r) where
+  Expr t ^+^ e2 | IM.null t = e2
+  e1 ^+^ Expr t | IM.null t = e1
+  e1 ^+^ e2 = normalizeExpr $ plus e1 e2
+  zeroV = Expr $ IM.empty
+  negateV = ((-1) *^)
 
-instance (Fractional r, Eq r) => Linear r (Expr r)
+instance (Num r, Eq r) => VectorSpace (Expr r) where
+  type Scalar (Expr r) = r
+  1 *^ e = e
+  0 *^ e = zeroV
+  c *^ e = mapCoeff (c*) e
 
 plus :: Num r => Expr r -> Expr r -> Expr r
 plus (Expr t1) (Expr t2) = Expr $ IM.unionWith (+) t1 t2
@@ -165,21 +162,21 @@
   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]
+evalLinear :: VectorSpace a => Model a -> a -> Expr (Scalar a) -> a
+evalLinear m u (Expr t) = sumV [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]
+lift1 :: VectorSpace x => x -> (Var -> x) -> Expr (Scalar x) -> x
+lift1 unit f (Expr t) = sumV [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))
+applySubst s (Expr m) = sumV (map f (IM.toList m))
   where
-    f (v,c) = c .*. (
+    f (v,c) = c *^ (
       case IM.lookup v s of
         Just tm -> tm
         Nothing -> var v)
@@ -189,7 +186,7 @@
 applySubst1 x e e1 =
   case extractMaybe x e1 of
     Nothing -> e1
-    Just (c,e2) -> c .*. e .+. e2
+    Just (c,e2) -> c *^ e ^+^ e2
 
 -- | lookup a coefficient of the variable.
 -- @
@@ -206,7 +203,7 @@
 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 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))
 {-
@@ -217,7 +214,7 @@
     (Just c, m2) -> (c, Expr m2)
 -}
 
--- | @extractMaybe v e@ returns @Just (c, e')@ such that @e == c .*. v .+. e'@
+-- | @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) =
@@ -265,40 +262,17 @@
 -- is equivalent to @a@.
 solveFor :: (Real r, Fractional r) => Atom r -> Var -> Maybe (ArithRel.RelOp, Expr r)
 solveFor (ArithRel.Rel lhs op rhs) v = do
-  (c,e) <- extractMaybe v (lhs .-. rhs)
+  (c,e) <- extractMaybe v (lhs ^-^ rhs)
   return ( if c < 0 then ArithRel.flipOp op else op
-         , (1/c) .*. lnegate e
+         , (1/c) *^ negateV e
          )
 
 -----------------------------------------------------------------------------
 
-type BoundsEnv r = Expr.VarMap (Interval r)
+type BoundsEnv r = 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 (ArithRel.Rel a op b) = do
-  a' <- compileExpr a
-  b' <- compileExpr b
-  return $ ArithRel.rel op a' b'
+computeInterval b = evalExpr b . mapCoeff singleton
 
 -----------------------------------------------------------------------------
diff --git a/src/Data/LA/FOL.hs b/src/Data/LA/FOL.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/LA/FOL.hs
@@ -0,0 +1,56 @@
+{-# OPTIONS_GHC -Wall #-}
+module Data.LA.FOL
+  ( fromFOLAtom
+  , toFOLFormula
+  , fromFOLExpr
+  , toFOLExpr
+  ) where
+
+import Control.Monad
+
+import Data.ArithRel
+import Data.FOL.Arith
+import Data.VectorSpace
+
+import qualified Data.LA as LA
+
+-- ---------------------------------------------------------------------------
+
+fromFOLAtom :: (Real r, Fractional r) => Atom r -> Maybe (LA.Atom r)
+fromFOLAtom (Rel a op b) = do
+  a' <- fromFOLExpr a
+  b' <- fromFOLExpr b
+  return $ rel op a' b'
+
+toFOLFormula :: (Real r, Fractional r) => LA.Atom r -> Formula (Atom r)
+toFOLFormula r = Atom $ fmap toFOLExpr r
+
+fromFOLExpr :: (Real r, Fractional r) => Expr r -> Maybe (LA.Expr r)
+fromFOLExpr (Const c) = return (LA.constant c)
+fromFOLExpr (Var v)   = return (LA.var v)
+fromFOLExpr (a :+: b) = liftM2 (^+^) (fromFOLExpr a) (fromFOLExpr b)
+fromFOLExpr (a :*: b) = do
+  a' <- fromFOLExpr a
+  b' <- fromFOLExpr b
+  msum [ do{ c <- LA.asConst a'; return (c *^ b') }
+       , do{ c <- LA.asConst b'; return (c *^ a') }
+       ]
+fromFOLExpr (a :/: b) = do
+  a' <- fromFOLExpr a
+  b' <- fromFOLExpr b
+  c <- LA.asConst b'
+  guard $ c /= 0
+  return (a' ^/ c)
+
+toFOLExpr :: (Real r, Fractional r) => LA.Expr r -> Expr r
+toFOLExpr e =
+  case map f (LA.terms e) of
+    []  -> Const 0
+    [t] -> t
+    ts  -> foldr1 (*) ts
+  where
+    f (c,x)
+      | x == LA.unitVar = Const c
+      | otherwise       = Const c * Var x
+
+-- ---------------------------------------------------------------------------
diff --git a/src/Data/Lattice.hs b/src/Data/Lattice.hs
deleted file mode 100644
--- a/src/Data/Lattice.hs
+++ /dev/null
@@ -1,90 +0,0 @@
-{-# 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
deleted file mode 100644
--- a/src/Data/Linear.hs
+++ /dev/null
@@ -1,72 +0,0 @@
-{-# 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
--- a/src/Data/Polyhedron.hs
+++ b/src/Data/Polyhedron.hs
@@ -24,14 +24,15 @@
 import Data.Ratio
 import qualified Data.IntSet as IS
 import qualified Data.Map as Map
+import Data.VectorSpace
 import Prelude hiding (null)
 
+import Algebra.Lattice
+
 import qualified Data.Interval as Interval
-import Data.Expr (Variables (..))
 import Data.ArithRel
 import qualified Data.LA as LA
-import Data.Linear
-import Data.Lattice
+import Data.Var
 
 type ExprR = LA.Expr Rational
 type ExprZ = LA.Expr Integer
@@ -50,15 +51,25 @@
   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
+instance JoinSemiLattice Polyhedron where
   join Empty b = b
   join a Empty = a
   join (Polyhedron m1) (Polyhedron m2) =
     normalize $ Polyhedron (Map.intersectionWith Interval.join m1 m2)
 
+instance MeetSemiLattice Polyhedron where
+  meet = intersection
+
+instance Lattice Polyhedron
+
+instance BoundedJoinSemiLattice Polyhedron where
+  bottom = empty  
+
+instance BoundedMeetSemiLattice Polyhedron where
+  top = univ
+
+instance BoundedLattice Polyhedron
+
 normalize :: Polyhedron -> Polyhedron
 normalize (Polyhedron m) | any Interval.null (Map.elems m) = Empty
 normalize p = p
@@ -94,7 +105,7 @@
           let rhs1 = - c * fromIntegral d
               (lhs2,op2,rhs2) =
                 if p lhs1
-                then (lnegate lhs1, flipOp op, - rhs1)
+                then (negateV lhs1, flipOp op, - rhs1)
                 else (lhs1, op, rhs1)
               ival =
                 case op of
diff --git a/src/Data/Polynomial.hs b/src/Data/Polynomial.hs
--- a/src/Data/Polynomial.hs
+++ b/src/Data/Polynomial.hs
@@ -1,13 +1,13 @@
-{-# LANGUAGE ScopedTypeVariables, FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances #-}
+{-# LANGUAGE ScopedTypeVariables, TypeFamilies #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Polynomial
--- Copyright   :  (c) Masahiro Sakai 2012
+-- Copyright   :  (c) Masahiro Sakai 2012-2013
 -- License     :  BSD-style
 -- 
 -- Maintainer  :  masahiro.sakai@gmail.com
 -- Stability   :  provisional
--- Portability :  non-portable (ScopedTypeVariables, FlexibleInstances, MultiParamTypeClasses, TypeSynonymInstances)
+-- Portability :  non-portable (ScopedTypeVariables, TypeFamilies)
 --
 -- Polynomials
 --
@@ -122,8 +122,7 @@
 import qualified Data.Map as Map
 import qualified Data.Set as Set
 import qualified Data.IntMap as IM
-
-import Data.Linear
+import Data.VectorSpace
 
 {--------------------------------------------------------------------
   Polynomial type
@@ -147,12 +146,14 @@
   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, Num k, Ord v, Show v) => AdditiveGroup (Polynomial k v) where
+  p ^+^ q = p + q
+  zeroV   = 0
+  negateV = negate
 
-instance (Eq k, Fractional k, Ord v, Show v) => Linear k (Polynomial k v)
+instance (Eq k, Num k, Ord v, Show v) => VectorSpace (Polynomial k v) where
+  type Scalar (Polynomial k v) = k
+  k *^ p = constant k * p
 
 instance (Show v, Ord v, Show k) => Show (Polynomial k v) where
   showsPrec d p  = showParen (d > 10) $
diff --git a/src/Data/Polynomial/Sturm.hs b/src/Data/Polynomial/Sturm.hs
--- a/src/Data/Polynomial/Sturm.hs
+++ b/src/Data/Polynomial/Sturm.hs
@@ -34,7 +34,7 @@
 import Data.Maybe
 import Data.Polynomial
 import qualified Data.Interval as Interval
-import Data.Interval (Interval)
+import Data.Interval (Interval, EndPoint (..), (<..<=), (<=..<=))
 
 -- | Sturm's chain (Sturm's sequence)
 type SturmChain = [UPolynomial Rational]
@@ -67,10 +67,10 @@
   | Interval.null ival2 = 0
   | otherwise =
       case (Interval.lowerBound ival2, Interval.upperBound ival2) of
-        (Just (in1,lb), Just (in2,ub)) ->
+        (Finite lb, Finite 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)
+          (if lb `Interval.member` ival2 && isRootOf lb p then 1 else 0) +
+          (if ub `Interval.notMember` ival2 && isRootOf ub p then -1 else 0)
         _ -> error "numRoots'': should not happen"
   where
     ival2 = boundInterval p ival
@@ -103,7 +103,7 @@
     (s,_) = leadingTerm grlex p
 
 boundInterval :: UPolynomial Rational -> Interval Rational -> Interval Rational
-boundInterval p ival = Interval.intersection ival (Interval.closedInterval lb ub)
+boundInterval p ival = Interval.intersection ival (Finite lb <=..<= Finite ub)
   where
     (lb,ub) = bounds p
 
@@ -128,7 +128,7 @@
     g (lb,ub) =
       case n lb - n ub of
         0 -> []
-        1 -> [Interval.interval (Just (False, lb)) (Just (True, ub))]
+        1 -> [Finite lb <..<= Finite ub]
         _ -> g (lb, mid) ++ g (mid, ub)
       where
         mid = (lb + ub) / 2
@@ -144,12 +144,12 @@
       | numRoots' chain ivalL > 0 = go ivalL
       | otherwise = go ivalR -- numRoots' chain ivalR > 0
       where
-        (_,lb) = fromJust $ Interval.lowerBound ival
-        (_,ub) = fromJust $ Interval.upperBound ival
+        Finite lb = Interval.lowerBound ival
+        Finite ub = 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)
+        ivalL = Interval.interval (Interval.lowerBound' ival) (Finite mid, True)
+        ivalR = Interval.interval (Finite mid, False) (Interval.upperBound' ival)
 
 approx :: UPolynomial Rational -> Interval Rational -> Rational -> Rational
 approx p = approx' (sturmChain p)
diff --git a/src/Data/Var.hs b/src/Data/Var.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Var.hs
@@ -0,0 +1,45 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Data.Var
+-- Copyright   :  (c) Masahiro Sakai 2011-2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+-- 
+-----------------------------------------------------------------------------
+module Data.Var
+  ( Var
+  , VarSet
+  , VarMap
+  , Variables (..)
+  , Model
+  ) 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
+
+-- ---------------------------------------------------------------------------
diff --git a/src/SAT.hs b/src/SAT.hs
--- a/src/SAT.hs
+++ b/src/SAT.hs
@@ -1,5 +1,5 @@
 {-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}
-{-# LANGUAGE BangPatterns, DoAndIfThenElse, DoRec, ScopedTypeVariables, CPP #-}
+{-# LANGUAGE BangPatterns, DoAndIfThenElse, DoRec, ScopedTypeVariables, CPP, DeriveDataTypeable #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  SAT
@@ -54,6 +54,7 @@
   -- * Solving
   , solve
   , solveWith
+  , BudgetExceeded (..)
 
   -- * Extract results
   , Model
@@ -83,6 +84,7 @@
   , setRandomFreq
   , defaultRandomFreq
   , setRandomSeed
+  , setConfBudget
 
   -- * Read state
   , nVars
@@ -115,6 +117,7 @@
 import qualified Data.IndexedPriorityQueue as PQ
 import qualified Data.SeqQueue as SQ
 import Data.Time
+import Data.Typeable
 import System.CPUTime
 import qualified System.Random as Rand
 import Text.Printf
@@ -243,6 +246,9 @@
   , svNConflict    :: !(IORef Int)
   , svNRestart     :: !(IORef Int)
   , svNAssigns     :: !(IORef Int)
+  , svNFixed       :: !(IORef Int)
+  , svNLearntGC    :: !(IORef Int)
+  , svNRemovedConstr :: !(IORef Int)
 
   -- | Inverse of the variable activity decay factor. (default 1 / 0.95)
   , svVarDecay     :: !(IORef Double)
@@ -280,6 +286,8 @@
   , svLearningStrategy :: !(IORef LearningStrategy)
 
   , svLogger :: !(IORef (Maybe (String -> IO ())))
+  , svStartWC    :: !(IORef UTCTime)
+  , svLastStatWC :: !(IORef UTCTime)
 
   , svCheckModel :: !(IORef Bool)
 
@@ -287,6 +295,8 @@
   , svRandomGen  :: !(IORef Rand.StdGen)
 
   , svFailedAssumptions :: !(IORef [Lit])
+
+  , svConfBudget :: !(IORef Int)
   }
 
 markBad :: Solver -> IO ()
@@ -324,6 +334,7 @@
 
       modifyIORef (svTrail solver) (lit:)
       modifyIORef' (svNAssigns solver) (+1)
+      when (lv == levelRoot) $ modifyIORef' (svNFixed solver) (+1)
       bcpEnqueue solver lit
 
       when debugMode $ logIO solver $ do
@@ -388,7 +399,7 @@
 
 reduceDB :: Solver -> IO ()
 reduceDB solver = do
-  (n,cs) <- readIORef (svLearntDB solver)
+  (_,cs) <- readIORef (svLearntDB solver)
 
   xs <- forM cs $ \c -> do
     p <- constrIsProtected solver c
@@ -414,7 +425,7 @@
   let cs2 = zs2 ++ map fst ws
       n2 = length cs2
 
-  log solver $ printf "learnt constraints deletion: %d -> %d" n n2
+  -- log solver $ printf "learnt constraints deletion: %d -> %d" n n2
   writeIORef (svLearntDB solver) (n2,cs2)
 
 type VarActivity = Double
@@ -504,6 +515,9 @@
   nconflict <- newIORef 0
   nrestart  <- newIORef 0
   nassigns  <- newIORef 0
+  nfixed    <- newIORef 0
+  nlearntgc <- newIORef 0
+  nremoved  <- newIORef 0
 
   claDecay <- newIORef (1 / 0.999)
   claInc   <- newIORef 1
@@ -523,12 +537,16 @@
   learntLimSeq    <- newIORef undefined
 
   logger <- newIORef Nothing
+  startWC    <- newIORef undefined
+  lastStatWC <- newIORef undefined
 
   randfreq <- newIORef defaultRandomFreq
   randgen  <- newIORef =<< Rand.newStdGen
 
   failed <- newIORef []
 
+  confBudget <- newIORef (-1)
+
   let solver =
         Solver
         { svOk = ok
@@ -547,6 +565,9 @@
         , svNConflict  = nconflict
         , svNRestart   = nrestart
         , svNAssigns   = nassigns
+        , svNFixed     = nfixed
+        , svNLearntGC  = nlearntgc
+        , svNRemovedConstr = nremoved
         , svVarDecay   = varDecay
         , svVarInc     = varInc
         , svClaDecay   = claDecay
@@ -562,10 +583,13 @@
         , svLearntLimAdjCnt = learntLimAdjCnt
         , svLearntLimSeq    = learntLimSeq
         , svLogger = logger
+        , svStartWC    = startWC
+        , svLastStatWC = lastStatWC
         , svCheckModel = checkModel
         , svRandomFreq = randfreq
         , svRandomGen  = randgen
         , svFailedAssumptions = failed
+        , svConfBudget = confBudget
         }
  return solver
 
@@ -788,6 +812,7 @@
 solve_ :: Solver -> IO Bool
 solve_ solver = do
   log solver "Solving starts ..."
+  resetStat solver
   writeIORef (svModel solver) Nothing
   writeIORef (svFailedAssumptions solver) []
 
@@ -828,21 +853,26 @@
 
       let loop [] = error "solve_: should not happen"
           loop (conflict_lim:rs) = do
+            printStat solver True
             ret <- search solver conflict_lim onConflict
             case ret of
-              Just x -> return x
-              Nothing -> do
+              SRFinished x -> return $ Just x
+              SRBudgetExceeded -> return Nothing
+              SRRestart -> do
                 modifyIORef' (svNRestart solver) (+1)
                 backtrackTo solver levelRoot
                 loop rs
 
+      printStatHeader solver
+
       startCPU <- getCPUTime
       startWC  <- getCurrentTime
+      writeIORef (svStartWC solver) startWC
       result <- loop restartSeq
       endCPU <- getCPUTime
       endWC  <- getCurrentTime
 
-      when result $ do
+      when (result == Just True) $ do
         checkModel <- readIORef (svCheckModel solver)
         when checkModel $ checkSatisfied solver
         constructModel solver
@@ -851,6 +881,7 @@
 
       when debugMode $ dumpVarActivity solver
       when debugMode $ dumpClaActivity solver
+      printStat solver True
       (log solver . printf "#cpu_time = %.3fs") (fromIntegral (endCPU - startCPU) / 10^(12::Int) :: Double)
       (log solver . printf "#wall_clock_time = %.3fs") (realToFrac (endWC `diffUTCTime` startWC) :: Double)
       (log solver . printf "#decision = %d") =<< readIORef (svNDecision solver)
@@ -858,12 +889,24 @@
       (log solver . printf "#conflict = %d") =<< readIORef (svNConflict solver)
       (log solver . printf "#restart = %d")  =<< readIORef (svNRestart solver)
 
-      return result
+      case result of
+        Just x  -> return x
+        Nothing -> throw BudgetExceeded
 
-search :: Solver -> Int -> IO () -> IO (Maybe Bool)
+data BudgetExceeded = BudgetExceeded
+  deriving (Show, Typeable)
+
+instance Exception BudgetExceeded
+
+data SearchResult
+  = SRFinished Bool
+  | SRRestart
+  | SRBudgetExceeded
+
+search :: Solver -> Int -> IO () -> IO SearchResult
 search solver !conflict_lim onConflict = loop 0
   where
-    loop :: Int -> IO (Maybe Bool)
+    loop :: Int -> IO SearchResult
     loop !c = do
       sanityCheck solver
       conflict <- deduce solver
@@ -877,17 +920,19 @@
           n <- nLearnt solver
           m <- nAssigns solver
           learnt_lim <- readIORef (svLearntLim solver)
-          when (learnt_lim >= 0 && n - m > learnt_lim) $ reduceDB solver
+          when (learnt_lim >= 0 && n - m > learnt_lim) $ do
+            modifyIORef' (svNLearntGC solver) (+1)
+            reduceDB solver
 
           r <- pickAssumption
           case r of
-            Nothing -> return (Just False)
+            Nothing -> return (SRFinished False)
             Just lit
               | lit /= litUndef -> decide solver lit >> loop c
               | otherwise -> do
                   lit2 <- pickBranchLit solver
                   if lit2 == litUndef
-                    then return (Just True)
+                    then return (SRFinished True)
                     else decide solver lit2 >> loop c
 
         Just constr -> do
@@ -902,15 +947,24 @@
             str <- showConstraint solver constr
             return $ printf "conflict(level=%d): %s" d str
 
+          when (c `mod` 100 == 0) $ do
+            printStat solver False
+
+          modifyIORef' (svConfBudget solver) $ \confBudget ->
+            if confBudget > 0 then confBudget - 1 else confBudget
+          confBudget <- readIORef (svConfBudget solver)
+
           if d == levelRoot
-            then markBad solver >> return (Just False)
+            then markBad solver >> return (SRFinished False)
+            else if confBudget==0 then
+              return SRBudgetExceeded
             else if conflict_lim >= 0 && c+1 >= conflict_lim then
-              return Nothing
+              return SRRestart
             else do
               b <- handleConflict constr
               if b
                 then loop (c+1)
-                else markBad solver >> return (Just False)
+                else markBad solver >> return (SRFinished False)
 
     pickAssumption :: IO (Maybe Lit)
     pickAssumption = do
@@ -1004,7 +1058,6 @@
 -- | Simplify the clause database according to the current top-level assigment.
 simplify :: Solver -> IO ()
 simplify solver = do
-  xs <- readIORef (svClauseDB solver)
   let loop [] rs !n     = return (rs,n)
       loop (y:ys) rs !n = do
         b1 <- isSatisfied solver y
@@ -1014,11 +1067,20 @@
            detach solver y
            loop ys rs (n+1)
          else loop ys (y:rs) n
-  (ys,n) <- loop xs [] (0::Int)
-  when (n > 0) $ 
-    log solver $ printf "simplify: %d satisfied constraints are removed" n
-  writeIORef (svClauseDB solver) ys
 
+  -- simplify original constraint DB
+  do
+    xs <- readIORef (svClauseDB solver)
+    (ys,n) <- loop xs [] (0::Int)
+    modifyIORef' (svNRemovedConstr solver) (+n)
+    writeIORef (svClauseDB solver) ys
+
+  -- simplify learnt constraint DB
+  do
+    (m,xs) <- readIORef (svLearntDB solver)
+    (ys,n) <- loop xs [] (0::Int)
+    writeIORef (svLearntDB solver) (m-n, ys)
+
 {--------------------------------------------------------------------
   Parameter settings.
 --------------------------------------------------------------------}
@@ -1104,6 +1166,10 @@
 setRandomSeed solver seed = do
   writeIORef (svRandomGen solver) (Rand.mkStdGen seed)
 
+setConfBudget :: Solver -> Maybe Int -> IO ()
+setConfBudget solver (Just b) | b >= 0 = writeIORef (svConfBudget solver) b
+setConfBudget solver _ = writeIORef (svConfBudget solver) (-1)
+
 {--------------------------------------------------------------------
   API for implementation of @solve@
 --------------------------------------------------------------------}
@@ -1515,6 +1581,70 @@
   forM_ xs $ \c -> constrRescaleActivity solver c
   modifyIORef' (svClaInc solver) (* 1e-20)
 
+resetStat :: Solver -> IO ()
+resetStat solver = do
+  writeIORef (svNDecision solver) 0
+  writeIORef (svNRandomDecision solver) 0
+  writeIORef (svNConflict solver) 0
+  writeIORef (svNRestart solver) 0
+  writeIORef (svNLearntGC  solver) 0
+
+printStatHeader :: Solver -> IO ()
+printStatHeader solver = do
+  log solver $ "============================[ Search Statistics ]============================"
+  log solver $ " Time | Restart | Decision | Conflict |      LEARNT     | Fixed    | Removed "
+  log solver $ "      |         |          |          |    Limit     GC | Var      | Constra "
+  log solver $ "============================================================================="
+
+printStat :: Solver -> Bool -> IO ()
+printStat solver force = do
+  nowWC <- getCurrentTime
+  b <- if force
+       then return True
+       else do
+         lastWC <- readIORef (svLastStatWC solver)
+         return $ (nowWC `diffUTCTime` lastWC) > 1
+  when b $ do
+    startWC   <- readIORef (svStartWC solver)
+    let tm = showTimeDiff $ nowWC `diffUTCTime` startWC
+    restart   <- readIORef (svNRestart solver)
+    dec       <- readIORef (svNDecision solver)
+    conflict  <- readIORef (svNConflict solver)
+    learntLim <- readIORef (svLearntLim solver)
+    learntGC  <- readIORef (svNLearntGC solver)
+    fixed     <- readIORef (svNFixed solver)
+    removed   <- readIORef (svNRemovedConstr solver)
+    log solver $ printf "%s | %7d | %8d | %8d | %8d %6d | %8d | %8d"
+      tm restart dec conflict learntLim learntGC fixed removed
+    writeIORef (svLastStatWC solver) nowWC
+
+showTimeDiff :: NominalDiffTime -> String
+showTimeDiff sec
+  | si <  100  = printf "%4.1fs" (fromRational s :: Double)
+  | si <= 9999 = printf "%4ds" si
+  | mi <  100  = printf "%4.1fm" (fromRational m :: Double)
+  | mi <= 9999 = printf "%4dm" mi
+  | hi <  100  = printf "%4.1fs" (fromRational h :: Double)
+  | otherwise  = printf "%4dh" hi
+  where
+    s :: Rational
+    s = realToFrac sec
+
+    si :: Integer
+    si = round s
+
+    m :: Rational
+    m = s / 60
+
+    mi :: Integer
+    mi = round m
+
+    h :: Rational
+    h = m / 60
+
+    hi :: Integer
+    hi = round h
+
 {--------------------------------------------------------------------
   constraint implementation
 --------------------------------------------------------------------}
@@ -2210,10 +2340,14 @@
         then return True
         else go xs
 
+#if !MIN_VERSION_base(4,6,0)
+
 modifyIORef' :: IORef a -> (a -> a) -> IO ()
 modifyIORef' ref f = do
   x <- readIORef ref
   writeIORef ref $! f x
+
+#endif
 
 shift :: IORef [a] -> IO a
 shift ref = do
diff --git a/src/SAT/Integer.hs b/src/SAT/Integer.hs
--- a/src/SAT/Integer.hs
+++ b/src/SAT/Integer.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE TypeFamilies #-}
 module SAT.Integer
   ( Expr (..)
   , newVar
@@ -10,10 +10,10 @@
 
 import Control.Monad
 import Data.Array.IArray
+import Data.VectorSpace
 import Text.Printf
 
 import Data.ArithRel
-import Data.Linear
 import qualified SAT
 import qualified SAT.TseitinEncoder as TseitinEncoder
 
@@ -29,10 +29,14 @@
   SAT.addPBAtMost solver xs hi'
   return $ Expr ((lo,[]) : [(c,[x]) | (c,x) <- xs])
 
-instance Module Integer Expr where
-  n .*. Expr xs = Expr [(n*m,lits) | (m,lits) <- xs]
-  Expr xs1 .+. Expr xs2 = Expr (xs1++xs2)
-  lzero = Expr []
+instance AdditiveGroup Expr where
+  Expr xs1 ^+^ Expr xs2 = Expr (xs1++xs2)
+  zeroV = Expr []
+  negateV = ((-1) *^)
+
+instance VectorSpace Expr where
+  type Scalar Expr = Integer
+  n *^ Expr xs = Expr [(n*m,lits) | (m,lits) <- xs]
 
 instance Num Expr where
   Expr xs1 + Expr xs2 = Expr (xs1++xs2)
diff --git a/src/SAT/MUS.hs b/src/SAT/MUS.hs
--- a/src/SAT/MUS.hs
+++ b/src/SAT/MUS.hs
@@ -26,7 +26,7 @@
 data Options
   = Options
   { optLogger     :: String -> IO ()
-  , optUpdater    :: [Lit] -> IO ()
+  , optUpdateBest :: [Lit] -> IO ()
   , optLitPrinter :: Lit -> String
   }
 
@@ -35,7 +35,7 @@
 defaultOptions =
   Options
   { optLogger     = \_ -> return ()
-  , optUpdater    = \_ -> return ()
+  , optUpdateBest = \_ -> return ()
   , optLitPrinter = show
   }
 
@@ -58,7 +58,7 @@
     log = optLogger opt
 
     update :: [Lit] -> IO ()
-    update = optUpdater opt
+    update = optUpdateBest opt
 
     showLit :: Lit -> String
     showLit = optLitPrinter opt
diff --git a/src/SAT/PBO.hs b/src/SAT/PBO.hs
--- a/src/SAT/PBO.hs
+++ b/src/SAT/PBO.hs
@@ -1,8 +1,9 @@
+{-# LANGUAGE DoAndIfThenElse #-}
 {-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  SAT.PBO
--- Copyright   :  (c) Masahiro Sakai 2012
+-- Copyright   :  (c) Masahiro Sakai 2012-2013
 -- License     :  BSD-style
 -- 
 -- Maintainer  :  masahiro.sakai@gmail.com
@@ -14,115 +15,197 @@
 -----------------------------------------------------------------------------
 module SAT.PBO where
 
+import Control.Exception
 import Control.Monad
 import Data.List
 import Data.Ord
 import Text.Printf
 import SAT
 import SAT.Types
+import qualified SAT.PBO.UnsatBased as UnsatBased
+import qualified SAT.PBO.MSU4 as MSU4
 
 data SearchStrategy
   = LinearSearch
   | BinarySearch
--- 'nothaddock' is inserted not to confuse haddock
-  -- nothaddock | AdaptiveSearch
+  | AdaptiveSearch
+  | UnsatBased
+  | MSU4
 
 data Options
   = Options
   { optLogger               :: String -> IO ()
-  , optUpdater              :: Model -> Integer -> IO ()
+  , optUpdateBest           :: Model -> Integer -> IO ()
+  , optUpdateLB             :: Integer -> IO ()
   , optObjFunVarsHeuristics :: Bool
   , optSearchStrategy       :: SearchStrategy
+  , optTrialLimitConf       :: Int
   }
 
 defaultOptions :: Options
 defaultOptions
   = Options
   { optLogger               = \_ -> return ()
-  , optUpdater              = \_ _ -> return ()
+  , optUpdateBest           = \_ _ -> return ()
+  , optUpdateLB             = \_ -> return ()
   , optObjFunVarsHeuristics = True
   , optSearchStrategy       = LinearSearch
+  , optTrialLimitConf       = 1000
   }
 
 minimize :: Solver -> [(Integer, Lit)] -> Options -> IO (Maybe Model)
 minimize solver obj opt = do
-  when (optObjFunVarsHeuristics opt) $ do
-    forM_ obj $ \(c,l) -> do
-      let p = if c > 0 then not (litPolarity l) else litPolarity l
-      setVarPolarity solver (litVar l) p
-    forM_ (zip [1..] (map snd (sortBy (comparing fst) [(abs c, l) | (c,l) <- obj]))) $ \(n,l) -> do
-      replicateM n $ varBumpActivity solver (litVar l)
+  when (optObjFunVarsHeuristics opt) $ tweakParams solver obj
 
-  result <- solve solver
-  if not result then
-     return Nothing
-   else
-     case optSearchStrategy opt of
-       LinearSearch -> liftM Just linSearch
-       BinarySearch -> liftM Just binSearch
+  case optSearchStrategy opt of
+    UnsatBased -> do
+      let opt2 = UnsatBased.defaultOptions
+                 { UnsatBased.optLogger     = optLogger opt
+                 , UnsatBased.optUpdateBest = optUpdateBest opt
+                 , UnsatBased.optUpdateLB   = optUpdateLB opt
+                 }
+      UnsatBased.solve solver obj opt2
+    MSU4 -> do
+      let opt2 = MSU4.defaultOptions
+                 { MSU4.optLogger     = optLogger opt
+                 , MSU4.optUpdateBest = optUpdateBest opt
+                 , MSU4.optUpdateLB   = optUpdateLB opt
+                 }
+      MSU4.solve solver obj opt2
+    _ -> do
+      updateLB (pbLowerBound obj)
+      result <- solve solver
+      if not result then
+        return Nothing
+      else
+        case optSearchStrategy opt of
+          LinearSearch   -> liftM Just linSearch
+          BinarySearch   -> liftM Just binSearch
+          AdaptiveSearch -> liftM Just adaptiveSearch
+          _              -> error "SAT.PBO.minimize: should not happen"
 
   where
-   logIO :: String -> IO ()
-   logIO = optLogger opt
+    logIO :: String -> IO ()
+    logIO = optLogger opt
 
-   update :: Model -> Integer -> IO ()
-   update = optUpdater opt
+    updateBest :: Model -> Integer -> IO ()
+    updateBest = optUpdateBest opt
 
-   linSearch :: IO Model
-   linSearch = do
-     m <- model solver
-     let v = pbEval m obj
-     update m v
-     addPBAtMost solver obj (v - 1)
-     result <- solve solver
-     if result
-       then linSearch
-       else return m
+    updateLB :: Integer -> IO ()
+    updateLB = optUpdateLB opt
 
-   binSearch :: IO Model
-   binSearch = do
-{-
-     logIO $ printf "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 (litVar l)
-         ]
--}
-     m0 <- model solver
-     let v0 = pbEval m0 obj
-     update m0 v0
-     let ub0 = v0 - 1
-         lb0 = pbLowerBound obj
-     addPBAtMost solver obj ub0
+    linSearch :: IO Model
+    linSearch = do
+      m <- model solver
+      let v = pbEval m obj
+      updateBest m v
+      addPBAtMost solver obj (v - 1)
+      result <- solve solver
+      if result
+        then linSearch
+        else return m
 
-     let loop lb ub m | ub < lb = return m
-         loop lb ub m = do
-           let mid = (lb + ub) `div` 2
-           logIO $ printf "Binary Search: %d <= obj <= %d; guessing obj <= %d" lb ub mid
-           sel <- newVar solver
-           addPBAtMostSoft solver sel obj mid
-           ret <- solveWith solver [sel]
-           if ret
-           then do
-             m2 <- model solver
-             let v = pbEval m2 obj
-             update m2 v
-             -- deactivating temporary constraint
-             -- FIXME: 本来は制約の削除をしたい
-             addClause solver [-sel]
-             let ub' = v - 1
-             logIO $ printf "Binary Search: updating upper bound: %d -> %d" ub ub'
-             addPBAtMost solver obj ub'
-             loop lb ub' m2
-           else do
-             -- deactivating temporary constraint
-             -- FIXME: 本来は制約の削除をしたい
-             addClause solver [-sel]
-             let lb' = mid + 1
-             logIO $ printf "Binary Search: updating lower bound: %d -> %d" lb lb'
-             addPBAtLeast solver obj lb'
-             loop lb' ub m
+    binSearch :: IO Model
+    binSearch = do
+      m0 <- model solver
+      let v0 = pbEval m0 obj
+      updateBest m0 v0
+      let ub0 = v0 - 1
+          lb0 = pbLowerBound obj
+      addPBAtMost solver obj ub0
+      loop lb0 ub0 m0
+      where
+        loop lb ub m | ub < lb = return m
+        loop lb ub m = do
+          let mid = (lb + ub) `div` 2
+          logIO $ printf "Binary Search: %d <= obj <= %d; guessing obj <= %d" lb ub mid
+          sel <- newVar solver
+          addPBAtMostSoft solver sel obj mid
+          ret <- solveWith solver [sel]
+          if ret then do
+            m2 <- model solver
+            let v = pbEval m2 obj
+            updateBest m2 v
+            -- deleting temporary constraint
+            -- ただし、これに依存した補題を活かすためには残したほうが良い?
+            addClause solver [-sel]
+            let ub' = v - 1
+            logIO $ printf "Binary Search: updating upper bound: %d -> %d" ub ub'
+            addPBAtMost solver obj ub'
+            loop lb ub' m2
+          else do
+            -- deleting temporary constraint
+            addClause solver [-sel]
+            let lb' = mid + 1
+            updateLB lb'
+            logIO $ printf "Binary Search: updating lower bound: %d -> %d" lb lb'
+            addPBAtLeast solver obj lb'
+            loop lb' ub m
 
-     loop lb0 ub0 m0
+    -- adaptive search strategy from pbct-0.1.3 <http://www.residual.se/pbct/>
+    adaptiveSearch :: IO Model
+    adaptiveSearch = do
+      m0 <- model solver
+      let v0 = pbEval m0 obj
+      updateBest m0 v0
+      let ub0 = v0 - 1
+          lb0 = pbLowerBound obj
+      addPBAtMost solver obj ub0
+      loop lb0 ub0 (0::Rational) m0
+      where
+        loop lb ub _ m | ub < lb = return m
+        loop lb ub fraction m = do
+          let interval = ub - lb
+              mid = ub - floor (fromIntegral interval * fraction)
+          if ub == mid then do
+            logIO $ printf "Adaptive Search: %d <= obj <= %d" lb ub
+            result <- solve solver
+            if result then do
+              m2 <- model solver
+              let v = pbEval m2 obj
+              updateBest m2 v
+              let ub'   = v - 1
+                  fraction' = min 0.5 (fraction + 0.1)
+              loop lb ub' fraction' m2
+            else
+              return m
+          else do
+            logIO $ printf "Adaptive Search: %d <= obj <= %d; guessing obj <= %d" lb ub mid
+            sel <- newVar solver
+            addPBAtMostSoft solver sel obj mid
+            setConfBudget solver $ Just (optTrialLimitConf opt)
+            ret' <- try $ solveWith solver [sel]
+            setConfBudget solver Nothing
+            case ret' of
+              Left BudgetExceeded -> do
+                let fraction' = max 0 (fraction - 0.05)
+                loop lb ub fraction' m
+              Right ret -> do
+                let fraction' = min 0.5 (fraction + 0.1)
+                if ret then do
+                  m2 <- model solver
+                  let v = pbEval m2 obj
+                  updateBest m2 v
+                  -- deleting temporary constraint
+                  -- ただし、これに依存した補題を活かすためには残したほうが良い?
+                  addClause solver [-sel]
+                  let ub' = v - 1
+                  logIO $ printf "Adaptive Search: updating upper bound: %d -> %d" ub ub'
+                  addPBAtMost solver obj ub'
+                  loop lb ub' fraction' m2
+                else do
+                  -- deleting temporary constraint
+                  addClause solver [-sel]
+                  let lb' = mid + 1
+                  updateLB lb'
+                  logIO $ printf "Adaptive Search: updating lower bound: %d -> %d" lb lb'
+                  addPBAtLeast solver obj lb'
+                  loop lb' ub fraction' m
+
+tweakParams :: Solver -> [(Integer, Lit)] -> IO ()
+tweakParams solver obj = do
+  forM_ obj $ \(c,l) -> do
+    let p = if c > 0 then not (litPolarity l) else litPolarity l
+    setVarPolarity solver (litVar l) p
+  forM_ (zip [1..] (map snd (sortBy (comparing fst) [(abs c, l) | (c,l) <- obj]))) $ \(n,l) -> do
+    replicateM n $ varBumpActivity solver (litVar l)
diff --git a/src/SAT/PBO/MSU4.hs b/src/SAT/PBO/MSU4.hs
new file mode 100644
--- /dev/null
+++ b/src/SAT/PBO/MSU4.hs
@@ -0,0 +1,108 @@
+{-# LANGUAGE DoAndIfThenElse #-}
+{-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  SAT.PBO.MSU4
+-- Copyright   :  (c) Masahiro Sakai 2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+-- 
+-- Reference:
+--
+-- * João P. Marques-Silva and Jordi Planes.
+--   Algorithms for Maximum Satisfiability using Unsatisfiable Cores.
+--   In Design, Automation and Test in Europe, 2008 (DATE '08). March 2008.
+--   pp. 408-413, doi:10.1109/date.2008.4484715.
+--   <http://dx.doi.org/10.1109/date.2008.4484715>
+--   <http://eprints.soton.ac.uk/265000/1/jpms-date08.pdf>
+--   <http://www.csi.ucd.ie/staff/jpms/talks/talksite/jpms-date08.pdf>
+--
+-----------------------------------------------------------------------------
+module SAT.PBO.MSU4
+  ( Options (..)
+  , defaultOptions
+  , solve
+  , solveWBO
+  ) where
+
+import qualified Data.IntSet as IS
+import qualified Data.IntMap as IM
+import qualified SAT as SAT
+import SAT.Types
+
+import Text.Printf
+
+data Options
+  = Options
+  { optLogger      :: String -> IO ()
+  , optUpdateBest  :: SAT.Model -> Integer -> IO ()
+  , optUpdateLB    :: Integer -> IO ()
+  }
+
+defaultOptions :: Options
+defaultOptions
+  = Options
+  { optLogger     = \_ -> return ()
+  , optUpdateBest = \_ _ -> return ()
+  , optUpdateLB   = \_ -> return ()
+  }
+
+solve :: SAT.Solver -> [(Integer, SAT.Lit)] -> Options -> IO (Maybe SAT.Model)
+solve solver obj opt = do
+  result <- solveWBO solver [(-v, c) | (c,v) <- obj'] opt'
+  case result of
+    Nothing -> return Nothing
+    Just (m,_) -> return (Just m)
+  where
+    (obj',offset) = normalizePBSum (obj,0)
+    opt' =
+      opt
+      { optUpdateBest = \m val -> optUpdateBest opt m (offset + val)
+      , optUpdateLB   = \val -> optUpdateLB opt (offset + val)
+      }
+
+solveWBO :: SAT.Solver -> [(Lit, Integer)] -> Options -> IO (Maybe (SAT.Model, Integer))
+solveWBO solver sels opt = do
+  optUpdateLB opt 0
+  loop (IM.keysSet weights) IS.empty 0 Nothing
+
+  where
+    weights = IM.fromList sels
+    
+    loop :: IS.IntSet -> IS.IntSet -> Integer -> Maybe (SAT.Model, Integer) -> IO (Maybe (SAT.Model, Integer))
+    loop unrelaxed relaxed lb best = do
+      ret <- SAT.solveWith solver (IS.toList unrelaxed)
+      if ret then do
+        currModel <- SAT.model solver
+        let violated = [weights IM.! l | l <- IS.toList relaxed, evalLit currModel l == False]
+            currVal = sum violated
+        best' <-
+          case best of
+            Just (_, bestVal)
+              | currVal < bestVal -> do
+                  optUpdateBest opt currModel currVal
+                  return $ Just (currModel, currVal)
+              | otherwise -> do
+                  return best
+            Nothing -> do
+              optUpdateBest opt currModel currVal
+              return $ Just (currModel, currVal)
+        SAT.addPBAtMost solver [(c,-l) | (l,c) <- sels] (currVal - 1)
+        cont unrelaxed relaxed lb best'
+      else do
+        core <- SAT.failedAssumptions solver
+        let ls = IS.fromList core `IS.intersection` unrelaxed
+        if IS.null ls then do
+          return best
+        else do
+          SAT.addAtLeast solver [-l | l <- IS.toList ls] 1
+          let lb' = lb + minimum [weights IM.! l | l <- IS.toList ls]
+          optUpdateLB opt lb'
+          cont (unrelaxed `IS.difference` ls)  (relaxed `IS.union` ls) lb' best
+
+    cont :: IS.IntSet -> IS.IntSet -> Integer -> Maybe (SAT.Model, Integer) -> IO (Maybe (SAT.Model, Integer))
+    cont _ _ lb best@(Just (_, bestVal)) | lb == bestVal  = return best
+    cont unrelaxed relaxed lb best = loop unrelaxed relaxed lb best
diff --git a/src/SAT/PBO/UnsatBased.hs b/src/SAT/PBO/UnsatBased.hs
new file mode 100644
--- /dev/null
+++ b/src/SAT/PBO/UnsatBased.hs
@@ -0,0 +1,92 @@
+{-# LANGUAGE BangPatterns, DoAndIfThenElse #-}
+{-# OPTIONS_GHC -Wall #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  SAT.PBO.UnsatBased
+-- Copyright   :  (c) Masahiro Sakai 2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  non-portable
+--
+-----------------------------------------------------------------------------
+module SAT.PBO.UnsatBased
+  ( Options (..)
+  , defaultOptions
+  , solve
+  , solveWBO
+  ) where
+
+import Control.Monad
+import qualified Data.IntMap as IM
+import qualified SAT as SAT
+import qualified SAT.Types as SAT
+
+data Options
+  = Options
+  { optLogger     :: String -> IO ()
+  , optUpdateBest :: SAT.Model -> Integer -> IO ()
+  , optUpdateLB   :: Integer -> IO ()
+  }
+
+defaultOptions :: Options
+defaultOptions
+  = Options
+  { optLogger     = \_ -> return ()
+  , optUpdateBest = \_ _ -> return ()
+  , optUpdateLB   = \_ -> return ()
+  }
+
+solve :: SAT.Solver -> [(Integer, SAT.Lit)] -> Options -> IO (Maybe SAT.Model)
+solve solver obj opt = do
+  result <- solveWBO solver [(-v, c) | (c,v) <- obj'] opt'
+  case result of
+    Nothing -> return Nothing
+    Just (m,_) -> return (Just m)
+  where
+    (obj',offset) = SAT.normalizePBSum (obj,0)
+    opt' =
+      opt
+      { optUpdateBest = \m val -> optUpdateBest opt m (offset + val)
+      , optUpdateLB   = \val -> optUpdateLB opt (offset + val)
+      }
+
+solveWBO :: SAT.Solver -> [(SAT.Lit, Integer)] -> Options -> IO (Maybe (SAT.Model, Integer))
+solveWBO solver sels0 opt = loop 0 (IM.fromList sels0)
+  where
+    loop :: Integer -> IM.IntMap Integer -> IO (Maybe (SAT.Model, Integer))
+    loop !lb sels = do
+      optUpdateLB opt lb
+
+      ret <- SAT.solveWith solver (IM.keys sels)
+      if ret
+      then do
+        m <- SAT.model solver
+        -- 余計な変数を除去する?
+        optUpdateBest opt m lb
+        return $ Just (m, lb)
+      else do
+        core <- SAT.failedAssumptions solver
+        case core of
+          [] -> return Nothing
+          _  -> do
+            let !min_c = minimum [sels IM.! sel | sel <- core]
+                !lb' = lb + min_c
+
+            xs <- forM core $ \sel -> do
+              r <- SAT.newVar solver
+              return (sel, r)
+            SAT.addAtMost solver (map snd xs) 1
+            SAT.addClause solver [-l | l <- core] -- optional constraint but sometimes useful
+
+            ys <- liftM IM.unions $ forM xs $ \(sel, r) -> do
+              s <- SAT.newVar solver
+              SAT.addClause solver [-s, r, sel]
+              let c = sels IM.! sel
+              if c > min_c
+                then return $ IM.fromList [(s, min_c), (sel, c - min_c)]
+                else return $ IM.singleton s min_c
+            let sels' = IM.union ys (IM.difference sels (IM.fromList [(sel, ()) | sel <- core]))
+
+            loop lb' sels'
diff --git a/src/SAT/Types.hs b/src/SAT/Types.hs
--- a/src/SAT/Types.hs
+++ b/src/SAT/Types.hs
@@ -30,6 +30,7 @@
   , normalizeAtLeast
 
   -- * Pseudo Boolean Constraint
+  , normalizePBSum
   , normalizePBAtLeast
   , normalizePBExactly
   , cutResolve
@@ -130,13 +131,10 @@
      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
+-- | normalizing PB term of the form /c1 x1 + c2 x2 ... cn xn + c/ into
+-- /d1 x1 + d2 x2 ... dm xm + d/ where d1,...,dm ≥ 1.
+normalizePBSum :: ([(Integer,Lit)], Integer) -> ([(Integer,Lit)], Integer)
+normalizePBSum = step2 . step1
   where
     -- 同じ変数が複数回現れないように、一度全部 @v@ に統一。
     step1 :: ([(Integer,Lit)], Integer) -> ([(Integer,Lit)], Integer)
@@ -149,7 +147,7 @@
         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
+            else loop (IM.insertWith (+) (litNot l) (negate c) ys, m+c) zs
 
     -- 係数が0のものも取り除き、係数が負のリテラルを反転することで、
     -- 係数が正になるようにする。
@@ -159,9 +157,22 @@
         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
+          | c < 0  = loop ((negate c,litNot l):ys, m+c) zs
           | otherwise = loop (t:ys,m) zs
 
+-- | normalizing PB constraint of the form /c1 x1 + c2 cn ... cn xn >= b/.
+normalizePBAtLeast :: ([(Integer,Lit)], Integer) -> ([(Integer,Lit)], Integer)
+normalizePBAtLeast a =
+　case step1 a of
+    (xs,n)
+      | n > 0     -> step3 (saturate n xs, n)
+      | otherwise -> ([], 0) -- trivially true
+  where
+    step1 :: ([(Integer,Lit)], Integer) -> ([(Integer,Lit)], Integer)
+    step1 (xs,n) =
+      case normalizePBSum (xs,-n) of
+        (ys,m) -> (ys, -m)
+
     -- degree以上の係数はそこで抑える。
     saturate :: Integer -> [(Integer,Lit)] -> [(Integer,Lit)]
     saturate n xs = [assert (c>0) (min n c, l) | (c,l) <- xs]
@@ -176,39 +187,20 @@
 -- | 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
+　case step1 $ a of
     (xs,n)
-      | n >= 0    -> step3 (xs, n)
+      | n >= 0    -> step2 (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
+      case normalizePBSum (xs,-n) of
+        (ys,m) -> (ys, -m)
 
     -- omega test と同様の係数の gcd による単純化
-    step3 :: ([(Integer,Lit)], Integer) -> ([(Integer,Lit)], Integer)
-    step3 ([],n) = ([],n)
-    step3 (xs,n)
+    step2 :: ([(Integer,Lit)], Integer) -> ([(Integer,Lit)], Integer)
+    step2 ([],n) = ([],n)
+    step2 (xs,n)
       | n `mod` d == 0 = ([(c `div` d, l) | (c,l) <- xs], n `div` d)
       | otherwise      = ([], 1) -- false
       where
diff --git a/src/Text/GCNF.hs b/src/Text/GCNF.hs
--- a/src/Text/GCNF.hs
+++ b/src/Text/GCNF.hs
@@ -27,6 +27,7 @@
   ) where
 
 import qualified SAT.Types as SAT
+import Text.Util
 
 data GCNF
   = GCNF
@@ -77,15 +78,15 @@
 parseLine s =
   case words s of
     (('{':w):xs) ->
-        let ys  = map read $ init xs
-            idx = read $ init w
+        let ys  = map readInt $ init xs
+            idx = readInt $ init w
         in seq idx $ seqList ys $ (idx, ys)
     _ -> error "parse error"
 
 parseCNFLine :: String -> SAT.Clause
 parseCNFLine s = seq xs $ seqList xs $ xs
   where
-    xs = init (map read (words s))
+    xs = init (map readInt (words s))
 
 seqList :: [a] -> b -> b
 seqList [] b = b
diff --git a/src/Text/MaxSAT.hs b/src/Text/MaxSAT.hs
--- a/src/Text/MaxSAT.hs
+++ b/src/Text/MaxSAT.hs
@@ -26,6 +26,7 @@
   ) where
 
 import qualified SAT.Types as SAT
+import Text.Util
 
 data WCNF
   = WCNF
@@ -83,16 +84,17 @@
 
 parseWCNFLine :: String -> WeightedClause
 parseWCNFLine s =
-  case map read (words s) of
+  case words s of
     (w:xs) ->
-        let ys = map fromIntegral $ init xs
-        in seq w $ seqList ys $ (w, ys)
+        let w' = readUnsignedInteger w
+            ys = map readInt $ 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))
+    xs = init (map readInt (words s))
 
 seqList :: [a] -> b -> b
 seqList [] b = b
diff --git a/src/Text/PBFile.hs b/src/Text/PBFile.hs
--- a/src/Text/PBFile.hs
+++ b/src/Text/PBFile.hs
@@ -59,6 +59,7 @@
 import Data.Word
 import Control.Exception (assert)
 import Text.Printf
+import Text.Util
 
 -- | Pair of /objective function/ and a list of constraints.
 type Formula = (Maybe Sum, [Constraint])
@@ -171,42 +172,6 @@
   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)
@@ -335,7 +300,7 @@
     size = showString (printf "* #variable= %d #constraint= %d\n" nv nc)
     part1 = 
       case top of
-        Nothing -> showString "soft: "
+        Nothing -> showString "soft: ;\n"
         Just t -> showString "soft: " . showsPrec 0 t . showString ";\n"
     part2 = foldr (.) id (map showSoftConstraint cs)
 
diff --git a/src/Text/Util.hs b/src/Text/Util.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Util.hs
@@ -0,0 +1,79 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Text.Util
+-- Copyright   :  (c) Masahiro Sakai 2012-2013
+-- License     :  BSD-style
+-- 
+-- Maintainer  :  masahiro.sakai@gmail.com
+-- Stability   :  provisional
+-- Portability :  portable
+--
+-----------------------------------------------------------------------------
+module Text.Util
+  ( readInt
+  , readUnsignedInteger
+  ) where
+
+import Control.Exception
+import Data.Word
+
+{-# INLINABLE readInt #-}
+readInt :: String -> Int
+readInt ('-':str) = - readUnsignedInt str
+readInt str = readUnsignedInt str
+
+{-# INLINABLE readUnsignedInt #-}
+readUnsignedInt :: String -> Int
+readUnsignedInt str = go 0 str
+  where
+    go !r [] = r
+    go !r (c:cs) = go (r*10 + charToInt c) cs
+
+    charToInt :: Char -> Int
+    charToInt '0' = 0
+    charToInt '1' = 1
+    charToInt '2' = 2
+    charToInt '3' = 3
+    charToInt '4' = 4
+    charToInt '5' = 5
+    charToInt '6' = 6
+    charToInt '7' = 7
+    charToInt '8' = 8
+    charToInt '9' = 9
+
+-- | '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.
+{-# INLINABLE readUnsignedInteger #-}
+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
diff --git a/src/Version.hs b/src/Version.hs
--- a/src/Version.hs
+++ b/src/Version.hs
@@ -26,6 +26,9 @@
 #ifdef VERSION_containers
   , ("containers",   VERSION_containers   )
 #endif
+#ifdef VERSION_data_interval
+  , ("data-interval",VERSION_data_interval)
+#endif
 #ifdef VERSION_deepseq
   , ("deepseq",      VERSION_deepseq      )
 #endif
@@ -64,6 +67,9 @@
 #endif
 #ifdef VERSION_unbounded_delays
   , ("unbounded-delays", VERSION_unbounded_delays)
+#endif
+#ifdef VERSION_vector_space
+  , ("vector-space", VERSION_vector_space)
 #endif
 #ifdef VERSION_logic_TPTP
   , ("logic-TPTP",   VERSION_logic_TPTP   )
diff --git a/test/TestContiTraverso.hs b/test/TestContiTraverso.hs
--- a/test/TestContiTraverso.hs
+++ b/test/TestContiTraverso.hs
@@ -4,7 +4,9 @@
 import Control.Monad
 import Data.List
 import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
 import qualified Data.Map as Map
+import Data.VectorSpace
 import Test.HUnit hiding (Test)
 import Test.Framework (Test, defaultMain, testGroup)
 import Test.Framework.TH
@@ -13,27 +15,27 @@
 import Algorithm.ContiTraverso
 
 import Data.ArithRel
-import Data.Linear
 import qualified Data.LA as LA
 import Data.OptDir
 import Data.Polynomial
 
 -- http://madscientist.jp/~ikegami/articles/IntroSequencePolynomial.html
 -- optimum is (3,2,0)
-case_ikegami = solve grlex OptMin obj cs @?= Just (IM.fromList [(1,3),(2,2),(3,0)])
+case_ikegami = solve grlex (IS.fromList vs) OptMin obj cs @?= Just (IM.fromList [(1,3),(2,2),(3,0)])
   where
-    [x,y,z] = map LA.var [1..3]
-    cs = [ 2.*.x .+. 2.*.y .+. 2.*.z .==. LA.constant 10
-         , 3.*.x .+. y .+. z .==. LA.constant 11
+    vs = [1..3]
+    [x,y,z] = map LA.var vs
+    cs = [ 2*^x ^+^ 2*^y ^+^ 2*^z .==. LA.constant 10
+         , 3*^x ^+^ y ^+^ z .==. LA.constant 11
          , x .>=. LA.constant 0
          , y .>=. LA.constant 0
          , z .>=. LA.constant 0
          ]
-    obj = x .+. 2.*.y .+. 3.*.z
+    obj = x ^+^ 2*^y ^+^ 3*^z
 
-case_ikegami' = solve' grlex obj cs @?= Just (IM.fromList [(1,3),(2,2),(3,0)])
+case_ikegami' = solve' grlex (IS.fromList vs) obj cs @?= Just (IM.fromList [(1,3),(2,2),(3,0)])
   where
-    [x,y,z] = [1..3]
+    vs@[x,y,z] = [1..3]
     cs = [ (LA.fromTerms [(2,x),(2,y),(2,z)], 10)
          , (LA.fromTerms [(3,x),(1,y),(1,z)], 11)
          ]
@@ -41,19 +43,20 @@
 
 -- http://posso.dm.unipi.it/users/traverso/conti-traverso-ip.ps
 -- optimum is (39, 75, 1, 8, 122)
-disabled_case_test1 = solve grlex OptMin obj cs @?= Just (IM.fromList [(1,39), (2,75), (3,1), (4,8), (5,122)])
+disabled_case_test1 = solve grlex (IS.fromList vs) OptMin obj cs @?= Just (IM.fromList [(1,39), (2,75), (3,1), (4,8), (5,122)])
   where
-    vs@[x1,x2,x3,x4,x5] = map LA.var [1..5]
-    cs = [ 2.*.x1 .+. 5.*.x2 .-. 3.*.x3 .+.     x4 .-. 2.*.x5 .==. LA.constant 214
-         ,     x1 .+. 7.*.x2 .+. 2.*.x3 .+. 3.*.x4 .+.     x5 .==. LA.constant 712
-         , 4.*.x1 .-. 2.*.x2 .-.     x3 .-. 5.*.x4 .+. 3.*.x5 .==. LA.constant 331
+    vs = [1..5]
+    vs2@[x1,x2,x3,x4,x5] = map LA.var vs
+    cs = [ 2*^x1 ^+^ 5*^x2 ^-^ 3*^x3 ^+^    x4 ^-^ 2*^x5 .==. LA.constant 214
+         ,    x1 ^+^ 7*^x2 ^+^ 2*^x3 ^+^ 3*^x4 ^+^    x5 .==. LA.constant 712
+         , 4*^x1 ^-^ 2*^x2 ^-^    x3 ^-^ 5*^x4 ^+^ 3*^x5 .==. LA.constant 331
          ] ++
-         [ v .>=. LA.constant 0 | v <- vs ]
-    obj = x1 .+. x2 .+. x3 .+. x4 .+. x5
+         [ v .>=. LA.constant 0 | v <- vs2 ]
+    obj = x1 ^+^ x2 ^+^ x3 ^+^ x4 ^+^ x5
 
-disabled_case_test1' = solve' grlex obj cs @?= Just (IM.fromList [(1,39), (2,75), (3,1), (4,8), (5,122)])
+disabled_case_test1' = solve' grlex (IS.fromList vs) obj cs @?= Just (IM.fromList [(1,39), (2,75), (3,1), (4,8), (5,122)])
   where
-    [x1,x2,x3,x4,x5] = [1..5]
+    vs@[x1,x2,x3,x4,x5] = [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)
@@ -61,30 +64,32 @@
     obj = LA.fromTerms [(1,x1),(1,x2),(1,x3),(1,x4),(1,x5)]
 
 -- optimum is (0,2,2)
-case_test2 = solve grlex OptMin obj cs @?= Just (IM.fromList [(1,0),(2,2),(3,2)])
+case_test2 = solve grlex (IS.fromList vs) OptMin obj cs @?= Just (IM.fromList [(1,0),(2,2),(3,2)])
   where
-    vs@[x1,x2,x3] = map LA.var [1..3]
-    cs = [ 2.*.x1 .+. 3.*.x2 .-. x3 .==. LA.constant 4 ] ++
-         [ v .>=. LA.constant 0 | v <- vs ]
-    obj = 2.*.x1 .+. x2
+    vs = [1..3]
+    vs2@[x1,x2,x3] = map LA.var vs
+    cs = [ 2*^x1 ^+^ 3*^x2 ^-^ x3 .==. LA.constant 4 ] ++
+         [ v .>=. LA.constant 0 | v <- vs2 ]
+    obj = 2*^x1 ^+^ x2
 
-case_test2' = solve' grlex obj cs @?= Just (IM.fromList [(1,0),(2,2),(3,2)])
+case_test2' = solve' grlex (IS.fromList vs) obj cs @?= Just (IM.fromList [(1,0),(2,2),(3,2)])
   where
-    [x1,x2,x3] = [1..3]
+    vs@[x1,x2,x3] = [1..3]
     cs = [ (LA.fromTerms [(2, x1), (3, x2), (-1, x3)], 4) ]
     obj = LA.fromTerms [(2,x1),(1,x2)]
 
 -- infeasible
-case_test3 = solve grlex OptMin obj cs @?= Nothing
+case_test3 = solve grlex (IS.fromList vs) OptMin obj cs @?= Nothing
   where
-    vs@[x1,x2,x3] = map LA.var [1..3]
-    cs = [ 2.*.x1 .+. 2.*.x2 .+. 2.*.x3 .==. LA.constant 3 ] ++
-         [ v .>=. LA.constant 0 | v <- vs ]
+    vs = [1..3]
+    vs2@[x1,x2,x3] = map LA.var vs
+    cs = [ 2*^x1 ^+^ 2*^x2 ^+^ 2*^x3 .==. LA.constant 3 ] ++
+         [ v .>=. LA.constant 0 | v <- vs2 ]
     obj = x1
 
-case_test3' = solve' grlex obj cs @?= Nothing
+case_test3' = solve' grlex (IS.fromList vs) obj cs @?= Nothing
   where
-    [x1,x2,x3] = [1..3]
+    vs@[x1,x2,x3] = [1..3]
     cs = [ (LA.fromTerms [(2, x1), (2, x2), (2, x3)], 3) ]
     obj = LA.fromTerms [(1,x1)]
 
diff --git a/test/TestInterval.hs b/test/TestInterval.hs
deleted file mode 100644
--- a/test/TestInterval.hs
+++ /dev/null
@@ -1,469 +0,0 @@
-{-# 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/test/TestMIPSolver2.hs b/test/TestMIPSolver2.hs
--- a/test/TestMIPSolver2.hs
+++ b/test/TestMIPSolver2.hs
@@ -6,18 +6,17 @@
 import Data.Ratio
 import qualified Data.IntMap as IM
 import qualified Data.IntSet as IS
+import Data.VectorSpace
 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 qualified Data.LA as LA
 import qualified Algorithm.Simplex2 as Simplex2
 import Algorithm.Simplex2
 import qualified Algorithm.MIPSolver2 as MIPSolver2
---import Algorithm.MIPSolver2
 
 ------------------------------------------------------------------------
 
@@ -29,11 +28,11 @@
     x2 = LA.var 2
     x3 = LA.var 3
     x4 = LA.var 4
-    obj = x1 .+. 2 .*. x2 .+. 3 .*. x3 .+. x4
+    obj = x1 ^+^ 2 *^ x2 ^+^ 3 *^ x3 ^+^ x4
     cs =
-      [ (-1) .*. x1 .+. x2 .+. x3 .+. 10.*.x4 .<=. LA.constant 20
-      , x1 .-. 3 .*. x2 .+. x3 .<=. LA.constant 30
-      , x2 .-. 3.5 .*. x4 .==. LA.constant 0
+      [ (-1) *^ x1 ^+^ x2 ^+^ x3 ^+^ 10*^x4 .<=. LA.constant 20
+      , x1 ^-^ 3 *^ x2 ^+^ x3 .<=. LA.constant 30
+      , x2 ^-^ 3.5 *^ x4 .==. LA.constant 0
       , LA.constant 0 .<=. x1
       , x1 .<=. LA.constant 40
       , LA.constant 0 .<=. x2
@@ -67,7 +66,7 @@
   lp <- Simplex2.newSolver
   replicateM 5 (Simplex2.newVar lp)
   setOptDir lp (f optdir)
-  setObj lp (lnegate obj)
+  setObj lp (negateV obj)
   mapM_ (Simplex2.assertAtom lp) cs
   mip <- MIPSolver2.newSolver lp ivs
   ret <- MIPSolver2.optimize mip (\_ _ -> return ())
@@ -90,11 +89,11 @@
   where
     optdir = OptMin
     [x1,x2,x3] = map LA.var [1..3]
-    obj = (-1) .*. x1 .-. 3 .*. x2 .-. 5 .*. x3
+    obj = (-1) *^ x1 ^-^ 3 *^ x2 ^-^ 5 *^ x3
     cs =
-      [ 3 .*. x1 .+. 4 .*. x2 .<=. LA.constant 10
-      , 2 .*. x1 .+. x2 .+. x3 .<=. LA.constant 7
-      , 3.*.x1 .+. x2 .+. 4 .*. x3 .==. LA.constant 12
+      [ 3 *^ x1 ^+^ 4 *^ x2 .<=. LA.constant 10
+      , 2 *^ x1 ^+^ x2 ^+^ x3 .<=. LA.constant 7
+      , 3 *^ x1 ^+^ x2 ^+^ 4 *^ x3 .==. LA.constant 12
       , LA.constant 0 .<=. x1
       , LA.constant 0 .<=. x2
       , LA.constant 0 .<=. x3
diff --git a/test/TestPolynomial.hs b/test/TestPolynomial.hs
--- a/test/TestPolynomial.hs
+++ b/test/TestPolynomial.hs
@@ -18,6 +18,7 @@
 import Data.Polynomial.Sturm
 import qualified Data.Polynomial.Lagrange as Lagrange
 import qualified Data.Interval as Interval
+import Data.Interval (Interval, EndPoint (..), (<=..<=), (<..<=), (<=..<), (<..<))
 
 {--------------------------------------------------------------------
   Polynomial type
@@ -477,11 +478,11 @@
 -- 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
+  [ numRoots p (Finite (-2)   <=..<= Finite 0)      @?= 2
+  , numRoots p (Finite 0      <=..<= Finite 2)      @?= 1
+  , numRoots p (Finite (-1.5) <=..<= Finite (-1.0)) @?= 1
+  , numRoots p (Finite (-0.5) <=..<= Finite 0)      @?= 1
+  , numRoots p (Finite 1      <=..<= Finite (1.5))  @?= 1
   ]
   where
     x = var ()
@@ -490,10 +491,10 @@
 -- 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
+  [ numRoots p (Finite 2 <..<=  Finite 3) @?= 0
+  , numRoots p (Finite 2 <=..<= Finite 3) @?= 1
+  , numRoots p (Finite 1 <..<   Finite 2) @?= 0
+  , numRoots p (Finite 1 <..<=  Finite 2) @?= 1
   ]
   where
     x = var ()
diff --git a/test/TestQE.hs b/test/TestQE.hs
--- a/test/TestQE.hs
+++ b/test/TestQE.hs
@@ -4,7 +4,10 @@
 import Control.Monad
 import Data.List
 import qualified Data.IntMap as IM
+import qualified Data.IntSet as IS
 import qualified Data.Map as Map
+import qualified Data.Set as Set
+import Data.VectorSpace
 import Test.HUnit hiding (Test)
 import Test.Framework (Test, defaultMain, testGroup)
 import Test.Framework.TH
@@ -12,9 +15,7 @@
 
 import Data.AlgebraicNumber
 import Data.ArithRel
-import Data.Expr
-import Data.Formula
-import Data.Linear
+import Data.FOL.Arith
 import qualified Data.LA as LA
 import qualified Data.Polynomial as P
 import Data.OptDir
@@ -79,8 +80,8 @@
     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
+    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]
 
@@ -125,14 +126,14 @@
   where
     x = LA.var 0
     y = LA.var 1
-    t1 = 11.*.x .+. 13.*.y
-    t2 = 7.*.x .-. 9.*.y
+    t1 = 11*^x ^+^ 13*^y
+    t2 = 7*^x ^-^ 9*^y
 
 ------------------------------------------------------------------------
 
 case_FourierMotzkin_test1 :: IO ()
 case_FourierMotzkin_test1 = 
-  case FourierMotzkin.solveConj test1' of
+  case FourierMotzkin.solve (IS.fromList [0,1,2]) test1' of
     Nothing -> assertFailure "expected: Just\n but got: Nothing"
     Just m  ->
       forM_ test1' $ \a -> do
@@ -140,7 +141,7 @@
 
 case_FourierMotzkin_test2 :: IO ()
 case_FourierMotzkin_test2 = 
-  case FourierMotzkin.solveConj test2' of
+  case FourierMotzkin.solve (IS.fromList [0,1]) test2' of
     Nothing -> assertFailure "expected: Just\n but got: Nothing"
     Just m  ->
       forM_ test2' $ \a -> do
@@ -150,7 +151,7 @@
 
 case_CAD_test1 :: IO ()
 case_CAD_test1 = 
-  case CAD.solve test1'' of
+  case CAD.solve (Set.fromList [0,1,2]) test1'' of
     Nothing -> assertFailure "expected: Just\n but got: Nothing"
     Just m  ->
       forM_ test1'' $ \a -> do
@@ -160,7 +161,7 @@
 
 case_CAD_test2 :: IO ()
 case_CAD_test2 = 
-  case CAD.solve test2'' of
+  case CAD.solve (Set.fromList [0,1]) test2'' of
     Nothing -> assertFailure "expected: Just\n but got: Nothing"
     Just m  ->
       forM_ test2'' $ \a -> do
@@ -184,7 +185,7 @@
 
 case_OmegaTest_test1 :: IO ()
 case_OmegaTest_test1 = 
-  case OmegaTest.solve test1' of
+  case OmegaTest.solve OmegaTest.defaultOptions (IS.fromList [0,1,2]) test1' of
     Nothing -> assertFailure "expected: Just\n but got: Nothing"
     Just m  -> do
       forM_ test1' $ \a -> do
@@ -192,7 +193,7 @@
 
 case_OmegaTest_test2 :: IO ()
 case_OmegaTest_test2 = 
-  case OmegaTest.solve test2' of
+  case OmegaTest.solve OmegaTest.defaultOptions (IS.fromList [0,1]) test2' of
     Just _  -> assertFailure "expected: Nothing\n but got: Just"
     Nothing -> return ()
 
@@ -200,7 +201,7 @@
 
 case_Cooper_test1 :: IO ()
 case_Cooper_test1 = 
-  case Cooper.solveConj test1' of
+  case Cooper.solve (IS.fromList [0,1,2]) test1' of
     Nothing -> assertFailure "expected: Just\n but got: Nothing"
     Just m  -> do
       forM_ test1' $ \a -> do
@@ -208,7 +209,7 @@
 
 case_Cooper_test2 :: IO ()
 case_Cooper_test2 = 
-  case Cooper.solveConj test2' of
+  case Cooper.solve (IS.fromList [0,1]) test2' of
     Just _  -> assertFailure "expected: Nothing\n but got: Just"
     Nothing -> return ()
 
@@ -236,7 +237,7 @@
 
 disabled_case_ContiTraverso_test1 :: IO ()
 disabled_case_ContiTraverso_test1 = 
-  case ContiTraverso.solve P.grlex OptMin (LA.constant 0) test1' of
+  case ContiTraverso.solve P.grlex (IS.fromList [0,1,2]) OptMin (LA.constant 0) test1' of
     Nothing -> assertFailure "expected: Just\n but got: Nothing"
     Just m  -> do
       forM_ test1' $ \a -> do
@@ -244,7 +245,7 @@
 
 disabled_case_ContiTraverso_test2 :: IO ()
 disabled_case_ContiTraverso_test2 = 
-  case ContiTraverso.solve P.grlex OptMin (LA.constant 0) test2' of
+  case ContiTraverso.solve P.grlex (IS.fromList [0,1]) OptMin (LA.constant 0) test2' of
     Just _  -> assertFailure "expected: Nothing\n but got: Just"
     Nothing -> return ()
 
diff --git a/test/TestSAT.hs b/test/TestSAT.hs
--- a/test/TestSAT.hs
+++ b/test/TestSAT.hs
@@ -281,6 +281,19 @@
 
 ------------------------------------------------------------------------
 
+-- -4*(not x1) + 3*x1 + 10*(not x2)
+-- = -4*(1 - x1) + 3*x1 + 10*(not x2)
+-- = -4 + 4*x1 + 3*x1 + 10*(not x2)
+-- = 7*x1 + 10*(not x2) - 4
+case_normalizePBSum :: Assertion
+case_normalizePBSum = do
+  sort e @?= sort [(7,x1),(10,-x2)]
+  c @?= -4
+  where
+    x1 = 1
+    x2 = 2
+    (e,c) = normalizePBSum ([(-4,-x1),(3,x1),(10,-x2)], 0)
+
 -- -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
diff --git a/test/TestSimplex2.hs b/test/TestSimplex2.hs
--- a/test/TestSimplex2.hs
+++ b/test/TestSimplex2.hs
@@ -4,13 +4,13 @@
 import Control.Monad
 import Data.List
 import Data.Ratio
+import Data.VectorSpace
 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 qualified Data.LA as LA
 import Algorithm.Simplex2
 
diff --git a/toysat/toysat.hs b/toysat/toysat.hs
--- a/toysat/toysat.hs
+++ b/toysat/toysat.hs
@@ -29,6 +29,7 @@
 import Data.Maybe
 import Data.Ord
 import Data.Ratio
+import Data.VectorSpace
 import Data.Version
 import Data.Time
 import System.IO
@@ -52,7 +53,7 @@
 #endif
 
 import Data.ArithRel
-import Data.Linear
+import qualified Converter.MaxSAT2WBO as MaxSAT2WBO
 import qualified SAT
 import qualified SAT.PBO as PBO
 import qualified SAT.Integer
@@ -166,7 +167,7 @@
 
     , Option [] ["search"]
         (ReqArg (\val opt -> opt{ optSearchStrategy = parseSearch val }) "<str>")
-        "Search algorithm used in optimization; linear (default), binary"
+        "Search algorithm used in optimization; linear (default), binary, adaptive, unsat"
     , Option [] ["objfun-heuristics"]
         (NoArg (\opt -> opt{ optObjFunVarsHeuristics = True }))
         "Enable heuristics for polarity/activity of variables in objective function (default)"
@@ -203,8 +204,11 @@
 
     parseSearch s =
       case map toLower s of
-        "linear" -> PBO.LinearSearch
-        "binary" -> PBO.BinarySearch
+        "linear"   -> PBO.LinearSearch
+        "binary"   -> PBO.BinarySearch
+        "adaptive" -> PBO.AdaptiveSearch
+        "unsat"    -> PBO.UnsatBased
+        "msu4"     -> PBO.MSU4
         _ -> error (printf "unknown search strategy %s" s)
 
     parseLS "clause" = SAT.LearningClause
@@ -400,7 +404,7 @@
 solveMUS :: Options -> SAT.Solver -> GCNF.GCNF -> IO ()
 solveMUS opt solver gcnf = do
   putCommentLine $ printf "#vars %d" (GCNF.numVars gcnf)
-  putCommentLine $ printf "#constraints %d" (length (GCNF.clauses gcnf))
+  putCommentLine $ printf "#constraints %d" (GCNF.numClauses gcnf)
   putCommentLine $ printf "#groups %d" (GCNF.lastGroupIndex gcnf)
 
   SAT.newVars_ solver (GCNF.numVars gcnf)
@@ -534,8 +538,9 @@
         PBO.defaultOptions
         { PBO.optObjFunVarsHeuristics = optObjFunVarsHeuristics opt
         , PBO.optSearchStrategy       = optSearchStrategy opt
-        , PBO.optLogger  = putCommentLine
-        , PBO.optUpdater = update
+        , PBO.optLogger     = putCommentLine
+        , PBO.optUpdateBest = update
+        , PBO.optUpdateLB   = \val -> putCommentLine $ printf "lower bound updated to %d" val
         }
   PBO.minimize solver obj opt2
 
@@ -625,18 +630,8 @@
     Right wcnf -> solveMaxSAT opt solver wcnf
 
 solveMaxSAT :: Options -> SAT.Solver -> MaxSAT.WCNF -> IO ()
-solveMaxSAT opt solver
-  MaxSAT.WCNF
-  { MaxSAT.topCost = top
-  , MaxSAT.clauses = 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
-               ]
-             )
+solveMaxSAT opt solver wcnf =
+  solveWBO opt solver True (MaxSAT2WBO.convert wcnf)
 
 -- ------------------------------------------------------------------------
 
@@ -691,7 +686,7 @@
         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) .*. product [vmap Map.! v | v <- vs] | LPFile.Term r vs <- lhs]
+            lhs' = sumV [asInteger (r * fromIntegral d) *^ product [vmap Map.! v | v <- vs] | LPFile.Term r vs <- lhs]
             rhs' = asInteger (rhs * fromIntegral d)
         case indicator of
           Nothing ->
@@ -723,7 +718,7 @@
       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) .*. product [vmap Map.! v | v <- vs] | LPFile.Term r vs <- obj]
+          obj2 = sumV [asInteger (r * fromIntegral d) *^ product [vmap Map.! v | v <- vs] | LPFile.Term r vs <- obj]
       (obj3,obj3_c) <- SAT.Integer.linearize enc obj2
 
       modelRef <- newIORef Nothing
diff --git a/toysolver.cabal b/toysolver.cabal
--- a/toysolver.cabal
+++ b/toysolver.cabal
@@ -1,12 +1,12 @@
 Name:		toysolver
-Version:	0.0.3
+Version:	0.0.4
 License:	BSD3
 License-File:	COPYING
 Author:		Masahiro Sakai (masahiro.sakai@gmail.com)
 Maintainer:	masahiro.sakai@gmail.com
-Category:	Algorithms
+Category:	Algorithms, Optimisation, Optimization
 Cabal-Version:	>= 1.8
-Synopsis:	Assorted decision procedures
+Synopsis:	Assorted decision procedures for SAT, Max-SAT, PB, MIP, etc
 Description:	Toy-level implementation of some decision procedures
 Bug-Reports:	https://github.com/msakai/toysolver/issues
 Extra-Source-Files:
@@ -18,6 +18,7 @@
    src/pbverify.hs
    src/pigeonhole.hs
    src/Algorithm/Wang.hs
+   samples/gcnf/*.cnf
    samples/gcnf/*.gcnf
    samples/lp/*.lp
    samples/lp/error/*.lp
@@ -50,56 +51,73 @@
   Build-Depends:
      base >=4 && <5,
      containers >= 0.4.2, mtl, array, random, stm >=2.3, parsec, bytestring, filepath, deepseq, time, old-locale, primes,
-     parse-dimacs, queue, heaps, unbounded-delays,
-     OptDir
+     parse-dimacs, queue, heaps, unbounded-delays, lattices >=1.2.1.1, vector-space >=0.8.6,
+     OptDir, data-interval >=0.1.0
   Extensions:
+     TypeFamilies
      MultiParamTypeClasses
      FlexibleInstances
      BangPatterns
      DoAndIfThenElse
      CPP
   Exposed-Modules:
+     Algebra.Lattice.Boolean
      Algorithm.BoundsInference
      Algorithm.CAD
      Algorithm.CongruenceClosure
      Algorithm.ContiTraverso
      Algorithm.Cooper
+     Algorithm.Cooper.Core
+     Algorithm.Cooper.FOL
      Algorithm.FOLModelFinder
      Algorithm.FourierMotzkin
+     Algorithm.FourierMotzkin.Core
+     Algorithm.FourierMotzkin.FOL
      Algorithm.LPSolver
      Algorithm.LPSolverHL
      Algorithm.LPUtil
      Algorithm.MIPSolverHL
      Algorithm.MIPSolver2
      Algorithm.OmegaTest
+     Algorithm.OmegaTest.Misc
      Algorithm.Simplex
      Algorithm.Simplex2
-     Converter.CNF2LP
      Converter.ObjType
-     Converter.PB2LP
      Converter.LP2SMT
      Converter.MaxSAT2LP
+     Converter.MaxSAT2NLPB
+     Converter.MaxSAT2WBO
+     Converter.PB2LP
+     Converter.PB2LSP
+     Converter.PB2WBO
+     Converter.PBSetObj
+     Converter.PB2SMP
+     Converter.SAT2PB
+     Converter.SAT2LP
+     Converter.WBO2PB
      Data.AlgebraicNumber
      Data.AlgebraicNumber.Root
      Data.ArithRel
      Data.Delta
-     Data.Expr
-     Data.Formula
+     Data.DNF
+     Data.FOL.Arith
+     Data.FOL.Formula
      Data.LA
-     Data.Lattice
+     Data.LA.FOL
      Data.LBool
-     Data.Linear
-     Data.Interval
      Data.Polynomial
      Data.Polynomial.FactorZ
      Data.Polynomial.GBase
      Data.Polynomial.Lagrange
      Data.Polynomial.Sturm
+     Data.Var
      SAT
      SAT.Integer
      SAT.MUS
      SAT.CAMUS
      SAT.PBO
+     SAT.PBO.MSU4
+     SAT.PBO.UnsatBased
      SAT.TheorySolver
      SAT.TseitinEncoder
      SAT.Types
@@ -116,6 +134,7 @@
   Other-Modules:
      Data.IndexedPriorityQueue
      Data.SeqQueue
+     Text.Util
      Paths_toysolver
   GHC-Prof-Options: -auto-all
 
@@ -132,7 +151,7 @@
 Executable toysat
   Main-is: toysat.hs
   HS-Source-Dirs: toysat
-  Build-Depends: base >=4 && <5, containers >= 0.4.2, array, parsec, bytestring, filepath, parse-dimacs, time, old-locale, unbounded-delays, toysolver
+  Build-Depends: base >=4 && <5, containers >= 0.4.2, array, parsec, bytestring, filepath, parse-dimacs, time, old-locale, unbounded-delays, vector-space >=0.8.6, toysolver
   if impl(ghc >= 7)
     GHC-Options: -rtsopts
   GHC-Prof-Options: -auto-all
@@ -153,6 +172,11 @@
   HS-Source-Dirs: lpconvert
   Build-Depends: base >=4 && <5, containers, filepath, parse-dimacs, toysolver
 
+Executable pbconvert
+  Main-is: pbconvert.hs
+  HS-Source-Dirs: pbconvert
+  Build-Depends: base >=4 && <5, containers, filepath, parse-dimacs, toysolver
+
 Test-suite TestSAT
   Type:              exitcode-stdio-1.0
   HS-Source-Dirs:    test
@@ -164,28 +188,21 @@
   Type:              exitcode-stdio-1.0
   HS-Source-Dirs:    test
   Main-is:           TestSimplex2.hs
-  Build-depends:     base >=4 && <5, containers, toysolver, test-framework,test-framework-th,test-framework-hunit,HUnit
+  Build-depends:     base >=4 && <5, containers, vector-space >=0.8.6, toysolver, test-framework,test-framework-th,test-framework-hunit,HUnit
   Extensions: TemplateHaskell, DoAndIfThenElse
 
 Test-suite TestMIPSolver2
   Type:              exitcode-stdio-1.0
   HS-Source-Dirs:    test
   Main-is:           TestMIPSolver2.hs
-  Build-depends:     base >=4 && <5, containers, toysolver, test-framework, test-framework-th, test-framework-hunit, HUnit, OptDir, stm
+  Build-depends:     base >=4 && <5, containers, vector-space >=0.8.6, toysolver, 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:    test
   Main-is:           TestPolynomial.hs
-  Build-depends:     base >=4 && <5, containers, toysolver, 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:    test
-  Main-is:           TestInterval.hs
-  Build-depends:     base >=4 && <5, containers, toysolver, test-framework,test-framework-th,test-framework-hunit,test-framework-quickcheck2,HUnit,QuickCheck >=2 && <3
+  Build-depends:     base >=4 && <5, containers, toysolver, test-framework,test-framework-th,test-framework-hunit,test-framework-quickcheck2,HUnit,QuickCheck >=2 && <3, data-interval >=0.1.0
   Extensions: TemplateHaskell, DoAndIfThenElse
 
 Test-suite TestAReal
@@ -199,14 +216,14 @@
   Type:              exitcode-stdio-1.0
   HS-Source-Dirs:    test
   Main-is:           TestQE.hs
-  Build-depends:     base >=4 && <5, containers, toysolver, OptDir, test-framework,test-framework-th,test-framework-hunit,test-framework-quickcheck2,HUnit,QuickCheck >=2 && <3
+  Build-depends:     base >=4 && <5, containers, vector-space >=0.8.6, toysolver, OptDir, test-framework,test-framework-th,test-framework-hunit,test-framework-quickcheck2,HUnit,QuickCheck >=2 && <3
   Extensions: TemplateHaskell, DoAndIfThenElse
 
 Test-suite TestContiTraverso
   Type:              exitcode-stdio-1.0
   HS-Source-Dirs:    test
   Main-is:           TestContiTraverso.hs
-  Build-depends:     base >=4 && <5, containers, toysolver, OptDir, test-framework,test-framework-th,test-framework-hunit,test-framework-quickcheck2,HUnit,QuickCheck >=2 && <3
+  Build-depends:     base >=4 && <5, containers, vector-space >=0.8.6, toysolver, OptDir, test-framework,test-framework-th,test-framework-hunit,test-framework-quickcheck2,HUnit,QuickCheck >=2 && <3
   Extensions: TemplateHaskell, DoAndIfThenElse
 
 Test-suite TestLPFile
diff --git a/toysolver/toysolver.hs b/toysolver/toysolver.hs
--- a/toysolver/toysolver.hs
+++ b/toysolver/toysolver.hs
@@ -32,15 +32,17 @@
 import System.IO
 import Text.Printf
 import qualified Language.CNF.Parse.ParseDIMACS as DIMACS
+import GHC.Conc (getNumProcessors, setNumCapabilities)
 
-import Data.Expr
 import Data.ArithRel
-import Data.Formula (Atom (..))
+import Data.FOL.Arith as FOL
 import Data.OptDir
 import qualified Data.LA as LA
+import qualified Data.LA.FOL as LAFOL
 import qualified Data.Polynomial as P
 import qualified Data.AlgebraicNumber as AReal
 import qualified Algorithm.OmegaTest as OmegaTest
+import qualified Algorithm.OmegaTest.Misc as OmegaTest
 import qualified Algorithm.Cooper as Cooper
 import qualified Algorithm.MIPSolverHL as MIPSolverHL
 import qualified Algorithm.Simplex2 as Simplex2
@@ -52,7 +54,7 @@
 import qualified Text.PBFile as PBFile
 import qualified Text.MaxSAT as MaxSAT
 import qualified Text.GurobiSol as GurobiSol
-import qualified Converter.CNF2LP as CNF2LP
+import qualified Converter.SAT2LP as SAT2LP
 import qualified Converter.PB2LP as PB2LP
 import qualified Converter.MaxSAT2LP as MaxSAT2LP
 import SAT.Printer
@@ -74,6 +76,7 @@
     | NoMIP
     | PivotStrategy String
     | NThread !Int
+    | OmegaReal String
     | Mode !Mode
     deriving Eq
 
@@ -85,11 +88,11 @@
     , Option [] ["print-rational"] (NoArg PrintRational) "print rational numbers instead of decimals"
     , Option ['w'] [] (ReqArg WriteFile "<filename>")  "write solution to filename in Gurobi .sol format"
 
-    , 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 [] ["omega-real"] (ReqArg OmegaReal "SOLVER") "fourier-motzkin (default), cad, simplex, none"
+
     , Option []    ["sat"]    (NoArg (Mode ModeSAT))    "solve boolean satisfiability 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"
@@ -158,46 +161,66 @@
       | NoMIP `elem` opt = Set.empty
       | otherwise        = LP.integerVariables lp
 
+    vs2  = IM.keysSet varToName
     ivs2 = IS.fromList . map (nameToVar Map.!) . Set.toList $ ivs
 
     solveByQE =
-      case mapM LA.compileAtom (cs1 ++ cs2) of
+      case mapM LAFOL.fromFOLAtom (cs1 ++ cs2) of
         Nothing -> do
           putStrLn "s UNKNOWN"
           exitFailure
         Just cs ->
-          case f cs ivs2 of
+          case f vs2 cs ivs2 of
             Nothing -> do
               putStrLn "s UNSATISFIABLE"
               exitFailure
             Just m -> do
-              putStrLn $ "o " ++ showValue (Data.Expr.eval m obj)
+              putStrLn $ "o " ++ showValue (FOL.evalExpr 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"      -> OmegaTest.solveQFLA
-               "omega-test" -> OmegaTest.solveQFLA
+               "omega"      -> OmegaTest.solveQFLA omegaOpt
+               "omega-test" -> OmegaTest.solveQFLA omegaOpt
                "cooper"     -> Cooper.solveQFLA
                _ -> error "unknown solver"
 
-    solveByMIP =
-      case MIPSolverHL.optimize (LP.dir lp) obj (cs1 ++ cs2) ivs2 of
-        OptUnknown -> do
+         omegaOpt =
+           OmegaTest.defaultOptions
+           { OmegaTest.optCheckReal = realSolver
+           }         
+           where
+             realSolver =
+               case last ("fourier-motzkin" : [s | OmegaReal s <- opt]) of
+                 "fourier-motzkin" -> OmegaTest.checkRealByFM
+                 "cad"             -> OmegaTest.checkRealByCAD
+                 "simplex"         -> OmegaTest.checkRealBySimplex
+                 "none"            -> OmegaTest.checkRealNoCheck
+                 s                 -> error ("unknown solver: " ++ s)
+
+    solveByMIP = do
+      let m = do
+            cs'  <- mapM LAFOL.fromFOLAtom (cs1 ++ cs2)
+            obj' <- LAFOL.fromFOLExpr obj
+            return (cs',obj')
+      case m of
+        Nothing -> 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
+        Just (cs',obj') ->
+          case MIPSolverHL.optimize (LP.dir lp) obj' cs' ivs2 of
+            MIPSolverHL.OptUnsat -> do
+              putStrLn "s UNSATISFIABLE"
+              exitFailure
+            MIPSolverHL.Unbounded -> do
+              putStrLn "s UNBOUNDED"
+              exitFailure
+            MIPSolverHL.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
@@ -213,20 +236,26 @@
       Simplex2.setLogger solver putCommentLine
       replicateM (length vsAssoc) (Simplex2.newVar solver) -- XXX
       Simplex2.setOptDir solver (LP.dir lp)
-      Simplex2.setObj solver $ fromJust (LA.compileExpr obj)
+      Simplex2.setObj solver $ fromJust (LAFOL.fromFOLExpr obj)
       putCommentLine "Loading constraints... "
       forM_ (cs1 ++ cs2) $ \c -> do
-        Simplex2.assertAtom solver $ fromJust (LA.compileAtom c)
+        Simplex2.assertAtom solver $ fromJust (LAFOL.fromFOLAtom c)
       putCommentLine "Loading constraints finished"
 
       mip <- MIPSolver2.newSolver solver ivs2
       MIPSolver2.setShowRational mip printRat
       MIPSolver2.setLogger mip putCommentLine
-      ncap <- getNumCapabilities
-      MIPSolver2.setNThread mip $
+
+      procs <-
         if nthreads >= 1
-        then min ncap nthreads
-        else ncap
+        then return nthreads
+        else do
+          ncap  <- getNumCapabilities
+          procs <- getNumProcessors
+          return $ max (procs - 1) ncap
+      setNumCapabilities procs
+      MIPSolver2.setNThread mip procs
+
       let update m val = do
             putStrLn $ "o " ++ showValue val
       ret <- MIPSolver2.optimize mip update
@@ -254,14 +283,15 @@
           exitFailure
       | otherwise = do
           let cs = map g $ cs1 ++ cs2
-          case CAD.solve cs of
+              vs3 = Set.fromAscList $ IS.toAscList vs2
+          case CAD.solve vs3 cs of
             Nothing -> do
               putStrLn "s UNSATISFIABLE"
               exitFailure
             Just m -> do
               let m2 = IM.map (\x -> AReal.approx x (2^^(-64::Int))) $
                          IM.fromAscList $ Map.toAscList $ m
-              putStrLn $ "o " ++ showValue (Data.Expr.eval m2 obj)
+              putStrLn $ "o " ++ showValue (FOL.evalExpr m2 obj)
               putStrLn "s SATISFIABLE"
               let m3 = Map.fromAscList [(v, m2 IM.! (nameToVar Map.! v)) | v <- Set.toList vs]
               printModel m3
@@ -286,8 +316,8 @@
           exitFailure
       | otherwise = do
           let tmp = do
-                linObj <- LA.compileExpr obj
-                linCon <- mapM LA.compileAtom (cs1 ++ cs2)
+                linObj <- LAFOL.fromFOLExpr obj
+                linCon <- mapM LAFOL.fromFOLAtom (cs1 ++ cs2)
                 return (linObj, linCon)
           case tmp of
             Nothing -> do
@@ -295,13 +325,13 @@
               putCommentLine "non-linear expressions are not supported by Conti-Traverso algorithm"
               exitFailure
             Just (linObj, linCon) -> do
-              case ContiTraverso.solve P.grlex (LP.dir lp) linObj linCon of
+              case ContiTraverso.solve P.grlex vs2 (LP.dir lp) linObj linCon of
                 Nothing -> do
                   putStrLn "s UNSATISFIABLE"
                   exitFailure
                 Just m -> do
                   let m2 = IM.map fromInteger m
-                  putStrLn $ "o " ++ showValue (Data.Expr.eval m2 obj)
+                  putStrLn $ "o " ++ showValue (FOL.evalExpr m2 obj)
                   putStrLn "s OPTIMUM FOUND"
                   let m3 = Map.fromAscList [(v, m2 IM.! (nameToVar Map.! v)) | v <- Set.toList vs]
                   printModel m3
@@ -357,7 +387,7 @@
           case ret of
             Left err -> hPrint stderr err >> exitFailure
             Right cnf -> do
-              let (lp,mtrans) = CNF2LP.convert CNF2LP.ObjNone cnf
+              let (lp,mtrans) = SAT2LP.convert cnf
               run (getSolver o) o lp $ \m -> do
                 let m2 = mtrans m
                 satPrintModel stdout m2 0
@@ -367,7 +397,7 @@
           case ret of
             Left err -> hPrint stderr err >> exitFailure
             Right pb -> do
-              let (lp,mtrans) = PB2LP.convert PB2LP.ObjNone pb
+              let (lp,mtrans) = PB2LP.convert pb
               run (getSolver o) o lp $ \m -> do
                 let m2 = mtrans m
                 pbPrintModel stdout m2 0
@@ -387,7 +417,7 @@
           case ret of
             Left err -> hPutStrLn stderr err >> exitFailure
             Right wcnf -> do
-              let (lp,mtrans) = MaxSAT2LP.convert wcnf
+              let (lp,mtrans) = MaxSAT2LP.convert False wcnf
               run (getSolver o) o lp $ \m -> do
                 let m2 = mtrans m
                 maxsatPrintModel stdout m2 0
