packages feed

toysolver-0.0.2: src/SAT/Integer.hs

{-# LANGUAGE MultiParamTypeClasses #-}
module SAT.Integer where

import Control.Monad
import Data.Array.IArray
import Text.Printf
import SAT
import Data.Linear

data Expr = Expr [(Integer, SAT.Lit)] Integer

newVar :: SAT.Solver -> Integer -> Integer -> IO Expr
newVar solver lo hi = do
  when (lo > hi) $ error $ printf "SAT.Integer.newVar: inconsistent bounds given [%d, %d]" lo hi
  let hi' = hi - lo
      bitWidth = head $ [w | w <- [1..], let mx = 2 ^ w - 1, hi' <= mx]
  vs <- replicateM bitWidth (SAT.newVar solver)
  let xs = zip (iterate (2*) 1) vs
  SAT.addPBAtMost solver xs hi'
  return $ Expr xs lo

constant :: Integer -> Expr
constant c = Expr [] c

instance Module Integer Expr where
  n .*. Expr xs c = Expr [(n*m,lit) | (m,lit) <- xs] (n*c)
  Expr xs1 c1 .+. Expr xs2 c2 = Expr (xs1++xs2) (c1+c2)
  lzero = Expr [] 0

addLe :: SAT.Solver -> Expr -> Expr -> IO ()
addLe solver lhs rhs = do
  let Expr xs c = lhs .-. rhs
  SAT.addPBAtMost solver xs (-c)

addGe :: SAT.Solver -> Expr -> Expr -> IO ()
addGe solver lhs rhs = do
  let Expr xs c = lhs .-. rhs
  SAT.addPBAtLeast solver xs (-c)

addEq :: SAT.Solver -> Expr -> Expr -> IO ()
addEq solver lhs rhs = do
  let Expr xs c = lhs .-. rhs
  SAT.addPBExactly solver xs (-c)

addLeSoft :: SAT.Solver -> SAT.Lit -> Expr -> Expr -> IO ()
addLeSoft solver ind lhs rhs = do
  let Expr xs c = lhs .-. rhs
  SAT.addPBAtMostSoft solver ind xs (-c)

addGeSoft :: SAT.Solver -> SAT.Lit -> Expr -> Expr -> IO ()
addGeSoft solver ind lhs rhs = do
  let Expr xs c = lhs .-. rhs
  SAT.addPBAtLeastSoft solver ind xs (-c)

addEqSoft :: SAT.Solver -> SAT.Lit -> Expr -> Expr -> IO ()
addEqSoft solver ind lhs rhs = do
  let Expr xs c = lhs .-. rhs
  SAT.addPBExactlySoft solver ind xs (-c)

eval :: SAT.Model -> Expr -> Integer
eval m (Expr ts c) = sum [if m ! SAT.litVar lit == SAT.litPolarity lit then n else 0 | (n,lit) <- ts] + c