Skip to content

Commit 192e1b4

Browse files
committed
Add option to find best install plan before backjump limit
1 parent f723563 commit 192e1b4

File tree

17 files changed

+369
-141
lines changed

17 files changed

+369
-141
lines changed

cabal-install/Distribution/Client/Config.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ instance Semigroup SavedConfig where
239239
installDryRun = combine installDryRun,
240240
installMaxBackjumps = combine installMaxBackjumps,
241241
installMaxScore = combine installMaxScore,
242+
installFindBestSolution = combine installFindBestSolution,
242243
installReorderGoals = combine installReorderGoals,
243244
installIndependentGoals = combine installIndependentGoals,
244245
installShadowPkgs = combine installShadowPkgs,

cabal-install/Distribution/Client/Dependency.hs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ module Distribution.Client.Dependency (
5454
setMaxBackjumps,
5555
setEnableBackjumping,
5656
setMaxScore,
57+
setFindBestSolution,
5758
addSourcePackages,
5859
hideInstalledPackagesSpecificByUnitId,
5960
hideInstalledPackagesSpecificBySourcePackageId,
@@ -159,7 +160,8 @@ data DepResolverParams = DepResolverParams {
159160
depResolverStrongFlags :: StrongFlags,
160161
depResolverMaxBackjumps :: Maybe Int,
161162
depResolverEnableBackjumping :: EnableBackjumping,
162-
depResolverMaxScore :: Maybe InstallPlanScore
163+
depResolverMaxScore :: Maybe InstallPlanScore,
164+
depResolverFindBestSolution :: FindBestSolution
163165
}
164166

165167
showDepResolverParams :: DepResolverParams -> String
@@ -232,7 +234,8 @@ basicDepResolverParams installedPkgIndex sourcePkgIndex =
232234
depResolverStrongFlags = StrongFlags False,
233235
depResolverMaxBackjumps = Nothing,
234236
depResolverEnableBackjumping = EnableBackjumping True,
235-
depResolverMaxScore = Nothing
237+
depResolverMaxScore = Nothing,
238+
depResolverFindBestSolution = FindBestSolution False
236239
}
237240

238241
addTargets :: [PackageName]
@@ -313,6 +316,12 @@ setMaxScore n params =
313316
depResolverMaxScore = n
314317
}
315318

319+
setFindBestSolution :: FindBestSolution -> DepResolverParams -> DepResolverParams
320+
setFindBestSolution findBest params =
321+
params {
322+
depResolverFindBestSolution = findBest
323+
}
324+
316325
-- | Some packages are specific to a given compiler version and should never be
317326
-- upgraded.
318327
dontUpgradeNonUpgradeablePackages :: DepResolverParams -> DepResolverParams
@@ -596,7 +605,7 @@ resolveDependencies platform comp pkgConfigDB solver params =
596605
Step (showDepResolverParams finalparams)
597606
$ fmap (uncurry $ validateSolverResult platform comp indGoals)
598607
$ runSolver solver (SolverConfig reorderGoals indGoals noReinstalls
599-
shadowing strFlags maxBkjumps enableBj mScore)
608+
shadowing strFlags maxBkjumps enableBj mScore findBest)
600609
platform comp installedPkgIndex sourcePkgIndex
601610
pkgConfigDB preferences constraints targets
602611
where
@@ -613,15 +622,16 @@ resolveDependencies platform comp pkgConfigDB solver params =
613622
strFlags
614623
maxBkjumps
615624
enableBj
616-
mScore) = dontUpgradeNonUpgradeablePackages
625+
mScore
626+
findBest) = dontUpgradeNonUpgradeablePackages
617627
-- TODO:
618628
-- The modular solver can properly deal with broken
619629
-- packages and won't select them. So the
620630
-- 'hideBrokenInstalledPackages' function should be moved
621631
-- into a module that is specific to the top-down solver.
622-
. (if solver /= Modular then hideBrokenInstalledPackages
623-
else id)
624-
$ params
632+
. (if solver /= Modular then hideBrokenInstalledPackages
633+
else id)
634+
$ params
625635

