pseudo-boolean 0.1.0.1 → 0.1.1.0
raw patch · 8 files changed
+107/−16 lines, 8 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.markdown +5/−0
- pseudo-boolean.cabal +2/−1
- src/Data/PseudoBoolean/Attoparsec.hs +3/−3
- src/Data/PseudoBoolean/Builder.hs +19/−3
- src/Data/PseudoBoolean/ByteStringBuilder.hs +19/−3
- src/Data/PseudoBoolean/Parsec.hs +7/−6
- src/Data/PseudoBoolean/Types.hs +27/−0
- test/TestPBFile.hs +25/−0
+ CHANGELOG.markdown view
@@ -0,0 +1,5 @@+0.1.1.0+-------+* parse* functions fails if the parser does not consume all of the inputs+* generate '#product=', 'sizeproduct=' and '#soft=' in header line of OPB/WBO files+* sort literals in a non-linear term when generating OPB/WBO files
pseudo-boolean.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: pseudo-boolean-version: 0.1.0.1+version: 0.1.1.0 synopsis: Reading/Writing OPB/WBO files used in pseudo boolean competition description: Reading\/Writing OPB\/WBO files used in pseudo boolean competition homepage: https://github.com/msakai/pseudo-boolean@@ -16,6 +16,7 @@ build-type: Simple extra-source-files: README.md+ CHANGELOG.markdown test/samples/*.opb test/samples/normalized-1096.cudf.paranoid.opb test/samples/*.wbo
src/Data/PseudoBoolean/Attoparsec.hs view
@@ -33,7 +33,7 @@ ) where import Prelude hiding (sum)-import Control.Applicative ((<|>))+import Control.Applicative ((<|>), (<*)) import Control.Monad import Data.Attoparsec.ByteString.Char8 hiding (isDigit) import qualified Data.Attoparsec.ByteString.Lazy as L@@ -201,7 +201,7 @@ -- | Parse a OPB format string containing pseudo boolean problem. parseOPBByteString :: BSLazy.ByteString -> Either String Formula-parseOPBByteString s = L.eitherResult $ L.parse formula s+parseOPBByteString s = L.eitherResult $ L.parse (formula <* endOfInput) s -- | Parse a OPB file containing pseudo boolean problem. parseOPBFile :: FilePath -> IO (Either String Formula)@@ -260,7 +260,7 @@ -- | Parse a WBO format string containing weighted boolean optimization problem. parseWBOByteString :: BSLazy.ByteString -> Either String SoftFormula-parseWBOByteString s = L.eitherResult $ L.parse softformula s+parseWBOByteString s = L.eitherResult $ L.parse (softformula <* endOfInput) s -- | Parse a WBO file containing weighted boolean optimization problem. parseWBOFile :: FilePath -> IO (Either String SoftFormula)
src/Data/PseudoBoolean/Builder.hs view
@@ -21,9 +21,14 @@ , 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@@ -34,7 +39,12 @@ where nv = pbNumVars opb nc = pbNumConstraints opb- size = fromString (printf "* #variable= %d #constraint= %d\n" nv nc)+ 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@@ -47,7 +57,13 @@ where nv = wboNumVars wbo nc = wboNumConstraints wbo- size = fromString (printf "* #variable= %d #constraint= %d\n" nv nc)+ 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"@@ -61,7 +77,7 @@ 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 lits+ xs = map showLit $ sortBy (comparing abs) lits showLit :: (Monoid a, IsString a) => Lit -> a showLit lit = if lit > 0 then v else fromString "~" <> v
src/Data/PseudoBoolean/ByteStringBuilder.hs view
@@ -27,10 +27,15 @@ , hPutWBO ) where +import qualified Prelude import Prelude hiding (sum)+import qualified Data.IntSet as IntSet+import qualified Data.Set as Set+import Data.List (sortBy) import Data.Monoid hiding (Sum (..)) import qualified Data.ByteString.Lazy as BS import Data.ByteString.Builder (Builder, intDec, integerDec, char7, string7, hPutBuilder, toLazyByteString)+import Data.Ord import System.IO import Data.PseudoBoolean.Types @@ -40,7 +45,12 @@ where nv = pbNumVars opb nc = pbNumConstraints opb- size = string7 "* #variable= " <> intDec nv <> string7 " #constraint= " <> intDec nc <> char7 '\n'+ p = pbProducts opb+ np = Set.size p+ sp = Prelude.sum [IntSet.size tm | tm <- Set.toList p]+ size = string7 "* #variable= " <> intDec nv <> string7 " #constraint= " <> intDec nc+ <> (if np >= 1 then string7 " #product= " <> intDec np <> string7 " sizeproduct= " <> intDec sp else mempty)+ <> char7 '\n' part1 = case pbObjectiveFunction opb of Nothing -> mempty@@ -53,7 +63,13 @@ where nv = wboNumVars wbo nc = wboNumConstraints wbo- size = string7 "* #variable= " <> intDec nv <> string7 " #constraint= " <> intDec nc <> char7 '\n'+ p = wboProducts wbo+ np = Set.size p+ sp = Prelude.sum [IntSet.size tm | tm <- Set.toList p]+ size = string7 "* #variable= " <> intDec nv <> string7 " #constraint= " <> intDec nc+ <> (if np >= 1 then string7 " #product= " <> intDec np <> string7 " sizeproduct= " <> intDec sp else mempty)+ <> string7 " #soft= " <> intDec (wboNumSoft wbo)+ <> char7 '\n' part1 = case wboTopCost wbo of Nothing -> string7 "soft: ;\n"@@ -67,7 +83,7 @@ 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+ xs = map showLit $ sortBy (comparing abs) lits showLit :: Lit -> Builder showLit lit = if lit > 0 then v else char7 '~' <> v
src/Data/PseudoBoolean/Parsec.hs view
@@ -35,6 +35,7 @@ ) where import Prelude hiding (sum)+import Control.Applicative ((<*)) import Control.Monad import Data.ByteString.Lazy (ByteString) import Data.Maybe@@ -200,15 +201,15 @@ -- | Parse a OPB format string containing pseudo boolean problem. parseOPBString :: SourceName -> String -> Either ParseError Formula-parseOPBString = parse formula+parseOPBString = parse (formula <* eof) -- | Parse a OPB format lazy bytestring containing pseudo boolean problem. parseOPBByteString :: SourceName -> ByteString -> Either ParseError Formula-parseOPBByteString = parse formula+parseOPBByteString = parse (formula <* eof) -- | Parse a OPB file containing pseudo boolean problem. parseOPBFile :: FilePath -> IO (Either ParseError Formula)-parseOPBFile = ParsecBS.parseFromFile formula+parseOPBFile = ParsecBS.parseFromFile (formula <* eof) -- <softformula>::= <sequence_of_comments> <softheader> <sequence_of_comments_or_constraints>@@ -262,12 +263,12 @@ -- | Parse a WBO format string containing weighted boolean optimization problem. parseWBOString :: SourceName -> String -> Either ParseError SoftFormula-parseWBOString = parse softformula+parseWBOString = parse (softformula <* eof) -- | Parse a WBO format lazy bytestring containing pseudo boolean problem. parseWBOByteString :: SourceName -> ByteString -> Either ParseError SoftFormula-parseWBOByteString = parse softformula+parseWBOByteString = parse (softformula <* eof) -- | Parse a WBO file containing weighted boolean optimization problem. parseWBOFile :: FilePath -> IO (Either ParseError SoftFormula)-parseWBOFile = ParsecBS.parseFromFile softformula+parseWBOFile = ParsecBS.parseFromFile (softformula <* eof)
src/Data/PseudoBoolean/Types.hs view
@@ -33,12 +33,20 @@ -- * Internal utilities , pbComputeNumVars+ , pbProducts , wboComputeNumVars+ , wboProducts+ , wboNumSoft ) where import GHC.Generics (Generic)+import Control.Monad import Control.DeepSeq import Data.Data+import Data.Set (Set)+import qualified Data.Set as Set+import Data.IntSet (IntSet)+import qualified Data.IntSet as IntSet import Data.Hashable import Data.Maybe @@ -117,3 +125,22 @@ (_, tm) <- s lit <- tm return $ abs lit++pbProducts :: Formula -> Set IntSet+pbProducts formula = Set.fromList $ do + s <- maybeToList (pbObjectiveFunction formula) ++ [s | (s,_,_) <- pbConstraints formula]+ (_, tm) <- s+ let tm2 = IntSet.fromList tm+ guard $ IntSet.size tm2 > 1+ return tm2++wboProducts :: SoftFormula -> Set IntSet+wboProducts softformula = Set.fromList $ do+ (_,(s,_,_)) <- wboConstraints softformula+ (_, tm) <- s+ let tm2 = IntSet.fromList tm+ guard $ IntSet.size tm2 > 1+ return tm2++wboNumSoft :: SoftFormula -> Int+wboNumSoft softformula = length [() | (Just _, _) <- wboConstraints softformula]
test/TestPBFile.hs view
@@ -2,6 +2,7 @@ {-# OPTIONS_GHC -Wall #-} module Main (main) where +import Data.Either import qualified Data.ByteString.Lazy.Char8 as BSChar8 import System.IO import System.IO.Temp@@ -36,6 +37,30 @@ case_normalized_mds_50_10_4 = checkOPBFile "test/samples/normalized-mds_50_10_4.opb" case_normalized_opt_market_split_4_30_2 = checkOPBFile "test/samples/normalized-opt-market-split_4_30_2.opb" case_pigeonhole_5_4 = checkOPBFile "test/samples/pigeonhole_5_4.opb"++case_trailing_junk = do+ isError (parseOPBString "" trailingJunk) @?= True+ isError (parseOPBByteString "" (BSChar8.pack trailingJunk)) @?= True+ isError (A.parseOPBByteString (BSChar8.pack trailingJunk)) @?= True+ where+ -- isLeft is available only on base >=4.7.0.0.+ isError :: Either a b -> Bool+ isError (Left _) = True+ isError (Right _) = False+ + trailingJunk = unlines+ [ "* #variable= 5 #constraint= 4"+ , "*"+ , "* this is a dummy instance"+ , "*"+ , "min: 1 x2 -1 x3 ;"+ , "1 x1 +4 x2 -2 x5 >= 2;"+ , "-1 x1 +4 x2 -2 x5 >= +3;"+ , "12345678901234567890 x4 +4 x3 >= 10;"+ , "* an equality constraint"+ , "2 x2 +3 x4 +2 x1 +3 x5 = 5;"+ , "foo"+ ] case_readUnsignedInteger_maxBound_bug :: IO () case_readUnsignedInteger_maxBound_bug =