pseudo-boolean-0.1.0.0: src/Data/PseudoBoolean/ByteStringBuilder.hs
{-# OPTIONS_GHC -Wall #-}
-----------------------------------------------------------------------------
-- |
-- Module : Data.PseudoBoolean.ByteStringBuilder
-- Copyright : (c) Masahiro Sakai 2011-2015
-- License : BSD-style
--
-- Maintainer : masahiro.sakai@gmail.com
-- Portability : portable
--
-----------------------------------------------------------------------------
module Data.PseudoBoolean.ByteStringBuilder
(
-- * Builder for (Lazy) ByteString generation
opbBuilder
, wboBuilder
-- * Lazy ByteString generation
, toOPBByteString
, toWBOByteString
-- * File I/O
, writeOPBFile
, writeWBOFile
, hPutOPB
, hPutWBO
) where
import Prelude hiding (sum)
import Data.Monoid hiding (Sum (..))
import qualified Data.ByteString.Lazy as BS
import Data.ByteString.Builder (Builder, intDec, integerDec, char7, string7, hPutBuilder, toLazyByteString)
import System.IO
import Data.PseudoBoolean.Types
-- | A ByteString Builder which renders a OPB format byte-string containing pseudo boolean problem.
opbBuilder :: Formula -> Builder
opbBuilder opb = (size <> part1 <> part2)
where
nv = pbNumVars opb
nc = pbNumConstraints opb
size = string7 "* #variable= " <> intDec nv <> string7 " #constraint= " <> intDec nc <> char7 '\n'
part1 =
case pbObjectiveFunction opb of
Nothing -> mempty
Just o -> string7 "min: " <> showSum o <> string7 ";\n"
part2 = mconcat $ map showConstraint (pbConstraints opb)
-- | A ByteString Builder which renders a WBO format byte-string containing weighted boolean optimization problem.
wboBuilder :: SoftFormula -> Builder
wboBuilder wbo = size <> part1 <> part2
where
nv = wboNumVars wbo
nc = wboNumConstraints wbo
size = string7 "* #variable= " <> intDec nv <> string7 " #constraint= " <> intDec nc <> char7 '\n'
part1 =
case wboTopCost wbo of
Nothing -> string7 "soft: ;\n"
Just t -> string7 "soft: " <> integerDec t <> string7 ";\n"
part2 = mconcat $ map showSoftConstraint (wboConstraints wbo)
showSum :: Sum -> Builder
showSum = mconcat . map showWeightedTerm
showWeightedTerm :: WeightedTerm -> Builder
showWeightedTerm (c, lits) = foldr (\f g -> f <> char7 ' ' <> g) mempty (x:xs)
where
x = if c >= 0 then char7 '+' <> integerDec c else integerDec c
xs = map showLit lits
showLit :: Lit -> Builder
showLit lit = if lit > 0 then v else char7 '~' <> v
where
v = char7 'x' <> intDec (abs lit)
showConstraint :: Constraint -> Builder
showConstraint (lhs, op, rhs) =
showSum lhs <> f op <> char7 ' ' <> integerDec rhs <> string7 ";\n"
where
f Eq = char7 '='
f Ge = string7 ">="
showSoftConstraint :: SoftConstraint -> Builder
showSoftConstraint (cost, constr) =
case cost of
Nothing -> showConstraint constr
Just c -> char7 '[' <> integerDec c <> string7 "] " <> showConstraint constr
-- | Generate a OPB format byte-string containing pseudo boolean problem.
toOPBByteString :: Formula -> BS.ByteString
toOPBByteString opb = toLazyByteString (opbBuilder opb)
-- | Generate a WBO format byte-string containing weighted boolean optimization problem.
toWBOByteString :: SoftFormula -> BS.ByteString
toWBOByteString wbo = toLazyByteString (wboBuilder wbo)
-- | Output a OPB file containing pseudo boolean problem.
writeOPBFile :: FilePath -> Formula -> IO ()
writeOPBFile filepath opb = withBinaryFile filepath WriteMode $ \h -> do
hSetBuffering h (BlockBuffering Nothing)
hPutOPB h opb
-- | Output a WBO file containing weighted boolean optimization problem.
writeWBOFile :: FilePath -> SoftFormula -> IO ()
writeWBOFile filepath wbo = withBinaryFile filepath WriteMode $ \h -> do
hSetBuffering h (BlockBuffering Nothing)
hPutWBO h wbo
-- | Output a OPB file to a 'Handle' using 'hPutBuilder'.
--
-- It is recommended that the 'Handle' is set to binary and
-- 'BlockBuffering' mode. See 'hSetBinaryMode' and 'hSetBuffering'.
--
-- This function is more efficient than 'hPut' . 'toOPBByteString'
-- because in many cases no buffer allocation has to be done.
hPutOPB :: Handle -> Formula -> IO ()
hPutOPB h opb = hPutBuilder h (opbBuilder opb)
-- | Output a WBO file to a 'Handle' using 'hPutBuilder'.
--
-- It is recommended that the 'Handle' is set to binary and
-- 'BlockBuffering' mode. See 'hSetBinaryMode' and 'hSetBuffering'.
--
-- This function is more efficient than 'hPut' . 'toWBOByteString'
-- because in many cases no buffer allocation has to be done.
hPutWBO :: Handle -> SoftFormula -> IO ()
hPutWBO h wbo = hPutBuilder h (wboBuilder wbo)