packages feed

toysolver 0.4.0 → 0.5.0

raw patch · 272 files changed

+37343/−10614 lines, 272 filesdep +OpenCLdep +attoparsecdep +clockdep −MemoTriedep −exceptionsdep −old-localedep ~arraydep ~basedep ~bytestringnew-component:exe:assignnew-component:exe:numberlinknew-component:exe:shortest-pathnew-component:exe:survey-propagationnew-component:exe:toyconvertnew-component:exe:toyqbfbinary-added

Dependencies added: OpenCL, attoparsec, clock, data-default, directory, hashtables, lattices, log-domain, megaparsec, primitive, scientific, text, xml-conduit

Dependencies removed: MemoTrie, exceptions, old-locale, parse-dimacs, type-level-numbers

Dependency ranges changed: array, base, bytestring, containers, criterion, data-interval, finite-field, hashable, intern, logic-TPTP, loop, parsec, pseudo-boolean, tasty-quickcheck, temporary, time, transformers, transformers-compat, unordered-containers, vector-space

Files

− .ghci
@@ -1,1 +0,0 @@-:set -isrc -idist/build/autogen -optP-include -optPdist/build/autogen/cabal_macros.h
− .travis.yml
@@ -1,96 +0,0 @@-language: c-sudo: false--cache:-  directories:-    - $HOME/.cabsnap-    - $HOME/.cabal/packages--before_cache:-  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log-  - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar--matrix:-  include:-    - env: CABALVER=1.16 GHCVER=7.6.3-      compiler: ": #GHC 7.6.3"-      addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3,alex-3.1.4,happy-1.19.5], sources: [hvr-ghc]}}-    - env: CABALVER=1.18 GHCVER=7.8.3 COVERAGE=1-      compiler: ": #GHC 7.8.3"-      addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.3,alex-3.1.4,happy-1.19.5], sources: [hvr-ghc]}}-    - env: CABALVER=1.22 GHCVER=7.10.3-      compiler: ": #GHC 7.10.3"-      addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3,alex-3.1.4,happy-1.19.5], sources: [hvr-ghc]}}-  allow_failures:-   - env: CABALVER=1.16 GHCVER=7.6.3--before_install:- - unset CC- - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:/opt/alex/3.1.4/bin:/opt/happy/1.19.5/bin:~/.cabal/bin:$PATH--install:- - cabal --version- - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"- - if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ];-   then-     zcat $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz >-          $HOME/.cabal/packages/hackage.haskell.org/00-index.tar;-   fi- - travis_retry cabal update -v- - sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config- - cabal install --only-dependencies --enable-tests --enable-benchmarks --flag=BuildToyFMF --flag=BuildSamplePrograms --flag=BuildMiscPrograms --dry -v > installplan.txt- - sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt--# check whether current requested install-plan matches cached package-db snapshot- - if diff -u installplan.txt $HOME/.cabsnap/installplan.txt;-   then-     echo "cabal build-cache HIT";-     rm -rfv .ghc;-     cp -a $HOME/.cabsnap/ghc $HOME/.ghc;-     cp -a $HOME/.cabsnap/lib $HOME/.cabsnap/share $HOME/.cabsnap/bin $HOME/.cabal/;-   else-     echo "cabal build-cache MISS";-     rm -rf $HOME/.cabsnap;-     mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin;-     cabal install --only-dependencies --enable-tests --enable-benchmarks --flag=BuildToyFMF --flag=BuildSamplePrograms --flag=BuildMiscPrograms;-   fi--# snapshot package-db on cache miss- - if [ ! -d $HOME/.cabsnap ];-   then-      echo "snapshotting package-db to build-cache";-      mkdir $HOME/.cabsnap;-      cp -a $HOME/.ghc $HOME/.cabsnap/ghc;-      cp -a $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin installplan.txt $HOME/.cabsnap/;-   fi--# Here starts the actual work to be performed for the package under test;-# any command which exits with a non-zero exit code causes the build to fail.-script:- - if [ -f configure.ac ]; then autoreconf -i; fi- - cabal configure --enable-tests --enable-benchmarks -v2 --flag=BuildToyFMF --flag=BuildSamplePrograms --flag=BuildMiscPrograms $([ "$COVERAGE" = "1" ] && echo "--enable-library-coverage") # -v2 provides useful information for debugging- - cabal build   # this builds all libraries and executables (including tests/benchmarks)- - cabal test- - cabal check- - cabal sdist   # tests that a source-distribution can be generated--# Check that the resulting source distribution can be built & installed.-# If there are no other `.tar.gz` files in `dist`, this can be even simpler:-# `cabal install --force-reinstalls dist/*-*.tar.gz`- - SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz &&-   (cd dist && cabal install --force-reinstalls "$SRC_TGZ")--# This block must be executed before before_cache-#after_script:- - "[ -n \"$COVERAGE\" ] && cabal install hpc-coveralls --avoid-reinstalls --constraint=\"regex-posix >=0.95.2\" || true" # regex-posix-0.95.1 has compilation problem- - "[ -n \"$COVERAGE\" ] && hpc-coveralls TestSuite TestPolynomial --exclude-dir=test || true"--notifications:-  webhooks:-    urls:-      - https://webhooks.gitter.im/e/d83a1749bd96e9513d76-    on_success: change  # options: [always|never|change] default: always-    on_failure: always  # options: [always|never|change] default: always-    on_start: never     # options: [always|never|change] default: always--# EOF
CHANGELOG.markdown view
@@ -1,3 +1,48 @@+0.5.0+-----+* new solvers:+  * `ToySolver.BitVector`+  * `ToySolver.Combinatorial.BipartiteMatching`+  * `ToySolver.Combinatorial.HittingSet.DAA`+  * `ToySolver.Combinatorial.HittingSet.MARCO`+  * `ToySolver.Arith.DifferenceLogic`+  * `ToySolver.Graph.ShortestPath`+  * `ToySolver.QBF`+* `toysat`+  * add `--init-sp` option to initialize variable state using survey propagation+  * allow using `UBCSAT` when solving PBO/WBO problems+* `toysmt`+  * suport bit-vector logic+* `toyconvert`+  * `pbconvert` and `lpconvert` were merged into a single command `toyconvert`+  * add `--ksat=NUMBER` option to convert to k-SAT formula+  * add `--linearlize` and `--linearizer-pb` options+  * add `--remove-usercuts` option+* add new modules to `ToySolver.Converter`+  * `ToySolver.Converter.GCNF2MaxSAT`+  * `ToySolver.Converter.MIP2PB`+  * `ToySolver.Converter.PBLinearlization`+  * `ToySolver.Converter.SAT2KSAT`+* `ToySolver.SAT`+  * introduce type classes for adding constraints+  * `ToySolver.SAT.Encoder.Tseitin`: add XOR and Full-adder encoder+  * `ToySolver.SAT.Encoder.PB`: add functionality to encode PB constraint using adder networks and sorting networks+  * `ToySolver.SAT.MUS.Enum`: add `GurvichKhachiyan1999` and `MARCO` to the MUS enumeration methods+  * implement learning rate based branching heuristics+  * add `ToySolver.SAT.ExistentialQuantification`+  * add `ToySolver.SAT.Store.CNF` and `ToySolver.SAT.Store.PB`+  * implement survey propagation as `ToySolver.SAT.MessagePassing.SurveyPropagation`+* `Data.MIP`+  * parameterize Problem type with coefficient type and use `Scientific` as default+  * introduce `Status` type+  * add solution file parsers: `ToySolver.Data.MIP.Solution.{CBC,CPLEX,GLPK,Gurobi,SCIP}`+  * add solver wrapper modules: `ToySolver.MIP.Solver.{CBC,CPLEX,Glpsol,GurobiCl,LPSolve,SCIP}`+* add a QDimacs parser as `ToySolver.Text.QDimacs`+* add `ToySolver.Text.CNF`, `ToySolver.Text.QDimacs`+* switch to use `megaparsec`+* use `clock` package for measuring duration+* add simple numberlink solver sample+ 0.4.0 ----- * add experimental SMT (Satisfiablity Modulo Theories) solver 'toysmt', which supports theory of uninterpreted functions and linear real arithmetics.
README.md view
@@ -3,7 +3,7 @@  [![Join the chat at https://gitter.im/msakai/toysolver](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/msakai/toysolver?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -[![Build Status](https://secure.travis-ci.org/msakai/toysolver.png?branch=master)](http://travis-ci.org/msakai/toysolver) [![Build status](https://ci.appveyor.com/api/projects/status/w7g615sp8ysiqk7w/branch/master?svg=true)](https://ci.appveyor.com/project/msakai/toysolver/branch/master) [![Coverage Status](https://coveralls.io/repos/msakai/toysolver/badge.svg)](https://coveralls.io/r/msakai/toysolver) [![Hackage](https://budueba.com/hackage/toysolver)](https://hackage.haskell.org/package/toysolver)+[![Build Status](https://secure.travis-ci.org/msakai/toysolver.png?branch=master)](http://travis-ci.org/msakai/toysolver) [![Build status](https://ci.appveyor.com/api/projects/status/w7g615sp8ysiqk7w/branch/master?svg=true)](https://ci.appveyor.com/project/msakai/toysolver/branch/master) [![Coverage Status](https://coveralls.io/repos/msakai/toysolver/badge.svg)](https://coveralls.io/r/msakai/toysolver) [![Hackage](https://img.shields.io/hackage/v/toysolver.svg)](https://hackage.haskell.org/package/toysolver)  It provides solver implementations of various problems including SAT, SMT, Max-SAT, PBS (Pseudo Boolean Satisfaction), PBO (Pseudo Boolean Optimization), MILP (Mixed Integer Linear Programming) and non-linear real arithmetic. @@ -104,31 +104,18 @@      toyfmf [file.tptp] [size] -### lpconvert--Converter between LP/MIP/SAT-related formats--Usage:--    lpconvert -o [outputfile] [inputfile]--Supported formats:--* Input formats: lp, mps, cnf, wcnf, opb, wbo-* Output formats: lp, .mps, smt2, ys--### pbconvert+### toyconvert -Converter between SAT/PB-related formats+Converter between various problem files.  Usage: -    pbconvert -o [outputfile] [inputfile]+    toyconvert -o [outputfile] [inputfile]  Supported formats: -* Input formats: cnf, wcnf, opb, wbo-* Output formats: opb, wbo, lsp, lp, mps, smp, smt2, ys+* Input formats: .cnf .wcnf .opb .wbo .gcnf .lp .mps+* Output formats: .cnf .wcnf .opb .wbo .lsp .lp .mps .smp .smt2 .ys  Bindings --------@@ -140,4 +127,4 @@ ----  * Local search-* Survey propagation+
Smtlib/Smtlib/Parsers/CommandsParsers.hs view
@@ -43,8 +43,8 @@            <|> Pc.try parseSetOption            <|> Pc.try parseSetInfo            <|> Pc.try parseDeclareSort-           <|> Pc.try parseDefineSort            <|> Pc.try parseDeclareConst+           <|> Pc.try parseDefineSort            <|> Pc.try parseDeclareFun            <|> Pc.try parseDefineFun            <|> Pc.try parseDefineFunRec
Smtlib/Smtlib/Parsers/CommonParsers.hs view
@@ -78,21 +78,24 @@  --parse a Symbol symbol :: ParsecT String u Identity String-symbol = simpleSymbol <|> quotedSymbol+symbol = symbol' reservedWordsSet +symbol' :: Set.Set String -> ParsecT String u Identity String+symbol' reserved = simpleSymbol' reserved <|> quotedSymbol+ quotedSymbol :: ParsecT String u Identity String quotedSymbol = char '|' *> Pc.many (noneOf "|")  <* char '|'  simpleSymbol :: ParsecT String u Identity String-simpleSymbol = Pc.try $ do+simpleSymbol = simpleSymbol' reservedWordsSet++simpleSymbol' :: Set.Set String -> ParsecT String u Identity String+simpleSymbol' reserved = Pc.try $ do   s <- (letter <|> spcSymb) <:>  sq   guard $ s `Set.notMember` reserved   return s   where     sq = Pc.many (alphaNum <|> spcSymb)-    reserved = Set.fromList $-      ["BINARY", "DECIMAL", "HEXADECIMAL", "NUMERAL", "STRING", "_", "!", "as", "let", "exists", "forall", "par"] ++-      ["set-logic", "set-option", "set-info", "declare-sort", "define-sort", "declare-const", "declare-fun", "declare-fun-rec", "declare-funs-rec", "push", "pop", "reset", "reset-assertions", "assert", "check-sat", "check-sat-assuming", "get-assertions", "get-model", "get-proof", "get-unsat-core", "get-unsat-assumptions", "get-value", "get-assignment", "get-option", "get-info", "echo", "exit"]  spcSymb :: ParsecT String u Identity Char spcSymb = oneOf  "+-/*=%?!.$_~^&<>@"@@ -415,7 +418,7 @@ parseSexprConstant = liftM SexprSpecConstant parseSpecConstant  parseSexprSymbol :: ParsecT String u Identity Sexpr-parseSexprSymbol = liftM SexprSymbol symbol+parseSexprSymbol = liftM SexprSymbol (symbol' Set.empty)  parseSexprKeyword :: ParsecT String u Identity Sexpr parseSexprKeyword = liftM SexprKeyword keyword
Smtlib/Smtlib/Syntax/ShowSL.hs view
@@ -27,18 +27,17 @@ joinNs = unwords.fmap show  showSymbol :: String -> String-showSymbol s+showSymbol = showSymbol' reservedWordsSet++showSymbol' :: Set.Set String -> String -> String+showSymbol' reserved s   | c:_ <- s, isDigit c = quoted   | all p s && s `Set.notMember` reserved = s   | otherwise = quoted   where     quoted = "|" ++ s ++ "|"     p c = (isAscii c && isAlpha c) || isDigit c || c `elem` "~!@$%^&*_-+=<>.?/"-    reserved = Set.fromList $-      ["BINARY", "DECIMAL", "HEXADECIMAL", "NUMERAL", "STRING", "_", "!", "as", "let", "exists", "forall", "par"] ++-      ["set-logic", "set-option", "set-info", "declare-sort", "define-sort", "declare-const", "declare-fun", "declare-fun-rec", "declare-funs-rec", "push", "pop", "reset", "reset-assertions", "assert", "check-sat", "check-sat-assuming", "get-assertions", "get-model", "get-proof", "get-unsat-core", "get-unsat-assumptions", "get-value", "get-assignment", "get-option", "get-info", "echo", "exit"] - class ShowSL a where   showSL :: a -> String @@ -185,7 +184,7 @@  instance ShowSL Sexpr where   showSL (SexprSpecConstant sc) = showSL sc-  showSL (SexprSymbol str) = showSymbol str+  showSL (SexprSymbol str) = showSymbol' Set.empty str   showSL (SexprKeyword str) = str   showSL (SexprSxp srps) = "(" ++ joinA srps ++ ")" 
Smtlib/Smtlib/Syntax/Syntax.hs view
@@ -11,6 +11,8 @@ -} module Smtlib.Syntax.Syntax where +import qualified Data.Set as Set+ {-    #########################################################################    #                                                                       #@@ -18,6 +20,11 @@    #                                                                       #    ######################################################################### -}++reservedWordsSet :: Set.Set String+reservedWordsSet =  Set.fromList $+  ["BINARY", "DECIMAL", "HEXADECIMAL", "NUMERAL", "STRING", "_", "!", "as", "let", "exists", "forall", "par"] +++  ["set-logic", "set-option", "set-info", "declare-sort", "define-sort", "declare-const", "declare-fun", "declare-fun-rec", "declare-funs-rec", "push", "pop", "reset", "reset-assertions", "assert", "check-sat", "check-sat-assuming", "get-assertions", "get-model", "get-proof", "get-unsat-core", "get-unsat-assumptions", "get-value", "get-assignment", "get-option", "get-info", "echo", "exit"]   type Source = [Command]
+ app/maxsatverify.hs view
@@ -0,0 +1,48 @@+{-# LANGUAGE CPP #-}+module Main where++import Control.Monad+import Data.Array.IArray+import Data.IORef+import System.Environment+import Text.Printf+import qualified ToySolver.Text.MaxSAT as MaxSAT+import ToySolver.SAT.Types+import ToySolver.Internal.Util (setEncodingChar8)++main :: IO ()+main = do+#ifdef FORCE_CHAR8+  setEncodingChar8+#endif++  [problemFile, modelFile] <- getArgs+  Right wcnf <- MaxSAT.parseFile problemFile+  model <- liftM readModel (readFile modelFile)+  costRef <- newIORef 0+  forM_ (MaxSAT.clauses wcnf) $ \(w,c) ->+    unless (eval model c) $+      if w == MaxSAT.topCost wcnf+      then printf "violated hard constraint: %s\n" (show c)+      else do+        tc <- readIORef costRef+        writeIORef costRef $! tc + w+  printf "total cost = %d\n" =<< readIORef costRef++eval :: Model -> Clause -> Bool+eval m lits = or [evalLit m lit | lit <- lits]++readModel :: String -> Model+readModel s = array (1, maximum (0 : map fst ls2)) ls2+  where+    ls = lines s+    ls2 = do+      l <- ls+      case l of+        'v':xs -> do+          w <- words xs+          case w of+            '-':ys -> return (read ys, False)+            ys -> return (read ys, True)+        _ -> mzero+
+ app/pbverify.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE CPP #-}+module Main where++import Control.Monad+import Data.Array.IArray+import System.Environment+import Text.Printf+import qualified Data.PseudoBoolean as PBFile+import qualified Data.PseudoBoolean.Attoparsec as PBFileAttoparsec+import ToySolver.SAT.Types+import ToySolver.Internal.Util (setEncodingChar8)++main :: IO ()+main = do+#ifdef FORCE_CHAR8+  setEncodingChar8+#endif++  [problemFile, modelFile] <- getArgs+  Right formula <- PBFileAttoparsec.parseOPBFile problemFile+  model <- liftM readModel (readFile modelFile)+  forM_ (PBFile.pbConstraints formula) $ \c ->+    unless (eval model c) $+      printf "violated: %s\n" (show c)++eval :: Model -> PBFile.Constraint -> Bool+eval m (lhs, op, rhs) = op_v lhs_v rhs+  where+    lhs_v = sum [c | (c,lits) <- lhs, all (evalLit m) lits]+    op_v  = case op of+              PBFile.Ge -> (>=)+              PBFile.Eq -> (==)++readModel :: String -> Model+readModel s = array (1, maximum (0 : map fst ls2)) ls2+  where+    ls = lines s+    ls2 = do+      l <- ls+      case l of+        'v':xs -> do+          w <- words xs+          case w of+            '-':'x':ys -> return (read ys, False)+            'x':ys -> return (read ys, True)+        _ -> mzero+
+ app/pigeonhole.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE CPP #-}+module Main where++import Data.List+import qualified Data.Map as Map+import Data.Map (Map)+import System.Environment+import System.Exit+import System.IO+import Data.PseudoBoolean as PBFile+import ToySolver.Internal.Util (setEncodingChar8)++pigeonHole :: Integer -> Integer -> Formula+pigeonHole p h =+  Formula+  { pbObjectiveFunction = Nothing+  , pbConstraints = cs1 ++ cs2+  , pbNumVars = fromIntegral $ p*h+  , pbNumConstraints = fromIntegral $ p+h+  }+  where+    vs :: Map (Integer,Integer) Int+    vs = Map.fromList $ zip [(i,j) | i<-[1..p], j<-[1..h]] [1..]++    cs1 :: [Constraint]+    cs1 = [ ([(1,[v]) | j<-[1..h], let v = vs Map.! (i,j)], PBFile.Ge, 1)+          | i<-[1..p]+          ]+    cs2 :: [Constraint]+    cs2 = [ ([(-1,[v]) | i<-[1..p], let v = vs Map.! (i,j)], PBFile.Ge, -1)+          | j<-[1..h]+          ]++main :: IO ()+main = do+#ifdef FORCE_CHAR8+  setEncodingChar8+#endif++  xs <- getArgs+  case xs of+    [p,h] -> do+      let opb = pigeonHole (read p) (read h)+      hPutOPB stdout opb+    _ -> do+      hPutStrLn stderr "Usage: pigeonhole number_of_pigeons number_of_holes"+      exitFailure
+ app/toyconvert.hs view
@@ -0,0 +1,295 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  toyconvert+-- Copyright   :  (c) Masahiro Sakai 2012-2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+-- Portability :  non-portable (CPP)+--+-----------------------------------------------------------------------------++module Main where++import Control.Applicative+import qualified Data.ByteString.Builder as ByteStringBuilder+import Data.Char+import Data.Default.Class+import Data.Maybe+import qualified Data.Foldable as F+import Data.Scientific (Scientific)+import qualified Data.Text.Lazy.Builder as TextBuilder+import qualified Data.Text.Lazy.IO as TLIO+import qualified Data.Traversable as T+import qualified Data.Version as V+import System.Environment+import System.IO+import System.Exit+import System.FilePath+import System.Console.GetOpt++import qualified Data.PseudoBoolean as PBFile+import qualified Data.PseudoBoolean.Attoparsec as PBFileAttoparsec++import qualified ToySolver.Data.MIP as MIP+import qualified ToySolver.Text.GCNF as GCNF+import qualified ToySolver.Text.MaxSAT as MaxSAT+import qualified ToySolver.Text.CNF as CNF+import ToySolver.Converter.ObjType+import qualified ToySolver.Converter.SAT2PB as SAT2PB+import qualified ToySolver.Converter.GCNF2MaxSAT as GCNF2MaxSAT+import qualified ToySolver.Converter.MIP2PB as MIP2PB+import qualified ToySolver.Converter.MIP2SMT as MIP2SMT+import qualified ToySolver.Converter.MaxSAT2WBO as MaxSAT2WBO+import qualified ToySolver.Converter.PB2IP as PB2IP+import qualified ToySolver.Converter.PBLinearization as PBLinearization+import qualified ToySolver.Converter.PB2LSP as PB2LSP+import qualified ToySolver.Converter.PB2WBO as PB2WBO+import qualified ToySolver.Converter.PBSetObj as PBSetObj+import qualified ToySolver.Converter.PB2SMP as PB2SMP+import qualified ToySolver.Converter.PB2SAT as PB2SAT+import qualified ToySolver.Converter.SAT2KSAT as SAT2KSAT+import qualified ToySolver.Converter.WBO2PB as WBO2PB+import qualified ToySolver.Converter.WBO2MaxSAT as WBO2MaxSAT+import ToySolver.Version+import ToySolver.Internal.Util (setEncodingChar8)++data Flag+  = Help+  | Version+  | Output String+  | AsMaxSAT+  | ObjType ObjType+  | IndicatorConstraint+  | SMTSetLogic String+  | SMTOptimize+  | SMTNoCheck+  | SMTNoProduceModel+  | Yices2+  | Linearization+  | LinearizationUsingPB+  | KSat !Int+  | FileEncoding String+  | RemoveUserCuts+  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-set-logic"] (ReqArg SMTSetLogic "STRING") "output \"(set-logic STRING)\""+    , Option []    ["smt-optimize"] (NoArg SMTOptimize)   "output optimiality condition which uses quantifiers"+    , Option []    ["smt-no-check"] (NoArg SMTNoCheck)    "do not output \"(check)\""+    , Option []    ["smt-no-produce-model"] (NoArg SMTNoProduceModel) "do not output \"(set-option :produce-models true)\""    +    , Option []    ["yices2"] (NoArg Yices2) "output for yices2 rather than yices1"+    , Option []    ["linearize"] (NoArg Linearization) "linearize nonlinear pseudo-boolean constraints"+    , Option []    ["linearizer-pb"] (NoArg LinearizationUsingPB) "Use PB constraint in linearization"+    , Option []    ["ksat"] (ReqArg (KSat . read) "NUMBER") "generate k-SAT formula when outputing .cnf file"+    , Option []    ["encoding"] (ReqArg FileEncoding "<ENCODING>") "file encoding for LP/MPS files"+    , Option []    ["remove-usercuts"] (NoArg RemoveUserCuts) "remove user-defined cuts from LP/MPS files"+    ]+  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:"+  , "    toyconvert -o <outputfile> <inputfile>"+  , ""+  , "Supported formats:"+  , "    input: .cnf .wcnf .opb .wbo .gcnf .lp .mps"+  , "    output: .cnf .wcnf .opb .wbo .lsp .lp .mps .smp .smt2 .ys"+  , ""+  , "Options:"+  ]++data Problem+  = ProbOPB PBFile.Formula+  | ProbWBO PBFile.SoftFormula+  | ProbMIP (MIP.Problem Scientific)++readProblem :: [Flag] -> String -> IO Problem+readProblem o fname = do+  enc <- T.mapM mkTextEncoding $ last $ Nothing : [Just s | FileEncoding s <- o]+  case map toLower (takeExtension fname) of+    ".cnf"+      | AsMaxSAT `elem` o -> readWCNF+      | otherwise -> do+          ret <- CNF.parseFile fname+          case ret of+            Left err  -> hPrint stderr err >> exitFailure+            Right cnf -> return $ ProbOPB $ SAT2PB.convert cnf+    ".wcnf" -> readWCNF+    ".opb"  -> do+      ret <- PBFileAttoparsec.parseOPBFile fname+      case ret of+        Left err -> hPutStrLn stderr err >> exitFailure+        Right opb -> return $ ProbOPB opb+    ".wbo"  -> do+      ret <- PBFileAttoparsec.parseWBOFile fname+      case ret of+        Left err -> hPutStrLn stderr err >> exitFailure+        Right wbo -> return $ ProbWBO wbo+    ".gcnf" -> do+      ret <- GCNF.parseFile fname+      case ret of+        Left err -> hPutStrLn stderr err >> exitFailure+        Right gcnf -> return $ ProbWBO $ MaxSAT2WBO.convert $ GCNF2MaxSAT.convert gcnf+    ".lp"   -> ProbMIP <$> MIP.readLPFile def{ MIP.optFileEncoding = enc } fname+    ".mps"  -> ProbMIP <$> MIP.readMPSFile def{ MIP.optFileEncoding = enc } fname+    ext ->+      error $ "unknown file extension: " ++ show ext+  where    +    readWCNF = do+      ret <- MaxSAT.parseFile fname+      case ret of+        Left err -> hPutStrLn stderr err >> exitFailure+        Right wcnf -> return $ ProbWBO $ MaxSAT2WBO.convert $ wcnf++transformProblem :: [Flag] -> Problem -> Problem+transformProblem o = transformObj o . transformPBLinearization o . transformMIPRemoveUserCuts o++transformObj :: [Flag] -> Problem -> Problem+transformObj o problem =+  case problem of+    ProbOPB opb | isNothing (PBFile.pbObjectiveFunction opb) -> ProbOPB $ PBSetObj.setObj objType opb+    _ -> problem+  where+    objType = last (ObjNone : [t | ObjType t <- o])++transformPBLinearization :: [Flag] -> Problem -> Problem+transformPBLinearization o problem+  | Linearization `elem` o =+      case problem of+        ProbOPB opb -> ProbOPB $ PBLinearization.linearize    opb (LinearizationUsingPB `elem` o)+        ProbWBO wbo -> ProbWBO $ PBLinearization.linearizeWBO wbo (LinearizationUsingPB `elem` o)+        ProbMIP mip -> ProbMIP mip+  | otherwise = problem++transformMIPRemoveUserCuts :: [Flag] -> Problem -> Problem+transformMIPRemoveUserCuts o problem+  | RemoveUserCuts `elem` o =+      case problem of+        ProbMIP mip -> ProbMIP $ mip{ MIP.userCuts = [] }+        _ -> problem+  | otherwise = problem++writeProblem :: [Flag] -> Problem -> IO ()+writeProblem o problem = do+  enc <- T.mapM mkTextEncoding $ last $ Nothing : [Just s | FileEncoding s <- o]+  let mip2smtOpt =+        def+        { MIP2SMT.optSetLogic     = listToMaybe [logic | SMTSetLogic logic <- o]+        , MIP2SMT.optCheckSAT     = not (SMTNoCheck `elem` o)+        , MIP2SMT.optProduceModel = not (SMTNoProduceModel `elem` o)+        , MIP2SMT.optOptimize     = SMTOptimize `elem` o+        }+  case head ([Just fname | Output fname <- o] ++ [Nothing]) of+    Nothing -> do+      hSetBinaryMode stdout True+      hSetBuffering stdout (BlockBuffering Nothing)+      case problem of+        ProbOPB opb -> PBFile.hPutOPB stdout opb+        ProbWBO wbo -> PBFile.hPutWBO stdout wbo+        ProbMIP mip -> do+          case MIP.toLPString def mip of+            Left err -> hPutStrLn stderr ("conversion failure: " ++ err) >> exitFailure+            Right s -> do+              F.mapM_ (hSetEncoding stdout) enc+              TLIO.hPutStr stdout s+    Just fname -> do+      let opb = case problem of+                  ProbOPB opb -> opb+                  ProbWBO wbo ->+                    case WBO2PB.convert wbo of+                      (opb, _, _)+                        | Linearization `elem` o ->+                            -- WBO->OPB conversion may have introduced non-linearity+                            PBLinearization.linearize opb (LinearizationUsingPB `elem` o)+                        | otherwise -> opb+                  ProbMIP mip ->+                    case MIP2PB.convert (fmap toRational mip) of+                      Left err -> error err+                      Right (opb, _, _) -> opb+          wbo = case problem of+                  ProbOPB opb -> PB2WBO.convert opb+                  ProbWBO wbo -> wbo+                  ProbMIP _   -> PB2WBO.convert opb+          lp  = case problem of+                  ProbOPB opb ->+                    case PB2IP.convert opb of+                      (ip, _, _) -> fmap fromInteger ip+                  ProbWBO wbo ->+                    case PB2IP.convertWBO (IndicatorConstraint `elem` o) wbo of+                      (ip, _, _) -> fmap fromInteger ip+                  ProbMIP mip -> mip+          lsp = case problem of+                  ProbOPB opb -> PB2LSP.convert opb+                  ProbWBO wbo -> PB2LSP.convertWBO wbo+                  ProbMIP _   -> PB2LSP.convert opb+      case map toLower (takeExtension fname) of+        ".opb" -> PBFile.writeOPBFile fname opb+        ".wbo" -> PBFile.writeWBOFile fname wbo+        ".cnf" ->+          case PB2SAT.convert opb of+            (cnf, _, _) ->+              case head ([Just k | KSat k <- o] ++ [Nothing]) of+                Nothing -> CNF.writeFile fname cnf+                Just k ->+                  let (cnf2, _, _) = SAT2KSAT.convert k cnf+                  in CNF.writeFile fname cnf2+        ".wcnf" ->+          case WBO2MaxSAT.convert wbo of+            (wcnf, _, _) -> MaxSAT.writeFile fname wcnf+        ".lsp" ->+          withBinaryFile fname WriteMode $ \h ->+            ByteStringBuilder.hPutBuilder h lsp+        ".lp" -> MIP.writeLPFile def{ MIP.optFileEncoding = enc } fname lp+        ".mps" -> MIP.writeMPSFile def{ MIP.optFileEncoding = enc } fname lp+        ".smp" -> do+          withBinaryFile fname WriteMode $ \h ->+            ByteStringBuilder.hPutBuilder h (PB2SMP.convert False opb)+        ".smt2" -> do+          withFile fname WriteMode $ \h -> do+            F.mapM_ (hSetEncoding h) enc+            TLIO.hPutStr h $ TextBuilder.toLazyText $+              MIP2SMT.convert mip2smtOpt (fmap toRational lp)+        ".ys" -> do+          let lang = MIP2SMT.YICES (if Yices2 `elem` o then MIP2SMT.Yices2 else MIP2SMT.Yices1)+          withFile fname WriteMode $ \h -> do+            F.mapM_ (hSetEncoding h) enc+            TLIO.hPutStr h $ TextBuilder.toLazyText $+              MIP2SMT.convert mip2smtOpt{ MIP2SMT.optLanguage = lang } (fmap toRational lp)+        ext -> do+          error $ "unknown file extension: " ++ show ext+          +main :: IO ()+main = do+#ifdef FORCE_CHAR8+  setEncodingChar8+#endif++  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+      prob <- readProblem o fname+      let prob2 = transformProblem o prob+      writeProblem o prob2+    (_,_,errs) -> do+      hPutStrLn stderr $ concat errs ++ usageInfo header options+      exitFailure
+ app/toyfmf.hs view
@@ -0,0 +1,131 @@+{-# LANGUAGE CPP, TypeFamilies, OverloadedStrings #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  toyfmf+-- Copyright   :  (c) Masahiro Sakai 2012+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+-- Portability :  non-portable (CPP, TypeFamilies, OverloadedStrings)+--+-- A toy-level model finder+--+-----------------------------------------------------------------------------+module Main where++import Control.Monad+import Data.Interned (intern, unintern)+import Data.IORef+import qualified Data.Map as Map+import Data.Monoid+import Data.Ratio+import Data.String+import qualified Data.Text as Text+import System.Environment+import System.IO+import qualified Codec.TPTP as TPTP+import ToySolver.Data.Boolean+import qualified ToySolver.EUF.FiniteModelFinder as MF+import ToySolver.Internal.Util (setEncodingChar8)++main :: IO ()+main = do+#ifdef FORCE_CHAR8+  setEncodingChar8+#endif++  args <- getArgs+  case args of+    [fpath, size] -> solve fpath (read size)+    _ -> hPutStrLn stderr "Usage: toyfmf <file.tptp> <size>"++solve :: FilePath -> Int -> IO ()+solve _ size | size <= 0 = error "<size> should be >=1"+solve fpath size = do+  inputs <- TPTP.parseFile fpath+  let fs = translateProblem inputs++  ref <- newIORef 0+  let skolem name _ = do+        n <- readIORef ref+        let fsym = intern $ unintern name <> "#" <> fromString (show n)+        writeIORef ref (n+1)+        return fsym+  cs <- liftM concat $ mapM (MF.toSkolemNF skolem) fs++  ret <- MF.findModel size cs+  case ret of+    Nothing -> do+      putStrLn "s NO MODEL FOUND"+    Just m -> do+      putStrLn "s SATISFIABLE"+      let isSkolem k = Text.any ('#'==) (unintern k)+      let m' = m{ MF.mFunctions = Map.filterWithKey (\k _ -> not (isSkolem k)) (MF.mFunctions m) }+      forM_ (MF.showModel m') $ \s ->+        putStrLn $ "v " ++ s++  return ()++-- ---------------------------------------------------------------------------++translateProblem :: [TPTP.TPTP_Input] -> [MF.Formula]+translateProblem inputs = do+  i <- inputs+  case i of+    TPTP.Comment _ -> []+    TPTP.Include _ _ -> error "\"include\" is not supported yet "+    TPTP.AFormula{ TPTP.name = _, TPTP.role = role, TPTP.formula = formula, TPTP.annotations = _ } ->+      return $ translateFormula formula++translateFormula :: TPTP.Formula -> MF.Formula+translateFormula = TPTP.foldF neg quant binop eq rel+  where+    neg phi = notB $ translateFormula phi+    quant q vs phi = foldr q' (translateFormula phi) [fromString v | TPTP.V v <- vs]+      where+        q' =+          case q of +            TPTP.All    -> MF.Forall+            TPTP.Exists -> MF.Exists+    binop phi op psi = op' phi' psi'+      where+        phi' = translateFormula phi+        psi' = translateFormula psi+        op' =+          case op of+            (TPTP.:<=>:)  -> (.<=>.)+            (TPTP.:=>:)   -> (.=>.)+            (TPTP.:<=:)   -> flip (.=>.)+            (TPTP.:&:)    -> (.&&.)+            (TPTP.:|:)    -> (.||.)+            (TPTP.:~&:)   -> \a b -> notB (a .&&. b)+            (TPTP.:~|:)   -> \a b -> notB (a .||. b)+            (TPTP.:<~>:)  -> \a b -> notB (a .<=>. b)+    eq lhs op rhs =+      case op of+        (TPTP.:=:)  -> MF.Atom $ MF.PApp "=" [lhs', rhs']+        (TPTP.:!=:) -> MF.Not $ MF.Atom $ MF.PApp "=" [lhs', rhs']+      where+        lhs' = translateTerm lhs+        rhs' = translateTerm rhs+    rel (TPTP.AtomicWord p) ts = MF.Atom $ MF.PApp (fromString p) ts'+      where+        ts' = map translateTerm ts++translateTerm :: TPTP.Term -> MF.Term+translateTerm = TPTP.foldT str num var app+  where+    str s = MF.TmApp (fromString (show s)) []+    num r = MF.TmApp (fromString (showRational r)) []+    var (TPTP.V v) = MF.TmVar (fromString v)+    app (TPTP.AtomicWord f) ts = MF.TmApp (fromString f) ts'+      where+        ts' = map translateTerm ts++    showRational r =+      if denominator r == 1+      then show (numerator r)+      else show (numerator r) ++ "/" ++ show (denominator r)++-- ---------------------------------------------------------------------------
+ app/toyqbf.hs view
@@ -0,0 +1,122 @@+{-# LANGUAGE ScopedTypeVariables, CPP #-}+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  toyqbf+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+-- Portability :  non-portable (ScopedTypeVariables, CPP)+--+-----------------------------------------------------------------------------++module Main where++import Control.Monad+import Data.Char+import Data.Default.Class+import qualified Data.IntSet as IntSet+import Data.List+import Data.Ord+import Data.Version+import System.Console.GetOpt+import System.Environment+import System.Exit+import System.IO++import ToySolver.Data.Boolean+import qualified ToySolver.Data.BoolExpr as BoolExpr+import qualified ToySolver.QBF as QBF+import qualified ToySolver.Text.QDimacs as QDimacs+import ToySolver.Internal.Util (setEncodingChar8)+import ToySolver.Version++data Mode+  = ModeHelp+  | ModeVersion+  deriving (Eq, Ord, Bounded, Enum)++data Options+  = Options+  { optMode :: Maybe Mode+  , optAlgorithm :: String+  }++instance Default Options where+  def =+    Options+    { optMode = Nothing+    , optAlgorithm = "cegar-incremental"+    }++options :: [OptDescr (Options -> Options)]+options =+    [ Option ['h'] ["help"]   (NoArg (\opt -> opt{ optMode = Just ModeHelp   })) "show help"+    , Option [] ["version"]   (NoArg (\opt -> opt{ optMode = Just ModeVersion})) "show version"+    , Option [] ["algorithm"]+        (ReqArg (\val opt -> opt{ optAlgorithm = val }) "<str>")+        "Algorithm: naive, cegar, cegar-incremental (default)"+    ]++main :: IO ()+main = do+#ifdef FORCE_CHAR8+  setEncodingChar8+#endif++  args <- getArgs+  case getOpt Permute options args of+    (_,_,errs@(_:_)) -> do+      mapM_ putStrLn errs+      exitFailure++    (o,args2,[]) -> do+      let opt = foldl (flip id) def o+      case optMode opt of+        Just ModeHelp -> showHelp stdout+        Just ModeVersion -> hPutStrLn stdout (showVersion version)+        Nothing -> do+          case args2 of+            [fname] -> do+              ret <- QDimacs.parseFile fname+              case ret of+                Left err -> hPutStrLn stderr err >> exitFailure+                Right qdimacs -> do+                  let nv = QDimacs.numVars qdimacs+                      nc = QDimacs.numClauses qdimacs+                      prefix' = QBF.quantifyFreeVariables nv [(q, IntSet.fromList xs) | (q,xs) <- QDimacs.prefix qdimacs]+                      matrix' = andB [orB [if lit > 0 then BoolExpr.Atom lit else notB (BoolExpr.Atom (abs lit)) | lit <- clause] | clause <- QDimacs.matrix qdimacs]+                  (ans, certificate) <-+                    case map toLower (optAlgorithm opt) of+                      "naive" -> QBF.solveNaive nv prefix' matrix'+                      "cegar" -> QBF.solveCEGAR nv prefix' matrix'+                      "cegar-incremental" -> QBF.solveCEGARIncremental nv prefix' matrix'+                      _ -> do+                        putStrLn $ "c unknown --algorithm option: " ++ show (optAlgorithm opt)+                        putStrLn $ "s cnf 0 " ++ show nv ++ " " ++ show nc+                        exitFailure+                  putStrLn $ "s cnf " ++ (if ans then "1" else "-1") ++ " " ++ show nv ++ " " ++ show nc+                  case certificate of+                    Nothing -> return ()+                    Just lits -> do+                      forM_ (sortBy (comparing abs) (IntSet.toList lits)) $ \lit -> do+                        putStrLn ("V " ++ show lit)+                  if ans then+                    exitWith (ExitFailure 10)+                  else+                    exitWith (ExitFailure 20)+            _ -> showHelp stderr >> exitFailure++showHelp :: Handle -> IO ()+showHelp h = hPutStrLn h (usageInfo header options)++header :: String+header = unlines+  [ "Usage:"+  , "  toyqbf [OPTION]... [file.qdimacs]"+  , "  toyqbf [OPTION]... [file.cnf]"+  , ""+  , "Options:"+  ]
+ app/toysat/UBCSAT.hs view
@@ -0,0 +1,163 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -Wall #-}+module UBCSAT+  ( ubcsatBest+  , ubcsatBestFeasible+  , ubcsatMany+  , Options (..)+  ) where++import Control.Exception+import Control.Monad+import Data.Array.IArray+import Data.Char+import Data.Default+import Data.Either+import Data.Function+import Data.List+#if MIN_VERSION_megaparsec(6,0,0)+import Data.Void+#endif+import System.Directory+import System.IO+import System.IO.Temp+import System.Process+import Text.Megaparsec hiding (try)+#if MIN_VERSION_megaparsec(6,0,0)+import Text.Megaparsec.Char+#else+import Text.Megaparsec.String+#endif++import qualified ToySolver.SAT.Types as SAT+import qualified ToySolver.Text.MaxSAT as MaxSAT++data Options+  = Options+  { optCommand :: FilePath+  , optTempDir :: Maybe FilePath+  , optProblem :: MaxSAT.WCNF+  , optProblemFile :: Maybe FilePath+  , optVarInit :: [SAT.Lit]+  }++instance Default Options where+  def = Options+        { optCommand = "ubcsat"+        , optTempDir = Nothing+        , optProblem =+            MaxSAT.WCNF+            { MaxSAT.numVars    = 0+            , MaxSAT.numClauses = 0+            , MaxSAT.topCost    = 1+            , MaxSAT.clauses    = []+            }+        , optProblemFile   = Nothing+        , optVarInit = []+        }++ubcsatBestFeasible :: Options -> IO (Maybe (Integer, SAT.Model))+ubcsatBestFeasible opt = do+  ret <- ubcsatBest opt+  case ret of+    Nothing -> return Nothing+    Just (obj,_) ->+      if obj < MaxSAT.topCost (optProblem opt) then+        return ret+      else+        return Nothing++ubcsatBest :: Options -> IO (Maybe (Integer, SAT.Model))+ubcsatBest opt = do+  sols <- ubcsatMany opt+  case sols of+    [] -> return Nothing+    _ -> return $ Just $ minimumBy (compare `on` fst) sols++ubcsatMany :: Options -> IO [(Integer, SAT.Model)]+ubcsatMany opt = do+  dir <- case optTempDir opt of+           Just dir -> return dir+           Nothing -> getTemporaryDirectory++  let f fname+        | null (optVarInit opt) = ubcsat' opt fname Nothing+        | otherwise = do+            withTempFile dir ".txt" $ \varInitFile h -> do+              hSetBinaryMode h True+              hSetBuffering h (BlockBuffering Nothing)+              forM_ (split 10 (optVarInit opt)) $ \xs -> do+                hPutStrLn h $ intercalate " "  (map show xs)+              hClose h+              ubcsat' opt fname (Just varInitFile)++  case optProblemFile opt of+    Just fname -> f fname+    Nothing -> do+      withTempFile dir ".wcnf" $ \fname h -> do+        hSetBinaryMode h True+        hSetBuffering h (BlockBuffering Nothing)+        MaxSAT.hPutWCNF h (optProblem opt)+        hClose h+        f fname++ubcsat' :: Options -> FilePath -> Maybe FilePath -> IO [(Integer, SAT.Model)]+ubcsat' opt fname varInitFile = do+  let wcnf = optProblem opt+  let args =+        [ "-w" | ".wcnf" `isSuffixOf` map toLower fname] +++        [ "-alg", "irots"+        , "-seed", "0"+        , "-runs", "10"+        , "-cutoff", show (MaxSAT.numVars wcnf * 50)+        , "-timeout", show (10 :: Int)+        , "-gtimeout", show (30 :: Int)+        , "-solve"+        , "-r", "bestsol"+        , "-inst", fname+        ] +++        (case varInitFile of+           Nothing -> []+           Just fname2 -> ["-varinitfile", fname2])+      stdinStr = ""++  putStrLn $ "c Running " ++ show (optCommand opt) ++ " with " ++ show args+  ret <- try $ readProcess (optCommand opt) args stdinStr+  case ret of+    Left (err :: IOError) -> do+      forM_ (lines (show err)) $ \l -> do+        putStr "c " >> putStrLn l+      return []+    Right s -> do+      forM_ (lines s) $ \l -> putStr "c " >> putStrLn l+      return $ scanSolutions (MaxSAT.numVars wcnf) s++scanSolutions :: Int -> String -> [(Integer, SAT.Model)]+scanSolutions nv s = rights $ map (parse (solution nv) "") $ lines s++#if MIN_VERSION_megaparsec(6,0,0)+solution :: MonadParsec Void String m => Int -> m (Integer, SAT.Model)+#else+solution :: Int -> Parser (Integer, SAT.Model)+#endif+solution nv = do+  skipSome digitChar+  space+  _ <- char '0' <|> char '1'+  space+  obj <- liftM read $ some digitChar+  space+  values <- many ((char '0' >> return False) <|> (char '1' >> return True))+  let m = array (1, nv) (zip [1..] values)+  return (obj, m)+++split :: Int -> [a] -> [[a]]+split n = go+  where+    go [] = []+    go xs =+      case splitAt n xs of+        (ys, zs) -> ys : go zs
+ app/toysat/toysat.hs view
@@ -0,0 +1,1039 @@+{-# LANGUAGE ScopedTypeVariables, CPP #-}+{-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  toysat+-- Copyright   :  (c) Masahiro Sakai 2012-2014+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+-- Portability :  non-portable (ScopedTypeVariables, CPP)+--+-- A toy-level SAT solver based on CDCL.+--+-----------------------------------------------------------------------------++module Main where++import Control.Applicative ((<$>))+import Control.Concurrent (getNumCapabilities)+import Control.Concurrent.Timeout+import Control.Monad+import Control.Exception+import Data.Array.IArray+import Data.Array.IO+import qualified Data.ByteString.Lazy as BS+import Data.Default.Class+import Data.IntMap (IntMap)+import qualified Data.IntMap as IntMap+import qualified Data.IntSet as IntSet+import Data.Map (Map)+import qualified Data.Map as Map+import qualified Data.Foldable as F+import qualified Data.Traversable as T+import Data.Char+import Data.IORef+import Data.List+import Data.Maybe+import Data.Ord+import Data.Word+import qualified Data.Vector.Unboxed as V+import Data.Version+import Data.Scientific as Scientific+import Data.Time+import System.IO+import System.Environment+import System.Exit+#if !MIN_VERSION_time(1,5,0)+import System.Locale (defaultTimeLocale)+#endif+import System.Clock+import System.Console.GetOpt+import System.FilePath+import qualified System.Info as SysInfo+import qualified System.Random.MWC as Rand+import Text.Printf+#ifdef __GLASGOW_HASKELL__+import GHC.Environment (getFullArgs)+#endif+#if defined(__GLASGOW_HASKELL__)+import qualified GHC.Stats as Stats+#endif++import qualified Data.PseudoBoolean as PBFile+import qualified Data.PseudoBoolean.Attoparsec as PBFileAttoparsec+import qualified ToySolver.Data.MIP as MIP+import qualified ToySolver.Data.MIP.Solution.Gurobi as GurobiSol+import qualified ToySolver.Converter.GCNF2MaxSAT as GCNF2MaxSAT+import qualified ToySolver.Converter.MaxSAT2WBO as MaxSAT2WBO+import qualified ToySolver.Converter.MIP2PB as MIP2PB+import qualified ToySolver.Converter.PB2SAT as PB2SAT+import qualified ToySolver.Converter.PB2WBO as PB2WBO+import qualified ToySolver.Converter.WBO2MaxSAT as WBO2MaxSAT+import qualified ToySolver.Converter.WBO2PB as WBO2PB+import qualified ToySolver.SAT as SAT+import qualified ToySolver.SAT.Types as SAT+import qualified ToySolver.SAT.PBO as PBO+import qualified ToySolver.SAT.Encoder.Integer as Integer+import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin+import qualified ToySolver.SAT.Encoder.PBNLC as PBNLC+import qualified ToySolver.SAT.MessagePassing.SurveyPropagation as SP+import qualified ToySolver.SAT.MUS as MUS+import qualified ToySolver.SAT.MUS.Enum as MUSEnum+import ToySolver.SAT.Printer+import qualified ToySolver.Text.CNF as CNF+import qualified ToySolver.Text.MaxSAT as MaxSAT+import qualified ToySolver.Text.GCNF as GCNF+import ToySolver.Version+import ToySolver.Internal.Util (showRational, setEncodingChar8)++import qualified UBCSAT++-- ------------------------------------------------------------------------++data Mode = ModeHelp | ModeVersion | ModeSAT | ModeMUS | ModePB | ModeWBO | ModeMaxSAT | ModeMIP++data Options+  = Options+  { optMode          :: Maybe Mode+  , optSATConfig     :: SAT.Config+  , optRandomSeed    :: Maybe Rand.Seed+  , optLinearizerPB  :: Bool+  , optOptMethod     :: PBO.Method+  , optObjFunVarsHeuristics :: Bool+  , optLocalSearchInitial   :: Bool+  , optMUSMethod :: MUS.Method+  , optAllMUSes :: Bool+  , optAllMUSMethod :: MUSEnum.Method+  , optPrintRational :: Bool+  , optTimeout :: Integer+  , optWriteFile :: Maybe FilePath+  , optUBCSAT :: FilePath+  , optInitSP :: Bool+  , optTempDir :: Maybe FilePath+  , optFileEncoding :: Maybe String+  }++instance Default Options where+  def =+    Options+    { optMode          = Nothing+    , optSATConfig     = def+    , optRandomSeed    = Nothing+    , optLinearizerPB  = False+    , optOptMethod     = def+    , optObjFunVarsHeuristics = PBO.defaultEnableObjFunVarsHeuristics+    , optLocalSearchInitial   = False+    , optMUSMethod = MUS.optMethod def+    , optAllMUSes = False+    , optAllMUSMethod = MUSEnum.optMethod def+    , optPrintRational = False+    , optTimeout = 0+    , optWriteFile = Nothing+    , optUBCSAT = "ubcsat"+    , optInitSP = False+    , optTempDir = Nothing+    , optFileEncoding = Nothing+    }++options :: [OptDescr (Options -> Options)]+options =+    [ Option ['h'] ["help"]   (NoArg (\opt -> opt{ optMode = Just ModeHelp   })) "show help"+    , Option [] ["version"]   (NoArg (\opt -> opt{ optMode = Just ModeVersion})) "show version"++    , Option []    ["sat"]    (NoArg (\opt -> opt{ optMode = Just ModeSAT    })) "solve boolean satisfiability problem in .cnf file (default)"+    , Option []    ["mus"]    (NoArg (\opt -> opt{ optMode = Just ModeMUS    })) "solve minimally unsatisfiable subset problem in .gcnf or .cnf file"+    , Option []    ["pb"]     (NoArg (\opt -> opt{ optMode = Just ModePB     })) "solve pseudo boolean problem in .opb file"+    , Option []    ["wbo"]    (NoArg (\opt -> opt{ optMode = Just ModeWBO    })) "solve weighted boolean optimization problem in .wbo file"+    , Option []    ["maxsat"] (NoArg (\opt -> opt{ optMode = Just ModeMaxSAT })) "solve MaxSAT problem in .cnf or .wcnf file"+    , Option []    ["lp"]     (NoArg (\opt -> opt{ optMode = Just ModeMIP    })) "solve bounded integer programming problem in .lp or .mps file"++    , Option [] ["restart"]+        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configRestartStrategy = parseRestartStrategy val } }) "<str>")+        ("Restart startegy: " ++ intercalate ", "+         [ SAT.showRestartStrategy s ++ (if SAT.configRestartStrategy (optSATConfig def) == s then " (default)" else "")+         | s <- [minBound .. maxBound] ])+    , Option [] ["restart-first"]+        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configRestartFirst = read val } }) "<int>")+        (printf "The initial restart limit. (default %d)" (SAT.configRestartFirst def))+    , Option [] ["restart-inc"]+        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configRestartInc = read val } }) "<real>")+        (printf "The factor with which the restart limit is multiplied in each restart. (default %f)" (SAT.configRestartInc def))+    , Option [] ["learning"]+        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configLearningStrategy = parseLearningStrategy val } }) "<str>")+        ("Leaning scheme: " ++ intercalate ", "+         [ SAT.showLearningStrategy s ++ (if SAT.configLearningStrategy (optSATConfig def) == s then " (default)" else "")+         | s <- [minBound .. maxBound] ])+    , Option [] ["learnt-size-first"]+        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configLearntSizeFirst = read val } }) "<int>")+        "The initial limit for learnt clauses."+    , Option [] ["learnt-size-inc"]+        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configLearntSizeInc = read val } }) "<real>")+        (printf "The limit for learnt clauses is multiplied with this factor periodically. (default %f)" (SAT.configLearntSizeInc def))+    , Option [] ["branch"]+        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configBranchingStrategy = parseBranchingStrategy val } }) "<str>")+        ("Branching startegy: " ++ intercalate ", "+         [ SAT.showBranchingStrategy s ++ (if SAT.configBranchingStrategy (optSATConfig def) == s then " (default)" else "")+         | s <- [minBound .. maxBound] ])+    , Option [] ["erwa-alpha-first"]+        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configERWAStepSizeFirst = read val } }) "<real>")+        (printf "step-size alpha in ERWA and LRB branching heuristic is initialized with this value. (default %f)" (SAT.configERWAStepSizeFirst def))+    , Option [] ["erwa-alpha-dec"]+        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configERWAStepSizeDec = read val } }) "<real>")+        (printf "step-size alpha in ERWA and LRB branching heuristic is decreased by this value after each conflict. (default %f)" (SAT.configERWAStepSizeDec def))+    , Option [] ["erwa-alpha-min"]+        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configERWAStepSizeMin = read val } }) "<real>")+        (printf "step-size alpha in ERWA and LRB branching heuristic is decreased until it reach the value. (default %f)" (SAT.configERWAStepSizeMin def))+    , Option [] ["ema-decay"]+        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configEMADecay = read val } }) "<real>")+        (printf "inverse of the variable EMA decay factor used by LRB branching heuristic. (default %f)" (SAT.configEMADecay def))+    , Option [] ["ccmin"]+        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configCCMin = read val } }) "<int>")+        (printf "Conflict clause minimization (0=none, 1=local, 2=recursive; default %d)" (SAT.configCCMin def))+    , Option [] ["enable-phase-saving"]+        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configEnablePhaseSaving = True } }))+        ("Enable phase saving" ++ (if SAT.configEnablePhaseSaving def then " (default)" else ""))+    , Option [] ["disable-phase-saving"]+        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configEnablePhaseSaving = False } }))+        ("Disable phase saving" ++ (if SAT.configEnablePhaseSaving def then "" else " (default)"))+    , Option [] ["enable-forward-subsumption-removal"]+        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configEnableForwardSubsumptionRemoval = True } }))+        ("Enable forward subumption removal (clauses only)" ++ (if SAT.configEnableForwardSubsumptionRemoval def then " (default)" else ""))+    , Option [] ["disable-forward-subsumption-removal"]+        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configEnableForwardSubsumptionRemoval = False } }))+        ("Disable forward subsumption removal (clauses only)" ++ (if SAT.configEnableForwardSubsumptionRemoval def then "" else " (default)"))+    , Option [] ["enable-backward-subsumption-removal"]+        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configEnableBackwardSubsumptionRemoval = True } }))+        ("Enable backward subsumption removal." ++ (if SAT.configEnableBackwardSubsumptionRemoval def then " (default)" else ""))+    , Option [] ["disable-backward-subsumption-removal"]+        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configEnableBackwardSubsumptionRemoval = False } }))+        ("Disable backward subsumption removal." ++ (if SAT.configEnableBackwardSubsumptionRemoval def then "" else " (default)"))++    , Option [] ["random-freq"]+        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configRandomFreq = read val } }) "<0..1>")+        (printf "The frequency with which the decision heuristic tries to choose a random variable (default %f)" (SAT.configRandomFreq def))+    , Option [] ["random-seed"]+        (ReqArg (\val opt -> opt{ optRandomSeed = Just (Rand.toSeed (V.singleton (read val) :: V.Vector Word32)) }) "<int>")+        "random seed used by the random variable selection"+    , Option [] ["random-gen"]+        (ReqArg (\val opt -> opt{ optRandomSeed = Just (Rand.toSeed (V.fromList (map read $ words $ val) :: V.Vector Word32)) }) "<str>")+        "another way of specifying random seed used by the random variable selection"++    , Option [] ["init-sp"]+        (NoArg (\opt -> opt{ optInitSP = True }))+        "Use survey propation to compute initial polarity (when possible)"++    , Option [] ["linearizer-pb"]+        (NoArg (\opt -> opt{ optLinearizerPB = True }))+        "Use PB constraint in linearization."++    , Option [] ["pb-handler"]+        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configPBHandlerType = parsePBHandler val } }) "<str>")+        ("PB constraint handler: " ++ intercalate ", "+         [ SAT.showPBHandlerType h ++ (if SAT.configPBHandlerType (optSATConfig def) == h then " (default)" else "")+         | h <- [minBound .. maxBound] ])+    , Option [] ["pb-split-clause-part"]+        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configEnablePBSplitClausePart = True } }))+        ("Split clause part of PB constraints." ++ (if SAT.configEnablePBSplitClausePart def then " (default)" else ""))+    , Option [] ["no-pb-split-clause-part"]+        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configEnablePBSplitClausePart = False } }))+        ("Do not split clause part of PB constraints." ++ (if SAT.configEnablePBSplitClausePart def then "" else " (default)"))++    , Option [] ["opt-method"]+        (ReqArg (\val opt -> opt{ optOptMethod = parseOptMethod val }) "<str>")+        ("Optimization method: " ++ intercalate ", "+         [PBO.showMethod m ++ (if optOptMethod def == m then " (default)" else "") | m <- [minBound .. maxBound]])+    , Option [] ["objfun-heuristics"]+        (NoArg (\opt -> opt{ optObjFunVarsHeuristics = True }))+        "Enable heuristics for polarity/activity of variables in objective function (default)"+    , Option [] ["no-objfun-heuristics"]+        (NoArg (\opt -> opt{ optObjFunVarsHeuristics = False }))+        "Disable heuristics for polarity/activity of variables in objective function"+    , Option [] ["ls-initial"]+        (NoArg (\opt -> opt{ optLocalSearchInitial = True }))+        "Use local search (currently UBCSAT) for finding initial solution"++    , Option [] ["all-mus"]+        (NoArg (\opt -> opt{ optMode = Just ModeMUS, optAllMUSes = True }))+        "enumerate all MUSes"+    , Option [] ["mus-method"]+        (ReqArg (\val opt -> opt{ optMUSMethod = parseMUSMethod val }) "<str>")+        ("MUS computation method: " ++ intercalate ", "+         [MUS.showMethod m ++ (if optMUSMethod def == m then " (default)" else "") | m <- [minBound .. maxBound]])+    , Option [] ["all-mus-method"]+        (ReqArg (\val opt -> opt{ optAllMUSMethod = parseAllMUSMethod val }) "<str>")+        ("MUS enumeration method: " ++ intercalate ", "+         [MUSEnum.showMethod m ++ (if optAllMUSMethod def == m then " (default)" else "") | m <- [minBound .. maxBound]])++    , Option [] ["print-rational"]+        (NoArg (\opt -> opt{ optPrintRational = True }))+        "print rational numbers instead of decimals"+    , Option ['w'] []+        (ReqArg (\val opt -> opt{ optWriteFile = Just val }) "<filename>")+        "write model to filename in Gurobi .sol format"++    , Option [] ["check-model"]+        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configCheckModel = True } }))+        "check model for debug"++    , Option [] ["timeout"]+        (ReqArg (\val opt -> opt{ optTimeout = read val }) "<int>")+        "Kill toysat after given number of seconds (default 0 (no limit))"++    , Option [] ["with-ubcsat"]+        (ReqArg (\val opt -> opt{ optUBCSAT = val }) "<PATH>")+        "give the path to the UBCSAT command"+    , Option [] ["temp-dir"]+        (ReqArg (\val opt -> opt{ optTempDir = Just val }) "<PATH>")+        "temporary directory"++    , Option [] ["encoding"]+        (ReqArg (\val opt -> opt{ optFileEncoding = Just val }) "<ENCODING>")+        "file encoding for LP/MPS files"+    ]+  where+    parseOptMethod s = fromMaybe (error (printf "unknown optimization method \"%s\"" s)) (PBO.parseMethod s)++    parseMUSMethod s = fromMaybe (error (printf "unknown MUS finding method \"%s\"" s)) (MUS.parseMethod s)++    parseAllMUSMethod s = fromMaybe (error (printf "unknown MUS enumeration method \"%s\"" s)) (MUSEnum.parseMethod s)++    parseRestartStrategy s = fromMaybe (error (printf "unknown restart strategy \"%s\"" s)) (SAT.parseRestartStrategy s)++    parseLearningStrategy s = fromMaybe (error (printf "unknown learning strategy \"%s\"" s)) (SAT.parseLearningStrategy s)++    parseBranchingStrategy s = fromMaybe (error (printf "unknown branching strategy \"%s\"" s)) (SAT.parseBranchingStrategy s)++    parsePBHandler s = fromMaybe (error (printf "unknown PB constraint handler \"%s\"" s)) (SAT.parsePBHandlerType s)++main :: IO ()+main = do+#ifdef FORCE_CHAR8+  setEncodingChar8+#endif++  startCPU <- getTime ProcessCPUTime+  startWC  <- getTime Monotonic+  args <- getArgs+  case getOpt Permute options args of+    (_,_,errs@(_:_)) -> do+      mapM_ putStrLn errs+      exitFailure++    (o,args2,[]) -> do+      let opt = foldl (flip id) def o      +          mode =+            case optMode opt of+              Just m  -> m+              Nothing ->+                case args2 of+                  [] -> ModeHelp+                  fname : _ ->+                    case map toLower (takeExtension fname) of+                      ".cnf"  -> ModeSAT+                      ".gcnf" -> ModeMUS+                      ".opb"  -> ModePB+                      ".wbo"  -> ModeWBO+                      ".wcnf" -> ModeMaxSAT+                      ".lp"   -> ModeMIP+                      ".mps"  -> ModeMIP+                      _ -> ModeSAT++      case mode of+        ModeHelp    -> showHelp stdout+        ModeVersion -> hPutStrLn stdout (showVersion version)+        _ -> do+          printSysInfo+#ifdef __GLASGOW_HASKELL__+          fullArgs <- getFullArgs+#else+          let fullArgs = args+#endif+          putCommentLine $ printf "command line = %s" (show fullArgs)++          let timelim = optTimeout opt * 10^(6::Int)+    +          ret <- timeout (if timelim > 0 then timelim else (-1)) $ do+             solver <- newSolver opt+             case mode of+               ModeHelp    -> showHelp stdout+               ModeVersion -> hPutStrLn stdout (showVersion version)+               ModeSAT     -> mainSAT opt solver args2+               ModeMUS     -> mainMUS opt solver args2+               ModePB      -> mainPB opt solver args2+               ModeWBO     -> mainWBO opt solver args2+               ModeMaxSAT  -> mainMaxSAT opt solver args2+               ModeMIP     -> mainMIP opt solver args2+    +          when (isNothing ret) $ do+            putCommentLine "TIMEOUT"+          endCPU <- getTime ProcessCPUTime+          endWC  <- getTime Monotonic+          putCommentLine $ printf "total CPU time = %.3fs" (durationSecs startCPU endCPU)+          putCommentLine $ printf "total wall clock time = %.3fs" (durationSecs startWC endWC)+          printGCStat++printGCStat :: IO ()+#if defined(__GLASGOW_HASKELL__)+#if __GLASGOW_HASKELL__ >= 802+printGCStat = do+  b <- Stats.getRTSStatsEnabled+  when b $ do+    stat <- Stats.getRTSStats+    putCommentLine "RTSStats:"+    putCommentLine $ printf "  gcs = %d"                             $ Stats.gcs stat+    putCommentLine $ printf "  major_gcs = %d"                       $ Stats.major_gcs stat+    putCommentLine $ printf "  allocated_bytes = %d"                 $ Stats.allocated_bytes stat+    putCommentLine $ printf "  max_live_bytes = %d"                  $ Stats.max_live_bytes stat+    putCommentLine $ printf "  max_large_objects_bytes = %d"         $ Stats.max_large_objects_bytes stat+    putCommentLine $ printf "  max_compact_bytes = %d"               $ Stats.max_compact_bytes stat+    putCommentLine $ printf "  max_slop_bytes = %d"                  $ Stats.max_slop_bytes stat+    putCommentLine $ printf "  max_mem_in_use_bytes = %d"            $ Stats.max_mem_in_use_bytes stat+    putCommentLine $ printf "  cumulative_live_bytes = %d"           $ Stats.cumulative_live_bytes stat+    putCommentLine $ printf "  copied_bytes = %d"                    $ Stats.copied_bytes stat+    putCommentLine $ printf "  par_copied_bytes = %d"                $ Stats.par_copied_bytes stat+    putCommentLine $ printf "  cumulative_par_max_copied_bytes = %d" $ Stats.cumulative_par_max_copied_bytes stat+    putCommentLine $ printf "  mutator_cpu_ns = %d"                  $ Stats.mutator_cpu_ns stat+    putCommentLine $ printf "  mutator_elapsed_ns = %d"              $ Stats.mutator_elapsed_ns stat+    putCommentLine $ printf "  gc_cpu_ns = %d"                       $ Stats.gc_cpu_ns stat+    putCommentLine $ printf "  gc_elapsed_ns = %d"                   $ Stats.gc_elapsed_ns stat+    putCommentLine $ printf "  cpu_ns = %d"                          $ Stats.cpu_ns stat+    putCommentLine $ printf "  elapsed_ns = %d"                      $ Stats.elapsed_ns stat+    let gc = Stats.gc stat+    putCommentLine $ "  gc:"+    putCommentLine $ printf "    gen = %d"                           $ Stats.gcdetails_gen gc+    putCommentLine $ printf "    threads = %d"                       $ Stats.gcdetails_threads gc+    putCommentLine $ printf "    allocated_bytes = %d"               $ Stats.gcdetails_allocated_bytes gc+    putCommentLine $ printf "    live_bytes = %d"                    $ Stats.gcdetails_live_bytes gc+    putCommentLine $ printf "    large_objects_bytes = %d"           $ Stats.gcdetails_large_objects_bytes gc+    putCommentLine $ printf "    compact_bytes = %d"                 $ Stats.gcdetails_compact_bytes gc+    putCommentLine $ printf "    slop_bytes = %d"                    $ Stats.gcdetails_slop_bytes gc+    putCommentLine $ printf "    mem_in_use_bytes = %d"              $ Stats.gcdetails_mem_in_use_bytes gc+    putCommentLine $ printf "    copied_bytes = %d"                  $ Stats.gcdetails_copied_bytes gc+    putCommentLine $ printf "    par_max_copied_bytes = %d"          $ Stats.gcdetails_par_max_copied_bytes gc+    putCommentLine $ printf "    sync_elapsed_ns = %d"               $ Stats.gcdetails_sync_elapsed_ns gc+    putCommentLine $ printf "    cpu_ns = %d"                        $ Stats.gcdetails_cpu_ns gc+    putCommentLine $ printf "    elapsed_ns = %d"                    $ Stats.gcdetails_elapsed_ns gc+#else+printGCStat = do+  b <- Stats.getGCStatsEnabled+  when b $ do+    stat <- Stats.getGCStats+    putCommentLine "GCStats:"+    putCommentLine $ printf "  bytesAllocated = %d"         $ Stats.bytesAllocated stat+    putCommentLine $ printf "  numGcs = %d"                 $ Stats.numGcs stat+    putCommentLine $ printf "  maxBytesUsed = %d"           $ Stats.maxBytesUsed stat+    putCommentLine $ printf "  numByteUsageSamples = %d"    $ Stats.numByteUsageSamples stat+    putCommentLine $ printf "  cumulativeBytesUsed = %d"    $ Stats.cumulativeBytesUsed stat+    putCommentLine $ printf "  bytesCopied = %d"            $ Stats.bytesCopied stat+    putCommentLine $ printf "  currentBytesUsed = %d"       $ Stats.currentBytesUsed stat+    putCommentLine $ printf "  currentBytesSlop = %d"       $ Stats.currentBytesSlop stat+    putCommentLine $ printf "  maxBytesSlop = %d"           $ Stats.maxBytesSlop stat+    putCommentLine $ printf "  peakMegabytesAllocated = %d" $ Stats.peakMegabytesAllocated stat+    putCommentLine $ printf "  mutatorCpuSeconds = %5.2f"   $ Stats.mutatorCpuSeconds stat+    putCommentLine $ printf "  mutatorWallSeconds = %5.2f"  $ Stats.mutatorWallSeconds stat+    putCommentLine $ printf "  gcCpuSeconds = %5.2f"        $ Stats.gcCpuSeconds stat+    putCommentLine $ printf "  gcWallSeconds = %5.2f"       $ Stats.gcWallSeconds stat+    putCommentLine $ printf "  cpuSeconds = %5.2f"          $ Stats.cpuSeconds stat+    putCommentLine $ printf "  wallSeconds = %5.2f"         $ Stats.wallSeconds stat+    putCommentLine $ printf "  parTotBytesCopied = %d"      $ Stats.parTotBytesCopied stat+    putCommentLine $ printf "  parMaxBytesCopied = %d"      $ Stats.parMaxBytesCopied stat+#endif+#else+printGCStat = return ()+#endif++showHelp :: Handle -> IO ()+showHelp h = hPutStrLn h (usageInfo header options)++header :: String+header = unlines+  [ "Usage:"+  , "  toysat [OPTION]... [file.cnf|-]"+  , "  toysat [OPTION]... --mus [file.gcnf|-]"+  , "  toysat [OPTION]... --pb [file.opb|-]"+  , "  toysat [OPTION]... --wbo [file.wbo|-]"+  , "  toysat [OPTION]... --maxsat [file.cnf|file.wcnf|-]"+  , "  toysat [OPTION]... --lp [file.lp|file.mps|-]"+  , ""+  , "Options:"+  ]++printSysInfo :: IO ()+printSysInfo = do+  tm <- getZonedTime+  putCommentLine $ printf "%s" (formatTime defaultTimeLocale "%FT%X%z" tm)+  putCommentLine $ printf "version = %s" (showVersion version)+  putCommentLine $ printf "githash = %s" (fromMaybe "<unknown>" gitHash)+  putCommentLine $ printf "compilationtime = %s" (show compilationTime)+  putCommentLine $ printf "arch = %s" SysInfo.arch+  putCommentLine $ printf "os = %s" SysInfo.os+  putCommentLine $ printf "compiler = %s %s" SysInfo.compilerName (showVersion SysInfo.compilerVersion)+  putCommentLine "packages:"+  forM_ packageVersions $ \(package, ver) -> do+    putCommentLine $ printf "  %s-%s" package ver++putCommentLine :: String -> IO ()+putCommentLine s = do+  putStr "c "+  putStrLn s+  hFlush stdout++putSLine :: String -> IO ()+putSLine  s = do+  putStr "s "+  putStrLn s+  hFlush stdout++putOLine :: String -> IO ()+putOLine  s = do+  putStr "o "+  putStrLn s+  hFlush stdout++newSolver :: Options -> IO SAT.Solver+newSolver opts = do+  solver <- SAT.newSolverWithConfig (optSATConfig opts)+  SAT.setLogger solver putCommentLine+  case optRandomSeed opts of+    Nothing -> SAT.setRandomGen solver =<< Rand.createSystemRandom+    Just s -> SAT.setRandomGen solver =<< Rand.initialize (Rand.fromSeed s)+  do gen <- SAT.getRandomGen solver+     s <- Rand.save gen+     putCommentLine $ "use --random-gen=" ++ show (unwords . map show . V.toList . Rand.fromSeed $ s) ++ " option to reproduce the execution"+  return solver++-- ------------------------------------------------------------------------++mainSAT :: Options -> SAT.Solver -> [String] -> IO ()+mainSAT opt solver args = do+  ret <- case args of+           ["-"]   -> liftM CNF.parseByteString $ BS.hGetContents stdin+           [fname] -> CNF.parseFile fname+           _ -> showHelp stderr >> exitFailure+  case ret of+    Left err -> hPrint stderr err >> exitFailure+    Right cnf -> do+      let fname = case args of+                    [fname] | or [".cnf" `isSuffixOf` map toLower fname] -> Just fname+                    _ -> Nothing+      solveSAT opt solver cnf fname++solveSAT :: Options -> SAT.Solver -> CNF.CNF -> Maybe FilePath -> IO ()+solveSAT opt solver cnf cnfFileName = do+  putCommentLine $ printf "#vars %d" (CNF.numVars cnf)+  putCommentLine $ printf "#constraints %d" (CNF.numClauses cnf)+  SAT.newVars_ solver (CNF.numVars cnf)+  forM_ (CNF.clauses cnf) $ \clause ->+    SAT.addClause solver clause++  spHighlyBiased <-+    if optInitSP opt then do+      initPolarityUsingSP solver (CNF.numVars cnf)+        (CNF.numVars cnf) [(1, clause) | clause <- CNF.clauses cnf]+    else+      return IntMap.empty++  when (optLocalSearchInitial opt) $ do+    fixed <- SAT.getFixedLiterals solver+    let var_init1 = IntMap.fromList [(abs lit, lit > 0) | lit <- fixed, abs lit <= CNF.numVars cnf]+        var_init2 = IntMap.map (>0) spHighlyBiased+        -- note that IntMap.union is left-biased.+        var_init = [if b then v else -v | (v, b) <- IntMap.toList (var_init1 `IntMap.union` var_init2)]+    let wcnf =+          MaxSAT.WCNF+          { MaxSAT.numVars = CNF.numVars cnf+          , MaxSAT.numClauses = CNF.numClauses cnf+          , MaxSAT.topCost = 1+          , MaxSAT.clauses = [(1, clause) | clause <- CNF.clauses cnf]+          }+    let opt2 =+          def+          { UBCSAT.optCommand = optUBCSAT opt+          , UBCSAT.optTempDir = optTempDir opt+          , UBCSAT.optProblem = wcnf+          , UBCSAT.optProblemFile = cnfFileName+          , UBCSAT.optVarInit = var_init+          }+    ret <- UBCSAT.ubcsatBest opt2+    case ret of+      Nothing -> return ()+      Just (_,m) -> do+        forM_ (assocs m) $ \(v, val) -> do+          SAT.setVarPolarity solver v val++  result <- SAT.solve solver+  putSLine $ if result then "SATISFIABLE" else "UNSATISFIABLE"+  when result $ do+    m <- SAT.getModel solver+    satPrintModel stdout m (CNF.numVars cnf)+    writeSOLFile opt m Nothing (CNF.numVars cnf)++initPolarityUsingSP :: SAT.Solver -> Int -> Int -> [(Double, SAT.Clause)] -> IO (IntMap Double)+initPolarityUsingSP solver nvOrig nv clauses = do+  n <- getNumCapabilities+  putCommentLine $ "Running survey propgation using " ++ show n ++" threads ..."+  startWC  <- getTime Monotonic+  sp <- SP.newSolver nv clauses  +  SP.initializeRandom sp =<< SAT.getRandomGen solver+  SP.setNThreads sp n+  lits <- SAT.getFixedLiterals solver+  forM_ lits $ \lit -> do+    when (abs lit <= nvOrig) $ SP.fixLit sp lit+  b <- SP.propagate sp+  endWC  <- getTime Monotonic+  if b then do+    putCommentLine $ printf "Survey propagation converged in %.3fs" (durationSecs startWC endWC)+    xs <- liftM catMaybes $ forM [1 .. nvOrig] $ \v -> do+      (pt,pf,_)<- SP.getVarProb sp v+      let bias = pt - pf+      SAT.setVarPolarity solver v (bias >= 0)+      if abs bias > 0.3 then+        return $ Just (v, bias)+      else+        return Nothing+    forM_ (zip (sortBy (comparing (abs . snd)) xs) [1..]) $ \((v,_),w) -> do+      replicateM w $ SAT.varBumpActivity solver v+    return $ IntMap.fromList xs+  else do+    putCommentLine $ printf "Survey propagation did not converge"+    return $ IntMap.empty++-- ------------------------------------------------------------------------++mainMUS :: Options -> SAT.Solver -> [String] -> IO ()+mainMUS opt solver args = do+  gcnf <- case args of+           ["-"]   -> do+             s <- BS.hGetContents stdin+             case GCNF.parseByteString s of+               Left err   -> hPutStrLn stderr err >> exitFailure+               Right gcnf -> return gcnf+           [fname] -> do+             ret <- GCNF.parseFile fname+             case ret of+               Left err   -> hPutStrLn stderr err >> exitFailure+               Right gcnf -> return gcnf+           _ -> showHelp stderr >> exitFailure+  solveMUS opt solver gcnf++solveMUS :: Options -> SAT.Solver -> GCNF.GCNF -> IO ()+solveMUS opt solver gcnf = do+  putCommentLine $ printf "#vars %d" (GCNF.numVars gcnf)+  putCommentLine $ printf "#constraints %d" (GCNF.numClauses gcnf)+  putCommentLine $ printf "#groups %d" (GCNF.lastGroupIndex gcnf)++  SAT.resizeVarCapacity solver (GCNF.numVars gcnf + GCNF.lastGroupIndex gcnf)+  SAT.newVars_ solver (GCNF.numVars gcnf)++  tbl <- forM [1 .. GCNF.lastGroupIndex gcnf] $ \i -> do+    sel <- SAT.newVar solver+    return (i, sel)+  let idx2sel :: Array Int SAT.Var+      idx2sel = array (1, GCNF.lastGroupIndex gcnf) tbl+      selrng  = if null tbl then (0,-1) else (snd $ head tbl, snd $ last tbl)+      sel2idx :: Array SAT.Lit Int+      sel2idx = array selrng [(sel, idx) | (idx, sel) <- tbl]++  (idx2clausesM :: IOArray Int [SAT.Clause]) <- newArray (1, GCNF.lastGroupIndex gcnf) []+  forM_ (GCNF.clauses gcnf) $ \(idx, clause) ->+    if idx==0+    then SAT.addClause solver clause+    else do+      SAT.addClause solver (- (idx2sel ! idx) : clause)+      cs <- readArray idx2clausesM idx+      writeArray idx2clausesM idx (clause : cs)+  (idx2clauses :: Array Int [SAT.Clause]) <- freeze idx2clausesM++  when (optInitSP opt) $ do+    let wcnf = GCNF2MaxSAT.convert gcnf+    initPolarityUsingSP solver (GCNF.numVars gcnf)+      (MaxSAT.numVars wcnf) [(fromIntegral w, clause) | (w, clause) <- MaxSAT.clauses wcnf]+    return ()++  result <- SAT.solveWith solver (map (idx2sel !) [1..GCNF.lastGroupIndex gcnf])+  putSLine $ if result then "SATISFIABLE" else "UNSATISFIABLE"+  if result+    then do+      m <- SAT.getModel solver+      satPrintModel stdout m (GCNF.numVars gcnf)+      writeSOLFile opt m Nothing (GCNF.numVars gcnf)+    else do+      if not (optAllMUSes opt)+      then do+          let opt2 = def+                     { MUS.optMethod = optMUSMethod opt+                     , MUS.optLogger = putCommentLine+                     , MUS.optShowLit = \lit -> show (sel2idx ! lit)+                     , MUS.optEvalConstr = \m sel ->+                         and [SAT.evalClause m c | c <- idx2clauses ! (sel2idx ! sel)]+                     }+          mus <- MUS.findMUSAssumptions solver opt2+          let mus2 = sort $ map (sel2idx !) $ IntSet.toList mus+          musPrintSol stdout mus2+      else do+          musCounter <- newIORef 1+          mcsCounter <- newIORef 1+          let opt2 = def+                     { MUSEnum.optMethod = optAllMUSMethod opt+                     , MUSEnum.optLogger = putCommentLine+                     , MUSEnum.optShowLit = \lit -> show (sel2idx ! lit)+                     , MUSEnum.optEvalConstr = \m sel ->+                         and [SAT.evalClause m c | c <- idx2clauses ! (sel2idx ! sel)]+                     , MUSEnum.optOnMCSFound = \mcs -> do+                         i <- readIORef mcsCounter+                         modifyIORef' mcsCounter (+1)+                         let mcs2 = sort $ map (sel2idx !) $ IntSet.toList mcs+                         putCommentLine $ "MCS #" ++ show (i :: Int) ++ ": " ++ intercalate " " (map show mcs2)+                     , MUSEnum.optOnMUSFound = \mus -> do+                         i <- readIORef musCounter+                         modifyIORef' musCounter (+1)+                         putCommentLine $ "MUS #" ++ show (i :: Int)+                         let mus2 = sort $ map (sel2idx !) $ IntSet.toList mus+                         musPrintSol stdout mus2+                     }+          MUSEnum.allMUSAssumptions solver (map snd tbl) opt2+          return ()++-- ------------------------------------------------------------------------++mainPB :: Options -> SAT.Solver -> [String] -> IO ()+mainPB opt solver args = do+  ret <- case args of+           ["-"]   -> liftM PBFileAttoparsec.parseOPBByteString $ BS.hGetContents stdin+           [fname] -> PBFileAttoparsec.parseOPBFile fname+           _ -> showHelp stderr >> exitFailure+  case ret of+    Left err -> hPutStrLn stderr err >> exitFailure+    Right formula -> solvePB opt solver formula++solvePB :: Options -> SAT.Solver -> PBFile.Formula -> IO ()+solvePB opt solver formula = do+  let nv = PBFile.pbNumVars formula+      nc = PBFile.pbNumConstraints formula+  putCommentLine $ printf "#vars %d" nv+  putCommentLine $ printf "#constraints %d" nc++  SAT.newVars_ solver nv+  enc <- Tseitin.newEncoderWithPBLin solver+  Tseitin.setUsePB enc (optLinearizerPB opt)+  pbnlc <- PBNLC.newEncoder solver enc++  forM_ (PBFile.pbConstraints formula) $ \(lhs, op, rhs) -> do+    case op of+      PBFile.Ge -> PBNLC.addPBNLAtLeast pbnlc lhs rhs+      PBFile.Eq -> PBNLC.addPBNLExactly pbnlc lhs rhs++  spHighlyBiased <- +    if optInitSP opt then do+      let (cnf, _, _) = PB2SAT.convert formula+      initPolarityUsingSP solver nv (CNF.numVars cnf) [(1.0, clause) | clause <- CNF.clauses cnf]+    else+      return IntMap.empty++  initialModel <- +    if optLocalSearchInitial opt then do+      let (wcnf, _, mtrans) = WBO2MaxSAT.convert $ PB2WBO.convert formula+      fixed <- filter (\lit -> abs lit <= nv) <$> SAT.getFixedLiterals solver+      let var_init1 = IntMap.fromList [(abs lit, lit > 0) | lit <- fixed, abs lit <= nv]+          var_init2 = IntMap.map (>0) spHighlyBiased+          -- note that IntMap.union is left-biased.+          var_init = [if b then v else -v | (v, b) <- IntMap.toList (var_init1 `IntMap.union` var_init2)]+      let opt2 =+            def+            { UBCSAT.optCommand = optUBCSAT opt+            , UBCSAT.optTempDir = optTempDir opt+            , UBCSAT.optProblem = wcnf+            , UBCSAT.optVarInit = var_init+            }+      ret <- UBCSAT.ubcsatBest opt2+      case ret of+        Nothing -> return Nothing+        Just (obj,m) -> do+          let m2 = mtrans m+          forM_ (assocs m2) $ \(v, val) -> do+            SAT.setVarPolarity solver v val+          if obj < MaxSAT.topCost wcnf then+            return $ Just m2 +          else+            return Nothing+    else+      return Nothing++  case PBFile.pbObjectiveFunction formula of+    Nothing -> do+      result <- SAT.solve solver+      putSLine $ if result then "SATISFIABLE" else "UNSATISFIABLE"+      when result $ do+        m <- SAT.getModel solver+        pbPrintModel stdout m nv+        writeSOLFile opt m Nothing nv++    Just obj' -> do+      obj'' <- PBNLC.linearizePBSumWithPolarity pbnlc Tseitin.polarityNeg obj'++      nv' <- SAT.getNVars solver+      defs <- Tseitin.getDefinitions enc+      let extendModel :: SAT.Model -> SAT.Model+          extendModel m = array (1,nv') (assocs a)+            where+              -- Use BOXED array to tie the knot+              a :: Array SAT.Var Bool+              a = array (1,nv') $ assocs m ++ [(v, Tseitin.evalFormula a phi) | (v,phi) <- defs]++      pbo <- PBO.newOptimizer2 solver obj'' (\m -> SAT.evalPBSum m obj')+      setupOptimizer pbo opt+      PBO.setOnUpdateBestSolution pbo $ \_ val -> putOLine (show val)+      PBO.setOnUpdateLowerBound pbo $ \lb -> do+        putCommentLine $ printf "lower bound updated to %d" lb++      case initialModel of+        Nothing -> return ()+        Just m -> PBO.addSolution pbo (extendModel m)++      finally (PBO.optimize pbo) $ do+        ret <- PBO.getBestSolution pbo+        case ret of+          Nothing -> do+            b <- PBO.isUnsat pbo+            if b+              then putSLine "UNSATISFIABLE"+              else putSLine "UNKNOWN"+          Just (m, val) -> do+            b <- PBO.isOptimum pbo+            if b+              then putSLine "OPTIMUM FOUND"+              else putSLine "SATISFIABLE"+            pbPrintModel stdout m nv+            writeSOLFile opt m (Just val) nv++setupOptimizer :: PBO.Optimizer -> Options -> IO ()+setupOptimizer pbo opt = do+  PBO.setEnableObjFunVarsHeuristics pbo $ optObjFunVarsHeuristics opt+  PBO.setMethod pbo $ optOptMethod opt+  PBO.setLogger pbo putCommentLine++-- ------------------------------------------------------------------------++mainWBO :: Options -> SAT.Solver -> [String] -> IO ()+mainWBO opt solver args = do+  ret <- case args of+           ["-"]   -> liftM PBFileAttoparsec.parseWBOByteString $ BS.hGetContents stdin+           [fname] -> PBFileAttoparsec.parseWBOFile fname+           _ -> showHelp stderr >> exitFailure+  case ret of+    Left err -> hPutStrLn stderr err >> exitFailure+    Right formula -> solveWBO opt solver False formula++solveWBO :: Options -> SAT.Solver -> Bool -> PBFile.SoftFormula -> IO ()+solveWBO opt solver isMaxSat formula =+  solveWBO' opt solver isMaxSat formula (WBO2MaxSAT.convert formula) Nothing++solveWBO' :: Options -> SAT.Solver -> Bool -> PBFile.SoftFormula -> (MaxSAT.WCNF, SAT.Model -> SAT.Model, SAT.Model -> SAT.Model) -> Maybe FilePath -> IO ()+solveWBO' opt solver isMaxSat formula (wcnf, _, mtrans) wcnfFileName = do+  let nv = PBFile.wboNumVars formula+      nc = PBFile.wboNumConstraints formula+  putCommentLine $ printf "#vars %d" nv+  putCommentLine $ printf "#constraints %d" nc++  SAT.resizeVarCapacity solver (nv + length [() | (Just _, _) <- PBFile.wboConstraints formula])+  enc <- Tseitin.newEncoderWithPBLin solver+  Tseitin.setUsePB enc (optLinearizerPB opt)+  pbnlc <- PBNLC.newEncoder solver enc+  (obj, defsPB) <- WBO2PB.addWBO pbnlc formula+  objLin <- PBNLC.linearizePBSumWithPolarity pbnlc Tseitin.polarityNeg obj++  spHighlyBiased <-+    if optInitSP opt then do+      initPolarityUsingSP solver nv (MaxSAT.numVars wcnf) [(fromIntegral w, c) | (w, c) <-  MaxSAT.clauses wcnf]+    else+      return IntMap.empty++  initialModel <- liftM (fmap (mtrans . snd)) $+    if optLocalSearchInitial opt then do+      fixed <- SAT.getFixedLiterals solver+      let var_init1 = IntMap.fromList [(abs lit, lit > 0) | lit <- fixed, abs lit <= nv]+          var_init2 = IntMap.map (>0) spHighlyBiased+          -- note that IntMap.union is left-biased.+          var_init = [if b then v else -v | (v, b) <- IntMap.toList (var_init1 `IntMap.union` var_init2)]+      let opt2 =+            def+            { UBCSAT.optCommand = optUBCSAT opt+            , UBCSAT.optTempDir = optTempDir opt+            , UBCSAT.optProblem = wcnf+            , UBCSAT.optProblemFile = wcnfFileName+            , UBCSAT.optVarInit = var_init+            }+      UBCSAT.ubcsatBestFeasible opt2+    else+      return Nothing++  nv' <- SAT.getNVars solver+  defsTseitin <- Tseitin.getDefinitions enc+  let extendModel :: SAT.Model -> SAT.Model+      extendModel m = array (1,nv') (assocs a)+        where+          -- Use BOXED array to tie the knot+          a :: Array SAT.Var Bool+          a = array (1,nv') $+                assocs m +++                [(v, Tseitin.evalFormula a phi) | (v, phi) <- defsTseitin] +++                [(v, SAT.evalPBConstraint a constr) | (v, constr) <- defsPB]++  let softConstrs = [(c, constr) | (Just c, constr) <- PBFile.wboConstraints formula]+                +  pbo <- PBO.newOptimizer2 solver objLin $ \m ->+           sum [if SAT.evalPBConstraint m constr then 0 else w | (w,constr) <- softConstrs]++  setupOptimizer pbo opt+  PBO.setOnUpdateBestSolution pbo $ \_ val -> putOLine (show val)+  PBO.setOnUpdateLowerBound pbo $ \lb -> do+    putCommentLine $ printf "lower bound updated to %d" lb++  case initialModel of+    Nothing -> return ()+    Just m -> PBO.addSolution pbo (extendModel m)++  finally (PBO.optimize pbo) $ do+    ret <- PBO.getBestSolution pbo+    case ret of+      Nothing -> do+        b <- PBO.isUnsat pbo+        if b+          then putSLine "UNSATISFIABLE"+          else putSLine "UNKNOWN"+      Just (m, val) -> do+        b <- PBO.isOptimum pbo+        if b then do+          putSLine "OPTIMUM FOUND"+          if isMaxSat then+            satPrintModel stdout m nv+          else+            pbPrintModel stdout m nv+          writeSOLFile opt m (Just val) nv+        else if not isMaxSat then do+          putSLine "SATISFIABLE"+          pbPrintModel stdout m nv+          writeSOLFile opt m (Just val) nv+        else +          putSLine "UNKNOWN"++-- ------------------------------------------------------------------------++mainMaxSAT :: Options -> SAT.Solver -> [String] -> IO ()+mainMaxSAT opt solver args = do+  ret <- case args of+           ["-"]   -> liftM MaxSAT.parseByteString BS.getContents+           [fname] -> MaxSAT.parseFile fname+           _ -> showHelp stderr  >> exitFailure+  case ret of+    Left err -> hPutStrLn stderr err >> exitFailure+    Right wcnf -> do+      let fname = case args of+                    [fname] | or [s `isSuffixOf` map toLower fname | s <- [".cnf", ".wcnf"]] -> Just fname+                    _ -> Nothing+      solveMaxSAT opt solver wcnf fname++solveMaxSAT :: Options -> SAT.Solver -> MaxSAT.WCNF -> Maybe FilePath -> IO ()+solveMaxSAT opt solver wcnf wcnfFileName =+  solveWBO' opt solver True (MaxSAT2WBO.convert wcnf) (wcnf, id, id) wcnfFileName++-- ------------------------------------------------------------------------++mainMIP :: Options -> SAT.Solver -> [String] -> IO ()+mainMIP opt solver args = do+  mip <-+    case args of+      [fname@"-"]   -> do+        F.mapM_ (\s -> hSetEncoding stdin =<< mkTextEncoding s) (optFileEncoding opt)+        s <- hGetContents stdin+        case MIP.parseLPString def fname s of+          Right mip -> return mip+          Left err ->+            case MIP.parseMPSString def fname s of+              Right mip -> return mip+              Left err2 -> do+                hPrint stderr err+                hPrint stderr err2+                exitFailure+      [fname] -> do+        enc <- T.mapM mkTextEncoding (optFileEncoding opt)+        MIP.readFile def{ MIP.optFileEncoding = enc } fname+      _ -> showHelp stderr >> exitFailure+  solveMIP opt solver (fmap toRational mip)++solveMIP :: Options -> SAT.Solver -> MIP.Problem Rational -> IO ()+solveMIP opt solver mip = do+  enc <- Tseitin.newEncoderWithPBLin solver+  Tseitin.setUsePB enc (optLinearizerPB opt)+  pbnlc <- PBNLC.newEncoder solver enc+  ret <- MIP2PB.addMIP pbnlc mip+  case ret of+    Left msg -> do+      putCommentLine msg+      putSLine "UNKNOWN"+      exitFailure+    Right (obj, otrans, mtrans) -> do+      (linObj, linObjOffset) <- Integer.linearize pbnlc obj++      let transformObjVal :: Integer -> Rational+          transformObjVal val = otrans (val + linObjOffset)+  +          printModel :: Map MIP.Var Integer -> IO ()+          printModel m = do+            forM_ (Map.toList m) $ \(v, val) -> do+              printf "v %s = %d\n" (MIP.fromVar v) val+            hFlush stdout+  +          writeSol :: Map MIP.Var Integer -> Rational -> IO ()+          writeSol m val = do+            case optWriteFile opt of+              Nothing -> return ()+              Just fname -> do+                let sol = MIP.Solution+                          { MIP.solStatus = MIP.StatusUnknown+                          , MIP.solObjectiveValue = Just $ Scientific.fromFloatDigits (fromRational val :: Double)+                          , MIP.solVariables = Map.fromList [(v, fromIntegral val) | (v,val) <- Map.toList m]+                          }+                GurobiSol.writeFile fname sol+  +      pbo <- PBO.newOptimizer solver linObj+      setupOptimizer pbo opt+      PBO.setOnUpdateBestSolution pbo $ \_ val -> do+        putOLine $ showRational (optPrintRational opt) (transformObjVal val)+  +      finally (PBO.optimize pbo) $ do+        ret <- PBO.getBestSolution pbo+        case ret of+          Nothing -> do+            b <- PBO.isUnsat pbo+            if b+              then putSLine "UNSATISFIABLE"+              else putSLine "UNKNOWN"+          Just (m,val) -> do+            b <- PBO.isOptimum pbo+            if b+              then putSLine "OPTIMUM FOUND"+              else putSLine "SATISFIABLE"+            let m2   = mtrans m+                val2 = transformObjVal val+            printModel m2+            writeSol m2 val2++-- ------------------------------------------------------------------------++writeSOLFile :: Options -> SAT.Model -> Maybe Integer -> Int -> IO ()+writeSOLFile opt m obj nbvar = do+  case optWriteFile opt of+    Nothing -> return ()+    Just fname -> do+      let sol = MIP.Solution+                { MIP.solStatus = MIP.StatusUnknown+                , MIP.solObjectiveValue = fmap fromIntegral obj+                , MIP.solVariables = Map.fromList [(MIP.toVar ("x" ++ show x), if b then 1.0 else 0.0) | (x,b) <- assocs m, x <= nbvar]+                }+      GurobiSol.writeFile fname sol++durationSecs :: TimeSpec -> TimeSpec -> Double+durationSecs start end = fromIntegral (toNanoSecs (end `diffTimeSpec` start)) / 10^(9::Int)
+ app/toysmt/ToySolver/SMT/SMTLIB2Solver.hs view
@@ -0,0 +1,889 @@+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.SMT.SMTLIB2Solver+-- Copyright   :  (c) Masahiro Sakai 2015+-- License     :  BSD-style+--+-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+-- Portability :  portable+--+-----------------------------------------------------------------------------+module ToySolver.SMT.SMTLIB2Solver+  ( module Smtlib.Syntax.Syntax+  , ShowSL (..)++  -- * The solver type+  , Solver+  , newSolver++  -- * High-level API+  , execCommand+  , execCommandString+  , runCommand+  , runCommandString+  , printResponse++  -- * Individual commands++  -- ** (Re)starting and terminating+  , reset+  , setLogic+  , setOption+  , exit++  -- ** Modifying the assertion stack+  , push+  , pop+  , resetAssertions++  -- ** Introducing new symbols+  , declareSort+  , defineSort+  , declareConst+  , declareFun+  , defineFun+  , defineFunRec+  , defineFunsRec++  -- ** Asserting and inspecting formulas+  , assert+  , getAssertions++  -- ** Checking for satisfiability+  , checkSat+  , checkSatAssuming++  -- ** Inspecting models+  , getValue+  , getAssignment+  , getModel++  -- ** Inspecting proofs+  , getProof+  , getUnsatCore+  , getUnsatAssumptions++  -- ** Inspecting settings+  , getInfo+  , getOption++  -- ** Script information+  , setInfo+  , echo+  ) where++import Control.Applicative+import qualified Control.Exception as E+import Control.Monad+import Data.Interned (unintern)+import Data.Interned.Text+import Data.IORef+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Maybe (catMaybes)+import Data.Ratio+import Data.String+import qualified Data.Text as T+import qualified Data.Version as V+import Numeric (readDec, readFloat, readHex)+import System.Exit+import System.IO+import qualified Text.Parsec as Parsec++import qualified ToySolver.BitVector as BV+import qualified ToySolver.SMT as SMT+import ToySolver.Version+import Smtlib.Syntax.Syntax+import Smtlib.Syntax.ShowSL+import qualified Smtlib.Parsers.CommandsParsers as CommandsParsers++-- ----------------------------------------------------------------------++data Mode+  = ModeStart+  | ModeAssert+  | ModeSat+  | ModeUnsat+  deriving (Eq, Ord, Show)++type EEnv = Map String EEntry+type SortEnv = Map String SortEntry+type Env = (EEnv, SortEnv)++data EEntry+  = EFSymBuiltin InternedText+  | EFSymDeclared SMT.FSym [SMT.Sort] SMT.Sort+  | EExpr SMT.Expr Bool+  | EFunDef EEnv [(String, SMT.Sort)] SMT.Sort Term++data SortEntry+  = SortSym SMT.SSym+  | SortExpr SMT.Sort+  | SortDef SortEnv [String] Sort++interpretSort :: SortEnv -> Sort -> SMT.Sort+interpretSort env s =+  case s of+    SortId ident -> f ident []+    SortIdentifiers ident args -> f ident args+  where+    f ident@(I_Symbol "BitVec" indexes) args+      | not (null args) = E.throw $ SMT.Error (showSL ident ++ ": wrong number of arguments (" ++ show (length args) ++ " for 0)")+      | [IndexNumeral n] <- indexes = SMT.sBitVec n+      | otherwise = E.throw $ SMT.Error ("BitVec: wrong number of indexes (" ++ show (length indexes) ++ " for 1)")+    f ident@(I_Symbol _ _) _ =+      E.throw $ SMT.Error ("unknown sort: " ++ showSL ident)+    f ident@(ISymbol name) args =+      case Map.lookup name env of+        Nothing -> E.throw $ SMT.Error ("unknown sort: " ++ showSL ident)+        Just (SortSym ssym)+          | SMT.ssymArity ssym == length args -> SMT.Sort ssym args'+          | otherwise -> E.throw $ SMT.Error (showSL ident ++ ": wrong number of arguments (" ++ show (length args) ++ " for " ++ show (SMT.ssymArity ssym) ++ ")")+        Just (SortExpr s')+          | null args -> s'+          | otherwise -> E.throw $ SMT.Error (showSL ident ++ ": wrong number of arguments (" ++ show (length args) ++ " for 0)")+        Just (SortDef env' params body) ->+          interpretSort (Map.fromList (zip params (map SortExpr args')) `Map.union` env') body+      where+        args' = map (interpretSort env) args++interpretFun :: Env -> Term -> SMT.Expr+interpretFun (env,senv) t =+  case t of+    TermSpecConstant (SpecConstantNumeral n) -> SMT.EValue $ SMT.ValRational $ fromInteger n+    TermSpecConstant (SpecConstantDecimal s) -> SMT.EValue $ SMT.ValRational $ fst $ head $ readFloat s+    TermSpecConstant (SpecConstantHexadecimal s) -> +      let n = fst $ head $ readHex s+      in SMT.EValue $ SMT.ValBitVec $ BV.nat2bv (length s * 4) n+    TermSpecConstant (SpecConstantBinary s) -> +      SMT.EValue $ SMT.ValBitVec $ BV.fromDescBits [c == '1' | c <- s]+    TermSpecConstant c@(SpecConstantString _s) -> E.throw $ SMT.Error (show c)+    TermQualIdentifier qid -> f qid []+    TermQualIdentifierT  qid args -> f qid args+    TermLet bindings body ->+      interpretFun (Map.fromList [(v, EExpr (interpretFun (env,senv) t2) False) | VB v t2 <- bindings] `Map.union` env, senv) body+    TermForall _bindings _body -> E.throw $ SMT.Error "universal quantifiers are not supported yet"+    TermExists _bindings _body -> E.throw $ SMT.Error "existential quantifiers are not supported yet"+    TermAnnot t2 _ -> interpretFun (env,senv) t2 -- annotations are not supported yet+  where+    unIdentifier :: Identifier -> (String, [Index])+    unIdentifier (ISymbol name) = (name, [])+    unIdentifier (I_Symbol name indexes) = (name, indexes)++    f (QIdentifierAs ident sort) args =+      case ident of+        ISymbol ('@':s) | (n,[]):_ <- reads s ->+          SMT.EValue $ SMT.ValUninterpreted n (interpretSort senv sort)+        _ -> f (QIdentifier ident) args+    f (QIdentifier ident) args+      | ('b':'v':xs, [IndexNumeral n]) <- unIdentifier ident+      , ((x,_):_) <- readDec xs+      , x < 2^n+      = if not (null args)+        then E.throw $ SMT.Error (showSL ident ++ " does not take indexes")+        else SMT.EValue $ SMT.ValBitVec $ BV.nat2bv n x+    f qid@(QIdentifier ident) args =+      case Map.lookup name env of+        Nothing -> E.throw $ SMT.Error ("unknown function symbol: " ++ showSL qid)+        Just (EFSymBuiltin name') ->+          SMT.EAp (SMT.FSym name' indexes') (map (interpretFun (env,senv)) args)+        Just _ | not (null indexes) -> E.throw $ SMT.Error (showSL ident ++ " does not take indexes")+        Just (EExpr e _) -> e+        Just (EFSymDeclared fsym _ _) -> SMT.EAp fsym (map (interpretFun (env,senv)) args)+        Just (EFunDef env' params _y body) ->+          interpretFun (Map.fromList [(p,a) | ((p,_s),a) <- zip params (map (\t -> EExpr (interpretFun (env,senv) t) False) args) ] `Map.union` env', senv) body+      where+        (name, indexes) = unIdentifier ident+        indexes' = map g indexes+        g (IndexNumeral n) = SMT.IndexNumeral (fromIntegral n)+        g (IndexSymbol s) = SMT.IndexSymbol (fromString s)++valueToTerm :: SMT.Value -> Term+valueToTerm (SMT.ValRational v) =+  case v `compare` 0 of+    GT -> f v+    EQ -> TermSpecConstant (SpecConstantNumeral 0)+    LT -> TermQualIdentifierT (QIdentifier $ ISymbol "-") [ f (negate v) ]+  where+    f v = TermQualIdentifierT (QIdentifier $ ISymbol "/")+          [ TermSpecConstant (SpecConstantNumeral (numerator v))+          , TermSpecConstant (SpecConstantNumeral (denominator v))+          ]+valueToTerm (SMT.ValBool b) =+  TermQualIdentifier $ QIdentifier $ ISymbol $ if b then "true" else "false"+valueToTerm (SMT.ValBitVec bv) =+  TermSpecConstant (SpecConstantBinary $ [if b then '1' else '0' | b <- BV.toDescBits bv])+valueToTerm (SMT.ValUninterpreted n s) =+  TermQualIdentifier $ QIdentifierAs (ISymbol $ "@" ++ show n) (sortToSortTerm s)++fsymToIdentifier :: SMT.FSym -> Identifier+fsymToIdentifier (SMT.FSym f indexes) = +  case indexes of+    [] -> ISymbol (T.unpack $ unintern f)+    _ -> I_Symbol (T.unpack $ unintern f) (map g indexes)+  where+    g (SMT.IndexNumeral n) =  IndexNumeral (fromIntegral n)+    g (SMT.IndexSymbol s)  = IndexSymbol (T.unpack $ unintern s)++exprToTerm :: SMT.Expr -> Term+exprToTerm (SMT.EValue v) = valueToTerm v+exprToTerm (SMT.EAp f []) = TermQualIdentifier (QIdentifier (fsymToIdentifier f))+exprToTerm (SMT.EAp f xs) = TermQualIdentifierT (QIdentifier (fsymToIdentifier f)) (map exprToTerm xs)++ssymToSymbol :: SMT.SSym -> Identifier+ssymToSymbol SMT.SSymBool = ISymbol "Bool"+ssymToSymbol SMT.SSymReal = ISymbol "Real"+ssymToSymbol (SMT.SSymBitVec n) = I_Symbol "BitVec" [IndexNumeral n]+ssymToSymbol (SMT.SSymUninterpreted name _) = ISymbol (T.unpack (unintern name))++sortToSortTerm :: SMT.Sort -> Sort+sortToSortTerm (SMT.Sort s []) = SortId (ssymToSymbol s)+sortToSortTerm (SMT.Sort s xs) = SortIdentifiers (ssymToSymbol s) (map sortToSortTerm xs)++-- ----------------------------------------------------------------------++data Solver+  = Solver+  { svSMTSolverRef :: !(IORef SMT.Solver)+  , svEnvRef :: !(IORef Env)+  , svModeRef :: !(IORef Mode)+  , svSavedContextsRef :: !(IORef [(Maybe (EEnv, SortEnv), [Term])])+  , svStatusRef :: IORef (Maybe Bool)+  , svAssertionsRef :: IORef [Term]+  , svRegularOutputChannelRef :: !(IORef (String, Handle))+  , svDiagnosticOutputChannelRef :: !(IORef (String, Handle))+  , svPrintSuccessRef :: !(IORef Bool)+  , svProduceAssertionsRef :: !(IORef Bool)+  , svProduceAssignmentRef :: !(IORef Bool)+  , svProduceModelsRef :: !(IORef Bool)+  , svProduceUnsatAssumptionsRef :: !(IORef Bool)+  , svProduceUnsatCoresRef :: !(IORef Bool)+  , svGlobalDeclarationsRef :: !(IORef Bool)+  , svUnsatAssumptionsRef :: !(IORef [Term])+  }++newSolver :: IO Solver+newSolver = do+  solverRef <- newIORef =<< SMT.newSolver+  envRef <- newIORef initialEnv+  modeRef <- newIORef ModeStart+  savedContextsRef <- newIORef []+  statusRef <- newIORef Nothing+  assertionsRef <- newIORef ([] :: [Term])+  regOutputRef <- newIORef ("stdout", stdout)+  diagOutputRef <- newIORef ("stderr", stderr)+  printSuccessRef <- newIORef True+  produceAssertionsRef <- newIORef False+  produceAssignmentRef <- newIORef False+  produceModelsRef <- newIORef False+  produceUnsatAssumptionsRef <- newIORef False+  produceUnsatCoresRef <- newIORef False  +  globalDeclarationsRef <- newIORef False+  unsatAssumptionsRef <- newIORef undefined+  return $+    Solver+    { svSMTSolverRef = solverRef+    , svEnvRef = envRef+    , svModeRef = modeRef+    , svUnsatAssumptionsRef = unsatAssumptionsRef+    , svSavedContextsRef = savedContextsRef+    , svStatusRef = statusRef+    , svAssertionsRef = assertionsRef+    , svRegularOutputChannelRef = regOutputRef+    , svDiagnosticOutputChannelRef = diagOutputRef+    , svPrintSuccessRef = printSuccessRef+    , svProduceAssertionsRef = produceAssertionsRef+    , svProduceAssignmentRef = produceAssignmentRef+    , svProduceModelsRef = produceModelsRef+    , svProduceUnsatCoresRef = produceUnsatCoresRef+    , svProduceUnsatAssumptionsRef = produceUnsatAssumptionsRef+    , svGlobalDeclarationsRef = globalDeclarationsRef+    }++initialEnv :: Env+initialEnv = (fenv, senv)+  where+    fenv = Map.fromList+      [ (name, EFSymBuiltin (fromString name))+      | name <- ["=", "true", "false", "not", "and", "or", "xor", "ite", "=>", "distinct"+                , "+", "-", "*", "/", ">=", "<=", ">", "<"+                , "extract", "concat", "bvnot", "bvneg"+                , "repeat", "zero_extend", "sign_extend", "rotate_left", "rotate_right"+                , "bvcomp"+                , "bvand", "bvor", "bvxor", "bvnand", "bvnor", "bvxnor"+                , "bvadd", "bvsub", "bvmul", "bvudiv", "bvurem", "bvsdiv", "bvsrem", "bvsmod", "bvshl", "bvlshr", "bvashr"+                , "bvule", "bvult", "bvuge", "bvugt", "bvsle", "bvslt", "bvsge", "bvsgt"+                ]+      ]+    senv = Map.fromList+      [ ("Real", SortSym SMT.SSymReal)+      , ("Bool", SortSym SMT.SSymBool)+      ]++execCommand :: Solver -> Command -> IO ()+execCommand solver cmd = do+  -- putStrLn $ showSL cmd+  printResponse solver =<< runCommand solver cmd++printResponse :: Solver -> CmdResponse -> IO ()+printResponse solver rsp = do+  b <- readIORef (svPrintSuccessRef solver)+  unless (rsp == CmdGenResponse Success && not b) $ do+    (_,h) <- readIORef (svRegularOutputChannelRef solver)+    hPutStrLn h (showSL rsp)++runCommand :: Solver -> Command -> IO CmdResponse+runCommand solver cmd = E.handle h $ do+  case cmd of+    SetLogic logic -> const (CmdGenResponse Success) <$> setLogic solver logic+    SetOption opt -> const (CmdGenResponse Success) <$> setOption solver opt+    GetOption s -> CmdGetOptionResponse <$> getOption solver s+    SetInfo attr -> const (CmdGenResponse Success) <$> setInfo solver attr+    GetInfo flags -> CmdGetInfoResponse <$> getInfo solver flags+    Push n -> const (CmdGenResponse Success) <$> push solver n+    Pop n -> const (CmdGenResponse Success) <$> pop solver n+    DeclareSort name arity -> const (CmdGenResponse Success) <$> declareSort solver name arity+    DefineSort name xs body -> const (CmdGenResponse Success) <$> defineSort solver name xs body+    DeclareConst name y -> const (CmdGenResponse Success) <$> declareConst solver name y+    DeclareFun name xs y -> const (CmdGenResponse Success) <$> declareFun solver name xs y+    DefineFun name xs y body -> const (CmdGenResponse Success) <$> defineFun solver name xs y body+    DefineFunRec name xs y body -> const (CmdGenResponse Success) <$> defineFunRec solver name xs y body+    DefineFunsRec fundecs terms -> const (CmdGenResponse Success) <$> defineFunsRec solver fundecs terms+    Assert tm -> const (CmdGenResponse Success) <$> assert solver tm+    GetAssertions -> CmdGetAssertionsResponse <$> getAssertions solver+    CheckSat -> CmdCheckSatResponse <$> checkSat solver+    CheckSatAssuming ts -> CmdCheckSatResponse <$> checkSatAssuming solver ts+    GetValue ts -> CmdGetValueResponse <$> getValue solver ts+    GetAssignment -> CmdGetAssignmentResponse <$> getAssignment solver+    GetModel -> CmdGetModelResponse <$> getModel solver+    GetProof -> CmdGetProofResponse <$> getProof solver+    GetUnsatCore -> CmdGetUnsatCoreResponse <$> getUnsatCore solver+    GetUnsatAssumptions -> CmdGetUnsatAssumptionsResponse <$> getUnsatAssumptions solver  +    Reset -> const (CmdGenResponse Success) <$> reset solver+    ResetAssertions -> const (CmdGenResponse Success) <$> resetAssertions solver+    Echo s -> CmdEchoResponse <$> echo solver s+    Exit -> const (CmdGenResponse Success) <$> exit solver+  where+    h SMT.Unsupported = return (CmdGenResponse Unsupported)+    h (SMT.Error s) = return $ CmdGenResponse $+     -- GenResponse type uses strings in printed form.+     Error $ "\"" ++ concat [if c == '"' then "\"\"" else [c] | c <- s] ++ "\""++execCommandString :: Solver -> String -> IO ()+execCommandString solver cmd = do+  printResponse solver =<< runCommandString solver cmd++runCommandString :: Solver -> String -> IO CmdResponse+runCommandString solver cmd =+  case Parsec.parse (Parsec.spaces >> CommandsParsers.parseCommand <* Parsec.eof) "" cmd of+    Left err -> +      -- GenResponse type uses strings in printed form.+      return $ CmdGenResponse $ Error $ "\"" ++ concat [if c == '"' then "\"\"" else [c] | c <- show err] ++ "\""+    Right cmd ->+      runCommand solver cmd++-- ----------------------------------------------------------------------++reset :: Solver -> IO GenResponse+reset solver = do+  writeIORef (svSMTSolverRef solver) =<< SMT.newSolver+  writeIORef (svEnvRef solver) initialEnv+  writeIORef (svModeRef solver) ModeStart+  writeIORef (svSavedContextsRef solver) []+  writeIORef (svStatusRef solver) Nothing+  writeIORef (svRegularOutputChannelRef solver) ("stdout",stdout)+  writeIORef (svDiagnosticOutputChannelRef solver) ("stderr",stderr)+  writeIORef (svPrintSuccessRef solver) True+  writeIORef (svProduceAssertionsRef solver) False+  writeIORef (svProduceAssignmentRef solver) False+  writeIORef (svProduceModelsRef solver) False+  writeIORef (svProduceUnsatAssumptionsRef solver) False+  writeIORef (svProduceUnsatCoresRef solver) False+  writeIORef (svUnsatAssumptionsRef solver) undefined+  return Success++setLogic :: Solver -> String -> IO ()+setLogic solver logic = do+  mode <- readIORef (svModeRef solver)+  if mode /= ModeStart then do+    E.throwIO $ SMT.Error "set-logic can only be used in start mode"+  else do+    writeIORef (svModeRef solver) ModeAssert+    case logic of+      "QF_UFLRA" -> return ()+      "QF_UFRDL" -> return ()+      "QF_UF" -> return ()+      "QF_RDL" -> return ()+      "QF_LRA" -> return ()+      "QF_BV" -> return ()+      "QF_UFBV" -> return ()+      "ALL" -> return ()+      "ALL_SUPPORTED" -> return ()+      _ -> E.throwIO SMT.Unsupported++setOption :: Solver -> Option -> IO ()+setOption solver opt = do+  mode <- readIORef (svModeRef solver)+  case opt of+    PrintSuccess b -> do+      writeIORef (svPrintSuccessRef solver) b+    ExpandDefinitions _b -> do+      -- expand-definitions has been removed in SMT-LIB 2.5.+      E.throwIO SMT.Unsupported+    InteractiveMode b -> do+      -- interactive-mode is the old name for produce-assertions. Deprecated.+      unless (mode == ModeStart) $ do+        E.throwIO $ SMT.Error "interactive-mode option can be set only in start mode"+      writeIORef (svProduceAssertionsRef solver) b+      return ()+    ProduceProofs b -> do+      if mode /= ModeStart then+        E.throwIO $ SMT.Error "produce-proofs option can be set only in start mode"+      else if b then+        E.throwIO SMT.Unsupported+      else+        return ()+    ProduceUnsatCores b -> do+      unless (mode == ModeStart) $ do+        E.throwIO $ SMT.Error "produce-unsat-cores option can be set only in start mode"+      writeIORef (svProduceUnsatCoresRef solver) b+      return ()+    ProduceUnsatAssumptions b -> do+      unless (mode == ModeStart) $ do+        E.throwIO $ SMT.Error "produce-unsat-assumptions option can be set only in start mode"+      writeIORef (svProduceUnsatAssumptionsRef solver) b+      return ()+    ProduceModels b -> do+      unless (mode == ModeStart) $ do+        E.throwIO $ SMT.Error "produce-models option can be set only in start mode"+      writeIORef (svProduceModelsRef solver) b+      return ()+    ProduceAssignments b -> do+      unless (mode == ModeStart) $ do+        E.throwIO $ SMT.Error "produce-assignments option can be set only in start mode"+      writeIORef (svProduceAssignmentRef solver) b+      return ()+    ProduceAssertions b -> do+      unless (mode == ModeStart) $ do+        E.throwIO $ SMT.Error "produce-assertions option can be set only in start mode"+      writeIORef (svProduceAssertionsRef solver) b+      return ()+    GlobalDeclarations b -> do+      unless (mode == ModeStart) $ do+        E.throwIO $ SMT.Error "global-declarations option can be set only in start mode"+      writeIORef (svGlobalDeclarationsRef solver) b+      smt <- readIORef (svSMTSolverRef solver)+      SMT.setGlobalDeclarations smt b+    RegularOutputChannel fname -> do+      h <- if fname == "stdout" then+             return stdout+           else+             openFile fname AppendMode+      writeIORef (svRegularOutputChannelRef solver) (fname, h)+      return ()+    DiagnosticOutputChannel fname -> do+      h <- if fname == "stderr" then+             return stderr+           else+             openFile fname AppendMode+      writeIORef (svDiagnosticOutputChannelRef solver) (fname, h)+      return ()+    RandomSeed _i ->+      if mode /= ModeStart then+        E.throwIO $ SMT.Error "random-seed option can be set only in start mode"+      else+        E.throwIO SMT.Unsupported+    Verbosity _lv -> E.throwIO SMT.Unsupported+    ReproducibleResourceLimit _val -> do+      if mode /= ModeStart then+        E.throwIO $ SMT.Error "reproducible-resource-limit option can be set only in start mode"+      else+        E.throwIO SMT.Unsupported+    OptionAttr _attr -> E.throwIO SMT.Unsupported++getOption :: Solver -> String -> IO GetOptionResponse+getOption solver opt =+  case opt of+    ":expand-definitions" -> do+      -- expand-definitions has been removed in SMT-LIB 2.5.+      let b = False+      return $ AttrValueSymbol (showSL b)+    ":global-declarations" -> do+      b <- readIORef (svGlobalDeclarationsRef solver)+      return $ AttrValueSymbol (showSL b)+    ":interactive-mode" -> do+      -- interactive-mode is the old name for produce-assertions. Deprecated.+      b <- readIORef (svProduceAssertionsRef solver)+      return $ AttrValueSymbol (showSL b)+    ":print-success" -> do+      b <- readIORef (svPrintSuccessRef solver)+      return $ AttrValueSymbol (showSL b) +    ":produce-assertions" -> do+      b <- readIORef (svProduceAssertionsRef solver)+      return $ AttrValueSymbol (showSL b)+    ":produce-assignments" -> do+      b <- readIORef (svProduceAssignmentRef solver)+      return $ AttrValueSymbol (showSL b)+    ":produce-models" -> do+      b <- readIORef (svProduceModelsRef solver)+      return $ AttrValueSymbol (showSL b)+    ":produce-proofs" -> do+      let b = False -- default value+      return $ AttrValueSymbol (showSL b)+    ":produce-unsat-cores" -> do+      b <- readIORef (svProduceUnsatCoresRef solver)+      return $ AttrValueSymbol (showSL b)+    ":produce-unsat-assumptions" -> do+      b <- readIORef (svProduceUnsatAssumptionsRef solver)+      return $ AttrValueSymbol (showSL b)+    ":regular-output-channel" -> do+      (fname,_) <- readIORef (svRegularOutputChannelRef solver)+      return $ AttrValueConstant (SpecConstantString fname)+    ":diagnostic-output-channel" -> do+      (fname,_) <- readIORef (svDiagnosticOutputChannelRef solver)+      return $ AttrValueConstant (SpecConstantString fname)+    ":random-seed" -> do+      return $ AttrValueConstant (SpecConstantNumeral 0) -- default value+    ":reproducible-resource-limit" -> do+      return $ AttrValueConstant (SpecConstantNumeral 0) -- default value+    ":verbosity" -> do+      return $ AttrValueConstant (SpecConstantNumeral 0) -- default value+    _ -> do+      E.throwIO SMT.Unsupported++setInfo :: Solver -> Attribute -> IO ()+setInfo solver (AttributeVal ":status" (AttrValueSymbol s)) = do+  v <- case s of+         "sat" -> return $ Just True+         "unsat" -> return $ Just False+         "unknown" -> return $ Nothing+         _ -> E.throwIO $ SMT.Error $ "invalid status value: " ++ s+  writeIORef (svStatusRef solver) v+setInfo _solver _ = return ()++getInfo :: Solver -> InfoFlags -> IO GetInfoResponse+getInfo solver flags = do+  mode <- readIORef (svModeRef solver)+  case flags of+    ErrorBehavior -> return [ResponseErrorBehavior ContinuedExecution]+    Name -> return [ResponseName "toysmt"]+    Authors -> return [ResponseName "Masahiro Sakai"]+    Version -> return [ResponseVersion (V.showVersion version)]+    Status -> E.throwIO SMT.Unsupported+    ReasonUnknown -> do+      if mode /= ModeSat then+        E.throwIO $ SMT.Error "Executions of get-info with :reason-unknown are allowed only when the solver is in sat mode following a check command whose response was unknown."+      else+        return [ResponseReasonUnknown Incomplete]+    AllStatistics -> do+      if not (mode == ModeSat || mode == ModeUnsat) then+        E.throwIO $ SMT.Error "Executions of get-info with :all-statistics are allowed only when the solver is in sat or unsat mode."+      else+        E.throwIO SMT.Unsupported+    AssertionStackLevels -> do+      saved <- readIORef (svSavedContextsRef solver)+      let n = length saved+      n `seq` return [ResponseAssertionStackLevels n]+    InfoFlags _s -> do+      E.throwIO SMT.Unsupported++push :: Solver -> Int -> IO ()+push solver n = do+  replicateM_ n $ do+    (env,senv) <- readIORef (svEnvRef solver)+    assertions <- readIORef (svAssertionsRef solver)+    globalDeclarations <- readIORef (svGlobalDeclarationsRef solver)+    if globalDeclarations then+      modifyIORef (svSavedContextsRef solver) ((Nothing, assertions) :)+    else+      modifyIORef (svSavedContextsRef solver) ((Just (env,senv), assertions) :)+    SMT.push =<< readIORef (svSMTSolverRef solver)+    writeIORef (svModeRef solver) ModeAssert++pop :: Solver -> Int -> IO ()+pop solver n = do+  replicateM_ n $ do+    cs <- readIORef (svSavedContextsRef solver)+    case cs of+      [] -> E.throwIO $ SMT.Error "pop from empty context"+      ((m,assertions) : cs) -> do+        case m of+          Just (env,senv) -> writeIORef (svEnvRef solver) (env,senv)+          Nothing -> return ()+        writeIORef (svAssertionsRef solver) assertions+        writeIORef (svSavedContextsRef solver) cs+        SMT.pop =<< readIORef (svSMTSolverRef solver)+        writeIORef (svModeRef solver) ModeAssert++resetAssertions :: Solver -> IO ()+resetAssertions solver = do+  cs <- readIORef (svSavedContextsRef solver)+  pop solver (length cs)++echo :: Solver -> String -> IO String+echo _solver s = return s++declareSort :: Solver -> String -> Int -> IO ()+declareSort solver name arity = do+  smt <- readIORef (svSMTSolverRef solver)+  s <- SMT.declareSSym smt name arity+  insertSort solver name (SortSym s)+  writeIORef (svModeRef solver) ModeAssert++defineSort :: Solver -> String -> [String] -> Sort -> IO ()+defineSort solver name xs body = do+  (_, senv) <- readIORef (svEnvRef solver)+  insertSort solver name (SortDef senv xs body)+  writeIORef (svModeRef solver) ModeAssert++declareConst :: Solver -> String -> Sort -> IO ()+declareConst solver name y = declareFun solver name [] y++declareFun :: Solver -> String -> [Sort] -> Sort -> IO ()+declareFun solver name xs y = do+  smt <- readIORef (svSMTSolverRef solver)+  (_, senv) <- readIORef (svEnvRef solver)+  let argsSorts = map (interpretSort senv) xs+      resultSort = interpretSort senv y+  f <- SMT.declareFSym smt name argsSorts resultSort+  insertFun solver name (EFSymDeclared f argsSorts resultSort)+  writeIORef (svModeRef solver) ModeAssert++defineFun :: Solver -> String -> [SortedVar] -> Sort -> Term -> IO ()+defineFun solver name xs y body = do+  writeIORef (svModeRef solver) ModeAssert+  (_, senv) <- readIORef (svEnvRef solver)+  let xs' = map (\(SV x s) -> (x, interpretSort senv s)) xs+      y'  = interpretSort senv y+  if null xs' then do+    body' <- processNamed solver body+    (fenv, _) <- readIORef (svEnvRef solver)+    -- use EExpr?+    insertFun solver name (EFunDef fenv [] y' body')+  else do+    (fenv, _) <- readIORef (svEnvRef solver)+    insertFun solver name (EFunDef fenv xs' y' body)+  writeIORef (svModeRef solver) ModeAssert++defineFunRec :: Solver -> String -> [SortedVar] -> Sort -> Term -> IO ()+defineFunRec _solver _name _xs _y _body = do+  E.throwIO SMT.Unsupported++defineFunsRec :: Solver -> [FunDec] -> [Term] -> IO ()+defineFunsRec _solver _fundecs _terms = do+  E.throwIO SMT.Unsupported++assert :: Solver -> Term -> IO ()+assert solver tm = do+  let mname =+        case tm of+          TermAnnot _body attrs+            | name:_ <- [name | AttributeVal ":named" (AttrValueSymbol name) <- attrs] ->+                Just name+          _ -> Nothing+  tm' <- processNamed solver tm+  smt <- readIORef (svSMTSolverRef solver)+  env <- readIORef (svEnvRef solver)+  case mname of+    Nothing -> SMT.assert smt (interpretFun env tm')+    Just name -> SMT.assertNamed smt name (interpretFun env tm')+  do b <- readIORef (svProduceAssertionsRef solver)+     when b $ modifyIORef (svAssertionsRef solver) (tm :)+  writeIORef (svModeRef solver) ModeAssert++getAssertions :: Solver -> IO GetAssertionsResponse+getAssertions solver = do+  mode <- readIORef (svModeRef solver)+  when (mode == ModeStart) $ do+    E.throwIO $ SMT.Error "get-assertions cannot be used in start mode"+  b <- readIORef (svProduceAssertionsRef solver)+  unless b $ do+    E.throwIO $ SMT.Error ":produce-assertions is not enabled"+  reverse <$> readIORef (svAssertionsRef solver)++checkSat :: Solver -> IO CheckSatResponse+checkSat solver = checkSatAssuming solver []++checkSatAssuming :: Solver -> [Term] -> IO CheckSatResponse+checkSatAssuming solver xs = do+  smt <- readIORef (svSMTSolverRef solver)++  env <- readIORef (svEnvRef solver)+  ref <- newIORef Map.empty+  ys <- forM xs $ \x -> do+    let y = interpretFun env x+    modifyIORef ref (Map.insert y x)+    return y++  ret <- SMT.checkSATAssuming smt ys++  do expected <- readIORef (svStatusRef solver)+     writeIORef (svStatusRef solver) Nothing -- I'm not sure if we should reset or not.+     h <- snd <$> readIORef (svDiagnosticOutputChannelRef solver)+     case expected of+       Just True | not ret -> hPutStrLn h "WARNING: unexpected unsat; expecting sat"+       Just False | ret -> hPutStrLn h "WARNING: unexpected sat; expecting unsat"+       _ -> return ()+     hFlush h++  if ret then do+    writeIORef (svModeRef solver) ModeSat+    return Sat+  else do+    writeIORef (svModeRef solver) ModeUnsat+    m <- readIORef ref+    es <- SMT.getUnsatAssumptions smt+    writeIORef (svUnsatAssumptionsRef solver) [m Map.! e | e <- es]+    return Unsat++getValue :: Solver -> [Term] -> IO GetValueResponse+getValue solver ts = do+  ts <- mapM (processNamed solver) ts  +  mode <- readIORef (svModeRef solver)+  unless (mode == ModeSat) $ do+    E.throwIO $ SMT.Error "get-value can only be used in sat mode"+  smt <- readIORef (svSMTSolverRef solver)+  m <- SMT.getModel smt+  env <- readIORef (svEnvRef solver)+  forM ts $ \t -> do+    let e = interpretFun env t+    let v = SMT.eval m e+    return $ ValuationPair t (valueToTerm v)++getAssignment :: Solver -> IO GetAssignmentResponse+getAssignment solver = do+  mode <- readIORef (svModeRef solver)+  unless (mode == ModeSat) $ do+    E.throwIO $ SMT.Error "get-assignment can only be used in sat mode"+  smt <- readIORef (svSMTSolverRef solver)+  m <- SMT.getModel smt+  (env, _) <- readIORef (svEnvRef solver)+  liftM concat $ forM (Map.toList env) $ \(name, entry) -> do+    case entry of+      EExpr e True -> do+        s <- SMT.exprSort smt e+        if s /= SMT.sBool then do+          return []+        else do+          let v = SMT.eval m e+          case v of+            (SMT.ValBool b) -> return [TValuationPair name b]+            _ -> E.throwIO $ SMT.Error "get-assignment: should not happen"+      _ -> return []++getModel :: Solver -> IO GetModelResponse+getModel solver = do+  mode <- readIORef (svModeRef solver)+  unless (mode == ModeSat) $ do+    E.throwIO $ SMT.Error "get-model can only be used in sat mode"+  smt <- readIORef (svSMTSolverRef solver)+  m <- SMT.getModel smt+  (env, _) <- readIORef (svEnvRef solver)+  defs <- liftM catMaybes $ forM (Map.toList env) $ \(name, entry) -> do+    case entry of+      EFSymDeclared sym argsSorts resultSort -> do+        case SMT.evalFSym m sym of+          SMT.FunDef [] val ->  do -- constant+            return $ Just $ DefineFun name [] (sortToSortTerm resultSort) (valueToTerm val)+          SMT.FunDef tbl defaultVal -> do -- proper function+            let argsSV :: [SortedVar]+                argsSV = [SV ("x!" ++ show i) (sortToSortTerm s) | (i,s) <- zip [(1::Int)..] argsSorts]+                args :: [Term]+                args = [TermQualIdentifier (QIdentifier (ISymbol x)) | SV x _ <- argsSV]+                f :: ([SMT.Value], SMT.Value) -> Term -> Term+                f (vals,val) tm = +                  TermQualIdentifierT (QIdentifier (ISymbol "ite")) [cond, valueToTerm val, tm]+                  where+                    cond =+                      case zipWith (\arg val -> TermQualIdentifierT (QIdentifier (ISymbol "=")) [arg, valueToTerm val]) args vals of+                        [c] -> c+                        cs -> TermQualIdentifierT (QIdentifier (ISymbol "and")) cs+            return $ Just $ DefineFun name argsSV (sortToSortTerm resultSort) $+              foldr f (valueToTerm defaultVal) tbl+      _ -> return Nothing+  return $ defs ++ [Assert (exprToTerm x) | x <- SMT.modelGetAssertions m]++getProof :: Solver -> IO GetProofResponse+getProof solver = do+  mode <- readIORef (svModeRef solver)+  if mode /= ModeUnsat then+    E.throwIO $ SMT.Error "get-proof can only be used in unsat mode"+  else+    E.throwIO SMT.Unsupported++getUnsatCore :: Solver -> IO GetUnsatCoreResponse+getUnsatCore solver = do+  smt <- readIORef (svSMTSolverRef solver)+  mode <- readIORef (svModeRef solver)+  unless (mode == ModeUnsat) $ do+    E.throwIO $ SMT.Error "get-unsat-core can only be used in unsat mode"+  SMT.getUnsatCore smt++getUnsatAssumptions :: Solver -> IO [Term]+getUnsatAssumptions solver = do+  mode <- readIORef (svModeRef solver)+  unless (mode == ModeUnsat) $ do+    E.throwIO $ SMT.Error "get-unsat-assumptions can only be used in unsat mode"+  readIORef (svUnsatAssumptionsRef solver)++exit :: Solver -> IO ()+exit _solver = exitSuccess++-- ----------------------------------------------------------------------++insertSort :: Solver -> String -> SortEntry -> IO ()+insertSort solver name sdef = do+  (fenv, senv) <- readIORef (svEnvRef solver)+  case Map.lookup name senv of+    Nothing -> writeIORef (svEnvRef solver) (fenv, Map.insert name sdef senv)+    Just _ -> E.throwIO $ SMT.Error (name ++ " is already used")++insertFun :: Solver -> String -> EEntry -> IO ()+insertFun solver name fdef = do+  (fenv, senv) <- readIORef (svEnvRef solver)+  case Map.lookup name fenv of+    Nothing -> writeIORef (svEnvRef solver) (Map.insert name fdef fenv, senv)+    Just _ -> E.throwIO $ SMT.Error (name ++ " is already used")++-- TODO: check closedness of terms+processNamed :: Solver -> Term -> IO Term+processNamed solver = f+  where+    f t@(TermSpecConstant _) = return t+    f t@(TermQualIdentifier _) = return t+    f (TermQualIdentifierT qid args) = do+      args' <- mapM f args+      return $ TermQualIdentifierT qid args'+    f (TermLet bindings body) = do+      body' <- f body+      return $ TermLet bindings body'+    f (TermForall bindings body) = do+      body' <- f body+      return $ TermForall bindings body'+    f (TermExists bindings body) = do+      body' <- f body+      return $ TermExists bindings body'+    f (TermAnnot body attrs) = do+      body' <- f body+      forM_ attrs $ \attr -> do+        case attr of+          AttributeVal ":named" val ->+            case val of+              AttrValueSymbol name -> do+                env <- readIORef (svEnvRef solver)+                let e = interpretFun env body'+                -- smt <- readIORef (svSMTSolverRef solver)+                -- s <- SMT.exprSort smt e+                insertFun solver name (EExpr e True)+              _ -> E.throwIO $ SMT.Error ":named attribute value should be a symbol"+          _ -> return ()+      let attrs' = [attr | attr <- attrs, attrName attr /= ":named"]+            where+              attrName (Attribute s) = s+              attrName (AttributeVal s _v) = s+      if null attrs' then+        return body'+      else+        return $ TermAnnot body' attrs'
+ app/toysmt/toysmt.hs view
@@ -0,0 +1,148 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE CPP #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  toysmt+-- Copyright   :  (c) Masahiro Sakai 2015+-- License     :  BSD-style+--+-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+-- Portability :  non-portable (CPP)+--+-----------------------------------------------------------------------------+module Main where++import Control.Applicative ((<*))+import Control.Monad+import Control.Monad.Trans+import Data.Default.Class+import Data.Version+import System.Console.GetOpt+#ifdef USE_HASKELINE_PACKAGE+import qualified System.Console.Haskeline as Haskeline+#endif+import System.Environment+import System.Exit+import System.IO+import Text.Parsec+import Text.Parsec.String++import Smtlib.Parsers.CommandsParsers++import ToySolver.Version+import ToySolver.SMT.SMTLIB2Solver+import ToySolver.Internal.Util (setEncodingChar8)++data Mode+  = ModeHelp+  | ModeVersion+  | ModeInteractive+  deriving (Eq, Ord, Bounded, Enum)++data Options+  = Options+  { optMode :: Maybe Mode+  , optInteractive :: Bool+  }++instance Default Options where+  def =+    Options+    { optMode = Nothing+    , optInteractive = False +    }++options :: [OptDescr (Options -> Options)]+options =+    [ Option ['h'] ["help"]   (NoArg (\opt -> opt{ optMode = Just ModeHelp   })) "show help"+    , Option [] ["version"]   (NoArg (\opt -> opt{ optMode = Just ModeVersion})) "show version"+    , Option [] ["interactive"] (NoArg (\opt -> opt{ optMode = Just ModeInteractive })) "force interactive mode"+    ]++main :: IO ()+main = do+#ifdef FORCE_CHAR8+  setEncodingChar8+#endif++  args <- getArgs+  case getOpt Permute options args of+    (_,_,errs@(_:_)) -> do+      mapM_ putStrLn errs+      exitFailure++    (o,args2,[]) -> do+      let opt = foldl (flip id) def o+      case optMode opt of+        Just ModeHelp -> showHelp stdout+        Just ModeVersion -> hPutStrLn stdout (showVersion version)+        Just ModeInteractive -> do+          solver <- newSolver+          mapM_ (loadFile solver) args2+          repl solver          +        Nothing -> do+          solver <- newSolver+          if null args2 then+            repl solver+          else+            mapM_ (loadFile solver) args2++loadFile :: Solver -> FilePath -> IO ()+loadFile solver fname = do+  ret <- parseFromFile (parseSource <* eof) fname+  case ret of+    Left err -> do+      hPrint stderr err+      exitFailure+    Right source -> do+      forM_ source $ \cmd -> do+        execCommand solver cmd++repl :: Solver -> IO ()+repl solver = do+#ifdef USE_HASKELINE_PACKAGE+  replHaskeline solver+#else+  replSimple solver+#endif++replSimple :: Solver -> IO ()+replSimple solver = do+  hSetBuffering stdin LineBuffering+  forever $ do+    putStr "toysmt> "+    hFlush stdout+    s <- getLine+    case parse (spaces >> parseCommand <* eof) "<stdin>" s of+      Left err -> do+        hPrint stderr err+      Right cmd -> do+        execCommand solver cmd++#ifdef USE_HASKELINE_PACKAGE++replHaskeline :: Solver -> IO ()+replHaskeline solver = Haskeline.runInputT Haskeline.defaultSettings $ forever $ do+  m <- Haskeline.getInputLine "toysmt> "+  case m of+    Nothing -> return ()+    Just s -> do+      case parse (spaces >> parseCommand) "<stdin>" s of+        Left err -> do+          lift $ hPrint stderr err+        Right cmd -> do+          lift $ execCommand solver cmd++#endif++showHelp :: Handle -> IO ()+showHelp h = hPutStrLn h (usageInfo header options)++header :: String+header = unlines+  [ "Usage:"+  , "  toysmt [OPTION]... [file.smt2]"+  , ""+  , "Options:"+  ]
+ app/toysolver.hs view
@@ -0,0 +1,491 @@+{-# LANGUAGE CPP #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  toysolver+-- Copyright   :  (c) Masahiro Sakai 2011-2014+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+-- Portability :  portable+--+-----------------------------------------------------------------------------+++module Main where++import Control.Monad+import Control.Concurrent+import Data.Array.IArray+import Data.Char+import Data.Default.Class+import Data.List+import Data.Maybe+import Data.Ratio+import Data.Scientific (Scientific)+import qualified Data.Scientific as Scientific+import Data.String+import qualified Data.Version as V+import qualified Data.Set as Set+import Data.Map (Map)+import qualified Data.Map as Map+import qualified Data.IntMap as IntMap+import qualified Data.IntSet as IntSet+import qualified Data.Traversable as T+import System.Exit+import System.Environment+import System.FilePath+import System.Console.GetOpt+import System.IO+import Text.Printf+import GHC.Conc (getNumProcessors, setNumCapabilities)++import Data.OptDir+import qualified Data.PseudoBoolean as PBFile+import qualified Data.PseudoBoolean.Attoparsec as PBFileAttoparsec++import ToySolver.Data.OrdRel+import ToySolver.Data.FOL.Arith as FOL+import qualified ToySolver.Data.LA as LA+import qualified ToySolver.Data.LA.FOL as LAFOL+import qualified ToySolver.Data.Polynomial as P+import qualified ToySolver.Data.AlgebraicNumber.Real as AReal+import qualified ToySolver.Data.MIP as MIP+import qualified ToySolver.Data.MIP.Solution.Gurobi as GurobiSol+import qualified ToySolver.Arith.OmegaTest as OmegaTest+import qualified ToySolver.Arith.Cooper as Cooper+import qualified ToySolver.Arith.Simplex.Textbook.MIPSolver.Simple as TextbookMIP+import qualified ToySolver.Arith.Simplex as Simplex+import qualified ToySolver.Arith.MIP as MIPSolver+import qualified ToySolver.Arith.CAD as CAD+import qualified ToySolver.Arith.ContiTraverso as ContiTraverso+import qualified ToySolver.Text.CNF as CNF+import qualified ToySolver.Text.MaxSAT as MaxSAT+import qualified ToySolver.Converter.SAT2IP as SAT2IP+import qualified ToySolver.Converter.PB2IP as PB2IP+import qualified ToySolver.Converter.MaxSAT2IP as MaxSAT2IP+import ToySolver.SAT.Printer+import qualified ToySolver.SAT.Types as SAT+import ToySolver.Version+import ToySolver.Internal.Util++-- ---------------------------------------------------------------------------++data Mode = ModeSAT | ModePB | ModeWBO | ModeMaxSAT | ModeMIP+  deriving (Eq, Ord)++data Flag+    = Help+    | Version+    | Solver String+    | PrintRational+    | WriteFile !FilePath+    | NoMIP+    | PivotStrategy String+    | NThread !Int+    | OmegaReal String+    | Mode !Mode+    | FileEncoding String+    deriving Eq++options :: [OptDescr Flag]+options =+    [ Option ['h'] ["help"]    (NoArg Help)            "show help"+    , Option ['v'] ["version"] (NoArg Version)         "show version number"+    , Option [] ["solver"] (ReqArg Solver "SOLVER")    "mip (default), omega-test, cooper, cad, old-mip, ct"+    , 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 [] ["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), virtual-substitution (or vs), cad, simplex, none"++    , Option []    ["sat"]    (NoArg (Mode ModeSAT))    "solve boolean satisfiability problem in .cnf file"+    , Option []    ["pb"]     (NoArg (Mode ModePB))     "solve pseudo boolean problem in .opb file"+    , Option []    ["wbo"]    (NoArg (Mode ModeWBO))    "solve weighted boolean optimization problem in .wbo file"+    , Option []    ["maxsat"] (NoArg (Mode ModeMaxSAT)) "solve MaxSAT problem in .cnf or .wcnf file"+    , Option []    ["lp"]     (NoArg (Mode ModeMIP))    "solve LP/MIP problem in .lp or .mps file (default)"++    , Option [] ["nomip"] (NoArg NoMIP)                 "consider all integer variables as continuous"++    , Option [] ["encoding"] (ReqArg FileEncoding "<ENCODING>") "file encoding for LP/MPS files"+    ]++header :: String+header = "Usage: toysolver [OPTION]... file"++-- ---------------------------------------------------------------------------++run+  :: String+  -> [Flag]+  -> MIP.Problem Rational+  -> (Map MIP.Var Rational -> IO ())+  -> IO ()+run solver opt mip printModel = do+  unless (Set.null (MIP.semiContinuousVariables mip)) $ do+    hPutStrLn stderr "semi-continuous variables are not supported."+    exitFailure  +  case map toLower solver of+    s | s `elem` ["omega", "omega-test", "cooper"] -> solveByQE+    s | s `elem` ["old-mip"] -> solveByMIP+    s | s `elem` ["cad"] -> solveByCAD+    s | s `elem` ["ct", "conti-traverso"] -> solveByContiTraverso+    _ -> solveByMIP2+  where+    vs = MIP.variables mip+    vsAssoc = zip (Set.toList vs) [0..]+    nameToVar = Map.fromList vsAssoc+    varToName = IntMap.fromList [(v,name) | (name,v) <- vsAssoc]++    compileE :: MIP.Expr Rational -> Expr Rational+    compileE = foldr (+) (Const 0) . map compileT . MIP.terms++    compileT :: MIP.Term Rational -> Expr Rational+    compileT (MIP.Term c vs) =+      foldr (*) (Const c) [Var (nameToVar Map.! v) | v <- vs]++    obj = compileE $ MIP.objExpr $ MIP.objectiveFunction mip++    cs1 = do+      v <- Set.toList vs+      let v2 = Var (nameToVar Map.! v)+      let (l,u) = MIP.getBounds mip v+      [Const x .<=. v2 | MIP.Finite x <- return l] +++        [v2 .<=. Const x | MIP.Finite x <- return u]+    cs2 = do+      MIP.Constraint+        { MIP.constrIndicator = ind+        , MIP.constrExpr = e+        , MIP.constrLB = lb+        , MIP.constrUB = ub+        } <- MIP.constraints mip+      case ind of+        Nothing -> do+          let e2 = compileE e+          msum+            [ case lb of+                MIP.NegInf -> []+                MIP.PosInf -> [OrdRel 1 Le 0] -- False+                MIP.Finite x -> [OrdRel e2 Ge (Const x)]+            , case ub of+                MIP.NegInf -> [OrdRel 1 Le 0] -- False+                MIP.PosInf -> []+                MIP.Finite x -> [OrdRel e2 Le (Const x)]+            ]+        Just _ -> error "indicator constraint is not supported yet"++    ivs+      | NoMIP `elem` opt = Set.empty+      | otherwise        = MIP.integerVariables mip++    vs2  = IntMap.keysSet varToName+    ivs2 = IntSet.fromList . map (nameToVar Map.!) . Set.toList $ ivs++    solveByQE =+      case mapM LAFOL.fromFOLAtom (cs1 ++ cs2) of+        Nothing -> do+          putSLine "UNKNOWN"+          exitFailure+        Just cs ->+          case f vs2 cs ivs2 of+            Nothing -> do+              putSLine "UNSATISFIABLE"+              exitFailure+            Just m -> do+              putOLine $ showValue (FOL.evalExpr m obj)+              putSLine "SATISFIABLE"+              let m2 = Map.fromAscList [(v, m IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs]+              printModel m2+       where+         f = case solver of+               "omega"      -> OmegaTest.solveQFLIRAConj omegaOpt+               "omega-test" -> OmegaTest.solveQFLIRAConj omegaOpt+               "cooper"     -> Cooper.solveQFLIRAConj+               _ -> error "unknown solver"++         omegaOpt =+           def+           { OmegaTest.optCheckReal = realSolver+           }         +           where+             realSolver =+               case last ("fourier-motzkin" : [s | OmegaReal s <- opt]) of+                 "fourier-motzkin" -> OmegaTest.checkRealByFM+                 "virtual-substitution" -> OmegaTest.checkRealByVS+                 "vs"              -> OmegaTest.checkRealByVS+                 "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+          putSLine "UNKNOWN"+          exitFailure+        Just (cs',obj') ->+          case TextbookMIP.optimize (MIP.objDir $ MIP.objectiveFunction mip) obj' cs' ivs2 of+            TextbookMIP.OptUnsat -> do+              putSLine "UNSATISFIABLE"+              exitFailure+            TextbookMIP.Unbounded -> do+              putSLine "UNBOUNDED"+              exitFailure+            TextbookMIP.Optimum r m -> do+              putOLine $ showValue r+              putSLine "OPTIMUM FOUND"+              let m2 = Map.fromAscList [(v, m IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs]+              printModel m2++    solveByMIP2 = do+      solver <- Simplex.newSolver++      let ps = last ("bland-rule" : [s | PivotStrategy s <- opt])+      case ps of+        "bland-rule"          -> Simplex.setPivotStrategy solver Simplex.PivotStrategyBlandRule+        "largest-coefficient" -> Simplex.setPivotStrategy solver Simplex.PivotStrategyLargestCoefficient+        _ -> error ("unknown pivot strategy \"" ++ ps ++ "\"")++      let nthreads = last (0 : [n | NThread n <- opt])++      Simplex.setLogger solver putCommentLine+      Simplex.enableTimeRecording solver+      replicateM (length vsAssoc) (Simplex.newVar solver) -- XXX+      Simplex.setOptDir solver $ MIP.objDir $ MIP.objectiveFunction mip+      Simplex.setObj solver $ fromJust (LAFOL.fromFOLExpr obj)+      putCommentLine "Loading constraints... "+      forM_ (cs1 ++ cs2) $ \c -> do+        Simplex.assertAtom solver $ fromJust (LAFOL.fromFOLAtom c)+      putCommentLine "Loading constraints finished"++      mip <- MIPSolver.newSolver solver ivs2+      MIPSolver.setShowRational mip printRat+      MIPSolver.setLogger mip putCommentLine+      MIPSolver.setOnUpdateBestSolution mip $ \m val -> putOLine (showValue val)++      procs <-+        if nthreads >= 1+        then return nthreads+        else do+          ncap  <- getNumCapabilities+          procs <- getNumProcessors+          return $ max (procs - 1) ncap+      setNumCapabilities procs+      MIPSolver.setNThread mip procs++      ret <- MIPSolver.optimize mip+      case ret of+        Simplex.Unsat -> do+          putSLine "UNSATISFIABLE"+          exitFailure+        Simplex.Unbounded -> do+          putSLine "UNBOUNDED"+          Just m <- MIPSolver.getBestModel mip+          let m2 = Map.fromAscList [(v, m IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs]+          printModel m2+          exitFailure+        Simplex.Optimum -> do+          Just m <- MIPSolver.getBestModel mip+          putSLine "OPTIMUM FOUND"+          let m2 = Map.fromAscList [(v, m IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs]+          printModel m2++    solveByCAD+      | not (IntSet.null ivs2) = do+          putSLine "UNKNOWN"+          putCommentLine "integer variables are not supported by CAD"+          exitFailure+      | otherwise = do+          let cs = map (fmap f) $ cs1 ++ cs2+              vs3 = Set.fromAscList $ IntSet.toAscList vs2+          case CAD.solve vs3 cs of+            Nothing -> do+              putSLine "UNSATISFIABLE"+              exitFailure+            Just m -> do+              let m2 = IntMap.map (\x -> AReal.approx x (2^^(-64::Int))) $+                         IntMap.fromAscList $ Map.toAscList $ m+              putOLine $ showValue (FOL.evalExpr m2 obj)+              putSLine "SATISFIABLE"+              let m3 = Map.fromAscList [(v, m2 IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs]+              printModel m3+      where+        f (Const r)   = P.constant r+        f (Var v)     = P.var v+        f (e1 :+: e2) = f e1 + f e2+        f (e1 :*: e2) = f e1 * f e2+        f (e1 :/: e2)+          | P.deg p > 0 = error "can't handle rational expression"+          | otherwise   = P.mapCoeff (/ c) $ f e1 +          where+            p = f e2+            c = P.coeff P.mone p++    solveByContiTraverso+      | not (vs `Set.isSubsetOf` ivs) = do+          putSLine "UNKNOWN"+          putCommentLine "continuous variables are not supported by Conti-Traverso algorithm"+          exitFailure+      | otherwise = do+          let tmp = do+                linObj <- LAFOL.fromFOLExpr obj+                linCon <- mapM LAFOL.fromFOLAtom (cs1 ++ cs2)+                return (linObj, linCon)+          case tmp of+            Nothing -> do+              putSLine "UNKNOWN"+              putCommentLine "non-linear expressions are not supported by Conti-Traverso algorithm"+              exitFailure+            Just (linObj, linCon) -> do+              case ContiTraverso.solve P.grlex vs2 (MIP.objDir $ MIP.objectiveFunction mip) linObj linCon of+                Nothing -> do+                  putSLine "UNSATISFIABLE"+                  exitFailure+                Just m -> do+                  let m2 = IntMap.map fromInteger m+                  putOLine $ showValue (FOL.evalExpr m2 obj)+                  putSLine "OPTIMUM FOUND"+                  let m3 = Map.fromAscList [(v, m2 IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs]+                  printModel m3++    printRat :: Bool+    printRat = PrintRational `elem` opt++    showValue :: Rational -> String+    showValue = showRational printRat++mipPrintModel :: Handle -> Bool -> Map MIP.Var Rational -> IO ()+mipPrintModel h asRat m = do+  forM_ (Map.toList m) $ \(v, val) -> do+    printf "v %s = %s\n" (MIP.fromVar v) (showRational asRat val)+++putCommentLine :: String -> IO ()+putCommentLine s = do+  putStr "c "+  putStrLn s+  hFlush stdout++putSLine :: String -> IO ()+putSLine  s = do+  putStr "s "+  putStrLn s+  hFlush stdout++putOLine :: String -> IO ()+putOLine  s = do+  putStr "o "+  putStrLn s+  hFlush stdout++-- ---------------------------------------------------------------------------++getSolver :: [Flag] -> String+getSolver xs = last $ "mip" : [s | Solver s <- xs]++main :: IO ()+main = do+#ifdef FORCE_CHAR8+  setEncodingChar8+#endif++  args <- getArgs+  case getOpt Permute options args of+    (o,_,[])+      | Help `elem` o    -> putStrLn (usageInfo header options)+      | Version `elem` o -> putStrLn (V.showVersion version)+    (o,[fname],[]) -> do++      let mode =+            case reverse [m | Mode m <- o] of+              m:_ -> m+              [] ->+                case map toLower (takeExtension fname) of+                  ".cnf"  -> ModeSAT+                  ".opb"  -> ModePB+                  ".wbo"  -> ModeWBO+                  ".wcnf" -> ModeMaxSAT+                  ".lp"   -> ModeMIP+                  ".mps"  -> ModeMIP+                  _ -> ModeMIP++      case mode of+        ModeSAT -> do+          ret <- CNF.parseFile fname+          case ret of+            Left err -> hPrint stderr err >> exitFailure+            Right cnf -> do+              let (mip,_,mtrans) = SAT2IP.convert cnf+              run (getSolver o) o (fmap fromInteger mip) $ \m -> do+                let m2 = mtrans m+                satPrintModel stdout m2 0+                writeSOLFileSAT o m2+        ModePB -> do+          ret <- PBFileAttoparsec.parseOPBFile fname+          case ret of+            Left err -> hPutStrLn stderr err >> exitFailure+            Right pb -> do+              let (mip,_,mtrans) = PB2IP.convert pb+              run (getSolver o) o (fmap fromInteger mip) $ \m -> do+                let m2 = mtrans m+                pbPrintModel stdout m2 0+                writeSOLFileSAT o m2+        ModeWBO -> do+          ret <- PBFileAttoparsec.parseWBOFile fname+          case ret of+            Left err -> hPutStrLn stderr err >> exitFailure+            Right wbo -> do+              let (mip,_,mtrans) = PB2IP.convertWBO False wbo+              run (getSolver o) o (fmap fromInteger mip) $ \m -> do+                let m2 = mtrans m+                pbPrintModel stdout m2 0+                writeSOLFileSAT o m2+        ModeMaxSAT -> do+          ret <- MaxSAT.parseFile fname+          case ret of+            Left err -> hPutStrLn stderr err >> exitFailure+            Right wcnf -> do+              let (mip,_,mtrans) = MaxSAT2IP.convert False wcnf+              run (getSolver o) o (fmap fromInteger mip) $ \m -> do+                let m2 = mtrans m+                maxsatPrintModel stdout m2 0+                writeSOLFileSAT o m2+        ModeMIP -> do+          enc <- T.mapM mkTextEncoding $ last $ Nothing : [Just s | FileEncoding s <- o]+          mip <- MIP.readFile def{ MIP.optFileEncoding = enc } fname+          run (getSolver o) o (fmap toRational mip) $ \m -> do+            mipPrintModel stdout (PrintRational `elem` o) m+            writeSOLFileMIP o m+    (_,_,errs) ->+        hPutStrLn stderr $ concat errs ++ usageInfo header options++-- FIXME: 目的関数値を表示するように+writeSOLFileMIP :: [Flag] -> Map MIP.Var Rational -> IO ()+writeSOLFileMIP opt m = do+  let sol = MIP.Solution+            { MIP.solStatus = MIP.StatusUnknown+            , MIP.solObjectiveValue = Nothing+            , MIP.solVariables = Map.fromList [(v, Scientific.fromFloatDigits (fromRational val :: Double)) | (v,val) <- Map.toList m]+            }+  writeSOLFileRaw opt sol++-- FIXME: 目的関数値を表示するように+writeSOLFileSAT :: [Flag] -> SAT.Model -> IO ()+writeSOLFileSAT opt m = do+  let sol = MIP.Solution+            { MIP.solStatus = MIP.StatusUnknown+            , MIP.solObjectiveValue = Nothing+            , MIP.solVariables = Map.fromList [(fromString ("x" ++ show x), if b then 1 else 0) | (x,b) <- assocs m]+            }+  writeSOLFileRaw opt sol++writeSOLFileRaw :: [Flag] -> MIP.Solution Scientific -> IO ()+writeSOLFileRaw opt sol = do+  forM_ [fname | WriteFile fname <- opt ] $ \fname -> do+    GurobiSol.writeFile fname sol
− appveyor.yml
@@ -1,20 +0,0 @@-install:-- ps: |-    choco install haskellplatform -version 2014.2.0.0 -y-    # Haskell Platfrom package doesn't update PATH for the current shell instance-    $env:Path += ";${env:ProgramFiles}\Haskell Platform\2014.2.0.0\bin"-    $env:Path += ";${env:ProgramFiles}\Haskell Platform\2014.2.0.0\lib\extralibs\bin"-    $env:Path += ";${env:ProgramFiles}\Haskell Platform\2014.2.0.0\mingw\bin"-    $env:Path += ";.\.cabal-sandbox\bin"-- cabal sandbox init-- cabal update-- cabal install --only-dependencies --enable-tests --enable-benchmarks --flag=BuildToyFMF --flag=BuildSamplePrograms --flag=BuildMiscPrograms--build_script:-- cabal configure --enable-tests --enable-benchmarks -v2 --flag=BuildToyFMF --flag=BuildSamplePrograms --flag=BuildMiscPrograms # -v2 provides useful information for debugging-- cabal build--test_script:-- cabal test-- cabal check-- cabal sdist
benchmarks/BenchmarkSATLIB.hs view
@@ -5,19 +5,19 @@ import Data.Default.Class import Text.Printf import Criterion.Main-import qualified Language.CNF.Parse.ParseDIMACS as DIMACS import qualified ToySolver.SAT as SAT+import qualified ToySolver.Text.CNF as CNF  solve :: FilePath -> IO () solve fname = do-  ret <- DIMACS.parseFile fname+  ret <- CNF.parseFile fname   case ret of     Left err  -> error $ show err     Right cnf -> do       solver <- SAT.newSolverWithConfig def{ SAT.configRandomFreq = 0 }-      _ <- replicateM (DIMACS.numVars cnf) (SAT.newVar solver)-      forM_ (DIMACS.clauses cnf) $ \clause ->-        SAT.addClause solver (elems clause)+      _ <- replicateM (CNF.numVars cnf) (SAT.newVar solver)+      forM_ (CNF.clauses cnf) $ \clause ->+        SAT.addClause solver clause       SAT.solve solver       return () 
− build_bdist_linux.sh
@@ -1,34 +0,0 @@-#!/bin/bash-export CABALVER=1.22-export GHCVER=7.10.3--sudo add-apt-repository -y ppa:hvr/ghc-sudo apt-get update--sudo apt-get install cabal-install-$CABALVER ghc-$GHCVER-export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:~/.cabal/bin:$PATH--sudo apt-get install happy-1.19.4 alex-3.1.3-export PATH=/opt/alex/3.1.3/bin:/opt/happy/1.19.4/bin:$PATH--cabal sandbox init-cabal update-cabal install --only-dependencies --flag=BuildToyFMF --flag=BuildSamplePrograms --flag=BuildMiscPrograms-#cabal configure --disable-shared --ghc-options="-static -optl-static -optl-pthread" --flag=BuildToyFMF --flag=BuildSamplePrograms --flag=BuildMiscPrograms-cabal configure -fLinuxStatic -f-UseHaskeline --flag=BuildToyFMF --flag=BuildSamplePrograms --flag=BuildMiscPrograms-cabal build--VER=`ghc -ignore-dot-ghci -e ":m + Control.Monad Distribution.Package Distribution.PackageDescription Distribution.PackageDescription.Parse Distribution.Verbosity Data.Version" -e 'putStrLn =<< liftM (showVersion . pkgVersion . package . packageDescription) (readPackageDescription silent "toysolver.cabal")'`-OS=`ghc -ignore-dot-ghci -e ":m +System.Info" -e "putStrLn os"`-ARCH=`ghc -ignore-dot-ghci -e ":m +System.Info" -e "putStrLn arch"`--PKG=toysolver-${VER}-${OS}-${ARCH}--rm -r $PKG-mkdir $PKG-mkdir $PKG/bin-cp dist/build/htc/htc dist/build/knapsack/knapsack dist/build/lpconvert/lpconvert dist/build/nonogram/nonogram dist/build/nqueens/nqueens dist/build/pbconvert/pbconvert dist/build/sudoku/sudoku dist/build/toyfmf/toyfmf dist/build/toysat/toysat dist/build/toysmt/toysmt dist/build/toysolver/toysolver $PKG/bin-strip $PKG/bin/*-cp -a samples $PKG/-cp COPYING-GPL README.md CHANGELOG.markdown $PKG/-tar Jcf $PKG.tar.xz $PKG --owner=sakai --group=sakai
− build_bdist_macos.sh
@@ -1,22 +0,0 @@-#!/bin/bash--export MACOSX_DEPLOYMENT_TARGET=10.6--cabal sandbox init-cabal update-cabal install --only-dependencies --flag=BuildToyFMF --flag=BuildSamplePrograms --flag=BuildMiscPrograms-cabal configure --flag=BuildToyFMF --flag=BuildSamplePrograms --flag=BuildMiscPrograms-cabal build--VER=`ghc -ignore-dot-ghci -e ":m + Control.Monad Distribution.Package Distribution.PackageDescription Distribution.PackageDescription.Parse Distribution.Verbosity Data.Version" -e 'putStrLn =<< liftM (showVersion . pkgVersion . package . packageDescription) (readPackageDescription silent "toysolver.cabal")'`--PKG=toysolver-$VER-macos--rm -r $PKG-mkdir $PKG-mkdir $PKG/bin-cp dist/build/htc/htc dist/build/knapsack/knapsack dist/build/lpconvert/lpconvert dist/build/nonogram/nonogram dist/build/nqueens/nqueens dist/build/pbconvert/pbconvert dist/build/sudoku/sudoku dist/build/toyfmf/toyfmf dist/build/toysat/toysat dist/build/toysmt/toysmt dist/build/toysolver/toysolver $PKG/bin-strip $PKG/bin/*-cp -a samples $PKG/-cp COPYING-GPL README.md CHANGELOG.markdown $PKG/-zip -r $PKG.zip $PKG
− build_bdist_maxsat_evaluation.sh
@@ -1,44 +0,0 @@-#!/bin/bash-export CABALVER=1.22-export GHCVER=7.10.3--sudo add-apt-repository -y ppa:hvr/ghc-sudo apt-get update--sudo apt-get install cabal-install-$CABALVER ghc-$GHCVER-export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:~/.cabal/bin:$PATH--sudo apt-get install happy-1.19.4 alex-3.1.3-export PATH=/opt/alex/3.1.3/bin:/opt/happy/1.19.4/bin:$PATH--cabal sandbox init-cabal update-cabal install --only-dependencies-#cabal configure --disable-shared --ghc-options="-static -optl-static -optl-pthread"-cabal configure -fLinuxStatic -fForceChar8-cabal build--PKG=toysat-maxsat`date +%Y`-`date +%Y%m%d`-`git rev-parse --short HEAD`-rm -r $PKG-mkdir $PKG-cp dist/build/toysat/toysat $PKG/toysat_main-cp misc/maxsat/toysat/README.md misc/maxsat/toysat/toysat $PKG/-tar Jcf $PKG.tar.xz $PKG --owner=sakai --group=sakai--if [ ! -f ubcsat-beta-12-b18.tar.gz ]; then-  wget http://ubcsat.dtompkins.com/downloads/ubcsat-beta-12-b18.tar.gz-fi-rm -r ubcsat-beta-12-b18-mkdir ubcsat-beta-12-b18-cd ubcsat-beta-12-b18-tar zxf ../ubcsat-beta-12-b18.tar.gz-gcc -Wall -O3 -static -o ubcsat src/adaptnovelty.c src/algorithms.c src/ddfw.c src/derandomized.c src/g2wsat.c src/gsat-tabu.c src/gsat.c src/gwsat.c src/hsat.c src/hwsat.c src/irots.c src/jack.c src/mt19937ar.c src/mylocal.c src/novelty+p.c src/novelty.c src/parameters.c src/paws.c src/random.c src/reports.c src/rgsat.c src/rnovelty.c src/rots.c src/samd.c src/saps.c src/sparrow.c src/ubcsat-help.c src/ubcsat-internal.c src/ubcsat-io.c src/ubcsat-mem.c src/ubcsat-reports.c src/ubcsat-time.c src/ubcsat-triggers.c src/ubcsat-version.c src/ubcsat.c src/vw.c src/walksat-tabu.c src/walksat.c src/weighted.c -lm-cd ..--PKG=toysat_ls-maxsat`date +%Y`-`date +%Y%m%d`-`git rev-parse --short HEAD`-rm -r $PKG-mkdir $PKG-cp dist/build/toysat/toysat $PKG/toysat_main-cp misc/maxsat/toysat_ls/README.md misc/maxsat/toysat_ls/toysat_ls $PKG/-cp ubcsat-beta-12-b18/ubcsat $PKG/-tar Jcf $PKG.tar.xz $PKG --owner=sakai --group=sakai
− build_bdist_pb_evaluation.sh
@@ -1,26 +0,0 @@-#!/bin/bash-export CABALVER=1.22-export GHCVER=7.10.3--sudo add-apt-repository -y ppa:hvr/ghc-sudo apt-get update--sudo apt-get install cabal-install-$CABALVER ghc-$GHCVER-export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:~/.cabal/bin:$PATH--sudo apt-get install happy-1.19.4 alex-3.1.3-export PATH=/opt/alex/3.1.3/bin:/opt/happy/1.19.4/bin:$PATH--cabal sandbox init-cabal update-cabal install --only-dependencies-#cabal configure --disable-shared --ghc-options="-static -optl-static -optl-pthread"-cabal configure -fLinuxStatic -fForceChar8-cabal build--PKG=toysat-pb`date +%Y`-`date +%Y%m%d`-`git rev-parse --short HEAD`-rm -r $PKG-mkdir $PKG-cp dist/build/toysat/toysat $PKG/-cp misc/pb/README.md $PKG/-tar Jcf $PKG.tar.xz $PKG --owner=sakai --group=sakai
− build_bdist_win32.sh
@@ -1,40 +0,0 @@-#!/bin/bash-HPVER=7.10.3-HPARCH=i386-export WINEPREFIX=~/.wine-hp-$HPARCH-GHC_PATH=$WINEPREFIX/drive_c/Program\ Files\ \(x86\)/Haskell\ Platform/$HPVER/bin/ghc.exe-ARCH=win32-BUILDDIR=dist-$ARCH--sudo apt-get update-sudo apt-get install wine wget cabal-install--if [ ! -f "$GHC_PATH" ]; then-  wget -c https://www.haskell.org/platform/download/$HPVER/HaskellPlatform-$HPVER-$HPARCH-setup.exe-  wine HaskellPlatform-$HPVER-$HPARCH-setup.exe /S-fi--# https://plus.google.com/+MasahiroSakai/posts/RTXUt5MkVPt-#wine cabal update-cabal update-mkdir -p $WINEPREFIX/drive_c/users/`whoami`/Application\ Data/cabal-cp -a ~/.cabal/packages $WINEPREFIX/drive_c/users/`whoami`/Application\ Data/cabal/--wine cabal sandbox init-wine cabal install --only-dependencies --flag=BuildToyFMF --flag=BuildSamplePrograms --flag=BuildMiscPrograms-wine cabal clean --builddir=$BUILDDIR-wine cabal configure --builddir=$BUILDDIR --flag=BuildToyFMF --flag=BuildSamplePrograms --flag=BuildMiscPrograms-wine cabal build --builddir=$BUILDDIR--VER=`wine ghc -ignore-dot-ghci -e ":m + Control.Monad Distribution.Package Distribution.PackageDescription Distribution.PackageDescription.Parse Distribution.Verbosity Data.Version System.IO" -e "hSetBinaryMode stdout True" -e 'putStrLn =<< liftM (showVersion . pkgVersion . package . packageDescription) (readPackageDescription silent "toysolver.cabal")'`--PKG=toysolver-$VER-$ARCH--rm -r $PKG-mkdir $PKG-mkdir $PKG/bin-cp $BUILDDIR/build/htc/htc.exe $BUILDDIR/build/knapsack/knapsack.exe $BUILDDIR/build/lpconvert/lpconvert.exe $BUILDDIR/build/nonogram/nonogram.exe $BUILDDIR/build/nqueens/nqueens.exe $BUILDDIR/build/pbconvert/pbconvert.exe $BUILDDIR/build/sudoku/sudoku.exe $BUILDDIR/build/toyfmf/toyfmf.exe $BUILDDIR/build/toysat/toysat.exe $BUILDDIR/build/toysmt/toysmt.exe $BUILDDIR/build/ToySolver/toysolver.exe $PKG/bin/-wine strip $PKG/bin/*.exe-cp -a samples $PKG/-cp COPYING-GPL README.md CHANGELOG.markdown $PKG/-zip -r $PKG.zip $PKG
− build_bdist_win64.sh
@@ -1,40 +0,0 @@-#!/bin/bash-HPVER=7.10.3-HPARCH=x86_64-export WINEPREFIX=~/.wine-hp-$HPARCH-GHC_PATH=$WINEPREFIX/drive_c/Program\ Files/Haskell\ Platform/$HPVER/bin/ghc.exe-ARCH=win64-BUILDDIR=dist-$ARCH--sudo apt-get update-sudo apt-get install wine wget cabal-install--if [ ! -f "$GHC_PATH" ]; then-  wget -c https://www.haskell.org/platform/download/$HPVER/HaskellPlatform-$HPVER-$HPARCH-setup.exe-  wine HaskellPlatform-$HPVER-$HPARCH-setup.exe /S-fi--# https://plus.google.com/+MasahiroSakai/posts/RTXUt5MkVPt-#wine cabal update-cabal update-mkdir -p $WINEPREFIX/drive_c/users/`whoami`/Application\ Data/cabal-cp -a ~/.cabal/packages $WINEPREFIX/drive_c/users/`whoami`/Application\ Data/cabal/--wine cabal sandbox init-wine cabal install --only-dependencies --flag=BuildToyFMF --flag=BuildSamplePrograms --flag=BuildMiscPrograms-wine cabal clean --builddir=$BUILDDIR-wine cabal configure --builddir=$BUILDDIR --flag=BuildToyFMF --flag=BuildSamplePrograms --flag=BuildMiscPrograms-wine cabal build --builddir=$BUILDDIR--VER=`wine ghc -ignore-dot-ghci -e ":m + Control.Monad Distribution.Package Distribution.PackageDescription Distribution.PackageDescription.Parse Distribution.Verbosity Data.Version System.IO" -e "hSetBinaryMode stdout True" -e 'putStrLn =<< liftM (showVersion . pkgVersion . package . packageDescription) (readPackageDescription silent "toysolver.cabal")'`--PKG=toysolver-$VER-$ARCH--rm -r $PKG-mkdir $PKG-mkdir $PKG/bin-cp $BUILDDIR/build/htc/htc.exe $BUILDDIR/build/knapsack/knapsack.exe $BUILDDIR/build/lpconvert/lpconvert.exe $BUILDDIR/build/nonogram/nonogram.exe $BUILDDIR/build/nqueens/nqueens.exe $BUILDDIR/build/pbconvert/pbconvert.exe $BUILDDIR/build/sudoku/sudoku.exe $BUILDDIR/build/toyfmf/toyfmf.exe $BUILDDIR/build/toysat/toysat.exe $BUILDDIR/build/toysmt/toysmt.exe $BUILDDIR/build/ToySolver/toysolver.exe $PKG/bin/-wine strip $PKG/bin/*.exe-cp -a samples $PKG/-cp COPYING-GPL README.md CHANGELOG.markdown $PKG/-zip -r $PKG.zip $PKG
+ doc-images/MIP-Status-diagram.png view

binary file changed (absent → 17223 bytes)

+ doc-images/MIP-Status-diagram.tex view
@@ -0,0 +1,18 @@+\documentclass{article}+\usepackage{tikz}+\begin{document}++\begin{tikzpicture}[scale=.7]+  \node (Optimal) at (-3,2) {Optimal};+  \node (Feasible) at (-3,0) {Feasible};+  \node (InfeasibleOrUnbounded) at (2,0) {InfeasibleOrUnbounded};+  \node (Unbounded) at (2,2) {Unbounded};+  \node (Infeasible) at (6,2) {Infeasible};+  \node (Unknown) at (0,-2) {Unknown};+  \draw (Unknown) -- (Feasible) -- (Optimal);+  \draw (Feasible) -- (Unbounded);+  \draw (Unknown) -- (InfeasibleOrUnbounded) -- (Unbounded);+   \draw (InfeasibleOrUnbounded) -- (Infeasible);+\end{tikzpicture}++\end{document}
− lpconvert/lpconvert.hs
@@ -1,190 +0,0 @@-{-# OPTIONS_GHC -Wall #-}--------------------------------------------------------------------------------- |--- Module      :  lpconvert--- Copyright   :  (c) Masahiro Sakai 2012-2014--- License     :  BSD-style--- --- Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  experimental--- Portability :  portable-----------------------------------------------------------------------------------module Main where--import Data.Char-import Data.Default.Class-import Data.Maybe-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 Data.PseudoBoolean as PBFile--import qualified ToySolver.Data.MIP as MIP-import qualified ToySolver.Text.MaxSAT as MaxSAT-import ToySolver.Converter.ObjType-import qualified ToySolver.Converter.MIP2SMT as MIP2SMT-import qualified ToySolver.Converter.MaxSAT2IP as MaxSAT2IP-import qualified ToySolver.Converter.MaxSAT2NLPB as MaxSAT2NLPB-import qualified ToySolver.Converter.PB2IP as PB2IP-import qualified ToySolver.Converter.PBSetObj as PBSetObj-import qualified ToySolver.Converter.SAT2PB as SAT2PB-import ToySolver.Version--data Flag-  = Help-  | Version-  | Output String-  | AsMaxSAT-  | ObjType ObjType-  | IndicatorConstraint-  | SMTSetLogic String-  | SMTOptimize-  | SMTNoCheck-  | SMTNoProduceModel-  | MaxSATNonLinear-  | Yices2-  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-set-logic"] (ReqArg SMTSetLogic "STRING") "output \"(set-logic STRING)\""-    , Option []    ["smt-optimize"] (NoArg SMTOptimize)   "output optimiality condition which uses quantifiers"-    , Option []    ["smt-no-check"] (NoArg SMTNoCheck)    "do not output \"(check)\""-    , Option []    ["smt-no-produce-model"] (NoArg SMTNoProduceModel) "do not output \"(set-option :produce-models true)\""    -    , Option []    ["maxsat-nonlinear"] (NoArg MaxSATNonLinear) "use non-linear formulation of Max-SAT"-    , Option []    ["yices2"] (NoArg Yices2) "output for yices2 rather than yices1"-    ]-  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:"-  , "    lpconvert -o <outputfile> <inputfile>"-  , ""-  , "Supported formats:"-  , "    input: .lp .mps .cnf .wcnf .opb .wbo"-  , "    output: .lp .mps .smt2 .ys"-  , ""-  , "Options:"-  ]--readLP :: [Flag] -> String -> IO MIP.Problem-readLP 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 -> do-              let pb = transformPBFile o $ SAT2PB.convert cnf-              let (mip, _) = PB2IP.convert pb-              return mip-    ".wcnf" -> readWCNF-    ".opb"  -> do-      ret <- PBFile.parseOPBFile fname-      case ret of-        Left err -> hPrint stderr err >> exitFailure-        Right formula -> do-          let pb = transformPBFile o formula-          let (mip, _) = PB2IP.convert pb-          return mip-    ".wbo"  -> do-      ret <- PBFile.parseWBOFile fname-      case ret of-        Left err -> hPrint stderr err >> exitFailure-        Right formula -> do-          let (mip, _) = PB2IP.convertWBO (IndicatorConstraint `elem` o) formula-          return mip-    ".lp"   -> do-      ret <- MIP.readLPFile fname-      case ret of-        Left err -> hPrint stderr err >> exitFailure-        Right mip -> return mip-    ".mps"  -> do-      ret <- MIP.readMPSFile fname-      case ret of-        Left err -> hPrint stderr err >> exitFailure-        Right mip -> return mip-    ext ->-      error $ "unknown file extension: " ++ show ext-  where-    readWCNF = do-      ret <- MaxSAT.parseFile fname-      case ret of-        Left err -> hPutStrLn stderr err >> exitFailure-        Right wcnf-          | MaxSATNonLinear `elem` o -> do-              let pb = transformPBFile o $ MaxSAT2NLPB.convert wcnf-                  (mip, _) = PB2IP.convert pb-              return mip-          | otherwise -> do-              let (mip, _) = MaxSAT2IP.convert (IndicatorConstraint `elem` o) wcnf-              return mip--transformPBFile :: [Flag] -> PBFile.Formula -> PBFile.Formula-transformPBFile o opb | isNothing (PBFile.pbObjectiveFunction opb) = PBSetObj.setObj objType opb-  where-    objType = last (ObjNone : [t | ObjType t <- o])-transformPBFile _ opb = opb--writeLP :: [Flag] -> MIP.Problem -> IO ()-writeLP o mip = do-  let mip2smtOpt =-        def-        { MIP2SMT.optSetLogic     = listToMaybe [logic | SMTSetLogic logic <- o]-        , MIP2SMT.optCheckSAT     = not (SMTNoCheck `elem` o)-        , MIP2SMT.optProduceModel = not (SMTNoProduceModel `elem` o)-        , MIP2SMT.optOptimize     = SMTOptimize `elem` o-        }--  case head ([Just fname | Output fname <- o] ++ [Nothing]) of-    Nothing -> -      case MIP.toLPString mip of-        Left err -> hPutStrLn stderr ("conversion failure: " ++ err) >> exitFailure-        Right s -> putStr s-    Just fname -> do-      case map toLower (takeExtension fname) of-        ".lp" -> MIP.writeLPFile fname mip-        ".mps" -> MIP.writeMPSFile fname mip-        ".smt2" -> do-          writeFile fname (MIP2SMT.convert mip2smtOpt mip "")-        ".ys" -> do-          let lang = MIP2SMT.YICES (if Yices2 `elem` o then MIP2SMT.Yices2 else MIP2SMT.Yices1)-          writeFile fname (MIP2SMT.convert mip2smtOpt{ MIP2SMT.optLanguage = lang } mip "")-        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-      mip <- readLP o fname-      writeLP o mip-    (_,_,errs) -> do-      hPutStrLn stderr $ concat errs ++ usageInfo header options-      exitFailure
− maxsatverify/maxsatverify.hs
@@ -1,42 +0,0 @@-module Main where--import Control.Monad-import Data.Array.IArray-import Data.IORef-import System.Environment-import Text.Printf-import qualified ToySolver.Text.MaxSAT as MaxSAT-import ToySolver.SAT.Types--main :: IO ()-main = do-  [problemFile, modelFile] <- getArgs-  Right wcnf <- MaxSAT.parseFile problemFile-  model <- liftM readModel (readFile modelFile)-  costRef <- newIORef 0-  forM_ (MaxSAT.clauses wcnf) $ \(w,c) ->-    unless (eval model c) $-      if w == MaxSAT.topCost wcnf-      then printf "violated hard constraint: %s\n" (show c)-      else do-        tc <- readIORef costRef-        writeIORef costRef $! tc + w-  printf "total cost = %d\n" =<< readIORef costRef--eval :: Model -> Clause -> Bool-eval m lits = or [evalLit m lit | lit <- lits]--readModel :: String -> Model-readModel s = array (1, maximum (0 : map fst ls2)) ls2-  where-    ls = lines s-    ls2 = do-      l <- ls-      case l of-        'v':xs -> do-          w <- words xs-          case w of-            '-':ys -> return (read ys, False)-            ys -> return (read ys, True)-        _ -> mzero-
+ misc/build_bdist_linux.sh view
@@ -0,0 +1,28 @@+#!/bin/bash++STACK_YAML=stack.yaml+RESOLVER=lts-9.2++# wget -qO- https://get.haskellstack.org/ | sh+PATH=$HOME/.local/bin:$PATH++stack --stack-yaml=$STACK_YAML --resolver=$RESOLVER --install-ghc build \+  --flag toysolver:BuildToyFMF \+  --flag toysolver:BuildSamplePrograms++VER=`stack exec ghc -- -ignore-dot-ghci -e ":m + Control.Monad Distribution.Package Distribution.PackageDescription Distribution.PackageDescription.Parse Distribution.Verbosity Data.Version" -e 'putStrLn =<< liftM (showVersion . pkgVersion . package . packageDescription) (readPackageDescription silent "toysolver.cabal")'`+STACK_LOCAL_INSTALL_ROOT=`stack --stack-yaml=$STACK_YAML --resolver=$RESOLVER path --local-install-root`+OS=`stack exec ghc -- -ignore-dot-ghci -e ":m +System.Info" -e "putStrLn os"`+ARCH=`stack exec ghc -- -ignore-dot-ghci -e ":m +System.Info" -e "putStrLn arch"`+PLATFORM=$ARCH-$OS++PKG=toysolver-${VER}-${OS}-${ARCH}++rm -r $PKG+mkdir $PKG+mkdir $PKG/bin+cp $STACK_LOCAL_INSTALL_ROOT/bin/{toyconvert,toyfmf,toyqbf,toysat,toysmt,toysolver} $PKG/bin/+cp $STACK_LOCAL_INSTALL_ROOT/bin/{assign,htc,knapsack,nonogram,nqueens,numberlink,shortest-path,sudoku} $PKG/bin/+cp -a samples $PKG/+cp COPYING-GPL README.md CHANGELOG.markdown $PKG/+tar Jcf $PKG.tar.xz $PKG --owner=sakai --group=sakai
+ misc/build_bdist_macos.sh view
@@ -0,0 +1,28 @@+#!/bin/bash++export MACOSX_DEPLOYMENT_TARGET=10.11++STACK_YAML=stack.yaml+RESOLVER=lts-9.2++# curl -sSL https://get.haskellstack.org/ | sh+PATH=$HOME/.local/bin:$PATH++stack --stack-yaml=$STACK_YAML --resolver=$RESOLVER --install-ghc build \+  --flag toysolver:BuildToyFMF \+  --flag toysolver:BuildSamplePrograms \+  --flag toysolver:OpenCL++VER=`stack exec ghc -- -ignore-dot-ghci -e ":m + Control.Monad Distribution.Package Distribution.PackageDescription Distribution.PackageDescription.Parse Distribution.Verbosity Data.Version" -e 'putStrLn =<< liftM (showVersion . pkgVersion . package . packageDescription) (readPackageDescription silent "toysolver.cabal")'`+STACK_LOCAL_INSTALL_ROOT=`stack --stack-yaml=$STACK_YAML --resolver=$RESOLVER path --local-install-root`++PKG=toysolver-$VER-macos++rm -r $PKG+mkdir $PKG+mkdir $PKG/bin+cp $STACK_LOCAL_INSTALL_ROOT/bin/{toyconvert,toyfmf,toyqbf,toysat,toysmt,toysolver} $PKG/bin/+cp $STACK_LOCAL_INSTALL_ROOT/bin/{assign,htc,knapsack,nonogram,nqueens,numberlink,shortest-path,sudoku} $PKG/bin/+cp -a samples $PKG/+cp COPYING-GPL README.md CHANGELOG.markdown $PKG/+zip -r $PKG.zip $PKG
+ misc/build_bdist_maxsat_evaluation.sh view
@@ -0,0 +1,44 @@+#!/bin/bash+export CABALVER=1.22+export GHCVER=7.10.3++sudo add-apt-repository -y ppa:hvr/ghc+sudo apt-get update++sudo apt-get install cabal-install-$CABALVER ghc-$GHCVER+export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:~/.cabal/bin:$PATH++sudo apt-get install happy-1.19.4 alex-3.1.3+export PATH=/opt/alex/3.1.3/bin:/opt/happy/1.19.4/bin:$PATH++cabal sandbox init+cabal update+cabal install --only-dependencies+#cabal configure --disable-shared --ghc-options="-static -optl-static -optl-pthread"+cabal configure -fLinuxStatic -fForceChar8+cabal build++PKG=toysat-maxsat`date +%Y`-`date +%Y%m%d`-`git rev-parse --short HEAD`+rm -r $PKG+mkdir $PKG+cp dist/build/toysat/toysat $PKG/toysat_main+cp COPYING misc/maxsat/toysat/README.md misc/maxsat/toysat/toysat $PKG/+tar Jcf $PKG.tar.xz $PKG --owner=sakai --group=sakai++if [ ! -f ubcsat-beta-12-b18.tar.gz ]; then+  wget http://ubcsat.dtompkins.com/downloads/ubcsat-beta-12-b18.tar.gz+fi+rm -r ubcsat-beta-12-b18+mkdir ubcsat-beta-12-b18+cd ubcsat-beta-12-b18+tar zxf ../ubcsat-beta-12-b18.tar.gz+gcc -Wall -O3 -static -o ubcsat src/adaptnovelty.c src/algorithms.c src/ddfw.c src/derandomized.c src/g2wsat.c src/gsat-tabu.c src/gsat.c src/gwsat.c src/hsat.c src/hwsat.c src/irots.c src/jack.c src/mt19937ar.c src/mylocal.c src/novelty+p.c src/novelty.c src/parameters.c src/paws.c src/random.c src/reports.c src/rgsat.c src/rnovelty.c src/rots.c src/samd.c src/saps.c src/sparrow.c src/ubcsat-help.c src/ubcsat-internal.c src/ubcsat-io.c src/ubcsat-mem.c src/ubcsat-reports.c src/ubcsat-time.c src/ubcsat-triggers.c src/ubcsat-version.c src/ubcsat.c src/vw.c src/walksat-tabu.c src/walksat.c src/weighted.c -lm+cd ..++PKG=toysat_ls-maxsat`date +%Y`-`date +%Y%m%d`-`git rev-parse --short HEAD`+rm -r $PKG+mkdir $PKG+cp dist/build/toysat/toysat $PKG/toysat_main+cp COPYING misc/maxsat/toysat_ls/README.md misc/maxsat/toysat_ls/toysat_ls $PKG/+cp ubcsat-beta-12-b18/ubcsat $PKG/+tar Jcf $PKG.tar.xz $PKG --owner=sakai --group=sakai
+ misc/build_bdist_pb_evaluation.sh view
@@ -0,0 +1,26 @@+#!/bin/bash+export CABALVER=1.22+export GHCVER=7.10.3++sudo add-apt-repository -y ppa:hvr/ghc+sudo apt-get update++sudo apt-get install cabal-install-$CABALVER ghc-$GHCVER+export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:~/.cabal/bin:$PATH++sudo apt-get install happy-1.19.4 alex-3.1.3+export PATH=/opt/alex/3.1.3/bin:/opt/happy/1.19.4/bin:$PATH++cabal sandbox init+cabal update+cabal install --only-dependencies+#cabal configure --disable-shared --ghc-options="-static -optl-static -optl-pthread"+cabal configure -fLinuxStatic -fForceChar8+cabal build++PKG=toysat-pb`date +%Y`-`date +%Y%m%d`-`git rev-parse --short HEAD`+rm -r $PKG+mkdir $PKG+cp dist/build/toysat/toysat $PKG/+cp COPYING misc/pb/README.md $PKG/+tar Jcf $PKG.tar.xz $PKG --owner=sakai --group=sakai
+ misc/build_bdist_qbf_evaluation.sh view
@@ -0,0 +1,27 @@+#!/bin/bash+export CABALVER=1.22+export GHCVER=7.10.3++sudo add-apt-repository -y ppa:hvr/ghc+sudo apt-get update++sudo apt-get install cabal-install-$CABALVER ghc-$GHCVER+export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:~/.cabal/bin:$PATH++sudo apt-get install happy-1.19.4 alex-3.1.3+export PATH=/opt/alex/3.1.3/bin:/opt/happy/1.19.4/bin:$PATH++cabal sandbox init+cabal update+cabal install --only-dependencies+#cabal configure --disable-shared --ghc-options="-static -optl-static -optl-pthread"+cabal configure -fLinuxStatic -fForceChar8+cabal build++PKG=toyqbf-qbfeval`date +%Y`-`date +%Y%m%d`-`git rev-parse --short HEAD`+rm -r $PKG+mkdir $PKG+cp dist/build/toyqbf/toyqbf $PKG/+cp misc/qbf/README.md $PKG/+cp COPYING $PKG/+tar Jcf $PKG.tar.xz $PKG --owner=sakai --group=sakai
+ misc/build_bdist_win32.sh view
@@ -0,0 +1,31 @@+#!/bin/bash++STACK_YAML=stack.yaml+RESOLVER=lts-9.2+ARCH=win32++if [ ! -f stack-windows-i386.zip ]; then+  curl -ostack-windows-i386.zip -L --insecure http://www.stackage.org/stack/windows-i386+fi+unzip stack-windows-i386.zip stack.exe++#sudo apt-get update+#sudo apt-get install wine++wine stack --stack-yaml=$STACK_YAML --resolver=$RESOLVER --install-ghc build \+  --flag toysolver:BuildToyFMF \+  --flag toysolver:BuildSamplePrograms++VER=`wine stack exec ghc -- -ignore-dot-ghci -e ":m + Control.Monad Distribution.Package Distribution.PackageDescription Distribution.PackageDescription.Parse Distribution.Verbosity Data.Version System.IO" -e "hSetBinaryMode stdout True" -e 'putStrLn =<< liftM (showVersion . pkgVersion . package . packageDescription) (readPackageDescription silent "toysolver.cabal")'`+STACK_LOCAL_INSTALL_ROOT=`wine stack --stack-yaml=$STACK_YAML --resolver=$RESOLVER path --local-install-root`++PKG=toysolver-${VER}-$ARCH++rm -r $PKG+mkdir $PKG+mkdir $PKG/bin+cp $STACK_LOCAL_INSTALL_ROOT/bin/{toyconvert,toyfmf,toyqbf,toysat,toysmt,toysolver}.exe $PKG/bin/+cp $STACK_LOCAL_INSTALL_ROOT/bin/{assign,htc,knapsack,nonogram,nqueens,numberlink,shortest-path,sudoku}.exe $PKG/bin/+cp -a samples $PKG/+cp COPYING-GPL README.md CHANGELOG.markdown $PKG/+zip -r $PKG.zip $PKG
+ misc/build_bdist_win64.sh view
@@ -0,0 +1,31 @@+#!/bin/bash++STACK_YAML=stack.yaml+RESOLVER=lts-9.2+ARCH=win64++if [ ! -f stack-windows-x86_64.zip ]; then+  curl -ostack-windows-x86_64.zip -L --insecure http://www.stackage.org/stack/windows-x86_64+fi+unzip stack-windows-x86_64.zip stack.exe++#sudo apt-get update+#sudo apt-get install wine++wine stack --stack-yaml=$STACK_YAML --resolver=$RESOLVER --install-ghc build \+  --flag toysolver:BuildToyFMF \+  --flag toysolver:BuildSamplePrograms++VER=`wine stack exec ghc -- -ignore-dot-ghci -e ":m + Control.Monad Distribution.Package Distribution.PackageDescription Distribution.PackageDescription.Parse Distribution.Verbosity Data.Version System.IO" -e "hSetBinaryMode stdout True" -e 'putStrLn =<< liftM (showVersion . pkgVersion . package . packageDescription) (readPackageDescription silent "toysolver.cabal")'`+STACK_LOCAL_INSTALL_ROOT=`wine stack --stack-yaml=$STACK_YAML --resolver=$RESOLVER path --local-install-root`++PKG=toysolver-${VER}-$ARCH++rm -r $PKG+mkdir $PKG+mkdir $PKG/bin+cp $STACK_LOCAL_INSTALL_ROOT/bin/{toyconvert,toyfmf,toyqbf,toysat,toysmt,toysolver}.exe $PKG/bin/+cp $STACK_LOCAL_INSTALL_ROOT/bin/{assign,htc,knapsack,nonogram,nqueens,numberlink,shortest-path,sudoku}.exe $PKG/bin/+cp -a samples $PKG/+cp COPYING-GPL README.md CHANGELOG.markdown $PKG/+zip -r $PKG.zip $PKG
misc/maxsat/toysat/toysat view
@@ -1,2 +1,5 @@ #!/bin/sh-./toysat_main +RTS -H1G -K1G -RTS --search=bcd2 --maxsat $@+tempdir=/tmp/toysat-$$-$1+./toysat_main +RTS -H1G -K1G -RTS --search=bcd2 --temp-dir=$tempdir --maxsat $@+rm -r $tempdir+
misc/maxsat/toysat_ls/toysat_ls view
@@ -1,2 +1,4 @@ #!/bin/sh-./toysat_main +RTS -H1G -K1G -RTS --maxsat --search=bcd2 --with-ubcsat=./ubcsat --ls-initial $@+tempdir=/tmp/toysat_ls-$$-$1+./toysat_main +RTS -H1G -K1G -RTS --maxsat --search=bcd2 --temp-dir=$tempdir --with-ubcsat=./ubcsat --ls-initial $@+rm -r $tempdir
misc/pb/README.md view
@@ -1,33 +1,41 @@-Toysat submission for the Pseudo-Boolean Evaluation 2015-========================================================+Toysat submission for the Pseudo-Boolean Competition 2016+=========================================================  Usage ----- -    ./toysat +RTS -H1G -K1G -RTS --search=bcd2 file.opb--About Solver Requirments and Optional Features-------------------------------------------------Minimum Requirments+    toysat +RTS -H1G -MMEMLIMITm -K1G -RTS --pb --search=bcd2 BENCHNAME -* solve decision problems: YES-* handle 32 bit Integers: YES-* handle cardinality constraints: YES+    toysat +RTS -H1G -MMEMLIMITm -K1G -RTS --wbo --search=bcd2 BENCHNAME -Optional Features+Categories of benchmarks+------------------------ -* solve optimization problems: YES-    * incomplete optimization: -    * complete optimization: ✓-* handle 64 bit Integers: YES (it can handle arbitrary integers)-* handle general pseudo-Boolean constraints: YES+* PB+  * DEC-BIGINT-LIN (no optimisation, big integers, linear constraints) +  * DEC-BIGINT-NLC (no optimisation, big integers, non linear constraints) +  * DEC-SMALLINT-LIN (no optimisation, small integers, linear constraints) +  * DEC-SMALLINT-NLC (no optimisation, small integers, non linear constraints) +  * DEC-SMALLINT-NLC (no optimisation, small integers, non linear constraints) +  * OPT-BIGINT-LIN (optimisation, big integers, linear constraints) +  * OPT-BIGINT-NLC (optimisation, big integers, non linear constraints) +  * OPT-SMALLINT-LIN (optimisation, small integers, linear constraints) +  * OPT-SMALLINT-NLC (optimisation, small integers, non linear constraints) +* WBO+  * PARTIAL-BIGINT-LIN (both soft and hard constraints, big integers, linear constraints) +  * PARTIAL-BIGINT-NLC (both soft and hard constraints, big integers, non linear constraints) +  * PARTIAL-SMALLINT-LIN (both soft and hard constraints, small integers, linear constraints) +  * PARTIAL-SMALLINT-NLC (both soft and hard constraints, small integers, non linear constraints) +  * SOFT-BIGINT-LIN (only soft constraints, big integers, linear constraints) +  * SOFT-BIGINT-NLC (only soft constraints, big integers, non linear constraints) +  * SOFT-SMALLINT-LIN (only soft constraints, small integers, linear constraints) +  * SOFT-SMALLINT-NLC (only soft constraints, small integers, non linear constraints)   Algorithm ---------  We have implemented BCD2 algorithm [1] on top on our own CDCL SAT solver-'toysat' with watch-literal based cardinality constraint handler and+'toysat' [2] with watch-literal based cardinality constraint handler and counter-based linear pseudo boolean constraint handler. One of the major difference from the original BCD2 is that our implementation uses incremental solving features of SAT solver to keep the information such as learnt clauses@@ -35,7 +43,7 @@  Non-linear constraints and objective functions are handled by linearization using a variant of Tseitin transformation that take the polarity into account-[2].+[3].  References ----------@@ -46,6 +54,8 @@   pp. 284-297.   <http://dx.doi.org/10.1007/978-3-642-31612-8_22> -* [2] N. Eén and N. Sörensson,+* [2] Masahiro Sakai. <https://github.com/msakai/toysolver>++* [3] N. Eén and N. Sörensson,   Translating pseudo-boolean constraints into SAT, Journal on Satisfiability,   Boolean Modeling and Computation, vol. 2, pp. 1-26, 2006.
+ misc/qbf/README.md view
@@ -0,0 +1,34 @@+Toyqbf submission for the QBFEVAL'16+====================================++Usage+-----++    ./toyqbf +RTS -H1G -K1G -RTS file.cnf+    ./toyqbf +RTS -H1G -K1G -RTS file.qdimacs++Algorithm+---------++We have implemented Counterexample Guided Refinement algorithm for QBF [1] on+top on our own CDCL SAT solver 'toysat'.++Source Code+-----------++The source code is available from <https://github.com/msakai/toysolver>.++License+-------++This program is licenced under the BSD-style license.+(See the file 'COPYING'.)++References+----------++* [1] Mikoláš Janota, William Klieber, Joao Marques-Silva, Edmund Clarke.+  Solving QBF with Counterexample Guided Refinement.+  In Theory and Applications of Satisfiability Testing (SAT 2012), pp. 114-128.+  <http://dx.doi.org/10.1007/978-3-642-31612-8_10>+  <https://www.cs.cmu.edu/~wklieber/papers/qbf-cegar-sat-2012.pdf>
− pbconvert/pbconvert.hs
@@ -1,193 +0,0 @@-{-# 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 Data.Default.Class-import Data.Maybe-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 Data.PseudoBoolean as PBFile-import qualified Data.PseudoBoolean.Attoparsec as PBFileAttoparsec--import qualified ToySolver.Data.MIP as MIP-import qualified ToySolver.Text.MaxSAT as MaxSAT-import ToySolver.Converter.ObjType-import qualified ToySolver.Converter.SAT2PB as SAT2PB-import qualified ToySolver.Converter.MIP2SMT as MIP2SMT-import qualified ToySolver.Converter.MaxSAT2WBO as MaxSAT2WBO-import qualified ToySolver.Converter.MaxSAT2NLPB as MaxSAT2NLPB-import qualified ToySolver.Converter.PB2IP as PB2IP-import qualified ToySolver.Converter.PB2LSP as PB2LSP-import qualified ToySolver.Converter.PB2WBO as PB2WBO-import qualified ToySolver.Converter.PBSetObj as PBSetObj-import qualified ToySolver.Converter.PB2SMP as PB2SMP-import qualified ToySolver.Converter.WBO2PB as WBO2PB-import ToySolver.Version--data Flag-  = Help-  | Version-  | Output String-  | AsMaxSAT-  | ObjType ObjType-  | IndicatorConstraint-  | SMTSetLogic String-  | SMTOptimize-  | SMTNoCheck-  | SMTNoProduceModel-  | MaxSATNonLinear-  | Yices2-  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-set-logic"] (ReqArg SMTSetLogic "STRING") "output \"(set-logic STRING)\""-    , Option []    ["smt-optimize"] (NoArg SMTOptimize)   "output optimiality condition which uses quantifiers"-    , Option []    ["smt-no-check"] (NoArg SMTNoCheck)    "do not output \"(check)\""-    , Option []    ["smt-no-produce-model"] (NoArg SMTNoProduceModel) "do not output \"(set-option :produce-models true)\""    -    , Option []    ["maxsat-nonlinear"] (NoArg MaxSATNonLinear) "use non-linear formulation of Max-SAT"-    , Option []    ["yices2"] (NoArg Yices2) "output for yices2 rather than yices1"-    ]-  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 <- PBFileAttoparsec.parseOPBFile fname-      case ret of-        Left err -> hPutStrLn stderr err >> exitFailure-        Right opb -> return $ Left opb-    ".wbo"  -> do-      ret <- PBFileAttoparsec.parseWBOFile fname-      case ret of-        Left err -> hPutStrLn stderr err >> exitFailure-        Right wbo -> return $ Right wbo-    ext ->-      error $ "unknown file extension: " ++ show ext-  where-    readWCNF = do-      ret <- MaxSAT.parseFile 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 | isNothing (PBFile.pbObjectiveFunction opb) -> 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 mip2smtOpt =-        def-        { MIP2SMT.optSetLogic     = listToMaybe [logic | SMTSetLogic logic <- o]-        , MIP2SMT.optCheckSAT     = not (SMTNoCheck `elem` o)-        , MIP2SMT.optProduceModel = not (SMTNoProduceModel `elem` o)-        , MIP2SMT.optOptimize     = SMTOptimize `elem` o-        }-  case head ([Just fname | Output fname <- o] ++ [Nothing]) of-    Nothing -> do-      hSetBinaryMode stdout True-      hSetBuffering stdout (BlockBuffering Nothing)-      case pb of-        Left opb  -> PBFile.hPutOPB stdout opb-        Right wbo -> PBFile.hPutWBO stdout 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 $ PB2IP.convert opb-                  Right wbo -> fst $ PB2IP.convertWBO (IndicatorConstraint `elem` o) wbo-          lsp = case pb of-                  Left opb  -> PB2LSP.convert opb-                  Right wbo -> PB2LSP.convertWBO wbo-      case map toLower (takeExtension fname) of-        ".opb" -> PBFile.writeOPBFile fname opb-        ".wbo" -> PBFile.writeWBOFile fname wbo-        ".lsp" -> writeFile fname (lsp "")-        ".lp" -> MIP.writeLPFile fname lp-        ".mps" -> MIP.writeMPSFile fname lp-        ".smp" -> do-          writeFile fname (PB2SMP.convert False opb "")-        ".smt2" -> do-          writeFile fname (MIP2SMT.convert mip2smtOpt lp "")-        ".ys" -> do-          let lang = MIP2SMT.YICES (if Yices2 `elem` o then MIP2SMT.Yices2 else MIP2SMT.Yices1)-          writeFile fname (MIP2SMT.convert mip2smtOpt{ MIP2SMT.optLanguage = lang } 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
− pbverify/pbverify.hs
@@ -1,41 +0,0 @@-module Main where--import Control.Monad-import Data.Array.IArray-import System.Environment-import Text.Printf-import qualified Data.PseudoBoolean as PBFile-import qualified Data.PseudoBoolean.Attoparsec as PBFileAttoparsec-import ToySolver.SAT.Types--main :: IO ()-main = do-  [problemFile, modelFile] <- getArgs-  Right formula <- PBFileAttoparsec.parseOPBFile problemFile-  model <- liftM readModel (readFile modelFile)-  forM_ (PBFile.pbConstraints formula) $ \c ->-    unless (eval model c) $-      printf "violated: %s\n" (show c)--eval :: Model -> PBFile.Constraint -> Bool-eval m (lhs, op, rhs) = op_v lhs_v rhs-  where-    lhs_v = sum [c | (c,lits) <- lhs, all (evalLit m) lits]-    op_v  = case op of-              PBFile.Ge -> (>=)-              PBFile.Eq -> (==)--readModel :: String -> Model-readModel s = array (1, maximum (0 : map fst ls2)) ls2-  where-    ls = lines s-    ls2 = do-      l <- ls-      case l of-        'v':xs -> do-          w <- words xs-          case w of-            '-':'x':ys -> return (read ys, False)-            'x':ys -> return (read ys, True)-        _ -> mzero-
− pigeonhole/pigeonhole.hs
@@ -1,41 +0,0 @@-module Main where--import Data.List-import qualified Data.Map as Map-import Data.Map (Map)-import System.Environment-import System.Exit-import System.IO-import Data.PseudoBoolean as PBFile--pigeonHole :: Integer -> Integer -> Formula-pigeonHole p h =-  Formula-  { pbObjectiveFunction = Nothing-  , pbConstraints = cs1 ++ cs2-  , pbNumVars = fromIntegral $ p*h-  , pbNumConstraints = fromIntegral $ p+h-  }-  where-    vs :: Map (Integer,Integer) Int-    vs = Map.fromList $ zip [(i,j) | i<-[1..p], j<-[1..h]] [1..]--    cs1 :: [Constraint]-    cs1 = [ ([(1,[v]) | j<-[1..h], let v = vs Map.! (i,j)], PBFile.Ge, 1)-          | i<-[1..p]-          ]-    cs2 :: [Constraint]-    cs2 = [ ([(-1,[v]) | i<-[1..p], let v = vs Map.! (i,j)], PBFile.Ge, -1)-          | j<-[1..h]-          ]--main :: IO ()-main = do-  xs <- getArgs-  case xs of-    [p,h] -> do-      let opb = pigeonHole (read p) (read h)-      hPutOPB stdout opb-    _ -> do-      hPutStrLn stderr "Usage: pigeonhole number_of_pigeons number_of_holes"-      exitFailure
+ samples/lp/infeasible.lp view
@@ -0,0 +1,10 @@+Minimize+  0 x+Subject To+  3 x >= 1+  3 x <= 2+Bounds+  -inf <= x <= +inf+General+  x+End
+ samples/lp/test-solution-cbc-infeasible.txt view
@@ -0,0 +1,4 @@+Integer infeasible - objective value 0.00000000+      0 x             0.11111111                       0+      1 y                      0                       0+      2 z             0.33333333                       0
+ samples/lp/test-solution-cbc-unbounded.txt view
@@ -0,0 +1,3 @@+Unbounded - objective value 0.00000000+**       0 x                      0                       0+      1 y                      0                    -1.5
+ samples/lp/test-solution-cbc.txt view
@@ -0,0 +1,5 @@+Optimal - objective value -122.50000000+      0 x1                    40                      -4+      1 x2                  10.5                       0+      2 x3                  19.5                       0+      3 x4                     3                    32.5
+ samples/lp/test-solution-cplex-unbounded.sol view
@@ -0,0 +1,32 @@+<?xml version = "1.0" encoding="UTF-8" standalone="yes"?>+<CPLEXSolution version="1.2">+ <header+   problemName="samples/lp/test-solution-glpk-unbounded.lp"+   solutionName="incumbent"+   solutionIndex="-1"+   objectiveValue="3"+   solutionTypeValue="3"+   solutionTypeString="primal"+   solutionStatusValue="118"+   solutionStatusString="integer unbounded"+   solutionMethodString="mip"+   primalFeasible="1"+   dualFeasible="0"+   MIPNodes="0"+   MIPIterations="0"+   writeLevel="1"/>+ <quality+   epInt="1.0000000000000001e-05"+   epRHS="9.9999999999999995e-07"+   maxIntInfeas="0"+   maxPrimalInfeas="0"+   maxX="2"+   maxSlack="0"/>+ <linearConstraints>+  <constraint name="c1" index="0" slack="0"/>+ </linearConstraints>+ <variables>+  <variable name="x" index="0" value="1"/>+  <variable name="y" index="1" value="2"/>+ </variables>+</CPLEXSolution>
+ samples/lp/test-solution-cplex.sol view
@@ -0,0 +1,36 @@+<?xml version = "1.0" encoding="UTF-8" standalone="yes"?>+<CPLEXSolution version="1.2">+ <header+   problemName="samples/lp/test.lp"+   solutionName="incumbent"+   solutionIndex="-1"+   objectiveValue="122.5"+   solutionTypeValue="3"+   solutionTypeString="primal"+   solutionStatusValue="101"+   solutionStatusString="integer optimal solution"+   solutionMethodString="mip"+   primalFeasible="1"+   dualFeasible="1"+   MIPNodes="0"+   MIPIterations="3"+   writeLevel="1"/>+ <quality+   epInt="1.0000000000000001e-05"+   epRHS="9.9999999999999995e-07"+   maxIntInfeas="0"+   maxPrimalInfeas="0"+   maxX="40"+   maxSlack="2"/>+ <linearConstraints>+  <constraint name="c1" index="0" slack="0"/>+  <constraint name="c2" index="1" slack="2"/>+  <constraint name="c3" index="2" slack="0"/>+ </linearConstraints>+ <variables>+  <variable name="x1" index="0" value="40"/>+  <variable name="x2" index="1" value="10.5"/>+  <variable name="x3" index="2" value="19.5"/>+  <variable name="x4" index="3" value="3"/>+ </variables>+</CPLEXSolution>
+ samples/lp/test-solution-glpk-infeasible.sol view
@@ -0,0 +1,30 @@+Problem:    +Rows:       3+Columns:    3 (3 integer, 0 binary)+Non-zeros:  5+Status:     INTEGER EMPTY+Objective:  obj = 0 (MINimum)++   No.   Row name        Activity     Lower bound   Upper bound+------ ------------    ------------- ------------- -------------+     1 r.4                         0             0             = +     2 r.5                         0             1               +     3 r.6                         0                           2 ++   No. Column name       Activity     Lower bound   Upper bound+------ ------------    ------------- ------------- -------------+     1 x            *              0                             +     2 y            *              0                             +     3 z            *              0             0               ++Integer feasibility conditions:++KKT.PE: max.abs.err = 0.00e+00 on row 0+        max.rel.err = 0.00e+00 on row 0+        High quality++KKT.PB: max.abs.err = 1.00e+00 on row 2+        max.rel.err = 5.00e-01 on row 2+        SOLUTION IS INFEASIBLE++End of output
+ samples/lp/test-solution-glpk-long.sol view
@@ -0,0 +1,32 @@+Problem:    +Rows:       3+Columns:    4 (1 integer, 0 binary)+Non-zeros:  9+Status:     INTEGER OPTIMAL+Objective:  obj = 122.5 (MAXimum)++   No.   Row name        Activity     Lower bound   Upper bound+------ ------------    ------------- ------------- -------------+     1 c1                         20                          20 +     2 c2                         28                          30 +     3 c3                          0             0             = ++   No. Column name       Activity     Lower bound   Upper bound+------ ------------    ------------- ------------- -------------+     1 x1AAAAAAAAAAAAAAAAAAAAAAAAAAAA+                                  40             0            40 +     2 x2                       10.5             0               +     3 x3                       19.5             0               +     4 x4           *              3             2             3 ++Integer feasibility conditions:++KKT.PE: max.abs.err = 0.00e+00 on row 0+        max.rel.err = 0.00e+00 on row 0+        High quality++KKT.PB: max.abs.err = 0.00e+00 on row 0+        max.rel.err = 0.00e+00 on row 0+        High quality++End of output
+ samples/lp/test-solution-glpk-unbounded.sol view
@@ -0,0 +1,27 @@+Problem:    +Rows:       1+Columns:    2 (2 integer, 0 binary)+Non-zeros:  2+Status:     INTEGER UNDEFINED+Objective:  obj = 0 (MAXimum)++   No.   Row name        Activity     Lower bound   Upper bound+------ ------------    ------------- ------------- -------------+     1 c1                          0             0               ++   No. Column name       Activity     Lower bound   Upper bound+------ ------------    ------------- ------------- -------------+     1 x            *              0             1               +     2 y            *              0             0               ++Integer feasibility conditions:++KKT.PE: max.abs.err = 0.00e+00 on row 0+        max.rel.err = 0.00e+00 on row 0+        High quality++KKT.PB: max.abs.err = 1.00e+00 on column 1+        max.rel.err = 5.00e-01 on column 1+        SOLUTION IS INFEASIBLE++End of output
+ samples/lp/test-solution-glpk.sol view
@@ -0,0 +1,31 @@+Problem:    +Rows:       3+Columns:    4 (1 integer, 0 binary)+Non-zeros:  9+Status:     INTEGER OPTIMAL+Objective:  obj = 122.5 (MAXimum)++   No.   Row name        Activity     Lower bound   Upper bound+------ ------------    ------------- ------------- -------------+     1 c1                         20                          20 +     2 c2                         28                          30 +     3 c3                          0             0             = ++   No. Column name       Activity     Lower bound   Upper bound+------ ------------    ------------- ------------- -------------+     1 x1                         40             0            40 +     2 x2                       10.5             0               +     3 x3                       19.5             0               +     4 x4           *              3             2             3 ++Integer feasibility conditions:++KKT.PE: max.abs.err = 0.00e+00 on row 0+        max.rel.err = 0.00e+00 on row 0+        High quality++KKT.PB: max.abs.err = 0.00e+00 on row 0+        max.rel.err = 0.00e+00 on row 0+        High quality++End of output
+ samples/lp/test-solution-gurobi.sol view
@@ -0,0 +1,6 @@+# Solution for model obj+# Objective value = 1.2250000000000006e+02+x1 40+x2 10.5+x3 1.9500000000000018e+01+x4 3
+ samples/lp/test-solution-scip.sol view
@@ -0,0 +1,6 @@+solution status: optimal solution found+objective value:                                122.5+x4                                                  3 	(obj:1)+x2                                               10.5 	(obj:2)+x3                                               19.5 	(obj:3)+x1                                                 40 	(obj:1)
+ samples/pbo/normalized-aries-da_network_20_2__17_12.opb view
@@ -0,0 +1,27 @@+* #variable= 58 #constraint= 20+****************************************+* begin normalizer comments+* category= OPT-BIGINT-LIN+* end normalizer comments+****************************************+min: +59982 x1 +55215 x2 +27972 x3 +45814 x4 +85690 x5 +10866 x6 +56247 x7 +94409 x8 +93132 x9 +10000 x10 +57425 x11 +63903 x12 +7469 x13 +25324 x14 +28114 x15 +71903 x16 +49195 x17 +53990 x18 +23416 x19 +20338 x20 +41747 x21 +10462 x22 +63146 x23 +60697 x24 +64740 x25 +60744 x26 +16925 x27 +72461 x28 +45951 x29 +18133 x30 +48667 x31 +8301 x32 +89878 x33 +31689 x34 +1005 x35 +61803 x36 +28382 x37 +49214 x38 +14903 x39 +15310 x40 ;++1 x31 +1 x32 = 1 ;++1 x21 +1 x22 +1 x23 = 1 ;+-2 x41 +1 x1 +1 x3 +1 x5 +1 x19 +1 x21 +1 x27 +1 x37 +1 x38 = 0 ;+-2 x42 +1 x2 +1 x6 +1 x10 +1 x11 +1 x16 +1 x25 +1 x39 +1 x40 = 0 ;+-2 x43 +1 x1 +1 x2 +1 x4 +1 x24 +1 x28 +1 x29 +1 x33 = 0 ;+-2 x44 +1 x3 +1 x4 +1 x7 +1 x14 +1 x26 = 0 ;+-2 x45 +1 x5 +1 x6 +1 x8 = 0 ;+-2 x46 +1 x7 +1 x8 +1 x9 +1 x12 +1 x15 +1 x32 +1 x34 +1 x37 = 0 ;+-2 x47 +1 x9 +1 x10 = 0 ;+-2 x48 +1 x11 +1 x12 +1 x13 +1 x18 +1 x20 = 0 ;+-2 x49 +1 x13 +1 x14 +1 x17 +1 x30 = 0 ;+-2 x50 +1 x15 +1 x16 +1 x22 +1 x38 = 0 ;+-2 x51 +1 x17 +1 x18 = 0 ;+-2 x52 +1 x19 +1 x20 = 0 ;+-2 x53 +1 x23 +1 x24 +1 x35 +1 x40 = 0 ;+-2 x54 +1 x25 +1 x26 = 0 ;+-2 x55 +1 x27 +1 x28 = 0 ;+-2 x56 +1 x29 +1 x30 +1 x31 +1 x36 = 0 ;+-2 x57 +1 x33 +1 x34 = 0 ;+-2 x58 +1 x35 +1 x36 +1 x39 = 0 ;
+ samples/pbo/normalized-aries-da_network_50_2__8_45__128.opb view
@@ -0,0 +1,157 @@+* #variable= 12848 #constraint= 150+****************************************+* begin normalizer comments+* category= OPT-BIGINT-LIN+* end normalizer comments+****************************************+min: +43197 x1 +43197 x2 +43197 x3 +43197 x4 +43197 x5 +43197 x6 +43197 x7 +43197 x8 +43197 x9 +43197 x10 +43197 x11 +43197 x12 +43197 x13 +43197 x14 +43197 x15 +43197 x16 +43197 x17 +43197 x18 +43197 x19 +43197 x20 +43197 x21 +43197 x22 +43197 x23 +43197 x24 +43197 x25 +43197 x26 +43197 x27 +43197 x28 +43197 x29 +43197 x30 +43197 x31 +43197 x32 +43197 x33 +43197 x34 +43197 x35 +43197 x36 +43197 x37 +43197 x38 +43197 x39 +43197 x40 +43197 x41 +43197 x42 +43197 x43 +43197 x44 +43197 x45 +43197 x46 +43197 x47 +43197 x48 +43197 x49 +43197 x50 +43197 x51 +43197 x52 +43197 x53 +43197 x54 +43197 x55 +43197 x56 +43197 x57 +43197 x58 +43197 x59 +43197 x60 +43197 x61 +43197 x62 +43197 x63 +43197 x64 +43197 x65 +43197 x66 +43197 x67 +43197 x68 +43197 x69 +43197 x70 +43197 x71 +43197 x72 +43197 x73 +43197 x74 +43197 x75 +43197 x76 +43197 x77 +43197 x78 +43197 x79 +43197 x80 +43197 x81 +43197 x82 +43197 x83 +43197 x84 +43197 x85 +43197 x86 +43197 x87 +43197 x88 +43197 x89 +43197 x90 +43197 x91 +43197 x92 +43197 x93 +43197 x94 +43197 x95 +43197 x96 +43197 x97 +43197 x98 +43197 x99 +43197 x100 +43197 x101 +43197 x102 +43197 x103 +43197 x104 +43197 x105 +43197 x106 +43197 x107 +43197 x108 +43197 x109 +43197 x110 +43197 x111 +43197 x112 +43197 x113 +43197 x114 +43197 x115 +43197 x116 +43197 x117 +43197 x118 +43197 x119 +43197 x120 +43197 x121 +43197 x122 +43197 x123 +43197 x124 +43197 x125 +43197 x126 +43197 x127 +43197 x128 +80478 x129 +80478 x130 +80478 x131 +80478 x132 +80478 x133 +80478 x134 +80478 x135 +80478 x136 +80478 x137 +80478 x138 +80478 x139 +80478 x140 +80478 x141 +80478 x142 +80478 x143 +80478 x144 +80478 x145 +80478 x146 +80478 x147 +80478 x148 +80478 x149 +80478 x150 +80478 x151 +80478 x152 +80478 x153 +80478 x154 +80478 x155 +80478 x156 +80478 x157 +80478 x158 +80478 x159 +80478 x160 +80478 x161 +80478 x162 +80478 x163 +80478 x164 +80478 x165 +80478 x166 +80478 x167 +80478 x168 +80478 x169 +80478 x170 +80478 x171 +80478 x172 +80478 x173 +80478 x174 +80478 x175 +80478 x176 +80478 x177 +80478 x178 +80478 x179 +80478 x180 +80478 x181 +80478 x182 +80478 x183 +80478 x184 +80478 x185 +80478 x186 +80478 x187 +80478 x188 +80478 x189 +80478 x190 +80478 x191 +80478 x192 +80478 x193 +80478 x194 +80478 x195 +80478 x196 +80478 x197 +80478 x198 +80478 x199 +80478 x200 +80478 x201 +80478 x202 +80478 x203 +80478 x204 +80478 x205 +80478 x206 +80478 x207 +80478 x208 +80478 x209 +80478 x210 +80478 x211 +80478 x212 +80478 x213 +80478 x214 +80478 x215 +80478 x216 +80478 x217 +80478 x218 +80478 x219 +80478 x220 +80478 x221 +80478 x222 +80478 x223 +80478 x224 +80478 x225 +80478 x226 +80478 x227 +80478 x228 +80478 x229 +80478 x230 +80478 x231 +80478 x232 +80478 x233 +80478 x234 +80478 x235 +80478 x236 +80478 x237 +80478 x238 +80478 x239 +80478 x240 +80478 x241 +80478 x242 +80478 x243 +80478 x244 +80478 x245 +80478 x246 +80478 x247 +80478 x248 +80478 x249 +80478 x250 +80478 x251 +80478 x252 +80478 x253 +80478 x254 +80478 x255 +80478 x256 +19488 x257 +19488 x258 +19488 x259 +19488 x260 +19488 x261 +19488 x262 +19488 x263 +19488 x264 +19488 x265 +19488 x266 +19488 x267 +19488 x268 +19488 x269 +19488 x270 +19488 x271 +19488 x272 +19488 x273 +19488 x274 +19488 x275 +19488 x276 +19488 x277 +19488 x278 +19488 x279 +19488 x280 +19488 x281 +19488 x282 +19488 x283 +19488 x284 +19488 x285 +19488 x286 +19488 x287 +19488 x288 +19488 x289 +19488 x290 +19488 x291 +19488 x292 +19488 x293 +19488 x294 +19488 x295 +19488 x296 +19488 x297 +19488 x298 +19488 x299 +19488 x300 +19488 x301 +19488 x302 +19488 x303 +19488 x304 +19488 x305 +19488 x306 +19488 x307 +19488 x308 +19488 x309 +19488 x310 +19488 x311 +19488 x312 +19488 x313 +19488 x314 +19488 x315 +19488 x316 +19488 x317 +19488 x318 +19488 x319 +19488 x320 +19488 x321 +19488 x322 +19488 x323 +19488 x324 +19488 x325 +19488 x326 +19488 x327 +19488 x328 +19488 x329 +19488 x330 +19488 x331 +19488 x332 +19488 x333 +19488 x334 +19488 x335 +19488 x336 +19488 x337 +19488 x338 +19488 x339 +19488 x340 +19488 x341 +19488 x342 +19488 x343 +19488 x344 +19488 x345 +19488 x346 +19488 x347 +19488 x348 +19488 x349 +19488 x350 +19488 x351 +19488 x352 +19488 x353 +19488 x354 +19488 x355 +19488 x356 +19488 x357 +19488 x358 +19488 x359 +19488 x360 +19488 x361 +19488 x362 +19488 x363 +19488 x364 +19488 x365 +19488 x366 +19488 x367 +19488 x368 +19488 x369 +19488 x370 +19488 x371 +19488 x372 +19488 x373 +19488 x374 +19488 x375 +19488 x376 +19488 x377 +19488 x378 +19488 x379 +19488 x380 +19488 x381 +19488 x382 +19488 x383 +19488 x384 +63597 x385 +63597 x386 +63597 x387 +63597 x388 +63597 x389 +63597 x390 +63597 x391 +63597 x392 +63597 x393 +63597 x394 +63597 x395 +63597 x396 +63597 x397 +63597 x398 +63597 x399 +63597 x400 +63597 x401 +63597 x402 +63597 x403 +63597 x404 +63597 x405 +63597 x406 +63597 x407 +63597 x408 +63597 x409 +63597 x410 +63597 x411 +63597 x412 +63597 x413 +63597 x414 +63597 x415 +63597 x416 +63597 x417 +63597 x418 +63597 x419 +63597 x420 +63597 x421 +63597 x422 +63597 x423 +63597 x424 +63597 x425 +63597 x426 +63597 x427 +63597 x428 +63597 x429 +63597 x430 +63597 x431 +63597 x432 +63597 x433 +63597 x434 +63597 x435 +63597 x436 +63597 x437 +63597 x438 +63597 x439 +63597 x440 +63597 x441 +63597 x442 +63597 x443 +63597 x444 +63597 x445 +63597 x446 +63597 x447 +63597 x448 +63597 x449 +63597 x450 +63597 x451 +63597 x452 +63597 x453 +63597 x454 +63597 x455 +63597 x456 +63597 x457 +63597 x458 +63597 x459 +63597 x460 +63597 x461 +63597 x462 +63597 x463 +63597 x464 +63597 x465 +63597 x466 +63597 x467 +63597 x468 +63597 x469 +63597 x470 +63597 x471 +63597 x472 +63597 x473 +63597 x474 +63597 x475 +63597 x476 +63597 x477 +63597 x478 +63597 x479 +63597 x480 +63597 x481 +63597 x482 +63597 x483 +63597 x484 +63597 x485 +63597 x486 +63597 x487 +63597 x488 +63597 x489 +63597 x490 +63597 x491 +63597 x492 +63597 x493 +63597 x494 +63597 x495 +63597 x496 +63597 x497 +63597 x498 +63597 x499 +63597 x500 +63597 x501 +63597 x502 +63597 x503 +63597 x504 +63597 x505 +63597 x506 +63597 x507 +63597 x508 +63597 x509 +63597 x510 +63597 x511 +63597 x512 +29557 x513 +29557 x514 +29557 x515 +29557 x516 +29557 x517 +29557 x518 +29557 x519 +29557 x520 +29557 x521 +29557 x522 +29557 x523 +29557 x524 +29557 x525 +29557 x526 +29557 x527 +29557 x528 +29557 x529 +29557 x530 +29557 x531 +29557 x532 +29557 x533 +29557 x534 +29557 x535 +29557 x536 +29557 x537 +29557 x538 +29557 x539 +29557 x540 +29557 x541 +29557 x542 +29557 x543 +29557 x544 +29557 x545 +29557 x546 +29557 x547 +29557 x548 +29557 x549 +29557 x550 +29557 x551 +29557 x552 +29557 x553 +29557 x554 +29557 x555 +29557 x556 +29557 x557 +29557 x558 +29557 x559 +29557 x560 +29557 x561 +29557 x562 +29557 x563 +29557 x564 +29557 x565 +29557 x566 +29557 x567 +29557 x568 +29557 x569 +29557 x570 +29557 x571 +29557 x572 +29557 x573 +29557 x574 +29557 x575 +29557 x576 +29557 x577 +29557 x578 +29557 x579 +29557 x580 +29557 x581 +29557 x582 +29557 x583 +29557 x584 +29557 x585 +29557 x586 +29557 x587 +29557 x588 +29557 x589 +29557 x590 +29557 x591 +29557 x592 +29557 x593 +29557 x594 +29557 x595 +29557 x596 +29557 x597 +29557 x598 +29557 x599 +29557 x600 +29557 x601 +29557 x602 +29557 x603 +29557 x604 +29557 x605 +29557 x606 +29557 x607 +29557 x608 +29557 x609 +29557 x610 +29557 x611 +29557 x612 +29557 x613 +29557 x614 +29557 x615 +29557 x616 +29557 x617 +29557 x618 +29557 x619 +29557 x620 +29557 x621 +29557 x622 +29557 x623 +29557 x624 +29557 x625 +29557 x626 +29557 x627 +29557 x628 +29557 x629 +29557 x630 +29557 x631 +29557 x632 +29557 x633 +29557 x634 +29557 x635 +29557 x636 +29557 x637 +29557 x638 +29557 x639 +29557 x640 +88301 x641 +88301 x642 +88301 x643 +88301 x644 +88301 x645 +88301 x646 +88301 x647 +88301 x648 +88301 x649 +88301 x650 +88301 x651 +88301 x652 +88301 x653 +88301 x654 +88301 x655 +88301 x656 +88301 x657 +88301 x658 +88301 x659 +88301 x660 +88301 x661 +88301 x662 +88301 x663 +88301 x664 +88301 x665 +88301 x666 +88301 x667 +88301 x668 +88301 x669 +88301 x670 +88301 x671 +88301 x672 +88301 x673 +88301 x674 +88301 x675 +88301 x676 +88301 x677 +88301 x678 +88301 x679 +88301 x680 +88301 x681 +88301 x682 +88301 x683 +88301 x684 +88301 x685 +88301 x686 +88301 x687 +88301 x688 +88301 x689 +88301 x690 +88301 x691 +88301 x692 +88301 x693 +88301 x694 +88301 x695 +88301 x696 +88301 x697 +88301 x698 +88301 x699 +88301 x700 +88301 x701 +88301 x702 +88301 x703 +88301 x704 +88301 x705 +88301 x706 +88301 x707 +88301 x708 +88301 x709 +88301 x710 +88301 x711 +88301 x712 +88301 x713 +88301 x714 +88301 x715 +88301 x716 +88301 x717 +88301 x718 +88301 x719 +88301 x720 +88301 x721 +88301 x722 +88301 x723 +88301 x724 +88301 x725 +88301 x726 +88301 x727 +88301 x728 +88301 x729 +88301 x730 +88301 x731 +88301 x732 +88301 x733 +88301 x734 +88301 x735 +88301 x736 +88301 x737 +88301 x738 +88301 x739 +88301 x740 +88301 x741 +88301 x742 +88301 x743 +88301 x744 +88301 x745 +88301 x746 +88301 x747 +88301 x748 +88301 x749 +88301 x750 +88301 x751 +88301 x752 +88301 x753 +88301 x754 +88301 x755 +88301 x756 +88301 x757 +88301 x758 +88301 x759 +88301 x760 +88301 x761 +88301 x762 +88301 x763 +88301 x764 +88301 x765 +88301 x766 +88301 x767 +88301 x768 +52567 x769 +52567 x770 +52567 x771 +52567 x772 +52567 x773 +52567 x774 +52567 x775 +52567 x776 +52567 x777 +52567 x778 +52567 x779 +52567 x780 +52567 x781 +52567 x782 +52567 x783 +52567 x784 +52567 x785 +52567 x786 +52567 x787 +52567 x788 +52567 x789 +52567 x790 +52567 x791 +52567 x792 +52567 x793 +52567 x794 +52567 x795 +52567 x796 +52567 x797 +52567 x798 +52567 x799 +52567 x800 +52567 x801 +52567 x802 +52567 x803 +52567 x804 +52567 x805 +52567 x806 +52567 x807 +52567 x808 +52567 x809 +52567 x810 +52567 x811 +52567 x812 +52567 x813 +52567 x814 +52567 x815 +52567 x816 +52567 x817 +52567 x818 +52567 x819 +52567 x820 +52567 x821 +52567 x822 +52567 x823 +52567 x824 +52567 x825 +52567 x826 +52567 x827 +52567 x828 +52567 x829 +52567 x830 +52567 x831 +52567 x832 +52567 x833 +52567 x834 +52567 x835 +52567 x836 +52567 x837 +52567 x838 +52567 x839 +52567 x840 +52567 x841 +52567 x842 +52567 x843 +52567 x844 +52567 x845 +52567 x846 +52567 x847 +52567 x848 +52567 x849 +52567 x850 +52567 x851 +52567 x852 +52567 x853 +52567 x854 +52567 x855 +52567 x856 +52567 x857 +52567 x858 +52567 x859 +52567 x860 +52567 x861 +52567 x862 +52567 x863 +52567 x864 +52567 x865 +52567 x866 +52567 x867 +52567 x868 +52567 x869 +52567 x870 +52567 x871 +52567 x872 +52567 x873 +52567 x874 +52567 x875 +52567 x876 +52567 x877 +52567 x878 +52567 x879 +52567 x880 +52567 x881 +52567 x882 +52567 x883 +52567 x884 +52567 x885 +52567 x886 +52567 x887 +52567 x888 +52567 x889 +52567 x890 +52567 x891 +52567 x892 +52567 x893 +52567 x894 +52567 x895 +52567 x896 +35911 x897 +35911 x898 +35911 x899 +35911 x900 +35911 x901 +35911 x902 +35911 x903 +35911 x904 +35911 x905 +35911 x906 +35911 x907 +35911 x908 +35911 x909 +35911 x910 +35911 x911 +35911 x912 +35911 x913 +35911 x914 +35911 x915 +35911 x916 +35911 x917 +35911 x918 +35911 x919 +35911 x920 +35911 x921 +35911 x922 +35911 x923 +35911 x924 +35911 x925 +35911 x926 +35911 x927 +35911 x928 +35911 x929 +35911 x930 +35911 x931 +35911 x932 +35911 x933 +35911 x934 +35911 x935 +35911 x936 +35911 x937 +35911 x938 +35911 x939 +35911 x940 +35911 x941 +35911 x942 +35911 x943 +35911 x944 +35911 x945 +35911 x946 +35911 x947 +35911 x948 +35911 x949 +35911 x950 +35911 x951 +35911 x952 +35911 x953 +35911 x954 +35911 x955 +35911 x956 +35911 x957 +35911 x958 +35911 x959 +35911 x960 +35911 x961 +35911 x962 +35911 x963 +35911 x964 +35911 x965 +35911 x966 +35911 x967 +35911 x968 +35911 x969 +35911 x970 +35911 x971 +35911 x972 +35911 x973 +35911 x974 +35911 x975 +35911 x976 +35911 x977 +35911 x978 +35911 x979 +35911 x980 +35911 x981 +35911 x982 +35911 x983 +35911 x984 +35911 x985 +35911 x986 +35911 x987 +35911 x988 +35911 x989 +35911 x990 +35911 x991 +35911 x992 +35911 x993 +35911 x994 +35911 x995 +35911 x996 +35911 x997 +35911 x998 +35911 x999 +35911 x1000 +35911 x1001 +35911 x1002 +35911 x1003 +35911 x1004 +35911 x1005 +35911 x1006 +35911 x1007 +35911 x1008 +35911 x1009 +35911 x1010 +35911 x1011 +35911 x1012 +35911 x1013 +35911 x1014 +35911 x1015 +35911 x1016 +35911 x1017 +35911 x1018 +35911 x1019 +35911 x1020 +35911 x1021 +35911 x1022 +35911 x1023 +35911 x1024 +75286 x1025 +75286 x1026 +75286 x1027 +75286 x1028 +75286 x1029 +75286 x1030 +75286 x1031 +75286 x1032 +75286 x1033 +75286 x1034 +75286 x1035 +75286 x1036 +75286 x1037 +75286 x1038 +75286 x1039 +75286 x1040 +75286 x1041 +75286 x1042 +75286 x1043 +75286 x1044 +75286 x1045 +75286 x1046 +75286 x1047 +75286 x1048 +75286 x1049 +75286 x1050 +75286 x1051 +75286 x1052 +75286 x1053 +75286 x1054 +75286 x1055 +75286 x1056 +75286 x1057 +75286 x1058 +75286 x1059 +75286 x1060 +75286 x1061 +75286 x1062 +75286 x1063 +75286 x1064 +75286 x1065 +75286 x1066 +75286 x1067 +75286 x1068 +75286 x1069 +75286 x1070 +75286 x1071 +75286 x1072 +75286 x1073 +75286 x1074 +75286 x1075 +75286 x1076 +75286 x1077 +75286 x1078 +75286 x1079 +75286 x1080 +75286 x1081 +75286 x1082 +75286 x1083 +75286 x1084 +75286 x1085 +75286 x1086 +75286 x1087 +75286 x1088 +75286 x1089 +75286 x1090 +75286 x1091 +75286 x1092 +75286 x1093 +75286 x1094 +75286 x1095 +75286 x1096 +75286 x1097 +75286 x1098 +75286 x1099 +75286 x1100 +75286 x1101 +75286 x1102 +75286 x1103 +75286 x1104 +75286 x1105 +75286 x1106 +75286 x1107 +75286 x1108 +75286 x1109 +75286 x1110 +75286 x1111 +75286 x1112 +75286 x1113 +75286 x1114 +75286 x1115 +75286 x1116 +75286 x1117 +75286 x1118 +75286 x1119 +75286 x1120 +75286 x1121 +75286 x1122 +75286 x1123 +75286 x1124 +75286 x1125 +75286 x1126 +75286 x1127 +75286 x1128 +75286 x1129 +75286 x1130 +75286 x1131 +75286 x1132 +75286 x1133 +75286 x1134 +75286 x1135 +75286 x1136 +75286 x1137 +75286 x1138 +75286 x1139 +75286 x1140 +75286 x1141 +75286 x1142 +75286 x1143 +75286 x1144 +75286 x1145 +75286 x1146 +75286 x1147 +75286 x1148 +75286 x1149 +75286 x1150 +75286 x1151 +75286 x1152 +32089 x1153 +32089 x1154 +32089 x1155 +32089 x1156 +32089 x1157 +32089 x1158 +32089 x1159 +32089 x1160 +32089 x1161 +32089 x1162 +32089 x1163 +32089 x1164 +32089 x1165 +32089 x1166 +32089 x1167 +32089 x1168 +32089 x1169 +32089 x1170 +32089 x1171 +32089 x1172 +32089 x1173 +32089 x1174 +32089 x1175 +32089 x1176 +32089 x1177 +32089 x1178 +32089 x1179 +32089 x1180 +32089 x1181 +32089 x1182 +32089 x1183 +32089 x1184 +32089 x1185 +32089 x1186 +32089 x1187 +32089 x1188 +32089 x1189 +32089 x1190 +32089 x1191 +32089 x1192 +32089 x1193 +32089 x1194 +32089 x1195 +32089 x1196 +32089 x1197 +32089 x1198 +32089 x1199 +32089 x1200 +32089 x1201 +32089 x1202 +32089 x1203 +32089 x1204 +32089 x1205 +32089 x1206 +32089 x1207 +32089 x1208 +32089 x1209 +32089 x1210 +32089 x1211 +32089 x1212 +32089 x1213 +32089 x1214 +32089 x1215 +32089 x1216 +32089 x1217 +32089 x1218 +32089 x1219 +32089 x1220 +32089 x1221 +32089 x1222 +32089 x1223 +32089 x1224 +32089 x1225 +32089 x1226 +32089 x1227 +32089 x1228 +32089 x1229 +32089 x1230 +32089 x1231 +32089 x1232 +32089 x1233 +32089 x1234 +32089 x1235 +32089 x1236 +32089 x1237 +32089 x1238 +32089 x1239 +32089 x1240 +32089 x1241 +32089 x1242 +32089 x1243 +32089 x1244 +32089 x1245 +32089 x1246 +32089 x1247 +32089 x1248 +32089 x1249 +32089 x1250 +32089 x1251 +32089 x1252 +32089 x1253 +32089 x1254 +32089 x1255 +32089 x1256 +32089 x1257 +32089 x1258 +32089 x1259 +32089 x1260 +32089 x1261 +32089 x1262 +32089 x1263 +32089 x1264 +32089 x1265 +32089 x1266 +32089 x1267 +32089 x1268 +32089 x1269 +32089 x1270 +32089 x1271 +32089 x1272 +32089 x1273 +32089 x1274 +32089 x1275 +32089 x1276 +32089 x1277 +32089 x1278 +32089 x1279 +32089 x1280 +39220 x1281 +39220 x1282 +39220 x1283 +39220 x1284 +39220 x1285 +39220 x1286 +39220 x1287 +39220 x1288 +39220 x1289 +39220 x1290 +39220 x1291 +39220 x1292 +39220 x1293 +39220 x1294 +39220 x1295 +39220 x1296 +39220 x1297 +39220 x1298 +39220 x1299 +39220 x1300 +39220 x1301 +39220 x1302 +39220 x1303 +39220 x1304 +39220 x1305 +39220 x1306 +39220 x1307 +39220 x1308 +39220 x1309 +39220 x1310 +39220 x1311 +39220 x1312 +39220 x1313 +39220 x1314 +39220 x1315 +39220 x1316 +39220 x1317 +39220 x1318 +39220 x1319 +39220 x1320 +39220 x1321 +39220 x1322 +39220 x1323 +39220 x1324 +39220 x1325 +39220 x1326 +39220 x1327 +39220 x1328 +39220 x1329 +39220 x1330 +39220 x1331 +39220 x1332 +39220 x1333 +39220 x1334 +39220 x1335 +39220 x1336 +39220 x1337 +39220 x1338 +39220 x1339 +39220 x1340 +39220 x1341 +39220 x1342 +39220 x1343 +39220 x1344 +39220 x1345 +39220 x1346 +39220 x1347 +39220 x1348 +39220 x1349 +39220 x1350 +39220 x1351 +39220 x1352 +39220 x1353 +39220 x1354 +39220 x1355 +39220 x1356 +39220 x1357 +39220 x1358 +39220 x1359 +39220 x1360 +39220 x1361 +39220 x1362 +39220 x1363 +39220 x1364 +39220 x1365 +39220 x1366 +39220 x1367 +39220 x1368 +39220 x1369 +39220 x1370 +39220 x1371 +39220 x1372 +39220 x1373 +39220 x1374 +39220 x1375 +39220 x1376 +39220 x1377 +39220 x1378 +39220 x1379 +39220 x1380 +39220 x1381 +39220 x1382 +39220 x1383 +39220 x1384 +39220 x1385 +39220 x1386 +39220 x1387 +39220 x1388 +39220 x1389 +39220 x1390 +39220 x1391 +39220 x1392 +39220 x1393 +39220 x1394 +39220 x1395 +39220 x1396 +39220 x1397 +39220 x1398 +39220 x1399 +39220 x1400 +39220 x1401 +39220 x1402 +39220 x1403 +39220 x1404 +39220 x1405 +39220 x1406 +39220 x1407 +39220 x1408 +44510 x1409 +44510 x1410 +44510 x1411 +44510 x1412 +44510 x1413 +44510 x1414 +44510 x1415 +44510 x1416 +44510 x1417 +44510 x1418 +44510 x1419 +44510 x1420 +44510 x1421 +44510 x1422 +44510 x1423 +44510 x1424 +44510 x1425 +44510 x1426 +44510 x1427 +44510 x1428 +44510 x1429 +44510 x1430 +44510 x1431 +44510 x1432 +44510 x1433 +44510 x1434 +44510 x1435 +44510 x1436 +44510 x1437 +44510 x1438 +44510 x1439 +44510 x1440 +44510 x1441 +44510 x1442 +44510 x1443 +44510 x1444 +44510 x1445 +44510 x1446 +44510 x1447 +44510 x1448 +44510 x1449 +44510 x1450 +44510 x1451 +44510 x1452 +44510 x1453 +44510 x1454 +44510 x1455 +44510 x1456 +44510 x1457 +44510 x1458 +44510 x1459 +44510 x1460 +44510 x1461 +44510 x1462 +44510 x1463 +44510 x1464 +44510 x1465 +44510 x1466 +44510 x1467 +44510 x1468 +44510 x1469 +44510 x1470 +44510 x1471 +44510 x1472 +44510 x1473 +44510 x1474 +44510 x1475 +44510 x1476 +44510 x1477 +44510 x1478 +44510 x1479 +44510 x1480 +44510 x1481 +44510 x1482 +44510 x1483 +44510 x1484 +44510 x1485 +44510 x1486 +44510 x1487 +44510 x1488 +44510 x1489 +44510 x1490 +44510 x1491 +44510 x1492 +44510 x1493 +44510 x1494 +44510 x1495 +44510 x1496 +44510 x1497 +44510 x1498 +44510 x1499 +44510 x1500 +44510 x1501 +44510 x1502 +44510 x1503 +44510 x1504 +44510 x1505 +44510 x1506 +44510 x1507 +44510 x1508 +44510 x1509 +44510 x1510 +44510 x1511 +44510 x1512 +44510 x1513 +44510 x1514 +44510 x1515 +44510 x1516 +44510 x1517 +44510 x1518 +44510 x1519 +44510 x1520 +44510 x1521 +44510 x1522 +44510 x1523 +44510 x1524 +44510 x1525 +44510 x1526 +44510 x1527 +44510 x1528 +44510 x1529 +44510 x1530 +44510 x1531 +44510 x1532 +44510 x1533 +44510 x1534 +44510 x1535 +44510 x1536 +31557 x1537 +31557 x1538 +31557 x1539 +31557 x1540 +31557 x1541 +31557 x1542 +31557 x1543 +31557 x1544 +31557 x1545 +31557 x1546 +31557 x1547 +31557 x1548 +31557 x1549 +31557 x1550 +31557 x1551 +31557 x1552 +31557 x1553 +31557 x1554 +31557 x1555 +31557 x1556 +31557 x1557 +31557 x1558 +31557 x1559 +31557 x1560 +31557 x1561 +31557 x1562 +31557 x1563 +31557 x1564 +31557 x1565 +31557 x1566 +31557 x1567 +31557 x1568 +31557 x1569 +31557 x1570 +31557 x1571 +31557 x1572 +31557 x1573 +31557 x1574 +31557 x1575 +31557 x1576 +31557 x1577 +31557 x1578 +31557 x1579 +31557 x1580 +31557 x1581 +31557 x1582 +31557 x1583 +31557 x1584 +31557 x1585 +31557 x1586 +31557 x1587 +31557 x1588 +31557 x1589 +31557 x1590 +31557 x1591 +31557 x1592 +31557 x1593 +31557 x1594 +31557 x1595 +31557 x1596 +31557 x1597 +31557 x1598 +31557 x1599 +31557 x1600 +31557 x1601 +31557 x1602 +31557 x1603 +31557 x1604 +31557 x1605 +31557 x1606 +31557 x1607 +31557 x1608 +31557 x1609 +31557 x1610 +31557 x1611 +31557 x1612 +31557 x1613 +31557 x1614 +31557 x1615 +31557 x1616 +31557 x1617 +31557 x1618 +31557 x1619 +31557 x1620 +31557 x1621 +31557 x1622 +31557 x1623 +31557 x1624 +31557 x1625 +31557 x1626 +31557 x1627 +31557 x1628 +31557 x1629 +31557 x1630 +31557 x1631 +31557 x1632 +31557 x1633 +31557 x1634 +31557 x1635 +31557 x1636 +31557 x1637 +31557 x1638 +31557 x1639 +31557 x1640 +31557 x1641 +31557 x1642 +31557 x1643 +31557 x1644 +31557 x1645 +31557 x1646 +31557 x1647 +31557 x1648 +31557 x1649 +31557 x1650 +31557 x1651 +31557 x1652 +31557 x1653 +31557 x1654 +31557 x1655 +31557 x1656 +31557 x1657 +31557 x1658 +31557 x1659 +31557 x1660 +31557 x1661 +31557 x1662 +31557 x1663 +31557 x1664 +20219 x1665 +20219 x1666 +20219 x1667 +20219 x1668 +20219 x1669 +20219 x1670 +20219 x1671 +20219 x1672 +20219 x1673 +20219 x1674 +20219 x1675 +20219 x1676 +20219 x1677 +20219 x1678 +20219 x1679 +20219 x1680 +20219 x1681 +20219 x1682 +20219 x1683 +20219 x1684 +20219 x1685 +20219 x1686 +20219 x1687 +20219 x1688 +20219 x1689 +20219 x1690 +20219 x1691 +20219 x1692 +20219 x1693 +20219 x1694 +20219 x1695 +20219 x1696 +20219 x1697 +20219 x1698 +20219 x1699 +20219 x1700 +20219 x1701 +20219 x1702 +20219 x1703 +20219 x1704 +20219 x1705 +20219 x1706 +20219 x1707 +20219 x1708 +20219 x1709 +20219 x1710 +20219 x1711 +20219 x1712 +20219 x1713 +20219 x1714 +20219 x1715 +20219 x1716 +20219 x1717 +20219 x1718 +20219 x1719 +20219 x1720 +20219 x1721 +20219 x1722 +20219 x1723 +20219 x1724 +20219 x1725 +20219 x1726 +20219 x1727 +20219 x1728 +20219 x1729 +20219 x1730 +20219 x1731 +20219 x1732 +20219 x1733 +20219 x1734 +20219 x1735 +20219 x1736 +20219 x1737 +20219 x1738 +20219 x1739 +20219 x1740 +20219 x1741 +20219 x1742 +20219 x1743 +20219 x1744 +20219 x1745 +20219 x1746 +20219 x1747 +20219 x1748 +20219 x1749 +20219 x1750 +20219 x1751 +20219 x1752 +20219 x1753 +20219 x1754 +20219 x1755 +20219 x1756 +20219 x1757 +20219 x1758 +20219 x1759 +20219 x1760 +20219 x1761 +20219 x1762 +20219 x1763 +20219 x1764 +20219 x1765 +20219 x1766 +20219 x1767 +20219 x1768 +20219 x1769 +20219 x1770 +20219 x1771 +20219 x1772 +20219 x1773 +20219 x1774 +20219 x1775 +20219 x1776 +20219 x1777 +20219 x1778 +20219 x1779 +20219 x1780 +20219 x1781 +20219 x1782 +20219 x1783 +20219 x1784 +20219 x1785 +20219 x1786 +20219 x1787 +20219 x1788 +20219 x1789 +20219 x1790 +20219 x1791 +20219 x1792 +35189 x1793 +35189 x1794 +35189 x1795 +35189 x1796 +35189 x1797 +35189 x1798 +35189 x1799 +35189 x1800 +35189 x1801 +35189 x1802 +35189 x1803 +35189 x1804 +35189 x1805 +35189 x1806 +35189 x1807 +35189 x1808 +35189 x1809 +35189 x1810 +35189 x1811 +35189 x1812 +35189 x1813 +35189 x1814 +35189 x1815 +35189 x1816 +35189 x1817 +35189 x1818 +35189 x1819 +35189 x1820 +35189 x1821 +35189 x1822 +35189 x1823 +35189 x1824 +35189 x1825 +35189 x1826 +35189 x1827 +35189 x1828 +35189 x1829 +35189 x1830 +35189 x1831 +35189 x1832 +35189 x1833 +35189 x1834 +35189 x1835 +35189 x1836 +35189 x1837 +35189 x1838 +35189 x1839 +35189 x1840 +35189 x1841 +35189 x1842 +35189 x1843 +35189 x1844 +35189 x1845 +35189 x1846 +35189 x1847 +35189 x1848 +35189 x1849 +35189 x1850 +35189 x1851 +35189 x1852 +35189 x1853 +35189 x1854 +35189 x1855 +35189 x1856 +35189 x1857 +35189 x1858 +35189 x1859 +35189 x1860 +35189 x1861 +35189 x1862 +35189 x1863 +35189 x1864 +35189 x1865 +35189 x1866 +35189 x1867 +35189 x1868 +35189 x1869 +35189 x1870 +35189 x1871 +35189 x1872 +35189 x1873 +35189 x1874 +35189 x1875 +35189 x1876 +35189 x1877 +35189 x1878 +35189 x1879 +35189 x1880 +35189 x1881 +35189 x1882 +35189 x1883 +35189 x1884 +35189 x1885 +35189 x1886 +35189 x1887 +35189 x1888 +35189 x1889 +35189 x1890 +35189 x1891 +35189 x1892 +35189 x1893 +35189 x1894 +35189 x1895 +35189 x1896 +35189 x1897 +35189 x1898 +35189 x1899 +35189 x1900 +35189 x1901 +35189 x1902 +35189 x1903 +35189 x1904 +35189 x1905 +35189 x1906 +35189 x1907 +35189 x1908 +35189 x1909 +35189 x1910 +35189 x1911 +35189 x1912 +35189 x1913 +35189 x1914 +35189 x1915 +35189 x1916 +35189 x1917 +35189 x1918 +35189 x1919 +35189 x1920 +3581 x1921 +3581 x1922 +3581 x1923 +3581 x1924 +3581 x1925 +3581 x1926 +3581 x1927 +3581 x1928 +3581 x1929 +3581 x1930 +3581 x1931 +3581 x1932 +3581 x1933 +3581 x1934 +3581 x1935 +3581 x1936 +3581 x1937 +3581 x1938 +3581 x1939 +3581 x1940 +3581 x1941 +3581 x1942 +3581 x1943 +3581 x1944 +3581 x1945 +3581 x1946 +3581 x1947 +3581 x1948 +3581 x1949 +3581 x1950 +3581 x1951 +3581 x1952 +3581 x1953 +3581 x1954 +3581 x1955 +3581 x1956 +3581 x1957 +3581 x1958 +3581 x1959 +3581 x1960 +3581 x1961 +3581 x1962 +3581 x1963 +3581 x1964 +3581 x1965 +3581 x1966 +3581 x1967 +3581 x1968 +3581 x1969 +3581 x1970 +3581 x1971 +3581 x1972 +3581 x1973 +3581 x1974 +3581 x1975 +3581 x1976 +3581 x1977 +3581 x1978 +3581 x1979 +3581 x1980 +3581 x1981 +3581 x1982 +3581 x1983 +3581 x1984 +3581 x1985 +3581 x1986 +3581 x1987 +3581 x1988 +3581 x1989 +3581 x1990 +3581 x1991 +3581 x1992 +3581 x1993 +3581 x1994 +3581 x1995 +3581 x1996 +3581 x1997 +3581 x1998 +3581 x1999 +3581 x2000 +3581 x2001 +3581 x2002 +3581 x2003 +3581 x2004 +3581 x2005 +3581 x2006 +3581 x2007 +3581 x2008 +3581 x2009 +3581 x2010 +3581 x2011 +3581 x2012 +3581 x2013 +3581 x2014 +3581 x2015 +3581 x2016 +3581 x2017 +3581 x2018 +3581 x2019 +3581 x2020 +3581 x2021 +3581 x2022 +3581 x2023 +3581 x2024 +3581 x2025 +3581 x2026 +3581 x2027 +3581 x2028 +3581 x2029 +3581 x2030 +3581 x2031 +3581 x2032 +3581 x2033 +3581 x2034 +3581 x2035 +3581 x2036 +3581 x2037 +3581 x2038 +3581 x2039 +3581 x2040 +3581 x2041 +3581 x2042 +3581 x2043 +3581 x2044 +3581 x2045 +3581 x2046 +3581 x2047 +3581 x2048 +42476 x2049 +42476 x2050 +42476 x2051 +42476 x2052 +42476 x2053 +42476 x2054 +42476 x2055 +42476 x2056 +42476 x2057 +42476 x2058 +42476 x2059 +42476 x2060 +42476 x2061 +42476 x2062 +42476 x2063 +42476 x2064 +42476 x2065 +42476 x2066 +42476 x2067 +42476 x2068 +42476 x2069 +42476 x2070 +42476 x2071 +42476 x2072 +42476 x2073 +42476 x2074 +42476 x2075 +42476 x2076 +42476 x2077 +42476 x2078 +42476 x2079 +42476 x2080 +42476 x2081 +42476 x2082 +42476 x2083 +42476 x2084 +42476 x2085 +42476 x2086 +42476 x2087 +42476 x2088 +42476 x2089 +42476 x2090 +42476 x2091 +42476 x2092 +42476 x2093 +42476 x2094 +42476 x2095 +42476 x2096 +42476 x2097 +42476 x2098 +42476 x2099 +42476 x2100 +42476 x2101 +42476 x2102 +42476 x2103 +42476 x2104 +42476 x2105 +42476 x2106 +42476 x2107 +42476 x2108 +42476 x2109 +42476 x2110 +42476 x2111 +42476 x2112 +42476 x2113 +42476 x2114 +42476 x2115 +42476 x2116 +42476 x2117 +42476 x2118 +42476 x2119 +42476 x2120 +42476 x2121 +42476 x2122 +42476 x2123 +42476 x2124 +42476 x2125 +42476 x2126 +42476 x2127 +42476 x2128 +42476 x2129 +42476 x2130 +42476 x2131 +42476 x2132 +42476 x2133 +42476 x2134 +42476 x2135 +42476 x2136 +42476 x2137 +42476 x2138 +42476 x2139 +42476 x2140 +42476 x2141 +42476 x2142 +42476 x2143 +42476 x2144 +42476 x2145 +42476 x2146 +42476 x2147 +42476 x2148 +42476 x2149 +42476 x2150 +42476 x2151 +42476 x2152 +42476 x2153 +42476 x2154 +42476 x2155 +42476 x2156 +42476 x2157 +42476 x2158 +42476 x2159 +42476 x2160 +42476 x2161 +42476 x2162 +42476 x2163 +42476 x2164 +42476 x2165 +42476 x2166 +42476 x2167 +42476 x2168 +42476 x2169 +42476 x2170 +42476 x2171 +42476 x2172 +42476 x2173 +42476 x2174 +42476 x2175 +42476 x2176 +6447 x2177 +6447 x2178 +6447 x2179 +6447 x2180 +6447 x2181 +6447 x2182 +6447 x2183 +6447 x2184 +6447 x2185 +6447 x2186 +6447 x2187 +6447 x2188 +6447 x2189 +6447 x2190 +6447 x2191 +6447 x2192 +6447 x2193 +6447 x2194 +6447 x2195 +6447 x2196 +6447 x2197 +6447 x2198 +6447 x2199 +6447 x2200 +6447 x2201 +6447 x2202 +6447 x2203 +6447 x2204 +6447 x2205 +6447 x2206 +6447 x2207 +6447 x2208 +6447 x2209 +6447 x2210 +6447 x2211 +6447 x2212 +6447 x2213 +6447 x2214 +6447 x2215 +6447 x2216 +6447 x2217 +6447 x2218 +6447 x2219 +6447 x2220 +6447 x2221 +6447 x2222 +6447 x2223 +6447 x2224 +6447 x2225 +6447 x2226 +6447 x2227 +6447 x2228 +6447 x2229 +6447 x2230 +6447 x2231 +6447 x2232 +6447 x2233 +6447 x2234 +6447 x2235 +6447 x2236 +6447 x2237 +6447 x2238 +6447 x2239 +6447 x2240 +6447 x2241 +6447 x2242 +6447 x2243 +6447 x2244 +6447 x2245 +6447 x2246 +6447 x2247 +6447 x2248 +6447 x2249 +6447 x2250 +6447 x2251 +6447 x2252 +6447 x2253 +6447 x2254 +6447 x2255 +6447 x2256 +6447 x2257 +6447 x2258 +6447 x2259 +6447 x2260 +6447 x2261 +6447 x2262 +6447 x2263 +6447 x2264 +6447 x2265 +6447 x2266 +6447 x2267 +6447 x2268 +6447 x2269 +6447 x2270 +6447 x2271 +6447 x2272 +6447 x2273 +6447 x2274 +6447 x2275 +6447 x2276 +6447 x2277 +6447 x2278 +6447 x2279 +6447 x2280 +6447 x2281 +6447 x2282 +6447 x2283 +6447 x2284 +6447 x2285 +6447 x2286 +6447 x2287 +6447 x2288 +6447 x2289 +6447 x2290 +6447 x2291 +6447 x2292 +6447 x2293 +6447 x2294 +6447 x2295 +6447 x2296 +6447 x2297 +6447 x2298 +6447 x2299 +6447 x2300 +6447 x2301 +6447 x2302 +6447 x2303 +6447 x2304 +48580 x2305 +48580 x2306 +48580 x2307 +48580 x2308 +48580 x2309 +48580 x2310 +48580 x2311 +48580 x2312 +48580 x2313 +48580 x2314 +48580 x2315 +48580 x2316 +48580 x2317 +48580 x2318 +48580 x2319 +48580 x2320 +48580 x2321 +48580 x2322 +48580 x2323 +48580 x2324 +48580 x2325 +48580 x2326 +48580 x2327 +48580 x2328 +48580 x2329 +48580 x2330 +48580 x2331 +48580 x2332 +48580 x2333 +48580 x2334 +48580 x2335 +48580 x2336 +48580 x2337 +48580 x2338 +48580 x2339 +48580 x2340 +48580 x2341 +48580 x2342 +48580 x2343 +48580 x2344 +48580 x2345 +48580 x2346 +48580 x2347 +48580 x2348 +48580 x2349 +48580 x2350 +48580 x2351 +48580 x2352 +48580 x2353 +48580 x2354 +48580 x2355 +48580 x2356 +48580 x2357 +48580 x2358 +48580 x2359 +48580 x2360 +48580 x2361 +48580 x2362 +48580 x2363 +48580 x2364 +48580 x2365 +48580 x2366 +48580 x2367 +48580 x2368 +48580 x2369 +48580 x2370 +48580 x2371 +48580 x2372 +48580 x2373 +48580 x2374 +48580 x2375 +48580 x2376 +48580 x2377 +48580 x2378 +48580 x2379 +48580 x2380 +48580 x2381 +48580 x2382 +48580 x2383 +48580 x2384 +48580 x2385 +48580 x2386 +48580 x2387 +48580 x2388 +48580 x2389 +48580 x2390 +48580 x2391 +48580 x2392 +48580 x2393 +48580 x2394 +48580 x2395 +48580 x2396 +48580 x2397 +48580 x2398 +48580 x2399 +48580 x2400 +48580 x2401 +48580 x2402 +48580 x2403 +48580 x2404 +48580 x2405 +48580 x2406 +48580 x2407 +48580 x2408 +48580 x2409 +48580 x2410 +48580 x2411 +48580 x2412 +48580 x2413 +48580 x2414 +48580 x2415 +48580 x2416 +48580 x2417 +48580 x2418 +48580 x2419 +48580 x2420 +48580 x2421 +48580 x2422 +48580 x2423 +48580 x2424 +48580 x2425 +48580 x2426 +48580 x2427 +48580 x2428 +48580 x2429 +48580 x2430 +48580 x2431 +48580 x2432 +37536 x2433 +37536 x2434 +37536 x2435 +37536 x2436 +37536 x2437 +37536 x2438 +37536 x2439 +37536 x2440 +37536 x2441 +37536 x2442 +37536 x2443 +37536 x2444 +37536 x2445 +37536 x2446 +37536 x2447 +37536 x2448 +37536 x2449 +37536 x2450 +37536 x2451 +37536 x2452 +37536 x2453 +37536 x2454 +37536 x2455 +37536 x2456 +37536 x2457 +37536 x2458 +37536 x2459 +37536 x2460 +37536 x2461 +37536 x2462 +37536 x2463 +37536 x2464 +37536 x2465 +37536 x2466 +37536 x2467 +37536 x2468 +37536 x2469 +37536 x2470 +37536 x2471 +37536 x2472 +37536 x2473 +37536 x2474 +37536 x2475 +37536 x2476 +37536 x2477 +37536 x2478 +37536 x2479 +37536 x2480 +37536 x2481 +37536 x2482 +37536 x2483 +37536 x2484 +37536 x2485 +37536 x2486 +37536 x2487 +37536 x2488 +37536 x2489 +37536 x2490 +37536 x2491 +37536 x2492 +37536 x2493 +37536 x2494 +37536 x2495 +37536 x2496 +37536 x2497 +37536 x2498 +37536 x2499 +37536 x2500 +37536 x2501 +37536 x2502 +37536 x2503 +37536 x2504 +37536 x2505 +37536 x2506 +37536 x2507 +37536 x2508 +37536 x2509 +37536 x2510 +37536 x2511 +37536 x2512 +37536 x2513 +37536 x2514 +37536 x2515 +37536 x2516 +37536 x2517 +37536 x2518 +37536 x2519 +37536 x2520 +37536 x2521 +37536 x2522 +37536 x2523 +37536 x2524 +37536 x2525 +37536 x2526 +37536 x2527 +37536 x2528 +37536 x2529 +37536 x2530 +37536 x2531 +37536 x2532 +37536 x2533 +37536 x2534 +37536 x2535 +37536 x2536 +37536 x2537 +37536 x2538 +37536 x2539 +37536 x2540 +37536 x2541 +37536 x2542 +37536 x2543 +37536 x2544 +37536 x2545 +37536 x2546 +37536 x2547 +37536 x2548 +37536 x2549 +37536 x2550 +37536 x2551 +37536 x2552 +37536 x2553 +37536 x2554 +37536 x2555 +37536 x2556 +37536 x2557 +37536 x2558 +37536 x2559 +37536 x2560 +77983 x2561 +77983 x2562 +77983 x2563 +77983 x2564 +77983 x2565 +77983 x2566 +77983 x2567 +77983 x2568 +77983 x2569 +77983 x2570 +77983 x2571 +77983 x2572 +77983 x2573 +77983 x2574 +77983 x2575 +77983 x2576 +77983 x2577 +77983 x2578 +77983 x2579 +77983 x2580 +77983 x2581 +77983 x2582 +77983 x2583 +77983 x2584 +77983 x2585 +77983 x2586 +77983 x2587 +77983 x2588 +77983 x2589 +77983 x2590 +77983 x2591 +77983 x2592 +77983 x2593 +77983 x2594 +77983 x2595 +77983 x2596 +77983 x2597 +77983 x2598 +77983 x2599 +77983 x2600 +77983 x2601 +77983 x2602 +77983 x2603 +77983 x2604 +77983 x2605 +77983 x2606 +77983 x2607 +77983 x2608 +77983 x2609 +77983 x2610 +77983 x2611 +77983 x2612 +77983 x2613 +77983 x2614 +77983 x2615 +77983 x2616 +77983 x2617 +77983 x2618 +77983 x2619 +77983 x2620 +77983 x2621 +77983 x2622 +77983 x2623 +77983 x2624 +77983 x2625 +77983 x2626 +77983 x2627 +77983 x2628 +77983 x2629 +77983 x2630 +77983 x2631 +77983 x2632 +77983 x2633 +77983 x2634 +77983 x2635 +77983 x2636 +77983 x2637 +77983 x2638 +77983 x2639 +77983 x2640 +77983 x2641 +77983 x2642 +77983 x2643 +77983 x2644 +77983 x2645 +77983 x2646 +77983 x2647 +77983 x2648 +77983 x2649 +77983 x2650 +77983 x2651 +77983 x2652 +77983 x2653 +77983 x2654 +77983 x2655 +77983 x2656 +77983 x2657 +77983 x2658 +77983 x2659 +77983 x2660 +77983 x2661 +77983 x2662 +77983 x2663 +77983 x2664 +77983 x2665 +77983 x2666 +77983 x2667 +77983 x2668 +77983 x2669 +77983 x2670 +77983 x2671 +77983 x2672 +77983 x2673 +77983 x2674 +77983 x2675 +77983 x2676 +77983 x2677 +77983 x2678 +77983 x2679 +77983 x2680 +77983 x2681 +77983 x2682 +77983 x2683 +77983 x2684 +77983 x2685 +77983 x2686 +77983 x2687 +77983 x2688 +57463 x2689 +57463 x2690 +57463 x2691 +57463 x2692 +57463 x2693 +57463 x2694 +57463 x2695 +57463 x2696 +57463 x2697 +57463 x2698 +57463 x2699 +57463 x2700 +57463 x2701 +57463 x2702 +57463 x2703 +57463 x2704 +57463 x2705 +57463 x2706 +57463 x2707 +57463 x2708 +57463 x2709 +57463 x2710 +57463 x2711 +57463 x2712 +57463 x2713 +57463 x2714 +57463 x2715 +57463 x2716 +57463 x2717 +57463 x2718 +57463 x2719 +57463 x2720 +57463 x2721 +57463 x2722 +57463 x2723 +57463 x2724 +57463 x2725 +57463 x2726 +57463 x2727 +57463 x2728 +57463 x2729 +57463 x2730 +57463 x2731 +57463 x2732 +57463 x2733 +57463 x2734 +57463 x2735 +57463 x2736 +57463 x2737 +57463 x2738 +57463 x2739 +57463 x2740 +57463 x2741 +57463 x2742 +57463 x2743 +57463 x2744 +57463 x2745 +57463 x2746 +57463 x2747 +57463 x2748 +57463 x2749 +57463 x2750 +57463 x2751 +57463 x2752 +57463 x2753 +57463 x2754 +57463 x2755 +57463 x2756 +57463 x2757 +57463 x2758 +57463 x2759 +57463 x2760 +57463 x2761 +57463 x2762 +57463 x2763 +57463 x2764 +57463 x2765 +57463 x2766 +57463 x2767 +57463 x2768 +57463 x2769 +57463 x2770 +57463 x2771 +57463 x2772 +57463 x2773 +57463 x2774 +57463 x2775 +57463 x2776 +57463 x2777 +57463 x2778 +57463 x2779 +57463 x2780 +57463 x2781 +57463 x2782 +57463 x2783 +57463 x2784 +57463 x2785 +57463 x2786 +57463 x2787 +57463 x2788 +57463 x2789 +57463 x2790 +57463 x2791 +57463 x2792 +57463 x2793 +57463 x2794 +57463 x2795 +57463 x2796 +57463 x2797 +57463 x2798 +57463 x2799 +57463 x2800 +57463 x2801 +57463 x2802 +57463 x2803 +57463 x2804 +57463 x2805 +57463 x2806 +57463 x2807 +57463 x2808 +57463 x2809 +57463 x2810 +57463 x2811 +57463 x2812 +57463 x2813 +57463 x2814 +57463 x2815 +57463 x2816 +27767 x2817 +27767 x2818 +27767 x2819 +27767 x2820 +27767 x2821 +27767 x2822 +27767 x2823 +27767 x2824 +27767 x2825 +27767 x2826 +27767 x2827 +27767 x2828 +27767 x2829 +27767 x2830 +27767 x2831 +27767 x2832 +27767 x2833 +27767 x2834 +27767 x2835 +27767 x2836 +27767 x2837 +27767 x2838 +27767 x2839 +27767 x2840 +27767 x2841 +27767 x2842 +27767 x2843 +27767 x2844 +27767 x2845 +27767 x2846 +27767 x2847 +27767 x2848 +27767 x2849 +27767 x2850 +27767 x2851 +27767 x2852 +27767 x2853 +27767 x2854 +27767 x2855 +27767 x2856 +27767 x2857 +27767 x2858 +27767 x2859 +27767 x2860 +27767 x2861 +27767 x2862 +27767 x2863 +27767 x2864 +27767 x2865 +27767 x2866 +27767 x2867 +27767 x2868 +27767 x2869 +27767 x2870 +27767 x2871 +27767 x2872 +27767 x2873 +27767 x2874 +27767 x2875 +27767 x2876 +27767 x2877 +27767 x2878 +27767 x2879 +27767 x2880 +27767 x2881 +27767 x2882 +27767 x2883 +27767 x2884 +27767 x2885 +27767 x2886 +27767 x2887 +27767 x2888 +27767 x2889 +27767 x2890 +27767 x2891 +27767 x2892 +27767 x2893 +27767 x2894 +27767 x2895 +27767 x2896 +27767 x2897 +27767 x2898 +27767 x2899 +27767 x2900 +27767 x2901 +27767 x2902 +27767 x2903 +27767 x2904 +27767 x2905 +27767 x2906 +27767 x2907 +27767 x2908 +27767 x2909 +27767 x2910 +27767 x2911 +27767 x2912 +27767 x2913 +27767 x2914 +27767 x2915 +27767 x2916 +27767 x2917 +27767 x2918 +27767 x2919 +27767 x2920 +27767 x2921 +27767 x2922 +27767 x2923 +27767 x2924 +27767 x2925 +27767 x2926 +27767 x2927 +27767 x2928 +27767 x2929 +27767 x2930 +27767 x2931 +27767 x2932 +27767 x2933 +27767 x2934 +27767 x2935 +27767 x2936 +27767 x2937 +27767 x2938 +27767 x2939 +27767 x2940 +27767 x2941 +27767 x2942 +27767 x2943 +27767 x2944 +29820 x2945 +29820 x2946 +29820 x2947 +29820 x2948 +29820 x2949 +29820 x2950 +29820 x2951 +29820 x2952 +29820 x2953 +29820 x2954 +29820 x2955 +29820 x2956 +29820 x2957 +29820 x2958 +29820 x2959 +29820 x2960 +29820 x2961 +29820 x2962 +29820 x2963 +29820 x2964 +29820 x2965 +29820 x2966 +29820 x2967 +29820 x2968 +29820 x2969 +29820 x2970 +29820 x2971 +29820 x2972 +29820 x2973 +29820 x2974 +29820 x2975 +29820 x2976 +29820 x2977 +29820 x2978 +29820 x2979 +29820 x2980 +29820 x2981 +29820 x2982 +29820 x2983 +29820 x2984 +29820 x2985 +29820 x2986 +29820 x2987 +29820 x2988 +29820 x2989 +29820 x2990 +29820 x2991 +29820 x2992 +29820 x2993 +29820 x2994 +29820 x2995 +29820 x2996 +29820 x2997 +29820 x2998 +29820 x2999 +29820 x3000 +29820 x3001 +29820 x3002 +29820 x3003 +29820 x3004 +29820 x3005 +29820 x3006 +29820 x3007 +29820 x3008 +29820 x3009 +29820 x3010 +29820 x3011 +29820 x3012 +29820 x3013 +29820 x3014 +29820 x3015 +29820 x3016 +29820 x3017 +29820 x3018 +29820 x3019 +29820 x3020 +29820 x3021 +29820 x3022 +29820 x3023 +29820 x3024 +29820 x3025 +29820 x3026 +29820 x3027 +29820 x3028 +29820 x3029 +29820 x3030 +29820 x3031 +29820 x3032 +29820 x3033 +29820 x3034 +29820 x3035 +29820 x3036 +29820 x3037 +29820 x3038 +29820 x3039 +29820 x3040 +29820 x3041 +29820 x3042 +29820 x3043 +29820 x3044 +29820 x3045 +29820 x3046 +29820 x3047 +29820 x3048 +29820 x3049 +29820 x3050 +29820 x3051 +29820 x3052 +29820 x3053 +29820 x3054 +29820 x3055 +29820 x3056 +29820 x3057 +29820 x3058 +29820 x3059 +29820 x3060 +29820 x3061 +29820 x3062 +29820 x3063 +29820 x3064 +29820 x3065 +29820 x3066 +29820 x3067 +29820 x3068 +29820 x3069 +29820 x3070 +29820 x3071 +29820 x3072 +30864 x3073 +30864 x3074 +30864 x3075 +30864 x3076 +30864 x3077 +30864 x3078 +30864 x3079 +30864 x3080 +30864 x3081 +30864 x3082 +30864 x3083 +30864 x3084 +30864 x3085 +30864 x3086 +30864 x3087 +30864 x3088 +30864 x3089 +30864 x3090 +30864 x3091 +30864 x3092 +30864 x3093 +30864 x3094 +30864 x3095 +30864 x3096 +30864 x3097 +30864 x3098 +30864 x3099 +30864 x3100 +30864 x3101 +30864 x3102 +30864 x3103 +30864 x3104 +30864 x3105 +30864 x3106 +30864 x3107 +30864 x3108 +30864 x3109 +30864 x3110 +30864 x3111 +30864 x3112 +30864 x3113 +30864 x3114 +30864 x3115 +30864 x3116 +30864 x3117 +30864 x3118 +30864 x3119 +30864 x3120 +30864 x3121 +30864 x3122 +30864 x3123 +30864 x3124 +30864 x3125 +30864 x3126 +30864 x3127 +30864 x3128 +30864 x3129 +30864 x3130 +30864 x3131 +30864 x3132 +30864 x3133 +30864 x3134 +30864 x3135 +30864 x3136 +30864 x3137 +30864 x3138 +30864 x3139 +30864 x3140 +30864 x3141 +30864 x3142 +30864 x3143 +30864 x3144 +30864 x3145 +30864 x3146 +30864 x3147 +30864 x3148 +30864 x3149 +30864 x3150 +30864 x3151 +30864 x3152 +30864 x3153 +30864 x3154 +30864 x3155 +30864 x3156 +30864 x3157 +30864 x3158 +30864 x3159 +30864 x3160 +30864 x3161 +30864 x3162 +30864 x3163 +30864 x3164 +30864 x3165 +30864 x3166 +30864 x3167 +30864 x3168 +30864 x3169 +30864 x3170 +30864 x3171 +30864 x3172 +30864 x3173 +30864 x3174 +30864 x3175 +30864 x3176 +30864 x3177 +30864 x3178 +30864 x3179 +30864 x3180 +30864 x3181 +30864 x3182 +30864 x3183 +30864 x3184 +30864 x3185 +30864 x3186 +30864 x3187 +30864 x3188 +30864 x3189 +30864 x3190 +30864 x3191 +30864 x3192 +30864 x3193 +30864 x3194 +30864 x3195 +30864 x3196 +30864 x3197 +30864 x3198 +30864 x3199 +30864 x3200 +30592 x3201 +30592 x3202 +30592 x3203 +30592 x3204 +30592 x3205 +30592 x3206 +30592 x3207 +30592 x3208 +30592 x3209 +30592 x3210 +30592 x3211 +30592 x3212 +30592 x3213 +30592 x3214 +30592 x3215 +30592 x3216 +30592 x3217 +30592 x3218 +30592 x3219 +30592 x3220 +30592 x3221 +30592 x3222 +30592 x3223 +30592 x3224 +30592 x3225 +30592 x3226 +30592 x3227 +30592 x3228 +30592 x3229 +30592 x3230 +30592 x3231 +30592 x3232 +30592 x3233 +30592 x3234 +30592 x3235 +30592 x3236 +30592 x3237 +30592 x3238 +30592 x3239 +30592 x3240 +30592 x3241 +30592 x3242 +30592 x3243 +30592 x3244 +30592 x3245 +30592 x3246 +30592 x3247 +30592 x3248 +30592 x3249 +30592 x3250 +30592 x3251 +30592 x3252 +30592 x3253 +30592 x3254 +30592 x3255 +30592 x3256 +30592 x3257 +30592 x3258 +30592 x3259 +30592 x3260 +30592 x3261 +30592 x3262 +30592 x3263 +30592 x3264 +30592 x3265 +30592 x3266 +30592 x3267 +30592 x3268 +30592 x3269 +30592 x3270 +30592 x3271 +30592 x3272 +30592 x3273 +30592 x3274 +30592 x3275 +30592 x3276 +30592 x3277 +30592 x3278 +30592 x3279 +30592 x3280 +30592 x3281 +30592 x3282 +30592 x3283 +30592 x3284 +30592 x3285 +30592 x3286 +30592 x3287 +30592 x3288 +30592 x3289 +30592 x3290 +30592 x3291 +30592 x3292 +30592 x3293 +30592 x3294 +30592 x3295 +30592 x3296 +30592 x3297 +30592 x3298 +30592 x3299 +30592 x3300 +30592 x3301 +30592 x3302 +30592 x3303 +30592 x3304 +30592 x3305 +30592 x3306 +30592 x3307 +30592 x3308 +30592 x3309 +30592 x3310 +30592 x3311 +30592 x3312 +30592 x3313 +30592 x3314 +30592 x3315 +30592 x3316 +30592 x3317 +30592 x3318 +30592 x3319 +30592 x3320 +30592 x3321 +30592 x3322 +30592 x3323 +30592 x3324 +30592 x3325 +30592 x3326 +30592 x3327 +30592 x3328 +126454 x3329 +126454 x3330 +126454 x3331 +126454 x3332 +126454 x3333 +126454 x3334 +126454 x3335 +126454 x3336 +126454 x3337 +126454 x3338 +126454 x3339 +126454 x3340 +126454 x3341 +126454 x3342 +126454 x3343 +126454 x3344 +126454 x3345 +126454 x3346 +126454 x3347 +126454 x3348 +126454 x3349 +126454 x3350 +126454 x3351 +126454 x3352 +126454 x3353 +126454 x3354 +126454 x3355 +126454 x3356 +126454 x3357 +126454 x3358 +126454 x3359 +126454 x3360 +126454 x3361 +126454 x3362 +126454 x3363 +126454 x3364 +126454 x3365 +126454 x3366 +126454 x3367 +126454 x3368 +126454 x3369 +126454 x3370 +126454 x3371 +126454 x3372 +126454 x3373 +126454 x3374 +126454 x3375 +126454 x3376 +126454 x3377 +126454 x3378 +126454 x3379 +126454 x3380 +126454 x3381 +126454 x3382 +126454 x3383 +126454 x3384 +126454 x3385 +126454 x3386 +126454 x3387 +126454 x3388 +126454 x3389 +126454 x3390 +126454 x3391 +126454 x3392 +126454 x3393 +126454 x3394 +126454 x3395 +126454 x3396 +126454 x3397 +126454 x3398 +126454 x3399 +126454 x3400 +126454 x3401 +126454 x3402 +126454 x3403 +126454 x3404 +126454 x3405 +126454 x3406 +126454 x3407 +126454 x3408 +126454 x3409 +126454 x3410 +126454 x3411 +126454 x3412 +126454 x3413 +126454 x3414 +126454 x3415 +126454 x3416 +126454 x3417 +126454 x3418 +126454 x3419 +126454 x3420 +126454 x3421 +126454 x3422 +126454 x3423 +126454 x3424 +126454 x3425 +126454 x3426 +126454 x3427 +126454 x3428 +126454 x3429 +126454 x3430 +126454 x3431 +126454 x3432 +126454 x3433 +126454 x3434 +126454 x3435 +126454 x3436 +126454 x3437 +126454 x3438 +126454 x3439 +126454 x3440 +126454 x3441 +126454 x3442 +126454 x3443 +126454 x3444 +126454 x3445 +126454 x3446 +126454 x3447 +126454 x3448 +126454 x3449 +126454 x3450 +126454 x3451 +126454 x3452 +126454 x3453 +126454 x3454 +126454 x3455 +126454 x3456 +16588 x3457 +16588 x3458 +16588 x3459 +16588 x3460 +16588 x3461 +16588 x3462 +16588 x3463 +16588 x3464 +16588 x3465 +16588 x3466 +16588 x3467 +16588 x3468 +16588 x3469 +16588 x3470 +16588 x3471 +16588 x3472 +16588 x3473 +16588 x3474 +16588 x3475 +16588 x3476 +16588 x3477 +16588 x3478 +16588 x3479 +16588 x3480 +16588 x3481 +16588 x3482 +16588 x3483 +16588 x3484 +16588 x3485 +16588 x3486 +16588 x3487 +16588 x3488 +16588 x3489 +16588 x3490 +16588 x3491 +16588 x3492 +16588 x3493 +16588 x3494 +16588 x3495 +16588 x3496 +16588 x3497 +16588 x3498 +16588 x3499 +16588 x3500 +16588 x3501 +16588 x3502 +16588 x3503 +16588 x3504 +16588 x3505 +16588 x3506 +16588 x3507 +16588 x3508 +16588 x3509 +16588 x3510 +16588 x3511 +16588 x3512 +16588 x3513 +16588 x3514 +16588 x3515 +16588 x3516 +16588 x3517 +16588 x3518 +16588 x3519 +16588 x3520 +16588 x3521 +16588 x3522 +16588 x3523 +16588 x3524 +16588 x3525 +16588 x3526 +16588 x3527 +16588 x3528 +16588 x3529 +16588 x3530 +16588 x3531 +16588 x3532 +16588 x3533 +16588 x3534 +16588 x3535 +16588 x3536 +16588 x3537 +16588 x3538 +16588 x3539 +16588 x3540 +16588 x3541 +16588 x3542 +16588 x3543 +16588 x3544 +16588 x3545 +16588 x3546 +16588 x3547 +16588 x3548 +16588 x3549 +16588 x3550 +16588 x3551 +16588 x3552 +16588 x3553 +16588 x3554 +16588 x3555 +16588 x3556 +16588 x3557 +16588 x3558 +16588 x3559 +16588 x3560 +16588 x3561 +16588 x3562 +16588 x3563 +16588 x3564 +16588 x3565 +16588 x3566 +16588 x3567 +16588 x3568 +16588 x3569 +16588 x3570 +16588 x3571 +16588 x3572 +16588 x3573 +16588 x3574 +16588 x3575 +16588 x3576 +16588 x3577 +16588 x3578 +16588 x3579 +16588 x3580 +16588 x3581 +16588 x3582 +16588 x3583 +16588 x3584 +23016 x3585 +23016 x3586 +23016 x3587 +23016 x3588 +23016 x3589 +23016 x3590 +23016 x3591 +23016 x3592 +23016 x3593 +23016 x3594 +23016 x3595 +23016 x3596 +23016 x3597 +23016 x3598 +23016 x3599 +23016 x3600 +23016 x3601 +23016 x3602 +23016 x3603 +23016 x3604 +23016 x3605 +23016 x3606 +23016 x3607 +23016 x3608 +23016 x3609 +23016 x3610 +23016 x3611 +23016 x3612 +23016 x3613 +23016 x3614 +23016 x3615 +23016 x3616 +23016 x3617 +23016 x3618 +23016 x3619 +23016 x3620 +23016 x3621 +23016 x3622 +23016 x3623 +23016 x3624 +23016 x3625 +23016 x3626 +23016 x3627 +23016 x3628 +23016 x3629 +23016 x3630 +23016 x3631 +23016 x3632 +23016 x3633 +23016 x3634 +23016 x3635 +23016 x3636 +23016 x3637 +23016 x3638 +23016 x3639 +23016 x3640 +23016 x3641 +23016 x3642 +23016 x3643 +23016 x3644 +23016 x3645 +23016 x3646 +23016 x3647 +23016 x3648 +23016 x3649 +23016 x3650 +23016 x3651 +23016 x3652 +23016 x3653 +23016 x3654 +23016 x3655 +23016 x3656 +23016 x3657 +23016 x3658 +23016 x3659 +23016 x3660 +23016 x3661 +23016 x3662 +23016 x3663 +23016 x3664 +23016 x3665 +23016 x3666 +23016 x3667 +23016 x3668 +23016 x3669 +23016 x3670 +23016 x3671 +23016 x3672 +23016 x3673 +23016 x3674 +23016 x3675 +23016 x3676 +23016 x3677 +23016 x3678 +23016 x3679 +23016 x3680 +23016 x3681 +23016 x3682 +23016 x3683 +23016 x3684 +23016 x3685 +23016 x3686 +23016 x3687 +23016 x3688 +23016 x3689 +23016 x3690 +23016 x3691 +23016 x3692 +23016 x3693 +23016 x3694 +23016 x3695 +23016 x3696 +23016 x3697 +23016 x3698 +23016 x3699 +23016 x3700 +23016 x3701 +23016 x3702 +23016 x3703 +23016 x3704 +23016 x3705 +23016 x3706 +23016 x3707 +23016 x3708 +23016 x3709 +23016 x3710 +23016 x3711 +23016 x3712 +54971 x3713 +54971 x3714 +54971 x3715 +54971 x3716 +54971 x3717 +54971 x3718 +54971 x3719 +54971 x3720 +54971 x3721 +54971 x3722 +54971 x3723 +54971 x3724 +54971 x3725 +54971 x3726 +54971 x3727 +54971 x3728 +54971 x3729 +54971 x3730 +54971 x3731 +54971 x3732 +54971 x3733 +54971 x3734 +54971 x3735 +54971 x3736 +54971 x3737 +54971 x3738 +54971 x3739 +54971 x3740 +54971 x3741 +54971 x3742 +54971 x3743 +54971 x3744 +54971 x3745 +54971 x3746 +54971 x3747 +54971 x3748 +54971 x3749 +54971 x3750 +54971 x3751 +54971 x3752 +54971 x3753 +54971 x3754 +54971 x3755 +54971 x3756 +54971 x3757 +54971 x3758 +54971 x3759 +54971 x3760 +54971 x3761 +54971 x3762 +54971 x3763 +54971 x3764 +54971 x3765 +54971 x3766 +54971 x3767 +54971 x3768 +54971 x3769 +54971 x3770 +54971 x3771 +54971 x3772 +54971 x3773 +54971 x3774 +54971 x3775 +54971 x3776 +54971 x3777 +54971 x3778 +54971 x3779 +54971 x3780 +54971 x3781 +54971 x3782 +54971 x3783 +54971 x3784 +54971 x3785 +54971 x3786 +54971 x3787 +54971 x3788 +54971 x3789 +54971 x3790 +54971 x3791 +54971 x3792 +54971 x3793 +54971 x3794 +54971 x3795 +54971 x3796 +54971 x3797 +54971 x3798 +54971 x3799 +54971 x3800 +54971 x3801 +54971 x3802 +54971 x3803 +54971 x3804 +54971 x3805 +54971 x3806 +54971 x3807 +54971 x3808 +54971 x3809 +54971 x3810 +54971 x3811 +54971 x3812 +54971 x3813 +54971 x3814 +54971 x3815 +54971 x3816 +54971 x3817 +54971 x3818 +54971 x3819 +54971 x3820 +54971 x3821 +54971 x3822 +54971 x3823 +54971 x3824 +54971 x3825 +54971 x3826 +54971 x3827 +54971 x3828 +54971 x3829 +54971 x3830 +54971 x3831 +54971 x3832 +54971 x3833 +54971 x3834 +54971 x3835 +54971 x3836 +54971 x3837 +54971 x3838 +54971 x3839 +54971 x3840 +14819 x3841 +14819 x3842 +14819 x3843 +14819 x3844 +14819 x3845 +14819 x3846 +14819 x3847 +14819 x3848 +14819 x3849 +14819 x3850 +14819 x3851 +14819 x3852 +14819 x3853 +14819 x3854 +14819 x3855 +14819 x3856 +14819 x3857 +14819 x3858 +14819 x3859 +14819 x3860 +14819 x3861 +14819 x3862 +14819 x3863 +14819 x3864 +14819 x3865 +14819 x3866 +14819 x3867 +14819 x3868 +14819 x3869 +14819 x3870 +14819 x3871 +14819 x3872 +14819 x3873 +14819 x3874 +14819 x3875 +14819 x3876 +14819 x3877 +14819 x3878 +14819 x3879 +14819 x3880 +14819 x3881 +14819 x3882 +14819 x3883 +14819 x3884 +14819 x3885 +14819 x3886 +14819 x3887 +14819 x3888 +14819 x3889 +14819 x3890 +14819 x3891 +14819 x3892 +14819 x3893 +14819 x3894 +14819 x3895 +14819 x3896 +14819 x3897 +14819 x3898 +14819 x3899 +14819 x3900 +14819 x3901 +14819 x3902 +14819 x3903 +14819 x3904 +14819 x3905 +14819 x3906 +14819 x3907 +14819 x3908 +14819 x3909 +14819 x3910 +14819 x3911 +14819 x3912 +14819 x3913 +14819 x3914 +14819 x3915 +14819 x3916 +14819 x3917 +14819 x3918 +14819 x3919 +14819 x3920 +14819 x3921 +14819 x3922 +14819 x3923 +14819 x3924 +14819 x3925 +14819 x3926 +14819 x3927 +14819 x3928 +14819 x3929 +14819 x3930 +14819 x3931 +14819 x3932 +14819 x3933 +14819 x3934 +14819 x3935 +14819 x3936 +14819 x3937 +14819 x3938 +14819 x3939 +14819 x3940 +14819 x3941 +14819 x3942 +14819 x3943 +14819 x3944 +14819 x3945 +14819 x3946 +14819 x3947 +14819 x3948 +14819 x3949 +14819 x3950 +14819 x3951 +14819 x3952 +14819 x3953 +14819 x3954 +14819 x3955 +14819 x3956 +14819 x3957 +14819 x3958 +14819 x3959 +14819 x3960 +14819 x3961 +14819 x3962 +14819 x3963 +14819 x3964 +14819 x3965 +14819 x3966 +14819 x3967 +14819 x3968 +22299 x3969 +22299 x3970 +22299 x3971 +22299 x3972 +22299 x3973 +22299 x3974 +22299 x3975 +22299 x3976 +22299 x3977 +22299 x3978 +22299 x3979 +22299 x3980 +22299 x3981 +22299 x3982 +22299 x3983 +22299 x3984 +22299 x3985 +22299 x3986 +22299 x3987 +22299 x3988 +22299 x3989 +22299 x3990 +22299 x3991 +22299 x3992 +22299 x3993 +22299 x3994 +22299 x3995 +22299 x3996 +22299 x3997 +22299 x3998 +22299 x3999 +22299 x4000 +22299 x4001 +22299 x4002 +22299 x4003 +22299 x4004 +22299 x4005 +22299 x4006 +22299 x4007 +22299 x4008 +22299 x4009 +22299 x4010 +22299 x4011 +22299 x4012 +22299 x4013 +22299 x4014 +22299 x4015 +22299 x4016 +22299 x4017 +22299 x4018 +22299 x4019 +22299 x4020 +22299 x4021 +22299 x4022 +22299 x4023 +22299 x4024 +22299 x4025 +22299 x4026 +22299 x4027 +22299 x4028 +22299 x4029 +22299 x4030 +22299 x4031 +22299 x4032 +22299 x4033 +22299 x4034 +22299 x4035 +22299 x4036 +22299 x4037 +22299 x4038 +22299 x4039 +22299 x4040 +22299 x4041 +22299 x4042 +22299 x4043 +22299 x4044 +22299 x4045 +22299 x4046 +22299 x4047 +22299 x4048 +22299 x4049 +22299 x4050 +22299 x4051 +22299 x4052 +22299 x4053 +22299 x4054 +22299 x4055 +22299 x4056 +22299 x4057 +22299 x4058 +22299 x4059 +22299 x4060 +22299 x4061 +22299 x4062 +22299 x4063 +22299 x4064 +22299 x4065 +22299 x4066 +22299 x4067 +22299 x4068 +22299 x4069 +22299 x4070 +22299 x4071 +22299 x4072 +22299 x4073 +22299 x4074 +22299 x4075 +22299 x4076 +22299 x4077 +22299 x4078 +22299 x4079 +22299 x4080 +22299 x4081 +22299 x4082 +22299 x4083 +22299 x4084 +22299 x4085 +22299 x4086 +22299 x4087 +22299 x4088 +22299 x4089 +22299 x4090 +22299 x4091 +22299 x4092 +22299 x4093 +22299 x4094 +22299 x4095 +22299 x4096 +5279 x4097 +5279 x4098 +5279 x4099 +5279 x4100 +5279 x4101 +5279 x4102 +5279 x4103 +5279 x4104 +5279 x4105 +5279 x4106 +5279 x4107 +5279 x4108 +5279 x4109 +5279 x4110 +5279 x4111 +5279 x4112 +5279 x4113 +5279 x4114 +5279 x4115 +5279 x4116 +5279 x4117 +5279 x4118 +5279 x4119 +5279 x4120 +5279 x4121 +5279 x4122 +5279 x4123 +5279 x4124 +5279 x4125 +5279 x4126 +5279 x4127 +5279 x4128 +5279 x4129 +5279 x4130 +5279 x4131 +5279 x4132 +5279 x4133 +5279 x4134 +5279 x4135 +5279 x4136 +5279 x4137 +5279 x4138 +5279 x4139 +5279 x4140 +5279 x4141 +5279 x4142 +5279 x4143 +5279 x4144 +5279 x4145 +5279 x4146 +5279 x4147 +5279 x4148 +5279 x4149 +5279 x4150 +5279 x4151 +5279 x4152 +5279 x4153 +5279 x4154 +5279 x4155 +5279 x4156 +5279 x4157 +5279 x4158 +5279 x4159 +5279 x4160 +5279 x4161 +5279 x4162 +5279 x4163 +5279 x4164 +5279 x4165 +5279 x4166 +5279 x4167 +5279 x4168 +5279 x4169 +5279 x4170 +5279 x4171 +5279 x4172 +5279 x4173 +5279 x4174 +5279 x4175 +5279 x4176 +5279 x4177 +5279 x4178 +5279 x4179 +5279 x4180 +5279 x4181 +5279 x4182 +5279 x4183 +5279 x4184 +5279 x4185 +5279 x4186 +5279 x4187 +5279 x4188 +5279 x4189 +5279 x4190 +5279 x4191 +5279 x4192 +5279 x4193 +5279 x4194 +5279 x4195 +5279 x4196 +5279 x4197 +5279 x4198 +5279 x4199 +5279 x4200 +5279 x4201 +5279 x4202 +5279 x4203 +5279 x4204 +5279 x4205 +5279 x4206 +5279 x4207 +5279 x4208 +5279 x4209 +5279 x4210 +5279 x4211 +5279 x4212 +5279 x4213 +5279 x4214 +5279 x4215 +5279 x4216 +5279 x4217 +5279 x4218 +5279 x4219 +5279 x4220 +5279 x4221 +5279 x4222 +5279 x4223 +5279 x4224 +27879 x4225 +27879 x4226 +27879 x4227 +27879 x4228 +27879 x4229 +27879 x4230 +27879 x4231 +27879 x4232 +27879 x4233 +27879 x4234 +27879 x4235 +27879 x4236 +27879 x4237 +27879 x4238 +27879 x4239 +27879 x4240 +27879 x4241 +27879 x4242 +27879 x4243 +27879 x4244 +27879 x4245 +27879 x4246 +27879 x4247 +27879 x4248 +27879 x4249 +27879 x4250 +27879 x4251 +27879 x4252 +27879 x4253 +27879 x4254 +27879 x4255 +27879 x4256 +27879 x4257 +27879 x4258 +27879 x4259 +27879 x4260 +27879 x4261 +27879 x4262 +27879 x4263 +27879 x4264 +27879 x4265 +27879 x4266 +27879 x4267 +27879 x4268 +27879 x4269 +27879 x4270 +27879 x4271 +27879 x4272 +27879 x4273 +27879 x4274 +27879 x4275 +27879 x4276 +27879 x4277 +27879 x4278 +27879 x4279 +27879 x4280 +27879 x4281 +27879 x4282 +27879 x4283 +27879 x4284 +27879 x4285 +27879 x4286 +27879 x4287 +27879 x4288 +27879 x4289 +27879 x4290 +27879 x4291 +27879 x4292 +27879 x4293 +27879 x4294 +27879 x4295 +27879 x4296 +27879 x4297 +27879 x4298 +27879 x4299 +27879 x4300 +27879 x4301 +27879 x4302 +27879 x4303 +27879 x4304 +27879 x4305 +27879 x4306 +27879 x4307 +27879 x4308 +27879 x4309 +27879 x4310 +27879 x4311 +27879 x4312 +27879 x4313 +27879 x4314 +27879 x4315 +27879 x4316 +27879 x4317 +27879 x4318 +27879 x4319 +27879 x4320 +27879 x4321 +27879 x4322 +27879 x4323 +27879 x4324 +27879 x4325 +27879 x4326 +27879 x4327 +27879 x4328 +27879 x4329 +27879 x4330 +27879 x4331 +27879 x4332 +27879 x4333 +27879 x4334 +27879 x4335 +27879 x4336 +27879 x4337 +27879 x4338 +27879 x4339 +27879 x4340 +27879 x4341 +27879 x4342 +27879 x4343 +27879 x4344 +27879 x4345 +27879 x4346 +27879 x4347 +27879 x4348 +27879 x4349 +27879 x4350 +27879 x4351 +27879 x4352 +34877 x4353 +34877 x4354 +34877 x4355 +34877 x4356 +34877 x4357 +34877 x4358 +34877 x4359 +34877 x4360 +34877 x4361 +34877 x4362 +34877 x4363 +34877 x4364 +34877 x4365 +34877 x4366 +34877 x4367 +34877 x4368 +34877 x4369 +34877 x4370 +34877 x4371 +34877 x4372 +34877 x4373 +34877 x4374 +34877 x4375 +34877 x4376 +34877 x4377 +34877 x4378 +34877 x4379 +34877 x4380 +34877 x4381 +34877 x4382 +34877 x4383 +34877 x4384 +34877 x4385 +34877 x4386 +34877 x4387 +34877 x4388 +34877 x4389 +34877 x4390 +34877 x4391 +34877 x4392 +34877 x4393 +34877 x4394 +34877 x4395 +34877 x4396 +34877 x4397 +34877 x4398 +34877 x4399 +34877 x4400 +34877 x4401 +34877 x4402 +34877 x4403 +34877 x4404 +34877 x4405 +34877 x4406 +34877 x4407 +34877 x4408 +34877 x4409 +34877 x4410 +34877 x4411 +34877 x4412 +34877 x4413 +34877 x4414 +34877 x4415 +34877 x4416 +34877 x4417 +34877 x4418 +34877 x4419 +34877 x4420 +34877 x4421 +34877 x4422 +34877 x4423 +34877 x4424 +34877 x4425 +34877 x4426 +34877 x4427 +34877 x4428 +34877 x4429 +34877 x4430 +34877 x4431 +34877 x4432 +34877 x4433 +34877 x4434 +34877 x4435 +34877 x4436 +34877 x4437 +34877 x4438 +34877 x4439 +34877 x4440 +34877 x4441 +34877 x4442 +34877 x4443 +34877 x4444 +34877 x4445 +34877 x4446 +34877 x4447 +34877 x4448 +34877 x4449 +34877 x4450 +34877 x4451 +34877 x4452 +34877 x4453 +34877 x4454 +34877 x4455 +34877 x4456 +34877 x4457 +34877 x4458 +34877 x4459 +34877 x4460 +34877 x4461 +34877 x4462 +34877 x4463 +34877 x4464 +34877 x4465 +34877 x4466 +34877 x4467 +34877 x4468 +34877 x4469 +34877 x4470 +34877 x4471 +34877 x4472 +34877 x4473 +34877 x4474 +34877 x4475 +34877 x4476 +34877 x4477 +34877 x4478 +34877 x4479 +34877 x4480 +58716 x4481 +58716 x4482 +58716 x4483 +58716 x4484 +58716 x4485 +58716 x4486 +58716 x4487 +58716 x4488 +58716 x4489 +58716 x4490 +58716 x4491 +58716 x4492 +58716 x4493 +58716 x4494 +58716 x4495 +58716 x4496 +58716 x4497 +58716 x4498 +58716 x4499 +58716 x4500 +58716 x4501 +58716 x4502 +58716 x4503 +58716 x4504 +58716 x4505 +58716 x4506 +58716 x4507 +58716 x4508 +58716 x4509 +58716 x4510 +58716 x4511 +58716 x4512 +58716 x4513 +58716 x4514 +58716 x4515 +58716 x4516 +58716 x4517 +58716 x4518 +58716 x4519 +58716 x4520 +58716 x4521 +58716 x4522 +58716 x4523 +58716 x4524 +58716 x4525 +58716 x4526 +58716 x4527 +58716 x4528 +58716 x4529 +58716 x4530 +58716 x4531 +58716 x4532 +58716 x4533 +58716 x4534 +58716 x4535 +58716 x4536 +58716 x4537 +58716 x4538 +58716 x4539 +58716 x4540 +58716 x4541 +58716 x4542 +58716 x4543 +58716 x4544 +58716 x4545 +58716 x4546 +58716 x4547 +58716 x4548 +58716 x4549 +58716 x4550 +58716 x4551 +58716 x4552 +58716 x4553 +58716 x4554 +58716 x4555 +58716 x4556 +58716 x4557 +58716 x4558 +58716 x4559 +58716 x4560 +58716 x4561 +58716 x4562 +58716 x4563 +58716 x4564 +58716 x4565 +58716 x4566 +58716 x4567 +58716 x4568 +58716 x4569 +58716 x4570 +58716 x4571 +58716 x4572 +58716 x4573 +58716 x4574 +58716 x4575 +58716 x4576 +58716 x4577 +58716 x4578 +58716 x4579 +58716 x4580 +58716 x4581 +58716 x4582 +58716 x4583 +58716 x4584 +58716 x4585 +58716 x4586 +58716 x4587 +58716 x4588 +58716 x4589 +58716 x4590 +58716 x4591 +58716 x4592 +58716 x4593 +58716 x4594 +58716 x4595 +58716 x4596 +58716 x4597 +58716 x4598 +58716 x4599 +58716 x4600 +58716 x4601 +58716 x4602 +58716 x4603 +58716 x4604 +58716 x4605 +58716 x4606 +58716 x4607 +58716 x4608 +3543 x4609 +3543 x4610 +3543 x4611 +3543 x4612 +3543 x4613 +3543 x4614 +3543 x4615 +3543 x4616 +3543 x4617 +3543 x4618 +3543 x4619 +3543 x4620 +3543 x4621 +3543 x4622 +3543 x4623 +3543 x4624 +3543 x4625 +3543 x4626 +3543 x4627 +3543 x4628 +3543 x4629 +3543 x4630 +3543 x4631 +3543 x4632 +3543 x4633 +3543 x4634 +3543 x4635 +3543 x4636 +3543 x4637 +3543 x4638 +3543 x4639 +3543 x4640 +3543 x4641 +3543 x4642 +3543 x4643 +3543 x4644 +3543 x4645 +3543 x4646 +3543 x4647 +3543 x4648 +3543 x4649 +3543 x4650 +3543 x4651 +3543 x4652 +3543 x4653 +3543 x4654 +3543 x4655 +3543 x4656 +3543 x4657 +3543 x4658 +3543 x4659 +3543 x4660 +3543 x4661 +3543 x4662 +3543 x4663 +3543 x4664 +3543 x4665 +3543 x4666 +3543 x4667 +3543 x4668 +3543 x4669 +3543 x4670 +3543 x4671 +3543 x4672 +3543 x4673 +3543 x4674 +3543 x4675 +3543 x4676 +3543 x4677 +3543 x4678 +3543 x4679 +3543 x4680 +3543 x4681 +3543 x4682 +3543 x4683 +3543 x4684 +3543 x4685 +3543 x4686 +3543 x4687 +3543 x4688 +3543 x4689 +3543 x4690 +3543 x4691 +3543 x4692 +3543 x4693 +3543 x4694 +3543 x4695 +3543 x4696 +3543 x4697 +3543 x4698 +3543 x4699 +3543 x4700 +3543 x4701 +3543 x4702 +3543 x4703 +3543 x4704 +3543 x4705 +3543 x4706 +3543 x4707 +3543 x4708 +3543 x4709 +3543 x4710 +3543 x4711 +3543 x4712 +3543 x4713 +3543 x4714 +3543 x4715 +3543 x4716 +3543 x4717 +3543 x4718 +3543 x4719 +3543 x4720 +3543 x4721 +3543 x4722 +3543 x4723 +3543 x4724 +3543 x4725 +3543 x4726 +3543 x4727 +3543 x4728 +3543 x4729 +3543 x4730 +3543 x4731 +3543 x4732 +3543 x4733 +3543 x4734 +3543 x4735 +3543 x4736 +45541 x4737 +45541 x4738 +45541 x4739 +45541 x4740 +45541 x4741 +45541 x4742 +45541 x4743 +45541 x4744 +45541 x4745 +45541 x4746 +45541 x4747 +45541 x4748 +45541 x4749 +45541 x4750 +45541 x4751 +45541 x4752 +45541 x4753 +45541 x4754 +45541 x4755 +45541 x4756 +45541 x4757 +45541 x4758 +45541 x4759 +45541 x4760 +45541 x4761 +45541 x4762 +45541 x4763 +45541 x4764 +45541 x4765 +45541 x4766 +45541 x4767 +45541 x4768 +45541 x4769 +45541 x4770 +45541 x4771 +45541 x4772 +45541 x4773 +45541 x4774 +45541 x4775 +45541 x4776 +45541 x4777 +45541 x4778 +45541 x4779 +45541 x4780 +45541 x4781 +45541 x4782 +45541 x4783 +45541 x4784 +45541 x4785 +45541 x4786 +45541 x4787 +45541 x4788 +45541 x4789 +45541 x4790 +45541 x4791 +45541 x4792 +45541 x4793 +45541 x4794 +45541 x4795 +45541 x4796 +45541 x4797 +45541 x4798 +45541 x4799 +45541 x4800 +45541 x4801 +45541 x4802 +45541 x4803 +45541 x4804 +45541 x4805 +45541 x4806 +45541 x4807 +45541 x4808 +45541 x4809 +45541 x4810 +45541 x4811 +45541 x4812 +45541 x4813 +45541 x4814 +45541 x4815 +45541 x4816 +45541 x4817 +45541 x4818 +45541 x4819 +45541 x4820 +45541 x4821 +45541 x4822 +45541 x4823 +45541 x4824 +45541 x4825 +45541 x4826 +45541 x4827 +45541 x4828 +45541 x4829 +45541 x4830 +45541 x4831 +45541 x4832 +45541 x4833 +45541 x4834 +45541 x4835 +45541 x4836 +45541 x4837 +45541 x4838 +45541 x4839 +45541 x4840 +45541 x4841 +45541 x4842 +45541 x4843 +45541 x4844 +45541 x4845 +45541 x4846 +45541 x4847 +45541 x4848 +45541 x4849 +45541 x4850 +45541 x4851 +45541 x4852 +45541 x4853 +45541 x4854 +45541 x4855 +45541 x4856 +45541 x4857 +45541 x4858 +45541 x4859 +45541 x4860 +45541 x4861 +45541 x4862 +45541 x4863 +45541 x4864 +10500 x4865 +10500 x4866 +10500 x4867 +10500 x4868 +10500 x4869 +10500 x4870 +10500 x4871 +10500 x4872 +10500 x4873 +10500 x4874 +10500 x4875 +10500 x4876 +10500 x4877 +10500 x4878 +10500 x4879 +10500 x4880 +10500 x4881 +10500 x4882 +10500 x4883 +10500 x4884 +10500 x4885 +10500 x4886 +10500 x4887 +10500 x4888 +10500 x4889 +10500 x4890 +10500 x4891 +10500 x4892 +10500 x4893 +10500 x4894 +10500 x4895 +10500 x4896 +10500 x4897 +10500 x4898 +10500 x4899 +10500 x4900 +10500 x4901 +10500 x4902 +10500 x4903 +10500 x4904 +10500 x4905 +10500 x4906 +10500 x4907 +10500 x4908 +10500 x4909 +10500 x4910 +10500 x4911 +10500 x4912 +10500 x4913 +10500 x4914 +10500 x4915 +10500 x4916 +10500 x4917 +10500 x4918 +10500 x4919 +10500 x4920 +10500 x4921 +10500 x4922 +10500 x4923 +10500 x4924 +10500 x4925 +10500 x4926 +10500 x4927 +10500 x4928 +10500 x4929 +10500 x4930 +10500 x4931 +10500 x4932 +10500 x4933 +10500 x4934 +10500 x4935 +10500 x4936 +10500 x4937 +10500 x4938 +10500 x4939 +10500 x4940 +10500 x4941 +10500 x4942 +10500 x4943 +10500 x4944 +10500 x4945 +10500 x4946 +10500 x4947 +10500 x4948 +10500 x4949 +10500 x4950 +10500 x4951 +10500 x4952 +10500 x4953 +10500 x4954 +10500 x4955 +10500 x4956 +10500 x4957 +10500 x4958 +10500 x4959 +10500 x4960 +10500 x4961 +10500 x4962 +10500 x4963 +10500 x4964 +10500 x4965 +10500 x4966 +10500 x4967 +10500 x4968 +10500 x4969 +10500 x4970 +10500 x4971 +10500 x4972 +10500 x4973 +10500 x4974 +10500 x4975 +10500 x4976 +10500 x4977 +10500 x4978 +10500 x4979 +10500 x4980 +10500 x4981 +10500 x4982 +10500 x4983 +10500 x4984 +10500 x4985 +10500 x4986 +10500 x4987 +10500 x4988 +10500 x4989 +10500 x4990 +10500 x4991 +10500 x4992 +14327 x4993 +14327 x4994 +14327 x4995 +14327 x4996 +14327 x4997 +14327 x4998 +14327 x4999 +14327 x5000 +14327 x5001 +14327 x5002 +14327 x5003 +14327 x5004 +14327 x5005 +14327 x5006 +14327 x5007 +14327 x5008 +14327 x5009 +14327 x5010 +14327 x5011 +14327 x5012 +14327 x5013 +14327 x5014 +14327 x5015 +14327 x5016 +14327 x5017 +14327 x5018 +14327 x5019 +14327 x5020 +14327 x5021 +14327 x5022 +14327 x5023 +14327 x5024 +14327 x5025 +14327 x5026 +14327 x5027 +14327 x5028 +14327 x5029 +14327 x5030 +14327 x5031 +14327 x5032 +14327 x5033 +14327 x5034 +14327 x5035 +14327 x5036 +14327 x5037 +14327 x5038 +14327 x5039 +14327 x5040 +14327 x5041 +14327 x5042 +14327 x5043 +14327 x5044 +14327 x5045 +14327 x5046 +14327 x5047 +14327 x5048 +14327 x5049 +14327 x5050 +14327 x5051 +14327 x5052 +14327 x5053 +14327 x5054 +14327 x5055 +14327 x5056 +14327 x5057 +14327 x5058 +14327 x5059 +14327 x5060 +14327 x5061 +14327 x5062 +14327 x5063 +14327 x5064 +14327 x5065 +14327 x5066 +14327 x5067 +14327 x5068 +14327 x5069 +14327 x5070 +14327 x5071 +14327 x5072 +14327 x5073 +14327 x5074 +14327 x5075 +14327 x5076 +14327 x5077 +14327 x5078 +14327 x5079 +14327 x5080 +14327 x5081 +14327 x5082 +14327 x5083 +14327 x5084 +14327 x5085 +14327 x5086 +14327 x5087 +14327 x5088 +14327 x5089 +14327 x5090 +14327 x5091 +14327 x5092 +14327 x5093 +14327 x5094 +14327 x5095 +14327 x5096 +14327 x5097 +14327 x5098 +14327 x5099 +14327 x5100 +14327 x5101 +14327 x5102 +14327 x5103 +14327 x5104 +14327 x5105 +14327 x5106 +14327 x5107 +14327 x5108 +14327 x5109 +14327 x5110 +14327 x5111 +14327 x5112 +14327 x5113 +14327 x5114 +14327 x5115 +14327 x5116 +14327 x5117 +14327 x5118 +14327 x5119 +14327 x5120 +13741 x5121 +13741 x5122 +13741 x5123 +13741 x5124 +13741 x5125 +13741 x5126 +13741 x5127 +13741 x5128 +13741 x5129 +13741 x5130 +13741 x5131 +13741 x5132 +13741 x5133 +13741 x5134 +13741 x5135 +13741 x5136 +13741 x5137 +13741 x5138 +13741 x5139 +13741 x5140 +13741 x5141 +13741 x5142 +13741 x5143 +13741 x5144 +13741 x5145 +13741 x5146 +13741 x5147 +13741 x5148 +13741 x5149 +13741 x5150 +13741 x5151 +13741 x5152 +13741 x5153 +13741 x5154 +13741 x5155 +13741 x5156 +13741 x5157 +13741 x5158 +13741 x5159 +13741 x5160 +13741 x5161 +13741 x5162 +13741 x5163 +13741 x5164 +13741 x5165 +13741 x5166 +13741 x5167 +13741 x5168 +13741 x5169 +13741 x5170 +13741 x5171 +13741 x5172 +13741 x5173 +13741 x5174 +13741 x5175 +13741 x5176 +13741 x5177 +13741 x5178 +13741 x5179 +13741 x5180 +13741 x5181 +13741 x5182 +13741 x5183 +13741 x5184 +13741 x5185 +13741 x5186 +13741 x5187 +13741 x5188 +13741 x5189 +13741 x5190 +13741 x5191 +13741 x5192 +13741 x5193 +13741 x5194 +13741 x5195 +13741 x5196 +13741 x5197 +13741 x5198 +13741 x5199 +13741 x5200 +13741 x5201 +13741 x5202 +13741 x5203 +13741 x5204 +13741 x5205 +13741 x5206 +13741 x5207 +13741 x5208 +13741 x5209 +13741 x5210 +13741 x5211 +13741 x5212 +13741 x5213 +13741 x5214 +13741 x5215 +13741 x5216 +13741 x5217 +13741 x5218 +13741 x5219 +13741 x5220 +13741 x5221 +13741 x5222 +13741 x5223 +13741 x5224 +13741 x5225 +13741 x5226 +13741 x5227 +13741 x5228 +13741 x5229 +13741 x5230 +13741 x5231 +13741 x5232 +13741 x5233 +13741 x5234 +13741 x5235 +13741 x5236 +13741 x5237 +13741 x5238 +13741 x5239 +13741 x5240 +13741 x5241 +13741 x5242 +13741 x5243 +13741 x5244 +13741 x5245 +13741 x5246 +13741 x5247 +13741 x5248 +48513 x5249 +48513 x5250 +48513 x5251 +48513 x5252 +48513 x5253 +48513 x5254 +48513 x5255 +48513 x5256 +48513 x5257 +48513 x5258 +48513 x5259 +48513 x5260 +48513 x5261 +48513 x5262 +48513 x5263 +48513 x5264 +48513 x5265 +48513 x5266 +48513 x5267 +48513 x5268 +48513 x5269 +48513 x5270 +48513 x5271 +48513 x5272 +48513 x5273 +48513 x5274 +48513 x5275 +48513 x5276 +48513 x5277 +48513 x5278 +48513 x5279 +48513 x5280 +48513 x5281 +48513 x5282 +48513 x5283 +48513 x5284 +48513 x5285 +48513 x5286 +48513 x5287 +48513 x5288 +48513 x5289 +48513 x5290 +48513 x5291 +48513 x5292 +48513 x5293 +48513 x5294 +48513 x5295 +48513 x5296 +48513 x5297 +48513 x5298 +48513 x5299 +48513 x5300 +48513 x5301 +48513 x5302 +48513 x5303 +48513 x5304 +48513 x5305 +48513 x5306 +48513 x5307 +48513 x5308 +48513 x5309 +48513 x5310 +48513 x5311 +48513 x5312 +48513 x5313 +48513 x5314 +48513 x5315 +48513 x5316 +48513 x5317 +48513 x5318 +48513 x5319 +48513 x5320 +48513 x5321 +48513 x5322 +48513 x5323 +48513 x5324 +48513 x5325 +48513 x5326 +48513 x5327 +48513 x5328 +48513 x5329 +48513 x5330 +48513 x5331 +48513 x5332 +48513 x5333 +48513 x5334 +48513 x5335 +48513 x5336 +48513 x5337 +48513 x5338 +48513 x5339 +48513 x5340 +48513 x5341 +48513 x5342 +48513 x5343 +48513 x5344 +48513 x5345 +48513 x5346 +48513 x5347 +48513 x5348 +48513 x5349 +48513 x5350 +48513 x5351 +48513 x5352 +48513 x5353 +48513 x5354 +48513 x5355 +48513 x5356 +48513 x5357 +48513 x5358 +48513 x5359 +48513 x5360 +48513 x5361 +48513 x5362 +48513 x5363 +48513 x5364 +48513 x5365 +48513 x5366 +48513 x5367 +48513 x5368 +48513 x5369 +48513 x5370 +48513 x5371 +48513 x5372 +48513 x5373 +48513 x5374 +48513 x5375 +48513 x5376 +30270 x5377 +30270 x5378 +30270 x5379 +30270 x5380 +30270 x5381 +30270 x5382 +30270 x5383 +30270 x5384 +30270 x5385 +30270 x5386 +30270 x5387 +30270 x5388 +30270 x5389 +30270 x5390 +30270 x5391 +30270 x5392 +30270 x5393 +30270 x5394 +30270 x5395 +30270 x5396 +30270 x5397 +30270 x5398 +30270 x5399 +30270 x5400 +30270 x5401 +30270 x5402 +30270 x5403 +30270 x5404 +30270 x5405 +30270 x5406 +30270 x5407 +30270 x5408 +30270 x5409 +30270 x5410 +30270 x5411 +30270 x5412 +30270 x5413 +30270 x5414 +30270 x5415 +30270 x5416 +30270 x5417 +30270 x5418 +30270 x5419 +30270 x5420 +30270 x5421 +30270 x5422 +30270 x5423 +30270 x5424 +30270 x5425 +30270 x5426 +30270 x5427 +30270 x5428 +30270 x5429 +30270 x5430 +30270 x5431 +30270 x5432 +30270 x5433 +30270 x5434 +30270 x5435 +30270 x5436 +30270 x5437 +30270 x5438 +30270 x5439 +30270 x5440 +30270 x5441 +30270 x5442 +30270 x5443 +30270 x5444 +30270 x5445 +30270 x5446 +30270 x5447 +30270 x5448 +30270 x5449 +30270 x5450 +30270 x5451 +30270 x5452 +30270 x5453 +30270 x5454 +30270 x5455 +30270 x5456 +30270 x5457 +30270 x5458 +30270 x5459 +30270 x5460 +30270 x5461 +30270 x5462 +30270 x5463 +30270 x5464 +30270 x5465 +30270 x5466 +30270 x5467 +30270 x5468 +30270 x5469 +30270 x5470 +30270 x5471 +30270 x5472 +30270 x5473 +30270 x5474 +30270 x5475 +30270 x5476 +30270 x5477 +30270 x5478 +30270 x5479 +30270 x5480 +30270 x5481 +30270 x5482 +30270 x5483 +30270 x5484 +30270 x5485 +30270 x5486 +30270 x5487 +30270 x5488 +30270 x5489 +30270 x5490 +30270 x5491 +30270 x5492 +30270 x5493 +30270 x5494 +30270 x5495 +30270 x5496 +30270 x5497 +30270 x5498 +30270 x5499 +30270 x5500 +30270 x5501 +30270 x5502 +30270 x5503 +30270 x5504 +13205 x5505 +13205 x5506 +13205 x5507 +13205 x5508 +13205 x5509 +13205 x5510 +13205 x5511 +13205 x5512 +13205 x5513 +13205 x5514 +13205 x5515 +13205 x5516 +13205 x5517 +13205 x5518 +13205 x5519 +13205 x5520 +13205 x5521 +13205 x5522 +13205 x5523 +13205 x5524 +13205 x5525 +13205 x5526 +13205 x5527 +13205 x5528 +13205 x5529 +13205 x5530 +13205 x5531 +13205 x5532 +13205 x5533 +13205 x5534 +13205 x5535 +13205 x5536 +13205 x5537 +13205 x5538 +13205 x5539 +13205 x5540 +13205 x5541 +13205 x5542 +13205 x5543 +13205 x5544 +13205 x5545 +13205 x5546 +13205 x5547 +13205 x5548 +13205 x5549 +13205 x5550 +13205 x5551 +13205 x5552 +13205 x5553 +13205 x5554 +13205 x5555 +13205 x5556 +13205 x5557 +13205 x5558 +13205 x5559 +13205 x5560 +13205 x5561 +13205 x5562 +13205 x5563 +13205 x5564 +13205 x5565 +13205 x5566 +13205 x5567 +13205 x5568 +13205 x5569 +13205 x5570 +13205 x5571 +13205 x5572 +13205 x5573 +13205 x5574 +13205 x5575 +13205 x5576 +13205 x5577 +13205 x5578 +13205 x5579 +13205 x5580 +13205 x5581 +13205 x5582 +13205 x5583 +13205 x5584 +13205 x5585 +13205 x5586 +13205 x5587 +13205 x5588 +13205 x5589 +13205 x5590 +13205 x5591 +13205 x5592 +13205 x5593 +13205 x5594 +13205 x5595 +13205 x5596 +13205 x5597 +13205 x5598 +13205 x5599 +13205 x5600 +13205 x5601 +13205 x5602 +13205 x5603 +13205 x5604 +13205 x5605 +13205 x5606 +13205 x5607 +13205 x5608 +13205 x5609 +13205 x5610 +13205 x5611 +13205 x5612 +13205 x5613 +13205 x5614 +13205 x5615 +13205 x5616 +13205 x5617 +13205 x5618 +13205 x5619 +13205 x5620 +13205 x5621 +13205 x5622 +13205 x5623 +13205 x5624 +13205 x5625 +13205 x5626 +13205 x5627 +13205 x5628 +13205 x5629 +13205 x5630 +13205 x5631 +13205 x5632 +40757 x5633 +40757 x5634 +40757 x5635 +40757 x5636 +40757 x5637 +40757 x5638 +40757 x5639 +40757 x5640 +40757 x5641 +40757 x5642 +40757 x5643 +40757 x5644 +40757 x5645 +40757 x5646 +40757 x5647 +40757 x5648 +40757 x5649 +40757 x5650 +40757 x5651 +40757 x5652 +40757 x5653 +40757 x5654 +40757 x5655 +40757 x5656 +40757 x5657 +40757 x5658 +40757 x5659 +40757 x5660 +40757 x5661 +40757 x5662 +40757 x5663 +40757 x5664 +40757 x5665 +40757 x5666 +40757 x5667 +40757 x5668 +40757 x5669 +40757 x5670 +40757 x5671 +40757 x5672 +40757 x5673 +40757 x5674 +40757 x5675 +40757 x5676 +40757 x5677 +40757 x5678 +40757 x5679 +40757 x5680 +40757 x5681 +40757 x5682 +40757 x5683 +40757 x5684 +40757 x5685 +40757 x5686 +40757 x5687 +40757 x5688 +40757 x5689 +40757 x5690 +40757 x5691 +40757 x5692 +40757 x5693 +40757 x5694 +40757 x5695 +40757 x5696 +40757 x5697 +40757 x5698 +40757 x5699 +40757 x5700 +40757 x5701 +40757 x5702 +40757 x5703 +40757 x5704 +40757 x5705 +40757 x5706 +40757 x5707 +40757 x5708 +40757 x5709 +40757 x5710 +40757 x5711 +40757 x5712 +40757 x5713 +40757 x5714 +40757 x5715 +40757 x5716 +40757 x5717 +40757 x5718 +40757 x5719 +40757 x5720 +40757 x5721 +40757 x5722 +40757 x5723 +40757 x5724 +40757 x5725 +40757 x5726 +40757 x5727 +40757 x5728 +40757 x5729 +40757 x5730 +40757 x5731 +40757 x5732 +40757 x5733 +40757 x5734 +40757 x5735 +40757 x5736 +40757 x5737 +40757 x5738 +40757 x5739 +40757 x5740 +40757 x5741 +40757 x5742 +40757 x5743 +40757 x5744 +40757 x5745 +40757 x5746 +40757 x5747 +40757 x5748 +40757 x5749 +40757 x5750 +40757 x5751 +40757 x5752 +40757 x5753 +40757 x5754 +40757 x5755 +40757 x5756 +40757 x5757 +40757 x5758 +40757 x5759 +40757 x5760 +39467 x5761 +39467 x5762 +39467 x5763 +39467 x5764 +39467 x5765 +39467 x5766 +39467 x5767 +39467 x5768 +39467 x5769 +39467 x5770 +39467 x5771 +39467 x5772 +39467 x5773 +39467 x5774 +39467 x5775 +39467 x5776 +39467 x5777 +39467 x5778 +39467 x5779 +39467 x5780 +39467 x5781 +39467 x5782 +39467 x5783 +39467 x5784 +39467 x5785 +39467 x5786 +39467 x5787 +39467 x5788 +39467 x5789 +39467 x5790 +39467 x5791 +39467 x5792 +39467 x5793 +39467 x5794 +39467 x5795 +39467 x5796 +39467 x5797 +39467 x5798 +39467 x5799 +39467 x5800 +39467 x5801 +39467 x5802 +39467 x5803 +39467 x5804 +39467 x5805 +39467 x5806 +39467 x5807 +39467 x5808 +39467 x5809 +39467 x5810 +39467 x5811 +39467 x5812 +39467 x5813 +39467 x5814 +39467 x5815 +39467 x5816 +39467 x5817 +39467 x5818 +39467 x5819 +39467 x5820 +39467 x5821 +39467 x5822 +39467 x5823 +39467 x5824 +39467 x5825 +39467 x5826 +39467 x5827 +39467 x5828 +39467 x5829 +39467 x5830 +39467 x5831 +39467 x5832 +39467 x5833 +39467 x5834 +39467 x5835 +39467 x5836 +39467 x5837 +39467 x5838 +39467 x5839 +39467 x5840 +39467 x5841 +39467 x5842 +39467 x5843 +39467 x5844 +39467 x5845 +39467 x5846 +39467 x5847 +39467 x5848 +39467 x5849 +39467 x5850 +39467 x5851 +39467 x5852 +39467 x5853 +39467 x5854 +39467 x5855 +39467 x5856 +39467 x5857 +39467 x5858 +39467 x5859 +39467 x5860 +39467 x5861 +39467 x5862 +39467 x5863 +39467 x5864 +39467 x5865 +39467 x5866 +39467 x5867 +39467 x5868 +39467 x5869 +39467 x5870 +39467 x5871 +39467 x5872 +39467 x5873 +39467 x5874 +39467 x5875 +39467 x5876 +39467 x5877 +39467 x5878 +39467 x5879 +39467 x5880 +39467 x5881 +39467 x5882 +39467 x5883 +39467 x5884 +39467 x5885 +39467 x5886 +39467 x5887 +39467 x5888 +9765 x5889 +9765 x5890 +9765 x5891 +9765 x5892 +9765 x5893 +9765 x5894 +9765 x5895 +9765 x5896 +9765 x5897 +9765 x5898 +9765 x5899 +9765 x5900 +9765 x5901 +9765 x5902 +9765 x5903 +9765 x5904 +9765 x5905 +9765 x5906 +9765 x5907 +9765 x5908 +9765 x5909 +9765 x5910 +9765 x5911 +9765 x5912 +9765 x5913 +9765 x5914 +9765 x5915 +9765 x5916 +9765 x5917 +9765 x5918 +9765 x5919 +9765 x5920 +9765 x5921 +9765 x5922 +9765 x5923 +9765 x5924 +9765 x5925 +9765 x5926 +9765 x5927 +9765 x5928 +9765 x5929 +9765 x5930 +9765 x5931 +9765 x5932 +9765 x5933 +9765 x5934 +9765 x5935 +9765 x5936 +9765 x5937 +9765 x5938 +9765 x5939 +9765 x5940 +9765 x5941 +9765 x5942 +9765 x5943 +9765 x5944 +9765 x5945 +9765 x5946 +9765 x5947 +9765 x5948 +9765 x5949 +9765 x5950 +9765 x5951 +9765 x5952 +9765 x5953 +9765 x5954 +9765 x5955 +9765 x5956 +9765 x5957 +9765 x5958 +9765 x5959 +9765 x5960 +9765 x5961 +9765 x5962 +9765 x5963 +9765 x5964 +9765 x5965 +9765 x5966 +9765 x5967 +9765 x5968 +9765 x5969 +9765 x5970 +9765 x5971 +9765 x5972 +9765 x5973 +9765 x5974 +9765 x5975 +9765 x5976 +9765 x5977 +9765 x5978 +9765 x5979 +9765 x5980 +9765 x5981 +9765 x5982 +9765 x5983 +9765 x5984 +9765 x5985 +9765 x5986 +9765 x5987 +9765 x5988 +9765 x5989 +9765 x5990 +9765 x5991 +9765 x5992 +9765 x5993 +9765 x5994 +9765 x5995 +9765 x5996 +9765 x5997 +9765 x5998 +9765 x5999 +9765 x6000 +9765 x6001 +9765 x6002 +9765 x6003 +9765 x6004 +9765 x6005 +9765 x6006 +9765 x6007 +9765 x6008 +9765 x6009 +9765 x6010 +9765 x6011 +9765 x6012 +9765 x6013 +9765 x6014 +9765 x6015 +9765 x6016 +17608 x6017 +17608 x6018 +17608 x6019 +17608 x6020 +17608 x6021 +17608 x6022 +17608 x6023 +17608 x6024 +17608 x6025 +17608 x6026 +17608 x6027 +17608 x6028 +17608 x6029 +17608 x6030 +17608 x6031 +17608 x6032 +17608 x6033 +17608 x6034 +17608 x6035 +17608 x6036 +17608 x6037 +17608 x6038 +17608 x6039 +17608 x6040 +17608 x6041 +17608 x6042 +17608 x6043 +17608 x6044 +17608 x6045 +17608 x6046 +17608 x6047 +17608 x6048 +17608 x6049 +17608 x6050 +17608 x6051 +17608 x6052 +17608 x6053 +17608 x6054 +17608 x6055 +17608 x6056 +17608 x6057 +17608 x6058 +17608 x6059 +17608 x6060 +17608 x6061 +17608 x6062 +17608 x6063 +17608 x6064 +17608 x6065 +17608 x6066 +17608 x6067 +17608 x6068 +17608 x6069 +17608 x6070 +17608 x6071 +17608 x6072 +17608 x6073 +17608 x6074 +17608 x6075 +17608 x6076 +17608 x6077 +17608 x6078 +17608 x6079 +17608 x6080 +17608 x6081 +17608 x6082 +17608 x6083 +17608 x6084 +17608 x6085 +17608 x6086 +17608 x6087 +17608 x6088 +17608 x6089 +17608 x6090 +17608 x6091 +17608 x6092 +17608 x6093 +17608 x6094 +17608 x6095 +17608 x6096 +17608 x6097 +17608 x6098 +17608 x6099 +17608 x6100 +17608 x6101 +17608 x6102 +17608 x6103 +17608 x6104 +17608 x6105 +17608 x6106 +17608 x6107 +17608 x6108 +17608 x6109 +17608 x6110 +17608 x6111 +17608 x6112 +17608 x6113 +17608 x6114 +17608 x6115 +17608 x6116 +17608 x6117 +17608 x6118 +17608 x6119 +17608 x6120 +17608 x6121 +17608 x6122 +17608 x6123 +17608 x6124 +17608 x6125 +17608 x6126 +17608 x6127 +17608 x6128 +17608 x6129 +17608 x6130 +17608 x6131 +17608 x6132 +17608 x6133 +17608 x6134 +17608 x6135 +17608 x6136 +17608 x6137 +17608 x6138 +17608 x6139 +17608 x6140 +17608 x6141 +17608 x6142 +17608 x6143 +17608 x6144 +29786 x6145 +29786 x6146 +29786 x6147 +29786 x6148 +29786 x6149 +29786 x6150 +29786 x6151 +29786 x6152 +29786 x6153 +29786 x6154 +29786 x6155 +29786 x6156 +29786 x6157 +29786 x6158 +29786 x6159 +29786 x6160 +29786 x6161 +29786 x6162 +29786 x6163 +29786 x6164 +29786 x6165 +29786 x6166 +29786 x6167 +29786 x6168 +29786 x6169 +29786 x6170 +29786 x6171 +29786 x6172 +29786 x6173 +29786 x6174 +29786 x6175 +29786 x6176 +29786 x6177 +29786 x6178 +29786 x6179 +29786 x6180 +29786 x6181 +29786 x6182 +29786 x6183 +29786 x6184 +29786 x6185 +29786 x6186 +29786 x6187 +29786 x6188 +29786 x6189 +29786 x6190 +29786 x6191 +29786 x6192 +29786 x6193 +29786 x6194 +29786 x6195 +29786 x6196 +29786 x6197 +29786 x6198 +29786 x6199 +29786 x6200 +29786 x6201 +29786 x6202 +29786 x6203 +29786 x6204 +29786 x6205 +29786 x6206 +29786 x6207 +29786 x6208 +29786 x6209 +29786 x6210 +29786 x6211 +29786 x6212 +29786 x6213 +29786 x6214 +29786 x6215 +29786 x6216 +29786 x6217 +29786 x6218 +29786 x6219 +29786 x6220 +29786 x6221 +29786 x6222 +29786 x6223 +29786 x6224 +29786 x6225 +29786 x6226 +29786 x6227 +29786 x6228 +29786 x6229 +29786 x6230 +29786 x6231 +29786 x6232 +29786 x6233 +29786 x6234 +29786 x6235 +29786 x6236 +29786 x6237 +29786 x6238 +29786 x6239 +29786 x6240 +29786 x6241 +29786 x6242 +29786 x6243 +29786 x6244 +29786 x6245 +29786 x6246 +29786 x6247 +29786 x6248 +29786 x6249 +29786 x6250 +29786 x6251 +29786 x6252 +29786 x6253 +29786 x6254 +29786 x6255 +29786 x6256 +29786 x6257 +29786 x6258 +29786 x6259 +29786 x6260 +29786 x6261 +29786 x6262 +29786 x6263 +29786 x6264 +29786 x6265 +29786 x6266 +29786 x6267 +29786 x6268 +29786 x6269 +29786 x6270 +29786 x6271 +29786 x6272 +16250 x6273 +16250 x6274 +16250 x6275 +16250 x6276 +16250 x6277 +16250 x6278 +16250 x6279 +16250 x6280 +16250 x6281 +16250 x6282 +16250 x6283 +16250 x6284 +16250 x6285 +16250 x6286 +16250 x6287 +16250 x6288 +16250 x6289 +16250 x6290 +16250 x6291 +16250 x6292 +16250 x6293 +16250 x6294 +16250 x6295 +16250 x6296 +16250 x6297 +16250 x6298 +16250 x6299 +16250 x6300 +16250 x6301 +16250 x6302 +16250 x6303 +16250 x6304 +16250 x6305 +16250 x6306 +16250 x6307 +16250 x6308 +16250 x6309 +16250 x6310 +16250 x6311 +16250 x6312 +16250 x6313 +16250 x6314 +16250 x6315 +16250 x6316 +16250 x6317 +16250 x6318 +16250 x6319 +16250 x6320 +16250 x6321 +16250 x6322 +16250 x6323 +16250 x6324 +16250 x6325 +16250 x6326 +16250 x6327 +16250 x6328 +16250 x6329 +16250 x6330 +16250 x6331 +16250 x6332 +16250 x6333 +16250 x6334 +16250 x6335 +16250 x6336 +16250 x6337 +16250 x6338 +16250 x6339 +16250 x6340 +16250 x6341 +16250 x6342 +16250 x6343 +16250 x6344 +16250 x6345 +16250 x6346 +16250 x6347 +16250 x6348 +16250 x6349 +16250 x6350 +16250 x6351 +16250 x6352 +16250 x6353 +16250 x6354 +16250 x6355 +16250 x6356 +16250 x6357 +16250 x6358 +16250 x6359 +16250 x6360 +16250 x6361 +16250 x6362 +16250 x6363 +16250 x6364 +16250 x6365 +16250 x6366 +16250 x6367 +16250 x6368 +16250 x6369 +16250 x6370 +16250 x6371 +16250 x6372 +16250 x6373 +16250 x6374 +16250 x6375 +16250 x6376 +16250 x6377 +16250 x6378 +16250 x6379 +16250 x6380 +16250 x6381 +16250 x6382 +16250 x6383 +16250 x6384 +16250 x6385 +16250 x6386 +16250 x6387 +16250 x6388 +16250 x6389 +16250 x6390 +16250 x6391 +16250 x6392 +16250 x6393 +16250 x6394 +16250 x6395 +16250 x6396 +16250 x6397 +16250 x6398 +16250 x6399 +16250 x6400 +21497 x6401 +21497 x6402 +21497 x6403 +21497 x6404 +21497 x6405 +21497 x6406 +21497 x6407 +21497 x6408 +21497 x6409 +21497 x6410 +21497 x6411 +21497 x6412 +21497 x6413 +21497 x6414 +21497 x6415 +21497 x6416 +21497 x6417 +21497 x6418 +21497 x6419 +21497 x6420 +21497 x6421 +21497 x6422 +21497 x6423 +21497 x6424 +21497 x6425 +21497 x6426 +21497 x6427 +21497 x6428 +21497 x6429 +21497 x6430 +21497 x6431 +21497 x6432 +21497 x6433 +21497 x6434 +21497 x6435 +21497 x6436 +21497 x6437 +21497 x6438 +21497 x6439 +21497 x6440 +21497 x6441 +21497 x6442 +21497 x6443 +21497 x6444 +21497 x6445 +21497 x6446 +21497 x6447 +21497 x6448 +21497 x6449 +21497 x6450 +21497 x6451 +21497 x6452 +21497 x6453 +21497 x6454 +21497 x6455 +21497 x6456 +21497 x6457 +21497 x6458 +21497 x6459 +21497 x6460 +21497 x6461 +21497 x6462 +21497 x6463 +21497 x6464 +21497 x6465 +21497 x6466 +21497 x6467 +21497 x6468 +21497 x6469 +21497 x6470 +21497 x6471 +21497 x6472 +21497 x6473 +21497 x6474 +21497 x6475 +21497 x6476 +21497 x6477 +21497 x6478 +21497 x6479 +21497 x6480 +21497 x6481 +21497 x6482 +21497 x6483 +21497 x6484 +21497 x6485 +21497 x6486 +21497 x6487 +21497 x6488 +21497 x6489 +21497 x6490 +21497 x6491 +21497 x6492 +21497 x6493 +21497 x6494 +21497 x6495 +21497 x6496 +21497 x6497 +21497 x6498 +21497 x6499 +21497 x6500 +21497 x6501 +21497 x6502 +21497 x6503 +21497 x6504 +21497 x6505 +21497 x6506 +21497 x6507 +21497 x6508 +21497 x6509 +21497 x6510 +21497 x6511 +21497 x6512 +21497 x6513 +21497 x6514 +21497 x6515 +21497 x6516 +21497 x6517 +21497 x6518 +21497 x6519 +21497 x6520 +21497 x6521 +21497 x6522 +21497 x6523 +21497 x6524 +21497 x6525 +21497 x6526 +21497 x6527 +21497 x6528 +33970 x6529 +33970 x6530 +33970 x6531 +33970 x6532 +33970 x6533 +33970 x6534 +33970 x6535 +33970 x6536 +33970 x6537 +33970 x6538 +33970 x6539 +33970 x6540 +33970 x6541 +33970 x6542 +33970 x6543 +33970 x6544 +33970 x6545 +33970 x6546 +33970 x6547 +33970 x6548 +33970 x6549 +33970 x6550 +33970 x6551 +33970 x6552 +33970 x6553 +33970 x6554 +33970 x6555 +33970 x6556 +33970 x6557 +33970 x6558 +33970 x6559 +33970 x6560 +33970 x6561 +33970 x6562 +33970 x6563 +33970 x6564 +33970 x6565 +33970 x6566 +33970 x6567 +33970 x6568 +33970 x6569 +33970 x6570 +33970 x6571 +33970 x6572 +33970 x6573 +33970 x6574 +33970 x6575 +33970 x6576 +33970 x6577 +33970 x6578 +33970 x6579 +33970 x6580 +33970 x6581 +33970 x6582 +33970 x6583 +33970 x6584 +33970 x6585 +33970 x6586 +33970 x6587 +33970 x6588 +33970 x6589 +33970 x6590 +33970 x6591 +33970 x6592 +33970 x6593 +33970 x6594 +33970 x6595 +33970 x6596 +33970 x6597 +33970 x6598 +33970 x6599 +33970 x6600 +33970 x6601 +33970 x6602 +33970 x6603 +33970 x6604 +33970 x6605 +33970 x6606 +33970 x6607 +33970 x6608 +33970 x6609 +33970 x6610 +33970 x6611 +33970 x6612 +33970 x6613 +33970 x6614 +33970 x6615 +33970 x6616 +33970 x6617 +33970 x6618 +33970 x6619 +33970 x6620 +33970 x6621 +33970 x6622 +33970 x6623 +33970 x6624 +33970 x6625 +33970 x6626 +33970 x6627 +33970 x6628 +33970 x6629 +33970 x6630 +33970 x6631 +33970 x6632 +33970 x6633 +33970 x6634 +33970 x6635 +33970 x6636 +33970 x6637 +33970 x6638 +33970 x6639 +33970 x6640 +33970 x6641 +33970 x6642 +33970 x6643 +33970 x6644 +33970 x6645 +33970 x6646 +33970 x6647 +33970 x6648 +33970 x6649 +33970 x6650 +33970 x6651 +33970 x6652 +33970 x6653 +33970 x6654 +33970 x6655 +33970 x6656 +16980 x6657 +16980 x6658 +16980 x6659 +16980 x6660 +16980 x6661 +16980 x6662 +16980 x6663 +16980 x6664 +16980 x6665 +16980 x6666 +16980 x6667 +16980 x6668 +16980 x6669 +16980 x6670 +16980 x6671 +16980 x6672 +16980 x6673 +16980 x6674 +16980 x6675 +16980 x6676 +16980 x6677 +16980 x6678 +16980 x6679 +16980 x6680 +16980 x6681 +16980 x6682 +16980 x6683 +16980 x6684 +16980 x6685 +16980 x6686 +16980 x6687 +16980 x6688 +16980 x6689 +16980 x6690 +16980 x6691 +16980 x6692 +16980 x6693 +16980 x6694 +16980 x6695 +16980 x6696 +16980 x6697 +16980 x6698 +16980 x6699 +16980 x6700 +16980 x6701 +16980 x6702 +16980 x6703 +16980 x6704 +16980 x6705 +16980 x6706 +16980 x6707 +16980 x6708 +16980 x6709 +16980 x6710 +16980 x6711 +16980 x6712 +16980 x6713 +16980 x6714 +16980 x6715 +16980 x6716 +16980 x6717 +16980 x6718 +16980 x6719 +16980 x6720 +16980 x6721 +16980 x6722 +16980 x6723 +16980 x6724 +16980 x6725 +16980 x6726 +16980 x6727 +16980 x6728 +16980 x6729 +16980 x6730 +16980 x6731 +16980 x6732 +16980 x6733 +16980 x6734 +16980 x6735 +16980 x6736 +16980 x6737 +16980 x6738 +16980 x6739 +16980 x6740 +16980 x6741 +16980 x6742 +16980 x6743 +16980 x6744 +16980 x6745 +16980 x6746 +16980 x6747 +16980 x6748 +16980 x6749 +16980 x6750 +16980 x6751 +16980 x6752 +16980 x6753 +16980 x6754 +16980 x6755 +16980 x6756 +16980 x6757 +16980 x6758 +16980 x6759 +16980 x6760 +16980 x6761 +16980 x6762 +16980 x6763 +16980 x6764 +16980 x6765 +16980 x6766 +16980 x6767 +16980 x6768 +16980 x6769 +16980 x6770 +16980 x6771 +16980 x6772 +16980 x6773 +16980 x6774 +16980 x6775 +16980 x6776 +16980 x6777 +16980 x6778 +16980 x6779 +16980 x6780 +16980 x6781 +16980 x6782 +16980 x6783 +16980 x6784 +9426 x6785 +9426 x6786 +9426 x6787 +9426 x6788 +9426 x6789 +9426 x6790 +9426 x6791 +9426 x6792 +9426 x6793 +9426 x6794 +9426 x6795 +9426 x6796 +9426 x6797 +9426 x6798 +9426 x6799 +9426 x6800 +9426 x6801 +9426 x6802 +9426 x6803 +9426 x6804 +9426 x6805 +9426 x6806 +9426 x6807 +9426 x6808 +9426 x6809 +9426 x6810 +9426 x6811 +9426 x6812 +9426 x6813 +9426 x6814 +9426 x6815 +9426 x6816 +9426 x6817 +9426 x6818 +9426 x6819 +9426 x6820 +9426 x6821 +9426 x6822 +9426 x6823 +9426 x6824 +9426 x6825 +9426 x6826 +9426 x6827 +9426 x6828 +9426 x6829 +9426 x6830 +9426 x6831 +9426 x6832 +9426 x6833 +9426 x6834 +9426 x6835 +9426 x6836 +9426 x6837 +9426 x6838 +9426 x6839 +9426 x6840 +9426 x6841 +9426 x6842 +9426 x6843 +9426 x6844 +9426 x6845 +9426 x6846 +9426 x6847 +9426 x6848 +9426 x6849 +9426 x6850 +9426 x6851 +9426 x6852 +9426 x6853 +9426 x6854 +9426 x6855 +9426 x6856 +9426 x6857 +9426 x6858 +9426 x6859 +9426 x6860 +9426 x6861 +9426 x6862 +9426 x6863 +9426 x6864 +9426 x6865 +9426 x6866 +9426 x6867 +9426 x6868 +9426 x6869 +9426 x6870 +9426 x6871 +9426 x6872 +9426 x6873 +9426 x6874 +9426 x6875 +9426 x6876 +9426 x6877 +9426 x6878 +9426 x6879 +9426 x6880 +9426 x6881 +9426 x6882 +9426 x6883 +9426 x6884 +9426 x6885 +9426 x6886 +9426 x6887 +9426 x6888 +9426 x6889 +9426 x6890 +9426 x6891 +9426 x6892 +9426 x6893 +9426 x6894 +9426 x6895 +9426 x6896 +9426 x6897 +9426 x6898 +9426 x6899 +9426 x6900 +9426 x6901 +9426 x6902 +9426 x6903 +9426 x6904 +9426 x6905 +9426 x6906 +9426 x6907 +9426 x6908 +9426 x6909 +9426 x6910 +9426 x6911 +9426 x6912 +5681 x6913 +5681 x6914 +5681 x6915 +5681 x6916 +5681 x6917 +5681 x6918 +5681 x6919 +5681 x6920 +5681 x6921 +5681 x6922 +5681 x6923 +5681 x6924 +5681 x6925 +5681 x6926 +5681 x6927 +5681 x6928 +5681 x6929 +5681 x6930 +5681 x6931 +5681 x6932 +5681 x6933 +5681 x6934 +5681 x6935 +5681 x6936 +5681 x6937 +5681 x6938 +5681 x6939 +5681 x6940 +5681 x6941 +5681 x6942 +5681 x6943 +5681 x6944 +5681 x6945 +5681 x6946 +5681 x6947 +5681 x6948 +5681 x6949 +5681 x6950 +5681 x6951 +5681 x6952 +5681 x6953 +5681 x6954 +5681 x6955 +5681 x6956 +5681 x6957 +5681 x6958 +5681 x6959 +5681 x6960 +5681 x6961 +5681 x6962 +5681 x6963 +5681 x6964 +5681 x6965 +5681 x6966 +5681 x6967 +5681 x6968 +5681 x6969 +5681 x6970 +5681 x6971 +5681 x6972 +5681 x6973 +5681 x6974 +5681 x6975 +5681 x6976 +5681 x6977 +5681 x6978 +5681 x6979 +5681 x6980 +5681 x6981 +5681 x6982 +5681 x6983 +5681 x6984 +5681 x6985 +5681 x6986 +5681 x6987 +5681 x6988 +5681 x6989 +5681 x6990 +5681 x6991 +5681 x6992 +5681 x6993 +5681 x6994 +5681 x6995 +5681 x6996 +5681 x6997 +5681 x6998 +5681 x6999 +5681 x7000 +5681 x7001 +5681 x7002 +5681 x7003 +5681 x7004 +5681 x7005 +5681 x7006 +5681 x7007 +5681 x7008 +5681 x7009 +5681 x7010 +5681 x7011 +5681 x7012 +5681 x7013 +5681 x7014 +5681 x7015 +5681 x7016 +5681 x7017 +5681 x7018 +5681 x7019 +5681 x7020 +5681 x7021 +5681 x7022 +5681 x7023 +5681 x7024 +5681 x7025 +5681 x7026 +5681 x7027 +5681 x7028 +5681 x7029 +5681 x7030 +5681 x7031 +5681 x7032 +5681 x7033 +5681 x7034 +5681 x7035 +5681 x7036 +5681 x7037 +5681 x7038 +5681 x7039 +5681 x7040 +36639 x7041 +36639 x7042 +36639 x7043 +36639 x7044 +36639 x7045 +36639 x7046 +36639 x7047 +36639 x7048 +36639 x7049 +36639 x7050 +36639 x7051 +36639 x7052 +36639 x7053 +36639 x7054 +36639 x7055 +36639 x7056 +36639 x7057 +36639 x7058 +36639 x7059 +36639 x7060 +36639 x7061 +36639 x7062 +36639 x7063 +36639 x7064 +36639 x7065 +36639 x7066 +36639 x7067 +36639 x7068 +36639 x7069 +36639 x7070 +36639 x7071 +36639 x7072 +36639 x7073 +36639 x7074 +36639 x7075 +36639 x7076 +36639 x7077 +36639 x7078 +36639 x7079 +36639 x7080 +36639 x7081 +36639 x7082 +36639 x7083 +36639 x7084 +36639 x7085 +36639 x7086 +36639 x7087 +36639 x7088 +36639 x7089 +36639 x7090 +36639 x7091 +36639 x7092 +36639 x7093 +36639 x7094 +36639 x7095 +36639 x7096 +36639 x7097 +36639 x7098 +36639 x7099 +36639 x7100 +36639 x7101 +36639 x7102 +36639 x7103 +36639 x7104 +36639 x7105 +36639 x7106 +36639 x7107 +36639 x7108 +36639 x7109 +36639 x7110 +36639 x7111 +36639 x7112 +36639 x7113 +36639 x7114 +36639 x7115 +36639 x7116 +36639 x7117 +36639 x7118 +36639 x7119 +36639 x7120 +36639 x7121 +36639 x7122 +36639 x7123 +36639 x7124 +36639 x7125 +36639 x7126 +36639 x7127 +36639 x7128 +36639 x7129 +36639 x7130 +36639 x7131 +36639 x7132 +36639 x7133 +36639 x7134 +36639 x7135 +36639 x7136 +36639 x7137 +36639 x7138 +36639 x7139 +36639 x7140 +36639 x7141 +36639 x7142 +36639 x7143 +36639 x7144 +36639 x7145 +36639 x7146 +36639 x7147 +36639 x7148 +36639 x7149 +36639 x7150 +36639 x7151 +36639 x7152 +36639 x7153 +36639 x7154 +36639 x7155 +36639 x7156 +36639 x7157 +36639 x7158 +36639 x7159 +36639 x7160 +36639 x7161 +36639 x7162 +36639 x7163 +36639 x7164 +36639 x7165 +36639 x7166 +36639 x7167 +36639 x7168 +11741 x7169 +11741 x7170 +11741 x7171 +11741 x7172 +11741 x7173 +11741 x7174 +11741 x7175 +11741 x7176 +11741 x7177 +11741 x7178 +11741 x7179 +11741 x7180 +11741 x7181 +11741 x7182 +11741 x7183 +11741 x7184 +11741 x7185 +11741 x7186 +11741 x7187 +11741 x7188 +11741 x7189 +11741 x7190 +11741 x7191 +11741 x7192 +11741 x7193 +11741 x7194 +11741 x7195 +11741 x7196 +11741 x7197 +11741 x7198 +11741 x7199 +11741 x7200 +11741 x7201 +11741 x7202 +11741 x7203 +11741 x7204 +11741 x7205 +11741 x7206 +11741 x7207 +11741 x7208 +11741 x7209 +11741 x7210 +11741 x7211 +11741 x7212 +11741 x7213 +11741 x7214 +11741 x7215 +11741 x7216 +11741 x7217 +11741 x7218 +11741 x7219 +11741 x7220 +11741 x7221 +11741 x7222 +11741 x7223 +11741 x7224 +11741 x7225 +11741 x7226 +11741 x7227 +11741 x7228 +11741 x7229 +11741 x7230 +11741 x7231 +11741 x7232 +11741 x7233 +11741 x7234 +11741 x7235 +11741 x7236 +11741 x7237 +11741 x7238 +11741 x7239 +11741 x7240 +11741 x7241 +11741 x7242 +11741 x7243 +11741 x7244 +11741 x7245 +11741 x7246 +11741 x7247 +11741 x7248 +11741 x7249 +11741 x7250 +11741 x7251 +11741 x7252 +11741 x7253 +11741 x7254 +11741 x7255 +11741 x7256 +11741 x7257 +11741 x7258 +11741 x7259 +11741 x7260 +11741 x7261 +11741 x7262 +11741 x7263 +11741 x7264 +11741 x7265 +11741 x7266 +11741 x7267 +11741 x7268 +11741 x7269 +11741 x7270 +11741 x7271 +11741 x7272 +11741 x7273 +11741 x7274 +11741 x7275 +11741 x7276 +11741 x7277 +11741 x7278 +11741 x7279 +11741 x7280 +11741 x7281 +11741 x7282 +11741 x7283 +11741 x7284 +11741 x7285 +11741 x7286 +11741 x7287 +11741 x7288 +11741 x7289 +11741 x7290 +11741 x7291 +11741 x7292 +11741 x7293 +11741 x7294 +11741 x7295 +11741 x7296 +21677 x7297 +21677 x7298 +21677 x7299 +21677 x7300 +21677 x7301 +21677 x7302 +21677 x7303 +21677 x7304 +21677 x7305 +21677 x7306 +21677 x7307 +21677 x7308 +21677 x7309 +21677 x7310 +21677 x7311 +21677 x7312 +21677 x7313 +21677 x7314 +21677 x7315 +21677 x7316 +21677 x7317 +21677 x7318 +21677 x7319 +21677 x7320 +21677 x7321 +21677 x7322 +21677 x7323 +21677 x7324 +21677 x7325 +21677 x7326 +21677 x7327 +21677 x7328 +21677 x7329 +21677 x7330 +21677 x7331 +21677 x7332 +21677 x7333 +21677 x7334 +21677 x7335 +21677 x7336 +21677 x7337 +21677 x7338 +21677 x7339 +21677 x7340 +21677 x7341 +21677 x7342 +21677 x7343 +21677 x7344 +21677 x7345 +21677 x7346 +21677 x7347 +21677 x7348 +21677 x7349 +21677 x7350 +21677 x7351 +21677 x7352 +21677 x7353 +21677 x7354 +21677 x7355 +21677 x7356 +21677 x7357 +21677 x7358 +21677 x7359 +21677 x7360 +21677 x7361 +21677 x7362 +21677 x7363 +21677 x7364 +21677 x7365 +21677 x7366 +21677 x7367 +21677 x7368 +21677 x7369 +21677 x7370 +21677 x7371 +21677 x7372 +21677 x7373 +21677 x7374 +21677 x7375 +21677 x7376 +21677 x7377 +21677 x7378 +21677 x7379 +21677 x7380 +21677 x7381 +21677 x7382 +21677 x7383 +21677 x7384 +21677 x7385 +21677 x7386 +21677 x7387 +21677 x7388 +21677 x7389 +21677 x7390 +21677 x7391 +21677 x7392 +21677 x7393 +21677 x7394 +21677 x7395 +21677 x7396 +21677 x7397 +21677 x7398 +21677 x7399 +21677 x7400 +21677 x7401 +21677 x7402 +21677 x7403 +21677 x7404 +21677 x7405 +21677 x7406 +21677 x7407 +21677 x7408 +21677 x7409 +21677 x7410 +21677 x7411 +21677 x7412 +21677 x7413 +21677 x7414 +21677 x7415 +21677 x7416 +21677 x7417 +21677 x7418 +21677 x7419 +21677 x7420 +21677 x7421 +21677 x7422 +21677 x7423 +21677 x7424 +10911 x7425 +10911 x7426 +10911 x7427 +10911 x7428 +10911 x7429 +10911 x7430 +10911 x7431 +10911 x7432 +10911 x7433 +10911 x7434 +10911 x7435 +10911 x7436 +10911 x7437 +10911 x7438 +10911 x7439 +10911 x7440 +10911 x7441 +10911 x7442 +10911 x7443 +10911 x7444 +10911 x7445 +10911 x7446 +10911 x7447 +10911 x7448 +10911 x7449 +10911 x7450 +10911 x7451 +10911 x7452 +10911 x7453 +10911 x7454 +10911 x7455 +10911 x7456 +10911 x7457 +10911 x7458 +10911 x7459 +10911 x7460 +10911 x7461 +10911 x7462 +10911 x7463 +10911 x7464 +10911 x7465 +10911 x7466 +10911 x7467 +10911 x7468 +10911 x7469 +10911 x7470 +10911 x7471 +10911 x7472 +10911 x7473 +10911 x7474 +10911 x7475 +10911 x7476 +10911 x7477 +10911 x7478 +10911 x7479 +10911 x7480 +10911 x7481 +10911 x7482 +10911 x7483 +10911 x7484 +10911 x7485 +10911 x7486 +10911 x7487 +10911 x7488 +10911 x7489 +10911 x7490 +10911 x7491 +10911 x7492 +10911 x7493 +10911 x7494 +10911 x7495 +10911 x7496 +10911 x7497 +10911 x7498 +10911 x7499 +10911 x7500 +10911 x7501 +10911 x7502 +10911 x7503 +10911 x7504 +10911 x7505 +10911 x7506 +10911 x7507 +10911 x7508 +10911 x7509 +10911 x7510 +10911 x7511 +10911 x7512 +10911 x7513 +10911 x7514 +10911 x7515 +10911 x7516 +10911 x7517 +10911 x7518 +10911 x7519 +10911 x7520 +10911 x7521 +10911 x7522 +10911 x7523 +10911 x7524 +10911 x7525 +10911 x7526 +10911 x7527 +10911 x7528 +10911 x7529 +10911 x7530 +10911 x7531 +10911 x7532 +10911 x7533 +10911 x7534 +10911 x7535 +10911 x7536 +10911 x7537 +10911 x7538 +10911 x7539 +10911 x7540 +10911 x7541 +10911 x7542 +10911 x7543 +10911 x7544 +10911 x7545 +10911 x7546 +10911 x7547 +10911 x7548 +10911 x7549 +10911 x7550 +10911 x7551 +10911 x7552 +50223 x7553 +50223 x7554 +50223 x7555 +50223 x7556 +50223 x7557 +50223 x7558 +50223 x7559 +50223 x7560 +50223 x7561 +50223 x7562 +50223 x7563 +50223 x7564 +50223 x7565 +50223 x7566 +50223 x7567 +50223 x7568 +50223 x7569 +50223 x7570 +50223 x7571 +50223 x7572 +50223 x7573 +50223 x7574 +50223 x7575 +50223 x7576 +50223 x7577 +50223 x7578 +50223 x7579 +50223 x7580 +50223 x7581 +50223 x7582 +50223 x7583 +50223 x7584 +50223 x7585 +50223 x7586 +50223 x7587 +50223 x7588 +50223 x7589 +50223 x7590 +50223 x7591 +50223 x7592 +50223 x7593 +50223 x7594 +50223 x7595 +50223 x7596 +50223 x7597 +50223 x7598 +50223 x7599 +50223 x7600 +50223 x7601 +50223 x7602 +50223 x7603 +50223 x7604 +50223 x7605 +50223 x7606 +50223 x7607 +50223 x7608 +50223 x7609 +50223 x7610 +50223 x7611 +50223 x7612 +50223 x7613 +50223 x7614 +50223 x7615 +50223 x7616 +50223 x7617 +50223 x7618 +50223 x7619 +50223 x7620 +50223 x7621 +50223 x7622 +50223 x7623 +50223 x7624 +50223 x7625 +50223 x7626 +50223 x7627 +50223 x7628 +50223 x7629 +50223 x7630 +50223 x7631 +50223 x7632 +50223 x7633 +50223 x7634 +50223 x7635 +50223 x7636 +50223 x7637 +50223 x7638 +50223 x7639 +50223 x7640 +50223 x7641 +50223 x7642 +50223 x7643 +50223 x7644 +50223 x7645 +50223 x7646 +50223 x7647 +50223 x7648 +50223 x7649 +50223 x7650 +50223 x7651 +50223 x7652 +50223 x7653 +50223 x7654 +50223 x7655 +50223 x7656 +50223 x7657 +50223 x7658 +50223 x7659 +50223 x7660 +50223 x7661 +50223 x7662 +50223 x7663 +50223 x7664 +50223 x7665 +50223 x7666 +50223 x7667 +50223 x7668 +50223 x7669 +50223 x7670 +50223 x7671 +50223 x7672 +50223 x7673 +50223 x7674 +50223 x7675 +50223 x7676 +50223 x7677 +50223 x7678 +50223 x7679 +50223 x7680 +12480 x7681 +12480 x7682 +12480 x7683 +12480 x7684 +12480 x7685 +12480 x7686 +12480 x7687 +12480 x7688 +12480 x7689 +12480 x7690 +12480 x7691 +12480 x7692 +12480 x7693 +12480 x7694 +12480 x7695 +12480 x7696 +12480 x7697 +12480 x7698 +12480 x7699 +12480 x7700 +12480 x7701 +12480 x7702 +12480 x7703 +12480 x7704 +12480 x7705 +12480 x7706 +12480 x7707 +12480 x7708 +12480 x7709 +12480 x7710 +12480 x7711 +12480 x7712 +12480 x7713 +12480 x7714 +12480 x7715 +12480 x7716 +12480 x7717 +12480 x7718 +12480 x7719 +12480 x7720 +12480 x7721 +12480 x7722 +12480 x7723 +12480 x7724 +12480 x7725 +12480 x7726 +12480 x7727 +12480 x7728 +12480 x7729 +12480 x7730 +12480 x7731 +12480 x7732 +12480 x7733 +12480 x7734 +12480 x7735 +12480 x7736 +12480 x7737 +12480 x7738 +12480 x7739 +12480 x7740 +12480 x7741 +12480 x7742 +12480 x7743 +12480 x7744 +12480 x7745 +12480 x7746 +12480 x7747 +12480 x7748 +12480 x7749 +12480 x7750 +12480 x7751 +12480 x7752 +12480 x7753 +12480 x7754 +12480 x7755 +12480 x7756 +12480 x7757 +12480 x7758 +12480 x7759 +12480 x7760 +12480 x7761 +12480 x7762 +12480 x7763 +12480 x7764 +12480 x7765 +12480 x7766 +12480 x7767 +12480 x7768 +12480 x7769 +12480 x7770 +12480 x7771 +12480 x7772 +12480 x7773 +12480 x7774 +12480 x7775 +12480 x7776 +12480 x7777 +12480 x7778 +12480 x7779 +12480 x7780 +12480 x7781 +12480 x7782 +12480 x7783 +12480 x7784 +12480 x7785 +12480 x7786 +12480 x7787 +12480 x7788 +12480 x7789 +12480 x7790 +12480 x7791 +12480 x7792 +12480 x7793 +12480 x7794 +12480 x7795 +12480 x7796 +12480 x7797 +12480 x7798 +12480 x7799 +12480 x7800 +12480 x7801 +12480 x7802 +12480 x7803 +12480 x7804 +12480 x7805 +12480 x7806 +12480 x7807 +12480 x7808 +29948 x7809 +29948 x7810 +29948 x7811 +29948 x7812 +29948 x7813 +29948 x7814 +29948 x7815 +29948 x7816 +29948 x7817 +29948 x7818 +29948 x7819 +29948 x7820 +29948 x7821 +29948 x7822 +29948 x7823 +29948 x7824 +29948 x7825 +29948 x7826 +29948 x7827 +29948 x7828 +29948 x7829 +29948 x7830 +29948 x7831 +29948 x7832 +29948 x7833 +29948 x7834 +29948 x7835 +29948 x7836 +29948 x7837 +29948 x7838 +29948 x7839 +29948 x7840 +29948 x7841 +29948 x7842 +29948 x7843 +29948 x7844 +29948 x7845 +29948 x7846 +29948 x7847 +29948 x7848 +29948 x7849 +29948 x7850 +29948 x7851 +29948 x7852 +29948 x7853 +29948 x7854 +29948 x7855 +29948 x7856 +29948 x7857 +29948 x7858 +29948 x7859 +29948 x7860 +29948 x7861 +29948 x7862 +29948 x7863 +29948 x7864 +29948 x7865 +29948 x7866 +29948 x7867 +29948 x7868 +29948 x7869 +29948 x7870 +29948 x7871 +29948 x7872 +29948 x7873 +29948 x7874 +29948 x7875 +29948 x7876 +29948 x7877 +29948 x7878 +29948 x7879 +29948 x7880 +29948 x7881 +29948 x7882 +29948 x7883 +29948 x7884 +29948 x7885 +29948 x7886 +29948 x7887 +29948 x7888 +29948 x7889 +29948 x7890 +29948 x7891 +29948 x7892 +29948 x7893 +29948 x7894 +29948 x7895 +29948 x7896 +29948 x7897 +29948 x7898 +29948 x7899 +29948 x7900 +29948 x7901 +29948 x7902 +29948 x7903 +29948 x7904 +29948 x7905 +29948 x7906 +29948 x7907 +29948 x7908 +29948 x7909 +29948 x7910 +29948 x7911 +29948 x7912 +29948 x7913 +29948 x7914 +29948 x7915 +29948 x7916 +29948 x7917 +29948 x7918 +29948 x7919 +29948 x7920 +29948 x7921 +29948 x7922 +29948 x7923 +29948 x7924 +29948 x7925 +29948 x7926 +29948 x7927 +29948 x7928 +29948 x7929 +29948 x7930 +29948 x7931 +29948 x7932 +29948 x7933 +29948 x7934 +29948 x7935 +29948 x7936 +17308 x7937 +17308 x7938 +17308 x7939 +17308 x7940 +17308 x7941 +17308 x7942 +17308 x7943 +17308 x7944 +17308 x7945 +17308 x7946 +17308 x7947 +17308 x7948 +17308 x7949 +17308 x7950 +17308 x7951 +17308 x7952 +17308 x7953 +17308 x7954 +17308 x7955 +17308 x7956 +17308 x7957 +17308 x7958 +17308 x7959 +17308 x7960 +17308 x7961 +17308 x7962 +17308 x7963 +17308 x7964 +17308 x7965 +17308 x7966 +17308 x7967 +17308 x7968 +17308 x7969 +17308 x7970 +17308 x7971 +17308 x7972 +17308 x7973 +17308 x7974 +17308 x7975 +17308 x7976 +17308 x7977 +17308 x7978 +17308 x7979 +17308 x7980 +17308 x7981 +17308 x7982 +17308 x7983 +17308 x7984 +17308 x7985 +17308 x7986 +17308 x7987 +17308 x7988 +17308 x7989 +17308 x7990 +17308 x7991 +17308 x7992 +17308 x7993 +17308 x7994 +17308 x7995 +17308 x7996 +17308 x7997 +17308 x7998 +17308 x7999 +17308 x8000 +17308 x8001 +17308 x8002 +17308 x8003 +17308 x8004 +17308 x8005 +17308 x8006 +17308 x8007 +17308 x8008 +17308 x8009 +17308 x8010 +17308 x8011 +17308 x8012 +17308 x8013 +17308 x8014 +17308 x8015 +17308 x8016 +17308 x8017 +17308 x8018 +17308 x8019 +17308 x8020 +17308 x8021 +17308 x8022 +17308 x8023 +17308 x8024 +17308 x8025 +17308 x8026 +17308 x8027 +17308 x8028 +17308 x8029 +17308 x8030 +17308 x8031 +17308 x8032 +17308 x8033 +17308 x8034 +17308 x8035 +17308 x8036 +17308 x8037 +17308 x8038 +17308 x8039 +17308 x8040 +17308 x8041 +17308 x8042 +17308 x8043 +17308 x8044 +17308 x8045 +17308 x8046 +17308 x8047 +17308 x8048 +17308 x8049 +17308 x8050 +17308 x8051 +17308 x8052 +17308 x8053 +17308 x8054 +17308 x8055 +17308 x8056 +17308 x8057 +17308 x8058 +17308 x8059 +17308 x8060 +17308 x8061 +17308 x8062 +17308 x8063 +17308 x8064 +38039 x8065 +38039 x8066 +38039 x8067 +38039 x8068 +38039 x8069 +38039 x8070 +38039 x8071 +38039 x8072 +38039 x8073 +38039 x8074 +38039 x8075 +38039 x8076 +38039 x8077 +38039 x8078 +38039 x8079 +38039 x8080 +38039 x8081 +38039 x8082 +38039 x8083 +38039 x8084 +38039 x8085 +38039 x8086 +38039 x8087 +38039 x8088 +38039 x8089 +38039 x8090 +38039 x8091 +38039 x8092 +38039 x8093 +38039 x8094 +38039 x8095 +38039 x8096 +38039 x8097 +38039 x8098 +38039 x8099 +38039 x8100 +38039 x8101 +38039 x8102 +38039 x8103 +38039 x8104 +38039 x8105 +38039 x8106 +38039 x8107 +38039 x8108 +38039 x8109 +38039 x8110 +38039 x8111 +38039 x8112 +38039 x8113 +38039 x8114 +38039 x8115 +38039 x8116 +38039 x8117 +38039 x8118 +38039 x8119 +38039 x8120 +38039 x8121 +38039 x8122 +38039 x8123 +38039 x8124 +38039 x8125 +38039 x8126 +38039 x8127 +38039 x8128 +38039 x8129 +38039 x8130 +38039 x8131 +38039 x8132 +38039 x8133 +38039 x8134 +38039 x8135 +38039 x8136 +38039 x8137 +38039 x8138 +38039 x8139 +38039 x8140 +38039 x8141 +38039 x8142 +38039 x8143 +38039 x8144 +38039 x8145 +38039 x8146 +38039 x8147 +38039 x8148 +38039 x8149 +38039 x8150 +38039 x8151 +38039 x8152 +38039 x8153 +38039 x8154 +38039 x8155 +38039 x8156 +38039 x8157 +38039 x8158 +38039 x8159 +38039 x8160 +38039 x8161 +38039 x8162 +38039 x8163 +38039 x8164 +38039 x8165 +38039 x8166 +38039 x8167 +38039 x8168 +38039 x8169 +38039 x8170 +38039 x8171 +38039 x8172 +38039 x8173 +38039 x8174 +38039 x8175 +38039 x8176 +38039 x8177 +38039 x8178 +38039 x8179 +38039 x8180 +38039 x8181 +38039 x8182 +38039 x8183 +38039 x8184 +38039 x8185 +38039 x8186 +38039 x8187 +38039 x8188 +38039 x8189 +38039 x8190 +38039 x8191 +38039 x8192 +49838 x8193 +49838 x8194 +49838 x8195 +49838 x8196 +49838 x8197 +49838 x8198 +49838 x8199 +49838 x8200 +49838 x8201 +49838 x8202 +49838 x8203 +49838 x8204 +49838 x8205 +49838 x8206 +49838 x8207 +49838 x8208 +49838 x8209 +49838 x8210 +49838 x8211 +49838 x8212 +49838 x8213 +49838 x8214 +49838 x8215 +49838 x8216 +49838 x8217 +49838 x8218 +49838 x8219 +49838 x8220 +49838 x8221 +49838 x8222 +49838 x8223 +49838 x8224 +49838 x8225 +49838 x8226 +49838 x8227 +49838 x8228 +49838 x8229 +49838 x8230 +49838 x8231 +49838 x8232 +49838 x8233 +49838 x8234 +49838 x8235 +49838 x8236 +49838 x8237 +49838 x8238 +49838 x8239 +49838 x8240 +49838 x8241 +49838 x8242 +49838 x8243 +49838 x8244 +49838 x8245 +49838 x8246 +49838 x8247 +49838 x8248 +49838 x8249 +49838 x8250 +49838 x8251 +49838 x8252 +49838 x8253 +49838 x8254 +49838 x8255 +49838 x8256 +49838 x8257 +49838 x8258 +49838 x8259 +49838 x8260 +49838 x8261 +49838 x8262 +49838 x8263 +49838 x8264 +49838 x8265 +49838 x8266 +49838 x8267 +49838 x8268 +49838 x8269 +49838 x8270 +49838 x8271 +49838 x8272 +49838 x8273 +49838 x8274 +49838 x8275 +49838 x8276 +49838 x8277 +49838 x8278 +49838 x8279 +49838 x8280 +49838 x8281 +49838 x8282 +49838 x8283 +49838 x8284 +49838 x8285 +49838 x8286 +49838 x8287 +49838 x8288 +49838 x8289 +49838 x8290 +49838 x8291 +49838 x8292 +49838 x8293 +49838 x8294 +49838 x8295 +49838 x8296 +49838 x8297 +49838 x8298 +49838 x8299 +49838 x8300 +49838 x8301 +49838 x8302 +49838 x8303 +49838 x8304 +49838 x8305 +49838 x8306 +49838 x8307 +49838 x8308 +49838 x8309 +49838 x8310 +49838 x8311 +49838 x8312 +49838 x8313 +49838 x8314 +49838 x8315 +49838 x8316 +49838 x8317 +49838 x8318 +49838 x8319 +49838 x8320 +9341 x8321 +9341 x8322 +9341 x8323 +9341 x8324 +9341 x8325 +9341 x8326 +9341 x8327 +9341 x8328 +9341 x8329 +9341 x8330 +9341 x8331 +9341 x8332 +9341 x8333 +9341 x8334 +9341 x8335 +9341 x8336 +9341 x8337 +9341 x8338 +9341 x8339 +9341 x8340 +9341 x8341 +9341 x8342 +9341 x8343 +9341 x8344 +9341 x8345 +9341 x8346 +9341 x8347 +9341 x8348 +9341 x8349 +9341 x8350 +9341 x8351 +9341 x8352 +9341 x8353 +9341 x8354 +9341 x8355 +9341 x8356 +9341 x8357 +9341 x8358 +9341 x8359 +9341 x8360 +9341 x8361 +9341 x8362 +9341 x8363 +9341 x8364 +9341 x8365 +9341 x8366 +9341 x8367 +9341 x8368 +9341 x8369 +9341 x8370 +9341 x8371 +9341 x8372 +9341 x8373 +9341 x8374 +9341 x8375 +9341 x8376 +9341 x8377 +9341 x8378 +9341 x8379 +9341 x8380 +9341 x8381 +9341 x8382 +9341 x8383 +9341 x8384 +9341 x8385 +9341 x8386 +9341 x8387 +9341 x8388 +9341 x8389 +9341 x8390 +9341 x8391 +9341 x8392 +9341 x8393 +9341 x8394 +9341 x8395 +9341 x8396 +9341 x8397 +9341 x8398 +9341 x8399 +9341 x8400 +9341 x8401 +9341 x8402 +9341 x8403 +9341 x8404 +9341 x8405 +9341 x8406 +9341 x8407 +9341 x8408 +9341 x8409 +9341 x8410 +9341 x8411 +9341 x8412 +9341 x8413 +9341 x8414 +9341 x8415 +9341 x8416 +9341 x8417 +9341 x8418 +9341 x8419 +9341 x8420 +9341 x8421 +9341 x8422 +9341 x8423 +9341 x8424 +9341 x8425 +9341 x8426 +9341 x8427 +9341 x8428 +9341 x8429 +9341 x8430 +9341 x8431 +9341 x8432 +9341 x8433 +9341 x8434 +9341 x8435 +9341 x8436 +9341 x8437 +9341 x8438 +9341 x8439 +9341 x8440 +9341 x8441 +9341 x8442 +9341 x8443 +9341 x8444 +9341 x8445 +9341 x8446 +9341 x8447 +9341 x8448 +48627 x8449 +48627 x8450 +48627 x8451 +48627 x8452 +48627 x8453 +48627 x8454 +48627 x8455 +48627 x8456 +48627 x8457 +48627 x8458 +48627 x8459 +48627 x8460 +48627 x8461 +48627 x8462 +48627 x8463 +48627 x8464 +48627 x8465 +48627 x8466 +48627 x8467 +48627 x8468 +48627 x8469 +48627 x8470 +48627 x8471 +48627 x8472 +48627 x8473 +48627 x8474 +48627 x8475 +48627 x8476 +48627 x8477 +48627 x8478 +48627 x8479 +48627 x8480 +48627 x8481 +48627 x8482 +48627 x8483 +48627 x8484 +48627 x8485 +48627 x8486 +48627 x8487 +48627 x8488 +48627 x8489 +48627 x8490 +48627 x8491 +48627 x8492 +48627 x8493 +48627 x8494 +48627 x8495 +48627 x8496 +48627 x8497 +48627 x8498 +48627 x8499 +48627 x8500 +48627 x8501 +48627 x8502 +48627 x8503 +48627 x8504 +48627 x8505 +48627 x8506 +48627 x8507 +48627 x8508 +48627 x8509 +48627 x8510 +48627 x8511 +48627 x8512 +48627 x8513 +48627 x8514 +48627 x8515 +48627 x8516 +48627 x8517 +48627 x8518 +48627 x8519 +48627 x8520 +48627 x8521 +48627 x8522 +48627 x8523 +48627 x8524 +48627 x8525 +48627 x8526 +48627 x8527 +48627 x8528 +48627 x8529 +48627 x8530 +48627 x8531 +48627 x8532 +48627 x8533 +48627 x8534 +48627 x8535 +48627 x8536 +48627 x8537 +48627 x8538 +48627 x8539 +48627 x8540 +48627 x8541 +48627 x8542 +48627 x8543 +48627 x8544 +48627 x8545 +48627 x8546 +48627 x8547 +48627 x8548 +48627 x8549 +48627 x8550 +48627 x8551 +48627 x8552 +48627 x8553 +48627 x8554 +48627 x8555 +48627 x8556 +48627 x8557 +48627 x8558 +48627 x8559 +48627 x8560 +48627 x8561 +48627 x8562 +48627 x8563 +48627 x8564 +48627 x8565 +48627 x8566 +48627 x8567 +48627 x8568 +48627 x8569 +48627 x8570 +48627 x8571 +48627 x8572 +48627 x8573 +48627 x8574 +48627 x8575 +48627 x8576 +7794 x8577 +7794 x8578 +7794 x8579 +7794 x8580 +7794 x8581 +7794 x8582 +7794 x8583 +7794 x8584 +7794 x8585 +7794 x8586 +7794 x8587 +7794 x8588 +7794 x8589 +7794 x8590 +7794 x8591 +7794 x8592 +7794 x8593 +7794 x8594 +7794 x8595 +7794 x8596 +7794 x8597 +7794 x8598 +7794 x8599 +7794 x8600 +7794 x8601 +7794 x8602 +7794 x8603 +7794 x8604 +7794 x8605 +7794 x8606 +7794 x8607 +7794 x8608 +7794 x8609 +7794 x8610 +7794 x8611 +7794 x8612 +7794 x8613 +7794 x8614 +7794 x8615 +7794 x8616 +7794 x8617 +7794 x8618 +7794 x8619 +7794 x8620 +7794 x8621 +7794 x8622 +7794 x8623 +7794 x8624 +7794 x8625 +7794 x8626 +7794 x8627 +7794 x8628 +7794 x8629 +7794 x8630 +7794 x8631 +7794 x8632 +7794 x8633 +7794 x8634 +7794 x8635 +7794 x8636 +7794 x8637 +7794 x8638 +7794 x8639 +7794 x8640 +7794 x8641 +7794 x8642 +7794 x8643 +7794 x8644 +7794 x8645 +7794 x8646 +7794 x8647 +7794 x8648 +7794 x8649 +7794 x8650 +7794 x8651 +7794 x8652 +7794 x8653 +7794 x8654 +7794 x8655 +7794 x8656 +7794 x8657 +7794 x8658 +7794 x8659 +7794 x8660 +7794 x8661 +7794 x8662 +7794 x8663 +7794 x8664 +7794 x8665 +7794 x8666 +7794 x8667 +7794 x8668 +7794 x8669 +7794 x8670 +7794 x8671 +7794 x8672 +7794 x8673 +7794 x8674 +7794 x8675 +7794 x8676 +7794 x8677 +7794 x8678 +7794 x8679 +7794 x8680 +7794 x8681 +7794 x8682 +7794 x8683 +7794 x8684 +7794 x8685 +7794 x8686 +7794 x8687 +7794 x8688 +7794 x8689 +7794 x8690 +7794 x8691 +7794 x8692 +7794 x8693 +7794 x8694 +7794 x8695 +7794 x8696 +7794 x8697 +7794 x8698 +7794 x8699 +7794 x8700 +7794 x8701 +7794 x8702 +7794 x8703 +7794 x8704 +47560 x8705 +47560 x8706 +47560 x8707 +47560 x8708 +47560 x8709 +47560 x8710 +47560 x8711 +47560 x8712 +47560 x8713 +47560 x8714 +47560 x8715 +47560 x8716 +47560 x8717 +47560 x8718 +47560 x8719 +47560 x8720 +47560 x8721 +47560 x8722 +47560 x8723 +47560 x8724 +47560 x8725 +47560 x8726 +47560 x8727 +47560 x8728 +47560 x8729 +47560 x8730 +47560 x8731 +47560 x8732 +47560 x8733 +47560 x8734 +47560 x8735 +47560 x8736 +47560 x8737 +47560 x8738 +47560 x8739 +47560 x8740 +47560 x8741 +47560 x8742 +47560 x8743 +47560 x8744 +47560 x8745 +47560 x8746 +47560 x8747 +47560 x8748 +47560 x8749 +47560 x8750 +47560 x8751 +47560 x8752 +47560 x8753 +47560 x8754 +47560 x8755 +47560 x8756 +47560 x8757 +47560 x8758 +47560 x8759 +47560 x8760 +47560 x8761 +47560 x8762 +47560 x8763 +47560 x8764 +47560 x8765 +47560 x8766 +47560 x8767 +47560 x8768 +47560 x8769 +47560 x8770 +47560 x8771 +47560 x8772 +47560 x8773 +47560 x8774 +47560 x8775 +47560 x8776 +47560 x8777 +47560 x8778 +47560 x8779 +47560 x8780 +47560 x8781 +47560 x8782 +47560 x8783 +47560 x8784 +47560 x8785 +47560 x8786 +47560 x8787 +47560 x8788 +47560 x8789 +47560 x8790 +47560 x8791 +47560 x8792 +47560 x8793 +47560 x8794 +47560 x8795 +47560 x8796 +47560 x8797 +47560 x8798 +47560 x8799 +47560 x8800 +47560 x8801 +47560 x8802 +47560 x8803 +47560 x8804 +47560 x8805 +47560 x8806 +47560 x8807 +47560 x8808 +47560 x8809 +47560 x8810 +47560 x8811 +47560 x8812 +47560 x8813 +47560 x8814 +47560 x8815 +47560 x8816 +47560 x8817 +47560 x8818 +47560 x8819 +47560 x8820 +47560 x8821 +47560 x8822 +47560 x8823 +47560 x8824 +47560 x8825 +47560 x8826 +47560 x8827 +47560 x8828 +47560 x8829 +47560 x8830 +47560 x8831 +47560 x8832 +34135 x8833 +34135 x8834 +34135 x8835 +34135 x8836 +34135 x8837 +34135 x8838 +34135 x8839 +34135 x8840 +34135 x8841 +34135 x8842 +34135 x8843 +34135 x8844 +34135 x8845 +34135 x8846 +34135 x8847 +34135 x8848 +34135 x8849 +34135 x8850 +34135 x8851 +34135 x8852 +34135 x8853 +34135 x8854 +34135 x8855 +34135 x8856 +34135 x8857 +34135 x8858 +34135 x8859 +34135 x8860 +34135 x8861 +34135 x8862 +34135 x8863 +34135 x8864 +34135 x8865 +34135 x8866 +34135 x8867 +34135 x8868 +34135 x8869 +34135 x8870 +34135 x8871 +34135 x8872 +34135 x8873 +34135 x8874 +34135 x8875 +34135 x8876 +34135 x8877 +34135 x8878 +34135 x8879 +34135 x8880 +34135 x8881 +34135 x8882 +34135 x8883 +34135 x8884 +34135 x8885 +34135 x8886 +34135 x8887 +34135 x8888 +34135 x8889 +34135 x8890 +34135 x8891 +34135 x8892 +34135 x8893 +34135 x8894 +34135 x8895 +34135 x8896 +34135 x8897 +34135 x8898 +34135 x8899 +34135 x8900 +34135 x8901 +34135 x8902 +34135 x8903 +34135 x8904 +34135 x8905 +34135 x8906 +34135 x8907 +34135 x8908 +34135 x8909 +34135 x8910 +34135 x8911 +34135 x8912 +34135 x8913 +34135 x8914 +34135 x8915 +34135 x8916 +34135 x8917 +34135 x8918 +34135 x8919 +34135 x8920 +34135 x8921 +34135 x8922 +34135 x8923 +34135 x8924 +34135 x8925 +34135 x8926 +34135 x8927 +34135 x8928 +34135 x8929 +34135 x8930 +34135 x8931 +34135 x8932 +34135 x8933 +34135 x8934 +34135 x8935 +34135 x8936 +34135 x8937 +34135 x8938 +34135 x8939 +34135 x8940 +34135 x8941 +34135 x8942 +34135 x8943 +34135 x8944 +34135 x8945 +34135 x8946 +34135 x8947 +34135 x8948 +34135 x8949 +34135 x8950 +34135 x8951 +34135 x8952 +34135 x8953 +34135 x8954 +34135 x8955 +34135 x8956 +34135 x8957 +34135 x8958 +34135 x8959 +34135 x8960 +21575 x8961 +21575 x8962 +21575 x8963 +21575 x8964 +21575 x8965 +21575 x8966 +21575 x8967 +21575 x8968 +21575 x8969 +21575 x8970 +21575 x8971 +21575 x8972 +21575 x8973 +21575 x8974 +21575 x8975 +21575 x8976 +21575 x8977 +21575 x8978 +21575 x8979 +21575 x8980 +21575 x8981 +21575 x8982 +21575 x8983 +21575 x8984 +21575 x8985 +21575 x8986 +21575 x8987 +21575 x8988 +21575 x8989 +21575 x8990 +21575 x8991 +21575 x8992 +21575 x8993 +21575 x8994 +21575 x8995 +21575 x8996 +21575 x8997 +21575 x8998 +21575 x8999 +21575 x9000 +21575 x9001 +21575 x9002 +21575 x9003 +21575 x9004 +21575 x9005 +21575 x9006 +21575 x9007 +21575 x9008 +21575 x9009 +21575 x9010 +21575 x9011 +21575 x9012 +21575 x9013 +21575 x9014 +21575 x9015 +21575 x9016 +21575 x9017 +21575 x9018 +21575 x9019 +21575 x9020 +21575 x9021 +21575 x9022 +21575 x9023 +21575 x9024 +21575 x9025 +21575 x9026 +21575 x9027 +21575 x9028 +21575 x9029 +21575 x9030 +21575 x9031 +21575 x9032 +21575 x9033 +21575 x9034 +21575 x9035 +21575 x9036 +21575 x9037 +21575 x9038 +21575 x9039 +21575 x9040 +21575 x9041 +21575 x9042 +21575 x9043 +21575 x9044 +21575 x9045 +21575 x9046 +21575 x9047 +21575 x9048 +21575 x9049 +21575 x9050 +21575 x9051 +21575 x9052 +21575 x9053 +21575 x9054 +21575 x9055 +21575 x9056 +21575 x9057 +21575 x9058 +21575 x9059 +21575 x9060 +21575 x9061 +21575 x9062 +21575 x9063 +21575 x9064 +21575 x9065 +21575 x9066 +21575 x9067 +21575 x9068 +21575 x9069 +21575 x9070 +21575 x9071 +21575 x9072 +21575 x9073 +21575 x9074 +21575 x9075 +21575 x9076 +21575 x9077 +21575 x9078 +21575 x9079 +21575 x9080 +21575 x9081 +21575 x9082 +21575 x9083 +21575 x9084 +21575 x9085 +21575 x9086 +21575 x9087 +21575 x9088 +22569 x9089 +22569 x9090 +22569 x9091 +22569 x9092 +22569 x9093 +22569 x9094 +22569 x9095 +22569 x9096 +22569 x9097 +22569 x9098 +22569 x9099 +22569 x9100 +22569 x9101 +22569 x9102 +22569 x9103 +22569 x9104 +22569 x9105 +22569 x9106 +22569 x9107 +22569 x9108 +22569 x9109 +22569 x9110 +22569 x9111 +22569 x9112 +22569 x9113 +22569 x9114 +22569 x9115 +22569 x9116 +22569 x9117 +22569 x9118 +22569 x9119 +22569 x9120 +22569 x9121 +22569 x9122 +22569 x9123 +22569 x9124 +22569 x9125 +22569 x9126 +22569 x9127 +22569 x9128 +22569 x9129 +22569 x9130 +22569 x9131 +22569 x9132 +22569 x9133 +22569 x9134 +22569 x9135 +22569 x9136 +22569 x9137 +22569 x9138 +22569 x9139 +22569 x9140 +22569 x9141 +22569 x9142 +22569 x9143 +22569 x9144 +22569 x9145 +22569 x9146 +22569 x9147 +22569 x9148 +22569 x9149 +22569 x9150 +22569 x9151 +22569 x9152 +22569 x9153 +22569 x9154 +22569 x9155 +22569 x9156 +22569 x9157 +22569 x9158 +22569 x9159 +22569 x9160 +22569 x9161 +22569 x9162 +22569 x9163 +22569 x9164 +22569 x9165 +22569 x9166 +22569 x9167 +22569 x9168 +22569 x9169 +22569 x9170 +22569 x9171 +22569 x9172 +22569 x9173 +22569 x9174 +22569 x9175 +22569 x9176 +22569 x9177 +22569 x9178 +22569 x9179 +22569 x9180 +22569 x9181 +22569 x9182 +22569 x9183 +22569 x9184 +22569 x9185 +22569 x9186 +22569 x9187 +22569 x9188 +22569 x9189 +22569 x9190 +22569 x9191 +22569 x9192 +22569 x9193 +22569 x9194 +22569 x9195 +22569 x9196 +22569 x9197 +22569 x9198 +22569 x9199 +22569 x9200 +22569 x9201 +22569 x9202 +22569 x9203 +22569 x9204 +22569 x9205 +22569 x9206 +22569 x9207 +22569 x9208 +22569 x9209 +22569 x9210 +22569 x9211 +22569 x9212 +22569 x9213 +22569 x9214 +22569 x9215 +22569 x9216 +62071 x9217 +62071 x9218 +62071 x9219 +62071 x9220 +62071 x9221 +62071 x9222 +62071 x9223 +62071 x9224 +62071 x9225 +62071 x9226 +62071 x9227 +62071 x9228 +62071 x9229 +62071 x9230 +62071 x9231 +62071 x9232 +62071 x9233 +62071 x9234 +62071 x9235 +62071 x9236 +62071 x9237 +62071 x9238 +62071 x9239 +62071 x9240 +62071 x9241 +62071 x9242 +62071 x9243 +62071 x9244 +62071 x9245 +62071 x9246 +62071 x9247 +62071 x9248 +62071 x9249 +62071 x9250 +62071 x9251 +62071 x9252 +62071 x9253 +62071 x9254 +62071 x9255 +62071 x9256 +62071 x9257 +62071 x9258 +62071 x9259 +62071 x9260 +62071 x9261 +62071 x9262 +62071 x9263 +62071 x9264 +62071 x9265 +62071 x9266 +62071 x9267 +62071 x9268 +62071 x9269 +62071 x9270 +62071 x9271 +62071 x9272 +62071 x9273 +62071 x9274 +62071 x9275 +62071 x9276 +62071 x9277 +62071 x9278 +62071 x9279 +62071 x9280 +62071 x9281 +62071 x9282 +62071 x9283 +62071 x9284 +62071 x9285 +62071 x9286 +62071 x9287 +62071 x9288 +62071 x9289 +62071 x9290 +62071 x9291 +62071 x9292 +62071 x9293 +62071 x9294 +62071 x9295 +62071 x9296 +62071 x9297 +62071 x9298 +62071 x9299 +62071 x9300 +62071 x9301 +62071 x9302 +62071 x9303 +62071 x9304 +62071 x9305 +62071 x9306 +62071 x9307 +62071 x9308 +62071 x9309 +62071 x9310 +62071 x9311 +62071 x9312 +62071 x9313 +62071 x9314 +62071 x9315 +62071 x9316 +62071 x9317 +62071 x9318 +62071 x9319 +62071 x9320 +62071 x9321 +62071 x9322 +62071 x9323 +62071 x9324 +62071 x9325 +62071 x9326 +62071 x9327 +62071 x9328 +62071 x9329 +62071 x9330 +62071 x9331 +62071 x9332 +62071 x9333 +62071 x9334 +62071 x9335 +62071 x9336 +62071 x9337 +62071 x9338 +62071 x9339 +62071 x9340 +62071 x9341 +62071 x9342 +62071 x9343 +62071 x9344 +51726 x9345 +51726 x9346 +51726 x9347 +51726 x9348 +51726 x9349 +51726 x9350 +51726 x9351 +51726 x9352 +51726 x9353 +51726 x9354 +51726 x9355 +51726 x9356 +51726 x9357 +51726 x9358 +51726 x9359 +51726 x9360 +51726 x9361 +51726 x9362 +51726 x9363 +51726 x9364 +51726 x9365 +51726 x9366 +51726 x9367 +51726 x9368 +51726 x9369 +51726 x9370 +51726 x9371 +51726 x9372 +51726 x9373 +51726 x9374 +51726 x9375 +51726 x9376 +51726 x9377 +51726 x9378 +51726 x9379 +51726 x9380 +51726 x9381 +51726 x9382 +51726 x9383 +51726 x9384 +51726 x9385 +51726 x9386 +51726 x9387 +51726 x9388 +51726 x9389 +51726 x9390 +51726 x9391 +51726 x9392 +51726 x9393 +51726 x9394 +51726 x9395 +51726 x9396 +51726 x9397 +51726 x9398 +51726 x9399 +51726 x9400 +51726 x9401 +51726 x9402 +51726 x9403 +51726 x9404 +51726 x9405 +51726 x9406 +51726 x9407 +51726 x9408 +51726 x9409 +51726 x9410 +51726 x9411 +51726 x9412 +51726 x9413 +51726 x9414 +51726 x9415 +51726 x9416 +51726 x9417 +51726 x9418 +51726 x9419 +51726 x9420 +51726 x9421 +51726 x9422 +51726 x9423 +51726 x9424 +51726 x9425 +51726 x9426 +51726 x9427 +51726 x9428 +51726 x9429 +51726 x9430 +51726 x9431 +51726 x9432 +51726 x9433 +51726 x9434 +51726 x9435 +51726 x9436 +51726 x9437 +51726 x9438 +51726 x9439 +51726 x9440 +51726 x9441 +51726 x9442 +51726 x9443 +51726 x9444 +51726 x9445 +51726 x9446 +51726 x9447 +51726 x9448 +51726 x9449 +51726 x9450 +51726 x9451 +51726 x9452 +51726 x9453 +51726 x9454 +51726 x9455 +51726 x9456 +51726 x9457 +51726 x9458 +51726 x9459 +51726 x9460 +51726 x9461 +51726 x9462 +51726 x9463 +51726 x9464 +51726 x9465 +51726 x9466 +51726 x9467 +51726 x9468 +51726 x9469 +51726 x9470 +51726 x9471 +51726 x9472 +17947 x9473 +17947 x9474 +17947 x9475 +17947 x9476 +17947 x9477 +17947 x9478 +17947 x9479 +17947 x9480 +17947 x9481 +17947 x9482 +17947 x9483 +17947 x9484 +17947 x9485 +17947 x9486 +17947 x9487 +17947 x9488 +17947 x9489 +17947 x9490 +17947 x9491 +17947 x9492 +17947 x9493 +17947 x9494 +17947 x9495 +17947 x9496 +17947 x9497 +17947 x9498 +17947 x9499 +17947 x9500 +17947 x9501 +17947 x9502 +17947 x9503 +17947 x9504 +17947 x9505 +17947 x9506 +17947 x9507 +17947 x9508 +17947 x9509 +17947 x9510 +17947 x9511 +17947 x9512 +17947 x9513 +17947 x9514 +17947 x9515 +17947 x9516 +17947 x9517 +17947 x9518 +17947 x9519 +17947 x9520 +17947 x9521 +17947 x9522 +17947 x9523 +17947 x9524 +17947 x9525 +17947 x9526 +17947 x9527 +17947 x9528 +17947 x9529 +17947 x9530 +17947 x9531 +17947 x9532 +17947 x9533 +17947 x9534 +17947 x9535 +17947 x9536 +17947 x9537 +17947 x9538 +17947 x9539 +17947 x9540 +17947 x9541 +17947 x9542 +17947 x9543 +17947 x9544 +17947 x9545 +17947 x9546 +17947 x9547 +17947 x9548 +17947 x9549 +17947 x9550 +17947 x9551 +17947 x9552 +17947 x9553 +17947 x9554 +17947 x9555 +17947 x9556 +17947 x9557 +17947 x9558 +17947 x9559 +17947 x9560 +17947 x9561 +17947 x9562 +17947 x9563 +17947 x9564 +17947 x9565 +17947 x9566 +17947 x9567 +17947 x9568 +17947 x9569 +17947 x9570 +17947 x9571 +17947 x9572 +17947 x9573 +17947 x9574 +17947 x9575 +17947 x9576 +17947 x9577 +17947 x9578 +17947 x9579 +17947 x9580 +17947 x9581 +17947 x9582 +17947 x9583 +17947 x9584 +17947 x9585 +17947 x9586 +17947 x9587 +17947 x9588 +17947 x9589 +17947 x9590 +17947 x9591 +17947 x9592 +17947 x9593 +17947 x9594 +17947 x9595 +17947 x9596 +17947 x9597 +17947 x9598 +17947 x9599 +17947 x9600 +40564 x9601 +40564 x9602 +40564 x9603 +40564 x9604 +40564 x9605 +40564 x9606 +40564 x9607 +40564 x9608 +40564 x9609 +40564 x9610 +40564 x9611 +40564 x9612 +40564 x9613 +40564 x9614 +40564 x9615 +40564 x9616 +40564 x9617 +40564 x9618 +40564 x9619 +40564 x9620 +40564 x9621 +40564 x9622 +40564 x9623 +40564 x9624 +40564 x9625 +40564 x9626 +40564 x9627 +40564 x9628 +40564 x9629 +40564 x9630 +40564 x9631 +40564 x9632 +40564 x9633 +40564 x9634 +40564 x9635 +40564 x9636 +40564 x9637 +40564 x9638 +40564 x9639 +40564 x9640 +40564 x9641 +40564 x9642 +40564 x9643 +40564 x9644 +40564 x9645 +40564 x9646 +40564 x9647 +40564 x9648 +40564 x9649 +40564 x9650 +40564 x9651 +40564 x9652 +40564 x9653 +40564 x9654 +40564 x9655 +40564 x9656 +40564 x9657 +40564 x9658 +40564 x9659 +40564 x9660 +40564 x9661 +40564 x9662 +40564 x9663 +40564 x9664 +40564 x9665 +40564 x9666 +40564 x9667 +40564 x9668 +40564 x9669 +40564 x9670 +40564 x9671 +40564 x9672 +40564 x9673 +40564 x9674 +40564 x9675 +40564 x9676 +40564 x9677 +40564 x9678 +40564 x9679 +40564 x9680 +40564 x9681 +40564 x9682 +40564 x9683 +40564 x9684 +40564 x9685 +40564 x9686 +40564 x9687 +40564 x9688 +40564 x9689 +40564 x9690 +40564 x9691 +40564 x9692 +40564 x9693 +40564 x9694 +40564 x9695 +40564 x9696 +40564 x9697 +40564 x9698 +40564 x9699 +40564 x9700 +40564 x9701 +40564 x9702 +40564 x9703 +40564 x9704 +40564 x9705 +40564 x9706 +40564 x9707 +40564 x9708 +40564 x9709 +40564 x9710 +40564 x9711 +40564 x9712 +40564 x9713 +40564 x9714 +40564 x9715 +40564 x9716 +40564 x9717 +40564 x9718 +40564 x9719 +40564 x9720 +40564 x9721 +40564 x9722 +40564 x9723 +40564 x9724 +40564 x9725 +40564 x9726 +40564 x9727 +40564 x9728 +60920 x9729 +60920 x9730 +60920 x9731 +60920 x9732 +60920 x9733 +60920 x9734 +60920 x9735 +60920 x9736 +60920 x9737 +60920 x9738 +60920 x9739 +60920 x9740 +60920 x9741 +60920 x9742 +60920 x9743 +60920 x9744 +60920 x9745 +60920 x9746 +60920 x9747 +60920 x9748 +60920 x9749 +60920 x9750 +60920 x9751 +60920 x9752 +60920 x9753 +60920 x9754 +60920 x9755 +60920 x9756 +60920 x9757 +60920 x9758 +60920 x9759 +60920 x9760 +60920 x9761 +60920 x9762 +60920 x9763 +60920 x9764 +60920 x9765 +60920 x9766 +60920 x9767 +60920 x9768 +60920 x9769 +60920 x9770 +60920 x9771 +60920 x9772 +60920 x9773 +60920 x9774 +60920 x9775 +60920 x9776 +60920 x9777 +60920 x9778 +60920 x9779 +60920 x9780 +60920 x9781 +60920 x9782 +60920 x9783 +60920 x9784 +60920 x9785 +60920 x9786 +60920 x9787 +60920 x9788 +60920 x9789 +60920 x9790 +60920 x9791 +60920 x9792 +60920 x9793 +60920 x9794 +60920 x9795 +60920 x9796 +60920 x9797 +60920 x9798 +60920 x9799 +60920 x9800 +60920 x9801 +60920 x9802 +60920 x9803 +60920 x9804 +60920 x9805 +60920 x9806 +60920 x9807 +60920 x9808 +60920 x9809 +60920 x9810 +60920 x9811 +60920 x9812 +60920 x9813 +60920 x9814 +60920 x9815 +60920 x9816 +60920 x9817 +60920 x9818 +60920 x9819 +60920 x9820 +60920 x9821 +60920 x9822 +60920 x9823 +60920 x9824 +60920 x9825 +60920 x9826 +60920 x9827 +60920 x9828 +60920 x9829 +60920 x9830 +60920 x9831 +60920 x9832 +60920 x9833 +60920 x9834 +60920 x9835 +60920 x9836 +60920 x9837 +60920 x9838 +60920 x9839 +60920 x9840 +60920 x9841 +60920 x9842 +60920 x9843 +60920 x9844 +60920 x9845 +60920 x9846 +60920 x9847 +60920 x9848 +60920 x9849 +60920 x9850 +60920 x9851 +60920 x9852 +60920 x9853 +60920 x9854 +60920 x9855 +60920 x9856 +48042 x9857 +48042 x9858 +48042 x9859 +48042 x9860 +48042 x9861 +48042 x9862 +48042 x9863 +48042 x9864 +48042 x9865 +48042 x9866 +48042 x9867 +48042 x9868 +48042 x9869 +48042 x9870 +48042 x9871 +48042 x9872 +48042 x9873 +48042 x9874 +48042 x9875 +48042 x9876 +48042 x9877 +48042 x9878 +48042 x9879 +48042 x9880 +48042 x9881 +48042 x9882 +48042 x9883 +48042 x9884 +48042 x9885 +48042 x9886 +48042 x9887 +48042 x9888 +48042 x9889 +48042 x9890 +48042 x9891 +48042 x9892 +48042 x9893 +48042 x9894 +48042 x9895 +48042 x9896 +48042 x9897 +48042 x9898 +48042 x9899 +48042 x9900 +48042 x9901 +48042 x9902 +48042 x9903 +48042 x9904 +48042 x9905 +48042 x9906 +48042 x9907 +48042 x9908 +48042 x9909 +48042 x9910 +48042 x9911 +48042 x9912 +48042 x9913 +48042 x9914 +48042 x9915 +48042 x9916 +48042 x9917 +48042 x9918 +48042 x9919 +48042 x9920 +48042 x9921 +48042 x9922 +48042 x9923 +48042 x9924 +48042 x9925 +48042 x9926 +48042 x9927 +48042 x9928 +48042 x9929 +48042 x9930 +48042 x9931 +48042 x9932 +48042 x9933 +48042 x9934 +48042 x9935 +48042 x9936 +48042 x9937 +48042 x9938 +48042 x9939 +48042 x9940 +48042 x9941 +48042 x9942 +48042 x9943 +48042 x9944 +48042 x9945 +48042 x9946 +48042 x9947 +48042 x9948 +48042 x9949 +48042 x9950 +48042 x9951 +48042 x9952 +48042 x9953 +48042 x9954 +48042 x9955 +48042 x9956 +48042 x9957 +48042 x9958 +48042 x9959 +48042 x9960 +48042 x9961 +48042 x9962 +48042 x9963 +48042 x9964 +48042 x9965 +48042 x9966 +48042 x9967 +48042 x9968 +48042 x9969 +48042 x9970 +48042 x9971 +48042 x9972 +48042 x9973 +48042 x9974 +48042 x9975 +48042 x9976 +48042 x9977 +48042 x9978 +48042 x9979 +48042 x9980 +48042 x9981 +48042 x9982 +48042 x9983 +48042 x9984 +10152 x9985 +10152 x9986 +10152 x9987 +10152 x9988 +10152 x9989 +10152 x9990 +10152 x9991 +10152 x9992 +10152 x9993 +10152 x9994 +10152 x9995 +10152 x9996 +10152 x9997 +10152 x9998 +10152 x9999 +10152 x10000 +10152 x10001 +10152 x10002 +10152 x10003 +10152 x10004 +10152 x10005 +10152 x10006 +10152 x10007 +10152 x10008 +10152 x10009 +10152 x10010 +10152 x10011 +10152 x10012 +10152 x10013 +10152 x10014 +10152 x10015 +10152 x10016 +10152 x10017 +10152 x10018 +10152 x10019 +10152 x10020 +10152 x10021 +10152 x10022 +10152 x10023 +10152 x10024 +10152 x10025 +10152 x10026 +10152 x10027 +10152 x10028 +10152 x10029 +10152 x10030 +10152 x10031 +10152 x10032 +10152 x10033 +10152 x10034 +10152 x10035 +10152 x10036 +10152 x10037 +10152 x10038 +10152 x10039 +10152 x10040 +10152 x10041 +10152 x10042 +10152 x10043 +10152 x10044 +10152 x10045 +10152 x10046 +10152 x10047 +10152 x10048 +10152 x10049 +10152 x10050 +10152 x10051 +10152 x10052 +10152 x10053 +10152 x10054 +10152 x10055 +10152 x10056 +10152 x10057 +10152 x10058 +10152 x10059 +10152 x10060 +10152 x10061 +10152 x10062 +10152 x10063 +10152 x10064 +10152 x10065 +10152 x10066 +10152 x10067 +10152 x10068 +10152 x10069 +10152 x10070 +10152 x10071 +10152 x10072 +10152 x10073 +10152 x10074 +10152 x10075 +10152 x10076 +10152 x10077 +10152 x10078 +10152 x10079 +10152 x10080 +10152 x10081 +10152 x10082 +10152 x10083 +10152 x10084 +10152 x10085 +10152 x10086 +10152 x10087 +10152 x10088 +10152 x10089 +10152 x10090 +10152 x10091 +10152 x10092 +10152 x10093 +10152 x10094 +10152 x10095 +10152 x10096 +10152 x10097 +10152 x10098 +10152 x10099 +10152 x10100 +10152 x10101 +10152 x10102 +10152 x10103 +10152 x10104 +10152 x10105 +10152 x10106 +10152 x10107 +10152 x10108 +10152 x10109 +10152 x10110 +10152 x10111 +10152 x10112 +20057 x10113 +20057 x10114 +20057 x10115 +20057 x10116 +20057 x10117 +20057 x10118 +20057 x10119 +20057 x10120 +20057 x10121 +20057 x10122 +20057 x10123 +20057 x10124 +20057 x10125 +20057 x10126 +20057 x10127 +20057 x10128 +20057 x10129 +20057 x10130 +20057 x10131 +20057 x10132 +20057 x10133 +20057 x10134 +20057 x10135 +20057 x10136 +20057 x10137 +20057 x10138 +20057 x10139 +20057 x10140 +20057 x10141 +20057 x10142 +20057 x10143 +20057 x10144 +20057 x10145 +20057 x10146 +20057 x10147 +20057 x10148 +20057 x10149 +20057 x10150 +20057 x10151 +20057 x10152 +20057 x10153 +20057 x10154 +20057 x10155 +20057 x10156 +20057 x10157 +20057 x10158 +20057 x10159 +20057 x10160 +20057 x10161 +20057 x10162 +20057 x10163 +20057 x10164 +20057 x10165 +20057 x10166 +20057 x10167 +20057 x10168 +20057 x10169 +20057 x10170 +20057 x10171 +20057 x10172 +20057 x10173 +20057 x10174 +20057 x10175 +20057 x10176 +20057 x10177 +20057 x10178 +20057 x10179 +20057 x10180 +20057 x10181 +20057 x10182 +20057 x10183 +20057 x10184 +20057 x10185 +20057 x10186 +20057 x10187 +20057 x10188 +20057 x10189 +20057 x10190 +20057 x10191 +20057 x10192 +20057 x10193 +20057 x10194 +20057 x10195 +20057 x10196 +20057 x10197 +20057 x10198 +20057 x10199 +20057 x10200 +20057 x10201 +20057 x10202 +20057 x10203 +20057 x10204 +20057 x10205 +20057 x10206 +20057 x10207 +20057 x10208 +20057 x10209 +20057 x10210 +20057 x10211 +20057 x10212 +20057 x10213 +20057 x10214 +20057 x10215 +20057 x10216 +20057 x10217 +20057 x10218 +20057 x10219 +20057 x10220 +20057 x10221 +20057 x10222 +20057 x10223 +20057 x10224 +20057 x10225 +20057 x10226 +20057 x10227 +20057 x10228 +20057 x10229 +20057 x10230 +20057 x10231 +20057 x10232 +20057 x10233 +20057 x10234 +20057 x10235 +20057 x10236 +20057 x10237 +20057 x10238 +20057 x10239 +20057 x10240 +60892 x10241 +60892 x10242 +60892 x10243 +60892 x10244 +60892 x10245 +60892 x10246 +60892 x10247 +60892 x10248 +60892 x10249 +60892 x10250 +60892 x10251 +60892 x10252 +60892 x10253 +60892 x10254 +60892 x10255 +60892 x10256 +60892 x10257 +60892 x10258 +60892 x10259 +60892 x10260 +60892 x10261 +60892 x10262 +60892 x10263 +60892 x10264 +60892 x10265 +60892 x10266 +60892 x10267 +60892 x10268 +60892 x10269 +60892 x10270 +60892 x10271 +60892 x10272 +60892 x10273 +60892 x10274 +60892 x10275 +60892 x10276 +60892 x10277 +60892 x10278 +60892 x10279 +60892 x10280 +60892 x10281 +60892 x10282 +60892 x10283 +60892 x10284 +60892 x10285 +60892 x10286 +60892 x10287 +60892 x10288 +60892 x10289 +60892 x10290 +60892 x10291 +60892 x10292 +60892 x10293 +60892 x10294 +60892 x10295 +60892 x10296 +60892 x10297 +60892 x10298 +60892 x10299 +60892 x10300 +60892 x10301 +60892 x10302 +60892 x10303 +60892 x10304 +60892 x10305 +60892 x10306 +60892 x10307 +60892 x10308 +60892 x10309 +60892 x10310 +60892 x10311 +60892 x10312 +60892 x10313 +60892 x10314 +60892 x10315 +60892 x10316 +60892 x10317 +60892 x10318 +60892 x10319 +60892 x10320 +60892 x10321 +60892 x10322 +60892 x10323 +60892 x10324 +60892 x10325 +60892 x10326 +60892 x10327 +60892 x10328 +60892 x10329 +60892 x10330 +60892 x10331 +60892 x10332 +60892 x10333 +60892 x10334 +60892 x10335 +60892 x10336 +60892 x10337 +60892 x10338 +60892 x10339 +60892 x10340 +60892 x10341 +60892 x10342 +60892 x10343 +60892 x10344 +60892 x10345 +60892 x10346 +60892 x10347 +60892 x10348 +60892 x10349 +60892 x10350 +60892 x10351 +60892 x10352 +60892 x10353 +60892 x10354 +60892 x10355 +60892 x10356 +60892 x10357 +60892 x10358 +60892 x10359 +60892 x10360 +60892 x10361 +60892 x10362 +60892 x10363 +60892 x10364 +60892 x10365 +60892 x10366 +60892 x10367 +60892 x10368 +32732 x10369 +32732 x10370 +32732 x10371 +32732 x10372 +32732 x10373 +32732 x10374 +32732 x10375 +32732 x10376 +32732 x10377 +32732 x10378 +32732 x10379 +32732 x10380 +32732 x10381 +32732 x10382 +32732 x10383 +32732 x10384 +32732 x10385 +32732 x10386 +32732 x10387 +32732 x10388 +32732 x10389 +32732 x10390 +32732 x10391 +32732 x10392 +32732 x10393 +32732 x10394 +32732 x10395 +32732 x10396 +32732 x10397 +32732 x10398 +32732 x10399 +32732 x10400 +32732 x10401 +32732 x10402 +32732 x10403 +32732 x10404 +32732 x10405 +32732 x10406 +32732 x10407 +32732 x10408 +32732 x10409 +32732 x10410 +32732 x10411 +32732 x10412 +32732 x10413 +32732 x10414 +32732 x10415 +32732 x10416 +32732 x10417 +32732 x10418 +32732 x10419 +32732 x10420 +32732 x10421 +32732 x10422 +32732 x10423 +32732 x10424 +32732 x10425 +32732 x10426 +32732 x10427 +32732 x10428 +32732 x10429 +32732 x10430 +32732 x10431 +32732 x10432 +32732 x10433 +32732 x10434 +32732 x10435 +32732 x10436 +32732 x10437 +32732 x10438 +32732 x10439 +32732 x10440 +32732 x10441 +32732 x10442 +32732 x10443 +32732 x10444 +32732 x10445 +32732 x10446 +32732 x10447 +32732 x10448 +32732 x10449 +32732 x10450 +32732 x10451 +32732 x10452 +32732 x10453 +32732 x10454 +32732 x10455 +32732 x10456 +32732 x10457 +32732 x10458 +32732 x10459 +32732 x10460 +32732 x10461 +32732 x10462 +32732 x10463 +32732 x10464 +32732 x10465 +32732 x10466 +32732 x10467 +32732 x10468 +32732 x10469 +32732 x10470 +32732 x10471 +32732 x10472 +32732 x10473 +32732 x10474 +32732 x10475 +32732 x10476 +32732 x10477 +32732 x10478 +32732 x10479 +32732 x10480 +32732 x10481 +32732 x10482 +32732 x10483 +32732 x10484 +32732 x10485 +32732 x10486 +32732 x10487 +32732 x10488 +32732 x10489 +32732 x10490 +32732 x10491 +32732 x10492 +32732 x10493 +32732 x10494 +32732 x10495 +32732 x10496 +19955 x10497 +19955 x10498 +19955 x10499 +19955 x10500 +19955 x10501 +19955 x10502 +19955 x10503 +19955 x10504 +19955 x10505 +19955 x10506 +19955 x10507 +19955 x10508 +19955 x10509 +19955 x10510 +19955 x10511 +19955 x10512 +19955 x10513 +19955 x10514 +19955 x10515 +19955 x10516 +19955 x10517 +19955 x10518 +19955 x10519 +19955 x10520 +19955 x10521 +19955 x10522 +19955 x10523 +19955 x10524 +19955 x10525 +19955 x10526 +19955 x10527 +19955 x10528 +19955 x10529 +19955 x10530 +19955 x10531 +19955 x10532 +19955 x10533 +19955 x10534 +19955 x10535 +19955 x10536 +19955 x10537 +19955 x10538 +19955 x10539 +19955 x10540 +19955 x10541 +19955 x10542 +19955 x10543 +19955 x10544 +19955 x10545 +19955 x10546 +19955 x10547 +19955 x10548 +19955 x10549 +19955 x10550 +19955 x10551 +19955 x10552 +19955 x10553 +19955 x10554 +19955 x10555 +19955 x10556 +19955 x10557 +19955 x10558 +19955 x10559 +19955 x10560 +19955 x10561 +19955 x10562 +19955 x10563 +19955 x10564 +19955 x10565 +19955 x10566 +19955 x10567 +19955 x10568 +19955 x10569 +19955 x10570 +19955 x10571 +19955 x10572 +19955 x10573 +19955 x10574 +19955 x10575 +19955 x10576 +19955 x10577 +19955 x10578 +19955 x10579 +19955 x10580 +19955 x10581 +19955 x10582 +19955 x10583 +19955 x10584 +19955 x10585 +19955 x10586 +19955 x10587 +19955 x10588 +19955 x10589 +19955 x10590 +19955 x10591 +19955 x10592 +19955 x10593 +19955 x10594 +19955 x10595 +19955 x10596 +19955 x10597 +19955 x10598 +19955 x10599 +19955 x10600 +19955 x10601 +19955 x10602 +19955 x10603 +19955 x10604 +19955 x10605 +19955 x10606 +19955 x10607 +19955 x10608 +19955 x10609 +19955 x10610 +19955 x10611 +19955 x10612 +19955 x10613 +19955 x10614 +19955 x10615 +19955 x10616 +19955 x10617 +19955 x10618 +19955 x10619 +19955 x10620 +19955 x10621 +19955 x10622 +19955 x10623 +19955 x10624 +9586 x10625 +9586 x10626 +9586 x10627 +9586 x10628 +9586 x10629 +9586 x10630 +9586 x10631 +9586 x10632 +9586 x10633 +9586 x10634 +9586 x10635 +9586 x10636 +9586 x10637 +9586 x10638 +9586 x10639 +9586 x10640 +9586 x10641 +9586 x10642 +9586 x10643 +9586 x10644 +9586 x10645 +9586 x10646 +9586 x10647 +9586 x10648 +9586 x10649 +9586 x10650 +9586 x10651 +9586 x10652 +9586 x10653 +9586 x10654 +9586 x10655 +9586 x10656 +9586 x10657 +9586 x10658 +9586 x10659 +9586 x10660 +9586 x10661 +9586 x10662 +9586 x10663 +9586 x10664 +9586 x10665 +9586 x10666 +9586 x10667 +9586 x10668 +9586 x10669 +9586 x10670 +9586 x10671 +9586 x10672 +9586 x10673 +9586 x10674 +9586 x10675 +9586 x10676 +9586 x10677 +9586 x10678 +9586 x10679 +9586 x10680 +9586 x10681 +9586 x10682 +9586 x10683 +9586 x10684 +9586 x10685 +9586 x10686 +9586 x10687 +9586 x10688 +9586 x10689 +9586 x10690 +9586 x10691 +9586 x10692 +9586 x10693 +9586 x10694 +9586 x10695 +9586 x10696 +9586 x10697 +9586 x10698 +9586 x10699 +9586 x10700 +9586 x10701 +9586 x10702 +9586 x10703 +9586 x10704 +9586 x10705 +9586 x10706 +9586 x10707 +9586 x10708 +9586 x10709 +9586 x10710 +9586 x10711 +9586 x10712 +9586 x10713 +9586 x10714 +9586 x10715 +9586 x10716 +9586 x10717 +9586 x10718 +9586 x10719 +9586 x10720 +9586 x10721 +9586 x10722 +9586 x10723 +9586 x10724 +9586 x10725 +9586 x10726 +9586 x10727 +9586 x10728 +9586 x10729 +9586 x10730 +9586 x10731 +9586 x10732 +9586 x10733 +9586 x10734 +9586 x10735 +9586 x10736 +9586 x10737 +9586 x10738 +9586 x10739 +9586 x10740 +9586 x10741 +9586 x10742 +9586 x10743 +9586 x10744 +9586 x10745 +9586 x10746 +9586 x10747 +9586 x10748 +9586 x10749 +9586 x10750 +9586 x10751 +9586 x10752 +12763 x10753 +12763 x10754 +12763 x10755 +12763 x10756 +12763 x10757 +12763 x10758 +12763 x10759 +12763 x10760 +12763 x10761 +12763 x10762 +12763 x10763 +12763 x10764 +12763 x10765 +12763 x10766 +12763 x10767 +12763 x10768 +12763 x10769 +12763 x10770 +12763 x10771 +12763 x10772 +12763 x10773 +12763 x10774 +12763 x10775 +12763 x10776 +12763 x10777 +12763 x10778 +12763 x10779 +12763 x10780 +12763 x10781 +12763 x10782 +12763 x10783 +12763 x10784 +12763 x10785 +12763 x10786 +12763 x10787 +12763 x10788 +12763 x10789 +12763 x10790 +12763 x10791 +12763 x10792 +12763 x10793 +12763 x10794 +12763 x10795 +12763 x10796 +12763 x10797 +12763 x10798 +12763 x10799 +12763 x10800 +12763 x10801 +12763 x10802 +12763 x10803 +12763 x10804 +12763 x10805 +12763 x10806 +12763 x10807 +12763 x10808 +12763 x10809 +12763 x10810 +12763 x10811 +12763 x10812 +12763 x10813 +12763 x10814 +12763 x10815 +12763 x10816 +12763 x10817 +12763 x10818 +12763 x10819 +12763 x10820 +12763 x10821 +12763 x10822 +12763 x10823 +12763 x10824 +12763 x10825 +12763 x10826 +12763 x10827 +12763 x10828 +12763 x10829 +12763 x10830 +12763 x10831 +12763 x10832 +12763 x10833 +12763 x10834 +12763 x10835 +12763 x10836 +12763 x10837 +12763 x10838 +12763 x10839 +12763 x10840 +12763 x10841 +12763 x10842 +12763 x10843 +12763 x10844 +12763 x10845 +12763 x10846 +12763 x10847 +12763 x10848 +12763 x10849 +12763 x10850 +12763 x10851 +12763 x10852 +12763 x10853 +12763 x10854 +12763 x10855 +12763 x10856 +12763 x10857 +12763 x10858 +12763 x10859 +12763 x10860 +12763 x10861 +12763 x10862 +12763 x10863 +12763 x10864 +12763 x10865 +12763 x10866 +12763 x10867 +12763 x10868 +12763 x10869 +12763 x10870 +12763 x10871 +12763 x10872 +12763 x10873 +12763 x10874 +12763 x10875 +12763 x10876 +12763 x10877 +12763 x10878 +12763 x10879 +12763 x10880 +32939 x10881 +32939 x10882 +32939 x10883 +32939 x10884 +32939 x10885 +32939 x10886 +32939 x10887 +32939 x10888 +32939 x10889 +32939 x10890 +32939 x10891 +32939 x10892 +32939 x10893 +32939 x10894 +32939 x10895 +32939 x10896 +32939 x10897 +32939 x10898 +32939 x10899 +32939 x10900 +32939 x10901 +32939 x10902 +32939 x10903 +32939 x10904 +32939 x10905 +32939 x10906 +32939 x10907 +32939 x10908 +32939 x10909 +32939 x10910 +32939 x10911 +32939 x10912 +32939 x10913 +32939 x10914 +32939 x10915 +32939 x10916 +32939 x10917 +32939 x10918 +32939 x10919 +32939 x10920 +32939 x10921 +32939 x10922 +32939 x10923 +32939 x10924 +32939 x10925 +32939 x10926 +32939 x10927 +32939 x10928 +32939 x10929 +32939 x10930 +32939 x10931 +32939 x10932 +32939 x10933 +32939 x10934 +32939 x10935 +32939 x10936 +32939 x10937 +32939 x10938 +32939 x10939 +32939 x10940 +32939 x10941 +32939 x10942 +32939 x10943 +32939 x10944 +32939 x10945 +32939 x10946 +32939 x10947 +32939 x10948 +32939 x10949 +32939 x10950 +32939 x10951 +32939 x10952 +32939 x10953 +32939 x10954 +32939 x10955 +32939 x10956 +32939 x10957 +32939 x10958 +32939 x10959 +32939 x10960 +32939 x10961 +32939 x10962 +32939 x10963 +32939 x10964 +32939 x10965 +32939 x10966 +32939 x10967 +32939 x10968 +32939 x10969 +32939 x10970 +32939 x10971 +32939 x10972 +32939 x10973 +32939 x10974 +32939 x10975 +32939 x10976 +32939 x10977 +32939 x10978 +32939 x10979 +32939 x10980 +32939 x10981 +32939 x10982 +32939 x10983 +32939 x10984 +32939 x10985 +32939 x10986 +32939 x10987 +32939 x10988 +32939 x10989 +32939 x10990 +32939 x10991 +32939 x10992 +32939 x10993 +32939 x10994 +32939 x10995 +32939 x10996 +32939 x10997 +32939 x10998 +32939 x10999 +32939 x11000 +32939 x11001 +32939 x11002 +32939 x11003 +32939 x11004 +32939 x11005 +32939 x11006 +32939 x11007 +32939 x11008 +10131 x11009 +10131 x11010 +10131 x11011 +10131 x11012 +10131 x11013 +10131 x11014 +10131 x11015 +10131 x11016 +10131 x11017 +10131 x11018 +10131 x11019 +10131 x11020 +10131 x11021 +10131 x11022 +10131 x11023 +10131 x11024 +10131 x11025 +10131 x11026 +10131 x11027 +10131 x11028 +10131 x11029 +10131 x11030 +10131 x11031 +10131 x11032 +10131 x11033 +10131 x11034 +10131 x11035 +10131 x11036 +10131 x11037 +10131 x11038 +10131 x11039 +10131 x11040 +10131 x11041 +10131 x11042 +10131 x11043 +10131 x11044 +10131 x11045 +10131 x11046 +10131 x11047 +10131 x11048 +10131 x11049 +10131 x11050 +10131 x11051 +10131 x11052 +10131 x11053 +10131 x11054 +10131 x11055 +10131 x11056 +10131 x11057 +10131 x11058 +10131 x11059 +10131 x11060 +10131 x11061 +10131 x11062 +10131 x11063 +10131 x11064 +10131 x11065 +10131 x11066 +10131 x11067 +10131 x11068 +10131 x11069 +10131 x11070 +10131 x11071 +10131 x11072 +10131 x11073 +10131 x11074 +10131 x11075 +10131 x11076 +10131 x11077 +10131 x11078 +10131 x11079 +10131 x11080 +10131 x11081 +10131 x11082 +10131 x11083 +10131 x11084 +10131 x11085 +10131 x11086 +10131 x11087 +10131 x11088 +10131 x11089 +10131 x11090 +10131 x11091 +10131 x11092 +10131 x11093 +10131 x11094 +10131 x11095 +10131 x11096 +10131 x11097 +10131 x11098 +10131 x11099 +10131 x11100 +10131 x11101 +10131 x11102 +10131 x11103 +10131 x11104 +10131 x11105 +10131 x11106 +10131 x11107 +10131 x11108 +10131 x11109 +10131 x11110 +10131 x11111 +10131 x11112 +10131 x11113 +10131 x11114 +10131 x11115 +10131 x11116 +10131 x11117 +10131 x11118 +10131 x11119 +10131 x11120 +10131 x11121 +10131 x11122 +10131 x11123 +10131 x11124 +10131 x11125 +10131 x11126 +10131 x11127 +10131 x11128 +10131 x11129 +10131 x11130 +10131 x11131 +10131 x11132 +10131 x11133 +10131 x11134 +10131 x11135 +10131 x11136 +61173 x11137 +61173 x11138 +61173 x11139 +61173 x11140 +61173 x11141 +61173 x11142 +61173 x11143 +61173 x11144 +61173 x11145 +61173 x11146 +61173 x11147 +61173 x11148 +61173 x11149 +61173 x11150 +61173 x11151 +61173 x11152 +61173 x11153 +61173 x11154 +61173 x11155 +61173 x11156 +61173 x11157 +61173 x11158 +61173 x11159 +61173 x11160 +61173 x11161 +61173 x11162 +61173 x11163 +61173 x11164 +61173 x11165 +61173 x11166 +61173 x11167 +61173 x11168 +61173 x11169 +61173 x11170 +61173 x11171 +61173 x11172 +61173 x11173 +61173 x11174 +61173 x11175 +61173 x11176 +61173 x11177 +61173 x11178 +61173 x11179 +61173 x11180 +61173 x11181 +61173 x11182 +61173 x11183 +61173 x11184 +61173 x11185 +61173 x11186 +61173 x11187 +61173 x11188 +61173 x11189 +61173 x11190 +61173 x11191 +61173 x11192 +61173 x11193 +61173 x11194 +61173 x11195 +61173 x11196 +61173 x11197 +61173 x11198 +61173 x11199 +61173 x11200 +61173 x11201 +61173 x11202 +61173 x11203 +61173 x11204 +61173 x11205 +61173 x11206 +61173 x11207 +61173 x11208 +61173 x11209 +61173 x11210 +61173 x11211 +61173 x11212 +61173 x11213 +61173 x11214 +61173 x11215 +61173 x11216 +61173 x11217 +61173 x11218 +61173 x11219 +61173 x11220 +61173 x11221 +61173 x11222 +61173 x11223 +61173 x11224 +61173 x11225 +61173 x11226 +61173 x11227 +61173 x11228 +61173 x11229 +61173 x11230 +61173 x11231 +61173 x11232 +61173 x11233 +61173 x11234 +61173 x11235 +61173 x11236 +61173 x11237 +61173 x11238 +61173 x11239 +61173 x11240 +61173 x11241 +61173 x11242 +61173 x11243 +61173 x11244 +61173 x11245 +61173 x11246 +61173 x11247 +61173 x11248 +61173 x11249 +61173 x11250 +61173 x11251 +61173 x11252 +61173 x11253 +61173 x11254 +61173 x11255 +61173 x11256 +61173 x11257 +61173 x11258 +61173 x11259 +61173 x11260 +61173 x11261 +61173 x11262 +61173 x11263 +61173 x11264 +5727 x11265 +5727 x11266 +5727 x11267 +5727 x11268 +5727 x11269 +5727 x11270 +5727 x11271 +5727 x11272 +5727 x11273 +5727 x11274 +5727 x11275 +5727 x11276 +5727 x11277 +5727 x11278 +5727 x11279 +5727 x11280 +5727 x11281 +5727 x11282 +5727 x11283 +5727 x11284 +5727 x11285 +5727 x11286 +5727 x11287 +5727 x11288 +5727 x11289 +5727 x11290 +5727 x11291 +5727 x11292 +5727 x11293 +5727 x11294 +5727 x11295 +5727 x11296 +5727 x11297 +5727 x11298 +5727 x11299 +5727 x11300 +5727 x11301 +5727 x11302 +5727 x11303 +5727 x11304 +5727 x11305 +5727 x11306 +5727 x11307 +5727 x11308 +5727 x11309 +5727 x11310 +5727 x11311 +5727 x11312 +5727 x11313 +5727 x11314 +5727 x11315 +5727 x11316 +5727 x11317 +5727 x11318 +5727 x11319 +5727 x11320 +5727 x11321 +5727 x11322 +5727 x11323 +5727 x11324 +5727 x11325 +5727 x11326 +5727 x11327 +5727 x11328 +5727 x11329 +5727 x11330 +5727 x11331 +5727 x11332 +5727 x11333 +5727 x11334 +5727 x11335 +5727 x11336 +5727 x11337 +5727 x11338 +5727 x11339 +5727 x11340 +5727 x11341 +5727 x11342 +5727 x11343 +5727 x11344 +5727 x11345 +5727 x11346 +5727 x11347 +5727 x11348 +5727 x11349 +5727 x11350 +5727 x11351 +5727 x11352 +5727 x11353 +5727 x11354 +5727 x11355 +5727 x11356 +5727 x11357 +5727 x11358 +5727 x11359 +5727 x11360 +5727 x11361 +5727 x11362 +5727 x11363 +5727 x11364 +5727 x11365 +5727 x11366 +5727 x11367 +5727 x11368 +5727 x11369 +5727 x11370 +5727 x11371 +5727 x11372 +5727 x11373 +5727 x11374 +5727 x11375 +5727 x11376 +5727 x11377 +5727 x11378 +5727 x11379 +5727 x11380 +5727 x11381 +5727 x11382 +5727 x11383 +5727 x11384 +5727 x11385 +5727 x11386 +5727 x11387 +5727 x11388 +5727 x11389 +5727 x11390 +5727 x11391 +5727 x11392 +62728 x11393 +62728 x11394 +62728 x11395 +62728 x11396 +62728 x11397 +62728 x11398 +62728 x11399 +62728 x11400 +62728 x11401 +62728 x11402 +62728 x11403 +62728 x11404 +62728 x11405 +62728 x11406 +62728 x11407 +62728 x11408 +62728 x11409 +62728 x11410 +62728 x11411 +62728 x11412 +62728 x11413 +62728 x11414 +62728 x11415 +62728 x11416 +62728 x11417 +62728 x11418 +62728 x11419 +62728 x11420 +62728 x11421 +62728 x11422 +62728 x11423 +62728 x11424 +62728 x11425 +62728 x11426 +62728 x11427 +62728 x11428 +62728 x11429 +62728 x11430 +62728 x11431 +62728 x11432 +62728 x11433 +62728 x11434 +62728 x11435 +62728 x11436 +62728 x11437 +62728 x11438 +62728 x11439 +62728 x11440 +62728 x11441 +62728 x11442 +62728 x11443 +62728 x11444 +62728 x11445 +62728 x11446 +62728 x11447 +62728 x11448 +62728 x11449 +62728 x11450 +62728 x11451 +62728 x11452 +62728 x11453 +62728 x11454 +62728 x11455 +62728 x11456 +62728 x11457 +62728 x11458 +62728 x11459 +62728 x11460 +62728 x11461 +62728 x11462 +62728 x11463 +62728 x11464 +62728 x11465 +62728 x11466 +62728 x11467 +62728 x11468 +62728 x11469 +62728 x11470 +62728 x11471 +62728 x11472 +62728 x11473 +62728 x11474 +62728 x11475 +62728 x11476 +62728 x11477 +62728 x11478 +62728 x11479 +62728 x11480 +62728 x11481 +62728 x11482 +62728 x11483 +62728 x11484 +62728 x11485 +62728 x11486 +62728 x11487 +62728 x11488 +62728 x11489 +62728 x11490 +62728 x11491 +62728 x11492 +62728 x11493 +62728 x11494 +62728 x11495 +62728 x11496 +62728 x11497 +62728 x11498 +62728 x11499 +62728 x11500 +62728 x11501 +62728 x11502 +62728 x11503 +62728 x11504 +62728 x11505 +62728 x11506 +62728 x11507 +62728 x11508 +62728 x11509 +62728 x11510 +62728 x11511 +62728 x11512 +62728 x11513 +62728 x11514 +62728 x11515 +62728 x11516 +62728 x11517 +62728 x11518 +62728 x11519 +62728 x11520 +42847 x11521 +42847 x11522 +42847 x11523 +42847 x11524 +42847 x11525 +42847 x11526 +42847 x11527 +42847 x11528 +42847 x11529 +42847 x11530 +42847 x11531 +42847 x11532 +42847 x11533 +42847 x11534 +42847 x11535 +42847 x11536 +42847 x11537 +42847 x11538 +42847 x11539 +42847 x11540 +42847 x11541 +42847 x11542 +42847 x11543 +42847 x11544 +42847 x11545 +42847 x11546 +42847 x11547 +42847 x11548 +42847 x11549 +42847 x11550 +42847 x11551 +42847 x11552 +42847 x11553 +42847 x11554 +42847 x11555 +42847 x11556 +42847 x11557 +42847 x11558 +42847 x11559 +42847 x11560 +42847 x11561 +42847 x11562 +42847 x11563 +42847 x11564 +42847 x11565 +42847 x11566 +42847 x11567 +42847 x11568 +42847 x11569 +42847 x11570 +42847 x11571 +42847 x11572 +42847 x11573 +42847 x11574 +42847 x11575 +42847 x11576 +42847 x11577 +42847 x11578 +42847 x11579 +42847 x11580 +42847 x11581 +42847 x11582 +42847 x11583 +42847 x11584 +42847 x11585 +42847 x11586 +42847 x11587 +42847 x11588 +42847 x11589 +42847 x11590 +42847 x11591 +42847 x11592 +42847 x11593 +42847 x11594 +42847 x11595 +42847 x11596 +42847 x11597 +42847 x11598 +42847 x11599 +42847 x11600 +42847 x11601 +42847 x11602 +42847 x11603 +42847 x11604 +42847 x11605 +42847 x11606 +42847 x11607 +42847 x11608 +42847 x11609 +42847 x11610 +42847 x11611 +42847 x11612 +42847 x11613 +42847 x11614 +42847 x11615 +42847 x11616 +42847 x11617 +42847 x11618 +42847 x11619 +42847 x11620 +42847 x11621 +42847 x11622 +42847 x11623 +42847 x11624 +42847 x11625 +42847 x11626 +42847 x11627 +42847 x11628 +42847 x11629 +42847 x11630 +42847 x11631 +42847 x11632 +42847 x11633 +42847 x11634 +42847 x11635 +42847 x11636 +42847 x11637 +42847 x11638 +42847 x11639 +42847 x11640 +42847 x11641 +42847 x11642 +42847 x11643 +42847 x11644 +42847 x11645 +42847 x11646 +42847 x11647 +42847 x11648 +57711 x11649 +57711 x11650 +57711 x11651 +57711 x11652 +57711 x11653 +57711 x11654 +57711 x11655 +57711 x11656 +57711 x11657 +57711 x11658 +57711 x11659 +57711 x11660 +57711 x11661 +57711 x11662 +57711 x11663 +57711 x11664 +57711 x11665 +57711 x11666 +57711 x11667 +57711 x11668 +57711 x11669 +57711 x11670 +57711 x11671 +57711 x11672 +57711 x11673 +57711 x11674 +57711 x11675 +57711 x11676 +57711 x11677 +57711 x11678 +57711 x11679 +57711 x11680 +57711 x11681 +57711 x11682 +57711 x11683 +57711 x11684 +57711 x11685 +57711 x11686 +57711 x11687 +57711 x11688 +57711 x11689 +57711 x11690 +57711 x11691 +57711 x11692 +57711 x11693 +57711 x11694 +57711 x11695 +57711 x11696 +57711 x11697 +57711 x11698 +57711 x11699 +57711 x11700 +57711 x11701 +57711 x11702 +57711 x11703 +57711 x11704 +57711 x11705 +57711 x11706 +57711 x11707 +57711 x11708 +57711 x11709 +57711 x11710 +57711 x11711 +57711 x11712 +57711 x11713 +57711 x11714 +57711 x11715 +57711 x11716 +57711 x11717 +57711 x11718 +57711 x11719 +57711 x11720 +57711 x11721 +57711 x11722 +57711 x11723 +57711 x11724 +57711 x11725 +57711 x11726 +57711 x11727 +57711 x11728 +57711 x11729 +57711 x11730 +57711 x11731 +57711 x11732 +57711 x11733 +57711 x11734 +57711 x11735 +57711 x11736 +57711 x11737 +57711 x11738 +57711 x11739 +57711 x11740 +57711 x11741 +57711 x11742 +57711 x11743 +57711 x11744 +57711 x11745 +57711 x11746 +57711 x11747 +57711 x11748 +57711 x11749 +57711 x11750 +57711 x11751 +57711 x11752 +57711 x11753 +57711 x11754 +57711 x11755 +57711 x11756 +57711 x11757 +57711 x11758 +57711 x11759 +57711 x11760 +57711 x11761 +57711 x11762 +57711 x11763 +57711 x11764 +57711 x11765 +57711 x11766 +57711 x11767 +57711 x11768 +57711 x11769 +57711 x11770 +57711 x11771 +57711 x11772 +57711 x11773 +57711 x11774 +57711 x11775 +57711 x11776 +21661 x11777 +21661 x11778 +21661 x11779 +21661 x11780 +21661 x11781 +21661 x11782 +21661 x11783 +21661 x11784 +21661 x11785 +21661 x11786 +21661 x11787 +21661 x11788 +21661 x11789 +21661 x11790 +21661 x11791 +21661 x11792 +21661 x11793 +21661 x11794 +21661 x11795 +21661 x11796 +21661 x11797 +21661 x11798 +21661 x11799 +21661 x11800 +21661 x11801 +21661 x11802 +21661 x11803 +21661 x11804 +21661 x11805 +21661 x11806 +21661 x11807 +21661 x11808 +21661 x11809 +21661 x11810 +21661 x11811 +21661 x11812 +21661 x11813 +21661 x11814 +21661 x11815 +21661 x11816 +21661 x11817 +21661 x11818 +21661 x11819 +21661 x11820 +21661 x11821 +21661 x11822 +21661 x11823 +21661 x11824 +21661 x11825 +21661 x11826 +21661 x11827 +21661 x11828 +21661 x11829 +21661 x11830 +21661 x11831 +21661 x11832 +21661 x11833 +21661 x11834 +21661 x11835 +21661 x11836 +21661 x11837 +21661 x11838 +21661 x11839 +21661 x11840 +21661 x11841 +21661 x11842 +21661 x11843 +21661 x11844 +21661 x11845 +21661 x11846 +21661 x11847 +21661 x11848 +21661 x11849 +21661 x11850 +21661 x11851 +21661 x11852 +21661 x11853 +21661 x11854 +21661 x11855 +21661 x11856 +21661 x11857 +21661 x11858 +21661 x11859 +21661 x11860 +21661 x11861 +21661 x11862 +21661 x11863 +21661 x11864 +21661 x11865 +21661 x11866 +21661 x11867 +21661 x11868 +21661 x11869 +21661 x11870 +21661 x11871 +21661 x11872 +21661 x11873 +21661 x11874 +21661 x11875 +21661 x11876 +21661 x11877 +21661 x11878 +21661 x11879 +21661 x11880 +21661 x11881 +21661 x11882 +21661 x11883 +21661 x11884 +21661 x11885 +21661 x11886 +21661 x11887 +21661 x11888 +21661 x11889 +21661 x11890 +21661 x11891 +21661 x11892 +21661 x11893 +21661 x11894 +21661 x11895 +21661 x11896 +21661 x11897 +21661 x11898 +21661 x11899 +21661 x11900 +21661 x11901 +21661 x11902 +21661 x11903 +21661 x11904 +61917 x11905 +61917 x11906 +61917 x11907 +61917 x11908 +61917 x11909 +61917 x11910 +61917 x11911 +61917 x11912 +61917 x11913 +61917 x11914 +61917 x11915 +61917 x11916 +61917 x11917 +61917 x11918 +61917 x11919 +61917 x11920 +61917 x11921 +61917 x11922 +61917 x11923 +61917 x11924 +61917 x11925 +61917 x11926 +61917 x11927 +61917 x11928 +61917 x11929 +61917 x11930 +61917 x11931 +61917 x11932 +61917 x11933 +61917 x11934 +61917 x11935 +61917 x11936 +61917 x11937 +61917 x11938 +61917 x11939 +61917 x11940 +61917 x11941 +61917 x11942 +61917 x11943 +61917 x11944 +61917 x11945 +61917 x11946 +61917 x11947 +61917 x11948 +61917 x11949 +61917 x11950 +61917 x11951 +61917 x11952 +61917 x11953 +61917 x11954 +61917 x11955 +61917 x11956 +61917 x11957 +61917 x11958 +61917 x11959 +61917 x11960 +61917 x11961 +61917 x11962 +61917 x11963 +61917 x11964 +61917 x11965 +61917 x11966 +61917 x11967 +61917 x11968 +61917 x11969 +61917 x11970 +61917 x11971 +61917 x11972 +61917 x11973 +61917 x11974 +61917 x11975 +61917 x11976 +61917 x11977 +61917 x11978 +61917 x11979 +61917 x11980 +61917 x11981 +61917 x11982 +61917 x11983 +61917 x11984 +61917 x11985 +61917 x11986 +61917 x11987 +61917 x11988 +61917 x11989 +61917 x11990 +61917 x11991 +61917 x11992 +61917 x11993 +61917 x11994 +61917 x11995 +61917 x11996 +61917 x11997 +61917 x11998 +61917 x11999 +61917 x12000 +61917 x12001 +61917 x12002 +61917 x12003 +61917 x12004 +61917 x12005 +61917 x12006 +61917 x12007 +61917 x12008 +61917 x12009 +61917 x12010 +61917 x12011 +61917 x12012 +61917 x12013 +61917 x12014 +61917 x12015 +61917 x12016 +61917 x12017 +61917 x12018 +61917 x12019 +61917 x12020 +61917 x12021 +61917 x12022 +61917 x12023 +61917 x12024 +61917 x12025 +61917 x12026 +61917 x12027 +61917 x12028 +61917 x12029 +61917 x12030 +61917 x12031 +61917 x12032 +18338 x12033 +18338 x12034 +18338 x12035 +18338 x12036 +18338 x12037 +18338 x12038 +18338 x12039 +18338 x12040 +18338 x12041 +18338 x12042 +18338 x12043 +18338 x12044 +18338 x12045 +18338 x12046 +18338 x12047 +18338 x12048 +18338 x12049 +18338 x12050 +18338 x12051 +18338 x12052 +18338 x12053 +18338 x12054 +18338 x12055 +18338 x12056 +18338 x12057 +18338 x12058 +18338 x12059 +18338 x12060 +18338 x12061 +18338 x12062 +18338 x12063 +18338 x12064 +18338 x12065 +18338 x12066 +18338 x12067 +18338 x12068 +18338 x12069 +18338 x12070 +18338 x12071 +18338 x12072 +18338 x12073 +18338 x12074 +18338 x12075 +18338 x12076 +18338 x12077 +18338 x12078 +18338 x12079 +18338 x12080 +18338 x12081 +18338 x12082 +18338 x12083 +18338 x12084 +18338 x12085 +18338 x12086 +18338 x12087 +18338 x12088 +18338 x12089 +18338 x12090 +18338 x12091 +18338 x12092 +18338 x12093 +18338 x12094 +18338 x12095 +18338 x12096 +18338 x12097 +18338 x12098 +18338 x12099 +18338 x12100 +18338 x12101 +18338 x12102 +18338 x12103 +18338 x12104 +18338 x12105 +18338 x12106 +18338 x12107 +18338 x12108 +18338 x12109 +18338 x12110 +18338 x12111 +18338 x12112 +18338 x12113 +18338 x12114 +18338 x12115 +18338 x12116 +18338 x12117 +18338 x12118 +18338 x12119 +18338 x12120 +18338 x12121 +18338 x12122 +18338 x12123 +18338 x12124 +18338 x12125 +18338 x12126 +18338 x12127 +18338 x12128 +18338 x12129 +18338 x12130 +18338 x12131 +18338 x12132 +18338 x12133 +18338 x12134 +18338 x12135 +18338 x12136 +18338 x12137 +18338 x12138 +18338 x12139 +18338 x12140 +18338 x12141 +18338 x12142 +18338 x12143 +18338 x12144 +18338 x12145 +18338 x12146 +18338 x12147 +18338 x12148 +18338 x12149 +18338 x12150 +18338 x12151 +18338 x12152 +18338 x12153 +18338 x12154 +18338 x12155 +18338 x12156 +18338 x12157 +18338 x12158 +18338 x12159 +18338 x12160 +33122 x12161 +33122 x12162 +33122 x12163 +33122 x12164 +33122 x12165 +33122 x12166 +33122 x12167 +33122 x12168 +33122 x12169 +33122 x12170 +33122 x12171 +33122 x12172 +33122 x12173 +33122 x12174 +33122 x12175 +33122 x12176 +33122 x12177 +33122 x12178 +33122 x12179 +33122 x12180 +33122 x12181 +33122 x12182 +33122 x12183 +33122 x12184 +33122 x12185 +33122 x12186 +33122 x12187 +33122 x12188 +33122 x12189 +33122 x12190 +33122 x12191 +33122 x12192 +33122 x12193 +33122 x12194 +33122 x12195 +33122 x12196 +33122 x12197 +33122 x12198 +33122 x12199 +33122 x12200 +33122 x12201 +33122 x12202 +33122 x12203 +33122 x12204 +33122 x12205 +33122 x12206 +33122 x12207 +33122 x12208 +33122 x12209 +33122 x12210 +33122 x12211 +33122 x12212 +33122 x12213 +33122 x12214 +33122 x12215 +33122 x12216 +33122 x12217 +33122 x12218 +33122 x12219 +33122 x12220 +33122 x12221 +33122 x12222 +33122 x12223 +33122 x12224 +33122 x12225 +33122 x12226 +33122 x12227 +33122 x12228 +33122 x12229 +33122 x12230 +33122 x12231 +33122 x12232 +33122 x12233 +33122 x12234 +33122 x12235 +33122 x12236 +33122 x12237 +33122 x12238 +33122 x12239 +33122 x12240 +33122 x12241 +33122 x12242 +33122 x12243 +33122 x12244 +33122 x12245 +33122 x12246 +33122 x12247 +33122 x12248 +33122 x12249 +33122 x12250 +33122 x12251 +33122 x12252 +33122 x12253 +33122 x12254 +33122 x12255 +33122 x12256 +33122 x12257 +33122 x12258 +33122 x12259 +33122 x12260 +33122 x12261 +33122 x12262 +33122 x12263 +33122 x12264 +33122 x12265 +33122 x12266 +33122 x12267 +33122 x12268 +33122 x12269 +33122 x12270 +33122 x12271 +33122 x12272 +33122 x12273 +33122 x12274 +33122 x12275 +33122 x12276 +33122 x12277 +33122 x12278 +33122 x12279 +33122 x12280 +33122 x12281 +33122 x12282 +33122 x12283 +33122 x12284 +33122 x12285 +33122 x12286 +33122 x12287 +33122 x12288 +36520 x12289 +36520 x12290 +36520 x12291 +36520 x12292 +36520 x12293 +36520 x12294 +36520 x12295 +36520 x12296 +36520 x12297 +36520 x12298 +36520 x12299 +36520 x12300 +36520 x12301 +36520 x12302 +36520 x12303 +36520 x12304 +36520 x12305 +36520 x12306 +36520 x12307 +36520 x12308 +36520 x12309 +36520 x12310 +36520 x12311 +36520 x12312 +36520 x12313 +36520 x12314 +36520 x12315 +36520 x12316 +36520 x12317 +36520 x12318 +36520 x12319 +36520 x12320 +36520 x12321 +36520 x12322 +36520 x12323 +36520 x12324 +36520 x12325 +36520 x12326 +36520 x12327 +36520 x12328 +36520 x12329 +36520 x12330 +36520 x12331 +36520 x12332 +36520 x12333 +36520 x12334 +36520 x12335 +36520 x12336 +36520 x12337 +36520 x12338 +36520 x12339 +36520 x12340 +36520 x12341 +36520 x12342 +36520 x12343 +36520 x12344 +36520 x12345 +36520 x12346 +36520 x12347 +36520 x12348 +36520 x12349 +36520 x12350 +36520 x12351 +36520 x12352 +36520 x12353 +36520 x12354 +36520 x12355 +36520 x12356 +36520 x12357 +36520 x12358 +36520 x12359 +36520 x12360 +36520 x12361 +36520 x12362 +36520 x12363 +36520 x12364 +36520 x12365 +36520 x12366 +36520 x12367 +36520 x12368 +36520 x12369 +36520 x12370 +36520 x12371 +36520 x12372 +36520 x12373 +36520 x12374 +36520 x12375 +36520 x12376 +36520 x12377 +36520 x12378 +36520 x12379 +36520 x12380 +36520 x12381 +36520 x12382 +36520 x12383 +36520 x12384 +36520 x12385 +36520 x12386 +36520 x12387 +36520 x12388 +36520 x12389 +36520 x12390 +36520 x12391 +36520 x12392 +36520 x12393 +36520 x12394 +36520 x12395 +36520 x12396 +36520 x12397 +36520 x12398 +36520 x12399 +36520 x12400 +36520 x12401 +36520 x12402 +36520 x12403 +36520 x12404 +36520 x12405 +36520 x12406 +36520 x12407 +36520 x12408 +36520 x12409 +36520 x12410 +36520 x12411 +36520 x12412 +36520 x12413 +36520 x12414 +36520 x12415 +36520 x12416 +67639 x12417 +67639 x12418 +67639 x12419 +67639 x12420 +67639 x12421 +67639 x12422 +67639 x12423 +67639 x12424 +67639 x12425 +67639 x12426 +67639 x12427 +67639 x12428 +67639 x12429 +67639 x12430 +67639 x12431 +67639 x12432 +67639 x12433 +67639 x12434 +67639 x12435 +67639 x12436 +67639 x12437 +67639 x12438 +67639 x12439 +67639 x12440 +67639 x12441 +67639 x12442 +67639 x12443 +67639 x12444 +67639 x12445 +67639 x12446 +67639 x12447 +67639 x12448 +67639 x12449 +67639 x12450 +67639 x12451 +67639 x12452 +67639 x12453 +67639 x12454 +67639 x12455 +67639 x12456 +67639 x12457 +67639 x12458 +67639 x12459 +67639 x12460 +67639 x12461 +67639 x12462 +67639 x12463 +67639 x12464 +67639 x12465 +67639 x12466 +67639 x12467 +67639 x12468 +67639 x12469 +67639 x12470 +67639 x12471 +67639 x12472 +67639 x12473 +67639 x12474 +67639 x12475 +67639 x12476 +67639 x12477 +67639 x12478 +67639 x12479 +67639 x12480 +67639 x12481 +67639 x12482 +67639 x12483 +67639 x12484 +67639 x12485 +67639 x12486 +67639 x12487 +67639 x12488 +67639 x12489 +67639 x12490 +67639 x12491 +67639 x12492 +67639 x12493 +67639 x12494 +67639 x12495 +67639 x12496 +67639 x12497 +67639 x12498 +67639 x12499 +67639 x12500 +67639 x12501 +67639 x12502 +67639 x12503 +67639 x12504 +67639 x12505 +67639 x12506 +67639 x12507 +67639 x12508 +67639 x12509 +67639 x12510 +67639 x12511 +67639 x12512 +67639 x12513 +67639 x12514 +67639 x12515 +67639 x12516 +67639 x12517 +67639 x12518 +67639 x12519 +67639 x12520 +67639 x12521 +67639 x12522 +67639 x12523 +67639 x12524 +67639 x12525 +67639 x12526 +67639 x12527 +67639 x12528 +67639 x12529 +67639 x12530 +67639 x12531 +67639 x12532 +67639 x12533 +67639 x12534 +67639 x12535 +67639 x12536 +67639 x12537 +67639 x12538 +67639 x12539 +67639 x12540 +67639 x12541 +67639 x12542 +67639 x12543 +67639 x12544 +31355 x12545 +31355 x12546 +31355 x12547 +31355 x12548 +31355 x12549 +31355 x12550 +31355 x12551 +31355 x12552 +31355 x12553 +31355 x12554 +31355 x12555 +31355 x12556 +31355 x12557 +31355 x12558 +31355 x12559 +31355 x12560 +31355 x12561 +31355 x12562 +31355 x12563 +31355 x12564 +31355 x12565 +31355 x12566 +31355 x12567 +31355 x12568 +31355 x12569 +31355 x12570 +31355 x12571 +31355 x12572 +31355 x12573 +31355 x12574 +31355 x12575 +31355 x12576 +31355 x12577 +31355 x12578 +31355 x12579 +31355 x12580 +31355 x12581 +31355 x12582 +31355 x12583 +31355 x12584 +31355 x12585 +31355 x12586 +31355 x12587 +31355 x12588 +31355 x12589 +31355 x12590 +31355 x12591 +31355 x12592 +31355 x12593 +31355 x12594 +31355 x12595 +31355 x12596 +31355 x12597 +31355 x12598 +31355 x12599 +31355 x12600 +31355 x12601 +31355 x12602 +31355 x12603 +31355 x12604 +31355 x12605 +31355 x12606 +31355 x12607 +31355 x12608 +31355 x12609 +31355 x12610 +31355 x12611 +31355 x12612 +31355 x12613 +31355 x12614 +31355 x12615 +31355 x12616 +31355 x12617 +31355 x12618 +31355 x12619 +31355 x12620 +31355 x12621 +31355 x12622 +31355 x12623 +31355 x12624 +31355 x12625 +31355 x12626 +31355 x12627 +31355 x12628 +31355 x12629 +31355 x12630 +31355 x12631 +31355 x12632 +31355 x12633 +31355 x12634 +31355 x12635 +31355 x12636 +31355 x12637 +31355 x12638 +31355 x12639 +31355 x12640 +31355 x12641 +31355 x12642 +31355 x12643 +31355 x12644 +31355 x12645 +31355 x12646 +31355 x12647 +31355 x12648 +31355 x12649 +31355 x12650 +31355 x12651 +31355 x12652 +31355 x12653 +31355 x12654 +31355 x12655 +31355 x12656 +31355 x12657 +31355 x12658 +31355 x12659 +31355 x12660 +31355 x12661 +31355 x12662 +31355 x12663 +31355 x12664 +31355 x12665 +31355 x12666 +31355 x12667 +31355 x12668 +31355 x12669 +31355 x12670 +31355 x12671 +31355 x12672 +4915 x12673 +4915 x12674 +4915 x12675 +4915 x12676 +4915 x12677 +4915 x12678 +4915 x12679 +4915 x12680 +4915 x12681 +4915 x12682 +4915 x12683 +4915 x12684 +4915 x12685 +4915 x12686 +4915 x12687 +4915 x12688 +4915 x12689 +4915 x12690 +4915 x12691 +4915 x12692 +4915 x12693 +4915 x12694 +4915 x12695 +4915 x12696 +4915 x12697 +4915 x12698 +4915 x12699 +4915 x12700 +4915 x12701 +4915 x12702 +4915 x12703 +4915 x12704 +4915 x12705 +4915 x12706 +4915 x12707 +4915 x12708 +4915 x12709 +4915 x12710 +4915 x12711 +4915 x12712 +4915 x12713 +4915 x12714 +4915 x12715 +4915 x12716 +4915 x12717 +4915 x12718 +4915 x12719 +4915 x12720 +4915 x12721 +4915 x12722 +4915 x12723 +4915 x12724 +4915 x12725 +4915 x12726 +4915 x12727 +4915 x12728 +4915 x12729 +4915 x12730 +4915 x12731 +4915 x12732 +4915 x12733 +4915 x12734 +4915 x12735 +4915 x12736 +4915 x12737 +4915 x12738 +4915 x12739 +4915 x12740 +4915 x12741 +4915 x12742 +4915 x12743 +4915 x12744 +4915 x12745 +4915 x12746 +4915 x12747 +4915 x12748 +4915 x12749 +4915 x12750 +4915 x12751 +4915 x12752 +4915 x12753 +4915 x12754 +4915 x12755 +4915 x12756 +4915 x12757 +4915 x12758 +4915 x12759 +4915 x12760 +4915 x12761 +4915 x12762 +4915 x12763 +4915 x12764 +4915 x12765 +4915 x12766 +4915 x12767 +4915 x12768 +4915 x12769 +4915 x12770 +4915 x12771 +4915 x12772 +4915 x12773 +4915 x12774 +4915 x12775 +4915 x12776 +4915 x12777 +4915 x12778 +4915 x12779 +4915 x12780 +4915 x12781 +4915 x12782 +4915 x12783 +4915 x12784 +4915 x12785 +4915 x12786 +4915 x12787 +4915 x12788 +4915 x12789 +4915 x12790 +4915 x12791 +4915 x12792 +4915 x12793 +4915 x12794 +4915 x12795 +4915 x12796 +4915 x12797 +4915 x12798 +4915 x12799 +4915 x12800 ;++1 x1537 +1 x1538 +1 x1539 +1 x1540 +1 x1541 +1 x1542 +1 x1543 +1 x1544 +1 x1545 +1 x1546 +1 x1547 +1 x1548 +1 x1549 +1 x1550 +1 x1551 +1 x1552 +1 x1553 +1 x1554 +1 x1555 +1 x1556 +1 x1557 +1 x1558 +1 x1559 +1 x1560 +1 x1561 +1 x1562 +1 x1563 +1 x1564 +1 x1565 +1 x1566 +1 x1567 +1 x1568 +1 x1569 +1 x1570 +1 x1571 +1 x1572 +1 x1573 +1 x1574 +1 x1575 +1 x1576 +1 x1577 +1 x1578 +1 x1579 +1 x1580 +1 x1581 +1 x1582 +1 x1583 +1 x1584 +1 x1585 +1 x1586 +1 x1587 +1 x1588 +1 x1589 +1 x1590 +1 x1591 +1 x1592 +1 x1593 +1 x1594 +1 x1595 +1 x1596 +1 x1597 +1 x1598 +1 x1599 +1 x1600 +1 x1601 +1 x1602 +1 x1603 +1 x1604 +1 x1605 +1 x1606 +1 x1607 +1 x1608 +1 x1609 +1 x1610 +1 x1611 +1 x1612 +1 x1613 +1 x1614 +1 x1615 +1 x1616 +1 x1617 +1 x1618 +1 x1619 +1 x1620 +1 x1621 +1 x1622 +1 x1623 +1 x1624 +1 x1625 +1 x1626 +1 x1627 +1 x1628 +1 x1629 +1 x1630 +1 x1631 +1 x1632 +1 x1633 +1 x1634 +1 x1635 +1 x1636 +1 x1637 +1 x1638 +1 x1639 +1 x1640 +1 x1641 +1 x1642 +1 x1643 +1 x1644 +1 x1645 +1 x1646 +1 x1647 +1 x1648 +1 x1649 +1 x1650 +1 x1651 +1 x1652 +1 x1653 +1 x1654 +1 x1655 +1 x1656 +1 x1657 +1 x1658 +1 x1659 +1 x1660 +1 x1661 +1 x1662 +1 x1663 +1 x1664 +1 x1665 +1 x1666 +1 x1667 +1 x1668 +1 x1669 +1 x1670 +1 x1671 +1 x1672 +1 x1673 +1 x1674 +1 x1675 +1 x1676 +1 x1677 +1 x1678 +1 x1679 +1 x1680 +1 x1681 +1 x1682 +1 x1683 +1 x1684 +1 x1685 +1 x1686 +1 x1687 +1 x1688 +1 x1689 +1 x1690 +1 x1691 +1 x1692 +1 x1693 +1 x1694 +1 x1695 +1 x1696 +1 x1697 +1 x1698 +1 x1699 +1 x1700 +1 x1701 +1 x1702 +1 x1703 +1 x1704 +1 x1705 +1 x1706 +1 x1707 +1 x1708 +1 x1709 +1 x1710 +1 x1711 +1 x1712 +1 x1713 +1 x1714 +1 x1715 +1 x1716 +1 x1717 +1 x1718 +1 x1719 +1 x1720 +1 x1721 +1 x1722 +1 x1723 +1 x1724 +1 x1725 +1 x1726 +1 x1727 +1 x1728 +1 x1729 +1 x1730 +1 x1731 +1 x1732 +1 x1733 +1 x1734 +1 x1735 +1 x1736 +1 x1737 +1 x1738 +1 x1739 +1 x1740 +1 x1741 +1 x1742 +1 x1743 +1 x1744 +1 x1745 +1 x1746 +1 x1747 +1 x1748 +1 x1749 +1 x1750 +1 x1751 +1 x1752 +1 x1753 +1 x1754 +1 x1755 +1 x1756 +1 x1757 +1 x1758 +1 x1759 +1 x1760 +1 x1761 +1 x1762 +1 x1763 +1 x1764 +1 x1765 +1 x1766 +1 x1767 +1 x1768 +1 x1769 +1 x1770 +1 x1771 +1 x1772 +1 x1773 +1 x1774 +1 x1775 +1 x1776 +1 x1777 +1 x1778 +1 x1779 +1 x1780 +1 x1781 +1 x1782 +1 x1783 +1 x1784 +1 x1785 +1 x1786 +1 x1787 +1 x1788 +1 x1789 +1 x1790 +1 x1791 +1 x1792 +1 x2433 +1 x2434 +1 x2435 +1 x2436 +1 x2437 +1 x2438 +1 x2439 +1 x2440 +1 x2441 +1 x2442 +1 x2443 +1 x2444 +1 x2445 +1 x2446 +1 x2447 +1 x2448 +1 x2449 +1 x2450 +1 x2451 +1 x2452 +1 x2453 +1 x2454 +1 x2455 +1 x2456 +1 x2457 +1 x2458 +1 x2459 +1 x2460 +1 x2461 +1 x2462 +1 x2463 +1 x2464 +1 x2465 +1 x2466 +1 x2467 +1 x2468 +1 x2469 +1 x2470 +1 x2471 +1 x2472 +1 x2473 +1 x2474 +1 x2475 +1 x2476 +1 x2477 +1 x2478 +1 x2479 +1 x2480 +1 x2481 +1 x2482 +1 x2483 +1 x2484 +1 x2485 +1 x2486 +1 x2487 +1 x2488 +1 x2489 +1 x2490 +1 x2491 +1 x2492 +1 x2493 +1 x2494 +1 x2495 +1 x2496 +1 x2497 +1 x2498 +1 x2499 +1 x2500 +1 x2501 +1 x2502 +1 x2503 +1 x2504 +1 x2505 +1 x2506 +1 x2507 +1 x2508 +1 x2509 +1 x2510 +1 x2511 +1 x2512 +1 x2513 +1 x2514 +1 x2515 +1 x2516 +1 x2517 +1 x2518 +1 x2519 +1 x2520 +1 x2521 +1 x2522 +1 x2523 +1 x2524 +1 x2525 +1 x2526 +1 x2527 +1 x2528 +1 x2529 +1 x2530 +1 x2531 +1 x2532 +1 x2533 +1 x2534 +1 x2535 +1 x2536 +1 x2537 +1 x2538 +1 x2539 +1 x2540 +1 x2541 +1 x2542 +1 x2543 +1 x2544 +1 x2545 +1 x2546 +1 x2547 +1 x2548 +1 x2549 +1 x2550 +1 x2551 +1 x2552 +1 x2553 +1 x2554 +1 x2555 +1 x2556 +1 x2557 +1 x2558 +1 x2559 +1 x2560 +1 x3969 +1 x3970 +1 x3971 +1 x3972 +1 x3973 +1 x3974 +1 x3975 +1 x3976 +1 x3977 +1 x3978 +1 x3979 +1 x3980 +1 x3981 +1 x3982 +1 x3983 +1 x3984 +1 x3985 +1 x3986 +1 x3987 +1 x3988 +1 x3989 +1 x3990 +1 x3991 +1 x3992 +1 x3993 +1 x3994 +1 x3995 +1 x3996 +1 x3997 +1 x3998 +1 x3999 +1 x4000 +1 x4001 +1 x4002 +1 x4003 +1 x4004 +1 x4005 +1 x4006 +1 x4007 +1 x4008 +1 x4009 +1 x4010 +1 x4011 +1 x4012 +1 x4013 +1 x4014 +1 x4015 +1 x4016 +1 x4017 +1 x4018 +1 x4019 +1 x4020 +1 x4021 +1 x4022 +1 x4023 +1 x4024 +1 x4025 +1 x4026 +1 x4027 +1 x4028 +1 x4029 +1 x4030 +1 x4031 +1 x4032 +1 x4033 +1 x4034 +1 x4035 +1 x4036 +1 x4037 +1 x4038 +1 x4039 +1 x4040 +1 x4041 +1 x4042 +1 x4043 +1 x4044 +1 x4045 +1 x4046 +1 x4047 +1 x4048 +1 x4049 +1 x4050 +1 x4051 +1 x4052 +1 x4053 +1 x4054 +1 x4055 +1 x4056 +1 x4057 +1 x4058 +1 x4059 +1 x4060 +1 x4061 +1 x4062 +1 x4063 +1 x4064 +1 x4065 +1 x4066 +1 x4067 +1 x4068 +1 x4069 +1 x4070 +1 x4071 +1 x4072 +1 x4073 +1 x4074 +1 x4075 +1 x4076 +1 x4077 +1 x4078 +1 x4079 +1 x4080 +1 x4081 +1 x4082 +1 x4083 +1 x4084 +1 x4085 +1 x4086 +1 x4087 +1 x4088 +1 x4089 +1 x4090 +1 x4091 +1 x4092 +1 x4093 +1 x4094 +1 x4095 +1 x4096 +1 x4353 +1 x4354 +1 x4355 +1 x4356 +1 x4357 +1 x4358 +1 x4359 +1 x4360 +1 x4361 +1 x4362 +1 x4363 +1 x4364 +1 x4365 +1 x4366 +1 x4367 +1 x4368 +1 x4369 +1 x4370 +1 x4371 +1 x4372 +1 x4373 +1 x4374 +1 x4375 +1 x4376 +1 x4377 +1 x4378 +1 x4379 +1 x4380 +1 x4381 +1 x4382 +1 x4383 +1 x4384 +1 x4385 +1 x4386 +1 x4387 +1 x4388 +1 x4389 +1 x4390 +1 x4391 +1 x4392 +1 x4393 +1 x4394 +1 x4395 +1 x4396 +1 x4397 +1 x4398 +1 x4399 +1 x4400 +1 x4401 +1 x4402 +1 x4403 +1 x4404 +1 x4405 +1 x4406 +1 x4407 +1 x4408 +1 x4409 +1 x4410 +1 x4411 +1 x4412 +1 x4413 +1 x4414 +1 x4415 +1 x4416 +1 x4417 +1 x4418 +1 x4419 +1 x4420 +1 x4421 +1 x4422 +1 x4423 +1 x4424 +1 x4425 +1 x4426 +1 x4427 +1 x4428 +1 x4429 +1 x4430 +1 x4431 +1 x4432 +1 x4433 +1 x4434 +1 x4435 +1 x4436 +1 x4437 +1 x4438 +1 x4439 +1 x4440 +1 x4441 +1 x4442 +1 x4443 +1 x4444 +1 x4445 +1 x4446 +1 x4447 +1 x4448 +1 x4449 +1 x4450 +1 x4451 +1 x4452 +1 x4453 +1 x4454 +1 x4455 +1 x4456 +1 x4457 +1 x4458 +1 x4459 +1 x4460 +1 x4461 +1 x4462 +1 x4463 +1 x4464 +1 x4465 +1 x4466 +1 x4467 +1 x4468 +1 x4469 +1 x4470 +1 x4471 +1 x4472 +1 x4473 +1 x4474 +1 x4475 +1 x4476 +1 x4477 +1 x4478 +1 x4479 +1 x4480 +1 x6657 +1 x6658 +1 x6659 +1 x6660 +1 x6661 +1 x6662 +1 x6663 +1 x6664 +1 x6665 +1 x6666 +1 x6667 +1 x6668 +1 x6669 +1 x6670 +1 x6671 +1 x6672 +1 x6673 +1 x6674 +1 x6675 +1 x6676 +1 x6677 +1 x6678 +1 x6679 +1 x6680 +1 x6681 +1 x6682 +1 x6683 +1 x6684 +1 x6685 +1 x6686 +1 x6687 +1 x6688 +1 x6689 +1 x6690 +1 x6691 +1 x6692 +1 x6693 +1 x6694 +1 x6695 +1 x6696 +1 x6697 +1 x6698 +1 x6699 +1 x6700 +1 x6701 +1 x6702 +1 x6703 +1 x6704 +1 x6705 +1 x6706 +1 x6707 +1 x6708 +1 x6709 +1 x6710 +1 x6711 +1 x6712 +1 x6713 +1 x6714 +1 x6715 +1 x6716 +1 x6717 +1 x6718 +1 x6719 +1 x6720 +1 x6721 +1 x6722 +1 x6723 +1 x6724 +1 x6725 +1 x6726 +1 x6727 +1 x6728 +1 x6729 +1 x6730 +1 x6731 +1 x6732 +1 x6733 +1 x6734 +1 x6735 +1 x6736 +1 x6737 +1 x6738 +1 x6739 +1 x6740 +1 x6741 +1 x6742 +1 x6743 +1 x6744 +1 x6745 +1 x6746 +1 x6747 +1 x6748 +1 x6749 +1 x6750 +1 x6751 +1 x6752 +1 x6753 +1 x6754 +1 x6755 +1 x6756 +1 x6757 +1 x6758 +1 x6759 +1 x6760 +1 x6761 +1 x6762 +1 x6763 +1 x6764 +1 x6765 +1 x6766 +1 x6767 +1 x6768 +1 x6769 +1 x6770 +1 x6771 +1 x6772 +1 x6773 +1 x6774 +1 x6775 +1 x6776 +1 x6777 +1 x6778 +1 x6779 +1 x6780 +1 x6781 +1 x6782 +1 x6783 +1 x6784 +1 x7041 +1 x7042 +1 x7043 +1 x7044 +1 x7045 +1 x7046 +1 x7047 +1 x7048 +1 x7049 +1 x7050 +1 x7051 +1 x7052 +1 x7053 +1 x7054 +1 x7055 +1 x7056 +1 x7057 +1 x7058 +1 x7059 +1 x7060 +1 x7061 +1 x7062 +1 x7063 +1 x7064 +1 x7065 +1 x7066 +1 x7067 +1 x7068 +1 x7069 +1 x7070 +1 x7071 +1 x7072 +1 x7073 +1 x7074 +1 x7075 +1 x7076 +1 x7077 +1 x7078 +1 x7079 +1 x7080 +1 x7081 +1 x7082 +1 x7083 +1 x7084 +1 x7085 +1 x7086 +1 x7087 +1 x7088 +1 x7089 +1 x7090 +1 x7091 +1 x7092 +1 x7093 +1 x7094 +1 x7095 +1 x7096 +1 x7097 +1 x7098 +1 x7099 +1 x7100 +1 x7101 +1 x7102 +1 x7103 +1 x7104 +1 x7105 +1 x7106 +1 x7107 +1 x7108 +1 x7109 +1 x7110 +1 x7111 +1 x7112 +1 x7113 +1 x7114 +1 x7115 +1 x7116 +1 x7117 +1 x7118 +1 x7119 +1 x7120 +1 x7121 +1 x7122 +1 x7123 +1 x7124 +1 x7125 +1 x7126 +1 x7127 +1 x7128 +1 x7129 +1 x7130 +1 x7131 +1 x7132 +1 x7133 +1 x7134 +1 x7135 +1 x7136 +1 x7137 +1 x7138 +1 x7139 +1 x7140 +1 x7141 +1 x7142 +1 x7143 +1 x7144 +1 x7145 +1 x7146 +1 x7147 +1 x7148 +1 x7149 +1 x7150 +1 x7151 +1 x7152 +1 x7153 +1 x7154 +1 x7155 +1 x7156 +1 x7157 +1 x7158 +1 x7159 +1 x7160 +1 x7161 +1 x7162 +1 x7163 +1 x7164 +1 x7165 +1 x7166 +1 x7167 +1 x7168 +1 x7553 +1 x7554 +1 x7555 +1 x7556 +1 x7557 +1 x7558 +1 x7559 +1 x7560 +1 x7561 +1 x7562 +1 x7563 +1 x7564 +1 x7565 +1 x7566 +1 x7567 +1 x7568 +1 x7569 +1 x7570 +1 x7571 +1 x7572 +1 x7573 +1 x7574 +1 x7575 +1 x7576 +1 x7577 +1 x7578 +1 x7579 +1 x7580 +1 x7581 +1 x7582 +1 x7583 +1 x7584 +1 x7585 +1 x7586 +1 x7587 +1 x7588 +1 x7589 +1 x7590 +1 x7591 +1 x7592 +1 x7593 +1 x7594 +1 x7595 +1 x7596 +1 x7597 +1 x7598 +1 x7599 +1 x7600 +1 x7601 +1 x7602 +1 x7603 +1 x7604 +1 x7605 +1 x7606 +1 x7607 +1 x7608 +1 x7609 +1 x7610 +1 x7611 +1 x7612 +1 x7613 +1 x7614 +1 x7615 +1 x7616 +1 x7617 +1 x7618 +1 x7619 +1 x7620 +1 x7621 +1 x7622 +1 x7623 +1 x7624 +1 x7625 +1 x7626 +1 x7627 +1 x7628 +1 x7629 +1 x7630 +1 x7631 +1 x7632 +1 x7633 +1 x7634 +1 x7635 +1 x7636 +1 x7637 +1 x7638 +1 x7639 +1 x7640 +1 x7641 +1 x7642 +1 x7643 +1 x7644 +1 x7645 +1 x7646 +1 x7647 +1 x7648 +1 x7649 +1 x7650 +1 x7651 +1 x7652 +1 x7653 +1 x7654 +1 x7655 +1 x7656 +1 x7657 +1 x7658 +1 x7659 +1 x7660 +1 x7661 +1 x7662 +1 x7663 +1 x7664 +1 x7665 +1 x7666 +1 x7667 +1 x7668 +1 x7669 +1 x7670 +1 x7671 +1 x7672 +1 x7673 +1 x7674 +1 x7675 +1 x7676 +1 x7677 +1 x7678 +1 x7679 +1 x7680 +1 x12161 +1 x12162 +1 x12163 +1 x12164 +1 x12165 +1 x12166 +1 x12167 +1 x12168 +1 x12169 +1 x12170 +1 x12171 +1 x12172 +1 x12173 +1 x12174 +1 x12175 +1 x12176 +1 x12177 +1 x12178 +1 x12179 +1 x12180 +1 x12181 +1 x12182 +1 x12183 +1 x12184 +1 x12185 +1 x12186 +1 x12187 +1 x12188 +1 x12189 +1 x12190 +1 x12191 +1 x12192 +1 x12193 +1 x12194 +1 x12195 +1 x12196 +1 x12197 +1 x12198 +1 x12199 +1 x12200 +1 x12201 +1 x12202 +1 x12203 +1 x12204 +1 x12205 +1 x12206 +1 x12207 +1 x12208 +1 x12209 +1 x12210 +1 x12211 +1 x12212 +1 x12213 +1 x12214 +1 x12215 +1 x12216 +1 x12217 +1 x12218 +1 x12219 +1 x12220 +1 x12221 +1 x12222 +1 x12223 +1 x12224 +1 x12225 +1 x12226 +1 x12227 +1 x12228 +1 x12229 +1 x12230 +1 x12231 +1 x12232 +1 x12233 +1 x12234 +1 x12235 +1 x12236 +1 x12237 +1 x12238 +1 x12239 +1 x12240 +1 x12241 +1 x12242 +1 x12243 +1 x12244 +1 x12245 +1 x12246 +1 x12247 +1 x12248 +1 x12249 +1 x12250 +1 x12251 +1 x12252 +1 x12253 +1 x12254 +1 x12255 +1 x12256 +1 x12257 +1 x12258 +1 x12259 +1 x12260 +1 x12261 +1 x12262 +1 x12263 +1 x12264 +1 x12265 +1 x12266 +1 x12267 +1 x12268 +1 x12269 +1 x12270 +1 x12271 +1 x12272 +1 x12273 +1 x12274 +1 x12275 +1 x12276 +1 x12277 +1 x12278 +1 x12279 +1 x12280 +1 x12281 +1 x12282 +1 x12283 +1 x12284 +1 x12285 +1 x12286 +1 x12287 +1 x12288 = 1 ;++1 x11009 +1 x11010 +1 x11011 +1 x11012 +1 x11013 +1 x11014 +1 x11015 +1 x11016 +1 x11017 +1 x11018 +1 x11019 +1 x11020 +1 x11021 +1 x11022 +1 x11023 +1 x11024 +1 x11025 +1 x11026 +1 x11027 +1 x11028 +1 x11029 +1 x11030 +1 x11031 +1 x11032 +1 x11033 +1 x11034 +1 x11035 +1 x11036 +1 x11037 +1 x11038 +1 x11039 +1 x11040 +1 x11041 +1 x11042 +1 x11043 +1 x11044 +1 x11045 +1 x11046 +1 x11047 +1 x11048 +1 x11049 +1 x11050 +1 x11051 +1 x11052 +1 x11053 +1 x11054 +1 x11055 +1 x11056 +1 x11057 +1 x11058 +1 x11059 +1 x11060 +1 x11061 +1 x11062 +1 x11063 +1 x11064 +1 x11065 +1 x11066 +1 x11067 +1 x11068 +1 x11069 +1 x11070 +1 x11071 +1 x11072 +1 x11073 +1 x11074 +1 x11075 +1 x11076 +1 x11077 +1 x11078 +1 x11079 +1 x11080 +1 x11081 +1 x11082 +1 x11083 +1 x11084 +1 x11085 +1 x11086 +1 x11087 +1 x11088 +1 x11089 +1 x11090 +1 x11091 +1 x11092 +1 x11093 +1 x11094 +1 x11095 +1 x11096 +1 x11097 +1 x11098 +1 x11099 +1 x11100 +1 x11101 +1 x11102 +1 x11103 +1 x11104 +1 x11105 +1 x11106 +1 x11107 +1 x11108 +1 x11109 +1 x11110 +1 x11111 +1 x11112 +1 x11113 +1 x11114 +1 x11115 +1 x11116 +1 x11117 +1 x11118 +1 x11119 +1 x11120 +1 x11121 +1 x11122 +1 x11123 +1 x11124 +1 x11125 +1 x11126 +1 x11127 +1 x11128 +1 x11129 +1 x11130 +1 x11131 +1 x11132 +1 x11133 +1 x11134 +1 x11135 +1 x11136 +1 x11137 +1 x11138 +1 x11139 +1 x11140 +1 x11141 +1 x11142 +1 x11143 +1 x11144 +1 x11145 +1 x11146 +1 x11147 +1 x11148 +1 x11149 +1 x11150 +1 x11151 +1 x11152 +1 x11153 +1 x11154 +1 x11155 +1 x11156 +1 x11157 +1 x11158 +1 x11159 +1 x11160 +1 x11161 +1 x11162 +1 x11163 +1 x11164 +1 x11165 +1 x11166 +1 x11167 +1 x11168 +1 x11169 +1 x11170 +1 x11171 +1 x11172 +1 x11173 +1 x11174 +1 x11175 +1 x11176 +1 x11177 +1 x11178 +1 x11179 +1 x11180 +1 x11181 +1 x11182 +1 x11183 +1 x11184 +1 x11185 +1 x11186 +1 x11187 +1 x11188 +1 x11189 +1 x11190 +1 x11191 +1 x11192 +1 x11193 +1 x11194 +1 x11195 +1 x11196 +1 x11197 +1 x11198 +1 x11199 +1 x11200 +1 x11201 +1 x11202 +1 x11203 +1 x11204 +1 x11205 +1 x11206 +1 x11207 +1 x11208 +1 x11209 +1 x11210 +1 x11211 +1 x11212 +1 x11213 +1 x11214 +1 x11215 +1 x11216 +1 x11217 +1 x11218 +1 x11219 +1 x11220 +1 x11221 +1 x11222 +1 x11223 +1 x11224 +1 x11225 +1 x11226 +1 x11227 +1 x11228 +1 x11229 +1 x11230 +1 x11231 +1 x11232 +1 x11233 +1 x11234 +1 x11235 +1 x11236 +1 x11237 +1 x11238 +1 x11239 +1 x11240 +1 x11241 +1 x11242 +1 x11243 +1 x11244 +1 x11245 +1 x11246 +1 x11247 +1 x11248 +1 x11249 +1 x11250 +1 x11251 +1 x11252 +1 x11253 +1 x11254 +1 x11255 +1 x11256 +1 x11257 +1 x11258 +1 x11259 +1 x11260 +1 x11261 +1 x11262 +1 x11263 +1 x11264 = 1 ;+-2 x12801 +1 x129 +1 x130 +1 x131 +1 x132 +1 x133 +1 x134 +1 x135 +1 x136 +1 x137 +1 x138 +1 x139 +1 x140 +1 x141 +1 x142 +1 x143 +1 x144 +1 x145 +1 x146 +1 x147 +1 x148 +1 x149 +1 x150 +1 x151 +1 x152 +1 x153 +1 x154 +1 x155 +1 x156 +1 x157 +1 x158 +1 x159 +1 x160 +1 x161 +1 x162 +1 x163 +1 x164 +1 x165 +1 x166 +1 x167 +1 x168 +1 x169 +1 x170 +1 x171 +1 x172 +1 x173 +1 x174 +1 x175 +1 x176 +1 x177 +1 x178 +1 x179 +1 x180 +1 x181 +1 x182 +1 x183 +1 x184 +1 x185 +1 x186 +1 x187 +1 x188 +1 x189 +1 x190 +1 x191 +1 x192 +1 x193 +1 x194 +1 x195 +1 x196 +1 x197 +1 x198 +1 x199 +1 x200 +1 x201 +1 x202 +1 x203 +1 x204 +1 x205 +1 x206 +1 x207 +1 x208 +1 x209 +1 x210 +1 x211 +1 x212 +1 x213 +1 x214 +1 x215 +1 x216 +1 x217 +1 x218 +1 x219 +1 x220 +1 x221 +1 x222 +1 x223 +1 x224 +1 x225 +1 x226 +1 x227 +1 x228 +1 x229 +1 x230 +1 x231 +1 x232 +1 x233 +1 x234 +1 x235 +1 x236 +1 x237 +1 x238 +1 x239 +1 x240 +1 x241 +1 x242 +1 x243 +1 x244 +1 x245 +1 x246 +1 x247 +1 x248 +1 x249 +1 x250 +1 x251 +1 x252 +1 x253 +1 x254 +1 x255 +1 x256 +1 x257 +1 x258 +1 x259 +1 x260 +1 x261 +1 x262 +1 x263 +1 x264 +1 x265 +1 x266 +1 x267 +1 x268 +1 x269 +1 x270 +1 x271 +1 x272 +1 x273 +1 x274 +1 x275 +1 x276 +1 x277 +1 x278 +1 x279 +1 x280 +1 x281 +1 x282 +1 x283 +1 x284 +1 x285 +1 x286 +1 x287 +1 x288 +1 x289 +1 x290 +1 x291 +1 x292 +1 x293 +1 x294 +1 x295 +1 x296 +1 x297 +1 x298 +1 x299 +1 x300 +1 x301 +1 x302 +1 x303 +1 x304 +1 x305 +1 x306 +1 x307 +1 x308 +1 x309 +1 x310 +1 x311 +1 x312 +1 x313 +1 x314 +1 x315 +1 x316 +1 x317 +1 x318 +1 x319 +1 x320 +1 x321 +1 x322 +1 x323 +1 x324 +1 x325 +1 x326 +1 x327 +1 x328 +1 x329 +1 x330 +1 x331 +1 x332 +1 x333 +1 x334 +1 x335 +1 x336 +1 x337 +1 x338 +1 x339 +1 x340 +1 x341 +1 x342 +1 x343 +1 x344 +1 x345 +1 x346 +1 x347 +1 x348 +1 x349 +1 x350 +1 x351 +1 x352 +1 x353 +1 x354 +1 x355 +1 x356 +1 x357 +1 x358 +1 x359 +1 x360 +1 x361 +1 x362 +1 x363 +1 x364 +1 x365 +1 x366 +1 x367 +1 x368 +1 x369 +1 x370 +1 x371 +1 x372 +1 x373 +1 x374 +1 x375 +1 x376 +1 x377 +1 x378 +1 x379 +1 x380 +1 x381 +1 x382 +1 x383 +1 x384 +1 x2305 +1 x2306 +1 x2307 +1 x2308 +1 x2309 +1 x2310 +1 x2311 +1 x2312 +1 x2313 +1 x2314 +1 x2315 +1 x2316 +1 x2317 +1 x2318 +1 x2319 +1 x2320 +1 x2321 +1 x2322 +1 x2323 +1 x2324 +1 x2325 +1 x2326 +1 x2327 +1 x2328 +1 x2329 +1 x2330 +1 x2331 +1 x2332 +1 x2333 +1 x2334 +1 x2335 +1 x2336 +1 x2337 +1 x2338 +1 x2339 +1 x2340 +1 x2341 +1 x2342 +1 x2343 +1 x2344 +1 x2345 +1 x2346 +1 x2347 +1 x2348 +1 x2349 +1 x2350 +1 x2351 +1 x2352 +1 x2353 +1 x2354 +1 x2355 +1 x2356 +1 x2357 +1 x2358 +1 x2359 +1 x2360 +1 x2361 +1 x2362 +1 x2363 +1 x2364 +1 x2365 +1 x2366 +1 x2367 +1 x2368 +1 x2369 +1 x2370 +1 x2371 +1 x2372 +1 x2373 +1 x2374 +1 x2375 +1 x2376 +1 x2377 +1 x2378 +1 x2379 +1 x2380 +1 x2381 +1 x2382 +1 x2383 +1 x2384 +1 x2385 +1 x2386 +1 x2387 +1 x2388 +1 x2389 +1 x2390 +1 x2391 +1 x2392 +1 x2393 +1 x2394 +1 x2395 +1 x2396 +1 x2397 +1 x2398 +1 x2399 +1 x2400 +1 x2401 +1 x2402 +1 x2403 +1 x2404 +1 x2405 +1 x2406 +1 x2407 +1 x2408 +1 x2409 +1 x2410 +1 x2411 +1 x2412 +1 x2413 +1 x2414 +1 x2415 +1 x2416 +1 x2417 +1 x2418 +1 x2419 +1 x2420 +1 x2421 +1 x2422 +1 x2423 +1 x2424 +1 x2425 +1 x2426 +1 x2427 +1 x2428 +1 x2429 +1 x2430 +1 x2431 +1 x2432 +1 x3841 +1 x3842 +1 x3843 +1 x3844 +1 x3845 +1 x3846 +1 x3847 +1 x3848 +1 x3849 +1 x3850 +1 x3851 +1 x3852 +1 x3853 +1 x3854 +1 x3855 +1 x3856 +1 x3857 +1 x3858 +1 x3859 +1 x3860 +1 x3861 +1 x3862 +1 x3863 +1 x3864 +1 x3865 +1 x3866 +1 x3867 +1 x3868 +1 x3869 +1 x3870 +1 x3871 +1 x3872 +1 x3873 +1 x3874 +1 x3875 +1 x3876 +1 x3877 +1 x3878 +1 x3879 +1 x3880 +1 x3881 +1 x3882 +1 x3883 +1 x3884 +1 x3885 +1 x3886 +1 x3887 +1 x3888 +1 x3889 +1 x3890 +1 x3891 +1 x3892 +1 x3893 +1 x3894 +1 x3895 +1 x3896 +1 x3897 +1 x3898 +1 x3899 +1 x3900 +1 x3901 +1 x3902 +1 x3903 +1 x3904 +1 x3905 +1 x3906 +1 x3907 +1 x3908 +1 x3909 +1 x3910 +1 x3911 +1 x3912 +1 x3913 +1 x3914 +1 x3915 +1 x3916 +1 x3917 +1 x3918 +1 x3919 +1 x3920 +1 x3921 +1 x3922 +1 x3923 +1 x3924 +1 x3925 +1 x3926 +1 x3927 +1 x3928 +1 x3929 +1 x3930 +1 x3931 +1 x3932 +1 x3933 +1 x3934 +1 x3935 +1 x3936 +1 x3937 +1 x3938 +1 x3939 +1 x3940 +1 x3941 +1 x3942 +1 x3943 +1 x3944 +1 x3945 +1 x3946 +1 x3947 +1 x3948 +1 x3949 +1 x3950 +1 x3951 +1 x3952 +1 x3953 +1 x3954 +1 x3955 +1 x3956 +1 x3957 +1 x3958 +1 x3959 +1 x3960 +1 x3961 +1 x3962 +1 x3963 +1 x3964 +1 x3965 +1 x3966 +1 x3967 +1 x3968 +1 x6273 +1 x6274 +1 x6275 +1 x6276 +1 x6277 +1 x6278 +1 x6279 +1 x6280 +1 x6281 +1 x6282 +1 x6283 +1 x6284 +1 x6285 +1 x6286 +1 x6287 +1 x6288 +1 x6289 +1 x6290 +1 x6291 +1 x6292 +1 x6293 +1 x6294 +1 x6295 +1 x6296 +1 x6297 +1 x6298 +1 x6299 +1 x6300 +1 x6301 +1 x6302 +1 x6303 +1 x6304 +1 x6305 +1 x6306 +1 x6307 +1 x6308 +1 x6309 +1 x6310 +1 x6311 +1 x6312 +1 x6313 +1 x6314 +1 x6315 +1 x6316 +1 x6317 +1 x6318 +1 x6319 +1 x6320 +1 x6321 +1 x6322 +1 x6323 +1 x6324 +1 x6325 +1 x6326 +1 x6327 +1 x6328 +1 x6329 +1 x6330 +1 x6331 +1 x6332 +1 x6333 +1 x6334 +1 x6335 +1 x6336 +1 x6337 +1 x6338 +1 x6339 +1 x6340 +1 x6341 +1 x6342 +1 x6343 +1 x6344 +1 x6345 +1 x6346 +1 x6347 +1 x6348 +1 x6349 +1 x6350 +1 x6351 +1 x6352 +1 x6353 +1 x6354 +1 x6355 +1 x6356 +1 x6357 +1 x6358 +1 x6359 +1 x6360 +1 x6361 +1 x6362 +1 x6363 +1 x6364 +1 x6365 +1 x6366 +1 x6367 +1 x6368 +1 x6369 +1 x6370 +1 x6371 +1 x6372 +1 x6373 +1 x6374 +1 x6375 +1 x6376 +1 x6377 +1 x6378 +1 x6379 +1 x6380 +1 x6381 +1 x6382 +1 x6383 +1 x6384 +1 x6385 +1 x6386 +1 x6387 +1 x6388 +1 x6389 +1 x6390 +1 x6391 +1 x6392 +1 x6393 +1 x6394 +1 x6395 +1 x6396 +1 x6397 +1 x6398 +1 x6399 +1 x6400 +1 x8193 +1 x8194 +1 x8195 +1 x8196 +1 x8197 +1 x8198 +1 x8199 +1 x8200 +1 x8201 +1 x8202 +1 x8203 +1 x8204 +1 x8205 +1 x8206 +1 x8207 +1 x8208 +1 x8209 +1 x8210 +1 x8211 +1 x8212 +1 x8213 +1 x8214 +1 x8215 +1 x8216 +1 x8217 +1 x8218 +1 x8219 +1 x8220 +1 x8221 +1 x8222 +1 x8223 +1 x8224 +1 x8225 +1 x8226 +1 x8227 +1 x8228 +1 x8229 +1 x8230 +1 x8231 +1 x8232 +1 x8233 +1 x8234 +1 x8235 +1 x8236 +1 x8237 +1 x8238 +1 x8239 +1 x8240 +1 x8241 +1 x8242 +1 x8243 +1 x8244 +1 x8245 +1 x8246 +1 x8247 +1 x8248 +1 x8249 +1 x8250 +1 x8251 +1 x8252 +1 x8253 +1 x8254 +1 x8255 +1 x8256 +1 x8257 +1 x8258 +1 x8259 +1 x8260 +1 x8261 +1 x8262 +1 x8263 +1 x8264 +1 x8265 +1 x8266 +1 x8267 +1 x8268 +1 x8269 +1 x8270 +1 x8271 +1 x8272 +1 x8273 +1 x8274 +1 x8275 +1 x8276 +1 x8277 +1 x8278 +1 x8279 +1 x8280 +1 x8281 +1 x8282 +1 x8283 +1 x8284 +1 x8285 +1 x8286 +1 x8287 +1 x8288 +1 x8289 +1 x8290 +1 x8291 +1 x8292 +1 x8293 +1 x8294 +1 x8295 +1 x8296 +1 x8297 +1 x8298 +1 x8299 +1 x8300 +1 x8301 +1 x8302 +1 x8303 +1 x8304 +1 x8305 +1 x8306 +1 x8307 +1 x8308 +1 x8309 +1 x8310 +1 x8311 +1 x8312 +1 x8313 +1 x8314 +1 x8315 +1 x8316 +1 x8317 +1 x8318 +1 x8319 +1 x8320 +1 x12289 +1 x12290 +1 x12291 +1 x12292 +1 x12293 +1 x12294 +1 x12295 +1 x12296 +1 x12297 +1 x12298 +1 x12299 +1 x12300 +1 x12301 +1 x12302 +1 x12303 +1 x12304 +1 x12305 +1 x12306 +1 x12307 +1 x12308 +1 x12309 +1 x12310 +1 x12311 +1 x12312 +1 x12313 +1 x12314 +1 x12315 +1 x12316 +1 x12317 +1 x12318 +1 x12319 +1 x12320 +1 x12321 +1 x12322 +1 x12323 +1 x12324 +1 x12325 +1 x12326 +1 x12327 +1 x12328 +1 x12329 +1 x12330 +1 x12331 +1 x12332 +1 x12333 +1 x12334 +1 x12335 +1 x12336 +1 x12337 +1 x12338 +1 x12339 +1 x12340 +1 x12341 +1 x12342 +1 x12343 +1 x12344 +1 x12345 +1 x12346 +1 x12347 +1 x12348 +1 x12349 +1 x12350 +1 x12351 +1 x12352 +1 x12353 +1 x12354 +1 x12355 +1 x12356 +1 x12357 +1 x12358 +1 x12359 +1 x12360 +1 x12361 +1 x12362 +1 x12363 +1 x12364 +1 x12365 +1 x12366 +1 x12367 +1 x12368 +1 x12369 +1 x12370 +1 x12371 +1 x12372 +1 x12373 +1 x12374 +1 x12375 +1 x12376 +1 x12377 +1 x12378 +1 x12379 +1 x12380 +1 x12381 +1 x12382 +1 x12383 +1 x12384 +1 x12385 +1 x12386 +1 x12387 +1 x12388 +1 x12389 +1 x12390 +1 x12391 +1 x12392 +1 x12393 +1 x12394 +1 x12395 +1 x12396 +1 x12397 +1 x12398 +1 x12399 +1 x12400 +1 x12401 +1 x12402 +1 x12403 +1 x12404 +1 x12405 +1 x12406 +1 x12407 +1 x12408 +1 x12409 +1 x12410 +1 x12411 +1 x12412 +1 x12413 +1 x12414 +1 x12415 +1 x12416 +1 x12417 +1 x12418 +1 x12419 +1 x12420 +1 x12421 +1 x12422 +1 x12423 +1 x12424 +1 x12425 +1 x12426 +1 x12427 +1 x12428 +1 x12429 +1 x12430 +1 x12431 +1 x12432 +1 x12433 +1 x12434 +1 x12435 +1 x12436 +1 x12437 +1 x12438 +1 x12439 +1 x12440 +1 x12441 +1 x12442 +1 x12443 +1 x12444 +1 x12445 +1 x12446 +1 x12447 +1 x12448 +1 x12449 +1 x12450 +1 x12451 +1 x12452 +1 x12453 +1 x12454 +1 x12455 +1 x12456 +1 x12457 +1 x12458 +1 x12459 +1 x12460 +1 x12461 +1 x12462 +1 x12463 +1 x12464 +1 x12465 +1 x12466 +1 x12467 +1 x12468 +1 x12469 +1 x12470 +1 x12471 +1 x12472 +1 x12473 +1 x12474 +1 x12475 +1 x12476 +1 x12477 +1 x12478 +1 x12479 +1 x12480 +1 x12481 +1 x12482 +1 x12483 +1 x12484 +1 x12485 +1 x12486 +1 x12487 +1 x12488 +1 x12489 +1 x12490 +1 x12491 +1 x12492 +1 x12493 +1 x12494 +1 x12495 +1 x12496 +1 x12497 +1 x12498 +1 x12499 +1 x12500 +1 x12501 +1 x12502 +1 x12503 +1 x12504 +1 x12505 +1 x12506 +1 x12507 +1 x12508 +1 x12509 +1 x12510 +1 x12511 +1 x12512 +1 x12513 +1 x12514 +1 x12515 +1 x12516 +1 x12517 +1 x12518 +1 x12519 +1 x12520 +1 x12521 +1 x12522 +1 x12523 +1 x12524 +1 x12525 +1 x12526 +1 x12527 +1 x12528 +1 x12529 +1 x12530 +1 x12531 +1 x12532 +1 x12533 +1 x12534 +1 x12535 +1 x12536 +1 x12537 +1 x12538 +1 x12539 +1 x12540 +1 x12541 +1 x12542 +1 x12543 +1 x12544 = 0 ;+-2 x12802 +1 x1 +1 x2 +1 x3 +1 x4 +1 x5 +1 x6 +1 x7 +1 x8 +1 x9 +1 x10 +1 x11 +1 x12 +1 x13 +1 x14 +1 x15 +1 x16 +1 x17 +1 x18 +1 x19 +1 x20 +1 x21 +1 x22 +1 x23 +1 x24 +1 x25 +1 x26 +1 x27 +1 x28 +1 x29 +1 x30 +1 x31 +1 x32 +1 x33 +1 x34 +1 x35 +1 x36 +1 x37 +1 x38 +1 x39 +1 x40 +1 x41 +1 x42 +1 x43 +1 x44 +1 x45 +1 x46 +1 x47 +1 x48 +1 x49 +1 x50 +1 x51 +1 x52 +1 x53 +1 x54 +1 x55 +1 x56 +1 x57 +1 x58 +1 x59 +1 x60 +1 x61 +1 x62 +1 x63 +1 x64 +1 x65 +1 x66 +1 x67 +1 x68 +1 x69 +1 x70 +1 x71 +1 x72 +1 x73 +1 x74 +1 x75 +1 x76 +1 x77 +1 x78 +1 x79 +1 x80 +1 x81 +1 x82 +1 x83 +1 x84 +1 x85 +1 x86 +1 x87 +1 x88 +1 x89 +1 x90 +1 x91 +1 x92 +1 x93 +1 x94 +1 x95 +1 x96 +1 x97 +1 x98 +1 x99 +1 x100 +1 x101 +1 x102 +1 x103 +1 x104 +1 x105 +1 x106 +1 x107 +1 x108 +1 x109 +1 x110 +1 x111 +1 x112 +1 x113 +1 x114 +1 x115 +1 x116 +1 x117 +1 x118 +1 x119 +1 x120 +1 x121 +1 x122 +1 x123 +1 x124 +1 x125 +1 x126 +1 x127 +1 x128 +1 x385 +1 x386 +1 x387 +1 x388 +1 x389 +1 x390 +1 x391 +1 x392 +1 x393 +1 x394 +1 x395 +1 x396 +1 x397 +1 x398 +1 x399 +1 x400 +1 x401 +1 x402 +1 x403 +1 x404 +1 x405 +1 x406 +1 x407 +1 x408 +1 x409 +1 x410 +1 x411 +1 x412 +1 x413 +1 x414 +1 x415 +1 x416 +1 x417 +1 x418 +1 x419 +1 x420 +1 x421 +1 x422 +1 x423 +1 x424 +1 x425 +1 x426 +1 x427 +1 x428 +1 x429 +1 x430 +1 x431 +1 x432 +1 x433 +1 x434 +1 x435 +1 x436 +1 x437 +1 x438 +1 x439 +1 x440 +1 x441 +1 x442 +1 x443 +1 x444 +1 x445 +1 x446 +1 x447 +1 x448 +1 x449 +1 x450 +1 x451 +1 x452 +1 x453 +1 x454 +1 x455 +1 x456 +1 x457 +1 x458 +1 x459 +1 x460 +1 x461 +1 x462 +1 x463 +1 x464 +1 x465 +1 x466 +1 x467 +1 x468 +1 x469 +1 x470 +1 x471 +1 x472 +1 x473 +1 x474 +1 x475 +1 x476 +1 x477 +1 x478 +1 x479 +1 x480 +1 x481 +1 x482 +1 x483 +1 x484 +1 x485 +1 x486 +1 x487 +1 x488 +1 x489 +1 x490 +1 x491 +1 x492 +1 x493 +1 x494 +1 x495 +1 x496 +1 x497 +1 x498 +1 x499 +1 x500 +1 x501 +1 x502 +1 x503 +1 x504 +1 x505 +1 x506 +1 x507 +1 x508 +1 x509 +1 x510 +1 x511 +1 x512 +1 x1153 +1 x1154 +1 x1155 +1 x1156 +1 x1157 +1 x1158 +1 x1159 +1 x1160 +1 x1161 +1 x1162 +1 x1163 +1 x1164 +1 x1165 +1 x1166 +1 x1167 +1 x1168 +1 x1169 +1 x1170 +1 x1171 +1 x1172 +1 x1173 +1 x1174 +1 x1175 +1 x1176 +1 x1177 +1 x1178 +1 x1179 +1 x1180 +1 x1181 +1 x1182 +1 x1183 +1 x1184 +1 x1185 +1 x1186 +1 x1187 +1 x1188 +1 x1189 +1 x1190 +1 x1191 +1 x1192 +1 x1193 +1 x1194 +1 x1195 +1 x1196 +1 x1197 +1 x1198 +1 x1199 +1 x1200 +1 x1201 +1 x1202 +1 x1203 +1 x1204 +1 x1205 +1 x1206 +1 x1207 +1 x1208 +1 x1209 +1 x1210 +1 x1211 +1 x1212 +1 x1213 +1 x1214 +1 x1215 +1 x1216 +1 x1217 +1 x1218 +1 x1219 +1 x1220 +1 x1221 +1 x1222 +1 x1223 +1 x1224 +1 x1225 +1 x1226 +1 x1227 +1 x1228 +1 x1229 +1 x1230 +1 x1231 +1 x1232 +1 x1233 +1 x1234 +1 x1235 +1 x1236 +1 x1237 +1 x1238 +1 x1239 +1 x1240 +1 x1241 +1 x1242 +1 x1243 +1 x1244 +1 x1245 +1 x1246 +1 x1247 +1 x1248 +1 x1249 +1 x1250 +1 x1251 +1 x1252 +1 x1253 +1 x1254 +1 x1255 +1 x1256 +1 x1257 +1 x1258 +1 x1259 +1 x1260 +1 x1261 +1 x1262 +1 x1263 +1 x1264 +1 x1265 +1 x1266 +1 x1267 +1 x1268 +1 x1269 +1 x1270 +1 x1271 +1 x1272 +1 x1273 +1 x1274 +1 x1275 +1 x1276 +1 x1277 +1 x1278 +1 x1279 +1 x1280 +1 x1793 +1 x1794 +1 x1795 +1 x1796 +1 x1797 +1 x1798 +1 x1799 +1 x1800 +1 x1801 +1 x1802 +1 x1803 +1 x1804 +1 x1805 +1 x1806 +1 x1807 +1 x1808 +1 x1809 +1 x1810 +1 x1811 +1 x1812 +1 x1813 +1 x1814 +1 x1815 +1 x1816 +1 x1817 +1 x1818 +1 x1819 +1 x1820 +1 x1821 +1 x1822 +1 x1823 +1 x1824 +1 x1825 +1 x1826 +1 x1827 +1 x1828 +1 x1829 +1 x1830 +1 x1831 +1 x1832 +1 x1833 +1 x1834 +1 x1835 +1 x1836 +1 x1837 +1 x1838 +1 x1839 +1 x1840 +1 x1841 +1 x1842 +1 x1843 +1 x1844 +1 x1845 +1 x1846 +1 x1847 +1 x1848 +1 x1849 +1 x1850 +1 x1851 +1 x1852 +1 x1853 +1 x1854 +1 x1855 +1 x1856 +1 x1857 +1 x1858 +1 x1859 +1 x1860 +1 x1861 +1 x1862 +1 x1863 +1 x1864 +1 x1865 +1 x1866 +1 x1867 +1 x1868 +1 x1869 +1 x1870 +1 x1871 +1 x1872 +1 x1873 +1 x1874 +1 x1875 +1 x1876 +1 x1877 +1 x1878 +1 x1879 +1 x1880 +1 x1881 +1 x1882 +1 x1883 +1 x1884 +1 x1885 +1 x1886 +1 x1887 +1 x1888 +1 x1889 +1 x1890 +1 x1891 +1 x1892 +1 x1893 +1 x1894 +1 x1895 +1 x1896 +1 x1897 +1 x1898 +1 x1899 +1 x1900 +1 x1901 +1 x1902 +1 x1903 +1 x1904 +1 x1905 +1 x1906 +1 x1907 +1 x1908 +1 x1909 +1 x1910 +1 x1911 +1 x1912 +1 x1913 +1 x1914 +1 x1915 +1 x1916 +1 x1917 +1 x1918 +1 x1919 +1 x1920 +1 x8577 +1 x8578 +1 x8579 +1 x8580 +1 x8581 +1 x8582 +1 x8583 +1 x8584 +1 x8585 +1 x8586 +1 x8587 +1 x8588 +1 x8589 +1 x8590 +1 x8591 +1 x8592 +1 x8593 +1 x8594 +1 x8595 +1 x8596 +1 x8597 +1 x8598 +1 x8599 +1 x8600 +1 x8601 +1 x8602 +1 x8603 +1 x8604 +1 x8605 +1 x8606 +1 x8607 +1 x8608 +1 x8609 +1 x8610 +1 x8611 +1 x8612 +1 x8613 +1 x8614 +1 x8615 +1 x8616 +1 x8617 +1 x8618 +1 x8619 +1 x8620 +1 x8621 +1 x8622 +1 x8623 +1 x8624 +1 x8625 +1 x8626 +1 x8627 +1 x8628 +1 x8629 +1 x8630 +1 x8631 +1 x8632 +1 x8633 +1 x8634 +1 x8635 +1 x8636 +1 x8637 +1 x8638 +1 x8639 +1 x8640 +1 x8641 +1 x8642 +1 x8643 +1 x8644 +1 x8645 +1 x8646 +1 x8647 +1 x8648 +1 x8649 +1 x8650 +1 x8651 +1 x8652 +1 x8653 +1 x8654 +1 x8655 +1 x8656 +1 x8657 +1 x8658 +1 x8659 +1 x8660 +1 x8661 +1 x8662 +1 x8663 +1 x8664 +1 x8665 +1 x8666 +1 x8667 +1 x8668 +1 x8669 +1 x8670 +1 x8671 +1 x8672 +1 x8673 +1 x8674 +1 x8675 +1 x8676 +1 x8677 +1 x8678 +1 x8679 +1 x8680 +1 x8681 +1 x8682 +1 x8683 +1 x8684 +1 x8685 +1 x8686 +1 x8687 +1 x8688 +1 x8689 +1 x8690 +1 x8691 +1 x8692 +1 x8693 +1 x8694 +1 x8695 +1 x8696 +1 x8697 +1 x8698 +1 x8699 +1 x8700 +1 x8701 +1 x8702 +1 x8703 +1 x8704 +1 x12545 +1 x12546 +1 x12547 +1 x12548 +1 x12549 +1 x12550 +1 x12551 +1 x12552 +1 x12553 +1 x12554 +1 x12555 +1 x12556 +1 x12557 +1 x12558 +1 x12559 +1 x12560 +1 x12561 +1 x12562 +1 x12563 +1 x12564 +1 x12565 +1 x12566 +1 x12567 +1 x12568 +1 x12569 +1 x12570 +1 x12571 +1 x12572 +1 x12573 +1 x12574 +1 x12575 +1 x12576 +1 x12577 +1 x12578 +1 x12579 +1 x12580 +1 x12581 +1 x12582 +1 x12583 +1 x12584 +1 x12585 +1 x12586 +1 x12587 +1 x12588 +1 x12589 +1 x12590 +1 x12591 +1 x12592 +1 x12593 +1 x12594 +1 x12595 +1 x12596 +1 x12597 +1 x12598 +1 x12599 +1 x12600 +1 x12601 +1 x12602 +1 x12603 +1 x12604 +1 x12605 +1 x12606 +1 x12607 +1 x12608 +1 x12609 +1 x12610 +1 x12611 +1 x12612 +1 x12613 +1 x12614 +1 x12615 +1 x12616 +1 x12617 +1 x12618 +1 x12619 +1 x12620 +1 x12621 +1 x12622 +1 x12623 +1 x12624 +1 x12625 +1 x12626 +1 x12627 +1 x12628 +1 x12629 +1 x12630 +1 x12631 +1 x12632 +1 x12633 +1 x12634 +1 x12635 +1 x12636 +1 x12637 +1 x12638 +1 x12639 +1 x12640 +1 x12641 +1 x12642 +1 x12643 +1 x12644 +1 x12645 +1 x12646 +1 x12647 +1 x12648 +1 x12649 +1 x12650 +1 x12651 +1 x12652 +1 x12653 +1 x12654 +1 x12655 +1 x12656 +1 x12657 +1 x12658 +1 x12659 +1 x12660 +1 x12661 +1 x12662 +1 x12663 +1 x12664 +1 x12665 +1 x12666 +1 x12667 +1 x12668 +1 x12669 +1 x12670 +1 x12671 +1 x12672 +1 x12673 +1 x12674 +1 x12675 +1 x12676 +1 x12677 +1 x12678 +1 x12679 +1 x12680 +1 x12681 +1 x12682 +1 x12683 +1 x12684 +1 x12685 +1 x12686 +1 x12687 +1 x12688 +1 x12689 +1 x12690 +1 x12691 +1 x12692 +1 x12693 +1 x12694 +1 x12695 +1 x12696 +1 x12697 +1 x12698 +1 x12699 +1 x12700 +1 x12701 +1 x12702 +1 x12703 +1 x12704 +1 x12705 +1 x12706 +1 x12707 +1 x12708 +1 x12709 +1 x12710 +1 x12711 +1 x12712 +1 x12713 +1 x12714 +1 x12715 +1 x12716 +1 x12717 +1 x12718 +1 x12719 +1 x12720 +1 x12721 +1 x12722 +1 x12723 +1 x12724 +1 x12725 +1 x12726 +1 x12727 +1 x12728 +1 x12729 +1 x12730 +1 x12731 +1 x12732 +1 x12733 +1 x12734 +1 x12735 +1 x12736 +1 x12737 +1 x12738 +1 x12739 +1 x12740 +1 x12741 +1 x12742 +1 x12743 +1 x12744 +1 x12745 +1 x12746 +1 x12747 +1 x12748 +1 x12749 +1 x12750 +1 x12751 +1 x12752 +1 x12753 +1 x12754 +1 x12755 +1 x12756 +1 x12757 +1 x12758 +1 x12759 +1 x12760 +1 x12761 +1 x12762 +1 x12763 +1 x12764 +1 x12765 +1 x12766 +1 x12767 +1 x12768 +1 x12769 +1 x12770 +1 x12771 +1 x12772 +1 x12773 +1 x12774 +1 x12775 +1 x12776 +1 x12777 +1 x12778 +1 x12779 +1 x12780 +1 x12781 +1 x12782 +1 x12783 +1 x12784 +1 x12785 +1 x12786 +1 x12787 +1 x12788 +1 x12789 +1 x12790 +1 x12791 +1 x12792 +1 x12793 +1 x12794 +1 x12795 +1 x12796 +1 x12797 +1 x12798 +1 x12799 +1 x12800 = 0 ;+-2 x12803 +1 x1 +1 x2 +1 x3 +1 x4 +1 x5 +1 x6 +1 x7 +1 x8 +1 x9 +1 x10 +1 x11 +1 x12 +1 x13 +1 x14 +1 x15 +1 x16 +1 x17 +1 x18 +1 x19 +1 x20 +1 x21 +1 x22 +1 x23 +1 x24 +1 x25 +1 x26 +1 x27 +1 x28 +1 x29 +1 x30 +1 x31 +1 x32 +1 x33 +1 x34 +1 x35 +1 x36 +1 x37 +1 x38 +1 x39 +1 x40 +1 x41 +1 x42 +1 x43 +1 x44 +1 x45 +1 x46 +1 x47 +1 x48 +1 x49 +1 x50 +1 x51 +1 x52 +1 x53 +1 x54 +1 x55 +1 x56 +1 x57 +1 x58 +1 x59 +1 x60 +1 x61 +1 x62 +1 x63 +1 x64 +1 x65 +1 x66 +1 x67 +1 x68 +1 x69 +1 x70 +1 x71 +1 x72 +1 x73 +1 x74 +1 x75 +1 x76 +1 x77 +1 x78 +1 x79 +1 x80 +1 x81 +1 x82 +1 x83 +1 x84 +1 x85 +1 x86 +1 x87 +1 x88 +1 x89 +1 x90 +1 x91 +1 x92 +1 x93 +1 x94 +1 x95 +1 x96 +1 x97 +1 x98 +1 x99 +1 x100 +1 x101 +1 x102 +1 x103 +1 x104 +1 x105 +1 x106 +1 x107 +1 x108 +1 x109 +1 x110 +1 x111 +1 x112 +1 x113 +1 x114 +1 x115 +1 x116 +1 x117 +1 x118 +1 x119 +1 x120 +1 x121 +1 x122 +1 x123 +1 x124 +1 x125 +1 x126 +1 x127 +1 x128 +1 x129 +1 x130 +1 x131 +1 x132 +1 x133 +1 x134 +1 x135 +1 x136 +1 x137 +1 x138 +1 x139 +1 x140 +1 x141 +1 x142 +1 x143 +1 x144 +1 x145 +1 x146 +1 x147 +1 x148 +1 x149 +1 x150 +1 x151 +1 x152 +1 x153 +1 x154 +1 x155 +1 x156 +1 x157 +1 x158 +1 x159 +1 x160 +1 x161 +1 x162 +1 x163 +1 x164 +1 x165 +1 x166 +1 x167 +1 x168 +1 x169 +1 x170 +1 x171 +1 x172 +1 x173 +1 x174 +1 x175 +1 x176 +1 x177 +1 x178 +1 x179 +1 x180 +1 x181 +1 x182 +1 x183 +1 x184 +1 x185 +1 x186 +1 x187 +1 x188 +1 x189 +1 x190 +1 x191 +1 x192 +1 x193 +1 x194 +1 x195 +1 x196 +1 x197 +1 x198 +1 x199 +1 x200 +1 x201 +1 x202 +1 x203 +1 x204 +1 x205 +1 x206 +1 x207 +1 x208 +1 x209 +1 x210 +1 x211 +1 x212 +1 x213 +1 x214 +1 x215 +1 x216 +1 x217 +1 x218 +1 x219 +1 x220 +1 x221 +1 x222 +1 x223 +1 x224 +1 x225 +1 x226 +1 x227 +1 x228 +1 x229 +1 x230 +1 x231 +1 x232 +1 x233 +1 x234 +1 x235 +1 x236 +1 x237 +1 x238 +1 x239 +1 x240 +1 x241 +1 x242 +1 x243 +1 x244 +1 x245 +1 x246 +1 x247 +1 x248 +1 x249 +1 x250 +1 x251 +1 x252 +1 x253 +1 x254 +1 x255 +1 x256 +1 x641 +1 x642 +1 x643 +1 x644 +1 x645 +1 x646 +1 x647 +1 x648 +1 x649 +1 x650 +1 x651 +1 x652 +1 x653 +1 x654 +1 x655 +1 x656 +1 x657 +1 x658 +1 x659 +1 x660 +1 x661 +1 x662 +1 x663 +1 x664 +1 x665 +1 x666 +1 x667 +1 x668 +1 x669 +1 x670 +1 x671 +1 x672 +1 x673 +1 x674 +1 x675 +1 x676 +1 x677 +1 x678 +1 x679 +1 x680 +1 x681 +1 x682 +1 x683 +1 x684 +1 x685 +1 x686 +1 x687 +1 x688 +1 x689 +1 x690 +1 x691 +1 x692 +1 x693 +1 x694 +1 x695 +1 x696 +1 x697 +1 x698 +1 x699 +1 x700 +1 x701 +1 x702 +1 x703 +1 x704 +1 x705 +1 x706 +1 x707 +1 x708 +1 x709 +1 x710 +1 x711 +1 x712 +1 x713 +1 x714 +1 x715 +1 x716 +1 x717 +1 x718 +1 x719 +1 x720 +1 x721 +1 x722 +1 x723 +1 x724 +1 x725 +1 x726 +1 x727 +1 x728 +1 x729 +1 x730 +1 x731 +1 x732 +1 x733 +1 x734 +1 x735 +1 x736 +1 x737 +1 x738 +1 x739 +1 x740 +1 x741 +1 x742 +1 x743 +1 x744 +1 x745 +1 x746 +1 x747 +1 x748 +1 x749 +1 x750 +1 x751 +1 x752 +1 x753 +1 x754 +1 x755 +1 x756 +1 x757 +1 x758 +1 x759 +1 x760 +1 x761 +1 x762 +1 x763 +1 x764 +1 x765 +1 x766 +1 x767 +1 x768 +1 x897 +1 x898 +1 x899 +1 x900 +1 x901 +1 x902 +1 x903 +1 x904 +1 x905 +1 x906 +1 x907 +1 x908 +1 x909 +1 x910 +1 x911 +1 x912 +1 x913 +1 x914 +1 x915 +1 x916 +1 x917 +1 x918 +1 x919 +1 x920 +1 x921 +1 x922 +1 x923 +1 x924 +1 x925 +1 x926 +1 x927 +1 x928 +1 x929 +1 x930 +1 x931 +1 x932 +1 x933 +1 x934 +1 x935 +1 x936 +1 x937 +1 x938 +1 x939 +1 x940 +1 x941 +1 x942 +1 x943 +1 x944 +1 x945 +1 x946 +1 x947 +1 x948 +1 x949 +1 x950 +1 x951 +1 x952 +1 x953 +1 x954 +1 x955 +1 x956 +1 x957 +1 x958 +1 x959 +1 x960 +1 x961 +1 x962 +1 x963 +1 x964 +1 x965 +1 x966 +1 x967 +1 x968 +1 x969 +1 x970 +1 x971 +1 x972 +1 x973 +1 x974 +1 x975 +1 x976 +1 x977 +1 x978 +1 x979 +1 x980 +1 x981 +1 x982 +1 x983 +1 x984 +1 x985 +1 x986 +1 x987 +1 x988 +1 x989 +1 x990 +1 x991 +1 x992 +1 x993 +1 x994 +1 x995 +1 x996 +1 x997 +1 x998 +1 x999 +1 x1000 +1 x1001 +1 x1002 +1 x1003 +1 x1004 +1 x1005 +1 x1006 +1 x1007 +1 x1008 +1 x1009 +1 x1010 +1 x1011 +1 x1012 +1 x1013 +1 x1014 +1 x1015 +1 x1016 +1 x1017 +1 x1018 +1 x1019 +1 x1020 +1 x1021 +1 x1022 +1 x1023 +1 x1024 +1 x1025 +1 x1026 +1 x1027 +1 x1028 +1 x1029 +1 x1030 +1 x1031 +1 x1032 +1 x1033 +1 x1034 +1 x1035 +1 x1036 +1 x1037 +1 x1038 +1 x1039 +1 x1040 +1 x1041 +1 x1042 +1 x1043 +1 x1044 +1 x1045 +1 x1046 +1 x1047 +1 x1048 +1 x1049 +1 x1050 +1 x1051 +1 x1052 +1 x1053 +1 x1054 +1 x1055 +1 x1056 +1 x1057 +1 x1058 +1 x1059 +1 x1060 +1 x1061 +1 x1062 +1 x1063 +1 x1064 +1 x1065 +1 x1066 +1 x1067 +1 x1068 +1 x1069 +1 x1070 +1 x1071 +1 x1072 +1 x1073 +1 x1074 +1 x1075 +1 x1076 +1 x1077 +1 x1078 +1 x1079 +1 x1080 +1 x1081 +1 x1082 +1 x1083 +1 x1084 +1 x1085 +1 x1086 +1 x1087 +1 x1088 +1 x1089 +1 x1090 +1 x1091 +1 x1092 +1 x1093 +1 x1094 +1 x1095 +1 x1096 +1 x1097 +1 x1098 +1 x1099 +1 x1100 +1 x1101 +1 x1102 +1 x1103 +1 x1104 +1 x1105 +1 x1106 +1 x1107 +1 x1108 +1 x1109 +1 x1110 +1 x1111 +1 x1112 +1 x1113 +1 x1114 +1 x1115 +1 x1116 +1 x1117 +1 x1118 +1 x1119 +1 x1120 +1 x1121 +1 x1122 +1 x1123 +1 x1124 +1 x1125 +1 x1126 +1 x1127 +1 x1128 +1 x1129 +1 x1130 +1 x1131 +1 x1132 +1 x1133 +1 x1134 +1 x1135 +1 x1136 +1 x1137 +1 x1138 +1 x1139 +1 x1140 +1 x1141 +1 x1142 +1 x1143 +1 x1144 +1 x1145 +1 x1146 +1 x1147 +1 x1148 +1 x1149 +1 x1150 +1 x1151 +1 x1152 +1 x2177 +1 x2178 +1 x2179 +1 x2180 +1 x2181 +1 x2182 +1 x2183 +1 x2184 +1 x2185 +1 x2186 +1 x2187 +1 x2188 +1 x2189 +1 x2190 +1 x2191 +1 x2192 +1 x2193 +1 x2194 +1 x2195 +1 x2196 +1 x2197 +1 x2198 +1 x2199 +1 x2200 +1 x2201 +1 x2202 +1 x2203 +1 x2204 +1 x2205 +1 x2206 +1 x2207 +1 x2208 +1 x2209 +1 x2210 +1 x2211 +1 x2212 +1 x2213 +1 x2214 +1 x2215 +1 x2216 +1 x2217 +1 x2218 +1 x2219 +1 x2220 +1 x2221 +1 x2222 +1 x2223 +1 x2224 +1 x2225 +1 x2226 +1 x2227 +1 x2228 +1 x2229 +1 x2230 +1 x2231 +1 x2232 +1 x2233 +1 x2234 +1 x2235 +1 x2236 +1 x2237 +1 x2238 +1 x2239 +1 x2240 +1 x2241 +1 x2242 +1 x2243 +1 x2244 +1 x2245 +1 x2246 +1 x2247 +1 x2248 +1 x2249 +1 x2250 +1 x2251 +1 x2252 +1 x2253 +1 x2254 +1 x2255 +1 x2256 +1 x2257 +1 x2258 +1 x2259 +1 x2260 +1 x2261 +1 x2262 +1 x2263 +1 x2264 +1 x2265 +1 x2266 +1 x2267 +1 x2268 +1 x2269 +1 x2270 +1 x2271 +1 x2272 +1 x2273 +1 x2274 +1 x2275 +1 x2276 +1 x2277 +1 x2278 +1 x2279 +1 x2280 +1 x2281 +1 x2282 +1 x2283 +1 x2284 +1 x2285 +1 x2286 +1 x2287 +1 x2288 +1 x2289 +1 x2290 +1 x2291 +1 x2292 +1 x2293 +1 x2294 +1 x2295 +1 x2296 +1 x2297 +1 x2298 +1 x2299 +1 x2300 +1 x2301 +1 x2302 +1 x2303 +1 x2304 +1 x4609 +1 x4610 +1 x4611 +1 x4612 +1 x4613 +1 x4614 +1 x4615 +1 x4616 +1 x4617 +1 x4618 +1 x4619 +1 x4620 +1 x4621 +1 x4622 +1 x4623 +1 x4624 +1 x4625 +1 x4626 +1 x4627 +1 x4628 +1 x4629 +1 x4630 +1 x4631 +1 x4632 +1 x4633 +1 x4634 +1 x4635 +1 x4636 +1 x4637 +1 x4638 +1 x4639 +1 x4640 +1 x4641 +1 x4642 +1 x4643 +1 x4644 +1 x4645 +1 x4646 +1 x4647 +1 x4648 +1 x4649 +1 x4650 +1 x4651 +1 x4652 +1 x4653 +1 x4654 +1 x4655 +1 x4656 +1 x4657 +1 x4658 +1 x4659 +1 x4660 +1 x4661 +1 x4662 +1 x4663 +1 x4664 +1 x4665 +1 x4666 +1 x4667 +1 x4668 +1 x4669 +1 x4670 +1 x4671 +1 x4672 +1 x4673 +1 x4674 +1 x4675 +1 x4676 +1 x4677 +1 x4678 +1 x4679 +1 x4680 +1 x4681 +1 x4682 +1 x4683 +1 x4684 +1 x4685 +1 x4686 +1 x4687 +1 x4688 +1 x4689 +1 x4690 +1 x4691 +1 x4692 +1 x4693 +1 x4694 +1 x4695 +1 x4696 +1 x4697 +1 x4698 +1 x4699 +1 x4700 +1 x4701 +1 x4702 +1 x4703 +1 x4704 +1 x4705 +1 x4706 +1 x4707 +1 x4708 +1 x4709 +1 x4710 +1 x4711 +1 x4712 +1 x4713 +1 x4714 +1 x4715 +1 x4716 +1 x4717 +1 x4718 +1 x4719 +1 x4720 +1 x4721 +1 x4722 +1 x4723 +1 x4724 +1 x4725 +1 x4726 +1 x4727 +1 x4728 +1 x4729 +1 x4730 +1 x4731 +1 x4732 +1 x4733 +1 x4734 +1 x4735 +1 x4736 +1 x4993 +1 x4994 +1 x4995 +1 x4996 +1 x4997 +1 x4998 +1 x4999 +1 x5000 +1 x5001 +1 x5002 +1 x5003 +1 x5004 +1 x5005 +1 x5006 +1 x5007 +1 x5008 +1 x5009 +1 x5010 +1 x5011 +1 x5012 +1 x5013 +1 x5014 +1 x5015 +1 x5016 +1 x5017 +1 x5018 +1 x5019 +1 x5020 +1 x5021 +1 x5022 +1 x5023 +1 x5024 +1 x5025 +1 x5026 +1 x5027 +1 x5028 +1 x5029 +1 x5030 +1 x5031 +1 x5032 +1 x5033 +1 x5034 +1 x5035 +1 x5036 +1 x5037 +1 x5038 +1 x5039 +1 x5040 +1 x5041 +1 x5042 +1 x5043 +1 x5044 +1 x5045 +1 x5046 +1 x5047 +1 x5048 +1 x5049 +1 x5050 +1 x5051 +1 x5052 +1 x5053 +1 x5054 +1 x5055 +1 x5056 +1 x5057 +1 x5058 +1 x5059 +1 x5060 +1 x5061 +1 x5062 +1 x5063 +1 x5064 +1 x5065 +1 x5066 +1 x5067 +1 x5068 +1 x5069 +1 x5070 +1 x5071 +1 x5072 +1 x5073 +1 x5074 +1 x5075 +1 x5076 +1 x5077 +1 x5078 +1 x5079 +1 x5080 +1 x5081 +1 x5082 +1 x5083 +1 x5084 +1 x5085 +1 x5086 +1 x5087 +1 x5088 +1 x5089 +1 x5090 +1 x5091 +1 x5092 +1 x5093 +1 x5094 +1 x5095 +1 x5096 +1 x5097 +1 x5098 +1 x5099 +1 x5100 +1 x5101 +1 x5102 +1 x5103 +1 x5104 +1 x5105 +1 x5106 +1 x5107 +1 x5108 +1 x5109 +1 x5110 +1 x5111 +1 x5112 +1 x5113 +1 x5114 +1 x5115 +1 x5116 +1 x5117 +1 x5118 +1 x5119 +1 x5120 +1 x5121 +1 x5122 +1 x5123 +1 x5124 +1 x5125 +1 x5126 +1 x5127 +1 x5128 +1 x5129 +1 x5130 +1 x5131 +1 x5132 +1 x5133 +1 x5134 +1 x5135 +1 x5136 +1 x5137 +1 x5138 +1 x5139 +1 x5140 +1 x5141 +1 x5142 +1 x5143 +1 x5144 +1 x5145 +1 x5146 +1 x5147 +1 x5148 +1 x5149 +1 x5150 +1 x5151 +1 x5152 +1 x5153 +1 x5154 +1 x5155 +1 x5156 +1 x5157 +1 x5158 +1 x5159 +1 x5160 +1 x5161 +1 x5162 +1 x5163 +1 x5164 +1 x5165 +1 x5166 +1 x5167 +1 x5168 +1 x5169 +1 x5170 +1 x5171 +1 x5172 +1 x5173 +1 x5174 +1 x5175 +1 x5176 +1 x5177 +1 x5178 +1 x5179 +1 x5180 +1 x5181 +1 x5182 +1 x5183 +1 x5184 +1 x5185 +1 x5186 +1 x5187 +1 x5188 +1 x5189 +1 x5190 +1 x5191 +1 x5192 +1 x5193 +1 x5194 +1 x5195 +1 x5196 +1 x5197 +1 x5198 +1 x5199 +1 x5200 +1 x5201 +1 x5202 +1 x5203 +1 x5204 +1 x5205 +1 x5206 +1 x5207 +1 x5208 +1 x5209 +1 x5210 +1 x5211 +1 x5212 +1 x5213 +1 x5214 +1 x5215 +1 x5216 +1 x5217 +1 x5218 +1 x5219 +1 x5220 +1 x5221 +1 x5222 +1 x5223 +1 x5224 +1 x5225 +1 x5226 +1 x5227 +1 x5228 +1 x5229 +1 x5230 +1 x5231 +1 x5232 +1 x5233 +1 x5234 +1 x5235 +1 x5236 +1 x5237 +1 x5238 +1 x5239 +1 x5240 +1 x5241 +1 x5242 +1 x5243 +1 x5244 +1 x5245 +1 x5246 +1 x5247 +1 x5248 = 0 ;+-2 x12804 +1 x257 +1 x258 +1 x259 +1 x260 +1 x261 +1 x262 +1 x263 +1 x264 +1 x265 +1 x266 +1 x267 +1 x268 +1 x269 +1 x270 +1 x271 +1 x272 +1 x273 +1 x274 +1 x275 +1 x276 +1 x277 +1 x278 +1 x279 +1 x280 +1 x281 +1 x282 +1 x283 +1 x284 +1 x285 +1 x286 +1 x287 +1 x288 +1 x289 +1 x290 +1 x291 +1 x292 +1 x293 +1 x294 +1 x295 +1 x296 +1 x297 +1 x298 +1 x299 +1 x300 +1 x301 +1 x302 +1 x303 +1 x304 +1 x305 +1 x306 +1 x307 +1 x308 +1 x309 +1 x310 +1 x311 +1 x312 +1 x313 +1 x314 +1 x315 +1 x316 +1 x317 +1 x318 +1 x319 +1 x320 +1 x321 +1 x322 +1 x323 +1 x324 +1 x325 +1 x326 +1 x327 +1 x328 +1 x329 +1 x330 +1 x331 +1 x332 +1 x333 +1 x334 +1 x335 +1 x336 +1 x337 +1 x338 +1 x339 +1 x340 +1 x341 +1 x342 +1 x343 +1 x344 +1 x345 +1 x346 +1 x347 +1 x348 +1 x349 +1 x350 +1 x351 +1 x352 +1 x353 +1 x354 +1 x355 +1 x356 +1 x357 +1 x358 +1 x359 +1 x360 +1 x361 +1 x362 +1 x363 +1 x364 +1 x365 +1 x366 +1 x367 +1 x368 +1 x369 +1 x370 +1 x371 +1 x372 +1 x373 +1 x374 +1 x375 +1 x376 +1 x377 +1 x378 +1 x379 +1 x380 +1 x381 +1 x382 +1 x383 +1 x384 +1 x385 +1 x386 +1 x387 +1 x388 +1 x389 +1 x390 +1 x391 +1 x392 +1 x393 +1 x394 +1 x395 +1 x396 +1 x397 +1 x398 +1 x399 +1 x400 +1 x401 +1 x402 +1 x403 +1 x404 +1 x405 +1 x406 +1 x407 +1 x408 +1 x409 +1 x410 +1 x411 +1 x412 +1 x413 +1 x414 +1 x415 +1 x416 +1 x417 +1 x418 +1 x419 +1 x420 +1 x421 +1 x422 +1 x423 +1 x424 +1 x425 +1 x426 +1 x427 +1 x428 +1 x429 +1 x430 +1 x431 +1 x432 +1 x433 +1 x434 +1 x435 +1 x436 +1 x437 +1 x438 +1 x439 +1 x440 +1 x441 +1 x442 +1 x443 +1 x444 +1 x445 +1 x446 +1 x447 +1 x448 +1 x449 +1 x450 +1 x451 +1 x452 +1 x453 +1 x454 +1 x455 +1 x456 +1 x457 +1 x458 +1 x459 +1 x460 +1 x461 +1 x462 +1 x463 +1 x464 +1 x465 +1 x466 +1 x467 +1 x468 +1 x469 +1 x470 +1 x471 +1 x472 +1 x473 +1 x474 +1 x475 +1 x476 +1 x477 +1 x478 +1 x479 +1 x480 +1 x481 +1 x482 +1 x483 +1 x484 +1 x485 +1 x486 +1 x487 +1 x488 +1 x489 +1 x490 +1 x491 +1 x492 +1 x493 +1 x494 +1 x495 +1 x496 +1 x497 +1 x498 +1 x499 +1 x500 +1 x501 +1 x502 +1 x503 +1 x504 +1 x505 +1 x506 +1 x507 +1 x508 +1 x509 +1 x510 +1 x511 +1 x512 +1 x513 +1 x514 +1 x515 +1 x516 +1 x517 +1 x518 +1 x519 +1 x520 +1 x521 +1 x522 +1 x523 +1 x524 +1 x525 +1 x526 +1 x527 +1 x528 +1 x529 +1 x530 +1 x531 +1 x532 +1 x533 +1 x534 +1 x535 +1 x536 +1 x537 +1 x538 +1 x539 +1 x540 +1 x541 +1 x542 +1 x543 +1 x544 +1 x545 +1 x546 +1 x547 +1 x548 +1 x549 +1 x550 +1 x551 +1 x552 +1 x553 +1 x554 +1 x555 +1 x556 +1 x557 +1 x558 +1 x559 +1 x560 +1 x561 +1 x562 +1 x563 +1 x564 +1 x565 +1 x566 +1 x567 +1 x568 +1 x569 +1 x570 +1 x571 +1 x572 +1 x573 +1 x574 +1 x575 +1 x576 +1 x577 +1 x578 +1 x579 +1 x580 +1 x581 +1 x582 +1 x583 +1 x584 +1 x585 +1 x586 +1 x587 +1 x588 +1 x589 +1 x590 +1 x591 +1 x592 +1 x593 +1 x594 +1 x595 +1 x596 +1 x597 +1 x598 +1 x599 +1 x600 +1 x601 +1 x602 +1 x603 +1 x604 +1 x605 +1 x606 +1 x607 +1 x608 +1 x609 +1 x610 +1 x611 +1 x612 +1 x613 +1 x614 +1 x615 +1 x616 +1 x617 +1 x618 +1 x619 +1 x620 +1 x621 +1 x622 +1 x623 +1 x624 +1 x625 +1 x626 +1 x627 +1 x628 +1 x629 +1 x630 +1 x631 +1 x632 +1 x633 +1 x634 +1 x635 +1 x636 +1 x637 +1 x638 +1 x639 +1 x640 +1 x769 +1 x770 +1 x771 +1 x772 +1 x773 +1 x774 +1 x775 +1 x776 +1 x777 +1 x778 +1 x779 +1 x780 +1 x781 +1 x782 +1 x783 +1 x784 +1 x785 +1 x786 +1 x787 +1 x788 +1 x789 +1 x790 +1 x791 +1 x792 +1 x793 +1 x794 +1 x795 +1 x796 +1 x797 +1 x798 +1 x799 +1 x800 +1 x801 +1 x802 +1 x803 +1 x804 +1 x805 +1 x806 +1 x807 +1 x808 +1 x809 +1 x810 +1 x811 +1 x812 +1 x813 +1 x814 +1 x815 +1 x816 +1 x817 +1 x818 +1 x819 +1 x820 +1 x821 +1 x822 +1 x823 +1 x824 +1 x825 +1 x826 +1 x827 +1 x828 +1 x829 +1 x830 +1 x831 +1 x832 +1 x833 +1 x834 +1 x835 +1 x836 +1 x837 +1 x838 +1 x839 +1 x840 +1 x841 +1 x842 +1 x843 +1 x844 +1 x845 +1 x846 +1 x847 +1 x848 +1 x849 +1 x850 +1 x851 +1 x852 +1 x853 +1 x854 +1 x855 +1 x856 +1 x857 +1 x858 +1 x859 +1 x860 +1 x861 +1 x862 +1 x863 +1 x864 +1 x865 +1 x866 +1 x867 +1 x868 +1 x869 +1 x870 +1 x871 +1 x872 +1 x873 +1 x874 +1 x875 +1 x876 +1 x877 +1 x878 +1 x879 +1 x880 +1 x881 +1 x882 +1 x883 +1 x884 +1 x885 +1 x886 +1 x887 +1 x888 +1 x889 +1 x890 +1 x891 +1 x892 +1 x893 +1 x894 +1 x895 +1 x896 +1 x1281 +1 x1282 +1 x1283 +1 x1284 +1 x1285 +1 x1286 +1 x1287 +1 x1288 +1 x1289 +1 x1290 +1 x1291 +1 x1292 +1 x1293 +1 x1294 +1 x1295 +1 x1296 +1 x1297 +1 x1298 +1 x1299 +1 x1300 +1 x1301 +1 x1302 +1 x1303 +1 x1304 +1 x1305 +1 x1306 +1 x1307 +1 x1308 +1 x1309 +1 x1310 +1 x1311 +1 x1312 +1 x1313 +1 x1314 +1 x1315 +1 x1316 +1 x1317 +1 x1318 +1 x1319 +1 x1320 +1 x1321 +1 x1322 +1 x1323 +1 x1324 +1 x1325 +1 x1326 +1 x1327 +1 x1328 +1 x1329 +1 x1330 +1 x1331 +1 x1332 +1 x1333 +1 x1334 +1 x1335 +1 x1336 +1 x1337 +1 x1338 +1 x1339 +1 x1340 +1 x1341 +1 x1342 +1 x1343 +1 x1344 +1 x1345 +1 x1346 +1 x1347 +1 x1348 +1 x1349 +1 x1350 +1 x1351 +1 x1352 +1 x1353 +1 x1354 +1 x1355 +1 x1356 +1 x1357 +1 x1358 +1 x1359 +1 x1360 +1 x1361 +1 x1362 +1 x1363 +1 x1364 +1 x1365 +1 x1366 +1 x1367 +1 x1368 +1 x1369 +1 x1370 +1 x1371 +1 x1372 +1 x1373 +1 x1374 +1 x1375 +1 x1376 +1 x1377 +1 x1378 +1 x1379 +1 x1380 +1 x1381 +1 x1382 +1 x1383 +1 x1384 +1 x1385 +1 x1386 +1 x1387 +1 x1388 +1 x1389 +1 x1390 +1 x1391 +1 x1392 +1 x1393 +1 x1394 +1 x1395 +1 x1396 +1 x1397 +1 x1398 +1 x1399 +1 x1400 +1 x1401 +1 x1402 +1 x1403 +1 x1404 +1 x1405 +1 x1406 +1 x1407 +1 x1408 +1 x1665 +1 x1666 +1 x1667 +1 x1668 +1 x1669 +1 x1670 +1 x1671 +1 x1672 +1 x1673 +1 x1674 +1 x1675 +1 x1676 +1 x1677 +1 x1678 +1 x1679 +1 x1680 +1 x1681 +1 x1682 +1 x1683 +1 x1684 +1 x1685 +1 x1686 +1 x1687 +1 x1688 +1 x1689 +1 x1690 +1 x1691 +1 x1692 +1 x1693 +1 x1694 +1 x1695 +1 x1696 +1 x1697 +1 x1698 +1 x1699 +1 x1700 +1 x1701 +1 x1702 +1 x1703 +1 x1704 +1 x1705 +1 x1706 +1 x1707 +1 x1708 +1 x1709 +1 x1710 +1 x1711 +1 x1712 +1 x1713 +1 x1714 +1 x1715 +1 x1716 +1 x1717 +1 x1718 +1 x1719 +1 x1720 +1 x1721 +1 x1722 +1 x1723 +1 x1724 +1 x1725 +1 x1726 +1 x1727 +1 x1728 +1 x1729 +1 x1730 +1 x1731 +1 x1732 +1 x1733 +1 x1734 +1 x1735 +1 x1736 +1 x1737 +1 x1738 +1 x1739 +1 x1740 +1 x1741 +1 x1742 +1 x1743 +1 x1744 +1 x1745 +1 x1746 +1 x1747 +1 x1748 +1 x1749 +1 x1750 +1 x1751 +1 x1752 +1 x1753 +1 x1754 +1 x1755 +1 x1756 +1 x1757 +1 x1758 +1 x1759 +1 x1760 +1 x1761 +1 x1762 +1 x1763 +1 x1764 +1 x1765 +1 x1766 +1 x1767 +1 x1768 +1 x1769 +1 x1770 +1 x1771 +1 x1772 +1 x1773 +1 x1774 +1 x1775 +1 x1776 +1 x1777 +1 x1778 +1 x1779 +1 x1780 +1 x1781 +1 x1782 +1 x1783 +1 x1784 +1 x1785 +1 x1786 +1 x1787 +1 x1788 +1 x1789 +1 x1790 +1 x1791 +1 x1792 +1 x3201 +1 x3202 +1 x3203 +1 x3204 +1 x3205 +1 x3206 +1 x3207 +1 x3208 +1 x3209 +1 x3210 +1 x3211 +1 x3212 +1 x3213 +1 x3214 +1 x3215 +1 x3216 +1 x3217 +1 x3218 +1 x3219 +1 x3220 +1 x3221 +1 x3222 +1 x3223 +1 x3224 +1 x3225 +1 x3226 +1 x3227 +1 x3228 +1 x3229 +1 x3230 +1 x3231 +1 x3232 +1 x3233 +1 x3234 +1 x3235 +1 x3236 +1 x3237 +1 x3238 +1 x3239 +1 x3240 +1 x3241 +1 x3242 +1 x3243 +1 x3244 +1 x3245 +1 x3246 +1 x3247 +1 x3248 +1 x3249 +1 x3250 +1 x3251 +1 x3252 +1 x3253 +1 x3254 +1 x3255 +1 x3256 +1 x3257 +1 x3258 +1 x3259 +1 x3260 +1 x3261 +1 x3262 +1 x3263 +1 x3264 +1 x3265 +1 x3266 +1 x3267 +1 x3268 +1 x3269 +1 x3270 +1 x3271 +1 x3272 +1 x3273 +1 x3274 +1 x3275 +1 x3276 +1 x3277 +1 x3278 +1 x3279 +1 x3280 +1 x3281 +1 x3282 +1 x3283 +1 x3284 +1 x3285 +1 x3286 +1 x3287 +1 x3288 +1 x3289 +1 x3290 +1 x3291 +1 x3292 +1 x3293 +1 x3294 +1 x3295 +1 x3296 +1 x3297 +1 x3298 +1 x3299 +1 x3300 +1 x3301 +1 x3302 +1 x3303 +1 x3304 +1 x3305 +1 x3306 +1 x3307 +1 x3308 +1 x3309 +1 x3310 +1 x3311 +1 x3312 +1 x3313 +1 x3314 +1 x3315 +1 x3316 +1 x3317 +1 x3318 +1 x3319 +1 x3320 +1 x3321 +1 x3322 +1 x3323 +1 x3324 +1 x3325 +1 x3326 +1 x3327 +1 x3328 +1 x5761 +1 x5762 +1 x5763 +1 x5764 +1 x5765 +1 x5766 +1 x5767 +1 x5768 +1 x5769 +1 x5770 +1 x5771 +1 x5772 +1 x5773 +1 x5774 +1 x5775 +1 x5776 +1 x5777 +1 x5778 +1 x5779 +1 x5780 +1 x5781 +1 x5782 +1 x5783 +1 x5784 +1 x5785 +1 x5786 +1 x5787 +1 x5788 +1 x5789 +1 x5790 +1 x5791 +1 x5792 +1 x5793 +1 x5794 +1 x5795 +1 x5796 +1 x5797 +1 x5798 +1 x5799 +1 x5800 +1 x5801 +1 x5802 +1 x5803 +1 x5804 +1 x5805 +1 x5806 +1 x5807 +1 x5808 +1 x5809 +1 x5810 +1 x5811 +1 x5812 +1 x5813 +1 x5814 +1 x5815 +1 x5816 +1 x5817 +1 x5818 +1 x5819 +1 x5820 +1 x5821 +1 x5822 +1 x5823 +1 x5824 +1 x5825 +1 x5826 +1 x5827 +1 x5828 +1 x5829 +1 x5830 +1 x5831 +1 x5832 +1 x5833 +1 x5834 +1 x5835 +1 x5836 +1 x5837 +1 x5838 +1 x5839 +1 x5840 +1 x5841 +1 x5842 +1 x5843 +1 x5844 +1 x5845 +1 x5846 +1 x5847 +1 x5848 +1 x5849 +1 x5850 +1 x5851 +1 x5852 +1 x5853 +1 x5854 +1 x5855 +1 x5856 +1 x5857 +1 x5858 +1 x5859 +1 x5860 +1 x5861 +1 x5862 +1 x5863 +1 x5864 +1 x5865 +1 x5866 +1 x5867 +1 x5868 +1 x5869 +1 x5870 +1 x5871 +1 x5872 +1 x5873 +1 x5874 +1 x5875 +1 x5876 +1 x5877 +1 x5878 +1 x5879 +1 x5880 +1 x5881 +1 x5882 +1 x5883 +1 x5884 +1 x5885 +1 x5886 +1 x5887 +1 x5888 +1 x10625 +1 x10626 +1 x10627 +1 x10628 +1 x10629 +1 x10630 +1 x10631 +1 x10632 +1 x10633 +1 x10634 +1 x10635 +1 x10636 +1 x10637 +1 x10638 +1 x10639 +1 x10640 +1 x10641 +1 x10642 +1 x10643 +1 x10644 +1 x10645 +1 x10646 +1 x10647 +1 x10648 +1 x10649 +1 x10650 +1 x10651 +1 x10652 +1 x10653 +1 x10654 +1 x10655 +1 x10656 +1 x10657 +1 x10658 +1 x10659 +1 x10660 +1 x10661 +1 x10662 +1 x10663 +1 x10664 +1 x10665 +1 x10666 +1 x10667 +1 x10668 +1 x10669 +1 x10670 +1 x10671 +1 x10672 +1 x10673 +1 x10674 +1 x10675 +1 x10676 +1 x10677 +1 x10678 +1 x10679 +1 x10680 +1 x10681 +1 x10682 +1 x10683 +1 x10684 +1 x10685 +1 x10686 +1 x10687 +1 x10688 +1 x10689 +1 x10690 +1 x10691 +1 x10692 +1 x10693 +1 x10694 +1 x10695 +1 x10696 +1 x10697 +1 x10698 +1 x10699 +1 x10700 +1 x10701 +1 x10702 +1 x10703 +1 x10704 +1 x10705 +1 x10706 +1 x10707 +1 x10708 +1 x10709 +1 x10710 +1 x10711 +1 x10712 +1 x10713 +1 x10714 +1 x10715 +1 x10716 +1 x10717 +1 x10718 +1 x10719 +1 x10720 +1 x10721 +1 x10722 +1 x10723 +1 x10724 +1 x10725 +1 x10726 +1 x10727 +1 x10728 +1 x10729 +1 x10730 +1 x10731 +1 x10732 +1 x10733 +1 x10734 +1 x10735 +1 x10736 +1 x10737 +1 x10738 +1 x10739 +1 x10740 +1 x10741 +1 x10742 +1 x10743 +1 x10744 +1 x10745 +1 x10746 +1 x10747 +1 x10748 +1 x10749 +1 x10750 +1 x10751 +1 x10752 = 0 ;+-2 x12805 +1 x513 +1 x514 +1 x515 +1 x516 +1 x517 +1 x518 +1 x519 +1 x520 +1 x521 +1 x522 +1 x523 +1 x524 +1 x525 +1 x526 +1 x527 +1 x528 +1 x529 +1 x530 +1 x531 +1 x532 +1 x533 +1 x534 +1 x535 +1 x536 +1 x537 +1 x538 +1 x539 +1 x540 +1 x541 +1 x542 +1 x543 +1 x544 +1 x545 +1 x546 +1 x547 +1 x548 +1 x549 +1 x550 +1 x551 +1 x552 +1 x553 +1 x554 +1 x555 +1 x556 +1 x557 +1 x558 +1 x559 +1 x560 +1 x561 +1 x562 +1 x563 +1 x564 +1 x565 +1 x566 +1 x567 +1 x568 +1 x569 +1 x570 +1 x571 +1 x572 +1 x573 +1 x574 +1 x575 +1 x576 +1 x577 +1 x578 +1 x579 +1 x580 +1 x581 +1 x582 +1 x583 +1 x584 +1 x585 +1 x586 +1 x587 +1 x588 +1 x589 +1 x590 +1 x591 +1 x592 +1 x593 +1 x594 +1 x595 +1 x596 +1 x597 +1 x598 +1 x599 +1 x600 +1 x601 +1 x602 +1 x603 +1 x604 +1 x605 +1 x606 +1 x607 +1 x608 +1 x609 +1 x610 +1 x611 +1 x612 +1 x613 +1 x614 +1 x615 +1 x616 +1 x617 +1 x618 +1 x619 +1 x620 +1 x621 +1 x622 +1 x623 +1 x624 +1 x625 +1 x626 +1 x627 +1 x628 +1 x629 +1 x630 +1 x631 +1 x632 +1 x633 +1 x634 +1 x635 +1 x636 +1 x637 +1 x638 +1 x639 +1 x640 +1 x641 +1 x642 +1 x643 +1 x644 +1 x645 +1 x646 +1 x647 +1 x648 +1 x649 +1 x650 +1 x651 +1 x652 +1 x653 +1 x654 +1 x655 +1 x656 +1 x657 +1 x658 +1 x659 +1 x660 +1 x661 +1 x662 +1 x663 +1 x664 +1 x665 +1 x666 +1 x667 +1 x668 +1 x669 +1 x670 +1 x671 +1 x672 +1 x673 +1 x674 +1 x675 +1 x676 +1 x677 +1 x678 +1 x679 +1 x680 +1 x681 +1 x682 +1 x683 +1 x684 +1 x685 +1 x686 +1 x687 +1 x688 +1 x689 +1 x690 +1 x691 +1 x692 +1 x693 +1 x694 +1 x695 +1 x696 +1 x697 +1 x698 +1 x699 +1 x700 +1 x701 +1 x702 +1 x703 +1 x704 +1 x705 +1 x706 +1 x707 +1 x708 +1 x709 +1 x710 +1 x711 +1 x712 +1 x713 +1 x714 +1 x715 +1 x716 +1 x717 +1 x718 +1 x719 +1 x720 +1 x721 +1 x722 +1 x723 +1 x724 +1 x725 +1 x726 +1 x727 +1 x728 +1 x729 +1 x730 +1 x731 +1 x732 +1 x733 +1 x734 +1 x735 +1 x736 +1 x737 +1 x738 +1 x739 +1 x740 +1 x741 +1 x742 +1 x743 +1 x744 +1 x745 +1 x746 +1 x747 +1 x748 +1 x749 +1 x750 +1 x751 +1 x752 +1 x753 +1 x754 +1 x755 +1 x756 +1 x757 +1 x758 +1 x759 +1 x760 +1 x761 +1 x762 +1 x763 +1 x764 +1 x765 +1 x766 +1 x767 +1 x768 +1 x1409 +1 x1410 +1 x1411 +1 x1412 +1 x1413 +1 x1414 +1 x1415 +1 x1416 +1 x1417 +1 x1418 +1 x1419 +1 x1420 +1 x1421 +1 x1422 +1 x1423 +1 x1424 +1 x1425 +1 x1426 +1 x1427 +1 x1428 +1 x1429 +1 x1430 +1 x1431 +1 x1432 +1 x1433 +1 x1434 +1 x1435 +1 x1436 +1 x1437 +1 x1438 +1 x1439 +1 x1440 +1 x1441 +1 x1442 +1 x1443 +1 x1444 +1 x1445 +1 x1446 +1 x1447 +1 x1448 +1 x1449 +1 x1450 +1 x1451 +1 x1452 +1 x1453 +1 x1454 +1 x1455 +1 x1456 +1 x1457 +1 x1458 +1 x1459 +1 x1460 +1 x1461 +1 x1462 +1 x1463 +1 x1464 +1 x1465 +1 x1466 +1 x1467 +1 x1468 +1 x1469 +1 x1470 +1 x1471 +1 x1472 +1 x1473 +1 x1474 +1 x1475 +1 x1476 +1 x1477 +1 x1478 +1 x1479 +1 x1480 +1 x1481 +1 x1482 +1 x1483 +1 x1484 +1 x1485 +1 x1486 +1 x1487 +1 x1488 +1 x1489 +1 x1490 +1 x1491 +1 x1492 +1 x1493 +1 x1494 +1 x1495 +1 x1496 +1 x1497 +1 x1498 +1 x1499 +1 x1500 +1 x1501 +1 x1502 +1 x1503 +1 x1504 +1 x1505 +1 x1506 +1 x1507 +1 x1508 +1 x1509 +1 x1510 +1 x1511 +1 x1512 +1 x1513 +1 x1514 +1 x1515 +1 x1516 +1 x1517 +1 x1518 +1 x1519 +1 x1520 +1 x1521 +1 x1522 +1 x1523 +1 x1524 +1 x1525 +1 x1526 +1 x1527 +1 x1528 +1 x1529 +1 x1530 +1 x1531 +1 x1532 +1 x1533 +1 x1534 +1 x1535 +1 x1536 +1 x2945 +1 x2946 +1 x2947 +1 x2948 +1 x2949 +1 x2950 +1 x2951 +1 x2952 +1 x2953 +1 x2954 +1 x2955 +1 x2956 +1 x2957 +1 x2958 +1 x2959 +1 x2960 +1 x2961 +1 x2962 +1 x2963 +1 x2964 +1 x2965 +1 x2966 +1 x2967 +1 x2968 +1 x2969 +1 x2970 +1 x2971 +1 x2972 +1 x2973 +1 x2974 +1 x2975 +1 x2976 +1 x2977 +1 x2978 +1 x2979 +1 x2980 +1 x2981 +1 x2982 +1 x2983 +1 x2984 +1 x2985 +1 x2986 +1 x2987 +1 x2988 +1 x2989 +1 x2990 +1 x2991 +1 x2992 +1 x2993 +1 x2994 +1 x2995 +1 x2996 +1 x2997 +1 x2998 +1 x2999 +1 x3000 +1 x3001 +1 x3002 +1 x3003 +1 x3004 +1 x3005 +1 x3006 +1 x3007 +1 x3008 +1 x3009 +1 x3010 +1 x3011 +1 x3012 +1 x3013 +1 x3014 +1 x3015 +1 x3016 +1 x3017 +1 x3018 +1 x3019 +1 x3020 +1 x3021 +1 x3022 +1 x3023 +1 x3024 +1 x3025 +1 x3026 +1 x3027 +1 x3028 +1 x3029 +1 x3030 +1 x3031 +1 x3032 +1 x3033 +1 x3034 +1 x3035 +1 x3036 +1 x3037 +1 x3038 +1 x3039 +1 x3040 +1 x3041 +1 x3042 +1 x3043 +1 x3044 +1 x3045 +1 x3046 +1 x3047 +1 x3048 +1 x3049 +1 x3050 +1 x3051 +1 x3052 +1 x3053 +1 x3054 +1 x3055 +1 x3056 +1 x3057 +1 x3058 +1 x3059 +1 x3060 +1 x3061 +1 x3062 +1 x3063 +1 x3064 +1 x3065 +1 x3066 +1 x3067 +1 x3068 +1 x3069 +1 x3070 +1 x3071 +1 x3072 +1 x3073 +1 x3074 +1 x3075 +1 x3076 +1 x3077 +1 x3078 +1 x3079 +1 x3080 +1 x3081 +1 x3082 +1 x3083 +1 x3084 +1 x3085 +1 x3086 +1 x3087 +1 x3088 +1 x3089 +1 x3090 +1 x3091 +1 x3092 +1 x3093 +1 x3094 +1 x3095 +1 x3096 +1 x3097 +1 x3098 +1 x3099 +1 x3100 +1 x3101 +1 x3102 +1 x3103 +1 x3104 +1 x3105 +1 x3106 +1 x3107 +1 x3108 +1 x3109 +1 x3110 +1 x3111 +1 x3112 +1 x3113 +1 x3114 +1 x3115 +1 x3116 +1 x3117 +1 x3118 +1 x3119 +1 x3120 +1 x3121 +1 x3122 +1 x3123 +1 x3124 +1 x3125 +1 x3126 +1 x3127 +1 x3128 +1 x3129 +1 x3130 +1 x3131 +1 x3132 +1 x3133 +1 x3134 +1 x3135 +1 x3136 +1 x3137 +1 x3138 +1 x3139 +1 x3140 +1 x3141 +1 x3142 +1 x3143 +1 x3144 +1 x3145 +1 x3146 +1 x3147 +1 x3148 +1 x3149 +1 x3150 +1 x3151 +1 x3152 +1 x3153 +1 x3154 +1 x3155 +1 x3156 +1 x3157 +1 x3158 +1 x3159 +1 x3160 +1 x3161 +1 x3162 +1 x3163 +1 x3164 +1 x3165 +1 x3166 +1 x3167 +1 x3168 +1 x3169 +1 x3170 +1 x3171 +1 x3172 +1 x3173 +1 x3174 +1 x3175 +1 x3176 +1 x3177 +1 x3178 +1 x3179 +1 x3180 +1 x3181 +1 x3182 +1 x3183 +1 x3184 +1 x3185 +1 x3186 +1 x3187 +1 x3188 +1 x3189 +1 x3190 +1 x3191 +1 x3192 +1 x3193 +1 x3194 +1 x3195 +1 x3196 +1 x3197 +1 x3198 +1 x3199 +1 x3200 +1 x4225 +1 x4226 +1 x4227 +1 x4228 +1 x4229 +1 x4230 +1 x4231 +1 x4232 +1 x4233 +1 x4234 +1 x4235 +1 x4236 +1 x4237 +1 x4238 +1 x4239 +1 x4240 +1 x4241 +1 x4242 +1 x4243 +1 x4244 +1 x4245 +1 x4246 +1 x4247 +1 x4248 +1 x4249 +1 x4250 +1 x4251 +1 x4252 +1 x4253 +1 x4254 +1 x4255 +1 x4256 +1 x4257 +1 x4258 +1 x4259 +1 x4260 +1 x4261 +1 x4262 +1 x4263 +1 x4264 +1 x4265 +1 x4266 +1 x4267 +1 x4268 +1 x4269 +1 x4270 +1 x4271 +1 x4272 +1 x4273 +1 x4274 +1 x4275 +1 x4276 +1 x4277 +1 x4278 +1 x4279 +1 x4280 +1 x4281 +1 x4282 +1 x4283 +1 x4284 +1 x4285 +1 x4286 +1 x4287 +1 x4288 +1 x4289 +1 x4290 +1 x4291 +1 x4292 +1 x4293 +1 x4294 +1 x4295 +1 x4296 +1 x4297 +1 x4298 +1 x4299 +1 x4300 +1 x4301 +1 x4302 +1 x4303 +1 x4304 +1 x4305 +1 x4306 +1 x4307 +1 x4308 +1 x4309 +1 x4310 +1 x4311 +1 x4312 +1 x4313 +1 x4314 +1 x4315 +1 x4316 +1 x4317 +1 x4318 +1 x4319 +1 x4320 +1 x4321 +1 x4322 +1 x4323 +1 x4324 +1 x4325 +1 x4326 +1 x4327 +1 x4328 +1 x4329 +1 x4330 +1 x4331 +1 x4332 +1 x4333 +1 x4334 +1 x4335 +1 x4336 +1 x4337 +1 x4338 +1 x4339 +1 x4340 +1 x4341 +1 x4342 +1 x4343 +1 x4344 +1 x4345 +1 x4346 +1 x4347 +1 x4348 +1 x4349 +1 x4350 +1 x4351 +1 x4352 +1 x5377 +1 x5378 +1 x5379 +1 x5380 +1 x5381 +1 x5382 +1 x5383 +1 x5384 +1 x5385 +1 x5386 +1 x5387 +1 x5388 +1 x5389 +1 x5390 +1 x5391 +1 x5392 +1 x5393 +1 x5394 +1 x5395 +1 x5396 +1 x5397 +1 x5398 +1 x5399 +1 x5400 +1 x5401 +1 x5402 +1 x5403 +1 x5404 +1 x5405 +1 x5406 +1 x5407 +1 x5408 +1 x5409 +1 x5410 +1 x5411 +1 x5412 +1 x5413 +1 x5414 +1 x5415 +1 x5416 +1 x5417 +1 x5418 +1 x5419 +1 x5420 +1 x5421 +1 x5422 +1 x5423 +1 x5424 +1 x5425 +1 x5426 +1 x5427 +1 x5428 +1 x5429 +1 x5430 +1 x5431 +1 x5432 +1 x5433 +1 x5434 +1 x5435 +1 x5436 +1 x5437 +1 x5438 +1 x5439 +1 x5440 +1 x5441 +1 x5442 +1 x5443 +1 x5444 +1 x5445 +1 x5446 +1 x5447 +1 x5448 +1 x5449 +1 x5450 +1 x5451 +1 x5452 +1 x5453 +1 x5454 +1 x5455 +1 x5456 +1 x5457 +1 x5458 +1 x5459 +1 x5460 +1 x5461 +1 x5462 +1 x5463 +1 x5464 +1 x5465 +1 x5466 +1 x5467 +1 x5468 +1 x5469 +1 x5470 +1 x5471 +1 x5472 +1 x5473 +1 x5474 +1 x5475 +1 x5476 +1 x5477 +1 x5478 +1 x5479 +1 x5480 +1 x5481 +1 x5482 +1 x5483 +1 x5484 +1 x5485 +1 x5486 +1 x5487 +1 x5488 +1 x5489 +1 x5490 +1 x5491 +1 x5492 +1 x5493 +1 x5494 +1 x5495 +1 x5496 +1 x5497 +1 x5498 +1 x5499 +1 x5500 +1 x5501 +1 x5502 +1 x5503 +1 x5504 +1 x7169 +1 x7170 +1 x7171 +1 x7172 +1 x7173 +1 x7174 +1 x7175 +1 x7176 +1 x7177 +1 x7178 +1 x7179 +1 x7180 +1 x7181 +1 x7182 +1 x7183 +1 x7184 +1 x7185 +1 x7186 +1 x7187 +1 x7188 +1 x7189 +1 x7190 +1 x7191 +1 x7192 +1 x7193 +1 x7194 +1 x7195 +1 x7196 +1 x7197 +1 x7198 +1 x7199 +1 x7200 +1 x7201 +1 x7202 +1 x7203 +1 x7204 +1 x7205 +1 x7206 +1 x7207 +1 x7208 +1 x7209 +1 x7210 +1 x7211 +1 x7212 +1 x7213 +1 x7214 +1 x7215 +1 x7216 +1 x7217 +1 x7218 +1 x7219 +1 x7220 +1 x7221 +1 x7222 +1 x7223 +1 x7224 +1 x7225 +1 x7226 +1 x7227 +1 x7228 +1 x7229 +1 x7230 +1 x7231 +1 x7232 +1 x7233 +1 x7234 +1 x7235 +1 x7236 +1 x7237 +1 x7238 +1 x7239 +1 x7240 +1 x7241 +1 x7242 +1 x7243 +1 x7244 +1 x7245 +1 x7246 +1 x7247 +1 x7248 +1 x7249 +1 x7250 +1 x7251 +1 x7252 +1 x7253 +1 x7254 +1 x7255 +1 x7256 +1 x7257 +1 x7258 +1 x7259 +1 x7260 +1 x7261 +1 x7262 +1 x7263 +1 x7264 +1 x7265 +1 x7266 +1 x7267 +1 x7268 +1 x7269 +1 x7270 +1 x7271 +1 x7272 +1 x7273 +1 x7274 +1 x7275 +1 x7276 +1 x7277 +1 x7278 +1 x7279 +1 x7280 +1 x7281 +1 x7282 +1 x7283 +1 x7284 +1 x7285 +1 x7286 +1 x7287 +1 x7288 +1 x7289 +1 x7290 +1 x7291 +1 x7292 +1 x7293 +1 x7294 +1 x7295 +1 x7296 +1 x7681 +1 x7682 +1 x7683 +1 x7684 +1 x7685 +1 x7686 +1 x7687 +1 x7688 +1 x7689 +1 x7690 +1 x7691 +1 x7692 +1 x7693 +1 x7694 +1 x7695 +1 x7696 +1 x7697 +1 x7698 +1 x7699 +1 x7700 +1 x7701 +1 x7702 +1 x7703 +1 x7704 +1 x7705 +1 x7706 +1 x7707 +1 x7708 +1 x7709 +1 x7710 +1 x7711 +1 x7712 +1 x7713 +1 x7714 +1 x7715 +1 x7716 +1 x7717 +1 x7718 +1 x7719 +1 x7720 +1 x7721 +1 x7722 +1 x7723 +1 x7724 +1 x7725 +1 x7726 +1 x7727 +1 x7728 +1 x7729 +1 x7730 +1 x7731 +1 x7732 +1 x7733 +1 x7734 +1 x7735 +1 x7736 +1 x7737 +1 x7738 +1 x7739 +1 x7740 +1 x7741 +1 x7742 +1 x7743 +1 x7744 +1 x7745 +1 x7746 +1 x7747 +1 x7748 +1 x7749 +1 x7750 +1 x7751 +1 x7752 +1 x7753 +1 x7754 +1 x7755 +1 x7756 +1 x7757 +1 x7758 +1 x7759 +1 x7760 +1 x7761 +1 x7762 +1 x7763 +1 x7764 +1 x7765 +1 x7766 +1 x7767 +1 x7768 +1 x7769 +1 x7770 +1 x7771 +1 x7772 +1 x7773 +1 x7774 +1 x7775 +1 x7776 +1 x7777 +1 x7778 +1 x7779 +1 x7780 +1 x7781 +1 x7782 +1 x7783 +1 x7784 +1 x7785 +1 x7786 +1 x7787 +1 x7788 +1 x7789 +1 x7790 +1 x7791 +1 x7792 +1 x7793 +1 x7794 +1 x7795 +1 x7796 +1 x7797 +1 x7798 +1 x7799 +1 x7800 +1 x7801 +1 x7802 +1 x7803 +1 x7804 +1 x7805 +1 x7806 +1 x7807 +1 x7808 = 0 ;+-2 x12806 +1 x769 +1 x770 +1 x771 +1 x772 +1 x773 +1 x774 +1 x775 +1 x776 +1 x777 +1 x778 +1 x779 +1 x780 +1 x781 +1 x782 +1 x783 +1 x784 +1 x785 +1 x786 +1 x787 +1 x788 +1 x789 +1 x790 +1 x791 +1 x792 +1 x793 +1 x794 +1 x795 +1 x796 +1 x797 +1 x798 +1 x799 +1 x800 +1 x801 +1 x802 +1 x803 +1 x804 +1 x805 +1 x806 +1 x807 +1 x808 +1 x809 +1 x810 +1 x811 +1 x812 +1 x813 +1 x814 +1 x815 +1 x816 +1 x817 +1 x818 +1 x819 +1 x820 +1 x821 +1 x822 +1 x823 +1 x824 +1 x825 +1 x826 +1 x827 +1 x828 +1 x829 +1 x830 +1 x831 +1 x832 +1 x833 +1 x834 +1 x835 +1 x836 +1 x837 +1 x838 +1 x839 +1 x840 +1 x841 +1 x842 +1 x843 +1 x844 +1 x845 +1 x846 +1 x847 +1 x848 +1 x849 +1 x850 +1 x851 +1 x852 +1 x853 +1 x854 +1 x855 +1 x856 +1 x857 +1 x858 +1 x859 +1 x860 +1 x861 +1 x862 +1 x863 +1 x864 +1 x865 +1 x866 +1 x867 +1 x868 +1 x869 +1 x870 +1 x871 +1 x872 +1 x873 +1 x874 +1 x875 +1 x876 +1 x877 +1 x878 +1 x879 +1 x880 +1 x881 +1 x882 +1 x883 +1 x884 +1 x885 +1 x886 +1 x887 +1 x888 +1 x889 +1 x890 +1 x891 +1 x892 +1 x893 +1 x894 +1 x895 +1 x896 +1 x897 +1 x898 +1 x899 +1 x900 +1 x901 +1 x902 +1 x903 +1 x904 +1 x905 +1 x906 +1 x907 +1 x908 +1 x909 +1 x910 +1 x911 +1 x912 +1 x913 +1 x914 +1 x915 +1 x916 +1 x917 +1 x918 +1 x919 +1 x920 +1 x921 +1 x922 +1 x923 +1 x924 +1 x925 +1 x926 +1 x927 +1 x928 +1 x929 +1 x930 +1 x931 +1 x932 +1 x933 +1 x934 +1 x935 +1 x936 +1 x937 +1 x938 +1 x939 +1 x940 +1 x941 +1 x942 +1 x943 +1 x944 +1 x945 +1 x946 +1 x947 +1 x948 +1 x949 +1 x950 +1 x951 +1 x952 +1 x953 +1 x954 +1 x955 +1 x956 +1 x957 +1 x958 +1 x959 +1 x960 +1 x961 +1 x962 +1 x963 +1 x964 +1 x965 +1 x966 +1 x967 +1 x968 +1 x969 +1 x970 +1 x971 +1 x972 +1 x973 +1 x974 +1 x975 +1 x976 +1 x977 +1 x978 +1 x979 +1 x980 +1 x981 +1 x982 +1 x983 +1 x984 +1 x985 +1 x986 +1 x987 +1 x988 +1 x989 +1 x990 +1 x991 +1 x992 +1 x993 +1 x994 +1 x995 +1 x996 +1 x997 +1 x998 +1 x999 +1 x1000 +1 x1001 +1 x1002 +1 x1003 +1 x1004 +1 x1005 +1 x1006 +1 x1007 +1 x1008 +1 x1009 +1 x1010 +1 x1011 +1 x1012 +1 x1013 +1 x1014 +1 x1015 +1 x1016 +1 x1017 +1 x1018 +1 x1019 +1 x1020 +1 x1021 +1 x1022 +1 x1023 +1 x1024 +1 x9985 +1 x9986 +1 x9987 +1 x9988 +1 x9989 +1 x9990 +1 x9991 +1 x9992 +1 x9993 +1 x9994 +1 x9995 +1 x9996 +1 x9997 +1 x9998 +1 x9999 +1 x10000 +1 x10001 +1 x10002 +1 x10003 +1 x10004 +1 x10005 +1 x10006 +1 x10007 +1 x10008 +1 x10009 +1 x10010 +1 x10011 +1 x10012 +1 x10013 +1 x10014 +1 x10015 +1 x10016 +1 x10017 +1 x10018 +1 x10019 +1 x10020 +1 x10021 +1 x10022 +1 x10023 +1 x10024 +1 x10025 +1 x10026 +1 x10027 +1 x10028 +1 x10029 +1 x10030 +1 x10031 +1 x10032 +1 x10033 +1 x10034 +1 x10035 +1 x10036 +1 x10037 +1 x10038 +1 x10039 +1 x10040 +1 x10041 +1 x10042 +1 x10043 +1 x10044 +1 x10045 +1 x10046 +1 x10047 +1 x10048 +1 x10049 +1 x10050 +1 x10051 +1 x10052 +1 x10053 +1 x10054 +1 x10055 +1 x10056 +1 x10057 +1 x10058 +1 x10059 +1 x10060 +1 x10061 +1 x10062 +1 x10063 +1 x10064 +1 x10065 +1 x10066 +1 x10067 +1 x10068 +1 x10069 +1 x10070 +1 x10071 +1 x10072 +1 x10073 +1 x10074 +1 x10075 +1 x10076 +1 x10077 +1 x10078 +1 x10079 +1 x10080 +1 x10081 +1 x10082 +1 x10083 +1 x10084 +1 x10085 +1 x10086 +1 x10087 +1 x10088 +1 x10089 +1 x10090 +1 x10091 +1 x10092 +1 x10093 +1 x10094 +1 x10095 +1 x10096 +1 x10097 +1 x10098 +1 x10099 +1 x10100 +1 x10101 +1 x10102 +1 x10103 +1 x10104 +1 x10105 +1 x10106 +1 x10107 +1 x10108 +1 x10109 +1 x10110 +1 x10111 +1 x10112 = 0 ;+-2 x12807 +1 x1025 +1 x1026 +1 x1027 +1 x1028 +1 x1029 +1 x1030 +1 x1031 +1 x1032 +1 x1033 +1 x1034 +1 x1035 +1 x1036 +1 x1037 +1 x1038 +1 x1039 +1 x1040 +1 x1041 +1 x1042 +1 x1043 +1 x1044 +1 x1045 +1 x1046 +1 x1047 +1 x1048 +1 x1049 +1 x1050 +1 x1051 +1 x1052 +1 x1053 +1 x1054 +1 x1055 +1 x1056 +1 x1057 +1 x1058 +1 x1059 +1 x1060 +1 x1061 +1 x1062 +1 x1063 +1 x1064 +1 x1065 +1 x1066 +1 x1067 +1 x1068 +1 x1069 +1 x1070 +1 x1071 +1 x1072 +1 x1073 +1 x1074 +1 x1075 +1 x1076 +1 x1077 +1 x1078 +1 x1079 +1 x1080 +1 x1081 +1 x1082 +1 x1083 +1 x1084 +1 x1085 +1 x1086 +1 x1087 +1 x1088 +1 x1089 +1 x1090 +1 x1091 +1 x1092 +1 x1093 +1 x1094 +1 x1095 +1 x1096 +1 x1097 +1 x1098 +1 x1099 +1 x1100 +1 x1101 +1 x1102 +1 x1103 +1 x1104 +1 x1105 +1 x1106 +1 x1107 +1 x1108 +1 x1109 +1 x1110 +1 x1111 +1 x1112 +1 x1113 +1 x1114 +1 x1115 +1 x1116 +1 x1117 +1 x1118 +1 x1119 +1 x1120 +1 x1121 +1 x1122 +1 x1123 +1 x1124 +1 x1125 +1 x1126 +1 x1127 +1 x1128 +1 x1129 +1 x1130 +1 x1131 +1 x1132 +1 x1133 +1 x1134 +1 x1135 +1 x1136 +1 x1137 +1 x1138 +1 x1139 +1 x1140 +1 x1141 +1 x1142 +1 x1143 +1 x1144 +1 x1145 +1 x1146 +1 x1147 +1 x1148 +1 x1149 +1 x1150 +1 x1151 +1 x1152 +1 x1153 +1 x1154 +1 x1155 +1 x1156 +1 x1157 +1 x1158 +1 x1159 +1 x1160 +1 x1161 +1 x1162 +1 x1163 +1 x1164 +1 x1165 +1 x1166 +1 x1167 +1 x1168 +1 x1169 +1 x1170 +1 x1171 +1 x1172 +1 x1173 +1 x1174 +1 x1175 +1 x1176 +1 x1177 +1 x1178 +1 x1179 +1 x1180 +1 x1181 +1 x1182 +1 x1183 +1 x1184 +1 x1185 +1 x1186 +1 x1187 +1 x1188 +1 x1189 +1 x1190 +1 x1191 +1 x1192 +1 x1193 +1 x1194 +1 x1195 +1 x1196 +1 x1197 +1 x1198 +1 x1199 +1 x1200 +1 x1201 +1 x1202 +1 x1203 +1 x1204 +1 x1205 +1 x1206 +1 x1207 +1 x1208 +1 x1209 +1 x1210 +1 x1211 +1 x1212 +1 x1213 +1 x1214 +1 x1215 +1 x1216 +1 x1217 +1 x1218 +1 x1219 +1 x1220 +1 x1221 +1 x1222 +1 x1223 +1 x1224 +1 x1225 +1 x1226 +1 x1227 +1 x1228 +1 x1229 +1 x1230 +1 x1231 +1 x1232 +1 x1233 +1 x1234 +1 x1235 +1 x1236 +1 x1237 +1 x1238 +1 x1239 +1 x1240 +1 x1241 +1 x1242 +1 x1243 +1 x1244 +1 x1245 +1 x1246 +1 x1247 +1 x1248 +1 x1249 +1 x1250 +1 x1251 +1 x1252 +1 x1253 +1 x1254 +1 x1255 +1 x1256 +1 x1257 +1 x1258 +1 x1259 +1 x1260 +1 x1261 +1 x1262 +1 x1263 +1 x1264 +1 x1265 +1 x1266 +1 x1267 +1 x1268 +1 x1269 +1 x1270 +1 x1271 +1 x1272 +1 x1273 +1 x1274 +1 x1275 +1 x1276 +1 x1277 +1 x1278 +1 x1279 +1 x1280 +1 x1921 +1 x1922 +1 x1923 +1 x1924 +1 x1925 +1 x1926 +1 x1927 +1 x1928 +1 x1929 +1 x1930 +1 x1931 +1 x1932 +1 x1933 +1 x1934 +1 x1935 +1 x1936 +1 x1937 +1 x1938 +1 x1939 +1 x1940 +1 x1941 +1 x1942 +1 x1943 +1 x1944 +1 x1945 +1 x1946 +1 x1947 +1 x1948 +1 x1949 +1 x1950 +1 x1951 +1 x1952 +1 x1953 +1 x1954 +1 x1955 +1 x1956 +1 x1957 +1 x1958 +1 x1959 +1 x1960 +1 x1961 +1 x1962 +1 x1963 +1 x1964 +1 x1965 +1 x1966 +1 x1967 +1 x1968 +1 x1969 +1 x1970 +1 x1971 +1 x1972 +1 x1973 +1 x1974 +1 x1975 +1 x1976 +1 x1977 +1 x1978 +1 x1979 +1 x1980 +1 x1981 +1 x1982 +1 x1983 +1 x1984 +1 x1985 +1 x1986 +1 x1987 +1 x1988 +1 x1989 +1 x1990 +1 x1991 +1 x1992 +1 x1993 +1 x1994 +1 x1995 +1 x1996 +1 x1997 +1 x1998 +1 x1999 +1 x2000 +1 x2001 +1 x2002 +1 x2003 +1 x2004 +1 x2005 +1 x2006 +1 x2007 +1 x2008 +1 x2009 +1 x2010 +1 x2011 +1 x2012 +1 x2013 +1 x2014 +1 x2015 +1 x2016 +1 x2017 +1 x2018 +1 x2019 +1 x2020 +1 x2021 +1 x2022 +1 x2023 +1 x2024 +1 x2025 +1 x2026 +1 x2027 +1 x2028 +1 x2029 +1 x2030 +1 x2031 +1 x2032 +1 x2033 +1 x2034 +1 x2035 +1 x2036 +1 x2037 +1 x2038 +1 x2039 +1 x2040 +1 x2041 +1 x2042 +1 x2043 +1 x2044 +1 x2045 +1 x2046 +1 x2047 +1 x2048 +1 x2561 +1 x2562 +1 x2563 +1 x2564 +1 x2565 +1 x2566 +1 x2567 +1 x2568 +1 x2569 +1 x2570 +1 x2571 +1 x2572 +1 x2573 +1 x2574 +1 x2575 +1 x2576 +1 x2577 +1 x2578 +1 x2579 +1 x2580 +1 x2581 +1 x2582 +1 x2583 +1 x2584 +1 x2585 +1 x2586 +1 x2587 +1 x2588 +1 x2589 +1 x2590 +1 x2591 +1 x2592 +1 x2593 +1 x2594 +1 x2595 +1 x2596 +1 x2597 +1 x2598 +1 x2599 +1 x2600 +1 x2601 +1 x2602 +1 x2603 +1 x2604 +1 x2605 +1 x2606 +1 x2607 +1 x2608 +1 x2609 +1 x2610 +1 x2611 +1 x2612 +1 x2613 +1 x2614 +1 x2615 +1 x2616 +1 x2617 +1 x2618 +1 x2619 +1 x2620 +1 x2621 +1 x2622 +1 x2623 +1 x2624 +1 x2625 +1 x2626 +1 x2627 +1 x2628 +1 x2629 +1 x2630 +1 x2631 +1 x2632 +1 x2633 +1 x2634 +1 x2635 +1 x2636 +1 x2637 +1 x2638 +1 x2639 +1 x2640 +1 x2641 +1 x2642 +1 x2643 +1 x2644 +1 x2645 +1 x2646 +1 x2647 +1 x2648 +1 x2649 +1 x2650 +1 x2651 +1 x2652 +1 x2653 +1 x2654 +1 x2655 +1 x2656 +1 x2657 +1 x2658 +1 x2659 +1 x2660 +1 x2661 +1 x2662 +1 x2663 +1 x2664 +1 x2665 +1 x2666 +1 x2667 +1 x2668 +1 x2669 +1 x2670 +1 x2671 +1 x2672 +1 x2673 +1 x2674 +1 x2675 +1 x2676 +1 x2677 +1 x2678 +1 x2679 +1 x2680 +1 x2681 +1 x2682 +1 x2683 +1 x2684 +1 x2685 +1 x2686 +1 x2687 +1 x2688 +1 x3713 +1 x3714 +1 x3715 +1 x3716 +1 x3717 +1 x3718 +1 x3719 +1 x3720 +1 x3721 +1 x3722 +1 x3723 +1 x3724 +1 x3725 +1 x3726 +1 x3727 +1 x3728 +1 x3729 +1 x3730 +1 x3731 +1 x3732 +1 x3733 +1 x3734 +1 x3735 +1 x3736 +1 x3737 +1 x3738 +1 x3739 +1 x3740 +1 x3741 +1 x3742 +1 x3743 +1 x3744 +1 x3745 +1 x3746 +1 x3747 +1 x3748 +1 x3749 +1 x3750 +1 x3751 +1 x3752 +1 x3753 +1 x3754 +1 x3755 +1 x3756 +1 x3757 +1 x3758 +1 x3759 +1 x3760 +1 x3761 +1 x3762 +1 x3763 +1 x3764 +1 x3765 +1 x3766 +1 x3767 +1 x3768 +1 x3769 +1 x3770 +1 x3771 +1 x3772 +1 x3773 +1 x3774 +1 x3775 +1 x3776 +1 x3777 +1 x3778 +1 x3779 +1 x3780 +1 x3781 +1 x3782 +1 x3783 +1 x3784 +1 x3785 +1 x3786 +1 x3787 +1 x3788 +1 x3789 +1 x3790 +1 x3791 +1 x3792 +1 x3793 +1 x3794 +1 x3795 +1 x3796 +1 x3797 +1 x3798 +1 x3799 +1 x3800 +1 x3801 +1 x3802 +1 x3803 +1 x3804 +1 x3805 +1 x3806 +1 x3807 +1 x3808 +1 x3809 +1 x3810 +1 x3811 +1 x3812 +1 x3813 +1 x3814 +1 x3815 +1 x3816 +1 x3817 +1 x3818 +1 x3819 +1 x3820 +1 x3821 +1 x3822 +1 x3823 +1 x3824 +1 x3825 +1 x3826 +1 x3827 +1 x3828 +1 x3829 +1 x3830 +1 x3831 +1 x3832 +1 x3833 +1 x3834 +1 x3835 +1 x3836 +1 x3837 +1 x3838 +1 x3839 +1 x3840 +1 x7425 +1 x7426 +1 x7427 +1 x7428 +1 x7429 +1 x7430 +1 x7431 +1 x7432 +1 x7433 +1 x7434 +1 x7435 +1 x7436 +1 x7437 +1 x7438 +1 x7439 +1 x7440 +1 x7441 +1 x7442 +1 x7443 +1 x7444 +1 x7445 +1 x7446 +1 x7447 +1 x7448 +1 x7449 +1 x7450 +1 x7451 +1 x7452 +1 x7453 +1 x7454 +1 x7455 +1 x7456 +1 x7457 +1 x7458 +1 x7459 +1 x7460 +1 x7461 +1 x7462 +1 x7463 +1 x7464 +1 x7465 +1 x7466 +1 x7467 +1 x7468 +1 x7469 +1 x7470 +1 x7471 +1 x7472 +1 x7473 +1 x7474 +1 x7475 +1 x7476 +1 x7477 +1 x7478 +1 x7479 +1 x7480 +1 x7481 +1 x7482 +1 x7483 +1 x7484 +1 x7485 +1 x7486 +1 x7487 +1 x7488 +1 x7489 +1 x7490 +1 x7491 +1 x7492 +1 x7493 +1 x7494 +1 x7495 +1 x7496 +1 x7497 +1 x7498 +1 x7499 +1 x7500 +1 x7501 +1 x7502 +1 x7503 +1 x7504 +1 x7505 +1 x7506 +1 x7507 +1 x7508 +1 x7509 +1 x7510 +1 x7511 +1 x7512 +1 x7513 +1 x7514 +1 x7515 +1 x7516 +1 x7517 +1 x7518 +1 x7519 +1 x7520 +1 x7521 +1 x7522 +1 x7523 +1 x7524 +1 x7525 +1 x7526 +1 x7527 +1 x7528 +1 x7529 +1 x7530 +1 x7531 +1 x7532 +1 x7533 +1 x7534 +1 x7535 +1 x7536 +1 x7537 +1 x7538 +1 x7539 +1 x7540 +1 x7541 +1 x7542 +1 x7543 +1 x7544 +1 x7545 +1 x7546 +1 x7547 +1 x7548 +1 x7549 +1 x7550 +1 x7551 +1 x7552 = 0 ;+-2 x12808 +1 x1281 +1 x1282 +1 x1283 +1 x1284 +1 x1285 +1 x1286 +1 x1287 +1 x1288 +1 x1289 +1 x1290 +1 x1291 +1 x1292 +1 x1293 +1 x1294 +1 x1295 +1 x1296 +1 x1297 +1 x1298 +1 x1299 +1 x1300 +1 x1301 +1 x1302 +1 x1303 +1 x1304 +1 x1305 +1 x1306 +1 x1307 +1 x1308 +1 x1309 +1 x1310 +1 x1311 +1 x1312 +1 x1313 +1 x1314 +1 x1315 +1 x1316 +1 x1317 +1 x1318 +1 x1319 +1 x1320 +1 x1321 +1 x1322 +1 x1323 +1 x1324 +1 x1325 +1 x1326 +1 x1327 +1 x1328 +1 x1329 +1 x1330 +1 x1331 +1 x1332 +1 x1333 +1 x1334 +1 x1335 +1 x1336 +1 x1337 +1 x1338 +1 x1339 +1 x1340 +1 x1341 +1 x1342 +1 x1343 +1 x1344 +1 x1345 +1 x1346 +1 x1347 +1 x1348 +1 x1349 +1 x1350 +1 x1351 +1 x1352 +1 x1353 +1 x1354 +1 x1355 +1 x1356 +1 x1357 +1 x1358 +1 x1359 +1 x1360 +1 x1361 +1 x1362 +1 x1363 +1 x1364 +1 x1365 +1 x1366 +1 x1367 +1 x1368 +1 x1369 +1 x1370 +1 x1371 +1 x1372 +1 x1373 +1 x1374 +1 x1375 +1 x1376 +1 x1377 +1 x1378 +1 x1379 +1 x1380 +1 x1381 +1 x1382 +1 x1383 +1 x1384 +1 x1385 +1 x1386 +1 x1387 +1 x1388 +1 x1389 +1 x1390 +1 x1391 +1 x1392 +1 x1393 +1 x1394 +1 x1395 +1 x1396 +1 x1397 +1 x1398 +1 x1399 +1 x1400 +1 x1401 +1 x1402 +1 x1403 +1 x1404 +1 x1405 +1 x1406 +1 x1407 +1 x1408 +1 x1409 +1 x1410 +1 x1411 +1 x1412 +1 x1413 +1 x1414 +1 x1415 +1 x1416 +1 x1417 +1 x1418 +1 x1419 +1 x1420 +1 x1421 +1 x1422 +1 x1423 +1 x1424 +1 x1425 +1 x1426 +1 x1427 +1 x1428 +1 x1429 +1 x1430 +1 x1431 +1 x1432 +1 x1433 +1 x1434 +1 x1435 +1 x1436 +1 x1437 +1 x1438 +1 x1439 +1 x1440 +1 x1441 +1 x1442 +1 x1443 +1 x1444 +1 x1445 +1 x1446 +1 x1447 +1 x1448 +1 x1449 +1 x1450 +1 x1451 +1 x1452 +1 x1453 +1 x1454 +1 x1455 +1 x1456 +1 x1457 +1 x1458 +1 x1459 +1 x1460 +1 x1461 +1 x1462 +1 x1463 +1 x1464 +1 x1465 +1 x1466 +1 x1467 +1 x1468 +1 x1469 +1 x1470 +1 x1471 +1 x1472 +1 x1473 +1 x1474 +1 x1475 +1 x1476 +1 x1477 +1 x1478 +1 x1479 +1 x1480 +1 x1481 +1 x1482 +1 x1483 +1 x1484 +1 x1485 +1 x1486 +1 x1487 +1 x1488 +1 x1489 +1 x1490 +1 x1491 +1 x1492 +1 x1493 +1 x1494 +1 x1495 +1 x1496 +1 x1497 +1 x1498 +1 x1499 +1 x1500 +1 x1501 +1 x1502 +1 x1503 +1 x1504 +1 x1505 +1 x1506 +1 x1507 +1 x1508 +1 x1509 +1 x1510 +1 x1511 +1 x1512 +1 x1513 +1 x1514 +1 x1515 +1 x1516 +1 x1517 +1 x1518 +1 x1519 +1 x1520 +1 x1521 +1 x1522 +1 x1523 +1 x1524 +1 x1525 +1 x1526 +1 x1527 +1 x1528 +1 x1529 +1 x1530 +1 x1531 +1 x1532 +1 x1533 +1 x1534 +1 x1535 +1 x1536 +1 x1537 +1 x1538 +1 x1539 +1 x1540 +1 x1541 +1 x1542 +1 x1543 +1 x1544 +1 x1545 +1 x1546 +1 x1547 +1 x1548 +1 x1549 +1 x1550 +1 x1551 +1 x1552 +1 x1553 +1 x1554 +1 x1555 +1 x1556 +1 x1557 +1 x1558 +1 x1559 +1 x1560 +1 x1561 +1 x1562 +1 x1563 +1 x1564 +1 x1565 +1 x1566 +1 x1567 +1 x1568 +1 x1569 +1 x1570 +1 x1571 +1 x1572 +1 x1573 +1 x1574 +1 x1575 +1 x1576 +1 x1577 +1 x1578 +1 x1579 +1 x1580 +1 x1581 +1 x1582 +1 x1583 +1 x1584 +1 x1585 +1 x1586 +1 x1587 +1 x1588 +1 x1589 +1 x1590 +1 x1591 +1 x1592 +1 x1593 +1 x1594 +1 x1595 +1 x1596 +1 x1597 +1 x1598 +1 x1599 +1 x1600 +1 x1601 +1 x1602 +1 x1603 +1 x1604 +1 x1605 +1 x1606 +1 x1607 +1 x1608 +1 x1609 +1 x1610 +1 x1611 +1 x1612 +1 x1613 +1 x1614 +1 x1615 +1 x1616 +1 x1617 +1 x1618 +1 x1619 +1 x1620 +1 x1621 +1 x1622 +1 x1623 +1 x1624 +1 x1625 +1 x1626 +1 x1627 +1 x1628 +1 x1629 +1 x1630 +1 x1631 +1 x1632 +1 x1633 +1 x1634 +1 x1635 +1 x1636 +1 x1637 +1 x1638 +1 x1639 +1 x1640 +1 x1641 +1 x1642 +1 x1643 +1 x1644 +1 x1645 +1 x1646 +1 x1647 +1 x1648 +1 x1649 +1 x1650 +1 x1651 +1 x1652 +1 x1653 +1 x1654 +1 x1655 +1 x1656 +1 x1657 +1 x1658 +1 x1659 +1 x1660 +1 x1661 +1 x1662 +1 x1663 +1 x1664 +1 x2049 +1 x2050 +1 x2051 +1 x2052 +1 x2053 +1 x2054 +1 x2055 +1 x2056 +1 x2057 +1 x2058 +1 x2059 +1 x2060 +1 x2061 +1 x2062 +1 x2063 +1 x2064 +1 x2065 +1 x2066 +1 x2067 +1 x2068 +1 x2069 +1 x2070 +1 x2071 +1 x2072 +1 x2073 +1 x2074 +1 x2075 +1 x2076 +1 x2077 +1 x2078 +1 x2079 +1 x2080 +1 x2081 +1 x2082 +1 x2083 +1 x2084 +1 x2085 +1 x2086 +1 x2087 +1 x2088 +1 x2089 +1 x2090 +1 x2091 +1 x2092 +1 x2093 +1 x2094 +1 x2095 +1 x2096 +1 x2097 +1 x2098 +1 x2099 +1 x2100 +1 x2101 +1 x2102 +1 x2103 +1 x2104 +1 x2105 +1 x2106 +1 x2107 +1 x2108 +1 x2109 +1 x2110 +1 x2111 +1 x2112 +1 x2113 +1 x2114 +1 x2115 +1 x2116 +1 x2117 +1 x2118 +1 x2119 +1 x2120 +1 x2121 +1 x2122 +1 x2123 +1 x2124 +1 x2125 +1 x2126 +1 x2127 +1 x2128 +1 x2129 +1 x2130 +1 x2131 +1 x2132 +1 x2133 +1 x2134 +1 x2135 +1 x2136 +1 x2137 +1 x2138 +1 x2139 +1 x2140 +1 x2141 +1 x2142 +1 x2143 +1 x2144 +1 x2145 +1 x2146 +1 x2147 +1 x2148 +1 x2149 +1 x2150 +1 x2151 +1 x2152 +1 x2153 +1 x2154 +1 x2155 +1 x2156 +1 x2157 +1 x2158 +1 x2159 +1 x2160 +1 x2161 +1 x2162 +1 x2163 +1 x2164 +1 x2165 +1 x2166 +1 x2167 +1 x2168 +1 x2169 +1 x2170 +1 x2171 +1 x2172 +1 x2173 +1 x2174 +1 x2175 +1 x2176 +1 x4737 +1 x4738 +1 x4739 +1 x4740 +1 x4741 +1 x4742 +1 x4743 +1 x4744 +1 x4745 +1 x4746 +1 x4747 +1 x4748 +1 x4749 +1 x4750 +1 x4751 +1 x4752 +1 x4753 +1 x4754 +1 x4755 +1 x4756 +1 x4757 +1 x4758 +1 x4759 +1 x4760 +1 x4761 +1 x4762 +1 x4763 +1 x4764 +1 x4765 +1 x4766 +1 x4767 +1 x4768 +1 x4769 +1 x4770 +1 x4771 +1 x4772 +1 x4773 +1 x4774 +1 x4775 +1 x4776 +1 x4777 +1 x4778 +1 x4779 +1 x4780 +1 x4781 +1 x4782 +1 x4783 +1 x4784 +1 x4785 +1 x4786 +1 x4787 +1 x4788 +1 x4789 +1 x4790 +1 x4791 +1 x4792 +1 x4793 +1 x4794 +1 x4795 +1 x4796 +1 x4797 +1 x4798 +1 x4799 +1 x4800 +1 x4801 +1 x4802 +1 x4803 +1 x4804 +1 x4805 +1 x4806 +1 x4807 +1 x4808 +1 x4809 +1 x4810 +1 x4811 +1 x4812 +1 x4813 +1 x4814 +1 x4815 +1 x4816 +1 x4817 +1 x4818 +1 x4819 +1 x4820 +1 x4821 +1 x4822 +1 x4823 +1 x4824 +1 x4825 +1 x4826 +1 x4827 +1 x4828 +1 x4829 +1 x4830 +1 x4831 +1 x4832 +1 x4833 +1 x4834 +1 x4835 +1 x4836 +1 x4837 +1 x4838 +1 x4839 +1 x4840 +1 x4841 +1 x4842 +1 x4843 +1 x4844 +1 x4845 +1 x4846 +1 x4847 +1 x4848 +1 x4849 +1 x4850 +1 x4851 +1 x4852 +1 x4853 +1 x4854 +1 x4855 +1 x4856 +1 x4857 +1 x4858 +1 x4859 +1 x4860 +1 x4861 +1 x4862 +1 x4863 +1 x4864 +1 x8065 +1 x8066 +1 x8067 +1 x8068 +1 x8069 +1 x8070 +1 x8071 +1 x8072 +1 x8073 +1 x8074 +1 x8075 +1 x8076 +1 x8077 +1 x8078 +1 x8079 +1 x8080 +1 x8081 +1 x8082 +1 x8083 +1 x8084 +1 x8085 +1 x8086 +1 x8087 +1 x8088 +1 x8089 +1 x8090 +1 x8091 +1 x8092 +1 x8093 +1 x8094 +1 x8095 +1 x8096 +1 x8097 +1 x8098 +1 x8099 +1 x8100 +1 x8101 +1 x8102 +1 x8103 +1 x8104 +1 x8105 +1 x8106 +1 x8107 +1 x8108 +1 x8109 +1 x8110 +1 x8111 +1 x8112 +1 x8113 +1 x8114 +1 x8115 +1 x8116 +1 x8117 +1 x8118 +1 x8119 +1 x8120 +1 x8121 +1 x8122 +1 x8123 +1 x8124 +1 x8125 +1 x8126 +1 x8127 +1 x8128 +1 x8129 +1 x8130 +1 x8131 +1 x8132 +1 x8133 +1 x8134 +1 x8135 +1 x8136 +1 x8137 +1 x8138 +1 x8139 +1 x8140 +1 x8141 +1 x8142 +1 x8143 +1 x8144 +1 x8145 +1 x8146 +1 x8147 +1 x8148 +1 x8149 +1 x8150 +1 x8151 +1 x8152 +1 x8153 +1 x8154 +1 x8155 +1 x8156 +1 x8157 +1 x8158 +1 x8159 +1 x8160 +1 x8161 +1 x8162 +1 x8163 +1 x8164 +1 x8165 +1 x8166 +1 x8167 +1 x8168 +1 x8169 +1 x8170 +1 x8171 +1 x8172 +1 x8173 +1 x8174 +1 x8175 +1 x8176 +1 x8177 +1 x8178 +1 x8179 +1 x8180 +1 x8181 +1 x8182 +1 x8183 +1 x8184 +1 x8185 +1 x8186 +1 x8187 +1 x8188 +1 x8189 +1 x8190 +1 x8191 +1 x8192 +1 x10241 +1 x10242 +1 x10243 +1 x10244 +1 x10245 +1 x10246 +1 x10247 +1 x10248 +1 x10249 +1 x10250 +1 x10251 +1 x10252 +1 x10253 +1 x10254 +1 x10255 +1 x10256 +1 x10257 +1 x10258 +1 x10259 +1 x10260 +1 x10261 +1 x10262 +1 x10263 +1 x10264 +1 x10265 +1 x10266 +1 x10267 +1 x10268 +1 x10269 +1 x10270 +1 x10271 +1 x10272 +1 x10273 +1 x10274 +1 x10275 +1 x10276 +1 x10277 +1 x10278 +1 x10279 +1 x10280 +1 x10281 +1 x10282 +1 x10283 +1 x10284 +1 x10285 +1 x10286 +1 x10287 +1 x10288 +1 x10289 +1 x10290 +1 x10291 +1 x10292 +1 x10293 +1 x10294 +1 x10295 +1 x10296 +1 x10297 +1 x10298 +1 x10299 +1 x10300 +1 x10301 +1 x10302 +1 x10303 +1 x10304 +1 x10305 +1 x10306 +1 x10307 +1 x10308 +1 x10309 +1 x10310 +1 x10311 +1 x10312 +1 x10313 +1 x10314 +1 x10315 +1 x10316 +1 x10317 +1 x10318 +1 x10319 +1 x10320 +1 x10321 +1 x10322 +1 x10323 +1 x10324 +1 x10325 +1 x10326 +1 x10327 +1 x10328 +1 x10329 +1 x10330 +1 x10331 +1 x10332 +1 x10333 +1 x10334 +1 x10335 +1 x10336 +1 x10337 +1 x10338 +1 x10339 +1 x10340 +1 x10341 +1 x10342 +1 x10343 +1 x10344 +1 x10345 +1 x10346 +1 x10347 +1 x10348 +1 x10349 +1 x10350 +1 x10351 +1 x10352 +1 x10353 +1 x10354 +1 x10355 +1 x10356 +1 x10357 +1 x10358 +1 x10359 +1 x10360 +1 x10361 +1 x10362 +1 x10363 +1 x10364 +1 x10365 +1 x10366 +1 x10367 +1 x10368 +1 x11265 +1 x11266 +1 x11267 +1 x11268 +1 x11269 +1 x11270 +1 x11271 +1 x11272 +1 x11273 +1 x11274 +1 x11275 +1 x11276 +1 x11277 +1 x11278 +1 x11279 +1 x11280 +1 x11281 +1 x11282 +1 x11283 +1 x11284 +1 x11285 +1 x11286 +1 x11287 +1 x11288 +1 x11289 +1 x11290 +1 x11291 +1 x11292 +1 x11293 +1 x11294 +1 x11295 +1 x11296 +1 x11297 +1 x11298 +1 x11299 +1 x11300 +1 x11301 +1 x11302 +1 x11303 +1 x11304 +1 x11305 +1 x11306 +1 x11307 +1 x11308 +1 x11309 +1 x11310 +1 x11311 +1 x11312 +1 x11313 +1 x11314 +1 x11315 +1 x11316 +1 x11317 +1 x11318 +1 x11319 +1 x11320 +1 x11321 +1 x11322 +1 x11323 +1 x11324 +1 x11325 +1 x11326 +1 x11327 +1 x11328 +1 x11329 +1 x11330 +1 x11331 +1 x11332 +1 x11333 +1 x11334 +1 x11335 +1 x11336 +1 x11337 +1 x11338 +1 x11339 +1 x11340 +1 x11341 +1 x11342 +1 x11343 +1 x11344 +1 x11345 +1 x11346 +1 x11347 +1 x11348 +1 x11349 +1 x11350 +1 x11351 +1 x11352 +1 x11353 +1 x11354 +1 x11355 +1 x11356 +1 x11357 +1 x11358 +1 x11359 +1 x11360 +1 x11361 +1 x11362 +1 x11363 +1 x11364 +1 x11365 +1 x11366 +1 x11367 +1 x11368 +1 x11369 +1 x11370 +1 x11371 +1 x11372 +1 x11373 +1 x11374 +1 x11375 +1 x11376 +1 x11377 +1 x11378 +1 x11379 +1 x11380 +1 x11381 +1 x11382 +1 x11383 +1 x11384 +1 x11385 +1 x11386 +1 x11387 +1 x11388 +1 x11389 +1 x11390 +1 x11391 +1 x11392 +1 x12033 +1 x12034 +1 x12035 +1 x12036 +1 x12037 +1 x12038 +1 x12039 +1 x12040 +1 x12041 +1 x12042 +1 x12043 +1 x12044 +1 x12045 +1 x12046 +1 x12047 +1 x12048 +1 x12049 +1 x12050 +1 x12051 +1 x12052 +1 x12053 +1 x12054 +1 x12055 +1 x12056 +1 x12057 +1 x12058 +1 x12059 +1 x12060 +1 x12061 +1 x12062 +1 x12063 +1 x12064 +1 x12065 +1 x12066 +1 x12067 +1 x12068 +1 x12069 +1 x12070 +1 x12071 +1 x12072 +1 x12073 +1 x12074 +1 x12075 +1 x12076 +1 x12077 +1 x12078 +1 x12079 +1 x12080 +1 x12081 +1 x12082 +1 x12083 +1 x12084 +1 x12085 +1 x12086 +1 x12087 +1 x12088 +1 x12089 +1 x12090 +1 x12091 +1 x12092 +1 x12093 +1 x12094 +1 x12095 +1 x12096 +1 x12097 +1 x12098 +1 x12099 +1 x12100 +1 x12101 +1 x12102 +1 x12103 +1 x12104 +1 x12105 +1 x12106 +1 x12107 +1 x12108 +1 x12109 +1 x12110 +1 x12111 +1 x12112 +1 x12113 +1 x12114 +1 x12115 +1 x12116 +1 x12117 +1 x12118 +1 x12119 +1 x12120 +1 x12121 +1 x12122 +1 x12123 +1 x12124 +1 x12125 +1 x12126 +1 x12127 +1 x12128 +1 x12129 +1 x12130 +1 x12131 +1 x12132 +1 x12133 +1 x12134 +1 x12135 +1 x12136 +1 x12137 +1 x12138 +1 x12139 +1 x12140 +1 x12141 +1 x12142 +1 x12143 +1 x12144 +1 x12145 +1 x12146 +1 x12147 +1 x12148 +1 x12149 +1 x12150 +1 x12151 +1 x12152 +1 x12153 +1 x12154 +1 x12155 +1 x12156 +1 x12157 +1 x12158 +1 x12159 +1 x12160 = 0 ;+-2 x12809 +1 x1793 +1 x1794 +1 x1795 +1 x1796 +1 x1797 +1 x1798 +1 x1799 +1 x1800 +1 x1801 +1 x1802 +1 x1803 +1 x1804 +1 x1805 +1 x1806 +1 x1807 +1 x1808 +1 x1809 +1 x1810 +1 x1811 +1 x1812 +1 x1813 +1 x1814 +1 x1815 +1 x1816 +1 x1817 +1 x1818 +1 x1819 +1 x1820 +1 x1821 +1 x1822 +1 x1823 +1 x1824 +1 x1825 +1 x1826 +1 x1827 +1 x1828 +1 x1829 +1 x1830 +1 x1831 +1 x1832 +1 x1833 +1 x1834 +1 x1835 +1 x1836 +1 x1837 +1 x1838 +1 x1839 +1 x1840 +1 x1841 +1 x1842 +1 x1843 +1 x1844 +1 x1845 +1 x1846 +1 x1847 +1 x1848 +1 x1849 +1 x1850 +1 x1851 +1 x1852 +1 x1853 +1 x1854 +1 x1855 +1 x1856 +1 x1857 +1 x1858 +1 x1859 +1 x1860 +1 x1861 +1 x1862 +1 x1863 +1 x1864 +1 x1865 +1 x1866 +1 x1867 +1 x1868 +1 x1869 +1 x1870 +1 x1871 +1 x1872 +1 x1873 +1 x1874 +1 x1875 +1 x1876 +1 x1877 +1 x1878 +1 x1879 +1 x1880 +1 x1881 +1 x1882 +1 x1883 +1 x1884 +1 x1885 +1 x1886 +1 x1887 +1 x1888 +1 x1889 +1 x1890 +1 x1891 +1 x1892 +1 x1893 +1 x1894 +1 x1895 +1 x1896 +1 x1897 +1 x1898 +1 x1899 +1 x1900 +1 x1901 +1 x1902 +1 x1903 +1 x1904 +1 x1905 +1 x1906 +1 x1907 +1 x1908 +1 x1909 +1 x1910 +1 x1911 +1 x1912 +1 x1913 +1 x1914 +1 x1915 +1 x1916 +1 x1917 +1 x1918 +1 x1919 +1 x1920 +1 x1921 +1 x1922 +1 x1923 +1 x1924 +1 x1925 +1 x1926 +1 x1927 +1 x1928 +1 x1929 +1 x1930 +1 x1931 +1 x1932 +1 x1933 +1 x1934 +1 x1935 +1 x1936 +1 x1937 +1 x1938 +1 x1939 +1 x1940 +1 x1941 +1 x1942 +1 x1943 +1 x1944 +1 x1945 +1 x1946 +1 x1947 +1 x1948 +1 x1949 +1 x1950 +1 x1951 +1 x1952 +1 x1953 +1 x1954 +1 x1955 +1 x1956 +1 x1957 +1 x1958 +1 x1959 +1 x1960 +1 x1961 +1 x1962 +1 x1963 +1 x1964 +1 x1965 +1 x1966 +1 x1967 +1 x1968 +1 x1969 +1 x1970 +1 x1971 +1 x1972 +1 x1973 +1 x1974 +1 x1975 +1 x1976 +1 x1977 +1 x1978 +1 x1979 +1 x1980 +1 x1981 +1 x1982 +1 x1983 +1 x1984 +1 x1985 +1 x1986 +1 x1987 +1 x1988 +1 x1989 +1 x1990 +1 x1991 +1 x1992 +1 x1993 +1 x1994 +1 x1995 +1 x1996 +1 x1997 +1 x1998 +1 x1999 +1 x2000 +1 x2001 +1 x2002 +1 x2003 +1 x2004 +1 x2005 +1 x2006 +1 x2007 +1 x2008 +1 x2009 +1 x2010 +1 x2011 +1 x2012 +1 x2013 +1 x2014 +1 x2015 +1 x2016 +1 x2017 +1 x2018 +1 x2019 +1 x2020 +1 x2021 +1 x2022 +1 x2023 +1 x2024 +1 x2025 +1 x2026 +1 x2027 +1 x2028 +1 x2029 +1 x2030 +1 x2031 +1 x2032 +1 x2033 +1 x2034 +1 x2035 +1 x2036 +1 x2037 +1 x2038 +1 x2039 +1 x2040 +1 x2041 +1 x2042 +1 x2043 +1 x2044 +1 x2045 +1 x2046 +1 x2047 +1 x2048 +1 x3457 +1 x3458 +1 x3459 +1 x3460 +1 x3461 +1 x3462 +1 x3463 +1 x3464 +1 x3465 +1 x3466 +1 x3467 +1 x3468 +1 x3469 +1 x3470 +1 x3471 +1 x3472 +1 x3473 +1 x3474 +1 x3475 +1 x3476 +1 x3477 +1 x3478 +1 x3479 +1 x3480 +1 x3481 +1 x3482 +1 x3483 +1 x3484 +1 x3485 +1 x3486 +1 x3487 +1 x3488 +1 x3489 +1 x3490 +1 x3491 +1 x3492 +1 x3493 +1 x3494 +1 x3495 +1 x3496 +1 x3497 +1 x3498 +1 x3499 +1 x3500 +1 x3501 +1 x3502 +1 x3503 +1 x3504 +1 x3505 +1 x3506 +1 x3507 +1 x3508 +1 x3509 +1 x3510 +1 x3511 +1 x3512 +1 x3513 +1 x3514 +1 x3515 +1 x3516 +1 x3517 +1 x3518 +1 x3519 +1 x3520 +1 x3521 +1 x3522 +1 x3523 +1 x3524 +1 x3525 +1 x3526 +1 x3527 +1 x3528 +1 x3529 +1 x3530 +1 x3531 +1 x3532 +1 x3533 +1 x3534 +1 x3535 +1 x3536 +1 x3537 +1 x3538 +1 x3539 +1 x3540 +1 x3541 +1 x3542 +1 x3543 +1 x3544 +1 x3545 +1 x3546 +1 x3547 +1 x3548 +1 x3549 +1 x3550 +1 x3551 +1 x3552 +1 x3553 +1 x3554 +1 x3555 +1 x3556 +1 x3557 +1 x3558 +1 x3559 +1 x3560 +1 x3561 +1 x3562 +1 x3563 +1 x3564 +1 x3565 +1 x3566 +1 x3567 +1 x3568 +1 x3569 +1 x3570 +1 x3571 +1 x3572 +1 x3573 +1 x3574 +1 x3575 +1 x3576 +1 x3577 +1 x3578 +1 x3579 +1 x3580 +1 x3581 +1 x3582 +1 x3583 +1 x3584 = 0 ;+-2 x12810 +1 x2049 +1 x2050 +1 x2051 +1 x2052 +1 x2053 +1 x2054 +1 x2055 +1 x2056 +1 x2057 +1 x2058 +1 x2059 +1 x2060 +1 x2061 +1 x2062 +1 x2063 +1 x2064 +1 x2065 +1 x2066 +1 x2067 +1 x2068 +1 x2069 +1 x2070 +1 x2071 +1 x2072 +1 x2073 +1 x2074 +1 x2075 +1 x2076 +1 x2077 +1 x2078 +1 x2079 +1 x2080 +1 x2081 +1 x2082 +1 x2083 +1 x2084 +1 x2085 +1 x2086 +1 x2087 +1 x2088 +1 x2089 +1 x2090 +1 x2091 +1 x2092 +1 x2093 +1 x2094 +1 x2095 +1 x2096 +1 x2097 +1 x2098 +1 x2099 +1 x2100 +1 x2101 +1 x2102 +1 x2103 +1 x2104 +1 x2105 +1 x2106 +1 x2107 +1 x2108 +1 x2109 +1 x2110 +1 x2111 +1 x2112 +1 x2113 +1 x2114 +1 x2115 +1 x2116 +1 x2117 +1 x2118 +1 x2119 +1 x2120 +1 x2121 +1 x2122 +1 x2123 +1 x2124 +1 x2125 +1 x2126 +1 x2127 +1 x2128 +1 x2129 +1 x2130 +1 x2131 +1 x2132 +1 x2133 +1 x2134 +1 x2135 +1 x2136 +1 x2137 +1 x2138 +1 x2139 +1 x2140 +1 x2141 +1 x2142 +1 x2143 +1 x2144 +1 x2145 +1 x2146 +1 x2147 +1 x2148 +1 x2149 +1 x2150 +1 x2151 +1 x2152 +1 x2153 +1 x2154 +1 x2155 +1 x2156 +1 x2157 +1 x2158 +1 x2159 +1 x2160 +1 x2161 +1 x2162 +1 x2163 +1 x2164 +1 x2165 +1 x2166 +1 x2167 +1 x2168 +1 x2169 +1 x2170 +1 x2171 +1 x2172 +1 x2173 +1 x2174 +1 x2175 +1 x2176 +1 x2177 +1 x2178 +1 x2179 +1 x2180 +1 x2181 +1 x2182 +1 x2183 +1 x2184 +1 x2185 +1 x2186 +1 x2187 +1 x2188 +1 x2189 +1 x2190 +1 x2191 +1 x2192 +1 x2193 +1 x2194 +1 x2195 +1 x2196 +1 x2197 +1 x2198 +1 x2199 +1 x2200 +1 x2201 +1 x2202 +1 x2203 +1 x2204 +1 x2205 +1 x2206 +1 x2207 +1 x2208 +1 x2209 +1 x2210 +1 x2211 +1 x2212 +1 x2213 +1 x2214 +1 x2215 +1 x2216 +1 x2217 +1 x2218 +1 x2219 +1 x2220 +1 x2221 +1 x2222 +1 x2223 +1 x2224 +1 x2225 +1 x2226 +1 x2227 +1 x2228 +1 x2229 +1 x2230 +1 x2231 +1 x2232 +1 x2233 +1 x2234 +1 x2235 +1 x2236 +1 x2237 +1 x2238 +1 x2239 +1 x2240 +1 x2241 +1 x2242 +1 x2243 +1 x2244 +1 x2245 +1 x2246 +1 x2247 +1 x2248 +1 x2249 +1 x2250 +1 x2251 +1 x2252 +1 x2253 +1 x2254 +1 x2255 +1 x2256 +1 x2257 +1 x2258 +1 x2259 +1 x2260 +1 x2261 +1 x2262 +1 x2263 +1 x2264 +1 x2265 +1 x2266 +1 x2267 +1 x2268 +1 x2269 +1 x2270 +1 x2271 +1 x2272 +1 x2273 +1 x2274 +1 x2275 +1 x2276 +1 x2277 +1 x2278 +1 x2279 +1 x2280 +1 x2281 +1 x2282 +1 x2283 +1 x2284 +1 x2285 +1 x2286 +1 x2287 +1 x2288 +1 x2289 +1 x2290 +1 x2291 +1 x2292 +1 x2293 +1 x2294 +1 x2295 +1 x2296 +1 x2297 +1 x2298 +1 x2299 +1 x2300 +1 x2301 +1 x2302 +1 x2303 +1 x2304 +1 x4865 +1 x4866 +1 x4867 +1 x4868 +1 x4869 +1 x4870 +1 x4871 +1 x4872 +1 x4873 +1 x4874 +1 x4875 +1 x4876 +1 x4877 +1 x4878 +1 x4879 +1 x4880 +1 x4881 +1 x4882 +1 x4883 +1 x4884 +1 x4885 +1 x4886 +1 x4887 +1 x4888 +1 x4889 +1 x4890 +1 x4891 +1 x4892 +1 x4893 +1 x4894 +1 x4895 +1 x4896 +1 x4897 +1 x4898 +1 x4899 +1 x4900 +1 x4901 +1 x4902 +1 x4903 +1 x4904 +1 x4905 +1 x4906 +1 x4907 +1 x4908 +1 x4909 +1 x4910 +1 x4911 +1 x4912 +1 x4913 +1 x4914 +1 x4915 +1 x4916 +1 x4917 +1 x4918 +1 x4919 +1 x4920 +1 x4921 +1 x4922 +1 x4923 +1 x4924 +1 x4925 +1 x4926 +1 x4927 +1 x4928 +1 x4929 +1 x4930 +1 x4931 +1 x4932 +1 x4933 +1 x4934 +1 x4935 +1 x4936 +1 x4937 +1 x4938 +1 x4939 +1 x4940 +1 x4941 +1 x4942 +1 x4943 +1 x4944 +1 x4945 +1 x4946 +1 x4947 +1 x4948 +1 x4949 +1 x4950 +1 x4951 +1 x4952 +1 x4953 +1 x4954 +1 x4955 +1 x4956 +1 x4957 +1 x4958 +1 x4959 +1 x4960 +1 x4961 +1 x4962 +1 x4963 +1 x4964 +1 x4965 +1 x4966 +1 x4967 +1 x4968 +1 x4969 +1 x4970 +1 x4971 +1 x4972 +1 x4973 +1 x4974 +1 x4975 +1 x4976 +1 x4977 +1 x4978 +1 x4979 +1 x4980 +1 x4981 +1 x4982 +1 x4983 +1 x4984 +1 x4985 +1 x4986 +1 x4987 +1 x4988 +1 x4989 +1 x4990 +1 x4991 +1 x4992 = 0 ;+-2 x12811 +1 x2305 +1 x2306 +1 x2307 +1 x2308 +1 x2309 +1 x2310 +1 x2311 +1 x2312 +1 x2313 +1 x2314 +1 x2315 +1 x2316 +1 x2317 +1 x2318 +1 x2319 +1 x2320 +1 x2321 +1 x2322 +1 x2323 +1 x2324 +1 x2325 +1 x2326 +1 x2327 +1 x2328 +1 x2329 +1 x2330 +1 x2331 +1 x2332 +1 x2333 +1 x2334 +1 x2335 +1 x2336 +1 x2337 +1 x2338 +1 x2339 +1 x2340 +1 x2341 +1 x2342 +1 x2343 +1 x2344 +1 x2345 +1 x2346 +1 x2347 +1 x2348 +1 x2349 +1 x2350 +1 x2351 +1 x2352 +1 x2353 +1 x2354 +1 x2355 +1 x2356 +1 x2357 +1 x2358 +1 x2359 +1 x2360 +1 x2361 +1 x2362 +1 x2363 +1 x2364 +1 x2365 +1 x2366 +1 x2367 +1 x2368 +1 x2369 +1 x2370 +1 x2371 +1 x2372 +1 x2373 +1 x2374 +1 x2375 +1 x2376 +1 x2377 +1 x2378 +1 x2379 +1 x2380 +1 x2381 +1 x2382 +1 x2383 +1 x2384 +1 x2385 +1 x2386 +1 x2387 +1 x2388 +1 x2389 +1 x2390 +1 x2391 +1 x2392 +1 x2393 +1 x2394 +1 x2395 +1 x2396 +1 x2397 +1 x2398 +1 x2399 +1 x2400 +1 x2401 +1 x2402 +1 x2403 +1 x2404 +1 x2405 +1 x2406 +1 x2407 +1 x2408 +1 x2409 +1 x2410 +1 x2411 +1 x2412 +1 x2413 +1 x2414 +1 x2415 +1 x2416 +1 x2417 +1 x2418 +1 x2419 +1 x2420 +1 x2421 +1 x2422 +1 x2423 +1 x2424 +1 x2425 +1 x2426 +1 x2427 +1 x2428 +1 x2429 +1 x2430 +1 x2431 +1 x2432 +1 x2433 +1 x2434 +1 x2435 +1 x2436 +1 x2437 +1 x2438 +1 x2439 +1 x2440 +1 x2441 +1 x2442 +1 x2443 +1 x2444 +1 x2445 +1 x2446 +1 x2447 +1 x2448 +1 x2449 +1 x2450 +1 x2451 +1 x2452 +1 x2453 +1 x2454 +1 x2455 +1 x2456 +1 x2457 +1 x2458 +1 x2459 +1 x2460 +1 x2461 +1 x2462 +1 x2463 +1 x2464 +1 x2465 +1 x2466 +1 x2467 +1 x2468 +1 x2469 +1 x2470 +1 x2471 +1 x2472 +1 x2473 +1 x2474 +1 x2475 +1 x2476 +1 x2477 +1 x2478 +1 x2479 +1 x2480 +1 x2481 +1 x2482 +1 x2483 +1 x2484 +1 x2485 +1 x2486 +1 x2487 +1 x2488 +1 x2489 +1 x2490 +1 x2491 +1 x2492 +1 x2493 +1 x2494 +1 x2495 +1 x2496 +1 x2497 +1 x2498 +1 x2499 +1 x2500 +1 x2501 +1 x2502 +1 x2503 +1 x2504 +1 x2505 +1 x2506 +1 x2507 +1 x2508 +1 x2509 +1 x2510 +1 x2511 +1 x2512 +1 x2513 +1 x2514 +1 x2515 +1 x2516 +1 x2517 +1 x2518 +1 x2519 +1 x2520 +1 x2521 +1 x2522 +1 x2523 +1 x2524 +1 x2525 +1 x2526 +1 x2527 +1 x2528 +1 x2529 +1 x2530 +1 x2531 +1 x2532 +1 x2533 +1 x2534 +1 x2535 +1 x2536 +1 x2537 +1 x2538 +1 x2539 +1 x2540 +1 x2541 +1 x2542 +1 x2543 +1 x2544 +1 x2545 +1 x2546 +1 x2547 +1 x2548 +1 x2549 +1 x2550 +1 x2551 +1 x2552 +1 x2553 +1 x2554 +1 x2555 +1 x2556 +1 x2557 +1 x2558 +1 x2559 +1 x2560 +1 x2689 +1 x2690 +1 x2691 +1 x2692 +1 x2693 +1 x2694 +1 x2695 +1 x2696 +1 x2697 +1 x2698 +1 x2699 +1 x2700 +1 x2701 +1 x2702 +1 x2703 +1 x2704 +1 x2705 +1 x2706 +1 x2707 +1 x2708 +1 x2709 +1 x2710 +1 x2711 +1 x2712 +1 x2713 +1 x2714 +1 x2715 +1 x2716 +1 x2717 +1 x2718 +1 x2719 +1 x2720 +1 x2721 +1 x2722 +1 x2723 +1 x2724 +1 x2725 +1 x2726 +1 x2727 +1 x2728 +1 x2729 +1 x2730 +1 x2731 +1 x2732 +1 x2733 +1 x2734 +1 x2735 +1 x2736 +1 x2737 +1 x2738 +1 x2739 +1 x2740 +1 x2741 +1 x2742 +1 x2743 +1 x2744 +1 x2745 +1 x2746 +1 x2747 +1 x2748 +1 x2749 +1 x2750 +1 x2751 +1 x2752 +1 x2753 +1 x2754 +1 x2755 +1 x2756 +1 x2757 +1 x2758 +1 x2759 +1 x2760 +1 x2761 +1 x2762 +1 x2763 +1 x2764 +1 x2765 +1 x2766 +1 x2767 +1 x2768 +1 x2769 +1 x2770 +1 x2771 +1 x2772 +1 x2773 +1 x2774 +1 x2775 +1 x2776 +1 x2777 +1 x2778 +1 x2779 +1 x2780 +1 x2781 +1 x2782 +1 x2783 +1 x2784 +1 x2785 +1 x2786 +1 x2787 +1 x2788 +1 x2789 +1 x2790 +1 x2791 +1 x2792 +1 x2793 +1 x2794 +1 x2795 +1 x2796 +1 x2797 +1 x2798 +1 x2799 +1 x2800 +1 x2801 +1 x2802 +1 x2803 +1 x2804 +1 x2805 +1 x2806 +1 x2807 +1 x2808 +1 x2809 +1 x2810 +1 x2811 +1 x2812 +1 x2813 +1 x2814 +1 x2815 +1 x2816 +1 x2817 +1 x2818 +1 x2819 +1 x2820 +1 x2821 +1 x2822 +1 x2823 +1 x2824 +1 x2825 +1 x2826 +1 x2827 +1 x2828 +1 x2829 +1 x2830 +1 x2831 +1 x2832 +1 x2833 +1 x2834 +1 x2835 +1 x2836 +1 x2837 +1 x2838 +1 x2839 +1 x2840 +1 x2841 +1 x2842 +1 x2843 +1 x2844 +1 x2845 +1 x2846 +1 x2847 +1 x2848 +1 x2849 +1 x2850 +1 x2851 +1 x2852 +1 x2853 +1 x2854 +1 x2855 +1 x2856 +1 x2857 +1 x2858 +1 x2859 +1 x2860 +1 x2861 +1 x2862 +1 x2863 +1 x2864 +1 x2865 +1 x2866 +1 x2867 +1 x2868 +1 x2869 +1 x2870 +1 x2871 +1 x2872 +1 x2873 +1 x2874 +1 x2875 +1 x2876 +1 x2877 +1 x2878 +1 x2879 +1 x2880 +1 x2881 +1 x2882 +1 x2883 +1 x2884 +1 x2885 +1 x2886 +1 x2887 +1 x2888 +1 x2889 +1 x2890 +1 x2891 +1 x2892 +1 x2893 +1 x2894 +1 x2895 +1 x2896 +1 x2897 +1 x2898 +1 x2899 +1 x2900 +1 x2901 +1 x2902 +1 x2903 +1 x2904 +1 x2905 +1 x2906 +1 x2907 +1 x2908 +1 x2909 +1 x2910 +1 x2911 +1 x2912 +1 x2913 +1 x2914 +1 x2915 +1 x2916 +1 x2917 +1 x2918 +1 x2919 +1 x2920 +1 x2921 +1 x2922 +1 x2923 +1 x2924 +1 x2925 +1 x2926 +1 x2927 +1 x2928 +1 x2929 +1 x2930 +1 x2931 +1 x2932 +1 x2933 +1 x2934 +1 x2935 +1 x2936 +1 x2937 +1 x2938 +1 x2939 +1 x2940 +1 x2941 +1 x2942 +1 x2943 +1 x2944 +1 x5505 +1 x5506 +1 x5507 +1 x5508 +1 x5509 +1 x5510 +1 x5511 +1 x5512 +1 x5513 +1 x5514 +1 x5515 +1 x5516 +1 x5517 +1 x5518 +1 x5519 +1 x5520 +1 x5521 +1 x5522 +1 x5523 +1 x5524 +1 x5525 +1 x5526 +1 x5527 +1 x5528 +1 x5529 +1 x5530 +1 x5531 +1 x5532 +1 x5533 +1 x5534 +1 x5535 +1 x5536 +1 x5537 +1 x5538 +1 x5539 +1 x5540 +1 x5541 +1 x5542 +1 x5543 +1 x5544 +1 x5545 +1 x5546 +1 x5547 +1 x5548 +1 x5549 +1 x5550 +1 x5551 +1 x5552 +1 x5553 +1 x5554 +1 x5555 +1 x5556 +1 x5557 +1 x5558 +1 x5559 +1 x5560 +1 x5561 +1 x5562 +1 x5563 +1 x5564 +1 x5565 +1 x5566 +1 x5567 +1 x5568 +1 x5569 +1 x5570 +1 x5571 +1 x5572 +1 x5573 +1 x5574 +1 x5575 +1 x5576 +1 x5577 +1 x5578 +1 x5579 +1 x5580 +1 x5581 +1 x5582 +1 x5583 +1 x5584 +1 x5585 +1 x5586 +1 x5587 +1 x5588 +1 x5589 +1 x5590 +1 x5591 +1 x5592 +1 x5593 +1 x5594 +1 x5595 +1 x5596 +1 x5597 +1 x5598 +1 x5599 +1 x5600 +1 x5601 +1 x5602 +1 x5603 +1 x5604 +1 x5605 +1 x5606 +1 x5607 +1 x5608 +1 x5609 +1 x5610 +1 x5611 +1 x5612 +1 x5613 +1 x5614 +1 x5615 +1 x5616 +1 x5617 +1 x5618 +1 x5619 +1 x5620 +1 x5621 +1 x5622 +1 x5623 +1 x5624 +1 x5625 +1 x5626 +1 x5627 +1 x5628 +1 x5629 +1 x5630 +1 x5631 +1 x5632 +1 x6913 +1 x6914 +1 x6915 +1 x6916 +1 x6917 +1 x6918 +1 x6919 +1 x6920 +1 x6921 +1 x6922 +1 x6923 +1 x6924 +1 x6925 +1 x6926 +1 x6927 +1 x6928 +1 x6929 +1 x6930 +1 x6931 +1 x6932 +1 x6933 +1 x6934 +1 x6935 +1 x6936 +1 x6937 +1 x6938 +1 x6939 +1 x6940 +1 x6941 +1 x6942 +1 x6943 +1 x6944 +1 x6945 +1 x6946 +1 x6947 +1 x6948 +1 x6949 +1 x6950 +1 x6951 +1 x6952 +1 x6953 +1 x6954 +1 x6955 +1 x6956 +1 x6957 +1 x6958 +1 x6959 +1 x6960 +1 x6961 +1 x6962 +1 x6963 +1 x6964 +1 x6965 +1 x6966 +1 x6967 +1 x6968 +1 x6969 +1 x6970 +1 x6971 +1 x6972 +1 x6973 +1 x6974 +1 x6975 +1 x6976 +1 x6977 +1 x6978 +1 x6979 +1 x6980 +1 x6981 +1 x6982 +1 x6983 +1 x6984 +1 x6985 +1 x6986 +1 x6987 +1 x6988 +1 x6989 +1 x6990 +1 x6991 +1 x6992 +1 x6993 +1 x6994 +1 x6995 +1 x6996 +1 x6997 +1 x6998 +1 x6999 +1 x7000 +1 x7001 +1 x7002 +1 x7003 +1 x7004 +1 x7005 +1 x7006 +1 x7007 +1 x7008 +1 x7009 +1 x7010 +1 x7011 +1 x7012 +1 x7013 +1 x7014 +1 x7015 +1 x7016 +1 x7017 +1 x7018 +1 x7019 +1 x7020 +1 x7021 +1 x7022 +1 x7023 +1 x7024 +1 x7025 +1 x7026 +1 x7027 +1 x7028 +1 x7029 +1 x7030 +1 x7031 +1 x7032 +1 x7033 +1 x7034 +1 x7035 +1 x7036 +1 x7037 +1 x7038 +1 x7039 +1 x7040 +1 x10497 +1 x10498 +1 x10499 +1 x10500 +1 x10501 +1 x10502 +1 x10503 +1 x10504 +1 x10505 +1 x10506 +1 x10507 +1 x10508 +1 x10509 +1 x10510 +1 x10511 +1 x10512 +1 x10513 +1 x10514 +1 x10515 +1 x10516 +1 x10517 +1 x10518 +1 x10519 +1 x10520 +1 x10521 +1 x10522 +1 x10523 +1 x10524 +1 x10525 +1 x10526 +1 x10527 +1 x10528 +1 x10529 +1 x10530 +1 x10531 +1 x10532 +1 x10533 +1 x10534 +1 x10535 +1 x10536 +1 x10537 +1 x10538 +1 x10539 +1 x10540 +1 x10541 +1 x10542 +1 x10543 +1 x10544 +1 x10545 +1 x10546 +1 x10547 +1 x10548 +1 x10549 +1 x10550 +1 x10551 +1 x10552 +1 x10553 +1 x10554 +1 x10555 +1 x10556 +1 x10557 +1 x10558 +1 x10559 +1 x10560 +1 x10561 +1 x10562 +1 x10563 +1 x10564 +1 x10565 +1 x10566 +1 x10567 +1 x10568 +1 x10569 +1 x10570 +1 x10571 +1 x10572 +1 x10573 +1 x10574 +1 x10575 +1 x10576 +1 x10577 +1 x10578 +1 x10579 +1 x10580 +1 x10581 +1 x10582 +1 x10583 +1 x10584 +1 x10585 +1 x10586 +1 x10587 +1 x10588 +1 x10589 +1 x10590 +1 x10591 +1 x10592 +1 x10593 +1 x10594 +1 x10595 +1 x10596 +1 x10597 +1 x10598 +1 x10599 +1 x10600 +1 x10601 +1 x10602 +1 x10603 +1 x10604 +1 x10605 +1 x10606 +1 x10607 +1 x10608 +1 x10609 +1 x10610 +1 x10611 +1 x10612 +1 x10613 +1 x10614 +1 x10615 +1 x10616 +1 x10617 +1 x10618 +1 x10619 +1 x10620 +1 x10621 +1 x10622 +1 x10623 +1 x10624 = 0 ;+-2 x12812 +1 x2561 +1 x2562 +1 x2563 +1 x2564 +1 x2565 +1 x2566 +1 x2567 +1 x2568 +1 x2569 +1 x2570 +1 x2571 +1 x2572 +1 x2573 +1 x2574 +1 x2575 +1 x2576 +1 x2577 +1 x2578 +1 x2579 +1 x2580 +1 x2581 +1 x2582 +1 x2583 +1 x2584 +1 x2585 +1 x2586 +1 x2587 +1 x2588 +1 x2589 +1 x2590 +1 x2591 +1 x2592 +1 x2593 +1 x2594 +1 x2595 +1 x2596 +1 x2597 +1 x2598 +1 x2599 +1 x2600 +1 x2601 +1 x2602 +1 x2603 +1 x2604 +1 x2605 +1 x2606 +1 x2607 +1 x2608 +1 x2609 +1 x2610 +1 x2611 +1 x2612 +1 x2613 +1 x2614 +1 x2615 +1 x2616 +1 x2617 +1 x2618 +1 x2619 +1 x2620 +1 x2621 +1 x2622 +1 x2623 +1 x2624 +1 x2625 +1 x2626 +1 x2627 +1 x2628 +1 x2629 +1 x2630 +1 x2631 +1 x2632 +1 x2633 +1 x2634 +1 x2635 +1 x2636 +1 x2637 +1 x2638 +1 x2639 +1 x2640 +1 x2641 +1 x2642 +1 x2643 +1 x2644 +1 x2645 +1 x2646 +1 x2647 +1 x2648 +1 x2649 +1 x2650 +1 x2651 +1 x2652 +1 x2653 +1 x2654 +1 x2655 +1 x2656 +1 x2657 +1 x2658 +1 x2659 +1 x2660 +1 x2661 +1 x2662 +1 x2663 +1 x2664 +1 x2665 +1 x2666 +1 x2667 +1 x2668 +1 x2669 +1 x2670 +1 x2671 +1 x2672 +1 x2673 +1 x2674 +1 x2675 +1 x2676 +1 x2677 +1 x2678 +1 x2679 +1 x2680 +1 x2681 +1 x2682 +1 x2683 +1 x2684 +1 x2685 +1 x2686 +1 x2687 +1 x2688 +1 x2689 +1 x2690 +1 x2691 +1 x2692 +1 x2693 +1 x2694 +1 x2695 +1 x2696 +1 x2697 +1 x2698 +1 x2699 +1 x2700 +1 x2701 +1 x2702 +1 x2703 +1 x2704 +1 x2705 +1 x2706 +1 x2707 +1 x2708 +1 x2709 +1 x2710 +1 x2711 +1 x2712 +1 x2713 +1 x2714 +1 x2715 +1 x2716 +1 x2717 +1 x2718 +1 x2719 +1 x2720 +1 x2721 +1 x2722 +1 x2723 +1 x2724 +1 x2725 +1 x2726 +1 x2727 +1 x2728 +1 x2729 +1 x2730 +1 x2731 +1 x2732 +1 x2733 +1 x2734 +1 x2735 +1 x2736 +1 x2737 +1 x2738 +1 x2739 +1 x2740 +1 x2741 +1 x2742 +1 x2743 +1 x2744 +1 x2745 +1 x2746 +1 x2747 +1 x2748 +1 x2749 +1 x2750 +1 x2751 +1 x2752 +1 x2753 +1 x2754 +1 x2755 +1 x2756 +1 x2757 +1 x2758 +1 x2759 +1 x2760 +1 x2761 +1 x2762 +1 x2763 +1 x2764 +1 x2765 +1 x2766 +1 x2767 +1 x2768 +1 x2769 +1 x2770 +1 x2771 +1 x2772 +1 x2773 +1 x2774 +1 x2775 +1 x2776 +1 x2777 +1 x2778 +1 x2779 +1 x2780 +1 x2781 +1 x2782 +1 x2783 +1 x2784 +1 x2785 +1 x2786 +1 x2787 +1 x2788 +1 x2789 +1 x2790 +1 x2791 +1 x2792 +1 x2793 +1 x2794 +1 x2795 +1 x2796 +1 x2797 +1 x2798 +1 x2799 +1 x2800 +1 x2801 +1 x2802 +1 x2803 +1 x2804 +1 x2805 +1 x2806 +1 x2807 +1 x2808 +1 x2809 +1 x2810 +1 x2811 +1 x2812 +1 x2813 +1 x2814 +1 x2815 +1 x2816 +1 x3585 +1 x3586 +1 x3587 +1 x3588 +1 x3589 +1 x3590 +1 x3591 +1 x3592 +1 x3593 +1 x3594 +1 x3595 +1 x3596 +1 x3597 +1 x3598 +1 x3599 +1 x3600 +1 x3601 +1 x3602 +1 x3603 +1 x3604 +1 x3605 +1 x3606 +1 x3607 +1 x3608 +1 x3609 +1 x3610 +1 x3611 +1 x3612 +1 x3613 +1 x3614 +1 x3615 +1 x3616 +1 x3617 +1 x3618 +1 x3619 +1 x3620 +1 x3621 +1 x3622 +1 x3623 +1 x3624 +1 x3625 +1 x3626 +1 x3627 +1 x3628 +1 x3629 +1 x3630 +1 x3631 +1 x3632 +1 x3633 +1 x3634 +1 x3635 +1 x3636 +1 x3637 +1 x3638 +1 x3639 +1 x3640 +1 x3641 +1 x3642 +1 x3643 +1 x3644 +1 x3645 +1 x3646 +1 x3647 +1 x3648 +1 x3649 +1 x3650 +1 x3651 +1 x3652 +1 x3653 +1 x3654 +1 x3655 +1 x3656 +1 x3657 +1 x3658 +1 x3659 +1 x3660 +1 x3661 +1 x3662 +1 x3663 +1 x3664 +1 x3665 +1 x3666 +1 x3667 +1 x3668 +1 x3669 +1 x3670 +1 x3671 +1 x3672 +1 x3673 +1 x3674 +1 x3675 +1 x3676 +1 x3677 +1 x3678 +1 x3679 +1 x3680 +1 x3681 +1 x3682 +1 x3683 +1 x3684 +1 x3685 +1 x3686 +1 x3687 +1 x3688 +1 x3689 +1 x3690 +1 x3691 +1 x3692 +1 x3693 +1 x3694 +1 x3695 +1 x3696 +1 x3697 +1 x3698 +1 x3699 +1 x3700 +1 x3701 +1 x3702 +1 x3703 +1 x3704 +1 x3705 +1 x3706 +1 x3707 +1 x3708 +1 x3709 +1 x3710 +1 x3711 +1 x3712 +1 x4481 +1 x4482 +1 x4483 +1 x4484 +1 x4485 +1 x4486 +1 x4487 +1 x4488 +1 x4489 +1 x4490 +1 x4491 +1 x4492 +1 x4493 +1 x4494 +1 x4495 +1 x4496 +1 x4497 +1 x4498 +1 x4499 +1 x4500 +1 x4501 +1 x4502 +1 x4503 +1 x4504 +1 x4505 +1 x4506 +1 x4507 +1 x4508 +1 x4509 +1 x4510 +1 x4511 +1 x4512 +1 x4513 +1 x4514 +1 x4515 +1 x4516 +1 x4517 +1 x4518 +1 x4519 +1 x4520 +1 x4521 +1 x4522 +1 x4523 +1 x4524 +1 x4525 +1 x4526 +1 x4527 +1 x4528 +1 x4529 +1 x4530 +1 x4531 +1 x4532 +1 x4533 +1 x4534 +1 x4535 +1 x4536 +1 x4537 +1 x4538 +1 x4539 +1 x4540 +1 x4541 +1 x4542 +1 x4543 +1 x4544 +1 x4545 +1 x4546 +1 x4547 +1 x4548 +1 x4549 +1 x4550 +1 x4551 +1 x4552 +1 x4553 +1 x4554 +1 x4555 +1 x4556 +1 x4557 +1 x4558 +1 x4559 +1 x4560 +1 x4561 +1 x4562 +1 x4563 +1 x4564 +1 x4565 +1 x4566 +1 x4567 +1 x4568 +1 x4569 +1 x4570 +1 x4571 +1 x4572 +1 x4573 +1 x4574 +1 x4575 +1 x4576 +1 x4577 +1 x4578 +1 x4579 +1 x4580 +1 x4581 +1 x4582 +1 x4583 +1 x4584 +1 x4585 +1 x4586 +1 x4587 +1 x4588 +1 x4589 +1 x4590 +1 x4591 +1 x4592 +1 x4593 +1 x4594 +1 x4595 +1 x4596 +1 x4597 +1 x4598 +1 x4599 +1 x4600 +1 x4601 +1 x4602 +1 x4603 +1 x4604 +1 x4605 +1 x4606 +1 x4607 +1 x4608 +1 x6017 +1 x6018 +1 x6019 +1 x6020 +1 x6021 +1 x6022 +1 x6023 +1 x6024 +1 x6025 +1 x6026 +1 x6027 +1 x6028 +1 x6029 +1 x6030 +1 x6031 +1 x6032 +1 x6033 +1 x6034 +1 x6035 +1 x6036 +1 x6037 +1 x6038 +1 x6039 +1 x6040 +1 x6041 +1 x6042 +1 x6043 +1 x6044 +1 x6045 +1 x6046 +1 x6047 +1 x6048 +1 x6049 +1 x6050 +1 x6051 +1 x6052 +1 x6053 +1 x6054 +1 x6055 +1 x6056 +1 x6057 +1 x6058 +1 x6059 +1 x6060 +1 x6061 +1 x6062 +1 x6063 +1 x6064 +1 x6065 +1 x6066 +1 x6067 +1 x6068 +1 x6069 +1 x6070 +1 x6071 +1 x6072 +1 x6073 +1 x6074 +1 x6075 +1 x6076 +1 x6077 +1 x6078 +1 x6079 +1 x6080 +1 x6081 +1 x6082 +1 x6083 +1 x6084 +1 x6085 +1 x6086 +1 x6087 +1 x6088 +1 x6089 +1 x6090 +1 x6091 +1 x6092 +1 x6093 +1 x6094 +1 x6095 +1 x6096 +1 x6097 +1 x6098 +1 x6099 +1 x6100 +1 x6101 +1 x6102 +1 x6103 +1 x6104 +1 x6105 +1 x6106 +1 x6107 +1 x6108 +1 x6109 +1 x6110 +1 x6111 +1 x6112 +1 x6113 +1 x6114 +1 x6115 +1 x6116 +1 x6117 +1 x6118 +1 x6119 +1 x6120 +1 x6121 +1 x6122 +1 x6123 +1 x6124 +1 x6125 +1 x6126 +1 x6127 +1 x6128 +1 x6129 +1 x6130 +1 x6131 +1 x6132 +1 x6133 +1 x6134 +1 x6135 +1 x6136 +1 x6137 +1 x6138 +1 x6139 +1 x6140 +1 x6141 +1 x6142 +1 x6143 +1 x6144 +1 x8833 +1 x8834 +1 x8835 +1 x8836 +1 x8837 +1 x8838 +1 x8839 +1 x8840 +1 x8841 +1 x8842 +1 x8843 +1 x8844 +1 x8845 +1 x8846 +1 x8847 +1 x8848 +1 x8849 +1 x8850 +1 x8851 +1 x8852 +1 x8853 +1 x8854 +1 x8855 +1 x8856 +1 x8857 +1 x8858 +1 x8859 +1 x8860 +1 x8861 +1 x8862 +1 x8863 +1 x8864 +1 x8865 +1 x8866 +1 x8867 +1 x8868 +1 x8869 +1 x8870 +1 x8871 +1 x8872 +1 x8873 +1 x8874 +1 x8875 +1 x8876 +1 x8877 +1 x8878 +1 x8879 +1 x8880 +1 x8881 +1 x8882 +1 x8883 +1 x8884 +1 x8885 +1 x8886 +1 x8887 +1 x8888 +1 x8889 +1 x8890 +1 x8891 +1 x8892 +1 x8893 +1 x8894 +1 x8895 +1 x8896 +1 x8897 +1 x8898 +1 x8899 +1 x8900 +1 x8901 +1 x8902 +1 x8903 +1 x8904 +1 x8905 +1 x8906 +1 x8907 +1 x8908 +1 x8909 +1 x8910 +1 x8911 +1 x8912 +1 x8913 +1 x8914 +1 x8915 +1 x8916 +1 x8917 +1 x8918 +1 x8919 +1 x8920 +1 x8921 +1 x8922 +1 x8923 +1 x8924 +1 x8925 +1 x8926 +1 x8927 +1 x8928 +1 x8929 +1 x8930 +1 x8931 +1 x8932 +1 x8933 +1 x8934 +1 x8935 +1 x8936 +1 x8937 +1 x8938 +1 x8939 +1 x8940 +1 x8941 +1 x8942 +1 x8943 +1 x8944 +1 x8945 +1 x8946 +1 x8947 +1 x8948 +1 x8949 +1 x8950 +1 x8951 +1 x8952 +1 x8953 +1 x8954 +1 x8955 +1 x8956 +1 x8957 +1 x8958 +1 x8959 +1 x8960 +1 x9473 +1 x9474 +1 x9475 +1 x9476 +1 x9477 +1 x9478 +1 x9479 +1 x9480 +1 x9481 +1 x9482 +1 x9483 +1 x9484 +1 x9485 +1 x9486 +1 x9487 +1 x9488 +1 x9489 +1 x9490 +1 x9491 +1 x9492 +1 x9493 +1 x9494 +1 x9495 +1 x9496 +1 x9497 +1 x9498 +1 x9499 +1 x9500 +1 x9501 +1 x9502 +1 x9503 +1 x9504 +1 x9505 +1 x9506 +1 x9507 +1 x9508 +1 x9509 +1 x9510 +1 x9511 +1 x9512 +1 x9513 +1 x9514 +1 x9515 +1 x9516 +1 x9517 +1 x9518 +1 x9519 +1 x9520 +1 x9521 +1 x9522 +1 x9523 +1 x9524 +1 x9525 +1 x9526 +1 x9527 +1 x9528 +1 x9529 +1 x9530 +1 x9531 +1 x9532 +1 x9533 +1 x9534 +1 x9535 +1 x9536 +1 x9537 +1 x9538 +1 x9539 +1 x9540 +1 x9541 +1 x9542 +1 x9543 +1 x9544 +1 x9545 +1 x9546 +1 x9547 +1 x9548 +1 x9549 +1 x9550 +1 x9551 +1 x9552 +1 x9553 +1 x9554 +1 x9555 +1 x9556 +1 x9557 +1 x9558 +1 x9559 +1 x9560 +1 x9561 +1 x9562 +1 x9563 +1 x9564 +1 x9565 +1 x9566 +1 x9567 +1 x9568 +1 x9569 +1 x9570 +1 x9571 +1 x9572 +1 x9573 +1 x9574 +1 x9575 +1 x9576 +1 x9577 +1 x9578 +1 x9579 +1 x9580 +1 x9581 +1 x9582 +1 x9583 +1 x9584 +1 x9585 +1 x9586 +1 x9587 +1 x9588 +1 x9589 +1 x9590 +1 x9591 +1 x9592 +1 x9593 +1 x9594 +1 x9595 +1 x9596 +1 x9597 +1 x9598 +1 x9599 +1 x9600 +1 x9857 +1 x9858 +1 x9859 +1 x9860 +1 x9861 +1 x9862 +1 x9863 +1 x9864 +1 x9865 +1 x9866 +1 x9867 +1 x9868 +1 x9869 +1 x9870 +1 x9871 +1 x9872 +1 x9873 +1 x9874 +1 x9875 +1 x9876 +1 x9877 +1 x9878 +1 x9879 +1 x9880 +1 x9881 +1 x9882 +1 x9883 +1 x9884 +1 x9885 +1 x9886 +1 x9887 +1 x9888 +1 x9889 +1 x9890 +1 x9891 +1 x9892 +1 x9893 +1 x9894 +1 x9895 +1 x9896 +1 x9897 +1 x9898 +1 x9899 +1 x9900 +1 x9901 +1 x9902 +1 x9903 +1 x9904 +1 x9905 +1 x9906 +1 x9907 +1 x9908 +1 x9909 +1 x9910 +1 x9911 +1 x9912 +1 x9913 +1 x9914 +1 x9915 +1 x9916 +1 x9917 +1 x9918 +1 x9919 +1 x9920 +1 x9921 +1 x9922 +1 x9923 +1 x9924 +1 x9925 +1 x9926 +1 x9927 +1 x9928 +1 x9929 +1 x9930 +1 x9931 +1 x9932 +1 x9933 +1 x9934 +1 x9935 +1 x9936 +1 x9937 +1 x9938 +1 x9939 +1 x9940 +1 x9941 +1 x9942 +1 x9943 +1 x9944 +1 x9945 +1 x9946 +1 x9947 +1 x9948 +1 x9949 +1 x9950 +1 x9951 +1 x9952 +1 x9953 +1 x9954 +1 x9955 +1 x9956 +1 x9957 +1 x9958 +1 x9959 +1 x9960 +1 x9961 +1 x9962 +1 x9963 +1 x9964 +1 x9965 +1 x9966 +1 x9967 +1 x9968 +1 x9969 +1 x9970 +1 x9971 +1 x9972 +1 x9973 +1 x9974 +1 x9975 +1 x9976 +1 x9977 +1 x9978 +1 x9979 +1 x9980 +1 x9981 +1 x9982 +1 x9983 +1 x9984 = 0 ;+-2 x12813 +1 x2817 +1 x2818 +1 x2819 +1 x2820 +1 x2821 +1 x2822 +1 x2823 +1 x2824 +1 x2825 +1 x2826 +1 x2827 +1 x2828 +1 x2829 +1 x2830 +1 x2831 +1 x2832 +1 x2833 +1 x2834 +1 x2835 +1 x2836 +1 x2837 +1 x2838 +1 x2839 +1 x2840 +1 x2841 +1 x2842 +1 x2843 +1 x2844 +1 x2845 +1 x2846 +1 x2847 +1 x2848 +1 x2849 +1 x2850 +1 x2851 +1 x2852 +1 x2853 +1 x2854 +1 x2855 +1 x2856 +1 x2857 +1 x2858 +1 x2859 +1 x2860 +1 x2861 +1 x2862 +1 x2863 +1 x2864 +1 x2865 +1 x2866 +1 x2867 +1 x2868 +1 x2869 +1 x2870 +1 x2871 +1 x2872 +1 x2873 +1 x2874 +1 x2875 +1 x2876 +1 x2877 +1 x2878 +1 x2879 +1 x2880 +1 x2881 +1 x2882 +1 x2883 +1 x2884 +1 x2885 +1 x2886 +1 x2887 +1 x2888 +1 x2889 +1 x2890 +1 x2891 +1 x2892 +1 x2893 +1 x2894 +1 x2895 +1 x2896 +1 x2897 +1 x2898 +1 x2899 +1 x2900 +1 x2901 +1 x2902 +1 x2903 +1 x2904 +1 x2905 +1 x2906 +1 x2907 +1 x2908 +1 x2909 +1 x2910 +1 x2911 +1 x2912 +1 x2913 +1 x2914 +1 x2915 +1 x2916 +1 x2917 +1 x2918 +1 x2919 +1 x2920 +1 x2921 +1 x2922 +1 x2923 +1 x2924 +1 x2925 +1 x2926 +1 x2927 +1 x2928 +1 x2929 +1 x2930 +1 x2931 +1 x2932 +1 x2933 +1 x2934 +1 x2935 +1 x2936 +1 x2937 +1 x2938 +1 x2939 +1 x2940 +1 x2941 +1 x2942 +1 x2943 +1 x2944 +1 x2945 +1 x2946 +1 x2947 +1 x2948 +1 x2949 +1 x2950 +1 x2951 +1 x2952 +1 x2953 +1 x2954 +1 x2955 +1 x2956 +1 x2957 +1 x2958 +1 x2959 +1 x2960 +1 x2961 +1 x2962 +1 x2963 +1 x2964 +1 x2965 +1 x2966 +1 x2967 +1 x2968 +1 x2969 +1 x2970 +1 x2971 +1 x2972 +1 x2973 +1 x2974 +1 x2975 +1 x2976 +1 x2977 +1 x2978 +1 x2979 +1 x2980 +1 x2981 +1 x2982 +1 x2983 +1 x2984 +1 x2985 +1 x2986 +1 x2987 +1 x2988 +1 x2989 +1 x2990 +1 x2991 +1 x2992 +1 x2993 +1 x2994 +1 x2995 +1 x2996 +1 x2997 +1 x2998 +1 x2999 +1 x3000 +1 x3001 +1 x3002 +1 x3003 +1 x3004 +1 x3005 +1 x3006 +1 x3007 +1 x3008 +1 x3009 +1 x3010 +1 x3011 +1 x3012 +1 x3013 +1 x3014 +1 x3015 +1 x3016 +1 x3017 +1 x3018 +1 x3019 +1 x3020 +1 x3021 +1 x3022 +1 x3023 +1 x3024 +1 x3025 +1 x3026 +1 x3027 +1 x3028 +1 x3029 +1 x3030 +1 x3031 +1 x3032 +1 x3033 +1 x3034 +1 x3035 +1 x3036 +1 x3037 +1 x3038 +1 x3039 +1 x3040 +1 x3041 +1 x3042 +1 x3043 +1 x3044 +1 x3045 +1 x3046 +1 x3047 +1 x3048 +1 x3049 +1 x3050 +1 x3051 +1 x3052 +1 x3053 +1 x3054 +1 x3055 +1 x3056 +1 x3057 +1 x3058 +1 x3059 +1 x3060 +1 x3061 +1 x3062 +1 x3063 +1 x3064 +1 x3065 +1 x3066 +1 x3067 +1 x3068 +1 x3069 +1 x3070 +1 x3071 +1 x3072 +1 x3329 +1 x3330 +1 x3331 +1 x3332 +1 x3333 +1 x3334 +1 x3335 +1 x3336 +1 x3337 +1 x3338 +1 x3339 +1 x3340 +1 x3341 +1 x3342 +1 x3343 +1 x3344 +1 x3345 +1 x3346 +1 x3347 +1 x3348 +1 x3349 +1 x3350 +1 x3351 +1 x3352 +1 x3353 +1 x3354 +1 x3355 +1 x3356 +1 x3357 +1 x3358 +1 x3359 +1 x3360 +1 x3361 +1 x3362 +1 x3363 +1 x3364 +1 x3365 +1 x3366 +1 x3367 +1 x3368 +1 x3369 +1 x3370 +1 x3371 +1 x3372 +1 x3373 +1 x3374 +1 x3375 +1 x3376 +1 x3377 +1 x3378 +1 x3379 +1 x3380 +1 x3381 +1 x3382 +1 x3383 +1 x3384 +1 x3385 +1 x3386 +1 x3387 +1 x3388 +1 x3389 +1 x3390 +1 x3391 +1 x3392 +1 x3393 +1 x3394 +1 x3395 +1 x3396 +1 x3397 +1 x3398 +1 x3399 +1 x3400 +1 x3401 +1 x3402 +1 x3403 +1 x3404 +1 x3405 +1 x3406 +1 x3407 +1 x3408 +1 x3409 +1 x3410 +1 x3411 +1 x3412 +1 x3413 +1 x3414 +1 x3415 +1 x3416 +1 x3417 +1 x3418 +1 x3419 +1 x3420 +1 x3421 +1 x3422 +1 x3423 +1 x3424 +1 x3425 +1 x3426 +1 x3427 +1 x3428 +1 x3429 +1 x3430 +1 x3431 +1 x3432 +1 x3433 +1 x3434 +1 x3435 +1 x3436 +1 x3437 +1 x3438 +1 x3439 +1 x3440 +1 x3441 +1 x3442 +1 x3443 +1 x3444 +1 x3445 +1 x3446 +1 x3447 +1 x3448 +1 x3449 +1 x3450 +1 x3451 +1 x3452 +1 x3453 +1 x3454 +1 x3455 +1 x3456 +1 x8705 +1 x8706 +1 x8707 +1 x8708 +1 x8709 +1 x8710 +1 x8711 +1 x8712 +1 x8713 +1 x8714 +1 x8715 +1 x8716 +1 x8717 +1 x8718 +1 x8719 +1 x8720 +1 x8721 +1 x8722 +1 x8723 +1 x8724 +1 x8725 +1 x8726 +1 x8727 +1 x8728 +1 x8729 +1 x8730 +1 x8731 +1 x8732 +1 x8733 +1 x8734 +1 x8735 +1 x8736 +1 x8737 +1 x8738 +1 x8739 +1 x8740 +1 x8741 +1 x8742 +1 x8743 +1 x8744 +1 x8745 +1 x8746 +1 x8747 +1 x8748 +1 x8749 +1 x8750 +1 x8751 +1 x8752 +1 x8753 +1 x8754 +1 x8755 +1 x8756 +1 x8757 +1 x8758 +1 x8759 +1 x8760 +1 x8761 +1 x8762 +1 x8763 +1 x8764 +1 x8765 +1 x8766 +1 x8767 +1 x8768 +1 x8769 +1 x8770 +1 x8771 +1 x8772 +1 x8773 +1 x8774 +1 x8775 +1 x8776 +1 x8777 +1 x8778 +1 x8779 +1 x8780 +1 x8781 +1 x8782 +1 x8783 +1 x8784 +1 x8785 +1 x8786 +1 x8787 +1 x8788 +1 x8789 +1 x8790 +1 x8791 +1 x8792 +1 x8793 +1 x8794 +1 x8795 +1 x8796 +1 x8797 +1 x8798 +1 x8799 +1 x8800 +1 x8801 +1 x8802 +1 x8803 +1 x8804 +1 x8805 +1 x8806 +1 x8807 +1 x8808 +1 x8809 +1 x8810 +1 x8811 +1 x8812 +1 x8813 +1 x8814 +1 x8815 +1 x8816 +1 x8817 +1 x8818 +1 x8819 +1 x8820 +1 x8821 +1 x8822 +1 x8823 +1 x8824 +1 x8825 +1 x8826 +1 x8827 +1 x8828 +1 x8829 +1 x8830 +1 x8831 +1 x8832 = 0 ;+-2 x12814 +1 x3073 +1 x3074 +1 x3075 +1 x3076 +1 x3077 +1 x3078 +1 x3079 +1 x3080 +1 x3081 +1 x3082 +1 x3083 +1 x3084 +1 x3085 +1 x3086 +1 x3087 +1 x3088 +1 x3089 +1 x3090 +1 x3091 +1 x3092 +1 x3093 +1 x3094 +1 x3095 +1 x3096 +1 x3097 +1 x3098 +1 x3099 +1 x3100 +1 x3101 +1 x3102 +1 x3103 +1 x3104 +1 x3105 +1 x3106 +1 x3107 +1 x3108 +1 x3109 +1 x3110 +1 x3111 +1 x3112 +1 x3113 +1 x3114 +1 x3115 +1 x3116 +1 x3117 +1 x3118 +1 x3119 +1 x3120 +1 x3121 +1 x3122 +1 x3123 +1 x3124 +1 x3125 +1 x3126 +1 x3127 +1 x3128 +1 x3129 +1 x3130 +1 x3131 +1 x3132 +1 x3133 +1 x3134 +1 x3135 +1 x3136 +1 x3137 +1 x3138 +1 x3139 +1 x3140 +1 x3141 +1 x3142 +1 x3143 +1 x3144 +1 x3145 +1 x3146 +1 x3147 +1 x3148 +1 x3149 +1 x3150 +1 x3151 +1 x3152 +1 x3153 +1 x3154 +1 x3155 +1 x3156 +1 x3157 +1 x3158 +1 x3159 +1 x3160 +1 x3161 +1 x3162 +1 x3163 +1 x3164 +1 x3165 +1 x3166 +1 x3167 +1 x3168 +1 x3169 +1 x3170 +1 x3171 +1 x3172 +1 x3173 +1 x3174 +1 x3175 +1 x3176 +1 x3177 +1 x3178 +1 x3179 +1 x3180 +1 x3181 +1 x3182 +1 x3183 +1 x3184 +1 x3185 +1 x3186 +1 x3187 +1 x3188 +1 x3189 +1 x3190 +1 x3191 +1 x3192 +1 x3193 +1 x3194 +1 x3195 +1 x3196 +1 x3197 +1 x3198 +1 x3199 +1 x3200 +1 x3201 +1 x3202 +1 x3203 +1 x3204 +1 x3205 +1 x3206 +1 x3207 +1 x3208 +1 x3209 +1 x3210 +1 x3211 +1 x3212 +1 x3213 +1 x3214 +1 x3215 +1 x3216 +1 x3217 +1 x3218 +1 x3219 +1 x3220 +1 x3221 +1 x3222 +1 x3223 +1 x3224 +1 x3225 +1 x3226 +1 x3227 +1 x3228 +1 x3229 +1 x3230 +1 x3231 +1 x3232 +1 x3233 +1 x3234 +1 x3235 +1 x3236 +1 x3237 +1 x3238 +1 x3239 +1 x3240 +1 x3241 +1 x3242 +1 x3243 +1 x3244 +1 x3245 +1 x3246 +1 x3247 +1 x3248 +1 x3249 +1 x3250 +1 x3251 +1 x3252 +1 x3253 +1 x3254 +1 x3255 +1 x3256 +1 x3257 +1 x3258 +1 x3259 +1 x3260 +1 x3261 +1 x3262 +1 x3263 +1 x3264 +1 x3265 +1 x3266 +1 x3267 +1 x3268 +1 x3269 +1 x3270 +1 x3271 +1 x3272 +1 x3273 +1 x3274 +1 x3275 +1 x3276 +1 x3277 +1 x3278 +1 x3279 +1 x3280 +1 x3281 +1 x3282 +1 x3283 +1 x3284 +1 x3285 +1 x3286 +1 x3287 +1 x3288 +1 x3289 +1 x3290 +1 x3291 +1 x3292 +1 x3293 +1 x3294 +1 x3295 +1 x3296 +1 x3297 +1 x3298 +1 x3299 +1 x3300 +1 x3301 +1 x3302 +1 x3303 +1 x3304 +1 x3305 +1 x3306 +1 x3307 +1 x3308 +1 x3309 +1 x3310 +1 x3311 +1 x3312 +1 x3313 +1 x3314 +1 x3315 +1 x3316 +1 x3317 +1 x3318 +1 x3319 +1 x3320 +1 x3321 +1 x3322 +1 x3323 +1 x3324 +1 x3325 +1 x3326 +1 x3327 +1 x3328 +1 x5249 +1 x5250 +1 x5251 +1 x5252 +1 x5253 +1 x5254 +1 x5255 +1 x5256 +1 x5257 +1 x5258 +1 x5259 +1 x5260 +1 x5261 +1 x5262 +1 x5263 +1 x5264 +1 x5265 +1 x5266 +1 x5267 +1 x5268 +1 x5269 +1 x5270 +1 x5271 +1 x5272 +1 x5273 +1 x5274 +1 x5275 +1 x5276 +1 x5277 +1 x5278 +1 x5279 +1 x5280 +1 x5281 +1 x5282 +1 x5283 +1 x5284 +1 x5285 +1 x5286 +1 x5287 +1 x5288 +1 x5289 +1 x5290 +1 x5291 +1 x5292 +1 x5293 +1 x5294 +1 x5295 +1 x5296 +1 x5297 +1 x5298 +1 x5299 +1 x5300 +1 x5301 +1 x5302 +1 x5303 +1 x5304 +1 x5305 +1 x5306 +1 x5307 +1 x5308 +1 x5309 +1 x5310 +1 x5311 +1 x5312 +1 x5313 +1 x5314 +1 x5315 +1 x5316 +1 x5317 +1 x5318 +1 x5319 +1 x5320 +1 x5321 +1 x5322 +1 x5323 +1 x5324 +1 x5325 +1 x5326 +1 x5327 +1 x5328 +1 x5329 +1 x5330 +1 x5331 +1 x5332 +1 x5333 +1 x5334 +1 x5335 +1 x5336 +1 x5337 +1 x5338 +1 x5339 +1 x5340 +1 x5341 +1 x5342 +1 x5343 +1 x5344 +1 x5345 +1 x5346 +1 x5347 +1 x5348 +1 x5349 +1 x5350 +1 x5351 +1 x5352 +1 x5353 +1 x5354 +1 x5355 +1 x5356 +1 x5357 +1 x5358 +1 x5359 +1 x5360 +1 x5361 +1 x5362 +1 x5363 +1 x5364 +1 x5365 +1 x5366 +1 x5367 +1 x5368 +1 x5369 +1 x5370 +1 x5371 +1 x5372 +1 x5373 +1 x5374 +1 x5375 +1 x5376 = 0 ;+-2 x12815 +1 x3329 +1 x3330 +1 x3331 +1 x3332 +1 x3333 +1 x3334 +1 x3335 +1 x3336 +1 x3337 +1 x3338 +1 x3339 +1 x3340 +1 x3341 +1 x3342 +1 x3343 +1 x3344 +1 x3345 +1 x3346 +1 x3347 +1 x3348 +1 x3349 +1 x3350 +1 x3351 +1 x3352 +1 x3353 +1 x3354 +1 x3355 +1 x3356 +1 x3357 +1 x3358 +1 x3359 +1 x3360 +1 x3361 +1 x3362 +1 x3363 +1 x3364 +1 x3365 +1 x3366 +1 x3367 +1 x3368 +1 x3369 +1 x3370 +1 x3371 +1 x3372 +1 x3373 +1 x3374 +1 x3375 +1 x3376 +1 x3377 +1 x3378 +1 x3379 +1 x3380 +1 x3381 +1 x3382 +1 x3383 +1 x3384 +1 x3385 +1 x3386 +1 x3387 +1 x3388 +1 x3389 +1 x3390 +1 x3391 +1 x3392 +1 x3393 +1 x3394 +1 x3395 +1 x3396 +1 x3397 +1 x3398 +1 x3399 +1 x3400 +1 x3401 +1 x3402 +1 x3403 +1 x3404 +1 x3405 +1 x3406 +1 x3407 +1 x3408 +1 x3409 +1 x3410 +1 x3411 +1 x3412 +1 x3413 +1 x3414 +1 x3415 +1 x3416 +1 x3417 +1 x3418 +1 x3419 +1 x3420 +1 x3421 +1 x3422 +1 x3423 +1 x3424 +1 x3425 +1 x3426 +1 x3427 +1 x3428 +1 x3429 +1 x3430 +1 x3431 +1 x3432 +1 x3433 +1 x3434 +1 x3435 +1 x3436 +1 x3437 +1 x3438 +1 x3439 +1 x3440 +1 x3441 +1 x3442 +1 x3443 +1 x3444 +1 x3445 +1 x3446 +1 x3447 +1 x3448 +1 x3449 +1 x3450 +1 x3451 +1 x3452 +1 x3453 +1 x3454 +1 x3455 +1 x3456 +1 x3457 +1 x3458 +1 x3459 +1 x3460 +1 x3461 +1 x3462 +1 x3463 +1 x3464 +1 x3465 +1 x3466 +1 x3467 +1 x3468 +1 x3469 +1 x3470 +1 x3471 +1 x3472 +1 x3473 +1 x3474 +1 x3475 +1 x3476 +1 x3477 +1 x3478 +1 x3479 +1 x3480 +1 x3481 +1 x3482 +1 x3483 +1 x3484 +1 x3485 +1 x3486 +1 x3487 +1 x3488 +1 x3489 +1 x3490 +1 x3491 +1 x3492 +1 x3493 +1 x3494 +1 x3495 +1 x3496 +1 x3497 +1 x3498 +1 x3499 +1 x3500 +1 x3501 +1 x3502 +1 x3503 +1 x3504 +1 x3505 +1 x3506 +1 x3507 +1 x3508 +1 x3509 +1 x3510 +1 x3511 +1 x3512 +1 x3513 +1 x3514 +1 x3515 +1 x3516 +1 x3517 +1 x3518 +1 x3519 +1 x3520 +1 x3521 +1 x3522 +1 x3523 +1 x3524 +1 x3525 +1 x3526 +1 x3527 +1 x3528 +1 x3529 +1 x3530 +1 x3531 +1 x3532 +1 x3533 +1 x3534 +1 x3535 +1 x3536 +1 x3537 +1 x3538 +1 x3539 +1 x3540 +1 x3541 +1 x3542 +1 x3543 +1 x3544 +1 x3545 +1 x3546 +1 x3547 +1 x3548 +1 x3549 +1 x3550 +1 x3551 +1 x3552 +1 x3553 +1 x3554 +1 x3555 +1 x3556 +1 x3557 +1 x3558 +1 x3559 +1 x3560 +1 x3561 +1 x3562 +1 x3563 +1 x3564 +1 x3565 +1 x3566 +1 x3567 +1 x3568 +1 x3569 +1 x3570 +1 x3571 +1 x3572 +1 x3573 +1 x3574 +1 x3575 +1 x3576 +1 x3577 +1 x3578 +1 x3579 +1 x3580 +1 x3581 +1 x3582 +1 x3583 +1 x3584 +1 x5633 +1 x5634 +1 x5635 +1 x5636 +1 x5637 +1 x5638 +1 x5639 +1 x5640 +1 x5641 +1 x5642 +1 x5643 +1 x5644 +1 x5645 +1 x5646 +1 x5647 +1 x5648 +1 x5649 +1 x5650 +1 x5651 +1 x5652 +1 x5653 +1 x5654 +1 x5655 +1 x5656 +1 x5657 +1 x5658 +1 x5659 +1 x5660 +1 x5661 +1 x5662 +1 x5663 +1 x5664 +1 x5665 +1 x5666 +1 x5667 +1 x5668 +1 x5669 +1 x5670 +1 x5671 +1 x5672 +1 x5673 +1 x5674 +1 x5675 +1 x5676 +1 x5677 +1 x5678 +1 x5679 +1 x5680 +1 x5681 +1 x5682 +1 x5683 +1 x5684 +1 x5685 +1 x5686 +1 x5687 +1 x5688 +1 x5689 +1 x5690 +1 x5691 +1 x5692 +1 x5693 +1 x5694 +1 x5695 +1 x5696 +1 x5697 +1 x5698 +1 x5699 +1 x5700 +1 x5701 +1 x5702 +1 x5703 +1 x5704 +1 x5705 +1 x5706 +1 x5707 +1 x5708 +1 x5709 +1 x5710 +1 x5711 +1 x5712 +1 x5713 +1 x5714 +1 x5715 +1 x5716 +1 x5717 +1 x5718 +1 x5719 +1 x5720 +1 x5721 +1 x5722 +1 x5723 +1 x5724 +1 x5725 +1 x5726 +1 x5727 +1 x5728 +1 x5729 +1 x5730 +1 x5731 +1 x5732 +1 x5733 +1 x5734 +1 x5735 +1 x5736 +1 x5737 +1 x5738 +1 x5739 +1 x5740 +1 x5741 +1 x5742 +1 x5743 +1 x5744 +1 x5745 +1 x5746 +1 x5747 +1 x5748 +1 x5749 +1 x5750 +1 x5751 +1 x5752 +1 x5753 +1 x5754 +1 x5755 +1 x5756 +1 x5757 +1 x5758 +1 x5759 +1 x5760 +1 x12417 +1 x12418 +1 x12419 +1 x12420 +1 x12421 +1 x12422 +1 x12423 +1 x12424 +1 x12425 +1 x12426 +1 x12427 +1 x12428 +1 x12429 +1 x12430 +1 x12431 +1 x12432 +1 x12433 +1 x12434 +1 x12435 +1 x12436 +1 x12437 +1 x12438 +1 x12439 +1 x12440 +1 x12441 +1 x12442 +1 x12443 +1 x12444 +1 x12445 +1 x12446 +1 x12447 +1 x12448 +1 x12449 +1 x12450 +1 x12451 +1 x12452 +1 x12453 +1 x12454 +1 x12455 +1 x12456 +1 x12457 +1 x12458 +1 x12459 +1 x12460 +1 x12461 +1 x12462 +1 x12463 +1 x12464 +1 x12465 +1 x12466 +1 x12467 +1 x12468 +1 x12469 +1 x12470 +1 x12471 +1 x12472 +1 x12473 +1 x12474 +1 x12475 +1 x12476 +1 x12477 +1 x12478 +1 x12479 +1 x12480 +1 x12481 +1 x12482 +1 x12483 +1 x12484 +1 x12485 +1 x12486 +1 x12487 +1 x12488 +1 x12489 +1 x12490 +1 x12491 +1 x12492 +1 x12493 +1 x12494 +1 x12495 +1 x12496 +1 x12497 +1 x12498 +1 x12499 +1 x12500 +1 x12501 +1 x12502 +1 x12503 +1 x12504 +1 x12505 +1 x12506 +1 x12507 +1 x12508 +1 x12509 +1 x12510 +1 x12511 +1 x12512 +1 x12513 +1 x12514 +1 x12515 +1 x12516 +1 x12517 +1 x12518 +1 x12519 +1 x12520 +1 x12521 +1 x12522 +1 x12523 +1 x12524 +1 x12525 +1 x12526 +1 x12527 +1 x12528 +1 x12529 +1 x12530 +1 x12531 +1 x12532 +1 x12533 +1 x12534 +1 x12535 +1 x12536 +1 x12537 +1 x12538 +1 x12539 +1 x12540 +1 x12541 +1 x12542 +1 x12543 +1 x12544 = 0 ;+-2 x12816 +1 x3585 +1 x3586 +1 x3587 +1 x3588 +1 x3589 +1 x3590 +1 x3591 +1 x3592 +1 x3593 +1 x3594 +1 x3595 +1 x3596 +1 x3597 +1 x3598 +1 x3599 +1 x3600 +1 x3601 +1 x3602 +1 x3603 +1 x3604 +1 x3605 +1 x3606 +1 x3607 +1 x3608 +1 x3609 +1 x3610 +1 x3611 +1 x3612 +1 x3613 +1 x3614 +1 x3615 +1 x3616 +1 x3617 +1 x3618 +1 x3619 +1 x3620 +1 x3621 +1 x3622 +1 x3623 +1 x3624 +1 x3625 +1 x3626 +1 x3627 +1 x3628 +1 x3629 +1 x3630 +1 x3631 +1 x3632 +1 x3633 +1 x3634 +1 x3635 +1 x3636 +1 x3637 +1 x3638 +1 x3639 +1 x3640 +1 x3641 +1 x3642 +1 x3643 +1 x3644 +1 x3645 +1 x3646 +1 x3647 +1 x3648 +1 x3649 +1 x3650 +1 x3651 +1 x3652 +1 x3653 +1 x3654 +1 x3655 +1 x3656 +1 x3657 +1 x3658 +1 x3659 +1 x3660 +1 x3661 +1 x3662 +1 x3663 +1 x3664 +1 x3665 +1 x3666 +1 x3667 +1 x3668 +1 x3669 +1 x3670 +1 x3671 +1 x3672 +1 x3673 +1 x3674 +1 x3675 +1 x3676 +1 x3677 +1 x3678 +1 x3679 +1 x3680 +1 x3681 +1 x3682 +1 x3683 +1 x3684 +1 x3685 +1 x3686 +1 x3687 +1 x3688 +1 x3689 +1 x3690 +1 x3691 +1 x3692 +1 x3693 +1 x3694 +1 x3695 +1 x3696 +1 x3697 +1 x3698 +1 x3699 +1 x3700 +1 x3701 +1 x3702 +1 x3703 +1 x3704 +1 x3705 +1 x3706 +1 x3707 +1 x3708 +1 x3709 +1 x3710 +1 x3711 +1 x3712 +1 x3713 +1 x3714 +1 x3715 +1 x3716 +1 x3717 +1 x3718 +1 x3719 +1 x3720 +1 x3721 +1 x3722 +1 x3723 +1 x3724 +1 x3725 +1 x3726 +1 x3727 +1 x3728 +1 x3729 +1 x3730 +1 x3731 +1 x3732 +1 x3733 +1 x3734 +1 x3735 +1 x3736 +1 x3737 +1 x3738 +1 x3739 +1 x3740 +1 x3741 +1 x3742 +1 x3743 +1 x3744 +1 x3745 +1 x3746 +1 x3747 +1 x3748 +1 x3749 +1 x3750 +1 x3751 +1 x3752 +1 x3753 +1 x3754 +1 x3755 +1 x3756 +1 x3757 +1 x3758 +1 x3759 +1 x3760 +1 x3761 +1 x3762 +1 x3763 +1 x3764 +1 x3765 +1 x3766 +1 x3767 +1 x3768 +1 x3769 +1 x3770 +1 x3771 +1 x3772 +1 x3773 +1 x3774 +1 x3775 +1 x3776 +1 x3777 +1 x3778 +1 x3779 +1 x3780 +1 x3781 +1 x3782 +1 x3783 +1 x3784 +1 x3785 +1 x3786 +1 x3787 +1 x3788 +1 x3789 +1 x3790 +1 x3791 +1 x3792 +1 x3793 +1 x3794 +1 x3795 +1 x3796 +1 x3797 +1 x3798 +1 x3799 +1 x3800 +1 x3801 +1 x3802 +1 x3803 +1 x3804 +1 x3805 +1 x3806 +1 x3807 +1 x3808 +1 x3809 +1 x3810 +1 x3811 +1 x3812 +1 x3813 +1 x3814 +1 x3815 +1 x3816 +1 x3817 +1 x3818 +1 x3819 +1 x3820 +1 x3821 +1 x3822 +1 x3823 +1 x3824 +1 x3825 +1 x3826 +1 x3827 +1 x3828 +1 x3829 +1 x3830 +1 x3831 +1 x3832 +1 x3833 +1 x3834 +1 x3835 +1 x3836 +1 x3837 +1 x3838 +1 x3839 +1 x3840 +1 x5889 +1 x5890 +1 x5891 +1 x5892 +1 x5893 +1 x5894 +1 x5895 +1 x5896 +1 x5897 +1 x5898 +1 x5899 +1 x5900 +1 x5901 +1 x5902 +1 x5903 +1 x5904 +1 x5905 +1 x5906 +1 x5907 +1 x5908 +1 x5909 +1 x5910 +1 x5911 +1 x5912 +1 x5913 +1 x5914 +1 x5915 +1 x5916 +1 x5917 +1 x5918 +1 x5919 +1 x5920 +1 x5921 +1 x5922 +1 x5923 +1 x5924 +1 x5925 +1 x5926 +1 x5927 +1 x5928 +1 x5929 +1 x5930 +1 x5931 +1 x5932 +1 x5933 +1 x5934 +1 x5935 +1 x5936 +1 x5937 +1 x5938 +1 x5939 +1 x5940 +1 x5941 +1 x5942 +1 x5943 +1 x5944 +1 x5945 +1 x5946 +1 x5947 +1 x5948 +1 x5949 +1 x5950 +1 x5951 +1 x5952 +1 x5953 +1 x5954 +1 x5955 +1 x5956 +1 x5957 +1 x5958 +1 x5959 +1 x5960 +1 x5961 +1 x5962 +1 x5963 +1 x5964 +1 x5965 +1 x5966 +1 x5967 +1 x5968 +1 x5969 +1 x5970 +1 x5971 +1 x5972 +1 x5973 +1 x5974 +1 x5975 +1 x5976 +1 x5977 +1 x5978 +1 x5979 +1 x5980 +1 x5981 +1 x5982 +1 x5983 +1 x5984 +1 x5985 +1 x5986 +1 x5987 +1 x5988 +1 x5989 +1 x5990 +1 x5991 +1 x5992 +1 x5993 +1 x5994 +1 x5995 +1 x5996 +1 x5997 +1 x5998 +1 x5999 +1 x6000 +1 x6001 +1 x6002 +1 x6003 +1 x6004 +1 x6005 +1 x6006 +1 x6007 +1 x6008 +1 x6009 +1 x6010 +1 x6011 +1 x6012 +1 x6013 +1 x6014 +1 x6015 +1 x6016 +1 x6401 +1 x6402 +1 x6403 +1 x6404 +1 x6405 +1 x6406 +1 x6407 +1 x6408 +1 x6409 +1 x6410 +1 x6411 +1 x6412 +1 x6413 +1 x6414 +1 x6415 +1 x6416 +1 x6417 +1 x6418 +1 x6419 +1 x6420 +1 x6421 +1 x6422 +1 x6423 +1 x6424 +1 x6425 +1 x6426 +1 x6427 +1 x6428 +1 x6429 +1 x6430 +1 x6431 +1 x6432 +1 x6433 +1 x6434 +1 x6435 +1 x6436 +1 x6437 +1 x6438 +1 x6439 +1 x6440 +1 x6441 +1 x6442 +1 x6443 +1 x6444 +1 x6445 +1 x6446 +1 x6447 +1 x6448 +1 x6449 +1 x6450 +1 x6451 +1 x6452 +1 x6453 +1 x6454 +1 x6455 +1 x6456 +1 x6457 +1 x6458 +1 x6459 +1 x6460 +1 x6461 +1 x6462 +1 x6463 +1 x6464 +1 x6465 +1 x6466 +1 x6467 +1 x6468 +1 x6469 +1 x6470 +1 x6471 +1 x6472 +1 x6473 +1 x6474 +1 x6475 +1 x6476 +1 x6477 +1 x6478 +1 x6479 +1 x6480 +1 x6481 +1 x6482 +1 x6483 +1 x6484 +1 x6485 +1 x6486 +1 x6487 +1 x6488 +1 x6489 +1 x6490 +1 x6491 +1 x6492 +1 x6493 +1 x6494 +1 x6495 +1 x6496 +1 x6497 +1 x6498 +1 x6499 +1 x6500 +1 x6501 +1 x6502 +1 x6503 +1 x6504 +1 x6505 +1 x6506 +1 x6507 +1 x6508 +1 x6509 +1 x6510 +1 x6511 +1 x6512 +1 x6513 +1 x6514 +1 x6515 +1 x6516 +1 x6517 +1 x6518 +1 x6519 +1 x6520 +1 x6521 +1 x6522 +1 x6523 +1 x6524 +1 x6525 +1 x6526 +1 x6527 +1 x6528 = 0 ;+-2 x12817 +1 x3841 +1 x3842 +1 x3843 +1 x3844 +1 x3845 +1 x3846 +1 x3847 +1 x3848 +1 x3849 +1 x3850 +1 x3851 +1 x3852 +1 x3853 +1 x3854 +1 x3855 +1 x3856 +1 x3857 +1 x3858 +1 x3859 +1 x3860 +1 x3861 +1 x3862 +1 x3863 +1 x3864 +1 x3865 +1 x3866 +1 x3867 +1 x3868 +1 x3869 +1 x3870 +1 x3871 +1 x3872 +1 x3873 +1 x3874 +1 x3875 +1 x3876 +1 x3877 +1 x3878 +1 x3879 +1 x3880 +1 x3881 +1 x3882 +1 x3883 +1 x3884 +1 x3885 +1 x3886 +1 x3887 +1 x3888 +1 x3889 +1 x3890 +1 x3891 +1 x3892 +1 x3893 +1 x3894 +1 x3895 +1 x3896 +1 x3897 +1 x3898 +1 x3899 +1 x3900 +1 x3901 +1 x3902 +1 x3903 +1 x3904 +1 x3905 +1 x3906 +1 x3907 +1 x3908 +1 x3909 +1 x3910 +1 x3911 +1 x3912 +1 x3913 +1 x3914 +1 x3915 +1 x3916 +1 x3917 +1 x3918 +1 x3919 +1 x3920 +1 x3921 +1 x3922 +1 x3923 +1 x3924 +1 x3925 +1 x3926 +1 x3927 +1 x3928 +1 x3929 +1 x3930 +1 x3931 +1 x3932 +1 x3933 +1 x3934 +1 x3935 +1 x3936 +1 x3937 +1 x3938 +1 x3939 +1 x3940 +1 x3941 +1 x3942 +1 x3943 +1 x3944 +1 x3945 +1 x3946 +1 x3947 +1 x3948 +1 x3949 +1 x3950 +1 x3951 +1 x3952 +1 x3953 +1 x3954 +1 x3955 +1 x3956 +1 x3957 +1 x3958 +1 x3959 +1 x3960 +1 x3961 +1 x3962 +1 x3963 +1 x3964 +1 x3965 +1 x3966 +1 x3967 +1 x3968 +1 x3969 +1 x3970 +1 x3971 +1 x3972 +1 x3973 +1 x3974 +1 x3975 +1 x3976 +1 x3977 +1 x3978 +1 x3979 +1 x3980 +1 x3981 +1 x3982 +1 x3983 +1 x3984 +1 x3985 +1 x3986 +1 x3987 +1 x3988 +1 x3989 +1 x3990 +1 x3991 +1 x3992 +1 x3993 +1 x3994 +1 x3995 +1 x3996 +1 x3997 +1 x3998 +1 x3999 +1 x4000 +1 x4001 +1 x4002 +1 x4003 +1 x4004 +1 x4005 +1 x4006 +1 x4007 +1 x4008 +1 x4009 +1 x4010 +1 x4011 +1 x4012 +1 x4013 +1 x4014 +1 x4015 +1 x4016 +1 x4017 +1 x4018 +1 x4019 +1 x4020 +1 x4021 +1 x4022 +1 x4023 +1 x4024 +1 x4025 +1 x4026 +1 x4027 +1 x4028 +1 x4029 +1 x4030 +1 x4031 +1 x4032 +1 x4033 +1 x4034 +1 x4035 +1 x4036 +1 x4037 +1 x4038 +1 x4039 +1 x4040 +1 x4041 +1 x4042 +1 x4043 +1 x4044 +1 x4045 +1 x4046 +1 x4047 +1 x4048 +1 x4049 +1 x4050 +1 x4051 +1 x4052 +1 x4053 +1 x4054 +1 x4055 +1 x4056 +1 x4057 +1 x4058 +1 x4059 +1 x4060 +1 x4061 +1 x4062 +1 x4063 +1 x4064 +1 x4065 +1 x4066 +1 x4067 +1 x4068 +1 x4069 +1 x4070 +1 x4071 +1 x4072 +1 x4073 +1 x4074 +1 x4075 +1 x4076 +1 x4077 +1 x4078 +1 x4079 +1 x4080 +1 x4081 +1 x4082 +1 x4083 +1 x4084 +1 x4085 +1 x4086 +1 x4087 +1 x4088 +1 x4089 +1 x4090 +1 x4091 +1 x4092 +1 x4093 +1 x4094 +1 x4095 +1 x4096 +1 x4097 +1 x4098 +1 x4099 +1 x4100 +1 x4101 +1 x4102 +1 x4103 +1 x4104 +1 x4105 +1 x4106 +1 x4107 +1 x4108 +1 x4109 +1 x4110 +1 x4111 +1 x4112 +1 x4113 +1 x4114 +1 x4115 +1 x4116 +1 x4117 +1 x4118 +1 x4119 +1 x4120 +1 x4121 +1 x4122 +1 x4123 +1 x4124 +1 x4125 +1 x4126 +1 x4127 +1 x4128 +1 x4129 +1 x4130 +1 x4131 +1 x4132 +1 x4133 +1 x4134 +1 x4135 +1 x4136 +1 x4137 +1 x4138 +1 x4139 +1 x4140 +1 x4141 +1 x4142 +1 x4143 +1 x4144 +1 x4145 +1 x4146 +1 x4147 +1 x4148 +1 x4149 +1 x4150 +1 x4151 +1 x4152 +1 x4153 +1 x4154 +1 x4155 +1 x4156 +1 x4157 +1 x4158 +1 x4159 +1 x4160 +1 x4161 +1 x4162 +1 x4163 +1 x4164 +1 x4165 +1 x4166 +1 x4167 +1 x4168 +1 x4169 +1 x4170 +1 x4171 +1 x4172 +1 x4173 +1 x4174 +1 x4175 +1 x4176 +1 x4177 +1 x4178 +1 x4179 +1 x4180 +1 x4181 +1 x4182 +1 x4183 +1 x4184 +1 x4185 +1 x4186 +1 x4187 +1 x4188 +1 x4189 +1 x4190 +1 x4191 +1 x4192 +1 x4193 +1 x4194 +1 x4195 +1 x4196 +1 x4197 +1 x4198 +1 x4199 +1 x4200 +1 x4201 +1 x4202 +1 x4203 +1 x4204 +1 x4205 +1 x4206 +1 x4207 +1 x4208 +1 x4209 +1 x4210 +1 x4211 +1 x4212 +1 x4213 +1 x4214 +1 x4215 +1 x4216 +1 x4217 +1 x4218 +1 x4219 +1 x4220 +1 x4221 +1 x4222 +1 x4223 +1 x4224 +1 x6529 +1 x6530 +1 x6531 +1 x6532 +1 x6533 +1 x6534 +1 x6535 +1 x6536 +1 x6537 +1 x6538 +1 x6539 +1 x6540 +1 x6541 +1 x6542 +1 x6543 +1 x6544 +1 x6545 +1 x6546 +1 x6547 +1 x6548 +1 x6549 +1 x6550 +1 x6551 +1 x6552 +1 x6553 +1 x6554 +1 x6555 +1 x6556 +1 x6557 +1 x6558 +1 x6559 +1 x6560 +1 x6561 +1 x6562 +1 x6563 +1 x6564 +1 x6565 +1 x6566 +1 x6567 +1 x6568 +1 x6569 +1 x6570 +1 x6571 +1 x6572 +1 x6573 +1 x6574 +1 x6575 +1 x6576 +1 x6577 +1 x6578 +1 x6579 +1 x6580 +1 x6581 +1 x6582 +1 x6583 +1 x6584 +1 x6585 +1 x6586 +1 x6587 +1 x6588 +1 x6589 +1 x6590 +1 x6591 +1 x6592 +1 x6593 +1 x6594 +1 x6595 +1 x6596 +1 x6597 +1 x6598 +1 x6599 +1 x6600 +1 x6601 +1 x6602 +1 x6603 +1 x6604 +1 x6605 +1 x6606 +1 x6607 +1 x6608 +1 x6609 +1 x6610 +1 x6611 +1 x6612 +1 x6613 +1 x6614 +1 x6615 +1 x6616 +1 x6617 +1 x6618 +1 x6619 +1 x6620 +1 x6621 +1 x6622 +1 x6623 +1 x6624 +1 x6625 +1 x6626 +1 x6627 +1 x6628 +1 x6629 +1 x6630 +1 x6631 +1 x6632 +1 x6633 +1 x6634 +1 x6635 +1 x6636 +1 x6637 +1 x6638 +1 x6639 +1 x6640 +1 x6641 +1 x6642 +1 x6643 +1 x6644 +1 x6645 +1 x6646 +1 x6647 +1 x6648 +1 x6649 +1 x6650 +1 x6651 +1 x6652 +1 x6653 +1 x6654 +1 x6655 +1 x6656 +1 x7297 +1 x7298 +1 x7299 +1 x7300 +1 x7301 +1 x7302 +1 x7303 +1 x7304 +1 x7305 +1 x7306 +1 x7307 +1 x7308 +1 x7309 +1 x7310 +1 x7311 +1 x7312 +1 x7313 +1 x7314 +1 x7315 +1 x7316 +1 x7317 +1 x7318 +1 x7319 +1 x7320 +1 x7321 +1 x7322 +1 x7323 +1 x7324 +1 x7325 +1 x7326 +1 x7327 +1 x7328 +1 x7329 +1 x7330 +1 x7331 +1 x7332 +1 x7333 +1 x7334 +1 x7335 +1 x7336 +1 x7337 +1 x7338 +1 x7339 +1 x7340 +1 x7341 +1 x7342 +1 x7343 +1 x7344 +1 x7345 +1 x7346 +1 x7347 +1 x7348 +1 x7349 +1 x7350 +1 x7351 +1 x7352 +1 x7353 +1 x7354 +1 x7355 +1 x7356 +1 x7357 +1 x7358 +1 x7359 +1 x7360 +1 x7361 +1 x7362 +1 x7363 +1 x7364 +1 x7365 +1 x7366 +1 x7367 +1 x7368 +1 x7369 +1 x7370 +1 x7371 +1 x7372 +1 x7373 +1 x7374 +1 x7375 +1 x7376 +1 x7377 +1 x7378 +1 x7379 +1 x7380 +1 x7381 +1 x7382 +1 x7383 +1 x7384 +1 x7385 +1 x7386 +1 x7387 +1 x7388 +1 x7389 +1 x7390 +1 x7391 +1 x7392 +1 x7393 +1 x7394 +1 x7395 +1 x7396 +1 x7397 +1 x7398 +1 x7399 +1 x7400 +1 x7401 +1 x7402 +1 x7403 +1 x7404 +1 x7405 +1 x7406 +1 x7407 +1 x7408 +1 x7409 +1 x7410 +1 x7411 +1 x7412 +1 x7413 +1 x7414 +1 x7415 +1 x7416 +1 x7417 +1 x7418 +1 x7419 +1 x7420 +1 x7421 +1 x7422 +1 x7423 +1 x7424 +1 x9601 +1 x9602 +1 x9603 +1 x9604 +1 x9605 +1 x9606 +1 x9607 +1 x9608 +1 x9609 +1 x9610 +1 x9611 +1 x9612 +1 x9613 +1 x9614 +1 x9615 +1 x9616 +1 x9617 +1 x9618 +1 x9619 +1 x9620 +1 x9621 +1 x9622 +1 x9623 +1 x9624 +1 x9625 +1 x9626 +1 x9627 +1 x9628 +1 x9629 +1 x9630 +1 x9631 +1 x9632 +1 x9633 +1 x9634 +1 x9635 +1 x9636 +1 x9637 +1 x9638 +1 x9639 +1 x9640 +1 x9641 +1 x9642 +1 x9643 +1 x9644 +1 x9645 +1 x9646 +1 x9647 +1 x9648 +1 x9649 +1 x9650 +1 x9651 +1 x9652 +1 x9653 +1 x9654 +1 x9655 +1 x9656 +1 x9657 +1 x9658 +1 x9659 +1 x9660 +1 x9661 +1 x9662 +1 x9663 +1 x9664 +1 x9665 +1 x9666 +1 x9667 +1 x9668 +1 x9669 +1 x9670 +1 x9671 +1 x9672 +1 x9673 +1 x9674 +1 x9675 +1 x9676 +1 x9677 +1 x9678 +1 x9679 +1 x9680 +1 x9681 +1 x9682 +1 x9683 +1 x9684 +1 x9685 +1 x9686 +1 x9687 +1 x9688 +1 x9689 +1 x9690 +1 x9691 +1 x9692 +1 x9693 +1 x9694 +1 x9695 +1 x9696 +1 x9697 +1 x9698 +1 x9699 +1 x9700 +1 x9701 +1 x9702 +1 x9703 +1 x9704 +1 x9705 +1 x9706 +1 x9707 +1 x9708 +1 x9709 +1 x9710 +1 x9711 +1 x9712 +1 x9713 +1 x9714 +1 x9715 +1 x9716 +1 x9717 +1 x9718 +1 x9719 +1 x9720 +1 x9721 +1 x9722 +1 x9723 +1 x9724 +1 x9725 +1 x9726 +1 x9727 +1 x9728 = 0 ;+-2 x12818 +1 x4097 +1 x4098 +1 x4099 +1 x4100 +1 x4101 +1 x4102 +1 x4103 +1 x4104 +1 x4105 +1 x4106 +1 x4107 +1 x4108 +1 x4109 +1 x4110 +1 x4111 +1 x4112 +1 x4113 +1 x4114 +1 x4115 +1 x4116 +1 x4117 +1 x4118 +1 x4119 +1 x4120 +1 x4121 +1 x4122 +1 x4123 +1 x4124 +1 x4125 +1 x4126 +1 x4127 +1 x4128 +1 x4129 +1 x4130 +1 x4131 +1 x4132 +1 x4133 +1 x4134 +1 x4135 +1 x4136 +1 x4137 +1 x4138 +1 x4139 +1 x4140 +1 x4141 +1 x4142 +1 x4143 +1 x4144 +1 x4145 +1 x4146 +1 x4147 +1 x4148 +1 x4149 +1 x4150 +1 x4151 +1 x4152 +1 x4153 +1 x4154 +1 x4155 +1 x4156 +1 x4157 +1 x4158 +1 x4159 +1 x4160 +1 x4161 +1 x4162 +1 x4163 +1 x4164 +1 x4165 +1 x4166 +1 x4167 +1 x4168 +1 x4169 +1 x4170 +1 x4171 +1 x4172 +1 x4173 +1 x4174 +1 x4175 +1 x4176 +1 x4177 +1 x4178 +1 x4179 +1 x4180 +1 x4181 +1 x4182 +1 x4183 +1 x4184 +1 x4185 +1 x4186 +1 x4187 +1 x4188 +1 x4189 +1 x4190 +1 x4191 +1 x4192 +1 x4193 +1 x4194 +1 x4195 +1 x4196 +1 x4197 +1 x4198 +1 x4199 +1 x4200 +1 x4201 +1 x4202 +1 x4203 +1 x4204 +1 x4205 +1 x4206 +1 x4207 +1 x4208 +1 x4209 +1 x4210 +1 x4211 +1 x4212 +1 x4213 +1 x4214 +1 x4215 +1 x4216 +1 x4217 +1 x4218 +1 x4219 +1 x4220 +1 x4221 +1 x4222 +1 x4223 +1 x4224 +1 x4225 +1 x4226 +1 x4227 +1 x4228 +1 x4229 +1 x4230 +1 x4231 +1 x4232 +1 x4233 +1 x4234 +1 x4235 +1 x4236 +1 x4237 +1 x4238 +1 x4239 +1 x4240 +1 x4241 +1 x4242 +1 x4243 +1 x4244 +1 x4245 +1 x4246 +1 x4247 +1 x4248 +1 x4249 +1 x4250 +1 x4251 +1 x4252 +1 x4253 +1 x4254 +1 x4255 +1 x4256 +1 x4257 +1 x4258 +1 x4259 +1 x4260 +1 x4261 +1 x4262 +1 x4263 +1 x4264 +1 x4265 +1 x4266 +1 x4267 +1 x4268 +1 x4269 +1 x4270 +1 x4271 +1 x4272 +1 x4273 +1 x4274 +1 x4275 +1 x4276 +1 x4277 +1 x4278 +1 x4279 +1 x4280 +1 x4281 +1 x4282 +1 x4283 +1 x4284 +1 x4285 +1 x4286 +1 x4287 +1 x4288 +1 x4289 +1 x4290 +1 x4291 +1 x4292 +1 x4293 +1 x4294 +1 x4295 +1 x4296 +1 x4297 +1 x4298 +1 x4299 +1 x4300 +1 x4301 +1 x4302 +1 x4303 +1 x4304 +1 x4305 +1 x4306 +1 x4307 +1 x4308 +1 x4309 +1 x4310 +1 x4311 +1 x4312 +1 x4313 +1 x4314 +1 x4315 +1 x4316 +1 x4317 +1 x4318 +1 x4319 +1 x4320 +1 x4321 +1 x4322 +1 x4323 +1 x4324 +1 x4325 +1 x4326 +1 x4327 +1 x4328 +1 x4329 +1 x4330 +1 x4331 +1 x4332 +1 x4333 +1 x4334 +1 x4335 +1 x4336 +1 x4337 +1 x4338 +1 x4339 +1 x4340 +1 x4341 +1 x4342 +1 x4343 +1 x4344 +1 x4345 +1 x4346 +1 x4347 +1 x4348 +1 x4349 +1 x4350 +1 x4351 +1 x4352 +1 x6145 +1 x6146 +1 x6147 +1 x6148 +1 x6149 +1 x6150 +1 x6151 +1 x6152 +1 x6153 +1 x6154 +1 x6155 +1 x6156 +1 x6157 +1 x6158 +1 x6159 +1 x6160 +1 x6161 +1 x6162 +1 x6163 +1 x6164 +1 x6165 +1 x6166 +1 x6167 +1 x6168 +1 x6169 +1 x6170 +1 x6171 +1 x6172 +1 x6173 +1 x6174 +1 x6175 +1 x6176 +1 x6177 +1 x6178 +1 x6179 +1 x6180 +1 x6181 +1 x6182 +1 x6183 +1 x6184 +1 x6185 +1 x6186 +1 x6187 +1 x6188 +1 x6189 +1 x6190 +1 x6191 +1 x6192 +1 x6193 +1 x6194 +1 x6195 +1 x6196 +1 x6197 +1 x6198 +1 x6199 +1 x6200 +1 x6201 +1 x6202 +1 x6203 +1 x6204 +1 x6205 +1 x6206 +1 x6207 +1 x6208 +1 x6209 +1 x6210 +1 x6211 +1 x6212 +1 x6213 +1 x6214 +1 x6215 +1 x6216 +1 x6217 +1 x6218 +1 x6219 +1 x6220 +1 x6221 +1 x6222 +1 x6223 +1 x6224 +1 x6225 +1 x6226 +1 x6227 +1 x6228 +1 x6229 +1 x6230 +1 x6231 +1 x6232 +1 x6233 +1 x6234 +1 x6235 +1 x6236 +1 x6237 +1 x6238 +1 x6239 +1 x6240 +1 x6241 +1 x6242 +1 x6243 +1 x6244 +1 x6245 +1 x6246 +1 x6247 +1 x6248 +1 x6249 +1 x6250 +1 x6251 +1 x6252 +1 x6253 +1 x6254 +1 x6255 +1 x6256 +1 x6257 +1 x6258 +1 x6259 +1 x6260 +1 x6261 +1 x6262 +1 x6263 +1 x6264 +1 x6265 +1 x6266 +1 x6267 +1 x6268 +1 x6269 +1 x6270 +1 x6271 +1 x6272 +1 x7809 +1 x7810 +1 x7811 +1 x7812 +1 x7813 +1 x7814 +1 x7815 +1 x7816 +1 x7817 +1 x7818 +1 x7819 +1 x7820 +1 x7821 +1 x7822 +1 x7823 +1 x7824 +1 x7825 +1 x7826 +1 x7827 +1 x7828 +1 x7829 +1 x7830 +1 x7831 +1 x7832 +1 x7833 +1 x7834 +1 x7835 +1 x7836 +1 x7837 +1 x7838 +1 x7839 +1 x7840 +1 x7841 +1 x7842 +1 x7843 +1 x7844 +1 x7845 +1 x7846 +1 x7847 +1 x7848 +1 x7849 +1 x7850 +1 x7851 +1 x7852 +1 x7853 +1 x7854 +1 x7855 +1 x7856 +1 x7857 +1 x7858 +1 x7859 +1 x7860 +1 x7861 +1 x7862 +1 x7863 +1 x7864 +1 x7865 +1 x7866 +1 x7867 +1 x7868 +1 x7869 +1 x7870 +1 x7871 +1 x7872 +1 x7873 +1 x7874 +1 x7875 +1 x7876 +1 x7877 +1 x7878 +1 x7879 +1 x7880 +1 x7881 +1 x7882 +1 x7883 +1 x7884 +1 x7885 +1 x7886 +1 x7887 +1 x7888 +1 x7889 +1 x7890 +1 x7891 +1 x7892 +1 x7893 +1 x7894 +1 x7895 +1 x7896 +1 x7897 +1 x7898 +1 x7899 +1 x7900 +1 x7901 +1 x7902 +1 x7903 +1 x7904 +1 x7905 +1 x7906 +1 x7907 +1 x7908 +1 x7909 +1 x7910 +1 x7911 +1 x7912 +1 x7913 +1 x7914 +1 x7915 +1 x7916 +1 x7917 +1 x7918 +1 x7919 +1 x7920 +1 x7921 +1 x7922 +1 x7923 +1 x7924 +1 x7925 +1 x7926 +1 x7927 +1 x7928 +1 x7929 +1 x7930 +1 x7931 +1 x7932 +1 x7933 +1 x7934 +1 x7935 +1 x7936 = 0 ;+-2 x12819 +1 x4353 +1 x4354 +1 x4355 +1 x4356 +1 x4357 +1 x4358 +1 x4359 +1 x4360 +1 x4361 +1 x4362 +1 x4363 +1 x4364 +1 x4365 +1 x4366 +1 x4367 +1 x4368 +1 x4369 +1 x4370 +1 x4371 +1 x4372 +1 x4373 +1 x4374 +1 x4375 +1 x4376 +1 x4377 +1 x4378 +1 x4379 +1 x4380 +1 x4381 +1 x4382 +1 x4383 +1 x4384 +1 x4385 +1 x4386 +1 x4387 +1 x4388 +1 x4389 +1 x4390 +1 x4391 +1 x4392 +1 x4393 +1 x4394 +1 x4395 +1 x4396 +1 x4397 +1 x4398 +1 x4399 +1 x4400 +1 x4401 +1 x4402 +1 x4403 +1 x4404 +1 x4405 +1 x4406 +1 x4407 +1 x4408 +1 x4409 +1 x4410 +1 x4411 +1 x4412 +1 x4413 +1 x4414 +1 x4415 +1 x4416 +1 x4417 +1 x4418 +1 x4419 +1 x4420 +1 x4421 +1 x4422 +1 x4423 +1 x4424 +1 x4425 +1 x4426 +1 x4427 +1 x4428 +1 x4429 +1 x4430 +1 x4431 +1 x4432 +1 x4433 +1 x4434 +1 x4435 +1 x4436 +1 x4437 +1 x4438 +1 x4439 +1 x4440 +1 x4441 +1 x4442 +1 x4443 +1 x4444 +1 x4445 +1 x4446 +1 x4447 +1 x4448 +1 x4449 +1 x4450 +1 x4451 +1 x4452 +1 x4453 +1 x4454 +1 x4455 +1 x4456 +1 x4457 +1 x4458 +1 x4459 +1 x4460 +1 x4461 +1 x4462 +1 x4463 +1 x4464 +1 x4465 +1 x4466 +1 x4467 +1 x4468 +1 x4469 +1 x4470 +1 x4471 +1 x4472 +1 x4473 +1 x4474 +1 x4475 +1 x4476 +1 x4477 +1 x4478 +1 x4479 +1 x4480 +1 x4481 +1 x4482 +1 x4483 +1 x4484 +1 x4485 +1 x4486 +1 x4487 +1 x4488 +1 x4489 +1 x4490 +1 x4491 +1 x4492 +1 x4493 +1 x4494 +1 x4495 +1 x4496 +1 x4497 +1 x4498 +1 x4499 +1 x4500 +1 x4501 +1 x4502 +1 x4503 +1 x4504 +1 x4505 +1 x4506 +1 x4507 +1 x4508 +1 x4509 +1 x4510 +1 x4511 +1 x4512 +1 x4513 +1 x4514 +1 x4515 +1 x4516 +1 x4517 +1 x4518 +1 x4519 +1 x4520 +1 x4521 +1 x4522 +1 x4523 +1 x4524 +1 x4525 +1 x4526 +1 x4527 +1 x4528 +1 x4529 +1 x4530 +1 x4531 +1 x4532 +1 x4533 +1 x4534 +1 x4535 +1 x4536 +1 x4537 +1 x4538 +1 x4539 +1 x4540 +1 x4541 +1 x4542 +1 x4543 +1 x4544 +1 x4545 +1 x4546 +1 x4547 +1 x4548 +1 x4549 +1 x4550 +1 x4551 +1 x4552 +1 x4553 +1 x4554 +1 x4555 +1 x4556 +1 x4557 +1 x4558 +1 x4559 +1 x4560 +1 x4561 +1 x4562 +1 x4563 +1 x4564 +1 x4565 +1 x4566 +1 x4567 +1 x4568 +1 x4569 +1 x4570 +1 x4571 +1 x4572 +1 x4573 +1 x4574 +1 x4575 +1 x4576 +1 x4577 +1 x4578 +1 x4579 +1 x4580 +1 x4581 +1 x4582 +1 x4583 +1 x4584 +1 x4585 +1 x4586 +1 x4587 +1 x4588 +1 x4589 +1 x4590 +1 x4591 +1 x4592 +1 x4593 +1 x4594 +1 x4595 +1 x4596 +1 x4597 +1 x4598 +1 x4599 +1 x4600 +1 x4601 +1 x4602 +1 x4603 +1 x4604 +1 x4605 +1 x4606 +1 x4607 +1 x4608 +1 x10753 +1 x10754 +1 x10755 +1 x10756 +1 x10757 +1 x10758 +1 x10759 +1 x10760 +1 x10761 +1 x10762 +1 x10763 +1 x10764 +1 x10765 +1 x10766 +1 x10767 +1 x10768 +1 x10769 +1 x10770 +1 x10771 +1 x10772 +1 x10773 +1 x10774 +1 x10775 +1 x10776 +1 x10777 +1 x10778 +1 x10779 +1 x10780 +1 x10781 +1 x10782 +1 x10783 +1 x10784 +1 x10785 +1 x10786 +1 x10787 +1 x10788 +1 x10789 +1 x10790 +1 x10791 +1 x10792 +1 x10793 +1 x10794 +1 x10795 +1 x10796 +1 x10797 +1 x10798 +1 x10799 +1 x10800 +1 x10801 +1 x10802 +1 x10803 +1 x10804 +1 x10805 +1 x10806 +1 x10807 +1 x10808 +1 x10809 +1 x10810 +1 x10811 +1 x10812 +1 x10813 +1 x10814 +1 x10815 +1 x10816 +1 x10817 +1 x10818 +1 x10819 +1 x10820 +1 x10821 +1 x10822 +1 x10823 +1 x10824 +1 x10825 +1 x10826 +1 x10827 +1 x10828 +1 x10829 +1 x10830 +1 x10831 +1 x10832 +1 x10833 +1 x10834 +1 x10835 +1 x10836 +1 x10837 +1 x10838 +1 x10839 +1 x10840 +1 x10841 +1 x10842 +1 x10843 +1 x10844 +1 x10845 +1 x10846 +1 x10847 +1 x10848 +1 x10849 +1 x10850 +1 x10851 +1 x10852 +1 x10853 +1 x10854 +1 x10855 +1 x10856 +1 x10857 +1 x10858 +1 x10859 +1 x10860 +1 x10861 +1 x10862 +1 x10863 +1 x10864 +1 x10865 +1 x10866 +1 x10867 +1 x10868 +1 x10869 +1 x10870 +1 x10871 +1 x10872 +1 x10873 +1 x10874 +1 x10875 +1 x10876 +1 x10877 +1 x10878 +1 x10879 +1 x10880 +1 x11009 +1 x11010 +1 x11011 +1 x11012 +1 x11013 +1 x11014 +1 x11015 +1 x11016 +1 x11017 +1 x11018 +1 x11019 +1 x11020 +1 x11021 +1 x11022 +1 x11023 +1 x11024 +1 x11025 +1 x11026 +1 x11027 +1 x11028 +1 x11029 +1 x11030 +1 x11031 +1 x11032 +1 x11033 +1 x11034 +1 x11035 +1 x11036 +1 x11037 +1 x11038 +1 x11039 +1 x11040 +1 x11041 +1 x11042 +1 x11043 +1 x11044 +1 x11045 +1 x11046 +1 x11047 +1 x11048 +1 x11049 +1 x11050 +1 x11051 +1 x11052 +1 x11053 +1 x11054 +1 x11055 +1 x11056 +1 x11057 +1 x11058 +1 x11059 +1 x11060 +1 x11061 +1 x11062 +1 x11063 +1 x11064 +1 x11065 +1 x11066 +1 x11067 +1 x11068 +1 x11069 +1 x11070 +1 x11071 +1 x11072 +1 x11073 +1 x11074 +1 x11075 +1 x11076 +1 x11077 +1 x11078 +1 x11079 +1 x11080 +1 x11081 +1 x11082 +1 x11083 +1 x11084 +1 x11085 +1 x11086 +1 x11087 +1 x11088 +1 x11089 +1 x11090 +1 x11091 +1 x11092 +1 x11093 +1 x11094 +1 x11095 +1 x11096 +1 x11097 +1 x11098 +1 x11099 +1 x11100 +1 x11101 +1 x11102 +1 x11103 +1 x11104 +1 x11105 +1 x11106 +1 x11107 +1 x11108 +1 x11109 +1 x11110 +1 x11111 +1 x11112 +1 x11113 +1 x11114 +1 x11115 +1 x11116 +1 x11117 +1 x11118 +1 x11119 +1 x11120 +1 x11121 +1 x11122 +1 x11123 +1 x11124 +1 x11125 +1 x11126 +1 x11127 +1 x11128 +1 x11129 +1 x11130 +1 x11131 +1 x11132 +1 x11133 +1 x11134 +1 x11135 +1 x11136 +1 x12289 +1 x12290 +1 x12291 +1 x12292 +1 x12293 +1 x12294 +1 x12295 +1 x12296 +1 x12297 +1 x12298 +1 x12299 +1 x12300 +1 x12301 +1 x12302 +1 x12303 +1 x12304 +1 x12305 +1 x12306 +1 x12307 +1 x12308 +1 x12309 +1 x12310 +1 x12311 +1 x12312 +1 x12313 +1 x12314 +1 x12315 +1 x12316 +1 x12317 +1 x12318 +1 x12319 +1 x12320 +1 x12321 +1 x12322 +1 x12323 +1 x12324 +1 x12325 +1 x12326 +1 x12327 +1 x12328 +1 x12329 +1 x12330 +1 x12331 +1 x12332 +1 x12333 +1 x12334 +1 x12335 +1 x12336 +1 x12337 +1 x12338 +1 x12339 +1 x12340 +1 x12341 +1 x12342 +1 x12343 +1 x12344 +1 x12345 +1 x12346 +1 x12347 +1 x12348 +1 x12349 +1 x12350 +1 x12351 +1 x12352 +1 x12353 +1 x12354 +1 x12355 +1 x12356 +1 x12357 +1 x12358 +1 x12359 +1 x12360 +1 x12361 +1 x12362 +1 x12363 +1 x12364 +1 x12365 +1 x12366 +1 x12367 +1 x12368 +1 x12369 +1 x12370 +1 x12371 +1 x12372 +1 x12373 +1 x12374 +1 x12375 +1 x12376 +1 x12377 +1 x12378 +1 x12379 +1 x12380 +1 x12381 +1 x12382 +1 x12383 +1 x12384 +1 x12385 +1 x12386 +1 x12387 +1 x12388 +1 x12389 +1 x12390 +1 x12391 +1 x12392 +1 x12393 +1 x12394 +1 x12395 +1 x12396 +1 x12397 +1 x12398 +1 x12399 +1 x12400 +1 x12401 +1 x12402 +1 x12403 +1 x12404 +1 x12405 +1 x12406 +1 x12407 +1 x12408 +1 x12409 +1 x12410 +1 x12411 +1 x12412 +1 x12413 +1 x12414 +1 x12415 +1 x12416 = 0 ;+-2 x12820 +1 x4609 +1 x4610 +1 x4611 +1 x4612 +1 x4613 +1 x4614 +1 x4615 +1 x4616 +1 x4617 +1 x4618 +1 x4619 +1 x4620 +1 x4621 +1 x4622 +1 x4623 +1 x4624 +1 x4625 +1 x4626 +1 x4627 +1 x4628 +1 x4629 +1 x4630 +1 x4631 +1 x4632 +1 x4633 +1 x4634 +1 x4635 +1 x4636 +1 x4637 +1 x4638 +1 x4639 +1 x4640 +1 x4641 +1 x4642 +1 x4643 +1 x4644 +1 x4645 +1 x4646 +1 x4647 +1 x4648 +1 x4649 +1 x4650 +1 x4651 +1 x4652 +1 x4653 +1 x4654 +1 x4655 +1 x4656 +1 x4657 +1 x4658 +1 x4659 +1 x4660 +1 x4661 +1 x4662 +1 x4663 +1 x4664 +1 x4665 +1 x4666 +1 x4667 +1 x4668 +1 x4669 +1 x4670 +1 x4671 +1 x4672 +1 x4673 +1 x4674 +1 x4675 +1 x4676 +1 x4677 +1 x4678 +1 x4679 +1 x4680 +1 x4681 +1 x4682 +1 x4683 +1 x4684 +1 x4685 +1 x4686 +1 x4687 +1 x4688 +1 x4689 +1 x4690 +1 x4691 +1 x4692 +1 x4693 +1 x4694 +1 x4695 +1 x4696 +1 x4697 +1 x4698 +1 x4699 +1 x4700 +1 x4701 +1 x4702 +1 x4703 +1 x4704 +1 x4705 +1 x4706 +1 x4707 +1 x4708 +1 x4709 +1 x4710 +1 x4711 +1 x4712 +1 x4713 +1 x4714 +1 x4715 +1 x4716 +1 x4717 +1 x4718 +1 x4719 +1 x4720 +1 x4721 +1 x4722 +1 x4723 +1 x4724 +1 x4725 +1 x4726 +1 x4727 +1 x4728 +1 x4729 +1 x4730 +1 x4731 +1 x4732 +1 x4733 +1 x4734 +1 x4735 +1 x4736 +1 x4737 +1 x4738 +1 x4739 +1 x4740 +1 x4741 +1 x4742 +1 x4743 +1 x4744 +1 x4745 +1 x4746 +1 x4747 +1 x4748 +1 x4749 +1 x4750 +1 x4751 +1 x4752 +1 x4753 +1 x4754 +1 x4755 +1 x4756 +1 x4757 +1 x4758 +1 x4759 +1 x4760 +1 x4761 +1 x4762 +1 x4763 +1 x4764 +1 x4765 +1 x4766 +1 x4767 +1 x4768 +1 x4769 +1 x4770 +1 x4771 +1 x4772 +1 x4773 +1 x4774 +1 x4775 +1 x4776 +1 x4777 +1 x4778 +1 x4779 +1 x4780 +1 x4781 +1 x4782 +1 x4783 +1 x4784 +1 x4785 +1 x4786 +1 x4787 +1 x4788 +1 x4789 +1 x4790 +1 x4791 +1 x4792 +1 x4793 +1 x4794 +1 x4795 +1 x4796 +1 x4797 +1 x4798 +1 x4799 +1 x4800 +1 x4801 +1 x4802 +1 x4803 +1 x4804 +1 x4805 +1 x4806 +1 x4807 +1 x4808 +1 x4809 +1 x4810 +1 x4811 +1 x4812 +1 x4813 +1 x4814 +1 x4815 +1 x4816 +1 x4817 +1 x4818 +1 x4819 +1 x4820 +1 x4821 +1 x4822 +1 x4823 +1 x4824 +1 x4825 +1 x4826 +1 x4827 +1 x4828 +1 x4829 +1 x4830 +1 x4831 +1 x4832 +1 x4833 +1 x4834 +1 x4835 +1 x4836 +1 x4837 +1 x4838 +1 x4839 +1 x4840 +1 x4841 +1 x4842 +1 x4843 +1 x4844 +1 x4845 +1 x4846 +1 x4847 +1 x4848 +1 x4849 +1 x4850 +1 x4851 +1 x4852 +1 x4853 +1 x4854 +1 x4855 +1 x4856 +1 x4857 +1 x4858 +1 x4859 +1 x4860 +1 x4861 +1 x4862 +1 x4863 +1 x4864 +1 x7937 +1 x7938 +1 x7939 +1 x7940 +1 x7941 +1 x7942 +1 x7943 +1 x7944 +1 x7945 +1 x7946 +1 x7947 +1 x7948 +1 x7949 +1 x7950 +1 x7951 +1 x7952 +1 x7953 +1 x7954 +1 x7955 +1 x7956 +1 x7957 +1 x7958 +1 x7959 +1 x7960 +1 x7961 +1 x7962 +1 x7963 +1 x7964 +1 x7965 +1 x7966 +1 x7967 +1 x7968 +1 x7969 +1 x7970 +1 x7971 +1 x7972 +1 x7973 +1 x7974 +1 x7975 +1 x7976 +1 x7977 +1 x7978 +1 x7979 +1 x7980 +1 x7981 +1 x7982 +1 x7983 +1 x7984 +1 x7985 +1 x7986 +1 x7987 +1 x7988 +1 x7989 +1 x7990 +1 x7991 +1 x7992 +1 x7993 +1 x7994 +1 x7995 +1 x7996 +1 x7997 +1 x7998 +1 x7999 +1 x8000 +1 x8001 +1 x8002 +1 x8003 +1 x8004 +1 x8005 +1 x8006 +1 x8007 +1 x8008 +1 x8009 +1 x8010 +1 x8011 +1 x8012 +1 x8013 +1 x8014 +1 x8015 +1 x8016 +1 x8017 +1 x8018 +1 x8019 +1 x8020 +1 x8021 +1 x8022 +1 x8023 +1 x8024 +1 x8025 +1 x8026 +1 x8027 +1 x8028 +1 x8029 +1 x8030 +1 x8031 +1 x8032 +1 x8033 +1 x8034 +1 x8035 +1 x8036 +1 x8037 +1 x8038 +1 x8039 +1 x8040 +1 x8041 +1 x8042 +1 x8043 +1 x8044 +1 x8045 +1 x8046 +1 x8047 +1 x8048 +1 x8049 +1 x8050 +1 x8051 +1 x8052 +1 x8053 +1 x8054 +1 x8055 +1 x8056 +1 x8057 +1 x8058 +1 x8059 +1 x8060 +1 x8061 +1 x8062 +1 x8063 +1 x8064 = 0 ;+-2 x12821 +1 x4865 +1 x4866 +1 x4867 +1 x4868 +1 x4869 +1 x4870 +1 x4871 +1 x4872 +1 x4873 +1 x4874 +1 x4875 +1 x4876 +1 x4877 +1 x4878 +1 x4879 +1 x4880 +1 x4881 +1 x4882 +1 x4883 +1 x4884 +1 x4885 +1 x4886 +1 x4887 +1 x4888 +1 x4889 +1 x4890 +1 x4891 +1 x4892 +1 x4893 +1 x4894 +1 x4895 +1 x4896 +1 x4897 +1 x4898 +1 x4899 +1 x4900 +1 x4901 +1 x4902 +1 x4903 +1 x4904 +1 x4905 +1 x4906 +1 x4907 +1 x4908 +1 x4909 +1 x4910 +1 x4911 +1 x4912 +1 x4913 +1 x4914 +1 x4915 +1 x4916 +1 x4917 +1 x4918 +1 x4919 +1 x4920 +1 x4921 +1 x4922 +1 x4923 +1 x4924 +1 x4925 +1 x4926 +1 x4927 +1 x4928 +1 x4929 +1 x4930 +1 x4931 +1 x4932 +1 x4933 +1 x4934 +1 x4935 +1 x4936 +1 x4937 +1 x4938 +1 x4939 +1 x4940 +1 x4941 +1 x4942 +1 x4943 +1 x4944 +1 x4945 +1 x4946 +1 x4947 +1 x4948 +1 x4949 +1 x4950 +1 x4951 +1 x4952 +1 x4953 +1 x4954 +1 x4955 +1 x4956 +1 x4957 +1 x4958 +1 x4959 +1 x4960 +1 x4961 +1 x4962 +1 x4963 +1 x4964 +1 x4965 +1 x4966 +1 x4967 +1 x4968 +1 x4969 +1 x4970 +1 x4971 +1 x4972 +1 x4973 +1 x4974 +1 x4975 +1 x4976 +1 x4977 +1 x4978 +1 x4979 +1 x4980 +1 x4981 +1 x4982 +1 x4983 +1 x4984 +1 x4985 +1 x4986 +1 x4987 +1 x4988 +1 x4989 +1 x4990 +1 x4991 +1 x4992 +1 x4993 +1 x4994 +1 x4995 +1 x4996 +1 x4997 +1 x4998 +1 x4999 +1 x5000 +1 x5001 +1 x5002 +1 x5003 +1 x5004 +1 x5005 +1 x5006 +1 x5007 +1 x5008 +1 x5009 +1 x5010 +1 x5011 +1 x5012 +1 x5013 +1 x5014 +1 x5015 +1 x5016 +1 x5017 +1 x5018 +1 x5019 +1 x5020 +1 x5021 +1 x5022 +1 x5023 +1 x5024 +1 x5025 +1 x5026 +1 x5027 +1 x5028 +1 x5029 +1 x5030 +1 x5031 +1 x5032 +1 x5033 +1 x5034 +1 x5035 +1 x5036 +1 x5037 +1 x5038 +1 x5039 +1 x5040 +1 x5041 +1 x5042 +1 x5043 +1 x5044 +1 x5045 +1 x5046 +1 x5047 +1 x5048 +1 x5049 +1 x5050 +1 x5051 +1 x5052 +1 x5053 +1 x5054 +1 x5055 +1 x5056 +1 x5057 +1 x5058 +1 x5059 +1 x5060 +1 x5061 +1 x5062 +1 x5063 +1 x5064 +1 x5065 +1 x5066 +1 x5067 +1 x5068 +1 x5069 +1 x5070 +1 x5071 +1 x5072 +1 x5073 +1 x5074 +1 x5075 +1 x5076 +1 x5077 +1 x5078 +1 x5079 +1 x5080 +1 x5081 +1 x5082 +1 x5083 +1 x5084 +1 x5085 +1 x5086 +1 x5087 +1 x5088 +1 x5089 +1 x5090 +1 x5091 +1 x5092 +1 x5093 +1 x5094 +1 x5095 +1 x5096 +1 x5097 +1 x5098 +1 x5099 +1 x5100 +1 x5101 +1 x5102 +1 x5103 +1 x5104 +1 x5105 +1 x5106 +1 x5107 +1 x5108 +1 x5109 +1 x5110 +1 x5111 +1 x5112 +1 x5113 +1 x5114 +1 x5115 +1 x5116 +1 x5117 +1 x5118 +1 x5119 +1 x5120 +1 x10113 +1 x10114 +1 x10115 +1 x10116 +1 x10117 +1 x10118 +1 x10119 +1 x10120 +1 x10121 +1 x10122 +1 x10123 +1 x10124 +1 x10125 +1 x10126 +1 x10127 +1 x10128 +1 x10129 +1 x10130 +1 x10131 +1 x10132 +1 x10133 +1 x10134 +1 x10135 +1 x10136 +1 x10137 +1 x10138 +1 x10139 +1 x10140 +1 x10141 +1 x10142 +1 x10143 +1 x10144 +1 x10145 +1 x10146 +1 x10147 +1 x10148 +1 x10149 +1 x10150 +1 x10151 +1 x10152 +1 x10153 +1 x10154 +1 x10155 +1 x10156 +1 x10157 +1 x10158 +1 x10159 +1 x10160 +1 x10161 +1 x10162 +1 x10163 +1 x10164 +1 x10165 +1 x10166 +1 x10167 +1 x10168 +1 x10169 +1 x10170 +1 x10171 +1 x10172 +1 x10173 +1 x10174 +1 x10175 +1 x10176 +1 x10177 +1 x10178 +1 x10179 +1 x10180 +1 x10181 +1 x10182 +1 x10183 +1 x10184 +1 x10185 +1 x10186 +1 x10187 +1 x10188 +1 x10189 +1 x10190 +1 x10191 +1 x10192 +1 x10193 +1 x10194 +1 x10195 +1 x10196 +1 x10197 +1 x10198 +1 x10199 +1 x10200 +1 x10201 +1 x10202 +1 x10203 +1 x10204 +1 x10205 +1 x10206 +1 x10207 +1 x10208 +1 x10209 +1 x10210 +1 x10211 +1 x10212 +1 x10213 +1 x10214 +1 x10215 +1 x10216 +1 x10217 +1 x10218 +1 x10219 +1 x10220 +1 x10221 +1 x10222 +1 x10223 +1 x10224 +1 x10225 +1 x10226 +1 x10227 +1 x10228 +1 x10229 +1 x10230 +1 x10231 +1 x10232 +1 x10233 +1 x10234 +1 x10235 +1 x10236 +1 x10237 +1 x10238 +1 x10239 +1 x10240 +1 x11137 +1 x11138 +1 x11139 +1 x11140 +1 x11141 +1 x11142 +1 x11143 +1 x11144 +1 x11145 +1 x11146 +1 x11147 +1 x11148 +1 x11149 +1 x11150 +1 x11151 +1 x11152 +1 x11153 +1 x11154 +1 x11155 +1 x11156 +1 x11157 +1 x11158 +1 x11159 +1 x11160 +1 x11161 +1 x11162 +1 x11163 +1 x11164 +1 x11165 +1 x11166 +1 x11167 +1 x11168 +1 x11169 +1 x11170 +1 x11171 +1 x11172 +1 x11173 +1 x11174 +1 x11175 +1 x11176 +1 x11177 +1 x11178 +1 x11179 +1 x11180 +1 x11181 +1 x11182 +1 x11183 +1 x11184 +1 x11185 +1 x11186 +1 x11187 +1 x11188 +1 x11189 +1 x11190 +1 x11191 +1 x11192 +1 x11193 +1 x11194 +1 x11195 +1 x11196 +1 x11197 +1 x11198 +1 x11199 +1 x11200 +1 x11201 +1 x11202 +1 x11203 +1 x11204 +1 x11205 +1 x11206 +1 x11207 +1 x11208 +1 x11209 +1 x11210 +1 x11211 +1 x11212 +1 x11213 +1 x11214 +1 x11215 +1 x11216 +1 x11217 +1 x11218 +1 x11219 +1 x11220 +1 x11221 +1 x11222 +1 x11223 +1 x11224 +1 x11225 +1 x11226 +1 x11227 +1 x11228 +1 x11229 +1 x11230 +1 x11231 +1 x11232 +1 x11233 +1 x11234 +1 x11235 +1 x11236 +1 x11237 +1 x11238 +1 x11239 +1 x11240 +1 x11241 +1 x11242 +1 x11243 +1 x11244 +1 x11245 +1 x11246 +1 x11247 +1 x11248 +1 x11249 +1 x11250 +1 x11251 +1 x11252 +1 x11253 +1 x11254 +1 x11255 +1 x11256 +1 x11257 +1 x11258 +1 x11259 +1 x11260 +1 x11261 +1 x11262 +1 x11263 +1 x11264 +1 x11905 +1 x11906 +1 x11907 +1 x11908 +1 x11909 +1 x11910 +1 x11911 +1 x11912 +1 x11913 +1 x11914 +1 x11915 +1 x11916 +1 x11917 +1 x11918 +1 x11919 +1 x11920 +1 x11921 +1 x11922 +1 x11923 +1 x11924 +1 x11925 +1 x11926 +1 x11927 +1 x11928 +1 x11929 +1 x11930 +1 x11931 +1 x11932 +1 x11933 +1 x11934 +1 x11935 +1 x11936 +1 x11937 +1 x11938 +1 x11939 +1 x11940 +1 x11941 +1 x11942 +1 x11943 +1 x11944 +1 x11945 +1 x11946 +1 x11947 +1 x11948 +1 x11949 +1 x11950 +1 x11951 +1 x11952 +1 x11953 +1 x11954 +1 x11955 +1 x11956 +1 x11957 +1 x11958 +1 x11959 +1 x11960 +1 x11961 +1 x11962 +1 x11963 +1 x11964 +1 x11965 +1 x11966 +1 x11967 +1 x11968 +1 x11969 +1 x11970 +1 x11971 +1 x11972 +1 x11973 +1 x11974 +1 x11975 +1 x11976 +1 x11977 +1 x11978 +1 x11979 +1 x11980 +1 x11981 +1 x11982 +1 x11983 +1 x11984 +1 x11985 +1 x11986 +1 x11987 +1 x11988 +1 x11989 +1 x11990 +1 x11991 +1 x11992 +1 x11993 +1 x11994 +1 x11995 +1 x11996 +1 x11997 +1 x11998 +1 x11999 +1 x12000 +1 x12001 +1 x12002 +1 x12003 +1 x12004 +1 x12005 +1 x12006 +1 x12007 +1 x12008 +1 x12009 +1 x12010 +1 x12011 +1 x12012 +1 x12013 +1 x12014 +1 x12015 +1 x12016 +1 x12017 +1 x12018 +1 x12019 +1 x12020 +1 x12021 +1 x12022 +1 x12023 +1 x12024 +1 x12025 +1 x12026 +1 x12027 +1 x12028 +1 x12029 +1 x12030 +1 x12031 +1 x12032 = 0 ;+-2 x12822 +1 x5121 +1 x5122 +1 x5123 +1 x5124 +1 x5125 +1 x5126 +1 x5127 +1 x5128 +1 x5129 +1 x5130 +1 x5131 +1 x5132 +1 x5133 +1 x5134 +1 x5135 +1 x5136 +1 x5137 +1 x5138 +1 x5139 +1 x5140 +1 x5141 +1 x5142 +1 x5143 +1 x5144 +1 x5145 +1 x5146 +1 x5147 +1 x5148 +1 x5149 +1 x5150 +1 x5151 +1 x5152 +1 x5153 +1 x5154 +1 x5155 +1 x5156 +1 x5157 +1 x5158 +1 x5159 +1 x5160 +1 x5161 +1 x5162 +1 x5163 +1 x5164 +1 x5165 +1 x5166 +1 x5167 +1 x5168 +1 x5169 +1 x5170 +1 x5171 +1 x5172 +1 x5173 +1 x5174 +1 x5175 +1 x5176 +1 x5177 +1 x5178 +1 x5179 +1 x5180 +1 x5181 +1 x5182 +1 x5183 +1 x5184 +1 x5185 +1 x5186 +1 x5187 +1 x5188 +1 x5189 +1 x5190 +1 x5191 +1 x5192 +1 x5193 +1 x5194 +1 x5195 +1 x5196 +1 x5197 +1 x5198 +1 x5199 +1 x5200 +1 x5201 +1 x5202 +1 x5203 +1 x5204 +1 x5205 +1 x5206 +1 x5207 +1 x5208 +1 x5209 +1 x5210 +1 x5211 +1 x5212 +1 x5213 +1 x5214 +1 x5215 +1 x5216 +1 x5217 +1 x5218 +1 x5219 +1 x5220 +1 x5221 +1 x5222 +1 x5223 +1 x5224 +1 x5225 +1 x5226 +1 x5227 +1 x5228 +1 x5229 +1 x5230 +1 x5231 +1 x5232 +1 x5233 +1 x5234 +1 x5235 +1 x5236 +1 x5237 +1 x5238 +1 x5239 +1 x5240 +1 x5241 +1 x5242 +1 x5243 +1 x5244 +1 x5245 +1 x5246 +1 x5247 +1 x5248 +1 x5249 +1 x5250 +1 x5251 +1 x5252 +1 x5253 +1 x5254 +1 x5255 +1 x5256 +1 x5257 +1 x5258 +1 x5259 +1 x5260 +1 x5261 +1 x5262 +1 x5263 +1 x5264 +1 x5265 +1 x5266 +1 x5267 +1 x5268 +1 x5269 +1 x5270 +1 x5271 +1 x5272 +1 x5273 +1 x5274 +1 x5275 +1 x5276 +1 x5277 +1 x5278 +1 x5279 +1 x5280 +1 x5281 +1 x5282 +1 x5283 +1 x5284 +1 x5285 +1 x5286 +1 x5287 +1 x5288 +1 x5289 +1 x5290 +1 x5291 +1 x5292 +1 x5293 +1 x5294 +1 x5295 +1 x5296 +1 x5297 +1 x5298 +1 x5299 +1 x5300 +1 x5301 +1 x5302 +1 x5303 +1 x5304 +1 x5305 +1 x5306 +1 x5307 +1 x5308 +1 x5309 +1 x5310 +1 x5311 +1 x5312 +1 x5313 +1 x5314 +1 x5315 +1 x5316 +1 x5317 +1 x5318 +1 x5319 +1 x5320 +1 x5321 +1 x5322 +1 x5323 +1 x5324 +1 x5325 +1 x5326 +1 x5327 +1 x5328 +1 x5329 +1 x5330 +1 x5331 +1 x5332 +1 x5333 +1 x5334 +1 x5335 +1 x5336 +1 x5337 +1 x5338 +1 x5339 +1 x5340 +1 x5341 +1 x5342 +1 x5343 +1 x5344 +1 x5345 +1 x5346 +1 x5347 +1 x5348 +1 x5349 +1 x5350 +1 x5351 +1 x5352 +1 x5353 +1 x5354 +1 x5355 +1 x5356 +1 x5357 +1 x5358 +1 x5359 +1 x5360 +1 x5361 +1 x5362 +1 x5363 +1 x5364 +1 x5365 +1 x5366 +1 x5367 +1 x5368 +1 x5369 +1 x5370 +1 x5371 +1 x5372 +1 x5373 +1 x5374 +1 x5375 +1 x5376 +1 x9217 +1 x9218 +1 x9219 +1 x9220 +1 x9221 +1 x9222 +1 x9223 +1 x9224 +1 x9225 +1 x9226 +1 x9227 +1 x9228 +1 x9229 +1 x9230 +1 x9231 +1 x9232 +1 x9233 +1 x9234 +1 x9235 +1 x9236 +1 x9237 +1 x9238 +1 x9239 +1 x9240 +1 x9241 +1 x9242 +1 x9243 +1 x9244 +1 x9245 +1 x9246 +1 x9247 +1 x9248 +1 x9249 +1 x9250 +1 x9251 +1 x9252 +1 x9253 +1 x9254 +1 x9255 +1 x9256 +1 x9257 +1 x9258 +1 x9259 +1 x9260 +1 x9261 +1 x9262 +1 x9263 +1 x9264 +1 x9265 +1 x9266 +1 x9267 +1 x9268 +1 x9269 +1 x9270 +1 x9271 +1 x9272 +1 x9273 +1 x9274 +1 x9275 +1 x9276 +1 x9277 +1 x9278 +1 x9279 +1 x9280 +1 x9281 +1 x9282 +1 x9283 +1 x9284 +1 x9285 +1 x9286 +1 x9287 +1 x9288 +1 x9289 +1 x9290 +1 x9291 +1 x9292 +1 x9293 +1 x9294 +1 x9295 +1 x9296 +1 x9297 +1 x9298 +1 x9299 +1 x9300 +1 x9301 +1 x9302 +1 x9303 +1 x9304 +1 x9305 +1 x9306 +1 x9307 +1 x9308 +1 x9309 +1 x9310 +1 x9311 +1 x9312 +1 x9313 +1 x9314 +1 x9315 +1 x9316 +1 x9317 +1 x9318 +1 x9319 +1 x9320 +1 x9321 +1 x9322 +1 x9323 +1 x9324 +1 x9325 +1 x9326 +1 x9327 +1 x9328 +1 x9329 +1 x9330 +1 x9331 +1 x9332 +1 x9333 +1 x9334 +1 x9335 +1 x9336 +1 x9337 +1 x9338 +1 x9339 +1 x9340 +1 x9341 +1 x9342 +1 x9343 +1 x9344 = 0 ;+-2 x12823 +1 x5377 +1 x5378 +1 x5379 +1 x5380 +1 x5381 +1 x5382 +1 x5383 +1 x5384 +1 x5385 +1 x5386 +1 x5387 +1 x5388 +1 x5389 +1 x5390 +1 x5391 +1 x5392 +1 x5393 +1 x5394 +1 x5395 +1 x5396 +1 x5397 +1 x5398 +1 x5399 +1 x5400 +1 x5401 +1 x5402 +1 x5403 +1 x5404 +1 x5405 +1 x5406 +1 x5407 +1 x5408 +1 x5409 +1 x5410 +1 x5411 +1 x5412 +1 x5413 +1 x5414 +1 x5415 +1 x5416 +1 x5417 +1 x5418 +1 x5419 +1 x5420 +1 x5421 +1 x5422 +1 x5423 +1 x5424 +1 x5425 +1 x5426 +1 x5427 +1 x5428 +1 x5429 +1 x5430 +1 x5431 +1 x5432 +1 x5433 +1 x5434 +1 x5435 +1 x5436 +1 x5437 +1 x5438 +1 x5439 +1 x5440 +1 x5441 +1 x5442 +1 x5443 +1 x5444 +1 x5445 +1 x5446 +1 x5447 +1 x5448 +1 x5449 +1 x5450 +1 x5451 +1 x5452 +1 x5453 +1 x5454 +1 x5455 +1 x5456 +1 x5457 +1 x5458 +1 x5459 +1 x5460 +1 x5461 +1 x5462 +1 x5463 +1 x5464 +1 x5465 +1 x5466 +1 x5467 +1 x5468 +1 x5469 +1 x5470 +1 x5471 +1 x5472 +1 x5473 +1 x5474 +1 x5475 +1 x5476 +1 x5477 +1 x5478 +1 x5479 +1 x5480 +1 x5481 +1 x5482 +1 x5483 +1 x5484 +1 x5485 +1 x5486 +1 x5487 +1 x5488 +1 x5489 +1 x5490 +1 x5491 +1 x5492 +1 x5493 +1 x5494 +1 x5495 +1 x5496 +1 x5497 +1 x5498 +1 x5499 +1 x5500 +1 x5501 +1 x5502 +1 x5503 +1 x5504 +1 x5505 +1 x5506 +1 x5507 +1 x5508 +1 x5509 +1 x5510 +1 x5511 +1 x5512 +1 x5513 +1 x5514 +1 x5515 +1 x5516 +1 x5517 +1 x5518 +1 x5519 +1 x5520 +1 x5521 +1 x5522 +1 x5523 +1 x5524 +1 x5525 +1 x5526 +1 x5527 +1 x5528 +1 x5529 +1 x5530 +1 x5531 +1 x5532 +1 x5533 +1 x5534 +1 x5535 +1 x5536 +1 x5537 +1 x5538 +1 x5539 +1 x5540 +1 x5541 +1 x5542 +1 x5543 +1 x5544 +1 x5545 +1 x5546 +1 x5547 +1 x5548 +1 x5549 +1 x5550 +1 x5551 +1 x5552 +1 x5553 +1 x5554 +1 x5555 +1 x5556 +1 x5557 +1 x5558 +1 x5559 +1 x5560 +1 x5561 +1 x5562 +1 x5563 +1 x5564 +1 x5565 +1 x5566 +1 x5567 +1 x5568 +1 x5569 +1 x5570 +1 x5571 +1 x5572 +1 x5573 +1 x5574 +1 x5575 +1 x5576 +1 x5577 +1 x5578 +1 x5579 +1 x5580 +1 x5581 +1 x5582 +1 x5583 +1 x5584 +1 x5585 +1 x5586 +1 x5587 +1 x5588 +1 x5589 +1 x5590 +1 x5591 +1 x5592 +1 x5593 +1 x5594 +1 x5595 +1 x5596 +1 x5597 +1 x5598 +1 x5599 +1 x5600 +1 x5601 +1 x5602 +1 x5603 +1 x5604 +1 x5605 +1 x5606 +1 x5607 +1 x5608 +1 x5609 +1 x5610 +1 x5611 +1 x5612 +1 x5613 +1 x5614 +1 x5615 +1 x5616 +1 x5617 +1 x5618 +1 x5619 +1 x5620 +1 x5621 +1 x5622 +1 x5623 +1 x5624 +1 x5625 +1 x5626 +1 x5627 +1 x5628 +1 x5629 +1 x5630 +1 x5631 +1 x5632 +1 x8321 +1 x8322 +1 x8323 +1 x8324 +1 x8325 +1 x8326 +1 x8327 +1 x8328 +1 x8329 +1 x8330 +1 x8331 +1 x8332 +1 x8333 +1 x8334 +1 x8335 +1 x8336 +1 x8337 +1 x8338 +1 x8339 +1 x8340 +1 x8341 +1 x8342 +1 x8343 +1 x8344 +1 x8345 +1 x8346 +1 x8347 +1 x8348 +1 x8349 +1 x8350 +1 x8351 +1 x8352 +1 x8353 +1 x8354 +1 x8355 +1 x8356 +1 x8357 +1 x8358 +1 x8359 +1 x8360 +1 x8361 +1 x8362 +1 x8363 +1 x8364 +1 x8365 +1 x8366 +1 x8367 +1 x8368 +1 x8369 +1 x8370 +1 x8371 +1 x8372 +1 x8373 +1 x8374 +1 x8375 +1 x8376 +1 x8377 +1 x8378 +1 x8379 +1 x8380 +1 x8381 +1 x8382 +1 x8383 +1 x8384 +1 x8385 +1 x8386 +1 x8387 +1 x8388 +1 x8389 +1 x8390 +1 x8391 +1 x8392 +1 x8393 +1 x8394 +1 x8395 +1 x8396 +1 x8397 +1 x8398 +1 x8399 +1 x8400 +1 x8401 +1 x8402 +1 x8403 +1 x8404 +1 x8405 +1 x8406 +1 x8407 +1 x8408 +1 x8409 +1 x8410 +1 x8411 +1 x8412 +1 x8413 +1 x8414 +1 x8415 +1 x8416 +1 x8417 +1 x8418 +1 x8419 +1 x8420 +1 x8421 +1 x8422 +1 x8423 +1 x8424 +1 x8425 +1 x8426 +1 x8427 +1 x8428 +1 x8429 +1 x8430 +1 x8431 +1 x8432 +1 x8433 +1 x8434 +1 x8435 +1 x8436 +1 x8437 +1 x8438 +1 x8439 +1 x8440 +1 x8441 +1 x8442 +1 x8443 +1 x8444 +1 x8445 +1 x8446 +1 x8447 +1 x8448 = 0 ;+-2 x12824 +1 x5633 +1 x5634 +1 x5635 +1 x5636 +1 x5637 +1 x5638 +1 x5639 +1 x5640 +1 x5641 +1 x5642 +1 x5643 +1 x5644 +1 x5645 +1 x5646 +1 x5647 +1 x5648 +1 x5649 +1 x5650 +1 x5651 +1 x5652 +1 x5653 +1 x5654 +1 x5655 +1 x5656 +1 x5657 +1 x5658 +1 x5659 +1 x5660 +1 x5661 +1 x5662 +1 x5663 +1 x5664 +1 x5665 +1 x5666 +1 x5667 +1 x5668 +1 x5669 +1 x5670 +1 x5671 +1 x5672 +1 x5673 +1 x5674 +1 x5675 +1 x5676 +1 x5677 +1 x5678 +1 x5679 +1 x5680 +1 x5681 +1 x5682 +1 x5683 +1 x5684 +1 x5685 +1 x5686 +1 x5687 +1 x5688 +1 x5689 +1 x5690 +1 x5691 +1 x5692 +1 x5693 +1 x5694 +1 x5695 +1 x5696 +1 x5697 +1 x5698 +1 x5699 +1 x5700 +1 x5701 +1 x5702 +1 x5703 +1 x5704 +1 x5705 +1 x5706 +1 x5707 +1 x5708 +1 x5709 +1 x5710 +1 x5711 +1 x5712 +1 x5713 +1 x5714 +1 x5715 +1 x5716 +1 x5717 +1 x5718 +1 x5719 +1 x5720 +1 x5721 +1 x5722 +1 x5723 +1 x5724 +1 x5725 +1 x5726 +1 x5727 +1 x5728 +1 x5729 +1 x5730 +1 x5731 +1 x5732 +1 x5733 +1 x5734 +1 x5735 +1 x5736 +1 x5737 +1 x5738 +1 x5739 +1 x5740 +1 x5741 +1 x5742 +1 x5743 +1 x5744 +1 x5745 +1 x5746 +1 x5747 +1 x5748 +1 x5749 +1 x5750 +1 x5751 +1 x5752 +1 x5753 +1 x5754 +1 x5755 +1 x5756 +1 x5757 +1 x5758 +1 x5759 +1 x5760 +1 x5761 +1 x5762 +1 x5763 +1 x5764 +1 x5765 +1 x5766 +1 x5767 +1 x5768 +1 x5769 +1 x5770 +1 x5771 +1 x5772 +1 x5773 +1 x5774 +1 x5775 +1 x5776 +1 x5777 +1 x5778 +1 x5779 +1 x5780 +1 x5781 +1 x5782 +1 x5783 +1 x5784 +1 x5785 +1 x5786 +1 x5787 +1 x5788 +1 x5789 +1 x5790 +1 x5791 +1 x5792 +1 x5793 +1 x5794 +1 x5795 +1 x5796 +1 x5797 +1 x5798 +1 x5799 +1 x5800 +1 x5801 +1 x5802 +1 x5803 +1 x5804 +1 x5805 +1 x5806 +1 x5807 +1 x5808 +1 x5809 +1 x5810 +1 x5811 +1 x5812 +1 x5813 +1 x5814 +1 x5815 +1 x5816 +1 x5817 +1 x5818 +1 x5819 +1 x5820 +1 x5821 +1 x5822 +1 x5823 +1 x5824 +1 x5825 +1 x5826 +1 x5827 +1 x5828 +1 x5829 +1 x5830 +1 x5831 +1 x5832 +1 x5833 +1 x5834 +1 x5835 +1 x5836 +1 x5837 +1 x5838 +1 x5839 +1 x5840 +1 x5841 +1 x5842 +1 x5843 +1 x5844 +1 x5845 +1 x5846 +1 x5847 +1 x5848 +1 x5849 +1 x5850 +1 x5851 +1 x5852 +1 x5853 +1 x5854 +1 x5855 +1 x5856 +1 x5857 +1 x5858 +1 x5859 +1 x5860 +1 x5861 +1 x5862 +1 x5863 +1 x5864 +1 x5865 +1 x5866 +1 x5867 +1 x5868 +1 x5869 +1 x5870 +1 x5871 +1 x5872 +1 x5873 +1 x5874 +1 x5875 +1 x5876 +1 x5877 +1 x5878 +1 x5879 +1 x5880 +1 x5881 +1 x5882 +1 x5883 +1 x5884 +1 x5885 +1 x5886 +1 x5887 +1 x5888 +1 x6785 +1 x6786 +1 x6787 +1 x6788 +1 x6789 +1 x6790 +1 x6791 +1 x6792 +1 x6793 +1 x6794 +1 x6795 +1 x6796 +1 x6797 +1 x6798 +1 x6799 +1 x6800 +1 x6801 +1 x6802 +1 x6803 +1 x6804 +1 x6805 +1 x6806 +1 x6807 +1 x6808 +1 x6809 +1 x6810 +1 x6811 +1 x6812 +1 x6813 +1 x6814 +1 x6815 +1 x6816 +1 x6817 +1 x6818 +1 x6819 +1 x6820 +1 x6821 +1 x6822 +1 x6823 +1 x6824 +1 x6825 +1 x6826 +1 x6827 +1 x6828 +1 x6829 +1 x6830 +1 x6831 +1 x6832 +1 x6833 +1 x6834 +1 x6835 +1 x6836 +1 x6837 +1 x6838 +1 x6839 +1 x6840 +1 x6841 +1 x6842 +1 x6843 +1 x6844 +1 x6845 +1 x6846 +1 x6847 +1 x6848 +1 x6849 +1 x6850 +1 x6851 +1 x6852 +1 x6853 +1 x6854 +1 x6855 +1 x6856 +1 x6857 +1 x6858 +1 x6859 +1 x6860 +1 x6861 +1 x6862 +1 x6863 +1 x6864 +1 x6865 +1 x6866 +1 x6867 +1 x6868 +1 x6869 +1 x6870 +1 x6871 +1 x6872 +1 x6873 +1 x6874 +1 x6875 +1 x6876 +1 x6877 +1 x6878 +1 x6879 +1 x6880 +1 x6881 +1 x6882 +1 x6883 +1 x6884 +1 x6885 +1 x6886 +1 x6887 +1 x6888 +1 x6889 +1 x6890 +1 x6891 +1 x6892 +1 x6893 +1 x6894 +1 x6895 +1 x6896 +1 x6897 +1 x6898 +1 x6899 +1 x6900 +1 x6901 +1 x6902 +1 x6903 +1 x6904 +1 x6905 +1 x6906 +1 x6907 +1 x6908 +1 x6909 +1 x6910 +1 x6911 +1 x6912 +1 x11649 +1 x11650 +1 x11651 +1 x11652 +1 x11653 +1 x11654 +1 x11655 +1 x11656 +1 x11657 +1 x11658 +1 x11659 +1 x11660 +1 x11661 +1 x11662 +1 x11663 +1 x11664 +1 x11665 +1 x11666 +1 x11667 +1 x11668 +1 x11669 +1 x11670 +1 x11671 +1 x11672 +1 x11673 +1 x11674 +1 x11675 +1 x11676 +1 x11677 +1 x11678 +1 x11679 +1 x11680 +1 x11681 +1 x11682 +1 x11683 +1 x11684 +1 x11685 +1 x11686 +1 x11687 +1 x11688 +1 x11689 +1 x11690 +1 x11691 +1 x11692 +1 x11693 +1 x11694 +1 x11695 +1 x11696 +1 x11697 +1 x11698 +1 x11699 +1 x11700 +1 x11701 +1 x11702 +1 x11703 +1 x11704 +1 x11705 +1 x11706 +1 x11707 +1 x11708 +1 x11709 +1 x11710 +1 x11711 +1 x11712 +1 x11713 +1 x11714 +1 x11715 +1 x11716 +1 x11717 +1 x11718 +1 x11719 +1 x11720 +1 x11721 +1 x11722 +1 x11723 +1 x11724 +1 x11725 +1 x11726 +1 x11727 +1 x11728 +1 x11729 +1 x11730 +1 x11731 +1 x11732 +1 x11733 +1 x11734 +1 x11735 +1 x11736 +1 x11737 +1 x11738 +1 x11739 +1 x11740 +1 x11741 +1 x11742 +1 x11743 +1 x11744 +1 x11745 +1 x11746 +1 x11747 +1 x11748 +1 x11749 +1 x11750 +1 x11751 +1 x11752 +1 x11753 +1 x11754 +1 x11755 +1 x11756 +1 x11757 +1 x11758 +1 x11759 +1 x11760 +1 x11761 +1 x11762 +1 x11763 +1 x11764 +1 x11765 +1 x11766 +1 x11767 +1 x11768 +1 x11769 +1 x11770 +1 x11771 +1 x11772 +1 x11773 +1 x11774 +1 x11775 +1 x11776 = 0 ;+-2 x12825 +1 x5889 +1 x5890 +1 x5891 +1 x5892 +1 x5893 +1 x5894 +1 x5895 +1 x5896 +1 x5897 +1 x5898 +1 x5899 +1 x5900 +1 x5901 +1 x5902 +1 x5903 +1 x5904 +1 x5905 +1 x5906 +1 x5907 +1 x5908 +1 x5909 +1 x5910 +1 x5911 +1 x5912 +1 x5913 +1 x5914 +1 x5915 +1 x5916 +1 x5917 +1 x5918 +1 x5919 +1 x5920 +1 x5921 +1 x5922 +1 x5923 +1 x5924 +1 x5925 +1 x5926 +1 x5927 +1 x5928 +1 x5929 +1 x5930 +1 x5931 +1 x5932 +1 x5933 +1 x5934 +1 x5935 +1 x5936 +1 x5937 +1 x5938 +1 x5939 +1 x5940 +1 x5941 +1 x5942 +1 x5943 +1 x5944 +1 x5945 +1 x5946 +1 x5947 +1 x5948 +1 x5949 +1 x5950 +1 x5951 +1 x5952 +1 x5953 +1 x5954 +1 x5955 +1 x5956 +1 x5957 +1 x5958 +1 x5959 +1 x5960 +1 x5961 +1 x5962 +1 x5963 +1 x5964 +1 x5965 +1 x5966 +1 x5967 +1 x5968 +1 x5969 +1 x5970 +1 x5971 +1 x5972 +1 x5973 +1 x5974 +1 x5975 +1 x5976 +1 x5977 +1 x5978 +1 x5979 +1 x5980 +1 x5981 +1 x5982 +1 x5983 +1 x5984 +1 x5985 +1 x5986 +1 x5987 +1 x5988 +1 x5989 +1 x5990 +1 x5991 +1 x5992 +1 x5993 +1 x5994 +1 x5995 +1 x5996 +1 x5997 +1 x5998 +1 x5999 +1 x6000 +1 x6001 +1 x6002 +1 x6003 +1 x6004 +1 x6005 +1 x6006 +1 x6007 +1 x6008 +1 x6009 +1 x6010 +1 x6011 +1 x6012 +1 x6013 +1 x6014 +1 x6015 +1 x6016 +1 x6017 +1 x6018 +1 x6019 +1 x6020 +1 x6021 +1 x6022 +1 x6023 +1 x6024 +1 x6025 +1 x6026 +1 x6027 +1 x6028 +1 x6029 +1 x6030 +1 x6031 +1 x6032 +1 x6033 +1 x6034 +1 x6035 +1 x6036 +1 x6037 +1 x6038 +1 x6039 +1 x6040 +1 x6041 +1 x6042 +1 x6043 +1 x6044 +1 x6045 +1 x6046 +1 x6047 +1 x6048 +1 x6049 +1 x6050 +1 x6051 +1 x6052 +1 x6053 +1 x6054 +1 x6055 +1 x6056 +1 x6057 +1 x6058 +1 x6059 +1 x6060 +1 x6061 +1 x6062 +1 x6063 +1 x6064 +1 x6065 +1 x6066 +1 x6067 +1 x6068 +1 x6069 +1 x6070 +1 x6071 +1 x6072 +1 x6073 +1 x6074 +1 x6075 +1 x6076 +1 x6077 +1 x6078 +1 x6079 +1 x6080 +1 x6081 +1 x6082 +1 x6083 +1 x6084 +1 x6085 +1 x6086 +1 x6087 +1 x6088 +1 x6089 +1 x6090 +1 x6091 +1 x6092 +1 x6093 +1 x6094 +1 x6095 +1 x6096 +1 x6097 +1 x6098 +1 x6099 +1 x6100 +1 x6101 +1 x6102 +1 x6103 +1 x6104 +1 x6105 +1 x6106 +1 x6107 +1 x6108 +1 x6109 +1 x6110 +1 x6111 +1 x6112 +1 x6113 +1 x6114 +1 x6115 +1 x6116 +1 x6117 +1 x6118 +1 x6119 +1 x6120 +1 x6121 +1 x6122 +1 x6123 +1 x6124 +1 x6125 +1 x6126 +1 x6127 +1 x6128 +1 x6129 +1 x6130 +1 x6131 +1 x6132 +1 x6133 +1 x6134 +1 x6135 +1 x6136 +1 x6137 +1 x6138 +1 x6139 +1 x6140 +1 x6141 +1 x6142 +1 x6143 +1 x6144 +1 x9345 +1 x9346 +1 x9347 +1 x9348 +1 x9349 +1 x9350 +1 x9351 +1 x9352 +1 x9353 +1 x9354 +1 x9355 +1 x9356 +1 x9357 +1 x9358 +1 x9359 +1 x9360 +1 x9361 +1 x9362 +1 x9363 +1 x9364 +1 x9365 +1 x9366 +1 x9367 +1 x9368 +1 x9369 +1 x9370 +1 x9371 +1 x9372 +1 x9373 +1 x9374 +1 x9375 +1 x9376 +1 x9377 +1 x9378 +1 x9379 +1 x9380 +1 x9381 +1 x9382 +1 x9383 +1 x9384 +1 x9385 +1 x9386 +1 x9387 +1 x9388 +1 x9389 +1 x9390 +1 x9391 +1 x9392 +1 x9393 +1 x9394 +1 x9395 +1 x9396 +1 x9397 +1 x9398 +1 x9399 +1 x9400 +1 x9401 +1 x9402 +1 x9403 +1 x9404 +1 x9405 +1 x9406 +1 x9407 +1 x9408 +1 x9409 +1 x9410 +1 x9411 +1 x9412 +1 x9413 +1 x9414 +1 x9415 +1 x9416 +1 x9417 +1 x9418 +1 x9419 +1 x9420 +1 x9421 +1 x9422 +1 x9423 +1 x9424 +1 x9425 +1 x9426 +1 x9427 +1 x9428 +1 x9429 +1 x9430 +1 x9431 +1 x9432 +1 x9433 +1 x9434 +1 x9435 +1 x9436 +1 x9437 +1 x9438 +1 x9439 +1 x9440 +1 x9441 +1 x9442 +1 x9443 +1 x9444 +1 x9445 +1 x9446 +1 x9447 +1 x9448 +1 x9449 +1 x9450 +1 x9451 +1 x9452 +1 x9453 +1 x9454 +1 x9455 +1 x9456 +1 x9457 +1 x9458 +1 x9459 +1 x9460 +1 x9461 +1 x9462 +1 x9463 +1 x9464 +1 x9465 +1 x9466 +1 x9467 +1 x9468 +1 x9469 +1 x9470 +1 x9471 +1 x9472 = 0 ;+-2 x12826 +1 x6145 +1 x6146 +1 x6147 +1 x6148 +1 x6149 +1 x6150 +1 x6151 +1 x6152 +1 x6153 +1 x6154 +1 x6155 +1 x6156 +1 x6157 +1 x6158 +1 x6159 +1 x6160 +1 x6161 +1 x6162 +1 x6163 +1 x6164 +1 x6165 +1 x6166 +1 x6167 +1 x6168 +1 x6169 +1 x6170 +1 x6171 +1 x6172 +1 x6173 +1 x6174 +1 x6175 +1 x6176 +1 x6177 +1 x6178 +1 x6179 +1 x6180 +1 x6181 +1 x6182 +1 x6183 +1 x6184 +1 x6185 +1 x6186 +1 x6187 +1 x6188 +1 x6189 +1 x6190 +1 x6191 +1 x6192 +1 x6193 +1 x6194 +1 x6195 +1 x6196 +1 x6197 +1 x6198 +1 x6199 +1 x6200 +1 x6201 +1 x6202 +1 x6203 +1 x6204 +1 x6205 +1 x6206 +1 x6207 +1 x6208 +1 x6209 +1 x6210 +1 x6211 +1 x6212 +1 x6213 +1 x6214 +1 x6215 +1 x6216 +1 x6217 +1 x6218 +1 x6219 +1 x6220 +1 x6221 +1 x6222 +1 x6223 +1 x6224 +1 x6225 +1 x6226 +1 x6227 +1 x6228 +1 x6229 +1 x6230 +1 x6231 +1 x6232 +1 x6233 +1 x6234 +1 x6235 +1 x6236 +1 x6237 +1 x6238 +1 x6239 +1 x6240 +1 x6241 +1 x6242 +1 x6243 +1 x6244 +1 x6245 +1 x6246 +1 x6247 +1 x6248 +1 x6249 +1 x6250 +1 x6251 +1 x6252 +1 x6253 +1 x6254 +1 x6255 +1 x6256 +1 x6257 +1 x6258 +1 x6259 +1 x6260 +1 x6261 +1 x6262 +1 x6263 +1 x6264 +1 x6265 +1 x6266 +1 x6267 +1 x6268 +1 x6269 +1 x6270 +1 x6271 +1 x6272 +1 x6273 +1 x6274 +1 x6275 +1 x6276 +1 x6277 +1 x6278 +1 x6279 +1 x6280 +1 x6281 +1 x6282 +1 x6283 +1 x6284 +1 x6285 +1 x6286 +1 x6287 +1 x6288 +1 x6289 +1 x6290 +1 x6291 +1 x6292 +1 x6293 +1 x6294 +1 x6295 +1 x6296 +1 x6297 +1 x6298 +1 x6299 +1 x6300 +1 x6301 +1 x6302 +1 x6303 +1 x6304 +1 x6305 +1 x6306 +1 x6307 +1 x6308 +1 x6309 +1 x6310 +1 x6311 +1 x6312 +1 x6313 +1 x6314 +1 x6315 +1 x6316 +1 x6317 +1 x6318 +1 x6319 +1 x6320 +1 x6321 +1 x6322 +1 x6323 +1 x6324 +1 x6325 +1 x6326 +1 x6327 +1 x6328 +1 x6329 +1 x6330 +1 x6331 +1 x6332 +1 x6333 +1 x6334 +1 x6335 +1 x6336 +1 x6337 +1 x6338 +1 x6339 +1 x6340 +1 x6341 +1 x6342 +1 x6343 +1 x6344 +1 x6345 +1 x6346 +1 x6347 +1 x6348 +1 x6349 +1 x6350 +1 x6351 +1 x6352 +1 x6353 +1 x6354 +1 x6355 +1 x6356 +1 x6357 +1 x6358 +1 x6359 +1 x6360 +1 x6361 +1 x6362 +1 x6363 +1 x6364 +1 x6365 +1 x6366 +1 x6367 +1 x6368 +1 x6369 +1 x6370 +1 x6371 +1 x6372 +1 x6373 +1 x6374 +1 x6375 +1 x6376 +1 x6377 +1 x6378 +1 x6379 +1 x6380 +1 x6381 +1 x6382 +1 x6383 +1 x6384 +1 x6385 +1 x6386 +1 x6387 +1 x6388 +1 x6389 +1 x6390 +1 x6391 +1 x6392 +1 x6393 +1 x6394 +1 x6395 +1 x6396 +1 x6397 +1 x6398 +1 x6399 +1 x6400 +1 x8449 +1 x8450 +1 x8451 +1 x8452 +1 x8453 +1 x8454 +1 x8455 +1 x8456 +1 x8457 +1 x8458 +1 x8459 +1 x8460 +1 x8461 +1 x8462 +1 x8463 +1 x8464 +1 x8465 +1 x8466 +1 x8467 +1 x8468 +1 x8469 +1 x8470 +1 x8471 +1 x8472 +1 x8473 +1 x8474 +1 x8475 +1 x8476 +1 x8477 +1 x8478 +1 x8479 +1 x8480 +1 x8481 +1 x8482 +1 x8483 +1 x8484 +1 x8485 +1 x8486 +1 x8487 +1 x8488 +1 x8489 +1 x8490 +1 x8491 +1 x8492 +1 x8493 +1 x8494 +1 x8495 +1 x8496 +1 x8497 +1 x8498 +1 x8499 +1 x8500 +1 x8501 +1 x8502 +1 x8503 +1 x8504 +1 x8505 +1 x8506 +1 x8507 +1 x8508 +1 x8509 +1 x8510 +1 x8511 +1 x8512 +1 x8513 +1 x8514 +1 x8515 +1 x8516 +1 x8517 +1 x8518 +1 x8519 +1 x8520 +1 x8521 +1 x8522 +1 x8523 +1 x8524 +1 x8525 +1 x8526 +1 x8527 +1 x8528 +1 x8529 +1 x8530 +1 x8531 +1 x8532 +1 x8533 +1 x8534 +1 x8535 +1 x8536 +1 x8537 +1 x8538 +1 x8539 +1 x8540 +1 x8541 +1 x8542 +1 x8543 +1 x8544 +1 x8545 +1 x8546 +1 x8547 +1 x8548 +1 x8549 +1 x8550 +1 x8551 +1 x8552 +1 x8553 +1 x8554 +1 x8555 +1 x8556 +1 x8557 +1 x8558 +1 x8559 +1 x8560 +1 x8561 +1 x8562 +1 x8563 +1 x8564 +1 x8565 +1 x8566 +1 x8567 +1 x8568 +1 x8569 +1 x8570 +1 x8571 +1 x8572 +1 x8573 +1 x8574 +1 x8575 +1 x8576 +1 x11521 +1 x11522 +1 x11523 +1 x11524 +1 x11525 +1 x11526 +1 x11527 +1 x11528 +1 x11529 +1 x11530 +1 x11531 +1 x11532 +1 x11533 +1 x11534 +1 x11535 +1 x11536 +1 x11537 +1 x11538 +1 x11539 +1 x11540 +1 x11541 +1 x11542 +1 x11543 +1 x11544 +1 x11545 +1 x11546 +1 x11547 +1 x11548 +1 x11549 +1 x11550 +1 x11551 +1 x11552 +1 x11553 +1 x11554 +1 x11555 +1 x11556 +1 x11557 +1 x11558 +1 x11559 +1 x11560 +1 x11561 +1 x11562 +1 x11563 +1 x11564 +1 x11565 +1 x11566 +1 x11567 +1 x11568 +1 x11569 +1 x11570 +1 x11571 +1 x11572 +1 x11573 +1 x11574 +1 x11575 +1 x11576 +1 x11577 +1 x11578 +1 x11579 +1 x11580 +1 x11581 +1 x11582 +1 x11583 +1 x11584 +1 x11585 +1 x11586 +1 x11587 +1 x11588 +1 x11589 +1 x11590 +1 x11591 +1 x11592 +1 x11593 +1 x11594 +1 x11595 +1 x11596 +1 x11597 +1 x11598 +1 x11599 +1 x11600 +1 x11601 +1 x11602 +1 x11603 +1 x11604 +1 x11605 +1 x11606 +1 x11607 +1 x11608 +1 x11609 +1 x11610 +1 x11611 +1 x11612 +1 x11613 +1 x11614 +1 x11615 +1 x11616 +1 x11617 +1 x11618 +1 x11619 +1 x11620 +1 x11621 +1 x11622 +1 x11623 +1 x11624 +1 x11625 +1 x11626 +1 x11627 +1 x11628 +1 x11629 +1 x11630 +1 x11631 +1 x11632 +1 x11633 +1 x11634 +1 x11635 +1 x11636 +1 x11637 +1 x11638 +1 x11639 +1 x11640 +1 x11641 +1 x11642 +1 x11643 +1 x11644 +1 x11645 +1 x11646 +1 x11647 +1 x11648 +1 x11777 +1 x11778 +1 x11779 +1 x11780 +1 x11781 +1 x11782 +1 x11783 +1 x11784 +1 x11785 +1 x11786 +1 x11787 +1 x11788 +1 x11789 +1 x11790 +1 x11791 +1 x11792 +1 x11793 +1 x11794 +1 x11795 +1 x11796 +1 x11797 +1 x11798 +1 x11799 +1 x11800 +1 x11801 +1 x11802 +1 x11803 +1 x11804 +1 x11805 +1 x11806 +1 x11807 +1 x11808 +1 x11809 +1 x11810 +1 x11811 +1 x11812 +1 x11813 +1 x11814 +1 x11815 +1 x11816 +1 x11817 +1 x11818 +1 x11819 +1 x11820 +1 x11821 +1 x11822 +1 x11823 +1 x11824 +1 x11825 +1 x11826 +1 x11827 +1 x11828 +1 x11829 +1 x11830 +1 x11831 +1 x11832 +1 x11833 +1 x11834 +1 x11835 +1 x11836 +1 x11837 +1 x11838 +1 x11839 +1 x11840 +1 x11841 +1 x11842 +1 x11843 +1 x11844 +1 x11845 +1 x11846 +1 x11847 +1 x11848 +1 x11849 +1 x11850 +1 x11851 +1 x11852 +1 x11853 +1 x11854 +1 x11855 +1 x11856 +1 x11857 +1 x11858 +1 x11859 +1 x11860 +1 x11861 +1 x11862 +1 x11863 +1 x11864 +1 x11865 +1 x11866 +1 x11867 +1 x11868 +1 x11869 +1 x11870 +1 x11871 +1 x11872 +1 x11873 +1 x11874 +1 x11875 +1 x11876 +1 x11877 +1 x11878 +1 x11879 +1 x11880 +1 x11881 +1 x11882 +1 x11883 +1 x11884 +1 x11885 +1 x11886 +1 x11887 +1 x11888 +1 x11889 +1 x11890 +1 x11891 +1 x11892 +1 x11893 +1 x11894 +1 x11895 +1 x11896 +1 x11897 +1 x11898 +1 x11899 +1 x11900 +1 x11901 +1 x11902 +1 x11903 +1 x11904 = 0 ;+-2 x12827 +1 x6401 +1 x6402 +1 x6403 +1 x6404 +1 x6405 +1 x6406 +1 x6407 +1 x6408 +1 x6409 +1 x6410 +1 x6411 +1 x6412 +1 x6413 +1 x6414 +1 x6415 +1 x6416 +1 x6417 +1 x6418 +1 x6419 +1 x6420 +1 x6421 +1 x6422 +1 x6423 +1 x6424 +1 x6425 +1 x6426 +1 x6427 +1 x6428 +1 x6429 +1 x6430 +1 x6431 +1 x6432 +1 x6433 +1 x6434 +1 x6435 +1 x6436 +1 x6437 +1 x6438 +1 x6439 +1 x6440 +1 x6441 +1 x6442 +1 x6443 +1 x6444 +1 x6445 +1 x6446 +1 x6447 +1 x6448 +1 x6449 +1 x6450 +1 x6451 +1 x6452 +1 x6453 +1 x6454 +1 x6455 +1 x6456 +1 x6457 +1 x6458 +1 x6459 +1 x6460 +1 x6461 +1 x6462 +1 x6463 +1 x6464 +1 x6465 +1 x6466 +1 x6467 +1 x6468 +1 x6469 +1 x6470 +1 x6471 +1 x6472 +1 x6473 +1 x6474 +1 x6475 +1 x6476 +1 x6477 +1 x6478 +1 x6479 +1 x6480 +1 x6481 +1 x6482 +1 x6483 +1 x6484 +1 x6485 +1 x6486 +1 x6487 +1 x6488 +1 x6489 +1 x6490 +1 x6491 +1 x6492 +1 x6493 +1 x6494 +1 x6495 +1 x6496 +1 x6497 +1 x6498 +1 x6499 +1 x6500 +1 x6501 +1 x6502 +1 x6503 +1 x6504 +1 x6505 +1 x6506 +1 x6507 +1 x6508 +1 x6509 +1 x6510 +1 x6511 +1 x6512 +1 x6513 +1 x6514 +1 x6515 +1 x6516 +1 x6517 +1 x6518 +1 x6519 +1 x6520 +1 x6521 +1 x6522 +1 x6523 +1 x6524 +1 x6525 +1 x6526 +1 x6527 +1 x6528 +1 x6529 +1 x6530 +1 x6531 +1 x6532 +1 x6533 +1 x6534 +1 x6535 +1 x6536 +1 x6537 +1 x6538 +1 x6539 +1 x6540 +1 x6541 +1 x6542 +1 x6543 +1 x6544 +1 x6545 +1 x6546 +1 x6547 +1 x6548 +1 x6549 +1 x6550 +1 x6551 +1 x6552 +1 x6553 +1 x6554 +1 x6555 +1 x6556 +1 x6557 +1 x6558 +1 x6559 +1 x6560 +1 x6561 +1 x6562 +1 x6563 +1 x6564 +1 x6565 +1 x6566 +1 x6567 +1 x6568 +1 x6569 +1 x6570 +1 x6571 +1 x6572 +1 x6573 +1 x6574 +1 x6575 +1 x6576 +1 x6577 +1 x6578 +1 x6579 +1 x6580 +1 x6581 +1 x6582 +1 x6583 +1 x6584 +1 x6585 +1 x6586 +1 x6587 +1 x6588 +1 x6589 +1 x6590 +1 x6591 +1 x6592 +1 x6593 +1 x6594 +1 x6595 +1 x6596 +1 x6597 +1 x6598 +1 x6599 +1 x6600 +1 x6601 +1 x6602 +1 x6603 +1 x6604 +1 x6605 +1 x6606 +1 x6607 +1 x6608 +1 x6609 +1 x6610 +1 x6611 +1 x6612 +1 x6613 +1 x6614 +1 x6615 +1 x6616 +1 x6617 +1 x6618 +1 x6619 +1 x6620 +1 x6621 +1 x6622 +1 x6623 +1 x6624 +1 x6625 +1 x6626 +1 x6627 +1 x6628 +1 x6629 +1 x6630 +1 x6631 +1 x6632 +1 x6633 +1 x6634 +1 x6635 +1 x6636 +1 x6637 +1 x6638 +1 x6639 +1 x6640 +1 x6641 +1 x6642 +1 x6643 +1 x6644 +1 x6645 +1 x6646 +1 x6647 +1 x6648 +1 x6649 +1 x6650 +1 x6651 +1 x6652 +1 x6653 +1 x6654 +1 x6655 +1 x6656 = 0 ;+-2 x12828 +1 x6657 +1 x6658 +1 x6659 +1 x6660 +1 x6661 +1 x6662 +1 x6663 +1 x6664 +1 x6665 +1 x6666 +1 x6667 +1 x6668 +1 x6669 +1 x6670 +1 x6671 +1 x6672 +1 x6673 +1 x6674 +1 x6675 +1 x6676 +1 x6677 +1 x6678 +1 x6679 +1 x6680 +1 x6681 +1 x6682 +1 x6683 +1 x6684 +1 x6685 +1 x6686 +1 x6687 +1 x6688 +1 x6689 +1 x6690 +1 x6691 +1 x6692 +1 x6693 +1 x6694 +1 x6695 +1 x6696 +1 x6697 +1 x6698 +1 x6699 +1 x6700 +1 x6701 +1 x6702 +1 x6703 +1 x6704 +1 x6705 +1 x6706 +1 x6707 +1 x6708 +1 x6709 +1 x6710 +1 x6711 +1 x6712 +1 x6713 +1 x6714 +1 x6715 +1 x6716 +1 x6717 +1 x6718 +1 x6719 +1 x6720 +1 x6721 +1 x6722 +1 x6723 +1 x6724 +1 x6725 +1 x6726 +1 x6727 +1 x6728 +1 x6729 +1 x6730 +1 x6731 +1 x6732 +1 x6733 +1 x6734 +1 x6735 +1 x6736 +1 x6737 +1 x6738 +1 x6739 +1 x6740 +1 x6741 +1 x6742 +1 x6743 +1 x6744 +1 x6745 +1 x6746 +1 x6747 +1 x6748 +1 x6749 +1 x6750 +1 x6751 +1 x6752 +1 x6753 +1 x6754 +1 x6755 +1 x6756 +1 x6757 +1 x6758 +1 x6759 +1 x6760 +1 x6761 +1 x6762 +1 x6763 +1 x6764 +1 x6765 +1 x6766 +1 x6767 +1 x6768 +1 x6769 +1 x6770 +1 x6771 +1 x6772 +1 x6773 +1 x6774 +1 x6775 +1 x6776 +1 x6777 +1 x6778 +1 x6779 +1 x6780 +1 x6781 +1 x6782 +1 x6783 +1 x6784 +1 x6785 +1 x6786 +1 x6787 +1 x6788 +1 x6789 +1 x6790 +1 x6791 +1 x6792 +1 x6793 +1 x6794 +1 x6795 +1 x6796 +1 x6797 +1 x6798 +1 x6799 +1 x6800 +1 x6801 +1 x6802 +1 x6803 +1 x6804 +1 x6805 +1 x6806 +1 x6807 +1 x6808 +1 x6809 +1 x6810 +1 x6811 +1 x6812 +1 x6813 +1 x6814 +1 x6815 +1 x6816 +1 x6817 +1 x6818 +1 x6819 +1 x6820 +1 x6821 +1 x6822 +1 x6823 +1 x6824 +1 x6825 +1 x6826 +1 x6827 +1 x6828 +1 x6829 +1 x6830 +1 x6831 +1 x6832 +1 x6833 +1 x6834 +1 x6835 +1 x6836 +1 x6837 +1 x6838 +1 x6839 +1 x6840 +1 x6841 +1 x6842 +1 x6843 +1 x6844 +1 x6845 +1 x6846 +1 x6847 +1 x6848 +1 x6849 +1 x6850 +1 x6851 +1 x6852 +1 x6853 +1 x6854 +1 x6855 +1 x6856 +1 x6857 +1 x6858 +1 x6859 +1 x6860 +1 x6861 +1 x6862 +1 x6863 +1 x6864 +1 x6865 +1 x6866 +1 x6867 +1 x6868 +1 x6869 +1 x6870 +1 x6871 +1 x6872 +1 x6873 +1 x6874 +1 x6875 +1 x6876 +1 x6877 +1 x6878 +1 x6879 +1 x6880 +1 x6881 +1 x6882 +1 x6883 +1 x6884 +1 x6885 +1 x6886 +1 x6887 +1 x6888 +1 x6889 +1 x6890 +1 x6891 +1 x6892 +1 x6893 +1 x6894 +1 x6895 +1 x6896 +1 x6897 +1 x6898 +1 x6899 +1 x6900 +1 x6901 +1 x6902 +1 x6903 +1 x6904 +1 x6905 +1 x6906 +1 x6907 +1 x6908 +1 x6909 +1 x6910 +1 x6911 +1 x6912 +1 x10881 +1 x10882 +1 x10883 +1 x10884 +1 x10885 +1 x10886 +1 x10887 +1 x10888 +1 x10889 +1 x10890 +1 x10891 +1 x10892 +1 x10893 +1 x10894 +1 x10895 +1 x10896 +1 x10897 +1 x10898 +1 x10899 +1 x10900 +1 x10901 +1 x10902 +1 x10903 +1 x10904 +1 x10905 +1 x10906 +1 x10907 +1 x10908 +1 x10909 +1 x10910 +1 x10911 +1 x10912 +1 x10913 +1 x10914 +1 x10915 +1 x10916 +1 x10917 +1 x10918 +1 x10919 +1 x10920 +1 x10921 +1 x10922 +1 x10923 +1 x10924 +1 x10925 +1 x10926 +1 x10927 +1 x10928 +1 x10929 +1 x10930 +1 x10931 +1 x10932 +1 x10933 +1 x10934 +1 x10935 +1 x10936 +1 x10937 +1 x10938 +1 x10939 +1 x10940 +1 x10941 +1 x10942 +1 x10943 +1 x10944 +1 x10945 +1 x10946 +1 x10947 +1 x10948 +1 x10949 +1 x10950 +1 x10951 +1 x10952 +1 x10953 +1 x10954 +1 x10955 +1 x10956 +1 x10957 +1 x10958 +1 x10959 +1 x10960 +1 x10961 +1 x10962 +1 x10963 +1 x10964 +1 x10965 +1 x10966 +1 x10967 +1 x10968 +1 x10969 +1 x10970 +1 x10971 +1 x10972 +1 x10973 +1 x10974 +1 x10975 +1 x10976 +1 x10977 +1 x10978 +1 x10979 +1 x10980 +1 x10981 +1 x10982 +1 x10983 +1 x10984 +1 x10985 +1 x10986 +1 x10987 +1 x10988 +1 x10989 +1 x10990 +1 x10991 +1 x10992 +1 x10993 +1 x10994 +1 x10995 +1 x10996 +1 x10997 +1 x10998 +1 x10999 +1 x11000 +1 x11001 +1 x11002 +1 x11003 +1 x11004 +1 x11005 +1 x11006 +1 x11007 +1 x11008 = 0 ;+-2 x12829 +1 x6913 +1 x6914 +1 x6915 +1 x6916 +1 x6917 +1 x6918 +1 x6919 +1 x6920 +1 x6921 +1 x6922 +1 x6923 +1 x6924 +1 x6925 +1 x6926 +1 x6927 +1 x6928 +1 x6929 +1 x6930 +1 x6931 +1 x6932 +1 x6933 +1 x6934 +1 x6935 +1 x6936 +1 x6937 +1 x6938 +1 x6939 +1 x6940 +1 x6941 +1 x6942 +1 x6943 +1 x6944 +1 x6945 +1 x6946 +1 x6947 +1 x6948 +1 x6949 +1 x6950 +1 x6951 +1 x6952 +1 x6953 +1 x6954 +1 x6955 +1 x6956 +1 x6957 +1 x6958 +1 x6959 +1 x6960 +1 x6961 +1 x6962 +1 x6963 +1 x6964 +1 x6965 +1 x6966 +1 x6967 +1 x6968 +1 x6969 +1 x6970 +1 x6971 +1 x6972 +1 x6973 +1 x6974 +1 x6975 +1 x6976 +1 x6977 +1 x6978 +1 x6979 +1 x6980 +1 x6981 +1 x6982 +1 x6983 +1 x6984 +1 x6985 +1 x6986 +1 x6987 +1 x6988 +1 x6989 +1 x6990 +1 x6991 +1 x6992 +1 x6993 +1 x6994 +1 x6995 +1 x6996 +1 x6997 +1 x6998 +1 x6999 +1 x7000 +1 x7001 +1 x7002 +1 x7003 +1 x7004 +1 x7005 +1 x7006 +1 x7007 +1 x7008 +1 x7009 +1 x7010 +1 x7011 +1 x7012 +1 x7013 +1 x7014 +1 x7015 +1 x7016 +1 x7017 +1 x7018 +1 x7019 +1 x7020 +1 x7021 +1 x7022 +1 x7023 +1 x7024 +1 x7025 +1 x7026 +1 x7027 +1 x7028 +1 x7029 +1 x7030 +1 x7031 +1 x7032 +1 x7033 +1 x7034 +1 x7035 +1 x7036 +1 x7037 +1 x7038 +1 x7039 +1 x7040 +1 x7041 +1 x7042 +1 x7043 +1 x7044 +1 x7045 +1 x7046 +1 x7047 +1 x7048 +1 x7049 +1 x7050 +1 x7051 +1 x7052 +1 x7053 +1 x7054 +1 x7055 +1 x7056 +1 x7057 +1 x7058 +1 x7059 +1 x7060 +1 x7061 +1 x7062 +1 x7063 +1 x7064 +1 x7065 +1 x7066 +1 x7067 +1 x7068 +1 x7069 +1 x7070 +1 x7071 +1 x7072 +1 x7073 +1 x7074 +1 x7075 +1 x7076 +1 x7077 +1 x7078 +1 x7079 +1 x7080 +1 x7081 +1 x7082 +1 x7083 +1 x7084 +1 x7085 +1 x7086 +1 x7087 +1 x7088 +1 x7089 +1 x7090 +1 x7091 +1 x7092 +1 x7093 +1 x7094 +1 x7095 +1 x7096 +1 x7097 +1 x7098 +1 x7099 +1 x7100 +1 x7101 +1 x7102 +1 x7103 +1 x7104 +1 x7105 +1 x7106 +1 x7107 +1 x7108 +1 x7109 +1 x7110 +1 x7111 +1 x7112 +1 x7113 +1 x7114 +1 x7115 +1 x7116 +1 x7117 +1 x7118 +1 x7119 +1 x7120 +1 x7121 +1 x7122 +1 x7123 +1 x7124 +1 x7125 +1 x7126 +1 x7127 +1 x7128 +1 x7129 +1 x7130 +1 x7131 +1 x7132 +1 x7133 +1 x7134 +1 x7135 +1 x7136 +1 x7137 +1 x7138 +1 x7139 +1 x7140 +1 x7141 +1 x7142 +1 x7143 +1 x7144 +1 x7145 +1 x7146 +1 x7147 +1 x7148 +1 x7149 +1 x7150 +1 x7151 +1 x7152 +1 x7153 +1 x7154 +1 x7155 +1 x7156 +1 x7157 +1 x7158 +1 x7159 +1 x7160 +1 x7161 +1 x7162 +1 x7163 +1 x7164 +1 x7165 +1 x7166 +1 x7167 +1 x7168 +1 x8961 +1 x8962 +1 x8963 +1 x8964 +1 x8965 +1 x8966 +1 x8967 +1 x8968 +1 x8969 +1 x8970 +1 x8971 +1 x8972 +1 x8973 +1 x8974 +1 x8975 +1 x8976 +1 x8977 +1 x8978 +1 x8979 +1 x8980 +1 x8981 +1 x8982 +1 x8983 +1 x8984 +1 x8985 +1 x8986 +1 x8987 +1 x8988 +1 x8989 +1 x8990 +1 x8991 +1 x8992 +1 x8993 +1 x8994 +1 x8995 +1 x8996 +1 x8997 +1 x8998 +1 x8999 +1 x9000 +1 x9001 +1 x9002 +1 x9003 +1 x9004 +1 x9005 +1 x9006 +1 x9007 +1 x9008 +1 x9009 +1 x9010 +1 x9011 +1 x9012 +1 x9013 +1 x9014 +1 x9015 +1 x9016 +1 x9017 +1 x9018 +1 x9019 +1 x9020 +1 x9021 +1 x9022 +1 x9023 +1 x9024 +1 x9025 +1 x9026 +1 x9027 +1 x9028 +1 x9029 +1 x9030 +1 x9031 +1 x9032 +1 x9033 +1 x9034 +1 x9035 +1 x9036 +1 x9037 +1 x9038 +1 x9039 +1 x9040 +1 x9041 +1 x9042 +1 x9043 +1 x9044 +1 x9045 +1 x9046 +1 x9047 +1 x9048 +1 x9049 +1 x9050 +1 x9051 +1 x9052 +1 x9053 +1 x9054 +1 x9055 +1 x9056 +1 x9057 +1 x9058 +1 x9059 +1 x9060 +1 x9061 +1 x9062 +1 x9063 +1 x9064 +1 x9065 +1 x9066 +1 x9067 +1 x9068 +1 x9069 +1 x9070 +1 x9071 +1 x9072 +1 x9073 +1 x9074 +1 x9075 +1 x9076 +1 x9077 +1 x9078 +1 x9079 +1 x9080 +1 x9081 +1 x9082 +1 x9083 +1 x9084 +1 x9085 +1 x9086 +1 x9087 +1 x9088 = 0 ;+-2 x12830 +1 x7169 +1 x7170 +1 x7171 +1 x7172 +1 x7173 +1 x7174 +1 x7175 +1 x7176 +1 x7177 +1 x7178 +1 x7179 +1 x7180 +1 x7181 +1 x7182 +1 x7183 +1 x7184 +1 x7185 +1 x7186 +1 x7187 +1 x7188 +1 x7189 +1 x7190 +1 x7191 +1 x7192 +1 x7193 +1 x7194 +1 x7195 +1 x7196 +1 x7197 +1 x7198 +1 x7199 +1 x7200 +1 x7201 +1 x7202 +1 x7203 +1 x7204 +1 x7205 +1 x7206 +1 x7207 +1 x7208 +1 x7209 +1 x7210 +1 x7211 +1 x7212 +1 x7213 +1 x7214 +1 x7215 +1 x7216 +1 x7217 +1 x7218 +1 x7219 +1 x7220 +1 x7221 +1 x7222 +1 x7223 +1 x7224 +1 x7225 +1 x7226 +1 x7227 +1 x7228 +1 x7229 +1 x7230 +1 x7231 +1 x7232 +1 x7233 +1 x7234 +1 x7235 +1 x7236 +1 x7237 +1 x7238 +1 x7239 +1 x7240 +1 x7241 +1 x7242 +1 x7243 +1 x7244 +1 x7245 +1 x7246 +1 x7247 +1 x7248 +1 x7249 +1 x7250 +1 x7251 +1 x7252 +1 x7253 +1 x7254 +1 x7255 +1 x7256 +1 x7257 +1 x7258 +1 x7259 +1 x7260 +1 x7261 +1 x7262 +1 x7263 +1 x7264 +1 x7265 +1 x7266 +1 x7267 +1 x7268 +1 x7269 +1 x7270 +1 x7271 +1 x7272 +1 x7273 +1 x7274 +1 x7275 +1 x7276 +1 x7277 +1 x7278 +1 x7279 +1 x7280 +1 x7281 +1 x7282 +1 x7283 +1 x7284 +1 x7285 +1 x7286 +1 x7287 +1 x7288 +1 x7289 +1 x7290 +1 x7291 +1 x7292 +1 x7293 +1 x7294 +1 x7295 +1 x7296 +1 x7297 +1 x7298 +1 x7299 +1 x7300 +1 x7301 +1 x7302 +1 x7303 +1 x7304 +1 x7305 +1 x7306 +1 x7307 +1 x7308 +1 x7309 +1 x7310 +1 x7311 +1 x7312 +1 x7313 +1 x7314 +1 x7315 +1 x7316 +1 x7317 +1 x7318 +1 x7319 +1 x7320 +1 x7321 +1 x7322 +1 x7323 +1 x7324 +1 x7325 +1 x7326 +1 x7327 +1 x7328 +1 x7329 +1 x7330 +1 x7331 +1 x7332 +1 x7333 +1 x7334 +1 x7335 +1 x7336 +1 x7337 +1 x7338 +1 x7339 +1 x7340 +1 x7341 +1 x7342 +1 x7343 +1 x7344 +1 x7345 +1 x7346 +1 x7347 +1 x7348 +1 x7349 +1 x7350 +1 x7351 +1 x7352 +1 x7353 +1 x7354 +1 x7355 +1 x7356 +1 x7357 +1 x7358 +1 x7359 +1 x7360 +1 x7361 +1 x7362 +1 x7363 +1 x7364 +1 x7365 +1 x7366 +1 x7367 +1 x7368 +1 x7369 +1 x7370 +1 x7371 +1 x7372 +1 x7373 +1 x7374 +1 x7375 +1 x7376 +1 x7377 +1 x7378 +1 x7379 +1 x7380 +1 x7381 +1 x7382 +1 x7383 +1 x7384 +1 x7385 +1 x7386 +1 x7387 +1 x7388 +1 x7389 +1 x7390 +1 x7391 +1 x7392 +1 x7393 +1 x7394 +1 x7395 +1 x7396 +1 x7397 +1 x7398 +1 x7399 +1 x7400 +1 x7401 +1 x7402 +1 x7403 +1 x7404 +1 x7405 +1 x7406 +1 x7407 +1 x7408 +1 x7409 +1 x7410 +1 x7411 +1 x7412 +1 x7413 +1 x7414 +1 x7415 +1 x7416 +1 x7417 +1 x7418 +1 x7419 +1 x7420 +1 x7421 +1 x7422 +1 x7423 +1 x7424 = 0 ;+-2 x12831 +1 x7425 +1 x7426 +1 x7427 +1 x7428 +1 x7429 +1 x7430 +1 x7431 +1 x7432 +1 x7433 +1 x7434 +1 x7435 +1 x7436 +1 x7437 +1 x7438 +1 x7439 +1 x7440 +1 x7441 +1 x7442 +1 x7443 +1 x7444 +1 x7445 +1 x7446 +1 x7447 +1 x7448 +1 x7449 +1 x7450 +1 x7451 +1 x7452 +1 x7453 +1 x7454 +1 x7455 +1 x7456 +1 x7457 +1 x7458 +1 x7459 +1 x7460 +1 x7461 +1 x7462 +1 x7463 +1 x7464 +1 x7465 +1 x7466 +1 x7467 +1 x7468 +1 x7469 +1 x7470 +1 x7471 +1 x7472 +1 x7473 +1 x7474 +1 x7475 +1 x7476 +1 x7477 +1 x7478 +1 x7479 +1 x7480 +1 x7481 +1 x7482 +1 x7483 +1 x7484 +1 x7485 +1 x7486 +1 x7487 +1 x7488 +1 x7489 +1 x7490 +1 x7491 +1 x7492 +1 x7493 +1 x7494 +1 x7495 +1 x7496 +1 x7497 +1 x7498 +1 x7499 +1 x7500 +1 x7501 +1 x7502 +1 x7503 +1 x7504 +1 x7505 +1 x7506 +1 x7507 +1 x7508 +1 x7509 +1 x7510 +1 x7511 +1 x7512 +1 x7513 +1 x7514 +1 x7515 +1 x7516 +1 x7517 +1 x7518 +1 x7519 +1 x7520 +1 x7521 +1 x7522 +1 x7523 +1 x7524 +1 x7525 +1 x7526 +1 x7527 +1 x7528 +1 x7529 +1 x7530 +1 x7531 +1 x7532 +1 x7533 +1 x7534 +1 x7535 +1 x7536 +1 x7537 +1 x7538 +1 x7539 +1 x7540 +1 x7541 +1 x7542 +1 x7543 +1 x7544 +1 x7545 +1 x7546 +1 x7547 +1 x7548 +1 x7549 +1 x7550 +1 x7551 +1 x7552 +1 x7553 +1 x7554 +1 x7555 +1 x7556 +1 x7557 +1 x7558 +1 x7559 +1 x7560 +1 x7561 +1 x7562 +1 x7563 +1 x7564 +1 x7565 +1 x7566 +1 x7567 +1 x7568 +1 x7569 +1 x7570 +1 x7571 +1 x7572 +1 x7573 +1 x7574 +1 x7575 +1 x7576 +1 x7577 +1 x7578 +1 x7579 +1 x7580 +1 x7581 +1 x7582 +1 x7583 +1 x7584 +1 x7585 +1 x7586 +1 x7587 +1 x7588 +1 x7589 +1 x7590 +1 x7591 +1 x7592 +1 x7593 +1 x7594 +1 x7595 +1 x7596 +1 x7597 +1 x7598 +1 x7599 +1 x7600 +1 x7601 +1 x7602 +1 x7603 +1 x7604 +1 x7605 +1 x7606 +1 x7607 +1 x7608 +1 x7609 +1 x7610 +1 x7611 +1 x7612 +1 x7613 +1 x7614 +1 x7615 +1 x7616 +1 x7617 +1 x7618 +1 x7619 +1 x7620 +1 x7621 +1 x7622 +1 x7623 +1 x7624 +1 x7625 +1 x7626 +1 x7627 +1 x7628 +1 x7629 +1 x7630 +1 x7631 +1 x7632 +1 x7633 +1 x7634 +1 x7635 +1 x7636 +1 x7637 +1 x7638 +1 x7639 +1 x7640 +1 x7641 +1 x7642 +1 x7643 +1 x7644 +1 x7645 +1 x7646 +1 x7647 +1 x7648 +1 x7649 +1 x7650 +1 x7651 +1 x7652 +1 x7653 +1 x7654 +1 x7655 +1 x7656 +1 x7657 +1 x7658 +1 x7659 +1 x7660 +1 x7661 +1 x7662 +1 x7663 +1 x7664 +1 x7665 +1 x7666 +1 x7667 +1 x7668 +1 x7669 +1 x7670 +1 x7671 +1 x7672 +1 x7673 +1 x7674 +1 x7675 +1 x7676 +1 x7677 +1 x7678 +1 x7679 +1 x7680 = 0 ;+-2 x12832 +1 x7681 +1 x7682 +1 x7683 +1 x7684 +1 x7685 +1 x7686 +1 x7687 +1 x7688 +1 x7689 +1 x7690 +1 x7691 +1 x7692 +1 x7693 +1 x7694 +1 x7695 +1 x7696 +1 x7697 +1 x7698 +1 x7699 +1 x7700 +1 x7701 +1 x7702 +1 x7703 +1 x7704 +1 x7705 +1 x7706 +1 x7707 +1 x7708 +1 x7709 +1 x7710 +1 x7711 +1 x7712 +1 x7713 +1 x7714 +1 x7715 +1 x7716 +1 x7717 +1 x7718 +1 x7719 +1 x7720 +1 x7721 +1 x7722 +1 x7723 +1 x7724 +1 x7725 +1 x7726 +1 x7727 +1 x7728 +1 x7729 +1 x7730 +1 x7731 +1 x7732 +1 x7733 +1 x7734 +1 x7735 +1 x7736 +1 x7737 +1 x7738 +1 x7739 +1 x7740 +1 x7741 +1 x7742 +1 x7743 +1 x7744 +1 x7745 +1 x7746 +1 x7747 +1 x7748 +1 x7749 +1 x7750 +1 x7751 +1 x7752 +1 x7753 +1 x7754 +1 x7755 +1 x7756 +1 x7757 +1 x7758 +1 x7759 +1 x7760 +1 x7761 +1 x7762 +1 x7763 +1 x7764 +1 x7765 +1 x7766 +1 x7767 +1 x7768 +1 x7769 +1 x7770 +1 x7771 +1 x7772 +1 x7773 +1 x7774 +1 x7775 +1 x7776 +1 x7777 +1 x7778 +1 x7779 +1 x7780 +1 x7781 +1 x7782 +1 x7783 +1 x7784 +1 x7785 +1 x7786 +1 x7787 +1 x7788 +1 x7789 +1 x7790 +1 x7791 +1 x7792 +1 x7793 +1 x7794 +1 x7795 +1 x7796 +1 x7797 +1 x7798 +1 x7799 +1 x7800 +1 x7801 +1 x7802 +1 x7803 +1 x7804 +1 x7805 +1 x7806 +1 x7807 +1 x7808 +1 x7809 +1 x7810 +1 x7811 +1 x7812 +1 x7813 +1 x7814 +1 x7815 +1 x7816 +1 x7817 +1 x7818 +1 x7819 +1 x7820 +1 x7821 +1 x7822 +1 x7823 +1 x7824 +1 x7825 +1 x7826 +1 x7827 +1 x7828 +1 x7829 +1 x7830 +1 x7831 +1 x7832 +1 x7833 +1 x7834 +1 x7835 +1 x7836 +1 x7837 +1 x7838 +1 x7839 +1 x7840 +1 x7841 +1 x7842 +1 x7843 +1 x7844 +1 x7845 +1 x7846 +1 x7847 +1 x7848 +1 x7849 +1 x7850 +1 x7851 +1 x7852 +1 x7853 +1 x7854 +1 x7855 +1 x7856 +1 x7857 +1 x7858 +1 x7859 +1 x7860 +1 x7861 +1 x7862 +1 x7863 +1 x7864 +1 x7865 +1 x7866 +1 x7867 +1 x7868 +1 x7869 +1 x7870 +1 x7871 +1 x7872 +1 x7873 +1 x7874 +1 x7875 +1 x7876 +1 x7877 +1 x7878 +1 x7879 +1 x7880 +1 x7881 +1 x7882 +1 x7883 +1 x7884 +1 x7885 +1 x7886 +1 x7887 +1 x7888 +1 x7889 +1 x7890 +1 x7891 +1 x7892 +1 x7893 +1 x7894 +1 x7895 +1 x7896 +1 x7897 +1 x7898 +1 x7899 +1 x7900 +1 x7901 +1 x7902 +1 x7903 +1 x7904 +1 x7905 +1 x7906 +1 x7907 +1 x7908 +1 x7909 +1 x7910 +1 x7911 +1 x7912 +1 x7913 +1 x7914 +1 x7915 +1 x7916 +1 x7917 +1 x7918 +1 x7919 +1 x7920 +1 x7921 +1 x7922 +1 x7923 +1 x7924 +1 x7925 +1 x7926 +1 x7927 +1 x7928 +1 x7929 +1 x7930 +1 x7931 +1 x7932 +1 x7933 +1 x7934 +1 x7935 +1 x7936 = 0 ;+-2 x12833 +1 x7937 +1 x7938 +1 x7939 +1 x7940 +1 x7941 +1 x7942 +1 x7943 +1 x7944 +1 x7945 +1 x7946 +1 x7947 +1 x7948 +1 x7949 +1 x7950 +1 x7951 +1 x7952 +1 x7953 +1 x7954 +1 x7955 +1 x7956 +1 x7957 +1 x7958 +1 x7959 +1 x7960 +1 x7961 +1 x7962 +1 x7963 +1 x7964 +1 x7965 +1 x7966 +1 x7967 +1 x7968 +1 x7969 +1 x7970 +1 x7971 +1 x7972 +1 x7973 +1 x7974 +1 x7975 +1 x7976 +1 x7977 +1 x7978 +1 x7979 +1 x7980 +1 x7981 +1 x7982 +1 x7983 +1 x7984 +1 x7985 +1 x7986 +1 x7987 +1 x7988 +1 x7989 +1 x7990 +1 x7991 +1 x7992 +1 x7993 +1 x7994 +1 x7995 +1 x7996 +1 x7997 +1 x7998 +1 x7999 +1 x8000 +1 x8001 +1 x8002 +1 x8003 +1 x8004 +1 x8005 +1 x8006 +1 x8007 +1 x8008 +1 x8009 +1 x8010 +1 x8011 +1 x8012 +1 x8013 +1 x8014 +1 x8015 +1 x8016 +1 x8017 +1 x8018 +1 x8019 +1 x8020 +1 x8021 +1 x8022 +1 x8023 +1 x8024 +1 x8025 +1 x8026 +1 x8027 +1 x8028 +1 x8029 +1 x8030 +1 x8031 +1 x8032 +1 x8033 +1 x8034 +1 x8035 +1 x8036 +1 x8037 +1 x8038 +1 x8039 +1 x8040 +1 x8041 +1 x8042 +1 x8043 +1 x8044 +1 x8045 +1 x8046 +1 x8047 +1 x8048 +1 x8049 +1 x8050 +1 x8051 +1 x8052 +1 x8053 +1 x8054 +1 x8055 +1 x8056 +1 x8057 +1 x8058 +1 x8059 +1 x8060 +1 x8061 +1 x8062 +1 x8063 +1 x8064 +1 x8065 +1 x8066 +1 x8067 +1 x8068 +1 x8069 +1 x8070 +1 x8071 +1 x8072 +1 x8073 +1 x8074 +1 x8075 +1 x8076 +1 x8077 +1 x8078 +1 x8079 +1 x8080 +1 x8081 +1 x8082 +1 x8083 +1 x8084 +1 x8085 +1 x8086 +1 x8087 +1 x8088 +1 x8089 +1 x8090 +1 x8091 +1 x8092 +1 x8093 +1 x8094 +1 x8095 +1 x8096 +1 x8097 +1 x8098 +1 x8099 +1 x8100 +1 x8101 +1 x8102 +1 x8103 +1 x8104 +1 x8105 +1 x8106 +1 x8107 +1 x8108 +1 x8109 +1 x8110 +1 x8111 +1 x8112 +1 x8113 +1 x8114 +1 x8115 +1 x8116 +1 x8117 +1 x8118 +1 x8119 +1 x8120 +1 x8121 +1 x8122 +1 x8123 +1 x8124 +1 x8125 +1 x8126 +1 x8127 +1 x8128 +1 x8129 +1 x8130 +1 x8131 +1 x8132 +1 x8133 +1 x8134 +1 x8135 +1 x8136 +1 x8137 +1 x8138 +1 x8139 +1 x8140 +1 x8141 +1 x8142 +1 x8143 +1 x8144 +1 x8145 +1 x8146 +1 x8147 +1 x8148 +1 x8149 +1 x8150 +1 x8151 +1 x8152 +1 x8153 +1 x8154 +1 x8155 +1 x8156 +1 x8157 +1 x8158 +1 x8159 +1 x8160 +1 x8161 +1 x8162 +1 x8163 +1 x8164 +1 x8165 +1 x8166 +1 x8167 +1 x8168 +1 x8169 +1 x8170 +1 x8171 +1 x8172 +1 x8173 +1 x8174 +1 x8175 +1 x8176 +1 x8177 +1 x8178 +1 x8179 +1 x8180 +1 x8181 +1 x8182 +1 x8183 +1 x8184 +1 x8185 +1 x8186 +1 x8187 +1 x8188 +1 x8189 +1 x8190 +1 x8191 +1 x8192 +1 x10369 +1 x10370 +1 x10371 +1 x10372 +1 x10373 +1 x10374 +1 x10375 +1 x10376 +1 x10377 +1 x10378 +1 x10379 +1 x10380 +1 x10381 +1 x10382 +1 x10383 +1 x10384 +1 x10385 +1 x10386 +1 x10387 +1 x10388 +1 x10389 +1 x10390 +1 x10391 +1 x10392 +1 x10393 +1 x10394 +1 x10395 +1 x10396 +1 x10397 +1 x10398 +1 x10399 +1 x10400 +1 x10401 +1 x10402 +1 x10403 +1 x10404 +1 x10405 +1 x10406 +1 x10407 +1 x10408 +1 x10409 +1 x10410 +1 x10411 +1 x10412 +1 x10413 +1 x10414 +1 x10415 +1 x10416 +1 x10417 +1 x10418 +1 x10419 +1 x10420 +1 x10421 +1 x10422 +1 x10423 +1 x10424 +1 x10425 +1 x10426 +1 x10427 +1 x10428 +1 x10429 +1 x10430 +1 x10431 +1 x10432 +1 x10433 +1 x10434 +1 x10435 +1 x10436 +1 x10437 +1 x10438 +1 x10439 +1 x10440 +1 x10441 +1 x10442 +1 x10443 +1 x10444 +1 x10445 +1 x10446 +1 x10447 +1 x10448 +1 x10449 +1 x10450 +1 x10451 +1 x10452 +1 x10453 +1 x10454 +1 x10455 +1 x10456 +1 x10457 +1 x10458 +1 x10459 +1 x10460 +1 x10461 +1 x10462 +1 x10463 +1 x10464 +1 x10465 +1 x10466 +1 x10467 +1 x10468 +1 x10469 +1 x10470 +1 x10471 +1 x10472 +1 x10473 +1 x10474 +1 x10475 +1 x10476 +1 x10477 +1 x10478 +1 x10479 +1 x10480 +1 x10481 +1 x10482 +1 x10483 +1 x10484 +1 x10485 +1 x10486 +1 x10487 +1 x10488 +1 x10489 +1 x10490 +1 x10491 +1 x10492 +1 x10493 +1 x10494 +1 x10495 +1 x10496 +1 x12545 +1 x12546 +1 x12547 +1 x12548 +1 x12549 +1 x12550 +1 x12551 +1 x12552 +1 x12553 +1 x12554 +1 x12555 +1 x12556 +1 x12557 +1 x12558 +1 x12559 +1 x12560 +1 x12561 +1 x12562 +1 x12563 +1 x12564 +1 x12565 +1 x12566 +1 x12567 +1 x12568 +1 x12569 +1 x12570 +1 x12571 +1 x12572 +1 x12573 +1 x12574 +1 x12575 +1 x12576 +1 x12577 +1 x12578 +1 x12579 +1 x12580 +1 x12581 +1 x12582 +1 x12583 +1 x12584 +1 x12585 +1 x12586 +1 x12587 +1 x12588 +1 x12589 +1 x12590 +1 x12591 +1 x12592 +1 x12593 +1 x12594 +1 x12595 +1 x12596 +1 x12597 +1 x12598 +1 x12599 +1 x12600 +1 x12601 +1 x12602 +1 x12603 +1 x12604 +1 x12605 +1 x12606 +1 x12607 +1 x12608 +1 x12609 +1 x12610 +1 x12611 +1 x12612 +1 x12613 +1 x12614 +1 x12615 +1 x12616 +1 x12617 +1 x12618 +1 x12619 +1 x12620 +1 x12621 +1 x12622 +1 x12623 +1 x12624 +1 x12625 +1 x12626 +1 x12627 +1 x12628 +1 x12629 +1 x12630 +1 x12631 +1 x12632 +1 x12633 +1 x12634 +1 x12635 +1 x12636 +1 x12637 +1 x12638 +1 x12639 +1 x12640 +1 x12641 +1 x12642 +1 x12643 +1 x12644 +1 x12645 +1 x12646 +1 x12647 +1 x12648 +1 x12649 +1 x12650 +1 x12651 +1 x12652 +1 x12653 +1 x12654 +1 x12655 +1 x12656 +1 x12657 +1 x12658 +1 x12659 +1 x12660 +1 x12661 +1 x12662 +1 x12663 +1 x12664 +1 x12665 +1 x12666 +1 x12667 +1 x12668 +1 x12669 +1 x12670 +1 x12671 +1 x12672 = 0 ;+-2 x12834 +1 x8193 +1 x8194 +1 x8195 +1 x8196 +1 x8197 +1 x8198 +1 x8199 +1 x8200 +1 x8201 +1 x8202 +1 x8203 +1 x8204 +1 x8205 +1 x8206 +1 x8207 +1 x8208 +1 x8209 +1 x8210 +1 x8211 +1 x8212 +1 x8213 +1 x8214 +1 x8215 +1 x8216 +1 x8217 +1 x8218 +1 x8219 +1 x8220 +1 x8221 +1 x8222 +1 x8223 +1 x8224 +1 x8225 +1 x8226 +1 x8227 +1 x8228 +1 x8229 +1 x8230 +1 x8231 +1 x8232 +1 x8233 +1 x8234 +1 x8235 +1 x8236 +1 x8237 +1 x8238 +1 x8239 +1 x8240 +1 x8241 +1 x8242 +1 x8243 +1 x8244 +1 x8245 +1 x8246 +1 x8247 +1 x8248 +1 x8249 +1 x8250 +1 x8251 +1 x8252 +1 x8253 +1 x8254 +1 x8255 +1 x8256 +1 x8257 +1 x8258 +1 x8259 +1 x8260 +1 x8261 +1 x8262 +1 x8263 +1 x8264 +1 x8265 +1 x8266 +1 x8267 +1 x8268 +1 x8269 +1 x8270 +1 x8271 +1 x8272 +1 x8273 +1 x8274 +1 x8275 +1 x8276 +1 x8277 +1 x8278 +1 x8279 +1 x8280 +1 x8281 +1 x8282 +1 x8283 +1 x8284 +1 x8285 +1 x8286 +1 x8287 +1 x8288 +1 x8289 +1 x8290 +1 x8291 +1 x8292 +1 x8293 +1 x8294 +1 x8295 +1 x8296 +1 x8297 +1 x8298 +1 x8299 +1 x8300 +1 x8301 +1 x8302 +1 x8303 +1 x8304 +1 x8305 +1 x8306 +1 x8307 +1 x8308 +1 x8309 +1 x8310 +1 x8311 +1 x8312 +1 x8313 +1 x8314 +1 x8315 +1 x8316 +1 x8317 +1 x8318 +1 x8319 +1 x8320 +1 x8321 +1 x8322 +1 x8323 +1 x8324 +1 x8325 +1 x8326 +1 x8327 +1 x8328 +1 x8329 +1 x8330 +1 x8331 +1 x8332 +1 x8333 +1 x8334 +1 x8335 +1 x8336 +1 x8337 +1 x8338 +1 x8339 +1 x8340 +1 x8341 +1 x8342 +1 x8343 +1 x8344 +1 x8345 +1 x8346 +1 x8347 +1 x8348 +1 x8349 +1 x8350 +1 x8351 +1 x8352 +1 x8353 +1 x8354 +1 x8355 +1 x8356 +1 x8357 +1 x8358 +1 x8359 +1 x8360 +1 x8361 +1 x8362 +1 x8363 +1 x8364 +1 x8365 +1 x8366 +1 x8367 +1 x8368 +1 x8369 +1 x8370 +1 x8371 +1 x8372 +1 x8373 +1 x8374 +1 x8375 +1 x8376 +1 x8377 +1 x8378 +1 x8379 +1 x8380 +1 x8381 +1 x8382 +1 x8383 +1 x8384 +1 x8385 +1 x8386 +1 x8387 +1 x8388 +1 x8389 +1 x8390 +1 x8391 +1 x8392 +1 x8393 +1 x8394 +1 x8395 +1 x8396 +1 x8397 +1 x8398 +1 x8399 +1 x8400 +1 x8401 +1 x8402 +1 x8403 +1 x8404 +1 x8405 +1 x8406 +1 x8407 +1 x8408 +1 x8409 +1 x8410 +1 x8411 +1 x8412 +1 x8413 +1 x8414 +1 x8415 +1 x8416 +1 x8417 +1 x8418 +1 x8419 +1 x8420 +1 x8421 +1 x8422 +1 x8423 +1 x8424 +1 x8425 +1 x8426 +1 x8427 +1 x8428 +1 x8429 +1 x8430 +1 x8431 +1 x8432 +1 x8433 +1 x8434 +1 x8435 +1 x8436 +1 x8437 +1 x8438 +1 x8439 +1 x8440 +1 x8441 +1 x8442 +1 x8443 +1 x8444 +1 x8445 +1 x8446 +1 x8447 +1 x8448 +1 x9089 +1 x9090 +1 x9091 +1 x9092 +1 x9093 +1 x9094 +1 x9095 +1 x9096 +1 x9097 +1 x9098 +1 x9099 +1 x9100 +1 x9101 +1 x9102 +1 x9103 +1 x9104 +1 x9105 +1 x9106 +1 x9107 +1 x9108 +1 x9109 +1 x9110 +1 x9111 +1 x9112 +1 x9113 +1 x9114 +1 x9115 +1 x9116 +1 x9117 +1 x9118 +1 x9119 +1 x9120 +1 x9121 +1 x9122 +1 x9123 +1 x9124 +1 x9125 +1 x9126 +1 x9127 +1 x9128 +1 x9129 +1 x9130 +1 x9131 +1 x9132 +1 x9133 +1 x9134 +1 x9135 +1 x9136 +1 x9137 +1 x9138 +1 x9139 +1 x9140 +1 x9141 +1 x9142 +1 x9143 +1 x9144 +1 x9145 +1 x9146 +1 x9147 +1 x9148 +1 x9149 +1 x9150 +1 x9151 +1 x9152 +1 x9153 +1 x9154 +1 x9155 +1 x9156 +1 x9157 +1 x9158 +1 x9159 +1 x9160 +1 x9161 +1 x9162 +1 x9163 +1 x9164 +1 x9165 +1 x9166 +1 x9167 +1 x9168 +1 x9169 +1 x9170 +1 x9171 +1 x9172 +1 x9173 +1 x9174 +1 x9175 +1 x9176 +1 x9177 +1 x9178 +1 x9179 +1 x9180 +1 x9181 +1 x9182 +1 x9183 +1 x9184 +1 x9185 +1 x9186 +1 x9187 +1 x9188 +1 x9189 +1 x9190 +1 x9191 +1 x9192 +1 x9193 +1 x9194 +1 x9195 +1 x9196 +1 x9197 +1 x9198 +1 x9199 +1 x9200 +1 x9201 +1 x9202 +1 x9203 +1 x9204 +1 x9205 +1 x9206 +1 x9207 +1 x9208 +1 x9209 +1 x9210 +1 x9211 +1 x9212 +1 x9213 +1 x9214 +1 x9215 +1 x9216 +1 x9729 +1 x9730 +1 x9731 +1 x9732 +1 x9733 +1 x9734 +1 x9735 +1 x9736 +1 x9737 +1 x9738 +1 x9739 +1 x9740 +1 x9741 +1 x9742 +1 x9743 +1 x9744 +1 x9745 +1 x9746 +1 x9747 +1 x9748 +1 x9749 +1 x9750 +1 x9751 +1 x9752 +1 x9753 +1 x9754 +1 x9755 +1 x9756 +1 x9757 +1 x9758 +1 x9759 +1 x9760 +1 x9761 +1 x9762 +1 x9763 +1 x9764 +1 x9765 +1 x9766 +1 x9767 +1 x9768 +1 x9769 +1 x9770 +1 x9771 +1 x9772 +1 x9773 +1 x9774 +1 x9775 +1 x9776 +1 x9777 +1 x9778 +1 x9779 +1 x9780 +1 x9781 +1 x9782 +1 x9783 +1 x9784 +1 x9785 +1 x9786 +1 x9787 +1 x9788 +1 x9789 +1 x9790 +1 x9791 +1 x9792 +1 x9793 +1 x9794 +1 x9795 +1 x9796 +1 x9797 +1 x9798 +1 x9799 +1 x9800 +1 x9801 +1 x9802 +1 x9803 +1 x9804 +1 x9805 +1 x9806 +1 x9807 +1 x9808 +1 x9809 +1 x9810 +1 x9811 +1 x9812 +1 x9813 +1 x9814 +1 x9815 +1 x9816 +1 x9817 +1 x9818 +1 x9819 +1 x9820 +1 x9821 +1 x9822 +1 x9823 +1 x9824 +1 x9825 +1 x9826 +1 x9827 +1 x9828 +1 x9829 +1 x9830 +1 x9831 +1 x9832 +1 x9833 +1 x9834 +1 x9835 +1 x9836 +1 x9837 +1 x9838 +1 x9839 +1 x9840 +1 x9841 +1 x9842 +1 x9843 +1 x9844 +1 x9845 +1 x9846 +1 x9847 +1 x9848 +1 x9849 +1 x9850 +1 x9851 +1 x9852 +1 x9853 +1 x9854 +1 x9855 +1 x9856 = 0 ;+-2 x12835 +1 x8449 +1 x8450 +1 x8451 +1 x8452 +1 x8453 +1 x8454 +1 x8455 +1 x8456 +1 x8457 +1 x8458 +1 x8459 +1 x8460 +1 x8461 +1 x8462 +1 x8463 +1 x8464 +1 x8465 +1 x8466 +1 x8467 +1 x8468 +1 x8469 +1 x8470 +1 x8471 +1 x8472 +1 x8473 +1 x8474 +1 x8475 +1 x8476 +1 x8477 +1 x8478 +1 x8479 +1 x8480 +1 x8481 +1 x8482 +1 x8483 +1 x8484 +1 x8485 +1 x8486 +1 x8487 +1 x8488 +1 x8489 +1 x8490 +1 x8491 +1 x8492 +1 x8493 +1 x8494 +1 x8495 +1 x8496 +1 x8497 +1 x8498 +1 x8499 +1 x8500 +1 x8501 +1 x8502 +1 x8503 +1 x8504 +1 x8505 +1 x8506 +1 x8507 +1 x8508 +1 x8509 +1 x8510 +1 x8511 +1 x8512 +1 x8513 +1 x8514 +1 x8515 +1 x8516 +1 x8517 +1 x8518 +1 x8519 +1 x8520 +1 x8521 +1 x8522 +1 x8523 +1 x8524 +1 x8525 +1 x8526 +1 x8527 +1 x8528 +1 x8529 +1 x8530 +1 x8531 +1 x8532 +1 x8533 +1 x8534 +1 x8535 +1 x8536 +1 x8537 +1 x8538 +1 x8539 +1 x8540 +1 x8541 +1 x8542 +1 x8543 +1 x8544 +1 x8545 +1 x8546 +1 x8547 +1 x8548 +1 x8549 +1 x8550 +1 x8551 +1 x8552 +1 x8553 +1 x8554 +1 x8555 +1 x8556 +1 x8557 +1 x8558 +1 x8559 +1 x8560 +1 x8561 +1 x8562 +1 x8563 +1 x8564 +1 x8565 +1 x8566 +1 x8567 +1 x8568 +1 x8569 +1 x8570 +1 x8571 +1 x8572 +1 x8573 +1 x8574 +1 x8575 +1 x8576 +1 x8577 +1 x8578 +1 x8579 +1 x8580 +1 x8581 +1 x8582 +1 x8583 +1 x8584 +1 x8585 +1 x8586 +1 x8587 +1 x8588 +1 x8589 +1 x8590 +1 x8591 +1 x8592 +1 x8593 +1 x8594 +1 x8595 +1 x8596 +1 x8597 +1 x8598 +1 x8599 +1 x8600 +1 x8601 +1 x8602 +1 x8603 +1 x8604 +1 x8605 +1 x8606 +1 x8607 +1 x8608 +1 x8609 +1 x8610 +1 x8611 +1 x8612 +1 x8613 +1 x8614 +1 x8615 +1 x8616 +1 x8617 +1 x8618 +1 x8619 +1 x8620 +1 x8621 +1 x8622 +1 x8623 +1 x8624 +1 x8625 +1 x8626 +1 x8627 +1 x8628 +1 x8629 +1 x8630 +1 x8631 +1 x8632 +1 x8633 +1 x8634 +1 x8635 +1 x8636 +1 x8637 +1 x8638 +1 x8639 +1 x8640 +1 x8641 +1 x8642 +1 x8643 +1 x8644 +1 x8645 +1 x8646 +1 x8647 +1 x8648 +1 x8649 +1 x8650 +1 x8651 +1 x8652 +1 x8653 +1 x8654 +1 x8655 +1 x8656 +1 x8657 +1 x8658 +1 x8659 +1 x8660 +1 x8661 +1 x8662 +1 x8663 +1 x8664 +1 x8665 +1 x8666 +1 x8667 +1 x8668 +1 x8669 +1 x8670 +1 x8671 +1 x8672 +1 x8673 +1 x8674 +1 x8675 +1 x8676 +1 x8677 +1 x8678 +1 x8679 +1 x8680 +1 x8681 +1 x8682 +1 x8683 +1 x8684 +1 x8685 +1 x8686 +1 x8687 +1 x8688 +1 x8689 +1 x8690 +1 x8691 +1 x8692 +1 x8693 +1 x8694 +1 x8695 +1 x8696 +1 x8697 +1 x8698 +1 x8699 +1 x8700 +1 x8701 +1 x8702 +1 x8703 +1 x8704 = 0 ;+-2 x12836 +1 x8705 +1 x8706 +1 x8707 +1 x8708 +1 x8709 +1 x8710 +1 x8711 +1 x8712 +1 x8713 +1 x8714 +1 x8715 +1 x8716 +1 x8717 +1 x8718 +1 x8719 +1 x8720 +1 x8721 +1 x8722 +1 x8723 +1 x8724 +1 x8725 +1 x8726 +1 x8727 +1 x8728 +1 x8729 +1 x8730 +1 x8731 +1 x8732 +1 x8733 +1 x8734 +1 x8735 +1 x8736 +1 x8737 +1 x8738 +1 x8739 +1 x8740 +1 x8741 +1 x8742 +1 x8743 +1 x8744 +1 x8745 +1 x8746 +1 x8747 +1 x8748 +1 x8749 +1 x8750 +1 x8751 +1 x8752 +1 x8753 +1 x8754 +1 x8755 +1 x8756 +1 x8757 +1 x8758 +1 x8759 +1 x8760 +1 x8761 +1 x8762 +1 x8763 +1 x8764 +1 x8765 +1 x8766 +1 x8767 +1 x8768 +1 x8769 +1 x8770 +1 x8771 +1 x8772 +1 x8773 +1 x8774 +1 x8775 +1 x8776 +1 x8777 +1 x8778 +1 x8779 +1 x8780 +1 x8781 +1 x8782 +1 x8783 +1 x8784 +1 x8785 +1 x8786 +1 x8787 +1 x8788 +1 x8789 +1 x8790 +1 x8791 +1 x8792 +1 x8793 +1 x8794 +1 x8795 +1 x8796 +1 x8797 +1 x8798 +1 x8799 +1 x8800 +1 x8801 +1 x8802 +1 x8803 +1 x8804 +1 x8805 +1 x8806 +1 x8807 +1 x8808 +1 x8809 +1 x8810 +1 x8811 +1 x8812 +1 x8813 +1 x8814 +1 x8815 +1 x8816 +1 x8817 +1 x8818 +1 x8819 +1 x8820 +1 x8821 +1 x8822 +1 x8823 +1 x8824 +1 x8825 +1 x8826 +1 x8827 +1 x8828 +1 x8829 +1 x8830 +1 x8831 +1 x8832 +1 x8833 +1 x8834 +1 x8835 +1 x8836 +1 x8837 +1 x8838 +1 x8839 +1 x8840 +1 x8841 +1 x8842 +1 x8843 +1 x8844 +1 x8845 +1 x8846 +1 x8847 +1 x8848 +1 x8849 +1 x8850 +1 x8851 +1 x8852 +1 x8853 +1 x8854 +1 x8855 +1 x8856 +1 x8857 +1 x8858 +1 x8859 +1 x8860 +1 x8861 +1 x8862 +1 x8863 +1 x8864 +1 x8865 +1 x8866 +1 x8867 +1 x8868 +1 x8869 +1 x8870 +1 x8871 +1 x8872 +1 x8873 +1 x8874 +1 x8875 +1 x8876 +1 x8877 +1 x8878 +1 x8879 +1 x8880 +1 x8881 +1 x8882 +1 x8883 +1 x8884 +1 x8885 +1 x8886 +1 x8887 +1 x8888 +1 x8889 +1 x8890 +1 x8891 +1 x8892 +1 x8893 +1 x8894 +1 x8895 +1 x8896 +1 x8897 +1 x8898 +1 x8899 +1 x8900 +1 x8901 +1 x8902 +1 x8903 +1 x8904 +1 x8905 +1 x8906 +1 x8907 +1 x8908 +1 x8909 +1 x8910 +1 x8911 +1 x8912 +1 x8913 +1 x8914 +1 x8915 +1 x8916 +1 x8917 +1 x8918 +1 x8919 +1 x8920 +1 x8921 +1 x8922 +1 x8923 +1 x8924 +1 x8925 +1 x8926 +1 x8927 +1 x8928 +1 x8929 +1 x8930 +1 x8931 +1 x8932 +1 x8933 +1 x8934 +1 x8935 +1 x8936 +1 x8937 +1 x8938 +1 x8939 +1 x8940 +1 x8941 +1 x8942 +1 x8943 +1 x8944 +1 x8945 +1 x8946 +1 x8947 +1 x8948 +1 x8949 +1 x8950 +1 x8951 +1 x8952 +1 x8953 +1 x8954 +1 x8955 +1 x8956 +1 x8957 +1 x8958 +1 x8959 +1 x8960 = 0 ;+-2 x12837 +1 x8961 +1 x8962 +1 x8963 +1 x8964 +1 x8965 +1 x8966 +1 x8967 +1 x8968 +1 x8969 +1 x8970 +1 x8971 +1 x8972 +1 x8973 +1 x8974 +1 x8975 +1 x8976 +1 x8977 +1 x8978 +1 x8979 +1 x8980 +1 x8981 +1 x8982 +1 x8983 +1 x8984 +1 x8985 +1 x8986 +1 x8987 +1 x8988 +1 x8989 +1 x8990 +1 x8991 +1 x8992 +1 x8993 +1 x8994 +1 x8995 +1 x8996 +1 x8997 +1 x8998 +1 x8999 +1 x9000 +1 x9001 +1 x9002 +1 x9003 +1 x9004 +1 x9005 +1 x9006 +1 x9007 +1 x9008 +1 x9009 +1 x9010 +1 x9011 +1 x9012 +1 x9013 +1 x9014 +1 x9015 +1 x9016 +1 x9017 +1 x9018 +1 x9019 +1 x9020 +1 x9021 +1 x9022 +1 x9023 +1 x9024 +1 x9025 +1 x9026 +1 x9027 +1 x9028 +1 x9029 +1 x9030 +1 x9031 +1 x9032 +1 x9033 +1 x9034 +1 x9035 +1 x9036 +1 x9037 +1 x9038 +1 x9039 +1 x9040 +1 x9041 +1 x9042 +1 x9043 +1 x9044 +1 x9045 +1 x9046 +1 x9047 +1 x9048 +1 x9049 +1 x9050 +1 x9051 +1 x9052 +1 x9053 +1 x9054 +1 x9055 +1 x9056 +1 x9057 +1 x9058 +1 x9059 +1 x9060 +1 x9061 +1 x9062 +1 x9063 +1 x9064 +1 x9065 +1 x9066 +1 x9067 +1 x9068 +1 x9069 +1 x9070 +1 x9071 +1 x9072 +1 x9073 +1 x9074 +1 x9075 +1 x9076 +1 x9077 +1 x9078 +1 x9079 +1 x9080 +1 x9081 +1 x9082 +1 x9083 +1 x9084 +1 x9085 +1 x9086 +1 x9087 +1 x9088 +1 x9089 +1 x9090 +1 x9091 +1 x9092 +1 x9093 +1 x9094 +1 x9095 +1 x9096 +1 x9097 +1 x9098 +1 x9099 +1 x9100 +1 x9101 +1 x9102 +1 x9103 +1 x9104 +1 x9105 +1 x9106 +1 x9107 +1 x9108 +1 x9109 +1 x9110 +1 x9111 +1 x9112 +1 x9113 +1 x9114 +1 x9115 +1 x9116 +1 x9117 +1 x9118 +1 x9119 +1 x9120 +1 x9121 +1 x9122 +1 x9123 +1 x9124 +1 x9125 +1 x9126 +1 x9127 +1 x9128 +1 x9129 +1 x9130 +1 x9131 +1 x9132 +1 x9133 +1 x9134 +1 x9135 +1 x9136 +1 x9137 +1 x9138 +1 x9139 +1 x9140 +1 x9141 +1 x9142 +1 x9143 +1 x9144 +1 x9145 +1 x9146 +1 x9147 +1 x9148 +1 x9149 +1 x9150 +1 x9151 +1 x9152 +1 x9153 +1 x9154 +1 x9155 +1 x9156 +1 x9157 +1 x9158 +1 x9159 +1 x9160 +1 x9161 +1 x9162 +1 x9163 +1 x9164 +1 x9165 +1 x9166 +1 x9167 +1 x9168 +1 x9169 +1 x9170 +1 x9171 +1 x9172 +1 x9173 +1 x9174 +1 x9175 +1 x9176 +1 x9177 +1 x9178 +1 x9179 +1 x9180 +1 x9181 +1 x9182 +1 x9183 +1 x9184 +1 x9185 +1 x9186 +1 x9187 +1 x9188 +1 x9189 +1 x9190 +1 x9191 +1 x9192 +1 x9193 +1 x9194 +1 x9195 +1 x9196 +1 x9197 +1 x9198 +1 x9199 +1 x9200 +1 x9201 +1 x9202 +1 x9203 +1 x9204 +1 x9205 +1 x9206 +1 x9207 +1 x9208 +1 x9209 +1 x9210 +1 x9211 +1 x9212 +1 x9213 +1 x9214 +1 x9215 +1 x9216 = 0 ;+-2 x12838 +1 x9217 +1 x9218 +1 x9219 +1 x9220 +1 x9221 +1 x9222 +1 x9223 +1 x9224 +1 x9225 +1 x9226 +1 x9227 +1 x9228 +1 x9229 +1 x9230 +1 x9231 +1 x9232 +1 x9233 +1 x9234 +1 x9235 +1 x9236 +1 x9237 +1 x9238 +1 x9239 +1 x9240 +1 x9241 +1 x9242 +1 x9243 +1 x9244 +1 x9245 +1 x9246 +1 x9247 +1 x9248 +1 x9249 +1 x9250 +1 x9251 +1 x9252 +1 x9253 +1 x9254 +1 x9255 +1 x9256 +1 x9257 +1 x9258 +1 x9259 +1 x9260 +1 x9261 +1 x9262 +1 x9263 +1 x9264 +1 x9265 +1 x9266 +1 x9267 +1 x9268 +1 x9269 +1 x9270 +1 x9271 +1 x9272 +1 x9273 +1 x9274 +1 x9275 +1 x9276 +1 x9277 +1 x9278 +1 x9279 +1 x9280 +1 x9281 +1 x9282 +1 x9283 +1 x9284 +1 x9285 +1 x9286 +1 x9287 +1 x9288 +1 x9289 +1 x9290 +1 x9291 +1 x9292 +1 x9293 +1 x9294 +1 x9295 +1 x9296 +1 x9297 +1 x9298 +1 x9299 +1 x9300 +1 x9301 +1 x9302 +1 x9303 +1 x9304 +1 x9305 +1 x9306 +1 x9307 +1 x9308 +1 x9309 +1 x9310 +1 x9311 +1 x9312 +1 x9313 +1 x9314 +1 x9315 +1 x9316 +1 x9317 +1 x9318 +1 x9319 +1 x9320 +1 x9321 +1 x9322 +1 x9323 +1 x9324 +1 x9325 +1 x9326 +1 x9327 +1 x9328 +1 x9329 +1 x9330 +1 x9331 +1 x9332 +1 x9333 +1 x9334 +1 x9335 +1 x9336 +1 x9337 +1 x9338 +1 x9339 +1 x9340 +1 x9341 +1 x9342 +1 x9343 +1 x9344 +1 x9345 +1 x9346 +1 x9347 +1 x9348 +1 x9349 +1 x9350 +1 x9351 +1 x9352 +1 x9353 +1 x9354 +1 x9355 +1 x9356 +1 x9357 +1 x9358 +1 x9359 +1 x9360 +1 x9361 +1 x9362 +1 x9363 +1 x9364 +1 x9365 +1 x9366 +1 x9367 +1 x9368 +1 x9369 +1 x9370 +1 x9371 +1 x9372 +1 x9373 +1 x9374 +1 x9375 +1 x9376 +1 x9377 +1 x9378 +1 x9379 +1 x9380 +1 x9381 +1 x9382 +1 x9383 +1 x9384 +1 x9385 +1 x9386 +1 x9387 +1 x9388 +1 x9389 +1 x9390 +1 x9391 +1 x9392 +1 x9393 +1 x9394 +1 x9395 +1 x9396 +1 x9397 +1 x9398 +1 x9399 +1 x9400 +1 x9401 +1 x9402 +1 x9403 +1 x9404 +1 x9405 +1 x9406 +1 x9407 +1 x9408 +1 x9409 +1 x9410 +1 x9411 +1 x9412 +1 x9413 +1 x9414 +1 x9415 +1 x9416 +1 x9417 +1 x9418 +1 x9419 +1 x9420 +1 x9421 +1 x9422 +1 x9423 +1 x9424 +1 x9425 +1 x9426 +1 x9427 +1 x9428 +1 x9429 +1 x9430 +1 x9431 +1 x9432 +1 x9433 +1 x9434 +1 x9435 +1 x9436 +1 x9437 +1 x9438 +1 x9439 +1 x9440 +1 x9441 +1 x9442 +1 x9443 +1 x9444 +1 x9445 +1 x9446 +1 x9447 +1 x9448 +1 x9449 +1 x9450 +1 x9451 +1 x9452 +1 x9453 +1 x9454 +1 x9455 +1 x9456 +1 x9457 +1 x9458 +1 x9459 +1 x9460 +1 x9461 +1 x9462 +1 x9463 +1 x9464 +1 x9465 +1 x9466 +1 x9467 +1 x9468 +1 x9469 +1 x9470 +1 x9471 +1 x9472 = 0 ;+-2 x12839 +1 x9473 +1 x9474 +1 x9475 +1 x9476 +1 x9477 +1 x9478 +1 x9479 +1 x9480 +1 x9481 +1 x9482 +1 x9483 +1 x9484 +1 x9485 +1 x9486 +1 x9487 +1 x9488 +1 x9489 +1 x9490 +1 x9491 +1 x9492 +1 x9493 +1 x9494 +1 x9495 +1 x9496 +1 x9497 +1 x9498 +1 x9499 +1 x9500 +1 x9501 +1 x9502 +1 x9503 +1 x9504 +1 x9505 +1 x9506 +1 x9507 +1 x9508 +1 x9509 +1 x9510 +1 x9511 +1 x9512 +1 x9513 +1 x9514 +1 x9515 +1 x9516 +1 x9517 +1 x9518 +1 x9519 +1 x9520 +1 x9521 +1 x9522 +1 x9523 +1 x9524 +1 x9525 +1 x9526 +1 x9527 +1 x9528 +1 x9529 +1 x9530 +1 x9531 +1 x9532 +1 x9533 +1 x9534 +1 x9535 +1 x9536 +1 x9537 +1 x9538 +1 x9539 +1 x9540 +1 x9541 +1 x9542 +1 x9543 +1 x9544 +1 x9545 +1 x9546 +1 x9547 +1 x9548 +1 x9549 +1 x9550 +1 x9551 +1 x9552 +1 x9553 +1 x9554 +1 x9555 +1 x9556 +1 x9557 +1 x9558 +1 x9559 +1 x9560 +1 x9561 +1 x9562 +1 x9563 +1 x9564 +1 x9565 +1 x9566 +1 x9567 +1 x9568 +1 x9569 +1 x9570 +1 x9571 +1 x9572 +1 x9573 +1 x9574 +1 x9575 +1 x9576 +1 x9577 +1 x9578 +1 x9579 +1 x9580 +1 x9581 +1 x9582 +1 x9583 +1 x9584 +1 x9585 +1 x9586 +1 x9587 +1 x9588 +1 x9589 +1 x9590 +1 x9591 +1 x9592 +1 x9593 +1 x9594 +1 x9595 +1 x9596 +1 x9597 +1 x9598 +1 x9599 +1 x9600 +1 x9601 +1 x9602 +1 x9603 +1 x9604 +1 x9605 +1 x9606 +1 x9607 +1 x9608 +1 x9609 +1 x9610 +1 x9611 +1 x9612 +1 x9613 +1 x9614 +1 x9615 +1 x9616 +1 x9617 +1 x9618 +1 x9619 +1 x9620 +1 x9621 +1 x9622 +1 x9623 +1 x9624 +1 x9625 +1 x9626 +1 x9627 +1 x9628 +1 x9629 +1 x9630 +1 x9631 +1 x9632 +1 x9633 +1 x9634 +1 x9635 +1 x9636 +1 x9637 +1 x9638 +1 x9639 +1 x9640 +1 x9641 +1 x9642 +1 x9643 +1 x9644 +1 x9645 +1 x9646 +1 x9647 +1 x9648 +1 x9649 +1 x9650 +1 x9651 +1 x9652 +1 x9653 +1 x9654 +1 x9655 +1 x9656 +1 x9657 +1 x9658 +1 x9659 +1 x9660 +1 x9661 +1 x9662 +1 x9663 +1 x9664 +1 x9665 +1 x9666 +1 x9667 +1 x9668 +1 x9669 +1 x9670 +1 x9671 +1 x9672 +1 x9673 +1 x9674 +1 x9675 +1 x9676 +1 x9677 +1 x9678 +1 x9679 +1 x9680 +1 x9681 +1 x9682 +1 x9683 +1 x9684 +1 x9685 +1 x9686 +1 x9687 +1 x9688 +1 x9689 +1 x9690 +1 x9691 +1 x9692 +1 x9693 +1 x9694 +1 x9695 +1 x9696 +1 x9697 +1 x9698 +1 x9699 +1 x9700 +1 x9701 +1 x9702 +1 x9703 +1 x9704 +1 x9705 +1 x9706 +1 x9707 +1 x9708 +1 x9709 +1 x9710 +1 x9711 +1 x9712 +1 x9713 +1 x9714 +1 x9715 +1 x9716 +1 x9717 +1 x9718 +1 x9719 +1 x9720 +1 x9721 +1 x9722 +1 x9723 +1 x9724 +1 x9725 +1 x9726 +1 x9727 +1 x9728 = 0 ;+-2 x12840 +1 x9729 +1 x9730 +1 x9731 +1 x9732 +1 x9733 +1 x9734 +1 x9735 +1 x9736 +1 x9737 +1 x9738 +1 x9739 +1 x9740 +1 x9741 +1 x9742 +1 x9743 +1 x9744 +1 x9745 +1 x9746 +1 x9747 +1 x9748 +1 x9749 +1 x9750 +1 x9751 +1 x9752 +1 x9753 +1 x9754 +1 x9755 +1 x9756 +1 x9757 +1 x9758 +1 x9759 +1 x9760 +1 x9761 +1 x9762 +1 x9763 +1 x9764 +1 x9765 +1 x9766 +1 x9767 +1 x9768 +1 x9769 +1 x9770 +1 x9771 +1 x9772 +1 x9773 +1 x9774 +1 x9775 +1 x9776 +1 x9777 +1 x9778 +1 x9779 +1 x9780 +1 x9781 +1 x9782 +1 x9783 +1 x9784 +1 x9785 +1 x9786 +1 x9787 +1 x9788 +1 x9789 +1 x9790 +1 x9791 +1 x9792 +1 x9793 +1 x9794 +1 x9795 +1 x9796 +1 x9797 +1 x9798 +1 x9799 +1 x9800 +1 x9801 +1 x9802 +1 x9803 +1 x9804 +1 x9805 +1 x9806 +1 x9807 +1 x9808 +1 x9809 +1 x9810 +1 x9811 +1 x9812 +1 x9813 +1 x9814 +1 x9815 +1 x9816 +1 x9817 +1 x9818 +1 x9819 +1 x9820 +1 x9821 +1 x9822 +1 x9823 +1 x9824 +1 x9825 +1 x9826 +1 x9827 +1 x9828 +1 x9829 +1 x9830 +1 x9831 +1 x9832 +1 x9833 +1 x9834 +1 x9835 +1 x9836 +1 x9837 +1 x9838 +1 x9839 +1 x9840 +1 x9841 +1 x9842 +1 x9843 +1 x9844 +1 x9845 +1 x9846 +1 x9847 +1 x9848 +1 x9849 +1 x9850 +1 x9851 +1 x9852 +1 x9853 +1 x9854 +1 x9855 +1 x9856 +1 x9857 +1 x9858 +1 x9859 +1 x9860 +1 x9861 +1 x9862 +1 x9863 +1 x9864 +1 x9865 +1 x9866 +1 x9867 +1 x9868 +1 x9869 +1 x9870 +1 x9871 +1 x9872 +1 x9873 +1 x9874 +1 x9875 +1 x9876 +1 x9877 +1 x9878 +1 x9879 +1 x9880 +1 x9881 +1 x9882 +1 x9883 +1 x9884 +1 x9885 +1 x9886 +1 x9887 +1 x9888 +1 x9889 +1 x9890 +1 x9891 +1 x9892 +1 x9893 +1 x9894 +1 x9895 +1 x9896 +1 x9897 +1 x9898 +1 x9899 +1 x9900 +1 x9901 +1 x9902 +1 x9903 +1 x9904 +1 x9905 +1 x9906 +1 x9907 +1 x9908 +1 x9909 +1 x9910 +1 x9911 +1 x9912 +1 x9913 +1 x9914 +1 x9915 +1 x9916 +1 x9917 +1 x9918 +1 x9919 +1 x9920 +1 x9921 +1 x9922 +1 x9923 +1 x9924 +1 x9925 +1 x9926 +1 x9927 +1 x9928 +1 x9929 +1 x9930 +1 x9931 +1 x9932 +1 x9933 +1 x9934 +1 x9935 +1 x9936 +1 x9937 +1 x9938 +1 x9939 +1 x9940 +1 x9941 +1 x9942 +1 x9943 +1 x9944 +1 x9945 +1 x9946 +1 x9947 +1 x9948 +1 x9949 +1 x9950 +1 x9951 +1 x9952 +1 x9953 +1 x9954 +1 x9955 +1 x9956 +1 x9957 +1 x9958 +1 x9959 +1 x9960 +1 x9961 +1 x9962 +1 x9963 +1 x9964 +1 x9965 +1 x9966 +1 x9967 +1 x9968 +1 x9969 +1 x9970 +1 x9971 +1 x9972 +1 x9973 +1 x9974 +1 x9975 +1 x9976 +1 x9977 +1 x9978 +1 x9979 +1 x9980 +1 x9981 +1 x9982 +1 x9983 +1 x9984 = 0 ;+-2 x12841 +1 x9985 +1 x9986 +1 x9987 +1 x9988 +1 x9989 +1 x9990 +1 x9991 +1 x9992 +1 x9993 +1 x9994 +1 x9995 +1 x9996 +1 x9997 +1 x9998 +1 x9999 +1 x10000 +1 x10001 +1 x10002 +1 x10003 +1 x10004 +1 x10005 +1 x10006 +1 x10007 +1 x10008 +1 x10009 +1 x10010 +1 x10011 +1 x10012 +1 x10013 +1 x10014 +1 x10015 +1 x10016 +1 x10017 +1 x10018 +1 x10019 +1 x10020 +1 x10021 +1 x10022 +1 x10023 +1 x10024 +1 x10025 +1 x10026 +1 x10027 +1 x10028 +1 x10029 +1 x10030 +1 x10031 +1 x10032 +1 x10033 +1 x10034 +1 x10035 +1 x10036 +1 x10037 +1 x10038 +1 x10039 +1 x10040 +1 x10041 +1 x10042 +1 x10043 +1 x10044 +1 x10045 +1 x10046 +1 x10047 +1 x10048 +1 x10049 +1 x10050 +1 x10051 +1 x10052 +1 x10053 +1 x10054 +1 x10055 +1 x10056 +1 x10057 +1 x10058 +1 x10059 +1 x10060 +1 x10061 +1 x10062 +1 x10063 +1 x10064 +1 x10065 +1 x10066 +1 x10067 +1 x10068 +1 x10069 +1 x10070 +1 x10071 +1 x10072 +1 x10073 +1 x10074 +1 x10075 +1 x10076 +1 x10077 +1 x10078 +1 x10079 +1 x10080 +1 x10081 +1 x10082 +1 x10083 +1 x10084 +1 x10085 +1 x10086 +1 x10087 +1 x10088 +1 x10089 +1 x10090 +1 x10091 +1 x10092 +1 x10093 +1 x10094 +1 x10095 +1 x10096 +1 x10097 +1 x10098 +1 x10099 +1 x10100 +1 x10101 +1 x10102 +1 x10103 +1 x10104 +1 x10105 +1 x10106 +1 x10107 +1 x10108 +1 x10109 +1 x10110 +1 x10111 +1 x10112 +1 x10113 +1 x10114 +1 x10115 +1 x10116 +1 x10117 +1 x10118 +1 x10119 +1 x10120 +1 x10121 +1 x10122 +1 x10123 +1 x10124 +1 x10125 +1 x10126 +1 x10127 +1 x10128 +1 x10129 +1 x10130 +1 x10131 +1 x10132 +1 x10133 +1 x10134 +1 x10135 +1 x10136 +1 x10137 +1 x10138 +1 x10139 +1 x10140 +1 x10141 +1 x10142 +1 x10143 +1 x10144 +1 x10145 +1 x10146 +1 x10147 +1 x10148 +1 x10149 +1 x10150 +1 x10151 +1 x10152 +1 x10153 +1 x10154 +1 x10155 +1 x10156 +1 x10157 +1 x10158 +1 x10159 +1 x10160 +1 x10161 +1 x10162 +1 x10163 +1 x10164 +1 x10165 +1 x10166 +1 x10167 +1 x10168 +1 x10169 +1 x10170 +1 x10171 +1 x10172 +1 x10173 +1 x10174 +1 x10175 +1 x10176 +1 x10177 +1 x10178 +1 x10179 +1 x10180 +1 x10181 +1 x10182 +1 x10183 +1 x10184 +1 x10185 +1 x10186 +1 x10187 +1 x10188 +1 x10189 +1 x10190 +1 x10191 +1 x10192 +1 x10193 +1 x10194 +1 x10195 +1 x10196 +1 x10197 +1 x10198 +1 x10199 +1 x10200 +1 x10201 +1 x10202 +1 x10203 +1 x10204 +1 x10205 +1 x10206 +1 x10207 +1 x10208 +1 x10209 +1 x10210 +1 x10211 +1 x10212 +1 x10213 +1 x10214 +1 x10215 +1 x10216 +1 x10217 +1 x10218 +1 x10219 +1 x10220 +1 x10221 +1 x10222 +1 x10223 +1 x10224 +1 x10225 +1 x10226 +1 x10227 +1 x10228 +1 x10229 +1 x10230 +1 x10231 +1 x10232 +1 x10233 +1 x10234 +1 x10235 +1 x10236 +1 x10237 +1 x10238 +1 x10239 +1 x10240 = 0 ;+-2 x12842 +1 x10241 +1 x10242 +1 x10243 +1 x10244 +1 x10245 +1 x10246 +1 x10247 +1 x10248 +1 x10249 +1 x10250 +1 x10251 +1 x10252 +1 x10253 +1 x10254 +1 x10255 +1 x10256 +1 x10257 +1 x10258 +1 x10259 +1 x10260 +1 x10261 +1 x10262 +1 x10263 +1 x10264 +1 x10265 +1 x10266 +1 x10267 +1 x10268 +1 x10269 +1 x10270 +1 x10271 +1 x10272 +1 x10273 +1 x10274 +1 x10275 +1 x10276 +1 x10277 +1 x10278 +1 x10279 +1 x10280 +1 x10281 +1 x10282 +1 x10283 +1 x10284 +1 x10285 +1 x10286 +1 x10287 +1 x10288 +1 x10289 +1 x10290 +1 x10291 +1 x10292 +1 x10293 +1 x10294 +1 x10295 +1 x10296 +1 x10297 +1 x10298 +1 x10299 +1 x10300 +1 x10301 +1 x10302 +1 x10303 +1 x10304 +1 x10305 +1 x10306 +1 x10307 +1 x10308 +1 x10309 +1 x10310 +1 x10311 +1 x10312 +1 x10313 +1 x10314 +1 x10315 +1 x10316 +1 x10317 +1 x10318 +1 x10319 +1 x10320 +1 x10321 +1 x10322 +1 x10323 +1 x10324 +1 x10325 +1 x10326 +1 x10327 +1 x10328 +1 x10329 +1 x10330 +1 x10331 +1 x10332 +1 x10333 +1 x10334 +1 x10335 +1 x10336 +1 x10337 +1 x10338 +1 x10339 +1 x10340 +1 x10341 +1 x10342 +1 x10343 +1 x10344 +1 x10345 +1 x10346 +1 x10347 +1 x10348 +1 x10349 +1 x10350 +1 x10351 +1 x10352 +1 x10353 +1 x10354 +1 x10355 +1 x10356 +1 x10357 +1 x10358 +1 x10359 +1 x10360 +1 x10361 +1 x10362 +1 x10363 +1 x10364 +1 x10365 +1 x10366 +1 x10367 +1 x10368 +1 x10369 +1 x10370 +1 x10371 +1 x10372 +1 x10373 +1 x10374 +1 x10375 +1 x10376 +1 x10377 +1 x10378 +1 x10379 +1 x10380 +1 x10381 +1 x10382 +1 x10383 +1 x10384 +1 x10385 +1 x10386 +1 x10387 +1 x10388 +1 x10389 +1 x10390 +1 x10391 +1 x10392 +1 x10393 +1 x10394 +1 x10395 +1 x10396 +1 x10397 +1 x10398 +1 x10399 +1 x10400 +1 x10401 +1 x10402 +1 x10403 +1 x10404 +1 x10405 +1 x10406 +1 x10407 +1 x10408 +1 x10409 +1 x10410 +1 x10411 +1 x10412 +1 x10413 +1 x10414 +1 x10415 +1 x10416 +1 x10417 +1 x10418 +1 x10419 +1 x10420 +1 x10421 +1 x10422 +1 x10423 +1 x10424 +1 x10425 +1 x10426 +1 x10427 +1 x10428 +1 x10429 +1 x10430 +1 x10431 +1 x10432 +1 x10433 +1 x10434 +1 x10435 +1 x10436 +1 x10437 +1 x10438 +1 x10439 +1 x10440 +1 x10441 +1 x10442 +1 x10443 +1 x10444 +1 x10445 +1 x10446 +1 x10447 +1 x10448 +1 x10449 +1 x10450 +1 x10451 +1 x10452 +1 x10453 +1 x10454 +1 x10455 +1 x10456 +1 x10457 +1 x10458 +1 x10459 +1 x10460 +1 x10461 +1 x10462 +1 x10463 +1 x10464 +1 x10465 +1 x10466 +1 x10467 +1 x10468 +1 x10469 +1 x10470 +1 x10471 +1 x10472 +1 x10473 +1 x10474 +1 x10475 +1 x10476 +1 x10477 +1 x10478 +1 x10479 +1 x10480 +1 x10481 +1 x10482 +1 x10483 +1 x10484 +1 x10485 +1 x10486 +1 x10487 +1 x10488 +1 x10489 +1 x10490 +1 x10491 +1 x10492 +1 x10493 +1 x10494 +1 x10495 +1 x10496 +1 x11393 +1 x11394 +1 x11395 +1 x11396 +1 x11397 +1 x11398 +1 x11399 +1 x11400 +1 x11401 +1 x11402 +1 x11403 +1 x11404 +1 x11405 +1 x11406 +1 x11407 +1 x11408 +1 x11409 +1 x11410 +1 x11411 +1 x11412 +1 x11413 +1 x11414 +1 x11415 +1 x11416 +1 x11417 +1 x11418 +1 x11419 +1 x11420 +1 x11421 +1 x11422 +1 x11423 +1 x11424 +1 x11425 +1 x11426 +1 x11427 +1 x11428 +1 x11429 +1 x11430 +1 x11431 +1 x11432 +1 x11433 +1 x11434 +1 x11435 +1 x11436 +1 x11437 +1 x11438 +1 x11439 +1 x11440 +1 x11441 +1 x11442 +1 x11443 +1 x11444 +1 x11445 +1 x11446 +1 x11447 +1 x11448 +1 x11449 +1 x11450 +1 x11451 +1 x11452 +1 x11453 +1 x11454 +1 x11455 +1 x11456 +1 x11457 +1 x11458 +1 x11459 +1 x11460 +1 x11461 +1 x11462 +1 x11463 +1 x11464 +1 x11465 +1 x11466 +1 x11467 +1 x11468 +1 x11469 +1 x11470 +1 x11471 +1 x11472 +1 x11473 +1 x11474 +1 x11475 +1 x11476 +1 x11477 +1 x11478 +1 x11479 +1 x11480 +1 x11481 +1 x11482 +1 x11483 +1 x11484 +1 x11485 +1 x11486 +1 x11487 +1 x11488 +1 x11489 +1 x11490 +1 x11491 +1 x11492 +1 x11493 +1 x11494 +1 x11495 +1 x11496 +1 x11497 +1 x11498 +1 x11499 +1 x11500 +1 x11501 +1 x11502 +1 x11503 +1 x11504 +1 x11505 +1 x11506 +1 x11507 +1 x11508 +1 x11509 +1 x11510 +1 x11511 +1 x11512 +1 x11513 +1 x11514 +1 x11515 +1 x11516 +1 x11517 +1 x11518 +1 x11519 +1 x11520 +1 x12673 +1 x12674 +1 x12675 +1 x12676 +1 x12677 +1 x12678 +1 x12679 +1 x12680 +1 x12681 +1 x12682 +1 x12683 +1 x12684 +1 x12685 +1 x12686 +1 x12687 +1 x12688 +1 x12689 +1 x12690 +1 x12691 +1 x12692 +1 x12693 +1 x12694 +1 x12695 +1 x12696 +1 x12697 +1 x12698 +1 x12699 +1 x12700 +1 x12701 +1 x12702 +1 x12703 +1 x12704 +1 x12705 +1 x12706 +1 x12707 +1 x12708 +1 x12709 +1 x12710 +1 x12711 +1 x12712 +1 x12713 +1 x12714 +1 x12715 +1 x12716 +1 x12717 +1 x12718 +1 x12719 +1 x12720 +1 x12721 +1 x12722 +1 x12723 +1 x12724 +1 x12725 +1 x12726 +1 x12727 +1 x12728 +1 x12729 +1 x12730 +1 x12731 +1 x12732 +1 x12733 +1 x12734 +1 x12735 +1 x12736 +1 x12737 +1 x12738 +1 x12739 +1 x12740 +1 x12741 +1 x12742 +1 x12743 +1 x12744 +1 x12745 +1 x12746 +1 x12747 +1 x12748 +1 x12749 +1 x12750 +1 x12751 +1 x12752 +1 x12753 +1 x12754 +1 x12755 +1 x12756 +1 x12757 +1 x12758 +1 x12759 +1 x12760 +1 x12761 +1 x12762 +1 x12763 +1 x12764 +1 x12765 +1 x12766 +1 x12767 +1 x12768 +1 x12769 +1 x12770 +1 x12771 +1 x12772 +1 x12773 +1 x12774 +1 x12775 +1 x12776 +1 x12777 +1 x12778 +1 x12779 +1 x12780 +1 x12781 +1 x12782 +1 x12783 +1 x12784 +1 x12785 +1 x12786 +1 x12787 +1 x12788 +1 x12789 +1 x12790 +1 x12791 +1 x12792 +1 x12793 +1 x12794 +1 x12795 +1 x12796 +1 x12797 +1 x12798 +1 x12799 +1 x12800 = 0 ;+-2 x12843 +1 x10497 +1 x10498 +1 x10499 +1 x10500 +1 x10501 +1 x10502 +1 x10503 +1 x10504 +1 x10505 +1 x10506 +1 x10507 +1 x10508 +1 x10509 +1 x10510 +1 x10511 +1 x10512 +1 x10513 +1 x10514 +1 x10515 +1 x10516 +1 x10517 +1 x10518 +1 x10519 +1 x10520 +1 x10521 +1 x10522 +1 x10523 +1 x10524 +1 x10525 +1 x10526 +1 x10527 +1 x10528 +1 x10529 +1 x10530 +1 x10531 +1 x10532 +1 x10533 +1 x10534 +1 x10535 +1 x10536 +1 x10537 +1 x10538 +1 x10539 +1 x10540 +1 x10541 +1 x10542 +1 x10543 +1 x10544 +1 x10545 +1 x10546 +1 x10547 +1 x10548 +1 x10549 +1 x10550 +1 x10551 +1 x10552 +1 x10553 +1 x10554 +1 x10555 +1 x10556 +1 x10557 +1 x10558 +1 x10559 +1 x10560 +1 x10561 +1 x10562 +1 x10563 +1 x10564 +1 x10565 +1 x10566 +1 x10567 +1 x10568 +1 x10569 +1 x10570 +1 x10571 +1 x10572 +1 x10573 +1 x10574 +1 x10575 +1 x10576 +1 x10577 +1 x10578 +1 x10579 +1 x10580 +1 x10581 +1 x10582 +1 x10583 +1 x10584 +1 x10585 +1 x10586 +1 x10587 +1 x10588 +1 x10589 +1 x10590 +1 x10591 +1 x10592 +1 x10593 +1 x10594 +1 x10595 +1 x10596 +1 x10597 +1 x10598 +1 x10599 +1 x10600 +1 x10601 +1 x10602 +1 x10603 +1 x10604 +1 x10605 +1 x10606 +1 x10607 +1 x10608 +1 x10609 +1 x10610 +1 x10611 +1 x10612 +1 x10613 +1 x10614 +1 x10615 +1 x10616 +1 x10617 +1 x10618 +1 x10619 +1 x10620 +1 x10621 +1 x10622 +1 x10623 +1 x10624 +1 x10625 +1 x10626 +1 x10627 +1 x10628 +1 x10629 +1 x10630 +1 x10631 +1 x10632 +1 x10633 +1 x10634 +1 x10635 +1 x10636 +1 x10637 +1 x10638 +1 x10639 +1 x10640 +1 x10641 +1 x10642 +1 x10643 +1 x10644 +1 x10645 +1 x10646 +1 x10647 +1 x10648 +1 x10649 +1 x10650 +1 x10651 +1 x10652 +1 x10653 +1 x10654 +1 x10655 +1 x10656 +1 x10657 +1 x10658 +1 x10659 +1 x10660 +1 x10661 +1 x10662 +1 x10663 +1 x10664 +1 x10665 +1 x10666 +1 x10667 +1 x10668 +1 x10669 +1 x10670 +1 x10671 +1 x10672 +1 x10673 +1 x10674 +1 x10675 +1 x10676 +1 x10677 +1 x10678 +1 x10679 +1 x10680 +1 x10681 +1 x10682 +1 x10683 +1 x10684 +1 x10685 +1 x10686 +1 x10687 +1 x10688 +1 x10689 +1 x10690 +1 x10691 +1 x10692 +1 x10693 +1 x10694 +1 x10695 +1 x10696 +1 x10697 +1 x10698 +1 x10699 +1 x10700 +1 x10701 +1 x10702 +1 x10703 +1 x10704 +1 x10705 +1 x10706 +1 x10707 +1 x10708 +1 x10709 +1 x10710 +1 x10711 +1 x10712 +1 x10713 +1 x10714 +1 x10715 +1 x10716 +1 x10717 +1 x10718 +1 x10719 +1 x10720 +1 x10721 +1 x10722 +1 x10723 +1 x10724 +1 x10725 +1 x10726 +1 x10727 +1 x10728 +1 x10729 +1 x10730 +1 x10731 +1 x10732 +1 x10733 +1 x10734 +1 x10735 +1 x10736 +1 x10737 +1 x10738 +1 x10739 +1 x10740 +1 x10741 +1 x10742 +1 x10743 +1 x10744 +1 x10745 +1 x10746 +1 x10747 +1 x10748 +1 x10749 +1 x10750 +1 x10751 +1 x10752 = 0 ;+-2 x12844 +1 x10753 +1 x10754 +1 x10755 +1 x10756 +1 x10757 +1 x10758 +1 x10759 +1 x10760 +1 x10761 +1 x10762 +1 x10763 +1 x10764 +1 x10765 +1 x10766 +1 x10767 +1 x10768 +1 x10769 +1 x10770 +1 x10771 +1 x10772 +1 x10773 +1 x10774 +1 x10775 +1 x10776 +1 x10777 +1 x10778 +1 x10779 +1 x10780 +1 x10781 +1 x10782 +1 x10783 +1 x10784 +1 x10785 +1 x10786 +1 x10787 +1 x10788 +1 x10789 +1 x10790 +1 x10791 +1 x10792 +1 x10793 +1 x10794 +1 x10795 +1 x10796 +1 x10797 +1 x10798 +1 x10799 +1 x10800 +1 x10801 +1 x10802 +1 x10803 +1 x10804 +1 x10805 +1 x10806 +1 x10807 +1 x10808 +1 x10809 +1 x10810 +1 x10811 +1 x10812 +1 x10813 +1 x10814 +1 x10815 +1 x10816 +1 x10817 +1 x10818 +1 x10819 +1 x10820 +1 x10821 +1 x10822 +1 x10823 +1 x10824 +1 x10825 +1 x10826 +1 x10827 +1 x10828 +1 x10829 +1 x10830 +1 x10831 +1 x10832 +1 x10833 +1 x10834 +1 x10835 +1 x10836 +1 x10837 +1 x10838 +1 x10839 +1 x10840 +1 x10841 +1 x10842 +1 x10843 +1 x10844 +1 x10845 +1 x10846 +1 x10847 +1 x10848 +1 x10849 +1 x10850 +1 x10851 +1 x10852 +1 x10853 +1 x10854 +1 x10855 +1 x10856 +1 x10857 +1 x10858 +1 x10859 +1 x10860 +1 x10861 +1 x10862 +1 x10863 +1 x10864 +1 x10865 +1 x10866 +1 x10867 +1 x10868 +1 x10869 +1 x10870 +1 x10871 +1 x10872 +1 x10873 +1 x10874 +1 x10875 +1 x10876 +1 x10877 +1 x10878 +1 x10879 +1 x10880 +1 x10881 +1 x10882 +1 x10883 +1 x10884 +1 x10885 +1 x10886 +1 x10887 +1 x10888 +1 x10889 +1 x10890 +1 x10891 +1 x10892 +1 x10893 +1 x10894 +1 x10895 +1 x10896 +1 x10897 +1 x10898 +1 x10899 +1 x10900 +1 x10901 +1 x10902 +1 x10903 +1 x10904 +1 x10905 +1 x10906 +1 x10907 +1 x10908 +1 x10909 +1 x10910 +1 x10911 +1 x10912 +1 x10913 +1 x10914 +1 x10915 +1 x10916 +1 x10917 +1 x10918 +1 x10919 +1 x10920 +1 x10921 +1 x10922 +1 x10923 +1 x10924 +1 x10925 +1 x10926 +1 x10927 +1 x10928 +1 x10929 +1 x10930 +1 x10931 +1 x10932 +1 x10933 +1 x10934 +1 x10935 +1 x10936 +1 x10937 +1 x10938 +1 x10939 +1 x10940 +1 x10941 +1 x10942 +1 x10943 +1 x10944 +1 x10945 +1 x10946 +1 x10947 +1 x10948 +1 x10949 +1 x10950 +1 x10951 +1 x10952 +1 x10953 +1 x10954 +1 x10955 +1 x10956 +1 x10957 +1 x10958 +1 x10959 +1 x10960 +1 x10961 +1 x10962 +1 x10963 +1 x10964 +1 x10965 +1 x10966 +1 x10967 +1 x10968 +1 x10969 +1 x10970 +1 x10971 +1 x10972 +1 x10973 +1 x10974 +1 x10975 +1 x10976 +1 x10977 +1 x10978 +1 x10979 +1 x10980 +1 x10981 +1 x10982 +1 x10983 +1 x10984 +1 x10985 +1 x10986 +1 x10987 +1 x10988 +1 x10989 +1 x10990 +1 x10991 +1 x10992 +1 x10993 +1 x10994 +1 x10995 +1 x10996 +1 x10997 +1 x10998 +1 x10999 +1 x11000 +1 x11001 +1 x11002 +1 x11003 +1 x11004 +1 x11005 +1 x11006 +1 x11007 +1 x11008 = 0 ;+-2 x12845 +1 x11265 +1 x11266 +1 x11267 +1 x11268 +1 x11269 +1 x11270 +1 x11271 +1 x11272 +1 x11273 +1 x11274 +1 x11275 +1 x11276 +1 x11277 +1 x11278 +1 x11279 +1 x11280 +1 x11281 +1 x11282 +1 x11283 +1 x11284 +1 x11285 +1 x11286 +1 x11287 +1 x11288 +1 x11289 +1 x11290 +1 x11291 +1 x11292 +1 x11293 +1 x11294 +1 x11295 +1 x11296 +1 x11297 +1 x11298 +1 x11299 +1 x11300 +1 x11301 +1 x11302 +1 x11303 +1 x11304 +1 x11305 +1 x11306 +1 x11307 +1 x11308 +1 x11309 +1 x11310 +1 x11311 +1 x11312 +1 x11313 +1 x11314 +1 x11315 +1 x11316 +1 x11317 +1 x11318 +1 x11319 +1 x11320 +1 x11321 +1 x11322 +1 x11323 +1 x11324 +1 x11325 +1 x11326 +1 x11327 +1 x11328 +1 x11329 +1 x11330 +1 x11331 +1 x11332 +1 x11333 +1 x11334 +1 x11335 +1 x11336 +1 x11337 +1 x11338 +1 x11339 +1 x11340 +1 x11341 +1 x11342 +1 x11343 +1 x11344 +1 x11345 +1 x11346 +1 x11347 +1 x11348 +1 x11349 +1 x11350 +1 x11351 +1 x11352 +1 x11353 +1 x11354 +1 x11355 +1 x11356 +1 x11357 +1 x11358 +1 x11359 +1 x11360 +1 x11361 +1 x11362 +1 x11363 +1 x11364 +1 x11365 +1 x11366 +1 x11367 +1 x11368 +1 x11369 +1 x11370 +1 x11371 +1 x11372 +1 x11373 +1 x11374 +1 x11375 +1 x11376 +1 x11377 +1 x11378 +1 x11379 +1 x11380 +1 x11381 +1 x11382 +1 x11383 +1 x11384 +1 x11385 +1 x11386 +1 x11387 +1 x11388 +1 x11389 +1 x11390 +1 x11391 +1 x11392 +1 x11393 +1 x11394 +1 x11395 +1 x11396 +1 x11397 +1 x11398 +1 x11399 +1 x11400 +1 x11401 +1 x11402 +1 x11403 +1 x11404 +1 x11405 +1 x11406 +1 x11407 +1 x11408 +1 x11409 +1 x11410 +1 x11411 +1 x11412 +1 x11413 +1 x11414 +1 x11415 +1 x11416 +1 x11417 +1 x11418 +1 x11419 +1 x11420 +1 x11421 +1 x11422 +1 x11423 +1 x11424 +1 x11425 +1 x11426 +1 x11427 +1 x11428 +1 x11429 +1 x11430 +1 x11431 +1 x11432 +1 x11433 +1 x11434 +1 x11435 +1 x11436 +1 x11437 +1 x11438 +1 x11439 +1 x11440 +1 x11441 +1 x11442 +1 x11443 +1 x11444 +1 x11445 +1 x11446 +1 x11447 +1 x11448 +1 x11449 +1 x11450 +1 x11451 +1 x11452 +1 x11453 +1 x11454 +1 x11455 +1 x11456 +1 x11457 +1 x11458 +1 x11459 +1 x11460 +1 x11461 +1 x11462 +1 x11463 +1 x11464 +1 x11465 +1 x11466 +1 x11467 +1 x11468 +1 x11469 +1 x11470 +1 x11471 +1 x11472 +1 x11473 +1 x11474 +1 x11475 +1 x11476 +1 x11477 +1 x11478 +1 x11479 +1 x11480 +1 x11481 +1 x11482 +1 x11483 +1 x11484 +1 x11485 +1 x11486 +1 x11487 +1 x11488 +1 x11489 +1 x11490 +1 x11491 +1 x11492 +1 x11493 +1 x11494 +1 x11495 +1 x11496 +1 x11497 +1 x11498 +1 x11499 +1 x11500 +1 x11501 +1 x11502 +1 x11503 +1 x11504 +1 x11505 +1 x11506 +1 x11507 +1 x11508 +1 x11509 +1 x11510 +1 x11511 +1 x11512 +1 x11513 +1 x11514 +1 x11515 +1 x11516 +1 x11517 +1 x11518 +1 x11519 +1 x11520 = 0 ;+-2 x12846 +1 x11521 +1 x11522 +1 x11523 +1 x11524 +1 x11525 +1 x11526 +1 x11527 +1 x11528 +1 x11529 +1 x11530 +1 x11531 +1 x11532 +1 x11533 +1 x11534 +1 x11535 +1 x11536 +1 x11537 +1 x11538 +1 x11539 +1 x11540 +1 x11541 +1 x11542 +1 x11543 +1 x11544 +1 x11545 +1 x11546 +1 x11547 +1 x11548 +1 x11549 +1 x11550 +1 x11551 +1 x11552 +1 x11553 +1 x11554 +1 x11555 +1 x11556 +1 x11557 +1 x11558 +1 x11559 +1 x11560 +1 x11561 +1 x11562 +1 x11563 +1 x11564 +1 x11565 +1 x11566 +1 x11567 +1 x11568 +1 x11569 +1 x11570 +1 x11571 +1 x11572 +1 x11573 +1 x11574 +1 x11575 +1 x11576 +1 x11577 +1 x11578 +1 x11579 +1 x11580 +1 x11581 +1 x11582 +1 x11583 +1 x11584 +1 x11585 +1 x11586 +1 x11587 +1 x11588 +1 x11589 +1 x11590 +1 x11591 +1 x11592 +1 x11593 +1 x11594 +1 x11595 +1 x11596 +1 x11597 +1 x11598 +1 x11599 +1 x11600 +1 x11601 +1 x11602 +1 x11603 +1 x11604 +1 x11605 +1 x11606 +1 x11607 +1 x11608 +1 x11609 +1 x11610 +1 x11611 +1 x11612 +1 x11613 +1 x11614 +1 x11615 +1 x11616 +1 x11617 +1 x11618 +1 x11619 +1 x11620 +1 x11621 +1 x11622 +1 x11623 +1 x11624 +1 x11625 +1 x11626 +1 x11627 +1 x11628 +1 x11629 +1 x11630 +1 x11631 +1 x11632 +1 x11633 +1 x11634 +1 x11635 +1 x11636 +1 x11637 +1 x11638 +1 x11639 +1 x11640 +1 x11641 +1 x11642 +1 x11643 +1 x11644 +1 x11645 +1 x11646 +1 x11647 +1 x11648 +1 x11649 +1 x11650 +1 x11651 +1 x11652 +1 x11653 +1 x11654 +1 x11655 +1 x11656 +1 x11657 +1 x11658 +1 x11659 +1 x11660 +1 x11661 +1 x11662 +1 x11663 +1 x11664 +1 x11665 +1 x11666 +1 x11667 +1 x11668 +1 x11669 +1 x11670 +1 x11671 +1 x11672 +1 x11673 +1 x11674 +1 x11675 +1 x11676 +1 x11677 +1 x11678 +1 x11679 +1 x11680 +1 x11681 +1 x11682 +1 x11683 +1 x11684 +1 x11685 +1 x11686 +1 x11687 +1 x11688 +1 x11689 +1 x11690 +1 x11691 +1 x11692 +1 x11693 +1 x11694 +1 x11695 +1 x11696 +1 x11697 +1 x11698 +1 x11699 +1 x11700 +1 x11701 +1 x11702 +1 x11703 +1 x11704 +1 x11705 +1 x11706 +1 x11707 +1 x11708 +1 x11709 +1 x11710 +1 x11711 +1 x11712 +1 x11713 +1 x11714 +1 x11715 +1 x11716 +1 x11717 +1 x11718 +1 x11719 +1 x11720 +1 x11721 +1 x11722 +1 x11723 +1 x11724 +1 x11725 +1 x11726 +1 x11727 +1 x11728 +1 x11729 +1 x11730 +1 x11731 +1 x11732 +1 x11733 +1 x11734 +1 x11735 +1 x11736 +1 x11737 +1 x11738 +1 x11739 +1 x11740 +1 x11741 +1 x11742 +1 x11743 +1 x11744 +1 x11745 +1 x11746 +1 x11747 +1 x11748 +1 x11749 +1 x11750 +1 x11751 +1 x11752 +1 x11753 +1 x11754 +1 x11755 +1 x11756 +1 x11757 +1 x11758 +1 x11759 +1 x11760 +1 x11761 +1 x11762 +1 x11763 +1 x11764 +1 x11765 +1 x11766 +1 x11767 +1 x11768 +1 x11769 +1 x11770 +1 x11771 +1 x11772 +1 x11773 +1 x11774 +1 x11775 +1 x11776 = 0 ;+-2 x12847 +1 x11777 +1 x11778 +1 x11779 +1 x11780 +1 x11781 +1 x11782 +1 x11783 +1 x11784 +1 x11785 +1 x11786 +1 x11787 +1 x11788 +1 x11789 +1 x11790 +1 x11791 +1 x11792 +1 x11793 +1 x11794 +1 x11795 +1 x11796 +1 x11797 +1 x11798 +1 x11799 +1 x11800 +1 x11801 +1 x11802 +1 x11803 +1 x11804 +1 x11805 +1 x11806 +1 x11807 +1 x11808 +1 x11809 +1 x11810 +1 x11811 +1 x11812 +1 x11813 +1 x11814 +1 x11815 +1 x11816 +1 x11817 +1 x11818 +1 x11819 +1 x11820 +1 x11821 +1 x11822 +1 x11823 +1 x11824 +1 x11825 +1 x11826 +1 x11827 +1 x11828 +1 x11829 +1 x11830 +1 x11831 +1 x11832 +1 x11833 +1 x11834 +1 x11835 +1 x11836 +1 x11837 +1 x11838 +1 x11839 +1 x11840 +1 x11841 +1 x11842 +1 x11843 +1 x11844 +1 x11845 +1 x11846 +1 x11847 +1 x11848 +1 x11849 +1 x11850 +1 x11851 +1 x11852 +1 x11853 +1 x11854 +1 x11855 +1 x11856 +1 x11857 +1 x11858 +1 x11859 +1 x11860 +1 x11861 +1 x11862 +1 x11863 +1 x11864 +1 x11865 +1 x11866 +1 x11867 +1 x11868 +1 x11869 +1 x11870 +1 x11871 +1 x11872 +1 x11873 +1 x11874 +1 x11875 +1 x11876 +1 x11877 +1 x11878 +1 x11879 +1 x11880 +1 x11881 +1 x11882 +1 x11883 +1 x11884 +1 x11885 +1 x11886 +1 x11887 +1 x11888 +1 x11889 +1 x11890 +1 x11891 +1 x11892 +1 x11893 +1 x11894 +1 x11895 +1 x11896 +1 x11897 +1 x11898 +1 x11899 +1 x11900 +1 x11901 +1 x11902 +1 x11903 +1 x11904 +1 x11905 +1 x11906 +1 x11907 +1 x11908 +1 x11909 +1 x11910 +1 x11911 +1 x11912 +1 x11913 +1 x11914 +1 x11915 +1 x11916 +1 x11917 +1 x11918 +1 x11919 +1 x11920 +1 x11921 +1 x11922 +1 x11923 +1 x11924 +1 x11925 +1 x11926 +1 x11927 +1 x11928 +1 x11929 +1 x11930 +1 x11931 +1 x11932 +1 x11933 +1 x11934 +1 x11935 +1 x11936 +1 x11937 +1 x11938 +1 x11939 +1 x11940 +1 x11941 +1 x11942 +1 x11943 +1 x11944 +1 x11945 +1 x11946 +1 x11947 +1 x11948 +1 x11949 +1 x11950 +1 x11951 +1 x11952 +1 x11953 +1 x11954 +1 x11955 +1 x11956 +1 x11957 +1 x11958 +1 x11959 +1 x11960 +1 x11961 +1 x11962 +1 x11963 +1 x11964 +1 x11965 +1 x11966 +1 x11967 +1 x11968 +1 x11969 +1 x11970 +1 x11971 +1 x11972 +1 x11973 +1 x11974 +1 x11975 +1 x11976 +1 x11977 +1 x11978 +1 x11979 +1 x11980 +1 x11981 +1 x11982 +1 x11983 +1 x11984 +1 x11985 +1 x11986 +1 x11987 +1 x11988 +1 x11989 +1 x11990 +1 x11991 +1 x11992 +1 x11993 +1 x11994 +1 x11995 +1 x11996 +1 x11997 +1 x11998 +1 x11999 +1 x12000 +1 x12001 +1 x12002 +1 x12003 +1 x12004 +1 x12005 +1 x12006 +1 x12007 +1 x12008 +1 x12009 +1 x12010 +1 x12011 +1 x12012 +1 x12013 +1 x12014 +1 x12015 +1 x12016 +1 x12017 +1 x12018 +1 x12019 +1 x12020 +1 x12021 +1 x12022 +1 x12023 +1 x12024 +1 x12025 +1 x12026 +1 x12027 +1 x12028 +1 x12029 +1 x12030 +1 x12031 +1 x12032 = 0 ;+-2 x12848 +1 x12033 +1 x12034 +1 x12035 +1 x12036 +1 x12037 +1 x12038 +1 x12039 +1 x12040 +1 x12041 +1 x12042 +1 x12043 +1 x12044 +1 x12045 +1 x12046 +1 x12047 +1 x12048 +1 x12049 +1 x12050 +1 x12051 +1 x12052 +1 x12053 +1 x12054 +1 x12055 +1 x12056 +1 x12057 +1 x12058 +1 x12059 +1 x12060 +1 x12061 +1 x12062 +1 x12063 +1 x12064 +1 x12065 +1 x12066 +1 x12067 +1 x12068 +1 x12069 +1 x12070 +1 x12071 +1 x12072 +1 x12073 +1 x12074 +1 x12075 +1 x12076 +1 x12077 +1 x12078 +1 x12079 +1 x12080 +1 x12081 +1 x12082 +1 x12083 +1 x12084 +1 x12085 +1 x12086 +1 x12087 +1 x12088 +1 x12089 +1 x12090 +1 x12091 +1 x12092 +1 x12093 +1 x12094 +1 x12095 +1 x12096 +1 x12097 +1 x12098 +1 x12099 +1 x12100 +1 x12101 +1 x12102 +1 x12103 +1 x12104 +1 x12105 +1 x12106 +1 x12107 +1 x12108 +1 x12109 +1 x12110 +1 x12111 +1 x12112 +1 x12113 +1 x12114 +1 x12115 +1 x12116 +1 x12117 +1 x12118 +1 x12119 +1 x12120 +1 x12121 +1 x12122 +1 x12123 +1 x12124 +1 x12125 +1 x12126 +1 x12127 +1 x12128 +1 x12129 +1 x12130 +1 x12131 +1 x12132 +1 x12133 +1 x12134 +1 x12135 +1 x12136 +1 x12137 +1 x12138 +1 x12139 +1 x12140 +1 x12141 +1 x12142 +1 x12143 +1 x12144 +1 x12145 +1 x12146 +1 x12147 +1 x12148 +1 x12149 +1 x12150 +1 x12151 +1 x12152 +1 x12153 +1 x12154 +1 x12155 +1 x12156 +1 x12157 +1 x12158 +1 x12159 +1 x12160 +1 x12161 +1 x12162 +1 x12163 +1 x12164 +1 x12165 +1 x12166 +1 x12167 +1 x12168 +1 x12169 +1 x12170 +1 x12171 +1 x12172 +1 x12173 +1 x12174 +1 x12175 +1 x12176 +1 x12177 +1 x12178 +1 x12179 +1 x12180 +1 x12181 +1 x12182 +1 x12183 +1 x12184 +1 x12185 +1 x12186 +1 x12187 +1 x12188 +1 x12189 +1 x12190 +1 x12191 +1 x12192 +1 x12193 +1 x12194 +1 x12195 +1 x12196 +1 x12197 +1 x12198 +1 x12199 +1 x12200 +1 x12201 +1 x12202 +1 x12203 +1 x12204 +1 x12205 +1 x12206 +1 x12207 +1 x12208 +1 x12209 +1 x12210 +1 x12211 +1 x12212 +1 x12213 +1 x12214 +1 x12215 +1 x12216 +1 x12217 +1 x12218 +1 x12219 +1 x12220 +1 x12221 +1 x12222 +1 x12223 +1 x12224 +1 x12225 +1 x12226 +1 x12227 +1 x12228 +1 x12229 +1 x12230 +1 x12231 +1 x12232 +1 x12233 +1 x12234 +1 x12235 +1 x12236 +1 x12237 +1 x12238 +1 x12239 +1 x12240 +1 x12241 +1 x12242 +1 x12243 +1 x12244 +1 x12245 +1 x12246 +1 x12247 +1 x12248 +1 x12249 +1 x12250 +1 x12251 +1 x12252 +1 x12253 +1 x12254 +1 x12255 +1 x12256 +1 x12257 +1 x12258 +1 x12259 +1 x12260 +1 x12261 +1 x12262 +1 x12263 +1 x12264 +1 x12265 +1 x12266 +1 x12267 +1 x12268 +1 x12269 +1 x12270 +1 x12271 +1 x12272 +1 x12273 +1 x12274 +1 x12275 +1 x12276 +1 x12277 +1 x12278 +1 x12279 +1 x12280 +1 x12281 +1 x12282 +1 x12283 +1 x12284 +1 x12285 +1 x12286 +1 x12287 +1 x12288 = 0 ;+-1 x1 -1 x2 -1 x3 -1 x4 -1 x5 -1 x6 -1 x7 -1 x8 -1 x9 -1 x10 -1 x11 -1 x12 -1 x13 -1 x14 -1 x15 -1 x16 -1 x17 -1 x18 -1 x19 -1 x20 -1 x21 -1 x22 -1 x23 -1 x24 -1 x25 -1 x26 -1 x27 -1 x28 -1 x29 -1 x30 -1 x31 -1 x32 -1 x33 -1 x34 -1 x35 -1 x36 -1 x37 -1 x38 -1 x39 -1 x40 -1 x41 -1 x42 -1 x43 -1 x44 -1 x45 -1 x46 -1 x47 -1 x48 -1 x49 -1 x50 -1 x51 -1 x52 -1 x53 -1 x54 -1 x55 -1 x56 -1 x57 -1 x58 -1 x59 -1 x60 -1 x61 -1 x62 -1 x63 -1 x64 -1 x65 -1 x66 -1 x67 -1 x68 -1 x69 -1 x70 -1 x71 -1 x72 -1 x73 -1 x74 -1 x75 -1 x76 -1 x77 -1 x78 -1 x79 -1 x80 -1 x81 -1 x82 -1 x83 -1 x84 -1 x85 -1 x86 -1 x87 -1 x88 -1 x89 -1 x90 -1 x91 -1 x92 -1 x93 -1 x94 -1 x95 -1 x96 -1 x97 -1 x98 -1 x99 -1 x100 -1 x101 -1 x102 -1 x103 -1 x104 -1 x105 -1 x106 -1 x107 -1 x108 -1 x109 -1 x110 -1 x111 -1 x112 -1 x113 -1 x114 -1 x115 -1 x116 -1 x117 -1 x118 -1 x119 -1 x120 -1 x121 -1 x122 -1 x123 -1 x124 -1 x125 -1 x126 -1 x127 -1 x128 >= -1 ;+-1 x129 -1 x130 -1 x131 -1 x132 -1 x133 -1 x134 -1 x135 -1 x136 -1 x137 -1 x138 -1 x139 -1 x140 -1 x141 -1 x142 -1 x143 -1 x144 -1 x145 -1 x146 -1 x147 -1 x148 -1 x149 -1 x150 -1 x151 -1 x152 -1 x153 -1 x154 -1 x155 -1 x156 -1 x157 -1 x158 -1 x159 -1 x160 -1 x161 -1 x162 -1 x163 -1 x164 -1 x165 -1 x166 -1 x167 -1 x168 -1 x169 -1 x170 -1 x171 -1 x172 -1 x173 -1 x174 -1 x175 -1 x176 -1 x177 -1 x178 -1 x179 -1 x180 -1 x181 -1 x182 -1 x183 -1 x184 -1 x185 -1 x186 -1 x187 -1 x188 -1 x189 -1 x190 -1 x191 -1 x192 -1 x193 -1 x194 -1 x195 -1 x196 -1 x197 -1 x198 -1 x199 -1 x200 -1 x201 -1 x202 -1 x203 -1 x204 -1 x205 -1 x206 -1 x207 -1 x208 -1 x209 -1 x210 -1 x211 -1 x212 -1 x213 -1 x214 -1 x215 -1 x216 -1 x217 -1 x218 -1 x219 -1 x220 -1 x221 -1 x222 -1 x223 -1 x224 -1 x225 -1 x226 -1 x227 -1 x228 -1 x229 -1 x230 -1 x231 -1 x232 -1 x233 -1 x234 -1 x235 -1 x236 -1 x237 -1 x238 -1 x239 -1 x240 -1 x241 -1 x242 -1 x243 -1 x244 -1 x245 -1 x246 -1 x247 -1 x248 -1 x249 -1 x250 -1 x251 -1 x252 -1 x253 -1 x254 -1 x255 -1 x256 >= -1 ;+-1 x257 -1 x258 -1 x259 -1 x260 -1 x261 -1 x262 -1 x263 -1 x264 -1 x265 -1 x266 -1 x267 -1 x268 -1 x269 -1 x270 -1 x271 -1 x272 -1 x273 -1 x274 -1 x275 -1 x276 -1 x277 -1 x278 -1 x279 -1 x280 -1 x281 -1 x282 -1 x283 -1 x284 -1 x285 -1 x286 -1 x287 -1 x288 -1 x289 -1 x290 -1 x291 -1 x292 -1 x293 -1 x294 -1 x295 -1 x296 -1 x297 -1 x298 -1 x299 -1 x300 -1 x301 -1 x302 -1 x303 -1 x304 -1 x305 -1 x306 -1 x307 -1 x308 -1 x309 -1 x310 -1 x311 -1 x312 -1 x313 -1 x314 -1 x315 -1 x316 -1 x317 -1 x318 -1 x319 -1 x320 -1 x321 -1 x322 -1 x323 -1 x324 -1 x325 -1 x326 -1 x327 -1 x328 -1 x329 -1 x330 -1 x331 -1 x332 -1 x333 -1 x334 -1 x335 -1 x336 -1 x337 -1 x338 -1 x339 -1 x340 -1 x341 -1 x342 -1 x343 -1 x344 -1 x345 -1 x346 -1 x347 -1 x348 -1 x349 -1 x350 -1 x351 -1 x352 -1 x353 -1 x354 -1 x355 -1 x356 -1 x357 -1 x358 -1 x359 -1 x360 -1 x361 -1 x362 -1 x363 -1 x364 -1 x365 -1 x366 -1 x367 -1 x368 -1 x369 -1 x370 -1 x371 -1 x372 -1 x373 -1 x374 -1 x375 -1 x376 -1 x377 -1 x378 -1 x379 -1 x380 -1 x381 -1 x382 -1 x383 -1 x384 >= -1 ;+-1 x385 -1 x386 -1 x387 -1 x388 -1 x389 -1 x390 -1 x391 -1 x392 -1 x393 -1 x394 -1 x395 -1 x396 -1 x397 -1 x398 -1 x399 -1 x400 -1 x401 -1 x402 -1 x403 -1 x404 -1 x405 -1 x406 -1 x407 -1 x408 -1 x409 -1 x410 -1 x411 -1 x412 -1 x413 -1 x414 -1 x415 -1 x416 -1 x417 -1 x418 -1 x419 -1 x420 -1 x421 -1 x422 -1 x423 -1 x424 -1 x425 -1 x426 -1 x427 -1 x428 -1 x429 -1 x430 -1 x431 -1 x432 -1 x433 -1 x434 -1 x435 -1 x436 -1 x437 -1 x438 -1 x439 -1 x440 -1 x441 -1 x442 -1 x443 -1 x444 -1 x445 -1 x446 -1 x447 -1 x448 -1 x449 -1 x450 -1 x451 -1 x452 -1 x453 -1 x454 -1 x455 -1 x456 -1 x457 -1 x458 -1 x459 -1 x460 -1 x461 -1 x462 -1 x463 -1 x464 -1 x465 -1 x466 -1 x467 -1 x468 -1 x469 -1 x470 -1 x471 -1 x472 -1 x473 -1 x474 -1 x475 -1 x476 -1 x477 -1 x478 -1 x479 -1 x480 -1 x481 -1 x482 -1 x483 -1 x484 -1 x485 -1 x486 -1 x487 -1 x488 -1 x489 -1 x490 -1 x491 -1 x492 -1 x493 -1 x494 -1 x495 -1 x496 -1 x497 -1 x498 -1 x499 -1 x500 -1 x501 -1 x502 -1 x503 -1 x504 -1 x505 -1 x506 -1 x507 -1 x508 -1 x509 -1 x510 -1 x511 -1 x512 >= -1 ;+-1 x513 -1 x514 -1 x515 -1 x516 -1 x517 -1 x518 -1 x519 -1 x520 -1 x521 -1 x522 -1 x523 -1 x524 -1 x525 -1 x526 -1 x527 -1 x528 -1 x529 -1 x530 -1 x531 -1 x532 -1 x533 -1 x534 -1 x535 -1 x536 -1 x537 -1 x538 -1 x539 -1 x540 -1 x541 -1 x542 -1 x543 -1 x544 -1 x545 -1 x546 -1 x547 -1 x548 -1 x549 -1 x550 -1 x551 -1 x552 -1 x553 -1 x554 -1 x555 -1 x556 -1 x557 -1 x558 -1 x559 -1 x560 -1 x561 -1 x562 -1 x563 -1 x564 -1 x565 -1 x566 -1 x567 -1 x568 -1 x569 -1 x570 -1 x571 -1 x572 -1 x573 -1 x574 -1 x575 -1 x576 -1 x577 -1 x578 -1 x579 -1 x580 -1 x581 -1 x582 -1 x583 -1 x584 -1 x585 -1 x586 -1 x587 -1 x588 -1 x589 -1 x590 -1 x591 -1 x592 -1 x593 -1 x594 -1 x595 -1 x596 -1 x597 -1 x598 -1 x599 -1 x600 -1 x601 -1 x602 -1 x603 -1 x604 -1 x605 -1 x606 -1 x607 -1 x608 -1 x609 -1 x610 -1 x611 -1 x612 -1 x613 -1 x614 -1 x615 -1 x616 -1 x617 -1 x618 -1 x619 -1 x620 -1 x621 -1 x622 -1 x623 -1 x624 -1 x625 -1 x626 -1 x627 -1 x628 -1 x629 -1 x630 -1 x631 -1 x632 -1 x633 -1 x634 -1 x635 -1 x636 -1 x637 -1 x638 -1 x639 -1 x640 >= -1 ;+-1 x641 -1 x642 -1 x643 -1 x644 -1 x645 -1 x646 -1 x647 -1 x648 -1 x649 -1 x650 -1 x651 -1 x652 -1 x653 -1 x654 -1 x655 -1 x656 -1 x657 -1 x658 -1 x659 -1 x660 -1 x661 -1 x662 -1 x663 -1 x664 -1 x665 -1 x666 -1 x667 -1 x668 -1 x669 -1 x670 -1 x671 -1 x672 -1 x673 -1 x674 -1 x675 -1 x676 -1 x677 -1 x678 -1 x679 -1 x680 -1 x681 -1 x682 -1 x683 -1 x684 -1 x685 -1 x686 -1 x687 -1 x688 -1 x689 -1 x690 -1 x691 -1 x692 -1 x693 -1 x694 -1 x695 -1 x696 -1 x697 -1 x698 -1 x699 -1 x700 -1 x701 -1 x702 -1 x703 -1 x704 -1 x705 -1 x706 -1 x707 -1 x708 -1 x709 -1 x710 -1 x711 -1 x712 -1 x713 -1 x714 -1 x715 -1 x716 -1 x717 -1 x718 -1 x719 -1 x720 -1 x721 -1 x722 -1 x723 -1 x724 -1 x725 -1 x726 -1 x727 -1 x728 -1 x729 -1 x730 -1 x731 -1 x732 -1 x733 -1 x734 -1 x735 -1 x736 -1 x737 -1 x738 -1 x739 -1 x740 -1 x741 -1 x742 -1 x743 -1 x744 -1 x745 -1 x746 -1 x747 -1 x748 -1 x749 -1 x750 -1 x751 -1 x752 -1 x753 -1 x754 -1 x755 -1 x756 -1 x757 -1 x758 -1 x759 -1 x760 -1 x761 -1 x762 -1 x763 -1 x764 -1 x765 -1 x766 -1 x767 -1 x768 >= -1 ;+-1 x769 -1 x770 -1 x771 -1 x772 -1 x773 -1 x774 -1 x775 -1 x776 -1 x777 -1 x778 -1 x779 -1 x780 -1 x781 -1 x782 -1 x783 -1 x784 -1 x785 -1 x786 -1 x787 -1 x788 -1 x789 -1 x790 -1 x791 -1 x792 -1 x793 -1 x794 -1 x795 -1 x796 -1 x797 -1 x798 -1 x799 -1 x800 -1 x801 -1 x802 -1 x803 -1 x804 -1 x805 -1 x806 -1 x807 -1 x808 -1 x809 -1 x810 -1 x811 -1 x812 -1 x813 -1 x814 -1 x815 -1 x816 -1 x817 -1 x818 -1 x819 -1 x820 -1 x821 -1 x822 -1 x823 -1 x824 -1 x825 -1 x826 -1 x827 -1 x828 -1 x829 -1 x830 -1 x831 -1 x832 -1 x833 -1 x834 -1 x835 -1 x836 -1 x837 -1 x838 -1 x839 -1 x840 -1 x841 -1 x842 -1 x843 -1 x844 -1 x845 -1 x846 -1 x847 -1 x848 -1 x849 -1 x850 -1 x851 -1 x852 -1 x853 -1 x854 -1 x855 -1 x856 -1 x857 -1 x858 -1 x859 -1 x860 -1 x861 -1 x862 -1 x863 -1 x864 -1 x865 -1 x866 -1 x867 -1 x868 -1 x869 -1 x870 -1 x871 -1 x872 -1 x873 -1 x874 -1 x875 -1 x876 -1 x877 -1 x878 -1 x879 -1 x880 -1 x881 -1 x882 -1 x883 -1 x884 -1 x885 -1 x886 -1 x887 -1 x888 -1 x889 -1 x890 -1 x891 -1 x892 -1 x893 -1 x894 -1 x895 -1 x896 >= -1 ;+-1 x897 -1 x898 -1 x899 -1 x900 -1 x901 -1 x902 -1 x903 -1 x904 -1 x905 -1 x906 -1 x907 -1 x908 -1 x909 -1 x910 -1 x911 -1 x912 -1 x913 -1 x914 -1 x915 -1 x916 -1 x917 -1 x918 -1 x919 -1 x920 -1 x921 -1 x922 -1 x923 -1 x924 -1 x925 -1 x926 -1 x927 -1 x928 -1 x929 -1 x930 -1 x931 -1 x932 -1 x933 -1 x934 -1 x935 -1 x936 -1 x937 -1 x938 -1 x939 -1 x940 -1 x941 -1 x942 -1 x943 -1 x944 -1 x945 -1 x946 -1 x947 -1 x948 -1 x949 -1 x950 -1 x951 -1 x952 -1 x953 -1 x954 -1 x955 -1 x956 -1 x957 -1 x958 -1 x959 -1 x960 -1 x961 -1 x962 -1 x963 -1 x964 -1 x965 -1 x966 -1 x967 -1 x968 -1 x969 -1 x970 -1 x971 -1 x972 -1 x973 -1 x974 -1 x975 -1 x976 -1 x977 -1 x978 -1 x979 -1 x980 -1 x981 -1 x982 -1 x983 -1 x984 -1 x985 -1 x986 -1 x987 -1 x988 -1 x989 -1 x990 -1 x991 -1 x992 -1 x993 -1 x994 -1 x995 -1 x996 -1 x997 -1 x998 -1 x999 -1 x1000 -1 x1001 -1 x1002 -1 x1003 -1 x1004 -1 x1005 -1 x1006 -1 x1007 -1 x1008 -1 x1009 -1 x1010 -1 x1011 -1 x1012 -1 x1013 -1 x1014 -1 x1015 -1 x1016 -1 x1017 -1 x1018 -1 x1019 -1 x1020 -1 x1021 -1 x1022 -1 x1023 -1 x1024 >= -1 ;+-1 x1025 -1 x1026 -1 x1027 -1 x1028 -1 x1029 -1 x1030 -1 x1031 -1 x1032 -1 x1033 -1 x1034 -1 x1035 -1 x1036 -1 x1037 -1 x1038 -1 x1039 -1 x1040 -1 x1041 -1 x1042 -1 x1043 -1 x1044 -1 x1045 -1 x1046 -1 x1047 -1 x1048 -1 x1049 -1 x1050 -1 x1051 -1 x1052 -1 x1053 -1 x1054 -1 x1055 -1 x1056 -1 x1057 -1 x1058 -1 x1059 -1 x1060 -1 x1061 -1 x1062 -1 x1063 -1 x1064 -1 x1065 -1 x1066 -1 x1067 -1 x1068 -1 x1069 -1 x1070 -1 x1071 -1 x1072 -1 x1073 -1 x1074 -1 x1075 -1 x1076 -1 x1077 -1 x1078 -1 x1079 -1 x1080 -1 x1081 -1 x1082 -1 x1083 -1 x1084 -1 x1085 -1 x1086 -1 x1087 -1 x1088 -1 x1089 -1 x1090 -1 x1091 -1 x1092 -1 x1093 -1 x1094 -1 x1095 -1 x1096 -1 x1097 -1 x1098 -1 x1099 -1 x1100 -1 x1101 -1 x1102 -1 x1103 -1 x1104 -1 x1105 -1 x1106 -1 x1107 -1 x1108 -1 x1109 -1 x1110 -1 x1111 -1 x1112 -1 x1113 -1 x1114 -1 x1115 -1 x1116 -1 x1117 -1 x1118 -1 x1119 -1 x1120 -1 x1121 -1 x1122 -1 x1123 -1 x1124 -1 x1125 -1 x1126 -1 x1127 -1 x1128 -1 x1129 -1 x1130 -1 x1131 -1 x1132 -1 x1133 -1 x1134 -1 x1135 -1 x1136 -1 x1137 -1 x1138 -1 x1139 -1 x1140 -1 x1141 -1 x1142 -1 x1143 -1 x1144 -1 x1145 -1 x1146 -1 x1147 -1 x1148 -1 x1149 -1 x1150 -1 x1151 -1 x1152 >= -1 ;+-1 x1153 -1 x1154 -1 x1155 -1 x1156 -1 x1157 -1 x1158 -1 x1159 -1 x1160 -1 x1161 -1 x1162 -1 x1163 -1 x1164 -1 x1165 -1 x1166 -1 x1167 -1 x1168 -1 x1169 -1 x1170 -1 x1171 -1 x1172 -1 x1173 -1 x1174 -1 x1175 -1 x1176 -1 x1177 -1 x1178 -1 x1179 -1 x1180 -1 x1181 -1 x1182 -1 x1183 -1 x1184 -1 x1185 -1 x1186 -1 x1187 -1 x1188 -1 x1189 -1 x1190 -1 x1191 -1 x1192 -1 x1193 -1 x1194 -1 x1195 -1 x1196 -1 x1197 -1 x1198 -1 x1199 -1 x1200 -1 x1201 -1 x1202 -1 x1203 -1 x1204 -1 x1205 -1 x1206 -1 x1207 -1 x1208 -1 x1209 -1 x1210 -1 x1211 -1 x1212 -1 x1213 -1 x1214 -1 x1215 -1 x1216 -1 x1217 -1 x1218 -1 x1219 -1 x1220 -1 x1221 -1 x1222 -1 x1223 -1 x1224 -1 x1225 -1 x1226 -1 x1227 -1 x1228 -1 x1229 -1 x1230 -1 x1231 -1 x1232 -1 x1233 -1 x1234 -1 x1235 -1 x1236 -1 x1237 -1 x1238 -1 x1239 -1 x1240 -1 x1241 -1 x1242 -1 x1243 -1 x1244 -1 x1245 -1 x1246 -1 x1247 -1 x1248 -1 x1249 -1 x1250 -1 x1251 -1 x1252 -1 x1253 -1 x1254 -1 x1255 -1 x1256 -1 x1257 -1 x1258 -1 x1259 -1 x1260 -1 x1261 -1 x1262 -1 x1263 -1 x1264 -1 x1265 -1 x1266 -1 x1267 -1 x1268 -1 x1269 -1 x1270 -1 x1271 -1 x1272 -1 x1273 -1 x1274 -1 x1275 -1 x1276 -1 x1277 -1 x1278 -1 x1279 -1 x1280 >= -1 ;+-1 x1281 -1 x1282 -1 x1283 -1 x1284 -1 x1285 -1 x1286 -1 x1287 -1 x1288 -1 x1289 -1 x1290 -1 x1291 -1 x1292 -1 x1293 -1 x1294 -1 x1295 -1 x1296 -1 x1297 -1 x1298 -1 x1299 -1 x1300 -1 x1301 -1 x1302 -1 x1303 -1 x1304 -1 x1305 -1 x1306 -1 x1307 -1 x1308 -1 x1309 -1 x1310 -1 x1311 -1 x1312 -1 x1313 -1 x1314 -1 x1315 -1 x1316 -1 x1317 -1 x1318 -1 x1319 -1 x1320 -1 x1321 -1 x1322 -1 x1323 -1 x1324 -1 x1325 -1 x1326 -1 x1327 -1 x1328 -1 x1329 -1 x1330 -1 x1331 -1 x1332 -1 x1333 -1 x1334 -1 x1335 -1 x1336 -1 x1337 -1 x1338 -1 x1339 -1 x1340 -1 x1341 -1 x1342 -1 x1343 -1 x1344 -1 x1345 -1 x1346 -1 x1347 -1 x1348 -1 x1349 -1 x1350 -1 x1351 -1 x1352 -1 x1353 -1 x1354 -1 x1355 -1 x1356 -1 x1357 -1 x1358 -1 x1359 -1 x1360 -1 x1361 -1 x1362 -1 x1363 -1 x1364 -1 x1365 -1 x1366 -1 x1367 -1 x1368 -1 x1369 -1 x1370 -1 x1371 -1 x1372 -1 x1373 -1 x1374 -1 x1375 -1 x1376 -1 x1377 -1 x1378 -1 x1379 -1 x1380 -1 x1381 -1 x1382 -1 x1383 -1 x1384 -1 x1385 -1 x1386 -1 x1387 -1 x1388 -1 x1389 -1 x1390 -1 x1391 -1 x1392 -1 x1393 -1 x1394 -1 x1395 -1 x1396 -1 x1397 -1 x1398 -1 x1399 -1 x1400 -1 x1401 -1 x1402 -1 x1403 -1 x1404 -1 x1405 -1 x1406 -1 x1407 -1 x1408 >= -1 ;+-1 x1409 -1 x1410 -1 x1411 -1 x1412 -1 x1413 -1 x1414 -1 x1415 -1 x1416 -1 x1417 -1 x1418 -1 x1419 -1 x1420 -1 x1421 -1 x1422 -1 x1423 -1 x1424 -1 x1425 -1 x1426 -1 x1427 -1 x1428 -1 x1429 -1 x1430 -1 x1431 -1 x1432 -1 x1433 -1 x1434 -1 x1435 -1 x1436 -1 x1437 -1 x1438 -1 x1439 -1 x1440 -1 x1441 -1 x1442 -1 x1443 -1 x1444 -1 x1445 -1 x1446 -1 x1447 -1 x1448 -1 x1449 -1 x1450 -1 x1451 -1 x1452 -1 x1453 -1 x1454 -1 x1455 -1 x1456 -1 x1457 -1 x1458 -1 x1459 -1 x1460 -1 x1461 -1 x1462 -1 x1463 -1 x1464 -1 x1465 -1 x1466 -1 x1467 -1 x1468 -1 x1469 -1 x1470 -1 x1471 -1 x1472 -1 x1473 -1 x1474 -1 x1475 -1 x1476 -1 x1477 -1 x1478 -1 x1479 -1 x1480 -1 x1481 -1 x1482 -1 x1483 -1 x1484 -1 x1485 -1 x1486 -1 x1487 -1 x1488 -1 x1489 -1 x1490 -1 x1491 -1 x1492 -1 x1493 -1 x1494 -1 x1495 -1 x1496 -1 x1497 -1 x1498 -1 x1499 -1 x1500 -1 x1501 -1 x1502 -1 x1503 -1 x1504 -1 x1505 -1 x1506 -1 x1507 -1 x1508 -1 x1509 -1 x1510 -1 x1511 -1 x1512 -1 x1513 -1 x1514 -1 x1515 -1 x1516 -1 x1517 -1 x1518 -1 x1519 -1 x1520 -1 x1521 -1 x1522 -1 x1523 -1 x1524 -1 x1525 -1 x1526 -1 x1527 -1 x1528 -1 x1529 -1 x1530 -1 x1531 -1 x1532 -1 x1533 -1 x1534 -1 x1535 -1 x1536 >= -1 ;+-1 x1537 -1 x1538 -1 x1539 -1 x1540 -1 x1541 -1 x1542 -1 x1543 -1 x1544 -1 x1545 -1 x1546 -1 x1547 -1 x1548 -1 x1549 -1 x1550 -1 x1551 -1 x1552 -1 x1553 -1 x1554 -1 x1555 -1 x1556 -1 x1557 -1 x1558 -1 x1559 -1 x1560 -1 x1561 -1 x1562 -1 x1563 -1 x1564 -1 x1565 -1 x1566 -1 x1567 -1 x1568 -1 x1569 -1 x1570 -1 x1571 -1 x1572 -1 x1573 -1 x1574 -1 x1575 -1 x1576 -1 x1577 -1 x1578 -1 x1579 -1 x1580 -1 x1581 -1 x1582 -1 x1583 -1 x1584 -1 x1585 -1 x1586 -1 x1587 -1 x1588 -1 x1589 -1 x1590 -1 x1591 -1 x1592 -1 x1593 -1 x1594 -1 x1595 -1 x1596 -1 x1597 -1 x1598 -1 x1599 -1 x1600 -1 x1601 -1 x1602 -1 x1603 -1 x1604 -1 x1605 -1 x1606 -1 x1607 -1 x1608 -1 x1609 -1 x1610 -1 x1611 -1 x1612 -1 x1613 -1 x1614 -1 x1615 -1 x1616 -1 x1617 -1 x1618 -1 x1619 -1 x1620 -1 x1621 -1 x1622 -1 x1623 -1 x1624 -1 x1625 -1 x1626 -1 x1627 -1 x1628 -1 x1629 -1 x1630 -1 x1631 -1 x1632 -1 x1633 -1 x1634 -1 x1635 -1 x1636 -1 x1637 -1 x1638 -1 x1639 -1 x1640 -1 x1641 -1 x1642 -1 x1643 -1 x1644 -1 x1645 -1 x1646 -1 x1647 -1 x1648 -1 x1649 -1 x1650 -1 x1651 -1 x1652 -1 x1653 -1 x1654 -1 x1655 -1 x1656 -1 x1657 -1 x1658 -1 x1659 -1 x1660 -1 x1661 -1 x1662 -1 x1663 -1 x1664 >= -1 ;+-1 x1665 -1 x1666 -1 x1667 -1 x1668 -1 x1669 -1 x1670 -1 x1671 -1 x1672 -1 x1673 -1 x1674 -1 x1675 -1 x1676 -1 x1677 -1 x1678 -1 x1679 -1 x1680 -1 x1681 -1 x1682 -1 x1683 -1 x1684 -1 x1685 -1 x1686 -1 x1687 -1 x1688 -1 x1689 -1 x1690 -1 x1691 -1 x1692 -1 x1693 -1 x1694 -1 x1695 -1 x1696 -1 x1697 -1 x1698 -1 x1699 -1 x1700 -1 x1701 -1 x1702 -1 x1703 -1 x1704 -1 x1705 -1 x1706 -1 x1707 -1 x1708 -1 x1709 -1 x1710 -1 x1711 -1 x1712 -1 x1713 -1 x1714 -1 x1715 -1 x1716 -1 x1717 -1 x1718 -1 x1719 -1 x1720 -1 x1721 -1 x1722 -1 x1723 -1 x1724 -1 x1725 -1 x1726 -1 x1727 -1 x1728 -1 x1729 -1 x1730 -1 x1731 -1 x1732 -1 x1733 -1 x1734 -1 x1735 -1 x1736 -1 x1737 -1 x1738 -1 x1739 -1 x1740 -1 x1741 -1 x1742 -1 x1743 -1 x1744 -1 x1745 -1 x1746 -1 x1747 -1 x1748 -1 x1749 -1 x1750 -1 x1751 -1 x1752 -1 x1753 -1 x1754 -1 x1755 -1 x1756 -1 x1757 -1 x1758 -1 x1759 -1 x1760 -1 x1761 -1 x1762 -1 x1763 -1 x1764 -1 x1765 -1 x1766 -1 x1767 -1 x1768 -1 x1769 -1 x1770 -1 x1771 -1 x1772 -1 x1773 -1 x1774 -1 x1775 -1 x1776 -1 x1777 -1 x1778 -1 x1779 -1 x1780 -1 x1781 -1 x1782 -1 x1783 -1 x1784 -1 x1785 -1 x1786 -1 x1787 -1 x1788 -1 x1789 -1 x1790 -1 x1791 -1 x1792 >= -1 ;+-1 x1793 -1 x1794 -1 x1795 -1 x1796 -1 x1797 -1 x1798 -1 x1799 -1 x1800 -1 x1801 -1 x1802 -1 x1803 -1 x1804 -1 x1805 -1 x1806 -1 x1807 -1 x1808 -1 x1809 -1 x1810 -1 x1811 -1 x1812 -1 x1813 -1 x1814 -1 x1815 -1 x1816 -1 x1817 -1 x1818 -1 x1819 -1 x1820 -1 x1821 -1 x1822 -1 x1823 -1 x1824 -1 x1825 -1 x1826 -1 x1827 -1 x1828 -1 x1829 -1 x1830 -1 x1831 -1 x1832 -1 x1833 -1 x1834 -1 x1835 -1 x1836 -1 x1837 -1 x1838 -1 x1839 -1 x1840 -1 x1841 -1 x1842 -1 x1843 -1 x1844 -1 x1845 -1 x1846 -1 x1847 -1 x1848 -1 x1849 -1 x1850 -1 x1851 -1 x1852 -1 x1853 -1 x1854 -1 x1855 -1 x1856 -1 x1857 -1 x1858 -1 x1859 -1 x1860 -1 x1861 -1 x1862 -1 x1863 -1 x1864 -1 x1865 -1 x1866 -1 x1867 -1 x1868 -1 x1869 -1 x1870 -1 x1871 -1 x1872 -1 x1873 -1 x1874 -1 x1875 -1 x1876 -1 x1877 -1 x1878 -1 x1879 -1 x1880 -1 x1881 -1 x1882 -1 x1883 -1 x1884 -1 x1885 -1 x1886 -1 x1887 -1 x1888 -1 x1889 -1 x1890 -1 x1891 -1 x1892 -1 x1893 -1 x1894 -1 x1895 -1 x1896 -1 x1897 -1 x1898 -1 x1899 -1 x1900 -1 x1901 -1 x1902 -1 x1903 -1 x1904 -1 x1905 -1 x1906 -1 x1907 -1 x1908 -1 x1909 -1 x1910 -1 x1911 -1 x1912 -1 x1913 -1 x1914 -1 x1915 -1 x1916 -1 x1917 -1 x1918 -1 x1919 -1 x1920 >= -1 ;+-1 x1921 -1 x1922 -1 x1923 -1 x1924 -1 x1925 -1 x1926 -1 x1927 -1 x1928 -1 x1929 -1 x1930 -1 x1931 -1 x1932 -1 x1933 -1 x1934 -1 x1935 -1 x1936 -1 x1937 -1 x1938 -1 x1939 -1 x1940 -1 x1941 -1 x1942 -1 x1943 -1 x1944 -1 x1945 -1 x1946 -1 x1947 -1 x1948 -1 x1949 -1 x1950 -1 x1951 -1 x1952 -1 x1953 -1 x1954 -1 x1955 -1 x1956 -1 x1957 -1 x1958 -1 x1959 -1 x1960 -1 x1961 -1 x1962 -1 x1963 -1 x1964 -1 x1965 -1 x1966 -1 x1967 -1 x1968 -1 x1969 -1 x1970 -1 x1971 -1 x1972 -1 x1973 -1 x1974 -1 x1975 -1 x1976 -1 x1977 -1 x1978 -1 x1979 -1 x1980 -1 x1981 -1 x1982 -1 x1983 -1 x1984 -1 x1985 -1 x1986 -1 x1987 -1 x1988 -1 x1989 -1 x1990 -1 x1991 -1 x1992 -1 x1993 -1 x1994 -1 x1995 -1 x1996 -1 x1997 -1 x1998 -1 x1999 -1 x2000 -1 x2001 -1 x2002 -1 x2003 -1 x2004 -1 x2005 -1 x2006 -1 x2007 -1 x2008 -1 x2009 -1 x2010 -1 x2011 -1 x2012 -1 x2013 -1 x2014 -1 x2015 -1 x2016 -1 x2017 -1 x2018 -1 x2019 -1 x2020 -1 x2021 -1 x2022 -1 x2023 -1 x2024 -1 x2025 -1 x2026 -1 x2027 -1 x2028 -1 x2029 -1 x2030 -1 x2031 -1 x2032 -1 x2033 -1 x2034 -1 x2035 -1 x2036 -1 x2037 -1 x2038 -1 x2039 -1 x2040 -1 x2041 -1 x2042 -1 x2043 -1 x2044 -1 x2045 -1 x2046 -1 x2047 -1 x2048 >= -1 ;+-1 x2049 -1 x2050 -1 x2051 -1 x2052 -1 x2053 -1 x2054 -1 x2055 -1 x2056 -1 x2057 -1 x2058 -1 x2059 -1 x2060 -1 x2061 -1 x2062 -1 x2063 -1 x2064 -1 x2065 -1 x2066 -1 x2067 -1 x2068 -1 x2069 -1 x2070 -1 x2071 -1 x2072 -1 x2073 -1 x2074 -1 x2075 -1 x2076 -1 x2077 -1 x2078 -1 x2079 -1 x2080 -1 x2081 -1 x2082 -1 x2083 -1 x2084 -1 x2085 -1 x2086 -1 x2087 -1 x2088 -1 x2089 -1 x2090 -1 x2091 -1 x2092 -1 x2093 -1 x2094 -1 x2095 -1 x2096 -1 x2097 -1 x2098 -1 x2099 -1 x2100 -1 x2101 -1 x2102 -1 x2103 -1 x2104 -1 x2105 -1 x2106 -1 x2107 -1 x2108 -1 x2109 -1 x2110 -1 x2111 -1 x2112 -1 x2113 -1 x2114 -1 x2115 -1 x2116 -1 x2117 -1 x2118 -1 x2119 -1 x2120 -1 x2121 -1 x2122 -1 x2123 -1 x2124 -1 x2125 -1 x2126 -1 x2127 -1 x2128 -1 x2129 -1 x2130 -1 x2131 -1 x2132 -1 x2133 -1 x2134 -1 x2135 -1 x2136 -1 x2137 -1 x2138 -1 x2139 -1 x2140 -1 x2141 -1 x2142 -1 x2143 -1 x2144 -1 x2145 -1 x2146 -1 x2147 -1 x2148 -1 x2149 -1 x2150 -1 x2151 -1 x2152 -1 x2153 -1 x2154 -1 x2155 -1 x2156 -1 x2157 -1 x2158 -1 x2159 -1 x2160 -1 x2161 -1 x2162 -1 x2163 -1 x2164 -1 x2165 -1 x2166 -1 x2167 -1 x2168 -1 x2169 -1 x2170 -1 x2171 -1 x2172 -1 x2173 -1 x2174 -1 x2175 -1 x2176 >= -1 ;+-1 x2177 -1 x2178 -1 x2179 -1 x2180 -1 x2181 -1 x2182 -1 x2183 -1 x2184 -1 x2185 -1 x2186 -1 x2187 -1 x2188 -1 x2189 -1 x2190 -1 x2191 -1 x2192 -1 x2193 -1 x2194 -1 x2195 -1 x2196 -1 x2197 -1 x2198 -1 x2199 -1 x2200 -1 x2201 -1 x2202 -1 x2203 -1 x2204 -1 x2205 -1 x2206 -1 x2207 -1 x2208 -1 x2209 -1 x2210 -1 x2211 -1 x2212 -1 x2213 -1 x2214 -1 x2215 -1 x2216 -1 x2217 -1 x2218 -1 x2219 -1 x2220 -1 x2221 -1 x2222 -1 x2223 -1 x2224 -1 x2225 -1 x2226 -1 x2227 -1 x2228 -1 x2229 -1 x2230 -1 x2231 -1 x2232 -1 x2233 -1 x2234 -1 x2235 -1 x2236 -1 x2237 -1 x2238 -1 x2239 -1 x2240 -1 x2241 -1 x2242 -1 x2243 -1 x2244 -1 x2245 -1 x2246 -1 x2247 -1 x2248 -1 x2249 -1 x2250 -1 x2251 -1 x2252 -1 x2253 -1 x2254 -1 x2255 -1 x2256 -1 x2257 -1 x2258 -1 x2259 -1 x2260 -1 x2261 -1 x2262 -1 x2263 -1 x2264 -1 x2265 -1 x2266 -1 x2267 -1 x2268 -1 x2269 -1 x2270 -1 x2271 -1 x2272 -1 x2273 -1 x2274 -1 x2275 -1 x2276 -1 x2277 -1 x2278 -1 x2279 -1 x2280 -1 x2281 -1 x2282 -1 x2283 -1 x2284 -1 x2285 -1 x2286 -1 x2287 -1 x2288 -1 x2289 -1 x2290 -1 x2291 -1 x2292 -1 x2293 -1 x2294 -1 x2295 -1 x2296 -1 x2297 -1 x2298 -1 x2299 -1 x2300 -1 x2301 -1 x2302 -1 x2303 -1 x2304 >= -1 ;+-1 x2305 -1 x2306 -1 x2307 -1 x2308 -1 x2309 -1 x2310 -1 x2311 -1 x2312 -1 x2313 -1 x2314 -1 x2315 -1 x2316 -1 x2317 -1 x2318 -1 x2319 -1 x2320 -1 x2321 -1 x2322 -1 x2323 -1 x2324 -1 x2325 -1 x2326 -1 x2327 -1 x2328 -1 x2329 -1 x2330 -1 x2331 -1 x2332 -1 x2333 -1 x2334 -1 x2335 -1 x2336 -1 x2337 -1 x2338 -1 x2339 -1 x2340 -1 x2341 -1 x2342 -1 x2343 -1 x2344 -1 x2345 -1 x2346 -1 x2347 -1 x2348 -1 x2349 -1 x2350 -1 x2351 -1 x2352 -1 x2353 -1 x2354 -1 x2355 -1 x2356 -1 x2357 -1 x2358 -1 x2359 -1 x2360 -1 x2361 -1 x2362 -1 x2363 -1 x2364 -1 x2365 -1 x2366 -1 x2367 -1 x2368 -1 x2369 -1 x2370 -1 x2371 -1 x2372 -1 x2373 -1 x2374 -1 x2375 -1 x2376 -1 x2377 -1 x2378 -1 x2379 -1 x2380 -1 x2381 -1 x2382 -1 x2383 -1 x2384 -1 x2385 -1 x2386 -1 x2387 -1 x2388 -1 x2389 -1 x2390 -1 x2391 -1 x2392 -1 x2393 -1 x2394 -1 x2395 -1 x2396 -1 x2397 -1 x2398 -1 x2399 -1 x2400 -1 x2401 -1 x2402 -1 x2403 -1 x2404 -1 x2405 -1 x2406 -1 x2407 -1 x2408 -1 x2409 -1 x2410 -1 x2411 -1 x2412 -1 x2413 -1 x2414 -1 x2415 -1 x2416 -1 x2417 -1 x2418 -1 x2419 -1 x2420 -1 x2421 -1 x2422 -1 x2423 -1 x2424 -1 x2425 -1 x2426 -1 x2427 -1 x2428 -1 x2429 -1 x2430 -1 x2431 -1 x2432 >= -1 ;+-1 x2433 -1 x2434 -1 x2435 -1 x2436 -1 x2437 -1 x2438 -1 x2439 -1 x2440 -1 x2441 -1 x2442 -1 x2443 -1 x2444 -1 x2445 -1 x2446 -1 x2447 -1 x2448 -1 x2449 -1 x2450 -1 x2451 -1 x2452 -1 x2453 -1 x2454 -1 x2455 -1 x2456 -1 x2457 -1 x2458 -1 x2459 -1 x2460 -1 x2461 -1 x2462 -1 x2463 -1 x2464 -1 x2465 -1 x2466 -1 x2467 -1 x2468 -1 x2469 -1 x2470 -1 x2471 -1 x2472 -1 x2473 -1 x2474 -1 x2475 -1 x2476 -1 x2477 -1 x2478 -1 x2479 -1 x2480 -1 x2481 -1 x2482 -1 x2483 -1 x2484 -1 x2485 -1 x2486 -1 x2487 -1 x2488 -1 x2489 -1 x2490 -1 x2491 -1 x2492 -1 x2493 -1 x2494 -1 x2495 -1 x2496 -1 x2497 -1 x2498 -1 x2499 -1 x2500 -1 x2501 -1 x2502 -1 x2503 -1 x2504 -1 x2505 -1 x2506 -1 x2507 -1 x2508 -1 x2509 -1 x2510 -1 x2511 -1 x2512 -1 x2513 -1 x2514 -1 x2515 -1 x2516 -1 x2517 -1 x2518 -1 x2519 -1 x2520 -1 x2521 -1 x2522 -1 x2523 -1 x2524 -1 x2525 -1 x2526 -1 x2527 -1 x2528 -1 x2529 -1 x2530 -1 x2531 -1 x2532 -1 x2533 -1 x2534 -1 x2535 -1 x2536 -1 x2537 -1 x2538 -1 x2539 -1 x2540 -1 x2541 -1 x2542 -1 x2543 -1 x2544 -1 x2545 -1 x2546 -1 x2547 -1 x2548 -1 x2549 -1 x2550 -1 x2551 -1 x2552 -1 x2553 -1 x2554 -1 x2555 -1 x2556 -1 x2557 -1 x2558 -1 x2559 -1 x2560 >= -1 ;+-1 x2561 -1 x2562 -1 x2563 -1 x2564 -1 x2565 -1 x2566 -1 x2567 -1 x2568 -1 x2569 -1 x2570 -1 x2571 -1 x2572 -1 x2573 -1 x2574 -1 x2575 -1 x2576 -1 x2577 -1 x2578 -1 x2579 -1 x2580 -1 x2581 -1 x2582 -1 x2583 -1 x2584 -1 x2585 -1 x2586 -1 x2587 -1 x2588 -1 x2589 -1 x2590 -1 x2591 -1 x2592 -1 x2593 -1 x2594 -1 x2595 -1 x2596 -1 x2597 -1 x2598 -1 x2599 -1 x2600 -1 x2601 -1 x2602 -1 x2603 -1 x2604 -1 x2605 -1 x2606 -1 x2607 -1 x2608 -1 x2609 -1 x2610 -1 x2611 -1 x2612 -1 x2613 -1 x2614 -1 x2615 -1 x2616 -1 x2617 -1 x2618 -1 x2619 -1 x2620 -1 x2621 -1 x2622 -1 x2623 -1 x2624 -1 x2625 -1 x2626 -1 x2627 -1 x2628 -1 x2629 -1 x2630 -1 x2631 -1 x2632 -1 x2633 -1 x2634 -1 x2635 -1 x2636 -1 x2637 -1 x2638 -1 x2639 -1 x2640 -1 x2641 -1 x2642 -1 x2643 -1 x2644 -1 x2645 -1 x2646 -1 x2647 -1 x2648 -1 x2649 -1 x2650 -1 x2651 -1 x2652 -1 x2653 -1 x2654 -1 x2655 -1 x2656 -1 x2657 -1 x2658 -1 x2659 -1 x2660 -1 x2661 -1 x2662 -1 x2663 -1 x2664 -1 x2665 -1 x2666 -1 x2667 -1 x2668 -1 x2669 -1 x2670 -1 x2671 -1 x2672 -1 x2673 -1 x2674 -1 x2675 -1 x2676 -1 x2677 -1 x2678 -1 x2679 -1 x2680 -1 x2681 -1 x2682 -1 x2683 -1 x2684 -1 x2685 -1 x2686 -1 x2687 -1 x2688 >= -1 ;+-1 x2689 -1 x2690 -1 x2691 -1 x2692 -1 x2693 -1 x2694 -1 x2695 -1 x2696 -1 x2697 -1 x2698 -1 x2699 -1 x2700 -1 x2701 -1 x2702 -1 x2703 -1 x2704 -1 x2705 -1 x2706 -1 x2707 -1 x2708 -1 x2709 -1 x2710 -1 x2711 -1 x2712 -1 x2713 -1 x2714 -1 x2715 -1 x2716 -1 x2717 -1 x2718 -1 x2719 -1 x2720 -1 x2721 -1 x2722 -1 x2723 -1 x2724 -1 x2725 -1 x2726 -1 x2727 -1 x2728 -1 x2729 -1 x2730 -1 x2731 -1 x2732 -1 x2733 -1 x2734 -1 x2735 -1 x2736 -1 x2737 -1 x2738 -1 x2739 -1 x2740 -1 x2741 -1 x2742 -1 x2743 -1 x2744 -1 x2745 -1 x2746 -1 x2747 -1 x2748 -1 x2749 -1 x2750 -1 x2751 -1 x2752 -1 x2753 -1 x2754 -1 x2755 -1 x2756 -1 x2757 -1 x2758 -1 x2759 -1 x2760 -1 x2761 -1 x2762 -1 x2763 -1 x2764 -1 x2765 -1 x2766 -1 x2767 -1 x2768 -1 x2769 -1 x2770 -1 x2771 -1 x2772 -1 x2773 -1 x2774 -1 x2775 -1 x2776 -1 x2777 -1 x2778 -1 x2779 -1 x2780 -1 x2781 -1 x2782 -1 x2783 -1 x2784 -1 x2785 -1 x2786 -1 x2787 -1 x2788 -1 x2789 -1 x2790 -1 x2791 -1 x2792 -1 x2793 -1 x2794 -1 x2795 -1 x2796 -1 x2797 -1 x2798 -1 x2799 -1 x2800 -1 x2801 -1 x2802 -1 x2803 -1 x2804 -1 x2805 -1 x2806 -1 x2807 -1 x2808 -1 x2809 -1 x2810 -1 x2811 -1 x2812 -1 x2813 -1 x2814 -1 x2815 -1 x2816 >= -1 ;+-1 x2817 -1 x2818 -1 x2819 -1 x2820 -1 x2821 -1 x2822 -1 x2823 -1 x2824 -1 x2825 -1 x2826 -1 x2827 -1 x2828 -1 x2829 -1 x2830 -1 x2831 -1 x2832 -1 x2833 -1 x2834 -1 x2835 -1 x2836 -1 x2837 -1 x2838 -1 x2839 -1 x2840 -1 x2841 -1 x2842 -1 x2843 -1 x2844 -1 x2845 -1 x2846 -1 x2847 -1 x2848 -1 x2849 -1 x2850 -1 x2851 -1 x2852 -1 x2853 -1 x2854 -1 x2855 -1 x2856 -1 x2857 -1 x2858 -1 x2859 -1 x2860 -1 x2861 -1 x2862 -1 x2863 -1 x2864 -1 x2865 -1 x2866 -1 x2867 -1 x2868 -1 x2869 -1 x2870 -1 x2871 -1 x2872 -1 x2873 -1 x2874 -1 x2875 -1 x2876 -1 x2877 -1 x2878 -1 x2879 -1 x2880 -1 x2881 -1 x2882 -1 x2883 -1 x2884 -1 x2885 -1 x2886 -1 x2887 -1 x2888 -1 x2889 -1 x2890 -1 x2891 -1 x2892 -1 x2893 -1 x2894 -1 x2895 -1 x2896 -1 x2897 -1 x2898 -1 x2899 -1 x2900 -1 x2901 -1 x2902 -1 x2903 -1 x2904 -1 x2905 -1 x2906 -1 x2907 -1 x2908 -1 x2909 -1 x2910 -1 x2911 -1 x2912 -1 x2913 -1 x2914 -1 x2915 -1 x2916 -1 x2917 -1 x2918 -1 x2919 -1 x2920 -1 x2921 -1 x2922 -1 x2923 -1 x2924 -1 x2925 -1 x2926 -1 x2927 -1 x2928 -1 x2929 -1 x2930 -1 x2931 -1 x2932 -1 x2933 -1 x2934 -1 x2935 -1 x2936 -1 x2937 -1 x2938 -1 x2939 -1 x2940 -1 x2941 -1 x2942 -1 x2943 -1 x2944 >= -1 ;+-1 x2945 -1 x2946 -1 x2947 -1 x2948 -1 x2949 -1 x2950 -1 x2951 -1 x2952 -1 x2953 -1 x2954 -1 x2955 -1 x2956 -1 x2957 -1 x2958 -1 x2959 -1 x2960 -1 x2961 -1 x2962 -1 x2963 -1 x2964 -1 x2965 -1 x2966 -1 x2967 -1 x2968 -1 x2969 -1 x2970 -1 x2971 -1 x2972 -1 x2973 -1 x2974 -1 x2975 -1 x2976 -1 x2977 -1 x2978 -1 x2979 -1 x2980 -1 x2981 -1 x2982 -1 x2983 -1 x2984 -1 x2985 -1 x2986 -1 x2987 -1 x2988 -1 x2989 -1 x2990 -1 x2991 -1 x2992 -1 x2993 -1 x2994 -1 x2995 -1 x2996 -1 x2997 -1 x2998 -1 x2999 -1 x3000 -1 x3001 -1 x3002 -1 x3003 -1 x3004 -1 x3005 -1 x3006 -1 x3007 -1 x3008 -1 x3009 -1 x3010 -1 x3011 -1 x3012 -1 x3013 -1 x3014 -1 x3015 -1 x3016 -1 x3017 -1 x3018 -1 x3019 -1 x3020 -1 x3021 -1 x3022 -1 x3023 -1 x3024 -1 x3025 -1 x3026 -1 x3027 -1 x3028 -1 x3029 -1 x3030 -1 x3031 -1 x3032 -1 x3033 -1 x3034 -1 x3035 -1 x3036 -1 x3037 -1 x3038 -1 x3039 -1 x3040 -1 x3041 -1 x3042 -1 x3043 -1 x3044 -1 x3045 -1 x3046 -1 x3047 -1 x3048 -1 x3049 -1 x3050 -1 x3051 -1 x3052 -1 x3053 -1 x3054 -1 x3055 -1 x3056 -1 x3057 -1 x3058 -1 x3059 -1 x3060 -1 x3061 -1 x3062 -1 x3063 -1 x3064 -1 x3065 -1 x3066 -1 x3067 -1 x3068 -1 x3069 -1 x3070 -1 x3071 -1 x3072 >= -1 ;+-1 x3073 -1 x3074 -1 x3075 -1 x3076 -1 x3077 -1 x3078 -1 x3079 -1 x3080 -1 x3081 -1 x3082 -1 x3083 -1 x3084 -1 x3085 -1 x3086 -1 x3087 -1 x3088 -1 x3089 -1 x3090 -1 x3091 -1 x3092 -1 x3093 -1 x3094 -1 x3095 -1 x3096 -1 x3097 -1 x3098 -1 x3099 -1 x3100 -1 x3101 -1 x3102 -1 x3103 -1 x3104 -1 x3105 -1 x3106 -1 x3107 -1 x3108 -1 x3109 -1 x3110 -1 x3111 -1 x3112 -1 x3113 -1 x3114 -1 x3115 -1 x3116 -1 x3117 -1 x3118 -1 x3119 -1 x3120 -1 x3121 -1 x3122 -1 x3123 -1 x3124 -1 x3125 -1 x3126 -1 x3127 -1 x3128 -1 x3129 -1 x3130 -1 x3131 -1 x3132 -1 x3133 -1 x3134 -1 x3135 -1 x3136 -1 x3137 -1 x3138 -1 x3139 -1 x3140 -1 x3141 -1 x3142 -1 x3143 -1 x3144 -1 x3145 -1 x3146 -1 x3147 -1 x3148 -1 x3149 -1 x3150 -1 x3151 -1 x3152 -1 x3153 -1 x3154 -1 x3155 -1 x3156 -1 x3157 -1 x3158 -1 x3159 -1 x3160 -1 x3161 -1 x3162 -1 x3163 -1 x3164 -1 x3165 -1 x3166 -1 x3167 -1 x3168 -1 x3169 -1 x3170 -1 x3171 -1 x3172 -1 x3173 -1 x3174 -1 x3175 -1 x3176 -1 x3177 -1 x3178 -1 x3179 -1 x3180 -1 x3181 -1 x3182 -1 x3183 -1 x3184 -1 x3185 -1 x3186 -1 x3187 -1 x3188 -1 x3189 -1 x3190 -1 x3191 -1 x3192 -1 x3193 -1 x3194 -1 x3195 -1 x3196 -1 x3197 -1 x3198 -1 x3199 -1 x3200 >= -1 ;+-1 x3201 -1 x3202 -1 x3203 -1 x3204 -1 x3205 -1 x3206 -1 x3207 -1 x3208 -1 x3209 -1 x3210 -1 x3211 -1 x3212 -1 x3213 -1 x3214 -1 x3215 -1 x3216 -1 x3217 -1 x3218 -1 x3219 -1 x3220 -1 x3221 -1 x3222 -1 x3223 -1 x3224 -1 x3225 -1 x3226 -1 x3227 -1 x3228 -1 x3229 -1 x3230 -1 x3231 -1 x3232 -1 x3233 -1 x3234 -1 x3235 -1 x3236 -1 x3237 -1 x3238 -1 x3239 -1 x3240 -1 x3241 -1 x3242 -1 x3243 -1 x3244 -1 x3245 -1 x3246 -1 x3247 -1 x3248 -1 x3249 -1 x3250 -1 x3251 -1 x3252 -1 x3253 -1 x3254 -1 x3255 -1 x3256 -1 x3257 -1 x3258 -1 x3259 -1 x3260 -1 x3261 -1 x3262 -1 x3263 -1 x3264 -1 x3265 -1 x3266 -1 x3267 -1 x3268 -1 x3269 -1 x3270 -1 x3271 -1 x3272 -1 x3273 -1 x3274 -1 x3275 -1 x3276 -1 x3277 -1 x3278 -1 x3279 -1 x3280 -1 x3281 -1 x3282 -1 x3283 -1 x3284 -1 x3285 -1 x3286 -1 x3287 -1 x3288 -1 x3289 -1 x3290 -1 x3291 -1 x3292 -1 x3293 -1 x3294 -1 x3295 -1 x3296 -1 x3297 -1 x3298 -1 x3299 -1 x3300 -1 x3301 -1 x3302 -1 x3303 -1 x3304 -1 x3305 -1 x3306 -1 x3307 -1 x3308 -1 x3309 -1 x3310 -1 x3311 -1 x3312 -1 x3313 -1 x3314 -1 x3315 -1 x3316 -1 x3317 -1 x3318 -1 x3319 -1 x3320 -1 x3321 -1 x3322 -1 x3323 -1 x3324 -1 x3325 -1 x3326 -1 x3327 -1 x3328 >= -1 ;+-1 x3329 -1 x3330 -1 x3331 -1 x3332 -1 x3333 -1 x3334 -1 x3335 -1 x3336 -1 x3337 -1 x3338 -1 x3339 -1 x3340 -1 x3341 -1 x3342 -1 x3343 -1 x3344 -1 x3345 -1 x3346 -1 x3347 -1 x3348 -1 x3349 -1 x3350 -1 x3351 -1 x3352 -1 x3353 -1 x3354 -1 x3355 -1 x3356 -1 x3357 -1 x3358 -1 x3359 -1 x3360 -1 x3361 -1 x3362 -1 x3363 -1 x3364 -1 x3365 -1 x3366 -1 x3367 -1 x3368 -1 x3369 -1 x3370 -1 x3371 -1 x3372 -1 x3373 -1 x3374 -1 x3375 -1 x3376 -1 x3377 -1 x3378 -1 x3379 -1 x3380 -1 x3381 -1 x3382 -1 x3383 -1 x3384 -1 x3385 -1 x3386 -1 x3387 -1 x3388 -1 x3389 -1 x3390 -1 x3391 -1 x3392 -1 x3393 -1 x3394 -1 x3395 -1 x3396 -1 x3397 -1 x3398 -1 x3399 -1 x3400 -1 x3401 -1 x3402 -1 x3403 -1 x3404 -1 x3405 -1 x3406 -1 x3407 -1 x3408 -1 x3409 -1 x3410 -1 x3411 -1 x3412 -1 x3413 -1 x3414 -1 x3415 -1 x3416 -1 x3417 -1 x3418 -1 x3419 -1 x3420 -1 x3421 -1 x3422 -1 x3423 -1 x3424 -1 x3425 -1 x3426 -1 x3427 -1 x3428 -1 x3429 -1 x3430 -1 x3431 -1 x3432 -1 x3433 -1 x3434 -1 x3435 -1 x3436 -1 x3437 -1 x3438 -1 x3439 -1 x3440 -1 x3441 -1 x3442 -1 x3443 -1 x3444 -1 x3445 -1 x3446 -1 x3447 -1 x3448 -1 x3449 -1 x3450 -1 x3451 -1 x3452 -1 x3453 -1 x3454 -1 x3455 -1 x3456 >= -1 ;+-1 x3457 -1 x3458 -1 x3459 -1 x3460 -1 x3461 -1 x3462 -1 x3463 -1 x3464 -1 x3465 -1 x3466 -1 x3467 -1 x3468 -1 x3469 -1 x3470 -1 x3471 -1 x3472 -1 x3473 -1 x3474 -1 x3475 -1 x3476 -1 x3477 -1 x3478 -1 x3479 -1 x3480 -1 x3481 -1 x3482 -1 x3483 -1 x3484 -1 x3485 -1 x3486 -1 x3487 -1 x3488 -1 x3489 -1 x3490 -1 x3491 -1 x3492 -1 x3493 -1 x3494 -1 x3495 -1 x3496 -1 x3497 -1 x3498 -1 x3499 -1 x3500 -1 x3501 -1 x3502 -1 x3503 -1 x3504 -1 x3505 -1 x3506 -1 x3507 -1 x3508 -1 x3509 -1 x3510 -1 x3511 -1 x3512 -1 x3513 -1 x3514 -1 x3515 -1 x3516 -1 x3517 -1 x3518 -1 x3519 -1 x3520 -1 x3521 -1 x3522 -1 x3523 -1 x3524 -1 x3525 -1 x3526 -1 x3527 -1 x3528 -1 x3529 -1 x3530 -1 x3531 -1 x3532 -1 x3533 -1 x3534 -1 x3535 -1 x3536 -1 x3537 -1 x3538 -1 x3539 -1 x3540 -1 x3541 -1 x3542 -1 x3543 -1 x3544 -1 x3545 -1 x3546 -1 x3547 -1 x3548 -1 x3549 -1 x3550 -1 x3551 -1 x3552 -1 x3553 -1 x3554 -1 x3555 -1 x3556 -1 x3557 -1 x3558 -1 x3559 -1 x3560 -1 x3561 -1 x3562 -1 x3563 -1 x3564 -1 x3565 -1 x3566 -1 x3567 -1 x3568 -1 x3569 -1 x3570 -1 x3571 -1 x3572 -1 x3573 -1 x3574 -1 x3575 -1 x3576 -1 x3577 -1 x3578 -1 x3579 -1 x3580 -1 x3581 -1 x3582 -1 x3583 -1 x3584 >= -1 ;+-1 x3585 -1 x3586 -1 x3587 -1 x3588 -1 x3589 -1 x3590 -1 x3591 -1 x3592 -1 x3593 -1 x3594 -1 x3595 -1 x3596 -1 x3597 -1 x3598 -1 x3599 -1 x3600 -1 x3601 -1 x3602 -1 x3603 -1 x3604 -1 x3605 -1 x3606 -1 x3607 -1 x3608 -1 x3609 -1 x3610 -1 x3611 -1 x3612 -1 x3613 -1 x3614 -1 x3615 -1 x3616 -1 x3617 -1 x3618 -1 x3619 -1 x3620 -1 x3621 -1 x3622 -1 x3623 -1 x3624 -1 x3625 -1 x3626 -1 x3627 -1 x3628 -1 x3629 -1 x3630 -1 x3631 -1 x3632 -1 x3633 -1 x3634 -1 x3635 -1 x3636 -1 x3637 -1 x3638 -1 x3639 -1 x3640 -1 x3641 -1 x3642 -1 x3643 -1 x3644 -1 x3645 -1 x3646 -1 x3647 -1 x3648 -1 x3649 -1 x3650 -1 x3651 -1 x3652 -1 x3653 -1 x3654 -1 x3655 -1 x3656 -1 x3657 -1 x3658 -1 x3659 -1 x3660 -1 x3661 -1 x3662 -1 x3663 -1 x3664 -1 x3665 -1 x3666 -1 x3667 -1 x3668 -1 x3669 -1 x3670 -1 x3671 -1 x3672 -1 x3673 -1 x3674 -1 x3675 -1 x3676 -1 x3677 -1 x3678 -1 x3679 -1 x3680 -1 x3681 -1 x3682 -1 x3683 -1 x3684 -1 x3685 -1 x3686 -1 x3687 -1 x3688 -1 x3689 -1 x3690 -1 x3691 -1 x3692 -1 x3693 -1 x3694 -1 x3695 -1 x3696 -1 x3697 -1 x3698 -1 x3699 -1 x3700 -1 x3701 -1 x3702 -1 x3703 -1 x3704 -1 x3705 -1 x3706 -1 x3707 -1 x3708 -1 x3709 -1 x3710 -1 x3711 -1 x3712 >= -1 ;+-1 x3713 -1 x3714 -1 x3715 -1 x3716 -1 x3717 -1 x3718 -1 x3719 -1 x3720 -1 x3721 -1 x3722 -1 x3723 -1 x3724 -1 x3725 -1 x3726 -1 x3727 -1 x3728 -1 x3729 -1 x3730 -1 x3731 -1 x3732 -1 x3733 -1 x3734 -1 x3735 -1 x3736 -1 x3737 -1 x3738 -1 x3739 -1 x3740 -1 x3741 -1 x3742 -1 x3743 -1 x3744 -1 x3745 -1 x3746 -1 x3747 -1 x3748 -1 x3749 -1 x3750 -1 x3751 -1 x3752 -1 x3753 -1 x3754 -1 x3755 -1 x3756 -1 x3757 -1 x3758 -1 x3759 -1 x3760 -1 x3761 -1 x3762 -1 x3763 -1 x3764 -1 x3765 -1 x3766 -1 x3767 -1 x3768 -1 x3769 -1 x3770 -1 x3771 -1 x3772 -1 x3773 -1 x3774 -1 x3775 -1 x3776 -1 x3777 -1 x3778 -1 x3779 -1 x3780 -1 x3781 -1 x3782 -1 x3783 -1 x3784 -1 x3785 -1 x3786 -1 x3787 -1 x3788 -1 x3789 -1 x3790 -1 x3791 -1 x3792 -1 x3793 -1 x3794 -1 x3795 -1 x3796 -1 x3797 -1 x3798 -1 x3799 -1 x3800 -1 x3801 -1 x3802 -1 x3803 -1 x3804 -1 x3805 -1 x3806 -1 x3807 -1 x3808 -1 x3809 -1 x3810 -1 x3811 -1 x3812 -1 x3813 -1 x3814 -1 x3815 -1 x3816 -1 x3817 -1 x3818 -1 x3819 -1 x3820 -1 x3821 -1 x3822 -1 x3823 -1 x3824 -1 x3825 -1 x3826 -1 x3827 -1 x3828 -1 x3829 -1 x3830 -1 x3831 -1 x3832 -1 x3833 -1 x3834 -1 x3835 -1 x3836 -1 x3837 -1 x3838 -1 x3839 -1 x3840 >= -1 ;+-1 x3841 -1 x3842 -1 x3843 -1 x3844 -1 x3845 -1 x3846 -1 x3847 -1 x3848 -1 x3849 -1 x3850 -1 x3851 -1 x3852 -1 x3853 -1 x3854 -1 x3855 -1 x3856 -1 x3857 -1 x3858 -1 x3859 -1 x3860 -1 x3861 -1 x3862 -1 x3863 -1 x3864 -1 x3865 -1 x3866 -1 x3867 -1 x3868 -1 x3869 -1 x3870 -1 x3871 -1 x3872 -1 x3873 -1 x3874 -1 x3875 -1 x3876 -1 x3877 -1 x3878 -1 x3879 -1 x3880 -1 x3881 -1 x3882 -1 x3883 -1 x3884 -1 x3885 -1 x3886 -1 x3887 -1 x3888 -1 x3889 -1 x3890 -1 x3891 -1 x3892 -1 x3893 -1 x3894 -1 x3895 -1 x3896 -1 x3897 -1 x3898 -1 x3899 -1 x3900 -1 x3901 -1 x3902 -1 x3903 -1 x3904 -1 x3905 -1 x3906 -1 x3907 -1 x3908 -1 x3909 -1 x3910 -1 x3911 -1 x3912 -1 x3913 -1 x3914 -1 x3915 -1 x3916 -1 x3917 -1 x3918 -1 x3919 -1 x3920 -1 x3921 -1 x3922 -1 x3923 -1 x3924 -1 x3925 -1 x3926 -1 x3927 -1 x3928 -1 x3929 -1 x3930 -1 x3931 -1 x3932 -1 x3933 -1 x3934 -1 x3935 -1 x3936 -1 x3937 -1 x3938 -1 x3939 -1 x3940 -1 x3941 -1 x3942 -1 x3943 -1 x3944 -1 x3945 -1 x3946 -1 x3947 -1 x3948 -1 x3949 -1 x3950 -1 x3951 -1 x3952 -1 x3953 -1 x3954 -1 x3955 -1 x3956 -1 x3957 -1 x3958 -1 x3959 -1 x3960 -1 x3961 -1 x3962 -1 x3963 -1 x3964 -1 x3965 -1 x3966 -1 x3967 -1 x3968 >= -1 ;+-1 x3969 -1 x3970 -1 x3971 -1 x3972 -1 x3973 -1 x3974 -1 x3975 -1 x3976 -1 x3977 -1 x3978 -1 x3979 -1 x3980 -1 x3981 -1 x3982 -1 x3983 -1 x3984 -1 x3985 -1 x3986 -1 x3987 -1 x3988 -1 x3989 -1 x3990 -1 x3991 -1 x3992 -1 x3993 -1 x3994 -1 x3995 -1 x3996 -1 x3997 -1 x3998 -1 x3999 -1 x4000 -1 x4001 -1 x4002 -1 x4003 -1 x4004 -1 x4005 -1 x4006 -1 x4007 -1 x4008 -1 x4009 -1 x4010 -1 x4011 -1 x4012 -1 x4013 -1 x4014 -1 x4015 -1 x4016 -1 x4017 -1 x4018 -1 x4019 -1 x4020 -1 x4021 -1 x4022 -1 x4023 -1 x4024 -1 x4025 -1 x4026 -1 x4027 -1 x4028 -1 x4029 -1 x4030 -1 x4031 -1 x4032 -1 x4033 -1 x4034 -1 x4035 -1 x4036 -1 x4037 -1 x4038 -1 x4039 -1 x4040 -1 x4041 -1 x4042 -1 x4043 -1 x4044 -1 x4045 -1 x4046 -1 x4047 -1 x4048 -1 x4049 -1 x4050 -1 x4051 -1 x4052 -1 x4053 -1 x4054 -1 x4055 -1 x4056 -1 x4057 -1 x4058 -1 x4059 -1 x4060 -1 x4061 -1 x4062 -1 x4063 -1 x4064 -1 x4065 -1 x4066 -1 x4067 -1 x4068 -1 x4069 -1 x4070 -1 x4071 -1 x4072 -1 x4073 -1 x4074 -1 x4075 -1 x4076 -1 x4077 -1 x4078 -1 x4079 -1 x4080 -1 x4081 -1 x4082 -1 x4083 -1 x4084 -1 x4085 -1 x4086 -1 x4087 -1 x4088 -1 x4089 -1 x4090 -1 x4091 -1 x4092 -1 x4093 -1 x4094 -1 x4095 -1 x4096 >= -1 ;+-1 x4097 -1 x4098 -1 x4099 -1 x4100 -1 x4101 -1 x4102 -1 x4103 -1 x4104 -1 x4105 -1 x4106 -1 x4107 -1 x4108 -1 x4109 -1 x4110 -1 x4111 -1 x4112 -1 x4113 -1 x4114 -1 x4115 -1 x4116 -1 x4117 -1 x4118 -1 x4119 -1 x4120 -1 x4121 -1 x4122 -1 x4123 -1 x4124 -1 x4125 -1 x4126 -1 x4127 -1 x4128 -1 x4129 -1 x4130 -1 x4131 -1 x4132 -1 x4133 -1 x4134 -1 x4135 -1 x4136 -1 x4137 -1 x4138 -1 x4139 -1 x4140 -1 x4141 -1 x4142 -1 x4143 -1 x4144 -1 x4145 -1 x4146 -1 x4147 -1 x4148 -1 x4149 -1 x4150 -1 x4151 -1 x4152 -1 x4153 -1 x4154 -1 x4155 -1 x4156 -1 x4157 -1 x4158 -1 x4159 -1 x4160 -1 x4161 -1 x4162 -1 x4163 -1 x4164 -1 x4165 -1 x4166 -1 x4167 -1 x4168 -1 x4169 -1 x4170 -1 x4171 -1 x4172 -1 x4173 -1 x4174 -1 x4175 -1 x4176 -1 x4177 -1 x4178 -1 x4179 -1 x4180 -1 x4181 -1 x4182 -1 x4183 -1 x4184 -1 x4185 -1 x4186 -1 x4187 -1 x4188 -1 x4189 -1 x4190 -1 x4191 -1 x4192 -1 x4193 -1 x4194 -1 x4195 -1 x4196 -1 x4197 -1 x4198 -1 x4199 -1 x4200 -1 x4201 -1 x4202 -1 x4203 -1 x4204 -1 x4205 -1 x4206 -1 x4207 -1 x4208 -1 x4209 -1 x4210 -1 x4211 -1 x4212 -1 x4213 -1 x4214 -1 x4215 -1 x4216 -1 x4217 -1 x4218 -1 x4219 -1 x4220 -1 x4221 -1 x4222 -1 x4223 -1 x4224 >= -1 ;+-1 x4225 -1 x4226 -1 x4227 -1 x4228 -1 x4229 -1 x4230 -1 x4231 -1 x4232 -1 x4233 -1 x4234 -1 x4235 -1 x4236 -1 x4237 -1 x4238 -1 x4239 -1 x4240 -1 x4241 -1 x4242 -1 x4243 -1 x4244 -1 x4245 -1 x4246 -1 x4247 -1 x4248 -1 x4249 -1 x4250 -1 x4251 -1 x4252 -1 x4253 -1 x4254 -1 x4255 -1 x4256 -1 x4257 -1 x4258 -1 x4259 -1 x4260 -1 x4261 -1 x4262 -1 x4263 -1 x4264 -1 x4265 -1 x4266 -1 x4267 -1 x4268 -1 x4269 -1 x4270 -1 x4271 -1 x4272 -1 x4273 -1 x4274 -1 x4275 -1 x4276 -1 x4277 -1 x4278 -1 x4279 -1 x4280 -1 x4281 -1 x4282 -1 x4283 -1 x4284 -1 x4285 -1 x4286 -1 x4287 -1 x4288 -1 x4289 -1 x4290 -1 x4291 -1 x4292 -1 x4293 -1 x4294 -1 x4295 -1 x4296 -1 x4297 -1 x4298 -1 x4299 -1 x4300 -1 x4301 -1 x4302 -1 x4303 -1 x4304 -1 x4305 -1 x4306 -1 x4307 -1 x4308 -1 x4309 -1 x4310 -1 x4311 -1 x4312 -1 x4313 -1 x4314 -1 x4315 -1 x4316 -1 x4317 -1 x4318 -1 x4319 -1 x4320 -1 x4321 -1 x4322 -1 x4323 -1 x4324 -1 x4325 -1 x4326 -1 x4327 -1 x4328 -1 x4329 -1 x4330 -1 x4331 -1 x4332 -1 x4333 -1 x4334 -1 x4335 -1 x4336 -1 x4337 -1 x4338 -1 x4339 -1 x4340 -1 x4341 -1 x4342 -1 x4343 -1 x4344 -1 x4345 -1 x4346 -1 x4347 -1 x4348 -1 x4349 -1 x4350 -1 x4351 -1 x4352 >= -1 ;+-1 x4353 -1 x4354 -1 x4355 -1 x4356 -1 x4357 -1 x4358 -1 x4359 -1 x4360 -1 x4361 -1 x4362 -1 x4363 -1 x4364 -1 x4365 -1 x4366 -1 x4367 -1 x4368 -1 x4369 -1 x4370 -1 x4371 -1 x4372 -1 x4373 -1 x4374 -1 x4375 -1 x4376 -1 x4377 -1 x4378 -1 x4379 -1 x4380 -1 x4381 -1 x4382 -1 x4383 -1 x4384 -1 x4385 -1 x4386 -1 x4387 -1 x4388 -1 x4389 -1 x4390 -1 x4391 -1 x4392 -1 x4393 -1 x4394 -1 x4395 -1 x4396 -1 x4397 -1 x4398 -1 x4399 -1 x4400 -1 x4401 -1 x4402 -1 x4403 -1 x4404 -1 x4405 -1 x4406 -1 x4407 -1 x4408 -1 x4409 -1 x4410 -1 x4411 -1 x4412 -1 x4413 -1 x4414 -1 x4415 -1 x4416 -1 x4417 -1 x4418 -1 x4419 -1 x4420 -1 x4421 -1 x4422 -1 x4423 -1 x4424 -1 x4425 -1 x4426 -1 x4427 -1 x4428 -1 x4429 -1 x4430 -1 x4431 -1 x4432 -1 x4433 -1 x4434 -1 x4435 -1 x4436 -1 x4437 -1 x4438 -1 x4439 -1 x4440 -1 x4441 -1 x4442 -1 x4443 -1 x4444 -1 x4445 -1 x4446 -1 x4447 -1 x4448 -1 x4449 -1 x4450 -1 x4451 -1 x4452 -1 x4453 -1 x4454 -1 x4455 -1 x4456 -1 x4457 -1 x4458 -1 x4459 -1 x4460 -1 x4461 -1 x4462 -1 x4463 -1 x4464 -1 x4465 -1 x4466 -1 x4467 -1 x4468 -1 x4469 -1 x4470 -1 x4471 -1 x4472 -1 x4473 -1 x4474 -1 x4475 -1 x4476 -1 x4477 -1 x4478 -1 x4479 -1 x4480 >= -1 ;+-1 x4481 -1 x4482 -1 x4483 -1 x4484 -1 x4485 -1 x4486 -1 x4487 -1 x4488 -1 x4489 -1 x4490 -1 x4491 -1 x4492 -1 x4493 -1 x4494 -1 x4495 -1 x4496 -1 x4497 -1 x4498 -1 x4499 -1 x4500 -1 x4501 -1 x4502 -1 x4503 -1 x4504 -1 x4505 -1 x4506 -1 x4507 -1 x4508 -1 x4509 -1 x4510 -1 x4511 -1 x4512 -1 x4513 -1 x4514 -1 x4515 -1 x4516 -1 x4517 -1 x4518 -1 x4519 -1 x4520 -1 x4521 -1 x4522 -1 x4523 -1 x4524 -1 x4525 -1 x4526 -1 x4527 -1 x4528 -1 x4529 -1 x4530 -1 x4531 -1 x4532 -1 x4533 -1 x4534 -1 x4535 -1 x4536 -1 x4537 -1 x4538 -1 x4539 -1 x4540 -1 x4541 -1 x4542 -1 x4543 -1 x4544 -1 x4545 -1 x4546 -1 x4547 -1 x4548 -1 x4549 -1 x4550 -1 x4551 -1 x4552 -1 x4553 -1 x4554 -1 x4555 -1 x4556 -1 x4557 -1 x4558 -1 x4559 -1 x4560 -1 x4561 -1 x4562 -1 x4563 -1 x4564 -1 x4565 -1 x4566 -1 x4567 -1 x4568 -1 x4569 -1 x4570 -1 x4571 -1 x4572 -1 x4573 -1 x4574 -1 x4575 -1 x4576 -1 x4577 -1 x4578 -1 x4579 -1 x4580 -1 x4581 -1 x4582 -1 x4583 -1 x4584 -1 x4585 -1 x4586 -1 x4587 -1 x4588 -1 x4589 -1 x4590 -1 x4591 -1 x4592 -1 x4593 -1 x4594 -1 x4595 -1 x4596 -1 x4597 -1 x4598 -1 x4599 -1 x4600 -1 x4601 -1 x4602 -1 x4603 -1 x4604 -1 x4605 -1 x4606 -1 x4607 -1 x4608 >= -1 ;+-1 x4609 -1 x4610 -1 x4611 -1 x4612 -1 x4613 -1 x4614 -1 x4615 -1 x4616 -1 x4617 -1 x4618 -1 x4619 -1 x4620 -1 x4621 -1 x4622 -1 x4623 -1 x4624 -1 x4625 -1 x4626 -1 x4627 -1 x4628 -1 x4629 -1 x4630 -1 x4631 -1 x4632 -1 x4633 -1 x4634 -1 x4635 -1 x4636 -1 x4637 -1 x4638 -1 x4639 -1 x4640 -1 x4641 -1 x4642 -1 x4643 -1 x4644 -1 x4645 -1 x4646 -1 x4647 -1 x4648 -1 x4649 -1 x4650 -1 x4651 -1 x4652 -1 x4653 -1 x4654 -1 x4655 -1 x4656 -1 x4657 -1 x4658 -1 x4659 -1 x4660 -1 x4661 -1 x4662 -1 x4663 -1 x4664 -1 x4665 -1 x4666 -1 x4667 -1 x4668 -1 x4669 -1 x4670 -1 x4671 -1 x4672 -1 x4673 -1 x4674 -1 x4675 -1 x4676 -1 x4677 -1 x4678 -1 x4679 -1 x4680 -1 x4681 -1 x4682 -1 x4683 -1 x4684 -1 x4685 -1 x4686 -1 x4687 -1 x4688 -1 x4689 -1 x4690 -1 x4691 -1 x4692 -1 x4693 -1 x4694 -1 x4695 -1 x4696 -1 x4697 -1 x4698 -1 x4699 -1 x4700 -1 x4701 -1 x4702 -1 x4703 -1 x4704 -1 x4705 -1 x4706 -1 x4707 -1 x4708 -1 x4709 -1 x4710 -1 x4711 -1 x4712 -1 x4713 -1 x4714 -1 x4715 -1 x4716 -1 x4717 -1 x4718 -1 x4719 -1 x4720 -1 x4721 -1 x4722 -1 x4723 -1 x4724 -1 x4725 -1 x4726 -1 x4727 -1 x4728 -1 x4729 -1 x4730 -1 x4731 -1 x4732 -1 x4733 -1 x4734 -1 x4735 -1 x4736 >= -1 ;+-1 x4737 -1 x4738 -1 x4739 -1 x4740 -1 x4741 -1 x4742 -1 x4743 -1 x4744 -1 x4745 -1 x4746 -1 x4747 -1 x4748 -1 x4749 -1 x4750 -1 x4751 -1 x4752 -1 x4753 -1 x4754 -1 x4755 -1 x4756 -1 x4757 -1 x4758 -1 x4759 -1 x4760 -1 x4761 -1 x4762 -1 x4763 -1 x4764 -1 x4765 -1 x4766 -1 x4767 -1 x4768 -1 x4769 -1 x4770 -1 x4771 -1 x4772 -1 x4773 -1 x4774 -1 x4775 -1 x4776 -1 x4777 -1 x4778 -1 x4779 -1 x4780 -1 x4781 -1 x4782 -1 x4783 -1 x4784 -1 x4785 -1 x4786 -1 x4787 -1 x4788 -1 x4789 -1 x4790 -1 x4791 -1 x4792 -1 x4793 -1 x4794 -1 x4795 -1 x4796 -1 x4797 -1 x4798 -1 x4799 -1 x4800 -1 x4801 -1 x4802 -1 x4803 -1 x4804 -1 x4805 -1 x4806 -1 x4807 -1 x4808 -1 x4809 -1 x4810 -1 x4811 -1 x4812 -1 x4813 -1 x4814 -1 x4815 -1 x4816 -1 x4817 -1 x4818 -1 x4819 -1 x4820 -1 x4821 -1 x4822 -1 x4823 -1 x4824 -1 x4825 -1 x4826 -1 x4827 -1 x4828 -1 x4829 -1 x4830 -1 x4831 -1 x4832 -1 x4833 -1 x4834 -1 x4835 -1 x4836 -1 x4837 -1 x4838 -1 x4839 -1 x4840 -1 x4841 -1 x4842 -1 x4843 -1 x4844 -1 x4845 -1 x4846 -1 x4847 -1 x4848 -1 x4849 -1 x4850 -1 x4851 -1 x4852 -1 x4853 -1 x4854 -1 x4855 -1 x4856 -1 x4857 -1 x4858 -1 x4859 -1 x4860 -1 x4861 -1 x4862 -1 x4863 -1 x4864 >= -1 ;+-1 x4865 -1 x4866 -1 x4867 -1 x4868 -1 x4869 -1 x4870 -1 x4871 -1 x4872 -1 x4873 -1 x4874 -1 x4875 -1 x4876 -1 x4877 -1 x4878 -1 x4879 -1 x4880 -1 x4881 -1 x4882 -1 x4883 -1 x4884 -1 x4885 -1 x4886 -1 x4887 -1 x4888 -1 x4889 -1 x4890 -1 x4891 -1 x4892 -1 x4893 -1 x4894 -1 x4895 -1 x4896 -1 x4897 -1 x4898 -1 x4899 -1 x4900 -1 x4901 -1 x4902 -1 x4903 -1 x4904 -1 x4905 -1 x4906 -1 x4907 -1 x4908 -1 x4909 -1 x4910 -1 x4911 -1 x4912 -1 x4913 -1 x4914 -1 x4915 -1 x4916 -1 x4917 -1 x4918 -1 x4919 -1 x4920 -1 x4921 -1 x4922 -1 x4923 -1 x4924 -1 x4925 -1 x4926 -1 x4927 -1 x4928 -1 x4929 -1 x4930 -1 x4931 -1 x4932 -1 x4933 -1 x4934 -1 x4935 -1 x4936 -1 x4937 -1 x4938 -1 x4939 -1 x4940 -1 x4941 -1 x4942 -1 x4943 -1 x4944 -1 x4945 -1 x4946 -1 x4947 -1 x4948 -1 x4949 -1 x4950 -1 x4951 -1 x4952 -1 x4953 -1 x4954 -1 x4955 -1 x4956 -1 x4957 -1 x4958 -1 x4959 -1 x4960 -1 x4961 -1 x4962 -1 x4963 -1 x4964 -1 x4965 -1 x4966 -1 x4967 -1 x4968 -1 x4969 -1 x4970 -1 x4971 -1 x4972 -1 x4973 -1 x4974 -1 x4975 -1 x4976 -1 x4977 -1 x4978 -1 x4979 -1 x4980 -1 x4981 -1 x4982 -1 x4983 -1 x4984 -1 x4985 -1 x4986 -1 x4987 -1 x4988 -1 x4989 -1 x4990 -1 x4991 -1 x4992 >= -1 ;+-1 x4993 -1 x4994 -1 x4995 -1 x4996 -1 x4997 -1 x4998 -1 x4999 -1 x5000 -1 x5001 -1 x5002 -1 x5003 -1 x5004 -1 x5005 -1 x5006 -1 x5007 -1 x5008 -1 x5009 -1 x5010 -1 x5011 -1 x5012 -1 x5013 -1 x5014 -1 x5015 -1 x5016 -1 x5017 -1 x5018 -1 x5019 -1 x5020 -1 x5021 -1 x5022 -1 x5023 -1 x5024 -1 x5025 -1 x5026 -1 x5027 -1 x5028 -1 x5029 -1 x5030 -1 x5031 -1 x5032 -1 x5033 -1 x5034 -1 x5035 -1 x5036 -1 x5037 -1 x5038 -1 x5039 -1 x5040 -1 x5041 -1 x5042 -1 x5043 -1 x5044 -1 x5045 -1 x5046 -1 x5047 -1 x5048 -1 x5049 -1 x5050 -1 x5051 -1 x5052 -1 x5053 -1 x5054 -1 x5055 -1 x5056 -1 x5057 -1 x5058 -1 x5059 -1 x5060 -1 x5061 -1 x5062 -1 x5063 -1 x5064 -1 x5065 -1 x5066 -1 x5067 -1 x5068 -1 x5069 -1 x5070 -1 x5071 -1 x5072 -1 x5073 -1 x5074 -1 x5075 -1 x5076 -1 x5077 -1 x5078 -1 x5079 -1 x5080 -1 x5081 -1 x5082 -1 x5083 -1 x5084 -1 x5085 -1 x5086 -1 x5087 -1 x5088 -1 x5089 -1 x5090 -1 x5091 -1 x5092 -1 x5093 -1 x5094 -1 x5095 -1 x5096 -1 x5097 -1 x5098 -1 x5099 -1 x5100 -1 x5101 -1 x5102 -1 x5103 -1 x5104 -1 x5105 -1 x5106 -1 x5107 -1 x5108 -1 x5109 -1 x5110 -1 x5111 -1 x5112 -1 x5113 -1 x5114 -1 x5115 -1 x5116 -1 x5117 -1 x5118 -1 x5119 -1 x5120 >= -1 ;+-1 x5121 -1 x5122 -1 x5123 -1 x5124 -1 x5125 -1 x5126 -1 x5127 -1 x5128 -1 x5129 -1 x5130 -1 x5131 -1 x5132 -1 x5133 -1 x5134 -1 x5135 -1 x5136 -1 x5137 -1 x5138 -1 x5139 -1 x5140 -1 x5141 -1 x5142 -1 x5143 -1 x5144 -1 x5145 -1 x5146 -1 x5147 -1 x5148 -1 x5149 -1 x5150 -1 x5151 -1 x5152 -1 x5153 -1 x5154 -1 x5155 -1 x5156 -1 x5157 -1 x5158 -1 x5159 -1 x5160 -1 x5161 -1 x5162 -1 x5163 -1 x5164 -1 x5165 -1 x5166 -1 x5167 -1 x5168 -1 x5169 -1 x5170 -1 x5171 -1 x5172 -1 x5173 -1 x5174 -1 x5175 -1 x5176 -1 x5177 -1 x5178 -1 x5179 -1 x5180 -1 x5181 -1 x5182 -1 x5183 -1 x5184 -1 x5185 -1 x5186 -1 x5187 -1 x5188 -1 x5189 -1 x5190 -1 x5191 -1 x5192 -1 x5193 -1 x5194 -1 x5195 -1 x5196 -1 x5197 -1 x5198 -1 x5199 -1 x5200 -1 x5201 -1 x5202 -1 x5203 -1 x5204 -1 x5205 -1 x5206 -1 x5207 -1 x5208 -1 x5209 -1 x5210 -1 x5211 -1 x5212 -1 x5213 -1 x5214 -1 x5215 -1 x5216 -1 x5217 -1 x5218 -1 x5219 -1 x5220 -1 x5221 -1 x5222 -1 x5223 -1 x5224 -1 x5225 -1 x5226 -1 x5227 -1 x5228 -1 x5229 -1 x5230 -1 x5231 -1 x5232 -1 x5233 -1 x5234 -1 x5235 -1 x5236 -1 x5237 -1 x5238 -1 x5239 -1 x5240 -1 x5241 -1 x5242 -1 x5243 -1 x5244 -1 x5245 -1 x5246 -1 x5247 -1 x5248 >= -1 ;+-1 x5249 -1 x5250 -1 x5251 -1 x5252 -1 x5253 -1 x5254 -1 x5255 -1 x5256 -1 x5257 -1 x5258 -1 x5259 -1 x5260 -1 x5261 -1 x5262 -1 x5263 -1 x5264 -1 x5265 -1 x5266 -1 x5267 -1 x5268 -1 x5269 -1 x5270 -1 x5271 -1 x5272 -1 x5273 -1 x5274 -1 x5275 -1 x5276 -1 x5277 -1 x5278 -1 x5279 -1 x5280 -1 x5281 -1 x5282 -1 x5283 -1 x5284 -1 x5285 -1 x5286 -1 x5287 -1 x5288 -1 x5289 -1 x5290 -1 x5291 -1 x5292 -1 x5293 -1 x5294 -1 x5295 -1 x5296 -1 x5297 -1 x5298 -1 x5299 -1 x5300 -1 x5301 -1 x5302 -1 x5303 -1 x5304 -1 x5305 -1 x5306 -1 x5307 -1 x5308 -1 x5309 -1 x5310 -1 x5311 -1 x5312 -1 x5313 -1 x5314 -1 x5315 -1 x5316 -1 x5317 -1 x5318 -1 x5319 -1 x5320 -1 x5321 -1 x5322 -1 x5323 -1 x5324 -1 x5325 -1 x5326 -1 x5327 -1 x5328 -1 x5329 -1 x5330 -1 x5331 -1 x5332 -1 x5333 -1 x5334 -1 x5335 -1 x5336 -1 x5337 -1 x5338 -1 x5339 -1 x5340 -1 x5341 -1 x5342 -1 x5343 -1 x5344 -1 x5345 -1 x5346 -1 x5347 -1 x5348 -1 x5349 -1 x5350 -1 x5351 -1 x5352 -1 x5353 -1 x5354 -1 x5355 -1 x5356 -1 x5357 -1 x5358 -1 x5359 -1 x5360 -1 x5361 -1 x5362 -1 x5363 -1 x5364 -1 x5365 -1 x5366 -1 x5367 -1 x5368 -1 x5369 -1 x5370 -1 x5371 -1 x5372 -1 x5373 -1 x5374 -1 x5375 -1 x5376 >= -1 ;+-1 x5377 -1 x5378 -1 x5379 -1 x5380 -1 x5381 -1 x5382 -1 x5383 -1 x5384 -1 x5385 -1 x5386 -1 x5387 -1 x5388 -1 x5389 -1 x5390 -1 x5391 -1 x5392 -1 x5393 -1 x5394 -1 x5395 -1 x5396 -1 x5397 -1 x5398 -1 x5399 -1 x5400 -1 x5401 -1 x5402 -1 x5403 -1 x5404 -1 x5405 -1 x5406 -1 x5407 -1 x5408 -1 x5409 -1 x5410 -1 x5411 -1 x5412 -1 x5413 -1 x5414 -1 x5415 -1 x5416 -1 x5417 -1 x5418 -1 x5419 -1 x5420 -1 x5421 -1 x5422 -1 x5423 -1 x5424 -1 x5425 -1 x5426 -1 x5427 -1 x5428 -1 x5429 -1 x5430 -1 x5431 -1 x5432 -1 x5433 -1 x5434 -1 x5435 -1 x5436 -1 x5437 -1 x5438 -1 x5439 -1 x5440 -1 x5441 -1 x5442 -1 x5443 -1 x5444 -1 x5445 -1 x5446 -1 x5447 -1 x5448 -1 x5449 -1 x5450 -1 x5451 -1 x5452 -1 x5453 -1 x5454 -1 x5455 -1 x5456 -1 x5457 -1 x5458 -1 x5459 -1 x5460 -1 x5461 -1 x5462 -1 x5463 -1 x5464 -1 x5465 -1 x5466 -1 x5467 -1 x5468 -1 x5469 -1 x5470 -1 x5471 -1 x5472 -1 x5473 -1 x5474 -1 x5475 -1 x5476 -1 x5477 -1 x5478 -1 x5479 -1 x5480 -1 x5481 -1 x5482 -1 x5483 -1 x5484 -1 x5485 -1 x5486 -1 x5487 -1 x5488 -1 x5489 -1 x5490 -1 x5491 -1 x5492 -1 x5493 -1 x5494 -1 x5495 -1 x5496 -1 x5497 -1 x5498 -1 x5499 -1 x5500 -1 x5501 -1 x5502 -1 x5503 -1 x5504 >= -1 ;+-1 x5505 -1 x5506 -1 x5507 -1 x5508 -1 x5509 -1 x5510 -1 x5511 -1 x5512 -1 x5513 -1 x5514 -1 x5515 -1 x5516 -1 x5517 -1 x5518 -1 x5519 -1 x5520 -1 x5521 -1 x5522 -1 x5523 -1 x5524 -1 x5525 -1 x5526 -1 x5527 -1 x5528 -1 x5529 -1 x5530 -1 x5531 -1 x5532 -1 x5533 -1 x5534 -1 x5535 -1 x5536 -1 x5537 -1 x5538 -1 x5539 -1 x5540 -1 x5541 -1 x5542 -1 x5543 -1 x5544 -1 x5545 -1 x5546 -1 x5547 -1 x5548 -1 x5549 -1 x5550 -1 x5551 -1 x5552 -1 x5553 -1 x5554 -1 x5555 -1 x5556 -1 x5557 -1 x5558 -1 x5559 -1 x5560 -1 x5561 -1 x5562 -1 x5563 -1 x5564 -1 x5565 -1 x5566 -1 x5567 -1 x5568 -1 x5569 -1 x5570 -1 x5571 -1 x5572 -1 x5573 -1 x5574 -1 x5575 -1 x5576 -1 x5577 -1 x5578 -1 x5579 -1 x5580 -1 x5581 -1 x5582 -1 x5583 -1 x5584 -1 x5585 -1 x5586 -1 x5587 -1 x5588 -1 x5589 -1 x5590 -1 x5591 -1 x5592 -1 x5593 -1 x5594 -1 x5595 -1 x5596 -1 x5597 -1 x5598 -1 x5599 -1 x5600 -1 x5601 -1 x5602 -1 x5603 -1 x5604 -1 x5605 -1 x5606 -1 x5607 -1 x5608 -1 x5609 -1 x5610 -1 x5611 -1 x5612 -1 x5613 -1 x5614 -1 x5615 -1 x5616 -1 x5617 -1 x5618 -1 x5619 -1 x5620 -1 x5621 -1 x5622 -1 x5623 -1 x5624 -1 x5625 -1 x5626 -1 x5627 -1 x5628 -1 x5629 -1 x5630 -1 x5631 -1 x5632 >= -1 ;+-1 x5633 -1 x5634 -1 x5635 -1 x5636 -1 x5637 -1 x5638 -1 x5639 -1 x5640 -1 x5641 -1 x5642 -1 x5643 -1 x5644 -1 x5645 -1 x5646 -1 x5647 -1 x5648 -1 x5649 -1 x5650 -1 x5651 -1 x5652 -1 x5653 -1 x5654 -1 x5655 -1 x5656 -1 x5657 -1 x5658 -1 x5659 -1 x5660 -1 x5661 -1 x5662 -1 x5663 -1 x5664 -1 x5665 -1 x5666 -1 x5667 -1 x5668 -1 x5669 -1 x5670 -1 x5671 -1 x5672 -1 x5673 -1 x5674 -1 x5675 -1 x5676 -1 x5677 -1 x5678 -1 x5679 -1 x5680 -1 x5681 -1 x5682 -1 x5683 -1 x5684 -1 x5685 -1 x5686 -1 x5687 -1 x5688 -1 x5689 -1 x5690 -1 x5691 -1 x5692 -1 x5693 -1 x5694 -1 x5695 -1 x5696 -1 x5697 -1 x5698 -1 x5699 -1 x5700 -1 x5701 -1 x5702 -1 x5703 -1 x5704 -1 x5705 -1 x5706 -1 x5707 -1 x5708 -1 x5709 -1 x5710 -1 x5711 -1 x5712 -1 x5713 -1 x5714 -1 x5715 -1 x5716 -1 x5717 -1 x5718 -1 x5719 -1 x5720 -1 x5721 -1 x5722 -1 x5723 -1 x5724 -1 x5725 -1 x5726 -1 x5727 -1 x5728 -1 x5729 -1 x5730 -1 x5731 -1 x5732 -1 x5733 -1 x5734 -1 x5735 -1 x5736 -1 x5737 -1 x5738 -1 x5739 -1 x5740 -1 x5741 -1 x5742 -1 x5743 -1 x5744 -1 x5745 -1 x5746 -1 x5747 -1 x5748 -1 x5749 -1 x5750 -1 x5751 -1 x5752 -1 x5753 -1 x5754 -1 x5755 -1 x5756 -1 x5757 -1 x5758 -1 x5759 -1 x5760 >= -1 ;+-1 x5761 -1 x5762 -1 x5763 -1 x5764 -1 x5765 -1 x5766 -1 x5767 -1 x5768 -1 x5769 -1 x5770 -1 x5771 -1 x5772 -1 x5773 -1 x5774 -1 x5775 -1 x5776 -1 x5777 -1 x5778 -1 x5779 -1 x5780 -1 x5781 -1 x5782 -1 x5783 -1 x5784 -1 x5785 -1 x5786 -1 x5787 -1 x5788 -1 x5789 -1 x5790 -1 x5791 -1 x5792 -1 x5793 -1 x5794 -1 x5795 -1 x5796 -1 x5797 -1 x5798 -1 x5799 -1 x5800 -1 x5801 -1 x5802 -1 x5803 -1 x5804 -1 x5805 -1 x5806 -1 x5807 -1 x5808 -1 x5809 -1 x5810 -1 x5811 -1 x5812 -1 x5813 -1 x5814 -1 x5815 -1 x5816 -1 x5817 -1 x5818 -1 x5819 -1 x5820 -1 x5821 -1 x5822 -1 x5823 -1 x5824 -1 x5825 -1 x5826 -1 x5827 -1 x5828 -1 x5829 -1 x5830 -1 x5831 -1 x5832 -1 x5833 -1 x5834 -1 x5835 -1 x5836 -1 x5837 -1 x5838 -1 x5839 -1 x5840 -1 x5841 -1 x5842 -1 x5843 -1 x5844 -1 x5845 -1 x5846 -1 x5847 -1 x5848 -1 x5849 -1 x5850 -1 x5851 -1 x5852 -1 x5853 -1 x5854 -1 x5855 -1 x5856 -1 x5857 -1 x5858 -1 x5859 -1 x5860 -1 x5861 -1 x5862 -1 x5863 -1 x5864 -1 x5865 -1 x5866 -1 x5867 -1 x5868 -1 x5869 -1 x5870 -1 x5871 -1 x5872 -1 x5873 -1 x5874 -1 x5875 -1 x5876 -1 x5877 -1 x5878 -1 x5879 -1 x5880 -1 x5881 -1 x5882 -1 x5883 -1 x5884 -1 x5885 -1 x5886 -1 x5887 -1 x5888 >= -1 ;+-1 x5889 -1 x5890 -1 x5891 -1 x5892 -1 x5893 -1 x5894 -1 x5895 -1 x5896 -1 x5897 -1 x5898 -1 x5899 -1 x5900 -1 x5901 -1 x5902 -1 x5903 -1 x5904 -1 x5905 -1 x5906 -1 x5907 -1 x5908 -1 x5909 -1 x5910 -1 x5911 -1 x5912 -1 x5913 -1 x5914 -1 x5915 -1 x5916 -1 x5917 -1 x5918 -1 x5919 -1 x5920 -1 x5921 -1 x5922 -1 x5923 -1 x5924 -1 x5925 -1 x5926 -1 x5927 -1 x5928 -1 x5929 -1 x5930 -1 x5931 -1 x5932 -1 x5933 -1 x5934 -1 x5935 -1 x5936 -1 x5937 -1 x5938 -1 x5939 -1 x5940 -1 x5941 -1 x5942 -1 x5943 -1 x5944 -1 x5945 -1 x5946 -1 x5947 -1 x5948 -1 x5949 -1 x5950 -1 x5951 -1 x5952 -1 x5953 -1 x5954 -1 x5955 -1 x5956 -1 x5957 -1 x5958 -1 x5959 -1 x5960 -1 x5961 -1 x5962 -1 x5963 -1 x5964 -1 x5965 -1 x5966 -1 x5967 -1 x5968 -1 x5969 -1 x5970 -1 x5971 -1 x5972 -1 x5973 -1 x5974 -1 x5975 -1 x5976 -1 x5977 -1 x5978 -1 x5979 -1 x5980 -1 x5981 -1 x5982 -1 x5983 -1 x5984 -1 x5985 -1 x5986 -1 x5987 -1 x5988 -1 x5989 -1 x5990 -1 x5991 -1 x5992 -1 x5993 -1 x5994 -1 x5995 -1 x5996 -1 x5997 -1 x5998 -1 x5999 -1 x6000 -1 x6001 -1 x6002 -1 x6003 -1 x6004 -1 x6005 -1 x6006 -1 x6007 -1 x6008 -1 x6009 -1 x6010 -1 x6011 -1 x6012 -1 x6013 -1 x6014 -1 x6015 -1 x6016 >= -1 ;+-1 x6017 -1 x6018 -1 x6019 -1 x6020 -1 x6021 -1 x6022 -1 x6023 -1 x6024 -1 x6025 -1 x6026 -1 x6027 -1 x6028 -1 x6029 -1 x6030 -1 x6031 -1 x6032 -1 x6033 -1 x6034 -1 x6035 -1 x6036 -1 x6037 -1 x6038 -1 x6039 -1 x6040 -1 x6041 -1 x6042 -1 x6043 -1 x6044 -1 x6045 -1 x6046 -1 x6047 -1 x6048 -1 x6049 -1 x6050 -1 x6051 -1 x6052 -1 x6053 -1 x6054 -1 x6055 -1 x6056 -1 x6057 -1 x6058 -1 x6059 -1 x6060 -1 x6061 -1 x6062 -1 x6063 -1 x6064 -1 x6065 -1 x6066 -1 x6067 -1 x6068 -1 x6069 -1 x6070 -1 x6071 -1 x6072 -1 x6073 -1 x6074 -1 x6075 -1 x6076 -1 x6077 -1 x6078 -1 x6079 -1 x6080 -1 x6081 -1 x6082 -1 x6083 -1 x6084 -1 x6085 -1 x6086 -1 x6087 -1 x6088 -1 x6089 -1 x6090 -1 x6091 -1 x6092 -1 x6093 -1 x6094 -1 x6095 -1 x6096 -1 x6097 -1 x6098 -1 x6099 -1 x6100 -1 x6101 -1 x6102 -1 x6103 -1 x6104 -1 x6105 -1 x6106 -1 x6107 -1 x6108 -1 x6109 -1 x6110 -1 x6111 -1 x6112 -1 x6113 -1 x6114 -1 x6115 -1 x6116 -1 x6117 -1 x6118 -1 x6119 -1 x6120 -1 x6121 -1 x6122 -1 x6123 -1 x6124 -1 x6125 -1 x6126 -1 x6127 -1 x6128 -1 x6129 -1 x6130 -1 x6131 -1 x6132 -1 x6133 -1 x6134 -1 x6135 -1 x6136 -1 x6137 -1 x6138 -1 x6139 -1 x6140 -1 x6141 -1 x6142 -1 x6143 -1 x6144 >= -1 ;+-1 x6145 -1 x6146 -1 x6147 -1 x6148 -1 x6149 -1 x6150 -1 x6151 -1 x6152 -1 x6153 -1 x6154 -1 x6155 -1 x6156 -1 x6157 -1 x6158 -1 x6159 -1 x6160 -1 x6161 -1 x6162 -1 x6163 -1 x6164 -1 x6165 -1 x6166 -1 x6167 -1 x6168 -1 x6169 -1 x6170 -1 x6171 -1 x6172 -1 x6173 -1 x6174 -1 x6175 -1 x6176 -1 x6177 -1 x6178 -1 x6179 -1 x6180 -1 x6181 -1 x6182 -1 x6183 -1 x6184 -1 x6185 -1 x6186 -1 x6187 -1 x6188 -1 x6189 -1 x6190 -1 x6191 -1 x6192 -1 x6193 -1 x6194 -1 x6195 -1 x6196 -1 x6197 -1 x6198 -1 x6199 -1 x6200 -1 x6201 -1 x6202 -1 x6203 -1 x6204 -1 x6205 -1 x6206 -1 x6207 -1 x6208 -1 x6209 -1 x6210 -1 x6211 -1 x6212 -1 x6213 -1 x6214 -1 x6215 -1 x6216 -1 x6217 -1 x6218 -1 x6219 -1 x6220 -1 x6221 -1 x6222 -1 x6223 -1 x6224 -1 x6225 -1 x6226 -1 x6227 -1 x6228 -1 x6229 -1 x6230 -1 x6231 -1 x6232 -1 x6233 -1 x6234 -1 x6235 -1 x6236 -1 x6237 -1 x6238 -1 x6239 -1 x6240 -1 x6241 -1 x6242 -1 x6243 -1 x6244 -1 x6245 -1 x6246 -1 x6247 -1 x6248 -1 x6249 -1 x6250 -1 x6251 -1 x6252 -1 x6253 -1 x6254 -1 x6255 -1 x6256 -1 x6257 -1 x6258 -1 x6259 -1 x6260 -1 x6261 -1 x6262 -1 x6263 -1 x6264 -1 x6265 -1 x6266 -1 x6267 -1 x6268 -1 x6269 -1 x6270 -1 x6271 -1 x6272 >= -1 ;+-1 x6273 -1 x6274 -1 x6275 -1 x6276 -1 x6277 -1 x6278 -1 x6279 -1 x6280 -1 x6281 -1 x6282 -1 x6283 -1 x6284 -1 x6285 -1 x6286 -1 x6287 -1 x6288 -1 x6289 -1 x6290 -1 x6291 -1 x6292 -1 x6293 -1 x6294 -1 x6295 -1 x6296 -1 x6297 -1 x6298 -1 x6299 -1 x6300 -1 x6301 -1 x6302 -1 x6303 -1 x6304 -1 x6305 -1 x6306 -1 x6307 -1 x6308 -1 x6309 -1 x6310 -1 x6311 -1 x6312 -1 x6313 -1 x6314 -1 x6315 -1 x6316 -1 x6317 -1 x6318 -1 x6319 -1 x6320 -1 x6321 -1 x6322 -1 x6323 -1 x6324 -1 x6325 -1 x6326 -1 x6327 -1 x6328 -1 x6329 -1 x6330 -1 x6331 -1 x6332 -1 x6333 -1 x6334 -1 x6335 -1 x6336 -1 x6337 -1 x6338 -1 x6339 -1 x6340 -1 x6341 -1 x6342 -1 x6343 -1 x6344 -1 x6345 -1 x6346 -1 x6347 -1 x6348 -1 x6349 -1 x6350 -1 x6351 -1 x6352 -1 x6353 -1 x6354 -1 x6355 -1 x6356 -1 x6357 -1 x6358 -1 x6359 -1 x6360 -1 x6361 -1 x6362 -1 x6363 -1 x6364 -1 x6365 -1 x6366 -1 x6367 -1 x6368 -1 x6369 -1 x6370 -1 x6371 -1 x6372 -1 x6373 -1 x6374 -1 x6375 -1 x6376 -1 x6377 -1 x6378 -1 x6379 -1 x6380 -1 x6381 -1 x6382 -1 x6383 -1 x6384 -1 x6385 -1 x6386 -1 x6387 -1 x6388 -1 x6389 -1 x6390 -1 x6391 -1 x6392 -1 x6393 -1 x6394 -1 x6395 -1 x6396 -1 x6397 -1 x6398 -1 x6399 -1 x6400 >= -1 ;+-1 x6401 -1 x6402 -1 x6403 -1 x6404 -1 x6405 -1 x6406 -1 x6407 -1 x6408 -1 x6409 -1 x6410 -1 x6411 -1 x6412 -1 x6413 -1 x6414 -1 x6415 -1 x6416 -1 x6417 -1 x6418 -1 x6419 -1 x6420 -1 x6421 -1 x6422 -1 x6423 -1 x6424 -1 x6425 -1 x6426 -1 x6427 -1 x6428 -1 x6429 -1 x6430 -1 x6431 -1 x6432 -1 x6433 -1 x6434 -1 x6435 -1 x6436 -1 x6437 -1 x6438 -1 x6439 -1 x6440 -1 x6441 -1 x6442 -1 x6443 -1 x6444 -1 x6445 -1 x6446 -1 x6447 -1 x6448 -1 x6449 -1 x6450 -1 x6451 -1 x6452 -1 x6453 -1 x6454 -1 x6455 -1 x6456 -1 x6457 -1 x6458 -1 x6459 -1 x6460 -1 x6461 -1 x6462 -1 x6463 -1 x6464 -1 x6465 -1 x6466 -1 x6467 -1 x6468 -1 x6469 -1 x6470 -1 x6471 -1 x6472 -1 x6473 -1 x6474 -1 x6475 -1 x6476 -1 x6477 -1 x6478 -1 x6479 -1 x6480 -1 x6481 -1 x6482 -1 x6483 -1 x6484 -1 x6485 -1 x6486 -1 x6487 -1 x6488 -1 x6489 -1 x6490 -1 x6491 -1 x6492 -1 x6493 -1 x6494 -1 x6495 -1 x6496 -1 x6497 -1 x6498 -1 x6499 -1 x6500 -1 x6501 -1 x6502 -1 x6503 -1 x6504 -1 x6505 -1 x6506 -1 x6507 -1 x6508 -1 x6509 -1 x6510 -1 x6511 -1 x6512 -1 x6513 -1 x6514 -1 x6515 -1 x6516 -1 x6517 -1 x6518 -1 x6519 -1 x6520 -1 x6521 -1 x6522 -1 x6523 -1 x6524 -1 x6525 -1 x6526 -1 x6527 -1 x6528 >= -1 ;+-1 x6529 -1 x6530 -1 x6531 -1 x6532 -1 x6533 -1 x6534 -1 x6535 -1 x6536 -1 x6537 -1 x6538 -1 x6539 -1 x6540 -1 x6541 -1 x6542 -1 x6543 -1 x6544 -1 x6545 -1 x6546 -1 x6547 -1 x6548 -1 x6549 -1 x6550 -1 x6551 -1 x6552 -1 x6553 -1 x6554 -1 x6555 -1 x6556 -1 x6557 -1 x6558 -1 x6559 -1 x6560 -1 x6561 -1 x6562 -1 x6563 -1 x6564 -1 x6565 -1 x6566 -1 x6567 -1 x6568 -1 x6569 -1 x6570 -1 x6571 -1 x6572 -1 x6573 -1 x6574 -1 x6575 -1 x6576 -1 x6577 -1 x6578 -1 x6579 -1 x6580 -1 x6581 -1 x6582 -1 x6583 -1 x6584 -1 x6585 -1 x6586 -1 x6587 -1 x6588 -1 x6589 -1 x6590 -1 x6591 -1 x6592 -1 x6593 -1 x6594 -1 x6595 -1 x6596 -1 x6597 -1 x6598 -1 x6599 -1 x6600 -1 x6601 -1 x6602 -1 x6603 -1 x6604 -1 x6605 -1 x6606 -1 x6607 -1 x6608 -1 x6609 -1 x6610 -1 x6611 -1 x6612 -1 x6613 -1 x6614 -1 x6615 -1 x6616 -1 x6617 -1 x6618 -1 x6619 -1 x6620 -1 x6621 -1 x6622 -1 x6623 -1 x6624 -1 x6625 -1 x6626 -1 x6627 -1 x6628 -1 x6629 -1 x6630 -1 x6631 -1 x6632 -1 x6633 -1 x6634 -1 x6635 -1 x6636 -1 x6637 -1 x6638 -1 x6639 -1 x6640 -1 x6641 -1 x6642 -1 x6643 -1 x6644 -1 x6645 -1 x6646 -1 x6647 -1 x6648 -1 x6649 -1 x6650 -1 x6651 -1 x6652 -1 x6653 -1 x6654 -1 x6655 -1 x6656 >= -1 ;+-1 x6657 -1 x6658 -1 x6659 -1 x6660 -1 x6661 -1 x6662 -1 x6663 -1 x6664 -1 x6665 -1 x6666 -1 x6667 -1 x6668 -1 x6669 -1 x6670 -1 x6671 -1 x6672 -1 x6673 -1 x6674 -1 x6675 -1 x6676 -1 x6677 -1 x6678 -1 x6679 -1 x6680 -1 x6681 -1 x6682 -1 x6683 -1 x6684 -1 x6685 -1 x6686 -1 x6687 -1 x6688 -1 x6689 -1 x6690 -1 x6691 -1 x6692 -1 x6693 -1 x6694 -1 x6695 -1 x6696 -1 x6697 -1 x6698 -1 x6699 -1 x6700 -1 x6701 -1 x6702 -1 x6703 -1 x6704 -1 x6705 -1 x6706 -1 x6707 -1 x6708 -1 x6709 -1 x6710 -1 x6711 -1 x6712 -1 x6713 -1 x6714 -1 x6715 -1 x6716 -1 x6717 -1 x6718 -1 x6719 -1 x6720 -1 x6721 -1 x6722 -1 x6723 -1 x6724 -1 x6725 -1 x6726 -1 x6727 -1 x6728 -1 x6729 -1 x6730 -1 x6731 -1 x6732 -1 x6733 -1 x6734 -1 x6735 -1 x6736 -1 x6737 -1 x6738 -1 x6739 -1 x6740 -1 x6741 -1 x6742 -1 x6743 -1 x6744 -1 x6745 -1 x6746 -1 x6747 -1 x6748 -1 x6749 -1 x6750 -1 x6751 -1 x6752 -1 x6753 -1 x6754 -1 x6755 -1 x6756 -1 x6757 -1 x6758 -1 x6759 -1 x6760 -1 x6761 -1 x6762 -1 x6763 -1 x6764 -1 x6765 -1 x6766 -1 x6767 -1 x6768 -1 x6769 -1 x6770 -1 x6771 -1 x6772 -1 x6773 -1 x6774 -1 x6775 -1 x6776 -1 x6777 -1 x6778 -1 x6779 -1 x6780 -1 x6781 -1 x6782 -1 x6783 -1 x6784 >= -1 ;+-1 x6785 -1 x6786 -1 x6787 -1 x6788 -1 x6789 -1 x6790 -1 x6791 -1 x6792 -1 x6793 -1 x6794 -1 x6795 -1 x6796 -1 x6797 -1 x6798 -1 x6799 -1 x6800 -1 x6801 -1 x6802 -1 x6803 -1 x6804 -1 x6805 -1 x6806 -1 x6807 -1 x6808 -1 x6809 -1 x6810 -1 x6811 -1 x6812 -1 x6813 -1 x6814 -1 x6815 -1 x6816 -1 x6817 -1 x6818 -1 x6819 -1 x6820 -1 x6821 -1 x6822 -1 x6823 -1 x6824 -1 x6825 -1 x6826 -1 x6827 -1 x6828 -1 x6829 -1 x6830 -1 x6831 -1 x6832 -1 x6833 -1 x6834 -1 x6835 -1 x6836 -1 x6837 -1 x6838 -1 x6839 -1 x6840 -1 x6841 -1 x6842 -1 x6843 -1 x6844 -1 x6845 -1 x6846 -1 x6847 -1 x6848 -1 x6849 -1 x6850 -1 x6851 -1 x6852 -1 x6853 -1 x6854 -1 x6855 -1 x6856 -1 x6857 -1 x6858 -1 x6859 -1 x6860 -1 x6861 -1 x6862 -1 x6863 -1 x6864 -1 x6865 -1 x6866 -1 x6867 -1 x6868 -1 x6869 -1 x6870 -1 x6871 -1 x6872 -1 x6873 -1 x6874 -1 x6875 -1 x6876 -1 x6877 -1 x6878 -1 x6879 -1 x6880 -1 x6881 -1 x6882 -1 x6883 -1 x6884 -1 x6885 -1 x6886 -1 x6887 -1 x6888 -1 x6889 -1 x6890 -1 x6891 -1 x6892 -1 x6893 -1 x6894 -1 x6895 -1 x6896 -1 x6897 -1 x6898 -1 x6899 -1 x6900 -1 x6901 -1 x6902 -1 x6903 -1 x6904 -1 x6905 -1 x6906 -1 x6907 -1 x6908 -1 x6909 -1 x6910 -1 x6911 -1 x6912 >= -1 ;+-1 x6913 -1 x6914 -1 x6915 -1 x6916 -1 x6917 -1 x6918 -1 x6919 -1 x6920 -1 x6921 -1 x6922 -1 x6923 -1 x6924 -1 x6925 -1 x6926 -1 x6927 -1 x6928 -1 x6929 -1 x6930 -1 x6931 -1 x6932 -1 x6933 -1 x6934 -1 x6935 -1 x6936 -1 x6937 -1 x6938 -1 x6939 -1 x6940 -1 x6941 -1 x6942 -1 x6943 -1 x6944 -1 x6945 -1 x6946 -1 x6947 -1 x6948 -1 x6949 -1 x6950 -1 x6951 -1 x6952 -1 x6953 -1 x6954 -1 x6955 -1 x6956 -1 x6957 -1 x6958 -1 x6959 -1 x6960 -1 x6961 -1 x6962 -1 x6963 -1 x6964 -1 x6965 -1 x6966 -1 x6967 -1 x6968 -1 x6969 -1 x6970 -1 x6971 -1 x6972 -1 x6973 -1 x6974 -1 x6975 -1 x6976 -1 x6977 -1 x6978 -1 x6979 -1 x6980 -1 x6981 -1 x6982 -1 x6983 -1 x6984 -1 x6985 -1 x6986 -1 x6987 -1 x6988 -1 x6989 -1 x6990 -1 x6991 -1 x6992 -1 x6993 -1 x6994 -1 x6995 -1 x6996 -1 x6997 -1 x6998 -1 x6999 -1 x7000 -1 x7001 -1 x7002 -1 x7003 -1 x7004 -1 x7005 -1 x7006 -1 x7007 -1 x7008 -1 x7009 -1 x7010 -1 x7011 -1 x7012 -1 x7013 -1 x7014 -1 x7015 -1 x7016 -1 x7017 -1 x7018 -1 x7019 -1 x7020 -1 x7021 -1 x7022 -1 x7023 -1 x7024 -1 x7025 -1 x7026 -1 x7027 -1 x7028 -1 x7029 -1 x7030 -1 x7031 -1 x7032 -1 x7033 -1 x7034 -1 x7035 -1 x7036 -1 x7037 -1 x7038 -1 x7039 -1 x7040 >= -1 ;+-1 x7041 -1 x7042 -1 x7043 -1 x7044 -1 x7045 -1 x7046 -1 x7047 -1 x7048 -1 x7049 -1 x7050 -1 x7051 -1 x7052 -1 x7053 -1 x7054 -1 x7055 -1 x7056 -1 x7057 -1 x7058 -1 x7059 -1 x7060 -1 x7061 -1 x7062 -1 x7063 -1 x7064 -1 x7065 -1 x7066 -1 x7067 -1 x7068 -1 x7069 -1 x7070 -1 x7071 -1 x7072 -1 x7073 -1 x7074 -1 x7075 -1 x7076 -1 x7077 -1 x7078 -1 x7079 -1 x7080 -1 x7081 -1 x7082 -1 x7083 -1 x7084 -1 x7085 -1 x7086 -1 x7087 -1 x7088 -1 x7089 -1 x7090 -1 x7091 -1 x7092 -1 x7093 -1 x7094 -1 x7095 -1 x7096 -1 x7097 -1 x7098 -1 x7099 -1 x7100 -1 x7101 -1 x7102 -1 x7103 -1 x7104 -1 x7105 -1 x7106 -1 x7107 -1 x7108 -1 x7109 -1 x7110 -1 x7111 -1 x7112 -1 x7113 -1 x7114 -1 x7115 -1 x7116 -1 x7117 -1 x7118 -1 x7119 -1 x7120 -1 x7121 -1 x7122 -1 x7123 -1 x7124 -1 x7125 -1 x7126 -1 x7127 -1 x7128 -1 x7129 -1 x7130 -1 x7131 -1 x7132 -1 x7133 -1 x7134 -1 x7135 -1 x7136 -1 x7137 -1 x7138 -1 x7139 -1 x7140 -1 x7141 -1 x7142 -1 x7143 -1 x7144 -1 x7145 -1 x7146 -1 x7147 -1 x7148 -1 x7149 -1 x7150 -1 x7151 -1 x7152 -1 x7153 -1 x7154 -1 x7155 -1 x7156 -1 x7157 -1 x7158 -1 x7159 -1 x7160 -1 x7161 -1 x7162 -1 x7163 -1 x7164 -1 x7165 -1 x7166 -1 x7167 -1 x7168 >= -1 ;+-1 x7169 -1 x7170 -1 x7171 -1 x7172 -1 x7173 -1 x7174 -1 x7175 -1 x7176 -1 x7177 -1 x7178 -1 x7179 -1 x7180 -1 x7181 -1 x7182 -1 x7183 -1 x7184 -1 x7185 -1 x7186 -1 x7187 -1 x7188 -1 x7189 -1 x7190 -1 x7191 -1 x7192 -1 x7193 -1 x7194 -1 x7195 -1 x7196 -1 x7197 -1 x7198 -1 x7199 -1 x7200 -1 x7201 -1 x7202 -1 x7203 -1 x7204 -1 x7205 -1 x7206 -1 x7207 -1 x7208 -1 x7209 -1 x7210 -1 x7211 -1 x7212 -1 x7213 -1 x7214 -1 x7215 -1 x7216 -1 x7217 -1 x7218 -1 x7219 -1 x7220 -1 x7221 -1 x7222 -1 x7223 -1 x7224 -1 x7225 -1 x7226 -1 x7227 -1 x7228 -1 x7229 -1 x7230 -1 x7231 -1 x7232 -1 x7233 -1 x7234 -1 x7235 -1 x7236 -1 x7237 -1 x7238 -1 x7239 -1 x7240 -1 x7241 -1 x7242 -1 x7243 -1 x7244 -1 x7245 -1 x7246 -1 x7247 -1 x7248 -1 x7249 -1 x7250 -1 x7251 -1 x7252 -1 x7253 -1 x7254 -1 x7255 -1 x7256 -1 x7257 -1 x7258 -1 x7259 -1 x7260 -1 x7261 -1 x7262 -1 x7263 -1 x7264 -1 x7265 -1 x7266 -1 x7267 -1 x7268 -1 x7269 -1 x7270 -1 x7271 -1 x7272 -1 x7273 -1 x7274 -1 x7275 -1 x7276 -1 x7277 -1 x7278 -1 x7279 -1 x7280 -1 x7281 -1 x7282 -1 x7283 -1 x7284 -1 x7285 -1 x7286 -1 x7287 -1 x7288 -1 x7289 -1 x7290 -1 x7291 -1 x7292 -1 x7293 -1 x7294 -1 x7295 -1 x7296 >= -1 ;+-1 x7297 -1 x7298 -1 x7299 -1 x7300 -1 x7301 -1 x7302 -1 x7303 -1 x7304 -1 x7305 -1 x7306 -1 x7307 -1 x7308 -1 x7309 -1 x7310 -1 x7311 -1 x7312 -1 x7313 -1 x7314 -1 x7315 -1 x7316 -1 x7317 -1 x7318 -1 x7319 -1 x7320 -1 x7321 -1 x7322 -1 x7323 -1 x7324 -1 x7325 -1 x7326 -1 x7327 -1 x7328 -1 x7329 -1 x7330 -1 x7331 -1 x7332 -1 x7333 -1 x7334 -1 x7335 -1 x7336 -1 x7337 -1 x7338 -1 x7339 -1 x7340 -1 x7341 -1 x7342 -1 x7343 -1 x7344 -1 x7345 -1 x7346 -1 x7347 -1 x7348 -1 x7349 -1 x7350 -1 x7351 -1 x7352 -1 x7353 -1 x7354 -1 x7355 -1 x7356 -1 x7357 -1 x7358 -1 x7359 -1 x7360 -1 x7361 -1 x7362 -1 x7363 -1 x7364 -1 x7365 -1 x7366 -1 x7367 -1 x7368 -1 x7369 -1 x7370 -1 x7371 -1 x7372 -1 x7373 -1 x7374 -1 x7375 -1 x7376 -1 x7377 -1 x7378 -1 x7379 -1 x7380 -1 x7381 -1 x7382 -1 x7383 -1 x7384 -1 x7385 -1 x7386 -1 x7387 -1 x7388 -1 x7389 -1 x7390 -1 x7391 -1 x7392 -1 x7393 -1 x7394 -1 x7395 -1 x7396 -1 x7397 -1 x7398 -1 x7399 -1 x7400 -1 x7401 -1 x7402 -1 x7403 -1 x7404 -1 x7405 -1 x7406 -1 x7407 -1 x7408 -1 x7409 -1 x7410 -1 x7411 -1 x7412 -1 x7413 -1 x7414 -1 x7415 -1 x7416 -1 x7417 -1 x7418 -1 x7419 -1 x7420 -1 x7421 -1 x7422 -1 x7423 -1 x7424 >= -1 ;+-1 x7425 -1 x7426 -1 x7427 -1 x7428 -1 x7429 -1 x7430 -1 x7431 -1 x7432 -1 x7433 -1 x7434 -1 x7435 -1 x7436 -1 x7437 -1 x7438 -1 x7439 -1 x7440 -1 x7441 -1 x7442 -1 x7443 -1 x7444 -1 x7445 -1 x7446 -1 x7447 -1 x7448 -1 x7449 -1 x7450 -1 x7451 -1 x7452 -1 x7453 -1 x7454 -1 x7455 -1 x7456 -1 x7457 -1 x7458 -1 x7459 -1 x7460 -1 x7461 -1 x7462 -1 x7463 -1 x7464 -1 x7465 -1 x7466 -1 x7467 -1 x7468 -1 x7469 -1 x7470 -1 x7471 -1 x7472 -1 x7473 -1 x7474 -1 x7475 -1 x7476 -1 x7477 -1 x7478 -1 x7479 -1 x7480 -1 x7481 -1 x7482 -1 x7483 -1 x7484 -1 x7485 -1 x7486 -1 x7487 -1 x7488 -1 x7489 -1 x7490 -1 x7491 -1 x7492 -1 x7493 -1 x7494 -1 x7495 -1 x7496 -1 x7497 -1 x7498 -1 x7499 -1 x7500 -1 x7501 -1 x7502 -1 x7503 -1 x7504 -1 x7505 -1 x7506 -1 x7507 -1 x7508 -1 x7509 -1 x7510 -1 x7511 -1 x7512 -1 x7513 -1 x7514 -1 x7515 -1 x7516 -1 x7517 -1 x7518 -1 x7519 -1 x7520 -1 x7521 -1 x7522 -1 x7523 -1 x7524 -1 x7525 -1 x7526 -1 x7527 -1 x7528 -1 x7529 -1 x7530 -1 x7531 -1 x7532 -1 x7533 -1 x7534 -1 x7535 -1 x7536 -1 x7537 -1 x7538 -1 x7539 -1 x7540 -1 x7541 -1 x7542 -1 x7543 -1 x7544 -1 x7545 -1 x7546 -1 x7547 -1 x7548 -1 x7549 -1 x7550 -1 x7551 -1 x7552 >= -1 ;+-1 x7553 -1 x7554 -1 x7555 -1 x7556 -1 x7557 -1 x7558 -1 x7559 -1 x7560 -1 x7561 -1 x7562 -1 x7563 -1 x7564 -1 x7565 -1 x7566 -1 x7567 -1 x7568 -1 x7569 -1 x7570 -1 x7571 -1 x7572 -1 x7573 -1 x7574 -1 x7575 -1 x7576 -1 x7577 -1 x7578 -1 x7579 -1 x7580 -1 x7581 -1 x7582 -1 x7583 -1 x7584 -1 x7585 -1 x7586 -1 x7587 -1 x7588 -1 x7589 -1 x7590 -1 x7591 -1 x7592 -1 x7593 -1 x7594 -1 x7595 -1 x7596 -1 x7597 -1 x7598 -1 x7599 -1 x7600 -1 x7601 -1 x7602 -1 x7603 -1 x7604 -1 x7605 -1 x7606 -1 x7607 -1 x7608 -1 x7609 -1 x7610 -1 x7611 -1 x7612 -1 x7613 -1 x7614 -1 x7615 -1 x7616 -1 x7617 -1 x7618 -1 x7619 -1 x7620 -1 x7621 -1 x7622 -1 x7623 -1 x7624 -1 x7625 -1 x7626 -1 x7627 -1 x7628 -1 x7629 -1 x7630 -1 x7631 -1 x7632 -1 x7633 -1 x7634 -1 x7635 -1 x7636 -1 x7637 -1 x7638 -1 x7639 -1 x7640 -1 x7641 -1 x7642 -1 x7643 -1 x7644 -1 x7645 -1 x7646 -1 x7647 -1 x7648 -1 x7649 -1 x7650 -1 x7651 -1 x7652 -1 x7653 -1 x7654 -1 x7655 -1 x7656 -1 x7657 -1 x7658 -1 x7659 -1 x7660 -1 x7661 -1 x7662 -1 x7663 -1 x7664 -1 x7665 -1 x7666 -1 x7667 -1 x7668 -1 x7669 -1 x7670 -1 x7671 -1 x7672 -1 x7673 -1 x7674 -1 x7675 -1 x7676 -1 x7677 -1 x7678 -1 x7679 -1 x7680 >= -1 ;+-1 x7681 -1 x7682 -1 x7683 -1 x7684 -1 x7685 -1 x7686 -1 x7687 -1 x7688 -1 x7689 -1 x7690 -1 x7691 -1 x7692 -1 x7693 -1 x7694 -1 x7695 -1 x7696 -1 x7697 -1 x7698 -1 x7699 -1 x7700 -1 x7701 -1 x7702 -1 x7703 -1 x7704 -1 x7705 -1 x7706 -1 x7707 -1 x7708 -1 x7709 -1 x7710 -1 x7711 -1 x7712 -1 x7713 -1 x7714 -1 x7715 -1 x7716 -1 x7717 -1 x7718 -1 x7719 -1 x7720 -1 x7721 -1 x7722 -1 x7723 -1 x7724 -1 x7725 -1 x7726 -1 x7727 -1 x7728 -1 x7729 -1 x7730 -1 x7731 -1 x7732 -1 x7733 -1 x7734 -1 x7735 -1 x7736 -1 x7737 -1 x7738 -1 x7739 -1 x7740 -1 x7741 -1 x7742 -1 x7743 -1 x7744 -1 x7745 -1 x7746 -1 x7747 -1 x7748 -1 x7749 -1 x7750 -1 x7751 -1 x7752 -1 x7753 -1 x7754 -1 x7755 -1 x7756 -1 x7757 -1 x7758 -1 x7759 -1 x7760 -1 x7761 -1 x7762 -1 x7763 -1 x7764 -1 x7765 -1 x7766 -1 x7767 -1 x7768 -1 x7769 -1 x7770 -1 x7771 -1 x7772 -1 x7773 -1 x7774 -1 x7775 -1 x7776 -1 x7777 -1 x7778 -1 x7779 -1 x7780 -1 x7781 -1 x7782 -1 x7783 -1 x7784 -1 x7785 -1 x7786 -1 x7787 -1 x7788 -1 x7789 -1 x7790 -1 x7791 -1 x7792 -1 x7793 -1 x7794 -1 x7795 -1 x7796 -1 x7797 -1 x7798 -1 x7799 -1 x7800 -1 x7801 -1 x7802 -1 x7803 -1 x7804 -1 x7805 -1 x7806 -1 x7807 -1 x7808 >= -1 ;+-1 x7809 -1 x7810 -1 x7811 -1 x7812 -1 x7813 -1 x7814 -1 x7815 -1 x7816 -1 x7817 -1 x7818 -1 x7819 -1 x7820 -1 x7821 -1 x7822 -1 x7823 -1 x7824 -1 x7825 -1 x7826 -1 x7827 -1 x7828 -1 x7829 -1 x7830 -1 x7831 -1 x7832 -1 x7833 -1 x7834 -1 x7835 -1 x7836 -1 x7837 -1 x7838 -1 x7839 -1 x7840 -1 x7841 -1 x7842 -1 x7843 -1 x7844 -1 x7845 -1 x7846 -1 x7847 -1 x7848 -1 x7849 -1 x7850 -1 x7851 -1 x7852 -1 x7853 -1 x7854 -1 x7855 -1 x7856 -1 x7857 -1 x7858 -1 x7859 -1 x7860 -1 x7861 -1 x7862 -1 x7863 -1 x7864 -1 x7865 -1 x7866 -1 x7867 -1 x7868 -1 x7869 -1 x7870 -1 x7871 -1 x7872 -1 x7873 -1 x7874 -1 x7875 -1 x7876 -1 x7877 -1 x7878 -1 x7879 -1 x7880 -1 x7881 -1 x7882 -1 x7883 -1 x7884 -1 x7885 -1 x7886 -1 x7887 -1 x7888 -1 x7889 -1 x7890 -1 x7891 -1 x7892 -1 x7893 -1 x7894 -1 x7895 -1 x7896 -1 x7897 -1 x7898 -1 x7899 -1 x7900 -1 x7901 -1 x7902 -1 x7903 -1 x7904 -1 x7905 -1 x7906 -1 x7907 -1 x7908 -1 x7909 -1 x7910 -1 x7911 -1 x7912 -1 x7913 -1 x7914 -1 x7915 -1 x7916 -1 x7917 -1 x7918 -1 x7919 -1 x7920 -1 x7921 -1 x7922 -1 x7923 -1 x7924 -1 x7925 -1 x7926 -1 x7927 -1 x7928 -1 x7929 -1 x7930 -1 x7931 -1 x7932 -1 x7933 -1 x7934 -1 x7935 -1 x7936 >= -1 ;+-1 x7937 -1 x7938 -1 x7939 -1 x7940 -1 x7941 -1 x7942 -1 x7943 -1 x7944 -1 x7945 -1 x7946 -1 x7947 -1 x7948 -1 x7949 -1 x7950 -1 x7951 -1 x7952 -1 x7953 -1 x7954 -1 x7955 -1 x7956 -1 x7957 -1 x7958 -1 x7959 -1 x7960 -1 x7961 -1 x7962 -1 x7963 -1 x7964 -1 x7965 -1 x7966 -1 x7967 -1 x7968 -1 x7969 -1 x7970 -1 x7971 -1 x7972 -1 x7973 -1 x7974 -1 x7975 -1 x7976 -1 x7977 -1 x7978 -1 x7979 -1 x7980 -1 x7981 -1 x7982 -1 x7983 -1 x7984 -1 x7985 -1 x7986 -1 x7987 -1 x7988 -1 x7989 -1 x7990 -1 x7991 -1 x7992 -1 x7993 -1 x7994 -1 x7995 -1 x7996 -1 x7997 -1 x7998 -1 x7999 -1 x8000 -1 x8001 -1 x8002 -1 x8003 -1 x8004 -1 x8005 -1 x8006 -1 x8007 -1 x8008 -1 x8009 -1 x8010 -1 x8011 -1 x8012 -1 x8013 -1 x8014 -1 x8015 -1 x8016 -1 x8017 -1 x8018 -1 x8019 -1 x8020 -1 x8021 -1 x8022 -1 x8023 -1 x8024 -1 x8025 -1 x8026 -1 x8027 -1 x8028 -1 x8029 -1 x8030 -1 x8031 -1 x8032 -1 x8033 -1 x8034 -1 x8035 -1 x8036 -1 x8037 -1 x8038 -1 x8039 -1 x8040 -1 x8041 -1 x8042 -1 x8043 -1 x8044 -1 x8045 -1 x8046 -1 x8047 -1 x8048 -1 x8049 -1 x8050 -1 x8051 -1 x8052 -1 x8053 -1 x8054 -1 x8055 -1 x8056 -1 x8057 -1 x8058 -1 x8059 -1 x8060 -1 x8061 -1 x8062 -1 x8063 -1 x8064 >= -1 ;+-1 x8065 -1 x8066 -1 x8067 -1 x8068 -1 x8069 -1 x8070 -1 x8071 -1 x8072 -1 x8073 -1 x8074 -1 x8075 -1 x8076 -1 x8077 -1 x8078 -1 x8079 -1 x8080 -1 x8081 -1 x8082 -1 x8083 -1 x8084 -1 x8085 -1 x8086 -1 x8087 -1 x8088 -1 x8089 -1 x8090 -1 x8091 -1 x8092 -1 x8093 -1 x8094 -1 x8095 -1 x8096 -1 x8097 -1 x8098 -1 x8099 -1 x8100 -1 x8101 -1 x8102 -1 x8103 -1 x8104 -1 x8105 -1 x8106 -1 x8107 -1 x8108 -1 x8109 -1 x8110 -1 x8111 -1 x8112 -1 x8113 -1 x8114 -1 x8115 -1 x8116 -1 x8117 -1 x8118 -1 x8119 -1 x8120 -1 x8121 -1 x8122 -1 x8123 -1 x8124 -1 x8125 -1 x8126 -1 x8127 -1 x8128 -1 x8129 -1 x8130 -1 x8131 -1 x8132 -1 x8133 -1 x8134 -1 x8135 -1 x8136 -1 x8137 -1 x8138 -1 x8139 -1 x8140 -1 x8141 -1 x8142 -1 x8143 -1 x8144 -1 x8145 -1 x8146 -1 x8147 -1 x8148 -1 x8149 -1 x8150 -1 x8151 -1 x8152 -1 x8153 -1 x8154 -1 x8155 -1 x8156 -1 x8157 -1 x8158 -1 x8159 -1 x8160 -1 x8161 -1 x8162 -1 x8163 -1 x8164 -1 x8165 -1 x8166 -1 x8167 -1 x8168 -1 x8169 -1 x8170 -1 x8171 -1 x8172 -1 x8173 -1 x8174 -1 x8175 -1 x8176 -1 x8177 -1 x8178 -1 x8179 -1 x8180 -1 x8181 -1 x8182 -1 x8183 -1 x8184 -1 x8185 -1 x8186 -1 x8187 -1 x8188 -1 x8189 -1 x8190 -1 x8191 -1 x8192 >= -1 ;+-1 x8193 -1 x8194 -1 x8195 -1 x8196 -1 x8197 -1 x8198 -1 x8199 -1 x8200 -1 x8201 -1 x8202 -1 x8203 -1 x8204 -1 x8205 -1 x8206 -1 x8207 -1 x8208 -1 x8209 -1 x8210 -1 x8211 -1 x8212 -1 x8213 -1 x8214 -1 x8215 -1 x8216 -1 x8217 -1 x8218 -1 x8219 -1 x8220 -1 x8221 -1 x8222 -1 x8223 -1 x8224 -1 x8225 -1 x8226 -1 x8227 -1 x8228 -1 x8229 -1 x8230 -1 x8231 -1 x8232 -1 x8233 -1 x8234 -1 x8235 -1 x8236 -1 x8237 -1 x8238 -1 x8239 -1 x8240 -1 x8241 -1 x8242 -1 x8243 -1 x8244 -1 x8245 -1 x8246 -1 x8247 -1 x8248 -1 x8249 -1 x8250 -1 x8251 -1 x8252 -1 x8253 -1 x8254 -1 x8255 -1 x8256 -1 x8257 -1 x8258 -1 x8259 -1 x8260 -1 x8261 -1 x8262 -1 x8263 -1 x8264 -1 x8265 -1 x8266 -1 x8267 -1 x8268 -1 x8269 -1 x8270 -1 x8271 -1 x8272 -1 x8273 -1 x8274 -1 x8275 -1 x8276 -1 x8277 -1 x8278 -1 x8279 -1 x8280 -1 x8281 -1 x8282 -1 x8283 -1 x8284 -1 x8285 -1 x8286 -1 x8287 -1 x8288 -1 x8289 -1 x8290 -1 x8291 -1 x8292 -1 x8293 -1 x8294 -1 x8295 -1 x8296 -1 x8297 -1 x8298 -1 x8299 -1 x8300 -1 x8301 -1 x8302 -1 x8303 -1 x8304 -1 x8305 -1 x8306 -1 x8307 -1 x8308 -1 x8309 -1 x8310 -1 x8311 -1 x8312 -1 x8313 -1 x8314 -1 x8315 -1 x8316 -1 x8317 -1 x8318 -1 x8319 -1 x8320 >= -1 ;+-1 x8321 -1 x8322 -1 x8323 -1 x8324 -1 x8325 -1 x8326 -1 x8327 -1 x8328 -1 x8329 -1 x8330 -1 x8331 -1 x8332 -1 x8333 -1 x8334 -1 x8335 -1 x8336 -1 x8337 -1 x8338 -1 x8339 -1 x8340 -1 x8341 -1 x8342 -1 x8343 -1 x8344 -1 x8345 -1 x8346 -1 x8347 -1 x8348 -1 x8349 -1 x8350 -1 x8351 -1 x8352 -1 x8353 -1 x8354 -1 x8355 -1 x8356 -1 x8357 -1 x8358 -1 x8359 -1 x8360 -1 x8361 -1 x8362 -1 x8363 -1 x8364 -1 x8365 -1 x8366 -1 x8367 -1 x8368 -1 x8369 -1 x8370 -1 x8371 -1 x8372 -1 x8373 -1 x8374 -1 x8375 -1 x8376 -1 x8377 -1 x8378 -1 x8379 -1 x8380 -1 x8381 -1 x8382 -1 x8383 -1 x8384 -1 x8385 -1 x8386 -1 x8387 -1 x8388 -1 x8389 -1 x8390 -1 x8391 -1 x8392 -1 x8393 -1 x8394 -1 x8395 -1 x8396 -1 x8397 -1 x8398 -1 x8399 -1 x8400 -1 x8401 -1 x8402 -1 x8403 -1 x8404 -1 x8405 -1 x8406 -1 x8407 -1 x8408 -1 x8409 -1 x8410 -1 x8411 -1 x8412 -1 x8413 -1 x8414 -1 x8415 -1 x8416 -1 x8417 -1 x8418 -1 x8419 -1 x8420 -1 x8421 -1 x8422 -1 x8423 -1 x8424 -1 x8425 -1 x8426 -1 x8427 -1 x8428 -1 x8429 -1 x8430 -1 x8431 -1 x8432 -1 x8433 -1 x8434 -1 x8435 -1 x8436 -1 x8437 -1 x8438 -1 x8439 -1 x8440 -1 x8441 -1 x8442 -1 x8443 -1 x8444 -1 x8445 -1 x8446 -1 x8447 -1 x8448 >= -1 ;+-1 x8449 -1 x8450 -1 x8451 -1 x8452 -1 x8453 -1 x8454 -1 x8455 -1 x8456 -1 x8457 -1 x8458 -1 x8459 -1 x8460 -1 x8461 -1 x8462 -1 x8463 -1 x8464 -1 x8465 -1 x8466 -1 x8467 -1 x8468 -1 x8469 -1 x8470 -1 x8471 -1 x8472 -1 x8473 -1 x8474 -1 x8475 -1 x8476 -1 x8477 -1 x8478 -1 x8479 -1 x8480 -1 x8481 -1 x8482 -1 x8483 -1 x8484 -1 x8485 -1 x8486 -1 x8487 -1 x8488 -1 x8489 -1 x8490 -1 x8491 -1 x8492 -1 x8493 -1 x8494 -1 x8495 -1 x8496 -1 x8497 -1 x8498 -1 x8499 -1 x8500 -1 x8501 -1 x8502 -1 x8503 -1 x8504 -1 x8505 -1 x8506 -1 x8507 -1 x8508 -1 x8509 -1 x8510 -1 x8511 -1 x8512 -1 x8513 -1 x8514 -1 x8515 -1 x8516 -1 x8517 -1 x8518 -1 x8519 -1 x8520 -1 x8521 -1 x8522 -1 x8523 -1 x8524 -1 x8525 -1 x8526 -1 x8527 -1 x8528 -1 x8529 -1 x8530 -1 x8531 -1 x8532 -1 x8533 -1 x8534 -1 x8535 -1 x8536 -1 x8537 -1 x8538 -1 x8539 -1 x8540 -1 x8541 -1 x8542 -1 x8543 -1 x8544 -1 x8545 -1 x8546 -1 x8547 -1 x8548 -1 x8549 -1 x8550 -1 x8551 -1 x8552 -1 x8553 -1 x8554 -1 x8555 -1 x8556 -1 x8557 -1 x8558 -1 x8559 -1 x8560 -1 x8561 -1 x8562 -1 x8563 -1 x8564 -1 x8565 -1 x8566 -1 x8567 -1 x8568 -1 x8569 -1 x8570 -1 x8571 -1 x8572 -1 x8573 -1 x8574 -1 x8575 -1 x8576 >= -1 ;+-1 x8577 -1 x8578 -1 x8579 -1 x8580 -1 x8581 -1 x8582 -1 x8583 -1 x8584 -1 x8585 -1 x8586 -1 x8587 -1 x8588 -1 x8589 -1 x8590 -1 x8591 -1 x8592 -1 x8593 -1 x8594 -1 x8595 -1 x8596 -1 x8597 -1 x8598 -1 x8599 -1 x8600 -1 x8601 -1 x8602 -1 x8603 -1 x8604 -1 x8605 -1 x8606 -1 x8607 -1 x8608 -1 x8609 -1 x8610 -1 x8611 -1 x8612 -1 x8613 -1 x8614 -1 x8615 -1 x8616 -1 x8617 -1 x8618 -1 x8619 -1 x8620 -1 x8621 -1 x8622 -1 x8623 -1 x8624 -1 x8625 -1 x8626 -1 x8627 -1 x8628 -1 x8629 -1 x8630 -1 x8631 -1 x8632 -1 x8633 -1 x8634 -1 x8635 -1 x8636 -1 x8637 -1 x8638 -1 x8639 -1 x8640 -1 x8641 -1 x8642 -1 x8643 -1 x8644 -1 x8645 -1 x8646 -1 x8647 -1 x8648 -1 x8649 -1 x8650 -1 x8651 -1 x8652 -1 x8653 -1 x8654 -1 x8655 -1 x8656 -1 x8657 -1 x8658 -1 x8659 -1 x8660 -1 x8661 -1 x8662 -1 x8663 -1 x8664 -1 x8665 -1 x8666 -1 x8667 -1 x8668 -1 x8669 -1 x8670 -1 x8671 -1 x8672 -1 x8673 -1 x8674 -1 x8675 -1 x8676 -1 x8677 -1 x8678 -1 x8679 -1 x8680 -1 x8681 -1 x8682 -1 x8683 -1 x8684 -1 x8685 -1 x8686 -1 x8687 -1 x8688 -1 x8689 -1 x8690 -1 x8691 -1 x8692 -1 x8693 -1 x8694 -1 x8695 -1 x8696 -1 x8697 -1 x8698 -1 x8699 -1 x8700 -1 x8701 -1 x8702 -1 x8703 -1 x8704 >= -1 ;+-1 x8705 -1 x8706 -1 x8707 -1 x8708 -1 x8709 -1 x8710 -1 x8711 -1 x8712 -1 x8713 -1 x8714 -1 x8715 -1 x8716 -1 x8717 -1 x8718 -1 x8719 -1 x8720 -1 x8721 -1 x8722 -1 x8723 -1 x8724 -1 x8725 -1 x8726 -1 x8727 -1 x8728 -1 x8729 -1 x8730 -1 x8731 -1 x8732 -1 x8733 -1 x8734 -1 x8735 -1 x8736 -1 x8737 -1 x8738 -1 x8739 -1 x8740 -1 x8741 -1 x8742 -1 x8743 -1 x8744 -1 x8745 -1 x8746 -1 x8747 -1 x8748 -1 x8749 -1 x8750 -1 x8751 -1 x8752 -1 x8753 -1 x8754 -1 x8755 -1 x8756 -1 x8757 -1 x8758 -1 x8759 -1 x8760 -1 x8761 -1 x8762 -1 x8763 -1 x8764 -1 x8765 -1 x8766 -1 x8767 -1 x8768 -1 x8769 -1 x8770 -1 x8771 -1 x8772 -1 x8773 -1 x8774 -1 x8775 -1 x8776 -1 x8777 -1 x8778 -1 x8779 -1 x8780 -1 x8781 -1 x8782 -1 x8783 -1 x8784 -1 x8785 -1 x8786 -1 x8787 -1 x8788 -1 x8789 -1 x8790 -1 x8791 -1 x8792 -1 x8793 -1 x8794 -1 x8795 -1 x8796 -1 x8797 -1 x8798 -1 x8799 -1 x8800 -1 x8801 -1 x8802 -1 x8803 -1 x8804 -1 x8805 -1 x8806 -1 x8807 -1 x8808 -1 x8809 -1 x8810 -1 x8811 -1 x8812 -1 x8813 -1 x8814 -1 x8815 -1 x8816 -1 x8817 -1 x8818 -1 x8819 -1 x8820 -1 x8821 -1 x8822 -1 x8823 -1 x8824 -1 x8825 -1 x8826 -1 x8827 -1 x8828 -1 x8829 -1 x8830 -1 x8831 -1 x8832 >= -1 ;+-1 x8833 -1 x8834 -1 x8835 -1 x8836 -1 x8837 -1 x8838 -1 x8839 -1 x8840 -1 x8841 -1 x8842 -1 x8843 -1 x8844 -1 x8845 -1 x8846 -1 x8847 -1 x8848 -1 x8849 -1 x8850 -1 x8851 -1 x8852 -1 x8853 -1 x8854 -1 x8855 -1 x8856 -1 x8857 -1 x8858 -1 x8859 -1 x8860 -1 x8861 -1 x8862 -1 x8863 -1 x8864 -1 x8865 -1 x8866 -1 x8867 -1 x8868 -1 x8869 -1 x8870 -1 x8871 -1 x8872 -1 x8873 -1 x8874 -1 x8875 -1 x8876 -1 x8877 -1 x8878 -1 x8879 -1 x8880 -1 x8881 -1 x8882 -1 x8883 -1 x8884 -1 x8885 -1 x8886 -1 x8887 -1 x8888 -1 x8889 -1 x8890 -1 x8891 -1 x8892 -1 x8893 -1 x8894 -1 x8895 -1 x8896 -1 x8897 -1 x8898 -1 x8899 -1 x8900 -1 x8901 -1 x8902 -1 x8903 -1 x8904 -1 x8905 -1 x8906 -1 x8907 -1 x8908 -1 x8909 -1 x8910 -1 x8911 -1 x8912 -1 x8913 -1 x8914 -1 x8915 -1 x8916 -1 x8917 -1 x8918 -1 x8919 -1 x8920 -1 x8921 -1 x8922 -1 x8923 -1 x8924 -1 x8925 -1 x8926 -1 x8927 -1 x8928 -1 x8929 -1 x8930 -1 x8931 -1 x8932 -1 x8933 -1 x8934 -1 x8935 -1 x8936 -1 x8937 -1 x8938 -1 x8939 -1 x8940 -1 x8941 -1 x8942 -1 x8943 -1 x8944 -1 x8945 -1 x8946 -1 x8947 -1 x8948 -1 x8949 -1 x8950 -1 x8951 -1 x8952 -1 x8953 -1 x8954 -1 x8955 -1 x8956 -1 x8957 -1 x8958 -1 x8959 -1 x8960 >= -1 ;+-1 x8961 -1 x8962 -1 x8963 -1 x8964 -1 x8965 -1 x8966 -1 x8967 -1 x8968 -1 x8969 -1 x8970 -1 x8971 -1 x8972 -1 x8973 -1 x8974 -1 x8975 -1 x8976 -1 x8977 -1 x8978 -1 x8979 -1 x8980 -1 x8981 -1 x8982 -1 x8983 -1 x8984 -1 x8985 -1 x8986 -1 x8987 -1 x8988 -1 x8989 -1 x8990 -1 x8991 -1 x8992 -1 x8993 -1 x8994 -1 x8995 -1 x8996 -1 x8997 -1 x8998 -1 x8999 -1 x9000 -1 x9001 -1 x9002 -1 x9003 -1 x9004 -1 x9005 -1 x9006 -1 x9007 -1 x9008 -1 x9009 -1 x9010 -1 x9011 -1 x9012 -1 x9013 -1 x9014 -1 x9015 -1 x9016 -1 x9017 -1 x9018 -1 x9019 -1 x9020 -1 x9021 -1 x9022 -1 x9023 -1 x9024 -1 x9025 -1 x9026 -1 x9027 -1 x9028 -1 x9029 -1 x9030 -1 x9031 -1 x9032 -1 x9033 -1 x9034 -1 x9035 -1 x9036 -1 x9037 -1 x9038 -1 x9039 -1 x9040 -1 x9041 -1 x9042 -1 x9043 -1 x9044 -1 x9045 -1 x9046 -1 x9047 -1 x9048 -1 x9049 -1 x9050 -1 x9051 -1 x9052 -1 x9053 -1 x9054 -1 x9055 -1 x9056 -1 x9057 -1 x9058 -1 x9059 -1 x9060 -1 x9061 -1 x9062 -1 x9063 -1 x9064 -1 x9065 -1 x9066 -1 x9067 -1 x9068 -1 x9069 -1 x9070 -1 x9071 -1 x9072 -1 x9073 -1 x9074 -1 x9075 -1 x9076 -1 x9077 -1 x9078 -1 x9079 -1 x9080 -1 x9081 -1 x9082 -1 x9083 -1 x9084 -1 x9085 -1 x9086 -1 x9087 -1 x9088 >= -1 ;+-1 x9089 -1 x9090 -1 x9091 -1 x9092 -1 x9093 -1 x9094 -1 x9095 -1 x9096 -1 x9097 -1 x9098 -1 x9099 -1 x9100 -1 x9101 -1 x9102 -1 x9103 -1 x9104 -1 x9105 -1 x9106 -1 x9107 -1 x9108 -1 x9109 -1 x9110 -1 x9111 -1 x9112 -1 x9113 -1 x9114 -1 x9115 -1 x9116 -1 x9117 -1 x9118 -1 x9119 -1 x9120 -1 x9121 -1 x9122 -1 x9123 -1 x9124 -1 x9125 -1 x9126 -1 x9127 -1 x9128 -1 x9129 -1 x9130 -1 x9131 -1 x9132 -1 x9133 -1 x9134 -1 x9135 -1 x9136 -1 x9137 -1 x9138 -1 x9139 -1 x9140 -1 x9141 -1 x9142 -1 x9143 -1 x9144 -1 x9145 -1 x9146 -1 x9147 -1 x9148 -1 x9149 -1 x9150 -1 x9151 -1 x9152 -1 x9153 -1 x9154 -1 x9155 -1 x9156 -1 x9157 -1 x9158 -1 x9159 -1 x9160 -1 x9161 -1 x9162 -1 x9163 -1 x9164 -1 x9165 -1 x9166 -1 x9167 -1 x9168 -1 x9169 -1 x9170 -1 x9171 -1 x9172 -1 x9173 -1 x9174 -1 x9175 -1 x9176 -1 x9177 -1 x9178 -1 x9179 -1 x9180 -1 x9181 -1 x9182 -1 x9183 -1 x9184 -1 x9185 -1 x9186 -1 x9187 -1 x9188 -1 x9189 -1 x9190 -1 x9191 -1 x9192 -1 x9193 -1 x9194 -1 x9195 -1 x9196 -1 x9197 -1 x9198 -1 x9199 -1 x9200 -1 x9201 -1 x9202 -1 x9203 -1 x9204 -1 x9205 -1 x9206 -1 x9207 -1 x9208 -1 x9209 -1 x9210 -1 x9211 -1 x9212 -1 x9213 -1 x9214 -1 x9215 -1 x9216 >= -1 ;+-1 x9217 -1 x9218 -1 x9219 -1 x9220 -1 x9221 -1 x9222 -1 x9223 -1 x9224 -1 x9225 -1 x9226 -1 x9227 -1 x9228 -1 x9229 -1 x9230 -1 x9231 -1 x9232 -1 x9233 -1 x9234 -1 x9235 -1 x9236 -1 x9237 -1 x9238 -1 x9239 -1 x9240 -1 x9241 -1 x9242 -1 x9243 -1 x9244 -1 x9245 -1 x9246 -1 x9247 -1 x9248 -1 x9249 -1 x9250 -1 x9251 -1 x9252 -1 x9253 -1 x9254 -1 x9255 -1 x9256 -1 x9257 -1 x9258 -1 x9259 -1 x9260 -1 x9261 -1 x9262 -1 x9263 -1 x9264 -1 x9265 -1 x9266 -1 x9267 -1 x9268 -1 x9269 -1 x9270 -1 x9271 -1 x9272 -1 x9273 -1 x9274 -1 x9275 -1 x9276 -1 x9277 -1 x9278 -1 x9279 -1 x9280 -1 x9281 -1 x9282 -1 x9283 -1 x9284 -1 x9285 -1 x9286 -1 x9287 -1 x9288 -1 x9289 -1 x9290 -1 x9291 -1 x9292 -1 x9293 -1 x9294 -1 x9295 -1 x9296 -1 x9297 -1 x9298 -1 x9299 -1 x9300 -1 x9301 -1 x9302 -1 x9303 -1 x9304 -1 x9305 -1 x9306 -1 x9307 -1 x9308 -1 x9309 -1 x9310 -1 x9311 -1 x9312 -1 x9313 -1 x9314 -1 x9315 -1 x9316 -1 x9317 -1 x9318 -1 x9319 -1 x9320 -1 x9321 -1 x9322 -1 x9323 -1 x9324 -1 x9325 -1 x9326 -1 x9327 -1 x9328 -1 x9329 -1 x9330 -1 x9331 -1 x9332 -1 x9333 -1 x9334 -1 x9335 -1 x9336 -1 x9337 -1 x9338 -1 x9339 -1 x9340 -1 x9341 -1 x9342 -1 x9343 -1 x9344 >= -1 ;+-1 x9345 -1 x9346 -1 x9347 -1 x9348 -1 x9349 -1 x9350 -1 x9351 -1 x9352 -1 x9353 -1 x9354 -1 x9355 -1 x9356 -1 x9357 -1 x9358 -1 x9359 -1 x9360 -1 x9361 -1 x9362 -1 x9363 -1 x9364 -1 x9365 -1 x9366 -1 x9367 -1 x9368 -1 x9369 -1 x9370 -1 x9371 -1 x9372 -1 x9373 -1 x9374 -1 x9375 -1 x9376 -1 x9377 -1 x9378 -1 x9379 -1 x9380 -1 x9381 -1 x9382 -1 x9383 -1 x9384 -1 x9385 -1 x9386 -1 x9387 -1 x9388 -1 x9389 -1 x9390 -1 x9391 -1 x9392 -1 x9393 -1 x9394 -1 x9395 -1 x9396 -1 x9397 -1 x9398 -1 x9399 -1 x9400 -1 x9401 -1 x9402 -1 x9403 -1 x9404 -1 x9405 -1 x9406 -1 x9407 -1 x9408 -1 x9409 -1 x9410 -1 x9411 -1 x9412 -1 x9413 -1 x9414 -1 x9415 -1 x9416 -1 x9417 -1 x9418 -1 x9419 -1 x9420 -1 x9421 -1 x9422 -1 x9423 -1 x9424 -1 x9425 -1 x9426 -1 x9427 -1 x9428 -1 x9429 -1 x9430 -1 x9431 -1 x9432 -1 x9433 -1 x9434 -1 x9435 -1 x9436 -1 x9437 -1 x9438 -1 x9439 -1 x9440 -1 x9441 -1 x9442 -1 x9443 -1 x9444 -1 x9445 -1 x9446 -1 x9447 -1 x9448 -1 x9449 -1 x9450 -1 x9451 -1 x9452 -1 x9453 -1 x9454 -1 x9455 -1 x9456 -1 x9457 -1 x9458 -1 x9459 -1 x9460 -1 x9461 -1 x9462 -1 x9463 -1 x9464 -1 x9465 -1 x9466 -1 x9467 -1 x9468 -1 x9469 -1 x9470 -1 x9471 -1 x9472 >= -1 ;+-1 x9473 -1 x9474 -1 x9475 -1 x9476 -1 x9477 -1 x9478 -1 x9479 -1 x9480 -1 x9481 -1 x9482 -1 x9483 -1 x9484 -1 x9485 -1 x9486 -1 x9487 -1 x9488 -1 x9489 -1 x9490 -1 x9491 -1 x9492 -1 x9493 -1 x9494 -1 x9495 -1 x9496 -1 x9497 -1 x9498 -1 x9499 -1 x9500 -1 x9501 -1 x9502 -1 x9503 -1 x9504 -1 x9505 -1 x9506 -1 x9507 -1 x9508 -1 x9509 -1 x9510 -1 x9511 -1 x9512 -1 x9513 -1 x9514 -1 x9515 -1 x9516 -1 x9517 -1 x9518 -1 x9519 -1 x9520 -1 x9521 -1 x9522 -1 x9523 -1 x9524 -1 x9525 -1 x9526 -1 x9527 -1 x9528 -1 x9529 -1 x9530 -1 x9531 -1 x9532 -1 x9533 -1 x9534 -1 x9535 -1 x9536 -1 x9537 -1 x9538 -1 x9539 -1 x9540 -1 x9541 -1 x9542 -1 x9543 -1 x9544 -1 x9545 -1 x9546 -1 x9547 -1 x9548 -1 x9549 -1 x9550 -1 x9551 -1 x9552 -1 x9553 -1 x9554 -1 x9555 -1 x9556 -1 x9557 -1 x9558 -1 x9559 -1 x9560 -1 x9561 -1 x9562 -1 x9563 -1 x9564 -1 x9565 -1 x9566 -1 x9567 -1 x9568 -1 x9569 -1 x9570 -1 x9571 -1 x9572 -1 x9573 -1 x9574 -1 x9575 -1 x9576 -1 x9577 -1 x9578 -1 x9579 -1 x9580 -1 x9581 -1 x9582 -1 x9583 -1 x9584 -1 x9585 -1 x9586 -1 x9587 -1 x9588 -1 x9589 -1 x9590 -1 x9591 -1 x9592 -1 x9593 -1 x9594 -1 x9595 -1 x9596 -1 x9597 -1 x9598 -1 x9599 -1 x9600 >= -1 ;+-1 x9601 -1 x9602 -1 x9603 -1 x9604 -1 x9605 -1 x9606 -1 x9607 -1 x9608 -1 x9609 -1 x9610 -1 x9611 -1 x9612 -1 x9613 -1 x9614 -1 x9615 -1 x9616 -1 x9617 -1 x9618 -1 x9619 -1 x9620 -1 x9621 -1 x9622 -1 x9623 -1 x9624 -1 x9625 -1 x9626 -1 x9627 -1 x9628 -1 x9629 -1 x9630 -1 x9631 -1 x9632 -1 x9633 -1 x9634 -1 x9635 -1 x9636 -1 x9637 -1 x9638 -1 x9639 -1 x9640 -1 x9641 -1 x9642 -1 x9643 -1 x9644 -1 x9645 -1 x9646 -1 x9647 -1 x9648 -1 x9649 -1 x9650 -1 x9651 -1 x9652 -1 x9653 -1 x9654 -1 x9655 -1 x9656 -1 x9657 -1 x9658 -1 x9659 -1 x9660 -1 x9661 -1 x9662 -1 x9663 -1 x9664 -1 x9665 -1 x9666 -1 x9667 -1 x9668 -1 x9669 -1 x9670 -1 x9671 -1 x9672 -1 x9673 -1 x9674 -1 x9675 -1 x9676 -1 x9677 -1 x9678 -1 x9679 -1 x9680 -1 x9681 -1 x9682 -1 x9683 -1 x9684 -1 x9685 -1 x9686 -1 x9687 -1 x9688 -1 x9689 -1 x9690 -1 x9691 -1 x9692 -1 x9693 -1 x9694 -1 x9695 -1 x9696 -1 x9697 -1 x9698 -1 x9699 -1 x9700 -1 x9701 -1 x9702 -1 x9703 -1 x9704 -1 x9705 -1 x9706 -1 x9707 -1 x9708 -1 x9709 -1 x9710 -1 x9711 -1 x9712 -1 x9713 -1 x9714 -1 x9715 -1 x9716 -1 x9717 -1 x9718 -1 x9719 -1 x9720 -1 x9721 -1 x9722 -1 x9723 -1 x9724 -1 x9725 -1 x9726 -1 x9727 -1 x9728 >= -1 ;+-1 x9729 -1 x9730 -1 x9731 -1 x9732 -1 x9733 -1 x9734 -1 x9735 -1 x9736 -1 x9737 -1 x9738 -1 x9739 -1 x9740 -1 x9741 -1 x9742 -1 x9743 -1 x9744 -1 x9745 -1 x9746 -1 x9747 -1 x9748 -1 x9749 -1 x9750 -1 x9751 -1 x9752 -1 x9753 -1 x9754 -1 x9755 -1 x9756 -1 x9757 -1 x9758 -1 x9759 -1 x9760 -1 x9761 -1 x9762 -1 x9763 -1 x9764 -1 x9765 -1 x9766 -1 x9767 -1 x9768 -1 x9769 -1 x9770 -1 x9771 -1 x9772 -1 x9773 -1 x9774 -1 x9775 -1 x9776 -1 x9777 -1 x9778 -1 x9779 -1 x9780 -1 x9781 -1 x9782 -1 x9783 -1 x9784 -1 x9785 -1 x9786 -1 x9787 -1 x9788 -1 x9789 -1 x9790 -1 x9791 -1 x9792 -1 x9793 -1 x9794 -1 x9795 -1 x9796 -1 x9797 -1 x9798 -1 x9799 -1 x9800 -1 x9801 -1 x9802 -1 x9803 -1 x9804 -1 x9805 -1 x9806 -1 x9807 -1 x9808 -1 x9809 -1 x9810 -1 x9811 -1 x9812 -1 x9813 -1 x9814 -1 x9815 -1 x9816 -1 x9817 -1 x9818 -1 x9819 -1 x9820 -1 x9821 -1 x9822 -1 x9823 -1 x9824 -1 x9825 -1 x9826 -1 x9827 -1 x9828 -1 x9829 -1 x9830 -1 x9831 -1 x9832 -1 x9833 -1 x9834 -1 x9835 -1 x9836 -1 x9837 -1 x9838 -1 x9839 -1 x9840 -1 x9841 -1 x9842 -1 x9843 -1 x9844 -1 x9845 -1 x9846 -1 x9847 -1 x9848 -1 x9849 -1 x9850 -1 x9851 -1 x9852 -1 x9853 -1 x9854 -1 x9855 -1 x9856 >= -1 ;+-1 x9857 -1 x9858 -1 x9859 -1 x9860 -1 x9861 -1 x9862 -1 x9863 -1 x9864 -1 x9865 -1 x9866 -1 x9867 -1 x9868 -1 x9869 -1 x9870 -1 x9871 -1 x9872 -1 x9873 -1 x9874 -1 x9875 -1 x9876 -1 x9877 -1 x9878 -1 x9879 -1 x9880 -1 x9881 -1 x9882 -1 x9883 -1 x9884 -1 x9885 -1 x9886 -1 x9887 -1 x9888 -1 x9889 -1 x9890 -1 x9891 -1 x9892 -1 x9893 -1 x9894 -1 x9895 -1 x9896 -1 x9897 -1 x9898 -1 x9899 -1 x9900 -1 x9901 -1 x9902 -1 x9903 -1 x9904 -1 x9905 -1 x9906 -1 x9907 -1 x9908 -1 x9909 -1 x9910 -1 x9911 -1 x9912 -1 x9913 -1 x9914 -1 x9915 -1 x9916 -1 x9917 -1 x9918 -1 x9919 -1 x9920 -1 x9921 -1 x9922 -1 x9923 -1 x9924 -1 x9925 -1 x9926 -1 x9927 -1 x9928 -1 x9929 -1 x9930 -1 x9931 -1 x9932 -1 x9933 -1 x9934 -1 x9935 -1 x9936 -1 x9937 -1 x9938 -1 x9939 -1 x9940 -1 x9941 -1 x9942 -1 x9943 -1 x9944 -1 x9945 -1 x9946 -1 x9947 -1 x9948 -1 x9949 -1 x9950 -1 x9951 -1 x9952 -1 x9953 -1 x9954 -1 x9955 -1 x9956 -1 x9957 -1 x9958 -1 x9959 -1 x9960 -1 x9961 -1 x9962 -1 x9963 -1 x9964 -1 x9965 -1 x9966 -1 x9967 -1 x9968 -1 x9969 -1 x9970 -1 x9971 -1 x9972 -1 x9973 -1 x9974 -1 x9975 -1 x9976 -1 x9977 -1 x9978 -1 x9979 -1 x9980 -1 x9981 -1 x9982 -1 x9983 -1 x9984 >= -1 ;+-1 x9985 -1 x9986 -1 x9987 -1 x9988 -1 x9989 -1 x9990 -1 x9991 -1 x9992 -1 x9993 -1 x9994 -1 x9995 -1 x9996 -1 x9997 -1 x9998 -1 x9999 -1 x10000 -1 x10001 -1 x10002 -1 x10003 -1 x10004 -1 x10005 -1 x10006 -1 x10007 -1 x10008 -1 x10009 -1 x10010 -1 x10011 -1 x10012 -1 x10013 -1 x10014 -1 x10015 -1 x10016 -1 x10017 -1 x10018 -1 x10019 -1 x10020 -1 x10021 -1 x10022 -1 x10023 -1 x10024 -1 x10025 -1 x10026 -1 x10027 -1 x10028 -1 x10029 -1 x10030 -1 x10031 -1 x10032 -1 x10033 -1 x10034 -1 x10035 -1 x10036 -1 x10037 -1 x10038 -1 x10039 -1 x10040 -1 x10041 -1 x10042 -1 x10043 -1 x10044 -1 x10045 -1 x10046 -1 x10047 -1 x10048 -1 x10049 -1 x10050 -1 x10051 -1 x10052 -1 x10053 -1 x10054 -1 x10055 -1 x10056 -1 x10057 -1 x10058 -1 x10059 -1 x10060 -1 x10061 -1 x10062 -1 x10063 -1 x10064 -1 x10065 -1 x10066 -1 x10067 -1 x10068 -1 x10069 -1 x10070 -1 x10071 -1 x10072 -1 x10073 -1 x10074 -1 x10075 -1 x10076 -1 x10077 -1 x10078 -1 x10079 -1 x10080 -1 x10081 -1 x10082 -1 x10083 -1 x10084 -1 x10085 -1 x10086 -1 x10087 -1 x10088 -1 x10089 -1 x10090 -1 x10091 -1 x10092 -1 x10093 -1 x10094 -1 x10095 -1 x10096 -1 x10097 -1 x10098 -1 x10099 -1 x10100 -1 x10101 -1 x10102 -1 x10103 -1 x10104 -1 x10105 -1 x10106 -1 x10107 -1 x10108 -1 x10109 -1 x10110 -1 x10111 -1 x10112 >= -1 ;+-1 x10113 -1 x10114 -1 x10115 -1 x10116 -1 x10117 -1 x10118 -1 x10119 -1 x10120 -1 x10121 -1 x10122 -1 x10123 -1 x10124 -1 x10125 -1 x10126 -1 x10127 -1 x10128 -1 x10129 -1 x10130 -1 x10131 -1 x10132 -1 x10133 -1 x10134 -1 x10135 -1 x10136 -1 x10137 -1 x10138 -1 x10139 -1 x10140 -1 x10141 -1 x10142 -1 x10143 -1 x10144 -1 x10145 -1 x10146 -1 x10147 -1 x10148 -1 x10149 -1 x10150 -1 x10151 -1 x10152 -1 x10153 -1 x10154 -1 x10155 -1 x10156 -1 x10157 -1 x10158 -1 x10159 -1 x10160 -1 x10161 -1 x10162 -1 x10163 -1 x10164 -1 x10165 -1 x10166 -1 x10167 -1 x10168 -1 x10169 -1 x10170 -1 x10171 -1 x10172 -1 x10173 -1 x10174 -1 x10175 -1 x10176 -1 x10177 -1 x10178 -1 x10179 -1 x10180 -1 x10181 -1 x10182 -1 x10183 -1 x10184 -1 x10185 -1 x10186 -1 x10187 -1 x10188 -1 x10189 -1 x10190 -1 x10191 -1 x10192 -1 x10193 -1 x10194 -1 x10195 -1 x10196 -1 x10197 -1 x10198 -1 x10199 -1 x10200 -1 x10201 -1 x10202 -1 x10203 -1 x10204 -1 x10205 -1 x10206 -1 x10207 -1 x10208 -1 x10209 -1 x10210 -1 x10211 -1 x10212 -1 x10213 -1 x10214 -1 x10215 -1 x10216 -1 x10217 -1 x10218 -1 x10219 -1 x10220 -1 x10221 -1 x10222 -1 x10223 -1 x10224 -1 x10225 -1 x10226 -1 x10227 -1 x10228 -1 x10229 -1 x10230 -1 x10231 -1 x10232 -1 x10233 -1 x10234 -1 x10235 -1 x10236 -1 x10237 -1 x10238 -1 x10239 -1 x10240 >= -1 ;+-1 x10241 -1 x10242 -1 x10243 -1 x10244 -1 x10245 -1 x10246 -1 x10247 -1 x10248 -1 x10249 -1 x10250 -1 x10251 -1 x10252 -1 x10253 -1 x10254 -1 x10255 -1 x10256 -1 x10257 -1 x10258 -1 x10259 -1 x10260 -1 x10261 -1 x10262 -1 x10263 -1 x10264 -1 x10265 -1 x10266 -1 x10267 -1 x10268 -1 x10269 -1 x10270 -1 x10271 -1 x10272 -1 x10273 -1 x10274 -1 x10275 -1 x10276 -1 x10277 -1 x10278 -1 x10279 -1 x10280 -1 x10281 -1 x10282 -1 x10283 -1 x10284 -1 x10285 -1 x10286 -1 x10287 -1 x10288 -1 x10289 -1 x10290 -1 x10291 -1 x10292 -1 x10293 -1 x10294 -1 x10295 -1 x10296 -1 x10297 -1 x10298 -1 x10299 -1 x10300 -1 x10301 -1 x10302 -1 x10303 -1 x10304 -1 x10305 -1 x10306 -1 x10307 -1 x10308 -1 x10309 -1 x10310 -1 x10311 -1 x10312 -1 x10313 -1 x10314 -1 x10315 -1 x10316 -1 x10317 -1 x10318 -1 x10319 -1 x10320 -1 x10321 -1 x10322 -1 x10323 -1 x10324 -1 x10325 -1 x10326 -1 x10327 -1 x10328 -1 x10329 -1 x10330 -1 x10331 -1 x10332 -1 x10333 -1 x10334 -1 x10335 -1 x10336 -1 x10337 -1 x10338 -1 x10339 -1 x10340 -1 x10341 -1 x10342 -1 x10343 -1 x10344 -1 x10345 -1 x10346 -1 x10347 -1 x10348 -1 x10349 -1 x10350 -1 x10351 -1 x10352 -1 x10353 -1 x10354 -1 x10355 -1 x10356 -1 x10357 -1 x10358 -1 x10359 -1 x10360 -1 x10361 -1 x10362 -1 x10363 -1 x10364 -1 x10365 -1 x10366 -1 x10367 -1 x10368 >= -1 ;+-1 x10369 -1 x10370 -1 x10371 -1 x10372 -1 x10373 -1 x10374 -1 x10375 -1 x10376 -1 x10377 -1 x10378 -1 x10379 -1 x10380 -1 x10381 -1 x10382 -1 x10383 -1 x10384 -1 x10385 -1 x10386 -1 x10387 -1 x10388 -1 x10389 -1 x10390 -1 x10391 -1 x10392 -1 x10393 -1 x10394 -1 x10395 -1 x10396 -1 x10397 -1 x10398 -1 x10399 -1 x10400 -1 x10401 -1 x10402 -1 x10403 -1 x10404 -1 x10405 -1 x10406 -1 x10407 -1 x10408 -1 x10409 -1 x10410 -1 x10411 -1 x10412 -1 x10413 -1 x10414 -1 x10415 -1 x10416 -1 x10417 -1 x10418 -1 x10419 -1 x10420 -1 x10421 -1 x10422 -1 x10423 -1 x10424 -1 x10425 -1 x10426 -1 x10427 -1 x10428 -1 x10429 -1 x10430 -1 x10431 -1 x10432 -1 x10433 -1 x10434 -1 x10435 -1 x10436 -1 x10437 -1 x10438 -1 x10439 -1 x10440 -1 x10441 -1 x10442 -1 x10443 -1 x10444 -1 x10445 -1 x10446 -1 x10447 -1 x10448 -1 x10449 -1 x10450 -1 x10451 -1 x10452 -1 x10453 -1 x10454 -1 x10455 -1 x10456 -1 x10457 -1 x10458 -1 x10459 -1 x10460 -1 x10461 -1 x10462 -1 x10463 -1 x10464 -1 x10465 -1 x10466 -1 x10467 -1 x10468 -1 x10469 -1 x10470 -1 x10471 -1 x10472 -1 x10473 -1 x10474 -1 x10475 -1 x10476 -1 x10477 -1 x10478 -1 x10479 -1 x10480 -1 x10481 -1 x10482 -1 x10483 -1 x10484 -1 x10485 -1 x10486 -1 x10487 -1 x10488 -1 x10489 -1 x10490 -1 x10491 -1 x10492 -1 x10493 -1 x10494 -1 x10495 -1 x10496 >= -1 ;+-1 x10497 -1 x10498 -1 x10499 -1 x10500 -1 x10501 -1 x10502 -1 x10503 -1 x10504 -1 x10505 -1 x10506 -1 x10507 -1 x10508 -1 x10509 -1 x10510 -1 x10511 -1 x10512 -1 x10513 -1 x10514 -1 x10515 -1 x10516 -1 x10517 -1 x10518 -1 x10519 -1 x10520 -1 x10521 -1 x10522 -1 x10523 -1 x10524 -1 x10525 -1 x10526 -1 x10527 -1 x10528 -1 x10529 -1 x10530 -1 x10531 -1 x10532 -1 x10533 -1 x10534 -1 x10535 -1 x10536 -1 x10537 -1 x10538 -1 x10539 -1 x10540 -1 x10541 -1 x10542 -1 x10543 -1 x10544 -1 x10545 -1 x10546 -1 x10547 -1 x10548 -1 x10549 -1 x10550 -1 x10551 -1 x10552 -1 x10553 -1 x10554 -1 x10555 -1 x10556 -1 x10557 -1 x10558 -1 x10559 -1 x10560 -1 x10561 -1 x10562 -1 x10563 -1 x10564 -1 x10565 -1 x10566 -1 x10567 -1 x10568 -1 x10569 -1 x10570 -1 x10571 -1 x10572 -1 x10573 -1 x10574 -1 x10575 -1 x10576 -1 x10577 -1 x10578 -1 x10579 -1 x10580 -1 x10581 -1 x10582 -1 x10583 -1 x10584 -1 x10585 -1 x10586 -1 x10587 -1 x10588 -1 x10589 -1 x10590 -1 x10591 -1 x10592 -1 x10593 -1 x10594 -1 x10595 -1 x10596 -1 x10597 -1 x10598 -1 x10599 -1 x10600 -1 x10601 -1 x10602 -1 x10603 -1 x10604 -1 x10605 -1 x10606 -1 x10607 -1 x10608 -1 x10609 -1 x10610 -1 x10611 -1 x10612 -1 x10613 -1 x10614 -1 x10615 -1 x10616 -1 x10617 -1 x10618 -1 x10619 -1 x10620 -1 x10621 -1 x10622 -1 x10623 -1 x10624 >= -1 ;+-1 x10625 -1 x10626 -1 x10627 -1 x10628 -1 x10629 -1 x10630 -1 x10631 -1 x10632 -1 x10633 -1 x10634 -1 x10635 -1 x10636 -1 x10637 -1 x10638 -1 x10639 -1 x10640 -1 x10641 -1 x10642 -1 x10643 -1 x10644 -1 x10645 -1 x10646 -1 x10647 -1 x10648 -1 x10649 -1 x10650 -1 x10651 -1 x10652 -1 x10653 -1 x10654 -1 x10655 -1 x10656 -1 x10657 -1 x10658 -1 x10659 -1 x10660 -1 x10661 -1 x10662 -1 x10663 -1 x10664 -1 x10665 -1 x10666 -1 x10667 -1 x10668 -1 x10669 -1 x10670 -1 x10671 -1 x10672 -1 x10673 -1 x10674 -1 x10675 -1 x10676 -1 x10677 -1 x10678 -1 x10679 -1 x10680 -1 x10681 -1 x10682 -1 x10683 -1 x10684 -1 x10685 -1 x10686 -1 x10687 -1 x10688 -1 x10689 -1 x10690 -1 x10691 -1 x10692 -1 x10693 -1 x10694 -1 x10695 -1 x10696 -1 x10697 -1 x10698 -1 x10699 -1 x10700 -1 x10701 -1 x10702 -1 x10703 -1 x10704 -1 x10705 -1 x10706 -1 x10707 -1 x10708 -1 x10709 -1 x10710 -1 x10711 -1 x10712 -1 x10713 -1 x10714 -1 x10715 -1 x10716 -1 x10717 -1 x10718 -1 x10719 -1 x10720 -1 x10721 -1 x10722 -1 x10723 -1 x10724 -1 x10725 -1 x10726 -1 x10727 -1 x10728 -1 x10729 -1 x10730 -1 x10731 -1 x10732 -1 x10733 -1 x10734 -1 x10735 -1 x10736 -1 x10737 -1 x10738 -1 x10739 -1 x10740 -1 x10741 -1 x10742 -1 x10743 -1 x10744 -1 x10745 -1 x10746 -1 x10747 -1 x10748 -1 x10749 -1 x10750 -1 x10751 -1 x10752 >= -1 ;+-1 x10753 -1 x10754 -1 x10755 -1 x10756 -1 x10757 -1 x10758 -1 x10759 -1 x10760 -1 x10761 -1 x10762 -1 x10763 -1 x10764 -1 x10765 -1 x10766 -1 x10767 -1 x10768 -1 x10769 -1 x10770 -1 x10771 -1 x10772 -1 x10773 -1 x10774 -1 x10775 -1 x10776 -1 x10777 -1 x10778 -1 x10779 -1 x10780 -1 x10781 -1 x10782 -1 x10783 -1 x10784 -1 x10785 -1 x10786 -1 x10787 -1 x10788 -1 x10789 -1 x10790 -1 x10791 -1 x10792 -1 x10793 -1 x10794 -1 x10795 -1 x10796 -1 x10797 -1 x10798 -1 x10799 -1 x10800 -1 x10801 -1 x10802 -1 x10803 -1 x10804 -1 x10805 -1 x10806 -1 x10807 -1 x10808 -1 x10809 -1 x10810 -1 x10811 -1 x10812 -1 x10813 -1 x10814 -1 x10815 -1 x10816 -1 x10817 -1 x10818 -1 x10819 -1 x10820 -1 x10821 -1 x10822 -1 x10823 -1 x10824 -1 x10825 -1 x10826 -1 x10827 -1 x10828 -1 x10829 -1 x10830 -1 x10831 -1 x10832 -1 x10833 -1 x10834 -1 x10835 -1 x10836 -1 x10837 -1 x10838 -1 x10839 -1 x10840 -1 x10841 -1 x10842 -1 x10843 -1 x10844 -1 x10845 -1 x10846 -1 x10847 -1 x10848 -1 x10849 -1 x10850 -1 x10851 -1 x10852 -1 x10853 -1 x10854 -1 x10855 -1 x10856 -1 x10857 -1 x10858 -1 x10859 -1 x10860 -1 x10861 -1 x10862 -1 x10863 -1 x10864 -1 x10865 -1 x10866 -1 x10867 -1 x10868 -1 x10869 -1 x10870 -1 x10871 -1 x10872 -1 x10873 -1 x10874 -1 x10875 -1 x10876 -1 x10877 -1 x10878 -1 x10879 -1 x10880 >= -1 ;+-1 x10881 -1 x10882 -1 x10883 -1 x10884 -1 x10885 -1 x10886 -1 x10887 -1 x10888 -1 x10889 -1 x10890 -1 x10891 -1 x10892 -1 x10893 -1 x10894 -1 x10895 -1 x10896 -1 x10897 -1 x10898 -1 x10899 -1 x10900 -1 x10901 -1 x10902 -1 x10903 -1 x10904 -1 x10905 -1 x10906 -1 x10907 -1 x10908 -1 x10909 -1 x10910 -1 x10911 -1 x10912 -1 x10913 -1 x10914 -1 x10915 -1 x10916 -1 x10917 -1 x10918 -1 x10919 -1 x10920 -1 x10921 -1 x10922 -1 x10923 -1 x10924 -1 x10925 -1 x10926 -1 x10927 -1 x10928 -1 x10929 -1 x10930 -1 x10931 -1 x10932 -1 x10933 -1 x10934 -1 x10935 -1 x10936 -1 x10937 -1 x10938 -1 x10939 -1 x10940 -1 x10941 -1 x10942 -1 x10943 -1 x10944 -1 x10945 -1 x10946 -1 x10947 -1 x10948 -1 x10949 -1 x10950 -1 x10951 -1 x10952 -1 x10953 -1 x10954 -1 x10955 -1 x10956 -1 x10957 -1 x10958 -1 x10959 -1 x10960 -1 x10961 -1 x10962 -1 x10963 -1 x10964 -1 x10965 -1 x10966 -1 x10967 -1 x10968 -1 x10969 -1 x10970 -1 x10971 -1 x10972 -1 x10973 -1 x10974 -1 x10975 -1 x10976 -1 x10977 -1 x10978 -1 x10979 -1 x10980 -1 x10981 -1 x10982 -1 x10983 -1 x10984 -1 x10985 -1 x10986 -1 x10987 -1 x10988 -1 x10989 -1 x10990 -1 x10991 -1 x10992 -1 x10993 -1 x10994 -1 x10995 -1 x10996 -1 x10997 -1 x10998 -1 x10999 -1 x11000 -1 x11001 -1 x11002 -1 x11003 -1 x11004 -1 x11005 -1 x11006 -1 x11007 -1 x11008 >= -1 ;+-1 x11009 -1 x11010 -1 x11011 -1 x11012 -1 x11013 -1 x11014 -1 x11015 -1 x11016 -1 x11017 -1 x11018 -1 x11019 -1 x11020 -1 x11021 -1 x11022 -1 x11023 -1 x11024 -1 x11025 -1 x11026 -1 x11027 -1 x11028 -1 x11029 -1 x11030 -1 x11031 -1 x11032 -1 x11033 -1 x11034 -1 x11035 -1 x11036 -1 x11037 -1 x11038 -1 x11039 -1 x11040 -1 x11041 -1 x11042 -1 x11043 -1 x11044 -1 x11045 -1 x11046 -1 x11047 -1 x11048 -1 x11049 -1 x11050 -1 x11051 -1 x11052 -1 x11053 -1 x11054 -1 x11055 -1 x11056 -1 x11057 -1 x11058 -1 x11059 -1 x11060 -1 x11061 -1 x11062 -1 x11063 -1 x11064 -1 x11065 -1 x11066 -1 x11067 -1 x11068 -1 x11069 -1 x11070 -1 x11071 -1 x11072 -1 x11073 -1 x11074 -1 x11075 -1 x11076 -1 x11077 -1 x11078 -1 x11079 -1 x11080 -1 x11081 -1 x11082 -1 x11083 -1 x11084 -1 x11085 -1 x11086 -1 x11087 -1 x11088 -1 x11089 -1 x11090 -1 x11091 -1 x11092 -1 x11093 -1 x11094 -1 x11095 -1 x11096 -1 x11097 -1 x11098 -1 x11099 -1 x11100 -1 x11101 -1 x11102 -1 x11103 -1 x11104 -1 x11105 -1 x11106 -1 x11107 -1 x11108 -1 x11109 -1 x11110 -1 x11111 -1 x11112 -1 x11113 -1 x11114 -1 x11115 -1 x11116 -1 x11117 -1 x11118 -1 x11119 -1 x11120 -1 x11121 -1 x11122 -1 x11123 -1 x11124 -1 x11125 -1 x11126 -1 x11127 -1 x11128 -1 x11129 -1 x11130 -1 x11131 -1 x11132 -1 x11133 -1 x11134 -1 x11135 -1 x11136 >= -1 ;+-1 x11137 -1 x11138 -1 x11139 -1 x11140 -1 x11141 -1 x11142 -1 x11143 -1 x11144 -1 x11145 -1 x11146 -1 x11147 -1 x11148 -1 x11149 -1 x11150 -1 x11151 -1 x11152 -1 x11153 -1 x11154 -1 x11155 -1 x11156 -1 x11157 -1 x11158 -1 x11159 -1 x11160 -1 x11161 -1 x11162 -1 x11163 -1 x11164 -1 x11165 -1 x11166 -1 x11167 -1 x11168 -1 x11169 -1 x11170 -1 x11171 -1 x11172 -1 x11173 -1 x11174 -1 x11175 -1 x11176 -1 x11177 -1 x11178 -1 x11179 -1 x11180 -1 x11181 -1 x11182 -1 x11183 -1 x11184 -1 x11185 -1 x11186 -1 x11187 -1 x11188 -1 x11189 -1 x11190 -1 x11191 -1 x11192 -1 x11193 -1 x11194 -1 x11195 -1 x11196 -1 x11197 -1 x11198 -1 x11199 -1 x11200 -1 x11201 -1 x11202 -1 x11203 -1 x11204 -1 x11205 -1 x11206 -1 x11207 -1 x11208 -1 x11209 -1 x11210 -1 x11211 -1 x11212 -1 x11213 -1 x11214 -1 x11215 -1 x11216 -1 x11217 -1 x11218 -1 x11219 -1 x11220 -1 x11221 -1 x11222 -1 x11223 -1 x11224 -1 x11225 -1 x11226 -1 x11227 -1 x11228 -1 x11229 -1 x11230 -1 x11231 -1 x11232 -1 x11233 -1 x11234 -1 x11235 -1 x11236 -1 x11237 -1 x11238 -1 x11239 -1 x11240 -1 x11241 -1 x11242 -1 x11243 -1 x11244 -1 x11245 -1 x11246 -1 x11247 -1 x11248 -1 x11249 -1 x11250 -1 x11251 -1 x11252 -1 x11253 -1 x11254 -1 x11255 -1 x11256 -1 x11257 -1 x11258 -1 x11259 -1 x11260 -1 x11261 -1 x11262 -1 x11263 -1 x11264 >= -1 ;+-1 x11265 -1 x11266 -1 x11267 -1 x11268 -1 x11269 -1 x11270 -1 x11271 -1 x11272 -1 x11273 -1 x11274 -1 x11275 -1 x11276 -1 x11277 -1 x11278 -1 x11279 -1 x11280 -1 x11281 -1 x11282 -1 x11283 -1 x11284 -1 x11285 -1 x11286 -1 x11287 -1 x11288 -1 x11289 -1 x11290 -1 x11291 -1 x11292 -1 x11293 -1 x11294 -1 x11295 -1 x11296 -1 x11297 -1 x11298 -1 x11299 -1 x11300 -1 x11301 -1 x11302 -1 x11303 -1 x11304 -1 x11305 -1 x11306 -1 x11307 -1 x11308 -1 x11309 -1 x11310 -1 x11311 -1 x11312 -1 x11313 -1 x11314 -1 x11315 -1 x11316 -1 x11317 -1 x11318 -1 x11319 -1 x11320 -1 x11321 -1 x11322 -1 x11323 -1 x11324 -1 x11325 -1 x11326 -1 x11327 -1 x11328 -1 x11329 -1 x11330 -1 x11331 -1 x11332 -1 x11333 -1 x11334 -1 x11335 -1 x11336 -1 x11337 -1 x11338 -1 x11339 -1 x11340 -1 x11341 -1 x11342 -1 x11343 -1 x11344 -1 x11345 -1 x11346 -1 x11347 -1 x11348 -1 x11349 -1 x11350 -1 x11351 -1 x11352 -1 x11353 -1 x11354 -1 x11355 -1 x11356 -1 x11357 -1 x11358 -1 x11359 -1 x11360 -1 x11361 -1 x11362 -1 x11363 -1 x11364 -1 x11365 -1 x11366 -1 x11367 -1 x11368 -1 x11369 -1 x11370 -1 x11371 -1 x11372 -1 x11373 -1 x11374 -1 x11375 -1 x11376 -1 x11377 -1 x11378 -1 x11379 -1 x11380 -1 x11381 -1 x11382 -1 x11383 -1 x11384 -1 x11385 -1 x11386 -1 x11387 -1 x11388 -1 x11389 -1 x11390 -1 x11391 -1 x11392 >= -1 ;+-1 x11393 -1 x11394 -1 x11395 -1 x11396 -1 x11397 -1 x11398 -1 x11399 -1 x11400 -1 x11401 -1 x11402 -1 x11403 -1 x11404 -1 x11405 -1 x11406 -1 x11407 -1 x11408 -1 x11409 -1 x11410 -1 x11411 -1 x11412 -1 x11413 -1 x11414 -1 x11415 -1 x11416 -1 x11417 -1 x11418 -1 x11419 -1 x11420 -1 x11421 -1 x11422 -1 x11423 -1 x11424 -1 x11425 -1 x11426 -1 x11427 -1 x11428 -1 x11429 -1 x11430 -1 x11431 -1 x11432 -1 x11433 -1 x11434 -1 x11435 -1 x11436 -1 x11437 -1 x11438 -1 x11439 -1 x11440 -1 x11441 -1 x11442 -1 x11443 -1 x11444 -1 x11445 -1 x11446 -1 x11447 -1 x11448 -1 x11449 -1 x11450 -1 x11451 -1 x11452 -1 x11453 -1 x11454 -1 x11455 -1 x11456 -1 x11457 -1 x11458 -1 x11459 -1 x11460 -1 x11461 -1 x11462 -1 x11463 -1 x11464 -1 x11465 -1 x11466 -1 x11467 -1 x11468 -1 x11469 -1 x11470 -1 x11471 -1 x11472 -1 x11473 -1 x11474 -1 x11475 -1 x11476 -1 x11477 -1 x11478 -1 x11479 -1 x11480 -1 x11481 -1 x11482 -1 x11483 -1 x11484 -1 x11485 -1 x11486 -1 x11487 -1 x11488 -1 x11489 -1 x11490 -1 x11491 -1 x11492 -1 x11493 -1 x11494 -1 x11495 -1 x11496 -1 x11497 -1 x11498 -1 x11499 -1 x11500 -1 x11501 -1 x11502 -1 x11503 -1 x11504 -1 x11505 -1 x11506 -1 x11507 -1 x11508 -1 x11509 -1 x11510 -1 x11511 -1 x11512 -1 x11513 -1 x11514 -1 x11515 -1 x11516 -1 x11517 -1 x11518 -1 x11519 -1 x11520 >= -1 ;+-1 x11521 -1 x11522 -1 x11523 -1 x11524 -1 x11525 -1 x11526 -1 x11527 -1 x11528 -1 x11529 -1 x11530 -1 x11531 -1 x11532 -1 x11533 -1 x11534 -1 x11535 -1 x11536 -1 x11537 -1 x11538 -1 x11539 -1 x11540 -1 x11541 -1 x11542 -1 x11543 -1 x11544 -1 x11545 -1 x11546 -1 x11547 -1 x11548 -1 x11549 -1 x11550 -1 x11551 -1 x11552 -1 x11553 -1 x11554 -1 x11555 -1 x11556 -1 x11557 -1 x11558 -1 x11559 -1 x11560 -1 x11561 -1 x11562 -1 x11563 -1 x11564 -1 x11565 -1 x11566 -1 x11567 -1 x11568 -1 x11569 -1 x11570 -1 x11571 -1 x11572 -1 x11573 -1 x11574 -1 x11575 -1 x11576 -1 x11577 -1 x11578 -1 x11579 -1 x11580 -1 x11581 -1 x11582 -1 x11583 -1 x11584 -1 x11585 -1 x11586 -1 x11587 -1 x11588 -1 x11589 -1 x11590 -1 x11591 -1 x11592 -1 x11593 -1 x11594 -1 x11595 -1 x11596 -1 x11597 -1 x11598 -1 x11599 -1 x11600 -1 x11601 -1 x11602 -1 x11603 -1 x11604 -1 x11605 -1 x11606 -1 x11607 -1 x11608 -1 x11609 -1 x11610 -1 x11611 -1 x11612 -1 x11613 -1 x11614 -1 x11615 -1 x11616 -1 x11617 -1 x11618 -1 x11619 -1 x11620 -1 x11621 -1 x11622 -1 x11623 -1 x11624 -1 x11625 -1 x11626 -1 x11627 -1 x11628 -1 x11629 -1 x11630 -1 x11631 -1 x11632 -1 x11633 -1 x11634 -1 x11635 -1 x11636 -1 x11637 -1 x11638 -1 x11639 -1 x11640 -1 x11641 -1 x11642 -1 x11643 -1 x11644 -1 x11645 -1 x11646 -1 x11647 -1 x11648 >= -1 ;+-1 x11649 -1 x11650 -1 x11651 -1 x11652 -1 x11653 -1 x11654 -1 x11655 -1 x11656 -1 x11657 -1 x11658 -1 x11659 -1 x11660 -1 x11661 -1 x11662 -1 x11663 -1 x11664 -1 x11665 -1 x11666 -1 x11667 -1 x11668 -1 x11669 -1 x11670 -1 x11671 -1 x11672 -1 x11673 -1 x11674 -1 x11675 -1 x11676 -1 x11677 -1 x11678 -1 x11679 -1 x11680 -1 x11681 -1 x11682 -1 x11683 -1 x11684 -1 x11685 -1 x11686 -1 x11687 -1 x11688 -1 x11689 -1 x11690 -1 x11691 -1 x11692 -1 x11693 -1 x11694 -1 x11695 -1 x11696 -1 x11697 -1 x11698 -1 x11699 -1 x11700 -1 x11701 -1 x11702 -1 x11703 -1 x11704 -1 x11705 -1 x11706 -1 x11707 -1 x11708 -1 x11709 -1 x11710 -1 x11711 -1 x11712 -1 x11713 -1 x11714 -1 x11715 -1 x11716 -1 x11717 -1 x11718 -1 x11719 -1 x11720 -1 x11721 -1 x11722 -1 x11723 -1 x11724 -1 x11725 -1 x11726 -1 x11727 -1 x11728 -1 x11729 -1 x11730 -1 x11731 -1 x11732 -1 x11733 -1 x11734 -1 x11735 -1 x11736 -1 x11737 -1 x11738 -1 x11739 -1 x11740 -1 x11741 -1 x11742 -1 x11743 -1 x11744 -1 x11745 -1 x11746 -1 x11747 -1 x11748 -1 x11749 -1 x11750 -1 x11751 -1 x11752 -1 x11753 -1 x11754 -1 x11755 -1 x11756 -1 x11757 -1 x11758 -1 x11759 -1 x11760 -1 x11761 -1 x11762 -1 x11763 -1 x11764 -1 x11765 -1 x11766 -1 x11767 -1 x11768 -1 x11769 -1 x11770 -1 x11771 -1 x11772 -1 x11773 -1 x11774 -1 x11775 -1 x11776 >= -1 ;+-1 x11777 -1 x11778 -1 x11779 -1 x11780 -1 x11781 -1 x11782 -1 x11783 -1 x11784 -1 x11785 -1 x11786 -1 x11787 -1 x11788 -1 x11789 -1 x11790 -1 x11791 -1 x11792 -1 x11793 -1 x11794 -1 x11795 -1 x11796 -1 x11797 -1 x11798 -1 x11799 -1 x11800 -1 x11801 -1 x11802 -1 x11803 -1 x11804 -1 x11805 -1 x11806 -1 x11807 -1 x11808 -1 x11809 -1 x11810 -1 x11811 -1 x11812 -1 x11813 -1 x11814 -1 x11815 -1 x11816 -1 x11817 -1 x11818 -1 x11819 -1 x11820 -1 x11821 -1 x11822 -1 x11823 -1 x11824 -1 x11825 -1 x11826 -1 x11827 -1 x11828 -1 x11829 -1 x11830 -1 x11831 -1 x11832 -1 x11833 -1 x11834 -1 x11835 -1 x11836 -1 x11837 -1 x11838 -1 x11839 -1 x11840 -1 x11841 -1 x11842 -1 x11843 -1 x11844 -1 x11845 -1 x11846 -1 x11847 -1 x11848 -1 x11849 -1 x11850 -1 x11851 -1 x11852 -1 x11853 -1 x11854 -1 x11855 -1 x11856 -1 x11857 -1 x11858 -1 x11859 -1 x11860 -1 x11861 -1 x11862 -1 x11863 -1 x11864 -1 x11865 -1 x11866 -1 x11867 -1 x11868 -1 x11869 -1 x11870 -1 x11871 -1 x11872 -1 x11873 -1 x11874 -1 x11875 -1 x11876 -1 x11877 -1 x11878 -1 x11879 -1 x11880 -1 x11881 -1 x11882 -1 x11883 -1 x11884 -1 x11885 -1 x11886 -1 x11887 -1 x11888 -1 x11889 -1 x11890 -1 x11891 -1 x11892 -1 x11893 -1 x11894 -1 x11895 -1 x11896 -1 x11897 -1 x11898 -1 x11899 -1 x11900 -1 x11901 -1 x11902 -1 x11903 -1 x11904 >= -1 ;+-1 x11905 -1 x11906 -1 x11907 -1 x11908 -1 x11909 -1 x11910 -1 x11911 -1 x11912 -1 x11913 -1 x11914 -1 x11915 -1 x11916 -1 x11917 -1 x11918 -1 x11919 -1 x11920 -1 x11921 -1 x11922 -1 x11923 -1 x11924 -1 x11925 -1 x11926 -1 x11927 -1 x11928 -1 x11929 -1 x11930 -1 x11931 -1 x11932 -1 x11933 -1 x11934 -1 x11935 -1 x11936 -1 x11937 -1 x11938 -1 x11939 -1 x11940 -1 x11941 -1 x11942 -1 x11943 -1 x11944 -1 x11945 -1 x11946 -1 x11947 -1 x11948 -1 x11949 -1 x11950 -1 x11951 -1 x11952 -1 x11953 -1 x11954 -1 x11955 -1 x11956 -1 x11957 -1 x11958 -1 x11959 -1 x11960 -1 x11961 -1 x11962 -1 x11963 -1 x11964 -1 x11965 -1 x11966 -1 x11967 -1 x11968 -1 x11969 -1 x11970 -1 x11971 -1 x11972 -1 x11973 -1 x11974 -1 x11975 -1 x11976 -1 x11977 -1 x11978 -1 x11979 -1 x11980 -1 x11981 -1 x11982 -1 x11983 -1 x11984 -1 x11985 -1 x11986 -1 x11987 -1 x11988 -1 x11989 -1 x11990 -1 x11991 -1 x11992 -1 x11993 -1 x11994 -1 x11995 -1 x11996 -1 x11997 -1 x11998 -1 x11999 -1 x12000 -1 x12001 -1 x12002 -1 x12003 -1 x12004 -1 x12005 -1 x12006 -1 x12007 -1 x12008 -1 x12009 -1 x12010 -1 x12011 -1 x12012 -1 x12013 -1 x12014 -1 x12015 -1 x12016 -1 x12017 -1 x12018 -1 x12019 -1 x12020 -1 x12021 -1 x12022 -1 x12023 -1 x12024 -1 x12025 -1 x12026 -1 x12027 -1 x12028 -1 x12029 -1 x12030 -1 x12031 -1 x12032 >= -1 ;+-1 x12033 -1 x12034 -1 x12035 -1 x12036 -1 x12037 -1 x12038 -1 x12039 -1 x12040 -1 x12041 -1 x12042 -1 x12043 -1 x12044 -1 x12045 -1 x12046 -1 x12047 -1 x12048 -1 x12049 -1 x12050 -1 x12051 -1 x12052 -1 x12053 -1 x12054 -1 x12055 -1 x12056 -1 x12057 -1 x12058 -1 x12059 -1 x12060 -1 x12061 -1 x12062 -1 x12063 -1 x12064 -1 x12065 -1 x12066 -1 x12067 -1 x12068 -1 x12069 -1 x12070 -1 x12071 -1 x12072 -1 x12073 -1 x12074 -1 x12075 -1 x12076 -1 x12077 -1 x12078 -1 x12079 -1 x12080 -1 x12081 -1 x12082 -1 x12083 -1 x12084 -1 x12085 -1 x12086 -1 x12087 -1 x12088 -1 x12089 -1 x12090 -1 x12091 -1 x12092 -1 x12093 -1 x12094 -1 x12095 -1 x12096 -1 x12097 -1 x12098 -1 x12099 -1 x12100 -1 x12101 -1 x12102 -1 x12103 -1 x12104 -1 x12105 -1 x12106 -1 x12107 -1 x12108 -1 x12109 -1 x12110 -1 x12111 -1 x12112 -1 x12113 -1 x12114 -1 x12115 -1 x12116 -1 x12117 -1 x12118 -1 x12119 -1 x12120 -1 x12121 -1 x12122 -1 x12123 -1 x12124 -1 x12125 -1 x12126 -1 x12127 -1 x12128 -1 x12129 -1 x12130 -1 x12131 -1 x12132 -1 x12133 -1 x12134 -1 x12135 -1 x12136 -1 x12137 -1 x12138 -1 x12139 -1 x12140 -1 x12141 -1 x12142 -1 x12143 -1 x12144 -1 x12145 -1 x12146 -1 x12147 -1 x12148 -1 x12149 -1 x12150 -1 x12151 -1 x12152 -1 x12153 -1 x12154 -1 x12155 -1 x12156 -1 x12157 -1 x12158 -1 x12159 -1 x12160 >= -1 ;+-1 x12161 -1 x12162 -1 x12163 -1 x12164 -1 x12165 -1 x12166 -1 x12167 -1 x12168 -1 x12169 -1 x12170 -1 x12171 -1 x12172 -1 x12173 -1 x12174 -1 x12175 -1 x12176 -1 x12177 -1 x12178 -1 x12179 -1 x12180 -1 x12181 -1 x12182 -1 x12183 -1 x12184 -1 x12185 -1 x12186 -1 x12187 -1 x12188 -1 x12189 -1 x12190 -1 x12191 -1 x12192 -1 x12193 -1 x12194 -1 x12195 -1 x12196 -1 x12197 -1 x12198 -1 x12199 -1 x12200 -1 x12201 -1 x12202 -1 x12203 -1 x12204 -1 x12205 -1 x12206 -1 x12207 -1 x12208 -1 x12209 -1 x12210 -1 x12211 -1 x12212 -1 x12213 -1 x12214 -1 x12215 -1 x12216 -1 x12217 -1 x12218 -1 x12219 -1 x12220 -1 x12221 -1 x12222 -1 x12223 -1 x12224 -1 x12225 -1 x12226 -1 x12227 -1 x12228 -1 x12229 -1 x12230 -1 x12231 -1 x12232 -1 x12233 -1 x12234 -1 x12235 -1 x12236 -1 x12237 -1 x12238 -1 x12239 -1 x12240 -1 x12241 -1 x12242 -1 x12243 -1 x12244 -1 x12245 -1 x12246 -1 x12247 -1 x12248 -1 x12249 -1 x12250 -1 x12251 -1 x12252 -1 x12253 -1 x12254 -1 x12255 -1 x12256 -1 x12257 -1 x12258 -1 x12259 -1 x12260 -1 x12261 -1 x12262 -1 x12263 -1 x12264 -1 x12265 -1 x12266 -1 x12267 -1 x12268 -1 x12269 -1 x12270 -1 x12271 -1 x12272 -1 x12273 -1 x12274 -1 x12275 -1 x12276 -1 x12277 -1 x12278 -1 x12279 -1 x12280 -1 x12281 -1 x12282 -1 x12283 -1 x12284 -1 x12285 -1 x12286 -1 x12287 -1 x12288 >= -1 ;+-1 x12289 -1 x12290 -1 x12291 -1 x12292 -1 x12293 -1 x12294 -1 x12295 -1 x12296 -1 x12297 -1 x12298 -1 x12299 -1 x12300 -1 x12301 -1 x12302 -1 x12303 -1 x12304 -1 x12305 -1 x12306 -1 x12307 -1 x12308 -1 x12309 -1 x12310 -1 x12311 -1 x12312 -1 x12313 -1 x12314 -1 x12315 -1 x12316 -1 x12317 -1 x12318 -1 x12319 -1 x12320 -1 x12321 -1 x12322 -1 x12323 -1 x12324 -1 x12325 -1 x12326 -1 x12327 -1 x12328 -1 x12329 -1 x12330 -1 x12331 -1 x12332 -1 x12333 -1 x12334 -1 x12335 -1 x12336 -1 x12337 -1 x12338 -1 x12339 -1 x12340 -1 x12341 -1 x12342 -1 x12343 -1 x12344 -1 x12345 -1 x12346 -1 x12347 -1 x12348 -1 x12349 -1 x12350 -1 x12351 -1 x12352 -1 x12353 -1 x12354 -1 x12355 -1 x12356 -1 x12357 -1 x12358 -1 x12359 -1 x12360 -1 x12361 -1 x12362 -1 x12363 -1 x12364 -1 x12365 -1 x12366 -1 x12367 -1 x12368 -1 x12369 -1 x12370 -1 x12371 -1 x12372 -1 x12373 -1 x12374 -1 x12375 -1 x12376 -1 x12377 -1 x12378 -1 x12379 -1 x12380 -1 x12381 -1 x12382 -1 x12383 -1 x12384 -1 x12385 -1 x12386 -1 x12387 -1 x12388 -1 x12389 -1 x12390 -1 x12391 -1 x12392 -1 x12393 -1 x12394 -1 x12395 -1 x12396 -1 x12397 -1 x12398 -1 x12399 -1 x12400 -1 x12401 -1 x12402 -1 x12403 -1 x12404 -1 x12405 -1 x12406 -1 x12407 -1 x12408 -1 x12409 -1 x12410 -1 x12411 -1 x12412 -1 x12413 -1 x12414 -1 x12415 -1 x12416 >= -1 ;+-1 x12417 -1 x12418 -1 x12419 -1 x12420 -1 x12421 -1 x12422 -1 x12423 -1 x12424 -1 x12425 -1 x12426 -1 x12427 -1 x12428 -1 x12429 -1 x12430 -1 x12431 -1 x12432 -1 x12433 -1 x12434 -1 x12435 -1 x12436 -1 x12437 -1 x12438 -1 x12439 -1 x12440 -1 x12441 -1 x12442 -1 x12443 -1 x12444 -1 x12445 -1 x12446 -1 x12447 -1 x12448 -1 x12449 -1 x12450 -1 x12451 -1 x12452 -1 x12453 -1 x12454 -1 x12455 -1 x12456 -1 x12457 -1 x12458 -1 x12459 -1 x12460 -1 x12461 -1 x12462 -1 x12463 -1 x12464 -1 x12465 -1 x12466 -1 x12467 -1 x12468 -1 x12469 -1 x12470 -1 x12471 -1 x12472 -1 x12473 -1 x12474 -1 x12475 -1 x12476 -1 x12477 -1 x12478 -1 x12479 -1 x12480 -1 x12481 -1 x12482 -1 x12483 -1 x12484 -1 x12485 -1 x12486 -1 x12487 -1 x12488 -1 x12489 -1 x12490 -1 x12491 -1 x12492 -1 x12493 -1 x12494 -1 x12495 -1 x12496 -1 x12497 -1 x12498 -1 x12499 -1 x12500 -1 x12501 -1 x12502 -1 x12503 -1 x12504 -1 x12505 -1 x12506 -1 x12507 -1 x12508 -1 x12509 -1 x12510 -1 x12511 -1 x12512 -1 x12513 -1 x12514 -1 x12515 -1 x12516 -1 x12517 -1 x12518 -1 x12519 -1 x12520 -1 x12521 -1 x12522 -1 x12523 -1 x12524 -1 x12525 -1 x12526 -1 x12527 -1 x12528 -1 x12529 -1 x12530 -1 x12531 -1 x12532 -1 x12533 -1 x12534 -1 x12535 -1 x12536 -1 x12537 -1 x12538 -1 x12539 -1 x12540 -1 x12541 -1 x12542 -1 x12543 -1 x12544 >= -1 ;+-1 x12545 -1 x12546 -1 x12547 -1 x12548 -1 x12549 -1 x12550 -1 x12551 -1 x12552 -1 x12553 -1 x12554 -1 x12555 -1 x12556 -1 x12557 -1 x12558 -1 x12559 -1 x12560 -1 x12561 -1 x12562 -1 x12563 -1 x12564 -1 x12565 -1 x12566 -1 x12567 -1 x12568 -1 x12569 -1 x12570 -1 x12571 -1 x12572 -1 x12573 -1 x12574 -1 x12575 -1 x12576 -1 x12577 -1 x12578 -1 x12579 -1 x12580 -1 x12581 -1 x12582 -1 x12583 -1 x12584 -1 x12585 -1 x12586 -1 x12587 -1 x12588 -1 x12589 -1 x12590 -1 x12591 -1 x12592 -1 x12593 -1 x12594 -1 x12595 -1 x12596 -1 x12597 -1 x12598 -1 x12599 -1 x12600 -1 x12601 -1 x12602 -1 x12603 -1 x12604 -1 x12605 -1 x12606 -1 x12607 -1 x12608 -1 x12609 -1 x12610 -1 x12611 -1 x12612 -1 x12613 -1 x12614 -1 x12615 -1 x12616 -1 x12617 -1 x12618 -1 x12619 -1 x12620 -1 x12621 -1 x12622 -1 x12623 -1 x12624 -1 x12625 -1 x12626 -1 x12627 -1 x12628 -1 x12629 -1 x12630 -1 x12631 -1 x12632 -1 x12633 -1 x12634 -1 x12635 -1 x12636 -1 x12637 -1 x12638 -1 x12639 -1 x12640 -1 x12641 -1 x12642 -1 x12643 -1 x12644 -1 x12645 -1 x12646 -1 x12647 -1 x12648 -1 x12649 -1 x12650 -1 x12651 -1 x12652 -1 x12653 -1 x12654 -1 x12655 -1 x12656 -1 x12657 -1 x12658 -1 x12659 -1 x12660 -1 x12661 -1 x12662 -1 x12663 -1 x12664 -1 x12665 -1 x12666 -1 x12667 -1 x12668 -1 x12669 -1 x12670 -1 x12671 -1 x12672 >= -1 ;+-1 x12673 -1 x12674 -1 x12675 -1 x12676 -1 x12677 -1 x12678 -1 x12679 -1 x12680 -1 x12681 -1 x12682 -1 x12683 -1 x12684 -1 x12685 -1 x12686 -1 x12687 -1 x12688 -1 x12689 -1 x12690 -1 x12691 -1 x12692 -1 x12693 -1 x12694 -1 x12695 -1 x12696 -1 x12697 -1 x12698 -1 x12699 -1 x12700 -1 x12701 -1 x12702 -1 x12703 -1 x12704 -1 x12705 -1 x12706 -1 x12707 -1 x12708 -1 x12709 -1 x12710 -1 x12711 -1 x12712 -1 x12713 -1 x12714 -1 x12715 -1 x12716 -1 x12717 -1 x12718 -1 x12719 -1 x12720 -1 x12721 -1 x12722 -1 x12723 -1 x12724 -1 x12725 -1 x12726 -1 x12727 -1 x12728 -1 x12729 -1 x12730 -1 x12731 -1 x12732 -1 x12733 -1 x12734 -1 x12735 -1 x12736 -1 x12737 -1 x12738 -1 x12739 -1 x12740 -1 x12741 -1 x12742 -1 x12743 -1 x12744 -1 x12745 -1 x12746 -1 x12747 -1 x12748 -1 x12749 -1 x12750 -1 x12751 -1 x12752 -1 x12753 -1 x12754 -1 x12755 -1 x12756 -1 x12757 -1 x12758 -1 x12759 -1 x12760 -1 x12761 -1 x12762 -1 x12763 -1 x12764 -1 x12765 -1 x12766 -1 x12767 -1 x12768 -1 x12769 -1 x12770 -1 x12771 -1 x12772 -1 x12773 -1 x12774 -1 x12775 -1 x12776 -1 x12777 -1 x12778 -1 x12779 -1 x12780 -1 x12781 -1 x12782 -1 x12783 -1 x12784 -1 x12785 -1 x12786 -1 x12787 -1 x12788 -1 x12789 -1 x12790 -1 x12791 -1 x12792 -1 x12793 -1 x12794 -1 x12795 -1 x12796 -1 x12797 -1 x12798 -1 x12799 -1 x12800 >= -1 ;
+ samples/programs/assign/assign.hs view
@@ -0,0 +1,107 @@+{-+A program for solving following assignment problems from+<http://people.brunel.ac.uk/~mastjjb/jeb/orlib/assigninfo.html>.++Problem set        Files+100                assign100+200                assign200+300                assign300+400                assign400+500                assign500+600                assign600+700                assign700+800                assign800++Use "-p" option to solve those problem.++Problem set        Files+800                assignp800+1500               assignp1500+3000               assignp3000+5000               assignp5000+-}+module Main where++import Control.Applicative+import Control.Monad+import Data.Attoparsec.ByteString.Char8 hiding (isSpace)+import qualified Data.Attoparsec.ByteString.Lazy as AL+import qualified Data.ByteString.Lazy.Char8 as BL+import Data.Char+import Data.IntMap (IntMap)+import qualified Data.IntMap as IntMap+import Data.IntSet (IntSet)+import qualified Data.IntSet as IntSet+import Data.List+import qualified Data.Vector.Unboxed as VU+import System.Environment+import ToySolver.Combinatorial.BipartiteMatching++main :: IO ()+main = do+  args <- getArgs+  case args of+    [fname] -> do+      s <- BL.readFile fname+      let (as, bs, w) = parse1 s+          (obj, m, _) = minimumWeightPerfectMatchingComplete as bs w+      putStrLn $ "obj = " ++ show obj+      forM_ (IntMap.toList m) $ \(a,b) -> do+        putStrLn $ unwords $ map show [a,b]+    ["-pp", fname] -> do+      s <- BL.readFile fname+      let (as, bs, w) = parse1 s+          es = [(a, b, w a b) | a <- IntSet.toList as, b <- IntSet.toList bs]+      case minimumWeightPerfectMatching as bs es of+        Nothing ->+          putStrLn $ "infeasible"+        Just (obj, m, _) -> do+          putStrLn $ "obj = " ++ show obj+          forM_ (IntMap.toList m) $ \(a,b) -> do+            putStrLn $ unwords $ map show [a,b]+    ["-p", fname] -> do+      s <- BL.readFile fname+      let (as, bs, es) = parse2 s+      case minimumWeightPerfectMatching as bs es of+        Nothing ->+          putStrLn $ "infeasible"+        Just (obj, m, _) -> do+          putStrLn $ "obj = " ++ show obj+          forM_ (IntMap.toList m) $ \(a,b) -> do+            putStrLn $ unwords $ map show [a,b]++parse1 :: BL.ByteString -> (IntSet, IntSet, Int -> Int -> Int)+parse1 s = (as, bs, w)+  where+    f s =+      case BL.readInt s of+        Nothing -> Nothing+        Just (i,s') -> Just (i, BL.dropWhile isSpace s')+    (n:xs) = unfoldr f (BL.dropWhile isSpace s)+    tbl :: VU.Vector Int+    tbl = VU.fromListN (n*n) xs+    as = IntSet.fromList [0..n-1]+    bs = as+    w a b = tbl VU.! (a*n+b)++parse2 :: BL.ByteString -> (IntSet, IntSet, [(Int,Int,Int)])+parse2 s =+  case AL.eitherResult (AL.parse pfile s) of+    Left s -> error s+    Right x -> x++pfile :: Parser (IntSet, IntSet, [(Int,Int,Int)])+pfile = do+  skipSpace+  n <- decimal <* skipSpace+  let p es =+        mplus+          (do a <- decimal <* skipSpace+              b <- decimal <* skipSpace+              w <- decimal <* skipSpace+              p ((a,b,w) : es))+          (endOfInput *> return es)+  es <- p []+  let as = IntSet.fromList [1..n]+      bs = as+  return (as, bs, es)
samples/programs/htc/htc.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ScopedTypeVariables, CPP #-} {-# OPTIONS_GHC -Wall #-} module Main where @@ -12,9 +12,15 @@ import System.IO import qualified ToySolver.Combinatorial.HittingSet.Simple as HittingSet import qualified ToySolver.Combinatorial.HittingSet.GurvichKhachiyan1999 as GurvichKhachiyan1999+import qualified ToySolver.Combinatorial.HittingSet.MARCO as MARCO+import ToySolver.Internal.Util (setEncodingChar8)  main :: IO () main = do+#ifdef FORCE_CHAR8+  setEncodingChar8+#endif+   args <- getArgs   case args of     [] -> do@@ -23,6 +29,7 @@       hPutStrLn stderr "Supported METHODs:"       hPutStrLn stderr "  simple"       hPutStrLn stderr "  gurvichkhachiyan1999"+      hPutStrLn stderr "  marco"     [method, fname] -> f (Just method) fname     [fname] -> f Nothing fname @@ -38,6 +45,7 @@           "simple" -> return $ HittingSet.minimalHittingSets xss           "gurvichkhachiyan1999" -> return $ GurvichKhachiyan1999.minimalHittingSets xss           "gurvichkhachiyan" -> return $ GurvichKhachiyan1999.minimalHittingSets xss+          "marco" -> return $ MARCO.minimalHittingSets xss           _ -> do             hPutStrLn stderr ("unknown method: " ++ s)             exitFailure
samples/programs/knapsack/knapsack.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ScopedTypeVariables, CPP #-} {-# OPTIONS_GHC -Wall #-} module Main where @@ -8,12 +8,17 @@ import System.IO import Text.Printf import qualified ToySolver.Combinatorial.Knapsack.BB as Knapsack+import ToySolver.Internal.Util (setEncodingChar8)  type Value = Integer type Weight = Integer  main :: IO () main = do+#ifdef FORCE_CHAR8+  setEncodingChar8+#endif+   args <- getArgs   case args of     [fname] -> do
samples/programs/nonogram/nonogram.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ScopedTypeVariables, FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables, FlexibleContexts, CPP #-} {-# OPTIONS_GHC -Wall #-} module Main where @@ -15,7 +15,8 @@ import System.Exit import System.IO import qualified ToySolver.SAT as SAT-import qualified ToySolver.SAT.TseitinEncoder as Tseitin+import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin+import ToySolver.Internal.Util (setEncodingChar8)  -- row patterns and column patterns type Problem = ([[Int]], [[Int]])@@ -170,6 +171,10 @@  main :: IO () main = do+#ifdef FORCE_CHAR8+  setEncodingChar8+#endif+   args <- getArgs   case getOpt Permute options args of     (_,_,errs@(_:_)) -> do
samples/programs/nqueens/nqueens.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ScopedTypeVariables, CPP #-} {-# OPTIONS_GHC -Wall #-} module Main where @@ -6,9 +6,14 @@ import Data.Array.IArray import System.Environment import qualified ToySolver.SAT as SAT+import ToySolver.Internal.Util (setEncodingChar8)  main :: IO () main = do+#ifdef FORCE_CHAR8+  setEncodingChar8+#endif+   [s] <- getArgs   let n = read s   ans <- solve n
+ samples/programs/numberlink/ADC2013/NL_Q04.txt view
@@ -0,0 +1,14 @@+SIZE 15X15+LINE_NUM 12+LINE#1 (10,0)-(4,14)+LINE#2 (9,5)-(9,14)+LINE#3 (2,7)-(4,12)+LINE#4 (2,5)-(7,13)+LINE#5 (2,4)-(4,10)+LINE#6 (2,2)-(5,5)+LINE#7 (6,5)-(5,10)+LINE#8 (5,0)-(7,9)+LINE#9 (10,2)-(12,7)+LINE#10 (7,1)-(12,9)+LINE#11 (9,8)-(12,12)+LINE#12 (8,9)-(12,10)
+ samples/programs/numberlink/ADC2013/NL_R04.txt view
@@ -0,0 +1,48 @@+SIZE 15X15+01,01,01,01,01,08,08,08,08,08,01,01,01,01,01+01,02,02,02,01,01,01,10,10,08,08,08,08,08,01+01,02,06,02,02,02,01,01,10,10,09,09,09,08,01+01,02,06,06,06,02,02,01,01,10,10,10,09,08,01+01,02,05,05,06,06,02,02,01,01,01,10,09,08,01+01,02,04,05,05,06,07,02,02,02,01,10,09,08,01+01,02,04,04,05,00,07,01,01,01,01,10,09,08,01+01,02,03,04,05,07,07,01,12,12,12,10,09,08,01+01,02,03,04,05,07,01,01,12,11,12,10,10,08,01+01,02,03,04,05,07,01,08,12,11,12,12,10,08,01+01,02,03,04,05,07,01,08,08,11,11,12,12,08,01+01,02,03,04,04,04,01,01,08,08,11,11,11,08,01+01,02,03,03,03,04,04,01,01,08,08,08,11,08,01+01,02,02,02,02,02,04,04,01,01,01,08,08,08,01+01,01,01,01,01,02,02,02,02,02,01,01,01,01,01++01,01,01,01,01,08,08,08,08,08,01,01,01,01,01+01,02,02,02,01,01,01,10,10,08,08,08,08,08,01+01,02,06,02,02,02,01,01,10,10,09,09,09,08,01+01,02,06,06,06,02,02,01,01,10,10,10,09,08,01+01,02,05,05,06,06,02,02,01,01,01,10,09,08,01+01,02,04,05,05,06,07,02,02,02,01,10,09,08,01+01,02,04,04,05,07,07,01,01,01,01,10,09,08,01+01,02,03,04,05,07,00,01,12,12,12,10,09,08,01+01,02,03,04,05,07,01,01,12,11,12,10,10,08,01+01,02,03,04,05,07,01,08,12,11,12,12,10,08,01+01,02,03,04,05,07,01,08,08,11,11,12,12,08,01+01,02,03,04,04,04,01,01,08,08,11,11,11,08,01+01,02,03,03,03,04,04,01,01,08,08,08,11,08,01+01,02,02,02,02,02,04,04,01,01,01,08,08,08,01+01,01,01,01,01,02,02,02,02,02,01,01,01,01,01++01,01,01,01,01,08,08,08,08,08,01,01,01,01,01+01,02,02,02,01,01,01,10,10,08,08,08,08,08,01+01,02,06,02,02,02,01,01,10,10,09,09,09,08,01+01,02,06,06,06,02,02,01,01,10,10,10,09,08,01+01,02,05,05,06,06,02,02,01,01,01,10,09,08,01+01,02,04,05,05,06,07,02,02,02,01,10,09,08,01+01,02,04,04,05,07,07,01,01,01,01,10,09,08,01+01,02,03,04,05,07,01,01,12,12,12,10,09,08,01+01,02,03,04,05,07,01,00,12,11,12,10,10,08,01+01,02,03,04,05,07,01,08,12,11,12,12,10,08,01+01,02,03,04,05,07,01,08,08,11,11,12,12,08,01+01,02,03,04,04,04,01,01,08,08,11,11,11,08,01+01,02,03,03,03,04,04,01,01,08,08,08,11,08,01+01,02,02,02,02,02,04,04,01,01,01,08,08,08,01+01,01,01,01,01,02,02,02,02,02,01,01,01,01,01
+ samples/programs/numberlink/ADC2014_QA/A/T99_A01.txt view
@@ -0,0 +1,11 @@+SIZE 10X10+05,05,05,05,05,05,05,05,05,05+05,06,06,06,06,06,06,06,01,05+05,07,07,07,07,07,07,06,01,05+05,01,01,01,01,01,01,01,01,05+05,01,02,02,02,02,02,02,02,02+05,01,01,01,01,01,01,01,01,02+05,05,05,05,05,05,04,03,01,02+04,04,04,04,04,04,04,03,01,02+04,03,03,03,03,03,03,03,01,02+03,03,02,02,02,02,02,02,02,02
+ samples/programs/numberlink/ADC2014_QA/A/T99_A02.txt view
@@ -0,0 +1,11 @@+SIZE 10X10+01,01,01,08,08,08,09,09,09,10+02,02,01,01,01,08,08,08,09,10+03,02,02,02,01,01,01,08,08,08+03,03,03,02,02,02,01,01,01,08+04,04,03,03,03,02,02,02,01,01+05,04,04,04,03,03,03,02,02,02+05,05,05,04,04,04,03,03,03,02+06,06,05,05,05,04,04,04,03,03+07,06,06,06,05,05,05,04,04,04+07,07,07,06,06,06,05,05,05,04
+ samples/programs/numberlink/ADC2014_QA/A/T99_A03.txt view
@@ -0,0 +1,19 @@+SIZE 10X18+01,01,01,01,01,01,01,01,01,01+01,02,02,02,02,02,02,02,02,02+01,02,03,03,03,03,03,03,03,03+01,02,03,04,04,04,04,04,04,04+01,02,03,04,05,05,05,05,05,05+01,02,03,04,05,06,06,06,06,06+01,02,03,04,05,06,07,07,07,07+01,02,03,04,05,06,07,08,08,08+01,02,03,04,05,06,07,08,09,08+01,02,03,04,05,06,07,08,09,08+01,02,03,04,05,06,07,08,09,08+01,02,03,04,05,06,07,08,09,08+01,02,03,04,05,06,07,08,09,08+01,02,03,04,05,06,07,08,09,08+01,02,03,04,05,06,07,08,09,08+01,02,03,04,05,06,07,08,09,08+01,02,03,04,05,06,07,08,09,08+01,02,03,04,05,06,07,08,09,08
+ samples/programs/numberlink/ADC2014_QA/A/T99_A04.txt view
@@ -0,0 +1,19 @@+SIZE 10X18+01,01,01,01,01,01,01,01,01,01+01,13,12,12,12,08,02,14,16,16+01,13,12,08,08,08,02,14,16,17+12,12,12,08,02,02,02,14,16,17+12,08,08,08,02,14,14,14,16,17+12,08,03,03,02,14,16,16,16,17+12,08,03,06,02,14,14,14,17,17+12,08,03,06,02,02,02,14,17,14+08,08,03,06,06,06,02,14,14,14+04,04,03,07,07,06,02,05,05,05+09,09,03,06,06,06,02,15,15,15+10,09,03,06,02,02,02,15,19,19+10,09,03,06,02,15,15,15,19,18+10,09,03,03,02,15,19,19,19,18+10,09,09,09,02,15,15,15,18,18+10,10,10,09,02,02,02,15,18,15+11,11,11,09,09,09,02,15,15,15+20,20,20,20,20,20,20,20,20,20
+ samples/programs/numberlink/ADC2014_QA/A/T99_A06.txt view
@@ -0,0 +1,19 @@+SIZE 14X18+03,03,03,03,03,03,03,04,04,04,04,04,04,04+03,02,02,02,02,02,03,04,05,05,05,05,05,04+03,02,01,01,01,02,03,04,05,06,06,06,05,04+03,02,09,07,01,02,03,04,05,06,07,08,05,04+03,02,09,07,01,02,03,04,05,06,07,08,05,04+03,02,09,07,01,02,03,04,05,06,07,08,05,04+03,02,09,07,01,02,03,04,05,06,07,08,05,04+03,02,09,07,01,02,03,04,05,06,07,08,05,04+03,02,09,07,01,02,03,04,05,06,07,08,05,04+03,02,09,07,01,02,03,04,05,06,07,08,05,04+03,02,09,07,01,02,03,04,05,06,07,08,05,04+03,02,09,07,01,02,03,04,05,06,07,08,05,04+03,02,09,07,01,02,03,04,05,06,07,08,05,04+03,02,09,07,01,02,03,04,05,06,07,08,05,04+03,02,09,07,07,07,07,07,07,07,07,08,05,04+03,02,09,09,09,09,09,09,09,09,09,09,05,04+03,02,02,02,02,02,02,05,05,05,05,05,05,04+03,03,03,03,03,03,03,03,03,03,03,03,03,03
+ samples/programs/numberlink/ADC2014_QA/A/T99_A07.txt view
@@ -0,0 +1,16 @@+SIZE 17X15+01,06,06,06,06,06,06,06,06,06,06,10,10,10,10,10,10+01,06,01,01,01,03,03,03,03,12,06,09,09,09,09,09,09+01,06,01,04,01,03,01,01,01,12,06,06,06,06,06,06,06+01,06,01,04,01,03,01,11,01,12,01,01,01,02,02,02,02+01,06,01,04,01,03,01,11,01,12,01,05,01,02,01,01,01+01,06,01,04,01,03,01,11,01,12,01,05,01,02,01,13,01+01,06,01,04,01,03,01,11,01,12,01,05,01,02,01,13,01+01,06,01,04,01,03,01,11,01,12,01,05,01,02,01,13,01+01,06,01,04,01,03,01,11,01,12,01,05,01,02,01,13,01+01,06,01,04,01,03,01,11,01,12,01,05,01,02,01,13,01+01,06,01,04,01,03,01,11,01,12,01,05,01,02,01,13,01+01,06,01,04,01,03,01,11,01,12,01,05,01,01,01,13,08+01,06,01,04,01,03,01,11,01,01,01,05,05,13,13,13,08+01,06,01,04,01,01,01,11,08,08,08,08,08,08,08,08,08+01,01,01,04,04,04,04,04,08,07,07,07,07,07,07,07,07
+ samples/programs/numberlink/ADC2014_QA/A/T99_A08.txt view
@@ -0,0 +1,20 @@+SIZE 16X19+28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28+28,25,25,27,27,27,27,27,27,27,27,27,27,27,27,28+28,24,25,27,05,05,05,06,06,06,07,07,07,26,27,28+28,24,25,27,05,01,05,06,02,06,07,03,07,26,27,28+28,24,25,27,05,01,05,06,02,06,07,03,07,26,27,28+28,24,25,27,05,01,05,06,02,06,07,03,07,26,27,28+28,24,25,27,01,01,05,02,02,06,03,03,07,26,27,28+28,24,25,27,01,05,05,02,06,06,03,07,07,26,27,28+28,24,25,27,01,08,08,02,09,09,03,26,26,26,27,28+28,24,25,27,01,01,08,02,02,09,03,03,28,28,28,28+21,21,21,27,28,01,08,10,02,09,11,03,28,22,22,22+21,04,04,28,28,01,10,10,02,11,11,03,28,04,04,22+04,04,15,28,01,01,10,02,02,11,03,03,28,16,04,04+04,15,15,28,01,12,10,02,13,11,03,14,28,16,16,04+04,17,17,28,01,12,10,02,13,11,03,14,28,18,18,04+04,04,17,28,01,12,12,02,13,13,03,14,28,18,04,04+19,04,04,28,28,28,28,28,28,28,28,28,28,04,04,20+19,19,04,04,04,04,04,04,04,04,04,04,04,04,20,20+23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23
+ samples/programs/numberlink/ADC2014_QA/A/T99_A09.txt view
@@ -0,0 +1,19 @@+SIZE 18X18+07,07,07,07,07,07,07,07,07,07,07,07,07,07,07,10,10,10+07,01,01,01,01,01,01,01,01,01,01,01,01,01,07,08,08,10+07,07,07,07,07,07,07,02,05,05,05,05,06,06,07,07,08,10+17,17,17,18,18,15,07,02,04,04,04,05,05,06,06,07,08,10+17,10,09,18,09,15,07,02,03,03,04,04,05,05,06,06,08,10+17,10,09,18,09,15,07,02,04,03,03,04,04,05,05,06,08,10+17,10,09,18,09,15,07,02,04,04,03,03,04,04,05,06,08,10+17,10,09,18,09,15,07,02,05,04,04,03,03,04,05,06,08,10+17,10,09,18,09,15,07,02,05,05,04,04,04,04,05,06,08,10+17,10,09,18,09,15,07,02,06,05,05,05,05,05,05,06,08,10+17,10,09,18,09,15,07,02,06,06,06,06,06,06,06,06,08,10+17,10,09,18,09,15,07,02,08,08,08,08,08,08,08,08,08,10+17,10,09,18,09,15,07,02,08,11,11,11,11,11,11,11,11,10+17,10,09,18,09,15,07,02,08,11,10,10,10,10,10,10,10,10+17,10,09,18,09,15,07,02,08,11,10,13,13,13,13,13,13,13+17,10,09,09,09,15,07,02,08,11,10,14,14,14,14,14,14,13+17,10,12,12,12,15,08,08,08,11,10,14,16,16,16,16,14,13+17,10,10,10,10,10,10,10,10,10,10,14,14,14,14,16,16,16
+ samples/programs/numberlink/ADC2014_QA/A/T99_A13.txt view
@@ -0,0 +1,22 @@+SIZE 18X21+12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12+12,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,12+12,15,13,13,13,13,13,13,13,13,13,13,13,13,13,13,15,12+12,15,13,01,01,01,01,01,01,01,01,01,01,01,01,13,15,12+12,15,13,01,06,06,06,07,07,07,07,07,07,06,01,13,15,12+12,15,13,01,06,08,06,06,06,06,06,06,07,06,01,13,15,12+12,15,13,01,06,08,08,08,08,08,08,06,06,06,01,13,15,12+12,15,13,01,01,01,01,01,01,02,02,02,02,02,01,13,15,12+12,15,13,13,13,13,13,13,13,13,03,03,13,13,13,13,15,12+12,15,15,15,15,15,15,14,14,03,03,13,13,15,15,15,15,12+17,17,17,17,16,16,14,14,03,03,13,13,15,15,17,17,17,17+17,16,16,16,16,14,14,03,03,13,13,15,15,16,16,16,16,17+17,16,14,14,14,14,03,03,13,13,14,14,14,14,14,14,16,17+17,16,14,05,04,04,04,04,04,04,04,05,05,05,05,14,16,17+17,16,14,05,09,10,10,10,10,10,10,09,09,09,05,14,16,17+17,16,14,05,09,10,09,09,09,09,09,09,11,09,05,14,16,17+17,16,14,05,09,09,09,11,11,11,11,11,11,09,05,14,16,17+17,16,14,05,05,05,05,05,05,05,05,05,05,05,05,14,16,17+17,16,14,14,14,14,14,14,14,14,14,14,14,14,14,14,16,17+17,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17
+ samples/programs/numberlink/ADC2014_QA/A/T99_A14.txt view
@@ -0,0 +1,66 @@+SIZE 18X21+12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12+12,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,12+12,15,13,13,13,13,13,13,13,13,13,13,13,13,13,13,15,12+12,15,13,01,01,01,01,01,01,01,01,01,01,01,01,13,15,12+12,15,13,01,06,06,06,07,07,07,07,07,07,06,01,13,15,12+12,15,13,01,06,08,06,06,06,06,06,06,07,06,01,13,15,12+12,15,13,01,06,08,08,08,08,08,08,06,06,06,01,13,15,12+12,15,13,01,01,01,01,01,01,02,02,02,02,02,01,13,15,12+12,15,13,13,13,13,13,13,13,13,03,03,13,13,13,13,15,12+12,15,15,15,15,15,15,14,14,03,03,13,13,15,15,15,15,12+17,17,17,17,16,16,14,14,03,03,13,13,15,15,17,17,17,17+17,16,16,16,16,14,14,03,03,13,13,15,15,16,16,16,16,17+17,16,14,14,14,14,03,03,13,13,14,14,14,14,14,14,16,17+17,16,14,05,04,04,04,04,04,04,04,05,05,05,05,14,16,17+17,16,14,05,09,00,10,10,10,10,10,09,09,09,05,14,16,17+17,16,14,05,09,10,10,09,09,09,09,09,11,09,05,14,16,17+17,16,14,05,09,09,09,09,11,11,11,11,11,09,05,14,16,17+17,16,14,05,05,05,05,05,05,05,05,05,05,05,05,14,16,17+17,16,14,14,14,14,14,14,14,14,14,14,14,14,14,14,16,17+17,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17++12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12+12,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,12+12,15,13,13,13,13,13,13,13,13,13,13,13,13,13,13,15,12+12,15,13,01,01,01,01,01,01,01,01,01,01,01,01,13,15,12+12,15,13,01,06,06,06,07,07,07,07,07,07,06,01,13,15,12+12,15,13,01,06,08,06,06,06,06,06,06,07,06,01,13,15,12+12,15,13,01,06,08,08,08,08,08,08,06,06,06,01,13,15,12+12,15,13,01,01,01,01,01,01,02,02,02,02,02,01,13,15,12+12,15,13,13,13,13,13,13,13,13,03,03,13,13,13,13,15,12+12,15,15,15,15,15,15,14,14,03,03,13,13,15,15,15,15,12+17,17,17,17,16,16,14,14,03,03,13,13,15,15,17,17,17,17+17,16,16,16,16,14,14,03,03,13,13,15,15,16,16,16,16,17+17,16,14,14,14,14,03,03,13,13,14,14,14,14,14,14,16,17+17,16,14,05,04,04,04,04,04,04,04,05,05,05,05,14,16,17+17,16,14,05,09,10,10,10,10,10,10,09,09,09,05,14,16,17+17,16,14,05,09,10,00,09,09,09,09,09,11,09,05,14,16,17+17,16,14,05,09,09,09,09,11,11,11,11,11,09,05,14,16,17+17,16,14,05,05,05,05,05,05,05,05,05,05,05,05,14,16,17+17,16,14,14,14,14,14,14,14,14,14,14,14,14,14,14,16,17+17,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17++12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12+12,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,12+12,15,13,13,13,13,13,13,13,13,13,13,13,13,13,13,15,12+12,15,13,01,01,01,01,01,01,01,01,01,01,01,01,13,15,12+12,15,13,01,06,06,06,07,07,07,07,07,07,06,01,13,15,12+12,15,13,01,06,08,06,06,06,06,06,06,07,06,01,13,15,12+12,15,13,01,06,08,08,08,08,08,08,06,06,06,01,13,15,12+12,15,13,01,01,01,01,01,01,02,02,02,02,02,01,13,15,12+12,15,13,13,13,13,13,13,13,13,03,03,13,13,13,13,15,12+12,15,15,15,15,15,15,14,14,03,03,13,13,15,15,15,15,12+17,17,17,17,16,16,14,14,03,03,13,13,15,15,17,17,17,17+17,16,16,16,16,14,14,03,03,13,13,15,15,16,16,16,16,17+17,16,14,14,14,14,03,03,13,13,14,14,14,14,14,14,16,17+17,16,14,05,04,04,04,04,04,04,04,05,05,05,05,14,16,17+17,16,14,05,09,10,10,10,10,10,10,09,09,09,05,14,16,17+17,16,14,05,09,10,09,09,09,09,09,09,11,09,05,14,16,17+17,16,14,05,09,09,09,00,11,11,11,11,11,09,05,14,16,17+17,16,14,05,05,05,05,05,05,05,05,05,05,05,05,14,16,17+17,16,14,14,14,14,14,14,14,14,14,14,14,14,14,14,16,17+17,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17
+ samples/programs/numberlink/ADC2014_QA/A/T99_A15.txt view
@@ -0,0 +1,20 @@+SIZE 35X19+07,07,07,07,07,07,07,07,07,07,07,07,07,07,07,10,10,10,10,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32+07,01,01,01,01,01,01,01,01,01,01,01,01,01,07,08,08,08,10,32,30,30,30,30,30,30,30,30,30,30,30,30,30,30,32+07,07,07,07,07,07,07,02,05,05,05,05,06,06,07,07,35,08,10,32,30,19,19,19,19,19,19,19,19,19,19,19,19,30,32+17,17,17,18,18,15,07,02,04,04,04,05,05,06,06,07,35,08,10,32,30,19,24,24,24,25,25,25,25,25,25,24,19,30,32+17,10,09,18,09,15,07,02,03,03,04,04,05,05,06,06,35,08,10,32,30,19,24,26,24,24,24,24,24,24,25,24,19,30,32+17,10,09,18,09,15,07,02,04,03,03,04,04,05,05,06,35,08,10,32,30,19,24,26,26,26,26,26,26,24,24,24,19,30,32+17,10,09,18,09,15,07,02,04,04,03,03,04,04,05,06,35,08,10,32,30,19,19,19,19,19,19,20,20,20,20,20,19,30,32+17,10,09,18,09,15,07,02,05,04,04,03,03,04,05,06,08,08,10,32,30,30,30,30,30,30,30,30,21,21,30,30,30,30,32+17,10,09,18,09,15,07,02,05,05,04,04,04,04,05,06,08,10,10,32,32,32,32,32,32,31,31,21,21,30,30,32,32,32,32+17,10,09,18,09,15,07,02,06,05,05,05,05,05,05,06,08,10,17,17,17,17,33,33,31,31,21,21,30,30,32,32,34,34,34+17,10,09,18,09,15,07,02,06,06,06,06,06,06,06,06,08,10,17,33,33,33,33,31,31,21,21,30,30,32,32,33,33,33,33+17,10,09,18,09,15,07,02,08,08,08,08,08,08,08,08,08,10,17,33,31,31,31,31,21,21,30,30,31,31,31,31,31,31,33+17,10,09,18,09,15,07,02,08,11,11,11,11,11,11,11,11,10,17,33,31,23,22,22,22,22,22,22,22,23,23,23,23,31,33+17,10,09,18,09,15,07,02,08,11,10,10,10,10,10,10,10,10,17,33,31,23,27,28,28,28,28,28,28,27,27,27,23,31,33+17,10,09,18,09,15,07,02,08,11,10,13,13,13,13,13,13,13,17,33,31,23,27,28,27,27,27,27,27,27,29,27,23,31,33+17,10,09,09,09,15,07,02,08,11,10,14,14,14,14,14,14,13,17,33,31,23,27,27,27,29,29,29,29,29,29,27,23,31,33+17,10,12,12,12,15,08,08,08,11,10,14,16,16,16,16,14,13,17,33,31,23,23,23,23,23,23,23,23,23,23,23,23,31,33+17,10,10,10,10,10,10,10,10,10,10,14,14,14,14,16,16,16,17,33,31,31,31,31,31,31,31,31,31,31,31,31,31,31,33+17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33,33
+ samples/programs/numberlink/ADC2014_QA/Q/NL_Q01.txt view
@@ -0,0 +1,9 @@+SIZE 10X10+LINE_NUM 7+LINE#1 (8,1)-(8,8)+LINE#2 (2,4)-(2,9)+LINE#3 (7,6)-(0,9)+LINE#4 (6,6)-(0,8)+LINE#5 (9,3)-(5,6)+LINE#6 (1,1)-(7,2)+LINE#7 (1,2)-(6,2)
+ samples/programs/numberlink/ADC2014_QA/Q/NL_Q02.txt view
@@ -0,0 +1,12 @@+SIZE 10X10+LINE_NUM 10+LINE#1 (0,0)-(9,4)+LINE#2 (0,1)-(9,6)+LINE#3 (0,2)-(9,7)+LINE#4 (0,4)-(9,9)+LINE#5 (0,5)-(8,9)+LINE#6 (0,7)-(5,9)+LINE#7 (0,8)-(2,9)+LINE#8 (3,0)-(9,3)+LINE#9 (6,0)-(8,1)+LINE#10 (9,0)-(9,1)
+ samples/programs/numberlink/ADC2014_QA/Q/NL_Q03.txt view
@@ -0,0 +1,11 @@+SIZE 10X18+LINE_NUM 9+LINE#1 (9,0)-(0,17)+LINE#2 (9,1)-(1,17)+LINE#3 (9,2)-(2,17)+LINE#4 (9,3)-(3,17)+LINE#5 (9,4)-(4,17)+LINE#6 (9,5)-(5,17)+LINE#7 (9,6)-(6,17)+LINE#8 (7,17)-(9,17)+LINE#9 (8,8)-(8,17)
+ samples/programs/numberlink/ADC2014_QA/Q/NL_Q04.txt view
@@ -0,0 +1,22 @@+SIZE 10X18+LINE_NUM 20+LINE#1 (9,0)-(0,2)+LINE#2 (6,1)-(6,16)+LINE#3 (3,5)-(3,13)+LINE#4 (0,9)-(1,9)+LINE#5 (7,9)-(9,9)+LINE#6 (3,6)-(3,12)+LINE#7 (3,9)-(4,9)+LINE#8 (5,1)-(0,8)+LINE#9 (0,10)-(5,16)+LINE#10 (0,11)-(2,15)+LINE#11 (0,16)-(2,16)+LINE#12 (4,1)-(0,7)+LINE#13 (1,1)-(1,2)+LINE#14 (7,1)-(9,7)+LINE#15 (9,10)-(9,15)+LINE#16 (9,1)-(6,5)+LINE#17 (9,2)-(8,7)+LINE#18 (9,12)-(8,15)+LINE#19 (9,11)-(6,13)+LINE#20 (0,17)-(9,17)
+ samples/programs/numberlink/ADC2014_QA/Q/NL_Q06.txt view
@@ -0,0 +1,11 @@+SIZE 14X18+LINE_NUM 9+LINE#1 (2,2)-(4,13)+LINE#2 (5,13)-(6,16)+LINE#3 (6,13)-(13,17)+LINE#4 (7,13)-(13,16)+LINE#5 (8,13)-(7,16)+LINE#6 (11,2)-(9,13)+LINE#7 (3,3)-(10,3)+LINE#8 (11,3)-(11,14)+LINE#9 (2,3)-(11,15)
+ samples/programs/numberlink/ADC2014_QA/Q/NL_Q07.txt view
@@ -0,0 +1,15 @@+SIZE 17X15+LINE_NUM 13+LINE#1 (0,0)-(16,10)+LINE#2 (16,3)-(13,10)+LINE#3 (8,1)-(5,12)+LINE#4 (3,2)-(7,14)+LINE#5 (11,4)-(12,12)+LINE#6 (16,2)-(1,13)+LINE#7 (9,14)-(16,14)+LINE#8 (16,11)-(8,14)+LINE#9 (11,1)-(16,1)+LINE#10 (11,0)-(16,0)+LINE#11 (7,3)-(7,13)+LINE#12 (9,1)-(9,11)+LINE#13 (15,5)-(13,12)
+ samples/programs/numberlink/ADC2014_QA/Q/NL_Q08.txt view
@@ -0,0 +1,30 @@+SIZE 16X19+LINE_NUM 28+LINE#1 (5,3)-(4,15)+LINE#2 (8,3)-(7,15)+LINE#3 (11,3)-(10,15)+LINE#4 (2,11)-(13,11)+LINE#5 (4,5)-(5,7)+LINE#6 (7,5)-(8,7)+LINE#7 (10,5)-(11,7)+LINE#8 (5,8)-(6,10)+LINE#9 (8,8)-(9,10)+LINE#10 (7,10)-(6,14)+LINE#11 (10,10)-(9,14)+LINE#12 (5,13)-(6,15)+LINE#13 (8,13)-(9,15)+LINE#14 (11,13)-(11,15)+LINE#15 (2,12)-(1,13)+LINE#16 (13,12)-(14,13)+LINE#17 (1,14)-(2,15)+LINE#18 (14,14)-(13,15)+LINE#19 (0,16)-(1,17)+LINE#20 (15,16)-(14,17)+LINE#21 (2,10)-(0,11)+LINE#22 (13,10)-(15,11)+LINE#23 (0,18)-(15,18)+LINE#24 (1,2)-(1,9)+LINE#25 (1,1)-(2,9)+LINE#26 (13,2)-(11,8)+LINE#27 (14,8)-(3,10)+LINE#28 (0,9)-(4,10)
+ samples/programs/numberlink/ADC2014_QA/Q/NL_Q09.txt view
@@ -0,0 +1,20 @@+SIZE 18X18+LINE_NUM 18+LINE#1 (1,1)-(13,1)+LINE#2 (7,2)-(7,15)+LINE#3 (8,4)-(12,7)+LINE#4 (8,3)-(8,5)+LINE#5 (8,2)-(8,7)+LINE#6 (12,2)-(8,9)+LINE#7 (15,3)-(6,15)+LINE#8 (15,1)-(6,16)+LINE#9 (2,4)-(4,4)+LINE#10 (15,0)-(1,4)+LINE#11 (16,12)-(9,16)+LINE#12 (2,16)-(4,16)+LINE#13 (11,14)-(17,16)+LINE#14 (16,16)-(14,17)+LINE#15 (5,3)-(5,16)+LINE#16 (12,16)-(17,17)+LINE#17 (2,3)-(0,17)+LINE#18 (4,3)-(3,14)
+ samples/programs/numberlink/ADC2014_QA/Q/NL_Q13.txt view
@@ -0,0 +1,19 @@+SIZE 18X21+LINE_NUM 17+LINE#1 (8,7)-(14,7)+LINE#2 (9,7)-(13,7)+LINE#3 (11,8)-(6,12)+LINE#4 (4,13)-(10,13)+LINE#5 (3,13)-(11,13)+LINE#6 (13,4)-(4,6)+LINE#7 (7,4)-(12,5)+LINE#8 (5,5)-(10,6)+LINE#9 (4,14)-(13,16)+LINE#10 (10,14)-(5,15)+LINE#11 (12,15)-(7,16)+LINE#12 (0,9)-(17,9)+LINE#13 (9,8)-(8,12)+LINE#14 (8,9)-(10,12)+LINE#15 (6,9)-(11,11)+LINE#16 (5,10)-(13,11)+LINE#17 (3,10)-(14,10)
+ samples/programs/numberlink/ADC2014_QA/Q/NL_Q14.txt view
@@ -0,0 +1,19 @@+SIZE 18X21+LINE_NUM 17+LINE#1 (8,7)-(14,7)+LINE#2 (9,7)-(13,7)+LINE#3 (11,8)-(6,12)+LINE#4 (4,13)-(10,13)+LINE#5 (3,13)-(11,13)+LINE#6 (13,4)-(4,6)+LINE#7 (7,4)-(12,5)+LINE#8 (5,5)-(10,6)+LINE#9 (4,14)-(13,16)+LINE#10 (10,14)-(5,15)+LINE#11 (12,15)-(8,16)+LINE#12 (0,9)-(17,9)+LINE#13 (9,8)-(8,12)+LINE#14 (8,9)-(10,12)+LINE#15 (6,9)-(11,11)+LINE#16 (5,10)-(13,11)+LINE#17 (3,10)-(14,10)
+ samples/programs/numberlink/ADC2014_QA/Q/NL_Q15.txt view
@@ -0,0 +1,37 @@+SIZE 35X19+LINE_NUM 35+LINE#1 (1,1)-(13,1)+LINE#2 (7,2)-(7,15)+LINE#3 (8,4)-(12,7)+LINE#4 (8,3)-(8,5)+LINE#5 (8,2)-(8,7)+LINE#6 (12,2)-(8,9)+LINE#7 (15,3)-(6,15)+LINE#8 (15,1)-(6,16)+LINE#9 (2,4)-(4,4)+LINE#10 (15,0)-(1,4)+LINE#11 (16,12)-(9,16)+LINE#12 (2,16)-(4,16)+LINE#13 (11,14)-(17,16)+LINE#14 (16,16)-(14,17)+LINE#15 (5,3)-(5,16)+LINE#16 (12,16)-(17,17)+LINE#17 (2,3)-(21,9)+LINE#18 (4,3)-(3,14)+LINE#19 (26,6)-(32,6)+LINE#20 (27,6)-(31,6)+LINE#21 (29,7)-(24,11)+LINE#22 (22,12)-(28,12)+LINE#23 (21,12)-(29,12)+LINE#24 (31,3)-(22,5)+LINE#25 (25,3)-(30,4)+LINE#26 (23,4)-(28,5)+LINE#27 (22,13)-(31,15)+LINE#28 (28,13)-(23,14)+LINE#29 (30,14)-(25,15)+LINE#30 (27,7)-(26,11)+LINE#31 (26,8)-(28,11)+LINE#32 (24,8)-(29,10)+LINE#33 (23,9)-(31,10)+LINE#34 (32,9)-(34,9)+LINE#35 (16,2)-(16,6)
+ samples/programs/numberlink/ADC2016/sample/01/NL_Q01.txt view
@@ -0,0 +1,18 @@+SIZE 10X10X2+LINE_NUM 7+LINE#1 (8,1,1) (8,9,2)+LINE#2 (2,4,1) (3,9,2)+LINE#3 (7,6,1) (1,9,2)+LINE#4 (6,6,1) (1,8,2)+LINE#5 (9,3,1) (5,7,2)+LINE#6 (1,1,1) (7,3,2)+LINE#7 (1,2,1) (6,3,2)++VIA#a (8,8,1) (8,8,2)+VIA#b (2,9,1) (2,9,2)+VIA#c (0,9,1) (0,9,2)+VIA#d (0,8,1) (0,8,2)+VIA#e (5,6,1) (5,6,2)+VIA#f (7,2,1) (7,2,2)+VIA#g (6,2,1) (6,2,2)+
+ samples/programs/numberlink/ADC2016/sample/01/T99_A01.txt view
@@ -0,0 +1,24 @@+SIZE 10X10x2+LAYER 1+05,05,05,05,05,05,05,05,05,05+05,06,06,06,06,06,06,06,01,05+05,07,07,07,07,07,07,06,01,05+05,01,01,01,01,01,01,01,01,05+05,01,02,02,02,02,02,02,02,02+05,01,01,01,01,01,01,01,01,02+05,05,05,05,05,05,04,03,01,02+04,04,04,04,04,04,04,03,01,02+04,03,03,03,03,03,03,03,01,02+03,03,02,02,02,02,02,02,02,02++LAYER 2+00,00,00,00,00,00,00,00,00,00+00,00,00,00,00,00,00,00,00,00+00,00,00,00,00,00,07,06,00,00+00,00,00,00,00,00,07,06,00,00+00,00,00,00,00,00,00,00,00,00+00,00,00,00,00,00,00,00,00,00+00,00,00,00,00,05,00,00,00,00+00,00,00,00,00,05,00,00,00,00+04,04,00,00,00,00,00,00,01,00+03,03,02,02,00,00,00,00,01,00
+ samples/programs/numberlink/README.md view
@@ -0,0 +1,11 @@+Numberlink solver+=================++This is a numberlink solver to solve problems in ADC (Algorithm+Design Contest) format.++See <http://www.sig-sldm.org/das/ADC/ADC.html> and+<https://github.com/dasadc/conmgr/blob/master/adc2016.md> for details.++Sample files in `ADC2013/`, `ADC2014_QA/`, `ADC2016/` directories+were downloaded from the above site.
+ samples/programs/numberlink/numberlink.hs view
@@ -0,0 +1,492 @@+{-# LANGUAGE FlexibleContexts, OverloadedStrings #-}+{-# OPTIONS_GHC -Wall #-}+module Main where++import Control.Applicative hiding (many, optional)+import Control.Monad+import Data.Array.IArray+import qualified Data.ByteString.Lazy.Char8 as BL+import Data.Char+import Data.Default.Class+import Data.List+import Data.Map.Strict (Map)+import qualified Data.Map.Strict as Map+import Data.Maybe+import qualified Data.PseudoBoolean as PB+import Data.Set (Set)+import qualified Data.Set as Set+import System.Console.GetOpt+import System.Environment+import System.Exit+import System.IO+import Text.Parsec hiding (try)+import qualified Text.Parsec.ByteString.Lazy as ParsecBL+import qualified ToySolver.SAT as SAT+import qualified ToySolver.SAT.PBO as PBO+import qualified ToySolver.SAT.Store.PB as PBStore++data Problem+  = Problem+  { probSize :: (Int,Int,Int)+  , probIsMultiLayer :: Bool+  , probLineNum :: Int+  , probLines :: [(Number, Cell, Cell)]+  , probVias :: [(Via, [Cell])]+  }+  deriving (Show)++type Number = Int+type Cell = (Int,Int,Int)+type Edge = (Cell, Cell)+type Via = String++parser ::  Stream s m Char => ParsecT s u m Problem+parser = do+  optional $ string "\xEF\xBB\xBF" -- BOM in UTF-8+  spaces+  _ <- string "SIZE"+  spaces+  w <- num+  _ <- char 'X'+  h <- num+  dd <- optionMaybe $ char 'X' >> num+  let (d,isMultiLayer) =+        case dd of+          Nothing -> (1, False)+          Just d -> (d, True)+  _ <- endOfLine++  let cell = do+        _ <- char '('+        x <- num+        _ <- char ','+        y <- num+        z <-+          if isMultiLayer then do+            _ <- char ','+            num+          else+            return 1+        _ <- char ')'+        spaces+        return (x,y,z)++  _ <- string "LINE_NUM"+  spaces+  n <- num+  _ <- endOfLine++  xs <- many $ do+    _ <- string "LINE#"+    i <- num+    spaces+    src <- cell+    optional $ char '-' >> spaces+    dst <- cell+    return (i,src,dst)++  ys <- many $ do+    _ <- string "VIA#"+    v <- many letter+    spaces+    cs <- cell `sepBy` optional (char '-' >> spaces)+    return (v,cs)++  return $ Problem (w,h,d) (isJust dd) n xs ys++  where+    num = read <$> many digit++type Encoded = (Array Cell (Array Number SAT.Var), Map Edge SAT.Var)++encode :: SAT.AddPBLin m enc => enc -> Options -> Problem -> m Encoded+encode enc opt Problem{ probSize = (w,h,d), probLineNum = n, probLines = ls, probVias = vias } = do+  let bnd = ((0,0,1), (w-1,h-1,d))+      cells = range bnd+      edges = [(a,b) | a@(x,y,z) <- cells, b <- [(x+1,y,z),(x,y+1,z)], inRange bnd b]+      adjacentEdges a@(x,y,z) =+        [(a,b) | b <- [(x+1,y,z),(x,y+1,z)], inRange bnd b] +++        [(b,a) | b <- [(x-1,y,z),(x,y-1,z)], inRange bnd b]+      ks = [1..n]++  -- ビアへの数字の割当を表す変数 (0 は数字なしを表す)+  viaVs <- liftM Map.fromList $ forM vias $ \(via, _) -> do+    let r = if optAssumeNoBlank opt+            then (1,n)+            else (0,n)+    zs <- liftM (array r) $ forM (range r) $ \k -> do+      v <- SAT.newVar enc+      return (k,v)+    return (via, zs)+  let viaPos = Map.fromList [(a,via) | (via,as) <- vias, a <- as]++  -- 各マスへの数字の割り当てを表す変数 (0 は数字なしを表す)+  vs <- liftM (array bnd) $ forM cells $ \a -> do+    case Map.lookup a viaPos of+      Just via -> return (a, viaVs Map.! via)+      Nothing -> do+        let r = if optAssumeNoBlank opt+                then (1,n)+                else (0,n)+        zs <- liftM (array r) $ forM (range r) $ \k -> do+          v <- SAT.newVar enc+          return (k,v)+        return (a, zs)+  -- 各辺の有無を表す変数+  evs <- liftM Map.fromList $ forM edges $ \e -> do+    v <- SAT.newVar enc+    return (e,v)++  -- 初期数字+  let m0 = Map.fromList [(c,k) | (k,src,dst) <- ls, c <- [src,dst]]+  forM_ (Map.toList m0) $ \(c,k) -> do+    SAT.addClause enc [vs!c!k]++  -- 各マスには高々ひとつしか数字が入らない+  forM_ (range bnd) $ \a -> do+    SAT.addExactly enc [v | v <- elems (vs!a)] 1+  forM_ (Map.toList evs) $ \((a,b),v) ->+    forM_ ks $ \k -> do+      -- 辺で連結されるマスは同じ数字+      SAT.addClause enc [-v, -(vs!a!k), vs!b!k]+      SAT.addClause enc [-v, -(vs!b!k), vs!a!k]+      -- 連結されない隣接マスは違う数字+      when (optAssumeNoDetour opt) $+        SAT.addClause enc [v, -(vs!a!k), -(vs!b!k)]++  forM_ (range bnd) $ \a -> do+    if a `Map.member` m0 then do+      -- 初期数字の入っているマスの次数は1+      SAT.addExactly enc [evs Map.! e | e <- adjacentEdges a] 1+    else if a `Map.member` viaPos then do+      -- ビアの次数は高々1 (ADC2016ルールでも中間層は0になるので注意)+      SAT.addAtMost enc [evs Map.! e | e <- adjacentEdges a] 1+    else do+      -- 初期数字の入っていないマスの次数は0か2+      if optAssumeNoBlank opt then do+        SAT.addExactly enc [evs Map.! e | e <- adjacentEdges a] 2+      else do+        let v = vs!a!0+        -- v → deg(a)=0+        -- SAT.addPBAtMostSoft enc v [(1, evs Map.! e) | e <- adjacentEdges a] 0+        forM_ (adjacentEdges a) $ \e -> SAT.addClause enc [-v, -(evs Map.! e)]     +        -- ¬v → deg(a)=2+        SAT.addPBExactlySoft enc (-v) [(1, evs Map.! e) | e <- adjacentEdges a] 2+        -- ¬v → deg(a)>0+        -- SAT.addClause enc $ v : [evs Map.! e | e <- adjacentEdges a]++  -- コの字の禁止+  when (optAssumeNoDetour opt) $ do+    forM_ [1..d] $ \z -> do+      forM_ [0..w-2] $ \x -> do+        forM_ [0..h-2] $ \y -> do+          let a = (x, y, z)+              b = (x+1, y, z)+              c = (x, y+1, z)+              d = (x+1, y+1, z)+          SAT.addAtMost enc [evs Map.! e | e <- [(a,b),(a,c),(b,d),(c,d)]] 2++  -- https://kaigi.org/jsai/webprogram/2016/pdf/67.pdf の追加成約+  when (optJSAI2016 opt) $ do+    let bs = Set.fromList [a | a <- range bnd, a `Map.notMember` m0, a `Map.notMember` viaPos]+    forM_ (range bnd) $ \a@(x,y,z) -> do+      let a_n = (x,y-1,z)+          a_s = (x,y+1,z)+          a_w = (x-1,y,z)+          a_e = (x+1,y,z)+          a_nw = Set.fromList $ takeWhile (inRange bnd) $ tail $ iterate (\(x,y,z) -> (x-1,y-1,z)) a+          a_ne = Set.fromList $ takeWhile (inRange bnd) $ tail $ iterate (\(x,y,z) -> (x+1,y-1,z)) a+          a_sw = Set.fromList $ takeWhile (inRange bnd) $ tail $ iterate (\(x,y,z) -> (x-1,y+1,z)) a+          a_se = Set.fromList $ takeWhile (inRange bnd) $ tail $ iterate (\(x,y,z) -> (x+1,y+1,z)) a+      when (inRange bnd a_n && inRange bnd a_w && a_nw `Set.isSubsetOf` bs) $ do+        SAT.addAtMost enc [evs Map.! (a_w,a), evs Map.! (a_n,a)] 1+      when (inRange bnd a_n && inRange bnd a_e && a_ne `Set.isSubsetOf` bs) $ do+        SAT.addAtMost enc [evs Map.! (a,a_e), evs Map.! (a_n,a)] 1+      when (inRange bnd a_s && inRange bnd a_w && a_sw `Set.isSubsetOf` bs) $ do+        SAT.addAtMost enc [evs Map.! (a_w,a), evs Map.! (a,a_s)] 1+      when (inRange bnd a_s && inRange bnd a_e && a_se `Set.isSubsetOf` bs) $ do+        SAT.addAtMost enc [evs Map.! (a,a_e), evs Map.! (a,a_s)] 1++  forM_ ls $ \(k, (_,_,z1), (_,_,z2)) -> do+    let vsk = [vs!k | (_, vs) <- Map.toList viaVs]+    if z1 == z2 then do+      -- ADC2016では(層をまたぐLINE数)=(VIA数)なので、他のLINEはVIAを使えない+      when (optADC2016 opt) $ SAT.addAtMost enc vsk 0+    else do+      -- 異なる盤面にある数字はビアを必ず使う+      SAT.addClause enc vsk+      -- ADC2016では(層をまたぐLINE数)=(VIA数)+      when (optADC2016 opt) $ SAT.addAtMost enc vsk 1++  return (vs, evs)++encodeObj :: SAT.AddPBLin m enc => enc -> Options -> Problem -> Encoded -> m SAT.PBLinSum+encodeObj enc opt Problem{ probSize = (w,h,d) } (cells,edges) = do+  let (o1, o2) = fromJust (optOptimize opt)+  obj1 <-+    if not o1 then do+      return []   +    else if optAssumeNoBlank opt then do+      v <- SAT.newVar enc+      SAT.addClause enc [v]+      return [(fromIntegral (w*h*d), v)]+    else+      return [(1, -(vs!0)) | vs <- elems cells]+  obj2 <-+    if not o2 then do+      return []+    else do+      forM (range (bounds cells)) $ \a@(x,y,z) -> do+        let w = ((x-1,y,z),a)+            e = (a,(x+1,y,z))+            n = ((x,y-1,z),a)+            s = (a,(x,y+1,z))+        v <- SAT.newVar enc+        forM_ [e,w] $ \e1 -> do+          case Map.lookup e1 edges of+            Nothing -> return ()+            Just v1 -> do+              forM_ [n,s] $ \e2 -> do+                case Map.lookup e2 edges of+                  Nothing -> return ()+                  Just v2 -> SAT.addClause enc [-v1, -v2, v]+        return (1,v)+  return $ obj1 ++ obj2++type Solution = (Map Cell Number, Set Edge)++decode :: Problem -> Encoded -> SAT.Model -> Solution+decode prob (vs, evs) m = (solCells, solEdges)+  where+    solCells = Map.fromList $ do+      a <- range (bounds vs)+      guard $ a `Set.member` usedCells+      case [k | (k,v) <- assocs (vs!a), SAT.evalLit m v] of+        k:_ -> return (a,k)+        [] -> mzero+    solEdges = Set.fromList [e | e@(a,_) <- edges, a `Set.member` usedCells]+    +    edges = [e | (e,ev) <- Map.toList evs, SAT.evalLit m ev]+    adjacents = Map.fromListWith Set.union $ concat $ [[(a, Set.singleton b), (b, Set.singleton a)] | (a,b) <- edges]+    usedVias = Set.fromList [(x,y,z) | ((x,y),zs) <- Map.toList cs, z <- [Set.findMin zs .. Set.findMax zs]]+      where+        cs = Map.fromList [((x,y), Set.singleton z) | (_,as) <- probVias prob, a@(x,y,z) <- as, a `Map.member` adjacents]+    usedCells = Set.union usedVias cs+      where+        cs = Set.unions [g (Set.fromList [a,b]) Set.empty | (_k,a,b) <- probLines prob]+        g xs visited+          | Set.null xs = visited+          | otherwise = g (Set.unions [Map.findWithDefault Set.empty x adjacents Set.\\ visited | x <- Set.toList xs]) (Set.union xs visited)++evalObj :: Options -> Problem -> Solution -> Integer+evalObj opt Problem{ probSize = (w,h,d) } (cells,edges) = obj1 + obj2+  where+    (o1, o2) = fromJust (optOptimize opt)+    bnd = ((0,0,1),(w-1,h-1,d))+    obj1+      | not o1 = 0+      | otherwise = fromIntegral $ Map.size cells+    obj2+      | not o2 = 0+      | otherwise = sum $ do+          a@(x,y,z) <- range bnd+          let w = ((x-1,y,z),a)+              e = (a,(x+1,y,z))+              n = ((x,y-1,z),a)+              s = (a,(x,y+1,z))+          if null [() | e1 <- [e,w], e1 `Set.member` edges, e2 <- [n,s], e2 `Set.member` edges] then+            return 0+          else+            return 1++createSolver :: Options -> Problem -> IO (IO (Maybe Solution))+createSolver opt prob = do+  solver <- SAT.newSolver+  SAT.setLogger solver $ hPutStrLn stderr+  encoded <- encode solver opt prob+  unless (optAssumeNoBlank opt) $ do+    forM_ (elems (fst encoded)) $ \xs -> do+      SAT.setVarPolarity solver (xs!0) False+  let m = do+        ret <- SAT.solve solver+        if ret then do+          m <- SAT.getModel solver+          let sol = decode prob encoded m+          SAT.addClause solver $ blockingClause prob encoded sol+          return $ Just sol+        else+          return Nothing+  return m++printSolution :: Problem -> Solution -> IO ()+printSolution prob (cells, _) = do+  let (w,h,d) = probSize prob+  forM_ [1 .. d] $ \z -> do+    when (probIsMultiLayer prob) $ do+      unless (z == 1) $ putStrLn ""+      putStrLn $ "LAYER " ++ show z+    forM_ [0 .. h-1] $ \y -> do+      putStrLn $ concat $ intersperse ","+       [ case Map.lookup (x,y,z) cells of+           Nothing -> replicate width '0'+           Just k -> replicate (width - length (show k)) '0' ++ show k+       | x <- [0 .. w-1]+       ]+  where+    width = length $ show (probLineNum prob)++blockingClause :: Problem -> Encoded -> Solution -> SAT.Clause+blockingClause _prob (_,edgesEnc) (_,edges) = [- (edgesEnc Map.! e) | e <- Set.toList edges]++data Options+  = Options+  { optOptimize :: Maybe Obj+  , optAssumeNoBlank :: Bool+  , optAssumeNoDetour :: Bool+  , optJSAI2016 :: Bool+  , optADC2016 :: Bool+  , optNumSolutions :: Int+  }++instance Default Options where+  def =+    Options+    { optOptimize = Nothing+    , optAssumeNoBlank = False+    , optAssumeNoDetour = False+    , optJSAI2016 = False+    , optADC2016 = False+    , optNumSolutions = 1+    }++type Obj = (Bool,Bool)++options :: [OptDescr (Options -> Options)]+options =+    [ Option [] ["optimize"]+        (OptArg (\arg opt -> opt{ optOptimize = Just (maybe (True,True) readObj arg) }) "<str>")+        "Specify objective functions (-n option will be ignored): both (default), length, corners"+    , Option [] ["no-blank"]+        (NoArg (\opt -> opt{ optAssumeNoBlank = True }))+        "Assume no blank cells in solution"+    , Option [] ["no-detour"]+        (NoArg (\opt -> opt{ optAssumeNoDetour = True }))+        "Assume no detour in solution"+    , Option [] ["jsai2016"]+        (NoArg (\opt -> opt{ optJSAI2016 = True }))+        "Add constraints of JSATI2016 paper of Tatsuya Seko et.al."+    , Option [] ["adc2016"]+        (NoArg (\opt -> opt{ optADC2016 = True }))+        "Add constraints specific to ADC2016 rule"+    , Option ['n'] []+        (ReqArg (\val opt -> opt{ optNumSolutions = read val }) "<int>")+        "Maximal number of solutions to enumerate, or negative value for all solutions (default: 1)"+    ]+  where+    readObj = f . map toLower+      where+        f "both" = (True, True)+        f "length" = (True, False)+        f "corners" = (False, True)+        f _ = error "unknown objective"++header :: String+header = unlines+  [ "Usage:"+  , "  numberlink [OPTION]... problem.txt"+  , "  numberlink [OPTION]... problem.txt encoded.opb"+  , ""+  , "Options:"+  ]++showHelp :: Handle -> IO ()+showHelp h = hPutStrLn h (usageInfo header options)++main :: IO ()+main = do+  args <- getArgs+  case getOpt Permute options args of+    (_,_,errs@(_:_)) -> do+      mapM_ putStrLn errs+      exitFailure+    (o,args2,[]) -> do+      let opt = foldl (flip id) def o+      case args2 of+        [fname] -> do+          r <- ParsecBL.parseFromFile parser fname+          case r of+            Left err -> error (show err)+            Right prob@Problem{ probSize = (w,h,d) } -> do+              putStrLn $ "SIZE " ++ show w ++ "X" ++ show h +++                           (if probIsMultiLayer prob then "X" ++ show d else "")+              case optOptimize opt of+                Nothing -> do+                  solve <- createSolver opt prob+                  let loop n+                        | n == 0 = return ()+                        | otherwise = do+                            m <- solve+                            case m of+                              Nothing -> return ()+                              Just sol -> do+                                printSolution prob sol+                                putStrLn ""+                                loop (if n > 0 then n - 1 else n)+                  loop (optNumSolutions opt)+                Just _ -> do+                  solver <- SAT.newSolver+                  SAT.setLogger solver $ hPutStrLn stderr+                  encoded@(cells,_edges) <- encode solver opt prob+                  unless (optAssumeNoBlank opt) $ do+                    forM_ (elems cells) $ \xs -> do+                      SAT.setVarPolarity solver (xs!0) False+                  obj <- encodeObj solver opt prob encoded+                  pbo <- PBO.newOptimizer2 solver obj (\m -> evalObj opt prob (decode prob encoded m))+                  PBO.setLogger pbo $ hPutStrLn stderr+                  PBO.setOnUpdateBestSolution pbo $ \m val -> do+                    hPutStrLn stderr $ "# obj = " ++ show val+                    hFlush stderr+                    let sol = decode prob encoded m+                    printSolution prob sol+                    putStrLn ""+                    hFlush stdout+                  PBO.optimize pbo++        [fname, fname2] -> do+          r <- ParsecBL.parseFromFile parser fname+          case r of+            Left err -> error (show err)+            Right prob -> do+              store <- PBStore.newPBStore+              obj <- do+                encoded <- encode store opt prob+                case optOptimize opt of+                  Nothing -> return Nothing+                  Just _ -> do+                    obj <- encodeObj store opt prob encoded+                    return $ Just [(c,[v]) | (c,v) <- obj]+              opb <- PBStore.getPBFormula store+              PB.writeOPBFile fname2 $ opb{ PB.pbObjectiveFunction = obj }+        _ -> do+          showHelp stderr++sampleFile :: BL.ByteString+sampleFile = BL.unlines+  [ "SIZE 15X15"+  , "LINE_NUM 12"+  , "LINE#1 (10,0)-(4,14)"+  , "LINE#2 (9,5)-(9,14)"+  , "LINE#3 (2,7)-(4,12)"+  , "LINE#4 (2,5)-(7,13)"+  , "LINE#5 (2,4)-(4,10)"+  , "LINE#6 (2,2)-(5,5)"+  , "LINE#7 (6,5)-(5,10)"+  , "LINE#8 (5,0)-(7,9)"+  , "LINE#9 (10,2)-(12,7)"+  , "LINE#10 (7,1)-(12,9)"+  , "LINE#11 (9,8)-(12,12)"+  , "LINE#12 (8,9)-(12,10)"+  ]++sample :: Problem+Right sample = parse parser "sample" sampleFile
+ samples/programs/shortest-path/shortest-path.hs view
@@ -0,0 +1,100 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Main where++import Control.Exception+import Control.Monad+import qualified Data.ByteString.Lazy.Char8 as BL+import Data.Char+import Data.Foldable (toList)+import qualified Data.HashMap.Strict as HashMap+import Data.Int+import Data.List+import Data.Maybe+import Data.Monoid+import Data.Ord+import qualified Data.Sequence as Seq+import System.Console.GetOpt+import System.Environment+import System.Exit+import System.IO+import qualified ToySolver.Graph.ShortestPath as ShortestPath+import ToySolver.Internal.Util (setEncodingChar8)++data Flag+  = Help+  | PrintResult+  | Method String+  deriving Eq++options :: [OptDescr Flag]+options =+    [ Option ['h'] ["help"] (NoArg Help) "show help"+    , Option []    ["print"]  (NoArg PrintResult)  "print result"+    , Option []    ["method"] (ReqArg Method "STRING") "method: dijkstra, bellman-ford, floyd-warshall"+    ]++header :: String+header = unlines+  [ "Usage:"+  , "    shortest-path [OPTIONS] INPUTFILE VERTEX.."+  , ""+  , "Options:"+  ]++main :: IO ()+main = do+#ifdef FORCE_CHAR8+  setEncodingChar8+#endif+  args <- getArgs+  case getOpt Permute options args of+    (o,_,[])+      | Help `elem` o -> putStrLn (usageInfo header options)+    (o,fname:vs',[]) -> do+      let method = last ("dijkstra" : [m | Method m <- o])+          vs0 = map read vs'+          vs = if null vs0 then [1] else vs0+      es <- load fname+      let g :: ShortestPath.Graph Int Int64 Int+          g = fmap toList $ HashMap.fromListWith (<>) [(s, Seq.singleton (t,fromIntegral w,i)) | (i,(s,t,w)) <- zip [(1::Int)..] es]+      case filter (\c -> c /= '-' && c /= '_') (map toLower method) of+        "dijkstra" -> do+          let ret = ShortestPath.dijkstra ShortestPath.unit g vs+          _ <- evaluate ret+          when (PrintResult `elem` o) $ do+            forM_ (sortBy (comparing fst) (HashMap.toList ret)) $ \(v, (cost,_)) -> do+              putStrLn $ show v ++ ": " ++ show cost+        "bellmanford" -> do+          let ret = ShortestPath.bellmanFord ShortestPath.unit g vs+          _ <- evaluate ret+          when (PrintResult `elem` o) $ do+            forM_ (sortBy (comparing fst) (HashMap.toList ret)) $ \(v, (cost,_)) -> do+              putStrLn $ show v ++ ": " ++ show cost+        "floydwarshall" -> do+          let ret = ShortestPath.floydWarshall ShortestPath.unit g+          _ <- evaluate ret+          when (PrintResult `elem` o) $ do+            forM_ (sortBy (comparing fst) (HashMap.toList ret)) $ \(v, m) -> do+              forM_ (sortBy (comparing fst) (HashMap.toList m)) $ \(u, (cost,_)) -> do+                putStrLn $ show v ++ "-" ++ show u ++ ": " ++ show cost+        _ -> error ("unknown method: " ++ method)+    (_,_,errs) -> do+      hPutStrLn stderr $ concat errs ++ usageInfo header options+      exitFailure++load :: FilePath -> IO [(Int,Int,Int)]+load fname = do+  s <- BL.readFile fname+  let f l = do+        -- 'BL.stripPrefix' is available only on bytestring >=0.10.8.0,+        -- But we still want to support bytestring-0.10.4.0 (lts-2.22) and bytestring-0.10.6.0 (lts-3.22).+        (c,l2) <- BL.uncons l+        guard $ c == 'a'+        (v,l3) <- BL.readInt $ BL.dropWhile isSpace l2+        (u,l4) <- BL.readInt $ BL.dropWhile isSpace l3+        (w,_)  <- BL.readInt $ BL.dropWhile isSpace l4+        return (v,u,w)+  return $ catMaybes [f l | l <- BL.lines s]
samples/programs/sudoku/sudoku.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ScopedTypeVariables, CPP #-} {-# OPTIONS_GHC -Wall #-} module Main where @@ -9,9 +9,14 @@ import System.Exit import System.IO import qualified ToySolver.SAT as SAT+import ToySolver.Internal.Util (setEncodingChar8)  main :: IO () main = do+#ifdef FORCE_CHAR8+  setEncodingChar8+#endif+   args <- getArgs   case args of     [fname] -> do
+ samples/programs/survey-propagation/survey-propagation.hs view
@@ -0,0 +1,136 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-}+import Control.Exception+import Control.Monad+import Data.Default.Class+import Data.List+import System.Console.GetOpt+import System.Environment+import System.Exit+import System.IO+import qualified ToySolver.Text.MaxSAT as MaxSAT+import qualified ToySolver.SAT.MessagePassing.SurveyPropagation as SP+#ifdef ENABLE_OPENCL+import Control.Parallel.OpenCL+import qualified ToySolver.SAT.MessagePassing.SurveyPropagation.OpenCL as SPCL+#endif++data Options+  = Options+  { optOpenCL :: Bool+  , optOpenCLPlatform :: Maybe String+  , optOpenCLDevice :: Int+  , optNThreads :: Int+  }++instance Default Options where+  def =+    Options+    { optOpenCL = False+    , optOpenCLPlatform = Nothing+    , optOpenCLDevice = 0+    , optNThreads = 1+    }++options :: [OptDescr (Options -> Options)]+options =+  [ Option [] ["opencl"] (NoArg (\opt -> opt{ optOpenCL = True })) "use OpenCL version"+  , Option [] ["opencl-platform"] (ReqArg (\val opt -> opt{ optOpenCLPlatform = Just val }) "<string>") "OpenCL platform to use"+  , Option [] ["opencl-device"] (ReqArg (\val opt -> opt{ optOpenCLDevice = read val }) "<integer>") "OpenCL device to use"+  , Option [] ["threads"] (ReqArg (\val opt -> opt{ optNThreads = read val }) "<integer>") "number of threads"+  ]++showHelp :: Handle -> IO ()+showHelp h = hPutStrLn h (usageInfo header options)++header :: String+header = unlines+  [ "Usage:"+  , "  spcl [OPTION]... [file.cnf|file.wcnf]"+  , ""+  , "Options:"+  ]++#ifdef ENABLE_OPENCL++getPlatform :: Maybe String -> IO CLPlatformID+getPlatform m = do+  putStrLn "Listing OpenCL platforms..."+  platforms <- clGetPlatformIDs+  case platforms of+    [] -> error "No OpenCL platform found"+    _ -> do+      tbl <- forM platforms $ \platform -> do+        s <- clGetPlatformInfo platform CL_PLATFORM_NAME+        devs <- clGetDeviceIDs platform CL_DEVICE_TYPE_ALL+        putStrLn $ "  " ++ s ++ " (" ++ show (length devs) ++ " devices)"+        forM_ (zip [0..] devs) $ \(i,dev) -> do+          devname <- clGetDeviceName dev +          ts <- clGetDeviceType dev+          let f t =+                case t of+                  CL_DEVICE_TYPE_CPU -> "CPU"+                  CL_DEVICE_TYPE_GPU -> "GPU"+                  CL_DEVICE_TYPE_ACCELERATOR -> "ACCELERATOR"+                  CL_DEVICE_TYPE_DEFAULT -> "DEFAULT"+                  CL_DEVICE_TYPE_ALL -> "ALL"+          putStrLn $ "    " ++ show i ++ ": " ++ devname ++ " (" ++ intercalate "," (map f ts) ++ ")"+        return (s,platform)+      case m of+        Nothing -> return (snd (head tbl))+        Just name ->+          case lookup name tbl of+            Nothing -> error ("no such platform: " ++ name)+            Just p -> return p++#endif++main :: IO ()+main = do+  args <- getArgs+  case getOpt Permute options args of+    (_,_,errs@(_:_)) -> do+      mapM_ putStrLn errs+      exitFailure++    (o,[fname],_) -> do+      let opt = foldl (flip id) def o+      handle (\(e::SomeException) -> hPrint stderr e) $ do+        Right wcnf <- MaxSAT.parseFile fname++#ifdef ENABLE_OPENCL+        if optOpenCL opt then do+          platform <- getPlatform (optOpenCLPlatform opt)+          devs <- clGetDeviceIDs platform CL_DEVICE_TYPE_ALL+          dev <-+            if optOpenCLDevice opt < length devs then+              return (devs !! optOpenCLDevice opt)+            else do+              name <- clGetPlatformInfo platform CL_PLATFORM_NAME+              error ("platform " ++ name ++ " has only " ++ show (length devs) ++ " devices")+          context <- clCreateContext [] [dev] print+          solver <- SPCL.newSolver putStrLn context dev+            (MaxSAT.numVars wcnf) [(fromIntegral w, clause) | (w,clause) <- MaxSAT.clauses wcnf]+          -- Rand.withSystemRandom $ SPCL.initializeRandom solver+          print =<< SPCL.propagate solver+          forM_ [1 .. MaxSAT.numVars wcnf] $ \v -> do+            prob <- SPCL.getVarProb solver v+            print (v,prob)+          SPCL.deleteSolver solver+#else+        if False then do+          return ()+#endif+        else do+          solver <- SP.newSolver+            (MaxSAT.numVars wcnf) [(fromIntegral w, clause) | (w,clause) <- MaxSAT.clauses wcnf]+          SP.setNThreads solver (optNThreads opt)+          -- Rand.withSystemRandom $ SP.initializeRandom solver+          print =<< SP.propagate solver+          forM_ [1 .. MaxSAT.numVars wcnf] $ \v -> do+            prob <- SP.getVarProb solver v+            print (v,prob)+          SP.deleteSolver solver++    _ -> do+       showHelp stderr
samples/programs/svm2lp/svm2lp.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# OPTIONS_GHC -Wall #-} import Control.Monad import qualified Data.Foldable as F@@ -8,12 +9,15 @@ import Data.IntMap (IntMap) import qualified Data.IntMap as IntMap import qualified Data.Map as Map+import Data.Scientific+import qualified Data.Text.Lazy.IO as TLIO import ToySolver.Data.MIP ((.==.), (.>=.)) import qualified ToySolver.Data.MIP as MIP import System.Console.GetOpt import System.Environment import System.Exit import System.IO+import ToySolver.Internal.Util (setEncodingChar8)  type Problem = [(Int, IntMap Double)] @@ -28,7 +32,7 @@       case words s of         (y : xs) -> (read (dropWhile ('+'==) y), IntMap.fromList [(read v, read val) | x <- xs, let [v,val] = splitOn ":" x]) -primal :: Maybe Double -> Problem -> MIP.Problem+primal :: Maybe Double -> Problem -> MIP.Problem Scientific primal c prob   = def   { MIP.objectiveFunction = def@@ -61,7 +65,7 @@   :: Maybe Double   -> (IntMap Double -> IntMap Double -> Double)   -> Problem-  -> MIP.Problem+  -> MIP.Problem Scientific dual c kernel prob   = def   { MIP.objectiveFunction = def@@ -135,6 +139,10 @@  main :: IO () main = do+#ifdef FORCE_CHAR8+  setEncodingChar8+#endif+   args <- getArgs   case getOpt Permute options args of     (_,_,errs@(_:_)) -> do@@ -162,9 +170,9 @@                      Nothing -> error "--gamma= must be specified"                      Just gamma -> dual (optC opt) (gaussian gamma) svm                  _ -> error $ "unknown kernel: "  ++ optKernel opt-          case MIP.toLPString mip of+          case MIP.toLPString def mip of             Left err -> do               hPutStrLn stderr err               exitFailure             Right s -> do-              putStr s+              TLIO.putStr s
+ samples/qbf/aim-50-1_6-yes1-3-00-shuffled.qdimacs view
@@ -0,0 +1,470 @@+p cnf 278 466+e 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 0+a 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 0+e 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 0+129 -242 0+27 -172 0+-275 102 0+-102 -255 0+-208 139 0+141 -231 0+105 -273 0+-171 -128 0+-146 -224 0+86 -36 0+-240 -131 0+43 -156 0+75 -25 0+-102 -278 0+-67 68 66 0+-177 -121 0+-51 85 -95 0+60 -11 0+143 -227 0+132 -240 0+-231 -140 0+-146 -153 0+86 87 -89 0+-234 -136 0+72 -23 0+-214 -143 0+-269 -109 0+-180 -118 0+-129 -244 0+114 -207 0+-34 84 0+-59 81 -82 0+-181 -117 0+-173 26 0+-73 -66 58 0+109 -240 0+95 -45 0+-95 -94 -93 0+107 -211 0+-177 22 0+101 -256 0+-119 -202 0+-86 61 88 0+-252 -121 0+-188 -110 0+-103 -220 0+-243 128 0+-278 -100 0+46 -153 0+-182 17 0+-62 -65 64 0+-223 147 0+-224 -147 0+-264 -113 0+94 -83 78 0+-211 -105 0+-262 -114 0+130 -243 0+-229 -140 0+-158 41 0+75 -92 79 0+-81 79 69 0+-139 -231 0+98 -53 -99 0+80 81 82 0+-32 82 0+-276 103 0+-111 -267 0+87 86 -88 0+-1 50 0+-107 -270 0+-162 -137 0+-135 -213 0+108 -268 0+-251 -122 0+56 -75 -76 0+-86 -84 -85 0+78 -28 0+-190 -108 0+-174 -125 0+-271 107 0+-238 132 0+-41 91 0+-272 104 0+136 -236 0+-264 105 0+-238 -133 0+135 -235 0+48 -151 0+64 -66 65 0+1 -198 0+-185 14 0+-58 61 60 0+-145 -205 0+-226 144 0+73 75 -74 0+138 -203 0+72 74 73 0+-69 70 -51 0+-219 -138 0+-113 -185 0+142 -200 0+-218 -134 0+-152 -147 0+-47 97 0+-192 -106 0+-89 97 91 0+-48 98 0+-128 -204 0+-132 -241 0+125 -248 0+115 -262 0+-258 -101 0+-236 134 0+126 -215 0+119 -256 0+-112 -186 0+71 -72 -70 0+-31 81 0+-196 -102 0+74 -80 95 0+144 -225 0+-254 120 0+-49 99 0+-228 -142 0+-56 -57 -54 0+146 -211 0+49 -150 0+88 89 -90 0+-163 -136 0+-132 -167 0+-135 -237 0+-99 53 52 0+-117 -210 0+-129 -216 0+-262 112 0+-18 67 0+-176 -122 0+-195 4 0+-146 -222 0+133 -239 0+58 -54 57 0+-218 -125 0+-144 -227 0+93 -73 -77 0+-274 100 0+-245 -127 0+-199 141 0+-197 2 0+-139 -229 0+-200 -125 0+-221 103 0+-184 15 0+110 -268 0+-147 -208 0+146 -225 0+-226 143 0+-219 -111 0+-204 -144 0+122 -252 0+-122 -250 0+139 -233 0+142 -230 0+-30 80 0+-87 84 67 0+63 -64 -62 0+-179 20 0+-265 113 0+94 92 -93 0+-105 -274 0+104 -271 0+-269 110 0+108 -267 0+89 90 -91 0+7 -192 0+-112 -266 0+42 -157 0+-183 16 0+145 -213 0+-4 53 0+-52 -70 -71 0+-149 -199 0+-40 90 0+-196 3 0+-206 -120 0+-150 -149 0+-238 -134 0+125 -247 0+-178 21 0+-181 18 0+116 -209 0+-53 50 52 0+-144 -228 0+77 76 78 0+96 -98 -97 0+-108 -209 0+-255 119 0+-123 -250 0+-216 115 0+-100 -276 0+-203 122 0+-275 -100 0+-258 117 0+-102 -220 0+-79 -78 -80 0+135 -236 0+137 -235 0+50 51 52 0+56 -54 -57 0+-126 -173 0+-111 -187 0+-270 -108 0+55 -50 54 0+-178 -120 0+-103 -195 0+-139 -232 0+-65 79 -73 0+-263 114 0+-27 77 0+-154 -145 0+-80 70 62 0+62 -13 0+34 -165 0+-121 -251 0+-225 -145 0+-141 -212 0+128 -244 0+-19 68 0+-253 -121 0+121 -254 0+148 -223 0+-172 -127 0+130 -206 0+130 -205 0+132 -239 0+59 -60 57 0+-212 -117 0+-111 -217 0+133 -204 0+-220 149 0+63 -62 -55 0+-207 -118 0+-241 -130 0+-51 53 50 0+-186 13 0+-113 -263 0+-39 89 0+-241 -131 0+-229 -143 0+36 -163 0+96 -46 0+-245 -128 0+-235 -136 0+-156 -143 0+38 -161 0+-171 28 0+-267 -110 0+35 -164 0+-259 117 0+-33 83 0+-62 -61 -63 0+124 -248 0+-158 -141 0+-152 47 0+-116 -182 0+-276 -102 0+138 -234 0+-160 -139 0+-107 -191 0+-12 61 0+-2 51 0+126 -247 0+-16 65 0+-274 -104 0+-217 121 0+-137 -233 0+-161 -138 0+-164 -135 0+-198 -100 0+-188 11 0+98 75 84 0+-260 -117 0+-129 -202 0+-58 -60 -59 0+-140 -159 0+-189 -109 0+-244 -127 0+-239 -109 0+-256 -120 0+-129 -200 0+116 -261 0+129 -243 0+87 -37 0+88 -38 0+89 90 93 0+124 -249 0+-249 -125 0+69 -20 0+-130 -242 0+148 -215 0+-151 -148 0+-100 -277 0+-64 68 99 0+-114 -184 0+-183 -115 0+-194 5 0+-228 -132 0+-221 -148 0+72 -73 71 0+104 -270 0+-273 100 0+-88 -72 0+24 -175 0+-26 76 0+64 -15 0+123 -251 0+118 -257 0+-168 -131 0+-234 -137 0+-246 -126 0+-166 -133 0+-138 -232 0+-61 62 60 0+-98 62 -76 0+107 -272 0+-116 -260 0+-160 39 0+-187 12 0+-123 -175 0+-5 54 0+79 -29 0+6 -193 0+73 -24 0+118 -258 0+137 -210 0+97 96 -94 0+-68 -67 69 0+-76 -81 93 0+-275 -104 0+-44 94 0+-201 -143 0+121 -255 0+66 -17 0+57 -8 0+-266 -110 0+120 -253 0+94 92 82 0+-206 -112 0+61 -71 0+-248 106 0+-126 -245 0+147 -222 0+-56 -75 -74 0+30 -169 0+-176 23 0+-257 117 0+-261 -115 0+111 -265 0+126 -201 0+-166 33 0+-272 -106 0+52 -3 0+-213 101 0+85 -35 0+9 -190 0+-78 77 79 0+140 -212 0+-252 120 0+32 -167 0+140 -232 0+-155 44 0+-174 25 0+-112 -215 0+-91 -63 99 0+-42 92 0+-223 -146 0+101 -277 0+-202 131 0+40 -159 0+-226 145 0+67 65 66 0+-124 -250 0+-57 55 -96 0+-242 131 0+-201 131 0+37 -162 0+-247 -106 0+-221 149 0+-6 55 0+-193 -105 0+-77 56 76 0+-273 -104 0+56 -7 0+-119 -179 0+-271 106 0+-14 63 0+-191 8 0+85 83 -84 0+-139 -230 0+-9 58 0+-259 -118 0+112 -263 0+-260 -115 0+80 -81 -79 0+31 -168 0+-142 -157 0+-90 67 91 0+-134 -165 0+-199 113 0+-71 52 -69 0+-246 127 0+-124 -205 0+-68 -67 51 0+-154 45 0+111 -266 0+156 204 271 163 182 247 196 151 180 202 229 207 218 225 266 227 210 240 160 215 169 222 165 228 200 186 272 195 177 214 274 179 172 253 258 260 166 219 242 278 236 181 162 237 209 189 270 208 251 254 261 275 199 212 201 244 221 263 239 168 255 164 217 216 206 259 153 157 178 154 197 246 158 188 176 243 269 194 235 124 230 174 175 248 152 226 223 257 193 155 273 232 231 256 276 245 173 203 277 249 198 238 234 267 220 159 241 170 192 262 187 161 213 211 205 224 268 265 183 264 184 167 252 250 191 171 185 150 190 233 0+93 -43 0+-96 -94 95 0+99 -97 96 0+-50 54 -55 0+-116 -259 0+-149 -222 0+-129 -170 0+-194 -104 0+-141 -208 0+-82 83 84 0+10 -189 0+-106 -246 0+-114 -261 0+-254 102 0+144 -224 0+89 90 -92 0+29 -170 0+-219 136 0+-207 -149 0+-268 109 0+-103 -277 0+127 -214 0+-180 19 0+134 -237 0+-249 -123 0+-119 -257 0+-216 123 0+-142 -227 0+86 -85 -87 0+-214 123 0+-100 -253 0+-155 -144 0+-278 -101 0+-218 -148 0+-107 -269 0+-22 71 0+-264 112 0+-265 112 0+59 -10 0+-140 -230 0+59 -83 -82 0+-134 -210 0+-21 70 0+-136 -233 0+-169 -130 0+50 54 -52 0+-101 -197 0+-133 -237 0+-209 123 0+71 -70 50 0
+ samples/qbf/ii8a1-90-shuffled.qdimacs view
@@ -0,0 +1,656 @@+p cnf 328 652+e 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 0+a 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 0+e 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 0+-297 101 0+-219 -75 0+-83 -323 0+115 -302 0+21 -60 0+63 65 64 0+-89 -320 0+129 -218 0+-92 -282 0+-189 -87 0+-61 25 0+-203 -107 0+-184 133 0+-74 -327 0+7 -60 0+128 -224 0+-55 32 0+134 -177 0+22 23 0+-296 112 0+11 -57 0+131 -200 0+-108 -154 0+-58 33 0+133 -183 0+-268 -73 0+39 -62 0+-61 23 0+89 -297 0+-258 124 0+-188 -88 0+-151 137 0+7 -63 0+-57 18 0+-85 -166 0+-296 109 0+31 30 0+136 -158 0+-264 123 0+-113 -224 0+109 -302 0+-251 125 0+-161 -95 0+40 -59 0+127 -235 0+-104 -276 0+-297 93 0+-72 -328 0+-200 -112 0+-103 -229 0+-57 7 0+-282 121 0+-283 121 0+-115 -307 0+-169 135 0+-83 -263 0+74 -304 0+90 -297 0+120 -290 0+-102 -205 0+135 -171 0+-170 135 0+115 -293 0+-97 -160 0+-70 25 0+-187 -90 0+-80 -324 0+-312 -105 0+26 -61 0+135 -172 0+-316 -97 0+-70 26 0+-266 -77 0+43 42 0+93 -300 0+-122 -148 0+9 -63 0+-95 -185 0+126 -237 0+128 -221 0+-317 -95 0+46 -59 0+10 -54 0+-319 -91 0+-295 84 0+-116 -306 0+72 -295 0+-294 94 0+-117 -198 0+-143 -136 0+-119 -245 0+-232 -97 0+3 -140 0+-56 38 0+120 -286 0+31 -61 0+21 20 0+-125 -147 0+-131 -145 0+-275 122 0+-63 20 0+-48 -46 -45 -39 -52 -51 -43 -40 0+-108 -274 0+22 -70 0+-195 132 0+-69 13 0+-167 135 0+15 -69 0+33 32 0+-296 106 0+113 -299 0+-304 73 0+-303 99 0+-67 32 0+-118 -269 0+111 -302 0+-70 29 0+-146 -127 0+8 -57 0+-66 16 0+38 -68 0+-62 53 0+77 -301 0+-196 132 0+-60 18 0+-51 -40 -39 -49 -46 -43 -53 -45 0+-70 37 0+-54 13 0+137 -155 0+-210 130 0+-214 129 0+83 -295 0+136 -161 0+-68 53 0+122 -271 0+-304 77 0+-180 -104 0+-59 53 0+-242 -76 0+-34 -27 -37 -31 -25 -22 -28 -32 0+8 -54 0+-124 -139 0+122 -274 0+38 -71 0+136 -164 0+9 -69 0+-27 -30 -32 -24 -35 -29 -36 -23 0+-246 -116 0+-244 -73 0+-291 120 0+125 -248 0+-278 -100 0+-231 -98 0+28 -64 0+-259 -90 0+121 -284 0+-84 -286 0+-106 -275 0+-254 124 0+-301 84 0+-300 98 0+-294 102 0+46 47 0+-92 -186 0+-166 135 0+-58 34 0+-108 -226 0+-38 -50 -44 -53 -43 -48 -41 -47 0+-103 -157 0+12 13 0+-94 -317 0+-101 -314 0+-311 -106 0+-68 48 0+-82 -239 0+-108 -310 0+-204 -105 0+34 -61 0+-267 123 0+-173 -119 0+-65 52 0+125 -247 0+-82 -191 0+45 -71 0+-256 124 0+131 -197 0+74 -295 0+116 -299 0+-225 -111 0+-105 -228 0+-261 123 0+44 -3 0+-79 -289 0+-120 -148 0+-64 30 0+-89 -260 0+-302 117 0+-300 97 0+-57 21 0+-78 -325 0+45 -68 0+-324 -81 0+-303 96 0+121 -277 0+-149 -119 0+88 -294 0+90 -294 0+-1 12 0+-138 -131 0+129 -220 0+-65 42 0+-98 -315 0+65 -5 0+-225 128 0+-242 126 0+41 -71 0+136 -163 0+-117 -306 0+-185 133 0+-201 131 0+135 -168 0+-178 134 0+-89 -212 0+-300 94 0+-284 -88 0+-79 -265 0+86 -298 0+-56 50 0+81 -301 0+-55 24 0+-68 40 0+129 -219 0+-257 124 0+-255 124 0+-65 48 0+-139 4 0+7 6 0+42 -71 0+-253 -103 0+-102 -277 0+-142 -78 0+-257 -95 0+-296 105 0+-2 35 0+-67 22 0+-119 -305 0+132 -191 0+-297 102 0+-290 -76 0+27 -58 0+-194 -76 0+26 -55 0+-60 9 0+131 -203 0+-96 -208 0+-218 -76 0+-107 -311 0+30 -67 0+-303 93 0+-188 133 0+6 -54 0+-299 110 0+41 -62 0+-114 -199 0+51 -71 0+-59 49 0+100 -294 0+130 -207 0+14 15 0+-26 -22 -34 -36 -28 -33 -24 -30 0+-72 -172 0+119 -299 0+-179 -106 0+-322 -85 0+122 -273 0+-293 104 0+130 -208 0+130 -211 0+125 -245 0+-91 -235 0+136 -162 0+-303 89 0+-250 -109 0+40 -56 0+130 -206 0+50 -68 0+-298 85 0+-296 114 0+-302 112 0+-21 -14 -7 -8 -17 -13 -19 -11 0+-304 79 0+95 -297 0+-65 46 0+-84 -190 0+12 -63 0+-299 104 0+-299 107 0+-103 -181 0+-297 98 0+122 -270 0+131 -198 0+13 -66 0+-56 45 0+127 -231 0+17 16 0+-79 -241 0+-81 -288 0+-278 121 0+-126 -146 0+-316 -96 0+-87 -321 0+18 -66 0+17 -57 0+-96 -184 0+-179 134 0+10 -63 0+-302 106 0+-215 129 0+14 -66 0+-298 77 0+-213 129 0+-293 110 0+-101 -141 0+-63 19 0+-92 -318 0+85 -304 0+-68 46 0+-92 -234 0+128 -222 0+-174 134 0+133 -186 0+-240 -81 0+-183 -98 0+18 -54 0+123 -263 0+-159 136 0+-132 -144 0+-76 -170 0+-82 -323 0+25 24 0+125 -250 0+-70 35 0+134 -180 0+-56 48 0+-309 -110 0+34 -67 0+-157 136 0+71 69 70 0+-92 -162 0+109 -299 0+82 -298 0+121 -280 0+-123 -147 0+-80 -216 0+-223 -114 0+-303 103 0+-304 80 0+-308 -112 0+125 -249 0+-213 -86 0+-90 -319 0+-173 134 0+-267 -74 0+-189 132 0+-87 -237 0+16 -54 0+123 -265 0+-300 88 0+-214 -85 0+112 -293 0+-202 -108 0+-63 14 0+-270 -116 0+-171 -75 0+-192 -80 0+15 -54 0+-326 -76 0+8 -66 0+-67 24 0+-63 16 0+-135 -143 0+100 -300 0+15 -60 0+96 -297 0+-111 -249 0+-209 -94 0+6 -69 0+121 -279 0+-174 -116 0+126 -240 0+29 -58 0+-88 -320 0+57 58 59 0+31 -55 0+-318 -93 0+-108 -178 0+-84 -238 0+-113 -152 0+-72 -292 0+-176 134 0+95 -303 0+-118 -305 0+87 -304 0+137 -150 0+-71 49 0+-204 131 0+-165 135 0+32 -64 0+125 -246 0+-145 -130 0+28 29 0+-254 -100 0+13 -57 0+-201 -110 0+50 51 0+-72 -196 0+132 -193 0+-158 -101 0+10 -66 0+-61 32 0+-303 90 0+-280 -97 0+26 27 0+-241 126 0+-70 33 0+-152 137 0+-89 -236 0+73 -298 0+83 -304 0+-64 36 0+-90 -283 0+-64 23 0+-78 -217 0+-276 122 0+37 -61 0+25 -64 0+44 -65 0+123 -268 0+-70 31 0+-58 23 0+103 -300 0+105 -302 0+-69 17 0+42 -68 0+-111 -153 0+-269 122 0+-58 24 0+131 -202 0+-19 -7 -16 -13 -11 -14 -20 -8 0+-59 39 0+26 -67 0+-12 -11 -18 -15 -6 -21 -9 -16 0+-114 -307 0+-111 -309 0+-176 -112 0+68 66 67 0+18 19 0+-262 123 0+-182 133 0+-65 51 0+129 -216 0+58 -4 0+-55 22 0+78 -295 0+-261 -87 0+-128 -146 0+-96 -256 0+-291 -74 0+-293 116 0+-301 72 0+-175 134 0+53 -71 0+-212 130 0+127 -229 0+-215 -82 0+-248 -112 0+-243 -75 0+11 10 0+108 -293 0+-82 -287 0+-67 29 0+-302 119 0+124 -259 0+-227 -107 0+127 -233 0+130 -209 0+-117 -150 0+-199 131 0+45 44 0+132 -192 0+-272 122 0+-74 -195 0+126 -239 0+-156 137 0+-322 -84 0+42 -56 0+-84 -262 0+127 -236 0+-107 -155 0+-207 -98 0+-105 -252 0+120 -287 0+121 -281 0+-168 -81 0+-292 120 0+-301 82 0+-295 86 0+-91 -211 0+-60 10 0+-100 -314 0+-206 -101 0+-95 -233 0+-313 -102 0+-79 -169 0+8 9 0+43 -59 0+40 41 0+-160 136 0+-106 -251 0+13 -60 0+-129 -145 0+106 -293 0+-296 118 0+-190 132 0+-326 -77 0+-234 127 0+128 -223 0+-104 -156 0+62 61 60 0+-24 -33 -27 -29 -37 -30 -23 -35 0+54 55 56 0+14 -57 0+-312 -104 0+-67 37 0+-66 21 0+-69 10 0+127 -232 0+48 49 0+48 -62 0+-221 -119 0+39 -65 0+-300 91 0+137 -153 0+128 -228 0+-285 120 0+124 -253 0+-86 -285 0+-238 126 0+-83 -167 0+26 -64 0+34 -55 0+-99 -315 0+-93 -258 0+-100 -230 0+216 297 238 299 184 192 327 326 301 212 224 190 151 201 308 160 223 196 205 167 313 322 280 255 172 295 284 152 250 298 165 179 139 234 261 200 260 140 300 156 207 157 236 154 279 240 161 145 143 266 274 270 321 245 173 249 162 229 168 288 304 244 199 232 226 227 277 237 204 283 202 149 243 148 254 217 317 235 171 241 328 183 272 239 206 289 265 181 276 305 294 306 325 214 310 146 318 257 169 233 311 242 153 287 213 215 290 263 293 251 174 163 187 220 79 281 193 208 222 292 150 194 138 309 178 186 247 166 307 267 198 203 159 211 230 177 228 197 248 219 319 285 218 303 258 180 158 170 278 314 268 189 225 155 175 252 262 191 221 188 144 324 323 271 264 286 231 182 315 296 256 195 246 176 291 209 275 302 259 210 141 253 282 142 316 185 147 273 269 312 320 164 0+-147 -124 0+38 39 0+137 -154 0+111 -296 0+36 -55 0+124 -260 0+-289 120 0+133 -181 0+-165 -87 0+-109 -310 0+-80 -264 0+92 -294 0+36 37 0+-65 41 0+75 -301 0+21 -69 0+76 -295 0+-110 -140 0+-294 96 0+-301 87 0+-273 -111 0+53 52 0+-142 1 0+-294 99 0+-313 -103 0+-46 -50 -49 -52 -42 -44 -38 -40 0+-210 -92 0+-301 78 0+-295 80 0+-114 -271 0+-220 -73 0+-222 -116 0+-99 -159 0+-144 -133 0+118 -293 0+-187 133 0+-143 -137 0+-272 -113 0+-60 16 0+-175 -114 0+-288 120 0+45 -62 0+114 -299 0+-59 45 0+-99 -255 0+128 -227 0+-205 130 0+-88 -164 0+128 -226 0+127 -230 0+80 -298 0+-59 50 0+126 -244 0+-55 29 0+101 -303 0+-14 -6 -17 -12 -10 -20 -18 -8 0+-95 -281 0+-118 -197 0+19 -69 0+-296 117 0+2 -141 0+-148 -121 0+-111 -177 0+137 -149 0+-71 47 0+79 -298 0+-328 -73 0+37 -58 0+-98 -279 0+-100 -182 0+5 -138 0+-194 132 0+-247 -115 0+-308 -113 0+6 -66 0+-91 -163 0+42 -62 0+-61 29 0+-58 30 0+-327 -75 0+-325 -79 0+-144 -134 0+-86 -321 0+50 -62 0+-64 35 0+74 -298 0+-217 129 0+-79 -193 0+47 -56 0+125 -252 0+-151 -115 0+-54 20 0+47 -62 0+34 35 0+-56 52 0+-243 126 0+-266 123 0
+ samples/sat/Hidoku_enu_6.cnf view
@@ -0,0 +1,11926 @@+c This formula is generated by enumerate Encoding.+p cnf 2508 11924+1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 0+37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 0+73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 0+109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 0+145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 0+181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 0+217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 0+253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 0+289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 0+325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 0+361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 0+397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 0+433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 0+469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 0+505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 0+541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 0+577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 0+613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 0+649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 0+685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 0+721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 0+757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 0+793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 0+829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 0+865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 0+901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 0+937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 0+973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 0+1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 0+1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 0+1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 0+1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 0+1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 0+1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 0+1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 0+1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 0+-1 -2 0+-1 -3 0+-1 -1619 0+-2 -3 0+-2 -1619 0+-3 -1619 0+-4 -5 0+-4 -1618 0+-4 1619 0+-5 -1618 0+-5 1619 0+-1618 1619 0+-6 -7 0+-6 -8 0+-6 -1620 0+-7 -8 0+-7 -1620 0+-8 -1620 0+-9 -1617 0+-9 1618 0+-9 1620 0+-1617 1618 0+-1617 1620 0+1618 1620 0+-10 -11 0+-10 -12 0+-10 -1622 0+-11 -12 0+-11 -1622 0+-12 -1622 0+-13 -14 0+-13 -1621 0+-13 1622 0+-14 -1621 0+-14 1622 0+-1621 1622 0+-15 -16 0+-15 -17 0+-15 -1623 0+-16 -17 0+-16 -1623 0+-17 -1623 0+-18 -1616 0+-18 -1624 0+-1616 -1624 0+1617 1621 0+1617 1623 0+1617 1624 0+1621 1623 0+1621 1624 0+1623 1624 0+-19 -20 0+-19 -21 0+-19 -1627 0+-20 -21 0+-20 -1627 0+-21 -1627 0+-22 -23 0+-22 -1626 0+-22 1627 0+-23 -1626 0+-23 1627 0+-1626 1627 0+-24 -25 0+-24 -26 0+-24 -1628 0+-25 -26 0+-25 -1628 0+-26 -1628 0+-27 -1625 0+-27 1626 0+-27 1628 0+-1625 1626 0+-1625 1628 0+1626 1628 0+-28 -29 0+-28 -30 0+-28 -1630 0+-29 -30 0+-29 -1630 0+-30 -1630 0+-31 -32 0+-31 -1629 0+-31 1630 0+-32 -1629 0+-32 1630 0+-1629 1630 0+-33 -34 0+-33 -35 0+-33 -1631 0+-34 -35 0+-34 -1631 0+-35 -1631 0+-36 1616 0+-36 -1632 0+1616 -1632 0+1625 1629 0+1625 1631 0+1625 1632 0+1629 1631 0+1629 1632 0+1631 1632 0+-37 -38 0+-37 -39 0+-37 -1636 0+-38 -39 0+-38 -1636 0+-39 -1636 0+-40 -41 0+-40 -1635 0+-40 1636 0+-41 -1635 0+-41 1636 0+-1635 1636 0+-42 -43 0+-42 -44 0+-42 -1637 0+-43 -44 0+-43 -1637 0+-44 -1637 0+-45 -1634 0+-45 1635 0+-45 1637 0+-1634 1635 0+-1634 1637 0+1635 1637 0+-46 -47 0+-46 -48 0+-46 -1639 0+-47 -48 0+-47 -1639 0+-48 -1639 0+-49 -50 0+-49 -1638 0+-49 1639 0+-50 -1638 0+-50 1639 0+-1638 1639 0+-51 -52 0+-51 -53 0+-51 -1640 0+-52 -53 0+-52 -1640 0+-53 -1640 0+-54 -1633 0+-54 -1641 0+-1633 -1641 0+1634 1638 0+1634 1640 0+1634 1641 0+1638 1640 0+1638 1641 0+1640 1641 0+-55 -56 0+-55 -57 0+-55 -1644 0+-56 -57 0+-56 -1644 0+-57 -1644 0+-58 -59 0+-58 -1643 0+-58 1644 0+-59 -1643 0+-59 1644 0+-1643 1644 0+-60 -61 0+-60 -62 0+-60 -1645 0+-61 -62 0+-61 -1645 0+-62 -1645 0+-63 -1642 0+-63 1643 0+-63 1645 0+-1642 1643 0+-1642 1645 0+1643 1645 0+-64 -65 0+-64 -66 0+-64 -1647 0+-65 -66 0+-65 -1647 0+-66 -1647 0+-67 -68 0+-67 -1646 0+-67 1647 0+-68 -1646 0+-68 1647 0+-1646 1647 0+-69 -70 0+-69 -71 0+-69 -1648 0+-70 -71 0+-70 -1648 0+-71 -1648 0+-72 1633 0+-72 -1649 0+1633 -1649 0+1642 1646 0+1642 1648 0+1642 1649 0+1646 1648 0+1646 1649 0+1648 1649 0+-73 -74 0+-73 -75 0+-73 -1653 0+-74 -75 0+-74 -1653 0+-75 -1653 0+-76 -77 0+-76 -1652 0+-76 1653 0+-77 -1652 0+-77 1653 0+-1652 1653 0+-78 -79 0+-78 -80 0+-78 -1654 0+-79 -80 0+-79 -1654 0+-80 -1654 0+-81 -1651 0+-81 1652 0+-81 1654 0+-1651 1652 0+-1651 1654 0+1652 1654 0+-82 -83 0+-82 -84 0+-82 -1656 0+-83 -84 0+-83 -1656 0+-84 -1656 0+-85 -86 0+-85 -1655 0+-85 1656 0+-86 -1655 0+-86 1656 0+-1655 1656 0+-87 -88 0+-87 -89 0+-87 -1657 0+-88 -89 0+-88 -1657 0+-89 -1657 0+-90 -1650 0+-90 -1658 0+-1650 -1658 0+1651 1655 0+1651 1657 0+1651 1658 0+1655 1657 0+1655 1658 0+1657 1658 0+-91 -92 0+-91 -93 0+-91 -1661 0+-92 -93 0+-92 -1661 0+-93 -1661 0+-94 -95 0+-94 -1660 0+-94 1661 0+-95 -1660 0+-95 1661 0+-1660 1661 0+-96 -97 0+-96 -98 0+-96 -1662 0+-97 -98 0+-97 -1662 0+-98 -1662 0+-99 -1659 0+-99 1660 0+-99 1662 0+-1659 1660 0+-1659 1662 0+1660 1662 0+-100 -101 0+-100 -102 0+-100 -1664 0+-101 -102 0+-101 -1664 0+-102 -1664 0+-103 -104 0+-103 -1663 0+-103 1664 0+-104 -1663 0+-104 1664 0+-1663 1664 0+-105 -106 0+-105 -107 0+-105 -1665 0+-106 -107 0+-106 -1665 0+-107 -1665 0+-108 1650 0+-108 -1666 0+1650 -1666 0+1659 1663 0+1659 1665 0+1659 1666 0+1663 1665 0+1663 1666 0+1665 1666 0+-109 -110 0+-109 -111 0+-109 -1670 0+-110 -111 0+-110 -1670 0+-111 -1670 0+-112 -113 0+-112 -1669 0+-112 1670 0+-113 -1669 0+-113 1670 0+-1669 1670 0+-114 -115 0+-114 -116 0+-114 -1671 0+-115 -116 0+-115 -1671 0+-116 -1671 0+-117 -1668 0+-117 1669 0+-117 1671 0+-1668 1669 0+-1668 1671 0+1669 1671 0+-118 -119 0+-118 -120 0+-118 -1673 0+-119 -120 0+-119 -1673 0+-120 -1673 0+-121 -122 0+-121 -1672 0+-121 1673 0+-122 -1672 0+-122 1673 0+-1672 1673 0+-123 -124 0+-123 -125 0+-123 -1674 0+-124 -125 0+-124 -1674 0+-125 -1674 0+-126 -1667 0+-126 -1675 0+-1667 -1675 0+1668 1672 0+1668 1674 0+1668 1675 0+1672 1674 0+1672 1675 0+1674 1675 0+-127 -128 0+-127 -129 0+-127 -1678 0+-128 -129 0+-128 -1678 0+-129 -1678 0+-130 -131 0+-130 -1677 0+-130 1678 0+-131 -1677 0+-131 1678 0+-1677 1678 0+-132 -133 0+-132 -134 0+-132 -1679 0+-133 -134 0+-133 -1679 0+-134 -1679 0+-135 -1676 0+-135 1677 0+-135 1679 0+-1676 1677 0+-1676 1679 0+1677 1679 0+-136 -137 0+-136 -138 0+-136 -1681 0+-137 -138 0+-137 -1681 0+-138 -1681 0+-139 -140 0+-139 -1680 0+-139 1681 0+-140 -1680 0+-140 1681 0+-1680 1681 0+-141 -142 0+-141 -143 0+-141 -1682 0+-142 -143 0+-142 -1682 0+-143 -1682 0+-144 1667 0+-144 -1683 0+1667 -1683 0+1676 1680 0+1676 1682 0+1676 1683 0+1680 1682 0+1680 1683 0+1682 1683 0+-145 -146 0+-145 -147 0+-145 -1687 0+-146 -147 0+-146 -1687 0+-147 -1687 0+-148 -149 0+-148 -1686 0+-148 1687 0+-149 -1686 0+-149 1687 0+-1686 1687 0+-150 -151 0+-150 -152 0+-150 -1688 0+-151 -152 0+-151 -1688 0+-152 -1688 0+-153 -1685 0+-153 1686 0+-153 1688 0+-1685 1686 0+-1685 1688 0+1686 1688 0+-154 -155 0+-154 -156 0+-154 -1690 0+-155 -156 0+-155 -1690 0+-156 -1690 0+-157 -158 0+-157 -1689 0+-157 1690 0+-158 -1689 0+-158 1690 0+-1689 1690 0+-159 -160 0+-159 -161 0+-159 -1691 0+-160 -161 0+-160 -1691 0+-161 -1691 0+-162 -1684 0+-162 -1692 0+-1684 -1692 0+1685 1689 0+1685 1691 0+1685 1692 0+1689 1691 0+1689 1692 0+1691 1692 0+-163 -164 0+-163 -165 0+-163 -1695 0+-164 -165 0+-164 -1695 0+-165 -1695 0+-166 -167 0+-166 -1694 0+-166 1695 0+-167 -1694 0+-167 1695 0+-1694 1695 0+-168 -169 0+-168 -170 0+-168 -1696 0+-169 -170 0+-169 -1696 0+-170 -1696 0+-171 -1693 0+-171 1694 0+-171 1696 0+-1693 1694 0+-1693 1696 0+1694 1696 0+-172 -173 0+-172 -174 0+-172 -1698 0+-173 -174 0+-173 -1698 0+-174 -1698 0+-175 -176 0+-175 -1697 0+-175 1698 0+-176 -1697 0+-176 1698 0+-1697 1698 0+-177 -178 0+-177 -179 0+-177 -1699 0+-178 -179 0+-178 -1699 0+-179 -1699 0+-180 1684 0+-180 -1700 0+1684 -1700 0+1693 1697 0+1693 1699 0+1693 1700 0+1697 1699 0+1697 1700 0+1699 1700 0+-181 -182 0+-181 -183 0+-181 -1704 0+-182 -183 0+-182 -1704 0+-183 -1704 0+-184 -185 0+-184 -1703 0+-184 1704 0+-185 -1703 0+-185 1704 0+-1703 1704 0+-186 -187 0+-186 -188 0+-186 -1705 0+-187 -188 0+-187 -1705 0+-188 -1705 0+-189 -1702 0+-189 1703 0+-189 1705 0+-1702 1703 0+-1702 1705 0+1703 1705 0+-190 -191 0+-190 -192 0+-190 -1707 0+-191 -192 0+-191 -1707 0+-192 -1707 0+-193 -194 0+-193 -1706 0+-193 1707 0+-194 -1706 0+-194 1707 0+-1706 1707 0+-195 -196 0+-195 -197 0+-195 -1708 0+-196 -197 0+-196 -1708 0+-197 -1708 0+-198 -1701 0+-198 -1709 0+-1701 -1709 0+1702 1706 0+1702 1708 0+1702 1709 0+1706 1708 0+1706 1709 0+1708 1709 0+-199 -200 0+-199 -201 0+-199 -1712 0+-200 -201 0+-200 -1712 0+-201 -1712 0+-202 -203 0+-202 -1711 0+-202 1712 0+-203 -1711 0+-203 1712 0+-1711 1712 0+-204 -205 0+-204 -206 0+-204 -1713 0+-205 -206 0+-205 -1713 0+-206 -1713 0+-207 -1710 0+-207 1711 0+-207 1713 0+-1710 1711 0+-1710 1713 0+1711 1713 0+-208 -209 0+-208 -210 0+-208 -1715 0+-209 -210 0+-209 -1715 0+-210 -1715 0+-211 -212 0+-211 -1714 0+-211 1715 0+-212 -1714 0+-212 1715 0+-1714 1715 0+-213 -214 0+-213 -215 0+-213 -1716 0+-214 -215 0+-214 -1716 0+-215 -1716 0+-216 1701 0+-216 -1717 0+1701 -1717 0+1710 1714 0+1710 1716 0+1710 1717 0+1714 1716 0+1714 1717 0+1716 1717 0+-217 -218 0+-217 -219 0+-217 -1721 0+-218 -219 0+-218 -1721 0+-219 -1721 0+-220 -221 0+-220 -1720 0+-220 1721 0+-221 -1720 0+-221 1721 0+-1720 1721 0+-222 -223 0+-222 -224 0+-222 -1722 0+-223 -224 0+-223 -1722 0+-224 -1722 0+-225 -1719 0+-225 1720 0+-225 1722 0+-1719 1720 0+-1719 1722 0+1720 1722 0+-226 -227 0+-226 -228 0+-226 -1724 0+-227 -228 0+-227 -1724 0+-228 -1724 0+-229 -230 0+-229 -1723 0+-229 1724 0+-230 -1723 0+-230 1724 0+-1723 1724 0+-231 -232 0+-231 -233 0+-231 -1725 0+-232 -233 0+-232 -1725 0+-233 -1725 0+-234 -1718 0+-234 -1726 0+-1718 -1726 0+1719 1723 0+1719 1725 0+1719 1726 0+1723 1725 0+1723 1726 0+1725 1726 0+-235 -236 0+-235 -237 0+-235 -1729 0+-236 -237 0+-236 -1729 0+-237 -1729 0+-238 -239 0+-238 -1728 0+-238 1729 0+-239 -1728 0+-239 1729 0+-1728 1729 0+-240 -241 0+-240 -242 0+-240 -1730 0+-241 -242 0+-241 -1730 0+-242 -1730 0+-243 -1727 0+-243 1728 0+-243 1730 0+-1727 1728 0+-1727 1730 0+1728 1730 0+-244 -245 0+-244 -246 0+-244 -1732 0+-245 -246 0+-245 -1732 0+-246 -1732 0+-247 -248 0+-247 -1731 0+-247 1732 0+-248 -1731 0+-248 1732 0+-1731 1732 0+-249 -250 0+-249 -251 0+-249 -1733 0+-250 -251 0+-250 -1733 0+-251 -1733 0+-252 1718 0+-252 -1734 0+1718 -1734 0+1727 1731 0+1727 1733 0+1727 1734 0+1731 1733 0+1731 1734 0+1733 1734 0+-253 -254 0+-253 -255 0+-253 -1738 0+-254 -255 0+-254 -1738 0+-255 -1738 0+-256 -257 0+-256 -1737 0+-256 1738 0+-257 -1737 0+-257 1738 0+-1737 1738 0+-258 -259 0+-258 -260 0+-258 -1739 0+-259 -260 0+-259 -1739 0+-260 -1739 0+-261 -1736 0+-261 1737 0+-261 1739 0+-1736 1737 0+-1736 1739 0+1737 1739 0+-262 -263 0+-262 -264 0+-262 -1741 0+-263 -264 0+-263 -1741 0+-264 -1741 0+-265 -266 0+-265 -1740 0+-265 1741 0+-266 -1740 0+-266 1741 0+-1740 1741 0+-267 -268 0+-267 -269 0+-267 -1742 0+-268 -269 0+-268 -1742 0+-269 -1742 0+-270 -1735 0+-270 -1743 0+-1735 -1743 0+1736 1740 0+1736 1742 0+1736 1743 0+1740 1742 0+1740 1743 0+1742 1743 0+-271 -272 0+-271 -273 0+-271 -1746 0+-272 -273 0+-272 -1746 0+-273 -1746 0+-274 -275 0+-274 -1745 0+-274 1746 0+-275 -1745 0+-275 1746 0+-1745 1746 0+-276 -277 0+-276 -278 0+-276 -1747 0+-277 -278 0+-277 -1747 0+-278 -1747 0+-279 -1744 0+-279 1745 0+-279 1747 0+-1744 1745 0+-1744 1747 0+1745 1747 0+-280 -281 0+-280 -282 0+-280 -1749 0+-281 -282 0+-281 -1749 0+-282 -1749 0+-283 -284 0+-283 -1748 0+-283 1749 0+-284 -1748 0+-284 1749 0+-1748 1749 0+-285 -286 0+-285 -287 0+-285 -1750 0+-286 -287 0+-286 -1750 0+-287 -1750 0+-288 1735 0+-288 -1751 0+1735 -1751 0+1744 1748 0+1744 1750 0+1744 1751 0+1748 1750 0+1748 1751 0+1750 1751 0+-289 -290 0+-289 -291 0+-289 -1755 0+-290 -291 0+-290 -1755 0+-291 -1755 0+-292 -293 0+-292 -1754 0+-292 1755 0+-293 -1754 0+-293 1755 0+-1754 1755 0+-294 -295 0+-294 -296 0+-294 -1756 0+-295 -296 0+-295 -1756 0+-296 -1756 0+-297 -1753 0+-297 1754 0+-297 1756 0+-1753 1754 0+-1753 1756 0+1754 1756 0+-298 -299 0+-298 -300 0+-298 -1758 0+-299 -300 0+-299 -1758 0+-300 -1758 0+-301 -302 0+-301 -1757 0+-301 1758 0+-302 -1757 0+-302 1758 0+-1757 1758 0+-303 -304 0+-303 -305 0+-303 -1759 0+-304 -305 0+-304 -1759 0+-305 -1759 0+-306 -1752 0+-306 -1760 0+-1752 -1760 0+1753 1757 0+1753 1759 0+1753 1760 0+1757 1759 0+1757 1760 0+1759 1760 0+-307 -308 0+-307 -309 0+-307 -1763 0+-308 -309 0+-308 -1763 0+-309 -1763 0+-310 -311 0+-310 -1762 0+-310 1763 0+-311 -1762 0+-311 1763 0+-1762 1763 0+-312 -313 0+-312 -314 0+-312 -1764 0+-313 -314 0+-313 -1764 0+-314 -1764 0+-315 -1761 0+-315 1762 0+-315 1764 0+-1761 1762 0+-1761 1764 0+1762 1764 0+-316 -317 0+-316 -318 0+-316 -1766 0+-317 -318 0+-317 -1766 0+-318 -1766 0+-319 -320 0+-319 -1765 0+-319 1766 0+-320 -1765 0+-320 1766 0+-1765 1766 0+-321 -322 0+-321 -323 0+-321 -1767 0+-322 -323 0+-322 -1767 0+-323 -1767 0+-324 1752 0+-324 -1768 0+1752 -1768 0+1761 1765 0+1761 1767 0+1761 1768 0+1765 1767 0+1765 1768 0+1767 1768 0+-325 -326 0+-325 -327 0+-325 -1772 0+-326 -327 0+-326 -1772 0+-327 -1772 0+-328 -329 0+-328 -1771 0+-328 1772 0+-329 -1771 0+-329 1772 0+-1771 1772 0+-330 -331 0+-330 -332 0+-330 -1773 0+-331 -332 0+-331 -1773 0+-332 -1773 0+-333 -1770 0+-333 1771 0+-333 1773 0+-1770 1771 0+-1770 1773 0+1771 1773 0+-334 -335 0+-334 -336 0+-334 -1775 0+-335 -336 0+-335 -1775 0+-336 -1775 0+-337 -338 0+-337 -1774 0+-337 1775 0+-338 -1774 0+-338 1775 0+-1774 1775 0+-339 -340 0+-339 -341 0+-339 -1776 0+-340 -341 0+-340 -1776 0+-341 -1776 0+-342 -1769 0+-342 -1777 0+-1769 -1777 0+1770 1774 0+1770 1776 0+1770 1777 0+1774 1776 0+1774 1777 0+1776 1777 0+-343 -344 0+-343 -345 0+-343 -1780 0+-344 -345 0+-344 -1780 0+-345 -1780 0+-346 -347 0+-346 -1779 0+-346 1780 0+-347 -1779 0+-347 1780 0+-1779 1780 0+-348 -349 0+-348 -350 0+-348 -1781 0+-349 -350 0+-349 -1781 0+-350 -1781 0+-351 -1778 0+-351 1779 0+-351 1781 0+-1778 1779 0+-1778 1781 0+1779 1781 0+-352 -353 0+-352 -354 0+-352 -1783 0+-353 -354 0+-353 -1783 0+-354 -1783 0+-355 -356 0+-355 -1782 0+-355 1783 0+-356 -1782 0+-356 1783 0+-1782 1783 0+-357 -358 0+-357 -359 0+-357 -1784 0+-358 -359 0+-358 -1784 0+-359 -1784 0+-360 1769 0+-360 -1785 0+1769 -1785 0+1778 1782 0+1778 1784 0+1778 1785 0+1782 1784 0+1782 1785 0+1784 1785 0+-361 -362 0+-361 -363 0+-361 -1789 0+-362 -363 0+-362 -1789 0+-363 -1789 0+-364 -365 0+-364 -1788 0+-364 1789 0+-365 -1788 0+-365 1789 0+-1788 1789 0+-366 -367 0+-366 -368 0+-366 -1790 0+-367 -368 0+-367 -1790 0+-368 -1790 0+-369 -1787 0+-369 1788 0+-369 1790 0+-1787 1788 0+-1787 1790 0+1788 1790 0+-370 -371 0+-370 -372 0+-370 -1792 0+-371 -372 0+-371 -1792 0+-372 -1792 0+-373 -374 0+-373 -1791 0+-373 1792 0+-374 -1791 0+-374 1792 0+-1791 1792 0+-375 -376 0+-375 -377 0+-375 -1793 0+-376 -377 0+-376 -1793 0+-377 -1793 0+-378 -1786 0+-378 -1794 0+-1786 -1794 0+1787 1791 0+1787 1793 0+1787 1794 0+1791 1793 0+1791 1794 0+1793 1794 0+-379 -380 0+-379 -381 0+-379 -1797 0+-380 -381 0+-380 -1797 0+-381 -1797 0+-382 -383 0+-382 -1796 0+-382 1797 0+-383 -1796 0+-383 1797 0+-1796 1797 0+-384 -385 0+-384 -386 0+-384 -1798 0+-385 -386 0+-385 -1798 0+-386 -1798 0+-387 -1795 0+-387 1796 0+-387 1798 0+-1795 1796 0+-1795 1798 0+1796 1798 0+-388 -389 0+-388 -390 0+-388 -1800 0+-389 -390 0+-389 -1800 0+-390 -1800 0+-391 -392 0+-391 -1799 0+-391 1800 0+-392 -1799 0+-392 1800 0+-1799 1800 0+-393 -394 0+-393 -395 0+-393 -1801 0+-394 -395 0+-394 -1801 0+-395 -1801 0+-396 1786 0+-396 -1802 0+1786 -1802 0+1795 1799 0+1795 1801 0+1795 1802 0+1799 1801 0+1799 1802 0+1801 1802 0+-397 -398 0+-397 -399 0+-397 -1806 0+-398 -399 0+-398 -1806 0+-399 -1806 0+-400 -401 0+-400 -1805 0+-400 1806 0+-401 -1805 0+-401 1806 0+-1805 1806 0+-402 -403 0+-402 -404 0+-402 -1807 0+-403 -404 0+-403 -1807 0+-404 -1807 0+-405 -1804 0+-405 1805 0+-405 1807 0+-1804 1805 0+-1804 1807 0+1805 1807 0+-406 -407 0+-406 -408 0+-406 -1809 0+-407 -408 0+-407 -1809 0+-408 -1809 0+-409 -410 0+-409 -1808 0+-409 1809 0+-410 -1808 0+-410 1809 0+-1808 1809 0+-411 -412 0+-411 -413 0+-411 -1810 0+-412 -413 0+-412 -1810 0+-413 -1810 0+-414 -1803 0+-414 -1811 0+-1803 -1811 0+1804 1808 0+1804 1810 0+1804 1811 0+1808 1810 0+1808 1811 0+1810 1811 0+-415 -416 0+-415 -417 0+-415 -1814 0+-416 -417 0+-416 -1814 0+-417 -1814 0+-418 -419 0+-418 -1813 0+-418 1814 0+-419 -1813 0+-419 1814 0+-1813 1814 0+-420 -421 0+-420 -422 0+-420 -1815 0+-421 -422 0+-421 -1815 0+-422 -1815 0+-423 -1812 0+-423 1813 0+-423 1815 0+-1812 1813 0+-1812 1815 0+1813 1815 0+-424 -425 0+-424 -426 0+-424 -1817 0+-425 -426 0+-425 -1817 0+-426 -1817 0+-427 -428 0+-427 -1816 0+-427 1817 0+-428 -1816 0+-428 1817 0+-1816 1817 0+-429 -430 0+-429 -431 0+-429 -1818 0+-430 -431 0+-430 -1818 0+-431 -1818 0+-432 1803 0+-432 -1819 0+1803 -1819 0+1812 1816 0+1812 1818 0+1812 1819 0+1816 1818 0+1816 1819 0+1818 1819 0+-433 -434 0+-433 -435 0+-433 -1823 0+-434 -435 0+-434 -1823 0+-435 -1823 0+-436 -437 0+-436 -1822 0+-436 1823 0+-437 -1822 0+-437 1823 0+-1822 1823 0+-438 -439 0+-438 -440 0+-438 -1824 0+-439 -440 0+-439 -1824 0+-440 -1824 0+-441 -1821 0+-441 1822 0+-441 1824 0+-1821 1822 0+-1821 1824 0+1822 1824 0+-442 -443 0+-442 -444 0+-442 -1826 0+-443 -444 0+-443 -1826 0+-444 -1826 0+-445 -446 0+-445 -1825 0+-445 1826 0+-446 -1825 0+-446 1826 0+-1825 1826 0+-447 -448 0+-447 -449 0+-447 -1827 0+-448 -449 0+-448 -1827 0+-449 -1827 0+-450 -1820 0+-450 -1828 0+-1820 -1828 0+1821 1825 0+1821 1827 0+1821 1828 0+1825 1827 0+1825 1828 0+1827 1828 0+-451 -452 0+-451 -453 0+-451 -1831 0+-452 -453 0+-452 -1831 0+-453 -1831 0+-454 -455 0+-454 -1830 0+-454 1831 0+-455 -1830 0+-455 1831 0+-1830 1831 0+-456 -457 0+-456 -458 0+-456 -1832 0+-457 -458 0+-457 -1832 0+-458 -1832 0+-459 -1829 0+-459 1830 0+-459 1832 0+-1829 1830 0+-1829 1832 0+1830 1832 0+-460 -461 0+-460 -462 0+-460 -1834 0+-461 -462 0+-461 -1834 0+-462 -1834 0+-463 -464 0+-463 -1833 0+-463 1834 0+-464 -1833 0+-464 1834 0+-1833 1834 0+-465 -466 0+-465 -467 0+-465 -1835 0+-466 -467 0+-466 -1835 0+-467 -1835 0+-468 1820 0+-468 -1836 0+1820 -1836 0+1829 1833 0+1829 1835 0+1829 1836 0+1833 1835 0+1833 1836 0+1835 1836 0+-469 -470 0+-469 -471 0+-469 -1840 0+-470 -471 0+-470 -1840 0+-471 -1840 0+-472 -473 0+-472 -1839 0+-472 1840 0+-473 -1839 0+-473 1840 0+-1839 1840 0+-474 -475 0+-474 -476 0+-474 -1841 0+-475 -476 0+-475 -1841 0+-476 -1841 0+-477 -1838 0+-477 1839 0+-477 1841 0+-1838 1839 0+-1838 1841 0+1839 1841 0+-478 -479 0+-478 -480 0+-478 -1843 0+-479 -480 0+-479 -1843 0+-480 -1843 0+-481 -482 0+-481 -1842 0+-481 1843 0+-482 -1842 0+-482 1843 0+-1842 1843 0+-483 -484 0+-483 -485 0+-483 -1844 0+-484 -485 0+-484 -1844 0+-485 -1844 0+-486 -1837 0+-486 -1845 0+-1837 -1845 0+1838 1842 0+1838 1844 0+1838 1845 0+1842 1844 0+1842 1845 0+1844 1845 0+-487 -488 0+-487 -489 0+-487 -1848 0+-488 -489 0+-488 -1848 0+-489 -1848 0+-490 -491 0+-490 -1847 0+-490 1848 0+-491 -1847 0+-491 1848 0+-1847 1848 0+-492 -493 0+-492 -494 0+-492 -1849 0+-493 -494 0+-493 -1849 0+-494 -1849 0+-495 -1846 0+-495 1847 0+-495 1849 0+-1846 1847 0+-1846 1849 0+1847 1849 0+-496 -497 0+-496 -498 0+-496 -1851 0+-497 -498 0+-497 -1851 0+-498 -1851 0+-499 -500 0+-499 -1850 0+-499 1851 0+-500 -1850 0+-500 1851 0+-1850 1851 0+-501 -502 0+-501 -503 0+-501 -1852 0+-502 -503 0+-502 -1852 0+-503 -1852 0+-504 1837 0+-504 -1853 0+1837 -1853 0+1846 1850 0+1846 1852 0+1846 1853 0+1850 1852 0+1850 1853 0+1852 1853 0+-505 -506 0+-505 -507 0+-505 -1857 0+-506 -507 0+-506 -1857 0+-507 -1857 0+-508 -509 0+-508 -1856 0+-508 1857 0+-509 -1856 0+-509 1857 0+-1856 1857 0+-510 -511 0+-510 -512 0+-510 -1858 0+-511 -512 0+-511 -1858 0+-512 -1858 0+-513 -1855 0+-513 1856 0+-513 1858 0+-1855 1856 0+-1855 1858 0+1856 1858 0+-514 -515 0+-514 -516 0+-514 -1860 0+-515 -516 0+-515 -1860 0+-516 -1860 0+-517 -518 0+-517 -1859 0+-517 1860 0+-518 -1859 0+-518 1860 0+-1859 1860 0+-519 -520 0+-519 -521 0+-519 -1861 0+-520 -521 0+-520 -1861 0+-521 -1861 0+-522 -1854 0+-522 -1862 0+-1854 -1862 0+1855 1859 0+1855 1861 0+1855 1862 0+1859 1861 0+1859 1862 0+1861 1862 0+-523 -524 0+-523 -525 0+-523 -1865 0+-524 -525 0+-524 -1865 0+-525 -1865 0+-526 -527 0+-526 -1864 0+-526 1865 0+-527 -1864 0+-527 1865 0+-1864 1865 0+-528 -529 0+-528 -530 0+-528 -1866 0+-529 -530 0+-529 -1866 0+-530 -1866 0+-531 -1863 0+-531 1864 0+-531 1866 0+-1863 1864 0+-1863 1866 0+1864 1866 0+-532 -533 0+-532 -534 0+-532 -1868 0+-533 -534 0+-533 -1868 0+-534 -1868 0+-535 -536 0+-535 -1867 0+-535 1868 0+-536 -1867 0+-536 1868 0+-1867 1868 0+-537 -538 0+-537 -539 0+-537 -1869 0+-538 -539 0+-538 -1869 0+-539 -1869 0+-540 1854 0+-540 -1870 0+1854 -1870 0+1863 1867 0+1863 1869 0+1863 1870 0+1867 1869 0+1867 1870 0+1869 1870 0+-541 -542 0+-541 -543 0+-541 -1874 0+-542 -543 0+-542 -1874 0+-543 -1874 0+-544 -545 0+-544 -1873 0+-544 1874 0+-545 -1873 0+-545 1874 0+-1873 1874 0+-546 -547 0+-546 -548 0+-546 -1875 0+-547 -548 0+-547 -1875 0+-548 -1875 0+-549 -1872 0+-549 1873 0+-549 1875 0+-1872 1873 0+-1872 1875 0+1873 1875 0+-550 -551 0+-550 -552 0+-550 -1877 0+-551 -552 0+-551 -1877 0+-552 -1877 0+-553 -554 0+-553 -1876 0+-553 1877 0+-554 -1876 0+-554 1877 0+-1876 1877 0+-555 -556 0+-555 -557 0+-555 -1878 0+-556 -557 0+-556 -1878 0+-557 -1878 0+-558 -1871 0+-558 -1879 0+-1871 -1879 0+1872 1876 0+1872 1878 0+1872 1879 0+1876 1878 0+1876 1879 0+1878 1879 0+-559 -560 0+-559 -561 0+-559 -1882 0+-560 -561 0+-560 -1882 0+-561 -1882 0+-562 -563 0+-562 -1881 0+-562 1882 0+-563 -1881 0+-563 1882 0+-1881 1882 0+-564 -565 0+-564 -566 0+-564 -1883 0+-565 -566 0+-565 -1883 0+-566 -1883 0+-567 -1880 0+-567 1881 0+-567 1883 0+-1880 1881 0+-1880 1883 0+1881 1883 0+-568 -569 0+-568 -570 0+-568 -1885 0+-569 -570 0+-569 -1885 0+-570 -1885 0+-571 -572 0+-571 -1884 0+-571 1885 0+-572 -1884 0+-572 1885 0+-1884 1885 0+-573 -574 0+-573 -575 0+-573 -1886 0+-574 -575 0+-574 -1886 0+-575 -1886 0+-576 1871 0+-576 -1887 0+1871 -1887 0+1880 1884 0+1880 1886 0+1880 1887 0+1884 1886 0+1884 1887 0+1886 1887 0+-577 -578 0+-577 -579 0+-577 -1891 0+-578 -579 0+-578 -1891 0+-579 -1891 0+-580 -581 0+-580 -1890 0+-580 1891 0+-581 -1890 0+-581 1891 0+-1890 1891 0+-582 -583 0+-582 -584 0+-582 -1892 0+-583 -584 0+-583 -1892 0+-584 -1892 0+-585 -1889 0+-585 1890 0+-585 1892 0+-1889 1890 0+-1889 1892 0+1890 1892 0+-586 -587 0+-586 -588 0+-586 -1894 0+-587 -588 0+-587 -1894 0+-588 -1894 0+-589 -590 0+-589 -1893 0+-589 1894 0+-590 -1893 0+-590 1894 0+-1893 1894 0+-591 -592 0+-591 -593 0+-591 -1895 0+-592 -593 0+-592 -1895 0+-593 -1895 0+-594 -1888 0+-594 -1896 0+-1888 -1896 0+1889 1893 0+1889 1895 0+1889 1896 0+1893 1895 0+1893 1896 0+1895 1896 0+-595 -596 0+-595 -597 0+-595 -1899 0+-596 -597 0+-596 -1899 0+-597 -1899 0+-598 -599 0+-598 -1898 0+-598 1899 0+-599 -1898 0+-599 1899 0+-1898 1899 0+-600 -601 0+-600 -602 0+-600 -1900 0+-601 -602 0+-601 -1900 0+-602 -1900 0+-603 -1897 0+-603 1898 0+-603 1900 0+-1897 1898 0+-1897 1900 0+1898 1900 0+-604 -605 0+-604 -606 0+-604 -1902 0+-605 -606 0+-605 -1902 0+-606 -1902 0+-607 -608 0+-607 -1901 0+-607 1902 0+-608 -1901 0+-608 1902 0+-1901 1902 0+-609 -610 0+-609 -611 0+-609 -1903 0+-610 -611 0+-610 -1903 0+-611 -1903 0+-612 1888 0+-612 -1904 0+1888 -1904 0+1897 1901 0+1897 1903 0+1897 1904 0+1901 1903 0+1901 1904 0+1903 1904 0+-613 -614 0+-613 -615 0+-613 -1908 0+-614 -615 0+-614 -1908 0+-615 -1908 0+-616 -617 0+-616 -1907 0+-616 1908 0+-617 -1907 0+-617 1908 0+-1907 1908 0+-618 -619 0+-618 -620 0+-618 -1909 0+-619 -620 0+-619 -1909 0+-620 -1909 0+-621 -1906 0+-621 1907 0+-621 1909 0+-1906 1907 0+-1906 1909 0+1907 1909 0+-622 -623 0+-622 -624 0+-622 -1911 0+-623 -624 0+-623 -1911 0+-624 -1911 0+-625 -626 0+-625 -1910 0+-625 1911 0+-626 -1910 0+-626 1911 0+-1910 1911 0+-627 -628 0+-627 -629 0+-627 -1912 0+-628 -629 0+-628 -1912 0+-629 -1912 0+-630 -1905 0+-630 -1913 0+-1905 -1913 0+1906 1910 0+1906 1912 0+1906 1913 0+1910 1912 0+1910 1913 0+1912 1913 0+-631 -632 0+-631 -633 0+-631 -1916 0+-632 -633 0+-632 -1916 0+-633 -1916 0+-634 -635 0+-634 -1915 0+-634 1916 0+-635 -1915 0+-635 1916 0+-1915 1916 0+-636 -637 0+-636 -638 0+-636 -1917 0+-637 -638 0+-637 -1917 0+-638 -1917 0+-639 -1914 0+-639 1915 0+-639 1917 0+-1914 1915 0+-1914 1917 0+1915 1917 0+-640 -641 0+-640 -642 0+-640 -1919 0+-641 -642 0+-641 -1919 0+-642 -1919 0+-643 -644 0+-643 -1918 0+-643 1919 0+-644 -1918 0+-644 1919 0+-1918 1919 0+-645 -646 0+-645 -647 0+-645 -1920 0+-646 -647 0+-646 -1920 0+-647 -1920 0+-648 1905 0+-648 -1921 0+1905 -1921 0+1914 1918 0+1914 1920 0+1914 1921 0+1918 1920 0+1918 1921 0+1920 1921 0+-649 -650 0+-649 -651 0+-649 -1925 0+-650 -651 0+-650 -1925 0+-651 -1925 0+-652 -653 0+-652 -1924 0+-652 1925 0+-653 -1924 0+-653 1925 0+-1924 1925 0+-654 -655 0+-654 -656 0+-654 -1926 0+-655 -656 0+-655 -1926 0+-656 -1926 0+-657 -1923 0+-657 1924 0+-657 1926 0+-1923 1924 0+-1923 1926 0+1924 1926 0+-658 -659 0+-658 -660 0+-658 -1928 0+-659 -660 0+-659 -1928 0+-660 -1928 0+-661 -662 0+-661 -1927 0+-661 1928 0+-662 -1927 0+-662 1928 0+-1927 1928 0+-663 -664 0+-663 -665 0+-663 -1929 0+-664 -665 0+-664 -1929 0+-665 -1929 0+-666 -1922 0+-666 -1930 0+-1922 -1930 0+1923 1927 0+1923 1929 0+1923 1930 0+1927 1929 0+1927 1930 0+1929 1930 0+-667 -668 0+-667 -669 0+-667 -1933 0+-668 -669 0+-668 -1933 0+-669 -1933 0+-670 -671 0+-670 -1932 0+-670 1933 0+-671 -1932 0+-671 1933 0+-1932 1933 0+-672 -673 0+-672 -674 0+-672 -1934 0+-673 -674 0+-673 -1934 0+-674 -1934 0+-675 -1931 0+-675 1932 0+-675 1934 0+-1931 1932 0+-1931 1934 0+1932 1934 0+-676 -677 0+-676 -678 0+-676 -1936 0+-677 -678 0+-677 -1936 0+-678 -1936 0+-679 -680 0+-679 -1935 0+-679 1936 0+-680 -1935 0+-680 1936 0+-1935 1936 0+-681 -682 0+-681 -683 0+-681 -1937 0+-682 -683 0+-682 -1937 0+-683 -1937 0+-684 1922 0+-684 -1938 0+1922 -1938 0+1931 1935 0+1931 1937 0+1931 1938 0+1935 1937 0+1935 1938 0+1937 1938 0+-685 -686 0+-685 -687 0+-685 -1942 0+-686 -687 0+-686 -1942 0+-687 -1942 0+-688 -689 0+-688 -1941 0+-688 1942 0+-689 -1941 0+-689 1942 0+-1941 1942 0+-690 -691 0+-690 -692 0+-690 -1943 0+-691 -692 0+-691 -1943 0+-692 -1943 0+-693 -1940 0+-693 1941 0+-693 1943 0+-1940 1941 0+-1940 1943 0+1941 1943 0+-694 -695 0+-694 -696 0+-694 -1945 0+-695 -696 0+-695 -1945 0+-696 -1945 0+-697 -698 0+-697 -1944 0+-697 1945 0+-698 -1944 0+-698 1945 0+-1944 1945 0+-699 -700 0+-699 -701 0+-699 -1946 0+-700 -701 0+-700 -1946 0+-701 -1946 0+-702 -1939 0+-702 -1947 0+-1939 -1947 0+1940 1944 0+1940 1946 0+1940 1947 0+1944 1946 0+1944 1947 0+1946 1947 0+-703 -704 0+-703 -705 0+-703 -1950 0+-704 -705 0+-704 -1950 0+-705 -1950 0+-706 -707 0+-706 -1949 0+-706 1950 0+-707 -1949 0+-707 1950 0+-1949 1950 0+-708 -709 0+-708 -710 0+-708 -1951 0+-709 -710 0+-709 -1951 0+-710 -1951 0+-711 -1948 0+-711 1949 0+-711 1951 0+-1948 1949 0+-1948 1951 0+1949 1951 0+-712 -713 0+-712 -714 0+-712 -1953 0+-713 -714 0+-713 -1953 0+-714 -1953 0+-715 -716 0+-715 -1952 0+-715 1953 0+-716 -1952 0+-716 1953 0+-1952 1953 0+-717 -718 0+-717 -719 0+-717 -1954 0+-718 -719 0+-718 -1954 0+-719 -1954 0+-720 1939 0+-720 -1955 0+1939 -1955 0+1948 1952 0+1948 1954 0+1948 1955 0+1952 1954 0+1952 1955 0+1954 1955 0+-721 -722 0+-721 -723 0+-721 -1959 0+-722 -723 0+-722 -1959 0+-723 -1959 0+-724 -725 0+-724 -1958 0+-724 1959 0+-725 -1958 0+-725 1959 0+-1958 1959 0+-726 -727 0+-726 -728 0+-726 -1960 0+-727 -728 0+-727 -1960 0+-728 -1960 0+-729 -1957 0+-729 1958 0+-729 1960 0+-1957 1958 0+-1957 1960 0+1958 1960 0+-730 -731 0+-730 -732 0+-730 -1962 0+-731 -732 0+-731 -1962 0+-732 -1962 0+-733 -734 0+-733 -1961 0+-733 1962 0+-734 -1961 0+-734 1962 0+-1961 1962 0+-735 -736 0+-735 -737 0+-735 -1963 0+-736 -737 0+-736 -1963 0+-737 -1963 0+-738 -1956 0+-738 -1964 0+-1956 -1964 0+1957 1961 0+1957 1963 0+1957 1964 0+1961 1963 0+1961 1964 0+1963 1964 0+-739 -740 0+-739 -741 0+-739 -1967 0+-740 -741 0+-740 -1967 0+-741 -1967 0+-742 -743 0+-742 -1966 0+-742 1967 0+-743 -1966 0+-743 1967 0+-1966 1967 0+-744 -745 0+-744 -746 0+-744 -1968 0+-745 -746 0+-745 -1968 0+-746 -1968 0+-747 -1965 0+-747 1966 0+-747 1968 0+-1965 1966 0+-1965 1968 0+1966 1968 0+-748 -749 0+-748 -750 0+-748 -1970 0+-749 -750 0+-749 -1970 0+-750 -1970 0+-751 -752 0+-751 -1969 0+-751 1970 0+-752 -1969 0+-752 1970 0+-1969 1970 0+-753 -754 0+-753 -755 0+-753 -1971 0+-754 -755 0+-754 -1971 0+-755 -1971 0+-756 1956 0+-756 -1972 0+1956 -1972 0+1965 1969 0+1965 1971 0+1965 1972 0+1969 1971 0+1969 1972 0+1971 1972 0+-757 -758 0+-757 -759 0+-757 -1976 0+-758 -759 0+-758 -1976 0+-759 -1976 0+-760 -761 0+-760 -1975 0+-760 1976 0+-761 -1975 0+-761 1976 0+-1975 1976 0+-762 -763 0+-762 -764 0+-762 -1977 0+-763 -764 0+-763 -1977 0+-764 -1977 0+-765 -1974 0+-765 1975 0+-765 1977 0+-1974 1975 0+-1974 1977 0+1975 1977 0+-766 -767 0+-766 -768 0+-766 -1979 0+-767 -768 0+-767 -1979 0+-768 -1979 0+-769 -770 0+-769 -1978 0+-769 1979 0+-770 -1978 0+-770 1979 0+-1978 1979 0+-771 -772 0+-771 -773 0+-771 -1980 0+-772 -773 0+-772 -1980 0+-773 -1980 0+-774 -1973 0+-774 -1981 0+-1973 -1981 0+1974 1978 0+1974 1980 0+1974 1981 0+1978 1980 0+1978 1981 0+1980 1981 0+-775 -776 0+-775 -777 0+-775 -1984 0+-776 -777 0+-776 -1984 0+-777 -1984 0+-778 -779 0+-778 -1983 0+-778 1984 0+-779 -1983 0+-779 1984 0+-1983 1984 0+-780 -781 0+-780 -782 0+-780 -1985 0+-781 -782 0+-781 -1985 0+-782 -1985 0+-783 -1982 0+-783 1983 0+-783 1985 0+-1982 1983 0+-1982 1985 0+1983 1985 0+-784 -785 0+-784 -786 0+-784 -1987 0+-785 -786 0+-785 -1987 0+-786 -1987 0+-787 -788 0+-787 -1986 0+-787 1987 0+-788 -1986 0+-788 1987 0+-1986 1987 0+-789 -790 0+-789 -791 0+-789 -1988 0+-790 -791 0+-790 -1988 0+-791 -1988 0+-792 1973 0+-792 -1989 0+1973 -1989 0+1982 1986 0+1982 1988 0+1982 1989 0+1986 1988 0+1986 1989 0+1988 1989 0+-793 -794 0+-793 -795 0+-793 -1993 0+-794 -795 0+-794 -1993 0+-795 -1993 0+-796 -797 0+-796 -1992 0+-796 1993 0+-797 -1992 0+-797 1993 0+-1992 1993 0+-798 -799 0+-798 -800 0+-798 -1994 0+-799 -800 0+-799 -1994 0+-800 -1994 0+-801 -1991 0+-801 1992 0+-801 1994 0+-1991 1992 0+-1991 1994 0+1992 1994 0+-802 -803 0+-802 -804 0+-802 -1996 0+-803 -804 0+-803 -1996 0+-804 -1996 0+-805 -806 0+-805 -1995 0+-805 1996 0+-806 -1995 0+-806 1996 0+-1995 1996 0+-807 -808 0+-807 -809 0+-807 -1997 0+-808 -809 0+-808 -1997 0+-809 -1997 0+-810 -1990 0+-810 -1998 0+-1990 -1998 0+1991 1995 0+1991 1997 0+1991 1998 0+1995 1997 0+1995 1998 0+1997 1998 0+-811 -812 0+-811 -813 0+-811 -2001 0+-812 -813 0+-812 -2001 0+-813 -2001 0+-814 -815 0+-814 -2000 0+-814 2001 0+-815 -2000 0+-815 2001 0+-2000 2001 0+-816 -817 0+-816 -818 0+-816 -2002 0+-817 -818 0+-817 -2002 0+-818 -2002 0+-819 -1999 0+-819 2000 0+-819 2002 0+-1999 2000 0+-1999 2002 0+2000 2002 0+-820 -821 0+-820 -822 0+-820 -2004 0+-821 -822 0+-821 -2004 0+-822 -2004 0+-823 -824 0+-823 -2003 0+-823 2004 0+-824 -2003 0+-824 2004 0+-2003 2004 0+-825 -826 0+-825 -827 0+-825 -2005 0+-826 -827 0+-826 -2005 0+-827 -2005 0+-828 1990 0+-828 -2006 0+1990 -2006 0+1999 2003 0+1999 2005 0+1999 2006 0+2003 2005 0+2003 2006 0+2005 2006 0+-829 -830 0+-829 -831 0+-829 -2010 0+-830 -831 0+-830 -2010 0+-831 -2010 0+-832 -833 0+-832 -2009 0+-832 2010 0+-833 -2009 0+-833 2010 0+-2009 2010 0+-834 -835 0+-834 -836 0+-834 -2011 0+-835 -836 0+-835 -2011 0+-836 -2011 0+-837 -2008 0+-837 2009 0+-837 2011 0+-2008 2009 0+-2008 2011 0+2009 2011 0+-838 -839 0+-838 -840 0+-838 -2013 0+-839 -840 0+-839 -2013 0+-840 -2013 0+-841 -842 0+-841 -2012 0+-841 2013 0+-842 -2012 0+-842 2013 0+-2012 2013 0+-843 -844 0+-843 -845 0+-843 -2014 0+-844 -845 0+-844 -2014 0+-845 -2014 0+-846 -2007 0+-846 -2015 0+-2007 -2015 0+2008 2012 0+2008 2014 0+2008 2015 0+2012 2014 0+2012 2015 0+2014 2015 0+-847 -848 0+-847 -849 0+-847 -2018 0+-848 -849 0+-848 -2018 0+-849 -2018 0+-850 -851 0+-850 -2017 0+-850 2018 0+-851 -2017 0+-851 2018 0+-2017 2018 0+-852 -853 0+-852 -854 0+-852 -2019 0+-853 -854 0+-853 -2019 0+-854 -2019 0+-855 -2016 0+-855 2017 0+-855 2019 0+-2016 2017 0+-2016 2019 0+2017 2019 0+-856 -857 0+-856 -858 0+-856 -2021 0+-857 -858 0+-857 -2021 0+-858 -2021 0+-859 -860 0+-859 -2020 0+-859 2021 0+-860 -2020 0+-860 2021 0+-2020 2021 0+-861 -862 0+-861 -863 0+-861 -2022 0+-862 -863 0+-862 -2022 0+-863 -2022 0+-864 2007 0+-864 -2023 0+2007 -2023 0+2016 2020 0+2016 2022 0+2016 2023 0+2020 2022 0+2020 2023 0+2022 2023 0+-865 -866 0+-865 -867 0+-865 -2027 0+-866 -867 0+-866 -2027 0+-867 -2027 0+-868 -869 0+-868 -2026 0+-868 2027 0+-869 -2026 0+-869 2027 0+-2026 2027 0+-870 -871 0+-870 -872 0+-870 -2028 0+-871 -872 0+-871 -2028 0+-872 -2028 0+-873 -2025 0+-873 2026 0+-873 2028 0+-2025 2026 0+-2025 2028 0+2026 2028 0+-874 -875 0+-874 -876 0+-874 -2030 0+-875 -876 0+-875 -2030 0+-876 -2030 0+-877 -878 0+-877 -2029 0+-877 2030 0+-878 -2029 0+-878 2030 0+-2029 2030 0+-879 -880 0+-879 -881 0+-879 -2031 0+-880 -881 0+-880 -2031 0+-881 -2031 0+-882 -2024 0+-882 -2032 0+-2024 -2032 0+2025 2029 0+2025 2031 0+2025 2032 0+2029 2031 0+2029 2032 0+2031 2032 0+-883 -884 0+-883 -885 0+-883 -2035 0+-884 -885 0+-884 -2035 0+-885 -2035 0+-886 -887 0+-886 -2034 0+-886 2035 0+-887 -2034 0+-887 2035 0+-2034 2035 0+-888 -889 0+-888 -890 0+-888 -2036 0+-889 -890 0+-889 -2036 0+-890 -2036 0+-891 -2033 0+-891 2034 0+-891 2036 0+-2033 2034 0+-2033 2036 0+2034 2036 0+-892 -893 0+-892 -894 0+-892 -2038 0+-893 -894 0+-893 -2038 0+-894 -2038 0+-895 -896 0+-895 -2037 0+-895 2038 0+-896 -2037 0+-896 2038 0+-2037 2038 0+-897 -898 0+-897 -899 0+-897 -2039 0+-898 -899 0+-898 -2039 0+-899 -2039 0+-900 2024 0+-900 -2040 0+2024 -2040 0+2033 2037 0+2033 2039 0+2033 2040 0+2037 2039 0+2037 2040 0+2039 2040 0+-901 -902 0+-901 -903 0+-901 -2044 0+-902 -903 0+-902 -2044 0+-903 -2044 0+-904 -905 0+-904 -2043 0+-904 2044 0+-905 -2043 0+-905 2044 0+-2043 2044 0+-906 -907 0+-906 -908 0+-906 -2045 0+-907 -908 0+-907 -2045 0+-908 -2045 0+-909 -2042 0+-909 2043 0+-909 2045 0+-2042 2043 0+-2042 2045 0+2043 2045 0+-910 -911 0+-910 -912 0+-910 -2047 0+-911 -912 0+-911 -2047 0+-912 -2047 0+-913 -914 0+-913 -2046 0+-913 2047 0+-914 -2046 0+-914 2047 0+-2046 2047 0+-915 -916 0+-915 -917 0+-915 -2048 0+-916 -917 0+-916 -2048 0+-917 -2048 0+-918 -2041 0+-918 -2049 0+-2041 -2049 0+2042 2046 0+2042 2048 0+2042 2049 0+2046 2048 0+2046 2049 0+2048 2049 0+-919 -920 0+-919 -921 0+-919 -2052 0+-920 -921 0+-920 -2052 0+-921 -2052 0+-922 -923 0+-922 -2051 0+-922 2052 0+-923 -2051 0+-923 2052 0+-2051 2052 0+-924 -925 0+-924 -926 0+-924 -2053 0+-925 -926 0+-925 -2053 0+-926 -2053 0+-927 -2050 0+-927 2051 0+-927 2053 0+-2050 2051 0+-2050 2053 0+2051 2053 0+-928 -929 0+-928 -930 0+-928 -2055 0+-929 -930 0+-929 -2055 0+-930 -2055 0+-931 -932 0+-931 -2054 0+-931 2055 0+-932 -2054 0+-932 2055 0+-2054 2055 0+-933 -934 0+-933 -935 0+-933 -2056 0+-934 -935 0+-934 -2056 0+-935 -2056 0+-936 2041 0+-936 -2057 0+2041 -2057 0+2050 2054 0+2050 2056 0+2050 2057 0+2054 2056 0+2054 2057 0+2056 2057 0+-937 -938 0+-937 -939 0+-937 -2061 0+-938 -939 0+-938 -2061 0+-939 -2061 0+-940 -941 0+-940 -2060 0+-940 2061 0+-941 -2060 0+-941 2061 0+-2060 2061 0+-942 -943 0+-942 -944 0+-942 -2062 0+-943 -944 0+-943 -2062 0+-944 -2062 0+-945 -2059 0+-945 2060 0+-945 2062 0+-2059 2060 0+-2059 2062 0+2060 2062 0+-946 -947 0+-946 -948 0+-946 -2064 0+-947 -948 0+-947 -2064 0+-948 -2064 0+-949 -950 0+-949 -2063 0+-949 2064 0+-950 -2063 0+-950 2064 0+-2063 2064 0+-951 -952 0+-951 -953 0+-951 -2065 0+-952 -953 0+-952 -2065 0+-953 -2065 0+-954 -2058 0+-954 -2066 0+-2058 -2066 0+2059 2063 0+2059 2065 0+2059 2066 0+2063 2065 0+2063 2066 0+2065 2066 0+-955 -956 0+-955 -957 0+-955 -2069 0+-956 -957 0+-956 -2069 0+-957 -2069 0+-958 -959 0+-958 -2068 0+-958 2069 0+-959 -2068 0+-959 2069 0+-2068 2069 0+-960 -961 0+-960 -962 0+-960 -2070 0+-961 -962 0+-961 -2070 0+-962 -2070 0+-963 -2067 0+-963 2068 0+-963 2070 0+-2067 2068 0+-2067 2070 0+2068 2070 0+-964 -965 0+-964 -966 0+-964 -2072 0+-965 -966 0+-965 -2072 0+-966 -2072 0+-967 -968 0+-967 -2071 0+-967 2072 0+-968 -2071 0+-968 2072 0+-2071 2072 0+-969 -970 0+-969 -971 0+-969 -2073 0+-970 -971 0+-970 -2073 0+-971 -2073 0+-972 2058 0+-972 -2074 0+2058 -2074 0+2067 2071 0+2067 2073 0+2067 2074 0+2071 2073 0+2071 2074 0+2073 2074 0+-973 -974 0+-973 -975 0+-973 -2078 0+-974 -975 0+-974 -2078 0+-975 -2078 0+-976 -977 0+-976 -2077 0+-976 2078 0+-977 -2077 0+-977 2078 0+-2077 2078 0+-978 -979 0+-978 -980 0+-978 -2079 0+-979 -980 0+-979 -2079 0+-980 -2079 0+-981 -2076 0+-981 2077 0+-981 2079 0+-2076 2077 0+-2076 2079 0+2077 2079 0+-982 -983 0+-982 -984 0+-982 -2081 0+-983 -984 0+-983 -2081 0+-984 -2081 0+-985 -986 0+-985 -2080 0+-985 2081 0+-986 -2080 0+-986 2081 0+-2080 2081 0+-987 -988 0+-987 -989 0+-987 -2082 0+-988 -989 0+-988 -2082 0+-989 -2082 0+-990 -2075 0+-990 -2083 0+-2075 -2083 0+2076 2080 0+2076 2082 0+2076 2083 0+2080 2082 0+2080 2083 0+2082 2083 0+-991 -992 0+-991 -993 0+-991 -2086 0+-992 -993 0+-992 -2086 0+-993 -2086 0+-994 -995 0+-994 -2085 0+-994 2086 0+-995 -2085 0+-995 2086 0+-2085 2086 0+-996 -997 0+-996 -998 0+-996 -2087 0+-997 -998 0+-997 -2087 0+-998 -2087 0+-999 -2084 0+-999 2085 0+-999 2087 0+-2084 2085 0+-2084 2087 0+2085 2087 0+-1000 -1001 0+-1000 -1002 0+-1000 -2089 0+-1001 -1002 0+-1001 -2089 0+-1002 -2089 0+-1003 -1004 0+-1003 -2088 0+-1003 2089 0+-1004 -2088 0+-1004 2089 0+-2088 2089 0+-1005 -1006 0+-1005 -1007 0+-1005 -2090 0+-1006 -1007 0+-1006 -2090 0+-1007 -2090 0+-1008 2075 0+-1008 -2091 0+2075 -2091 0+2084 2088 0+2084 2090 0+2084 2091 0+2088 2090 0+2088 2091 0+2090 2091 0+-1009 -1010 0+-1009 -1011 0+-1009 -2095 0+-1010 -1011 0+-1010 -2095 0+-1011 -2095 0+-1012 -1013 0+-1012 -2094 0+-1012 2095 0+-1013 -2094 0+-1013 2095 0+-2094 2095 0+-1014 -1015 0+-1014 -1016 0+-1014 -2096 0+-1015 -1016 0+-1015 -2096 0+-1016 -2096 0+-1017 -2093 0+-1017 2094 0+-1017 2096 0+-2093 2094 0+-2093 2096 0+2094 2096 0+-1018 -1019 0+-1018 -1020 0+-1018 -2098 0+-1019 -1020 0+-1019 -2098 0+-1020 -2098 0+-1021 -1022 0+-1021 -2097 0+-1021 2098 0+-1022 -2097 0+-1022 2098 0+-2097 2098 0+-1023 -1024 0+-1023 -1025 0+-1023 -2099 0+-1024 -1025 0+-1024 -2099 0+-1025 -2099 0+-1026 -2092 0+-1026 -2100 0+-2092 -2100 0+2093 2097 0+2093 2099 0+2093 2100 0+2097 2099 0+2097 2100 0+2099 2100 0+-1027 -1028 0+-1027 -1029 0+-1027 -2103 0+-1028 -1029 0+-1028 -2103 0+-1029 -2103 0+-1030 -1031 0+-1030 -2102 0+-1030 2103 0+-1031 -2102 0+-1031 2103 0+-2102 2103 0+-1032 -1033 0+-1032 -1034 0+-1032 -2104 0+-1033 -1034 0+-1033 -2104 0+-1034 -2104 0+-1035 -2101 0+-1035 2102 0+-1035 2104 0+-2101 2102 0+-2101 2104 0+2102 2104 0+-1036 -1037 0+-1036 -1038 0+-1036 -2106 0+-1037 -1038 0+-1037 -2106 0+-1038 -2106 0+-1039 -1040 0+-1039 -2105 0+-1039 2106 0+-1040 -2105 0+-1040 2106 0+-2105 2106 0+-1041 -1042 0+-1041 -1043 0+-1041 -2107 0+-1042 -1043 0+-1042 -2107 0+-1043 -2107 0+-1044 2092 0+-1044 -2108 0+2092 -2108 0+2101 2105 0+2101 2107 0+2101 2108 0+2105 2107 0+2105 2108 0+2107 2108 0+-1045 -1046 0+-1045 -1047 0+-1045 -2112 0+-1046 -1047 0+-1046 -2112 0+-1047 -2112 0+-1048 -1049 0+-1048 -2111 0+-1048 2112 0+-1049 -2111 0+-1049 2112 0+-2111 2112 0+-1050 -1051 0+-1050 -1052 0+-1050 -2113 0+-1051 -1052 0+-1051 -2113 0+-1052 -2113 0+-1053 -2110 0+-1053 2111 0+-1053 2113 0+-2110 2111 0+-2110 2113 0+2111 2113 0+-1054 -1055 0+-1054 -1056 0+-1054 -2115 0+-1055 -1056 0+-1055 -2115 0+-1056 -2115 0+-1057 -1058 0+-1057 -2114 0+-1057 2115 0+-1058 -2114 0+-1058 2115 0+-2114 2115 0+-1059 -1060 0+-1059 -1061 0+-1059 -2116 0+-1060 -1061 0+-1060 -2116 0+-1061 -2116 0+-1062 -2109 0+-1062 -2117 0+-2109 -2117 0+2110 2114 0+2110 2116 0+2110 2117 0+2114 2116 0+2114 2117 0+2116 2117 0+-1063 -1064 0+-1063 -1065 0+-1063 -2120 0+-1064 -1065 0+-1064 -2120 0+-1065 -2120 0+-1066 -1067 0+-1066 -2119 0+-1066 2120 0+-1067 -2119 0+-1067 2120 0+-2119 2120 0+-1068 -1069 0+-1068 -1070 0+-1068 -2121 0+-1069 -1070 0+-1069 -2121 0+-1070 -2121 0+-1071 -2118 0+-1071 2119 0+-1071 2121 0+-2118 2119 0+-2118 2121 0+2119 2121 0+-1072 -1073 0+-1072 -1074 0+-1072 -2123 0+-1073 -1074 0+-1073 -2123 0+-1074 -2123 0+-1075 -1076 0+-1075 -2122 0+-1075 2123 0+-1076 -2122 0+-1076 2123 0+-2122 2123 0+-1077 -1078 0+-1077 -1079 0+-1077 -2124 0+-1078 -1079 0+-1078 -2124 0+-1079 -2124 0+-1080 2109 0+-1080 -2125 0+2109 -2125 0+2118 2122 0+2118 2124 0+2118 2125 0+2122 2124 0+2122 2125 0+2124 2125 0+-1081 -1082 0+-1081 -1083 0+-1081 -2129 0+-1082 -1083 0+-1082 -2129 0+-1083 -2129 0+-1084 -1085 0+-1084 -2128 0+-1084 2129 0+-1085 -2128 0+-1085 2129 0+-2128 2129 0+-1086 -1087 0+-1086 -1088 0+-1086 -2130 0+-1087 -1088 0+-1087 -2130 0+-1088 -2130 0+-1089 -2127 0+-1089 2128 0+-1089 2130 0+-2127 2128 0+-2127 2130 0+2128 2130 0+-1090 -1091 0+-1090 -1092 0+-1090 -2132 0+-1091 -1092 0+-1091 -2132 0+-1092 -2132 0+-1093 -1094 0+-1093 -2131 0+-1093 2132 0+-1094 -2131 0+-1094 2132 0+-2131 2132 0+-1095 -1096 0+-1095 -1097 0+-1095 -2133 0+-1096 -1097 0+-1096 -2133 0+-1097 -2133 0+-1098 -2126 0+-1098 -2134 0+-2126 -2134 0+2127 2131 0+2127 2133 0+2127 2134 0+2131 2133 0+2131 2134 0+2133 2134 0+-1099 -1100 0+-1099 -1101 0+-1099 -2137 0+-1100 -1101 0+-1100 -2137 0+-1101 -2137 0+-1102 -1103 0+-1102 -2136 0+-1102 2137 0+-1103 -2136 0+-1103 2137 0+-2136 2137 0+-1104 -1105 0+-1104 -1106 0+-1104 -2138 0+-1105 -1106 0+-1105 -2138 0+-1106 -2138 0+-1107 -2135 0+-1107 2136 0+-1107 2138 0+-2135 2136 0+-2135 2138 0+2136 2138 0+-1108 -1109 0+-1108 -1110 0+-1108 -2140 0+-1109 -1110 0+-1109 -2140 0+-1110 -2140 0+-1111 -1112 0+-1111 -2139 0+-1111 2140 0+-1112 -2139 0+-1112 2140 0+-2139 2140 0+-1113 -1114 0+-1113 -1115 0+-1113 -2141 0+-1114 -1115 0+-1114 -2141 0+-1115 -2141 0+-1116 2126 0+-1116 -2142 0+2126 -2142 0+2135 2139 0+2135 2141 0+2135 2142 0+2139 2141 0+2139 2142 0+2141 2142 0+-1117 -1118 0+-1117 -1119 0+-1117 -2146 0+-1118 -1119 0+-1118 -2146 0+-1119 -2146 0+-1120 -1121 0+-1120 -2145 0+-1120 2146 0+-1121 -2145 0+-1121 2146 0+-2145 2146 0+-1122 -1123 0+-1122 -1124 0+-1122 -2147 0+-1123 -1124 0+-1123 -2147 0+-1124 -2147 0+-1125 -2144 0+-1125 2145 0+-1125 2147 0+-2144 2145 0+-2144 2147 0+2145 2147 0+-1126 -1127 0+-1126 -1128 0+-1126 -2149 0+-1127 -1128 0+-1127 -2149 0+-1128 -2149 0+-1129 -1130 0+-1129 -2148 0+-1129 2149 0+-1130 -2148 0+-1130 2149 0+-2148 2149 0+-1131 -1132 0+-1131 -1133 0+-1131 -2150 0+-1132 -1133 0+-1132 -2150 0+-1133 -2150 0+-1134 -2143 0+-1134 -2151 0+-2143 -2151 0+2144 2148 0+2144 2150 0+2144 2151 0+2148 2150 0+2148 2151 0+2150 2151 0+-1135 -1136 0+-1135 -1137 0+-1135 -2154 0+-1136 -1137 0+-1136 -2154 0+-1137 -2154 0+-1138 -1139 0+-1138 -2153 0+-1138 2154 0+-1139 -2153 0+-1139 2154 0+-2153 2154 0+-1140 -1141 0+-1140 -1142 0+-1140 -2155 0+-1141 -1142 0+-1141 -2155 0+-1142 -2155 0+-1143 -2152 0+-1143 2153 0+-1143 2155 0+-2152 2153 0+-2152 2155 0+2153 2155 0+-1144 -1145 0+-1144 -1146 0+-1144 -2157 0+-1145 -1146 0+-1145 -2157 0+-1146 -2157 0+-1147 -1148 0+-1147 -2156 0+-1147 2157 0+-1148 -2156 0+-1148 2157 0+-2156 2157 0+-1149 -1150 0+-1149 -1151 0+-1149 -2158 0+-1150 -1151 0+-1150 -2158 0+-1151 -2158 0+-1152 2143 0+-1152 -2159 0+2143 -2159 0+2152 2156 0+2152 2158 0+2152 2159 0+2156 2158 0+2156 2159 0+2158 2159 0+-1153 -1154 0+-1153 -1155 0+-1153 -2163 0+-1154 -1155 0+-1154 -2163 0+-1155 -2163 0+-1156 -1157 0+-1156 -2162 0+-1156 2163 0+-1157 -2162 0+-1157 2163 0+-2162 2163 0+-1158 -1159 0+-1158 -1160 0+-1158 -2164 0+-1159 -1160 0+-1159 -2164 0+-1160 -2164 0+-1161 -2161 0+-1161 2162 0+-1161 2164 0+-2161 2162 0+-2161 2164 0+2162 2164 0+-1162 -1163 0+-1162 -1164 0+-1162 -2166 0+-1163 -1164 0+-1163 -2166 0+-1164 -2166 0+-1165 -1166 0+-1165 -2165 0+-1165 2166 0+-1166 -2165 0+-1166 2166 0+-2165 2166 0+-1167 -1168 0+-1167 -1169 0+-1167 -2167 0+-1168 -1169 0+-1168 -2167 0+-1169 -2167 0+-1170 -2160 0+-1170 -2168 0+-2160 -2168 0+2161 2165 0+2161 2167 0+2161 2168 0+2165 2167 0+2165 2168 0+2167 2168 0+-1171 -1172 0+-1171 -1173 0+-1171 -2171 0+-1172 -1173 0+-1172 -2171 0+-1173 -2171 0+-1174 -1175 0+-1174 -2170 0+-1174 2171 0+-1175 -2170 0+-1175 2171 0+-2170 2171 0+-1176 -1177 0+-1176 -1178 0+-1176 -2172 0+-1177 -1178 0+-1177 -2172 0+-1178 -2172 0+-1179 -2169 0+-1179 2170 0+-1179 2172 0+-2169 2170 0+-2169 2172 0+2170 2172 0+-1180 -1181 0+-1180 -1182 0+-1180 -2174 0+-1181 -1182 0+-1181 -2174 0+-1182 -2174 0+-1183 -1184 0+-1183 -2173 0+-1183 2174 0+-1184 -2173 0+-1184 2174 0+-2173 2174 0+-1185 -1186 0+-1185 -1187 0+-1185 -2175 0+-1186 -1187 0+-1186 -2175 0+-1187 -2175 0+-1188 2160 0+-1188 -2176 0+2160 -2176 0+2169 2173 0+2169 2175 0+2169 2176 0+2173 2175 0+2173 2176 0+2175 2176 0+-1189 -1190 0+-1189 -1191 0+-1189 -2180 0+-1190 -1191 0+-1190 -2180 0+-1191 -2180 0+-1192 -1193 0+-1192 -2179 0+-1192 2180 0+-1193 -2179 0+-1193 2180 0+-2179 2180 0+-1194 -1195 0+-1194 -1196 0+-1194 -2181 0+-1195 -1196 0+-1195 -2181 0+-1196 -2181 0+-1197 -2178 0+-1197 2179 0+-1197 2181 0+-2178 2179 0+-2178 2181 0+2179 2181 0+-1198 -1199 0+-1198 -1200 0+-1198 -2183 0+-1199 -1200 0+-1199 -2183 0+-1200 -2183 0+-1201 -1202 0+-1201 -2182 0+-1201 2183 0+-1202 -2182 0+-1202 2183 0+-2182 2183 0+-1203 -1204 0+-1203 -1205 0+-1203 -2184 0+-1204 -1205 0+-1204 -2184 0+-1205 -2184 0+-1206 -2177 0+-1206 -2185 0+-2177 -2185 0+2178 2182 0+2178 2184 0+2178 2185 0+2182 2184 0+2182 2185 0+2184 2185 0+-1207 -1208 0+-1207 -1209 0+-1207 -2188 0+-1208 -1209 0+-1208 -2188 0+-1209 -2188 0+-1210 -1211 0+-1210 -2187 0+-1210 2188 0+-1211 -2187 0+-1211 2188 0+-2187 2188 0+-1212 -1213 0+-1212 -1214 0+-1212 -2189 0+-1213 -1214 0+-1213 -2189 0+-1214 -2189 0+-1215 -2186 0+-1215 2187 0+-1215 2189 0+-2186 2187 0+-2186 2189 0+2187 2189 0+-1216 -1217 0+-1216 -1218 0+-1216 -2191 0+-1217 -1218 0+-1217 -2191 0+-1218 -2191 0+-1219 -1220 0+-1219 -2190 0+-1219 2191 0+-1220 -2190 0+-1220 2191 0+-2190 2191 0+-1221 -1222 0+-1221 -1223 0+-1221 -2192 0+-1222 -1223 0+-1222 -2192 0+-1223 -2192 0+-1224 2177 0+-1224 -2193 0+2177 -2193 0+2186 2190 0+2186 2192 0+2186 2193 0+2190 2192 0+2190 2193 0+2192 2193 0+-1225 -1226 0+-1225 -1227 0+-1225 -2197 0+-1226 -1227 0+-1226 -2197 0+-1227 -2197 0+-1228 -1229 0+-1228 -2196 0+-1228 2197 0+-1229 -2196 0+-1229 2197 0+-2196 2197 0+-1230 -1231 0+-1230 -1232 0+-1230 -2198 0+-1231 -1232 0+-1231 -2198 0+-1232 -2198 0+-1233 -2195 0+-1233 2196 0+-1233 2198 0+-2195 2196 0+-2195 2198 0+2196 2198 0+-1234 -1235 0+-1234 -1236 0+-1234 -2200 0+-1235 -1236 0+-1235 -2200 0+-1236 -2200 0+-1237 -1238 0+-1237 -2199 0+-1237 2200 0+-1238 -2199 0+-1238 2200 0+-2199 2200 0+-1239 -1240 0+-1239 -1241 0+-1239 -2201 0+-1240 -1241 0+-1240 -2201 0+-1241 -2201 0+-1242 -2194 0+-1242 -2202 0+-2194 -2202 0+2195 2199 0+2195 2201 0+2195 2202 0+2199 2201 0+2199 2202 0+2201 2202 0+-1243 -1244 0+-1243 -1245 0+-1243 -2205 0+-1244 -1245 0+-1244 -2205 0+-1245 -2205 0+-1246 -1247 0+-1246 -2204 0+-1246 2205 0+-1247 -2204 0+-1247 2205 0+-2204 2205 0+-1248 -1249 0+-1248 -1250 0+-1248 -2206 0+-1249 -1250 0+-1249 -2206 0+-1250 -2206 0+-1251 -2203 0+-1251 2204 0+-1251 2206 0+-2203 2204 0+-2203 2206 0+2204 2206 0+-1252 -1253 0+-1252 -1254 0+-1252 -2208 0+-1253 -1254 0+-1253 -2208 0+-1254 -2208 0+-1255 -1256 0+-1255 -2207 0+-1255 2208 0+-1256 -2207 0+-1256 2208 0+-2207 2208 0+-1257 -1258 0+-1257 -1259 0+-1257 -2209 0+-1258 -1259 0+-1258 -2209 0+-1259 -2209 0+-1260 2194 0+-1260 -2210 0+2194 -2210 0+2203 2207 0+2203 2209 0+2203 2210 0+2207 2209 0+2207 2210 0+2209 2210 0+-1261 -1262 0+-1261 -1263 0+-1261 -2214 0+-1262 -1263 0+-1262 -2214 0+-1263 -2214 0+-1264 -1265 0+-1264 -2213 0+-1264 2214 0+-1265 -2213 0+-1265 2214 0+-2213 2214 0+-1266 -1267 0+-1266 -1268 0+-1266 -2215 0+-1267 -1268 0+-1267 -2215 0+-1268 -2215 0+-1269 -2212 0+-1269 2213 0+-1269 2215 0+-2212 2213 0+-2212 2215 0+2213 2215 0+-1270 -1271 0+-1270 -1272 0+-1270 -2217 0+-1271 -1272 0+-1271 -2217 0+-1272 -2217 0+-1273 -1274 0+-1273 -2216 0+-1273 2217 0+-1274 -2216 0+-1274 2217 0+-2216 2217 0+-1275 -1276 0+-1275 -1277 0+-1275 -2218 0+-1276 -1277 0+-1276 -2218 0+-1277 -2218 0+-1278 -2211 0+-1278 -2219 0+-2211 -2219 0+2212 2216 0+2212 2218 0+2212 2219 0+2216 2218 0+2216 2219 0+2218 2219 0+-1279 -1280 0+-1279 -1281 0+-1279 -2222 0+-1280 -1281 0+-1280 -2222 0+-1281 -2222 0+-1282 -1283 0+-1282 -2221 0+-1282 2222 0+-1283 -2221 0+-1283 2222 0+-2221 2222 0+-1284 -1285 0+-1284 -1286 0+-1284 -2223 0+-1285 -1286 0+-1285 -2223 0+-1286 -2223 0+-1287 -2220 0+-1287 2221 0+-1287 2223 0+-2220 2221 0+-2220 2223 0+2221 2223 0+-1288 -1289 0+-1288 -1290 0+-1288 -2225 0+-1289 -1290 0+-1289 -2225 0+-1290 -2225 0+-1291 -1292 0+-1291 -2224 0+-1291 2225 0+-1292 -2224 0+-1292 2225 0+-2224 2225 0+-1293 -1294 0+-1293 -1295 0+-1293 -2226 0+-1294 -1295 0+-1294 -2226 0+-1295 -2226 0+-1296 2211 0+-1296 -2227 0+2211 -2227 0+2220 2224 0+2220 2226 0+2220 2227 0+2224 2226 0+2224 2227 0+2226 2227 0+1 37 73 109 145 181 217 253 289 325 361 397 433 469 505 541 577 613 649 685 721 757 793 829 865 901 937 973 1009 1045 1081 1117 1153 1189 1225 1261 0+2 38 74 110 146 182 218 254 290 326 362 398 434 470 506 542 578 614 650 686 722 758 794 830 866 902 938 974 1010 1046 1082 1118 1154 1190 1226 1262 0+3 39 75 111 147 183 219 255 291 327 363 399 435 471 507 543 579 615 651 687 723 759 795 831 867 903 939 975 1011 1047 1083 1119 1155 1191 1227 1263 0+4 40 76 112 148 184 220 256 292 328 364 400 436 472 508 544 580 616 652 688 724 760 796 832 868 904 940 976 1012 1048 1084 1120 1156 1192 1228 1264 0+5 41 77 113 149 185 221 257 293 329 365 401 437 473 509 545 581 617 653 689 725 761 797 833 869 905 941 977 1013 1049 1085 1121 1157 1193 1229 1265 0+6 42 78 114 150 186 222 258 294 330 366 402 438 474 510 546 582 618 654 690 726 762 798 834 870 906 942 978 1014 1050 1086 1122 1158 1194 1230 1266 0+7 43 79 115 151 187 223 259 295 331 367 403 439 475 511 547 583 619 655 691 727 763 799 835 871 907 943 979 1015 1051 1087 1123 1159 1195 1231 1267 0+8 44 80 116 152 188 224 260 296 332 368 404 440 476 512 548 584 620 656 692 728 764 800 836 872 908 944 980 1016 1052 1088 1124 1160 1196 1232 1268 0+9 45 81 117 153 189 225 261 297 333 369 405 441 477 513 549 585 621 657 693 729 765 801 837 873 909 945 981 1017 1053 1089 1125 1161 1197 1233 1269 0+10 46 82 118 154 190 226 262 298 334 370 406 442 478 514 550 586 622 658 694 730 766 802 838 874 910 946 982 1018 1054 1090 1126 1162 1198 1234 1270 0+11 47 83 119 155 191 227 263 299 335 371 407 443 479 515 551 587 623 659 695 731 767 803 839 875 911 947 983 1019 1055 1091 1127 1163 1199 1235 1271 0+12 48 84 120 156 192 228 264 300 336 372 408 444 480 516 552 588 624 660 696 732 768 804 840 876 912 948 984 1020 1056 1092 1128 1164 1200 1236 1272 0+13 49 85 121 157 193 229 265 301 337 373 409 445 481 517 553 589 625 661 697 733 769 805 841 877 913 949 985 1021 1057 1093 1129 1165 1201 1237 1273 0+14 50 86 122 158 194 230 266 302 338 374 410 446 482 518 554 590 626 662 698 734 770 806 842 878 914 950 986 1022 1058 1094 1130 1166 1202 1238 1274 0+15 51 87 123 159 195 231 267 303 339 375 411 447 483 519 555 591 627 663 699 735 771 807 843 879 915 951 987 1023 1059 1095 1131 1167 1203 1239 1275 0+16 52 88 124 160 196 232 268 304 340 376 412 448 484 520 556 592 628 664 700 736 772 808 844 880 916 952 988 1024 1060 1096 1132 1168 1204 1240 1276 0+17 53 89 125 161 197 233 269 305 341 377 413 449 485 521 557 593 629 665 701 737 773 809 845 881 917 953 989 1025 1061 1097 1133 1169 1205 1241 1277 0+18 54 90 126 162 198 234 270 306 342 378 414 450 486 522 558 594 630 666 702 738 774 810 846 882 918 954 990 1026 1062 1098 1134 1170 1206 1242 1278 0+19 55 91 127 163 199 235 271 307 343 379 415 451 487 523 559 595 631 667 703 739 775 811 847 883 919 955 991 1027 1063 1099 1135 1171 1207 1243 1279 0+20 56 92 128 164 200 236 272 308 344 380 416 452 488 524 560 596 632 668 704 740 776 812 848 884 920 956 992 1028 1064 1100 1136 1172 1208 1244 1280 0+21 57 93 129 165 201 237 273 309 345 381 417 453 489 525 561 597 633 669 705 741 777 813 849 885 921 957 993 1029 1065 1101 1137 1173 1209 1245 1281 0+22 58 94 130 166 202 238 274 310 346 382 418 454 490 526 562 598 634 670 706 742 778 814 850 886 922 958 994 1030 1066 1102 1138 1174 1210 1246 1282 0+23 59 95 131 167 203 239 275 311 347 383 419 455 491 527 563 599 635 671 707 743 779 815 851 887 923 959 995 1031 1067 1103 1139 1175 1211 1247 1283 0+24 60 96 132 168 204 240 276 312 348 384 420 456 492 528 564 600 636 672 708 744 780 816 852 888 924 960 996 1032 1068 1104 1140 1176 1212 1248 1284 0+25 61 97 133 169 205 241 277 313 349 385 421 457 493 529 565 601 637 673 709 745 781 817 853 889 925 961 997 1033 1069 1105 1141 1177 1213 1249 1285 0+26 62 98 134 170 206 242 278 314 350 386 422 458 494 530 566 602 638 674 710 746 782 818 854 890 926 962 998 1034 1070 1106 1142 1178 1214 1250 1286 0+27 63 99 135 171 207 243 279 315 351 387 423 459 495 531 567 603 639 675 711 747 783 819 855 891 927 963 999 1035 1071 1107 1143 1179 1215 1251 1287 0+28 64 100 136 172 208 244 280 316 352 388 424 460 496 532 568 604 640 676 712 748 784 820 856 892 928 964 1000 1036 1072 1108 1144 1180 1216 1252 1288 0+29 65 101 137 173 209 245 281 317 353 389 425 461 497 533 569 605 641 677 713 749 785 821 857 893 929 965 1001 1037 1073 1109 1145 1181 1217 1253 1289 0+30 66 102 138 174 210 246 282 318 354 390 426 462 498 534 570 606 642 678 714 750 786 822 858 894 930 966 1002 1038 1074 1110 1146 1182 1218 1254 1290 0+31 67 103 139 175 211 247 283 319 355 391 427 463 499 535 571 607 643 679 715 751 787 823 859 895 931 967 1003 1039 1075 1111 1147 1183 1219 1255 1291 0+32 68 104 140 176 212 248 284 320 356 392 428 464 500 536 572 608 644 680 716 752 788 824 860 896 932 968 1004 1040 1076 1112 1148 1184 1220 1256 1292 0+33 69 105 141 177 213 249 285 321 357 393 429 465 501 537 573 609 645 681 717 753 789 825 861 897 933 969 1005 1041 1077 1113 1149 1185 1221 1257 1293 0+34 70 106 142 178 214 250 286 322 358 394 430 466 502 538 574 610 646 682 718 754 790 826 862 898 934 970 1006 1042 1078 1114 1150 1186 1222 1258 1294 0+35 71 107 143 179 215 251 287 323 359 395 431 467 503 539 575 611 647 683 719 755 791 827 863 899 935 971 1007 1043 1079 1115 1151 1187 1223 1259 1295 0+36 72 108 144 180 216 252 288 324 360 396 432 468 504 540 576 612 648 684 720 756 792 828 864 900 936 972 1008 1044 1080 1116 1152 1188 1224 1260 1296 0+-1 -1302 38 0+-2 -1302 39 0+-3 -1302 40 0+-4 -1302 41 0+-5 -1302 42 0+-6 -1302 43 0+-7 -1302 44 0+-8 -1302 45 0+-9 -1302 46 0+-10 -1302 47 0+-11 -1302 48 0+-12 -1302 49 0+-13 -1302 50 0+-14 -1302 51 0+-15 -1302 52 0+-16 -1302 53 0+-17 -1302 54 0+-18 -1302 55 0+-19 -1302 56 0+-20 -1302 57 0+-21 -1302 58 0+-22 -1302 59 0+-23 -1302 60 0+-24 -1302 61 0+-25 -1302 62 0+-26 -1302 63 0+-27 -1302 64 0+-28 -1302 65 0+-29 -1302 66 0+-30 -1302 67 0+-31 -1302 68 0+-32 -1302 69 0+-33 -1302 70 0+-34 -1302 71 0+-35 -1302 72 0+-1 -1304 218 0+-2 -1304 219 0+-3 -1304 220 0+-4 -1304 221 0+-5 -1304 222 0+-6 -1304 223 0+-7 -1304 224 0+-8 -1304 225 0+-9 -1304 226 0+-10 -1304 227 0+-11 -1304 228 0+-12 -1304 229 0+-13 -1304 230 0+-14 -1304 231 0+-15 -1304 232 0+-16 -1304 233 0+-17 -1304 234 0+-18 -1304 235 0+-19 -1304 236 0+-20 -1304 237 0+-21 -1304 238 0+-22 -1304 239 0+-23 -1304 240 0+-24 -1304 241 0+-25 -1304 242 0+-26 -1304 243 0+-27 -1304 244 0+-28 -1304 245 0+-29 -1304 246 0+-30 -1304 247 0+-31 -1304 248 0+-32 -1304 249 0+-33 -1304 250 0+-34 -1304 251 0+-35 -1304 252 0+-1 -1305 254 0+-2 -1305 255 0+-3 -1305 256 0+-4 -1305 257 0+-5 -1305 258 0+-6 -1305 259 0+-7 -1305 260 0+-8 -1305 261 0+-9 -1305 262 0+-10 -1305 263 0+-11 -1305 264 0+-12 -1305 265 0+-13 -1305 266 0+-14 -1305 267 0+-15 -1305 268 0+-16 -1305 269 0+-17 -1305 270 0+-18 -1305 271 0+-19 -1305 272 0+-20 -1305 273 0+-21 -1305 274 0+-22 -1305 275 0+-23 -1305 276 0+-24 -1305 277 0+-25 -1305 278 0+-26 -1305 279 0+-27 -1305 280 0+-28 -1305 281 0+-29 -1305 282 0+-30 -1305 283 0+-31 -1305 284 0+-32 -1305 285 0+-33 -1305 286 0+-34 -1305 287 0+-35 -1305 288 0+-1302 -1304 0+-1302 -1305 0+-1304 -1305 0+1302 1304 1305 0+-37 -1309 2 0+-38 -1309 3 0+-39 -1309 4 0+-40 -1309 5 0+-41 -1309 6 0+-42 -1309 7 0+-43 -1309 8 0+-44 -1309 9 0+-45 -1309 10 0+-46 -1309 11 0+-47 -1309 12 0+-48 -1309 13 0+-49 -1309 14 0+-50 -1309 15 0+-51 -1309 16 0+-52 -1309 17 0+-53 -1309 18 0+-54 -1309 19 0+-55 -1309 20 0+-56 -1309 21 0+-57 -1309 22 0+-58 -1309 23 0+-59 -1309 24 0+-60 -1309 25 0+-61 -1309 26 0+-62 -1309 27 0+-63 -1309 28 0+-64 -1309 29 0+-65 -1309 30 0+-66 -1309 31 0+-67 -1309 32 0+-68 -1309 33 0+-69 -1309 34 0+-70 -1309 35 0+-71 -1309 36 0+-37 -1311 74 0+-38 -1311 75 0+-39 -1311 76 0+-40 -1311 77 0+-41 -1311 78 0+-42 -1311 79 0+-43 -1311 80 0+-44 -1311 81 0+-45 -1311 82 0+-46 -1311 83 0+-47 -1311 84 0+-48 -1311 85 0+-49 -1311 86 0+-50 -1311 87 0+-51 -1311 88 0+-52 -1311 89 0+-53 -1311 90 0+-54 -1311 91 0+-55 -1311 92 0+-56 -1311 93 0+-57 -1311 94 0+-58 -1311 95 0+-59 -1311 96 0+-60 -1311 97 0+-61 -1311 98 0+-62 -1311 99 0+-63 -1311 100 0+-64 -1311 101 0+-65 -1311 102 0+-66 -1311 103 0+-67 -1311 104 0+-68 -1311 105 0+-69 -1311 106 0+-70 -1311 107 0+-71 -1311 108 0+-37 -1312 218 0+-38 -1312 219 0+-39 -1312 220 0+-40 -1312 221 0+-41 -1312 222 0+-42 -1312 223 0+-43 -1312 224 0+-44 -1312 225 0+-45 -1312 226 0+-46 -1312 227 0+-47 -1312 228 0+-48 -1312 229 0+-49 -1312 230 0+-50 -1312 231 0+-51 -1312 232 0+-52 -1312 233 0+-53 -1312 234 0+-54 -1312 235 0+-55 -1312 236 0+-56 -1312 237 0+-57 -1312 238 0+-58 -1312 239 0+-59 -1312 240 0+-60 -1312 241 0+-61 -1312 242 0+-62 -1312 243 0+-63 -1312 244 0+-64 -1312 245 0+-65 -1312 246 0+-66 -1312 247 0+-67 -1312 248 0+-68 -1312 249 0+-69 -1312 250 0+-70 -1312 251 0+-71 -1312 252 0+-37 -1313 254 0+-38 -1313 255 0+-39 -1313 256 0+-40 -1313 257 0+-41 -1313 258 0+-42 -1313 259 0+-43 -1313 260 0+-44 -1313 261 0+-45 -1313 262 0+-46 -1313 263 0+-47 -1313 264 0+-48 -1313 265 0+-49 -1313 266 0+-50 -1313 267 0+-51 -1313 268 0+-52 -1313 269 0+-53 -1313 270 0+-54 -1313 271 0+-55 -1313 272 0+-56 -1313 273 0+-57 -1313 274 0+-58 -1313 275 0+-59 -1313 276 0+-60 -1313 277 0+-61 -1313 278 0+-62 -1313 279 0+-63 -1313 280 0+-64 -1313 281 0+-65 -1313 282 0+-66 -1313 283 0+-67 -1313 284 0+-68 -1313 285 0+-69 -1313 286 0+-70 -1313 287 0+-71 -1313 288 0+-37 -1314 290 0+-38 -1314 291 0+-39 -1314 292 0+-40 -1314 293 0+-41 -1314 294 0+-42 -1314 295 0+-43 -1314 296 0+-44 -1314 297 0+-45 -1314 298 0+-46 -1314 299 0+-47 -1314 300 0+-48 -1314 301 0+-49 -1314 302 0+-50 -1314 303 0+-51 -1314 304 0+-52 -1314 305 0+-53 -1314 306 0+-54 -1314 307 0+-55 -1314 308 0+-56 -1314 309 0+-57 -1314 310 0+-58 -1314 311 0+-59 -1314 312 0+-60 -1314 313 0+-61 -1314 314 0+-62 -1314 315 0+-63 -1314 316 0+-64 -1314 317 0+-65 -1314 318 0+-66 -1314 319 0+-67 -1314 320 0+-68 -1314 321 0+-69 -1314 322 0+-70 -1314 323 0+-71 -1314 324 0+-1309 -1311 0+-1309 -2236 0+-1311 -2236 0+-1312 -1313 0+-1312 -1314 0+-1312 2236 0+-1313 -1314 0+-1313 2236 0+-1314 2236 0+1309 1311 1312 1313 1314 0+-73 -1318 38 0+-74 -1318 39 0+-75 -1318 40 0+-76 -1318 41 0+-77 -1318 42 0+-78 -1318 43 0+-79 -1318 44 0+-80 -1318 45 0+-81 -1318 46 0+-82 -1318 47 0+-83 -1318 48 0+-84 -1318 49 0+-85 -1318 50 0+-86 -1318 51 0+-87 -1318 52 0+-88 -1318 53 0+-89 -1318 54 0+-90 -1318 55 0+-91 -1318 56 0+-92 -1318 57 0+-93 -1318 58 0+-94 -1318 59 0+-95 -1318 60 0+-96 -1318 61 0+-97 -1318 62 0+-98 -1318 63 0+-99 -1318 64 0+-100 -1318 65 0+-101 -1318 66 0+-102 -1318 67 0+-103 -1318 68 0+-104 -1318 69 0+-105 -1318 70 0+-106 -1318 71 0+-107 -1318 72 0+-73 -1320 110 0+-74 -1320 111 0+-75 -1320 112 0+-76 -1320 113 0+-77 -1320 114 0+-78 -1320 115 0+-79 -1320 116 0+-80 -1320 117 0+-81 -1320 118 0+-82 -1320 119 0+-83 -1320 120 0+-84 -1320 121 0+-85 -1320 122 0+-86 -1320 123 0+-87 -1320 124 0+-88 -1320 125 0+-89 -1320 126 0+-90 -1320 127 0+-91 -1320 128 0+-92 -1320 129 0+-93 -1320 130 0+-94 -1320 131 0+-95 -1320 132 0+-96 -1320 133 0+-97 -1320 134 0+-98 -1320 135 0+-99 -1320 136 0+-100 -1320 137 0+-101 -1320 138 0+-102 -1320 139 0+-103 -1320 140 0+-104 -1320 141 0+-105 -1320 142 0+-106 -1320 143 0+-107 -1320 144 0+-73 -1321 254 0+-74 -1321 255 0+-75 -1321 256 0+-76 -1321 257 0+-77 -1321 258 0+-78 -1321 259 0+-79 -1321 260 0+-80 -1321 261 0+-81 -1321 262 0+-82 -1321 263 0+-83 -1321 264 0+-84 -1321 265 0+-85 -1321 266 0+-86 -1321 267 0+-87 -1321 268 0+-88 -1321 269 0+-89 -1321 270 0+-90 -1321 271 0+-91 -1321 272 0+-92 -1321 273 0+-93 -1321 274 0+-94 -1321 275 0+-95 -1321 276 0+-96 -1321 277 0+-97 -1321 278 0+-98 -1321 279 0+-99 -1321 280 0+-100 -1321 281 0+-101 -1321 282 0+-102 -1321 283 0+-103 -1321 284 0+-104 -1321 285 0+-105 -1321 286 0+-106 -1321 287 0+-107 -1321 288 0+-73 -1322 290 0+-74 -1322 291 0+-75 -1322 292 0+-76 -1322 293 0+-77 -1322 294 0+-78 -1322 295 0+-79 -1322 296 0+-80 -1322 297 0+-81 -1322 298 0+-82 -1322 299 0+-83 -1322 300 0+-84 -1322 301 0+-85 -1322 302 0+-86 -1322 303 0+-87 -1322 304 0+-88 -1322 305 0+-89 -1322 306 0+-90 -1322 307 0+-91 -1322 308 0+-92 -1322 309 0+-93 -1322 310 0+-94 -1322 311 0+-95 -1322 312 0+-96 -1322 313 0+-97 -1322 314 0+-98 -1322 315 0+-99 -1322 316 0+-100 -1322 317 0+-101 -1322 318 0+-102 -1322 319 0+-103 -1322 320 0+-104 -1322 321 0+-105 -1322 322 0+-106 -1322 323 0+-107 -1322 324 0+-73 -1323 326 0+-74 -1323 327 0+-75 -1323 328 0+-76 -1323 329 0+-77 -1323 330 0+-78 -1323 331 0+-79 -1323 332 0+-80 -1323 333 0+-81 -1323 334 0+-82 -1323 335 0+-83 -1323 336 0+-84 -1323 337 0+-85 -1323 338 0+-86 -1323 339 0+-87 -1323 340 0+-88 -1323 341 0+-89 -1323 342 0+-90 -1323 343 0+-91 -1323 344 0+-92 -1323 345 0+-93 -1323 346 0+-94 -1323 347 0+-95 -1323 348 0+-96 -1323 349 0+-97 -1323 350 0+-98 -1323 351 0+-99 -1323 352 0+-100 -1323 353 0+-101 -1323 354 0+-102 -1323 355 0+-103 -1323 356 0+-104 -1323 357 0+-105 -1323 358 0+-106 -1323 359 0+-107 -1323 360 0+-1318 -1320 0+-1318 -2242 0+-1320 -2242 0+-1321 -1322 0+-1321 -1323 0+-1321 2242 0+-1322 -1323 0+-1322 2242 0+-1323 2242 0+1318 1320 1321 1322 1323 0+-109 -1327 74 0+-110 -1327 75 0+-111 -1327 76 0+-112 -1327 77 0+-113 -1327 78 0+-114 -1327 79 0+-115 -1327 80 0+-116 -1327 81 0+-117 -1327 82 0+-118 -1327 83 0+-119 -1327 84 0+-120 -1327 85 0+-121 -1327 86 0+-122 -1327 87 0+-123 -1327 88 0+-124 -1327 89 0+-125 -1327 90 0+-126 -1327 91 0+-127 -1327 92 0+-128 -1327 93 0+-129 -1327 94 0+-130 -1327 95 0+-131 -1327 96 0+-132 -1327 97 0+-133 -1327 98 0+-134 -1327 99 0+-135 -1327 100 0+-136 -1327 101 0+-137 -1327 102 0+-138 -1327 103 0+-139 -1327 104 0+-140 -1327 105 0+-141 -1327 106 0+-142 -1327 107 0+-143 -1327 108 0+-109 -1329 146 0+-110 -1329 147 0+-111 -1329 148 0+-112 -1329 149 0+-113 -1329 150 0+-114 -1329 151 0+-115 -1329 152 0+-116 -1329 153 0+-117 -1329 154 0+-118 -1329 155 0+-119 -1329 156 0+-120 -1329 157 0+-121 -1329 158 0+-122 -1329 159 0+-123 -1329 160 0+-124 -1329 161 0+-125 -1329 162 0+-126 -1329 163 0+-127 -1329 164 0+-128 -1329 165 0+-129 -1329 166 0+-130 -1329 167 0+-131 -1329 168 0+-132 -1329 169 0+-133 -1329 170 0+-134 -1329 171 0+-135 -1329 172 0+-136 -1329 173 0+-137 -1329 174 0+-138 -1329 175 0+-139 -1329 176 0+-140 -1329 177 0+-141 -1329 178 0+-142 -1329 179 0+-143 -1329 180 0+-109 -1330 290 0+-110 -1330 291 0+-111 -1330 292 0+-112 -1330 293 0+-113 -1330 294 0+-114 -1330 295 0+-115 -1330 296 0+-116 -1330 297 0+-117 -1330 298 0+-118 -1330 299 0+-119 -1330 300 0+-120 -1330 301 0+-121 -1330 302 0+-122 -1330 303 0+-123 -1330 304 0+-124 -1330 305 0+-125 -1330 306 0+-126 -1330 307 0+-127 -1330 308 0+-128 -1330 309 0+-129 -1330 310 0+-130 -1330 311 0+-131 -1330 312 0+-132 -1330 313 0+-133 -1330 314 0+-134 -1330 315 0+-135 -1330 316 0+-136 -1330 317 0+-137 -1330 318 0+-138 -1330 319 0+-139 -1330 320 0+-140 -1330 321 0+-141 -1330 322 0+-142 -1330 323 0+-143 -1330 324 0+-109 -1331 326 0+-110 -1331 327 0+-111 -1331 328 0+-112 -1331 329 0+-113 -1331 330 0+-114 -1331 331 0+-115 -1331 332 0+-116 -1331 333 0+-117 -1331 334 0+-118 -1331 335 0+-119 -1331 336 0+-120 -1331 337 0+-121 -1331 338 0+-122 -1331 339 0+-123 -1331 340 0+-124 -1331 341 0+-125 -1331 342 0+-126 -1331 343 0+-127 -1331 344 0+-128 -1331 345 0+-129 -1331 346 0+-130 -1331 347 0+-131 -1331 348 0+-132 -1331 349 0+-133 -1331 350 0+-134 -1331 351 0+-135 -1331 352 0+-136 -1331 353 0+-137 -1331 354 0+-138 -1331 355 0+-139 -1331 356 0+-140 -1331 357 0+-141 -1331 358 0+-142 -1331 359 0+-143 -1331 360 0+-109 -1332 362 0+-110 -1332 363 0+-111 -1332 364 0+-112 -1332 365 0+-113 -1332 366 0+-114 -1332 367 0+-115 -1332 368 0+-116 -1332 369 0+-117 -1332 370 0+-118 -1332 371 0+-119 -1332 372 0+-120 -1332 373 0+-121 -1332 374 0+-122 -1332 375 0+-123 -1332 376 0+-124 -1332 377 0+-125 -1332 378 0+-126 -1332 379 0+-127 -1332 380 0+-128 -1332 381 0+-129 -1332 382 0+-130 -1332 383 0+-131 -1332 384 0+-132 -1332 385 0+-133 -1332 386 0+-134 -1332 387 0+-135 -1332 388 0+-136 -1332 389 0+-137 -1332 390 0+-138 -1332 391 0+-139 -1332 392 0+-140 -1332 393 0+-141 -1332 394 0+-142 -1332 395 0+-143 -1332 396 0+-1327 -1329 0+-1327 -2248 0+-1329 -2248 0+-1330 -1331 0+-1330 -1332 0+-1330 2248 0+-1331 -1332 0+-1331 2248 0+-1332 2248 0+1327 1329 1330 1331 1332 0+-145 -1336 110 0+-146 -1336 111 0+-147 -1336 112 0+-148 -1336 113 0+-149 -1336 114 0+-150 -1336 115 0+-151 -1336 116 0+-152 -1336 117 0+-153 -1336 118 0+-154 -1336 119 0+-155 -1336 120 0+-156 -1336 121 0+-157 -1336 122 0+-158 -1336 123 0+-159 -1336 124 0+-160 -1336 125 0+-161 -1336 126 0+-162 -1336 127 0+-163 -1336 128 0+-164 -1336 129 0+-165 -1336 130 0+-166 -1336 131 0+-167 -1336 132 0+-168 -1336 133 0+-169 -1336 134 0+-170 -1336 135 0+-171 -1336 136 0+-172 -1336 137 0+-173 -1336 138 0+-174 -1336 139 0+-175 -1336 140 0+-176 -1336 141 0+-177 -1336 142 0+-178 -1336 143 0+-179 -1336 144 0+-145 -1338 182 0+-146 -1338 183 0+-147 -1338 184 0+-148 -1338 185 0+-149 -1338 186 0+-150 -1338 187 0+-151 -1338 188 0+-152 -1338 189 0+-153 -1338 190 0+-154 -1338 191 0+-155 -1338 192 0+-156 -1338 193 0+-157 -1338 194 0+-158 -1338 195 0+-159 -1338 196 0+-160 -1338 197 0+-161 -1338 198 0+-162 -1338 199 0+-163 -1338 200 0+-164 -1338 201 0+-165 -1338 202 0+-166 -1338 203 0+-167 -1338 204 0+-168 -1338 205 0+-169 -1338 206 0+-170 -1338 207 0+-171 -1338 208 0+-172 -1338 209 0+-173 -1338 210 0+-174 -1338 211 0+-175 -1338 212 0+-176 -1338 213 0+-177 -1338 214 0+-178 -1338 215 0+-179 -1338 216 0+-145 -1339 326 0+-146 -1339 327 0+-147 -1339 328 0+-148 -1339 329 0+-149 -1339 330 0+-150 -1339 331 0+-151 -1339 332 0+-152 -1339 333 0+-153 -1339 334 0+-154 -1339 335 0+-155 -1339 336 0+-156 -1339 337 0+-157 -1339 338 0+-158 -1339 339 0+-159 -1339 340 0+-160 -1339 341 0+-161 -1339 342 0+-162 -1339 343 0+-163 -1339 344 0+-164 -1339 345 0+-165 -1339 346 0+-166 -1339 347 0+-167 -1339 348 0+-168 -1339 349 0+-169 -1339 350 0+-170 -1339 351 0+-171 -1339 352 0+-172 -1339 353 0+-173 -1339 354 0+-174 -1339 355 0+-175 -1339 356 0+-176 -1339 357 0+-177 -1339 358 0+-178 -1339 359 0+-179 -1339 360 0+-145 -1340 362 0+-146 -1340 363 0+-147 -1340 364 0+-148 -1340 365 0+-149 -1340 366 0+-150 -1340 367 0+-151 -1340 368 0+-152 -1340 369 0+-153 -1340 370 0+-154 -1340 371 0+-155 -1340 372 0+-156 -1340 373 0+-157 -1340 374 0+-158 -1340 375 0+-159 -1340 376 0+-160 -1340 377 0+-161 -1340 378 0+-162 -1340 379 0+-163 -1340 380 0+-164 -1340 381 0+-165 -1340 382 0+-166 -1340 383 0+-167 -1340 384 0+-168 -1340 385 0+-169 -1340 386 0+-170 -1340 387 0+-171 -1340 388 0+-172 -1340 389 0+-173 -1340 390 0+-174 -1340 391 0+-175 -1340 392 0+-176 -1340 393 0+-177 -1340 394 0+-178 -1340 395 0+-179 -1340 396 0+-145 -1341 398 0+-146 -1341 399 0+-147 -1341 400 0+-148 -1341 401 0+-149 -1341 402 0+-150 -1341 403 0+-151 -1341 404 0+-152 -1341 405 0+-153 -1341 406 0+-154 -1341 407 0+-155 -1341 408 0+-156 -1341 409 0+-157 -1341 410 0+-158 -1341 411 0+-159 -1341 412 0+-160 -1341 413 0+-161 -1341 414 0+-162 -1341 415 0+-163 -1341 416 0+-164 -1341 417 0+-165 -1341 418 0+-166 -1341 419 0+-167 -1341 420 0+-168 -1341 421 0+-169 -1341 422 0+-170 -1341 423 0+-171 -1341 424 0+-172 -1341 425 0+-173 -1341 426 0+-174 -1341 427 0+-175 -1341 428 0+-176 -1341 429 0+-177 -1341 430 0+-178 -1341 431 0+-179 -1341 432 0+-1336 -1338 0+-1336 -2254 0+-1338 -2254 0+-1339 -1340 0+-1339 -1341 0+-1339 2254 0+-1340 -1341 0+-1340 2254 0+-1341 2254 0+1336 1338 1339 1340 1341 0+-181 -1345 146 0+-182 -1345 147 0+-183 -1345 148 0+-184 -1345 149 0+-185 -1345 150 0+-186 -1345 151 0+-187 -1345 152 0+-188 -1345 153 0+-189 -1345 154 0+-190 -1345 155 0+-191 -1345 156 0+-192 -1345 157 0+-193 -1345 158 0+-194 -1345 159 0+-195 -1345 160 0+-196 -1345 161 0+-197 -1345 162 0+-198 -1345 163 0+-199 -1345 164 0+-200 -1345 165 0+-201 -1345 166 0+-202 -1345 167 0+-203 -1345 168 0+-204 -1345 169 0+-205 -1345 170 0+-206 -1345 171 0+-207 -1345 172 0+-208 -1345 173 0+-209 -1345 174 0+-210 -1345 175 0+-211 -1345 176 0+-212 -1345 177 0+-213 -1345 178 0+-214 -1345 179 0+-215 -1345 180 0+-181 -1348 362 0+-182 -1348 363 0+-183 -1348 364 0+-184 -1348 365 0+-185 -1348 366 0+-186 -1348 367 0+-187 -1348 368 0+-188 -1348 369 0+-189 -1348 370 0+-190 -1348 371 0+-191 -1348 372 0+-192 -1348 373 0+-193 -1348 374 0+-194 -1348 375 0+-195 -1348 376 0+-196 -1348 377 0+-197 -1348 378 0+-198 -1348 379 0+-199 -1348 380 0+-200 -1348 381 0+-201 -1348 382 0+-202 -1348 383 0+-203 -1348 384 0+-204 -1348 385 0+-205 -1348 386 0+-206 -1348 387 0+-207 -1348 388 0+-208 -1348 389 0+-209 -1348 390 0+-210 -1348 391 0+-211 -1348 392 0+-212 -1348 393 0+-213 -1348 394 0+-214 -1348 395 0+-215 -1348 396 0+-181 -1349 398 0+-182 -1349 399 0+-183 -1349 400 0+-184 -1349 401 0+-185 -1349 402 0+-186 -1349 403 0+-187 -1349 404 0+-188 -1349 405 0+-189 -1349 406 0+-190 -1349 407 0+-191 -1349 408 0+-192 -1349 409 0+-193 -1349 410 0+-194 -1349 411 0+-195 -1349 412 0+-196 -1349 413 0+-197 -1349 414 0+-198 -1349 415 0+-199 -1349 416 0+-200 -1349 417 0+-201 -1349 418 0+-202 -1349 419 0+-203 -1349 420 0+-204 -1349 421 0+-205 -1349 422 0+-206 -1349 423 0+-207 -1349 424 0+-208 -1349 425 0+-209 -1349 426 0+-210 -1349 427 0+-211 -1349 428 0+-212 -1349 429 0+-213 -1349 430 0+-214 -1349 431 0+-215 -1349 432 0+-1345 -1348 0+-1345 -1349 0+-1348 -1349 0+1345 1348 1349 0+-217 -1352 2 0+-218 -1352 3 0+-219 -1352 4 0+-220 -1352 5 0+-221 -1352 6 0+-222 -1352 7 0+-223 -1352 8 0+-224 -1352 9 0+-225 -1352 10 0+-226 -1352 11 0+-227 -1352 12 0+-228 -1352 13 0+-229 -1352 14 0+-230 -1352 15 0+-231 -1352 16 0+-232 -1352 17 0+-233 -1352 18 0+-234 -1352 19 0+-235 -1352 20 0+-236 -1352 21 0+-237 -1352 22 0+-238 -1352 23 0+-239 -1352 24 0+-240 -1352 25 0+-241 -1352 26 0+-242 -1352 27 0+-243 -1352 28 0+-244 -1352 29 0+-245 -1352 30 0+-246 -1352 31 0+-247 -1352 32 0+-248 -1352 33 0+-249 -1352 34 0+-250 -1352 35 0+-251 -1352 36 0+-217 -1353 38 0+-218 -1353 39 0+-219 -1353 40 0+-220 -1353 41 0+-221 -1353 42 0+-222 -1353 43 0+-223 -1353 44 0+-224 -1353 45 0+-225 -1353 46 0+-226 -1353 47 0+-227 -1353 48 0+-228 -1353 49 0+-229 -1353 50 0+-230 -1353 51 0+-231 -1353 52 0+-232 -1353 53 0+-233 -1353 54 0+-234 -1353 55 0+-235 -1353 56 0+-236 -1353 57 0+-237 -1353 58 0+-238 -1353 59 0+-239 -1353 60 0+-240 -1353 61 0+-241 -1353 62 0+-242 -1353 63 0+-243 -1353 64 0+-244 -1353 65 0+-245 -1353 66 0+-246 -1353 67 0+-247 -1353 68 0+-248 -1353 69 0+-249 -1353 70 0+-250 -1353 71 0+-251 -1353 72 0+-217 -1356 254 0+-218 -1356 255 0+-219 -1356 256 0+-220 -1356 257 0+-221 -1356 258 0+-222 -1356 259 0+-223 -1356 260 0+-224 -1356 261 0+-225 -1356 262 0+-226 -1356 263 0+-227 -1356 264 0+-228 -1356 265 0+-229 -1356 266 0+-230 -1356 267 0+-231 -1356 268 0+-232 -1356 269 0+-233 -1356 270 0+-234 -1356 271 0+-235 -1356 272 0+-236 -1356 273 0+-237 -1356 274 0+-238 -1356 275 0+-239 -1356 276 0+-240 -1356 277 0+-241 -1356 278 0+-242 -1356 279 0+-243 -1356 280 0+-244 -1356 281 0+-245 -1356 282 0+-246 -1356 283 0+-247 -1356 284 0+-248 -1356 285 0+-249 -1356 286 0+-250 -1356 287 0+-251 -1356 288 0+-217 -1358 434 0+-218 -1358 435 0+-219 -1358 436 0+-220 -1358 437 0+-221 -1358 438 0+-222 -1358 439 0+-223 -1358 440 0+-224 -1358 441 0+-225 -1358 442 0+-226 -1358 443 0+-227 -1358 444 0+-228 -1358 445 0+-229 -1358 446 0+-230 -1358 447 0+-231 -1358 448 0+-232 -1358 449 0+-233 -1358 450 0+-234 -1358 451 0+-235 -1358 452 0+-236 -1358 453 0+-237 -1358 454 0+-238 -1358 455 0+-239 -1358 456 0+-240 -1358 457 0+-241 -1358 458 0+-242 -1358 459 0+-243 -1358 460 0+-244 -1358 461 0+-245 -1358 462 0+-246 -1358 463 0+-247 -1358 464 0+-248 -1358 465 0+-249 -1358 466 0+-250 -1358 467 0+-251 -1358 468 0+-217 -1359 470 0+-218 -1359 471 0+-219 -1359 472 0+-220 -1359 473 0+-221 -1359 474 0+-222 -1359 475 0+-223 -1359 476 0+-224 -1359 477 0+-225 -1359 478 0+-226 -1359 479 0+-227 -1359 480 0+-228 -1359 481 0+-229 -1359 482 0+-230 -1359 483 0+-231 -1359 484 0+-232 -1359 485 0+-233 -1359 486 0+-234 -1359 487 0+-235 -1359 488 0+-236 -1359 489 0+-237 -1359 490 0+-238 -1359 491 0+-239 -1359 492 0+-240 -1359 493 0+-241 -1359 494 0+-242 -1359 495 0+-243 -1359 496 0+-244 -1359 497 0+-245 -1359 498 0+-246 -1359 499 0+-247 -1359 500 0+-248 -1359 501 0+-249 -1359 502 0+-250 -1359 503 0+-251 -1359 504 0+-1352 -1353 0+-1352 -2263 0+-1353 -2263 0+-1356 -1358 0+-1356 -1359 0+-1356 2263 0+-1358 -1359 0+-1358 2263 0+-1359 2263 0+1352 1353 1356 1358 1359 0+-253 -1360 2 0+-254 -1360 3 0+-255 -1360 4 0+-256 -1360 5 0+-257 -1360 6 0+-258 -1360 7 0+-259 -1360 8 0+-260 -1360 9 0+-261 -1360 10 0+-262 -1360 11 0+-263 -1360 12 0+-264 -1360 13 0+-265 -1360 14 0+-266 -1360 15 0+-267 -1360 16 0+-268 -1360 17 0+-269 -1360 18 0+-270 -1360 19 0+-271 -1360 20 0+-272 -1360 21 0+-273 -1360 22 0+-274 -1360 23 0+-275 -1360 24 0+-276 -1360 25 0+-277 -1360 26 0+-278 -1360 27 0+-279 -1360 28 0+-280 -1360 29 0+-281 -1360 30 0+-282 -1360 31 0+-283 -1360 32 0+-284 -1360 33 0+-285 -1360 34 0+-286 -1360 35 0+-287 -1360 36 0+-253 -1361 38 0+-254 -1361 39 0+-255 -1361 40 0+-256 -1361 41 0+-257 -1361 42 0+-258 -1361 43 0+-259 -1361 44 0+-260 -1361 45 0+-261 -1361 46 0+-262 -1361 47 0+-263 -1361 48 0+-264 -1361 49 0+-265 -1361 50 0+-266 -1361 51 0+-267 -1361 52 0+-268 -1361 53 0+-269 -1361 54 0+-270 -1361 55 0+-271 -1361 56 0+-272 -1361 57 0+-273 -1361 58 0+-274 -1361 59 0+-275 -1361 60 0+-276 -1361 61 0+-277 -1361 62 0+-278 -1361 63 0+-279 -1361 64 0+-280 -1361 65 0+-281 -1361 66 0+-282 -1361 67 0+-283 -1361 68 0+-284 -1361 69 0+-285 -1361 70 0+-286 -1361 71 0+-287 -1361 72 0+-253 -1362 74 0+-254 -1362 75 0+-255 -1362 76 0+-256 -1362 77 0+-257 -1362 78 0+-258 -1362 79 0+-259 -1362 80 0+-260 -1362 81 0+-261 -1362 82 0+-262 -1362 83 0+-263 -1362 84 0+-264 -1362 85 0+-265 -1362 86 0+-266 -1362 87 0+-267 -1362 88 0+-268 -1362 89 0+-269 -1362 90 0+-270 -1362 91 0+-271 -1362 92 0+-272 -1362 93 0+-273 -1362 94 0+-274 -1362 95 0+-275 -1362 96 0+-276 -1362 97 0+-277 -1362 98 0+-278 -1362 99 0+-279 -1362 100 0+-280 -1362 101 0+-281 -1362 102 0+-282 -1362 103 0+-283 -1362 104 0+-284 -1362 105 0+-285 -1362 106 0+-286 -1362 107 0+-287 -1362 108 0+-253 -1363 218 0+-254 -1363 219 0+-255 -1363 220 0+-256 -1363 221 0+-257 -1363 222 0+-258 -1363 223 0+-259 -1363 224 0+-260 -1363 225 0+-261 -1363 226 0+-262 -1363 227 0+-263 -1363 228 0+-264 -1363 229 0+-265 -1363 230 0+-266 -1363 231 0+-267 -1363 232 0+-268 -1363 233 0+-269 -1363 234 0+-270 -1363 235 0+-271 -1363 236 0+-272 -1363 237 0+-273 -1363 238 0+-274 -1363 239 0+-275 -1363 240 0+-276 -1363 241 0+-277 -1363 242 0+-278 -1363 243 0+-279 -1363 244 0+-280 -1363 245 0+-281 -1363 246 0+-282 -1363 247 0+-283 -1363 248 0+-284 -1363 249 0+-285 -1363 250 0+-286 -1363 251 0+-287 -1363 252 0+-253 -1365 290 0+-254 -1365 291 0+-255 -1365 292 0+-256 -1365 293 0+-257 -1365 294 0+-258 -1365 295 0+-259 -1365 296 0+-260 -1365 297 0+-261 -1365 298 0+-262 -1365 299 0+-263 -1365 300 0+-264 -1365 301 0+-265 -1365 302 0+-266 -1365 303 0+-267 -1365 304 0+-268 -1365 305 0+-269 -1365 306 0+-270 -1365 307 0+-271 -1365 308 0+-272 -1365 309 0+-273 -1365 310 0+-274 -1365 311 0+-275 -1365 312 0+-276 -1365 313 0+-277 -1365 314 0+-278 -1365 315 0+-279 -1365 316 0+-280 -1365 317 0+-281 -1365 318 0+-282 -1365 319 0+-283 -1365 320 0+-284 -1365 321 0+-285 -1365 322 0+-286 -1365 323 0+-287 -1365 324 0+-253 -1366 434 0+-254 -1366 435 0+-255 -1366 436 0+-256 -1366 437 0+-257 -1366 438 0+-258 -1366 439 0+-259 -1366 440 0+-260 -1366 441 0+-261 -1366 442 0+-262 -1366 443 0+-263 -1366 444 0+-264 -1366 445 0+-265 -1366 446 0+-266 -1366 447 0+-267 -1366 448 0+-268 -1366 449 0+-269 -1366 450 0+-270 -1366 451 0+-271 -1366 452 0+-272 -1366 453 0+-273 -1366 454 0+-274 -1366 455 0+-275 -1366 456 0+-276 -1366 457 0+-277 -1366 458 0+-278 -1366 459 0+-279 -1366 460 0+-280 -1366 461 0+-281 -1366 462 0+-282 -1366 463 0+-283 -1366 464 0+-284 -1366 465 0+-285 -1366 466 0+-286 -1366 467 0+-287 -1366 468 0+-253 -1367 470 0+-254 -1367 471 0+-255 -1367 472 0+-256 -1367 473 0+-257 -1367 474 0+-258 -1367 475 0+-259 -1367 476 0+-260 -1367 477 0+-261 -1367 478 0+-262 -1367 479 0+-263 -1367 480 0+-264 -1367 481 0+-265 -1367 482 0+-266 -1367 483 0+-267 -1367 484 0+-268 -1367 485 0+-269 -1367 486 0+-270 -1367 487 0+-271 -1367 488 0+-272 -1367 489 0+-273 -1367 490 0+-274 -1367 491 0+-275 -1367 492 0+-276 -1367 493 0+-277 -1367 494 0+-278 -1367 495 0+-279 -1367 496 0+-280 -1367 497 0+-281 -1367 498 0+-282 -1367 499 0+-283 -1367 500 0+-284 -1367 501 0+-285 -1367 502 0+-286 -1367 503 0+-287 -1367 504 0+-253 -1368 506 0+-254 -1368 507 0+-255 -1368 508 0+-256 -1368 509 0+-257 -1368 510 0+-258 -1368 511 0+-259 -1368 512 0+-260 -1368 513 0+-261 -1368 514 0+-262 -1368 515 0+-263 -1368 516 0+-264 -1368 517 0+-265 -1368 518 0+-266 -1368 519 0+-267 -1368 520 0+-268 -1368 521 0+-269 -1368 522 0+-270 -1368 523 0+-271 -1368 524 0+-272 -1368 525 0+-273 -1368 526 0+-274 -1368 527 0+-275 -1368 528 0+-276 -1368 529 0+-277 -1368 530 0+-278 -1368 531 0+-279 -1368 532 0+-280 -1368 533 0+-281 -1368 534 0+-282 -1368 535 0+-283 -1368 536 0+-284 -1368 537 0+-285 -1368 538 0+-286 -1368 539 0+-287 -1368 540 0+-1360 -1361 0+-1360 -2273 0+-1361 -2273 0+-1362 -1363 0+-1362 -2272 0+-1362 2273 0+-1363 -2272 0+-1363 2273 0+-2272 2273 0+-1365 -1366 0+-1365 -2274 0+-1366 -2274 0+-1367 -1368 0+-1367 2272 0+-1367 2274 0+-1368 2272 0+-1368 2274 0+2272 2274 0+1360 1361 1362 1363 1365 1366 1367 1368 0+-289 -1369 38 0+-290 -1369 39 0+-291 -1369 40 0+-292 -1369 41 0+-293 -1369 42 0+-294 -1369 43 0+-295 -1369 44 0+-296 -1369 45 0+-297 -1369 46 0+-298 -1369 47 0+-299 -1369 48 0+-300 -1369 49 0+-301 -1369 50 0+-302 -1369 51 0+-303 -1369 52 0+-304 -1369 53 0+-305 -1369 54 0+-306 -1369 55 0+-307 -1369 56 0+-308 -1369 57 0+-309 -1369 58 0+-310 -1369 59 0+-311 -1369 60 0+-312 -1369 61 0+-313 -1369 62 0+-314 -1369 63 0+-315 -1369 64 0+-316 -1369 65 0+-317 -1369 66 0+-318 -1369 67 0+-319 -1369 68 0+-320 -1369 69 0+-321 -1369 70 0+-322 -1369 71 0+-323 -1369 72 0+-289 -1370 74 0+-290 -1370 75 0+-291 -1370 76 0+-292 -1370 77 0+-293 -1370 78 0+-294 -1370 79 0+-295 -1370 80 0+-296 -1370 81 0+-297 -1370 82 0+-298 -1370 83 0+-299 -1370 84 0+-300 -1370 85 0+-301 -1370 86 0+-302 -1370 87 0+-303 -1370 88 0+-304 -1370 89 0+-305 -1370 90 0+-306 -1370 91 0+-307 -1370 92 0+-308 -1370 93 0+-309 -1370 94 0+-310 -1370 95 0+-311 -1370 96 0+-312 -1370 97 0+-313 -1370 98 0+-314 -1370 99 0+-315 -1370 100 0+-316 -1370 101 0+-317 -1370 102 0+-318 -1370 103 0+-319 -1370 104 0+-320 -1370 105 0+-321 -1370 106 0+-322 -1370 107 0+-323 -1370 108 0+-289 -1371 110 0+-290 -1371 111 0+-291 -1371 112 0+-292 -1371 113 0+-293 -1371 114 0+-294 -1371 115 0+-295 -1371 116 0+-296 -1371 117 0+-297 -1371 118 0+-298 -1371 119 0+-299 -1371 120 0+-300 -1371 121 0+-301 -1371 122 0+-302 -1371 123 0+-303 -1371 124 0+-304 -1371 125 0+-305 -1371 126 0+-306 -1371 127 0+-307 -1371 128 0+-308 -1371 129 0+-309 -1371 130 0+-310 -1371 131 0+-311 -1371 132 0+-312 -1371 133 0+-313 -1371 134 0+-314 -1371 135 0+-315 -1371 136 0+-316 -1371 137 0+-317 -1371 138 0+-318 -1371 139 0+-319 -1371 140 0+-320 -1371 141 0+-321 -1371 142 0+-322 -1371 143 0+-323 -1371 144 0+-289 -1372 254 0+-290 -1372 255 0+-291 -1372 256 0+-292 -1372 257 0+-293 -1372 258 0+-294 -1372 259 0+-295 -1372 260 0+-296 -1372 261 0+-297 -1372 262 0+-298 -1372 263 0+-299 -1372 264 0+-300 -1372 265 0+-301 -1372 266 0+-302 -1372 267 0+-303 -1372 268 0+-304 -1372 269 0+-305 -1372 270 0+-306 -1372 271 0+-307 -1372 272 0+-308 -1372 273 0+-309 -1372 274 0+-310 -1372 275 0+-311 -1372 276 0+-312 -1372 277 0+-313 -1372 278 0+-314 -1372 279 0+-315 -1372 280 0+-316 -1372 281 0+-317 -1372 282 0+-318 -1372 283 0+-319 -1372 284 0+-320 -1372 285 0+-321 -1372 286 0+-322 -1372 287 0+-323 -1372 288 0+-289 -1374 326 0+-290 -1374 327 0+-291 -1374 328 0+-292 -1374 329 0+-293 -1374 330 0+-294 -1374 331 0+-295 -1374 332 0+-296 -1374 333 0+-297 -1374 334 0+-298 -1374 335 0+-299 -1374 336 0+-300 -1374 337 0+-301 -1374 338 0+-302 -1374 339 0+-303 -1374 340 0+-304 -1374 341 0+-305 -1374 342 0+-306 -1374 343 0+-307 -1374 344 0+-308 -1374 345 0+-309 -1374 346 0+-310 -1374 347 0+-311 -1374 348 0+-312 -1374 349 0+-313 -1374 350 0+-314 -1374 351 0+-315 -1374 352 0+-316 -1374 353 0+-317 -1374 354 0+-318 -1374 355 0+-319 -1374 356 0+-320 -1374 357 0+-321 -1374 358 0+-322 -1374 359 0+-323 -1374 360 0+-289 -1375 470 0+-290 -1375 471 0+-291 -1375 472 0+-292 -1375 473 0+-293 -1375 474 0+-294 -1375 475 0+-295 -1375 476 0+-296 -1375 477 0+-297 -1375 478 0+-298 -1375 479 0+-299 -1375 480 0+-300 -1375 481 0+-301 -1375 482 0+-302 -1375 483 0+-303 -1375 484 0+-304 -1375 485 0+-305 -1375 486 0+-306 -1375 487 0+-307 -1375 488 0+-308 -1375 489 0+-309 -1375 490 0+-310 -1375 491 0+-311 -1375 492 0+-312 -1375 493 0+-313 -1375 494 0+-314 -1375 495 0+-315 -1375 496 0+-316 -1375 497 0+-317 -1375 498 0+-318 -1375 499 0+-319 -1375 500 0+-320 -1375 501 0+-321 -1375 502 0+-322 -1375 503 0+-323 -1375 504 0+-289 -1376 506 0+-290 -1376 507 0+-291 -1376 508 0+-292 -1376 509 0+-293 -1376 510 0+-294 -1376 511 0+-295 -1376 512 0+-296 -1376 513 0+-297 -1376 514 0+-298 -1376 515 0+-299 -1376 516 0+-300 -1376 517 0+-301 -1376 518 0+-302 -1376 519 0+-303 -1376 520 0+-304 -1376 521 0+-305 -1376 522 0+-306 -1376 523 0+-307 -1376 524 0+-308 -1376 525 0+-309 -1376 526 0+-310 -1376 527 0+-311 -1376 528 0+-312 -1376 529 0+-313 -1376 530 0+-314 -1376 531 0+-315 -1376 532 0+-316 -1376 533 0+-317 -1376 534 0+-318 -1376 535 0+-319 -1376 536 0+-320 -1376 537 0+-321 -1376 538 0+-322 -1376 539 0+-323 -1376 540 0+-289 -1377 542 0+-290 -1377 543 0+-291 -1377 544 0+-292 -1377 545 0+-293 -1377 546 0+-294 -1377 547 0+-295 -1377 548 0+-296 -1377 549 0+-297 -1377 550 0+-298 -1377 551 0+-299 -1377 552 0+-300 -1377 553 0+-301 -1377 554 0+-302 -1377 555 0+-303 -1377 556 0+-304 -1377 557 0+-305 -1377 558 0+-306 -1377 559 0+-307 -1377 560 0+-308 -1377 561 0+-309 -1377 562 0+-310 -1377 563 0+-311 -1377 564 0+-312 -1377 565 0+-313 -1377 566 0+-314 -1377 567 0+-315 -1377 568 0+-316 -1377 569 0+-317 -1377 570 0+-318 -1377 571 0+-319 -1377 572 0+-320 -1377 573 0+-321 -1377 574 0+-322 -1377 575 0+-323 -1377 576 0+-1369 -1370 0+-1369 -2284 0+-1370 -2284 0+-1371 -1372 0+-1371 -2283 0+-1371 2284 0+-1372 -2283 0+-1372 2284 0+-2283 2284 0+-1374 -1375 0+-1374 -2285 0+-1375 -2285 0+-1376 -1377 0+-1376 2283 0+-1376 2285 0+-1377 2283 0+-1377 2285 0+2283 2285 0+1369 1370 1371 1372 1374 1375 1376 1377 0+-325 -1378 74 0+-326 -1378 75 0+-327 -1378 76 0+-328 -1378 77 0+-329 -1378 78 0+-330 -1378 79 0+-331 -1378 80 0+-332 -1378 81 0+-333 -1378 82 0+-334 -1378 83 0+-335 -1378 84 0+-336 -1378 85 0+-337 -1378 86 0+-338 -1378 87 0+-339 -1378 88 0+-340 -1378 89 0+-341 -1378 90 0+-342 -1378 91 0+-343 -1378 92 0+-344 -1378 93 0+-345 -1378 94 0+-346 -1378 95 0+-347 -1378 96 0+-348 -1378 97 0+-349 -1378 98 0+-350 -1378 99 0+-351 -1378 100 0+-352 -1378 101 0+-353 -1378 102 0+-354 -1378 103 0+-355 -1378 104 0+-356 -1378 105 0+-357 -1378 106 0+-358 -1378 107 0+-359 -1378 108 0+-325 -1379 110 0+-326 -1379 111 0+-327 -1379 112 0+-328 -1379 113 0+-329 -1379 114 0+-330 -1379 115 0+-331 -1379 116 0+-332 -1379 117 0+-333 -1379 118 0+-334 -1379 119 0+-335 -1379 120 0+-336 -1379 121 0+-337 -1379 122 0+-338 -1379 123 0+-339 -1379 124 0+-340 -1379 125 0+-341 -1379 126 0+-342 -1379 127 0+-343 -1379 128 0+-344 -1379 129 0+-345 -1379 130 0+-346 -1379 131 0+-347 -1379 132 0+-348 -1379 133 0+-349 -1379 134 0+-350 -1379 135 0+-351 -1379 136 0+-352 -1379 137 0+-353 -1379 138 0+-354 -1379 139 0+-355 -1379 140 0+-356 -1379 141 0+-357 -1379 142 0+-358 -1379 143 0+-359 -1379 144 0+-325 -1380 146 0+-326 -1380 147 0+-327 -1380 148 0+-328 -1380 149 0+-329 -1380 150 0+-330 -1380 151 0+-331 -1380 152 0+-332 -1380 153 0+-333 -1380 154 0+-334 -1380 155 0+-335 -1380 156 0+-336 -1380 157 0+-337 -1380 158 0+-338 -1380 159 0+-339 -1380 160 0+-340 -1380 161 0+-341 -1380 162 0+-342 -1380 163 0+-343 -1380 164 0+-344 -1380 165 0+-345 -1380 166 0+-346 -1380 167 0+-347 -1380 168 0+-348 -1380 169 0+-349 -1380 170 0+-350 -1380 171 0+-351 -1380 172 0+-352 -1380 173 0+-353 -1380 174 0+-354 -1380 175 0+-355 -1380 176 0+-356 -1380 177 0+-357 -1380 178 0+-358 -1380 179 0+-359 -1380 180 0+-325 -1381 290 0+-326 -1381 291 0+-327 -1381 292 0+-328 -1381 293 0+-329 -1381 294 0+-330 -1381 295 0+-331 -1381 296 0+-332 -1381 297 0+-333 -1381 298 0+-334 -1381 299 0+-335 -1381 300 0+-336 -1381 301 0+-337 -1381 302 0+-338 -1381 303 0+-339 -1381 304 0+-340 -1381 305 0+-341 -1381 306 0+-342 -1381 307 0+-343 -1381 308 0+-344 -1381 309 0+-345 -1381 310 0+-346 -1381 311 0+-347 -1381 312 0+-348 -1381 313 0+-349 -1381 314 0+-350 -1381 315 0+-351 -1381 316 0+-352 -1381 317 0+-353 -1381 318 0+-354 -1381 319 0+-355 -1381 320 0+-356 -1381 321 0+-357 -1381 322 0+-358 -1381 323 0+-359 -1381 324 0+-325 -1383 362 0+-326 -1383 363 0+-327 -1383 364 0+-328 -1383 365 0+-329 -1383 366 0+-330 -1383 367 0+-331 -1383 368 0+-332 -1383 369 0+-333 -1383 370 0+-334 -1383 371 0+-335 -1383 372 0+-336 -1383 373 0+-337 -1383 374 0+-338 -1383 375 0+-339 -1383 376 0+-340 -1383 377 0+-341 -1383 378 0+-342 -1383 379 0+-343 -1383 380 0+-344 -1383 381 0+-345 -1383 382 0+-346 -1383 383 0+-347 -1383 384 0+-348 -1383 385 0+-349 -1383 386 0+-350 -1383 387 0+-351 -1383 388 0+-352 -1383 389 0+-353 -1383 390 0+-354 -1383 391 0+-355 -1383 392 0+-356 -1383 393 0+-357 -1383 394 0+-358 -1383 395 0+-359 -1383 396 0+-325 -1384 506 0+-326 -1384 507 0+-327 -1384 508 0+-328 -1384 509 0+-329 -1384 510 0+-330 -1384 511 0+-331 -1384 512 0+-332 -1384 513 0+-333 -1384 514 0+-334 -1384 515 0+-335 -1384 516 0+-336 -1384 517 0+-337 -1384 518 0+-338 -1384 519 0+-339 -1384 520 0+-340 -1384 521 0+-341 -1384 522 0+-342 -1384 523 0+-343 -1384 524 0+-344 -1384 525 0+-345 -1384 526 0+-346 -1384 527 0+-347 -1384 528 0+-348 -1384 529 0+-349 -1384 530 0+-350 -1384 531 0+-351 -1384 532 0+-352 -1384 533 0+-353 -1384 534 0+-354 -1384 535 0+-355 -1384 536 0+-356 -1384 537 0+-357 -1384 538 0+-358 -1384 539 0+-359 -1384 540 0+-325 -1385 542 0+-326 -1385 543 0+-327 -1385 544 0+-328 -1385 545 0+-329 -1385 546 0+-330 -1385 547 0+-331 -1385 548 0+-332 -1385 549 0+-333 -1385 550 0+-334 -1385 551 0+-335 -1385 552 0+-336 -1385 553 0+-337 -1385 554 0+-338 -1385 555 0+-339 -1385 556 0+-340 -1385 557 0+-341 -1385 558 0+-342 -1385 559 0+-343 -1385 560 0+-344 -1385 561 0+-345 -1385 562 0+-346 -1385 563 0+-347 -1385 564 0+-348 -1385 565 0+-349 -1385 566 0+-350 -1385 567 0+-351 -1385 568 0+-352 -1385 569 0+-353 -1385 570 0+-354 -1385 571 0+-355 -1385 572 0+-356 -1385 573 0+-357 -1385 574 0+-358 -1385 575 0+-359 -1385 576 0+-325 -1386 578 0+-326 -1386 579 0+-327 -1386 580 0+-328 -1386 581 0+-329 -1386 582 0+-330 -1386 583 0+-331 -1386 584 0+-332 -1386 585 0+-333 -1386 586 0+-334 -1386 587 0+-335 -1386 588 0+-336 -1386 589 0+-337 -1386 590 0+-338 -1386 591 0+-339 -1386 592 0+-340 -1386 593 0+-341 -1386 594 0+-342 -1386 595 0+-343 -1386 596 0+-344 -1386 597 0+-345 -1386 598 0+-346 -1386 599 0+-347 -1386 600 0+-348 -1386 601 0+-349 -1386 602 0+-350 -1386 603 0+-351 -1386 604 0+-352 -1386 605 0+-353 -1386 606 0+-354 -1386 607 0+-355 -1386 608 0+-356 -1386 609 0+-357 -1386 610 0+-358 -1386 611 0+-359 -1386 612 0+-1378 -1379 0+-1378 -2295 0+-1379 -2295 0+-1380 -1381 0+-1380 -2294 0+-1380 2295 0+-1381 -2294 0+-1381 2295 0+-2294 2295 0+-1383 -1384 0+-1383 -2296 0+-1384 -2296 0+-1385 -1386 0+-1385 2294 0+-1385 2296 0+-1386 2294 0+-1386 2296 0+2294 2296 0+1378 1379 1380 1381 1383 1384 1385 1386 0+-361 -1387 110 0+-362 -1387 111 0+-363 -1387 112 0+-364 -1387 113 0+-365 -1387 114 0+-366 -1387 115 0+-367 -1387 116 0+-368 -1387 117 0+-369 -1387 118 0+-370 -1387 119 0+-371 -1387 120 0+-372 -1387 121 0+-373 -1387 122 0+-374 -1387 123 0+-375 -1387 124 0+-376 -1387 125 0+-377 -1387 126 0+-378 -1387 127 0+-379 -1387 128 0+-380 -1387 129 0+-381 -1387 130 0+-382 -1387 131 0+-383 -1387 132 0+-384 -1387 133 0+-385 -1387 134 0+-386 -1387 135 0+-387 -1387 136 0+-388 -1387 137 0+-389 -1387 138 0+-390 -1387 139 0+-391 -1387 140 0+-392 -1387 141 0+-393 -1387 142 0+-394 -1387 143 0+-395 -1387 144 0+-361 -1388 146 0+-362 -1388 147 0+-363 -1388 148 0+-364 -1388 149 0+-365 -1388 150 0+-366 -1388 151 0+-367 -1388 152 0+-368 -1388 153 0+-369 -1388 154 0+-370 -1388 155 0+-371 -1388 156 0+-372 -1388 157 0+-373 -1388 158 0+-374 -1388 159 0+-375 -1388 160 0+-376 -1388 161 0+-377 -1388 162 0+-378 -1388 163 0+-379 -1388 164 0+-380 -1388 165 0+-381 -1388 166 0+-382 -1388 167 0+-383 -1388 168 0+-384 -1388 169 0+-385 -1388 170 0+-386 -1388 171 0+-387 -1388 172 0+-388 -1388 173 0+-389 -1388 174 0+-390 -1388 175 0+-391 -1388 176 0+-392 -1388 177 0+-393 -1388 178 0+-394 -1388 179 0+-395 -1388 180 0+-361 -1389 182 0+-362 -1389 183 0+-363 -1389 184 0+-364 -1389 185 0+-365 -1389 186 0+-366 -1389 187 0+-367 -1389 188 0+-368 -1389 189 0+-369 -1389 190 0+-370 -1389 191 0+-371 -1389 192 0+-372 -1389 193 0+-373 -1389 194 0+-374 -1389 195 0+-375 -1389 196 0+-376 -1389 197 0+-377 -1389 198 0+-378 -1389 199 0+-379 -1389 200 0+-380 -1389 201 0+-381 -1389 202 0+-382 -1389 203 0+-383 -1389 204 0+-384 -1389 205 0+-385 -1389 206 0+-386 -1389 207 0+-387 -1389 208 0+-388 -1389 209 0+-389 -1389 210 0+-390 -1389 211 0+-391 -1389 212 0+-392 -1389 213 0+-393 -1389 214 0+-394 -1389 215 0+-395 -1389 216 0+-361 -1390 326 0+-362 -1390 327 0+-363 -1390 328 0+-364 -1390 329 0+-365 -1390 330 0+-366 -1390 331 0+-367 -1390 332 0+-368 -1390 333 0+-369 -1390 334 0+-370 -1390 335 0+-371 -1390 336 0+-372 -1390 337 0+-373 -1390 338 0+-374 -1390 339 0+-375 -1390 340 0+-376 -1390 341 0+-377 -1390 342 0+-378 -1390 343 0+-379 -1390 344 0+-380 -1390 345 0+-381 -1390 346 0+-382 -1390 347 0+-383 -1390 348 0+-384 -1390 349 0+-385 -1390 350 0+-386 -1390 351 0+-387 -1390 352 0+-388 -1390 353 0+-389 -1390 354 0+-390 -1390 355 0+-391 -1390 356 0+-392 -1390 357 0+-393 -1390 358 0+-394 -1390 359 0+-395 -1390 360 0+-361 -1392 398 0+-362 -1392 399 0+-363 -1392 400 0+-364 -1392 401 0+-365 -1392 402 0+-366 -1392 403 0+-367 -1392 404 0+-368 -1392 405 0+-369 -1392 406 0+-370 -1392 407 0+-371 -1392 408 0+-372 -1392 409 0+-373 -1392 410 0+-374 -1392 411 0+-375 -1392 412 0+-376 -1392 413 0+-377 -1392 414 0+-378 -1392 415 0+-379 -1392 416 0+-380 -1392 417 0+-381 -1392 418 0+-382 -1392 419 0+-383 -1392 420 0+-384 -1392 421 0+-385 -1392 422 0+-386 -1392 423 0+-387 -1392 424 0+-388 -1392 425 0+-389 -1392 426 0+-390 -1392 427 0+-391 -1392 428 0+-392 -1392 429 0+-393 -1392 430 0+-394 -1392 431 0+-395 -1392 432 0+-361 -1393 542 0+-362 -1393 543 0+-363 -1393 544 0+-364 -1393 545 0+-365 -1393 546 0+-366 -1393 547 0+-367 -1393 548 0+-368 -1393 549 0+-369 -1393 550 0+-370 -1393 551 0+-371 -1393 552 0+-372 -1393 553 0+-373 -1393 554 0+-374 -1393 555 0+-375 -1393 556 0+-376 -1393 557 0+-377 -1393 558 0+-378 -1393 559 0+-379 -1393 560 0+-380 -1393 561 0+-381 -1393 562 0+-382 -1393 563 0+-383 -1393 564 0+-384 -1393 565 0+-385 -1393 566 0+-386 -1393 567 0+-387 -1393 568 0+-388 -1393 569 0+-389 -1393 570 0+-390 -1393 571 0+-391 -1393 572 0+-392 -1393 573 0+-393 -1393 574 0+-394 -1393 575 0+-395 -1393 576 0+-361 -1394 578 0+-362 -1394 579 0+-363 -1394 580 0+-364 -1394 581 0+-365 -1394 582 0+-366 -1394 583 0+-367 -1394 584 0+-368 -1394 585 0+-369 -1394 586 0+-370 -1394 587 0+-371 -1394 588 0+-372 -1394 589 0+-373 -1394 590 0+-374 -1394 591 0+-375 -1394 592 0+-376 -1394 593 0+-377 -1394 594 0+-378 -1394 595 0+-379 -1394 596 0+-380 -1394 597 0+-381 -1394 598 0+-382 -1394 599 0+-383 -1394 600 0+-384 -1394 601 0+-385 -1394 602 0+-386 -1394 603 0+-387 -1394 604 0+-388 -1394 605 0+-389 -1394 606 0+-390 -1394 607 0+-391 -1394 608 0+-392 -1394 609 0+-393 -1394 610 0+-394 -1394 611 0+-395 -1394 612 0+-361 -1395 614 0+-362 -1395 615 0+-363 -1395 616 0+-364 -1395 617 0+-365 -1395 618 0+-366 -1395 619 0+-367 -1395 620 0+-368 -1395 621 0+-369 -1395 622 0+-370 -1395 623 0+-371 -1395 624 0+-372 -1395 625 0+-373 -1395 626 0+-374 -1395 627 0+-375 -1395 628 0+-376 -1395 629 0+-377 -1395 630 0+-378 -1395 631 0+-379 -1395 632 0+-380 -1395 633 0+-381 -1395 634 0+-382 -1395 635 0+-383 -1395 636 0+-384 -1395 637 0+-385 -1395 638 0+-386 -1395 639 0+-387 -1395 640 0+-388 -1395 641 0+-389 -1395 642 0+-390 -1395 643 0+-391 -1395 644 0+-392 -1395 645 0+-393 -1395 646 0+-394 -1395 647 0+-395 -1395 648 0+-1387 -1388 0+-1387 -2306 0+-1388 -2306 0+-1389 -1390 0+-1389 -2305 0+-1389 2306 0+-1390 -2305 0+-1390 2306 0+-2305 2306 0+-1392 -1393 0+-1392 -2307 0+-1393 -2307 0+-1394 -1395 0+-1394 2305 0+-1394 2307 0+-1395 2305 0+-1395 2307 0+2305 2307 0+1387 1388 1389 1390 1392 1393 1394 1395 0+-397 -1396 146 0+-398 -1396 147 0+-399 -1396 148 0+-400 -1396 149 0+-401 -1396 150 0+-402 -1396 151 0+-403 -1396 152 0+-404 -1396 153 0+-405 -1396 154 0+-406 -1396 155 0+-407 -1396 156 0+-408 -1396 157 0+-409 -1396 158 0+-410 -1396 159 0+-411 -1396 160 0+-412 -1396 161 0+-413 -1396 162 0+-414 -1396 163 0+-415 -1396 164 0+-416 -1396 165 0+-417 -1396 166 0+-418 -1396 167 0+-419 -1396 168 0+-420 -1396 169 0+-421 -1396 170 0+-422 -1396 171 0+-423 -1396 172 0+-424 -1396 173 0+-425 -1396 174 0+-426 -1396 175 0+-427 -1396 176 0+-428 -1396 177 0+-429 -1396 178 0+-430 -1396 179 0+-431 -1396 180 0+-397 -1397 182 0+-398 -1397 183 0+-399 -1397 184 0+-400 -1397 185 0+-401 -1397 186 0+-402 -1397 187 0+-403 -1397 188 0+-404 -1397 189 0+-405 -1397 190 0+-406 -1397 191 0+-407 -1397 192 0+-408 -1397 193 0+-409 -1397 194 0+-410 -1397 195 0+-411 -1397 196 0+-412 -1397 197 0+-413 -1397 198 0+-414 -1397 199 0+-415 -1397 200 0+-416 -1397 201 0+-417 -1397 202 0+-418 -1397 203 0+-419 -1397 204 0+-420 -1397 205 0+-421 -1397 206 0+-422 -1397 207 0+-423 -1397 208 0+-424 -1397 209 0+-425 -1397 210 0+-426 -1397 211 0+-427 -1397 212 0+-428 -1397 213 0+-429 -1397 214 0+-430 -1397 215 0+-431 -1397 216 0+-397 -1399 362 0+-398 -1399 363 0+-399 -1399 364 0+-400 -1399 365 0+-401 -1399 366 0+-402 -1399 367 0+-403 -1399 368 0+-404 -1399 369 0+-405 -1399 370 0+-406 -1399 371 0+-407 -1399 372 0+-408 -1399 373 0+-409 -1399 374 0+-410 -1399 375 0+-411 -1399 376 0+-412 -1399 377 0+-413 -1399 378 0+-414 -1399 379 0+-415 -1399 380 0+-416 -1399 381 0+-417 -1399 382 0+-418 -1399 383 0+-419 -1399 384 0+-420 -1399 385 0+-421 -1399 386 0+-422 -1399 387 0+-423 -1399 388 0+-424 -1399 389 0+-425 -1399 390 0+-426 -1399 391 0+-427 -1399 392 0+-428 -1399 393 0+-429 -1399 394 0+-430 -1399 395 0+-431 -1399 396 0+-397 -1402 578 0+-398 -1402 579 0+-399 -1402 580 0+-400 -1402 581 0+-401 -1402 582 0+-402 -1402 583 0+-403 -1402 584 0+-404 -1402 585 0+-405 -1402 586 0+-406 -1402 587 0+-407 -1402 588 0+-408 -1402 589 0+-409 -1402 590 0+-410 -1402 591 0+-411 -1402 592 0+-412 -1402 593 0+-413 -1402 594 0+-414 -1402 595 0+-415 -1402 596 0+-416 -1402 597 0+-417 -1402 598 0+-418 -1402 599 0+-419 -1402 600 0+-420 -1402 601 0+-421 -1402 602 0+-422 -1402 603 0+-423 -1402 604 0+-424 -1402 605 0+-425 -1402 606 0+-426 -1402 607 0+-427 -1402 608 0+-428 -1402 609 0+-429 -1402 610 0+-430 -1402 611 0+-431 -1402 612 0+-397 -1403 614 0+-398 -1403 615 0+-399 -1403 616 0+-400 -1403 617 0+-401 -1403 618 0+-402 -1403 619 0+-403 -1403 620 0+-404 -1403 621 0+-405 -1403 622 0+-406 -1403 623 0+-407 -1403 624 0+-408 -1403 625 0+-409 -1403 626 0+-410 -1403 627 0+-411 -1403 628 0+-412 -1403 629 0+-413 -1403 630 0+-414 -1403 631 0+-415 -1403 632 0+-416 -1403 633 0+-417 -1403 634 0+-418 -1403 635 0+-419 -1403 636 0+-420 -1403 637 0+-421 -1403 638 0+-422 -1403 639 0+-423 -1403 640 0+-424 -1403 641 0+-425 -1403 642 0+-426 -1403 643 0+-427 -1403 644 0+-428 -1403 645 0+-429 -1403 646 0+-430 -1403 647 0+-431 -1403 648 0+-1396 -1397 0+-1396 -2313 0+-1397 -2313 0+-1399 -1402 0+-1399 -1403 0+-1399 2313 0+-1402 -1403 0+-1402 2313 0+-1403 2313 0+1396 1397 1399 1402 1403 0+-433 -1406 218 0+-434 -1406 219 0+-435 -1406 220 0+-436 -1406 221 0+-437 -1406 222 0+-438 -1406 223 0+-439 -1406 224 0+-440 -1406 225 0+-441 -1406 226 0+-442 -1406 227 0+-443 -1406 228 0+-444 -1406 229 0+-445 -1406 230 0+-446 -1406 231 0+-447 -1406 232 0+-448 -1406 233 0+-449 -1406 234 0+-450 -1406 235 0+-451 -1406 236 0+-452 -1406 237 0+-453 -1406 238 0+-454 -1406 239 0+-455 -1406 240 0+-456 -1406 241 0+-457 -1406 242 0+-458 -1406 243 0+-459 -1406 244 0+-460 -1406 245 0+-461 -1406 246 0+-462 -1406 247 0+-463 -1406 248 0+-464 -1406 249 0+-465 -1406 250 0+-466 -1406 251 0+-467 -1406 252 0+-433 -1407 254 0+-434 -1407 255 0+-435 -1407 256 0+-436 -1407 257 0+-437 -1407 258 0+-438 -1407 259 0+-439 -1407 260 0+-440 -1407 261 0+-441 -1407 262 0+-442 -1407 263 0+-443 -1407 264 0+-444 -1407 265 0+-445 -1407 266 0+-446 -1407 267 0+-447 -1407 268 0+-448 -1407 269 0+-449 -1407 270 0+-450 -1407 271 0+-451 -1407 272 0+-452 -1407 273 0+-453 -1407 274 0+-454 -1407 275 0+-455 -1407 276 0+-456 -1407 277 0+-457 -1407 278 0+-458 -1407 279 0+-459 -1407 280 0+-460 -1407 281 0+-461 -1407 282 0+-462 -1407 283 0+-463 -1407 284 0+-464 -1407 285 0+-465 -1407 286 0+-466 -1407 287 0+-467 -1407 288 0+-433 -1410 470 0+-434 -1410 471 0+-435 -1410 472 0+-436 -1410 473 0+-437 -1410 474 0+-438 -1410 475 0+-439 -1410 476 0+-440 -1410 477 0+-441 -1410 478 0+-442 -1410 479 0+-443 -1410 480 0+-444 -1410 481 0+-445 -1410 482 0+-446 -1410 483 0+-447 -1410 484 0+-448 -1410 485 0+-449 -1410 486 0+-450 -1410 487 0+-451 -1410 488 0+-452 -1410 489 0+-453 -1410 490 0+-454 -1410 491 0+-455 -1410 492 0+-456 -1410 493 0+-457 -1410 494 0+-458 -1410 495 0+-459 -1410 496 0+-460 -1410 497 0+-461 -1410 498 0+-462 -1410 499 0+-463 -1410 500 0+-464 -1410 501 0+-465 -1410 502 0+-466 -1410 503 0+-467 -1410 504 0+-433 -1412 650 0+-434 -1412 651 0+-435 -1412 652 0+-436 -1412 653 0+-437 -1412 654 0+-438 -1412 655 0+-439 -1412 656 0+-440 -1412 657 0+-441 -1412 658 0+-442 -1412 659 0+-443 -1412 660 0+-444 -1412 661 0+-445 -1412 662 0+-446 -1412 663 0+-447 -1412 664 0+-448 -1412 665 0+-449 -1412 666 0+-450 -1412 667 0+-451 -1412 668 0+-452 -1412 669 0+-453 -1412 670 0+-454 -1412 671 0+-455 -1412 672 0+-456 -1412 673 0+-457 -1412 674 0+-458 -1412 675 0+-459 -1412 676 0+-460 -1412 677 0+-461 -1412 678 0+-462 -1412 679 0+-463 -1412 680 0+-464 -1412 681 0+-465 -1412 682 0+-466 -1412 683 0+-467 -1412 684 0+-433 -1413 686 0+-434 -1413 687 0+-435 -1413 688 0+-436 -1413 689 0+-437 -1413 690 0+-438 -1413 691 0+-439 -1413 692 0+-440 -1413 693 0+-441 -1413 694 0+-442 -1413 695 0+-443 -1413 696 0+-444 -1413 697 0+-445 -1413 698 0+-446 -1413 699 0+-447 -1413 700 0+-448 -1413 701 0+-449 -1413 702 0+-450 -1413 703 0+-451 -1413 704 0+-452 -1413 705 0+-453 -1413 706 0+-454 -1413 707 0+-455 -1413 708 0+-456 -1413 709 0+-457 -1413 710 0+-458 -1413 711 0+-459 -1413 712 0+-460 -1413 713 0+-461 -1413 714 0+-462 -1413 715 0+-463 -1413 716 0+-464 -1413 717 0+-465 -1413 718 0+-466 -1413 719 0+-467 -1413 720 0+-1406 -1407 0+-1406 -2319 0+-1407 -2319 0+-1410 -1412 0+-1410 -1413 0+-1410 2319 0+-1412 -1413 0+-1412 2319 0+-1413 2319 0+1406 1407 1410 1412 1413 0+-469 -1414 218 0+-470 -1414 219 0+-471 -1414 220 0+-472 -1414 221 0+-473 -1414 222 0+-474 -1414 223 0+-475 -1414 224 0+-476 -1414 225 0+-477 -1414 226 0+-478 -1414 227 0+-479 -1414 228 0+-480 -1414 229 0+-481 -1414 230 0+-482 -1414 231 0+-483 -1414 232 0+-484 -1414 233 0+-485 -1414 234 0+-486 -1414 235 0+-487 -1414 236 0+-488 -1414 237 0+-489 -1414 238 0+-490 -1414 239 0+-491 -1414 240 0+-492 -1414 241 0+-493 -1414 242 0+-494 -1414 243 0+-495 -1414 244 0+-496 -1414 245 0+-497 -1414 246 0+-498 -1414 247 0+-499 -1414 248 0+-500 -1414 249 0+-501 -1414 250 0+-502 -1414 251 0+-503 -1414 252 0+-469 -1415 254 0+-470 -1415 255 0+-471 -1415 256 0+-472 -1415 257 0+-473 -1415 258 0+-474 -1415 259 0+-475 -1415 260 0+-476 -1415 261 0+-477 -1415 262 0+-478 -1415 263 0+-479 -1415 264 0+-480 -1415 265 0+-481 -1415 266 0+-482 -1415 267 0+-483 -1415 268 0+-484 -1415 269 0+-485 -1415 270 0+-486 -1415 271 0+-487 -1415 272 0+-488 -1415 273 0+-489 -1415 274 0+-490 -1415 275 0+-491 -1415 276 0+-492 -1415 277 0+-493 -1415 278 0+-494 -1415 279 0+-495 -1415 280 0+-496 -1415 281 0+-497 -1415 282 0+-498 -1415 283 0+-499 -1415 284 0+-500 -1415 285 0+-501 -1415 286 0+-502 -1415 287 0+-503 -1415 288 0+-469 -1416 290 0+-470 -1416 291 0+-471 -1416 292 0+-472 -1416 293 0+-473 -1416 294 0+-474 -1416 295 0+-475 -1416 296 0+-476 -1416 297 0+-477 -1416 298 0+-478 -1416 299 0+-479 -1416 300 0+-480 -1416 301 0+-481 -1416 302 0+-482 -1416 303 0+-483 -1416 304 0+-484 -1416 305 0+-485 -1416 306 0+-486 -1416 307 0+-487 -1416 308 0+-488 -1416 309 0+-489 -1416 310 0+-490 -1416 311 0+-491 -1416 312 0+-492 -1416 313 0+-493 -1416 314 0+-494 -1416 315 0+-495 -1416 316 0+-496 -1416 317 0+-497 -1416 318 0+-498 -1416 319 0+-499 -1416 320 0+-500 -1416 321 0+-501 -1416 322 0+-502 -1416 323 0+-503 -1416 324 0+-469 -1417 434 0+-470 -1417 435 0+-471 -1417 436 0+-472 -1417 437 0+-473 -1417 438 0+-474 -1417 439 0+-475 -1417 440 0+-476 -1417 441 0+-477 -1417 442 0+-478 -1417 443 0+-479 -1417 444 0+-480 -1417 445 0+-481 -1417 446 0+-482 -1417 447 0+-483 -1417 448 0+-484 -1417 449 0+-485 -1417 450 0+-486 -1417 451 0+-487 -1417 452 0+-488 -1417 453 0+-489 -1417 454 0+-490 -1417 455 0+-491 -1417 456 0+-492 -1417 457 0+-493 -1417 458 0+-494 -1417 459 0+-495 -1417 460 0+-496 -1417 461 0+-497 -1417 462 0+-498 -1417 463 0+-499 -1417 464 0+-500 -1417 465 0+-501 -1417 466 0+-502 -1417 467 0+-503 -1417 468 0+-469 -1419 506 0+-470 -1419 507 0+-471 -1419 508 0+-472 -1419 509 0+-473 -1419 510 0+-474 -1419 511 0+-475 -1419 512 0+-476 -1419 513 0+-477 -1419 514 0+-478 -1419 515 0+-479 -1419 516 0+-480 -1419 517 0+-481 -1419 518 0+-482 -1419 519 0+-483 -1419 520 0+-484 -1419 521 0+-485 -1419 522 0+-486 -1419 523 0+-487 -1419 524 0+-488 -1419 525 0+-489 -1419 526 0+-490 -1419 527 0+-491 -1419 528 0+-492 -1419 529 0+-493 -1419 530 0+-494 -1419 531 0+-495 -1419 532 0+-496 -1419 533 0+-497 -1419 534 0+-498 -1419 535 0+-499 -1419 536 0+-500 -1419 537 0+-501 -1419 538 0+-502 -1419 539 0+-503 -1419 540 0+-469 -1420 650 0+-470 -1420 651 0+-471 -1420 652 0+-472 -1420 653 0+-473 -1420 654 0+-474 -1420 655 0+-475 -1420 656 0+-476 -1420 657 0+-477 -1420 658 0+-478 -1420 659 0+-479 -1420 660 0+-480 -1420 661 0+-481 -1420 662 0+-482 -1420 663 0+-483 -1420 664 0+-484 -1420 665 0+-485 -1420 666 0+-486 -1420 667 0+-487 -1420 668 0+-488 -1420 669 0+-489 -1420 670 0+-490 -1420 671 0+-491 -1420 672 0+-492 -1420 673 0+-493 -1420 674 0+-494 -1420 675 0+-495 -1420 676 0+-496 -1420 677 0+-497 -1420 678 0+-498 -1420 679 0+-499 -1420 680 0+-500 -1420 681 0+-501 -1420 682 0+-502 -1420 683 0+-503 -1420 684 0+-469 -1421 686 0+-470 -1421 687 0+-471 -1421 688 0+-472 -1421 689 0+-473 -1421 690 0+-474 -1421 691 0+-475 -1421 692 0+-476 -1421 693 0+-477 -1421 694 0+-478 -1421 695 0+-479 -1421 696 0+-480 -1421 697 0+-481 -1421 698 0+-482 -1421 699 0+-483 -1421 700 0+-484 -1421 701 0+-485 -1421 702 0+-486 -1421 703 0+-487 -1421 704 0+-488 -1421 705 0+-489 -1421 706 0+-490 -1421 707 0+-491 -1421 708 0+-492 -1421 709 0+-493 -1421 710 0+-494 -1421 711 0+-495 -1421 712 0+-496 -1421 713 0+-497 -1421 714 0+-498 -1421 715 0+-499 -1421 716 0+-500 -1421 717 0+-501 -1421 718 0+-502 -1421 719 0+-503 -1421 720 0+-469 -1422 722 0+-470 -1422 723 0+-471 -1422 724 0+-472 -1422 725 0+-473 -1422 726 0+-474 -1422 727 0+-475 -1422 728 0+-476 -1422 729 0+-477 -1422 730 0+-478 -1422 731 0+-479 -1422 732 0+-480 -1422 733 0+-481 -1422 734 0+-482 -1422 735 0+-483 -1422 736 0+-484 -1422 737 0+-485 -1422 738 0+-486 -1422 739 0+-487 -1422 740 0+-488 -1422 741 0+-489 -1422 742 0+-490 -1422 743 0+-491 -1422 744 0+-492 -1422 745 0+-493 -1422 746 0+-494 -1422 747 0+-495 -1422 748 0+-496 -1422 749 0+-497 -1422 750 0+-498 -1422 751 0+-499 -1422 752 0+-500 -1422 753 0+-501 -1422 754 0+-502 -1422 755 0+-503 -1422 756 0+-1414 -1415 0+-1414 -2329 0+-1415 -2329 0+-1416 -1417 0+-1416 -2328 0+-1416 2329 0+-1417 -2328 0+-1417 2329 0+-2328 2329 0+-1419 -1420 0+-1419 -2330 0+-1420 -2330 0+-1421 -1422 0+-1421 2328 0+-1421 2330 0+-1422 2328 0+-1422 2330 0+2328 2330 0+1414 1415 1416 1417 1419 1420 1421 1422 0+-505 -1423 254 0+-506 -1423 255 0+-507 -1423 256 0+-508 -1423 257 0+-509 -1423 258 0+-510 -1423 259 0+-511 -1423 260 0+-512 -1423 261 0+-513 -1423 262 0+-514 -1423 263 0+-515 -1423 264 0+-516 -1423 265 0+-517 -1423 266 0+-518 -1423 267 0+-519 -1423 268 0+-520 -1423 269 0+-521 -1423 270 0+-522 -1423 271 0+-523 -1423 272 0+-524 -1423 273 0+-525 -1423 274 0+-526 -1423 275 0+-527 -1423 276 0+-528 -1423 277 0+-529 -1423 278 0+-530 -1423 279 0+-531 -1423 280 0+-532 -1423 281 0+-533 -1423 282 0+-534 -1423 283 0+-535 -1423 284 0+-536 -1423 285 0+-537 -1423 286 0+-538 -1423 287 0+-539 -1423 288 0+-505 -1424 290 0+-506 -1424 291 0+-507 -1424 292 0+-508 -1424 293 0+-509 -1424 294 0+-510 -1424 295 0+-511 -1424 296 0+-512 -1424 297 0+-513 -1424 298 0+-514 -1424 299 0+-515 -1424 300 0+-516 -1424 301 0+-517 -1424 302 0+-518 -1424 303 0+-519 -1424 304 0+-520 -1424 305 0+-521 -1424 306 0+-522 -1424 307 0+-523 -1424 308 0+-524 -1424 309 0+-525 -1424 310 0+-526 -1424 311 0+-527 -1424 312 0+-528 -1424 313 0+-529 -1424 314 0+-530 -1424 315 0+-531 -1424 316 0+-532 -1424 317 0+-533 -1424 318 0+-534 -1424 319 0+-535 -1424 320 0+-536 -1424 321 0+-537 -1424 322 0+-538 -1424 323 0+-539 -1424 324 0+-505 -1425 326 0+-506 -1425 327 0+-507 -1425 328 0+-508 -1425 329 0+-509 -1425 330 0+-510 -1425 331 0+-511 -1425 332 0+-512 -1425 333 0+-513 -1425 334 0+-514 -1425 335 0+-515 -1425 336 0+-516 -1425 337 0+-517 -1425 338 0+-518 -1425 339 0+-519 -1425 340 0+-520 -1425 341 0+-521 -1425 342 0+-522 -1425 343 0+-523 -1425 344 0+-524 -1425 345 0+-525 -1425 346 0+-526 -1425 347 0+-527 -1425 348 0+-528 -1425 349 0+-529 -1425 350 0+-530 -1425 351 0+-531 -1425 352 0+-532 -1425 353 0+-533 -1425 354 0+-534 -1425 355 0+-535 -1425 356 0+-536 -1425 357 0+-537 -1425 358 0+-538 -1425 359 0+-539 -1425 360 0+-505 -1426 470 0+-506 -1426 471 0+-507 -1426 472 0+-508 -1426 473 0+-509 -1426 474 0+-510 -1426 475 0+-511 -1426 476 0+-512 -1426 477 0+-513 -1426 478 0+-514 -1426 479 0+-515 -1426 480 0+-516 -1426 481 0+-517 -1426 482 0+-518 -1426 483 0+-519 -1426 484 0+-520 -1426 485 0+-521 -1426 486 0+-522 -1426 487 0+-523 -1426 488 0+-524 -1426 489 0+-525 -1426 490 0+-526 -1426 491 0+-527 -1426 492 0+-528 -1426 493 0+-529 -1426 494 0+-530 -1426 495 0+-531 -1426 496 0+-532 -1426 497 0+-533 -1426 498 0+-534 -1426 499 0+-535 -1426 500 0+-536 -1426 501 0+-537 -1426 502 0+-538 -1426 503 0+-539 -1426 504 0+-505 -1428 542 0+-506 -1428 543 0+-507 -1428 544 0+-508 -1428 545 0+-509 -1428 546 0+-510 -1428 547 0+-511 -1428 548 0+-512 -1428 549 0+-513 -1428 550 0+-514 -1428 551 0+-515 -1428 552 0+-516 -1428 553 0+-517 -1428 554 0+-518 -1428 555 0+-519 -1428 556 0+-520 -1428 557 0+-521 -1428 558 0+-522 -1428 559 0+-523 -1428 560 0+-524 -1428 561 0+-525 -1428 562 0+-526 -1428 563 0+-527 -1428 564 0+-528 -1428 565 0+-529 -1428 566 0+-530 -1428 567 0+-531 -1428 568 0+-532 -1428 569 0+-533 -1428 570 0+-534 -1428 571 0+-535 -1428 572 0+-536 -1428 573 0+-537 -1428 574 0+-538 -1428 575 0+-539 -1428 576 0+-505 -1429 686 0+-506 -1429 687 0+-507 -1429 688 0+-508 -1429 689 0+-509 -1429 690 0+-510 -1429 691 0+-511 -1429 692 0+-512 -1429 693 0+-513 -1429 694 0+-514 -1429 695 0+-515 -1429 696 0+-516 -1429 697 0+-517 -1429 698 0+-518 -1429 699 0+-519 -1429 700 0+-520 -1429 701 0+-521 -1429 702 0+-522 -1429 703 0+-523 -1429 704 0+-524 -1429 705 0+-525 -1429 706 0+-526 -1429 707 0+-527 -1429 708 0+-528 -1429 709 0+-529 -1429 710 0+-530 -1429 711 0+-531 -1429 712 0+-532 -1429 713 0+-533 -1429 714 0+-534 -1429 715 0+-535 -1429 716 0+-536 -1429 717 0+-537 -1429 718 0+-538 -1429 719 0+-539 -1429 720 0+-505 -1430 722 0+-506 -1430 723 0+-507 -1430 724 0+-508 -1430 725 0+-509 -1430 726 0+-510 -1430 727 0+-511 -1430 728 0+-512 -1430 729 0+-513 -1430 730 0+-514 -1430 731 0+-515 -1430 732 0+-516 -1430 733 0+-517 -1430 734 0+-518 -1430 735 0+-519 -1430 736 0+-520 -1430 737 0+-521 -1430 738 0+-522 -1430 739 0+-523 -1430 740 0+-524 -1430 741 0+-525 -1430 742 0+-526 -1430 743 0+-527 -1430 744 0+-528 -1430 745 0+-529 -1430 746 0+-530 -1430 747 0+-531 -1430 748 0+-532 -1430 749 0+-533 -1430 750 0+-534 -1430 751 0+-535 -1430 752 0+-536 -1430 753 0+-537 -1430 754 0+-538 -1430 755 0+-539 -1430 756 0+-505 -1431 758 0+-506 -1431 759 0+-507 -1431 760 0+-508 -1431 761 0+-509 -1431 762 0+-510 -1431 763 0+-511 -1431 764 0+-512 -1431 765 0+-513 -1431 766 0+-514 -1431 767 0+-515 -1431 768 0+-516 -1431 769 0+-517 -1431 770 0+-518 -1431 771 0+-519 -1431 772 0+-520 -1431 773 0+-521 -1431 774 0+-522 -1431 775 0+-523 -1431 776 0+-524 -1431 777 0+-525 -1431 778 0+-526 -1431 779 0+-527 -1431 780 0+-528 -1431 781 0+-529 -1431 782 0+-530 -1431 783 0+-531 -1431 784 0+-532 -1431 785 0+-533 -1431 786 0+-534 -1431 787 0+-535 -1431 788 0+-536 -1431 789 0+-537 -1431 790 0+-538 -1431 791 0+-539 -1431 792 0+-1423 -1424 0+-1423 -2340 0+-1424 -2340 0+-1425 -1426 0+-1425 -2339 0+-1425 2340 0+-1426 -2339 0+-1426 2340 0+-2339 2340 0+-1428 -1429 0+-1428 -2341 0+-1429 -2341 0+-1430 -1431 0+-1430 2339 0+-1430 2341 0+-1431 2339 0+-1431 2341 0+2339 2341 0+1423 1424 1425 1426 1428 1429 1430 1431 0+-541 -1432 290 0+-542 -1432 291 0+-543 -1432 292 0+-544 -1432 293 0+-545 -1432 294 0+-546 -1432 295 0+-547 -1432 296 0+-548 -1432 297 0+-549 -1432 298 0+-550 -1432 299 0+-551 -1432 300 0+-552 -1432 301 0+-553 -1432 302 0+-554 -1432 303 0+-555 -1432 304 0+-556 -1432 305 0+-557 -1432 306 0+-558 -1432 307 0+-559 -1432 308 0+-560 -1432 309 0+-561 -1432 310 0+-562 -1432 311 0+-563 -1432 312 0+-564 -1432 313 0+-565 -1432 314 0+-566 -1432 315 0+-567 -1432 316 0+-568 -1432 317 0+-569 -1432 318 0+-570 -1432 319 0+-571 -1432 320 0+-572 -1432 321 0+-573 -1432 322 0+-574 -1432 323 0+-575 -1432 324 0+-541 -1433 326 0+-542 -1433 327 0+-543 -1433 328 0+-544 -1433 329 0+-545 -1433 330 0+-546 -1433 331 0+-547 -1433 332 0+-548 -1433 333 0+-549 -1433 334 0+-550 -1433 335 0+-551 -1433 336 0+-552 -1433 337 0+-553 -1433 338 0+-554 -1433 339 0+-555 -1433 340 0+-556 -1433 341 0+-557 -1433 342 0+-558 -1433 343 0+-559 -1433 344 0+-560 -1433 345 0+-561 -1433 346 0+-562 -1433 347 0+-563 -1433 348 0+-564 -1433 349 0+-565 -1433 350 0+-566 -1433 351 0+-567 -1433 352 0+-568 -1433 353 0+-569 -1433 354 0+-570 -1433 355 0+-571 -1433 356 0+-572 -1433 357 0+-573 -1433 358 0+-574 -1433 359 0+-575 -1433 360 0+-541 -1434 362 0+-542 -1434 363 0+-543 -1434 364 0+-544 -1434 365 0+-545 -1434 366 0+-546 -1434 367 0+-547 -1434 368 0+-548 -1434 369 0+-549 -1434 370 0+-550 -1434 371 0+-551 -1434 372 0+-552 -1434 373 0+-553 -1434 374 0+-554 -1434 375 0+-555 -1434 376 0+-556 -1434 377 0+-557 -1434 378 0+-558 -1434 379 0+-559 -1434 380 0+-560 -1434 381 0+-561 -1434 382 0+-562 -1434 383 0+-563 -1434 384 0+-564 -1434 385 0+-565 -1434 386 0+-566 -1434 387 0+-567 -1434 388 0+-568 -1434 389 0+-569 -1434 390 0+-570 -1434 391 0+-571 -1434 392 0+-572 -1434 393 0+-573 -1434 394 0+-574 -1434 395 0+-575 -1434 396 0+-541 -1435 506 0+-542 -1435 507 0+-543 -1435 508 0+-544 -1435 509 0+-545 -1435 510 0+-546 -1435 511 0+-547 -1435 512 0+-548 -1435 513 0+-549 -1435 514 0+-550 -1435 515 0+-551 -1435 516 0+-552 -1435 517 0+-553 -1435 518 0+-554 -1435 519 0+-555 -1435 520 0+-556 -1435 521 0+-557 -1435 522 0+-558 -1435 523 0+-559 -1435 524 0+-560 -1435 525 0+-561 -1435 526 0+-562 -1435 527 0+-563 -1435 528 0+-564 -1435 529 0+-565 -1435 530 0+-566 -1435 531 0+-567 -1435 532 0+-568 -1435 533 0+-569 -1435 534 0+-570 -1435 535 0+-571 -1435 536 0+-572 -1435 537 0+-573 -1435 538 0+-574 -1435 539 0+-575 -1435 540 0+-541 -1437 578 0+-542 -1437 579 0+-543 -1437 580 0+-544 -1437 581 0+-545 -1437 582 0+-546 -1437 583 0+-547 -1437 584 0+-548 -1437 585 0+-549 -1437 586 0+-550 -1437 587 0+-551 -1437 588 0+-552 -1437 589 0+-553 -1437 590 0+-554 -1437 591 0+-555 -1437 592 0+-556 -1437 593 0+-557 -1437 594 0+-558 -1437 595 0+-559 -1437 596 0+-560 -1437 597 0+-561 -1437 598 0+-562 -1437 599 0+-563 -1437 600 0+-564 -1437 601 0+-565 -1437 602 0+-566 -1437 603 0+-567 -1437 604 0+-568 -1437 605 0+-569 -1437 606 0+-570 -1437 607 0+-571 -1437 608 0+-572 -1437 609 0+-573 -1437 610 0+-574 -1437 611 0+-575 -1437 612 0+-541 -1438 722 0+-542 -1438 723 0+-543 -1438 724 0+-544 -1438 725 0+-545 -1438 726 0+-546 -1438 727 0+-547 -1438 728 0+-548 -1438 729 0+-549 -1438 730 0+-550 -1438 731 0+-551 -1438 732 0+-552 -1438 733 0+-553 -1438 734 0+-554 -1438 735 0+-555 -1438 736 0+-556 -1438 737 0+-557 -1438 738 0+-558 -1438 739 0+-559 -1438 740 0+-560 -1438 741 0+-561 -1438 742 0+-562 -1438 743 0+-563 -1438 744 0+-564 -1438 745 0+-565 -1438 746 0+-566 -1438 747 0+-567 -1438 748 0+-568 -1438 749 0+-569 -1438 750 0+-570 -1438 751 0+-571 -1438 752 0+-572 -1438 753 0+-573 -1438 754 0+-574 -1438 755 0+-575 -1438 756 0+-541 -1439 758 0+-542 -1439 759 0+-543 -1439 760 0+-544 -1439 761 0+-545 -1439 762 0+-546 -1439 763 0+-547 -1439 764 0+-548 -1439 765 0+-549 -1439 766 0+-550 -1439 767 0+-551 -1439 768 0+-552 -1439 769 0+-553 -1439 770 0+-554 -1439 771 0+-555 -1439 772 0+-556 -1439 773 0+-557 -1439 774 0+-558 -1439 775 0+-559 -1439 776 0+-560 -1439 777 0+-561 -1439 778 0+-562 -1439 779 0+-563 -1439 780 0+-564 -1439 781 0+-565 -1439 782 0+-566 -1439 783 0+-567 -1439 784 0+-568 -1439 785 0+-569 -1439 786 0+-570 -1439 787 0+-571 -1439 788 0+-572 -1439 789 0+-573 -1439 790 0+-574 -1439 791 0+-575 -1439 792 0+-541 -1440 794 0+-542 -1440 795 0+-543 -1440 796 0+-544 -1440 797 0+-545 -1440 798 0+-546 -1440 799 0+-547 -1440 800 0+-548 -1440 801 0+-549 -1440 802 0+-550 -1440 803 0+-551 -1440 804 0+-552 -1440 805 0+-553 -1440 806 0+-554 -1440 807 0+-555 -1440 808 0+-556 -1440 809 0+-557 -1440 810 0+-558 -1440 811 0+-559 -1440 812 0+-560 -1440 813 0+-561 -1440 814 0+-562 -1440 815 0+-563 -1440 816 0+-564 -1440 817 0+-565 -1440 818 0+-566 -1440 819 0+-567 -1440 820 0+-568 -1440 821 0+-569 -1440 822 0+-570 -1440 823 0+-571 -1440 824 0+-572 -1440 825 0+-573 -1440 826 0+-574 -1440 827 0+-575 -1440 828 0+-1432 -1433 0+-1432 -2351 0+-1433 -2351 0+-1434 -1435 0+-1434 -2350 0+-1434 2351 0+-1435 -2350 0+-1435 2351 0+-2350 2351 0+-1437 -1438 0+-1437 -2352 0+-1438 -2352 0+-1439 -1440 0+-1439 2350 0+-1439 2352 0+-1440 2350 0+-1440 2352 0+2350 2352 0+1432 1433 1434 1435 1437 1438 1439 1440 0+-577 -1441 326 0+-578 -1441 327 0+-579 -1441 328 0+-580 -1441 329 0+-581 -1441 330 0+-582 -1441 331 0+-583 -1441 332 0+-584 -1441 333 0+-585 -1441 334 0+-586 -1441 335 0+-587 -1441 336 0+-588 -1441 337 0+-589 -1441 338 0+-590 -1441 339 0+-591 -1441 340 0+-592 -1441 341 0+-593 -1441 342 0+-594 -1441 343 0+-595 -1441 344 0+-596 -1441 345 0+-597 -1441 346 0+-598 -1441 347 0+-599 -1441 348 0+-600 -1441 349 0+-601 -1441 350 0+-602 -1441 351 0+-603 -1441 352 0+-604 -1441 353 0+-605 -1441 354 0+-606 -1441 355 0+-607 -1441 356 0+-608 -1441 357 0+-609 -1441 358 0+-610 -1441 359 0+-611 -1441 360 0+-577 -1442 362 0+-578 -1442 363 0+-579 -1442 364 0+-580 -1442 365 0+-581 -1442 366 0+-582 -1442 367 0+-583 -1442 368 0+-584 -1442 369 0+-585 -1442 370 0+-586 -1442 371 0+-587 -1442 372 0+-588 -1442 373 0+-589 -1442 374 0+-590 -1442 375 0+-591 -1442 376 0+-592 -1442 377 0+-593 -1442 378 0+-594 -1442 379 0+-595 -1442 380 0+-596 -1442 381 0+-597 -1442 382 0+-598 -1442 383 0+-599 -1442 384 0+-600 -1442 385 0+-601 -1442 386 0+-602 -1442 387 0+-603 -1442 388 0+-604 -1442 389 0+-605 -1442 390 0+-606 -1442 391 0+-607 -1442 392 0+-608 -1442 393 0+-609 -1442 394 0+-610 -1442 395 0+-611 -1442 396 0+-577 -1443 398 0+-578 -1443 399 0+-579 -1443 400 0+-580 -1443 401 0+-581 -1443 402 0+-582 -1443 403 0+-583 -1443 404 0+-584 -1443 405 0+-585 -1443 406 0+-586 -1443 407 0+-587 -1443 408 0+-588 -1443 409 0+-589 -1443 410 0+-590 -1443 411 0+-591 -1443 412 0+-592 -1443 413 0+-593 -1443 414 0+-594 -1443 415 0+-595 -1443 416 0+-596 -1443 417 0+-597 -1443 418 0+-598 -1443 419 0+-599 -1443 420 0+-600 -1443 421 0+-601 -1443 422 0+-602 -1443 423 0+-603 -1443 424 0+-604 -1443 425 0+-605 -1443 426 0+-606 -1443 427 0+-607 -1443 428 0+-608 -1443 429 0+-609 -1443 430 0+-610 -1443 431 0+-611 -1443 432 0+-577 -1444 542 0+-578 -1444 543 0+-579 -1444 544 0+-580 -1444 545 0+-581 -1444 546 0+-582 -1444 547 0+-583 -1444 548 0+-584 -1444 549 0+-585 -1444 550 0+-586 -1444 551 0+-587 -1444 552 0+-588 -1444 553 0+-589 -1444 554 0+-590 -1444 555 0+-591 -1444 556 0+-592 -1444 557 0+-593 -1444 558 0+-594 -1444 559 0+-595 -1444 560 0+-596 -1444 561 0+-597 -1444 562 0+-598 -1444 563 0+-599 -1444 564 0+-600 -1444 565 0+-601 -1444 566 0+-602 -1444 567 0+-603 -1444 568 0+-604 -1444 569 0+-605 -1444 570 0+-606 -1444 571 0+-607 -1444 572 0+-608 -1444 573 0+-609 -1444 574 0+-610 -1444 575 0+-611 -1444 576 0+-577 -1446 614 0+-578 -1446 615 0+-579 -1446 616 0+-580 -1446 617 0+-581 -1446 618 0+-582 -1446 619 0+-583 -1446 620 0+-584 -1446 621 0+-585 -1446 622 0+-586 -1446 623 0+-587 -1446 624 0+-588 -1446 625 0+-589 -1446 626 0+-590 -1446 627 0+-591 -1446 628 0+-592 -1446 629 0+-593 -1446 630 0+-594 -1446 631 0+-595 -1446 632 0+-596 -1446 633 0+-597 -1446 634 0+-598 -1446 635 0+-599 -1446 636 0+-600 -1446 637 0+-601 -1446 638 0+-602 -1446 639 0+-603 -1446 640 0+-604 -1446 641 0+-605 -1446 642 0+-606 -1446 643 0+-607 -1446 644 0+-608 -1446 645 0+-609 -1446 646 0+-610 -1446 647 0+-611 -1446 648 0+-577 -1447 758 0+-578 -1447 759 0+-579 -1447 760 0+-580 -1447 761 0+-581 -1447 762 0+-582 -1447 763 0+-583 -1447 764 0+-584 -1447 765 0+-585 -1447 766 0+-586 -1447 767 0+-587 -1447 768 0+-588 -1447 769 0+-589 -1447 770 0+-590 -1447 771 0+-591 -1447 772 0+-592 -1447 773 0+-593 -1447 774 0+-594 -1447 775 0+-595 -1447 776 0+-596 -1447 777 0+-597 -1447 778 0+-598 -1447 779 0+-599 -1447 780 0+-600 -1447 781 0+-601 -1447 782 0+-602 -1447 783 0+-603 -1447 784 0+-604 -1447 785 0+-605 -1447 786 0+-606 -1447 787 0+-607 -1447 788 0+-608 -1447 789 0+-609 -1447 790 0+-610 -1447 791 0+-611 -1447 792 0+-577 -1448 794 0+-578 -1448 795 0+-579 -1448 796 0+-580 -1448 797 0+-581 -1448 798 0+-582 -1448 799 0+-583 -1448 800 0+-584 -1448 801 0+-585 -1448 802 0+-586 -1448 803 0+-587 -1448 804 0+-588 -1448 805 0+-589 -1448 806 0+-590 -1448 807 0+-591 -1448 808 0+-592 -1448 809 0+-593 -1448 810 0+-594 -1448 811 0+-595 -1448 812 0+-596 -1448 813 0+-597 -1448 814 0+-598 -1448 815 0+-599 -1448 816 0+-600 -1448 817 0+-601 -1448 818 0+-602 -1448 819 0+-603 -1448 820 0+-604 -1448 821 0+-605 -1448 822 0+-606 -1448 823 0+-607 -1448 824 0+-608 -1448 825 0+-609 -1448 826 0+-610 -1448 827 0+-611 -1448 828 0+-577 -1449 830 0+-578 -1449 831 0+-579 -1449 832 0+-580 -1449 833 0+-581 -1449 834 0+-582 -1449 835 0+-583 -1449 836 0+-584 -1449 837 0+-585 -1449 838 0+-586 -1449 839 0+-587 -1449 840 0+-588 -1449 841 0+-589 -1449 842 0+-590 -1449 843 0+-591 -1449 844 0+-592 -1449 845 0+-593 -1449 846 0+-594 -1449 847 0+-595 -1449 848 0+-596 -1449 849 0+-597 -1449 850 0+-598 -1449 851 0+-599 -1449 852 0+-600 -1449 853 0+-601 -1449 854 0+-602 -1449 855 0+-603 -1449 856 0+-604 -1449 857 0+-605 -1449 858 0+-606 -1449 859 0+-607 -1449 860 0+-608 -1449 861 0+-609 -1449 862 0+-610 -1449 863 0+-611 -1449 864 0+-1441 -1442 0+-1441 -2362 0+-1442 -2362 0+-1443 -1444 0+-1443 -2361 0+-1443 2362 0+-1444 -2361 0+-1444 2362 0+-2361 2362 0+-1446 -1447 0+-1446 -2363 0+-1447 -2363 0+-1448 -1449 0+-1448 2361 0+-1448 2363 0+-1449 2361 0+-1449 2363 0+2361 2363 0+1441 1442 1443 1444 1446 1447 1448 1449 0+-613 -1450 362 0+-614 -1450 363 0+-615 -1450 364 0+-616 -1450 365 0+-617 -1450 366 0+-618 -1450 367 0+-619 -1450 368 0+-620 -1450 369 0+-621 -1450 370 0+-622 -1450 371 0+-623 -1450 372 0+-624 -1450 373 0+-625 -1450 374 0+-626 -1450 375 0+-627 -1450 376 0+-628 -1450 377 0+-629 -1450 378 0+-630 -1450 379 0+-631 -1450 380 0+-632 -1450 381 0+-633 -1450 382 0+-634 -1450 383 0+-635 -1450 384 0+-636 -1450 385 0+-637 -1450 386 0+-638 -1450 387 0+-639 -1450 388 0+-640 -1450 389 0+-641 -1450 390 0+-642 -1450 391 0+-643 -1450 392 0+-644 -1450 393 0+-645 -1450 394 0+-646 -1450 395 0+-647 -1450 396 0+-613 -1451 398 0+-614 -1451 399 0+-615 -1451 400 0+-616 -1451 401 0+-617 -1451 402 0+-618 -1451 403 0+-619 -1451 404 0+-620 -1451 405 0+-621 -1451 406 0+-622 -1451 407 0+-623 -1451 408 0+-624 -1451 409 0+-625 -1451 410 0+-626 -1451 411 0+-627 -1451 412 0+-628 -1451 413 0+-629 -1451 414 0+-630 -1451 415 0+-631 -1451 416 0+-632 -1451 417 0+-633 -1451 418 0+-634 -1451 419 0+-635 -1451 420 0+-636 -1451 421 0+-637 -1451 422 0+-638 -1451 423 0+-639 -1451 424 0+-640 -1451 425 0+-641 -1451 426 0+-642 -1451 427 0+-643 -1451 428 0+-644 -1451 429 0+-645 -1451 430 0+-646 -1451 431 0+-647 -1451 432 0+-613 -1453 578 0+-614 -1453 579 0+-615 -1453 580 0+-616 -1453 581 0+-617 -1453 582 0+-618 -1453 583 0+-619 -1453 584 0+-620 -1453 585 0+-621 -1453 586 0+-622 -1453 587 0+-623 -1453 588 0+-624 -1453 589 0+-625 -1453 590 0+-626 -1453 591 0+-627 -1453 592 0+-628 -1453 593 0+-629 -1453 594 0+-630 -1453 595 0+-631 -1453 596 0+-632 -1453 597 0+-633 -1453 598 0+-634 -1453 599 0+-635 -1453 600 0+-636 -1453 601 0+-637 -1453 602 0+-638 -1453 603 0+-639 -1453 604 0+-640 -1453 605 0+-641 -1453 606 0+-642 -1453 607 0+-643 -1453 608 0+-644 -1453 609 0+-645 -1453 610 0+-646 -1453 611 0+-647 -1453 612 0+-613 -1456 794 0+-614 -1456 795 0+-615 -1456 796 0+-616 -1456 797 0+-617 -1456 798 0+-618 -1456 799 0+-619 -1456 800 0+-620 -1456 801 0+-621 -1456 802 0+-622 -1456 803 0+-623 -1456 804 0+-624 -1456 805 0+-625 -1456 806 0+-626 -1456 807 0+-627 -1456 808 0+-628 -1456 809 0+-629 -1456 810 0+-630 -1456 811 0+-631 -1456 812 0+-632 -1456 813 0+-633 -1456 814 0+-634 -1456 815 0+-635 -1456 816 0+-636 -1456 817 0+-637 -1456 818 0+-638 -1456 819 0+-639 -1456 820 0+-640 -1456 821 0+-641 -1456 822 0+-642 -1456 823 0+-643 -1456 824 0+-644 -1456 825 0+-645 -1456 826 0+-646 -1456 827 0+-647 -1456 828 0+-613 -1457 830 0+-614 -1457 831 0+-615 -1457 832 0+-616 -1457 833 0+-617 -1457 834 0+-618 -1457 835 0+-619 -1457 836 0+-620 -1457 837 0+-621 -1457 838 0+-622 -1457 839 0+-623 -1457 840 0+-624 -1457 841 0+-625 -1457 842 0+-626 -1457 843 0+-627 -1457 844 0+-628 -1457 845 0+-629 -1457 846 0+-630 -1457 847 0+-631 -1457 848 0+-632 -1457 849 0+-633 -1457 850 0+-634 -1457 851 0+-635 -1457 852 0+-636 -1457 853 0+-637 -1457 854 0+-638 -1457 855 0+-639 -1457 856 0+-640 -1457 857 0+-641 -1457 858 0+-642 -1457 859 0+-643 -1457 860 0+-644 -1457 861 0+-645 -1457 862 0+-646 -1457 863 0+-647 -1457 864 0+-1450 -1451 0+-1450 -2369 0+-1451 -2369 0+-1453 -1456 0+-1453 -1457 0+-1453 2369 0+-1456 -1457 0+-1456 2369 0+-1457 2369 0+1450 1451 1453 1456 1457 0+-649 -1460 434 0+-650 -1460 435 0+-651 -1460 436 0+-652 -1460 437 0+-653 -1460 438 0+-654 -1460 439 0+-655 -1460 440 0+-656 -1460 441 0+-657 -1460 442 0+-658 -1460 443 0+-659 -1460 444 0+-660 -1460 445 0+-661 -1460 446 0+-662 -1460 447 0+-663 -1460 448 0+-664 -1460 449 0+-665 -1460 450 0+-666 -1460 451 0+-667 -1460 452 0+-668 -1460 453 0+-669 -1460 454 0+-670 -1460 455 0+-671 -1460 456 0+-672 -1460 457 0+-673 -1460 458 0+-674 -1460 459 0+-675 -1460 460 0+-676 -1460 461 0+-677 -1460 462 0+-678 -1460 463 0+-679 -1460 464 0+-680 -1460 465 0+-681 -1460 466 0+-682 -1460 467 0+-683 -1460 468 0+-649 -1461 470 0+-650 -1461 471 0+-651 -1461 472 0+-652 -1461 473 0+-653 -1461 474 0+-654 -1461 475 0+-655 -1461 476 0+-656 -1461 477 0+-657 -1461 478 0+-658 -1461 479 0+-659 -1461 480 0+-660 -1461 481 0+-661 -1461 482 0+-662 -1461 483 0+-663 -1461 484 0+-664 -1461 485 0+-665 -1461 486 0+-666 -1461 487 0+-667 -1461 488 0+-668 -1461 489 0+-669 -1461 490 0+-670 -1461 491 0+-671 -1461 492 0+-672 -1461 493 0+-673 -1461 494 0+-674 -1461 495 0+-675 -1461 496 0+-676 -1461 497 0+-677 -1461 498 0+-678 -1461 499 0+-679 -1461 500 0+-680 -1461 501 0+-681 -1461 502 0+-682 -1461 503 0+-683 -1461 504 0+-649 -1464 686 0+-650 -1464 687 0+-651 -1464 688 0+-652 -1464 689 0+-653 -1464 690 0+-654 -1464 691 0+-655 -1464 692 0+-656 -1464 693 0+-657 -1464 694 0+-658 -1464 695 0+-659 -1464 696 0+-660 -1464 697 0+-661 -1464 698 0+-662 -1464 699 0+-663 -1464 700 0+-664 -1464 701 0+-665 -1464 702 0+-666 -1464 703 0+-667 -1464 704 0+-668 -1464 705 0+-669 -1464 706 0+-670 -1464 707 0+-671 -1464 708 0+-672 -1464 709 0+-673 -1464 710 0+-674 -1464 711 0+-675 -1464 712 0+-676 -1464 713 0+-677 -1464 714 0+-678 -1464 715 0+-679 -1464 716 0+-680 -1464 717 0+-681 -1464 718 0+-682 -1464 719 0+-683 -1464 720 0+-649 -1466 866 0+-650 -1466 867 0+-651 -1466 868 0+-652 -1466 869 0+-653 -1466 870 0+-654 -1466 871 0+-655 -1466 872 0+-656 -1466 873 0+-657 -1466 874 0+-658 -1466 875 0+-659 -1466 876 0+-660 -1466 877 0+-661 -1466 878 0+-662 -1466 879 0+-663 -1466 880 0+-664 -1466 881 0+-665 -1466 882 0+-666 -1466 883 0+-667 -1466 884 0+-668 -1466 885 0+-669 -1466 886 0+-670 -1466 887 0+-671 -1466 888 0+-672 -1466 889 0+-673 -1466 890 0+-674 -1466 891 0+-675 -1466 892 0+-676 -1466 893 0+-677 -1466 894 0+-678 -1466 895 0+-679 -1466 896 0+-680 -1466 897 0+-681 -1466 898 0+-682 -1466 899 0+-683 -1466 900 0+-649 -1467 902 0+-650 -1467 903 0+-651 -1467 904 0+-652 -1467 905 0+-653 -1467 906 0+-654 -1467 907 0+-655 -1467 908 0+-656 -1467 909 0+-657 -1467 910 0+-658 -1467 911 0+-659 -1467 912 0+-660 -1467 913 0+-661 -1467 914 0+-662 -1467 915 0+-663 -1467 916 0+-664 -1467 917 0+-665 -1467 918 0+-666 -1467 919 0+-667 -1467 920 0+-668 -1467 921 0+-669 -1467 922 0+-670 -1467 923 0+-671 -1467 924 0+-672 -1467 925 0+-673 -1467 926 0+-674 -1467 927 0+-675 -1467 928 0+-676 -1467 929 0+-677 -1467 930 0+-678 -1467 931 0+-679 -1467 932 0+-680 -1467 933 0+-681 -1467 934 0+-682 -1467 935 0+-683 -1467 936 0+-1460 -1461 0+-1460 -2375 0+-1461 -2375 0+-1464 -1466 0+-1464 -1467 0+-1464 2375 0+-1466 -1467 0+-1466 2375 0+-1467 2375 0+1460 1461 1464 1466 1467 0+-685 -1468 434 0+-686 -1468 435 0+-687 -1468 436 0+-688 -1468 437 0+-689 -1468 438 0+-690 -1468 439 0+-691 -1468 440 0+-692 -1468 441 0+-693 -1468 442 0+-694 -1468 443 0+-695 -1468 444 0+-696 -1468 445 0+-697 -1468 446 0+-698 -1468 447 0+-699 -1468 448 0+-700 -1468 449 0+-701 -1468 450 0+-702 -1468 451 0+-703 -1468 452 0+-704 -1468 453 0+-705 -1468 454 0+-706 -1468 455 0+-707 -1468 456 0+-708 -1468 457 0+-709 -1468 458 0+-710 -1468 459 0+-711 -1468 460 0+-712 -1468 461 0+-713 -1468 462 0+-714 -1468 463 0+-715 -1468 464 0+-716 -1468 465 0+-717 -1468 466 0+-718 -1468 467 0+-719 -1468 468 0+-685 -1469 470 0+-686 -1469 471 0+-687 -1469 472 0+-688 -1469 473 0+-689 -1469 474 0+-690 -1469 475 0+-691 -1469 476 0+-692 -1469 477 0+-693 -1469 478 0+-694 -1469 479 0+-695 -1469 480 0+-696 -1469 481 0+-697 -1469 482 0+-698 -1469 483 0+-699 -1469 484 0+-700 -1469 485 0+-701 -1469 486 0+-702 -1469 487 0+-703 -1469 488 0+-704 -1469 489 0+-705 -1469 490 0+-706 -1469 491 0+-707 -1469 492 0+-708 -1469 493 0+-709 -1469 494 0+-710 -1469 495 0+-711 -1469 496 0+-712 -1469 497 0+-713 -1469 498 0+-714 -1469 499 0+-715 -1469 500 0+-716 -1469 501 0+-717 -1469 502 0+-718 -1469 503 0+-719 -1469 504 0+-685 -1470 506 0+-686 -1470 507 0+-687 -1470 508 0+-688 -1470 509 0+-689 -1470 510 0+-690 -1470 511 0+-691 -1470 512 0+-692 -1470 513 0+-693 -1470 514 0+-694 -1470 515 0+-695 -1470 516 0+-696 -1470 517 0+-697 -1470 518 0+-698 -1470 519 0+-699 -1470 520 0+-700 -1470 521 0+-701 -1470 522 0+-702 -1470 523 0+-703 -1470 524 0+-704 -1470 525 0+-705 -1470 526 0+-706 -1470 527 0+-707 -1470 528 0+-708 -1470 529 0+-709 -1470 530 0+-710 -1470 531 0+-711 -1470 532 0+-712 -1470 533 0+-713 -1470 534 0+-714 -1470 535 0+-715 -1470 536 0+-716 -1470 537 0+-717 -1470 538 0+-718 -1470 539 0+-719 -1470 540 0+-685 -1471 650 0+-686 -1471 651 0+-687 -1471 652 0+-688 -1471 653 0+-689 -1471 654 0+-690 -1471 655 0+-691 -1471 656 0+-692 -1471 657 0+-693 -1471 658 0+-694 -1471 659 0+-695 -1471 660 0+-696 -1471 661 0+-697 -1471 662 0+-698 -1471 663 0+-699 -1471 664 0+-700 -1471 665 0+-701 -1471 666 0+-702 -1471 667 0+-703 -1471 668 0+-704 -1471 669 0+-705 -1471 670 0+-706 -1471 671 0+-707 -1471 672 0+-708 -1471 673 0+-709 -1471 674 0+-710 -1471 675 0+-711 -1471 676 0+-712 -1471 677 0+-713 -1471 678 0+-714 -1471 679 0+-715 -1471 680 0+-716 -1471 681 0+-717 -1471 682 0+-718 -1471 683 0+-719 -1471 684 0+-685 -1473 722 0+-686 -1473 723 0+-687 -1473 724 0+-688 -1473 725 0+-689 -1473 726 0+-690 -1473 727 0+-691 -1473 728 0+-692 -1473 729 0+-693 -1473 730 0+-694 -1473 731 0+-695 -1473 732 0+-696 -1473 733 0+-697 -1473 734 0+-698 -1473 735 0+-699 -1473 736 0+-700 -1473 737 0+-701 -1473 738 0+-702 -1473 739 0+-703 -1473 740 0+-704 -1473 741 0+-705 -1473 742 0+-706 -1473 743 0+-707 -1473 744 0+-708 -1473 745 0+-709 -1473 746 0+-710 -1473 747 0+-711 -1473 748 0+-712 -1473 749 0+-713 -1473 750 0+-714 -1473 751 0+-715 -1473 752 0+-716 -1473 753 0+-717 -1473 754 0+-718 -1473 755 0+-719 -1473 756 0+-685 -1474 866 0+-686 -1474 867 0+-687 -1474 868 0+-688 -1474 869 0+-689 -1474 870 0+-690 -1474 871 0+-691 -1474 872 0+-692 -1474 873 0+-693 -1474 874 0+-694 -1474 875 0+-695 -1474 876 0+-696 -1474 877 0+-697 -1474 878 0+-698 -1474 879 0+-699 -1474 880 0+-700 -1474 881 0+-701 -1474 882 0+-702 -1474 883 0+-703 -1474 884 0+-704 -1474 885 0+-705 -1474 886 0+-706 -1474 887 0+-707 -1474 888 0+-708 -1474 889 0+-709 -1474 890 0+-710 -1474 891 0+-711 -1474 892 0+-712 -1474 893 0+-713 -1474 894 0+-714 -1474 895 0+-715 -1474 896 0+-716 -1474 897 0+-717 -1474 898 0+-718 -1474 899 0+-719 -1474 900 0+-685 -1475 902 0+-686 -1475 903 0+-687 -1475 904 0+-688 -1475 905 0+-689 -1475 906 0+-690 -1475 907 0+-691 -1475 908 0+-692 -1475 909 0+-693 -1475 910 0+-694 -1475 911 0+-695 -1475 912 0+-696 -1475 913 0+-697 -1475 914 0+-698 -1475 915 0+-699 -1475 916 0+-700 -1475 917 0+-701 -1475 918 0+-702 -1475 919 0+-703 -1475 920 0+-704 -1475 921 0+-705 -1475 922 0+-706 -1475 923 0+-707 -1475 924 0+-708 -1475 925 0+-709 -1475 926 0+-710 -1475 927 0+-711 -1475 928 0+-712 -1475 929 0+-713 -1475 930 0+-714 -1475 931 0+-715 -1475 932 0+-716 -1475 933 0+-717 -1475 934 0+-718 -1475 935 0+-719 -1475 936 0+-685 -1476 938 0+-686 -1476 939 0+-687 -1476 940 0+-688 -1476 941 0+-689 -1476 942 0+-690 -1476 943 0+-691 -1476 944 0+-692 -1476 945 0+-693 -1476 946 0+-694 -1476 947 0+-695 -1476 948 0+-696 -1476 949 0+-697 -1476 950 0+-698 -1476 951 0+-699 -1476 952 0+-700 -1476 953 0+-701 -1476 954 0+-702 -1476 955 0+-703 -1476 956 0+-704 -1476 957 0+-705 -1476 958 0+-706 -1476 959 0+-707 -1476 960 0+-708 -1476 961 0+-709 -1476 962 0+-710 -1476 963 0+-711 -1476 964 0+-712 -1476 965 0+-713 -1476 966 0+-714 -1476 967 0+-715 -1476 968 0+-716 -1476 969 0+-717 -1476 970 0+-718 -1476 971 0+-719 -1476 972 0+-1468 -1469 0+-1468 -2385 0+-1469 -2385 0+-1470 -1471 0+-1470 -2384 0+-1470 2385 0+-1471 -2384 0+-1471 2385 0+-2384 2385 0+-1473 -1474 0+-1473 -2386 0+-1474 -2386 0+-1475 -1476 0+-1475 2384 0+-1475 2386 0+-1476 2384 0+-1476 2386 0+2384 2386 0+1468 1469 1470 1471 1473 1474 1475 1476 0+-721 -1477 470 0+-722 -1477 471 0+-723 -1477 472 0+-724 -1477 473 0+-725 -1477 474 0+-726 -1477 475 0+-727 -1477 476 0+-728 -1477 477 0+-729 -1477 478 0+-730 -1477 479 0+-731 -1477 480 0+-732 -1477 481 0+-733 -1477 482 0+-734 -1477 483 0+-735 -1477 484 0+-736 -1477 485 0+-737 -1477 486 0+-738 -1477 487 0+-739 -1477 488 0+-740 -1477 489 0+-741 -1477 490 0+-742 -1477 491 0+-743 -1477 492 0+-744 -1477 493 0+-745 -1477 494 0+-746 -1477 495 0+-747 -1477 496 0+-748 -1477 497 0+-749 -1477 498 0+-750 -1477 499 0+-751 -1477 500 0+-752 -1477 501 0+-753 -1477 502 0+-754 -1477 503 0+-755 -1477 504 0+-721 -1478 506 0+-722 -1478 507 0+-723 -1478 508 0+-724 -1478 509 0+-725 -1478 510 0+-726 -1478 511 0+-727 -1478 512 0+-728 -1478 513 0+-729 -1478 514 0+-730 -1478 515 0+-731 -1478 516 0+-732 -1478 517 0+-733 -1478 518 0+-734 -1478 519 0+-735 -1478 520 0+-736 -1478 521 0+-737 -1478 522 0+-738 -1478 523 0+-739 -1478 524 0+-740 -1478 525 0+-741 -1478 526 0+-742 -1478 527 0+-743 -1478 528 0+-744 -1478 529 0+-745 -1478 530 0+-746 -1478 531 0+-747 -1478 532 0+-748 -1478 533 0+-749 -1478 534 0+-750 -1478 535 0+-751 -1478 536 0+-752 -1478 537 0+-753 -1478 538 0+-754 -1478 539 0+-755 -1478 540 0+-721 -1479 542 0+-722 -1479 543 0+-723 -1479 544 0+-724 -1479 545 0+-725 -1479 546 0+-726 -1479 547 0+-727 -1479 548 0+-728 -1479 549 0+-729 -1479 550 0+-730 -1479 551 0+-731 -1479 552 0+-732 -1479 553 0+-733 -1479 554 0+-734 -1479 555 0+-735 -1479 556 0+-736 -1479 557 0+-737 -1479 558 0+-738 -1479 559 0+-739 -1479 560 0+-740 -1479 561 0+-741 -1479 562 0+-742 -1479 563 0+-743 -1479 564 0+-744 -1479 565 0+-745 -1479 566 0+-746 -1479 567 0+-747 -1479 568 0+-748 -1479 569 0+-749 -1479 570 0+-750 -1479 571 0+-751 -1479 572 0+-752 -1479 573 0+-753 -1479 574 0+-754 -1479 575 0+-755 -1479 576 0+-721 -1480 686 0+-722 -1480 687 0+-723 -1480 688 0+-724 -1480 689 0+-725 -1480 690 0+-726 -1480 691 0+-727 -1480 692 0+-728 -1480 693 0+-729 -1480 694 0+-730 -1480 695 0+-731 -1480 696 0+-732 -1480 697 0+-733 -1480 698 0+-734 -1480 699 0+-735 -1480 700 0+-736 -1480 701 0+-737 -1480 702 0+-738 -1480 703 0+-739 -1480 704 0+-740 -1480 705 0+-741 -1480 706 0+-742 -1480 707 0+-743 -1480 708 0+-744 -1480 709 0+-745 -1480 710 0+-746 -1480 711 0+-747 -1480 712 0+-748 -1480 713 0+-749 -1480 714 0+-750 -1480 715 0+-751 -1480 716 0+-752 -1480 717 0+-753 -1480 718 0+-754 -1480 719 0+-755 -1480 720 0+-721 -1482 758 0+-722 -1482 759 0+-723 -1482 760 0+-724 -1482 761 0+-725 -1482 762 0+-726 -1482 763 0+-727 -1482 764 0+-728 -1482 765 0+-729 -1482 766 0+-730 -1482 767 0+-731 -1482 768 0+-732 -1482 769 0+-733 -1482 770 0+-734 -1482 771 0+-735 -1482 772 0+-736 -1482 773 0+-737 -1482 774 0+-738 -1482 775 0+-739 -1482 776 0+-740 -1482 777 0+-741 -1482 778 0+-742 -1482 779 0+-743 -1482 780 0+-744 -1482 781 0+-745 -1482 782 0+-746 -1482 783 0+-747 -1482 784 0+-748 -1482 785 0+-749 -1482 786 0+-750 -1482 787 0+-751 -1482 788 0+-752 -1482 789 0+-753 -1482 790 0+-754 -1482 791 0+-755 -1482 792 0+-721 -1483 902 0+-722 -1483 903 0+-723 -1483 904 0+-724 -1483 905 0+-725 -1483 906 0+-726 -1483 907 0+-727 -1483 908 0+-728 -1483 909 0+-729 -1483 910 0+-730 -1483 911 0+-731 -1483 912 0+-732 -1483 913 0+-733 -1483 914 0+-734 -1483 915 0+-735 -1483 916 0+-736 -1483 917 0+-737 -1483 918 0+-738 -1483 919 0+-739 -1483 920 0+-740 -1483 921 0+-741 -1483 922 0+-742 -1483 923 0+-743 -1483 924 0+-744 -1483 925 0+-745 -1483 926 0+-746 -1483 927 0+-747 -1483 928 0+-748 -1483 929 0+-749 -1483 930 0+-750 -1483 931 0+-751 -1483 932 0+-752 -1483 933 0+-753 -1483 934 0+-754 -1483 935 0+-755 -1483 936 0+-721 -1484 938 0+-722 -1484 939 0+-723 -1484 940 0+-724 -1484 941 0+-725 -1484 942 0+-726 -1484 943 0+-727 -1484 944 0+-728 -1484 945 0+-729 -1484 946 0+-730 -1484 947 0+-731 -1484 948 0+-732 -1484 949 0+-733 -1484 950 0+-734 -1484 951 0+-735 -1484 952 0+-736 -1484 953 0+-737 -1484 954 0+-738 -1484 955 0+-739 -1484 956 0+-740 -1484 957 0+-741 -1484 958 0+-742 -1484 959 0+-743 -1484 960 0+-744 -1484 961 0+-745 -1484 962 0+-746 -1484 963 0+-747 -1484 964 0+-748 -1484 965 0+-749 -1484 966 0+-750 -1484 967 0+-751 -1484 968 0+-752 -1484 969 0+-753 -1484 970 0+-754 -1484 971 0+-755 -1484 972 0+-721 -1485 974 0+-722 -1485 975 0+-723 -1485 976 0+-724 -1485 977 0+-725 -1485 978 0+-726 -1485 979 0+-727 -1485 980 0+-728 -1485 981 0+-729 -1485 982 0+-730 -1485 983 0+-731 -1485 984 0+-732 -1485 985 0+-733 -1485 986 0+-734 -1485 987 0+-735 -1485 988 0+-736 -1485 989 0+-737 -1485 990 0+-738 -1485 991 0+-739 -1485 992 0+-740 -1485 993 0+-741 -1485 994 0+-742 -1485 995 0+-743 -1485 996 0+-744 -1485 997 0+-745 -1485 998 0+-746 -1485 999 0+-747 -1485 1000 0+-748 -1485 1001 0+-749 -1485 1002 0+-750 -1485 1003 0+-751 -1485 1004 0+-752 -1485 1005 0+-753 -1485 1006 0+-754 -1485 1007 0+-755 -1485 1008 0+-1477 -1478 0+-1477 -2396 0+-1478 -2396 0+-1479 -1480 0+-1479 -2395 0+-1479 2396 0+-1480 -2395 0+-1480 2396 0+-2395 2396 0+-1482 -1483 0+-1482 -2397 0+-1483 -2397 0+-1484 -1485 0+-1484 2395 0+-1484 2397 0+-1485 2395 0+-1485 2397 0+2395 2397 0+1477 1478 1479 1480 1482 1483 1484 1485 0+-757 -1486 506 0+-758 -1486 507 0+-759 -1486 508 0+-760 -1486 509 0+-761 -1486 510 0+-762 -1486 511 0+-763 -1486 512 0+-764 -1486 513 0+-765 -1486 514 0+-766 -1486 515 0+-767 -1486 516 0+-768 -1486 517 0+-769 -1486 518 0+-770 -1486 519 0+-771 -1486 520 0+-772 -1486 521 0+-773 -1486 522 0+-774 -1486 523 0+-775 -1486 524 0+-776 -1486 525 0+-777 -1486 526 0+-778 -1486 527 0+-779 -1486 528 0+-780 -1486 529 0+-781 -1486 530 0+-782 -1486 531 0+-783 -1486 532 0+-784 -1486 533 0+-785 -1486 534 0+-786 -1486 535 0+-787 -1486 536 0+-788 -1486 537 0+-789 -1486 538 0+-790 -1486 539 0+-791 -1486 540 0+-757 -1487 542 0+-758 -1487 543 0+-759 -1487 544 0+-760 -1487 545 0+-761 -1487 546 0+-762 -1487 547 0+-763 -1487 548 0+-764 -1487 549 0+-765 -1487 550 0+-766 -1487 551 0+-767 -1487 552 0+-768 -1487 553 0+-769 -1487 554 0+-770 -1487 555 0+-771 -1487 556 0+-772 -1487 557 0+-773 -1487 558 0+-774 -1487 559 0+-775 -1487 560 0+-776 -1487 561 0+-777 -1487 562 0+-778 -1487 563 0+-779 -1487 564 0+-780 -1487 565 0+-781 -1487 566 0+-782 -1487 567 0+-783 -1487 568 0+-784 -1487 569 0+-785 -1487 570 0+-786 -1487 571 0+-787 -1487 572 0+-788 -1487 573 0+-789 -1487 574 0+-790 -1487 575 0+-791 -1487 576 0+-757 -1488 578 0+-758 -1488 579 0+-759 -1488 580 0+-760 -1488 581 0+-761 -1488 582 0+-762 -1488 583 0+-763 -1488 584 0+-764 -1488 585 0+-765 -1488 586 0+-766 -1488 587 0+-767 -1488 588 0+-768 -1488 589 0+-769 -1488 590 0+-770 -1488 591 0+-771 -1488 592 0+-772 -1488 593 0+-773 -1488 594 0+-774 -1488 595 0+-775 -1488 596 0+-776 -1488 597 0+-777 -1488 598 0+-778 -1488 599 0+-779 -1488 600 0+-780 -1488 601 0+-781 -1488 602 0+-782 -1488 603 0+-783 -1488 604 0+-784 -1488 605 0+-785 -1488 606 0+-786 -1488 607 0+-787 -1488 608 0+-788 -1488 609 0+-789 -1488 610 0+-790 -1488 611 0+-791 -1488 612 0+-757 -1489 722 0+-758 -1489 723 0+-759 -1489 724 0+-760 -1489 725 0+-761 -1489 726 0+-762 -1489 727 0+-763 -1489 728 0+-764 -1489 729 0+-765 -1489 730 0+-766 -1489 731 0+-767 -1489 732 0+-768 -1489 733 0+-769 -1489 734 0+-770 -1489 735 0+-771 -1489 736 0+-772 -1489 737 0+-773 -1489 738 0+-774 -1489 739 0+-775 -1489 740 0+-776 -1489 741 0+-777 -1489 742 0+-778 -1489 743 0+-779 -1489 744 0+-780 -1489 745 0+-781 -1489 746 0+-782 -1489 747 0+-783 -1489 748 0+-784 -1489 749 0+-785 -1489 750 0+-786 -1489 751 0+-787 -1489 752 0+-788 -1489 753 0+-789 -1489 754 0+-790 -1489 755 0+-791 -1489 756 0+-757 -1491 794 0+-758 -1491 795 0+-759 -1491 796 0+-760 -1491 797 0+-761 -1491 798 0+-762 -1491 799 0+-763 -1491 800 0+-764 -1491 801 0+-765 -1491 802 0+-766 -1491 803 0+-767 -1491 804 0+-768 -1491 805 0+-769 -1491 806 0+-770 -1491 807 0+-771 -1491 808 0+-772 -1491 809 0+-773 -1491 810 0+-774 -1491 811 0+-775 -1491 812 0+-776 -1491 813 0+-777 -1491 814 0+-778 -1491 815 0+-779 -1491 816 0+-780 -1491 817 0+-781 -1491 818 0+-782 -1491 819 0+-783 -1491 820 0+-784 -1491 821 0+-785 -1491 822 0+-786 -1491 823 0+-787 -1491 824 0+-788 -1491 825 0+-789 -1491 826 0+-790 -1491 827 0+-791 -1491 828 0+-757 -1492 938 0+-758 -1492 939 0+-759 -1492 940 0+-760 -1492 941 0+-761 -1492 942 0+-762 -1492 943 0+-763 -1492 944 0+-764 -1492 945 0+-765 -1492 946 0+-766 -1492 947 0+-767 -1492 948 0+-768 -1492 949 0+-769 -1492 950 0+-770 -1492 951 0+-771 -1492 952 0+-772 -1492 953 0+-773 -1492 954 0+-774 -1492 955 0+-775 -1492 956 0+-776 -1492 957 0+-777 -1492 958 0+-778 -1492 959 0+-779 -1492 960 0+-780 -1492 961 0+-781 -1492 962 0+-782 -1492 963 0+-783 -1492 964 0+-784 -1492 965 0+-785 -1492 966 0+-786 -1492 967 0+-787 -1492 968 0+-788 -1492 969 0+-789 -1492 970 0+-790 -1492 971 0+-791 -1492 972 0+-757 -1493 974 0+-758 -1493 975 0+-759 -1493 976 0+-760 -1493 977 0+-761 -1493 978 0+-762 -1493 979 0+-763 -1493 980 0+-764 -1493 981 0+-765 -1493 982 0+-766 -1493 983 0+-767 -1493 984 0+-768 -1493 985 0+-769 -1493 986 0+-770 -1493 987 0+-771 -1493 988 0+-772 -1493 989 0+-773 -1493 990 0+-774 -1493 991 0+-775 -1493 992 0+-776 -1493 993 0+-777 -1493 994 0+-778 -1493 995 0+-779 -1493 996 0+-780 -1493 997 0+-781 -1493 998 0+-782 -1493 999 0+-783 -1493 1000 0+-784 -1493 1001 0+-785 -1493 1002 0+-786 -1493 1003 0+-787 -1493 1004 0+-788 -1493 1005 0+-789 -1493 1006 0+-790 -1493 1007 0+-791 -1493 1008 0+-757 -1494 1010 0+-758 -1494 1011 0+-759 -1494 1012 0+-760 -1494 1013 0+-761 -1494 1014 0+-762 -1494 1015 0+-763 -1494 1016 0+-764 -1494 1017 0+-765 -1494 1018 0+-766 -1494 1019 0+-767 -1494 1020 0+-768 -1494 1021 0+-769 -1494 1022 0+-770 -1494 1023 0+-771 -1494 1024 0+-772 -1494 1025 0+-773 -1494 1026 0+-774 -1494 1027 0+-775 -1494 1028 0+-776 -1494 1029 0+-777 -1494 1030 0+-778 -1494 1031 0+-779 -1494 1032 0+-780 -1494 1033 0+-781 -1494 1034 0+-782 -1494 1035 0+-783 -1494 1036 0+-784 -1494 1037 0+-785 -1494 1038 0+-786 -1494 1039 0+-787 -1494 1040 0+-788 -1494 1041 0+-789 -1494 1042 0+-790 -1494 1043 0+-791 -1494 1044 0+-1486 -1487 0+-1486 -2407 0+-1487 -2407 0+-1488 -1489 0+-1488 -2406 0+-1488 2407 0+-1489 -2406 0+-1489 2407 0+-2406 2407 0+-1491 -1492 0+-1491 -2408 0+-1492 -2408 0+-1493 -1494 0+-1493 2406 0+-1493 2408 0+-1494 2406 0+-1494 2408 0+2406 2408 0+1486 1487 1488 1489 1491 1492 1493 1494 0+-793 -1495 542 0+-794 -1495 543 0+-795 -1495 544 0+-796 -1495 545 0+-797 -1495 546 0+-798 -1495 547 0+-799 -1495 548 0+-800 -1495 549 0+-801 -1495 550 0+-802 -1495 551 0+-803 -1495 552 0+-804 -1495 553 0+-805 -1495 554 0+-806 -1495 555 0+-807 -1495 556 0+-808 -1495 557 0+-809 -1495 558 0+-810 -1495 559 0+-811 -1495 560 0+-812 -1495 561 0+-813 -1495 562 0+-814 -1495 563 0+-815 -1495 564 0+-816 -1495 565 0+-817 -1495 566 0+-818 -1495 567 0+-819 -1495 568 0+-820 -1495 569 0+-821 -1495 570 0+-822 -1495 571 0+-823 -1495 572 0+-824 -1495 573 0+-825 -1495 574 0+-826 -1495 575 0+-827 -1495 576 0+-793 -1496 578 0+-794 -1496 579 0+-795 -1496 580 0+-796 -1496 581 0+-797 -1496 582 0+-798 -1496 583 0+-799 -1496 584 0+-800 -1496 585 0+-801 -1496 586 0+-802 -1496 587 0+-803 -1496 588 0+-804 -1496 589 0+-805 -1496 590 0+-806 -1496 591 0+-807 -1496 592 0+-808 -1496 593 0+-809 -1496 594 0+-810 -1496 595 0+-811 -1496 596 0+-812 -1496 597 0+-813 -1496 598 0+-814 -1496 599 0+-815 -1496 600 0+-816 -1496 601 0+-817 -1496 602 0+-818 -1496 603 0+-819 -1496 604 0+-820 -1496 605 0+-821 -1496 606 0+-822 -1496 607 0+-823 -1496 608 0+-824 -1496 609 0+-825 -1496 610 0+-826 -1496 611 0+-827 -1496 612 0+-793 -1497 614 0+-794 -1497 615 0+-795 -1497 616 0+-796 -1497 617 0+-797 -1497 618 0+-798 -1497 619 0+-799 -1497 620 0+-800 -1497 621 0+-801 -1497 622 0+-802 -1497 623 0+-803 -1497 624 0+-804 -1497 625 0+-805 -1497 626 0+-806 -1497 627 0+-807 -1497 628 0+-808 -1497 629 0+-809 -1497 630 0+-810 -1497 631 0+-811 -1497 632 0+-812 -1497 633 0+-813 -1497 634 0+-814 -1497 635 0+-815 -1497 636 0+-816 -1497 637 0+-817 -1497 638 0+-818 -1497 639 0+-819 -1497 640 0+-820 -1497 641 0+-821 -1497 642 0+-822 -1497 643 0+-823 -1497 644 0+-824 -1497 645 0+-825 -1497 646 0+-826 -1497 647 0+-827 -1497 648 0+-793 -1498 758 0+-794 -1498 759 0+-795 -1498 760 0+-796 -1498 761 0+-797 -1498 762 0+-798 -1498 763 0+-799 -1498 764 0+-800 -1498 765 0+-801 -1498 766 0+-802 -1498 767 0+-803 -1498 768 0+-804 -1498 769 0+-805 -1498 770 0+-806 -1498 771 0+-807 -1498 772 0+-808 -1498 773 0+-809 -1498 774 0+-810 -1498 775 0+-811 -1498 776 0+-812 -1498 777 0+-813 -1498 778 0+-814 -1498 779 0+-815 -1498 780 0+-816 -1498 781 0+-817 -1498 782 0+-818 -1498 783 0+-819 -1498 784 0+-820 -1498 785 0+-821 -1498 786 0+-822 -1498 787 0+-823 -1498 788 0+-824 -1498 789 0+-825 -1498 790 0+-826 -1498 791 0+-827 -1498 792 0+-793 -1500 830 0+-794 -1500 831 0+-795 -1500 832 0+-796 -1500 833 0+-797 -1500 834 0+-798 -1500 835 0+-799 -1500 836 0+-800 -1500 837 0+-801 -1500 838 0+-802 -1500 839 0+-803 -1500 840 0+-804 -1500 841 0+-805 -1500 842 0+-806 -1500 843 0+-807 -1500 844 0+-808 -1500 845 0+-809 -1500 846 0+-810 -1500 847 0+-811 -1500 848 0+-812 -1500 849 0+-813 -1500 850 0+-814 -1500 851 0+-815 -1500 852 0+-816 -1500 853 0+-817 -1500 854 0+-818 -1500 855 0+-819 -1500 856 0+-820 -1500 857 0+-821 -1500 858 0+-822 -1500 859 0+-823 -1500 860 0+-824 -1500 861 0+-825 -1500 862 0+-826 -1500 863 0+-827 -1500 864 0+-793 -1501 974 0+-794 -1501 975 0+-795 -1501 976 0+-796 -1501 977 0+-797 -1501 978 0+-798 -1501 979 0+-799 -1501 980 0+-800 -1501 981 0+-801 -1501 982 0+-802 -1501 983 0+-803 -1501 984 0+-804 -1501 985 0+-805 -1501 986 0+-806 -1501 987 0+-807 -1501 988 0+-808 -1501 989 0+-809 -1501 990 0+-810 -1501 991 0+-811 -1501 992 0+-812 -1501 993 0+-813 -1501 994 0+-814 -1501 995 0+-815 -1501 996 0+-816 -1501 997 0+-817 -1501 998 0+-818 -1501 999 0+-819 -1501 1000 0+-820 -1501 1001 0+-821 -1501 1002 0+-822 -1501 1003 0+-823 -1501 1004 0+-824 -1501 1005 0+-825 -1501 1006 0+-826 -1501 1007 0+-827 -1501 1008 0+-793 -1502 1010 0+-794 -1502 1011 0+-795 -1502 1012 0+-796 -1502 1013 0+-797 -1502 1014 0+-798 -1502 1015 0+-799 -1502 1016 0+-800 -1502 1017 0+-801 -1502 1018 0+-802 -1502 1019 0+-803 -1502 1020 0+-804 -1502 1021 0+-805 -1502 1022 0+-806 -1502 1023 0+-807 -1502 1024 0+-808 -1502 1025 0+-809 -1502 1026 0+-810 -1502 1027 0+-811 -1502 1028 0+-812 -1502 1029 0+-813 -1502 1030 0+-814 -1502 1031 0+-815 -1502 1032 0+-816 -1502 1033 0+-817 -1502 1034 0+-818 -1502 1035 0+-819 -1502 1036 0+-820 -1502 1037 0+-821 -1502 1038 0+-822 -1502 1039 0+-823 -1502 1040 0+-824 -1502 1041 0+-825 -1502 1042 0+-826 -1502 1043 0+-827 -1502 1044 0+-793 -1503 1046 0+-794 -1503 1047 0+-795 -1503 1048 0+-796 -1503 1049 0+-797 -1503 1050 0+-798 -1503 1051 0+-799 -1503 1052 0+-800 -1503 1053 0+-801 -1503 1054 0+-802 -1503 1055 0+-803 -1503 1056 0+-804 -1503 1057 0+-805 -1503 1058 0+-806 -1503 1059 0+-807 -1503 1060 0+-808 -1503 1061 0+-809 -1503 1062 0+-810 -1503 1063 0+-811 -1503 1064 0+-812 -1503 1065 0+-813 -1503 1066 0+-814 -1503 1067 0+-815 -1503 1068 0+-816 -1503 1069 0+-817 -1503 1070 0+-818 -1503 1071 0+-819 -1503 1072 0+-820 -1503 1073 0+-821 -1503 1074 0+-822 -1503 1075 0+-823 -1503 1076 0+-824 -1503 1077 0+-825 -1503 1078 0+-826 -1503 1079 0+-827 -1503 1080 0+-1495 -1496 0+-1495 -2418 0+-1496 -2418 0+-1497 -1498 0+-1497 -2417 0+-1497 2418 0+-1498 -2417 0+-1498 2418 0+-2417 2418 0+-1500 -1501 0+-1500 -2419 0+-1501 -2419 0+-1502 -1503 0+-1502 2417 0+-1502 2419 0+-1503 2417 0+-1503 2419 0+2417 2419 0+1495 1496 1497 1498 1500 1501 1502 1503 0+-829 -1504 578 0+-830 -1504 579 0+-831 -1504 580 0+-832 -1504 581 0+-833 -1504 582 0+-834 -1504 583 0+-835 -1504 584 0+-836 -1504 585 0+-837 -1504 586 0+-838 -1504 587 0+-839 -1504 588 0+-840 -1504 589 0+-841 -1504 590 0+-842 -1504 591 0+-843 -1504 592 0+-844 -1504 593 0+-845 -1504 594 0+-846 -1504 595 0+-847 -1504 596 0+-848 -1504 597 0+-849 -1504 598 0+-850 -1504 599 0+-851 -1504 600 0+-852 -1504 601 0+-853 -1504 602 0+-854 -1504 603 0+-855 -1504 604 0+-856 -1504 605 0+-857 -1504 606 0+-858 -1504 607 0+-859 -1504 608 0+-860 -1504 609 0+-861 -1504 610 0+-862 -1504 611 0+-863 -1504 612 0+-829 -1505 614 0+-830 -1505 615 0+-831 -1505 616 0+-832 -1505 617 0+-833 -1505 618 0+-834 -1505 619 0+-835 -1505 620 0+-836 -1505 621 0+-837 -1505 622 0+-838 -1505 623 0+-839 -1505 624 0+-840 -1505 625 0+-841 -1505 626 0+-842 -1505 627 0+-843 -1505 628 0+-844 -1505 629 0+-845 -1505 630 0+-846 -1505 631 0+-847 -1505 632 0+-848 -1505 633 0+-849 -1505 634 0+-850 -1505 635 0+-851 -1505 636 0+-852 -1505 637 0+-853 -1505 638 0+-854 -1505 639 0+-855 -1505 640 0+-856 -1505 641 0+-857 -1505 642 0+-858 -1505 643 0+-859 -1505 644 0+-860 -1505 645 0+-861 -1505 646 0+-862 -1505 647 0+-863 -1505 648 0+-829 -1507 794 0+-830 -1507 795 0+-831 -1507 796 0+-832 -1507 797 0+-833 -1507 798 0+-834 -1507 799 0+-835 -1507 800 0+-836 -1507 801 0+-837 -1507 802 0+-838 -1507 803 0+-839 -1507 804 0+-840 -1507 805 0+-841 -1507 806 0+-842 -1507 807 0+-843 -1507 808 0+-844 -1507 809 0+-845 -1507 810 0+-846 -1507 811 0+-847 -1507 812 0+-848 -1507 813 0+-849 -1507 814 0+-850 -1507 815 0+-851 -1507 816 0+-852 -1507 817 0+-853 -1507 818 0+-854 -1507 819 0+-855 -1507 820 0+-856 -1507 821 0+-857 -1507 822 0+-858 -1507 823 0+-859 -1507 824 0+-860 -1507 825 0+-861 -1507 826 0+-862 -1507 827 0+-863 -1507 828 0+-829 -1510 1010 0+-830 -1510 1011 0+-831 -1510 1012 0+-832 -1510 1013 0+-833 -1510 1014 0+-834 -1510 1015 0+-835 -1510 1016 0+-836 -1510 1017 0+-837 -1510 1018 0+-838 -1510 1019 0+-839 -1510 1020 0+-840 -1510 1021 0+-841 -1510 1022 0+-842 -1510 1023 0+-843 -1510 1024 0+-844 -1510 1025 0+-845 -1510 1026 0+-846 -1510 1027 0+-847 -1510 1028 0+-848 -1510 1029 0+-849 -1510 1030 0+-850 -1510 1031 0+-851 -1510 1032 0+-852 -1510 1033 0+-853 -1510 1034 0+-854 -1510 1035 0+-855 -1510 1036 0+-856 -1510 1037 0+-857 -1510 1038 0+-858 -1510 1039 0+-859 -1510 1040 0+-860 -1510 1041 0+-861 -1510 1042 0+-862 -1510 1043 0+-863 -1510 1044 0+-829 -1511 1046 0+-830 -1511 1047 0+-831 -1511 1048 0+-832 -1511 1049 0+-833 -1511 1050 0+-834 -1511 1051 0+-835 -1511 1052 0+-836 -1511 1053 0+-837 -1511 1054 0+-838 -1511 1055 0+-839 -1511 1056 0+-840 -1511 1057 0+-841 -1511 1058 0+-842 -1511 1059 0+-843 -1511 1060 0+-844 -1511 1061 0+-845 -1511 1062 0+-846 -1511 1063 0+-847 -1511 1064 0+-848 -1511 1065 0+-849 -1511 1066 0+-850 -1511 1067 0+-851 -1511 1068 0+-852 -1511 1069 0+-853 -1511 1070 0+-854 -1511 1071 0+-855 -1511 1072 0+-856 -1511 1073 0+-857 -1511 1074 0+-858 -1511 1075 0+-859 -1511 1076 0+-860 -1511 1077 0+-861 -1511 1078 0+-862 -1511 1079 0+-863 -1511 1080 0+-1504 -1505 0+-1504 -2425 0+-1505 -2425 0+-1507 -1510 0+-1507 -1511 0+-1507 2425 0+-1510 -1511 0+-1510 2425 0+-1511 2425 0+1504 1505 1507 1510 1511 0+-865 -1514 650 0+-866 -1514 651 0+-867 -1514 652 0+-868 -1514 653 0+-869 -1514 654 0+-870 -1514 655 0+-871 -1514 656 0+-872 -1514 657 0+-873 -1514 658 0+-874 -1514 659 0+-875 -1514 660 0+-876 -1514 661 0+-877 -1514 662 0+-878 -1514 663 0+-879 -1514 664 0+-880 -1514 665 0+-881 -1514 666 0+-882 -1514 667 0+-883 -1514 668 0+-884 -1514 669 0+-885 -1514 670 0+-886 -1514 671 0+-887 -1514 672 0+-888 -1514 673 0+-889 -1514 674 0+-890 -1514 675 0+-891 -1514 676 0+-892 -1514 677 0+-893 -1514 678 0+-894 -1514 679 0+-895 -1514 680 0+-896 -1514 681 0+-897 -1514 682 0+-898 -1514 683 0+-899 -1514 684 0+-865 -1515 686 0+-866 -1515 687 0+-867 -1515 688 0+-868 -1515 689 0+-869 -1515 690 0+-870 -1515 691 0+-871 -1515 692 0+-872 -1515 693 0+-873 -1515 694 0+-874 -1515 695 0+-875 -1515 696 0+-876 -1515 697 0+-877 -1515 698 0+-878 -1515 699 0+-879 -1515 700 0+-880 -1515 701 0+-881 -1515 702 0+-882 -1515 703 0+-883 -1515 704 0+-884 -1515 705 0+-885 -1515 706 0+-886 -1515 707 0+-887 -1515 708 0+-888 -1515 709 0+-889 -1515 710 0+-890 -1515 711 0+-891 -1515 712 0+-892 -1515 713 0+-893 -1515 714 0+-894 -1515 715 0+-895 -1515 716 0+-896 -1515 717 0+-897 -1515 718 0+-898 -1515 719 0+-899 -1515 720 0+-865 -1518 902 0+-866 -1518 903 0+-867 -1518 904 0+-868 -1518 905 0+-869 -1518 906 0+-870 -1518 907 0+-871 -1518 908 0+-872 -1518 909 0+-873 -1518 910 0+-874 -1518 911 0+-875 -1518 912 0+-876 -1518 913 0+-877 -1518 914 0+-878 -1518 915 0+-879 -1518 916 0+-880 -1518 917 0+-881 -1518 918 0+-882 -1518 919 0+-883 -1518 920 0+-884 -1518 921 0+-885 -1518 922 0+-886 -1518 923 0+-887 -1518 924 0+-888 -1518 925 0+-889 -1518 926 0+-890 -1518 927 0+-891 -1518 928 0+-892 -1518 929 0+-893 -1518 930 0+-894 -1518 931 0+-895 -1518 932 0+-896 -1518 933 0+-897 -1518 934 0+-898 -1518 935 0+-899 -1518 936 0+-865 -1520 1082 0+-866 -1520 1083 0+-867 -1520 1084 0+-868 -1520 1085 0+-869 -1520 1086 0+-870 -1520 1087 0+-871 -1520 1088 0+-872 -1520 1089 0+-873 -1520 1090 0+-874 -1520 1091 0+-875 -1520 1092 0+-876 -1520 1093 0+-877 -1520 1094 0+-878 -1520 1095 0+-879 -1520 1096 0+-880 -1520 1097 0+-881 -1520 1098 0+-882 -1520 1099 0+-883 -1520 1100 0+-884 -1520 1101 0+-885 -1520 1102 0+-886 -1520 1103 0+-887 -1520 1104 0+-888 -1520 1105 0+-889 -1520 1106 0+-890 -1520 1107 0+-891 -1520 1108 0+-892 -1520 1109 0+-893 -1520 1110 0+-894 -1520 1111 0+-895 -1520 1112 0+-896 -1520 1113 0+-897 -1520 1114 0+-898 -1520 1115 0+-899 -1520 1116 0+-865 -1521 1118 0+-866 -1521 1119 0+-867 -1521 1120 0+-868 -1521 1121 0+-869 -1521 1122 0+-870 -1521 1123 0+-871 -1521 1124 0+-872 -1521 1125 0+-873 -1521 1126 0+-874 -1521 1127 0+-875 -1521 1128 0+-876 -1521 1129 0+-877 -1521 1130 0+-878 -1521 1131 0+-879 -1521 1132 0+-880 -1521 1133 0+-881 -1521 1134 0+-882 -1521 1135 0+-883 -1521 1136 0+-884 -1521 1137 0+-885 -1521 1138 0+-886 -1521 1139 0+-887 -1521 1140 0+-888 -1521 1141 0+-889 -1521 1142 0+-890 -1521 1143 0+-891 -1521 1144 0+-892 -1521 1145 0+-893 -1521 1146 0+-894 -1521 1147 0+-895 -1521 1148 0+-896 -1521 1149 0+-897 -1521 1150 0+-898 -1521 1151 0+-899 -1521 1152 0+-1514 -1515 0+-1514 -2431 0+-1515 -2431 0+-1518 -1520 0+-1518 -1521 0+-1518 2431 0+-1520 -1521 0+-1520 2431 0+-1521 2431 0+1514 1515 1518 1520 1521 0+-901 -1522 650 0+-902 -1522 651 0+-903 -1522 652 0+-904 -1522 653 0+-905 -1522 654 0+-906 -1522 655 0+-907 -1522 656 0+-908 -1522 657 0+-909 -1522 658 0+-910 -1522 659 0+-911 -1522 660 0+-912 -1522 661 0+-913 -1522 662 0+-914 -1522 663 0+-915 -1522 664 0+-916 -1522 665 0+-917 -1522 666 0+-918 -1522 667 0+-919 -1522 668 0+-920 -1522 669 0+-921 -1522 670 0+-922 -1522 671 0+-923 -1522 672 0+-924 -1522 673 0+-925 -1522 674 0+-926 -1522 675 0+-927 -1522 676 0+-928 -1522 677 0+-929 -1522 678 0+-930 -1522 679 0+-931 -1522 680 0+-932 -1522 681 0+-933 -1522 682 0+-934 -1522 683 0+-935 -1522 684 0+-901 -1523 686 0+-902 -1523 687 0+-903 -1523 688 0+-904 -1523 689 0+-905 -1523 690 0+-906 -1523 691 0+-907 -1523 692 0+-908 -1523 693 0+-909 -1523 694 0+-910 -1523 695 0+-911 -1523 696 0+-912 -1523 697 0+-913 -1523 698 0+-914 -1523 699 0+-915 -1523 700 0+-916 -1523 701 0+-917 -1523 702 0+-918 -1523 703 0+-919 -1523 704 0+-920 -1523 705 0+-921 -1523 706 0+-922 -1523 707 0+-923 -1523 708 0+-924 -1523 709 0+-925 -1523 710 0+-926 -1523 711 0+-927 -1523 712 0+-928 -1523 713 0+-929 -1523 714 0+-930 -1523 715 0+-931 -1523 716 0+-932 -1523 717 0+-933 -1523 718 0+-934 -1523 719 0+-935 -1523 720 0+-901 -1524 722 0+-902 -1524 723 0+-903 -1524 724 0+-904 -1524 725 0+-905 -1524 726 0+-906 -1524 727 0+-907 -1524 728 0+-908 -1524 729 0+-909 -1524 730 0+-910 -1524 731 0+-911 -1524 732 0+-912 -1524 733 0+-913 -1524 734 0+-914 -1524 735 0+-915 -1524 736 0+-916 -1524 737 0+-917 -1524 738 0+-918 -1524 739 0+-919 -1524 740 0+-920 -1524 741 0+-921 -1524 742 0+-922 -1524 743 0+-923 -1524 744 0+-924 -1524 745 0+-925 -1524 746 0+-926 -1524 747 0+-927 -1524 748 0+-928 -1524 749 0+-929 -1524 750 0+-930 -1524 751 0+-931 -1524 752 0+-932 -1524 753 0+-933 -1524 754 0+-934 -1524 755 0+-935 -1524 756 0+-901 -1525 866 0+-902 -1525 867 0+-903 -1525 868 0+-904 -1525 869 0+-905 -1525 870 0+-906 -1525 871 0+-907 -1525 872 0+-908 -1525 873 0+-909 -1525 874 0+-910 -1525 875 0+-911 -1525 876 0+-912 -1525 877 0+-913 -1525 878 0+-914 -1525 879 0+-915 -1525 880 0+-916 -1525 881 0+-917 -1525 882 0+-918 -1525 883 0+-919 -1525 884 0+-920 -1525 885 0+-921 -1525 886 0+-922 -1525 887 0+-923 -1525 888 0+-924 -1525 889 0+-925 -1525 890 0+-926 -1525 891 0+-927 -1525 892 0+-928 -1525 893 0+-929 -1525 894 0+-930 -1525 895 0+-931 -1525 896 0+-932 -1525 897 0+-933 -1525 898 0+-934 -1525 899 0+-935 -1525 900 0+-901 -1527 938 0+-902 -1527 939 0+-903 -1527 940 0+-904 -1527 941 0+-905 -1527 942 0+-906 -1527 943 0+-907 -1527 944 0+-908 -1527 945 0+-909 -1527 946 0+-910 -1527 947 0+-911 -1527 948 0+-912 -1527 949 0+-913 -1527 950 0+-914 -1527 951 0+-915 -1527 952 0+-916 -1527 953 0+-917 -1527 954 0+-918 -1527 955 0+-919 -1527 956 0+-920 -1527 957 0+-921 -1527 958 0+-922 -1527 959 0+-923 -1527 960 0+-924 -1527 961 0+-925 -1527 962 0+-926 -1527 963 0+-927 -1527 964 0+-928 -1527 965 0+-929 -1527 966 0+-930 -1527 967 0+-931 -1527 968 0+-932 -1527 969 0+-933 -1527 970 0+-934 -1527 971 0+-935 -1527 972 0+-901 -1528 1082 0+-902 -1528 1083 0+-903 -1528 1084 0+-904 -1528 1085 0+-905 -1528 1086 0+-906 -1528 1087 0+-907 -1528 1088 0+-908 -1528 1089 0+-909 -1528 1090 0+-910 -1528 1091 0+-911 -1528 1092 0+-912 -1528 1093 0+-913 -1528 1094 0+-914 -1528 1095 0+-915 -1528 1096 0+-916 -1528 1097 0+-917 -1528 1098 0+-918 -1528 1099 0+-919 -1528 1100 0+-920 -1528 1101 0+-921 -1528 1102 0+-922 -1528 1103 0+-923 -1528 1104 0+-924 -1528 1105 0+-925 -1528 1106 0+-926 -1528 1107 0+-927 -1528 1108 0+-928 -1528 1109 0+-929 -1528 1110 0+-930 -1528 1111 0+-931 -1528 1112 0+-932 -1528 1113 0+-933 -1528 1114 0+-934 -1528 1115 0+-935 -1528 1116 0+-901 -1529 1118 0+-902 -1529 1119 0+-903 -1529 1120 0+-904 -1529 1121 0+-905 -1529 1122 0+-906 -1529 1123 0+-907 -1529 1124 0+-908 -1529 1125 0+-909 -1529 1126 0+-910 -1529 1127 0+-911 -1529 1128 0+-912 -1529 1129 0+-913 -1529 1130 0+-914 -1529 1131 0+-915 -1529 1132 0+-916 -1529 1133 0+-917 -1529 1134 0+-918 -1529 1135 0+-919 -1529 1136 0+-920 -1529 1137 0+-921 -1529 1138 0+-922 -1529 1139 0+-923 -1529 1140 0+-924 -1529 1141 0+-925 -1529 1142 0+-926 -1529 1143 0+-927 -1529 1144 0+-928 -1529 1145 0+-929 -1529 1146 0+-930 -1529 1147 0+-931 -1529 1148 0+-932 -1529 1149 0+-933 -1529 1150 0+-934 -1529 1151 0+-935 -1529 1152 0+-901 -1530 1154 0+-902 -1530 1155 0+-903 -1530 1156 0+-904 -1530 1157 0+-905 -1530 1158 0+-906 -1530 1159 0+-907 -1530 1160 0+-908 -1530 1161 0+-909 -1530 1162 0+-910 -1530 1163 0+-911 -1530 1164 0+-912 -1530 1165 0+-913 -1530 1166 0+-914 -1530 1167 0+-915 -1530 1168 0+-916 -1530 1169 0+-917 -1530 1170 0+-918 -1530 1171 0+-919 -1530 1172 0+-920 -1530 1173 0+-921 -1530 1174 0+-922 -1530 1175 0+-923 -1530 1176 0+-924 -1530 1177 0+-925 -1530 1178 0+-926 -1530 1179 0+-927 -1530 1180 0+-928 -1530 1181 0+-929 -1530 1182 0+-930 -1530 1183 0+-931 -1530 1184 0+-932 -1530 1185 0+-933 -1530 1186 0+-934 -1530 1187 0+-935 -1530 1188 0+-1522 -1523 0+-1522 -2441 0+-1523 -2441 0+-1524 -1525 0+-1524 -2440 0+-1524 2441 0+-1525 -2440 0+-1525 2441 0+-2440 2441 0+-1527 -1528 0+-1527 -2442 0+-1528 -2442 0+-1529 -1530 0+-1529 2440 0+-1529 2442 0+-1530 2440 0+-1530 2442 0+2440 2442 0+1522 1523 1524 1525 1527 1528 1529 1530 0+-937 -1531 686 0+-938 -1531 687 0+-939 -1531 688 0+-940 -1531 689 0+-941 -1531 690 0+-942 -1531 691 0+-943 -1531 692 0+-944 -1531 693 0+-945 -1531 694 0+-946 -1531 695 0+-947 -1531 696 0+-948 -1531 697 0+-949 -1531 698 0+-950 -1531 699 0+-951 -1531 700 0+-952 -1531 701 0+-953 -1531 702 0+-954 -1531 703 0+-955 -1531 704 0+-956 -1531 705 0+-957 -1531 706 0+-958 -1531 707 0+-959 -1531 708 0+-960 -1531 709 0+-961 -1531 710 0+-962 -1531 711 0+-963 -1531 712 0+-964 -1531 713 0+-965 -1531 714 0+-966 -1531 715 0+-967 -1531 716 0+-968 -1531 717 0+-969 -1531 718 0+-970 -1531 719 0+-971 -1531 720 0+-937 -1532 722 0+-938 -1532 723 0+-939 -1532 724 0+-940 -1532 725 0+-941 -1532 726 0+-942 -1532 727 0+-943 -1532 728 0+-944 -1532 729 0+-945 -1532 730 0+-946 -1532 731 0+-947 -1532 732 0+-948 -1532 733 0+-949 -1532 734 0+-950 -1532 735 0+-951 -1532 736 0+-952 -1532 737 0+-953 -1532 738 0+-954 -1532 739 0+-955 -1532 740 0+-956 -1532 741 0+-957 -1532 742 0+-958 -1532 743 0+-959 -1532 744 0+-960 -1532 745 0+-961 -1532 746 0+-962 -1532 747 0+-963 -1532 748 0+-964 -1532 749 0+-965 -1532 750 0+-966 -1532 751 0+-967 -1532 752 0+-968 -1532 753 0+-969 -1532 754 0+-970 -1532 755 0+-971 -1532 756 0+-937 -1533 758 0+-938 -1533 759 0+-939 -1533 760 0+-940 -1533 761 0+-941 -1533 762 0+-942 -1533 763 0+-943 -1533 764 0+-944 -1533 765 0+-945 -1533 766 0+-946 -1533 767 0+-947 -1533 768 0+-948 -1533 769 0+-949 -1533 770 0+-950 -1533 771 0+-951 -1533 772 0+-952 -1533 773 0+-953 -1533 774 0+-954 -1533 775 0+-955 -1533 776 0+-956 -1533 777 0+-957 -1533 778 0+-958 -1533 779 0+-959 -1533 780 0+-960 -1533 781 0+-961 -1533 782 0+-962 -1533 783 0+-963 -1533 784 0+-964 -1533 785 0+-965 -1533 786 0+-966 -1533 787 0+-967 -1533 788 0+-968 -1533 789 0+-969 -1533 790 0+-970 -1533 791 0+-971 -1533 792 0+-937 -1534 902 0+-938 -1534 903 0+-939 -1534 904 0+-940 -1534 905 0+-941 -1534 906 0+-942 -1534 907 0+-943 -1534 908 0+-944 -1534 909 0+-945 -1534 910 0+-946 -1534 911 0+-947 -1534 912 0+-948 -1534 913 0+-949 -1534 914 0+-950 -1534 915 0+-951 -1534 916 0+-952 -1534 917 0+-953 -1534 918 0+-954 -1534 919 0+-955 -1534 920 0+-956 -1534 921 0+-957 -1534 922 0+-958 -1534 923 0+-959 -1534 924 0+-960 -1534 925 0+-961 -1534 926 0+-962 -1534 927 0+-963 -1534 928 0+-964 -1534 929 0+-965 -1534 930 0+-966 -1534 931 0+-967 -1534 932 0+-968 -1534 933 0+-969 -1534 934 0+-970 -1534 935 0+-971 -1534 936 0+-937 -1536 974 0+-938 -1536 975 0+-939 -1536 976 0+-940 -1536 977 0+-941 -1536 978 0+-942 -1536 979 0+-943 -1536 980 0+-944 -1536 981 0+-945 -1536 982 0+-946 -1536 983 0+-947 -1536 984 0+-948 -1536 985 0+-949 -1536 986 0+-950 -1536 987 0+-951 -1536 988 0+-952 -1536 989 0+-953 -1536 990 0+-954 -1536 991 0+-955 -1536 992 0+-956 -1536 993 0+-957 -1536 994 0+-958 -1536 995 0+-959 -1536 996 0+-960 -1536 997 0+-961 -1536 998 0+-962 -1536 999 0+-963 -1536 1000 0+-964 -1536 1001 0+-965 -1536 1002 0+-966 -1536 1003 0+-967 -1536 1004 0+-968 -1536 1005 0+-969 -1536 1006 0+-970 -1536 1007 0+-971 -1536 1008 0+-937 -1537 1118 0+-938 -1537 1119 0+-939 -1537 1120 0+-940 -1537 1121 0+-941 -1537 1122 0+-942 -1537 1123 0+-943 -1537 1124 0+-944 -1537 1125 0+-945 -1537 1126 0+-946 -1537 1127 0+-947 -1537 1128 0+-948 -1537 1129 0+-949 -1537 1130 0+-950 -1537 1131 0+-951 -1537 1132 0+-952 -1537 1133 0+-953 -1537 1134 0+-954 -1537 1135 0+-955 -1537 1136 0+-956 -1537 1137 0+-957 -1537 1138 0+-958 -1537 1139 0+-959 -1537 1140 0+-960 -1537 1141 0+-961 -1537 1142 0+-962 -1537 1143 0+-963 -1537 1144 0+-964 -1537 1145 0+-965 -1537 1146 0+-966 -1537 1147 0+-967 -1537 1148 0+-968 -1537 1149 0+-969 -1537 1150 0+-970 -1537 1151 0+-971 -1537 1152 0+-937 -1538 1154 0+-938 -1538 1155 0+-939 -1538 1156 0+-940 -1538 1157 0+-941 -1538 1158 0+-942 -1538 1159 0+-943 -1538 1160 0+-944 -1538 1161 0+-945 -1538 1162 0+-946 -1538 1163 0+-947 -1538 1164 0+-948 -1538 1165 0+-949 -1538 1166 0+-950 -1538 1167 0+-951 -1538 1168 0+-952 -1538 1169 0+-953 -1538 1170 0+-954 -1538 1171 0+-955 -1538 1172 0+-956 -1538 1173 0+-957 -1538 1174 0+-958 -1538 1175 0+-959 -1538 1176 0+-960 -1538 1177 0+-961 -1538 1178 0+-962 -1538 1179 0+-963 -1538 1180 0+-964 -1538 1181 0+-965 -1538 1182 0+-966 -1538 1183 0+-967 -1538 1184 0+-968 -1538 1185 0+-969 -1538 1186 0+-970 -1538 1187 0+-971 -1538 1188 0+-937 -1539 1190 0+-938 -1539 1191 0+-939 -1539 1192 0+-940 -1539 1193 0+-941 -1539 1194 0+-942 -1539 1195 0+-943 -1539 1196 0+-944 -1539 1197 0+-945 -1539 1198 0+-946 -1539 1199 0+-947 -1539 1200 0+-948 -1539 1201 0+-949 -1539 1202 0+-950 -1539 1203 0+-951 -1539 1204 0+-952 -1539 1205 0+-953 -1539 1206 0+-954 -1539 1207 0+-955 -1539 1208 0+-956 -1539 1209 0+-957 -1539 1210 0+-958 -1539 1211 0+-959 -1539 1212 0+-960 -1539 1213 0+-961 -1539 1214 0+-962 -1539 1215 0+-963 -1539 1216 0+-964 -1539 1217 0+-965 -1539 1218 0+-966 -1539 1219 0+-967 -1539 1220 0+-968 -1539 1221 0+-969 -1539 1222 0+-970 -1539 1223 0+-971 -1539 1224 0+-1531 -1532 0+-1531 -2452 0+-1532 -2452 0+-1533 -1534 0+-1533 -2451 0+-1533 2452 0+-1534 -2451 0+-1534 2452 0+-2451 2452 0+-1536 -1537 0+-1536 -2453 0+-1537 -2453 0+-1538 -1539 0+-1538 2451 0+-1538 2453 0+-1539 2451 0+-1539 2453 0+2451 2453 0+1531 1532 1533 1534 1536 1537 1538 1539 0+-973 -1540 722 0+-974 -1540 723 0+-975 -1540 724 0+-976 -1540 725 0+-977 -1540 726 0+-978 -1540 727 0+-979 -1540 728 0+-980 -1540 729 0+-981 -1540 730 0+-982 -1540 731 0+-983 -1540 732 0+-984 -1540 733 0+-985 -1540 734 0+-986 -1540 735 0+-987 -1540 736 0+-988 -1540 737 0+-989 -1540 738 0+-990 -1540 739 0+-991 -1540 740 0+-992 -1540 741 0+-993 -1540 742 0+-994 -1540 743 0+-995 -1540 744 0+-996 -1540 745 0+-997 -1540 746 0+-998 -1540 747 0+-999 -1540 748 0+-1000 -1540 749 0+-1001 -1540 750 0+-1002 -1540 751 0+-1003 -1540 752 0+-1004 -1540 753 0+-1005 -1540 754 0+-1006 -1540 755 0+-1007 -1540 756 0+-973 -1541 758 0+-974 -1541 759 0+-975 -1541 760 0+-976 -1541 761 0+-977 -1541 762 0+-978 -1541 763 0+-979 -1541 764 0+-980 -1541 765 0+-981 -1541 766 0+-982 -1541 767 0+-983 -1541 768 0+-984 -1541 769 0+-985 -1541 770 0+-986 -1541 771 0+-987 -1541 772 0+-988 -1541 773 0+-989 -1541 774 0+-990 -1541 775 0+-991 -1541 776 0+-992 -1541 777 0+-993 -1541 778 0+-994 -1541 779 0+-995 -1541 780 0+-996 -1541 781 0+-997 -1541 782 0+-998 -1541 783 0+-999 -1541 784 0+-1000 -1541 785 0+-1001 -1541 786 0+-1002 -1541 787 0+-1003 -1541 788 0+-1004 -1541 789 0+-1005 -1541 790 0+-1006 -1541 791 0+-1007 -1541 792 0+-973 -1542 794 0+-974 -1542 795 0+-975 -1542 796 0+-976 -1542 797 0+-977 -1542 798 0+-978 -1542 799 0+-979 -1542 800 0+-980 -1542 801 0+-981 -1542 802 0+-982 -1542 803 0+-983 -1542 804 0+-984 -1542 805 0+-985 -1542 806 0+-986 -1542 807 0+-987 -1542 808 0+-988 -1542 809 0+-989 -1542 810 0+-990 -1542 811 0+-991 -1542 812 0+-992 -1542 813 0+-993 -1542 814 0+-994 -1542 815 0+-995 -1542 816 0+-996 -1542 817 0+-997 -1542 818 0+-998 -1542 819 0+-999 -1542 820 0+-1000 -1542 821 0+-1001 -1542 822 0+-1002 -1542 823 0+-1003 -1542 824 0+-1004 -1542 825 0+-1005 -1542 826 0+-1006 -1542 827 0+-1007 -1542 828 0+-973 -1543 938 0+-974 -1543 939 0+-975 -1543 940 0+-976 -1543 941 0+-977 -1543 942 0+-978 -1543 943 0+-979 -1543 944 0+-980 -1543 945 0+-981 -1543 946 0+-982 -1543 947 0+-983 -1543 948 0+-984 -1543 949 0+-985 -1543 950 0+-986 -1543 951 0+-987 -1543 952 0+-988 -1543 953 0+-989 -1543 954 0+-990 -1543 955 0+-991 -1543 956 0+-992 -1543 957 0+-993 -1543 958 0+-994 -1543 959 0+-995 -1543 960 0+-996 -1543 961 0+-997 -1543 962 0+-998 -1543 963 0+-999 -1543 964 0+-1000 -1543 965 0+-1001 -1543 966 0+-1002 -1543 967 0+-1003 -1543 968 0+-1004 -1543 969 0+-1005 -1543 970 0+-1006 -1543 971 0+-1007 -1543 972 0+-973 -1545 1010 0+-974 -1545 1011 0+-975 -1545 1012 0+-976 -1545 1013 0+-977 -1545 1014 0+-978 -1545 1015 0+-979 -1545 1016 0+-980 -1545 1017 0+-981 -1545 1018 0+-982 -1545 1019 0+-983 -1545 1020 0+-984 -1545 1021 0+-985 -1545 1022 0+-986 -1545 1023 0+-987 -1545 1024 0+-988 -1545 1025 0+-989 -1545 1026 0+-990 -1545 1027 0+-991 -1545 1028 0+-992 -1545 1029 0+-993 -1545 1030 0+-994 -1545 1031 0+-995 -1545 1032 0+-996 -1545 1033 0+-997 -1545 1034 0+-998 -1545 1035 0+-999 -1545 1036 0+-1000 -1545 1037 0+-1001 -1545 1038 0+-1002 -1545 1039 0+-1003 -1545 1040 0+-1004 -1545 1041 0+-1005 -1545 1042 0+-1006 -1545 1043 0+-1007 -1545 1044 0+-973 -1546 1154 0+-974 -1546 1155 0+-975 -1546 1156 0+-976 -1546 1157 0+-977 -1546 1158 0+-978 -1546 1159 0+-979 -1546 1160 0+-980 -1546 1161 0+-981 -1546 1162 0+-982 -1546 1163 0+-983 -1546 1164 0+-984 -1546 1165 0+-985 -1546 1166 0+-986 -1546 1167 0+-987 -1546 1168 0+-988 -1546 1169 0+-989 -1546 1170 0+-990 -1546 1171 0+-991 -1546 1172 0+-992 -1546 1173 0+-993 -1546 1174 0+-994 -1546 1175 0+-995 -1546 1176 0+-996 -1546 1177 0+-997 -1546 1178 0+-998 -1546 1179 0+-999 -1546 1180 0+-1000 -1546 1181 0+-1001 -1546 1182 0+-1002 -1546 1183 0+-1003 -1546 1184 0+-1004 -1546 1185 0+-1005 -1546 1186 0+-1006 -1546 1187 0+-1007 -1546 1188 0+-973 -1547 1190 0+-974 -1547 1191 0+-975 -1547 1192 0+-976 -1547 1193 0+-977 -1547 1194 0+-978 -1547 1195 0+-979 -1547 1196 0+-980 -1547 1197 0+-981 -1547 1198 0+-982 -1547 1199 0+-983 -1547 1200 0+-984 -1547 1201 0+-985 -1547 1202 0+-986 -1547 1203 0+-987 -1547 1204 0+-988 -1547 1205 0+-989 -1547 1206 0+-990 -1547 1207 0+-991 -1547 1208 0+-992 -1547 1209 0+-993 -1547 1210 0+-994 -1547 1211 0+-995 -1547 1212 0+-996 -1547 1213 0+-997 -1547 1214 0+-998 -1547 1215 0+-999 -1547 1216 0+-1000 -1547 1217 0+-1001 -1547 1218 0+-1002 -1547 1219 0+-1003 -1547 1220 0+-1004 -1547 1221 0+-1005 -1547 1222 0+-1006 -1547 1223 0+-1007 -1547 1224 0+-973 -1548 1226 0+-974 -1548 1227 0+-975 -1548 1228 0+-976 -1548 1229 0+-977 -1548 1230 0+-978 -1548 1231 0+-979 -1548 1232 0+-980 -1548 1233 0+-981 -1548 1234 0+-982 -1548 1235 0+-983 -1548 1236 0+-984 -1548 1237 0+-985 -1548 1238 0+-986 -1548 1239 0+-987 -1548 1240 0+-988 -1548 1241 0+-989 -1548 1242 0+-990 -1548 1243 0+-991 -1548 1244 0+-992 -1548 1245 0+-993 -1548 1246 0+-994 -1548 1247 0+-995 -1548 1248 0+-996 -1548 1249 0+-997 -1548 1250 0+-998 -1548 1251 0+-999 -1548 1252 0+-1000 -1548 1253 0+-1001 -1548 1254 0+-1002 -1548 1255 0+-1003 -1548 1256 0+-1004 -1548 1257 0+-1005 -1548 1258 0+-1006 -1548 1259 0+-1007 -1548 1260 0+-1540 -1541 0+-1540 -2463 0+-1541 -2463 0+-1542 -1543 0+-1542 -2462 0+-1542 2463 0+-1543 -2462 0+-1543 2463 0+-2462 2463 0+-1545 -1546 0+-1545 -2464 0+-1546 -2464 0+-1547 -1548 0+-1547 2462 0+-1547 2464 0+-1548 2462 0+-1548 2464 0+2462 2464 0+1540 1541 1542 1543 1545 1546 1547 1548 0+-1009 -1549 758 0+-1010 -1549 759 0+-1011 -1549 760 0+-1012 -1549 761 0+-1013 -1549 762 0+-1014 -1549 763 0+-1015 -1549 764 0+-1016 -1549 765 0+-1017 -1549 766 0+-1018 -1549 767 0+-1019 -1549 768 0+-1020 -1549 769 0+-1021 -1549 770 0+-1022 -1549 771 0+-1023 -1549 772 0+-1024 -1549 773 0+-1025 -1549 774 0+-1026 -1549 775 0+-1027 -1549 776 0+-1028 -1549 777 0+-1029 -1549 778 0+-1030 -1549 779 0+-1031 -1549 780 0+-1032 -1549 781 0+-1033 -1549 782 0+-1034 -1549 783 0+-1035 -1549 784 0+-1036 -1549 785 0+-1037 -1549 786 0+-1038 -1549 787 0+-1039 -1549 788 0+-1040 -1549 789 0+-1041 -1549 790 0+-1042 -1549 791 0+-1043 -1549 792 0+-1009 -1550 794 0+-1010 -1550 795 0+-1011 -1550 796 0+-1012 -1550 797 0+-1013 -1550 798 0+-1014 -1550 799 0+-1015 -1550 800 0+-1016 -1550 801 0+-1017 -1550 802 0+-1018 -1550 803 0+-1019 -1550 804 0+-1020 -1550 805 0+-1021 -1550 806 0+-1022 -1550 807 0+-1023 -1550 808 0+-1024 -1550 809 0+-1025 -1550 810 0+-1026 -1550 811 0+-1027 -1550 812 0+-1028 -1550 813 0+-1029 -1550 814 0+-1030 -1550 815 0+-1031 -1550 816 0+-1032 -1550 817 0+-1033 -1550 818 0+-1034 -1550 819 0+-1035 -1550 820 0+-1036 -1550 821 0+-1037 -1550 822 0+-1038 -1550 823 0+-1039 -1550 824 0+-1040 -1550 825 0+-1041 -1550 826 0+-1042 -1550 827 0+-1043 -1550 828 0+-1009 -1551 830 0+-1010 -1551 831 0+-1011 -1551 832 0+-1012 -1551 833 0+-1013 -1551 834 0+-1014 -1551 835 0+-1015 -1551 836 0+-1016 -1551 837 0+-1017 -1551 838 0+-1018 -1551 839 0+-1019 -1551 840 0+-1020 -1551 841 0+-1021 -1551 842 0+-1022 -1551 843 0+-1023 -1551 844 0+-1024 -1551 845 0+-1025 -1551 846 0+-1026 -1551 847 0+-1027 -1551 848 0+-1028 -1551 849 0+-1029 -1551 850 0+-1030 -1551 851 0+-1031 -1551 852 0+-1032 -1551 853 0+-1033 -1551 854 0+-1034 -1551 855 0+-1035 -1551 856 0+-1036 -1551 857 0+-1037 -1551 858 0+-1038 -1551 859 0+-1039 -1551 860 0+-1040 -1551 861 0+-1041 -1551 862 0+-1042 -1551 863 0+-1043 -1551 864 0+-1009 -1552 974 0+-1010 -1552 975 0+-1011 -1552 976 0+-1012 -1552 977 0+-1013 -1552 978 0+-1014 -1552 979 0+-1015 -1552 980 0+-1016 -1552 981 0+-1017 -1552 982 0+-1018 -1552 983 0+-1019 -1552 984 0+-1020 -1552 985 0+-1021 -1552 986 0+-1022 -1552 987 0+-1023 -1552 988 0+-1024 -1552 989 0+-1025 -1552 990 0+-1026 -1552 991 0+-1027 -1552 992 0+-1028 -1552 993 0+-1029 -1552 994 0+-1030 -1552 995 0+-1031 -1552 996 0+-1032 -1552 997 0+-1033 -1552 998 0+-1034 -1552 999 0+-1035 -1552 1000 0+-1036 -1552 1001 0+-1037 -1552 1002 0+-1038 -1552 1003 0+-1039 -1552 1004 0+-1040 -1552 1005 0+-1041 -1552 1006 0+-1042 -1552 1007 0+-1043 -1552 1008 0+-1009 -1554 1046 0+-1010 -1554 1047 0+-1011 -1554 1048 0+-1012 -1554 1049 0+-1013 -1554 1050 0+-1014 -1554 1051 0+-1015 -1554 1052 0+-1016 -1554 1053 0+-1017 -1554 1054 0+-1018 -1554 1055 0+-1019 -1554 1056 0+-1020 -1554 1057 0+-1021 -1554 1058 0+-1022 -1554 1059 0+-1023 -1554 1060 0+-1024 -1554 1061 0+-1025 -1554 1062 0+-1026 -1554 1063 0+-1027 -1554 1064 0+-1028 -1554 1065 0+-1029 -1554 1066 0+-1030 -1554 1067 0+-1031 -1554 1068 0+-1032 -1554 1069 0+-1033 -1554 1070 0+-1034 -1554 1071 0+-1035 -1554 1072 0+-1036 -1554 1073 0+-1037 -1554 1074 0+-1038 -1554 1075 0+-1039 -1554 1076 0+-1040 -1554 1077 0+-1041 -1554 1078 0+-1042 -1554 1079 0+-1043 -1554 1080 0+-1009 -1555 1190 0+-1010 -1555 1191 0+-1011 -1555 1192 0+-1012 -1555 1193 0+-1013 -1555 1194 0+-1014 -1555 1195 0+-1015 -1555 1196 0+-1016 -1555 1197 0+-1017 -1555 1198 0+-1018 -1555 1199 0+-1019 -1555 1200 0+-1020 -1555 1201 0+-1021 -1555 1202 0+-1022 -1555 1203 0+-1023 -1555 1204 0+-1024 -1555 1205 0+-1025 -1555 1206 0+-1026 -1555 1207 0+-1027 -1555 1208 0+-1028 -1555 1209 0+-1029 -1555 1210 0+-1030 -1555 1211 0+-1031 -1555 1212 0+-1032 -1555 1213 0+-1033 -1555 1214 0+-1034 -1555 1215 0+-1035 -1555 1216 0+-1036 -1555 1217 0+-1037 -1555 1218 0+-1038 -1555 1219 0+-1039 -1555 1220 0+-1040 -1555 1221 0+-1041 -1555 1222 0+-1042 -1555 1223 0+-1043 -1555 1224 0+-1009 -1556 1226 0+-1010 -1556 1227 0+-1011 -1556 1228 0+-1012 -1556 1229 0+-1013 -1556 1230 0+-1014 -1556 1231 0+-1015 -1556 1232 0+-1016 -1556 1233 0+-1017 -1556 1234 0+-1018 -1556 1235 0+-1019 -1556 1236 0+-1020 -1556 1237 0+-1021 -1556 1238 0+-1022 -1556 1239 0+-1023 -1556 1240 0+-1024 -1556 1241 0+-1025 -1556 1242 0+-1026 -1556 1243 0+-1027 -1556 1244 0+-1028 -1556 1245 0+-1029 -1556 1246 0+-1030 -1556 1247 0+-1031 -1556 1248 0+-1032 -1556 1249 0+-1033 -1556 1250 0+-1034 -1556 1251 0+-1035 -1556 1252 0+-1036 -1556 1253 0+-1037 -1556 1254 0+-1038 -1556 1255 0+-1039 -1556 1256 0+-1040 -1556 1257 0+-1041 -1556 1258 0+-1042 -1556 1259 0+-1043 -1556 1260 0+-1009 -1557 1262 0+-1010 -1557 1263 0+-1011 -1557 1264 0+-1012 -1557 1265 0+-1013 -1557 1266 0+-1014 -1557 1267 0+-1015 -1557 1268 0+-1016 -1557 1269 0+-1017 -1557 1270 0+-1018 -1557 1271 0+-1019 -1557 1272 0+-1020 -1557 1273 0+-1021 -1557 1274 0+-1022 -1557 1275 0+-1023 -1557 1276 0+-1024 -1557 1277 0+-1025 -1557 1278 0+-1026 -1557 1279 0+-1027 -1557 1280 0+-1028 -1557 1281 0+-1029 -1557 1282 0+-1030 -1557 1283 0+-1031 -1557 1284 0+-1032 -1557 1285 0+-1033 -1557 1286 0+-1034 -1557 1287 0+-1035 -1557 1288 0+-1036 -1557 1289 0+-1037 -1557 1290 0+-1038 -1557 1291 0+-1039 -1557 1292 0+-1040 -1557 1293 0+-1041 -1557 1294 0+-1042 -1557 1295 0+-1043 -1557 1296 0+-1549 -1550 0+-1549 -2474 0+-1550 -2474 0+-1551 -1552 0+-1551 -2473 0+-1551 2474 0+-1552 -2473 0+-1552 2474 0+-2473 2474 0+-1554 -1555 0+-1554 -2475 0+-1555 -2475 0+-1556 -1557 0+-1556 2473 0+-1556 2475 0+-1557 2473 0+-1557 2475 0+2473 2475 0+1549 1550 1551 1552 1554 1555 1556 1557 0+-1045 -1558 794 0+-1046 -1558 795 0+-1047 -1558 796 0+-1048 -1558 797 0+-1049 -1558 798 0+-1050 -1558 799 0+-1051 -1558 800 0+-1052 -1558 801 0+-1053 -1558 802 0+-1054 -1558 803 0+-1055 -1558 804 0+-1056 -1558 805 0+-1057 -1558 806 0+-1058 -1558 807 0+-1059 -1558 808 0+-1060 -1558 809 0+-1061 -1558 810 0+-1062 -1558 811 0+-1063 -1558 812 0+-1064 -1558 813 0+-1065 -1558 814 0+-1066 -1558 815 0+-1067 -1558 816 0+-1068 -1558 817 0+-1069 -1558 818 0+-1070 -1558 819 0+-1071 -1558 820 0+-1072 -1558 821 0+-1073 -1558 822 0+-1074 -1558 823 0+-1075 -1558 824 0+-1076 -1558 825 0+-1077 -1558 826 0+-1078 -1558 827 0+-1079 -1558 828 0+-1045 -1559 830 0+-1046 -1559 831 0+-1047 -1559 832 0+-1048 -1559 833 0+-1049 -1559 834 0+-1050 -1559 835 0+-1051 -1559 836 0+-1052 -1559 837 0+-1053 -1559 838 0+-1054 -1559 839 0+-1055 -1559 840 0+-1056 -1559 841 0+-1057 -1559 842 0+-1058 -1559 843 0+-1059 -1559 844 0+-1060 -1559 845 0+-1061 -1559 846 0+-1062 -1559 847 0+-1063 -1559 848 0+-1064 -1559 849 0+-1065 -1559 850 0+-1066 -1559 851 0+-1067 -1559 852 0+-1068 -1559 853 0+-1069 -1559 854 0+-1070 -1559 855 0+-1071 -1559 856 0+-1072 -1559 857 0+-1073 -1559 858 0+-1074 -1559 859 0+-1075 -1559 860 0+-1076 -1559 861 0+-1077 -1559 862 0+-1078 -1559 863 0+-1079 -1559 864 0+-1045 -1561 1010 0+-1046 -1561 1011 0+-1047 -1561 1012 0+-1048 -1561 1013 0+-1049 -1561 1014 0+-1050 -1561 1015 0+-1051 -1561 1016 0+-1052 -1561 1017 0+-1053 -1561 1018 0+-1054 -1561 1019 0+-1055 -1561 1020 0+-1056 -1561 1021 0+-1057 -1561 1022 0+-1058 -1561 1023 0+-1059 -1561 1024 0+-1060 -1561 1025 0+-1061 -1561 1026 0+-1062 -1561 1027 0+-1063 -1561 1028 0+-1064 -1561 1029 0+-1065 -1561 1030 0+-1066 -1561 1031 0+-1067 -1561 1032 0+-1068 -1561 1033 0+-1069 -1561 1034 0+-1070 -1561 1035 0+-1071 -1561 1036 0+-1072 -1561 1037 0+-1073 -1561 1038 0+-1074 -1561 1039 0+-1075 -1561 1040 0+-1076 -1561 1041 0+-1077 -1561 1042 0+-1078 -1561 1043 0+-1079 -1561 1044 0+-1045 -1564 1226 0+-1046 -1564 1227 0+-1047 -1564 1228 0+-1048 -1564 1229 0+-1049 -1564 1230 0+-1050 -1564 1231 0+-1051 -1564 1232 0+-1052 -1564 1233 0+-1053 -1564 1234 0+-1054 -1564 1235 0+-1055 -1564 1236 0+-1056 -1564 1237 0+-1057 -1564 1238 0+-1058 -1564 1239 0+-1059 -1564 1240 0+-1060 -1564 1241 0+-1061 -1564 1242 0+-1062 -1564 1243 0+-1063 -1564 1244 0+-1064 -1564 1245 0+-1065 -1564 1246 0+-1066 -1564 1247 0+-1067 -1564 1248 0+-1068 -1564 1249 0+-1069 -1564 1250 0+-1070 -1564 1251 0+-1071 -1564 1252 0+-1072 -1564 1253 0+-1073 -1564 1254 0+-1074 -1564 1255 0+-1075 -1564 1256 0+-1076 -1564 1257 0+-1077 -1564 1258 0+-1078 -1564 1259 0+-1079 -1564 1260 0+-1045 -1565 1262 0+-1046 -1565 1263 0+-1047 -1565 1264 0+-1048 -1565 1265 0+-1049 -1565 1266 0+-1050 -1565 1267 0+-1051 -1565 1268 0+-1052 -1565 1269 0+-1053 -1565 1270 0+-1054 -1565 1271 0+-1055 -1565 1272 0+-1056 -1565 1273 0+-1057 -1565 1274 0+-1058 -1565 1275 0+-1059 -1565 1276 0+-1060 -1565 1277 0+-1061 -1565 1278 0+-1062 -1565 1279 0+-1063 -1565 1280 0+-1064 -1565 1281 0+-1065 -1565 1282 0+-1066 -1565 1283 0+-1067 -1565 1284 0+-1068 -1565 1285 0+-1069 -1565 1286 0+-1070 -1565 1287 0+-1071 -1565 1288 0+-1072 -1565 1289 0+-1073 -1565 1290 0+-1074 -1565 1291 0+-1075 -1565 1292 0+-1076 -1565 1293 0+-1077 -1565 1294 0+-1078 -1565 1295 0+-1079 -1565 1296 0+-1558 -1559 0+-1558 -2481 0+-1559 -2481 0+-1561 -1564 0+-1561 -1565 0+-1561 2481 0+-1564 -1565 0+-1564 2481 0+-1565 2481 0+1558 1559 1561 1564 1565 0+-1081 -1568 866 0+-1082 -1568 867 0+-1083 -1568 868 0+-1084 -1568 869 0+-1085 -1568 870 0+-1086 -1568 871 0+-1087 -1568 872 0+-1088 -1568 873 0+-1089 -1568 874 0+-1090 -1568 875 0+-1091 -1568 876 0+-1092 -1568 877 0+-1093 -1568 878 0+-1094 -1568 879 0+-1095 -1568 880 0+-1096 -1568 881 0+-1097 -1568 882 0+-1098 -1568 883 0+-1099 -1568 884 0+-1100 -1568 885 0+-1101 -1568 886 0+-1102 -1568 887 0+-1103 -1568 888 0+-1104 -1568 889 0+-1105 -1568 890 0+-1106 -1568 891 0+-1107 -1568 892 0+-1108 -1568 893 0+-1109 -1568 894 0+-1110 -1568 895 0+-1111 -1568 896 0+-1112 -1568 897 0+-1113 -1568 898 0+-1114 -1568 899 0+-1115 -1568 900 0+-1081 -1569 902 0+-1082 -1569 903 0+-1083 -1569 904 0+-1084 -1569 905 0+-1085 -1569 906 0+-1086 -1569 907 0+-1087 -1569 908 0+-1088 -1569 909 0+-1089 -1569 910 0+-1090 -1569 911 0+-1091 -1569 912 0+-1092 -1569 913 0+-1093 -1569 914 0+-1094 -1569 915 0+-1095 -1569 916 0+-1096 -1569 917 0+-1097 -1569 918 0+-1098 -1569 919 0+-1099 -1569 920 0+-1100 -1569 921 0+-1101 -1569 922 0+-1102 -1569 923 0+-1103 -1569 924 0+-1104 -1569 925 0+-1105 -1569 926 0+-1106 -1569 927 0+-1107 -1569 928 0+-1108 -1569 929 0+-1109 -1569 930 0+-1110 -1569 931 0+-1111 -1569 932 0+-1112 -1569 933 0+-1113 -1569 934 0+-1114 -1569 935 0+-1115 -1569 936 0+-1081 -1572 1118 0+-1082 -1572 1119 0+-1083 -1572 1120 0+-1084 -1572 1121 0+-1085 -1572 1122 0+-1086 -1572 1123 0+-1087 -1572 1124 0+-1088 -1572 1125 0+-1089 -1572 1126 0+-1090 -1572 1127 0+-1091 -1572 1128 0+-1092 -1572 1129 0+-1093 -1572 1130 0+-1094 -1572 1131 0+-1095 -1572 1132 0+-1096 -1572 1133 0+-1097 -1572 1134 0+-1098 -1572 1135 0+-1099 -1572 1136 0+-1100 -1572 1137 0+-1101 -1572 1138 0+-1102 -1572 1139 0+-1103 -1572 1140 0+-1104 -1572 1141 0+-1105 -1572 1142 0+-1106 -1572 1143 0+-1107 -1572 1144 0+-1108 -1572 1145 0+-1109 -1572 1146 0+-1110 -1572 1147 0+-1111 -1572 1148 0+-1112 -1572 1149 0+-1113 -1572 1150 0+-1114 -1572 1151 0+-1115 -1572 1152 0+-1568 -1569 0+-1568 -1572 0+-1569 -1572 0+1568 1569 1572 0+-1117 -1576 866 0+-1118 -1576 867 0+-1119 -1576 868 0+-1120 -1576 869 0+-1121 -1576 870 0+-1122 -1576 871 0+-1123 -1576 872 0+-1124 -1576 873 0+-1125 -1576 874 0+-1126 -1576 875 0+-1127 -1576 876 0+-1128 -1576 877 0+-1129 -1576 878 0+-1130 -1576 879 0+-1131 -1576 880 0+-1132 -1576 881 0+-1133 -1576 882 0+-1134 -1576 883 0+-1135 -1576 884 0+-1136 -1576 885 0+-1137 -1576 886 0+-1138 -1576 887 0+-1139 -1576 888 0+-1140 -1576 889 0+-1141 -1576 890 0+-1142 -1576 891 0+-1143 -1576 892 0+-1144 -1576 893 0+-1145 -1576 894 0+-1146 -1576 895 0+-1147 -1576 896 0+-1148 -1576 897 0+-1149 -1576 898 0+-1150 -1576 899 0+-1151 -1576 900 0+-1117 -1577 902 0+-1118 -1577 903 0+-1119 -1577 904 0+-1120 -1577 905 0+-1121 -1577 906 0+-1122 -1577 907 0+-1123 -1577 908 0+-1124 -1577 909 0+-1125 -1577 910 0+-1126 -1577 911 0+-1127 -1577 912 0+-1128 -1577 913 0+-1129 -1577 914 0+-1130 -1577 915 0+-1131 -1577 916 0+-1132 -1577 917 0+-1133 -1577 918 0+-1134 -1577 919 0+-1135 -1577 920 0+-1136 -1577 921 0+-1137 -1577 922 0+-1138 -1577 923 0+-1139 -1577 924 0+-1140 -1577 925 0+-1141 -1577 926 0+-1142 -1577 927 0+-1143 -1577 928 0+-1144 -1577 929 0+-1145 -1577 930 0+-1146 -1577 931 0+-1147 -1577 932 0+-1148 -1577 933 0+-1149 -1577 934 0+-1150 -1577 935 0+-1151 -1577 936 0+-1117 -1578 938 0+-1118 -1578 939 0+-1119 -1578 940 0+-1120 -1578 941 0+-1121 -1578 942 0+-1122 -1578 943 0+-1123 -1578 944 0+-1124 -1578 945 0+-1125 -1578 946 0+-1126 -1578 947 0+-1127 -1578 948 0+-1128 -1578 949 0+-1129 -1578 950 0+-1130 -1578 951 0+-1131 -1578 952 0+-1132 -1578 953 0+-1133 -1578 954 0+-1134 -1578 955 0+-1135 -1578 956 0+-1136 -1578 957 0+-1137 -1578 958 0+-1138 -1578 959 0+-1139 -1578 960 0+-1140 -1578 961 0+-1141 -1578 962 0+-1142 -1578 963 0+-1143 -1578 964 0+-1144 -1578 965 0+-1145 -1578 966 0+-1146 -1578 967 0+-1147 -1578 968 0+-1148 -1578 969 0+-1149 -1578 970 0+-1150 -1578 971 0+-1151 -1578 972 0+-1117 -1579 1082 0+-1118 -1579 1083 0+-1119 -1579 1084 0+-1120 -1579 1085 0+-1121 -1579 1086 0+-1122 -1579 1087 0+-1123 -1579 1088 0+-1124 -1579 1089 0+-1125 -1579 1090 0+-1126 -1579 1091 0+-1127 -1579 1092 0+-1128 -1579 1093 0+-1129 -1579 1094 0+-1130 -1579 1095 0+-1131 -1579 1096 0+-1132 -1579 1097 0+-1133 -1579 1098 0+-1134 -1579 1099 0+-1135 -1579 1100 0+-1136 -1579 1101 0+-1137 -1579 1102 0+-1138 -1579 1103 0+-1139 -1579 1104 0+-1140 -1579 1105 0+-1141 -1579 1106 0+-1142 -1579 1107 0+-1143 -1579 1108 0+-1144 -1579 1109 0+-1145 -1579 1110 0+-1146 -1579 1111 0+-1147 -1579 1112 0+-1148 -1579 1113 0+-1149 -1579 1114 0+-1150 -1579 1115 0+-1151 -1579 1116 0+-1117 -1581 1154 0+-1118 -1581 1155 0+-1119 -1581 1156 0+-1120 -1581 1157 0+-1121 -1581 1158 0+-1122 -1581 1159 0+-1123 -1581 1160 0+-1124 -1581 1161 0+-1125 -1581 1162 0+-1126 -1581 1163 0+-1127 -1581 1164 0+-1128 -1581 1165 0+-1129 -1581 1166 0+-1130 -1581 1167 0+-1131 -1581 1168 0+-1132 -1581 1169 0+-1133 -1581 1170 0+-1134 -1581 1171 0+-1135 -1581 1172 0+-1136 -1581 1173 0+-1137 -1581 1174 0+-1138 -1581 1175 0+-1139 -1581 1176 0+-1140 -1581 1177 0+-1141 -1581 1178 0+-1142 -1581 1179 0+-1143 -1581 1180 0+-1144 -1581 1181 0+-1145 -1581 1182 0+-1146 -1581 1183 0+-1147 -1581 1184 0+-1148 -1581 1185 0+-1149 -1581 1186 0+-1150 -1581 1187 0+-1151 -1581 1188 0+-1576 -1577 0+-1576 -2490 0+-1577 -2490 0+-1578 -1579 0+-1578 -1581 0+-1578 2490 0+-1579 -1581 0+-1579 2490 0+-1581 2490 0+1576 1577 1578 1579 1581 0+-1153 -1585 902 0+-1154 -1585 903 0+-1155 -1585 904 0+-1156 -1585 905 0+-1157 -1585 906 0+-1158 -1585 907 0+-1159 -1585 908 0+-1160 -1585 909 0+-1161 -1585 910 0+-1162 -1585 911 0+-1163 -1585 912 0+-1164 -1585 913 0+-1165 -1585 914 0+-1166 -1585 915 0+-1167 -1585 916 0+-1168 -1585 917 0+-1169 -1585 918 0+-1170 -1585 919 0+-1171 -1585 920 0+-1172 -1585 921 0+-1173 -1585 922 0+-1174 -1585 923 0+-1175 -1585 924 0+-1176 -1585 925 0+-1177 -1585 926 0+-1178 -1585 927 0+-1179 -1585 928 0+-1180 -1585 929 0+-1181 -1585 930 0+-1182 -1585 931 0+-1183 -1585 932 0+-1184 -1585 933 0+-1185 -1585 934 0+-1186 -1585 935 0+-1187 -1585 936 0+-1153 -1586 938 0+-1154 -1586 939 0+-1155 -1586 940 0+-1156 -1586 941 0+-1157 -1586 942 0+-1158 -1586 943 0+-1159 -1586 944 0+-1160 -1586 945 0+-1161 -1586 946 0+-1162 -1586 947 0+-1163 -1586 948 0+-1164 -1586 949 0+-1165 -1586 950 0+-1166 -1586 951 0+-1167 -1586 952 0+-1168 -1586 953 0+-1169 -1586 954 0+-1170 -1586 955 0+-1171 -1586 956 0+-1172 -1586 957 0+-1173 -1586 958 0+-1174 -1586 959 0+-1175 -1586 960 0+-1176 -1586 961 0+-1177 -1586 962 0+-1178 -1586 963 0+-1179 -1586 964 0+-1180 -1586 965 0+-1181 -1586 966 0+-1182 -1586 967 0+-1183 -1586 968 0+-1184 -1586 969 0+-1185 -1586 970 0+-1186 -1586 971 0+-1187 -1586 972 0+-1153 -1587 974 0+-1154 -1587 975 0+-1155 -1587 976 0+-1156 -1587 977 0+-1157 -1587 978 0+-1158 -1587 979 0+-1159 -1587 980 0+-1160 -1587 981 0+-1161 -1587 982 0+-1162 -1587 983 0+-1163 -1587 984 0+-1164 -1587 985 0+-1165 -1587 986 0+-1166 -1587 987 0+-1167 -1587 988 0+-1168 -1587 989 0+-1169 -1587 990 0+-1170 -1587 991 0+-1171 -1587 992 0+-1172 -1587 993 0+-1173 -1587 994 0+-1174 -1587 995 0+-1175 -1587 996 0+-1176 -1587 997 0+-1177 -1587 998 0+-1178 -1587 999 0+-1179 -1587 1000 0+-1180 -1587 1001 0+-1181 -1587 1002 0+-1182 -1587 1003 0+-1183 -1587 1004 0+-1184 -1587 1005 0+-1185 -1587 1006 0+-1186 -1587 1007 0+-1187 -1587 1008 0+-1153 -1588 1118 0+-1154 -1588 1119 0+-1155 -1588 1120 0+-1156 -1588 1121 0+-1157 -1588 1122 0+-1158 -1588 1123 0+-1159 -1588 1124 0+-1160 -1588 1125 0+-1161 -1588 1126 0+-1162 -1588 1127 0+-1163 -1588 1128 0+-1164 -1588 1129 0+-1165 -1588 1130 0+-1166 -1588 1131 0+-1167 -1588 1132 0+-1168 -1588 1133 0+-1169 -1588 1134 0+-1170 -1588 1135 0+-1171 -1588 1136 0+-1172 -1588 1137 0+-1173 -1588 1138 0+-1174 -1588 1139 0+-1175 -1588 1140 0+-1176 -1588 1141 0+-1177 -1588 1142 0+-1178 -1588 1143 0+-1179 -1588 1144 0+-1180 -1588 1145 0+-1181 -1588 1146 0+-1182 -1588 1147 0+-1183 -1588 1148 0+-1184 -1588 1149 0+-1185 -1588 1150 0+-1186 -1588 1151 0+-1187 -1588 1152 0+-1153 -1590 1190 0+-1154 -1590 1191 0+-1155 -1590 1192 0+-1156 -1590 1193 0+-1157 -1590 1194 0+-1158 -1590 1195 0+-1159 -1590 1196 0+-1160 -1590 1197 0+-1161 -1590 1198 0+-1162 -1590 1199 0+-1163 -1590 1200 0+-1164 -1590 1201 0+-1165 -1590 1202 0+-1166 -1590 1203 0+-1167 -1590 1204 0+-1168 -1590 1205 0+-1169 -1590 1206 0+-1170 -1590 1207 0+-1171 -1590 1208 0+-1172 -1590 1209 0+-1173 -1590 1210 0+-1174 -1590 1211 0+-1175 -1590 1212 0+-1176 -1590 1213 0+-1177 -1590 1214 0+-1178 -1590 1215 0+-1179 -1590 1216 0+-1180 -1590 1217 0+-1181 -1590 1218 0+-1182 -1590 1219 0+-1183 -1590 1220 0+-1184 -1590 1221 0+-1185 -1590 1222 0+-1186 -1590 1223 0+-1187 -1590 1224 0+-1585 -1586 0+-1585 -2496 0+-1586 -2496 0+-1587 -1588 0+-1587 -1590 0+-1587 2496 0+-1588 -1590 0+-1588 2496 0+-1590 2496 0+1585 1586 1587 1588 1590 0+-1189 -1594 938 0+-1190 -1594 939 0+-1191 -1594 940 0+-1192 -1594 941 0+-1193 -1594 942 0+-1194 -1594 943 0+-1195 -1594 944 0+-1196 -1594 945 0+-1197 -1594 946 0+-1198 -1594 947 0+-1199 -1594 948 0+-1200 -1594 949 0+-1201 -1594 950 0+-1202 -1594 951 0+-1203 -1594 952 0+-1204 -1594 953 0+-1205 -1594 954 0+-1206 -1594 955 0+-1207 -1594 956 0+-1208 -1594 957 0+-1209 -1594 958 0+-1210 -1594 959 0+-1211 -1594 960 0+-1212 -1594 961 0+-1213 -1594 962 0+-1214 -1594 963 0+-1215 -1594 964 0+-1216 -1594 965 0+-1217 -1594 966 0+-1218 -1594 967 0+-1219 -1594 968 0+-1220 -1594 969 0+-1221 -1594 970 0+-1222 -1594 971 0+-1223 -1594 972 0+-1189 -1595 974 0+-1190 -1595 975 0+-1191 -1595 976 0+-1192 -1595 977 0+-1193 -1595 978 0+-1194 -1595 979 0+-1195 -1595 980 0+-1196 -1595 981 0+-1197 -1595 982 0+-1198 -1595 983 0+-1199 -1595 984 0+-1200 -1595 985 0+-1201 -1595 986 0+-1202 -1595 987 0+-1203 -1595 988 0+-1204 -1595 989 0+-1205 -1595 990 0+-1206 -1595 991 0+-1207 -1595 992 0+-1208 -1595 993 0+-1209 -1595 994 0+-1210 -1595 995 0+-1211 -1595 996 0+-1212 -1595 997 0+-1213 -1595 998 0+-1214 -1595 999 0+-1215 -1595 1000 0+-1216 -1595 1001 0+-1217 -1595 1002 0+-1218 -1595 1003 0+-1219 -1595 1004 0+-1220 -1595 1005 0+-1221 -1595 1006 0+-1222 -1595 1007 0+-1223 -1595 1008 0+-1189 -1596 1010 0+-1190 -1596 1011 0+-1191 -1596 1012 0+-1192 -1596 1013 0+-1193 -1596 1014 0+-1194 -1596 1015 0+-1195 -1596 1016 0+-1196 -1596 1017 0+-1197 -1596 1018 0+-1198 -1596 1019 0+-1199 -1596 1020 0+-1200 -1596 1021 0+-1201 -1596 1022 0+-1202 -1596 1023 0+-1203 -1596 1024 0+-1204 -1596 1025 0+-1205 -1596 1026 0+-1206 -1596 1027 0+-1207 -1596 1028 0+-1208 -1596 1029 0+-1209 -1596 1030 0+-1210 -1596 1031 0+-1211 -1596 1032 0+-1212 -1596 1033 0+-1213 -1596 1034 0+-1214 -1596 1035 0+-1215 -1596 1036 0+-1216 -1596 1037 0+-1217 -1596 1038 0+-1218 -1596 1039 0+-1219 -1596 1040 0+-1220 -1596 1041 0+-1221 -1596 1042 0+-1222 -1596 1043 0+-1223 -1596 1044 0+-1189 -1597 1154 0+-1190 -1597 1155 0+-1191 -1597 1156 0+-1192 -1597 1157 0+-1193 -1597 1158 0+-1194 -1597 1159 0+-1195 -1597 1160 0+-1196 -1597 1161 0+-1197 -1597 1162 0+-1198 -1597 1163 0+-1199 -1597 1164 0+-1200 -1597 1165 0+-1201 -1597 1166 0+-1202 -1597 1167 0+-1203 -1597 1168 0+-1204 -1597 1169 0+-1205 -1597 1170 0+-1206 -1597 1171 0+-1207 -1597 1172 0+-1208 -1597 1173 0+-1209 -1597 1174 0+-1210 -1597 1175 0+-1211 -1597 1176 0+-1212 -1597 1177 0+-1213 -1597 1178 0+-1214 -1597 1179 0+-1215 -1597 1180 0+-1216 -1597 1181 0+-1217 -1597 1182 0+-1218 -1597 1183 0+-1219 -1597 1184 0+-1220 -1597 1185 0+-1221 -1597 1186 0+-1222 -1597 1187 0+-1223 -1597 1188 0+-1189 -1599 1226 0+-1190 -1599 1227 0+-1191 -1599 1228 0+-1192 -1599 1229 0+-1193 -1599 1230 0+-1194 -1599 1231 0+-1195 -1599 1232 0+-1196 -1599 1233 0+-1197 -1599 1234 0+-1198 -1599 1235 0+-1199 -1599 1236 0+-1200 -1599 1237 0+-1201 -1599 1238 0+-1202 -1599 1239 0+-1203 -1599 1240 0+-1204 -1599 1241 0+-1205 -1599 1242 0+-1206 -1599 1243 0+-1207 -1599 1244 0+-1208 -1599 1245 0+-1209 -1599 1246 0+-1210 -1599 1247 0+-1211 -1599 1248 0+-1212 -1599 1249 0+-1213 -1599 1250 0+-1214 -1599 1251 0+-1215 -1599 1252 0+-1216 -1599 1253 0+-1217 -1599 1254 0+-1218 -1599 1255 0+-1219 -1599 1256 0+-1220 -1599 1257 0+-1221 -1599 1258 0+-1222 -1599 1259 0+-1223 -1599 1260 0+-1594 -1595 0+-1594 -2502 0+-1595 -2502 0+-1596 -1597 0+-1596 -1599 0+-1596 2502 0+-1597 -1599 0+-1597 2502 0+-1599 2502 0+1594 1595 1596 1597 1599 0+-1225 -1603 974 0+-1226 -1603 975 0+-1227 -1603 976 0+-1228 -1603 977 0+-1229 -1603 978 0+-1230 -1603 979 0+-1231 -1603 980 0+-1232 -1603 981 0+-1233 -1603 982 0+-1234 -1603 983 0+-1235 -1603 984 0+-1236 -1603 985 0+-1237 -1603 986 0+-1238 -1603 987 0+-1239 -1603 988 0+-1240 -1603 989 0+-1241 -1603 990 0+-1242 -1603 991 0+-1243 -1603 992 0+-1244 -1603 993 0+-1245 -1603 994 0+-1246 -1603 995 0+-1247 -1603 996 0+-1248 -1603 997 0+-1249 -1603 998 0+-1250 -1603 999 0+-1251 -1603 1000 0+-1252 -1603 1001 0+-1253 -1603 1002 0+-1254 -1603 1003 0+-1255 -1603 1004 0+-1256 -1603 1005 0+-1257 -1603 1006 0+-1258 -1603 1007 0+-1259 -1603 1008 0+-1225 -1604 1010 0+-1226 -1604 1011 0+-1227 -1604 1012 0+-1228 -1604 1013 0+-1229 -1604 1014 0+-1230 -1604 1015 0+-1231 -1604 1016 0+-1232 -1604 1017 0+-1233 -1604 1018 0+-1234 -1604 1019 0+-1235 -1604 1020 0+-1236 -1604 1021 0+-1237 -1604 1022 0+-1238 -1604 1023 0+-1239 -1604 1024 0+-1240 -1604 1025 0+-1241 -1604 1026 0+-1242 -1604 1027 0+-1243 -1604 1028 0+-1244 -1604 1029 0+-1245 -1604 1030 0+-1246 -1604 1031 0+-1247 -1604 1032 0+-1248 -1604 1033 0+-1249 -1604 1034 0+-1250 -1604 1035 0+-1251 -1604 1036 0+-1252 -1604 1037 0+-1253 -1604 1038 0+-1254 -1604 1039 0+-1255 -1604 1040 0+-1256 -1604 1041 0+-1257 -1604 1042 0+-1258 -1604 1043 0+-1259 -1604 1044 0+-1225 -1605 1046 0+-1226 -1605 1047 0+-1227 -1605 1048 0+-1228 -1605 1049 0+-1229 -1605 1050 0+-1230 -1605 1051 0+-1231 -1605 1052 0+-1232 -1605 1053 0+-1233 -1605 1054 0+-1234 -1605 1055 0+-1235 -1605 1056 0+-1236 -1605 1057 0+-1237 -1605 1058 0+-1238 -1605 1059 0+-1239 -1605 1060 0+-1240 -1605 1061 0+-1241 -1605 1062 0+-1242 -1605 1063 0+-1243 -1605 1064 0+-1244 -1605 1065 0+-1245 -1605 1066 0+-1246 -1605 1067 0+-1247 -1605 1068 0+-1248 -1605 1069 0+-1249 -1605 1070 0+-1250 -1605 1071 0+-1251 -1605 1072 0+-1252 -1605 1073 0+-1253 -1605 1074 0+-1254 -1605 1075 0+-1255 -1605 1076 0+-1256 -1605 1077 0+-1257 -1605 1078 0+-1258 -1605 1079 0+-1259 -1605 1080 0+-1225 -1606 1190 0+-1226 -1606 1191 0+-1227 -1606 1192 0+-1228 -1606 1193 0+-1229 -1606 1194 0+-1230 -1606 1195 0+-1231 -1606 1196 0+-1232 -1606 1197 0+-1233 -1606 1198 0+-1234 -1606 1199 0+-1235 -1606 1200 0+-1236 -1606 1201 0+-1237 -1606 1202 0+-1238 -1606 1203 0+-1239 -1606 1204 0+-1240 -1606 1205 0+-1241 -1606 1206 0+-1242 -1606 1207 0+-1243 -1606 1208 0+-1244 -1606 1209 0+-1245 -1606 1210 0+-1246 -1606 1211 0+-1247 -1606 1212 0+-1248 -1606 1213 0+-1249 -1606 1214 0+-1250 -1606 1215 0+-1251 -1606 1216 0+-1252 -1606 1217 0+-1253 -1606 1218 0+-1254 -1606 1219 0+-1255 -1606 1220 0+-1256 -1606 1221 0+-1257 -1606 1222 0+-1258 -1606 1223 0+-1259 -1606 1224 0+-1225 -1608 1262 0+-1226 -1608 1263 0+-1227 -1608 1264 0+-1228 -1608 1265 0+-1229 -1608 1266 0+-1230 -1608 1267 0+-1231 -1608 1268 0+-1232 -1608 1269 0+-1233 -1608 1270 0+-1234 -1608 1271 0+-1235 -1608 1272 0+-1236 -1608 1273 0+-1237 -1608 1274 0+-1238 -1608 1275 0+-1239 -1608 1276 0+-1240 -1608 1277 0+-1241 -1608 1278 0+-1242 -1608 1279 0+-1243 -1608 1280 0+-1244 -1608 1281 0+-1245 -1608 1282 0+-1246 -1608 1283 0+-1247 -1608 1284 0+-1248 -1608 1285 0+-1249 -1608 1286 0+-1250 -1608 1287 0+-1251 -1608 1288 0+-1252 -1608 1289 0+-1253 -1608 1290 0+-1254 -1608 1291 0+-1255 -1608 1292 0+-1256 -1608 1293 0+-1257 -1608 1294 0+-1258 -1608 1295 0+-1259 -1608 1296 0+-1603 -1604 0+-1603 -2508 0+-1604 -2508 0+-1605 -1606 0+-1605 -1608 0+-1605 2508 0+-1606 -1608 0+-1606 2508 0+-1608 2508 0+1603 1604 1605 1606 1608 0+-1261 -1612 1010 0+-1262 -1612 1011 0+-1263 -1612 1012 0+-1264 -1612 1013 0+-1265 -1612 1014 0+-1266 -1612 1015 0+-1267 -1612 1016 0+-1268 -1612 1017 0+-1269 -1612 1018 0+-1270 -1612 1019 0+-1271 -1612 1020 0+-1272 -1612 1021 0+-1273 -1612 1022 0+-1274 -1612 1023 0+-1275 -1612 1024 0+-1276 -1612 1025 0+-1277 -1612 1026 0+-1278 -1612 1027 0+-1279 -1612 1028 0+-1280 -1612 1029 0+-1281 -1612 1030 0+-1282 -1612 1031 0+-1283 -1612 1032 0+-1284 -1612 1033 0+-1285 -1612 1034 0+-1286 -1612 1035 0+-1287 -1612 1036 0+-1288 -1612 1037 0+-1289 -1612 1038 0+-1290 -1612 1039 0+-1291 -1612 1040 0+-1292 -1612 1041 0+-1293 -1612 1042 0+-1294 -1612 1043 0+-1295 -1612 1044 0+-1261 -1613 1046 0+-1262 -1613 1047 0+-1263 -1613 1048 0+-1264 -1613 1049 0+-1265 -1613 1050 0+-1266 -1613 1051 0+-1267 -1613 1052 0+-1268 -1613 1053 0+-1269 -1613 1054 0+-1270 -1613 1055 0+-1271 -1613 1056 0+-1272 -1613 1057 0+-1273 -1613 1058 0+-1274 -1613 1059 0+-1275 -1613 1060 0+-1276 -1613 1061 0+-1277 -1613 1062 0+-1278 -1613 1063 0+-1279 -1613 1064 0+-1280 -1613 1065 0+-1281 -1613 1066 0+-1282 -1613 1067 0+-1283 -1613 1068 0+-1284 -1613 1069 0+-1285 -1613 1070 0+-1286 -1613 1071 0+-1287 -1613 1072 0+-1288 -1613 1073 0+-1289 -1613 1074 0+-1290 -1613 1075 0+-1291 -1613 1076 0+-1292 -1613 1077 0+-1293 -1613 1078 0+-1294 -1613 1079 0+-1295 -1613 1080 0+-1261 -1615 1226 0+-1262 -1615 1227 0+-1263 -1615 1228 0+-1264 -1615 1229 0+-1265 -1615 1230 0+-1266 -1615 1231 0+-1267 -1615 1232 0+-1268 -1615 1233 0+-1269 -1615 1234 0+-1270 -1615 1235 0+-1271 -1615 1236 0+-1272 -1615 1237 0+-1273 -1615 1238 0+-1274 -1615 1239 0+-1275 -1615 1240 0+-1276 -1615 1241 0+-1277 -1615 1242 0+-1278 -1615 1243 0+-1279 -1615 1244 0+-1280 -1615 1245 0+-1281 -1615 1246 0+-1282 -1615 1247 0+-1283 -1615 1248 0+-1284 -1615 1249 0+-1285 -1615 1250 0+-1286 -1615 1251 0+-1287 -1615 1252 0+-1288 -1615 1253 0+-1289 -1615 1254 0+-1290 -1615 1255 0+-1291 -1615 1256 0+-1292 -1615 1257 0+-1293 -1615 1258 0+-1294 -1615 1259 0+-1295 -1615 1260 0+-1612 -1613 0+-1612 -1615 0+-1613 -1615 0+1612 1613 1615 0
samples/smt/QF_ABV.smt2 view
@@ -1,20 +1,20 @@-(set-logic QF_ABV)
-(declare-fun x () (_ BitVec 32))
-(declare-fun y () (_ BitVec 16))
-(declare-fun z () (_ BitVec 20))
-(declare-fun A () (Array (_ BitVec 16) (_ BitVec 32)))
-(assert
-  (let ((c1 (= ((_ sign_extend 12) z) (select A y)))
-        (A2 (store A ((_ extract 15 0) x) x)))
-    (let ((c2 (= A A2)))
-      (let ((c3
-        (bvslt (concat z (_ bv5 12))
-               (bvand (bvor (bvxor (bvnot x)
-                                   (select A2 ((_ zero_extend 12) #b1111)))
-                            (concat #xAF02 y))
-                      (concat ((_ extract 15 0)
-                               (bvmul x (select (store A y x) #x35FB)))
-                              (bvashr (_ bv42 16) #x0001))))))
-        (and c1 (xor c2 c3))))))
-(check-sat)
-(exit)
+(set-logic QF_ABV)+(declare-fun x () (_ BitVec 32))+(declare-fun y () (_ BitVec 16))+(declare-fun z () (_ BitVec 20))+(declare-fun A () (Array (_ BitVec 16) (_ BitVec 32)))+(assert+  (let ((c1 (= ((_ sign_extend 12) z) (select A y)))+        (A2 (store A ((_ extract 15 0) x) x)))+    (let ((c2 (= A A2)))+      (let ((c3+        (bvslt (concat z (_ bv5 12))+               (bvand (bvor (bvxor (bvnot x)+                                   (select A2 ((_ zero_extend 12) #b1111)))+                            (concat #xAF02 y))+                      (concat ((_ extract 15 0)+                               (bvmul x (select (store A y x) #x35FB)))+                              (bvashr (_ bv42 16) #x0001))))))+        (and c1 (xor c2 c3))))))+(check-sat)+(exit)
samples/smt/QF_AUFLIA.smt2 view
@@ -1,15 +1,15 @@-(set-logic QF_AUFLIA)
-(declare-fun A () (Array Int Int))
-(declare-fun x () Int)
-(declare-fun y () Int)
-(declare-fun P () Bool)
-(declare-sort U 0)
-(declare-fun f (U) (Array Int Int))
-(declare-fun c () U)
-(assert
-  (let ((fc (f c)))
-    (and
-      (=> (= A (store fc x 5)) (> (+ (select fc y) (* 4 x)) 0))
-      (= P (< (select A (+ 3 y)) (* (- 2) x))))))
-(check-sat)
-(exit)
+(set-logic QF_AUFLIA)+(declare-fun A () (Array Int Int))+(declare-fun x () Int)+(declare-fun y () Int)+(declare-fun P () Bool)+(declare-sort U 0)+(declare-fun f (U) (Array Int Int))+(declare-fun c () U)+(assert+  (let ((fc (f c)))+    (and+      (=> (= A (store fc x 5)) (> (+ (select fc y) (* 4 x)) 0))+      (= P (< (select A (+ 3 y)) (* (- 2) x))))))+(check-sat)+(exit)
samples/smt/QF_BV.smt2 view
@@ -1,16 +1,18 @@-(set-logic QF_BV)
-(declare-fun x () (_ BitVec 32))
-(declare-fun y () (_ BitVec 16))
-(declare-fun z () (_ BitVec 20))
-(assert
-  (let ((c1 (= x ((_ sign_extend 12) z))))
-    (let ((c2 (= y ((_ extract 18 3) x))))
-      (let ((c3
-              (bvslt (concat z (_ bv5 12))
-                     (bvand (bvor (bvxor (bvnot x) ((_ zero_extend 28) #b1111))
-                                  (concat #xAF02 y))
-                            (concat (bvmul ((_ extract 31 16) x) y)
-                                    (bvashr (_ bv42 16) #x0001))))))
-        (and c1 (xor c2 c3))))))
-(check-sat)
-(exit)
+(set-option :produce-models true)+(set-logic QF_BV)+(declare-fun x () (_ BitVec 32))+(declare-fun y () (_ BitVec 16))+(declare-fun z () (_ BitVec 20))+(assert+  (let ((c1 (= x ((_ sign_extend 12) z))))+    (let ((c2 (= y ((_ extract 18 3) x))))+      (let ((c3+              (bvslt (concat z (_ bv5 12))+                     (bvand (bvor (bvxor (bvnot x) ((_ zero_extend 28) #b1111))+                                  (concat #xAF02 y))+                            (concat (bvmul ((_ extract 31 16) x) y)+                                    (bvashr (_ bv42 16) #x0001))))))+        (and c1 (xor c2 c3))))))+(check-sat)+(get-model)+(exit)
samples/smt/QF_LIA.smt2 view
@@ -1,12 +1,12 @@-(set-logic QF_LIA)
-(declare-fun x () Int)
-(declare-fun y () Int)
-(declare-fun A () Bool)
-(assert
-  (let ((i1 (ite A (<= (+ (* 2 x) (* (- 1) y)) (- 4))
-                   (= (* y 5) (- 2 x)))))
-    (and
-      i1
-      (or (> x y) (= A (< (* 3 x) (+ (- 1) (* 1 (+ x y)))))))))
-(check-sat)
-(exit)
+(set-logic QF_LIA)+(declare-fun x () Int)+(declare-fun y () Int)+(declare-fun A () Bool)+(assert+  (let ((i1 (ite A (<= (+ (* 2 x) (* (- 1) y)) (- 4))+                   (= (* y 5) (- 2 x)))))+    (and+      i1+      (or (> x y) (= A (< (* 3 x) (+ (- 1) (* 1 (+ x y)))))))))+(check-sat)+(exit)
samples/smt/QF_LRA.smt2 view
@@ -1,12 +1,12 @@-(set-logic QF_LRA)
-(declare-fun x () Real)
-(declare-fun y () Real)
-(declare-fun A () Bool)
-(assert
-  (let ((i1 (ite A (<= (+ (* 2.0 x) (* (/ 1 3) y)) (- 4))
-                   (= (* y 1.5) (- 2 x)))))
-    (and
-      i1
-      (or (> x y) (= A (< (* 3 x) (+ (- 1) (* (/ 1 5) (+ x y)))))))))
-(check-sat)
-(exit)
+(set-logic QF_LRA)+(declare-fun x () Real)+(declare-fun y () Real)+(declare-fun A () Bool)+(assert+  (let ((i1 (ite A (<= (+ (* 2.0 x) (* (/ 1 3) y)) (- 4))+                   (= (* y 1.5) (- 2 x)))))+    (and+      i1+      (or (> x y) (= A (< (* 3 x) (+ (- 1) (* (/ 1 5) (+ x y)))))))))+(check-sat)+(exit)
samples/smt/QF_LRA_2.smt2 view
@@ -1,39 +1,39 @@-(set-option :print-success true)
-(set-logic QF_LRA)
-(declare-fun c0 () Bool)
-(declare-fun E0 () Bool)
-(declare-fun f0 () Bool)
-(declare-fun f1 () Bool)
-(push 1)
-(assert
-  (let ((.def_10 (not f0)))
-    (let ((.def_9 (not c0)))
-      (let ((.def_11 (or .def_9 .def_10)))
-        (let ((.def_7 (not f1)))
-          (let ((.def_8 (or c0 .def_7)))
-            (let ((.def_12 (and .def_8 .def_11)))
-  .def_12
-)))))))
-(check-sat)
-(pop 1)
-(declare-fun f2 () Bool)
-(declare-fun f3 () Bool)
-(declare-fun f4 () Bool)
-(declare-fun c1 () Bool)
-(declare-fun E1 () Bool)
-(assert
-  (let ((.def_23 (not f2)))
-    (let ((.def_20 (= c0 c1)))
-      (let ((.def_22 (or E0 .def_20)))
-        (let ((.def_24 (or .def_22 .def_23)))
-          (let ((.def_18 (not f4)))
-            (let ((.def_19 (or c1 .def_18)))
-              (let ((.def_25 (and .def_19 .def_24)))
-  .def_25
-))))))))
-(push 1)
-(check-sat)
-(assert (and f1 (not f1)))
-(check-sat)
-(pop 1)
-(exit)
+(set-option :print-success true)+(set-logic QF_LRA)+(declare-fun c0 () Bool)+(declare-fun E0 () Bool)+(declare-fun f0 () Bool)+(declare-fun f1 () Bool)+(push 1)+(assert+  (let ((.def_10 (not f0)))+    (let ((.def_9 (not c0)))+      (let ((.def_11 (or .def_9 .def_10)))+        (let ((.def_7 (not f1)))+          (let ((.def_8 (or c0 .def_7)))+            (let ((.def_12 (and .def_8 .def_11)))+  .def_12+)))))))+(check-sat)+(pop 1)+(declare-fun f2 () Bool)+(declare-fun f3 () Bool)+(declare-fun f4 () Bool)+(declare-fun c1 () Bool)+(declare-fun E1 () Bool)+(assert+  (let ((.def_23 (not f2)))+    (let ((.def_20 (= c0 c1)))+      (let ((.def_22 (or E0 .def_20)))+        (let ((.def_24 (or .def_22 .def_23)))+          (let ((.def_18 (not f4)))+            (let ((.def_19 (or c1 .def_18)))+              (let ((.def_25 (and .def_19 .def_24)))+  .def_25+))))))))+(push 1)+(check-sat)+(assert (and f1 (not f1)))+(check-sat)+(pop 1)+(exit)
samples/smt/QF_UF.smt2 view
@@ -1,14 +1,14 @@-(set-logic QF_UF)
-(set-info :status sat)
-(declare-sort U 0)
-(declare-fun f (U) U)
-(declare-fun g (U) U)
-(declare-fun A () Bool)
-(declare-fun x () U)
-(declare-fun y () U)
-(assert
-(let ((fx (f x))
-      (cls1 (or A (= x y))))
-  (and cls1 (distinct fx (g y)))))
-(check-sat)
-(exit)
+(set-logic QF_UF)+(set-info :status sat)+(declare-sort U 0)+(declare-fun f (U) U)+(declare-fun g (U) U)+(declare-fun A () Bool)+(declare-fun x () U)+(declare-fun y () U)+(assert+(let ((fx (f x))+      (cls1 (or A (= x y))))+  (and cls1 (distinct fx (g y)))))+(check-sat)+(exit)
samples/smt/QF_UFLRA.smt2 view
@@ -1,4 +1,4 @@-(set-option :produce-models)+(set-option :produce-models true) (set-logic QF_UFLRA) (declare-sort U 0) (declare-fun x () Real)
samples/smt/division-by-zero.smt2 view
@@ -7,10 +7,12 @@ (define-fun y2 () Real (/ x2 0)) (check-sat) ; sat (get-value (x1 x2 y1 y2))+(get-model)  (assert (not (= y1 y2))) (check-sat) ; sat (get-value (x1 x2 y1 y2))+(get-model)  (assert (= x1 x2)) (check-sat) ; unsat
+ samples/smt/swap.smt2 view
@@ -0,0 +1,28 @@+; Modeling sequential code with bitvectors+;; Correct swap with no temp var+; int x, y;+; x = x + y;+; y = x - y;+; x = x - y;++(set-option :produce-models true)+(set-logic QF_BV) ++(declare-const x_0 (_ BitVec 32))+(declare-const x_1 (_ BitVec 32))+(declare-const x_2 (_ BitVec 32))   +(declare-const y_0 (_ BitVec 32))+(declare-const y_1 (_ BitVec 32))   +(assert (= x_1 (bvadd x_0 y_0))) +(assert (= y_1 (bvsub x_1 y_0)))+(assert (= x_2 (bvsub x_1 y_1)))+(assert (= x_1 (bvadd x_0 y_0))) +(assert (= y_1 (bvadd x_1 (bvneg y_0))))+(assert (= x_2 (bvadd x_1 (bvneg y_1))))++(assert (not+  (and (= x_2 y_0)+       (= y_1 x_0))))+(check-sat)+; unsat+(exit)
src/ToySolver/Arith/BoundsInference.hs view
@@ -27,7 +27,7 @@ import ToySolver.Data.OrdRel import ToySolver.Data.LA (BoundsEnv) import qualified ToySolver.Data.LA as LA-import ToySolver.Data.Var+import ToySolver.Data.IntVar import ToySolver.Internal.Util (isInteger)  type C r = (RelOp, LA.Expr r)
src/ToySolver/Arith/ContiTraverso.hs view
@@ -46,7 +46,7 @@ import ToySolver.Data.Polynomial (Polynomial, UPolynomial, Monomial, MonomialOrder) import qualified ToySolver.Data.Polynomial as P import ToySolver.Data.Polynomial.GroebnerBasis as GB-import ToySolver.Data.Var+import ToySolver.Data.IntVar import qualified ToySolver.Arith.LPUtil as LPUtil  solve :: MonomialOrder Var -> VarSet -> OptDir -> LA.Expr Rational -> [LA.Atom Rational] -> Maybe (Model Integer)@@ -112,7 +112,7 @@ costOrdering obj = compare `on` f   where     vs = vars obj-    f xs = LA.evalExpr (mkModel (IS.toList vs) xs) obj+    f xs = LA.eval (mkModel (IS.toList vs) xs) obj  elimOrdering :: IS.IntSet -> MonomialOrder Var elimOrdering xs = compare `on` f
src/ToySolver/Arith/Cooper/Base.hs view
@@ -34,6 +34,7 @@     , (.|.)     , evalQFFormula     , Model+    , Eval (..)      -- * Projection     , project@@ -64,7 +65,7 @@ import ToySolver.Data.BoolExpr (BoolExpr (..)) import qualified ToySolver.Data.BoolExpr as BoolExpr import qualified ToySolver.Data.LA as LA-import ToySolver.Data.Var+import ToySolver.Data.IntVar import qualified ToySolver.Arith.FourierMotzkin as FM  -- ---------------------------------------------------------------------------@@ -170,28 +171,33 @@     c' = c `checkedDiv` d     e' = LA.mapCoeff (`checkedDiv` d) e2 +{-# DEPRECATED evalQFFormula "Use Eval class instead" #-} -- | @'evalQFFormula' M φ@ returns whether @M ⊧_LIA φ@ or not. evalQFFormula :: Model Integer -> QFFormula -> Bool-evalQFFormula m = BoolExpr.fold (evalLit m)+evalQFFormula = eval +{-# DEPRECATED evalLit "Use Eval class instead" #-} evalLit :: Model Integer -> Lit -> Bool-evalLit m (IsPos 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+evalLit = eval +instance Eval (Model Integer) Lit Bool where+  eval m (IsPos e) = LA.eval m e > 0+  eval m (Divisible True n e)  = LA.eval m e `mod` n == 0+  eval m (Divisible False n e) = LA.eval m e `mod` n /= 0+ -- ---------------------------------------------------------------------------  data Witness = WCase1 Integer ExprZ | WCase2 Integer Integer Integer (Set ExprZ)   deriving (Show) -evalWitness :: Model Integer -> Witness -> Integer-evalWitness model (WCase1 c e) = LA.evalExpr model e `checkedDiv` c-evalWitness model (WCase2 c j delta us)-  | Set.null us' = j `checkedDiv` c-  | otherwise = (j + (((u - delta - 1) `div` delta) * delta)) `checkedDiv` c-  where-    us' = Set.map (LA.evalExpr model) us-    u = Set.findMin us'+instance Eval (Model Integer) Witness Integer where+  eval model (WCase1 c e) = LA.eval model e `checkedDiv` c+  eval model (WCase2 c j delta us)+    | Set.null us' = j `checkedDiv` c+    | otherwise = (j + (((u - delta - 1) `div` delta) * delta)) `checkedDiv` c+    where+      us' = Set.map (LA.eval model) us+      u = Set.findMin us'  -- --------------------------------------------------------------------------- @@ -208,7 +214,7 @@     formula' = orB' [phi | (phi,_) <- xs]     mt m = head $ do       (phi, mt') <- xs-      guard $ evalQFFormula m phi+      guard $ eval m phi       return $ mt' m     orB' = orB . concatMap f       where@@ -240,7 +246,7 @@ 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)+  return (phi, \m -> IM.insert x (eval m wit) m)  projectCases' :: Var -> QFFormula -> [(QFFormula, Witness)] projectCases' x formula = [(phi', w) | (phi,w) <- case1 ++ case2, let phi' = simplify phi, phi' /= false]@@ -385,8 +391,9 @@ solveQFFormula :: VarSet -> QFFormula -> Maybe (Model Integer) solveQFFormula vs formula = listToMaybe $ do   (formula2, mt) <- projectCasesN vs formula-  let m = IM.empty-  guard $ evalQFFormula m formula2+  let m :: Model Integer+      m = IM.empty+  guard $ eval m formula2   return $ mt m  -- | @'solve' {x1,…,xn} φ@ returns @Just M@ that @M ⊧_LIA φ@ when
src/ToySolver/Arith/Cooper/FOL.hs view
@@ -21,7 +21,7 @@ import ToySolver.Data.Boolean import qualified ToySolver.Data.FOL.Arith as FOL import qualified ToySolver.Data.LA.FOL as LAFOL-import ToySolver.Data.Var+import ToySolver.Data.IntVar import ToySolver.Arith.Cooper.Base  -- | Eliminate quantifiers and returns equivalent quantifier-free formula.
+ src/ToySolver/Arith/DifferenceLogic.hs view
@@ -0,0 +1,73 @@+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Arith.DifferenceLogic+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+-- Portability :  portable+--+-- Reference:+--+-- * Albert Oliveras and Enric Rodriguez-Carbonell.+--   “General overview of a T-Solver for Difference Logic”.+--   <https://www.cs.upc.edu/~oliveras/TDV/dl.pdf>+--+-----------------------------------------------------------------------------+module ToySolver.Arith.DifferenceLogic+  ( SimpleAtom (..)+  , Diff (..)+  , solve+  ) where++import Data.Hashable+import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import Data.HashSet (HashSet)+import qualified Data.HashSet as HashSet+import Data.Monoid++import ToySolver.Graph.ShortestPath (bellmanFord, lastInEdge, bellmanFordDetectNegativeCycle, monoid')++infixl 6 :-+infix 4 :<=++-- | Difference of two variables+data Diff v = v :- v+  deriving (Eq, Ord, Show)++-- | @a :- b :<= k@ represents /a - b ≤ k/+data SimpleAtom v b = Diff v :<= b+  deriving (Eq, Ord, Show)++-- | Takes labeled list of constraints, and returns either+--+-- * unsatisfiable set of constraints as a set of labels, or+--+-- * satisfying assignment.+solve+  :: (Hashable label, Eq label, Hashable v, Eq v, Real b)+  => [(label, SimpleAtom v b)]+  -> Either (HashSet label) (HashMap v b)+solve xs =+  case bellmanFordDetectNegativeCycle (monoid' (\(_,_,_,l) -> Endo (l:))) g d of+    Just f -> Left $ HashSet.fromList $ appEndo f []+    Nothing -> Right $ fmap (\(c,_) -> - c) d+  where+    vs = HashSet.toList $ HashSet.fromList [v | (_,(a :- b :<= _)) <- xs, v <- [a,b]]+    g = HashMap.fromList [(a,[(b,k,l)]) | (l,(a :- b :<= k)) <- xs]+    d = bellmanFord lastInEdge g vs++-- M = {a−b ≤ 2, b−c ≤ 3, c−a ≤ −3}+test_sat = solve xs+  where+    xs :: [(Int, SimpleAtom Char Int)]+    xs = [(1, ('a' :- 'b' :<= 2)), (2, ('b' :- 'c' :<= 3)), (3, ('c' :- 'a' :<= -3))]++-- M = {a−b ≤ 2, b−c ≤ 3, c−a ≤ −7}+test_unsat = solve xs+  where+    xs :: [(Int, SimpleAtom Char Int)]+    xs = [(1, ('a' :- 'b' :<= 2)), (2, ('b' :- 'c' :<= 3)), (3, ('c' :- 'a' :<= -7))]
src/ToySolver/Arith/FourierMotzkin/Base.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, MultiParamTypeClasses #-} {-# OPTIONS_GHC -Wall #-} ----------------------------------------------------------------------------- -- |@@ -7,7 +8,7 @@ --  -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  provisional--- Portability :  portable+-- Portability :  non-portable (TypeSynonymInstances, FlexibleInstances, MultiParamTypeClasses) -- -- Naïve implementation of Fourier-Motzkin Variable Elimination -- @@ -62,7 +63,7 @@ import ToySolver.Data.Boolean import ToySolver.Data.DNF import qualified ToySolver.Data.LA as LA-import ToySolver.Data.Var+import ToySolver.Data.IntVar  -- --------------------------------------------------------------------------- @@ -141,10 +142,10 @@         Just x -> guard (x == 0) >> return []         Nothing -> return [c] -evalConstr :: Model Rational -> Constr -> Bool-evalConstr m (IsPos t)    = LA.evalExpr m (LA.mapCoeff fromInteger t) > 0-evalConstr m (IsNonneg t) = LA.evalExpr m (LA.mapCoeff fromInteger t) >= 0-evalConstr m (IsZero t)   = LA.evalExpr m (LA.mapCoeff fromInteger t) == 0+instance Eval (Model Rational) Constr Bool where+  eval m (IsPos t)    = LA.eval m (LA.mapCoeff fromInteger t :: LA.Expr Rational) > 0+  eval m (IsNonneg t) = LA.eval m (LA.mapCoeff fromInteger t :: LA.Expr Rational) >= 0+  eval m (IsZero t)   = LA.eval m (LA.mapCoeff fromInteger t :: LA.Expr Rational) == 0  -- --------------------------------------------------------------------------- @@ -299,8 +300,9 @@ solve' :: VarSet -> [Constr] -> Maybe (Model Rational) solve' vs cs = do   (cs2,mt) <- projectN' vs =<< simplify cs-  let m = IM.empty-  guard $ all (evalConstr m) cs2+  let m :: Model Rational+      m = IM.empty+  guard $ all (eval m) cs2   return $ mt m  -- ---------------------------------------------------------------------------
src/ToySolver/Arith/FourierMotzkin/FOL.hs view
@@ -15,7 +15,7 @@ import ToySolver.Data.DNF import qualified ToySolver.Data.FOL.Arith as FOL import qualified ToySolver.Data.LA.FOL as LAFOL-import ToySolver.Data.Var+import ToySolver.Data.IntVar  import ToySolver.Arith.FourierMotzkin.Base 
src/ToySolver/Arith/FourierMotzkin/Optimization.hs view
@@ -32,7 +32,7 @@  import ToySolver.Data.DNF import qualified ToySolver.Data.LA as LA-import ToySolver.Data.Var+import ToySolver.Data.IntVar import ToySolver.Arith.FourierMotzkin.Base  -- | @optimize dir obj φ@ returns @(I, lift)@ where
− src/ToySolver/Arith/LPSolver.hs
@@ -1,328 +0,0 @@-{-# LANGUAGE ScopedTypeVariables #-}-{-# OPTIONS_GHC -Wall #-}--------------------------------------------------------------------------------- |--- Module      :  ToySolver.Arith.LPSolver--- Copyright   :  (c) Masahiro Sakai 2011--- License     :  BSD-style--- --- Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  provisional--- Portability :  non-portable (ScopedTypeVariables)------ Naïve implementation of Simplex method--- --- Reference:------ * <http://www.math.cuhk.edu.hk/~wei/lpch3.pdf>-----------------------------------------------------------------------------------module ToySolver.Arith.LPSolver-  (-  -- * Solver type-    Solver-  , emptySolver--  -- * LP monad-  , LP-  , getTableau-  , putTableau--  -- * Problem specification-  , newVar-  , addConstraint-  , addConstraintWithArtificialVariable-  , tableau-  , define--  -- * Solving-  , phaseI-  , simplex-  , dualSimplex-  , OptResult (..)-  , twoPhaseSimplex-  , primalDualSimplex--  -- * Extract results-  , getModel--  -- * Utilities-  , collectNonnegVars-  ) where--import Control.Exception (assert)-import Control.Monad-import Control.Monad.State-import qualified Data.IntMap as IM-import qualified Data.IntSet as IS-import Data.OptDir-import Data.VectorSpace--import Data.Interval ((<=!), (>=!), (==!), (<!), (>!), (/=!))-import qualified Data.Interval as Interval--import ToySolver.Data.OrdRel-import qualified ToySolver.Data.LA as LA-import ToySolver.Data.Var-import qualified ToySolver.Arith.Simplex as Simplex-import qualified ToySolver.Arith.BoundsInference as BI---- ------------------------------------------------------------------------------ Solver type--type Solver r = (Var, Simplex.Tableau r, VarSet, VarMap (LA.Expr r))--emptySolver :: VarSet -> Solver r-emptySolver vs = (1 + maximum ((-1) : IS.toList vs), Simplex.emptyTableau, IS.empty, IM.empty)---- ------------------------------------------------------------------------------ LP Monad--type LP r = State (Solver r)---- | Allocate a new /non-negative/ variable.-newVar :: LP r Var-newVar = do-  (x,tbl,avs,defs) <- get-  put (x+1,tbl,avs,defs)-  return x--getTableau :: LP r (Simplex.Tableau r)-getTableau = do-  (_,tbl,_,_) <- get-  return tbl--putTableau :: Simplex.Tableau r -> LP r ()-putTableau tbl = do-  (x,_,avs,defs) <- get-  put (x,tbl,avs,defs)--addArtificialVariable :: Var -> LP r ()-addArtificialVariable v = do-  (x,tbl,avs,defs) <- get-  put (x, tbl, IS.insert v avs, defs)--getArtificialVariables :: LP r VarSet-getArtificialVariables = do-  (_,_,avs,_) <- get-  return avs--clearArtificialVariables :: LP r ()-clearArtificialVariables = do-  (x,tbl,_,defs) <- get-  put (x, tbl, IS.empty, defs)--define :: Var -> LA.Expr r -> LP r ()-define v e = do-  (x,tbl,avs,defs) <- get-  put (x,tbl,avs, IM.insert v e defs)--getDefs :: LP r (VarMap (LA.Expr r))-getDefs = do-  (_,_,_,defs) <- get-  return defs---- ------------------------------------------------------------------------------- | Add a contraint and maintain feasibility condition by introducing artificial variable (if necessary).------ * Disequality is not supported.--- --- * Unlike 'addConstraint', an equality contstraint becomes one row with an artificial variable.--- -addConstraintWithArtificialVariable :: Real r => LA.Atom r -> LP r ()-addConstraintWithArtificialVariable c = do-  c2 <- expandDefs' c-  let (e, rop, b) = normalizeConstraint c2-  assert (b >= 0) $ return ()-  tbl <- getTableau-  case rop of-    -- x≥0 is trivially true, since x is non-negative.-    Ge | b==0 && isSingleVar e -> return ()-    -- -x≤0 is trivially true, since x is non-negative.-    Le | b==0 && isSingleNegatedVar e -> return ()--    Le -> do-      v <- newVar -- slack variable-      putTableau $ Simplex.addRow tbl v (LA.coeffMap e, b)-    Ge -> do-      v1 <- newVar -- surplus variable-      v2 <- newVar -- artificial variable-      putTableau $ Simplex.addRow tbl v2 (LA.coeffMap (e ^-^ LA.var v1), b)-      addArtificialVariable v2-    Eql -> do-      v <- newVar -- artificial variable-      putTableau $ Simplex.addRow tbl v (LA.coeffMap e, b)-      addArtificialVariable v-    _ -> error $ "ToySolver.LPSolver.addConstraintWithArtificialVariable does not support " ++ show rop---- | Add a contraint, without maintaining feasibilty condition of tableaus.------ * Disequality is not supported.------ * Unlike 'addConstraintWithArtificialVariable', an equality constraint becomes two rows.--- -addConstraint :: Real r => LA.Atom r -> LP r ()-addConstraint c = do-  OrdRel lhs rop rhs <- expandDefs' c-  let-    (b', e) = LA.extract LA.unitVar (lhs ^-^ rhs)-    b = - b'-  case rop of-    Le -> f e b-    Ge -> f (negateV e) (negate b)-    Eql -> do-      -- Unlike addConstraintWithArtificialVariable, an equality constraint becomes two rows.-      f e b-      f (negateV e) (negate b)-    _ -> error $ "ToySolver.LPSolver.addConstraint does not support " ++ show rop-  where-    -- -x≤b with b≥0 is trivially true.-    f e b | isSingleNegatedVar e && 0 <= b = return ()-    f e b = do-      tbl <- getTableau-      v <- newVar -- slack variable-      putTableau $ Simplex.addRow tbl v (LA.coeffMap e, b)--isSingleVar :: Real r => LA.Expr r -> Bool-isSingleVar e =-  case LA.terms e of-    [(1,_)] -> True-    _ -> False--isSingleNegatedVar :: Real r => LA.Expr r -> Bool-isSingleNegatedVar e =-  case LA.terms e of-    [(-1,_)] -> True-    _ -> False--expandDefs :: (Num r, Eq r) => LA.Expr r -> LP r (LA.Expr r)-expandDefs e = do-  defs <- getDefs-  return $ LA.applySubst defs e--expandDefs' :: (Num r, Eq r) => LA.Atom r -> LP r (LA.Atom r)-expandDefs' (OrdRel lhs op rhs) = do-  lhs' <- expandDefs lhs-  rhs' <- expandDefs rhs-  return $ OrdRel lhs' op rhs'--tableau :: (RealFrac r) => [LA.Atom r] -> LP r ()-tableau cs = do-  let (nonnegVars, cs') = collectNonnegVars cs IS.empty-      fvs = vars cs `IS.difference` nonnegVars-  forM_ (IS.toList fvs) $ \v -> do-    v1 <- newVar-    v2 <- newVar-    define v (LA.var v1 ^-^ LA.var v2)-  mapM_ addConstraint cs'--getModel :: Fractional r => VarSet -> LP r (Model r)-getModel vs = do-  tbl <- getTableau-  defs <- getDefs-  let vs' = (vs `IS.difference` IM.keysSet defs) `IS.union` IS.unions [vars e | e <- IM.elems defs]-      m0 = IM.fromAscList [(v, Simplex.currentValue tbl v) | v <- IS.toAscList vs']-  return $ IM.filterWithKey (\k _ -> k `IS.member` vs) $ IM.map (LA.evalExpr m0) defs `IM.union` m0--phaseI :: (Fractional r, Real r) => LP r Bool-phaseI = do-  introduceArtificialVariables-  tbl <- getTableau-  avs <- getArtificialVariables-  let (ret, tbl') = Simplex.phaseI tbl avs-  putTableau tbl'-  when ret clearArtificialVariables-  return ret--introduceArtificialVariables :: (Real r) => LP r ()-introduceArtificialVariables = do-  tbl <- getTableau-  tbl' <- liftM IM.fromList $ forM (IM.toList tbl) $ \(v,(e,rhs)) -> do-    if rhs >= 0 then do-      return (v,(e,rhs)) -- v + e == rhs-    else do-      a <- newVar-      addArtificialVariable a-      return (a, (IM.insert v (-1) (IM.map negate e), -rhs)) -- a - (v + e) == -rhs-  putTableau tbl'--simplex :: (Fractional r, Real r) => OptDir -> LA.Expr r -> LP r Bool-simplex optdir obj = do-  tbl <- getTableau-  defs <- getDefs-  let (ret, tbl') = Simplex.simplex optdir (Simplex.setObjFun tbl (LA.applySubst defs obj))-  putTableau tbl'-  return ret--dualSimplex :: (Fractional r, Real r) => OptDir -> LA.Expr r -> LP r Bool-dualSimplex optdir obj = do-  tbl <- getTableau-  defs <- getDefs-  let (ret, tbl') = Simplex.dualSimplex optdir (Simplex.setObjFun tbl (LA.applySubst defs obj))-  putTableau tbl'-  return ret---- | results of optimization-data OptResult = Optimum | Unsat | Unbounded-  deriving (Show, Eq, Ord)--twoPhaseSimplex :: (Fractional r, Real r) => OptDir -> LA.Expr r -> LP r OptResult-twoPhaseSimplex optdir obj = do-  ret <- phaseI-  if not ret then-    return Unsat-  else do-    ret <- simplex optdir obj-    if ret then-      return Optimum-    else-      return Unbounded--primalDualSimplex :: (Fractional r, Real r) => OptDir -> LA.Expr r -> LP r OptResult-primalDualSimplex optdir obj = do-  tbl <- getTableau-  defs <- getDefs-  let (ret, tbl') = Simplex.primalDualSimplex optdir (Simplex.setObjFun tbl (LA.applySubst defs obj))-  putTableau tbl'-  if ret then-    return Optimum-  else if not (Simplex.isFeasible tbl') then-    return Unsat-  else-    return Unbounded---- ------------------------------------------------------------------------------- convert right hand side to be non-negative-normalizeConstraint :: forall r. Real r => LA.Atom r -> (LA.Expr r, RelOp, r)-normalizeConstraint (OrdRel a op b)-  | rhs < 0   = (negateV lhs, flipOp op, negate rhs)-  | otherwise = (lhs, op, rhs)-  where-    (c, lhs) = LA.extract LA.unitVar (a ^-^ b)-    rhs = - c--collectNonnegVars :: forall r. (RealFrac r) => [LA.Atom r] -> VarSet -> (VarSet, [LA.Atom r])-collectNonnegVars cs ivs = (nonnegVars, cs)-  where-    vs = vars cs-    bounds = BI.inferBounds initialBounds cs ivs 1000-      where-        initialBounds = IM.fromAscList [(v, Interval.whole) | v <- IS.toAscList vs]-    nonnegVars = IS.filter (\v -> 0 <=! (bounds IM.! v)) vs--    isTriviallyTrue :: LA.Atom r -> Bool-    isTriviallyTrue (OrdRel a op b) =-      case op of-        Le -> i <=! 0-        Ge -> i >=! 0-        Lt -> i <! 0-        Gt -> i >! 0-        Eql -> i ==! 0-        NEq -> i /=! 0-      where-        i = LA.computeInterval bounds (a ^-^ b)---- ---------------------------------------------------------------------------
− src/ToySolver/Arith/LPSolverHL.hs
@@ -1,275 +0,0 @@-{-# LANGUAGE ScopedTypeVariables #-}-{-# OPTIONS_GHC -Wall #-}--------------------------------------------------------------------------------- |--- Module      :  ToySolver.Arith.LPSolverHL--- Copyright   :  (c) Masahiro Sakai 2011--- License     :  BSD-style--- --- Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  provisional--- Portability :  non-portable (ScopedTypeVariables)------ High-Level API for LPSolver.hs-----------------------------------------------------------------------------------module ToySolver.Arith.LPSolverHL-  ( OptResult (..)-  , minimize-  , maximize-  , optimize-  , solve-  ) where--import Control.Monad.State-import qualified Data.IntMap as IM-import qualified Data.IntSet as IS-import Data.OptDir-import Data.VectorSpace--import ToySolver.Data.OrdRel-import qualified ToySolver.Data.LA as LA-import ToySolver.Data.Var-import qualified ToySolver.Arith.Simplex as Simplex-import qualified ToySolver.Arith.LPSolver as LPSolver-import ToySolver.Arith.LPSolver hiding (OptResult (..))---- ------------------------------------------------------------------------------- | 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) => LA.Expr r -> [LA.Atom r] -> OptResult r-minimize = optimize OptMin--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 Nothing-      else do-        m <- getModel vs-        return (Just m)-  where-    vs = vars cs--optimize :: (RealFrac r) => OptDir -> LA.Expr r -> [LA.Atom r] -> OptResult r-optimize optdir obj cs =-  flip evalState (emptySolver vs) $ do-    tableau cs-    ret <- LPSolver.twoPhaseSimplex optdir obj-    case ret of-      LPSolver.Unsat -> return OptUnsat-      LPSolver.Unbounded -> return Unbounded-      LPSolver.Optimum -> do-        m <- getModel vs-        tbl <- getTableau -        return $ Optimum (Simplex.currentObjValue tbl) m-  where-    vs = vars cs `IS.union` vars obj---- ------------------------------------------------------------------------------ Test cases--example_3_2 :: (LA.Expr Rational, [LA.Atom Rational])-example_3_2 = (obj, cond)-  where-    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-test_3_2 =-  uncurry maximize example_3_2 == -  Optimum (27/5) (IM.fromList [(1,1/5),(2,0),(3,8/5)])--example_3_5 :: (LA.Expr Rational, [LA.Atom Rational])-example_3_5 = (obj, cond)-  where-    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-test_3_5 =-  uncurry minimize example_3_5 ==-  Optimum 19 (IM.fromList [(1,-1),(2,0),(3,1),(4,0),(5,2)])--example_4_1 :: (LA.Expr Rational, [LA.Atom Rational])-example_4_1 = (obj, cond)-  where-    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-test_4_1 =-  uncurry maximize example_4_1 ==-  OptUnsat--example_4_2 :: (LA.Expr Rational, [LA.Atom Rational])-example_4_2 = (obj, cond)-  where-    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-test_4_2 =-  uncurry maximize example_4_2 ==-  Unbounded--example_4_3 :: (LA.Expr Rational, [LA.Atom Rational])-example_4_3 = (obj, cond)-  where-    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-test_4_3 =-  uncurry maximize example_4_3 ==-  Optimum 12 (IM.fromList [(1,4),(2,6)])--example_4_5 :: (LA.Expr Rational, [LA.Atom Rational])-example_4_5 = (obj, cond)-  where-    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-test_4_5 =-  uncurry maximize example_4_5 ==-  Optimum 5 (IM.fromList [(1,3/2),(2,2)])--example_4_6 :: (LA.Expr Rational, [LA.Atom Rational])-example_4_6 = (obj, cond)-  where-    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-test_4_6 =-  uncurry maximize example_4_6 ==-  Optimum (165/4) (IM.fromList [(1,2),(2,1),(3,0),(4,1)])--example_4_7 :: (LA.Expr Rational, [LA.Atom Rational])-example_4_7 = (obj, cond)-  where-    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-test_4_7 =-  uncurry maximize example_4_7 ==-  Optimum (48/11) (IM.fromList [(1,0),(2,0),(3,81),(4,41)])---- 退化して巡回の起こるKuhnの7変数3制約の例-kuhn_7_3 :: (LA.Expr Rational, [LA.Atom Rational])-kuhn_7_3 = (obj, cond)-  where-    [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-test_kuhn_7_3 =-  uncurry minimize kuhn_7_3 ==-  Optimum (-2) (IM.fromList [(1,2),(2,0),(3,0),(4,2),(5,0),(6,2),(7,0)])--testAll :: Bool-testAll = and-  [ test_3_2-  , test_3_5-  , test_4_1-  , test_4_2-  , test_4_3-  , test_4_5-  , test_4_6-  , test_4_7-  , test_kuhn_7_3-  ]---- ---------------------------------------------------------------------------
src/ToySolver/Arith/LPUtil.hs view
@@ -15,7 +15,7 @@  import ToySolver.Data.OrdRel import qualified ToySolver.Data.LA as LA-import ToySolver.Data.Var+import ToySolver.Data.IntVar import qualified ToySolver.Arith.BoundsInference as BI  toStandardForm@@ -27,10 +27,11 @@   where     vs = vars obj `IS.union` vars cs     (prob2,s) = toStandardForm' prob1+    mt :: Model Rational -> Model Rational     mt m = IM.fromAscList $ do       v <- IS.toAscList vs       case IM.lookup v s of-        Just def -> return (v, LA.evalExpr m def)+        Just def -> return (v, LA.eval m def)         Nothing  -> return (v, m IM.! v)  type M = State Var
+ src/ToySolver/Arith/MIP.hs view
@@ -0,0 +1,501 @@+{-# LANGUAGE ScopedTypeVariables, Rank2Types #-}+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Arith.MIP+-- Copyright   :  (c) Masahiro Sakai 2012+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable (ScopedTypeVariables, Rank2Types)+--+-- Naïve implementation of MIP solver based on Simplex module+-- +-- Reference:+--+-- * <http://www.math.cuhk.edu.hk/~wei/lpch3.pdf>+-- +-- * Ralph E. Gomory.+--   \"An Algorithm for the Mixed Integer Problem\", Technical Report+--   RM-2597, 1960, The Rand Corporation, Santa Monica, CA.+--   <http://www.rand.org/pubs/research_memoranda/RM2597.html>+--+-- * Ralph E. Gomory.+--   \"Outline of an algorithm for integer solutions to linear programs\".+--   Bull. Amer. Math. Soc., Vol. 64, No. 5. (1958), pp. 275-278.+--   <http://projecteuclid.org/euclid.bams/1183522679>+-- +-- * R. C. Daniel and Martyn Jeffreys.+--   \"Unboundedness in Integer and Discrete Programming L.P. Relaxations\"+--   The Journal of the Operational Research Society, Vol. 30, No. 12. (1979)+--   <http://www.jstor.org/stable/3009435>+-- +-----------------------------------------------------------------------------+module ToySolver.Arith.MIP+  (+  -- * The @Solver@ type+    Solver+  , newSolver++  -- * Solving+  , optimize++  -- * Extract results+  , getBestSolution+  , getBestValue+  , getBestModel++  -- * Configulation+  , setNThread+  , setLogger+  , setOnUpdateBestSolution+  , setShowRational+  ) where++import Prelude hiding (log)++import Control.Monad+import Control.Exception+import Control.Concurrent+import Control.Concurrent.STM+import Data.Default.Class+import Data.List+import Data.OptDir+import Data.Ord+import Data.IORef+import Data.Maybe+import qualified Data.IntSet as IS+import qualified Data.IntMap as IM+import qualified Data.Map as Map+import qualified Data.Sequence as Seq+import qualified Data.Foldable as F+import Data.VectorSpace+import System.Clock+import System.Timeout+import Text.Printf++import qualified ToySolver.Data.LA as LA+import ToySolver.Data.OrdRel ((.<=.), (.>=.))+import qualified ToySolver.Arith.Simplex as Simplex+import ToySolver.Arith.Simplex (OptResult (..), Var, Model)+import ToySolver.Internal.Util (isInteger, fracPart)++data Solver+  = MIP+  { mipRootLP :: Simplex.Solver+  , mipIVs    :: IS.IntSet+  , mipBest   :: TVar (Maybe Node)++  , mipNThread :: IORef Int+  , mipLogger  :: IORef (Maybe (String -> IO ()))+  , mipOnUpdateBestSolution :: IORef (Model -> Rational -> IO ())+  , mipShowRational :: IORef Bool+  }++data Node =+  Node+  { ndLP    :: Simplex.Solver+  , ndDepth :: {-# UNPACK #-} !Int+  , ndValue :: Rational+  }++newSolver :: Simplex.Solver -> IS.IntSet -> IO Solver+newSolver lp ivs = do+  lp2 <- Simplex.cloneSolver lp++  forM_ (IS.toList ivs) $ \v -> do+    lb <- Simplex.getLB lp2 v+    case lb of+      Just (l,_) | not (isInteger l) ->+        Simplex.assertLower lp2 v (fromInteger (ceiling l))+      _ -> return ()+    ub <- Simplex.getUB lp2 v+    case ub of+      Just (u,_) | not (isInteger u) ->+        Simplex.assertLower lp2 v (fromInteger (floor u))+      _ -> return ()++  bestRef <- newTVarIO Nothing++  nthreadRef <- newIORef 0+  logRef  <- newIORef Nothing+  showRef <- newIORef False+  updateRef <- newIORef (\_ _ -> return ())++  return $+    MIP+    { mipRootLP = lp2+    , mipIVs    = ivs+    , mipBest   = bestRef++    , mipNThread = nthreadRef+    , mipLogger = logRef+    , mipOnUpdateBestSolution = updateRef+    , mipShowRational = showRef+    }++optimize :: Solver -> IO OptResult+optimize solver = do+  let lp = mipRootLP solver+  update <- readIORef (mipOnUpdateBestSolution solver)+  log solver "MIP: Solving LP relaxation..."+  ret <- Simplex.check lp+  if not ret+  then return Unsat+  else do+    s0 <- showValue solver =<< Simplex.getObjValue lp+    log solver (printf "MIP: LP relaxation is satisfiable with obj = %s" s0)+    log solver "MIP: Optimizing LP relaxation"+    ret2 <- Simplex.optimize lp def+    case ret2 of+      Unsat    -> error "should not happen"+      ObjLimit -> error "should not happen"+      Unbounded -> do+        log solver "MIP: LP relaxation is unbounded"+        let ivs = mipIVs solver+        if IS.null ivs+          then return Unbounded+          else do+            {-+              * In general, original problem may have optimal+                solution even though LP relaxiation is unbounded.+              * But if restricted to rational numbers, the+                original problem is unbounded or unsatisfiable+                when LP relaxation is unbounded.+            -}+            origObj <- Simplex.getObj lp+            lp2 <- Simplex.cloneSolver lp+            Simplex.clearLogger lp2+            Simplex.setObj lp2 (LA.constant 0)+            branchAndBound solver lp2 $ \m _ -> do+              update m (LA.eval m origObj)+            best <- readTVarIO (mipBest solver)+            case best of+              Just nd -> do+                m <- Simplex.getModel (ndLP nd)+                atomically $ writeTVar (mipBest solver) $ Just nd{ ndValue = LA.eval m origObj }+                return Unbounded+              Nothing -> return Unsat+      Optimum -> do+        s1 <- showValue solver =<< Simplex.getObjValue lp+        log solver $ "MIP: LP relaxation optimum is " ++ s1+        log solver "MIP: Integer optimization begins..."+        Simplex.clearLogger lp+        branchAndBound solver lp update+        m <- readTVarIO (mipBest solver)+        case m of+          Nothing -> return Unsat+          Just _ -> return Optimum++branchAndBound :: Solver -> Simplex.Solver -> (Model -> Rational -> IO ()) -> IO ()+branchAndBound solver rootLP update = do+  dir <- Simplex.getOptDir rootLP+  rootVal <- Simplex.getObjValue rootLP+  let root = Node{ ndLP = rootLP, ndDepth = 0, ndValue = rootVal }++  pool <- newTVarIO (Seq.singleton root)+  activeThreads <- newTVarIO (Map.empty)+  visitedNodes <- newTVarIO 0+  solchan <- newTChanIO++  let addNode :: Node -> STM ()+      addNode nd = do+        modifyTVar pool (Seq.|> nd)++      pickNode :: IO (Maybe Node)+      pickNode = do+        self <- myThreadId+        atomically $ modifyTVar activeThreads (Map.delete self)+        atomically $ do+          s <- readTVar pool+          case Seq.viewl s of+            nd Seq.:< s2 -> do+              writeTVar pool s2+              modifyTVar activeThreads (Map.insert self nd)+              return (Just nd)+            Seq.EmptyL -> do+              ths <- readTVar activeThreads+              if Map.null ths+                then return Nothing+                else retry++      processNode :: Node -> IO ()+      processNode node = do+        let lp = ndLP node+        lim <- liftM (fmap ndValue) $ readTVarIO (mipBest solver)+        ret <- Simplex.dualSimplex lp def{ Simplex.objLimit = lim }++        case ret of+          Unbounded -> error "should not happen"+          Unsat ->  return ()+          ObjLimit -> return ()+          Optimum -> do+            val <- Simplex.getObjValue lp+            p <- prune solver val+            unless p $ do+              xs <- violated node (mipIVs solver)+              case xs of+                [] -> atomically $ writeTChan solchan $ node { ndValue = val }+                _ -> do+                  r <- if ndDepth node `mod` 100 /= 0+                       then return Nothing+                       else liftM listToMaybe $ filterM (canDeriveGomoryCut lp) $ map fst xs+                  case r of+                    Nothing -> do -- branch+                      let (v0,val0) = fst $ maximumBy (comparing snd)+                                      [((v,vval), abs (fromInteger (round vval) - vval)) | (v,vval) <- xs]+                      let lp1 = lp+                      lp2 <- Simplex.cloneSolver lp+                      Simplex.assertAtom lp1 (LA.var v0 .<=. LA.constant (fromInteger (floor val0)))+                      Simplex.assertAtom lp2 (LA.var v0 .>=. LA.constant (fromInteger (ceiling val0)))+                      atomically $ do+                        addNode $ Node lp1 (ndDepth node + 1) val+                        addNode $ Node lp2 (ndDepth node + 1) val+                        modifyTVar visitedNodes (+1)+                    Just v -> do -- cut+                      atom <- deriveGomoryCut lp (mipIVs solver) v+                      Simplex.assertAtom lp atom+                      atomically $ do+                        addNode $ Node lp (ndDepth node + 1) val++  let isCompleted = do+        nodes <- readTVar pool+        threads <- readTVar activeThreads+        return $ Seq.null nodes && Map.null threads++  -- fork worker threads+  nthreads <- liftM (max 1) $ readIORef (mipNThread solver)++  log solver $ printf "MIP: forking %d worker threads..." nthreads++  startCPU <- getTime ProcessCPUTime+  startWC  <- getTime Monotonic+  ex <- newEmptyTMVarIO++  let printStatus :: Seq.Seq Node -> Int -> IO ()+      printStatus nodes visited+        | Seq.null nodes = return () -- should not happen+        | otherwise = do+            nowCPU <- getTime ProcessCPUTime+            nowWC  <- getTime Monotonic+            let spentCPU = sec (nowCPU `diffTimeSpec` startCPU)+            let spentWC  = sec (nowWC  `diffTimeSpec` startWC )++            let vs = map ndValue (F.toList nodes)+                dualBound =+                  case dir of+                    OptMin -> minimum vs+                    OptMax -> maximum vs++            primalBound <- do+              x <- readTVarIO (mipBest solver) -- TODO: 引数にするようにした方が良い?+              return $ case x of+                Nothing -> Nothing+                Just node -> Just (ndValue node)++            (p,g) <- case primalBound of+                   Nothing -> return ("not yet found", "--")+                   Just val -> do+                     p <- showValue solver val+                     let g = if val == 0+                             then "inf"+                             else printf "%.2f%%" (fromRational (abs (dualBound - val) * 100 / abs val) :: Double)+                     return (p, g)+            d <- showValue solver dualBound+ +            let range =+                  case dir of+                    OptMin -> p ++ " >= " ++ d+                    OptMax -> p ++ " <= " ++ d++            log solver $ printf "cpu time = %d sec; wc time = %d sec; active nodes = %d; visited nodes = %d; %s; gap = %s"+              spentCPU spentWC (Seq.length nodes) visited range g++  mask $ \(restore :: forall a. IO a -> IO a) -> do+    threads <- replicateM nthreads $ do+      forkIO $ do+        let loop = do+              m <- pickNode+              case m of+                Nothing -> return ()+                Just node -> processNode node >> loop+        ret <- try $ restore loop+        case ret of+          Left e -> atomically (putTMVar ex e)+          Right _ -> return ()    ++    let propagateException :: SomeException -> IO ()+        propagateException e = do+          mapM_ (\t -> throwTo t e) threads+          throwIO e++    let loop = do+          ret <- try $ timeout (2*1000*1000) $ restore $ atomically $ msum+            [ do node <- readTChan solchan+                 ret <- do+                   old <- readTVar (mipBest solver)+                   case old of+                     Nothing -> do+                       writeTVar (mipBest solver) (Just node)+                       return True+                     Just best -> do+                       let isBetter = if dir==OptMin then ndValue node < ndValue best else ndValue node > ndValue best+                       when isBetter $ writeTVar (mipBest solver) (Just node)+                       return isBetter+                 return $ do+                   when ret $ do+                     let lp = ndLP node+                     m <- Simplex.getModel lp+                     update m (ndValue node)+                   loop+            , do b <- isCompleted+                 guard b+                 return $ return ()+            , do e <- readTMVar ex+                 return $ propagateException e+            ]++          case ret of+            Left (e::SomeException) -> propagateException e+            Right (Just m) -> m+            Right Nothing -> do -- timeout+              (nodes, visited) <- atomically $ do+                nodes    <- readTVar pool+                athreads <- readTVar activeThreads+                visited  <- readTVar visitedNodes+                return (Seq.fromList (Map.elems athreads) Seq.>< nodes, visited)+              printStatus nodes visited+              loop++    loop++getBestSolution :: Solver -> IO (Maybe (Model, Rational))+getBestSolution solver = do+  ret <- readTVarIO (mipBest solver)+  case ret of+    Nothing -> return Nothing+    Just node -> do+      m <- Simplex.getModel (ndLP node)+      return $ Just (m, ndValue node)++getBestModel :: Solver -> IO (Maybe Model)+getBestModel solver = liftM (fmap fst) $ getBestSolution solver++getBestValue :: Solver -> IO (Maybe Rational)+getBestValue solver = liftM (fmap snd) $ getBestSolution solver++violated :: Node -> IS.IntSet -> IO [(Var, Rational)]+violated node ivs = do+  m <- Simplex.getModel (ndLP node)+  let p (v,val) = v `IS.member` ivs && not (isInteger val)+  return $ filter p (IM.toList m)++prune :: Solver -> Rational -> IO Bool+prune solver lb = do+  b <- readTVarIO (mipBest solver)+  case b of+    Nothing -> return False+    Just node -> do+      dir <- Simplex.getOptDir (mipRootLP solver)+      return $ if dir==OptMin then ndValue node <= lb else ndValue node >= lb++showValue :: Solver -> Rational -> IO String+showValue solver v = do+  printRat <- readIORef (mipShowRational solver)+  return $ Simplex.showValue printRat v++setShowRational :: Solver -> Bool -> IO ()+setShowRational solver = writeIORef (mipShowRational solver)++setNThread :: Solver -> Int -> IO ()+setNThread solver = writeIORef (mipNThread solver)++{--------------------------------------------------------------------+  Logging+--------------------------------------------------------------------}++-- | set callback function for receiving messages.+setLogger :: Solver -> (String -> IO ()) -> IO ()+setLogger solver logger = do+  writeIORef (mipLogger solver) (Just logger)++setOnUpdateBestSolution :: Solver -> (Model -> Rational -> IO ()) -> IO ()+setOnUpdateBestSolution solver cb = do+  writeIORef (mipOnUpdateBestSolution solver) cb++log :: Solver -> String -> IO ()+log solver msg = logIO solver (return msg)++logIO :: Solver -> IO String -> IO ()+logIO solver action = do+  m <- readIORef (mipLogger solver)+  case m of+    Nothing -> return ()+    Just logger -> action >>= logger++{--------------------------------------------------------------------+  GomoryCut+--------------------------------------------------------------------}++deriveGomoryCut :: Simplex.Solver -> IS.IntSet -> Var -> IO (LA.Atom Rational)+deriveGomoryCut lp ivs xi = do+  v0 <- Simplex.getValue lp xi+  let f0 = fracPart v0+  assert (0 < f0 && f0 < 1) $ return ()++  row <- Simplex.getRow lp xi++  -- remove fixed variables+  let p (_,xj) = do+        lb <- Simplex.getLB lp xj+        ub <- Simplex.getUB lp xj+        case (lb,ub) of+          (Just l, Just u) -> return (l < u)+          _ -> return True+  ns <- filterM p $ LA.terms row++  js <- flip filterM ns $ \(_, xj) -> do+    vj <- Simplex.getValue lp xj+    lb <- Simplex.getLB lp xj+    return $ Just vj == Simplex.boundValue lb+  ks <- flip filterM ns $ \(_, xj) -> do+    vj <- Simplex.getValue lp xj+    ub <- Simplex.getUB lp xj+    return $ Just vj == Simplex.boundValue ub++  xs1 <- forM js $ \(aij, xj) -> do+    let fj = fracPart aij+    Just (lj,_) <- Simplex.getLB lp xj+    let c = if xj `IS.member` ivs+            then (if fj <= 1 - f0 then fj  / (1 - f0) else ((1 - fj) / f0))+            else (if aij > 0      then aij / (1 - f0) else (-aij     / f0))+    return $ c *^ (LA.var xj ^-^ LA.constant lj)+  xs2 <- forM ks $ \(aij, xj) -> do+    let fj = fracPart aij+    Just (uj, _) <- Simplex.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 $ sumV xs1 ^+^ sumV xs2 .>=. LA.constant 1++-- TODO: Simplexをδに対応させたら、xi, xj がδを含まない有理数であるという条件も必要+canDeriveGomoryCut :: Simplex.Solver -> Var -> IO Bool+canDeriveGomoryCut lp xi = do+  b <- Simplex.isBasicVariable lp xi+  if not b+    then return False+    else do+      val <- Simplex.getValue lp xi+      if isInteger val+        then return False+        else do+          row <- Simplex.getRow lp xi+          ys <- forM (LA.terms row) $ \(_,xj) -> do+            vj <- Simplex.getValue lp xj+            lb <- Simplex.getLB lp xj+            ub <- Simplex.getUB lp xj+            return $ Just vj == Simplex.boundValue lb || Just vj == Simplex.boundValue ub+          return (and ys)
− src/ToySolver/Arith/MIPSolver2.hs
@@ -1,502 +0,0 @@-{-# LANGUAGE ScopedTypeVariables, Rank2Types #-}-{-# OPTIONS_GHC -Wall #-}--------------------------------------------------------------------------------- |--- Module      :  ToySolver.Arith.MIPSolver2--- Copyright   :  (c) Masahiro Sakai 2012--- License     :  BSD-style--- --- Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  provisional--- Portability :  non-portable (ScopedTypeVariables, Rank2Types)------ Naïve implementation of MIP solver based on Simplex2 module--- --- Reference:------ * <http://www.math.cuhk.edu.hk/~wei/lpch3.pdf>--- --- * Ralph E. Gomory.---   \"An Algorithm for the Mixed Integer Problem\", Technical Report---   RM-2597, 1960, The Rand Corporation, Santa Monica, CA.---   <http://www.rand.org/pubs/research_memoranda/RM2597.html>------ * Ralph E. Gomory.---   \"Outline of an algorithm for integer solutions to linear programs\".---   Bull. Amer. Math. Soc., Vol. 64, No. 5. (1958), pp. 275-278.---   <http://projecteuclid.org/euclid.bams/1183522679>--- --- * R. C. Daniel and Martyn Jeffreys.---   \"Unboundedness in Integer and Discrete Programming L.P. Relaxations\"---   The Journal of the Operational Research Society, Vol. 30, No. 12. (1979)---   <http://www.jstor.org/stable/3009435>--- -------------------------------------------------------------------------------module ToySolver.Arith.MIPSolver2-  (-  -- * The @Solver@ type-    Solver-  , newSolver--  -- * Solving-  , optimize--  -- * Extract results-  , getBestSolution-  , getBestValue-  , getBestModel--  -- * Configulation-  , setNThread-  , setLogger-  , setOnUpdateBestSolution-  , setShowRational-  ) where--import Prelude hiding (log)--import Control.Monad-import Control.Exception-import Control.Concurrent-import Control.Concurrent.STM-import Data.Default.Class-import Data.List-import Data.OptDir-import Data.Ord-import Data.IORef-import Data.Maybe-import qualified Data.IntSet as IS-import qualified Data.IntMap as IM-import qualified Data.Map as Map-import qualified Data.Sequence as Seq-import qualified Data.Foldable as F-import Data.VectorSpace-import Data.Time-import System.CPUTime-import System.Timeout-import Text.Printf--import qualified ToySolver.Data.LA as LA-import ToySolver.Data.OrdRel ((.<=.), (.>=.))-import qualified ToySolver.Arith.Simplex2 as Simplex2-import ToySolver.Arith.Simplex2 (OptResult (..), Var, Model)-import ToySolver.Internal.Util (isInteger, fracPart)--data Solver-  = MIP-  { mipRootLP :: Simplex2.Solver-  , mipIVs    :: IS.IntSet-  , mipBest   :: TVar (Maybe Node)--  , mipNThread :: IORef Int-  , mipLogger  :: IORef (Maybe (String -> IO ()))-  , mipOnUpdateBestSolution :: IORef (Model -> Rational -> IO ())-  , mipShowRational :: IORef Bool-  }--data Node =-  Node-  { ndLP    :: Simplex2.Solver-  , ndDepth :: {-# UNPACK #-} !Int-  , ndValue :: Rational-  }--newSolver :: Simplex2.Solver -> IS.IntSet -> IO Solver-newSolver lp ivs = do-  lp2 <- Simplex2.cloneSolver lp--  forM_ (IS.toList ivs) $ \v -> do-    lb <- Simplex2.getLB lp2 v-    case lb of-      Just (l,_) | not (isInteger l) ->-        Simplex2.assertLower lp2 v (fromInteger (ceiling l))-      _ -> return ()-    ub <- Simplex2.getUB lp2 v-    case ub of-      Just (u,_) | not (isInteger u) ->-        Simplex2.assertLower lp2 v (fromInteger (floor u))-      _ -> return ()--  bestRef <- newTVarIO Nothing--  nthreadRef <- newIORef 0-  logRef  <- newIORef Nothing-  showRef <- newIORef False-  updateRef <- newIORef (\_ _ -> return ())--  return $-    MIP-    { mipRootLP = lp2-    , mipIVs    = ivs-    , mipBest   = bestRef--    , mipNThread = nthreadRef-    , mipLogger = logRef-    , mipOnUpdateBestSolution = updateRef-    , mipShowRational = showRef-    }--optimize :: Solver -> IO OptResult-optimize solver = do-  let lp = mipRootLP solver-  update <- readIORef (mipOnUpdateBestSolution solver)-  log solver "MIP: Solving LP relaxation..."-  ret <- Simplex2.check lp-  if not ret-  then return Unsat-  else do-    s0 <- showValue solver =<< Simplex2.getObjValue lp-    log solver (printf "MIP: LP relaxation is satisfiable with obj = %s" s0)-    log solver "MIP: Optimizing LP relaxation"-    ret2 <- Simplex2.optimize lp def-    case ret2 of-      Unsat    -> error "should not happen"-      ObjLimit -> error "should not happen"-      Unbounded -> do-        log solver "MIP: LP relaxation is unbounded"-        let ivs = mipIVs solver-        if IS.null ivs-          then return Unbounded-          else do-            {--              * In general, original problem may have optimal-                solution even though LP relaxiation is unbounded.-              * But if restricted to rational numbers, the-                original problem is unbounded or unsatisfiable-                when LP relaxation is unbounded.-            -}-            origObj <- Simplex2.getObj lp-            lp2 <- Simplex2.cloneSolver lp-            Simplex2.clearLogger lp2-            Simplex2.setObj lp2 (LA.constant 0)-            branchAndBound solver lp2 $ \m _ -> do-              update m (LA.evalExpr m origObj)-            best <- readTVarIO (mipBest solver)-            case best of-              Just nd -> do-                m <- Simplex2.getModel (ndLP nd)-                atomically $ writeTVar (mipBest solver) $ Just nd{ ndValue = LA.evalExpr m origObj }-                return Unbounded-              Nothing -> return Unsat-      Optimum -> do-        s1 <- showValue solver =<< Simplex2.getObjValue lp-        log solver $ "MIP: LP relaxation optimum is " ++ s1-        log solver "MIP: Integer optimization begins..."-        Simplex2.clearLogger lp-        branchAndBound solver lp update-        m <- readTVarIO (mipBest solver)-        case m of-          Nothing -> return Unsat-          Just _ -> return Optimum--branchAndBound :: Solver -> Simplex2.Solver -> (Model -> Rational -> IO ()) -> IO ()-branchAndBound solver rootLP update = do-  dir <- Simplex2.getOptDir rootLP-  rootVal <- Simplex2.getObjValue rootLP-  let root = Node{ ndLP = rootLP, ndDepth = 0, ndValue = rootVal }--  pool <- newTVarIO (Seq.singleton root)-  activeThreads <- newTVarIO (Map.empty)-  visitedNodes <- newTVarIO 0-  solchan <- newTChanIO--  let addNode :: Node -> STM ()-      addNode nd = do-        modifyTVar pool (Seq.|> nd)--      pickNode :: IO (Maybe Node)-      pickNode = do-        self <- myThreadId-        atomically $ modifyTVar activeThreads (Map.delete self)-        atomically $ do-          s <- readTVar pool-          case Seq.viewl s of-            nd Seq.:< s2 -> do-              writeTVar pool s2-              modifyTVar activeThreads (Map.insert self nd)-              return (Just nd)-            Seq.EmptyL -> do-              ths <- readTVar activeThreads-              if Map.null ths-                then return Nothing-                else retry--      processNode :: Node -> IO ()-      processNode node = do-        let lp = ndLP node-        lim <- liftM (fmap ndValue) $ readTVarIO (mipBest solver)-        ret <- Simplex2.dualSimplex lp def{ Simplex2.objLimit = lim }--        case ret of-          Unbounded -> error "should not happen"-          Unsat ->  return ()-          ObjLimit -> return ()-          Optimum -> do-            val <- Simplex2.getObjValue lp-            p <- prune solver val-            unless p $ do-              xs <- violated node (mipIVs solver)-              case xs of-                [] -> atomically $ writeTChan solchan $ node { ndValue = val }-                _ -> do-                  r <- if ndDepth node `mod` 100 /= 0-                       then return Nothing-                       else liftM listToMaybe $ filterM (canDeriveGomoryCut lp) $ map fst xs-                  case r of-                    Nothing -> do -- branch-                      let (v0,val0) = fst $ maximumBy (comparing snd)-                                      [((v,vval), abs (fromInteger (round vval) - vval)) | (v,vval) <- xs]-                      let lp1 = lp-                      lp2 <- Simplex2.cloneSolver lp-                      Simplex2.assertAtom lp1 (LA.var v0 .<=. LA.constant (fromInteger (floor val0)))-                      Simplex2.assertAtom lp2 (LA.var v0 .>=. LA.constant (fromInteger (ceiling val0)))-                      atomically $ do-                        addNode $ Node lp1 (ndDepth node + 1) val-                        addNode $ Node lp2 (ndDepth node + 1) val-                        modifyTVar visitedNodes (+1)-                    Just v -> do -- cut-                      atom <- deriveGomoryCut lp (mipIVs solver) v-                      Simplex2.assertAtom lp atom-                      atomically $ do-                        addNode $ Node lp (ndDepth node + 1) val--  let isCompleted = do-        nodes <- readTVar pool-        threads <- readTVar activeThreads-        return $ Seq.null nodes && Map.null threads--  -- fork worker threads-  nthreads <- liftM (max 1) $ readIORef (mipNThread solver)--  log solver $ printf "MIP: forking %d worker threads..." nthreads--  startCPU <- getCPUTime-  startWC  <- getCurrentTime-  ex <- newEmptyTMVarIO--  let printStatus :: Seq.Seq Node -> Int -> IO ()-      printStatus nodes visited-        | Seq.null nodes = return () -- should not happen-        | otherwise = do-            nowCPU <- getCPUTime-            nowWC  <- getCurrentTime-            let spentCPU = (nowCPU - startCPU) `div` 10^(12::Int)-            let spentWC  = round (nowWC `diffUTCTime` startWC) :: Int--            let vs = map ndValue (F.toList nodes)-                dualBound =-                  case dir of-                    OptMin -> minimum vs-                    OptMax -> maximum vs--            primalBound <- do-              x <- readTVarIO (mipBest solver) -- TODO: 引数にするようにした方が良い?-              return $ case x of-                Nothing -> Nothing-                Just node -> Just (ndValue node)--            (p,g) <- case primalBound of-                   Nothing -> return ("not yet found", "--")-                   Just val -> do-                     p <- showValue solver val-                     let g = if val == 0-                             then "inf"-                             else printf "%.2f%%" (fromRational (abs (dualBound - val) * 100 / abs val) :: Double)-                     return (p, g)-            d <- showValue solver dualBound- -            let range =-                  case dir of-                    OptMin -> p ++ " >= " ++ d-                    OptMax -> p ++ " <= " ++ d--            log solver $ printf "cpu time = %d sec; wc time = %d sec; active nodes = %d; visited nodes = %d; %s; gap = %s"-              spentCPU spentWC (Seq.length nodes) visited range g--  mask $ \(restore :: forall a. IO a -> IO a) -> do-    threads <- replicateM nthreads $ do-      forkIO $ do-        let loop = do-              m <- pickNode-              case m of-                Nothing -> return ()-                Just node -> processNode node >> loop-        ret <- try $ restore loop-        case ret of-          Left e -> atomically (putTMVar ex e)-          Right _ -> return ()    --    let propagateException :: SomeException -> IO ()-        propagateException e = do-          mapM_ (\t -> throwTo t e) threads-          throwIO e--    let loop = do-          ret <- try $ timeout (2*1000*1000) $ restore $ atomically $ msum-            [ do node <- readTChan solchan-                 ret <- do-                   old <- readTVar (mipBest solver)-                   case old of-                     Nothing -> do-                       writeTVar (mipBest solver) (Just node)-                       return True-                     Just best -> do-                       let isBetter = if dir==OptMin then ndValue node < ndValue best else ndValue node > ndValue best-                       when isBetter $ writeTVar (mipBest solver) (Just node)-                       return isBetter-                 return $ do-                   when ret $ do-                     let lp = ndLP node-                     m <- Simplex2.getModel lp-                     update m (ndValue node)-                   loop-            , do b <- isCompleted-                 guard b-                 return $ return ()-            , do e <- readTMVar ex-                 return $ propagateException e-            ]--          case ret of-            Left (e::SomeException) -> propagateException e-            Right (Just m) -> m-            Right Nothing -> do -- timeout-              (nodes, visited) <- atomically $ do-                nodes    <- readTVar pool-                athreads <- readTVar activeThreads-                visited  <- readTVar visitedNodes-                return (Seq.fromList (Map.elems athreads) Seq.>< nodes, visited)-              printStatus nodes visited-              loop--    loop--getBestSolution :: Solver -> IO (Maybe (Model, Rational))-getBestSolution solver = do-  ret <- readTVarIO (mipBest solver)-  case ret of-    Nothing -> return Nothing-    Just node -> do-      m <- Simplex2.getModel (ndLP node)-      return $ Just (m, ndValue node)--getBestModel :: Solver -> IO (Maybe Model)-getBestModel solver = liftM (fmap fst) $ getBestSolution solver--getBestValue :: Solver -> IO (Maybe Rational)-getBestValue solver = liftM (fmap snd) $ getBestSolution solver--violated :: Node -> IS.IntSet -> IO [(Var, Rational)]-violated node ivs = do-  m <- Simplex2.getModel (ndLP node)-  let p (v,val) = v `IS.member` ivs && not (isInteger val)-  return $ filter p (IM.toList m)--prune :: Solver -> Rational -> IO Bool-prune solver lb = do-  b <- readTVarIO (mipBest solver)-  case b of-    Nothing -> return False-    Just node -> do-      dir <- Simplex2.getOptDir (mipRootLP solver)-      return $ if dir==OptMin then ndValue node <= lb else ndValue node >= lb--showValue :: Solver -> Rational -> IO String-showValue solver v = do-  printRat <- readIORef (mipShowRational solver)-  return $ Simplex2.showValue printRat v--setShowRational :: Solver -> Bool -> IO ()-setShowRational solver = writeIORef (mipShowRational solver)--setNThread :: Solver -> Int -> IO ()-setNThread solver = writeIORef (mipNThread solver)--{---------------------------------------------------------------------  Logging---------------------------------------------------------------------}---- | set callback function for receiving messages.-setLogger :: Solver -> (String -> IO ()) -> IO ()-setLogger solver logger = do-  writeIORef (mipLogger solver) (Just logger)--setOnUpdateBestSolution :: Solver -> (Model -> Rational -> IO ()) -> IO ()-setOnUpdateBestSolution solver cb = do-  writeIORef (mipOnUpdateBestSolution solver) cb--log :: Solver -> String -> IO ()-log solver msg = logIO solver (return msg)--logIO :: Solver -> IO String -> IO ()-logIO solver action = do-  m <- readIORef (mipLogger solver)-  case m of-    Nothing -> return ()-    Just logger -> action >>= logger--{---------------------------------------------------------------------  GomoryCut---------------------------------------------------------------------}--deriveGomoryCut :: Simplex2.Solver -> IS.IntSet -> Var -> IO (LA.Atom Rational)-deriveGomoryCut lp ivs xi = do-  v0 <- Simplex2.getValue lp xi-  let f0 = fracPart v0-  assert (0 < f0 && f0 < 1) $ return ()--  row <- Simplex2.getRow lp xi--  -- remove fixed variables-  let p (_,xj) = do-        lb <- Simplex2.getLB lp xj-        ub <- Simplex2.getUB lp xj-        case (lb,ub) of-          (Just l, Just u) -> return (l < u)-          _ -> return True-  ns <- filterM p $ LA.terms row--  js <- flip filterM ns $ \(_, xj) -> do-    vj <- Simplex2.getValue lp xj-    lb <- Simplex2.getLB lp xj-    return $ Just vj == Simplex2.boundValue lb-  ks <- flip filterM ns $ \(_, xj) -> do-    vj <- Simplex2.getValue lp xj-    ub <- Simplex2.getUB lp xj-    return $ Just vj == Simplex2.boundValue ub--  xs1 <- forM js $ \(aij, xj) -> do-    let fj = fracPart aij-    Just (lj,_) <- Simplex2.getLB lp xj-    let c = if xj `IS.member` ivs-            then (if fj <= 1 - f0 then fj  / (1 - f0) else ((1 - fj) / f0))-            else (if aij > 0      then aij / (1 - f0) else (-aij     / f0))-    return $ c *^ (LA.var xj ^-^ LA.constant lj)-  xs2 <- forM ks $ \(aij, xj) -> do-    let fj = fracPart aij-    Just (uj, _) <- Simplex2.getUB lp xj-    let c = if xj `IS.member` ivs-            then (if fj <= f0 then fj  / f0 else ((1 - fj) / (1 - f0)))-            else (if aij > 0  then aij / f0 else (-aij     / (1 - f0)))-    return $ c *^ (LA.constant uj ^-^ LA.var xj)--  return $ sumV xs1 ^+^ sumV xs2 .>=. LA.constant 1---- TODO: Simplex2をδに対応させたら、xi, xj がδを含まない有理数であるという条件も必要-canDeriveGomoryCut :: Simplex2.Solver -> Var -> IO Bool-canDeriveGomoryCut lp xi = do-  b <- Simplex2.isBasicVariable lp xi-  if not b-    then return False-    else do-      val <- Simplex2.getValue lp xi-      if isInteger val-        then return False-        else do-          row <- Simplex2.getRow lp xi-          ys <- forM (LA.terms row) $ \(_,xj) -> do-            vj <- Simplex2.getValue lp xj-            lb <- Simplex2.getLB lp xj-            ub <- Simplex2.getUB lp xj-            return $ Just vj == Simplex2.boundValue lb || Just vj == Simplex2.boundValue ub-          return (and ys)
− src/ToySolver/Arith/MIPSolverHL.hs
@@ -1,282 +0,0 @@-{-# LANGUAGE ScopedTypeVariables #-}-{-# OPTIONS_GHC -Wall #-}--------------------------------------------------------------------------------- |--- Module      :  ToySolver.Arith.MIPSolverHL--- Copyright   :  (c) Masahiro Sakai 2011--- License     :  BSD-style------ Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  provisional--- Portability :  non-portable (ScopedTypeVariables)------ References:--- --- * [Gomory1960]---   Ralph E. Gomory.---   An Algorithm for the Mixed Integer Problem, Technical Report---   RM-2597, 1960, The Rand Corporation, Santa Monica, CA.---   <http://www.rand.org/pubs/research_memoranda/RM2597.html>------ * [Gomory1958]---   Ralph E. Gomory.---   Outline of an algorithm for integer solutions to linear programs.---   Bull. Amer. Math. Soc., Vol. 64, No. 5. (1958), pp. 275-278.---   <http://projecteuclid.org/euclid.bams/1183522679>--------------------------------------------------------------------------------module ToySolver.Arith.MIPSolverHL-  ( module Data.OptDir-  , OptResult (..)-  , minimize-  , maximize-  , optimize-  ) where--import Control.Exception-import Control.Monad.State-import Data.Default.Class-import Data.Ord-import Data.Maybe-import Data.List (maximumBy)-import qualified Data.IntMap as IM-import qualified Data.IntSet as IS-import Data.OptDir-import Data.VectorSpace--import ToySolver.Data.OrdRel-import ToySolver.Data.Var-import qualified ToySolver.Data.LA as LA-import qualified ToySolver.Arith.Simplex as Simplex-import qualified ToySolver.Arith.LPSolver as LPSolver-import ToySolver.Arith.LPSolver hiding (OptResult (..))-import ToySolver.Arith.LPSolverHL (OptResult (..))-import qualified ToySolver.Arith.OmegaTest as OmegaTest-import ToySolver.Internal.Util (isInteger, fracPart)---- -----------------------------------------------------------------------------data Node r-  = Node-  { ndSolver :: LPSolver.Solver r-  , ndDepth  :: {-# UNPACK #-} !Int---  , ndCutSlackVariables :: VarSet-  }--ndTableau :: Node r  -> Simplex.Tableau r-ndTableau node = evalState getTableau (ndSolver node)--ndLowerBound :: (Num r, Eq r) => Node r -> r-ndLowerBound node = evalState (liftM Simplex.currentObjValue getTableau) (ndSolver node)--data Err = ErrUnbounded | ErrUnsat deriving (Ord, Eq, Show, Enum, Bounded)--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-        ErrUnsat -> OptUnsat-        ErrUnbounded ->-          if IS.null ivs-          then Unbounded-          else-            {--               Fallback to Fourier-Motzkin + OmegaTest-               * In general, original problem may have optimal-                 solution even though LP relaxiation is unbounded.-               * But if restricted to rational numbers, the-                 original problem is unbounded or unsatisfiable-                 when LP relaxation is unbounded.-            -}-            case OmegaTest.solveQFLIRAConj def (vars cs `IS.union` ivs) (map conv cs) ivs of-              Nothing -> OptUnsat-              Just _ -> Unbounded        -    Right (node0, ivs2) -> -      case traverseBBTree optdir obj ivs2 node0 of-        Left ErrUnbounded -> error "shoud not happen"-        Left ErrUnsat -> OptUnsat-        Right node -> flip evalState (ndSolver node) $ do-          tbl <- getTableau-          model <- getModel vs-          return $ Optimum (Simplex.currentObjValue tbl) model-  where-    vs = vars cs `IS.union` vars obj--tableau' :: (RealFrac r) => [LA.Atom r] -> VarSet -> LP r VarSet-tableau' cs ivs = do-  let (nonnegVars, cs') = collectNonnegVars cs ivs-      fvs = vars cs `IS.difference` nonnegVars-  ivs2 <- liftM IS.unions $ forM (IS.toList fvs) $ \v -> do-    v1 <- newVar-    v2 <- newVar-    define v (LA.var v1 ^-^ LA.var v2)-    return $ if v `IS.member` ivs then IS.fromList [v1,v2] else IS.empty-  mapM_ addConstraint cs'-  return ivs2--conv :: RealFrac r => LA.Atom r -> LA.Atom Rational-conv = fmap (LA.mapCoeff toRational)--mkInitialNode :: RealFrac r => OptDir -> LA.Expr r -> [LA.Atom r] -> VarSet -> Either Err (Node r, VarSet)-mkInitialNode optdir obj cs ivs =-  flip evalState (emptySolver vs) $ do-    ivs2 <- tableau' cs ivs-    ret <- LPSolver.twoPhaseSimplex optdir obj-    case ret of-      LPSolver.Unsat -> return (Left ErrUnsat)-      LPSolver.Unbounded -> return (Left ErrUnbounded)-      LPSolver.Optimum -> do-        solver <- get-        return $ Right $-          ( Node{ ndSolver = solver-                , ndDepth = 0---                , ndCutSlackVariables = IS.empty-                }-          , ivs `IS.union` ivs2-          )-  where-    vs = vars cs `IS.union` vars obj--isStrictlyBetter :: RealFrac r => OptDir -> r -> r -> Bool-isStrictlyBetter optdir = if optdir==OptMin then (<) else (>)--traverseBBTree :: forall r. RealFrac r => OptDir -> LA.Expr r -> VarSet -> Node r -> Either Err (Node r)-traverseBBTree optdir obj ivs node0 = loop [node0] Nothing-  where-    loop :: [Node r] -> Maybe (Node r) -> Either Err (Node r)-    loop [] (Just best) = Right best-    loop [] Nothing = Left ErrUnsat-    loop (n:ns) Nothing =-      case children n of-        Nothing -> loop ns (Just n)-        Just cs -> loop (cs++ns) Nothing-    loop (n:ns) (Just best)-      | isStrictlyBetter optdir (ndLowerBound n) (ndLowerBound best) =-          case children n of-            Nothing -> loop ns (Just n)-            Just cs -> loop (cs++ns) (Just best)-      | otherwise = loop ns (Just best)--    reopt :: Solver r -> Maybe (Solver r)-    reopt s = flip evalState s $ do-      ret <- dualSimplex optdir obj-      if ret-        then liftM Just get-        else return Nothing--    children :: Node r -> Maybe [Node r]-    children node-      | null xs = Nothing -- no violation-      | ndDepth node `mod` 100 == 0 = -- cut-          let-            (f0, m0) = maximumBy (comparing fst) [(fracPart val, m) | (_,m,val) <- xs]-            sv = flip execState (ndSolver node) $ do-                   s <- newVar-                   let g j x = assert (a >= 0) a-                         where-                           a | j `IS.member` ivs =-                                if fracPart x <= f0-                                then fracPart x-                                else (f0 / (f0 - 1)) * (fracPart x - 1)-                                     -- [Gomory1960] では (f0 / (1 - f0)) * (fracPart x - 1) としているが、-                                     -- これは誤り-                             | otherwise =-                                if x >= 0-                                then x-                                else (f0 / (f0 - 1)) * x-                   putTableau $ IM.insert s (IM.mapWithKey (\j x -> negate (g j x)) m0, negate f0) tbl-          in Just $ [node{ ndSolver = sv2, ndDepth = ndDepth node + 1 } | sv2 <- maybeToList (reopt sv)]-      | otherwise = -- branch-          let (v0, val0) = snd $ maximumBy (comparing fst) [(fracPart val, (v, val)) | (v,_,val) <- xs]-              cs = [ LA.var v0 .>=. LA.constant (fromIntegral (ceiling val0 :: Integer))-                   , LA.var v0 .<=. LA.constant (fromIntegral (floor val0 :: Integer))-                   ]-              svs = [execState (addConstraint c) (ndSolver node) | c <- cs]-          in Just $ [node{ ndSolver = sv, ndDepth = ndDepth node + 1 } | Just sv <- map reopt svs]-        -      where-        tbl :: Simplex.Tableau r-        tbl = ndTableau node--        xs :: [(Var, VarMap r, r)]-        xs = [ (v, m, val)-             | v <- IS.toList ivs-             , Just (m, val) <- return (IM.lookup v tbl)-             , not (isInteger val)-             ]---- -----------------------------------------------------------------------------example1 :: (Fractional r, Eq r) => (OptDir, LA.Expr r, [LA.Atom r], VarSet)-example1 = (optdir, obj, cs, ivs)-  where-    optdir = OptMax-    x1 = LA.var 1-    x2 = LA.var 2-    x3 = LA.var 3-    x4 = LA.var 4-    obj = x1 ^+^ 2 *^ x2 ^+^ 3 *^ x3 ^+^ x4-    cs =-      [ (-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-      , LA.constant 0 .<=. x3-      , LA.constant 2 .<=. x4-      , x4 .<=. LA.constant 3-      ]-    ivs = IS.singleton 4--test1 :: Bool-test1 = result==expected-  where-    (optdir, obj, cs, ivs) = example1-    result, expected :: OptResult Rational-    result = optimize optdir obj cs ivs-    expected = Optimum (245/2) (IM.fromList [(1,40),(2,21/2),(3,39/2),(4,3)])--test1' :: Bool-test1' = result==expected-  where-    (optdir, obj, cs, ivs) = example1-    f OptMin = OptMax-    f OptMax = OptMin-    result, expected :: OptResult Rational-    result = optimize (f optdir) (negateV obj) cs ivs-    expected = Optimum (-245/2) (IM.fromList [(1,40),(2,21/2),(3,39/2),(4,3)])---- 『数理計画法の基礎』(坂和 正敏) p.109 例 3.8-example2 :: (Fractional r, Eq r) => (OptDir, LA.Expr r, [LA.Atom r], VarSet)-example2 = (optdir, obj, cs, ivs)-  where-    optdir = OptMin-    [x1,x2,x3] = map LA.var [1..3]-    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-      , LA.constant 0 .<=. x1-      , LA.constant 0 .<=. x2-      , LA.constant 0 .<=. x3-      ]-    ivs = IS.fromList [1,2]--test2 :: Bool-test2 = result == expected-  where-    result, expected :: OptResult Rational-    result = optimize optdir obj cs ivs-    expected = Optimum (-37/2) (IM.fromList [(1,0),(2,2),(3,5/2)])-    (optdir, obj, cs, ivs) = example2---- ---------------------------------------------------------------------------
src/ToySolver/Arith/OmegaTest.hs view
@@ -40,17 +40,17 @@     ) where  import Control.Monad+import Control.Monad.ST 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 ToySolver.Data.LA as LA import qualified ToySolver.Data.Polynomial as P-import ToySolver.Data.Var+import ToySolver.Data.IntVar import qualified ToySolver.Arith.CAD as CAD-import qualified ToySolver.Arith.Simplex2 as Simplex2+import qualified ToySolver.Arith.Simplex as Simplex import qualified ToySolver.Arith.VirtualSubstitution as VS import ToySolver.Arith.OmegaTest.Base @@ -69,11 +69,11 @@ checkRealByVS vs as = isJust $ VS.solve vs as  checkRealBySimplex :: VarSet -> [LA.Atom Rational] -> Bool-checkRealBySimplex vs as = unsafePerformIO $ do-  solver <- Simplex2.newSolver+checkRealBySimplex vs as = runST $ do+  solver <- Simplex.newSolver   s <- liftM IM.fromAscList $ forM (IS.toAscList vs) $ \v -> do-    v2 <- Simplex2.newVar solver+    v2 <- Simplex.newVar solver     return (v, LA.var v2)   forM_ as $ \a -> do-    Simplex2.assertAtomEx solver (fmap (LA.applySubst s) a)-  Simplex2.check solver+    Simplex.assertAtomEx solver (fmap (LA.applySubst s) a)+  Simplex.check solver
src/ToySolver/Arith/OmegaTest/Base.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, MultiParamTypeClasses #-} {-# OPTIONS_GHC -Wall #-} ----------------------------------------------------------------------------- -- |@@ -7,7 +8,7 @@ --  -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  provisional--- Portability :  portable+-- Portability :  non-portable (TypeSynonymInstances, FlexibleInstances, MultiParamTypeClasses) -- -- (incomplete) implementation of Omega Test --@@ -51,7 +52,7 @@ import ToySolver.Data.Boolean import ToySolver.Data.DNF import qualified ToySolver.Data.LA as LA-import ToySolver.Data.Var+import ToySolver.Data.IntVar import ToySolver.Internal.Util (combineMaybe) import qualified ToySolver.Arith.FourierMotzkin as FM @@ -141,9 +142,9 @@ applySubst1Constr v e (IsNonneg e2) = LA.applySubst1 v e e2 `geZ` LA.constant 0 applySubst1Constr v e (IsZero e2)   = LA.applySubst1 v e e2 `eqZ` LA.constant 0 -evalConstr :: Model Integer -> Constr -> Bool-evalConstr m (IsNonneg t) = LA.evalExpr m t >= 0-evalConstr m (IsZero t)   = LA.evalExpr m t == 0+instance Eval (Model Integer) Constr Bool where+  eval m (IsNonneg t) = LA.eval m t >= 0+  eval m (IsZero t)   = LA.eval m t == 0  -- --------------------------------------------------------------------------- @@ -159,8 +160,8 @@ evalBoundsZ :: Model Integer -> BoundsZ -> IntervalZ evalBoundsZ model (ls,us) =   foldl' intersectZ univZ $ -    [ (Just (ceiling (LA.evalExpr model x % c)), Nothing) | (x,c) <- ls ] ++ -    [ (Nothing, Just (floor (LA.evalExpr model x % c))) | (x,c) <- us ]+    [ (Just (ceiling (LA.eval model x % c)), Nothing) | (x,c) <- ls ] ++ +    [ (Nothing, Just (floor (LA.eval model x % c))) | (x,c) <- us ]  collectBoundsZ :: Var -> [Constr] -> (BoundsZ, [Constr]) collectBoundsZ v = foldr phi (([],[]),[])@@ -182,8 +183,9 @@   where     go :: VarSet -> [Constr] -> Maybe (Model Integer)     go vs cs | IS.null vs = do-      let m = IM.empty-      guard $ all (evalConstr m) cs+      let m :: Model Integer+          m = IM.empty+      guard $ all (eval m) cs       return m     go vs cs | Just (e,cs2) <- extractEq cs = do       (vs',cs3, mt) <- eliminateEq e vs cs2@@ -250,7 +252,7 @@         return $            ( IS.delete xk vs            , [applySubst1Constr xk xk_def c | c <- cs]-           , \model -> IM.insert xk (LA.evalExpr model xk_def) model+           , \model -> IM.insert xk (LA.eval model xk_def) model            )   else do     let m = abs ak + 1@@ -267,7 +269,8 @@         e2 = (- abs ak) *^ LA.var sigma ^+^                  LA.fromTerms [((floor (a%m + 1/2) + (a `zmod` m)), x) | (a,x) <- LA.terms e, x /= xk]     assert (m *^ e2 == LA.applySubst1 xk xk_def e) $ return ()-    let mt model = IM.delete sigma $ IM.insert xk (LA.evalExpr model xk_def) model+    let mt :: Model Integer -> Model Integer+        mt model = IM.delete sigma $ IM.insert xk (LA.eval model xk_def) model     c <- isZero e2     return (IS.insert sigma (IS.delete xk vs), c : [applySubst1Constr xk xk_def c | c <- cs], mt) 
src/ToySolver/Arith/Simplex.hs view
@@ -1,366 +1,1223 @@-{-# LANGUAGE ScopedTypeVariables #-}-{-# OPTIONS_GHC -Wall #-}--------------------------------------------------------------------------------- |--- Module      :  ToySolver.Arith.Simplex--- Copyright   :  (c) Masahiro Sakai 2011--- License     :  BSD-style--- --- Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  provisional--- Portability :  non-portable (ScopedTypeVariables)------ Naïve implementation of Simplex method--- --- Reference:------ * <http://www.math.cuhk.edu.hk/~wei/lpch3.pdf>----------------------------------------------------------------------------------module ToySolver.Arith.Simplex-  (-  -- * The @Tableau@ type-    Tableau-  , RowIndex-  , ColIndex-  , Row-  , emptyTableau-  , objRowIndex-  , pivot-  , lookupRow-  , addRow-  , setObjFun--  -- * Optimization direction-  , module Data.OptDir--  -- * Reading status-  , currentValue-  , currentObjValue-  , isFeasible-  , isOptimal--  -- * High-level solving functions-  , simplex-  , dualSimplex-  , phaseI-  , primalDualSimplex--  -- * For debugging-  , isValidTableau-  , toCSV-  ) where--import Data.Ord-import Data.List-import qualified Data.IntMap as IM-import qualified Data.IntSet as IS-import Data.OptDir-import Data.VectorSpace-import Control.Exception--import qualified ToySolver.Data.LA as LA-import ToySolver.Data.Var---- -----------------------------------------------------------------------------type Tableau r = VarMap (Row r)-{--tbl ! v == (m, val)-==>-var v .+. m .==. constant val--}---- | Basic variables-type RowIndex = Int---- | Non-basic variables-type ColIndex = Int--type Row r = (VarMap r, r)--data PivotResult r = PivotUnbounded | PivotFinished | PivotSuccess (Tableau r)-  deriving (Show, Eq, Ord)--emptyTableau :: Tableau r-emptyTableau = IM.empty--objRowIndex :: RowIndex-objRowIndex = -1--pivot :: (Fractional r, Eq r) => RowIndex -> ColIndex -> Tableau r -> Tableau r-{-# INLINE pivot #-}-{-# SPECIALIZE pivot :: RowIndex -> ColIndex -> Tableau Rational -> Tableau Rational #-}-{-# SPECIALIZE pivot :: RowIndex -> ColIndex -> Tableau Double -> Tableau Double #-}-pivot r s tbl =-    assert (isValidTableau tbl) $  -- precondition-    assert (isValidTableau tbl') $ -- postcondition-      tbl'-  where-    tbl' = IM.insert s row_s $ IM.map f $ IM.delete r $ tbl-    f orig@(row_i, row_i_val) =-      case IM.lookup s row_i of-        Nothing -> orig-        Just c ->-          ( IM.filter (0/=) $ IM.unionWith (+) (IM.delete s row_i) (IM.map (negate c *) row_r')-          , row_i_val - c*row_r_val'-          )-    (row_r, row_r_val) = lookupRow r tbl-    a_rs = row_r IM.! s-    row_r' = IM.map (/ a_rs) $ IM.insert r 1 $ IM.delete s row_r-    row_r_val' = row_r_val / a_rs-    row_s = (row_r', row_r_val')---- | Lookup a row by basic variable-lookupRow :: RowIndex -> Tableau r -> Row r-lookupRow r m = m IM.! r---- 行の基底変数の列が0になるように変形-normalizeRow :: (Num r, Eq r) => Tableau r -> Row r -> Row r-normalizeRow a (row0,val0) = obj'-  where-    obj' = g $ foldl' f (IM.empty, val0) $ -           [ case IM.lookup j a of-               Nothing -> (IM.singleton j x, 0)-               Just (row,val) -> (IM.map ((-x)*) (IM.delete j row), -x*val)-           | (j,x) <- IM.toList row0 ]-    f (m1,v1) (m2,v2) = (IM.unionWith (+) m1 m2, v1+v2)-    g (m,v) = (IM.filter (0/=) m, v)--setRow :: (Num r, Eq r) => Tableau r -> RowIndex -> Row r -> Tableau r-setRow tbl i row = assert (isValidTableau tbl) $ assert (isValidTableau tbl') $ tbl'-  where-    tbl' = IM.insert i (normalizeRow tbl row) tbl--addRow :: (Num r, Eq r) => Tableau r -> RowIndex -> Row r -> Tableau r-addRow tbl i row = assert (i `IM.notMember` tbl) $ setRow tbl i row--setObjFun :: (Num r, Eq r) => Tableau r -> LA.Expr r -> Tableau r-setObjFun tbl e = addRow tbl objRowIndex row-  where-    row =-      case LA.extract LA.unitVar e of-        (c, e') -> (LA.coeffMap (negateV e'), c)--copyObjRow :: (Num r, Eq r) => Tableau r -> Tableau r -> Tableau r-copyObjRow from to =-  case IM.lookup objRowIndex from of-    Nothing -> IM.delete objRowIndex to-    Just row -> addRow to objRowIndex row--currentValue :: Num r => Tableau r -> Var -> r-currentValue tbl v =-  case IM.lookup v tbl of-    Nothing -> 0-    Just (_, val) -> val--currentObjValue :: Num r => Tableau r -> r-currentObjValue = snd . lookupRow objRowIndex--isValidTableau :: Tableau r -> Bool-isValidTableau tbl =-  and [v `IM.notMember` m | (v, (m,_)) <- IM.toList tbl, v /= objRowIndex] &&-  and [IS.null (IM.keysSet m `IS.intersection` vs) | (m,_) <- IM.elems tbl']-  where-    tbl' = IM.delete objRowIndex tbl-    vs = IM.keysSet tbl' --isFeasible :: Real r => Tableau r -> Bool-isFeasible tbl = -  and [val >= 0 | (v, (_,val)) <- IM.toList tbl, v /= objRowIndex]--isOptimal :: Real r => OptDir -> Tableau r -> Bool-isOptimal optdir tbl =-  and [not (cmp cj) | cj <- IM.elems (fst (lookupRow objRowIndex tbl))]-  where-    cmp = case optdir of-            OptMin -> (0<)-            OptMax -> (0>)--isImproving :: Real r => OptDir -> Tableau r -> Tableau r -> Bool-isImproving OptMin from to = currentObjValue to <= currentObjValue from -isImproving OptMax from to = currentObjValue to >= currentObjValue from ---- ------------------------------------------------------------------------------ primal simplex--simplex :: (Real r, Fractional r) => OptDir -> Tableau r -> (Bool, Tableau r)-{-# SPECIALIZE simplex :: OptDir -> Tableau Rational -> (Bool, Tableau Rational) #-}-{-# SPECIALIZE simplex :: OptDir -> Tableau Double -> (Bool, Tableau Double) #-}-simplex optdir = go-  where-    go tbl = assert (isFeasible tbl) $-      case primalPivot optdir tbl of-        PivotFinished  -> assert (isOptimal optdir tbl) (True, tbl)-        PivotUnbounded -> (False, tbl)-        PivotSuccess tbl' -> assert (isImproving optdir tbl tbl') $ go tbl'--primalPivot :: (Real r, Fractional r) => OptDir -> Tableau r -> PivotResult r-{-# INLINE primalPivot #-}-primalPivot optdir tbl-  | null cs   = PivotFinished-  | null rs   = PivotUnbounded-  | otherwise = PivotSuccess (pivot r s tbl)-  where-    cmp = case optdir of-            OptMin -> (0<)-            OptMax -> (0>)-    cs = [(j,cj) | (j,cj) <- IM.toList (fst (lookupRow objRowIndex tbl)), cmp cj]-    -- smallest subscript rule-    s = fst $ head cs-    -- classical rule-    --s = fst $ (if optdir==OptMin then maximumBy else minimumBy) (compare `on` snd) cs-    rs = [ (i, y_i0 / y_is)-         | (i, (row_i, y_i0)) <- IM.toList tbl, i /= objRowIndex-         , let y_is = IM.findWithDefault 0 s row_i, y_is > 0-         ]-    r = fst $ minimumBy (comparing snd) rs---- ------------------------------------------------------------------------------ dual simplex--dualSimplex :: (Real r, Fractional r) => OptDir -> Tableau r -> (Bool, Tableau r)-{-# SPECIALIZE dualSimplex :: OptDir -> Tableau Rational -> (Bool, Tableau Rational) #-}-{-# SPECIALIZE dualSimplex :: OptDir -> Tableau Double -> (Bool, Tableau Double) #-}-dualSimplex optdir = go-  where-    go tbl = assert (isOptimal optdir tbl) $-      case dualPivot optdir tbl of-        PivotFinished  -> assert (isFeasible tbl) $ (True, tbl)-        PivotUnbounded -> (False, tbl)-        PivotSuccess tbl' -> assert (isImproving optdir tbl' tbl) $ go tbl'--dualPivot :: (Real r, Fractional r) => OptDir -> Tableau r -> PivotResult r-{-# INLINE dualPivot #-}-dualPivot optdir tbl-  | null rs   = PivotFinished-  | null cs   = PivotUnbounded-  | otherwise = PivotSuccess (pivot r s tbl)-  where-    rs = [(i, row_i) | (i, (row_i, y_i0)) <- IM.toList tbl, i /= objRowIndex, 0 > y_i0]-    (r, row_r) = head rs-    cs = [ (j, if optdir==OptMin then y_0j / y_rj else - y_0j / y_rj)-         | (j, y_rj) <- IM.toList row_r-         , y_rj < 0-         , let y_0j = IM.findWithDefault 0 j obj-         ]-    s = fst $ minimumBy (comparing snd) cs-    (obj,_) = lookupRow objRowIndex tbl---- ------------------------------------------------------------------------------ phase I of the two-phased method--phaseI :: (Real r, Fractional r) => Tableau r -> VarSet -> (Bool, Tableau r)-{-# SPECIALIZE phaseI :: Tableau Rational -> VarSet -> (Bool, Tableau Rational) #-}-{-# SPECIALIZE phaseI :: Tableau Double -> VarSet -> (Bool, Tableau Double) #-}-phaseI tbl avs-  | currentObjValue tbl1' /= 0 = (False, tbl1')-  | otherwise = (True, copyObjRow tbl $ removeArtificialVariables avs $ tbl1')-  where-    optdir = OptMax-    tbl1 = setObjFun tbl $ negateV $ sumV [LA.var v | v <- IS.toList avs]-    tbl1' = go tbl1-    go tbl2-      | currentObjValue tbl2 == 0 = tbl2-      | otherwise = -        case primalPivot optdir tbl2 of-          PivotSuccess tbl2' -> assert (isImproving optdir tbl2 tbl2') $ go tbl2'-          PivotFinished -> assert (isOptimal optdir tbl2) tbl2-          PivotUnbounded -> error "phaseI: should not happen"---- post-processing of phaseI--- pivotを使ってartificial variablesを基底から除いて、削除-removeArtificialVariables :: (Real r, Fractional r) => VarSet -> Tableau r -> Tableau r-removeArtificialVariables avs tbl0 = tbl2-  where-    tbl1 = foldl' f (IM.delete objRowIndex tbl0) (IS.toList avs)-    tbl2 = IM.map (\(row,val) ->  (IM.filterWithKey (\j _ -> j `IS.notMember` avs) row, val)) tbl1-    f tbl i =-      case IM.lookup i tbl of-        Nothing -> tbl-        Just row ->-          case [j | (j,c) <- IM.toList (fst row), c /= 0, j `IS.notMember` avs] of-            [] -> IM.delete i tbl-            j:_ -> pivot i j tbl---- ------------------------------------------------------------------------------ primal-dual simplex--data PDResult = PDUnsat | PDOptimal | PDUnbounded--primalDualSimplex :: (Real r, Fractional r) => OptDir -> Tableau r -> (Bool, Tableau r)-{-# SPECIALIZE primalDualSimplex :: OptDir -> Tableau Rational -> (Bool, Tableau Rational) #-}-{-# SPECIALIZE primalDualSimplex :: OptDir -> Tableau Double -> (Bool, Tableau Double) #-}-primalDualSimplex optdir = go-  where-    go tbl =-      case pdPivot optdir tbl of-        Left PDOptimal   -> assert (isFeasible tbl) $ assert (isOptimal optdir tbl) $ (True, tbl)-        Left PDUnsat     -> assert (not (isFeasible tbl)) $ (False, tbl)-        Left PDUnbounded -> assert (not (isOptimal optdir tbl)) $ (False, tbl)-        Right tbl' -> go tbl'--pdPivot :: (Real r, Fractional r) => OptDir -> Tableau r -> Either PDResult (Tableau r)-pdPivot optdir tbl-  | null ps && null qs = Left PDOptimal -- optimal-  | otherwise =-      case ret of-        Left p -> -- primal update-          let rs = [ (i, (bi - t) / y_ip)-                   | (i, (row_i, bi)) <- IM.toList tbl, i /= objRowIndex-                   , let y_ip = IM.findWithDefault 0 p row_i, y_ip > 0-                   ]-              q = fst $ minimumBy (comparing snd) rs-          in if null rs-             then Left PDUnsat-             else Right (pivot q p tbl)-        Right q -> -- dual update-          let (row_q, _bq) = (tbl IM.! q)-              cs = [ (j, (cj'-t) / (-y_qj))-                   | (j, y_qj) <- IM.toList row_q-                   , y_qj < 0-                   , let cj  = IM.findWithDefault 0 j obj-                   , let cj' = if optdir==OptMax then cj else -cj-                   ]-              p = fst $ maximumBy (comparing snd) cs-              (obj,_) = lookupRow objRowIndex tbl-          in if null cs-             then Left PDUnbounded -- dual infeasible-             else Right (pivot q p tbl)-  where-    qs = [ (Right i, bi) | (i, (_row_i, bi)) <- IM.toList tbl, i /= objRowIndex, 0 > bi ]-    ps = [ (Left j, cj')-         | (j,cj) <- IM.toList (fst (lookupRow objRowIndex tbl))-         , let cj' = if optdir==OptMax then cj else -cj-         , 0 > cj' ]-    (ret, t) = minimumBy (comparing snd) (qs ++ ps)---- -----------------------------------------------------------------------------toCSV :: (Num r, Eq r, Show r) => (r -> String) -> Tableau r -> String-toCSV showCell tbl = unlines . map (concat . intersperse ",") $ header : body-  where-    header :: [String]-    header = "" : map colName cols ++ [""]--    body :: [[String]]-    body = [showRow i (lookupRow i tbl) | i <- rows]--    rows :: [RowIndex]-    rows = IM.keys (IM.delete objRowIndex tbl) ++ [objRowIndex]--    cols :: [ColIndex]-    cols = [0..colMax]-      where-        colMax = maximum (-1 : [c | (row, _) <- IM.elems tbl, c <- IM.keys row])--    rowName :: RowIndex -> String-    rowName i = if i==objRowIndex then "obj" else "x" ++ show i--    colName :: ColIndex -> String-    colName j = "x" ++ show j--    showRow i (row, row_val) = rowName i : [showCell (IM.findWithDefault 0 j row') | j <- cols] ++ [showCell row_val]-      where row' = IM.insert i 1 row---- ---------------------------------------------------------------------------+{-# LANGUAGE ScopedTypeVariables, Rank2Types, TypeOperators, TypeSynonymInstances, FlexibleInstances, TypeFamilies, CPP #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Arith.Simplex+-- Copyright   :  (c) Masahiro Sakai 2012+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable (ScopedTypeVariables, Rank2Types, TypeOperators, TypeSynonymInstances, FlexibleInstances, TypeFamilies, CPP)+--+-- Naïve implementation of Simplex method+-- +-- Reference:+--+-- * <http://www.math.cuhk.edu.hk/~wei/lpch3.pdf>+-- +-- * Bruno Dutertre and Leonardo de Moura.+--   A Fast Linear-Arithmetic Solver for DPLL(T).+--   Computer Aided Verification In Computer Aided Verification, Vol. 4144 (2006), pp. 81-94.+--   <http://yices.csl.sri.com/cav06.pdf>+--+-- * Bruno Dutertre and Leonardo de Moura.+--   Integrating Simplex with DPLL(T).+--   CSL Technical Report SRI-CSL-06-01. 2006.+--   <http://yices.csl.sri.com/sri-csl-06-01.pdf>+--+-----------------------------------------------------------------------------+module ToySolver.Arith.Simplex+  (+  -- * The @Solver@ type+    Solver+  , GenericSolver+  , GenericSolverM+  , SolverValue (..)+  , newSolver+  , cloneSolver++  -- * Problem specification+  , Var+  , newVar+  , RelOp (..)+  , (.<=.), (.>=.), (.==.), (.<.), (.>.)+  , Atom (..)+  , ConstrID+  , ConstrIDSet+  , assertAtom+  , assertAtom'+  , assertAtomEx+  , assertAtomEx'+  , assertLower+  , assertLower'+  , assertUpper+  , assertUpper'+  , setObj+  , getObj+  , OptDir (..)+  , setOptDir+  , getOptDir++  -- * Solving+  , check+  , pushBacktrackPoint+  , popBacktrackPoint+  , Options (..)+  , OptResult (..)+  , optimize+  , dualSimplex++  -- * Extract results+  , Model+  , getModel+  , RawModel+  , getRawModel+  , getValue+  , getObjValue+  , explain++  -- * Reading status+  , getTableau+  , getRow+  , getCol+  , getCoeff+  , nVars+  , isBasicVariable+  , isNonBasicVariable+  , isFeasible+  , isOptimal+  , getLB+  , getUB+  , Bound+  , boundValue+  , boundExplanation++  -- * Configulation+  , setLogger+  , clearLogger+  , enableTimeRecording+  , disableTimeRecording+  , PivotStrategy (..)+  , setPivotStrategy++  -- * Debug+  , dump++  -- * Misc+  , simplifyAtom+  ) where++import Prelude hiding (log)+import Control.Exception+import Control.Monad+import Control.Monad.Primitive+import Data.Default.Class+import Data.Ord+import Data.List+import Data.Maybe+import Data.Monoid+import Data.Primitive.MutVar+import Data.Ratio+import Data.Map (Map)+import qualified Data.Map as Map+import Data.IntMap (IntMap)+import qualified Data.IntMap as IntMap+import Data.IntSet (IntSet)+import qualified Data.IntSet as IntSet+import Text.Printf+import Data.OptDir+import Data.VectorSpace+import System.Clock++import qualified ToySolver.Data.LA as LA+import ToySolver.Data.LA (Atom (..))+import ToySolver.Data.OrdRel+import ToySolver.Data.Delta+import ToySolver.Internal.Util (showRational)++infixr 0 ~>+-- | A natural transformation from @f@ to @g@.+type f ~> g = forall x. f x -> g x++infixr 0 :~>, $$+-- | A natural transformation suitable for storing in a container.+newtype f :~> g = Nat { ($$) :: f ~> g }++{--------------------------------------------------------------------+  The @Solver@ type+--------------------------------------------------------------------}++type Var = Int++data GenericSolverM m v+  = GenericSolverM+  { svTableau :: !(MutVar (PrimState m) (IntMap (LA.Expr Rational)))+  , svLB      :: !(MutVar (PrimState m) (IntMap (v, ConstrIDSet)))+  , svUB      :: !(MutVar (PrimState m) (IntMap (v, ConstrIDSet)))+  , svModel   :: !(MutVar (PrimState m) (IntMap v))+  , svExplanation :: !(MutVar (PrimState m) ConstrIDSet)+  , svVCnt    :: !(MutVar (PrimState m) Int)+  , svOk      :: !(MutVar (PrimState m) Bool)+  , svOptDir  :: !(MutVar (PrimState m) OptDir)++  , svDefDB  :: !(MutVar (PrimState m) (Map (LA.Expr Rational) Var))++  , svLogger :: !(MutVar (PrimState m) (Maybe (String -> m ())))+  , svRecTime :: !(MutVar (PrimState m) (Maybe (GenericSolverM m v -> (m :~> m))))+  , svPivotStrategy :: !(MutVar (PrimState m) PivotStrategy)+  , svNPivot  :: !(MutVar (PrimState m) Int)++  , svBacktrackPoints :: !(MutVar (PrimState m) [BacktrackPoint m v])+  }++type GenericSolver v = GenericSolverM IO v++type Solver = GenericSolver Rational++-- special basic variable+objVar :: Int+objVar = -1++newSolver :: (PrimMonad m, SolverValue v) => m (GenericSolverM m v)+newSolver = do+  t <- newMutVar (IntMap.singleton objVar zeroV)+  l <- newMutVar IntMap.empty+  u <- newMutVar IntMap.empty+  m <- newMutVar (IntMap.singleton objVar zeroV)+  e <- newMutVar mempty+  v <- newMutVar 0+  ok <- newMutVar True+  dir <- newMutVar OptMin+  defs <- newMutVar Map.empty+  logger <- newMutVar Nothing+  rectm <- newMutVar Nothing+  pivot <- newMutVar PivotStrategyBlandRule+  npivot <- newMutVar 0+  bps <- newMutVar []+  return $+    GenericSolverM+    { svTableau = t+    , svLB      = l+    , svUB      = u+    , svModel   = m+    , svExplanation = e+    , svVCnt    = v+    , svOk      = ok+    , svOptDir  = dir+    , svDefDB   = defs+    , svLogger  = logger+    , svRecTime = rectm+    , svNPivot  = npivot+    , svPivotStrategy = pivot+    , svBacktrackPoints = bps+    }++cloneSolver :: PrimMonad m => GenericSolverM m v -> m (GenericSolverM m v)+cloneSolver solver = do+  t      <- newMutVar =<< readMutVar (svTableau solver)+  l      <- newMutVar =<< readMutVar (svLB solver)+  u      <- newMutVar =<< readMutVar (svUB solver)+  m      <- newMutVar =<< readMutVar (svModel solver)+  e      <- newMutVar =<< readMutVar (svExplanation solver)+  v      <- newMutVar =<< readMutVar (svVCnt solver)+  ok     <- newMutVar =<< readMutVar (svOk solver)+  dir    <- newMutVar =<< readMutVar (svOptDir solver)+  defs   <- newMutVar =<< readMutVar (svDefDB solver)+  logger <- newMutVar =<< readMutVar (svLogger solver)+  rectm  <- newMutVar =<< readMutVar (svRecTime solver)+  pivot  <- newMutVar =<< readMutVar (svPivotStrategy solver)+  npivot <- newMutVar =<< readMutVar (svNPivot solver)+  bps    <- newMutVar =<< mapM cloneBacktrackPoint =<< readMutVar (svBacktrackPoints solver)+  return $+    GenericSolverM+    { svTableau = t+    , svLB      = l+    , svUB      = u+    , svModel   = m+    , svExplanation = e+    , svVCnt    = v+    , svOk      = ok+    , svOptDir  = dir+    , svDefDB   = defs+    , svLogger  = logger+    , svRecTime = rectm+    , svNPivot  = npivot+    , svPivotStrategy = pivot+    , svBacktrackPoints = bps+    }  ++class (VectorSpace v, Scalar v ~ Rational, Ord v) => SolverValue v where+  toValue :: Rational -> v+  showValue :: Bool -> v -> String+  getModel :: PrimMonad m => GenericSolverM m v -> m Model++instance SolverValue Rational where+  toValue = id+  showValue = showRational+  getModel = getRawModel++instance SolverValue (Delta Rational) where+  toValue = fromReal+  showValue = showDelta+  getModel solver = do+    xs <- variables solver+    ys <- liftM concat $ forM xs $ \x -> do+      Delta p q  <- getValue solver x+      lb <- getLB solver x+      ub <- getUB solver x+      return $+        [(p - c) / (k - q) | Just (Delta c k, _) <- return lb, c < p, k > q] +++        [(d - p) / (q - h) | Just (Delta d h, _) <- return ub, p < d, q > h]+    let delta0 :: Rational+        delta0 = if null ys then 0.1 else minimum ys+        f :: Delta Rational -> Rational+        f (Delta r k) = r + k * delta0+    liftM (IntMap.map f) $ readMutVar (svModel solver)++type ConstrID = Int+type ConstrIDSet = IntSet++type Bound v = Maybe (v, ConstrIDSet)++boundValue :: SolverValue v => Bound v -> Maybe v+boundValue = fmap fst++boundExplanation :: SolverValue v => Bound v -> ConstrIDSet+boundExplanation = maybe mempty snd++{-+Largest coefficient rule: original rule suggested by G. Dantzig.+Largest increase rule: computationally more expensive in comparison with Largest coefficient, but locally maximizes the progress.+Steepest edge rule: best pivot rule in practice, an efficient approximate implementation is "Devex".+Bland’s rule: avoids cycling but one of the slowest rules.+Random edge rule: Randomized have lead to the current best provable bounds for the number of pivot steps of the simplex method.+Lexicographic rule: used for avoiding cyclying.+-}+data PivotStrategy+  = PivotStrategyBlandRule+  | PivotStrategyLargestCoefficient+--  | PivotStrategySteepestEdge+  deriving (Eq, Ord, Enum, Show, Read)++setPivotStrategy :: PrimMonad m => GenericSolverM m v -> PivotStrategy -> m ()+setPivotStrategy solver ps = writeMutVar (svPivotStrategy solver) ps++{--------------------------------------------------------------------+  problem description+--------------------------------------------------------------------}++data BacktrackPoint m v+  = BacktrackPoint+  { bpSavedLB :: !(MutVar (PrimState m) (IntMap (Bound v)))+  , bpSavedUB :: !(MutVar (PrimState m) (IntMap (Bound v)))+  }++cloneBacktrackPoint :: PrimMonad m => BacktrackPoint m v -> m (BacktrackPoint m v)+cloneBacktrackPoint bp = do+  lbs <- newMutVar =<< readMutVar (bpSavedLB bp)+  ubs <- newMutVar =<< readMutVar (bpSavedUB bp)+  return $ BacktrackPoint lbs ubs++pushBacktrackPoint :: PrimMonad m => GenericSolverM m v -> m ()+pushBacktrackPoint solver = do+  savedLBs <- newMutVar IntMap.empty+  savedUBs <- newMutVar IntMap.empty+  lbs <- readMutVar (svLB solver)+  ubs <- readMutVar (svUB solver)+  modifyMutVar (svBacktrackPoints solver) (BacktrackPoint savedLBs savedUBs :)++popBacktrackPoint :: PrimMonad m => GenericSolverM m v -> m ()+popBacktrackPoint solver = do+  bps <- readMutVar (svBacktrackPoints solver)+  case bps of+    [] -> error "popBacktrackPoint: empty backtrack points"+    bp : bps' -> do+      lbs <- readMutVar (svLB solver)+      savedLBs <- readMutVar (bpSavedLB bp)+      writeMutVar (svLB solver) $ IntMap.mergeWithKey (\_ _curr saved -> saved) id (const IntMap.empty) lbs savedLBs++      ubs <- readMutVar (svUB solver)+      savedUBs <- readMutVar (bpSavedUB bp)+      writeMutVar (svUB solver) $ IntMap.mergeWithKey (\_ _curr saved -> saved) id (const IntMap.empty) ubs savedUBs++      writeMutVar (svBacktrackPoints solver) bps'+      writeMutVar (svOk solver) True++withBacktrackpoint :: PrimMonad m => GenericSolverM m v -> (BacktrackPoint m v -> m ()) -> m ()+withBacktrackpoint solver f = do+  bps <- readMutVar (svBacktrackPoints solver)+  case bps of+    [] -> return ()+    bp : _ -> f bp++bpSaveLB :: PrimMonad m => GenericSolverM m v -> Var -> m ()+bpSaveLB solver v = do+  withBacktrackpoint solver $ \bp -> do+    saved <- readMutVar (bpSavedLB bp)+    if v `IntMap.member` saved then+      return ()+    else do+      lb <- readMutVar (svLB solver)+      let old = IntMap.lookup v lb+      seq old $ writeMutVar (bpSavedLB bp) (IntMap.insert v old saved)++bpSaveUB :: PrimMonad m => GenericSolverM m v -> Var -> m ()+bpSaveUB solver v = do+  withBacktrackpoint solver $ \bp -> do+    saved <- readMutVar (bpSavedUB bp)+    if v `IntMap.member` saved then+      return ()+    else do+      ub <- readMutVar (svUB solver)+      let old = IntMap.lookup v ub+      seq old $ writeMutVar (bpSavedUB bp) (IntMap.insert v old saved)++{--------------------------------------------------------------------+  problem description+--------------------------------------------------------------------}++newVar :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> m Var+newVar solver = do+  v <- readMutVar (svVCnt solver)+  writeMutVar (svVCnt solver) $! v+1+  modifyMutVar (svModel solver) (IntMap.insert v zeroV)+  return v++assertAtom :: PrimMonad m => GenericSolverM m Rational -> LA.Atom Rational -> m ()+assertAtom solver atom = assertAtom' solver atom Nothing++assertAtom' :: PrimMonad m => GenericSolverM m Rational -> LA.Atom Rational -> Maybe ConstrID -> m ()+assertAtom' solver atom cid = do+  (v,op,rhs') <- simplifyAtom solver atom+  case op of+    Le  -> assertUpper' solver v (toValue rhs') cid+    Ge  -> assertLower' solver v (toValue rhs') cid+    Eql -> do+      assertLower' solver v (toValue rhs') cid+      assertUpper' solver v (toValue rhs') cid+    _ -> error "unsupported"+  return ()++assertAtomEx :: PrimMonad m => GenericSolverM m (Delta Rational) -> LA.Atom Rational -> m ()+assertAtomEx solver atom = assertAtomEx' solver atom Nothing++assertAtomEx' :: PrimMonad m => GenericSolverM m (Delta Rational) -> LA.Atom Rational -> Maybe ConstrID -> m ()+assertAtomEx' solver atom cid = do+  (v,op,rhs') <- simplifyAtom solver atom+  case op of+    Le  -> assertUpper' solver v (toValue rhs') cid+    Ge  -> assertLower' solver v (toValue rhs') cid+    Lt  -> assertUpper' solver v (toValue rhs' ^-^ delta) cid+    Gt  -> assertLower' solver v (toValue rhs' ^+^ delta) cid+    Eql -> do+      assertLower' solver v (toValue rhs') cid+      assertUpper' solver v (toValue rhs') cid+  return ()++simplifyAtom :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> LA.Atom Rational -> m (Var, RelOp, Rational)+simplifyAtom solver (OrdRel lhs op rhs) = do+  let (lhs',rhs') =+        case LA.extract LA.unitVar (lhs ^-^ rhs) of+          (n,e) -> (e, -n)+  case LA.terms lhs' of+    [(1,v)] -> return (v, op, rhs')+    [(-1,v)] -> return (v, flipOp op, -rhs')+    _ -> do+      defs <- readMutVar (svDefDB solver)+      let (c,lhs'') = scale lhs' -- lhs' = lhs'' / c = rhs'+          rhs'' = c *^ rhs'+          op''  = if c < 0 then flipOp op else op+      case Map.lookup lhs'' defs of+        Just v -> do+          return (v,op'',rhs'')+        Nothing -> do+          v <- newVar solver+          setRow solver v lhs''+          modifyMutVar (svDefDB solver) $ Map.insert lhs'' v+          case LA.asConst lhs'' of+            Just 0 -> do+              modifyMutVar (svLB solver) (IntMap.insert v (toValue 0, mempty))+              modifyMutVar (svUB solver) (IntMap.insert v (toValue 0, mempty))+            _ -> return ()+          return (v,op'',rhs'')+  where+    scale :: LA.Expr Rational -> (Rational, LA.Expr Rational)+    scale e = (c, c *^ e)+      where+        c = c1 * c2+        c1 = fromIntegral $ foldl' lcm 1 [denominator c | (c, _) <- LA.terms e]+        c2 = signum $ head ([c | (c,x) <- LA.terms e] ++ [1])+             +assertLower :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> Var -> v -> m ()+assertLower solver x l = assertLower' solver x l Nothing++assertLower' :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> Var -> v -> Maybe ConstrID -> m ()+assertLower' solver x l cid = do+  let cidSet = IntSet.fromList $ maybeToList cid+  l0 <- getLB solver x+  u0 <- getUB solver x+  case (l0,u0) of +    (Just (l0', _), _) | l <= l0' -> return ()+    (_, Just (u0', cidSet2)) | u0' < l -> do+      writeMutVar (svExplanation solver) $ cidSet `IntSet.union` cidSet2+      markBad solver+    _ -> do+      bpSaveLB solver x+      modifyMutVar (svLB solver) (IntMap.insert x (l, cidSet))+      b <- isNonBasicVariable solver x+      v <- getValue solver x+      when (b && not (l <= v)) $ update solver x l+      checkNBFeasibility solver++assertUpper :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> Var -> v -> m ()+assertUpper solver x u = assertUpper' solver x u Nothing ++assertUpper' :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> Var -> v -> Maybe ConstrID -> m ()+assertUpper' solver x u cid = do+  let cidSet = IntSet.fromList $ maybeToList cid+  l0 <- getLB solver x+  u0 <- getUB solver x+  case (l0,u0) of+    (_, Just (u0', _)) | u0' <= u -> return ()+    (Just (l0', cidSet2), _) | u < l0' -> do+      writeMutVar (svExplanation solver) $ cidSet `IntSet.union` cidSet2+      markBad solver+    _ -> do+      bpSaveUB solver x+      modifyMutVar (svUB solver) (IntMap.insert x (u, cidSet))+      b <- isNonBasicVariable solver x+      v <- getValue solver x+      when (b && not (v <= u)) $ update solver x u+      checkNBFeasibility solver++-- FIXME: 式に定数項が含まれる可能性を考えるとこれじゃまずい?+setObj :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> LA.Expr Rational -> m ()+setObj solver e = setRow solver objVar e++getObj :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> m (LA.Expr Rational)+getObj solver = getRow solver objVar++setRow :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> Var -> LA.Expr Rational -> m ()+setRow solver v e = do+  modifyMutVar (svTableau solver) $ \t ->+    IntMap.insert v (LA.applySubst t e) t+  modifyMutVar (svModel solver) $ \m -> +    IntMap.insert v (LA.evalLinear m (toValue 1) e) m  ++setOptDir :: PrimMonad m => GenericSolverM m v -> OptDir -> m ()+setOptDir solver dir = writeMutVar (svOptDir solver) dir++getOptDir :: PrimMonad m => GenericSolverM m v -> m OptDir+getOptDir solver = readMutVar (svOptDir solver)++{--------------------------------------------------------------------+  Status+--------------------------------------------------------------------}++nVars :: PrimMonad m => GenericSolverM m v -> m Int+nVars solver = readMutVar (svVCnt solver)++isBasicVariable :: PrimMonad m => GenericSolverM m v -> Var -> m Bool+isBasicVariable solver v = do+  t <- readMutVar (svTableau solver)+  return $ v `IntMap.member` t++isNonBasicVariable  :: PrimMonad m => GenericSolverM m v -> Var -> m Bool+isNonBasicVariable solver x = liftM not (isBasicVariable solver x)++isFeasible :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> m Bool+isFeasible solver = do+  xs <- variables solver+  liftM and $ forM xs $ \x -> do+    v <- getValue solver x+    l <- getLB solver x+    u <- getUB solver x+    return (testLB l v && testUB u v)++isOptimal :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> m Bool+isOptimal solver = do+  obj <- getRow solver objVar+  ret <- selectEnteringVariable solver+  return $! isNothing ret++{--------------------------------------------------------------------+  Satisfiability solving+--------------------------------------------------------------------}++check :: forall m v. (PrimMonad m, SolverValue v) => GenericSolverM m v -> m Bool+check solver = do+  let+    loop :: m Bool+    loop = do+      m <- selectViolatingBasicVariable solver++      case m of+        Nothing -> return True+        Just xi  -> do+          li <- getLB solver xi+          ui <- getUB solver xi+          isLBViolated <- do+            vi <- getValue solver xi+            return $ not (testLB li vi)+          let q = if isLBViolated+                  then -- select the smallest non-basic variable xj such that+                       -- (aij > 0 and β(xj) < uj) or (aij < 0 and β(xj) > lj)+                       canIncrease solver+                  else -- select the smallest non-basic variable xj such that+                       -- (aij < 0 and β(xj) < uj) or (aij > 0 and β(xj) > lj)+                       canDecrease solver+          xi_def <- getRow solver xi+          r <- liftM (fmap snd) $ findM q (LA.terms xi_def)              +          case r of+            Nothing -> do+              let c = if isLBViolated then li else ui+              core <- liftM (mconcat . map boundExplanation . (c :)) $ forM (LA.terms xi_def) $ \(aij, xj) -> do+                if isLBViolated then do+                  if aij > 0 then do+                    getUB solver xj+                  else do+                    getLB solver xj+                else do+                  if aij > 0 then do+                    getLB solver xj+                  else do+                    getUB solver xj+              writeMutVar (svExplanation solver) core+              markBad solver+              return False+            Just xj -> do+              pivotAndUpdate solver xi xj (fromJust $ boundValue $ if isLBViolated then li else ui)+              loop++  ok <- readMutVar (svOk solver)+  if not ok+  then return False+  else do+    log solver "check"+    result <- recordTime solver loop+    when result $ checkFeasibility solver+    return result++selectViolatingBasicVariable :: forall m v. (PrimMonad m, SolverValue v) => GenericSolverM m v -> m (Maybe Var)+selectViolatingBasicVariable solver = do+  let+    p :: Var -> m Bool+    p x | x == objVar = return False+    p xi = do+      li <- getLB solver xi+      ui <- getUB solver xi+      vi <- getValue solver xi+      return $ not (testLB li vi) || not (testUB ui vi)+  vs <- basicVariables solver++  ps <- readMutVar (svPivotStrategy solver)+  case ps of+    PivotStrategyBlandRule ->+      findM p vs+    PivotStrategyLargestCoefficient -> do+      xs <- filterM p vs+      case xs of+        [] -> return Nothing+        _ -> do+          xs2 <- forM xs $ \xi -> do+              vi <- getValue solver xi+              li <- getLB solver xi+              ui <- getUB solver xi+              if not (testLB li vi)+                then return (xi, fromJust (boundValue li) ^-^ vi)+                else return (xi, vi ^-^ fromJust (boundValue ui))+          return $ Just $ fst $ maximumBy (comparing snd) xs2++{--------------------------------------------------------------------+  Optimization+--------------------------------------------------------------------}++-- | results of optimization+data OptResult = Optimum | Unsat | Unbounded | ObjLimit+  deriving (Show, Eq, Ord)++-- | Options for solving.+--+-- The default option can be obtained by 'def'.+data Options+  = Options+  { objLimit :: Maybe Rational+  }+  deriving (Show, Eq, Ord)++instance Default Options where+  def =+    Options+    { objLimit = Nothing+    }++optimize :: forall m. PrimMonad m => GenericSolverM m Rational -> Options -> m OptResult+optimize solver opt = do+  ret <- do+    is_fea <- isFeasible solver+    if is_fea then return True else check solver+  if not ret+    then return Unsat -- unsat+    else do+      log solver "optimize"+      result <- recordTime solver loop+      when (result == Optimum) $ checkOptimality solver+      return result+  where+    loop :: m OptResult+    loop = do+      checkFeasibility solver+      ret <- selectEnteringVariable solver+      case ret of+       Nothing -> return Optimum+       Just (c,xj) -> do+         dir <- getOptDir solver+         r <- if dir==OptMin+              then if c > 0+                then decreaseNB solver xj -- xj を小さくして目的関数を小さくする+                else increaseNB solver xj -- xj を大きくして目的関数を小さくする+              else if c > 0+                then increaseNB solver xj -- xj を大きくして目的関数を大きくする+                else decreaseNB solver xj -- xj を小さくして目的関数を大きくする+         if r+           then loop+           else return Unbounded++selectEnteringVariable :: forall m v. (PrimMonad m, SolverValue v) => GenericSolverM m v -> m (Maybe (Rational, Var))+selectEnteringVariable solver = do+  ps <- readMutVar (svPivotStrategy solver)+  obj_def <- getRow solver objVar+  case ps of+    PivotStrategyBlandRule ->+      findM canEnter (LA.terms obj_def)+    PivotStrategyLargestCoefficient -> do+      ts <- filterM canEnter (LA.terms obj_def)+      case ts of+        [] -> return Nothing+        _ -> return $ Just $ snd $ maximumBy (comparing fst) [(abs c, (c,xj)) | (c,xj) <- ts]+  where+    canEnter :: (Rational, Var) -> m Bool+    canEnter (_,xj) | xj == LA.unitVar = return False+    canEnter (c,xj) = do+      dir <- getOptDir solver+      if dir==OptMin+       then canDecrease solver (c,xj)+       else canIncrease solver (c,xj)++canIncrease :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> (Rational,Var) -> m Bool+canIncrease solver (a,x) =+  case compare a 0 of+    EQ -> return False+    GT -> canIncrease1 solver x+    LT -> canDecrease1 solver x++canDecrease :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> (Rational,Var) -> m Bool+canDecrease solver (a,x) =+  case compare a 0 of+    EQ -> return False+    GT -> canDecrease1 solver x+    LT -> canIncrease1 solver x++canIncrease1 :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> Var -> m Bool+canIncrease1 solver x = do+  u <- getUB solver x+  v <- getValue solver x+  case u of+    Nothing -> return True+    Just (uv, _) -> return $! (v < uv)++canDecrease1 :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> Var -> m Bool+canDecrease1 solver x = do+  l <- getLB solver x+  v <- getValue solver x+  case l of+    Nothing -> return True+    Just (lv, _) -> return $! (lv < v)++-- | feasibility を保ちつつ non-basic variable xj の値を大きくする+increaseNB :: PrimMonad m => GenericSolverM m Rational -> Var -> m Bool+increaseNB solver xj = do+  col <- getCol solver xj++  -- Upper bounds of θ+  -- NOTE: xj 自体の上限も考慮するのに注意+  ubs <- liftM concat $ forM ((xj,1) : IntMap.toList col) $ \(xi,aij) -> do+    v1 <- getValue solver xi+    li <- getLB solver xi+    ui <- getUB solver xi+    return [ assert (theta >= zeroV) ((xi,v2), theta)+           | Just v2 <- [boundValue ui | aij > 0] ++ [boundValue li | aij < 0]+           , let theta = (v2 ^-^ v1) ^/ aij ]++  -- β(xj) := β(xj) + θ なので θ を大きく+  case ubs of+    [] -> return False -- unbounded+    _ -> do+      let (xi, v) = fst $ minimumBy (comparing snd) ubs+      pivotAndUpdate solver xi xj v+      return True++-- | feasibility を保ちつつ non-basic variable xj の値を小さくする+decreaseNB :: PrimMonad m => GenericSolverM m Rational -> Var -> m Bool+decreaseNB solver xj = do+  col <- getCol solver xj++  -- Lower bounds of θ+  -- NOTE: xj 自体の下限も考慮するのに注意+  lbs <- liftM concat $ forM ((xj,1) : IntMap.toList col) $ \(xi,aij) -> do+    v1 <- getValue solver xi+    li <- getLB solver xi+    ui <- getUB solver xi+    return [ assert (theta <= zeroV) ((xi,v2), theta)+           | Just v2 <- [boundValue li | aij > 0] ++ [boundValue ui | aij < 0]+           , let theta = (v2 ^-^ v1) ^/ aij ]++  -- β(xj) := β(xj) + θ なので θ を小さく+  case lbs of+    [] -> return False -- unbounded+    _ -> do+      let (xi, v) = fst $ maximumBy (comparing snd) lbs+      pivotAndUpdate solver xi xj v+      return True++dualSimplex :: forall m. PrimMonad m => GenericSolverM m Rational -> Options -> m OptResult+dualSimplex solver opt = do+  let+    loop :: m OptResult+    loop = do+      checkOptimality solver++      p <- prune solver opt+      if p+        then return ObjLimit+        else do+          m <- selectViolatingBasicVariable solver+          case m of+            Nothing -> return Optimum+            Just xi  -> do+              xi_def  <- getRow solver xi+              li <- getLB solver xi+              ui <- getUB solver xi+              isLBViolated <- do+                vi <- getValue solver xi+                return $ not (testLB li vi)+              r <- dualRTest solver xi_def isLBViolated+              case r of+                Nothing -> do+                  -- dual unbounded+                  let c = if isLBViolated then li else ui+                  core <- liftM (mconcat . map boundExplanation . (c :)) $ forM (LA.terms xi_def) $ \(aij, xj) -> do+                    if isLBViolated then do+                      if aij > 0 then do+                        getUB solver xj+                      else do+                        getLB solver xj+                    else do+                      if aij > 0 then do+                        getLB solver xj+                      else do+                        getUB solver xj+                  writeMutVar (svExplanation solver) core+                  markBad solver+                  return Unsat+                Just xj -> do+                  pivotAndUpdate solver xi xj (fromJust $ boundValue $ if isLBViolated then li else ui)+                  loop++  ok <- readMutVar (svOk solver)+  if not ok+  then return Unsat+  else do+    log solver "dual simplex"+    result <- recordTime solver loop+    when (result == Optimum) $ checkFeasibility solver+    return result++dualRTest :: PrimMonad m => GenericSolverM m Rational -> LA.Expr Rational -> Bool -> m (Maybe Var)+dualRTest solver row isLBViolated = do+  -- normalize to the cases of minimization+  obj_def <- do+    def <- getRow solver objVar+    dir <- getOptDir solver+    return $+      case dir of+        OptMin -> def+        OptMax -> negateV def+  -- normalize to the cases of lower bound violation+  let xi_def =+       if isLBViolated+       then row+       else negateV row+  ws <- do+    -- select non-basic variable xj such that+    -- (aij > 0 and β(xj) < uj) or (aij < 0 and β(xj) > lj)+    liftM concat $ forM (LA.terms xi_def) $ \(aij, xj) -> do+      b <- canIncrease solver (aij, xj)+      if b+      then do+        let cj = LA.coeff xj obj_def+        let ratio = cj / aij+        return [(xj, ratio) | ratio >= 0]+      else+        return []+  case ws of+    [] -> return Nothing+    _ -> return $ Just $ fst $ minimumBy (comparing snd) ws++prune :: PrimMonad m => GenericSolverM m Rational -> Options -> m Bool+prune solver opt =+  case objLimit opt of+    Nothing -> return False+    Just lim -> do    +      o <- getObjValue solver+      dir <- getOptDir solver+      case dir of+        OptMin -> return $! (lim <= o)+        OptMax -> return $! (lim >= o)++{--------------------------------------------------------------------+  Extract results+--------------------------------------------------------------------}++type RawModel v = IntMap v++getRawModel :: PrimMonad m => GenericSolverM m v -> m (RawModel v)+getRawModel solver = do+  xs <- variables solver+  liftM IntMap.fromList $ forM xs $ \x -> do+    val <- getValue solver x+    return (x,val)++getObjValue :: PrimMonad m => GenericSolverM m v -> m v+getObjValue solver = getValue solver objVar  ++type Model = IntMap Rational++explain :: PrimMonad m => GenericSolverM m v -> m ConstrIDSet+explain solver = readMutVar (svExplanation solver)+  +{--------------------------------------------------------------------+  major function+--------------------------------------------------------------------}++update :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> Var -> v -> m ()+update solver xj v = do+  -- log solver $ printf "before update x%d (%s)" xj (show v)+  -- dump solver++  v0 <- getValue solver xj+  let diff = v ^-^ v0++  aj <- getCol solver xj+  modifyMutVar (svModel solver) $ \m ->+    let m2 = IntMap.map (\aij -> aij *^ diff) aj+    in IntMap.insert xj v $ IntMap.unionWith (^+^) m2 m++  -- log solver $ printf "after update x%d (%s)" xj (show v)+  -- dump solver++pivot :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> Var -> Var -> m ()+pivot solver xi xj = do+  modifyMutVar' (svNPivot solver) (+1)+  modifyMutVar' (svTableau solver) $ \defs ->+    case LA.solveFor (LA.var xi .==. (defs IntMap.! xi)) xj of+      Just (Eql, xj_def) ->+        IntMap.insert xj xj_def . IntMap.map (LA.applySubst1 xj xj_def) . IntMap.delete xi $ defs+      _ -> error "pivot: should not happen"++pivotAndUpdate :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> Var -> Var -> v -> m ()+pivotAndUpdate solver xi xj v | xi == xj = update solver xi v -- xi = xj is non-basic variable+pivotAndUpdate solver xi xj v = do+  -- xi is basic variable+  -- xj is non-basic varaible++  -- log solver $ printf "before pivotAndUpdate x%d x%d (%s)" xi xj (show v)+  -- dump solver++  m <- readMutVar (svModel solver)++  aj <- getCol solver xj+  let aij = aj IntMap.! xi+  let theta = (v ^-^ (m IntMap.! xi)) ^/ aij++  let m' = IntMap.fromList $+           [(xi, v), (xj, (m IntMap.! xj) ^+^ theta)] +++           [(xk, (m IntMap.! xk) ^+^ (akj *^ theta)) | (xk, akj) <- IntMap.toList aj, xk /= xi]+  writeMutVar (svModel solver) (IntMap.union m' m) -- note that 'IntMap.union' is left biased.++  pivot solver xi xj++  -- log solver $ printf "after pivotAndUpdate x%d x%d (%s)" xi xj (show v)+  -- dump solver++getLB :: PrimMonad m => GenericSolverM m v -> Var -> m (Bound v)+getLB solver x = do+  lb <- readMutVar (svLB solver)+  return $ IntMap.lookup x lb++getUB :: PrimMonad m => GenericSolverM m v -> Var -> m (Bound v)+getUB solver x = do+  ub <- readMutVar (svUB solver)+  return $ IntMap.lookup x ub++getTableau :: PrimMonad m => GenericSolverM m v -> m (IntMap (LA.Expr Rational))+getTableau solver = do+  t <- readMutVar (svTableau solver)+  return $ IntMap.delete objVar t++getValue :: PrimMonad m => GenericSolverM m v -> Var -> m v+getValue solver x = do+  m <- readMutVar (svModel solver)+  return $ m IntMap.! x++getRow :: PrimMonad m => GenericSolverM m v -> Var -> m (LA.Expr Rational)+getRow solver x = do+  -- x should be basic variable or 'objVar'+  t <- readMutVar (svTableau solver)+  return $! (t IntMap.! x)++-- aijが非ゼロの列も全部探しているのは効率が悪い+getCol :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> Var -> m (IntMap Rational)+getCol solver xj = do+  t <- readMutVar (svTableau solver)+  return $ IntMap.mapMaybe (LA.lookupCoeff xj) t++getCoeff :: PrimMonad m => GenericSolverM m v -> Var -> Var -> m Rational+getCoeff solver xi xj = do+  xi_def <- getRow solver xi+  return $! LA.coeff xj xi_def++markBad :: PrimMonad m => GenericSolverM m v -> m ()+markBad solver = writeMutVar (svOk solver) False++{--------------------------------------------------------------------+  utility+--------------------------------------------------------------------}++findM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a)+findM _ [] = return Nothing+findM p (x:xs) = do+  r <- p x+  if r+  then return (Just x)+  else findM p xs++testLB :: SolverValue v => Bound v -> v -> Bool+testLB Nothing _  = True+testLB (Just (l,_)) x = l <= x++testUB :: SolverValue v => Bound v -> v -> Bool+testUB Nothing _  = True+testUB (Just (u,_)) x = x <= u++variables :: PrimMonad m => GenericSolverM m v -> m [Var]+variables solver = do+  vcnt <- nVars solver+  return [0..vcnt-1]++basicVariables :: PrimMonad m => GenericSolverM m v -> m [Var]+basicVariables solver = do+  t <- readMutVar (svTableau solver)+  return (IntMap.keys t)++recordTime :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> m a -> m a+recordTime solver act = do+  dumpSize solver+  writeMutVar (svNPivot solver) 0+  rectm <- readMutVar (svRecTime solver)+  result <-+    case rectm of+      Nothing -> act+      Just f -> f solver $$ act+  (log solver . printf "#pivot = %d") =<< readMutVar (svNPivot solver)+  return result++showDelta :: Bool -> Delta Rational -> String+showDelta asRatio v = +  case v of+    (Delta r k) -> +      f r +++        case compare k 0 of+          EQ -> ""+          GT -> " + " ++ f k ++ " delta"+          LT -> " - " ++ f (abs k) ++ " delta"+  where+    f = showRational asRatio++{--------------------------------------------------------------------+  Logging+--------------------------------------------------------------------}++-- | set callback function for receiving messages.+setLogger :: PrimMonad m => GenericSolverM m v -> (String -> m ()) -> m ()+setLogger solver logger = do+  writeMutVar (svLogger solver) (Just logger)++clearLogger :: PrimMonad m => GenericSolverM m v -> m ()+clearLogger solver = writeMutVar (svLogger solver) Nothing++log :: PrimMonad m => GenericSolverM m v -> String -> m ()+log solver msg = logM solver (return msg)++logM :: PrimMonad m => GenericSolverM m v -> m String -> m ()+logM solver action = do+  m <- readMutVar (svLogger solver)+  case m of+    Nothing -> return ()+    Just logger -> action >>= logger++enableTimeRecording :: GenericSolverM IO v -> IO ()+enableTimeRecording solver = do+  writeMutVar (svRecTime solver) (Just f)+  where+    f solver = Nat $ \act -> do+        startCPU <- getTime ProcessCPUTime+        startWC  <- getTime Monotonic+        result <- act+        endCPU <- getTime ProcessCPUTime+        endWC  <- getTime Monotonic+        let durationSecs :: TimeSpec -> TimeSpec -> Double+            durationSecs start end = fromIntegral (toNanoSecs (end `diffTimeSpec` start)) / 10^(9::Int)      +        (log solver . printf "cpu time = %.3fs") (durationSecs startCPU endCPU)+        (log solver . printf "wall clock time = %.3fs") (durationSecs startWC endWC)+        return result++disableTimeRecording :: PrimMonad m => GenericSolverM m v -> m ()+disableTimeRecording solver = writeMutVar (svRecTime solver) Nothing++{--------------------------------------------------------------------+  debug and tests+--------------------------------------------------------------------}++test4 :: IO ()+test4 = do+  solver <- newSolver+  setLogger solver putStrLn+  x0 <- newVar solver+  x1 <- newVar solver++  writeMutVar (svTableau solver) (IntMap.fromList [(x1, LA.var x0)])+  writeMutVar (svLB solver) $ fmap (\v -> (v, mempty)) $ IntMap.fromList [(x0, 0), (x1, 0)]+  writeMutVar (svUB solver) $ fmap (\v -> (v, mempty)) $ IntMap.fromList [(x0, 2), (x1, 3)]+  setObj solver (LA.fromTerms [(-1, x0)])++  ret <- optimize solver def+  print ret+  dump solver++test5 :: IO ()+test5 = do+  solver <- newSolver+  setLogger solver putStrLn+  x0 <- newVar solver+  x1 <- newVar solver++  writeMutVar (svTableau solver) (IntMap.fromList [(x1, LA.var x0)])+  writeMutVar (svLB solver) $ fmap (\v -> (v, mempty)) $ IntMap.fromList [(x0, 0), (x1, 0)]+  writeMutVar (svUB solver) $ fmap (\v -> (v, mempty)) $ IntMap.fromList [(x0, 2), (x1, 0)]+  setObj solver (LA.fromTerms [(-1, x0)])++  checkFeasibility solver++  ret <- optimize solver def+  print ret+  dump solver++test6 :: IO ()+test6 = do+  solver <- newSolver+  setLogger solver putStrLn+  x0 <- newVar solver++  assertAtom solver (LA.constant 1 .<. LA.var x0)+  assertAtom solver (LA.constant 2 .>. LA.var x0)++  ret <- check solver+  print ret+  dump solver++  m <- getModel solver+  print m++dumpSize :: forall m v. PrimMonad m => SolverValue v => GenericSolverM m v -> m ()+dumpSize solver = do+  t <- readMutVar (svTableau solver)+  let nrows = IntMap.size t - 1 -- -1 is objVar+  xs <- variables solver+  let ncols = length xs - nrows+  let nnz = sum [IntMap.size $ LA.coeffMap xi_def | (xi,xi_def) <- IntMap.toList t, xi /= objVar]+  log solver $ printf "%d rows, %d columns, %d non-zeros" nrows ncols nnz++dump :: PrimMonad m => SolverValue v => GenericSolverM m v -> m ()+dump solver = do+  log solver "============="++  log solver "Tableau:"+  t <- readMutVar (svTableau solver)+  log solver $ printf "obj = %s" (show (t IntMap.! objVar))+  forM_ (IntMap.toList t) $ \(xi, e) -> do+    when (xi /= objVar) $ log solver $ printf "x%d = %s" xi (show e)++  log solver ""++  log solver "Assignments and Bounds:"+  objVal <- getValue solver objVar+  log solver $ printf "beta(obj) = %s" (showValue True objVal)+  xs <- variables solver +  forM_ xs $ \x -> do+    l <- getLB solver x+    u <- getUB solver x+    v <- getValue solver x+    let f Nothing = "Nothing"+        f (Just (x,_)) = showValue True x+    log solver $ printf "beta(x%d) = %s; %s <= x%d <= %s" x (showValue True v) (f l) x (f u)++  log solver ""+  log solver "Status:"+  is_fea <- isFeasible solver+  is_opt <- isOptimal solver+  log solver $ printf "Feasible: %s" (show is_fea)+  log solver $ printf "Optimal: %s" (show is_opt)++  log solver "============="++checkFeasibility :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> m ()+checkFeasibility _ | True = return ()+checkFeasibility solver = do+  xs <- variables solver+  forM_ xs $ \x -> do+    v <- getValue solver x+    l <- getLB solver x+    u <- getUB solver x+    let f Nothing = "Nothing"+        f (Just (x,_)) = showValue True x+    unless (testLB l v) $+      error (printf "(%s) <= x%d is violated; x%d = (%s)" (f l) x x (showValue True v))+    unless (testUB u v) $+      error (printf "x%d <= (%s) is violated; x%d = (%s)" x (f u) x (showValue True v))+    return ()++checkNBFeasibility :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> m ()+checkNBFeasibility _ | True = return ()+checkNBFeasibility solver = do+  xs <- variables solver+  forM_ xs $ \x -> do+    b <- isNonBasicVariable solver x+    when b $ do+      v <- getValue solver x+      l <- getLB solver x+      u <- getUB solver x+      let f Nothing = "Nothing"+          f (Just (x,_)) = showValue True x+      unless (testLB l v) $+        error (printf "checkNBFeasibility: (%s) <= x%d is violated; x%d = (%s)" (f l) x x (showValue True v))+      unless (testUB u v) $+        error (printf "checkNBFeasibility: x%d <= (%s) is violated; x%d = (%s)" x (f u) x (showValue True v))++checkOptimality :: (PrimMonad m, SolverValue v) => GenericSolverM m v -> m ()+checkOptimality _ | True = return ()+checkOptimality solver = do+  ret <- selectEnteringVariable solver+  case ret of+    Nothing -> return () -- optimal+    Just (_,x) -> error (printf "checkOptimality: not optimal (x%d can be changed)" x)
+ src/ToySolver/Arith/Simplex/Simple.hs view
@@ -0,0 +1,71 @@+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Arith.Simplex.Simple+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  portable+--+-----------------------------------------------------------------------------+module ToySolver.Arith.Simplex.Simple+  ( Model+  , OptDir (..)+  , OptResult (..)+  , check+  , optimize+  ) where++import Control.Monad+import Control.Monad.ST+import Data.Default.Class+import qualified Data.IntMap.Strict as IntMap+import qualified Data.IntSet as IntSet+import qualified ToySolver.Data.LA as LA+import ToySolver.Data.IntVar hiding (Model)+import qualified ToySolver.Arith.Simplex as Simplex+import ToySolver.Arith.Simplex hiding (check, optimize)++check :: VarSet -> [LA.Atom Rational] -> Maybe Model+check vs as = runST $ do+  solver <- Simplex.newSolver+  s <- liftM IntMap.fromAscList $ forM (IntSet.toAscList vs) $ \v -> do+    v2 <- Simplex.newVar solver+    return (v, v2)+  let s' = fmap LA.var s+      mtrans m = fmap (m IntMap.!) s+  forM_ as $ \a -> do+    Simplex.assertAtomEx solver (fmap (LA.applySubst s') a)+  ret <- Simplex.check solver+  if ret then do+    m <- Simplex.getModel solver    +    return $ Just $ mtrans m+  else+    return Nothing++optimize :: VarSet -> OptDir -> LA.Expr Rational -> [LA.Atom Rational] -> (OptResult, Maybe Model)+optimize vs dir obj as = runST $ do+  solver <- Simplex.newSolver+  s <- liftM IntMap.fromAscList $ forM (IntSet.toAscList vs) $ \v -> do+    v2 <- Simplex.newVar solver+    return (v, v2)+  let s' = fmap LA.var s+      mtrans m = fmap (m IntMap.!) s+  forM_ as $ \a -> do+    assertAtom solver (fmap (LA.applySubst s') a)+  Simplex.setOptDir solver dir+  Simplex.setObj solver obj+  ret <- Simplex.optimize solver def+  case ret of+    Optimum -> do+      m <- Simplex.getModel solver+      return $ (ret, Just (mtrans m))+    Unsat -> do+      return $ (ret, Nothing)+    Unbounded -> do+      m <- Simplex.getModel solver+      return $ (ret, Just (mtrans m))+    ObjLimit -> do+      error "should not happen"
+ src/ToySolver/Arith/Simplex/Textbook.hs view
@@ -0,0 +1,366 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Arith.Simplex.Textbook+-- Copyright   :  (c) Masahiro Sakai 2011+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable (ScopedTypeVariables)+--+-- Naïve implementation of Simplex method+-- +-- Reference:+--+-- * <http://www.math.cuhk.edu.hk/~wei/lpch3.pdf>+--+-----------------------------------------------------------------------------+module ToySolver.Arith.Simplex.Textbook+  (+  -- * The @Tableau@ type+    Tableau+  , RowIndex+  , ColIndex+  , Row+  , emptyTableau+  , objRowIndex+  , pivot+  , lookupRow+  , addRow+  , setObjFun++  -- * Optimization direction+  , module Data.OptDir++  -- * Reading status+  , currentValue+  , currentObjValue+  , isFeasible+  , isOptimal++  -- * High-level solving functions+  , simplex+  , dualSimplex+  , phaseI+  , primalDualSimplex++  -- * For debugging+  , isValidTableau+  , toCSV+  ) where++import Data.Ord+import Data.List+import qualified Data.IntMap as IM+import qualified Data.IntSet as IS+import Data.OptDir+import Data.VectorSpace+import Control.Exception++import qualified ToySolver.Data.LA as LA+import ToySolver.Data.IntVar++-- ---------------------------------------------------------------------------++type Tableau r = VarMap (Row r)+{-+tbl ! v == (m, val)+==>+var v .+. m .==. constant val+-}++-- | Basic variables+type RowIndex = Int++-- | Non-basic variables+type ColIndex = Int++type Row r = (VarMap r, r)++data PivotResult r = PivotUnbounded | PivotFinished | PivotSuccess (Tableau r)+  deriving (Show, Eq, Ord)++emptyTableau :: Tableau r+emptyTableau = IM.empty++objRowIndex :: RowIndex+objRowIndex = -1++pivot :: (Fractional r, Eq r) => RowIndex -> ColIndex -> Tableau r -> Tableau r+{-# INLINE pivot #-}+{-# SPECIALIZE pivot :: RowIndex -> ColIndex -> Tableau Rational -> Tableau Rational #-}+{-# SPECIALIZE pivot :: RowIndex -> ColIndex -> Tableau Double -> Tableau Double #-}+pivot r s tbl =+    assert (isValidTableau tbl) $  -- precondition+    assert (isValidTableau tbl') $ -- postcondition+      tbl'+  where+    tbl' = IM.insert s row_s $ IM.map f $ IM.delete r $ tbl+    f orig@(row_i, row_i_val) =+      case IM.lookup s row_i of+        Nothing -> orig+        Just c ->+          ( IM.filter (0/=) $ IM.unionWith (+) (IM.delete s row_i) (IM.map (negate c *) row_r')+          , row_i_val - c*row_r_val'+          )+    (row_r, row_r_val) = lookupRow r tbl+    a_rs = row_r IM.! s+    row_r' = IM.map (/ a_rs) $ IM.insert r 1 $ IM.delete s row_r+    row_r_val' = row_r_val / a_rs+    row_s = (row_r', row_r_val')++-- | Lookup a row by basic variable+lookupRow :: RowIndex -> Tableau r -> Row r+lookupRow r m = m IM.! r++-- 行の基底変数の列が0になるように変形+normalizeRow :: (Num r, Eq r) => Tableau r -> Row r -> Row r+normalizeRow a (row0,val0) = obj'+  where+    obj' = g $ foldl' f (IM.empty, val0) $ +           [ case IM.lookup j a of+               Nothing -> (IM.singleton j x, 0)+               Just (row,val) -> (IM.map ((-x)*) (IM.delete j row), -x*val)+           | (j,x) <- IM.toList row0 ]+    f (m1,v1) (m2,v2) = (IM.unionWith (+) m1 m2, v1+v2)+    g (m,v) = (IM.filter (0/=) m, v)++setRow :: (Num r, Eq r) => Tableau r -> RowIndex -> Row r -> Tableau r+setRow tbl i row = assert (isValidTableau tbl) $ assert (isValidTableau tbl') $ tbl'+  where+    tbl' = IM.insert i (normalizeRow tbl row) tbl++addRow :: (Num r, Eq r) => Tableau r -> RowIndex -> Row r -> Tableau r+addRow tbl i row = assert (i `IM.notMember` tbl) $ setRow tbl i row++setObjFun :: (Num r, Eq r) => Tableau r -> LA.Expr r -> Tableau r+setObjFun tbl e = addRow tbl objRowIndex row+  where+    row =+      case LA.extract LA.unitVar e of+        (c, e') -> (LA.coeffMap (negateV e'), c)++copyObjRow :: (Num r, Eq r) => Tableau r -> Tableau r -> Tableau r+copyObjRow from to =+  case IM.lookup objRowIndex from of+    Nothing -> IM.delete objRowIndex to+    Just row -> addRow to objRowIndex row++currentValue :: Num r => Tableau r -> Var -> r+currentValue tbl v =+  case IM.lookup v tbl of+    Nothing -> 0+    Just (_, val) -> val++currentObjValue :: Tableau r -> r+currentObjValue = snd . lookupRow objRowIndex++isValidTableau :: Tableau r -> Bool+isValidTableau tbl =+  and [v `IM.notMember` m | (v, (m,_)) <- IM.toList tbl, v /= objRowIndex] &&+  and [IS.null (IM.keysSet m `IS.intersection` vs) | (m,_) <- IM.elems tbl']+  where+    tbl' = IM.delete objRowIndex tbl+    vs = IM.keysSet tbl' ++isFeasible :: Real r => Tableau r -> Bool+isFeasible tbl = +  and [val >= 0 | (v, (_,val)) <- IM.toList tbl, v /= objRowIndex]++isOptimal :: Real r => OptDir -> Tableau r -> Bool+isOptimal optdir tbl =+  and [not (cmp cj) | cj <- IM.elems (fst (lookupRow objRowIndex tbl))]+  where+    cmp = case optdir of+            OptMin -> (0<)+            OptMax -> (0>)++isImproving :: Real r => OptDir -> Tableau r -> Tableau r -> Bool+isImproving OptMin from to = currentObjValue to <= currentObjValue from +isImproving OptMax from to = currentObjValue to >= currentObjValue from ++-- ---------------------------------------------------------------------------+-- primal simplex++simplex :: (Real r, Fractional r) => OptDir -> Tableau r -> (Bool, Tableau r)+{-# SPECIALIZE simplex :: OptDir -> Tableau Rational -> (Bool, Tableau Rational) #-}+{-# SPECIALIZE simplex :: OptDir -> Tableau Double -> (Bool, Tableau Double) #-}+simplex optdir = go+  where+    go tbl = assert (isFeasible tbl) $+      case primalPivot optdir tbl of+        PivotFinished  -> assert (isOptimal optdir tbl) (True, tbl)+        PivotUnbounded -> (False, tbl)+        PivotSuccess tbl' -> assert (isImproving optdir tbl tbl') $ go tbl'++primalPivot :: (Real r, Fractional r) => OptDir -> Tableau r -> PivotResult r+{-# INLINE primalPivot #-}+primalPivot optdir tbl+  | null cs   = PivotFinished+  | null rs   = PivotUnbounded+  | otherwise = PivotSuccess (pivot r s tbl)+  where+    cmp = case optdir of+            OptMin -> (0<)+            OptMax -> (0>)+    cs = [(j,cj) | (j,cj) <- IM.toList (fst (lookupRow objRowIndex tbl)), cmp cj]+    -- smallest subscript rule+    s = fst $ head cs+    -- classical rule+    --s = fst $ (if optdir==OptMin then maximumBy else minimumBy) (compare `on` snd) cs+    rs = [ (i, y_i0 / y_is)+         | (i, (row_i, y_i0)) <- IM.toList tbl, i /= objRowIndex+         , let y_is = IM.findWithDefault 0 s row_i, y_is > 0+         ]+    r = fst $ minimumBy (comparing snd) rs++-- ---------------------------------------------------------------------------+-- dual simplex++dualSimplex :: (Real r, Fractional r) => OptDir -> Tableau r -> (Bool, Tableau r)+{-# SPECIALIZE dualSimplex :: OptDir -> Tableau Rational -> (Bool, Tableau Rational) #-}+{-# SPECIALIZE dualSimplex :: OptDir -> Tableau Double -> (Bool, Tableau Double) #-}+dualSimplex optdir = go+  where+    go tbl = assert (isOptimal optdir tbl) $+      case dualPivot optdir tbl of+        PivotFinished  -> assert (isFeasible tbl) $ (True, tbl)+        PivotUnbounded -> (False, tbl)+        PivotSuccess tbl' -> assert (isImproving optdir tbl' tbl) $ go tbl'++dualPivot :: (Real r, Fractional r) => OptDir -> Tableau r -> PivotResult r+{-# INLINE dualPivot #-}+dualPivot optdir tbl+  | null rs   = PivotFinished+  | null cs   = PivotUnbounded+  | otherwise = PivotSuccess (pivot r s tbl)+  where+    rs = [(i, row_i) | (i, (row_i, y_i0)) <- IM.toList tbl, i /= objRowIndex, 0 > y_i0]+    (r, row_r) = head rs+    cs = [ (j, if optdir==OptMin then y_0j / y_rj else - y_0j / y_rj)+         | (j, y_rj) <- IM.toList row_r+         , y_rj < 0+         , let y_0j = IM.findWithDefault 0 j obj+         ]+    s = fst $ minimumBy (comparing snd) cs+    (obj,_) = lookupRow objRowIndex tbl++-- ---------------------------------------------------------------------------+-- phase I of the two-phased method++phaseI :: (Real r, Fractional r) => Tableau r -> VarSet -> (Bool, Tableau r)+{-# SPECIALIZE phaseI :: Tableau Rational -> VarSet -> (Bool, Tableau Rational) #-}+{-# SPECIALIZE phaseI :: Tableau Double -> VarSet -> (Bool, Tableau Double) #-}+phaseI tbl avs+  | currentObjValue tbl1' /= 0 = (False, tbl1')+  | otherwise = (True, copyObjRow tbl $ removeArtificialVariables avs $ tbl1')+  where+    optdir = OptMax+    tbl1 = setObjFun tbl $ negateV $ sumV [LA.var v | v <- IS.toList avs]+    tbl1' = go tbl1+    go tbl2+      | currentObjValue tbl2 == 0 = tbl2+      | otherwise = +        case primalPivot optdir tbl2 of+          PivotSuccess tbl2' -> assert (isImproving optdir tbl2 tbl2') $ go tbl2'+          PivotFinished -> assert (isOptimal optdir tbl2) tbl2+          PivotUnbounded -> error "phaseI: should not happen"++-- post-processing of phaseI+-- pivotを使ってartificial variablesを基底から除いて、削除+removeArtificialVariables :: (Real r, Fractional r) => VarSet -> Tableau r -> Tableau r+removeArtificialVariables avs tbl0 = tbl2+  where+    tbl1 = foldl' f (IM.delete objRowIndex tbl0) (IS.toList avs)+    tbl2 = IM.map (\(row,val) ->  (IM.filterWithKey (\j _ -> j `IS.notMember` avs) row, val)) tbl1+    f tbl i =+      case IM.lookup i tbl of+        Nothing -> tbl+        Just row ->+          case [j | (j,c) <- IM.toList (fst row), c /= 0, j `IS.notMember` avs] of+            [] -> IM.delete i tbl+            j:_ -> pivot i j tbl++-- ---------------------------------------------------------------------------+-- primal-dual simplex++data PDResult = PDUnsat | PDOptimal | PDUnbounded++primalDualSimplex :: (Real r, Fractional r) => OptDir -> Tableau r -> (Bool, Tableau r)+{-# SPECIALIZE primalDualSimplex :: OptDir -> Tableau Rational -> (Bool, Tableau Rational) #-}+{-# SPECIALIZE primalDualSimplex :: OptDir -> Tableau Double -> (Bool, Tableau Double) #-}+primalDualSimplex optdir = go+  where+    go tbl =+      case pdPivot optdir tbl of+        Left PDOptimal   -> assert (isFeasible tbl) $ assert (isOptimal optdir tbl) $ (True, tbl)+        Left PDUnsat     -> assert (not (isFeasible tbl)) $ (False, tbl)+        Left PDUnbounded -> assert (not (isOptimal optdir tbl)) $ (False, tbl)+        Right tbl' -> go tbl'++pdPivot :: (Real r, Fractional r) => OptDir -> Tableau r -> Either PDResult (Tableau r)+pdPivot optdir tbl+  | null ps && null qs = Left PDOptimal -- optimal+  | otherwise =+      case ret of+        Left p -> -- primal update+          let rs = [ (i, (bi - t) / y_ip)+                   | (i, (row_i, bi)) <- IM.toList tbl, i /= objRowIndex+                   , let y_ip = IM.findWithDefault 0 p row_i, y_ip > 0+                   ]+              q = fst $ minimumBy (comparing snd) rs+          in if null rs+             then Left PDUnsat+             else Right (pivot q p tbl)+        Right q -> -- dual update+          let (row_q, _bq) = (tbl IM.! q)+              cs = [ (j, (cj'-t) / (-y_qj))+                   | (j, y_qj) <- IM.toList row_q+                   , y_qj < 0+                   , let cj  = IM.findWithDefault 0 j obj+                   , let cj' = if optdir==OptMax then cj else -cj+                   ]+              p = fst $ maximumBy (comparing snd) cs+              (obj,_) = lookupRow objRowIndex tbl+          in if null cs+             then Left PDUnbounded -- dual infeasible+             else Right (pivot q p tbl)+  where+    qs = [ (Right i, bi) | (i, (_row_i, bi)) <- IM.toList tbl, i /= objRowIndex, 0 > bi ]+    ps = [ (Left j, cj')+         | (j,cj) <- IM.toList (fst (lookupRow objRowIndex tbl))+         , let cj' = if optdir==OptMax then cj else -cj+         , 0 > cj' ]+    (ret, t) = minimumBy (comparing snd) (qs ++ ps)++-- ---------------------------------------------------------------------------++toCSV :: (Num r) => (r -> String) -> Tableau r -> String+toCSV showCell tbl = unlines . map (concat . intersperse ",") $ header : body+  where+    header :: [String]+    header = "" : map colName cols ++ [""]++    body :: [[String]]+    body = [showRow i (lookupRow i tbl) | i <- rows]++    rows :: [RowIndex]+    rows = IM.keys (IM.delete objRowIndex tbl) ++ [objRowIndex]++    cols :: [ColIndex]+    cols = [0..colMax]+      where+        colMax = maximum (-1 : [c | (row, _) <- IM.elems tbl, c <- IM.keys row])++    rowName :: RowIndex -> String+    rowName i = if i==objRowIndex then "obj" else "x" ++ show i++    colName :: ColIndex -> String+    colName j = "x" ++ show j++    showRow i (row, row_val) = rowName i : [showCell (IM.findWithDefault 0 j row') | j <- cols] ++ [showCell row_val]+      where row' = IM.insert i 1 row++-- ---------------------------------------------------------------------------
+ src/ToySolver/Arith/Simplex/Textbook/LPSolver.hs view
@@ -0,0 +1,328 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Arith.Simplex.Textbook.LPSolver+-- Copyright   :  (c) Masahiro Sakai 2011+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable (ScopedTypeVariables)+--+-- Naïve implementation of Simplex method+-- +-- Reference:+--+-- * <http://www.math.cuhk.edu.hk/~wei/lpch3.pdf>+--+-----------------------------------------------------------------------------++module ToySolver.Arith.Simplex.Textbook.LPSolver+  (+  -- * Solver type+    Solver+  , emptySolver++  -- * LP monad+  , LP+  , getTableau+  , putTableau++  -- * Problem specification+  , newVar+  , addConstraint+  , addConstraintWithArtificialVariable+  , tableau+  , define++  -- * Solving+  , phaseI+  , simplex+  , dualSimplex+  , OptResult (..)+  , twoPhaseSimplex+  , primalDualSimplex++  -- * Extract results+  , getModel++  -- * Utilities+  , collectNonnegVars+  ) where++import Control.Exception (assert)+import Control.Monad+import Control.Monad.State+import qualified Data.IntMap as IM+import qualified Data.IntSet as IS+import Data.OptDir+import Data.VectorSpace++import Data.Interval ((<=!), (>=!), (==!), (<!), (>!), (/=!))+import qualified Data.Interval as Interval++import ToySolver.Data.OrdRel+import qualified ToySolver.Data.LA as LA+import ToySolver.Data.IntVar+import qualified ToySolver.Arith.Simplex.Textbook as Simplex+import qualified ToySolver.Arith.BoundsInference as BI++-- ---------------------------------------------------------------------------+-- Solver type++type Solver r = (Var, Simplex.Tableau r, VarSet, VarMap (LA.Expr r))++emptySolver :: VarSet -> Solver r+emptySolver vs = (1 + maximum ((-1) : IS.toList vs), Simplex.emptyTableau, IS.empty, IM.empty)++-- ---------------------------------------------------------------------------+-- LP Monad++type LP r = State (Solver r)++-- | Allocate a new /non-negative/ variable.+newVar :: LP r Var+newVar = do+  (x,tbl,avs,defs) <- get+  put (x+1,tbl,avs,defs)+  return x++getTableau :: LP r (Simplex.Tableau r)+getTableau = do+  (_,tbl,_,_) <- get+  return tbl++putTableau :: Simplex.Tableau r -> LP r ()+putTableau tbl = do+  (x,_,avs,defs) <- get+  put (x,tbl,avs,defs)++addArtificialVariable :: Var -> LP r ()+addArtificialVariable v = do+  (x,tbl,avs,defs) <- get+  put (x, tbl, IS.insert v avs, defs)++getArtificialVariables :: LP r VarSet+getArtificialVariables = do+  (_,_,avs,_) <- get+  return avs++clearArtificialVariables :: LP r ()+clearArtificialVariables = do+  (x,tbl,_,defs) <- get+  put (x, tbl, IS.empty, defs)++define :: Var -> LA.Expr r -> LP r ()+define v e = do+  (x,tbl,avs,defs) <- get+  put (x,tbl,avs, IM.insert v e defs)++getDefs :: LP r (VarMap (LA.Expr r))+getDefs = do+  (_,_,_,defs) <- get+  return defs++-- ---------------------------------------------------------------------------++-- | Add a contraint and maintain feasibility condition by introducing artificial variable (if necessary).+--+-- * Disequality is not supported.+-- +-- * Unlike 'addConstraint', an equality contstraint becomes one row with an artificial variable.+-- +addConstraintWithArtificialVariable :: Real r => LA.Atom r -> LP r ()+addConstraintWithArtificialVariable c = do+  c2 <- expandDefs' c+  let (e, rop, b) = normalizeConstraint c2+  assert (b >= 0) $ return ()+  tbl <- getTableau+  case rop of+    -- x≥0 is trivially true, since x is non-negative.+    Ge | b==0 && isSingleVar e -> return ()+    -- -x≤0 is trivially true, since x is non-negative.+    Le | b==0 && isSingleNegatedVar e -> return ()++    Le -> do+      v <- newVar -- slack variable+      putTableau $ Simplex.addRow tbl v (LA.coeffMap e, b)+    Ge -> do+      v1 <- newVar -- surplus variable+      v2 <- newVar -- artificial variable+      putTableau $ Simplex.addRow tbl v2 (LA.coeffMap (e ^-^ LA.var v1), b)+      addArtificialVariable v2+    Eql -> do+      v <- newVar -- artificial variable+      putTableau $ Simplex.addRow tbl v (LA.coeffMap e, b)+      addArtificialVariable v+    _ -> error $ "ToySolver.LPSolver.addConstraintWithArtificialVariable does not support " ++ show rop++-- | Add a contraint, without maintaining feasibilty condition of tableaus.+--+-- * Disequality is not supported.+--+-- * Unlike 'addConstraintWithArtificialVariable', an equality constraint becomes two rows.+-- +addConstraint :: Real r => LA.Atom r -> LP r ()+addConstraint c = do+  OrdRel lhs rop rhs <- expandDefs' c+  let+    (b', e) = LA.extract LA.unitVar (lhs ^-^ rhs)+    b = - b'+  case rop of+    Le -> f e b+    Ge -> f (negateV e) (negate b)+    Eql -> do+      -- Unlike addConstraintWithArtificialVariable, an equality constraint becomes two rows.+      f e b+      f (negateV e) (negate b)+    _ -> error $ "ToySolver.LPSolver.addConstraint does not support " ++ show rop+  where+    -- -x≤b with b≥0 is trivially true.+    f e b | isSingleNegatedVar e && 0 <= b = return ()+    f e b = do+      tbl <- getTableau+      v <- newVar -- slack variable+      putTableau $ Simplex.addRow tbl v (LA.coeffMap e, b)++isSingleVar :: Real r => LA.Expr r -> Bool+isSingleVar e =+  case LA.terms e of+    [(1,_)] -> True+    _ -> False++isSingleNegatedVar :: Real r => LA.Expr r -> Bool+isSingleNegatedVar e =+  case LA.terms e of+    [(-1,_)] -> True+    _ -> False++expandDefs :: (Num r, Eq r) => LA.Expr r -> LP r (LA.Expr r)+expandDefs e = do+  defs <- getDefs+  return $ LA.applySubst defs e++expandDefs' :: (Num r, Eq r) => LA.Atom r -> LP r (LA.Atom r)+expandDefs' (OrdRel lhs op rhs) = do+  lhs' <- expandDefs lhs+  rhs' <- expandDefs rhs+  return $ OrdRel lhs' op rhs'++tableau :: (RealFrac r) => [LA.Atom r] -> LP r ()+tableau cs = do+  let (nonnegVars, cs') = collectNonnegVars cs IS.empty+      fvs = vars cs `IS.difference` nonnegVars+  forM_ (IS.toList fvs) $ \v -> do+    v1 <- newVar+    v2 <- newVar+    define v (LA.var v1 ^-^ LA.var v2)+  mapM_ addConstraint cs'++getModel :: Fractional r => VarSet -> LP r (Model r)+getModel vs = do+  tbl <- getTableau+  defs <- getDefs+  let vs' = (vs `IS.difference` IM.keysSet defs) `IS.union` IS.unions [vars e | e <- IM.elems defs]+      m0 = IM.fromAscList [(v, Simplex.currentValue tbl v) | v <- IS.toAscList vs']+  return $ IM.filterWithKey (\k _ -> k `IS.member` vs) $ IM.map (LA.eval m0) defs `IM.union` m0++phaseI :: (Fractional r, Real r) => LP r Bool+phaseI = do+  introduceArtificialVariables+  tbl <- getTableau+  avs <- getArtificialVariables+  let (ret, tbl') = Simplex.phaseI tbl avs+  putTableau tbl'+  when ret clearArtificialVariables+  return ret++introduceArtificialVariables :: (Real r) => LP r ()+introduceArtificialVariables = do+  tbl <- getTableau+  tbl' <- liftM IM.fromList $ forM (IM.toList tbl) $ \(v,(e,rhs)) -> do+    if rhs >= 0 then do+      return (v,(e,rhs)) -- v + e == rhs+    else do+      a <- newVar+      addArtificialVariable a+      return (a, (IM.insert v (-1) (IM.map negate e), -rhs)) -- a - (v + e) == -rhs+  putTableau tbl'++simplex :: (Fractional r, Real r) => OptDir -> LA.Expr r -> LP r Bool+simplex optdir obj = do+  tbl <- getTableau+  defs <- getDefs+  let (ret, tbl') = Simplex.simplex optdir (Simplex.setObjFun tbl (LA.applySubst defs obj))+  putTableau tbl'+  return ret++dualSimplex :: (Fractional r, Real r) => OptDir -> LA.Expr r -> LP r Bool+dualSimplex optdir obj = do+  tbl <- getTableau+  defs <- getDefs+  let (ret, tbl') = Simplex.dualSimplex optdir (Simplex.setObjFun tbl (LA.applySubst defs obj))+  putTableau tbl'+  return ret++-- | results of optimization+data OptResult = Optimum | Unsat | Unbounded+  deriving (Show, Eq, Ord)++twoPhaseSimplex :: (Fractional r, Real r) => OptDir -> LA.Expr r -> LP r OptResult+twoPhaseSimplex optdir obj = do+  ret <- phaseI+  if not ret then+    return Unsat+  else do+    ret <- simplex optdir obj+    if ret then+      return Optimum+    else+      return Unbounded++primalDualSimplex :: (Fractional r, Real r) => OptDir -> LA.Expr r -> LP r OptResult+primalDualSimplex optdir obj = do+  tbl <- getTableau+  defs <- getDefs+  let (ret, tbl') = Simplex.primalDualSimplex optdir (Simplex.setObjFun tbl (LA.applySubst defs obj))+  putTableau tbl'+  if ret then+    return Optimum+  else if not (Simplex.isFeasible tbl') then+    return Unsat+  else+    return Unbounded++-- ---------------------------------------------------------------------------++-- convert right hand side to be non-negative+normalizeConstraint :: forall r. Real r => LA.Atom r -> (LA.Expr r, RelOp, r)+normalizeConstraint (OrdRel a op b)+  | rhs < 0   = (negateV lhs, flipOp op, negate rhs)+  | otherwise = (lhs, op, rhs)+  where+    (c, lhs) = LA.extract LA.unitVar (a ^-^ b)+    rhs = - c++collectNonnegVars :: forall r. (RealFrac r) => [LA.Atom r] -> VarSet -> (VarSet, [LA.Atom r])+collectNonnegVars cs ivs = (nonnegVars, cs)+  where+    vs = vars cs+    bounds = BI.inferBounds initialBounds cs ivs 1000+      where+        initialBounds = IM.fromAscList [(v, Interval.whole) | v <- IS.toAscList vs]+    nonnegVars = IS.filter (\v -> 0 <=! (bounds IM.! v)) vs++    isTriviallyTrue :: LA.Atom r -> Bool+    isTriviallyTrue (OrdRel a op b) =+      case op of+        Le -> i <=! 0+        Ge -> i >=! 0+        Lt -> i <! 0+        Gt -> i >! 0+        Eql -> i ==! 0+        NEq -> i /=! 0+      where+        i = LA.computeInterval bounds (a ^-^ b)++-- ---------------------------------------------------------------------------
+ src/ToySolver/Arith/Simplex/Textbook/LPSolver/Simple.hs view
@@ -0,0 +1,275 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Arith.Simplex.Textbook.LPSolver.Simple+-- Copyright   :  (c) Masahiro Sakai 2011+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable (ScopedTypeVariables)+--+-- High-Level API for LPSolver.hs+--+-----------------------------------------------------------------------------++module ToySolver.Arith.Simplex.Textbook.LPSolver.Simple+  ( OptResult (..)+  , minimize+  , maximize+  , optimize+  , solve+  ) where++import Control.Monad.State+import qualified Data.IntMap as IM+import qualified Data.IntSet as IS+import Data.OptDir+import Data.VectorSpace++import ToySolver.Data.OrdRel+import qualified ToySolver.Data.LA as LA+import ToySolver.Data.IntVar+import qualified ToySolver.Arith.Simplex.Textbook as Simplex+import qualified ToySolver.Arith.Simplex.Textbook.LPSolver as LPSolver+import ToySolver.Arith.Simplex.Textbook.LPSolver hiding (OptResult (..))++-- ---------------------------------------------------------------------------++-- | 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) => LA.Expr r -> [LA.Atom r] -> OptResult r+minimize = optimize OptMin++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 Nothing+      else do+        m <- getModel vs+        return (Just m)+  where+    vs = vars cs++optimize :: (RealFrac r) => OptDir -> LA.Expr r -> [LA.Atom r] -> OptResult r+optimize optdir obj cs =+  flip evalState (emptySolver vs) $ do+    tableau cs+    ret <- LPSolver.twoPhaseSimplex optdir obj+    case ret of+      LPSolver.Unsat -> return OptUnsat+      LPSolver.Unbounded -> return Unbounded+      LPSolver.Optimum -> do+        m <- getModel vs+        tbl <- getTableau +        return $ Optimum (Simplex.currentObjValue tbl) m+  where+    vs = vars cs `IS.union` vars obj++-- ---------------------------------------------------------------------------+-- Test cases++example_3_2 :: (LA.Expr Rational, [LA.Atom Rational])+example_3_2 = (obj, cond)+  where+    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+test_3_2 =+  uncurry maximize example_3_2 == +  Optimum (27/5) (IM.fromList [(1,1/5),(2,0),(3,8/5)])++example_3_5 :: (LA.Expr Rational, [LA.Atom Rational])+example_3_5 = (obj, cond)+  where+    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+test_3_5 =+  uncurry minimize example_3_5 ==+  Optimum 19 (IM.fromList [(1,-1),(2,0),(3,1),(4,0),(5,2)])++example_4_1 :: (LA.Expr Rational, [LA.Atom Rational])+example_4_1 = (obj, cond)+  where+    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+test_4_1 =+  uncurry maximize example_4_1 ==+  OptUnsat++example_4_2 :: (LA.Expr Rational, [LA.Atom Rational])+example_4_2 = (obj, cond)+  where+    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+test_4_2 =+  uncurry maximize example_4_2 ==+  Unbounded++example_4_3 :: (LA.Expr Rational, [LA.Atom Rational])+example_4_3 = (obj, cond)+  where+    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+test_4_3 =+  uncurry maximize example_4_3 ==+  Optimum 12 (IM.fromList [(1,4),(2,6)])++example_4_5 :: (LA.Expr Rational, [LA.Atom Rational])+example_4_5 = (obj, cond)+  where+    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+test_4_5 =+  uncurry maximize example_4_5 ==+  Optimum 5 (IM.fromList [(1,3/2),(2,2)])++example_4_6 :: (LA.Expr Rational, [LA.Atom Rational])+example_4_6 = (obj, cond)+  where+    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+test_4_6 =+  uncurry maximize example_4_6 ==+  Optimum (165/4) (IM.fromList [(1,2),(2,1),(3,0),(4,1)])++example_4_7 :: (LA.Expr Rational, [LA.Atom Rational])+example_4_7 = (obj, cond)+  where+    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+test_4_7 =+  uncurry maximize example_4_7 ==+  Optimum (48/11) (IM.fromList [(1,0),(2,0),(3,81),(4,41)])++-- 退化して巡回の起こるKuhnの7変数3制約の例+kuhn_7_3 :: (LA.Expr Rational, [LA.Atom Rational])+kuhn_7_3 = (obj, cond)+  where+    [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+test_kuhn_7_3 =+  uncurry minimize kuhn_7_3 ==+  Optimum (-2) (IM.fromList [(1,2),(2,0),(3,0),(4,2),(5,0),(6,2),(7,0)])++testAll :: Bool+testAll = and+  [ test_3_2+  , test_3_5+  , test_4_1+  , test_4_2+  , test_4_3+  , test_4_5+  , test_4_6+  , test_4_7+  , test_kuhn_7_3+  ]++-- ---------------------------------------------------------------------------
+ src/ToySolver/Arith/Simplex/Textbook/MIPSolver/Simple.hs view
@@ -0,0 +1,282 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Arith.Simplex.Textbook.MIPSolver.Simple+-- Copyright   :  (c) Masahiro Sakai 2011+-- License     :  BSD-style+--+-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable (ScopedTypeVariables)+--+-- References:+-- +-- * [Gomory1960]+--   Ralph E. Gomory.+--   An Algorithm for the Mixed Integer Problem, Technical Report+--   RM-2597, 1960, The Rand Corporation, Santa Monica, CA.+--   <http://www.rand.org/pubs/research_memoranda/RM2597.html>+--+-- * [Gomory1958]+--   Ralph E. Gomory.+--   Outline of an algorithm for integer solutions to linear programs.+--   Bull. Amer. Math. Soc., Vol. 64, No. 5. (1958), pp. 275-278.+--   <http://projecteuclid.org/euclid.bams/1183522679>+-----------------------------------------------------------------------------++module ToySolver.Arith.Simplex.Textbook.MIPSolver.Simple+  ( module Data.OptDir+  , OptResult (..)+  , minimize+  , maximize+  , optimize+  ) where++import Control.Exception+import Control.Monad.State+import Data.Default.Class+import Data.Ord+import Data.Maybe+import Data.List (maximumBy)+import qualified Data.IntMap as IM+import qualified Data.IntSet as IS+import Data.OptDir+import Data.VectorSpace++import ToySolver.Data.OrdRel+import ToySolver.Data.IntVar+import qualified ToySolver.Data.LA as LA+import qualified ToySolver.Arith.Simplex.Textbook as Simplex+import qualified ToySolver.Arith.Simplex.Textbook.LPSolver as LPSolver+import ToySolver.Arith.Simplex.Textbook.LPSolver hiding (OptResult (..))+import ToySolver.Arith.Simplex.Textbook.LPSolver.Simple (OptResult (..))+import qualified ToySolver.Arith.OmegaTest as OmegaTest+import ToySolver.Internal.Util (isInteger, fracPart)++-- ---------------------------------------------------------------------------++data Node r+  = Node+  { ndSolver :: LPSolver.Solver r+  , ndDepth  :: {-# UNPACK #-} !Int+--  , ndCutSlackVariables :: VarSet+  }++ndTableau :: Node r  -> Simplex.Tableau r+ndTableau node = evalState getTableau (ndSolver node)++ndLowerBound :: Node r -> r+ndLowerBound node = evalState (liftM Simplex.currentObjValue getTableau) (ndSolver node)++data Err = ErrUnbounded | ErrUnsat deriving (Ord, Eq, Show, Enum, Bounded)++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+        ErrUnsat -> OptUnsat+        ErrUnbounded ->+          if IS.null ivs+          then Unbounded+          else+            {-+               Fallback to Fourier-Motzkin + OmegaTest+               * In general, original problem may have optimal+                 solution even though LP relaxiation is unbounded.+               * But if restricted to rational numbers, the+                 original problem is unbounded or unsatisfiable+                 when LP relaxation is unbounded.+            -}+            case OmegaTest.solveQFLIRAConj def (vars cs `IS.union` ivs) (map conv cs) ivs of+              Nothing -> OptUnsat+              Just _ -> Unbounded        +    Right (node0, ivs2) -> +      case traverseBBTree optdir obj ivs2 node0 of+        Left ErrUnbounded -> error "shoud not happen"+        Left ErrUnsat -> OptUnsat+        Right node -> flip evalState (ndSolver node) $ do+          tbl <- getTableau+          model <- getModel vs+          return $ Optimum (Simplex.currentObjValue tbl) model+  where+    vs = vars cs `IS.union` vars obj++tableau' :: (RealFrac r) => [LA.Atom r] -> VarSet -> LP r VarSet+tableau' cs ivs = do+  let (nonnegVars, cs') = collectNonnegVars cs ivs+      fvs = vars cs `IS.difference` nonnegVars+  ivs2 <- liftM IS.unions $ forM (IS.toList fvs) $ \v -> do+    v1 <- newVar+    v2 <- newVar+    define v (LA.var v1 ^-^ LA.var v2)+    return $ if v `IS.member` ivs then IS.fromList [v1,v2] else IS.empty+  mapM_ addConstraint cs'+  return ivs2++conv :: RealFrac r => LA.Atom r -> LA.Atom Rational+conv = fmap (LA.mapCoeff toRational)++mkInitialNode :: RealFrac r => OptDir -> LA.Expr r -> [LA.Atom r] -> VarSet -> Either Err (Node r, VarSet)+mkInitialNode optdir obj cs ivs =+  flip evalState (emptySolver vs) $ do+    ivs2 <- tableau' cs ivs+    ret <- LPSolver.twoPhaseSimplex optdir obj+    case ret of+      LPSolver.Unsat -> return (Left ErrUnsat)+      LPSolver.Unbounded -> return (Left ErrUnbounded)+      LPSolver.Optimum -> do+        solver <- get+        return $ Right $+          ( Node{ ndSolver = solver+                , ndDepth = 0+--                , ndCutSlackVariables = IS.empty+                }+          , ivs `IS.union` ivs2+          )+  where+    vs = vars cs `IS.union` vars obj++isStrictlyBetter :: RealFrac r => OptDir -> r -> r -> Bool+isStrictlyBetter optdir = if optdir==OptMin then (<) else (>)++traverseBBTree :: forall r. RealFrac r => OptDir -> LA.Expr r -> VarSet -> Node r -> Either Err (Node r)+traverseBBTree optdir obj ivs node0 = loop [node0] Nothing+  where+    loop :: [Node r] -> Maybe (Node r) -> Either Err (Node r)+    loop [] (Just best) = Right best+    loop [] Nothing = Left ErrUnsat+    loop (n:ns) Nothing =+      case children n of+        Nothing -> loop ns (Just n)+        Just cs -> loop (cs++ns) Nothing+    loop (n:ns) (Just best)+      | isStrictlyBetter optdir (ndLowerBound n) (ndLowerBound best) =+          case children n of+            Nothing -> loop ns (Just n)+            Just cs -> loop (cs++ns) (Just best)+      | otherwise = loop ns (Just best)++    reopt :: Solver r -> Maybe (Solver r)+    reopt s = flip evalState s $ do+      ret <- dualSimplex optdir obj+      if ret+        then liftM Just get+        else return Nothing++    children :: Node r -> Maybe [Node r]+    children node+      | null xs = Nothing -- no violation+      | ndDepth node `mod` 100 == 0 = -- cut+          let+            (f0, m0) = maximumBy (comparing fst) [(fracPart val, m) | (_,m,val) <- xs]+            sv = flip execState (ndSolver node) $ do+                   s <- newVar+                   let g j x = assert (a >= 0) a+                         where+                           a | j `IS.member` ivs =+                                if fracPart x <= f0+                                then fracPart x+                                else (f0 / (f0 - 1)) * (fracPart x - 1)+                                     -- [Gomory1960] では (f0 / (1 - f0)) * (fracPart x - 1) としているが、+                                     -- これは誤り+                             | otherwise =+                                if x >= 0+                                then x+                                else (f0 / (f0 - 1)) * x+                   putTableau $ IM.insert s (IM.mapWithKey (\j x -> negate (g j x)) m0, negate f0) tbl+          in Just $ [node{ ndSolver = sv2, ndDepth = ndDepth node + 1 } | sv2 <- maybeToList (reopt sv)]+      | otherwise = -- branch+          let (v0, val0) = snd $ maximumBy (comparing fst) [(fracPart val, (v, val)) | (v,_,val) <- xs]+              cs = [ LA.var v0 .>=. LA.constant (fromIntegral (ceiling val0 :: Integer))+                   , LA.var v0 .<=. LA.constant (fromIntegral (floor val0 :: Integer))+                   ]+              svs = [execState (addConstraint c) (ndSolver node) | c <- cs]+          in Just $ [node{ ndSolver = sv, ndDepth = ndDepth node + 1 } | Just sv <- map reopt svs]+        +      where+        tbl :: Simplex.Tableau r+        tbl = ndTableau node++        xs :: [(Var, VarMap r, r)]+        xs = [ (v, m, val)+             | v <- IS.toList ivs+             , Just (m, val) <- return (IM.lookup v tbl)+             , not (isInteger val)+             ]++-- ---------------------------------------------------------------------------++example1 :: (Fractional r, Eq r) => (OptDir, LA.Expr r, [LA.Atom r], VarSet)+example1 = (optdir, obj, cs, ivs)+  where+    optdir = OptMax+    x1 = LA.var 1+    x2 = LA.var 2+    x3 = LA.var 3+    x4 = LA.var 4+    obj = x1 ^+^ 2 *^ x2 ^+^ 3 *^ x3 ^+^ x4+    cs =+      [ (-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+      , LA.constant 0 .<=. x3+      , LA.constant 2 .<=. x4+      , x4 .<=. LA.constant 3+      ]+    ivs = IS.singleton 4++test1 :: Bool+test1 = result==expected+  where+    (optdir, obj, cs, ivs) = example1+    result, expected :: OptResult Rational+    result = optimize optdir obj cs ivs+    expected = Optimum (245/2) (IM.fromList [(1,40),(2,21/2),(3,39/2),(4,3)])++test1' :: Bool+test1' = result==expected+  where+    (optdir, obj, cs, ivs) = example1+    f OptMin = OptMax+    f OptMax = OptMin+    result, expected :: OptResult Rational+    result = optimize (f optdir) (negateV obj) cs ivs+    expected = Optimum (-245/2) (IM.fromList [(1,40),(2,21/2),(3,39/2),(4,3)])++-- 『数理計画法の基礎』(坂和 正敏) p.109 例 3.8+example2 :: (Fractional r, Eq r) => (OptDir, LA.Expr r, [LA.Atom r], VarSet)+example2 = (optdir, obj, cs, ivs)+  where+    optdir = OptMin+    [x1,x2,x3] = map LA.var [1..3]+    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+      , LA.constant 0 .<=. x1+      , LA.constant 0 .<=. x2+      , LA.constant 0 .<=. x3+      ]+    ivs = IS.fromList [1,2]++test2 :: Bool+test2 = result == expected+  where+    result, expected :: OptResult Rational+    result = optimize optdir obj cs ivs+    expected = Optimum (-37/2) (IM.fromList [(1,0),(2,2),(3,5/2)])+    (optdir, obj, cs, ivs) = example2++-- ---------------------------------------------------------------------------
− src/ToySolver/Arith/Simplex2.hs
@@ -1,1192 +0,0 @@-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, TypeFamilies, CPP #-}--------------------------------------------------------------------------------- |--- Module      :  ToySolver.Arith.Simplex2--- Copyright   :  (c) Masahiro Sakai 2012--- License     :  BSD-style--- --- Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  provisional--- Portability :  non-portable (TypeSynonymInstances, FlexibleInstances, TypeFamilies, CPP)------ Naïve implementation of Simplex method--- --- Reference:------ * <http://www.math.cuhk.edu.hk/~wei/lpch3.pdf>--- --- * Bruno Dutertre and Leonardo de Moura.---   A Fast Linear-Arithmetic Solver for DPLL(T).---   Computer Aided Verification In Computer Aided Verification, Vol. 4144 (2006), pp. 81-94.---   <http://yices.csl.sri.com/cav06.pdf>------ * Bruno Dutertre and Leonardo de Moura.---   Integrating Simplex with DPLL(T).---   CSL Technical Report SRI-CSL-06-01. 2006.---   <http://yices.csl.sri.com/sri-csl-06-01.pdf>----------------------------------------------------------------------------------module ToySolver.Arith.Simplex2-  (-  -- * The @Solver@ type-    Solver-  , GenericSolver-  , SolverValue (..)-  , newSolver-  , cloneSolver--  -- * Problem specification-  , Var-  , newVar-  , RelOp (..)-  , (.<=.), (.>=.), (.==.), (.<.), (.>.)-  , Atom (..)-  , ConstrID-  , ConstrIDSet-  , assertAtom-  , assertAtom'-  , assertAtomEx-  , assertAtomEx'-  , assertLower-  , assertLower'-  , assertUpper-  , assertUpper'-  , setObj-  , getObj-  , OptDir (..)-  , setOptDir-  , getOptDir--  -- * Solving-  , check-  , pushBacktrackPoint-  , popBacktrackPoint-  , Options (..)-  , OptResult (..)-  , optimize-  , dualSimplex--  -- * Extract results-  , Model-  , getModel-  , RawModel-  , getRawModel-  , getValue-  , getObjValue-  , explain--  -- * Reading status-  , getTableau-  , getRow-  , getCol-  , getCoeff-  , nVars-  , isBasicVariable-  , isNonBasicVariable-  , isFeasible-  , isOptimal-  , getLB-  , getUB-  , Bound-  , boundValue-  , boundExplanation--  -- * Configulation-  , setLogger-  , clearLogger-  , PivotStrategy (..)-  , setPivotStrategy--  -- * Debug-  , dump--  -- * Misc-  , simplifyAtom-  ) where--import Prelude hiding (log)-import Control.Exception-import Control.Monad-import Data.Default.Class-import Data.Ord-import Data.IORef-import Data.List-import Data.Maybe-import Data.Monoid-import Data.Ratio-import Data.Map (Map)-import qualified Data.Map as Map-import Data.IntMap (IntMap)-import qualified Data.IntMap as IntMap-import Data.IntSet (IntSet)-import qualified Data.IntSet as IntSet-import Text.Printf-import Data.Time-import Data.OptDir-import Data.VectorSpace-import System.CPUTime--import qualified ToySolver.Data.LA as LA-import ToySolver.Data.LA (Atom (..))-import ToySolver.Data.OrdRel-import ToySolver.Data.Delta-import ToySolver.Internal.Util (showRational)--{---------------------------------------------------------------------  The @Solver@ type---------------------------------------------------------------------}--type Var = Int--data GenericSolver v-  = GenericSolver-  { svTableau :: !(IORef (IntMap (LA.Expr Rational)))-  , svLB      :: !(IORef (IntMap (v, ConstrIDSet)))-  , svUB      :: !(IORef (IntMap (v, ConstrIDSet)))-  , svModel   :: !(IORef (IntMap v))-  , svExplanation :: !(IORef ConstrIDSet)-  , svVCnt    :: !(IORef Int)-  , svOk      :: !(IORef Bool)-  , svOptDir  :: !(IORef OptDir)--  , svDefDB  :: !(IORef (Map (LA.Expr Rational) Var))--  , svLogger :: !(IORef (Maybe (String -> IO ())))-  , svPivotStrategy :: !(IORef PivotStrategy)-  , svNPivot  :: !(IORef Int)--  , svBacktrackPoints :: !(IORef [BacktrackPoint v])-  }--type Solver = GenericSolver Rational---- special basic variable-objVar :: Int-objVar = -1--newSolver :: SolverValue v => IO (GenericSolver v)-newSolver = do-  t <- newIORef (IntMap.singleton objVar zeroV)-  l <- newIORef IntMap.empty-  u <- newIORef IntMap.empty-  m <- newIORef (IntMap.singleton objVar zeroV)-  e <- newIORef mempty-  v <- newIORef 0-  ok <- newIORef True-  dir <- newIORef OptMin-  defs <- newIORef Map.empty-  logger <- newIORef Nothing-  pivot <- newIORef PivotStrategyBlandRule-  npivot <- newIORef 0-  bps <- newIORef []-  return $-    GenericSolver-    { svTableau = t-    , svLB      = l-    , svUB      = u-    , svModel   = m-    , svExplanation = e-    , svVCnt    = v-    , svOk      = ok-    , svOptDir  = dir-    , svDefDB   = defs-    , svLogger  = logger-    , svNPivot  = npivot-    , svPivotStrategy = pivot-    , svBacktrackPoints = bps-    }--cloneSolver :: GenericSolver v -> IO (GenericSolver v)-cloneSolver solver = do-  t      <- newIORef =<< readIORef (svTableau solver)-  l      <- newIORef =<< readIORef (svLB solver)-  u      <- newIORef =<< readIORef (svUB solver)-  m      <- newIORef =<< readIORef (svModel solver)-  e      <- newIORef =<< readIORef (svExplanation solver)-  v      <- newIORef =<< readIORef (svVCnt solver)-  ok     <- newIORef =<< readIORef (svOk solver)-  dir    <- newIORef =<< readIORef (svOptDir solver)-  defs   <- newIORef =<< readIORef (svDefDB solver)-  logger <- newIORef =<< readIORef (svLogger solver)-  pivot  <- newIORef =<< readIORef (svPivotStrategy solver)-  npivot <- newIORef =<< readIORef (svNPivot solver)-  bps    <- newIORef =<< mapM cloneBacktrackPoint =<< readIORef (svBacktrackPoints solver)-  return $-    GenericSolver-    { svTableau = t-    , svLB      = l-    , svUB      = u-    , svModel   = m-    , svExplanation = e-    , svVCnt    = v-    , svOk      = ok-    , svOptDir  = dir-    , svDefDB   = defs-    , svLogger  = logger-    , svNPivot  = npivot-    , svPivotStrategy = pivot-    , svBacktrackPoints = bps-    }  --class (VectorSpace v, Scalar v ~ Rational, Ord v) => SolverValue v where-  toValue :: Rational -> v-  showValue :: Bool -> v -> String-  getModel :: GenericSolver v -> IO Model--instance SolverValue Rational where-  toValue = id-  showValue = showRational-  getModel = getRawModel--instance SolverValue (Delta Rational) where-  toValue = fromReal-  showValue = showDelta-  getModel solver = do-    xs <- variables solver-    ys <- liftM concat $ forM xs $ \x -> do-      Delta p q  <- getValue solver x-      lb <- getLB solver x-      ub <- getUB solver x-      return $-        [(p - c) / (k - q) | Just (Delta c k, _) <- return lb, c < p, k > q] ++-        [(d - p) / (q - h) | Just (Delta d h, _) <- return ub, p < d, q > h]-    let delta0 :: Rational-        delta0 = if null ys then 0.1 else minimum ys-        f :: Delta Rational -> Rational-        f (Delta r k) = r + k * delta0-    liftM (IntMap.map f) $ readIORef (svModel solver)--type ConstrID = Int-type ConstrIDSet = IntSet--type Bound v = Maybe (v, ConstrIDSet)--boundValue :: SolverValue v => Bound v -> Maybe v-boundValue = fmap fst--boundExplanation :: SolverValue v => Bound v -> ConstrIDSet-boundExplanation = maybe mempty snd--{--Largest coefficient rule: original rule suggested by G. Dantzig.-Largest increase rule: computationally more expensive in comparison with Largest coefficient, but locally maximizes the progress.-Steepest edge rule: best pivot rule in practice, an efficient approximate implementation is "Devex".-Bland’s rule: avoids cycling but one of the slowest rules.-Random edge rule: Randomized have lead to the current best provable bounds for the number of pivot steps of the simplex method.-Lexicographic rule: used for avoiding cyclying.--}-data PivotStrategy-  = PivotStrategyBlandRule-  | PivotStrategyLargestCoefficient---  | PivotStrategySteepestEdge-  deriving (Eq, Ord, Enum, Show, Read)--setPivotStrategy :: GenericSolver v -> PivotStrategy -> IO ()-setPivotStrategy solver ps = writeIORef (svPivotStrategy solver) ps--{---------------------------------------------------------------------  problem description---------------------------------------------------------------------}--data BacktrackPoint v-  = BacktrackPoint-  { bpSavedLB :: !(IORef (IntMap (Bound v)))-  , bpSavedUB :: !(IORef (IntMap (Bound v)))-  }--cloneBacktrackPoint :: BacktrackPoint v -> IO (BacktrackPoint v)-cloneBacktrackPoint bp = do-  lbs <- newIORef =<< readIORef (bpSavedLB bp)-  ubs <- newIORef =<< readIORef (bpSavedUB bp)-  return $ BacktrackPoint lbs ubs--pushBacktrackPoint :: GenericSolver v -> IO ()-pushBacktrackPoint solver = do-  savedLBs <- newIORef IntMap.empty-  savedUBs <- newIORef IntMap.empty-  lbs <- readIORef (svLB solver)-  ubs <- readIORef (svUB solver)-  modifyIORef (svBacktrackPoints solver) (BacktrackPoint savedLBs savedUBs :)--popBacktrackPoint :: GenericSolver v -> IO ()-popBacktrackPoint solver = do-  bps <- readIORef (svBacktrackPoints solver)-  case bps of-    [] -> error "popBacktrackPoint: empty backtrack points"-    bp : bps' -> do-      lbs <- readIORef (svLB solver)-      savedLBs <- readIORef (bpSavedLB bp)-      writeIORef (svLB solver) $ IntMap.mergeWithKey (\_ _curr saved -> saved) id (const IntMap.empty) lbs savedLBs--      ubs <- readIORef (svUB solver)-      savedUBs <- readIORef (bpSavedUB bp)-      writeIORef (svUB solver) $ IntMap.mergeWithKey (\_ _curr saved -> saved) id (const IntMap.empty) ubs savedUBs--      writeIORef (svBacktrackPoints solver) bps'-      writeIORef (svOk solver) True--withBacktrackpoint :: GenericSolver v -> (BacktrackPoint v -> IO ()) -> IO ()-withBacktrackpoint solver f = do-  bps <- readIORef (svBacktrackPoints solver)-  case bps of-    [] -> return ()-    bp : _ -> f bp--bpSaveLB :: GenericSolver v -> Var -> IO ()-bpSaveLB solver v = do-  withBacktrackpoint solver $ \bp -> do-    saved <- readIORef (bpSavedLB bp)-    if v `IntMap.member` saved then-      return ()-    else do-      lb <- readIORef (svLB solver)-      let old = IntMap.lookup v lb-      seq old $ writeIORef (bpSavedLB bp) (IntMap.insert v old saved)--bpSaveUB :: GenericSolver v -> Var -> IO ()-bpSaveUB solver v = do-  withBacktrackpoint solver $ \bp -> do-    saved <- readIORef (bpSavedUB bp)-    if v `IntMap.member` saved then-      return ()-    else do-      ub <- readIORef (svUB solver)-      let old = IntMap.lookup v ub-      seq old $ writeIORef (bpSavedUB bp) (IntMap.insert v old saved)--{---------------------------------------------------------------------  problem description---------------------------------------------------------------------}--newVar :: SolverValue v => GenericSolver v -> IO Var-newVar solver = do-  v <- readIORef (svVCnt solver)-  writeIORef (svVCnt solver) $! v+1-  modifyIORef (svModel solver) (IntMap.insert v zeroV)-  return v--assertAtom :: Solver -> LA.Atom Rational -> IO ()-assertAtom solver atom = assertAtom' solver atom Nothing--assertAtom' :: Solver -> LA.Atom Rational -> Maybe ConstrID -> IO ()-assertAtom' solver atom cid = do-  (v,op,rhs') <- simplifyAtom solver atom-  case op of-    Le  -> assertUpper' solver v (toValue rhs') cid-    Ge  -> assertLower' solver v (toValue rhs') cid-    Eql -> do-      assertLower' solver v (toValue rhs') cid-      assertUpper' solver v (toValue rhs') cid-    _ -> error "unsupported"-  return ()--assertAtomEx :: GenericSolver (Delta Rational) -> LA.Atom Rational -> IO ()-assertAtomEx solver atom = assertAtomEx' solver atom Nothing--assertAtomEx' :: GenericSolver (Delta Rational) -> LA.Atom Rational -> Maybe ConstrID -> IO ()-assertAtomEx' solver atom cid = do-  (v,op,rhs') <- simplifyAtom solver atom-  case op of-    Le  -> assertUpper' solver v (toValue rhs') cid-    Ge  -> assertLower' solver v (toValue rhs') cid-    Lt  -> assertUpper' solver v (toValue rhs' ^-^ delta) cid-    Gt  -> assertLower' solver v (toValue rhs' ^+^ delta) cid-    Eql -> do-      assertLower' solver v (toValue rhs') cid-      assertUpper' solver v (toValue rhs') cid-  return ()--simplifyAtom :: SolverValue v => GenericSolver v -> LA.Atom Rational -> IO (Var, RelOp, Rational)-simplifyAtom solver (OrdRel lhs op rhs) = do-  let (lhs',rhs') =-        case LA.extract LA.unitVar (lhs ^-^ rhs) of-          (n,e) -> (e, -n)-  case LA.terms lhs' of-    [(1,v)] -> return (v, op, rhs')-    [(-1,v)] -> return (v, flipOp op, -rhs')-    _ -> do-      defs <- readIORef (svDefDB solver)-      let (c,lhs'') = scale lhs' -- lhs' = lhs'' / c = rhs'-          rhs'' = c *^ rhs'-          op''  = if c < 0 then flipOp op else op-      case Map.lookup lhs'' defs of-        Just v -> do-          return (v,op'',rhs'')-        Nothing -> do-          v <- newVar solver-          setRow solver v lhs''-          modifyIORef (svDefDB solver) $ Map.insert lhs'' v-          case LA.asConst lhs'' of-            Just 0 -> do-              modifyIORef (svLB solver) (IntMap.insert v (toValue 0, mempty))-              modifyIORef (svUB solver) (IntMap.insert v (toValue 0, mempty))-            _ -> return ()-          return (v,op'',rhs'')-  where-    scale :: LA.Expr Rational -> (Rational, LA.Expr Rational)-    scale e = (c, c *^ e)-      where-        c = c1 * c2-        c1 = fromIntegral $ foldl' lcm 1 [denominator c | (c, _) <- LA.terms e]-        c2 = signum $ head ([c | (c,x) <- LA.terms e] ++ [1])-             -assertLower :: SolverValue v => GenericSolver v -> Var -> v -> IO ()-assertLower solver x l = assertLower' solver x l Nothing--assertLower' :: SolverValue v => GenericSolver v -> Var -> v -> Maybe ConstrID -> IO ()-assertLower' solver x l cid = do-  let cidSet = IntSet.fromList $ maybeToList cid-  l0 <- getLB solver x-  u0 <- getUB solver x-  case (l0,u0) of -    (Just (l0', _), _) | l <= l0' -> return ()-    (_, Just (u0', cidSet2)) | u0' < l -> do-      writeIORef (svExplanation solver) $ cidSet `IntSet.union` cidSet2-      markBad solver-    _ -> do-      bpSaveLB solver x-      modifyIORef (svLB solver) (IntMap.insert x (l, cidSet))-      b <- isNonBasicVariable solver x-      v <- getValue solver x-      when (b && not (l <= v)) $ update solver x l-      checkNBFeasibility solver--assertUpper :: SolverValue v => GenericSolver v -> Var -> v -> IO ()-assertUpper solver x u = assertUpper' solver x u Nothing --assertUpper' :: SolverValue v => GenericSolver v -> Var -> v -> Maybe ConstrID -> IO ()-assertUpper' solver x u cid = do-  let cidSet = IntSet.fromList $ maybeToList cid-  l0 <- getLB solver x-  u0 <- getUB solver x-  case (l0,u0) of-    (_, Just (u0', _)) | u0' <= u -> return ()-    (Just (l0', cidSet2), _) | u < l0' -> do-      writeIORef (svExplanation solver) $ cidSet `IntSet.union` cidSet2-      markBad solver-    _ -> do-      bpSaveUB solver x-      modifyIORef (svUB solver) (IntMap.insert x (u, cidSet))-      b <- isNonBasicVariable solver x-      v <- getValue solver x-      when (b && not (v <= u)) $ update solver x u-      checkNBFeasibility solver---- FIXME: 式に定数項が含まれる可能性を考えるとこれじゃまずい?-setObj :: SolverValue v => GenericSolver v -> LA.Expr Rational -> IO ()-setObj solver e = setRow solver objVar e--getObj :: SolverValue v => GenericSolver v -> IO (LA.Expr Rational)-getObj solver = getRow solver objVar--setRow :: SolverValue v => GenericSolver v -> Var -> LA.Expr Rational -> IO ()-setRow solver v e = do-  modifyIORef (svTableau solver) $ \t ->-    IntMap.insert v (LA.applySubst t e) t-  modifyIORef (svModel solver) $ \m -> -    IntMap.insert v (LA.evalLinear m (toValue 1) e) m  --setOptDir :: GenericSolver v -> OptDir -> IO ()-setOptDir solver dir = writeIORef (svOptDir solver) dir--getOptDir :: GenericSolver v -> IO OptDir-getOptDir solver = readIORef (svOptDir solver)--{---------------------------------------------------------------------  Status---------------------------------------------------------------------}--nVars :: GenericSolver v -> IO Int-nVars solver = readIORef (svVCnt solver)--isBasicVariable :: GenericSolver v -> Var -> IO Bool-isBasicVariable solver v = do-  t <- readIORef (svTableau solver)-  return $ v `IntMap.member` t--isNonBasicVariable  :: GenericSolver v -> Var -> IO Bool-isNonBasicVariable solver x = liftM not (isBasicVariable solver x)--isFeasible :: SolverValue v => GenericSolver v -> IO Bool-isFeasible solver = do-  xs <- variables solver-  liftM and $ forM xs $ \x -> do-    v <- getValue solver x-    l <- getLB solver x-    u <- getUB solver x-    return (testLB l v && testUB u v)--isOptimal :: SolverValue v => GenericSolver v -> IO Bool-isOptimal solver = do-  obj <- getRow solver objVar-  ret <- selectEnteringVariable solver-  return $! isNothing ret--{---------------------------------------------------------------------  Satisfiability solving---------------------------------------------------------------------}--check :: SolverValue v => GenericSolver v -> IO Bool-check solver = do-  let-    loop :: IO Bool-    loop = do-      m <- selectViolatingBasicVariable solver--      case m of-        Nothing -> return True-        Just xi  -> do-          li <- getLB solver xi-          ui <- getUB solver xi-          isLBViolated <- do-            vi <- getValue solver xi-            return $ not (testLB li vi)-          let q = if isLBViolated-                  then -- select the smallest non-basic variable xj such that-                       -- (aij > 0 and β(xj) < uj) or (aij < 0 and β(xj) > lj)-                       canIncrease solver-                  else -- select the smallest non-basic variable xj such that-                       -- (aij < 0 and β(xj) < uj) or (aij > 0 and β(xj) > lj)-                       canDecrease solver-          xi_def <- getRow solver xi-          r <- liftM (fmap snd) $ findM q (LA.terms xi_def)              -          case r of-            Nothing -> do-              let c = if isLBViolated then li else ui-              core <- liftM (mconcat . map boundExplanation . (c :)) $ forM (LA.terms xi_def) $ \(aij, xj) -> do-                if isLBViolated then do-                  if aij > 0 then do-                    getUB solver xj-                  else do-                    getLB solver xj-                else do-                  if aij > 0 then do-                    getLB solver xj-                  else do-                    getUB solver xj-              writeIORef (svExplanation solver) core-              markBad solver-              return False-            Just xj -> do-              pivotAndUpdate solver xi xj (fromJust $ boundValue $ if isLBViolated then li else ui)-              loop--  ok <- readIORef (svOk solver)-  if not ok-  then return False-  else do-    log solver "check"-    result <- recordTime solver loop-    when result $ checkFeasibility solver-    return result--selectViolatingBasicVariable :: SolverValue v => GenericSolver v -> IO (Maybe Var)-selectViolatingBasicVariable solver = do-  let-    p :: Var -> IO Bool-    p x | x == objVar = return False-    p xi = do-      li <- getLB solver xi-      ui <- getUB solver xi-      vi <- getValue solver xi-      return $ not (testLB li vi) || not (testUB ui vi)-  vs <- basicVariables solver--  ps <- readIORef (svPivotStrategy solver)-  case ps of-    PivotStrategyBlandRule ->-      findM p vs-    PivotStrategyLargestCoefficient -> do-      xs <- filterM p vs-      case xs of-        [] -> return Nothing-        _ -> do-          xs2 <- forM xs $ \xi -> do-              vi <- getValue solver xi-              li <- getLB solver xi-              ui <- getUB solver xi-              if not (testLB li vi)-                then return (xi, fromJust (boundValue li) ^-^ vi)-                else return (xi, vi ^-^ fromJust (boundValue ui))-          return $ Just $ fst $ maximumBy (comparing snd) xs2--{---------------------------------------------------------------------  Optimization---------------------------------------------------------------------}---- | results of optimization-data OptResult = Optimum | Unsat | Unbounded | ObjLimit-  deriving (Show, Eq, Ord)---- | Options for solving.------ The default option can be obtained by 'def'.-data Options-  = Options-  { objLimit :: Maybe Rational-  }-  deriving (Show, Eq, Ord)--instance Default Options where-  def =-    Options-    { objLimit = Nothing-    }--optimize :: Solver -> Options -> IO OptResult-optimize solver opt = do-  ret <- do-    is_fea <- isFeasible solver-    if is_fea then return True else check solver-  if not ret-    then return Unsat -- unsat-    else do-      log solver "optimize"-      result <- recordTime solver loop-      when (result == Optimum) $ checkOptimality solver-      return result-  where-    loop :: IO OptResult-    loop = do-      checkFeasibility solver-      ret <- selectEnteringVariable solver-      case ret of-       Nothing -> return Optimum-       Just (c,xj) -> do-         dir <- getOptDir solver-         r <- if dir==OptMin-              then if c > 0-                then decreaseNB solver xj -- xj を小さくして目的関数を小さくする-                else increaseNB solver xj -- xj を大きくして目的関数を小さくする-              else if c > 0-                then increaseNB solver xj -- xj を大きくして目的関数を大きくする-                else decreaseNB solver xj -- xj を小さくして目的関数を大きくする-         if r-           then loop-           else return Unbounded--selectEnteringVariable :: SolverValue v => GenericSolver v -> IO (Maybe (Rational, Var))-selectEnteringVariable solver = do-  ps <- readIORef (svPivotStrategy solver)-  obj_def <- getRow solver objVar-  case ps of-    PivotStrategyBlandRule ->-      findM canEnter (LA.terms obj_def)-    PivotStrategyLargestCoefficient -> do-      ts <- filterM canEnter (LA.terms obj_def)-      case ts of-        [] -> return Nothing-        _ -> return $ Just $ snd $ maximumBy (comparing fst) [(abs c, (c,xj)) | (c,xj) <- ts]-  where-    canEnter :: (Rational, Var) -> IO Bool-    canEnter (_,xj) | xj == LA.unitVar = return False-    canEnter (c,xj) = do-      dir <- getOptDir solver-      if dir==OptMin-       then canDecrease solver (c,xj)-       else canIncrease solver (c,xj)--canIncrease :: SolverValue v => GenericSolver v -> (Rational,Var) -> IO Bool-canIncrease solver (a,x) =-  case compare a 0 of-    EQ -> return False-    GT -> canIncrease1 solver x-    LT -> canDecrease1 solver x--canDecrease :: SolverValue v => GenericSolver v -> (Rational,Var) -> IO Bool-canDecrease solver (a,x) =-  case compare a 0 of-    EQ -> return False-    GT -> canDecrease1 solver x-    LT -> canIncrease1 solver x--canIncrease1 :: SolverValue v => GenericSolver v -> Var -> IO Bool-canIncrease1 solver x = do-  u <- getUB solver x-  v <- getValue solver x-  case u of-    Nothing -> return True-    Just (uv, _) -> return $! (v < uv)--canDecrease1 :: SolverValue v => GenericSolver v -> Var -> IO Bool-canDecrease1 solver x = do-  l <- getLB solver x-  v <- getValue solver x-  case l of-    Nothing -> return True-    Just (lv, _) -> return $! (lv < v)---- | feasibility を保ちつつ non-basic variable xj の値を大きくする-increaseNB :: Solver -> Var -> IO Bool-increaseNB solver xj = do-  col <- getCol solver xj--  -- Upper bounds of θ-  -- NOTE: xj 自体の上限も考慮するのに注意-  ubs <- liftM concat $ forM ((xj,1) : IntMap.toList col) $ \(xi,aij) -> do-    v1 <- getValue solver xi-    li <- getLB solver xi-    ui <- getUB solver xi-    return [ assert (theta >= zeroV) ((xi,v2), theta)-           | Just v2 <- [boundValue ui | aij > 0] ++ [boundValue li | aij < 0]-           , let theta = (v2 ^-^ v1) ^/ aij ]--  -- β(xj) := β(xj) + θ なので θ を大きく-  case ubs of-    [] -> return False -- unbounded-    _ -> do-      let (xi, v) = fst $ minimumBy (comparing snd) ubs-      pivotAndUpdate solver xi xj v-      return True---- | feasibility を保ちつつ non-basic variable xj の値を小さくする-decreaseNB :: Solver -> Var -> IO Bool-decreaseNB solver xj = do-  col <- getCol solver xj--  -- Lower bounds of θ-  -- NOTE: xj 自体の下限も考慮するのに注意-  lbs <- liftM concat $ forM ((xj,1) : IntMap.toList col) $ \(xi,aij) -> do-    v1 <- getValue solver xi-    li <- getLB solver xi-    ui <- getUB solver xi-    return [ assert (theta <= zeroV) ((xi,v2), theta)-           | Just v2 <- [boundValue li | aij > 0] ++ [boundValue ui | aij < 0]-           , let theta = (v2 ^-^ v1) ^/ aij ]--  -- β(xj) := β(xj) + θ なので θ を小さく-  case lbs of-    [] -> return False -- unbounded-    _ -> do-      let (xi, v) = fst $ maximumBy (comparing snd) lbs-      pivotAndUpdate solver xi xj v-      return True--dualSimplex :: Solver -> Options -> IO OptResult-dualSimplex solver opt = do-  let-    loop :: IO OptResult-    loop = do-      checkOptimality solver--      p <- prune solver opt-      if p-        then return ObjLimit-        else do-          m <- selectViolatingBasicVariable solver-          case m of-            Nothing -> return Optimum-            Just xi  -> do-              xi_def  <- getRow solver xi-              li <- getLB solver xi-              ui <- getUB solver xi-              isLBViolated <- do-                vi <- getValue solver xi-                return $ not (testLB li vi)-              r <- dualRTest solver xi_def isLBViolated-              case r of-                Nothing -> do-                  -- dual unbounded-                  let c = if isLBViolated then li else ui-                  core <- liftM (mconcat . map boundExplanation . (c :)) $ forM (LA.terms xi_def) $ \(aij, xj) -> do-                    if isLBViolated then do-                      if aij > 0 then do-                        getUB solver xj-                      else do-                        getLB solver xj-                    else do-                      if aij > 0 then do-                        getLB solver xj-                      else do-                        getUB solver xj-                  writeIORef (svExplanation solver) core-                  markBad solver-                  return Unsat-                Just xj -> do-                  pivotAndUpdate solver xi xj (fromJust $ boundValue $ if isLBViolated then li else ui)-                  loop--  ok <- readIORef (svOk solver)-  if not ok-  then return Unsat-  else do-    log solver "dual simplex"-    result <- recordTime solver loop-    when (result == Optimum) $ checkFeasibility solver-    return result--dualRTest :: Solver -> LA.Expr Rational -> Bool -> IO (Maybe Var)-dualRTest solver row isLBViolated = do-  -- normalize to the cases of minimization-  obj_def <- do-    def <- getRow solver objVar-    dir <- getOptDir solver-    return $-      case dir of-        OptMin -> def-        OptMax -> negateV def-  -- normalize to the cases of lower bound violation-  let xi_def =-       if isLBViolated-       then row-       else negateV row-  ws <- do-    -- select non-basic variable xj such that-    -- (aij > 0 and β(xj) < uj) or (aij < 0 and β(xj) > lj)-    liftM concat $ forM (LA.terms xi_def) $ \(aij, xj) -> do-      b <- canIncrease solver (aij, xj)-      if b-      then do-        let cj = LA.coeff xj obj_def-        let ratio = cj / aij-        return [(xj, ratio) | ratio >= 0]-      else-        return []-  case ws of-    [] -> return Nothing-    _ -> return $ Just $ fst $ minimumBy (comparing snd) ws--prune :: Solver -> Options -> IO Bool-prune solver opt =-  case objLimit opt of-    Nothing -> return False-    Just lim -> do    -      o <- getObjValue solver-      dir <- getOptDir solver-      case dir of-        OptMin -> return $! (lim <= o)-        OptMax -> return $! (lim >= o)--{---------------------------------------------------------------------  Extract results---------------------------------------------------------------------}--type RawModel v = IntMap v--getRawModel :: GenericSolver v -> IO (RawModel v)-getRawModel solver = do-  xs <- variables solver-  liftM IntMap.fromList $ forM xs $ \x -> do-    val <- getValue solver x-    return (x,val)--getObjValue :: GenericSolver v -> IO v-getObjValue solver = getValue solver objVar  --type Model = IntMap Rational--explain :: GenericSolver v -> IO ConstrIDSet-explain solver = readIORef (svExplanation solver)-  -{---------------------------------------------------------------------  major function---------------------------------------------------------------------}--update :: SolverValue v => GenericSolver v -> Var -> v -> IO ()-update solver xj v = do-  -- log solver $ printf "before update x%d (%s)" xj (show v)-  -- dump solver--  v0 <- getValue solver xj-  let diff = v ^-^ v0--  aj <- getCol solver xj-  modifyIORef (svModel solver) $ \m ->-    let m2 = IntMap.map (\aij -> aij *^ diff) aj-    in IntMap.insert xj v $ IntMap.unionWith (^+^) m2 m--  -- log solver $ printf "after update x%d (%s)" xj (show v)-  -- dump solver--pivot :: SolverValue v => GenericSolver v -> Var -> Var -> IO ()-pivot solver xi xj = do-  modifyIORef' (svNPivot solver) (+1)-  modifyIORef' (svTableau solver) $ \defs ->-    case LA.solveFor (LA.var xi .==. (defs IntMap.! xi)) xj of-      Just (Eql, xj_def) ->-        IntMap.insert xj xj_def . IntMap.map (LA.applySubst1 xj xj_def) . IntMap.delete xi $ defs-      _ -> error "pivot: should not happen"--pivotAndUpdate :: SolverValue v => GenericSolver v -> Var -> Var -> v -> IO ()-pivotAndUpdate solver xi xj v | xi == xj = update solver xi v -- xi = xj is non-basic variable-pivotAndUpdate solver xi xj v = do-  -- xi is basic variable-  -- xj is non-basic varaible--  -- log solver $ printf "before pivotAndUpdate x%d x%d (%s)" xi xj (show v)-  -- dump solver--  m <- readIORef (svModel solver)--  aj <- getCol solver xj-  let aij = aj IntMap.! xi-  let theta = (v ^-^ (m IntMap.! xi)) ^/ aij--  let m' = IntMap.fromList $-           [(xi, v), (xj, (m IntMap.! xj) ^+^ theta)] ++-           [(xk, (m IntMap.! xk) ^+^ (akj *^ theta)) | (xk, akj) <- IntMap.toList aj, xk /= xi]-  writeIORef (svModel solver) (IntMap.union m' m) -- note that 'IntMap.union' is left biased.--  pivot solver xi xj--  -- log solver $ printf "after pivotAndUpdate x%d x%d (%s)" xi xj (show v)-  -- dump solver--getLB :: GenericSolver v -> Var -> IO (Bound v)-getLB solver x = do-  lb <- readIORef (svLB solver)-  return $ IntMap.lookup x lb--getUB :: GenericSolver v -> Var -> IO (Bound v)-getUB solver x = do-  ub <- readIORef (svUB solver)-  return $ IntMap.lookup x ub--getTableau :: GenericSolver v -> IO (IntMap (LA.Expr Rational))-getTableau solver = do-  t <- readIORef (svTableau solver)-  return $ IntMap.delete objVar t--getValue :: GenericSolver v -> Var -> IO v-getValue solver x = do-  m <- readIORef (svModel solver)-  return $ m IntMap.! x--getRow :: GenericSolver v -> Var -> IO (LA.Expr Rational)-getRow solver x = do-  -- x should be basic variable or 'objVar'-  t <- readIORef (svTableau solver)-  return $! (t IntMap.! x)---- aijが非ゼロの列も全部探しているのは効率が悪い-getCol :: SolverValue v => GenericSolver v -> Var -> IO (IntMap Rational)-getCol solver xj = do-  t <- readIORef (svTableau solver)-  return $ IntMap.mapMaybe (LA.lookupCoeff xj) t--getCoeff :: GenericSolver v -> Var -> Var -> IO Rational-getCoeff solver xi xj = do-  xi_def <- getRow solver xi-  return $! LA.coeff xj xi_def--markBad :: GenericSolver v -> IO ()-markBad solver = writeIORef (svOk solver) False--{---------------------------------------------------------------------  utility---------------------------------------------------------------------}--findM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a)-findM _ [] = return Nothing-findM p (x:xs) = do-  r <- p x-  if r-  then return (Just x)-  else findM p xs--testLB :: SolverValue v => Bound v -> v -> Bool-testLB Nothing _  = True-testLB (Just (l,_)) x = l <= x--testUB :: SolverValue v => Bound v -> v -> Bool-testUB Nothing _  = True-testUB (Just (u,_)) x = x <= u--variables :: GenericSolver v -> IO [Var]-variables solver = do-  vcnt <- nVars solver-  return [0..vcnt-1]--basicVariables :: GenericSolver v -> IO [Var]-basicVariables solver = do-  t <- readIORef (svTableau solver)-  return (IntMap.keys t)--recordTime :: SolverValue v => GenericSolver v -> IO a -> IO a-recordTime solver act = do-  dumpSize solver-  writeIORef (svNPivot solver) 0--  startCPU <- getCPUTime-  startWC  <- getCurrentTime--  result <- act--  endCPU <- getCPUTime-  endWC  <- getCurrentTime--  (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 "#pivot = %d") =<< readIORef (svNPivot solver)-  return result--showDelta :: Bool -> Delta Rational -> String-showDelta asRatio v = -  case v of-    (Delta r k) -> -      f r ++-        case compare k 0 of-          EQ -> ""-          GT -> " + " ++ f k ++ " delta"-          LT -> " - " ++ f (abs k) ++ " delta"-  where-    f = showRational asRatio--{---------------------------------------------------------------------  Logging---------------------------------------------------------------------}---- | set callback function for receiving messages.-setLogger :: GenericSolver v -> (String -> IO ()) -> IO ()-setLogger solver logger = do-  writeIORef (svLogger solver) (Just logger)--clearLogger :: GenericSolver v -> IO ()-clearLogger solver = writeIORef (svLogger solver) Nothing--log :: GenericSolver v -> String -> IO ()-log solver msg = logIO solver (return msg)--logIO :: GenericSolver v -> IO String -> IO ()-logIO solver action = do-  m <- readIORef (svLogger solver)-  case m of-    Nothing -> return ()-    Just logger -> action >>= logger--{---------------------------------------------------------------------  debug and tests---------------------------------------------------------------------}--test4 :: IO ()-test4 = do-  solver <- newSolver-  setLogger solver putStrLn-  x0 <- newVar solver-  x1 <- newVar solver--  writeIORef (svTableau solver) (IntMap.fromList [(x1, LA.var x0)])-  writeIORef (svLB solver) $ fmap (\v -> (v, mempty)) $ IntMap.fromList [(x0, 0), (x1, 0)]-  writeIORef (svUB solver) $ fmap (\v -> (v, mempty)) $ IntMap.fromList [(x0, 2), (x1, 3)]-  setObj solver (LA.fromTerms [(-1, x0)])--  ret <- optimize solver def-  print ret-  dump solver--test5 :: IO ()-test5 = do-  solver <- newSolver-  setLogger solver putStrLn-  x0 <- newVar solver-  x1 <- newVar solver--  writeIORef (svTableau solver) (IntMap.fromList [(x1, LA.var x0)])-  writeIORef (svLB solver) $ fmap (\v -> (v, mempty)) $ IntMap.fromList [(x0, 0), (x1, 0)]-  writeIORef (svUB solver) $ fmap (\v -> (v, mempty)) $ IntMap.fromList [(x0, 2), (x1, 0)]-  setObj solver (LA.fromTerms [(-1, x0)])--  checkFeasibility solver--  ret <- optimize solver def-  print ret-  dump solver--test6 :: IO ()-test6 = do-  solver <- newSolver-  setLogger solver putStrLn-  x0 <- newVar solver--  assertAtom solver (LA.constant 1 .<. LA.var x0)-  assertAtom solver (LA.constant 2 .>. LA.var x0)--  ret <- check solver-  print ret-  dump solver--  m <- getModel solver-  print m--dumpSize :: SolverValue v => GenericSolver v -> IO ()-dumpSize solver = do-  t <- readIORef (svTableau solver)-  let nrows = IntMap.size t - 1 -- -1 is objVar-  xs <- variables solver-  let ncols = length xs - nrows-  let nnz = sum [IntMap.size $ LA.coeffMap xi_def | (xi,xi_def) <- IntMap.toList t, xi /= objVar]-  log solver $ printf "%d rows, %d columns, %d non-zeros" nrows ncols nnz--dump :: SolverValue v => GenericSolver v -> IO ()-dump solver = do-  log solver "============="--  log solver "Tableau:"-  t <- readIORef (svTableau solver)-  log solver $ printf "obj = %s" (show (t IntMap.! objVar))-  forM_ (IntMap.toList t) $ \(xi, e) -> do-    when (xi /= objVar) $ log solver $ printf "x%d = %s" xi (show e)--  log solver ""--  log solver "Assignments and Bounds:"-  objVal <- getValue solver objVar-  log solver $ printf "beta(obj) = %s" (showValue True objVal)-  xs <- variables solver -  forM_ xs $ \x -> do-    l <- getLB solver x-    u <- getUB solver x-    v <- getValue solver x-    let f Nothing = "Nothing"-        f (Just (x,_)) = showValue True x-    log solver $ printf "beta(x%d) = %s; %s <= x%d <= %s" x (showValue True v) (f l) x (f u)--  log solver ""-  log solver "Status:"-  is_fea <- isFeasible solver-  is_opt <- isOptimal solver-  log solver $ printf "Feasible: %s" (show is_fea)-  log solver $ printf "Optimal: %s" (show is_opt)--  log solver "============="--checkFeasibility :: SolverValue v => GenericSolver v -> IO ()-checkFeasibility _ | True = return ()-checkFeasibility solver = do-  xs <- variables solver-  forM_ xs $ \x -> do-    v <- getValue solver x-    l <- getLB solver x-    u <- getUB solver x-    let f Nothing = "Nothing"-        f (Just (x,_)) = showValue True x-    unless (testLB l v) $-      error (printf "(%s) <= x%d is violated; x%d = (%s)" (f l) x x (showValue True v))-    unless (testUB u v) $-      error (printf "x%d <= (%s) is violated; x%d = (%s)" x (f u) x (showValue True v))-    return ()--checkNBFeasibility :: SolverValue v => GenericSolver v -> IO ()-checkNBFeasibility _ | True = return ()-checkNBFeasibility solver = do-  xs <- variables solver-  forM_ xs $ \x -> do-    b <- isNonBasicVariable solver x-    when b $ do-      v <- getValue solver x-      l <- getLB solver x-      u <- getUB solver x-      let f Nothing = "Nothing"-          f (Just (x,_)) = showValue True x-      unless (testLB l v) $-        error (printf "checkNBFeasibility: (%s) <= x%d is violated; x%d = (%s)" (f l) x x (showValue True v))-      unless (testUB u v) $-        error (printf "checkNBFeasibility: x%d <= (%s) is violated; x%d = (%s)" x (f u) x (showValue True v))--checkOptimality :: Solver -> IO ()-checkOptimality _ | True = return ()-checkOptimality solver = do-  ret <- selectEnteringVariable solver-  case ret of-    Nothing -> return () -- optimal-    Just (_,x) -> error (printf "checkOptimality: not optimal (x%d can be changed)" x)
src/ToySolver/Arith/VirtualSubstitution.hs view
@@ -23,6 +23,8 @@ module ToySolver.Arith.VirtualSubstitution   ( QFFormula   , evalQFFormula+  , Model+  , Eval (..)    -- * Projection   , project@@ -50,16 +52,15 @@ import ToySolver.Data.BoolExpr (BoolExpr (..)) import qualified ToySolver.Data.BoolExpr as BoolExpr import qualified ToySolver.Data.LA as LA-import ToySolver.Data.Var+import ToySolver.Data.IntVar  -- | Quantifier-free formula of LRA type QFFormula = BoolExpr (LA.Atom Rational) +{-# DEPRECATED evalQFFormula "Use Eval class instead" #-} -- | @'evalQFFormula' M φ@ returns whether @M ⊧_LRA φ@ or not. evalQFFormula :: Model Rational -> QFFormula -> Bool-evalQFFormula m = BoolExpr.fold f-  where-    f (OrdRel lhs op rhs) = evalOp op (LA.evalExpr m lhs) (LA.evalExpr m rhs)+evalQFFormula = eval  {-| @'project' x φ@ returns @(ψ, lift)@ such that: @@ -74,7 +75,7 @@     formula' = orB' [phi | (phi,_) <- xs]     mt m = head $ do       (phi, mt') <- xs-      guard $ evalQFFormula m phi+      guard $ eval m phi       return $ mt' m     orB' = orB . concatMap f       where@@ -104,7 +105,7 @@ * if @M ⊧_LRA ψ_i@ then @lift_i M ⊧_LRA φ@. -} projectCases :: Var -> QFFormula -> [(QFFormula, Model Rational -> Model Rational)]-projectCases v phi = [(psi, \m -> IM.insert v (LA.evalExpr m t) m) | (psi, t) <- projectCases' v phi]+projectCases v phi = [(psi, \m -> IM.insert v (LA.eval m t) m) | (psi, t) <- projectCases' v phi]  {-| @'projectCases' x φ@ returns @[(ψ_1, lift_1), …, (ψ_m, lift_m)]@ such that: @@ -185,8 +186,9 @@ solveQFFormula :: VarSet -> QFFormula -> Maybe (Model Rational) solveQFFormula vs formula = listToMaybe $ do   (formula2, mt) <- projectCasesN vs formula-  let m = IM.empty-  guard $ evalQFFormula m formula2+  let m :: Model Rational+      m = IM.empty+  guard $ eval m formula2   return $ mt m  -- | @'solve' {x1,…,xn} φ@ returns @Just M@ such that @M ⊧_LRA φ@ when
+ src/ToySolver/BitVector.hs view
@@ -0,0 +1,9 @@+module ToySolver.BitVector+  (+    module ToySolver.BitVector.Base+  , module ToySolver.BitVector.Solver+  ) where++import Prelude hiding (repeat)+import ToySolver.BitVector.Base+import ToySolver.BitVector.Solver
+ src/ToySolver/BitVector/Base.hs view
@@ -0,0 +1,573 @@+{-# OPTIONS_GHC -Wall -fno-warn-orphans #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.BitVector.Base+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+--+-----------------------------------------------------------------------------+module ToySolver.BitVector.Base+  (+  -- * BitVector values+    BV+  , bv2nat+  , nat2bv+  , fromAscBits+  , fromDescBits+  , toAscBits+  , toDescBits+  , IsBV (..)++  -- * BitVector language+  , Var (..)+  , Expr (..)+  , Op1 (..)+  , Op2 (..)+  , repeat+  , zeroExtend+  , signExtend+  , Atom (..)+  , BVComparison (..)+  , module ToySolver.Data.OrdRel+  , Model+  , evalExpr+  , evalAtom+  ) where++import Prelude hiding (repeat)+import Data.Bits+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Monoid+import Data.Ord+import qualified Data.Vector as V+import qualified Data.Vector.Generic as VG+import qualified Data.Vector.Unboxed as VU+import ToySolver.Data.Boolean+import ToySolver.Data.OrdRel++class Monoid a => IsBV a where+  width :: a -> Int+  extract :: Int -> Int -> a -> a+  fromBV :: BV -> a++  bvnot  :: a -> a+  bvand  :: a -> a -> a+  bvor   :: a -> a -> a+  bvxor  :: a -> a -> a+  bvnand :: a -> a -> a+  bvnor  :: a -> a -> a+  bvxnor :: a -> a -> a++  bvneg  :: a -> a+  bvadd  :: a -> a -> a+  bvsub  :: a -> a -> a+  bvmul  :: a -> a -> a+  bvudiv :: a -> a -> a+  bvurem :: a -> a -> a+  bvsdiv :: a -> a -> a+  bvsrem :: a -> a -> a+  bvsmod :: a -> a -> a+  bvshl  :: a -> a -> a+  bvlshr :: a -> a -> a+  bvashr :: a -> a -> a+  bvcomp :: a -> a -> a++  bvnand s t = bvnot (bvand s t)+  bvnor s t  = bvnot (bvor s t)+  bvxnor s t = bvnot (bvxor s t)++  bvsub s t = bvadd s (bvneg t)++repeat :: Monoid m => Int -> m -> m+repeat i x = mconcat (replicate i x)++zeroExtend :: IsBV a => Int -> a -> a+zeroExtend i s = fromAscBits (replicate i False) <> s++signExtend :: IsBV a => Int -> a -> a+signExtend i s+  | w == 0 = fromAscBits (replicate i False)+  | otherwise = repeat i (extract (w-1) (w-1) s) <> s+  where+    w = width s++class (IsBV a, IsEqRel a (ComparisonResult a), Complement (ComparisonResult a)) => BVComparison a where+  type ComparisonResult a++  bvule, bvult, bvuge, bvugt, bvsle, bvslt, bvsge, bvsgt :: a -> a -> ComparisonResult a++  bvule a b = notB (bvult b a)+  bvult a b = notB (bvule b a)+  bvuge a b = bvule b a+  bvugt a b = bvult b a++  bvsle a b = notB (bvslt b a)+  bvslt a b = notB (bvsle b a)+  bvsge a b = bvsle b a+  bvsgt a b = bvslt b a++  {-# MINIMAL (bvule | bvult), (bvsle | bvslt) #-}++-- ------------------------------------------------------------------------+    +newtype BV = BV (VU.Vector Bool)+  deriving (Eq)++instance Ord BV where+  compare (BV bs1) (BV bs2) =+    (comparing VG.length <> comparing VG.reverse) bs1 bs2++instance Monoid BV where+  mempty = BV VG.empty+  mappend (BV hi) (BV lo) = BV (lo <> hi) ++instance Show BV where+  show bv = "0b" ++ [if b then '1' else '0' | b <- toDescBits bv]++instance Bits BV where+  (.&.) = bvand+  (.|.) = bvor+  xor = bvxor+  complement = bvnot++  shiftL x i+    | i < w = extract (w-1-i) 0 x <> nat2bv i 0+    | otherwise = nat2bv w 0+    where+      w = width x+  shiftR x i+    | i < w = nat2bv i 0 <> extract (w-1) i x+    | otherwise = nat2bv w 0+    where+      w = width x+  rotateL x i+    | w == 0 = x+    | otherwise = extract (w-1-j) 0 x <> extract (w-1) (w-j) x+    where+      w = width x+      j = i `mod` w+  rotateR x i+    | w == 0 = x+    | otherwise = extract (j-1) 0 x <> extract (w-1) j x+    where+      w = width x+      j = i `mod` w++  zeroBits = error "zeroBits is not implemented"++  bit = error "bit is not implemented"++  setBit x@(BV bs) i +    | 0 <= i && i < w = BV $ bs VG.// [(i,True)]+    | otherwise = x+    where+      w = width x+  clearBit x@(BV bs) i+    | 0 <= i && i < w = BV $ bs VG.// [(i,False)]+    | otherwise = x+    where+      w = width x+  complementBit x@(BV bs) i+    | 0 <= i && i < w = BV $ bs VG.// [(i, not (testBit x i))]+    | otherwise = x+    where+      w = width x+  testBit x@(BV bs) i+    | 0 <= i && i < w = bs VG.! i+    | otherwise = False+    where+      w = width x++  popCount x = sum [1 | b <- toAscBits x, b]++  bitSizeMaybe _ = Nothing+  bitSize _ = error "bitSize is not implemented"+  isSigned _ = False++instance IsBV BV where+  width (BV bs) = VG.length bs+  extract i j (BV bs) = BV $ VG.slice j (i - j + 1) bs+  fromBV = id++  bvnot (BV bs) = BV $ VG.map not bs++  bvand (BV bs1) (BV bs2)+    | VG.length bs1 /= VG.length bs2 = error "width mismatch"+    | otherwise = BV $ VG.zipWith (&&) bs1 bs2+  bvor (BV bs1) (BV bs2)+    | VG.length bs1 /= VG.length bs2 = error "width mismatch"+    | otherwise = BV $ VG.zipWith (||) bs1 bs2+  bvxor (BV bs1) (BV bs2) +    | VG.length bs1 /= VG.length bs2 = error "width mismatch"+    | otherwise = BV $ VG.zipWith (/=) bs1 bs2++  bvneg x = nat2bv (width x) $ 2 ^ width x - bv2nat x++  bvadd x y+    | width x /= width y = error "invalid width"+    | otherwise = nat2bv (width x) (bv2nat x + bv2nat y)++  bvmul x y+    | width x /= width y = error "invalid width"+    | otherwise = nat2bv (width x) (bv2nat x * bv2nat y)++  bvudiv x y+    | width x /= width y = error "invalid width"+    | y' == 0 = error "division by zero"+    | otherwise = nat2bv (width x) (bv2nat x `div` y')+    where+      y' :: Integer+      y' = bv2nat y++  bvurem x y+    | width x /= width y = error "invalid width"+    | y' == 0 = error "division by zero"+    | otherwise = nat2bv (width x) (bv2nat x `mod` y')+    where+      y' :: Integer+      y' = bv2nat y++  bvsdiv x y+    | width x < 1 || width y < 1 || width x /= width y = error "invalid width"+    | not msb_x && not msb_y = bvudiv x y+    | msb_x && not msb_y = bvneg $ bvudiv (bvneg x) y+    | not msb_x && msb_y = bvneg $ bvudiv x (bvneg y)+    | otherwise = bvudiv (bvneg x) (bvneg y)+    where+      msb_x = testBit x (width x - 1)+      msb_y = testBit y (width y - 1)++  bvsrem x y+    | width x < 1 || width y < 1 || width x /= width y = error "invalid width"+    | not msb_x && not msb_y = bvurem x y+    | msb_x && not msb_y = bvneg $ bvurem (bvneg x) y+    | not msb_x && msb_y = bvurem x (bvneg y)+    | otherwise = bvneg $ bvurem (bvneg x) (bvneg y)+    where+      msb_x = testBit x (width x - 1)+      msb_y = testBit y (width y - 1)++  bvsmod x y+    | width x < 1 || width y < 1 || width x /= width y = error "invalid width"+    | bv2nat u == (0::Integer) = u+    | not msb_x && not msb_y = u+    | msb_x && not msb_y = bvadd (bvneg u) y+    | not msb_x && msb_y = bvadd u y+    | otherwise = bvneg u+    where+      msb_x = testBit x (width x - 1)+      msb_y = testBit y (width y - 1)+      abs_x = if msb_x then bvneg x else x+      abs_y = if msb_y then bvneg y else y+      u = bvurem abs_x abs_y++  bvshl  x y+    | width x /= width y = error "invalid width"+    | otherwise = nat2bv (width x) (bv2nat x `shiftL` bv2nat y)++  bvlshr x y+    | width x /= width y = error "invalid width"+    | otherwise = nat2bv (width x) (bv2nat x `shiftR` bv2nat y)++  bvashr x y+    | width x /= width y = error "invalid width"+    | not msb_x = bvlshr x y+    | otherwise = bvneg $ bvlshr (bvneg x) y+    where+      msb_x = testBit x (width x - 1)++  bvcomp x y+    | width x /= width y = error "invalid width"+    | otherwise = nat2bv 1 (if x==y then 1 else 0)++instance IsEqRel BV Bool where+  (.==.) = (==)+  (./=.) = (/=)++instance BVComparison BV where+  type ComparisonResult BV = Bool++  bvule = (<=)++  bvsle bs1 bs2+    | width bs1 /= width bs2 = error ("length mismatch: " ++ show (width bs1) ++ " and " ++ show (width bs2))+    | w == 0 = true+    | otherwise = bs1_msb && not bs2_msb || (bs1_msb == bs2_msb) && bs1 <= bs2+    where+      w = width bs1+      bs1_msb = testBit bs1 (w-1)+      bs2_msb = testBit bs2 (w-1)++bv2nat :: Integral a => BV -> a+bv2nat (BV bv) = VG.ifoldl' (\r i x -> if x then r+2^i else r) 0 bv++nat2bv :: IsBV a => Int -> Integer -> a+nat2bv m x = fromBV $ BV $ VG.generate m (testBit x)++fromAscBits :: IsBV a => [Bool] -> a+fromAscBits = fromBV . BV . VG.fromList++fromDescBits :: IsBV a => [Bool] -> a+fromDescBits = fromBV . fromAscBits . reverse++toAscBits :: BV -> [Bool]+toAscBits (BV bs) = VG.toList bs++toDescBits :: BV -> [Bool]+toDescBits = reverse . toAscBits++-- ------------------------------------------------------------------------++data Var+  = Var+  { varWidth :: {-# UNPACK #-} !Int+  , varId :: {-# UNPACK #-} !Int+  }+  deriving (Eq, Ord, Show)++data Expr+  = EConst BV+  | EVar Var+  | EOp1 Op1 Expr+  | EOp2 Op2 Expr Expr+  deriving (Eq, Ord, Show)++data Op1+  = OpExtract !Int !Int+  | OpNot+  | OpNeg+  deriving (Eq, Ord, Show)++data Op2+  = OpConcat+  | OpAnd+  | OpOr+  | OpXOr+  | OpComp+  | OpAdd+  | OpMul+  | OpUDiv+  | OpURem+  | OpSDiv+  | OpSRem+  | OpSMod+  | OpShl+  | OpLShr+  | OpAShr+  deriving (Eq, Ord, Enum, Bounded, Show)++instance IsBV Expr where+  width (EConst x) = width x+  width (EVar v) = varWidth v+  width (EOp1 op arg) =+    case op of+      OpExtract i j -> i - j + 1+      _ -> width arg+  width (EOp2 op arg1 arg2) =+    case op of+      OpConcat -> width arg1 + width arg2+      OpComp -> 1+      _ -> width arg1++  extract i j = EOp1 (OpExtract i j)++  fromBV = EConst++  bvnot = EOp1 OpNot+  bvand = EOp2 OpAnd+  bvor  = EOp2 OpOr+  bvxor = EOp2 OpXOr++  bvneg  = EOp1 OpNeg+  bvadd  = EOp2 OpAdd+  bvmul  = EOp2 OpMul+  bvudiv = EOp2 OpUDiv+  bvurem = EOp2 OpURem+  bvsdiv = EOp2 OpSDiv+  bvsrem = EOp2 OpSRem+  bvsmod = EOp2 OpSMod+  bvshl  = EOp2 OpShl+  bvlshr = EOp2 OpLShr+  bvashr = EOp2 OpAShr+  bvcomp = EOp2 OpComp++instance Monoid Expr where+  mempty = EConst mempty+  mappend = EOp2 OpConcat++instance Bits Expr where+  (.&.) = bvand+  (.|.) = bvor+  xor = bvxor+  complement = bvnot+  shiftL x i+    | i < w = extract (w-1-i) 0 x <> nat2bv i 0+    | otherwise = nat2bv w 0+    where+      w = width x+  shiftR x i+    | i < w = nat2bv i 0 <> extract (w-1) i x+    | otherwise = nat2bv w 0+    where+      w = width x+  rotateL x i+    | w == 0 = x+    | otherwise = extract (w-1-j) 0 x <> extract (w-1) (w-j) x+    where+      w = width x+      j = i `mod` w+  rotateR x i+    | w == 0 = x+    | otherwise = extract (j-1) 0 x <> extract (w-1) j x+    where+      w = width x+      j = i `mod` w++  zeroBits = error "zeroBits is not implemented"++  bit = error "bit is not implemented"++  setBit x i+    | 0 <= i && i < w = extract (w-1) (i+1) x <> fromDescBits [True] <> extract (i-1) 0 x+    | otherwise = x+    where+      w = width x++  clearBit x i+    | 0 <= i && i < w = extract (w-1) (i+1) x <> fromDescBits [False] <> extract (i-1) 0 x+    | otherwise = x+    where+      w = width x++  complementBit x i+    | 0 <= i && i < w = extract (w-1) (i+1) x <> bvnot (extract i i x) <> extract (i-1) 0 x+    | otherwise = x+    where+      w = width x++  testBit = error "testBit is not implemented"++  popCount = error "popCount is not implemented"++  bitSizeMaybe _ = Nothing+  bitSize _ = error "bitSize is not implemented"+  isSigned _ = False++data Atom = Rel (OrdRel Expr) Bool+  deriving (Eq, Ord, Show)++instance Complement Atom where+  notB (Rel rel signed) = Rel (notB rel) signed++instance IsEqRel Expr Atom where+  a .==. b = Rel (a .==. b) False+  a ./=. b = Rel (a ./=. b) False++instance BVComparison Expr where+  type ComparisonResult Expr = Atom++  bvule s t = Rel (s .<=. t) False+  bvult s t = Rel (s .<.  t) False+  bvuge s t = Rel (s .>=. t) False+  bvugt s t = Rel (s .>.  t) False+  bvsle s t = Rel (s .<=. t) True+  bvslt s t = Rel (s .<.  t) True+  bvsge s t = Rel (s .>=. t) True+  bvsgt s t = Rel (s .>.  t) True++-- ------------------------------------------------------------------------++type Model = (V.Vector BV, Map BV BV, Map BV BV)++evalExpr :: Model -> Expr -> BV+evalExpr (env, divTable, remTable) = f+  where+    f (EConst bv) = bv+    f (EVar v) = env VG.! varId v+    f (EOp1 op x) = evalOp1 op (f x)+    f (EOp2 op x y) = evalOp2 op (f x) (f y)++    evalOp1 (OpExtract i j) = extract i j+    evalOp1 OpNot = bvnot+    evalOp1 OpNeg = bvneg++    evalOp2 OpConcat a b = a <> b+    evalOp2 OpAnd x y = bvand x y+    evalOp2 OpOr x y = bvor x y+    evalOp2 OpXOr x y = bvxor x y+    evalOp2 OpAdd x y = bvadd x y+    evalOp2 OpMul x y = bvmul x y+    evalOp2 OpUDiv x y+      | y' /= 0 = bvudiv x y+      | otherwise =+          case Map.lookup x divTable of+            Just d -> d+            Nothing -> nat2bv (width x) 0+      where+        y' :: Integer+        y' = bv2nat y+    evalOp2 OpURem x y+      | y' /= 0 = bvurem x y+      | otherwise =+          case Map.lookup x remTable of+            Just r -> r+            Nothing -> nat2bv (width x) 0+      where+        y' :: Integer+        y' = bv2nat y+    evalOp2 OpSDiv x y+      | width x < 1 || width y < 1 || width x /= width y = error "invalid width"+      | not msb_x && not msb_y = evalOp2 OpUDiv x y+      | msb_x && not msb_y = bvneg $ evalOp2 OpUDiv (bvneg x) y+      | not msb_x && msb_y = bvneg $ evalOp2 OpUDiv x (bvneg y)+      | otherwise = evalOp2 OpUDiv (bvneg x) (bvneg y)+      where+        msb_x = testBit x (width x - 1)+        msb_y = testBit y (width y - 1)+    evalOp2 OpSRem x y+      | width x < 1 || width y < 1 || width x /= width y = error "invalid width"+      | not msb_x && not msb_y = evalOp2 OpURem x y+      | msb_x && not msb_y = bvneg $ evalOp2 OpURem (bvneg x) y+      | not msb_x && msb_y = evalOp2 OpURem x (bvneg y)+      | otherwise = bvneg $ evalOp2 OpURem (bvneg x) (bvneg y)+      where+        msb_x = testBit x (width x - 1)+        msb_y = testBit y (width y - 1)+    evalOp2 OpSMod x y+      | width x < 1 || width y < 1 || width x /= width y = error "invalid width"+      | bv2nat u == (0::Integer) = u+      | not msb_x && not msb_y = u+      | msb_x && not msb_y = bvadd (bvneg u) y+      | not msb_x && msb_y = bvadd u y+      | otherwise = bvneg u+      where+        msb_x = testBit x (width x - 1)+        msb_y = testBit y (width y - 1)+        abs_x = if msb_x then bvneg x else x+        abs_y = if msb_y then bvneg y else y+        u = evalOp2 OpURem abs_x abs_y+    evalOp2 OpShl x y = bvshl x y+    evalOp2 OpLShr x y = bvlshr x y+    evalOp2 OpAShr x y = bvashr x y+    evalOp2 OpComp x y = nat2bv 1 (if x==y then 1 else 0)++evalAtom :: Model -> Atom -> Bool+evalAtom m (Rel (OrdRel lhs op rhs) False) = evalOp op (evalExpr m lhs) (evalExpr m rhs)+evalAtom m (Rel (OrdRel lhs op rhs) True) =+  case op of+    Lt -> bvslt lhs' rhs'+    Gt -> bvslt rhs' lhs'+    Le -> bvsle lhs' rhs'+    Ge -> bvsle rhs' lhs'+    Eql -> lhs' == rhs'+    NEq -> lhs' /= rhs'+  where+    lhs' = evalExpr m lhs+    rhs' = evalExpr m rhs
+ src/ToySolver/BitVector/Solver.hs view
@@ -0,0 +1,524 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.BitVector.Solver+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+--+-----------------------------------------------------------------------------+module ToySolver.BitVector.Solver+  (    +  -- * BitVector solver+    Solver+  , newSolver+  , newVar+  , newVar'+  , assertAtom+  , check+  , getModel+  , explain+  , pushBacktrackPoint+  , popBacktrackPoint+  ) where++import Prelude hiding (repeat)+import Control.Applicative hiding (Const (..))+import Control.Monad+import qualified Data.Foldable as F+import Data.IntMap (IntMap)+import qualified Data.IntMap as IntMap+import Data.IntSet (IntSet)+import qualified Data.IntSet as IntSet+import Data.IORef+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Maybe+import Data.Monoid+import qualified Data.Vector.Generic as VG+import qualified Data.Vector.Unboxed as VU+import Data.Sequence (Seq)+import qualified Data.Sequence as Seq+import ToySolver.Data.BoolExpr+import ToySolver.Data.Boolean+import ToySolver.Data.OrdRel+import qualified ToySolver.Internal.Data.SeqQueue as SQ+import qualified ToySolver.Internal.Data.Vec as Vec+import qualified ToySolver.SAT as SAT+import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin++import ToySolver.BitVector.Base++-- ------------------------------------------------------------------------++data Solver+  = Solver+  { svVars :: Vec.Vec (VU.Vector SAT.Lit)+  , svSATSolver :: SAT.Solver+  , svTseitin :: Tseitin.Encoder IO+  , svEncTable :: IORef (Map Expr (VU.Vector SAT.Lit))+  , svDivRemTable :: IORef [(VU.Vector SAT.Lit, VU.Vector SAT.Lit, VU.Vector SAT.Lit, VU.Vector SAT.Lit)]+  , svAtomTable :: IORef (Map NormalizedAtom SAT.Lit)+  , svContexts :: Vec.Vec (IntMap (Maybe Int))+  }++newSolver :: IO Solver+newSolver = do+  vars <- Vec.new+  sat <- SAT.newSolver+  tseitin <- Tseitin.newEncoder sat+  table <- newIORef Map.empty+  divRemTable <- newIORef []+  atomTable <- newIORef Map.empty+  contexts <- Vec.new+  Vec.push contexts IntMap.empty+  return $+    Solver+    { svVars = vars+    , svSATSolver = sat+    , svTseitin = tseitin+    , svEncTable = table+    , svDivRemTable = divRemTable+    , svAtomTable = atomTable+    , svContexts = contexts+    }++newVar :: Solver -> Int -> IO Expr+newVar solver w = EVar <$> newVar' solver w++newVar' :: Solver -> Int -> IO Var+newVar' solver w = do+  bs <- VG.fromList <$> SAT.newVars (svSATSolver solver) w+  v <- Vec.getSize $ svVars solver+  Vec.push (svVars solver) bs+  return $ Var{ varWidth = w, varId = v }++data NormalizedRel = NRSLt | NRULt | NREql+  deriving (Eq, Ord, Enum, Bounded, Show)  ++data NormalizedAtom = NormalizedAtom NormalizedRel Expr Expr+  deriving (Eq, Ord, Show)++normalizeAtom :: Atom -> (NormalizedAtom, Bool)+normalizeAtom (Rel (OrdRel lhs op rhs) True) =+  case op of+    Lt -> (NormalizedAtom NRSLt lhs rhs, True)+    Gt -> (NormalizedAtom NRSLt rhs lhs, True)+    Le -> (NormalizedAtom NRSLt rhs lhs, False)+    Ge -> (NormalizedAtom NRSLt lhs rhs, False)+    Eql -> (NormalizedAtom NREql lhs rhs, True)+    NEq -> (NormalizedAtom NREql lhs rhs, False)+normalizeAtom (Rel (OrdRel lhs op rhs) False) =+  case op of+    Lt -> (NormalizedAtom NRULt lhs rhs, True)+    Gt -> (NormalizedAtom NRULt rhs lhs, True)+    Le -> (NormalizedAtom NRULt rhs lhs, False)+    Ge -> (NormalizedAtom NRULt lhs rhs, False)+    Eql -> (NormalizedAtom NREql lhs rhs, True)+    NEq -> (NormalizedAtom NREql lhs rhs, False)++assertAtom :: Solver -> Atom -> Maybe Int -> IO ()+assertAtom solver atom label = do+  let (atom'@(NormalizedAtom op lhs rhs), polarity) = normalizeAtom atom+  table <- readIORef (svAtomTable solver)+  l <- (if polarity then id else negate) <$>+    case Map.lookup atom' table of+      Just lit -> return lit+      Nothing -> do+        s <- encodeExpr solver lhs+        t <- encodeExpr solver rhs+        l <- Tseitin.encodeFormula (svTseitin solver) $+          case op of+            NRULt -> isULT s t+            NRSLt -> isSLT s t+            NREql -> isEQ s t+        writeIORef (svAtomTable solver) $ Map.insert atom' l table+        return l+  size <- Vec.getSize (svContexts solver)+  case label of+    Nothing | size == 1 -> SAT.addClause (svTseitin solver) [l]+    _ -> do+      Vec.modify (svContexts solver) (size - 1) (IntMap.insert l label)++check :: Solver -> IO Bool+check solver = do+  size <- Vec.getSize (svContexts solver)+  m <- Vec.read (svContexts solver) (size - 1)+  b <- SAT.solveWith (svSATSolver solver) (IntMap.keys m)+  return b++getModel :: Solver -> IO Model+getModel solver = do+  m <- SAT.getModel (svSATSolver solver)+  vss <- Vec.getElems (svVars solver)+  let f = fromAscBits . map (SAT.evalLit m) . VG.toList+      isZero = not . or . toAscBits+      env = VG.fromList [f vs | vs <- vss]+  xs <- readIORef (svDivRemTable solver)+  let divTable = Map.fromList [(f s, f d) | (s,t,d,_r) <- xs, isZero (f t)]+      remTable = Map.fromList [(f s, f r) | (s,t,_d,r) <- xs, isZero (f t)]+  return (env, divTable, remTable)++explain :: Solver -> IO IntSet+explain solver = do+  xs <- SAT.getFailedAssumptions (svSATSolver solver)+  size <- Vec.getSize (svContexts solver)+  m <- Vec.read (svContexts solver) (size - 1)+  return $ IntSet.fromList $ catMaybes [m IntMap.! x | x <- xs]++pushBacktrackPoint :: Solver -> IO ()+pushBacktrackPoint solver = do+  size <- Vec.getSize (svContexts solver)+  m <- Vec.read (svContexts solver) (size - 1)+  Vec.push (svContexts solver) m++popBacktrackPoint :: Solver -> IO ()+popBacktrackPoint solver = do+  _ <- Vec.pop (svContexts solver)+  return ()++-- ------------------------------------------------------------------------++type SBV = VU.Vector SAT.Lit++encodeExpr :: Solver -> Expr -> IO SBV+encodeExpr solver = enc+  where+    enc e@(EConst _) = enc' e+    enc e@(EVar _) = enc' e+    enc e = do+      table <- readIORef (svEncTable solver)+      case Map.lookup e table of+        Just vs -> return vs+        Nothing -> do+          vs <- enc' e+          modifyIORef (svEncTable solver) (Map.insert e vs)+          return vs++    enc' (EConst bs) =+      liftM VU.fromList $ forM (toAscBits bs) $ \b ->+        if b+        then Tseitin.encodeConj (svTseitin solver) []+        else Tseitin.encodeDisj (svTseitin solver) []+    enc' (EVar v) = Vec.read (svVars solver) (varId v)+    enc' (EOp1 op arg) = do+      arg' <- enc arg+      case op of+        OpExtract i j -> do+          unless (VG.length arg' > i && i >= j && j >= 0) $+            error ("invalid extract " ++ show (i,j) ++ " on bit-vector of length " ++ show (VG.length arg') ++ " : " ++ show arg)+          return $ VG.slice j (i - j + 1) arg'+        OpNot -> return $ VG.map negate arg'+        OpNeg -> encodeNegate (svTseitin solver) arg'+    enc' (EOp2 op arg1 arg2) = do+      arg1' <- enc arg1+      arg2' <- enc arg2+      case op of+        OpConcat -> return (arg2' <> arg1')+        OpAnd -> VG.zipWithM (\l1 l2 -> Tseitin.encodeConj (svTseitin solver) [l1,l2]) arg1' arg2'+        OpOr  -> VG.zipWithM (\l1 l2 -> Tseitin.encodeDisj (svTseitin solver) [l1,l2]) arg1' arg2'+        OpXOr -> VG.zipWithM (Tseitin.encodeXOR (svTseitin solver)) arg1' arg2'+        OpComp -> VG.singleton <$> Tseitin.encodeFormula (svTseitin solver) (isEQ arg1' arg2')+        OpAdd -> encodeSum (svTseitin solver) (VG.length arg1') True [arg1', arg2']+        OpMul -> encodeMul (svTseitin solver) True arg1' arg2'+        OpUDiv -> fst <$> encodeDivRem solver arg1' arg2'+        OpURem -> snd <$> encodeDivRem solver arg1' arg2'+        OpSDiv -> encodeSDiv solver arg1' arg2'+        OpSRem -> encodeSRem solver arg1' arg2'+        OpSMod -> encodeSMod solver arg1' arg2'+        OpShl  -> encodeShl (svTseitin solver) arg1' arg2'+        OpLShr -> encodeLShr (svTseitin solver) arg1' arg2'+        OpAShr -> encodeAShr (svTseitin solver) arg1' arg2'++encodeMul :: Tseitin.Encoder IO -> Bool -> SBV -> SBV -> IO SBV+encodeMul enc allowOverflow arg1 arg2 = do+  let w = VG.length arg1+  b0 <- Tseitin.encodeDisj enc [] -- False+  bss <- forM (zip [0..] (VG.toList arg2)) $ \(i,b2) -> do+    let arg1' = if allowOverflow+                then VG.take (w - i) arg1+                else arg1+    bs <- VG.forM arg1' $ \b1 -> do+            Tseitin.encodeConj enc [b1,b2]+    return (VG.replicate i b0 <> bs)+  encodeSum enc w allowOverflow bss++encodeSum :: Tseitin.Encoder IO -> Int -> Bool -> [SBV] -> IO SBV+encodeSum enc w allowOverflow xss = do+  (buckets :: IORef (Seq (SQ.SeqQueue IO SAT.Lit))) <- newIORef Seq.empty+  let insert i x = do+        bs <- readIORef buckets+        let n = Seq.length bs+        q <- if i < n then do+               return $ Seq.index bs i+             else do+               qs <- replicateM (i+1 - n) SQ.newFifo+               let bs' = bs Seq.>< Seq.fromList qs+               writeIORef buckets bs'+               return $ Seq.index bs' i+        SQ.enqueue q x++  forM_ xss $ \xs -> do+#if MIN_VERSION_vector(0,11,0)+    VG.imapM insert xs+#else+    VG.mapM (uncurry insert) (VG.indexed xs)+#endif++  let loop i ret+        | i >= w = do+            unless allowOverflow $ do+              bs <- readIORef buckets+              forM_ (F.toList bs) $ \q -> do+                ls <- SQ.dequeueBatch q+                forM_ ls $ \l -> do+                  SAT.addClause  enc [-l]+            return (reverse ret)+        | otherwise = do+            bs <- readIORef buckets+            let n = Seq.length bs+            if i >= n then do+              b <- Tseitin.encodeDisj enc [] -- False+              loop (i+1) (b : ret)+            else do+              let q = Seq.index bs i+              m <- SQ.queueSize q+              case m of+                0 -> do+                  b <- Tseitin.encodeDisj enc [] -- False+                  loop (i+1) (b : ret)+                1 -> do+                  Just b <- SQ.dequeue q+                  loop (i+1) (b : ret)+                2 -> do+                  Just b1 <- SQ.dequeue q+                  Just b2 <- SQ.dequeue q+                  s <- encodeHASum enc b1 b2+                  c <- encodeHACarry enc b1 b2+                  insert (i+1) c+                  loop (i+1) (s : ret)+                _ -> do+                  Just b1 <- SQ.dequeue q+                  Just b2 <- SQ.dequeue q+                  Just b3 <- SQ.dequeue q+                  s <- Tseitin.encodeFASum enc b1 b2 b3+                  c <- Tseitin.encodeFACarry enc b1 b2 b3+                  insert i s+                  insert (i+1) c+                  loop i ret+  VU.fromList <$> loop 0 []++encodeHASum :: Tseitin.Encoder IO -> SAT.Lit -> SAT.Lit -> IO SAT.Lit+encodeHASum = Tseitin.encodeXOR++encodeHACarry :: Tseitin.Encoder IO -> SAT.Lit -> SAT.Lit -> IO SAT.Lit+encodeHACarry enc a b = Tseitin.encodeConj enc [a,b]++encodeNegate :: Tseitin.Encoder IO -> SBV -> IO SBV+encodeNegate enc s = do+  let f _ [] ret = return $ VU.fromList $ reverse ret+      f b (x:xs) ret = do+        y <- Tseitin.encodeITE enc b (- x) x+        b' <- Tseitin.encodeDisj enc [b, x]+        f b' xs (y : ret)+  b0 <- Tseitin.encodeDisj enc []+  f b0 (VG.toList s) []++encodeAbs :: Tseitin.Encoder IO -> SBV -> IO SBV+encodeAbs enc s = do+  let w = VG.length s+  if w == 0 then+    return VG.empty+  else do+    let msb_s = VG.last s+    r <- VG.fromList <$> SAT.newVars enc w+    t <- encodeNegate enc s+    Tseitin.addFormula enc $+      ite (Atom (-msb_s)) (isEQ r s) (isEQ r t)+    return r++encodeShl :: Tseitin.Encoder IO -> SBV -> SBV -> IO SBV+encodeShl enc s t = do+  let w = VG.length s+  when (w /= VG.length t) $ error "invalid width"+  b0 <- Tseitin.encodeDisj enc [] -- False+  let go bs (i,b) =+        VG.generateM w $ \j -> do+          let k = toInteger j - 2^i+              t = if k >= 0 then bs VG.! fromInteger k else b0+              e = bs VG.! j+          Tseitin.encodeITE enc b t e+  foldM go s (zip [(0::Int)..] (VG.toList t))+  +encodeLShr :: Tseitin.Encoder IO -> SBV -> SBV -> IO SBV+encodeLShr enc s t = do+  let w = VG.length s+  when (w /= VG.length t) $ error "invalid width"+  b0 <- Tseitin.encodeDisj enc [] -- False+  let go bs (i,b) =+        VG.generateM w $ \j -> do+          let k = toInteger j + 2^i+              t = if k < fromIntegral (VG.length bs) then bs VG.! fromInteger k else b0+              e = bs VG.! j+          Tseitin.encodeITE enc b t e+  foldM go s (zip [(0::Int)..] (VG.toList t))++encodeAShr :: Tseitin.Encoder IO -> SBV -> SBV -> IO SBV+encodeAShr enc s t = do+  let w = VG.length s+  when (w /= VG.length t) $ error "invalid width"+  if w == 0 then+    return VG.empty+  else do+    let msb_s = VG.last s+    r <- VG.fromList <$> SAT.newVars enc w+    s' <- encodeNegate enc s+    a <- encodeLShr enc s t+    b <- encodeNegate enc =<< encodeLShr enc s' t+    Tseitin.addFormula enc $+      ite (Atom (-msb_s)) (isEQ r a) (isEQ r b)+    return r++encodeDivRem :: Solver -> SBV -> SBV -> IO (SBV, SBV)+encodeDivRem solver s t = do+  let w = VG.length s+  d <- VG.fromList <$> SAT.newVars (svSATSolver solver) w+  r <- VG.fromList <$> SAT.newVars (svSATSolver solver) w+  c <- do+    tmp <- encodeMul (svTseitin solver) False d t+    encodeSum (svTseitin solver) w False [tmp, r]+  tbl <- readIORef (svDivRemTable solver)+  Tseitin.addFormula (svTseitin solver) $+    ite (isZero t)+        (And [(isEQ s s' .&&. isZero t') .=>. (isEQ d d' .&&. isEQ r r') | (s',t',d',r') <- tbl, w == VG.length s'])+        (isEQ s c .&&. isULT r t)+  modifyIORef (svDivRemTable solver) ((s,t,d,r) :)+  return (d,r)++encodeSDiv :: Solver -> SBV -> SBV -> IO SBV+encodeSDiv solver s t = do+  let w = VG.length s+  when (w /= VG.length t) $ error "invalid width"+  if w == 0 then+    return VG.empty+  else do    +    s' <- encodeNegate (svTseitin solver) s+    t' <- encodeNegate (svTseitin solver) t+    let msb_s = VG.last s+        msb_t = VG.last t+    r <- VG.fromList <$> SAT.newVars (svSATSolver solver) w+    let f x y = fst <$> encodeDivRem solver x y+    a <- f s t+    b <- encodeNegate (svTseitin solver) =<< f s' t+    c <- encodeNegate (svTseitin solver) =<< f s t'+    d <- f s' t'+    Tseitin.addFormula (svTseitin solver) $+      ite (Atom (-msb_s) .&&. Atom (-msb_t)) (isEQ r a) $+      ite (Atom msb_s .&&. Atom (-msb_t)) (isEQ r b) $+      ite (Atom (-msb_s) .&&. Atom msb_t) (isEQ r c) $+      (isEQ r d)+    return r++encodeSRem :: Solver -> SBV -> SBV -> IO SBV+encodeSRem solver s t = do+  let w = VG.length s+  when (w /= VG.length t) $ error "invalid width"+  if w == 0 then+    return VG.empty+  else do+    s' <- encodeNegate (svTseitin solver) s+    t' <- encodeNegate (svTseitin solver) t+    let msb_s = VG.last s+        msb_t = VG.last t+    r <- VG.fromList <$> SAT.newVars (svSATSolver solver) w+    let f x y = snd <$> encodeDivRem solver x y+    a <- f s t+    b <- encodeNegate (svTseitin solver) =<< f s' t+    c <- f s t'+    d <- encodeNegate (svTseitin solver) =<< f s' t'+    Tseitin.addFormula (svTseitin solver) $+      ite (Atom (-msb_s) .&&. Atom (-msb_t)) (isEQ r a) $+      ite (Atom msb_s .&&. Atom (-msb_t)) (isEQ r b) $+      ite (Atom (-msb_s) .&&. Atom msb_t) (isEQ r c) $+      (isEQ r d)+    return r++encodeSMod :: Solver -> SBV -> SBV -> IO SBV+encodeSMod solver s t = do+  let w = VG.length s+  when (w /= VG.length t) $ error "invalid width"+  if w == 0 then+    return VG.empty+  else do+    let msb_s = VG.last s+        msb_t = VG.last t+    r <- VG.fromList <$> SAT.newVars (svSATSolver solver) w+    abs_s <- encodeAbs (svTseitin solver) s+    abs_t <- encodeAbs (svTseitin solver) t+    u <- snd <$> encodeDivRem solver abs_s abs_t+    u' <- encodeNegate (svTseitin solver) u+    a <- encodeSum (svTseitin solver) w True [u', t]+    b <- encodeSum (svTseitin solver) w True [u, t]+    Tseitin.addFormula (svTseitin solver) $+      ite (isZero u .||. (Atom (-msb_s) .&&. Atom (-msb_t))) (isEQ r u) $+      ite (Atom msb_s .&&. Atom (-msb_t)) (isEQ r a) $+      ite (Atom (-msb_s) .&&. Atom msb_t) (isEQ r b) $+      (isEQ r u')+    return r++isZero :: SBV -> Tseitin.Formula+isZero bs = And [Not (Atom b) | b <- VG.toList bs]++isEQ :: SBV -> SBV -> Tseitin.Formula+isEQ bs1 bs2+  | VG.length bs1 /= VG.length bs2 = error ("length mismatch: " ++ show (VG.length bs1) ++ " and " ++ show (VG.length bs2))+  | otherwise = And [Equiv (Atom b1) (Atom b2) | (b1,b2) <- zip (VG.toList bs1) (VG.toList bs2)]++isULT :: SBV -> SBV -> Tseitin.Formula+isULT bs1 bs2+  | VG.length bs1 /= VG.length bs2 = error ("length mismatch: " ++ show (VG.length bs1) ++ " and " ++ show (VG.length bs2))+  | otherwise = f (VG.toList (VG.reverse bs1)) (VG.toList (VG.reverse bs2))+  where+    f [] [] = false+    f (b1:bs1) (b2:bs2) =+      (notB (Atom b1) .&&. Atom b2) .||. ((Atom b1 .=>. Atom b2) .&&. f bs1 bs2)+    f _ _ = error "should not happen"++isSLT :: SBV -> SBV -> Tseitin.Formula+isSLT bs1 bs2+  | VG.length bs1 /= VG.length bs2 = error ("length mismatch: " ++ show (VG.length bs1) ++ " and " ++ show (VG.length bs2))+  | w == 0 = false+  | otherwise =+      Atom bs1_msb .&&. Not (Atom bs2_msb)+      .||. (Atom bs1_msb .<=>. Atom bs2_msb) .&&. isULT bs1 bs2+  where+    w = VG.length bs1+    bs1_msb = bs1 VG.! (w-1)+    bs2_msb = bs2 VG.! (w-1)++-- ------------------------------------------------------------------------++test1 :: IO ()+test1 = do+  solver <- newSolver+  v1 <- newVar solver 8+  v2 <- newVar solver 8+  assertAtom solver (EOp2 OpMul v1 v2 .==. nat2bv 8 6) Nothing+  print =<< check solver+  m <- getModel solver+  print m++test2 :: IO ()+test2 = do+  solver <- newSolver+  v1 <- newVar solver 8+  v2 <- newVar solver 8+  let z = nat2bv 8 0+  assertAtom solver (EOp2 OpUDiv v1 z ./=. EOp2 OpUDiv v2 z) Nothing+  assertAtom solver (v1 .==. v2) Nothing+  print =<< check solver -- False
+ src/ToySolver/Combinatorial/BipartiteMatching.hs view
@@ -0,0 +1,445 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE ScopedTypeVariables, BangPatterns #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Combinatorial.BipartiteMatching+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+--+-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+-- Portability :  non-portable (ScopedTypeVariables, BangPatterns)+--+-- This module provides functions for computing several kind of bipartite+-- matching. +-- +-- Reference:+--+-- * Friedrich Eisenbrand. “Linear and Discrete Optimization”.+--   <https://www.coursera.org/course/linearopt>+--+-----------------------------------------------------------------------------+module ToySolver.Combinatorial.BipartiteMatching+  ( +  -- * Maximum cardinality bipartite matching+    maximumCardinalityMatching++  -- * Maximum weight bipartite matching+  , maximumWeightMatching+  , maximumWeightMatchingComplete++  -- * Maximum/Minimum weight bipartite perfect matching+  , maximumWeightPerfectMatching+  , minimumWeightPerfectMatching+  , maximumWeightPerfectMatchingComplete+  , minimumWeightPerfectMatchingComplete++  -- * Misc+  , minimumCardinalityEdgeCover+  , minimumWeightEdgeCover+  , minimumWeightEdgeCoverComplete+  ) where++import Control.Monad+import qualified Data.Foldable as F+import Data.IntMap.Strict (IntMap, (!))+import qualified Data.IntMap.Strict as IntMap+import Data.IntSet (IntSet)+import qualified Data.IntSet as IntSet+import Data.Set (Set)+import qualified Data.Set as Set+import Data.Maybe++-- -----------------------------------------------------------------------------++-- | Maximum cardinality matching on a bipartite graph (A+B, E).+maximumCardinalityMatching+  :: IntSet      -- ^ vertex set A+  -> IntSet      -- ^ vertex set B+  -> [(Int,Int)] -- ^ set of edges E⊆A×B+  -> IntMap Int+maximumCardinalityMatching _as bs es = +  case maximumCardinalityMatching' bs (\b -> IntMap.findWithDefault IntSet.empty b e_b2a) IntMap.empty of+    (m, _, _) -> m+  where+    e_b2a :: IntMap IntSet+    e_b2a = IntMap.fromListWith IntSet.union [(b, IntSet.singleton a) | (a,b) <- es]++-- | Alternating path b_0, a_0, …, b_{n-1}, a_{n-1}, b_n is represented as+-- (b_n, [(a_{n-1}, b_{n-1}) .. (a_0, b_0)], b_0).+type AlternatingPath = (Int, [(Int,Int)], Int)++-- | Augmenting path b_0, a_0, …, b_n, a_n is represented as+-- ([(a_n, b_n) .. (a_0, b_0)], b_0).+type AugmentingPath = ([(Int,Int)], Int)++-- | Internal low-level routine for maximum cardinality bipartite matching.+--+-- It returns a maximum cardinality matching M together with sets of+-- vertexes reachable from exposed B vertexes (b∈B such that ∀a∈A. (a,b)∉M)+-- on a directed graph (A+B, {a→b|(a,b)∈M}∪{b→a|(a,b)⊆E\\M}).+maximumCardinalityMatching'+  :: IntSet          -- ^ vertex set B+  -> (Int -> IntSet) -- ^ set of edges E⊆A×B represented as a mapping from B to 2^A.+  -> IntMap Int      -- ^ partial matching represented as an injective mapping from A to B+  -> (IntMap Int, IntSet, IntSet)+maximumCardinalityMatching' bs e_b2a m0 = loop m0 m0_b_exposed+  where+    m0_b_exposed = bs `IntSet.difference` IntSet.fromList (IntMap.elems m0)++    loop :: IntMap Int -> IntSet -> (IntMap Int, IntSet, IntSet)+    loop m m_b_exposed =+      case search m_b_exposed of+        (l_a, l_b, []) -> (m, l_a, l_b)+        (_, _, ds) ->+          let -- Note that IntMap.union is left-biased+              ds2 = [IntMap.fromList d2 | (d2,_) <- ds]+              m' = IntMap.unions ds2 `IntMap.union` m+              m_b_exposed' = m_b_exposed `IntSet.difference` IntSet.fromList [b0 | (_, b0) <- ds]+          in loop m' m_b_exposed'+      where+        search :: IntSet -> (IntSet, IntSet, [AugmentingPath])+        search b_exposed = loopB IntSet.empty b_exposed [(b, [], b) | b <- IntSet.toList b_exposed] [] []+          where+            loopB :: IntSet -> IntSet -> [AlternatingPath] -> [AlternatingPath] -> [AugmentingPath] -> (IntSet, IntSet, [AugmentingPath])+            loopB !visitedA !visitedB [] [] result = (visitedA, visitedB, result)+            loopB !visitedA !visitedB [] nextB result = loopB visitedA visitedB nextB [] result+            loopB !visitedA !visitedB ((b, d2, b0) : currB) nextB result = loopA visitedA visitedB (IntSet.toList (e_b2a b)) currB nextB result+              where+                loopA !visitedA !visitedB [] currB nextB result = loopB visitedA visitedB currB nextB result+                loopA !visitedA !visitedB (a:as) currB nextB result+                  | a `IntSet.member` visitedA = loopA visitedA visitedB as currB nextB result+                  | otherwise =+                      case IntMap.lookup a m of+                        Nothing ->+                          loopB (IntSet.insert a visitedA) visitedB (filter (\(_,_,b0') -> b0/=b0') currB) (filter (\(_,_,b0') -> b0/=b0') nextB) (((a,b) : d2, b0) : result)+                        Just b2+                          | b==b2 -> loopA visitedA visitedB as currB nextB result+                          | b2 `IntSet.member` visitedB -> loopA (IntSet.insert a visitedA) visitedB as currB nextB result+                          | otherwise -> loopA (IntSet.insert a visitedA) (IntSet.insert b2 visitedB) as currB ((b2, (a,b):d2, b0) : nextB) result++-- -----------------------------------------------------------------------------++-- | Maximum weight matching of a complete bipartite graph (A+B,A×B).+maximumWeightMatchingComplete+  :: forall w. (Real w)+  => IntSet            -- ^ vertex set A+  -> IntSet            -- ^ vertex set B+  -> (Int -> Int -> w) -- ^ weight of edges A×B+  -> (w, IntMap Int)+maximumWeightMatchingComplete as bs w =+  case maximumWeightMaximumMatchingComplete as bs (\a b -> max 0 (w a b)) of+    (_, m) ->+      let m' = IntMap.filterWithKey (\a b -> w a b > 0) m+      in (sum [w a b | (a,b) <- IntMap.toList m'], m')++-- | Maximum weight matching of a bipartite graph (A+B,E).+maximumWeightMatching+  :: forall w. (Real w)+  => IntSet          -- ^ vertex set A+  -> IntSet          -- ^ vertex set B+  -> [(Int, Int, w)] -- ^ edges E⊆A×B and their weights+  -> (w, IntMap Int)+maximumWeightMatching as bs w =+  case maximumWeightMaximumMatchingComplete as bs g of+    (_, m) ->+      let m' = IntMap.filterWithKey (\a b -> isJust (f a b)) m+      in (sum [g a b | (a,b) <- IntMap.toList m'], m')+  where+    tbl :: IntMap (IntMap w)+    tbl = IntMap.fromListWith IntMap.union [(a, (IntMap.singleton b v)) | (a,b,v) <- w]+    f a b = do+      t <- IntMap.lookup a tbl +      v <- IntMap.lookup b t+      guard $ v >= 0+      return v+    g a b = fromMaybe 0 (f a b)++-- -----------------------------------------------------------------------------++-- | Maximum weight maximum matching of a complete bipartite graph (A+B,A×B).+maximumWeightMaximumMatchingComplete+  :: forall w. (Real w)+  => IntSet            -- ^ vertex set A+  -> IntSet            -- ^ vertex set B+  -> (Int -> Int -> w) -- ^ weight of edges A×B+  -> (w, IntMap Int)+maximumWeightMaximumMatchingComplete as bs w =+  case as_size `compare` bs_size of+    EQ ->+      case maximumWeightPerfectMatchingComplete as bs w of+        (obj, sol, _) -> (obj, sol)+    GT ->+      let bs' = bs `IntSet.union` IntSet.fromAscList (take (as_size-bs_size) $ filter (`IntSet.notMember` bs) [0..])+          w' a b+            | b `IntSet.member` bs = w a b+            | otherwise = 0+      in case maximumWeightPerfectMatchingComplete as bs' w' of+           (obj, sol, _) ->+             ( obj+             , IntMap.filterWithKey (\_ b -> b `IntSet.member` bs) sol+             )+    LT ->+      let as' = as `IntSet.union` IntSet.fromAscList (take (bs_size-as_size) $ filter (`IntSet.notMember` as) [0..])+          w' a b+            | a `IntSet.member` as = w a b+            | otherwise = 0+      in case maximumWeightPerfectMatchingComplete as' bs w' of+           (obj, sol, _) ->+             ( obj+             , IntMap.filterWithKey (\a _ -> a `IntSet.member` as) sol+             )+  where+    as_size = IntSet.size as+    bs_size = IntSet.size bs++-- -----------------------------------------------------------------------------++-- | Maximum weight perfect matching of a complete bipartite graph (A+B,A×B).+--+-- The two sets must be same size (\|A\| = \|B\|).+maximumWeightPerfectMatchingComplete+  :: forall w. (Real w)+  => IntSet            -- ^ vertex set A+  -> IntSet            -- ^ vertex set B+  -> (Int -> Int -> w) -- ^ weight of edges A×B+  -> (w, IntMap Int, (IntMap w, IntMap w))+maximumWeightPerfectMatchingComplete as bs w =+  case minimumWeightPerfectMatchingComplete as bs (\a b -> - w a b) of+    (obj, m, (ysA,ysB)) -> (- obj, m, (IntMap.map negate ysA, IntMap.map negate ysB))++-- | Minimum weight perfect matching of a complete bipartite graph (A+B,A×B).+--+-- The two sets must be same size (\|A\| = \|B\|).+minimumWeightPerfectMatchingComplete+  :: forall w. (Real w)+  => IntSet            -- ^ vertex set A+  -> IntSet            -- ^ vertex set B+  -> (Int -> Int -> w) -- ^ weight of edges A×B+  -> (w, IntMap Int, (IntMap w, IntMap w))+minimumWeightPerfectMatchingComplete as bs w+  | n /= IntSet.size bs = error "minimumWeightPerfectMatchingComplete: two sets must be same size"+  | otherwise = loop m0 ys0 (equalityGraph ys0)+  where+    n = IntSet.size as++    ys0 :: (IntMap w, IntMap w)+    ys0 = ( IntMap.fromSet (\a -> minimum [w a b | b <- IntSet.toList bs]) as+          , IntMap.fromSet (\_ -> 0) bs+          )+    m0 = IntMap.empty++    loop+      :: IntMap Int -> (IntMap w, IntMap w) -> IntMap IntSet+      -> (w, IntMap Int, (IntMap w, IntMap w))+    loop m_pre ys@(ysA,ysB) g_eq+      | IntMap.size m == n = (F.sum ysA + F.sum ysB, m, ys)+      | otherwise = loop m ys' g_eq'+      where+        (m, l_a, l_b) = maximumCardinalityMatching' bs (g_eq !) m_pre+        l_a' = as `IntSet.difference` l_a -- A \ L++        slack :: w+        slack = minimum+                [ w a b - (ysA!a + ysB!b)+                | a <- IntSet.toList l_a'+                , b <- IntSet.toList l_b+                ]++        -- augmenting dual solution+        ys' :: (IntMap w, IntMap w)+        ys' = (IntMap.mapWithKey f ysA, IntMap.mapWithKey g ysB)+          where+            f a val+              | a `IntSet.notMember` l_a = val + slack+              | otherwise = val+            g b val+              | b `IntSet.notMember` l_b = val - slack+              | otherwise = val++        g_eq' :: IntMap IntSet+        g_eq' = IntMap.mapWithKey f g_eq+          where+            f b as3+              | b `IntSet.member` l_b =+                  as3 `IntSet.union` IntSet.filter (\a -> w a b == (fst ys' ! a + snd ys' ! b)) l_a'+              | otherwise = as3 `IntSet.difference` l_a++    equalityGraph :: (IntMap w, IntMap w) -> IntMap IntSet+    equalityGraph (ysA,ysB) =+      IntMap.fromSet (\b -> IntSet.filter (\a -> w a b == ysA!a + ysB!b) as) bs++-- -----------------------------------------------------------------------------++-- | Maximum weight perfect matching of a complete bipartite graph (A+B,E).+--+-- If no such matching exist, it returns @Nothing@.+maximumWeightPerfectMatching+  :: forall w. (Real w)+  => IntSet        -- ^ vertex set A+  -> IntSet        -- ^ vertex set B+  -> [(Int,Int,w)] -- ^ edges E⊆A×B and their weights+  -> Maybe (w, IntMap Int, (IntMap w, IntMap w))+maximumWeightPerfectMatching as bs es = do+  (obj, m, (ysA,ysB)) <- minimumWeightPerfectMatching as bs [(a,b,-w) |(a,b,w) <- es]+  return (- obj, m, (IntMap.map negate ysA, IntMap.map negate ysB))++-- | Minimum weight perfect matching of a bipartite graph (A+B, E).+--+-- If no such matching exist, it returns @Nothing@.+minimumWeightPerfectMatching+  :: forall w. (Real w)+  => IntSet        -- ^ vertex set A+  -> IntSet        -- ^ vertex set B+  -> [(Int,Int,w)] -- ^ edges E⊆A×B and their weights+  -> Maybe (w, IntMap Int, (IntMap w, IntMap w))+minimumWeightPerfectMatching as bs es+  | n /= IntSet.size bs = Nothing+  | F.any IntMap.null e_b2a = Nothing+  | otherwise = loop m0 ys0 (equalityGraph ys0)+  where+    n = IntSet.size as++    -- Note that IntMap.union is left-biased.+    e_b2a :: IntMap (IntMap w)+    e_b2a = fmap IntMap.fromList $ IntMap.fromListWith (++) [(b,[(a,w)]) | (a,b,w) <- es]+              `IntMap.union` IntMap.fromSet (\_ -> []) bs+{-+    e_b2a = IntMap.fromListWith IntMap.union [(b, IntMap.singleton a w) | (a,b,w) <- es]+              `IntMap.union` IntMap.fromList [(b, IntMap.empty) | b <- IntSet.toList bs]+-}++    ys0 :: (IntMap w, IntMap w)+    ys0 = ( IntMap.fromSet (\_ -> 0) as+          , fmap F.minimum e_b2a+          )+    m0 = IntMap.empty++    loop+      :: IntMap Int -> (IntMap w, IntMap w) -> IntMap IntSet+      -> Maybe (w, IntMap Int, (IntMap w, IntMap w))+    loop m_pre ys@(ysA,ysB) g_eq+      | IntMap.size m == n = Just (F.sum ysA + F.sum ysB, m, ys)+      | null slacks = Nothing+      | otherwise = loop m ys' g_eq'+      where+        (m, l_a, l_b) = maximumCardinalityMatching' bs (g_eq !) m_pre++        slacks :: [w]+        slacks = [w - (ysA!a + ysB!b) | b <- IntSet.toList l_b, (a,w) <- IntMap.toList (e_b2a ! b), a `IntSet.notMember` l_a]++        slack :: w+        slack = minimum slacks++        -- augmenting dual solution+        ys' :: (IntMap w, IntMap w)+        ys' = (IntMap.mapWithKey f ysA, IntMap.mapWithKey g ysB)+          where+            f a val+              | a `IntSet.notMember` l_a = val + slack+              | otherwise = val+            g b val+              | b `IntSet.notMember` l_b = val - slack+              | otherwise = val++        g_eq' :: IntMap IntSet+        g_eq' = IntMap.mapWithKey f g_eq+          where+            f b as3+              | b `IntSet.member` l_b =+                  as3 `IntSet.union` IntSet.fromAscList [a | (a,w) <- IntMap.toAscList (e_b2a ! b), a `IntSet.notMember` l_a, w == fst ys' ! a + snd ys' ! b]+              | otherwise = as3 `IntSet.difference` l_a++    equalityGraph :: (IntMap w, IntMap w) -> IntMap IntSet+    equalityGraph (ysA,ysB) = IntMap.mapWithKey f e_b2a+      where+        f b xs = IntSet.fromAscList [a | (a,w) <- IntMap.toAscList xs, w == ysA!a + ysB!b]++-- -----------------------------------------------------------------------------++-- | Minimum cardinality edge cover of bipartite graph (A+B, E).+minimumCardinalityEdgeCover+  :: IntSet      -- ^ vertex set A+  -> IntSet      -- ^ vertex set B+  -> [(Int,Int)] -- ^ edges E⊆A×B+  -> Maybe (Set (Int,Int))+minimumCardinalityEdgeCover as bs es+  | IntMap.size ca /= IntSet.size as = Nothing+  | IntMap.size cb /= IntSet.size bs = Nothing+  | otherwise =+      case maximumCardinalityMatching as bs es of+        m -> +          let ma = IntMap.keysSet m+              mb = IntSet.fromList $ IntMap.elems m+              m2 = Set.unions+                   [ Set.fromList (IntMap.toList m)+                   , Set.fromList [(a,b) | a <- IntSet.toList (as `IntSet.difference` ma), let b = ca IntMap.! a]+                   , Set.fromList [(a,b) | b <- IntSet.toList (bs `IntSet.difference` mb), let a = cb IntMap.! b]+                   ]+          in Just $ m2+  where+    ca = IntMap.fromList es+    cb = IntMap.fromList [(b,a) | (a,b) <- es]++-- | Minimum weight edge cover of bipartite graph (A+B, E).+minimumWeightEdgeCover+  :: forall w. (Real w)+  => IntSet        -- ^ vertex set A+  -> IntSet        -- ^ vertex set B+  -> [(Int,Int,w)] -- ^ edges E⊆A×B and their weights+  -> Maybe (Set (Int,Int))+minimumWeightEdgeCover as bs es+  | IntMap.size ca /= IntSet.size as = Nothing+  | IntMap.size cb /= IntSet.size bs = Nothing+  | otherwise =+      case maximumWeightMatching as' bs' es' of+        (_, m) ->+          let ma = IntMap.keysSet m+              mb = IntSet.fromList $ IntMap.elems m+              m2 = Set.unions+                   [ Set.fromList (IntMap.toList m)+                   , Set.fromList [(a,b) | a <- IntSet.toList (as `IntSet.difference` ma), let (b,_) = ca IntMap.! a]+                   , Set.fromList [(a,b) | b <- IntSet.toList (bs `IntSet.difference` mb), let (a,_) = cb IntMap.! b]+                   , Set.fromList [(a,b) | (a,b,w) <- es, w < 0]+                   ]+          in Just m2+  where+    minOnSnd xw1@(_,w1) xw2@(_,w2) = if w1 <= w2 then xw1 else xw2+    ca = IntMap.fromListWith minOnSnd [(a,(b,w)) | (a,b,w) <- es]+    cb = IntMap.fromListWith minOnSnd [(b,(a,w)) | (a,b,w) <- es]+    as' = IntSet.fromAscList [a | (a,(_,w)) <- IntMap.toAscList ca, w >= 0]+    bs' = IntSet.fromAscList [b | (b,(_,w)) <- IntMap.toAscList cb, w >= 0]+    es' = [(a, b, (snd (ca IntMap.! a) + snd (cb IntMap.! b)) - w) | (a,b,w) <- es, w >= 0]++-- | Minimum weight edge cover of complete bipartite graph (A+B, A×B).+minimumWeightEdgeCoverComplete+  :: forall w. (Real w)+  => IntSet            -- ^ vertex set A+  -> IntSet            -- ^ vertex set B+  -> (Int -> Int -> w) -- ^ weight of edges A×B+  -> Maybe (Set (Int,Int))+minimumWeightEdgeCoverComplete as bs w+  | IntMap.size ca /= IntSet.size as = Nothing+  | IntMap.size cb /= IntSet.size bs = Nothing+  | otherwise =+      case maximumWeightMatching as' bs' es' of+        (_, m) ->+          let ma = IntMap.keysSet m+              mb = IntSet.fromList $ IntMap.elems m+              m2 = Set.unions+                   [ Set.fromList (IntMap.toList m)+                   , Set.fromList [(a,b) | a <- IntSet.toList (as `IntSet.difference` ma), let (b,_) = ca IntMap.! a]+                   , Set.fromList [(a,b) | b <- IntSet.toList (bs `IntSet.difference` mb), let (a,_) = cb IntMap.! b]+                   , Set.fromList [(a,b) | a <- IntSet.toList as, b <- IntSet.toList bs, let w' = w a b, w' < 0]+                   ]+          in Just m2+  where+    minOnSnd xw1@(_,w1) xw2@(_,w2) = if w1 <= w2 then xw1 else xw2+    ca = IntMap.fromListWith minOnSnd [(a, (b, w a b)) | a <- IntSet.toList as, b <- IntSet.toList bs]+    cb = IntMap.fromListWith minOnSnd [(b, (a, w a b)) | a <- IntSet.toList as, b <- IntSet.toList bs]+    as' = IntSet.fromAscList [a | (a,(_,w)) <- IntMap.toAscList ca, w >= 0]+    bs' = IntSet.fromAscList [b | (b,(_,w)) <- IntMap.toAscList cb, w >= 0]+    es' = [ (a, b, (snd (ca IntMap.! a) + snd (cb IntMap.! b)) - w')+          | a <- IntSet.toList as, b <- IntSet.toList bs, let w' = w a b, w' >= 0 ]++-- -----------------------------------------------------------------------------
+ src/ToySolver/Combinatorial/HittingSet/DAA.hs view
@@ -0,0 +1,116 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Combinatorial.HittingSet.DAA+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable+--+-- "Dualize and Advance" algorithm for enumerating maximal interesting sets+-- and minimal non-interesting sets.+--+-- * [GMKT1997]+--   D. Gunopulos, H. Mannila, R. Khardon, and H. Toivonen, Data mining,+--   hypergraph transversals, and machine learning (extended abstract),+--   in Proceedings of the Sixteenth ACM SIGACT-SIGMOD-SIGART Symposium+--   on Principles of Database Systems, ser. PODS '97. 1997, pp. 209-216.+--   <http://almaden.ibm.com/cs/projects/iis/hdb/Publications/papers/pods97_trans.pdf>+-- +-- * [BaileyStuckey2015]+--   J. Bailey and P. Stuckey, Discovery of minimal unsatisfiable+--   subsets of constraints using hitting set dualization," in Practical+--   Aspects of Declarative Languages, pp. 174-186, 2005.+--   <http://ww2.cs.mu.oz.au/~pjs/papers/padl05.pdf>+--+-----------------------------------------------------------------------------+module ToySolver.Combinatorial.HittingSet.DAA+  (+  -- * Problem definition+    module ToySolver.Combinatorial.HittingSet.InterestingSets++  -- * Main functionality+  , run++  -- * Applications: minimal hitting sets+  , generateCNFAndDNF+  ) where++import Control.Monad.Identity+import Data.Default.Class+import Data.IntSet (IntSet)+import qualified Data.IntSet as IntSet+import Data.Set (Set)+import qualified Data.Set as Set+import ToySolver.Combinatorial.HittingSet.InterestingSets+import ToySolver.Combinatorial.HittingSet.Util (maintainNoSupersets)++-- | Given a problem and an option, it computes maximal interesting sets and+-- minimal uninteresting sets.+run :: forall prob m. IsProblem prob m => prob -> Options m -> m (Set IntSet, Set IntSet)+run prob opt = do+  let comp_pos = Set.map complement (optMaximalInterestingSets opt)+  hst_comp_pos <- optMinimalHittingSets opt comp_pos+  loop comp_pos hst_comp_pos (optMinimalUninterestingSets opt)++  where+    univ :: IntSet+    univ = universe prob++    complement :: IntSet -> IntSet+    complement = (univ `IntSet.difference`)++    loop :: Set IntSet -> Set IntSet -> Set IntSet -> m (Set IntSet, Set IntSet)+    loop comp_pos hst_comp_pos neg = do+      let xss = hst_comp_pos `Set.difference` neg+      if Set.null xss then+        return (Set.map complement comp_pos, neg)+      else do+        (comp_pos', hst_comp_pos', neg') <- loop2 comp_pos hst_comp_pos neg (Set.toList xss)+        loop comp_pos' hst_comp_pos' neg'++    loop2 :: Set IntSet -> Set IntSet -> Set IntSet -> [IntSet] -> m (Set IntSet, Set IntSet, Set IntSet)+    loop2 comp_pos hst_comp_pos neg [] = return (comp_pos, hst_comp_pos, neg)+    loop2 comp_pos hst_comp_pos neg (xs : xss) = do+      ret <- maximalInterestingSet prob xs+      case ret of+        Nothing -> do+          optOnMinimalUninterestingSetFound opt xs+          loop2 comp_pos hst_comp_pos (Set.insert xs neg) xss+        Just ys -> do+          optOnMaximalInterestingSetFound opt ys+          let zs = complement ys+              comp_pos' = Set.insert zs comp_pos+              -- "4.2 Incremental Hitting set Calculation" from [BaileyStuckey2015]+              hst_comp_pos' = Set.fromList $ maintainNoSupersets $+                [IntSet.insert w ws | ws <- Set.toList hst_comp_pos, w <- IntSet.toList zs]+          -- hst_comp_pos' <- optMinimalHittingSets opt comp_pos'+          return (comp_pos', hst_comp_pos', neg)++-- | Compute the irredundant CNF representation and DNF representation.+--+-- Let /f/ be a monotone boolean function over set of variables /S/.+-- This function returns /C/ and /D/ where ∧_{I∈C} ∨_{i∈I} x_i and+-- ∨_{I∈D} ∧_{i∈I} x_i are the irredundant CNF representation /f/ and+-- DNF representation of /f/ respectively.+generateCNFAndDNF+  :: IntSet -- ^ Set of variables /V/+  -> (IntSet -> Bool) -- ^ A monotone boolean function /f/ from /{0,1}^|V| ≅ P(V)/ to @Bool@+  -> Set IntSet -- ^ Subset /C'/ of prime implicates /C/ of /f/+  -> Set IntSet -- ^ Subset /D'/ of prime implicants /D/ of /f/+  -> (Set IntSet, Set IntSet)+generateCNFAndDNF vs f cs ds = (Set.map (vs `IntSet.difference`) pos, neg)+  where+    prob = SimpleProblem vs (not . f)+    opt = def+      { optMaximalInterestingSets = Set.map (vs `IntSet.difference`) cs+      , optMinimalUninterestingSets = ds+      }+    (pos,neg) = runIdentity $ run prob opt
src/ToySolver/Combinatorial/HittingSet/FredmanKhachiyan1996.hs view
@@ -297,7 +297,7 @@ -- Complexity: /O(n^o(log n))/ where @n = 'Set.size' f + 'Set.size' g@. checkDualityB   :: Set IntSet -- ^ a monotone boolean function /f/ given in DNF-  -> Set IntSet -- ^ a monotone boolean function /f/ given in DNF+  -> Set IntSet -- ^ a monotone boolean function /g/ given in DNF   -> Maybe IntSet checkDualityB f g   | Just xs <- condition_1_1_solve f g = Just xs
src/ToySolver/Combinatorial/HittingSet/GurvichKhachiyan1999.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# OPTIONS_GHC -Wall #-} ----------------------------------------------------------------------------- -- |@@ -19,18 +20,60 @@ -- ----------------------------------------------------------------------------- module ToySolver.Combinatorial.HittingSet.GurvichKhachiyan1999-  ( findPrimeImplicateOrPrimeImplicant+  (+  -- * Problem definition+    module ToySolver.Combinatorial.HittingSet.InterestingSets++  -- * Main functionality+  , run++  -- * Applications: monotone boolean functions+  , findPrimeImplicateOrPrimeImplicant   , generateCNFAndDNF++  -- * Applicaitons: minimal hitting sets   , minimalHittingSets   , enumMinimalHittingSets   ) where +import Control.Monad.Identity+import Data.Default.Class import Data.IntSet (IntSet) import qualified Data.IntSet as IntSet import Data.Set (Set) import qualified Data.Set as Set import qualified ToySolver.Combinatorial.HittingSet.FredmanKhachiyan1996 as FredmanKhachiyan1996+import ToySolver.Combinatorial.HittingSet.InterestingSets +-- -----------------------------------------------------------------++-- | Given a problem and an option, it computes maximal interesting sets and+-- minimal uninteresting sets.+run :: forall m prob. IsProblem prob m => prob -> Options m -> m (Set IntSet, Set IntSet)+run prob opt = loop (Set.map complement (optMaximalInterestingSets opt)) (optMinimalUninterestingSets opt)+  where+    univ :: IntSet+    univ = universe prob++    complement :: IntSet -> IntSet+    complement = (univ `IntSet.difference`)++    loop :: Set IntSet -> Set IntSet -> m (Set IntSet, Set IntSet)+    loop comp_pos neg = do+      case FredmanKhachiyan1996.checkDuality neg comp_pos of+        Nothing -> return (Set.map complement comp_pos, neg)+        Just xs -> do+          ret <- minimalUninterestingSetOrMaximalInterestingSet prob xs+          case ret of+            UninterestingSet ys -> do+              optOnMinimalUninterestingSetFound opt ys+              loop comp_pos (Set.insert ys neg)+            InterestingSet ys -> do+              optOnMaximalInterestingSetFound opt ys+              loop (Set.insert (complement ys) comp_pos) neg++-- -----------------------------------------------------------------+ -- | Find a new prime implicant or implicate. -- -- Let /f/ be a monotone boolean function over set of variables /S/.@@ -50,47 +93,13 @@   -> (IntSet -> Bool) -- ^ A monotone boolean function /f/ from /{0,1}^|V| ≅ P(V)/ to @Bool@   -> Set IntSet -- ^ Subset /C'/ of prime implicates /C/ of /f/   -> Set IntSet -- ^ Subset /D'/ of prime implicants /D/ of /f/-  -> Maybe (Either IntSet IntSet)+  -> Maybe ImplicateOrImplicant findPrimeImplicateOrPrimeImplicant vs f cs ds = do-  ret <- findImplicateOrImplicant vs f cs ds-  case ret of-    Left xs -> return $ Left $ minimizeImplicate vs f xs-    Right xs -> return $ Right $ minimizeImplicant vs f xs--findImplicateOrImplicant-  :: IntSet -- ^ Set of variables /V/-  -> (IntSet -> Bool) -- ^ A monotone boolean function /f/ from /{0,1}^|V| ≅ P(V)/ to @Bool@-  -> Set IntSet -- ^ Subset /C'/ of prime implicates /C/ of /f/-  -> Set IntSet -- ^ Subset /D'/ of prime implicants /D/ of /f/-  -> Maybe (Either IntSet IntSet)-findImplicateOrImplicant vs f cs ds = do   xs <- FredmanKhachiyan1996.checkDuality ds cs-  if f xs then-    return $ Right xs-  else-    return $ Left (vs `IntSet.difference` xs)---- Minimize I such that ∧_{i∈I} x_i → f(x)-minimizeImplicant :: IntSet -> (IntSet -> Bool) -> IntSet -> IntSet-minimizeImplicant _ f is = loop (IntSet.toList is) is-  where-    loop [] !ret = ret-    loop (x:xs) !ret =-      if f (IntSet.delete x ret)-      then loop xs (IntSet.delete x ret)-      else loop xs ret---- Minimize I such that f(x) → ∨_{i∈I} x_i--- i.e. Minimize I such that ∧_{i∈I} ¬x_i → ¬f(x)--- i.e. Maximize J such that ∧_{j∈J} x_j → ¬f(x)-minimizeImplicate :: IntSet -> (IntSet -> Bool) -> IntSet -> IntSet-minimizeImplicate vs f is = (vs `IntSet.difference`) $ loop (IntSet.toList is) (vs `IntSet.difference` is)-  where-    loop [] !ret = ret-    loop (x:xs) !ret =-      if not (f (IntSet.insert x ret))-      then loop xs (IntSet.insert x ret)-      else loop xs ret+  let prob = SimpleProblem vs (not . f)+  case runIdentity (minimalUninterestingSetOrMaximalInterestingSet prob xs) of+    UninterestingSet ys -> return (Implicant ys)+    InterestingSet ys -> return (Implicate (vs `IntSet.difference` ys))  -- | Compute the irredundant CNF representation and DNF representation. --@@ -104,11 +113,14 @@   -> Set IntSet -- ^ Subset /C'/ of prime implicates /C/ of /f/   -> Set IntSet -- ^ Subset /D'/ of prime implicants /D/ of /f/   -> (Set IntSet, Set IntSet)-generateCNFAndDNF vs f cs ds =-  case findPrimeImplicateOrPrimeImplicant vs f cs ds of-    Nothing -> (cs, ds)-    Just (Left xs)  -> generateCNFAndDNF vs f (Set.insert xs cs) ds-    Just (Right xs) -> generateCNFAndDNF vs f cs (Set.insert xs ds)+generateCNFAndDNF vs f cs ds = (Set.map (vs `IntSet.difference`) pos, neg)+  where+    prob = SimpleProblem vs (not . f)+    opt = def+      { optMaximalInterestingSets = Set.map (vs `IntSet.difference`) cs+      , optMinimalUninterestingSets = ds+      }+    (pos,neg) = runIdentity $ run prob opt  minimalHittingSets :: Set IntSet -> Set IntSet minimalHittingSets = Set.fromList . enumMinimalHittingSets@@ -123,8 +135,8 @@     loop cs =       case findPrimeImplicateOrPrimeImplicant vs f cs dnf of         Nothing -> []-        Just (Left c)  -> c : loop (Set.insert c cs)-        Just (Right _) -> error "GurvichKhachiyan1999.enumMinimalHittingSets: should not happen"+        Just (Implicate c)  -> c : loop (Set.insert c cs)+        Just (Implicant _) -> error "GurvichKhachiyan1999.enumMinimalHittingSets: should not happen"  evalDNF :: Set IntSet -> IntSet -> Bool evalDNF dnf xs = or [is `IntSet.isSubsetOf` xs | is <- Set.toList dnf]@@ -137,11 +149,11 @@ f = Set.fromList $ map IntSet.fromList [[2,4,7], [7,8], [9]] g = Set.fromList $ map IntSet.fromList [[7,9], [4,8,9], [2,8,9]] -testA1, testA2, testA3, testA4 :: Maybe (Either IntSet IntSet)+testA1, testA2, testA3, testA4 :: Maybe ImplicateOrImplicant testA1 = findPrimeImplicateOrPrimeImplicant (IntSet.fromList [2,4,7,8,9]) (evalDNF f) Set.empty f  testA2 = findPrimeImplicateOrPrimeImplicant (IntSet.fromList [2,4,7,8,9]) (evalDNF f) (Set.singleton (IntSet.fromList [2,8,9])) f testA3 = findPrimeImplicateOrPrimeImplicant (IntSet.fromList [2,4,7,8,9]) (evalDNF f) (Set.fromList [IntSet.fromList [2,8,9], IntSet.fromList [4,8,9]]) f testA4 = findPrimeImplicateOrPrimeImplicant (IntSet.fromList [2,4,7,8,9]) (evalDNF f) (Set.fromList [IntSet.fromList [2,8,9], IntSet.fromList [4,8,9], IntSet.fromList [7,9]]) f -testB1 :: Maybe (Either IntSet IntSet)+testB1 :: Maybe ImplicateOrImplicant testB1 = findPrimeImplicateOrPrimeImplicant (IntSet.fromList [2,4,7,8,9]) (evalDNF f) g Set.empty
+ src/ToySolver/Combinatorial/HittingSet/InterestingSets.hs view
@@ -0,0 +1,181 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MultiParamTypeClasses #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Combinatorial.HittingSet.InterestingSets+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable+--+-- * D. Gunopulos, H. Mannila, R. Khardon, and H. Toivonen, Data mining,+--   hypergraph transversals, and machine learning (extended abstract),+--   in Proceedings of the Sixteenth ACM SIGACT-SIGMOD-SIGART Symposium+--   on Principles of Database Systems, ser. PODS '97. 1997, pp. 209-216.+--   <http://almaden.ibm.com/cs/projects/iis/hdb/Publications/papers/pods97_trans.pdf>+--+-----------------------------------------------------------------------------+module ToySolver.Combinatorial.HittingSet.InterestingSets+  (+  -- * Problem definition+    IsProblem (..)+  , InterestingOrUninterestingSet (..)+  , defaultGrow+  , defaultShrink+  , defaultMaximalInterestingSet+  , defaultMinimalUninterestingSet+  , defaultMinimalUninterestingSetOrMaximalInterestingSet+  , SimpleProblem (..)++  -- * Options for maximal interesting sets enumeration+  , Options (..)++  -- * Datatype for monotone CNF/DNF dualization+  , ImplicateOrImplicant (..)+  ) where++import Control.Monad+import Data.Default.Class+import Data.IntSet (IntSet)+import qualified Data.IntSet as IntSet+import Data.Set (Set)+import qualified Data.Set as Set+import qualified ToySolver.Combinatorial.HittingSet.Simple as HTC++data InterestingOrUninterestingSet+  = UninterestingSet IntSet+  | InterestingSet IntSet+  deriving (Eq, Ord, Show, Read)++-- | A problem is essentially a pair of an @IntSet@ (@universe@) and+-- a monotone pure function @IntSet -> Bool@ (@isInteresting@), but+-- we generalize a bit for potentialial optimization opportunity.+--+-- For simple cases you can just use 'SimpleProblem' instance.+class Monad m => IsProblem prob m | prob -> m where+  universe :: prob -> IntSet++  -- | Interesting sets are lower closed subsets of 'universe', i.e. if @xs@ is+  -- interesting then @ys@ ⊆ @xs@ is also interesting.+  isInteresting :: prob -> IntSet -> m Bool+  isInteresting prob xs = do+    ret <- isInteresting' prob xs+    return $!+      case ret of+        InterestingSet _ -> True+        UninterestingSet _ -> False++  -- | If @xs@ is interesting it returns @InterestingSet ys@ where @ys@ is an interesting superset of @xs@.+  -- If @xs@ is uninteresting it returns @UninterestingSet ys@ where @ys@ is an uninteresting subset of @xs@.+  isInteresting' :: prob -> IntSet -> m InterestingOrUninterestingSet+  isInteresting' prob xs = do+    b <- isInteresting prob xs+    return $ if b then InterestingSet xs else UninterestingSet xs++  -- | @grow xs@ computes maximal interesting set @ys@ that is a superset of @xs@.+  grow :: prob -> IntSet -> m IntSet+  grow = defaultGrow++  -- | @shrink xs@ computes minimal uninteresting set @ys@ that is a subset of @xs@.+  shrink :: prob -> IntSet -> m IntSet+  shrink = defaultShrink++  -- | If @xs@ is an interesting set @maximalInterestingSet prob xs@ returns @Just ys@+  -- such that @ys@ is a maximal interesting superset of @xs@, otherwise it returns @Nothing@.+  maximalInterestingSet :: prob -> IntSet -> m (Maybe IntSet)+  maximalInterestingSet = defaultMaximalInterestingSet++  -- | If @xs@ is an uninteresting set @minimalUninterestingSet prob xs@ returns @Just ys@+  -- such that @ys@ is a minimal uninteresting subset of @xs@, otherwise it returns @Nothing@.+  minimalUninterestingSet :: prob -> IntSet -> m (Maybe IntSet)+  minimalUninterestingSet = defaultMinimalUninterestingSet++  -- | If @xs@ is an uninteresting set @minimalUninterestingSetOrMaximalInterestingSet prob xs@ returns @Left ys@+  -- such that @ys@ is a minimal uninteresting subset of @xs@.+  -- If @xs@ is an interesting set @minimalUninterestingSetOrMaximalInterestingSet prob xs@ returns @Right ys@+  -- such that @ys@ is a maximal interesting superset of @xs@+  minimalUninterestingSetOrMaximalInterestingSet :: prob -> IntSet -> m InterestingOrUninterestingSet+  minimalUninterestingSetOrMaximalInterestingSet = defaultMinimalUninterestingSetOrMaximalInterestingSet++  {-# MINIMAL universe, (isInteresting | isInteresting') #-}++-- | Default implementation of 'grow' using 'isInteresting''.+defaultGrow :: IsProblem prob m => prob -> IntSet -> m IntSet+defaultGrow prob xs = foldM f xs (IntSet.toList (universe prob `IntSet.difference` xs))+  where+    f xs' y = do+      ret <- isInteresting' prob (IntSet.insert y xs')+      case ret of+        UninterestingSet _ -> return xs'+        InterestingSet xs'' -> return xs''++-- | Default implementation of 'shrink' using 'isInteresting''.+defaultShrink :: IsProblem prob m => prob -> IntSet -> m IntSet+defaultShrink prob xs = foldM f xs (IntSet.toList xs)+  where+    f xs' y = do+      ret <- isInteresting' prob (IntSet.delete y xs')+      case ret of+        UninterestingSet xs'' -> return xs''+        InterestingSet _ -> return xs'++-- | Default implementation of 'maximalUninterestingSet' using 'isInteresting'' and 'grow'.+defaultMaximalInterestingSet :: IsProblem prob m => prob -> IntSet -> m (Maybe IntSet)+defaultMaximalInterestingSet prob xs = do+ ret <- isInteresting' prob xs+ case ret of+   UninterestingSet _ -> return Nothing+   InterestingSet xs' -> liftM Just $ grow prob xs'++-- | Default implementation of 'minimalUninterestingSet' using 'isInteresting'' and 'shrink'.+defaultMinimalUninterestingSet :: IsProblem prob m => prob -> IntSet -> m (Maybe IntSet)+defaultMinimalUninterestingSet prob xs = do+ ret <- isInteresting' prob xs+ case ret of+   UninterestingSet xs' -> liftM Just $ shrink prob xs'+   InterestingSet _ -> return Nothing++-- | Default implementation of 'minimalUninterestingSetOrMaximalInterestingSet' using 'isInteresting'', 'shrink' 'grow'.+defaultMinimalUninterestingSetOrMaximalInterestingSet+  :: IsProblem prob m => prob -> IntSet -> m InterestingOrUninterestingSet+defaultMinimalUninterestingSetOrMaximalInterestingSet prob xs = do+ ret <- isInteresting' prob xs+ case ret of+   UninterestingSet ys -> liftM UninterestingSet $ shrink prob ys+   InterestingSet ys -> liftM InterestingSet $ grow prob ys++data SimpleProblem (m :: * -> *) = SimpleProblem IntSet (IntSet -> Bool)++instance Monad m => IsProblem (SimpleProblem m) m where+  universe (SimpleProblem univ _) = univ+  isInteresting (SimpleProblem _ f) = return . f++data Options m+  = Options+  { optMinimalHittingSets :: Set IntSet -> m (Set IntSet)+  , optMaximalInterestingSets :: Set IntSet+  , optMinimalUninterestingSets :: Set IntSet+  , optOnMaximalInterestingSetFound :: IntSet -> m ()+  , optOnMinimalUninterestingSetFound :: IntSet -> m ()+  }++instance Monad m => Default (Options m) where+  def =+    Options+    { optMinimalHittingSets = return . HTC.minimalHittingSets+    , optMaximalInterestingSets = Set.empty+    , optMinimalUninterestingSets = Set.empty+    , optOnMaximalInterestingSetFound = \_ -> return ()+    , optOnMinimalUninterestingSetFound = \_ -> return ()+    }+++data ImplicateOrImplicant+  = Implicate IntSet+  | Implicant IntSet+  deriving (Eq, Ord, Show, Read)
+ src/ToySolver/Combinatorial/HittingSet/MARCO.hs view
@@ -0,0 +1,117 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE ScopedTypeVariables #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Combinatorial.HittingSet.MARCO+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable+--+-- * M. Liffiton and A. Malik, "Enumerating infeasibility: Finding multiple+--   MUSes quickly," in Integration of AI and OR Techniques in Constraint+--   Programming for Combinatorial Optimization Problems, C. Gomes and+--   M. Sellmann, Eds. pp. 160-175.+--   <http://sun.iwu.edu/~mliffito/publications/cpaior13_liffiton_MARCO.pdf>+--+-----------------------------------------------------------------------------+module ToySolver.Combinatorial.HittingSet.MARCO+  (+  -- * Problem definition+    module ToySolver.Combinatorial.HittingSet.InterestingSets++  -- * Main functionality+  , run++  -- * Applications: monotone boolean functions+  , generateCNFAndDNF++  -- * Applicaitons: minimal hitting sets+  , minimalHittingSets+  ) where++import Control.Monad+import Data.Default.Class+import Data.IntMap ((!))+import qualified Data.IntMap as IntMap+import Data.IntSet (IntSet)+import qualified Data.IntSet as IntSet+import Data.IORef+import Data.Set (Set)+import qualified Data.Set as Set+import System.IO.Unsafe+import ToySolver.Combinatorial.HittingSet.InterestingSets+import qualified ToySolver.SAT as SAT++-- | Given a problem and an option, it computes maximal interesting sets and+-- minimal uninteresting sets.+run :: forall prob. IsProblem prob IO => prob -> Options IO -> IO (Set IntSet, Set IntSet)+run prob opt = do+  solver <- SAT.newSolver+  item2var <- liftM IntMap.fromList $ forM (IntSet.toList (universe prob)) $ \item -> do+    v <- SAT.newVar solver+    return (item,v)+  let blockUp xs = SAT.addClause solver [-(item2var ! x) | x <- IntSet.toList xs]+      blockDown xs = SAT.addClause solver [item2var ! x | x <- IntSet.toList (universe prob `IntSet.difference` xs)]+  posRef <- newIORef $ Set.toList $ optMaximalInterestingSets opt+  negRef <- newIORef $ Set.toList $ optMinimalUninterestingSets opt+  mapM_ blockUp $ Set.toList $ optMinimalUninterestingSets opt+  mapM_ blockDown $ Set.toList $ optMaximalInterestingSets opt+  let loop = do+        ret <- SAT.solve solver+        if not ret then+          return ()+        else do+          model <- SAT.getModel solver+          let xs = IntMap.keysSet $ IntMap.filter (SAT.evalLit model) item2var+          ret2 <- minimalUninterestingSetOrMaximalInterestingSet prob xs+          case ret2 of+            UninterestingSet ys -> do+              blockUp ys+              modifyIORef negRef (ys :)+              optOnMinimalUninterestingSetFound opt ys+            InterestingSet ys -> do+              blockDown ys+              modifyIORef posRef (ys :)+              optOnMaximalInterestingSetFound opt ys+          loop+  loop+  pos <- readIORef posRef+  neg <- readIORef negRef+  return (Set.fromList pos, Set.fromList neg)++-- | Compute the irredundant CNF representation and DNF representation.+--+-- Let /f/ be a monotone boolean function over set of variables /S/.+-- This function returns /C/ and /D/ where ∧_{I∈C} ∨_{i∈I} x_i and+-- ∨_{I∈D} ∧_{i∈I} x_i are the irredundant CNF representation /f/ and+-- DNF representation of /f/ respectively.+generateCNFAndDNF+  :: IntSet -- ^ Set of variables /V/+  -> (IntSet -> Bool) -- ^ A monotone boolean function /f/ from /{0,1}^|V| ≅ P(V)/ to @Bool@+  -> Set IntSet -- ^ Subset /C'/ of prime implicates /C/ of /f/+  -> Set IntSet -- ^ Subset /D'/ of prime implicants /D/ of /f/+  -> (Set IntSet, Set IntSet)+generateCNFAndDNF vs f cs ds = unsafeDupablePerformIO $ do+  (pos,neg) <- run prob opt+  return (Set.map (vs `IntSet.difference`) pos, neg)+  where+    prob = SimpleProblem vs (not . f)+    opt = def+      { optMaximalInterestingSets = Set.map (vs `IntSet.difference`) cs+      , optMinimalUninterestingSets = ds+      }++minimalHittingSets :: Set IntSet -> Set IntSet+minimalHittingSets xss = +  case generateCNFAndDNF (IntSet.unions $ Set.toList xss) (evalDNF xss) Set.empty xss of+    (yss, _) -> yss++evalDNF :: Set IntSet -> IntSet -> Bool+evalDNF dnf xs = or [is `IntSet.isSubsetOf` xs | is <- Set.toList dnf]
src/ToySolver/Combinatorial/HittingSet/Simple.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ScopedTypeVariables, BangPatterns #-}+{-# OPTIONS_GHC -Wall #-} ----------------------------------------------------------------------------- -- | -- Module      :  ToySolver.Combinatorial.HittingSet.Simple@@ -18,9 +18,9 @@ import Control.Monad import Data.IntSet (IntSet) import qualified Data.IntSet as IntSet-import Data.List import Data.Set (Set) import qualified Data.Set as Set+import ToySolver.Combinatorial.HittingSet.Util (maintainNoSupersets)  minimalHittingSets :: Set IntSet -> Set IntSet minimalHittingSets = Set.fromList . minimalHittingSets' . Set.toList@@ -47,14 +47,6 @@     xs = filter (v `IntSet.notMember`) es     ys = map (IntSet.filter (v <) . (`IntSet.difference` e)) xs     zs = maintainNoSupersets ys--maintainNoSupersets :: [IntSet] -> [IntSet]-maintainNoSupersets xss = go [] xss-  where-    go yss [] = yss-    go yss (xs:xss) = go (xs : filter p yss) (filter p xss)-      where-        p zs = not (xs `IntSet.isSubsetOf` zs)  nubOrd :: Ord a => [a] -> [a] nubOrd = go Set.empty
+ src/ToySolver/Combinatorial/HittingSet/Util.hs view
@@ -0,0 +1,26 @@+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Combinatorial.HittingSet.Util+-- Copyright   :  (c) Masahiro Sakai 2012-2014+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  portable+--+-----------------------------------------------------------------------------+module ToySolver.Combinatorial.HittingSet.Util+  ( maintainNoSupersets+  ) where++import Data.IntSet (IntSet)+import qualified Data.IntSet as IntSet++maintainNoSupersets :: [IntSet] -> [IntSet]+maintainNoSupersets xss = go [] xss+  where+    go yss [] = yss+    go yss (xs:xss) = go (xs : filter p yss) (filter p xss)+      where+        p zs = not (xs `IntSet.isSubsetOf` zs)
+ src/ToySolver/Converter/GCNF2MaxSAT.hs view
@@ -0,0 +1,37 @@+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Converter.GCNF2MaxSAT+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+-- Portability :  portable+--+-----------------------------------------------------------------------------+module ToySolver.Converter.GCNF2MaxSAT+  ( convert+  ) where++import qualified ToySolver.Text.GCNF as GCNF+import qualified ToySolver.Text.MaxSAT as MaxSAT++convert :: GCNF.GCNF -> MaxSAT.WCNF+convert+  GCNF.GCNF+  { GCNF.numVars        = nv+  , GCNF.numClauses     = nc+  , GCNF.lastGroupIndex = lastg+  , GCNF.clauses        = cs+  }+  =+  MaxSAT.WCNF+  { MaxSAT.topCost = top+  , MaxSAT.clauses = [(top, if g==0 then c else -(nv+g) : c) | (g,c) <- cs] ++ [(1,[v]) | v <- [nv+1..nv+lastg]]+  , MaxSAT.numVars = nv + lastg+  , MaxSAT.numClauses = nc + lastg+  }+  where+    top :: MaxSAT.Weight+    top = fromIntegral (lastg + 1)
+ src/ToySolver/Converter/MIP2PB.hs view
@@ -0,0 +1,136 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE MultiParamTypeClasses #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Converter.MIP2PB+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+--+-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+-- Portability :  non-portable (MultiParamTypeClasses)+--+-----------------------------------------------------------------------------+module ToySolver.Converter.MIP2PB+  ( convert+  , addMIP+  ) where++import Control.Monad+import Control.Monad.ST+import Control.Monad.Trans+import Control.Monad.Trans.Except+import Data.List (intercalate, foldl', sortBy)+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Ord+import Data.Ratio+import qualified Data.Set as Set+import Data.VectorSpace++import qualified Data.PseudoBoolean as PBFile+import qualified ToySolver.Data.MIP as MIP+import ToySolver.Data.OrdRel+import qualified ToySolver.SAT.Types as SAT+import qualified ToySolver.SAT.Encoder.Integer as Integer+import ToySolver.SAT.Store.PB+import ToySolver.Internal.Util (revForM)++-- -----------------------------------------------------------------------------++convert :: MIP.Problem Rational -> Either String (PBFile.Formula, Integer -> Rational, SAT.Model -> Map MIP.Var Integer)+convert mip = runST $ runExceptT $ m+  where+    m :: ExceptT String (ST s) (PBFile.Formula, Integer -> Rational, SAT.Model -> Map MIP.Var Integer)+    m = do+      db <- lift $ newPBStore+      (Integer.Expr obj, otrans, mtrans) <- addMIP' db mip+      formula <- lift $ getPBFormula db+      return $ (formula{ PBFile.pbObjectiveFunction = Just obj }, otrans, mtrans)++-- -----------------------------------------------------------------------------++addMIP :: SAT.AddPBNL m enc => enc -> MIP.Problem Rational -> m (Either String (Integer.Expr, Integer -> Rational, SAT.Model -> Map MIP.Var Integer))+addMIP enc mip = runExceptT $ addMIP' enc mip++addMIP' :: SAT.AddPBNL m enc => enc -> MIP.Problem Rational -> ExceptT String m (Integer.Expr, Integer -> Rational, SAT.Model -> Map MIP.Var Integer)+addMIP' enc mip = do+  if not (Set.null nivs) then do+    throwE $ "cannot handle non-integer variables: " ++ intercalate ", " (map MIP.fromVar (Set.toList nivs))+  else do+    vmap <- liftM Map.fromList $ revForM (Set.toList ivs) $ \v -> do+      case MIP.getBounds mip v of+        (MIP.Finite lb, MIP.Finite ub) -> do+          v2 <- lift $ Integer.newVar enc (ceiling lb) (floor ub)+          return (v,v2)+        _ -> do+          throwE $ "cannot handle unbounded variable: " ++ MIP.fromVar v+    forM_ (MIP.constraints mip) $ \c -> do+      let lhs = MIP.constrExpr c+      let f op rhs = do+            let d = foldl' lcm 1 (map denominator  (rhs:[r | MIP.Term r _ <- MIP.terms lhs]))+                lhs' = sumV [asInteger (r * fromIntegral d) *^ product [vmap Map.! v | v <- vs] | MIP.Term r vs <- MIP.terms lhs]+                rhs' = asInteger (rhs * fromIntegral d)+                c2 = case op of+                       MIP.Le  -> lhs' .<=. fromInteger rhs'+                       MIP.Ge  -> lhs' .>=. fromInteger rhs'+                       MIP.Eql -> lhs' .==. fromInteger rhs'+            case MIP.constrIndicator c of+              Nothing -> lift $ Integer.addConstraint enc c2+              Just (var, val) -> do+                let var' = asBin (vmap Map.! var)+                case val of+                  1 -> lift $ Integer.addConstraintSoft enc var' c2+                  0 -> lift $ Integer.addConstraintSoft enc (SAT.litNot var') c2+                  _ -> return ()+      case (MIP.constrLB c, MIP.constrUB c) of+        (MIP.Finite x1, MIP.Finite x2) | x1==x2 -> f MIP.Eql x2+        (lb, ub) -> do+          case lb of+            MIP.NegInf -> return ()+            MIP.Finite x -> f MIP.Ge x+            MIP.PosInf -> lift $ SAT.addClause enc []+          case ub of+            MIP.NegInf -> lift $ SAT.addClause enc []+            MIP.Finite x -> f MIP.Le x+            MIP.PosInf -> return ()++    forM_ (MIP.sosConstraints mip) $ \MIP.SOSConstraint{ MIP.sosType = typ, MIP.sosBody = xs } -> do+      case typ of+        MIP.S1 -> lift $ SAT.addAtMost enc (map (asBin . (vmap Map.!) . fst) xs) 1+        MIP.S2 -> do+          let ps = nonAdjacentPairs $ map fst $ sortBy (comparing snd) $ xs+          forM_ ps $ \(x1,x2) -> do+            lift $ SAT.addClause enc [SAT.litNot $ asBin $ vmap Map.! v | v <- [x1,x2]]++    let obj = MIP.objectiveFunction mip+        d = foldl' lcm 1 [denominator r | MIP.Term r _ <- MIP.terms (MIP.objExpr obj)] *+            (if MIP.objDir obj == MIP.OptMin then 1 else -1)+        obj2 = sumV [asInteger (r * fromIntegral d) *^ product [vmap Map.! v | v <- vs] | MIP.Term r vs <- MIP.terms (MIP.objExpr obj)]++    let transformObjVal :: Integer -> Rational+        transformObjVal val = fromIntegral val / fromIntegral d++        transformModel :: SAT.Model -> Map MIP.Var Integer+        transformModel m = Map.fromList+          [ (v, Integer.eval m (vmap Map.! v)) | v <- Set.toList ivs ]++    return (obj2, transformObjVal, transformModel)+  where+    ivs = MIP.integerVariables mip+    nivs = MIP.variables mip `Set.difference` ivs++    asInteger :: Rational -> Integer+    asInteger r+      | denominator r /= 1 = error (show r ++ " is not integer")+      | otherwise = numerator r++    nonAdjacentPairs :: [a] -> [(a,a)]+    nonAdjacentPairs (x1:x2:xs) = [(x1,x3) | x3 <- xs] ++ nonAdjacentPairs (x2:xs)+    nonAdjacentPairs _ = []++    asBin :: Integer.Expr -> SAT.Lit+    asBin (Integer.Expr [(1,[lit])]) = lit+    asBin _ = error "asBin: failure"++-- -----------------------------------------------------------------------------
src/ToySolver/Converter/MIP2SMT.hs view
@@ -1,13 +1,14 @@ {-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE OverloadedStrings #-} ----------------------------------------------------------------------------- -- | -- Module      :  ToySolver.Converter.MIP2SMT--- Copyright   :  (c) Masahiro Sakai 2012-2014+-- Copyright   :  (c) Masahiro Sakai 2012-2014,2016 -- License     :  BSD-style --  -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  experimental--- Portability :  portable+-- Portability :  non-portable (OverloadedStrings) -- ----------------------------------------------------------------------------- module ToySolver.Converter.MIP2SMT@@ -19,13 +20,19 @@  import Data.Char import Data.Default.Class+import Data.Interned import Data.Ord import Data.List+import Data.Monoid import Data.Ratio import qualified Data.Set as Set import Data.Map (Map) import qualified Data.Map as Map-import System.IO+import qualified Data.Text as T+import qualified Data.Text.Lazy.IO as TLIO+import Data.Text.Lazy.Builder (Builder)+import qualified Data.Text.Lazy.Builder as B+import qualified Data.Text.Lazy.Builder.Int as B import Text.Printf  import qualified ToySolver.Data.MIP as MIP@@ -66,117 +73,111 @@  -- ------------------------------------------------------------------------ -type Var = String+type Var = T.Text type Env = Map MIP.Var Var -concatS :: [ShowS] -> ShowS-concatS = foldr (.) id- -unlinesS :: [ShowS] -> ShowS-unlinesS = concatS . map (. showChar '\n')--list :: [ShowS] -> ShowS-list xs = showParen True $ concatS (intersperse (showChar ' ') xs)+list :: [Builder] -> Builder+list xs = B.singleton '(' <> mconcat (intersperse (B.singleton ' ') xs) <> B.singleton ')' -and' :: [ShowS] -> ShowS-and' [] = showString "true"+and' :: [Builder] -> Builder+and' [] = "true" and' [x] = x-and' xs = list (showString "and" : xs)+and' xs = list ("and" : xs) -or' :: [ShowS] -> ShowS-or' [] = showString "false"+or' :: [Builder] -> Builder+or' [] = "false" or' [x] = x-or' xs = list (showString "or" : xs)+or' xs = list ("or" : xs) -not' :: ShowS -> ShowS-not' x = list [showString "not", x]+not' :: Builder -> Builder+not' x = list ["not", x] -intExpr :: Options -> Env -> MIP.Problem -> MIP.Expr -> ShowS+intExpr :: Options -> Env -> MIP.Problem Rational -> MIP.Expr Rational -> Builder intExpr opt env _mip e =   case MIP.terms e of     [] -> intNum opt 0     [t] -> f t-    ts -> list (showChar '+' : map f ts)+    ts -> list (B.singleton '+' : map f ts)   where     f (MIP.Term c _) | not (isInteger c) =       error ("ToySolver.Converter.MIP2SMT.intExpr: fractional coefficient: " ++ show c)     f (MIP.Term c []) = intNum opt (floor c)-    f (MIP.Term (-1) vs) = list [showChar '-', f (MIP.Term 1 vs)]+    f (MIP.Term (-1) vs) = list [B.singleton '-', f (MIP.Term 1 vs)]     f (MIP.Term c vs) =       case xs of         [] -> intNum opt 1         [x] -> x-        _ -> list (showChar '*' : xs)+        _ -> list (B.singleton '*' : xs)       where         xs = [intNum opt (floor c) | c /= 1] ++-             [showString (env Map.! v) | v <- vs]+             [B.fromText (env Map.! v) | v <- vs] -realExpr :: Options -> Env -> MIP.Problem -> MIP.Expr -> ShowS+realExpr :: Options -> Env -> MIP.Problem Rational -> MIP.Expr Rational -> Builder realExpr opt env mip e =   case MIP.terms e of     [] -> realNum opt 0     [t] -> f t-    ts -> list (showChar '+' : map f ts)+    ts -> list (B.singleton '+' : map f ts)   where     f (MIP.Term c []) = realNum opt c-    f (MIP.Term (-1) vs) = list [showChar '-', f (MIP.Term 1 vs)]+    f (MIP.Term (-1) vs) = list [B.singleton '-', f (MIP.Term 1 vs)]     f (MIP.Term c vs) =       case xs of         [] -> realNum opt 1         [x] -> x-        _ -> list (showChar '*' : xs)+        _ -> list (B.singleton '*' : xs)       where         xs = [realNum opt c | c /= 1] ++              [ v3              | v <- vs              , let v2 = env Map.! v              , let v3 = if isInt mip v-                        then toReal opt (showString v2)-                        else showString v2+                        then toReal opt (B.fromText v2)+                        else B.fromText v2              ] -intNum :: Options -> Integer -> ShowS+intNum :: Options -> Integer -> Builder intNum opt x =   case optLanguage opt of     SMTLIB2-      | x < 0     -> list [showChar '-', shows (negate x)]-      | otherwise -> shows x-    YICES _ -> shows x+      | x < 0     -> list [B.singleton '-', B.decimal (negate x)]+      | otherwise -> B.decimal x+    YICES _ -> B.decimal x -realNum :: Options -> Rational -> ShowS+realNum :: Options -> Rational -> Builder realNum opt r =   case optLanguage opt of     SMTLIB2-      | r < 0     -> list [showChar '-', f (negate r)]+      | r < 0     -> list [B.singleton '-', f (negate r)]       | otherwise -> f r     YICES Yices1 ->       if denominator r == 1-        then shows (numerator r)-        else shows (numerator r) . showChar '/' . shows (denominator r)+        then B.decimal (numerator r)+        else B.decimal (numerator r) <> B.singleton '/' <> B.decimal (denominator r)     YICES Yices2 ->       case showRationalAsFiniteDecimal r of-        Just s  -> showString s-        Nothing -> shows (numerator r) . showChar '/' . shows (denominator r)+        Just s  -> B.fromString s+        Nothing -> B.decimal (numerator r) <> B.singleton '/' <> B.decimal (denominator r)   where     f r = case showRationalAsFiniteDecimal r of-            Just s  -> showString s-            Nothing -> list [showChar '/', shows (numerator r) . showString ".0", shows (denominator r) . showString ".0"]+            Just s  -> B.fromString s+            Nothing -> list [B.singleton '/', B.decimal (numerator r) <> ".0", B.decimal (denominator r) <> ".0"] -rel2 :: Options -> Env -> MIP.Problem -> Bool -> MIP.BoundExpr -> MIP.Expr -> MIP.BoundExpr -> ShowS+rel2 :: Options -> Env -> MIP.Problem Rational -> Bool -> MIP.BoundExpr Rational -> MIP.Expr Rational -> MIP.BoundExpr Rational -> Builder rel2 opt env mip q lb e ub = and' (c1 ++ c2)   where     c1 =       case lb of         MIP.NegInf -> []         MIP.Finite x -> [rel opt env mip q MIP.Ge e x]-        MIP.PosInf -> [showString "false"]+        MIP.PosInf -> ["false"]     c2 =       case ub of-        MIP.NegInf -> [showString "false"]+        MIP.NegInf -> ["false"]         MIP.Finite x -> [rel opt env mip q MIP.Le e x]         MIP.PosInf -> [] -rel :: Options -> Env -> MIP.Problem -> Bool -> MIP.RelOp -> MIP.Expr -> Rational -> ShowS+rel :: Options -> Env -> MIP.Problem Rational -> Bool -> MIP.RelOp -> MIP.Expr Rational -> Rational -> Builder rel opt env mip q op lhs rhs   | and [isInt mip v | v <- Set.toList (MIP.vars lhs)] &&     and [isInteger c | MIP.Term c _ <- MIP.terms lhs] && isInteger rhs =@@ -184,31 +185,31 @@   | otherwise =       f q op (realExpr opt env mip lhs) (realNum opt rhs)   where-    f :: Bool -> MIP.RelOp -> ShowS -> ShowS -> ShowS+    f :: Bool -> MIP.RelOp -> Builder -> Builder -> Builder     f True MIP.Eql x y = and' [f False MIP.Le x y, f False MIP.Ge x y]-    f _ MIP.Eql x y = list [showString "=", x, y]-    f _ MIP.Le x y = list [showString "<=", x, y]-    f _ MIP.Ge x y = list [showString ">=", x, y]+    f _ MIP.Eql x y = list ["=", x, y]+    f _ MIP.Le x y = list ["<=", x, y]+    f _ MIP.Ge x y = list [">=", x, y] -toReal :: Options -> ShowS -> ShowS+toReal :: Options -> Builder -> Builder toReal opt x =   case optLanguage opt of-    SMTLIB2 -> list [showString "to_real", x]+    SMTLIB2 -> list ["to_real", x]     YICES _ -> x -assert :: Options -> (ShowS, Maybe String) -> ShowS-assert opt (x, label) = list [showString "assert", x']+assert :: Options -> (Builder, Maybe T.Text) -> Builder+assert opt (x, label) = list ["assert", x']   where     x' = case label of            Just name | optLanguage opt == SMTLIB2 ->-             list [ showString "!"+             list [ "!"                   , x-                  , showString ":named"-                  , showString (encode opt name)+                  , ":named"+                  , B.fromText (encode opt name)                   ]            _ -> x -constraint :: Options -> Bool -> Env -> MIP.Problem -> MIP.Constraint -> (ShowS, Maybe String)+constraint :: Options -> Bool -> Env -> MIP.Problem Rational -> MIP.Constraint Rational -> (Builder, Maybe T.Text) constraint opt q env mip   MIP.Constraint   { MIP.constrLabel     = label@@ -222,12 +223,12 @@     c1 = case g of            Nothing -> c0            Just (var,val) ->-             list [ showString "=>"+             list [ "=>"                   , rel opt env mip q MIP.Eql (MIP.varExpr var) val                   , c0                   ] -conditions :: Options -> Bool -> Env -> MIP.Problem -> [(ShowS, Maybe String)]+conditions :: Options -> Bool -> Env -> MIP.Problem Rational -> [(Builder, Maybe T.Text)] conditions opt q env mip = bnds ++ cs ++ ss   where     vs = MIP.variables mip@@ -245,11 +246,11 @@             -- Supported solvers: cvc4-1.1, yices-2.2.1, z3-4.3.0             -- Unsupported solvers: z3-4.0             SMTLIB2-              | lb == MIP.PosInf || ub == MIP.NegInf -> showString "false"-              | length args >= 2 -> list (showString "<=" : args)-              | otherwise -> showString "true"+              | lb == MIP.PosInf || ub == MIP.NegInf -> "false"+              | length args >= 2 -> list ("<=" : args)+              | otherwise -> "true"                   where-                    args = lb2 ++ [showString v2] ++ ub2+                    args = lb2 ++ [B.fromText v2] ++ ub2                     lb2 = case lb of                             MIP.NegInf -> []                             MIP.PosInf -> error "should not happen"@@ -266,24 +267,24 @@               where                 s1 = case lb of                        MIP.NegInf -> []-                       MIP.PosInf -> [showString "false"]+                       MIP.PosInf -> ["false"]                        MIP.Finite x ->                          if isInt mip v-                         then [list [showString "<=", intNum opt (ceiling x), showString v2]]-                         else [list [showString "<=", realNum opt x, showString v2]]+                         then [list ["<=", intNum opt (ceiling x), B.fromText v2]]+                         else [list ["<=", realNum opt x, B.fromText v2]]                 s2 = case ub of-                       MIP.NegInf -> [showString "false"]+                       MIP.NegInf -> ["false"]                        MIP.PosInf -> []                        MIP.Finite x ->                          if isInt mip v-                         then [list [showString "<=", showString v2, intNum opt (floor x)]]-                         else [list [showString "<=", showString v2, realNum opt x]]+                         then [list ["<=", B.fromText v2, intNum opt (floor x)]]+                         else [list ["<=", B.fromText v2, realNum opt x]]          c1 = case MIP.getVarType mip v of                MIP.SemiContinuousVariable ->-                 or' [list [showString "=", showString v2, realNum opt 0], c0]+                 or' [list ["=", B.fromText v2, realNum opt 0], c0]                MIP.SemiIntegerVariable ->-                 or' [list [showString "=", showString v2, intNum opt 0], c0]+                 or' [list ["=", B.fromText v2, intNum opt 0], c0]                _ ->                  c0 @@ -294,12 +295,12 @@                     MIP.S1 -> pairs $ map fst xs                     MIP.S2 -> nonAdjacentPairs $ map fst $ sortBy (comparing snd) $ xs       let c = not' $ and'-            [ list [showString "/=", v3, realNum opt 0]+            [ list ["/=", v3, realNum opt 0]             | v<-[x1,x2]             , let v2 = env Map.! v             , let v3 = if isInt mip v-                       then toReal opt (showString v2)-                       else showString v2+                       then toReal opt (B.fromText v2)+                       else B.fromText v2             ]       return (c, label) @@ -311,14 +312,15 @@ nonAdjacentPairs (x1:x2:xs) = [(x1,x3) | x3 <- xs] ++ nonAdjacentPairs (x2:xs) nonAdjacentPairs _ = [] -convert :: Options -> MIP.Problem -> ShowS+convert :: Options -> MIP.Problem Rational -> Builder convert opt mip =-  unlinesS $ options ++ set_logic ++ defs ++ map (assert opt) (conditions opt False env mip)-             ++ [ assert opt (optimality, Nothing) | optOptimize opt ]-             ++ [ case optLanguage opt of-                    SMTLIB2 -> list [showString "check-sat"]-                    YICES _ -> list [showString "check"]-                | optCheckSAT opt ]+  mconcat $ map (<> B.singleton '\n') $+    options ++ set_logic ++ defs ++ map (assert opt) (conditions opt False env mip)+    ++ [ assert opt (optimality, Nothing) | optOptimize opt ]+    ++ [ case optLanguage opt of+           SMTLIB2 -> list ["check-sat"]+           YICES _ -> list ["check"]+       | optCheckSAT opt ]   where     vs = MIP.variables mip     real_vs = vs `Set.difference` int_vs@@ -333,63 +335,63 @@         YICES _ -> "int"     ts = [(v, realType) | v <- Set.toList real_vs] ++ [(v, intType) | v <- Set.toList int_vs]     obj = MIP.objectiveFunction mip-    env = Map.fromList [(v, encode opt (MIP.fromVar v)) | v <- Set.toList vs]+    env = Map.fromList [(v, encode opt (unintern v)) | v <- Set.toList vs]     -- Note that identifiers of LPFile does not contain '-'.     -- So that there are no name crash.-    env2 = Map.fromList [(v, encode opt (MIP.fromVar v ++ "-2")) | v <- Set.toList vs]+    env2 = Map.fromList [(v, encode opt (unintern v <> "-2")) | v <- Set.toList vs]      options =       [ case optLanguage opt of-          SMTLIB2 -> list [showString "set-option", showString ":produce-models", showString "true"]-          YICES _ -> list [showString "set-evidence!", showString "true"]+          SMTLIB2 -> list ["set-option", ":produce-models", "true"]+          YICES _ -> list ["set-evidence!", "true"]       | optProduceModel opt && optLanguage opt /= YICES Yices2       ]      set_logic =       case optSetLogic opt of-        Just logic | optLanguage opt == SMTLIB2 -> [list [showString "set-logic", showString logic]]+        Just logic | optLanguage opt == SMTLIB2 -> [list ["set-logic", B.fromString logic]]         _ -> []      defs = do       (v,t) <- ts       let v2 = env Map.! v-      return $ showString $+      return $         case optLanguage opt of-          SMTLIB2 -> printf "(declare-fun %s () %s)" v2 t-          YICES _ -> printf "(define %s::%s) ; %s"  v2 t (MIP.fromVar v)+          SMTLIB2 -> "(declare-fun " <> B.fromText v2 <> " () " <> B.fromString t <> ")"+          YICES _ -> "(define " <> B.fromText v2 <> "::" <> B.fromString t <> ") ; " <> B.fromString  (MIP.fromVar v) -    optimality = list [showString "forall", decl, body]+    optimality = list ["forall", decl, body]       where         decl =           case optLanguage opt of-            SMTLIB2 -> list [list [showString (env2 Map.! v), showString t] | (v,t) <- ts]-            YICES _ -> list [showString $ printf "%s::%s" (env2 Map.! v) t | (v,t) <- ts]-        body = list [showString "=>"+            SMTLIB2 -> list [list [B.fromText (env2 Map.! v), B.fromString t] | (v,t) <- ts]+            YICES _ -> list [B.fromText (env2 Map.! v) <> "::" <> B.fromString t | (v,t) <- ts]+        body = list ["=>"                     , and' (map fst (conditions opt True env2 mip))-                    , list [ showString $ if MIP.objDir obj == MIP.OptMin then "<=" else ">="+                    , list [ if MIP.objDir obj == MIP.OptMin then "<=" else ">="                            , realExpr opt env mip (MIP.objExpr obj), realExpr opt env2 mip (MIP.objExpr obj)                            ]                     ] -encode :: Options -> String -> String+encode :: Options -> T.Text -> T.Text encode opt s =    case optLanguage opt of     SMTLIB2-     | all p s   -> s-     | any q s   -> error $ "cannot encode " ++ show s-     | otherwise -> "|" ++ s ++ "|"-    YICES _ -> concatMap f s+     | T.all p s   -> s+     | T.any q s   -> error $ "cannot encode " ++ show s+     | otherwise -> "|" <> s <> "|"+    YICES _ -> T.concatMap f s   where-    p c = isAscii c && (isAlpha c || isDigit c || c `elem` "~!@$%^&*_-+=<>.?/")+    p c = isAscii c && (isAlpha c || isDigit c || c `elem` ("~!@$%^&*_-+=<>.?/" :: [Char]))     q c = c == '|' && c == '\\'      -- Note that '[', ']', '\\' does not appear in identifiers of LP file.     f '(' = "["     f ')' = "]"-    f c | c `elem` "/\";" = printf "\\x%02d" (fromEnum c :: Int)-    f c = [c]+    f c | c `elem` ("/\";" :: [Char]) = T.pack $ printf "\\x%02d" (fromEnum c :: Int)+    f c = T.singleton c -isInt :: MIP.Problem -> MIP.Var -> Bool+isInt :: MIP.Problem Rational -> MIP.Var -> Bool isInt mip v = vt == MIP.IntegerVariable || vt == MIP.SemiIntegerVariable   where     vt = MIP.getVarType mip v@@ -398,16 +400,14 @@  testFile :: FilePath -> IO () testFile fname = do-  result <- MIP.readLPFile fname-  case result of-    Right mip -> putStrLn $ convert def mip ""-    Left err -> hPrint stderr err+  mip <- MIP.readLPFile def fname+  TLIO.putStrLn $ B.toLazyText $ convert def (fmap toRational mip)  test :: IO ()-test = putStrLn $ convert def testdata ""+test = TLIO.putStrLn $ B.toLazyText $ convert def testdata -testdata :: MIP.Problem-Right testdata = MIP.parseLPString "test" $ unlines+testdata :: MIP.Problem Rational+Right testdata = fmap (fmap toRational) $ MIP.parseLPString def "test" $ unlines   [ "Maximize"   , " obj: x1 + 2 x2 + 3 x3 + x4"   , "Subject To"
src/ToySolver/Converter/MaxSAT2IP.hs view
@@ -17,9 +17,9 @@ import Data.Map (Map) import qualified ToySolver.Data.MIP as MIP import qualified ToySolver.Text.MaxSAT as MaxSAT-import ToySolver.SAT.Types+import qualified ToySolver.SAT.Types as SAT import qualified ToySolver.Converter.MaxSAT2WBO as MaxSAT2WBO import qualified ToySolver.Converter.PB2IP as PB2IP -convert :: Bool -> MaxSAT.WCNF -> (MIP.Problem, Map MIP.Var Rational -> Model)+convert :: Bool -> MaxSAT.WCNF -> (MIP.Problem Integer, SAT.Model -> Map MIP.Var Rational, Map MIP.Var Rational -> SAT.Model) convert useIndicator wcnf = PB2IP.convertWBO useIndicator (MaxSAT2WBO.convert wcnf)
− src/ToySolver/Converter/MaxSAT2NLPB.hs
@@ -1,35 +0,0 @@-{-# OPTIONS_GHC -Wall #-}--------------------------------------------------------------------------------- |--- Module      :  ToySolver.Converter.MaxSAT2NLPB--- Copyright   :  (c) Masahiro Sakai 2013--- License     :  BSD-style--- --- Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  experimental--- Portability :  portable----------------------------------------------------------------------------------module ToySolver.Converter.MaxSAT2NLPB-  ( convert-  ) where--import qualified Data.PseudoBoolean as PBFile-import qualified ToySolver.Text.MaxSAT as MaxSAT--convert :: MaxSAT.WCNF -> PBFile.Formula-convert-  MaxSAT.WCNF-  { MaxSAT.topCost = top-  , MaxSAT.clauses = cs-  , MaxSAT.numVars = nv-  } =-  PBFile.Formula-  { PBFile.pbObjectiveFunction = Just obj-  , PBFile.pbConstraints = cs2-  , PBFile.pbNumVars = nv-  , PBFile.pbNumConstraints = length 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]
src/ToySolver/Converter/PB2IP.hs view
@@ -26,8 +26,8 @@ import ToySolver.Data.MIP ((.==.), (.<=.), (.>=.)) import qualified ToySolver.SAT.Types as SAT -convert :: PBFile.Formula -> (MIP.Problem, Map MIP.Var Rational -> SAT.Model)-convert formula = (mip, mtrans (PBFile.pbNumVars formula))+convert :: PBFile.Formula -> (MIP.Problem Integer, SAT.Model -> Map MIP.Var Rational, Map MIP.Var Rational -> SAT.Model)+convert formula = (mip, mforth, mtrans (PBFile.pbNumVars formula))   where     mip = def       { MIP.objectiveFunction = obj2@@ -46,15 +46,18 @@     cs2 = do       (lhs,op,rhs) <- PBFile.pbConstraints formula       let (lhs2,c) = splitConst $ convExpr lhs-          rhs2 = fromIntegral rhs - c+          rhs2 = rhs - c       return $ case op of         PBFile.Ge -> def{ MIP.constrExpr = lhs2, MIP.constrLB = MIP.Finite rhs2 }         PBFile.Eq -> def{ MIP.constrExpr = lhs2, MIP.constrLB = MIP.Finite rhs2, MIP.constrUB = MIP.Finite rhs2 } -convExpr :: PBFile.Sum -> MIP.Expr+    mforth :: SAT.Model -> Map MIP.Var Rational+    mforth m = Map.fromList [(convVar v, if val then 1 else 0) | (v,val) <- assocs m]++convExpr :: PBFile.Sum -> MIP.Expr Integer convExpr s = sum [product (fromIntegral w : map f tm) | (w,tm) <- s]   where-    f :: PBFile.Lit -> MIP.Expr+    f :: PBFile.Lit -> MIP.Expr Integer     f x       | x > 0     = MIP.varExpr (convVar x)       | otherwise = 1 - MIP.varExpr (convVar (abs x))@@ -62,8 +65,8 @@ convVar :: PBFile.Var -> MIP.Var convVar x = MIP.toVar ("x" ++ show x) -convertWBO :: Bool -> PBFile.SoftFormula -> (MIP.Problem, Map MIP.Var Rational -> SAT.Model)-convertWBO useIndicator formula = (mip, mtrans (PBFile.wboNumVars formula))+convertWBO :: Bool -> PBFile.SoftFormula -> (MIP.Problem Integer, SAT.Model -> Map MIP.Var Rational, Map MIP.Var Rational -> SAT.Model)+convertWBO useIndicator formula = (mip, mforth, mtrans (PBFile.wboNumVars formula))   where     mip = def       { MIP.objectiveFunction = obj2@@ -76,22 +79,24 @@      obj2 = def       { MIP.objDir = MIP.OptMin-      , MIP.objExpr = MIP.Expr [MIP.Term (fromIntegral w) [v] | (ts, _) <- cs2, (w, v) <- ts]+      , MIP.objExpr = MIP.Expr [MIP.Term w [v] | (ts, _) <- cs2, (w, v) <- ts]       } -    topConstr :: [MIP.Constraint]+    topConstr :: [MIP.Constraint Integer]     topConstr =       case PBFile.wboTopCost formula of        Nothing -> []        Just t ->           [ def{ MIP.constrExpr = MIP.objExpr obj2, MIP.constrUB = MIP.Finite (fromInteger t - 1) } ] -    cs2 :: [([(Integer, MIP.Var)], MIP.Constraint)]+    relaxVariables :: [(MIP.Var, PBFile.SoftConstraint)]+    relaxVariables = [(MIP.toVar ("r" ++ show n), c) | (n, c) <- zip [(0::Int)..] (PBFile.wboConstraints formula)]++    cs2 :: [([(Integer, MIP.Var)], MIP.Constraint Integer)]     cs2 = do-      (n, (w, (lhs,op,rhs))) <- zip [(0::Int)..] (PBFile.wboConstraints formula)+      (v, (w, (lhs,op,rhs))) <- relaxVariables       let (lhs2,c) = splitConst $ convExpr lhs-          rhs2 = fromIntegral rhs - c-          v = MIP.toVar ("r" ++ show n)+          rhs2 = rhs - c           (ts,ind) =             case w of               Nothing -> ([], Nothing)@@ -113,18 +118,24 @@                  c2 = lhsLE .<=. MIP.constExpr rhsLE              [ (ts, c1), ([], c2) ] -splitConst :: MIP.Expr -> (MIP.Expr, Rational)+    mforth :: SAT.Model -> Map MIP.Var Rational+    mforth m = Map.union m1 m2+      where+        m1 = Map.fromList $ [(convVar v, if val then 1 else 0) | (v,val) <- assocs m]+        m2 = Map.fromList $ [(v, if SAT.evalPBConstraint m c then 0 else 1) | (v, (Just _, c)) <- relaxVariables]++splitConst :: MIP.Expr Integer -> (MIP.Expr Integer, Integer) splitConst e = (e2, c)   where     e2 = MIP.Expr [t | t@(MIP.Term _ (_:_)) <- MIP.terms e]     c = sum [c | MIP.Term c [] <- MIP.terms e]              -relaxGE :: MIP.Var -> (MIP.Expr, Rational) -> (MIP.Expr, Rational)+relaxGE :: MIP.Var -> (MIP.Expr Integer, Integer) -> (MIP.Expr Integer, Integer) relaxGE v (lhs, rhs) = (MIP.constExpr (rhs - lhs_lb) * MIP.varExpr v + lhs, rhs)   where     lhs_lb = sum [min c 0 | MIP.Term c _ <- MIP.terms lhs] -relaxLE :: MIP.Var -> (MIP.Expr, Rational) -> (MIP.Expr, Rational)+relaxLE :: MIP.Var -> (MIP.Expr Integer, Integer) -> (MIP.Expr Integer, Integer) relaxLE v (lhs, rhs) = (MIP.constExpr (rhs - lhs_ub) * MIP.varExpr v + lhs, rhs)   where     lhs_ub = sum [max c 0 | MIP.Term c _ <- MIP.terms lhs]
src/ToySolver/Converter/PB2LSP.hs view
@@ -1,13 +1,14 @@ {-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE OverloadedStrings #-} ----------------------------------------------------------------------------- -- | -- Module      :  ToySolver.Converter.PB2LSP--- Copyright   :  (c) Masahiro Sakai 2013-2014+-- Copyright   :  (c) Masahiro Sakai 2013-2014,2016 -- License     :  BSD-style --  -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  experimental--- Portability :  portable+-- Portability :  non-portable (OverloadedStrings) -- ----------------------------------------------------------------------------- module ToySolver.Converter.PB2LSP@@ -15,89 +16,89 @@   , convertWBO   ) where +import Data.ByteString.Builder import Data.List+import Data.Monoid import qualified Data.PseudoBoolean as PBFile -convert :: PBFile.Formula -> ShowS+convert :: PBFile.Formula -> Builder convert formula =-  showString "function model() {\n" .-  decls .-  constrs .-  obj2 .-  showString "}\n"+  byteString "function model() {\n" <>+  decls <>+  constrs <>+  obj2 <>+  "}\n"   where     nv = PBFile.pbNumVars formula -    decls = showString $-      "  for [i in 1.." ++ show nv ++ "] x[i] <- bool();\n"+    decls = byteString "  for [i in 1.." <> intDec nv <> byteString "] x[i] <- bool();\n" -    constrs = foldr (.) id-      [ showString "  constraint " .-        showString (showConstr c) .-        showString ";\n"+    constrs = mconcat+      [ byteString "  constraint " <>+        showConstr c <>+        ";\n"       | c <- PBFile.pbConstraints formula       ]      obj2 =       case PBFile.pbObjectiveFunction formula of-        Just obj' -> showString "  minimize " . showString (showSum obj') . showString ";\n"-        Nothing -> id+        Just obj' -> byteString "  minimize " <> showSum obj' <> ";\n"+        Nothing -> mempty -convertWBO :: PBFile.SoftFormula -> ShowS+convertWBO :: PBFile.SoftFormula -> Builder convertWBO softFormula =-  showString "function model() {\n" .-  decls .-  constrs .-  costDef .-  topConstr .-  showString "  minimize cost;\n" .-  showString "}\n"+  byteString "function model() {\n" <>+  decls <>+  constrs <>+  costDef <>+  topConstr <>+  byteString "  minimize cost;\n}\n"   where     nv = PBFile.wboNumVars softFormula -    decls = showString $-      "  for [i in 1.." ++ show nv ++ "] x[i] <- bool();\n"+    decls = byteString "  for [i in 1.." <> intDec nv <> byteString "] x[i] <- bool();\n" -    constrs = foldr (.) id-      [ showString "  constraint " .-        showString (showConstr c) .-        showString ";\n"+    constrs = mconcat+      [ byteString "  constraint " <>+        showConstr c <>+        ";\n"       | (Nothing, c) <- PBFile.wboConstraints softFormula       ] -    costDef = showString "  cost <- sum(\n" . s . showString ");\n"+    costDef = byteString "  cost <- sum(\n" <> s <> ");\n"       where-        s = foldr (.) id . intersperse (showString ",\n") . map showString $ xs-        xs = ["    " ++ show w ++ "*!(" ++ showConstr c ++ ")" | (Just w, c) <- PBFile.wboConstraints softFormula]+        s = mconcat . intersperse (",\n") $ xs+        xs = ["    " <> integerDec w <> "*!(" <> showConstr c <> ")"+             | (Just w, c) <- PBFile.wboConstraints softFormula]      topConstr =       case PBFile.wboTopCost softFormula of-        Nothing -> id-        Just t -> showString $ "  constraint cost <= " ++ show t ++ ";\n"+        Nothing -> mempty+        Just t -> byteString "  constraint cost <= " <> integerDec t <> ";\n" -showConstr :: PBFile.Constraint -> String+showConstr :: PBFile.Constraint -> Builder showConstr (lhs, PBFile.Ge, 1) | and [c==1 | (c,_) <- lhs] =-  "or(" ++ intercalate "," (map (f . snd) lhs) ++ ")"+  "or(" <> mconcat (intersperse "," (map (f . snd) lhs)) <> ")"   where     f [l] = showLit l-    f ls  = "and(" ++ intercalate "," (map showLit ls) ++ ")"-showConstr (lhs, op, rhs) = showSum lhs  ++ op2 ++ show rhs+    f ls  = "and(" <> mconcat (intersperse "," (map showLit ls)) <> ")"+showConstr (lhs, op, rhs) = showSum lhs  <> op2 <> integerDec rhs   where     op2 = case op of             PBFile.Ge -> " >= "             PBFile.Eq -> " == " -sum' :: [String] -> String-sum' xs = "sum(" ++ intercalate ", " xs ++ ")"+sum' :: [Builder] -> Builder+sum' xs = "sum(" <> mconcat (intersperse ", " xs) <> ")" -showSum :: PBFile.Sum -> String+showSum :: PBFile.Sum -> Builder showSum = sum' . map showTerm -showTerm :: PBFile.WeightedTerm -> String-showTerm (n,ls) = intercalate "*" $ [show n | n /= 1] ++ [showLit l | l<-ls]+showTerm :: PBFile.WeightedTerm -> Builder+showTerm (n,ls) = mconcat $ intersperse "*" $ [integerDec n | n /= 1] ++ [showLit l | l<-ls] -showLit :: PBFile.Lit -> String+showLit :: PBFile.Lit -> Builder showLit l =   if l < 0-  then "!x[" ++ show (abs l) ++ "]"-  else "x[" ++ show l ++ "]"+  then "!x[" <> intDec (abs l) <> "]"+  else "x[" <> intDec l <> "]"
+ src/ToySolver/Converter/PB2SAT.hs view
@@ -0,0 +1,60 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE FlexibleContexts, MultiParamTypeClasses #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Converter.PB2SAT+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+--+-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+-- Portability :  non-portable (FlexibleContexts, MultiParamTypeClasses)+--+-----------------------------------------------------------------------------+module ToySolver.Converter.PB2SAT (convert) where++import Control.Monad+import Control.Monad.ST+import Data.Array.IArray+import qualified Data.PseudoBoolean as PBFile++import qualified ToySolver.SAT.Types as SAT+import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin+import qualified ToySolver.SAT.Encoder.PB as PB+import qualified ToySolver.SAT.Encoder.PBNLC as PBNLC+import ToySolver.SAT.Store.CNF+import qualified ToySolver.Text.CNF as CNF++-- | Convert a pseudo boolean formula φ to a equisatisfiable CNF formula ψ+-- together with two functions f and g such that:+--+-- * if M ⊨ φ then f(M) ⊨ ψ+--+-- * if M ⊨ ψ then g(M) ⊨ φ+-- +convert :: PBFile.Formula -> (CNF.CNF, SAT.Model -> SAT.Model, SAT.Model -> SAT.Model)+convert formula = runST $ do+  db <- newCNFStore+  let nv1 = PBFile.pbNumVars formula+  SAT.newVars_ db nv1+  tseitin <-  Tseitin.newEncoder db+  pb <- PB.newEncoder tseitin+  pbnlc <- PBNLC.newEncoder pb tseitin+  forM_ (PBFile.pbConstraints formula) $ \(lhs,op,rhs) -> do+    case op of+      PBFile.Ge -> SAT.addPBNLAtLeast pbnlc lhs rhs+      PBFile.Eq -> SAT.addPBNLExactly pbnlc lhs rhs+  cnf <- getCNFFormula db++  defs <- Tseitin.getDefinitions tseitin+  let extendModel :: SAT.Model -> SAT.Model+      extendModel m = array (1, CNF.numVars cnf) (assocs a)+        where+          -- Use BOXED array to tie the knot+          a :: Array SAT.Var Bool+          a = array (1, CNF.numVars cnf) $+                assocs m ++ [(v, Tseitin.evalFormula a phi) | (v, phi) <- defs]++  return (cnf, extendModel, SAT.restrictModel nv1)++-- -----------------------------------------------------------------------------
src/ToySolver/Converter/PB2SMP.hs view
@@ -1,85 +1,87 @@ {-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE OverloadedStrings #-} ----------------------------------------------------------------------------- -- | -- Module      :  ToySolver.Converter.PB2SMP--- Copyright   :  (c) Masahiro Sakai 2013+-- Copyright   :  (c) Masahiro Sakai 2013,2016 -- License     :  BSD-style --  -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  experimental--- Portability :  portable+-- Portability :  non-portable (OverloadedStrings) -- ----------------------------------------------------------------------------- module ToySolver.Converter.PB2SMP   ( convert   ) where +import Data.ByteString.Builder import Data.List+import Data.Monoid import qualified Data.PseudoBoolean as PBFile -convert :: Bool -> PBFile.Formula -> ShowS+convert :: Bool -> PBFile.Formula -> Builder convert isUnix formula =-  header .-  decls .-  showString "\n" .-  obj2 .-  showString "\n" .-  constrs .-  showString "\n" .-  actions .+  header <>+  decls <>+  char7 '\n' <>+  obj2 <>+  char7 '\n' <>+  constrs <>+  char7 '\n' <>+  actions <>   footer   where     nv = PBFile.pbNumVars formula      header =       if isUnix-      then showString "#include \"simple.h\"\nvoid ufun()\n{\n\n"-      else id+      then byteString "#include \"simple.h\"\nvoid ufun()\n{\n\n"+      else mempty          footer =       if isUnix-      then showString "\n}\n"-      else id+      then "\n}\n"+      else mempty -    actions =-      showString "solve();\n" .-      showString "x[i].val.print();\n" .-      showString "cost.val.print();\n"+    actions = byteString $+      "solve();\n" <>+      "x[i].val.print();\n" <>+      "cost.val.print();\n" -    decls = showString $-      "Element i(set=\"1 .. " ++ show nv ++ "\");\n" ++-      "IntegerVariable x(type=binary, index=i);\n"+    decls =+      byteString "Element i(set=\"1 .. " <> intDec nv <>+      byteString "\");\nIntegerVariable x(type=binary, index=i);\n" -    constrs = foldr (.) id-      [ showString (showSum lhs) .-        showString op2 .-        shows rhs .-        showString ";\n"+    constrs = mconcat+      [ showSum lhs <>+        op2 <>+        integerDec rhs <>+        ";\n"       | (lhs, op, rhs) <- PBFile.pbConstraints formula       , let op2 = case op of                     PBFile.Ge -> " >= "                     PBFile.Eq -> " == "       ] -    showSum :: PBFile.Sum -> String-    showSum [] = "0"-    showSum xs = intercalate " + " $ map showTerm xs+    showSum :: PBFile.Sum -> Builder+    showSum [] = char7 '0'+    showSum xs = mconcat $ intersperse " + " $ map showTerm xs -    showTerm (n,ls) = intercalate "*" $ showCoeff n ++ [showLit l | l<-ls]+    showTerm (n,ls) = mconcat $ intersperse (char7 '*') $ showCoeff n ++ [showLit l | l<-ls]      showCoeff n       | n == 1    = []-      | n < 0     = ["(" ++ show n ++ ")"]-      | otherwise = [show n]+      | n < 0     = [char7 '(' <> integerDec n <> char7 ')']+      | otherwise = [integerDec n]      showLit l =       if l < 0-      then "(1-x[" ++ show (abs l) ++ "])"-      else "x[" ++ show l ++ "]"+      then "(1-x[" <> intDec (abs l) <> "])"+      else "x[" <> intDec l <> "]"      obj2 =       case PBFile.pbObjectiveFunction formula of         Just obj' ->-          showString "Objective cost(type=minimize);\n" .-          showString "cost = " . showString (showSum obj') . showString ";\n"-        Nothing -> id+          byteString "Objective cost(type=minimize);\ncost = " <> showSum obj' <> ";\n"+        Nothing -> mempty
+ src/ToySolver/Converter/PBLinearization.hs view
@@ -0,0 +1,77 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE MultiParamTypeClasses #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Converter.PBLinearization+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+--+-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+-- Portability :  portable+--+-----------------------------------------------------------------------------+module ToySolver.Converter.PBLinearization+  ( linearize+  , linearizeWBO+  ) where++import Control.Monad+import Control.Monad.ST+import qualified Data.PseudoBoolean as PBFile++import qualified ToySolver.SAT.Types as SAT+import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin+import qualified ToySolver.SAT.Encoder.PBNLC as PBNLC+import ToySolver.SAT.Store.PB++linearize :: PBFile.Formula -> Bool -> PBFile.Formula+linearize formula usePB = runST $ do+  db <- newPBStore+  SAT.newVars_ db (PBFile.pbNumVars formula)+  tseitin <-  Tseitin.newEncoderWithPBLin db+  Tseitin.setUsePB tseitin usePB+  pbnlc <- PBNLC.newEncoder db tseitin+  cs' <- forM (PBFile.pbConstraints formula) $ \(lhs,op,rhs) -> do+    let p = case op of+              PBFile.Ge -> Tseitin.polarityPos+              PBFile.Eq -> Tseitin.polarityBoth+    lhs' <- PBNLC.linearizePBSumWithPolarity pbnlc p lhs+    return ([(c,[l]) | (c,l) <- lhs'],op,rhs)+  obj' <-+    case PBFile.pbObjectiveFunction formula of+      Nothing -> return Nothing+      Just obj -> do+        obj' <- PBNLC.linearizePBSumWithPolarity pbnlc Tseitin.polarityNeg obj+        return $ Just [(c, [l]) | (c,l) <- obj']+  formula' <- getPBFormula db+  return $+    formula'+    { PBFile.pbObjectiveFunction = obj'+    , PBFile.pbConstraints = cs' ++ PBFile.pbConstraints formula'+    , PBFile.pbNumConstraints = PBFile.pbNumConstraints formula + PBFile.pbNumConstraints formula'+    }++linearizeWBO :: PBFile.SoftFormula -> Bool -> PBFile.SoftFormula+linearizeWBO formula usePB = runST $ do+  db <- newPBStore+  SAT.newVars_ db (PBFile.wboNumVars formula)+  tseitin <-  Tseitin.newEncoderWithPBLin db+  Tseitin.setUsePB tseitin usePB+  pbnlc <- PBNLC.newEncoder db tseitin+  cs' <- forM (PBFile.wboConstraints formula) $ \(cost,(lhs,op,rhs)) -> do+    let p = case op of+              PBFile.Ge -> Tseitin.polarityPos+              PBFile.Eq -> Tseitin.polarityBoth+    lhs' <- PBNLC.linearizePBSumWithPolarity pbnlc p lhs+    return (cost,([(c,[l]) | (c,l) <- lhs'],op,rhs))+  formula' <- getPBFormula db+  return $+    PBFile.SoftFormula+    { PBFile.wboTopCost = PBFile.wboTopCost formula+    , PBFile.wboConstraints = cs' ++ [(Nothing, constr) | constr <- PBFile.pbConstraints formula']+    , PBFile.wboNumVars = PBFile.pbNumVars formula'+    , PBFile.wboNumConstraints = PBFile.wboNumConstraints formula + PBFile.pbNumConstraints formula'+    }++-- -----------------------------------------------------------------------------
src/ToySolver/Converter/SAT2IP.hs view
@@ -15,12 +15,12 @@   ) where  import Data.Map (Map)-import qualified Language.CNF.Parse.ParseDIMACS as DIMACS  import qualified ToySolver.Data.MIP as MIP import qualified ToySolver.SAT.Types as SAT import qualified ToySolver.Converter.PB2IP as PB2IP import qualified ToySolver.Converter.SAT2PB as SAT2PB+import qualified ToySolver.Text.CNF as CNF -convert :: DIMACS.CNF -> (MIP.Problem, Map MIP.Var Rational -> SAT.Model)+convert :: CNF.CNF -> (MIP.Problem Integer, SAT.Model -> Map MIP.Var Rational, Map MIP.Var Rational -> SAT.Model) convert cnf = PB2IP.convert (SAT2PB.convert cnf)
+ src/ToySolver/Converter/SAT2KSAT.hs view
@@ -0,0 +1,70 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE FlexibleContexts, MultiParamTypeClasses #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Converter.SAT2KSAT+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+--+-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+-- Portability :  non-portable (FlexibleContexts, MultiParamTypeClasses)+--+-----------------------------------------------------------------------------+module ToySolver.Converter.SAT2KSAT (convert) where++import Control.Monad+import Control.Monad.ST+import Data.Array.MArray+import Data.Array.ST+import Data.Foldable (toList)+import Data.Sequence ((<|), (|>))+import qualified Data.Sequence as Seq+import Data.STRef++import qualified ToySolver.SAT.Types as SAT+import ToySolver.SAT.Store.CNF+import qualified ToySolver.Text.CNF as CNF++convert :: Int -> CNF.CNF -> (CNF.CNF, SAT.Model -> SAT.Model, SAT.Model -> SAT.Model)+convert k _ | k < 3 = error "ToySolver.Converter.SAT2KSAT.convert: k must be >=3"+convert k cnf = runST $ do+  let nv1 = CNF.numVars cnf+  db <- newCNFStore+  defsRef <- newSTRef Seq.empty+  SAT.newVars_ db (CNF.numVars cnf)+  forM_ (CNF.clauses cnf) $ \clause -> do+    let loop lits = do+          if Seq.length lits <= k then+            SAT.addClause db (toList lits)+          else do+            v <- SAT.newVar db+            case Seq.splitAt (k-1) lits of+              (lits1, lits2) -> do+                SAT.addClause db (toList (lits1 |> (-v)))+                modifySTRef' defsRef (|> (v, toList lits1))+                loop (v <| lits2)+    loop $ Seq.fromList clause+    +  cnf2 <- getCNFFormula db++  defs <- readSTRef defsRef++  let extendModel :: SAT.Model -> SAT.Model+      extendModel m = runSTUArray $ do+        m2 <- newArray_ (1,CNF.numVars cnf2)+        forM_ [1..nv1] $ \v -> do+          writeArray m2 v (SAT.evalVar m v)+        forM_ (toList defs) $ \(v, clause) -> do+          let f lit =+                if lit > 0 then+                  readArray m2 lit+                else+                  liftM not (readArray m2 (- lit))+          val <- liftM or (mapM f clause)+          writeArray m2 v val+        return m2++  return (cnf2, extendModel, SAT.restrictModel nv1)++-- -----------------------------------------------------------------------------
src/ToySolver/Converter/SAT2PB.hs view
@@ -14,18 +14,16 @@   ( convert   ) where -import Data.Array.IArray-import qualified Language.CNF.Parse.ParseDIMACS as DIMACS- import qualified Data.PseudoBoolean as PBFile+import qualified ToySolver.Text.CNF as CNF -convert :: DIMACS.CNF -> PBFile.Formula+convert :: CNF.CNF -> PBFile.Formula convert cnf   = PBFile.Formula   { PBFile.pbObjectiveFunction = Nothing-  , PBFile.pbConstraints = map f (DIMACS.clauses cnf)-  , PBFile.pbNumVars = DIMACS.numVars cnf-  , PBFile.pbNumConstraints = DIMACS.numClauses cnf+  , PBFile.pbConstraints = map f (CNF.clauses cnf)+  , PBFile.pbNumVars = CNF.numVars cnf+  , PBFile.pbNumConstraints = CNF.numClauses cnf   }   where-    f clause = ([(1,[l]) | l <- elems clause], PBFile.Ge, 1)+    f clause = ([(1,[l]) | l <- clause], PBFile.Ge, 1)
+ src/ToySolver/Converter/WBO2MaxSAT.hs view
@@ -0,0 +1,89 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE FlexibleContexts, MultiParamTypeClasses #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Converter.WBO2MaxSAT+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+--+-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+-- Portability :  non-portable (FlexibleContexts, MultiParamTypeClasses)+--+-----------------------------------------------------------------------------+module ToySolver.Converter.WBO2MaxSAT (convert) where++import Control.Applicative+import Control.Monad+import Control.Monad.ST+import Data.Array.IArray+import qualified Data.Foldable as F+import Data.Monoid+import qualified Data.Sequence as Seq+import qualified Data.PseudoBoolean as PBFile++import qualified ToySolver.SAT.Types as SAT+import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin+import qualified ToySolver.SAT.Encoder.PB as PB+import qualified ToySolver.SAT.Encoder.PBNLC as PBNLC+import ToySolver.SAT.Store.CNF+import qualified ToySolver.Text.MaxSAT as MaxSAT+import qualified ToySolver.Text.CNF as CNF++convert :: PBFile.SoftFormula -> (MaxSAT.WCNF, SAT.Model -> SAT.Model, SAT.Model -> SAT.Model)+convert formula = runST $ do+  db <- newCNFStore+  SAT.newVars_ db (PBFile.wboNumVars formula)+  tseitin <-  Tseitin.newEncoder db+  pb <- PB.newEncoder tseitin+  pbnlc <- PBNLC.newEncoder pb tseitin++  softClauses <- liftM mconcat $ forM (PBFile.wboConstraints formula) $ \(cost, (lhs,op,rhs)) -> do+    case cost of+      Nothing ->+        case op of+          PBFile.Ge -> SAT.addPBNLAtLeast pbnlc lhs rhs >> return mempty+          PBFile.Eq -> SAT.addPBNLExactly pbnlc lhs rhs >> return mempty+      Just c -> do+        case op of+          PBFile.Ge -> do+            lhs2 <- PBNLC.linearizePBSumWithPolarity pbnlc Tseitin.polarityPos lhs+            let (lhs3,rhs3) = SAT.normalizePBLinAtLeast (lhs2,rhs)+            if rhs3==1 && and [c==1 | (c,_) <- lhs3] then+              return $ Seq.singleton (c, [l | (_,l) <- lhs3])+            else do+              lit <- PB.encodePBLinAtLeast pb (lhs3,rhs3)+              return $ Seq.singleton (c, [lit])+          PBFile.Eq -> do+            lhs2 <- PBNLC.linearizePBSumWithPolarity pbnlc Tseitin.polarityBoth lhs+            lit1 <- PB.encodePBLinAtLeast pb (lhs2, rhs)+            lit2 <- PB.encodePBLinAtLeast pb ([(-c, l) | (c,l) <- lhs2], negate rhs)+            lit <- Tseitin.encodeConjWithPolarity tseitin Tseitin.polarityPos [lit1,lit2]+            return $ Seq.singleton (c, [lit])++  case PBFile.wboTopCost formula of+    Nothing -> return ()+    Just top -> SAT.addPBNLAtMost pbnlc [(c, [-l | l <- clause]) | (c,clause) <- F.toList softClauses] (top - 1)++  let top = F.sum (fst <$> softClauses) + 1+  cnf <- getCNFFormula db+  let cs = softClauses <> Seq.fromList [(top, clause) | clause <- CNF.clauses cnf]+  let wcnf = MaxSAT.WCNF+             { MaxSAT.numVars = CNF.numVars cnf+             , MaxSAT.numClauses = Seq.length cs+             , MaxSAT.topCost = top+             , MaxSAT.clauses = F.toList cs+             }++  defs <- Tseitin.getDefinitions tseitin+  let extendModel :: SAT.Model -> SAT.Model+      extendModel m = array (1, CNF.numVars cnf) (assocs a)+        where+          -- Use BOXED array to tie the knot+          a :: Array SAT.Var Bool+          a = array (1, CNF.numVars cnf) $+                assocs m ++ [(v, Tseitin.evalFormula a phi) | (v, phi) <- defs]++  return (wcnf, extendModel, SAT.restrictModel (PBFile.wboNumVars formula))++-- -----------------------------------------------------------------------------
src/ToySolver/Converter/WBO2PB.hs view
@@ -1,57 +1,93 @@ {-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE MultiParamTypeClasses #-} ----------------------------------------------------------------------------- -- | -- Module      :  ToySolver.Converter.WBO2PB--- Copyright   :  (c) Masahiro Sakai 2013+-- Copyright   :  (c) Masahiro Sakai 2013,2016 -- License     :  BSD-style --  -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  experimental--- Portability :  portable+-- Portability :  non-portable (MultiParamTypeClasses) -- ------------------------------------------------------------------------------module ToySolver.Converter.WBO2PB (convert) where+module ToySolver.Converter.WBO2PB+  ( convert+  , addWBO+  ) where +import Control.Monad+import Control.Monad.Primitive+import Control.Monad.ST import Data.Array.IArray+import Data.Primitive.MutVar import qualified ToySolver.SAT.Types as SAT+import ToySolver.SAT.Store.PB import qualified Data.PseudoBoolean as PBFile -convert :: PBFile.SoftFormula -> (PBFile.Formula, SAT.Model -> SAT.Model)-convert wbo = (formula, mtrans)-  where-    nv = PBFile.wboNumVars wbo+convert :: PBFile.SoftFormula -> (PBFile.Formula, SAT.Model -> SAT.Model, SAT.Model -> SAT.Model)+convert wbo = runST $ do+  let nv = PBFile.wboNumVars wbo+  db <- newPBStore+  (obj, defs) <- addWBO db wbo +  formula <- getPBFormula db -    cm  = zip [nv+1..] (PBFile.wboConstraints wbo)-    obj = [(w, [i]) | (i, (Just w,_)) <- cm]+  let mforth :: SAT.Model -> SAT.Model+      mforth m = array (1, PBFile.pbNumVars formula) $ assocs m ++ [(v, SAT.evalPBConstraint m constr) | (v, constr) <- defs] -    f :: (PBFile.Var, PBFile.SoftConstraint) -> [PBFile.Constraint]-    f (_, (Nothing, c)) = return c-    f (i, (Just _, c))  = relax i c+      mback :: SAT.Model -> SAT.Model+      mback = SAT.restrictModel nv -    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)+  return+    ( formula{ PBFile.pbObjectiveFunction = Just obj }+    , mforth+    , mback+    ) -    topConstr :: [PBFile.Constraint]-    topConstr = -     case PBFile.wboTopCost wbo of-       Nothing -> []-       Just t -> [([(-c,ls) | (c,ls) <- obj], PBFile.Ge, - (t - 1))] -    formula =-      PBFile.Formula-      { PBFile.pbObjectiveFunction = Just obj-      , PBFile.pbConstraints = cs-      , PBFile.pbNumVars = nv + PBFile.wboNumConstraints wbo-      , PBFile.pbNumConstraints = length cs-      }-      where-        cs = topConstr ++ concatMap f cm+addWBO :: (PrimMonad m, SAT.AddPBNL m enc) => enc -> PBFile.SoftFormula -> m (SAT.PBSum, [(SAT.Var, PBFile.Constraint)])+addWBO db wbo = do+  SAT.newVars_ db $ PBFile.wboNumVars wbo -    mtrans :: SAT.Model -> SAT.Model-    mtrans m = -      array (1, nv) [(x, m ! x) | x <- [1..nv]]+  objRef <- newMutVar []+  defsRef <- newMutVar []+  forM_ (PBFile.wboConstraints wbo) $ \(cost, constr@(lhs,op,rhs)) -> do+    case cost of+      Nothing -> do+        case op of+          PBFile.Ge -> SAT.addPBNLAtLeast db lhs rhs+          PBFile.Eq -> SAT.addPBNLExactly db lhs rhs+      Just w -> do+        case op of+          PBFile.Ge -> do+            case lhs of+              [(1,ls)] | rhs == 1 -> do+                -- ∧L ≥ 1 ⇔ ∧L+                -- obj += w * (1 - ∧L)+                modifyMutVar objRef (\obj -> (w,[]) : (-w,ls) : obj)+              [(-1,ls)] | rhs == 0 -> do+                -- -1*∧L ≥ 0 ⇔ (1 - ∧L) ≥ 1 ⇔ ¬∧L+                -- obj += w * ∧L+                modifyMutVar objRef ((w,ls) :)+              _ | and [c==1 && length ls == 1 | (c,ls) <- lhs] && rhs == 1 -> do+                -- ∑L ≥ 1 ⇔ ∨L ⇔ ¬∧¬L+                -- obj += w * ∧¬L+                modifyMutVar objRef ((w, [-l | (_,[l]) <- lhs]) :)+              _ -> do+                sel <- SAT.newVar db+                SAT.addPBNLAtLeastSoft db sel lhs rhs+                modifyMutVar objRef ((w,[-sel]) :)+                modifyMutVar defsRef ((sel,constr) :)+          PBFile.Eq -> do+            sel <- SAT.newVar db+            SAT.addPBNLExactlySoft db sel lhs rhs+            modifyMutVar objRef ((w,[-sel]) :)+            modifyMutVar defsRef ((sel,constr) :)+  obj <- liftM reverse $ readMutVar objRef+  defs <- liftM reverse $ readMutVar defsRef++  case PBFile.wboTopCost wbo of+    Nothing -> return ()+    Just t -> SAT.addPBNLAtMost db obj (t - 1)++  return (obj, defs)
src/ToySolver/Data/AlgebraicNumber/Real.hs view
@@ -399,7 +399,7 @@ -- coefficients of the irreducible and primitive polynomial with integral -- rational coefficients. height :: AReal -> Integer-height x = maximum [abs (numerator c) | (c,_) <- P.terms $ P.pp $ minimalPolynomial x]+height x = maximum [abs c | (c,_) <- P.terms $ P.pp $ minimalPolynomial x]  -- | root index, satisfying --
src/ToySolver/Data/AlgebraicNumber/Root.hs view
@@ -1,13 +1,13 @@-{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE Rank2Types, ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- | -- Module      :  ToySolver.Data.AlgebraicNumber.Root--- Copyright   :  (c) Masahiro Sakai 2012+-- Copyright   :  (c) Masahiro Sakai 2012-2016 -- License     :  BSD-style --  -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  provisional--- Portability :  non-portable (Rank2Types)+-- Portability :  non-portable (Rank2Types, ScopedTypeVariables) -- -- Manipulating polynomials for corresponding operations for algebraic numbers. -- @@ -34,63 +34,65 @@   Manipulation of polynomials --------------------------------------------------------------------} -normalizePoly :: UPolynomial Rational -> UPolynomial Rational+normalizePoly :: (Fractional k, Eq k) => UPolynomial k -> UPolynomial k normalizePoly = P.toMonic P.nat -rootAdd :: UPolynomial Rational -> UPolynomial Rational -> UPolynomial Rational+rootAdd :: (Fractional k, Ord k) => UPolynomial k -> UPolynomial k -> UPolynomial k rootAdd p1 p2 = lift2 (+) p1 p2 -rootMul :: UPolynomial Rational -> UPolynomial Rational -> UPolynomial Rational+rootMul :: (Fractional k, Ord k) => UPolynomial k -> UPolynomial k -> UPolynomial k rootMul p1 p2 = lift2 (*) p1 p2 -rootShift :: Rational -> UPolynomial Rational -> UPolynomial Rational+rootShift :: (Fractional k, Eq k) => k -> UPolynomial k -> UPolynomial k rootShift 0 p = p rootShift r p = normalizePoly $ P.subst p (\X -> P.var X - P.constant r) -rootScale :: Rational -> UPolynomial Rational -> UPolynomial Rational+rootScale :: (Fractional k, Eq k) => k -> UPolynomial k -> UPolynomial k rootScale 0 p = P.var X rootScale r p = normalizePoly $ P.subst p (\X -> P.constant (recip r) * P.var X) -rootRecip :: UPolynomial Rational -> UPolynomial Rational+rootRecip :: (Fractional k, Eq k) => UPolynomial k -> UPolynomial k rootRecip p = normalizePoly $ P.fromTerms [(c, P.var X `P.mpow` (d - P.deg xs)) | (c, xs) <- P.terms p]   where     d = P.deg p --- 代数的数を係数とする多項式の根を、有理数係数多項式の根として表す-rootSimpPoly :: (a -> UPolynomial Rational) -> UPolynomial a -> UPolynomial Rational+-- | Given a polynomial P = Σ_i a_i x^i over L/K where each a_i is a root of polynomial @f a_i@ over K,+-- @rootSimpPoly f P@ computes a polynomial Q over K such that roots of P is a subset of roots of Q.+rootSimpPoly :: forall k l. (Fractional k, Ord k) => (l -> UPolynomial k) -> UPolynomial l -> UPolynomial k rootSimpPoly f p = findPoly (P.var 0) ps   where-    ys :: [(UPolynomial Rational, Var)]+    ys :: [(UPolynomial k, Var)]     ys = zip (Set.toAscList $ Set.fromList [f c | (c, _) <- P.terms p]) [1..] -    m :: Map (UPolynomial Rational) Var+    m :: Map (UPolynomial k) Var     m = Map.fromDistinctAscList ys -    p' :: Polynomial Rational Var+    p' :: Polynomial k Var     p' = P.eval (\X -> P.var 0) (P.mapCoeff (\c -> P.var (m Map.! (f c))) p) -    ps :: [Polynomial Rational Var]+    ps :: [Polynomial k Var]     ps = p' : [P.subst q (\X -> P.var x) | (q, x) <- ys] -rootNthRoot :: Integer -> UPolynomial Rational -> UPolynomial Rational+rootNthRoot :: (Fractional k, Ord k) => Integer -> UPolynomial k -> UPolynomial k rootNthRoot n p = P.subst p (\X -> (P.var X)^n) -lift2 :: (forall a. Num a => a -> a -> a)-      -> UPolynomial Rational -> UPolynomial Rational -> UPolynomial Rational+lift2 :: forall k. (Fractional k, Ord k) => (forall a. Num a => a -> a -> a)+      -> UPolynomial k -> UPolynomial k -> UPolynomial k lift2 f p1 p2 = findPoly f_a_b gbase   where     a, b :: Var     a = 0     b = 1 -    f_a_b :: Polynomial Rational Var+    f_a_b :: Polynomial k Var     f_a_b = f (P.var a) (P.var b) -    gbase :: [Polynomial Rational Var]+    gbase :: [Polynomial k Var]     gbase = [ P.subst p1 (\X -> P.var a), P.subst p2 (\X -> P.var b) ]               --- ps のもとで c を根とする多項式を求める-findPoly :: Polynomial Rational Var -> [Polynomial Rational Var] -> UPolynomial Rational+-- | Given a polynomial P and polynomials {P1,…,Pn} over K,+-- findPoly P [P1..Pn] computes a non-zero polynomial Q such that Q[P] = 0 modulo {P1,…,Pn}.+findPoly :: forall k. (Fractional k, Ord k) => Polynomial k Var -> [Polynomial k Var] -> UPolynomial k findPoly c ps = normalizePoly $ sum [P.constant coeff * (P.var X) ^ n | (n,coeff) <- zip [0..] coeffs]   where       vn :: Var@@ -98,14 +100,14 @@       where         vs = Set.fromList [x | p <- (c:ps), (_,xs) <- P.terms p, (x,_) <- P.mindices xs] -    coeffs :: [Rational]+    coeffs :: [k]     coeffs = head $ catMaybes $ [isLinearlyDependent cs2 | cs2 <- inits cs]       where         cmp = P.grlex         ps' = GB.basis cmp ps         cs  = iterate (\p -> P.reduce cmp (c * p) ps') 1 -    isLinearlyDependent :: [Polynomial Rational Var] -> Maybe [Rational]+    isLinearlyDependent :: [Polynomial k Var] -> Maybe [k]     isLinearlyDependent cs = if any (0/=) sol then Just sol else Nothing       where         cs2 = zip [vn..] cs
src/ToySolver/Data/BoolExpr.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE DeriveDataTypeable, MultiParamTypeClasses #-}+{-# LANGUAGE DeriveDataTypeable, MultiParamTypeClasses, FlexibleContexts, FlexibleInstances #-} {-# OPTIONS_GHC -Wall #-} ----------------------------------------------------------------------------- -- |@@ -8,7 +8,7 @@ --  -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  provisional--- Portability :  non-portable (MultiParamTypeClasses, DeriveDataTypeable)+-- Portability :  non-portable (MultiParamTypeClasses, DeriveDataTypeable, FlexibleContexts, FlexibleInstances) -- -- Boolean expression over a given type of atoms -- @@ -31,7 +31,7 @@ import Data.Hashable import Data.Traversable import ToySolver.Data.Boolean-import ToySolver.Data.Var+import ToySolver.Data.IntVar  -- | Boolean expression over a given type of atoms data BoolExpr a@@ -117,6 +117,9 @@ {-# RULES   "fold/fmap"    forall f g e.  fold f (fmap g e) = fold (f.g) e  #-}++instance Eval m a Bool => Eval m (BoolExpr a) Bool where+  eval m = fold (eval m)  simplify :: BoolExpr a -> BoolExpr a simplify = runSimplify . fold (Simplify . Atom)
src/ToySolver/Data/FOL/Arith.hs view
@@ -37,7 +37,7 @@  import ToySolver.Data.OrdRel import ToySolver.Data.FOL.Formula-import ToySolver.Data.Var+import ToySolver.Data.IntVar  -- --------------------------------------------------------------------------- @@ -92,6 +92,9 @@     f (a :+: b) = f a + f b     f (a :*: b) = f a * f b     f (a :/: b) = f a / f b++instance Fractional r => Eval (Model r) (Expr r) r where+  eval = evalExpr  -- --------------------------------------------------------------------------- 
src/ToySolver/Data/FOL/Formula.hs view
@@ -25,7 +25,7 @@ import qualified Data.IntSet as IS  import ToySolver.Data.Boolean-import ToySolver.Data.Var+import ToySolver.Data.IntVar  -- --------------------------------------------------------------------------- 
+ src/ToySolver/Data/IntVar.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Data.IntVar+-- Copyright   :  (c) Masahiro Sakai 2011-2013+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable (MultiParamTypeClasses)+-- +-----------------------------------------------------------------------------+module ToySolver.Data.IntVar+  ( Var+  , VarSet+  , VarMap+  , Variables (..)+  , Model+  , Eval (..)+  ) where++import Data.IntMap (IntMap)+import Data.IntSet (IntSet)+import qualified Data.IntSet as IntSet+import Data.Ratio++-- ---------------------------------------------------------------------------++-- | Variables are represented as non-negative integers+type Var = Int++-- | Set of variables+type VarSet = IntSet++-- | Map from variables+type VarMap = IntMap++-- | collecting free variables+class Variables a where+  vars :: a -> VarSet++instance Variables a => Variables [a] where+  vars = IntSet.unions . map vars++-- | A @Model@ is a map from variables to values.+type Model r = VarMap r++-- | Evaluataion of something (e.g. expression or formula) under the model.+class Eval m e v | m e -> v where+  eval :: m -> e -> v++-- ---------------------------------------------------------------------------
src/ToySolver/Data/LA.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeFamilies, TypeSynonymInstances, FlexibleInstances, MultiParamTypeClasses #-} ----------------------------------------------------------------------------- -- | -- Module      :  ToySolver.Data.LA@@ -7,7 +7,7 @@ --  -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  provisional--- Portability :  non-portable (TypeFamilies)+-- Portability :  non-portable (TypeFamilies, TypeSynonymInstances, FlexibleInstances, MultiParamTypeClasses) -- -- Some definition for Theory of Linear Arithmetics. -- @@ -53,6 +53,9 @@   , solveFor   , module ToySolver.Data.OrdRel +  -- * Evaluation of expression and atomic formula+  , Eval (..)+   -- * misc   , BoundsEnv   , computeInterval@@ -70,7 +73,7 @@  import qualified ToySolver.Data.OrdRel as OrdRel import ToySolver.Data.OrdRel-import ToySolver.Data.Var+import ToySolver.Data.IntVar  ----------------------------------------------------------------------------- @@ -163,10 +166,14 @@ plus :: Num r => Expr r -> Expr r -> Expr r plus (Expr t1) (Expr t2) = Expr $ IntMap.unionWith (+) t1 t2 +instance Num r => Eval (Model r) (Expr r) r where+  eval m (Expr t) = sum [(m' IntMap.! v) * c | (v,c) <- IntMap.toList t]+    where m' = IntMap.insert unitVar 1 m++{-# DEPRECATED evalExpr "Use Eval class instead" #-} -- | evaluate the expression under the model. evalExpr :: Num r => Model r -> Expr r -> r-evalExpr m (Expr t) = sum [(m' IntMap.! v) * c | (v,c) <- IntMap.toList t]-  where m' = IntMap.insert unitVar 1 m+evalExpr = eval  -- | evaluate the expression under the model. evalLinear :: VectorSpace a => Model a -> a -> Expr (Scalar a) -> a@@ -259,9 +266,10 @@ showAtom :: (Num r, Eq r, Show r) => Atom r -> String showAtom (OrdRel lhs op rhs) = showExpr lhs ++ showOp op ++ showExpr rhs +{-# DEPRECATED evalAtom "Use Eval class instead" #-} -- | evaluate the formula under the model. evalAtom :: (Num r, Ord r) => Model r -> Atom r -> Bool-evalAtom m (OrdRel lhs op rhs) = evalOp op (evalExpr m lhs) (evalExpr m rhs)+evalAtom = eval  applySubstAtom :: (Num r, Eq r) => VarMap (Expr r) -> Atom r -> Atom r applySubstAtom s (OrdRel lhs op rhs) = OrdRel (applySubst s lhs) op (applySubst s rhs)
src/ToySolver/Data/LA/FOL.hs view
@@ -21,7 +21,7 @@   b' <- fromFOLExpr b   return $ ordRel op a' b' -toFOLFormula :: (Real r, Fractional r) => LA.Atom r -> Formula (Atom r)+toFOLFormula :: (Real r) => LA.Atom r -> Formula (Atom r) toFOLFormula r = Atom $ fmap toFOLExpr r  fromFOLExpr :: (Real r, Fractional r) => Expr r -> Maybe (LA.Expr r)@@ -41,7 +41,7 @@   guard $ c /= 0   return (a' ^/ c) -toFOLExpr :: (Real r, Fractional r) => LA.Expr r -> Expr r+toFOLExpr :: (Real r) => LA.Expr r -> Expr r toFOLExpr e =   case map f (LA.terms e) of     []  -> Const 0
src/ToySolver/Data/MIP.hs view
@@ -1,13 +1,14 @@ {-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE CPP #-} ----------------------------------------------------------------------------- -- | -- Module      :  ToySolver.Data.MIP -- Copyright   :  (c) Masahiro Sakai 2011-2014 -- License     :  BSD-style--- +-- -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  provisional--- Portability :  portable+-- Portability :  non-portable -- -- Mixed-Integer Programming Problems with some commmonly used extensions --@@ -24,63 +25,93 @@   , writeMPSFile   , toLPString   , toMPSString+  , ParseError (..)   ) where  import Prelude hiding (readFile, writeFile)-import qualified Prelude as P+import Control.Exception import Data.Char+import Data.Scientific (Scientific)+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.IO as TLIO+#if MIN_VERSION_megaparsec(6,0,0)+import Data.Void+#endif import System.FilePath (takeExtension)-import Text.Parsec+import System.IO hiding (readFile, writeFile)+import Text.Megaparsec  import ToySolver.Data.MIP.Base import qualified ToySolver.Data.MIP.LPFile as LPFile import qualified ToySolver.Data.MIP.MPSFile as MPSFile  -- | Parse .lp or .mps file based on file extension-readFile :: FilePath -> IO (Either ParseError Problem)-readFile fname =+readFile :: FileOptions -> FilePath -> IO (Problem Scientific)+readFile opt fname =   case map toLower (takeExtension fname) of-    ".lp"  -> readLPFile fname-    ".mps" -> readMPSFile fname+    ".lp"  -> readLPFile opt fname+    ".mps" -> readMPSFile opt fname     ext -> ioError $ userError $ "unknown extension: " ++ ext  -- | Parse a file containing LP file data.-readLPFile :: FilePath -> IO (Either ParseError Problem)+readLPFile :: FileOptions -> FilePath -> IO (Problem Scientific) readLPFile = LPFile.parseFile  -- | Parse a file containing MPS file data.-readMPSFile :: FilePath -> IO (Either ParseError Problem)+readMPSFile :: FileOptions -> FilePath -> IO (Problem Scientific) readMPSFile = MPSFile.parseFile  -- | Parse a string containing LP file data.-parseLPString :: SourceName -> String -> Either ParseError Problem+#if MIN_VERSION_megaparsec(6,0,0)+parseLPString :: FileOptions -> String -> String -> Either (ParseError Char Void) (Problem Scientific)+#elif MIN_VERSION_megaparsec(5,0,0)+parseLPString :: FileOptions -> String -> String -> Either (ParseError Char Dec) (Problem Scientific)+#else+parseLPString :: FileOptions -> String -> String -> Either ParseError (Problem Scientific)+#endif parseLPString = LPFile.parseString  -- | Parse a string containing MPS file data.-parseMPSString :: SourceName -> String -> Either ParseError Problem+#if MIN_VERSION_megaparsec(6,0,0)+parseMPSString :: FileOptions -> String -> String -> Either (ParseError Char Void) (Problem Scientific)+#elif MIN_VERSION_megaparsec(5,0,0)+parseMPSString :: FileOptions -> String -> String -> Either (ParseError Char Dec) (Problem Scientific)+#else+parseMPSString :: FileOptions -> String -> String -> Either ParseError (Problem Scientific)+#endif parseMPSString = MPSFile.parseString -writeFile :: FilePath -> Problem -> IO ()-writeFile fname prob =+writeFile :: FileOptions -> FilePath -> Problem Scientific -> IO ()+writeFile opt fname prob =   case map toLower (takeExtension fname) of-    ".lp"  -> writeLPFile fname prob-    ".mps" -> writeMPSFile fname prob+    ".lp"  -> writeLPFile opt fname prob+    ".mps" -> writeMPSFile opt fname prob     ext -> ioError $ userError $ "unknown extension: " ++ ext -writeLPFile :: FilePath -> Problem -> IO ()-writeLPFile fname prob =-  case LPFile.render prob of+writeLPFile :: FileOptions -> FilePath -> Problem Scientific -> IO ()+writeLPFile opt fname prob =+  case LPFile.render opt prob of     Left err -> ioError $ userError err-    Right s -> P.writeFile fname s+    Right s ->+      withFile fname WriteMode $ \h -> do+        case optFileEncoding opt of+          Nothing -> return ()+          Just enc -> hSetEncoding h enc+        TLIO.hPutStr h s -writeMPSFile :: FilePath -> Problem -> IO ()-writeMPSFile fname prob = -  case MPSFile.render prob of+writeMPSFile :: FileOptions -> FilePath -> Problem Scientific -> IO ()+writeMPSFile opt fname prob =+  case MPSFile.render opt prob of     Left err -> ioError $ userError err-    Right s -> P.writeFile fname s+    Right s ->+      withFile fname WriteMode $ \h -> do+        case optFileEncoding opt of+          Nothing -> return ()+          Just enc -> hSetEncoding h enc+        TLIO.hPutStr h s -toLPString :: Problem -> Either String String+toLPString :: FileOptions -> Problem Scientific -> Either String TL.Text toLPString = LPFile.render -toMPSString :: Problem -> Either String String+toMPSString :: FileOptions -> Problem Scientific -> Either String TL.Text toMPSString = MPSFile.render
src/ToySolver/Data/MIP/Base.hs view
@@ -4,7 +4,7 @@ -- Module      :  ToySolver.Data.MIP.Base -- Copyright   :  (c) Masahiro Sakai 2011-2014 -- License     :  BSD-style--- +-- -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  provisional -- Portability :  portable@@ -13,72 +13,105 @@ -- ----------------------------------------------------------------------------- module ToySolver.Data.MIP.Base-  ( Problem (..)+  ( +  -- * The MIP Problem type+    Problem (..)+  , Label++  -- * Variables+  , Var+  , toVar+  , fromVar++  -- ** Variable types+  , VarType (..)+  , getVarType++  -- ** Variable bounds+  , BoundExpr+  , Extended (..)+  , Bounds+  , defaultBounds+  , defaultLB+  , defaultUB+  , getBounds++  -- ** Variable getters+  , variables+  , integerVariables+  , semiContinuousVariables+  , semiIntegerVariables++  -- * Expressions   , Expr (..)   , varExpr   , constExpr   , terms   , Term (..)++  -- * Objective function   , OptDir (..)   , ObjectiveFunction (..)++  -- * Constraints++  -- ** Linear (or Quadratic or Polynomial) constraints   , Constraint (..)   , (.==.)   , (.<=.)   , (.>=.)-  , Bounds-  , Label-  , Var-  , VarType (..)-  , BoundExpr-  , Extended (..)   , RelOp (..)++  -- ** SOS constraints   , SOSType (..)   , SOSConstraint (..)-  , defaultBounds-  , defaultLB-  , defaultUB-  , toVar-  , fromVar-  , getVarType-  , getBounds-  , variables-  , integerVariables-  , semiContinuousVariables-  , semiIntegerVariables +  -- * Solutions+  , Solution (..)+  , Status (..)++  -- * File I/O options+  , FileOptions (..)+   -- * Utilities   , Variables (..)   , intersectBounds   ) where +import Algebra.Lattice+import Algebra.PartialOrd+import Control.Arrow ((***)) import Data.Default.Class import Data.Map (Map) import qualified Data.Map as Map import Data.Set (Set) import qualified Data.Set as Set-import Data.Interned (intern, unintern)-import Data.Interned.String+import Data.Interned (unintern)+import Data.Interned.Text import Data.ExtendedReal import Data.OptDir+import Data.String+import qualified Data.Text as T+import System.IO (TextEncoding)  infix 4 .<=., .>=., .==.  -- ---------------------------------------------------------------------------  -- | Problem-data Problem+data Problem c   = Problem-  { name :: Maybe String-  , objectiveFunction :: ObjectiveFunction-  , constraints :: [Constraint]-  , sosConstraints :: [SOSConstraint]-  , userCuts :: [Constraint]+  { name :: Maybe T.Text+  , objectiveFunction :: ObjectiveFunction c+  , constraints :: [Constraint c]+  , sosConstraints :: [SOSConstraint c]+  , userCuts :: [Constraint c]   , varType :: Map Var VarType-  , varBounds :: Map Var Bounds+  , varBounds :: Map Var (Bounds c)   }   deriving (Show, Eq, Ord) -instance Default Problem where+instance Default (Problem c) where   def = Problem         { name = Nothing         , objectiveFunction = def@@ -89,21 +122,88 @@         , varBounds = Map.empty         } +instance Functor Problem where+  fmap f prob =+    prob+    { objectiveFunction = fmap f (objectiveFunction prob)+    , constraints       = map (fmap f) (constraints prob)+    , sosConstraints    = map (fmap f) (sosConstraints prob)+    , userCuts          = map (fmap f) (userCuts prob)+    , varBounds         = fmap (fmap f *** fmap f) (varBounds prob)+    }++-- | label+type Label = T.Text++-- ---------------------------------------------------------------------------++-- | variable+type Var = InternedText++-- | convert a string into a variable+toVar :: String -> Var+toVar = fromString++-- | convert a variable into a string+fromVar :: Var -> String+fromVar = T.unpack . unintern++data VarType+  = ContinuousVariable+  | IntegerVariable+  | SemiContinuousVariable+  | SemiIntegerVariable+  deriving (Eq, Ord, Show)++instance Default VarType where+  def = ContinuousVariable++-- | looking up bounds for a variable+getVarType :: Problem c -> Var -> VarType+getVarType mip v = Map.findWithDefault def v (varType mip)++-- | type for representing lower/upper bound of variables+type BoundExpr c = Extended c++-- | type for representing lower/upper bound of variables+type Bounds c = (BoundExpr c, BoundExpr c)++-- | default bounds+defaultBounds :: Num c => Bounds c+defaultBounds = (defaultLB, defaultUB)++-- | default lower bound (0)+defaultLB :: Num c => BoundExpr c+defaultLB = Finite 0++-- | default upper bound (+∞)+defaultUB :: BoundExpr c+defaultUB = PosInf++-- | looking up bounds for a variable+getBounds :: Num c => Problem c -> Var -> Bounds c+getBounds mip v = Map.findWithDefault defaultBounds v (varBounds mip)++intersectBounds :: Ord c => Bounds c -> Bounds c -> Bounds c+intersectBounds (lb1,ub1) (lb2,ub2) = (max lb1 lb2, min ub1 ub2)++-- ---------------------------------------------------------------------------+ -- | expressions-newtype Expr = Expr [Term]+newtype Expr c = Expr [Term c]   deriving (Eq, Ord, Show) -varExpr :: Var -> Expr+varExpr :: Num c => Var -> Expr c varExpr v = Expr [Term 1 [v]] -constExpr :: Rational -> Expr+constExpr :: (Eq c, Num c) => c -> Expr c constExpr 0 = Expr [] constExpr c = Expr [Term c []]-           -terms :: Expr -> [Term]++terms :: Expr c -> [Term c] terms (Expr ts) = ts -instance Num Expr where+instance Num c => Num (Expr c) where   Expr e1 + Expr e2 = Expr (e1 ++ e2)   Expr e1 * Expr e2 = Expr [Term (c1*c2) (vs1 ++ vs2) | Term c1 vs1 <- e1, Term c2 vs2 <- e2]   negate (Expr e) = Expr [Term (-c) vs | Term c vs <- e]@@ -112,113 +212,187 @@   fromInteger 0 = Expr []   fromInteger c = Expr [Term (fromInteger c) []] +instance Functor Expr where+  fmap f (Expr ts) = Expr $ map (fmap f) ts++splitConst :: Num c => Expr c -> (Expr c, c)+splitConst e = (e2, c2)+  where+    e2 = Expr [t | t@(Term _ (_:_)) <- terms e]+    c2 = sum [c | Term c [] <- terms e]+ -- | terms-data Term = Term Rational [Var]+data Term c = Term c [Var]   deriving (Eq, Ord, Show) +instance Functor Term where+  fmap f (Term c vs) = Term (f c) vs++-- ---------------------------------------------------------------------------+ -- | objective function-data ObjectiveFunction+data ObjectiveFunction c   = ObjectiveFunction   { objLabel :: Maybe Label   , objDir :: OptDir-  , objExpr :: Expr+  , objExpr :: Expr c   }   deriving (Eq, Ord, Show) -instance Default ObjectiveFunction where+instance Default (ObjectiveFunction c) where   def =     ObjectiveFunction     { objLabel = Nothing     , objDir = OptMin-    , objExpr = 0+    , objExpr = Expr []     } +instance Functor ObjectiveFunction where+  fmap f obj = obj{ objExpr = fmap f (objExpr obj) }++-- ---------------------------------------------------------------------------+ -- | constraint-data Constraint+data Constraint c   = Constraint   { constrLabel     :: Maybe Label-  , constrIndicator :: Maybe (Var, Rational)-  , constrExpr      :: Expr-  , constrLB        :: BoundExpr-  , constrUB        :: BoundExpr+  , constrIndicator :: Maybe (Var, c)+  , constrExpr      :: Expr c+  , constrLB        :: BoundExpr c+  , constrUB        :: BoundExpr c   , constrIsLazy    :: Bool   }   deriving (Eq, Ord, Show) -(.==.) :: Expr -> Expr -> Constraint+(.==.) :: Num c => Expr c -> Expr c -> Constraint c lhs .==. rhs =   case splitConst (lhs - rhs) of     (e, c) -> def{ constrExpr = e, constrLB = Finite (- c), constrUB = Finite (- c) } -(.<=.) :: Expr -> Expr -> Constraint+(.<=.) :: Num c => Expr c -> Expr c -> Constraint c lhs .<=. rhs =   case splitConst (lhs - rhs) of     (e, c) -> def{ constrExpr = e, constrUB = Finite (- c) } -(.>=.) :: Expr -> Expr -> Constraint+(.>=.) :: Num c => Expr c -> Expr c -> Constraint c lhs .>=. rhs =   case splitConst (lhs - rhs) of     (e, c) -> def{ constrExpr = e, constrLB = Finite (- c) } -splitConst :: Expr -> (Expr, Rational)-splitConst e = (e2, c)-  where-    e2 = Expr [t | t@(Term _ (_:_)) <- terms e]-    c = sum [c | Term c [] <- terms e]-    -instance Default Constraint where+instance Default (Constraint c) where   def = Constraint         { constrLabel = Nothing         , constrIndicator = Nothing-        , constrExpr = 0-        , constrLB = -inf-        , constrUB = inf+        , constrExpr = Expr []+        , constrLB = NegInf+        , constrUB = PosInf         , constrIsLazy = False         } -data VarType-  = ContinuousVariable-  | IntegerVariable--- 'nothaddock' is inserted not to confuse haddock-  -- nothaddock | BinaryVariable-  | SemiContinuousVariable-  | SemiIntegerVariable-  deriving (Eq, Ord, Show)--instance Default VarType where-  def = ContinuousVariable---- | type for representing lower/upper bound of variables-type Bounds = (BoundExpr, BoundExpr)---- | label-type Label = String---- | variable-type Var = InternedString---- | type for representing lower/upper bound of variables-type BoundExpr = Extended Rational+instance Functor Constraint where+  fmap f c =+    c+    { constrIndicator = fmap (id *** f) (constrIndicator c)+    , constrExpr = fmap f (constrExpr c)+    , constrLB = fmap f (constrLB c)+    , constrUB = fmap f (constrUB c)+    }  -- | relational operators data RelOp = Le | Ge | Eql-    deriving (Eq, Ord, Enum, Show)+  deriving (Eq, Ord, Enum, Show) +-- ---------------------------------------------------------------------------+ -- | types of SOS (special ordered sets) constraints data SOSType   = S1 -- ^ Type 1 SOS constraint   | S2 -- ^ Type 2 SOS constraint-    deriving (Eq, Ord, Enum, Show, Read)+  deriving (Eq, Ord, Enum, Show, Read)  -- | SOS (special ordered sets) constraints-data SOSConstraint+data SOSConstraint c   = SOSConstraint   { sosLabel :: Maybe Label   , sosType  :: SOSType-  , sosBody  :: [(Var, Rational)]+  , sosBody  :: [(Var, c)]   }   deriving (Eq, Ord, Show) +instance Functor SOSConstraint where+  fmap f c = c{ sosBody = map (id *** f) (sosBody c) }++-- ---------------------------------------------------------------------------++-- | MIP status with the following partial order:+-- +-- <<doc-images/MIP-Status-diagram.png>>+data Status+  = StatusUnknown+  | StatusFeasible+  | StatusOptimal+  | StatusInfeasibleOrUnbounded+  | StatusInfeasible+  | StatusUnbounded+  deriving (Eq, Ord, Enum, Bounded, Show)++instance PartialOrd Status where+  leq a b = (a,b) `Set.member` rel+    where+      rel = unsafeLfpFrom rel0 $ \r ->+        Set.union r (Set.fromList [(a,c) | (a,b) <- Set.toList r, (b',c) <- Set.toList r, b == b'])+      rel0 = Set.fromList $+        [(a,a) | a <- [minBound .. maxBound]] +++        [ (StatusUnknown, StatusFeasible)+        , (StatusUnknown, StatusInfeasibleOrUnbounded)+        , (StatusFeasible, StatusOptimal)+        , (StatusFeasible, StatusUnbounded)+        , (StatusInfeasibleOrUnbounded, StatusUnbounded)+        , (StatusInfeasibleOrUnbounded, StatusInfeasible)+        ]++instance MeetSemiLattice Status where+  StatusUnknown `meet` b = StatusUnknown+  StatusFeasible `meet` b+    | StatusFeasible `leq` b = StatusFeasible+    | otherwise = StatusUnknown+  StatusOptimal `meet` StatusOptimal = StatusOptimal+  StatusOptimal `meet` b+    | StatusFeasible `leq` b = StatusFeasible+    | otherwise = StatusUnknown+  StatusInfeasibleOrUnbounded `meet` b+    | StatusInfeasibleOrUnbounded `leq` b = StatusInfeasibleOrUnbounded+    | otherwise = StatusUnknown+  StatusInfeasible `meet` StatusInfeasible = StatusInfeasible+  StatusInfeasible `meet` b+    | StatusInfeasibleOrUnbounded `leq` b = StatusInfeasibleOrUnbounded+    | otherwise = StatusUnknown+  StatusUnbounded `meet` StatusUnbounded = StatusUnbounded+  StatusUnbounded `meet` b+    | StatusFeasible `leq` b = StatusFeasible+    | StatusInfeasibleOrUnbounded `leq` b = StatusInfeasibleOrUnbounded+    | otherwise = StatusUnknown++data Solution r+  = Solution+  { solStatus :: Status+  , solObjectiveValue :: Maybe r+  , solVariables :: Map Var r+  }+  deriving (Eq, Ord, Show)++instance Functor Solution where+  fmap f (Solution status obj vs) = Solution status (fmap f obj) (fmap f vs)++instance Default (Solution r) where+  def = Solution+        { solStatus = StatusUnknown+        , solObjectiveValue = Nothing+        , solVariables = Map.empty+        }++-- ---------------------------------------------------------------------------+ class Variables a where   vars :: a -> Set Var @@ -229,65 +403,49 @@   vars (Left a)  = vars a   vars (Right b) = vars b -instance Variables Problem where+instance Variables (Problem c) where   vars = variables -instance Variables Expr where+instance Variables (Expr c) where   vars (Expr e) = vars e -instance Variables Term where+instance Variables (Term c) where   vars (Term _ xs) = Set.fromList xs -instance Variables ObjectiveFunction where+instance Variables (ObjectiveFunction c) where   vars ObjectiveFunction{ objExpr = e } = vars e -instance Variables Constraint where+instance Variables (Constraint c) where   vars Constraint{ constrIndicator = ind, constrExpr = e } = Set.union (vars e) vs2     where       vs2 = maybe Set.empty (Set.singleton . fst) ind -instance Variables SOSConstraint where+instance Variables (SOSConstraint c) where   vars SOSConstraint{ sosBody = xs } = Set.fromList (map fst xs) --- | default bounds-defaultBounds :: Bounds-defaultBounds = (defaultLB, defaultUB)---- | default lower bound (0)-defaultLB :: BoundExpr-defaultLB = 0---- | default upper bound (+∞)-defaultUB :: BoundExpr-defaultUB = PosInf---- | convert a string into a variable-toVar :: String -> Var-toVar = intern---- | convert a variable into a string-fromVar :: Var -> String-fromVar = unintern---- | looking up bounds for a variable-getVarType :: Problem -> Var -> VarType-getVarType mip v = Map.findWithDefault def v (varType mip)---- | looking up bounds for a variable-getBounds :: Problem -> Var -> Bounds-getBounds mip v = Map.findWithDefault defaultBounds v (varBounds mip)--intersectBounds :: Bounds -> Bounds -> Bounds-intersectBounds (lb1,ub1) (lb2,ub2) = (max lb1 lb2, min ub1 ub2)+-- --------------------------------------------------------------------------- -variables :: Problem -> Set Var+variables :: Problem c -> Set Var variables mip = Map.keysSet $ varType mip -integerVariables :: Problem -> Set Var+integerVariables :: Problem c -> Set Var integerVariables mip = Map.keysSet $ Map.filter (IntegerVariable ==) (varType mip) -semiContinuousVariables :: Problem -> Set Var+semiContinuousVariables :: Problem c -> Set Var semiContinuousVariables mip = Map.keysSet $ Map.filter (SemiContinuousVariable ==) (varType mip) -semiIntegerVariables :: Problem -> Set Var+semiIntegerVariables :: Problem c -> Set Var semiIntegerVariables mip = Map.keysSet $ Map.filter (SemiIntegerVariable ==) (varType mip)++-- ---------------------------------------------------------------------------++data FileOptions+  = FileOptions+  { optFileEncoding :: Maybe TextEncoding+  } deriving (Show)++instance Default FileOptions where+  def =+    FileOptions+    { optFileEncoding = Nothing+    }
src/ToySolver/Data/MIP/LPFile.hs view
@@ -1,23 +1,29 @@-{-# LANGUAGE OverloadedStrings, BangPatterns #-} {-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}+{-# LANGUAGE BangPatterns  #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts  #-}+{-# LANGUAGE OverloadedStrings  #-}+{-# LANGUAGE ScopedTypeVariables  #-}+{-# LANGUAGE TypeFamilies #-} ----------------------------------------------------------------------------- -- | -- Module      :  ToySolver.Data.MIP.LPFile -- Copyright   :  (c) Masahiro Sakai 2011-2014 -- License     :  BSD-style--- +-- -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  provisional--- Portability :  portable+-- Portability :  non-portable -- -- A CPLEX .lp format parser library.--- +-- -- References:--- +-- -- * <http://publib.boulder.ibm.com/infocenter/cosinfoc/v12r2/index.jsp?topic=/ilog.odms.cplex.help/Content/Optimization/Documentation/CPLEX/_pubskel/CPLEX880.html>--- +-- -- * <http://www.gurobi.com/doc/45/refman/node589.html>--- +-- -- * <http://lpsolve.sourceforge.net/5.5/CPLEX-format.htm> -- -----------------------------------------------------------------------------@@ -28,80 +34,131 @@   , render   ) where -import Control.Applicative ((<*))+import Control.Applicative+import Control.Exception (throw) import Control.Monad import Control.Monad.Writer import Control.Monad.ST import Data.Char import Data.Default.Class+import Data.Interned import Data.List import Data.Maybe-import Data.Ratio+import Data.Monoid+import Data.Scientific (Scientific)+#if !MIN_VERSION_megaparsec(5,0,0)+import Data.Scientific (fromFloatDigits)+#endif import Data.Map (Map) import qualified Data.Map as Map import Data.Set (Set) import qualified Data.Set as Set import Data.STRef+import Data.String+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import Data.Text.Lazy.Builder (Builder)+import qualified Data.Text.Lazy.Builder as B+import qualified Data.Text.Lazy.Builder.Scientific as B+import qualified Data.Text.Lazy.IO as TLIO import Data.OptDir-import Text.Parsec hiding (label)-import Text.Parsec.String+#if MIN_VERSION_megaparsec(6,0,0)+import Data.Void+#endif+import System.IO+#if MIN_VERSION_megaparsec(6,0,0)+import Text.Megaparsec hiding (label, skipManyTill)+import Text.Megaparsec.Char hiding (string', char')+import qualified Text.Megaparsec.Char.Lexer as P+#else+import Text.Megaparsec hiding (label, string', char')+import qualified Text.Megaparsec.Lexer as P+import Text.Megaparsec.Prim (MonadParsec ())+#endif  import qualified ToySolver.Data.MIP.Base as MIP import ToySolver.Internal.Util (combineMaybe)-import ToySolver.Internal.TextUtil (readUnsignedInteger)  -- --------------------------------------------------------------------------- +#if MIN_VERSION_megaparsec(6,0,0)+type C e s m = (MonadParsec e s m, Token s ~ Char, IsString (Tokens s))+#elif MIN_VERSION_megaparsec(5,0,0)+type C e s m = (MonadParsec e s m, Token s ~ Char)+#else+type C e s m = (MonadParsec s m Char)+#endif+ -- | Parse a string containing LP file data. -- The source name is only | used in error messages and may be the empty string.-parseString :: SourceName -> String -> Either ParseError MIP.Problem-parseString = parse (parser <* eof)+#if MIN_VERSION_megaparsec(6,0,0)+parseString :: (Stream s, Token s ~ Char, IsString (Tokens s)) => MIP.FileOptions -> String -> s -> Either (ParseError Char Void) (MIP.Problem Scientific)+#elif MIN_VERSION_megaparsec(5,0,0)+parseString :: (Stream s, Token s ~ Char) => MIP.FileOptions -> String -> s -> Either (ParseError Char Dec) (MIP.Problem Scientific)+#else+parseString :: Stream s Char => MIP.FileOptions -> String -> s -> Either ParseError (MIP.Problem Scientific)+#endif+parseString _ = parse (parser <* eof)  -- | Parse a file containing LP file data.-parseFile :: FilePath -> IO (Either ParseError MIP.Problem)-parseFile = parseFromFile (parser <* eof)+parseFile :: MIP.FileOptions -> FilePath -> IO (MIP.Problem Scientific)+parseFile opt fname = do+  h <- openFile fname ReadMode+  case MIP.optFileEncoding opt of+    Nothing -> return ()+    Just enc -> hSetEncoding h enc+  ret <- parse (parser <* eof) fname <$> TLIO.hGetContents h+  case ret of+#if MIN_VERSION_megaparsec(6,0,0)+    Left e -> throw (e :: ParseError Char Void)+#elif MIN_VERSION_megaparsec(5,0,0)+    Left e -> throw (e :: ParseError Char Dec)+#else+    Left e -> throw (e :: ParseError)+#endif+    Right a -> return a  -- --------------------------------------------------------------------------- -char' :: Char -> Parser Char+char' :: C e s m => Char -> m Char char' c = (char c <|> char (toUpper c)) <?> show c -string' :: String -> Parser ()+string' :: C e s m => String -> m () string' s = mapM_ char' s <?> show s -sep :: Parser ()-sep = skipMany ((comment >> return ()) <|> (space >> return ()))+sep :: C e s m => m ()+sep = skipMany ((comment >> return ()) <|> (spaceChar >> return ())) -comment :: Parser String+comment :: C e s m => m () comment = do   char '\\'-  manyTill anyChar (try newline)+  skipManyTill anyChar (try newline) -tok :: Parser a -> Parser a+tok :: C e s m => m a -> m a tok p = do   x <- p   sep   return x -ident :: Parser String+ident :: C e s m => m String ident = tok $ do-  x <- letter <|> oneOf syms1 -  xs <- many (alphaNum <|> oneOf syms2)-  let s = x:xs +  x <- letterChar <|> oneOf syms1+  xs <- many (alphaNumChar <|> oneOf syms2)+  let s = x:xs   guard $ map toLower s `Set.notMember` reserved   return s   where     syms1 = "!\"#$%&()/,;?@_`'{}|~"     syms2 = '.' : syms1 -variable :: Parser MIP.Var+variable :: C e s m => m MIP.Var variable = liftM MIP.toVar ident -label :: Parser MIP.Label+label :: C e s m => m MIP.Label label = do   name <- ident   tok $ char ':'-  return name+  return $! T.pack name  reserved :: Set String reserved = Set.fromList@@ -117,12 +174,18 @@ -- ---------------------------------------------------------------------------  -- | LP file parser-parser :: Parser MIP.Problem+#if MIN_VERSION_megaparsec(6,0,0)+parser :: (MonadParsec e s m, Token s ~ Char, IsString (Tokens s)) => m (MIP.Problem Scientific)+#elif MIN_VERSION_megaparsec(5,0,0)+parser :: (MonadParsec e s m, Token s ~ Char) => m (MIP.Problem Scientific)+#else+parser :: MonadParsec s m Char => m (MIP.Problem Scientific)+#endif parser = do-  name <- optionMaybe $ try $ do-    spaces-    string' "\\* Problem: " -    manyTill anyChar (try (string " *\\\n"))+  name <- optional $ try $ do+    space+    string' "\\* Problem: "+    liftM fromString $ manyTill anyChar (try (string " *\\\n"))   sep   obj <- problem @@ -172,27 +235,27 @@     , MIP.varBounds         = Map.fromAscList [ (v, Map.findWithDefault MIP.defaultBounds v bnds2) | v <- Set.toAscList vs]     } -problem :: Parser MIP.ObjectiveFunction+problem :: C e s m => m (MIP.ObjectiveFunction Scientific) problem = do   flag <-  (try minimize >> return OptMin)        <|> (try maximize >> return OptMax)-  name <- optionMaybe (try label)+  name <- optional (try label)   obj <- expr   return def{ MIP.objLabel = name, MIP.objDir = flag, MIP.objExpr = obj } -minimize, maximize :: Parser ()-minimize = tok $ string' "min" >> optional (string' "imize")-maximize = tok $ string' "max" >> optional (string' "imize")+minimize, maximize :: C e s m => m ()+minimize = tok $ string' "min" >> optional (string' "imize") >> return ()+maximize = tok $ string' "max" >> optional (string' "imize") >> return () -end :: Parser ()+end :: C e s m => m () end = tok $ string' "end"  -- --------------------------------------------------------------------------- -constraintSection :: Parser [MIP.Constraint]+constraintSection :: C e s m => m [MIP.Constraint Scientific] constraintSection = subjectTo >> many (try (constraint False)) -subjectTo :: Parser ()+subjectTo :: C e s m => m () subjectTo = msum   [ try $ tok (string' "subject") >> tok (string' "to")   , try $ tok (string' "such") >> tok (string' "that")@@ -201,16 +264,10 @@         >> tok (char '.') >> return ()   ] -constraint :: Bool -> Parser MIP.Constraint+constraint :: C e s m => Bool -> m (MIP.Constraint Scientific) constraint isLazy = do-  name <- optionMaybe (try label)--  g <- optionMaybe $ try $ do-    var <- variable-    tok (char '=')-    val <- tok ((char '0' >> return 0) <|> (char '1' >> return 1))-    tok $ string "->"-    return (var, val)+  name <- optional (try label)+  g <- optional $ try indicator    -- It seems that CPLEX allows empty lhs, but GLPK rejects it.   e <- expr@@ -223,7 +280,7 @@           MIP.Le -> (MIP.NegInf, MIP.Finite rhs)           MIP.Ge -> (MIP.Finite rhs, MIP.PosInf)           MIP.Eql -> (MIP.Finite rhs, MIP.Finite rhs)-         +   return $ MIP.Constraint     { MIP.constrLabel     = name     , MIP.constrIndicator = g@@ -233,7 +290,7 @@     , MIP.constrIsLazy    = isLazy     } -relOp :: Parser MIP.RelOp+relOp :: C e s m => m MIP.RelOp relOp = tok $ msum   [ char '<' >> optional (char '=') >> return MIP.Le   , char '>' >> optional (char '=') >> return MIP.Ge@@ -243,21 +300,29 @@                      ]   ] -lazyConstraintsSection :: Parser [MIP.Constraint]+indicator :: C e s m => m (MIP.Var, Scientific)+indicator = do+  var <- variable+  tok (char '=')+  val <- tok ((char '0' >> return 0) <|> (char '1' >> return 1))+  tok $ string "->"+  return (var, val)++lazyConstraintsSection :: C e s m => m [MIP.Constraint Scientific] lazyConstraintsSection = do   tok $ string' "lazy"   tok $ string' "constraints"   many $ try $ constraint True -userCutsSection :: Parser [MIP.Constraint]+userCutsSection :: C e s m => m [MIP.Constraint Scientific] userCutsSection = do   tok $ string' "user"   tok $ string' "cuts"   many $ try $ constraint False -type Bounds2 = (Maybe MIP.BoundExpr, Maybe MIP.BoundExpr)+type Bounds2 c = (Maybe (MIP.BoundExpr c), Maybe (MIP.BoundExpr c)) -boundsSection :: Parser (Map MIP.Var MIP.Bounds)+boundsSection :: C e s m => m (Map MIP.Var (MIP.Bounds Scientific)) boundsSection = do   tok $ string' "bound" >> optional (char' 's')   liftM (Map.map g . Map.fromListWith f) $ many (try bound)@@ -267,7 +332,7 @@                  , fromMaybe MIP.defaultUB ub                  ) -bound :: Parser (MIP.Var, Bounds2)+bound :: C e s m => m (MIP.Var, Bounds2 Scientific) bound = msum   [ try $ do       v <- try variable@@ -298,8 +363,8 @@       return (v, (b1, b2))   ] -boundExpr :: Parser MIP.BoundExpr-boundExpr = msum +boundExpr :: C e s m => m (MIP.BoundExpr Scientific)+boundExpr = msum   [ try (tok (char '+') >> inf >> return MIP.PosInf)   , try (tok (char '-') >> inf >> return MIP.NegInf)   , do@@ -308,27 +373,27 @@       return $ MIP.Finite (s*x)   ] -inf :: Parser ()-inf = tok (string "inf" >> optional (string "inity"))+inf :: C e s m => m ()+inf = tok (string "inf" >> optional (string "inity")) >> return ()  -- --------------------------------------------------------------------------- -generalSection :: Parser [MIP.Var]+generalSection :: C e s m => m [MIP.Var] generalSection = do   tok $ string' "gen" >> optional (string' "eral" >> optional (string' "s"))   many (try variable) -binarySection :: Parser [MIP.Var]+binarySection :: C e s m => m [MIP.Var] binarySection = do   tok $ string' "bin" >> optional (string' "ar" >> (string' "y" <|> string' "ies"))   many (try variable) -semiSection :: Parser [MIP.Var]+semiSection :: C e s m => m [MIP.Var] semiSection = do   tok $ string' "semi" >> optional (string' "-continuous" <|> string' "s")   many (try variable) -sosSection :: Parser [MIP.SOSConstraint]+sosSection :: C e s m => m [MIP.SOSConstraint Scientific] sosSection = do   tok $ string' "sos"   many $ try $ do@@ -348,28 +413,28 @@  -- --------------------------------------------------------------------------- -expr :: Parser MIP.Expr+expr :: forall e s m. C e s m => m (MIP.Expr Scientific) expr = try expr1 <|> return 0   where-    expr1 :: Parser MIP.Expr+    expr1 :: m (MIP.Expr Scientific)     expr1 = do       t <- term True       ts <- many (term False)-      return $ sum (t : ts)+      return $ foldr (+) 0 (t : ts) -sign :: Num a => Parser a+sign :: (C e s m, Num a) => m a sign = tok ((char '+' >> return 1) <|> (char '-' >> return (-1))) -term :: Bool -> Parser MIP.Expr+term :: C e s m => Bool -> m (MIP.Expr Scientific) term flag = do-  s <- if flag then optionMaybe sign else liftM Just sign-  c <- optionMaybe number+  s <- if flag then optional sign else liftM Just sign+  c <- optional number   e <- liftM MIP.varExpr variable <|> qexpr   return $ case combineMaybe (*) s c of     Nothing -> e     Just d -> MIP.constExpr d * e -qexpr :: Parser MIP.Expr+qexpr :: C e s m => m (MIP.Expr Scientific) qexpr = do   tok (char '[')   t <- qterm True@@ -381,79 +446,69 @@       return $ MIP.constExpr (1/2) * e)    <|> return e -qterm :: Bool -> Parser MIP.Term+qterm :: C e s m => Bool -> m (MIP.Term Scientific) qterm flag = do-  s <- if flag then optionMaybe sign else liftM Just sign-  c <- optionMaybe number-  es <- qfactor `chainl1`  (tok (char '*') >> return (++))+  s <- if flag then optional sign else liftM Just sign+  c <- optional number+  es <- do+    e <- qfactor+    es <- many (tok (char '*') >> qfactor)+    return $ e ++ concat es   return $ case combineMaybe (*) s c of     Nothing -> MIP.Term 1 es     Just d -> MIP.Term d es -qfactor :: Parser [MIP.Var]+qfactor :: C e s m => m [MIP.Var] qfactor = do   v <- variable   msum [ tok (char '^') >> tok (char '2') >> return [v,v]        , return [v]        ] -number :: Parser Rational-number = tok $ do-  b <- (do{ x <- nat; y <- option 0 frac; return (fromInteger x + y) })-    <|> frac-  c <- option 0 e-  return (b*10^^c)-  where-    digits = many1 digit--    nat :: Parser Integer-    nat = liftM readUnsignedInteger digits--    frac :: Parser Rational-    frac = do-      char '.'-      s <- digits-      return (readUnsignedInteger s % 10^(length s))+number :: forall e s m. C e s m => m Scientific+#if MIN_VERSION_megaparsec(6,0,0)+number = tok $ P.signed sep P.scientific+#elif MIN_VERSION_megaparsec(5,0,0)+number = tok $ P.signed sep P.number+#else+number = tok $ liftM (either fromInteger fromFloatDigits) $ P.signed sep P.number+#endif -    e :: Parser Integer-    e = do-      oneOf "eE"-      f <- msum [ char '+' >> return id-                , char '-' >> return negate-                , return id-                ]-      liftM f nat+skipManyTill :: Alternative m => m a -> m end -> m ()+skipManyTill p end' = scan+  where+    scan = (end' *> pure ()) <|> (p *> scan)  -- --------------------------------------------------------------------------- -type M a = Writer ShowS a+type M a = Writer Builder a -execM :: M a -> String-execM m = execWriter m ""+execM :: M a -> TL.Text+execM m = B.toLazyText $ execWriter m -writeString :: String -> M ()-writeString s = tell $ showString s+writeString :: T.Text -> M ()+writeString s = tell $ B.fromText s  writeChar :: Char -> M ()-writeChar c = tell $ showChar c+writeChar c = tell $ B.singleton c  -- ---------------------------------------------------------------------------  -- | Render a problem into a string.-render :: MIP.Problem -> Either String String-render mip = Right $ execM $ render' $ normalize mip+render :: MIP.FileOptions -> MIP.Problem Scientific -> Either String TL.Text+render _ mip = Right $ execM $ render' $ normalize mip  writeVar :: MIP.Var -> M ()-writeVar v = writeString $ MIP.fromVar v+writeVar v = writeString $ unintern v -render' :: MIP.Problem -> M ()+render' :: MIP.Problem Scientific -> M () render' mip = do   case MIP.name mip of-    Just name -> writeString $ "\\* Problem: " ++ name ++ " *\\\n"+    Just name -> writeString $ "\\* Problem: " <> name <> " *\\\n"     Nothing -> return () -  let obj = MIP.objectiveFunction mip   -  +  let obj = MIP.objectiveFunction mip+   writeString $     case MIP.objDir obj of       OptMin -> "MINIMIZE"@@ -514,19 +569,19 @@     writeString "SOS\n"     forM_ (MIP.sosConstraints mip) $ \(MIP.SOSConstraint l typ xs) -> do       renderLabel l-      writeString $ show typ+      writeString $ fromString $ show typ       writeString " ::"       forM_ xs $ \(v, r) -> do         writeString "  "         writeVar v         writeString " : "-        writeString $ showValue r+        tell $ B.scientificBuilder r       writeChar '\n'    writeString "END\n"  -- FIXME: Gurobi は quadratic term が最後に一つある形式でないとダメっぽい-renderExpr :: Bool -> MIP.Expr -> M ()+renderExpr :: Bool -> MIP.Expr Scientific -> M () renderExpr isObj e = fill 80 (ts1 ++ ts2)   where     (ts,qts) = partition isLin (MIP.terms e)@@ -542,36 +597,32 @@         -- SCIP-3.1.0 does not allow spaces between '/' and '2'.         ["+ ["] ++ map g qts ++ [if isObj then "] /2" else "]"] -    f :: MIP.Term -> String+    f :: MIP.Term Scientific -> T.Text     f (MIP.Term c [])  = showConstTerm c-    f (MIP.Term c [v]) = showCoeff c ++ MIP.fromVar v+    f (MIP.Term c [v]) = showCoeff c <> fromString (MIP.fromVar v)     f _ = error "should not happen" -    g :: MIP.Term -> String-    g (MIP.Term c vs) = -      (if isObj then showCoeff (2*c) else showCoeff c) ++-      intercalate " * " (map MIP.fromVar vs)+    g :: MIP.Term Scientific -> T.Text+    g (MIP.Term c vs) =+      (if isObj then showCoeff (2*c) else showCoeff c) <>+      mconcat (intersperse " * " (map (fromString . MIP.fromVar) vs)) -showValue :: Rational -> String-showValue c =-  if denominator c == 1-    then show (numerator c)-    else show (fromRational c :: Double)+showValue :: Scientific -> T.Text+showValue = fromString . show -showCoeff :: Rational -> String+showCoeff :: Scientific -> T.Text showCoeff c =   if c' == 1     then s-    else s ++ showValue c' ++ " "+    else s <> showValue c' <> " "   where     c' = abs c     s = if c >= 0 then "+ " else "- " -showConstTerm :: Rational -> String-showConstTerm c = s ++ v+showConstTerm :: Scientific -> T.Text+showConstTerm c = s <> showValue (abs c)   where     s = if c >= 0 then "+ " else "- "-    v = showValue (abs c)  renderLabel :: Maybe MIP.Label -> M () renderLabel l =@@ -584,7 +635,7 @@ renderOp MIP.Ge = writeString ">=" renderOp MIP.Eql = writeString "=" -renderConstraint :: MIP.Constraint -> M ()+renderConstraint :: MIP.Constraint Scientific -> M () renderConstraint c@MIP.Constraint{ MIP.constrExpr = e, MIP.constrLB = lb, MIP.constrUB = ub } = do   renderLabel (MIP.constrLabel c)   case MIP.constrIndicator c of@@ -592,7 +643,7 @@     Just (v,vval) -> do       writeVar v       writeString " = "-      writeString $ showValue vval+      tell $ B.scientificBuilder vval       writeString " -> "    renderExpr False e@@ -605,30 +656,30 @@           _ -> error "ToySolver.Data.MIP.LPFile.renderConstraint: should not happen"   renderOp op   writeChar ' '-  writeString $ showValue val+  tell $ B.scientificBuilder val -renderBoundExpr :: MIP.BoundExpr -> M ()-renderBoundExpr (MIP.Finite r) = writeString $ showValue r+renderBoundExpr :: MIP.BoundExpr Scientific -> M ()+renderBoundExpr (MIP.Finite r) = tell $ B.scientificBuilder r renderBoundExpr MIP.NegInf = writeString "-inf" renderBoundExpr MIP.PosInf = writeString "+inf"  renderVariableList :: [MIP.Var] -> M ()-renderVariableList vs = fill 80 (map MIP.fromVar vs) >> writeChar '\n'+renderVariableList vs = fill 80 (map unintern vs) >> writeChar '\n' -fill :: Int -> [String] -> M ()+fill :: Int -> [T.Text] -> M () fill width str = go str 0   where     go [] _ = return ()-    go (x:xs) 0 = writeString x >> go xs (length x)+    go (x:xs) 0 = writeString x >> go xs (T.length x)     go (x:xs) w =-      if w + 1 + length x <= width-        then writeChar ' ' >> writeString x >> go xs (w + 1 + length x)+      if w + 1 + T.length x <= width+        then writeChar ' ' >> writeString x >> go xs (w + 1 + T.length x)         else writeChar '\n' >> go (x:xs) 0  -- ---------------------------------------------------------------------------  {--compileExpr :: Expr -> Maybe (Map Var Rational)+compileExpr :: Expr -> Maybe (Map Var Scientific) compileExpr e = do   xs <- forM e $ \(Term c vs) ->     case vs of@@ -639,15 +690,15 @@  -- --------------------------------------------------------------------------- -normalize :: MIP.Problem -> MIP.Problem+normalize :: (Eq r, Num r) => MIP.Problem r -> MIP.Problem r normalize = removeEmptyExpr . removeRangeConstraints -removeRangeConstraints :: MIP.Problem -> MIP.Problem+removeRangeConstraints :: (Eq r, Num r) => MIP.Problem r -> MIP.Problem r removeRangeConstraints prob = runST $ do   vsRef <- newSTRef $ MIP.variables prob   cntRef <- newSTRef (0::Int)   newvsRef <- newSTRef []-            +   let gensym = do         vs <- readSTRef vsRef         let loop !c = do@@ -671,8 +722,8 @@         return $           c           { MIP.constrExpr = MIP.constrExpr c - MIP.varExpr v-          , MIP.constrLB = 0-          , MIP.constrUB = 0+          , MIP.constrLB = MIP.Finite 0+          , MIP.constrUB = MIP.Finite 0           }    newvs <- liftM reverse $ readSTRef newvsRef@@ -682,8 +733,8 @@     , MIP.varType = MIP.varType prob `Map.union` Map.fromList [(v, MIP.ContinuousVariable) | (v,_) <- newvs]     , MIP.varBounds = MIP.varBounds prob `Map.union` (Map.fromList newvs)     }-          -removeEmptyExpr :: MIP.Problem -> MIP.Problem++removeEmptyExpr :: Num r => MIP.Problem r -> MIP.Problem r removeEmptyExpr prob =   prob   { MIP.objectiveFunction = obj{ MIP.objExpr = convertExpr (MIP.objExpr obj) }@@ -692,7 +743,7 @@   }   where     obj = MIP.objectiveFunction prob-    +     convertExpr (MIP.Expr []) = MIP.Expr [MIP.Term 0 [MIP.toVar "x0"]]     convertExpr e = e 
src/ToySolver/Data/MIP/MPSFile.hs view
@@ -1,23 +1,28 @@-{-# LANGUAGE TypeFamilies #-} {-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-} ----------------------------------------------------------------------------- -- | -- Module      :  ToySolver.Data.MIP.MPSFile -- Copyright   :  (c) Masahiro Sakai 2012-2014 -- License     :  BSD-style--- +-- -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  provisional--- Portability :  non-portable (TypeFamilies)+-- Portability :  non-portable -- -- A .mps format parser library.--- +-- -- References:--- +-- -- * <http://pic.dhe.ibm.com/infocenter/cosinfoc/v12r4/topic/ilog.odms.cplex.help/CPLEX/File_formats_reference/topics/MPS_synopsis.html>--- +-- -- * <http://pic.dhe.ibm.com/infocenter/cosinfoc/v12r4/topic/ilog.odms.cplex.help/CPLEX/File_formats_reference/topics/MPS_ext_synopsis.html>--- +-- -- * <http://www.gurobi.com/documentation/5.0/reference-manual/node744> -- -- * <http://en.wikipedia.org/wiki/MPS_(format)>@@ -30,30 +35,47 @@   , render   ) where -import Control.Applicative ((<*))+import Control.Applicative ((<$>), (<*))+import Control.Exception (throw) import Control.Monad import Control.Monad.Writer import Data.Default.Class import Data.Maybe+import Data.Monoid import Data.Set (Set) import qualified Data.Set as Set import Data.Map (Map) import qualified Data.Map as Map-import Data.Ratio+import Data.Scientific import Data.Interned-import Data.Interned.String--import qualified Text.Parsec as P-import Text.Parsec hiding (spaces, newline, Column)-import Text.Parsec.String-import Text.Printf+import Data.Interned.Text+import Data.String+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import Data.Text.Lazy.Builder (Builder)+import qualified Data.Text.Lazy.Builder as B+import qualified Data.Text.Lazy.IO as TLIO+#if MIN_VERSION_megaparsec(6,0,0)+import Data.Void+#endif+import System.IO+#if MIN_VERSION_megaparsec(6,0,0)+import Text.Megaparsec+import Text.Megaparsec.Char hiding (string', newline)+import qualified Text.Megaparsec.Char as P+import qualified Text.Megaparsec.Char.Lexer as Lexer+#else+import qualified Text.Megaparsec as P+import Text.Megaparsec hiding (string', newline)+import qualified Text.Megaparsec.Lexer as Lexer+import Text.Megaparsec.Prim (MonadParsec ())+#endif  import Data.OptDir import qualified ToySolver.Data.MIP.Base as MIP-import ToySolver.Internal.TextUtil (readUnsignedInteger)  type Column = MIP.Var-type Row = InternedString+type Row = InternedText  data BoundType   = LO  -- lower bound@@ -71,91 +93,104 @@  -- --------------------------------------------------------------------------- +#if MIN_VERSION_megaparsec(6,0,0)+type C e s m = (MonadParsec e s m, Token s ~ Char, IsString (Tokens s))+#elif MIN_VERSION_megaparsec(5,0,0)+type C e s m = (MonadParsec e s m, Token s ~ Char)+#else+type C e s m = (MonadParsec s m Char)+#endif+ -- | Parse a string containing MPS file data. -- The source name is only | used in error messages and may be the empty string.-parseString :: SourceName -> String -> Either ParseError MIP.Problem-parseString = parse (parser <* eof)+#if MIN_VERSION_megaparsec(6,0,0)+parseString :: (Stream s, Token s ~ Char, IsString (Tokens s)) => MIP.FileOptions -> String -> s -> Either (ParseError Char Void) (MIP.Problem Scientific)+#elif MIN_VERSION_megaparsec(5,0,0)+parseString :: (Stream s, Token s ~ Char) => MIP.FileOptions -> String -> s -> Either (ParseError Char Dec) (MIP.Problem Scientific)+#else+parseString :: Stream s Char => MIP.FileOptions -> String -> s -> Either ParseError (MIP.Problem Scientific)+#endif+parseString _ = parse (parser <* eof)  -- | Parse a file containing MPS file data.-parseFile :: FilePath -> IO (Either ParseError MIP.Problem)-parseFile = parseFromFile (parser <* eof)+parseFile :: MIP.FileOptions -> FilePath -> IO (MIP.Problem Scientific)+parseFile opt fname = do+  h <- openFile fname ReadMode+  case MIP.optFileEncoding opt of+    Nothing -> return ()+    Just enc -> hSetEncoding h enc+  ret <- parse (parser <* eof) fname <$> TLIO.hGetContents h+  case ret of+#if MIN_VERSION_megaparsec(6,0,0)+    Left e -> throw (e :: ParseError Char Void)+#elif MIN_VERSION_megaparsec(5,0,0)+    Left e -> throw (e :: ParseError Char Dec)+#else+    Left e -> throw (e :: ParseError)+#endif+    Right a -> return a  -- --------------------------------------------------------------------------- -space' :: Parser Char+space' :: C e s m => m Char space' = oneOf [' ', '\t'] -spaces' :: Parser ()+spaces' :: C e s m => m () spaces' = skipMany space' -spaces1' :: Parser ()-spaces1' = skipMany1 space'+spaces1' :: C e s m => m ()+spaces1' = skipSome space' -commentline :: Parser ()+commentline :: C e s m => m () commentline = do   _ <- char '*'   _ <- manyTill anyChar P.newline   return () -newline' :: Parser ()+newline' :: C e s m => m () newline' = do   spaces'   _ <- P.newline   skipMany commentline   return () -tok :: Parser a -> Parser a+tok :: C e s m => m a -> m a tok p = do   x <- p-  msum [spaces1', lookAhead (try (char '\n' >> return ())), eof]+  msum [eof, lookAhead (char '\n' >> return ()), spaces1']   return x -row :: Parser Row+row :: C e s m => m Row row = liftM intern ident -column :: Parser Column-column = liftM MIP.toVar ident--ident :: Parser String-ident = tok $ many1 $ noneOf [' ', '\t', '\n']--stringLn :: String -> Parser ()-stringLn s = string s >> newline'--sign :: Num a => Parser a-sign = (char '+' >> return 1) <|> (char '-' >> return (-1))--number :: Parser Rational-number = tok $ do-  b <- (do{ s <- option 1 sign; x <- nat; y <- option 0 frac; return (s * (fromInteger x + y)) })-    <|> frac-  c <- option 0 e-  return (b*10^^c)-  where-    digits = many1 digit+column :: C e s m => m Column+column = liftM intern $ ident -    nat :: Parser Integer-    nat = liftM readUnsignedInteger digits+ident :: C e s m => m T.Text+ident = liftM fromString $ tok $ some $ noneOf [' ', '\t', '\n'] -    frac :: Parser Rational-    frac = do-      char '.'-      s <- digits-      return (readUnsignedInteger s % 10^(length s))+stringLn :: C e s m => String -> m ()+stringLn s = string (fromString s) >> newline' -    e :: Parser Integer-    e = do-      oneOf "eE"-      f <- msum [ char '+' >> return id-                , char '-' >> return negate-                , return id-                ]-      liftM f nat+number :: forall e s m. C e s m => m Scientific+#if MIN_VERSION_megaparsec(6,0,0)+number = tok $ Lexer.signed (return ()) Lexer.scientific+#elif MIN_VERSION_megaparsec(5,0,0)+number = tok $ Lexer.signed (return ()) Lexer.number+#else+number = tok $ liftM (either fromInteger fromFloatDigits) $ Lexer.signed (return ()) Lexer.number+#endif  -- ---------------------------------------------------------------------------  -- | MPS file parser-parser :: Parser MIP.Problem+#if MIN_VERSION_megaparsec(6,0,0)+parser :: (MonadParsec e s m, Token s ~ Char, IsString (Tokens s)) => m (MIP.Problem Scientific)+#elif MIN_VERSION_megaparsec(5,0,0)+parser :: (MonadParsec e s m, Token s ~ Char) => m (MIP.Problem Scientific)+#else+parser :: MonadParsec s m Char => m (MIP.Problem Scientific)+#endif parser = do   many commentline @@ -163,14 +198,14 @@    -- http://pic.dhe.ibm.com/infocenter/cosinfoc/v12r4/topic/ilog.odms.cplex.help/CPLEX/File_formats_reference/topics/MPS_ext_objsen.html   -- CPLEX extends the MPS standard by allowing two additional sections: OBJSEN and OBJNAME.-  -- If these options are used, they must appear in order and as the first and second sections after the NAME section. -  objsense <- optionMaybe $ objSenseSection-  objname  <- optionMaybe $ objNameSection+  -- If these options are used, they must appear in order and as the first and second sections after the NAME section.+  objsense <- optional $ objSenseSection+  objname  <- optional $ objNameSection    rows <- rowsSection    -- http://pic.dhe.ibm.com/infocenter/cosinfoc/v12r4/topic/ilog.odms.cplex.help/CPLEX/File_formats_reference/topics/MPS_ext_usercuts.html-  -- The order of sections must be ROWS USERCUTS.  +  -- The order of sections must be ROWS USERCUTS.   usercuts <- option [] userCutsSection    -- http://pic.dhe.ibm.com/infocenter/cosinfoc/v12r4/topic/ilog.odms.cplex.help/CPLEX/File_formats_reference/topics/MPS_ext_lazycons.html@@ -191,7 +226,7 @@   sos <- option [] sosSection    -- http://pic.dhe.ibm.com/infocenter/cosinfoc/v12r4/topic/ilog.odms.cplex.help/CPLEX/File_formats_reference/topics/MPS_ext_qcmatrix.html-  -- QCMATRIX sections appear after the optional SOS section. +  -- QCMATRIX sections appear after the optional SOS section.   qterms <- liftM Map.fromList $ many qcMatrixSection    -- http://pic.dhe.ibm.com/infocenter/cosinfoc/v12r4/topic/ilog.odms.cplex.help/CPLEX/File_formats_reference/topics/MPS_ext_indicators.html@@ -199,7 +234,7 @@   inds <- option Map.empty indicatorsSection    string "ENDATA"-  P.spaces+  P.space    let objrow =         case objname of@@ -277,17 +312,17 @@               (v, (fromMaybe (MIP.Finite 0) lb, fromMaybe MIP.PosInf ub))         | v <- Set.toList vs ] -  let rowCoeffs :: Map Row (Map Column Rational)-      rowCoeffs = Map.fromListWith Map.union [(row, Map.singleton col coeff) | (col,m) <- Map.toList cols, (row,coeff) <- Map.toList m]+  let rowCoeffs :: Map Row (Map Column Scientific)+      rowCoeffs = Map.fromListWith Map.union [(r, Map.singleton col coeff) | (col,m) <- Map.toList cols, (r,coeff) <- Map.toList m] -  let f :: Bool -> (Maybe MIP.RelOp, Row) -> [MIP.Constraint]+  let f :: Bool -> (Maybe MIP.RelOp, Row) -> [MIP.Constraint Scientific]       f _isLazy (Nothing, _row) = []-      f isLazy (Just op, row) = do-        let lhs = [MIP.Term c [col] | (col,c) <- Map.toList (Map.findWithDefault Map.empty row rowCoeffs)]-                  ++ Map.findWithDefault [] row qterms-        let rhs = Map.findWithDefault 0 row rhss+      f isLazy (Just op, r) = do+        let lhs = [MIP.Term c [col] | (col,c) <- Map.toList (Map.findWithDefault Map.empty r rowCoeffs)]+                  ++ Map.findWithDefault [] r qterms+        let rhs = Map.findWithDefault 0 r rhss             (lb,ub) =-              case Map.lookup row rngs of+              case Map.lookup r rngs of                 Nothing  ->                   case op of                     MIP.Ge  -> (MIP.Finite rhs, MIP.PosInf)@@ -303,8 +338,8 @@                       else (MIP.Finite rhs, MIP.Finite (rhs + rng))         return $           MIP.Constraint-          { MIP.constrLabel     = Just $ unintern row-          , MIP.constrIndicator = Map.lookup row inds+          { MIP.constrLabel     = Just $ unintern r+          , MIP.constrIndicator = Map.lookup r inds           , MIP.constrIsLazy    = isLazy           , MIP.constrExpr      = MIP.Expr lhs           , MIP.constrLB        = lb@@ -341,16 +376,16 @@    return mip -nameSection :: Parser (Maybe String)+nameSection :: C e s m => m (Maybe T.Text) nameSection = do   string "NAME"-  n <- optionMaybe $ try $ do+  n <- optional $ try $ do     spaces1'     ident   newline'   return n -objSenseSection :: Parser OptDir+objSenseSection :: C e s m => m OptDir objSenseSection = do   try $ stringLn "OBJSENSE"   spaces1'@@ -358,7 +393,7 @@     <|> (stringLn "MIN" >> return OptMin)   return d -objNameSection :: Parser String+objNameSection :: C e s m => m T.Text objNameSection = do   try $ stringLn "OBJNAME"   spaces1'@@ -366,22 +401,22 @@   newline'   return name -rowsSection :: Parser [(Maybe MIP.RelOp, Row)]+rowsSection :: C e s m => m [(Maybe MIP.RelOp, Row)] rowsSection = do   try $ stringLn "ROWS"   rowsBody -userCutsSection :: Parser [(Maybe MIP.RelOp, Row)]+userCutsSection :: C e s m => m [(Maybe MIP.RelOp, Row)] userCutsSection = do   try $ stringLn "USERCUTS"   rowsBody -lazyConsSection :: Parser [(Maybe MIP.RelOp, Row)]+lazyConsSection :: C e s m => m [(Maybe MIP.RelOp, Row)] lazyConsSection = do   try $ stringLn "LAZYCONS"   rowsBody -rowsBody :: Parser [(Maybe MIP.RelOp, Row)]+rowsBody :: C e s m => m [(Maybe MIP.RelOp, Row)] rowsBody = many $ do   spaces1'   op <- msum@@ -395,26 +430,28 @@   newline'   return (op, name) -colsSection :: Parser (Map Column (Map Row Rational), Set Column)+colsSection :: forall e s m. C e s m => m (Map Column (Map Row Scientific), Set Column) colsSection = do   try $ stringLn "COLUMNS"   body False Map.empty Set.empty   where-    body :: Bool -> Map Column (Map Row Rational) -> Set Column -> Parser (Map Column (Map Row Rational), Set Column)+    body :: Bool -> Map Column (Map Row Scientific) -> Set Column -> m (Map Column (Map Row Scientific), Set Column)     body isInt rs ivs = msum-      [ do isInt' <- try intMarker-           body isInt' rs ivs-      , do (k,v) <- entry-           let rs'  = Map.insertWith Map.union k v rs-               ivs' = if isInt then Set.insert k ivs else ivs-           seq rs' $ seq ivs' $ body isInt rs' ivs'+      [ do _ <- spaces1'+           x <- ident+           msum+             [ do isInt' <- try intMarker+                  body isInt' rs ivs+             , do (k,v) <- entry x+                  let rs'  = Map.insertWith Map.union k v rs+                      ivs' = if isInt then Set.insert k ivs else ivs+                  seq rs' $ seq ivs' $ body isInt rs' ivs'+             ]       , return (rs, ivs)       ] -    intMarker :: Parser Bool+    intMarker :: m Bool     intMarker = do-      spaces1'-      _marker <- ident        string "'MARKER'"       spaces1'       b <-  (try (string "'INTORG'") >> return True)@@ -422,24 +459,23 @@       newline'       return b -    entry :: Parser (Column, Map Row Rational)-    entry = do-      spaces1'-      col <- column+    entry :: T.Text -> m (Column, Map Row Scientific)+    entry x = do+      let col = intern x       rv1 <- rowAndVal-      opt <- optionMaybe rowAndVal+      opt <- optional rowAndVal       newline'       case opt of         Nothing -> return (col, rv1)         Just rv2 ->  return (col, Map.union rv1 rv2) -rowAndVal :: Parser (Map Row Rational)+rowAndVal :: C e s m => m (Map Row Scientific) rowAndVal = do   r <- row   val <- number   return $ Map.singleton r val -rhsSection :: Parser (Map Row Rational)+rhsSection :: C e s m => m (Map Row Scientific) rhsSection = do   try $ stringLn "RHS"   liftM Map.unions $ many entry@@ -448,13 +484,13 @@       spaces1'       _name <- ident       rv1 <- rowAndVal-      opt <- optionMaybe rowAndVal+      opt <- optional rowAndVal       newline'       case opt of         Nothing  -> return rv1         Just rv2 -> return $ Map.union rv1 rv2 -rangesSection :: Parser (Map Row Rational)+rangesSection :: C e s m => m (Map Row Scientific) rangesSection = do   try $ stringLn "RANGES"   liftM Map.unions $ many entry@@ -463,13 +499,13 @@       spaces1'       _name <- ident       rv1 <- rowAndVal-      opt <- optionMaybe rowAndVal+      opt <- optional rowAndVal       newline'       case opt of         Nothing  -> return rv1         Just rv2 -> return $ Map.union rv1 rv2 -boundsSection :: Parser [(BoundType, Column, Rational)]+boundsSection :: C e s m => m [(BoundType, Column, Scientific)] boundsSection = do   try $ stringLn "BOUNDS"   many entry@@ -485,11 +521,11 @@       newline'       return (typ, col, val) -boundType :: Parser BoundType+boundType :: C e s m => m BoundType boundType = tok $ do-  msum [try (string (show k)) >> return k | k <- [minBound..maxBound]]+  msum [try (string (fromString (show k))) >> return k | k <- [minBound..maxBound]] -sosSection :: Parser [MIP.SOSConstraint]+sosSection :: forall e s m. C e s m => m [MIP.SOSConstraint Scientific] sosSection = do   try $ stringLn "SOS"   many entry@@ -504,7 +540,7 @@       xs <- many (try identAndVal)       return $ MIP.SOSConstraint{ MIP.sosLabel = Just name, MIP.sosType = typ, MIP.sosBody = xs } -    identAndVal :: Parser (Column, Rational)+    identAndVal :: m (Column, Scientific)     identAndVal = do       spaces1'       col <- column@@ -512,7 +548,7 @@       newline'       return (col, val) -quadObjSection :: Parser [MIP.Term]+quadObjSection :: C e s m => m [MIP.Term Scientific] quadObjSection = do   try $ stringLn "QUADOBJ"   many entry@@ -525,7 +561,7 @@       newline'       return $ MIP.Term (if col1 /= col2 then val else val / 2) [col1, col2] -qMatrixSection :: Parser [MIP.Term]+qMatrixSection :: C e s m => m [MIP.Term Scientific] qMatrixSection = do   try $ stringLn "QMATRIX"   many entry@@ -538,7 +574,7 @@       newline'       return $ MIP.Term (val / 2) [col1, col2] -qcMatrixSection :: Parser (Row, [MIP.Term])+qcMatrixSection :: C e s m => m (Row, [MIP.Term Scientific]) qcMatrixSection = do   try $ string "QCMATRIX"   spaces1'@@ -555,7 +591,7 @@       newline'       return $ MIP.Term val [col1, col2] -indicatorsSection :: Parser (Map Row (Column, Rational))+indicatorsSection :: C e s m => m (Map Row (Column, Scientific)) indicatorsSection = do   try $ stringLn "INDICATORS"   liftM Map.fromList $ many entry@@ -572,31 +608,31 @@  -- --------------------------------------------------------------------------- -type M a = Writer ShowS a+type M a = Writer Builder a -execM :: M a -> String-execM m = execWriter m ""+execM :: M a -> TL.Text+execM m = B.toLazyText $ execWriter m -writeString :: String -> M ()-writeString s = tell $ showString s+writeText :: T.Text -> M ()+writeText s = tell $ B.fromText s  writeChar :: Char -> M ()-writeChar c = tell $ showChar c+writeChar c = tell $ B.singleton c  -- --------------------------------------------------------------------------- -render :: MIP.Problem -> Either String String-render mip | not (checkAtMostQuadratic mip) = Left "Expression must be atmost quadratic"-render mip = Right $ execM $ render' $ nameRows mip+render :: MIP.FileOptions -> MIP.Problem Scientific -> Either String TL.Text+render _ mip | not (checkAtMostQuadratic mip) = Left "Expression must be atmost quadratic"+render _ mip = Right $ execM $ render' $ nameRows mip -render' :: MIP.Problem -> M ()+render' :: MIP.Problem Scientific -> M () render' mip = do   let probName = fromMaybe "" (MIP.name mip)    -- NAME section   -- The name starts in column 15 in fixed formats.-  writeSectionHeader $ "NAME" ++ replicate 10 ' ' ++ probName-  +  writeSectionHeader $ "NAME" <> T.replicate 10 " " <> probName+   let MIP.ObjectiveFunction        { MIP.objLabel = Just objName        , MIP.objDir = dir@@ -653,7 +689,7 @@    -- COLUMNS section   writeSectionHeader "COLUMNS"-  let cols :: Map Column (Map String Rational)+  let cols :: Map Column (Map T.Text Scientific)       cols = Map.fromListWith Map.union              [ (v, Map.singleton l d)              | (Just l, xs) <-@@ -662,8 +698,8 @@              , MIP.Term d [v] <- MIP.terms xs              ]       f col xs =-        forM_ (Map.toList xs) $ \(row, d) -> do-          writeFields ["", unintern col, row, showValue d]+        forM_ (Map.toList xs) $ \(r, d) -> do+          writeFields ["", unintern col, r, showValue d]       ivs = MIP.integerVariables mip `Set.union` MIP.semiIntegerVariables mip   forM_ (Map.toList (Map.filterWithKey (\col _ -> col `Set.notMember` ivs) cols)) $ \(col, xs) -> f col xs   unless (Set.null ivs) $ do@@ -692,10 +728,10 @@       (MIP.NegInf, MIP.PosInf) -> do         -- free variable (no lower or upper bound)         writeFields ["FR", "bound", unintern col]-                  +       (MIP.Finite 0, MIP.Finite 1) | vt == MIP.IntegerVariable -> do         -- variable is binary (equal 0 or 1)-        writeFields ["BV", "bound", unintern col] +        writeFields ["BV", "bound", unintern col]        (MIP.Finite a, MIP.Finite b) | a == b -> do         -- variable is fixed at the specified value@@ -733,11 +769,11 @@    -- QMATRIX section   -- Gurobiは対称行列になっていないと "qmatrix isn't symmetric" というエラーを発生させる-  let qm = Map.map (2*) $ quadMatrix obj-  unless (Map.null qm) $ do-    writeSectionHeader "QMATRIX"-    forM_ (Map.toList qm) $ \(((v1,v2), val)) -> do-      writeFields ["", unintern v1, unintern v2, showValue val]+  do let qm = Map.map (2*) $ quadMatrix obj+     unless (Map.null qm) $ do+       writeSectionHeader "QMATRIX"+       forM_ (Map.toList qm) $ \(((v1,v2), val)) -> do+         writeFields ["", unintern v1, unintern v2, showValue val]    -- SOS section   unless (null (MIP.sosConstraints mip)) $ do@@ -757,9 +793,9 @@            , let qm = quadMatrix lhs            , not (Map.null qm) ]   unless (null xs) $ do-    forM_ xs $ \(row, qm) -> do+    forM_ xs $ \(r, qm) -> do       -- The name starts in column 12 in fixed formats.-      writeSectionHeader $ "QCMATRIX" ++ replicate 3 ' ' ++ row+      writeSectionHeader $ "QCMATRIX" <> T.replicate 3 " " <> r       forM_ (Map.toList qm) $ \((v1,v2), val) -> do         writeFields ["", unintern v1, unintern v2, showValue val] @@ -775,85 +811,100 @@   -- ENDATA section   writeSectionHeader "ENDATA" -writeSectionHeader :: String -> M ()-writeSectionHeader s = writeString s >> writeChar '\n'+writeSectionHeader :: T.Text -> M ()+writeSectionHeader s = writeText s >> writeChar '\n'  -- Fields start in column 2, 5, 15, 25, 40 and 50-writeFields :: [String] -> M ()-writeFields xs = f1 xs >> writeChar '\n'+writeFields :: [T.Text] -> M ()+writeFields xs0 = f1 xs0 >> writeChar '\n'   where     -- columns 1-4     f1 [] = return ()-    f1 [x] = writeString (' ' : x)+    f1 [x] = writeChar ' ' >> writeText x     f1 (x:xs) = do-      writeString $ printf " %-2s " x+      writeChar ' '+      writeText x+      let len = T.length x+      when (len < 2) $ writeText $ T.replicate (2 - len) " "+      writeChar ' '       f2 xs      -- columns 5-14     f2 [] = return ()-    f2 [x] = writeString x+    f2 [x] = writeText x     f2 (x:xs) = do-      writeString $ printf "%-9s " x+      writeText x+      let len = T.length x+      when (len < 9) $ writeText $ T.replicate (9 - len) " "+      writeChar ' '       f3 xs      -- columns 15-24     f3 [] = return ()-    f3 [x] = writeString x+    f3 [x] = writeText x     f3 (x:xs) = do-      writeString $ printf "%-9s " x+      writeText x+      let len = T.length x+      when (len < 9) $ writeText $ T.replicate (9 - len) " "+      writeChar ' '       f4 xs      -- columns 25-39     f4 [] = return ()-    f4 [x] = writeString x+    f4 [x] = writeText x     f4 (x:xs) = do-      writeString $ printf "%-14s " x+      writeText x+      let len = T.length x+      when (len < 14) $ writeText $ T.replicate (14 - len) " "+      writeChar ' '       f5 xs      -- columns 40-49     f5 [] = return ()-    f5 [x] = writeString x+    f5 [x] = writeText x     f5 (x:xs) = do-      writeString $ printf "%-19s " x+      writeText x+      let len = T.length x+      when (len < 19) $ writeText $ T.replicate (19 - len) " "+      writeChar ' '       f6 xs      -- columns 50-     f6 [] = return ()-    f6 [x] = writeString x+    f6 [x] = writeText x     f6 _ = error "MPSFile: >6 fields (this should not happen)" -showValue :: Rational -> String-showValue c =-  if denominator c == 1-    then show (numerator c)-    else show (fromRational c :: Double)- -nameRows :: MIP.Problem -> MIP.Problem+showValue :: Scientific -> T.Text+showValue = fromString . show++nameRows :: MIP.Problem r -> MIP.Problem r nameRows mip   = mip   { MIP.objectiveFunction = (MIP.objectiveFunction mip){ MIP.objLabel = Just objName' }-  , MIP.constraints = f (MIP.constraints mip) ["row" ++ show n | n <- [(1::Int)..]]-  , MIP.userCuts = f (MIP.userCuts mip) ["usercut" ++ show n | n <- [(1::Int)..]]-  , MIP.sosConstraints = g (MIP.sosConstraints mip) ["sos" ++ show n | n <- [(1::Int)..]]+  , MIP.constraints = f (MIP.constraints mip) [T.pack $ "row" ++ show n | n <- [(1::Int)..]]+  , MIP.userCuts = f (MIP.userCuts mip) [T.pack $ "usercut" ++ show n | n <- [(1::Int)..]]+  , MIP.sosConstraints = g (MIP.sosConstraints mip) [T.pack $ "sos" ++ show n | n <- [(1::Int)..]]   }   where     objName = MIP.objLabel $ MIP.objectiveFunction mip     used = Set.fromList $ catMaybes $ objName : [MIP.constrLabel c | c <- MIP.constraints mip ++ MIP.userCuts mip] ++ [MIP.sosLabel c | c <- MIP.sosConstraints mip]-    objName' = fromMaybe (head [name | n <- [(1::Int)..], let name = "obj" ++ show n, name `Set.notMember` used]) objName+    objName' = fromMaybe (head [name | n <- [(1::Int)..], let name = T.pack ("obj" ++ show n), name `Set.notMember` used]) objName      f [] _ = []     f (c:cs) (name:names)       | isJust (MIP.constrLabel c) = c : f cs (name:names)       | name `Set.notMember` used = c{ MIP.constrLabel = Just name } : f cs names       | otherwise = f (c:cs) names+    f _ [] = error "should not happen"      g [] _ = []     g (c:cs) (name:names)       | isJust (MIP.sosLabel c) = c : g cs (name:names)       | name `Set.notMember` used = c{ MIP.sosLabel = Just name } : g cs names       | otherwise = g (c:cs) names+    g _ [] = error "should not happen" -quadMatrix :: MIP.Expr -> Map (MIP.Var, MIP.Var) Rational+quadMatrix :: Fractional r => MIP.Expr r -> Map (MIP.Var, MIP.Var) r quadMatrix e = Map.fromList $ do   let m = Map.fromListWith (+) [(if v1<=v2 then (v1,v2) else (v2,v1), c) | MIP.Term c [v1,v2] <- MIP.terms e]   ((v1,v2),c) <- Map.toList m@@ -862,12 +913,12 @@   else     [((v1,v2), c/2), ((v2,v1), c/2)] -checkAtMostQuadratic :: MIP.Problem -> Bool+checkAtMostQuadratic :: forall r. MIP.Problem r -> Bool checkAtMostQuadratic mip =  all (all f . MIP.terms) es   where     es = MIP.objExpr (MIP.objectiveFunction mip) :          [lhs | c <- MIP.constraints mip ++ MIP.userCuts mip, let lhs = MIP.constrExpr c]-    f :: MIP.Term -> Bool+    f :: MIP.Term r -> Bool     f (MIP.Term _ [_]) = True     f (MIP.Term _ [_,_]) = True     f _ = False
+ src/ToySolver/Data/MIP/Solution/CBC.hs view
@@ -0,0 +1,71 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE OverloadedStrings #-}+module ToySolver.Data.MIP.Solution.CBC+  ( Solution (..)+  , parse+  , readFile+  ) where++import Prelude hiding (readFile, writeFile)+import Control.Applicative+import Control.Monad.Except+import Data.Interned (intern)+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Scientific (Scientific)+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.IO as TLIO+import ToySolver.Data.MIP (Solution)+import qualified ToySolver.Data.MIP as MIP++parse :: TL.Text -> MIP.Solution Scientific+parse t =+  case parse' $ TL.lines t of+    Left e -> error e+    Right x -> x++parse' :: [TL.Text] -> Either String (MIP.Solution Scientific)+parse' (l1:ls) = do+  (status, obj) <-+    case TL.break ('-'==) l1 of+      (s1,s2) -> +        case TL.stripPrefix "- objective value " s2 of+          Nothing -> throwError "fail to parse header"+          Just s3 -> do+            let s1' = TL.toStrict (TL.strip s1)+            return+              ( case Map.lookup s1' statusTable of+                  Just st -> st+                  Nothing ->+                    if T.isPrefixOf "Stopped on " s1'+                    then MIP.StatusUnknown+                    else MIP.StatusUnknown+              , read (TL.unpack s3)+              )+  let f :: [(MIP.Var, Scientific)] -> TL.Text -> Either String [(MIP.Var, Scientific)]+      f vs t =+        case TL.words t of+          ("**":_no:var:val:_) -> return $ (intern (TL.toStrict var), read (TL.unpack val)) : vs+          (_no:var:val:_) -> return $ (intern (TL.toStrict var), read (TL.unpack val)) : vs+          [] -> return $ vs+          _ -> throwError ("ToySolver.Data.MIP.Solution.CBC: invalid line " ++ show t)+  vs <- foldM f [] ls+  return $+    MIP.Solution+    { MIP.solStatus = status+    , MIP.solObjectiveValue = Just obj+    , MIP.solVariables = Map.fromList vs+    }+parse' _ = throwError "must have >=1 lines"++statusTable :: Map T.Text MIP.Status+statusTable = Map.fromList+  [ ("Optimal", MIP.StatusOptimal)+  , ("Unbounded", MIP.StatusInfeasibleOrUnbounded)+  , ("Integer infeasible", MIP.StatusInfeasible)+  , ("Infeasible", MIP.StatusInfeasible)+  ]++readFile :: FilePath -> IO (MIP.Solution Scientific)+readFile fname = parse <$> TLIO.readFile fname
+ src/ToySolver/Data/MIP/Solution/CPLEX.hs view
@@ -0,0 +1,148 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+module ToySolver.Data.MIP.Solution.CPLEX+  ( Solution (..)+  , parse+  , readFile+  ) where++import Prelude hiding (readFile)+import Control.Applicative+import Data.Default.Class+import Data.Interned+import Data.IntMap (IntMap)+import qualified Data.IntMap as IntMap+import qualified Data.Map as Map+import Data.Maybe+import Data.Scientific (Scientific)+import Data.String+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import qualified Text.XML as XML+import Text.XML.Cursor+import ToySolver.Data.MIP (Solution)+import qualified ToySolver.Data.MIP.Base as MIP++parseDoc :: XML.Document -> MIP.Solution Scientific+parseDoc doc = +  MIP.Solution+  { MIP.solStatus = status+  , MIP.solObjectiveValue = obj+  , MIP.solVariables = Map.fromList vs+  }+  where+    obj :: Maybe Scientific+    obj = listToMaybe+      $  fromDocument doc+      $| element "CPLEXSolution"+      &/ element "header"+      >=> attribute "objectiveValue"+      &| (read . T.unpack)++    status :: MIP.Status+    status = head+      $  fromDocument doc+      $| element "CPLEXSolution"+      &/ element "header"+      >=> attribute "solutionStatusValue"+      &| (flip (IntMap.findWithDefault MIP.StatusUnknown) table . read . T.unpack)++    f :: Cursor -> [(MIP.Var, Scientific)]+    f x+      | XML.NodeElement e <- node x = maybeToList $ do+          let m = XML.elementAttributes e+          name <- Map.lookup "name" m+          value <- read . T.unpack <$> Map.lookup "value" m+          return (intern name, value)+      | otherwise = []+    vs = fromDocument doc+      $| element "CPLEXSolution"+      &/ element "variables"+      &/ element "variable"+      >=> f++-- https://www.ibm.com/support/knowledgecenter/en/SSSA5P_12.7.0/ilog.odms.cplex.help/refcallablelibrary/macros/Solution_status_codes.html+table :: IntMap MIP.Status+table = IntMap.fromList+  [ (1,   MIP.StatusOptimal)               -- CPX_STAT_OPTIMAL+  , (2,   MIP.StatusUnbounded)             -- CPX_STAT_UNBOUNDED+  , (3,   MIP.StatusInfeasible)            -- CPX_STAT_INFEASIBLE+  , (4,   MIP.StatusInfeasibleOrUnbounded) -- CPX_STAT_INForUNBD+  , (5,   MIP.StatusOptimal)               -- CPX_STAT_OPTIMAL_INFEAS+{-+  , (6,   ) -- CPX_STAT_NUM_BEST+  , (10,  ) -- CPX_STAT_ABORT_IT_LIM+  , (11,  ) -- CPX_STAT_ABORT_TIME_LIM+  , (12,  ) -- CPX_STAT_ABORT_OBJ_LIM+  , (13,  ) -- CPX_STAT_ABORT_USER+  , (14,  ) -- CPX_STAT_FEASIBLE_RELAXED_SUM+  , (15,  ) -- CPX_STAT_OPTIMAL_RELAXED_SUM+  , (16,  ) -- CPX_STAT_FEASIBLE_RELAXED_INF+  , (17,  ) -- CPX_STAT_OPTIMAL_RELAXED_INF+  , (18,  ) -- CPX_STAT_FEASIBLE_RELAXED_QUAD+  , (19,  ) -- CPX_STAT_OPTIMAL_RELAXED_QUAD+  , (20,  ) -- CPX_STAT_OPTIMAL_FACE_UNBOUNDED+  , (21,  ) -- CPX_STAT_ABORT_PRIM_OBJ_LIM+  , (22,  ) -- CPX_STAT_ABORT_DUAL_OBJ_LIM+  , (23,  ) -- CPX_STAT_FEASIBLE+-}+  , (24,  MIP.StatusFeasible) -- CPX_STAT_FIRSTORDER+{-+  , (25,  ) -- CPX_STAT_ABORT_DETTIME_LIM+  , (30,  ) -- CPX_STAT_CONFLICT_FEASIBLE+  , (31,  ) -- CPX_STAT_CONFLICT_MINIMAL+  , (32,  ) -- CPX_STAT_CONFLICT_ABORT_CONTRADICTION+  , (33,  ) -- CPX_STAT_CONFLICT_ABORT_TIME_LIM+  , (34,  ) -- CPX_STAT_CONFLICT_ABORT_IT_LIM+  , (35,  ) -- CPX_STAT_CONFLICT_ABORT_NODE_LIM+  , (36,  ) -- CPX_STAT_CONFLICT_ABORT_OBJ_LIM+  , (37,  ) -- CPX_STAT_CONFLICT_ABORT_MEM_LIM+  , (38,  ) -- CPX_STAT_CONFLICT_ABORT_USER+  , (39,  ) -- CPX_STAT_CONFLICT_ABORT_DETTIME_LIM+-}+  , (40,  MIP.StatusInfeasibleOrUnbounded) -- CPX_STAT_BENDERS_MASTER_UNBOUNDED+--  , (41,  ) -- CPX_STAT_BENDERS_NUM_BEST+  , (101, MIP.StatusOptimal)               -- CPXMIP_OPTIMAL+  , (102, MIP.StatusOptimal)               -- CPXMIP_OPTIMAL_TOL+  , (103, MIP.StatusInfeasible)            -- CPXMIP_INFEASIBLE+--  , (104, ) -- CPXMIP_SOL_LIM+  , (105, MIP.StatusFeasible)              -- CPXMIP_NODE_LIM_FEAS+--  , (106, ) -- CPXMIP_NODE_LIM_INFEAS+  , (107, MIP.StatusFeasible)              -- CPXMIP_TIME_LIM_FEAS+--  , (108, ) -- CPXMIP_TIME_LIM_INFEAS+  , (109, MIP.StatusFeasible)              -- CPXMIP_FAIL_FEAS+--  , (110, ) -- CPXMIP_FAIL_INFEAS+  , (111, MIP.StatusFeasible)              -- CPXMIP_MEM_LIM_FEAS+--  , (112, ) -- CPXMIP_MEM_LIM_INFEAS+  , (113, MIP.StatusFeasible)              -- CPXMIP_ABORT_FEAS+--  , (114, ) -- CPXMIP_ABORT_INFEAS+  , (115, MIP.StatusOptimal)               -- CPXMIP_OPTIMAL_INFEAS+  , (116, MIP.StatusFeasible)              -- CPXMIP_FAIL_FEAS_NO_TREE+--  , (117, ) -- CPXMIP_FAIL_INFEAS_NO_TREE+  , (118, MIP.StatusUnbounded)             -- CPXMIP_UNBOUNDED+  , (119, MIP.StatusInfeasibleOrUnbounded) -- CPXMIP_INForUNBD+{-+  , (120, ) -- CPXMIP_FEASIBLE_RELAXED_SUM+  , (121, ) -- CPXMIP_OPTIMAL_RELAXED_SUM+  , (122, ) -- CPXMIP_FEASIBLE_RELAXED_INF+  , (123, ) -- CPXMIP_OPTIMAL_RELAXED_INF+  , (124, ) -- CPXMIP_FEASIBLE_RELAXED_QUAD+  , (125, ) -- CPXMIP_OPTIMAL_RELAXED_QUAD+  , (126, ) -- CPXMIP_ABORT_RELAXED+-}+  , (127, MIP.StatusFeasible)              -- CPXMIP_FEASIBLE+--  , (128, ) -- CPXMIP_POPULATESOL_LIM+  , (129, MIP.StatusOptimal)               -- CPXMIP_OPTIMAL_POPULATED+  , (130, MIP.StatusOptimal)               -- CPXMIP_OPTIMAL_POPULATED_TOL+  , (131, MIP.StatusFeasible)              -- CPXMIP_DETTIME_LIM_FEAS+--  , (132, ) -- CPXMIP_DETTIME_LIM_INFEAS+  , (133, MIP.StatusInfeasibleOrUnbounded) -- CPXMIP_ABORT_RELAXATION_UNBOUNDED+  ]++parse :: TL.Text -> MIP.Solution Scientific+parse t = parseDoc $ XML.parseText_ def t++readFile :: FilePath -> IO (MIP.Solution Scientific)+readFile fname = parseDoc <$> XML.readFile def (fromString fname)+
+ src/ToySolver/Data/MIP/Solution/GLPK.hs view
@@ -0,0 +1,90 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE OverloadedStrings #-}+module ToySolver.Data.MIP.Solution.GLPK+  ( Solution (..)+  , parse+  , readFile+  ) where++import Prelude hiding (readFile, writeFile)+import Control.Applicative+import Data.Interned (intern)+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Scientific (Scientific)+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.IO as TLIO+import ToySolver.Data.MIP (Solution)+import qualified ToySolver.Data.MIP as MIP++parse :: TL.Text -> MIP.Solution Scientific+parse t = parse' $ TL.lines t++parse' :: [TL.Text] -> MIP.Solution Scientific+parse' ls =+  case parseHeaders ls of+    (headers, ls2) ->+      case parseColumns (skipRows ls2) of+        (vs, _) ->+          let status = Map.findWithDefault MIP.StatusUnknown (headers Map.! "Status") statusTable+              objstr = headers Map.! "Objective"+              objstr2 = +                case T.findIndex ('='==) objstr of+                  Nothing -> objstr+                  Just idx -> T.drop (idx+1) objstr+              obj = case reads (T.unpack objstr2) of+                      [] -> error "parse error"+                      (r,_):_ -> r+          in MIP.Solution+             { MIP.solStatus = status+             , MIP.solObjectiveValue = Just obj+             , MIP.solVariables = vs+             }++parseHeaders :: [TL.Text] -> (Map T.Text T.Text, [TL.Text])+parseHeaders = f Map.empty+  where+    f _ [] = error "parse error"+    f ret ("":ls) = (ret, ls)+    f ret (l:ls) =+      case TL.break (':'==) l of+        (_, "") -> error "parse error"+        (name, val) -> f (Map.insert (TL.toStrict name) (TL.toStrict (TL.strip (TL.tail val))) ret) ls++skipRows :: [TL.Text] -> [TL.Text]+skipRows [] = error "parse error"+skipRows ("":ls) = ls+skipRows (_:ls) = skipRows ls++parseColumns :: [TL.Text] -> (Map MIP.Var Scientific, [TL.Text])+parseColumns (l1:l2:ls)+  | l1 == "   No. Column name       Activity     Lower bound   Upper bound"+  , l2 == "------ ------------    ------------- ------------- -------------"+    = f [] ls+  where+    f :: [(MIP.Var, Scientific)] -> [TL.Text] -> (Map MIP.Var Scientific, [TL.Text])+    f _ [] = error "parse error"+    f ret ("":ls2) = (Map.fromList ret, ls2)+    f ret (l:ls2) =+      case ws of+        (_no : col : "*" : activity : _) -> f ((intern (TL.toStrict col), read (TL.unpack activity)) : ret) ls3+        (_no : col : activity : _) -> f ((intern (TL.toStrict col), read (TL.unpack activity)) : ret) ls3+        _ -> error "parse error"+      where+        (ws,ls3) =+          case TL.words l of+            ws1@(_:_:_:_) -> (ws1, ls2)+            ws1@[_,_] -> (ws1 ++ TL.words (head ls2), tail ls2)+            _ -> error "parse error"+parseColumns _ = error "parse error"++statusTable :: Map T.Text MIP.Status+statusTable = Map.fromList+  [ ("INTEGER OPTIMAL", MIP.StatusOptimal)+  , ("INTEGER NON-OPTIMAL", MIP.StatusUnknown)+  , ("INTEGER EMPTY", MIP.StatusInfeasible)+  ]++readFile :: FilePath -> IO (MIP.Solution Scientific)+readFile fname = parse <$> TLIO.readFile fname
+ src/ToySolver/Data/MIP/Solution/Gurobi.hs view
@@ -0,0 +1,62 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE OverloadedStrings #-}+module ToySolver.Data.MIP.Solution.Gurobi+  ( Solution (..)+  , render+  , writeFile+  , parse+  , readFile+  ) where++import Prelude hiding (readFile, writeFile)+import Control.Applicative+import Data.Default.Class+import Data.Interned (intern, unintern)+import Data.List (foldl')+import qualified Data.Map as Map+import Data.Monoid+import Data.Scientific (Scientific)+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.Builder as B+import qualified Data.Text.Lazy.Builder.Scientific as B+import qualified Data.Text.Lazy.IO as TLIO+import ToySolver.Data.MIP (Solution)+import qualified ToySolver.Data.MIP as MIP++render :: MIP.Solution Scientific -> TL.Text+render sol = B.toLazyText $ ls1 <> mconcat ls2+  where+    ls1 = case MIP.solObjectiveValue sol of+            Nothing  -> mempty+            Just val -> "# Objective value = " <> B.scientificBuilder val <> B.singleton '\n'+    ls2 = [ B.fromText (unintern name) <> B.singleton ' ' <> B.scientificBuilder val <> B.singleton '\n'+          | (name,val) <- Map.toList (MIP.solVariables sol)+          ]++writeFile :: FilePath -> MIP.Solution Scientific -> IO ()+writeFile fname sol = do+  TLIO.writeFile fname (render sol)++parse :: TL.Text -> MIP.Solution Scientific+parse t = +  case foldl' f (Nothing,[]) $ TL.lines t of+    (obj, vs) ->+      def{ MIP.solStatus = MIP.StatusFeasible+         , MIP.solObjectiveValue = obj+         , MIP.solVariables = Map.fromList vs+         }+  where+    f :: (Maybe Scientific, [(MIP.Var, Scientific)]) -> TL.Text -> (Maybe Scientific, [(MIP.Var, Scientific)])+    f (obj,vs) l+      | Just l2 <- TL.stripPrefix "# " l+      , Just l3 <- TL.stripPrefix "objective value = " (TL.toLower l2)+      , (r:_) <- [r | (r,[]) <- reads (TL.unpack l3)] =+          (Just r, vs)+      | otherwise =+          case TL.words (TL.takeWhile (/= '#') l) of+            [w1, w2] -> (obj, (intern (TL.toStrict w1), read (TL.unpack w2)) : vs)+            [] -> (obj, vs)+            _ -> error ("ToySolver.Data.MIP.Solution.Gurobi: invalid line " ++ show l)++readFile :: FilePath -> IO (MIP.Solution Scientific)+readFile fname = parse <$> TLIO.readFile fname
+ src/ToySolver/Data/MIP/Solution/SCIP.hs view
@@ -0,0 +1,80 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE OverloadedStrings #-}+module ToySolver.Data.MIP.Solution.SCIP+  ( Solution (..)+  , parse+  , readFile+  ) where++import Prelude hiding (readFile, writeFile)+import Control.Applicative+import Control.Monad.Except+import Data.Interned (intern)+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Scientific (Scientific)+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import qualified Data.Text.Lazy.IO as TLIO+import ToySolver.Data.MIP (Solution)+import qualified ToySolver.Data.MIP as MIP++parse :: TL.Text -> MIP.Solution Scientific+parse t =+  case parse' $ TL.lines t of+    Left e -> error e+    Right x -> x++parse' :: [TL.Text] -> Either String (MIP.Solution Scientific)+parse' (t1:t2:ts) = do+  status <-+    case TL.stripPrefix "solution status:" t1 of+      Nothing -> throwError "first line must start with \"solution status:\""+      Just s -> return $ Map.findWithDefault MIP.StatusUnknown (TL.toStrict $ TL.strip s) statusTable+  if t2 == "no solution available" then do+    return $ +      MIP.Solution+      { MIP.solStatus = status+      , MIP.solObjectiveValue = Nothing+      , MIP.solVariables = Map.empty+      }+  else do+    obj <-+      case TL.stripPrefix "objective value:" t2 of+        Nothing -> throwError "second line must start with \"objective value:\""+        Just s -> return $ read $ TL.unpack $ TL.strip s+    let f :: [(MIP.Var, Scientific)] -> TL.Text -> Either String [(MIP.Var, Scientific)]+        f vs t =+          case TL.words t of+            (w1:w2:_) -> return $ (intern (TL.toStrict w1), read (TL.unpack w2)) : vs+            [] -> return $ vs+            _ -> throwError ("ToySolver.Data.MIP.Solution.SCIP: invalid line " ++ show t)+    vs <- foldM f [] ts+    return $+      MIP.Solution+      { MIP.solStatus = status+      , MIP.solObjectiveValue = Just obj+      , MIP.solVariables = Map.fromList vs+      }+parse' _ = throwError "must have >=2 lines"++statusTable :: Map T.Text MIP.Status+statusTable = Map.fromList+  [ ("user interrupt", MIP.StatusUnknown)+  , ("node limit reached", MIP.StatusUnknown)+  , ("total node limit reached", MIP.StatusUnknown)+  , ("stall node limit reached", MIP.StatusUnknown)+  , ("time limit reached", MIP.StatusUnknown)+  , ("memory limit reached", MIP.StatusUnknown)+  , ("gap limit reached", MIP.StatusUnknown)+  , ("solution limit reached", MIP.StatusUnknown)+  , ("solution improvement limit reached", MIP.StatusUnknown)+  , ("optimal solution found", MIP.StatusOptimal)+  , ("infeasible", MIP.StatusInfeasible)+  , ("unbounded", MIP.StatusUnbounded)+  , ("infeasible or unbounded", MIP.StatusInfeasibleOrUnbounded)+  -- , ("unknown", )+  ]++readFile :: FilePath -> IO (MIP.Solution Scientific)+readFile fname = parse <$> TLIO.readFile fname
+ src/ToySolver/Data/MIP/Solver.hs view
@@ -0,0 +1,18 @@+{-# OPTIONS_GHC -Wall #-}+module ToySolver.Data.MIP.Solver+  ( module ToySolver.Data.MIP.Solver.Base+  , module ToySolver.Data.MIP.Solver.CBC+  , module ToySolver.Data.MIP.Solver.CPLEX+  , module ToySolver.Data.MIP.Solver.Glpsol+  , module ToySolver.Data.MIP.Solver.GurobiCl+  , module ToySolver.Data.MIP.Solver.LPSolve+  , module ToySolver.Data.MIP.Solver.SCIP+  ) where++import ToySolver.Data.MIP.Solver.Base+import ToySolver.Data.MIP.Solver.CBC+import ToySolver.Data.MIP.Solver.CPLEX+import ToySolver.Data.MIP.Solver.Glpsol+import ToySolver.Data.MIP.Solver.GurobiCl+import ToySolver.Data.MIP.Solver.LPSolve+import ToySolver.Data.MIP.Solver.SCIP
+ src/ToySolver/Data/MIP/Solver/Base.hs view
@@ -0,0 +1,32 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE FunctionalDependencies #-}+module ToySolver.Data.MIP.Solver.Base+  ( SolveOptions (..)+  , Default (..)+  , IsSolver (..)+  ) where++import Data.Default.Class+import Data.Scientific (Scientific)+import ToySolver.Data.MIP.Base as MIP++data SolveOptions+  = SolveOptions+  { solveTimeLimit :: Maybe Double+    -- ^ time limit in seconds+  , solveLogger :: String -> IO ()+    -- ^ invoked when a solver output a line+  , solveErrorLogger :: String -> IO ()+    -- ^ invoked when a solver output a line to stderr+  }++instance Default SolveOptions where+  def =+    SolveOptions+    { solveTimeLimit = Nothing+    , solveLogger = const $ return ()+    , solveErrorLogger = const $ return ()+    }++class Monad m => IsSolver s m | s -> m where+  solve :: s -> SolveOptions -> MIP.Problem Scientific -> m (MIP.Solution Scientific)
+ src/ToySolver/Data/MIP/Solver/CBC.hs view
@@ -0,0 +1,55 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE MultiParamTypeClasses #-}+module ToySolver.Data.MIP.Solver.CBC+  ( CBC (..)+  , cbc+  ) where++import Data.Default.Class+import qualified Data.Text.Lazy.IO as TLIO+import System.Exit+import System.IO+import System.IO.Temp+import qualified ToySolver.Data.MIP.Base as MIP+import qualified ToySolver.Data.MIP.LPFile as LPFile+import ToySolver.Data.MIP.Solver.Base+import qualified ToySolver.Data.MIP.Solution.CBC as CBCSol+import ToySolver.Internal.ProcessUtil (runProcessWithOutputCallback)++data CBC+  = CBC+  { cbcPath :: String+  }++instance Default CBC where+  def = cbc++cbc :: CBC+cbc = CBC "cbc"++instance IsSolver CBC IO where+  solve solver opt prob = do+    case LPFile.render def prob of+      Left err -> ioError $ userError err+      Right lp -> do+        withSystemTempFile "cbc.lp" $ \fname1 h1 -> do+          TLIO.hPutStr h1 lp+          hClose h1+          withSystemTempFile "cbc.sol" $ \fname2 h2 -> do+            hClose h2+            let args = [fname1]+                    ++ (case solveTimeLimit opt of+                          Nothing -> []+                          Just sec -> ["sec", show sec])+                    ++ ["solve", "solu", fname2]+                onGetLine = solveLogger opt+                onGetErrorLine = solveErrorLogger opt+            exitcode <- runProcessWithOutputCallback (cbcPath solver) args "" onGetLine onGetErrorLine+            case exitcode of+              ExitFailure n -> ioError $ userError $ "exit with " ++ show n+              ExitSuccess -> do+                sol <- CBCSol.readFile fname2+                if MIP.objDir (MIP.objectiveFunction prob) == MIP.OptMax then+                  return $ sol{ MIP.solObjectiveValue = fmap negate (MIP.solObjectiveValue sol) }+                else+                  return sol
+ src/ToySolver/Data/MIP/Solver/CPLEX.hs view
@@ -0,0 +1,71 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE MultiParamTypeClasses #-}+module ToySolver.Data.MIP.Solver.CPLEX+  ( CPLEX (..)+  , cplex+  ) where++import Control.Monad+import Data.Default.Class+import Data.IORef+import qualified Data.Text.Lazy.IO as TLIO+import System.Exit+import System.IO+import System.IO.Temp+import qualified ToySolver.Data.MIP.Base as MIP+import qualified ToySolver.Data.MIP.LPFile as LPFile+import ToySolver.Data.MIP.Solver.Base+import qualified ToySolver.Data.MIP.Solution.CPLEX as CPLEXSol+import ToySolver.Internal.ProcessUtil (runProcessWithOutputCallback)++data CPLEX+  = CPLEX+  { cplexPath :: String+  }++instance Default CPLEX where+  def = cplex++cplex :: CPLEX+cplex = CPLEX "cplex"++instance IsSolver CPLEX IO where+  solve solver opt prob = do+    case LPFile.render def prob of+      Left err -> ioError $ userError err+      Right lp -> do+        withSystemTempFile "cplex.lp" $ \fname1 h1 -> do+          TLIO.hPutStr h1 lp+          hClose h1+          withSystemTempFile "cplex.sol" $ \fname2 h2 -> do+            hClose h2+            isInfeasibleRef <- newIORef False+            let args = []+                input = unlines $+                  (case solveTimeLimit opt of+                          Nothing -> []+                          Just sec -> ["set timelimit ", show sec]) +++                  [ "read " ++ show fname1+                  , "optimize"+                  , "write " ++ show fname2+                  , "y"+                  , "quit"+                  ]+                onGetLine s = do+                  when (s == "MIP - Integer infeasible.") $ do+                    writeIORef isInfeasibleRef True+                  solveLogger opt s+                onGetErrorLine = solveErrorLogger opt+            exitcode <- runProcessWithOutputCallback (cplexPath solver) args input onGetLine onGetErrorLine+            case exitcode of+              ExitFailure n -> ioError $ userError $ "exit with " ++ show n+              ExitSuccess -> do+                size <- withFile fname2 ReadMode $ hFileSize+                if size == 0 then do+                  isInfeasible <- readIORef isInfeasibleRef+                  if isInfeasible then+                    return def{ MIP.solStatus = MIP.StatusInfeasible }+                  else+                    return def+                else+                  CPLEXSol.readFile fname2
+ src/ToySolver/Data/MIP/Solver/Glpsol.hs view
@@ -0,0 +1,72 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE MultiParamTypeClasses #-}+module ToySolver.Data.MIP.Solver.Glpsol+  ( Glpsol (..)+  , glpsol+  ) where++import Algebra.PartialOrd+import Control.Monad+import Data.Default.Class+import Data.IORef+import qualified Data.Text.Lazy.IO as TLIO+import System.Exit+import System.IO+import System.IO.Temp+import qualified ToySolver.Data.MIP.Base as MIP+import qualified ToySolver.Data.MIP.LPFile as LPFile+import ToySolver.Data.MIP.Solver.Base+import qualified ToySolver.Data.MIP.Solution.GLPK as GLPKSol+import ToySolver.Internal.ProcessUtil (runProcessWithOutputCallback)++data Glpsol+  = Glpsol+  { glpsolPath :: String+  }++instance Default Glpsol where+  def = glpsol++glpsol :: Glpsol+glpsol = Glpsol "glpsol"++instance IsSolver Glpsol IO where+  solve solver opt prob = do+    case LPFile.render def prob of+      Left err -> ioError $ userError err+      Right lp -> do+        withSystemTempFile "glpsol.lp" $ \fname1 h1 -> do+          TLIO.hPutStr h1 lp+          hClose h1+          withSystemTempFile "glpsol.sol" $ \fname2 h2 -> do+            hClose h2+            isUnboundedRef <- newIORef False+            isInfeasibleRef <- newIORef False+            let args = ["--lp", fname1, "-o", fname2] +++                       (case solveTimeLimit opt of+                          Nothing -> []+                          Just sec -> ["--tmlim", show (max 1 (floor sec) :: Int)])+                onGetLine s = do+                  case s of+                    "LP HAS UNBOUNDED PRIMAL SOLUTION" ->+                      writeIORef isUnboundedRef True+                    "PROBLEM HAS UNBOUNDED SOLUTION" ->+                      writeIORef isUnboundedRef True+                    "PROBLEM HAS NO PRIMAL FEASIBLE SOLUTION" ->+                      writeIORef isInfeasibleRef True+                    _ -> return ()+                  solveLogger opt s+                onGetErrorLine = solveErrorLogger opt+            exitcode <- runProcessWithOutputCallback (glpsolPath solver) args "" onGetLine onGetErrorLine+            case exitcode of+              ExitFailure n -> ioError $ userError $ "exit with " ++ show n+              ExitSuccess -> do+                sol <- GLPKSol.readFile fname2+                isUnbounded <- readIORef isUnboundedRef+                isInfeasible <- readIORef isInfeasibleRef+                if isUnbounded && MIP.solStatus sol `leq` MIP.StatusInfeasibleOrUnbounded then+                  return $ sol{ MIP.solStatus = MIP.StatusInfeasibleOrUnbounded }+                else if isInfeasible && MIP.solStatus sol `leq` MIP.StatusInfeasible then+                  return $ sol{ MIP.solStatus = MIP.StatusInfeasible }+                else+                  return sol
+ src/ToySolver/Data/MIP/Solver/GurobiCl.hs view
@@ -0,0 +1,64 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE MultiParamTypeClasses #-}+module ToySolver.Data.MIP.Solver.GurobiCl+  ( GurobiCl (..)+  , gurobiCl+  ) where++import Data.Default.Class+import Data.IORef+import Data.List (isPrefixOf)+import qualified Data.Text.Lazy.IO as TLIO+import System.Exit+import System.IO+import System.IO.Temp+import qualified ToySolver.Data.MIP.Base as MIP+import qualified ToySolver.Data.MIP.LPFile as LPFile+import ToySolver.Data.MIP.Solver.Base+import qualified ToySolver.Data.MIP.Solution.Gurobi as GurobiSol+import ToySolver.Internal.ProcessUtil (runProcessWithOutputCallback)++data GurobiCl+  = GurobiCl+  { gurobiClPath :: String+  }++instance Default GurobiCl where+  def = gurobiCl++gurobiCl :: GurobiCl+gurobiCl = GurobiCl "gurobi_cl"++instance IsSolver GurobiCl IO where+  solve solver opt prob = do+    case LPFile.render def prob of+      Left err -> ioError $ userError err+      Right lp -> do+        withSystemTempFile "gurobi.lp" $ \fname1 h1 -> do+          TLIO.hPutStr h1 lp+          hClose h1+          withSystemTempFile "gurobi.sol" $ \fname2 h2 -> do+            hClose h2+            statusRef <- newIORef MIP.StatusUnknown+            let args = ["ResultFile=" ++ fname2]+                    ++ (case solveTimeLimit opt of+                          Nothing -> []+                          Just sec -> ["TimeLimit=" ++ show sec])+                    ++ [fname1]+                onGetLine s = do+                  case s of+                    -- "Time limit reached" -> writeIORef statusRef MIP.StatusUnknown+                    "Model is unbounded" -> writeIORef statusRef MIP.StatusUnbounded+                    "Model is infeasible" -> writeIORef statusRef MIP.StatusInfeasible+                    "Model is infeasible or unbounded" -> writeIORef statusRef MIP.StatusInfeasibleOrUnbounded+                    _ | isPrefixOf "Optimal solution found" s -> writeIORef statusRef MIP.StatusOptimal+                    _ -> return ()+                  solveLogger opt s+                onGetErrorLine = solveErrorLogger opt+            exitcode <- runProcessWithOutputCallback (gurobiClPath solver) args "" onGetLine onGetErrorLine+            case exitcode of+              ExitFailure n -> ioError $ userError $ "exit with " ++ show n+              ExitSuccess -> do+                status <- readIORef statusRef+                sol <- GurobiSol.readFile fname2+                return $ sol{ MIP.solStatus = status }
+ src/ToySolver/Data/MIP/Solver/LPSolve.hs view
@@ -0,0 +1,85 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE MultiParamTypeClasses #-}+module ToySolver.Data.MIP.Solver.LPSolve+  ( LPSolve (..)+  , lpSolve+  ) where++import Control.Monad+import Data.Default.Class+import Data.IORef+import Data.List (stripPrefix)+import qualified Data.Map as Map+import Data.String+import qualified Data.Text.Lazy.IO as TLIO+import System.Exit+import System.IO+import System.IO.Temp+import qualified ToySolver.Data.MIP.Base as MIP+import qualified ToySolver.Data.MIP.MPSFile as MPSFile+import ToySolver.Data.MIP.Solver.Base+import ToySolver.Internal.ProcessUtil (runProcessWithOutputCallback)++data LPSolve+  = LPSolve+  { lpSolvePath :: String+  }++instance Default LPSolve where+  def = lpSolve++lpSolve :: LPSolve+lpSolve = LPSolve "lp_solve"++instance IsSolver LPSolve IO where+  solve solver opt prob = do+    case MPSFile.render def prob of+      Left err -> ioError $ userError err+      Right lp -> do+        withSystemTempFile "lp_solve.mps" $ \fname1 h1 -> do+          TLIO.hPutStr h1 lp+          hClose h1+          objRef <- newIORef Nothing+          solRef <- newIORef []+          flagRef <- newIORef False+          let args = (case solveTimeLimit opt of+                        Nothing -> []+                        Just sec -> ["-timeout", show sec])+                  ++ ["-fmps", fname1]+              onGetLine s = do+                case s of+                  "Actual values of the variables:" -> writeIORef flagRef True+                  _ | Just v <- stripPrefix "Value of objective function: " s -> do+                    writeIORef objRef (Just (read v))+                  _ -> do+                    flag <- readIORef flagRef+                    when flag $ do+                      case words s of+                        [var,val] -> modifyIORef solRef ((fromString var, read val) :)+                        _ -> return ()+                    return ()+                solveLogger opt s+              onGetErrorLine = solveErrorLogger opt+          exitcode <- runProcessWithOutputCallback (lpSolvePath solver) args "" onGetLine onGetErrorLine+          status <-+            case exitcode of+              ExitSuccess      -> return MIP.StatusOptimal+              ExitFailure (-2) -> return MIP.StatusUnknown               -- NOMEMORY+              ExitFailure 1    -> return MIP.StatusFeasible              -- SUBOPTIMAL+              ExitFailure 2    -> return MIP.StatusInfeasible            -- INFEASIBLE+              ExitFailure 3    -> return MIP.StatusInfeasibleOrUnbounded -- UNBOUNDED+              ExitFailure 4    -> return MIP.StatusUnknown               -- DEGENERATE+              ExitFailure 5    -> return MIP.StatusUnknown               -- NUMFAILURE+              ExitFailure 6    -> return MIP.StatusUnknown               -- USERABORT+              ExitFailure 7    -> return MIP.StatusUnknown               -- TIMEOUT+              ExitFailure 9    -> return MIP.StatusOptimal               -- PRESOLVED+              ExitFailure 25   -> return MIP.StatusUnknown               -- NUMFAILURE+              ExitFailure n    -> ioError $ userError $ "unknown exit code: " ++ show n+          obj <- readIORef objRef+          sol <- readIORef solRef+          return $+            MIP.Solution+            { MIP.solStatus = status+            , MIP.solObjectiveValue = obj+            , MIP.solVariables = Map.fromList sol+            }
+ src/ToySolver/Data/MIP/Solver/SCIP.hs view
@@ -0,0 +1,52 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE MultiParamTypeClasses #-}+module ToySolver.Data.MIP.Solver.SCIP+  ( SCIP (..)+  , scip+  ) where++import Data.Default.Class+import qualified Data.Text.Lazy.IO as TLIO+import System.Exit+import System.IO+import System.IO.Temp+import qualified ToySolver.Data.MIP.LPFile as LPFile+import ToySolver.Data.MIP.Solver.Base+import qualified ToySolver.Data.MIP.Solution.SCIP as ScipSol+import ToySolver.Internal.ProcessUtil (runProcessWithOutputCallback)++data SCIP+  = SCIP+  { scipPath :: String+  }++instance Default SCIP where+  def = scip++scip :: SCIP+scip = SCIP "scip"++instance IsSolver SCIP IO where+  solve solver opt prob = do+    case LPFile.render def prob of+      Left err -> ioError $ userError err+      Right lp -> do+        withSystemTempFile "scip.lp" $ \fname1 h1 -> do+          TLIO.hPutStr h1 lp+          hClose h1+          withSystemTempFile "scip.sol" $ \fname2 h2 -> do+            hClose h2+            let args = [ "-c", "read " ++ show fname1 ]+                    ++ (case solveTimeLimit opt of+                          Nothing -> []+                          Just sec -> ["-c", "set limits time " ++ show sec])+                    ++ [ "-c", "optimize"+                       , "-c", "write solution " ++ show fname2+                       , "-c", "quit"+                       ]+                onGetLine = solveLogger opt+                onGetErrorLine = solveErrorLogger opt+            exitcode <- runProcessWithOutputCallback (scipPath solver) args "" onGetLine onGetErrorLine+            case exitcode of+              ExitFailure n -> ioError $ userError $ "exit with " ++ show n+              ExitSuccess -> ScipSol.readFile fname2
src/ToySolver/Data/OrdRel.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, FunctionalDependencies #-}+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, FunctionalDependencies, UndecidableInstances #-} ----------------------------------------------------------------------------- -- | -- Module      :  ToySolver.Data.OrdRel@@ -7,7 +7,7 @@ --  -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  provisional--- Portability :  non-portable (FlexibleInstances, MultiParamTypeClasses, FunctionalDependencies)+-- Portability :  non-portable (FlexibleInstances, MultiParamTypeClasses, FunctionalDependencies, UndecidableInstances) -- -- Ordering relations -- @@ -33,7 +33,7 @@ import qualified Data.IntSet as IS  import ToySolver.Data.Boolean-import ToySolver.Data.Var+import ToySolver.Data.IntVar  infix 4 .<., .<=., .>=., .>., .==., ./=. @@ -136,3 +136,6 @@ fromOrdRel (OrdRel a op b) = ordRel op a b  -- ---------------------------------------------------------------------------++instance (Eval m e a, Ord a) => Eval m (OrdRel e) Bool where+  eval m (OrdRel lhs op rhs) = evalOp op (eval m lhs) (eval m rhs)
src/ToySolver/Data/Polyhedron.hs view
@@ -33,7 +33,7 @@ import qualified Data.Interval as Interval import ToySolver.Data.OrdRel import qualified ToySolver.Data.LA as LA-import ToySolver.Data.Var+import ToySolver.Data.IntVar  type ExprR = LA.Expr Rational type ExprZ = LA.Expr Integer
src/ToySolver/Data/Polynomial.hs view
@@ -77,6 +77,7 @@   , isRootOf   , isSquareFree   , nat+  , eisensteinsCriterion    -- * Term   , Term
src/ToySolver/Data/Polynomial/Base.hs view
@@ -78,6 +78,7 @@   , isRootOf   , isSquareFree   , nat+  , eisensteinsCriterion    -- * Term   , Term@@ -132,6 +133,7 @@ import Data.Hashable import Data.List import Data.Monoid+import Data.Numbers.Primes (primeFactors) import Data.Ratio import Data.String (IsString (..)) import Data.Map.Strict (Map)@@ -188,7 +190,7 @@   type Scalar (Polynomial k v) = k   k *^ p = scale k p -instance (Show v, Ord v, Show k) => Show (Polynomial k v) where+instance (Show v, Show k) => Show (Polynomial k v) where   showsPrec d p  = showParen (d > 10) $     showString "fromTerms " . shows (terms p) @@ -201,7 +203,7 @@ instance (Eq k, Num k, Ord v) => Var (Polynomial k v) v where   var x = fromTerm (1, var x) -instance (Eq k, Num k, Ord v) => Vars (Polynomial k v) v where+instance (Ord v) => Vars (Polynomial k v) v where   vars p = Set.unions $ [vars mm | (_, mm) <- terms p]  instance Degree (Polynomial k v) where@@ -209,7 +211,7 @@     | isZero p  = -1     | otherwise = maximum [deg mm | (_,mm) <- terms p] -normalize :: (Eq k, Num k, Ord v) => Polynomial k v -> Polynomial k v+normalize :: (Eq k, Num k) => Polynomial k v -> Polynomial k v normalize (Polynomial m) = Polynomial (Map.filter (0/=) m)  asConstant :: Num k => Polynomial k v -> Maybe k@@ -219,7 +221,7 @@     [(c,xs)] | Map.null (mindicesMap xs) -> Just c     _ -> Nothing -scale :: (Eq k, Num k, Ord v) => k -> Polynomial k v -> Polynomial k v+scale :: (Eq k, Num k) => k -> Polynomial k v -> Polynomial k v scale 0 _ = zero scale 1 p = p scale a (Polynomial m) = Polynomial (Map.mapMaybe f m)@@ -227,7 +229,7 @@     f b = if c == 0 then Nothing else Just c       where c = a * b -zero :: (Eq k, Num k, Ord v) => Polynomial k v+zero :: Polynomial k v zero = Polynomial $ Map.empty  plus :: (Eq k, Num k, Ord v) => Polynomial k v -> Polynomial k v -> Polynomial k v@@ -237,7 +239,7 @@       where         c = a + b -neg :: (Eq k, Num k, Ord v) => Polynomial k v -> Polynomial k v+neg :: (Num k) => Polynomial k v -> Polynomial k v neg (Polynomial m) = Polynomial $ Map.map negate m  mult :: (Eq k, Num k, Ord v) => Polynomial k v -> Polynomial k v -> Polynomial k v@@ -253,18 +255,18 @@ isZero (Polynomial m) = Map.null m  -- | construct a polynomial from a constant-constant :: (Eq k, Num k, Ord v) => k -> Polynomial k v+constant :: (Eq k, Num k) => k -> Polynomial k v constant c = fromTerm (c, mone)  -- | construct a polynomial from a list of terms fromTerms :: (Eq k, Num k, Ord v) => [Term k v] -> Polynomial k v fromTerms = fromCoeffMap . Map.fromListWith (+) . map (\(c,xs) -> (xs,c)) -fromCoeffMap :: (Eq k, Num k, Ord v) => Map (Monomial v) k -> Polynomial k v+fromCoeffMap :: (Eq k, Num k) => Map (Monomial v) k -> Polynomial k v fromCoeffMap m = normalize $ Polynomial m  -- | construct a polynomial from a singlet term-fromTerm :: (Eq k, Num k, Ord v) => Term k v -> Polynomial k v+fromTerm :: (Eq k, Num k) => Term k v -> Polynomial k v fromTerm (0,_) = zero fromTerm (c,xs) = Polynomial $ Map.singleton xs c @@ -273,18 +275,18 @@ terms (Polynomial m) = [(c,xs) | (xs,c) <- Map.toList m]  -- | leading term with respect to a given monomial order-lt :: (Eq k, Num k, Ord v) => MonomialOrder v -> Polynomial k v -> Term k v+lt :: (Num k) => MonomialOrder v -> Polynomial k v -> Term k v lt cmp p =   case terms p of     [] -> (0, mone) -- should be error?     ms -> maximumBy (cmp `on` snd) ms  -- | leading coefficient with respect to a given monomial order-lc :: (Eq k, Num k, Ord v) => MonomialOrder v -> Polynomial k v -> k+lc :: (Num k) => MonomialOrder v -> Polynomial k v -> k lc cmp = fst . lt cmp  -- | leading monomial with respect to a given monomial order-lm :: (Eq k, Num k, Ord v) => MonomialOrder v -> Polynomial k v -> Monomial v+lm :: (Num k) => MonomialOrder v -> Polynomial k v -> Monomial v lm cmp = snd . lt cmp  -- | Look up a coefficient for a given monomial.@@ -308,27 +310,32 @@     f x = assert (x `Prelude.mod` c == 0) $ x `Prelude.div` c  class ContPP k where+  type PPCoeff k+   -- | Content of a polynomial     cont :: (Ord v) => Polynomial k v -> k   -- constructive-algebra-0.3.0 では cont 0 は error になる    -- | Primitive part of a polynomial-  pp :: (Ord v) => Polynomial k v -> Polynomial k v+  pp :: (Ord v) => Polynomial k v -> Polynomial (PPCoeff k) v  instance ContPP Integer where+  type PPCoeff Integer = Integer   cont = contI   pp   = ppI  instance Integral r => ContPP (Ratio r) where   {-# SPECIALIZE instance ContPP (Ratio Integer) #-} +  type PPCoeff (Ratio r) = r+   cont 0 = 1   cont p = foldl1' Prelude.gcd ns % foldl' Prelude.lcm 1 ds     where       ns = [abs (numerator c) | (c,_) <- terms p]       ds = [denominator c     | (c,_) <- terms p]   -  pp p = mapCoeff (/ c) p+  pp p = mapCoeff (numerator . (/ c)) p     where       c = cont p @@ -345,18 +352,18 @@ integral p x = sumV [fromTerm (tintegral m x) | m <- terms p]  -- | Evaluation-eval :: (Num k, Ord v) => (v -> k) -> Polynomial k v -> k+eval :: (Num k) => (v -> k) -> Polynomial k v -> k eval env p = sum [c * product [(env x) ^ e | (x,e) <- mindices xs] | (c,xs) <- terms p]  -- | Substitution or bind subst-  :: (Eq k, Num k, Ord v1, Ord v2)+  :: (Eq k, Num k, Ord v2)   => Polynomial k v1 -> (v1 -> Polynomial k v2) -> Polynomial k v2 subst p s =   sumV [constant c * product [(s x)^e | (x,e) <- mindices xs] | (c, xs) <- terms p]  -- | Transform polynomial coefficients.-mapCoeff :: (Eq k1, Num k1, Ord v) => (k -> k1) -> Polynomial k v -> Polynomial k1 v+mapCoeff :: (Eq k1, Num k1) => (k -> k1) -> Polynomial k v -> Polynomial k1 v mapCoeff f (Polynomial m) = Polynomial $ Map.mapMaybe g m   where     g x = if y == 0 then Nothing else Just y@@ -364,7 +371,7 @@         y = f x  -- | Transform a polynomial into a monic polynomial with respect to the given monomial order.-toMonic :: (Eq r, Fractional r, Ord v) => MonomialOrder v -> Polynomial r v -> Polynomial r v+toMonic :: (Eq r, Fractional r) => MonomialOrder v -> Polynomial r v -> Polynomial r v toMonic cmp p   | c == 0 || c == 1 = p   | otherwise = mapCoeff (/c) p@@ -452,6 +459,33 @@   -- return a list @[(p1,n1), (p2,n2), ..]@.   sqfree :: a -> [(a, Integer)] +-- | Eisenstein's irreducibility criterion.+--+-- Given a polynomial with integer coefficients @P[x] = an x^n + .. + a1*x + a0@,+-- it is irreducible over rational numbers if there exists a prime number @p@+-- satisfying the following conditions:+--+-- * @p@ divides ai for @i /= n@,+--+-- * @p@ does not divides @an@, and+--+-- * @p^2@ does not divides @a0@.+--+eisensteinsCriterion+  :: (ContPP k, PPCoeff k ~ Integer)+  => UPolynomial k -> Bool+eisensteinsCriterion p+  | deg p <= 1 = True+  | otherwise  = eisensteinsCriterion' (pp p)++eisensteinsCriterion' :: UPolynomial Integer -> Bool+eisensteinsCriterion' p = or [criterion prime | prime <- map head $ group $ primeFactors c]+  where+    Just ((_,an), ts) = Map.maxViewWithKey (coeffMap p)+    a0 = coeff mone p+    c = foldl' Prelude.gcd 0 [ai | (_,ai) <- Map.toList ts]+    criterion prime = an `Prelude.mod` prime /= 0 && a0 `Prelude.mod` (prime*prime) /= 0+ {--------------------------------------------------------------------   Pretty printing --------------------------------------------------------------------}@@ -480,7 +514,7 @@   pPrintPrec = prettyPrint def  prettyPrint-  :: (Ord k, Num k, Ord v)+  :: (Ord k, Num k)   => PrintOptions k v   -> PrettyLevel -> Rational -> Polynomial k v -> Doc prettyPrint opt lv prec p =@@ -491,11 +525,11 @@         prettyParen (prec > addPrec) $           PP.hcat (pLeadingTerm addPrec t : map pTrailingTerm ts)     where-      pLeadingTerm prec (c,xs) =+      pLeadingTerm prec' (c,xs) =         if pOptIsNegativeCoeff opt c-        then prettyParen (prec > addPrec) $+        then prettyParen (prec' > addPrec) $                PP.char '-' <> prettyPrintTerm opt lv (addPrec+1) (-c,xs)-        else prettyPrintTerm opt lv prec (c,xs)+        else prettyPrintTerm opt lv prec' (c,xs)        pTrailingTerm (c,xs) =         if pOptIsNegativeCoeff opt c@@ -503,7 +537,7 @@         else PP.space <> PP.char '+' <> PP.space <> prettyPrintTerm opt lv (addPrec+1) (c,xs)  prettyPrintTerm-  :: (Ord k, Num k, Ord v)+  :: (Ord k, Num k)   => PrintOptions k v   -> PrettyLevel -> Rational -> Term k v -> Doc prettyPrintTerm opt lv prec (c,xs)@@ -518,9 +552,9 @@       fs  = [pOptPrintCoeff opt lv (appPrec+1) c | c /= 1] ++ [pPow (mulPrec+1) p | p <- mindices xs]       -- intentionally specify (appPrec+1) to parenthesize any composite expression -      pPow prec (x,1) = pOptPrintVar opt lv prec x-      pPow prec (x,n) =-        prettyParen (prec > expPrec) $+      pPow prec' (x,1) = pOptPrintVar opt lv prec' x+      pPow prec' (x,n) =+        prettyParen (prec' > expPrec) $           pOptPrintVar opt lv (expPrec+1) x <> PP.char '^' <> PP.integer n  class PrettyCoeff a where@@ -684,7 +718,7 @@             s = fromTerm (lc_f1, lm_f1 `mdiv` lm_g)  -- | GCD of univariate polynomials-gcd' :: (Eq r, Integral r) => UPolynomial r -> UPolynomial r -> UPolynomial r+gcd' :: (Integral r) => UPolynomial r -> UPolynomial r -> UPolynomial r gcd' f1 0  = ppI f1 gcd' f1 f2 = gcd' f2 (f1 `pmod` f2) @@ -707,24 +741,24 @@ tdeg :: Term k v -> Integer tdeg (_,xs) = deg xs -tscale :: (Num k, Ord v) => k -> Term k v -> Term k v+tscale :: (Num k) => k -> Term k v -> Term k v tscale a (c, xs) = (a*c, xs)  tmult :: (Num k, Ord v) => Term k v -> Term k v -> Term k v tmult (c1,xs1) (c2,xs2) = (c1*c2, xs1 `mmult` xs2) -tdivides :: (Fractional k, Ord v) => Term k v -> Term k v -> Bool+tdivides :: (Ord v) => Term k v -> Term k v -> Bool tdivides (_,xs1) (_,xs2) = xs1 `mdivides` xs2  tdiv :: (Fractional k, Ord v) => Term k v -> Term k v -> Term k v tdiv (c1,xs1) (c2,xs2) = (c1 / c2, xs1 `mdiv` xs2) -tderiv :: (Eq k, Num k, Ord v) => Term k v -> v -> Term k v+tderiv :: (Num k, Ord v) => Term k v -> v -> Term k v tderiv (c,xs) x =   case mderiv xs x of     (s,ys) -> (c * fromIntegral s, ys) -tintegral :: (Eq k, Fractional k, Ord v) => Term k v -> v -> Term k v+tintegral :: (Fractional k, Ord v) => Term k v -> v -> Term k v tintegral (c,xs) x =   case mintegral xs x of     (s,ys) -> (c * fromRational s, ys)@@ -741,7 +775,7 @@  type UMonomial = Monomial X -instance (Ord v, Show v) => Show (Monomial v) where+instance (Show v) => Show (Monomial v) where   showsPrec d m  = showParen (d > 10) $     showString "mfromIndices " . shows (mindices m) @@ -776,10 +810,10 @@   | any (\(_,e) -> 0>e) (Map.toList m) = error "ToySolver.Data.Polynomial.mfromIndicesMap: negative exponent"   | otherwise = mfromIndicesMap' m -mfromIndicesMap' :: Ord v => Map v Integer -> Monomial v+mfromIndicesMap' :: Map v Integer -> Monomial v mfromIndicesMap' m = Monomial $ Map.filter (>0) m -mindices :: Ord v => Monomial v -> [(v, Integer)]+mindices :: Monomial v -> [(v, Integer)] mindices = Map.toAscList . mindicesMap  mmult :: Ord v => Monomial v -> Monomial v -> Monomial v@@ -835,7 +869,7 @@  -- | Lexicographic order lex :: Ord v => MonomialOrder v-lex xs1 xs2 = go (mindices xs1) (mindices xs2)+lex = go `on` mindices   where     go [] [] = EQ     go [] _  = LT -- = compare 0 n2@@ -850,7 +884,7 @@ --  -- Note that revlex is /NOT/ a monomial order. revlex :: Ord v => Monomial v -> Monomial v -> Ordering-revlex xs1 xs2 = go (Map.toDescList (mindicesMap xs1)) (Map.toDescList (mindicesMap xs2))+revlex = go `on` (Map.toDescList . mindicesMap)   where     go [] [] = EQ     go [] _  = GT -- = cmp 0 n2
src/ToySolver/Data/Polynomial/Factorization/FiniteField.hs view
@@ -34,16 +34,16 @@ import Data.List import Data.Set (Set) import qualified Data.Set as Set-import qualified TypeLevel.Number.Nat as TL+import GHC.TypeLits  import ToySolver.Data.Polynomial.Base (Polynomial, UPolynomial, X (..)) import qualified ToySolver.Data.Polynomial.Base as P import qualified ToySolver.Data.Polynomial.GroebnerBasis as GB -instance TL.Nat p => P.Factor (UPolynomial (PrimeField p)) where+instance KnownNat p => P.Factor (UPolynomial (PrimeField p)) where   factor = factor -instance TL.Nat p => P.SQFree (UPolynomial (PrimeField p)) where+instance KnownNat p => P.SQFree (UPolynomial (PrimeField p)) where   sqfree = sqfree  factor :: forall k. (Ord k, FiniteField k) => UPolynomial k -> [(UPolynomial k, Integer)]
src/ToySolver/Data/Polynomial/Factorization/Hensel/Internal.hs view
@@ -25,14 +25,15 @@  import Control.Exception (assert) import Data.FiniteField-import qualified TypeLevel.Number.Nat as TL+import Data.Proxy+import GHC.TypeLits  import ToySolver.Data.Polynomial.Base (UPolynomial) import qualified ToySolver.Data.Polynomial.Base as P  -- import Text.PrettyPrint.HughesPJClass -hensel :: forall p. TL.Nat p => UPolynomial Integer -> [UPolynomial (PrimeField p)] -> Integer -> [UPolynomial Integer]+hensel :: forall p. KnownNat p => UPolynomial Integer -> [UPolynomial (PrimeField p)] -> Integer -> [UPolynomial Integer] hensel f fs1 k   | k <= 0    = error "ToySolver.Data.Polynomial.Factorization.Hensel.hensel: k <= 0"   | otherwise = assert precondition $ go 1 (map (P.mapCoeff Data.FiniteField.toInteger) fs1)@@ -42,7 +43,7 @@       P.deg f == P.deg (product fs1)      p :: Integer-    p = TL.toInt (undefined :: p)+    p = natVal (Proxy :: Proxy p)      go :: Integer -> [UPolynomial Integer] -> [UPolynomial Integer]     go !i fs@@ -50,20 +51,20 @@       | otherwise = assert (check i fs) $ go (i+1) (lift i fs)      check :: Integer -> [UPolynomial Integer] -> Bool-    check k fs =+    check k' fs =         and          [ P.mapCoeff (`mod` pk) f == P.mapCoeff (`mod` pk) (product fs)         , fs1 == map (P.mapCoeff fromInteger) fs         , and [P.deg fi1 == P.deg fik | (fi1, fik) <- zip fs1 fs]         ]       where-        pk = p ^ k+        pk = p ^ k'      lift :: Integer -> [UPolynomial Integer] -> [UPolynomial Integer]-    lift k fs = fs'+    lift k' fs = fs'       where-        pk  = p^k-        pk1 = p^(k+1)+        pk  = p^k'+        pk1 = p^(k'+1)          -- f ≡ product fs + p^k h  (mod p^(k+1))         h :: UPolynomial Integer@@ -83,18 +84,18 @@ cabook_proposition_5_10 fs = normalize (go fs)   where     check :: [UPolynomial k] -> [UPolynomial k] -> Bool-    check es fs = sum [ei * (product fs `P.div` fi) | (ei,fi) <- zip es fs] == 1+    check es fs' = sum [ei * (product fs' `P.div` fi) | (ei,fi) <- zip es fs'] == 1      go :: [UPolynomial k] -> [UPolynomial k]     go [] = error "cabook_proposition_5_10: empty list"     go [fi] = assert (check [1] [fi]) [1]-    go fs@(fi : fs') = +    go (fi : fs') =       case P.exgcd (product fs') fi of         (g,ei,v) ->            assert (g == 1) $              let es' = go fs'                  es  = ei : map (v*) es'-             in assert (check es fs) es+             in assert (check es (fi : fs')) es      normalize :: [UPolynomial k] -> [UPolynomial k]     normalize es = assert (check es2 fs) es2@@ -103,12 +104,12 @@  -- http://www.math.kobe-u.ac.jp/Asir/ca.pdf cabook_proposition_5_11-  :: forall k. (Num k, Fractional k, Eq k, P.PrettyCoeff k, Ord k)+  :: forall k. (Fractional k, Ord k)   => [UPolynomial k] -> UPolynomial k -> [UPolynomial k] cabook_proposition_5_11 fs g =   assert (P.deg g <= P.deg (product fs)) $   assert (P.deg c <= 0) $-  assert (check es2 fs g) $+  assert (check es2) $     es2   where     es  = map (g*) $ cabook_proposition_5_10 fs@@ -116,7 +117,7 @@     es2 = case zipWith P.mod es fs of             e2' : es2' -> e2' + c * head fs : es2'           -    check :: [UPolynomial k] -> [UPolynomial k] -> UPolynomial k -> Bool-    check es fs g =-      sum [ei * (product fs `P.div` fi) | (ei,fi) <- zip es fs] == g &&-      and [P.deg ei <= P.deg fi | (ei,fi) <- zip es fs]+    check :: [UPolynomial k] -> Bool+    check es' =+      sum [ei * (product fs `P.div` fi) | (ei,fi) <- zip es' fs] == g &&+      and [P.deg ei <= P.deg fi | (ei,fi) <- zip es' fs]
src/ToySolver/Data/Polynomial/Factorization/Kronecker.hs view
@@ -71,7 +71,7 @@     Just (xi,_) ->       let q1 = x - P.constant xi           q2 = p' `P.div` P.mapCoeff fromInteger q1-      in Just (q1, toZ q2)+      in Just (q1, P.pp q2)     Nothing ->       let qs = map Interpolation.interpolate $                   sequence [[(fromInteger xi, fromInteger z) | z <- factors yi] | (xi,yi) <- vs]@@ -82,7 +82,7 @@                ]       in case zs of            [] -> Nothing-           (q1,q2):_ -> Just (toZ q1, toZ q2)+           (q1,q2):_ -> Just (P.pp q1, P.pp q2)   where     n = P.deg p `div` 2     xs = take (fromIntegral n + 1) xvalues@@ -93,9 +93,6 @@  isUPolyZ :: UPolynomial Rational -> Bool isUPolyZ p = and [isInteger c | (c,_) <- P.terms p]--toZ :: Ord v => Polynomial Rational v -> Polynomial Integer v-toZ = P.mapCoeff numerator . P.pp  -- [0, 1, -1, 2, -2, 3, -3 ..] xvalues :: [Integer]
src/ToySolver/Data/Polynomial/Factorization/Rational.hs view
@@ -12,6 +12,6 @@   factor 0 = [(0,1)]   factor p = [(P.constant c, 1) | c /= 1] ++ qs2     where-      qs  = P.factor $ P.mapCoeff numerator $ P.pp p+      qs  = P.factor $ P.pp p       qs2 = [(P.mapCoeff fromInteger q, m) | (q,m) <- qs, P.deg q > 0]       c   = toRational (product [(P.coeff P.mone q)^m | (q,m) <- qs, P.deg q == 0]) * P.cont p
src/ToySolver/Data/Polynomial/Factorization/SquareFree.hs view
@@ -60,4 +60,4 @@           [(P.constant (numerator u), 1) | u /= 1] ++ ys       go !u ys ((g,n):xs)         | P.deg g <= 0 = go (u * P.coeff P.mone g) ys xs-        | otherwise    = go (u * (P.cont g)^n) ((P.mapCoeff numerator (P.pp g), n) : ys) xs+        | otherwise    = go (u * (P.cont g)^n) ((P.pp g, n) : ys) xs
src/ToySolver/Data/Polynomial/Factorization/Zassenhaus.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE BangPatterns, ScopedTypeVariables #-}+{-# LANGUAGE BangPatterns, ScopedTypeVariables, Rank2Types #-} {-# OPTIONS_GHC -Wall #-} ----------------------------------------------------------------------------- -- |@@ -8,7 +8,7 @@ --  -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  provisional--- Portability :  non-portable (BangPatterns, ScopedTypeVariables)+-- Portability :  non-portable (BangPatterns, ScopedTypeVariables, Rank2Types) -- -- Factoriation of integer-coefficient polynomial using Zassenhaus algorithm. --@@ -37,7 +37,8 @@ import ToySolver.Data.Polynomial.Factorization.SquareFree () import qualified ToySolver.Data.Polynomial.Factorization.Hensel as Hensel -import qualified TypeLevel.Number.Nat as TL+import Data.Proxy+import GHC.TypeLits import Data.FiniteField  -- import Text.PrettyPrint.HughesPJClass@@ -46,9 +47,9 @@ factor f = [(h,n) | (g,n) <- P.sqfree f, h <- if P.deg g > 0 then zassenhaus g else return g]  zassenhaus :: UPolynomial Integer -> [UPolynomial Integer]-zassenhaus f = fromJust $ msum [TL.withNat zassenhausWithP p | p <- primes :: [Integer]]+zassenhaus f = fromJust $ msum [withNat zassenhausWithP p | p <- primes :: [Integer]]   where-    zassenhausWithP :: forall p. TL.Nat p => p -> Maybe [UPolynomial Integer]+    zassenhausWithP :: forall p. KnownNat p => Proxy p -> Maybe [UPolynomial Integer]     zassenhausWithP _ = do       let f_mod_p :: UPolynomial (PrimeField p)           f_mod_p = P.mapCoeff fromInteger f@@ -58,6 +59,12 @@           fs = [assert (n==1) fi | (fi,n) <- P.factor f_mod_p]       return $ lift f fs +    withNat :: (forall p. KnownNat p => Proxy p -> a) -> Integer -> a+    withNat f p =+      case someNatVal p of+        Just (SomeNat x) -> f x+        Nothing -> undefined+ {- Suppose @g@ is a factor of @f@. @@ -72,7 +79,7 @@  Then it call @search@ to look for actual factorization. -}-lift :: forall p. TL.Nat p => UPolynomial Integer -> [UPolynomial (PrimeField p)] -> [UPolynomial Integer]+lift :: forall p. KnownNat p => UPolynomial Integer -> [UPolynomial (PrimeField p)] -> [UPolynomial Integer] lift f [_] = [f] lift f fs  = search pk f (Hensel.hensel f fs k)   where@@ -114,7 +121,7 @@       let f1 = P.mapCoeff fromInteger f        when (P.deg g1 > 0 && g1 `P.divides` f1) $ do-        let g2 = P.mapCoeff numerator $ P.pp g1+        let g2 = P.pp g1             -- we choose leading coefficient to be positive.             g :: UPolynomial Integer             g = if P.lc P.nat g2 < 0 then - g2 else g2
− src/ToySolver/Data/Var.hs
@@ -1,46 +0,0 @@--------------------------------------------------------------------------------- |--- Module      :  ToySolver.Data.Var--- Copyright   :  (c) Masahiro Sakai 2011-2013--- License     :  BSD-style--- --- Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  provisional--- Portability :  portable--- -------------------------------------------------------------------------------module ToySolver.Data.Var-  ( Var-  , VarSet-  , VarMap-  , Variables (..)-  , Model-  ) where--import Data.IntMap (IntMap)-import Data.IntSet (IntSet)-import qualified Data.IntSet as IntSet-import Data.Ratio---- ------------------------------------------------------------------------------- | Variables are represented as non-negative integers-type Var = Int---- | Set of variables-type VarSet = IntSet---- | Map from variables-type VarMap = IntMap---- | collecting free variables-class Variables a where-  vars :: a -> VarSet--instance Variables a => Variables [a] where-  vars = IntSet.unions . map vars---- | A @Model@ is a map from variables to values.-type Model r = VarMap r---- ---------------------------------------------------------------------------
src/ToySolver/EUF/EUFSolver.hs view
@@ -189,11 +189,3 @@ fsymToTerm     = CC.fsymToTerm     . svCCSolver fsymToFlatTerm = CC.fsymToFlatTerm . svCCSolver flatTermToFSym = CC.flatTermToFSym . svCCSolver--#if !MIN_VERSION_base(4,7,0)--isRight :: Either a b -> Bool-isRight (Left  _) = False-isRight (Right _) = True--#endif
src/ToySolver/EUF/FiniteModelFinder.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, ScopedTypeVariables, MultiParamTypeClasses #-}+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, ScopedTypeVariables, MultiParamTypeClasses, OverloadedStrings #-} ----------------------------------------------------------------------------- -- | -- Module      :  ToySolver.EUF.FiniteModelFinder@@ -7,7 +7,7 @@ --  -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  provisional--- Portability :  non-portable (TypeSynonymInstances, FlexibleInstances, ScopedTypeVariables, MultiParamTypeClasses)+-- Portability :  non-portable (TypeSynonymInstances, FlexibleInstances, ScopedTypeVariables, MultiParamTypeClasses, OverloadedStrings) -- -- A simple model finder. --@@ -55,13 +55,19 @@ import Control.Monad import Control.Monad.State import Data.Array.IArray+import Data.Interned (intern, unintern)+import Data.Interned.Text import Data.IORef import Data.List import Data.Maybe import Data.Map (Map) import qualified Data.Map as Map+import Data.Monoid import Data.Set (Set) import qualified Data.Set as Set+import Data.String+import Data.Text (Text)+import qualified Data.Text as Text import Text.Printf  import ToySolver.Data.Boolean@@ -70,13 +76,13 @@ -- ---------------------------------------------------------------------------  -- | Variable-type Var = String+type Var = InternedText  -- | Function Symbol-type FSym = String+type FSym = InternedText  -- | Predicate Symbol-type PSym = String+type PSym = InternedText  class Vars a where   vars :: a -> Set Var@@ -196,7 +202,7 @@ -- TODO: --  -- * Tseitin encoding-toSkolemNF :: forall m. Monad m => (String -> Int -> m FSym) -> Formula -> m [Clause]+toSkolemNF :: forall m. Monad m => (Var -> Int -> m FSym) -> Formula -> m [Clause] toSkolemNF skolem phi = f [] Map.empty (toNNF phi)   where     f :: [Var] -> Map Var Term -> Formula -> m [Clause]@@ -213,17 +219,17 @@       psi' <- f uvs s psi       return $ [c1++c2 | c1 <- phi', c2 <- psi']     f uvs s psi@(Forall v phi) = do-      let v' = gensym v (vars psi `Set.union` Set.fromList uvs)+      let v' = gensym (unintern v) (vars psi `Set.union` Set.fromList uvs)       f (v' : uvs) (Map.insert v (TmVar v') s) phi     f uvs s (Exists v phi) = do       fsym <- skolem v (length uvs)       f uvs (Map.insert v (TmApp fsym [TmVar v | v <- reverse uvs]) s) phi     f _ _ _ = error "ToySolver.EUF.FiniteModelFinder.toSkolemNF: should not happen" -    gensym :: String -> Set Var -> Var+    gensym :: Text -> Set Var -> Var     gensym template vs = head [name | name <- names, Set.notMember name vs]       where-        names = template : [template ++ show n | n <-[1..]]+        names = map intern $ template : [template <> fromString (show n) | n <-[1..]]      substAtom :: Map Var Term -> Atom -> Atom     substAtom s (PApp p ts) = PApp p (map (substTerm s) ts)@@ -234,9 +240,10 @@  test_toSkolemNF = do   ref <- newIORef 0-  let skolem name _ = do+  let skolem :: Var -> Int -> IO FSym+      skolem name _ = do         n <- readIORef ref-        let fsym = name ++ "#" ++ show n+        let fsym = intern $ unintern name <> "#" <> fromString (show n)         writeIORef ref (n+1)         return fsym @@ -297,7 +304,7 @@       (vs, n, defs, ls) <- get       let go :: Int -> M Var           go m = do-            let v = "#" ++ show m+            let v = intern $ "#" <> fromString (show m)             if v `Set.member` vs               then go (m+1)               else do@@ -473,11 +480,11 @@ showModel :: Model -> [String] showModel m =    printf "DOMAIN = {%s}" (intercalate ", " (map showEntity (mUniverse m))) :-  [ printf "%s = { %s }" p s+  [ printf "%s = { %s }" (Text.unpack (unintern p)) s   | (p, xss) <- Map.toList (mRelations m)   , let s = intercalate ", " [if length xs == 1 then showEntity (head xs) else showEntityTuple xs | xs <- Set.toList xss]   ] ++-  [ printf "%s%s = %s" f (if length xs == 0 then "" else showEntityTuple xs) (showEntity y)+  [ printf "%s%s = %s" (Text.unpack (unintern f)) (if length xs == 0 then "" else showEntityTuple xs) (showEntity y)   | (f, xss) <- Map.toList (mFunctions m)   , (xs, y) <- Map.toList xss   ]@@ -620,9 +627,10 @@               Atom (PApp "=" [TmApp "f" [TmVar "y"], TmVar "x"])    ref <- newIORef 0-  let skolem name _ = do+  let skolem :: Var -> Int -> IO FSym+      skolem name _ = do         n <- readIORef ref-        let fsym = name ++ "#" ++ show n+        let fsym = intern $ unintern name <> "#" <> fromString (show n)         writeIORef ref (n+1)         return fsym   cs <- toSkolemNF skolem phi
+ src/ToySolver/Graph/ShortestPath.hs view
@@ -0,0 +1,434 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE ScopedTypeVariables #-}+--------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Graph.ShortestPath+-- Copyright   :  (c) Masahiro Sakai 2016-2017+-- License     :  BSD-style+--+-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable+--+-- This module provides functions for shotest path computation.+--+-- Reference:+--+-- * Friedrich Eisenbrand. “Linear and Discrete Optimization”.+--   <https://www.coursera.org/course/linearopt>+--+--------------------------------------------------------------------------+module ToySolver.Graph.ShortestPath+  (+  -- * Graph data types+    Graph+  , Edge+  , OutEdge+  , InEdge++  -- * Fold data type+  , Fold (..)+  , monoid'+  , monoid+  , unit+  , pair+  , path+  , firstOutEdge+  , lastInEdge++  -- * Path data types+  , Path (..)+  , pathFrom+  , pathTo+  , pathCost+  , pathEmpty+  , pathAppend+  , pathEdges+  , pathEdgesBackward+  , pathEdgesSeq+  , pathVertexes+  , pathVertexesBackward+  , pathVertexesSeq+  , pathFold++  -- * Shortest-path algorithms+  , bellmanFord+  , dijkstra+  , floydWarshall++  -- * Utility functions+  , bellmanFordDetectNegativeCycle+  ) where++import Control.Applicative+import Control.Monad+import Control.Monad.ST+import Control.Monad.Trans+import Control.Monad.Trans.Except+import Data.Hashable+import qualified Data.HashTable.Class as H+import qualified Data.HashTable.ST.Cuckoo as C+import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import qualified Data.HashSet as HashSet+import qualified Data.Heap as Heap -- http://hackage.haskell.org/package/heaps+import Data.List (foldl')+import Data.Monoid+import Data.Ord+import Data.Sequence (Seq)+import qualified Data.Sequence as Seq+import Data.STRef++-- ------------------------------------------------------------------------++-- | Graph represented as a map from vertexes to their outgoing edges+type Graph vertex cost label = HashMap vertex [OutEdge vertex cost label]++-- | Edge data type+type Edge vertex cost label = (vertex, vertex, cost, label)++-- | Outgoing edge data type (source vertex is implicit)+type OutEdge vertex cost label = (vertex, cost, label)++-- | Incoming edge data type (target vertex is implicit)+type InEdge vertex cost label = (vertex, cost, label)++-- | path data type.+data Path vertex cost label +  = Empty vertex+    -- ^ empty path+  | Singleton (Edge vertex cost label)+    -- ^ path with single edge+  | Append (Path vertex cost label) (Path vertex cost label) !cost+    -- ^ concatenation of two paths+  deriving (Eq, Show)++-- | Source vertex+pathFrom :: Path vertex cost label -> vertex+pathFrom (Empty v) = v+pathFrom (Singleton (from,_,_,_)) = from+pathFrom (Append p1 _ _) = pathFrom p1++-- | Target vertex+pathTo :: Path vertex cost label -> vertex+pathTo (Empty v) = v+pathTo (Singleton (_,to,_,_)) = to+pathTo (Append _ p2 _) = pathTo p2++-- | Cost of a path+pathCost :: Num cost => Path vertex cost label -> cost+pathCost (Empty _) = 0+pathCost (Singleton (_,_,c,_)) = c+pathCost (Append _ _ c) = c++-- | Empty path+pathEmpty :: vertex -> Path vertex cost label+pathEmpty = Empty++-- | Concatenation of two paths+pathAppend :: (Eq vertex, Num cost) => Path vertex cost label -> Path vertex cost label -> Path vertex cost label+pathAppend p1 p2 +  | pathTo p1 /= pathFrom p2 = error "ToySolver.Graph.ShortestPath.pathAppend: pathTo/pathFrom mismatch"+  | otherwise =+      case (p1, p2) of+        (Empty _, _) -> p2+        (_, Empty _) -> p1+        _ -> Append p1 p2 (pathCost p1 + pathCost p2)++-- | Edges of a path+pathEdges :: Path vertex cost label -> [Edge vertex cost label]+pathEdges p = f p []+  where+    f (Empty _) xs = xs+    f (Singleton e) xs = e : xs+    f (Append p1 p2 _) xs = f p1 (f p2 xs)++-- | Edges of a path, but in the reverse order+pathEdgesBackward :: Path vertex cost label -> [Edge vertex cost label]+pathEdgesBackward p = f p []+  where+    f (Empty _) xs = xs+    f (Singleton e) xs = e : xs+    f (Append p1 p2 _) xs = f p2 (f p1 xs)++-- | Edges of a path, but as `Seq`+pathEdgesSeq :: Path vertex cost label -> Seq (Edge vertex cost label)+pathEdgesSeq (Empty _) = Seq.empty+pathEdgesSeq (Singleton e) = Seq.singleton e+pathEdgesSeq (Append p1 p2 _) = pathEdgesSeq p1 <> pathEdgesSeq p2++-- | Vertexes of a path+pathVertexes :: Path vertex cost label -> [vertex]+pathVertexes p = pathFrom p : f p []+  where+    f (Empty _) xs = xs+    f (Singleton (_,v2,_,_)) xs = v2 : xs+    f (Append p1 p2 _) xs = f p1 (f p2 xs)++-- | Vertexes of a path, but in the reverse order+pathVertexesBackward :: Path vertex cost label -> [vertex]+pathVertexesBackward p = pathTo p : f p []+  where+    f (Empty _) xs = xs+    f (Singleton (v1,_,_,_)) xs = v1 : xs+    f (Append p1 p2 _) xs = f p2 (f p1 xs)++-- | Vertex of a path, but as `Seq`+pathVertexesSeq :: Path vertex cost label -> Seq vertex+pathVertexesSeq p = f True p+  where+    f True  (Empty v) = Seq.singleton v+    f False (Empty _) = mempty+    f True  (Singleton (v1,v2,_,_)) = Seq.fromList [v1, v2]+    f False (Singleton (v1,_,_,_))  = Seq.singleton v1+    f b (Append p1 p2 _) = f False p1 <> f b p2++pathMin :: (Num cost, Ord cost) => Path vertex cost label -> Path vertex cost label -> Path vertex cost label+pathMin p1 p2+  | pathCost p1 <= pathCost p2 = p1+  | otherwise = p2++-- | Fold a path using a given 'Fold` operation.+pathFold :: Fold vertex cost label a -> Path vertex cost label -> a+pathFold (Fold fV fE fC fD) p = fD (h p)+  where+    h (Empty v) = fV v+    h (Singleton e) = fE e+    h (Append p1 p2 _) = fC (h p1) (h p2)++-- ------------------------------------------------------------------------++-- | Strict pair type+data Pair a b = Pair !a !b++-- ------------------------------------------------------------------------++-- | Operations for folding edge information along with a path into a @r@ value.+--+-- @Fold vertex cost label r@ consists of three operations+--+-- * @vertex -> a@ corresponds to an empty path,+--+-- * @Edge vertex cost label -> a@ corresponds to a single edge,+--+-- * @a -> a -> a@ corresponds to path concatenation,+--+-- and @a -> r@ to finish the computation.+data Fold vertex cost label r+  = forall a. Fold (vertex -> a) (Edge vertex cost label -> a) (a -> a -> a) (a -> r)++instance Functor (Fold vertex cost label) where+  {-# INLINE fmap #-}+  fmap f (Fold fV fE fC fD) = Fold fV fE fC (f . fD)++instance Applicative (Fold vertex cost label) where+  {-# INLINE pure #-}+  pure a = Fold (\_ -> ()) (\_ -> ()) (\_ _ -> ()) (const a)++  {-# INLINE (<*>) #-}+  Fold fV1 fE1 fC1 fD1 <*> Fold fV2 fE2 fC2 fD2 =+    Fold (\v -> Pair (fV1 v) (fV2 v))+         (\e -> Pair (fE1 e) (fE2 e))+         (\(Pair a1 b1) (Pair a2 b2) -> Pair (fC1 a1 a2) (fC2 b1 b2))+         (\(Pair a b) -> fD1 a (fD2 b))++-- | Project `Edge` into a monoid value and fold using monoidal operation.+monoid' :: Monoid m => (Edge vertex cost label -> m) -> Fold vertex cost label m+monoid' f = Fold (\_ -> mempty) f mappend id++-- | Similar to 'monoid'' but a /label/ is directly used as a monoid value.+monoid :: Monoid m => Fold vertex cost m m+monoid = monoid' (\(_,_,_,m) -> m)++-- | Ignore contents and return a unit value.+unit :: Fold vertex cost label ()+unit = monoid' (\_ -> ())++-- | Pairs two `Fold` into one that produce a tuple.+pair :: Fold vertex cost label a -> Fold vertex cost label b -> Fold vertex cost label (a,b)+pair (Fold fV1 fE1 fC1 fD1) (Fold fV2 fE2 fC2 fD2) =+  Fold (\v -> Pair (fV1 v) (fV2 v))+       (\e -> Pair (fE1 e) (fE2 e))+       (\(Pair a1 b1) (Pair a2 b2) -> Pair (fC1 a1 a2) (fC2 b1 b2))+       (\(Pair a b) -> (fD1 a, fD2 b))++-- | Construct a `Path` value.+path :: (Eq vertex, Num cost) => Fold vertex cost label (Path vertex cost label)+path = Fold pathEmpty Singleton pathAppend id++-- | Compute cost of a path.+cost :: Num cost => Fold vertex cost label cost+cost = Fold (\_ -> 0) (\(_,_,c,_) -> c) (+) id++-- | Get the first `OutEdge` of a path.+firstOutEdge :: Fold vertex cost label (First (OutEdge vertex cost label))+firstOutEdge = monoid' (\(_,v,c,l) -> First (Just (v,c,l)))++-- | Get the last `InEdge` of a path.+-- This is useful for constructing a /parent/ map of a spanning tree.+lastInEdge :: Fold vertex cost label (Last (InEdge vertex cost label))+lastInEdge = monoid' (\(v,_,c,l) -> Last (Just (v,c,l)))++-- ------------------------------------------------------------------------++-- | Bellman-Ford algorithm for finding shortest paths from source vertexes+-- to all of the other vertices in a weighted graph with negative weight+-- edges allowed.+--+-- It compute shortest-paths from given source vertexes, and folds edge+-- information along shortest paths using a given 'Fold' operation.+bellmanFord+  :: (Eq vertex, Hashable vertex, Real cost)+  => Fold vertex cost label a+     -- ^ Operation used to fold shotest paths+  -> Graph vertex cost label+  -> [vertex]+     -- ^ List of source vertexes @vs@+  -> HashMap vertex (cost, a)+bellmanFord (Fold fV fE fC fD) g ss = runST $ do+  let n = HashMap.size g+  d <- C.newSized n+  forM_ ss $ \s -> H.insert d s (Pair 0 (fV s))++  updatedRef <- newSTRef (HashSet.fromList ss)+  _ <- runExceptT $ replicateM_ n $ do+    us <- lift $ readSTRef updatedRef+    when (HashSet.null us) $ throwE ()+    lift $ do+      writeSTRef updatedRef HashSet.empty+      forM_ (HashSet.toList us) $ \u -> do+        Just (Pair du a) <- H.lookup d u+        forM_ (HashMap.lookupDefault [] u g) $ \(v, c, l) -> do+          m <- H.lookup d v+          case m of+            Just (Pair c0 _) | c0 <= du + c -> return ()+            _ -> do+              H.insert d v (Pair (du + c) (a `fC` fE (u,v,c,l)))+              modifySTRef' updatedRef (HashSet.insert v)++  liftM (fmap (\(Pair c x) -> (c, fD x))) $ freezeHashTable d++freezeHashTable :: (H.HashTable h, Hashable k, Eq k) => h s k v -> ST s (HashMap k v)+freezeHashTable h = H.foldM (\m (k,v) -> return $! HashMap.insert k v m) HashMap.empty h++-- | Utility function for detecting a negative cycle.+bellmanFordDetectNegativeCycle+  :: forall vertex cost label a. (Eq vertex, Hashable vertex, Real cost)+  => Fold vertex cost label a+     -- ^ Operation used to fold a cycle+  -> Graph vertex cost label+  -> HashMap vertex (cost, Last (InEdge vertex cost label))+     -- ^ Result of @'bellmanFord' 'lastInEdge' vs@+  -> Maybe a+bellmanFordDetectNegativeCycle (Fold fV fE fC fD) g d = either (Just . fD) (const Nothing) $ do+  forM_ (HashMap.toList d) $ \(u,(du,_)) ->+    forM_ (HashMap.lookupDefault [] u g) $ \(v, c, l) -> do+      let (dv,_) = d HashMap.! v+      when (du + c < dv) $ do+        -- a negative cycle is detected+        let d' = HashMap.insert v (du + c, Last (Just (u, c, l))) d+            parent u = do+              case HashMap.lookup u d' of+                Just (_, Last (Just (v,_,_))) -> v+                _ -> undefined+            u0 = go (parent (parent v)) (parent v)+              where+                go hare tortoise+                  | hare == tortoise = hare+                  | otherwise = go (parent (parent hare)) (parent tortoise)+        let go u result = do+              let Just (_, Last (Just (v,c,l))) = HashMap.lookup u d'+              if v == u0 then+                fC (fE (v,u,c,l)) result+              else+                go v (fC (fE (v,u,c,l)) result)+        Left $ go u0 (fV u0)++-- ------------------------------------------------------------------------++-- | Dijkstra's algorithm for finding shortest paths from source vertexes+-- to all of the other vertices in a weighted graph with non-negative edge+-- weight.+--+-- It compute shortest-paths from given source vertexes, and folds edge+-- information along shortest paths using a given 'Fold' operation.+dijkstra+  :: forall vertex cost label a. (Eq vertex, Hashable vertex, Real cost)+  => Fold vertex cost label a+     -- ^ Operation used to fold shotest paths+  -> Graph vertex cost label+  -> [vertex]+     -- ^ List of source vertexes+  -> HashMap vertex (cost, a)+dijkstra (Fold fV fE fC (fD :: x -> a)) g ss =+  fmap (\(Pair c x) -> (c, fD x)) $+    loop (Heap.fromList [Heap.Entry 0 (Pair s (fV s)) | s <- ss]) HashMap.empty+  where+    loop+      :: Heap.Heap (Heap.Entry cost (Pair vertex x))+      -> HashMap vertex (Pair cost x)+      -> HashMap vertex (Pair cost x)+    loop q visited =+      case Heap.viewMin q of+        Nothing -> visited+        Just (Heap.Entry c (Pair v a), q')+          | v `HashMap.member` visited -> loop q' visited+          | otherwise ->+              let q2 = Heap.fromList+                       [ Heap.Entry (c+c') (Pair ch (a `fC` fE (v,ch,c',l)))+                       | (ch,c',l) <- HashMap.lookupDefault [] v g+                       , not (ch `HashMap.member` visited)+                       ]+              in loop (Heap.union q' q2) (HashMap.insert v (Pair c a) visited)++-- ------------------------------------------------------------------------++-- | Floyd-Warshall algorithm for finding shortest paths in a weighted graph+-- with positive or negative edge weights (but with no negative cycles).+--+-- It compute shortest-paths between each pair of vertexes, and folds edge+-- information along shortest paths using a given 'Fold' operation.+floydWarshall+  :: forall vertex cost label a. (Eq vertex, Hashable vertex, Real cost)+  => Fold vertex cost label a+     -- ^ Operation used to fold shotest paths+  -> Graph vertex cost label+  -> HashMap vertex (HashMap vertex (cost, a))+floydWarshall (Fold fV fE fC (fD :: x -> a)) g =+  fmap (fmap (\(Pair c x) -> (c, fD x))) $+    HashMap.unionWith (HashMap.unionWith minP) (foldl' f tbl0 vs) paths0+  where+    vs = HashMap.keys g++    paths0 :: HashMap vertex (HashMap vertex (Pair cost x))+    paths0 = HashMap.mapWithKey (\v _ -> HashMap.singleton v (Pair 0 (fV v))) g++    tbl0 :: HashMap vertex (HashMap vertex (Pair cost x))+    tbl0 = HashMap.mapWithKey (\v es -> HashMap.fromListWith minP [(u, (Pair c (fE (v,u,c,l)))) | (u,c,l) <- es]) g++    minP :: Pair cost x -> Pair cost x -> Pair cost x+    minP = minBy (comparing (\(Pair c _) -> c))++    f :: HashMap vertex (HashMap vertex (Pair cost x))+      -> vertex+      -> HashMap vertex (HashMap vertex (Pair cost x))+    f tbl vk =+      case HashMap.lookup vk tbl of+        Nothing -> tbl+        Just hk -> HashMap.map h tbl+          where+            h :: HashMap vertex (Pair cost x) -> HashMap vertex (Pair cost x)+            h m =+              case HashMap.lookup vk m of+                Nothing -> m+                Just (Pair c1 x1) -> HashMap.unionWith minP m (HashMap.map (\(Pair c2 x2) -> (Pair (c1+c2) (fC x1 x2))) hk)++minBy :: (a -> a -> Ordering) -> a -> a -> a+minBy f a b =+  case f a b of+    LT -> a+    EQ -> a+    GT -> b++-- ------------------------------------------------------------------------
src/ToySolver/Internal/Data/IndexedPriorityQueue.hs view
@@ -40,6 +40,7 @@   , QueueSize (..)   , member   , update+  , rebuild   , getHeapArray   , getHeapVec @@ -48,6 +49,7 @@   , resizeTableCapacity   ) where +import Control.Loop import Control.Monad import qualified Data.Array.IO as A import Data.Queue.Classes@@ -231,6 +233,12 @@   j <- loop i   Vec.unsafeWrite (heap q) j val   Vec.unsafeWrite (table q) val j++rebuild :: PriorityQueue -> IO ()+rebuild q = do+  n <- Vec.getSize (heap q)+  forLoop 0 (<n) (+1) $ \i -> do+    up q i  -- | Get the internal representation of a given priority queue. getHeapArray :: PriorityQueue -> IO (A.IOUArray Index Value)
src/ToySolver/Internal/Data/PriorityQueue.hs view
@@ -31,6 +31,7 @@   , Enqueue (..)   , Dequeue (..)   , QueueSize (..)+  , rebuild   , getHeapArray   , getHeapVec @@ -38,6 +39,7 @@   , resizeHeapCapacity   ) where +import Control.Loop import qualified Data.Array.IO as A import Data.Queue.Classes import qualified ToySolver.Internal.Data.Vec as Vec@@ -157,6 +159,12 @@                loop child   j <- loop i   Vec.unsafeWrite (heap q) j val++rebuild :: PriorityQueue a -> IO ()+rebuild q = do+  n <- Vec.getSize (heap q)+  forLoop 0 (<n) (+1) $ \i -> do+    up q i  -- | Get the internal representation of a given priority queue. getHeapArray :: PriorityQueue a -> IO (A.IOArray Index a)
src/ToySolver/Internal/Data/SeqQueue.hs view
@@ -27,41 +27,49 @@   , clear   ) where -import Data.IORef+import Control.Monad.Primitive+import Control.Monad.ST import Data.Queue import Data.Foldable+import Data.Primitive.MutVar import qualified Data.Sequence as Seq -newtype SeqQueue a = SeqQueue (IORef (Seq.Seq a))+newtype SeqQueue m a = SeqQueue (MutVar (PrimState m) (Seq.Seq a)) -instance NewFifo (SeqQueue a) IO where+instance PrimMonad m => NewFifo (SeqQueue m a) m where+  {-# INLINE newFifo #-}   newFifo = do-    ref <- newIORef Seq.empty+    ref <- newMutVar Seq.empty     return (SeqQueue ref) -instance Enqueue (SeqQueue a) IO a where+instance PrimMonad m => Enqueue (SeqQueue m a) m a where+  {-# INLINE enqueue #-}   enqueue (SeqQueue ref) val = do-    modifyIORef ref (Seq.|> val)+    modifyMutVar ref (Seq.|> val) -instance Dequeue (SeqQueue a) IO a where+instance PrimMonad m => Dequeue (SeqQueue m a) m a where+  {-# INLINE dequeue #-}   dequeue (SeqQueue ref) = do-    s <- readIORef ref+    s <- readMutVar ref     case Seq.viewl s of       Seq.EmptyL -> return Nothing       val Seq.:< s' -> do-        writeIORef ref s'+        writeMutVar ref s'         return (Just val) +  {-# INLINE dequeueBatch #-}   dequeueBatch (SeqQueue ref) = do-    s <- readIORef ref-    writeIORef ref Seq.empty+    s <- readMutVar ref+    writeMutVar ref Seq.empty     return (toList s) -instance QueueSize (SeqQueue a) IO where+instance PrimMonad m => QueueSize (SeqQueue m a) m where+  {-# INLINE queueSize #-}   queueSize (SeqQueue ref) = do-    s <- readIORef ref+    s <- readMutVar ref     return $! Seq.length s -clear :: SeqQueue a -> IO ()+{-# INLINE clear #-}+clear :: PrimMonad m => SeqQueue m a -> m () clear (SeqQueue ref) = do-  writeIORef ref Seq.empty+  writeMutVar ref Seq.empty
src/ToySolver/Internal/Data/Vec.hs view
@@ -78,7 +78,7 @@  {- INLINE getSize #-} -- | Get the internal representation array-getSize :: A.MArray a e IO => GenericVec a e -> IO Int+getSize :: GenericVec a e -> IO Int getSize (GenericVec sizeRef _) = readIOURef sizeRef  {-# SPECIALIZE read :: Vec e -> Int -> IO e #-}@@ -283,7 +283,8 @@   arr <- readIORef arrayRef   capa0 <- liftM rangeSize $ A.getBounds arr   when (capa0 < capa) $ do-    arr' <- A.newArray_ (0, capa-1)+    let capa' = max capa (n * 3 `div` 2)+    arr' <- A.newArray_ (0, capa'-1)     copyTo arr arr' (0, n-1)     writeIORef arrayRef arr' 
src/ToySolver/Internal/Util.hs view
@@ -19,6 +19,8 @@ import Data.Ratio import Data.Set (Set) import qualified Data.Set as Set+import System.IO+import GHC.IO.Encoding  -- | Combining two @Maybe@ values using given function. combineMaybe :: (a -> a -> a) -> Maybe a -> Maybe a -> Maybe a@@ -85,3 +87,9 @@ {-# INLINE revForM #-} revForM :: Monad m => [a] -> (a -> m b) -> m [b] revForM = flip revMapM++setEncodingChar8 :: IO ()+setEncodingChar8 = do+  setLocaleEncoding char8+  setForeignEncoding char8+  setFileSystemEncoding char8
+ src/ToySolver/QBF.hs view
@@ -0,0 +1,404 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE BangPatterns #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.QBF+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable (BangPatterns)+--+-- Reference:+--+-- * Mikoláš Janota, William Klieber, Joao Marques-Silva, Edmund Clarke.+--   Solving QBF with Counterexample Guided Refinement.+--   In Theory and Applications of Satisfiability Testing (SAT 2012), pp. 114-128.+--   <http://dx.doi.org/10.1007/978-3-642-31612-8_10>+--   <https://www.cs.cmu.edu/~wklieber/papers/qbf-cegar-sat-2012.pdf>+--+-----------------------------------------------------------------------------+module ToySolver.QBF+  ( Quantifier (..)+  , Prefix+  , normalizePrefix+  , quantifyFreeVariables +  , Matrix+  , solve+  , solveNaive+  , solveCEGAR+  , solveCEGARIncremental+  ) where++import Control.Monad+import Control.Monad.State.Strict+import Control.Monad.Trans.Except+import qualified Data.IntMap as IntMap+import qualified Data.IntSet as IntSet+import Data.Function (on)+import Data.List (groupBy, foldl')+import Data.Maybe++import ToySolver.Data.Boolean+import ToySolver.Data.BoolExpr (BoolExpr)+import qualified ToySolver.Data.BoolExpr as BoolExpr+import qualified ToySolver.SAT as SAT+import ToySolver.SAT.Types (LitSet, VarSet, VarMap)+import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin++import ToySolver.Text.QDimacs (Quantifier (..))++-- ----------------------------------------------------------------------------++type Prefix = [(Quantifier, VarSet)]++normalizePrefix :: Prefix -> Prefix+normalizePrefix = groupQuantifiers . removeEmptyQuantifiers++removeEmptyQuantifiers :: Prefix -> Prefix+removeEmptyQuantifiers = filter (\(_,xs) -> not (IntSet.null xs))++groupQuantifiers :: Prefix -> Prefix+groupQuantifiers = map f . groupBy ((==) `on` fst)+  where+    f qs = (fst (head qs), IntSet.unions [xs | (_,xs) <- qs])++quantifyFreeVariables :: Int -> Prefix -> Prefix+quantifyFreeVariables nv prefix+  | IntSet.null rest = prefix+  | otherwise = (E, rest) : prefix+  where+    rest = IntSet.fromList [1..nv] `IntSet.difference` IntSet.unions [vs | (_q, vs) <- prefix]++prefixStartWithA :: Prefix -> Bool+prefixStartWithA ((A,_) : _) = True+prefixStartWithA _ = False++prefixStartWithE :: Prefix -> Bool+prefixStartWithE ((E,_) : _) = True+prefixStartWithE _ = False++-- ----------------------------------------------------------------------------++type Matrix = BoolExpr SAT.Lit++reduct :: Matrix -> LitSet -> Matrix+reduct m ls = BoolExpr.simplify $ m >>= s+  where+    s l+      |   l  `IntSet.member` ls = true+      | (-l) `IntSet.member` ls = false+      | otherwise = BoolExpr.Atom l++substVarMap :: Matrix -> VarMap Matrix -> Matrix+substVarMap m s = BoolExpr.simplify $ m >>= \l -> do+  let v = abs l+  (if l > 0 then id else notB) $ IntMap.findWithDefault (BoolExpr.Atom v) v s++-- XXX+prenexAnd :: (Int, Prefix, Matrix) -> (Int, Prefix, Matrix) -> (Int, Prefix, Matrix)+prenexAnd (nv1, prefix1, matrix1) (nv2, prefix2, matrix2) =+  evalState (f [] IntSet.empty IntMap.empty IntMap.empty prefix1 prefix2) (nv1 `max` nv2)+  where+    f :: Prefix -> VarSet+      -> VarMap (BoolExpr SAT.Lit) -> VarMap (BoolExpr SAT.Lit)+      -> Prefix -> Prefix+      -> State Int (Int, Prefix, Matrix)+    f prefix _bvs subst1 subst2 [] [] = do+      nv <- get+      return (nv, prefix, BoolExpr.simplify (substVarMap matrix1 subst1 .&&. substVarMap matrix2 subst2))+    f prefix bvs subst1 subst2 ((A,xs1) : prefix1') ((A,xs2) : prefix2') = do+      let xs = IntSet.union xs1 xs2+          ys = IntSet.intersection bvs xs+      nv <- get+      put (nv + IntSet.size ys)+      let s  = IntMap.fromList $ zip (IntSet.toList ys) [(nv+1) ..]+          xs' = (xs `IntSet.difference` bvs) `IntSet.union` IntSet.fromList (IntMap.elems s)+          subst1' = fmap BoolExpr.Atom (IntMap.filterWithKey (\x _ -> x `IntSet.member` xs1) s) `IntMap.union` subst1+          subst2' = fmap BoolExpr.Atom (IntMap.filterWithKey (\x _ -> x `IntSet.member` xs2) s) `IntMap.union` subst2+      f (prefix ++ [(A, xs')]) (bvs `IntSet.union` xs') subst1' subst2' prefix1' prefix2'+    f prefix bvs subst1 subst2 ((q,xs) : prefix1') prefix2 | q==E || not (prefixStartWithE prefix2) = do+      let ys = IntSet.intersection bvs xs+      nv <- get+      put (nv + IntSet.size ys)+      let s  = IntMap.fromList $ zip (IntSet.toList ys) [(nv+1) ..]+          xs' = (xs `IntSet.difference` bvs) `IntSet.union` IntSet.fromList (IntMap.elems s)+          subst1' = fmap BoolExpr.Atom s `IntMap.union` subst1+      f (prefix ++ [(q, xs')]) (bvs `IntSet.union` xs') subst1' subst2 prefix1' prefix2+    f prefix bvs subst1 subst2 prefix1 ((q,xs) : prefix2')  = do+      let ys = IntSet.intersection bvs xs+      nv <- get+      put (nv + IntSet.size ys)+      let s  = IntMap.fromList $ zip (IntSet.toList ys) [(nv+1) ..]+          xs' = (xs `IntSet.difference` bvs) `IntSet.union` IntSet.fromList (IntMap.elems s)+          subst2' = fmap BoolExpr.Atom s `IntMap.union` subst2+      f (prefix ++ [(q, xs')]) (bvs `IntSet.union` xs') subst1 subst2' prefix1 prefix2'++-- XXX     +prenexOr :: (Int, Prefix, Matrix) -> (Int, Prefix, Matrix) -> (Int, Prefix, Matrix)+prenexOr (nv1, prefix1, matrix1) (nv2, prefix2, matrix2) =+  evalState (f [] IntSet.empty IntMap.empty IntMap.empty prefix1 prefix2) (nv1 `max` nv2)+  where+    f :: Prefix -> VarSet+      -> VarMap (BoolExpr SAT.Lit) -> VarMap (BoolExpr SAT.Lit)+      -> Prefix -> Prefix+      -> State Int (Int, Prefix, Matrix)+    f prefix _bvs subst1 subst2 [] [] = do+      nv <- get+      return (nv, prefix, BoolExpr.simplify (substVarMap matrix1 subst1 .||. substVarMap matrix2 subst2))+    f prefix bvs subst1 subst2 ((E,xs1) : prefix1') ((E,xs2) : prefix2') = do+      let xs = IntSet.union xs1 xs2+          ys = IntSet.intersection bvs xs+      nv <- get+      put (nv + IntSet.size ys)+      let s  = IntMap.fromList $ zip (IntSet.toList ys) [(nv+1) ..]+          xs' = (xs `IntSet.difference` bvs) `IntSet.union` IntSet.fromList (IntMap.elems s)+          subst1' = fmap BoolExpr.Atom (IntMap.filterWithKey (\x _ -> x `IntSet.member` xs1) s) `IntMap.union` subst1+          subst2' = fmap BoolExpr.Atom (IntMap.filterWithKey (\x _ -> x `IntSet.member` xs2) s) `IntMap.union` subst2+      f (prefix ++ [(A, xs')]) (bvs `IntSet.union` xs') subst1' subst2' prefix1' prefix2'+    f prefix bvs subst1 subst2 ((q,xs) : prefix1') prefix2 | q==A || not (prefixStartWithA prefix2)= do+      let ys = IntSet.intersection bvs xs+      nv <- get+      put (nv + IntSet.size ys)+      let s  = IntMap.fromList $ zip (IntSet.toList ys) [(nv+1) ..]+          xs' = (xs `IntSet.difference` bvs) `IntSet.union` IntSet.fromList (IntMap.elems s)+          subst1' = fmap BoolExpr.Atom s `IntMap.union` subst1+      f (prefix ++ [(q, xs')]) (bvs `IntSet.union` xs') subst1' subst2 prefix1' prefix2+    f prefix bvs subst1 subst2 prefix1 ((q,xs) : prefix2')  = do+      let ys = IntSet.intersection bvs xs+      nv <- get+      put (nv + IntSet.size ys)+      let s  = IntMap.fromList $ zip (IntSet.toList ys) [(nv+1) ..]+          xs' = (xs `IntSet.difference` bvs) `IntSet.union` IntSet.fromList (IntMap.elems s)+          subst2' = fmap BoolExpr.Atom s `IntMap.union` subst2+      f (prefix ++ [(q, xs')]) (bvs `IntSet.union` xs') subst1 subst2' prefix1 prefix2'++-- ----------------------------------------------------------------------------++solve :: Int -> Prefix -> Matrix -> IO (Bool, Maybe LitSet)+solve = solveCEGARIncremental++-- ----------------------------------------------------------------------------++-- | Naive Algorithm for a Winning Move+solveNaive :: Int -> Prefix -> Matrix -> IO (Bool, Maybe LitSet)+solveNaive nv prefix matrix =+  case prefix' of+    [] -> if BoolExpr.fold undefined matrix+          then return (True, Just IntSet.empty)+          else return (False, Nothing)+    (E,_) : _ -> do+      m <- f prefix' matrix+      return (isJust m, m)+    (A,_) : _ -> do+      m <- f prefix' matrix+      return (isNothing m, m)+  where+    prefix' = normalizePrefix prefix++    {- Naive Algorithm for a Winning Move+    Function Solve (QX. Φ)+    begin+      if Φ has no quant then+        return (Q = ∃) ? SAT(φ) : SAT(¬φ)+      Λ ← {true, false}^X  // consider all assignments+      while true do+        if Λ = ∅ then      // all assignments used up+          return NULL+        τ ← pick(Λ)        // pick a candidate solution+        μ ← Solve(Φ[τ])    // find a countermove+        if μ = NULL then   // winning move+          return τ+        Λ ← Λ \ {τ}        // remove bad candidate+      end+    end+    -}+    f :: Prefix -> Matrix -> IO (Maybe LitSet)+    f [] _matrix = error "should not happen"+    f [(q,xs)] matrix = do+      solver <- SAT.newSolver+      SAT.newVars_ solver nv+      enc <- Tseitin.newEncoder solver+      case q of+        E -> Tseitin.addFormula enc matrix+        A -> Tseitin.addFormula enc (notB matrix)+      ret <- SAT.solve solver+      if ret then do+        m <- SAT.getModel solver+        return $ Just $ IntSet.fromList [if SAT.evalLit m x then x else -x | x <- IntSet.toList xs]+      else+        return Nothing+    f ((_q,xs) : prefix') matrix = do+      ret <- runExceptT $ do+        let moves :: [LitSet]+            moves = map IntSet.fromList $ sequence [[x, -x] | x <- IntSet.toList xs]+        forM_ moves $ \tau -> do+          ret <- lift $ f prefix' (reduct matrix tau)+          case ret of+            Nothing  -> throwE tau+            Just _nu -> return ()+      case ret of+        Left tau -> return (Just tau)+        Right () -> return Nothing++-- ----------------------------------------------------------------------------++-- | Abstraction-Based Algorithm for a Winning Move                    +solveCEGAR :: Int -> Prefix -> Matrix -> IO (Bool, Maybe LitSet)+solveCEGAR nv prefix matrix =+  case prefix' of+    [] -> if BoolExpr.fold undefined matrix+          then return (True, Just IntSet.empty)+          else return (False, Nothing)+    (E,_) : _ -> do+      m <- f nv prefix' matrix+      return (isJust m, m)+    (A,_) : _ -> do+      m <- f nv prefix' matrix+      return (isNothing m, m)+  where+    prefix' = normalizePrefix prefix++    {-+    Function Solve (QX. Φ)+    begin+      if Φ has no quant then+        return (Q = ∃) ? SAT(φ) : SAT(¬φ)+      ω ← ∅+      while true do+        α ← (Q = ∃) ? ∧_{μ∈ω} Φ[μ] : ∨_{μ∈ω} Φ[μ] // abstraction+        τ' ← Solve(Prenex(QX.α)) // find a candidate+        if τ' = NULL then return NULL // no winning move+        τ ← {l | l ∈ τ′ ∧ var(l) ∈ X} // filter a move for X+        μ ← Solve(Φ[τ])+        if μ = NULL then return τ+        ω ← ω∪{μ}+      end+    end+    -}+    f :: Int -> Prefix -> Matrix -> IO (Maybe LitSet)+    f _nv [] _matrix = error "should not happen"+    f nv [(q,xs)] matrix = do+      solver <- SAT.newSolver+      SAT.newVars_ solver nv+      enc <- Tseitin.newEncoder solver+      case q of+        E -> Tseitin.addFormula enc matrix+        A -> Tseitin.addFormula enc (notB matrix)+      ret <- SAT.solve solver+      if ret then do+        m <- SAT.getModel solver+        return $ Just $ IntSet.fromList [if SAT.evalLit m x then x else -x | x <- IntSet.toList xs]+      else+        return Nothing+    f nv ((q,xs) : prefix'@((_q2,_) : prefix'')) matrix = do+      let loop counterMoves = do+            let ys = [(nv, prefix'', reduct matrix nu) | nu <- counterMoves]+                (nv2, prefix2, matrix2) =+                  if q==E+                  then foldl' prenexAnd (nv,[],true) ys+                  else foldl' prenexOr (nv,[],false) ys+            ret <- f nv2 (normalizePrefix ((q,xs) : prefix2)) matrix2+            case ret of+              Nothing -> return Nothing+              Just tau' -> do+                let tau = IntSet.filter (\l -> abs l `IntSet.member` xs) tau'+                ret2 <- f nv prefix' (reduct matrix tau)+                case ret2 of+                  Nothing -> return (Just tau)+                  Just nu -> loop (nu : counterMoves)+      loop []++-- ----------------------------------------------------------------------------++-- | Abstraction-Based Algorithm for a Winning Move+solveCEGARIncremental :: Int -> Prefix -> Matrix -> IO (Bool, Maybe LitSet)+solveCEGARIncremental nv prefix matrix =+  case prefix' of+    [] -> if BoolExpr.fold undefined matrix+          then return (True, Just IntSet.empty)+          else return (False, Nothing)+    (E,_) : _ -> do+      m <- f nv IntSet.empty prefix' matrix+      return (isJust m, m)+    (A,_) : _ -> do+      m <- f nv IntSet.empty prefix' matrix+      return (isNothing m, m)+  where+    prefix' = normalizePrefix prefix++    {-+    Function Solve (QX. Φ)+    begin+      if Φ has no quant then+        return (Q = ∃) ? SAT(φ) : SAT(¬φ)+      ω ← ∅+      while true do+        α ← (Q = ∃) ? ∧_{μ∈ω} Φ[μ] : ∨_{μ∈ω} Φ[μ] // abstraction+        τ' ← Solve(Prenex(QX.α)) // find a candidate+        if τ' = NULL then return NULL // no winning move+        τ ← {l | l ∈ τ′ ∧ var(l) ∈ X} // filter a move for X+        μ ← Solve(Φ[τ])+        if μ = NULL then return τ+        ω ← ω∪{μ}+      end+    end+    -}+    f :: Int -> LitSet -> Prefix -> Matrix -> IO (Maybe LitSet)+    f nv assumptions prefix matrix = do+      solver <- SAT.newSolver+      SAT.newVars_ solver nv+      enc <- Tseitin.newEncoder solver+      xs <-+        case last prefix of+          (E, xs) -> do+            Tseitin.addFormula enc matrix+            return xs+          (A, xs) -> do+            Tseitin.addFormula enc (notB matrix)+            return xs+      let g :: Int -> LitSet -> Prefix -> Matrix -> IO (Maybe LitSet)+          g _nv _assumptions [] _matrix = error "should not happen"+          g nv assumptions [(q,xs)] matrix = do+            ret <- SAT.solveWith solver (IntSet.toList assumptions)+            if ret then do+              m <- SAT.getModel solver+              return $ Just $ IntSet.fromList [if SAT.evalLit m x then x else -x | x <- IntSet.toList xs]+            else+              return Nothing            +          g nv assumptions prefix@((q,xs) : prefix'@((_q2,_) : prefix'')) matrix = do+            let loop counterMoves = do+                  let ys = [(nv, prefix'', reduct matrix nu) | nu <- counterMoves]+                      (nv2, prefix2, matrix2) =+                        if q==E+                        then foldl' prenexAnd (nv,[],true) ys+                        else foldl' prenexOr (nv,[],false) ys+                  ret <- f nv2 assumptions (normalizePrefix ((q,xs) : prefix2)) matrix2+                  case ret of+                    Nothing -> return Nothing+                    Just tau' -> do+                      let tau = IntSet.filter (\l -> abs l `IntSet.member` xs) tau'+                      ret2 <- g nv (assumptions `IntSet.union` tau) prefix' (reduct matrix tau)+                      case ret2 of+                        Nothing -> return (Just tau)+                        Just nu -> loop (nu : counterMoves)+            loop []+      g nv IntSet.empty prefix matrix++-- ----------------------------------------------------------------------------++-- ∀y ∃x. x ∧ (y ∨ ¬x)+test = solveNaive 2 [(A, IntSet.singleton 2), (E, IntSet.singleton 1)] (x .&&. (y .||. notB x))+  where+    x  = BoolExpr.Atom 1+    y  = BoolExpr.Atom 2++test' = solveCEGAR 2 [(A, IntSet.singleton 2), (E, IntSet.singleton 1)] (x .&&. (y .||. notB x))+  where+    x  = BoolExpr.Atom 1+    y  = BoolExpr.Atom 2++test1 = prenexAnd (1, [(A, IntSet.singleton 1)], BoolExpr.Atom 1) (1, [(A, IntSet.singleton 1)], notB (BoolExpr.Atom 1))++test2 = prenexOr (1, [(A, IntSet.singleton 1)], BoolExpr.Atom 1) (1, [(A, IntSet.singleton 1)], BoolExpr.Atom 1)
src/ToySolver/SAT.hs view
@@ -1,5 +1,5 @@ {-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}-{-# LANGUAGE BangPatterns, ScopedTypeVariables, CPP, DeriveDataTypeable, RecursiveDo #-}+{-# LANGUAGE BangPatterns, ScopedTypeVariables, CPP, DeriveDataTypeable, RecursiveDo, MultiParamTypeClasses, InstanceSigs #-} #ifdef __GLASGOW_HASKELL__ {-# LANGUAGE UnboxedTuples, MagicHash #-} #endif@@ -46,25 +46,18 @@   , newVars_   , resizeVarCapacity   -- ** Clauses-  , addClause+  , AddClause (..)   , Clause   , evalClause   -- ** Cardinality constraints-  , addAtLeast-  , addAtMost-  , addExactly+  , AddCardinality (..)   , AtLeast   , Exactly   , evalAtLeast   , evalExactly    -- ** (Linear) pseudo-boolean constraints-  , addPBAtLeast-  , addPBAtMost-  , addPBExactly-  , addPBAtLeastSoft-  , addPBAtMostSoft-  , addPBExactlySoft+  , AddPBLin (..)   , PBLinTerm   , PBLinSum   , PBLinAtLeast@@ -73,17 +66,18 @@   , evalPBLinAtLeast   , evalPBLinExactly   -- ** XOR clauses-  , addXORClause-  , addXORClauseSoft+  , AddXORClause (..)   , XORClause   , evalXORClause-  -- ** Thery+  -- ** Theory   , setTheory    -- * Solving   , solve   , solveWith   , BudgetExceeded (..)+  , cancel+  , Canceled (..)    -- * Extract results   , IModel (..)@@ -93,48 +87,35 @@   , getAssumptionsImplications    -- * Solver configulation-  , Config (..)+  , module ToySolver.SAT.Config   , getConfig   , setConfig   , modifyConfig-  , RestartStrategy (..)-  , LearningStrategy (..)   , setVarPolarity   , setLogger   , setRandomGen   , getRandomGen   , setConfBudget-  , PBHandlerType (..)    -- ** Deprecated   , setRestartStrategy   , setRestartFirst-  , defaultRestartFirst   , setRestartInc-  , defaultRestartInc   , setLearntSizeFirst-  , defaultLearntSizeFirst   , setLearntSizeInc-  , defaultLearntSizeInc   , setCCMin-  , defaultCCMin   , setLearningStrategy   , setEnablePhaseSaving   , getEnablePhaseSaving-  , defaultEnablePhaseSaving   , setEnableForwardSubsumptionRemoval   , getEnableForwardSubsumptionRemoval-  , defaultEnableForwardSubsumptionRemoval   , setEnableBackwardSubsumptionRemoval   , getEnableBackwardSubsumptionRemoval-  , defaultEnableBackwardSubsumptionRemoval   , setCheckModel   , setRandomFreq-  , defaultRandomFreq   , setPBHandlerType   , setPBSplitClausePart   , getPBSplitClausePart-  , defaultPBSplitClausePart    -- * Read state   , getNVars@@ -159,6 +140,9 @@ import Control.Applicative hiding (empty) import Control.Loop import Control.Monad+import Control.Monad.IO.Class+import Control.Monad.Trans+import Control.Monad.Trans.Except import Control.Exception #if MIN_VERSION_array(0,5,0) import Data.Array.IO@@ -171,6 +155,7 @@ import Data.Bits (xor) -- for defining 'combine' function #endif import Data.Default.Class+import Data.Either import Data.Function (on) import Data.Hashable import Data.HashSet (HashSet)@@ -185,9 +170,8 @@ import ToySolver.Internal.Data.IOURef import qualified ToySolver.Internal.Data.IndexedPriorityQueue as PQ import qualified ToySolver.Internal.Data.Vec as Vec-import Data.Time import Data.Typeable-import System.CPUTime+import System.Clock import qualified System.Random.MWC as Rand import Text.Printf @@ -197,6 +181,7 @@ #endif  import ToySolver.Data.LBool+import ToySolver.SAT.Config import ToySolver.SAT.Types import ToySolver.SAT.TheorySolver import ToySolver.Internal.Util (revMapM)@@ -223,6 +208,14 @@   , vdLevel :: !(IOURef Level)   , vdReason :: !(IORef (Maybe SomeConstraintHandler))   , vdOnUnassigned :: !(IORef [SomeConstraintHandler])+  -- | exponential moving average estimate+  , vdEMAScaled :: !(IOURef Double)+  -- | When v was last assigned+  , vdWhenAssigned :: !(IOURef Int)+  -- | The number of learnt clauses v participated in generating since Assigned.+  , vdParticipated :: !(IOURef Int)+  -- | The number of learnt clauses v reasoned in generating since Assigned.+  , vdReasoned :: !(IOURef Int)   }  data LitData@@ -246,6 +239,11 @@   reason <- newIORef Nothing   onUnassigned <- newIORef [] +  ema <- newIOURef 0+  whenAssigned <- newIOURef (-1)+  participated <- newIOURef 0+  reasoned <- newIOURef 0+   return $     VarData     { vdPolarity = polarity@@ -258,6 +256,10 @@     , vdLevel = lv     , vdReason = reason     , vdOnUnassigned = onUnassigned+    , vdEMAScaled = ema+    , vdWhenAssigned = whenAssigned+    , vdParticipated = participated+    , vdReasoned = reasoned     }  newLitData :: IO LitData@@ -306,7 +308,7 @@   else     return lUndef -getLitFixed :: Solver -> Var -> IO LBool+getLitFixed :: Solver -> Lit -> IO LBool getLitFixed solver !l = do   -- litVar による heap allocation を避けるために、   -- litPolarityによる分岐後にvarDataを呼ぶ。@@ -392,10 +394,11 @@    -- Logging   , svLogger :: !(IORef (Maybe (String -> IO ())))-  , svStartWC    :: !(IORef UTCTime)-  , svLastStatWC :: !(IORef UTCTime)+  , svStartWC    :: !(IORef TimeSpec)+  , svLastStatWC :: !(IORef TimeSpec)    -- Working spaces+  , svCanceled        :: !(IORef Bool)   , svAssumptions     :: !(Vec.UVec Lit)   , svLearntLim       :: !(IORef Int)   , svLearntLimAdjCnt :: !(IORef Int)@@ -406,6 +409,13 @@    -- | Amount to bump next constraint with.   , svConstrInc    :: !(IOURef Double)++  -- ERWA / LRB++  -- | step-size parameter α+  , svERWAStepSize :: !(IOURef Double)+  , svEMAScale :: !(IOURef Double)+  , svLearntCounter :: !(IOURef Int)   }  markBad :: Solver -> IO ()@@ -469,6 +479,9 @@     writeIOURef (vdTrailIndex vd) idx     writeIOURef (vdLevel vd) lv     writeIORef (vdReason vd) reason+    writeIOURef (vdWhenAssigned vd) =<< readIOURef (svLearntCounter solver)+    writeIOURef (vdParticipated vd) 0+    writeIOURef (vdReasoned vd) 0      Vec.push (svTrail solver) lit @@ -494,6 +507,24 @@   writeIOURef (vdLevel vd) maxBound   writeIORef (vdReason vd) Nothing +  -- ERWA / LRB computation+  interval <- do+    t2 <- readIOURef (svLearntCounter solver)+    t1 <- readIOURef (vdWhenAssigned vd)+    return (t2 - t1)+  -- Interval = 0 is possible due to restarts.+  when (interval > 0) $ do+    participated <- readIOURef (vdParticipated vd)+    reasoned <- readIOURef (vdReasoned vd)+    alpha <- readIOURef (svERWAStepSize solver)+    let learningRate = fromIntegral participated / fromIntegral interval+        reasonSideRate = fromIntegral reasoned / fromIntegral interval+    scale <- readIOURef (svEMAScale solver)+    -- ema := (1 - α)ema + α*r+    modifyIOURef (vdEMAScaled vd) $ \orig -> (1 - alpha) * orig + alpha * scale * (learningRate + reasonSideRate)+    -- If v is assigned by random decision, it's possible that v is still in the queue.+    PQ.update (svVarQueue solver) v+   let !l = if val == lTrue then v else -v   cs <- readIORef (vdOnUnassigned vd)   writeIORef (vdOnUnassigned vd) []@@ -602,7 +633,9 @@   inc <- readIOURef (svVarInc solver)   vd <- varData solver v   modifyIOURef (vdActivity vd) (+inc)-  PQ.update (svVarQueue solver) v+  conf <- getConfig solver+  when (configBranchingStrategy conf == BranchingVSIDS) $ do+    PQ.update (svVarQueue solver) v   aval <- readIOURef (vdActivity vd)   when (aval > 1e20) $     -- Rescale@@ -616,6 +649,42 @@     modifyIOURef (vdActivity vd) (* 1e-20)   modifyIOURef (svVarInc solver) (* 1e-20) +varEMAScaled :: Solver -> Var -> IO Double+varEMAScaled solver v = do+  vd <- varData solver v+  readIOURef (vdEMAScaled vd)++varIncrementParticipated :: Solver -> Var -> IO ()+varIncrementParticipated solver v = do+  vd <- varData solver v+  modifyIOURef (vdParticipated vd) (+1)++varIncrementReasoned :: Solver -> Var -> IO ()+varIncrementReasoned solver v = do+  vd <- varData solver v+  modifyIOURef (vdReasoned vd) (+1)++varEMADecay :: Solver -> IO ()+varEMADecay solver = do+  config <- getConfig solver++  alpha <- readIOURef (svERWAStepSize solver)+  let alphaMin = configERWAStepSizeMin config+  when (alpha > alphaMin) $ do+    writeIOURef (svERWAStepSize solver) (max alphaMin (alpha - configERWAStepSizeDec config))++  case configBranchingStrategy config of+    BranchingLRB -> do+      modifyIOURef (svEMAScale solver) (configEMADecay config *)+      scale <- readIOURef (svEMAScale solver)+      when (scale > 1e20) $ do+        vs <- variables solver+        forM_ vs $ \v -> do+          vd <- varData solver v+          modifyIOURef (vdEMAScaled vd) (/ scale)+        writeIOURef (svEMAScale solver) 1.0+    _ -> return ()+ variables :: Solver -> IO [Var] variables solver = do   n <- getNVars solver@@ -688,6 +757,7 @@   db2 <- newIORef (0,[])   as  <- Vec.new   m   <- newIORef Nothing+  canceled <- newIORef False   ndecision <- newIOURef 0   nranddec  <- newIOURef 0   nconflict <- newIOURef 0@@ -718,6 +788,10 @@   tsolver <- newIORef Nothing   tchecked <- newIOURef 0 +  alpha <- newIOURef 0.4+  emaScale <- newIOURef 1.0+  learntCounter <- newIOURef 0+   let solver =         Solver         { svOk = ok@@ -757,48 +831,58 @@         , svLastStatWC = lastStatWC          -- Working space+        , svCanceled        = canceled         , svAssumptions     = as         , svLearntLim       = learntLim         , svLearntLimAdjCnt = learntLimAdjCnt         , svLearntLimSeq    = learntLimSeq         , svVarInc      = varInc         , svConstrInc   = constrInc++        , svERWAStepSize = alpha+        , svEMAScale = emaScale+        , svLearntCounter = learntCounter         }  return solver  ltVar :: Solver -> Var -> Var -> IO Bool-ltVar solver v1 v2 = do-  a1 <- varActivity solver v1-  a2 <- varActivity solver v2-  return $! a1 > a2+ltVar solver !v1 !v2 = do+  conf <- getConfig solver+  case configBranchingStrategy conf of+    BranchingVSIDS -> do+      a1 <- varActivity solver v1+      a2 <- varActivity solver v2+      return $! a1 > a2+    _ -> do -- BranchingERWA and BranchingLRB+      a1 <- varEMAScaled solver v1+      a2 <- varEMAScaled solver v1+      return $! a1 > a2  {--------------------------------------------------------------------   Problem specification --------------------------------------------------------------------} --- |Add a new variable-newVar :: Solver -> IO Var-newVar solver = do-  n <- Vec.getSize (svVarData solver)-  let v = n + 1-  vd <- newVarData-  Vec.push (svVarData solver) vd-  PQ.enqueue (svVarQueue solver) v-  return v+instance NewVar IO Solver where+  newVar :: Solver -> IO Var+  newVar solver = do+    n <- Vec.getSize (svVarData solver)+    let v = n + 1+    vd <- newVarData+    Vec.push (svVarData solver) vd+    PQ.enqueue (svVarQueue solver) v+    return v --- |Add variables. @newVars solver n = replicateM n (newVar solver)@-newVars :: Solver -> Int -> IO [Var]-newVars solver n = do-  nv <- getNVars solver-  resizeVarCapacity solver (nv+n)-  replicateM n (newVar solver)+  newVars :: Solver -> Int -> IO [Var]+  newVars solver n = do+    nv <- getNVars solver+    resizeVarCapacity solver (nv+n)+    replicateM n (newVar solver) --- |Add variables. @newVars_ solver n = newVars solver n >> return ()@-newVars_ :: Solver -> Int -> IO ()-newVars_ solver n = do-  nv <- getNVars solver-  resizeVarCapacity solver (nv+n)-  replicateM_ n (newVar solver)+  newVars_ :: Solver -> Int -> IO ()+  newVars_ solver n = do+    nv <- getNVars solver+    resizeVarCapacity solver (nv+n)+    replicateM_ n (newVar solver)  -- |Pre-allocate internal buffer for @n@ variables. resizeVarCapacity :: Solver -> Int -> IO ()@@ -807,126 +891,120 @@   PQ.resizeHeapCapacity (svVarQueue solver) n   PQ.resizeTableCapacity (svVarQueue solver) (n+1) --- |Add a clause to the solver.-addClause :: Solver -> Clause -> IO ()-addClause solver lits = do-  d <- getDecisionLevel solver-  assert (d == levelRoot) $ return ()+instance AddClause IO Solver where+  addClause :: Solver -> Clause -> IO ()+  addClause solver lits = do+    d <- getDecisionLevel solver+    assert (d == levelRoot) $ return () -  ok <- readIORef (svOk solver)-  when ok $ do-    m <- instantiateClause (getLitFixed solver) lits-    case normalizeClause =<< m of-      Nothing -> return ()-      Just [] -> markBad solver-      Just [lit] -> do+    ok <- readIORef (svOk solver)+    when ok $ do+      m <- instantiateClause (getLitFixed solver) lits+      case normalizeClause =<< m of+        Nothing -> return ()+        Just [] -> markBad solver+        Just [lit] -> do+          {- We do not call 'removeBackwardSubsumedBy' here,+             because subsumed constraints will be removed by 'simplify'. -}+          ret <- assign solver lit+          assert ret $ return ()+          ret2 <- deduce solver+          case ret2 of+            Nothing -> return ()+            Just _ -> markBad solver+        Just lits2 -> do+          subsumed <- checkForwardSubsumption solver lits+          unless subsumed $ do+            removeBackwardSubsumedBy solver ([(1,lit) | lit <- lits2], 1)+            clause <- newClauseHandler lits2 False+            addToDB solver clause+            _ <- basicAttachClauseHandler solver clause+            return ()++instance AddCardinality IO Solver where+  addAtLeast :: Solver -> [Lit] -> Int -> IO ()+  addAtLeast solver lits n = do+    d <- getDecisionLevel solver+    assert (d == levelRoot) $ return ()++    ok <- readIORef (svOk solver)+    when ok $ do+      (lits',n') <- liftM normalizeAtLeast $ instantiateAtLeast (getLitFixed solver) (lits,n)+      let len = length lits'++      if n' <= 0 then return ()+      else if n' > len then markBad solver+      else if n' == 1 then addClause solver lits'+      else if n' == len then do         {- We do not call 'removeBackwardSubsumedBy' here,            because subsumed constraints will be removed by 'simplify'. -}-        ret <- assign solver lit-        assert ret $ return ()+        forM_ lits' $ \l -> do+          ret <- assign solver l+          assert ret $ return ()         ret2 <- deduce solver         case ret2 of           Nothing -> return ()           Just _ -> markBad solver-      Just lits2 -> do-        subsumed <- checkForwardSubsumption solver lits-        unless subsumed $ do-          removeBackwardSubsumedBy solver ([(1,lit) | lit <- lits2], 1)-          clause <- newClauseHandler lits2 False-          addToDB solver clause-          _ <- basicAttachClauseHandler solver clause-          return ()---- | Add a cardinality constraints /atleast({l1,l2,..},n)/.-addAtLeast :: Solver -- ^ The 'Solver' argument.-           -> [Lit]  -- ^ set of literals /{l1,l2,..}/ (duplicated elements are ignored)-           -> Int    -- ^ /n/.-           -> IO ()-addAtLeast solver lits n = do-  d <- getDecisionLevel solver-  assert (d == levelRoot) $ return ()+      else do -- n' < len+        removeBackwardSubsumedBy solver ([(1,lit) | lit <- lits'], fromIntegral n')+        c <- newAtLeastHandler lits' n' False+        addToDB solver c+        _ <- basicAttachAtLeastHandler solver c+        return () -  ok <- readIORef (svOk solver)-  when ok $ do-    (lits',n') <- liftM normalizeAtLeast $ instantiateAtLeast (getLitFixed solver) (lits,n)-    let len = length lits'+instance AddPBLin IO Solver where+  addPBAtLeast :: Solver -> PBLinSum -> Integer -> IO ()+  addPBAtLeast solver ts n = do+    d <- getDecisionLevel solver+    assert (d == levelRoot) $ return () -    if n' <= 0 then return ()-    else if n' > len then markBad solver-    else if n' == 1 then addClause solver lits'-    else if n' == len then do-      {- We do not call 'removeBackwardSubsumedBy' here,-         because subsumed constraints will be removed by 'simplify'. -}-      forM_ lits' $ \l -> do-        ret <- assign solver l-        assert ret $ return ()-      ret2 <- deduce solver-      case ret2 of-        Nothing -> return ()-        Just _ -> markBad solver-    else do -- n' < len-      removeBackwardSubsumedBy solver ([(1,lit) | lit <- lits'], fromIntegral n')-      c <- newAtLeastHandler lits' n' False-      addToDB solver c-      _ <- basicAttachAtLeastHandler solver c-      return ()+    ok <- readIORef (svOk solver)+    when ok $ do+      (ts',n') <- liftM normalizePBLinAtLeast $ instantiatePBLinAtLeast (getLitFixed solver) (ts,n) --- | Add a cardinality constraints /atmost({l1,l2,..},n)/.-addAtMost :: Solver -- ^ The 'Solver' argument-          -> [Lit]  -- ^ set of literals /{l1,l2,..}/ (duplicated elements are ignored)-          -> Int    -- ^ /n/-          -> IO ()-addAtMost solver lits n =-  addAtLeast solver (map litNot lits) (length lits - n)+      case pbToAtLeast (ts',n') of+        Just (lhs',rhs') -> addAtLeast solver lhs' rhs'+        Nothing -> do+          let cs = map fst ts'+              slack = sum cs - n'+          if n' <= 0 then return ()+          else if slack < 0 then markBad solver+          else do+            removeBackwardSubsumedBy solver (ts', n')+            (ts'',n'') <- do+              b <- getPBSplitClausePart solver+              if b+              then pbSplitClausePart solver (ts',n')+              else return (ts',n') --- | Add a cardinality constraints /exactly({l1,l2,..},n)/.-addExactly :: Solver -- ^ The 'Solver' argument-           -> [Lit]  -- ^ set of literals /{l1,l2,..}/ (duplicated elements are ignored)-           -> Int    -- ^ /n/-           -> IO ()-addExactly solver lits n = do-  addAtLeast solver lits n-  addAtMost solver lits n+            c <- newPBHandler solver ts'' n'' False+            let constr = toConstraintHandler c+            addToDB solver constr+            ret <- attach solver constr+            if not ret then do+              markBad solver+            else do+              ret2 <- deduce solver+              case ret2 of+                Nothing -> return ()+                Just _ -> markBad solver --- | Add a pseudo boolean constraints /c1*l1 + c2*l2 + … ≥ n/.-addPBAtLeast :: Solver          -- ^ The 'Solver' argument.-             -> PBLinSum        -- ^ list of terms @[(c1,l1),(c2,l2),…]@-             -> Integer         -- ^ /n/-             -> IO ()-addPBAtLeast solver ts n = do-  d <- getDecisionLevel solver-  assert (d == levelRoot) $ return ()+  addPBExactly :: Solver -> PBLinSum -> Integer -> IO ()+  addPBExactly solver ts n = do+    (ts2,n2) <- liftM normalizePBLinExactly $ instantiatePBLinExactly (getLitFixed solver) (ts,n)+    addPBAtLeast solver ts2 n2+    addPBAtMost solver ts2 n2 -  ok <- readIORef (svOk solver)-  when ok $ do-    (ts',n') <- liftM normalizePBLinAtLeast $ instantiatePBLinAtLeast (getLitFixed solver) (ts,n)-  -    case pbToAtLeast (ts',n') of-      Just (lhs',rhs') -> addAtLeast solver lhs' rhs'-      Nothing -> do-        let cs = map fst ts'-            slack = sum cs - n'-        if n' <= 0 then return ()-        else if slack < 0 then markBad solver-        else do-          removeBackwardSubsumedBy solver (ts', n')          -          (ts'',n'') <- do-            b <- getPBSplitClausePart solver-            if b-            then pbSplitClausePart solver (ts',n')-            else return (ts',n')+  addPBAtLeastSoft :: Solver -> Lit -> PBLinSum -> Integer -> IO ()+  addPBAtLeastSoft solver sel lhs rhs = do+    (lhs', rhs') <- liftM normalizePBLinAtLeast $ instantiatePBLinAtLeast (getLitFixed solver) (lhs,rhs)+    addPBAtLeast solver ((rhs', litNot sel) : lhs') rhs' -          c <- newPBHandler solver ts'' n'' False-          let constr = toConstraintHandler c-          addToDB solver constr-          ret <- attach solver constr-          if not ret then do-            markBad solver-          else do-            ret2 <- deduce solver-            case ret2 of-              Nothing -> return ()-              Just _ -> markBad solver+  addPBExactlySoft :: Solver -> Lit -> PBLinSum -> Integer -> IO ()+  addPBExactlySoft solver sel lhs rhs = do+    (lhs2, rhs2) <- liftM normalizePBLinExactly $ instantiatePBLinExactly (getLitFixed solver) (lhs,rhs)+    addPBAtLeastSoft solver sel lhs2 rhs2+    addPBAtMostSoft solver sel lhs2 rhs2  -- | See documentation of 'setPBSplitClausePart'. pbSplitClausePart :: Solver -> PBLinAtLeast -> IO PBLinAtLeast@@ -939,90 +1017,24 @@     addClause solver $ -sel : [l | (_,l) <- ts1]     return ((rhs,sel) : ts2, rhs) --- | Add a pseudo boolean constraints /c1*l1 + c2*l2 + … ≤ n/.-addPBAtMost :: Solver          -- ^ The 'Solver' argument.-            -> PBLinSum        -- ^ list of @[(c1,l1),(c2,l2),…]@-            -> Integer         -- ^ /n/-            -> IO ()-addPBAtMost solver ts n = addPBAtLeast solver [(-c,l) | (c,l) <- ts] (negate n)---- | Add a pseudo boolean constraints /c1*l1 + c2*l2 + … = n/.-addPBExactly :: Solver          -- ^ The 'Solver' argument.-             -> PBLinSum        -- ^ list of terms @[(c1,l1),(c2,l2),…]@-             -> Integer         -- ^ /n/-             -> IO ()-addPBExactly solver ts n = do-  (ts2,n2) <- liftM normalizePBLinExactly $ instantiatePBLinExactly (getLitFixed solver) (ts,n)-  addPBAtLeast solver ts2 n2-  addPBAtMost solver ts2 n2---- | Add a soft pseudo boolean constraints /sel ⇒ c1*l1 + c2*l2 + … ≥ n/.-addPBAtLeastSoft-  :: Solver          -- ^ The 'Solver' argument.-  -> Lit             -- ^ Selector literal @sel@-  -> PBLinSum        -- ^ list of terms @[(c1,l1),(c2,l2),…]@-  -> Integer         -- ^ /n/-  -> IO ()-addPBAtLeastSoft solver sel lhs rhs = do-  (lhs', rhs') <- liftM normalizePBLinAtLeast $ instantiatePBLinAtLeast (getLitFixed solver) (lhs,rhs)-  addPBAtLeast solver ((rhs', litNot sel) : lhs') rhs'---- | Add a soft pseudo boolean constraints /sel ⇒ c1*l1 + c2*l2 + … ≤ n/.-addPBAtMostSoft-  :: Solver          -- ^ The 'Solver' argument.-  -> Lit             -- ^ Selector literal @sel@-  -> PBLinSum        -- ^ list of terms @[(c1,l1),(c2,l2),…]@-  -> Integer         -- ^ /n/-  -> IO ()-addPBAtMostSoft solver sel lhs rhs =-  addPBAtLeastSoft solver sel [(negate c, lit) | (c,lit) <- lhs] (negate rhs)---- | Add a soft pseudo boolean constraints /sel ⇒ c1*l1 + c2*l2 + … = n/.-addPBExactlySoft-  :: Solver          -- ^ The 'Solver' argument.-  -> Lit             -- ^ Selector literal @sel@-  -> PBLinSum        -- ^ list of terms @[(c1,l1),(c2,l2),…]@-  -> Integer         -- ^ /n/-  -> IO ()-addPBExactlySoft solver sel lhs rhs = do-  (lhs2, rhs2) <- liftM normalizePBLinExactly $ instantiatePBLinExactly (getLitFixed solver) (lhs,rhs)-  addPBAtLeastSoft solver sel lhs2 rhs2-  addPBAtMostSoft solver sel lhs2 rhs2---- | Add a parity constraint /l1 ⊕ l2 ⊕ … ⊕ ln = rhs/-addXORClause-  :: Solver -- ^ The 'Solver' argument.-  -> [Lit]  -- ^ literals @[l1, l2, …, ln]@-  -> Bool   -- ^ /rhs/-  -> IO ()-addXORClause solver lits rhs = do-  d <- getDecisionLevel solver-  assert (d == levelRoot) $ return ()--  ok <- readIORef (svOk solver)-  when ok $ do-    xcl <- instantiateXORClause (getLitFixed solver) (lits,rhs)-    case normalizeXORClause xcl of-      ([], True) -> markBad solver-      ([], False) -> return ()-      ([l], b) -> addClause solver [if b then l else litNot l]-      (l:ls, b) -> do-        c <- newXORClauseHandler ((if b then l else litNot l) : ls) False-        addToDB solver c-        _ <- basicAttachXORClauseHandler solver c-        return ()+instance AddXORClause IO Solver where+  addXORClause :: Solver -> [Lit] -> Bool -> IO ()+  addXORClause solver lits rhs = do+    d <- getDecisionLevel solver+    assert (d == levelRoot) $ return () --- | Add a soft parity constraint /sel ⇒ l1 ⊕ l2 ⊕ … ⊕ ln = rhs/-addXORClauseSoft-  :: Solver -- ^ The 'Solver' argument.-  -> Lit    -- ^ Selector literal @sel@-  -> [Lit]  -- ^ literals @[l1, l2, …, ln]@-  -> Bool   -- ^ /rhs/-  -> IO ()-addXORClauseSoft solver sel lits rhs = do-  reified <- newVar solver-  addXORClause solver (litNot reified : lits) rhs-  addClause solver [litNot sel, reified] -- sel ⇒ reified+    ok <- readIORef (svOk solver)+    when ok $ do+      xcl <- instantiateXORClause (getLitFixed solver) (lits,rhs)+      case normalizeXORClause xcl of+        ([], True) -> markBad solver+        ([], False) -> return ()+        ([l], b) -> addClause solver [if b then l else litNot l]+        (l:ls, b) -> do+          c <- newXORClauseHandler ((if b then l else litNot l) : ls) False+          addToDB solver c+          _ <- basicAttachXORClauseHandler solver c+          return ()  {--------------------------------------------------------------------   Problem solving@@ -1054,6 +1066,7 @@    log solver "Solving starts ..."   resetStat solver+  writeIORef (svCanceled solver) False   writeIORef (svModel solver) Nothing   writeIORef (svFailedAssumptions solver) [] @@ -1068,13 +1081,10 @@     nv <- getNVars solver     Vec.resizeCapacity (svTrail solver) nv -    restartStrategy <- configRestartStrategy <$> getConfig solver-    restartFirst  <- configRestartFirst <$> getConfig solver-    restartInc    <- configRestartInc <$> getConfig solver-    unless (restartInc > 1) $ error "restartInc must be >1"+    unless (configRestartInc config > 1) $ error "RestartInc must be >1"     let restartSeq =-          if restartFirst > 0-          then mkRestartSeq restartStrategy restartFirst restartInc+          if configRestartFirst config  > 0+          then mkRestartSeq (configRestartStrategy config) (configRestartFirst config) (configRestartInc config)           else repeat 0      let learntSizeAdj = do@@ -1089,23 +1099,30 @@      cnt <- readIORef (svLearntLimAdjCnt solver)     when (cnt == -1) $ do-      learntSizeFirst <- configLearntSizeFirst <$> getConfig solver-      learntSizeInc   <- configLearntSizeInc <$> getConfig solver-      unless (learntSizeInc > 1) $ error "learntSizeInc must be >1"+      unless (configLearntSizeInc config > 1) $ error "LearntSizeInc must be >1"       nc <- getNConstraints solver-      let initialLearntLim = if learntSizeFirst > 0 then learntSizeFirst else max ((nc + nv) `div` 3) 16-          learntSizeSeq    = iterate (ceiling . (learntSizeInc*) . fromIntegral) initialLearntLim+      let initialLearntLim = if configLearntSizeFirst config > 0 then configLearntSizeFirst config else max ((nc + nv) `div` 3) 16+          learntSizeSeq    = iterate (ceiling . (configLearntSizeInc config *) . fromIntegral) initialLearntLim           learntSizeAdjSeq = iterate (\x -> (x * 3) `div` 2) (100::Int)       writeIORef (svLearntLimSeq solver) (zip learntSizeSeq learntSizeAdjSeq)       learntSizeAdj +    unless (0 <= configERWAStepSizeFirst config && configERWAStepSizeFirst config <= 1) $ +      error "ERWAStepSizeFirst must be in [0..1]"+    unless (0 <= configERWAStepSizeMin config && configERWAStepSizeFirst config <= 1) $+      error "ERWAStepSizeMin must be in [0..1]"+    unless (0 <= configERWAStepSizeDec config) $+      error "ERWAStepSizeDec must be >=0"+    writeIOURef (svERWAStepSize solver) (configERWAStepSizeFirst config)+     let loop [] = error "solve_: should not happen"         loop (conflict_lim:rs) = do           printStat solver True           ret <- search solver conflict_lim onConflict           case ret of-            SRFinished x -> return $ Just x-            SRBudgetExceeded -> return Nothing+            SRFinished x -> return $ Right x+            SRBudgetExceeded -> return $ Left (throw BudgetExceeded)+            SRCanceled -> return $ Left (throw Canceled)             SRRestart -> do               modifyIOURef (svNRestart solver) (+1)               backtrackTo solver levelRoot@@ -1113,48 +1130,59 @@      printStatHeader solver -    startCPU <- getCPUTime-    startWC  <- getCurrentTime+    startCPU <- getTime ProcessCPUTime+    startWC  <- getTime Monotonic     writeIORef (svStartWC solver) startWC     result <- loop restartSeq-    endCPU <- getCPUTime-    endWC  <- getCurrentTime+    endCPU <- getTime ProcessCPUTime+    endWC  <- getTime Monotonic -    when (result == Just True) $ do-      when (configCheckModel config) $ checkSatisfied solver-      constructModel solver-      mt <- getTheory solver-      case mt of-        Nothing -> return ()-        Just t -> thConstructModel t-    unless (result == Just False) $ do-      saveAssumptionsImplications solver+    case result of+      Right True -> do+        when (configCheckModel config) $ checkSatisfied solver+        constructModel solver+        mt <- getTheory solver+        case mt of+          Nothing -> return ()+          Just t -> thConstructModel t+      _ -> return ()+    case result of+      Right False -> return ()+      _ -> saveAssumptionsImplications solver      backtrackTo solver levelRoot      when debugMode $ dumpVarActivity solver     when debugMode $ dumpConstrActivity 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)+    let durationSecs :: TimeSpec -> TimeSpec -> Double+        durationSecs start end = fromIntegral (toNanoSecs (end `diffTimeSpec` start)) / 10^(9::Int)+    (log solver . printf "#cpu_time = %.3fs") (durationSecs startCPU endCPU)+    (log solver . printf "#wall_clock_time = %.3fs") (durationSecs startWC endWC)     (log solver . printf "#decision = %d") =<< readIOURef (svNDecision solver)     (log solver . printf "#random_decision = %d") =<< readIOURef (svNRandomDecision solver)     (log solver . printf "#conflict = %d") =<< readIOURef (svNConflict solver)     (log solver . printf "#restart = %d")  =<< readIOURef (svNRestart solver)      case result of-      Just x  -> return x-      Nothing -> throw BudgetExceeded+      Right x  -> return x+      Left m -> m  data BudgetExceeded = BudgetExceeded   deriving (Show, Typeable)  instance Exception BudgetExceeded +data Canceled = Canceled+  deriving (Show, Typeable)++instance Exception Canceled+ data SearchResult   = SRFinished Bool   | SRRestart   | SRBudgetExceeded+  | SRCanceled  search :: Solver -> Int -> IO () -> IO SearchResult search solver !conflict_lim onConflict = do@@ -1220,6 +1248,7 @@      handleConflict :: IORef Int -> SomeConstraintHandler -> IO (Maybe SearchResult)     handleConflict conflictCounter constr = do+      varEMADecay solver       varDecayActivity solver       constrDecayActivity solver       onConflict@@ -1237,6 +1266,7 @@       modifyIOURef (svConfBudget solver) $ \confBudget ->         if confBudget > 0 then confBudget - 1 else confBudget       confBudget <- readIOURef (svConfBudget solver)+      canceled <- readIORef (svCanceled solver)        when (c `mod` 100 == 0) $ do         printStat solver False@@ -1246,11 +1276,14 @@         return $ Just (SRFinished False)       else if confBudget==0 then         return $ Just SRBudgetExceeded+      else if canceled then+        return $ Just SRCanceled       else if conflict_lim > 0 && c >= conflict_lim then         return $ Just SRRestart       else do-        strat <- configLearningStrategy <$> getConfig solver-        case strat of+        modifyIOURef (svLearntCounter solver) (+1)+        config <- getConfig solver+        case configLearningStrategy config of           LearningClause -> learnClause constr >> return Nothing           LearningHybrid -> learnHybrid conflictCounter constr @@ -1320,6 +1353,12 @@                   else                     handleConflict conflictCounter h +-- | Cancel exectution of 'solve' or 'solveWith'.+--+-- This can be called from other threads.+cancel :: Solver -> IO ()+cancel solver = writeIORef (svCanceled solver) True+ -- | After 'solve' returns True, it returns an satisfying assignment. getModel :: Solver -> IO Model getModel solver = do@@ -1447,82 +1486,15 @@   Configulation --------------------------------------------------------------------}          -data Config-  = Config-  { configRestartStrategy :: !RestartStrategy-  , configRestartFirst :: !Int-    -- ^ The initial restart limit. (default 100)-    -- Zero and negative values are used to disable restart.-  , configRestartInc :: !Double-    -- ^ The factor with which the restart limit is multiplied in each restart. (default 1.5)-    -- This must be @>1@.-  , configLearningStrategy :: !LearningStrategy-  , configLearntSizeFirst :: !Int-    -- ^ The initial limit for learnt constraints.-    -- Negative value means computing default value from problem instance.-  , configLearntSizeInc :: !Double-    -- ^ The limit for learnt constraints is multiplied with this factor periodically. (default 1.1)-    -- This must be @>1@.                     -  , configCCMin :: !Int-    -- ^ Controls conflict constraint minimization (0=none, 1=local, 2=recursive)-  , configEnablePhaseSaving :: !Bool-  , configEnableForwardSubsumptionRemoval :: !Bool-  , configEnableBackwardSubsumptionRemoval :: !Bool-  , configRandomFreq :: !Double-    -- ^ The frequency with which the decision heuristic tries to choose a random variable-  , configPBHandlerType :: !PBHandlerType-  , configEnablePBSplitClausePart :: !Bool-    -- ^ Split PB-constraints into a PB part and a clause part.-    ---    -- Example from minisat+ paper:-    ---    -- * 4 x1 + 4 x2 + 4 x3 + 4 x4 + 2y1 + y2 + y3 ≥ 4-    -- -    -- would be split into-    ---    -- * x1 + x2 + x3 + x4 + ¬z ≥ 1 (clause part)-    ---    -- * 2 y1 + y2 + y3 + 4 z ≥ 4 (PB part)-    ---    -- where z is a newly introduced variable, not present in any other constraint.-    -- -    -- Reference:-    -- -    -- * N . Eéen and N. Sörensson. Translating Pseudo-Boolean Constraints into SAT. JSAT 2:1–26, 2006.-    --                               -  , configCheckModel :: !Bool-  , configVarDecay :: !Double-    -- ^ Inverse of the variable activity decay factor. (default 1 / 0.95)-  , configConstrDecay :: !Double-    -- ^ Inverse of the constraint activity decay factor. (1 / 0.999)-  } deriving (Show, Eq, Ord)--instance Default Config where-  def =-    Config-    { configRestartStrategy = def-    , configRestartFirst = defaultRestartFirst-    , configRestartInc = defaultRestartInc-    , configLearningStrategy = def-    , configLearntSizeFirst = defaultLearntSizeFirst-    , configLearntSizeInc = defaultLearntSizeInc-    , configCCMin = defaultCCMin-    , configEnablePhaseSaving = defaultEnablePhaseSaving-    , configEnableForwardSubsumptionRemoval = defaultEnableForwardSubsumptionRemoval-    , configEnableBackwardSubsumptionRemoval = defaultEnableBackwardSubsumptionRemoval-    , configRandomFreq = defaultRandomFreq-    , configPBHandlerType = def-    , configEnablePBSplitClausePart = defaultPBSplitClausePart-    , configCheckModel = False-    , configVarDecay = 1 / 0.95-    , configConstrDecay = 1 / 0.999-    }- getConfig :: Solver -> IO Config getConfig solver = readIORef $ svConfig solver  setConfig :: Solver -> Config -> IO ()-setConfig solver = writeIORef (svConfig solver)+setConfig solver conf = do+  orig <- readIORef $ svConfig solver+  writeIORef (svConfig solver) conf+  when (configBranchingStrategy orig /= configBranchingStrategy conf) $ do+    PQ.rebuild (svVarQueue solver)  modifyConfig :: Solver -> (Config -> Config) -> IO () modifyConfig solver = modifyIORef' (svConfig solver)@@ -1537,11 +1509,6 @@ setRestartFirst :: Solver -> Int -> IO () setRestartFirst solver !n = modifyIORef' (svConfig solver) $ \config -> config{ configRestartFirst = n } --- | default value for @RestartFirst@.-{-# DEPRECATED defaultRestartFirst "Use configRestartFirst def" #-}-defaultRestartFirst :: Int-defaultRestartFirst = 100- -- | The factor with which the restart limit is multiplied in each restart. (default 1.5) --  -- This must be @>1@.@@ -1551,22 +1518,6 @@   | r > 1 = modifyIORef' (svConfig solver) $ \config -> config{ configRestartInc = r }   | otherwise = error "setRestartInc: RestartInc must be >1" --- | default value for @RestartInc@.-{-# DEPRECATED defaultRestartInc "Use configRestartInc def" #-}-defaultRestartInc :: Double-defaultRestartInc = 1.5---- | Learning strategy.------ The default value can be obtained by 'def'.-data LearningStrategy-  = LearningClause-  | LearningHybrid-  deriving (Show, Eq, Ord, Enum, Bounded)--instance Default LearningStrategy where-  def = LearningClause- {-# DEPRECATED setLearningStrategy "Use setConfig" #-} setLearningStrategy :: Solver -> LearningStrategy -> IO () setLearningStrategy solver l = modifyIORef' (svConfig solver) $ \config -> config{ configLearningStrategy = l }@@ -1578,11 +1529,6 @@ setLearntSizeFirst :: Solver -> Int -> IO () setLearntSizeFirst solver !x = modifyIORef' (svConfig solver) $ \config -> config{ configLearntSizeFirst = x } --- | default value for @LearntSizeFirst@.-{-# DEPRECATED defaultLearntSizeFirst "Use learntSizeFirst def" #-}-defaultLearntSizeFirst :: Int-defaultLearntSizeFirst = -1- -- | The limit for learnt clauses is multiplied with this factor each restart. (default 1.1) --  -- This must be @>1@.@@ -1592,21 +1538,11 @@   | r > 1 = modifyIORef' (svConfig solver) $ \config -> config{ configLearntSizeInc = r }   | otherwise = error "setLearntSizeInc: LearntSizeInc must be >1" --- | default value for @LearntSizeInc@.-{-# DEPRECATED defaultLearntSizeInc "Use learntSizeInc def" #-}-defaultLearntSizeInc :: Double-defaultLearntSizeInc = 1.1- -- | Controls conflict clause minimization (0=none, 1=basic, 2=deep) {-# DEPRECATED setCCMin "Use setConfig" #-} setCCMin :: Solver -> Int -> IO () setCCMin solver !v = modifyIORef' (svConfig solver) $ \config -> config{ configCCMin = v } --- | default value for @CCMin@.-{-# DEPRECATED defaultCCMin "Use ccMin def" #-}-defaultCCMin :: Int-defaultCCMin = 2- -- | The default polarity of a variable. setVarPolarity :: Solver -> Var -> Bool -> IO () setVarPolarity solver v val = do@@ -1624,10 +1560,6 @@ setRandomFreq solver r =   modifyIORef' (svConfig solver) $ \config -> config{ configRandomFreq = r } -{-# DEPRECATED defaultRandomFreq "Use configRandomFreq def" #-}-defaultRandomFreq :: Double-defaultRandomFreq = 0.005- -- | Set random generator used by the random variable selection setRandomGen :: Solver -> Rand.GenIO -> IO () setRandomGen solver = writeIORef (svRandomGen solver)@@ -1640,15 +1572,6 @@ setConfBudget solver (Just b) | b >= 0 = writeIOURef (svConfBudget solver) b setConfBudget solver _ = writeIOURef (svConfBudget solver) (-1) --- | Pseudo boolean constraint handler implimentation.------ The default value can be obtained by 'def'.-data PBHandlerType = PBHandlerTypeCounter | PBHandlerTypePueblo-  deriving (Show, Eq, Ord, Enum, Bounded)--instance Default PBHandlerType where-  def = PBHandlerTypeCounter- {-# DEPRECATED setPBHandlerType "Use setConfig" #-} setPBHandlerType :: Solver -> PBHandlerType -> IO () setPBHandlerType solver ht = do@@ -1670,7 +1593,7 @@ --  -- Reference: -- --- * N . Eéen and N. Sörensson. Translating Pseudo-Boolean Constraints into SAT. JSAT 2:1–26, 2006.+-- * N. Eén and N. Sörensson. Translating Pseudo-Boolean Constraints into SAT. JSAT 2:1–26, 2006. -- {-# DEPRECATED setPBSplitClausePart "Use setConfig" #-} setPBSplitClausePart :: Solver -> Bool -> IO ()@@ -1682,11 +1605,6 @@ getPBSplitClausePart solver =   configEnablePBSplitClausePart <$> getConfig solver --- | See documentation of 'setPBSplitClausePart'.-{-# DEPRECATED defaultPBSplitClausePart "Use configEnablePBSplitClausePart def" #-}-defaultPBSplitClausePart :: Bool-defaultPBSplitClausePart = False- {-# DEPRECATED setEnablePhaseSaving "Use setConfig" #-} setEnablePhaseSaving :: Solver -> Bool -> IO () setEnablePhaseSaving solver flag = do@@ -1697,10 +1615,6 @@ getEnablePhaseSaving solver = do   configEnablePhaseSaving <$> getConfig solver -{-# DEPRECATED defaultEnablePhaseSaving "Use configEnablePhaseSaving def" #-}-defaultEnablePhaseSaving :: Bool-defaultEnablePhaseSaving = True- {-# DEPRECATED setEnableForwardSubsumptionRemoval "Use setConfig" #-} setEnableForwardSubsumptionRemoval :: Solver -> Bool -> IO () setEnableForwardSubsumptionRemoval solver flag = do@@ -1711,10 +1625,6 @@ getEnableForwardSubsumptionRemoval solver = do   configEnableForwardSubsumptionRemoval <$> getConfig solver -{-# DEPRECATED defaultEnableForwardSubsumptionRemoval "Use configEnableForwardSubsumptionRemoval def" #-}-defaultEnableForwardSubsumptionRemoval :: Bool-defaultEnableForwardSubsumptionRemoval = False- {-# DEPRECATED setEnableBackwardSubsumptionRemoval "Use setConfig" #-} setEnableBackwardSubsumptionRemoval :: Solver -> Bool -> IO () setEnableBackwardSubsumptionRemoval solver flag = do@@ -1725,10 +1635,6 @@ getEnableBackwardSubsumptionRemoval solver = do   configEnableBackwardSubsumptionRemoval <$> getConfig solver -{-# DEPRECATED defaultEnableBackwardSubsumptionRemoval "Use configEnableBackwardSubsumptionRemoval def" #-}-defaultEnableBackwardSubsumptionRemoval :: Bool-defaultEnableBackwardSubsumptionRemoval = False- {--------------------------------------------------------------------   API for implementation of @solve@ --------------------------------------------------------------------}@@ -1789,42 +1695,31 @@   return ()  deduce :: Solver -> IO (Maybe SomeConstraintHandler)-deduce solver = do-  m <- deduceB solver-  case m of-    Just _ -> return m-    Nothing -> do-      m2 <- deduceT solver-      case m2 of-        Just _ -> return m2-        Nothing -> do-          empty <- bcpIsEmpty solver-          if empty then-            return Nothing-          else-            deduce solver+deduce solver = liftM (either Just (const Nothing)) $ runExceptT $ do+  let loop = do+        deduceB solver+        deduceT solver+        empty <- liftIO $ bcpIsEmpty solver+        unless empty $ loop+  loop -deduceB :: Solver -> IO (Maybe SomeConstraintHandler)+deduceB :: Solver -> ExceptT SomeConstraintHandler IO () deduceB solver = loop   where-    loop :: IO (Maybe SomeConstraintHandler)+    loop :: ExceptT SomeConstraintHandler IO ()     loop = do-      r <- bcpDequeue solver+      r <- liftIO $ bcpDequeue solver       case r of-        Nothing -> return Nothing+        Nothing -> return ()         Just lit -> do-          ret <- processLit lit-          case ret of-            Just _ -> return ret-            Nothing -> do-              ret <- processVar lit-              case ret of-                Just _ -> return ret-                Nothing -> loop+          processLit lit+          processVar lit+          loop -    processLit :: Lit -> IO (Maybe SomeConstraintHandler)-    processLit !lit = do-      let falsifiedLit = litNot lit+    processLit :: Lit -> ExceptT SomeConstraintHandler IO ()+    processLit !lit = ExceptT $ liftM (maybe (Right ()) Left) $ do+      let falsifiedLit =+              litNot lit       ld <- litData solver falsifiedLit       let wsref = ldWatches ld       let loop2 [] = return Nothing@@ -1839,8 +1734,8 @@       writeIORef wsref []       loop2 ws -    processVar :: Lit -> IO (Maybe SomeConstraintHandler)-    processVar !lit = do+    processVar :: Lit -> ExceptT SomeConstraintHandler IO ()+    processVar !lit = ExceptT $ liftM (maybe (Right ()) Left) $ do       let falsifiedLit = litNot lit       vd <- varData solver (litVar lit)       let wsref = vdWatches vd@@ -1889,7 +1784,9 @@                 Just constr2 -> do                   constrBumpActivity solver constr2                   xs <- reasonOf solver constr2 (Just l)-                  forM_ xs $ \lit -> varBumpActivity solver (litVar lit)+                  forM_ xs $ \lit -> do+                     varBumpActivity solver (litVar lit)+                     varIncrementParticipated solver (litVar lit)                   popTrail solver                   (ys,zs) <- split xs                   loop (IS.delete (litNot l) lits1 `IS.union` ys)@@ -1900,12 +1797,16 @@    constrBumpActivity solver constr   conflictClause <- reasonOf solver constr Nothing-  forM_ conflictClause $ \lit -> varBumpActivity solver (litVar lit)+  forM_ conflictClause $ \lit -> do+    varBumpActivity solver (litVar lit)+    varIncrementParticipated solver (litVar lit)   (ys,zs) <- split conflictClause   lits <- loop ys zs    lits2 <- minimizeConflictClause solver lits +  incrementReasoned solver (IS.toList lits2)+   xs <- liftM (sortBy (flip (comparing snd))) $     forM (IS.toList lits2) $ \l -> do       lv <- litLevel solver l@@ -1976,7 +1877,9 @@                     return (lits1,lits2)                   else do                     constrBumpActivity solver constr2-                    forM_ xs $ \lit -> varBumpActivity solver (litVar lit)+                    forM_ xs $ \lit -> do+                      varBumpActivity solver (litVar lit)+                      varIncrementParticipated solver (litVar lit)                     (ys,zs) <- split xs                     return  (IS.delete (litNot l) lits1 `IS.union` ys, lits2 `IS.union` zs) @@ -2011,12 +1914,16 @@       toPBLinAtLeast constr     else       return (clauseToPBLinAtLeast conflictClause)-  forM_ conflictClause $ \lit -> varBumpActivity solver (litVar lit)+  forM_ conflictClause $ \lit -> do+    varBumpActivity solver (litVar lit)+    varIncrementParticipated solver (litVar lit)   (ys,zs) <- split conflictClause   (lits, pb) <- loop ys zs pbConfl    lits2 <- minimizeConflictClause solver lits +  incrementReasoned solver (IS.toList lits2)+   xs <- liftM (sortBy (flip (comparing snd))) $     forM (IS.toList lits2) $ \l -> do       lv <- litLevel solver l@@ -2127,6 +2034,20 @@     log solver $ show ys   return $ IS.fromAscList $ ys +incrementReasoned :: Solver -> Clause -> IO ()+incrementReasoned solver ls = do+  let f reasonSided l = do+        m <- varReason solver (litVar l)+        case m of+          Nothing -> return reasonSided+          Just constr -> do+            v <- litValue solver l+            unless (v == lFalse) undefined+            xs <- constrReasonOf solver constr (Just (litNot l))+            return $ reasonSided `IS.union` IS.fromList (map litVar xs)+  reasonSided <- foldM f IS.empty ls+  mapM_ (varIncrementReasoned solver) (IS.toList reasonSided)+ peekTrail :: Solver -> IO Lit peekTrail solver = do   n <- Vec.getSize (svTrail solver)@@ -2261,15 +2182,15 @@  printStat :: Solver -> Bool -> IO () printStat solver force = do-  nowWC <- getCurrentTime+  nowWC <- getTime Monotonic   b <- if force        then return True        else do          lastWC <- readIORef (svLastStatWC solver)-         return $ (nowWC `diffUTCTime` lastWC) > 1+         return $ sec (nowWC `diffTimeSpec` lastWC) > 1   when b $ do     startWC   <- readIORef (svStartWC solver)-    let tm = showTimeDiff $ nowWC `diffUTCTime` startWC+    let tm = showTimeDiff $ nowWC `diffTimeSpec` startWC     restart   <- readIOURef (svNRestart solver)     dec       <- readIOURef (svNDecision solver)     conflict  <- readIOURef (svNConflict solver)@@ -2281,8 +2202,8 @@       tm restart dec conflict learntLim learntGC fixed removed     writeIORef (svLastStatWC solver) nowWC -showTimeDiff :: NominalDiffTime -> String-showTimeDiff sec+showTimeDiff :: TimeSpec -> String+showTimeDiff t   | si <  100  = printf "%4.1fs" (fromRational s :: Double)   | si <= 9999 = printf "%4ds" si   | mi <  100  = printf "%4.1fm" (fromRational m :: Double)@@ -2291,10 +2212,10 @@   | otherwise  = printf "%4dh" hi   where     s :: Rational-    s = realToFrac sec+    s = fromIntegral (toNanoSecs t) / 10^(9::Int)      si :: Integer-    si = round s+    si = fromIntegral (sec t)      m :: Rational     m = s / 60@@ -2765,9 +2686,10 @@     return ([(1,l) | l <- lits], 1)    isSatisfied solver this = do-    lits <- getElems (claLits this)-    vals <- mapM (litValue solver) lits-    return $ lTrue `elem` vals+    (lb,ub) <- getBounds (claLits this)+    liftM isLeft $ runExceptT $ numLoop lb ub $ \i -> do+      v <- lift $ litValue solver =<< unsafeRead (claLits this) i+      when (v == lTrue) $ throwE ()    constrIsProtected _ this = do     size <- claGetSize this@@ -3029,9 +2951,15 @@     return ([(1,l) | l <- lits], fromIntegral (atLeastNum this))    isSatisfied solver this = do-    lits <- getElems (atLeastLits this)-    vals <- mapM (litValue solver) lits-    return $ length [v | v <- vals, v == lTrue] >= atLeastNum this+    (lb,ub) <- getBounds (atLeastLits this)+    liftM isLeft $ runExceptT $ numLoopState lb ub 0 $ \(!n) i -> do+      v <- lift $ litValue solver =<< unsafeRead (atLeastLits this) i+      if v /= lTrue then do+        return n+      else do+        let n' = n + 1+        when (n' >= atLeastNum this) $ throwE ()+        return n'    constrReadActivity this = readIORef (atLeastActivity this) @@ -3685,35 +3613,29 @@ getTheory :: Solver -> IO (Maybe TheorySolver) getTheory solver = readIORef (svTheorySolver solver) -deduceT :: Solver -> IO (Maybe SomeConstraintHandler)+deduceT :: Solver -> ExceptT SomeConstraintHandler IO () deduceT solver = do-  mt <- readIORef (svTheorySolver solver)+  mt <- liftIO $ readIORef (svTheorySolver solver)   case mt of-    Nothing -> return Nothing+    Nothing -> return ()     Just t -> do-      n <- Vec.getSize (svTrail solver)+      n <- liftIO $ Vec.getSize (svTrail solver)       let h = CHTheory TheoryHandler           callback l = assignBy solver l h           loop i = do-            if i < n then do-              l <- Vec.unsafeRead (svTrail solver) i-              ok <- thAssertLit t callback l+            when (i < n) $ do+              l <- liftIO $ Vec.unsafeRead (svTrail solver) i+              ok <- liftIO $ thAssertLit t callback l               if ok then                 loop (i+1)               else-                return False-            else do-              return True-      b <- loop =<< readIOURef (svTheoryChecked solver)-      if not b then-        return (Just h)-      else do-        b2 <- thCheck t callback-        if b2 then do-          writeIOURef (svTheoryChecked solver) n-          return Nothing-        else-          return (Just h)+                throwE h+      loop =<< liftIO (readIOURef (svTheoryChecked solver))+      b2 <- liftIO $ thCheck t callback+      if b2 then do+        liftIO $ writeIOURef (svTheoryChecked solver) n+      else+        throwE h  data TheoryHandler = TheoryHandler deriving (Eq) @@ -3756,15 +3678,6 @@ {--------------------------------------------------------------------   Restart strategy --------------------------------------------------------------------}---- | Restart strategy.------ The default value can be obtained by 'def'.-data RestartStrategy = MiniSATRestarts | ArminRestarts | LubyRestarts-  deriving (Show, Eq, Ord, Enum, Bounded)--instance Default RestartStrategy where-  def = MiniSATRestarts  mkRestartSeq :: RestartStrategy -> Int -> Double -> [Int] mkRestartSeq MiniSATRestarts = miniSatRestartSeq
+ src/ToySolver/SAT/Config.hs view
@@ -0,0 +1,262 @@+module ToySolver.SAT.Config+  ( -- * Solver configulation+    Config (..)+  , RestartStrategy (..)+  , showRestartStrategy+  , parseRestartStrategy+  , LearningStrategy (..)+  , showLearningStrategy+  , parseLearningStrategy+  , BranchingStrategy (..)+  , showBranchingStrategy+  , parseBranchingStrategy+  , PBHandlerType (..)+  , showPBHandlerType+  , parsePBHandlerType++  -- ** Deprecated+  , defaultRestartFirst+  , defaultRestartInc+  , defaultLearntSizeFirst+  , defaultLearntSizeInc+  , defaultCCMin+  , defaultEnablePhaseSaving+  , defaultEnableForwardSubsumptionRemoval+  , defaultEnableBackwardSubsumptionRemoval+  , defaultRandomFreq+  , defaultPBSplitClausePart+  ) where++import Data.Char+import Data.Default.Class++data Config+  = Config+  { configRestartStrategy :: !RestartStrategy+  , configRestartFirst :: !Int+    -- ^ The initial restart limit. (default 100)+    -- Zero and negative values are used to disable restart.+  , configRestartInc :: !Double+    -- ^ The factor with which the restart limit is multiplied in each restart. (default 1.5)+    -- This must be @>1@.+  , configLearningStrategy :: !LearningStrategy+  , configLearntSizeFirst :: !Int+    -- ^ The initial limit for learnt constraints.+    -- Negative value means computing default value from problem instance.+  , configLearntSizeInc :: !Double+    -- ^ The limit for learnt constraints is multiplied with this factor periodically. (default 1.1)+    -- This must be @>1@.                     +  , configCCMin :: !Int+    -- ^ Controls conflict constraint minimization (0=none, 1=local, 2=recursive)+  , configBranchingStrategy :: !BranchingStrategy+  , configERWAStepSizeFirst :: !Double+    -- ^ step-size α in ERWA and LRB branching heuristic is initialized with this value. (default 0.4)+  , configERWAStepSizeDec :: !Double+    -- ^ step-size α in ERWA and LRB branching heuristic is decreased by this value after each conflict. (default 0.06)+  , configERWAStepSizeMin :: !Double+    -- ^ step-size α in ERWA and LRB branching heuristic is decreased until it reach the value. (default 0.06)+  , configEMADecay :: !Double+    -- ^ inverse of the variable EMA decay factor used by LRB branching heuristic. (default 1 / 0.95)+  , configEnablePhaseSaving :: !Bool+  , configEnableForwardSubsumptionRemoval :: !Bool+  , configEnableBackwardSubsumptionRemoval :: !Bool+  , configRandomFreq :: !Double+    -- ^ The frequency with which the decision heuristic tries to choose a random variable+  , configPBHandlerType :: !PBHandlerType+  , configEnablePBSplitClausePart :: !Bool+    -- ^ Split PB-constraints into a PB part and a clause part.+    --+    -- Example from minisat+ paper:+    --+    -- * 4 x1 + 4 x2 + 4 x3 + 4 x4 + 2y1 + y2 + y3 ≥ 4+    -- +    -- would be split into+    --+    -- * x1 + x2 + x3 + x4 + ¬z ≥ 1 (clause part)+    --+    -- * 2 y1 + y2 + y3 + 4 z ≥ 4 (PB part)+    --+    -- where z is a newly introduced variable, not present in any other constraint.+    -- +    -- Reference:+    -- +    -- * N . Eéen and N. Sörensson. Translating Pseudo-Boolean Constraints into SAT. JSAT 2:1–26, 2006.+    --                               +  , configCheckModel :: !Bool+  , configVarDecay :: !Double+    -- ^ Inverse of the variable activity decay factor. (default 1 / 0.95)+  , configConstrDecay :: !Double+    -- ^ Inverse of the constraint activity decay factor. (1 / 0.999)+  } deriving (Show, Eq, Ord)++instance Default Config where+  def =+    Config+    { configRestartStrategy = def+    , configRestartFirst = defaultRestartFirst+    , configRestartInc = defaultRestartInc+    , configLearningStrategy = def+    , configLearntSizeFirst = defaultLearntSizeFirst+    , configLearntSizeInc = defaultLearntSizeInc+    , configCCMin = defaultCCMin+    , configBranchingStrategy = def+    , configERWAStepSizeFirst = 0.4+    , configERWAStepSizeDec = 10**(-6)+    , configERWAStepSizeMin = 0.06+    , configEMADecay = 1 / 0.95+    , configEnablePhaseSaving = defaultEnablePhaseSaving+    , configEnableForwardSubsumptionRemoval = defaultEnableForwardSubsumptionRemoval+    , configEnableBackwardSubsumptionRemoval = defaultEnableBackwardSubsumptionRemoval+    , configRandomFreq = defaultRandomFreq+    , configPBHandlerType = def+    , configEnablePBSplitClausePart = defaultPBSplitClausePart+    , configCheckModel = False+    , configVarDecay = 1 / 0.95+    , configConstrDecay = 1 / 0.999+    }++-- | Restart strategy.+--+-- The default value can be obtained by 'def'.+data RestartStrategy = MiniSATRestarts | ArminRestarts | LubyRestarts+  deriving (Show, Eq, Ord, Enum, Bounded)++instance Default RestartStrategy where+  def = MiniSATRestarts++showRestartStrategy :: RestartStrategy -> String+showRestartStrategy MiniSATRestarts = "minisat"+showRestartStrategy ArminRestarts = "armin"+showRestartStrategy LubyRestarts = "luby"++parseRestartStrategy :: String -> Maybe RestartStrategy+parseRestartStrategy s =+  case map toLower s of+    "minisat" -> Just MiniSATRestarts+    "armin" -> Just ArminRestarts+    "luby" -> Just LubyRestarts+    _ -> Nothing++-- | default value for @RestartFirst@.+{-# DEPRECATED defaultRestartFirst "Use configRestartFirst def" #-}+defaultRestartFirst :: Int+defaultRestartFirst = 100++-- | default value for @RestartInc@.+{-# DEPRECATED defaultRestartInc "Use configRestartInc def" #-}+defaultRestartInc :: Double+defaultRestartInc = 1.5++-- | Learning strategy.+--+-- The default value can be obtained by 'def'.+data LearningStrategy+  = LearningClause+  | LearningHybrid+  deriving (Show, Eq, Ord, Enum, Bounded)++instance Default LearningStrategy where+  def = LearningClause++showLearningStrategy :: LearningStrategy -> String+showLearningStrategy LearningClause = "clause"+showLearningStrategy LearningHybrid = "hybrid"++parseLearningStrategy :: String -> Maybe LearningStrategy+parseLearningStrategy s =+  case map toLower s of+    "clause" -> Just LearningClause+    "hybrid" -> Just LearningHybrid+    _ -> Nothing++-- | Branching strategy.+--+-- The default value can be obtained by 'def'.+--+-- 'BranchingERWA' and 'BranchingLRB' is based on [Liang et al 2016].+--+-- * J. Liang, V. Ganesh, P. Poupart, and K. Czarnecki, "Learning rate based branching heuristic for SAT solvers,"+--   in Proceedings of Theory and Applications of Satisfiability Testing (SAT 2016), pp. 123-140.+--   <http://link.springer.com/chapter/10.1007/978-3-319-40970-2_9>+--   <https://cs.uwaterloo.ca/~ppoupart/publications/sat/learning-rate-branching-heuristic-SAT.pdf>+data BranchingStrategy+  = BranchingVSIDS+    -- ^ VSIDS (Variable State Independent Decaying Sum) branching heuristic+  | BranchingERWA+    -- ^ ERWA (Exponential Recency Weighted Average) branching heuristic+  | BranchingLRB+    -- ^ LRB (Learning Rate Branching) heuristic+  deriving (Show, Eq, Ord, Enum, Bounded)++instance Default BranchingStrategy where+  def = BranchingVSIDS++showBranchingStrategy :: BranchingStrategy -> String+showBranchingStrategy BranchingVSIDS = "vsids"+showBranchingStrategy BranchingERWA  = "erwa"+showBranchingStrategy BranchingLRB   = "lrb"++parseBranchingStrategy :: String -> Maybe BranchingStrategy+parseBranchingStrategy s =+  case map toLower s of+    "vsids" -> Just BranchingVSIDS+    "erwa"  -> Just BranchingERWA+    "lrb"   -> Just BranchingLRB+    _ -> Nothing++-- | default value for @LearntSizeFirst@.+{-# DEPRECATED defaultLearntSizeFirst "Use learntSizeFirst def" #-}+defaultLearntSizeFirst :: Int+defaultLearntSizeFirst = -1+++-- | default value for @LearntSizeInc@.+{-# DEPRECATED defaultLearntSizeInc "Use learntSizeInc def" #-}+defaultLearntSizeInc :: Double+defaultLearntSizeInc = 1.1++-- | default value for @CCMin@.+{-# DEPRECATED defaultCCMin "Use ccMin def" #-}+defaultCCMin :: Int+defaultCCMin = 2++{-# DEPRECATED defaultRandomFreq "Use configRandomFreq def" #-}+defaultRandomFreq :: Double+defaultRandomFreq = 0.005++-- | Pseudo boolean constraint handler implimentation.+--+-- The default value can be obtained by 'def'.+data PBHandlerType = PBHandlerTypeCounter | PBHandlerTypePueblo+  deriving (Show, Eq, Ord, Enum, Bounded)++instance Default PBHandlerType where+  def = PBHandlerTypeCounter++showPBHandlerType :: PBHandlerType -> String+showPBHandlerType PBHandlerTypeCounter = "counter"+showPBHandlerType PBHandlerTypePueblo = "pueblo"++parsePBHandlerType :: String -> Maybe PBHandlerType+parsePBHandlerType s =+  case map toLower s of+    "counter" -> Just PBHandlerTypeCounter+    "pueblo" -> Just PBHandlerTypePueblo+    _ -> Nothing++-- | See documentation of 'setPBSplitClausePart'.+{-# DEPRECATED defaultPBSplitClausePart "Use configEnablePBSplitClausePart def" #-}+defaultPBSplitClausePart :: Bool+defaultPBSplitClausePart = False++{-# DEPRECATED defaultEnablePhaseSaving "Use configEnablePhaseSaving def" #-}+defaultEnablePhaseSaving :: Bool+defaultEnablePhaseSaving = True++{-# DEPRECATED defaultEnableForwardSubsumptionRemoval "Use configEnableForwardSubsumptionRemoval def" #-}+defaultEnableForwardSubsumptionRemoval :: Bool+defaultEnableForwardSubsumptionRemoval = False++{-# DEPRECATED defaultEnableBackwardSubsumptionRemoval "Use configEnableBackwardSubsumptionRemoval def" #-}+defaultEnableBackwardSubsumptionRemoval :: Bool+defaultEnableBackwardSubsumptionRemoval = False
+ src/ToySolver/SAT/Encoder/Integer.hs view
@@ -0,0 +1,94 @@+{-# LANGUAGE TypeFamilies #-}+module ToySolver.SAT.Encoder.Integer+  ( Expr (..)+  , newVar+  , linearize+  , addConstraint+  , addConstraintSoft+  , eval+  ) where++import Control.Monad+import Control.Monad.Primitive+import Data.Array.IArray+import Data.VectorSpace+import Text.Printf++import ToySolver.Data.OrdRel+import qualified ToySolver.SAT.Types as SAT+import qualified ToySolver.SAT.Encoder.PBNLC as PBNLC++newtype Expr = Expr SAT.PBSum++newVar :: SAT.AddPBNL m enc => enc -> Integer -> Integer -> m Expr+newVar enc lo hi+  | lo > hi = do+      SAT.addClause enc [] -- assert inconsistency+      return 0+  | lo == hi = return $ fromInteger lo+  | otherwise = do+      let hi' = hi - lo+          bitWidth = head $ [w | w <- [1..], let mx = 2 ^ w - 1, hi' <= mx]+      vs <- SAT.newVars enc bitWidth+      let xs = zip (iterate (2*) 1) vs+      SAT.addPBAtMost enc xs hi'+      return $ Expr ((lo,[]) : [(c,[x]) | (c,x) <- xs])++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)+  Expr xs1 * Expr xs2 = Expr [(c1*c2, lits1++lits2) | (c1,lits1) <- xs1, (c2,lits2) <- xs2]+  negate (Expr xs) = Expr [(-c,lits) | (c,lits) <- xs]+  abs      = id+  signum _ = 1+  fromInteger c = Expr [(c,[])]++linearize :: PrimMonad m => PBNLC.Encoder m -> Expr -> m (SAT.PBLinSum, Integer)+linearize enc (Expr xs) = do+  let ys = [(c,lits) | (c,lits@(_:_)) <- xs]+      c  = sum [c | (c,[]) <- xs]+  zs <- PBNLC.linearizePBSum enc ys+  return (zs, c)++addConstraint :: SAT.AddPBNL m enc => enc -> OrdRel Expr -> m ()+addConstraint enc (OrdRel lhs op rhs) = do+  let Expr e = lhs - rhs+  case op of+    Le  -> SAT.addPBNLAtMost  enc e 0+    Lt  -> SAT.addPBNLAtMost  enc e (-1)+    Ge  -> SAT.addPBNLAtLeast enc e 0+    Gt  -> SAT.addPBNLAtLeast enc e 1+    Eql -> SAT.addPBNLExactly enc e 0+    NEq -> do+      sel <- SAT.newVar enc+      SAT.addPBNLAtLeastSoft enc sel e 1+      SAT.addPBNLAtMostSoft  enc (-sel) e (-1)++addConstraintSoft :: SAT.AddPBNL m enc => enc -> SAT.Lit -> OrdRel Expr -> m ()+addConstraintSoft enc sel (OrdRel lhs op rhs) = do+  let Expr e = lhs - rhs+  case op of+    Le  -> SAT.addPBNLAtMostSoft  enc sel e 0+    Lt  -> SAT.addPBNLAtMostSoft  enc sel e (-1)+    Ge  -> SAT.addPBNLAtLeastSoft enc sel e 0+    Gt  -> SAT.addPBNLAtLeastSoft enc sel e 1+    Eql -> SAT.addPBNLExactlySoft enc sel e 0+    NEq -> do+      sel2 <- SAT.newVar enc+      sel3 <- SAT.newVar enc+      sel4 <- SAT.newVar enc+      SAT.addClause enc [-sel, -sel2, sel3] -- sel ∧  sel2 → sel3+      SAT.addClause enc [-sel,  sel2, sel4] -- sel ∧ ¬sel2 → sel4+      SAT.addPBNLAtLeastSoft enc sel3 e 1+      SAT.addPBNLAtMostSoft  enc sel4 e (-1)++eval :: SAT.IModel m => m -> Expr -> Integer+eval m (Expr ts) = sum [if and [SAT.evalLit m lit | lit <- lits] then n else 0 | (n,lits) <- ts]
+ src/ToySolver/SAT/Encoder/PB.hs view
@@ -0,0 +1,93 @@+{-# LANGUAGE BangPatterns, ScopedTypeVariables, FlexibleInstances, MultiParamTypeClasses #-}+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.SAT.Encoder.PB+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable (BangPatterns, ScopedTypeVariables, FlexibleInstances, MultiParamTypeClasses)+--+-- References:+--+-- * [ES06] N. Eén and N. Sörensson. Translating Pseudo-Boolean+--   Constraints into SAT. JSAT 2:1–26, 2006.+--+-----------------------------------------------------------------------------+module ToySolver.SAT.Encoder.PB+  ( Encoder+  , Strategy (..)+  , newEncoder+  , newEncoderWithStrategy+  , encodePBLinAtLeast+  ) where++import Control.Monad.Primitive+import Data.Default.Class+import qualified ToySolver.SAT.Types as SAT+import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin+import ToySolver.SAT.Encoder.PB.Internal.Adder (addPBLinAtLeastAdder, encodePBLinAtLeastAdder)+import ToySolver.SAT.Encoder.PB.Internal.BDD (addPBLinAtLeastBDD, encodePBLinAtLeastBDD)+import ToySolver.SAT.Encoder.PB.Internal.Sorter (addPBLinAtLeastSorter, encodePBLinAtLeastSorter)++data Encoder m = Encoder (Tseitin.Encoder m) Strategy++data Strategy+  = BDD+  | Adder+  | Sorter+  | Hybrid -- not implemented yet+  deriving (Show, Eq, Ord, Enum, Bounded)++instance Default Strategy where+  def = Hybrid++newEncoder :: Monad m => Tseitin.Encoder m -> m (Encoder m)+newEncoder tseitin = newEncoderWithStrategy tseitin Hybrid++newEncoderWithStrategy :: Monad m => Tseitin.Encoder m -> Strategy -> m (Encoder m)+newEncoderWithStrategy tseitin strategy = return (Encoder tseitin strategy)++instance Monad m => SAT.NewVar m (Encoder m) where+  newVar   (Encoder a _) = SAT.newVar a+  newVars  (Encoder a _) = SAT.newVars a+  newVars_ (Encoder a _) = SAT.newVars_ a++instance Monad m => SAT.AddClause m (Encoder m) where+  addClause (Encoder a _) = SAT.addClause a++instance PrimMonad m => SAT.AddCardinality m (Encoder m) where+  addAtLeast enc lhs rhs = SAT.addPBAtLeast enc [(1, l) | l <- lhs] (fromIntegral rhs)++instance PrimMonad m => SAT.AddPBLin m (Encoder m) where+  addPBAtLeast enc lhs rhs = do+    let (lhs',rhs') = SAT.normalizePBLinAtLeast (lhs,rhs)+    if rhs' == 1 && and [c==1 | (c,_) <- lhs'] then+      SAT.addClause enc [l | (_,l) <- lhs']+    else do+      addPBLinAtLeast' enc (lhs',rhs')++encodePBLinAtLeast :: forall m. PrimMonad m => Encoder m -> SAT.PBLinAtLeast -> m SAT.Lit+encodePBLinAtLeast enc constr =+  encodePBLinAtLeast' enc $ SAT.normalizePBLinAtLeast constr++-- -----------------------------------------------------------------------++addPBLinAtLeast' :: PrimMonad m => Encoder m -> SAT.PBLinAtLeast -> m ()+addPBLinAtLeast' (Encoder tseitin strategy) =+  case strategy of+    Adder -> addPBLinAtLeastAdder tseitin+    Sorter -> addPBLinAtLeastSorter tseitin+    _ -> addPBLinAtLeastBDD tseitin++encodePBLinAtLeast' :: PrimMonad m => Encoder m -> SAT.PBLinAtLeast -> m SAT.Lit+encodePBLinAtLeast' (Encoder tseitin strategy) =+  case strategy of+    Adder -> encodePBLinAtLeastAdder tseitin+    Sorter -> encodePBLinAtLeastSorter tseitin+    _ -> encodePBLinAtLeastBDD tseitin++-- -----------------------------------------------------------------------+
+ src/ToySolver/SAT/Encoder/PB/Internal/Adder.hs view
@@ -0,0 +1,130 @@+{-# LANGUAGE BangPatterns, FlexibleContexts, ScopedTypeVariables #-}+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.SAT.Encoder.PB.Internal.Adder+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable+--+-- References:+--+-- * [ES06] N. Eén and N. Sörensson. Translating Pseudo-Boolean+--   Constraints into SAT. JSAT 2:1–26, 2006.+--+-----------------------------------------------------------------------------+module ToySolver.SAT.Encoder.PB.Internal.Adder+  ( addPBLinAtLeastAdder+  , encodePBLinAtLeastAdder+  ) where++import Control.Monad+import Control.Monad.Primitive+import Data.Bits+import Data.Primitive.MutVar+import Data.Sequence (Seq)+import qualified Data.Sequence as Seq+import ToySolver.Data.Boolean+import ToySolver.Data.BoolExpr+import qualified ToySolver.Internal.Data.SeqQueue as SQ+import qualified ToySolver.SAT.Types as SAT+import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin++addPBLinAtLeastAdder :: forall m. PrimMonad m => Tseitin.Encoder m -> SAT.PBLinAtLeast -> m ()+addPBLinAtLeastAdder enc constr = do+  formula <- encodePBLinAtLeastAdder' enc constr+  Tseitin.addFormula enc formula++encodePBLinAtLeastAdder :: PrimMonad m => Tseitin.Encoder m -> SAT.PBLinAtLeast -> m SAT.Lit+encodePBLinAtLeastAdder enc constr = do+  formula <- encodePBLinAtLeastAdder' enc constr+  Tseitin.encodeFormula enc formula++encodePBLinAtLeastAdder' :: PrimMonad m => Tseitin.Encoder m -> SAT.PBLinAtLeast -> m Tseitin.Formula+encodePBLinAtLeastAdder' _ (_,rhs) | rhs <= 0 = return true+encodePBLinAtLeastAdder' enc (lhs,rhs) = do+  lhs1 <- encodePBLinSumAdder enc lhs+  let rhs1 = bits rhs+  if length lhs1 < length rhs1 then do+    return false+  else do+    let lhs2 = reverse lhs1+        rhs2 = replicate (length lhs1 - length rhs1) False ++ reverse rhs1+        f [] = true+        f ((x,False) : xs) = Atom x .||. f xs+        f ((x,True) : xs) = Atom x .&&. f xs+    return $ f (zip lhs2 rhs2)+  where+    bits :: Integer -> [Bool]+    bits n = f n 0+      where+        f 0 !_ = []+        f n i = testBit n i : f (clearBit n i) (i+1)++encodePBLinSumAdder :: forall m. PrimMonad m => Tseitin.Encoder m -> SAT.PBLinSum -> m [SAT.Lit]+encodePBLinSumAdder enc lhs = do+  (buckets :: MutVar (PrimState m) (Seq (SQ.SeqQueue m SAT.Lit))) <- newMutVar Seq.empty+  let insert i x = do+        bs <- readMutVar buckets+        let n = Seq.length bs+        q <- if i < n then do+               return $ Seq.index bs i+             else do+               qs <- replicateM (i+1 - n) SQ.newFifo+               let bs' = bs Seq.>< Seq.fromList qs+               writeMutVar buckets bs'+               return $ Seq.index bs' i+        SQ.enqueue q x++      bits :: Integer -> [Int]+      bits n = f n 0+        where+          f 0 !_ = []+          f n i+            | testBit n i = i : f (clearBit n i) (i+1)+            | otherwise = f n (i+1)++  forM_ lhs $ \(c,x) -> do+    forM_ (bits c) $ \i -> insert i x++  let loop i ret = do+        bs <- readMutVar buckets+        let n = Seq.length bs+        if i >= n then do+          return $ reverse ret+        else do+          let q = Seq.index bs i+          m <- SQ.queueSize q+          case m of+            0 -> do+              b <- Tseitin.encodeDisj enc [] -- False+              loop (i+1) (b : ret)+            1 -> do+              Just b <- SQ.dequeue q+              loop (i+1) (b : ret)+            2 -> do+              Just b1 <- SQ.dequeue q+              Just b2 <- SQ.dequeue q+              s <- encodeHASum enc b1 b2+              c <- encodeHACarry enc b1 b2+              insert (i+1) c+              loop (i+1) (s : ret)+            _ -> do+              Just b1 <- SQ.dequeue q+              Just b2 <- SQ.dequeue q+              Just b3 <- SQ.dequeue q+              s <- Tseitin.encodeFASum enc b1 b2 b3+              c <- Tseitin.encodeFACarry enc b1 b2 b3+              insert i s+              insert (i+1) c+              loop i ret+  loop 0 []++encodeHASum :: PrimMonad m => Tseitin.Encoder m -> SAT.Lit -> SAT.Lit -> m SAT.Lit+encodeHASum = Tseitin.encodeXOR++encodeHACarry :: PrimMonad m => Tseitin.Encoder m -> SAT.Lit -> SAT.Lit -> m SAT.Lit+encodeHACarry enc a b = Tseitin.encodeConj enc [a,b]
+ src/ToySolver/SAT/Encoder/PB/Internal/BDD.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE ScopedTypeVariables, FlexibleContexts #-}+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.SAT.Encoder.PB.Internal.BDD+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable+--+-- References:+--+-- * [ES06] N. Eén and N. Sörensson. Translating Pseudo-Boolean+--   Constraints into SAT. JSAT 2:1–26, 2006.+--+-----------------------------------------------------------------------------+module ToySolver.SAT.Encoder.PB.Internal.BDD+  ( addPBLinAtLeastBDD+  , encodePBLinAtLeastBDD+  ) where++import Control.Monad.State.Strict+import Control.Monad.Primitive+import Data.Ord+import Data.List+import Data.Map.Strict (Map)+import qualified Data.Map.Strict as Map+import qualified ToySolver.SAT.Types as SAT+import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin++addPBLinAtLeastBDD :: PrimMonad m => Tseitin.Encoder m -> SAT.PBLinAtLeast -> m ()+addPBLinAtLeastBDD enc constr = do+  l <- encodePBLinAtLeastBDD enc constr+  SAT.addClause enc [l]++encodePBLinAtLeastBDD :: forall m. PrimMonad m => Tseitin.Encoder m -> SAT.PBLinAtLeast -> m SAT.Lit+encodePBLinAtLeastBDD enc (lhs,rhs) = do+  let lhs' = sortBy (flip (comparing fst)) lhs+  flip evalStateT Map.empty $ do+    let f :: SAT.PBLinSum -> Integer -> Integer -> StateT (Map (SAT.PBLinSum, Integer) SAT.Lit) m SAT.Lit+        f xs rhs slack+          | rhs <= 0  = lift $ Tseitin.encodeConj enc [] -- true+          | slack < 0 = lift $ Tseitin.encodeDisj enc [] -- false+          | otherwise = do+              m <- get+              case Map.lookup (xs,rhs) m of+                Just l -> return l+                Nothing -> do+                  case xs of+                    [(_,l)] -> return l+                    (c,l) : xs' -> do+                      thenLit <- f xs' (rhs - c) slack+                      l2 <- lift $ Tseitin.encodeConjWithPolarity enc Tseitin.polarityPos [l, thenLit]+                      l3 <- if c > slack then+                              return l2+                            else do+                              elseLit <- f xs' rhs (slack - c)+                              lift $ Tseitin.encodeDisjWithPolarity enc Tseitin.polarityPos [l2, elseLit]+                      modify (Map.insert (xs,rhs) l3)+                      return l3+    f lhs' rhs (sum [c | (c,_) <- lhs'] - rhs)
+ src/ToySolver/SAT/Encoder/PB/Internal/Sorter.hs view
@@ -0,0 +1,229 @@+{-# LANGUAGE ScopedTypeVariables, FlexibleContexts #-}+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.SAT.Encoder.PB.Internal.Sorter+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable+--+-- References:+--+-- * [ES06] N. Eén and N. Sörensson. Translating Pseudo-Boolean+--   Constraints into SAT. JSAT 2:1–26, 2006.+--+-----------------------------------------------------------------------------+module ToySolver.SAT.Encoder.PB.Internal.Sorter+  ( Base+  , UDigit+  , UNumber+  , isRepresentable+  , encode+  , decode++  , Cost+  , optimizeBase++  , genSorterCircuit+  , sortVector++  , addPBLinAtLeastSorter+  , encodePBLinAtLeastSorter+  ) where++import Control.Monad.Primitive+import Control.Monad.State+import Control.Monad.Writer+import Data.List+import Data.Maybe+import Data.Ord+import Data.Vector (Vector, (!))+import qualified Data.Vector as V+import qualified Data.Vector.Mutable as MV+import ToySolver.Data.BoolExpr+import ToySolver.Data.Boolean+import qualified ToySolver.SAT.Types as SAT+import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin++-- ------------------------------------------------------------------------+-- Circuit-like implementation of Batcher's odd-even mergesort++genSorterCircuit :: Int -> [(Int,Int)]+genSorterCircuit len = execWriter (mergeSort (V.iterateN len (+1) 0)) []+  where+    genCompareAndSwap i j = tell ((i,j) :)++    mergeSort is+      | V.length is <= 1 = return ()+      | V.length is == 2 = genCompareAndSwap (is!0) (is!1)+      | otherwise =+          case halve is of+            (is1,is2) -> do+              mergeSort is1+              mergeSort is2+              oddEvenMerge is++    oddEvenMerge is+      | V.length is <= 1 = return ()+      | V.length is == 2 = genCompareAndSwap (is!0) (is!1)+      | otherwise =+          case splitOddEven is of+            (os,es) -> do+              oddEvenMerge os+              oddEvenMerge es+              forM_ [2,3 .. V.length is-1] $ \i -> do+                genCompareAndSwap (is!(i-1)) (is!i)++halve :: Vector a -> (Vector a, Vector a)+halve v+  | V.length v <= 1 = (v, V.empty)+  | otherwise = (V.slice 0 len1 v, V.slice len1 len2 v)+      where+        n = head $ dropWhile (< V.length v) $ iterate (*2) 1+        len1 = n `div` 2+        len2 = V.length v - len1++splitOddEven :: Vector a -> (Vector a, Vector a)+splitOddEven v = (V.generate len1 (\i -> v V.! (i*2+1)), V.generate len2 (\i -> v V.! (i*2)))+  where+    len1 = V.length v `div` 2+    len2 = (V.length v + 1) `div` 2++sortVector :: (Ord a) => Vector a -> Vector a+sortVector v = V.create $ do+  m <- V.thaw v+  forM_ (genSorterCircuit (V.length v)) $ \(i,j) -> do+    vi <- MV.read m i+    vj <- MV.read m j+    when (vi > vj) $ do+      MV.write m i vj+      MV.write m j vi+  return m++-- ------------------------------------------------------------------------++type Base = [Int]+type UDigit = Int+type UNumber = [UDigit]++isRepresentable :: Base -> Integer -> Bool+isRepresentable _ 0 = True+isRepresentable [] x = x <= fromIntegral (maxBound :: UDigit)+isRepresentable (b:bs) x = isRepresentable bs (x `div` fromIntegral b)++encode :: Base -> Integer -> UNumber+encode _ 0 = []+encode [] x+  | x <= fromIntegral (maxBound :: UDigit) = [fromIntegral x]+  | otherwise = undefined+encode (b:bs) x = fromIntegral (x `mod` fromIntegral b) : encode bs (x `div` fromIntegral b)++decode :: Base -> UNumber -> Integer+decode _ [] = 0+decode [] [x] = fromIntegral x+decode (b:bs) (x:xs) = fromIntegral x + fromIntegral b * decode bs xs++{-+test1 = encode [3,5] 164 -- [2,4,10]+test2 = decode [3,5] [2,4,10] -- 164++test3 = optimizeBase [1,1,2,2,3,3,3,3,7]+-}++-- ------------------------------------------------------------------------++type Cost = Integer++primes :: [Int]+primes = [2, 3, 5, 7, 11, 13, 17]++optimizeBase :: [Integer] -> Base+optimizeBase xs = reverse $ fst $ fromJust $ execState (m xs [] 0) Nothing+  where+    m :: [Integer] -> Base -> Integer -> State (Maybe (Base, Cost)) ()+    m xs base cost = do+      let lb = cost + sum [1 | x <- xs, x > 0]+      best <- get+      case best of+        Just (_bestBase, bestCost) | bestCost <= lb -> return ()+        _ -> do+          when (sum xs <= 1024) $ do+            let cost' = cost + sum xs+            case best of+              Just (_bestBase, bestCost) | bestCost < cost' -> return ()+              _ -> put $ Just (base, cost')+          unless (null xs) $ do+            let delta = sortBy (comparing snd) [(p, sum [x `mod` fromIntegral p | x <- xs]) | p <- primes]+            case delta of+              (p,0) : _ -> do+                m [d | x <- xs, let d = x `div` fromIntegral p, d > 0] (p : base) cost+              _ -> do+                forM_ delta $ \(p,s) -> do+                  m [d | x <- xs, let d = x `div` fromIntegral p, d > 0] (p : base) (cost + s)++-- ------------------------------------------------------------------------++addPBLinAtLeastSorter :: PrimMonad m => Tseitin.Encoder m -> SAT.PBLinAtLeast -> m ()+addPBLinAtLeastSorter enc constr = do+  formula <- encodePBLinAtLeastSorter' enc constr+  Tseitin.addFormula enc formula++encodePBLinAtLeastSorter :: PrimMonad m => Tseitin.Encoder m -> SAT.PBLinAtLeast -> m SAT.Lit+encodePBLinAtLeastSorter enc constr = do+  formula <- encodePBLinAtLeastSorter' enc constr+  Tseitin.encodeFormula enc formula++encodePBLinAtLeastSorter' :: PrimMonad m => Tseitin.Encoder m -> SAT.PBLinAtLeast -> m Tseitin.Formula+encodePBLinAtLeastSorter' enc (lhs,rhs) = do+  let base = optimizeBase [c | (c,_) <- lhs]+  if isRepresentable base rhs then do+    sorters <- genSorters enc base [(encode base c, l) | (c,l) <- lhs] []+    return $ lexComp base sorters (encode base rhs)+  else do+    return false++genSorters :: PrimMonad m => Tseitin.Encoder m -> Base -> [(UNumber, SAT.Lit)] -> [SAT.Lit] -> m [Vector SAT.Lit]+genSorters enc base lhs carry = do+  let is = V.fromList carry <> V.concat [V.replicate (fromIntegral d) l | (d:_,l) <- lhs, d /= 0]+  buf <- V.thaw is+  forM_ (genSorterCircuit (V.length is)) $ \(i,j) -> do+    vi <- MV.read buf i+    vj <- MV.read buf j+    MV.write buf i =<< Tseitin.encodeDisj enc [vi,vj]+    MV.write buf j =<< Tseitin.encodeConj enc [vi,vj]+  os <- V.freeze buf+  case base of+    [] -> return [os]+    b:bs -> do+      oss <- genSorters enc bs [(ds,l) | (_:ds,l) <- lhs] [os!(i-1) | i <- takeWhile (<= V.length os) (iterate (+b) b)]+      return $ os : oss++isGE :: Vector SAT.Lit -> Int -> Tseitin.Formula+isGE out lim+  | lim <= 0 = true+  | lim - 1 < V.length out = Atom $ out ! (lim - 1)+  | otherwise = false++isGEMod :: Int -> Vector SAT.Lit -> Int -> Tseitin.Formula+isGEMod _n _out lim | lim <= 0 = true+isGEMod n out lim =+  orB [isGE out (j + lim) .&&. notB isGE out (j + n) | j <- [0, n .. V.length out - 1]]++lexComp :: Base -> [Vector SAT.Lit] -> UNumber -> Tseitin.Formula+lexComp base lhs rhs = f true base lhs rhs+  where+    f ret (b:bs) (out:os) ds = f (gt .||. (ge .&&. ret)) bs os (drop 1 ds)+      where+        d = if null ds then 0 else head ds+        gt = isGEMod b out (d+1)+        ge = isGEMod b out d+    f ret [] [out] ds = gt .||. (ge .&&. ret)+      where+        d = if null ds then 0 else head ds+        gt = isGE out (d+1)+        ge = isGE out d++-- ------------------------------------------------------------------------
+ src/ToySolver/SAT/Encoder/PBNLC.hs view
@@ -0,0 +1,129 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE ExistentialQuantification, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.SAT.Encoder.PBNLC+-- Copyright   :  (c) Masahiro Sakai 2015+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable (ExistentialQuantification, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses)+-- +-----------------------------------------------------------------------------+module ToySolver.SAT.Encoder.PBNLC+  (+  -- * The encoder type+    Encoder+  , newEncoder+  , getTseitinEncoder++  -- * Adding constraints+  , addPBNLAtLeast+  , addPBNLAtMost  +  , addPBNLExactly+  , addPBNLAtLeastSoft+  , addPBNLAtMostSoft+  , addPBNLExactlySoft++  -- * Linearization+  , linearizePBSum+  , linearizePBSumWithPolarity+  ) where++import Control.Monad.Primitive+import ToySolver.SAT.Types as SAT+import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin+import ToySolver.Internal.Util (revForM)++data Encoder m+  = forall a. SAT.AddPBLin m a => Encoder+  { encBase    :: a+  , encTseitin :: Tseitin.Encoder m+  }++instance Monad m => SAT.NewVar m (Encoder m) where+  newVar Encoder{ encBase = a }   = SAT.newVar a+  newVars Encoder{ encBase = a }  = SAT.newVars a+  newVars_ Encoder{ encBase = a } = SAT.newVars_ a++instance Monad m => SAT.AddClause m (Encoder m) where+  addClause Encoder{ encBase = a } = SAT.addClause a++instance Monad m => SAT.AddCardinality m (Encoder m) where+  addAtLeast Encoder{ encBase = a } = SAT.addAtLeast a+  addAtMost  Encoder{ encBase = a } = SAT.addAtMost a+  addExactly Encoder{ encBase = a } = SAT.addExactly a++instance Monad m => SAT.AddPBLin m (Encoder m) where+  addPBAtLeast Encoder{ encBase = a } = SAT.addPBAtLeast a+  addPBAtMost  Encoder{ encBase = a } = SAT.addPBAtMost a+  addPBExactly Encoder{ encBase = a } = SAT.addPBExactly a+  addPBAtLeastSoft Encoder{ encBase = a } = SAT.addPBAtLeastSoft a+  addPBAtMostSoft  Encoder{ encBase = a } = SAT.addPBAtMostSoft a+  addPBExactlySoft Encoder{ encBase = a } = SAT.addPBExactlySoft a++newEncoder :: (SAT.AddPBLin m a) => a -> Tseitin.Encoder m -> m (Encoder m)+newEncoder a tseitin = return $ Encoder a tseitin++getTseitinEncoder :: Encoder m -> Tseitin.Encoder m+getTseitinEncoder Encoder{ encTseitin = tseitin } = tseitin++instance PrimMonad m => SAT.AddPBNL m (Encoder m) where+  addPBNLAtLeast enc lhs rhs = do+    let c = sum [c | (c,[]) <- lhs]+    lhs' <- linearizePBSumWithPolarity enc Tseitin.polarityPos [(c,ls) | (c,ls) <- lhs, not (null ls)]+    SAT.addPBAtLeast enc lhs' (rhs - c)++  addPBNLAtMost enc lhs rhs =+    addPBNLAtLeast enc [(-c,ls) | (c,ls) <- lhs] (negate rhs)++  addPBNLExactly enc lhs rhs = do+    let c = sum [c | (c,[]) <- lhs]+    lhs' <- linearizePBSum enc [(c,ls) | (c,ls) <- lhs, not (null ls)]+    SAT.addPBExactly enc lhs' (rhs - c)++  addPBNLAtLeastSoft enc sel lhs rhs = do+    let c = sum [c | (c,[]) <- lhs]+    lhs' <- linearizePBSumWithPolarity enc Tseitin.polarityPos [(c,ls) | (c,ls) <- lhs, not (null ls)]+    SAT.addPBAtLeastSoft enc sel lhs' (rhs - c)++  addPBNLAtMostSoft enc sel lhs rhs =+    addPBNLAtLeastSoft enc sel [(negate c, lit) | (c,lit) <- lhs] (negate rhs)++  addPBNLExactlySoft enc sel lhs rhs = do+    let c = sum [c | (c,[]) <- lhs]+    lhs' <- linearizePBSum enc [(c,ls) | (c,ls) <- lhs, not (null ls)]+    SAT.addPBExactlySoft enc sel lhs' (rhs - c)++-- | Encode a non-linear 'PBSum' into a lienar 'PBLinSum'.+--+-- @linearizePBSum enc s@ is equivalent to @linearizePBSumWithPolarity enc polarityBoth@.+linearizePBSum+  :: PrimMonad m+  => Encoder m+  -> PBSum+  -> m PBLinSum+linearizePBSum enc = linearizePBSumWithPolarity enc Tseitin.polarityBoth++-- | Linearize a non-linear 'PBSum' into a lienar 'PBLinSum'.+--+-- The input 'PBSum' is assumed to occur only in specified polarity.+--+-- * If @'polarityPosOccurs' p@, the value of resulting 'PBLinSum' is /greater than/ or /equal to/ the value of original 'PBSum'.+--+-- * If @'polarityNegOccurs' p@, the value of resulting 'PBLinSum' is /lesser than/ or /equal to/ the value of original 'PBSum'.+-- +linearizePBSumWithPolarity+  :: PrimMonad m+  => Encoder m+  -> Tseitin.Polarity -- polarity /p/+  -> PBSum+  -> m PBLinSum+linearizePBSumWithPolarity Encoder{ encTseitin = tseitin } p xs =+  revForM xs $ \(c,ls) -> do+    l <- if c > 0 then+           Tseitin.encodeConjWithPolarity tseitin p ls+         else+           Tseitin.encodeConjWithPolarity tseitin (Tseitin.negatePolarity p) ls+    return (c,l)
+ src/ToySolver/SAT/Encoder/Tseitin.hs view
@@ -0,0 +1,471 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE ScopedTypeVariables, FlexibleInstances, MultiParamTypeClasses, ExistentialQuantification #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.SAT.Encoder.Tseitin+-- Copyright   :  (c) Masahiro Sakai 2012+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable (ScopedTypeVariables, FlexibleInstances, MultiParamTypeClasses, ExistentialQuantification)+-- +-- Tseitin encoding+--+-- TODO:+-- +-- * reduce variables.+--+-- References:+--+-- * [Tse83] G. Tseitin. On the complexity of derivation in propositional+--   calculus. Automation of Reasoning: Classical Papers in Computational+--   Logic, 2:466-483, 1983. Springer-Verlag. +--+-- * [For60] R. Fortet. Application de l'algèbre de Boole en rechercheop+--   opérationelle. Revue Française de Recherche Opérationelle, 4:17-26,+--   1960. +--+-- * [BM84a] E. Balas and J. B. Mazzola. Nonlinear 0-1 programming:+--   I. Linearization techniques. Mathematical Programming, 30(1):1-21,+--   1984.+-- +-- * [BM84b] E. Balas and J. B. Mazzola. Nonlinear 0-1 programming:+--   II. Dominance relations and algorithms. Mathematical Programming,+--   30(1):22-45, 1984.+--+-- * [PG86] D. Plaisted and S. Greenbaum. A Structure-preserving+--    Clause Form Translation. In Journal on Symbolic Computation,+--    volume 2, 1986.+--+-- * [ES06] N. Eén and N. Sörensson. Translating Pseudo-Boolean+--   Constraints into SAT. JSAT 2:1–26, 2006.+--+-----------------------------------------------------------------------------+module ToySolver.SAT.Encoder.Tseitin+  (+  -- * The @Encoder@ type+    Encoder+  , newEncoder+  , newEncoderWithPBLin+  , setUsePB++  -- * Polarity+  , Polarity (..)+  , negatePolarity+  , polarityPos+  , polarityNeg+  , polarityBoth+  , polarityNone++  -- * Boolean formula type+  , Formula+  , evalFormula++  -- * Encoding of boolean formulas+  , addFormula+  , encodeFormula+  , encodeFormulaWithPolarity+  , encodeConj+  , encodeConjWithPolarity+  , encodeDisj+  , encodeDisjWithPolarity+  , encodeITE+  , encodeITEWithPolarity+  , encodeXOR+  , encodeXORWithPolarity+  , encodeFASum+  , encodeFASumWithPolarity+  , encodeFACarry+  , encodeFACarryWithPolarity++  -- * Retrieving definitions+  , getDefinitions+  ) where++import Control.Monad+import Control.Monad.Primitive+import Data.Primitive.MutVar+import Data.Map (Map)+import qualified Data.Map as Map+import qualified Data.IntSet as IntSet+import ToySolver.Data.Boolean+import ToySolver.Data.BoolExpr+import qualified ToySolver.SAT.Types as SAT++-- | Arbitrary formula not restricted to CNF+type Formula = BoolExpr SAT.Lit++evalFormula :: SAT.IModel m => m -> Formula -> Bool+evalFormula m = fold (SAT.evalLit m)++-- | Encoder instance+data Encoder m =+  forall a. SAT.AddClause m a =>+  Encoder+  { encBase :: a+  , encAddPBAtLeast :: Maybe (SAT.PBLinSum -> Integer -> m ())+  , encUsePB     :: !(MutVar (PrimState m) Bool)+  , encConjTable :: !(MutVar (PrimState m) (Map SAT.LitSet (SAT.Var, Bool, Bool)))+  , encITETable  :: !(MutVar (PrimState m) (Map (SAT.Lit, SAT.Lit, SAT.Lit) (SAT.Var, Bool, Bool)))+  , encXORTable  :: !(MutVar (PrimState m) (Map (SAT.Lit, SAT.Lit) (SAT.Var, Bool, Bool)))+  , encFASumTable   :: !(MutVar (PrimState m) (Map (SAT.Lit, SAT.Lit, SAT.Lit) (SAT.Var, Bool, Bool)))+  , encFACarryTable :: !(MutVar (PrimState m) (Map (SAT.Lit, SAT.Lit, SAT.Lit) (SAT.Var, Bool, Bool)))+  }++instance Monad m => SAT.NewVar m (Encoder m) where+  newVar   Encoder{ encBase = a } = SAT.newVar a+  newVars  Encoder{ encBase = a } = SAT.newVars a+  newVars_ Encoder{ encBase = a } = SAT.newVars_ a++instance Monad m => SAT.AddClause m (Encoder m) where+  addClause Encoder{ encBase = a } = SAT.addClause a++-- | Create a @Encoder@ instance.+-- If the encoder is built using this function, 'setUsePB' has no effect.+newEncoder :: PrimMonad m => SAT.AddClause m a => a -> m (Encoder m)+newEncoder solver = do+  usePBRef <- newMutVar False+  tableConj <- newMutVar Map.empty+  tableITE <- newMutVar Map.empty+  tableXOR <- newMutVar Map.empty+  tableFASum <- newMutVar Map.empty+  tableFACarry <- newMutVar Map.empty+  return $+    Encoder+    { encBase = solver+    , encAddPBAtLeast = Nothing+    , encUsePB  = usePBRef+    , encConjTable = tableConj+    , encITETable = tableITE+    , encXORTable = tableXOR+    , encFASumTable = tableFASum+    , encFACarryTable = tableFACarry+    }++-- | Create a @Encoder@ instance.+-- If the encoder is built using this function, 'setUsePB' has an effect.+newEncoderWithPBLin :: PrimMonad m => SAT.AddPBLin m a => a -> m (Encoder m)+newEncoderWithPBLin solver = do+  usePBRef <- newMutVar False+  tableConj <- newMutVar Map.empty+  tableITE <- newMutVar Map.empty+  tableXOR <- newMutVar Map.empty+  tableFASum <- newMutVar Map.empty+  tableFACarry <- newMutVar Map.empty+  return $+    Encoder+    { encBase = solver+    , encAddPBAtLeast = Just (SAT.addPBAtLeast solver)+    , encUsePB  = usePBRef+    , encConjTable = tableConj+    , encITETable = tableITE+    , encXORTable = tableXOR+    , encFASumTable = tableFASum+    , encFACarryTable = tableFACarry+    }++-- | Use /pseudo boolean constraints/ or use only /clauses/.+-- This option has an effect only when the encoder is built using 'newEncoderWithPBLin'.+setUsePB :: PrimMonad m => Encoder m -> Bool -> m ()+setUsePB encoder usePB = writeMutVar (encUsePB encoder) usePB++-- | Assert a given formula to underlying SAT solver by using+-- Tseitin encoding.+addFormula :: PrimMonad m => Encoder m -> Formula -> m ()+addFormula encoder formula = do+  case formula of+    And xs -> mapM_ (addFormula encoder) xs+    Equiv a b -> do+      lit1 <- encodeFormula encoder a+      lit2 <- encodeFormula encoder b+      SAT.addClause encoder [SAT.litNot lit1, lit2] -- a→b+      SAT.addClause encoder [SAT.litNot lit2, lit1] -- b→a+    Not (Not a)     -> addFormula encoder a+    Not (Or xs)     -> addFormula encoder (andB (map notB xs))+    Not (Imply a b) -> addFormula encoder (a .&&. notB b)+    Not (Equiv a b) -> do+      lit1 <- encodeFormula encoder a+      lit2 <- encodeFormula encoder b+      SAT.addClause encoder [lit1, lit2] -- a ∨ b+      SAT.addClause encoder [SAT.litNot lit1, SAT.litNot lit2] -- ¬a ∨ ¬b+    ITE c t e -> do+      c' <- encodeFormula encoder c+      t' <- encodeFormulaWithPolarity encoder polarityPos t+      e' <- encodeFormulaWithPolarity encoder polarityPos e+      SAT.addClause encoder [-c', t'] --  c' → t'+      SAT.addClause encoder [ c', e'] -- ¬c' → e'+    _ -> do+      c <- encodeToClause encoder formula+      SAT.addClause encoder c++encodeToClause :: PrimMonad m => Encoder m -> Formula -> m SAT.Clause+encodeToClause encoder formula =+  case formula of+    And [x] -> encodeToClause encoder x+    Or xs -> do+      cs <- mapM (encodeToClause encoder) xs+      return $ concat cs+    Not (Not x)  -> encodeToClause encoder x+    Not (And xs) -> do+      encodeToClause encoder (orB (map notB xs))+    Imply a b -> do+      encodeToClause encoder (notB a .||. b)+    _ -> do+      l <- encodeFormulaWithPolarity encoder polarityPos formula+      return [l]++encodeFormula :: PrimMonad m => Encoder m -> Formula -> m SAT.Lit+encodeFormula encoder = encodeFormulaWithPolarity encoder polarityBoth++encodeWithPolarityHelper+  :: (PrimMonad m, Ord k)+  => Encoder m+  -> MutVar (PrimState m) (Map k (SAT.Var, Bool, Bool))+  -> (SAT.Lit -> m ()) -> (SAT.Lit -> m ())+  -> Polarity+  -> k+  -> m SAT.Var+encodeWithPolarityHelper encoder tableRef definePos defineNeg (Polarity pos neg) k = do+  table <- readMutVar tableRef+  case Map.lookup k table of+    Just (v, posDefined, negDefined) -> do+      when (pos && not posDefined) $ definePos v+      when (neg && not negDefined) $ defineNeg v+      when (posDefined < pos || negDefined < neg) $+        modifyMutVar' tableRef (Map.insert k (v, (max posDefined pos), (max negDefined neg)))+      return v+    Nothing -> do+      v <- SAT.newVar encoder+      when pos $ definePos v+      when neg $ defineNeg v+      modifyMutVar' tableRef (Map.insert k (v, pos, neg))+      return v+++encodeFormulaWithPolarity :: PrimMonad m => Encoder m -> Polarity -> Formula -> m SAT.Lit+encodeFormulaWithPolarity encoder p formula = do+  case formula of+    Atom l -> return l+    And xs -> encodeConjWithPolarity encoder p =<< mapM (encodeFormulaWithPolarity encoder p) xs+    Or xs  -> encodeDisjWithPolarity encoder p =<< mapM (encodeFormulaWithPolarity encoder p) xs+    Not x -> liftM SAT.litNot $ encodeFormulaWithPolarity encoder (negatePolarity p) x+    Imply x y -> do+      encodeFormulaWithPolarity encoder p (notB x .||. y)+    Equiv x y -> do+      lit1 <- encodeFormulaWithPolarity encoder polarityBoth x+      lit2 <- encodeFormulaWithPolarity encoder polarityBoth y+      encodeFormulaWithPolarity encoder p $+        (Atom lit1 .=>. Atom lit2) .&&. (Atom lit2 .=>. Atom lit1)+    ITE c t e -> do+      c' <- encodeFormulaWithPolarity encoder polarityBoth c+      t' <- encodeFormulaWithPolarity encoder p t+      e' <- encodeFormulaWithPolarity encoder p e+      encodeITEWithPolarity encoder p c' t' e'++-- | Return an literal which is equivalent to a given conjunction.+--+-- @+--   encodeConj encoder = 'encodeConjWithPolarity' encoder 'polarityBoth'+-- @+encodeConj :: PrimMonad m => Encoder m -> [SAT.Lit] -> m SAT.Lit+encodeConj encoder = encodeConjWithPolarity encoder polarityBoth++-- | Return an literal which is equivalent to a given conjunction which occurs only in specified polarity.+encodeConjWithPolarity :: forall m. PrimMonad m => Encoder m -> Polarity -> [SAT.Lit] -> m SAT.Lit+encodeConjWithPolarity _ _ [l] =  return l+encodeConjWithPolarity encoder polarity ls = do+  usePB <- readMutVar (encUsePB encoder)+  table <- readMutVar (encConjTable encoder)+  let ls3 = IntSet.fromList ls+      ls2 = case Map.lookup IntSet.empty table of+              Nothing -> ls3+              Just (litTrue, _, _)+                | litFalse `IntSet.member` ls3 -> IntSet.singleton litFalse+                | otherwise -> IntSet.delete litTrue ls3+                where litFalse = SAT.litNot litTrue++  if IntSet.size ls2 == 1 then do+    return $ head $ IntSet.toList ls2+  else do+    let -- If F is monotone, F(A ∧ B) ⇔ ∃x. F(x) ∧ (x → A∧B)+        definePos :: SAT.Lit -> m ()+        definePos l = do+          case encAddPBAtLeast encoder of+            Just addPBAtLeast | usePB -> do+              -- ∀i.(l → li) ⇔ Σli >= n*l ⇔ Σli - n*l >= 0+              let n = IntSet.size ls2+              addPBAtLeast ((- fromIntegral n, l) : [(1,li) | li <- IntSet.toList ls2]) 0+            _ -> do+              forM_ (IntSet.toList ls2) $ \li -> do+                -- (l → li)  ⇔  (¬l ∨ li)+                SAT.addClause encoder [SAT.litNot l, li]+        -- If F is anti-monotone, F(A ∧ B) ⇔ ∃x. F(x) ∧ (x ← A∧B) ⇔ ∃x. F(x) ∧ (x∨¬A∨¬B).+        defineNeg :: SAT.Lit -> m ()+        defineNeg l = do+          -- ((l1 ∧ l2 ∧ … ∧ ln) → l)  ⇔  (¬l1 ∨ ¬l2 ∨ … ∨ ¬ln ∨ l)+          SAT.addClause encoder (l : map SAT.litNot (IntSet.toList ls2))+    encodeWithPolarityHelper encoder (encConjTable encoder) definePos defineNeg polarity ls2++-- | Return an literal which is equivalent to a given disjunction.+--+-- @+--   encodeDisj encoder = 'encodeDisjWithPolarity' encoder 'polarityBoth'+-- @+encodeDisj :: PrimMonad m => Encoder m -> [SAT.Lit] -> m SAT.Lit+encodeDisj encoder = encodeDisjWithPolarity encoder polarityBoth++-- | Return an literal which is equivalent to a given disjunction which occurs only in specified polarity.+encodeDisjWithPolarity :: PrimMonad m => Encoder m -> Polarity -> [SAT.Lit] -> m SAT.Lit+encodeDisjWithPolarity _ _ [l] =  return l+encodeDisjWithPolarity encoder p ls = do+  -- ¬l ⇔ ¬(¬l1 ∧ … ∧ ¬ln) ⇔ (l1 ∨ … ∨ ln)+  l <- encodeConjWithPolarity encoder (negatePolarity p) [SAT.litNot li | li <- ls]+  return $ SAT.litNot l++-- | Return an literal which is equivalent to a given if-then-else.+--+-- @+--   encodeITE encoder = 'encodeITEWithPolarity' encoder 'polarityBoth'+-- @+encodeITE :: PrimMonad m => Encoder m -> SAT.Lit -> SAT.Lit -> SAT.Lit -> m SAT.Lit+encodeITE encoder = encodeITEWithPolarity encoder polarityBoth++-- | Return an literal which is equivalent to a given if-then-else which occurs only in specified polarity.+encodeITEWithPolarity :: forall m. PrimMonad m => Encoder m -> Polarity -> SAT.Lit -> SAT.Lit -> SAT.Lit -> m SAT.Lit+encodeITEWithPolarity encoder p c t e | c < 0 =+  encodeITEWithPolarity encoder p (- c) e t+encodeITEWithPolarity encoder polarity c t e = do+  let definePos :: SAT.Lit -> m ()+      definePos x = do+        -- x → ite(c,t,e)+        -- ⇔ x → (c∧t ∨ ¬c∧e)+        -- ⇔ (x∧c → t) ∧ (x∧¬c → e)+        -- ⇔ (¬x∨¬c∨t) ∧ (¬x∨c∨e)+        SAT.addClause encoder [-x, -c, t]+        SAT.addClause encoder [-x, c, e]+        SAT.addClause encoder [t, e, -x] -- redundant, but will increase the strength of unit propagation.+  +      defineNeg :: SAT.Lit -> m ()+      defineNeg x = do+        -- ite(c,t,e) → x+        -- ⇔ (c∧t ∨ ¬c∧e) → x+        -- ⇔ (c∧t → x) ∨ (¬c∧e →x)+        -- ⇔ (¬c∨¬t∨x) ∨ (c∧¬e∨x)+        SAT.addClause encoder [-c, -t, x]+        SAT.addClause encoder [c, -e, x]+        SAT.addClause encoder [-t, -e, x] -- redundant, but will increase the strength of unit propagation.++  encodeWithPolarityHelper encoder (encITETable encoder) definePos defineNeg polarity (c,t,e)++-- | Return an literal which is equivalent to an XOR of given two literals.+--+-- @+--   encodeXOR encoder = 'encodeXORWithPolarity' encoder 'polarityBoth'+-- @+encodeXOR :: PrimMonad m => Encoder m -> SAT.Lit -> SAT.Lit -> m SAT.Lit+encodeXOR encoder = encodeXORWithPolarity encoder polarityBoth++-- | Return an literal which is equivalent to an XOR of given two literals which occurs only in specified polarity.+encodeXORWithPolarity :: forall m. PrimMonad m => Encoder m -> Polarity -> SAT.Lit -> SAT.Lit -> m SAT.Lit+encodeXORWithPolarity encoder polarity a b = do+  let defineNeg x = do+        -- (a ⊕ b) → x+        SAT.addClause encoder [a, -b, x]   -- ¬a ∧  b → x+        SAT.addClause encoder [-a, b, x]   --  a ∧ ¬b → x+      definePos x = do+        -- x → (a ⊕ b)+        SAT.addClause encoder [a, b, -x]   -- ¬a ∧ ¬b → ¬x+        SAT.addClause encoder [-a, -b, -x] --  a ∧  b → ¬x+  encodeWithPolarityHelper encoder (encXORTable encoder) definePos defineNeg polarity (a,b)++-- | Return an "sum"-pin of a full-adder.+--+-- @+--   encodeFASum encoder = 'encodeFASumWithPolarity' encoder 'polarityBoth'+-- @+encodeFASum :: forall m. PrimMonad m => Encoder m -> SAT.Lit -> SAT.Lit -> SAT.Lit -> m SAT.Lit+encodeFASum encoder = encodeFASumWithPolarity encoder polarityBoth++-- | Return an "sum"-pin of a full-adder which occurs only in specified polarity.+encodeFASumWithPolarity :: forall m. PrimMonad m => Encoder m -> Polarity -> SAT.Lit -> SAT.Lit -> SAT.Lit -> m SAT.Lit+encodeFASumWithPolarity encoder polarity a b c = do+  let defineNeg x = do+        -- FASum(a,b,c) → x+        SAT.addClause encoder [-a,-b,-c,x] --  a ∧  b ∧  c → x+        SAT.addClause encoder [-a,b,c,x]   --  a ∧ ¬b ∧ ¬c → x+        SAT.addClause encoder [a,-b,c,x]   -- ¬a ∧  b ∧ ¬c → x+        SAT.addClause encoder [a,b,-c,x]   -- ¬a ∧ ¬b ∧  c → x+      definePos x = do+        -- x → FASum(a,b,c)+        -- ⇔ ¬FASum(a,b,c) → ¬x+        SAT.addClause encoder [a,b,c,-x]   -- ¬a ∧ ¬b ∧ ¬c → -x+        SAT.addClause encoder [a,-b,-c,-x] -- ¬a ∧  b ∧  c → -x+        SAT.addClause encoder [-a,b,-c,-x] --  a ∧ ¬b ∧  c → -x+        SAT.addClause encoder [-a,-b,c,-x] --  a ∧  b ∧ ¬c → -x+  encodeWithPolarityHelper encoder (encFASumTable encoder) definePos defineNeg polarity (a,b,c)++-- | Return an "carry"-pin of a full-adder.+--+-- @+--   encodeFACarry encoder = 'encodeFACarryWithPolarity' encoder 'polarityBoth'+-- @+encodeFACarry :: forall m. PrimMonad m => Encoder m -> SAT.Lit -> SAT.Lit -> SAT.Lit -> m SAT.Lit+encodeFACarry encoder = encodeFACarryWithPolarity encoder polarityBoth++-- | Return an "carry"-pin of a full-adder which occurs only in specified polarity.+encodeFACarryWithPolarity :: forall m. PrimMonad m => Encoder m -> Polarity -> SAT.Lit -> SAT.Lit -> SAT.Lit -> m SAT.Lit+encodeFACarryWithPolarity encoder polarity a b c = do+  let defineNeg x = do+        -- FACarry(a,b,c) → x+        SAT.addClause encoder [-a,-b,x] -- a ∧ b → x+        SAT.addClause encoder [-a,-c,x] -- a ∧ c → x+        SAT.addClause encoder [-b,-c,x] -- b ∧ c → x+      definePos x = do+        -- x → FACarry(a,b,c)+        -- ⇔ ¬FACarry(a,b,c) → ¬x+        SAT.addClause encoder [a,b,-x]  --  ¬a ∧ ¬b → ¬x+        SAT.addClause encoder [a,c,-x]  --  ¬a ∧ ¬c → ¬x+        SAT.addClause encoder [b,c,-x]  --  ¬b ∧ ¬c → ¬x+  encodeWithPolarityHelper encoder (encFACarryTable encoder) definePos defineNeg polarity (a,b,c)+++getDefinitions :: PrimMonad m => Encoder m -> m [(SAT.Var, Formula)]+getDefinitions encoder = do+  tableConj <- readMutVar (encConjTable encoder)+  tableITE <- readMutVar (encITETable encoder)+  tableXOR <- readMutVar (encXORTable encoder)+  tableFASum <- readMutVar (encFASumTable encoder)+  tableFACarry <- readMutVar (encFACarryTable encoder)+  let m1 = [(v, andB [Atom l1 | l1 <- IntSet.toList ls]) | (ls, (v, _, _)) <- Map.toList tableConj]+      m2 = [(v, ite (Atom c) (Atom t) (Atom e)) | ((c,t,e), (v, _, _)) <- Map.toList tableITE]+      m3 = [(v, (Atom a .||. Atom b) .&&. (Atom (-a) .||. Atom (-b))) | ((a,b), (v, _, _)) <- Map.toList tableXOR]+      m4 = [(v, orB [andB [Atom l | l <- ls] | ls <- [[a,b,c],[a,-b,-c],[-a,b,-c],[-a,-b,c]]])+             | ((a,b,c), (v, _, _)) <- Map.toList tableFASum]+      m5 = [(v, orB [andB [Atom l | l <- ls] | ls <- [[a,b],[a,c],[b,c]]])+             | ((a,b,c), (v, _, _)) <- Map.toList tableFACarry]+  return $ concat [m1, m2, m3, m4, m5]+++data Polarity+  = Polarity+  { polarityPosOccurs :: Bool+  , polarityNegOccurs :: Bool+  }+  deriving (Eq, Show)++negatePolarity :: Polarity -> Polarity+negatePolarity (Polarity pos neg) = (Polarity neg pos)++polarityPos :: Polarity+polarityPos = Polarity True False++polarityNeg :: Polarity+polarityNeg = Polarity False True++polarityBoth :: Polarity+polarityBoth = Polarity True True++polarityNone :: Polarity+polarityNone = Polarity False False+
+ src/ToySolver/SAT/ExistentialQuantification.hs view
@@ -0,0 +1,143 @@+{-# Language BangPatterns #-}+{-# OPTIONS_GHC -Wall #-}+-- -------------------------------------------------------------------+-- |+-- Module      :  ToySolver.SAT.ExistentialQuantification+-- Copyright   :  (c) Masahiro Sakai 2017+-- License     :  BSD-style+--+-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable+--+-- References:+--+-- * [BrauerKingKriener2011] Jörg Brauer, Andy King, and Jael Kriener,+--   "Existential quantification as incremental SAT," in Computer Aided+--   Verification (CAV 2011), G. Gopalakrishnan and S. Qadeer, Eds.+--   pp. 191-207.+--   <https://www.embedded.rwth-aachen.de/lib/exe/fetch.php?media=bib:bkk11a.pdf>+--+-- -------------------------------------------------------------------++module ToySolver.SAT.ExistentialQuantification+  ( project+  , shortestImplicants+  ) where++import Control.Applicative+import Control.Monad+import qualified Data.IntMap as IntMap+import qualified Data.IntSet as IntSet+import Data.IORef+import ToySolver.SAT as SAT+import ToySolver.SAT.Types as SAT+import ToySolver.Text.CNF as CNF++-- -------------------------------------------------------------------++data Info+  = Info+  { forwardMap :: SAT.VarMap (SAT.Var, SAT.Var)+  , backwardMap :: SAT.VarMap SAT.Lit+  }++dualRailEncoding :: SAT.VarSet -> CNF.CNF -> (CNF.CNF, Info)+dualRailEncoding vs cnf =+  ( cnf'+  , Info+    { forwardMap = forward+    , backwardMap = backward+    }+  )+  where+    cnf' =+      CNF.CNF+      { CNF.numVars = CNF.numVars cnf + IntSet.size vs+      , CNF.numClauses = CNF.numClauses cnf + IntSet.size vs+      , CNF.clauses = [ fmap f c | c <- CNF.clauses cnf ] ++ [[-xp,-xn] | (xp,xn) <- IntMap.elems forward]+      }+    f x =+      case IntMap.lookup (abs x) forward of+        Nothing -> x+        Just (xp,xn) -> if x > 0 then xp else xn+    forward =+      IntMap.fromList+      [ (x, (x,x'))+      | (x,x') <- zip (IntSet.toList vs) [CNF.numVars cnf + 1 ..]+      ]+    backward = IntMap.fromList $ concat $+      [ [(xp,x), (xn,-x)]+      | (x, (xp,xn)) <- IntMap.toList forward+      ]++{-+forwardLit :: Info -> Lit -> Lit+forwardLit info l =+  case IntMap.lookup (abs l) (forwardMap info) of+    Nothing -> l+    Just (xp,xn) -> if l > 0 then xp else xn+-}++-- -------------------------------------------------------------------++cube :: Info -> SAT.Model -> LitSet+cube info m = IntSet.fromList $ concat $+  [ if SAT.evalLit m xp then [x]+    else if SAT.evalLit m xn then [-x]+    else []+  | (x, (xp,xn)) <- IntMap.toList (forwardMap info)+  ]++blockingClause :: Info -> SAT.Model -> Clause+blockingClause info m = [-y | y <- IntMap.keys (backwardMap info), SAT.evalLit m y]++shortestImplicants :: SAT.VarSet -> CNF.CNF -> IO [LitSet]+shortestImplicants vs formula = do+  let (tau_formula, info) = dualRailEncoding vs formula+  solver <- SAT.newSolver+  SAT.newVars_ solver (CNF.numVars tau_formula)+  forM_ (CNF.clauses tau_formula) (addClause solver)++  ref <- newIORef []++  let lim = IntMap.size (forwardMap info)++      loop !n | n > lim = return ()+      loop !n = do+        sel <- SAT.newVar solver+        SAT.addPBAtMostSoft solver sel [(1,l) | l <- IntMap.keys (backwardMap info)] (fromIntegral n)+        let loop2 = do+              b <- SAT.solveWith solver [sel]+              when b $ do+                m <- SAT.getModel solver+                let c = cube info m+                modifyIORef ref (c:)+                SAT.addClause solver (blockingClause info m)+                loop2+        loop2+        SAT.addClause solver [-sel]+        loop (n+1)++  loop 0+  reverse <$> readIORef ref++project :: SAT.VarSet -> CNF.CNF -> IO CNF.CNF+project xs cnf = do+  let ys = IntSet.fromList [1 .. CNF.numVars cnf] IntSet.\\ xs+      nv = if IntSet.null ys then 0 else IntSet.findMax ys+  implicants <- shortestImplicants ys cnf+  let cnf' =+        CNF.CNF+        { CNF.numVars = nv+        , CNF.numClauses = length implicants+        , CNF.clauses = map (map negate . IntSet.toList) implicants+        }+  negated_implicates <- shortestImplicants ys cnf'+  let implicates = map (map negate . IntSet.toList) negated_implicates+  return $+    CNF.CNF+    { CNF.numVars = nv+    , CNF.numClauses = length implicates+    , CNF.clauses = implicates+    }
− src/ToySolver/SAT/Integer.hs
@@ -1,95 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-module ToySolver.SAT.Integer-  ( Expr (..)-  , newVar-  , linearize-  , addConstraint-  , addConstraintSoft-  , eval-  ) where--import Control.Monad-import Data.Array.IArray-import Data.VectorSpace-import Text.Printf--import ToySolver.Data.OrdRel-import qualified ToySolver.SAT as SAT-import qualified ToySolver.SAT.Types as SAT-import qualified ToySolver.SAT.TseitinEncoder as TseitinEncoder-import qualified ToySolver.SAT.PBNLC as PBNLC--newtype Expr = Expr PBNLC.PBSum--newVar :: SAT.Solver -> Integer -> Integer -> IO Expr-newVar solver lo hi-  | lo > hi = do-      SAT.addClause solver [] -- assert inconsistency-      return 0-  | lo == hi = return $ fromInteger lo-  | otherwise = do-      let hi' = hi - lo-          bitWidth = head $ [w | w <- [1..], let mx = 2 ^ w - 1, hi' <= mx]-      vs <- SAT.newVars solver bitWidth-      let xs = zip (iterate (2*) 1) vs-      SAT.addPBAtMost solver xs hi'-      return $ Expr ((lo,[]) : [(c,[x]) | (c,x) <- xs])--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)-  Expr xs1 * Expr xs2 = Expr [(c1*c2, lits1++lits2) | (c1,lits1) <- xs1, (c2,lits2) <- xs2]-  negate (Expr xs) = Expr [(-c,lits) | (c,lits) <- xs]-  abs      = id-  signum _ = 1-  fromInteger c = Expr [(c,[])]--linearize :: TseitinEncoder.Encoder -> Expr -> IO (SAT.PBLinSum, Integer)-linearize enc (Expr xs) = do-  let ys = [(c,lits) | (c,lits@(_:_)) <- xs]-      c  = sum [c | (c,[]) <- xs]-  zs <- PBNLC.linearizePBSum enc ys-  return (zs, c)--addConstraint :: TseitinEncoder.Encoder -> OrdRel Expr -> IO ()-addConstraint enc (OrdRel lhs op rhs) = do-  let solver = TseitinEncoder.encSolver enc-  let Expr e = lhs - rhs-  case op of-    Le  -> PBNLC.addPBAtMost  enc e 0-    Lt  -> PBNLC.addPBAtMost  enc e (-1)-    Ge  -> PBNLC.addPBAtLeast enc e 0-    Gt  -> PBNLC.addPBAtLeast enc e 1-    Eql -> PBNLC.addPBExactly enc e 0-    NEq -> do-      sel <- SAT.newVar solver-      PBNLC.addPBAtLeastSoft enc sel e 1-      PBNLC.addPBAtMostSoft  enc (-sel) e (-1)--addConstraintSoft :: TseitinEncoder.Encoder -> SAT.Lit -> OrdRel Expr -> IO ()-addConstraintSoft enc sel (OrdRel lhs op rhs) = do-  let solver = TseitinEncoder.encSolver enc-  let Expr e = lhs - rhs-  case op of-    Le  -> PBNLC.addPBAtMostSoft  enc sel e 0-    Lt  -> PBNLC.addPBAtMostSoft  enc sel e (-1)-    Ge  -> PBNLC.addPBAtLeastSoft enc sel e 0-    Gt  -> PBNLC.addPBAtLeastSoft enc sel e 1-    Eql -> PBNLC.addPBExactlySoft enc sel e 0-    NEq -> do-      sel2 <- SAT.newVar solver-      sel3 <- TseitinEncoder.encodeConjWithPolarity enc TseitinEncoder.polarityNeg [sel,sel2]-      sel4 <- TseitinEncoder.encodeConjWithPolarity enc TseitinEncoder.polarityNeg [sel,-sel2]-      PBNLC.addPBAtLeastSoft enc sel3 e 1-      PBNLC.addPBAtMostSoft  enc sel4 e (-1)--eval :: SAT.IModel m => m -> Expr -> Integer-eval m (Expr ts) = sum [if and [SAT.evalLit m lit | lit <- lits] then n else 0 | (n,lits) <- ts]
src/ToySolver/SAT/MUS.hs view
@@ -1,3 +1,4 @@+{-# OPTIONS_GHC -Wall #-} ----------------------------------------------------------------------------- -- | -- Module      :  ToySolver.SAT.MUS@@ -10,38 +11,41 @@ -- -- Minimal Unsatifiable Subset (MUS) Finder --+-- References:+--+-- * Ulrich Junker. QuickXplain: Preferred explanations and relaxations for+--   over-constrained problems. In Proc. of AAAI’04, pages 167-172, 2004.+--   <http://www.aaai.org/Papers/AAAI/2004/AAAI04-027.pdf>+-- ----------------------------------------------------------------------------- module ToySolver.SAT.MUS   ( module ToySolver.SAT.MUS.Types+  , Method (..)+  , showMethod+  , parseMethod   , Options (..)   , findMUSAssumptions   ) where -import Control.Monad-import Data.Default.Class-import Data.List-import qualified Data.IntSet as IS+import Data.Char import qualified ToySolver.SAT as SAT-import ToySolver.SAT.Types+import ToySolver.SAT.MUS.Base import ToySolver.SAT.MUS.Types+import qualified ToySolver.SAT.MUS.Deletion as Deletion+import qualified ToySolver.SAT.MUS.Insertion as Insertion+import qualified ToySolver.SAT.MUS.QuickXplain as QuickXplain --- | Options for 'findMUSAssumptions' function------ The default value can be obtained by 'def'.-data Options-  = Options-  { optLogger     :: String -> IO ()-  , optUpdateBest :: [Lit] -> IO ()-  , optLitPrinter :: Lit -> String-  }+showMethod :: Method -> String+showMethod m = map toLower (show m) -instance Default Options where-  def =-    Options-    { optLogger     = \_ -> return ()-    , optUpdateBest = \_ -> return ()-    , optLitPrinter = show-    }+parseMethod :: String -> Maybe Method+parseMethod s =+  case map toLower s of+    "linear" -> Just Deletion+    "deletion" -> Just Deletion+    "insertion" -> Just Insertion+    "quickxplain" -> Just QuickXplain+    _ -> Nothing  -- | Find a minimal set of assumptions that causes a conflict. -- Initial set of assumptions is taken from 'SAT.getFailedAssumptions'.@@ -49,46 +53,8 @@   :: SAT.Solver   -> Options   -> IO MUS-findMUSAssumptions solver opt = do-  log "computing a minimal unsatisfiable core"-  core <- liftM IS.fromList $ SAT.getFailedAssumptions solver-  update $ IS.toList core-  log $ "core = " ++ showLits core-  loop core IS.empty--  where-    log :: String -> IO ()-    log = optLogger opt--    update :: [Lit] -> IO ()-    update = optUpdateBest opt--    showLit :: Lit -> String-    showLit = optLitPrinter opt--    showLits :: IS.IntSet -> String-    showLits ls = "{" ++ intercalate ", " (map showLit (IS.toList ls)) ++ "}"--    loop :: IS.IntSet -> IS.IntSet -> IO MUS-    loop ls1 fixed = do-      case IS.minView ls1 of-        Nothing -> do-          log $ "found a minimal unsatisfiable core"-          return fixed-        Just (l,ls) -> do-          log $ "trying to remove " ++ showLit l-          ret <- SAT.solveWith solver (IS.toList ls)-          if not ret-            then do-              ls2 <- liftM IS.fromList $ SAT.getFailedAssumptions solver-              let removed = ls1 `IS.difference` ls2-              log $ "successed to remove " ++ showLits removed-              log $ "new core = " ++ showLits (ls2 `IS.union` fixed)-              update $ IS.toList ls2-              forM_ (IS.toList removed) $ \l ->-                SAT.addClause solver [-l]-              loop ls2 fixed-            else do-              log $ "failed to remove " ++ showLit l-              SAT.addClause solver [l]-              loop ls (IS.insert l fixed)+findMUSAssumptions solver opt =+  case optMethod opt of+    Deletion -> Deletion.findMUSAssumptions solver opt+    Insertion -> Insertion.findMUSAssumptions solver opt+    QuickXplain -> QuickXplain.findMUSAssumptions solver opt
+ src/ToySolver/SAT/MUS/Base.hs view
@@ -0,0 +1,57 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.SAT.MUS.Base+-- Copyright   :  (c) Masahiro Sakai 2012+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+--+-----------------------------------------------------------------------------+module ToySolver.SAT.MUS.Base+  ( module ToySolver.SAT.MUS.Types+  , Method (..)+  , Options (..)+  ) where++import Control.Monad+import Data.Default.Class+import Data.List+import qualified Data.IntSet as IS+import qualified ToySolver.SAT as SAT+import ToySolver.SAT.Types+import ToySolver.SAT.MUS.Types++data Method+  = Deletion+  | Insertion+  | QuickXplain+  deriving (Eq, Ord, Enum, Bounded, Show)++-- | Options for MUS finding.+--+-- The default value can be obtained by 'def'.+data Options+  = Options+  { optMethod     :: Method+  , optLogger     :: String -> IO ()+  , optShowLit    :: Lit -> String+  , optEvalConstr :: SAT.Model -> Lit -> Bool+    -- ^ Because each soft constraint /C_i/ is represented as a selector+    -- literal /l_i/ together with a hard constraint /l_i ⇒ C_i/, there+    -- are cases that a model assigns false to /l_i/ even though /C_i/+    -- itself is true. This function is used to inform the truth value+    -- of the original constraint /C_i/ that corresponds to the selector+    -- literal /l_i/.+  , optUpdateBest :: US -> IO ()+  }++instance Default Options where+  def =+    Options+    { optMethod     = Deletion+    , optLogger     = \_ -> return ()+    , optShowLit    = show+    , optEvalConstr = SAT.evalLit+    , optUpdateBest = \_ -> return ()+    }
− src/ToySolver/SAT/MUS/CAMUS.hs
@@ -1,147 +0,0 @@--------------------------------------------------------------------------------- |--- Module      :  ToySolver.SAT.MUS.CAMUS--- Copyright   :  (c) Masahiro Sakai 2012-2014--- License     :  BSD-style--- --- Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  provisional--- Portability :  portable------ In this module, we assume each soft constraint /C_i/ is represented as a literal.--- If a constraint /C_i/ is not a literal, we can represent it as a fresh variable /v/--- together with a hard constraint /v ⇒ C_i/.------ References:------ * [CAMUS] M. Liffiton and K. Sakallah, Algorithms for computing minimal---   unsatisfiable subsets of constraints, Journal of Automated Reasoning,---   vol. 40, no. 1, pp. 1-33, Jan. 2008. ---   <http://sun.iwu.edu/~mliffito/publications/jar_liffiton_CAMUS.pdf>------ * [HYCAM] A. Gregoire, B. Mazure, and C. Piette, Boosting a complete---   technique to find MSS and MUS: thanks to a local search oracle, in---   Proceedings of the 20th international joint conference on Artifical---   intelligence, ser. IJCAI'07. San Francisco, CA, USA: Morgan Kaufmann---   Publishers Inc., 2007, pp. 2300-2305.---   <http://ijcai.org/papers07/Papers/IJCAI07-370.pdf>----------------------------------------------------------------------------------module ToySolver.SAT.MUS.CAMUS-  ( module ToySolver.SAT.MUS.Types-  , Options (..)-  , allMCSAssumptions-  , allMUSAssumptions-  , enumMCSAssumptions-  , camus-  ) where--import Control.Monad-import Data.Array.IArray-import Data.Default.Class-import qualified Data.IntSet as IS-import Data.List-import Data.IORef-import Data.Set (Set)-import qualified Data.Set as Set-import qualified ToySolver.Combinatorial.HittingSet.Simple as HittingSet-import qualified ToySolver.SAT as SAT-import ToySolver.SAT.Types-import ToySolver.SAT.MUS.Types---- | Options for 'enumMCSAssumptions', 'allMCSAssumptions', 'allMUSAssumptions'------ The default value can be obtained by 'def'.-data Options-  = Options-  { optLogger     :: String -> IO ()-  , optOnMCSFound :: MCS -> IO ()-  , optOnMUSFound :: MUS -> IO ()-  , optKnownMCSes :: [MCS]-  , optKnownMUSes :: [MUS]-  , optKnownCSes  :: [CS]-    -- ^ MCS candidates (see HYCAM paper for details).-    -- A MCS candidate must be a superset of a real MCS.-  }--instance Default Options where-  def =-    Options-    { optLogger     = \_ -> return ()-    , optOnMCSFound = \_ -> return ()-    , optOnMUSFound = \_ -> return ()-    , optKnownMCSes = []-    , optKnownMUSes = []-    , optKnownCSes = []-    }--enumMCSAssumptions :: SAT.Solver -> [Lit] -> Options -> IO ()-enumMCSAssumptions solver sels opt = do-  candRef <- newIORef [(IS.size cs, cs) | cs <- optKnownCSes opt]-  loop candRef 1--  where-    log :: String -> IO ()-    log = optLogger opt--    mcsFound :: MCS -> IO ()-    mcsFound mcs = do-      optOnMCSFound opt mcs-      SAT.addClause solver (IS.toList mcs)--    loop :: IORef [(Int, LitSet)] -> Int -> IO ()-    loop candRef k = do-      log $ "CAMUS: k = " ++ show k-      cand <- readIORef candRef--      ret <- if not (null cand) then return True else SAT.solve solver-      when ret $ do-        forM_ cand $ \(size,cs) -> do-          when (size == k) $ do-            -- If a candidate MCS is not superset of already obtained MCS,-            -- we are sure that it is actually an MCS.-            mcsFound cs-        writeIORef candRef [(size,cs) | (size,cs) <- cand, size /= k]--        vk <- SAT.newVar solver-        SAT.addPBAtMostSoft solver vk [(1,-sel) | sel <- sels] (fromIntegral k)-        let loop2 = do-              ret2 <- SAT.solveWith solver [vk]-              when ret2 $ do-                m <- SAT.getModel solver-                let mcs = IS.fromList [sel | sel <- sels, not (evalLit m sel)]-                mcsFound mcs-                modifyIORef candRef (filter (\(_,cs) -> not (mcs `IS.isSubsetOf` cs)))-                loop2-        loop2-        SAT.addClause solver [-vk]-        loop candRef (k+1)--allMCSAssumptions :: SAT.Solver -> [Lit] -> Options -> IO [MCS]-allMCSAssumptions solver sels opt = do-  ref <- newIORef []  -  let opt2 =-        opt-        { optOnMCSFound = \mcs -> do-            modifyIORef ref (mcs:)-            optOnMCSFound opt mcs-        }-  enumMCSAssumptions solver sels opt2-  readIORef ref--allMUSAssumptions :: SAT.Solver -> [Lit] -> Options -> IO [MUS]-allMUSAssumptions solver sels opt = do-  (muses, _mcses) <- camus solver sels opt-  return $ muses--camus :: SAT.Solver -> [Lit] -> Options -> IO ([MUS], [MCS])-camus solver sels opt = do-  log "CAMUS: MCS enumeration begins"-  mcses <- allMCSAssumptions solver sels opt-  log "CAMUS: MCS enumeration done"-  let muses = HittingSet.enumMinimalHittingSets $ Set.fromList mcses-  mapM_ (optOnMUSFound opt) muses-  return (muses, mcses)-  where-    log :: String -> IO ()-    log = optLogger opt
− src/ToySolver/SAT/MUS/DAA.hs
@@ -1,127 +0,0 @@-{-# OPTIONS_GHC -Wall #-}---------------------------------------------------------------------------------- |--- Module      :  ToySolver.SAT.MUS.DAA--- Copyright   :  (c) Masahiro Sakai 2014--- License     :  BSD-style--- --- Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  provisional--- Portability :  portable------ "Dualize and Advance" algorithm for finding minimal unsatisfiable sets.------ * [DAA] J. Bailey and P. Stuckey, Discovery of minimal unsatisfiable---   subsets of constraints using hitting set dualization," in Practical---   Aspects of Declarative Languages, pp. 174-186, 2005.---   <http://ww2.cs.mu.oz.au/~pjs/papers/padl05.pdf>----------------------------------------------------------------------------------module ToySolver.SAT.MUS.DAA-  ( module ToySolver.SAT.MUS.Types-  , Options (..)-  , allMCSAssumptions-  , allMUSAssumptions-  , daa-  ) where--import Control.Monad-import qualified Data.IntSet as IntSet-import Data.Set (Set)-import qualified Data.Set as Set-import qualified ToySolver.Combinatorial.HittingSet.Simple as HittingSet-import qualified ToySolver.SAT as SAT-import ToySolver.SAT.Types-import ToySolver.SAT.MUS.Types-import ToySolver.SAT.MUS.CAMUS (Options (..))--allMCSAssumptions :: SAT.Solver -> [Lit] -> Options -> IO [MCS]-allMCSAssumptions solver sels opt = do-  (_, mcses) <- daa solver sels opt-  return mcses--allMUSAssumptions :: SAT.Solver -> [Lit] -> Options -> IO [MUS]-allMUSAssumptions solver sels opt = do-  (muses, _) <- daa solver sels opt-  return muses--daa :: SAT.Solver -> [Lit] -> Options -> IO ([MUS], [MCS])-daa solver sels opt =-  loop (Set.fromList (optKnownMUSes opt)) (Set.fromList (optKnownMCSes opt))-  where-    selsSet :: LitSet-    selsSet = IntSet.fromList sels--    loop :: Set LitSet -> Set LitSet -> IO ([MUS], [MCS])-    loop muses mcses = do-      let f muses [] = return (Set.toList muses, Set.toList mcses)-          f muses (xs:xss) = do-            ret <- findMSS xs-            case ret of-              Just mss -> do-                let mcs = selsSet `IntSet.difference` mss-                optOnMCSFound opt mcs-                loop muses (Set.insert mcs mcses)-              Nothing -> do-                let mus = xs-                optOnMUSFound opt mus-                f (Set.insert mus muses) xss-      f muses (Set.toList (HittingSet.minimalHittingSets mcses `Set.difference` muses))--    findMSS :: LitSet -> IO (Maybe LitSet)-    findMSS xs = do-      forM_ sels $ \l -> do-        SAT.setVarPolarity solver (litVar l) (litPolarity l)-      b <- SAT.solveWith solver (IntSet.toList xs)-      if b then do-        m <- SAT.getModel solver-        liftM Just $ grow $ IntSet.fromList [l | l <- sels, evalLit m l]-      else do-        SAT.addClause solver [-l | l <- IntSet.toList xs] -- lemma-        return Nothing--    grow :: LitSet -> IO LitSet-    grow xs = loop xs (selsSet `IntSet.difference` xs)-      where-        loop xs ys =-          case IntSet.minView ys of-            Nothing -> return xs-            Just (c, ys') -> do-              b <- SAT.solveWith solver (c : IntSet.toList xs)-              if b then do-                m <- SAT.getModel solver-                let cs = IntSet.fromList [l | l <- sels, evalLit m l]-                loop (xs `IntSet.union` cs) (ys' `IntSet.difference` cs)-              else do-                zs <- SAT.getFailedAssumptions solver-                SAT.addClause solver [-l | l <- zs] -- lemma-                loop xs ys'--{--daa_min_unsat(U)-  bA := ∅-  bX := ∅-  X := ∅-  repeat-    M := grow(X,U);-    bX := bX ∪ {U - M}-    bN := HST (X)-    X := ∅-    for (S ∈ bN - bA)-      if (sat(S))-        X := S-        break-      else bA := bA ∪ {S}-    endfor-  until (X = ∅)-  return (bA)--grow(S,U)-  for (c ∈ U - S)-    if (sat(S ∪ {c})) S := S ∪ {c}-  endfor-  return(S)--Fig. 1. Dualize and advance algorithm for finding minimal unsatisfiable sets.--}
+ src/ToySolver/SAT/MUS/Deletion.hs view
@@ -0,0 +1,77 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.SAT.MUS.Deletion+-- Copyright   :  (c) Masahiro Sakai 2012+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable+--+-- Minimal Unsatifiable Subset (MUS) Finder+--+-----------------------------------------------------------------------------+module ToySolver.SAT.MUS.Deletion+  ( module ToySolver.SAT.MUS.Base+  , findMUSAssumptions+  ) where++import Control.Monad+import Data.Default.Class+import Data.List+import qualified Data.IntSet as IS+import qualified ToySolver.SAT as SAT+import ToySolver.SAT.Types+import ToySolver.SAT.MUS.Base++-- | Find a minimal set of assumptions that causes a conflict.+-- Initial set of assumptions is taken from 'SAT.getFailedAssumptions'.+findMUSAssumptions+  :: SAT.Solver+  -> Options+  -> IO MUS+findMUSAssumptions solver opt = do+  log "computing a minimal unsatisfiable core by deletion method"+  core <- liftM IS.fromList $ SAT.getFailedAssumptions solver+  log $ "initial core = " ++ showLits core+  update core+  if IS.null core then+    return core+  else+    loop core IS.empty++  where+    log :: String -> IO ()+    log = optLogger opt++    update :: US -> IO ()+    update = optUpdateBest opt++    showLit :: Lit -> String+    showLit = optShowLit opt++    showLits :: IS.IntSet -> String+    showLits ls = "{" ++ intercalate ", " (map showLit (IS.toList ls)) ++ "}"++    loop :: IS.IntSet -> IS.IntSet -> IO MUS+    loop ls1 fixed = do+      case IS.minView ls1 of+        Nothing -> do+          log $ "found a minimal unsatisfiable core"+          return fixed+        Just (l,ls) -> do+          log $ "trying to remove " ++ showLit l+          ret <- SAT.solveWith solver (IS.toList ls)+          if not ret then do+            ls2 <- liftM IS.fromList $ SAT.getFailedAssumptions solver+            let removed = ls1 `IS.difference` ls2+            log $ "successed to remove " ++ showLits removed+            log $ "new core = " ++ showLits (ls2 `IS.union` fixed)+            update ls2+            forM_ (IS.toList removed) $ \l ->+              SAT.addClause solver [-l]+            loop ls2 fixed+          else do+            log $ "failed to remove " ++ showLit l+            SAT.addClause solver [l]+            loop ls (IS.insert l fixed)
+ src/ToySolver/SAT/MUS/Enum.hs view
@@ -0,0 +1,137 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE MultiParamTypeClasses #-}++-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.SAT.MUS.Enum+-- Copyright   :  (c) Masahiro Sakai 2012-2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable (MultiParamTypeClasses)+--+-- In this module, we assume each soft constraint /C_i/ is represented as a literal.+-- If a constraint /C_i/ is not a literal, we can represent it as a fresh variable /v/+-- together with a hard constraint /v ⇒ C_i/.+--+-- References:+--+-- * [CAMUS] M. Liffiton and K. Sakallah, Algorithms for computing minimal+--   unsatisfiable subsets of constraints, Journal of Automated Reasoning,+--   vol. 40, no. 1, pp. 1-33, Jan. 2008. +--   <http://sun.iwu.edu/~mliffito/publications/jar_liffiton_CAMUS.pdf>+--+-- * [HYCAM] A. Gregoire, B. Mazure, and C. Piette, Boosting a complete+--   technique to find MSS and MUS: thanks to a local search oracle, in+--   Proceedings of the 20th international joint conference on Artifical+--   intelligence, ser. IJCAI'07. San Francisco, CA, USA: Morgan Kaufmann+--   Publishers Inc., 2007, pp. 2300-2305.+--   <http://ijcai.org/papers07/Papers/IJCAI07-370.pdf>+--+-- * [DAA] J. Bailey and P. Stuckey, Discovery of minimal unsatisfiable+--   subsets of constraints using hitting set dualization," in Practical+--   Aspects of Declarative Languages, pp. 174-186, 2005.+--   <http://ww2.cs.mu.oz.au/~pjs/papers/padl05.pdf>+--+-----------------------------------------------------------------------------+module ToySolver.SAT.MUS.Enum+  ( module ToySolver.SAT.MUS.Types+  , Method (..)+  , showMethod+  , parseMethod+  , Options (..)+  , allMUSAssumptions+  ) where++import Data.Char+import Data.Default.Class+import qualified Data.IntSet as IntSet+import Data.List (intercalate)+import qualified Data.Set as Set+import qualified ToySolver.Combinatorial.HittingSet.InterestingSets as I+import qualified ToySolver.Combinatorial.HittingSet.DAA as DAA+import qualified ToySolver.Combinatorial.HittingSet.MARCO as MARCO+import qualified ToySolver.Combinatorial.HittingSet.GurvichKhachiyan1999 as GurvichKhachiyan1999+import qualified ToySolver.SAT as SAT+import ToySolver.SAT.Types+import ToySolver.SAT.MUS.Types+import ToySolver.SAT.MUS.Enum.Base+import qualified ToySolver.SAT.MUS.Enum.CAMUS as CAMUS++showMethod :: Method -> String+showMethod m = map toLower (show m)++parseMethod :: String -> Maybe Method+parseMethod s =+  case filter (/='-') $ map toLower s of+    "camus" -> Just CAMUS+    "daa" -> Just DAA+    "marco" -> Just MARCO+    "gurvichkhachiyan1999" -> Just GurvichKhachiyan1999+    _ -> Nothing++allMUSAssumptions :: SAT.Solver -> [Lit] -> Options -> IO ([MUS], [MCS])+allMUSAssumptions solver sels opt =+  case optMethod opt of+    CAMUS -> CAMUS.allMUSAssumptions solver sels opt+    DAA -> do+      (msses, muses) <- DAA.run prob opt2+      return (Set.toList muses, map mss2mcs (Set.toList msses))+    MARCO -> do+      (msses, muses) <- MARCO.run prob opt2+      return (Set.toList muses, map mss2mcs (Set.toList msses))+    GurvichKhachiyan1999 -> do+      (msses, muses) <- GurvichKhachiyan1999.run prob opt2+      return (Set.toList muses, map mss2mcs (Set.toList msses))+  where+    prob = Problem solver selsSet opt++    opt2 :: I.Options IO+    opt2 =+      (def :: I.Options IO)+      { I.optOnMaximalInterestingSetFound = \xs ->+          optOnMCSFound opt (mss2mcs xs)+      , I.optOnMinimalUninterestingSetFound = \xs ->+          optOnMUSFound opt xs+      }++    selsSet :: LitSet+    selsSet = IntSet.fromList sels++    mss2mcs :: LitSet -> LitSet+    mss2mcs = (selsSet `IntSet.difference`)++-- -----------------------------------------------------------------++data Problem = Problem SAT.Solver LitSet Options++instance I.IsProblem Problem IO where+  universe (Problem _ univ _) = univ++  isInteresting' (Problem solver univ opt) xs = do+    b <- SAT.solveWith solver (IntSet.toList xs)+    if b then do+      m <- SAT.getModel solver+      return $ I.InterestingSet $ IntSet.fromList [l | l <- IntSet.toList univ, optEvalConstr opt m l]+    else do+      zs <- SAT.getFailedAssumptions solver+      return $ I.UninterestingSet $ IntSet.fromList zs++  grow prob@(Problem _ _ opt) xs = do+    optLogger opt $ show (optMethod opt) ++ ": grow " ++ showLits prob xs+    ys <- I.defaultGrow prob xs+    optLogger opt $ show (optMethod opt) ++ ": grow added " ++ showLits prob (ys `IntSet.difference` xs)+    return ys++  shrink prob@(Problem _ _ opt) xs = do+    optLogger opt $ show (optMethod opt) ++ ": shrink " ++ showLits prob xs+    ys <- I.defaultShrink prob xs+    optLogger opt $ show (optMethod opt) ++ ": shrink deleted " ++ showLits prob (xs `IntSet.difference` ys)+    return ys++showLits :: Problem -> IntSet.IntSet -> String+showLits (Problem _ _ opt) ls =+  "{" ++ intercalate ", " (map (optShowLit opt) (IntSet.toList ls)) ++ "}"++-- -----------------------------------------------------------------
+ src/ToySolver/SAT/MUS/Enum/Base.hs view
@@ -0,0 +1,53 @@+module ToySolver.SAT.MUS.Enum.Base+  ( module ToySolver.SAT.MUS.Types+  , Method (..)+  , Options (..)+  ) where++import Data.Default.Class+import qualified ToySolver.SAT as SAT+import ToySolver.SAT.Types+import ToySolver.SAT.MUS.Types++data Method+  = CAMUS+  | DAA+  | MARCO+  | GurvichKhachiyan1999+  deriving (Eq, Ord, Enum, Bounded, Show)++-- The default value can be obtained by 'def'.+data Options+  = Options+  { optMethod     :: Method+  , optLogger     :: String -> IO ()+  , optShowLit    :: Lit -> String+    -- ^ MCS candidates (see HYCAM paper for details).+    -- A MCS candidate must be a superset of a real MCS.+  , optEvalConstr :: SAT.Model -> Lit -> Bool+    -- ^ Because each soft constraint /C_i/ is represented as a selector+    -- literal /l_i/ together with a hard constraint /l_i ⇒ C_i/, there+    -- are cases that a model assigns false to /l_i/ even though /C_i/+    -- itself is true. This function is used to inform the truth value+    -- of the original constraint /C_i/ that corresponds to the selector+    -- literal /l_i/.+  , optOnMCSFound :: MCS -> IO ()+  , optOnMUSFound :: MUS -> IO ()+  , optKnownMCSes :: [MCS]+  , optKnownMUSes :: [MUS]+  , optKnownCSes  :: [CS]+  }++instance Default Options where+  def =+    Options+    { optMethod     = CAMUS+    , optLogger     = \_ -> return ()+    , optShowLit    = show+    , optEvalConstr = SAT.evalLit+    , optOnMCSFound = \_ -> return ()+    , optOnMUSFound = \_ -> return ()+    , optKnownMCSes = []+    , optKnownMUSes = []+    , optKnownCSes = []+    }
+ src/ToySolver/SAT/MUS/Enum/CAMUS.hs view
@@ -0,0 +1,114 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.SAT.MUS.Enum.CAMUS+-- Copyright   :  (c) Masahiro Sakai 2012-2014+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  portable+--+-- In this module, we assume each soft constraint /C_i/ is represented as a literal.+-- If a constraint /C_i/ is not a literal, we can represent it as a fresh variable /v/+-- together with a hard constraint /v ⇒ C_i/.+--+-- References:+--+-- * [CAMUS] M. Liffiton and K. Sakallah, Algorithms for computing minimal+--   unsatisfiable subsets of constraints, Journal of Automated Reasoning,+--   vol. 40, no. 1, pp. 1-33, Jan. 2008. +--   <http://sun.iwu.edu/~mliffito/publications/jar_liffiton_CAMUS.pdf>+--+-- * [HYCAM] A. Gregoire, B. Mazure, and C. Piette, Boosting a complete+--   technique to find MSS and MUS: thanks to a local search oracle, in+--   Proceedings of the 20th international joint conference on Artifical+--   intelligence, ser. IJCAI'07. San Francisco, CA, USA: Morgan Kaufmann+--   Publishers Inc., 2007, pp. 2300-2305.+--   <http://ijcai.org/papers07/Papers/IJCAI07-370.pdf>+--+-----------------------------------------------------------------------------+module ToySolver.SAT.MUS.Enum.CAMUS+  ( module ToySolver.SAT.MUS.Enum.Base+  , allMUSAssumptions+  , allMCSAssumptions+  , enumMCSAssumptions+  ) where++import Control.Monad+import Data.Array.IArray+import Data.Default.Class+import qualified Data.IntSet as IS+import Data.List+import Data.IORef+import Data.Set (Set)+import qualified Data.Set as Set+import qualified ToySolver.Combinatorial.HittingSet.Simple as HittingSet+import qualified ToySolver.SAT as SAT+import ToySolver.SAT.Types+import ToySolver.SAT.MUS.Enum.Base++enumMCSAssumptions :: SAT.Solver -> [Lit] -> Options -> IO ()+enumMCSAssumptions solver sels opt = do+  candRef <- newIORef [(IS.size cs, cs) | cs <- optKnownCSes opt]+  loop candRef 1++  where+    log :: String -> IO ()+    log = optLogger opt++    mcsFound :: MCS -> IO ()+    mcsFound mcs = do+      optOnMCSFound opt mcs+      SAT.addClause solver (IS.toList mcs)++    loop :: IORef [(Int, LitSet)] -> Int -> IO ()+    loop candRef k = do+      log $ "CAMUS: k = " ++ show k+      cand <- readIORef candRef++      ret <- if not (null cand) then return True else SAT.solve solver+      when ret $ do+        forM_ cand $ \(size,cs) -> do+          when (size == k) $ do+            -- If a candidate MCS is not superset of already obtained MCS,+            -- we are sure that it is actually an MCS.+            mcsFound cs+        writeIORef candRef [(size,cs) | (size,cs) <- cand, size /= k]++        vk <- SAT.newVar solver+        SAT.addPBAtMostSoft solver vk [(1,-sel) | sel <- sels] (fromIntegral k)+        let loop2 = do+              ret2 <- SAT.solveWith solver [vk]+              when ret2 $ do+                m <- SAT.getModel solver+                let mcs = IS.fromList [sel | sel <- sels, not (evalLit m sel)]+                mcsFound mcs+                modifyIORef candRef (filter (\(_,cs) -> not (mcs `IS.isSubsetOf` cs)))+                loop2+        loop2+        SAT.addClause solver [-vk]+        loop candRef (k+1)++allMCSAssumptions :: SAT.Solver -> [Lit] -> Options -> IO [MCS]+allMCSAssumptions solver sels opt = do+  ref <- newIORef []  +  let opt2 =+        opt+        { optOnMCSFound = \mcs -> do+            modifyIORef ref (mcs:)+            optOnMCSFound opt mcs+        }+  enumMCSAssumptions solver sels opt2+  readIORef ref++allMUSAssumptions :: SAT.Solver -> [Lit] -> Options -> IO ([MUS], [MCS])+allMUSAssumptions solver sels opt = do+  log "CAMUS: MCS enumeration begins"+  mcses <- allMCSAssumptions solver sels opt+  log "CAMUS: MCS enumeration done"+  let muses = HittingSet.enumMinimalHittingSets $ Set.fromList mcses+  mapM_ (optOnMUSFound opt) muses+  return (muses, mcses)+  where+    log :: String -> IO ()+    log = optLogger opt
+ src/ToySolver/SAT/MUS/Insertion.hs view
@@ -0,0 +1,88 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.SAT.MUS.Insertion+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable+--+-- Minimal Unsatifiable Subset (MUS) Finder+--+-- References:+--+-- * <http://logos.ucd.ie/~jpms/talks/talksite/jpms-ismvl10.pdf>+--+-----------------------------------------------------------------------------+module ToySolver.SAT.MUS.Insertion+  ( module ToySolver.SAT.MUS.Base+  , findMUSAssumptions+  ) where++import Control.Monad+import Data.Default.Class+import Data.List+import qualified Data.IntSet as IntSet+import qualified ToySolver.SAT as SAT+import ToySolver.SAT.Types+import ToySolver.SAT.MUS.Base++-- | Find a minimal set of assumptions that causes a conflict.+-- Initial set of assumptions is taken from 'SAT.getFailedAssumptions'.+findMUSAssumptions+  :: SAT.Solver+  -> Options+  -> IO MUS+findMUSAssumptions solver opt = do+  log "computing a minimal unsatisfiable core by insertion method"+  core <- liftM IntSet.fromList $ SAT.getFailedAssumptions solver+  log $ "initial core = " ++ showLits core+  update core+  if IntSet.null core then+    return core+  else do+    mus <- do+      b <- SAT.solve solver+      if b then+        loop IntSet.empty core+      else+        return IntSet.empty+    log $ "new core = " ++ showLits mus+    update mus+    return mus+  where+    log :: String -> IO ()+    log = optLogger opt++    update :: US -> IO ()+    update = optUpdateBest opt++    showLit :: Lit -> String+    showLit = optShowLit opt++    showLits :: IntSet.IntSet -> String+    showLits ls = "{" ++ intercalate ", " (map showLit (IntSet.toList ls)) ++ "}"++    loop :: IntSet.IntSet -> IntSet.IntSet -> IO MUS+    loop m f = do+      -- pre: (m∩f = ∅), (m⊎f is unsatisfiable), (f=∅ → m is unsatisfiable)+      case IntSet.minView f of+        Nothing -> return m+        Just (c, f') -> do+          -- m is satisfiable+          let loop2 s c = do+                -- pre: (m⊎s⊎{c} ⊆ f), (m⊎s is satisfiable)+                b <- SAT.solveWith solver (c : IntSet.toList (m `IntSet.union` s))+                if not b then do+                  -- c is a transition clause+                  log $ "found a transition constraint: " ++ showLit c+                  return (s,c)+                else do+                  model <- SAT.getModel solver+                  let s' = IntSet.filter (optEvalConstr opt model) f+                  case IntSet.minView (f `IntSet.difference` s') of+                    Nothing -> error "shuld not happen"+                    Just (c', _) -> loop2 s' c'+          (s,c') <- loop2 IntSet.empty c+          loop (IntSet.insert c' m) s
src/ToySolver/SAT/MUS/QuickXplain.hs view
@@ -18,7 +18,7 @@ -- ----------------------------------------------------------------------------- module ToySolver.SAT.MUS.QuickXplain-  ( module ToySolver.SAT.MUS.Types+  ( module ToySolver.SAT.MUS.Base   , Options (..)   , findMUSAssumptions   ) where@@ -29,8 +29,7 @@ import qualified Data.IntSet as IS import qualified ToySolver.SAT as SAT import ToySolver.SAT.Types-import ToySolver.SAT.MUS.Types-import ToySolver.SAT.MUS hiding (findMUSAssumptions)+import ToySolver.SAT.MUS.Base  -- | Find a minimal set of assumptions that causes a conflict. -- Initial set of assumptions is taken from 'SAT.getFailedAssumptions'.@@ -39,10 +38,10 @@   -> Options   -> IO MUS findMUSAssumptions solver opt = do-  log "computing a minimal unsatisfiable core"+  log "computing a minimal unsatisfiable core by QuickXplain"   core <- liftM IS.fromList $ SAT.getFailedAssumptions solver-  update $ IS.toList core-  log $ "core = " ++ showLits core+  log $ "initial core = " ++ showLits core+  update core   if IS.null core then     return core   else@@ -52,11 +51,11 @@     log :: String -> IO ()     log = optLogger opt -    update :: [Lit] -> IO ()+    update :: US -> IO ()     update = optUpdateBest opt      showLit :: Lit -> String-    showLit = optLitPrinter opt+    showLit = optShowLit opt      showLits :: IS.IntSet -> String     showLits ls = "{" ++ intercalate ", " (map showLit (IS.toList ls)) ++ "}"@@ -87,7 +86,7 @@         log $ showLits bs ++ " is unsatisfiable"         bs' <- liftM IS.fromList $ SAT.getFailedAssumptions solver         log $ "new core = " ++ showLits bs'-        update $ IS.toList bs'+        update bs'         return (IS.empty, bs')       else do         log $ showLits bs ++ " is satisfiable"
+ src/ToySolver/SAT/MessagePassing/SurveyPropagation.hs view
@@ -0,0 +1,470 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE ScopedTypeVariables, BangPatterns, TypeFamilies #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.SAT.MessagePassing.SurveyPropagation+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable (ScopedTypeVariables, BangPatterns, TypeFamilies)+--+-- References:+--+-- * Alfredo Braunstein, Marc Mézard and Riccardo Zecchina.+--   Survey Propagation: An Algorithm for Satisfiability,+--   <http://arxiv.org/abs/cs/0212002>+--+-- * Corrie Scalisi. Visualizing Survey Propagation in 3-SAT Factor Graphs,+--   <http://classes.soe.ucsc.edu/cmps290c/Winter06/proj/corriereport.pdf>.+--+-----------------------------------------------------------------------------+module ToySolver.SAT.MessagePassing.SurveyPropagation+  (+  -- * The Solver type+    Solver+  , newSolver+  , deleteSolver++  -- * Problem information+  , getNVars+  , getNConstraints++  -- * Parameters+  , getTolerance+  , setTolerance+  , getIterationLimit+  , setIterationLimit+  , getNThreads+  , setNThreads++  -- * Computing marginal distributions+  , initializeRandom+  , initializeRandomDirichlet+  , propagate+  , getVarProb++  -- * Solving+  , fixLit+  , unfixLit++  -- * Debugging+  , printInfo+  ) where++import Control.Applicative+import Control.Concurrent+import Control.Concurrent.STM+import Control.Exception+import Control.Loop+import Control.Monad+import qualified Data.Array.IArray as A+import qualified Data.IntMap as IntMap+import qualified Data.IntSet as IntSet+import Data.IORef+import Data.Maybe (fromJust)+import qualified Data.Vector as V+import qualified Data.Vector.Mutable as VM+import qualified Data.Vector.Unboxed as VU+import qualified Data.Vector.Unboxed.Mutable as VUM+import Data.Vector.Generic ((!))+import qualified Data.Vector.Generic as VG+import qualified Data.Vector.Generic.Mutable as VGM+import qualified Numeric.Log as L+import qualified System.Random.MWC as Rand+import qualified System.Random.MWC.Distributions as Rand++import qualified ToySolver.SAT.Types as SAT++infixr 8 ^*++(^*) :: Num a => L.Log a -> a -> L.Log a+L.Exp a ^* b = L.Exp (a*b)++comp :: (RealFloat a, L.Precise a) => L.Log a -> L.Log a+comp (L.Exp a) = L.Exp $ L.log1p $ max (-1) $ negate (exp a)++type ClauseIndex = Int+type EdgeIndex   = Int++data Solver+  = Solver+  { svVarEdges :: !(V.Vector (VU.Vector EdgeIndex))+  , svVarProbT :: !(VUM.IOVector (L.Log Double))+  , svVarProbF :: !(VUM.IOVector (L.Log Double))+  , svVarFixed :: !(VM.IOVector (Maybe Bool))++  , svClauseEdges :: !(V.Vector (VU.Vector EdgeIndex))+  , svClauseWeight :: !(VU.Vector Double)++  , svEdgeLit    :: !(VU.Vector SAT.Lit) -- i+  , svEdgeClause :: !(VU.Vector ClauseIndex) -- a+  , svEdgeSurvey :: !(VUM.IOVector (L.Log Double)) -- η_{a → i}+  , svEdgeProbU  :: !(VUM.IOVector (L.Log Double)) -- Π^u_{i → a} / (Π^u_{i → a} + Π^s_{i → a} + Π^0_{i → a})++  , svTolRef :: !(IORef Double)+  , svIterLimRef :: !(IORef (Maybe Int))+  , svNThreadsRef :: !(IORef Int)+  }++newSolver :: Int -> [(Double, SAT.Clause)] -> IO Solver+newSolver nv clauses = do+  let num_clauses = length clauses+      num_edges = sum [length c | (_,c) <- clauses]++  varEdgesRef <- newIORef IntMap.empty+  clauseEdgesM <- VGM.new num_clauses++  (edgeLitM :: VUM.IOVector SAT.Lit) <- VGM.new num_edges+  (edgeClauseM :: VUM.IOVector ClauseIndex) <- VGM.new num_edges++  ref <- newIORef 0+  forM_ (zip [0..] clauses) $ \(i,(_,c)) -> do+    es <- forM c $ \lit -> do+      e <- readIORef ref+      modifyIORef' ref (+1)+      modifyIORef' varEdgesRef (IntMap.insertWith IntSet.union (abs lit) (IntSet.singleton e))+      VGM.unsafeWrite edgeLitM e lit+      VGM.unsafeWrite edgeClauseM e i+      return e+    VGM.unsafeWrite clauseEdgesM i (VG.fromList es)++  varEdges <- readIORef varEdgesRef+  clauseEdges <- VG.unsafeFreeze clauseEdgesM++  edgeLit     <- VG.unsafeFreeze edgeLitM+  edgeClause  <- VG.unsafeFreeze edgeClauseM++  -- Initialize all surveys with non-zero values.+  -- If we initialize to zero, following trivial solution exists:+  -- +  -- η_{a→i} = 0 for all i and a.+  -- +  -- Π^0_{i→a} = 1, Π^u_{i→a} = Π^s_{i→a} = 0 for all i and a,+  -- +  -- \^{Π}^{0}_i = 1, \^{Π}^{+}_i = \^{Π}^{-}_i = 0+  -- +  edgeSurvey  <- VGM.replicate num_edges 0.5+  edgeProbU   <- VGM.new num_edges++  varFixed <- VGM.replicate nv Nothing+  varProbT <- VGM.new nv+  varProbF <- VGM.new nv++  tolRef <- newIORef 0.01+  maxIterRef <- newIORef (Just 1000)+  nthreadsRef <- newIORef 1++  let solver = Solver+        { svVarEdges    = VG.generate nv $ \i ->+            case IntMap.lookup (i+1) varEdges of+              Nothing -> VG.empty+              Just es -> VG.fromListN (IntSet.size es) (IntSet.toList es)+        , svVarProbT = varProbT+        , svVarProbF = varProbF+        , svVarFixed = varFixed++        , svClauseEdges = clauseEdges+        , svClauseWeight = VG.fromListN (VG.length clauseEdges) (map fst clauses)++        , svEdgeLit     = edgeLit+        , svEdgeClause  = edgeClause+        , svEdgeSurvey  = edgeSurvey+        , svEdgeProbU   = edgeProbU++        , svTolRef = tolRef+        , svIterLimRef = maxIterRef+        , svNThreadsRef = nthreadsRef+        }++  return solver++deleteSolver :: Solver -> IO ()+deleteSolver solver = return ()++initializeRandom :: Solver -> Rand.GenIO -> IO ()+initializeRandom solver gen = do+  VG.forM_ (svClauseEdges solver) $ \es -> do+    case VG.length es of+      0 -> return ()+      1 -> VGM.unsafeWrite (svEdgeSurvey solver) (es ! 0) 1+      n -> do+        let p :: Double+            p = 1 / fromIntegral n+        VG.forM_ es $ \e -> do+          d <- Rand.uniformR (p*0.5, p*1.5) gen+          VGM.unsafeWrite (svEdgeSurvey solver) e (realToFrac d)++initializeRandomDirichlet :: Solver -> Rand.GenIO -> IO ()+initializeRandomDirichlet solver gen = do+  VG.forM_ (svClauseEdges solver) $ \es -> do+    case VG.length es of+      0 -> return ()+      1 -> VGM.unsafeWrite (svEdgeSurvey solver) (es ! 0) 1+      len -> do+        (ps :: V.Vector Double) <- Rand.dirichlet (VG.replicate len 1) gen+        numLoop 0 (len-1) $ \i -> do+          VGM.unsafeWrite (svEdgeSurvey solver) (es ! i) (realToFrac (ps ! i))++-- | number of variables of the problem.+getNVars :: Solver -> IO Int+getNVars solver = return $ VG.length (svVarEdges solver)++-- | number of constraints of the problem.+getNConstraints :: Solver -> IO Int+getNConstraints solver = return $ VG.length (svClauseEdges solver)++-- | number of edges of the factor graph+getNEdges :: Solver -> IO Int+getNEdges solver = return $ VG.length (svEdgeLit solver)++getTolerance :: Solver -> IO Double+getTolerance solver = readIORef (svTolRef solver)++setTolerance :: Solver -> Double -> IO ()+setTolerance solver !tol = writeIORef (svTolRef solver) tol++getIterationLimit :: Solver -> IO (Maybe Int)+getIterationLimit solver = readIORef (svIterLimRef solver)++setIterationLimit :: Solver -> Maybe Int -> IO ()+setIterationLimit solver val = writeIORef (svIterLimRef solver) val++getNThreads :: Solver -> IO Int+getNThreads solver = readIORef (svNThreadsRef solver)++setNThreads :: Solver -> Int -> IO ()+setNThreads solver val = writeIORef (svNThreadsRef solver) val++propagate :: Solver -> IO Bool+propagate solver = do+  nthreads <- getNThreads solver+  if nthreads > 1 then+    propagateMT solver nthreads+  else+    propagateST solver++propagateST :: Solver -> IO Bool+propagateST solver = do+  tol <- getTolerance solver+  lim <- getIterationLimit solver+  nv <- getNVars solver+  nc <- getNConstraints solver+  let max_v_len = VG.maximum $ VG.map VG.length $ svVarEdges solver+      max_c_len = VG.maximum $ VG.map VG.length $ svClauseEdges solver+  tmp <- VGM.new (max (max_v_len * 2) max_c_len)+  let loop !i+        | Just l <- lim, i >= l = return False+        | otherwise = do+            numLoop 1 nv $ \v -> updateEdgeProb solver v tmp+            let f maxDelta c = max maxDelta <$> updateEdgeSurvey solver c tmp+            delta <- foldM f 0 [0 .. nc-1]+            if delta <= tol then do+              numLoop 1 nv $ \v -> computeVarProb solver v+              return True+            else+              loop (i+1)+  loop 0++data WorkerCommand+  = WCUpdateEdgeProb+  | WCUpdateSurvey+  | WCComputeVarProb+  | WCTerminate++propagateMT :: Solver -> Int -> IO Bool+propagateMT solver nthreads = do+  tol <- getTolerance solver+  lim <- getIterationLimit solver+  nv <- getNVars solver+  nc <- getNConstraints solver++  mask $ \restore -> do+    ex <- newEmptyTMVarIO+    let wait :: STM a -> IO a+        wait m = join $ atomically $ liftM return m `orElse` liftM throwIO (takeTMVar ex)++    workers <- do+      let mV = (nv + nthreads - 1) `div` nthreads+          mC = (nc + nthreads - 1) `div` nthreads+      forM [0..nthreads-1] $ \i -> do+         let lbV = mV * i + 1 -- inclusive+             ubV = min (lbV + mV) (nv + 1) -- exclusive+             lbC = mC * i -- exclusive+             ubC = min (lbC + mC) nc -- exclusive+         let max_v_len = VG.maximum $ VG.map VG.length $ VG.slice (lbV - 1) (ubV - lbV) (svVarEdges solver)+             max_c_len = VG.maximum $ VG.map VG.length $ VG.slice lbC (ubC - lbC) (svClauseEdges solver)+         tmp <- VGM.new (max (max_v_len*2) max_c_len)+         reqVar   <- newEmptyMVar+         respVar  <- newEmptyTMVarIO+         respVar2 <- newEmptyTMVarIO+         th <- forkIO $ do+           let loop = do+                 cmd <- takeMVar reqVar+                 case cmd of+                   WCTerminate -> return ()+                   WCUpdateEdgeProb -> do+                     numLoop lbV (ubV-1) $ \v -> updateEdgeProb solver v tmp+                     atomically $ putTMVar respVar ()+                     loop+                   WCUpdateSurvey -> do+                     let f maxDelta c = max maxDelta <$> updateEdgeSurvey solver c tmp+                     delta <- foldM f 0 [lbC .. ubC-1]+                     atomically $ putTMVar respVar2 delta+                     loop+                   WCComputeVarProb -> do+                     numLoop lbV (ubV-1) $ \v -> computeVarProb solver v+                     atomically $ putTMVar respVar ()+                     loop+           restore loop `catch` \(e :: SomeException) -> atomically (tryPutTMVar ex e >> return ())+         return (th, reqVar, respVar, respVar2)+ +    let loop !i+          | Just l <- lim, i >= l = return False+          | otherwise = do+              mapM_ (\(_,reqVar,_,_) -> putMVar reqVar WCUpdateEdgeProb) workers+              mapM_ (\(_,_,respVar,_) -> wait (takeTMVar respVar)) workers+              mapM_ (\(_,reqVar,_,_) -> putMVar reqVar WCUpdateSurvey) workers+              delta <- foldM (\delta (_,_,_,respVar2) -> max delta <$> wait (takeTMVar respVar2)) 0 workers+              if delta <= tol then do+                mapM_ (\(_,reqVar,_,_) -> putMVar reqVar WCComputeVarProb) workers+                mapM_ (\(_,_,respVar,_) -> wait (takeTMVar respVar)) workers+                mapM_ (\(_,reqVar,_,_) -> putMVar reqVar WCTerminate) workers+                return True+              else+                loop (i+1)++    ret <- try $ restore $ loop 0+    case ret of+      Right b -> return b+      Left (e :: SomeException) -> do+        mapM_ (\(th,_,_,_) -> killThread th) workers+        throwIO e++-- tmp1 must have at least @VG.length (svVarEdges solver ! (v - 1)) * 2@ elements+updateEdgeProb :: Solver -> SAT.Var -> VUM.IOVector (L.Log Double) -> IO ()+updateEdgeProb solver v tmp = do+  let i = v - 1+      edges = svVarEdges solver ! i+  m <- VGM.unsafeRead (svVarFixed solver) i+  case m of+    Just val -> do+      VG.forM_ edges $ \e -> do+        let lit = svEdgeLit solver ! e+            flag = (lit > 0) == val+        VGM.unsafeWrite (svEdgeProbU solver) e (if flag then 0 else 1)+    Nothing -> do+      let f !k !val1_pre !val2_pre+            | k >= VG.length edges = return ()+            | otherwise = do+                let e = edges ! k+                    a = svEdgeClause solver ! e+                VGM.unsafeWrite tmp (k*2) val1_pre+                VGM.unsafeWrite tmp (k*2+1) val2_pre+                eta_ai <- VGM.unsafeRead (svEdgeSurvey solver) e -- η_{a→i}+                let w = svClauseWeight solver ! a+                    lit2 = svEdgeLit solver ! e+                    val1_pre' = if lit2 > 0 then val1_pre * comp eta_ai ^* w else val1_pre+                    val2_pre' = if lit2 > 0 then val2_pre else val2_pre * comp eta_ai ^* w+                f (k+1) val1_pre' val2_pre'+      f 0 1 1+      -- tmp ! (k*2)   == Π_{a∈edges[0..k-1], a∈V^{+}(i)} (1 - eta_ai)^{w_i}+      -- tmp ! (k*2+1) == Π_{a∈edges[0..k-1], a∈V^{-}(i)} (1 - eta_ai)^{w_i}++      let g !k !val1_post !val2_post+            | k < 0 = return ()+            | otherwise = do+                let e = edges ! k+                    a = svEdgeClause solver ! e+                    lit2 = svEdgeLit solver ! e+                val1_pre <- VGM.unsafeRead tmp (k*2)+                val2_pre <- VGM.unsafeRead tmp (k*2+1)+                let val1 = val1_pre * val1_post -- val1 == Π_{b∈edges, b∈V^{+}(i), a≠b} (1 - eta_bi)^{w_i}+                    val2 = val2_pre * val2_post -- val2 == Π_{b∈edges, b∈V^{-}(i), a≠b} (1 - eta_bi)^{w_i}+                eta_ai <- VGM.unsafeRead (svEdgeSurvey solver) e -- η_{a→i}+                let w = svClauseWeight solver ! a+                    val1_post' = if lit2 > 0 then val1_post * comp eta_ai ^* w else val1_post+                    val2_post' = if lit2 > 0 then val2_post else val2_post * comp eta_ai ^* w+                let pi_0 = val1 * val2 -- Π^0_{i→a}+                    pi_u = if lit2 > 0 then comp val2 * val1 else comp val1 * val2 -- Π^u_{i→a}+                    pi_s = if lit2 > 0 then comp val1 * val2 else comp val2 * val1 -- Π^s_{i→a}+                VGM.unsafeWrite (svEdgeProbU solver) e (pi_u / L.sum [pi_0, pi_u, pi_s])+                g (k-1) val1_post' val2_post'+      g (VG.length edges - 1) 1 1++-- tmp must have at least @VG.length (svClauseEdges solver ! a)@ elements+updateEdgeSurvey :: Solver -> ClauseIndex -> VUM.IOVector (L.Log Double) -> IO Double+updateEdgeSurvey solver a tmp = do+  let edges = svClauseEdges solver ! a+  let f !k !p_pre+        | k >= VG.length edges = return ()+        | otherwise = do+            let e = edges ! k+            VGM.unsafeWrite tmp k p_pre+            p <- VGM.unsafeRead (svEdgeProbU solver) e+            -- p is the probability of lit being false, if the edge does not exist.+            f (k+1) (p_pre * p)+  let g !k !p_post !maxDelta+        | k < 0 = return maxDelta+        | otherwise = do+            let e = edges ! k+            -- p_post == Π_{e∈edges[k+1..]} p_e+            p_pre <- VGM.unsafeRead tmp k -- Π_{e∈edges[0..k-1]} p_e+            p <- VGM.unsafeRead (svEdgeProbU solver) e+            eta_ai <- VGM.unsafeRead (svEdgeSurvey solver) e+            let eta_ai' = p_pre * p_post -- Π_{e∈edges[0,..,k-1,k+1,..]} p_e+            VGM.unsafeWrite (svEdgeSurvey solver) e eta_ai'+            let delta = abs (realToFrac eta_ai' - realToFrac eta_ai)+            g (k-1) (p_post * p) (max delta maxDelta)+  f 0 1+  -- tmp ! k == Π_{e∈edges[0..k-1]} p_e+  g (VG.length edges - 1) 1 0++computeVarProb :: Solver -> SAT.Var -> IO ()+computeVarProb solver v = do+  let i = v - 1+      f (val1,val2) e = do+        let lit = svEdgeLit solver ! e+            a = svEdgeClause solver ! e+            w = svClauseWeight solver ! a+        eta_ai <- VGM.unsafeRead (svEdgeSurvey solver) e+        let val1' = if lit > 0 then val1 * comp eta_ai ^* w else val1+            val2' = if lit < 0 then val2 * comp eta_ai ^* w else val2+        return (val1',val2')+  (val1,val2) <- VG.foldM' f (1,1) (svVarEdges solver ! i)+  let p0 = val1 * val2       -- \^{Π}^{0}_i+      pp = comp val1 * val2 -- \^{Π}^{+}_i+      pn = comp val2 * val1 -- \^{Π}^{-}_i+  let wp = pp / (pp + pn + p0)+      wn = pn / (pp + pn + p0)+  VGM.unsafeWrite (svVarProbT solver) i wp -- W^{(+)}_i+  VGM.unsafeWrite (svVarProbF solver) i wn -- W^{(-)}_i++-- | Get the marginal probability of the variable to be @True@, @False@ and unspecified respectively.+getVarProb :: Solver -> SAT.Var -> IO (Double, Double, Double)+getVarProb solver v = do+  pt <- realToFrac <$> VGM.unsafeRead (svVarProbT solver) (v - 1)+  pf <- realToFrac <$> VGM.unsafeRead (svVarProbF solver) (v - 1)+  return (pt, pf, 1 - (pt + pf))++fixLit :: Solver -> SAT.Lit -> IO ()+fixLit solver lit = do+  VGM.unsafeWrite (svVarFixed solver) (abs lit - 1) (if lit > 0 then Just True else Just False)++unfixLit :: Solver -> SAT.Lit -> IO ()+unfixLit solver lit = do+  VGM.unsafeWrite (svVarFixed solver) (abs lit - 1) Nothing++printInfo :: Solver -> IO ()+printInfo solver = do+  (surveys :: VU.Vector (L.Log Double)) <- VG.freeze (svEdgeSurvey solver)+  (u :: VU.Vector (L.Log Double)) <- VG.freeze (svEdgeProbU solver)+  let xs = [(clause, lit, eta, u ! e) | (e, eta) <- zip [0..] (VG.toList surveys), let lit = svEdgeLit solver ! e, let clause = svEdgeClause solver ! e]+  putStrLn $ "edges: " ++ show xs++  (pt :: VU.Vector (L.Log Double)) <- VG.freeze (svVarProbT solver)+  (pf :: VU.Vector (L.Log Double)) <- VG.freeze (svVarProbF solver)+  nv <- getNVars solver+  let xs2 = [(v, realToFrac (pt ! i) :: Double, realToFrac (pf ! i) :: Double, realToFrac (pt ! i) - realToFrac (pf ! i) :: Double) | v <- [1..nv], let i = v - 1]+  putStrLn $ "vars: " ++ show xs2
+ src/ToySolver/SAT/MessagePassing/SurveyPropagation/OpenCL.hs view
@@ -0,0 +1,459 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables, BangPatterns, TemplateHaskell #-}+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.SAT.MessagePassing.SurveyPropagation.OpenCL+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable (ScopedTypeVariables, BangPatterns, TypeFamilies)+--+-- References:+--+-- * Alfredo Braunstein, Marc Mézard and Riccardo Zecchina.+--   Survey Propagation: An Algorithm for Satisfiability,+--   <http://arxiv.org/abs/cs/0212002>+--+-- * Corrie Scalisi. Visualizing Survey Propagation in 3-SAT Factor Graphs,+--   <http://classes.soe.ucsc.edu/cmps290c/Winter06/proj/corriereport.pdf>.+--+-----------------------------------------------------------------------------+module ToySolver.SAT.MessagePassing.SurveyPropagation.OpenCL+  (+  -- * The Solver type+    Solver+  , newSolver+  , deleteSolver++  -- * Problem information+  , getNVars+  , getNConstraints++  -- * Parameters+  , getTolerance+  , setTolerance+  , getIterationLimit+  , setIterationLimit++  -- * Computing marginal distributions+  , initializeRandom+  , initializeRandomDirichlet+  , propagate+  , getVarProb++  -- * Solving+  , fixLit+  , unfixLit+  ) where++import Control.Applicative ((<$>))+import Control.Exception+import Control.Loop+import Control.Monad+import Control.Parallel.OpenCL+import Data.Bits+import Data.Int+import Data.IORef+import qualified Data.Vector as V+import qualified Data.Vector.Mutable as VM+import qualified Data.Vector.Storable as VS+import qualified Data.Vector.Storable.Mutable as VSM+import Data.Vector.Generic ((!))+import qualified Data.Vector.Generic as VG+import qualified Data.Vector.Generic.Mutable as VGM+import Foreign( castPtr, nullPtr, sizeOf )+import Foreign.C.Types( CFloat )+import Language.Haskell.TH (runIO, litE, stringL)+import Language.Haskell.TH.Syntax (addDependentFile)+import qualified Numeric.Log as L+import System.IO+import qualified System.Random.MWC as Rand+import qualified System.Random.MWC.Distributions as Rand+import Text.Printf++import qualified ToySolver.SAT.Types as SAT++data Solver+  = Solver+  { svOutputMessage :: !(String -> IO ())++  , svContext :: !CLContext+  , svDevice  :: !CLDeviceID+  , svQueue   :: !CLCommandQueue+  , svUpdateEdgeProb   :: !CLKernel+  , svUpdateEdgeSurvey :: !CLKernel+  , svComputeVarProb   :: !CLKernel++  , svVarEdges       :: !(VSM.IOVector CLint)+  , svVarEdgesWeight :: !(VSM.IOVector CFloat)+  , svVarOffset      :: !(VSM.IOVector CLint)+  , svVarLength      :: !(VSM.IOVector CLint)+  , svVarFixed       :: !(VSM.IOVector Int8)+  , svVarProb        :: !(VSM.IOVector (L.Log CFloat))+  , svClauseOffset   :: !(VSM.IOVector CLint)+  , svClauseLength   :: !(VSM.IOVector CLint)+  , svEdgeSurvey     :: !(VSM.IOVector (L.Log CFloat)) -- η_{a → i}+  , svEdgeProbU      :: !(VSM.IOVector (L.Log CFloat)) -- Π^u_{i → a} / (Π^u_{i → a} + Π^s_{i → a} + Π^0_{i → a})++  , svTolRef :: !(IORef Double)+  , svIterLimRef :: !(IORef (Maybe Int))+  }++newSolver :: (String -> IO ()) -> CLContext -> CLDeviceID -> Int -> [(Double, SAT.Clause)] -> IO Solver+newSolver outputMessage context dev nv clauses = do+  _ <- clRetainContext context+  queue <- clCreateCommandQueue context dev []++  let num_clauses = length clauses+      num_edges = sum [length c | (_,c) <- clauses]++  (varEdgesTmp :: VM.IOVector [(Int,Bool,Double)]) <- VGM.replicate nv []+  clauseOffset <- VGM.new num_clauses+  clauseLength <- VGM.new num_clauses++  ref <- newIORef 0+  forM_ (zip [0..] clauses) $ \(i,(w,c)) -> do+    VGM.write clauseOffset i =<< liftM fromIntegral (readIORef ref)+    VGM.write clauseLength i (fromIntegral (length c))+    forM_ c $ \lit -> do+      e <- readIORef ref+      modifyIORef' ref (+1)+#if MIN_VERSION_vector(0,11,0)+      VGM.modify varEdgesTmp ((e,lit>0,w) :) (abs lit - 1)+#else+      VGM.write varEdgesTmp (abs lit - 1) =<< liftM ((e,lit>0,w) :) (VGM.read varEdgesTmp (abs lit - 1))+#endif++  varOffset <- VGM.new nv+  varLength <- VGM.new nv+  varFixed  <- VGM.new nv+  varEdges <- VGM.new num_edges+  varEdgesWeight   <- VGM.new num_edges+  let loop !i !offset+        | i >= nv   = return ()+        | otherwise = do+            xs <- VGM.read (varEdgesTmp) i+            let len = length xs+            VGM.write varOffset i (fromIntegral offset)+            VGM.write varLength i (fromIntegral len)+            VGM.write varFixed i 0+            forM_ (zip [offset..] (reverse xs)) $ \(j, (e,polarity,w)) -> do+              VGM.write varEdges j $ (fromIntegral e `shiftL` 1) .|. (if polarity then 1 else 0)+              VGM.write varEdgesWeight j (realToFrac w)+            loop (i+1) (offset + len)+  loop 0 0++  -- Initialize all surveys with non-zero values.+  -- If we initialize to zero, following trivial solution exists:+  -- +  -- η_{a→i} = 0 for all i and a.+  -- +  -- Π^0_{i→a} = 1, Π^u_{i→a} = Π^s_{i→a} = 0 for all i and a,+  -- +  -- \^{Π}^{0}_i = 1, \^{Π}^{+}_i = \^{Π}^{-}_i = 0+  -- +  edgeSurvey  <- VGM.replicate num_edges (L.Exp (log 0.5))+  edgeProbU   <- VGM.new num_edges++  varProb <- VGM.new (nv*2)++  tolRef <- newIORef 0.01+  maxIterRef <- newIORef (Just 1000)++  -- Compile+  let byteSize :: forall a. VSM.Storable a => VSM.IOVector a -> Int+      byteSize v = VGM.length v * sizeOf (undefined :: a)+  (maxConstantBufferSize :: Int) <- fromIntegral <$> clGetDeviceMaxConstantBufferSize dev+  let reqConstantBufferSize =+        byteSize varEdges + byteSize varEdgesWeight ++        byteSize varOffset + byteSize varLength ++        byteSize clauseOffset + byteSize clauseLength+  let flags =+        ["-DUSE_CONSTANT_BUFFER" | maxConstantBufferSize >= reqConstantBufferSize]+  -- programSource <- openBinaryFile "sp.cl" ReadMode >>= hGetContents+  let programSource = $(runIO (do{ h <- openFile "src/ToySolver/SAT/MessagePassing/SurveyPropagation/sp.cl" ReadMode; hSetEncoding h utf8; hGetContents h }) >>= \s -> addDependentFile "src/ToySolver/SAT/MessagePassing/SurveyPropagation/sp.cl" >> litE (stringL s))+  outputMessage $ "Compiling kernels with options: " ++ unwords flags+  program <- clCreateProgramWithSource context programSource+  finally (clBuildProgram program [dev] (unwords flags))+          (outputMessage =<< clGetProgramBuildLog program dev)+  update_edge_prob   <- clCreateKernel program "update_edge_prob"+  update_edge_survey <- clCreateKernel program "update_edge_survey"+  compute_var_prob   <- clCreateKernel program "compute_var_prob"++  return $+    Solver+    { svOutputMessage = outputMessage++    , svContext = context+    , svDevice  = dev+    , svQueue   = queue+    , svUpdateEdgeProb   = update_edge_prob+    , svUpdateEdgeSurvey = update_edge_survey+    , svComputeVarProb   = compute_var_prob++    , svVarEdges       = varEdges+    , svVarEdgesWeight = varEdgesWeight+    , svVarOffset      = varOffset+    , svVarLength      = varLength+    , svVarFixed       = varFixed+    , svVarProb        = varProb+    , svClauseOffset   = clauseOffset+    , svClauseLength   = clauseLength+    , svEdgeSurvey     = edgeSurvey+    , svEdgeProbU      = edgeProbU++    , svTolRef = tolRef+    , svIterLimRef = maxIterRef+    }++deleteSolver :: Solver -> IO ()+deleteSolver solver = do+  _ <- clReleaseKernel (svUpdateEdgeProb solver)+  _ <- clReleaseKernel (svUpdateEdgeSurvey solver)+  _ <- clReleaseKernel (svComputeVarProb solver)+  _ <- clReleaseCommandQueue (svQueue solver)+  _ <- clReleaseContext (svContext solver)+  return ()++initializeRandom :: Solver -> Rand.GenIO -> IO ()+initializeRandom solver gen = do+  n <- getNConstraints solver+  numLoop 0 (n-1) $ \i -> do+    off <- fromIntegral <$> VGM.unsafeRead (svClauseOffset solver) i+    len <- fromIntegral <$> VGM.unsafeRead (svClauseLength solver) i+    case len of+      0 -> return ()+      1 -> VGM.unsafeWrite (svEdgeSurvey solver) off (L.Exp 0)+      _ -> do+        let p :: Double+            p = 1 / fromIntegral len+        numLoop 0 (len-1) $ \i -> do+          d <- Rand.uniformR (p*0.5, p*1.5) gen+          VGM.unsafeWrite (svEdgeSurvey solver) (off+i) (L.Exp (realToFrac (log d)))++initializeRandomDirichlet :: Solver -> Rand.GenIO -> IO ()+initializeRandomDirichlet solver gen = do+  n <- getNConstraints solver+  numLoop 0 (n-1) $ \i -> do+    off <- fromIntegral <$> VGM.unsafeRead (svClauseOffset solver) i+    len <- fromIntegral <$> VGM.unsafeRead (svClauseLength solver) i+    case len of+      0 -> return ()+      1 -> VGM.unsafeWrite (svEdgeSurvey solver) off (L.Exp 0)+      _ -> do+        (ps :: V.Vector Double) <- Rand.dirichlet (VG.replicate len 1) gen+        numLoop 0 (len-1) $ \i -> do+          VGM.unsafeWrite (svEdgeSurvey solver) (off+i) (L.Exp (realToFrac (log (ps ! i))))++-- | number of variables of the problem.+getNVars :: Solver -> IO Int+getNVars solver = return $ VGM.length (svVarOffset solver)++-- | number of constraints of the problem.+getNConstraints :: Solver -> IO Int+getNConstraints solver = return $ VGM.length (svClauseOffset solver)++-- | number of edges of the factor graph+getNEdges :: Solver -> IO Int+getNEdges solver = return $ VGM.length (svEdgeSurvey solver)++getTolerance :: Solver -> IO Double+getTolerance solver = readIORef (svTolRef solver)++setTolerance :: Solver -> Double -> IO ()+setTolerance solver !tol = writeIORef (svTolRef solver) tol++getIterationLimit :: Solver -> IO (Maybe Int)+getIterationLimit solver = readIORef (svIterLimRef solver)++setIterationLimit :: Solver -> Maybe Int -> IO ()+setIterationLimit solver val = writeIORef (svIterLimRef solver) val++-- | Get the marginal probability of the variable to be @True@, @False@ and unspecified respectively.+getVarProb :: Solver -> SAT.Var -> IO (Double, Double, Double)+getVarProb solver v = do+  let i = v - 1+  pt <- (exp . realToFrac . L.ln) <$> VGM.read (svVarProb solver) (i*2)+  pf <- (exp . realToFrac . L.ln) <$> VGM.read (svVarProb solver) (i*2+1)+  return (pt, pf, 1 - (pt + pf))++propagate :: Solver -> IO Bool+propagate solver = do+  tol <- getTolerance solver+  lim <- getIterationLimit solver+  nv <- getNVars solver+  nc <- getNConstraints solver+  let ne = VGM.length (svEdgeSurvey solver)++  let context = svContext solver+      dev = svDevice solver+      queue = svQueue solver+  platform <- clGetDevicePlatform dev++  let infos = [CL_PLATFORM_PROFILE, CL_PLATFORM_VERSION, CL_PLATFORM_NAME, CL_PLATFORM_VENDOR, CL_PLATFORM_EXTENSIONS]+  forM_ infos $ \info -> do+    s <- clGetPlatformInfo platform info+    svOutputMessage solver $ show info ++ " = " ++ s+  devname <- clGetDeviceName dev +  svOutputMessage solver $ "DEVICE = " ++ devname++  (maxComputeUnits :: Int) <- fromIntegral <$> clGetDeviceMaxComputeUnits dev+  (maxWorkGroupSize :: Int) <- fromIntegral <$> clGetDeviceMaxWorkGroupSize dev+  maxWorkItemSizes@(maxWorkItemSize:_) <- fmap fromIntegral <$> clGetDeviceMaxWorkItemSizes dev+  svOutputMessage solver $ "MAX_COMPUTE_UNITS = " ++ show maxComputeUnits+  svOutputMessage solver $ "MAX_WORK_GROUP_SIZE = " ++ show maxWorkGroupSize+  svOutputMessage solver $ "MAX_WORK_ITEM_SIZES = " ++ show maxWorkItemSizes+  (globalMemSize :: Int) <- fromIntegral <$> clGetDeviceGlobalMemSize dev+  (localMemSize :: Int) <- fromIntegral <$> clGetDeviceLocalMemSize dev+  (maxConstantBufferSize :: Int) <- fromIntegral <$> clGetDeviceMaxConstantBufferSize dev+  (maxConstantArgs :: Int) <- fromIntegral <$> clGetDeviceMaxConstantArgs dev+  svOutputMessage solver $ "GLOBAL_MEM_SIZE = " ++ show globalMemSize+  svOutputMessage solver $ "LOCAL_MEM_SIZE = " ++ show localMemSize+  svOutputMessage solver $ "MAX_CONSTANT_BUFFER_SIZE = " ++ show maxConstantBufferSize+  svOutputMessage solver $ "MAX_CONSTANT_ARGS = " ++ show maxConstantArgs++  let defaultNumGroups = maxComputeUnits * 4++  (updateEdgeProb_kernel_workgroup_size :: Int)+      <- fromIntegral <$> clGetKernelWorkGroupSize (svUpdateEdgeProb solver) dev+  let updateEdgeProb_local_size    = min 32 updateEdgeProb_kernel_workgroup_size+      updateEdgeProb_num_groups    = min defaultNumGroups (maxWorkItemSize `div` updateEdgeProb_local_size)+      updateEdgeProb_global_size   = updateEdgeProb_num_groups * updateEdgeProb_local_size+  svOutputMessage solver $+    printf "update_edge_prob kernel: CL_KERNEL_WORK_GROUP_SIZE=%d -> groupSize=%d numGroups=%d globalSize=%d"+      updateEdgeProb_kernel_workgroup_size updateEdgeProb_local_size updateEdgeProb_num_groups updateEdgeProb_global_size++  (updateEdgeSurvey_kernel_workgroup_size :: Int)+      <- fromIntegral <$> clGetKernelWorkGroupSize (svUpdateEdgeSurvey solver) dev+  let updateEdgeSurvey_local_size  = min 32 updateEdgeSurvey_kernel_workgroup_size+      updateEdgeSurvey_num_groups  = min defaultNumGroups (maxWorkItemSize `div` updateEdgeSurvey_local_size)+      updateEdgeSurvey_global_size = updateEdgeSurvey_num_groups * updateEdgeSurvey_local_size+  svOutputMessage solver $+    printf "update_edge_survey kernel: CL_KERNEL_WORK_GROUP_SIZE=%d -> groupSize=%d numGroups=%d globalSize=%d"+      updateEdgeSurvey_kernel_workgroup_size updateEdgeSurvey_local_size updateEdgeSurvey_num_groups updateEdgeSurvey_global_size++  (computeVarProb_kernel_workgroup_size :: Int)+      <- fromIntegral <$> clGetKernelWorkGroupSize (svComputeVarProb solver) dev+  let computeVarProb_local_size    = min 32 computeVarProb_kernel_workgroup_size+      computeVarProb_num_groups    = min defaultNumGroups (maxWorkItemSize `div` computeVarProb_local_size)+      computeVarProb_global_size   = computeVarProb_num_groups * computeVarProb_local_size+  svOutputMessage solver $+    printf "compute_var_prob kernel: CL_KERNEL_WORK_GROUP_SIZE=%d -> groupSize=%d numGroups=%d globalSize=%d"+      computeVarProb_kernel_workgroup_size computeVarProb_local_size computeVarProb_num_groups computeVarProb_global_size++  let createBufferFromVector :: forall a. VSM.Storable a => [CLMemFlag] -> VSM.IOVector a -> IO CLMem+      createBufferFromVector flags v = do+        VSM.unsafeWith v $ \ptr ->+          clCreateBuffer context (CL_MEM_COPY_HOST_PTR : flags)+            (VGM.length v * sizeOf (undefined :: a), castPtr ptr)++      readBufferToVectorAsync :: forall a. VSM.Storable a => CLMem -> VSM.IOVector a -> IO CLEvent+      readBufferToVectorAsync mem vec = do+        VSM.unsafeWith vec $ \ptr -> do+          clEnqueueReadBuffer queue mem False+            0 (VSM.length vec * sizeOf (undefined :: a)) (castPtr ptr) []+      +      readBufferToVector :: forall a. VSM.Storable a => CLMem -> VSM.IOVector a -> IO ()+      readBufferToVector mem vec = do+        VSM.unsafeWith vec $ \ptr -> do+          ev <- clEnqueueReadBuffer queue mem True+            0 (VSM.length vec * sizeOf (undefined :: a)) (castPtr ptr) []+          _ <- clReleaseEvent ev+          return ()++  var_offset         <- createBufferFromVector [CL_MEM_READ_ONLY] $ svVarOffset solver+  var_degree         <- createBufferFromVector [CL_MEM_READ_ONLY] $ svVarLength solver+  var_fixed          <- createBufferFromVector [CL_MEM_READ_ONLY] $ svVarFixed solver+  var_edges          <- createBufferFromVector [CL_MEM_READ_ONLY] $ svVarEdges solver+  var_edges_weight   <- createBufferFromVector [CL_MEM_READ_ONLY] $ svVarEdgesWeight solver+  clause_offset      <- createBufferFromVector [CL_MEM_READ_ONLY] $ svClauseOffset solver+  clause_degree      <- createBufferFromVector [CL_MEM_READ_ONLY] $ svClauseLength solver+  edge_survey        <- createBufferFromVector [CL_MEM_READ_WRITE] $ svEdgeSurvey solver+  edge_prob_u        <- clCreateBuffer context [CL_MEM_READ_WRITE {-, CL_MEM_HOST_NOACCESS -}]+                          (ne * sizeOf (undefined :: CFloat), nullPtr)++  global_buf         <- clCreateBuffer context [CL_MEM_READ_WRITE {-, CL_MEM_HOST_NOACCESS -}]+                          (ne * sizeOf (undefined :: CFloat) * 2, nullPtr)+  var_prob           <- clCreateBuffer context [CL_MEM_WRITE_ONLY {-, CL_MEM_HOST_READONLY -}]+                          (nv * sizeOf (undefined :: CFloat) * 2, nullPtr)+  group_max_delta    <- clCreateBuffer context [CL_MEM_WRITE_ONLY {-, CL_MEM_HOST_READONLY -}]+                          (updateEdgeSurvey_num_groups * sizeOf (undefined :: CFloat), nullPtr)++  clSetKernelArgSto (svUpdateEdgeProb solver) 0 (fromIntegral nv :: CLint)+  clSetKernelArgSto (svUpdateEdgeProb solver) 1 var_offset+  clSetKernelArgSto (svUpdateEdgeProb solver) 2 var_degree+  clSetKernelArgSto (svUpdateEdgeProb solver) 3 var_fixed+  clSetKernelArgSto (svUpdateEdgeProb solver) 4 var_edges+  clSetKernelArgSto (svUpdateEdgeProb solver) 5 var_edges_weight+  clSetKernelArgSto (svUpdateEdgeProb solver) 6 global_buf+  clSetKernelArgSto (svUpdateEdgeProb solver) 7 edge_survey+  clSetKernelArgSto (svUpdateEdgeProb solver) 8 edge_prob_u++  clSetKernelArgSto (svUpdateEdgeSurvey solver) 0 (fromIntegral nc :: CLint)+  clSetKernelArgSto (svUpdateEdgeSurvey solver) 1 clause_offset+  clSetKernelArgSto (svUpdateEdgeSurvey solver) 2 clause_degree+  clSetKernelArgSto (svUpdateEdgeSurvey solver) 3 edge_survey+  clSetKernelArgSto (svUpdateEdgeSurvey solver) 4 edge_prob_u+  clSetKernelArgSto (svUpdateEdgeSurvey solver) 5 global_buf+  clSetKernelArgSto (svUpdateEdgeSurvey solver) 6 group_max_delta+  clSetKernelArg    (svUpdateEdgeSurvey solver) 7 (updateEdgeSurvey_local_size * sizeOf (undefined :: CFloat)) nullPtr -- reduce_buf++  clSetKernelArgSto (svComputeVarProb solver) 0 (fromIntegral nv :: CLint)+  clSetKernelArgSto (svComputeVarProb solver) 1 var_offset+  clSetKernelArgSto (svComputeVarProb solver) 2 var_degree+  clSetKernelArgSto (svComputeVarProb solver) 3 var_prob+  clSetKernelArgSto (svComputeVarProb solver) 4 var_edges+  clSetKernelArgSto (svComputeVarProb solver) 5 var_edges_weight+  clSetKernelArgSto (svComputeVarProb solver) 6 edge_survey+  +  (group_max_delta_vec :: VSM.IOVector CFloat) <- VGM.new updateEdgeSurvey_num_groups++  let loop !i+        | Just l <- lim, i >= l = return (False,i)+        | otherwise = do+            _ <- clReleaseEvent =<< clEnqueueNDRangeKernel queue (svUpdateEdgeProb solver)+                   [updateEdgeProb_global_size] [updateEdgeProb_local_size] []          +            _ <- clReleaseEvent =<< clEnqueueNDRangeKernel queue (svUpdateEdgeSurvey solver)+                   [updateEdgeSurvey_global_size] [updateEdgeSurvey_local_size] []+            readBufferToVector group_max_delta group_max_delta_vec+            !delta <- VG.maximum <$> VS.unsafeFreeze group_max_delta_vec+            if realToFrac delta <= tol then do+              return (True,i)+            else+              loop (i+1)++  (b,_steps) <- loop 0++  _ <- clReleaseEvent =<< readBufferToVectorAsync edge_survey (svEdgeSurvey solver)+  when b $ do+    _ <- clReleaseEvent =<< clEnqueueNDRangeKernel queue (svComputeVarProb solver)+      [computeVarProb_global_size] [computeVarProb_local_size] []+    _ <- clReleaseEvent =<< readBufferToVectorAsync var_prob (svVarProb solver)+    return ()++  _ <- clFinish queue++  _ <- clReleaseMemObject var_offset+  _ <- clReleaseMemObject var_degree+  _ <- clReleaseMemObject var_edges+  _ <- clReleaseMemObject var_edges_weight+  _ <- clReleaseMemObject clause_offset+  _ <- clReleaseMemObject clause_degree+  _ <- clReleaseMemObject edge_survey+  _ <- clReleaseMemObject edge_prob_u+  _ <- clReleaseMemObject global_buf+  _ <- clReleaseMemObject var_prob+  _ <- clReleaseMemObject group_max_delta++  return b++fixLit :: Solver -> SAT.Lit -> IO ()+fixLit solver lit = do+  VGM.unsafeWrite (svVarFixed solver) (abs lit - 1) (if lit > 0 then 1 else -1)++unfixLit :: Solver -> SAT.Lit -> IO ()+unfixLit solver lit = do+  VGM.unsafeWrite (svVarFixed solver) (abs lit - 1) 0
+ src/ToySolver/SAT/MessagePassing/SurveyPropagation/sp.cl view
@@ -0,0 +1,193 @@+/* -*- mode: c -*- */++#ifdef USE_CONSTANT_BUFFER+#define CONSTANT __constant+#else+#define CONSTANT __global+#endif++typedef float logfloat;+typedef float2 logfloat2;++static inline logfloat comp(logfloat x) {+  return log1p(fmax(-1.0f, -exp(x)));+}++__kernel void+update_edge_prob(+    int n_vars,+    CONSTANT int *var_offset,         // int[n_vars]+    CONSTANT int *var_degree,         // int[n_vars]+    CONSTANT char *var_fixed,         // char[n_vars]+    CONSTANT int *var_edges,          // int[M]+    CONSTANT float *var_edges_weight, // float[M]+    __global logfloat2 *var_edges_buf,// logfloat2[M]+    __global logfloat *edge_survey,   // logfloat[n_edges]+    __global logfloat *edge_prob_u    // logfloat[n_edges]+    )+{+    int global_size = get_global_size(0);+    for (int i = get_global_id(0); i < n_vars; i += global_size) {+        int offset = var_offset[i];+        int degree = var_degree[i];+        int fixed  = var_fixed[i];++        if (fixed != 0) {+            for (int j = 0; j < degree; j++) {+                int tmp = var_edges[offset+j];+                int e = tmp >> 1;+                bool polarity = tmp & 1;+                if (polarity == (bool)(tmp > 0))+                    edge_prob_u[e] = log(0.0f);+                else+                    edge_prob_u[e] = log(1.0f);+            }+        }++        logfloat val1_pre = log(1.0f);+        logfloat val2_pre = log(1.0f);+        for (int j = 0; j < degree; j++) {+            var_edges_buf[offset+j] = (float2)(val1_pre, val2_pre);++            int tmp = var_edges[offset+j];+            int e = tmp >> 1;+            bool polarity = tmp & 1;+            logfloat eta_ai = edge_survey[e];+            logfloat w = var_edges_weight[offset+j];++            if (polarity) {+              val1_pre += comp(eta_ai) * w;+            } else {+              val2_pre += comp(eta_ai) * w;+            }+        }++        logfloat val1_post = log(1.0f);+        logfloat val2_post = log(1.0f);+        for (int j = degree - 1; j >= 0; j--) {+            int tmp = var_edges[offset+j];+            int e = tmp >> 1;+            bool polarity = tmp & 1;+            logfloat eta_ai = edge_survey[e];+            float w = var_edges_weight[offset+j];++            logfloat2 pre = var_edges_buf[offset+j];+            logfloat val1 = pre.x + val1_post; // probability that other edges do not depends on v=1.+            logfloat val2 = pre.y + val2_post; // probability that other edges do not depends on v=0.+            logfloat pi_0 = val1 + val2; // Π^0_{i→a}+            logfloat pi_u; // Π^u_{i→a}+            logfloat pi_s; // Π^s_{i→a}+            if (polarity) {+                pi_u = comp(val2) + val1;+                pi_s = comp(val1) + val2;+                val1_post += comp(eta_ai) * w;+            } else {+                pi_u = comp(val1) + val2;+                pi_s = comp(val2) + val1;+                val2_post += comp(eta_ai) * w;+            }+            float psum = exp(pi_0) + exp(pi_u) + exp(pi_s);+            if (psum > 0) {+                edge_prob_u[e] = pi_u - log(psum);+            } else {+                edge_prob_u[e] = log(0.0f); // is that ok?+            }+        }+    }+}+++__kernel void+update_edge_survey(+   int n_clauses,+   CONSTANT int *clause_offset,     // int[n_clauses]+   CONSTANT int *clause_degree,     // int[n_clauses]+   __global logfloat *edge_survey,  // logfloat[n_edges]+   __global logfloat *edge_prob_u,  // logfloat[n_edges]+   __global logfloat *edge_buf,     // logfloat[n_edges]+   __global float *group_max_delta, // float[get_num_groups(0)]+   __local float *reduce_buf        // float[get_local_size(0)]+   )+{+    float max_delta = 0;++    int global_size = get_global_size(0);+    for (int a = get_global_id(0); a < n_clauses; a += global_size) {+        int len = clause_degree[a];+        int offset = clause_offset[a];++        logfloat pre = log(1.0f);+        for (int j = 0; j < len; j++) {+            int e = offset+j;+            edge_buf[e] = pre;+            pre += edge_prob_u[e];+        }++        logfloat post = log(1.0f);+        for (int j = len-1; j >=0; j--) {+            int e = offset+j;+            logfloat pre = edge_buf[e];+            logfloat eta_ai_orig = edge_survey[e];+            logfloat eta_ai_new  = pre + post;+            edge_survey[e] = eta_ai_new;+            max_delta = fmax(max_delta, fabs(exp(eta_ai_new) - exp(eta_ai_orig)));+            post += edge_prob_u[e];+        }+    }++    // reduction+    int local_id = get_local_id(0);+    int local_size = get_local_size(0);+    barrier(CLK_LOCAL_MEM_FENCE);+    reduce_buf[local_id] = max_delta;+    for (int stride = local_size / 2; stride > 0; stride /= 2) {+        barrier(CLK_LOCAL_MEM_FENCE);+        if (local_id < stride) {+            reduce_buf[local_id] = fmax(reduce_buf[local_id], reduce_buf[local_id + stride]);+        }+    }+    if (local_id==0)+        group_max_delta[get_group_id(0)] = reduce_buf[0];+}++__kernel void+compute_var_prob(+    int n_vars,+    CONSTANT int *var_offset,            // int[n_vars]+    CONSTANT int *var_degree,            // int[n_vars]+    __global logfloat2 *var_prob,        // logfloat2[n_vars]+    CONSTANT int *var_edges,             // int[M]+    CONSTANT logfloat *var_edges_weight, // logfloat[M]+    __global logfloat *edge_survey       // logfloat[E]+    )+{+    int global_size = get_global_size(0);++    for (int i = get_global_id(0); i < n_vars; i += global_size) {+        int offset = var_offset[i];+        int degree = var_degree[i];++        logfloat val1 = log(1.0f);+        logfloat val2 = log(1.0f);+        for (int j = 0; j < degree; j++) {+            int tmp = var_edges[offset+j];+            int e = tmp >> 1;+            bool polarity = tmp & 1;+            float eta_ai = edge_survey[e];+            float w = var_edges_weight[offset+j];++            if (polarity) {+              val1 += comp(eta_ai) * w;+            } else {+              val2 += comp(eta_ai) * w;+            }+        }++        float p0 = val1 + val2;       // \^{Π}^{0}_i+        float pp = comp(val1) + val2; // \^{Π}^{+}_i+        float pn = comp(val2) + val1; // \^{Π}^{-}_i+        float wp = pp - log(exp(pp) + exp(pn) + exp(p0)); // W^{(+)}_i+        float wn = pn - log(exp(pp) + exp(pn) + exp(p0)); // W^{(-)}_i+        var_prob[i] = (float2)(wp, wn);+    }+}
− src/ToySolver/SAT/PBNLC.hs
@@ -1,138 +0,0 @@-{-# OPTIONS_GHC -Wall #-}--------------------------------------------------------------------------------- |--- Module      :  ToySolver.SAT.PBNLC--- Copyright   :  (c) Masahiro Sakai 2015--- License     :  BSD-style--- --- Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  provisional--- Portability :  portable--- -------------------------------------------------------------------------------module ToySolver.SAT.PBNLC-  (-    PBTerm-  , PBSum--  -- * Adding constraints-  , addPBAtLeast-  , addPBAtMost  -  , addPBExactly-  , addPBAtLeastSoft-  , addPBAtMostSoft-  , addPBExactlySoft--  -- * Linearlization-  , linearizePBSum-  , linearizePBSumWithPolarity--  -- * Evaluation-  , evalPBSum-  ) where--import qualified ToySolver.SAT as SAT-import ToySolver.SAT.Types-import ToySolver.SAT.TseitinEncoder-import ToySolver.Internal.Util (revForM)--type PBTerm = (Integer, [Lit])-type PBSum = [PBTerm]---- | Add a non-linear pseudo boolean constraints /c1*ls1 + c2*ls2 + … ≥ n/.-addPBAtLeast-  :: Encoder-  -> PBSum   -- ^ @[(c1,ls1),(c2,ls2),…]@-  -> Integer -- ^ /n/-  -> IO ()-addPBAtLeast enc lhs rhs = do-  let c = sum [c | (c,[]) <- lhs]-  lhs' <- linearizePBSumWithPolarity enc polarityPos [(c,ls) | (c,ls) <- lhs, not (null ls)]-  SAT.addPBAtLeast (encSolver enc) lhs' (rhs - c)---- | Add a non-linear pseudo boolean constraints /c1*ls1 + c2*ls2 + … ≥ n/.-addPBAtMost-  :: Encoder-  -> PBSum   -- ^ @[(c1,ls1),(c2,ls2),…]@-  -> Integer -- ^ /n/-  -> IO ()-addPBAtMost enc lhs rhs =-  addPBAtLeast enc [(-c,ls) | (c,ls) <- lhs] (negate rhs)---- | Add a non-linear pseudo boolean constraints /c1*ls1 + c2*ls2 + … = n/.-addPBExactly-  :: Encoder-  -> PBSum   -- ^ @[(c1,ls1),(c2,ls2),…]@-  -> Integer -- ^ /n/-  -> IO ()-addPBExactly enc lhs rhs = do-  let c = sum [c | (c,[]) <- lhs]-  lhs' <- linearizePBSum enc [(c,ls) | (c,ls) <- lhs, not (null ls)]-  SAT.addPBExactly (encSolver enc) lhs' (rhs - c)---- | Add a soft non-linear pseudo boolean constraints /sel ⇒ c1*ls1 + c2*ls2 + … ≥ n/.-addPBAtLeastSoft-  :: Encoder-  -> Lit     -- ^ Selector literal @sel@-  -> PBSum   -- ^ @[(c1,ls1),(c2,ls2),…]@-  -> Integer -- ^ /n/-  -> IO ()-addPBAtLeastSoft enc sel lhs rhs = do-  let c = sum [c | (c,[]) <- lhs]-  lhs' <- linearizePBSumWithPolarity enc polarityPos [(c,ls) | (c,ls) <- lhs, not (null ls)]-  SAT.addPBAtLeastSoft (encSolver enc) sel lhs' (rhs - c)---- | Add a soft non-linear pseudo boolean constraints /sel ⇒ c1*ls1 + c2*ls2 + … ≤ n/.-addPBAtMostSoft-  :: Encoder-  -> Lit     -- ^ Selector literal @sel@-  -> PBSum   -- ^ @[(c1,ls1),(c2,ls2),…]@-  -> Integer -- ^ /n/-  -> IO ()-addPBAtMostSoft enc sel lhs rhs =-  addPBAtLeastSoft enc sel [(negate c, lit) | (c,lit) <- lhs] (negate rhs)---- | Add a soft non-linear pseudo boolean constraints /lit ⇒ c1*ls1 + c2*ls2 + … = n/.-addPBExactlySoft-  :: Encoder-  -> Lit     -- ^ indicator @lit@-  -> PBSum   -- ^ @[(c1,ls1),(c2,ls2),…]@-  -> Integer -- ^ /n/-  -> IO ()-addPBExactlySoft enc sel lhs rhs = do-  let c = sum [c | (c,[]) <- lhs]-  lhs' <- linearizePBSum enc [(c,ls) | (c,ls) <- lhs, not (null ls)]-  SAT.addPBExactlySoft (encSolver enc) sel lhs' (rhs - c)---- | Encode a non-linear 'PBSum' into a lienar 'PBLinSum'.------ @linearizePBSum enc s@ is equivalent to @linearizePBSumWithPolarity enc polarityBoth@.-linearizePBSum-  :: Encoder-  -> PBSum-  -> IO PBLinSum-linearizePBSum enc = linearizePBSumWithPolarity enc polarityBoth---- | Linearize a non-linear 'PBSum' into a lienar 'PBLinSum'.------ The input 'PBSum' is assumed to occur only in specified polarity.------ * If @'polarityPosOccurs' p@, the value of resulting 'PBLinSum' is /greater than/ or /equal to/ the value of original 'PBSum'.------ * If @'polarityNegOccurs' p@, the value of resulting 'PBLinSum' is /lesser than/ or /equal to/ the value of original 'PBSum'.--- -linearizePBSumWithPolarity-  :: Encoder-  -> Polarity -- polarity /p/-  -> PBSum-  -> IO PBLinSum-linearizePBSumWithPolarity enc p xs =-  revForM xs $ \(c,ls) -> do-    l <- if c > 0 then-           encodeConjWithPolarity enc p ls-         else-           encodeConjWithPolarity enc (negatePolarity p) ls-    return (c,l)--evalPBSum :: IModel m => m -> PBSum -> Integer-evalPBSum m xs = sum [c | (c,lits) <- xs, all (evalLit m) lits]
src/ToySolver/SAT/PBO.hs view
@@ -32,9 +32,11 @@   , isFinished    -- * Configulation-  , SearchStrategy (..)-  , getSearchStrategy-  , setSearchStrategy+  , Method (..)+  , showMethod+  , parseMethod+  , getMethod+  , setMethod   , defaultEnableObjFunVarsHeuristics   , getEnableObjFunVarsHeuristics   , setEnableObjFunVarsHeuristics@@ -50,6 +52,7 @@ import Control.Exception import Control.Monad import Data.Array.IArray+import Data.Char import Data.Default.Class import Data.IORef import qualified Data.Set as Set@@ -63,10 +66,10 @@ import qualified ToySolver.SAT.PBO.UnsatBased as UnsatBased import qualified ToySolver.SAT.PBO.MSU4 as MSU4 --- | Optimization strategy+-- | Optimization method -- -- The default value can be obtained by 'def'.-data SearchStrategy+data Method   = LinearSearch   | BinarySearch   | AdaptiveSearch@@ -77,14 +80,39 @@   | BCD2   deriving (Eq, Ord, Show, Enum, Bounded) -instance Default SearchStrategy where+instance Default Method where   def = LinearSearch +showMethod :: Method -> String+showMethod m =+  case m of+    LinearSearch -> "linear"+    BinarySearch -> "binary"+    AdaptiveSearch -> "adaptive"+    UnsatBased -> "unsat-based"+    MSU4 -> "msu4"+    BC -> "bc"+    BCD -> "bcd"+    BCD2 -> "bcd2"++parseMethod :: String -> Maybe Method+parseMethod s =+  case map toLower s of+    "linear"   -> Just LinearSearch+    "binary"   -> Just BinarySearch+    "adaptive" -> Just AdaptiveSearch+    "unsat"    -> Just UnsatBased+    "msu4"     -> Just MSU4+    "bc"       -> Just BC+    "bcd"      -> Just BCD+    "bcd2"     -> Just BCD2+    _ -> Nothing+ data Optimizer   = Optimizer   { optContext :: C.SimpleContext   , optSolver  :: SAT.Solver-  , optSearchStrategyRef :: IORef SearchStrategy+  , optMethodRef :: IORef Method   , optEnableObjFunVarsHeuristicsRef :: IORef Bool   , optTrialLimitConfRef :: IORef Int   }@@ -102,7 +130,7 @@     Optimizer     { optContext = cxt     , optSolver = solver-    , optSearchStrategyRef = strategyRef+    , optMethodRef = strategyRef     , optEnableObjFunVarsHeuristicsRef = heuristicsRef     , optTrialLimitConfRef = trialLimitRef     }@@ -123,7 +151,7 @@       forM_ (assocs m) $ \(v, val) -> do         SAT.setVarPolarity solver v val -  strategy <- getSearchStrategy opt+  strategy <- getMethod opt   case strategy of     UnsatBased -> UnsatBased.solve cxt solver     MSU4 -> MSU4.solve cxt solver@@ -163,11 +191,11 @@           adaptiveSearch cxt solver lim         _              -> error "ToySolver.SAT.PBO.minimize: should not happen"   -getSearchStrategy :: Optimizer -> IO SearchStrategy-getSearchStrategy opt = readIORef (optSearchStrategyRef opt)+getMethod :: Optimizer -> IO Method+getMethod opt = readIORef (optMethodRef opt) -setSearchStrategy :: Optimizer -> SearchStrategy -> IO ()-setSearchStrategy opt val = writeIORef (optSearchStrategyRef opt) val+setMethod :: Optimizer -> Method -> IO ()+setMethod opt val = writeIORef (optMethodRef opt) val  defaultEnableObjFunVarsHeuristics :: Bool defaultEnableObjFunVarsHeuristics = False
+ src/ToySolver/SAT/Store/CNF.hs view
@@ -0,0 +1,56 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.SAT.Store.CNF+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+-- Portability :  non-portable (FlexibleContexts, FlexibleInstances, MultiParamTypeClasses)+--+-----------------------------------------------------------------------------+module ToySolver.SAT.Store.CNF+  ( CNFStore+  , newCNFStore+  , getCNFFormula+  ) where++import Control.Monad.Primitive+import qualified Data.Foldable as F+import Data.Primitive.MutVar+import Data.Sequence (Seq, (|>))+import qualified Data.Sequence as Seq+import qualified ToySolver.SAT.Types as SAT+import qualified ToySolver.Text.CNF as CNF++data CNFStore m = CNFStore (MutVar (PrimState m) Int) (MutVar (PrimState m) (Seq SAT.Clause))++instance PrimMonad m => SAT.NewVar m (CNFStore m) where+  newVar (CNFStore ref _) = do+    modifyMutVar' ref (+1)+    readMutVar ref++instance PrimMonad m => SAT.AddClause m (CNFStore m) where+  addClause (CNFStore _ ref) clause =+    case SAT.normalizeClause clause of+      Just clause' -> modifyMutVar' ref (|> clause')+      Nothing -> return ()++newCNFStore :: PrimMonad m => m (CNFStore m)+newCNFStore = do+  ref1 <- newMutVar 0+  ref2 <- newMutVar Seq.empty+  return (CNFStore ref1 ref2)++getCNFFormula :: PrimMonad m => CNFStore m -> m CNF.CNF+getCNFFormula (CNFStore ref1 ref2) = do+  nv <- readMutVar ref1+  cs <- readMutVar ref2+  return $+     CNF.CNF+     { CNF.numVars = nv+     , CNF.numClauses = Seq.length cs+     , CNF.clauses = F.toList cs+     }
+ src/ToySolver/SAT/Store/PB.hs view
@@ -0,0 +1,72 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.SAT.Store.PB+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  experimental+-- Portability :  non-portable (FlexibleContexts, FlexibleInstances, MultiParamTypeClasses)+--+-----------------------------------------------------------------------------+module ToySolver.SAT.Store.PB+  ( PBStore+  , newPBStore+  , getPBFormula+  ) where++import Control.Monad.Primitive+import Data.Foldable (toList)+import Data.Primitive.MutVar+import Data.Sequence (Seq, (|>))+import qualified Data.Sequence as Seq+import qualified Data.PseudoBoolean as PBFile+import qualified ToySolver.SAT.Types as SAT++data PBStore m = PBStore (MutVar (PrimState m) Int) (MutVar (PrimState m) (Seq PBFile.Constraint))++instance PrimMonad m => SAT.NewVar m (PBStore m) where+  newVar (PBStore ref _) = do+    modifyMutVar' ref (+1)+    readMutVar ref++instance PrimMonad m => SAT.AddClause m (PBStore m) where+  addClause enc clause = SAT.addPBNLAtLeast enc [(1,[l]) | l <- clause] 1++instance PrimMonad m => SAT.AddCardinality m (PBStore m) where+  addAtLeast enc lhs rhs = SAT.addPBNLAtLeast enc [(1,[l]) | l <- lhs] (fromIntegral rhs)++instance PrimMonad m => SAT.AddPBLin m (PBStore m) where+  addPBAtLeast enc lhs rhs = SAT.addPBNLAtLeast enc [(c,[l]) | (c,l) <- lhs] rhs+  addPBAtMost enc lhs rhs  = SAT.addPBNLAtMost enc  [(c,[l]) | (c,l) <- lhs] rhs+  addPBExactly enc lhs rhs = SAT.addPBNLExactly enc [(c,[l]) | (c,l) <- lhs] rhs++instance PrimMonad m => SAT.AddPBNL m (PBStore m) where+  addPBNLAtLeast (PBStore _ ref) lhs rhs = do+    let lhs' = [(c,ls) | (c,ls@(_:_)) <- lhs]+        rhs' = rhs - sum [c | (c,[]) <- lhs]+    modifyMutVar' ref (|> (lhs', PBFile.Ge, rhs'))+  addPBNLExactly (PBStore _ ref) lhs rhs = do+    let lhs' = [(c,ls) | (c,ls@(_:_)) <- lhs]+        rhs' = rhs - sum [c | (c,[]) <- lhs]+    modifyMutVar' ref (|> (lhs', PBFile.Eq, rhs'))++newPBStore :: PrimMonad m => m (PBStore m)+newPBStore = do+  ref1 <- newMutVar 0+  ref2 <- newMutVar Seq.empty+  return (PBStore ref1 ref2)++getPBFormula :: PrimMonad m => PBStore m -> m (PBFile.Formula)+getPBFormula (PBStore ref1 ref2) = do+  nv <- readMutVar ref1+  cs <- readMutVar ref2+  return $+    PBFile.Formula+    { PBFile.pbObjectiveFunction = Nothing+    , PBFile.pbConstraints = toList cs+    , PBFile.pbNumVars = nv+    , PBFile.pbNumConstraints = Seq.length cs+    }
− src/ToySolver/SAT/TseitinEncoder.hs
@@ -1,330 +0,0 @@-{-# OPTIONS_GHC -Wall #-}--------------------------------------------------------------------------------- |--- Module      :  ToySolver.SAT.TseitinEncoder--- Copyright   :  (c) Masahiro Sakai 2012--- License     :  BSD-style--- --- Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  provisional--- Portability :  portable--- --- Tseitin encoding------ TODO:--- --- * reduce variables.------ References:------ * [Tse83] G. Tseitin. On the complexity of derivation in propositional---   calculus. Automation of Reasoning: Classical Papers in Computational---   Logic, 2:466-483, 1983. Springer-Verlag. ------ * [For60] R. Fortet. Application de l'algèbre de Boole en rechercheop---   opérationelle. Revue Française de Recherche Opérationelle, 4:17-26,---   1960. ------ * [BM84a] E. Balas and J. B. Mazzola. Nonlinear 0-1 programming:---   I. Linearization techniques. Mathematical Programming, 30(1):1-21,---   1984.--- --- * [BM84b] E. Balas and J. B. Mazzola. Nonlinear 0-1 programming:---   II. Dominance relations and algorithms. Mathematical Programming,---   30(1):22-45, 1984.------ * [PG86] D. Plaisted and S. Greenbaum. A Structure-preserving---    Clause Form Translation. In Journal on Symbolic Computation,---    volume 2, 1986.------ * [ES06] N . Eéen and N. Sörensson. Translating Pseudo-Boolean---   Constraints into SAT. JSAT 2:1–26, 2006.----------------------------------------------------------------------------------module ToySolver.SAT.TseitinEncoder-  (-  -- * The @Encoder@ type-    Encoder-  , newEncoder-  , setUsePB-  , encSolver--  -- * Polarity-  , Polarity (..)-  , negatePolarity-  , polarityPos-  , polarityNeg-  , polarityBoth-  , polarityNone--  -- * Boolean formula type-  , Formula-  , evalFormula--  -- * Encoding of boolean formulas-  , addFormula-  , encodeFormula-  , encodeFormulaWithPolarity-  , encodeConj-  , encodeConjWithPolarity-  , encodeDisj-  , encodeDisjWithPolarity-  , encodeITE-  , encodeITEWithPolarity--  -- * Retrieving definitions-  , getDefinitions-  ) where--import Control.Monad-import Data.IORef-import Data.Map (Map)-import qualified Data.Map as Map-import qualified Data.IntSet as IntSet-import ToySolver.Data.Boolean-import ToySolver.Data.BoolExpr-import qualified ToySolver.SAT as SAT-import qualified ToySolver.SAT.Types as SAT---- | Arbitrary formula not restricted to CNF-type Formula = BoolExpr SAT.Lit--evalFormula :: SAT.IModel m => m -> Formula -> Bool-evalFormula m = fold (SAT.evalLit m)---- | Encoder instance-data Encoder =-  Encoder-  { encSolver    :: SAT.Solver-  , encUsePB     :: IORef Bool-  , encConjTable :: !(IORef (Map SAT.LitSet (SAT.Lit, Bool, Bool)))-  , encITETable  :: !(IORef (Map (SAT.Lit, SAT.Lit, SAT.Lit) (SAT.Lit, Bool, Bool)))-  }---- | Create a @Encoder@ instance.-newEncoder :: SAT.Solver -> IO Encoder-newEncoder solver = do-  usePBRef <- newIORef False-  table <- newIORef Map.empty-  table2 <- newIORef Map.empty-  return $-    Encoder-    { encSolver = solver-    , encUsePB  = usePBRef-    , encConjTable = table-    , encITETable = table2-    }---- | Use /pseudo boolean constraints/ or use only /clauses/.-setUsePB :: Encoder -> Bool -> IO ()-setUsePB encoder usePB = writeIORef (encUsePB encoder) usePB---- | Assert a given formula to underlying SAT solver by using--- Tseitin encoding.-addFormula :: Encoder -> Formula -> IO ()-addFormula encoder formula = do-  let solver = encSolver encoder-  case formula of-    And xs -> mapM_ (addFormula encoder) xs-    Equiv a b -> do-      lit1 <- encodeFormula encoder a-      lit2 <- encodeFormula encoder b-      SAT.addClause solver [SAT.litNot lit1, lit2] -- a→b-      SAT.addClause solver [SAT.litNot lit2, lit1] -- b→a-    Not (Not a)     -> addFormula encoder a-    Not (Or xs)     -> addFormula encoder (andB (map notB xs))-    Not (Imply a b) -> addFormula encoder (a .&&. notB b)-    Not (Equiv a b) -> do-      lit1 <- encodeFormula encoder a-      lit2 <- encodeFormula encoder b-      SAT.addClause solver [lit1, lit2] -- a ∨ b-      SAT.addClause solver [SAT.litNot lit1, SAT.litNot lit2] -- ¬a ∨ ¬b-    _ -> do-      c <- encodeToClause encoder formula-      SAT.addClause solver c--encodeToClause :: Encoder -> Formula -> IO SAT.Clause-encodeToClause encoder formula =-  case formula of-    And [x] -> encodeToClause encoder x-    Or xs -> do-      cs <- mapM (encodeToClause encoder) xs-      return $ concat cs-    Not (Not x)  -> encodeToClause encoder x-    Not (And xs) -> do-      encodeToClause encoder (orB (map notB xs))-    Imply a b -> do-      encodeToClause encoder (notB a .||. b)-    _ -> do-      l <- encodeFormulaWithPolarity encoder polarityPos formula-      return [l]--encodeFormula :: Encoder -> Formula -> IO SAT.Lit-encodeFormula encoder = encodeFormulaWithPolarity encoder polarityBoth--encodeFormulaWithPolarity :: Encoder -> Polarity -> Formula -> IO SAT.Lit-encodeFormulaWithPolarity encoder p formula = do-  case formula of-    Atom l -> return l-    And xs -> encodeConjWithPolarity encoder p =<< mapM (encodeFormulaWithPolarity encoder p) xs-    Or xs  -> encodeDisjWithPolarity encoder p =<< mapM (encodeFormulaWithPolarity encoder p) xs-    Not x -> liftM SAT.litNot $ encodeFormulaWithPolarity encoder (negatePolarity p) x-    Imply x y -> do-      encodeFormulaWithPolarity encoder p (notB x .||. y)-    Equiv x y -> do-      lit1 <- encodeFormulaWithPolarity encoder polarityBoth x-      lit2 <- encodeFormulaWithPolarity encoder polarityBoth y-      encodeFormulaWithPolarity encoder p $-        (Atom lit1 .=>. Atom lit2) .&&. (Atom lit2 .=>. Atom lit1)-    ITE c t e -> do-      c' <- encodeFormulaWithPolarity encoder polarityBoth c-      t' <- encodeFormulaWithPolarity encoder p t-      e' <- encodeFormulaWithPolarity encoder p e-      encodeITEWithPolarity encoder p c' t' e'---- | Return an literal which is equivalent to a given conjunction.------ @---   encodeConj encoder = 'encodeConjWithPolarity' encoder 'polarityBoth'--- @-encodeConj :: Encoder -> [SAT.Lit] -> IO SAT.Lit-encodeConj encoder = encodeConjWithPolarity encoder polarityBoth---- | Return an literal which is equivalent to a given conjunction which occurs only in specified polarity.-encodeConjWithPolarity :: Encoder -> Polarity -> [SAT.Lit] -> IO SAT.Lit-encodeConjWithPolarity _ _ [l] =  return l-encodeConjWithPolarity encoder (Polarity pos neg) ls = do-  let ls2 = IntSet.fromList ls-  let solver = encSolver encoder-  usePB <- readIORef (encUsePB encoder)-  table <- readIORef (encConjTable encoder)--  let -- If F is monotone, F(A ∧ B) ⇔ ∃x. F(x) ∧ (x → A∧B)-      definePos :: SAT.Lit -> IO ()-      definePos l = do-        if usePB then do-          -- ∀i.(l → li) ⇔ Σli >= n*l ⇔ Σli - n*l >= 0-          let n = IntSet.size ls2-          SAT.addPBAtLeast solver ((- fromIntegral n, l) : [(1,li) | li <- IntSet.toList ls2]) 0-        else do-          forM_ (IntSet.toList ls2) $ \li -> do-            -- (l → li)  ⇔  (¬l ∨ li)-            SAT.addClause solver [SAT.litNot l, li]--      -- If F is anti-monotone, F(A ∧ B) ⇔ ∃x. F(x) ∧ (x ← A∧B) ⇔ ∃x. F(x) ∧ (x∨¬A∨¬B).-      defineNeg :: SAT.Lit -> IO ()-      defineNeg l = do-        let solver = encSolver encoder-        -- ((l1 ∧ l2 ∧ … ∧ ln) → l)  ⇔  (¬l1 ∨ ¬l2 ∨ … ∨ ¬ln ∨ l)-        SAT.addClause solver (l : map SAT.litNot (IntSet.toList ls2))--  case Map.lookup ls2 table of-    Just (l, posDefined, negDefined) -> do-      when (pos && not posDefined) $ definePos l-      when (neg && not negDefined) $ defineNeg l-      when (posDefined < pos || negDefined < neg) $-        modifyIORef (encConjTable encoder) (Map.insert ls2 (l, (max posDefined pos), (max negDefined neg)))-      return l-    Nothing -> do-      let sat = encSolver encoder-      l <- SAT.newVar sat-      when pos $ definePos l-      when neg $ defineNeg l-      modifyIORef (encConjTable encoder) (Map.insert ls2 (l, pos, neg))-      return l---- | Return an literal which is equivalent to a given disjunction.------ @---   encodeDisj encoder = 'encodeDisjWithPolarity' encoder 'polarityBoth'--- @-encodeDisj :: Encoder -> [SAT.Lit] -> IO SAT.Lit-encodeDisj encoder = encodeDisjWithPolarity encoder polarityBoth---- | Return an literal which is equivalent to a given disjunction which occurs only in specified polarity.-encodeDisjWithPolarity :: Encoder -> Polarity -> [SAT.Lit] -> IO SAT.Lit-encodeDisjWithPolarity _ _ [l] =  return l-encodeDisjWithPolarity encoder p ls = do-  -- ¬l ⇔ ¬(¬l1 ∧ … ∧ ¬ln) ⇔ (l1 ∨ … ∨ ln)-  l <- encodeConjWithPolarity encoder (negatePolarity p) [SAT.litNot li | li <- ls]-  return $ SAT.litNot l---- | Return an literal which is equivalent to a given if-then-else.------ @---   encodeITE encoder = 'encodeITEWithPolarity' encoder 'polarityBoth'--- @-encodeITE :: Encoder -> SAT.Lit -> SAT.Lit -> SAT.Lit -> IO SAT.Lit-encodeITE encoder = encodeITEWithPolarity encoder polarityBoth---- | Return an literal which is equivalent to a given if-then-else which occurs only in specified polarity.-encodeITEWithPolarity :: Encoder -> Polarity -> SAT.Lit -> SAT.Lit -> SAT.Lit -> IO SAT.Lit-encodeITEWithPolarity encoder p c t e | c < 0 =-  encodeITEWithPolarity encoder p (- c) e t-encodeITEWithPolarity encoder (Polarity pos neg) c t e = do-  let solver = encSolver encoder-  table <- readIORef (encITETable encoder)--  let definePos :: SAT.Lit -> IO ()-      definePos x = do-        -- x → ite(c,t,e)-        -- ⇔ x → (c∧t ∨ ¬c∧e)-        -- ⇔ (x∧c → t) ∧ (x∧¬c → e)-        -- ⇔ (¬x∨¬c∨t) ∧ (¬x∨c∨e)-        SAT.addClause solver [-x, -c, t]-        SAT.addClause solver [-x, c, e]-        SAT.addClause solver [t, e, -x] -- redundant, but will increase the strength of unit propagation.-  -      defineNeg :: SAT.Lit -> IO ()-      defineNeg x = do-        -- ite(c,t,e) → x-        -- ⇔ (c∧t ∨ ¬c∧e) → x-        -- ⇔ (c∧t → x) ∨ (¬c∧e →x)-        -- ⇔ (¬c∨¬t∨x) ∨ (c∧¬e∨x)-        SAT.addClause solver [-c, -t, x]-        SAT.addClause solver [c, -e, x]-        SAT.addClause solver [-t, -e, x] -- redundant, but will increase the strength of unit propagation.--  case Map.lookup (c,t,e) table of-    Just (l, posDefined, negDefined) -> do-      when (pos && not posDefined) $ definePos l-      when (neg && not negDefined) $ defineNeg l-      when (posDefined < pos || negDefined < neg) $-        modifyIORef (encITETable encoder) (Map.insert (c,t,e) (l, (max posDefined pos), (max negDefined neg)))-      return l-    Nothing -> do-      l <- SAT.newVar solver-      when pos $ definePos l-      when neg $ defineNeg l-      modifyIORef (encITETable encoder) (Map.insert (c,t,e) (l, pos, neg))-      return l---getDefinitions :: Encoder -> IO [(SAT.Lit, Formula)]-getDefinitions encoder = do-  t <- readIORef (encConjTable encoder)-  return $ [(l, andB [Atom l1 | l1 <- IntSet.toList ls]) | (ls, (l, _, _)) <- Map.toList t]---data Polarity-  = Polarity-  { polarityPosOccurs :: Bool-  , polarityNegOccurs :: Bool-  }-  deriving (Eq, Show)--negatePolarity :: Polarity -> Polarity-negatePolarity (Polarity pos neg) = (Polarity neg pos)--polarityPos :: Polarity-polarityPos = Polarity True False--polarityNeg :: Polarity-polarityNeg = Polarity False True--polarityBoth :: Polarity-polarityBoth = Polarity True True--polarityNone :: Polarity-polarityNone = Polarity False False-
src/ToySolver/SAT/Types.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ScopedTypeVariables, BangPatterns, FlexibleInstances #-}+{-# LANGUAGE ScopedTypeVariables, BangPatterns, FlexibleInstances, MultiParamTypeClasses, FunctionalDependencies #-} module ToySolver.SAT.Types   (   -- * Variable@@ -10,6 +10,7 @@   -- * Model   , IModel (..)   , Model+  , restrictModel    -- * Literal   , Lit@@ -39,7 +40,7 @@   , evalAtLeast   , evalExactly -  -- * Pseudo Boolean Constraint+  -- * (Linear) Pseudo Boolean Constraint   , PBLinTerm   , PBLinSum   , PBLinAtLeast@@ -58,12 +59,26 @@   , pbLowerBound   , pbUpperBound   , pbSubsume+  , evalPBConstraint +  -- * Non-linear Pseudo Boolean constraint+  , PBTerm+  , PBSum+  , evalPBSum+   -- * XOR Clause   , XORClause   , normalizeXORClause   , instantiateXORClause   , evalXORClause++  -- * Type classes for solvers+  , NewVar (..)+  , AddClause (..)+  , AddCardinality (..)+  , AddPBLin (..)+  , AddPBNL (..)+  , AddXORClause (..)   ) where  import Control.Monad@@ -76,6 +91,7 @@ import Data.IntSet (IntSet) import qualified Data.IntSet as IntSet import qualified Data.Vector as V+import qualified Data.PseudoBoolean as PBFile import ToySolver.Data.LBool import qualified ToySolver.Combinatorial.SubsetSum as SubsetSum @@ -95,6 +111,10 @@ -- | A model is represented as a mapping from variables to its values. type Model = UArray Var Bool +-- | Restrict model to first @nv@ variables.+restrictModel :: Int -> Model -> Model+restrictModel nv m = array (1,nv) [(v, m ! v) | v <- [1..nv]]+ instance IModel (UArray Var Bool) where   evalVar m v = m ! v @@ -388,7 +408,19 @@   where     lhs2' = IntMap.fromList [(l,c) | (c,l) <- lhs2] +type PBTerm = (Integer, [Lit])+type PBSum = [PBTerm] +evalPBSum :: IModel m => m -> PBSum -> Integer+evalPBSum m xs = sum [c | (c,lits) <- xs, all (evalLit m) lits]++evalPBConstraint :: IModel m => m -> PBFile.Constraint -> Bool+evalPBConstraint m (lhs,op,rhs) = op' (evalPBSum m lhs) rhs+  where+    op' = case op of+            PBFile.Ge -> (>=)+            PBFile.Eq -> (==)+ -- | XOR clause -- -- '([l1,l2..ln], b)' means l1 ⊕ l2 ⊕ ⋯ ⊕ ln = b.@@ -438,3 +470,192 @@     xor = (/=)     f 0 = True     f lit = evalLit m lit+++class Monad m => NewVar m a | a -> m where+  {-# MINIMAL newVar #-}++  -- | Add a new variable+  newVar :: a -> m Var++  -- | Add variables. @newVars a n = replicateM n (newVar a)@, but maybe faster.+  newVars :: a -> Int -> m [Var]+  newVars a n = replicateM n (newVar a)++  -- | Add variables. @newVars_ a n = newVars a n >> return ()@, but maybe faster.+  newVars_ :: a -> Int -> m ()+  newVars_ a n = replicateM_ n (newVar a)++class NewVar m a => AddClause m a | a -> m where+  addClause :: a -> Clause -> m ()++class AddClause m a => AddCardinality m a | a -> m where+  {-# MINIMAL addAtLeast #-}++  -- | Add a cardinality constraints /atleast({l1,l2,..},n)/.  +  addAtLeast+    :: a+    -> [Lit] -- ^ set of literals /{l1,l2,..}/ (duplicated elements are ignored)+    -> Int   -- ^ /n/+    -> m ()++  -- | Add a cardinality constraints /atmost({l1,l2,..},n)/.+  addAtMost+    :: a+    -> [Lit] -- ^ set of literals /{l1,l2,..}/ (duplicated elements are ignored)+    -> Int   -- ^ /n/+    -> m ()+  addAtMost a lits n = do+    addAtLeast a (map litNot lits) (length lits - n)++  -- | Add a cardinality constraints /exactly({l1,l2,..},n)/.+  addExactly+    :: a+    -> [Lit] -- ^ set of literals /{l1,l2,..}/ (duplicated elements are ignored)+    -> Int   -- ^ /n/+    -> m ()+  addExactly a lits n = do+    addAtLeast a lits n+    addAtMost a lits n++class AddCardinality m a => AddPBLin m a | a -> m where+  {-# MINIMAL addPBAtLeast #-}++  -- | Add a pseudo boolean constraints /c1*l1 + c2*l2 + … ≥ n/.+  addPBAtLeast+    :: a+    -> PBLinSum -- ^ list of terms @[(c1,l1),(c2,l2),…]@+    -> Integer  -- ^ /n/+    -> m ()++  -- | Add a pseudo boolean constraints /c1*l1 + c2*l2 + … ≤ n/.+  addPBAtMost+    :: a+    -> PBLinSum -- ^ list of @[(c1,l1),(c2,l2),…]@+    -> Integer  -- ^ /n/+    -> m ()+  addPBAtMost a ts n = addPBAtLeast a [(-c,l) | (c,l) <- ts] (negate n)++  -- | Add a pseudo boolean constraints /c1*l1 + c2*l2 + … = n/.+  addPBExactly+    :: a+    -> PBLinSum -- ^ list of terms @[(c1,l1),(c2,l2),…]@+    -> Integer  -- ^ /n/+    -> m ()+  addPBExactly a ts n = do+    addPBAtLeast a ts n+    addPBAtMost a ts n++  -- | Add a soft pseudo boolean constraints /sel ⇒ c1*l1 + c2*l2 + … ≥ n/.+  addPBAtLeastSoft+    :: a+    -> Lit             -- ^ Selector literal @sel@+    -> PBLinSum        -- ^ list of terms @[(c1,l1),(c2,l2),…]@+    -> Integer         -- ^ /n/+    -> m ()+  addPBAtLeastSoft a sel lhs rhs = do+    let (lhs2,rhs2) = normalizePBLinAtLeast (lhs,rhs)+    addPBAtLeast a ((rhs2, litNot sel) : lhs2) rhs2++  -- | Add a soft pseudo boolean constraints /sel ⇒ c1*l1 + c2*l2 + … ≤ n/.+  addPBAtMostSoft+    :: a+    -> Lit             -- ^ Selector literal @sel@+    -> PBLinSum        -- ^ list of terms @[(c1,l1),(c2,l2),…]@+    -> Integer         -- ^ /n/+    -> m ()+  addPBAtMostSoft a sel lhs rhs =+    addPBAtLeastSoft a sel [(negate c, lit) | (c,lit) <- lhs] (negate rhs)++  -- | Add a soft pseudo boolean constraints /sel ⇒ c1*l1 + c2*l2 + … = n/.+  addPBExactlySoft+    :: a+    -> Lit             -- ^ Selector literal @sel@+    -> PBLinSum        -- ^ list of terms @[(c1,l1),(c2,l2),…]@+    -> Integer         -- ^ /n/+    -> m ()+  addPBExactlySoft a sel lhs rhs = do+    addPBAtLeastSoft a sel lhs rhs+    addPBAtMostSoft a sel lhs rhs++class AddPBLin m a => AddPBNL m a | a -> m where+  {-# MINIMAL addPBNLAtLeast #-}++  -- | Add a non-linear pseudo boolean constraints /c1*ls1 + c2*ls2 + … ≥ n/.+  addPBNLAtLeast+    :: a+    -> PBSum   -- ^ List of terms @[(c1,ls1),(c2,ls2),…]@+    -> Integer -- ^ /n/+    -> m ()++  -- | Add a non-linear pseudo boolean constraints /c1*ls1 + c2*ls2 + … ≥ n/.+  addPBNLAtMost+    :: a+    -> PBSum   -- ^ List of terms @[(c1,ls1),(c2,ls2),…]@+    -> Integer -- ^ /n/+    -> m ()+  addPBNLAtMost a ts n = addPBNLAtLeast a [(-c,ls) | (c,ls) <- ts] (negate n)++  -- | Add a non-linear pseudo boolean constraints /c1*ls1 + c2*ls2 + … = n/.+  addPBNLExactly+    :: a+    -> PBSum   -- ^ List of terms @[(c1,ls1),(c2,ls2),…]@+    -> Integer -- ^ /n/+    -> m ()+  addPBNLExactly a ts n = do+    addPBNLAtLeast a ts n+    addPBNLAtMost a ts n++  -- | Add a soft non-linear pseudo boolean constraints /sel ⇒ c1*ls1 + c2*ls2 + … ≥ n/.+  addPBNLAtLeastSoft+    :: a+    -> Lit     -- ^ Selector literal @sel@+    -> PBSum   -- ^ List of terms @[(c1,ls1),(c2,ls2),…]@+    -> Integer -- ^ /n/+    -> m ()+  addPBNLAtLeastSoft a sel lhs rhs = do+    let n = rhs - sum [min c 0 | (c,_) <- lhs]+    addPBNLAtLeast a ((n, [litNot sel]) : lhs) rhs++  -- | Add a soft non-linear pseudo boolean constraints /sel ⇒ c1*ls1 + c2*ls2 + … ≤ n/.+  addPBNLAtMostSoft+    :: a+    -> Lit     -- ^ Selector literal @sel@+    -> PBSum   -- ^ List of terms @[(c1,ls1),(c2,ls2),…]@+    -> Integer -- ^ /n/+    -> m ()+  addPBNLAtMostSoft a sel lhs rhs =+    addPBNLAtLeastSoft a sel [(negate c, ls) | (c,ls) <- lhs] (negate rhs)++  -- | Add a soft non-linear pseudo boolean constraints /lit ⇒ c1*ls1 + c2*ls2 + … = n/.+  addPBNLExactlySoft+    :: a+    -> Lit     -- ^ Selector literal @sel@+    -> PBSum   -- ^ List of terms @[(c1,ls1),(c2,ls2),…]@+    -> Integer -- ^ /n/+    -> m ()+  addPBNLExactlySoft a sel lhs rhs = do+    addPBNLAtLeastSoft a sel lhs rhs+    addPBNLAtMostSoft a sel lhs rhs++class AddClause m a => AddXORClause m a | a -> m where+  {-# MINIMAL addXORClause #-}++  -- | Add a parity constraint /l1 ⊕ l2 ⊕ … ⊕ ln = rhs/+  addXORClause+    :: a+    -> [Lit]  -- ^ literals @[l1, l2, …, ln]@+    -> Bool   -- ^ /rhs/+    -> m ()++  -- | Add a soft parity constraint /sel ⇒ l1 ⊕ l2 ⊕ … ⊕ ln = rhs/+  addXORClauseSoft+    :: a+    -> Lit    -- ^ Selector literal @sel@+    -> [Lit]  -- ^ literals @[l1, l2, …, ln]@+    -> Bool   -- ^ /rhs/+    -> m ()+  addXORClauseSoft a sel lits rhs = do+    reified <- newVar a+    addXORClause a (litNot reified : lits) rhs+    addClause a [litNot sel, reified] -- sel ⇒ reified
src/ToySolver/SMT.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, DeriveDataTypeable, CPP #-}+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, DeriveDataTypeable, CPP, OverloadedStrings, ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- | -- Module      :  ToySolver.SMT@@ -7,7 +7,7 @@ --  -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  unstable--- Portability :  non-portable (MultiParamTypeClasses, FlexibleInstances, DeriveDataTypeable, CPP)+-- Portability :  non-portable (MultiParamTypeClasses, FlexibleInstances, DeriveDataTypeable, CPP, OverloadedStrings, ScopedTypeVariables) -- ----------------------------------------------------------------------------- module ToySolver.SMT@@ -23,10 +23,12 @@   , Sort (..)   , sBool   , sReal+  , sBitVec   , FunType   , Expr (..)   , exprSort-  , FSym+  , Index (..)+  , FSym (..)   , declareSSym   , declareSort   , VASortFun@@ -53,17 +55,22 @@   , valSort   , FunDef (..)   , evalFSym+  , modelGetAssertions    -- * Inspecting proofs   , getUnsatAssumptions   , getUnsatCore   ) where +import Control.Applicative import qualified Control.Exception as E import Control.Monad import Control.Monad.Trans import Control.Monad.Trans.Except+import Data.Bits import Data.Either+import Data.Interned (intern, unintern)+import Data.Interned.Text import Data.IntMap (IntMap) import qualified Data.IntMap as IntMap import Data.IntSet (IntSet)@@ -73,8 +80,11 @@ import Data.Map (Map) import qualified Data.Map as Map import Data.Maybe (catMaybes)+import Data.Monoid import Data.Set (Set) import qualified Data.Set as Set+import Data.String+import qualified Data.Text as T import Data.Typeable import Data.VectorSpace @@ -86,23 +96,36 @@ import qualified ToySolver.Internal.Data.Vec as Vec import qualified ToySolver.SAT as SAT import ToySolver.SAT.TheorySolver-import qualified ToySolver.SAT.TseitinEncoder as Tseitin-import qualified ToySolver.Arith.Simplex2 as Simplex2+import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin+import qualified ToySolver.Arith.Simplex as Simplex+import qualified ToySolver.BitVector as BV import qualified ToySolver.EUF.EUFSolver as EUF -type FSym = String+data Index+  = IndexNumeral !Integer+  | IndexSymbol !InternedText+  deriving (Show,Eq, Ord) +data FSym+  = FSym !InternedText [Index]+  deriving (Show,Eq,Ord)++instance IsString FSym where+  fromString s = FSym (fromString s) []+ -- | Sort symbols data SSym   = SSymBool   | SSymReal-  | SSymUserDeclared String !Int+  | SSymBitVec !Int+  | SSymUninterpreted !InternedText !Int   deriving (Show, Eq, Ord)  ssymArity :: SSym -> Int ssymArity SSymBool = 0 ssymArity SSymReal = 0-ssymArity (SSymUserDeclared _ ar) = ar+ssymArity (SSymBitVec _) = 0+ssymArity (SSymUninterpreted _ ar) = ar  data Sort = Sort SSym [Sort]   deriving (Show, Eq, Ord)@@ -113,11 +136,14 @@ sReal :: Sort sReal = Sort SSymReal [] +sBitVec :: Int -> Sort+sBitVec n = Sort (SSymBitVec n) []+ type FunType = ([Sort],Sort)  data Expr   = EAp FSym [Expr]-  | EFrac Rational+  | EValue !Value   deriving (Show, Eq, Ord)  instance MonotoneBoolean Expr where@@ -143,11 +169,11 @@   negate x = EAp "-" [x]   abs x = error "Num{ToySolver.SMT.Expr}.abs is not implemented"   signum x = error "Num{ToySolver.SMT.Expr}.signum is not implemented"-  fromInteger x = EFrac (fromInteger x)+  fromInteger x = EValue $ ValRational $ fromInteger x  instance Fractional Expr where   x / y = EAp "/" [x,y]-  fromRational x = EFrac x+  fromRational x = EValue $ ValRational x  instance IsEqRel Expr Expr where   a .==. b = EAp "=" [a,b]@@ -162,6 +188,7 @@ data FDef   = FBoolVar SAT.Var   | FLRAVar LA.Var+  | FBVVar BV.Var   | FEUFFun FunType EUF.FSym   deriving (Show) @@ -175,19 +202,23 @@ data Solver   = Solver   { smtSAT :: !SAT.Solver-  , smtEnc :: !Tseitin.Encoder+  , smtEnc :: !(Tseitin.Encoder IO)   , smtEUF :: !EUF.Solver-  , smtLRA :: !(Simplex2.GenericSolver (Delta Rational))+  , smtLRA :: !(Simplex.GenericSolver (Delta Rational))+  , smtBV :: !BV.Solver    , smtEUFAtomDefs  :: !(IORef (Map (EUF.Term, EUF.Term) SAT.Var, IntMap (EUF.Term, EUF.Term)))   , smtLRAAtomDefs  :: !(IORef (Map (LA.Var, Rational) (SAT.Lit, SAT.Lit, SAT.Lit), IntMap (LA.Atom Rational)))+  , smtBVAtomDefs   :: !(IORef (Map BVAtomNormalized SAT.Var, IntMap BVAtomNormalized))   , smtBoolTermDefs :: !(IORef (Map EUF.Term SAT.Lit, IntMap EUF.Term))   , smtRealTermDefs :: !(IORef (Map (LA.Expr Rational) EUF.FSym, IntMap (LA.Expr Rational)))+  , smtBVTermDefs :: !(IORef (Map BV.Expr EUF.FSym, IntMap (IntMap BV.Expr)))   , smtEUFTrue  :: !EUF.Term   , smtEUFFalse :: !EUF.Term    , smtEUFModel :: !(IORef EUF.Model)-  , smtLRAModel :: !(IORef Simplex2.Model)+  , smtLRAModel :: !(IORef Simplex.Model)+  , smtBVModel :: !(IORef BV.Model)    , smtGlobalDeclarationsRef :: !(IORef Bool)   , smtFDefs :: !(IORef (Map FSym FDef))@@ -205,12 +236,19 @@   , alSelector :: SAT.Lit   } +data TheorySolverID+  = TheorySolverEUF+  | TheorySolverSimplex+  | TheorySolverBV+  deriving (Eq, Ord, Enum, Bounded)+ newSolver :: IO Solver newSolver = do   sat <- SAT.newSolver   enc <- Tseitin.newEncoder sat   euf <- EUF.newSolver-  lra <- Simplex2.newSolver+  lra <- Simplex.newSolver+  bv <- BV.newSolver    litTrue <- Tseitin.encodeConj enc []   let litFalse = -litTrue@@ -222,83 +260,101 @@    eufAtomDefs <- newIORef (Map.empty, IntMap.empty)   lraAtomDefs <- newIORef (Map.empty, IntMap.empty)+  bvAtomDefs <- newIORef (Map.empty, IntMap.empty)   boolTermDefs <- newIORef $     ( Map.fromList [(eufTrue, litTrue), (eufFalse, litFalse)]     , IntMap.fromList [(litTrue, eufTrue), (litFalse, eufFalse)]     )   realTermDefs <- newIORef (Map.empty, IntMap.empty)+  bvTermDefs <- newIORef (Map.empty, IntMap.empty)    eufModelRef <- newIORef (undefined :: EUF.Model)-  lraModelRef <- newIORef (undefined :: Simplex2.Model)+  lraModelRef <- newIORef (undefined :: Simplex.Model)+  bvModelRef <- newIORef (undefined :: BV.Model)    globalDeclarationsRef <- newIORef False   fdefs <- newIORef $ Map.singleton "_/0" (FEUFFun ([sReal], sReal) divByZero) -  conflictTheory <- newIORef True+  conflictTheory <- newIORef undefined    let tsolver =         TheorySolver-        { thAssertLit = \_ l -> do-            (_, defsLRA) <- readIORef lraAtomDefs-            (_, defsEUF) <- readIORef eufAtomDefs+        { thAssertLit = \_ l -> liftM (either id id) $ runExceptT $ do+            (_, defsLRA) <- lift $ readIORef lraAtomDefs             case IntMap.lookup l defsLRA of+              Nothing -> return ()               Just atom -> do-                Simplex2.assertAtomEx' lra atom (Just l)-                return True-              Nothing ->-                case IntMap.lookup (SAT.litVar l) defsEUF of-                  Just (t1,t2) -> do-                    if SAT.litPolarity l then do-                      EUF.assertEqual' euf t1 t2 (Just l)-                      return True-                    else do-                      EUF.assertNotEqual' euf t1 t2 (Just l)-                      return True-                  Nothing ->-                    return True-        , thCheck = \callback -> do-            b <- Simplex2.check lra-            if b then do-              b2 <- EUF.check euf-              if b2 then do-                (_, defsEUF) <- readIORef eufAtomDefs-                liftM isRight $ runExceptT $ do-                  forM_ (IntMap.toList defsEUF) $ \(v, (t1, t2)) -> do-                    b3 <- lift $ EUF.areEqual euf t1 t2-                    when b3 $ do-                      b4 <- lift $ callback v-                      unless b4 $ throwE ()-              else do-                writeIORef conflictTheory False-                return b2-            else do-              writeIORef conflictTheory True-              return False+                lift $ Simplex.assertAtomEx' lra atom (Just l)+                throwE True++            (_, defsEUF) <- lift $ readIORef eufAtomDefs+            case IntMap.lookup (SAT.litVar l) defsEUF of+              Nothing -> return ()+              Just (t1,t2) -> do+                if SAT.litPolarity l then do+                  lift $ EUF.assertEqual' euf t1 t2 (Just l)+                else do+                  lift $ EUF.assertNotEqual' euf t1 t2 (Just l)+                throwE True++            (_, defsBV) <- lift $ readIORef bvAtomDefs+            case IntMap.lookup (SAT.litVar l) defsBV of+              Nothing -> return ()+              Just atom -> do+                lift $ BV.assertAtom bv (unnormalizeBVAtom (atom, SAT.litPolarity l)) (Just l)+                throwE True++            return True++        , thCheck = \callback -> liftM isRight $ runExceptT $ do+            do b <- lift $ Simplex.check lra+               unless b $ do+                 lift $ writeIORef conflictTheory TheorySolverSimplex+                 throwE ()+            do b <- lift $ EUF.check euf+               unless b $ do+                 lift $ writeIORef conflictTheory TheorySolverEUF+                 throwE ()+               (_, defsEUF) <- lift $ readIORef eufAtomDefs+               forM_ (IntMap.toList defsEUF) $ \(v, (t1, t2)) -> do+                  b2 <- lift $ EUF.areEqual euf t1 t2+                  when b2 $ do+                    b3 <- lift $ callback v+                    unless b3 $ throwE ()+            do b <- lift $ BV.check bv+               unless b $ do+                 lift $ writeIORef conflictTheory TheorySolverBV+                 throwE ()+         , thExplain = \m -> do             case m of               Nothing -> do-                b <- readIORef conflictTheory-                if b then-                  liftM IntSet.toList $ Simplex2.explain lra-                else-                  liftM IntSet.toList $ EUF.explain euf Nothing+                t <- readIORef conflictTheory+                case t of+                  TheorySolverSimplex -> liftM IntSet.toList $ Simplex.explain lra+                  TheorySolverBV -> liftM IntSet.toList $ BV.explain bv+                  TheorySolverEUF -> liftM IntSet.toList $ EUF.explain euf Nothing               Just v -> do                 (_, defsEUF) <- readIORef eufAtomDefs                 case IntMap.lookup v defsEUF of                   Nothing -> error "should not happen"                   Just (t1,t2) -> liftM IntSet.toList $ EUF.explain euf (Just (t1,t2))+         , thPushBacktrackPoint = do-            Simplex2.pushBacktrackPoint lra+            Simplex.pushBacktrackPoint lra             EUF.pushBacktrackPoint euf+            BV.pushBacktrackPoint bv         , thPopBacktrackPoint = do-            Simplex2.popBacktrackPoint lra+            Simplex.popBacktrackPoint lra             EUF.popBacktrackPoint euf+            BV.popBacktrackPoint bv         , thConstructModel = do             writeIORef eufModelRef =<< EUF.getModel euf-            -- We need to call Simplex2.getModel here.+            -- We need to call Simplex.getModel here.             -- Because backtracking removes constraints that are necessary             -- for computing the value of delta.-            writeIORef lraModelRef =<< Simplex2.getModel lra+            writeIORef lraModelRef =<< Simplex.getModel lra+            writeIORef bvModelRef =<< BV.getModel bv             return ()         }   SAT.setTheory sat tsolver@@ -316,16 +372,20 @@     , smtEnc = enc     , smtEUF = euf     , smtLRA = lra+    , smtBV  = bv      , smtEUFAtomDefs = eufAtomDefs     , smtLRAAtomDefs = lraAtomDefs+    , smtBVAtomDefs = bvAtomDefs     , smtBoolTermDefs = boolTermDefs     , smtRealTermDefs = realTermDefs+    , smtBVTermDefs = bvTermDefs     , smtEUFTrue  = eufTrue     , smtEUFFalse = eufFalse      , smtEUFModel = eufModelRef     , smtLRAModel = lraModelRef+    , smtBVModel = bvModelRef      , smtGlobalDeclarationsRef = globalDeclarationsRef     , smtFDefs = fdefs@@ -337,7 +397,7 @@     }  declareSSym :: Solver -> String -> Int -> IO SSym-declareSSym solver name arity = return (SSymUserDeclared name arity)+declareSSym solver name arity = return (SSymUninterpreted (fromString name) arity)  declareSort :: VASortFun a => Solver -> String -> Int -> IO a declareSort solver name arity = do@@ -360,18 +420,22 @@   arityVASortFun f = arityVASortFun (f undefined) + 1  declareFSym :: Solver -> String -> [Sort] -> Sort -> IO FSym-declareFSym solver f xs y = do+declareFSym solver f' xs y = do+  let f = FSym (intern (T.pack f')) []   fdefs <- readIORef (smtFDefs solver)   when (f `Map.member` fdefs) $ do-    E.throwIO $ Error $ "function symbol " ++ f ++ " is already used"+    E.throwIO $ Error $ "function symbol " ++ f' ++ " is already used"   fdef <-     case (xs, y) of-      ([], Sort SSymBool []) -> do+      ([], Sort SSymBool _) -> do         v <- SAT.newVar (smtSAT solver)         return (FBoolVar v)-      ([], Sort SSymReal []) -> do-        v <- Simplex2.newVar (smtLRA solver)+      ([], Sort SSymReal _) -> do+        v <- Simplex.newVar (smtLRA solver)         return (FLRAVar v)+      ([], Sort (SSymBitVec n) _) -> do+        v <- BV.newVar' (smtBV solver) n+        return (FBVVar v)       _ -> do         v <- EUF.newFSym (smtEUF solver)         return (FEUFFun (xs,y) v)@@ -428,16 +492,40 @@   return $! exprSort' fdefs e  exprSort' :: Map FSym FDef -> Expr -> Sort-exprSort' _fdefs (EFrac _) = Sort SSymReal []+exprSort' _fdefs (EValue v) = valSort v exprSort' fdefs (EAp f xs)-  | f `Set.member` Set.fromList ["true","false","and","or","not","=>","=",">=","<=",">","<"] = Sort SSymBool []-  | f `Set.member` Set.fromList ["+", "-", "*", "/"] = Sort SSymReal []+  | f `Set.member` Set.fromList ["true","false","and","or","xor","not","=>","=",">=","<=",">","<"] = sBool+  | f `Set.member` Set.fromList ["bvule", "bvult", "bvuge", "bvugt", "bvsle", "bvslt", "bvsge", "bvsgt"] = sBool+  | f `Set.member` Set.fromList ["+", "-", "*", "/"] = sReal+  | FSym "extract" [IndexNumeral i, IndexNumeral j] <- f = sBitVec (fromIntegral (i - j + 1))+  | f == "concat" =+      case (exprSort' fdefs (xs !! 0), exprSort' fdefs (xs !! 1)) of+        (Sort (SSymBitVec m) [], Sort (SSymBitVec n) []) -> sBitVec (m+n)+        _ -> undefined+  | FSym "repeat" [IndexNumeral i] <- f =+      case exprSort' fdefs (xs !! 0) of+        Sort (SSymBitVec m) [] -> sBitVec (m * fromIntegral i)+        _ -> undefined+  | FSym name [IndexNumeral i] <- f, name == "zero_extend" || name == "sign_extend" =+      case exprSort' fdefs (xs !! 0) of+        Sort (SSymBitVec m) [] -> sBitVec (m + fromIntegral i)+        _ -> undefined+  | FSym name [IndexNumeral i] <- f, name == "rotate_left" || name == "rotate_right" =+      exprSort' fdefs (xs !! 0)+  | f == "bvnot" || f == "bvneg" = exprSort' fdefs (xs !! 0)+  | f == "bvcomp" = sBitVec 1+  | f `Set.member` Set.fromList [name | (name, _op::BV.BV->BV.BV->BV.BV) <- bvBinOpsSameSize] =+      exprSort' fdefs (xs !! 0)   | f == "ite" = exprSort' fdefs (xs !! 1)   | otherwise =-      case fdefs Map.! f of-        FBoolVar _ -> Sort SSymBool []-        FLRAVar _ -> Sort SSymReal []-        FEUFFun (_,s) _ -> s+      case Map.lookup f fdefs of+        Nothing -> error $ show f ++ " was not found"+        Just fdef ->+          case fdef of+            FBoolVar _ -> sBool+            FLRAVar _ -> sReal+            FBVVar v -> sBitVec (BV.varWidth v)+            FEUFFun (_,s) _ -> s  -- -------------------------------------------------------------------                                               @@ -448,6 +536,9 @@   liftM andB $ mapM (exprToFormula solver) xs exprToFormula solver (EAp "or" xs) =   liftM orB $ mapM (exprToFormula solver) xs+exprToFormula solver (EAp "xor" xs) = do+  ys <- mapM (exprToFormula solver) xs+  return $ foldr (\a b -> notB (a .<=>. b)) false ys exprToFormula solver (EAp "not" [x]) =   liftM notB $ exprToFormula solver x exprToFormula solver (EAp "not" _) = undefined@@ -496,6 +587,21 @@     Just (FBoolVar v) -> return (Atom v)     Just _ -> E.throwIO $ Error "non Bool constant appears in a boolean context"     Nothing -> E.throwIO $ Error $ "unknown function symbol: " ++ show f+exprToFormula solver (EAp op [e1,e2]) | Just f <- Map.lookup op table = do+  e1' <- exprToBVExpr solver e1+  e2' <- exprToBVExpr solver e2+  liftM Atom $ abstractBVAtom solver (f e1' e2')+  where+    table = Map.fromList+      [ ("bvule", BV.bvule)+      , ("bvult", BV.bvult)+      , ("bvuge", BV.bvuge)+      , ("bvugt", BV.bvugt)+      , ("bvsle", BV.bvsle)+      , ("bvslt", BV.bvslt)+      , ("bvsge", BV.bvsge)+      , ("bvsgt", BV.bvsgt)+      ] exprToFormula solver (EAp f xs) = do   e' <- exprToEUFTerm solver f xs   formulaFromEUFTerm solver e'@@ -520,7 +626,11 @@       e1' <- exprToLRAExpr solver e1       e2' <- exprToLRAExpr solver e2       liftM Atom $ abstractLRAAtom solver (e1' .==. e2')-    (Sort (SSymUserDeclared _ _) _) -> do+    (Sort (SSymBitVec _) _) -> do+      e1' <- exprToBVExpr solver e1+      e2' <- exprToBVExpr solver e2+      liftM Atom $ abstractBVAtom solver (e1' .==. e2')+    (Sort (SSymUninterpreted _ _) _) -> do       e1' <- exprToEUFArg solver e1       e2' <- exprToEUFArg solver e2       liftM Atom $ abstractEUFAtom solver (e1',e2')@@ -528,7 +638,7 @@ -- -------------------------------------------------------------------  exprToLRAExpr :: Solver -> Expr -> IO (LA.Expr Rational)-exprToLRAExpr solver (EFrac r) = return (LA.constant r)+exprToLRAExpr solver (EValue (ValRational r)) = return (LA.constant r) exprToLRAExpr solver (EAp "-" []) = E.throwIO $ Error "ToySolver.SMT: nullary '-' function" exprToLRAExpr solver (EAp "-" [x]) = liftM negateV $ exprToLRAExpr solver x exprToLRAExpr solver (EAp "-" (x:xs)) = do@@ -553,7 +663,7 @@       return $ (1/c) *^ x' exprToLRAExpr solver (EAp "ite" [c,t,e]) = do   c' <- exprToFormula solver c-  ret <- liftM LA.var $ Simplex2.newVar (smtLRA solver)+  ret <- liftM LA.var $ Simplex.newVar (smtLRA solver)   t' <- exprToLRAExpr solver t   e' <- exprToLRAExpr solver e   c1 <- abstractLRAAtom solver (ret .==. t')@@ -565,7 +675,7 @@  abstractLRAAtom :: Solver -> LA.Atom Rational -> IO SAT.Lit abstractLRAAtom solver atom = do-  (v,op,rhs) <- Simplex2.simplifyAtom (smtLRA solver) atom+  (v,op,rhs) <- Simplex.simplifyAtom (smtLRA solver) atom   (tbl,defs) <- readIORef (smtLRAAtomDefs solver)   (vLt, vEq, vGt) <-     case Map.lookup (v,rhs) tbl of@@ -621,7 +731,7 @@   case IntMap.lookup c fsymToReal of     Just e -> return e     Nothing -> do-      v <- Simplex2.newVar (smtLRA solver)+      v <- Simplex.newVar (smtLRA solver)       let e = LA.var v       forM_ (IntMap.toList fsymToReal) $ \(d, d_lra) -> do         -- allocate interface equalities@@ -636,6 +746,155 @@  -- ------------------------------------------------------------------- +bvBinOpsSameSize :: (IsString s, BV.IsBV bv) => [(s, bv -> bv -> bv)]+bvBinOpsSameSize =+  [ ("bvand", BV.bvand)+  , ("bvor", BV.bvor)+  , ("bvxor", BV.bvxor)+  , ("bvnand", BV.bvnand)+  , ("bvnor", BV.bvnor)+  , ("bvxnor", BV.bvxnor)+  , ("bvadd", BV.bvadd)+  , ("bvsub", BV.bvsub)+  , ("bvmul", BV.bvmul)+  , ("bvudiv", BV.bvudiv)+  , ("bvurem", BV.bvurem)+  , ("bvsdiv", BV.bvsdiv)+  , ("bvsrem", BV.bvsrem)+  , ("bvsmod", BV.bvsmod)+  , ("bvshl", BV.bvshl)+  , ("bvlshr", BV.bvlshr)+  , ("bvashr", BV.bvashr)+  ]++exprToBVExpr :: Solver -> Expr -> IO BV.Expr+exprToBVExpr solver (EValue (ValBitVec bv)) = return $ BV.fromBV bv+exprToBVExpr solver (EAp "concat" [x,y]) = do+  liftM2 (<>) (exprToBVExpr solver x) (exprToBVExpr solver y)+exprToBVExpr solver (EAp (FSym "extract" [IndexNumeral i, IndexNumeral j]) [x]) = do+  BV.extract (fromIntegral i) (fromIntegral j) <$> exprToBVExpr solver x+exprToBVExpr solver (EAp (FSym "repeat" [IndexNumeral i]) [x]) = do+  BV.repeat (fromIntegral i) <$> exprToBVExpr solver x+exprToBVExpr solver (EAp (FSym "zero_extend" [IndexNumeral i]) [x]) = do+  BV.zeroExtend (fromIntegral i) <$> exprToBVExpr solver x+exprToBVExpr solver (EAp (FSym "sign_extend" [IndexNumeral i]) [x]) = do+  BV.signExtend (fromIntegral i) <$> exprToBVExpr solver x+exprToBVExpr solver (EAp (FSym "rotate_left" [IndexNumeral i]) [x]) = do+  rotateL <$> exprToBVExpr solver x <*> pure (fromIntegral i)+exprToBVExpr solver (EAp (FSym "rotate_right" [IndexNumeral i]) [x]) = do+  rotateR <$> exprToBVExpr solver x <*> pure (fromIntegral i)+exprToBVExpr solver (EAp (FSym op1 []) [x])+  | Just op1' <- Map.lookup op1 table = op1' <$> exprToBVExpr solver x+  where+    table =+      Map.fromList+      [ ("bvnot", BV.bvnot)+      , ("bvneg", BV.bvneg)+      ]+exprToBVExpr solver (EAp (FSym op2 []) [x,y])+  | Just op2' <- Map.lookup op2 table = liftM2 op2' (exprToBVExpr solver x) (exprToBVExpr solver y)+  where+    table = Map.fromList $ [("bvcomp", BV.bvcomp)] ++ bvBinOpsSameSize+exprToBVExpr solver (EAp "ite" [c,t,e]) = do+  c' <- exprToFormula solver c+  t' <- exprToBVExpr solver t+  e' <- exprToBVExpr solver e+  ret <- BV.newVar (smtBV solver) (BV.width t')+  c1 <- abstractBVAtom solver (ret .==. t')+  c2 <- abstractBVAtom solver (ret .==. e')+  Tseitin.addFormula (smtEnc solver) $ ite c' (Atom c1) (Atom c2)+  return ret+exprToBVExpr solver e@(EAp f xs) = do+  s <- exprSort solver e+  case s of+    Sort (SSymBitVec w) [] -> do+      t <- exprToEUFTerm solver f xs+      bvExprFromTerm solver t w+    _ -> error "should not happen"++data BVAtomNormalized+  = BVEql BV.Expr BV.Expr+  | BVULt BV.Expr BV.Expr+  | BVSLt BV.Expr BV.Expr+  deriving (Eq, Ord)++normalizeBVAtom :: BV.Atom -> (BVAtomNormalized, Bool)+normalizeBVAtom (BV.Rel (OrdRel lhs op rhs) False) =+  case op of+    Lt  -> (BVULt lhs rhs, True)+    Gt  -> (BVULt rhs lhs, True)+    Eql -> (BVEql lhs rhs, True)+    NEq -> (BVEql lhs rhs, False)+    Le  -> (BVULt rhs lhs, False)+    Ge  -> (BVULt lhs rhs, False)+normalizeBVAtom (BV.Rel (OrdRel lhs op rhs) True) =+  case op of+    Lt  -> (BVSLt lhs rhs, True)+    Gt  -> (BVSLt rhs lhs, True)+    Eql -> (BVEql lhs rhs, True)+    NEq -> (BVEql lhs rhs, False)+    Le  -> (BVSLt rhs lhs, False)+    Ge  -> (BVSLt lhs rhs, False)++unnormalizeBVAtom :: (BVAtomNormalized, Bool) -> BV.Atom+unnormalizeBVAtom (BVEql lhs rhs, p) = (if p then id else notB) $ BV.Rel (OrdRel lhs Eql rhs) False+unnormalizeBVAtom (BVULt lhs rhs, p) = (if p then id else notB) $ BV.Rel (OrdRel lhs Lt rhs) False+unnormalizeBVAtom (BVSLt lhs rhs, p) = (if p then id else notB) $ BV.Rel (OrdRel lhs Lt rhs) True++abstractBVAtom :: Solver -> BV.Atom -> IO SAT.Lit+abstractBVAtom solver atom = do+  let (atom', s) = normalizeBVAtom atom+  (tbl,defs) <- readIORef (smtBVAtomDefs solver)+  v <- case Map.lookup atom' tbl of+         Just v -> return v+         Nothing -> do+           v <- SAT.newVar (smtSAT solver)+           writeIORef (smtBVAtomDefs solver) (Map.insert atom' v tbl, IntMap.insert v atom' defs)+           return v+  return $ if s then v else -v++bvExprToEUFTerm :: Solver -> BV.Expr -> IO EUF.Term+bvExprToEUFTerm solver e = do+  (bvToFSym, fsymToBV) <- readIORef (smtBVTermDefs solver)+  case Map.lookup e bvToFSym of+    Just c -> return (EUF.TApp c [])+    Nothing -> do+      c <- EUF.newFSym (smtEUF solver)+      let w = BV.width e+          m = IntMap.findWithDefault IntMap.empty w fsymToBV +      forM_ (IntMap.toList m) $ \(d, d_bv) -> do+        -- allocate interface equalities+        b1 <- abstractEUFAtom solver (EUF.TApp c [], EUF.TApp d [])+        b2 <- abstractBVAtom solver (e .==. d_bv)+        Tseitin.addFormula (smtEnc solver) (Atom b1 .<=>. Atom b2)+      writeIORef (smtBVTermDefs solver) $+        ( Map.insert e c bvToFSym+        , IntMap.insert w (IntMap.insert c e m) fsymToBV+        )+      return (EUF.TApp c [])++bvExprFromTerm :: Solver -> EUF.Term -> Int -> IO BV.Expr+bvExprFromTerm solver t w = do+  (bvToFSym, fsymToBV) <- readIORef (smtBVTermDefs solver)+  c <- EUF.termToFSym (smtEUF solver) t+  let m = IntMap.findWithDefault IntMap.empty w fsymToBV+  case IntMap.lookup c m of+    Just e -> return e+    Nothing -> do+      e <- BV.newVar (smtBV solver) w+      forM_ (IntMap.toList m) $ \(d, d_bv) -> do+        -- allocate interface equalities+        b1 <- abstractEUFAtom solver (EUF.TApp c [], EUF.TApp d [])+        b2 <- abstractBVAtom solver (e .==. d_bv)+        Tseitin.addFormula (smtEnc solver) (Atom b1 .<=>. Atom b2)+      writeIORef (smtBVTermDefs solver) $+        ( Map.insert e c bvToFSym+        , IntMap.insert w (IntMap.insert c e m) fsymToBV+        )+      return e++-- -------------------------------------------------------------------+ exprToEUFTerm :: Solver -> FSym -> [Expr] -> IO EUF.Term exprToEUFTerm solver "ite" [c,t,e] = do   c' <- exprToFormula solver c@@ -651,19 +910,26 @@   case Map.lookup f fdefs of     Just (FBoolVar v) -> formulaToEUFTerm solver (Atom v)     Just (FLRAVar v) -> lraExprToEUFTerm solver (LA.var v)+    Just (FBVVar v) -> bvExprToEUFTerm solver (BV.EVar v)     Just (FEUFFun (ps,_) fsym) -> do       unless (length ps == length xs) $ do         E.throwIO $ Error "argument number error"       liftM (EUF.TApp fsym) $ mapM (exprToEUFArg solver) xs     _ -> E.throw $ Error $ "unknown function symbol: " ++ show f +valToEUFArg :: Solver -> Value -> IO EUF.Term+valToEUFArg solver (ValBool b) = return $! if b then smtEUFTrue solver else smtEUFFalse solver+valToEUFArg solver (ValRational r) = lraExprToEUFTerm solver (LA.constant r)+valToEUFArg solver (ValBitVec bv) = bvExprToEUFTerm solver (BV.fromBV bv)+ exprToEUFArg :: Solver -> Expr -> IO EUF.Term-exprToEUFArg solver (EFrac r) = lraExprToEUFTerm solver (LA.constant r)+exprToEUFArg solver (EValue v) = valToEUFArg solver v exprToEUFArg solver e@(EAp f xs) = do   Sort s _ <- exprSort solver e   case s of     SSymBool -> formulaToEUFTerm solver =<< exprToFormula solver e     SSymReal -> lraExprToEUFTerm solver =<< exprToLRAExpr solver e+    SSymBitVec _ -> bvExprToEUFTerm solver =<< exprToBVExpr solver e     _ -> exprToEUFTerm solver f xs  abstractEUFAtom :: Solver -> (EUF.Term, EUF.Term) -> IO SAT.Lit@@ -784,48 +1050,63 @@   = Model   { mDefs      :: !(Map FSym FDef)   , mBoolModel :: !SAT.Model-  , mLRAModel  :: !Simplex2.Model+  , mLRAModel  :: !Simplex.Model+  , mBVModel   :: !BV.Model   , mEUFModel  :: !EUF.Model   , mEUFTrue   :: !EUF.Entity   , mEUFFalse  :: !EUF.Entity   , mEntityToRational :: !(IntMap Rational)   , mRationalToEntity :: !(Map Rational EUF.Entity)+  , mEntityToBitVec :: !(IntMap BV.BV)+  , mBitVecToEntity :: !(Map BV.BV EUF.Entity)   }   deriving (Show)  data Value   = ValRational !Rational+  | ValBitVec !BV.BV   | ValBool !Bool   | ValUninterpreted !Int !Sort-  deriving (Eq, Show)+  deriving (Eq, Ord, Show)  getModel :: Solver -> IO Model getModel solver = do   defs <- readIORef (smtFDefs solver)   boolModel <- SAT.getModel (smtSAT solver)   lraModel <- readIORef (smtLRAModel solver)+  bvModel  <- readIORef (smtBVModel solver)   eufModel <- readIORef (smtEUFModel solver)+   (_, fsymToReal) <- readIORef (smtRealTermDefs solver)-  let xs = [(e, LA.evalExpr lraModel lraExpr) | (fsym, lraExpr) <- IntMap.toList fsymToReal, let e = EUF.evalAp eufModel fsym [], e /= EUF.mUnspecified eufModel]+  let xs = [(e, LA.eval lraModel lraExpr) | (fsym, lraExpr) <- IntMap.toList fsymToReal, let e = EUF.evalAp eufModel fsym [], e /= EUF.mUnspecified eufModel]++  (_, fsymToBV) <- readIORef (smtBVTermDefs solver)+  let ys = [(e, BV.evalExpr bvModel bvExpr) | (w,m) <- IntMap.toList fsymToBV, (fsym, bvExpr) <- IntMap.toList m, let e = EUF.evalAp eufModel fsym [], e /= EUF.mUnspecified eufModel]+   return $     Model     { mDefs = defs     , mBoolModel = boolModel     , mLRAModel = lraModel+    , mBVModel  = bvModel     , mEUFModel = eufModel     , mEUFTrue  = EUF.eval eufModel (smtEUFTrue solver)     , mEUFFalse = EUF.eval eufModel (smtEUFFalse solver)     , mEntityToRational = IntMap.fromList xs     , mRationalToEntity = Map.fromList [(r,e) | (e,r) <- xs]++    , mEntityToBitVec = IntMap.fromList ys+    , mBitVecToEntity = Map.fromList [(bv,e) | (e,bv) <- ys]     }  eval :: Model -> Expr -> Value-eval m (EFrac r) = ValRational r+eval m (EValue v) = v eval m (EAp "true" [])   = ValBool True eval m (EAp "false" [])  = ValBool False eval m (EAp "ite" [a,b,c]) = if valToBool m (eval m a) then eval m b else eval m c eval m (EAp "and" xs)    = ValBool $ and $ map (valToBool m . eval m) xs eval m (EAp "or" xs)     = ValBool $ or $ map (valToBool m . eval m) xs+eval m (EAp "xor" xs)    = ValBool $ foldr xor False $ map (valToBool m . eval m) xs eval m (EAp "not" [x])   = ValBool $ not $ valToBool m $ eval m x eval m (EAp "=>" [x,y])  = ValBool $ valToBool m (eval m x) .=>. valToBool m (eval m y) eval m (EAp "<=" [x,y])  = ValBool $ valToRational m (eval m x) <= valToRational m (eval m y)@@ -841,6 +1122,47 @@   | otherwise = ValRational $ valToRational m (eval m x) / y'   where     y' = valToRational m (eval m y)++eval m (EAp "bvule" [x,y]) = ValBool $ BV.bvule (valToBitVec m (eval m x)) (valToBitVec m (eval m y))+eval m (EAp "bvult" [x,y]) = ValBool $ BV.bvult (valToBitVec m (eval m x)) (valToBitVec m (eval m y))+eval m (EAp "bvuge" [x,y]) = ValBool $ BV.bvuge (valToBitVec m (eval m x)) (valToBitVec m (eval m y))+eval m (EAp "bvugt" [x,y]) = ValBool $ BV.bvugt (valToBitVec m (eval m x)) (valToBitVec m (eval m y))+eval m (EAp "bvsle" [x,y]) = ValBool $ BV.bvsle (valToBitVec m (eval m x)) (valToBitVec m (eval m y))+eval m (EAp "bvslt" [x,y]) = ValBool $ BV.bvslt (valToBitVec m (eval m x)) (valToBitVec m (eval m y))+eval m (EAp "bvsge" [x,y]) = ValBool $ BV.bvsge (valToBitVec m (eval m x)) (valToBitVec m (eval m y))+eval m (EAp "bvsgt" [x,y]) = ValBool $ BV.bvsgt (valToBitVec m (eval m x)) (valToBitVec m (eval m y))+eval m (EAp "concat" [x,y]) =+  ValBitVec $ valToBitVec m (eval m x) <> valToBitVec m (eval m y)+eval m (EAp (FSym "extract" [IndexNumeral i, IndexNumeral j]) [x]) =+  ValBitVec $ BV.extract (fromIntegral i) (fromIntegral j) (valToBitVec m (eval m x))+eval m (EAp (FSym "repeat" [IndexNumeral i]) [x]) =+  ValBitVec $ BV.repeat (fromIntegral i) (valToBitVec m (eval m x))+eval m (EAp (FSym "zero_extend" [IndexNumeral i]) [x]) =+  ValBitVec $ BV.zeroExtend (fromIntegral i) (valToBitVec m (eval m x))+eval m (EAp (FSym "sign_extend" [IndexNumeral i]) [x]) =+  ValBitVec $ BV.signExtend (fromIntegral i) (valToBitVec m (eval m x))+eval m (EAp (FSym "rotate_left" [IndexNumeral i]) [x]) =+  ValBitVec $ rotateL (valToBitVec m (eval m x)) (fromIntegral i)+eval m (EAp (FSym "rotate_right" [IndexNumeral i]) [x]) =+  ValBitVec $ rotateR (valToBitVec m (eval m x)) (fromIntegral i)+eval m (EAp (FSym op1 []) [x])+  | Just op1' <- Map.lookup op1 table =+      let x' = BV.EConst $ valToBitVec m (eval m x)+      in ValBitVec $ BV.evalExpr (mBVModel m) $ op1' x'+  where+    table =+      Map.fromList+      [ ("bvnot", BV.bvnot)+      , ("bvneg", BV.bvneg)+      ]+eval m (EAp (FSym op2 []) [x,y])+  | Just op2' <- Map.lookup op2 table =+      let x' = BV.EConst $ valToBitVec m (eval m x)+          y' = BV.EConst $ valToBitVec m (eval m y)+      in ValBitVec $ BV.evalExpr (mBVModel m) $ op2' x' y'+  where+    table = Map.fromList $ [("bvcomp", BV.bvcomp)] ++ bvBinOpsSameSize+ eval m (EAp "=" [x,y])   = ValBool $   case (eval m x, eval m y) of     (v1, v2) -> v1 == v2@@ -849,15 +1171,20 @@     Nothing -> E.throw $ Error $ "unknown function symbol: " ++ show f     Just (FBoolVar v) -> ValBool $ SAT.evalLit (mBoolModel m) v     Just (FLRAVar v) -> ValRational $ mLRAModel m IntMap.! v-    Just (FEUFFun (_, Sort s []) sym) ->+    Just (FBVVar v) -> ValBitVec $ BV.evalExpr (mBVModel m) (BV.EVar v)+    Just (FEUFFun (_, Sort s _) sym) ->       let e = EUF.evalAp (mEUFModel m) sym (map (valToEntity m . eval m) xs)       in case s of-           SSymUserDeclared _ _ -> ValUninterpreted e (exprSort' (mDefs m) expr)+           SSymUninterpreted _ _ -> ValUninterpreted e (exprSort' (mDefs m) expr)            SSymBool -> ValBool (e == mEUFTrue m)            SSymReal ->              case IntMap.lookup e (mEntityToRational m) of                Just r -> ValRational r                Nothing -> ValRational (fromIntegral (1000000 + e))+           SSymBitVec w ->+             case IntMap.lookup e (mEntityToBitVec m) of+               Just bv -> ValBitVec bv+               Nothing -> ValBitVec (BV.nat2bv w 0)  valToBool :: Model -> Value -> Bool valToBool _ (ValBool b) = b@@ -867,6 +1194,10 @@ valToRational _ (ValRational r) = r valToRational _ _ = E.throw $ Error "rational value is expected" +valToBitVec :: Model -> Value -> BV.BV+valToBitVec _ (ValBitVec bv) = bv+valToBitVec _ _ = E.throw $ Error "bitvector value is expected"+ valToEntity :: Model -> Value -> EUF.Entity valToEntity _ (ValUninterpreted e _) = e valToEntity m (ValBool b)     = if b then mEUFTrue m else mEUFFalse m@@ -874,6 +1205,10 @@   case Map.lookup r (mRationalToEntity m) of     Just e -> e     Nothing -> EUF.mUnspecified (mEUFModel m)+valToEntity m (ValBitVec bv) =+  case Map.lookup bv (mBitVecToEntity m) of+    Just e -> e+    Nothing -> EUF.mUnspecified (mEUFModel m)  entityToValue :: Model -> EUF.Entity -> Sort -> Value entityToValue m e s = @@ -883,14 +1218,20 @@       case IntMap.lookup e (mEntityToRational m) of         Just r -> ValRational r         Nothing -> ValRational (fromIntegral (1000000 + e))-    Sort (SSymUserDeclared _ _) _ -> ValUninterpreted e s+    Sort (SSymBitVec n) _ ->+      case IntMap.lookup e (mEntityToBitVec m) of+        Just bv -> ValBitVec bv+        Nothing -> ValBitVec (BV.nat2bv n 0)+    Sort (SSymUninterpreted _ _) _ -> ValUninterpreted e s -valSort :: Model -> Value -> Sort-valSort _m (ValUninterpreted _e s) = s-valSort _m (ValBool _b)     = sBool-valSort _m (ValRational _r) = sReal+valSort :: Value -> Sort+valSort (ValUninterpreted _e s) = s+valSort (ValBool _b)     = sBool+valSort (ValRational _r) = sReal+valSort (ValBitVec bv) = sBitVec (BV.width bv)  data FunDef = FunDef [([Value], Value)] Value+  deriving (Eq, Show)  evalFSym :: Model -> FSym -> FunDef evalFSym m f = @@ -899,15 +1240,55 @@       let tbl = EUF.mFunctions (mEUFModel m) IntMap.! sym           defaultVal =             case resultSort of-              Sort SSymReal [] -> ValRational 555555 -- Is it ok?-              Sort SSymBool [] -> ValBool False -- Is it ok?-              Sort (SSymUserDeclared _s _ar) _ss -> ValUninterpreted (EUF.mUnspecified (mEUFModel m)) resultSort+              Sort SSymReal _ -> ValRational 555555+              Sort SSymBool _ -> ValBool False+              Sort (SSymBitVec w) _ -> ValBitVec (BV.nat2bv w 0)+              Sort (SSymUninterpreted _s _ar) _ -> ValUninterpreted (EUF.mUnspecified (mEUFModel m)) resultSort       in FunDef [ (zipWith (entityToValue m) args argsSorts, entityToValue m result resultSort)                 | (args, result) <- Map.toList tbl ]                 defaultVal     Just _ -> FunDef [] $ eval m (EAp f []) -- constant symbol     Nothing -> E.throw $ Error $ "unknown function symbol: " ++ show f +-- | Constraints that cannot represented as function definitions.+-- +-- For example, zero-division result values cannot be specified by+-- function definition, because division is interpreted function.+modelGetAssertions :: Model -> [Expr]+modelGetAssertions m =+  [ EAp "="+      [ EAp "/"+        [ EValue (entityToValue m arg sReal)+        , EValue (ValRational 0)+        ]+      , EValue (entityToValue m result sReal)+      ]+  | let FEUFFun _ sym = mDefs m Map.! "_/0"+  , ([arg], result) <- Map.toList $ EUF.mFunctions (mEUFModel m) IntMap.! sym+  ]+  +++  [ EAp "="+      [ EAp "bvudiv"+        [ EValue (ValBitVec s)+        , EValue (ValBitVec (BV.nat2bv (BV.width s) 0))+        ]+      , EValue (ValBitVec t)+      ]+  | (s,t) <- Map.toList bvDivTable+  ]+  +++  [ EAp "="+      [ EAp "bvurem"+        [ EValue (ValBitVec s)+        , EValue (ValBitVec (BV.nat2bv (BV.width s) 0))+        ]+      , EValue (ValBitVec t)+      ]+  | (s,t) <- Map.toList bvRemTable+  ]  +  where+    (_, bvDivTable, bvRemTable) = mBVModel m+ -- -------------------------------------------------------------------  getUnsatAssumptions :: Solver -> IO [Expr]@@ -923,11 +1304,3 @@ pairs :: [a] -> [(a,a)] pairs [] = [] pairs (x:xs) = [(x,y) | y <- xs] ++ pairs xs--#if !MIN_VERSION_base(4,7,0)--isRight :: Either a b -> Bool-isRight (Left  _) = False-isRight (Right _) = True--#endif
+ src/ToySolver/Text/CNF.hs view
@@ -0,0 +1,104 @@+{-# LANGUAGE FlexibleContexts, OverloadedStrings #-}+{-# OPTIONS_GHC -Wall #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Text.CNF+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  non-portable (FlexibleContexts, OverloadedStrings)+--+-----------------------------------------------------------------------------+module ToySolver.Text.CNF+  (+    CNF (..)++  -- * Parsing .cnf files+  , parseFile+  , parseByteString++  -- * Generating .cnf files+  , writeFile+  , hPutCNF+  , cnfBuilder+  ) where++import Prelude hiding (writeFile)+import qualified Data.ByteString.Lazy.Char8 as BS+import Data.ByteString.Builder+import Data.Char+import Data.Monoid+import System.IO hiding (writeFile)++import qualified ToySolver.SAT.Types as SAT++data CNF+  = CNF+  { numVars :: !Int+  , numClauses :: !Int+  , clauses :: [SAT.Clause]+  }+  deriving (Show, Eq, Ord)++parseFile :: FilePath -> IO (Either String CNF)+parseFile filename = do+  s <- BS.readFile filename+  return $ parseByteString s++parseByteString :: BS.ByteString -> Either String CNF+parseByteString s =+  case BS.words l of+    (["p","cnf", nvar, nclause]) ->+      Right $+        CNF+        { numVars    = read $ BS.unpack nvar+        , numClauses = read $ BS.unpack nclause+        , clauses    = map parseClauseBS ls+        }+    _ ->+      Left "cannot find cnf header"+  where+    l :: BS.ByteString+    ls :: [BS.ByteString]+    (l:ls) = filter (not . isCommentBS) (BS.lines s)++parseClauseBS :: BS.ByteString -> SAT.Clause+parseClauseBS s = seqList xs $ xs+  where+    xs = go s+    go s =+      case BS.readInt (BS.dropWhile isSpace s) of+        Nothing -> error "ToySolver.Text.MaxSAT: parse error"+        Just (0,_) -> []+        Just (i,s') -> i : go s'++isCommentBS :: BS.ByteString -> Bool+isCommentBS s =+  case BS.uncons s of+    Just ('c',_) ->  True+    _ -> False++seqList :: [a] -> b -> b+seqList [] b = b+seqList (x:xs) b = seq x $ seqList xs b++writeFile :: FilePath -> CNF -> IO ()+writeFile filepath cnf = do+  withBinaryFile filepath WriteMode $ \h -> do+    hSetBuffering h (BlockBuffering Nothing)+    hPutBuilder h (cnfBuilder cnf)++cnfBuilder :: CNF -> Builder+cnfBuilder cnf = header <> mconcat (map f (clauses cnf))+  where+    header = mconcat+      [ byteString "p cnf "+      , intDec (numVars cnf), char7 ' '+      , intDec (numClauses cnf), char7 '\n'+      ]+    f c = mconcat [intDec lit <> char7 ' '| lit <- c] <> byteString "0\n"++hPutCNF :: Handle -> CNF -> IO ()+hPutCNF h cnf = hPutBuilder h (cnfBuilder cnf)
src/ToySolver/Text/GCNF.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_GHC -Wall #-} ----------------------------------------------------------------------------- -- |@@ -7,7 +8,7 @@ --  -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  provisional--- Portability :  portable+-- Portability :  non-portable (OverloadedStrings) --  -- References: -- @@ -22,11 +23,22 @@   , GClause    -- * Parsing .gcnf files-  , parseString+  , parseByteString   , parseFile++  -- * Generating .gcnf files+  , writeFile+  , hPutGCNF+  , gcnfBuilder   ) where +import Prelude hiding (writeFile)+import qualified Data.ByteString.Lazy.Char8 as BS+import Data.ByteString.Builder+import Data.Char+import Data.Monoid import qualified ToySolver.SAT.Types as SAT+import System.IO hiding (writeFile) import ToySolver.Internal.TextUtil  data GCNF@@ -41,53 +53,92 @@  type GClause = (GroupIndex, SAT.Clause) -parseString :: String -> Either String GCNF-parseString s =-  case words l of++parseFile :: FilePath -> IO (Either String GCNF)+parseFile filename = do+  s <- BS.readFile filename+  return $ parseByteString s++parseByteString :: BS.ByteString -> Either String GCNF+parseByteString s =+  case BS.words l of     (["p","gcnf", nbvar', nbclauses', lastGroupIndex']) ->       Right $         GCNF-        { numVars        = read nbvar'-        , numClauses     = read nbclauses'-        , lastGroupIndex = read lastGroupIndex'-        , clauses        = map parseLine ls+        { numVars        = read $ BS.unpack nbvar'+        , numClauses     = read $ BS.unpack nbclauses'+        , lastGroupIndex = read $ BS.unpack lastGroupIndex'+        , clauses        = map parseLineBS ls         }     (["p","cnf", nbvar', nbclause']) ->       Right $         GCNF-        { numVars        = read nbvar'-        , numClauses     = read nbclause'-        , lastGroupIndex = read nbclause'-        , clauses        = zip [1..] $ map parseCNFLine ls+        { numVars        = read $ BS.unpack nbvar'+        , numClauses     = read $ BS.unpack nbclause'+        , lastGroupIndex = read $ BS.unpack nbclause'+        , clauses        = zip [1..] $ map parseCNFLineBS ls         }     _ ->       Left "cannot find gcnf header"   where-    (l:ls) = filter (not . isComment) (lines s)--parseFile :: FilePath -> IO (Either String GCNF)-parseFile filename = do-  s <- readFile filename-  return $ parseString s--isComment :: String -> Bool-isComment ('c':_) = True-isComment _ = False--parseLine :: String -> GClause-parseLine s =-  case words s of-    (('{':w):xs) ->-        let ys  = map readInt $ init xs-            idx = readInt $ init w-        in seq idx $ seqList ys $ (idx, ys)+    l :: BS.ByteString+    ls :: [BS.ByteString]+    (l:ls) = filter (not . isCommentBS) (BS.lines s)+    +parseLineBS :: BS.ByteString -> GClause+parseLineBS s =+  case BS.uncons (BS.dropWhile isSpace s) of+    Just ('{', s1) ->+      case BS.readInt s1 of+        Just (idx,s2) | Just ('}', s3) <- BS.uncons s2 -> +          let ys = parseClauseBS s3+          in seq idx $ seqList ys $ (idx, ys)+        _ -> error "ToySolver.Text.GCNF: parse error"     _ -> error "ToySolver.Text.GCNF: parse error" -parseCNFLine :: String -> SAT.Clause-parseCNFLine s = seq xs $ seqList xs $ xs+parseCNFLineBS :: BS.ByteString -> SAT.Clause+parseCNFLineBS s = seq xs $ seqList xs $ xs   where-    xs = init (map readInt (words s))+    xs = parseClauseBS s +parseClauseBS :: BS.ByteString -> SAT.Clause+parseClauseBS s = seqList xs $ xs+  where+    xs = go s+    go s =+      case BS.readInt (BS.dropWhile isSpace s) of+        Nothing -> error "ToySolver.Text.GCNF: parse error"+        Just (0,_) -> []+        Just (i,s') -> i : go s'++isCommentBS :: BS.ByteString -> Bool+isCommentBS s =+  case BS.uncons s of+    Just ('c',_) ->  True+    _ -> False+ seqList :: [a] -> b -> b seqList [] b = b seqList (x:xs) b = seq x $ seqList xs b++writeFile :: FilePath -> GCNF -> IO ()+writeFile filepath gcnf = do+  withBinaryFile filepath WriteMode $ \h -> do+    hSetBuffering h (BlockBuffering Nothing)+    hPutGCNF h gcnf++gcnfBuilder :: GCNF -> Builder+gcnfBuilder gcnf = header <> mconcat (map f (clauses gcnf))+  where+    header = mconcat+      [ byteString "p gcnf "+      , intDec (numVars gcnf), char7 ' '+      , intDec (numClauses gcnf), char7 ' '+      , intDec (lastGroupIndex gcnf), char7 '\n'+      ]+    f (idx,c) = char7 '{' <> intDec idx <> char7 '}' <>+                mconcat [char7 ' ' <> intDec lit | lit <- c] <>+                byteString " 0\n"++hPutGCNF :: Handle -> GCNF -> IO ()+hPutGCNF h gcnf = hPutBuilder h (gcnfBuilder gcnf)
− src/ToySolver/Text/GurobiSol.hs
@@ -1,18 +0,0 @@-module ToySolver.Text.GurobiSol-  ( Model-  , render-  ) where--import Data.Map (Map)-import qualified Data.Map as Map-import Data.Ratio--type Model = Map String Double--render :: Model -> Maybe Double -> String-render m obj = unlines $ ls1 ++ ls2-  where-    ls1 = case obj of-            Nothing  -> []-            Just val -> ["# Objective value = " ++ show val]-    ls2 = [name ++ " " ++ show val | (name,val) <- Map.toList m]
src/ToySolver/Text/MaxSAT.hs view
@@ -23,12 +23,21 @@    -- * Parsing .cnf/.wcnf files   , parseFile-  , parseString   , parseByteString++  -- * Generating .wcnf files+  , writeFile+  , hPutWCNF+  , wcnfBuilder   ) where +import Prelude hiding (writeFile) import qualified Data.ByteString.Lazy.Char8 as BS+import Data.ByteString.Builder import Data.Char+import Data.Monoid+import System.IO hiding (writeFile)+ import qualified ToySolver.SAT.Types as SAT import ToySolver.Internal.TextUtil @@ -47,70 +56,9 @@  parseFile :: FilePath -> IO (Either String WCNF) parseFile filename = do-{--  s <- readFile filename-  return $ parseString s--}   s <- BS.readFile filename   return $ parseByteString s -parseString :: String -> Either String WCNF-parseString s =-  case words l of-    (["p","wcnf", nvar, nclause, top]) ->-      Right $-        WCNF-        { numVars    = read nvar-        , numClauses = read nclause-        , topCost    = read top-        , clauses    = map parseWCNFLine ls-        }-    (["p","wcnf", nvar, nclause]) ->-      Right $-        WCNF-        { numVars    = read nvar-        , numClauses = read nclause-          -- top must be greater than the sum of the weights of violated soft clauses.-        , topCost    = fromInteger $ 2^(63::Int) - 1-        , clauses    = map parseWCNFLine ls-        }-    (["p","cnf", nvar, nclause]) ->-      Right $-        WCNF-        { numVars    = read nvar-        , numClauses = read nclause-          -- top must be greater than the sum of the weights of violated soft clauses.-        , topCost    = fromInteger $ 2^(63::Int) - 1-        , clauses    = map parseCNFLine ls-        }-    _ ->-      Left "cannot find wcnf/cnf header"-  where-    (l:ls) = filter (not . isComment) (lines s)--isComment :: String -> Bool-isComment ('c':_) = True-isComment _ = False--parseWCNFLine :: String -> WeightedClause-parseWCNFLine s =-  case words s of-    (w:xs)-      | last xs == "0" -> seq w' $ seqList ys $ (w', ys)-      | otherwise -> error "ToySolver.Text.MaxSAT: parse error"-      where-        w' = readUnsignedInteger w-        ys = map readInt $ init xs-    _ -> error "ToySolver.Text.MaxSAT: parse error"--parseCNFLine :: String -> WeightedClause-parseCNFLine s-  | null xs || last xs /= 0 = error "ToySolver.Text.MaxSAT: parse error"-  | otherwise = seqList ys $ (1, ys)-  where-    xs = map readInt (words s)-    ys = init xs- parseByteString :: BS.ByteString -> Either String WCNF parseByteString s =   case BS.words l of@@ -179,3 +127,23 @@ seqList :: [a] -> b -> b seqList [] b = b seqList (x:xs) b = seq x $ seqList xs b++writeFile :: FilePath -> WCNF -> IO ()+writeFile filepath wcnf = do+  withBinaryFile filepath WriteMode $ \h -> do+    hSetBuffering h (BlockBuffering Nothing)+    hPutWCNF h wcnf++wcnfBuilder :: WCNF -> Builder+wcnfBuilder wcnf = header <> mconcat (map f (clauses wcnf))+  where+    header = mconcat+      [ byteString "p wcnf "+      , intDec (numVars wcnf), char7 ' '+      , intDec (numClauses wcnf), char7 ' '+      , integerDec (topCost wcnf), char7 '\n'+      ]+    f (w,c) = integerDec w <> mconcat [char7 ' ' <> intDec lit | lit <- c] <> byteString " 0\n"++hPutWCNF :: Handle -> WCNF -> IO ()+hPutWCNF h wcnf = hPutBuilder h (wcnfBuilder wcnf)
+ src/ToySolver/Text/QDimacs.hs view
@@ -0,0 +1,131 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE OverloadedStrings #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  ToySolver.Text.QDimacs+-- Copyright   :  (c) Masahiro Sakai 2016+-- License     :  BSD-style+-- +-- Maintainer  :  masahiro.sakai@gmail.com+-- Stability   :  provisional+-- Portability :  portable+--+-- References:+--+-- * QDIMACS standard Ver. 1.1+--   <http://www.qbflib.org/qdimacs.html>+--+-----------------------------------------------------------------------------+module ToySolver.Text.QDimacs+  ( QDimacs (..)+  , Quantifier (..)+  , QuantSet+  , Atom+  , Lit+  , Clause+  , parseFile+  , parseByteString+  ) where++import Control.DeepSeq+import qualified Data.ByteString.Lazy.Char8 as BL+import Data.Char++{-+http://www.qbflib.org/qdimacs.html++<input> ::= <preamble> <prefix> <matrix> EOF++<preamble> ::= [<comment_lines>] <problem_line>+<comment_lines> ::= <comment_line> <comment_lines> | <comment_line> +<comment_line> ::= c <text> EOL+<problem_line> ::= p cnf <pnum> <pnum> EOL++<prefix> ::= [<quant_sets>]+<quant_sets> ::= <quant_set> <quant_sets> | <quant_set>+<quant_set> ::= <quantifier> <atom_set> 0 EOL+<quantifier> ::= e | a+<atom_set> ::= <pnum> <atom_set> | <pnum>++<matrix> ::= <clause_list>+<clause_list> ::= <clause> <clause_list> | <clause> +<clause> ::= <literal> <clause> | <literal> 0 EOL+<literal> ::= <num>++<text> ::= {A sequence of non-special ASCII characters}+<num> ::= {A 32-bit signed integer different from 0}+<pnum> ::= {A 32-bit signed integer greater than 0}+-}++data QDimacs+  = QDimacs+  { numVars :: !Int+  , numClauses :: !Int+  , prefix :: [QuantSet]+  , matrix :: [Clause]+  }+  deriving (Eq, Ord, Show, Read)++data Quantifier+  = E -- ^ existential quantifier+  | A -- ^ universal quantifier+  deriving (Eq, Ord, Show, Read, Enum, Bounded)++type QuantSet = (Quantifier, [Atom])++type Atom = Int -- better to use Int32?++type Lit = Int -- better to use Int32++type Clause = [Lit]++parseFile :: FilePath -> IO (Either String QDimacs)+parseFile filename = do+  s <- BL.readFile filename+  return $ parseByteString s++parseByteString :: BL.ByteString -> (Either String QDimacs)+parseByteString = f . BL.lines+  where+    f [] = Left "QDimacs.parseByteString: premature end of file"+    f (l : ls) =+      case BL.uncons l of+        Nothing -> Left "QDimacs.parseByteString: no problem line"+        Just ('c', _) -> f ls+        Just ('p', s) ->+          case BL.words s of+            ["cnf", numVars', numClauses'] ->+              case parsePrefix ls of+                (prefix', ls') -> Right $+                  QDimacs+                  { numVars = read $ BL.unpack numVars'+                  , numClauses = read $ BL.unpack numClauses'+                  , prefix = prefix'+                  , matrix = parseClauses ls'+                  }+            _ -> Left "QDimacs.parseByteString: invalid problem line"+        Just (c, _) -> Left ("QDimacs.parseByteString: invalid prefix " ++ show c)++parsePrefix :: [BL.ByteString] -> ([QuantSet], [BL.ByteString])+parsePrefix = go []+  where+    go result [] = (reverse result, [])+    go result lls@(l : ls) =+      case BL.uncons l of+        Just (c,s)+          | c=='a' || c=='e' ->+              let atoms = readInts s+                  q = if c=='a' then A else E+              in seq q $ deepseq atoms $ go ((q, atoms) : result) ls+          | otherwise ->+              (reverse result, lls)+        _ -> error "QDimacs.parseProblem: invalid line"++parseClauses :: [BL.ByteString] -> [Clause]+parseClauses = map readInts++readInts :: BL.ByteString -> [Int]+readInts s =+  case BL.readInt (BL.dropWhile isSpace s) of+    Just (z, s') -> if z == 0 then [] else z : readInts s'+    Nothing -> []
src/ToySolver/Text/SDPFile.hs view
@@ -1,13 +1,15 @@+{-# LANGUAGE CPP, ConstraintKinds, FlexibleContexts, GADTs, ScopedTypeVariables #-}+{-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_GHC -Wall #-} ----------------------------------------------------------------------------- -- | -- Module      :  ToySolver.Text.SDPFile--- Copyright   :  (c) Masahiro Sakai 2012+-- Copyright   :  (c) Masahiro Sakai 2012,2016 -- License     :  BSD-style --  -- Maintainer  :  masahiro.sakai@gmail.com -- Stability   :  provisional--- Portability :  portable+-- Portability :  non-portable -- -- References: --@@ -38,22 +40,54 @@   , renderSparse      -- * Parsing-  , parseDataString+  , ParseError+  , parseData   , parseDataFile-  , parseSparseDataString+  , parseSparseData   , parseSparseDataFile   ) where  import Control.Applicative ((<*)) import Control.Monad+import qualified Data.ByteString.Lazy as BL+import Data.ByteString.Builder (Builder)+import qualified Data.ByteString.Builder as B+import qualified Data.ByteString.Builder.Scientific as B import Data.List (intersperse)-import Data.Ratio+import Data.Monoid+import Data.Scientific (Scientific)+#if !MIN_VERSION_megaparsec(5,0,0)+import Data.Scientific (fromFloatDigits)+#endif import Data.Map (Map) import qualified Data.Map as Map import qualified Data.IntMap as IntMap-import Text.Parsec-import Text.Parsec.String+import qualified Text.Megaparsec as MegaParsec+#if MIN_VERSION_megaparsec(6,0,0)+import Data.Word+import Data.Void+import Text.Megaparsec hiding (ParseError)+import Text.Megaparsec.Byte hiding (oneOf)+import qualified Text.Megaparsec.Byte as MegaParsec+import qualified Text.Megaparsec.Byte.Lexer as Lexer+#else+import qualified Data.ByteString.Lazy.Char8 as BL8+import Text.Megaparsec hiding (ParseError, oneOf)+import qualified Text.Megaparsec.Lexer as Lexer+import Text.Megaparsec.Prim (MonadParsec ())+#endif +#if MIN_VERSION_megaparsec(6,0,0)+type C e s m = (MonadParsec e s m, Token s ~ Word8)+type ParseError = MegaParsec.ParseError Word8 Void+#elif MIN_VERSION_megaparsec(5,0,0)+type C e s m = (MonadParsec e s m, Token s ~ Char)+type ParseError = MegaParsec.ParseError Char Dec+#else+type C e s m = (MonadParsec s m Char)+type ParseError = MegaParsec.ParseError+#endif+ -- --------------------------------------------------------------------------- -- problem description -- ---------------------------------------------------------------------------@@ -61,14 +95,14 @@ data Problem   = Problem   { blockStruct :: [Int]      -- ^ the block strcuture vector (bLOCKsTRUCT)-  , costs       :: [Rational] -- ^ Constant Vector+  , costs       :: [Scientific] -- ^ Constant Vector   , matrices    :: [Matrix]   -- ^ Constraint Matrices   }   deriving (Show, Ord, Eq)  type Matrix = [Block] -type Block = Map (Int,Int) Rational+type Block = Map (Int,Int) Scientific  -- | the number of primal variables (mDim) mDim :: Problem -> Int@@ -78,7 +112,7 @@ nBlock :: Problem -> Int nBlock prob = length (blockStruct prob) -blockElem :: Int -> Int -> Block -> Rational+blockElem :: Int -> Int -> Block -> Scientific blockElem i j b = Map.findWithDefault 0 (i,j) b  -- ---------------------------------------------------------------------------@@ -87,7 +121,7 @@  type DenseMatrix = [DenseBlock] -type DenseBlock = [[Rational]]+type DenseBlock = [[Scientific]]  denseBlock :: DenseBlock -> Block denseBlock xxs = Map.fromList [((i,j),x) | (i,xs) <- zip [1..] xxs, (j,x) <- zip [1..] xs, x /= 0]@@ -95,7 +129,7 @@ denseMatrix :: DenseMatrix -> Matrix denseMatrix = map denseBlock -diagBlock :: [Rational] -> Block+diagBlock :: [Scientific] -> Block diagBlock xs = Map.fromList [((i,i),x) | (i,x) <- zip [1..] xs]  -- ---------------------------------------------------------------------------@@ -103,22 +137,26 @@ -- ---------------------------------------------------------------------------  -- | Parse a SDPA format (.dat) string.-parseDataString :: SourceName -> String -> Either ParseError Problem-parseDataString = parse (pDataFile <* eof)+parseData :: String -> BL.ByteString -> Either ParseError Problem+parseData = parse (pDataFile <* eof)  -- | Parse a SDPA format file (.dat). parseDataFile :: FilePath -> IO (Either ParseError Problem)-parseDataFile = parseFromFile (pDataFile <* eof)+parseDataFile fname = do+  s <- BL.readFile fname+  return $! parse (pDataFile <* eof) fname s  -- | Parse a SDPA sparse format (.dat-s) string.-parseSparseDataString :: SourceName -> String -> Either ParseError Problem-parseSparseDataString = parse (pSparseDataFile <* eof)+parseSparseData :: String -> BL.ByteString -> Either ParseError Problem+parseSparseData = parse (pSparseDataFile <* eof)  -- | Parse a SDPA sparse format file (.dat-s). parseSparseDataFile :: FilePath -> IO (Either ParseError Problem)-parseSparseDataFile = parseFromFile (pSparseDataFile <* eof)+parseSparseDataFile fname = do+  s <- BL.readFile fname+  return $! parse (pSparseDataFile <* eof) fname s -pDataFile :: Parser Problem+pDataFile :: C e s m => m Problem pDataFile = do   _ <- many pComment   m  <- nat_line -- mDim@@ -126,7 +164,7 @@   bs <- pBlockStruct -- bLOCKsTRUCT   cs <- pCosts   ms <- pDenseMatrices (fromIntegral m) bs-  spaces+  space   return $     Problem     { blockStruct = bs@@ -134,7 +172,7 @@     , matrices    = ms     } -pSparseDataFile :: Parser Problem+pSparseDataFile :: C e s m => m Problem pSparseDataFile = do   _ <- many pComment   m  <- nat_line -- mDim@@ -142,7 +180,7 @@   bs <- pBlockStruct -- bLOCKsTRUCT   cs <- pCosts   ms <- pSparseMatrices (fromIntegral m) bs-  spaces+  space   return $     Problem     { blockStruct = bs@@ -150,35 +188,39 @@     , matrices    = ms     } -pComment :: Parser String+pComment :: C e s m => m BL.ByteString pComment = do   c <- oneOf "*\""   cs <- manyTill anyChar newline-  return (c:cs)+#if MIN_VERSION_megaparsec(6,0,0)+  return $ BL.pack (c:cs)+#else+  return $ BL8.pack (c:cs)+#endif -pBlockStruct :: Parser [Int]+pBlockStruct :: C e s m => m [Int] pBlockStruct = do-  optional sep+  _ <- optional sep   let int' = int >>= \i -> optional sep >> return i   xs <- many int'   _ <- manyTill anyChar newline   return $ map fromIntegral xs    where-    sep = many1 (oneOf " \t(){},")+    sep = some (oneOf " \t(){},") -pCosts :: Parser [Rational]+pCosts :: C e s m => m [Scientific] pCosts = do-  let sep = many1 (oneOf " \t(){},")+  let sep = some (oneOf " \t(){},")       real' = real >>= \r -> optional sep >> return r-  optional sep+  _ <- optional sep   cs <- many real'   _ <- newline   return cs -pDenseMatrices :: Int -> [Int] -> Parser [Matrix]+pDenseMatrices :: C e s m => Int -> [Int] -> m [Matrix] pDenseMatrices m bs = optional sep >> replicateM (fromIntegral m + 1) pDenceMatrix   where-    sep = many1 (space <|> oneOf "(){},")+    sep = some ((spaceChar >> return ()) <|> (oneOf "(){}," >> return ()))     real' = real >>= \r -> optional sep >> return r     pDenceMatrix = forM bs $ \b ->       if b >= 0@@ -189,7 +231,7 @@         xs <- replicateM (abs b) real'         return $ diagBlock xs -pSparseMatrices :: Int -> [Int] -> Parser [Matrix]+pSparseMatrices :: C e s m => Int -> [Int] -> m [Matrix] pSparseMatrices m bs = do   xs <- many pLine   let t = IntMap.unionsWith (IntMap.unionWith Map.union)@@ -201,9 +243,9 @@     ]    where-    sep = many1 (oneOf " \t") >> return ()+    sep = some (oneOf " \t") >> return ()     pLine = do-      optional sep+      _ <- optional sep       matno <- nat       sep       blkno <- nat@@ -213,130 +255,108 @@       j <- nat       sep       e <- real-      optional sep+      _ <- optional sep       _ <- newline       return (fromIntegral matno, fromIntegral blkno, fromIntegral i, fromIntegral j, e) -nat_line :: Parser Integer+nat_line :: C e s m => m Integer nat_line = do-  spaces+  space   n <- nat   _ <- manyTill anyChar newline   return n -nat :: Parser Integer-nat = do-  ds <- many1 digit-  return $! read ds--int :: Parser Integer-int = do-  s <- option 1 sign-  n <- nat-  return $! s * n--real :: Parser Rational-real = do-  s <- option 1 sign -  b <- (do{ x <- nat; y <- option 0 frac; return (fromInteger x + y) })-    <|> frac-  c <- option 0 e-  return (s * b*10^^c)-  where-    digits = many1 digit+nat :: C e s m => m Integer+nat = Lexer.decimal -    frac :: Parser Rational-    frac = do-      _ <- char '.'-      s <- digits-      return (read s % 10^(length s))+int :: C e s m => m Integer+int = Lexer.signed (return ()) Lexer.decimal -    e :: Parser Integer-    e = do-      _ <- oneOf "eE"-      f <- msum [ char '+' >> return id-                , char '-' >> return negate-                , return id-                ]-      liftM f nat+real :: forall e s m. C e s m => m Scientific+#if MIN_VERSION_megaparsec(6,0,0)+real = Lexer.signed (return ()) Lexer.scientific+#elif MIN_VERSION_megaparsec(5,0,0)+real = Lexer.signed (return ()) Lexer.number+#else+real = liftM (either fromInteger fromFloatDigits) $ Lexer.signed (return ()) $ Lexer.number+#endif -sign :: Num a => Parser a-sign = (char '+' >> return 1) <|> (char '-' >> return (-1))+#if MIN_VERSION_megaparsec(6,0,0)+oneOf :: C e s m => [Char] -> m Word8+oneOf = MegaParsec.oneOf . map (fromIntegral . fromEnum)+#else+oneOf :: C e s m => [Char] -> m Char+oneOf = MegaParsec.oneOf+#endif  -- --------------------------------------------------------------------------- -- rendering -- --------------------------------------------------------------------------- -render :: Problem -> ShowS+render :: Problem -> Builder render = renderImpl False -renderSparse :: Problem -> ShowS+renderSparse :: Problem -> Builder renderSparse = renderImpl True -renderImpl :: Bool -> Problem -> ShowS-renderImpl sparse prob =+renderImpl :: Bool -> Problem -> Builder+renderImpl sparse prob = mconcat+  [   -- mDim-  shows (mDim prob) . showString " = mDIM\n" .+    B.intDec (mDim prob) <> " = mDIM\n"    -- nBlock-  shows (nBlock prob) . showString " = nBlock\n" .+  , B.intDec (nBlock prob) <> " = nBlock\n"    -- blockStruct-  showChar '(' .-    sepByS [shows i | i <- blockStruct prob] (showString ", ") .-    showChar ')' .-    showString " = bLOCKsTRUCT\n" .+  , B.char7 '('+  , sepByS [B.intDec i | i <- blockStruct prob] ", "+  , B.char7 ')'+  , " = bLOCKsTRUCT\n"    -- costs-  showChar '(' .-    sepByS [showRat c | c <- costs prob] (showString ", ") .-    showString ")\n" .+  , B.char7 '('+  , sepByS [B.scientificBuilder c | c <- costs prob] ", "+  , ")\n"    -- matrices-  if sparse-    then concatS [renderSparseMatrix matno m | (matno, m) <- zip [0..] (matrices prob)]-    else concatS $ map renderDenseMatrix (matrices prob)+  , if sparse+    then mconcat [renderSparseMatrix matno m | (matno, m) <- zip [0..] (matrices prob)]+    else mconcat $ map renderDenseMatrix (matrices prob)+  ]    where-    renderSparseMatrix :: Int -> Matrix -> ShowS+    renderSparseMatrix :: Int -> Matrix -> Builder     renderSparseMatrix matno m =-      concatS [ shows matno . showChar ' ' .-                shows blkno . showChar ' ' .-                shows i . showChar ' ' .-                shows j . showChar ' ' .-                showRat e . showChar '\n'+      mconcat [ B.intDec matno <> B.char7 ' ' <>+                B.intDec blkno <> B.char7 ' ' <>+                B.intDec i <> B.char7 ' ' <>+                B.intDec j <> B.char7 ' ' <>+                B.scientificBuilder e <> B.char7 '\n'               | (blkno, blk) <- zip [(1::Int)..] m, ((i,j),e) <- Map.toList blk, i <= j ] -    renderDenseMatrix :: Matrix -> ShowS+    renderDenseMatrix :: Matrix -> Builder     renderDenseMatrix m = -      showString "{\n" .-      concatS [renderDenseBlock b s . showString "\n" | (b,s) <- zip m (blockStruct prob)] .-      showString "}\n"+      "{\n" <>+      mconcat [renderDenseBlock b s <> "\n" | (b,s) <- zip m (blockStruct prob)] <>+      "}\n" -    renderDenseBlock :: Block -> Int -> ShowS+    renderDenseBlock :: Block -> Int -> Builder     renderDenseBlock b s       | s < 0 =-          showString "  " . renderVec [blockElem i i b | i <- [1 .. abs s]]+          "  " <> renderVec [blockElem i i b | i <- [1 .. abs s]]       | otherwise = -          showString "  { " .-          sepByS [renderRow i | i <- [1..s]] (showString ", ") .     -          showString " }"+          "  { " <>+          sepByS [renderRow i | i <- [1..s]] ", " <>     +          " }"       where         renderRow i = renderVec [blockElem i j b | j <- [1..s]] -renderVec :: [Rational] -> ShowS+renderVec :: [Scientific] -> Builder renderVec xs =-  showChar '{' .-  sepByS (map showRat xs) (showString ", ") .-  showChar '}'--showRat :: Rational -> ShowS-showRat r-  | denominator r == 1 = shows (numerator r)-  | otherwise = shows (fromRational r :: Double)--concatS :: [ShowS] -> ShowS-concatS = foldr (.) id+  B.char7 '{' <>+  sepByS (map B.scientificBuilder xs) ", " <>+  B.char7 '}' -sepByS :: [ShowS] -> ShowS -> ShowS-sepByS xs sep = concatS $ intersperse sep xs+sepByS :: [Builder] -> Builder -> Builder+sepByS xs sep = mconcat $ intersperse sep xs
src/ToySolver/Version.hs view
@@ -15,114 +15,153 @@ packageVersions :: [(String, String)] packageVersions = sort $ tail   [ (undefined, undefined) -- dummy+#ifdef VERSION_OpenCL+  , ("OpenCL", VERSION_OpenCL)+#endif #ifdef VERSION_OptDir-  , ("OptDir",       VERSION_OptDir       )+  , ("OptDir", VERSION_OptDir) #endif #ifdef VERSION_array-  , ("array",        VERSION_array        )+  , ("array", VERSION_array) #endif+#ifdef VERSION_attoparsec+  , ("attoparsec", VERSION_attoparsec)+#endif #ifdef VERSION_base-  , ("base",         VERSION_base         )+  , ("base", VERSION_base) #endif #ifdef VERSION_bytestring-  , ("bytestring",   VERSION_bytestring   )+  , ("bytestring", VERSION_bytestring) #endif #ifdef VERSION_bytestring_builder-  , ("bytestring-builder",   VERSION_bytestring_builder   )+  , ("bytestring-builder", VERSION_bytestring_builder) #endif+#ifdef VERSION_clock+  , ("clock", VERSION_clock)+#endif #ifdef VERSION_containers-  , ("containers",   VERSION_containers   )+  , ("containers", VERSION_containers) #endif-#ifdef VERSION_data_interval-  , ("data-interval", VERSION_data_interval)+#ifdef VERSION_data_default+  , ("data-default", VERSION_data_default) #endif #ifdef VERSION_data_default_class   , ("data-default-class", VERSION_data_default_class) #endif+#ifdef VERSION_data_interval+  , ("data-interval", VERSION_data_interval)+#endif #ifdef VERSION_deepseq-  , ("deepseq",      VERSION_deepseq      )+  , ("deepseq", VERSION_deepseq) #endif-#ifdef VERSION_exceptions-  , ("exceptions",   VERSION_exceptions   )+#ifdef VERSION_directory+  , ("directory", VERSION_directory) #endif #ifdef VERSION_extended_reals   , ("extended-reals", VERSION_extended_reals) #endif #ifdef VERSION_filepath-  , ("filepath",     VERSION_filepath     )+  , ("filepath", VERSION_filepath) #endif #ifdef VERSION_finite_field-  , ("finite-field", VERSION_finite_field )+  , ("finite-field", VERSION_finite_field) #endif+#ifdef VERSION_ghc_prim+  , ("ghc-prim", VERSION_ghc_prim)+#endif #ifdef VERSION_hashable-  , ("hashable",     VERSION_hashable     )+  , ("hashable", VERSION_hashable) #endif+#ifdef VERSION_hashtables+  , ("hashtables", VERSION_hashtables)+#endif+#ifdef VERSION_haskeline+  , ("haskeline", VERSION_haskeline)+#endif #ifdef VERSION_heaps-  , ("heaps",        VERSION_heaps        )+  , ("heaps", VERSION_heaps) #endif #ifdef VERSION_intern-  , ("intern",       VERSION_intern       )+  , ("intern", VERSION_intern) #endif+#ifdef VERSION_lattices+  , ("lattices", VERSION_lattices)+#endif+#ifdef VERSION_log_domain+  , ("log-domain", VERSION_log_domain)+#endif+#ifdef VERSION_logic_TPTP+  , ("logic-TPTP", VERSION_logic_TPTP)+#endif #ifdef VERSION_loop-  , ("loop",         VERSION_loop         )+  , ("loop", VERSION_loop) #endif+#ifdef VERSION_megaparsec+  , ("megaparsec", VERSION_megaparsec)+#endif #ifdef VERSION_mtl-  , ("mtl",          VERSION_mtl          )+  , ("mtl", VERSION_mtl) #endif #ifdef VERSION_multiset-  , ("multiset",     VERSION_multiset     )+  , ("multiset", VERSION_multiset) #endif #ifdef VERSION_mwc_random-  , ("mwc-random",   VERSION_mwc_random   )-#endif-#ifdef VERSION_old_locale-  , ("old-locale",   VERSION_old_locale   )-#endif-#ifdef VERSION_parse_dimacs-  , ("parse_dimacs", VERSION_parse_dimacs )+  , ("mwc-random", VERSION_mwc_random) #endif #ifdef VERSION_parsec-  , ("parsec",       VERSION_parsec       )+  , ("parsec", VERSION_parsec) #endif #ifdef VERSION_prettyclass-  , ("prettyclass",  VERSION_prettyclass  )+  , ("prettyclass", VERSION_prettyclass) #endif #ifdef VERSION_primes-  , ("primes",       VERSION_primes       )+  , ("primes", VERSION_primes) #endif+#ifdef VERSION_primitive+  , ("primitive", VERSION_primitive)+#endif #ifdef VERSION_process-  , ("process",      VERSION_process      )+  , ("process", VERSION_process) #endif #ifdef VERSION_pseudo_boolean   , ("pseudo-boolean", VERSION_pseudo_boolean) #endif #ifdef VERSION_queue-  , ("queue",        VERSION_queue        )+  , ("queue", VERSION_queue) #endif+#ifdef VERSION_scientific+  , ("scientific", VERSION_scientific)+#endif #ifdef VERSION_semigroups-  , ("semigroups",   VERSION_semigroups   )+  , ("semigroups", VERSION_semigroups) #endif #ifdef VERSION_sign-  , ("sign",         VERSION_sign         )+  , ("sign", VERSION_sign) #endif-#ifdef VERSION_stm-  , ("stm",          VERSION_stm          )+#ifdef VERSION_split+  , ("split", VERSION_split) #endif-#ifdef VERSION_transformers-  , ("transformers", VERSION_transformers )+#ifdef VERSION_stm+  , ("stm", VERSION_stm) #endif-#ifdef VERSION_transformers_compat-  , ("transformers-compat", VERSION_transformers_compat)+#ifdef VERSION_template_haskell+  , ("template-haskell", VERSION_template_haskell) #endif #ifdef VERSION_temporary-  , ("temporary",    VERSION_temporary    )+  , ("temporary", VERSION_temporary) #endif+#ifdef VERSION_text+  , ("text", VERSION_text)+#endif #ifdef VERSION_time-  , ("time",         VERSION_time         )+  , ("time", VERSION_time) #endif-#ifdef VERSION_type_level_numbers-  , ("type-level-numbers", VERSION_type_level_numbers)+#ifdef VERSION_transformers+  , ("transformers", VERSION_transformers) #endif+#ifdef VERSION_transformers_compat+  , ("transformers-compat", VERSION_transformers_compat)+#endif #ifdef VERSION_unbounded_delays   , ("unbounded-delays", VERSION_unbounded_delays) #endif@@ -130,13 +169,13 @@   , ("unordered-containers", VERSION_unordered_containers) #endif #ifdef VERSION_vector-  , ("vector",       VERSION_vector)+  , ("vector", VERSION_vector) #endif #ifdef VERSION_vector_space   , ("vector-space", VERSION_vector_space) #endif-#ifdef VERSION_logic_TPTP-  , ("logic-TPTP",   VERSION_logic_TPTP   )+#ifdef VERSION_xml_conduit+  , ("xml-conduit", VERSION_xml_conduit) #endif   ] 
− src/TseitinEncode.hs
@@ -1,117 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}--------------------------------------------------------------------------------- |--- Module      :  TseitingEncoding--- Copyright   :  (c) Masahiro Sakai 2011--- License     :  BSD-style--- --- Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  provisional--- Portability :  non-portable (GeneralizedNewtypeDeriving)--- -------------------------------------------------------------------------------module TseitingEncoding-  ( Var-  , Lit-  , Clause-  , CNF-  , Formula-  , CNFGenMonad (..)-  , emitFormula-  , CNFGen-  , runCNFGen-  , execCNFGen-  , evalCNFGen-  ) where--import Control.Monad-import Control.Monad.RWS--type Var = Int-data Lit = Pos Var | Neg Var deriving (Show, Eq, Ord)-type Clause = [Lit]-type CNF = [Clause]--data Formula-  = Var Var-  | And [Formula]-  | Or [Formula]-  | Not Formula-  | Imply Formula Formula-  deriving (Show, Eq, Ord)--class Monad m => CNFGenMonad m where-  newVar :: m Var-  emitClause :: Clause -> m ()--emitFormula :: CNFGenMonad m => Formula -> m ()-emitFormula x = do-  v <- enc x-  emitClause [Pos v]--enc :: CNFGenMonad m => Formula -> m Var-enc (Var v) = return v-enc (And xs) = do-  v <- newVar-  vs <- mapM enc xs-  forM vs $ \v2 -> emitClause [Neg v, Pos v2]-  emitClause (Pos v : map Neg vs)-  return v-enc (Or xs) = do-  v <- newVar-  vs <- mapM enc xs-  forM vs $ \v2 -> emitClause [Pos v, Neg v2]-  emitClause (Neg v : map Pos vs)-  return v-enc (Not x) = do-  v <- newVar-  v2 <- enc x-  emitClause [Pos v, Pos v2]-  emitClause [Neg v, Neg v2]-  return v-enc (Imply x y) = enc (Or [Not x, y])--newtype CNFGen a = CNFGen (RWS () (Endo [Clause]) Int a)-  deriving Monad--instance CNFGenMonad CNFGen where-  newVar = CNFGen $ do-    cnt <- get-    put (cnt+1)-    return cnt-  emitClause cl = CNFGen (tell (Endo (cl:)))--runCNFGen :: CNFGen x -> (x, Int, CNF)-runCNFGen (CNFGen m) =-  case runRWS m () 0 of-    (x, cnt, f) -> (x, cnt, appEndo f [])--execCNFGen :: CNFGen x -> (Int, CNF)-execCNFGen m =-  case runCNFGen m of-    (_,cnt,cnf) -> (cnt,cnf)--evalCNFGen :: CNFGen x -> (x, CNF)-evalCNFGen m = -  case runCNFGen m of-    (x,_,cnf) -> (x,cnf)--test :: (Int, CNF)-test = execCNFGen $ do-  x <- newVar-  y <- newVar-  z <- newVar-  emitFormula $ And [Or [Var x, Var y] , Var z]-{--=>-(5-, [ [Pos 4,Neg 0]-  , [Pos 4,Neg 1]-  , [Neg 4,Pos 0,Pos 1]-  , [Neg 3,Pos 4]-  , [Neg 3,Pos 2]-  , [Pos 3,Neg 4,Neg 2]-  , [Pos 3]-  ]-)--}
test/Test/Arith.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-} module Test.Arith (arithTestGroup) where  import Control.Monad@@ -26,7 +26,7 @@ import ToySolver.Data.FOL.Arith import qualified ToySolver.Data.LA as LA import qualified ToySolver.Data.Polynomial as P-import ToySolver.Data.Var+import ToySolver.Data.IntVar  import qualified ToySolver.Arith.FourierMotzkin as FourierMotzkin import qualified ToySolver.Arith.FourierMotzkin.Optimization as FMOpt@@ -34,7 +34,8 @@ import qualified ToySolver.Arith.OmegaTest.Base as OmegaTest import qualified ToySolver.Arith.Cooper as Cooper import qualified ToySolver.Arith.CAD as CAD-import qualified ToySolver.Arith.Simplex2 as Simplex2+import qualified ToySolver.Arith.Simplex as Simplex+import qualified ToySolver.Arith.Simplex.Simple as SimplexSimple import qualified ToySolver.Arith.ContiTraverso as ContiTraverso import qualified ToySolver.Arith.VirtualSubstitution as VirtualSubstitution @@ -195,8 +196,8 @@ prop_FourierMotzkin_solve =   forAll genQFLAConj $ \(vs,cs) ->     case FourierMotzkin.solve vs cs of-      Nothing -> forAll (genModel vs) $ \m -> all (LA.evalAtom m) cs == False-      Just m  -> property $ all (LA.evalAtom m) cs+      Nothing -> forAll (genModel vs) $ \(m :: Model Rational) -> all (LA.eval m) cs == False+      Just m  -> property $ all (LA.eval m) cs  case_FourierMotzkin_test1 :: Assertion case_FourierMotzkin_test1 = @@ -204,7 +205,7 @@     Nothing -> assertFailure "expected: Just\n but got: Nothing"     Just m  ->       forM_ (snd test1') $ \a -> do-        LA.evalAtom m a @?= True+        LA.eval m a @?= True  case_FourierMotzkin_test2 :: Assertion case_FourierMotzkin_test2 = @@ -212,7 +213,7 @@     Nothing -> assertFailure "expected: Just\n but got: Nothing"     Just m  ->       forM_ (snd test2') $ \a -> do-        LA.evalAtom m a @?= True+        LA.eval m a @?= True  {- Maximize@@ -229,7 +230,7 @@ case_FourierMotzkinOptimization_test1 :: Assertion case_FourierMotzkinOptimization_test1 = do   Interval.upperBound' i @?= (3005/24, True)-  and [LA.evalAtom m c | c <- cs] @?= True+  and [LA.eval m c | c <- cs] @?= True   where     (i, f) = FMOpt.optimize (IS.fromList vs) OptMax obj cs     m = f (3005/24)@@ -253,8 +254,8 @@ prop_VirtualSubstitution_solve =    forAll genQFLAConj $ \(vs,cs) ->      case VirtualSubstitution.solve vs cs of-       Nothing -> forAll (genModel vs) $ \m -> all (LA.evalAtom m) cs == False-       Just m  -> property $ all (LA.evalAtom m) cs+       Nothing -> forAll (genModel vs) $ \(m :: Model Rational) -> all (LA.eval m) cs == False+       Just m  -> property $ all (LA.eval m) cs  case_VirtualSubstitution_test1 :: Assertion case_VirtualSubstitution_test1 = @@ -262,7 +263,7 @@     Nothing -> assertFailure "expected: Just\n but got: Nothing"     Just m  ->       forM_ (snd test1') $ \a -> do-        LA.evalAtom m a @?= True+        LA.eval m a @?= True  case_VirtualSubstitution_test2 :: Assertion case_VirtualSubstitution_test2 = @@ -270,7 +271,7 @@     Nothing -> assertFailure "expected: Just\n but got: Nothing"     Just m  ->       forM_ (snd test2') $ \a -> do-        LA.evalAtom m a @?= True+        LA.eval m a @?= True  ------------------------------------------------------------------------         @@ -340,8 +341,9 @@ prop_OmegaTest_solve =    forAll genQFLAConjSmallInt $ \(vs,cs) ->      case OmegaTest.solve def vs cs of-       Nothing -> forAll (genModel vs) $ \m -> all (LA.evalAtom (fmap fromInteger m)) cs == False-       Just m  -> property $ all (LA.evalAtom (fmap fromInteger m)) cs+       Nothing ->+         forAll (liftM (fmap fromInteger) $ genModel vs) $ \(m :: Model Rational) -> all (LA.eval m) cs == False+       Just m  -> property $ all (LA.eval (fmap fromInteger m :: Model Rational)) cs  case_OmegaTest_test1 :: Assertion case_OmegaTest_test1 = @@ -349,7 +351,7 @@     Nothing -> assertFailure "expected: Just\n but got: Nothing"     Just m  -> do       forM_ (snd test1') $ \a -> do-        LA.evalAtom (IM.map fromInteger m) a @?= True+        LA.eval (IM.map fromInteger m :: Model Rational) a @?= True  case_OmegaTest_test2 :: Assertion case_OmegaTest_test2 = @@ -371,9 +373,10 @@    forAll genQFLAConjSmallInt $ \(vs,cs) ->      case Cooper.solve vs cs of        Nothing ->-         (forAll (genModel vs) $ \m -> all (LA.evalAtom (fmap fromInteger m)) cs == False) QC..&&.+         (forAll (liftM (fmap fromInteger) $ genModel vs) $ \(m :: Model Rational) -> all (LA.eval m) cs == False)+         QC..&&.          property (OmegaTest.solve def vs cs == Nothing)-       Just m  -> property $ all (LA.evalAtom (fmap fromInteger m)) cs+       Just m  -> property $ all (LA.eval (fmap fromInteger m :: Model Rational)) cs  case_Cooper_test1 :: Assertion case_Cooper_test1 = @@ -381,7 +384,7 @@     Nothing -> assertFailure "expected: Just\n but got: Nothing"     Just m  -> do       forM_ (snd test1') $ \a -> do-        LA.evalAtom (IM.map fromInteger m) a @?= True+        LA.eval (IM.map fromInteger m :: Model Rational) a @?= True  case_Cooper_test2 :: Assertion case_Cooper_test2 = @@ -391,81 +394,61 @@  ------------------------------------------------------------------------     -prop_Simplex2_solve :: Property-prop_Simplex2_solve = QM.monadicIO $ do-   (vs,cs) <- QM.pick genQFLAConj-   join $ QM.run $ do-     solver <- Simplex2.newSolver-     m <- liftM IM.fromList $ forM (IS.toList vs) $ \v -> do-       v2 <- Simplex2.newVar solver-       return (v, LA.var v2)-     let cs' = map (LA.applySubstAtom m) cs-     forM_ cs' $ \c -> do-       Simplex2.assertAtomEx solver c-     ret <- Simplex2.check solver-     if ret then do-       m <- Simplex2.getModel solver-       return $ forM_ cs' $ \c -> QM.assert (LA.evalAtom m c)-     else do-       return $ return ()+prop_Simplex_solve :: Property+prop_Simplex_solve = forAll genQFLAConj $ \(vs,cs) -> do+  case SimplexSimple.check vs cs of+    Nothing -> True+    Just m -> all (LA.eval m) cs -case_Simplex2_test1 :: Assertion-case_Simplex2_test1 = do-  solver <- Simplex2.newSolver-  forM_ (IS.toList (fst test1')) $ \_ -> Simplex2.newVar solver-  mapM_ (Simplex2.assertAtomEx solver) (snd test1')-  ret <- Simplex2.check solver-  ret @?= True+case_Simplex_test1 :: Assertion+case_Simplex_test1 =+  isJust (uncurry SimplexSimple.check test1') @?= True -case_Simplex2_test2 :: Assertion-case_Simplex2_test2 = do-  solver <- Simplex2.newSolver-  forM_ (IS.toList (fst test2')) $ \_ -> Simplex2.newVar solver-  mapM_ (Simplex2.assertAtomEx solver) (snd test2')-  ret <- Simplex2.check solver-  ret @?= True+case_Simplex_test2 :: Assertion+case_Simplex_test2 = do+  isJust (uncurry SimplexSimple.check test2') @?= True -prop_Simplex2_backtrack :: Property-prop_Simplex2_backtrack = QM.monadicIO $ do+prop_Simplex_backtrack :: Property+prop_Simplex_backtrack = QM.monadicIO $ do    (vs,cs) <- QM.pick genQFLAConj    (vs2,cs2) <- QM.pick genQFLAConj     join $ QM.run $ do-     solver <- Simplex2.newSolver+     solver <- Simplex.newSolver      m <- liftM IM.fromList $ forM (IS.toList (vs `IS.union` vs2)) $ \v -> do-       v2 <- Simplex2.newVar solver+       v2 <- Simplex.newVar solver        return (v, LA.var v2)      forM_ cs $ \c -> do-       Simplex2.assertAtomEx solver (LA.applySubstAtom m c)-     ret <- Simplex2.check solver+       Simplex.assertAtomEx solver (LA.applySubstAtom m c)+     ret <- Simplex.check solver      if ret then do-       Simplex2.pushBacktrackPoint solver+       Simplex.pushBacktrackPoint solver        forM_ cs2 $ \c -> do-         Simplex2.assertAtomEx solver (LA.applySubstAtom m c)-       _ <- Simplex2.check solver-       Simplex2.popBacktrackPoint solver-       ret2 <- Simplex2.check solver+         Simplex.assertAtomEx solver (LA.applySubstAtom m c)+       _ <- Simplex.check solver+       Simplex.popBacktrackPoint solver+       ret2 <- Simplex.check solver        return $ QM.assert ret2      else do        return $ return () -prop_Simplex2_explain :: Property-prop_Simplex2_explain = QM.monadicIO $ do+prop_Simplex_explain :: Property+prop_Simplex_explain = QM.monadicIO $ do    (vs,cs) <- QM.pick genQFLAConj     let f p = QM.run $ do-         solver <- Simplex2.newSolver+         solver <- Simplex.newSolver          m <- liftM IM.fromList $ forM (IS.toList vs) $ \v -> do-           v2 <- Simplex2.newVar solver+           v2 <- Simplex.newVar solver            return (v, LA.var v2)          forM (zip [0..] cs) $ \(i,c) -> do            when (p i) $-             Simplex2.assertAtomEx' solver (LA.applySubstAtom m c) (Just i)-         ret <- Simplex2.check solver+             Simplex.assertAtomEx' solver (LA.applySubstAtom m c) (Just i)+         ret <- Simplex.check solver          if ret then do            return Nothing          else do-           liftM Just $ Simplex2.explain solver+           liftM Just $ Simplex.explain solver     ret <- f (const True)    case ret of@@ -487,7 +470,7 @@     Nothing -> assertFailure "expected: Just\n but got: Nothing"     Just m  -> do       forM_ (snd test1') $ \a -> do-        LA.evalAtom (IM.map fromInteger m) a @?= True+        LA.eval (IM.map fromInteger m :: Model Rational) a @?= True  disabled_case_ContiTraverso_test2 :: Assertion disabled_case_ContiTraverso_test2 = 
+ test/Test/BipartiteMatching.hs view
@@ -0,0 +1,225 @@+{-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-}+module Test.BipartiteMatching (bipartiteMatchingTestGroup) where++import Control.Monad+import qualified Data.Foldable as F+import Data.Hashable+import Data.IntSet (IntSet)+import qualified Data.IntSet as IntSet+import Data.IntMap (IntMap)+import qualified Data.IntMap as IntMap+import Data.Map (Map, (!))+import qualified Data.Map as Map+import Data.Set+import qualified Data.Set as Set+import ToySolver.Combinatorial.BipartiteMatching++import Test.Tasty+import Test.Tasty.QuickCheck+import Test.Tasty.HUnit+import Test.Tasty.TH++prop_maximumCardinalityMatching =+  forAll (arbitrarySmallIntSet 7) $ \as ->+    forAll (arbitrarySmallIntSet 7) $ \bs ->+      forAll (arbitrarySubsetOf [(a,b) | a <- IntSet.toList as, b <- IntSet.toList bs]) $ \es ->+        let m = maximumCardinalityMatching as bs es+        in isMatching m &&+           and [not (isMatching m') || IntMap.size m >= IntMap.size m' | m' <- allMatchings as bs es]+  where+    isMatching m = IntSet.size (IntSet.fromList (IntMap.elems m)) == IntMap.size m++prop_maximumWeightMatching =+  forAll (arbitrarySmallIntSet 7) $ \as ->+    forAll (arbitrarySmallIntSet 7) $ \bs ->+      forAll (arbitraryWeight' as bs) $ \(w :: Map (Int,Int) Rational) ->+        let (obj, m) = maximumWeightMatching as bs [(a,b,w) | ((a,b),w) <- Map.toList w]+        in isMatching m &&+           obj == sum [w Map.! (a,b) | (a,b) <- IntMap.toList m] &&+           and [ not (isMatching m') || obj >= sum [w Map.! (a,b) | (a,b) <- IntMap.toList m']+               | m' <- allMatchings as bs (Map.keys w) ]+  where+    isMatching m = IntSet.size (IntSet.fromList (IntMap.elems m)) == IntMap.size m++prop_maximumWeightMatchingComplete =+  forAll (arbitrarySmallIntSet 7) $ \as ->+    forAll (arbitrarySmallIntSet 7) $ \bs ->+      forAll (arbitraryWeight as bs) $ \(w :: Map (Int,Int) Rational) ->+        let (obj, m) = maximumWeightMatchingComplete as bs (\a b -> w Map.! (a,b))+        in isMatching m &&+           obj == sum [w Map.! (a,b) | (a,b) <- IntMap.toList m] &&+           and [ not (isMatching m') || obj >= sum [w Map.! (a,b) | (a,b) <- IntMap.toList m']+               | m' <- allMatchings as bs (Map.keys w) ]+  where+    isMatching m = IntSet.size (IntSet.fromList (IntMap.elems m)) == IntMap.size m++case_minimumWeightPerfectMatchingComplete_1 = do+  obj @?= 8+  m @?= IntMap.fromList [(1,2), (3,4)]+  where+    (obj, m, _) = minimumWeightPerfectMatchingComplete as bs (\a b -> w Map.! (a,b))+    as = IntSet.fromList [1,3]+    bs = IntSet.fromList [2,4]+    w :: Map (Int,Int) Int+    w = Map.fromList [((1,2),5),((1,4),2),((3,2),9),((3,4),3)]++prop_minimumWeightPerfectMatchingComplete =+  forAll (choose (0,10)) $ \n ->+    let as = IntSet.fromList [1..n]+        bs = as+        isPerfectMatching m = IntMap.keysSet m == as && IntSet.fromList (IntMap.elems m) == bs+    in forAll (arbitraryWeight as bs) $ \(w' :: Map (Int,Int) Rational) ->+         let w a b = w' ! (a,b)+             (obj, m, (ysA,ysB)) = minimumWeightPerfectMatchingComplete as bs w+         in isPerfectMatching m &&+            obj == sum [w a b | (a,b) <- IntMap.toList m] &&+            obj == F.sum ysA + F.sum ysB &&+            and [ya + yb <= w a b | (a,ya) <- IntMap.toList ysA, (b,yb) <- IntMap.toList ysB]++prop_maximumWeightPerfectMatchingComplete =+  forAll (choose (0,10)) $ \n ->+    let as = IntSet.fromList [1..n]+        bs = as+        isPerfectMatching m = IntMap.keysSet m == as && IntSet.fromList (IntMap.elems m) == bs+    in forAll (arbitraryWeight as as) $ \(w' :: Map (Int,Int) Rational) ->+         let w a b = w' ! (a,b)+             (obj, m, (ysA,ysB)) = maximumWeightPerfectMatchingComplete as as w+         in isPerfectMatching m &&+            obj == sum [w a b | (a,b) <- IntMap.toList m] &&+            obj == F.sum ysA + F.sum ysB &&+            and [ya + yb >= w a b | (a,ya) <- IntMap.toList ysA, (b,yb) <- IntMap.toList ysB]++prop_minimumWeightPerfectMatching =+  forAll (arbitrarySmallIntSet 7) $ \as ->+    forAll (arbitrarySmallIntSet 7) $ \bs ->+      let isPerfectMatching m = IntMap.keysSet m == as && IntSet.fromList (IntMap.elems m) == bs+      in forAll (arbitraryWeight' as bs) $ \(w :: Map (Int,Int) Rational) ->+           case minimumWeightPerfectMatching as bs [(a,b,w) | ((a,b),w) <- Map.toList w] of+             Nothing ->+               and [not (isPerfectMatching m) | m <- allMatchings as bs (Map.keys w)]+             Just (obj, m, (ysA,ysB)) ->+               isPerfectMatching m &&+               obj == sum [w Map.! (a,b) | (a,b) <- IntMap.toList m] &&+               obj == F.sum ysA + F.sum ysB &&+               and [ case Map.lookup (a,b) w of+                       Nothing -> True+                       Just v -> ya + yb <= v+                   | (a,ya) <- IntMap.toList ysA, (b,yb) <- IntMap.toList ysB ] &&+               and [ not (isPerfectMatching m') || obj <= sum [w Map.! (a,b) | (a,b) <- IntMap.toList m']+                   | m' <- allMatchings as bs (Map.keys w) ]++prop_maximumWeightPerfectMatching =+  forAll (arbitrarySmallIntSet 7) $ \as ->+    forAll (arbitrarySmallIntSet 7) $ \bs ->+      let isPerfectMatching m = IntMap.keysSet m == as && IntSet.fromList (IntMap.elems m) == bs+      in forAll (arbitraryWeight' as bs) $ \(w :: Map (Int,Int) Rational) ->+           case maximumWeightPerfectMatching as bs [(a,b,w) | ((a,b),w) <- Map.toList w] of+             Nothing ->+               and [not (isPerfectMatching m) | m <- allMatchings as bs (Map.keys w)]+             Just (obj, m, (ysA,ysB)) ->+               isPerfectMatching m &&+               obj == sum [w Map.! (a,b) | (a,b) <- IntMap.toList m] &&+               obj == F.sum ysA + F.sum ysB &&+               and [ case Map.lookup (a,b) w of+                       Nothing -> True+                       Just v -> ya + yb >= v+                   | (a,ya) <- IntMap.toList ysA, (b,yb) <- IntMap.toList ysB ] &&+               and [ not (isPerfectMatching m') || obj >= sum [w Map.! (a,b) | (a,b) <- IntMap.toList m']+                   | m' <- allMatchings as bs (Map.keys w) ]++prop_minimumCardinalityEdgeCover =+  forAll (arbitrarySmallIntSet 4) $ \as ->+    forAll (arbitrarySmallIntSet 4) $ \bs ->+      forAll (arbitrarySubsetOf [(a,b) | a <- IntSet.toList as, b <- IntSet.toList bs]) $ \es ->+        let isEdgeCover cs =+              IntSet.fromList [a | (a,_) <- Set.toList cs] == as &&+              IntSet.fromList [b | (_,b) <- Set.toList cs] == bs+        in case minimumCardinalityEdgeCover as bs es of+             Nothing ->+               and [not (isEdgeCover cs') | cs' <- fmap Set.fromList $ subsetsOf es]+             Just cs ->+               isEdgeCover cs &&+               and [not (isEdgeCover cs') || Set.size cs <= Set.size cs' | cs' <- fmap Set.fromList $ subsetsOf es]++prop_minimumWeightEdgeCover =+  forAll (arbitrarySmallIntSet 4) $ \as ->+    forAll (arbitrarySmallIntSet 4) $ \bs ->+      forAll (arbitraryWeight' as bs) $ \(w :: Map (Int,Int) Rational) ->+        let es = Map.keys w+            isEdgeCover cs =+              IntSet.fromList [a | (a,_) <- Set.toList cs] == as &&+              IntSet.fromList [b | (_,b) <- Set.toList cs] == bs+            obj cs = sum [w Map.! (a,b) | (a,b) <- Set.toList cs]+        in case minimumWeightEdgeCover as bs [(a,b,w) | ((a,b),w) <- Map.toList w] of+             Nothing ->+               and [not (isEdgeCover cs') | cs' <- fmap Set.fromList $ subsetsOf es]+             Just cs ->+               isEdgeCover cs &&+               and [not (isEdgeCover cs') || obj cs <= obj cs' | cs' <- fmap Set.fromList $ subsetsOf es]++prop_minimumWeightEdgeCoverComplete =+  forAll (arbitrarySmallIntSet 4) $ \as ->+    forAll (arbitrarySmallIntSet 4) $ \bs ->+      forAll (arbitraryWeight as bs) $ \(w :: Map (Int,Int) Rational) ->+        let es = Map.keys w+            isEdgeCover cs =+              IntSet.fromList [a | (a,_) <- Set.toList cs] == as &&+              IntSet.fromList [b | (_,b) <- Set.toList cs] == bs+            obj cs = sum [w Map.! (a,b) | (a,b) <- Set.toList cs]+        in case minimumWeightEdgeCoverComplete as bs (\a b -> w Map.! (a,b)) of+             Nothing ->+               and [not (isEdgeCover cs') | cs' <- fmap Set.fromList $ subsetsOf es]+             Just cs ->+               isEdgeCover cs &&+               and [not (isEdgeCover cs') || obj cs <= obj cs' | cs' <- fmap Set.fromList $ subsetsOf es]++allMatchings :: IntSet -> IntSet -> [(Int,Int)] -> [IntMap Int]+allMatchings as bs es = loop (IntSet.toList as) IntSet.empty IntMap.empty+  where+    es2 = Map.fromListWith IntSet.union [(a, IntSet.singleton b) | (a,b) <- es]+    loop [] _ m = return m+    loop (a : as) bs' m = do+      b <- IntSet.toList (Map.findWithDefault IntSet.empty a es2 `IntSet.difference` bs')+      loop as (IntSet.insert b bs') (IntMap.insert a b m)++subsetsOf :: [a] -> [[a]]+subsetsOf [] = [[]]+subsetsOf (x:xs) = do+  ys <- subsetsOf xs+  [ys, x:ys]++arbitrarySubsetOf :: [a] -> Gen [a]+arbitrarySubsetOf [] = return []+arbitrarySubsetOf (x:xs) = do+  ys <- arbitrarySubsetOf xs+  b <- arbitrary+  if b then+    return ys+  else+    return (x:ys)++arbitrarySmallIntSet :: Int -> Gen IntSet+arbitrarySmallIntSet maxCard = do+  nX <- choose (0,maxCard)+  liftM IntSet.fromList $ replicateM nX $ arbitrary++arbitraryWeight :: (Arbitrary w) => IntSet -> IntSet -> Gen (Map (Int, Int) w)+arbitraryWeight as bs =+  liftM Map.unions $ forM (IntSet.toList as) $ \a -> do+    liftM Map.fromList $ forM (IntSet.toList bs) $ \b -> do+      w <- arbitrary+      return ((a,b),w)++arbitraryWeight' :: (Arbitrary w) => IntSet -> IntSet -> Gen (Map (Int, Int) w)+arbitraryWeight' as bs =+  liftM Map.unions $ forM (IntSet.toList as) $ \a -> do+    liftM Map.unions $ forM (IntSet.toList bs) $ \b -> do+      x <- arbitrary+      if x then do+        w <- arbitrary+        return $ Map.singleton (a,b) w+      else+        return Map.empty++bipartiteMatchingTestGroup :: TestTree+bipartiteMatchingTestGroup = $(testGroupGenerator)
+ test/Test/BitVector.hs view
@@ -0,0 +1,151 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -Wall #-}+module Test.BitVector (bitVectorTestGroup) where++import Test.Tasty+import Test.Tasty.QuickCheck+import Test.Tasty.HUnit+import Test.Tasty.TH+import qualified Test.QuickCheck.Monadic as QM++import Control.Applicative+import Control.Monad+import Data.Monoid+import Data.Maybe++import ToySolver.Data.OrdRel+import qualified ToySolver.BitVector as BV++-- ------------------------------------------------------------------------++prop_BVSolver :: Property+prop_BVSolver = QM.monadicIO $ do+  (vs,cs) <- QM.pick genFormula+  ret <- QM.run $ do+    solver <- BV.newSolver+    forM_ vs $ \v -> do+      v' <- BV.newVar solver (BV.varWidth v)+      unless (v' == BV.EVar v) undefined -- XXX+      return ()+    forM_ cs $ \c -> do+      BV.assertAtom solver c Nothing+    ret <- BV.check solver+    if ret then do+      m <- BV.getModel solver+      return $ Just m+    else+      return Nothing+  case ret of+    Nothing -> return ()+    Just m -> do+      QM.monitor (counterexample $ show m)+      QM.assert $ and [BV.evalAtom m c | c <- cs]++case_division_by_zero_cong :: IO ()+case_division_by_zero_cong = do+  solver <- BV.newSolver+  v1 <- BV.newVar solver 8+  v2 <- BV.newVar solver 8+  let z = BV.nat2bv 8 0+  BV.assertAtom solver (BV.bvudiv v1 z ./=. BV.bvudiv v2 z) Nothing+  ret <- BV.check solver+  ret @?= True+  BV.assertAtom solver (v1 .==. v2) Nothing+  ret2 <- BV.check solver+  ret2 @?= False++-- ------------------------------------------------------------------------+-- Generators++genBVExpr :: [BV.Expr] -> Int -> Int -> Gen BV.Expr+genBVExpr bases = f+  where+    f :: Int -> Int -> Gen BV.Expr+    f w s = do+      let gBase+            | w > 0 && wmax >= w = Just $ do+                e <- elements [e | e <- bases, BV.width e >= w]+                if BV.width e == w then do+                  return e+                else do+                  l <- choose (0, BV.width e - w) -- inclusive range+                  let u = l + w - 1+                  return $ BV.extract u l e+            | otherwise = Nothing+            where+              wmax = maximum (0 : map BV.width bases)+          gConst = do+            bs <- replicateM w arbitrary+            return $ BV.fromDescBits bs+          gConcat = do+            if s <= 0 then do+              w1 <- choose (1,w-1)+              lhs <- f w1 0+              rhs <- f (w - w1) 0+              return $ lhs <> rhs+            else do+              w1 <- choose (0,w)+              s1 <- choose (0,s)+              lhs <- f w1 s1+              rhs <- f (w - w1) (s - s1)+              return $ lhs <> rhs+          gExtract = do+            wd <- choose (0,10)+            e <- f (w + wd) (s - 1)+            l <- choose (0, BV.width e - w) -- inclusive range+            let u = l + w - 1+            return $ BV.extract u l e+          gNormalOp1 = do+            op <- elements [BV.bvnot, BV.bvneg]+            e <- f w (s - 1)+            return $ op e+          gNormalOp2 = do+            op <- elements $+                    [BV.bvand, BV.bvor, BV.bvxor, BV.bvnand, BV.bvnor, BV.bvxnor] +++                    [BV.bvadd, BV.bvsub, BV.bvmul, BV.bvudiv, BV.bvurem, BV.bvshl, BV.bvlshr, BV.bvashr] +++                    (if w >= 1 then [BV.bvsdiv, BV.bvsrem, BV.bvsmod] else [])+            s1 <- choose (0,s)+            lhs <- f w s1+            rhs <- f w (s - s1)+            return $ op lhs rhs+          gComp = do+            w1 <- choose (0, wmax*2)+            s1 <- choose (0,s)+            lhs <- f w1 s1+            rhs <- f w1 (s - s1)+            return $ BV.bvcomp lhs rhs+            where+              wmax = maximum (0 : map BV.width bases)+      if s <= 0 then do+        oneof $ maybeToList gBase ++ [gConst] ++ [gConcat | w >= 2]+      else do+        oneof $ maybeToList gBase ++ [gConst, gNormalOp1, gNormalOp2] ++ (if w > 0 then [gConcat, gExtract] else []) ++ [gComp | w == 1]++genBVAtom :: [BV.Expr] -> Int -> Gen BV.Atom+genBVAtom bases size = do+  w <- choose (0,16)+  s1 <- choose (0,size)+  e1 <- genBVExpr bases w s1+  e2 <- genBVExpr bases w (size - s1)+  op  <- elements [Lt, Le, Ge, Gt, Eql, NEq]+  signed <- arbitrary+  return $ BV.Rel (ordRel op e1 e2) signed++genFormula :: Gen ([BV.Var], [BV.Atom])+genFormula = do+  vs <- forM [0..2] $ \v -> do+    w <- choose (1,16)+    return $ BV.Var{ BV.varWidth = w, BV.varId = v }+  let bases = [BV.EVar v | v <- vs]+  nc <- choose (0,3)+  cs <- replicateM nc $ do+    size <- choose (1,8)+    genBVAtom bases size+  return (vs,cs)++-- ------------------------------------------------------------------------+-- Test harness++bitVectorTestGroup :: TestTree+bitVectorTestGroup = $(testGroupGenerator)
test/Test/CongruenceClosure.hs view
@@ -7,9 +7,7 @@ import Data.Array import Data.Graph import qualified Data.Tree as Tree-import Data.IntSet (IntSet) import qualified Data.IntSet as IntSet-import Data.Set (Set) import qualified Data.Set as Set  import Test.Tasty@@ -190,7 +188,7 @@   a <- newConst solver   b <- newConst solver   c <- newConst solver-  d <- newConst solver+  _d <- newConst solver   f <- newFun solver   g <- newFun solver   h <- newFun solver
test/Test/FiniteModelFinder.hs view
@@ -1,11 +1,14 @@-{-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell, ScopedTypeVariables, OverloadedStrings #-} module Test.FiniteModelFinder (fmfTestGroup) where  import Control.Monad import Control.Monad.State import Control.Monad.Trans+import Data.Interned (intern, unintern) import Data.Map (Map) import qualified Data.Map as Map+import Data.Monoid+import Data.String  import Test.Tasty import Test.Tasty.QuickCheck hiding ((.&&.), (.||.))@@ -58,16 +61,16 @@   nPred <- choose (0::Int, 3)   fsyms <- liftM Map.fromList $ forM [0..nFun-1] $ \i -> do     arity <- if i == 0 then return 0 else choose (0, 3)-    return ("f" ++ show i, arity)+    return (intern ("f" <> fromString (show i)), arity)   psyms <- liftM Map.fromList $ forM [0..nPred-1] $ \i -> do     arity <- choose (0, 3)-    return ("p" ++ show i, arity)+    return (intern ("p" <> fromString (show i)), arity)   return (fsyms, psyms)  prop_findModel_soundness = QM.monadicIO $ do   sig <- QM.pick genSmallSig   nv <- QM.pick $ choose (0::Int, 2)-  let vs = ["v" ++ show i | i <- [0..nv-1]]+  let vs = [fromString ("v" ++ show i) | i <- [0..nv-1]]   nc <- QM.pick $ choose (0::Int, 3)   cs <- QM.pick $ replicateM nc $ genClause sig vs   size <- QM.pick $ choose (1::Int, 5)
+ test/Test/GraphShortestPath.hs view
@@ -0,0 +1,985 @@+{-# OPTIONS_GHC -Wall -fno-warn-orphans #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-}+module Test.GraphShortestPath (graphShortestPathTestGroup) where++import Control.Monad+import Data.Hashable+import Data.Monoid+import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.QuickCheck hiding ((.&&.), (.||.))+import Test.Tasty.TH+import ToySolver.Graph.ShortestPath+import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HashMap+import qualified Data.HashSet as HashSet++-- ------------------------------------------------------------------------++type Vertex = Int+type Cost = Rational+type Label = Char+    +genGraph :: Gen Cost -> Gen (HashMap Vertex [OutEdge Vertex Cost Label])+genGraph genCost = do+  n <- choose (1, 20) -- inclusive+  liftM HashMap.fromList $ forM [1..n] $ \i -> do+    m <- choose (0, min (n+1) 20)+    ys <- replicateM m $ do+      j <- choose (1, n)+      c <- genCost+      l <- elements ['A'..'Z']+      return (j,c,l)+    return (i, ys)++genGraphNonNegative :: Gen (HashMap Vertex [OutEdge Vertex Cost Label])+genGraphNonNegative = genGraph (liftM getNonNegative arbitrary)++isValidEdge+  :: (Eq vertex, Hashable vertex, Eq cost, Eq label)+  => HashMap vertex [OutEdge vertex cost label]+  -> Edge vertex cost label+  -> Bool+isValidEdge g (v,u,c,l) =+  case HashMap.lookup  v g of+    Nothing -> False+    Just outs -> (u,c,l) `elem` outs++isValidPath+  :: (Eq vertex, Hashable vertex, Eq cost, Num cost, Eq label)+  => HashMap vertex [OutEdge vertex cost label]+  -> Path vertex cost label+  -> Bool+isValidPath g = f+  where+    f (Empty v) = v `HashMap.member` g+    f (Singleton e) = isValidEdge g e+    f (Append p1 p2 c) = f p1 && f p2 && pathTo p1 == pathFrom p2 && pathCost p1 + pathCost p2 == c++isValidNegativeCostCycle+  :: (Eq vertex, Hashable vertex, Num cost, Ord cost, Eq label)+  => HashMap vertex [OutEdge vertex cost label]+  -> Path vertex cost label+  -> Bool+isValidNegativeCostCycle g cyclePath =+  isValidPath g cyclePath &&+  pathFrom cyclePath == pathTo cyclePath &&+  pathCost cyclePath < 0++isValidResult+  :: (Eq vertex, Hashable vertex, Eq cost, Num cost, Eq label)+  => HashMap vertex [OutEdge vertex cost label]+  -> [vertex]+  -> HashMap vertex (cost, Last (InEdge vertex cost label))+  -> Bool+isValidResult g ss p = +  and+  [ case m of+      Nothing -> tc == 0 && u `HashSet.member` ss'+      Just (v,c,l) -> isValidEdge g (v,u,c,l) && tc == fst (p HashMap.! v) + c+  | (u, (tc,Last m)) <- HashMap.toList p+  ]+  where+    ss' = HashSet.fromList ss++-- ------------------------------------------------------------------------++prop_bellmanFord_valid_path :: Property+prop_bellmanFord_valid_path =+  forAll (genGraph arbitrary) $ \g ->+    forAll (sublistOf (HashMap.keys g)) $ \ss ->+      and+      [ isValidPath g p &&+        pathTo p == u &&+        pathFrom p `elem` ss+      | (u, (_,p)) <- HashMap.toList $ bellmanFord path g ss+      ]++prop_dijkstra_valid_path :: Property+prop_dijkstra_valid_path =+  forAll (genGraphNonNegative) $ \g ->+    forAll (sublistOf (HashMap.keys g)) $ \ss ->+      and+      [ isValidPath g p &&+        pathTo p == u &&+        pathFrom p `elem` ss+      | (u, (_,p)) <- HashMap.toList $ dijkstra path g ss+      ]++prop_floydWarshall_valid_path :: Property+prop_floydWarshall_valid_path =+  forAll (genGraphNonNegative) $ \g ->+      and+      [ isValidPath g p &&+        pathFrom p == u &&+        pathTo p == v+      | (u,m) <- HashMap.toList (floydWarshall path g)+      , (v,(_,p)) <- HashMap.toList m+      ]++prop_dijkstra_equals_bellmanFord :: Property+prop_dijkstra_equals_bellmanFord =+  forAll (genGraphNonNegative) $ \g ->+    let vs = HashMap.keys g+    in forAll (elements vs) $ \v ->+       forAll (elements vs) $ \u ->+         (fmap (pathCost . snd) . HashMap.lookup u $ dijkstra path g [v])+         ==+         (fmap (pathCost . snd) . HashMap.lookup u $ bellmanFord path g [v])++prop_floydWarshall_equals_dijkstra :: Property+prop_floydWarshall_equals_dijkstra =+  forAll (genGraphNonNegative) $ \g ->+    let vs = HashMap.keys g+        m  = floydWarshall path g+    in forAll (elements vs) $ \v ->+       forAll (elements vs) $ \u ->+         fmap (pathCost . snd) (HashMap.lookup u =<< HashMap.lookup v m)+         ==+         fmap (pathCost . snd) (HashMap.lookup u $ dijkstra path g [v])++prop_floydWarshall_equals_bellmanFord :: Property+prop_floydWarshall_equals_bellmanFord =+  forAll (genGraph arbitrary) $ \g ->+    let vs = HashMap.keys g+        ret1 = floydWarshall lastInEdge g+    in counterexample (show ret1) $ conjoin $+         [ counterexample (show v) $ counterexample (show ret2) $+             case bellmanFordDetectNegativeCycle path g ret2 of+               Just cyclePath ->+                 conjoin+                 [ counterexample (show u) (fst (ret1 HashMap.! u HashMap.! u) < 0)+                 | u <- pathVertexes cyclePath+                 ]+               Nothing ->+                 fmap fst (HashMap.lookupDefault HashMap.empty v ret1)+                 ===+                 fmap fst ret2+         | v <- vs+         , let ret2 = bellmanFord lastInEdge g [v]+         ]++-- progassgn5.py example from “Linear and Discrete Optimization”+-- <https://www.coursera.org/course/linearopt>+case_bellmanFord_test1 :: Assertion+case_bellmanFord_test1 = do+  let ret = bellmanFord lastInEdge g ['A']+  ret @?= expected+  bellmanFordDetectNegativeCycle path g ret @?= Nothing+  where+    g :: HashMap Char [(Char, Int, ())]+    g = HashMap.fromList+        [ ('A', [('B',-7,()), ('C',-9,())])+        , ('B', [('C',-8,()), ('D',-10,())])+        , ('C', [('D',4,())])+        , ('D', [('E',-3,())])+        , ('E', [('F',5,())])+        , ('F', [('C',-3,())])+        ]+    expected = HashMap.fromList+      [ ('A', (0, Last Nothing))+      , ('B', (-7, Last (Just ('A',-7,()))))+      , ('C', (-18, Last (Just ('F',-3,()))))+      , ('D', (-17, Last (Just ('B',-10,()))))+      , ('E', (-20, Last (Just ('D',-3,()))))+      , ('F', (-15, Last (Just ('E',5,()))))+      ]++case_bellmanFord_normal :: Assertion+case_bellmanFord_normal = do+  let g = HashMap.fromListWith (++) $+            [(v,[(u,c,())]) | ((v,u),c) <- bellmanford_example_normal]+      m = bellmanFord lastInEdge g [24]+  assertBool (show m ++ " is not a valid result") $ isValidResult g [24] m+  case bellmanFordDetectNegativeCycle path g m of+    Nothing -> return ()+    Just cyclePath -> assertFailure ("negative cost cycle should not be found (" ++ show cyclePath ++ ")")++bellmanford_example_normal :: [((Vertex, Vertex), Cost)]+bellmanford_example_normal =+  [ ((7, 3), 236)+  , ((20, 25), 218)+  , ((6, 28), 765)+  , ((21, 28), 447)+  , ((17, 20), 454)+  , ((23, 26), 234)+  , ((21, 6), 19)+  , ((8, 5), 759)+  , ((9, 0), 814)+  , ((10, 7), 406)+  , ((0, 17), 456)+  , ((12, 17), 878)+  , ((25, 15), 633)+  , ((15, 4), 445)+  , ((26, 12), 758)+  , ((29, 17), 865)+  , ((29, 11), 143)+  , ((6, 23), 640)+  , ((20, 14), 235)+  , ((21, 15), 802)+  , ((23, 9), 548)+  , ((10, 14), 805)+  , ((11, 15), 563)+  , ((9, 19), 435)+  , ((24, 21), 841)+  , ((26, 23), 944)+  , ((4, 12), 831)+  , ((28, 1), 461)+  , ((6, 14), 858)+  , ((19, 18), 453)+  , ((18, 5), 72)+  , ((10, 9), 257)+  , ((8, 25), 328)+  , ((24, 28), 120)+  , ((12, 29), 901)+  , ((25, 3), 64)+  , ((6, 1), 597)+  , ((7, 4), 920)+  , ((5, 20), 812)+  , ((6, 27), 493)+  , ((9, 29), 178)+  , ((12, 20), 611)+  , ((25, 4), 662)+  , ((29, 22), 183)+  , ((28, 13), 319)+  , ((5, 29), 248)+  , ((20, 27), 255)+  , ((16, 11), 522)+  , ((21, 26), 537)+  , ((19, 6), 913)+  , ((18, 17), 743)+  , ((22, 11), -30)+  , ((9, 6), 819)+  , ((10, 5), 83)+  , ((11, 8), 361)+  , ((24, 16), 102)+  , ((12, 19), 371)+  , ((1, 18), 516)+  , ((15, 6), 353)+  , ((2, 25), 259)+  , ((26, 10), 23)+  , ((3, 4), 191)+  , ((5, 6), 609)+  , ((6, 21), 244)+  , ((19, 15), 359)+  , ((20, 8), 336)+  , ((16, 24), 282)+  , ((21, 13), -18)+  , ((23, 11), -33)+  , ((10, 12), 35)+  , ((8, 20), 132)+  , ((9, 17), 168)+  , ((25, 22), 367)+  , ((2, 16), 628)+  , ((27, 24), 350)+  , ((5, 15), 691)+  , ((29, 2), 677)+  , ((6, 12), 146)+  , ((4, 20), 253)+  , ((17, 4), 38)+  , ((23, 0), 937)+  , ((11, 6), 870)+  , ((10, 17), 200)+  , ((13, 4), 976)+  , ((0, 7), 371)+  , ((28, 26), 603)+  , ((2, 5), 867)+  , ((3, 24), 661)+  , ((7, 6), -10)+  , ((16, 22), 73)+  , ((6, 25), 188)+  , ((19, 3), 746)+  , ((22, 28), 330)+  , ((20, 4), 451)+  , ((24, 11), 213)+  , ((27, 22), 969)+  , ((13, 23), 970)+  , ((29, 20), 522)+  , ((27, 12), 13)+  , ((4, 26), 741)+  , ((28, 15), 956)+  , ((5, 27), 463)+  , ((29, 14), 779)+  , ((17, 8), 119)+  , ((7, 21), 797)+  , ((22, 23), 97)+  , ((23, 22), 840)+  , ((22, 9), 175)+  , ((23, 12), 633)+  , ((11, 10), 893)+  , ((14, 5), 734)+  , ((12, 13), 411)+  , ((26, 8), 33)+  , ((1, 10), 104)+  , ((4, 1), -7)+  , ((16, 4), 115)+  , ((6, 11), 318)+  , ((16, 26), 161)+  , ((17, 27), 564)+  , ((9, 13), 377)+  , ((11, 25), 407)+  , ((3, 15), 755)+  , ((1, 3), 745)+  , ((6, 2), 626)+  , ((19, 22), 94)+  , ((7, 11), 188)+  , ((16, 17), 283)+  , ((21, 20), 611)+  , ((9, 24), 179)+  , ((25, 29), 25)+  , ((13, 2), 391)+  , ((0, 25), 710)+  , ((28, 20), 800)+  , ((2, 3), 382)+  , ((27, 9), 415)+  , ((5, 16), 628)+  , ((20, 24), 540)+  , ((21, 29), 176)+  , ((19, 5), 530)+  , ((17, 21), 806)+  , ((8, 4), 385)+  , ((11, 23), 541)+  , ((1, 29), 177)+  , ((25, 8), 636)+  , ((26, 15), 347)+  , ((27, 14), 746)+  , ((29, 12), 147)+  , ((16, 15), 309)+  , ((6, 22), 624)+  , ((19, 10), 661)+  , ((17, 14), 188)+  , ((23, 14), 845)+  , ((8, 17), 228)+  , ((11, 12), 252)+  , ((24, 20), 358)+  , ((12, 15), 475)+  , ((13, 14), 963)+  , ((0, 13), 255)+  , ((3, 8), 753)+  , ((4, 3), 124)+  , ((28, 0), 205)+  , ((6, 9), 678)+  , ((17, 7), 167)+  , ((7, 12), 612)+  , ((17, 25), 38)+  , ((11, 5), 466)+  , ((24, 27), 651)+  , ((10, 18), 51)+  , ((25, 26), 544)+  , ((15, 11), 178)+  , ((0, 4), 17)+  , ((24, 1), 60)+  , ((12, 28), 161)+  , ((4, 10), 357)+  , ((5, 11), 66)+  , ((6, 0), 710)+  , ((4, 16), 633)+  , ((19, 24), 864)+  , ((5, 21), 449)+  , ((21, 18), 899)+  , ((17, 18), 759)+  , ((22, 25), -25)+  , ((18, 25), 896)+  , ((23, 28), 733)+  , ((14, 21), 578)+  , ((26, 24), 552)+  , ((0, 27), 644)+  , ((24, 8), 492)+  , ((28, 22), 325)+  , ((2, 1), 357)+  , ((29, 23), 421)+  , ((3, 28), 748)+  , ((6, 29), 809)+  , ((7, 24), 840)+  , ((18, 16), 634)+  , ((21, 5), 392)+  , ((8, 6), -18)+  , ((14, 28), 69)+  , ((10, 4), -42)+  , ((15, 25), 755)+  , ((12, 18), 721)+  , ((1, 19), 228)+  , ((25, 14), 789)+  , ((13, 19), 540)+  , ((2, 24), -44)+  , ((26, 13), 22)+  , ((0, 8), 485)+  , ((29, 16), 298)+  , ((3, 5), 725)+  , ((4, 6), 210)+  , ((28, 11), -38)+  , ((5, 7), 976)+  , ((29, 10), 185)+  , ((16, 1), 799)+  , ((17, 12), 478)+  , ((7, 17), 546)+  , ((20, 15), 872)+  , ((21, 14), 960)+  , ((8, 13), 145)+  , ((22, 13), 994)+  , ((23, 8), 556)+  , ((10, 15), 337)+  , ((8, 19), 423)+  , ((14, 9), 157)+  , ((12, 9), 567)+  , ((1, 20), 229)+  , ((15, 12), -46)+  , ((13, 12), 541)+  , ((28, 2), 738)+  , ((17, 5), 960)+  , ((7, 14), -38)+  , ((18, 28), 827)+  , ((23, 1), 665)+  , ((11, 7), 72)+  , ((9, 27), 490)+  , ((24, 29), 665)+  , ((12, 0), 126)+  , ((13, 5), 73)+  , ((2, 4), 217)+  , ((5, 9), 14)+  , ((21, 16), 843)+  , ((19, 0), 456)+  , ((17, 16), 682)+  , ((7, 29), 506)+  , ((8, 1), 146)+  , ((14, 27), 518)+  , ((15, 18), 92)+  , ((0, 29), 579)+  , ((24, 10), 722)+  , ((1, 24), 70)+  , ((25, 11), 848)+  , ((13, 24), 739)+  , ((28, 16), 301)+  , ((4, 25), 457)+  , ((29, 15), 429)+  , ((16, 12), 485)+  , ((6, 19), 502)+  , ((21, 25), 548)+  , ((19, 9), 772)+  , ((18, 14), 12)+  , ((9, 5), 378)+  , ((0, 20), 219)+  , ((24, 17), 563)+  , ((1, 17), 371)+  , ((25, 12), 846)+  , ((15, 1), 581)+  , ((2, 22), 986)+  , ((26, 11), 79)+  , ((0, 10), 696)+  , ((3, 7), 286)+  , ((27, 2), 280)+  , ((1, 11), -24)+  , ((4, 0), 583)+  , ((16, 3), 798)+  , ((6, 10), 518)+  , ((19, 14), 437)+  , ((17, 2), -20)+  , ((16, 25), 157)+  , ((10, 13), 587)+  , ((14, 15), 307)+  , ((15, 14), 690)+  , ((3, 12), 124)+  , ((4, 15), 755)+  , ((5, 14), -17)+  , ((29, 1), 550)+  , ((7, 8), 57)+  , ((17, 29), 593)+  , ((18, 26), 606)+  , ((23, 3), 515)+  , ((8, 28), 446)+  , ((13, 3), 899)+  , ((26, 29), 474)+  , ((12, 24), 300)+  , ((1, 5), 278)+  , ((28, 27), 194)+  , ((3, 27), 620)+  , ((4, 28), -33)+  , ((19, 28), 295)+  , ((7, 1), 482)+  , ((5, 17), 82)+  , ((19, 2), 151)+  , ((18, 21), 389)+  , ((9, 2), 942)+  , ((14, 25), 678)+  , ((10, 25), 669)+  , ((15, 28), 719)+  , ((11, 20), 719)+  , ((24, 12), 540)+  , ((2, 29), 582)+  , ((29, 19), 540)+  , ((3, 0), 264)+  , ((28, 8), 253)+  , ((5, 26), 974)+  , ((29, 13), 327)+  , ((19, 11), 143)+  , ((20, 12), 696)+  , ((18, 12), 493)+  , ((21, 1), 976)+  , ((22, 14), 285)+  , ((23, 15), 418)+  , ((10, 0), 306)+  , ((24, 19), 244)+  , ((12, 14), 281)+  , ((25, 18), 799)+  , ((15, 3), 224)+  , ((13, 15), 480)+  , ((26, 9), 162)+  , ((5, 3), 813)+  , ((29, 6), 492)+  , ((7, 13), 616)+  , ((18, 7), 312)+  , ((21, 10), 666)+  , ((10, 11), 106)+  , ((8, 23), 9)+  , ((11, 2), 39)+  , ((0, 3), 612)+  , ((24, 0), 982)+  , ((3, 14), 718)+  , ((1, 2), 981)+  , ((5, 12), 399)+  , ((3, 20), 451)+  , ((6, 3), 450)+  , ((4, 23), 554)+  , ((19, 25), 387)+  , ((20, 18), -6)+  , ((23, 29), 611)+  , ((14, 20), 449)+  , ((10, 28), 983)+  , ((15, 17), 383)+  , ((26, 27), 157)+  , ((24, 7), 505)+  , ((25, 6), 610)+  , ((13, 27), 746)+  , ((2, 0), 722)+  , ((26, 5), 346)+  , ((27, 8), 284)+  ]++case_bellmanFord_negativecost_cycle :: Assertion+case_bellmanFord_negativecost_cycle = do+  let g = HashMap.fromListWith (++) $+            [(v, [(u,c,())]) | ((v,u),c) <- bellmanford_example_negativecost_cycle]+      m = bellmanFord lastInEdge g [25]+  case bellmanFordDetectNegativeCycle path g m of+    Nothing -> assertFailure ("negative cost cycle should be found (" ++ show m ++ ")") +    Just cyclePath -> assertBool (show cyclePath ++ " should be valid negative cost cycle") $ isValidNegativeCostCycle g cyclePath++bellmanford_example_negativecost_cycle :: [((Vertex, Vertex), Cost)]+bellmanford_example_negativecost_cycle =+  [ ((7, 3), 558)+  , ((16, 9), 913)+  , ((21, 28), 902)+  , ((19, 4), 144)+  , ((7, 25), 706)+  , ((20, 7), 175)+  , ((18, 19), 767)+  , ((10, 7), 637)+  , ((11, 22), 55)+  , ((2, 27), 106)+  , ((29, 17), 736)+  , ((3, 2), 648)+  , ((4, 5), 783)+  , ((28, 10), 225)+  , ((5, 24), 69)+  , ((29, 11), 78)+  , ((21, 15), 91)+  , ((23, 9), 398)+  , ((10, 14), 388)+  , ((8, 18), 386)+  , ((14, 8), 80)+  , ((15, 13), 248)+  , ((2, 18), 373)+  , ((26, 23), 781)+  , ((1, 15), 79)+  , ((4, 12), 66)+  , ((5, 1), 382)+  , ((29, 4), 795)+  , ((3, 17), 61)+  , ((20, 21), 734)+  , ((17, 24), 796)+  , ((23, 6), 707)+  , ((9, 20), 29)+  , ((24, 28), 236)+  , ((12, 7), 779)+  , ((0, 5), 388)+  , ((2, 7), 32)+  , ((5, 10), 853)+  , ((19, 27), 133)+  , ((7, 4), 586)+  , ((5, 20), 543)+  , ((20, 28), 543)+  , ((6, 27), 423)+  , ((19, 1), 118)+  , ((18, 22), 853)+  , ((9, 29), 421)+  , ((10, 26), -41)+  , ((29, 22), 547)+  , ((27, 10), 729)+  , ((4, 24), 350)+  , ((28, 13), 668)+  , ((5, 29), 417)+  , ((20, 27), 275)+  , ((21, 26), 383)+  , ((17, 10), 596)+  , ((7, 27), 384)+  , ((8, 7), 889)+  , ((22, 11), 248)+  , ((11, 8), 946)+  , ((24, 16), 693)+  , ((14, 7), 908)+  , ((12, 19), 658)+  , ((1, 18), 469)+  , ((2, 25), 791)+  , ((26, 10), 201)+  , ((0, 9), 861)+  , ((4, 7), 38)+  , ((6, 21), 317)+  , ((18, 8), -30)+  , ((16, 24), 843)+  , ((22, 2), 573)+  , ((23, 11), 353)+  , ((11, 1), 734)+  , ((24, 23), 229)+  , ((12, 10), 697)+  , ((2, 16), 697)+  , ((3, 13), 177)+  , ((4, 14), 958)+  , ((29, 2), 651)+  , ((7, 9), 554)+  , ((20, 23), 229)+  , ((21, 22), 306)+  , ((22, 5), 84)+  , ((23, 0), 600)+  , ((8, 27), 74)+  , ((14, 17), 2)+  , ((12, 1), 227)+  , ((10, 17), -14)+  , ((15, 20), 53)+  , ((13, 4), 458)+  , ((26, 28), 75)+  , ((0, 7), 35)+  , ((1, 6), -7)+  , ((28, 26), 323)+  , ((29, 27), 441)+  , ((3, 24), -5)+  , ((6, 7), 731)+  , ((19, 29), 753)+  , ((7, 6), 932)+  , ((16, 22), 873)+  , ((19, 3), 863)+  , ((18, 20), 208)+  , ((23, 25), 237)+  , ((12, 22), 201)+  , ((27, 22), 783)+  , ((25, 10), 108)+  , ((13, 23), -29)+  , ((26, 1), 491)+  , ((3, 1), 524)+  , ((28, 15), 680)+  , ((16, 13), 54)+  , ((7, 21), 685)+  , ((23, 22), 288)+  , ((22, 9), 37)+  , ((23, 12), 160)+  , ((15, 26), 869)+  , ((11, 10), 950)+  , ((0, 21), 444)+  , ((14, 5), 875)+  , ((1, 16), 929)+  , ((25, 19), 426)+  , ((0, 11), 465)+  , ((27, 5), 883)+  , ((1, 10), 14)+  , ((28, 6), 909)+  , ((29, 7), 801)+  , ((6, 11), 144)+  , ((17, 1), 488)+  , ((7, 18), 670)+  , ((20, 10), 438)+  , ((16, 26), 760)+  , ((17, 27), 478)+  , ((23, 5), 997)+  , ((8, 22), 589)+  , ((11, 3), 582)+  , ((12, 4), 391)+  , ((25, 20), 212)+  , ((13, 9), 158)+  , ((27, 26), 723)+  , ((1, 3), 683)+  , ((4, 8), 726)+  , ((28, 29), 749)+  , ((2, 8), 18)+  , ((29, 0), 676)+  , ((20, 17), 599)+  , ((16, 17), 500)+  , ((21, 20), 343)+  , ((22, 27), 871)+  , ((18, 27), 363)+  , ((8, 29), 89)+  , ((14, 23), 79)+  , ((25, 29), 513)+  , ((15, 22), 323)+  , ((13, 2), 300)+  , ((27, 19), 503)+  , ((1, 4), 440)+  , ((13, 28), 993)+  , ((29, 25), 650)+  , ((3, 26), 920)+  , ((6, 5), 241)+  , ((5, 16), 297)+  , ((20, 24), 739)+  , ((21, 29), 194)+  , ((17, 21), 455)+  , ((8, 4), 787)+  , ((9, 1), 666)+  , ((11, 23), 77)+  , ((0, 16), 927)+  , ((24, 13), 334)+  , ((14, 0), 317)+  , ((12, 16), 955)+  , ((15, 5), 334)+  , ((2, 26), 748)+  , ((26, 15), 643)+  , ((28, 9), 333)+  , ((17, 14), 863)+  , ((22, 21), 359)+  , ((20, 13), 918)+  , ((18, 13), 1000)+  , ((0, 23), 688)+  , ((14, 11), 345)+  , ((0, 13), 401)+  , ((3, 8), 167)+  , ((27, 7), 323)+  , ((4, 3), 208)+  , ((28, 0), 470)+  , ((2, 15), 710)+  , ((16, 6), 393)+  , ((6, 9), 997)+  , ((17, 7), 223)+  , ((18, 4), 101)+  , ((17, 25), 854)+  , ((22, 6), 619)+  , ((23, 7), 488)+  , ((10, 8), 391)+  , ((11, 5), 380)+  , ((24, 27), 706)+  , ((12, 6), 86)+  , ((10, 18), 959)+  , ((25, 26), 168)+  , ((15, 11), 189)+  , ((11, 27), 946)+  , ((0, 4), 997)+  , ((12, 28), 120)+  , ((27, 28), 341)+  , ((4, 10), 177)+  , ((2, 6), 166)+  , ((5, 11), 118)+  , ((19, 24), 941)+  , ((16, 19), 695)+  , ((6, 26), 500)+  , ((17, 18), 572)+  , ((22, 25), 100)+  , ((23, 28), 175)+  , ((13, 0), 658)+  , ((26, 24), 144)+  , ((0, 27), 22)+  , ((24, 8), 445)+  , ((12, 27), 710)+  , ((27, 21), -7)+  , ((13, 26), 697)+  , ((28, 22), 82)+  , ((2, 1), 291)+  , ((26, 2), 997)+  , ((29, 23), 571)+  , ((28, 12), 60)+  , ((7, 2), 362)+  , ((20, 26), 105)+  , ((16, 10), 673)+  , ((21, 27), 463)+  , ((19, 7), 585)+  , ((22, 16), 158)+  , ((20, 0), 777)+  , ((23, 21), 495)+  , ((21, 5), 957)+  , ((8, 6), 566)+  , ((22, 10), 879)+  , ((14, 28), 48)+  , ((10, 4), 518)+  , ((11, 9), 516)+  , ((0, 18), 787)+  , ((14, 6), 879)+  , ((12, 18), 138)+  , ((2, 24), 585)+  , ((3, 5), 383)+  , ((5, 7), 661)+  , ((6, 20), 831)+  , ((23, 18), 784)+  , ((9, 8), 655)+  , ((10, 15), 254)+  , ((8, 19), 391)+  , ((14, 9), 862)+  , ((12, 9), 764)+  , ((25, 23), 685)+  , ((13, 12), 988)+  , ((27, 25), 435)+  , ((5, 0), 145)+  , ((6, 15), 843)+  , ((19, 21), -7)+  , ((21, 23), 583)+  , ((22, 4), 203)+  , ((11, 7), 457)+  , ((10, 16), 119)+  , ((11, 29), 520)+  , ((0, 6), 769)+  , ((24, 3), 430)+  , ((1, 7), 11)+  , ((25, 2), 68)+  , ((28, 25), 168)+  , ((2, 4), 183)+  , ((5, 9), 246)+  , ((29, 28), 737)+  , ((3, 25), 476)+  , ((5, 19), 455)+  , ((20, 29), 209)+  , ((18, 23), 168)+  , ((14, 27), 396)+  , ((24, 10), 480)+  , ((28, 16), 898)+  , ((27, 13), 816)+  , ((5, 28), 640)+  , ((6, 19), 287)+  , ((21, 25), -17)+  , ((19, 9), 451)+  , ((17, 9), 742)+  , ((18, 14), 223)+  , ((15, 27), 100)+  , ((25, 12), 579)+  , ((26, 11), 123)+  , ((1, 11), 314)+  , ((4, 0), 204)+  , ((6, 10), -36)+  , ((19, 14), 854)+  , ((18, 9), 641)+  , ((16, 25), 41)+  , ((21, 12), 870)+  , ((23, 10), 324)+  , ((8, 21), 123)+  , ((9, 16), 250)+  , ((12, 11), 28)+  , ((10, 23), 916)+  , ((26, 18), 53)+  , ((3, 12), 15)+  , ((4, 15), 459)+  , ((2, 11), 33)+  , ((5, 14), 859)+  , ((29, 1), -39)+  , ((3, 18), -16)+  , ((6, 13), 587)+  , ((17, 29), 369)+  , ((22, 26), 797)+  , ((18, 26), 173)+  , ((8, 28), 360)+  , ((9, 25), 859)+  , ((15, 23), 280)+  , ((13, 3), 12)+  , ((0, 24), 898)+  , ((25, 0), 942)+  , ((29, 26), 882)+  , ((6, 4), 307)+  , ((7, 1), 435)+  , ((16, 23), 667)+  , ((20, 5), 320)+  , ((23, 24), 287)+  , ((8, 3), 643)+  , ((24, 12), 679)+  , ((12, 23), 358)+  , ((25, 9), 437)+  , ((26, 14), 918)+  , ((4, 27), 74)+  , ((29, 13), 808)+  , ((6, 17), 647)+  , ((17, 15), 620)+  , ((20, 12), 735)+  , ((18, 12), 683)+  , ((23, 17), 342)+  , ((21, 1), 104)+  , ((8, 10), 297)+  , ((11, 13), 352)+  , ((0, 22), -17)+  , ((14, 10), 910)+  , ((12, 14), 458)+  , ((1, 23), -18)+  , ((25, 18), -13)+  , ((1, 9), 44)+  , ((28, 7), 20)+  , ((2, 14), -46)+  , ((5, 3), 25)+  , ((16, 5), 733)+  , ((17, 0), 854)+  , ((7, 13), 226)+  , ((18, 7), 770)+  , ((21, 10), 775)+  , ((23, 4), 29)+  , ((11, 2), 399)+  , ((24, 26), 762)+  , ((12, 5), 922)+  , ((15, 8), 709)+  , ((26, 16), 159)+  , ((24, 0), 953)+  , ((27, 29), 689)+  , ((2, 9), 539)+  , ((7, 10), 156)+  , ((16, 18), -7)+  , ((21, 19), 883)+  , ((23, 29), 960)+  , ((10, 28), 518)+  , ((25, 28), 744)+  , ((13, 1), 908)+  , ((0, 26), 810)+  , ((27, 18), 123)+  , ((1, 27), 453)+  , ((28, 21), 461)+  , ((2, 0), 449)+  , ((29, 24), 441)+  ]++case_floydWarshall_normal :: Assertion+case_floydWarshall_normal = do+  fmap (fmap fst) m @?= expected+  forM_ (HashMap.toList m) $ \(u,m1) -> do+    forM_ (HashMap.toList m1) $ \(v,(_,p)) -> do+      pathFrom p @?= u+      pathTo p @?= v+      assertBool (show p ++ " is not a valid path") (isValidPath floydWarshall_example p)+  where+    m = floydWarshall path floydWarshall_example+    expected = HashMap.fromListWith HashMap.union [(u, HashMap.singleton v c) | ((u,v),c) <- xs]+    xs =+      [ ((1,1),0), ((1,2),-1), ((1,3),-2), ((1,4),0)+      , ((2,1),4), ((2,2),0),  ((2,3),2),  ((2,4),4)+      , ((3,1),5), ((3,2),1),  ((3,3),0),  ((3,4),2)+      , ((4,1),3), ((4,2),-1), ((4,3),1),  ((4,4),0)+      ]++-- https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm+floydWarshall_example :: HashMap Vertex [OutEdge Vertex Cost ()]+floydWarshall_example = HashMap.fromList+  [ (1, [(3,-2,())])+  , (2, [(1,4,()), (3,3,())])+  , (3, [(4,2,())])+  , (4, [(2,-1,())])+  ]++-- ------------------------------------------------------------------------++#if !MIN_VERSION_QuickCheck(2,8,0)+sublistOf :: [a] -> Gen [a]+sublistOf xs = filterM (\_ -> choose (False, True)) xs+#endif++-- ------------------------------------------------------------------------+-- Test harness++graphShortestPathTestGroup :: TestTree+graphShortestPathTestGroup = $(testGroupGenerator)
test/Test/HittingSets.hs view
@@ -19,6 +19,8 @@ import qualified ToySolver.Combinatorial.HittingSet.Simple as HittingSet import qualified ToySolver.Combinatorial.HittingSet.FredmanKhachiyan1996 as FredmanKhachiyan1996 import qualified ToySolver.Combinatorial.HittingSet.GurvichKhachiyan1999 as GurvichKhachiyan1999+import qualified ToySolver.Combinatorial.HittingSet.DAA as DAA+import qualified ToySolver.Combinatorial.HittingSet.MARCO as MARCO  -- --------------------------------------------------------------------- -- Hitting sets@@ -249,8 +251,10 @@     f = Set.fromList $ map IntSet.fromList [[2,4,7], [7,8], [9]]     g = Set.fromList $ map IntSet.fromList [[7,9], [4,8,9], [2,8,9]] -prop_GurvichKhachiyan1999_generateCNFAndDNF :: Property-prop_GurvichKhachiyan1999_generateCNFAndDNF =+propGenerateCNFAndDNF+  :: (IntSet -> (IntSet -> Bool) -> Set IntSet -> Set IntSet -> (Set IntSet, Set IntSet))+  -> Property+propGenerateCNFAndDNF impl =    forAll hyperGraph $ \g ->     let vs = IntSet.unions $ Set.toList g         f xs = any (\is -> not $ IntSet.null $ xs `IntSet.intersection` is) (Set.toList g)@@ -259,30 +263,63 @@         is `isImplicateOf` f = is `isImplicantOf` dual f         is `isPrimeImplicantOf` f = is `isImplicantOf` f && all (\i -> not (IntSet.delete i is `isImplicantOf` f)) (IntSet.toList is)         is `isPrimeImplicateOf` f = is `isImplicateOf` f && all (\i -> not (IntSet.delete i is `isImplicateOf` f)) (IntSet.toList is)-        (cnf,dnf) = GurvichKhachiyan1999.generateCNFAndDNF vs f Set.empty Set.empty+        (cnf,dnf) = impl vs f Set.empty Set.empty     in all (`isPrimeImplicantOf` f) (Set.toList dnf) &&        all (`isPrimeImplicateOf` f) (Set.toList cnf) +propMinimalHittingSetsMinimality :: (Set IntSet -> Set IntSet) -> Property+propMinimalHittingSetsMinimality minimalHittingSets =+  forAll hyperGraph $ \g ->+    forAll (elements (Set.toList (minimalHittingSets g))) $ \s ->+      if IntSet.null s then+        property True+      else+        forAll (elements (IntSet.toList s)) $ \v ->+          not $ IntSet.delete v s `isHittingSetOf` g++propMinimalHittingSetsDuality :: (Set IntSet -> Set IntSet) -> Property+propMinimalHittingSetsDuality minimalHittingSets =+  forAll hyperGraph $ \g ->+    let h = minimalHittingSets g+    in h == minimalHittingSets (minimalHittingSets h)++propMinimalHittingSetsIsHittingSet :: (Set IntSet -> Set IntSet) -> Property+propMinimalHittingSetsIsHittingSet minimalHittingSets =+  forAll hyperGraph $ \g ->+    all (`isHittingSetOf` g) (minimalHittingSets g)++prop_GurvichKhachiyan1999_generateCNFAndDNF :: Property+prop_GurvichKhachiyan1999_generateCNFAndDNF = propGenerateCNFAndDNF GurvichKhachiyan1999.generateCNFAndDNF+ prop_GurvichKhachiyan1999_minimalHittingSets_duality :: Property prop_GurvichKhachiyan1999_minimalHittingSets_duality =-  forAll hyperGraph $ \g ->-    let h = GurvichKhachiyan1999.minimalHittingSets g-    in h == GurvichKhachiyan1999.minimalHittingSets (GurvichKhachiyan1999.minimalHittingSets h)+  propMinimalHittingSetsDuality GurvichKhachiyan1999.minimalHittingSets  prop_GurvichKhachiyan1999_minimalHittingSets_isHittingSet :: Property prop_GurvichKhachiyan1999_minimalHittingSets_isHittingSet =-  forAll hyperGraph $ \g ->-    all (`isHittingSetOf` g) (GurvichKhachiyan1999.minimalHittingSets g)+  propMinimalHittingSetsIsHittingSet GurvichKhachiyan1999.minimalHittingSets  prop_GurvichKhachiyan1999_minimalHittingSets_minimality :: Property prop_GurvichKhachiyan1999_minimalHittingSets_minimality =-  forAll hyperGraph $ \g ->-    forAll (elements (Set.toList (GurvichKhachiyan1999.minimalHittingSets g))) $ \s ->-      if IntSet.null s then-        property True-      else-        forAll (elements (IntSet.toList s)) $ \v ->-          not $ IntSet.delete v s `isHittingSetOf` g+  propMinimalHittingSetsIsHittingSet GurvichKhachiyan1999.minimalHittingSets++prop_DAA_generateCNFAndDNF :: Property+prop_DAA_generateCNFAndDNF = propGenerateCNFAndDNF DAA.generateCNFAndDNF++prop_MARCO_generateCNFAndDNF :: Property+prop_MARCO_generateCNFAndDNF = propGenerateCNFAndDNF MARCO.generateCNFAndDNF++prop_MARCO_minimalHittingSets_duality :: Property+prop_MARCO_minimalHittingSets_duality =+  propMinimalHittingSetsDuality MARCO.minimalHittingSets++prop_MARCO_minimalHittingSets_isHittingSet :: Property+prop_MARCO_minimalHittingSets_isHittingSet =+  propMinimalHittingSetsIsHittingSet MARCO.minimalHittingSets++prop_MARCO_minimalHittingSets_minimality :: Property+prop_MARCO_minimalHittingSets_minimality =+  propMinimalHittingSetsIsHittingSet MARCO.minimalHittingSets  ------------------------------------------------------------------------ -- Test harness
test/Test/LPFile.hs view
@@ -2,6 +2,7 @@ module Test.LPFile (lpTestGroup) where  import Control.Monad+import Data.Default.Class import Data.List import Data.Maybe import Test.Tasty@@ -42,20 +43,17 @@  checkFile :: FilePath -> Assertion checkFile fname = do-  r <- parseFile fname-  case r of-    Left err -> assertFailure $ show err-    Right lp ->-      case render lp of-        Left err -> assertFailure ("render failure: " ++ err)-        Right _ -> return ()+  lp <- parseFile def fname+  case render def lp of+    Left err -> assertFailure ("render failure: " ++ err)+    Right _ -> return ()  checkString :: String -> String -> Assertion checkString name str = do-  case parseString name str of+  case parseString def name str of     Left err -> assertFailure $ show err     Right lp ->-      case render lp of+      case render def lp of         Left err -> assertFailure ("render failure: " ++ err)         Right _ -> return () 
+ test/Test/MIP.hs view
@@ -0,0 +1,146 @@+{-# OPTIONS_GHC -Wall -fno-warn-orphans #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Test.MIP (mipTestGroup) where++import Algebra.PartialOrd+import Algebra.Lattice+import Data.Maybe+import qualified Data.Map as Map+import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.QuickCheck+import Test.Tasty.TH+import qualified ToySolver.Data.MIP as MIP+import qualified ToySolver.Data.MIP.Solution.CBC as CBCSol+import qualified ToySolver.Data.MIP.Solution.CPLEX as CPLEXSol+import qualified ToySolver.Data.MIP.Solution.GLPK as GLPKSol+import qualified ToySolver.Data.MIP.Solution.Gurobi as GurobiSol+import qualified ToySolver.Data.MIP.Solution.SCIP as SCIPSol++prop_status_refl :: Property+prop_status_refl = forAll arbitrary $ \(x :: MIP.Status) -> do+  x `leq` x++prop_status_trans :: Property+prop_status_trans =+  forAll arbitrary $ \(x :: MIP.Status) ->+    forAll (upper x) $ \y ->+      forAll (upper y) $ \z ->+        x `leq` z+  where+    -- upper :: (PartialOrd a, Enum a, Bounded a) => a -> Gen a+    upper a = elements [b | b <- [minBound .. maxBound], a `leq` b]++prop_status_meet_idempotency :: Property+prop_status_meet_idempotency =+  forAll arbitrary $ \(x :: MIP.Status) ->+    x `meet` x == x++prop_status_meet_comm :: Property+prop_status_meet_comm =+  forAll arbitrary $ \(x :: MIP.Status) y ->+    x `meet` y == y `meet` x++prop_status_meet_assoc :: Property+prop_status_meet_assoc =+  forAll arbitrary $ \(x :: MIP.Status) y z ->+    (x `meet` y) `meet` z == x `meet` (y `meet` z)++prop_status_meet_leq :: Property+prop_status_meet_leq =+  forAll arbitrary $ \(x :: MIP.Status) y ->+    x `meetLeq` y == x `leq` y++instance Arbitrary MIP.Status where+  arbitrary = arbitraryBoundedEnum++case_CBCSol :: Assertion+case_CBCSol = do+  sol <- CBCSol.readFile "samples/lp/test-solution-cbc.txt"+  sol @?=+    MIP.Solution+    { MIP.solStatus = MIP.StatusOptimal+    , MIP.solObjectiveValue = Just (-122.5)+    , MIP.solVariables = Map.fromList [("x1", 40), ("x2", 10.5), ("x3", 19.5), ("x4", 3)]+    }++case_CBCSol_infeasible :: Assertion+case_CBCSol_infeasible = do+  sol <- CBCSol.readFile "samples/lp/test-solution-cbc-infeasible.txt"+  sol @?=+    MIP.Solution+    { MIP.solStatus = MIP.StatusInfeasible+    , MIP.solObjectiveValue = Just 0.00000000+    , MIP.solVariables = Map.fromList [("x", 0.11111111), ("y", 0), ("z", 0.33333333)]+    }++case_CBCSol_unbounded :: Assertion+case_CBCSol_unbounded = do+  sol <- CBCSol.readFile "samples/lp/test-solution-cbc-unbounded.txt"+  sol @?=+    MIP.Solution+    { MIP.solStatus = MIP.StatusInfeasibleOrUnbounded+    , MIP.solObjectiveValue = Just 0.00000000+    , MIP.solVariables = Map.fromList [("x", 0), ("y", 0)]+    }++case_CPLEXSol :: Assertion+case_CPLEXSol = do+  sol <- CPLEXSol.readFile "samples/lp/test-solution-cplex.sol"+  sol @?=+    MIP.Solution+    { MIP.solStatus = MIP.StatusOptimal+    , MIP.solObjectiveValue = Just 122.5+    , MIP.solVariables = Map.fromList [("x1", 40), ("x2", 10.5), ("x3", 19.5), ("x4", 3)]+    }++case_CPLEXSol_unbounded :: Assertion+case_CPLEXSol_unbounded = do+  sol <- CPLEXSol.readFile "samples/lp/test-solution-cplex-unbounded.sol"+  sol @?=+    MIP.Solution+    { MIP.solStatus = MIP.StatusUnbounded+    , MIP.solObjectiveValue = Just 3.0+    , MIP.solVariables = Map.fromList [("x", 1.0), ("y", 2.0)]+    }++case_GLPKSol :: Assertion+case_GLPKSol = do+  sol <- GLPKSol.readFile "samples/lp/test-solution-glpk.sol"+  sol @?=+    MIP.Solution+    { MIP.solStatus = MIP.StatusOptimal+    , MIP.solObjectiveValue = Just 122.5+    , MIP.solVariables = Map.fromList [("x1", 40), ("x2", 10.5), ("x3", 19.5), ("x4", 3)]+    }++case_GLPKSol_long_var :: Assertion+case_GLPKSol_long_var = do+  sol <- GLPKSol.readFile "samples/lp/test-solution-glpk-long.sol"+  sol @?=+    MIP.Solution+    { MIP.solStatus = MIP.StatusOptimal+    , MIP.solObjectiveValue = Just 122.5+    , MIP.solVariables = Map.fromList [("x1AAAAAAAAAAAAAAAAAAAAAAAAAAAA", 40), ("x2", 10.5), ("x3", 19.5), ("x4", 3)]+    }++case_GurobiSol :: Assertion+case_GurobiSol = do+  sol <- GurobiSol.readFile "samples/lp/test-solution-gurobi.sol"+  isJust (GurobiSol.solObjectiveValue sol) @?= True+  GurobiSol.parse (GurobiSol.render sol) @?= sol++case_SCIPSol :: Assertion+case_SCIPSol = do+  sol <- SCIPSol.readFile "samples/lp/test-solution-scip.sol"+  sol @?=+    MIP.Solution+    { MIP.solStatus = MIP.StatusOptimal+    , MIP.solObjectiveValue = Just 122.5+    , MIP.solVariables = Map.fromList [("x1", 40), ("x2", 10.5), ("x3", 19.5), ("x4", 3)]+    }++mipTestGroup :: TestTree+mipTestGroup = $(testGroupGenerator)
+ test/Test/MIPSolver.hs view
@@ -0,0 +1,301 @@+{-# OPTIONS_GHC -Wall #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE OverloadedStrings #-}+module Test.MIPSolver (mipSolverTestGroup) where++import Control.Monad+import Data.Default.Class+import qualified Data.Map as Map+import Test.Tasty+import Test.Tasty.HUnit+import qualified ToySolver.Data.MIP as MIP+import ToySolver.Data.MIP.Solver++-- ------------------------------------------------------------------------++case_cbc :: Assertion+case_cbc = do+  prob <- MIP.readFile def "samples/lp/test.lp"+  sol <- solve cbc def prob+  sol @?=+    MIP.Solution+    { MIP.solStatus = MIP.StatusOptimal+    , MIP.solObjectiveValue = Just 122.5+    , MIP.solVariables = Map.fromList [("x1", 40), ("x2", 10.5), ("x3", 19.5), ("x4", 3)]+    }++case_cbc_unbounded :: Assertion+case_cbc_unbounded = do+  prob <- MIP.readFile def "samples/lp/unbounded-ip.lp"+  sol <- solve cbc def prob+  let status = MIP.solStatus sol+  unless (status == MIP.StatusUnbounded || status == MIP.StatusFeasible || status == MIP.StatusInfeasibleOrUnbounded) $+    assertFailure $ unlines $+      [ "expected: StatusUnbounded, StatusFeasible or StatusInfeasibleOrUnbounded"+      , " but got: " ++ show status+      ]++case_cbc_infeasible :: Assertion+case_cbc_infeasible = do+  prob <- MIP.readFile def "samples/lp/infeasible.lp"+  sol <- solve cbc def prob+  MIP.solStatus sol @?= MIP.StatusInfeasible++case_cbc_infeasible2 :: Assertion+case_cbc_infeasible2 = do+  prob <- MIP.readFile def "samples/lp/glpk-preprocess-bug.lp"+  sol <- solve cbc def prob+  let status = MIP.solStatus sol+  unless (status == MIP.StatusInfeasible || status == MIP.StatusInfeasibleOrUnbounded) $+    assertFailure $ unlines $+      [ "expected: StatusInfeasible or StatusInfeasibleOrUnbounded"+      , " but got: " ++ show status+      ]++-- ------------------------------------------------------------------------++case_cplex :: Assertion+case_cplex = do+  prob <- MIP.readFile def "samples/lp/test.lp"+  sol <- solve cplex def prob+  sol @?=+    MIP.Solution+    { MIP.solStatus = MIP.StatusOptimal+    , MIP.solObjectiveValue = Just 122.5+    , MIP.solVariables = Map.fromList [("x1", 40), ("x2", 10.5), ("x3", 19.5), ("x4", 3)]+    }++case_cplex_unbounded :: Assertion+case_cplex_unbounded = do+  prob <- MIP.readFile def "samples/lp/unbounded-ip.lp"+  sol <- solve cplex def prob+  let status = MIP.solStatus sol+  unless (status == MIP.StatusUnbounded || status == MIP.StatusFeasible || status == MIP.StatusInfeasibleOrUnbounded) $+    assertFailure $ unlines $+      [ "expected: StatusUnbounded, StatusFeasible or StatusInfeasibleOrUnbounded"+      , " but got: " ++ show status+      ]++case_cplex_infeasible :: Assertion+case_cplex_infeasible = do+  prob <- MIP.readFile def "samples/lp/infeasible.lp"+  sol <- solve cplex def prob+  MIP.solStatus sol @?= MIP.StatusInfeasible++case_cplex_infeasible2 :: Assertion+case_cplex_infeasible2 = do+  prob <- MIP.readFile def "samples/lp/glpk-preprocess-bug.lp"+  sol <- solve cplex def prob+  let status = MIP.solStatus sol+  unless (status == MIP.StatusInfeasible || status == MIP.StatusInfeasibleOrUnbounded) $+    assertFailure $ unlines $+      [ "expected: StatusInfeasible or StatusInfeasibleOrUnbounded"+      , " but got: " ++ show status+      ]++-- ------------------------------------------------------------------------++case_glpsol :: Assertion+case_glpsol = do+  prob <- MIP.readFile def "samples/lp/test.lp"+  sol <- solve glpsol def prob+  sol @?=+    MIP.Solution+    { MIP.solStatus = MIP.StatusOptimal+    , MIP.solObjectiveValue = Just 122.5+    , MIP.solVariables = Map.fromList [("x1", 40), ("x2", 10.5), ("x3", 19.5), ("x4", 3)]+    }++case_glpsol_unbounded :: Assertion+case_glpsol_unbounded = do+  prob <- MIP.readFile def "samples/lp/unbounded-ip.lp"+  sol <- solve glpsol def prob+  let status = MIP.solStatus sol+  unless (status == MIP.StatusUnbounded || status == MIP.StatusFeasible || status == MIP.StatusInfeasibleOrUnbounded) $+    assertFailure $ unlines $+      [ "expected: StatusUnbounded, StatusFeasible or StatusInfeasibleOrUnbounded"+      , " but got: " ++ show status+      ]++case_glpsol_infeasible :: Assertion+case_glpsol_infeasible = do+  prob <- MIP.readFile def "samples/lp/infeasible.lp"+  sol <- solve glpsol def prob+  MIP.solStatus sol @?= MIP.StatusInfeasible++-- ------------------------------------------------------------------------++case_gurobiCl :: Assertion+case_gurobiCl = do+  prob <- MIP.readFile def "samples/lp/test.lp"+  sol <- solve gurobiCl def prob+  sol @?=+    MIP.Solution+    { MIP.solStatus = MIP.StatusOptimal+    , MIP.solObjectiveValue = Just 122.50000000000006+    , MIP.solVariables = Map.fromList [("x1", 40), ("x2", 10.5), ("x3", 19.500000000000018), ("x4", 3)]+    }++case_gurobiCl_unbounded :: Assertion+case_gurobiCl_unbounded = do+  prob <- MIP.readFile def "samples/lp/unbounded-ip.lp"+  sol <- solve gurobiCl def prob+  let status = MIP.solStatus sol+  unless (status == MIP.StatusUnbounded || status == MIP.StatusFeasible || status == MIP.StatusInfeasibleOrUnbounded) $+    assertFailure $ unlines $+      [ "expected: StatusUnbounded, StatusFeasible or StatusInfeasibleOrUnbounded"+      , " but got: " ++ show status+      ]++case_gurobiCl_infeasible :: Assertion+case_gurobiCl_infeasible = do+  prob <- MIP.readFile def "samples/lp/infeasible.lp"+  sol <- solve gurobiCl def prob+  MIP.solStatus sol @?= MIP.StatusInfeasible++case_gurobiCl_infeasible2 :: Assertion+case_gurobiCl_infeasible2 = do+  prob <- MIP.readFile def "samples/lp/glpk-preprocess-bug.lp"+  sol <- solve gurobiCl def prob+  let status = MIP.solStatus sol+  unless (status == MIP.StatusInfeasible || status == MIP.StatusInfeasibleOrUnbounded) $+    assertFailure $ unlines $+      [ "expected: StatusInfeasible or StatusInfeasibleOrUnbounded"+      , " but got: " ++ show status+      ]++-- ------------------------------------------------------------------------++case_lpSolve :: Assertion+case_lpSolve = do+  prob <- MIP.readFile def "samples/lp/test.lp"+  sol <- solve lpSolve def prob+  sol @?=+    MIP.Solution+    { MIP.solStatus = MIP.StatusOptimal+    , MIP.solObjectiveValue = Just 122.5+    , MIP.solVariables = Map.fromList [("x1", 40), ("x2", 10.5), ("x3", 19.5), ("x4", 3)]+    }++case_lpSolve_unbounded :: Assertion+case_lpSolve_unbounded = do+  prob <- MIP.readFile def "samples/lp/unbounded-ip.lp"+  sol <- solve lpSolve def prob+  let status = MIP.solStatus sol+  unless (status == MIP.StatusUnbounded || status == MIP.StatusFeasible || status == MIP.StatusInfeasibleOrUnbounded) $+    assertFailure $ unlines $+      [ "expected: StatusUnbounded, StatusFeasible or StatusInfeasibleOrUnbounded"+      , " but got: " ++ show status+      ]++case_lpSolve_infeasible :: Assertion+case_lpSolve_infeasible = do+  prob <- MIP.readFile def "samples/lp/infeasible.lp"+  sol <- solve lpSolve def prob+  MIP.solStatus sol @?= MIP.StatusInfeasible++case_lpSolve_infeasible2 :: Assertion+case_lpSolve_infeasible2 = do+  prob <- MIP.readFile def "samples/lp/glpk-preprocess-bug.lp"+  sol <- solve lpSolve def prob+  let status = MIP.solStatus sol+  unless (status == MIP.StatusInfeasible || status == MIP.StatusInfeasibleOrUnbounded) $+    assertFailure $ unlines $+      [ "expected: StatusInfeasible or StatusInfeasibleOrUnbounded"+      , " but got: " ++ show status+      ]++-- ------------------------------------------------------------------------++case_scip :: Assertion+case_scip = do+  prob <- MIP.readFile def "samples/lp/test.lp"+  sol <- solve scip def prob+  sol @?=+    MIP.Solution+    { MIP.solStatus = MIP.StatusOptimal+    , MIP.solObjectiveValue = Just 122.5+    , MIP.solVariables = Map.fromList [("x1", 40), ("x2", 10.5), ("x3", 19.5), ("x4", 3)]+    }++case_scip_unbounded :: Assertion+case_scip_unbounded = do+  prob <- MIP.readFile def "samples/lp/unbounded-ip.lp"+  sol <- solve scip def prob+  let status = MIP.solStatus sol+  unless (status == MIP.StatusUnbounded || status == MIP.StatusFeasible || status == MIP.StatusInfeasibleOrUnbounded) $+    assertFailure $ unlines $+      [ "expected: StatusUnbounded, StatusFeasible or StatusInfeasibleOrUnbounded"+      , " but got: " ++ show status+      ]++case_scip_infeasible :: Assertion+case_scip_infeasible = do+  prob <- MIP.readFile def "samples/lp/infeasible.lp"+  sol <- solve scip def prob+  MIP.solStatus sol @?= MIP.StatusInfeasible++case_scip_infeasible2 :: Assertion+case_scip_infeasible2 = do+  prob <- MIP.readFile def "samples/lp/glpk-preprocess-bug.lp"+  sol <- solve scip def prob+  let status = MIP.solStatus sol+  unless (status == MIP.StatusInfeasible || status == MIP.StatusInfeasibleOrUnbounded) $+    assertFailure $ unlines $+      [ "expected: StatusInfeasible or StatusInfeasibleOrUnbounded"+      , " but got: " ++ show status+      ]++-- ------------------------------------------------------------------------++mipSolverTestGroup :: TestTree+mipSolverTestGroup = testGroup "Test.MIPSolver" $ []+#ifdef TEST_CBC+  +++  [ testCase "cbc" case_cbc+  , testCase "cbc unbounded" case_cbc_unbounded+  , testCase "cbc infeasible" case_cbc_infeasible+  , testCase "cbc infeasible2" case_cbc_infeasible2+  ]+#endif+#ifdef TEST_CPLEX+  +++  [ testCase "cplex" case_cplex+  , testCase "cplex unbounded" case_cplex_unbounded+  , testCase "cplex infeasible" case_cplex_infeasible+  , testCase "cplex infeasible2" case_cplex_infeasible2+  ]+#endif+#ifdef TEST_GLPSOL+  +++  [ testCase "glpsol" case_glpsol+  , testCase "glpsol unbounded" case_glpsol_unbounded+  , testCase "glpsol infeasible" case_glpsol_infeasible+  ]+#endif+#ifdef TEST_GUROBI_CL+  +++  [ testCase "gurobiCl" case_gurobiCl+  , testCase "gurobiCl unbounded" case_gurobiCl_unbounded+  , testCase "gurobiCl infeasible" case_gurobiCl_infeasible+  , testCase "gurobiCl infeasible2" case_gurobiCl_infeasible2+  ]+#endif+#ifdef TEST_LP_SOLVE+  +++  [ testCase "lpSolve" case_lpSolve+  , testCase "lpSolve unbounded" case_lpSolve_unbounded+  , testCase "lpSolve infeasible" case_lpSolve_infeasible+  , testCase "lpSolve infeasible2" case_lpSolve_infeasible2+  ]+#endif+#ifdef TEST_SCIP+  +++  [ testCase "scip" case_scip+  , testCase "scip unbounded" case_scip_unbounded+  , testCase "scip infeasible" case_scip_infeasible+  , testCase "scip infeasible2" case_scip_infeasible2+  ]+#endif+
test/Test/MIPSolver2.hs view
@@ -13,9 +13,9 @@ import Text.Printf  import qualified ToySolver.Data.LA as LA-import qualified ToySolver.Arith.Simplex2 as Simplex2-import ToySolver.Arith.Simplex2-import qualified ToySolver.Arith.MIPSolver2 as MIPSolver2+import qualified ToySolver.Arith.Simplex as Simplex+import ToySolver.Arith.Simplex+import qualified ToySolver.Arith.MIP as MIPSolver  ------------------------------------------------------------------------ @@ -43,40 +43,40 @@  case_test1 = do   let (optdir, obj, cs, ivs) = example1-  lp <- Simplex2.newSolver-  replicateM 5 (Simplex2.newVar lp)+  lp <- Simplex.newSolver+  replicateM 5 (Simplex.newVar lp)   setOptDir lp optdir   setObj lp obj-  mapM_ (Simplex2.assertAtom lp) cs-  mip <- MIPSolver2.newSolver lp ivs-  ret <- MIPSolver2.optimize mip+  mapM_ (Simplex.assertAtom lp) cs+  mip <- MIPSolver.newSolver lp ivs+  ret <- MIPSolver.optimize mip   -  ret @?= Simplex2.Optimum+  ret @?= Simplex.Optimum -  Just m <- MIPSolver2.getBestModel mip+  Just m <- MIPSolver.getBestModel mip   forM_ [(1,40),(2,21/2),(3,39/2),(4,3)] $ \(var, val) ->     m IM.! var @?= val -  Just v <- MIPSolver2.getBestValue mip+  Just v <- MIPSolver.getBestValue mip   v @?= 245/2  case_test1' = do   let (optdir, obj, cs, ivs) = example1-  lp <- Simplex2.newSolver-  replicateM 5 (Simplex2.newVar lp)+  lp <- Simplex.newSolver+  replicateM 5 (Simplex.newVar lp)   setOptDir lp (f optdir)   setObj lp (negateV obj)-  mapM_ (Simplex2.assertAtom lp) cs-  mip <- MIPSolver2.newSolver lp ivs-  ret <- MIPSolver2.optimize mip+  mapM_ (Simplex.assertAtom lp) cs+  mip <- MIPSolver.newSolver lp ivs+  ret <- MIPSolver.optimize mip   -  ret @?= Simplex2.Optimum+  ret @?= Simplex.Optimum -  Just m <- MIPSolver2.getBestModel mip+  Just m <- MIPSolver.getBestModel mip   forM_ [(1,40),(2,21/2),(3,39/2),(4,3)] $ \(var, val) ->     m IM.! var @?= val -  Just v <- MIPSolver2.getBestValue mip+  Just v <- MIPSolver.getBestValue mip   v @?= -245/2    where@@ -101,21 +101,21 @@  case_test2 = do   let (optdir, obj, cs, ivs) = example2-  lp <- Simplex2.newSolver-  replicateM 4 (Simplex2.newVar lp)+  lp <- Simplex.newSolver+  replicateM 4 (Simplex.newVar lp)   setOptDir lp optdir   setObj lp obj-  mapM_ (Simplex2.assertAtom lp) cs-  mip <- MIPSolver2.newSolver lp ivs-  ret <- MIPSolver2.optimize mip+  mapM_ (Simplex.assertAtom lp) cs+  mip <- MIPSolver.newSolver lp ivs+  ret <- MIPSolver.optimize mip   -  ret @?= Simplex2.Optimum+  ret @?= Simplex.Optimum -  Just m <- MIPSolver2.getBestModel mip+  Just m <- MIPSolver.getBestModel mip   forM_ [(1,0),(2,2),(3,5/2)] $ \(var, val) ->     m IM.! var @?= val -  Just v <- MIPSolver2.getBestValue mip+  Just v <- MIPSolver.getBestValue mip   v @?= -37/2  ------------------------------------------------------------------------
test/Test/MPSFile.hs view
@@ -2,6 +2,7 @@ module Test.MPSFile (mpsTestGroup) where  import Control.Monad+import Data.Default.Class import Data.List import Data.Maybe import Test.Tasty@@ -50,14 +51,12 @@  checkFile :: FilePath -> Assertion checkFile fname = do-  r <- parseFile fname-  case r of-    Left err -> assertFailure (show err)-    Right lp -> return ()+  _ <- parseFile def fname+  return ()  checkString :: String -> String -> Assertion checkString name str = do-  case parseString name str of+  case parseString def name str of     Left err -> assertFailure (show err)     Right lp -> return () 
+ test/Test/QBF.hs view
@@ -0,0 +1,145 @@+{-# OPTIONS_GHC -Wall -fno-warn-orphans #-}+{-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-}+module Test.QBF (qbfTestGroup) where++import Control.Applicative((<$>))+import Control.Monad+import qualified Data.IntSet as IntSet+import Data.IntMap (IntMap)+import qualified Data.IntMap as IntMap+import Data.Maybe (catMaybes)++import Test.Tasty+import Test.Tasty.QuickCheck hiding ((.&&.), (.||.))+import Test.Tasty.TH+import qualified Test.QuickCheck.Monadic as QM++import ToySolver.Data.Boolean+import qualified ToySolver.Data.BoolExpr as BoolExpr+import qualified ToySolver.QBF as QBF++-- -------------------------------------------------------------------++prop_solveCEGAR :: Property+prop_solveCEGAR = QM.monadicIO $ do+  (nv, prefix@(_ : prefix'), matrix) <- QM.pick arbitrarySmallQBF+  (sat, cert) <- QM.run $ QBF.solveCEGAR nv prefix matrix+  QM.assert $ sat == evalQBFNaive prefix matrix+  case cert of+    Nothing -> return ()+    Just ls ->+      QM.assert $ sat == evalQBFNaive' (IntMap.fromList [(abs lit, lit > 0) | lit <- IntSet.toList ls]) prefix' matrix++prop_solveCEGARIncremental :: Property+prop_solveCEGARIncremental = QM.monadicIO $ do+  (nv, prefix@(_ : prefix'), matrix) <- QM.pick arbitrarySmallQBF+  (sat, cert) <- QM.run $ QBF.solveCEGARIncremental nv prefix matrix+  QM.assert $ sat == evalQBFNaive prefix matrix+  case cert of+    Nothing -> return ()+    Just ls ->+      QM.assert $ sat == evalQBFNaive' (IntMap.fromList [(abs lit, lit > 0) | lit <- IntSet.toList ls]) prefix' matrix+++{-+If the innermost quantifier is a universal quantifier,+we can remove the bound variable v from the clauses that+do not contain v and ¬v simultaneously.+-}+prop_eliminate_last_universal_quantifier :: Property+prop_eliminate_last_universal_quantifier = QM.monadicIO $ do+  (nv, prefix, matrix1) <- QM.pick gen+  let (QBF.A, xs) = last prefix+      matrix2 = [[lit | lit <- clause, abs lit `IntSet.notMember` xs] | clause <- matrix1]+      matrix1' = andB [orB [f lit | lit <- clause] | clause <- matrix1]+      matrix2' = andB [orB [f lit | lit <- clause] | clause <- matrix2]+      f lit = if lit > 0+              then BoolExpr.Atom lit+              else notB (BoolExpr.Atom (abs lit))+  (sat1, cert1) <- QM.run $ QBF.solveCEGAR nv prefix matrix1'+  (sat2, cert2) <- QM.run $ QBF.solveCEGAR nv (init prefix) matrix2'+  QM.assert $ sat1 == sat2+  where+    gen :: Gen (Int, QBF.Prefix, [[Int]])+    gen = do+      nv <- choose (0,10)+      nc <- choose (0,50)+      let vs = [1..nv]+      q1 <- arbitrary+      q2 <- arbitrary+      vs1 <- IntSet.fromList <$> subsetof vs+      vs2 <- IntSet.fromList <$> subsetof vs    +      matrix <- replicateM nc $ do+        if nv == 0 then+          return []+        else do+          mapM (\v -> elements [v, -v]) =<< subsetof vs+      return+        ( nv+        , [(q1,vs1), (q2, vs2 IntSet.\\ vs1), (QBF.A, IntSet.fromList vs IntSet.\\ (vs1 `IntSet.union` vs2))]+        , matrix+        )++-- -------------------------------------------------------------------++evalQBFNaive :: QBF.Prefix -> QBF.Matrix -> Bool+evalQBFNaive prefix = evalQBFNaive' IntMap.empty prefix++evalQBFNaive' :: IntMap Bool -> QBF.Prefix -> QBF.Matrix -> Bool+evalQBFNaive' env prefix = f env [(q,v) | (q,vs) <- prefix, v <- IntSet.toList vs]+  where+    f env [] matrix = BoolExpr.fold (env IntMap.!) matrix+    f env ((QBF.A,x) : prefix) matrix =+      f (IntMap.insert x True  env) prefix matrix &&+      f (IntMap.insert x False env) prefix matrix+    f env ((QBF.E,x) : prefix) matrix =+      f (IntMap.insert x True  env) prefix matrix ||+      f (IntMap.insert x False env) prefix matrix++-- -------------------------------------------------------------------++subsetof :: [a] -> Gen [a]+subsetof xs = catMaybes <$> sequence [elements [Just x, Nothing] | x <- xs]++arbitrarySmallQBF :: Gen (Int, QBF.Prefix, QBF.Matrix)+arbitrarySmallQBF = do+  (nv, prefix, matrix') <- arbitrarySmallQBF'+  let f lit = if lit > 0+              then BoolExpr.Atom lit+              else notB (BoolExpr.Atom (abs lit))+      matrix = andB [orB [f lit | lit <- clause] | clause <- matrix']+  return (nv, prefix, matrix)++arbitrarySmallQBF' :: Gen (Int, QBF.Prefix, [[Int]])+arbitrarySmallQBF' = do+  nv <- choose (0,10)+  nc <- choose (0,50)++  let vs = [1..nv]+  q1 <- arbitrary+  q2 <- arbitrary+  q3 <- arbitrary+  vs1 <- IntSet.fromList <$> subsetof vs+  vs2 <- IntSet.fromList <$> subsetof vs++  matrix <- replicateM nc $ do+    len <- choose (0,10)+    if nv == 0 then+      return []+    else+      replicateM len $ choose (-nv, nv) `suchThat` (/= 0)+  +  return+    ( nv+    , [(q1,vs1), (q2, vs2 IntSet.\\ vs1), (q3, IntSet.fromList vs IntSet.\\ (vs1 `IntSet.union` vs2))]+    , matrix+    )++instance Arbitrary QBF.Quantifier where+  arbitrary = arbitraryBoundedEnum++-- -------------------------------------------------------------------+-- Test harness++qbfTestGroup :: TestTree+qbfTestGroup = $(testGroupGenerator)
test/Test/SAT.hs view
@@ -1,13 +1,16 @@-{-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE TemplateHaskell, ScopedTypeVariables, FlexibleContexts #-} module Test.SAT (satTestGroup) where  import Control.Monad import Data.Array.IArray import Data.Default.Class+import qualified Data.Foldable as F import Data.IORef import Data.List import Data.Map (Map) import qualified Data.Map as Map+import Data.Maybe import Data.Set (Set) import qualified Data.Set as Set import Data.IntMap (IntMap)@@ -30,17 +33,27 @@ import qualified ToySolver.SAT as SAT import qualified ToySolver.SAT.Types as SAT import ToySolver.SAT.TheorySolver-import qualified ToySolver.SAT.TseitinEncoder as Tseitin+import qualified ToySolver.SAT.Encoder.Tseitin as Tseitin+import qualified ToySolver.SAT.Encoder.PB as PB+import qualified ToySolver.SAT.Encoder.PB.Internal.Sorter as PBEncSorter+import qualified ToySolver.SAT.Encoder.PBNLC as PBNLC import qualified ToySolver.SAT.MUS as MUS-import qualified ToySolver.SAT.MUS.QuickXplain as QuickXplain-import qualified ToySolver.SAT.MUS.CAMUS as CAMUS-import qualified ToySolver.SAT.MUS.DAA as DAA+import qualified ToySolver.SAT.MUS.Enum as MUSEnum import qualified ToySolver.SAT.PBO as PBO-import qualified ToySolver.SAT.PBNLC as PBNLC+import qualified ToySolver.SAT.Store.CNF as CNFStore+import qualified ToySolver.SAT.ExistentialQuantification as ExistentialQuantification +import qualified Data.PseudoBoolean as PBFile+import qualified ToySolver.Converter.PB2SAT as PB2SAT+import qualified ToySolver.Converter.WBO2MaxSAT as WBO2MaxSAT+import qualified ToySolver.Converter.WBO2PB as WBO2PB+import qualified ToySolver.Converter.SAT2KSAT as SAT2KSAT+import qualified ToySolver.Text.CNF as CNF+import qualified ToySolver.Text.MaxSAT as MaxSAT+ import ToySolver.Data.OrdRel import qualified ToySolver.Data.LA as LA-import qualified ToySolver.Arith.Simplex2 as Simplex2+import qualified ToySolver.Arith.Simplex as Simplex import qualified ToySolver.EUF.EUFSolver as EUF  allAssignments :: Int -> [SAT.Model]@@ -48,19 +61,19 @@  prop_solveCNF :: Property prop_solveCNF = QM.monadicIO $ do-  cnf@(nv,_) <- QM.pick arbitraryCNF+  cnf <- QM.pick arbitraryCNF   solver <- arbitrarySolver   ret <- QM.run $ solveCNF solver cnf   case ret of     Just m -> QM.assert $ evalCNF m cnf     Nothing -> do-      forM_ (allAssignments nv) $ \m -> do+      forM_ (allAssignments (CNF.numVars cnf)) $ \m -> do         QM.assert $ not (evalCNF m cnf) -solveCNF :: SAT.Solver -> (Int,[SAT.Clause]) -> IO (Maybe SAT.Model)-solveCNF solver (nv,cs) = do-  SAT.newVars_ solver nv-  forM_ cs $ \c -> SAT.addClause solver c+solveCNF :: SAT.Solver -> CNF.CNF -> IO (Maybe SAT.Model)+solveCNF solver cnf = do+  SAT.newVars_ solver (CNF.numVars cnf)+  forM_ (CNF.clauses cnf) $ \c -> SAT.addClause solver c   ret <- SAT.solve solver   if ret then do     m <- SAT.getModel solver@@ -68,7 +81,7 @@   else do     return Nothing -arbitraryCNF :: Gen (Int,[SAT.Clause])+arbitraryCNF :: Gen CNF.CNF arbitraryCNF = do   nv <- choose (0,10)   nc <- choose (0,50)@@ -78,10 +91,15 @@       return []     else       replicateM len $ choose (-nv, nv) `suchThat` (/= 0)-  return (nv, cs)+  return $+    CNF.CNF+    { CNF.numVars = nv+    , CNF.numClauses = nc+    , CNF.clauses = cs+    } -evalCNF :: SAT.Model -> (Int,[SAT.Clause]) -> Bool-evalCNF m (_,cs) = all (SAT.evalClause m) cs+evalCNF :: SAT.Model -> CNF.CNF -> Bool+evalCNF m cnf = all (SAT.evalClause m) (CNF.clauses cnf)   prop_solvePB :: Property@@ -173,7 +191,60 @@   PBO.optimize opt   PBO.getBestSolution opt +evalWBO :: SAT.Model -> (Int, [(Maybe Integer, (PBRel,SAT.PBLinSum,Integer))], Maybe Integer) -> Maybe Integer+evalWBO m (nv,cs,top) = do+  cost <- liftM sum $ forM cs $ \(w,(o,lhs,rhs)) -> do+    if evalPBRel o (SAT.evalPBLinSum m lhs) rhs then+      return 0+    else+      w+  case top of+    Just t -> guard (cost < t)+    Nothing -> return ()+  return cost +arbitraryWBO :: Gen (Int, [(Maybe Integer, (PBRel,SAT.PBLinSum,Integer))], Maybe Integer)+arbitraryWBO = do+  (nv,cs) <- arbitraryPB+  cs2 <- forM cs $ \c -> do+    b <- arbitrary+    cost <- if b then return Nothing+            else liftM (Just . (1+) . abs) arbitrary+    return (cost, c)+  b <- arbitrary+  top <- if b then return Nothing+         else liftM (Just . (1+) . abs) arbitrary+  return (nv,cs2,top)++optimizeWBO+  :: SAT.Solver+  -> PBO.Method+  -> (Int, [(Maybe Integer, (PBRel,SAT.PBLinSum,Integer))], Maybe Integer)+  -> IO (Maybe (SAT.Model, Integer))+optimizeWBO solver method (nv,cs,top) = do+  SAT.newVars_ solver nv+  obj <- liftM catMaybes $ forM cs $ \(cost, (o,lhs,rhs)) -> do+    case cost of+      Nothing -> do+        case o of+          PBRelGE -> SAT.addPBAtLeast solver lhs rhs+          PBRelLE -> SAT.addPBAtMost solver lhs rhs+          PBRelEQ -> SAT.addPBExactly solver lhs rhs+        return Nothing+      Just w -> do+        sel <- SAT.newVar solver+        case o of+          PBRelGE -> SAT.addPBAtLeastSoft solver sel lhs rhs+          PBRelLE -> SAT.addPBAtMostSoft solver sel lhs rhs+          PBRelEQ -> SAT.addPBExactlySoft solver sel lhs rhs+        return $ Just (w,-sel)+  case top of+    Nothing -> return ()+    Just c -> SAT.addPBAtMost solver obj (c-1)+  opt <- PBO.newOptimizer solver obj+  PBO.optimize opt+  liftM (fmap (\(m, val) -> (SAT.restrictModel nv m, val))) $ PBO.getBestSolution opt+ prop_solvePBNLC :: Property prop_solvePBNLC = QM.monadicIO $ do   prob@(nv,_) <- QM.pick arbitraryPBNLC@@ -185,23 +256,42 @@       forM_ (allAssignments nv) $ \m -> do         QM.assert $ not (evalPBNLC m prob) -solvePBNLC :: SAT.Solver -> (Int,[(PBRel,PBNLC.PBSum,Integer)]) -> IO (Maybe SAT.Model)+solvePBNLC :: SAT.Solver -> (Int,[(PBRel,SAT.PBSum,Integer)]) -> IO (Maybe SAT.Model) solvePBNLC solver (nv,cs) = do   SAT.newVars_ solver nv-  enc <- Tseitin.newEncoder solver+  enc <- PBNLC.newEncoder solver =<< Tseitin.newEncoder solver   forM_ cs $ \(o,lhs,rhs) -> do     case o of-      PBRelGE -> PBNLC.addPBAtLeast enc lhs rhs-      PBRelLE -> PBNLC.addPBAtMost enc lhs rhs-      PBRelEQ -> PBNLC.addPBExactly enc lhs rhs+      PBRelGE -> PBNLC.addPBNLAtLeast enc lhs rhs+      PBRelLE -> PBNLC.addPBNLAtMost enc lhs rhs+      PBRelEQ -> PBNLC.addPBNLExactly enc lhs rhs   ret <- SAT.solve solver   if ret then do     m <- SAT.getModel solver-    return (Just m)+    return $ Just $ SAT.restrictModel nv m   else do     return Nothing -arbitraryPBNLC :: Gen (Int,[(PBRel,PBNLC.PBSum,Integer)])+optimizePBNLC+  :: SAT.Solver+  -> PBO.Method+  -> (Int, SAT.PBSum, [(PBRel,SAT.PBSum,Integer)])+  -> IO (Maybe (SAT.Model, Integer))+optimizePBNLC solver method (nv,obj,cs) = do+  SAT.newVars_ solver nv+  enc <- PBNLC.newEncoder solver =<< Tseitin.newEncoder solver+  forM_ cs $ \(o,lhs,rhs) -> do+    case o of+      PBRelGE -> PBNLC.addPBNLAtLeast enc lhs rhs+      PBRelLE -> PBNLC.addPBNLAtMost enc lhs rhs+      PBRelEQ -> PBNLC.addPBNLExactly enc lhs rhs+  obj2 <- PBNLC.linearizePBSumWithPolarity enc Tseitin.polarityNeg obj+  opt <- PBO.newOptimizer2 solver obj2 (\m -> SAT.evalPBSum m obj)+  PBO.setMethod opt method+  PBO.optimize opt+  liftM (fmap (\(m, val) -> (SAT.restrictModel nv m, val))) $ PBO.getBestSolution opt++arbitraryPBNLC :: Gen (Int,[(PBRel,SAT.PBSum,Integer)]) arbitraryPBNLC = do   nv <- choose (0,10)   nc <- choose (0,50)@@ -220,8 +310,8 @@     return $ (rel,lhs,rhs)   return (nv, cs) -evalPBNLC :: SAT.Model -> (Int,[(PBRel,PBNLC.PBSum,Integer)]) -> Bool-evalPBNLC m (_,cs) = all (\(o,lhs,rhs) -> evalPBRel o (PBNLC.evalPBSum m lhs) rhs) cs+evalPBNLC :: SAT.Model -> (Int,[(PBRel,SAT.PBSum,Integer)]) -> Bool+evalPBNLC m (_,cs) = all (\(o,lhs,rhs) -> evalPBRel o (SAT.evalPBSum m lhs) rhs) cs   prop_solveXOR :: Property@@ -266,8 +356,10 @@ evalXOR m (_,cs) = all (SAT.evalXORClause m) cs  -newTheorySolver :: (Int, [SAT.Clause]) -> IO TheorySolver-newTheorySolver cnf@(nv,cs) = do+newTheorySolver :: CNF.CNF -> IO TheorySolver+newTheorySolver cnf = do+  let nv = CNF.numVars cnf+      cs = CNF.clauses cnf   solver <- SAT.newSolver   SAT.newVars_ solver nv   forM_ cs $ \c -> SAT.addClause solver c@@ -299,9 +391,12 @@  prop_solveCNF_using_BooleanTheory :: Property prop_solveCNF_using_BooleanTheory = QM.monadicIO $ do-  cnf@(nv,cs) <- QM.pick arbitraryCNF-  let cnf1 = (nv, [c | (i,c) <- zip [0..] cs, i `mod` 2 == 0])-      cnf2 = (nv, [c | (i,c) <- zip [0..] cs, i `mod` 2 /= 0])+  cnf <- QM.pick arbitraryCNF+  let nv = CNF.numVars cnf+      nc = CNF.numClauses cnf+      cs = CNF.clauses cnf+      cnf1 = cnf{ CNF.clauses = [c | (i,c) <- zip [0..] cs, i `mod` 2 == 0], CNF.numClauses = nc - (nc `div` 2) }+      cnf2 = cnf{ CNF.clauses = [c | (i,c) <- zip [0..] cs, i `mod` 2 /= 0], CNF.numClauses = nc `div` 2 }    solver <- arbitrarySolver @@ -311,7 +406,7 @@     tsolver <- newTheorySolver cnf1     SAT.setTheory solver tsolver -    forM_ (snd cnf2) $ \c -> SAT.addClause solver c+    forM_ (CNF.clauses cnf2) $ \c -> SAT.addClause solver c     ret <- SAT.solve solver     if ret then do       m <- SAT.getModel solver@@ -328,13 +423,13 @@ case_QF_LRA :: Assertion case_QF_LRA = do   satSolver <- SAT.newSolver-  lraSolver <- Simplex2.newSolver+  lraSolver <- Simplex.newSolver    tblRef <- newIORef $ Map.empty   defsRef <- newIORef $ IntMap.empty   let abstractLAAtom :: LA.Atom Rational -> IO SAT.Lit       abstractLAAtom atom = do-        (v,op,rhs) <- Simplex2.simplifyAtom lraSolver atom+        (v,op,rhs) <- Simplex.simplifyAtom lraSolver atom         tbl <- readIORef tblRef         (vLt, vEq, vGt) <-           case Map.lookup (v,rhs) tbl of@@ -378,18 +473,18 @@             case IntMap.lookup l defs of               Nothing -> return True               Just atom -> do-                Simplex2.assertAtomEx' lraSolver atom (Just l)+                Simplex.assertAtomEx' lraSolver atom (Just l)                 return True         , thCheck = \_ -> do-            Simplex2.check lraSolver+            Simplex.check lraSolver         , thExplain = \m -> do             case m of-              Nothing -> liftM IntSet.toList $ Simplex2.explain lraSolver+              Nothing -> liftM IntSet.toList $ Simplex.explain lraSolver               Just _ -> return []         , thPushBacktrackPoint = do-            Simplex2.pushBacktrackPoint lraSolver+            Simplex.pushBacktrackPoint lraSolver         , thPopBacktrackPoint = do-            Simplex2.popBacktrackPoint lraSolver+            Simplex.popBacktrackPoint lraSolver         , thConstructModel = do             return ()         }@@ -400,8 +495,8 @@       addFormula c = Tseitin.addFormula enc =<< abstract c    a <- SAT.newVar satSolver-  x <- Simplex2.newVar lraSolver-  y <- Simplex2.newVar lraSolver+  x <- Simplex.newVar lraSolver+  y <- Simplex.newVar lraSolver    let le1 = LA.fromTerms [(2,x), (1/3,y)] .<=. LA.constant (-4) -- 2 x + (1/3) y <= -4       eq2 = LA.fromTerms [(1.5,x)] .==. LA.fromTerms [(-2,x)] -- 1.5 y = -2 x@@ -419,10 +514,10 @@   ret @?= True    m1 <- SAT.getModel satSolver-  m2 <- Simplex2.getModel lraSolver+  m2 <- Simplex.getModel lraSolver   defs <- readIORef defsRef   let f (Left lit) = SAT.evalLit m1 lit-      f (Right atom) = LA.evalAtom m2 atom+      f (Right atom) = LA.eval m2 atom   fold f c1 @?= True   fold f c2 @?= True @@ -883,12 +978,12 @@  prop_getAssumptionsImplications :: Property prop_getAssumptionsImplications = QM.monadicIO $ do-  cnf@(nv,cs) <- QM.pick arbitraryCNF+  cnf <- QM.pick arbitraryCNF   solver <- arbitrarySolver-  ls <- QM.pick $ liftM concat $ mapM (\v -> elements [[],[-v],[v]]) [1..nv]+  ls <- QM.pick $ liftM concat $ mapM (\v -> elements [[],[-v],[v]]) [1..CNF.numVars cnf]   ret <- QM.run $ do-    SAT.newVars_ solver nv-    forM_ cs $ \c -> SAT.addClause solver c+    SAT.newVars_ solver (CNF.numVars cnf)+    forM_ (CNF.clauses cnf) $ \c -> SAT.addClause solver c     SAT.solveWith solver ls   when ret $ do     xs <- QM.run $ SAT.getAssumptionsImplications solver@@ -1279,33 +1374,49 @@       g m = (not x1 || (x3 && x4)) || (not x2 || (x3 && x5))         where           [x1,x2,x3,x4,x5] = elems m-  let ms :: [SAT.Model]-      ms = liftM (array (1,5)) $ sequence [[(x,val) | val <- [False,True]] | x <- xs]-  forM_ ms $ \m -> do+  forM_ (allAssignments 5) $ \m -> do     Tseitin.evalFormula m f @?= g m -------------------------------------------------------------------------+prop_PBEncoder_addPBAtLeast = QM.monadicIO $ do+  let nv = 4+  (lhs,rhs) <- QM.pick $ do+    lhs <- arbitraryPBLinSum nv+    rhs <- arbitrary+    return $ SAT.normalizePBLinAtLeast (lhs, rhs)+  strategy <- QM.pick arbitrary+  (cnf,defs) <- QM.run $ do+    db <- CNFStore.newCNFStore+    SAT.newVars_ db nv+    tseitin <- Tseitin.newEncoder db+    pb <- PB.newEncoderWithStrategy tseitin strategy+    SAT.addPBAtLeast pb lhs rhs+    cnf <- CNFStore.getCNFFormula db+    defs <- Tseitin.getDefinitions tseitin+    return (cnf, defs)+  forM_ (allAssignments 4) $ \m -> do+    let m2 :: Array SAT.Var Bool+        m2 = array (1, CNF.numVars cnf) $ assocs m ++ [(v, Tseitin.evalFormula m2 phi) | (v,phi) <- defs]+        b1 = SAT.evalPBLinAtLeast m (lhs,rhs)+        b2 = evalCNF (array (bounds m2) (assocs m2)) cnf+    QM.assert $ b1 == b2 -case_MUS = do-  solver <- SAT.newSolver-  [x1,x2,x3] <- SAT.newVars solver 3-  sels@[y1,y2,y3,y4,y5,y6] <- SAT.newVars solver 6-  SAT.addClause solver [-y1, x1]-  SAT.addClause solver [-y2, -x1]-  SAT.addClause solver [-y3, -x1, x2]-  SAT.addClause solver [-y4, -x2]-  SAT.addClause solver [-y5, -x1, x3]-  SAT.addClause solver [-y6, -x3]+prop_PBEncoder_Sorter_genSorter :: [Int] -> Bool+prop_PBEncoder_Sorter_genSorter xs =+  V.toList (PBEncSorter.sortVector (V.fromList xs)) == sort xs -  ret <- SAT.solveWith solver sels-  ret @?= False+prop_PBEncoder_Sorter_decode_encode :: Property+prop_PBEncoder_Sorter_decode_encode =+  forAll arbitrary $ \base' ->+    forAll arbitrary $ \(NonNegative x) ->+      let base = [b | Positive b <- base']+      in PBEncSorter.isRepresentable base x+         ==>+         (PBEncSorter.decode base . PBEncSorter.encode base) x == x -  actual <- MUS.findMUSAssumptions solver def-  let actual'  = IntSet.map (\x -> x-3) actual-      expected = map IntSet.fromList [[1, 2], [1, 3, 4], [1, 5, 6]]-  actual' `elem` expected @?= True+------------------------------------------------------------------------ -case_MUS_QuickXplain = do+findMUSAssumptions_case1 :: MUS.Method -> IO ()+findMUSAssumptions_case1 method = do   solver <- SAT.newSolver   [x1,x2,x3] <- SAT.newVars solver 3   sels@[y1,y2,y3,y4,y5,y6] <- SAT.newVars solver 6@@ -1319,11 +1430,15 @@   ret <- SAT.solveWith solver sels   ret @?= False -  actual <- QuickXplain.findMUSAssumptions solver def+  actual <- MUS.findMUSAssumptions solver def{ MUS.optMethod = method }   let actual'  = IntSet.map (\x -> x-3) actual       expected = map IntSet.fromList [[1, 2], [1, 3, 4], [1, 5, 6]]   actual' `elem` expected @?= True +case_findMUSAssumptions_Deletion = findMUSAssumptions_case1 MUS.Deletion+case_findMUSAssumptions_Insertion = findMUSAssumptions_case1 MUS.Insertion+case_findMUSAssumptions_QuickXplain = findMUSAssumptions_case1 MUS.QuickXplain+ ------------------------------------------------------------------------  {-@@ -1340,39 +1455,8 @@ -3 0 -} -case_camus_allMCSAssumptions = do-  solver <- SAT.newSolver-  [x1,x2,x3] <- SAT.newVars solver 3-  sels@[y1,y2,y3,y4,y5,y6] <- SAT.newVars solver 6-  SAT.addClause solver [-y1, x1]-  SAT.addClause solver [-y2, -x1]-  SAT.addClause solver [-y3, -x1, x2]-  SAT.addClause solver [-y4, -x2]-  SAT.addClause solver [-y5, -x1, x3]-  SAT.addClause solver [-y6, -x3]-  actual <- CAMUS.allMCSAssumptions solver sels def-  let actual'   = Set.fromList actual-      expected  = map (IntSet.fromList . map (+3)) [[1], [2,3,5], [2,3,6], [2,4,5], [2,4,6]]-      expected' = Set.fromList expected-  actual' @?= expected'--case_DAA_allMCSAssumptions = do-  solver <- SAT.newSolver-  [x1,x2,x3] <- SAT.newVars solver 3-  sels@[y1,y2,y3,y4,y5,y6] <- SAT.newVars solver 6-  SAT.addClause solver [-y1, x1]-  SAT.addClause solver [-y2, -x1]-  SAT.addClause solver [-y3, -x1, x2]-  SAT.addClause solver [-y4, -x2]-  SAT.addClause solver [-y5, -x1, x3]-  SAT.addClause solver [-y6, -x3]-  actual <- DAA.allMCSAssumptions solver sels def-  let actual'   = Set.fromList $ actual-      expected  = map (IntSet.fromList . map (+3)) [[1], [2,3,5], [2,3,6], [2,4,5], [2,4,6]]-      expected' = Set.fromList $ expected-  actual' @?= expected'--case_camus_allMUSAssumptions = do+allMUSAssumptions_case1 :: MUSEnum.Method -> IO ()+allMUSAssumptions_case1 method = do   solver <- SAT.newSolver   [x1,x2,x3] <- SAT.newVars solver 3   sels@[y1,y2,y3,y4,y5,y6] <- SAT.newVars solver 6@@ -1382,27 +1466,14 @@   SAT.addClause solver [-y4, -x2]   SAT.addClause solver [-y5, -x1, x3]   SAT.addClause solver [-y6, -x3]-  actual <- CAMUS.allMUSAssumptions solver sels def-  let actual'   = Set.fromList $ actual-      expected  = map (IntSet.fromList . map (+3)) [[1,2], [1,3,4], [1,5,6]]-      expected' = Set.fromList $ expected-  actual' @?= expected'+  (muses, mcses) <- MUSEnum.allMUSAssumptions solver sels def{ MUSEnum.optMethod = method }+  Set.fromList muses @?= Set.fromList (map (IntSet.fromList . map (+3)) [[1,2], [1,3,4], [1,5,6]])+  Set.fromList mcses @?= Set.fromList (map (IntSet.fromList . map (+3)) [[1], [2,3,5], [2,3,6], [2,4,5], [2,4,6]]) -case_DAA_allMUSAssumptions = do-  solver <- SAT.newSolver-  [x1,x2,x3] <- SAT.newVars solver 3-  sels@[y1,y2,y3,y4,y5,y6] <- SAT.newVars solver 6-  SAT.addClause solver [-y1, x1]-  SAT.addClause solver [-y2, -x1]-  SAT.addClause solver [-y3, -x1, x2]-  SAT.addClause solver [-y4, -x2]-  SAT.addClause solver [-y5, -x1, x3]-  SAT.addClause solver [-y6, -x3]-  actual <- DAA.allMUSAssumptions solver sels def-  let actual'   = Set.fromList $ actual-      expected  = map (IntSet.fromList . map (+3)) [[1,2], [1,3,4], [1,5,6]]-      expected' = Set.fromList $ expected-  actual' @?= expected'+case_allMUSAssumptions_CAMUS = allMUSAssumptions_case1 MUSEnum.CAMUS+case_allMUSAssumptions_DAA = allMUSAssumptions_case1 MUSEnum.DAA+case_allMUSAssumptions_MARCO = allMUSAssumptions_case1 MUSEnum.MARCO+case_allMUSAssumptions_GurvichKhachiyan1999 = allMUSAssumptions_case1 MUSEnum.GurvichKhachiyan1999  {- Boosting a Complete Technique to Find MSS and MUS thanks to a Local Search Oracle@@ -1422,7 +1493,8 @@ C11 : (a ∨ ¬b ∨ c) C12 : (a ∨ ¬b ∨ ¬d) -}-case_camus_allMUSAssumptions_2 = do+allMUSAssumptions_case2 :: MUSEnum.Method -> IO ()+allMUSAssumptions_case2 method = do   solver <- SAT.newSolver   [a,b,c,d,e] <- SAT.newVars solver 5   sels@[y0,y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12] <- SAT.newVars solver 13@@ -1471,12 +1543,17 @@       ret <- SAT.solveWith solver xs       assertBool (show core ++ " should be satisfiable") ret -  actual <- CAMUS.allMUSAssumptions solver sels def+  (actual,_) <- MUSEnum.allMUSAssumptions solver sels def{ MUSEnum.optMethod = method }   let actual'   = Set.fromList actual       expected' = Set.fromList $ map IntSet.fromList $ cores   actual' @?= expected' -case_HYCAM_allMUSAssumptions = do+case_allMUSAssumptions_2_CAMUS = allMUSAssumptions_case2 MUSEnum.CAMUS+case_allMUSAssumptions_2_DAA = allMUSAssumptions_case2 MUSEnum.DAA+case_allMUSAssumptions_2_MARCO = allMUSAssumptions_case2 MUSEnum.MARCO+case_allMUSAssumptions_2_GurvichKhachiyan1999 = allMUSAssumptions_case2 MUSEnum.GurvichKhachiyan1999++case_allMUSAssumptions_2_HYCAM = do   solver <- SAT.newSolver   [a,b,c,d,e] <- SAT.newVars solver 5   sels@[y0,y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12] <- SAT.newVars solver 13@@ -1543,73 +1620,349 @@   assertBool "failed to prove the bug of HYCAM paper" (not ret)      let cand = map IntSet.fromList [[y5], [y3,y2], [y0,y1,y2]]-  actual <- CAMUS.allMUSAssumptions solver sels def{ CAMUS.optKnownCSes = cand }+  (actual,_) <- MUSEnum.allMUSAssumptions solver sels def{ MUSEnum.optMethod = MUSEnum.CAMUS, MUSEnum.optKnownCSes = cand }   let actual'   = Set.fromList $ actual       expected' = Set.fromList $ map IntSet.fromList cores   actual' @?= expected' -case_DAA_allMUSAssumptions_2 = do-  solver <- SAT.newSolver-  [a,b,c,d,e] <- SAT.newVars solver 5-  sels@[y0,y1,y2,y3,y4,y5,y6,y7,y8,y9,y10,y11,y12] <- SAT.newVars solver 13-  SAT.addClause solver [-y0, d]-  SAT.addClause solver [-y1, b, c]-  SAT.addClause solver [-y2, a, b]-  SAT.addClause solver [-y3, a, -c]-  SAT.addClause solver [-y4, -b, -e]-  SAT.addClause solver [-y5, -a, -b]-  SAT.addClause solver [-y6, a, e]-  SAT.addClause solver [-y7, -a, -e]-  SAT.addClause solver [-y8, b, e]-  SAT.addClause solver [-y9, -a, b, -c]-  SAT.addClause solver [-y10, -a, b, -d]-  SAT.addClause solver [-y11, a, -b, c]-  SAT.addClause solver [-y12, a, -b, -d]+------------------------------------------------------------------------ -  -- Only three of the MUSes (marked with asterisks) are on the paper.-  let cores =-        [ [y0,y1,y2,y5,y9,y12]-        , [y0,y1,y3,y4,y5,y6,y10]-        , [y0,y1,y3,y5,y7,y8,y12]-        , [y0,y1,y3,y5,y9,y12]-        , [y0,y1,y3,y5,y10,y11]-        , [y0,y1,y3,y5,y10,y12]-        , [y0,y2,y3,y5,y10,y11]-        , [y0,y2,y4,y5,y6,y10]-        , [y0,y2,y5,y7,y8,y12]-        , [y0,y2,y5,y10,y12]   -- (*)-        , [y1,y2,y4,y5,y6,y9]-        , [y1,y3,y4,y5,y6,y7,y8]-        , [y1,y3,y4,y5,y6,y9]-        , [y1,y3,y5,y7,y8,y11]-        , [y1,y3,y5,y9,y11]    -- (*)-        , [y2,y3,y5,y7,y8,y11]-        , [y2,y4,y5,y6,y7,y8]  -- (*)-        ]+prop_ExistentialQuantification :: Property+prop_ExistentialQuantification = QM.monadicIO $ do+  phi <- QM.pick arbitraryCNF+  xs <- QM.pick $ liftM IntSet.fromList $ sublistOf [1 .. CNF.numVars phi]+  let ys = IntSet.fromList [1 .. CNF.numVars phi] IntSet.\\ xs+  psi <- QM.run $ ExistentialQuantification.project xs phi+  forM_ (replicateM (IntSet.size ys) [False,True]) $ \bs -> do+    let m :: SAT.Model+        m = array (1, if IntSet.null ys then 0 else IntSet.findMax ys) (zip (IntSet.toList ys) bs)+    b1 <- QM.run $ do+      solver <- SAT.newSolver+      SAT.newVars_ solver (CNF.numVars phi)+      forM_ (CNF.clauses phi) $ \c -> SAT.addClause solver c+      SAT.solveWith solver [if SAT.evalLit m y then y else -y | y <- IntSet.toList ys]+    let b2 = evalCNF m psi+    QM.assert $ b1 == b2 -  let remove1 :: [a] -> [[a]]-      remove1 [] = []-      remove1 (x:xs) = xs : [x : ys | ys <- remove1 xs]-  forM_ cores $ \core -> do-    ret <- SAT.solveWith solver core-    assertBool (show core ++ " should be a core") (not ret)-    forM (remove1 core) $ \xs -> do-      ret <- SAT.solveWith solver xs-      assertBool (show core ++ " should be satisfiable") ret+brauer11_phi :: CNF.CNF+brauer11_phi =+  CNF.CNF+  { CNF.numVars = 13+  , CNF.numClauses = 23+  , CNF.clauses =+      [+      -- μ+        [-x2, -y2]+      , [-y2, -y1]+      , [-x4, -x6, y1]+      , [-x3, y4], [x3, -y4]+      , [-x4, y3], [x4, -y3]+      , [-x5, y6], [x5, -y6]+      , [-x6, y5], [x6, -y5] -  actual <- DAA.allMUSAssumptions solver sels def-  let actual'   = Set.fromList actual-      expected' = Set.fromList $ map IntSet.fromList cores-  actual' @?= expected'+      -- ξ+      , [-x13, x1]+      , [-x13, -x2]+      , [-x13, x3]+      , [-x13, -x4]+      , [-x13, x5]+      , [-x13, -x6]+      , [x13, x1]+      , [x13, -x2]+      , [x13, -x3]+      , [x13, x4]+      , [x13, -x5]+      , [x13, x6]+      ]+  }+  where+    [y1,y2,y3,y4,y5,y6] = [1..6]+    [x1,x2,x3,x4,x5,x6,x13] = [7..13] +{-+ξ(m'1) = (¬y1 ∧ ¬y3 ∧ y4 ∧ ¬y5 ∧ y6)+ξ(m'2) = (y1 ∧ ¬y2 ∧ ¬y3 ∧ y4 ∧ ¬y5 ∧ y6)+ξ(m'3) = (y1 ∧ ¬y2 ∧ y3 ∧ ¬y4 ∧ y5 ∧ ¬y6)+ω = ¬(ξ(m'1) ∨ ξ(m'2) ∨ ξ(m'3))+-}+brauer11_omega :: CNF.CNF+brauer11_omega =+  CNF.CNF+  { CNF.numVars = 6+  , CNF.numClauses = 3+  , CNF.clauses =+      [ [y1, y3, -y4, y5, -y6]+      , [-y1, y2, y3, -y4, y5, -y6]+      , [-y1, y2, -y3, y4, -y5, y6]+      ]+  }+  where+    [y1,y2,y3,y4,y5,y6] = [1..6]++case_ExistentialQuantification_project_phi :: Assertion+case_ExistentialQuantification_project_phi = do+  psi <- ExistentialQuantification.project (IntSet.fromList [7..13]) brauer11_phi+  forM_ (replicateM 6 [False,True]) $ \bs -> do+    let m :: SAT.Model+        m = array (1,13) (zip [1..] bs)    +    b1 <- do+      solver <- SAT.newSolver+      SAT.newVars_ solver (CNF.numVars brauer11_phi)+      forM_ (CNF.clauses brauer11_phi) $ \c -> SAT.addClause solver c+      SAT.solveWith solver [if SAT.evalLit m y then y else -y | y <- [1..6]]+    let b2 = all (SAT.evalClause m) (CNF.clauses psi)+    (b1 == b2) @?= True++case_ExistentialQuantification_project_phi' :: Assertion+case_ExistentialQuantification_project_phi' = do+  let [y1,y2,y3,y4,y5,y6] = [1..6]+      psi = CNF.CNF+            { CNF.numVars = 6+            , CNF.numClauses = 8+            , CNF.clauses =+                [ [-y2, y6]+                , [-y3, -y6]+                , [y5, y6]+                , [y3, -y5]+                , [y4, -y6]+                , [y1, y6]+                , [-y1, -y2]+                , [-y4, y6]+                ]+            }+  forM_ (replicateM 6 [False,True]) $ \bs -> do+    let m :: SAT.Model+        m = array (1,13) (zip [1..] bs)+    b1 <- do+      solver <- SAT.newSolver+      SAT.newVars_ solver (CNF.numVars brauer11_phi)+      forM_ (CNF.clauses brauer11_phi) $ \c -> SAT.addClause solver c+      SAT.solveWith solver [if SAT.evalLit m y then y else -y | y <- [1..6]]+    let b2 = all (SAT.evalClause m) (CNF.clauses psi)    +    (b1 == b2) @?= True++case_shortestImplicants_phi :: Assertion+case_shortestImplicants_phi = do+  xss <- ExistentialQuantification.shortestImplicants (IntSet.fromList [1..6]) brauer11_phi+  forM_ (replicateM 6 [False,True]) $ \bs -> do+    let m :: SAT.Model+        m = array (1,6) (zip [1..] bs)+    b1 <- do+      solver <- SAT.newSolver+      SAT.newVars_ solver (CNF.numVars brauer11_phi)+      forM_ (CNF.clauses brauer11_phi) $ \c -> SAT.addClause solver c+      SAT.solveWith solver [if SAT.evalLit m y then y else -y | y <- [1..6]]+    let b2 = any (all (SAT.evalLit m) . IntSet.toList) xss+    (b1 == b2) @?= True++case_shortestImplicants_phi' :: Assertion+case_shortestImplicants_phi' = do+  let [y1,y2,y3,y4,y5,y6] = [1..6]+      xss = map IntSet.fromList+            [ [-y1, -y3, y4, -y5, y6]+            , [y1, -y2, -y3, y4, -y5, y6]+            , [y1, -y2, y3, -y4, y5, -y6]+            ]+  forM_ (replicateM 6 [False,True]) $ \bs -> do+    let m :: SAT.Model+        m = array (1,6) (zip [1..] bs)+    b1 <- do+      solver <- SAT.newSolver+      SAT.newVars_ solver (CNF.numVars brauer11_phi)+      forM_ (CNF.clauses brauer11_phi) $ \c -> SAT.addClause solver c+      SAT.solveWith solver [if SAT.evalLit m y then y else -y | y <- [1..6]]+    let b2 = any (all (SAT.evalLit m) . IntSet.toList) xss+    (b1 == b2) @?= True++case_shortestImplicants_omega :: Assertion+case_shortestImplicants_omega = do+  xss <- ExistentialQuantification.shortestImplicants (IntSet.fromList [1..6]) brauer11_omega+  forM_ (replicateM 6 [False,True]) $ \bs -> do+    let m :: SAT.Model+        m = array (1,6) (zip [1..] bs)+    b1 <- do+      solver <- SAT.newSolver+      SAT.newVars_ solver (CNF.numVars brauer11_omega)+      forM_ (CNF.clauses brauer11_omega) $ \c -> SAT.addClause solver c+      SAT.solveWith solver [if SAT.evalLit m y then y else -y | y <- [1..6]]+    let b2 = any (all (SAT.evalLit m) . IntSet.toList) xss+    unless (b1 == b2) $ print m++case_shortestImplicants_omega' :: Assertion+case_shortestImplicants_omega' = do+  let [y1,y2,y3,y4,y5,y6] = [1..6]+      xss = map IntSet.fromList+              [ [y2, -y6]+              , [y3, y6]+              , [-y5, -y6]+              , [-y3, y5]+              , [-y4, y6]+              , [-y1, -y6]+              , [y1, y2]+              , [y4, -y6]+              ]+  forM_ (replicateM 6 [False,True]) $ \bs -> do+    let m :: SAT.Model+        m = array (1,6) (zip [1..] bs)+    b1 <- do+      solver <- SAT.newSolver+      SAT.newVars_ solver (CNF.numVars brauer11_omega)+      forM_ (CNF.clauses brauer11_omega) $ \c -> SAT.addClause solver c+      SAT.solveWith solver [if SAT.evalLit m y then y else -y | y <- [1..6]]+    let b2 = any (all (SAT.evalLit m) . IntSet.toList) xss+    (b1 == b2) @?= True+ ------------------------------------------------------------------------ ++prop_pb2sat :: Property+prop_pb2sat = QM.monadicIO $ do+  pb@(nv,cs) <- QM.pick arbitraryPB+  let f (PBRelGE,lhs,rhs) = ([(c,[l]) | (c,l) <- lhs], PBFile.Ge, rhs)+      f (PBRelLE,lhs,rhs) = ([(-c,[l]) | (c,l) <- lhs], PBFile.Ge, -rhs)+      f (PBRelEQ,lhs,rhs) = ([(c,[l]) | (c,l) <- lhs], PBFile.Eq, rhs)+  let opb = PBFile.Formula+            { PBFile.pbObjectiveFunction = Nothing+            , PBFile.pbNumVars = nv+            , PBFile.pbNumConstraints = length cs+            , PBFile.pbConstraints = map f cs+            }+  let (cnf, mforth, mback) = PB2SAT.convert opb++  solver1 <- arbitrarySolver+  solver2 <- arbitrarySolver+  ret1 <- QM.run $ solvePB solver1 pb+  ret2 <- QM.run $ solveCNF solver2 cnf+  QM.assert $ isJust ret1 == isJust ret2+  case ret1 of+    Nothing -> return ()+    Just m1 -> do+      let m2 = mforth m1+      QM.assert $ bounds m2 == (1, CNF.numVars cnf)+      QM.assert $ evalCNF m2 cnf+  case ret2 of+    Nothing -> return ()+    Just m2 -> do+      let m1 = mback m2+      QM.assert $ bounds m1 == (1, nv)+      QM.assert $ evalPB m1 pb++prop_wbo2maxsat :: Property+prop_wbo2maxsat = QM.monadicIO $ do+  wbo1@(nv,cs,top) <- QM.pick arbitraryWBO+  let f (w,(PBRelGE,lhs,rhs)) = (w,([(c,[l]) | (c,l) <- lhs], PBFile.Ge, rhs))+      f (w,(PBRelLE,lhs,rhs)) = (w,([(-c,[l]) | (c,l) <- lhs], PBFile.Ge, -rhs))+      f (w,(PBRelEQ,lhs,rhs)) = (w,([(c,[l]) | (c,l) <- lhs], PBFile.Eq, rhs))+  let wbo1' = PBFile.SoftFormula+            { PBFile.wboNumVars = nv+            , PBFile.wboNumConstraints = length cs+            , PBFile.wboConstraints = map f cs+            , PBFile.wboTopCost = top+            }+  let (wcnf, mforth, mback) = WBO2MaxSAT.convert wbo1'+      wbo2 = ( MaxSAT.numVars wcnf+             , [ ( if w == MaxSAT.topCost wcnf then Nothing else Just w+                 , (PBRelGE, [(1,l) | l <- clause], 1)+                 )+               | (w,clause) <- MaxSAT.clauses wcnf+               ]+             , Nothing+             )++  solver1 <- arbitrarySolver+  solver2 <- arbitrarySolver+  method <- QM.pick arbitrary+  ret1 <- QM.run $ optimizeWBO solver1 method wbo1+  ret2 <- QM.run $ optimizeWBO solver2 method wbo2+  QM.assert $ isJust ret1 == isJust ret2+  case ret1 of+    Nothing -> return ()+    Just (m1,val) -> do+      let m2 = mforth m1+      QM.assert $ bounds m2 == (1, MaxSAT.numVars wcnf)+      QM.assert $ evalWBO m2 wbo2 == Just val+  case ret2 of+    Nothing -> return ()+    Just (m2,val) -> do+      let m1 = mback m2+      QM.assert $ bounds m1 == (1, nv)+      QM.assert $ evalWBO m1 wbo1 == Just val++prop_wbo2pb :: Property+prop_wbo2pb = QM.monadicIO $ do+  wbo@(nv,cs,top) <- QM.pick arbitraryWBO+  let f (w,(PBRelGE,lhs,rhs)) = (w,([(c,[l]) | (c,l) <- lhs], PBFile.Ge, rhs))+      f (w,(PBRelLE,lhs,rhs)) = (w,([(-c,[l]) | (c,l) <- lhs], PBFile.Ge, -rhs))+      f (w,(PBRelEQ,lhs,rhs)) = (w,([(c,[l]) | (c,l) <- lhs], PBFile.Eq, rhs))+  let wbo' = PBFile.SoftFormula+            { PBFile.wboNumVars = nv+            , PBFile.wboNumConstraints = length cs+            , PBFile.wboConstraints = map f cs+            , PBFile.wboTopCost = top+            }+  let (opb, mforth, mback) = WBO2PB.convert wbo'+      obj = fromMaybe [] $ PBFile.pbObjectiveFunction opb+      f (lhs, PBFile.Ge, rhs) = (PBRelGE, lhs, rhs)+      f (lhs, PBFile.Eq, rhs) = (PBRelEQ, lhs, rhs)+      cs2 = map f (PBFile.pbConstraints opb)+      pb = (PBFile.pbNumVars opb, obj, cs2)++  solver1 <- arbitrarySolver+  solver2 <- arbitrarySolver+  method <- QM.pick arbitrary+  ret1 <- QM.run $ optimizeWBO solver1 method wbo+  ret2 <- QM.run $ optimizePBNLC solver2 method pb+  QM.assert $ isJust ret1 == isJust ret2+  case ret1 of+    Nothing -> return ()+    Just (m1,val1) -> do+      let m2 = mforth m1+      QM.assert $ bounds m2 == (1, PBFile.pbNumVars opb)+      QM.assert $ evalPBNLC m2 (PBFile.pbNumVars opb, cs2)+      QM.assert $ SAT.evalPBSum m2 obj == val1+  case ret2 of+    Nothing -> return ()+    Just (m2,val2) -> do+      let m1 = mback m2+      QM.assert $ bounds m1 == (1,nv)+      QM.assert $ evalWBO m1 wbo == Just val2++prop_sat2ksat :: Property+prop_sat2ksat = QM.monadicIO $ do+  k <- QM.pick $ choose (3,10)++  cnf1 <- QM.pick arbitraryCNF+  let (cnf2, mforth, mback) = SAT2KSAT.convert k cnf1++  solver1 <- arbitrarySolver+  solver2 <- arbitrarySolver+  ret1 <- QM.run $ solveCNF solver1 cnf1+  ret2 <- QM.run $ solveCNF solver2 cnf2+  QM.assert $ isJust ret1 == isJust ret2+  case ret1 of+    Nothing -> return ()+    Just m1 -> do+      let m2 = mforth m1+      QM.assert $ bounds m2 == (1, CNF.numVars cnf2)+      QM.assert $ evalCNF m2 cnf2+  case ret2 of+    Nothing -> return ()+    Just m2 -> do+      let m1 = mback m2+      QM.assert $ bounds m1 == (1, CNF.numVars cnf1)+      QM.assert $ evalCNF m1 cnf1++------------------------------------------------------------------------+ instance Arbitrary SAT.LearningStrategy where   arbitrary = arbitraryBoundedEnum  instance Arbitrary SAT.RestartStrategy where   arbitrary = arbitraryBoundedEnum +instance Arbitrary SAT.BranchingStrategy where+  arbitrary = arbitraryBoundedEnum+ instance Arbitrary SAT.PBHandlerType where   arbitrary = arbitraryBoundedEnum @@ -1621,6 +1974,10 @@     learningStrategy <- arbitrary     learntSizeFirst <- arbitrary     learntSizeInc <- liftM ((1.01 +) . abs) arbitrary+    branchingStrategy <- arbitrary+    erwaStepSizeFirst <- choose (0, 1)+    erwaStepSizeMin   <- choose (0, 1)+    erwaStepSizeDec   <- choose (0, 1)     pbhandler <- arbitrary     ccmin <- choose (0,2)     phaseSaving <- arbitrary@@ -1637,6 +1994,10 @@       , SAT.configLearntSizeInc = learntSizeInc       , SAT.configPBHandlerType = pbhandler       , SAT.configCCMin = ccmin+      , SAT.configBranchingStrategy = branchingStrategy+      , SAT.configERWAStepSizeFirst = erwaStepSizeFirst+      , SAT.configERWAStepSizeDec   = erwaStepSizeDec+      , SAT.configERWAStepSizeMin   = erwaStepSizeMin       , SAT.configEnablePhaseSaving = phaseSaving       , SAT.configEnableForwardSubsumptionRemoval = forwardSubsumptionRemoval       , SAT.configEnableBackwardSubsumptionRemoval = backwardSubsumptionRemoval@@ -1655,14 +2016,24 @@  arbitraryOptimizer :: SAT.Solver -> SAT.PBLinSum -> QM.PropertyM IO PBO.Optimizer arbitraryOptimizer solver obj = do-  strategy <- QM.pick arbitrary+  method <- QM.pick arbitrary   QM.run $ do     opt <- PBO.newOptimizer solver obj-    PBO.setSearchStrategy opt strategy+    PBO.setMethod opt method     return opt -instance Arbitrary PBO.SearchStrategy where+instance Arbitrary PBO.Method where   arbitrary = arbitraryBoundedEnum++instance Arbitrary PB.Strategy where+  arbitrary = arbitraryBoundedEnum++-- ---------------------------------------------------------------------++#if !MIN_VERSION_QuickCheck(2,8,0)+sublistOf :: [a] -> Gen [a]+sublistOf xs = filterM (\_ -> choose (False, True)) xs+#endif  ------------------------------------------------------------------------ -- Test harness
test/Test/SDPFile.hs view
@@ -4,6 +4,7 @@ import Control.Monad import Data.List import Data.Maybe+import Data.ByteString.Builder (toLazyByteString) import Test.Tasty import Test.Tasty.QuickCheck import Test.Tasty.HUnit@@ -49,23 +50,23 @@  case_test1 = checkParsed example1b example1   where-    s = render example1 ""-    example1b = parseDataString "" s+    s = toLazyByteString $ render example1+    example1b = parseData "" s  case_test2 = checkParsed example1b example1   where-    s = renderSparse example1 ""-    example1b = parseSparseDataString "" s+    s = toLazyByteString $ renderSparse example1+    example1b = parseSparseData "" s  case_test3 = checkParsed example2b example2   where-    s = render example2 ""-    example2b = parseDataString "" s+    s = toLazyByteString $ render example2+    example2b = parseData "" s  case_test4 = checkParsed example2b example2   where-    s = renderSparse example2 ""-    example2b = parseSparseDataString "" s+    s = toLazyByteString $ renderSparse example2+    example2b = parseSparseData "" s  -- checkParsed :: Either ParseError Problem -> Problem -> Assertion checkParsed actual expected =
test/Test/SMT.hs view
@@ -1,7 +1,8 @@-{-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-}+{-# LANGUAGE TemplateHaskell, ScopedTypeVariables, OverloadedStrings #-} module Test.SMT (smtTestGroup) where  import Control.Applicative((<$>))+import Control.DeepSeq import Control.Exception (evaluate) import Control.Monad import Control.Monad.State.Strict@@ -14,10 +15,12 @@ import Test.Tasty.TH import qualified Test.QuickCheck.Monadic as QM +import qualified ToySolver.BitVector as BV import ToySolver.Data.Boolean import ToySolver.Data.OrdRel import ToySolver.SMT (Expr (..)) import qualified ToySolver.SMT as SMT+import ToySolver.BitVector (nat2bv)  -- ------------------------------------------------------------------- @@ -234,6 +237,20 @@ violation of a+b < 15. -} +case_uninterpretedSortFunction_eval :: Assertion+case_uninterpretedSortFunction_eval = do+  solver <- SMT.newSolver+  (sF :: SMT.Sort -> SMT.Sort) <- SMT.declareSort solver "F" 1+  (sU :: SMT.Sort) <- SMT.declareSort solver "U" 0+  let s = sF sU+  x <- SMT.declareConst solver "x" s+  ret <- SMT.checkSAT solver+  ret @?= True+  m <- SMT.getModel solver+  case SMT.eval m x of+    SMT.ValUninterpreted n s' -> s' @?= s+    _ -> assertFailure "should be ValUninterpreted"+ prop_getModel_eval :: Property prop_getModel_eval = QM.monadicIO $ do   solver <- QM.run $ SMT.newSolver@@ -243,20 +260,26 @@     s <- SMT.declareSort solver ("U" ++ show i) 0     c <- SMT.declareFSym solver ("U" ++ show i ++ "const") [] s     return (s, (c, ([],s)))-  let sorts = [SMT.sBool, SMT.sReal] ++ map fst xs+  let genSorts = oneof $+        [ return SMT.sBool+        , return SMT.sReal+        , do w <- choose (1,10) -- inclusive+             return $ SMT.Sort (SMT.SSymBitVec w) []+        ] +++        [ fst <$> elements xs | not (null xs) ]       cs = map snd xs   fs1 <- QM.pick $ do-    ts <- listOf (genFunType sorts)+    ts <- listOf (genFunType genSorts)     return [("f" ++ show i, t) | (i,t) <- zip [1..] ts]   fs2 <- QM.run $ forM fs1 $ \(name, t@(argsSorts, resultSort)) -> do     f <- SMT.declareFSym solver name argsSorts resultSort     return (f, t) -  let sig =  [("ite", ([SMT.sBool,s,s], s)) | s <- sorts]-          ++ [("=", ([s,s], SMT.sBool)) | s <- sorts]-          ++ [ ("true", ([], SMT.sBool))+  let sig =  [ ("true", ([], SMT.sBool))+             , ("false", ([], SMT.sBool))              , ("and", ([SMT.sBool,SMT.sBool], SMT.sBool))              , ("or", ([SMT.sBool,SMT.sBool], SMT.sBool))+             , ("xor", ([SMT.sBool,SMT.sBool], SMT.sBool))              , ("not", ([SMT.sBool], SMT.sBool))              , ("=>", ([SMT.sBool,SMT.sBool], SMT.sBool))              , ("+", ([SMT.sReal,SMT.sReal], SMT.sReal))@@ -273,7 +296,7 @@    constrs <- QM.pick $ do     nconstrs <- choose ((0::Int), 3)-    replicateM nconstrs (genExpr sig SMT.sBool 10)+    replicateM nconstrs (genExpr genSorts sig SMT.sBool 10)   ret <- QM.run $ do     forM_ constrs $ \constr -> SMT.assert solver constr     SMT.checkSAT solver@@ -282,14 +305,89 @@     forM_ constrs $ \constr -> do       QM.assert $ SMT.eval m constr == SMT.ValBool True -genFunType :: [SMT.Sort] -> Gen SMT.FunType-genFunType sorts = do-  resultSort <- elements sorts-  argsSorts <- listOf $ elements sorts+prop_getModel_evalFSym :: Property+prop_getModel_evalFSym = QM.monadicIO $ do+  solver <- QM.run $ SMT.newSolver++  nsorts <- QM.pick $ choose ((0::Int), 3)+  xs <- QM.run $ forM [(1::Int)..nsorts] $ \i -> do+    s <- SMT.declareSort solver ("U" ++ show i) 0+    c <- SMT.declareFSym solver ("U" ++ show i ++ "const") [] s+    return (s, (c, ([],s)))+  let genSorts = oneof $+        [ return SMT.sBool+        , return SMT.sReal+        , do w <- choose (1,10) -- inclusive+             return $ SMT.Sort (SMT.SSymBitVec w) []+        ] +++        [ fst <$> elements xs | not (null xs) ]+      cs = map snd xs+  fs1 <- QM.pick $ do+    ts <- listOf (genFunType genSorts)+    return [("f" ++ show i, t) | (i,t) <- zip [1..] ts]+  fs2 <- QM.run $ forM fs1 $ \(name, t@(argsSorts, resultSort)) -> do+    f <- SMT.declareFSym solver name argsSorts resultSort+    return (f, t)++  let sig =  [ ("true", ([], SMT.sBool))+             , ("false", ([], SMT.sBool))+             , ("and", ([SMT.sBool,SMT.sBool], SMT.sBool))+             , ("or", ([SMT.sBool,SMT.sBool], SMT.sBool))+             , ("xor", ([SMT.sBool,SMT.sBool], SMT.sBool))+             , ("not", ([SMT.sBool], SMT.sBool))+             , ("=>", ([SMT.sBool,SMT.sBool], SMT.sBool))+             , ("+", ([SMT.sReal,SMT.sReal], SMT.sReal))+             , ("-", ([SMT.sReal,SMT.sReal], SMT.sReal))+             , ("*", ([SMT.sReal,SMT.sReal], SMT.sReal))+             , ("/", ([SMT.sReal,SMT.sReal], SMT.sReal))+             , ("-", ([SMT.sReal], SMT.sReal))+             , (">=", ([SMT.sReal, SMT.sReal], SMT.sBool))+             , ("<=", ([SMT.sReal, SMT.sReal], SMT.sBool))+             , (">", ([SMT.sReal, SMT.sReal], SMT.sBool))+             , ("<", ([SMT.sReal, SMT.sReal], SMT.sBool))+             ]+          ++ fs2 ++ cs++  constrs <- QM.pick $ do+    nconstrs <- choose ((0::Int), 3)+    replicateM nconstrs (genExpr genSorts sig SMT.sBool 10)+  QM.run $ do+    forM_ constrs $ \constr -> SMT.assert solver constr+    ret <- SMT.checkSAT solver    +    when ret $ do+      m <- SMT.getModel solver+      forM_ fs2 $ \(f,_) -> do+        evaluate $ force $ show $ SMT.evalFSym m f+      return ()++-- https://github.com/msakai/toysolver/issues/21+case_issue21_32bit :: Assertion+case_issue21_32bit = do+  solver <- SMT.newSolver+  let constr =+        SMT.EAp (SMT.FSym "bvlshr" []) [SMT.EValue (SMT.ValBitVec (nat2bv 32 0)), SMT.EValue (SMT.ValBitVec (nat2bv 32 31))]+        .==.+        SMT.EValue (SMT.ValBitVec (nat2bv 32 0))+  SMT.assert solver constr++-- https://github.com/msakai/toysolver/issues/21+case_issue21_64bit :: Assertion+case_issue21_64bit = do+  solver <- SMT.newSolver+  let constr =+        SMT.EAp (SMT.FSym "bvlshr" []) [SMT.EValue (SMT.ValBitVec (nat2bv 64 0)), SMT.EValue (SMT.ValBitVec (nat2bv 64 63))]+        .==.+        SMT.EValue (SMT.ValBitVec (nat2bv 64 0))+  SMT.assert solver constr++genFunType :: Gen SMT.Sort -> Gen SMT.FunType+genFunType genSorts = do+  resultSort <- genSorts+  argsSorts <- listOf $ genSorts   return (argsSorts, resultSort) -genExpr :: [(SMT.FSym, SMT.FunType)] -> SMT.Sort -> Int -> Gen SMT.Expr-genExpr sig s size = evalStateT (f s) size+genExpr :: Gen SMT.Sort -> [(SMT.FSym, SMT.FunType)] -> SMT.Sort -> Int -> Gen SMT.Expr+genExpr genSorts sig s size = evalStateT (f s) size   where     sig' :: Map SMT.Sort [(SMT.FSym, [SMT.Sort])]     sig' = Map.fromListWith (++) [(resultSort, [(fsym, argsSorts)]) | (fsym, (argsSorts,resultSort)) <- sig]@@ -318,8 +416,83 @@         , op /= "*" && op /= "/"         , size >= length argsSorts || null argsSorts         ]+        +++        [ flip runStateT size $ do+            arg1 <- f SMT.sBool+            arg2 <- f s+            arg3 <- f s+            return $ EAp "ite" [arg1, arg2, arg3]+        | size >= 3+        ]       put size'       return e+    f s@(SMT.Sort (SMT.SSymBitVec w) []) = do+      modify (subtract 1)+      size <- get+      (e,size') <- lift $ oneof $+        [ do+            bs <- replicateM w arbitrary+            return (EValue (SMT.ValBitVec (BV.fromDescBits bs)), size)+        ]+        +++        [ flip runStateT size $ do+            w1 <- lift $ choose (1,w-1)+            arg1 <- f (SMT.Sort (SMT.SSymBitVec w1) [])+            arg2 <- f (SMT.Sort (SMT.SSymBitVec (w - w1)) [])+            return $ EAp "concat" [arg1,arg2]+        | w > 0, size >= 2+        ]+        +++        [ flip runStateT size $ do+            wd <- lift $ choose (0,10)+            l <- lift $ choose (0, wd) -- inclusive range+            let u = l + w - 1+            arg <- f (SMT.Sort (SMT.SSymBitVec (w + wd)) [])+            return $ EAp (SMT.FSym "extract" [SMT.IndexNumeral (fromIntegral u), SMT.IndexNumeral (fromIntegral l)]) [arg]+        | w > 0, size >= 1+        ]+        +++        [ flip runStateT size $ do+            arg <- f s+            return $ EAp op [arg]+        | op <- ["bvnot","bvneg"]+        , size >= 1+        ]+        +++        [ flip runStateT size $ do+            arg1 <- f s+            arg2 <- f s+            return $ EAp op [arg1, arg2]+        | op <- ["bvand","bvor","bvxor","bvnand","bvnor","bvxnor","bvadd"] +++                ["bvsub","bvmul","bvudiv","bvurem","bvshl","bvlshr","bvashr"] +++                (if w >= 1 then ["bvsdiv", "bvsrem", "bvsmod"] else [])+        , size >= 2+        ]+        +++        [ flip runStateT size $ do+            w2 <- lift $ choose (1, 10)+            arg1 <- f (SMT.Sort (SMT.SSymBitVec w2) [])+            arg2 <- f (SMT.Sort (SMT.SSymBitVec w2) [])+            return $ EAp "bvcomp" [arg1, arg2]+        | w == 1, size >= 2+        ]+        +++        [ flip runStateT size $ do+            args <- mapM f argsSorts+            return $ EAp op args+        | (op, argsSorts) <- Map.findWithDefault [] s sig'+        , size >= length argsSorts || null argsSorts+        ]+        +++        [ flip runStateT size $ do+            arg1 <- f SMT.sBool+            arg2 <- f s+            arg3 <- f s+            return $ EAp "ite" [arg1, arg2, arg3]+        | size >= 3+        ]+      put size'+      return e           f s = do       modify (subtract 1)       size <- get@@ -329,6 +502,32 @@             return $ EAp op args         | (op, argsSorts) <- Map.findWithDefault [] s sig'         , size >= length argsSorts || null argsSorts+        ]+        +++        [ flip runStateT size $ do+            arg1 <- f SMT.sBool+            arg2 <- f s+            arg3 <- f s+            return $ EAp "ite" [arg1, arg2, arg3]+        | size >= 3+        ]+        +++        [ flip runStateT size $ do+            s1 <- lift $ genSorts+            arg1 <- f s1+            arg2 <- f s1+            return $ EAp op [arg1, arg2]+        | s == SMT.sBool, size >= 2+        , op <- ["="]+        ]+        ++ +        [ flip runStateT size $ do+            w <- lift $ choose (1, 10)+            arg1 <- f (SMT.Sort (SMT.SSymBitVec w) [])+            arg2 <- f (SMT.Sort (SMT.SSymBitVec w) [])+            return $ EAp op [arg1, arg2]+        | s == SMT.sBool, size >= 2+        , op <- ["bvule","bvult","bvuge","bvugt","bvsle","bvslt","bvsge","bvsgt"]         ]       put size'       return e
test/Test/Simplex.hs view
@@ -2,173 +2,404 @@ module Test.Simplex (simplexTestGroup) where  import Control.Monad-import Control.Monad.State-import Data.IntMap (IntMap)-import qualified Data.IntMap as IntMap-import Data.IntSet (IntSet)-import qualified Data.IntSet as IntSet+import Data.Default.Class import Data.List import Data.Ratio+import Data.VectorSpace import Test.Tasty import Test.Tasty.HUnit import Test.Tasty.TH import Text.Printf- import qualified ToySolver.Data.LA as LA-import ToySolver.Data.LA ((.<=.)) import ToySolver.Arith.Simplex-import qualified ToySolver.Arith.LPSolver as LP -example_3_2 :: Tableau Rational-example_3_2 = IntMap.fromList-  [ (4, (IntMap.fromList [(1,2), (2,1), (3,1)], 2))-  , (5, (IntMap.fromList [(1,1), (2,2), (3,3)], 5))-  , (6, (IntMap.fromList [(1,2), (2,2), (3,1)], 6))-  , (objRowIndex, (IntMap.fromList [(1,-3), (2,-2), (3,-3)], 0))-  ]+case_test1 :: Assertion+case_test1 = do+  solver <- newSolver+  x <- newVar solver+  y <- newVar solver+  z <- newVar solver+  assertAtom solver (LA.fromTerms [(7,x), (12,y), (31,z)] .==. LA.constant 17)+  assertAtom solver (LA.fromTerms [(3,x), (5,y), (14,z)]  .==. LA.constant 7)+  assertAtom solver (LA.var x .>=. LA.constant 1)+  assertAtom solver (LA.var x .<=. LA.constant 40)+  assertAtom solver (LA.var y .>=. LA.constant (-50))+  assertAtom solver (LA.var y .<=. LA.constant 50) -case_example_3_2_simplex :: Assertion-case_example_3_2_simplex = do-  assertBool "simplex failed" ret-  assertBool "invalid tableau" (isValidTableau result)-  assertBool "infeasible tableau" (isFeasible result)-  assertBool "unoptimal tableau" (isOptimal OptMax result)-  currentObjValue result @?= 27/5-  where-    ret :: Bool-    result :: Tableau Rational-    (ret,result) = simplex OptMax example_3_2+  ret <- check solver+  ret @?= True -case_example_3_2_primalDualSimplex :: Assertion-case_example_3_2_primalDualSimplex = do-  assertBool "simplex failed" ret-  assertBool "invalid tableau" (isValidTableau result)-  assertBool "infeasible tableau" (isFeasible result)-  assertBool "unoptimal tableau" (isOptimal OptMax result)-  currentObjValue result @?= 27/5-  where-    ret :: Bool-    result :: Tableau Rational-    (ret,result) = primalDualSimplex OptMax example_3_2+  vx <- getValue solver x+  vy <- getValue solver y+  vz <- getValue solver z+  7*vx + 12*vy + 31*vz @?= 17+  3*vx + 5*vy + 14*vz @?= 7+  assertBool (printf "vx should be >=1 but %s"   (show vx)) $ vx >= 1+  assertBool (printf "vx should be <=40 but %s"  (show vx)) $ vx <= 40+  assertBool (printf "vx should be >=-50 but %s" (show vy)) $ vy >= -50+  assertBool (printf "vx should be <=50 but %s"  (show vy)) $ vy <= 50 --- from http://www.math.cuhk.edu.hk/~wei/lpch5.pdf-exampe_5_3_phase1 :: Tableau Rational-exampe_5_3_phase1 = IntMap.fromList-  [ (6, (IntMap.fromList [(2,-1), (3,-1), (5,1), (6,1)], 1))-  , (7, (IntMap.fromList [(3,1), (4,-1), (5,1), (7,1)], 0))-  ]+case_test2 :: Assertion+case_test2 = do+  solver <- newSolver+  x <- newVar solver+  y <- newVar solver+  assertAtom solver (LA.fromTerms [(11,x), (13,y)] .>=. LA.constant 27)+  assertAtom solver (LA.fromTerms [(11,x), (13,y)] .<=. LA.constant 45)+  assertAtom solver (LA.fromTerms [(7,x), (-9,y)] .>=. LA.constant (-10))+  assertAtom solver (LA.fromTerms [(7,x), (-9,y)] .<=. LA.constant 4) -case_exampe_5_3_phase1 :: Assertion-case_exampe_5_3_phase1 = do-  let (ret,result) = phaseI exampe_5_3_phase1 (IntSet.fromList [6,7])-  assertBool "phase1 failed" ret-  assertBool "invalid tableau" (isValidTableau result)-  assertBool "infeasible tableau" (isFeasible result)    +  ret <- check solver+  ret @?= True --- 退化して巡回の起こるKuhnの7変数3制約の例-kuhn_7_3 :: Tableau Rational-kuhn_7_3 = IntMap.fromList-  [ (1, (IntMap.fromList [(4,-2), (5,-9), (6,1), (7,9)],       0))-  , (2, (IntMap.fromList [(4,1/3), (5,1), (6,-1/3), (7,-2)],   0))-  , (3, (IntMap.fromList [(4,2), (5,3), (6,-1), (7,-12)],      2))-  , (objRowIndex, (IntMap.fromList [(4,2), (5,3), (6,-1), (7,-12)], 0))-  ]+  vx <- getValue solver x+  vy <- getValue solver y+  let v1 = 11*vx + 13*vy+      v2 = 7*vx - 9*vy+  assertBool (printf "11*vx + 13*vy should be >=27 but %s" (show v1)) $ 27 <= v1+  assertBool (printf "11*vx + 13*vy should be <=45 but %s" (show v1)) $ v1 <= 45+  assertBool (printf "7*vx - 9*vy should be >=-10 but %s" (show v2)) $ -10 <= v2+  assertBool (printf "7*vx - 9*vy should be >=-10 but %s" (show v2)) $ v2 <= 4 -case_kuhn_7_3 :: Assertion-case_kuhn_7_3 = do-  assertBool "simplex failed" ret-  assertBool "invalid tableau" (isValidTableau result)-  currentObjValue result @?= -2-  where-    ret :: Bool-    result :: Tableau Rational-    (ret,result) = simplex OptMin kuhn_7_3 --- case_pd_kuhn_7_3 :: Assertion--- case_pd_kuhn_7_3 = do---   assertBool "simplex failed" ret---   assertBool "invalid tableau" (isValidTableau result)---   currentObjValue result @?= -2---   where---     ret :: Bool---     result :: Tableau Rational---     (ret,result) = primalDualSimplex OptMin kuhn_7_3+{-+Minimize+ obj: - x1 - 2 x2 - 3 x3 - x4+Subject To+ c1: - x1 + x2 + x3 + 10 x4 <= 20+ c2: x1 - 3 x2 + x3 <= 30+ c3: x2 - 3.5 x4 = 0+Bounds+ 0 <= x1 <= 40+ 2 <= x4 <= 3+End+-}+case_test3 :: Assertion+case_test3 = do+  solver <- newSolver --- from http://www.math.cuhk.edu.hk/~wei/lpch5.pdf-example_5_7 :: Tableau Rational-example_5_7 = IntMap.fromList-  [ (4, (IntMap.fromList [(1,-1), (2,-2), (3,-3)], -5))-  , (5, (IntMap.fromList [(1,-2), (2,-2), (3,-1)], -6))-  , (objRowIndex, (IntMap.fromList [(1,3),(2,4),(3,5)], 0))-  ]+  _ <- newVar solver+  x1 <- newVar solver+  x2 <- newVar solver+  x3 <- newVar solver+  x4 <- newVar solver -case_example_5_7 :: Assertion-case_example_5_7 = do-  assertBool "dual simplex failed" ret-  assertBool "invalid tableau" (isValidTableau result)-  currentObjValue result @?= -11-  where-    ret :: Bool-    result :: Tableau Rational-    (ret,result) = dualSimplex OptMax example_5_7+  setObj solver (LA.fromTerms [(-1,x1), (-2,x2), (-3,x3), (-1,x4)]) -case_pd_example_5_7 :: Assertion-case_pd_example_5_7 = do-  assertBool "dual simplex failed" ret-  assertBool "invalid tableau" (isValidTableau result)-  currentObjValue result @?= -11-  where-    ret :: Bool-    result :: Tableau Rational-    (ret,result) = primalDualSimplex OptMax example_5_7+  assertAtom solver (LA.fromTerms [(-1,x1), (1,x2), (1,x3), (10,x4)] .<=. LA.constant 20)+  assertAtom solver (LA.fromTerms [(1,x1), (-3,x2), (1,x3)] .<=. LA.constant 30)+  assertAtom solver (LA.fromTerms [(1,x2), (-3.5,x4)] .==. LA.constant 0) +  assertAtom solver (LA.fromTerms [(1,x1)] .>=. LA.constant 0)+  assertAtom solver (LA.fromTerms [(1,x1)] .<=. LA.constant 40)+  assertAtom solver (LA.fromTerms [(1,x2)] .>=. LA.constant 0)+  assertAtom solver (LA.fromTerms [(1,x3)] .>=. LA.constant 0)+  assertAtom solver (LA.fromTerms [(1,x4)] .>=. LA.constant 2)+  assertAtom solver (LA.fromTerms [(1,x4)] .<=. LA.constant 3)++  ret1 <- check solver+  ret1 @?= True++  ret2 <- optimize solver def+  ret2 @?= Optimum++{-+http://www.math.cuhk.edu.hk/~wei/lpch5.pdf+example 5.7++minimize 3 x1 + 4 x2 + 5 x3+subject to +1 x1 + 2 x2 + 3 x3 >= 5+2 x1 + 2 x2 + 1 x3 >= 6++optimal value is 11+-}+case_test6 :: Assertion+case_test6 = do+  solver <- newSolver++  _  <- newVar solver+  x1 <- newVar solver+  x2 <- newVar solver+  x3 <- newVar solver++  assertLower solver x1 0+  assertLower solver x2 0+  assertLower solver x3 0+  assertAtom solver (LA.fromTerms [(1,x1),(2,x2),(3,x3)] .>=. LA.constant 5)+  assertAtom solver (LA.fromTerms [(2,x1),(2,x2),(1,x3)] .>=. LA.constant 6)++  setObj solver (LA.fromTerms [(3,x1),(4,x2),(5,x3)])+  setOptDir solver OptMin+  b <- isOptimal solver+  assertBool "should be optimal" $ b++  ret <- dualSimplex solver def+  ret @?= Optimum++  val <- getObjValue solver+  val @?= 11++{-+http://www.math.cuhk.edu.hk/~wei/lpch5.pdf+example 5.7++maximize -3 x1 -4 x2 -5 x3+subject to +-1 x1 -2 x2 -3 x3 <= -5+-2 x1 -2 x2 -1 x3 <= -6++optimal value should be -11+-}+case_test7 :: Assertion+case_test7 = do+  solver <- newSolver++  _  <- newVar solver+  x1 <- newVar solver+  x2 <- newVar solver+  x3 <- newVar solver++  assertLower solver x1 0+  assertLower solver x2 0+  assertLower solver x3 0+  assertAtom solver (LA.fromTerms [(-1,x1),(-2,x2),(-3,x3)] .<=. LA.constant (-5))+  assertAtom solver (LA.fromTerms [(-2,x1),(-2,x2),(-1,x3)] .<=. LA.constant (-6))++  setObj solver (LA.fromTerms [(-3,x1),(-4,x2),(-5,x3)])+  setOptDir solver OptMax+  b <- isOptimal solver+  assertBool "should be optimal" $ b++  ret <- dualSimplex solver def+  ret @?= Optimum++  val <- getObjValue solver+  val @?= -11++case_AssertAtom :: Assertion+case_AssertAtom = do+  solver <- newSolver+  x0 <- newVar solver+  assertAtom solver (LA.constant 1 .<=. LA.var x0)+  ret <- getLB solver x0+  boundValue ret @?= Just 1++  solver <- newSolver+  x0 <- newVar solver+  assertAtom solver (LA.var x0 .>=. LA.constant 1)+  ret <- getLB solver x0+  boundValue ret @?= Just 1++  solver <- newSolver+  x0 <- newVar solver+  assertAtom solver (LA.constant 1 .>=. LA.var x0)+  ret <- getUB solver x0+  boundValue ret @?= Just 1++  solver <- newSolver+  x0 <- newVar solver+  assertAtom solver (LA.var x0 .<=. LA.constant 1)+  ret <- getUB solver x0+  boundValue ret @?= Just 1+ ------------------------------------------------------------------------ -case_lp_example_5_7_twoPhaseSimplex :: Assertion-case_lp_example_5_7_twoPhaseSimplex = do  -  ret @?= LP.Optimum-  oval @?= -11-  assertBool "invalid tableau" (isValidTableau tbl)-  assertBool "infeasible tableau" (isFeasible tbl)-  assertBool "non-optimal tableau" (isOptimal OptMax tbl)-  where-    oval :: Rational-    ((ret,tbl,oval),result) = flip runState (LP.emptySolver IntSet.empty) $ do-      _ <- LP.newVar-      x1 <- LP.newVar -      x2 <- LP.newVar-      x3 <- LP.newVar-      LP.addConstraint (LA.fromTerms [(-1,x1),(-2,x2),(-3,x3)] .<=. LA.constant (-5))-      LP.addConstraint (LA.fromTerms [(-2,x1),(-2,x2),(-1,x3)] .<=. LA.constant (-6))-      let obj = LA.fromTerms [(-3,x1), (-4,x2),(-5,x3)]-      ret <- LP.twoPhaseSimplex OptMax obj-      tbl <- LP.getTableau-      m <- LP.getModel (IntSet.fromList [x1,x2,x3])-      let oval = LA.evalExpr m obj-      return (ret,tbl,oval)+case_example_3_2 = do+  solver <- newSolver+  [x1,x2,x3] <- replicateM 3 (newVar solver)+  setOptDir solver OptMax+  setObj solver $ LA.fromTerms [(3,x1), (2,x2), (3,x3)]+  mapM_ (assertAtom solver) $+    [ LA.fromTerms [(2,x1), (1,x2), (1,x3)] .<=. LA.constant 2+    , LA.fromTerms [(1,x1), (2,x2), (3,x3)] .<=. LA.constant 5+    , LA.fromTerms [(2,x1), (2,x2), (1,x3)] .<=. LA.constant 6+    , LA.var x1 .>=. LA.constant 0+    , LA.var x2 .>=. LA.constant 0+    , LA.var x3 .>=. LA.constant 0+    ] -case_lp_example_5_7_primalDualSimplex :: Assertion-case_lp_example_5_7_primalDualSimplex = do  -  ret @?= LP.Optimum-  oval @?= -11-  assertBool "invalid tableau" (isValidTableau tbl)-  assertBool "infeasible tableau" (isFeasible tbl)-  assertBool "non-optimal tableau" (isOptimal OptMax tbl)-  where-    oval :: Rational-    ((ret,tbl,oval),result) = flip runState (LP.emptySolver IntSet.empty) $ do-      _ <- LP.newVar-      x1 <- LP.newVar -      x2 <- LP.newVar-      x3 <- LP.newVar-      LP.addConstraint (LA.fromTerms [(-1,x1),(-2,x2),(-3,x3)] .<=. LA.constant (-5))-      LP.addConstraint (LA.fromTerms [(-2,x1),(-2,x2),(-1,x3)] .<=. LA.constant (-6))-      let obj = LA.fromTerms [(-3,x1), (-4,x2),(-5,x3)]-      ret <- LP.primalDualSimplex OptMax obj-      tbl <- LP.getTableau-      m <- LP.getModel (IntSet.fromList [x1,x2,x3])-      let oval = LA.evalExpr m obj-      return (ret,tbl,oval)+  ret <- optimize solver def+  ret @?= Optimum+  val <- getObjValue solver+  val @?= 27/5++  forM_ [(x1,1/5),(x2,0),(x3,8/5)] $ \(var,expected) -> do+    val <- getValue solver var+    val @?= expected++case_example_3_5 = do+  solver <- newSolver+  [x1,x2,x3,x4,x5] <- replicateM 5 (newVar solver)+  setOptDir solver OptMin+  setObj solver $ LA.fromTerms [(-2,x1), (4,x2), (7,x3), (1,x4), (5,x5)]+  mapM_ (assertAtom solver) $+    [ LA.fromTerms [(-1,x1), (1,x2), (2,x3), (1,x4), (2,x5)] .==. LA.constant 7+    , LA.fromTerms [(-1,x1), (2,x2), (3,x3), (1,x4), (1,x5)] .==. LA.constant 6+    , LA.fromTerms [(-1,x1), (1,x2), (1,x3), (2,x4), (1,x5)] .==. LA.constant 4+    , LA.var x2 .>=. LA.constant 0+    , LA.var x3 .>=. LA.constant 0+    , LA.var x4 .>=. LA.constant 0+    , LA.var x5 .>=. LA.constant 0+    ]++  ret <- optimize solver def+  ret @?= Optimum+  val <- getObjValue solver+  val @?= 19++  forM_ [(x1,-1),(x2,0),(x3,1),(x4,0),(x5,2)] $ \(var,expected) -> do+    val <- getValue solver var+    val @?= expected++case_example_4_1 = do+  solver <- newSolver+  [x1,x2] <- replicateM 2 (newVar solver)+  setOptDir solver OptMin+  setObj solver $ LA.fromTerms [(2,x1), (1,x2)]+  mapM_ (assertAtom solver) $+    [ LA.fromTerms [(-1,x1), (1,x2)] .>=. LA.constant 2+    , LA.fromTerms [( 1,x1), (1,x2)] .<=. LA.constant 1+    , LA.var x1 .>=. LA.constant 0+    , LA.var x2 .>=. LA.constant 0+    ]+  ret <- optimize solver def+  ret @?= Unsat++case_example_4_2 = do+  solver <- newSolver+  [x1,x2] <- replicateM 2 (newVar solver)+  setOptDir solver OptMax+  setObj solver $ LA.fromTerms [(2,x1), (1,x2)]+  mapM_ (assertAtom solver) $+    [ LA.fromTerms [(-1,x1), (-1,x2)] .<=. LA.constant 10+    , LA.fromTerms [( 2,x1), (-1,x2)] .<=. LA.constant 40+    , LA.var x1 .>=. LA.constant 0+    , LA.var x2 .>=. LA.constant 0+    ]+  ret <- optimize solver def+  ret @?= Unbounded++case_example_4_3 = do+  solver <- newSolver+  [x1,x2] <- replicateM 2 (newVar solver)+  setOptDir solver OptMax+  setObj solver $ LA.fromTerms [(6,x1), (-2,x2)]+  mapM_ (assertAtom solver) $+    [ LA.fromTerms [(2,x1), (-1,x2)] .<=. LA.constant 2+    , LA.var x1 .<=. LA.constant 4+    , LA.var x1 .>=. LA.constant 0+    , LA.var x2 .>=. LA.constant 0+    ]++  ret <- optimize solver def+  ret @?= Optimum+  val <- getObjValue solver+  val @?= 12++  forM_ [(x1,4),(x2,6)] $ \(var,expected) -> do+    val <- getValue solver var+    val @?= expected++case_example_4_5 = do+  solver <- newSolver+  [x1,x2] <- replicateM 2 (newVar solver)+  setOptDir solver OptMax+  setObj solver $ LA.fromTerms [(2,x1), (1,x2)]+  mapM_ (assertAtom solver) $+    [ LA.fromTerms [(4,x1), ( 3,x2)] .<=. LA.constant 12+    , LA.fromTerms [(4,x1), ( 1,x2)] .<=. LA.constant 8+    , LA.fromTerms [(4,x1), (-1,x2)] .<=. LA.constant 8+    , LA.var x1 .>=. LA.constant 0+    , LA.var x2 .>=. LA.constant 0+    ]++  ret <- optimize solver def+  ret @?= Optimum+  val <- getObjValue solver+  val @?= 5++  forM_ [(x1,3/2),(x2,2)] $ \(var,expected) -> do+    val <- getValue solver var+    val @?= expected++case_example_4_6 = do+  solver <- newSolver+  [x1,x2,x3,x4] <- replicateM 4 (newVar solver)+  setOptDir solver OptMax+  setObj solver $ LA.fromTerms [(20,x1), (1/2,x2), (-6,x3), (3/4,x4)]+  mapM_ (assertAtom solver) $+    [ LA.var x1 .<=. LA.constant 2+    , LA.fromTerms [( 8,x1), (  -1,x2), (9,x3), (1/4, x4)] .<=. LA.constant 16+    , LA.fromTerms [(12,x1), (-1/2,x2), (3,x3), (1/2, x4)] .<=. LA.constant 24+    , LA.var x2 .<=. LA.constant 1+    , LA.var x1 .>=. LA.constant 0+    , LA.var x2 .>=. LA.constant 0+    , LA.var x3 .>=. LA.constant 0+    , LA.var x4 .>=. LA.constant 0+    ]++  ret <- optimize solver def+  ret @?= Optimum+  val <- getObjValue solver+  val @?= 165/4++  forM_ [(x1,2),(x2,1),(x3,0),(x4,1)] $ \(var,expected) -> do+    val <- getValue solver var+    val @?= expected++case_example_4_7 = do+  solver <- newSolver+  [x1,x2,x3,x4] <- replicateM 4 (newVar solver)+  setOptDir solver OptMax+  setObj solver $ LA.fromTerms [(1,x1), (1.5,x2), (5,x3), (2,x4)]+  mapM_ (assertAtom solver) $+    [ LA.fromTerms [(3,x1), (2,x2), ( 1,x3), (4,x4)] .<=. LA.constant 6+    , LA.fromTerms [(2,x1), (1,x2), ( 5,x3), (1,x4)] .<=. LA.constant 4+    , LA.fromTerms [(2,x1), (6,x2), (-4,x3), (8,x4)] .==. LA.constant 0+    , LA.fromTerms [(1,x1), (3,x2), (-2,x3), (4,x4)] .==. LA.constant 0+    , LA.var x1 .>=. LA.constant 0+    , LA.var x2 .>=. LA.constant 0+    , LA.var x3 .>=. LA.constant 0+    , LA.var x4 .>=. LA.constant 0+    ]++  ret <- optimize solver def+  ret @?= Optimum+  val <- getObjValue solver+  val @?= 48/11++  forM_ [(x1,0),(x2,0),(x3,8/11),(x4,4/11)] $ \(var,expected) -> do+    val <- getValue solver var+    val @?= expected++-- 退化して巡回の起こるKuhnの7変数3制約の例+case_kuhn_7_3 = do+  solver <- newSolver+  [x1,x2,x3,x4,x5,x6,x7] <- replicateM 7 (newVar solver)+  setOptDir solver OptMin+  setObj solver $ LA.fromTerms [(-2,x4),(-3,x5),(1,x6),(12,x7)]+  mapM_ (assertAtom solver) $+    [ LA.fromTerms [(1,x1), ( -2,x4), (-9,x5), (   1,x6), (  9,x7)] .==. LA.constant 0+    , LA.fromTerms [(1,x2), (1/3,x4), ( 1,x5), (-1/3,x6), ( -2,x7)] .==. LA.constant 0+    , LA.fromTerms [(1,x3), (  2,x4), ( 3,x5), (  -1,x6), (-12,x7)] .==. LA.constant 2+    , LA.var x1 .>=. LA.constant 0+    , LA.var x2 .>=. LA.constant 0+    , LA.var x3 .>=. LA.constant 0+    , LA.var x4 .>=. LA.constant 0+    , LA.var x5 .>=. LA.constant 0+    , LA.var x6 .>=. LA.constant 0+    , LA.var x7 .>=. LA.constant 0+    ]++  ret <- optimize solver def+  ret @?= Optimum+  val <- getObjValue solver+  val @?= -2++  forM_ [(x1,2),(x2,0),(x3,0),(x4,2),(x5,0),(x6,2),(x7,0)] $ \(var,expected) -> do+    val <- getValue solver var+    val @?= expected  ------------------------------------------------------------------------ -- Test harness
− test/Test/Simplex2.hs
@@ -1,408 +0,0 @@-{-# LANGUAGE TemplateHaskell #-}-module Test.Simplex2 (simplex2TestGroup) where--import Control.Monad-import Data.Default.Class-import Data.List-import Data.Ratio-import Data.VectorSpace-import Test.Tasty-import Test.Tasty.HUnit-import Test.Tasty.TH-import Text.Printf-import qualified ToySolver.Data.LA as LA-import ToySolver.Arith.Simplex2--case_test1 :: Assertion-case_test1 = do-  solver <- newSolver-  x <- newVar solver-  y <- newVar solver-  z <- newVar solver-  assertAtom solver (LA.fromTerms [(7,x), (12,y), (31,z)] .==. LA.constant 17)-  assertAtom solver (LA.fromTerms [(3,x), (5,y), (14,z)]  .==. LA.constant 7)-  assertAtom solver (LA.var x .>=. LA.constant 1)-  assertAtom solver (LA.var x .<=. LA.constant 40)-  assertAtom solver (LA.var y .>=. LA.constant (-50))-  assertAtom solver (LA.var y .<=. LA.constant 50)--  ret <- check solver-  ret @?= True--  vx <- getValue solver x-  vy <- getValue solver y-  vz <- getValue solver z-  7*vx + 12*vy + 31*vz @?= 17-  3*vx + 5*vy + 14*vz @?= 7-  assertBool (printf "vx should be >=1 but %s"   (show vx)) $ vx >= 1-  assertBool (printf "vx should be <=40 but %s"  (show vx)) $ vx <= 40-  assertBool (printf "vx should be >=-50 but %s" (show vy)) $ vy >= -50-  assertBool (printf "vx should be <=50 but %s"  (show vy)) $ vy <= 50--case_test2 :: Assertion-case_test2 = do-  solver <- newSolver-  x <- newVar solver-  y <- newVar solver-  assertAtom solver (LA.fromTerms [(11,x), (13,y)] .>=. LA.constant 27)-  assertAtom solver (LA.fromTerms [(11,x), (13,y)] .<=. LA.constant 45)-  assertAtom solver (LA.fromTerms [(7,x), (-9,y)] .>=. LA.constant (-10))-  assertAtom solver (LA.fromTerms [(7,x), (-9,y)] .<=. LA.constant 4)--  ret <- check solver-  ret @?= True--  vx <- getValue solver x-  vy <- getValue solver y-  let v1 = 11*vx + 13*vy-      v2 = 7*vx - 9*vy-  assertBool (printf "11*vx + 13*vy should be >=27 but %s" (show v1)) $ 27 <= v1-  assertBool (printf "11*vx + 13*vy should be <=45 but %s" (show v1)) $ v1 <= 45-  assertBool (printf "7*vx - 9*vy should be >=-10 but %s" (show v2)) $ -10 <= v2-  assertBool (printf "7*vx - 9*vy should be >=-10 but %s" (show v2)) $ v2 <= 4---{--Minimize- obj: - x1 - 2 x2 - 3 x3 - x4-Subject To- c1: - x1 + x2 + x3 + 10 x4 <= 20- c2: x1 - 3 x2 + x3 <= 30- c3: x2 - 3.5 x4 = 0-Bounds- 0 <= x1 <= 40- 2 <= x4 <= 3-End--}-case_test3 :: Assertion-case_test3 = do-  solver <- newSolver--  _ <- newVar solver-  x1 <- newVar solver-  x2 <- newVar solver-  x3 <- newVar solver-  x4 <- newVar solver--  setObj solver (LA.fromTerms [(-1,x1), (-2,x2), (-3,x3), (-1,x4)])--  assertAtom solver (LA.fromTerms [(-1,x1), (1,x2), (1,x3), (10,x4)] .<=. LA.constant 20)-  assertAtom solver (LA.fromTerms [(1,x1), (-3,x2), (1,x3)] .<=. LA.constant 30)-  assertAtom solver (LA.fromTerms [(1,x2), (-3.5,x4)] .==. LA.constant 0)--  assertAtom solver (LA.fromTerms [(1,x1)] .>=. LA.constant 0)-  assertAtom solver (LA.fromTerms [(1,x1)] .<=. LA.constant 40)-  assertAtom solver (LA.fromTerms [(1,x2)] .>=. LA.constant 0)-  assertAtom solver (LA.fromTerms [(1,x3)] .>=. LA.constant 0)-  assertAtom solver (LA.fromTerms [(1,x4)] .>=. LA.constant 2)-  assertAtom solver (LA.fromTerms [(1,x4)] .<=. LA.constant 3)--  ret1 <- check solver-  ret1 @?= True--  ret2 <- optimize solver def-  ret2 @?= Optimum--{--http://www.math.cuhk.edu.hk/~wei/lpch5.pdf-example 5.7--minimize 3 x1 + 4 x2 + 5 x3-subject to -1 x1 + 2 x2 + 3 x3 >= 5-2 x1 + 2 x2 + 1 x3 >= 6--optimal value is 11--}-case_test6 :: Assertion-case_test6 = do-  solver <- newSolver--  _  <- newVar solver-  x1 <- newVar solver-  x2 <- newVar solver-  x3 <- newVar solver--  assertLower solver x1 0-  assertLower solver x2 0-  assertLower solver x3 0-  assertAtom solver (LA.fromTerms [(1,x1),(2,x2),(3,x3)] .>=. LA.constant 5)-  assertAtom solver (LA.fromTerms [(2,x1),(2,x2),(1,x3)] .>=. LA.constant 6)--  setObj solver (LA.fromTerms [(3,x1),(4,x2),(5,x3)])-  setOptDir solver OptMin-  b <- isOptimal solver-  assertBool "should be optimal" $ b--  ret <- dualSimplex solver def-  ret @?= Optimum--  val <- getObjValue solver-  val @?= 11--{--http://www.math.cuhk.edu.hk/~wei/lpch5.pdf-example 5.7--maximize -3 x1 -4 x2 -5 x3-subject to --1 x1 -2 x2 -3 x3 <= -5--2 x1 -2 x2 -1 x3 <= -6--optimal value should be -11--}-case_test7 :: Assertion-case_test7 = do-  solver <- newSolver--  _  <- newVar solver-  x1 <- newVar solver-  x2 <- newVar solver-  x3 <- newVar solver--  assertLower solver x1 0-  assertLower solver x2 0-  assertLower solver x3 0-  assertAtom solver (LA.fromTerms [(-1,x1),(-2,x2),(-3,x3)] .<=. LA.constant (-5))-  assertAtom solver (LA.fromTerms [(-2,x1),(-2,x2),(-1,x3)] .<=. LA.constant (-6))--  setObj solver (LA.fromTerms [(-3,x1),(-4,x2),(-5,x3)])-  setOptDir solver OptMax-  b <- isOptimal solver-  assertBool "should be optimal" $ b--  ret <- dualSimplex solver def-  ret @?= Optimum--  val <- getObjValue solver-  val @?= -11--case_AssertAtom :: Assertion-case_AssertAtom = do-  solver <- newSolver-  x0 <- newVar solver-  assertAtom solver (LA.constant 1 .<=. LA.var x0)-  ret <- getLB solver x0-  boundValue ret @?= Just 1--  solver <- newSolver-  x0 <- newVar solver-  assertAtom solver (LA.var x0 .>=. LA.constant 1)-  ret <- getLB solver x0-  boundValue ret @?= Just 1--  solver <- newSolver-  x0 <- newVar solver-  assertAtom solver (LA.constant 1 .>=. LA.var x0)-  ret <- getUB solver x0-  boundValue ret @?= Just 1--  solver <- newSolver-  x0 <- newVar solver-  assertAtom solver (LA.var x0 .<=. LA.constant 1)-  ret <- getUB solver x0-  boundValue ret @?= Just 1----------------------------------------------------------------------------case_example_3_2 = do-  solver <- newSolver-  [x1,x2,x3] <- replicateM 3 (newVar solver)-  setOptDir solver OptMax-  setObj solver $ LA.fromTerms [(3,x1), (2,x2), (3,x3)]-  mapM_ (assertAtom solver) $-    [ LA.fromTerms [(2,x1), (1,x2), (1,x3)] .<=. LA.constant 2-    , LA.fromTerms [(1,x1), (2,x2), (3,x3)] .<=. LA.constant 5-    , LA.fromTerms [(2,x1), (2,x2), (1,x3)] .<=. LA.constant 6-    , LA.var x1 .>=. LA.constant 0-    , LA.var x2 .>=. LA.constant 0-    , LA.var x3 .>=. LA.constant 0-    ]--  ret <- optimize solver def-  ret @?= Optimum-  val <- getObjValue solver-  val @?= 27/5--  forM_ [(x1,1/5),(x2,0),(x3,8/5)] $ \(var,expected) -> do-    val <- getValue solver var-    val @?= expected--case_example_3_5 = do-  solver <- newSolver-  [x1,x2,x3,x4,x5] <- replicateM 5 (newVar solver)-  setOptDir solver OptMin-  setObj solver $ LA.fromTerms [(-2,x1), (4,x2), (7,x3), (1,x4), (5,x5)]-  mapM_ (assertAtom solver) $-    [ LA.fromTerms [(-1,x1), (1,x2), (2,x3), (1,x4), (2,x5)] .==. LA.constant 7-    , LA.fromTerms [(-1,x1), (2,x2), (3,x3), (1,x4), (1,x5)] .==. LA.constant 6-    , LA.fromTerms [(-1,x1), (1,x2), (1,x3), (2,x4), (1,x5)] .==. LA.constant 4-    , LA.var x2 .>=. LA.constant 0-    , LA.var x3 .>=. LA.constant 0-    , LA.var x4 .>=. LA.constant 0-    , LA.var x5 .>=. LA.constant 0-    ]--  ret <- optimize solver def-  ret @?= Optimum-  val <- getObjValue solver-  val @?= 19--  forM_ [(x1,-1),(x2,0),(x3,1),(x4,0),(x5,2)] $ \(var,expected) -> do-    val <- getValue solver var-    val @?= expected--case_example_4_1 = do-  solver <- newSolver-  [x1,x2] <- replicateM 2 (newVar solver)-  setOptDir solver OptMin-  setObj solver $ LA.fromTerms [(2,x1), (1,x2)]-  mapM_ (assertAtom solver) $-    [ LA.fromTerms [(-1,x1), (1,x2)] .>=. LA.constant 2-    , LA.fromTerms [( 1,x1), (1,x2)] .<=. LA.constant 1-    , LA.var x1 .>=. LA.constant 0-    , LA.var x2 .>=. LA.constant 0-    ]-  ret <- optimize solver def-  ret @?= Unsat--case_example_4_2 = do-  solver <- newSolver-  [x1,x2] <- replicateM 2 (newVar solver)-  setOptDir solver OptMax-  setObj solver $ LA.fromTerms [(2,x1), (1,x2)]-  mapM_ (assertAtom solver) $-    [ LA.fromTerms [(-1,x1), (-1,x2)] .<=. LA.constant 10-    , LA.fromTerms [( 2,x1), (-1,x2)] .<=. LA.constant 40-    , LA.var x1 .>=. LA.constant 0-    , LA.var x2 .>=. LA.constant 0-    ]-  ret <- optimize solver def-  ret @?= Unbounded--case_example_4_3 = do-  solver <- newSolver-  [x1,x2] <- replicateM 2 (newVar solver)-  setOptDir solver OptMax-  setObj solver $ LA.fromTerms [(6,x1), (-2,x2)]-  mapM_ (assertAtom solver) $-    [ LA.fromTerms [(2,x1), (-1,x2)] .<=. LA.constant 2-    , LA.var x1 .<=. LA.constant 4-    , LA.var x1 .>=. LA.constant 0-    , LA.var x2 .>=. LA.constant 0-    ]--  ret <- optimize solver def-  ret @?= Optimum-  val <- getObjValue solver-  val @?= 12--  forM_ [(x1,4),(x2,6)] $ \(var,expected) -> do-    val <- getValue solver var-    val @?= expected--case_example_4_5 = do-  solver <- newSolver-  [x1,x2] <- replicateM 2 (newVar solver)-  setOptDir solver OptMax-  setObj solver $ LA.fromTerms [(2,x1), (1,x2)]-  mapM_ (assertAtom solver) $-    [ LA.fromTerms [(4,x1), ( 3,x2)] .<=. LA.constant 12-    , LA.fromTerms [(4,x1), ( 1,x2)] .<=. LA.constant 8-    , LA.fromTerms [(4,x1), (-1,x2)] .<=. LA.constant 8-    , LA.var x1 .>=. LA.constant 0-    , LA.var x2 .>=. LA.constant 0-    ]--  ret <- optimize solver def-  ret @?= Optimum-  val <- getObjValue solver-  val @?= 5--  forM_ [(x1,3/2),(x2,2)] $ \(var,expected) -> do-    val <- getValue solver var-    val @?= expected--case_example_4_6 = do-  solver <- newSolver-  [x1,x2,x3,x4] <- replicateM 4 (newVar solver)-  setOptDir solver OptMax-  setObj solver $ LA.fromTerms [(20,x1), (1/2,x2), (-6,x3), (3/4,x4)]-  mapM_ (assertAtom solver) $-    [ LA.var x1 .<=. LA.constant 2-    , LA.fromTerms [( 8,x1), (  -1,x2), (9,x3), (1/4, x4)] .<=. LA.constant 16-    , LA.fromTerms [(12,x1), (-1/2,x2), (3,x3), (1/2, x4)] .<=. LA.constant 24-    , LA.var x2 .<=. LA.constant 1-    , LA.var x1 .>=. LA.constant 0-    , LA.var x2 .>=. LA.constant 0-    , LA.var x3 .>=. LA.constant 0-    , LA.var x4 .>=. LA.constant 0-    ]--  ret <- optimize solver def-  ret @?= Optimum-  val <- getObjValue solver-  val @?= 165/4--  forM_ [(x1,2),(x2,1),(x3,0),(x4,1)] $ \(var,expected) -> do-    val <- getValue solver var-    val @?= expected--case_example_4_7 = do-  solver <- newSolver-  [x1,x2,x3,x4] <- replicateM 4 (newVar solver)-  setOptDir solver OptMax-  setObj solver $ LA.fromTerms [(1,x1), (1.5,x2), (5,x3), (2,x4)]-  mapM_ (assertAtom solver) $-    [ LA.fromTerms [(3,x1), (2,x2), ( 1,x3), (4,x4)] .<=. LA.constant 6-    , LA.fromTerms [(2,x1), (1,x2), ( 5,x3), (1,x4)] .<=. LA.constant 4-    , LA.fromTerms [(2,x1), (6,x2), (-4,x3), (8,x4)] .==. LA.constant 0-    , LA.fromTerms [(1,x1), (3,x2), (-2,x3), (4,x4)] .==. LA.constant 0-    , LA.var x1 .>=. LA.constant 0-    , LA.var x2 .>=. LA.constant 0-    , LA.var x3 .>=. LA.constant 0-    , LA.var x4 .>=. LA.constant 0-    ]--  ret <- optimize solver def-  ret @?= Optimum-  val <- getObjValue solver-  val @?= 48/11--  forM_ [(x1,0),(x2,0),(x3,8/11),(x4,4/11)] $ \(var,expected) -> do-    val <- getValue solver var-    val @?= expected---- 退化して巡回の起こるKuhnの7変数3制約の例-case_kuhn_7_3 = do-  solver <- newSolver-  [x1,x2,x3,x4,x5,x6,x7] <- replicateM 7 (newVar solver)-  setOptDir solver OptMin-  setObj solver $ LA.fromTerms [(-2,x4),(-3,x5),(1,x6),(12,x7)]-  mapM_ (assertAtom solver) $-    [ LA.fromTerms [(1,x1), ( -2,x4), (-9,x5), (   1,x6), (  9,x7)] .==. LA.constant 0-    , LA.fromTerms [(1,x2), (1/3,x4), ( 1,x5), (-1/3,x6), ( -2,x7)] .==. LA.constant 0-    , LA.fromTerms [(1,x3), (  2,x4), ( 3,x5), (  -1,x6), (-12,x7)] .==. LA.constant 2-    , LA.var x1 .>=. LA.constant 0-    , LA.var x2 .>=. LA.constant 0-    , LA.var x3 .>=. LA.constant 0-    , LA.var x4 .>=. LA.constant 0-    , LA.var x5 .>=. LA.constant 0-    , LA.var x6 .>=. LA.constant 0-    , LA.var x7 .>=. LA.constant 0-    ]--  ret <- optimize solver def-  ret @?= Optimum-  val <- getObjValue solver-  val @?= -2--  forM_ [(x1,2),(x2,0),(x3,0),(x4,2),(x5,0),(x6,2),(x7,0)] $ \(var,expected) -> do-    val <- getValue solver var-    val @?= expected----------------------------------------------------------------------------- Test harness--simplex2TestGroup :: TestTree-simplex2TestGroup = $(testGroupGenerator)
+ test/Test/SimplexTextbook.hs view
@@ -0,0 +1,177 @@+{-# LANGUAGE TemplateHaskell #-}+module Test.SimplexTextbook (simplexTextbookTestGroup) where++import Control.Monad+import Control.Monad.State+import Data.IntMap (IntMap)+import qualified Data.IntMap as IntMap+import Data.IntSet (IntSet)+import qualified Data.IntSet as IntSet+import Data.List+import Data.Ratio+import Test.Tasty+import Test.Tasty.HUnit+import Test.Tasty.TH+import Text.Printf++import qualified ToySolver.Data.LA as LA+import ToySolver.Data.LA ((.<=.))+import ToySolver.Arith.Simplex.Textbook+import qualified ToySolver.Arith.Simplex.Textbook.LPSolver as LP++example_3_2 :: Tableau Rational+example_3_2 = IntMap.fromList+  [ (4, (IntMap.fromList [(1,2), (2,1), (3,1)], 2))+  , (5, (IntMap.fromList [(1,1), (2,2), (3,3)], 5))+  , (6, (IntMap.fromList [(1,2), (2,2), (3,1)], 6))+  , (objRowIndex, (IntMap.fromList [(1,-3), (2,-2), (3,-3)], 0))+  ]++case_example_3_2_simplex :: Assertion+case_example_3_2_simplex = do+  assertBool "simplex failed" ret+  assertBool "invalid tableau" (isValidTableau result)+  assertBool "infeasible tableau" (isFeasible result)+  assertBool "unoptimal tableau" (isOptimal OptMax result)+  currentObjValue result @?= 27/5+  where+    ret :: Bool+    result :: Tableau Rational+    (ret,result) = simplex OptMax example_3_2++case_example_3_2_primalDualSimplex :: Assertion+case_example_3_2_primalDualSimplex = do+  assertBool "simplex failed" ret+  assertBool "invalid tableau" (isValidTableau result)+  assertBool "infeasible tableau" (isFeasible result)+  assertBool "unoptimal tableau" (isOptimal OptMax result)+  currentObjValue result @?= 27/5+  where+    ret :: Bool+    result :: Tableau Rational+    (ret,result) = primalDualSimplex OptMax example_3_2++-- from http://www.math.cuhk.edu.hk/~wei/lpch5.pdf+example_5_3_phase1 :: Tableau Rational+example_5_3_phase1 = IntMap.fromList+  [ (6, (IntMap.fromList [(2,-1), (3,-1), (5,1)], 1))+  , (7, (IntMap.fromList [(3,1), (4,-1), (5,1)], 0))+  ]++case_example_5_3_phase1 :: Assertion+case_example_5_3_phase1 = do+  let (ret,result) = phaseI example_5_3_phase1 (IntSet.fromList [6,7])+  assertBool "phase1 failed" ret+  assertBool "invalid tableau" (isValidTableau result)+  assertBool "infeasible tableau" (isFeasible result)    ++-- 退化して巡回の起こるKuhnの7変数3制約の例+kuhn_7_3 :: Tableau Rational+kuhn_7_3 = IntMap.fromList+  [ (1, (IntMap.fromList [(4,-2), (5,-9), (6,1), (7,9)],       0))+  , (2, (IntMap.fromList [(4,1/3), (5,1), (6,-1/3), (7,-2)],   0))+  , (3, (IntMap.fromList [(4,2), (5,3), (6,-1), (7,-12)],      2))+  , (objRowIndex, (IntMap.fromList [(4,2), (5,3), (6,-1), (7,-12)], 0))+  ]++case_kuhn_7_3 :: Assertion+case_kuhn_7_3 = do+  assertBool "simplex failed" ret+  assertBool "invalid tableau" (isValidTableau result)+  currentObjValue result @?= -2+  where+    ret :: Bool+    result :: Tableau Rational+    (ret,result) = simplex OptMin kuhn_7_3++-- case_pd_kuhn_7_3 :: Assertion+-- case_pd_kuhn_7_3 = do+--   assertBool "simplex failed" ret+--   assertBool "invalid tableau" (isValidTableau result)+--   currentObjValue result @?= -2+--   where+--     ret :: Bool+--     result :: Tableau Rational+--     (ret,result) = primalDualSimplex OptMin kuhn_7_3++-- from http://www.math.cuhk.edu.hk/~wei/lpch5.pdf+example_5_7 :: Tableau Rational+example_5_7 = IntMap.fromList+  [ (4, (IntMap.fromList [(1,-1), (2,-2), (3,-3)], -5))+  , (5, (IntMap.fromList [(1,-2), (2,-2), (3,-1)], -6))+  , (objRowIndex, (IntMap.fromList [(1,3),(2,4),(3,5)], 0))+  ]++case_example_5_7 :: Assertion+case_example_5_7 = do+  assertBool "dual simplex failed" ret+  assertBool "invalid tableau" (isValidTableau result)+  currentObjValue result @?= -11+  where+    ret :: Bool+    result :: Tableau Rational+    (ret,result) = dualSimplex OptMax example_5_7++case_pd_example_5_7 :: Assertion+case_pd_example_5_7 = do+  assertBool "dual simplex failed" ret+  assertBool "invalid tableau" (isValidTableau result)+  currentObjValue result @?= -11+  where+    ret :: Bool+    result :: Tableau Rational+    (ret,result) = primalDualSimplex OptMax example_5_7++------------------------------------------------------------------------++case_lp_example_5_7_twoPhaseSimplex :: Assertion+case_lp_example_5_7_twoPhaseSimplex = do  +  ret @?= LP.Optimum+  oval @?= -11+  assertBool "invalid tableau" (isValidTableau tbl)+  assertBool "infeasible tableau" (isFeasible tbl)+  assertBool "non-optimal tableau" (isOptimal OptMax tbl)+  where+    oval :: Rational+    ((ret,tbl,oval),result) = flip runState (LP.emptySolver IntSet.empty) $ do+      _ <- LP.newVar+      x1 <- LP.newVar +      x2 <- LP.newVar+      x3 <- LP.newVar+      LP.addConstraint (LA.fromTerms [(-1,x1),(-2,x2),(-3,x3)] .<=. LA.constant (-5))+      LP.addConstraint (LA.fromTerms [(-2,x1),(-2,x2),(-1,x3)] .<=. LA.constant (-6))+      let obj = LA.fromTerms [(-3,x1), (-4,x2),(-5,x3)]+      ret <- LP.twoPhaseSimplex OptMax obj+      tbl <- LP.getTableau+      m <- LP.getModel (IntSet.fromList [x1,x2,x3])+      let oval = LA.eval m obj+      return (ret,tbl,oval)++case_lp_example_5_7_primalDualSimplex :: Assertion+case_lp_example_5_7_primalDualSimplex = do  +  ret @?= LP.Optimum+  oval @?= -11+  assertBool "invalid tableau" (isValidTableau tbl)+  assertBool "infeasible tableau" (isFeasible tbl)+  assertBool "non-optimal tableau" (isOptimal OptMax tbl)+  where+    oval :: Rational+    ((ret,tbl,oval),result) = flip runState (LP.emptySolver IntSet.empty) $ do+      _ <- LP.newVar+      x1 <- LP.newVar +      x2 <- LP.newVar+      x3 <- LP.newVar+      LP.addConstraint (LA.fromTerms [(-1,x1),(-2,x2),(-3,x3)] .<=. LA.constant (-5))+      LP.addConstraint (LA.fromTerms [(-2,x1),(-2,x2),(-1,x3)] .<=. LA.constant (-6))+      let obj = LA.fromTerms [(-3,x1), (-4,x2),(-5,x3)]+      ret <- LP.primalDualSimplex OptMax obj+      tbl <- LP.getTableau+      m <- LP.getModel (IntSet.fromList [x1,x2,x3])+      let oval = LA.eval m obj+      return (ret,tbl,oval)++------------------------------------------------------------------------+-- Test harness++simplexTextbookTestGroup :: TestTree+simplexTextbookTestGroup = $(testGroupGenerator)
+ test/Test/Smtlib.hs view
@@ -0,0 +1,605 @@+{-# OPTIONS_GHC -Wall -fno-warn-orphans #-}+{-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-}+module Test.Smtlib (smtlibTestGroup) where++import Control.Applicative+import Control.DeepSeq+import Control.Monad+import qualified Data.Set as Set++import Test.Tasty+import Test.Tasty.QuickCheck hiding (Success)+import Test.Tasty.HUnit+import Test.Tasty.TH++import Smtlib.Syntax.Syntax+import Smtlib.Syntax.ShowSL+import Smtlib.Parsers.CommonParsers+import Smtlib.Parsers.CommandsParsers+import Smtlib.Parsers.ResponseParsers+import Text.Parsec (parse, ParseError)++import Debug.Trace++prop_parseTerm :: Property+prop_parseTerm = forAll arbitrary $ \(t :: Term) ->+  parse parseTerm "" (showSL t) == Right t++prop_parseAttribute :: Property+prop_parseAttribute = forAll arbitrary $ \a ->+  parse parseAttribute "" (showSL a) == Right a++prop_parseSort :: Property+prop_parseSort = forAll arbitrary $ \s ->+  parse parseSort "" (showSL s) == Right s++prop_parseIdentifier :: Property+prop_parseIdentifier = forAll arbitrary $ \a ->+  parse parseIdentifier "" (showSL a) == Right a++prop_parseSexpr :: Property+prop_parseSexpr = forAll arbitrary $ \a ->+  parse parseSexpr "" (showSL a) == Right a++prop_parseSpecConstant :: Property+prop_parseSpecConstant = forAll arbitrary $ \a ->+  parse parseSpecConstant "" (showSL a) == Right a++prop_parseSource :: Property+prop_parseSource = forAll arbitrary $ \a ->+  parse parseSource "" (joinA a) == Right a++prop_parseCommand :: Property+prop_parseCommand = forAll arbitrary $ \a ->+  parse parseCommand "" (showSL a) == Right a++prop_parseOption :: Property+prop_parseOption = forAll arbitrary $ \a ->+  parse parseOption "" (showSL a) == Right a++prop_parseInfoFlags :: Property+prop_parseInfoFlags = forAll arbitrary $ \a ->+  parse parseOption "" (showSL a) == Right a++prop_parseCmdResult :: Property+prop_parseCmdResult = forAll arbitrary $ \(a :: CmdResponse) ->+  case parse parseCmdResult "" (showSL a) of+    Left err -> error (show err)+    Right a' -> parse parseCmdResult "" (showSL a') == Right a'++prop_parseGenResponse :: Property+prop_parseGenResponse = forAll arbitrary $ \a ->+  parse parseGenResponse "" (showSL a) == Right a++prop_parseGetInfoResponse :: Property+prop_parseGetInfoResponse = forAll arbitrary $ \a ->  +  parse parseGetInfoResponse "" ("(" ++ joinA a ++ ")") == Right a++prop_parseCheckSatResponse :: Property+prop_parseCheckSatResponse = forAll arbitrary $ \a ->+  parse parseCheckSatResponse "" (showSL a) == Right a++prop_parseGetAssertionsResponse :: Property+prop_parseGetAssertionsResponse = forAll genGetAssertionsResponse $ \a ->+  parse parseGetAssertionsResponse "" ("(" ++ joinA a ++ ")") == Right a++prop_parseGetAssignmentResp :: Property+prop_parseGetAssignmentResp = forAll arbitrary $ \a ->+  parse parseGetAssignmentResp "" ("(" ++ joinA a ++ ")") == Right a++prop_parseGetProofResponse :: Property+prop_parseGetProofResponse = forAll arbitrary $ \a ->+  parse parseGetProofResponse "" (showSL a) == Right a++prop_parseGetUnsatCoreResp :: Property+prop_parseGetUnsatCoreResp = forAll genGetUnsatCoreResponse $ \a ->+  parse parseGetUnsatCoreResp "" ("(" ++ unwords (fmap showSymbol a) ++ ")") == Right a++prop_parseGetUnsatAssumptionsResp :: Property+prop_parseGetUnsatAssumptionsResp = forAll (listOf' genSymbol) $ \a ->+  parse parseGetUnsatCoreResp "" ("(" ++ unwords (fmap showSymbol a) ++ ")") == Right a++prop_parseGetValueResponse :: Property+prop_parseGetValueResponse = forAll genGetValueResponse $ \a ->+  parse parseGetValueResponse "" ("(" ++ joinA a ++ ")") == Right a++prop_parseGetModelResponse :: Property+prop_parseGetModelResponse = forAll genGetModelResponse $ \a ->+  parse parseGetModelResponse "" ("(" ++ joinA a ++ ")") == Right a++prop_parseGetOptionResponse :: Property+prop_parseGetOptionResponse = forAll arbitrary $ \a ->+  parse parseGetOptionResponse "" (showSL a) == Right a++prop_parseEchoResponse :: Property+prop_parseEchoResponse = forAll genEchoResponse $ \a ->+  parse parseEchoResponse "" a == Right a++case_bug_1 :: Assertion+case_bug_1 = do+  parse parseSort "" "(_a b)" @?= Right (SortIdentifiers (ISymbol "_a") [SortId (ISymbol "b")])+  parse parseTerm "" "(_a b)" @?= Right (TermQualIdentifierT (QIdentifier (ISymbol "_a")) [TermQualIdentifier (QIdentifier (ISymbol "b"))])++case_bug_2 :: Assertion+case_bug_2 = do+  parse parseTerm "" "(asX b)" @?= Right (TermQualIdentifierT (QIdentifier (ISymbol "asX")) [TermQualIdentifier (QIdentifier (ISymbol "b"))])++case_parse_string_literal_ascii :: Assertion+case_parse_string_literal_ascii = parse str "" s @?= Right s+  where+    s = showStringLiteral $ ['\t','\n','\r'] ++ [toEnum 32 .. toEnum 126]++prop_parse_string_literal :: Property+prop_parse_string_literal =+  forAll genStringLiteral $  \s ->+    parse str "" s == Right s++case_parseSexprKeyword_bug :: Assertion+case_parseSexprKeyword_bug = +  parse parseSexprKeyword "" ":keyword" @?= Right (SexprKeyword ":keyword")++case_parseHexadecimal :: Assertion+case_parseHexadecimal = parse parseHexadecimal "" (showSL s) @?= Right s+  where+    s = SpecConstantHexadecimal "afbf00"++case_parseBinary :: Assertion+case_parseBinary = parse parseBinary "" (showSL s) @?= Right s+  where+    s = SpecConstantBinary "011001"++case_comment :: Assertion+case_comment = do+  parse parseTerm "" "(f ; hogehoge\na;bbb\n)" @?=+    Right (TermQualIdentifierT (QIdentifier (ISymbol "f")) [TermQualIdentifier (QIdentifier (ISymbol "a"))])++-- ---------------------------------------------------------------------++prop_Command_show :: Property+prop_Command_show = forAll arbitrary $ \(a :: Command) ->+  show a `deepseq` True++prop_Option_show :: Property+prop_Option_show = forAll arbitrary $ \(a :: Option) ->+  show a `deepseq` True++prop_InfoFlags_show :: Property+prop_InfoFlags_show = forAll arbitrary $ \(a :: InfoFlags) ->+  show a `deepseq` True++prop_Term_show :: Property+prop_Term_show = forAll arbitrary $ \(a :: Term) ->+  show a `deepseq` True++prop_VarBinding_show :: Property+prop_VarBinding_show = forAll arbitrary $ \(a :: VarBinding) ->+  show a `deepseq` True++prop_SortedVar_show :: Property+prop_SortedVar_show = forAll arbitrary $ \(a :: VarBinding) ->+  show a `deepseq` True++prop_QualIdentifier_show :: Property+prop_QualIdentifier_show = forAll arbitrary $ \(a :: QualIdentifier) ->+  show a `deepseq` True++prop_FunDec_show :: Property+prop_FunDec_show = forAll arbitrary $ \(a :: FunDec) ->+  show a `deepseq` True++prop_AttrValue_show :: Property+prop_AttrValue_show = forAll arbitrary $ \(a :: AttrValue) ->+  show a `deepseq` True++prop_Attribute_show :: Property+prop_Attribute_show = forAll arbitrary $ \(a :: Attribute) ->+  show a `deepseq` True++prop_Index_show :: Property+prop_Index_show = forAll arbitrary $ \(a :: Index) ->+  show a `deepseq` True++prop_Identifier_show :: Property+prop_Identifier_show = forAll arbitrary $ \(a :: Identifier) ->+  show a `deepseq` True++prop_Sort_show :: Property+prop_Sort_show = forAll arbitrary $ \(a :: Sort) ->+  show a `deepseq` True++prop_SpecConstant_show :: Property+prop_SpecConstant_show = forAll arbitrary $ \(a :: SpecConstant) ->+  show a `deepseq` True++prop_Sexpr_show :: Property+prop_Sexpr_show = forAll arbitrary $ \(a :: Sexpr) ->+  show a `deepseq` True++prop_CmdResponse_show :: Property+prop_CmdResponse_show = forAll arbitrary $ \(a :: CmdResponse) ->+  show a `deepseq` True++prop_GenResponse_show :: Property+prop_GenResponse_show = forAll arbitrary $ \(a :: GenResponse) ->+  show a `deepseq` True++prop_ErrorBehavior_show :: Property+prop_ErrorBehavior_show = forAll arbitrary $ \(a :: ErrorBehavior) ->+  show a `deepseq` True++prop_ReasonUnknown_show :: Property+prop_ReasonUnknown_show = forAll arbitrary $ \(a :: ReasonUnknown) ->+  show a `deepseq` True++prop_CheckSatResponse_show :: Property+prop_CheckSatResponse_show = forAll arbitrary $ \(a :: CheckSatResponse) ->+  show a `deepseq` True++prop_InfoResponse_show :: Property+prop_InfoResponse_show = forAll arbitrary $ \(a :: InfoResponse) ->+  show a `deepseq` True++prop_ValuationPair_show :: Property+prop_ValuationPair_show = forAll arbitrary $ \(a :: ValuationPair) ->+  show a `deepseq` True++prop_TValuationPair_show :: Property+prop_TValuationPair_show = forAll arbitrary $ \(a :: TValuationPair) ->+  show a `deepseq` True++-- ---------------------------------------------------------------------++instance Arbitrary Term where+  arbitrary = sized $ \n -> oneof $+    [ TermSpecConstant <$> arbitrary+    , TermQualIdentifier <$> arbitrary+    ] ++ (if n > 0 then gs else [])+    where+      gs = +        [ liftM2 TermQualIdentifierT arbitrary (listOf1' arbitrary')+        , liftM2 TermLet (listOf1' arbitrary) arbitrary'+        , liftM2 TermForall (listOf1' arbitrary) arbitrary'+        , liftM2 TermExists (listOf1' arbitrary) arbitrary'+        , liftM2 TermAnnot arbitrary' (listOf1' arbitrary)+        ]++instance Arbitrary VarBinding where+  arbitrary = liftM2 VB genSymbol arbitrary'++instance Arbitrary SortedVar where+  arbitrary = liftM2 SV genSymbol arbitrary++instance Arbitrary AttrValue where+  arbitrary = oneof+    [ AttrValueConstant <$> arbitrary+    , AttrValueSymbol <$> genSymbol+    , AttrValueSexpr <$> listOf' arbitrary+    ]+   +instance Arbitrary Attribute where+  arbitrary = oneof+    [ Attribute <$> genKeyword+    , liftM2 AttributeVal genKeyword arbitrary+    ]++instance Arbitrary QualIdentifier where+  arbitrary = oneof+    [ QIdentifier <$> arbitrary+    , liftM2 QIdentifierAs arbitrary arbitrary+    ]+   +instance Arbitrary Index where+  arbitrary = oneof+    [ IndexNumeral <$> abs <$> arbitrary+    , IndexSymbol <$> genSymbol+    ]++instance Arbitrary Identifier where+  arbitrary = oneof+    [ ISymbol <$> genSymbol+    , liftM2 I_Symbol genSymbol (listOf1' arbitrary)+    ]++instance Arbitrary Sort where+  arbitrary = oneof+    [ SortId <$> arbitrary+    , liftM2 SortIdentifiers arbitrary (listOf1' arbitrary')+    ]++instance Arbitrary SpecConstant where+  arbitrary = oneof+    [ SpecConstantNumeral <$> abs <$> arbitrary+    , liftM SpecConstantDecimal $ do+        a <- show <$> abs <$> (arbitrary :: Gen Int)+        b <- listOf $ return '0'+        c <- show <$> abs <$> (arbitrary :: Gen Int)+        return $ a ++ "." ++ b ++ c+    , SpecConstantHexadecimal <$> listOf1 (elements (['0'..'9'] ++ ['a'..'f'] ++ ['A'..'F']))+    , SpecConstantBinary <$> listOf1 (elements ['0','1'])+    , liftM SpecConstantString $ do+        let p c = c `elem` ['\t','\n','\r'] || (32 <= fromEnum c && fromEnum c <= 126) || 128 <= fromEnum c+        s <- listOf $ arbitrary `suchThat` p+        return $ "\"" ++ concat [if c == '"' then "\"\"" else [c] | c <- s] ++ "\""+    ]+   +instance Arbitrary Sexpr where+  arbitrary = sized $ \n -> oneof $+    [ SexprSpecConstant <$> arbitrary+    , SexprSymbol <$> genSymbol+    , SexprKeyword <$> genKeyword+    ] +++    [ liftM SexprSxp $ listOf' arbitrary' | n > 0 ]++halve :: Gen a -> Gen a+halve g = sized (\n -> resize (n `div` 2) g)++arbitrary' :: Arbitrary a => Gen a+arbitrary' = halve arbitrary++listOf' :: Gen a -> Gen [a]+listOf' g = do+  n <- frequency [(6, return 0), (3, return 1), (1, return 2)]+  replicateM n g++listOf1' :: Gen a -> Gen [a]+listOf1' g = do+  n <- frequency [(10, return 1), (4, return 2), (1, return 3)]+  replicateM n g++-- ---------------------------------------------------------------------++type Symbol = String++genSymbol :: Gen Symbol+genSymbol = oneof [genSimpleSymbol, genQuotedSymbol]++genSimpleSymbol :: Gen Symbol+genSimpleSymbol = g `suchThat` (`Set.notMember` reserved)+  where+    xs = ['a'..'z']++['A'..'Z']++"~!@$%^&*_-+=<>.?/"+    g = liftM2 (:) (elements xs) (listOf1 $ elements $ ['0'..'9'] ++ xs)+    reserved = Set.fromList $+      ["BINARY", "DECIMAL", "HEXADECIMAL", "NUMERAL", "STRING", "_", "!", "as", "let", "exists", "forall", "par"] +++      ["set-logic", "set-option", "set-info", "declare-sort", "define-sort", "declare-const", "declare-fun", "declare-fun-rec", "declare-funs-rec", "push", "pop", "reset", "reset-assertions", "assert", "check-sat", "check-sat-assuming", "get-assertions", "get-model", "get-proof", "get-unsat-core", "get-unsat-assumptions", "get-value", "get-assignment", "get-option", "get-info", "echo", "exit"]++genQuotedSymbol :: Gen Symbol+genQuotedSymbol = listOf1 g+  where+    g :: Gen Char+    g = oneof [elements (Set.toList xs), choose (toEnum 128, maxBound)]+    xs = Set.fromList (['\t','\n','\r'] ++ [' ' .. toEnum 126]) `Set.difference` Set.fromList ['\\', '|']    ++genKeyword :: Gen String+genKeyword = oneof+  [ (':':) <$> genSimpleSymbol+  , elements+      [ ":print-success"+      , ":expand-definitions"+      , ":interactive-mode"+      , ":produce-proofs"+      , ":produce-unsat-cores"+      , ":produce-unsat-assumptions"+      , ":produce-models"+      , ":produce-assignments"+      , ":produce-assertions"+      , ":global-declarations"+      , ":regular-output-channel"+      , ":diagnostic-output-channel"+      , ":random-seed"+      , ":verbosity"+      , ":reproducible-resource-limit"++      , ":error-behavior"+      , ":name"+      , ":authors"+      , ":version"+      , ":status"+      , ":reason-unknown"+      , ":all-statistics"+      , ":assertion-stack-levels"+      ]+  ]++genStringLiteral :: Gen String+genStringLiteral = showStringLiteral <$> listOf genStringChar++showStringLiteral :: String -> String+showStringLiteral s = "\"" ++ concat [if c == '"' then "\"\"" else [c] | c <- s] ++ "\""++genStringChar :: Gen Char+genStringChar = arbitrary `suchThat` p+   where+    p c = c `elem` ['\t','\n','\r'] || (32 <= fromEnum c && fromEnum c <= 126) || 128 <= fromEnum c++-- ---------------------------------------------------------------------++instance Arbitrary Command where+  arbitrary = oneof+    [ SetLogic <$> genSymbol+    , SetOption <$> arbitrary+    , SetInfo <$> arbitrary+    , DeclareSort <$> genSymbol <*> (abs <$> arbitrary)+    , DefineSort <$> genSymbol <*> listOf' genSymbol <*> arbitrary+    , DeclareConst <$> genSymbol <*> arbitrary+    , DeclareFun <$> genSymbol <*> listOf' arbitrary <*> arbitrary+    , DefineFun <$> genSymbol <*> listOf' arbitrary <*> arbitrary <*> arbitrary+    , DefineFunRec <$> genSymbol <*> listOf' arbitrary <*> arbitrary <*> arbitrary+    , DefineFunsRec <$> listOf1' arbitrary <*> listOf1' arbitrary+    , Push <$> (abs <$> arbitrary)+    , Pop <$> (abs <$> arbitrary)+    , return Reset+    , return ResetAssertions+    , Assert <$> arbitrary+    , return CheckSat+    , CheckSatAssuming <$> listOf' arbitrary+    , return GetAssertions+    , return GetModel+    , return GetProof+    , return GetUnsatCore+    , return GetUnsatAssumptions+    , GetValue <$> listOf1' arbitrary+    , return GetAssignment+    , GetOption <$> genKeyword+    , GetInfo <$> arbitrary+    , Echo <$> genStringLiteral+    , return Exit+    ]++instance Arbitrary Option where+  arbitrary = oneof+    [ PrintSuccess <$> arbitrary+    , ExpandDefinitions <$> arbitrary+    , InteractiveMode <$> arbitrary+    , ProduceProofs <$> arbitrary+    , ProduceUnsatCores <$> arbitrary+    , ProduceUnsatAssumptions <$> arbitrary+    , ProduceModels <$> arbitrary+    , ProduceAssignments <$> arbitrary+    , ProduceAssertions <$> arbitrary+    , GlobalDeclarations <$> arbitrary+    , RegularOutputChannel <$> genStringLiteral+    , DiagnosticOutputChannel <$> genStringLiteral+    , RandomSeed <$> (abs <$> arbitrary)+    , Verbosity <$> abs <$> arbitrary+    , ReproducibleResourceLimit <$> abs <$> arbitrary+    , OptionAttr <$> (arbitrary `suchThat` p)+    ]+    where+      p (Attribute kw) = kw `Set.notMember` reserved+      p (AttributeVal kw _) = kw `Set.notMember` reserved+      reserved = Set.fromList+        [ ":print-success"+        , ":expand-definitions"+        , ":interactive-mode"+        , ":produce-proofs"+        , ":produce-unsat-cores"+        , ":produce-unsat-assumptions"+        , ":produce-models"+        , ":produce-assignments"+        , ":produce-assertions"+        , ":global-declarations"+        , ":regular-output-channel"+        , ":diagnostic-output-channel"+        , ":random-seed"+        , ":verbosity"+        , ":reproducible-resource-limit"+        ]++instance Arbitrary InfoFlags where+  arbitrary = oneof+    [ return ErrorBehavior+    , return Name+    , return Authors+    , return Version+    , return Status+    , return ReasonUnknown+    , return AllStatistics+    , return AssertionStackLevels+    , InfoFlags <$> (genKeyword `suchThat` (`Set.notMember` reserved))+    ]+    where+      reserved = Set.fromList+        [ ":error-behavior"+        , ":name"+        , ":authors"+        , ":version"+        , ":status"+        , ":reason-unknown"+        , ":all-statistics"+        , ":assertion-stack-levels"+        ]++instance Arbitrary FunDec where+  arbitrary = FunDec <$> genSymbol <*> listOf' arbitrary <*> arbitrary++-- ---------------------------------------------------------------------++instance Arbitrary CmdResponse where+  arbitrary = oneof+    [ CmdGenResponse <$> arbitrary+    , CmdGetInfoResponse <$> genGetInfoResponse+    , CmdCheckSatResponse <$> arbitrary+    , CmdGetAssertionsResponse <$> genGetAssertionsResponse+    , CmdGetAssignmentResponse <$> arbitrary+    , CmdGetProofResponse <$> arbitrary+    , CmdGetUnsatCoreResponse <$> genGetUnsatCoreResponse+    , CmdGetUnsatAssumptionsResponse <$> arbitrary+    , CmdGetValueResponse <$> genGetValueResponse+    , CmdGetModelResponse <$> arbitrary+    , CmdGetOptionResponse <$> arbitrary+    , CmdEchoResponse <$> genEchoResponse+    ]++instance Arbitrary GenResponse where+  arbitrary = oneof +    [ return Unsupported+    , return Success+    , Error <$> genStringLiteral+    ]++instance Arbitrary ErrorBehavior where+  arbitrary = elements [ImmediateExit, ContinuedExecution]++instance Arbitrary ReasonUnknown where+  arbitrary = elements [Memout, Incomplete]++instance Arbitrary CheckSatResponse where+  arbitrary = elements [Sat, Unsat, Unknown]++instance Arbitrary InfoResponse where +  arbitrary = oneof+    [ ResponseErrorBehavior <$> arbitrary+    , ResponseName <$> genStringLiteral+    , ResponseAuthors <$> genStringLiteral+    , ResponseVersion <$> genStringLiteral+    , ResponseReasonUnknown <$> arbitrary+    , ResponseAssertionStackLevels <$> abs <$> arbitrary+    , ResponseAttribute <$> (arbitrary `suchThat` p)+    ]+    where+      p (Attribute kw) = kw `Set.notMember` reserved+      p (AttributeVal kw _) = kw `Set.notMember` reserved+      reserved = Set.fromList+        [ ":error-behavior"+        , ":name"+        , ":authors"+        , ":version"+        , ":status"+        , ":reason-unknown"+        , ":all-statistics"+        , ":assertion-stack-levels"+        ]++genGetInfoResponse :: Gen [InfoResponse]+genGetInfoResponse = listOf' arbitrary++genGetAssertionsResponse :: Gen [Term]+genGetAssertionsResponse = listOf' arbitrary++genGetUnsatCoreResponse :: Gen [Symbol]+genGetUnsatCoreResponse = listOf' genSymbol++genGetValueResponse :: Gen [ValuationPair]+genGetValueResponse = listOf' arbitrary++genGetModelResponse :: Gen [Command]+genGetModelResponse = listOf1' $ oneof+  [ DefineFun <$> genSymbol <*> listOf' arbitrary <*> arbitrary <*> arbitrary+  , DefineFunRec <$> genSymbol <*> listOf' arbitrary <*> arbitrary <*> arbitrary+  , DefineFunsRec <$> listOf1' arbitrary <*> listOf1' arbitrary+  ]++genEchoResponse :: Gen String+genEchoResponse = genStringLiteral++instance Arbitrary ValuationPair where+  arbitrary = ValuationPair <$> arbitrary <*> arbitrary++instance Arbitrary TValuationPair where+  arbitrary = TValuationPair <$> genSymbol <*> arbitrary++-- ---------------------------------------------------------------------+-- Test harness++smtlibTestGroup :: TestTree+smtlibTestGroup = $(testGroupGenerator)
test/TestPolynomial.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE TemplateHaskell, ScopedTypeVariables #-}+{-# LANGUAGE FlexibleContexts, TemplateHaskell, ScopedTypeVariables, DataKinds #-}  import Prelude hiding (lex) import qualified Control.Exception as E@@ -256,6 +256,7 @@   P.cont p @?= 1/6   P.pp p   @?= (2*x^5 + 21*x^2 + 12*x + 6)   where+    x :: P.Var a X => a     x = P.var X     p :: UPolynomial Rational     p = P.constant (1/3) * x^5 + P.constant (7/2) * x^2 + 2 * x + 1@@ -905,6 +906,15 @@         , (3, 27)         ]     q = 6*x^2 - 11*x + 6++-- ---------------------------------------------------------------------++-- http://www.math.tamu.edu/~geller/factoring.pdf+case_eisensteinsCriterion_1 = P.eisensteinsCriterion p @?= True+  where+    x :: UPolynomial Rational+    x = P.var X+    p = 2*x^17 - 18*x^12 + 24*x^9 + 243*x^6 - 30*x^3 - 6  ------------------------------------------------------------------------ -- Test harness
test/TestSuite.hs view
@@ -5,48 +5,60 @@ import Test.AReal import Test.AReal2 import Test.Arith+import Test.BitVector import Test.BoolExpr import Test.CongruenceClosure import Test.ContiTraverso import Test.Delta import Test.FiniteModelFinder+import Test.GraphShortestPath import Test.HittingSets import Test.Knapsack import Test.LPFile+import Test.MIP+import Test.MIPSolver import Test.MIPSolver2 import Test.MPSFile import Test.SDPFile import Test.Misc+import Test.QBF import Test.SAT import Test.Simplex-import Test.Simplex2+import Test.SimplexTextbook import Test.SMT import Test.SMTLIB2Solver import Test.Smtlib import Test.SubsetSum+import Test.BipartiteMatching  main :: IO () main = defaultMain $ testGroup "ToySolver test suite"   [ arealTestGroup --  , areal2TestGroup   , arithTestGroup+  , bitVectorTestGroup   , boolExprTestGroup   , ccTestGroup   , ctTestGroup   , deltaTestGroup   , fmfTestGroup+  , graphShortestPathTestGroup   , hittingSetsTestGroup   , knapsackTestGroup   , lpTestGroup   , miscTestGroup+  , mipTestGroup+  , mipSolverTestGroup   , mipSolver2TestGroup   , mpsTestGroup+  , qbfTestGroup   , satTestGroup   , sdpTestGroup   , simplexTestGroup-  , simplex2TestGroup+  , simplexTextbookTestGroup   , smtTestGroup   , smtlib2SolverTestGroup   , smtlibTestGroup   , subsetSumTestGroup+  , bipartiteMatchingTestGroup   ]
− toyfmf/toyfmf.hs
@@ -1,121 +0,0 @@--------------------------------------------------------------------------------- |--- Module      :  toyfmf--- Copyright   :  (c) Masahiro Sakai 2012--- License     :  BSD-style--- --- Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  experimental--- Portability :  portable------ A toy-level model finder----------------------------------------------------------------------------------module Main where--import Control.Monad-import Data.IORef-import qualified Data.Map as Map-import Data.Ratio-import System.Environment-import System.IO-import qualified Codec.TPTP as TPTP-import ToySolver.Data.Boolean-import qualified ToySolver.EUF.FiniteModelFinder as MF--main :: IO ()-main = do-  args <- getArgs-  case args of-    [fpath, size] -> solve fpath (read size)-    _ -> hPutStrLn stderr "Usage: toyfmf <file.tptp> <size>"--solve :: FilePath -> Int -> IO ()-solve _ size | size <= 0 = error "<size> should be >=1"-solve fpath size = do-  inputs <- TPTP.parseFile fpath-  let fs = translateProblem inputs--  ref <- newIORef 0-  let skolem name _ = do-        n <- readIORef ref-        let fsym = name ++ "#" ++ show n-        writeIORef ref (n+1)-        return fsym-  cs <- liftM concat $ mapM (MF.toSkolemNF skolem) fs--  ret <- MF.findModel size cs-  case ret of-    Nothing -> do-      putStrLn "s NO MODEL FOUND"-    Just m -> do-      putStrLn "s SATISFIABLE"-      let isSkolem k = '#' `elem` k-      let m' = m{ MF.mFunctions = Map.filterWithKey (\k _ -> not (isSkolem k)) (MF.mFunctions m) }-      forM_ (MF.showModel m') $ \s ->-        putStrLn $ "v " ++ s--  return ()---- -----------------------------------------------------------------------------translateProblem :: [TPTP.TPTP_Input] -> [MF.Formula]-translateProblem inputs = do-  i <- inputs-  case i of-    TPTP.Comment _ -> []-    TPTP.Include _ _ -> error "\"include\" is not supported yet "-    TPTP.AFormula{ TPTP.name = _, TPTP.role = role, TPTP.formula = formula, TPTP.annotations = _ } ->-      return $ translateFormula formula--translateFormula :: TPTP.Formula -> MF.Formula-translateFormula = TPTP.foldF neg quant binop eq rel-  where-    neg phi = notB $ translateFormula phi-    quant q vs phi = foldr q' (translateFormula phi) [v | TPTP.V v <- vs]-      where-        q' =-          case q of -            TPTP.All    -> MF.Forall-            TPTP.Exists -> MF.Exists-    binop phi op psi = op' phi' psi'-      where-        phi' = translateFormula phi-        psi' = translateFormula psi-        op' =-          case op of-            (TPTP.:<=>:)  -> (.<=>.)-            (TPTP.:=>:)   -> (.=>.)-            (TPTP.:<=:)   -> flip (.=>.)-            (TPTP.:&:)    -> (.&&.)-            (TPTP.:|:)    -> (.||.)-            (TPTP.:~&:)   -> \a b -> notB (a .&&. b)-            (TPTP.:~|:)   -> \a b -> notB (a .||. b)-            (TPTP.:<~>:)  -> \a b -> notB (a .<=>. b)-    eq lhs op rhs =-      case op of-        (TPTP.:=:)  -> MF.Atom $ MF.PApp "=" [lhs', rhs']-        (TPTP.:!=:) -> MF.Not $ MF.Atom $ MF.PApp "=" [lhs', rhs']-      where-        lhs' = translateTerm lhs-        rhs' = translateTerm rhs-    rel (TPTP.AtomicWord p) ts = MF.Atom $ MF.PApp p ts'-      where-        ts' = map translateTerm ts--translateTerm :: TPTP.Term -> MF.Term-translateTerm = TPTP.foldT str num var app-  where-    str s = MF.TmApp (show s) []-    num r = MF.TmApp (showRational r) []-    var (TPTP.V v) = MF.TmVar v-    app (TPTP.AtomicWord f) ts = MF.TmApp f ts'-      where-        ts' = map translateTerm ts--    showRational r =-      if denominator r == 1-      then show (numerator r)-      else show (numerator r) ++ "/" ++ show (denominator r)---- ---------------------------------------------------------------------------
− toysat/UBCSAT.hs
@@ -1,61 +0,0 @@-{-# LANGUAGE ScopedTypeVariables #-}-{-# OPTIONS_GHC -Wall #-}-module UBCSAT (ubcsat) where--import Control.Exception-import Control.Monad-import Data.Array.IArray-import Data.Char-import Data.Either-import Data.Function-import Data.List-import System.Process-import Text.ParserCombinators.Parsec hiding (try)--import qualified ToySolver.SAT.Types as SAT-import qualified ToySolver.Text.MaxSAT as MaxSAT--ubcsat :: FilePath -> FilePath -> MaxSAT.WCNF -> IO (Maybe SAT.Model)-ubcsat cmd fname wcnf = do-  let args =-        [ "-w" | ".wcnf" `isSuffixOf` map toLower fname] ++-        [ "-alg", "irots"-        , "-seed", "0"-        , "-runs", "10"-        , "-cutoff", show (MaxSAT.numVars wcnf * 50)-        , "-solve"-        , "-r", "bestsol"-        , "-inst", fname-        ]-      stdinStr = ""-    -  ret <- try $ readProcess cmd args stdinStr-  case ret of-    Left (err :: IOError) -> do-      forM_ (lines (show err)) $ \l -> do-        putStr "c " >> putStrLn l-      return Nothing-    Right s -> do-      forM_ (lines s) $ \l -> putStr "c " >> putStrLn l-      case scanSolutions s of-        [] -> return Nothing-        sols -> do-          let (obj,m) = minimumBy (compare `on` fst) sols-          if obj < MaxSAT.topCost wcnf then-            return $ Just $ array (1, MaxSAT.numVars wcnf) (zip [1..] m)-          else-            return Nothing--scanSolutions :: String -> [(Integer, [Bool])]-scanSolutions s = rights $ map (parse solution "") $ lines s--solution :: Parser (Integer, [Bool])-solution = do-  skipMany1 digit-  spaces-  _ <- char '0' <|> char '1'-  spaces-  obj <- liftM read $ many1 digit-  spaces-  values <- many ((char '0' >> return False) <|> (char '1' >> return True))-  return (obj, values)
− toysat/toysat.hs
@@ -1,941 +0,0 @@-{-# LANGUAGE ScopedTypeVariables, CPP #-}-{-# OPTIONS_GHC -Wall -fno-warn-unused-do-bind #-}--------------------------------------------------------------------------------- |--- Module      :  toysat--- Copyright   :  (c) Masahiro Sakai 2012-2014--- License     :  BSD-style--- --- Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  experimental--- Portability :  non-portable (ScopedTypeVariables, CPP)------ A toy-level SAT solver based on CDCL.-----------------------------------------------------------------------------------module Main where--import Control.Concurrent.Timeout-import Control.Monad-import Control.Exception-import Data.Array.IArray-import qualified Data.ByteString.Lazy as BS-import Data.Default.Class-import qualified Data.Set as Set-import qualified Data.IntSet as IntSet-import Data.Map (Map)-import qualified Data.Map as Map-import Data.Char-import Data.IORef-import Data.List-import Data.Maybe-import Data.Ord-import Data.Ratio-import Data.Word-import qualified Data.Vector.Unboxed as V-import Data.VectorSpace-import Data.Version-import Data.Time-import System.IO-import System.Environment-import System.Exit-#if !MIN_VERSION_time(1,5,0)-import System.Locale (defaultTimeLocale)-#endif-import System.Console.GetOpt-import System.CPUTime-import System.FilePath-import qualified System.Info as SysInfo-import qualified System.Random.MWC as Rand-import qualified Language.CNF.Parse.ParseDIMACS as DIMACS-import Text.Printf-#ifdef __GLASGOW_HASKELL__-import GHC.Environment (getFullArgs)-#endif-#ifdef FORCE_CHAR8-import GHC.IO.Encoding-#endif-#if defined(__GLASGOW_HASKELL__)-import qualified GHC.Stats as Stats-#endif--import qualified Data.PseudoBoolean as PBFile-import qualified Data.PseudoBoolean.Attoparsec as PBFileAttoparsec-import ToySolver.Data.OrdRel-import qualified ToySolver.Data.MIP as MIP-import qualified ToySolver.Converter.MaxSAT2WBO as MaxSAT2WBO-import qualified ToySolver.SAT as SAT-import qualified ToySolver.SAT.PBO as PBO-import qualified ToySolver.SAT.Integer as Integer-import qualified ToySolver.SAT.TseitinEncoder as Tseitin-import qualified ToySolver.SAT.PBNLC as PBNLC-import qualified ToySolver.SAT.MUS as MUS-import qualified ToySolver.SAT.MUS.QuickXplain as QuickXplain-import qualified ToySolver.SAT.MUS.CAMUS as CAMUS-import qualified ToySolver.SAT.MUS.DAA as DAA-import ToySolver.SAT.Printer-import qualified ToySolver.Text.MaxSAT as MaxSAT-import qualified ToySolver.Text.GCNF as GCNF-import qualified ToySolver.Text.GurobiSol as GurobiSol-import ToySolver.Version-import ToySolver.Internal.Util (showRational, revForM)--import UBCSAT---- --------------------------------------------------------------------------data Mode = ModeHelp | ModeVersion | ModeSAT | ModeMUS | ModePB | ModeWBO | ModeMaxSAT | ModeMIP--data MUSMethod = MUSLinear | MUSQuickXplain--data AllMUSMethod = AllMUSCAMUS | AllMUSDAA--data Options-  = Options-  { optMode          :: Maybe Mode-  , optSATConfig     :: SAT.Config-  , optRandomSeed    :: Maybe Rand.Seed-  , optLinearizerPB  :: Bool-  , optSearchStrategy       :: PBO.SearchStrategy-  , optObjFunVarsHeuristics :: Bool-  , optLocalSearchInitial   :: Bool-  , optMUSMethod :: MUSMethod-  , optAllMUSes :: Bool-  , optAllMUSMethod :: AllMUSMethod-  , optPrintRational :: Bool-  , optTimeout :: Integer-  , optWriteFile :: Maybe FilePath-  , optUBCSAT :: FilePath-  }--instance Default Options where-  def =-    Options-    { optMode          = Nothing-    , optSATConfig     = def-    , optRandomSeed    = Nothing-    , optLinearizerPB  = False-    , optSearchStrategy       = def-    , optObjFunVarsHeuristics = PBO.defaultEnableObjFunVarsHeuristics-    , optLocalSearchInitial   = False-    , optMUSMethod = MUSLinear-    , optAllMUSes = False-    , optAllMUSMethod = AllMUSCAMUS-    , optPrintRational = False-    , optTimeout = 0-    , optWriteFile = Nothing-    , optUBCSAT = "ubcsat"-    }--options :: [OptDescr (Options -> Options)]-options =-    [ Option ['h'] ["help"]   (NoArg (\opt -> opt{ optMode = Just ModeHelp   })) "show help"-    , Option [] ["version"]   (NoArg (\opt -> opt{ optMode = Just ModeVersion})) "show version"--    , Option []    ["sat"]    (NoArg (\opt -> opt{ optMode = Just ModeSAT    })) "solve boolean satisfiability problem in .cnf file (default)"-    , Option []    ["mus"]    (NoArg (\opt -> opt{ optMode = Just ModeMUS    })) "solve minimally unsatisfiable subset problem in .gcnf or .cnf file"-    , Option []    ["pb"]     (NoArg (\opt -> opt{ optMode = Just ModePB     })) "solve pseudo boolean problem in .opb file"-    , Option []    ["wbo"]    (NoArg (\opt -> opt{ optMode = Just ModeWBO    })) "solve weighted boolean optimization problem in .wbo file"-    , Option []    ["maxsat"] (NoArg (\opt -> opt{ optMode = Just ModeMaxSAT })) "solve MaxSAT problem in .cnf or .wcnf file"-    , Option []    ["lp"]     (NoArg (\opt -> opt{ optMode = Just ModeMIP    })) "solve bounded integer programming problem in .lp or .mps file"--    , Option [] ["restart"]-        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configRestartStrategy = parseRestartStrategy val } }) "<str>")-        "Restart startegy: MiniSAT (default), Armin, Luby."-    , Option [] ["restart-first"]-        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configRestartFirst = read val } }) "<integer>")-        (printf "The initial restart limit. (default %d)" (SAT.configRestartFirst def))-    , Option [] ["restart-inc"]-        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configRestartInc = read val } }) "<real>")-        (printf "The factor with which the restart limit is multiplied in each restart. (default %f)" (SAT.configRestartInc def))-    , Option [] ["learning"]-        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configLearningStrategy = parseLS val } }) "<name>")-        "Leaning scheme: clause (default), hybrid"-    , Option [] ["learnt-size-first"]-        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configLearntSizeFirst = read val } }) "<int>")-        "The initial limit for learnt clauses."-    , Option [] ["learnt-size-inc"]-        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configLearntSizeInc = read val } }) "<real>")-        (printf "The limit for learnt clauses is multiplied with this factor periodically. (default %f)" (SAT.configLearntSizeInc def))-    , Option [] ["ccmin"]-        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configCCMin = read val } }) "<int>")-        (printf "Conflict clause minimization (0=none, 1=local, 2=recursive; default %d)" (SAT.configCCMin def))-    , Option [] ["enable-phase-saving"]-        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configEnablePhaseSaving = True } }))-        ("Enable phase saving" ++ (if SAT.configEnablePhaseSaving def then " (default)" else ""))-    , Option [] ["disable-phase-saving"]-        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configEnablePhaseSaving = False } }))-        ("Disable phase saving" ++ (if SAT.configEnablePhaseSaving def then "" else " (default)"))-    , Option [] ["enable-forward-subsumption-removal"]-        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configEnableForwardSubsumptionRemoval = True } }))-        ("Enable forward subumption removal (clauses only)" ++ (if SAT.configEnableForwardSubsumptionRemoval def then " (default)" else ""))-    , Option [] ["disable-forward-subsumption-removal"]-        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configEnableForwardSubsumptionRemoval = False } }))-        ("Disable forward subsumption removal (clauses only)" ++ (if SAT.configEnableForwardSubsumptionRemoval def then "" else " (default)"))-    , Option [] ["enable-backward-subsumption-removal"]-        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configEnableBackwardSubsumptionRemoval = True } }))-        ("Enable backward subsumption removal." ++ (if SAT.configEnableBackwardSubsumptionRemoval def then " (default)" else ""))-    , Option [] ["disable-backward-subsumption-removal"]-        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configEnableBackwardSubsumptionRemoval = False } }))-        ("Disable backward subsumption removal." ++ (if SAT.configEnableBackwardSubsumptionRemoval def then "" else " (default)"))--    , Option [] ["random-freq"]-        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configRandomFreq = read val } }) "<0..1>")-        (printf "The frequency with which the decision heuristic tries to choose a random variable (default %f)" (SAT.configRandomFreq def))-    , Option [] ["random-seed"]-        (ReqArg (\val opt -> opt{ optRandomSeed = Just (Rand.toSeed (V.singleton (read val) :: V.Vector Word32)) }) "<int>")-        "random seed used by the random variable selection"-    , Option [] ["random-gen"]-        (ReqArg (\val opt -> opt{ optRandomSeed = Just (Rand.toSeed (V.fromList (map read $ words $ val) :: V.Vector Word32)) }) "<str>")-        "another way of specifying random seed used by the random variable selection"--    , Option [] ["linearizer-pb"]-        (NoArg (\opt -> opt{ optLinearizerPB = True }))-        "Use PB constraint in linearization."--    , Option [] ["pb-handler"]-        (ReqArg (\val opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configPBHandlerType = parsePBHandler val } }) "<name>")-        "PB constraint handler: counter (default), pueblo"-    , Option [] ["pb-split-clause-part"]-        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configEnablePBSplitClausePart = True } }))-        ("Split clause part of PB constraints." ++ (if SAT.configEnablePBSplitClausePart def then " (default)" else ""))-    , Option [] ["no-pb-split-clause-part"]-        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configEnablePBSplitClausePart = False } }))-        ("Do not split clause part of PB constraints." ++ (if SAT.configEnablePBSplitClausePart def then "" else " (default)"))--    , Option [] ["search"]-        (ReqArg (\val opt -> opt{ optSearchStrategy = parseSearch val }) "<str>")-        "Search algorithm used in optimization; linear (default), binary, adaptive, unsat, msu4, bc, bcd, bcd2"-    , Option [] ["objfun-heuristics"]-        (NoArg (\opt -> opt{ optObjFunVarsHeuristics = True }))-        "Enable heuristics for polarity/activity of variables in objective function (default)"-    , Option [] ["no-objfun-heuristics"]-        (NoArg (\opt -> opt{ optObjFunVarsHeuristics = False }))-        "Disable heuristics for polarity/activity of variables in objective function"-    , Option [] ["ls-initial"]-        (NoArg (\opt -> opt{ optLocalSearchInitial = True }))-        "Use local search (currently UBCSAT) for finding initial solution"--    , Option [] ["all-mus"]-        (NoArg (\opt -> opt{ optMode = Just ModeMUS, optAllMUSes = True }))-        "enumerate all MUSes"-    , Option [] ["mus-method"]-        (ReqArg (\val opt -> opt{ optMUSMethod = parseMUSMethod val }) "<str>")-        "MUS computation method: linear (default), QuickXplain"-    , Option [] ["all-mus-method"]-        (ReqArg (\val opt -> opt{ optAllMUSMethod = parseAllMUSMethod val }) "<str>")-        "MUS enumeration method: camus (default), daa"--    , Option [] ["print-rational"]-        (NoArg (\opt -> opt{ optPrintRational = True }))-        "print rational numbers instead of decimals"-    , Option ['w'] []-        (ReqArg (\val opt -> opt{ optWriteFile = Just val }) "<filename>")-        "write model to filename in Gurobi .sol format"--    , Option [] ["check-model"]-        (NoArg (\opt -> opt{ optSATConfig = (optSATConfig opt){ SAT.configCheckModel = True } }))-        "check model for debug"--    , Option [] ["timeout"]-        (ReqArg (\val opt -> opt{ optTimeout = read val }) "<int>")-        "Kill toysat after given number of seconds (default 0 (no limit))"--    , Option [] ["with-ubcsat"]-        (ReqArg (\val opt -> opt{ optUBCSAT = val }) "<PATH>")-        "give the path to the UBCSAT command"-    ]-  where-    parseRestartStrategy s =-      case map toLower s of-        "minisat" -> SAT.MiniSATRestarts-        "armin" -> SAT.ArminRestarts-        "luby" -> SAT.LubyRestarts-        _ -> error (printf "unknown restart strategy \"%s\"" s)--    parseSearch s =-      case map toLower s of-        "linear"   -> PBO.LinearSearch-        "binary"   -> PBO.BinarySearch-        "adaptive" -> PBO.AdaptiveSearch-        "unsat"    -> PBO.UnsatBased-        "msu4"     -> PBO.MSU4-        "bc"       -> PBO.BC-        "bcd"      -> PBO.BCD-        "bcd2"     -> PBO.BCD2-        _ -> error (printf "unknown search strategy \"%s\"" s)--    parseMUSMethod s =-      case map toLower s of-        "linear"      -> MUSLinear-        "quickxplain" -> MUSQuickXplain-        _ -> error (printf "unknown MUS finding method \"%s\"" s)--    parseAllMUSMethod s =-      case map toLower s of-        "camus"    -> AllMUSCAMUS-        "daa"      -> AllMUSDAA-        _ -> error (printf "unknown MUS enumeration method \"%s\"" s)--    parseLS s =-      case map toLower s of-        "clause" -> SAT.LearningClause-        "hybrid" -> SAT.LearningHybrid-        _ -> error (printf "unknown learning strategy \"%s\"" s)--    parsePBHandler s =-      case map toLower s of-        "counter" -> SAT.PBHandlerTypeCounter-        "pueblo"  -> SAT.PBHandlerTypePueblo-        _ -> error (printf "unknown PB constraint handler %s" s)--main :: IO ()-main = do-#ifdef FORCE_CHAR8-  setLocaleEncoding char8-  setForeignEncoding char8-  setFileSystemEncoding char8-#endif--  startCPU <- getCPUTime-  startWC  <- getCurrentTime-  args <- getArgs-  case getOpt Permute options args of-    (_,_,errs@(_:_)) -> do-      mapM_ putStrLn errs-      exitFailure--    (o,args2,[]) -> do-      let opt = foldl (flip id) def o      -          mode =-            case optMode opt of-              Just m  -> m-              Nothing ->-                case args2 of-                  [] -> ModeHelp-                  fname : _ ->-                    case map toLower (takeExtension fname) of-                      ".cnf"  -> ModeSAT-                      ".gcnf" -> ModeMUS-                      ".opb"  -> ModePB-                      ".wbo"  -> ModeWBO-                      ".wcnf" -> ModeMaxSAT-                      ".lp"   -> ModeMIP-                      ".mps"  -> ModeMIP-                      _ -> ModeSAT--      case mode of-        ModeHelp    -> showHelp stdout-        ModeVersion -> hPutStrLn stdout (showVersion version)-        _ -> do-          printSysInfo-#ifdef __GLASGOW_HASKELL__-          fullArgs <- getFullArgs-#else-          let fullArgs = args-#endif-          putCommentLine $ printf "command line = %s" (show fullArgs)--          let timelim = optTimeout opt * 10^(6::Int)-    -          ret <- timeout (if timelim > 0 then timelim else (-1)) $ do-             solver <- newSolver opt-             case mode of-               ModeHelp    -> showHelp stdout-               ModeVersion -> hPutStrLn stdout (showVersion version)-               ModeSAT     -> mainSAT opt solver args2-               ModeMUS     -> mainMUS opt solver args2-               ModePB      -> mainPB opt solver args2-               ModeWBO     -> mainWBO opt solver args2-               ModeMaxSAT  -> mainMaxSAT opt solver args2-               ModeMIP     -> mainMIP opt solver args2-    -          when (isNothing ret) $ do-            putCommentLine "TIMEOUT"-          endCPU <- getCPUTime-          endWC  <- getCurrentTime-          putCommentLine $ printf "total CPU time = %.3fs" (fromIntegral (endCPU - startCPU) / 10^(12::Int) :: Double)-          putCommentLine $ printf "total wall clock time = %.3fs" (realToFrac (endWC `diffUTCTime` startWC) :: Double)-          printGCStat--printGCStat :: IO ()-#if defined(__GLASGOW_HASKELL__)-printGCStat = do-  b <- Stats.getGCStatsEnabled-  when b $ do-    stat <- Stats.getGCStats-    putCommentLine "GCStats:"-    putCommentLine $ printf "  bytesAllocated = %d"         $ Stats.bytesAllocated stat-    putCommentLine $ printf "  numGcs = %d"                 $ Stats.numGcs stat-    putCommentLine $ printf "  maxBytesUsed = %d"           $ Stats.maxBytesUsed stat-    putCommentLine $ printf "  numByteUsageSamples = %d"    $ Stats.numByteUsageSamples stat-    putCommentLine $ printf "  cumulativeBytesUsed = %d"    $ Stats.cumulativeBytesUsed stat-    putCommentLine $ printf "  bytesCopied = %d"            $ Stats.bytesCopied stat-    putCommentLine $ printf "  currentBytesUsed = %d"       $ Stats.currentBytesUsed stat-    putCommentLine $ printf "  currentBytesSlop = %d"       $ Stats.currentBytesSlop stat-    putCommentLine $ printf "  maxBytesSlop = %d"           $ Stats.maxBytesSlop stat-    putCommentLine $ printf "  peakMegabytesAllocated = %d" $ Stats.peakMegabytesAllocated stat-    putCommentLine $ printf "  mutatorCpuSeconds = %5.2f"   $ Stats.mutatorCpuSeconds stat-    putCommentLine $ printf "  mutatorWallSeconds = %5.2f"  $ Stats.mutatorWallSeconds stat-    putCommentLine $ printf "  gcCpuSeconds = %5.2f"        $ Stats.gcCpuSeconds stat-    putCommentLine $ printf "  gcWallSeconds = %5.2f"       $ Stats.gcWallSeconds stat-    putCommentLine $ printf "  cpuSeconds = %5.2f"          $ Stats.cpuSeconds stat-    putCommentLine $ printf "  wallSeconds = %5.2f"         $ Stats.wallSeconds stat-    putCommentLine $ printf "  parTotBytesCopied = %d"      $ Stats.parTotBytesCopied stat-    putCommentLine $ printf "  parMaxBytesCopied = %d"      $ Stats.parMaxBytesCopied stat-#else-printGCStat = return ()-#endif--showHelp :: Handle -> IO ()-showHelp h = hPutStrLn h (usageInfo header options)--header :: String-header = unlines-  [ "Usage:"-  , "  toysat [OPTION]... [file.cnf|-]"-  , "  toysat [OPTION]... --mus [file.gcnf|-]"-  , "  toysat [OPTION]... --pb [file.opb|-]"-  , "  toysat [OPTION]... --wbo [file.wbo|-]"-  , "  toysat [OPTION]... --maxsat [file.cnf|file.wcnf|-]"-  , "  toysat [OPTION]... --lp [file.lp|file.mps|-]"-  , ""-  , "Options:"-  ]--printSysInfo :: IO ()-printSysInfo = do-  tm <- getZonedTime-  putCommentLine $ printf "%s" (formatTime defaultTimeLocale "%FT%X%z" tm)-  putCommentLine $ printf "version = %s" (showVersion version)-  putCommentLine $ printf "githash = %s" (fromMaybe "<unknown>" gitHash)-  putCommentLine $ printf "compilationtime = %s" (show compilationTime)-  putCommentLine $ printf "arch = %s" SysInfo.arch-  putCommentLine $ printf "os = %s" SysInfo.os-  putCommentLine $ printf "compiler = %s %s" SysInfo.compilerName (showVersion SysInfo.compilerVersion)-  putCommentLine "packages:"-  forM_ packageVersions $ \(package, ver) -> do-    putCommentLine $ printf "  %s-%s" package ver--putCommentLine :: String -> IO ()-putCommentLine s = do-  putStr "c "-  putStrLn s-  hFlush stdout--putSLine :: String -> IO ()-putSLine  s = do-  putStr "s "-  putStrLn s-  hFlush stdout--putOLine :: String -> IO ()-putOLine  s = do-  putStr "o "-  putStrLn s-  hFlush stdout--newSolver :: Options -> IO SAT.Solver-newSolver opts = do-  solver <- SAT.newSolverWithConfig (optSATConfig opts)-  SAT.setLogger solver putCommentLine-  case optRandomSeed opts of-    Nothing -> SAT.setRandomGen solver =<< Rand.createSystemRandom-    Just s -> SAT.setRandomGen solver =<< Rand.initialize (Rand.fromSeed s)-  do gen <- SAT.getRandomGen solver-     s <- Rand.save gen-     putCommentLine $ "use --random-gen=" ++ show (unwords . map show . V.toList . Rand.fromSeed $ s) ++ " option to reproduce the execution"-  return solver---- --------------------------------------------------------------------------mainSAT :: Options -> SAT.Solver -> [String] -> IO ()-mainSAT opt solver args = do-  ret <- case args of-           ["-"]   -> liftM (DIMACS.parseByteString "-") $ BS.hGetContents stdin-           [fname] -> DIMACS.parseFile fname-           _ -> showHelp stderr >> exitFailure-  case ret of-    Left err -> hPrint stderr err >> exitFailure-    Right cnf -> solveSAT opt solver cnf--solveSAT :: Options -> SAT.Solver -> DIMACS.CNF -> IO ()-solveSAT opt solver cnf = do-  putCommentLine $ printf "#vars %d" (DIMACS.numVars cnf)-  putCommentLine $ printf "#constraints %d" (DIMACS.numClauses cnf)-  SAT.newVars_ solver (DIMACS.numVars cnf)-  forM_ (DIMACS.clauses cnf) $ \clause ->-    SAT.addClause solver (elems clause)-  result <- SAT.solve solver-  putSLine $ if result then "SATISFIABLE" else "UNSATISFIABLE"-  when result $ do-    m <- SAT.getModel solver-    satPrintModel stdout m (DIMACS.numVars cnf)-    writeSOLFile opt m Nothing (DIMACS.numVars cnf)---- --------------------------------------------------------------------------mainMUS :: Options -> SAT.Solver -> [String] -> IO ()-mainMUS opt solver args = do-  gcnf <- case args of-           ["-"]   -> do-             s <- hGetContents stdin-             case GCNF.parseString s of-               Left err   -> hPutStrLn stderr err >> exitFailure-               Right gcnf -> return gcnf-           [fname] -> do-             ret <- GCNF.parseFile fname-             case ret of-               Left err   -> hPutStrLn stderr err >> exitFailure-               Right gcnf -> return gcnf-           _ -> showHelp stderr >> exitFailure-  solveMUS opt solver gcnf--solveMUS :: Options -> SAT.Solver -> GCNF.GCNF -> IO ()-solveMUS opt solver gcnf = do-  putCommentLine $ printf "#vars %d" (GCNF.numVars gcnf)-  putCommentLine $ printf "#constraints %d" (GCNF.numClauses gcnf)-  putCommentLine $ printf "#groups %d" (GCNF.lastGroupIndex gcnf)--  SAT.resizeVarCapacity solver (GCNF.numVars gcnf + GCNF.lastGroupIndex gcnf)-  SAT.newVars_ solver (GCNF.numVars gcnf)--  tbl <- forM [1 .. GCNF.lastGroupIndex gcnf] $ \i -> do-    sel <- SAT.newVar solver-    return (i, sel)-  let idx2sel :: Array Int SAT.Var-      idx2sel = array (1, GCNF.lastGroupIndex gcnf) tbl-      selrng  = if null tbl then (0,-1) else (snd $ head tbl, snd $ last tbl)-      sel2idx :: Array SAT.Lit Int-      sel2idx = array selrng [(sel, idx) | (idx, sel) <- tbl]--  forM_ (GCNF.clauses gcnf) $ \(idx, clause) ->-    if idx==0-    then SAT.addClause solver clause-    else SAT.addClause solver (- (idx2sel ! idx) : clause)--  result <- SAT.solveWith solver (map (idx2sel !) [1..GCNF.lastGroupIndex gcnf])-  putSLine $ if result then "SATISFIABLE" else "UNSATISFIABLE"-  if result-    then do-      m <- SAT.getModel solver-      satPrintModel stdout m (GCNF.numVars gcnf)-      writeSOLFile opt m Nothing (GCNF.numVars gcnf)-    else do-      if not (optAllMUSes opt)-      then do-          let opt2 = def-                     { MUS.optLogger = putCommentLine-                     , MUS.optLitPrinter = \lit ->-                         show (sel2idx ! lit)-                     }-          mus <--            case optMUSMethod opt of-              MUSLinear -> MUS.findMUSAssumptions solver opt2-              MUSQuickXplain -> QuickXplain.findMUSAssumptions solver opt2-          let mus2 = sort $ map (sel2idx !) $ IntSet.toList mus-          musPrintSol stdout mus2-      else do-          counter <- newIORef 1-          let opt2 = def-                     { CAMUS.optLogger = putCommentLine-                     , CAMUS.optOnMCSFound = \mcs -> do-                         let mcs2 = sort $ map (sel2idx !) $ IntSet.toList mcs-                         putCommentLine $ "MCS found: " ++ show mcs2-                     , CAMUS.optOnMUSFound = \mus -> do-                         i <- readIORef counter-                         modifyIORef' counter (+1)-                         putCommentLine $ "MUS #" ++ show (i :: Int)-                         let mus2 = sort $ map (sel2idx !) $ IntSet.toList mus-                         musPrintSol stdout mus2-                     }-          case optAllMUSMethod opt of-            AllMUSCAMUS -> CAMUS.allMUSAssumptions solver (map snd tbl) opt2-            AllMUSDAA   -> DAA.allMUSAssumptions solver (map snd tbl) opt2-          return ()---- --------------------------------------------------------------------------mainPB :: Options -> SAT.Solver -> [String] -> IO ()-mainPB opt solver args = do-  ret <- case args of-           ["-"]   -> liftM PBFileAttoparsec.parseOPBByteString $ BS.hGetContents stdin-           [fname] -> PBFileAttoparsec.parseOPBFile fname-           _ -> showHelp stderr >> exitFailure-  case ret of-    Left err -> hPutStrLn stderr err >> exitFailure-    Right formula -> solvePB opt solver formula Nothing--solvePB :: Options -> SAT.Solver -> PBFile.Formula -> Maybe SAT.Model -> IO ()-solvePB opt solver formula initialModel = do-  let nv = PBFile.pbNumVars formula-      nc = PBFile.pbNumConstraints formula-  putCommentLine $ printf "#vars %d" nv-  putCommentLine $ printf "#constraints %d" nc--  SAT.newVars_ solver nv-  enc <- Tseitin.newEncoder solver-  Tseitin.setUsePB enc (optLinearizerPB opt)--  forM_ (PBFile.pbConstraints formula) $ \(lhs, op, rhs) -> do-    case op of-      PBFile.Ge -> PBNLC.addPBAtLeast enc lhs rhs-      PBFile.Eq -> PBNLC.addPBExactly enc lhs rhs--  case PBFile.pbObjectiveFunction formula of-    Nothing -> do-      result <- SAT.solve solver-      putSLine $ if result then "SATISFIABLE" else "UNSATISFIABLE"-      when result $ do-        m <- SAT.getModel solver-        pbPrintModel stdout m nv-        writeSOLFile opt m Nothing nv--    Just obj' -> do-      obj'' <- PBNLC.linearizePBSumWithPolarity enc Tseitin.polarityNeg obj'--      nv' <- SAT.getNVars solver-      defs <- Tseitin.getDefinitions enc-      let extendModel :: SAT.Model -> SAT.Model-          extendModel m = array (1,nv') (assocs a)-            where-              -- Use BOXED array to tie the knot-              a :: Array SAT.Var Bool-              a = array (1,nv') $ assocs m ++ [(v, Tseitin.evalFormula a phi) | (v,phi) <- defs]--      pbo <- PBO.newOptimizer2 solver obj'' (\m -> evalPBSum m obj')-      setupOptimizer pbo opt-      PBO.setOnUpdateBestSolution pbo $ \_ val -> putOLine (show val)-      PBO.setOnUpdateLowerBound pbo $ \lb -> do-        putCommentLine $ printf "lower bound updated to %d" lb--      case initialModel of-        Nothing -> return ()-        Just m -> PBO.addSolution pbo (extendModel m)--      finally (PBO.optimize pbo) $ do-        ret <- PBO.getBestSolution pbo-        case ret of-          Nothing -> do-            b <- PBO.isUnsat pbo-            if b-              then putSLine "UNSATISFIABLE"-              else putSLine "UNKNOWN"-          Just (m, val) -> do-            b <- PBO.isOptimum pbo-            if b-              then putSLine "OPTIMUM FOUND"-              else putSLine "SATISFIABLE"-            pbPrintModel stdout m nv-            writeSOLFile opt m (Just val) nv--evalPBSum :: SAT.IModel m => m -> PBFile.Sum -> Integer-evalPBSum m s = sum [if and [SAT.evalLit m lit | lit <- tm] then c else 0 | (c,tm) <- s]--evalPBConstraint :: SAT.IModel m => m -> PBFile.Constraint -> Bool-evalPBConstraint m (lhs,op,rhs) = op' lhs' rhs-  where-    op' = case op of-            PBFile.Ge -> (>=)-            PBFile.Eq -> (==)-    lhs' = evalPBSum m lhs--setupOptimizer :: PBO.Optimizer -> Options -> IO ()-setupOptimizer pbo opt = do-  PBO.setEnableObjFunVarsHeuristics pbo $ optObjFunVarsHeuristics opt-  PBO.setSearchStrategy pbo $ optSearchStrategy opt-  PBO.setLogger pbo putCommentLine---- --------------------------------------------------------------------------mainWBO :: Options -> SAT.Solver -> [String] -> IO ()-mainWBO opt solver args = do-  ret <- case args of-           ["-"]   -> liftM PBFileAttoparsec.parseWBOByteString $ BS.hGetContents stdin-           [fname] -> PBFileAttoparsec.parseWBOFile fname-           _ -> showHelp stderr >> exitFailure-  case ret of-    Left err -> hPutStrLn stderr err >> exitFailure-    Right formula -> solveWBO opt solver False formula Nothing--solveWBO :: Options -> SAT.Solver -> Bool -> PBFile.SoftFormula -> Maybe SAT.Model -> IO ()-solveWBO opt solver isMaxSat formula initialModel = do-  let nv = PBFile.wboNumVars formula-      nc = PBFile.wboNumConstraints formula-  putCommentLine $ printf "#vars %d" nv-  putCommentLine $ printf "#constraints %d" nc--  SAT.resizeVarCapacity solver (nv + length [() | (Just _, _) <- PBFile.wboConstraints formula])-  SAT.newVars_ solver nv-  enc <- Tseitin.newEncoder solver-  Tseitin.setUsePB enc (optLinearizerPB opt)--  objRef <- newIORef []-  defsRef <- newIORef []--  forM_ (PBFile.wboConstraints formula) $ \(cost, constr@(lhs, op, rhs)) -> do-    case cost of-      Nothing -> do-        case op of-          PBFile.Ge -> PBNLC.addPBAtLeast enc lhs rhs-          PBFile.Eq -> PBNLC.addPBExactly enc lhs rhs-      Just cval -> do-        sel <--          case op of-            PBFile.Ge -> do-              case lhs of-                [(1,ls)] | rhs == 1 ->-                  Tseitin.encodeConjWithPolarity enc Tseitin.polarityPos ls-                _ -> do-                  sel <- SAT.newVar solver-                  PBNLC.addPBAtLeastSoft enc sel lhs rhs-                  modifyIORef defsRef ((sel, constr) : )-                  return sel-            PBFile.Eq -> do-              sel <- SAT.newVar solver-              PBNLC.addPBExactlySoft enc sel lhs rhs-              modifyIORef defsRef ((sel, constr) : )-              return sel-        modifyIORef objRef ((cval, SAT.litNot sel) : )--  obj <- readIORef objRef--  case PBFile.wboTopCost formula of-    Nothing -> return ()-    Just c -> SAT.addPBAtMost solver obj (c-1)--  nv' <- SAT.getNVars solver-  defs1 <- Tseitin.getDefinitions enc-  defs2 <- readIORef defsRef-  let extendModel :: SAT.Model -> SAT.Model-      extendModel m = array (1,nv') (assocs a)-        where-          -- Use BOXED array to tie the knot-          a :: Array SAT.Var Bool-          a = array (1,nv') $-                assocs m ++-                [(v, Tseitin.evalFormula a phi) | (v, phi) <- defs1] ++-                [(v, evalPBConstraint a constr) | (v, constr) <- defs2]--  let softConstrs = [(c, constr) | (Just c, constr) <- PBFile.wboConstraints formula]-                -  pbo <- PBO.newOptimizer2 solver obj $ \m ->-           sum [if evalPBConstraint m constr then 0 else w | (w,constr) <- softConstrs]--  setupOptimizer pbo opt-  PBO.setOnUpdateBestSolution pbo $ \_ val -> putOLine (show val)-  PBO.setOnUpdateLowerBound pbo $ \lb -> do-    putCommentLine $ printf "lower bound updated to %d" lb--  case initialModel of-    Nothing -> return ()-    Just m -> PBO.addSolution pbo (extendModel m)--  finally (PBO.optimize pbo) $ do-    ret <- PBO.getBestSolution pbo-    case ret of-      Nothing -> do-        b <- PBO.isUnsat pbo-        if b-          then putSLine "UNSATISFIABLE"-          else putSLine "UNKNOWN"-      Just (m, val) -> do-        b <- PBO.isOptimum pbo-        if b then do-          putSLine "OPTIMUM FOUND"-          if isMaxSat then-            satPrintModel stdout m nv-          else-            pbPrintModel stdout m nv-          writeSOLFile opt m (Just val) nv-        else if not isMaxSat then do-          putSLine "SATISFIABLE"-          pbPrintModel stdout m nv-          writeSOLFile opt m (Just val) nv-        else -          putSLine "UNKNOWN"---- --------------------------------------------------------------------------mainMaxSAT :: Options -> SAT.Solver -> [String] -> IO ()-mainMaxSAT opt solver args = do-  ret <- case args of-           ["-"]   -> liftM MaxSAT.parseByteString BS.getContents-           [fname] -> MaxSAT.parseFile fname-           _ -> showHelp stderr  >> exitFailure-  case ret of-    Left err -> hPutStrLn stderr err >> exitFailure-    Right wcnf -> do-      initialModel <--        case args of-          [fname] | optLocalSearchInitial opt && or [s `isSuffixOf` map toLower fname | s <- [".cnf", ".wcnf"] ] ->-            UBCSAT.ubcsat (optUBCSAT opt) fname wcnf-          _ -> return Nothing-      solveMaxSAT opt solver wcnf initialModel--solveMaxSAT :: Options -> SAT.Solver -> MaxSAT.WCNF -> Maybe SAT.Model -> IO ()-solveMaxSAT opt solver wcnf initialModel =-  solveWBO opt solver True (MaxSAT2WBO.convert wcnf) initialModel---- --------------------------------------------------------------------------mainMIP :: Options -> SAT.Solver -> [String] -> IO ()-mainMIP opt solver args = do-  mip <--    case args of-      [fname@"-"]   -> do-        s <- hGetContents stdin-        case MIP.parseLPString fname s of-          Right mip -> return mip-          Left err ->-            case MIP.parseMPSString fname s of-              Right mip -> return mip-              Left err2 -> do-                hPrint stderr err-                hPrint stderr err2-                exitFailure-      [fname] -> do-        ret <- MIP.readFile fname-        case ret of-          Left err -> hPrint stderr err >> exitFailure-          Right mip -> return mip-      _ -> showHelp stderr >> exitFailure-  solveMIP opt solver mip--solveMIP :: Options -> SAT.Solver -> MIP.Problem -> IO ()-solveMIP opt solver mip = do-  if not (Set.null nivs) then do-    putCommentLine $ "cannot handle non-integer variables: " ++ intercalate ", " (map MIP.fromVar (Set.toList nivs))-    putSLine "UNKNOWN"-    exitFailure-  else do-    enc <- Tseitin.newEncoder solver-    Tseitin.setUsePB enc (optLinearizerPB opt)--    putCommentLine $ "Loading variables and bounds"-    vmap <- liftM Map.fromList $ revForM (Set.toList ivs) $ \v -> do-      case MIP.getBounds mip v of-        (MIP.Finite lb, MIP.Finite ub) -> do-          v2 <- Integer.newVar solver (ceiling lb) (floor ub)-          return (v,v2)-        _ -> do-          putCommentLine $ "cannot handle unbounded variable: " ++ MIP.fromVar v-          putSLine "UNKNOWN"-          exitFailure--    putCommentLine "Loading constraints"-    forM_ (MIP.constraints mip) $ \c -> do-      let lhs = MIP.constrExpr c                            -      let f op rhs = do-            let d = foldl' lcm 1 (map denominator  (rhs:[r | MIP.Term r _ <- MIP.terms lhs]))-                lhs' = sumV [asInteger (r * fromIntegral d) *^ product [vmap Map.! v | v <- vs] | MIP.Term r vs <- MIP.terms lhs]-                rhs' = asInteger (rhs * fromIntegral d)-                c2 = case op of-                       MIP.Le  -> lhs' .<=. fromInteger rhs'-                       MIP.Ge  -> lhs' .>=. fromInteger rhs'-                       MIP.Eql -> lhs' .==. fromInteger rhs'-            case MIP.constrIndicator c of-              Nothing -> Integer.addConstraint enc c2-              Just (var, val) -> do-                let var' = asBin (vmap Map.! var)-                case val of-                  1 -> Integer.addConstraintSoft enc var' c2-                  0 -> Integer.addConstraintSoft enc (SAT.litNot var') c2-                  _ -> return ()-      case (MIP.constrLB c, MIP.constrUB c) of-        (MIP.Finite x1, MIP.Finite x2) | x1==x2 -> f MIP.Eql x2-        (lb, ub) -> do-          case lb of-            MIP.NegInf -> return ()-            MIP.Finite x -> f MIP.Ge x-            MIP.PosInf -> SAT.addClause solver []-          case ub of-            MIP.NegInf -> SAT.addClause solver []-            MIP.Finite x -> f MIP.Le x-            MIP.PosInf -> return ()--    putCommentLine "Loading SOS constraints"-    forM_ (MIP.sosConstraints mip) $ \MIP.SOSConstraint{ MIP.sosType = typ, MIP.sosBody = xs } -> do-      case typ of-        MIP.S1 -> SAT.addAtMost solver (map (asBin . (vmap Map.!) . fst) xs) 1-        MIP.S2 -> do-          let ps = nonAdjacentPairs $ map fst $ sortBy (comparing snd) $ xs-          forM_ ps $ \(x1,x2) -> do-            SAT.addClause solver [SAT.litNot $ asBin $ vmap Map.! v | v <- [x1,x2]]--    let obj = MIP.objectiveFunction mip-        d = foldl' lcm 1 [denominator r | MIP.Term r _ <- MIP.terms (MIP.objExpr obj)] *-            (if MIP.objDir obj == MIP.OptMin then 1 else -1)-        obj2 = sumV [asInteger (r * fromIntegral d) *^ product [vmap Map.! v | v <- vs] | MIP.Term r vs <- MIP.terms (MIP.objExpr obj)]-    (obj3,obj3_c) <- Integer.linearize enc obj2--    let transformObjVal :: Integer -> Rational-        transformObjVal val = fromIntegral (val + obj3_c) / fromIntegral d--        transformModel :: SAT.Model -> Map String Integer-        transformModel m = Map.fromList-          [ (MIP.fromVar v, Integer.eval m (vmap Map.! v)) | v <- Set.toList ivs ]--        printModel :: Map String Integer -> IO ()-        printModel m = do-          forM_ (Map.toList m) $ \(v, val) -> do-            printf "v %s = %d\n" v val-          hFlush stdout--        writeSol :: Map String Integer -> Rational -> IO ()-        writeSol m val = do-          case optWriteFile opt of-            Nothing -> return ()-            Just fname -> do-              writeFile fname (GurobiSol.render (fmap fromInteger m) (Just (fromRational val)))--    pbo <- PBO.newOptimizer solver obj3-    setupOptimizer pbo opt-    PBO.setOnUpdateBestSolution pbo $ \_ val -> do-      putOLine $ showRational (optPrintRational opt) (transformObjVal val)--    finally (PBO.optimize pbo) $ do-      ret <- PBO.getBestSolution pbo-      case ret of-        Nothing -> do-          b <- PBO.isUnsat pbo-          if b-            then putSLine "UNSATISFIABLE"-            else putSLine "UNKNOWN"-        Just (m,val) -> do-          b <- PBO.isOptimum pbo-          if b-            then putSLine "OPTIMUM FOUND"-            else putSLine "SATISFIABLE"-          let m2   = transformModel m-              val2 = transformObjVal val-          printModel m2-          writeSol m2 val2--  where-    ivs = MIP.integerVariables mip-    nivs = MIP.variables mip `Set.difference` ivs--    asInteger :: Rational -> Integer-    asInteger r-      | denominator r /= 1 = error (show r ++ " is not integer")-      | otherwise = numerator r-    -    nonAdjacentPairs :: [a] -> [(a,a)]-    nonAdjacentPairs (x1:x2:xs) = [(x1,x3) | x3 <- xs] ++ nonAdjacentPairs (x2:xs)-    nonAdjacentPairs _ = []--    asBin :: Integer.Expr -> SAT.Lit-    asBin (Integer.Expr [(1,[lit])]) = lit-    asBin _ = error "asBin: failure"---- --------------------------------------------------------------------------writeSOLFile :: Options -> SAT.Model -> Maybe Integer -> Int -> IO ()-writeSOLFile opt m obj nbvar = do-  case optWriteFile opt of-    Nothing -> return ()-    Just fname -> do-      let m2 = Map.fromList [("x" ++ show x, if b then 1 else 0) | (x,b) <- assocs m, x <= nbvar]-      writeFile fname (GurobiSol.render (Map.map fromInteger m2) (fmap fromInteger obj))
− toysmt/ToySolver/SMT/SMTLIB2Solver.hs
@@ -1,829 +0,0 @@-{-# OPTIONS_GHC -Wall #-}--------------------------------------------------------------------------------- |--- Module      :  ToySolver.SMT.SMTLIB2Solver--- Copyright   :  (c) Masahiro Sakai 2015--- License     :  BSD-style------ Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  experimental--- Portability :  portable----------------------------------------------------------------------------------module ToySolver.SMT.SMTLIB2Solver-  ( module Smtlib.Syntax.Syntax-  , ShowSL (..)--  -- * The solver type-  , Solver-  , newSolver--  -- * High-level API-  , execCommand-  , execCommandString-  , runCommand-  , runCommandString-  , printResponse--  -- * Individual commands--  -- ** (Re)starting and terminating-  , reset-  , setLogic-  , setOption-  , exit--  -- ** Modifying the assertion stack-  , push-  , pop-  , resetAssertions--  -- ** Introducing new symbols-  , declareSort-  , defineSort-  , declareConst-  , declareFun-  , defineFun-  , defineFunRec-  , defineFunsRec--  -- ** Asserting and inspecting formulas-  , assert-  , getAssertions--  -- ** Checking for satisfiability-  , checkSat-  , checkSatAssuming--  -- ** Inspecting models-  , getValue-  , getAssignment-  , getModel--  -- ** Inspecting proofs-  , getProof-  , getUnsatCore-  , getUnsatAssumptions--  -- ** Inspecting settings-  , getInfo-  , getOption--  -- ** Script information-  , setInfo-  , echo-  ) where--import Control.Applicative-import qualified Control.Exception as E-import Control.Monad-import Data.IORef-import Data.Map (Map)-import qualified Data.Map as Map-import Data.Maybe (catMaybes)-import Data.Ratio-import qualified Data.Version as V-import Numeric (readFloat, readHex)-import System.Exit-import System.IO-import qualified Text.Parsec as Parsec--import qualified ToySolver.SMT as SMT-import ToySolver.Version-import Smtlib.Syntax.Syntax-import Smtlib.Syntax.ShowSL-import qualified Smtlib.Parsers.CommandsParsers as CommandsParsers-import qualified Smtlib.Parsers.CommonParsers as CommonParsers---- ------------------------------------------------------------------------data Mode-  = ModeStart-  | ModeAssert-  | ModeSat-  | ModeUnsat-  deriving (Eq, Ord, Show)--type EEnv = Map String EEntry-type SortEnv = Map String SortEntry-type Env = (EEnv, SortEnv)--data EEntry-  = EFSymBuiltin SMT.FSym-  | EFSymDeclared SMT.FSym [SMT.Sort] SMT.Sort-  | EExpr SMT.Expr Bool-  | EFunDef EEnv [(String, SMT.Sort)] SMT.Sort Term--data SortEntry-  = SortSym SMT.SSym-  | SortExpr SMT.Sort-  | SortDef SortEnv [String] Sort--interpretSort :: SortEnv -> Sort -> SMT.Sort-interpretSort env s =-  case s of-    SortId ident -> f (idToName ident) []-    SortIdentifiers ident args -> f (idToName ident) args-  where-    f name args =-      case Map.lookup name env of-        Nothing -> error ("unknown sort: " ++ name)-        Just (SortSym ssym) -> SMT.Sort ssym []-        Just (SortExpr s') -> s'-        Just (SortDef env' params body) ->-          interpretSort (Map.fromList (zip params (map (SortExpr . interpretSort env) args)) `Map.union` env') body--interpretFun :: EEnv -> Term -> SMT.Expr-interpretFun env t =-  case t of-    TermSpecConstant (SpecConstantNumeral n) -> SMT.EFrac (fromInteger n)-    TermSpecConstant (SpecConstantDecimal s) -> SMT.EFrac $ fst $ head $ readFloat s-    TermSpecConstant (SpecConstantHexadecimal s) -> SMT.EFrac $ fst $ head $ readHex s-    TermSpecConstant c@(SpecConstantBinary _s) -> error (show c)-    TermSpecConstant c@(SpecConstantString _s) -> error (show c)-    TermQualIdentifier qid -> f qid []-    TermQualIdentifierT  qid args -> f qid args-    TermLet bindings body ->-      interpretFun (Map.fromList [(v, EExpr (interpretFun env t2) False) | VB v t2 <- bindings] `Map.union` env) body-    TermForall _bindings _body -> error "universal quantifiers are not supported yet"-    TermExists _bindings _body -> error "existential quantifiers are not supported yet"-    TermAnnot t2 _ -> interpretFun env t2 -- annotations are not supported yet-  where-    getName :: QualIdentifier -> String-    getName (QIdentifier ident) = idToName ident-    getName (QIdentifierAs ident _sort) = idToName ident--    f qid args =-      case Map.lookup (getName qid) env of-        Nothing -> error ("unknown function symbol: " ++ getName qid)-        Just (EExpr e _) -> e-        Just (EFSymBuiltin fsym) -> SMT.EAp fsym (map (interpretFun env) args)-        Just (EFSymDeclared fsym _ _) -> SMT.EAp fsym (map (interpretFun env) args)-        Just (EFunDef env' params _y body) ->-          interpretFun (Map.fromList [(p,a) | ((p,_s),a) <- zip params (map (\t -> EExpr (interpretFun env t) False) args) ] `Map.union` env') body--valueToTerm :: SMT.Value -> Term-valueToTerm (SMT.ValRational v) =-  case v `compare` 0 of-    GT -> f v-    EQ -> TermSpecConstant (SpecConstantNumeral 0)-    LT -> TermQualIdentifierT (QIdentifier $ ISymbol "-") [ f (negate v) ]-  where-    f v = TermQualIdentifierT (QIdentifier $ ISymbol "/")-          [ TermSpecConstant (SpecConstantNumeral (numerator v))-          , TermSpecConstant (SpecConstantNumeral (denominator v))-          ]-valueToTerm (SMT.ValBool b) =-  TermQualIdentifier $ QIdentifier $ ISymbol $ if b then "true" else "false"-valueToTerm (SMT.ValUninterpreted n s) =-  TermQualIdentifier $ QIdentifierAs (ISymbol $ "@" ++ show n) (sortToSortTerm s)--sortToSortTerm :: SMT.Sort -> Sort-sortToSortTerm (SMT.Sort SMT.SSymBool []) = SortId (ISymbol "Bool")-sortToSortTerm (SMT.Sort SMT.SSymReal []) = SortId (ISymbol "Real")-sortToSortTerm (SMT.Sort (SMT.SSymUserDeclared name 0) []) = SortId (nameToId name)-sortToSortTerm (SMT.Sort (SMT.SSymUserDeclared name _arity) xs) = SortIdentifiers (nameToId name) (map sortToSortTerm xs)-sortToSortTerm s = error ("unknown sort: " ++ show s)--idToName :: Identifier -> String-idToName = showSL--nameToId :: String -> Identifier-nameToId s =-  case Parsec.parse CommonParsers.parseIdentifier "" s of-    Left e -> error (show e)-    Right x -> x---- ------------------------------------------------------------------------data Solver-  = Solver-  { svSMTSolverRef :: !(IORef SMT.Solver)-  , svEnvRef :: !(IORef Env)-  , svModeRef :: !(IORef Mode)-  , svSavedContextsRef :: !(IORef [(Maybe (EEnv, SortEnv), [Term])])-  , svStatusRef :: IORef (Maybe Bool)-  , svAssertionsRef :: IORef [Term]-  , svRegularOutputChannelRef :: !(IORef (String, Handle))-  , svDiagnosticOutputChannelRef :: !(IORef (String, Handle))-  , svPrintSuccessRef :: !(IORef Bool)-  , svProduceAssertionsRef :: !(IORef Bool)-  , svProduceAssignmentRef :: !(IORef Bool)-  , svProduceModelsRef :: !(IORef Bool)-  , svProduceUnsatAssumptionsRef :: !(IORef Bool)-  , svProduceUnsatCoresRef :: !(IORef Bool)-  , svGlobalDeclarationsRef :: !(IORef Bool)-  , svUnsatAssumptionsRef :: !(IORef [Term])-  }--newSolver :: IO Solver-newSolver = do-  solverRef <- newIORef =<< SMT.newSolver-  envRef <- newIORef initialEnv-  modeRef <- newIORef ModeStart-  savedContextsRef <- newIORef []-  statusRef <- newIORef Nothing-  assertionsRef <- newIORef ([] :: [Term])-  regOutputRef <- newIORef ("stdout", stdout)-  diagOutputRef <- newIORef ("stderr", stderr)-  printSuccessRef <- newIORef True-  produceAssertionsRef <- newIORef False-  produceAssignmentRef <- newIORef False-  produceModelsRef <- newIORef False-  produceUnsatAssumptionsRef <- newIORef False-  produceUnsatCoresRef <- newIORef False  -  globalDeclarationsRef <- newIORef False-  unsatAssumptionsRef <- newIORef undefined-  return $-    Solver-    { svSMTSolverRef = solverRef-    , svEnvRef = envRef-    , svModeRef = modeRef-    , svUnsatAssumptionsRef = unsatAssumptionsRef-    , svSavedContextsRef = savedContextsRef-    , svStatusRef = statusRef-    , svAssertionsRef = assertionsRef-    , svRegularOutputChannelRef = regOutputRef-    , svDiagnosticOutputChannelRef = diagOutputRef-    , svPrintSuccessRef = printSuccessRef-    , svProduceAssertionsRef = produceAssertionsRef-    , svProduceAssignmentRef = produceAssignmentRef-    , svProduceModelsRef = produceModelsRef-    , svProduceUnsatCoresRef = produceUnsatCoresRef-    , svProduceUnsatAssumptionsRef = produceUnsatAssumptionsRef-    , svGlobalDeclarationsRef = globalDeclarationsRef-    }--initialEnv :: Env-initialEnv = (fenv, senv)-  where-    fenv = Map.fromList-      [ (name, EFSymBuiltin name)-      | name <- ["=", "true", "false", "not", "and", "or", "ite", "=>", "distinct", "+", "-", "*", "/", ">=", "<=", ">", "<"]-      ]-    senv = Map.fromList-      [ ("Real", SortExpr SMT.sReal)-      , ("Bool", SortExpr SMT.sBool)-      ]--execCommand :: Solver -> Command -> IO ()-execCommand solver cmd = do-  -- putStrLn $ showSL cmd-  printResponse solver =<< runCommand solver cmd--printResponse :: Solver -> CmdResponse -> IO ()-printResponse solver rsp = do-  b <- readIORef (svPrintSuccessRef solver)-  unless (rsp == CmdGenResponse Success && not b) $ do-    (_,h) <- readIORef (svRegularOutputChannelRef solver)-    hPutStrLn h (showSL rsp)--runCommand :: Solver -> Command -> IO CmdResponse-runCommand solver cmd = E.handle h $ do-  case cmd of-    SetLogic logic -> const (CmdGenResponse Success) <$> setLogic solver logic-    SetOption opt -> const (CmdGenResponse Success) <$> setOption solver opt-    GetOption s -> CmdGetOptionResponse <$> getOption solver s-    SetInfo attr -> const (CmdGenResponse Success) <$> setInfo solver attr-    GetInfo flags -> CmdGetInfoResponse <$> getInfo solver flags-    Push n -> const (CmdGenResponse Success) <$> push solver n-    Pop n -> const (CmdGenResponse Success) <$> pop solver n-    DeclareSort name arity -> const (CmdGenResponse Success) <$> declareSort solver name arity-    DefineSort name xs body -> const (CmdGenResponse Success) <$> defineSort solver name xs body-    DeclareConst name y -> const (CmdGenResponse Success) <$> declareConst solver name y-    DeclareFun name xs y -> const (CmdGenResponse Success) <$> declareFun solver name xs y-    DefineFun name xs y body -> const (CmdGenResponse Success) <$> defineFun solver name xs y body-    DefineFunRec name xs y body -> const (CmdGenResponse Success) <$> defineFunRec solver name xs y body-    DefineFunsRec fundecs terms -> const (CmdGenResponse Success) <$> defineFunsRec solver fundecs terms-    Assert tm -> const (CmdGenResponse Success) <$> assert solver tm-    GetAssertions -> CmdGetAssertionsResponse <$> getAssertions solver-    CheckSat -> CmdCheckSatResponse <$> checkSat solver-    CheckSatAssuming ts -> CmdCheckSatResponse <$> checkSatAssuming solver ts-    GetValue ts -> CmdGetValueResponse <$> getValue solver ts-    GetAssignment -> CmdGetAssignmentResponse <$> getAssignment solver-    GetModel -> CmdGetModelResponse <$> getModel solver-    GetProof -> CmdGetProofResponse <$> getProof solver-    GetUnsatCore -> CmdGetUnsatCoreResponse <$> getUnsatCore solver-    GetUnsatAssumptions -> CmdGetUnsatAssumptionsResponse <$> getUnsatAssumptions solver  -    Reset -> const (CmdGenResponse Success) <$> reset solver-    ResetAssertions -> const (CmdGenResponse Success) <$> resetAssertions solver-    Echo s -> CmdEchoResponse <$> echo solver s-    Exit -> const (CmdGenResponse Success) <$> exit solver-  where-    h SMT.Unsupported = return (CmdGenResponse Unsupported)-    h (SMT.Error s) = return $ CmdGenResponse $-     -- GenResponse type uses strings in printed form.-     Error $ "\"" ++ concat [if c == '"' then "\"\"" else [c] | c <- s] ++ "\""--execCommandString :: Solver -> String -> IO ()-execCommandString solver cmd = do-  printResponse solver =<< runCommandString solver cmd--runCommandString :: Solver -> String -> IO CmdResponse-runCommandString solver cmd =-  case Parsec.parse (Parsec.spaces >> CommandsParsers.parseCommand <* Parsec.eof) "" cmd of-    Left err -> -      -- GenResponse type uses strings in printed form.-      return $ CmdGenResponse $ Error $ "\"" ++ concat [if c == '"' then "\"\"" else [c] | c <- show err] ++ "\""-    Right cmd ->-      runCommand solver cmd---- ------------------------------------------------------------------------reset :: Solver -> IO GenResponse-reset solver = do-  writeIORef (svSMTSolverRef solver) =<< SMT.newSolver-  writeIORef (svEnvRef solver) initialEnv-  writeIORef (svModeRef solver) ModeStart-  writeIORef (svSavedContextsRef solver) []-  writeIORef (svStatusRef solver) Nothing-  writeIORef (svRegularOutputChannelRef solver) ("stdout",stdout)-  writeIORef (svDiagnosticOutputChannelRef solver) ("stderr",stderr)-  writeIORef (svPrintSuccessRef solver) True-  writeIORef (svProduceAssertionsRef solver) False-  writeIORef (svProduceAssignmentRef solver) False-  writeIORef (svProduceModelsRef solver) False-  writeIORef (svProduceUnsatAssumptionsRef solver) False-  writeIORef (svProduceUnsatCoresRef solver) False-  writeIORef (svUnsatAssumptionsRef solver) undefined-  return Success--setLogic :: Solver -> String -> IO ()-setLogic solver logic = do-  mode <- readIORef (svModeRef solver)-  if mode /= ModeStart then do-    E.throwIO $ SMT.Error "set-logic can only be used in start mode"-  else do-    writeIORef (svModeRef solver) ModeAssert-    case logic of-      "QF_UFLRA" -> return ()-      "QF_UFRDL" -> return ()-      "QF_UF" -> return ()-      "QF_RDL" -> return ()-      "QF_LRA" -> return ()-      "ALL" -> return ()-      _ -> E.throwIO SMT.Unsupported--setOption :: Solver -> Option -> IO ()-setOption solver opt = do-  mode <- readIORef (svModeRef solver)-  case opt of-    PrintSuccess b -> do-      writeIORef (svPrintSuccessRef solver) b-    ExpandDefinitions _b -> do-      -- expand-definitions has been removed in SMT-LIB 2.5.-      E.throwIO SMT.Unsupported-    InteractiveMode b -> do-      -- interactive-mode is the old name for produce-assertions. Deprecated.-      unless (mode == ModeStart) $ do-        E.throwIO $ SMT.Error "interactive-mode option can be set only in start mode"-      writeIORef (svProduceAssertionsRef solver) b-      return ()-    ProduceProofs b -> do-      if mode /= ModeStart then-        E.throwIO $ SMT.Error "produce-proofs option can be set only in start mode"-      else if b then-        E.throwIO SMT.Unsupported-      else-        return ()-    ProduceUnsatCores b -> do-      unless (mode == ModeStart) $ do-        E.throwIO $ SMT.Error "produce-unsat-cores option can be set only in start mode"-      writeIORef (svProduceUnsatCoresRef solver) b-      return ()-    ProduceUnsatAssumptions b -> do-      unless (mode == ModeStart) $ do-        E.throwIO $ SMT.Error "produce-unsat-assumptions option can be set only in start mode"-      writeIORef (svProduceUnsatAssumptionsRef solver) b-      return ()-    ProduceModels b -> do-      unless (mode == ModeStart) $ do-        E.throwIO $ SMT.Error "produce-models option can be set only in start mode"-      writeIORef (svProduceModelsRef solver) b-      return ()-    ProduceAssignments b -> do-      unless (mode == ModeStart) $ do-        E.throwIO $ SMT.Error "produce-assignments option can be set only in start mode"-      writeIORef (svProduceAssignmentRef solver) b-      return ()-    ProduceAssertions b -> do-      unless (mode == ModeStart) $ do-        E.throwIO $ SMT.Error "produce-assertions option can be set only in start mode"-      writeIORef (svProduceAssertionsRef solver) b-      return ()-    GlobalDeclarations b -> do-      unless (mode == ModeStart) $ do-        E.throwIO $ SMT.Error "global-declarations option can be set only in start mode"-      writeIORef (svGlobalDeclarationsRef solver) b-      smt <- readIORef (svSMTSolverRef solver)-      SMT.setGlobalDeclarations smt b-    RegularOutputChannel fname -> do-      h <- if fname == "stdout" then-             return stdout-           else-             openFile fname AppendMode-      writeIORef (svRegularOutputChannelRef solver) (fname, h)-      return ()-    DiagnosticOutputChannel fname -> do-      h <- if fname == "stderr" then-             return stderr-           else-             openFile fname AppendMode-      writeIORef (svDiagnosticOutputChannelRef solver) (fname, h)-      return ()-    RandomSeed _i ->-      if mode /= ModeStart then-        E.throwIO $ SMT.Error "random-seed option can be set only in start mode"-      else-        E.throwIO SMT.Unsupported-    Verbosity _lv -> E.throwIO SMT.Unsupported-    ReproducibleResourceLimit _val -> do-      if mode /= ModeStart then-        E.throwIO $ SMT.Error "reproducible-resource-limit option can be set only in start mode"-      else-        E.throwIO SMT.Unsupported-    OptionAttr _attr -> E.throwIO SMT.Unsupported--getOption :: Solver -> String -> IO GetOptionResponse-getOption solver opt =-  case opt of-    ":expand-definitions" -> do-      -- expand-definitions has been removed in SMT-LIB 2.5.-      let b = False-      return $ AttrValueSymbol (showSL b)-    ":global-declarations" -> do-      b <- readIORef (svGlobalDeclarationsRef solver)-      return $ AttrValueSymbol (showSL b)-    ":interactive-mode" -> do-      -- interactive-mode is the old name for produce-assertions. Deprecated.-      b <- readIORef (svProduceAssertionsRef solver)-      return $ AttrValueSymbol (showSL b)-    ":print-success" -> do-      b <- readIORef (svPrintSuccessRef solver)-      return $ AttrValueSymbol (showSL b) -    ":produce-assertions" -> do-      b <- readIORef (svProduceAssertionsRef solver)-      return $ AttrValueSymbol (showSL b)-    ":produce-assignments" -> do-      b <- readIORef (svProduceAssignmentRef solver)-      return $ AttrValueSymbol (showSL b)-    ":produce-models" -> do-      b <- readIORef (svProduceModelsRef solver)-      return $ AttrValueSymbol (showSL b)-    ":produce-proofs" -> do-      let b = False -- default value-      return $ AttrValueSymbol (showSL b)-    ":produce-unsat-cores" -> do-      b <- readIORef (svProduceUnsatCoresRef solver)-      return $ AttrValueSymbol (showSL b)-    ":produce-unsat-assumptions" -> do-      b <- readIORef (svProduceUnsatAssumptionsRef solver)-      return $ AttrValueSymbol (showSL b)-    ":regular-output-channel" -> do-      (fname,_) <- readIORef (svRegularOutputChannelRef solver)-      return $ AttrValueConstant (SpecConstantString fname)-    ":diagnostic-output-channel" -> do-      (fname,_) <- readIORef (svDiagnosticOutputChannelRef solver)-      return $ AttrValueConstant (SpecConstantString fname)-    ":random-seed" -> do-      return $ AttrValueConstant (SpecConstantNumeral 0) -- default value-    ":reproducible-resource-limit" -> do-      return $ AttrValueConstant (SpecConstantNumeral 0) -- default value-    ":verbosity" -> do-      return $ AttrValueConstant (SpecConstantNumeral 0) -- default value-    _ -> do-      E.throwIO SMT.Unsupported--setInfo :: Solver -> Attribute -> IO ()-setInfo solver (AttributeVal ":status" (AttrValueSymbol s)) = do-  v <- case s of-         "sat" -> return $ Just True-         "unsat" -> return $ Just False-         "unknown" -> return $ Nothing-         _ -> E.throwIO $ SMT.Error $ "invalid status value: " ++ s-  writeIORef (svStatusRef solver) v-setInfo _solver _ = return ()--getInfo :: Solver -> InfoFlags -> IO GetInfoResponse-getInfo solver flags = do-  mode <- readIORef (svModeRef solver)-  case flags of-    ErrorBehavior -> return [ResponseErrorBehavior ContinuedExecution]-    Name -> return [ResponseName "toysmt"]-    Authors -> return [ResponseName "Masahiro Sakai"]-    Version -> return [ResponseVersion (V.showVersion version)]-    Status -> E.throwIO SMT.Unsupported-    ReasonUnknown -> do-      if mode /= ModeSat then-        E.throwIO $ SMT.Error "Executions of get-info with :reason-unknown are allowed only when the solver is in sat mode following a check command whose response was unknown."-      else-        return [ResponseReasonUnknown Incomplete]-    AllStatistics -> do-      if not (mode == ModeSat || mode == ModeUnsat) then-        E.throwIO $ SMT.Error "Executions of get-info with :all-statistics are allowed only when the solver is in sat or unsat mode."-      else-        E.throwIO SMT.Unsupported-    AssertionStackLevels -> do-      saved <- readIORef (svSavedContextsRef solver)-      let n = length saved-      n `seq` return [ResponseAssertionStackLevels n]-    InfoFlags _s -> do-      E.throwIO SMT.Unsupported--push :: Solver -> Int -> IO ()-push solver n = do-  replicateM_ n $ do-    (env,senv) <- readIORef (svEnvRef solver)-    assertions <- readIORef (svAssertionsRef solver)-    globalDeclarations <- readIORef (svGlobalDeclarationsRef solver)-    if globalDeclarations then-      modifyIORef (svSavedContextsRef solver) ((Nothing, assertions) :)-    else-      modifyIORef (svSavedContextsRef solver) ((Just (env,senv), assertions) :)-    SMT.push =<< readIORef (svSMTSolverRef solver)-    writeIORef (svModeRef solver) ModeAssert--pop :: Solver -> Int -> IO ()-pop solver n = do-  replicateM_ n $ do-    cs <- readIORef (svSavedContextsRef solver)-    case cs of-      [] -> E.throwIO $ SMT.Error "pop from empty context"-      ((m,assertions) : cs) -> do-        case m of-          Just (env,senv) -> writeIORef (svEnvRef solver) (env,senv)-          Nothing -> return ()-        writeIORef (svAssertionsRef solver) assertions-        writeIORef (svSavedContextsRef solver) cs-        SMT.pop =<< readIORef (svSMTSolverRef solver)-        writeIORef (svModeRef solver) ModeAssert--resetAssertions :: Solver -> IO ()-resetAssertions solver = do-  cs <- readIORef (svSavedContextsRef solver)-  pop solver (length cs)--echo :: Solver -> String -> IO String-echo _solver s = return s--declareSort :: Solver -> String -> Int -> IO ()-declareSort solver name arity = do-  smt <- readIORef (svSMTSolverRef solver)-  s <- SMT.declareSSym smt name arity-  insertSort solver name (SortSym s)-  writeIORef (svModeRef solver) ModeAssert--defineSort :: Solver -> String -> [String] -> Sort -> IO ()-defineSort solver name xs body = do-  (_, senv) <- readIORef (svEnvRef solver)-  insertSort solver name (SortDef senv xs body)-  writeIORef (svModeRef solver) ModeAssert--declareConst :: Solver -> String -> Sort -> IO ()-declareConst solver name y = declareFun solver name [] y--declareFun :: Solver -> String -> [Sort] -> Sort -> IO ()-declareFun solver name xs y = do-  smt <- readIORef (svSMTSolverRef solver)-  (_, senv) <- readIORef (svEnvRef solver)-  let argsSorts = map (interpretSort senv) xs-      resultSort = interpretSort senv y-  f <- SMT.declareFSym smt name argsSorts resultSort-  insertFun solver name (EFSymDeclared f argsSorts resultSort)-  writeIORef (svModeRef solver) ModeAssert--defineFun :: Solver -> String -> [SortedVar] -> Sort -> Term -> IO ()-defineFun solver name xs y body = do-  writeIORef (svModeRef solver) ModeAssert-  (_, senv) <- readIORef (svEnvRef solver)-  let xs' = map (\(SV x s) -> (x, interpretSort senv s)) xs-      y'  = interpretSort senv y-  if null xs' then do-    body' <- processNamed solver body-    (fenv, _) <- readIORef (svEnvRef solver)-    -- use EExpr?-    insertFun solver name (EFunDef fenv [] y' body')-  else do-    (fenv, _) <- readIORef (svEnvRef solver)-    insertFun solver name (EFunDef fenv xs' y' body)-  writeIORef (svModeRef solver) ModeAssert--defineFunRec :: Solver -> String -> [SortedVar] -> Sort -> Term -> IO ()-defineFunRec _solver _name _xs _y _body = do-  E.throwIO SMT.Unsupported--defineFunsRec :: Solver -> [FunDec] -> [Term] -> IO ()-defineFunsRec _solver _fundecs _terms = do-  E.throwIO SMT.Unsupported--assert :: Solver -> Term -> IO ()-assert solver tm = do-  let mname =-        case tm of-          TermAnnot _body attrs-            | name:_ <- [name | AttributeVal ":named" (AttrValueSymbol name) <- attrs] ->-                Just name-          _ -> Nothing-  tm' <- processNamed solver tm-  smt <- readIORef (svSMTSolverRef solver)-  (env,_) <- readIORef (svEnvRef solver)-  case mname of-    Nothing -> SMT.assert smt (interpretFun env tm')-    Just name -> SMT.assertNamed smt name (interpretFun env tm')-  do b <- readIORef (svProduceAssertionsRef solver)-     when b $ modifyIORef (svAssertionsRef solver) (tm :)-  writeIORef (svModeRef solver) ModeAssert--getAssertions :: Solver -> IO GetAssertionsResponse-getAssertions solver = do-  mode <- readIORef (svModeRef solver)-  when (mode == ModeStart) $ do-    E.throwIO $ SMT.Error "get-assertions cannot be used in start mode"-  b <- readIORef (svProduceAssertionsRef solver)-  unless b $ do-    E.throwIO $ SMT.Error ":produce-assertions is not enabled"-  reverse <$> readIORef (svAssertionsRef solver)--checkSat :: Solver -> IO CheckSatResponse-checkSat solver = checkSatAssuming solver []--checkSatAssuming :: Solver -> [Term] -> IO CheckSatResponse-checkSatAssuming solver xs = do-  smt <- readIORef (svSMTSolverRef solver)--  (env,_) <- readIORef (svEnvRef solver)-  ref <- newIORef Map.empty-  ys <- forM xs $ \x -> do-    let y = interpretFun env x-    modifyIORef ref (Map.insert y x)-    return y--  ret <- SMT.checkSATAssuming smt ys--  do expected <- readIORef (svStatusRef solver)-     writeIORef (svStatusRef solver) Nothing -- I'm not sure if we should reset or not.-     h <- snd <$> readIORef (svDiagnosticOutputChannelRef solver)-     case expected of-       Just True | not ret -> hPutStrLn h "WARNING: unexpected unsat; expecting sat"-       Just False | ret -> hPutStrLn h "WARNING: unexpected sat; expecting unsat"-       _ -> return ()-     hFlush h--  if ret then do-    writeIORef (svModeRef solver) ModeSat-    return Sat-  else do-    writeIORef (svModeRef solver) ModeUnsat-    m <- readIORef ref-    es <- SMT.getUnsatAssumptions smt-    writeIORef (svUnsatAssumptionsRef solver) [m Map.! e | e <- es]-    return Unsat--getValue :: Solver -> [Term] -> IO GetValueResponse-getValue solver ts = do-  ts <- mapM (processNamed solver) ts  -  mode <- readIORef (svModeRef solver)-  unless (mode == ModeSat) $ do-    E.throwIO $ SMT.Error "get-value can only be used in sat mode"-  smt <- readIORef (svSMTSolverRef solver)-  m <- SMT.getModel smt-  (env,_) <- readIORef (svEnvRef solver)-  forM ts $ \t -> do-    let e = interpretFun env t-    let v = SMT.eval m e-    return $ ValuationPair t (valueToTerm v)--getAssignment :: Solver -> IO GetAssignmentResponse-getAssignment solver = do-  mode <- readIORef (svModeRef solver)-  unless (mode == ModeSat) $ do-    E.throwIO $ SMT.Error "get-assignment can only be used in sat mode"-  smt <- readIORef (svSMTSolverRef solver)-  m <- SMT.getModel smt-  (env, _) <- readIORef (svEnvRef solver)-  liftM concat $ forM (Map.toList env) $ \(name, entry) -> do-    case entry of-      EExpr e True -> do-        s <- SMT.exprSort smt e-        if s /= SMT.sBool then do-          return []-        else do-          let v = SMT.eval m e-          case v of-            (SMT.ValBool b) -> return [TValuationPair name b]-            _ -> E.throwIO $ SMT.Error "get-assignment: should not happen"-      _ -> return []--getModel :: Solver -> IO GetModelResponse-getModel solver = do-  mode <- readIORef (svModeRef solver)-  unless (mode == ModeSat) $ do-    E.throwIO $ SMT.Error "get-model can only be used in sat mode"-  smt <- readIORef (svSMTSolverRef solver)-  m <- SMT.getModel smt-  (env, _) <- readIORef (svEnvRef solver)-  liftM catMaybes $ forM (Map.toList env) $ \(name, entry) -> do-    case entry of-      EFSymDeclared sym argsSorts resultSort -> do-        case SMT.evalFSym m sym of-          SMT.FunDef [] val ->  do -- constant-            return $ Just $ DefineFun name [] (sortToSortTerm resultSort) (valueToTerm val)-          SMT.FunDef tbl defaultVal -> do -- proper function-            let argsSV :: [SortedVar]-                argsSV = [SV ("x!" ++ show i) (sortToSortTerm s) | (i,s) <- zip [(1::Int)..] argsSorts]-                args :: [Term]-                args = [TermQualIdentifier (QIdentifier (ISymbol x)) | SV x _ <- argsSV]-                f :: ([SMT.Value], SMT.Value) -> Term -> Term-                f (vals,val) tm = -                  TermQualIdentifierT (QIdentifier (ISymbol "ite")) [cond, valueToTerm val, tm]-                  where-                    cond =-                      case zipWith (\arg val -> TermQualIdentifierT (QIdentifier (ISymbol "=")) [arg, valueToTerm val]) args vals of-                        [c] -> c-                        cs -> TermQualIdentifierT (QIdentifier (ISymbol "and")) cs-            return $ Just $ DefineFun name argsSV (sortToSortTerm resultSort) $-              foldr f (valueToTerm defaultVal) tbl-      _ -> return Nothing--getProof :: Solver -> IO GetProofResponse-getProof solver = do-  mode <- readIORef (svModeRef solver)-  if mode /= ModeUnsat then-    E.throwIO $ SMT.Error "get-proof can only be used in unsat mode"-  else-    E.throwIO SMT.Unsupported--getUnsatCore :: Solver -> IO GetUnsatCoreResponse-getUnsatCore solver = do-  smt <- readIORef (svSMTSolverRef solver)-  mode <- readIORef (svModeRef solver)-  unless (mode == ModeUnsat) $ do-    E.throwIO $ SMT.Error "get-unsat-core can only be used in unsat mode"-  SMT.getUnsatCore smt--getUnsatAssumptions :: Solver -> IO [Term]-getUnsatAssumptions solver = do-  mode <- readIORef (svModeRef solver)-  unless (mode == ModeUnsat) $ do-    E.throwIO $ SMT.Error "get-unsat-assumptions can only be used in unsat mode"-  readIORef (svUnsatAssumptionsRef solver)--exit :: Solver -> IO ()-exit _solver = exitSuccess---- ------------------------------------------------------------------------insertSort :: Solver -> String -> SortEntry -> IO ()-insertSort solver name sdef = do-  (fenv, senv) <- readIORef (svEnvRef solver)-  case Map.lookup name senv of-    Nothing -> writeIORef (svEnvRef solver) (fenv, Map.insert name sdef senv)-    Just _ -> E.throwIO $ SMT.Error (name ++ " is already used")--insertFun :: Solver -> String -> EEntry -> IO ()-insertFun solver name fdef = do-  (fenv, senv) <- readIORef (svEnvRef solver)-  case Map.lookup name fenv of-    Nothing -> writeIORef (svEnvRef solver) (Map.insert name fdef fenv, senv)-    Just _ -> E.throwIO $ SMT.Error (name ++ " is already used")---- TODO: check closedness of terms-processNamed :: Solver -> Term -> IO Term-processNamed solver = f-  where-    f t@(TermSpecConstant _) = return t-    f t@(TermQualIdentifier _) = return t-    f (TermQualIdentifierT qid args) = do-      args' <- mapM f args-      return $ TermQualIdentifierT qid args'-    f (TermLet bindings body) = do-      body' <- f body-      return $ TermLet bindings body'-    f (TermForall bindings body) = do-      body' <- f body-      return $ TermForall bindings body'-    f (TermExists bindings body) = do-      body' <- f body-      return $ TermExists bindings body'-    f (TermAnnot body attrs) = do-      body' <- f body-      forM_ attrs $ \attr -> do-        case attr of-          AttributeVal ":named" val ->-            case val of-              AttrValueSymbol name -> do-                (env,_) <- readIORef (svEnvRef solver)-                let e = interpretFun env body'-                -- smt <- readIORef (svSMTSolverRef solver)-                -- s <- SMT.exprSort smt e-                insertFun solver name (EExpr e True)-              _ -> E.throwIO $ SMT.Error ":named attribute value should be a symbol"-          _ -> return ()-      let attrs' = [attr | attr <- attrs, attrName attr /= ":named"]-            where-              attrName (Attribute s) = s-              attrName (AttributeVal s _v) = s-      if null attrs' then-        return body'-      else-        return $ TermAnnot body' attrs'
− toysmt/toysmt.hs
@@ -1,143 +0,0 @@-{-# OPTIONS_GHC -Wall #-}-{-# LANGUAGE CPP #-}--------------------------------------------------------------------------------- |--- Module      :  toysmt--- Copyright   :  (c) Masahiro Sakai 2015--- License     :  BSD-style------ Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  experimental--- Portability :  non-portable (CPP)----------------------------------------------------------------------------------module Main where--import Control.Applicative ((<*))-import Control.Monad-import Control.Monad.Trans-import Data.Default.Class-import Data.Version-import System.Console.GetOpt-#ifdef USE_HASKELINE_PACKAGE-import qualified System.Console.Haskeline as Haskeline-#endif-import System.Environment-import System.Exit-import System.IO-import Text.Parsec-import Text.Parsec.String--import Smtlib.Parsers.CommandsParsers--import ToySolver.Version-import ToySolver.SMT.SMTLIB2Solver--data Mode-  = ModeHelp-  | ModeVersion-  | ModeInteractive-  deriving (Eq, Ord, Bounded, Enum)--data Options-  = Options-  { optMode :: Maybe Mode-  , optInteractive :: Bool-  }--instance Default Options where-  def =-    Options-    { optMode = Nothing-    , optInteractive = False -    }--options :: [OptDescr (Options -> Options)]-options =-    [ Option ['h'] ["help"]   (NoArg (\opt -> opt{ optMode = Just ModeHelp   })) "show help"-    , Option [] ["version"]   (NoArg (\opt -> opt{ optMode = Just ModeVersion})) "show version"-    , Option [] ["interactive"] (NoArg (\opt -> opt{ optMode = Just ModeInteractive })) "force interactive mode"-    ]--main :: IO ()-main = do-  args <- getArgs-  case getOpt Permute options args of-    (_,_,errs@(_:_)) -> do-      mapM_ putStrLn errs-      exitFailure--    (o,args2,[]) -> do-      let opt = foldl (flip id) def o-      case optMode opt of-        Just ModeHelp -> showHelp stdout-        Just ModeVersion -> hPutStrLn stdout (showVersion version)-        Just ModeInteractive -> do-          solver <- newSolver-          mapM_ (loadFile solver) args2-          repl solver          -        Nothing -> do-          solver <- newSolver-          if null args2 then-            repl solver-          else-            mapM_ (loadFile solver) args2--loadFile :: Solver -> FilePath -> IO ()-loadFile solver fname = do-  ret <- parseFromFile (parseSource <* eof) fname-  case ret of-    Left err -> do-      hPrint stderr err-      exitFailure-    Right source -> do-      forM_ source $ \cmd -> do-        execCommand solver cmd--repl :: Solver -> IO ()-repl solver = do-#ifdef USE_HASKELINE_PACKAGE-  replHaskeline solver-#else-  replSimple solver-#endif--replSimple :: Solver -> IO ()-replSimple solver = do-  hSetBuffering stdin LineBuffering-  forever $ do-    putStr "toysmt> "-    hFlush stdout-    s <- getLine-    case parse (spaces >> parseCommand <* eof) "<stdin>" s of-      Left err -> do-        hPrint stderr err-      Right cmd -> do-        execCommand solver cmd--#ifdef USE_HASKELINE_PACKAGE--replHaskeline :: Solver -> IO ()-replHaskeline solver = Haskeline.runInputT Haskeline.defaultSettings $ forever $ do-  m <- Haskeline.getInputLine "toysmt> "-  case m of-    Nothing -> return ()-    Just s -> do-      case parse (spaces >> parseCommand) "<stdin>" s of-        Left err -> do-          lift $ hPrint stderr err-        Right cmd -> do-          lift $ execCommand solver cmd--#endif--showHelp :: Handle -> IO ()-showHelp h = hPutStrLn h (usageInfo header options)--header :: String-header = unlines-  [ "Usage:"-  , "  toysmt [OPTION]... [file.smt2]"-  , ""-  , "Options:"-  ]
toysolver.cabal view
@@ -1,43 +1,45 @@ Name:		toysolver-Version:	0.4.0+Version:	0.5.0 License:	BSD3 License-File:	COPYING Author:		Masahiro Sakai (masahiro.sakai@gmail.com) Maintainer:	masahiro.sakai@gmail.com-Category:	Algorithms, Optimisation, Optimization, Theorem Provers, Constraints, Logic-Cabal-Version:	>= 1.10-Synopsis:	Assorted decision procedures for SAT, Max-SAT, PB, MIP, etc+Category:	Algorithms, Optimisation, Optimization, Theorem Provers, Constraints, Logic, Formal Methods+Cabal-Version:	>= 1.18+Synopsis:	Assorted decision procedures for SAT, SMT, Max-SAT, PB, MIP, etc Description:	Toy-level implementation of some decision procedures+Homepage:	https://github.com/msakai/toysolver/ Bug-Reports:	https://github.com/msakai/toysolver/issues Tested-With:-   GHC ==7.6.3-   GHC ==7.8.3+   GHC ==7.8.4    GHC ==7.10.3+   GHC ==8.0.1 Extra-Source-Files:    README.md    CHANGELOG.markdown    COPYING    COPYING-GPL-   .ghci-   .travis.yml-   appveyor.yml-   build_bdist_linux.sh-   build_bdist_macos.sh-   build_bdist_win32.sh-   build_bdist_win64.sh-   build_bdist_maxsat_evaluation.sh-   build_bdist_pb_evaluation.sh+   misc/build_bdist_linux.sh+   misc/build_bdist_macos.sh+   misc/build_bdist_win32.sh+   misc/build_bdist_win64.sh+   misc/build_bdist_maxsat_evaluation.sh+   misc/build_bdist_pb_evaluation.sh+   misc/build_bdist_qbf_evaluation.sh    misc/maxsat/toysat/README.md    misc/maxsat/toysat/toysat    misc/maxsat/toysat_ls/README.md    misc/maxsat/toysat_ls/toysat_ls    misc/pb/README.md-   src/TseitinEncode.hs+   misc/qbf/README.md    src/ToySolver/Data/Polyhedron.hs+   src/ToySolver/SAT/MessagePassing/SurveyPropagation/sp.cl    samples/gcnf/*.cnf    samples/gcnf/*.gcnf    samples/gcnf/edn_20403_8.cnf_0.03000000.unsat.gcnf    samples/lp/*.lp+   samples/lp/*.sol+   samples/lp/*.txt    samples/lp/error/*.lp    samples/maxsat/*.cnf    samples/maxsat/t3pm3-5555.spn.cnf@@ -62,8 +64,16 @@    samples/programs/svm2lp/a1a    samples/programs/nonogram/*.cwd    samples/programs/nonogram/README.md+   samples/programs/numberlink/README.md+   samples/programs/numberlink/ADC2013/*.txt+   samples/programs/numberlink/ADC2014_QA/A/*.txt+   samples/programs/numberlink/ADC2014_QA/Q/*.txt+   samples/programs/numberlink/ADC2016/sample/01/*.txt    benchmarks/UF250.1065.100/*.cnf    benchmarks/UUF250.1065.100/*.cnf+   doc-images/MIP-Status-diagram.tex+Extra-Doc-Files:+   doc-images/MIP-Status-diagram.png Build-Type: Simple  Flag ForceChar8@@ -91,23 +101,51 @@   Default: False   Manual: True -Flag Exceptions06-  Description: use exceptions >=0.6-  Manual: False--Flag Time15-  Description: use time >=1.5.0-  Manual: False--Flag Transformers051-  Description: use transformers >=0.5.1+Flag LogicTPTP045+  Description: use logic-TPTP >=0.4.5.0   Manual: False+  Default: True  Flag UseHaskeline   Description: use haskeline package   Manual: True   Default: True +Flag OpenCL+  Description: use opencl package+  Manual: True+  Default: False++Flag TestCBC+  Description: run test cases that depends on cbc command+  Manual: True+  Default: False++Flag TestCPLEX+  Description: run test cases that depends on cplex command+  Manual: True+  Default: False++Flag TestGlpsol+  Description: run test cases that depends on glpsol command+  Manual: True+  Default: False++Flag TestGurobiCl+  Description: run test cases that depends on gurobi_cl command+  Manual: True+  Default: False++Flag TestLPSolve+  Description: run test cases that depends on lp_solve command+  Manual: True+  Default: False++Flag TestSCIP+  Description: run test cases that depends on scip command+  Manual: True+  Default: False+ source-repository head   type:     git   location: git://github.com/msakai/toysolver.git@@ -116,58 +154,56 @@   Exposed: True   Hs-source-dirs: src   Build-Depends:-     base >=4.6 && <5,-     template-haskell,-     -- IntMap.mergeWithKey and IntMap.toDescList require containers >=0.5.0-     containers >=0.5.0,-     unordered-containers >=0.2.3 && <0.3.0,-     transformers >=0.2,-     transformers-compat >=0.3,-     mtl >=2.1.2,      array >=0.4.0.0,-     stm >=2.3,-     parsec >=3.1.2 && <4,+     base >=4.7 && <5,      bytestring >=0.9.2.1 && <0.11,      bytestring-builder,-     filepath,+     clock >=0.7.1,+     -- IntMap.mergeWithKey and IntMap.toDescList require containers >=0.5.0+     containers >=0.5.0,+     data-default-class,+     data-interval >=1.0.1 && <1.4.0,      deepseq,-     time,-     primes,-     process >=1.1.0.2,-     parse-dimacs,-     queue,-     heaps,-     vector,-     vector-space >=0.8.6,-     multiset,-     prettyclass >=1.0.0,-     type-level-numbers >=0.1.1.0 && <0.2.0.0,+     extended-reals >=0.1 && <1.0,+     filepath,+     finite-field >=0.9.0 && <1.0.0,      hashable >=1.1.2.5 && <1.3.0.0,+     hashtables,+     heaps,      intern >=0.9.1.2 && <1.0.0.0,-     loop >=0.2.0 && < 1.0.0,-     data-default-class,+     log-domain,+     -- numLoopState requires loop >=0.3.0+     loop >=0.3.0 && < 1.0.0,+     mtl >=2.1.2,+     multiset,      -- createSystemRandom requires mwc-random >=0.13.1.0      mwc-random >=0.13.1 && <0.14,-     semigroups >=0.17,      OptDir,-     extended-reals >=0.1 && <1.0,-     data-interval >=1.0.1 && <1.3.0,-     finite-field >=0.7.0 && <1.0.0,+     lattices,+     megaparsec >=4 && <7,+     prettyclass >=1.0.0,+     primes,+     primitive >=0.6,+     process >=1.1.0.2,+     pseudo-boolean >=0.1.3.0 && <0.2.0.0,+     queue,+     scientific,+     semigroups >=0.17,      sign >=0.2.0 && <1.0.0,-     pseudo-boolean >=0.1.3.0 && <0.2.0.0-  -- NOTE: temporary-1.2.0.2 does not work with exceptions-0.6-  if flag(Exceptions06)-     Build-Depends: temporary >1.2.0.2, exceptions >=0.6-  else-     Build-Depends: temporary >=1.2, exceptions ==0.5-  if impl(ghc <7.7)-    Build-Depends:-      -- vector-space depends on MemoTrie, but MemoTrie >=0.6.3 uses extensions that are not available on GHC 7.6.-      MemoTrie <=0.6.2-  if flag(Transformers051)-     Build-Depends: transformers >=0.5.1.0-  else-     Build-Depends: transformers <0.5.1.0+     stm >=2.3,+     template-haskell,+     temporary >=1.2,+     text >=1.1.0.0,+     time >=1.5.0,+     transformers >=0.2,+     transformers-compat >=0.3,+     unordered-containers >=0.2.3 && <0.3.0,+     vector,+     vector-space >=0.8.6,+     xml-conduit+  if flag(OpenCL)+     Build-Depends: OpenCL >=1.0.3.4+     Exposed-Modules: ToySolver.SAT.MessagePassing.SurveyPropagation.OpenCL   if impl(ghc)      Build-Depends: ghc-prim   Default-Language: Haskell2010@@ -175,6 +211,7 @@      BangPatterns      CPP      DeriveDataTypeable+     ExistentialQuantification      FlexibleContexts      FlexibleInstances      FunctionalDependencies@@ -186,7 +223,10 @@      ScopedTypeVariables      TemplateHaskell      TypeFamilies+     TypeOperators      TypeSynonymInstances+     -- commented out because cabal-1.16 does not understand InstanceSigs extension+     -- InstanceSigs   if impl(ghc)      Other-Extensions:         MagicHash@@ -198,44 +238,59 @@      ToySolver.Arith.Cooper      ToySolver.Arith.Cooper.Base      ToySolver.Arith.Cooper.FOL+     ToySolver.Arith.DifferenceLogic      ToySolver.Arith.FourierMotzkin      ToySolver.Arith.FourierMotzkin.Base      ToySolver.Arith.FourierMotzkin.FOL      ToySolver.Arith.FourierMotzkin.Optimization-     ToySolver.Arith.LPSolver-     ToySolver.Arith.LPSolverHL      ToySolver.Arith.LPUtil-     ToySolver.Arith.MIPSolverHL-     ToySolver.Arith.MIPSolver2+     ToySolver.Arith.MIP      ToySolver.Arith.OmegaTest      ToySolver.Arith.OmegaTest.Base      ToySolver.Arith.Simplex-     ToySolver.Arith.Simplex2+     ToySolver.Arith.Simplex.Simple+     ToySolver.Arith.Simplex.Textbook+     ToySolver.Arith.Simplex.Textbook.LPSolver+     ToySolver.Arith.Simplex.Textbook.LPSolver.Simple+     ToySolver.Arith.Simplex.Textbook.MIPSolver.Simple      ToySolver.Arith.VirtualSubstitution+     ToySolver.BitVector+     ToySolver.BitVector.Base+     ToySolver.BitVector.Solver      ToySolver.EUF.CongruenceClosure      ToySolver.EUF.EUFSolver      ToySolver.EUF.FiniteModelFinder+     ToySolver.Combinatorial.BipartiteMatching+     ToySolver.Combinatorial.HittingSet.DAA+     ToySolver.Combinatorial.HittingSet.MARCO      ToySolver.Combinatorial.HittingSet.Simple      ToySolver.Combinatorial.HittingSet.HTCBDD+     ToySolver.Combinatorial.HittingSet.InterestingSets      ToySolver.Combinatorial.HittingSet.SHD      ToySolver.Combinatorial.HittingSet.FredmanKhachiyan1996      ToySolver.Combinatorial.HittingSet.GurvichKhachiyan1999+     ToySolver.Combinatorial.HittingSet.Util      ToySolver.Combinatorial.Knapsack.BB      ToySolver.Combinatorial.Knapsack.DPDense      ToySolver.Combinatorial.Knapsack.DPSparse      ToySolver.Combinatorial.SubsetSum+     ToySolver.Converter.GCNF2MaxSAT      ToySolver.Converter.ObjType+     ToySolver.Converter.MIP2PB      ToySolver.Converter.MIP2SMT      ToySolver.Converter.MaxSAT2IP-     ToySolver.Converter.MaxSAT2NLPB      ToySolver.Converter.MaxSAT2WBO      ToySolver.Converter.PB2IP+     ToySolver.Converter.PBLinearization      ToySolver.Converter.PB2LSP+     ToySolver.Converter.PB2SAT      ToySolver.Converter.PB2WBO      ToySolver.Converter.PBSetObj      ToySolver.Converter.PB2SMP+     ToySolver.Converter.SAT2KSAT      ToySolver.Converter.SAT2PB      ToySolver.Converter.SAT2IP+     ToySolver.Converter.WBO2MaxSAT      ToySolver.Converter.WBO2PB      ToySolver.Data.AlgebraicNumber.Complex      ToySolver.Data.AlgebraicNumber.Real@@ -247,6 +302,7 @@      ToySolver.Data.DNF      ToySolver.Data.FOL.Arith      ToySolver.Data.FOL.Formula+     ToySolver.Data.IntVar      ToySolver.Data.LA      ToySolver.Data.LA.FOL      ToySolver.Data.LBool@@ -254,6 +310,19 @@      ToySolver.Data.MIP.Base      ToySolver.Data.MIP.LPFile      ToySolver.Data.MIP.MPSFile+     ToySolver.Data.MIP.Solution.CBC+     ToySolver.Data.MIP.Solution.CPLEX+     ToySolver.Data.MIP.Solution.GLPK+     ToySolver.Data.MIP.Solution.Gurobi+     ToySolver.Data.MIP.Solution.SCIP+     ToySolver.Data.MIP.Solver+     ToySolver.Data.MIP.Solver.Base+     ToySolver.Data.MIP.Solver.CBC+     ToySolver.Data.MIP.Solver.CPLEX+     ToySolver.Data.MIP.Solver.Glpsol+     ToySolver.Data.MIP.Solver.GurobiCl+     ToySolver.Data.MIP.Solver.LPSolve+     ToySolver.Data.MIP.Solver.SCIP      ToySolver.Data.OrdRel      ToySolver.Data.Polynomial      ToySolver.Data.Polynomial.Factorization.FiniteField@@ -266,15 +335,22 @@      ToySolver.Data.Polynomial.Factorization.Zassenhaus      ToySolver.Data.Polynomial.GroebnerBasis      ToySolver.Data.Polynomial.Interpolation.Lagrange-     ToySolver.Data.Var+     ToySolver.Graph.ShortestPath+     ToySolver.QBF      ToySolver.SAT-     ToySolver.SAT.Integer+     ToySolver.SAT.Config+     ToySolver.SAT.Encoder.Integer+     ToySolver.SAT.Encoder.PB+     ToySolver.SAT.Encoder.PB.Internal.Adder+     ToySolver.SAT.Encoder.PB.Internal.BDD+     ToySolver.SAT.Encoder.PB.Internal.Sorter+     ToySolver.SAT.Encoder.PBNLC+     ToySolver.SAT.Encoder.Tseitin+     ToySolver.SAT.ExistentialQuantification+     ToySolver.SAT.MessagePassing.SurveyPropagation      ToySolver.SAT.MUS-     ToySolver.SAT.MUS.CAMUS-     ToySolver.SAT.MUS.DAA+     ToySolver.SAT.MUS.Enum      ToySolver.SAT.MUS.Types-     ToySolver.SAT.MUS.QuickXplain-     ToySolver.SAT.PBNLC      ToySolver.SAT.PBO      ToySolver.SAT.PBO.Context      ToySolver.SAT.PBO.BC@@ -282,14 +358,16 @@      ToySolver.SAT.PBO.BCD2      ToySolver.SAT.PBO.MSU4      ToySolver.SAT.PBO.UnsatBased+     ToySolver.SAT.Store.CNF+     ToySolver.SAT.Store.PB      ToySolver.SAT.TheorySolver-     ToySolver.SAT.TseitinEncoder      ToySolver.SAT.Types      ToySolver.SAT.Printer      ToySolver.SMT+     ToySolver.Text.CNF      ToySolver.Text.GCNF-     ToySolver.Text.GurobiSol      ToySolver.Text.MaxSAT+     ToySolver.Text.QDimacs      ToySolver.Text.SDPFile      ToySolver.Internal.Data.IndexedPriorityQueue      ToySolver.Internal.Data.IOURef@@ -304,26 +382,34 @@   Other-Modules:      ToySolver.Data.AlgebraicNumber.Graeffe      ToySolver.Data.Polynomial.Base+     ToySolver.SAT.MUS.Base+     ToySolver.SAT.MUS.Deletion+     ToySolver.SAT.MUS.Insertion+     ToySolver.SAT.MUS.QuickXplain+     ToySolver.SAT.MUS.Enum.Base+     ToySolver.SAT.MUS.Enum.CAMUS      ToySolver.Version.TH      Paths_toysolver   -- GHC-Prof-Options: -auto-all  Executable toysolver   Main-is: toysolver.hs-  HS-Source-Dirs: toysolver+  HS-Source-Dirs: app   Build-Depends:+    array,     base,     containers,-    array,     data-default-class,     filepath,     OptDir,-    parse-dimacs,     pseudo-boolean,+    scientific,     toysolver   Default-Language: Haskell2010-  if impl(ghc)-    GHC-Options: -rtsopts -threaded+  Other-Extensions: CPP+  GHC-Options: -rtsopts -threaded+  if flag(ForceChar8)+    CPP-OPtions: "-DFORCE_CHAR8"   if flag(LinuxStatic)     GHC-Options: -static -optl-static -optl-pthread   -- GHC-Prof-Options: -auto-all@@ -331,40 +417,38 @@ Executable toysat   Main-is: toysat.hs   Other-Modules: UBCSAT-  HS-Source-Dirs: toysat+  HS-Source-Dirs: app/toysat   Build-Depends:+    array,     base,+    bytestring,+    containers,+    clock,+    data-default,     data-default-class,+    directory,+    filepath,+    megaparsec,     mwc-random,-    containers,-    array,     process >=1.1.0.2,-    parsec,-    bytestring,-    filepath,-    parse-dimacs,-    unbounded-delays,-    vector,-    vector-space,     pseudo-boolean,-    toysolver-  if flag(Time15)-    Build-Depends: time >=1.5.0-  else-    Build-Depends: time <1.5.0, old-locale+    scientific,+    temporary,+    time,+    toysolver,+    unbounded-delays,+    vector   Default-Language: Haskell2010   Other-Extensions: ScopedTypeVariables, CPP-  if impl(ghc)-    GHC-Options: -rtsopts+  GHC-Options: -rtsopts -threaded   -- GHC-Prof-Options: -auto-all-  if flag(ForceChar8) && impl(ghc)-    Build-Depends: base >=4.5+  if flag(ForceChar8)     CPP-OPtions: "-DFORCE_CHAR8"   if flag(LinuxStatic)     GHC-Options: -static -optl-static -optl-pthread  Executable toysmt-  HS-Source-Dirs: toysmt, Smtlib+  HS-Source-Dirs: app/toysmt, Smtlib   Main-is: toysmt.hs   Other-Modules:      ToySolver.SMT.SMTLIB2Solver,@@ -380,73 +464,96 @@     base,     containers,     data-default-class,+    -- TODO: remove intern dependency+    intern,     mtl,-    parsec,+    parsec >=3.1.2 && <4,+    toysolver,+    text,     transformers,-    transformers-compat,-    toysolver+    transformers-compat   if flag(UseHaskeline)     Build-Depends: haskeline >=0.7 && <0.8     CPP-Options: "-DUSE_HASKELINE_PACKAGE"   Default-Language: Haskell2010   Other-Extensions: ScopedTypeVariables, CPP-  if impl(ghc >= 7)-    GHC-Options: -rtsopts+  GHC-Options: -rtsopts   -- GHC-Prof-Options: -auto-all-  if flag(ForceChar8) && impl(ghc)-    Build-Depends: base >=4.5+  if flag(ForceChar8)     CPP-OPtions: "-DFORCE_CHAR8"   if flag(LinuxStatic)     GHC-Options: -static -optl-static -optl-pthread +Executable toyqbf+  Main-is: toyqbf.hs+  HS-Source-Dirs: app+  Build-Depends:+    base,+    containers,+    data-default-class,+    toysolver+  Default-Language: Haskell2010+  Other-Extensions: ScopedTypeVariables, CPP+  GHC-Options: -rtsopts+  -- GHC-Prof-Options: -auto-all+  if flag(ForceChar8)+    CPP-OPtions: "-DFORCE_CHAR8"+  if flag(LinuxStatic)+    GHC-Options: -static -optl-static -optl-pthread+ Executable toyfmf   If !flag(BuildToyFMF)     Buildable: False   Main-is: toyfmf.hs-  HS-Source-Dirs: toyfmf+  HS-Source-Dirs: app   If flag(BuildToyFMF)     Build-Depends:       base,       containers,-      toysolver,-      logic-TPTP >=0.4.1-    -- logic-TPTP <=0.4.3 has build error on ghc <7.9 and transformers >=0.5.1.-    if impl(ghc <7.9) && flag(Transformers051)-      Build-Depends: logic-TPTP >=0.4.4.0+      intern,+      -- logic-TPTP <=0.4.3 has build error on ghc <7.9 and transformers >=0.5.1.+      -- https://github.com/DanielSchuessler/logic-TPTP/pull/4+      logic-TPTP >=0.4.4.0,+      text,+      toysolver+    -- logic-TPTP <=0.4.4.0 is not compatible with transformers-compat >=0.5+    if impl(ghc <7.9)+      if flag(LogicTPTP045)+        Build-Depends:+          logic-TPTP >=0.4.5.0+      else+        Build-Depends:+          transformers-compat <0.5   Default-Language: Haskell2010-  if impl(ghc)-    GHC-Options: -rtsopts+  Other-Extensions: CPP+  GHC-Options: -rtsopts+  if flag(ForceChar8)+    CPP-OPtions: "-DFORCE_CHAR8"   if flag(LinuxStatic)     GHC-Options: -static -optl-static -optl-pthread   -- GHC-Prof-Options: -auto-all  -- Converters -Executable lpconvert-  Main-is: lpconvert.hs-  HS-Source-Dirs: lpconvert+Executable toyconvert+  Main-is: toyconvert.hs+  HS-Source-Dirs: app   Build-Depends:     base,-    filepath,+    bytestring,+    bytestring-builder,     data-default-class,-    parse-dimacs,-    pseudo-boolean,-    toysolver-  Default-Language: Haskell2010-  if flag(LinuxStatic)-    GHC-Options: -static -optl-static -optl-pthread--Executable pbconvert-  Main-is: pbconvert.hs-  HS-Source-Dirs: pbconvert-  Build-Depends:-    base >=4 && <5,     filepath,-    data-default-class,-    parse-dimacs,     pseudo-boolean,+    scientific,+    text,     toysolver   Default-Language: Haskell2010+  Other-Extensions: CPP+  GHC-Options: -rtsopts+  -- GHC-Prof-Options: -auto-all+  if flag(ForceChar8)+    CPP-OPtions: "-DFORCE_CHAR8"   if flag(LinuxStatic)     GHC-Options: -static -optl-static -optl-pthread @@ -458,10 +565,14 @@   Main-is: sudoku.hs   HS-Source-Dirs: samples/programs/sudoku   Build-Depends:-    base,     array,+    base,     toysolver   Default-Language: Haskell2010+  Other-Extensions: CPP+  GHC-Options: -rtsopts+  if flag(ForceChar8)+    CPP-OPtions: "-DFORCE_CHAR8"   if flag(LinuxStatic)     GHC-Options: -static -optl-static -optl-pthread @@ -471,11 +582,16 @@   Main-is: nonogram.hs   HS-Source-Dirs: samples/programs/nonogram   Build-Depends:-    base,     array,+    base,     containers,     toysolver   Default-Language: Haskell2010+  Other-Extensions: CPP+  GHC-Options: -rtsopts+  -- GHC-Prof-Options: -auto-all+  if flag(ForceChar8)+    CPP-OPtions: "-DFORCE_CHAR8"   if flag(LinuxStatic)     GHC-Options: -static -optl-static -optl-pthread @@ -485,10 +601,38 @@   Main-is: nqueens.hs   HS-Source-Dirs: samples/programs/nqueens   Build-Depends:+    array,     base,+    toysolver+  Default-Language: Haskell2010+  Other-Extensions: CPP+  GHC-Options: -rtsopts+  -- GHC-Prof-Options: -auto-all+  if flag(ForceChar8)+    CPP-OPtions: "-DFORCE_CHAR8"+  if flag(LinuxStatic)+    GHC-Options: -static -optl-static -optl-pthread++Executable numberlink+  If !flag(BuildSamplePrograms)+    Buildable: False+  Main-is: numberlink.hs+  HS-Source-Dirs: samples/programs/numberlink+  Build-Depends:     array,+    base,+    bytestring,+    containers,+    data-default-class,+    parsec,+    pseudo-boolean,     toysolver   Default-Language: Haskell2010+  Other-Extensions: CPP+  GHC-Options: -rtsopts+  -- GHC-Prof-Options: -auto-all+  if flag(ForceChar8)+    CPP-OPtions: "-DFORCE_CHAR8"   if flag(LinuxStatic)     GHC-Options: -static -optl-static -optl-pthread @@ -501,9 +645,55 @@     base,     toysolver   Default-Language: Haskell2010+  Other-Extensions: CPP+  GHC-Options: -rtsopts+  -- GHC-Prof-Options: -auto-all+  if flag(ForceChar8)+    CPP-OPtions: "-DFORCE_CHAR8"   if flag(LinuxStatic)     GHC-Options: -static -optl-static -optl-pthread +Executable assign+  If !flag(BuildSamplePrograms)+    Buildable: False+  Main-is: assign.hs+  HS-Source-Dirs: samples/programs/assign+  Build-Depends:+    attoparsec,+    base,+    bytestring,+    containers,+    toysolver,+    vector+  Default-Language: Haskell2010+  Other-Extensions: CPP+  GHC-Options: -rtsopts+  -- GHC-Prof-Options: -auto-all+  if flag(ForceChar8)+    CPP-OPtions: "-DFORCE_CHAR8"+  if flag(LinuxStatic)+    GHC-Options: -static -optl-static -optl-pthread++Executable shortest-path+  If !flag(BuildSamplePrograms)+    Buildable: False+  Main-is: shortest-path.hs+  HS-Source-Dirs: samples/programs/shortest-path+  Build-Depends:+    base,+    bytestring,+    containers,+    unordered-containers,+    toysolver+  Default-Language: Haskell2010+  Other-Extensions: CPP+  GHC-Options: -rtsopts+  -- GHC-Prof-Options: -auto-all+  if flag(ForceChar8)+    CPP-OPtions: "-DFORCE_CHAR8"+  if flag(LinuxStatic)+    GHC-Options: -static -optl-static -optl-pthread+ Executable htc   If !flag(BuildSamplePrograms)     Buildable: False@@ -514,6 +704,11 @@     containers,     toysolver   Default-Language: Haskell2010+  Other-Extensions: CPP+  GHC-Options: -rtsopts+  -- GHC-Prof-Options: -auto-all+  if flag(ForceChar8)+    CPP-OPtions: "-DFORCE_CHAR8"   if flag(LinuxStatic)     GHC-Options: -static -optl-static -optl-pthread @@ -526,25 +721,60 @@     base,     containers,     data-default-class,+    scientific,     split,+    text,     toysolver   Default-Language: Haskell2010+  Other-Extensions: CPP+  GHC-Options: -rtsopts+  -- GHC-Prof-Options: -auto-all+  if flag(ForceChar8)+    CPP-OPtions: "-DFORCE_CHAR8"   if flag(LinuxStatic)     GHC-Options: -static -optl-static -optl-pthread +Executable survey-propagation+  if !flag(BuildSamplePrograms)+    Buildable: False    +  Main-is: survey-propagation.hs+  HS-Source-Dirs: samples/programs/survey-propagation+  Build-Depends:+    base,+    data-default-class,+    toysolver+  if flag(OpenCL)+    Build-Depends: OpenCL+    CPP-Options: "-DENABLE_OPENCL"+  Default-Language: Haskell2010+  Other-Extensions: CPP+  -- We use threaded RTS to avoid the error "schedule: re-entered unsafely.+  -- Perhaps a 'foreign import unsafe' should be 'safe'?" on NVIDIA CUDA.+  GHC-Options: -rtsopts -threaded+  -- GHC-Prof-Options: -auto-all+  if flag(ForceChar8)+    CPP-Options: "-DFORCE_CHAR8"+  if flag(LinuxStatic)+    GHC-Options: -static -optl-static -optl-pthread+ -- Misc Programs  Executable pigeonhole   If !flag(BuildMiscPrograms)     Buildable: False   Main-is: pigeonhole.hs-  HS-Source-Dirs: pigeonhole+  HS-Source-Dirs: app   Build-Depends:     base,     containers,     pseudo-boolean,     toysolver   Default-Language: Haskell2010+  Other-Extensions: CPP+  GHC-Options: -rtsopts+  -- GHC-Prof-Options: -auto-all+  if flag(ForceChar8)+    CPP-OPtions: "-DFORCE_CHAR8"   if flag(LinuxStatic)     GHC-Options: -static -optl-static -optl-pthread @@ -552,12 +782,17 @@   If !flag(BuildMiscPrograms)     Buildable: False   Main-is: maxsatverify.hs-  HS-Source-Dirs: maxsatverify+  HS-Source-Dirs: app   Build-Depends:-    base,     array,+    base,     toysolver   Default-Language: Haskell2010+  Other-Extensions: CPP+  GHC-Options: -rtsopts+  -- GHC-Prof-Options: -auto-all+  if flag(ForceChar8)+    CPP-OPtions: "-DFORCE_CHAR8"   if flag(LinuxStatic)     GHC-Options: -static -optl-static -optl-pthread @@ -565,13 +800,18 @@   Main-is: pbverify.hs   If !flag(BuildMiscPrograms)     Buildable: False-  HS-Source-Dirs: pbverify+  HS-Source-Dirs: app   Build-Depends:-    base,     array,+    base,     pseudo-boolean,     toysolver   Default-Language: Haskell2010+  Other-Extensions: CPP+  GHC-Options: -rtsopts+  -- GHC-Prof-Options: -auto-all+  if flag(ForceChar8)+    CPP-OPtions: "-DFORCE_CHAR8"   if flag(LinuxStatic)     GHC-Options: -static -optl-static -optl-pthread @@ -584,83 +824,111 @@   Build-depends:     base,     containers,-    toysolver,+    data-interval,+    finite-field >=0.7.0 && <1.0.0,+    prettyclass >=1.0.0,     tasty >=0.10.1,     tasty-hunit ==0.9.*,-    tasty-quickcheck ==0.8.*,+    tasty-quickcheck >=0.8 && <0.10,     tasty-th,-    data-interval,-    finite-field >=0.7.0 && <1.0.0,-    prettyclass >=1.0.0+    toysolver   Default-Language: Haskell2010   Other-Extensions: TemplateHaskell  Test-suite TestSuite   Type:              exitcode-stdio-1.0-  HS-Source-Dirs:    test Smtlib toysmt+  HS-Source-Dirs:    test Smtlib app/toysmt   Main-is:           TestSuite.hs   Other-Modules:     Test.AReal     Test.AReal2     Test.Arith+    Test.BitVector     Test.BoolExpr+    Test.BipartiteMatching     Test.CongruenceClosure     Test.ContiTraverso     Test.Delta     Test.FiniteModelFinder+    Test.GraphShortestPath     Test.HittingSets     Test.Knapsack     Test.LPFile     Test.Misc+    Test.MIP+    Test.MIPSolver     Test.MIPSolver2     Test.MPSFile+    Test.QBF     Test.SAT     Test.SDPFile     Test.Simplex-    Test.Simplex2+    Test.SimplexTextbook     Test.SMT     Test.SMTLIB2Solver+    Test.Smtlib     Test.SubsetSum+    ToySolver.SMT.SMTLIB2Solver,     Smtlib.Parsers.CommonParsers,     Smtlib.Parsers.ResponseParsers,     Smtlib.Parsers.CommandsParsers,     Smtlib.Syntax.Syntax,     Smtlib.Syntax.ShowSL   Build-depends:-    base,     array,+    base,+    bytestring,+    bytestring-builder,     containers,     data-default-class,+    data-interval,     deepseq,+    hashable,+    intern,+    lattices,+    megaparsec,     mtl,     mwc-random,-    parsec,-    transformers,-    transformers-compat,-    vector,-    vector-space,-    toysolver,-    data-interval,     OptDir,+    parsec >=3.1.2 && <4,+    pseudo-boolean,+    QuickCheck >=2.5 && <3,     tasty >=0.10.1,     tasty-hunit ==0.9.*,-    tasty-quickcheck ==0.8.*,+    tasty-quickcheck >=0.8 && <0.10,     tasty-th,-    QuickCheck >=2.5 && <3+    text,+    toysolver,+    transformers,+    transformers-compat,+    unordered-containers,+    vector,+    vector-space   Default-Language: Haskell2010   Other-Extensions: TemplateHaskell, ScopedTypeVariables+  if flag(TestCBC)+    CPP-Options: "-DTEST_CBC"+  if flag(TestCPLEX)+    CPP-Options: "-DTEST_CPLEX"+  if flag(TestGlpsol)+    CPP-Options: "-DTEST_GLPSOL"+  if flag(TestGurobiCl)+    CPP-Options: "-DTEST_GUROBI_CL"+  if flag(TestLPSolve)+    CPP-Options: "-DTEST_LP_SOLVE"+  if flag(TestSCIP)+    CPP-Options: "-DTEST_SCIP"  Benchmark BenchmarkSATLIB   type:             exitcode-stdio-1.0   hs-source-dirs:   benchmarks   main-is:          BenchmarkSATLIB.hs   build-depends:-    base >=4 && <5,     array,+    base,+    criterion >=1.0 && <1.3,     data-default-class,-    parse-dimacs,-    toysolver,-    criterion >=1.0 && <1.2+    toysolver   Default-Language: Haskell2010  Benchmark BenchmarkKnapsack@@ -668,9 +936,9 @@   hs-source-dirs:   benchmarks   main-is:          BenchmarkKnapsack.hs   build-depends:-    base >=4 && <5,-    toysolver,-    criterion >=1.0 && <1.2+    base,+    criterion >=1.0 && <1.3,+    toysolver   Default-Language: Haskell2010  Benchmark BenchmarkSubsetSum@@ -678,8 +946,8 @@   hs-source-dirs:   benchmarks   main-is:          BenchmarkSubsetSum.hs   build-depends:-    base >=4 && <5,-    vector,+    base,+    criterion >=1.0 && <1.3,     toysolver,-    criterion >=1.0 && <1.2+    vector   Default-Language: Haskell2010
− toysolver/toysolver.hs
@@ -1,473 +0,0 @@--------------------------------------------------------------------------------- |--- Module      :  toysolver--- Copyright   :  (c) Masahiro Sakai 2011-2014--- License     :  BSD-style--- --- Maintainer  :  masahiro.sakai@gmail.com--- Stability   :  experimental--- Portability :  portable------------------------------------------------------------------------------------module Main where--import Control.Monad-import Control.Concurrent-import Data.Array.IArray-import Data.Char-import Data.Default.Class-import Data.List-import Data.Maybe-import Data.Ratio-import qualified Data.Version as V-import qualified Data.Set as Set-import Data.Map (Map)-import qualified Data.Map as Map-import qualified Data.IntMap as IntMap-import qualified Data.IntSet as IntSet-import System.Exit-import System.Environment-import System.FilePath-import System.Console.GetOpt-import System.IO-import Text.Printf-import qualified Language.CNF.Parse.ParseDIMACS as DIMACS-import GHC.Conc (getNumProcessors, setNumCapabilities)--import Data.OptDir-import qualified Data.PseudoBoolean as PBFile-import qualified Data.PseudoBoolean.Attoparsec as PBFileAttoparsec--import ToySolver.Data.OrdRel-import ToySolver.Data.FOL.Arith as FOL-import qualified ToySolver.Data.LA as LA-import qualified ToySolver.Data.LA.FOL as LAFOL-import qualified ToySolver.Data.Polynomial as P-import qualified ToySolver.Data.AlgebraicNumber.Real as AReal-import qualified ToySolver.Data.MIP as MIP-import qualified ToySolver.Arith.OmegaTest as OmegaTest-import qualified ToySolver.Arith.Cooper as Cooper-import qualified ToySolver.Arith.MIPSolverHL as MIPSolverHL-import qualified ToySolver.Arith.Simplex2 as Simplex2-import qualified ToySolver.Arith.MIPSolver2 as MIPSolver2-import qualified ToySolver.Arith.CAD as CAD-import qualified ToySolver.Arith.ContiTraverso as ContiTraverso-import qualified ToySolver.Text.MaxSAT as MaxSAT-import qualified ToySolver.Text.GurobiSol as GurobiSol-import qualified ToySolver.Converter.SAT2IP as SAT2IP-import qualified ToySolver.Converter.PB2IP as PB2IP-import qualified ToySolver.Converter.MaxSAT2IP as MaxSAT2IP-import ToySolver.SAT.Printer-import qualified ToySolver.SAT.Types as SAT-import ToySolver.Version-import ToySolver.Internal.Util---- -----------------------------------------------------------------------------data Mode = ModeSAT | ModePB | ModeWBO | ModeMaxSAT | ModeMIP-  deriving (Eq, Ord)--data Flag-    = Help-    | Version-    | Solver String-    | PrintRational-    | WriteFile !FilePath-    | NoMIP-    | PivotStrategy String-    | NThread !Int-    | OmegaReal String-    | Mode !Mode-    deriving Eq--options :: [OptDescr Flag]-options =-    [ Option ['h'] ["help"]    (NoArg Help)            "show help"-    , Option ['v'] ["version"] (NoArg Version)         "show version number"-    , Option [] ["solver"] (ReqArg Solver "SOLVER")    "mip (default), omega-test, cooper, cad, old-mip, ct"-    , 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 [] ["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), virtual-substitution (or vs), cad, simplex, none"--    , Option []    ["sat"]    (NoArg (Mode ModeSAT))    "solve boolean satisfiability problem in .cnf file"-    , Option []    ["pb"]     (NoArg (Mode ModePB))     "solve pseudo boolean problem in .opb file"-    , Option []    ["wbo"]    (NoArg (Mode ModeWBO))    "solve weighted boolean optimization problem in .wbo file"-    , Option []    ["maxsat"] (NoArg (Mode ModeMaxSAT)) "solve MaxSAT problem in .cnf or .wcnf file"-    , Option []    ["lp"]     (NoArg (Mode ModeMIP))    "solve LP/MIP problem in .lp or .mps file (default)"--    , Option [] ["nomip"] (NoArg NoMIP)                 "consider all integer variables as continuous"-    ]--header :: String-header = "Usage: toysolver [OPTION]... file"---- -----------------------------------------------------------------------------run-  :: String-  -> [Flag]-  -> MIP.Problem-  -> (Map MIP.Var Rational -> IO ())-  -> IO ()-run solver opt mip printModel = do-  unless (Set.null (MIP.semiContinuousVariables mip)) $ do-    hPutStrLn stderr "semi-continuous variables are not supported."-    exitFailure  -  case map toLower solver of-    s | s `elem` ["omega", "omega-test", "cooper"] -> solveByQE-    s | s `elem` ["old-mip"] -> solveByMIP-    s | s `elem` ["cad"] -> solveByCAD-    s | s `elem` ["ct", "conti-traverso"] -> solveByContiTraverso-    _ -> solveByMIP2-  where-    vs = MIP.variables mip-    vsAssoc = zip (Set.toList vs) [0..]-    nameToVar = Map.fromList vsAssoc-    varToName = IntMap.fromList [(v,name) | (name,v) <- vsAssoc]--    compileE :: MIP.Expr -> Expr Rational-    compileE = foldr (+) (Const 0) . map compileT . MIP.terms--    compileT :: MIP.Term -> Expr Rational-    compileT (MIP.Term c vs) =-      foldr (*) (Const c) [Var (nameToVar Map.! v) | v <- vs]--    obj = compileE $ MIP.objExpr $ MIP.objectiveFunction mip--    cs1 = do-      v <- Set.toList vs-      let v2 = Var (nameToVar Map.! v)-      let (l,u) = MIP.getBounds mip v-      [Const x .<=. v2 | MIP.Finite x <- return l] ++-        [v2 .<=. Const x | MIP.Finite x <- return u]-    cs2 = do-      MIP.Constraint-        { MIP.constrIndicator = ind-        , MIP.constrExpr = e-        , MIP.constrLB = lb-        , MIP.constrUB = ub-        } <- MIP.constraints mip-      case ind of-        Nothing -> do-          let e2 = compileE e-          msum-            [ case lb of-                MIP.NegInf -> []-                MIP.PosInf -> [OrdRel 1 Le 0] -- False-                MIP.Finite x -> [OrdRel e2 Ge (Const x)]-            , case ub of-                MIP.NegInf -> [OrdRel 1 Le 0] -- False-                MIP.PosInf -> []-                MIP.Finite x -> [OrdRel e2 Le (Const x)]-            ]-        Just _ -> error "indicator constraint is not supported yet"--    ivs-      | NoMIP `elem` opt = Set.empty-      | otherwise        = MIP.integerVariables mip--    vs2  = IntMap.keysSet varToName-    ivs2 = IntSet.fromList . map (nameToVar Map.!) . Set.toList $ ivs--    solveByQE =-      case mapM LAFOL.fromFOLAtom (cs1 ++ cs2) of-        Nothing -> do-          putSLine "UNKNOWN"-          exitFailure-        Just cs ->-          case f vs2 cs ivs2 of-            Nothing -> do-              putSLine "UNSATISFIABLE"-              exitFailure-            Just m -> do-              putOLine $ showValue (FOL.evalExpr m obj)-              putSLine "SATISFIABLE"-              let m2 = Map.fromAscList [(v, m IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs]-              printModel m2-       where-         f = case solver of-               "omega"      -> OmegaTest.solveQFLIRAConj omegaOpt-               "omega-test" -> OmegaTest.solveQFLIRAConj omegaOpt-               "cooper"     -> Cooper.solveQFLIRAConj-               _ -> error "unknown solver"--         omegaOpt =-           def-           { OmegaTest.optCheckReal = realSolver-           }         -           where-             realSolver =-               case last ("fourier-motzkin" : [s | OmegaReal s <- opt]) of-                 "fourier-motzkin" -> OmegaTest.checkRealByFM-                 "virtual-substitution" -> OmegaTest.checkRealByVS-                 "vs"              -> OmegaTest.checkRealByVS-                 "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-          putSLine "UNKNOWN"-          exitFailure-        Just (cs',obj') ->-          case MIPSolverHL.optimize (MIP.objDir $ MIP.objectiveFunction mip) obj' cs' ivs2 of-            MIPSolverHL.OptUnsat -> do-              putSLine "UNSATISFIABLE"-              exitFailure-            MIPSolverHL.Unbounded -> do-              putSLine "UNBOUNDED"-              exitFailure-            MIPSolverHL.Optimum r m -> do-              putOLine $ showValue r-              putSLine "OPTIMUM FOUND"-              let m2 = Map.fromAscList [(v, m IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs]-              printModel m2--    solveByMIP2 = do-      solver <- Simplex2.newSolver--      let ps = last ("bland-rule" : [s | PivotStrategy s <- opt])-      case ps of-        "bland-rule"          -> Simplex2.setPivotStrategy solver Simplex2.PivotStrategyBlandRule-        "largest-coefficient" -> Simplex2.setPivotStrategy solver Simplex2.PivotStrategyLargestCoefficient-        _ -> error ("unknown pivot strategy \"" ++ ps ++ "\"")--      let nthreads = last (0 : [n | NThread n <- opt])--      Simplex2.setLogger solver putCommentLine-      replicateM (length vsAssoc) (Simplex2.newVar solver) -- XXX-      Simplex2.setOptDir solver $ MIP.objDir $ MIP.objectiveFunction mip-      Simplex2.setObj solver $ fromJust (LAFOL.fromFOLExpr obj)-      putCommentLine "Loading constraints... "-      forM_ (cs1 ++ cs2) $ \c -> do-        Simplex2.assertAtom solver $ fromJust (LAFOL.fromFOLAtom c)-      putCommentLine "Loading constraints finished"--      mip <- MIPSolver2.newSolver solver ivs2-      MIPSolver2.setShowRational mip printRat-      MIPSolver2.setLogger mip putCommentLine-      MIPSolver2.setOnUpdateBestSolution mip $ \m val -> putOLine (showValue val)--      procs <--        if nthreads >= 1-        then return nthreads-        else do-          ncap  <- getNumCapabilities-          procs <- getNumProcessors-          return $ max (procs - 1) ncap-      setNumCapabilities procs-      MIPSolver2.setNThread mip procs--      ret <- MIPSolver2.optimize mip-      case ret of-        Simplex2.Unsat -> do-          putSLine "UNSATISFIABLE"-          exitFailure-        Simplex2.Unbounded -> do-          putSLine "UNBOUNDED"-          Just m <- MIPSolver2.getBestModel mip-          let m2 = Map.fromAscList [(v, m IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs]-          printModel m2-          exitFailure-        Simplex2.Optimum -> do-          Just m <- MIPSolver2.getBestModel mip-          putSLine "OPTIMUM FOUND"-          let m2 = Map.fromAscList [(v, m IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs]-          printModel m2--    solveByCAD-      | not (IntSet.null ivs2) = do-          putSLine "UNKNOWN"-          putCommentLine "integer variables are not supported by CAD"-          exitFailure-      | otherwise = do-          let cs = map (fmap f) $ cs1 ++ cs2-              vs3 = Set.fromAscList $ IntSet.toAscList vs2-          case CAD.solve vs3 cs of-            Nothing -> do-              putSLine "UNSATISFIABLE"-              exitFailure-            Just m -> do-              let m2 = IntMap.map (\x -> AReal.approx x (2^^(-64::Int))) $-                         IntMap.fromAscList $ Map.toAscList $ m-              putOLine $ showValue (FOL.evalExpr m2 obj)-              putSLine "SATISFIABLE"-              let m3 = Map.fromAscList [(v, m2 IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs]-              printModel m3-      where-        f (Const r)   = P.constant r-        f (Var v)     = P.var v-        f (e1 :+: e2) = f e1 + f e2-        f (e1 :*: e2) = f e1 * f e2-        f (e1 :/: e2)-          | P.deg p > 0 = error "can't handle rational expression"-          | otherwise   = P.mapCoeff (/ c) $ f e1 -          where-            p = f e2-            c = P.coeff P.mone p--    solveByContiTraverso-      | not (vs `Set.isSubsetOf` ivs) = do-          putSLine "UNKNOWN"-          putCommentLine "continuous variables are not supported by Conti-Traverso algorithm"-          exitFailure-      | otherwise = do-          let tmp = do-                linObj <- LAFOL.fromFOLExpr obj-                linCon <- mapM LAFOL.fromFOLAtom (cs1 ++ cs2)-                return (linObj, linCon)-          case tmp of-            Nothing -> do-              putSLine "UNKNOWN"-              putCommentLine "non-linear expressions are not supported by Conti-Traverso algorithm"-              exitFailure-            Just (linObj, linCon) -> do-              case ContiTraverso.solve P.grlex vs2 (MIP.objDir $ MIP.objectiveFunction mip) linObj linCon of-                Nothing -> do-                  putSLine "UNSATISFIABLE"-                  exitFailure-                Just m -> do-                  let m2 = IntMap.map fromInteger m-                  putOLine $ showValue (FOL.evalExpr m2 obj)-                  putSLine "OPTIMUM FOUND"-                  let m3 = Map.fromAscList [(v, m2 IntMap.! (nameToVar Map.! v)) | v <- Set.toList vs]-                  printModel m3--    printRat :: Bool-    printRat = PrintRational `elem` opt--    showValue :: Rational -> String-    showValue = showRational printRat--mipPrintModel :: Handle -> Bool -> Map MIP.Var Rational -> IO ()-mipPrintModel h asRat m = do-  forM_ (Map.toList m) $ \(v, val) -> do-    printf "v %s = %s\n" (MIP.fromVar v) (showRational asRat val)---putCommentLine :: String -> IO ()-putCommentLine s = do-  putStr "c "-  putStrLn s-  hFlush stdout--putSLine :: String -> IO ()-putSLine  s = do-  putStr "s "-  putStrLn s-  hFlush stdout--putOLine :: String -> IO ()-putOLine  s = do-  putStr "o "-  putStrLn s-  hFlush stdout---- -----------------------------------------------------------------------------getSolver :: [Flag] -> String-getSolver xs = last $ "mip" : [s | Solver s <- xs]--main :: IO ()-main = do-  args <- getArgs-  case getOpt Permute options args of-    (o,_,[])-      | Help `elem` o    -> putStrLn (usageInfo header options)-      | Version `elem` o -> putStrLn (V.showVersion version)-    (o,[fname],[]) -> do--      let mode =-            case reverse [m | Mode m <- o] of-              m:_ -> m-              [] ->-                case map toLower (takeExtension fname) of-                  ".cnf"  -> ModeSAT-                  ".opb"  -> ModePB-                  ".wbo"  -> ModeWBO-                  ".wcnf" -> ModeMaxSAT-                  ".lp"   -> ModeMIP-                  ".mps"  -> ModeMIP-                  _ -> ModeMIP--      case mode of-        ModeSAT -> do-          ret <- DIMACS.parseFile fname-          case ret of-            Left err -> hPrint stderr err >> exitFailure-            Right cnf -> do-              let (mip,mtrans) = SAT2IP.convert cnf-              run (getSolver o) o mip $ \m -> do-                let m2 = mtrans m-                satPrintModel stdout m2 0-                writeSOLFileSAT o m2-        ModePB -> do-          ret <- PBFileAttoparsec.parseOPBFile fname-          case ret of-            Left err -> hPutStrLn stderr err >> exitFailure-            Right pb -> do-              let (mip,mtrans) = PB2IP.convert pb-              run (getSolver o) o mip $ \m -> do-                let m2 = mtrans m-                pbPrintModel stdout m2 0-                writeSOLFileSAT o m2-        ModeWBO -> do-          ret <- PBFileAttoparsec.parseWBOFile fname-          case ret of-            Left err -> hPutStrLn stderr err >> exitFailure-            Right wbo -> do-              let (mip,mtrans) = PB2IP.convertWBO False wbo-              run (getSolver o) o mip $ \m -> do-                let m2 = mtrans m-                pbPrintModel stdout m2 0-                writeSOLFileSAT o m2-        ModeMaxSAT -> do-          ret <- MaxSAT.parseFile fname-          case ret of-            Left err -> hPutStrLn stderr err >> exitFailure-            Right wcnf -> do-              let (mip,mtrans) = MaxSAT2IP.convert False wcnf-              run (getSolver o) o mip $ \m -> do-                let m2 = mtrans m-                maxsatPrintModel stdout m2 0-                writeSOLFileSAT o m2-        ModeMIP -> do-          ret <- MIP.readFile fname-          mip <- case ret of-                  Right mip -> return mip-                  Left err -> hPrint stderr err >> exitFailure-          run (getSolver o) o mip $ \m -> do-            mipPrintModel stdout (PrintRational `elem` o) m-            writeSOLFileMIP o m-    (_,_,errs) ->-        hPutStrLn stderr $ concat errs ++ usageInfo header options---- FIXME: 目的関数値を表示するように-writeSOLFileMIP :: [Flag] -> Map MIP.Var Rational -> IO ()-writeSOLFileMIP opt m = do-  let m2 = Map.fromList [(MIP.fromVar v, fromRational val) | (v,val) <- Map.toList m]-  writeSOLFileRaw opt m2---- FIXME: 目的関数値を表示するように-writeSOLFileSAT :: [Flag] -> SAT.Model -> IO ()-writeSOLFileSAT opt m = do-  let m2 = Map.fromList [("x" ++ show x, if b then 1 else 0) | (x,b) <- assocs m]-  writeSOLFileRaw opt m2--writeSOLFileRaw :: [Flag] -> Map String Rational -> IO ()-writeSOLFileRaw opt m = do-  forM_ [fname | WriteFile fname <- opt ] $ \fname -> do-    let m2 = Map.map fromRational m-    writeFile fname (GurobiSol.render m2 Nothing)