626636
preferences = interpretPackagesPreference
627637
(Set.fromList targets) defpref prefs
@@ -849,7 +859,8 @@ resolveWithoutDependencies :: DepResolverParams
849859
resolveWithoutDependencies (DepResolverParams targets constraints
850860
prefs defpref installedPkgIndex sourcePkgIndex
851861
_reorderGoals _indGoals _avoidReinstalls
852-
_shadowing _strFlags _maxBjumps _enableBj _maxScore) =
862+
_shadowing _strFlags _maxBjumps _enableBj _maxScore
863+
_findBest) =
853864
collectEithers (map selectPackage targets)
854865
where
855866
selectPackage :: PackageName -> Either ResolveNoDepsError UnresolvedSourcePackage

cabal-install/Distribution/Client/Install.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,8 @@ planPackages comp platform mSandboxPkgInfo solver
369369

370370
. setMaxScore maxScore
371371

372+
. setFindBestSolution findBest
373+
372374
. setIndependentGoals independentGoals
373375

374376
. setReorderGoals reorderGoals
@@ -431,6 +433,7 @@ planPackages comp platform mSandboxPkgInfo solver
431433
strongFlags = fromFlag (installStrongFlags installFlags)
432434
maxBackjumps = fromFlag (installMaxBackjumps installFlags)
433435
maxScore = flagToMaybe (installMaxScore installFlags)
436+
findBest = fromFlag (installFindBestSolution installFlags)
434437
upgradeDeps = fromFlag (installUpgradeDeps installFlags)
435438
onlyDeps = fromFlag (installOnlyDeps installFlags)
436439
allowNewer = fromMaybe AllowNewerNone (configAllowNewer configFlags)

cabal-install/Distribution/Client/ProjectConfig/Legacy.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,7 @@ convertToLegacySharedConfig
495495
installMaxBackjumps = projectConfigMaxBackjumps,
496496
installMaxScore = mempty, --projectConfigMaxScore,
497497
installUpgradeDeps = mempty, --projectConfigUpgradeDeps,
498+
installFindBestSolution = mempty, --projectConfigFindBestSolution,
498499
installReorderGoals = projectConfigReorderGoals,
499500
installIndependentGoals = mempty, --projectConfigIndependentGoals,
500501
installShadowPkgs = mempty, --projectConfigShadowPkgs,

