Skip to content

Commit 21793a4

Browse files
committed
Add option to find best install plan before backjump limit
1 parent c38ebbd commit 21793a4

File tree

17 files changed

+375
-135
lines changed

17 files changed

+375
-135
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
installCountConflicts = combine installCountConflicts,
244245
installIndependentGoals = combine installIndependentGoals,

cabal-install/Distribution/Client/Dependency.hs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ module Distribution.Client.Dependency (
5757
setEnableBackjumping,
5858
setGoalOrder,
5959
setMaxScore,
60+
setFindBestSolution,
6061
addSourcePackages,
6162
hideInstalledPackagesSpecificByUnitId,
6263
hideInstalledPackagesSpecificBySourcePackageId,
@@ -171,7 +172,8 @@ data DepResolverParams = DepResolverParams {
171172

172173
-- | Function to override the solver's goal-ordering heuristics.
173174
depResolverGoalOrder :: Maybe (Variable QPN -> Variable QPN -> Ordering),
174-
depResolverMaxScore :: Maybe InstallPlanScore
175+
depResolverMaxScore :: Maybe InstallPlanScore,
176+
depResolverFindBestSolution :: FindBestSolution
175177
}
176178

177179
showDepResolverParams :: DepResolverParams -> String
@@ -247,7 +249,8 @@ basicDepResolverParams installedPkgIndex sourcePkgIndex =
247249
depResolverMaxBackjumps = Nothing,
248250
depResolverEnableBackjumping = EnableBackjumping True,
249251
depResolverGoalOrder = Nothing,
250-
depResolverMaxScore = Nothing
252+
depResolverMaxScore = Nothing,
253+
depResolverFindBestSolution = FindBestSolution False
251254
}
252255

253256
addTargets :: [PackageName]
@@ -342,6 +345,12 @@ setMaxScore n params =
342345
depResolverMaxScore = n
343346
}
344347

348+
setFindBestSolution :: FindBestSolution -> DepResolverParams -> DepResolverParams
349+
setFindBestSolution findBest params =
350+
params {
351+
depResolverFindBestSolution = findBest
352+
}
353+
345354
-- | Some packages are specific to a given compiler version and should never be
346355
-- upgraded.
347356
dontUpgradeNonUpgradeablePackages :: DepResolverParams -> DepResolverParams
@@ -642,7 +651,7 @@ resolveDependencies platform comp pkgConfigDB solver params =
642651
Step (showDepResolverParams finalparams)
643652
$ fmap (uncurry $ validateSolverResult platform comp indGoals)
644653
$ runSolver solver (SolverConfig reordGoals cntConflicts indGoals noReinstalls
645-
shadowing strFlags maxBkjumps enableBj order mScore)
654+
shadowing strFlags maxBkjumps enableBj order mScore findBest)
646655
platform comp installedPkgIndex sourcePkgIndex
647656
pkgConfigDB preferences constraints targets
648657
where
@@ -661,7 +670,8 @@ resolveDependencies platform comp pkgConfigDB solver params =
661670
maxBkjumps
662671
enableBj
663672
order
664-
mScore) = dontUpgradeNonUpgradeablePackages
673+
mScore
674+
findBest) = dontUpgradeNonUpgradeablePackages
665675
-- TODO:
666676
-- The modular solver can properly deal with broken
667677
-- packages and won't select them. So the
@@ -895,7 +905,8 @@ resolveWithoutDependencies :: DepResolverParams
895905
resolveWithoutDependencies (DepResolverParams targets constraints
896906
prefs defpref installedPkgIndex sourcePkgIndex
897907
_reorderGoals _countConflicts _indGoals _avoidReinstalls
898-
_shadowing _strFlags _maxBjumps _enableBj _order _maxScore) =
908+
_shadowing _strFlags _maxBjumps _enableBj _order _maxScore
909+
_findBest) =
899910
collectEithers (map selectPackage targets)
900911
where
901912
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
@@ -380,6 +380,8 @@ planPackages comp platform mSandboxPkgInfo solver
380380

381381
. setMaxScore maxScore
382382

383+
. setFindBestSolution findBest
384+
383385
. setIndependentGoals independentGoals
384386

385387
. setReorderGoals reorderGoals
@@ -445,6 +447,7 @@ planPackages comp platform mSandboxPkgInfo solver
445447
strongFlags = fromFlag (installStrongFlags installFlags)
446448
maxBackjumps = fromFlag (installMaxBackjumps installFlags)
447449
maxScore = flagToMaybe (installMaxScore installFlags)
450+
findBest = fromFlag (installFindBestSolution installFlags)
448451
upgradeDeps = fromFlag (installUpgradeDeps installFlags)
449452
onlyDeps = fromFlag (installOnlyDeps installFlags)
450453
allowNewer = maybe RelaxDepsNone unAllowNewer (configAllowNewer configFlags)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,7 @@ convertToLegacySharedConfig
497497
installMaxBackjumps = projectConfigMaxBackjumps,
498498
installMaxScore = mempty, --projectConfigMaxScore,
499499
installUpgradeDeps = mempty, --projectConfigUpgradeDeps,
500+
installFindBestSolution = mempty, --projectConfigFindBestSolution,
500501
installReorderGoals = projectConfigReorderGoals,
501502
installCountConflicts = projectConfigCountConflicts,
502503
installIndependentGoals = mempty, --projectConfigIndependentGoals,

