monadiccp 0.5.2 → 0.6
raw patch · 39 files changed
+3791/−734 lines, 39 filesdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
- Control.CP.ComposableTransformers: (:-) :: c1 -> c2 -> Composition (CEvalState c1, CEvalState c2) (CTreeState c1, CTreeState c2) solver a
- Control.CP.ComposableTransformers: BBP :: Int -> (Bound solver) -> BBEvalState solver
- Control.CP.ComposableTransformers: TStack :: c -> TStack (CEvalState c) (CTreeState c) solver a
- Control.CP.ComposableTransformers: completeCT :: (CTransformer c) => c -> CEvalState c -> Bool
- Control.CP.ComposableTransformers: continueCT :: CContinueSig c a
- Control.CP.ComposableTransformers: data BBEvalState solver
- Control.CP.ComposableTransformers: data Composition es ts solver a
- Control.CP.ComposableTransformers: data TStack es ts solver :: (* -> *) a
- Control.CP.ComposableTransformers: evalCT :: CSearchSig c a
- Control.CP.ComposableTransformers: exitCT :: CContinueSig c a
- Control.CP.ComposableTransformers: initCT :: (CTransformer c) => c -> (CEvalState c, CTreeState c)
- Control.CP.ComposableTransformers: leftCT :: (CTransformer c) => c -> CTreeState c -> CTreeState c
- Control.CP.ComposableTransformers: nextCT :: (CTransformer c) => CSearchSig c (CForResult c)
- Control.CP.ComposableTransformers: nextTStack :: (Solver solver, Queue q, (Elem q) ~ (Label solver, Tree solver a, ts)) => Int -> Tree solver a -> q -> (TStack es ts solver a) -> es -> ts -> solver (Int, [a])
- Control.CP.ComposableTransformers: returnCT :: (CTransformer c) => CContinueSig c (CForResult c)
- Control.CP.ComposableTransformers: rightCT :: (CTransformer c) => c -> CTreeState c -> CTreeState c
- Control.CP.ComposableTransformers: type Bound solver = forall a. Tree solver a -> Tree solver a
- Control.CP.ComposableTransformers: type CONTINUE c a = CEvalState c -> (CForSolver c) (Int, [a])
- Control.CP.ComposableTransformers: type EVAL c a = Tree (CForSolver c) a -> CEvalState c -> CTreeState c -> (CForSolver c) (Int, [a])
- Control.CP.ComposableTransformers: type EXIT c a = (CEvalState c) -> (CForSolver c) (Int, [a])
- Control.CP.ComposableTransformers: type CSearchSig c a = (Solver (CForSolver c), CTransformer c) => Tree (CForSolver c) a -> c -> CEvalState c -> CTreeState c -> (EVAL c a) -> (CONTINUE c a) -> (EXIT c a) -> (CForSolver c) (Int, [a])
- Control.CP.ComposableTransformers: type CContinueSig c a = (Solver (CForSolver c), CTransformer c) => c -> CEvalState c -> (CONTINUE c a) -> (EXIT c a) -> (CForSolver c) (Int, [a])
- Control.CP.FD.Domain: class ToDomain a
- Control.CP.FD.Domain: data Domain
- Control.CP.FD.Domain: difference :: Domain -> Domain -> Domain
- Control.CP.FD.Domain: elems :: Domain -> [Int]
- Control.CP.FD.Domain: empty :: Domain
- Control.CP.FD.Domain: filterGreaterThan :: Int -> Domain -> Domain
- Control.CP.FD.Domain: filterLessThan :: Int -> Domain -> Domain
- Control.CP.FD.Domain: findMax :: Domain -> Int
- Control.CP.FD.Domain: findMin :: Domain -> Int
- Control.CP.FD.Domain: instance [incoherent] (Integral a) => ToDomain [a]
- Control.CP.FD.Domain: instance [incoherent] (Integral a) => ToDomain a
- Control.CP.FD.Domain: instance [incoherent] (Integral a, Integral b) => ToDomain (a, b)
- Control.CP.FD.Domain: instance [incoherent] Eq Domain
- Control.CP.FD.Domain: instance [incoherent] Show Domain
- Control.CP.FD.Domain: instance [incoherent] ToDomain ()
- Control.CP.FD.Domain: instance [incoherent] ToDomain Domain
- Control.CP.FD.Domain: instance [incoherent] ToDomain IntSet
- Control.CP.FD.Domain: intersection :: Domain -> Domain -> Domain
- Control.CP.FD.Domain: isSingleton :: Domain -> Bool
- Control.CP.FD.Domain: isSubsetOf :: Domain -> Domain -> Bool
- Control.CP.FD.Domain: member :: Int -> Domain -> Bool
- Control.CP.FD.Domain: null :: Domain -> Bool
- Control.CP.FD.Domain: shiftDomain :: Domain -> Int -> Domain
- Control.CP.FD.Domain: singleton :: Int -> Domain
- Control.CP.FD.Domain: size :: Domain -> Int
- Control.CP.FD.Domain: toDomain :: (ToDomain a) => a -> Domain
- Control.CP.FD.Domain: union :: Domain -> Domain -> Domain
- Control.CP.FD.FD: (#<) :: (To_FD_Term a, To_FD_Term b) => a -> b -> FD Bool
- Control.CP.FD.FD: (.*.) :: (ToExpr a, ToExpr b) => a -> b -> Expr
- Control.CP.FD.FD: (.+.) :: (ToExpr a, ToExpr b) => a -> b -> Expr
- Control.CP.FD.FD: (.-.) :: (ToExpr a, ToExpr b) => a -> b -> Expr
- Control.CP.FD.FD: (./=.) :: (ToExpr a, ToExpr b) => a -> b -> FD Bool
- Control.CP.FD.FD: (.<.) :: FDVar -> FDVar -> FD Bool
- Control.CP.FD.FD: (.==.) :: (ToExpr a, ToExpr b) => a -> b -> FD Bool
- Control.CP.FD.FD: Expr :: FD (FDVar) -> Expr
- Control.CP.FD.FD: FD :: StateT FDState Maybe a -> FD a
- Control.CP.FD.FD: FDState :: VarSupply -> VarMap -> FDVar -> FDState
- Control.CP.FD.FD: FDVar :: Int -> FDVar
- Control.CP.FD.FD: FD_AllDiff :: [FD_Term] -> FD_Constraint
- Control.CP.FD.FD: FD_Diff :: FD_Term -> FD_Term -> FD_Constraint
- Control.CP.FD.FD: FD_Dom :: FD_Term -> (Int, Int) -> FD_Constraint
- Control.CP.FD.FD: FD_Eq :: a -> b -> FD_Constraint
- Control.CP.FD.FD: FD_GT :: FD_Term -> Int -> FD_Constraint
- Control.CP.FD.FD: FD_HasValue :: FD_Term -> Int -> FD_Constraint
- Control.CP.FD.FD: FD_LT :: FD_Term -> Int -> FD_Constraint
- Control.CP.FD.FD: FD_Less :: FD_Term -> FD_Term -> FD_Constraint
- Control.CP.FD.FD: FD_NEq :: a -> b -> FD_Constraint
- Control.CP.FD.FD: FD_Same :: FD_Term -> FD_Term -> FD_Constraint
- Control.CP.FD.FD: FD_Var :: FDVar -> FD_Term
- Control.CP.FD.FD: VarInfo :: FD Bool -> Domain -> VarInfo
- Control.CP.FD.FD: addArithmeticConstraint :: (ToExpr a, ToExpr b) => (Domain -> Domain -> Domain) -> (Domain -> Domain -> Domain) -> (Domain -> Domain -> Domain) -> a -> b -> Expr
- Control.CP.FD.FD: addBinaryConstraint :: BinaryConstraint -> BinaryConstraint
- Control.CP.FD.FD: addConstraint :: FDVar -> FD Bool -> FD ()
- Control.CP.FD.FD: allDifferent :: [FDVar] -> FD ()
- Control.CP.FD.FD: class ToExpr a
- Control.CP.FD.FD: class To_FD_Term a
- Control.CP.FD.FD: consistentFD :: FD Bool
- Control.CP.FD.FD: data FDState
- Control.CP.FD.FD: data FD_Constraint
- Control.CP.FD.FD: data FD_Term
- Control.CP.FD.FD: data VarInfo
- Control.CP.FD.FD: delayedConstraints :: VarInfo -> FD Bool
- Control.CP.FD.FD: different :: FDVar -> FDVar -> FD Bool
- Control.CP.FD.FD: domain :: VarInfo -> Domain
- Control.CP.FD.FD: dump :: [FDVar] -> FD [Domain]
- Control.CP.FD.FD: exprVar :: (ToExpr a) => a -> FD FDVar
- Control.CP.FD.FD: fd_domain :: FD_Term -> FD [Int]
- Control.CP.FD.FD: fd_objective :: FD FD_Term
- Control.CP.FD.FD: getDomainDiv :: Domain -> Domain -> Domain
- Control.CP.FD.FD: getDomainMinus :: Domain -> Domain -> Domain
- Control.CP.FD.FD: getDomainMult :: Domain -> Domain -> Domain
- Control.CP.FD.FD: getDomainPlus :: Domain -> Domain -> Domain
- Control.CP.FD.FD: hasValue :: FDVar -> Int -> FD Bool
- Control.CP.FD.FD: in_range :: FD_Term -> (Int, Int) -> FD Bool
- Control.CP.FD.FD: initState :: FDState
- Control.CP.FD.FD: instance [overlap ok] (Integral i) => ToExpr i
- Control.CP.FD.FD: instance [overlap ok] Eq FDState
- Control.CP.FD.FD: instance [overlap ok] Eq FDVar
- Control.CP.FD.FD: instance [overlap ok] Monad FD
- Control.CP.FD.FD: instance [overlap ok] MonadPlus FD
- Control.CP.FD.FD: instance [overlap ok] MonadState FDState FD
- Control.CP.FD.FD: instance [overlap ok] Ord FDState
- Control.CP.FD.FD: instance [overlap ok] Ord FDVar
- Control.CP.FD.FD: instance [overlap ok] Show FDState
- Control.CP.FD.FD: instance [overlap ok] Show FDVar
- Control.CP.FD.FD: instance [overlap ok] Show FD_Term
- Control.CP.FD.FD: instance [overlap ok] Show VarInfo
- Control.CP.FD.FD: instance [overlap ok] Solver FD
- Control.CP.FD.FD: instance [overlap ok] Term FD FD_Term
- Control.CP.FD.FD: instance [overlap ok] ToExpr Expr
- Control.CP.FD.FD: instance [overlap ok] ToExpr FDVar
- Control.CP.FD.FD: instance [overlap ok] ToExpr FD_Term
- Control.CP.FD.FD: instance [overlap ok] To_FD_Term Expr
- Control.CP.FD.FD: instance [overlap ok] To_FD_Term FD_Term
- Control.CP.FD.FD: instance [overlap ok] To_FD_Term Int
- Control.CP.FD.FD: lookup :: FDVar -> FD Domain
- Control.CP.FD.FD: newVar :: (ToDomain a) => a -> FD FDVar
- Control.CP.FD.FD: newVars :: (ToDomain a) => Int -> a -> FD [FDVar]
- Control.CP.FD.FD: newtype Expr
- Control.CP.FD.FD: newtype FD a
- Control.CP.FD.FD: newtype FDVar
- Control.CP.FD.FD: objective :: FDState -> FDVar
- Control.CP.FD.FD: runFD :: FD a -> a
- Control.CP.FD.FD: same :: FDVar -> FDVar -> FD Bool
- Control.CP.FD.FD: toExpr :: (ToExpr a) => a -> Expr
- Control.CP.FD.FD: to_fd_term :: (To_FD_Term a) => a -> FD FD_Term
- Control.CP.FD.FD: type BinaryConstraint = FDVar -> FDVar -> FD Bool
- Control.CP.FD.FD: type VarMap = Map FDVar VarInfo
- Control.CP.FD.FD: type VarSupply = FDVar
- Control.CP.FD.FD: unExpr :: Expr -> FD (FDVar)
- Control.CP.FD.FD: unFD :: FD a -> StateT FDState Maybe a
- Control.CP.FD.FD: unFDVar :: FDVar -> Int
- Control.CP.FD.FD: update :: FDVar -> Domain -> FD Bool
- Control.CP.FD.FD: varMap :: FDState -> VarMap
- Control.CP.FD.FD: varSupply :: FDState -> VarSupply
- Control.CP.FD.FDSugar: (:+) :: FD_Term -> Int -> Plus
- Control.CP.FD.FDSugar: (@<) :: FD_Term -> Int -> Tree FD ()
- Control.CP.FD.FDSugar: (@=) :: FD_Term -> Int -> Tree FD ()
- Control.CP.FD.FDSugar: (@>) :: FD_Term -> Int -> Tree FD ()
- Control.CP.FD.FDSugar: (@\=) :: FD_Term -> FD_Term -> Tree FD ()
- Control.CP.FD.FDSugar: (@\==) :: FD_Term -> Plus -> Tree FD ()
- Control.CP.FD.FDSugar: bb :: NewBound FD -> CBranchBoundST FD a
- Control.CP.FD.FDSugar: data Plus
- Control.CP.FD.FDSugar: db :: Int -> CDepthBoundedST FD a
- Control.CP.FD.FDSugar: fs :: CFirstSolutionST FD a
- Control.CP.FD.FDSugar: in_order :: (Monad m) => a -> m a
- Control.CP.FD.FDSugar: it :: CIdentityCST FD a
- Control.CP.FD.FDSugar: ld :: Int -> CLimitedDiscrepancyST FD a
- Control.CP.FD.FDSugar: nb :: Int -> CNodeBoundedST FD a
- Control.CP.FD.FDSugar: newBound :: NewBound FD
- Control.CP.FD.FDSugar: newBoundBis :: NewBound FD
- Control.CP.FD.FDSugar: pfs :: (Ord a) => PriorityQueue a (a, b, c)
- Control.CP.FD.FDSugar: ra :: Int -> CRandomST FD a
- Control.CP.FD.FDSugar: restart :: (Queue q, Solver solver, CTransformer c, (CForSolver c) ~ solver, (Elem q) ~ (Label solver, Tree solver (CForResult c), CTreeState c)) => q -> [c] -> Tree solver (CForResult c) -> (Int, [CForResult c])
- Control.CP.FD.FDSugar: restartOpt :: (Queue q, CTransformer c, (CForSolver c) ~ FD, (Elem q) ~ (Label FD, Tree FD (CForResult c), CTreeState c)) => q -> [c] -> Tree FD (CForResult c) -> (Int, [CForResult c])
- Control.CP.Herbrand.Herbrand: ACTION :: (m Bool) -> Binding t m
- Control.CP.Herbrand.Herbrand: HState :: VarSupply t -> Heap t m -> HState t m
- Control.CP.Herbrand.Herbrand: NONVAR :: t -> Binding t m
- Control.CP.Herbrand.Herbrand: Unify :: t -> t -> Unify t
- Control.CP.Herbrand.Herbrand: VAR :: (VarId t) -> Binding t m
- Control.CP.Herbrand.Herbrand: bindt :: (HTerm t, MonadState (HState t m) m) => VarId t -> t -> m Bool
- Control.CP.Herbrand.Herbrand: bindv :: (HTerm t, MonadState (HState t m) m) => VarId t -> VarId t -> m Bool
- Control.CP.Herbrand.Herbrand: data Binding t m
- Control.CP.Herbrand.Herbrand: heap :: HState t m -> Heap t m
- Control.CP.Herbrand.Herbrand: normalize :: (HTerm t, MonadState (HState t m) m) => t -> m t
- Control.CP.Herbrand.Herbrand: type Heap t m = Map (VarId t) (Binding t m)
- Control.CP.Herbrand.Herbrand: updateState :: (HTerm t, MonadState (HState t m) m) => (HState t m -> HState t m) -> m ()
- Control.CP.Herbrand.Herbrand: var_supply :: HState t m -> VarSupply t
- Control.CP.SearchTree: add :: (MonadTree tree) => Constraint (TreeSolver tree) -> tree ()
- Control.CP.Transformers: DBST :: Int -> DepthBoundedST a
- Control.CP.Transformers: NBST :: Int -> NodeBoundedST a
- Control.CP.Transformers: newtype DepthBoundedST solver :: (* -> *) a
- Control.CP.Transformers: newtype NodeBoundedST solver :: (* -> *) a
- Control.CP.Transformers: type ContinueSig solver q t a = (Solver solver, Queue q, Transformer t, (Elem q) ~ (Label solver, Tree solver a, TreeState t), (ForSolver t) ~ solver) => Int -> q -> t -> EvalState t -> solver (Int, [a])
+ Control.CP.EnumTerm: assignment :: (EnumTerm s t) => t -> Tree s (TermDomain s t)
+ Control.CP.EnumTerm: assignments :: (EnumTerm s t) => [t] -> Tree s [TermDomain s t]
+ Control.CP.EnumTerm: class (Term s t, Enum (TermDomain s t)) => EnumTerm s t where { type family TermDomain s t :: *; { enumerate l = label firstfail l label o l = Label $ do { x <- o l; split_domains x } split_domains [] = return $ return () split_domains [a] = split_domain a split_domains (a : b) = do { ta <- split_domain a; tb <- split_domains b; return $ ta /\ tb } split_domain v = do { let rec tree = do { tree; Label $ do { x <- get_value v; case x of { Nothing -> split_domain v Just _ -> return $ return () } } }; lst <- split_domain_partial v; return $ levelList $ map rec lst } } }
+ Control.CP.EnumTerm: endsout :: [a] -> [a]
+ Control.CP.EnumTerm: enumerate :: (EnumTerm s t) => [t] -> Tree s ()
+ Control.CP.EnumTerm: firstfail :: (EnumTerm m a) => [a] -> m [a]
+ Control.CP.EnumTerm: get_domain_size :: (EnumTerm s t) => t -> s Int
+ Control.CP.EnumTerm: get_value :: (EnumTerm s t) => t -> s (Maybe (TermDomain s t))
+ Control.CP.EnumTerm: in_order :: (Monad m) => a -> m a
+ Control.CP.EnumTerm: interleave :: [t] -> [t] -> [t]
+ Control.CP.EnumTerm: label :: (EnumTerm s t) => ([t] -> s [t]) -> [t] -> Tree s ()
+ Control.CP.EnumTerm: middleout :: [a] -> [a]
+ Control.CP.EnumTerm: split_domain :: (EnumTerm s t) => t -> s (Tree s ())
+ Control.CP.EnumTerm: split_domain_partial :: (EnumTerm s t) => t -> s [Tree s ()]
+ Control.CP.EnumTerm: split_domains :: (EnumTerm s t) => [t] -> s (Tree s ())
+ Control.CP.FD.Example.Example: example_main :: (forall s. (FDSolver s) => [String] -> FDTree s [FDExpr s]) -> IO ()
+ Control.CP.FD.Example.Example: example_main_single :: (Read n) => (forall s. (FDSolver s) => n -> FDTree s [FDExpr s]) -> IO ()
+ Control.CP.FD.Example.Example: example_main_void :: (forall s. (FDSolver s) => FDTree s [FDExpr s]) -> IO ()
+ Control.CP.FD.Example.Example: type FDModel = (FDSolver s) => Tree (FDWrapper s) [FDExpr s]
+ Control.CP.FD.Expr: Abs :: (Expr t) -> Expr t
+ Control.CP.FD.Expr: Const :: Integer -> Expr t
+ Control.CP.FD.Expr: Div :: (Expr t) -> (Expr t) -> Expr t
+ Control.CP.FD.Expr: ExprKey :: (Expr s) -> ExprKey s
+ Control.CP.FD.Expr: Minus :: (Expr t) -> (Expr t) -> Expr t
+ Control.CP.FD.Expr: Mod :: (Expr t) -> (Expr t) -> Expr t
+ Control.CP.FD.Expr: Mult :: (Expr t) -> (Expr t) -> Expr t
+ Control.CP.FD.Expr: Plus :: (Expr t) -> (Expr t) -> Expr t
+ Control.CP.FD.Expr: Term :: t -> Expr t
+ Control.CP.FD.Expr: class ToExpr tt t
+ Control.CP.FD.Expr: data Expr t
+ Control.CP.FD.Expr: instance (Eq s) => Eq (ExprKey s)
+ Control.CP.FD.Expr: instance (Eq s, Show s) => Enum (Expr s)
+ Control.CP.FD.Expr: instance (Eq s, Show s) => Integral (Expr s)
+ Control.CP.FD.Expr: instance (Eq s, Show s) => Num (Expr s)
+ Control.CP.FD.Expr: instance (Eq s, Show s) => Ord (Expr s)
+ Control.CP.FD.Expr: instance (Eq s, Show s) => Real (Expr s)
+ Control.CP.FD.Expr: instance (Eq t) => Eq (Expr t)
+ Control.CP.FD.Expr: instance (Ord s) => Ord (ExprKey s)
+ Control.CP.FD.Expr: instance (Show s) => Show (ExprKey s)
+ Control.CP.FD.Expr: instance (Show t) => Show (Expr t)
+ Control.CP.FD.Expr: instance ToExpr t (Expr t)
+ Control.CP.FD.Expr: instance ToExpr t t
+ Control.CP.FD.Expr: instance ToExpr tt Int
+ Control.CP.FD.Expr: instance ToExpr tt Integer
+ Control.CP.FD.Expr: newtype ExprKey s
+ Control.CP.FD.Expr: toExpr :: (ToExpr tt t) => t -> Expr tt
+ Control.CP.FD.Expr: unExprKey :: ExprKey s -> Expr s
+ Control.CP.FD.FD: (@%) :: (ToExpr tt t, ToExpr tt t1, Eq tt, Show tt) => t -> t1 -> Expr tt
+ Control.CP.FD.FD: (@*) :: (ToExpr tt t, ToExpr tt t1, Eq tt, Show tt) => t -> t1 -> Expr tt
+ Control.CP.FD.FD: (@+) :: (ToExpr tt t, ToExpr tt t1, Eq tt, Show tt) => t -> t1 -> Expr tt
+ Control.CP.FD.FD: (@-) :: (ToExpr tt t, ToExpr tt t1, Eq tt, Show tt) => t -> t1 -> Expr tt
+ Control.CP.FD.FD: (@/) :: (ToExpr tt t, ToExpr tt t1, Eq tt, Show tt) => t -> t1 -> Expr tt
+ Control.CP.FD.FD: (@/=) :: ((FDConstraint s) ~ (Constraint (TreeSolver tree)), MonadTree tree, Show (FDTerm s)) => Expr (FDTerm s) -> Expr (FDTerm s) -> tree ()
+ Control.CP.FD.FD: (@:) :: ((FDConstraint s) ~ (Constraint (TreeSolver tree)), MonadTree tree, Integral t, Integral t1, Show (FDTerm s)) => Expr (FDTerm s) -> (t, t1) -> tree ()
+ Control.CP.FD.FD: (@<) :: ((FDConstraint s) ~ (Constraint (TreeSolver tree)), MonadTree tree, Show (FDTerm s)) => Expr (FDTerm s) -> Expr (FDTerm s) -> tree ()
+ Control.CP.FD.FD: (@<=) :: ((FDConstraint s) ~ (Constraint (TreeSolver tree)), MonadTree tree, Eq (FDTerm s), Show (FDTerm s)) => Expr (FDTerm s) -> Expr (FDTerm s) -> tree ()
+ Control.CP.FD.FD: (@=) :: ((FDConstraint s) ~ (Constraint (TreeSolver tree)), MonadTree tree, Show (FDTerm s)) => Expr (FDTerm s) -> Expr (FDTerm s) -> tree ()
+ Control.CP.FD.FD: (@>) :: ((FDConstraint s) ~ (Constraint (TreeSolver tree)), MonadTree tree, Show (FDTerm s)) => Expr (FDTerm s) -> Expr (FDTerm s) -> tree ()
+ Control.CP.FD.FD: (@>=) :: ((FDConstraint s) ~ (Constraint (TreeSolver tree)), MonadTree tree, Eq (FDTerm s), Show (FDTerm s)) => Expr (FDTerm s) -> Expr (FDTerm s) -> tree ()
+ Control.CP.FD.FD: AllDiff :: [Expr (FDTerm s)] -> FDConstraint s
+ Control.CP.FD.FD: Diff :: (Expr (FDTerm s)) -> (Expr (FDTerm s)) -> FDConstraint s
+ Control.CP.FD.FD: Dom :: (Expr (FDTerm s)) -> Integer -> Integer -> FDConstraint s
+ Control.CP.FD.FD: FDLabel :: (Label s) -> FDLabel s
+ Control.CP.FD.FD: FDWrapper :: s a -> FDWrapper s a
+ Control.CP.FD.FD: Less :: (Expr (FDTerm s)) -> (Expr (FDTerm s)) -> FDConstraint s
+ Control.CP.FD.FD: Same :: (Expr (FDTerm s)) -> (Expr (FDTerm s)) -> FDConstraint s
+ Control.CP.FD.FD: Sorted :: [Expr (FDTerm s)] -> Bool -> FDConstraint s
+ Control.CP.FD.FD: allDiff :: ((FDConstraint s) ~ (Constraint (TreeSolver tree)), MonadTree tree, Show (FDTerm s)) => [Expr (FDTerm s)] -> tree ()
+ Control.CP.FD.FD: allin :: ((FDConstraint s) ~ (Constraint (TreeSolver tree)), MonadTree tree, Integral t, Integral t1, Show (FDTerm s)) => [Expr (FDTerm s)] -> (t, t1) -> tree ()
+ Control.CP.FD.FD: class (Show (FDTerm s), Eq (FDTerm s), Term s (FDTerm s)) => FDSolver s where { type family FDTerm s :: *; { specific_fresh_var = mixinId specific_decompose = mixinId } }
+ Control.CP.FD.FD: compile_constraint :: (FDSolver s) => FDConstraint s -> Tree s Bool
+ Control.CP.FD.FD: cte :: (Num a, Integral a1) => a1 -> a
+ Control.CP.FD.FD: data (Show (FDTerm s)) => FDConstraint s
+ Control.CP.FD.FD: decompose :: (FDSolver s) => Expr (FDTerm s) -> Tree s (FDTerm s)
+ Control.CP.FD.FD: fresh_var :: (FDSolver s) => Tree s (FDTerm s)
+ Control.CP.FD.FD: instance (FDSolver s) => Monad (FDWrapper s)
+ Control.CP.FD.FD: instance (FDSolver s) => Solver (FDWrapper s)
+ Control.CP.FD.FD: instance (FDTerm s ~ t, FDSolver s, Eq t, EnumTerm s t, Integral (TermDomain s t)) => EnumTerm (FDWrapper s) (Expr t)
+ Control.CP.FD.FD: instance (Show (FDTerm s)) => Show (FDConstraint s)
+ Control.CP.FD.FD: instance (t ~ Expr (FDTerm s), FDSolver s) => Term (FDWrapper s) t
+ Control.CP.FD.FD: newtype FDLabel s
+ Control.CP.FD.FD: newtype FDWrapper s a
+ Control.CP.FD.FD: sSorted :: ((FDConstraint s) ~ (Constraint (TreeSolver tree)), MonadTree tree, Show (FDTerm s)) => [Expr (FDTerm s)] -> tree ()
+ Control.CP.FD.FD: sorted :: ((FDConstraint s) ~ (Constraint (TreeSolver tree)), MonadTree tree, Show (FDTerm s)) => [Expr (FDTerm s)] -> tree ()
+ Control.CP.FD.FD: specific_compile_constraint :: (FDSolver s) => Mixin (FDConstraint s -> Tree s Bool)
+ Control.CP.FD.FD: specific_decompose :: (FDSolver s) => Mixin (Expr (FDTerm s) -> Tree s (FDTerm s))
+ Control.CP.FD.FD: specific_fresh_var :: (FDSolver s) => Mixin (Tree s (FDTerm s))
+ Control.CP.FD.FD: subFD :: FDWrapper s a -> s a
+ Control.CP.FD.FD: type FDExpr s = Expr (FDTerm s)
+ Control.CP.FD.FD: type FDTree s a = Tree (FDWrapper s) a
+ Control.CP.FD.FD: unwrap :: (FDSolver s) => Tree (FDWrapper s) a -> Tree s a
+ Control.CP.FD.FD: wrap :: (FDSolver s) => Tree s a -> Tree (FDWrapper s) a
+ Control.CP.FD.Gecode.CodegenSolver: CodegenSolver :: State Store a -> CodegenSolver a
+ Control.CP.FD.Gecode.CodegenSolver: SNIntl :: StoreNode -> StoreNode -> StoreNodeType
+ Control.CP.FD.Gecode.CodegenSolver: SNLeaf :: StoreNodeType
+ Control.CP.FD.Gecode.CodegenSolver: Store :: Int -> [VarData] -> StoreNode -> [Bool] -> Map (ExprKey (FDTerm CodegenSolver)) Int -> Store
+ Control.CP.FD.Gecode.CodegenSolver: StoreNode :: [GConstraint] -> [VarBoundPropagator] -> [Int] -> StoreNodeType -> StoreNode
+ Control.CP.FD.Gecode.CodegenSolver: VarBound :: VarId -> LowerBound -> UpperBound -> VarBound
+ Control.CP.FD.Gecode.CodegenSolver: cexpr :: Store -> Map (ExprKey (FDTerm CodegenSolver)) Int
+ Control.CP.FD.Gecode.CodegenSolver: compile :: Tree CodegenSolver a -> Store
+ Control.CP.FD.Gecode.CodegenSolver: cons :: StoreNode -> [GConstraint]
+ Control.CP.FD.Gecode.CodegenSolver: cpath :: Store -> [Bool]
+ Control.CP.FD.Gecode.CodegenSolver: ctree :: Store -> StoreNode
+ Control.CP.FD.Gecode.CodegenSolver: data Store
+ Control.CP.FD.Gecode.CodegenSolver: data StoreNode
+ Control.CP.FD.Gecode.CodegenSolver: data StoreNodeType
+ Control.CP.FD.Gecode.CodegenSolver: data VarBound
+ Control.CP.FD.Gecode.CodegenSolver: dis :: StoreNode -> StoreNodeType
+ Control.CP.FD.Gecode.CodegenSolver: getAllBounds :: Store -> VarBoundMap
+ Control.CP.FD.Gecode.CodegenSolver: getVarType :: Store -> Int -> GType
+ Control.CP.FD.Gecode.CodegenSolver: instance Eq VarBound
+ Control.CP.FD.Gecode.CodegenSolver: instance FDSolver CodegenSolver
+ Control.CP.FD.Gecode.CodegenSolver: instance GecodeSolver CodegenSolver
+ Control.CP.FD.Gecode.CodegenSolver: instance Monad CodegenSolver
+ Control.CP.FD.Gecode.CodegenSolver: instance MonadState Store CodegenSolver
+ Control.CP.FD.Gecode.CodegenSolver: instance Show Store
+ Control.CP.FD.Gecode.CodegenSolver: instance Show StoreNode
+ Control.CP.FD.Gecode.CodegenSolver: instance Show StoreNodeType
+ Control.CP.FD.Gecode.CodegenSolver: instance Show VarBound
+ Control.CP.FD.Gecode.CodegenSolver: instance Show VarData
+ Control.CP.FD.Gecode.CodegenSolver: instance Solver CodegenSolver
+ Control.CP.FD.Gecode.CodegenSolver: instance Term CodegenSolver BoolTerm
+ Control.CP.FD.Gecode.CodegenSolver: instance Term CodegenSolver IntTerm
+ Control.CP.FD.Gecode.CodegenSolver: isVarImplicit :: Store -> Int -> Bool
+ Control.CP.FD.Gecode.CodegenSolver: lbound :: VarBound -> LowerBound
+ Control.CP.FD.Gecode.CodegenSolver: nbounds :: StoreNode -> [VarBoundPropagator]
+ Control.CP.FD.Gecode.CodegenSolver: newtype CodegenSolver a
+ Control.CP.FD.Gecode.CodegenSolver: nvars :: StoreNode -> [Int]
+ Control.CP.FD.Gecode.CodegenSolver: state :: CodegenSolver a -> State Store a
+ Control.CP.FD.Gecode.CodegenSolver: ubound :: VarBound -> UpperBound
+ Control.CP.FD.Gecode.CodegenSolver: vardata :: Store -> [VarData]
+ Control.CP.FD.Gecode.CodegenSolver: varid :: VarBound -> VarId
+ Control.CP.FD.Gecode.CodegenSolver: vars :: Store -> Int
+ Control.CP.FD.Gecode.Common: BoolConst :: Bool -> BoolTerm
+ Control.CP.FD.Gecode.Common: BoolVar :: Int -> BoolTerm
+ Control.CP.FD.Gecode.Common: CAbs :: IntTerm -> IntTerm -> GConstraint
+ Control.CP.FD.Gecode.Common: CAllDiff :: [IntTerm] -> GConstraint
+ Control.CP.FD.Gecode.Common: CDiff :: t -> t -> GConstraint
+ Control.CP.FD.Gecode.Common: CDiv :: IntTerm -> IntTerm -> IntTerm -> GConstraint
+ Control.CP.FD.Gecode.Common: CDom :: IntTerm -> Integer -> Integer -> GConstraint
+ Control.CP.FD.Gecode.Common: CLinear :: [(IntTerm, Integer)] -> GOperator -> Integer -> GConstraint
+ Control.CP.FD.Gecode.Common: CMod :: IntTerm -> IntTerm -> IntTerm -> GConstraint
+ Control.CP.FD.Gecode.Common: CMult :: IntTerm -> IntTerm -> IntTerm -> GConstraint
+ Control.CP.FD.Gecode.Common: CRel :: IntTerm -> GOperator -> IntTerm -> GConstraint
+ Control.CP.FD.Gecode.Common: CSame :: t -> t -> GConstraint
+ Control.CP.FD.Gecode.Common: CSorted :: [IntTerm] -> Bool -> GConstraint
+ Control.CP.FD.Gecode.Common: CValue :: IntTerm -> Integer -> GConstraint
+ Control.CP.FD.Gecode.Common: IntConst :: Integer -> IntTerm
+ Control.CP.FD.Gecode.Common: IntVar :: Int -> IntTerm
+ Control.CP.FD.Gecode.Common: ODiff :: GOperator
+ Control.CP.FD.Gecode.Common: OEqual :: GOperator
+ Control.CP.FD.Gecode.Common: OLess :: GOperator
+ Control.CP.FD.Gecode.Common: TypeBool :: GType
+ Control.CP.FD.Gecode.Common: TypeInt :: GType
+ Control.CP.FD.Gecode.Common: basicCompile :: (FDSolver s, (Constraint s) ~ GConstraint, (FDTerm s) ~ IntTerm) => Mixin (FDConstraint s -> Tree s Bool)
+ Control.CP.FD.Gecode.Common: caching_decompose :: (GecodeSolver s, GecodeSolver s) => Mixin (Expr (FDTerm s) -> Tree s IntTerm)
+ Control.CP.FD.Gecode.Common: class GTerm t
+ Control.CP.FD.Gecode.Common: class (Solver s, Term s IntTerm) => GecodeSolver s
+ Control.CP.FD.Gecode.Common: data BoolTerm
+ Control.CP.FD.Gecode.Common: data GConstraint
+ Control.CP.FD.Gecode.Common: data GOperator
+ Control.CP.FD.Gecode.Common: data GType
+ Control.CP.FD.Gecode.Common: data IntTerm
+ Control.CP.FD.Gecode.Common: getDefBounds :: (GTerm t) => t -> (Integer, Integer)
+ Control.CP.FD.Gecode.Common: getIntValue :: (GTerm t) => t -> Maybe Integer
+ Control.CP.FD.Gecode.Common: getVarId :: (GTerm t) => t -> Maybe Int
+ Control.CP.FD.Gecode.Common: instance Eq BoolTerm
+ Control.CP.FD.Gecode.Common: instance Eq GType
+ Control.CP.FD.Gecode.Common: instance Eq IntTerm
+ Control.CP.FD.Gecode.Common: instance GTerm BoolTerm
+ Control.CP.FD.Gecode.Common: instance GTerm IntTerm
+ Control.CP.FD.Gecode.Common: instance Ord IntTerm
+ Control.CP.FD.Gecode.Common: instance Show BoolTerm
+ Control.CP.FD.Gecode.Common: instance Show GConstraint
+ Control.CP.FD.Gecode.Common: instance Show GOperator
+ Control.CP.FD.Gecode.Common: instance Show GType
+ Control.CP.FD.Gecode.Common: instance Show IntTerm
+ Control.CP.FD.Gecode.Common: linearCompile :: (FDSolver s, (Constraint s) ~ GConstraint, (FDTerm s) ~ IntTerm) => Mixin (FDConstraint s -> Tree s Bool)
+ Control.CP.FD.Gecode.Common: orElse :: Maybe a -> Maybe a -> Maybe a
+ Control.CP.FD.Gecode.Common: setVarImplicit :: (GecodeSolver s) => IntTerm -> Bool -> s ()
+ Control.CP.FD.Gecode.Translate: generate_gecode :: Tree CodegenSolver a -> String
+ Control.CP.FD.OvertonFD.OvertonFD: OAbs :: FDVar -> FDVar -> OConstraint
+ Control.CP.FD.OvertonFD.OvertonFD: OAdd :: FDVar -> FDVar -> FDVar -> OConstraint
+ Control.CP.FD.OvertonFD.OvertonFD: ODiff :: FDVar -> FDVar -> OConstraint
+ Control.CP.FD.OvertonFD.OvertonFD: OHasValue :: FDVar -> Int -> OConstraint
+ Control.CP.FD.OvertonFD.OvertonFD: OLess :: FDVar -> FDVar -> OConstraint
+ Control.CP.FD.OvertonFD.OvertonFD: OMult :: FDVar -> FDVar -> FDVar -> OConstraint
+ Control.CP.FD.OvertonFD.OvertonFD: OSame :: FDVar -> FDVar -> OConstraint
+ Control.CP.FD.OvertonFD.OvertonFD: OSub :: FDVar -> FDVar -> FDVar -> OConstraint
+ Control.CP.FD.OvertonFD.OvertonFD: data FDVar
+ Control.CP.FD.OvertonFD.OvertonFD: data OConstraint
+ Control.CP.FD.OvertonFD.OvertonFD: data OvertonFD a
+ Control.CP.FD.OvertonFD.OvertonFD: fd_domain :: FDVar -> OvertonFD [Int]
+ Control.CP.FD.OvertonFD.OvertonFD: fd_objective :: OvertonFD FDVar
+ Control.CP.FD.OvertonFD.OvertonFD: instance EnumTerm OvertonFD FDVar
+ Control.CP.FD.OvertonFD.OvertonFD: instance Eq FDState
+ Control.CP.FD.OvertonFD.OvertonFD: instance Eq FDVar
+ Control.CP.FD.OvertonFD.OvertonFD: instance Monad OvertonFD
+ Control.CP.FD.OvertonFD.OvertonFD: instance MonadPlus OvertonFD
+ Control.CP.FD.OvertonFD.OvertonFD: instance MonadState FDState OvertonFD
+ Control.CP.FD.OvertonFD.OvertonFD: instance Ord FDState
+ Control.CP.FD.OvertonFD.OvertonFD: instance Ord FDVar
+ Control.CP.FD.OvertonFD.OvertonFD: instance Show FDState
+ Control.CP.FD.OvertonFD.OvertonFD: instance Show FDVar
+ Control.CP.FD.OvertonFD.OvertonFD: instance Show VarInfo
+ Control.CP.FD.OvertonFD.OvertonFD: instance Solver OvertonFD
+ Control.CP.FD.OvertonFD.OvertonFD: instance Term OvertonFD FDVar
+ Control.CP.FD.OvertonFD.Sugar: instance FDSolver OvertonFD
+ Control.CP.FD.OvertonFD.Sugar: newBound :: NewBound OvertonFD
+ Control.CP.FD.OvertonFD.Sugar: newBoundBis :: NewBound OvertonFD
+ Control.CP.FD.OvertonFD.Sugar: restart :: (Queue q, Solver solver, CTransformer c, (CForSolver c) ~ solver, (Elem q) ~ (Label solver, Tree solver (CForResult c), CTreeState c)) => q -> [c] -> Tree solver (CForResult c) -> (Int, [CForResult c])
+ Control.CP.FD.OvertonFD.Sugar: restartOpt :: (Queue q, CTransformer c, (CForSolver c) ~ OvertonFD, (Elem q) ~ (Label OvertonFD, Tree OvertonFD (CForResult c), CTreeState c)) => q -> [c] -> Tree OvertonFD (CForResult c) -> (Int, [CForResult c])
+ Control.CP.FD.Solvers: as_gecode_codegen :: Tree (FDWrapper CodegenSolver) a -> Tree CodegenSolver a
+ Control.CP.FD.Solvers: as_overtonfd :: Tree (FDWrapper OvertonFD) a -> Tree (FDWrapper OvertonFD) a
+ Control.CP.FD.Solvers: bb :: NewBound s -> CBranchBoundST s a
+ Control.CP.FD.Solvers: db :: Int -> CDepthBoundedST s a
+ Control.CP.FD.Solvers: fs :: CFirstSolutionST s a
+ Control.CP.FD.Solvers: it :: CIdentityCST s a
+ Control.CP.FD.Solvers: ld :: Int -> CLimitedDiscrepancyST s a
+ Control.CP.FD.Solvers: nb :: Int -> CNodeBoundedST s a
+ Control.CP.FD.Solvers: pfs :: (Ord a) => PriorityQueue a (a, b, c)
+ Control.CP.FD.Solvers: ra :: Int -> CRandomST s a
+ Control.CP.Mixin: (<@>) :: Mixin a -> Mixin a -> Mixin a
+ Control.CP.Mixin: mixin :: Mixin a -> a
+ Control.CP.Mixin: mixinConst :: a -> a -> a -> a
+ Control.CP.Mixin: mixinId :: Mixin a
+ Control.CP.Mixin: type Mixin a = a -> a -> a
+ Control.CP.SearchTree: addC :: (MonadTree tree) => Constraint (TreeSolver tree) -> tree ()
+ Control.CP.SearchTree: addT :: (MonadTree tree) => Constraint (TreeSolver tree) -> tree Bool
+ Control.CP.SearchTree: indent :: Int -> String
+ Control.CP.SearchTree: showTree :: (Show (Constraint s), Show a, Solver s) => Int -> Tree s a -> s String
+ Control.CP.SearchTree: transformTree :: (Solver s) => Mixin (Tree s a -> Tree s a)
+ Control.CP.SearchTree: untree :: (Solver s) => v -> Tree s v -> s v
+ Control.CP.Solver: help :: (Term solver term) => solver () -> term -> Help solver term
+ Control.CP.Transformers: data DepthBoundedST solver :: (* -> *) a
+ Control.CP.Transformers: data NodeBoundedST solver :: (* -> *) a
- Control.CP.ComposableTransformers: class (Solver (CForSolver c)) => CTransformer c where { type family CEvalState c :: *; type family CTreeState c :: *; type family CForSolver c :: * -> *; type family CForResult c :: *; { completeCT _ _ = True returnCT = continueCT nextCT = evalCT rightCT = leftCT leftCT _ = id } }
+ Control.CP.ComposableTransformers: class (Solver (CForSolver c)) => CTransformer c where { type family CTreeState c :: *; type family CForSolver c :: * -> *; type family CForResult c :: *; { completeCT _ _ = True returnCT = continueCT nextCT = evalCT rightCT = leftCT leftCT _ = id } }
- Control.CP.SearchTree: class (Monad m, Solver (TreeSolver m)) => MonadTree m where { type family TreeSolver m :: * -> *; }
+ Control.CP.SearchTree: class (Monad m, Solver (TreeSolver m)) => MonadTree m
- Control.CP.SearchTree: disj2 :: (Solver s) => [Tree s a] -> Tree s a
+ Control.CP.SearchTree: disj2 :: (MonadTree tree) => [tree a] -> tree a
- Control.CP.SearchTree: forall :: (Solver s, Term s t) => [t] -> (t -> Tree s ()) -> Tree s ()
+ Control.CP.SearchTree: forall :: (MonadTree tree, Term (TreeSolver tree) t) => [t] -> (t -> tree ()) -> tree ()
- Control.CP.Solver: class (Solver solver) => Term solver term
+ Control.CP.Solver: class (Solver solver) => Term solver term where { type family Help solver term; }
Files
- Control/CP/ComposableTransformers.hs +20/−3
- Control/CP/Debug.hs +13/−0
- Control/CP/EnumTerm.hs +102/−0
- Control/CP/FD/Domain.hs +0/−167
- Control/CP/FD/Example/Example.hs +44/−0
- Control/CP/FD/Expr.hs +236/−0
- Control/CP/FD/FD.hs +195/−362
- Control/CP/FD/FDSugar.hs +0/−129
- Control/CP/FD/Gecode/CodegenSolver.hs +476/−0
- Control/CP/FD/Gecode/Common.hs +277/−0
- Control/CP/FD/Gecode/Interface.hsc +173/−0
- Control/CP/FD/Gecode/RuntimeSolver.hs +291/−0
- Control/CP/FD/Gecode/Translate.hs +203/−0
- Control/CP/FD/OvertonFD/Domain.hs +176/−0
- Control/CP/FD/OvertonFD/OvertonFD.hs +384/−0
- Control/CP/FD/OvertonFD/Sugar.hs +116/−0
- Control/CP/FD/Solvers.hs +60/−0
- Control/CP/Herbrand/Herbrand.hs +17/−4
- Control/CP/Herbrand/HerbrandT.hs +4/−1
- Control/CP/Herbrand/Prolog.hs +2/−0
- Control/CP/Herbrand/PrologTerm.hs +3/−4
- Control/CP/Mixin.hs +24/−0
- Control/CP/Queue.hs +11/−2
- Control/CP/SearchTree.hs +117/−38
- Control/CP/Solver.hs +27/−5
- Control/CP/Transformers.hs +13/−4
- examples/AllInterval.hs +18/−0
- examples/Alpha.hs +61/−0
- examples/Grocery.hs +21/−0
- examples/MagicSquare.hs +31/−0
- examples/Olympic.hs +51/−0
- examples/Partition.hs +73/−0
- examples/Queens.hs +20/−0
- examples/Ring.hs +30/−0
- examples/StressDomain.hs +23/−0
- examples/TryDemo.hs +19/−0
- examples/Zebra.hs +39/−0
- lib/gecodeglue.cpp +380/−0
- monadiccp.cabal +41/−15
Control/CP/ComposableTransformers.hs view
@@ -3,18 +3,35 @@ - http://www.cs.kuleuven.be/~toms/Haskell/ - Tom Schrijvers -}-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE Rank2Types #-} {-# LANGUAGE GADTs #-}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ImpredicativeTypes #-} {-# LANGUAGE FlexibleContexts #-} -module Control.CP.ComposableTransformers where +module Control.CP.ComposableTransformers (+ solve, + NewBound, + CTransformer, + CForSolver, + CForResult, + CTreeState, + RestartST(..) , + SealedCST(..), + CNodeBoundedST(..), + CDepthBoundedST(..),+ CBranchBoundST(..),+ CFirstSolutionST(..),+ CIdentityCST(..),+ CRandomST(..),+ CLimitedDiscrepancyST(..)+) where import Control.CP.Transformers import Control.CP.SearchTree import Control.CP.Solver import Control.CP.Queue+import Control.CP.Debug import System.Random (mkStdGen, randoms)
+ Control/CP/Debug.hs view
@@ -0,0 +1,13 @@+{-# LANGUAGE CPP #-}++module Control.CP.Debug (+ debug+) where++import Debug.Trace++#ifdef DEBUG+debug = trace+#else+debug = flip const+#endif
+ Control/CP/EnumTerm.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TransformListComp #-}+{-# LANGUAGE FlexibleContexts #-}++module Control.CP.EnumTerm (+ EnumTerm,+ TermDomain,+ get_domain_size,+ get_value,+ split_domain_partial,+ split_domain,+ split_domains,+ in_order,+ firstfail,+ middleout,+ endsout,+ interleave,+ assignment,+ assignments,+ enumerate,+ label+) where++import GHC.Exts (sortWith)++import Data.List (splitAt)+import Control.CP.SearchTree hiding (label)+import Control.CP.Solver++--------------------------------------------------------------------------------+-- ENUMERATION+--------------------------------------------------------------------------------++class (Term s t, Enum (TermDomain s t)) => EnumTerm s t where+ type TermDomain s t :: *+ get_domain_size :: t -> s Int+ get_value :: t -> s (Maybe (TermDomain s t))+ split_domain_partial :: t -> s [Tree s ()]+ + split_domain :: t -> s (Tree s ())+ split_domain v = do+ let rec tree = do+ tree+ Label $ do+ x <- get_value v+ case x of+ Nothing -> split_domain v+ Just _ -> return $ return ()+ lst <- split_domain_partial v+ return $ levelList $ map rec lst+ + split_domains :: [t] -> s (Tree s ())+ split_domains [] = return $ return ()+ split_domains [a] = split_domain a+ split_domains (a:b) = do+ ta <- split_domain a+ tb <- split_domains b+ return $ ta /\ tb+ + label :: ([t] -> s [t]) -> [t] -> Tree s ()+ label o l = Label $ do+ x <- o l+ split_domains x+ + enumerate :: [t] -> Tree s ()+ enumerate l = label firstfail l++levelList :: Solver s => [Tree s ()] -> Tree s ()+levelList [] = Fail+levelList [a] = a+levelList l = + let len = length l+ (p1,p2) = splitAt (len `div` 2) l+ in Try (levelList p1) (levelList p2)+++in_order :: Monad m => a -> m a+in_order = return ++firstfail qs = do ds <- mapM get_domain_size qs + return [ q | (d,q) <- zip ds qs + , then sortWith by d ]++middleout l = let n = (length l) `div` 2 in+ interleave (drop n l) (reverse $ take n l)++endsout l = let n = (length l) `div` 2 in+ interleave (reverse $ drop n l) (take n l)++interleave [] ys = ys+interleave (x:xs) ys = x:interleave ys xs++--------------------------------------------------------------------------------+-- RESULT+--------------------------------------------------------------------------------++assignment :: EnumTerm s t => t -> Tree s (TermDomain s t)+assignment q = Label $ get_value q >>= \(Just x) -> return $ Return x++assignments :: EnumTerm s t => [t] -> Tree s [TermDomain s t]+assignments = mapM assignment
− Control/CP/FD/Domain.hs
@@ -1,167 +0,0 @@-{- - - Origin:- - Constraint Programming in Haskell - - http://overtond.blogspot.com/2008/07/pre.html- - author: David Overton, Melbourne Australia- -- - Modifications:- - Monadic Constraint Programming- - http://www.cs.kuleuven.be/~toms/Haskell/- - Tom Schrijvers- -} --{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE OverlappingInstances #-}-{-# LANGUAGE IncoherentInstances #-}-{-# LANGUAGE UndecidableInstances #-}-module Control.CP.FD.Domain (- Domain,- ToDomain,- toDomain,- member,- isSubsetOf,- elems,- intersection,- difference,- union,- empty,- null,- singleton,- isSingleton,- filterLessThan,- filterGreaterThan,- findMax,- findMin,- size,- shiftDomain-) where--import qualified Data.IntSet as IntSet-import Data.IntSet (IntSet)-import Prelude hiding (null)--data Domain- = Set IntSet- | Range Int Int- deriving Show--size :: Domain -> Int-size (Range l u) = u - l + 1-size (Set set) = IntSet.size set---- Domain constructors-class ToDomain a where- toDomain :: a -> Domain--instance ToDomain Domain where- toDomain = id--instance ToDomain IntSet where- toDomain = Set--instance Integral a => ToDomain [a] where- toDomain = toDomain . IntSet.fromList . map fromIntegral--instance (Integral a, Integral b) => ToDomain (a, b) where- toDomain (a, b) = Range (fromIntegral a) (fromIntegral b)--instance ToDomain () where- toDomain () = Range minBound maxBound--instance Integral a => ToDomain a where- toDomain a = toDomain (a, a)---- Operations on Domains-instance Eq Domain where- (Range xl xh) == (Range yl yh) = xl == yl && xh == yh- xs == ys = elems xs == elems ys--member :: Int -> Domain -> Bool-member n (Set xs) = n `IntSet.member` xs-member n (Range xl xh) = n >= xl && n <= xh--isSubsetOf :: Domain -> Domain -> Bool-isSubsetOf (Set xs) (Set ys) = xs `IntSet.isSubsetOf` ys-isSubsetOf (Range xl xh) (Range yl yh) = xl >= yl && xh <= yh-isSubsetOf (Set xs) yd@(Range yl yh) =- isSubsetOf (Range xl xh) yd where- xl = IntSet.findMin xs- xh = IntSet.findMax xs-isSubsetOf (Range xl xh) (Set ys) =- all (`IntSet.member` ys) [xl..xh]--elems :: Domain -> [Int]-elems (Set xs) = IntSet.elems xs-elems (Range xl xh) = [xl..xh]--intersection :: Domain -> Domain -> Domain-intersection (Set xs) (Set ys) = Set (xs `IntSet.intersection` ys)-intersection (Range xl xh) (Range yl yh) = Range (max xl yl) (min xh yh)-intersection (Set xs) (Range yl yh) =- Set $ IntSet.filter (\x -> x >= yl && x <= yh) xs-intersection x y = intersection y x--union :: Domain -> Domain -> Domain-union (Set xs) (Set ys) = Set (xs `IntSet.union` ys)-union (Range xl xh) (Range yl yh) - | xh + 1 >= yl || yh+1 >= xl = Range (min xl yl) (max xh yh)- | otherwise = union (Set $ IntSet.fromList [xl..xh]) - (Set $ IntSet.fromList [yl..yh]) -union x@(Set xs) y@(Range yl yh) =- if null x then y - else- let xmin = IntSet.findMin xs- xmax = IntSet.findMax xs- in - if (xmin + 1 >= yl && xmax - 1 <= yh) - then Range (min xmin yl) (max xmax yh)- else union (Set xs) (Set $ IntSet.fromList [yl..yh])-union x y = union y x--difference :: Domain -> Domain -> Domain-difference (Set xs) (Set ys) = Set (xs `IntSet.difference` ys)-difference xd@(Range xl xh) (Range yl yh)- | yl > xh || yh < xl = xd- | otherwise = Set $ IntSet.fromList [x | x <- [xl..xh], x < yl || x > yh]-difference (Set xs) (Range yl yh) =- Set $ IntSet.filter (\x -> x < yl || x > yh) xs-difference (Range xl xh) (Set ys)- | IntSet.findMin ys > xh || IntSet.findMax ys < xl = Range xl xh- | otherwise = Set $- IntSet.fromList [x | x <- [xl..xh], not (x `IntSet.member` ys)]--null :: Domain -> Bool-null (Set xs) = IntSet.null xs-null (Range xl xh) = xl > xh--singleton :: Int -> Domain-singleton x = Set (IntSet.singleton x)--isSingleton :: Domain -> Bool-isSingleton (Set xs) = case IntSet.elems xs of- [x] -> True- _ -> False-isSingleton (Range xl xh) = xl == xh--filterLessThan :: Int -> Domain -> Domain-filterLessThan n (Set xs) = Set $ IntSet.filter (< n) xs-filterLessThan n (Range xl xh) = Range xl (min (n-1) xh)--filterGreaterThan :: Int -> Domain -> Domain-filterGreaterThan n (Set xs) = Set $ IntSet.filter (> n) xs-filterGreaterThan n (Range xl xh) = Range (max (n+1) xl) xh--findMax :: Domain -> Int-findMax (Set xs) = IntSet.findMax xs-findMax (Range xl xh) = xh--findMin :: Domain -> Int-findMin (Set xs) = IntSet.findMin xs-findMin (Range xl xh) = xl--empty :: Domain-empty = Range 1 0--shiftDomain :: Domain -> Int -> Domain-shiftDomain (Range l u) d = Range (l + d) (u + d)-shiftDomain (Set xs) d = Set $ IntSet.fromList $ map (+d) (IntSet.elems xs)
+ Control/CP/FD/Example/Example.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE CPP #-}++module Control.CP.FD.Example.Example (+ example_main,+ example_main_void,+ example_main_single,+ FDModel+) where+++import System (getArgs)++import Control.CP.ComposableTransformers+import Control.CP.FD.Gecode.Translate+import Control.CP.FD.Solvers+import Control.CP.FD.FD+import Control.CP.EnumTerm+import Control.CP.SearchTree hiding (label)++#ifdef RGECODE+import Control.CP.FD.Gecode.RuntimeSolver+#endif++example_main :: (forall s. FDSolver s => [String] -> FDTree s [FDExpr s]) -> IO ()+example_main f = do+ args <- getArgs+ case args of+ ("gecode_compile":r) -> putStr $ generate_gecode $ as_gecode_codegen $ f r+#ifdef RGECODE+ ("gecode_run":r) -> print $ solve dfs fs $ as_gecode_runtime $ f r >>= \l -> enumerate l /\ assignments l+ ("gecode_search":r) -> print $ solve dfs fs $ as_gecode_search $ f r >>= \l -> enumerate l /\ assignments l+#endif+ ("overton_run":r) -> print $ solve dfs fs $ as_overtonfd $ f r >>= \l -> enumerate l /\ assignments l+ [] -> putStr "Solver type required\n"+ (a:r) -> putStr ("Unsupported solver: " ++ a ++ "\n")++example_main_void :: (forall s. FDSolver s => FDTree s [FDExpr s]) -> IO ()+example_main_void f = example_main (const f)++example_main_single :: Read n => (forall s. FDSolver s => n -> FDTree s [FDExpr s]) -> IO ()+example_main_single f = example_main (f . read . head)++type FDModel = FDSolver s => Tree (FDWrapper s) [FDExpr s]
+ Control/CP/FD/Expr.hs view
@@ -0,0 +1,236 @@+{- + - Monadic Constraint Programming+ - http://www.cs.kuleuven.be/~toms/Haskell/+ - Tom Schrijvers & Pieter Wuille+ -}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Control.CP.FD.Expr (+ Expr(..),+ ToExpr(..),+ ExprKey(..),+ unExprKey+) where ++import GHC.Exts (sortWith)+import qualified Control.CP.PriorityQueue as PriorityQueue+import qualified Data.Sequence++import Control.CP.SearchTree hiding (label)+import Control.CP.Transformers+import Control.CP.ComposableTransformers+import Control.CP.Queue+import Control.CP.Solver+import Control.CP.EnumTerm+import Control.CP.Debug+import Control.CP.Mixin++-- some simple kinds of expressions+data Expr t =+ Term t+ | Const Integer+ | Plus (Expr t) (Expr t)+ | Minus (Expr t) (Expr t)+ | Mult (Expr t) (Expr t)+ | Div (Expr t) (Expr t)+ | Mod (Expr t) (Expr t)+ | Abs (Expr t)+ deriving (Show,Eq)++varrefs :: forall s. Expr s -> Int+varrefs (Term _) = 1+varrefs (Const _) = 0+varrefs (Plus a b) = varrefs a + varrefs b+varrefs (Minus a b) = varrefs a + varrefs b+varrefs (Mult a b) = varrefs a + varrefs b+varrefs (Div a b) = varrefs a + varrefs b+varrefs (Mod a b) = varrefs a + varrefs b+varrefs (Abs a) = varrefs a++simplify :: (Eq s, Show s) => Expr s -> Expr s+-- simplification rules (either decrease # of variable references, or leave that equal and decrease # of tree nodes)+--- level 0 (result in a final expression)+simplify (Mult (Const 0) _) = Const 0+simplify (Div (Const 0) _) = Const 0+simplify (Mod (Const 0) _) = Const 0+simplify (Mod _ (Const 1)) = Const 0+simplify (Mod _ (Const (-1))) = Const 0+simplify (Mod (Mult (Const a) b) (Const c)) | (a `mod` c)==0 = Const 0+simplify (Minus a b) | a==b = Const 0+simplify (Plus (Const a) (Const b)) = Const (a+b)+simplify (Minus (Const a) (Const b)) = Const (a-b)+simplify (Mult (Const a) (Const b)) = Const (a*b)+simplify (Div (Const a) (Const b)) = Const $ (a `div` b)+simplify (Abs (Const a)) = Const (abs a)+simplify (Mod (Const a) (Const b)) = Const $ (a `div` b)+simplify (Plus (Const 0) a) = a+simplify (Mult (Const 1) a) = a+simplify (Div a (Const 1)) = a+--- level 1 (result in one recursive call to simplify)+simplify (Plus a b) | a==b = 2 * a+simplify (Div a (Const (-1))) = negate a+simplify (Plus (Const c) (Plus (Const a) b)) = (Const $ c+a) + b+simplify (Plus (Const c) (Minus (Const a) b)) = (Const $ c+a) - b+simplify (Minus (Const c) (Plus (Const a) b)) = (Const $ c-a) - b+simplify (Minus (Const c) (Minus (Const a) b)) = (Const $ c-a) + b+simplify (Mult (Const c) (Mult (Const a) b)) = (Const $ a*c) * b+simplify (Div (Mult (Const a) b) (Const c)) | (a `mod` c)==0 = (Const (a `div` c)) * b+--- level 2 (result in two recursive calls to simplify)+simplify (Plus a (Mult b c)) | a==b && ((varrefs a)>0) = (c+1) * a+simplify (Plus a (Mult b c)) | a==c && ((varrefs a)>0) = (b+1) * a+simplify (Plus (Mult b c) a) | a==b && ((varrefs a)>0) = (c+1) * a+simplify (Plus (Mult b c) a) | a==c && ((varrefs a)>0) = (b+1) * a+simplify (Plus (Mult a b) (Mult c d)) | a==c = (b+d) * a+simplify (Plus (Mult a b) (Mult c d)) | a==d = (b+c) * a+simplify (Plus (Mult a b) (Mult c d)) | b==c = (a+d) * b+simplify (Plus (Mult a b) (Mult c d)) | b==d = (a+c) * b+simplify (Minus a (Mult b c)) | a==b && ((varrefs a)>0) = (1-c) * a+simplify (Minus a (Mult b c)) | a==c && ((varrefs a)>0) = (1-b) * a+simplify (Minus (Mult b c) a) | a==b && ((varrefs a)>0) = (c-1) * a+simplify (Minus (Mult b c) a) | a==c && ((varrefs a)>0) = (b-1) * a+simplify (Minus (Mult a b) (Mult c d)) | a==c = (b-d) * a+simplify (Minus (Mult a b) (Mult c d)) | a==d = (b-c) * a+simplify (Minus (Mult a b) (Mult c d)) | b==c = (a-d) * b+simplify (Minus (Mult a b) (Mult c d)) | b==d = (a-c) * b+simplify (Mult (Abs a) (Abs b)) = abs (a*b)+simplify (Div (Abs a) (Abs b)) = abs (a `div` b)+-- reordering rules (do not decrease # of variables or # of tree nodes, but normalize an expression in such a way that the same normalization cannot be applied anymore - possibly because that can only occur in a case already matched by a simplification rule above)+--- level 1+simplify (Plus a (Const c)) = (Const c) + a+simplify (Minus a (Const c)) = (Const (-c)) + a+simplify (Mult a (Const c)) = (Const c) * a+simplify (Mult (Const (-1)) a) = negate a+--- level 2+simplify (Mult (Const c) (Plus (Const a) b)) = (Const (a*c)) + ((Const c)*b)+simplify (Mult (Const c) (Minus (Const a) b)) = (Const (a*c)) - ((Const c)*b)+simplify (Plus a (Plus (Const b) c)) = (Const b) + (a+c)+simplify (Plus a (Minus (Const b) c)) = (Const b) + (a-c)+simplify (Minus a (Plus (Const b) c)) = (Const (-b)) + (a-c)+simplify (Minus a (Minus (Const b) c)) = (Const (-b)) + (a+c)+simplify (Mult a (Mult (Const b) c)) = (Const b) * (a*c)+simplify (Plus (Plus (Const a) b) c) = (Const a) + (b+c)+simplify (Plus (Minus (Const a) b) c) = (Const a) + (c-b)+simplify (Minus (Plus (Const a) b) c) = (Const a) + (b-c)+simplify (Minus (Minus (Const a) b) c) = (Const a) - (b+c)+simplify (Mult (Mult (Const a) b) c) = (Const a) * (b*c)+simplify (Mult a (Minus (Const 0) b)) = negate (a*b)+simplify (Mult (Minus (Const 0) b) a) = negate (a*b)+simplify (Div (Minus (Const 0) a) b) = negate $ a `div` b+simplify (Div a (Minus (Const 0) b)) = negate $ a `div` b+-- fallback rule+simplify a = a++instance (Eq s, Show s) => Num (Expr s) where+ a + b = simplify $ Plus a b+ a - b = simplify $ Minus a b+ a * b = simplify $ Mult a b+ abs a = simplify $ Abs a+ negate a = 0 - a+ fromInteger c = Const $ fromInteger c+ signum (Const a) = Const (signum a)+ signum a = error "signum not possible for generic Expr"++instance (Eq s, Show s) => Ord (Expr s) where+ compare (Const x) (Const y) = compare x y+ compare _ _ = error "compare not possible for generic Expr"++instance (Eq s, Show s) => Real (Expr s) where+ toRational (Const x) = toRational x+ toRational _ = error "toRational not possible for generic Expr"++instance (Eq s, Show s) => Enum (Expr s) where+ succ a = a + 1+ pred a = a - 1+ toEnum = Const . toEnum+ fromEnum (Const a) = fromEnum a+ fromEnum _ = error "fromEnum not possible for generic Expr"++instance (Eq s, Show s) => Integral (Expr s) where+ toInteger (Const a) = toInteger a+ toInteger _ = error "toInteger not possible for generic Expr"+ divMod a b = (simplify $ Div a b, simplify $ Mod a b)+ quotRem (Const a) (Const b) = case quotRem a b of (c,d) -> (Const c,Const d)+ quotRem (Const 0) b = (Const 0,Const 0)+ quotRem a (Const 1) = (a,Const 0)+ quotRem a (Const (-1)) = (negate a,Const 0)+ quotRem _ _ = error "quotRem not possible for generic Expr"++-- a class of types convertible to expressions+class ToExpr tt t where+ toExpr :: t -> Expr tt++-- integers can be used as constant expressions+instance ToExpr tt Integer where+ toExpr = Const++-- ints can be used as constant expressions+instance ToExpr tt Int where+ toExpr = Const . toInteger++-- expressions themselves are trivially convertible to expressions+instance ToExpr t (Expr t) where+ toExpr = id++-- the terms used by the solver can be used as expressions referring+-- to a variable+instance ToExpr t t where+ toExpr = Term++--------------------------------------------------------------------------------+-- ExprKey+--------------------------------------------------------------------------------++newtype ExprKey s = ExprKey (Expr s)+ deriving (Eq, Show)++unExprKey :: ExprKey s -> Expr s+unExprKey (ExprKey x) = x++instance Ord s => Ord (ExprKey s) where+ -- consts+ compare (ExprKey (Const i1)) (ExprKey (Const i2)) = compare i1 i2+ compare (ExprKey (Const _)) _ = LT+ compare _ (ExprKey (Const _)) = GT+ -- abs+ compare (ExprKey (Abs i1)) (ExprKey (Abs i2)) = compare (ExprKey i1) (ExprKey i2)+ compare (ExprKey (Abs _)) _ = LT+ compare _ (ExprKey (Abs _)) = GT+ -- plus+ compare (ExprKey (Plus a1 a2)) (ExprKey (Plus b1 b2)) = case (compare (ExprKey a1) (ExprKey b1)) of+ LT -> LT+ GT -> GT+ EQ -> compare (ExprKey a2) (ExprKey b2)+ compare (ExprKey (Plus _ _)) _ = LT+ compare _ (ExprKey (Plus _ _)) = GT+ -- minus+ compare (ExprKey (Minus a1 a2)) (ExprKey (Minus b1 b2)) = case (compare (ExprKey a1) (ExprKey b1)) of+ LT -> LT+ GT -> GT+ EQ -> compare (ExprKey a2) (ExprKey b2)+ compare (ExprKey (Minus _ _)) _ = LT+ compare _ (ExprKey (Minus _ _)) = GT+ -- mult+ compare (ExprKey (Mult a1 a2)) (ExprKey (Mult b1 b2)) = case (compare (ExprKey a1) (ExprKey b1)) of+ LT -> LT+ GT -> GT+ EQ -> compare (ExprKey a2) (ExprKey b2)+ compare (ExprKey (Mult _ _)) _ = LT+ compare _ (ExprKey (Mult _ _)) = GT+ -- div+ compare (ExprKey (Div a1 a2)) (ExprKey (Div b1 b2)) = case (compare (ExprKey a1) (ExprKey b1)) of+ LT -> LT+ GT -> GT+ EQ -> compare (ExprKey a2) (ExprKey b2)+ compare (ExprKey (Div _ _)) _ = LT+ compare _ (ExprKey (Div _ _)) = GT+ -- mod+ compare (ExprKey (Mod a1 a2)) (ExprKey (Mod b1 b2)) = case (compare (ExprKey a1) (ExprKey b1)) of+ LT -> LT+ GT -> GT+ EQ -> compare (ExprKey a2) (ExprKey b2)+ compare (ExprKey (Mod _ _)) _ = LT+ compare _ (ExprKey (Mod _ _)) = GT+ -- variables+ compare (ExprKey (Term v1)) (ExprKey (Term v2)) = compare v1 v2
Control/CP/FD/FD.hs view
@@ -1,411 +1,244 @@ {- - - Origin:- - Constraint Programming in Haskell - - http://overtond.blogspot.com/2008/07/pre.html- - author: David Overton, Melbourne Australia- -- - Modifications: - Monadic Constraint Programming - http://www.cs.kuleuven.be/~toms/Haskell/- - Tom Schrijvers- -} --{-# OPTIONS_GHC -fglasgow-exts #-}+ - Tom Schrijvers & Pieter Wuille+ -}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE OverlappingInstances #-}--module Control.CP.FD.FD where +{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-} -import Prelude hiding (lookup)-import Maybe (fromJust,isJust)-import Control.Monad.State.Lazy-import Control.Monad.Trans-import qualified Data.Map as Map-import Data.Map ((!), Map)-import Control.Monad (liftM,(<=<))+module Control.CP.FD.FD (+ FDSolver(..),+ fresh_var,+ decompose,+ compile_constraint,+ FDExpr,+ FDConstraint(..),+ FDWrapper(..),+ FDTree,+ FDLabel(..),+ wrap,+ unwrap,+ (@:), (@<), (@>), (@<=), (@>=), (@=), (@/=),+ (@+), (@-), (@*), (@/), (@%), + cte,+ allDiff,+ sorted,+ sSorted,+ allin+)where -import Control.CP.FD.Domain as Domain+import GHC.Exts (sortWith) +import Control.CP.SearchTree hiding (label)+import Control.CP.Transformers+import Control.CP.ComposableTransformers+import Control.CP.Queue import Control.CP.Solver+import Control.CP.EnumTerm+import Control.CP.Debug+import Control.CP.Mixin+import Control.CP.FD.Expr --- import Debug.Trace-trace = flip const ----------------------------------------------------------------------------------- Solver instance -------------------------------------------------------------+-- SYNTACTIC SUGAR -------------------------------------------------------------------------------- -instance Solver FD where- type Constraint FD = FD_Constraint- type Label FD = FDState- add = addFD- run p = runFD p- mark = get- goto = put +-- define class FDSolver, instances of which must define a compile_constraint+-- function, to convert a constraint specified in syntactic sugar to a +-- corresponding search Tree. Instances must furthermore specify a+-- FDTerm x type, referring to the type of terms used+class (Show (FDTerm s), Eq (FDTerm s), Term s (FDTerm s)) => FDSolver s where+ -- types+ type FDTerm s :: *+ -- functions+ specific_compile_constraint :: Mixin (FDConstraint s -> Tree s Bool)+ specific_decompose :: Mixin (Expr (FDTerm s) -> Tree s (FDTerm s))+ specific_fresh_var :: Mixin (Tree s (FDTerm s))+ -- default implementations+ specific_decompose = mixinId+ specific_fresh_var = mixinId -instance Term FD FD_Term where- newvar = newVar () >>= return . FD_Var +-- compile constraint + defaults+compile_constraint :: FDSolver s => FDConstraint s -> Tree s Bool+compile_constraint = mixin (specific_compile_constraint <@> default_compile_constraint)+default_compile_constraint :: FDSolver so => Mixin (FDConstraint so -> Tree so Bool)+default_compile_constraint = default_compile_alldiff + <@> default_compile_sorted + <@> default_compile_dom -data FD_Term where- FD_Var :: FDVar -> FD_Term- deriving Show+-- decompose + default+decompose :: FDSolver s => Expr (FDTerm s) -> Tree s (FDTerm s)+decompose = mixin (front_decompose <@> specific_decompose <@> default_decompose)+default_decompose :: FDSolver s => Mixin (Expr (FDTerm s) -> Tree s (FDTerm s))+default_decompose _ _ x = debug "default_decompose" $ do+ v <- fresh_var+ compile_constraint (Same x (Term v))+ return v+front_decompose :: FDSolver s => Mixin (Expr (FDTerm s) -> Tree s (FDTerm s))+front_decompose s t (Term x) = debug "front_decompose Term" $ return x+front_decompose s t x = debug "front_decompose _" $ s x -un_fd (FD_Var v) = v+-- fresh_var + default+fresh_var :: FDSolver s => Tree s (FDTerm s)+fresh_var = mixin (specific_fresh_var <@> default_fresh_var)+default_fresh_var :: FDSolver s => Mixin (Tree s (FDTerm s))+default_fresh_var _ _ = debug "default_fresh_var" $ NewVar $ \v -> return v -data FD_Constraint where- FD_Diff :: FD_Term -> FD_Term -> FD_Constraint- FD_Same :: FD_Term -> FD_Term -> FD_Constraint- FD_Less :: FD_Term -> FD_Term -> FD_Constraint- FD_LT :: FD_Term -> Int -> FD_Constraint- FD_GT :: FD_Term -> Int -> FD_Constraint- FD_HasValue :: FD_Term -> Int -> FD_Constraint- FD_Eq :: (ToExpr a, ToExpr b) => a -> b -> FD_Constraint- FD_NEq :: (ToExpr a, ToExpr b) => a -> b -> FD_Constraint- FD_AllDiff :: [FD_Term] -> FD_Constraint- FD_Dom :: FD_Term -> (Int,Int) -> FD_Constraint+type FDExpr s = Expr (FDTerm s) -addFD (FD_Diff (FD_Var v1) (FD_Var v2)) = different v1 v2-addFD (FD_Same (FD_Var v1) (FD_Var v2)) = same v1 v2-addFD (FD_Less (FD_Var v1) (FD_Var v2)) = v1 .<. v2 -addFD (FD_HasValue (FD_Var v1) i) = hasValue v1 i-addFD (FD_Eq e1 e2) = e1 .==. e2-addFD (FD_NEq e1 e2) = e1 ./=. e2 --- addFD (FD_AllDiff vs) = allDifferent (map un_fd vs)-addFD (FD_Dom v (l,u)) = v `in_range` (l-1,u+1)-addFD (FD_LT (FD_Var v) i) = do iv <- exprVar $ toExpr i- v .<. iv-addFD (FD_GT (FD_Var v) i) = do iv <- exprVar $ toExpr i- iv .<. v+-- currently 4 simple constraints + more complex (see default compiler at the bottom)+data Show (FDTerm s) => FDConstraint s =+ Less (Expr (FDTerm s)) (Expr (FDTerm s))+ | Diff (Expr (FDTerm s)) (Expr (FDTerm s))+ | Same (Expr (FDTerm s)) (Expr (FDTerm s))+ | Dom (Expr (FDTerm s)) Integer Integer+ | AllDiff [Expr (FDTerm s)]+ | Sorted [Expr (FDTerm s)] Bool -- True = less-or-equal, False = less +deriving instance Show (FDTerm s) => Show (FDConstraint s) -(#<) :: (To_FD_Term a, To_FD_Term b) => a -> b -> FD Bool-x #< y =- do xt <- to_fd_term x- yt <- to_fd_term y- addFD (FD_Less xt yt) -in_range :: FD_Term -> (Int,Int) -> FD Bool-in_range x (l,u) =- do l #< x- x #< u+----------------------- FDWrapper -all_different = addFD . FD_AllDiff+newtype FDWrapper s a = FDWrapper { subFD :: s a } -instance ToExpr FD_Term where- toExpr (FD_Var v) = toExpr v+type FDTree s a = Tree (FDWrapper s) a -fd_domain :: FD_Term -> FD [Int]-fd_domain (FD_Var v) = do d <- lookup v- return $ elems d+newtype FDLabel s = FDLabel (Label s) -fd_objective :: FD FD_Term-fd_objective =- do s <- get- return $ FD_Var $ objective s+instance FDSolver s => Monad (FDWrapper s) where+ FDWrapper { subFD = a } >>= f = FDWrapper { subFD = a >>= (\x -> subFD $ f x) }+ return x = FDWrapper { subFD = return x } -class To_FD_Term a where- to_fd_term :: a -> FD FD_Term+instance FDSolver s => Solver (FDWrapper s) where+ type Constraint (FDWrapper s) = FDConstraint s+ type Label (FDWrapper s) = FDLabel s+ add c = FDWrapper { subFD = untree False $ compile_constraint c }+ run (FDWrapper { subFD = x}) = run x+ mark = FDWrapper { subFD = mark >>= \x -> return (FDLabel x) }+ goto (FDLabel l) = FDWrapper { subFD = goto l } -instance To_FD_Term FD_Term where- to_fd_term = return . id+data EQHelp a b where+ EQHelp :: EQHelp a a -instance To_FD_Term Int where- to_fd_term i = newVar i >>= return . FD_Var+instance (FDSolver s, t ~ Expr (FDTerm s)) => Term (FDWrapper s) t where+ type Help (FDWrapper s) t = EQHelp t (Expr (FDTerm s))+ help _ _ = EQHelp+ newvar = FDWrapper { subFD = newvar >>= (\x -> return (Term x)) } -instance To_FD_Term Expr where- to_fd_term e = unExpr e >>= return . FD_Var+instance (FDSolver s, FDTerm s ~ t, Eq t, EnumTerm s t, Integral (TermDomain s t)) => EnumTerm (FDWrapper s) (Expr t) where+ type TermDomain (FDWrapper s) (Expr t) = TermDomain s t+ get_domain_size (Const c) = return 1+ get_domain_size (Term v) = FDWrapper (get_domain_size v)+ get_value (Const c) = return $ Just $ fromInteger c+ get_value (Term v) = FDWrapper $ get_value v+ split_domain_partial (Const c) = return [return ()]+ split_domain_partial (Term v) = FDWrapper $ split_domain_partial v >>= return . map wrap+ split_domain (Const c) = return $ return ()+ split_domain (Term v) = FDWrapper $ split_domain v >>= return . wrap+ split_domains l = FDWrapper $ split_domains (map (\x -> case x of Term t -> t) l) >>= return . wrap ---------------------------------------------------------------------------------+unwrap :: forall s a .FDSolver s => Tree (FDWrapper s) a -> Tree s a+unwrap Fail = Fail+unwrap (Return a) = Return a+unwrap (Try l r) = Try (unwrap l) (unwrap r)+unwrap (NewVar (f :: t -> Tree (FDWrapper s) a)) = NewVar ((\v -> + case help (undefined :: FDWrapper s ()) (undefined :: t) of+ EQHelp -> unwrap (f (Term v :: Expr (FDTerm s)))) + :: FDTerm s -> Tree s a)+unwrap (Add c t) = compile_constraint c >>= (\b -> if b then (unwrap t) else Fail)+unwrap (Label (FDWrapper { subFD = m })) = Label (m >>= \x -> return (unwrap x)) --- The FD monad-newtype FD a = FD { unFD :: StateT FDState Maybe a }- deriving (Monad, MonadState FDState, MonadPlus)+wrap :: forall s a .FDSolver s => Tree s a -> Tree (FDWrapper s) a+wrap Fail = Fail+wrap (Return a) = Return a+wrap (Try l r) = Try (wrap l) (wrap r)+wrap (Label m) = Label $ FDWrapper $ m >>= return . wrap+wrap (Add c t) = Label $ FDWrapper $ add c >>= \res -> if res then return $ wrap t else return $ false+wrap (NewVar f) = Label $ FDWrapper $ newvar >>= return . wrap . f --- FD variables-newtype FDVar = FDVar { unFDVar :: Int } deriving (Ord, Eq, Show) -type VarSupply = FDVar+-- TODO: wrap afmaken+-- TODO: Tree opsplitsen in Tree (Try nodes) en Conjunction (de rest) -data VarInfo = VarInfo- { delayedConstraints :: FD Bool, domain :: Domain } -instance Show VarInfo where- show x = show $ domain x--type VarMap = Map FDVar VarInfo--data FDState = FDState- { varSupply :: VarSupply, varMap :: VarMap, objective :: FDVar }- deriving Show--instance Eq FDState where- s1 == s2 = f s1 == f s2- where f s = head $ elems $ domain $ varMap s ! (objective s) --instance Ord FDState where- compare s1 s2 = compare (f s1) (f s2)- where f s = head $ elems $ domain $ varMap s ! (objective s) -- -- TOM: inconsistency is not observable within the FD monad-consistentFD :: FD Bool-consistentFD = return True---- Run the FD monad and produce a lazy list of possible solutions.-runFD :: FD a -> a-runFD fd = fromJust $ evalStateT (unFD fd') initState- where fd' = fd -- fd' = newVar () >> fd--initState :: FDState-initState = FDState { varSupply = FDVar 0, varMap = Map.empty, objective = FDVar 0 }---- Get a new FDVar-newVar :: ToDomain a => a -> FD FDVar-newVar d = do- s <- get- let v = varSupply s- put $ s { varSupply = FDVar (unFDVar v + 1) }- modify $ \s ->- let vm = varMap s- vi = VarInfo {- delayedConstraints = return True,- domain = toDomain d}- in- s { varMap = Map.insert v vi vm }- return v--newVars :: ToDomain a => Int -> a -> FD [FDVar]-newVars n d = replicateM n (newVar d)---- Lookup the current domain of a variable.-lookup :: FDVar -> FD Domain-lookup x = do- s <- get- return . domain $ varMap s ! x---- Update the domain of a variable and fire all delayed constraints--- associated with that variable.-update :: FDVar -> Domain -> FD Bool-update x i = do- trace (show x ++ " <- " ++ show i) (return ())- s <- get- let vm = varMap s- let vi = vm ! x- trace ("where old domain = " ++ show (domain vi)) (return ())- put $ s { varMap = Map.insert x (vi { domain = i}) vm }- delayedConstraints vi---- Add a new constraint for a variable to the constraint store.-addConstraint :: FDVar -> FD Bool -> FD ()-addConstraint x constraint = do- s <- get- let vm = varMap s- let vi = vm ! x- let cs = delayedConstraints vi- put $ s { varMap =- Map.insert x (vi { delayedConstraints = do b <- cs - if b then constraint- else return False}) vm }- --- Useful helper function for adding binary constraints between FDVars.-type BinaryConstraint = FDVar -> FDVar -> FD Bool-addBinaryConstraint :: BinaryConstraint -> BinaryConstraint -addBinaryConstraint f x y = do- let constraint = f x y- b <- constraint - when b $ (do addConstraint x constraint- addConstraint y constraint)- return b---- Constrain a variable to a particular value.-hasValue :: FDVar -> Int -> FD Bool-var `hasValue` val = do- vals <- lookup var- if val `member` vals- then do let i = singleton val- if (i /= vals) - then update var i- else return True- else return False---- Constrain two variables to have the same value.-same :: FDVar -> FDVar -> FD Bool-same = addBinaryConstraint $ \x y -> do- xv <- lookup x- yv <- lookup y- let i = xv `intersection` yv- if not $ Domain.null i- then whenwhen (i /= xv) (i /= yv) (update x i) (update y i)- else return False--whenwhen c1 c2 a1 a2 =- if c1- then do b1 <- a1- if b1 - then if c2- then a2- else return True- else return False - else if c2- then a2- else return True---- Constrain two variables to have different values.-different :: FDVar -> FDVar -> FD Bool-different = addBinaryConstraint $ \x y -> do- xv <- lookup x- yv <- lookup y- if not (isSingleton xv) || not (isSingleton yv) || xv /= yv- then whenwhen (isSingleton xv && xv `isSubsetOf` yv)- (isSingleton yv && yv `isSubsetOf` xv)- (update y (yv `difference` xv))- (update x (xv `difference` yv))- else return False---- Constrain a list of variables to all have different values.-allDifferent :: [FDVar ] -> FD ()-allDifferent (x:xs) = do- mapM_ (different x) xs- allDifferent xs-allDifferent _ = return ()---- Constrain one variable to have a value less than the value of another--- variable.-infix 4 .<.-(.<.) :: FDVar -> FDVar -> FD Bool-(.<.) = addBinaryConstraint $ \x y -> do- xv <- lookup x- yv <- lookup y- let xv' = filterLessThan (findMax yv) xv- let yv' = filterGreaterThan (findMin xv) yv- if not $ Domain.null xv'- then if not $ Domain.null yv'- then whenwhen (xv /= xv') (yv /= yv') (update x xv') (update y yv')- else return False- else return False--{---- Get all solutions for a constraint without actually updating the--- constraint store.-solutions :: FD s a -> FD s [a]-solutions constraint = do- s <- get- return $ evalStateT (unFD constraint) s---- Label variables using a depth-first left-to-right search.-labelling :: [FDVar s] -> FD s [Int]-labelling = mapM label where- label var = do- vals <- lookup var- val <- FD . lift $ elems vals- var `hasValue` val- return val--}--dump :: [FDVar] -> FD [Domain]-dump = mapM lookup--newtype Expr = Expr { unExpr :: FD (FDVar) }+----------------------- Operators -class ToExpr a where- toExpr :: a -> Expr+-- syntactic sugar for expressions+infixl 6 @++infixl 6 @-+infixl 7 @*+infixl 7 @/+infixl 7 @%+a @+ b = (toExpr a) + (toExpr b)+a @- b = (toExpr a) - (toExpr b)+a @* b = (toExpr a) * (toExpr b)+a @/ b = (toExpr a) `div` (toExpr b)+a @% b = (toExpr a) `mod` (toExpr b)+cte x = fromInteger $ toInteger x -instance ToExpr FDVar where- toExpr = Expr . return+-- syntactic sugar for relations -instance ToExpr Expr where- toExpr = id+infix 4 @:+a @: (b,c) = addC $ Dom a (toInteger b) (toInteger c) -instance Integral i => ToExpr i where- toExpr n = Expr $ newVar n+infix 4 @<+a @< b = addC $ Less a b -exprVar :: ToExpr a => a -> FD FDVar-exprVar = unExpr . toExpr+infix 4 @<=+a @<= b = addC $ Less a (b + 1) --- Add constraint (z = x `op` y) for new var z-addArithmeticConstraint :: (ToExpr a, ToExpr b) =>- (Domain -> Domain -> Domain) ->- (Domain -> Domain -> Domain) ->- (Domain -> Domain -> Domain) ->- a -> b -> Expr-addArithmeticConstraint getZDomain getXDomain getYDomain xexpr yexpr = Expr $ do- x <- exprVar xexpr- y <- exprVar yexpr- xv <- lookup x- yv <- lookup y- z <- newVar (getZDomain xv yv)- let constraint z x y getDomain = do- xv <- lookup x- yv <- lookup y- zv <- lookup z- let znew = zv `intersection` (getDomain xv yv)- trace (show z ++ " before: " ++ show zv ++ show "; after: " ++ show znew) (return ())- if not $ Domain.null znew- then if (znew /= zv) - then update z znew- else return True- else return False- let zConstraint = constraint z x y getZDomain- xConstraint = constraint x z y getXDomain- yConstraint = constraint y z x getYDomain- addConstraint z xConstraint- addConstraint z yConstraint- addConstraint x zConstraint- addConstraint x yConstraint- addConstraint y zConstraint- addConstraint y xConstraint- return z+infix 4 @>+a @> b = addC $ Less b a -infixl 6 .+.-(.+.) :: (ToExpr a, ToExpr b) => a -> b -> Expr-(.+.) = addArithmeticConstraint getDomainPlus getDomainMinus getDomainMinus+infix 4 @>=+a @>= b = addC $ Less b (a + 1) -infixl 6 .-.-(.-.) :: (ToExpr a, ToExpr b) => a -> b -> Expr-(.-.) = addArithmeticConstraint getDomainMinus getDomainPlus- (flip getDomainMinus)+infix 4 @=+a @= b = addC $ Same a b -infixl 7 .*.-(.*.) :: (ToExpr a, ToExpr b) => a -> b -> Expr-(.*.) = addArithmeticConstraint getDomainMult getDomainDiv getDomainDiv+infix 4 @/=+a @/= b = addC $ Diff a b -getDomainPlus :: Domain -> Domain -> Domain-getDomainPlus xs ys = toDomain (zl, zh) where- zl = findMin xs + findMin ys- zh = findMax xs + findMax ys+allDiff l = addC $ AllDiff l+sorted l = addC $ Sorted l True+sSorted l = addC $ Sorted l False -getDomainMinus :: Domain -> Domain -> Domain-getDomainMinus xs ys = toDomain (zl, zh) where- zl = findMin xs - findMax ys- zh = findMax xs - findMin ys+allin list range = foldr1 (/\) $ map (@: range) list -getDomainMult :: Domain -> Domain -> Domain-getDomainMult xs ys = toDomain (zl, zh) where- zl = minimum products- zh = maximum products- products = [x * y |- x <- [findMin xs, findMax xs],- y <- [findMin ys, findMax ys]]+---------------------------------------------------------------------------------+-- Default compilations+--------------------------------------------------------------------------------- -getDomainDiv :: Domain -> Domain -> Domain-getDomainDiv xs ys = toDomain (zl, zh) where- zl = minimum quotientsl- zh = maximum quotientsh- quotientsl = [if y /= 0 then x `div` y else minBound |- x <- [findMin xs, findMax xs],- y <- [findMin ys, findMax ys]]- quotientsh = [if y /= 0 then x `div` y else maxBound |- x <- [findMin xs, findMax xs],- y <- [findMin ys, findMax ys]]+default_compile_alldiff :: FDSolver so => Mixin (FDConstraint so -> Tree so Bool)+default_compile_alldiff s t c = case c of+ (AllDiff []) -> return True+ (AllDiff (x:xs)) -> do+ conj [ (t $ Diff x e) /\ return () | e <- xs ]+ t $ AllDiff xs+ return True+ _ -> s c -infix 4 .==.-(.==.) :: (ToExpr a, ToExpr b) => a -> b -> FD Bool-xexpr .==. yexpr = do- x <- exprVar xexpr- y <- exprVar yexpr- x `same` y+default_compile_sorted :: FDSolver so => Mixin (FDConstraint so -> Tree so Bool)+default_compile_sorted s t c = case c of+ (Sorted [] _) -> return True+ (Sorted (x:xs) eq) -> do+ conj [ (t $ Less x (if eq then e+1 else e)) /\ return () | e <- xs ]+ t $ Sorted xs eq+ return True+ _ -> s c -infix 4 ./=.-(./=.) :: (ToExpr a, ToExpr b) => a -> b -> FD Bool-xexpr ./=. yexpr = do- x <- exprVar xexpr- y <- exprVar yexpr- x `different` y+default_compile_dom :: FDSolver so => Mixin (FDConstraint so -> Tree so Bool)+default_compile_dom s t c = case c of+ (Dom _ l u) | l>u -> Fail+ (Dom x l u) -> do+ t $ Less x (Const $ u+1)+ t $ Less (Const $ l-1) x+ return True+ _ -> s c
− Control/CP/FD/FDSugar.hs
@@ -1,129 +0,0 @@-{- - - Monadic Constraint Programming- - http://www.cs.kuleuven.be/~toms/Haskell/- - Tom Schrijvers- -}-{-# LANGUAGE TransformListComp #-}-{-# LANGUAGE Rank2Types #-}-{-# LANGUAGE TypeFamilies #-}--module Control.CP.FD.FDSugar where --import Control.CP.SearchTree hiding (label)-import Control.CP.Transformers-import Control.CP.ComposableTransformers-import Control.CP.Queue-import Control.CP.Solver--import GHC.Exts (sortWith)-import qualified Control.CP.PriorityQueue as PriorityQueue-import qualified Data.Sequence-import Control.CP.FD.FD--dfs = []-bfs = Data.Sequence.empty-pfs :: Ord a => PriorityQueue.PriorityQueue a (a,b,c)-pfs = PriorityQueue.empty--nb :: Int -> CNodeBoundedST FD a-nb = CNBST-db :: Int -> CDepthBoundedST FD a-db = CDBST-bb :: NewBound FD -> CBranchBoundST FD a-bb = CBBST-fs :: CFirstSolutionST FD a-fs = CFSST-it :: CIdentityCST FD a-it = CIST-ra :: Int -> CRandomST FD a-ra = CRST-ld :: Int -> CLimitedDiscrepancyST FD a-ld = CLDST--newBound :: NewBound FD-newBound = do obj <- fd_objective- (val:_) <- fd_domain obj - l <- mark- return ((\tree -> tree `insertTree` (obj @< val)) :: forall b . Tree FD b -> Tree FD b)--newBoundBis :: NewBound FD -newBoundBis = do obj <- fd_objective- (val:_) <- fd_domain obj - let m = val `div` 2- return ((\tree -> (obj @< (m + 1) \/ ( obj @> m /\ obj @< val)) /\ tree) :: forall b . Tree FD b -> Tree FD b)--restart :: (Queue q, Solver solver, CTransformer c, CForSolver c ~ solver,- Elem q ~ (Label solver,Tree solver (CForResult c),CTreeState c)) - => q -> [c] -> Tree solver (CForResult c) -> (Int,[CForResult c])-restart q cs model = run $ eval model q (RestartST (map Seal cs) return)--restartOpt :: (Queue q, CTransformer c, CForSolver c ~ FD,- Elem q ~ (Label FD,Tree FD (CForResult c),CTreeState c)) - => q -> [c] -> Tree FD (CForResult c) -> (Int,[CForResult c])-restartOpt q cs model = run $ eval model q (RestartST (map Seal cs) opt)- where opt tree = newBound >>= \f -> return (f tree)------------------------------------------------------------------------------------- ENUMERATION-----------------------------------------------------------------------------------enumerate = Label . (label in_order) --- enumerate = Label . (label firstfail) --label sel qs = do qs' <- sel qs - label' qs' - where label' [] = return true- label' (q:qs) = do d <- fd_domain q --- return $ enum q (middleout d) /\ enumerate qs- return $ enum q d /\ enumerate qs--in_order :: Monad m => a -> m a-in_order = return --firstfail qs = do ds <- mapM fd_domain qs - return [ q | (d,q) <- zip ds qs - , then sortWith by (length d) ] -enum queen values = - disj [ queen @= value - | value <- values - ] --value var = do [val] <- fd_domain var- return val--middleout l = let n = (length l) `div` 2 in- interleave (drop n l) (reverse $ take n l)--endsout l = let n = (length l) `div` 2 in- interleave (reverse $ drop n l) (take n l)--interleave [] ys = ys-interleave (x:xs) ys = x:interleave ys xs------------------------------------------------------------------------------------ RESULT-----------------------------------------------------------------------------------assignments = mapM assignment -assignment q = Label $ value q >>= (return . Return)------------------------------------------------------------------------------------ SYNTACTIC SUGAR-----------------------------------------------------------------------------------in_domain v (l,u) = Add (FD_Dom v (l,u)) true-(@\=) :: FD_Term -> FD_Term -> Tree FD ()-v1 @\= v2 = Add (FD_NEq v1 v2) true--(@=) :: FD_Term -> Int -> Tree FD ()-v1 @= v2 = Add (FD_Eq v1 v2) true--data Plus = FD_Term :+ Int -(@+) = (:+)--(@\==) :: FD_Term -> Plus -> Tree FD ()-v1 @\== (v2 :+ i) = Add (FD_NEq v1 (v2 .+. i)) true--(@<) :: FD_Term -> Int -> Tree FD ()-v @< i = Add (FD_LT v i) true--(@>) :: FD_Term -> Int -> Tree FD ()-v @> i = Add (FD_GT v i) true
+ Control/CP/FD/Gecode/CodegenSolver.hs view
@@ -0,0 +1,476 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Control.CP.FD.Gecode.CodegenSolver (+ CodegenSolver(..),+ compile,+ Store(..),+ StoreNode(..),+ StoreNodeType(..),+ getVarType,+ isVarImplicit,+ VarBound(..),+ getAllBounds+) where++import Maybe (fromMaybe,catMaybes,isJust,fromJust)+import List (findIndex,find)+import Data.Map hiding (map,filter)++import Control.Monad.State.Lazy+import Control.Monad.Trans+import Control.Monad.Cont+++import Control.CP.SearchTree hiding (label)+import Control.CP.Solver+import Control.CP.FD.FD+import Control.CP.FD.Expr+import Control.CP.Debug+import Control.CP.Mixin++import Control.CP.FD.Gecode.Common++--------------------------------------------------------------------------------+-- | Helper functions+--------------------------------------------------------------------------------++repl l i v = case l of+ [] -> [v]+ a:ar -> if i==0+ then v:ar+ else repl ar (i-1) v++revrepl l i v = repl l ((length l)-i-1) v++revget l i = l !! ((length l)-i-1)++dump n l = case l of+ [] -> []+ (a:b) -> if (n==0) then b else a:(dump (n-1) b)++--------------------------------------------------------------------------------+-- | Gecode Solver instance declaration+--------------------------------------------------------------------------------+instance Solver CodegenSolver where+ type Constraint CodegenSolver = GConstraint+ type Label CodegenSolver = Store+ add = addGecode+ run = runGecode + mark = get+ goto = put++--------------------------------------------------------------------------------+-- | CodegenSolver terms+--------------------------------------------------------------------------------++instance Term CodegenSolver IntTerm where+ newvar = newVar False TypeInt >>= return . IntVar+ type Help CodegenSolver IntTerm = ()+ help _ _ = ()++instance Term CodegenSolver BoolTerm where+ newvar = newVar False TypeBool >>= return . BoolVar+ type Help CodegenSolver BoolTerm = ()+ help _ _ = ()++--------------------------------------------------------------------------------+-- | CodegenSolver monad definition +--------------------------------------------------------------------------------++newtype CodegenSolver a = CodegenSolver { state :: State Store a }+ deriving (Monad, MonadState Store)++-- instance Show (CodegenSolver a) where+-- show c = show $ execState (state c) initState+++type VarId = Int+type LowerBound = Maybe Integer+type UpperBound = Maybe Integer++data VarBound = VarBound { varid :: VarId, lbound :: LowerBound, ubound :: UpperBound }+ deriving (Show, Eq)++type VarBoundMap = Map VarId VarBound+type VarBoundPropagator = VarBoundMap -> [ VarBound ]++--------------------------------------------------------------------------------+{- |+ StoreNode represents a node in the search tree.+ * Each node adds new constraints and variables.+ * A node is a leaf node or an internal node+ -}+data StoreNode = + StoreNode { cons :: [ GConstraint ]+ -- ^ new constraints added in this node+ , nbounds :: [ VarBoundPropagator ]+ -- ^ new bound-generator functions in this node+ , nvars :: [ Int ]+ -- ^ id's of variables added in this node+ , dis :: StoreNodeType+ -- ^ either no children, or one left and one right child+ }++data StoreNodeType = SNLeaf | SNIntl StoreNode StoreNode+ deriving Show++instance Show StoreNode+ where show sn = "StoreNode { cons=" ++ (show $ cons sn) ++ + ", nbounds=" ++ (show $ length $ nbounds sn) ++ + ", nvars=" ++ (show $ nvars sn) ++ + ", dus=" ++ (show $ dis sn) +++ "}"+--------------------------------------------------------------------------------++data VarData = VarData { vtype :: GType, vimpl :: Bool }+ deriving Show++data Store = Store { vars :: Int, vardata :: [ VarData ], ctree :: StoreNode, cpath :: [ Bool ], cexpr :: Map (ExprKey (FDTerm CodegenSolver)) Int }+ deriving Show+++setVarImplicitHelper :: Store -> Int -> Bool -> Store+setVarImplicitHelper s p v = s { vardata = revrepl (vardata s) p ( (revget (vardata s) p) { vimpl = v } ) }++initNode = StoreNode { cons = [], dis = SNLeaf, nvars = [], nbounds=[] }+initState = Store { vars=0, vardata=[], ctree=initNode, cpath=[], cexpr=empty }++addStateTree node path con vars bounds = case (dis node,path) of+ (_,[]) -> node { cons = con++(cons node), nvars = vars++(nvars node), nbounds = bounds++(nbounds node) }+ (SNLeaf,s:sr) -> node { dis = if s then SNIntl initNode (addStateTree initNode sr con vars bounds) + else SNIntl (addStateTree initNode sr con vars bounds) initNode }+ (SNIntl l r,s:sr) -> node { dis = if s then SNIntl l (addStateTree r sr con vars bounds) + else SNIntl (addStateTree l sr con vars bounds) r }++addState store con vars bounds = store { ctree = addStateTree (ctree store) (cpath store) con vars bounds }++getConstraintsTree tree path = (cons tree) ++ case (dis tree,path) of+ (SNLeaf,_) -> []+ (SNIntl l _, False:s) -> getConstraintsTree l s+ (SNIntl l _, []) -> getConstraintsTree l []+ (SNIntl _ r, True:s) -> getConstraintsTree r s+++getConstraints state = getConstraintsTree (ctree state) (cpath state)++--------------------------------------------------------------------------------+-- | CodegenSolver compilation+--------------------------------------------------------------------------------++compile :: Tree CodegenSolver a -> Store+compile x = execGecode (buildState x)++execGecode :: CodegenSolver a -> Store+execGecode x = execState (state x) initState++buildState :: Tree CodegenSolver a -> CodegenSolver ()+buildState (Add c v) = do add c+ buildState v+buildState (NewVar f) = do v <- newvar+ buildState $ f v+buildState (Try l r) = do v1 <- get+ let opath = cpath v1+ let ocexpr = cexpr v1+ put $ v1 { cpath = opath ++ [ False ], cexpr = ocexpr }+ buildState l+ v2 <- get+ put $ v2 { cpath = opath ++ [ True ], cexpr = ocexpr }+ buildState r+ v3 <- get+ put $ v3 { cpath = opath, cexpr = ocexpr }+buildState (Label m) = m >>= buildState+buildState _ = return ()++--------------------------------------------------------------------------------+-- | Bounds+--------------------------------------------------------------------------------++data XInt = XInfMin | XInfPlus | XInt Integer++toXInt isUpper Nothing = if isUpper then XInfPlus else XInfMin+toXInt _ (Just i) = XInt i++bndMult (XInt a) (XInt b) _ _ = [XInt (a*b)]+bndMult XInfMin XInfMin _ _ = [XInfPlus]+bndMult XInfPlus XInfMin _ _ = [XInfMin]+bndMult XInfPlus XInfPlus _ _ = [XInfPlus]+bndMult (XInt a) XInfPlus la _+ | a < 0 = [XInfMin]+ | a > 0 = [XInfPlus]+ | a == 0 && la = [XInfPlus]+ | a == 0 && not la = [XInfMin]+bndMult (XInt a) XInfMin la _+ | a < 0 = [XInfPlus]+ | a > 0 = [XInfMin]+ | a == 0 && la = [XInfMin]+ | a == 0 && not la = [XInfPlus]+bndMult a b c d = bndMult b a d c++bndDiv _ _ _ _ = [XInfMin,XInfPlus]++boundFn f v1 v2 l1 l2 = f (toXInt l1 v1) (toXInt l2 v2) l1 l2++lowestBound :: [XInt] -> XInt+lowestBound = foldl1 m + where m XInfMin _ = XInfMin+ m _ XInfMin = XInfMin+ m (XInt a) (XInt b) = XInt $ min a b+ m (XInt a) _ = XInt a+ m _ (XInt a) = XInt a+ m XInfPlus XInfPlus = XInfPlus++highestBound :: [XInt] -> XInt+highestBound = foldl1 m + where m XInfPlus _ = XInfPlus+ m _ XInfPlus = XInfPlus+ m (XInt a) (XInt b) = XInt $ max a b+ m (XInt a) _ = XInt a+ m _ (XInt a) = XInt a+ m XInfMin XInfMin = XInfMin++boundRelation f (i1,i2,o) b = + let (i1l,i1u) = getBounds b i1+ (i2l,i2u) = getBounds b i2+ bns = foldl1 (++) $ map (\(a,b,c,d) -> boundFn f a b c d) + [(i1l,i2l,False,False)+ ,(i1l,i2u,False,True)+ ,(i1u,i2l,True,False)+ ,(i1u,i2u,True,True)+ ]+ xl = lowestBound bns+ xu = highestBound bns+ fromXInt XInfPlus = Nothing+ fromXInt XInfMin = Nothing+ fromXInt (XInt a) = Just a+ in case (xl,xu) of+ (XInfPlus,_) -> []+ (_,XInfMin) -> []+ (_,_) -> [VarBound { varid = o, lbound = fromXInt xl, ubound = fromXInt xu }]++catPropagators p = foldl1 (\a b -> \x -> (a x) ++ (b x)) p++linearPropagator l p c = \b -> + let (IntVar i,cc) = l !! p+ (low,high) = foldl + (\x y -> case (x,y) of+ ((Just l1,Just h1),(Just l2,Just h2)) -> (Just (l1-h2),Just (h1-l2))+ ((Nothing,Just h1),(Just l2,_)) -> (Nothing,Just (h1-l2))+ ((_,Just h1),(Just l2,Nothing)) -> (Nothing,Just (h1-l2))+ ((Just l1,Nothing),(_,Just h2)) -> (Just (l1-h2),Nothing)+ ( (Just l1,_),(Nothing,Just h2)) -> (Just (l1-h2),Nothing)+ _ -> (Nothing,Nothing)+ ) (Just c,Just c) cbounds+ cbounds = map + (\x -> case x of + (c,(Just l,Just h)) -> if c<0 then (Just (c*h),Just (c*l)) else (Just (c*l),Just (c*h))+ (c,(Nothing,Just h)) -> if c<0 then (Just (c*h),Nothing) else (Nothing,Just (c*h))+ (c,(Just l,Nothing)) -> if c<0 then (Nothing,Just (c*l)) else (Just (c*l),Nothing)+ _ -> (Nothing,Nothing)+ ) dbounds+ dbounds = dump p bounds+ bounds = map (\(IntVar v,c) -> {- debug ("var "++(show v)++" is in "++(show $ getBounds b v)) $ -} (c,getBounds b v)) l+ in (i,cc,low,high)++linearEqPropagator ll p c = \b -> case linearPropagator ll p c b of+ (_,0,_,_) -> []+ (i,cc,Just l,Just h) -> {- debug ("["++(if l>h then "AAAARGH! " else "")++(show ll)++"="++(show c)++"/"++(show cc)++"->["++(show p)++"]: var "++(show i)++" in ["++(show l)++".."++(show h)++"]]\n") $ -} if (cc<0) + then let x=[ VarBound i (Just ((-h) `div` (-cc))) (Just (l `div` cc)) ] in {- debug (show x) -} x+ else let x=[ VarBound i (Just ((-l) `div` (-cc))) (Just (h `div` cc)) ] in {- debug (show x) -} x+ (i,cc,Nothing,Just h) -> {- debug ("["++(show ll)++"="++(show c)++"/"++(show cc)++"->["++(show p)++"]: var "++(show i)++" in [.."++(show h)++"]]\n") $ -} if (cc<0) + then let x=[ VarBound i (Just ((-h) `div` (-cc))) Nothing ] in {- debug (show x) -} x+ else let x=[ VarBound i Nothing (Just (h `div` cc)) ] in {- debug (show x) -} x+ (i,cc,Just l,Nothing) -> {- debug ("["++(show ll)++"="++(show c)++"/"++(show cc)++"->["++(show p)++"]: var "++(show i)++" in ["++(show l)++"..]]\n") $ -} if (cc<0) + then let x=[ VarBound i Nothing (Just (l `div` cc)) ] in {- debug (show x) -} x+ else let x=[ VarBound i (Just ((-l) `div` (-cc))) Nothing ] in {- debug (show x) -} x+ (i,cc,_,_) -> {- debug ("["++(show ll)++"="++(show c)++"/"++(show cc)++"->["++(show p)++"]: var "++(show i)++" in [..]]\n") $ -} []++linearLessPropagator l p c = \b -> case (linearPropagator l p c b) of+ (_,0,_,_) -> []+ (i,cc,_,Just h) -> if (cc<0) + then [ VarBound i (Just ((1-h) `div` (-cc))) Nothing ]+ else [ VarBound i Nothing (Just ((h-1) `div` cc)) ]+ _ -> []++debugBoundsPropagator :: GConstraint -> VarBoundPropagator+debugBoundsPropagator c = let cc = boundsPropagator c in+ \b -> let ccc = cc b in {- debug ("debugBounds: "++(show c)++" -> "++(show ccc)) -} ccc++boundsPropagator :: GConstraint -> VarBoundPropagator+boundsPropagator c = case c of+ CValue (IntVar i) v -> (\_ -> [ VarBound i (Just v) (Just v) ])+ CDom (IntVar i) l u -> (\_ -> [ VarBound i (Just l) (Just u) ])+ CRel (IntVar i) OLess (IntVar j) -> \b ->+ let (jbl,jbu) = getBounds b j+ (ibl,ibu) = getBounds b i+ in catMaybes [ if isJust jbu then Just $ VarBound i Nothing (Just $ (fromJust jbu)-1) else Nothing,+ if isJust ibl then Just $ VarBound j (Just $ (fromJust ibl)+1) Nothing else Nothing+ ]+ CRel (IntVar i) OEqual (IntVar j) -> \b ->+ let (jbl,jbu) = getBounds b j+ (ibl,ibu) = getBounds b i+ in [ VarBound i jbl jbu, VarBound j ibl ibu ]+ CRel (IntVar i) OEqual (IntConst c) -> boundsPropagator $ CValue (IntVar i) c+ CRel (IntConst c) OEqual (IntVar i) -> boundsPropagator $ CValue (IntVar i) c+ CRel (IntVar i) OLess (IntConst c) -> (\_ -> [ VarBound i Nothing (Just (c-1)) ])+ CRel (IntConst c) OLess (IntVar i) -> (\_ -> [ VarBound i (Just (c+1)) Nothing ])+ CLinear [(IntVar i,f)] OEqual c | (c `mod` f)==0 -> boundsPropagator $ CValue (IntVar i) (c `div` f)+ CLinear l OEqual c -> catPropagators $ map (\p -> linearEqPropagator l p c) [0..((length l)-1)]+ CLinear l OLess c -> catPropagators $ map (\p -> linearLessPropagator l p c) [0..((length l)-1)]+ CMult (IntVar f1) (IntVar f2) (IntVar m) -> catPropagators+ [ boundRelation bndMult (f1,f2,m)+ , boundRelation bndDiv (m,f1,f2)+ , boundRelation bndDiv (m,f2,f1)+ ]+ CAbs (IntVar v1) (IntVar v2) -> \b ->+ let (v1l,v1h) = getBounds b v1+ (v2l,v2h) = getBounds b v2+ in [ case v2h of+ Nothing -> VarBound v1 Nothing Nothing+ Just h -> VarBound v1 (Just (-h)) (Just h)+ , case (v1l,v1h) of+ (Nothing,Nothing) -> VarBound v2 (Just 0) (Nothing)+ (Just l,Nothing) | l<0 -> VarBound v2 (Just 0) Nothing+ (Nothing,Just h) | h>0 -> VarBound v2 (Just 0) Nothing+ (Just l,Nothing) | l>=0 -> VarBound v2 (Just l) Nothing+ (Nothing,Just h) | h<=0 -> VarBound v2 (Just (-h)) Nothing+ (Just l,Just h) | l<=0 && h>=0 -> VarBound v2 (Just 0) (Just ((-l) `max` h))+ (Just l,Just h) | h<0 -> VarBound v2 (Just (-h)) (Just (-l))+ (Just l,Just h) | l>0 -> VarBound v2 (Just l) (Just h)+ ]+ _ -> (\_ -> [])++-- Combination+propagateVarBounds :: [ VarBoundPropagator ] -> VarBoundMap -> VarBoundMap+propagateVarBounds propagators vbmap = fixP propagators vbmap+ where+ fixP :: [VarBoundPropagator] -> VarBoundMap -> VarBoundMap + fixP [] src = src+ fixP (p:ps) src = case propagate p src of+ Nothing -> fixP ps src+ Just src' -> fixP propagators src'+ propagate p src = + either (const Nothing) Just $ foldl combine (Left src) (p src)+ where combine prev vb = prev `fromMaybe` (intersectBound vb src >>= return . Right) + where src = either id id prev++-- add a new bound to a bounds map - returns Nothing if map remains unchanged, Just <newmap> otherwise+intersectBound :: VarBound -> VarBoundMap -> Maybe VarBoundMap+intersectBound nw k + | oldValue == newValue = Nothing+ | otherwise = Just result+ where + (oldValue,result) = insertLookupWithKey (\k n o -> n) (varid nw) (fromJust newValue) k+ newValue = + (do ov <- oldValue+ return $ adj ov+ ) `orElse` (Just nw)+ adj fnd@(VarBound {lbound = olb, ubound = oub}) = nb+ where+ nlb = newmax 1 olb $ lbound nw+ nub = newmax (-1) oub $ ubound nw+ nb = fnd { lbound = nlb, ubound = nub }+ newmax f b1 b2 = + (do x <- b1+ y <- b2+ return $ ((f*x) `max` (f*y)) `div` f+ ) `orElse` b1 `orElse` b2++unionBounds :: VarBoundMap -> VarBoundMap -> VarBoundMap+unionBounds = unionWith unioner+ where unioner (VarBound i1 l1 u1) (VarBound i2 l2 u2) = VarBound i1 (newmax (-1) l1 l2) (newmax 1 u1 u2)+ newmax f b1 b2 = + do x <- b1+ y <- b2+ return $ ((f*x) `max` (f*y)) `div` f++getBounds :: VarBoundMap -> VarId -> (LowerBound, UpperBound)+getBounds b v = + let bnd = case Data.Map.lookup v b of+ Nothing -> (Nothing,Nothing)+ Just k -> (lbound k,ubound k)+ in {- debug ("v"++(show v)++": "++(show bnd)) -} bnd++getNodeBounds :: StoreNode -> [ Bool ] -> [ VarBoundPropagator ] -> [ VarId ] -> [VarBoundMap]+getNodeBounds node path bnds vars = + let nvrs = nvars node ++ vars+ nbnds = nbounds node ++ bnds+ in case dis node of+ SNLeaf -> [ propagateVarBounds nbnds $ fromList $ map (\x -> (x,VarBound x Nothing Nothing)) nvrs ]+ SNIntl l r -> case path of+ [] -> (getNodeBounds l [] nbnds nvrs) ++ (getNodeBounds r [] nbnds nvrs)+ x:rp -> getNodeBounds (if x then r else l) rp nbnds nvrs+++getPathBounds :: Store -> [Bool] -> VarBoundMap+getPathBounds s p = foldl (flip unionBounds) empty (getNodeBounds (ctree s) p [] [])++getAllBounds s = getPathBounds s []+getCurBounds s = getPathBounds s (cpath s)++--------------------------------------------------------------------------------+-- | CodegenSolver solver implementation+--------------------------------------------------------------------------------++addGecode c = do+ s <- get+ put $ addState s [c] [] [boundsPropagator c]+ return True++newVar :: Bool -> GType -> CodegenSolver Int+newVar impl tp = do+ s <- get+ let vn = vars s+ put $ addState (s { vars = vn + 1, vardata = (VarData { vtype=tp, vimpl=impl }) : (vardata s) }) [] [vn] []+ return $ vn++runGecode :: CodegenSolver p -> p+runGecode x = evalState (state x) initState++--------------------------------------------------------------------------------+-- | CodegenSolver FDSolver instance+--------------------------------------------------------------------------------++instance GecodeSolver CodegenSolver where+ caching_decompose super this x = Label $ do+ s <- get+ let wx = ExprKey x+ case Data.Map.lookup wx (cexpr s) of+ Nothing -> return $ do+ n@(IntVar i) <- super x+ Label $ do+ s <- get+ put $ s { cexpr = insert wx i $ cexpr s }+ return $ return n+ Just i -> return $ return $ IntVar i+ setVarImplicit (IntVar i) b = do+ s <- get+ put $ setVarImplicitHelper s i b++instance FDSolver CodegenSolver where+ type FDTerm CodegenSolver = IntTerm+ specific_compile_constraint = linearCompile <@> basicCompile+ specific_decompose = caching_decompose+ specific_fresh_var super this = do+ v@(IntVar i) <- super+ Label $ do+ setVarImplicit (IntVar i) True+ return $ Return v++-- | utility++getNumVars :: Store -> Int+getNumVars s = vars s++getVarData :: Store -> Int -> VarData+getVarData s i = (vardata s) !! ((length $ vardata s)-1-i)++modVarData :: Store -> Int -> VarData -> Store+modVarData s i d = s { vardata = revrepl (vardata s) i d }++getVarType :: Store -> Int -> GType+getVarType s i = vtype $ getVarData s i++isVarImplicit :: Store -> Int -> Bool+isVarImplicit s i = vimpl $ getVarData s i
+ Control/CP/FD/Gecode/Common.hs view
@@ -0,0 +1,277 @@+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}++module Control.CP.FD.Gecode.Common (+ GTerm(..),+ GType(..),+ IntTerm(..),+ BoolTerm(..),+ GConstraint(..),+ GOperator(..),+ GecodeSolver(..),+ orElse,+ linearCompile,+ basicCompile+) where++import Maybe (fromMaybe,catMaybes,isJust,fromJust)+import List (findIndex,find)+import Data.Map hiding (map,filter)++import Control.Monad.State.Lazy+import Control.Monad.Trans+import Control.Monad.Cont+++import Control.CP.SearchTree hiding (label)+import Control.CP.Solver+import Control.CP.FD.FD+import Control.CP.FD.Expr+import Control.CP.Debug+import Control.CP.Mixin+-- import Control.CP.Gecode.Gecode++--------------------------------------------------------------------------------+-- | Gecode terms+--------------------------------------------------------------------------------++class GTerm t where+ getVarId :: t -> Maybe Int+ getIntValue :: t -> Maybe Integer+ getDefBounds :: t -> (Integer,Integer)++data GType = TypeInt | TypeBool+ deriving (Show, Eq)++-- | integer terms+data IntTerm+ = IntVar Int+ | IntConst Integer+ deriving Eq++instance Ord IntTerm where+ compare (IntVar i1) (IntVar i2) = compare i1 i2+ compare (IntVar _) _ = LT+ compare _ (IntVar _) = GT+ compare (IntConst c1) (IntConst c2) = compare c1 c2++instance Show IntTerm where+ show (IntVar i) = "i" ++ (show i)+ show (IntConst i) = (show i)++instance GTerm IntTerm where+ getVarId (IntVar i) = Just i+ getVarId (IntConst _) = Nothing+ getIntValue (IntVar _) = Nothing+ getIntValue (IntConst c) = Just c+ getDefBounds _ = (-1000000000,1000000000)++-- | boolean terms+data BoolTerm where+ BoolVar :: Int -> BoolTerm+ BoolConst :: Bool -> BoolTerm+ deriving Eq++instance Show BoolTerm where+ show (BoolVar i) = "b" ++ (show i)+ show (BoolConst b) = show b++instance GTerm BoolTerm where+ getVarId (BoolVar i) = Just i+ getVarId (BoolConst _) = Nothing+ getIntValue (BoolVar _) = Nothing+ getIntValue (BoolConst c) = Just $ if c then 1 else 0+ getDefBounds _ = (0,1)++-- instance Term Gecode BoolTerm where+-- type TermInfo Gecode BoolTerm = Bool+-- newvar = newVar False TypeBool >>= return . BoolVar+-- +-- instance Term Gecode IntTerm where+-- type TermInfo Gecode IntTerm = Bool+-- newvar = newVar False TypeInt >>= return . IntVar+++--------------------------------------------------------------------------------+-- | Gecode constraints +--------------------------------------------------------------------------------++data GConstraint + = forall t . GTerm t => CDiff t t+ | forall t . GTerm t => CSame t t+ | CRel IntTerm GOperator IntTerm+ | CMult IntTerm IntTerm IntTerm+ | CAbs IntTerm IntTerm+ | CDiv IntTerm IntTerm IntTerm+ | CMod IntTerm IntTerm IntTerm+ | CValue IntTerm Integer+ | CDom IntTerm Integer Integer+ | CLinear [(IntTerm,Integer)] GOperator Integer+ | CAllDiff [IntTerm]+ | CSorted [IntTerm] Bool++instance Show GConstraint where+ show (CRel x o y) = "(Rel: " ++ (show x) ++ (show o) ++ (show y) ++ ")"+ show (CMult x y z) = "(Mult: " ++ (show x) ++ " * " ++ (show y) ++ " = " ++ (show z) ++ ")"+ show (CDiv x y z) = "(Div: " ++ (show x) ++ " / " ++ (show y) ++ " = " ++ (show z) ++ ")"+ show (CMod x y z) = "(Mod: " ++ (show x) ++ " % " ++ (show y) ++ " = " ++ (show z) ++ ")"+ show (CAbs x y) = "(Abs: abs " ++ (show x) ++ " = " ++ (show y) ++ ")"+ show (CDom x y z) = "(Dom: " ++ (show x) ++ " in [" ++ (show y) ++ "," ++ (show z) ++ "])"+ show (CValue x y) = "(Value: " ++ (show x) ++ " is " ++ (show y) ++ ")"+ show (CLinear l o c) = "(Linear: " ++ (show l) ++ (show o) ++ (show c) ++ ")"+ show (CAllDiff l) = "(AllDiff: " ++ (show l) ++ ")"++data GOperator+ = OEqual+ | ODiff+ | OLess++instance Show GOperator where+ show OEqual = "=="+ show ODiff = "/="+ show OLess = "<"++--------------------------------------------------------------------------------+-- | Gecode FDSolver instance+--------------------------------------------------------------------------------++class (Solver s, Term s IntTerm) => GecodeSolver s where+ setVarImplicit :: IntTerm -> Bool -> s ()+ setVarImplicit _ _ = return ()+ caching_decompose :: GecodeSolver s => Mixin (Expr (FDTerm s) -> Tree s IntTerm)+ caching_decompose s _ x = s x++-- | basic compilation++basicCompile :: (FDSolver s, Constraint s ~ GConstraint, FDTerm s ~ IntTerm) => Mixin (FDConstraint s -> Tree s Bool)+basicCompile s t (Same a (Plus b c)) = do+ va <- getAsVar a+ vb <- getAsVar b+ vc <- getAsVar c+ addT (CLinear [(va,1),(vb,-1),(vc,-1)] OEqual 0)+basicCompile s t (Same a (Minus b c)) = do+ va <- getAsVar a+ vb <- getAsVar b+ vc <- getAsVar c+ addT (CLinear [(va,1),(vb,1),(vc,1)] OEqual 0)+basicCompile s t (Same a (Mult b c)) = do+ va <- getAsVar a+ vb <- getAsVar b+ vc <- getAsVar c+ addT (CMult vb vc va)+basicCompile s t (Same a (Div b c)) = do+ va <- getAsVar a+ vb <- getAsVar b+ vc <- getAsVar c+ addT (CDiv vb vc va)+basicCompile s t (Same a (Mod b c)) = do+ va <- getAsVar a+ vb <- getAsVar b+ vc <- getAsVar c+ addT (CMod vb vc va)+basicCompile s t (Same a (Abs b)) = do+ va <- getAsVar a+ vb <- getAsVar b+ addT (CAbs vb va)+basicCompile s t (Same a@(Plus _ _) b) = basicCompile s t $ Same b a+basicCompile s t (Same a@(Minus _ _) b) = basicCompile s t $ Same b a+basicCompile s t (Same a@(Mult _ _) b) = basicCompile s t $ Same b a+basicCompile s t (Same a@(Div _ _) b) = basicCompile s t $ Same b a+basicCompile s t (Same a@(Mod _ _) b) = basicCompile s t $ Same b a+basicCompile s t (Same a@(Abs _) b) = basicCompile s t $ Same b a+basicCompile s t (Same a@(Const _) b) = basicCompile s t $ Same b a+basicCompile s t (Same a (Const i)) = do+ va <- getAsVar a+ addT (CValue va i)+basicCompile s t (x@(Same a b)) = do+ va <- getAsVar a+ vb <- getAsTerm b+ addT (CRel va OEqual vb)+basicCompile s t (Diff a b) = do+ va <- getAsVar a+ vb <- getAsTerm b+ addT (CRel va ODiff vb)+basicCompile s t (Less a b) = do+ va <- getAsVar a+ vb <- getAsTerm b+ addT (CRel va OLess vb)+basicCompile s t (Dom a l h) = do+ va <- getAsVar a+ addT (CDom va l h)+basicCompile s t (AllDiff l) = do+ vl <- mapM getAsVar l+ addT (CAllDiff vl)+basicCompile s t (Sorted l e) = do+ vl <- mapM getAsVar l+ addT (CSorted vl e)+-- basicCompile s _ x = s x++getAsVar :: (FDSolver s, Constraint s ~ GConstraint, FDTerm s ~ IntTerm) => Expr IntTerm -> Tree s IntTerm+getAsVar = decompose+getAsTerm :: (FDSolver s, Constraint s ~ GConstraint, FDTerm s ~ IntTerm) => Expr IntTerm -> Tree s IntTerm+getAsTerm (Const c) = return $ IntConst c+getAsTerm x = decompose x++-- | linear constraint compilation++linearCompile :: (FDSolver s, Constraint s ~ GConstraint, FDTerm s ~ IntTerm) => Mixin (FDConstraint s -> Tree s Bool)+linearCompile s t (Same a@(Plus _ _) b) = linearCompileX a b OEqual+linearCompile s t (Same a@(Minus _ _) b) = linearCompileX a b OEqual+linearCompile s t (Same b a@(Plus _ _)) = linearCompileX a b OEqual+linearCompile s t (Same b a@(Minus _ _)) = linearCompileX a b OEqual+linearCompile s t (Diff a@(Plus _ _) b) = linearCompileX a b ODiff+linearCompile s t (Diff a@(Minus _ _) b) = linearCompileX a b ODiff+linearCompile s t (Diff a b@(Plus _ _)) = linearCompileX a b ODiff+linearCompile s t (Diff a b@(Minus _ _)) = linearCompileX a b ODiff+linearCompile s t (Less a@(Plus _ _) b) = linearCompileX a b OLess+linearCompile s t (Less a@(Minus _ _) b) = linearCompileX a b OLess+linearCompile s t (Less a b@(Plus _ _)) = linearCompileX a b OLess+linearCompile s t (Less a b@(Minus _ _)) = linearCompileX a b OLess+linearCompile s t x = s x++linearCompileX a b o = + do t1 <- linearExprCompile a+ t2 <- linearExprCompile b+ let (x,a,c) = linearAdd t1 t2 1 (-1)+ addT (CLinear (filter (\(_,a) -> a /= 0) $ map (\(xe,ae) -> (IntVar xe,ae)) $ zip x a) o c)++linearExprCompile :: (FDSolver s, Constraint s ~ GConstraint, FDTerm s ~ IntTerm) => Expr (FDTerm s) -> Tree s ([Int],[Integer],Integer)+linearExprCompile (Term (IntVar i)) = + return ([i],[1],0)+linearExprCompile (Term (IntConst c)) = + return ([],[],-c)+linearExprCompile (Const c) = + return ([],[],-c)+linearExprCompile (Plus a b) = + do t1 <- linearExprCompile a+ t2 <- linearExprCompile b+ return $ linearAdd t1 t2 1 1+linearExprCompile (Minus a b) = + do t1 <- linearExprCompile a+ t2 <- linearExprCompile b+ return $ linearAdd t1 t2 1 (-1)+linearExprCompile (Mult (Const c) a) = + do t <- linearExprCompile a+ return $ linearAdd t ([],[],0) c 1+linearExprCompile (Mult a (Const c)) = + linearExprCompile (Mult (Const c) a)+linearExprCompile x =+ do (IntVar i) <- getAsVar x+ return ([i],[1],0)++linearAdd (x1,a1,c1) (x2,a2,c2) m1 m2 = case (x1,a1) of+ ([],[]) -> (x2,map (*m2) a2,m1*c1+m2*c2)+ (x1e:x1s,a1e:a1s) -> linearAdd (x1s,a1s,c1) (linearAddTerm (x2,a2,c2) x1e a1e m2 m1 [] []) m1 1++linearAddTerm (x1,a1,c1) x2e a2e m1 m2 xc ac = case (x1,a1) of+ ([],[]) -> (x2e:xc,(a2e*m2):ac,c1*m1)+ (x1e:x1s,a1e:a1s) -> if x1e == x2e+ then ((x2e:x1s) ++ xc,((a1e*m1+a2e*m2):(map (*m1) a1s)) ++ ac,c1*m1)+ else linearAddTerm (x1s,a1s,c1) x2e a2e m1 m2 (x1e:xc) ((a1e*m1):ac)++-- | utility++orElse :: Maybe a -> Maybe a -> Maybe a+orElse = mplus
+ Control/CP/FD/Gecode/Interface.hsc view
@@ -0,0 +1,173 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++{-# CFILES glue/interface.cpp #-}++module Control.CP.FD.Gecode.Interface (+ CGOperator(..),+ CGIntVar(..),+ CGBoolVar(..),+ CGBool(..),+ CGVal(..),+ toCGIntVar,+ toCGBoolVar,+ toCGVal,+ fromCGVal,+ toCGBool,+ fromCGBool,+ Space,+ Search,+ newSpace,+ copySpace,+ newSearch,+ runSearch,+ IntTermInfo(..),+ getIntTermInfo,+ mapGOperator,+ c_gecode_int_dom,+ c_gecode_int_rel,+ c_gecode_int_rel_cf,+ c_gecode_int_rel_cs,+ c_gecode_int_value,+ c_gecode_int_mult,+ c_gecode_int_div,+ c_gecode_int_mod,+ c_gecode_int_abs,+ c_gecode_int_linear,+ c_gecode_int_alldiff,+ c_gecode_int_sorted,+ c_gecode_int_newvar,+ c_gecode_int_branch,+ c_gecode_bool_newvar+) where++#ifdef RGECODE++import Foreign+import Foreign.C+import Foreign.C.Types+import Foreign.ForeignPtr++import Control.CP.FD.Gecode.Common++#include "gecodeglue.h"++newtype CGOperator = CGOperator CInt+ deriving Storable+newtype CGIntVar = CGIntVar CInt+ deriving Storable+newtype CGBoolVar = CGBoolVar CInt+ deriving Storable+newtype CGBool = CGBool CInt+ deriving Storable+newtype CGVal = CGVal CInt+ deriving Storable++mapGOperator :: GOperator -> CGOperator+mapGOperator OEqual = CGOperator #const GOPERATOR_OEQUAL+mapGOperator ODiff = CGOperator #const GOPERATOR_ODIFF+mapGOperator OLess = CGOperator #const GOPERATOR_OLESS++newtype GecodeModel = GecodeModel (Ptr GecodeModel)+newtype GecodeSearch = GecodeSearch (Ptr GecodeSearch)++foreign import ccall unsafe "gecode_model_create" c_gecode_model_create :: IO (Ptr GecodeModel)+foreign import ccall unsafe "gecode_model_destroy" c_gecode_model_destroy :: Ptr GecodeModel -> IO ()+foreign import ccall unsafe "&gecode_model_destroy" c_gecode_model_finalize :: FunPtr (Ptr GecodeModel -> IO ())+foreign import ccall unsafe "gecode_model_copy" c_gecode_model_copy :: Ptr GecodeModel -> IO (Ptr GecodeModel)+foreign import ccall unsafe "gecode_model_fail" c_gecode_model_fail :: Ptr GecodeModel -> IO ()+foreign import ccall unsafe "gecode_int_newvar" c_gecode_int_newvar :: Ptr GecodeModel -> IO CGIntVar+foreign import ccall unsafe "gecode_int_rel" c_gecode_int_rel :: Ptr GecodeModel -> CGIntVar -> CGOperator -> CGIntVar -> IO CGBool+foreign import ccall unsafe "gecode_int_rel_cf" c_gecode_int_rel_cf :: Ptr GecodeModel -> CGVal -> CGOperator -> CGIntVar -> IO CGBool+foreign import ccall unsafe "gecode_int_rel_cs" c_gecode_int_rel_cs :: Ptr GecodeModel -> CGIntVar -> CGOperator -> CGVal -> IO CGBool+foreign import ccall unsafe "gecode_int_value" c_gecode_int_value :: Ptr GecodeModel -> CGIntVar -> CGVal -> IO CGBool+foreign import ccall unsafe "gecode_int_mult" c_gecode_int_mult :: Ptr GecodeModel -> CGIntVar -> CGIntVar -> CGIntVar -> IO CGBool+foreign import ccall unsafe "gecode_int_div" c_gecode_int_div :: Ptr GecodeModel -> CGIntVar -> CGIntVar -> CGIntVar -> IO CGBool+foreign import ccall unsafe "gecode_int_mod" c_gecode_int_mod :: Ptr GecodeModel -> CGIntVar -> CGIntVar -> CGIntVar -> IO CGBool+foreign import ccall unsafe "gecode_int_abs" c_gecode_int_abs :: Ptr GecodeModel -> CGIntVar -> CGIntVar -> IO CGBool+foreign import ccall unsafe "gecode_int_dom" c_gecode_int_dom :: Ptr GecodeModel -> CGIntVar -> CGVal -> CGVal -> IO CGBool+foreign import ccall unsafe "gecode_int_linear" c_gecode_int_linear :: Ptr GecodeModel -> CInt -> Ptr CGIntVar -> Ptr CGVal -> CGOperator -> CGVal -> IO CGBool+foreign import ccall unsafe "gecode_int_alldiff" c_gecode_int_alldiff :: Ptr GecodeModel -> CInt -> Ptr CGIntVar -> IO CGBool+foreign import ccall unsafe "gecode_int_sorted" c_gecode_int_sorted :: Ptr GecodeModel -> CInt -> Ptr CGIntVar -> CGBool -> IO CGBool+foreign import ccall unsafe "gecode_int_info" c_gecode_int_info :: Ptr GecodeModel -> CGIntVar -> Ptr CGVal -> Ptr CGVal -> Ptr CGVal -> Ptr CInt -> Ptr CGVal -> IO ()+foreign import ccall unsafe "gecode_int_branch" c_gecode_int_branch :: Ptr GecodeModel -> CInt -> Ptr CGIntVar -> IO ()+foreign import ccall unsafe "gecode_bool_newvar" c_gecode_bool_newvar :: Ptr GecodeModel -> IO CGBoolVar+foreign import ccall unsafe "gecode_bool_branch" c_gecode_bool_branch :: Ptr GecodeModel -> CInt -> Ptr CGBoolVar -> IO ()++foreign import ccall unsafe "gecode_search_create" c_gecode_search_create :: Ptr GecodeModel -> IO (Ptr GecodeSearch)+foreign import ccall unsafe "&gecode_search_destroy" c_gecode_search_finalize :: FunPtr (Ptr GecodeSearch -> IO ())+foreign import ccall unsafe "gecode_search_destroy" c_gecode_search_destroy :: Ptr GecodeSearch -> IO ()+foreign import ccall unsafe "gecode_search_next" c_gecode_search_next :: Ptr GecodeSearch -> IO (Ptr GecodeModel)++---- accessor functions++toCGIntVar :: Integral a => a -> CGIntVar+toCGIntVar n = CGIntVar $ fromIntegral n++toCGBoolVar :: Integral a => a -> CGBoolVar+toCGBoolVar n = CGBoolVar $ fromIntegral n++toCGVal :: Integral a => a -> CGVal+toCGVal n = CGVal $ fromIntegral n++fromCGVal :: Num a => CGVal -> a+fromCGVal (CGVal x) = fromIntegral x++toCGBool :: Bool -> CGBool+toCGBool n = CGBool $ if n then 1 else 0++fromCGBool :: CGBool -> Bool+fromCGBool (CGBool x) = x /= 0++type Space = ForeignPtr GecodeModel+type Search = ForeignPtr GecodeSearch++newSpace :: IO Space+newSpace = do+ x <- c_gecode_model_create+ newForeignPtr c_gecode_model_finalize x++copySpace :: Space -> IO Space+copySpace s = withForeignPtr s $ \ptr -> do+ x <- c_gecode_model_copy ptr+ newForeignPtr c_gecode_model_finalize x++newSearch :: Space -> IO Search+newSearch s = withForeignPtr s $ \ptr -> do+ x <- c_gecode_search_create ptr+ newForeignPtr c_gecode_search_finalize x++runSearch :: Search -> IO (Maybe Space)+runSearch s = withForeignPtr s $ \ptr -> do+ x <- c_gecode_search_next ptr+ if (x == nullPtr)+ then return Nothing+ else do+ res <- newForeignPtr c_gecode_model_finalize x+ return $ Just res++data IntTermInfo = IntTermInfo { iti_low :: CInt, iti_high :: CInt, iti_med :: CInt, iti_size :: CInt, iti_val :: Maybe CInt }++getIntTermInfo :: Integral a => Space -> a -> IO IntTermInfo+getIntTermInfo s i = do+ alloca $ \pLow ->+ alloca $ \pHigh ->+ alloca $ \pMed ->+ alloca $ \pSize ->+ alloca $ \pVal -> do+ withForeignPtr s $ \ptr -> c_gecode_int_info ptr (toCGIntVar i) pLow pHigh pMed pSize pVal+ vLow <- peek pLow+ vHigh <- peek pHigh+ vMed <- peek pMed+ vSize <- peek pSize+ vVal <- peek pVal+ return $ IntTermInfo {+ iti_low = fromCGVal vLow,+ iti_high = fromCGVal vHigh,+ iti_med = fromCGVal vMed,+ iti_size = fromIntegral vSize,+ iti_val = if (vSize==1) then Just (fromCGVal vVal) else Nothing + }++#endif
+ Control/CP/FD/Gecode/RuntimeSolver.hs view
@@ -0,0 +1,291 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE MultiParamTypeClasses #-}++#ifdef RGECODE++module Control.CP.FD.Gecode.RuntimeSolver (+ SearchSolver(..),+ RuntimeSolver(..)+) where++import Maybe (fromMaybe,catMaybes,isJust,fromJust)+import List (findIndex,find)+import Data.Map hiding (map,filter)++import Control.Monad.State.Lazy+import Control.Monad.Trans+import Control.Monad.Cont++import Data.Bits+import Data.Word+import Foreign+import Foreign.Storable+import Foreign.Marshal+import Foreign.Marshal.Array+import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.C.String+import Foreign.C.Types++import Control.CP.SearchTree hiding (label)+import Control.CP.Solver+import Control.CP.FD.FD+import Control.CP.FD.Expr+import Control.CP.Debug+import Control.CP.Mixin+import Control.CP.EnumTerm++import Control.CP.FD.Gecode.Common+import Control.CP.FD.Gecode.Interface++class (Monad s, MonadState (GecodeState s) s, MonadIO s, Term s IntTerm) => RuntimeGecodeSolver s where+ stateM :: s a -> StateT (GecodeState s) IO a++instance Solver RuntimeSolver where+ type Constraint RuntimeSolver = GConstraint+ type Label RuntimeSolver = GecodeState RuntimeSolver+ add = addRuntimeGecode+ run = fst . runRuntimeGecode False+ mark = do+ s <- get+ copyState s+ goto s = do+ x <- copyState s+ put x++instance Solver SearchSolver where+ type Constraint SearchSolver = GConstraint+ type Label SearchSolver = GecodeState SearchSolver+ add = addRuntimeGecode+ run = fst . runRuntimeGecode False+ mark = do+ s <- get+ copyState s+ goto s = do+ x <- copyState s+ put x++--------------------------------------------------------------------------------+-- | Gecode terms+--------------------------------------------------------------------------------++instance Term SearchSolver IntTerm where+ newvar = newVarInt+ type Help SearchSolver IntTerm = ()+ help _ _ = ()+instance Term RuntimeSolver IntTerm where+ newvar = newVarInt+ type Help RuntimeSolver IntTerm = ()+ help _ _ = ()+instance Term SearchSolver BoolTerm where+ newvar = newVarBool+ type Help SearchSolver BoolTerm = ()+ help _ _ = ()+instance Term RuntimeSolver BoolTerm where+ newvar = newVarBool+ type Help RuntimeSolver BoolTerm = ()+ help _ _ = ()+ ++--------------------------------------------------------------------------------+-- | Gecode monad definition +--------------------------------------------------------------------------------++data RuntimeGecodeSolver s => GecodeState s = GecodeState { spaceRef :: Space, cexpr :: Map (ExprKey (FDTerm s)) Int }+++newtype RuntimeSolver a = RuntimeSolver { rStateM :: StateT (GecodeState RuntimeSolver) IO a }+ deriving (Monad, MonadState (GecodeState RuntimeSolver), MonadIO)+newtype SearchSolver a = SearchSolver { sStateM :: StateT (GecodeState SearchSolver) IO a }+ deriving (Monad, MonadState (GecodeState SearchSolver), MonadIO)++newState :: RuntimeGecodeSolver s => Bool -> IO (GecodeState s)+newState gcs = do+ initSpace <- newSpace+ return $ GecodeState { spaceRef = initSpace, cexpr = Data.Map.empty }++copyState :: RuntimeGecodeSolver s => GecodeState s -> s (GecodeState s)+copyState state = do+ x <- liftIO $ copySpace (spaceRef state)+ return $ state { spaceRef = x }++runRuntimeGecode :: RuntimeGecodeSolver s => Bool -> s a -> (a, GecodeState s)+runRuntimeGecode gcs p = unsafePerformIO $ do+ initState <- newState gcs+ runStateT (stateM p) initState++continueRuntimeGecode :: RuntimeGecodeSolver s => GecodeState s -> s a -> (a, GecodeState s)+continueRuntimeGecode st p = unsafePerformIO $ runStateT (stateM p) st++intTermInfo :: RuntimeGecodeSolver s => IntTerm -> s IntTermInfo+intTermInfo (IntVar i) = do+ GecodeState { spaceRef = s } <- get+ liftIO $ getIntTermInfo s i++addRuntimeGecode :: RuntimeGecodeSolver s => GConstraint -> s Bool+addRuntimeGecode (CDom (IntVar i) low high) = proc $ \ptr -> c_gecode_int_dom ptr (toCGIntVar i) (toCGVal low) (toCGVal high)+addRuntimeGecode (CRel (IntVar i1) op (IntVar i2)) = proc $ \ptr -> c_gecode_int_rel ptr (toCGIntVar i1) (mapGOperator op) (toCGIntVar i2)+addRuntimeGecode (CRel (IntConst c1) op (IntVar i2)) = proc $ \ptr -> c_gecode_int_rel_cf ptr (toCGVal c1) (mapGOperator op) (toCGIntVar i2)+addRuntimeGecode (CRel (IntVar i1) op (IntConst c2)) = proc $ \ptr -> c_gecode_int_rel_cs ptr (toCGIntVar i1) (mapGOperator op) (toCGVal c2)+addRuntimeGecode (CValue (IntVar i) val) = proc $ \ptr -> c_gecode_int_value ptr (toCGIntVar i) (toCGVal val)+addRuntimeGecode (CMult (IntVar i1) (IntVar i2) (IntVar ir)) = proc $ \ptr -> c_gecode_int_mult ptr (toCGIntVar i1) (toCGIntVar i2) (toCGIntVar ir)+addRuntimeGecode (CDiv (IntVar i1) (IntVar i2) (IntVar ir)) = proc $ \ptr -> c_gecode_int_div ptr (toCGIntVar i1) (toCGIntVar i2) (toCGIntVar ir)+addRuntimeGecode (CMod (IntVar i1) (IntVar i2) (IntVar ir)) = proc $ \ptr -> c_gecode_int_mod ptr (toCGIntVar i1) (toCGIntVar i2) (toCGIntVar ir)+addRuntimeGecode (CAbs (IntVar i) (IntVar ir)) = proc $ \ptr -> c_gecode_int_abs ptr (toCGIntVar i) (toCGIntVar ir)+addRuntimeGecode (CLinear l op val) = do+ GecodeState { spaceRef = s } <- get+ let len = length l+ let vars = map (\(IntVar var,_) -> toCGIntVar var) l+ let coefs = map (\(_,coef) -> toCGVal coef) l+ liftIO $ + withArray vars $ \pVars ->+ withArray coefs $ \pCoefs -> do+ b <- withForeignPtr s $ \ptr -> c_gecode_int_linear ptr (fromIntegral len) pVars pCoefs (mapGOperator op) (toCGVal val)+ return $ fromCGBool b+addRuntimeGecode (CAllDiff l) = do+ GecodeState { spaceRef = s } <- get+ let len = length l+ let vars = map (\(IntVar i) -> toCGIntVar i) l+ liftIO $+ withArray vars $ \pVars -> do+ b <- withForeignPtr s $ \ptr -> c_gecode_int_alldiff ptr (fromIntegral len) pVars+ return $ fromCGBool b+addRuntimeGecode (CSorted l strict) = do+ GecodeState { spaceRef = s } <- get+ let len = length l+ let vars = map (\(IntVar i) -> toCGIntVar i) l+ liftIO $+ withArray vars $ \pVars -> do+ b <- withForeignPtr s $ \ptr -> c_gecode_int_sorted ptr (fromIntegral len) pVars (toCGBool strict)+ return $ fromCGBool b++proc f = do+ GecodeState { spaceRef = s } <- get+ liftIO $ do+ b <- withForeignPtr s f+ return $ fromCGBool b++--------------------------------------------------------------------------------+-- | RuntimeSolver solver implementation+--------------------------------------------------------------------------------++newVarInt :: RuntimeGecodeSolver s => s IntTerm+newVarInt = do+ GecodeState { spaceRef = s } <- get+ (CGIntVar r) <- liftIO $ withForeignPtr s $ c_gecode_int_newvar + return (IntVar $ fromIntegral r)++newVarBool :: RuntimeGecodeSolver s => s BoolTerm+newVarBool = do+ GecodeState { spaceRef = s } <- get+ (CGBoolVar r) <- liftIO $ withForeignPtr s $ c_gecode_bool_newvar+ return (BoolVar $ fromIntegral r)++--------------------------------------------------------------------------------+-- | RuntimeSolver FDSolver instance+--------------------------------------------------------------------------------++instance (RuntimeGecodeSolver s, Ord (FDTerm s)) => GecodeSolver s where+ caching_decompose super this x = Label $ do+ s <- get+ let wx = ExprKey x+ case Data.Map.lookup wx (cexpr s) of+ Nothing -> return $ do+ n@(IntVar i) <- super x+ Label $ do+ s <- get+ put $ s { cexpr = insert wx i $ cexpr s }+ return $ return n+ Just i -> return $ return $ IntVar i+ setVarImplicit (IntVar i) b = return ()++instance FDSolver RuntimeSolver where+ type FDTerm RuntimeSolver = IntTerm+ specific_compile_constraint = linearCompile <@> basicCompile+ specific_decompose = caching_decompose+ specific_fresh_var super this = do+ v@(IntVar i) <- super+ Label $ do+ setVarImplicit (IntVar i) True+ return $ Return v++instance FDSolver SearchSolver where+ type FDTerm SearchSolver = IntTerm+ specific_compile_constraint = linearCompile <@> basicCompile+ specific_decompose = caching_decompose+ specific_fresh_var super this = do+ v@(IntVar i) <- super+ Label $ do+ setVarImplicit (IntVar i) True+ return $ Return v+++instance EnumTerm RuntimeSolver IntTerm where+ type TermDomain RuntimeSolver IntTerm = CInt+ get_domain_size v = do+ IntTermInfo { iti_size = size } <- intTermInfo v+ return $ fromIntegral size+ get_value v = do+ IntTermInfo { iti_val = val } <- intTermInfo v+ return val+ split_domain_partial v@(IntVar it) = do+ IntTermInfo { iti_val = val, iti_med = med, iti_size = size } <- intTermInfo v+ return $ if size == 0+ then []+ else if isJust val+ then [return ()]+ else [Add (CRel v OLess (IntConst $ (fromIntegral med)+1)) $ enumerate [v],Add (CRel (IntConst $ fromIntegral med) OLess v) $ enumerate [v]]+++instance EnumTerm SearchSolver IntTerm where+ type TermDomain SearchSolver IntTerm = CInt+ get_domain_size v = do+ IntTermInfo { iti_size = size } <- intTermInfo v+ return $ fromIntegral size+ get_value v = do+ IntTermInfo { iti_val = val } <- intTermInfo v+ return val+ + split_domains lst = do+ let + folder a b = case a of+ IntVar i -> (i:b)+ _ -> b+ let vars = map toCGIntVar $ foldr folder [] lst+ state <- get+ liftIO $ withArray vars $ \ptr -> withForeignPtr (spaceRef state) $ \sptr -> c_gecode_int_branch sptr (fromIntegral $ length vars) ptr+ search <- liftIO $ newSearch $ spaceRef state+ let + go i = unsafePerformIO $ do+ res <- runSearch search+ case res of+ Nothing -> return $ return ()+ Just x -> return $ Try (Label $ do+ put state { spaceRef = x }+ return $ return ()+ ) (go $ i+1)+ return $ go 0++ split_domain_partial v = do+ x <- split_domains [v]+ return [x]++ label _ = Label . split_domains+ enumerate = Label . split_domains++---------------------------------------------+-- | RuntimeGecodeSolver instances+---------------------------------------------++instance RuntimeGecodeSolver RuntimeSolver where+ stateM = rStateM++instance RuntimeGecodeSolver SearchSolver where+ stateM = sStateM++#endif
+ Control/CP/FD/Gecode/Translate.hs view
@@ -0,0 +1,203 @@+-- optimalisaties: zie http://www.cs.mu.oz.au/~pjs/papers/padl2008.pdf+-- zie ook http://www.cs.mu.oz.au/~pjs/papers/constraints08b.pdf+-- mcp paper: http://www.cs.kuleuven.be/~toms/Research/papers/monadic_cp_draft.pdf++module Control.CP.FD.Gecode.Translate (+ generate_gecode+) where++import Maybe (fromJust,isNothing,isJust)+import List (findIndex)+import Data.Map (elems,Map,lookup)++import Control.CP.FD.Gecode.CodegenSolver+import Control.CP.FD.Gecode.Common+import Control.CP.Solver++--------------------------------------------------------------------------------+-- Main compilation function+--------------------------------------------------------------------------------++generate_gecode = stateToProg . compile+-- generate_gecode = show . compile++--------------------------------------------------------------------------------+-- Implementation+--------------------------------------------------------------------------------++countTypeVars :: Store -> GType -> Int -> Int+countTypeVars s t u = foldl (+) 0 $ map (\x -> 1) $ filter (\x -> (u<0 || x<u) && (t == getVarType s x)) $ varsUsed (ctree s) []+++maxDepth :: StoreNode -> Int+maxDepth (StoreNode { cons=_, dis=SNLeaf}) = 1+maxDepth (StoreNode { cons=_, dis=SNIntl l r }) = 1 + (maxDepth l `max` maxDepth r)++typeList = [TypeBool, TypeInt]++varsUsed :: StoreNode -> [ Bool ] -> [ Int ]+varsUsed node path = (nvars node) ++ case (dis node,path) of+ (SNLeaf,_) -> []+ (SNIntl l _,[]) -> (varsUsed l [])+ (SNIntl l _,False:o) -> varsUsed l o+ (SNIntl _ r,True:o) -> varsUsed r o++typeToString :: GType -> String+typeToString TypeInt = "IntVar"+typeToString TypeBool = "BoolVar"++typeToDefArgs :: GType -> (String,String)+typeToDefArgs TypeInt = ("-1000000000","1000000000")+typeToDefArgs TypeBool = ("0","1")++getVarName :: Store -> String -> Int -> String+getVarName s pre i = pre ++ "bb" ++ (typeToString $ getVarType s i) ++ "[" ++ (show $ countTypeVars s (getVarType s i) i) ++ "]"++getName :: GTerm t => Store -> String -> t -> String+getName s pre v = case (getVarId v) of+ Nothing -> case (getIntValue v) of+ Nothing -> error "oei"+ Just n -> show n+ Just i -> getVarName s pre i++stateToExplList :: Store -> [ (String,String,String) ]+stateToExplList s = map (fm) $ filter (\x -> not $ isVarImplicit s x) $ [0..((vars s)-1)]+ where fm i = (typeToString $ getVarType s i,"v"++(show i),getVarName s "" i)++stateToConstList :: Store -> Map Int VarBound -> [ String ]+stateToConstList s b = map fm $ elems $ b+ where fm (VarBound i l u) = (getVarName s "" i) ++ "(*this," ++ (if isJust l then show $ fromJust l else defl) ++ "," ++ (if isJust u then show $ fromJust u else defu) ++ ")"+ where (defl,defu) = typeToDefArgs $ getVarType s i++gopToGCRel :: GOperator -> String+gopToGCRel OEqual = "IRT_EQ"+gopToGCRel ODiff = "IRT_NQ"+gopToGCRel OLess = "IRT_LE"++gopToInvGCRel :: GOperator -> String+gopToInvGCRel OEqual = "IRT_EQ"+gopToInvGCRel ODiff = "IRT_NQ"+gopToInvGCRel OLess = "IRT_GR"++stateToPostList :: Store -> [ GConstraint ] -> [ String ]+stateToPostList s c = map fm $ reverse $ c+ where fm (CRel t1 o t2) = "rel(home," ++ (gn t1) ++ "," ++ (gopToGCRel o) ++ "," ++ (gn t2) ++ ")"+ fm (CMult t1 t2 t3) = "mult(home," ++ (gn t1) ++ "," ++ (gn t2) ++ "," ++ (gn t3) ++ ")"+ fm (CDiv t1 t2 t3) = "div(home," ++ (gn t1) ++ "," ++ (gn t2) ++ "," ++ (gn t3) ++ ")"+ fm (CMod t1 t2 t3) = "mod(home," ++ (gn t1) ++ "," ++ (gn t2) ++ "," ++ (gn t3) ++ ")"+ fm (CAbs t1 t2) = "abs(home," ++ (gn t1) ++ "," ++ (gn t2) ++ ")"+ fm (CDom t l u) = "dom(home," ++ (gn t) ++ "," ++ (show l) ++ "," ++ (show u) ++ ")"+ fm (CValue t v) = "rel(home," ++ (gn t) ++ ",IRT_EQ," ++ (show v) ++ ")"+ fm (CLinear l o c) = case (c,l) of+ (0,[(v1,a),(v2,b)]) | a+b==0 && a>0 -> "rel(home," ++ (gn v1) ++ "," ++ (gopToGCRel o) ++ "," ++ (gn v2) ++ ")"+ (0,[(v1,a),(v2,b)]) | a+b==0 && a<0 -> "rel(home," ++ (gn v1) ++ "," ++ (gopToInvGCRel o) ++ "," ++ (gn v2) ++ ")"+ (_,[(v1,a)]) | a>0 && ((c `mod` a)==0) -> "rel(home," ++ (gn v1) ++ "," ++ (gopToGCRel o) ++ "," ++ (show (c `div` a)) ++ ")"+ (_,[(v1,a)]) | a<0 && ((c `mod` (-a))==0) -> "rel(home," ++ (gn v1) ++ "," ++ (gopToInvGCRel o) ++ "," ++ (show (c `div` a)) ++ ")"+ (_,l) | all (\(_,a) -> a==1) l -> case unzip l of+ (x,a) -> "{ " ++ (bl "iva" x) ++ " linear(home,iva," ++ (gopToGCRel o) ++ "," ++ (show c) ++ "); }"+ _ -> case unzip l of+ (x,a) -> "{ IntArgs ia(" ++ (show $ length a) ++ (foldl (\x y -> x ++ "," ++ (show y)) "" a) ++ "); "++(bl "iva" x) ++ " linear(home,ia,iva," ++ (gopToGCRel o) ++ "," ++ (show c) ++ "); }"+ fm (CAllDiff l) = "{ " ++ (bl "ia" l) ++ "; distinct(home,ia); }"+ fm (CSorted l e) = "{ " ++ (bl "ia" l) ++ "; rel(home,ia,"++(if e then "IRT_LQ" else "IRT_LE")++"); }"+ gn t = getName s "p->" t+ bl n l = "IntVarArgs "++n++"(" ++ (show $ length l) ++ "); " ++ (foldl (++) "" (map (\i -> n++"[" ++ (show i) ++ "]=" ++ (getVarName s "p->" $ fromJust $ getVarId $ l !! i) ++ "; ") [0..(length l)-1]))++stateToBranchList :: Store -> GType -> [ String ]+stateToBranchList s t = map fm $ filter ff $ [0..((vars s)-1)]+ where ff i = (not $ isVarImplicit s i) && (t == getVarType s i)+ fm i = getVarName s "" i++stateToBranchCode s t = " " ++ tn ++ "Args b" ++ tn ++ "(" ++ (show (length vars)) ++ ");\n" ++ (+ foldl (\x y -> x ++ " b" ++ tn ++ "[" ++ (show y) ++ "]=" ++ (vars !! y) ++ ";\n") "" [0..(length vars)-1]) +++ " branch(*this, b"++tn++", INT_VAR_SIZE_MIN, INT_VAL_SPLIT_MIN);\n"+ where tn = typeToString t+ vars = stateToBranchList s t++stateToBranches s = foldl (++) [] $ map (stateToBranchCode s) typeList++-- countExplicits :: Store -> GType -> Int+-- countExplicits s t = foldl (+) 0 $ map (\x -> if isVarImplicit s x then 0 else 1) $ filter (\x -> t == getVarType s x) $ varsUsed (ctree s) []++nodeToProg :: Store -> Map Int VarBound -> StoreNode -> [ Bool ] -> String+nodeToProg store bnds node path = + " static void node" ++ pathS ++ "(Space &home) {\n" +++ " /* varsused" ++ (show vrs) ++ "*/\n" +++ " HaskellProg *p = (HaskellProg *)(&home);\n" +++ (foldl (\x y -> x ++ " " ++ y ++ ";\n") "" $ map (\x -> (getVarName store "p->" x)++".init(home,"++(lowest x)++","++(highest x)++")") $ nvars node) +++ (foldl (\x y -> x ++ " " ++ y ++ ";\n") "" $ stateToPostList store $ cons node) +++ (case dis node of + SNLeaf -> (foldl (++) "" $ map (\x -> " rel(home,p->i["++(show x)++"],IRT_EQ,0);\n") [(length path)..(maxDepth $ ctree store)-2]) ++ + (foldl (++) "" $ map (\x -> " rel(home," ++ (getVarName store "p->" x) ++ ",IRT_EQ,"++(lowest x)++");\n") $ filter (\x -> isNothing $ findIndex (== x) vrs) [0..(vars store)-1])+ SNIntl _ _ -> " when(home,p->i[" ++ lenS ++ "],&node"++pathS++"R,&node"++pathS++"L);\n"+ ) +++ " }\n" +++ (case (dis node) of+ SNLeaf -> ""+ SNIntl l r -> nodeToProg store bnds l (path ++ [ False ]) ++ nodeToProg store bnds r (path ++ [ True ])+ )+ where pathS = foldl (++) "" $ map (\x -> if x then "R" else "L") path+ lenS = show $ length path+ vrs = varsUsed (ctree store) path+ lowest i = case Data.Map.lookup i bnds of+ Nothing -> case typeToDefArgs $ getVarType store i of+ (x,_) -> x+ Just (VarBound _ Nothing _) -> case typeToDefArgs $ getVarType store i of+ (x,_) -> x+ Just (VarBound _ (Just l) _) -> show l+ highest i = case Data.Map.lookup i bnds of+ Nothing -> case typeToDefArgs $ getVarType store i of+ (_,x) -> x+ Just (VarBound _ _ Nothing) -> case typeToDefArgs $ getVarType store i of+ (_,x) -> x+ Just (VarBound _ _ (Just l)) -> show l+ ++stateToProg :: Store -> String+stateToProg s = + "#include \"gecode/kernel.hh\"\n"+++ "#include \"gecode/support.hh\"\n"++ + "#include \"gecode/int.hh\"\n"+++ "#include \"gecode/search.hh\"\n"+++ "#include \"gecode/minimodel.hh\"\n"+++ "\n"+++ "using namespace Gecode;\n"+++ "\n"+++ "class HaskellProg : public Space {\n"+++ "protected:\n"+++-- (foldl (\x (y1,y2) -> x ++ " " ++ y1 ++ " " ++ y2 ++ ";\n") "" (stateToDefList s)) ++ + " BoolVarArray i;\n\n"+++ (foldl (++) "" $ map (\x -> " " ++ (typeToString x) ++ "Array bb" ++ (typeToString x) ++ ";\n") typeList) +++ "public:\n"+++ " HaskellProg() : " ++ + (foldl (\x y -> (if x=="" then "" else x ++ ", ") ++ y) "" $ map (\x -> "bb" ++ typeToString x ++ "(*this," ++ (show $ countTypeVars s x (-1)) ++ ")") typeList) ++ + ", i(*this,"++(show $ (maxDepth (ctree s)) - 1)++",0,1) {\n"+++ " node(*this);\n"+++ " branch(*this, i, INT_VAR_SIZE_MIN, INT_VAL_MIN);\n" ++ stateToBranches s +++ " };\n"+++ " virtual void print(std::ostream& os) {\n"+++ (foldl (\x (vType,vName,vExpr) -> x ++ " os << \"" ++ vName ++ ": \" << " ++ vExpr ++ " << std::endl;\n") "" (stateToExplList s)) +++ " }\n"+++ " HaskellProg(bool share, HaskellProg &s) : Space(share,s) {\n"+++-- (foldl (\x (vType,vName,vExpr) -> x ++ " " ++ vExpr ++ ".update(*this, share, s." ++ vExpr ++ ");\n") "" (stateToExplList s)) +++ " i.update(*this,share,s.i);\n" +++ (foldl (\x y -> x ++ " " ++ y ++ ";\n") "" $ map (\x -> "bb" ++ (typeToString x) ++ ".update(*this,share,s.bb"++(typeToString x)++")") typeList) +++ " }\n"+++ " virtual Space* copy(bool share) {\n"+++ " return new HaskellProg(share, *this);\n"+++ " }\n"+++ nodeToProg s bounds (ctree s) [] +++ "};\n"+++ "\n"+++ "int main(void) {\n"+++ " HaskellProg *prog=new HaskellProg();\n"+++ " DFS<HaskellProg> srch(prog);\n"+++ " delete prog;\n"+++ " do {\n"+++ " HaskellProg *sol=srch.next();\n"+++ " if (sol==NULL) break;\n"+++ " sol->print(std::cout);\n"+++ " } while(0);\n"+++ " return 0;\n"+++ "}\n"+ where bounds = getAllBounds s+ vrs = varsUsed (ctree s) []
+ Control/CP/FD/OvertonFD/Domain.hs view
@@ -0,0 +1,176 @@+{- + - Origin:+ - Constraint Programming in Haskell + - http://overtond.blogspot.com/2008/07/pre.html+ - author: David Overton, Melbourne Australia+ -+ - Modifications:+ - Monadic Constraint Programming+ - http://www.cs.kuleuven.be/~toms/Haskell/+ - Tom Schrijvers+ -} ++{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE IncoherentInstances #-}+{-# LANGUAGE UndecidableInstances #-}++module Control.CP.FD.OvertonFD.Domain (+ Domain,+ ToDomain,+ toDomain,+ member,+ isSubsetOf,+ elems,+ intersection,+ difference,+ union,+ empty,+ null,+ singleton,+ isSingleton,+ filterLessThan,+ filterGreaterThan,+ findMax,+ findMin,+ size,+ shiftDomain,+ mapDomain+) where++import qualified Data.IntSet as IntSet+import Data.IntSet (IntSet)+import Prelude hiding (null)+import Control.CP.Debug++data Domain+ = Set IntSet+ | Range Int Int+ deriving Show++size :: Domain -> Int+size (Range l u) = u - l + 1+size (Set set) = IntSet.size set++-- Domain constructors+class ToDomain a where+ toDomain :: a -> Domain++instance ToDomain Domain where+ toDomain = id++instance ToDomain IntSet where+ toDomain = Set++instance Integral a => ToDomain [a] where+ toDomain = toDomain . IntSet.fromList . map fromIntegral++instance (Integral a, Integral b) => ToDomain (a, b) where+ toDomain (a, b) = Range (fromIntegral a) (fromIntegral b)++instance ToDomain () where+ toDomain () = Range (-10000) 10000 -- minBound maxBound (too sensitive to overflow, e.g. 2 * minBound == 0)++instance Integral a => ToDomain a where+ toDomain a = toDomain (a, a)++-- Operations on Domains+instance Eq Domain where+ (Range xl xh) == (Range yl yh) = xl == yl && xh == yh+ xs == ys = elems xs == elems ys++member :: Int -> Domain -> Bool+member n x@(Set xs) = debugDom "[Domain.member]" x $ n `IntSet.member` xs+member n x@(Range xl xh) = debugDom "[Domain.member]" x $ n >= xl && n <= xh++isSubsetOf :: Domain -> Domain -> Bool+isSubsetOf x@(Set xs) (Set ys) = debugDom "[Domain.isso]" x $ xs `IntSet.isSubsetOf` ys+isSubsetOf x@(Range xl xh) (Range yl yh) = debugDom "[Domain.isso]" x $ xl >= yl && xh <= yh+isSubsetOf x@(Set xs) yd@(Range yl yh) = debugDom "[Domain.isso]" x $ + isSubsetOf (Range xl xh) yd where+ xl = IntSet.findMin xs+ xh = IntSet.findMax xs+isSubsetOf (Range xl xh) x@(Set ys) = debugDom "[Domain.isso]" x $ + all (`IntSet.member` ys) [xl..xh]++elems :: Domain -> [Int]+elems x@(Set xs) = debugDom "[Domain.elems]" x $ IntSet.elems xs+elems x@(Range xl xh) = debugDom "[Domain.elems]" x $ [xl..xh]++intersection :: Domain -> Domain -> Domain+intersection x@(Set xs) (Set ys) = debugDom "[Domain.intersection]" x $ Set (xs `IntSet.intersection` ys)+intersection x@(Range xl xh) (Range yl yh) = debugDom "[Domain.intersection]" x $ Range (max xl yl) (min xh yh)+intersection x@(Set xs) (Range yl yh) = debugDom "[Domain.intersection]" x $ + Set $ IntSet.filter (\x -> x >= yl && x <= yh) xs+intersection x y = intersection y x++union :: Domain -> Domain -> Domain+union x@(Set xs) (Set ys) = debugDom "[Domain.union]" x $ Set (xs `IntSet.union` ys)+union x@(Range xl xh) (Range yl yh) + | xh + 1 >= yl || yh+1 >= xl = debugDom "[Domain.union]" x $ Range (min xl yl) (max xh yh)+ | otherwise = debugDom "[Domain.union]" x $ union (Set $ IntSet.fromList [xl..xh]) (Set $ IntSet.fromList [yl..yh]) +union x@(Set xs) y@(Range yl yh) = debugDom "[Domain.union]" x $ + if null x then y + else+ let xmin = IntSet.findMin xs+ xmax = IntSet.findMax xs+ in + if (xmin + 1 >= yl && xmax - 1 <= yh) + then Range (min xmin yl) (max xmax yh)+ else union (Set xs) (Set $ IntSet.fromList [yl..yh])+union x y = union y x++difference :: Domain -> Domain -> Domain+difference (x@(Set xs)) (y@(Set ys)) = debugDom "[Domain.difference]" x $ Set (xs `IntSet.difference` ys)+difference xd@(Range xl xh) (Range yl yh)+ | yl > xh || yh < xl = debugDom "[Domain.difference]" xd $ xd+ | otherwise = debugDom "[Domain.difference]" xd $ Set $ IntSet.fromList [x | x <- [xl..xh], x < yl || x > yh]+difference (x@(Set xs)) (Range yl yh) =+ debugDom "[Domain.difference]" x $ Set $ IntSet.filter (\x -> x < yl || x > yh) xs+difference (x@(Range xl xh)) (Set ys)+ | IntSet.findMin ys > xh || IntSet.findMax ys < xl = debugDom "[Domain.difference]" x $ Range xl xh+ | otherwise = debugDom "[Domain.difference]" x $ Set $+ IntSet.fromList [x | x <- [xl..xh], not (x `IntSet.member` ys)]++null :: Domain -> Bool+null (x@(Set xs)) = debug ("[Domain.null] " ++ printDom x) $ IntSet.null xs+null (x@(Range xl xh)) = debug ("[Domain.null] " ++ printDom x) $ xl > xh++singleton :: Int -> Domain+singleton x = Set (IntSet.singleton x)++isSingleton :: Domain -> Bool+isSingleton (x@(Set xs)) = debugDom "[Domain.isSingleton]" x $ (IntSet.size xs)==1+isSingleton (x@(Range xl xh)) = debug ("[Domain.isSingleton] " ++ printDom x) $ xl == xh++filterLessThan :: Int -> Domain -> Domain+filterLessThan n (x@(Set xs)) = debug ("[Domain.filterLess] " ++ printDom x) $ Set $ IntSet.filter (< n) xs+filterLessThan n (x@(Range xl xh)) = debug ("[Domain.filterLess] " ++ printDom x) $ Range xl (min (n-1) xh)++filterGreaterThan :: Int -> Domain -> Domain+filterGreaterThan n (x@(Set xs)) = debug ("[Domain.filterGreater] " ++ printDom x) $ Set $ IntSet.filter (> n) xs+filterGreaterThan n (x@(Range xl xh)) = debug ("[Domain.filterGreater] " ++ printDom x) $ Range (max (n+1) xl) xh++findMax :: Domain -> Int+findMax (x@(Set xs)) = debug ("[Domain.findMax] " ++ printDom x) $ IntSet.findMax xs+findMax (x@(Range xl xh)) = debug ("[Domain.findMax] " ++ printDom x) $ xh++findMin :: Domain -> Int+findMin (Set xs) = IntSet.findMin xs+findMin (Range xl xh) = xl++empty :: Domain+empty = Range 1 0++shiftDomain :: Domain -> Int -> Domain+shiftDomain (x@(Range l u)) d = debug ("[Domain.shift] " ++ printDom x) $ Range (l + d) (u + d)+shiftDomain (x@(Set xs)) d = debug ("[Domain.shift] " ++ printDom x) $ Set $ IntSet.fromList $ map (+d) (IntSet.elems xs)++mapDomain :: Domain -> (Int -> [Int]) -> Domain+mapDomain d f = debug ("[Domain.map] " ++ printDom d) $ Set $ IntSet.fromList $ concatMap f $ elems d++printDom :: Domain -> String+printDom (Set cs) = "dom:Set(#" ++ (show $ IntSet.size cs) ++ ")"+printDom (Range l h) = "dom:Range(#" ++ (show $ h-l+1) ++ ":" ++ (show l) ++ "-" ++ (show h) ++ ")"++debugDom :: String -> Domain -> a -> a+debugDom s d a = debug ("[Domain.findMax] " ++ printDom d) a
+ Control/CP/FD/OvertonFD/OvertonFD.hs view
@@ -0,0 +1,384 @@+{- + - Origin:+ - Constraint Programming in Haskell + - http://overtond.blogspot.com/2008/07/pre.html+ - author: David Overton, Melbourne Australia+ -+ - Modifications:+ - Monadic Constraint Programming+ - http://www.cs.kuleuven.be/~toms/Haskell/+ - Tom Schrijvers+ -} ++-- {-# OPTIONS_GHC -fglasgow-exts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Control.CP.FD.OvertonFD.OvertonFD (+ OvertonFD,+ fd_objective,+ fd_domain,+ FDVar,+ OConstraint(..),+) where++import Prelude hiding (lookup)+import Maybe (fromJust,isJust)+import Control.Monad.State.Lazy+import Control.Monad.Trans+import qualified Data.Map as Map+import Data.Map ((!), Map)+import Control.Monad (liftM,(<=<))++import Control.CP.FD.OvertonFD.Domain as Domain+import Control.CP.FD.FD+import Control.CP.EnumTerm+import Control.CP.Solver+import Control.CP.SearchTree++import Control.CP.Debug++--------------------------------------------------------------------------------+-- Solver instance -------------------------------------------------------------+--------------------------------------------------------------------------------++data OConstraint =+ OHasValue FDVar Int+ | OSame FDVar FDVar+ | ODiff FDVar FDVar+ | OLess FDVar FDVar+ | OAdd FDVar FDVar FDVar+ | OSub FDVar FDVar FDVar+ | OMult FDVar FDVar FDVar+ | OAbs FDVar FDVar++instance Solver OvertonFD where+ type Constraint OvertonFD = OConstraint+ type Label OvertonFD = FDState+ add c = addFD c+ run p = runFD p+ mark = get+ goto = put ++instance Term OvertonFD FDVar where+ newvar = newVar ()+ type Help OvertonFD FDVar = ()+ help _ _ = ()++instance EnumTerm OvertonFD FDVar where+ type TermDomain OvertonFD FDVar = Int+ get_domain_size v = do+ dom <- debug "get_domain_size:fd_domain" $ fd_domain v+ return $ length dom+ split_domain_partial v = do+ dom <- debug "split_domain:fd_domain" $ fd_domain v+ case dom of+ [] -> return [ return () ]+ _ -> return [ addC $ v `OHasValue` c | c <- dom ]+ get_value v = do+ x <- debug "get_value:fd_domain" $ fd_domain v+ case x of+ [val] -> return $ Just val+ _ -> return Nothing++--------------------------------------------------------------------------------+-- Constraints -----------------------------------------------------------------+--------------------------------------------------------------------------------++addFD (OHasValue v i) = v `hasValue` i+addFD (OSame a b) = a `same` b+addFD (ODiff a b) = a `different` b+addFD (OLess a b) = a .<. b+addFD (OAdd a b c) = addSum a b c+addFD (OSub a b c) = addSub a b c+addFD (OMult a b c) = addMult a b c+addFD (OAbs a b) = addAbs a b++fd_domain :: FDVar -> OvertonFD [Int]+fd_domain v = do d <- lookup v+ return $ elems d++fd_objective :: OvertonFD FDVar+fd_objective =+ do s <- get+ return $ objective s++--------------------------------------------------------------------------------++-- The FD monad+newtype OvertonFD a = OvertonFD { unFD :: StateT FDState Maybe a }+ deriving (Monad, MonadState FDState, MonadPlus)++-- FD variables+newtype FDVar = FDVar { unFDVar :: Int } deriving (Ord, Eq, Show)++type VarSupply = FDVar++data VarInfo = VarInfo+ { delayedConstraints :: OvertonFD Bool, domain :: Domain }++instance Show VarInfo where+ show x = show $ domain x++type VarMap = Map FDVar VarInfo++data FDState = FDState+ { varSupply :: VarSupply, varMap :: VarMap, objective :: FDVar }+ deriving Show++instance Eq FDState where+ s1 == s2 = f s1 == f s2+ where f s = head $ elems $ domain $ varMap s ! (objective s) ++instance Ord FDState where+ compare s1 s2 = compare (f s1) (f s2)+ where f s = head $ elems $ domain $ varMap s ! (objective s) ++ -- TOM: inconsistency is not observable within the OvertonFD monad+consistentFD :: OvertonFD Bool+consistentFD = return True++-- Run the FD monad and produce a lazy list of possible solutions.+runFD :: OvertonFD a -> a+runFD fd = fromJust $ evalStateT (unFD fd') initState+ where fd' = fd -- fd' = newVar () >> fd++initState :: FDState+initState = FDState { varSupply = FDVar 0, varMap = Map.empty, objective = FDVar 0 }++-- Get a new FDVar+newVar :: ToDomain a => a -> OvertonFD FDVar+newVar d = do+ s <- get+ let v = varSupply s+ put $ s { varSupply = FDVar (unFDVar v + 1) }+ modify $ \s ->+ let vm = varMap s+ vi = VarInfo {+ delayedConstraints = return True,+ domain = toDomain d}+ in+ s { varMap = Map.insert v vi vm }+ return v++newVars :: ToDomain a => Int -> a -> OvertonFD [FDVar]+newVars n d = replicateM n (newVar d)++-- Lookup the current domain of a variable.+lookup :: FDVar -> OvertonFD Domain+lookup x = do+ s <- get+ return . domain $ varMap s ! x++-- Update the domain of a variable and fire all delayed constraints+-- associated with that variable.+update :: FDVar -> Domain -> OvertonFD Bool+update x i = do+ debug (show x ++ " <- " ++ show i) (return ())+ s <- get+ let vm = varMap s+ let vi = vm ! x+ debug ("where old domain = " ++ show (domain vi)) (return ())+ put $ s { varMap = Map.insert x (vi { domain = i}) vm }+ delayedConstraints vi++-- Add a new constraint for a variable to the constraint store.+addConstraint :: FDVar -> OvertonFD Bool -> OvertonFD ()+addConstraint x constraint = do+ s <- get+ let vm = varMap s+ let vi = vm ! x+ let cs = delayedConstraints vi+ put $ s { varMap =+ Map.insert x (vi { delayedConstraints = do b <- cs + if b then constraint+ else return False}) vm }+ +-- Useful helper function for adding binary constraints between FDVars.+type BinaryConstraint = FDVar -> FDVar -> OvertonFD Bool+addBinaryConstraint :: BinaryConstraint -> BinaryConstraint +addBinaryConstraint f x y = do+ let constraint = f x y+ b <- constraint + when b $ (do addConstraint x constraint+ addConstraint y constraint)+ return b++-- Constrain a variable to a particular value.+hasValue :: FDVar -> Int -> OvertonFD Bool+var `hasValue` val = do+ vals <- lookup var+ if val `member` vals+ then do let i = singleton val+ if (i /= vals) + then update var i+ else return True+ else return False++-- Constrain two variables to have the same value.+same :: FDVar -> FDVar -> OvertonFD Bool+same = addBinaryConstraint $ \x y -> do + debug "inside same" $ return ()+ xv <- lookup x+ yv <- lookup y+ debug (show xv ++ " same " ++ show yv) $ return ()+ let i = xv `intersection` yv+ if not $ Domain.null i+ then whenwhen (i /= xv) (i /= yv) (update x i) (update y i)+ else return False++whenwhen c1 c2 a1 a2 =+ if c1+ then do b1 <- a1+ if b1 + then if c2+ then a2+ else return True+ else return False + else if c2+ then a2+ else return True++-- Constrain two variables to have different values.+different :: FDVar -> FDVar -> OvertonFD Bool+different = addBinaryConstraint $ \x y -> do+ xv <- lookup x+ yv <- lookup y+ if not (isSingleton xv) || not (isSingleton yv) || xv /= yv+ then whenwhen (isSingleton xv && xv `isSubsetOf` yv)+ (isSingleton yv && yv `isSubsetOf` xv)+ (update y (yv `difference` xv))+ (update x (xv `difference` yv))+ else return False++-- Constrain one variable to have a value less than the value of another+-- variable.+infix 4 .<.+(.<.) :: FDVar -> FDVar -> OvertonFD Bool+(.<.) = addBinaryConstraint $ \x y -> do+ xv <- lookup x+ yv <- lookup y+ let xv' = filterLessThan (findMax yv) xv+ let yv' = filterGreaterThan (findMin xv) yv+ if not $ Domain.null xv'+ then if not $ Domain.null yv'+ then whenwhen (xv /= xv') (yv /= yv') (update x xv') (update y yv')+ else return False+ else return False++{-+-- Get all solutions for a constraint without actually updating the+-- constraint store.+solutions :: OvertonFD s a -> OvertonFD s [a]+solutions constraint = do+ s <- get+ return $ evalStateT (unFD constraint) s++-- Label variables using a depth-first left-to-right search.+labelling :: [FDVar s] -> OvertonFD s [Int]+labelling = mapM label where+ label var = do+ vals <- lookup var+ val <- OvertonFD . lift $ elems vals+ var `hasValue` val+ return val+-}++dump :: [FDVar] -> OvertonFD [Domain]+dump = mapM lookup++-- Add constraint (z = x `op` y) for var z+addArithmeticConstraint :: + (Domain -> Domain -> Domain) ->+ (Domain -> Domain -> Domain) ->+ (Domain -> Domain -> Domain) ->+ FDVar -> FDVar -> FDVar -> OvertonFD Bool+addArithmeticConstraint getZDomain getXDomain getYDomain x y z = do+ xv <- lookup x+ yv <- lookup y+ let constraint z x y getDomain = do+ xv <- lookup x+ yv <- lookup y+ zv <- lookup z+ let znew = debug "binaryArith:intersection" $ (debug "binaryArith:zv" $ zv) `intersection` (debug "binaryArith:getDomain" $ getDomain xv yv)+ debug ("binaryArith:" ++ show z ++ " before: " ++ show zv ++ show "; after: " ++ show znew) (return ())+ if debug "binaryArith:null?" $ not $ Domain.null (debug "binaryArith:null?:znew" $ znew)+ then if (znew /= zv) + then debug ("binaryArith:update") $ update z znew+ else return True+ else return False+ let zConstraint = debug "binaryArith: zConstraint" $ constraint z x y getZDomain+ xConstraint = debug "binaryArith: xConstraint" $ constraint x z y getXDomain+ yConstraint = debug "binaryArith: yConstraint" $ constraint y z x getYDomain+ debug ("addBinaryArith: z x") (return ())+ addConstraint z xConstraint+ debug ("addBinaryArith: z y") (return ())+ addConstraint z yConstraint+ debug ("addBinaryArith: x z") (return ())+ addConstraint x zConstraint+ debug ("addBinaryArith: x y") (return ())+ addConstraint x yConstraint+ debug ("addBinaryArith: y z") (return ())+ addConstraint y zConstraint+ debug ("addBinaryArith: y x") (return ())+ addConstraint y xConstraint+ debug ("addBinaryArith: done") (return ())+ return True++-- Add constraint (z = op x) for var z+addUnaryArithmeticConstraint :: (Domain -> Domain) -> (Domain -> Domain) -> FDVar -> FDVar -> OvertonFD Bool+addUnaryArithmeticConstraint getZDomain getXDomain x z = do+ xv <- lookup x+ let constraint z x getDomain = do+ xv <- lookup x+ zv <- lookup z+ let znew = zv `intersection` (getDomain xv)+ debug ("unaryArith:" ++ show z ++ " before: " ++ show zv ++ show "; after: " ++ show znew) (return ())+ if not $ Domain.null znew+ then if (znew /= zv) + then update z znew+ else return True+ else return False+ let zConstraint = constraint z x getZDomain+ xConstraint = constraint x z getXDomain+ addConstraint z xConstraint+ addConstraint x zConstraint+ return True++addSum = addArithmeticConstraint getDomainPlus getDomainMinus getDomainMinus++addSub = addArithmeticConstraint getDomainMinus getDomainPlus (flip getDomainMinus)++addMult = addArithmeticConstraint getDomainMult getDomainDiv getDomainDiv++addAbs = addUnaryArithmeticConstraint (\x -> mapDomain x (\i -> [abs i])) (\z -> mapDomain z (\i -> [i,-i]))++getDomainPlus :: Domain -> Domain -> Domain+getDomainPlus xs ys = toDomain (zl, zh) where+ zl = findMin xs + findMin ys+ zh = findMax xs + findMax ys++getDomainMinus :: Domain -> Domain -> Domain+getDomainMinus xs ys = toDomain (zl, zh) where+ zl = findMin xs - findMax ys+ zh = findMax xs - findMin ys++getDomainMult :: Domain -> Domain -> Domain+getDomainMult xs ys = (\d -> debug ("multDomain" ++ show d ++ "=" ++ show xs ++ "*" ++ show ys ) d) $ toDomain (zl, zh) where+ zl = minimum products+ zh = maximum products+ products = [x * y |+ x <- [findMin xs, findMax xs],+ y <- [findMin ys, findMax ys]]++getDomainDiv :: Domain -> Domain -> Domain+getDomainDiv xs ys = toDomain (zl, zh) where+ zl = minimum quotientsl+ zh = maximum quotientsh+ quotientsl = [if y /= 0 then x `div` y else minBound |+ x <- [findMin xs, findMax xs],+ y <- [findMin ys, findMax ys]]+ quotientsh = [if y /= 0 then x `div` y else maxBound |+ x <- [findMin xs, findMax xs],+ y <- [findMin ys, findMax ys]]
+ Control/CP/FD/OvertonFD/Sugar.hs view
@@ -0,0 +1,116 @@+{- + - Monadic Constraint Programming+ - http://www.cs.kuleuven.be/~toms/Haskell/+ - Tom Schrijvers+ -}+{-# LANGUAGE Rank2Types #-}+{-# LANGUAGE TypeFamilies #-}++module Control.CP.FD.OvertonFD.Sugar (+ newBound,+ newBoundBis,+ restart,+ restartOpt,+) where ++import Control.CP.SearchTree hiding (label)+import Control.CP.Transformers+import Control.CP.ComposableTransformers+import Control.CP.Queue+import Control.CP.Solver+import Control.CP.Debug+import Control.CP.FD.FD+import Control.CP.FD.Expr+import Control.CP.EnumTerm+import Control.CP.Mixin++import qualified Control.CP.PriorityQueue as PriorityQueue+import qualified Data.Sequence+import Control.CP.FD.OvertonFD.OvertonFD++newBound :: NewBound OvertonFD+newBound = do obj <- fd_objective+ (val:_) <- fd_domain obj + l <- mark+ return ((\tree -> tree `insertTree` (obj @@< val)) :: forall b . Tree OvertonFD b -> Tree OvertonFD b)++newBoundBis :: NewBound OvertonFD +newBoundBis = do obj <- fd_objective+ (val:_) <- fd_domain obj + let m = val `div` 2+ return ((\tree -> (obj @@< (m + 1) \/ ( obj @@> m /\ obj @@< val)) /\ tree) :: forall b . Tree OvertonFD b -> Tree OvertonFD b)++restart :: (Queue q, Solver solver, CTransformer c, CForSolver c ~ solver,+ Elem q ~ (Label solver,Tree solver (CForResult c),CTreeState c)) + => q -> [c] -> Tree solver (CForResult c) -> (Int,[CForResult c])+restart q cs model = run $ eval model q (RestartST (map Seal cs) return)++restartOpt :: (Queue q, CTransformer c, CForSolver c ~ OvertonFD,+ Elem q ~ (Label OvertonFD,Tree OvertonFD (CForResult c),CTreeState c)) + => q -> [c] -> Tree OvertonFD (CForResult c) -> (Int,[CForResult c])+restartOpt q cs model = run $ eval model q (RestartST (map Seal cs) opt)+ where opt tree = newBound >>= \f -> return (f tree)++--------------------------------------------------------------------------------+-- SYNTACTIC SUGAR+--------------------------------------------------------------------------------++in_domain v (l,u) = Add (Dom (Term v) l u) true++(@@<) :: FDVar -> Int -> Tree OvertonFD ()+v @@< i = (compile_constraint $ Less (Term v) (Const $ toInteger i)) /\ return ()++(@@>) :: FDVar -> Int -> Tree OvertonFD ()+v @@> i = (compile_constraint $ Less (Const $ toInteger i) (Term v)) /\ return ()++--------------------------------------------------------------------------------+-- FD SUGAR+--------------------------------------------------------------------------------++instance FDSolver OvertonFD where+ type FDTerm OvertonFD = FDVar+ specific_compile_constraint = convert++-- convert :: Mixin (FDConstraint OvertonFD -> Tree OvertonFD Bool)+convert s t (Same a (Const i)) = debug "convert (Same a (Const i))" $ do+ va <- decompose a+ addT $ OHasValue va $ fromInteger i+convert s t (Same (Const i) a) = debug "convert (Same (Const i) a)" $ do+ va <- decompose a+ addT $ OHasValue va $ fromInteger i+convert s t (Same (Plus a b) c) = debug "convert (Same (Plus a b) c)" $ do+ va <- decompose a+ vb <- decompose b+ vc <- decompose c+ addT $ OAdd va vb vc+convert s t (Same (Minus a b) c) = debug "convert (Same (Minus a b) c)" $ do+ va <- decompose a+ vb <- decompose b+ vc <- decompose c+ addT $ OSub va vb vc+convert s t (Same (Mult a b) c) = debug "convert (Same (Mult a b) c)" $ do+ va <- decompose a+ vb <- decompose b+ vc <- decompose c+ addT $ OMult va vb vc+convert s t (Same (Abs a) c) = debug "convert (Same (Abs a) c)" $ do+ va <- decompose a+ vc <- decompose c+ addT $ OAbs va vc+convert s t (Same a b@(Plus _ _)) = debug "convert (Same a Plus)" $ convert s t $ Same b a+convert s t (Same a b@(Minus _ _)) = debug "convert (Same a Minus)" $ convert s t $ Same b a+convert s t (Same a b@(Mult _ _)) = debug "convert (Same a Mult)" $ convert s t $ Same b a+convert s t (Same a b@(Abs _)) = debug "convert (Same a Abs)" $ convert s t $ Same b a+convert s t (Same a b) = debug "convert (Same a b)" $ do+ va <- decompose a+ vb <- decompose b+ addT $ OSame va vb+convert s t (Diff a b) = debug "convert (Diff a b)" $ do+ va <- decompose a+ vb <- decompose b+ addT $ ODiff va vb+convert s t (Less a b) = debug "convert (Less a b)" $ do+ va <- decompose a+ vb <- decompose b+ addT $ OLess va vb+convert s t x = debug "convert _" $ s x
+ Control/CP/FD/Solvers.hs view
@@ -0,0 +1,60 @@+{-# LANGUAGE CPP #-}++module Control.CP.FD.Solvers where++import qualified Control.CP.PriorityQueue as PriorityQueue+import qualified Data.Sequence++import Control.CP.ComposableTransformers+import Control.CP.SearchTree+import Control.CP.FD.FD+import Control.CP.FD.OvertonFD.Sugar+import Control.CP.FD.OvertonFD.OvertonFD+import Control.CP.FD.Gecode.CodegenSolver++#ifdef RGECODE+import Control.CP.FD.Gecode.RuntimeSolver+#endif++--------------------------------------------------------------------------------+-- FORCE SOLVERS+--------------------------------------------------------------------------------++as_overtonfd :: Tree (FDWrapper OvertonFD) a -> Tree (FDWrapper OvertonFD) a+as_overtonfd = id++as_gecode_codegen :: Tree (FDWrapper CodegenSolver) a -> Tree CodegenSolver a+as_gecode_codegen = unwrap++#ifdef RGECODE+as_gecode_runtime :: Tree (FDWrapper RuntimeSolver) a -> Tree (FDWrapper RuntimeSolver) a+as_gecode_runtime = id++as_gecode_search :: Tree (FDWrapper SearchSolver) a -> Tree (FDWrapper SearchSolver) a+as_gecode_search = id+#endif++------------------------------------------------------------------------------+-- SEARCH STRATEGIES+------------------------------------------------------------------------------++dfs = []+bfs = Data.Sequence.empty+pfs :: Ord a => PriorityQueue.PriorityQueue a (a,b,c)+pfs = PriorityQueue.empty++nb :: Int -> CNodeBoundedST s a+nb = CNBST+db :: Int -> CDepthBoundedST s a+db = CDBST+bb :: NewBound s -> CBranchBoundST s a+bb = CBBST+fs :: CFirstSolutionST s a+fs = CFSST+it :: CIdentityCST s a+it = CIST+ra :: Int -> CRandomST s a+ra = CRST+ld :: Int -> CLimitedDiscrepancyST s a+ld = CLDST+
Control/CP/Herbrand/Herbrand.hs view
@@ -1,13 +1,25 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE PatternGuards #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE PatternGuards #-} -- |This module provides a Herbrand solver. -- -- The type of terms is parameterized by the "HTerm" type class.-module Control.CP.Herbrand.Herbrand where +module Control.CP.Herbrand.Herbrand (+ HTerm(..),+ Herbrand(..),+ failure,+ success,+ unify,+ shallow_normalize,+ registerAction,+ HState,+ Unify,+ initState,+ addH,+ newvarH+) where import Control.Monad.State.Lazy import Control.Applicative@@ -80,7 +92,8 @@ instance HTerm t => Term (Herbrand t) t where newvar = newvarH-+ type Help (Herbrand t) t = ()+ help _ _ = () initState :: HTerm t => HState t m initState = HState varSupply Data.Map.empty
Control/CP/Herbrand/HerbrandT.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleInstances #-}@@ -49,6 +48,10 @@ instance (HTerm t, Solver s) => Term (HerbrandT t s) (L t) where newvar = newvarH >>= return . L + type Help (HerbrandT t s) (L t) = ()+ help _ _ = () instance (HTerm t, Solver s, Term s st) => Term (HerbrandT t s) (R st) where newvar = lift newvar >>= return . R+ type Help (HerbrandT t s) (R st) = ()+ help _ _ = ()
Control/CP/Herbrand/Prolog.hs view
@@ -30,6 +30,8 @@ instance Term Prolog PrologTerm where newvar = Prolog $ newvar+ type Help Prolog PrologTerm = ()+ help _ _ = () data PConstraint = PrologTerm := PrologTerm | NotFunctor PrologTerm String
Control/CP/Herbrand/PrologTerm.hs view
@@ -1,9 +1,8 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE UndecidableInstances #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-} -module Control.CP.Herbrand.PrologTerm where +module Control.CP.Herbrand.PrologTerm (+ PrologTerm(..)+) where import Data.List (intersperse)
+ Control/CP/Mixin.hs view
@@ -0,0 +1,24 @@+module Control.CP.Mixin (+ Mixin,+ (<@>),+ mixin,+ mixinConst,+ mixinId+) where++type Mixin a = a -> a -> a++infixl 5 <@>+(<@>) :: Mixin a -> Mixin a -> Mixin a+(f1 <@> f2) s t = f1 (f2 s t) t++mixin :: Mixin a -> a+mixin f = let + x = f (error "super called in top-level mixin") x + in x++mixinConst :: a -> a -> a -> a+mixinConst _ _ c = c++mixinId :: Mixin a+mixinId s _ = s
Control/CP/Queue.hs view
@@ -9,7 +9,14 @@ - Tom Schrijvers -} -module Control.CP.Queue where+module Control.CP.Queue (+ Queue,+ Elem,+ emptyQ,+ isEmptyQ,+ popQ,+ pushQ+) where import qualified Data.Sequence import qualified Control.CP.PriorityQueue as PriorityQueue@@ -32,7 +39,9 @@ type Elem (Data.Sequence.Seq a) = a emptyQ _ = Data.Sequence.empty isEmptyQ = Data.Sequence.null - popQ (Data.Sequence.viewl -> x Data.Sequence.:< xs) = (x,xs)+-- popQ (Data.Sequence.viewl -> x Data.Sequence.:< xs) = (x,xs)+ popQ l = case Data.Sequence.viewl l of+ x Data.Sequence.:< xs -> (x,xs) pushQ = flip (Data.Sequence.|>) instance Ord a => Queue (PriorityQueue.PriorityQueue a (a,b,c)) where
Control/CP/SearchTree.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS_GHC -fglasgow-exts #-} {- - The Tree data type, a generic modelling language for constraint solvers. -@@ -6,10 +5,38 @@ - http://www.cs.kuleuven.be/~toms/Haskell/ - Tom Schrijvers -}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE FlexibleContexts #-} -module Control.CP.SearchTree where+module Control.CP.SearchTree (+ Tree(..),+ transformTree,+ bindTree,+ insertTree,+ (\/),+ (/\),+ true,+ disj,+ conj,+ disj2,+ prim,+ addC,+ addT,+ exist,+ forall,+ addTo,+ false,+ exists,+ label,+ indent,+ showTree,+ MonadTree,+ untree+) where import Control.CP.Solver+import Control.CP.Mixin import Control.Monad import Control.Monad.Reader@@ -18,6 +45,7 @@ import Data.Monoid + ------------------------------------------------------------------------------- ----------------------------------- Tree -------------------------------------- -------------------------------------------------------------------------------@@ -30,13 +58,14 @@ NewVar :: Term s t => (t -> Tree s a) -> Tree s a -- add a new variable to a tree Label :: s (Tree s a) -> Tree s a -- label with a strategy -instance Show (Tree s a) where- show Fail = "Fail"- show (Return _) = "Return"- show (Try l r) = "Try (" ++ show l ++ ") (" ++ show r ++ ")"- show (Add _ t) = "Add (" ++ show t ++ ")"- show (NewVar _) = "NewVar <function>"- show (Label _) = "Label <monadic value>"+transformTree :: Solver s => Mixin (Tree s a -> Tree s a)+transformTree _ _ Fail = Fail+transformTree _ _ (Return x) = Return x+transformTree _ t (Try x y) = Try (t x) (t y)+transformTree _ t (Add c x) = Add c (t x)+transformTree _ t (NewVar f) = NewVar (\x -> t $ f x)+transformTree _ t (Label m) = Label $ m >>= return . t+-- transformTree s _ x = s x instance Solver s => Functor (Tree s) where fmap = liftM @@ -51,15 +80,14 @@ (Return x) `bindTree` k = k x (Try m n) `bindTree` k = Try (m `bindTree` k) (n `bindTree` k) (Add c m) `bindTree` k = Add c (m `bindTree` k)-(NewVar f) `bindTree` k = NewVar (\x -> f x `bindTree` k) +(NewVar f) `bindTree` k = NewVar (\x -> f x `bindTree` k) (Label m) `bindTree` k = Label (m >>= \t -> return (t `bindTree` k)) insertTree :: Solver s => Tree s a -> Tree s () -> Tree s a-(NewVar f) `insertTree` t = NewVar (\x -> f x `insertTree` t) +(NewVar f) `insertTree` t = NewVar (\x -> f x `insertTree` t) (Add c o) `insertTree` t = Add c (o `insertTree` t) other `insertTree` t = t /\ other - {- Monad laws: - - 1. return x >>= f == f x@@ -85,10 +113,10 @@ - 4) Add c m >>= return - == Add c (m >>= return) (bind def) - == Add c m (induction) - - 5) NewVar f >>= return- - == NewVar (\v -> f v >>= return) (bind def) - - == NewVar (\v -> f v) ((co)-induction?)- - == NewVar f (eta reduction)+ - 5) NewVar i f >>= return+ - == NewVar i (\v -> f v >>= return) (bind def) + - == NewVar i (\v -> f v) ((co)-induction?)+ - == NewVar i f (eta reduction) - 6) Label sm >>= return - == Label (sm >>= \m -> return (m >>= return)) (bind def) - == Label (sm >>= \m -> return m) (co-induction)@@ -112,12 +140,12 @@ - == Try ((l >>= f) >>= g) ((r >>= f) >>= g) (bind def) - == Try (l >>= (\x -> f x >>= g)) (r >>= (\x -> f x >>= g)) (induction) - == Try l r >>= (\x -> f x >>= g) (bind def)- - 4) (NewVar m >>= f) >>= g- - == NewVar (\v -> m v >>= f) >>= g (bind def)- - == NewVar (\w -> (\v -> m v >>= f) w >>= g) (bind def)- - == NewVar (\w -> (m w >>= f) >>= g) (beta reduction) - - == NewVar (\w -> m w >>= (\x -> f x >>= g)) (co-induction)- - == NewVar m >>= (\x -> f x >>= g) (bind def)+ - 4) (NewVar i m >>= f) >>= g+ - == NewVar i (\v -> m v >>= f) >>= g (bind def)+ - == NewVar i (\w -> (\v -> m v >>= f) w >>= g) (bind def)+ - == NewVar i (\w -> (m w >>= f) >>= g) (beta reduction) + - == NewVar i (\w -> m w >>= (\x -> f x >>= g)) (co-induction)+ - == NewVar i m >>= (\x -> f x >>= g) (bind def) - 5) (Label sm >>= f) >>= g - == Label (sm >>= \m -> return (m >>= f)) >>= g (bind def) - == Label ((sm >>= \m -> return (m >>= f)) >>= \m' -> return (m' >>= g))@@ -164,37 +192,89 @@ true = return () disj :: MonadTree tree => [tree a] -> tree a-disj = foldr (\/) false+disj [] = false+disj a = foldr1 (\/) a conj :: MonadTree tree => [tree ()] -> tree ()-conj = foldr (/\) true+conj [] = true+conj a = foldr1 (/\) a -disj2 :: Solver s => [Tree s a] -> Tree s a+disj2 :: MonadTree tree => [tree a] -> tree a disj2 (x: []) = x disj2 l = let (xs,ys) = split l split [] = ([],[]) split (a:as) = let (bs,cs) = split as in (a:cs,bs)- in Try (disj2 xs) (disj2 ys)- + in (disj2 xs) \/ (disj2 ys)++prim :: MonadTree tree => TreeSolver tree a -> tree a+prim action = label (action >>= return . return)++addC :: MonadTree tree => Constraint (TreeSolver tree) -> tree ()+addC c = c `addTo` true++addT :: MonadTree tree => Constraint (TreeSolver tree) -> tree Bool+addT c = c `addTo` (return True)+ exist :: (MonadTree tree, Term (TreeSolver tree) t) => Int -> ([t] -> tree a) -> tree a exist n ftree = f n []- where f 0 acc = ftree acc+ where f 0 acc = ftree $ reverse acc f n acc = exists $ \v -> f (n-1) (v:acc) -forall :: (Solver s, Term s t) => [t] -> (t -> Tree s ()) -> Tree s ()+forall :: (MonadTree tree, Term (TreeSolver tree) t) => [t] -> (t -> tree ()) -> tree () forall list ftree = conj $ map ftree list- -prim :: MonadTree tree => TreeSolver tree a -> tree a-prim action = label (action >>= return . return) -add :: MonadTree tree => Constraint (TreeSolver tree) -> tree ()-add c = c `addTo` true+-- Shortcut the search procedure for a Tree that does not contain Try nodes.+-- create a solver monad that returns the result of the Tree, or a specified+-- value upon failure+untree :: Solver s => v -> Tree s v -> s v+untree _ (Return x) = return x+untree _ (Try _ _) = error "convertion of Try nodes to solver is not supported"+untree e (Fail) = return e+untree e (Label s) = s >>= untree e+untree e (Add c t) = (add c) >>= (\x -> if x then untree e t else return e)+untree e (NewVar f) = do+ v <- newvar+ untree e (f v) ------------------------------------------------------------------------------------------------------------ Monad Transformer Instances -------------------------------------------------------------------------------------------------------+-- | show +indent :: Int -> String+indent l = replicate (2*l) ' '++showTree :: (Show (Constraint s), Show a, Solver s) => Int -> Tree s a -> s String+showTree l Fail = return $ indent l ++ "Fail\n"+showTree l (Return x) = return $ indent l ++ "Return [" ++ (show x) ++ "]\n"+showTree l (Try a b) = do+ m <- mark+ s1 <- showTree (l+1) a+ goto m+ s2 <- showTree (l+1) b+ return $ indent l ++ "Try\n" ++ s1 ++ s2+showTree l (Add c t) = do+ s <- showTree (l+1) t+ return $ indent l ++ "Add (" ++ (show c) ++ ")\n" ++ s+showTree l (NewVar f) = do+ n <- newvar+ s <- showTree (l+1) (f n)+ return $ indent l ++ "NewVar\n" ++ s+showTree l (Label a) = do+ r <- a+ s <- showTree (l+1) r+ return $ indent l ++ "Label\n" ++ s++instance Show (Tree s a) where+ show Fail = "Fail"+ show (Return _) = "Return"+ show (Try l r) = "Try (" ++ show l ++ ") (" ++ show r ++ ")"+ show (Add _ t) = "Add (" ++ show t ++ ")"+ show (NewVar _) = "NewVar <function>"+ show (Label _) = "Label <monadic value>"++----------------------------------------------------------------------+-- Monad Transformer Instances+----------------------------------------------------------------------+ instance MonadTree t => MonadTree (ReaderT env t) where type TreeSolver (ReaderT env t) = TreeSolver t addTo constraint tree = ReaderT $ \env -> addTo constraint (runReaderT tree env)@@ -202,7 +282,6 @@ l \/ r = ReaderT $ \env -> runReaderT l env \/ runReaderT r env exists f = ReaderT $ \env -> exists (\var -> runReaderT (f var) env) label p = ReaderT $ \env -> label (p >>= \m -> return $ runReaderT m env)- instance (Monoid w, MonadTree t) => MonadTree (WriterT w t) where type TreeSolver (WriterT w t) = TreeSolver t
Control/CP/Solver.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS_GHC -fglasgow-exts #-} {- - The Solver class, a generic interface for constraint solvers. -@@ -6,8 +5,25 @@ - http://www.cs.kuleuven.be/~toms/Haskell/ - Tom Schrijvers -}-module Control.CP.Solver where +{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}++module Control.CP.Solver (+ Solver,+ Constraint,+ Label,+ add,+ run,+ mark,+ goto,+ Term,+ newvar,+ Help,+ help+) where + import Control.Monad.Writer import Data.Monoid @@ -17,7 +33,7 @@ -- | the labels type Label solver :: * -- | add a constraint to the current state, and- -- return whethe the resulting state is consistent+ -- return whether the resulting state is consistent add :: Constraint solver -> solver Bool -- | run a computation run :: solver a -> a@@ -26,10 +42,13 @@ -- | go to the state with given label goto :: Label solver -> solver () -class Solver solver => Term solver term where+class (Solver solver) => Term solver term where -- | produce a fresh constraint variable newvar :: solver term- ++ type Help solver term+ help :: solver () -> term -> Help solver term+ -- | WriterT decoration of a solver -- useful for producing statistics during solving instance (Monoid w, Solver s) => Solver (WriterT w s) where@@ -42,3 +61,6 @@ instance (Monoid w, Term s t) => Term (WriterT w s) t where newvar = lift newvar+ type Help (WriterT w s) t = ()+ help _ _ = ()+
Control/CP/Transformers.hs view
@@ -6,11 +6,19 @@ {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE Rank2Types #-}-module Control.CP.Transformers where +module Control.CP.Transformers (+ eval,+ eval',+ continue,+ NodeBoundedST,+ DepthBoundedST,+ Transformer(..),+) where import Control.CP.Solver import Control.CP.SearchTree import Control.CP.Queue+import Control.CP.Debug -------------------------------------------------------------------------------- -- EVALUATION@@ -19,8 +27,9 @@ eval :: (Solver solver, Queue q, Elem q ~ (Label solver,Tree solver (ForResult t),TreeState t), Transformer t, ForSolver t ~ solver) => Tree solver (ForResult t) -> q -> t -> solver (Int,[ForResult t])-eval tree q t = do (es,ts) <- initT t tree- eval' 0 tree q t es ts+eval tree q t = debug "eval" $ + do (es,ts) <- initT t tree+ eval' 0 tree q t es ts eval' :: SearchSig solver q t (ForResult t) eval' i (Return x) wl t es ts = do (j,xs) <- returnT (i+1) wl t es@@ -28,7 +37,7 @@ eval' i (Add c k) wl t es ts = do b <- Control.CP.Solver.add c if b then eval' (i+1) k wl t es ts else continue (i+1) wl t es-eval' i (NewVar f) wl t es ts = do v <- newvar +eval' i (NewVar f) wl t es ts = do v <- newvar eval' (i+1) (f v) wl t es ts eval' i (Try l r) wl t es ts = do now <- mark
+ examples/AllInterval.hs view
@@ -0,0 +1,18 @@+{-# LANGUAGE OverlappingInstances #-}++import Control.CP.FD.Example.Example+import Control.CP.FD.FD+import Control.CP.FD.Expr+import Control.CP.SearchTree++main = example_main_single model++model n = exist n $ \list -> do+ allin list (0,n-1)+ let dlist = zipWith (\a b -> abs $ a-b) (take (n-1) list) (tail list)+ allin dlist (1,n-1)+ allDiff list+ allDiff dlist+ (list!!0) @< (list!!1)+ (dlist!!0) @> (dlist!!(n-2))+ return list
+ examples/Alpha.hs view
@@ -0,0 +1,61 @@+-- --------------------------------------------------------------------------+-- Benchmark (Finite Domain) INRIA Rocquencourt - ChLoE Project --+-- --+-- Name : alpha.pl --+-- Title : alphacipher --+-- Original Source: Daniel Diaz - INRIA France --+-- Date : January 1993 --+-- Adapted for MCP: Tom Schrijvers --+-- --+-- This problem comes from the news group rec.puzzle. --+-- The numbers 1 - 26 have been randomly assigned to the letters of the --+-- alphabet. The numbers beside each word are the total of the values --+-- assigned to the letters in the word. e.g for LYRE L,Y,R,E might equal --+-- 5,9,20 and 13 respectively or any other combination that add up to 47. --+-- Find the value of each letter under the equations: --+-- --+-- BALLET 45 GLEE 66 POLKA 59 SONG 61 --+-- CELLO 43 JAZZ 58 QUARTET 50 SOPRANO 82 --+-- CONCERT 74 LYRE 47 SAXOPHONE 134 THEME 72 --+-- FLUTE 30 OBOE 53 SCALE 51 VIOLIN 100 --+-- FUGUE 50 OPERA 65 SOLO 37 WALTZ 34 --+-- --+-- Solution: --+-- [A, B,C, D, E,F, G, H, I, J, K,L,M, N, O, P,Q, R, S,T,U, V,W, X, Y, Z] --+-- [5,13,9,16,20,4,24,21,25,17,23,2,8,12,10,19,7,11,15,3,1,26,6,22,14,18] --+-- --------------------------------------------------------------------------++import Control.CP.FD.Example.Example+import Control.CP.FD.FD+import Control.CP.FD.Expr+import Control.CP.SearchTree++main = example_main_void model++model :: FDSolver solver => Tree (FDWrapper solver) [FDExpr solver]+model =+ exist 26 $ + \list@[a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z] ->+ allin list (1,26) /\+ allDiff list /\+ b + a + l + l + e + t @= 45 /\+ c + e + l + l + o @= 43 /\+ c + o + n + c + e + r + t @= 74 /\+ f + l + u + t + e @= 30 /\+ f + u + g + u + e @= 50 /\+ g + l + e + e @= 66 /\+ j + a + z + z @= 58 /\+ l + y + r + e @= 47 /\+ o + b + o + e @= 53 /\+ o + p + e + r + a @= 65 /\+ p + o + l + k + a @= 59 /\+ q + u + a + r + t + e + t @= 50 /\+ s + a + x + o + p + h + o + n + e @= 134 /\+ s + c + a + l + e @= 51 /\+ s + o + l + o @= 37 /\+ s + o + n + g @= 61 /\+ s + o + p + r + a + n + o @= 82 /\+ t + h + e + m + e @= 72 /\+ v + i + o + l + i + n @= 100 /\+ w + a + l + t + z @= 34 /\+ return list
+ examples/Grocery.hs view
@@ -0,0 +1,21 @@+-- A kid goes into a grocery store and buys four items. The cashier charges $7.11. +-- The kid pays and is about to leave when the cashier calls the kid back, and says +-- "Hold on, I multiplied the four items instead of adding them; I'll try again... +-- Gosh, with adding them the price still comes to $7.11"! What were the prices of +-- the four items?++import Control.CP.FD.Example.Example+import Control.CP.FD.FD+import Control.CP.FD.Expr+import Control.CP.SearchTree++main = example_main_void model++model :: FDModel+model =+ exist 4 $ \list@[a,b,c,d] -> + list `allin` (0,711) /\+ a + b + c + d @= 711 /\+ (a * b) * (c * d) @= 711*100*100*100 /\+ sorted list /\+ return list
+ examples/MagicSquare.hs view
@@ -0,0 +1,31 @@+import Control.CP.FD.Example.Example+import Control.CP.FD.FD+import Control.CP.FD.Expr+import Control.CP.SearchTree+import Data.List (transpose)++main = example_main_single model++cutAt p l = case (splitAt p l) of+ (l,[]) -> [l]+ (b,r) -> b:(cutAt p r)+mexist r c = exist (r*c) $ \list -> return $ cutAt c list+lsum v l = (foldl1 (+) l) @= v+diag bc ic m = map (\x -> (m!!x)!!(bc+ic*x)) [0..(length m)-1]++interleave [] ys = ys+interleave (x:xs) ys = x : (interleave ys xs)++model n = do+ let nn = n*n+ let s = nn*(nn+1) `div` (2*n)+ let sums = lsum $ cte s+ m <- mexist n n+ allin (concat m) (1,nn)+ conj $ interleave (map sums m) (map sums $ transpose m)+ sums $ diag 0 1 m+ sums $ diag (n-1) (-1) m+ allDiff $ concat m+ (m!!0)!!0 @> (m!!0)!!(n-1)+ (m!!0)!!0 @> (m!!(n-1))!!0+ return $ concat m
+ examples/Olympic.hs view
@@ -0,0 +1,51 @@+{-+% File : olympic.pl+% Author : Neng-Fa ZHOU+% Date : 1993+% Purpose: solve a puzzle taken from Olympic Arithmetic Contest+/***********************************************************************+ Given ten variables with the following configuration:++ X7 X8 X9 X10++ X4 X5 X6++ X2 X1 ++ X1++ We already know that X1 is equal to 3 and want to assign each variable+ with a different integer from {1,2,...,10} such that for any three+ variables + Xi Xj++ Xk+ the following constraint is satisfied:++ |Xi-Xj| = Xk+***********************************************************************/+-}+++import Control.CP.FD.Example.Example+import Control.CP.FD.FD+import Control.CP.FD.Expr+import Control.CP.SearchTree++main = example_main_void model++model :: FDSolver solver => Tree (FDWrapper solver) [Expr (FDTerm solver)]+model = + exist 10 $ \list@[x1,x2,x3,x4,x5,x6,x7,x8,x9,x10] + -> list `allin` (1,10) /\ + allDiff list /\ + x1 @= 3 /\ + minus x2 x3 x1 /\+ minus x4 x5 x2 /\+ minus x5 x6 x3 /\+ minus x7 x8 x4 /\+ minus x8 x9 x5 /\+ minus x9 x10 x6 /\+ return list++minus x1 x2 x3 = (abs (x1-x2)) @= x3
+ examples/Partition.hs view
@@ -0,0 +1,73 @@+-- --------------------------------------------------------------------------+-- Benchmark (Finite Domain) --+-- --+-- Name : partit.pl --+-- Title : integer partitionning --+-- Original Source: Daniel Diaz - INRIA France --+-- Adapted by : Daniel Diaz for GNU Prolog --+-- Date : September 1993 (modified March 1997) --+-- --+-- Partition numbers 1,2,...,N into two groups A and B such that: --+-- a) A and B have the same length, --+-- b) sum of numbers in A = sum of numbers in B, --+-- c) sum of squares of numbers in A = sum of squares of numbers in B. --+-- --+-- This problem admits a solution if N is a multiple of 8. --+-- --+-- Note: finding a partition of 1,2...,N into 2 groups A and B such that: --+-- --+-- Sum (k^p) = Sum l^p --+-- k in A l in B --+-- --+-- admits a solution if N mod 2^(p+1) = 0 (N is a multiple of 2^(p+1)). --+-- Condition a) is a special case where p=0, b) where p=1 and c) where p=2.--+-- --+-- Two redundant constraints are used: --+-- --+-- - in order to avoid duplicate solutions (permutations) we impose --+-- A1<A2<....<AN/2, B1<B2<...<BN/2 and A1<B1. This achieves much more --+-- pruning than only fd_all_differents(A) and fd_all_differents(B). --+-- --+-- - the half sums are known --+-- N --+-- Sum k^1 = Sum l^1 = (Sum i) / 2 = N*(N+1) / 4 --+-- k in A l in B i=1 --+-- N --+-- Sum k^2 = Sum l^2 = (Sum i^2)/2 = N*(N+1)*(2*N+1) / 12 --+-- k in A l in B i=1 --++import Control.CP.FD.Example.Example+import Control.CP.FD.FD+import Control.CP.FD.Expr+import Control.CP.SearchTree++main = example_main_single model++model n =+ exist n $ \list1 ->+ exist n $ \list2 ->+ allin list1 (1,2*n) /\+ allin list2 (1,2*n) /\+ (let list = list1 ++ list2 + in ascending list1 /\+ ascending list2 /\+ head list1 @< head list2 /\+ allDiff list /\+ csum list1 @= csum list2 /\+ csum (square list1) @= csum (square list2) /\+ csum list1 @= (cte $ hs (2*n)) /\+ csum list2 @= (cte $ hs (2*n)) /\+ csum (square list1) @= (cte $ hss (2*n)) /\+ csum (square list2) @= (cte $ hss (2*n)) /\+ return list+ ) ++ascending list = sSorted list++hs, hss :: Int -> Int+hs n = (n * (n + 1)) `div` 4+hss n = (n * (n + 1) * (2 * n +1)) `div` 12++csum l = foldl1 (+) l++square l = map (\x -> x * x) l
+ examples/Queens.hs view
@@ -0,0 +1,20 @@+{- + - Monadic Constraint Programming+ - http://www.cs.kuleuven.be/~toms/Haskell/+ - Tom Schrijvers & Pieter Wuille+ -}++import Control.CP.FD.Example.Example+import Control.CP.FD.FD+import Control.CP.FD.Expr+import Control.CP.SearchTree++main = example_main_single nqueens++nqueens n = + exist n $ \q -> q `allin` (1,n) /\ conj [ + q!!i @/= q!!j /\ + (q!!i) @+ i @/= (q!!j) @+ j /\ + (q!!i) @- i @/= (q!!j) @- j + | i <- [0..n-1], j <- [0..n-1], i > j + ] /\ return q
+ examples/Ring.hs view
@@ -0,0 +1,30 @@+import Control.CP.FD.Example.Example+import Control.CP.FD.FD+import Control.CP.FD.Expr+import Control.CP.SearchTree++import List (tails)+import Data.Map (toList)++main = example_main_single model++-- generate a disjunction producing a list of variables, consisting of alr+-- prefixed by up to maxlen new variables+varexist :: FDSolver solver => Int -> [FDExpr solver] -> Tree (FDWrapper solver) [FDExpr solver]+varexist maxlen alr = + if maxlen==0+ then return alr+ else return alr \/ (exists $ \x -> varexist (maxlen-1) (x:alr))++-- constr list i = (if (i < (length list)-2) then v2 @= v0 * v1 - i else true) /\ v0 @: (-10,10)+constr list i = 2*v1 @= 2*v2 - v0 /\ + v0 @: (-10,10)+ where v0 = list !! i+ v1 = list !! ((i+1) `mod` (length list))+ v2 = list !! ((i+2) `mod` (length list))++model :: FDSolver solver => Int -> Tree (FDWrapper solver) [FDExpr solver]+model n = exists $ \x -> + do list <- varexist n [x]+ conj $ [ constr list i | i <- [0..(length list)-1] ]+ return list
+ examples/StressDomain.hs view
@@ -0,0 +1,23 @@+import List (transpose)++import Control.CP.FD.Example.Example+import Control.CP.FD.FD+import Control.CP.FD.Expr+import Control.CP.SearchTree++main = example_main_single model++cutAt p l = case (splitAt p l) of+ (l,[]) -> [l]+ (b,r) -> b:(cutAt p r)+mexist r c = exist (r*c) $ \list -> return $ cutAt c list+lsum v l = (foldl1 (+) l) @= v+diag bc ic m = map (\x -> (m!!x)!!(bc+ic*x)) [0..(length m)-1]++model :: FDSolver solver => Int -> Tree (FDWrapper solver) [FDExpr solver]+model n = exist 5 $ \l -> do+ allin l (0,5*n)+ let forvar v = conj $ map (\p -> conj $ map (\j -> v @/= 5*j+p) [0..(cte (5*n))]) [0,2,4]+ conj $ map forvar $ reverse l+ conj $ map (\j -> conj $ map (\v -> v @>= cte (5*j) /\ v @<= cte (5*(j+5*(n `div` 2)))) $ reverse l) [0..5*(n `div` 2)]+ return l
+ examples/TryDemo.hs view
@@ -0,0 +1,19 @@+{- + - Monadic Constraint Programming+ - http://www.cs.kuleuven.be/~toms/Haskell/+ - Tom Schrijvers & Pieter Wuille+ -}++import Control.CP.FD.Example.Example+import Control.CP.FD.FD+import Control.CP.FD.Expr+import Control.CP.SearchTree++main = example_main_void model++model :: FDSolver solver => Tree (FDWrapper solver) [FDExpr solver]+model = exist 2 $ \[a,b] -> a @: (1,5) /\+ b @: (0,4) /\+ a - b @= 1 /\+ (a @= 2 \/ a @= 3 \/ a @= 4) /\+ return [a,b]
+ examples/Zebra.hs view
@@ -0,0 +1,39 @@+import Control.CP.FD.Example.Example+import Control.CP.FD.FD+import Control.CP.FD.Expr+import Control.CP.SearchTree++main = example_main_void model++model :: FDSolver solver => Tree (FDWrapper solver) [FDExpr solver]+model = + exist 5 $ \ns@[n1,n2,n3,n4,n5] -> + exist 5 $ \cs@[c1,c2,c3,c4,c5] -> + exist 5 $ \ps@[p1,p2,p3,p4,p5] -> + exist 5 $ \as@[a1,a2,a3,a4,a5] -> + exist 5 $ \ds@[d1,d2,d3,d4,d5] -> + let vars = ns ++ cs ++ ps ++ as ++ ds in+ vars `allin` (1,5) /\+ allDiff ns /\+ allDiff cs /\+ allDiff ps /\+ allDiff as /\+ allDiff ds /\+ n1 @= c2 /\+ n2 @= a1 /\+ n3 @= p1 /\+ n4 @= d3 /\+ n5 @= 1 /\+ d5 @= 3 /\+ p3 @= d1 /\+ c1 @= d4 /\+ p5 @= a4 /\+ p2 @= c3 /\+ c1 @= c5+1 /\+ plusorminus a3 p4 1 /\+ plusorminus a5 p2 1 /\+ plusorminus n5 c4 1 /\+ return vars ++plusorminus x y c =+ x @= y+c \/ x @= y-c
+ lib/gecodeglue.cpp view
@@ -0,0 +1,380 @@+#define _interface_cpp_++#include <vector>+#include <iostream>++#include "gecode/kernel.hh" +#include "gecode/support.hh" +#include "gecode/int.hh" +#include "gecode/search.hh" ++#include "gecodeglue.h"++using namespace std;+using namespace Gecode;++int static nModels=0;+int static nOrigModels=0;++class HaskellModel : public Space {+protected:+ vector<BoolVar> boolVars;+ vector<IntVar> intVars;+ IntConLevel icl;+#ifndef NDEBUG+ int level;+ int origNum,num;+#endif+private:+ static IntRelType mapGoperator(goperator_t op, bool revert=false) {+ switch(op) {+ case GOPERATOR_OEQUAL: return IRT_EQ;+ case GOPERATOR_ODIFF: return IRT_NQ;+ case GOPERATOR_OLESS: return revert ? IRT_GR : IRT_LE;+ }+#ifndef NDEBUG+ cerr << "(unknown goperator " << op << "\n";+#endif+ assert(0);+ }+ +public:+ HaskellModel() : boolVars(), intVars(), icl(ICL_DEF)+#ifndef NDEBUG+ , level(0), origNum(++nOrigModels), num(++nModels) +#endif+ {+#ifndef NDEBUG+ identify(); cerr << "newmodel\n";+#endif+ }+ ~HaskellModel() {+#ifndef NDEBUG+ identify(); cerr << "delmodel\n";+#endif+ }+ HaskellModel(bool share, HaskellModel &model) : Space(share,model), boolVars(model.boolVars.size()), intVars(model.intVars.size()), icl(model.icl)+#ifndef NDEBUG+ , level(model.level+1), origNum(model.origNum), num(++nModels)+#endif+ {+#ifndef NDEBUG+ identify(); cerr << "newmodel from [" << model.origNum << ":" << model.num << "]\n";+#endif+ for (int i=0; i<model.boolVars.size(); i++) {+ boolVars.at(i).update(*this, share, model.boolVars.at(i));+ }+ for (int i=0; i<model.intVars.size(); i++) {+ intVars.at(i).update(*this, share, model.intVars.at(i));+ }+ }+ virtual Space *copy(bool share) {+ return new HaskellModel(share, *this);+ }++#ifndef NDEBUG+ void identify() {+ for (int i=0; i<level; i++) {+ cerr << " ";+ }+ cerr << "[" << origNum << ":" << num << "] ";+ }+#endif+ + int addIntVar(int low, int high) {+ int ret = intVars.size();+ IntVar b(*this,low,high);+ intVars.push_back(b);+#ifndef NDEBUG+ identify(); cerr << "addintvar v" << ret << "\n";+#endif+ return ret;+ }+ int addBoolVar(int low, int high) {+ int ret = boolVars.size();+ BoolVar b(*this,low,high);+ boolVars.push_back(b);+#ifndef NDEBUG+ identify(); cerr << "addboolvar v" << ret << "\n";+#endif+ return ret;+ }+ void getIntInfo(int var, int *min, int *max, int *med, int *size, int *val) {+ assert(var>=0 && var<intVars.size());+ IntVar &v = intVars.at(var);+ SpaceStatus state=status();+ if (state==SS_FAILED) {+ if (min) *min=0;+ if (max) *max=0;+ if (med) *med=0;+ if (size) *size=0;+#ifndef NDEBUG+ identify(); cerr << "getintinfo failed)\n";+#endif+ return;+ }+ if (min) *min=v.min();+ if (max) *max=v.max();+ if (med) *med=v.med();+ int ss=v.size();+ if (ss==1) {+ if (size) *size=1;+ if (val) *val=v.val();+ } else {+ if (size) *size=ss;+ }+#ifndef NDEBUG+ identify(); cerr << "getintinfo v" << var << ": min=" << v.min() << ", max=" << v.max() << ", med=" << v.med() << ", size=" << v.size() << ", val=" << ((v.size()<2) ? v.val() : -666) << "\n";+#endif+ }+ int testIntDomain(int var, int val) {+ assert(var>=0 && var<intVars.size());+ return intVars.at(var).in(val);+ }+ void getBoolInfo(int var, int *bound, int *val) {+ assert(var>=0 && var<boolVars.size());+ BoolVar &v = boolVars.at(var);+ if (v.assigned()) {+ if (bound) *bound=1;+ if (val) *val=v.val();+ } else {+ if (bound) *bound=0;+ }+ }++ void postIntValue(int var, int val) {+ assert(var>=0 && var<intVars.size());+#ifndef NDEBUG+ identify(); cerr << "intvalue v" << var << " = " << val << "\n";+#endif+ IntVar &v = intVars.at(var);+ rel(*this,v,IRT_EQ,val,icl);+ }++ void postIntSame(int var1, int var2) {+ assert(var1>=0 && var1<intVars.size());+ assert(var2>=0 && var2<intVars.size());+#ifndef NDEBUG+ identify(); cerr << "intsame v" << var1 << " = v" << var2 << "\n";+#endif+ IntVar &v1 = intVars.at(var1);+ IntVar &v2 = intVars.at(var2);+ rel(*this,v1,IRT_EQ,v2,icl);+ }++ void postIntDiff(int var1, int var2) {+ assert(var1>=0 && var1<intVars.size());+ assert(var2>=0 && var2<intVars.size());+#ifndef NDEBUG+ identify(); cerr << "intdiff v" << var1 << " != v" << var2 << "\n";+#endif+ IntVar &v1 = intVars.at(var1);+ IntVar &v2 = intVars.at(var2);+ rel(*this,v1,IRT_NQ,v2,icl);+ }+ + void postIntRel(int var1, goperator_t op, int var2) {+ assert(var1>=0 && var1<intVars.size());+ assert(var2>=0 && var2<intVars.size());+#ifndef NDEBUG+ identify(); cerr << "intrel v" << var1 << " " << (op==GOPERATOR_OEQUAL ? "==" : (op==GOPERATOR_OLESS ? "<" : "!=")) << " v" << var2 << "\n";+#endif+ IntVar &v1 = intVars.at(var1);+ IntVar &v2 = intVars.at(var2);+ rel(*this,v1,mapGoperator(op),v2,icl);+ }+ + void postIntRelCf(int v1, goperator_t op, int var2) {+ assert(var2>=0 && var2<intVars.size());+#ifndef NDEBUG+ identify(); cerr << "intrelcf " << v1 << " " << (op==GOPERATOR_OEQUAL ? "==" : (op==GOPERATOR_OLESS ? "<" : "!=")) << " v" << var2 << "\n";+#endif+ IntVar &v2 = intVars.at(var2);+ rel(*this,v2,mapGoperator(op,true),v1,icl);+ }++ void postIntRelCs(int var1, goperator_t op, int v2) {+ assert(var1>=0 && var1<intVars.size());+#ifndef NDEBUG+ identify(); cerr << "intrelcs v" << var1 << " " << (op==GOPERATOR_OEQUAL ? "==" : (op==GOPERATOR_OLESS ? "<" : "!=")) << " " << v2 << "\n";+#endif+ IntVar &v1 = intVars.at(var1);+ rel(*this,v1,mapGoperator(op),v2,icl);+ }++ void postIntMult(int var1, int var2, int varr) {+ assert(var1>=0 && var1<intVars.size());+ assert(var2>=0 && var2<intVars.size());+ assert(varr>=0 && varr<intVars.size());+#ifndef NDEBUG+ identify(); cerr << "intmult v" << var1 << " * v" << var2 << " = v" << varr << "\n";+#endif+ IntVar &v1 = intVars.at(var1);+ IntVar &v2 = intVars.at(var2);+ IntVar &vr = intVars.at(varr);+ mult(*this,v1,v2,vr,icl);+ }++ void postIntDiv(int var1, int var2, int varr) {+ assert(var1>=0 && var1<intVars.size());+ assert(var2>=0 && var2<intVars.size());+ assert(varr>=0 && varr<intVars.size());+#ifndef NDEBUG+ identify(); cerr << "intdiv v" << var1 << " / v" << var2 << " = v" << varr << "\n";+#endif+ IntVar &v1 = intVars.at(var1);+ IntVar &v2 = intVars.at(var2);+ IntVar &vr = intVars.at(varr);+ div(*this,v1,v2,vr,icl);+ }++ void postIntMod(int var1, int var2, int varr) {+ assert(var1>=0 && var1<intVars.size());+ assert(var2>=0 && var2<intVars.size());+ assert(varr>=0 && varr<intVars.size());+#ifndef NDEBUG+ identify(); cerr << "intmod v" << var1 << " mod v" << var2 << " = v" << varr << "\n";+#endif+ IntVar &v1 = intVars.at(var1);+ IntVar &v2 = intVars.at(var2);+ IntVar &vr = intVars.at(varr);+ mod(*this,v1,v2,vr,icl);+ }++ void postIntAbs(int var, int varr) {+ assert(var>=0 && var<intVars.size());+ assert(varr>=0 && varr<intVars.size());+#ifndef NDEBUG+ identify(); cerr << "intabs abs(v" << var << ") = v" << varr << "\n";+#endif+ IntVar &v = intVars.at(var);+ IntVar &vr = intVars.at(varr);+ abs(*this,v,vr,icl);+ }++ void postIntDom(int var, int low, int high) {+ assert(var>=0 && var<intVars.size());+#ifndef NDEBUG+ identify(); cerr << "intdom v" << var << " = [" << low << "," << high << "]\n";+#endif+ IntVar &v = intVars.at(var);+ dom(*this,v,low,high,icl);+ }++ void postIntLinear(int num, int *vars, int *coef, goperator_t op, int val) {+ IntVarArgs vrs(num);+ IntArgs vls(num,coef);+ for (int i=0; i<num; i++) {+ int id=vars[i];+ assert(id>=0 && id<intVars.size());+ vrs[i]=intVars.at(id);+ }+#ifndef NDEBUG+ identify(); cerr << "intlinear num=" << num << "\n";+#endif+ linear(*this,vls,vrs,mapGoperator(op),val,icl);+ }++ void postIntAlldiff(int num, int *vars) {+ IntVarArgs vrs(num);+ for (int i=0; i<num; i++) {+ int id=vars[i];+ assert(id>=0 && id<intVars.size());+ vrs[i]=intVars.at(id);+ }+#ifndef NDEBUG+ identify(); cerr << "intalldiff num=" << num << "\n";+#endif+ distinct(*this,vrs,icl);+ }++ void postIntSorted(int num, int *vars, int strict) {+ IntVarArgs vrs(num);+ for (int i=0; i<num; i++) {+ int id=vars[i];+ assert(id>=0 && id<intVars.size());+ vrs[i]=intVars.at(id);+ }+#ifndef NDEBUG+ identify(); cerr << "intsorted num=" << num << "\n";+#endif+ rel(*this,vrs,strict ? IRT_LE : IRT_LQ,icl);+ }++ void postIntBranching(int num, int *vars) {+ IntVarArgs vrs(num);+ for (int i=0; i<num; i++) {+ int id=vars[i];+ assert(id>=0 && id<intVars.size());+ vrs[i]=intVars.at(id);+ }+#ifndef NDEBUG+ identify(); cerr << "intbranch num=" << num << "\n";+#endif+ branch(*this,vrs, INT_VAR_SIZE_MIN, INT_VAL_SPLIT_MIN);+ }++ void postBoolBranching(int num, int *vars) {+ IntVarArgs vrs(num);+ for (int i=0; i<num; i++) {+ int id=vars[i];+ assert(id>=0 && id<intVars.size());+ vrs[i]=intVars.at(id);+ }+#ifndef NDEBUG+ identify(); cerr << "boolbranch num=" << num << "\n";+#endif+ branch(*this,vrs, INT_VAR_SIZE_MIN, INT_VAL_SPLIT_MIN);+ }+++};++extern "C" HaskellModel *gecode_model_create(void) { return new HaskellModel(); }+extern "C" HaskellModel *gecode_model_copy(HaskellModel *model) { return (HaskellModel*)(model->clone(true)); }+extern "C" HaskellModel *gecode_model_copy_reentrant(HaskellModel *model) { return (HaskellModel*)(model->clone(false)); }+extern "C" void gecode_model_fail(HaskellModel *model) { model->fail(); }+extern "C" void gecode_model_destroy(HaskellModel *model) { delete model; }+extern "C" int gecode_int_rel(HaskellModel *model, int v1, goperator_t op, int v2) { model->postIntRel(v1,op,v2); return !model->failed(); }+extern "C" int gecode_int_rel_cf(HaskellModel *model, int v1, goperator_t op, int v2) { model->postIntRelCf(v1,op,v2); return !model->failed(); }+extern "C" int gecode_int_rel_cs(HaskellModel *model, int v1, goperator_t op, int v2) { model->postIntRelCs(v1,op,v2); return !model->failed(); }+extern "C" int gecode_int_newvar(HaskellModel *model) { return model->addIntVar(-1000000000,1000000000); }+extern "C" int gecode_int_value(HaskellModel *model, int v, int val) { model->postIntValue(v,val); return !model->failed(); }+extern "C" int gecode_int_mult(HaskellModel *model, int v1, int v2, int vr) { model->postIntMult(v1,v2,vr); return !model->failed(); }+extern "C" int gecode_int_div(HaskellModel *model, int v1, int v2, int vr) { model->postIntDiv(v1,v2,vr); return !model->failed(); }+extern "C" int gecode_int_mod(HaskellModel *model, int v1, int v2, int vr) { model->postIntMod(v1,v2,vr); return !model->failed(); }+extern "C" int gecode_int_abs(HaskellModel *model, int v, int vr) { model->postIntAbs(v,vr); return !model->failed(); }+extern "C" int gecode_int_dom(HaskellModel *model, int v, int low, int high) { model->postIntDom(v,low,high); return !model->failed(); }+extern "C" int gecode_int_linear(HaskellModel *model, int num, int *vars, int *coef, goperator_t op, int val) { model->postIntLinear(num,vars,coef,op,val); return !model->failed(); }+extern "C" int gecode_int_alldiff(HaskellModel *model, int num, int *vars) { model->postIntAlldiff(num,vars); return !model->failed(); }+extern "C" int gecode_int_sorted(HaskellModel *model, int num, int *vars, int strict) { model->postIntSorted(num,vars,strict); return !model->failed(); }+extern "C" void gecode_int_branch(HaskellModel *model, int num, int *vars) { model->postIntBranching(num,vars); }+extern "C" void gecode_int_info(HaskellModel *model, int var, int *min, int *max, int *med, int *size, int *val) { model->getIntInfo(var,min,max,med,size,val); }+extern "C" int gecode_bool_newvar(HaskellModel *model) { return model->addBoolVar(0,1); }+extern "C" void gecode_bool_branch(HaskellModel *model, int num, int *vars) { model->postBoolBranching(num,vars); }++extern "C" DFS<HaskellModel> *gecode_search_create(HaskellModel *model) { + DFS<HaskellModel> *srch=new DFS<HaskellModel>(model);+#ifndef NDEBUG+ model->identify(); cerr << "search " << srch << " created\n";+#endif+ return srch;+}++extern "C" void gecode_search_destroy(DFS<HaskellModel> *search) { +#ifndef NDEBUG+ cerr << "[search " << search << "] destroyed\n";+#endif+ delete search;+}++extern "C" HaskellModel *gecode_search_next(DFS<HaskellModel> *search) { +#ifndef NDEBUG+ cerr << "[search " << search << "] requesting next\n";+#endif+ HaskellModel *res=search->next();+#ifndef NDEBUG+ cerr << "[search " << search << "] requested next (" << res << ")\n";+#endif+ return res;+}
monadiccp.cabal view
@@ -1,15 +1,41 @@-Name: monadiccp-Version: 0.5.2-Description: Monadic Constraint Programming framework-License: BSD3-License-file: LICENSE-Author: Tom Schrijvers -Maintainer: tom.schrijvers@cs.kuleuven.be-Build-Depends: base, containers, mtl, haskell98, random-Build-Type: Simple-Exposed-modules: Control.CP.ComposableTransformers Control.CP.PriorityQueue Control.CP.Queue Control.CP.Solver Control.CP.SearchTree Control.CP.Transformers Control.CP.FD.Domain Control.CP.FD.FD Control.CP.FD.FDSugar Control.CP.Herbrand.Herbrand Control.CP.Herbrand.PrologTerm Control.CP.Herbrand.Prolog Control.CP.Herbrand.HerbrandT-ghc-options: -Category: control-Synopsis: Constraint Programming-Homepage: http://www.cs.kuleuven.be/~toms/Haskell/-bug-reports: http://trac.haskell.org/monadiccp/+Name: monadiccp+Version: 0.6+Description: Monadic Constraint Programming framework+License: BSD3+License-file: LICENSE+Author: Tom Schrijvers, Pieter Wuille+Maintainer: tom.schrijvers@cs.kuleuven.be+Build-Type: Simple+Category: control+Synopsis: Constraint Programming+Homepage: http://www.cs.kuleuven.be/~toms/Haskell/+Bug-reports: http://trac.haskell.org/monadiccp/+Cabal-Version: >=1.6+Extra-Source-Files: examples/*.hs++-- examples/Alpha.hs examples/Grocery.hs examples/MagicSquare.hs examples/Olympic.hs examples/Partition.hs examples/Queens.hs examples/Ring.hs examples/StressDomain.hs examples/TryDemo.hs examples/Zebra.hs++Flag RuntimeGecode+ Description: Include the RuntimeSolver and SearchSolver for Gecode. Requires a working Gecode 3.1 installation.+ Default: False++Flag Debug+ Description: Generate debug output+ Default: False++library+ Build-Depends: base >= 2 && < 4, containers, mtl, haskell98, random+ Exposed-Modules: Control.CP.SearchTree Control.CP.Transformers Control.CP.FD.Gecode.Common Control.CP.FD.Gecode.Translate Control.CP.FD.Gecode.CodegenSolver Control.CP.FD.OvertonFD.Sugar Control.CP.FD.OvertonFD.OvertonFD Control.CP.FD.Solvers Control.CP.FD.FD Control.CP.FD.Example.Example Control.CP.FD.Expr Control.CP.Solver Control.CP.ComposableTransformers Control.CP.EnumTerm Control.CP.PriorityQueue Control.CP.Mixin Control.CP.Herbrand.PrologTerm Control.CP.Herbrand.Prolog Control.CP.Herbrand.Herbrand Control.CP.Herbrand.HerbrandT Control.CP.Queue+ Other-Modules: Control.CP.Debug Control.CP.FD.OvertonFD.Domain+ Include-Dirs: lib+ if flag(Debug)+ CPP-Options: -DDEBUG+ CC-Options: "-O1" "-ggdb3"+ else+ CC-Options: "-O3" "-g0" "-DNDEBUG"+ if flag(RuntimeGecode)+ C-Sources: lib/gecodeglue.cpp+ Extra-Libraries: gecodesupport gecodeset gecodeint gecodekernel gecodesearch+ Exposed-Modules: Control.CP.FD.Gecode.RuntimeSolver+ Other-Modules: Control.CP.FD.Gecode.Interface+ CPP-Options: -DRGECODE