cabal-install/Distribution/Client/Setup.hs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,7 @@ data FetchFlags = FetchFlags {
605605
fetchSolver :: Flag PreSolver,
606606
fetchMaxBackjumps :: Flag Int,
607607
fetchMaxScore :: Flag InstallPlanScore,
608+
fetchFindBestSolution :: Flag FindBestSolution,
608609
fetchReorderGoals :: Flag ReorderGoals,
609610
fetchIndependentGoals :: Flag IndependentGoals,
610611
fetchShadowPkgs :: Flag ShadowPkgs,
@@ -620,6 +621,7 @@ defaultFetchFlags = FetchFlags {
620621
fetchSolver = Flag defaultSolver,
621622
fetchMaxBackjumps = Flag defaultMaxBackjumps,
622623
fetchMaxScore = mempty,
624+
fetchFindBestSolution = Flag (FindBestSolution False),
623625
fetchReorderGoals = Flag (ReorderGoals False),
624626
fetchIndependentGoals = Flag (IndependentGoals False),
625627
fetchShadowPkgs = Flag (ShadowPkgs False),
@@ -667,6 +669,7 @@ fetchCommand = CommandUI {
667669
optionSolverFlags showOrParseArgs
668670
fetchMaxBackjumps (\v flags -> flags { fetchMaxBackjumps = v })
669671
fetchMaxScore (\v flags -> flags { fetchMaxScore = v })
672+
fetchFindBestSolution (\v flags -> flags { fetchFindBestSolution = v })
670673
fetchReorderGoals (\v flags -> flags { fetchReorderGoals = v })
671674
fetchIndependentGoals (\v flags -> flags { fetchIndependentGoals = v })
672675
fetchShadowPkgs (\v flags -> flags { fetchShadowPkgs = v })
@@ -685,6 +688,7 @@ data FreezeFlags = FreezeFlags {
685688
freezeSolver :: Flag PreSolver,
686689
freezeMaxBackjumps :: Flag Int,
687690
freezeMaxScore :: Flag InstallPlanScore,
691+
freezeFindBestSolution :: Flag FindBestSolution,
688692
freezeReorderGoals :: Flag ReorderGoals,
689693
freezeIndependentGoals :: Flag IndependentGoals,
690694
freezeShadowPkgs :: Flag ShadowPkgs,
@@ -700,6 +704,7 @@ defaultFreezeFlags = FreezeFlags {
700704
freezeSolver = Flag defaultSolver,
701705
freezeMaxBackjumps = Flag defaultMaxBackjumps,
702706
freezeMaxScore = mempty,
707+
freezeFindBestSolution = Flag (FindBestSolution False),
703708
freezeReorderGoals = Flag (ReorderGoals False),
704709
freezeIndependentGoals = Flag (IndependentGoals False),
705710
freezeShadowPkgs = Flag (ShadowPkgs False),
@@ -746,6 +751,7 @@ freezeCommand = CommandUI {
746751
optionSolverFlags showOrParseArgs
747752
freezeMaxBackjumps (\v flags -> flags { freezeMaxBackjumps = v })
748753
freezeMaxScore (\v flags -> flags { freezeMaxScore = v })
754+
freezeFindBestSolution (\v flags -> flags { freezeFindBestSolution = v })
749755
freezeReorderGoals (\v flags -> flags { freezeReorderGoals = v })
750756
freezeIndependentGoals (\v flags -> flags { freezeIndependentGoals = v })
751757
freezeShadowPkgs (\v flags -> flags { freezeShadowPkgs = v })
@@ -1149,6 +1155,7 @@ data InstallFlags = InstallFlags {
11491155
installDryRun :: Flag Bool,
11501156
installMaxBackjumps :: Flag Int,
11511157
installMaxScore :: Flag InstallPlanScore,
1158+
installFindBestSolution :: Flag FindBestSolution,
11521159
installReorderGoals :: Flag ReorderGoals,
11531160
installIndependentGoals :: Flag IndependentGoals,
11541161
installShadowPkgs :: Flag ShadowPkgs,
@@ -1181,6 +1188,7 @@ defaultInstallFlags = InstallFlags {
11811188
installDryRun = Flag False,
11821189
installMaxBackjumps = Flag defaultMaxBackjumps,
11831190
installMaxScore = mempty,
1191+
installFindBestSolution= Flag (FindBestSolution False),
11841192
installReorderGoals = Flag (ReorderGoals False),
11851193
installIndependentGoals= Flag (IndependentGoals False),
11861194
installShadowPkgs = Flag (ShadowPkgs False),
@@ -1326,6 +1334,7 @@ installOptions showOrParseArgs =
13261334
optionSolverFlags showOrParseArgs
13271335
installMaxBackjumps (\v flags -> flags { installMaxBackjumps = v })
13281336
installMaxScore (\v flags -> flags { installMaxScore = v })
1337+
installFindBestSolution (\v flags -> flags { installFindBestSolution = v })
13291338
installReorderGoals (\v flags -> flags { installReorderGoals = v })
13301339
installIndependentGoals (\v flags -> flags { installIndependentGoals = v })
13311340
installShadowPkgs (\v flags -> flags { installShadowPkgs = v })
@@ -2079,12 +2088,13 @@ optionSolver get set =
20792088
optionSolverFlags :: ShowOrParseArgs
20802089
-> (flags -> Flag Int ) -> (Flag Int -> flags -> flags)
20812090
-> (flags -> Flag InstallPlanScore) -> (Flag InstallPlanScore -> flags -> flags)
2091+
-> (flags -> Flag FindBestSolution) -> (Flag FindBestSolution -> flags -> flags)
20822092
-> (flags -> Flag ReorderGoals) -> (Flag ReorderGoals -> flags -> flags)
20832093
-> (flags -> Flag IndependentGoals) -> (Flag IndependentGoals -> flags -> flags)
20842094
-> (flags -> Flag ShadowPkgs) -> (Flag ShadowPkgs -> flags -> flags)
20852095
-> (flags -> Flag StrongFlags) -> (Flag StrongFlags -> flags -> flags)
20862096
-> [OptionField flags]
2087-
optionSolverFlags showOrParseArgs getmbj setmbj getms setms getrg setrg _getig _setig getsip setsip getstrfl setstrfl =
2097+
optionSolverFlags showOrParseArgs getmbj setmbj getms setms getfb setfb getrg setrg _getig _setig getsip setsip getstrfl setstrfl =
20882098
[ option [] ["max-backjumps"]
20892099
("Maximum number of backjumps allowed while solving (default: " ++ show defaultMaxBackjumps ++ "). Use a negative number to enable unlimited backtracking. Use 0 to disable backtracking completely.")
20902100
getmbj setmbj
@@ -2096,6 +2106,11 @@ optionSolverFlags showOrParseArgs getmbj setmbj getms setms getrg setrg _getig _
20962106
(setms . fmap InstallPlanScore)
20972107
(reqArg "NUM" (readP_to_E ("Cannot parse number: "++) (fmap (toFlag . (fromIntegral :: Int -> Double)) parse))
20982108
(map show . flagToList))
2109+
, option [] ["find-best-solution"]
2110+
"Find the best-scoring solution within the backjump limit."
2111+
(fmap asBool . getfb)
2112+
(setfb . fmap FindBestSolution)
2113+
(yesNoOpt showOrParseArgs)
20992114
, option [] ["reorder-goals"]
21002115
"Try to reorder goals according to certain heuristics. Slows things down on average, but may make backtracking faster for some packages."
21012116
(fmap asBool . getrg)

cabal-install/Distribution/Solver/Modular/Cycles.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ import Distribution.Solver.Modular.Tree
1414
import qualified Distribution.Solver.Modular.ConflictSet as CS
1515

1616
-- | Find and reject any solutions that are cyclic
17-
detectCyclesPhase :: Tree a QGoalReason -> Tree a QGoalReason
17+
detectCyclesPhase :: Tree a b -> Tree a b
1818
detectCyclesPhase = cata go
1919
where
2020
-- The only node of interest is DoneF
21-
go :: TreeF a QGoalReason (Tree a QGoalReason) -> Tree a QGoalReason
21+
go :: TreeF a b (Tree a b) -> Tree a b
2222
go (PChoiceF qpn gr cs) = PChoice qpn gr cs
2323
go (FChoiceF qfn gr w m cs) = FChoice qfn gr w m cs
2424
go (SChoiceF qsn gr w cs) = SChoice qsn gr w cs

cabal-install/Distribution/Solver/Modular/Dependency.hs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ module Distribution.Solver.Modular.Dependency (
99
, ConflictSet
1010
, CS.ConflictType(..)
1111
, CS.showCS
12+
-- * Install plan scoring
13+
, ScoringState(..)
1214
-- * Constrained instances
1315
, CI(..)
1416
, merge
@@ -56,6 +58,21 @@ import Distribution.Solver.Modular.Version
5658
import qualified Distribution.Solver.Modular.ConflictSet as CS
5759

5860
import Distribution.Solver.Types.ComponentDeps (Component(..))
61+
import Distribution.Solver.Types.Settings
62+
63+
{-------------------------------------------------------------------------------
64+
Install plan scoring
65+
-------------------------------------------------------------------------------}
66+
67+
-- | State used for finding solutions based on score. Storing 'ScoringState' on
68+
-- nodes allows the nodes to be scored before the cutoff score is known.
69+
data ScoringState = ScoringState {
70+
-- | The sum of the scores of all nodes from the root to the current node.
71+
ssTotalScore :: InstallPlanScore
72+
73+
-- | The conflict set that should be used if a node exceeds the max score.
74+
, ssConflictSet :: ConflictSet QPN
75+
}
5976

6077
{-------------------------------------------------------------------------------
6178
Constrained instances

0 commit comments

Comments
 (0)