cabal-install/Distribution/Client/Setup.hs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,7 @@ data FetchFlags = FetchFlags {
606606
fetchSolver :: Flag PreSolver,
607607
fetchMaxBackjumps :: Flag Int,
608608
fetchMaxScore :: Flag InstallPlanScore,
609+
fetchFindBestSolution :: Flag FindBestSolution,
609610
fetchReorderGoals :: Flag ReorderGoals,
610611
fetchCountConflicts :: Flag CountConflicts,
611612
fetchIndependentGoals :: Flag IndependentGoals,
@@ -622,6 +623,7 @@ defaultFetchFlags = FetchFlags {
622623
fetchSolver = Flag defaultSolver,
623624
fetchMaxBackjumps = Flag defaultMaxBackjumps,
624625
fetchMaxScore = mempty,
626+
fetchFindBestSolution = Flag (FindBestSolution False),
625627
fetchReorderGoals = Flag (ReorderGoals False),
626628
fetchCountConflicts = Flag (CountConflicts True),
627629
fetchIndependentGoals = Flag (IndependentGoals False),
@@ -670,6 +672,7 @@ fetchCommand = CommandUI {
670672
optionSolverFlags showOrParseArgs
671673
fetchMaxBackjumps (\v flags -> flags { fetchMaxBackjumps = v })
672674
fetchMaxScore (\v flags -> flags { fetchMaxScore = v })
675+
fetchFindBestSolution (\v flags -> flags { fetchFindBestSolution = v })
673676
fetchReorderGoals (\v flags -> flags { fetchReorderGoals = v })
674677
fetchCountConflicts (\v flags -> flags { fetchCountConflicts = v })
675678
fetchIndependentGoals (\v flags -> flags { fetchIndependentGoals = v })
@@ -689,6 +692,7 @@ data FreezeFlags = FreezeFlags {
689692
freezeSolver :: Flag PreSolver,
690693
freezeMaxBackjumps :: Flag Int,
691694
freezeMaxScore :: Flag InstallPlanScore,
695+
freezeFindBestSolution :: Flag FindBestSolution,
692696
freezeReorderGoals :: Flag ReorderGoals,
693697
freezeCountConflicts :: Flag CountConflicts,
694698
freezeIndependentGoals :: Flag IndependentGoals,
@@ -705,6 +709,7 @@ defaultFreezeFlags = FreezeFlags {
705709
freezeSolver = Flag defaultSolver,
706710
freezeMaxBackjumps = Flag defaultMaxBackjumps,
707711
freezeMaxScore = mempty,
712+
freezeFindBestSolution = Flag (FindBestSolution False),
708713
freezeReorderGoals = Flag (ReorderGoals False),
709714
freezeCountConflicts = Flag (CountConflicts True),
710715
freezeIndependentGoals = Flag (IndependentGoals False),
@@ -752,6 +757,7 @@ freezeCommand = CommandUI {
752757
optionSolverFlags showOrParseArgs
753758
freezeMaxBackjumps (\v flags -> flags { freezeMaxBackjumps = v })
754759
freezeMaxScore (\v flags -> flags { freezeMaxScore = v })
760+
freezeFindBestSolution (\v flags -> flags { freezeFindBestSolution = v })
755761
freezeReorderGoals (\v flags -> flags { freezeReorderGoals = v })
756762
freezeCountConflicts (\v flags -> flags { freezeCountConflicts = v })
757763
freezeIndependentGoals (\v flags -> flags { freezeIndependentGoals = v })
@@ -1156,6 +1162,7 @@ data InstallFlags = InstallFlags {
11561162
installDryRun :: Flag Bool,
11571163
installMaxBackjumps :: Flag Int,
11581164
installMaxScore :: Flag InstallPlanScore,
1165+
installFindBestSolution :: Flag FindBestSolution,
11591166
installReorderGoals :: Flag ReorderGoals,
11601167
installCountConflicts :: Flag CountConflicts,
11611168
installIndependentGoals :: Flag IndependentGoals,
@@ -1190,6 +1197,7 @@ defaultInstallFlags = InstallFlags {
11901197
installDryRun = Flag False,
11911198
installMaxBackjumps = Flag defaultMaxBackjumps,
11921199
installMaxScore = mempty,
1200+
installFindBestSolution= Flag (FindBestSolution False),
11931201
installReorderGoals = Flag (ReorderGoals False),
11941202
installCountConflicts = Flag (CountConflicts True),
11951203
installIndependentGoals= Flag (IndependentGoals False),
@@ -1337,6 +1345,7 @@ installOptions showOrParseArgs =
13371345
optionSolverFlags showOrParseArgs
13381346
installMaxBackjumps (\v flags -> flags { installMaxBackjumps = v })
13391347
installMaxScore (\v flags -> flags { installMaxScore = v })
1348+
installFindBestSolution (\v flags -> flags { installFindBestSolution = v })
13401349
installReorderGoals (\v flags -> flags { installReorderGoals = v })
13411350
installCountConflicts (\v flags -> flags { installCountConflicts = v })
13421351
installIndependentGoals (\v flags -> flags { installIndependentGoals = v })
@@ -2104,13 +2113,14 @@ optionSolver get set =
21042113
optionSolverFlags :: ShowOrParseArgs
21052114
-> (flags -> Flag Int ) -> (Flag Int -> flags -> flags)
21062115
-> (flags -> Flag InstallPlanScore) -> (Flag InstallPlanScore -> flags -> flags)
2116+
-> (flags -> Flag FindBestSolution) -> (Flag FindBestSolution -> flags -> flags)
21072117
-> (flags -> Flag ReorderGoals) -> (Flag ReorderGoals -> flags -> flags)
21082118
-> (flags -> Flag CountConflicts) -> (Flag CountConflicts -> flags -> flags)
21092119
-> (flags -> Flag IndependentGoals) -> (Flag IndependentGoals -> flags -> flags)
21102120
-> (flags -> Flag ShadowPkgs) -> (Flag ShadowPkgs -> flags -> flags)
21112121
-> (flags -> Flag StrongFlags) -> (Flag StrongFlags -> flags -> flags)
21122122
-> [OptionField flags]
2113-
optionSolverFlags showOrParseArgs getmbj setmbj getms setms getrg setrg getcc setcc _getig _setig getsip setsip getstrfl setstrfl =
2123+
optionSolverFlags showOrParseArgs getmbj setmbj getms setms getfb setfb getrg setrg getcc setcc _getig _setig getsip setsip getstrfl setstrfl =
21142124
[ option [] ["max-backjumps"]
21152125
("Maximum number of backjumps allowed while solving (default: " ++ show defaultMaxBackjumps ++ "). Use a negative number to enable unlimited backtracking. Use 0 to disable backtracking completely.")
21162126
getmbj setmbj
@@ -2123,6 +2133,11 @@ optionSolverFlags showOrParseArgs getmbj setmbj getms setms getrg setrg getcc se
21232133
(reqArg "NUM" (readP_to_E ("Cannot parse number: "++)
21242134
(fmap toFlag (Parse.readS_to_P reads)))
21252135
(map show . flagToList))
2136+
, option [] ["find-best-solution"]
2137+
"Find the best-scoring solution within the backjump limit."
2138+
(fmap asBool . getfb)
2139+
(setfb . fmap FindBestSolution)
2140+
(yesNoOpt showOrParseArgs)
21262141
, option [] ["reorder-goals"]
21272142
"Try to reorder goals according to certain heuristics. Slows things down on average, but may make backtracking faster for some packages."
21282143
(fmap asBool . getrg)

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ module Distribution.Solver.Modular.Dependency (
1414
, ConflictSet
1515
, CS.ConflictType(..)
1616
, CS.showCS
17+
-- * Install plan scoring
18+
, ScoringState(..)
1719
-- * Constrained instances
1820
, CI(..)
1921
, merge
@@ -63,6 +65,21 @@ import qualified Distribution.Solver.Modular.ConflictSet as CS
6365

6466
import Distribution.Solver.Types.ComponentDeps (Component(..))
6567
import Distribution.Solver.Types.PackagePath
68+
import Distribution.Solver.Types.Settings
69+
70+
{-------------------------------------------------------------------------------
71+
Install plan scoring
72+
-------------------------------------------------------------------------------}
73+
74+
-- | State used for finding solutions based on score. Storing 'ScoringState' on
75+
-- nodes allows the nodes to be scored before the cutoff score is known.
76+
data ScoringState = ScoringState {
77+
-- | The sum of the scores of all nodes from the root to the current node.
78+
ssTotalScore :: InstallPlanScore
79+
80+
-- | The conflict set that should be used if a node exceeds the max score.
81+
, ssConflictSet :: ConflictSet QPN
82+
}
6683

6784
#ifdef DEBUG_CONFLICT_SETS
6885
import GHC.Stack (CallStack)

0 commit comments

Comments
 (0)