pseudo-boolean-0.1.1.0: src/Data/PseudoBoolean/Builder.hs
{-# OPTIONS_GHC -Wall #-}
-----------------------------------------------------------------------------
-- |
-- Module : Data.PseudoBoolean.Builder
-- Copyright : (c) Masahiro Sakai 2011-2015
-- License : BSD-style
--
-- Maintainer : masahiro.sakai@gmail.com
-- Portability : portable
--
-----------------------------------------------------------------------------
module Data.PseudoBoolean.Builder
(
-- * Builder for String-like Monoid
opbBuilder
, wboBuilder
-- * String generation
, toOPBString
, toWBOString
) where
import qualified Prelude
import Prelude hiding (sum)
import qualified Data.DList as DList
import qualified Data.IntSet as IntSet
import qualified Data.Set as Set
import Data.List (sortBy)
import Data.Monoid hiding (Sum (..))
import Data.Ord
import Data.String
import Text.Printf
import Data.PseudoBoolean.Types
-- | A builder which renders a OPB format in any String-like 'Monoid'.
opbBuilder :: (Monoid a, IsString a) => Formula -> a
opbBuilder opb = (size <> part1 <> part2)
where
nv = pbNumVars opb
nc = pbNumConstraints opb
p = pbProducts opb
np = Set.size p
sp = Prelude.sum [IntSet.size tm | tm <- Set.toList p]
size = fromString (printf "* #variable= %d #constraint= %d" nv nc)
<> (if np >= 1 then fromString (printf " #product= %d sizeproduct= %d" np sp) else mempty)
<> fromString "\n"
part1 =
case pbObjectiveFunction opb of
Nothing -> mempty
Just o -> fromString "min: " <> showSum o <> fromString ";\n"
part2 = mconcat $ map showConstraint (pbConstraints opb)
-- | A builder which renders a WBO format in any String-like 'Monoid'.
wboBuilder :: (Monoid a, IsString a) => SoftFormula -> a
wboBuilder wbo = size <> part1 <> part2
where
nv = wboNumVars wbo
nc = wboNumConstraints wbo
p = wboProducts wbo
np = Set.size p
sp = Prelude.sum [IntSet.size tm | tm <- Set.toList p]
size = fromString (printf "* #variable= %d #constraint= %d" nv nc)
<> (if np >= 1 then fromString (printf " #product= %d sizeproduct= %d" np sp) else mempty)
<> fromString (printf " #soft= %d" (wboNumSoft wbo))
<> fromString "\n"
part1 =
case wboTopCost wbo of
Nothing -> fromString "soft: ;\n"
Just t -> fromString "soft: " <> fromString (show t) <> fromString ";\n"
part2 = mconcat $ map showSoftConstraint (wboConstraints wbo)
showSum :: (Monoid a, IsString a) => Sum -> a
showSum = mconcat . map showWeightedTerm
showWeightedTerm :: (Monoid a, IsString a) => WeightedTerm -> a
showWeightedTerm (c, lits) = foldr (\f g -> f <> fromString " " <> g) mempty (x:xs)
where
x = if c >= 0 then fromString "+" <> fromString (show c) else fromString (show c)
xs = map showLit $ sortBy (comparing abs) lits
showLit :: (Monoid a, IsString a) => Lit -> a
showLit lit = if lit > 0 then v else fromString "~" <> v
where
v = fromString "x" <> fromString (show (abs lit))
showConstraint :: (Monoid a, IsString a) => Constraint -> a
showConstraint (lhs, op, rhs) =
showSum lhs <> f op <> fromString " " <> fromString (show rhs) <> fromString ";\n"
where
f Eq = fromString "="
f Ge = fromString ">="
showSoftConstraint :: (Monoid a, IsString a) => SoftConstraint -> a
showSoftConstraint (cost, constr) =
case cost of
Nothing -> showConstraint constr
Just c -> fromString "[" <> fromString (show c) <> fromString "] " <> showConstraint constr
-- | Generate a OPB format string containing pseudo boolean problem.
toOPBString :: Formula -> String
toOPBString opb = DList.apply (opbBuilder opb) ""
-- | Generate a WBO format string containing weighted boolean optimization problem.
toWBOString :: SoftFormula -> String
toWBOString wbo = DList.apply (wboBuilder wbo) ""