@@ -4,7 +4,6 @@ module Distribution.Solver.Modular.Explore
4
4
, backjumpAndExplore
5
5
) where
6
6
7
- import Control.Monad.State.Lazy
8
7
import Data.Foldable as F
9
8
import Data.List as L (foldl' )
10
9
import Data.Map as M
@@ -20,8 +19,6 @@ import Distribution.Solver.Types.PackagePath
20
19
import Distribution.Solver.Types.Settings (EnableBackjumping (.. ), CountConflicts (.. ))
21
20
import qualified Distribution.Solver.Types.Progress as P
22
21
23
- type Explore = State ConflictMap
24
-
25
22
-- | This function takes the variable we're currently considering, an
26
23
-- initial conflict set and a
27
24
-- list of children's logs. Each log yields either a solution or a
@@ -46,29 +43,29 @@ type Explore = State ConflictMap
46
43
-- variable. See also the comments for 'avoidSet'.
47
44
--
48
45
backjump :: EnableBackjumping -> Var QPN
49
- -> ConflictSet QPN -> P. PSQ k (Explore ( ConflictSetLog a ) )
50
- -> Explore ( ConflictSetLog a )
46
+ -> ConflictSet QPN -> P. PSQ k (ConflictMap -> ConflictSetLog a )
47
+ -> ConflictMap -> ConflictSetLog a
51
48
backjump (EnableBackjumping enableBj) var initial xs =
52
49
F. foldr combine logBackjump xs initial
53
50
where
54
- combine :: Explore ( ConflictSetLog a )
55
- -> (ConflictSet QPN -> Explore ( ConflictSetLog a ) )
56
- -> ConflictSet QPN -> Explore ( ConflictSetLog a )
57
- combine x f csAcc = do
58
- l <- x
59
- case l of
60
- P. Done d -> return ( P. Done d)
61
- P. Fail cs
62
- | enableBj && not (var `CS.member` cs) -> logBackjump cs
63
- | otherwise -> f (csAcc `CS.union` cs)
64
- P. Step m ms -> do
65
- l' <- combine (return ms) f csAcc
66
- return ( P. Step m l')
51
+ combine :: ( ConflictMap -> ConflictSetLog a )
52
+ -> (ConflictSet QPN -> ConflictMap -> ConflictSetLog a )
53
+ -> ConflictSet QPN -> ConflictMap -> ConflictSetLog a
54
+ combine x f csAcc cm =
55
+ let l = x cm
56
+ in case l of
57
+ P. Done d -> P. Done d
58
+ P. Fail (cs, cm')
59
+ | enableBj && not (var `CS.member` cs) -> logBackjump cs cm'
60
+ | otherwise -> f (csAcc `CS.union` cs) cm'
61
+ P. Step m ms ->
62
+ let l' = combine (\ _ -> ms) f csAcc cm
63
+ in P. Step m l'
67
64
68
- logBackjump :: ConflictSet QPN -> Explore ( ConflictSetLog a )
69
- logBackjump cs = return ( failWith (Failure cs Backjump ) cs )
65
+ logBackjump :: ConflictSet QPN -> ConflictMap -> ConflictSetLog a
66
+ logBackjump cs cm = failWith (Failure cs Backjump ) (cs, cm )
70
67
71
- type ConflictSetLog = P. Progress Message (ConflictSet QPN )
68
+ type ConflictSetLog = P. Progress Message (ConflictSet QPN , ConflictMap )
72
69
73
70
type ConflictMap = Map (Var QPN ) Int
74
71
@@ -95,51 +92,54 @@ updateCM cs cm =
95
92
-- | A tree traversal that simultaneously propagates conflict sets up
96
93
-- the tree from the leaves and creates a log.
97
94
exploreLog :: EnableBackjumping -> CountConflicts -> Tree QGoalReason
98
- -> (Assignment -> Explore ( ConflictSetLog (Assignment , RevDepMap ) ))
95
+ -> (Assignment -> ConflictMap -> ConflictSetLog (Assignment , RevDepMap ))
99
96
exploreLog enableBj (CountConflicts countConflicts) = cata go
100
97
where
101
- updateCM' :: ConflictSet QPN -> Explore a -> Explore a
98
+ updateCM' :: ConflictSet QPN -> ConflictMap -> ConflictMap
102
99
updateCM'
103
- | countConflicts = \ c k -> modify' ( updateCM c) >> k
104
- | otherwise = \ _ k -> k
100
+ | countConflicts = \ c cm -> updateCM c cm
101
+ | otherwise = \ _ cm -> cm
105
102
106
- getBestGoal' :: P. PSQ (Goal QPN ) a -> Explore (Goal QPN , a )
103
+ getBestGoal' :: P. PSQ (Goal QPN ) a -> ConflictMap -> (Goal QPN , a )
107
104
getBestGoal'
108
- | countConflicts = \ ts -> get >>= \ cm -> return ( getBestGoal cm ts)
109
- | otherwise = return . getFirstGoal
105
+ | countConflicts = \ ts cm -> getBestGoal cm ts
106
+ | otherwise = \ ts _ -> getFirstGoal ts
110
107
111
- go :: TreeF QGoalReason (Assignment -> Explore (ConflictSetLog (Assignment , RevDepMap )))
112
- -> (Assignment -> Explore (ConflictSetLog (Assignment , RevDepMap )))
113
- go (FailF c fr) _ = updateCM' c (return (failWith (Failure c fr) c))
114
- go (DoneF rdm) a = return (succeedWith Success (a, rdm))
108
+ go :: TreeF QGoalReason (Assignment -> ConflictMap -> ConflictSetLog (Assignment , RevDepMap ))
109
+ -> (Assignment -> ConflictMap -> ConflictSetLog (Assignment , RevDepMap ))
110
+ go (FailF c fr) _ = \ cm -> let failure = failWith (Failure c fr)
111
+ in if countConflicts
112
+ then failure (c, updateCM' c cm)
113
+ else failure (c, cm)
114
+ go (DoneF rdm) a = \ _ -> succeedWith Success (a, rdm)
115
115
go (PChoiceF qpn gr ts) (A pa fa sa) =
116
116
backjump enableBj (P qpn) (avoidSet (P qpn) gr) $ -- try children in order,
117
117
P. mapWithKey -- when descending ...
118
- (\ i@ (POption k _) r -> do
119
- l <- r (A (M. insert qpn k pa) fa sa)
120
- return ( tryWith (TryP qpn i) l)
118
+ (\ i@ (POption k _) r cm ->
119
+ let l = r (A (M. insert qpn k pa) fa sa) cm
120
+ in tryWith (TryP qpn i) l
121
121
)
122
122
ts
123
123
go (FChoiceF qfn gr _ _ ts) (A pa fa sa) =
124
124
backjump enableBj (F qfn) (avoidSet (F qfn) gr) $ -- try children in order,
125
125
P. mapWithKey -- when descending ...
126
- (\ k r -> do
127
- l <- r (A pa (M. insert qfn k fa) sa)
128
- return ( tryWith (TryF qfn k) l)
126
+ (\ k r cm ->
127
+ let l = r (A pa (M. insert qfn k fa) sa) cm
128
+ in tryWith (TryF qfn k) l
129
129
)
130
130
ts
131
131
go (SChoiceF qsn gr _ ts) (A pa fa sa) =
132
132
backjump enableBj (S qsn) (avoidSet (S qsn) gr) $ -- try children in order,
133
133
P. mapWithKey -- when descending ...
134
- (\ k r -> do
135
- l <- r (A pa fa (M. insert qsn k sa))
136
- return ( tryWith (TryS qsn k) l)
134
+ (\ k r cm ->
135
+ let l = r (A pa fa (M. insert qsn k sa)) cm
136
+ in tryWith (TryS qsn k) l
137
137
)
138
138
ts
139
- go (GoalChoiceF ts) a = do
140
- (k, v) <- getBestGoal' ts
141
- l <- v a
142
- return ( continueWith (Next k) l)
139
+ go (GoalChoiceF ts) a = \ cm ->
140
+ let (k, v) = getBestGoal' ts cm
141
+ l = v a cm
142
+ in continueWith (Next k) l
143
143
144
144
-- | Build a conflict set corresponding to the (virtual) option not to
145
145
-- choose a solution for a goal at all.
@@ -173,7 +173,7 @@ backjumpAndExplore :: EnableBackjumping
173
173
-> CountConflicts
174
174
-> Tree QGoalReason -> Log Message (Assignment , RevDepMap )
175
175
backjumpAndExplore enableBj countConflicts t =
176
- toLog $ fst $ runState (exploreLog enableBj countConflicts t (A M. empty M. empty M. empty)) M. empty
176
+ toLog $ (exploreLog enableBj countConflicts t (A M. empty M. empty M. empty)) M. empty
177
177
where
178
178
toLog :: P. Progress step fail done -> Log step done
179
179
toLog = P. foldProgress P. Step (const (P. Fail () )) P. Done
0 commit comments