Skip to content

Commit 7cc6f71

Browse files
committed
Add option to find best install plan before backjump limit
1 parent 17d6ecb commit 7cc6f71

File tree

17 files changed

+376
-136
lines changed

17 files changed

+376
-136
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
@@ -53,6 +53,7 @@ module Distribution.Client.Dependency (
5353
setEnableBackjumping,
5454
setGoalOrder,
5555
setMaxScore,
56+
setFindBestSolution,
5657
removeLowerBounds,
5758
removeUpperBounds,
5859
addDefaultSetupDependencies,
@@ -162,7 +163,8 @@ data DepResolverParams = DepResolverParams {
162163

163164
-- | Function to override the solver's goal-ordering heuristics.
164165
depResolverGoalOrder :: Maybe (Variable QPN -> Variable QPN -> Ordering),
165-
depResolverMaxScore :: Maybe InstallPlanScore
166+
depResolverMaxScore :: Maybe InstallPlanScore,
167+
depResolverFindBestSolution :: FindBestSolution
166168
}
167169

168170
showDepResolverParams :: DepResolverParams -> String
@@ -238,7 +240,8 @@ basicDepResolverParams installedPkgIndex sourcePkgIndex =
238240
depResolverMaxBackjumps = Nothing,
239241
depResolverEnableBackjumping = EnableBackjumping True,
240242
depResolverGoalOrder = Nothing,
241-
depResolverMaxScore = Nothing
243+
depResolverMaxScore = Nothing,
244+
depResolverFindBestSolution = FindBestSolution False
242245
}
243246

244247
addTargets :: [PackageName]
@@ -333,6 +336,12 @@ setMaxScore n params =
333336
depResolverMaxScore = n
334337
}
335338

339+
setFindBestSolution :: FindBestSolution -> DepResolverParams -> DepResolverParams
340+
setFindBestSolution findBest params =
341+
params {
342+
depResolverFindBestSolution = findBest
343+
}
344+
336345
-- | Some packages are specific to a given compiler version and should never be
337346
-- upgraded.
338347
dontUpgradeNonUpgradeablePackages :: DepResolverParams -> DepResolverParams
@@ -618,7 +627,7 @@ resolveDependencies platform comp pkgConfigDB solver params =
618627
Step (showDepResolverParams finalparams)
619628
$ fmap (uncurry $ validateSolverResult platform comp indGoals)
620629
$ runSolver solver (SolverConfig reordGoals cntConflicts indGoals noReinstalls
621-
shadowing strFlags maxBkjumps enableBj order mScore)
630+
shadowing strFlags maxBkjumps enableBj order mScore findBest)
622631
platform comp installedPkgIndex sourcePkgIndex
623632
pkgConfigDB preferences constraints targets
624633
where
@@ -637,7 +646,8 @@ resolveDependencies platform comp pkgConfigDB solver params =
637646
maxBkjumps
638647
enableBj
639648
order
640-
mScore) = dontUpgradeNonUpgradeablePackages params
649+
mScore
650+
findBest) = dontUpgradeNonUpgradeablePackages params
641651

642652
preferences = interpretPackagesPreference
643653
(Set.fromList targets) defpref prefs
@@ -864,7 +874,8 @@ resolveWithoutDependencies :: DepResolverParams
864874
resolveWithoutDependencies (DepResolverParams targets constraints
865875
prefs defpref installedPkgIndex sourcePkgIndex
866876
_reorderGoals _countConflicts _indGoals _avoidReinstalls
867-
_shadowing _strFlags _maxBjumps _enableBj _order _maxScore) =
877+
_shadowing _strFlags _maxBjumps _enableBj _order _maxScore
878+
_findBest) =
868879
collectEithers (map selectPackage targets)
869880
where
870881
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
@@ -382,6 +382,8 @@ planPackages comp platform mSandboxPkgInfo solver
382382

383383
. setMaxScore maxScore
384384

385+
. setFindBestSolution findBest
386+
385387
. setIndependentGoals independentGoals
386388

387389
. setReorderGoals reorderGoals
@@ -448,6 +450,7 @@ planPackages comp platform mSandboxPkgInfo solver
448450
strongFlags = fromFlag (installStrongFlags installFlags)
449451
maxBackjumps = fromFlag (installMaxBackjumps installFlags)
450452
maxScore = flagToMaybe (installMaxScore installFlags)
453+
findBest = fromFlag (installFindBestSolution installFlags)
451454
upgradeDeps = fromFlag (installUpgradeDeps installFlags)
452455
onlyDeps = fromFlag (installOnlyDeps installFlags)
453456
allowOlder = fromMaybe (AllowOlder RelaxDepsNone)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ convertToLegacySharedConfig
499499
installMaxBackjumps = projectConfigMaxBackjumps,
500500
installMaxScore = mempty, --projectConfigMaxScore,
501501
installUpgradeDeps = mempty, --projectConfigUpgradeDeps,
502+
installFindBestSolution = mempty, --projectConfigFindBestSolution,
502503
installReorderGoals = projectConfigReorderGoals,
503504
installCountConflicts = projectConfigCountConflicts,
504505
installIndependentGoals = mempty, --projectConfigIndependentGoals,

cabal-install/Distribution/Client/Setup.hs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,7 @@ data FetchFlags = FetchFlags {
607607
fetchSolver :: Flag PreSolver,
608608
fetchMaxBackjumps :: Flag Int,
609609
fetchMaxScore :: Flag InstallPlanScore,
610+
fetchFindBestSolution :: Flag FindBestSolution,
610611
fetchReorderGoals :: Flag ReorderGoals,
611612
fetchCountConflicts :: Flag CountConflicts,
612613
fetchIndependentGoals :: Flag IndependentGoals,
@@ -623,6 +624,7 @@ defaultFetchFlags = FetchFlags {
623624
fetchSolver = Flag defaultSolver,
624625
fetchMaxBackjumps = Flag defaultMaxBackjumps,
625626
fetchMaxScore = mempty,
627+
fetchFindBestSolution = Flag (FindBestSolution False),
626628
fetchReorderGoals = Flag (ReorderGoals False),
627629
fetchCountConflicts = Flag (CountConflicts True),
628630
fetchIndependentGoals = Flag (IndependentGoals False),
@@ -671,6 +673,7 @@ fetchCommand = CommandUI {
671673
optionSolverFlags showOrParseArgs
672674
fetchMaxBackjumps (\v flags -> flags { fetchMaxBackjumps = v })
673675
fetchMaxScore (\v flags -> flags { fetchMaxScore = v })
676+
fetchFindBestSolution (\v flags -> flags { fetchFindBestSolution = v })
674677
fetchReorderGoals (\v flags -> flags { fetchReorderGoals = v })
675678
fetchCountConflicts (\v flags -> flags { fetchCountConflicts = v })
676679
fetchIndependentGoals (\v flags -> flags { fetchIndependentGoals = v })
@@ -690,6 +693,7 @@ data FreezeFlags = FreezeFlags {
690693
freezeSolver :: Flag PreSolver,
691694
freezeMaxBackjumps :: Flag Int,
692695
freezeMaxScore :: Flag InstallPlanScore,
696+
freezeFindBestSolution :: Flag FindBestSolution,
693697
freezeReorderGoals :: Flag ReorderGoals,
694698
freezeCountConflicts :: Flag CountConflicts,
695699
freezeIndependentGoals :: Flag IndependentGoals,
@@ -706,6 +710,7 @@ defaultFreezeFlags = FreezeFlags {
706710
freezeSolver = Flag defaultSolver,
707711
freezeMaxBackjumps = Flag defaultMaxBackjumps,
708712
freezeMaxScore = mempty,
713+
freezeFindBestSolution = Flag (FindBestSolution False),
709714
freezeReorderGoals = Flag (ReorderGoals False),
710715
freezeCountConflicts = Flag (CountConflicts True),
711716
freezeIndependentGoals = Flag (IndependentGoals False),
@@ -753,6 +758,7 @@ freezeCommand = CommandUI {
753758
optionSolverFlags showOrParseArgs
754759
freezeMaxBackjumps (\v flags -> flags { freezeMaxBackjumps = v })
755760
freezeMaxScore (\v flags -> flags { freezeMaxScore = v })
761+
freezeFindBestSolution (\v flags -> flags { freezeFindBestSolution = v })
756762
freezeReorderGoals (\v flags -> flags { freezeReorderGoals = v })
757763
freezeCountConflicts (\v flags -> flags { freezeCountConflicts = v })
758764
freezeIndependentGoals (\v flags -> flags { freezeIndependentGoals = v })
@@ -1157,6 +1163,7 @@ data InstallFlags = InstallFlags {
11571163
installDryRun :: Flag Bool,
11581164
installMaxBackjumps :: Flag Int,
11591165
installMaxScore :: Flag InstallPlanScore,
1166+
installFindBestSolution :: Flag FindBestSolution,
11601167
installReorderGoals :: Flag ReorderGoals,
11611168
installCountConflicts :: Flag CountConflicts,
11621169
installIndependentGoals :: Flag IndependentGoals,
@@ -1191,6 +1198,7 @@ defaultInstallFlags = InstallFlags {
11911198
installDryRun = Flag False,
11921199
installMaxBackjumps = Flag defaultMaxBackjumps,
11931200
installMaxScore = mempty,
1201+
installFindBestSolution= Flag (FindBestSolution False),
11941202
installReorderGoals = Flag (ReorderGoals False),
11951203
installCountConflicts = Flag (CountConflicts True),
11961204
installIndependentGoals= Flag (IndependentGoals False),
@@ -1338,6 +1346,7 @@ installOptions showOrParseArgs =
13381346
optionSolverFlags showOrParseArgs
13391347
installMaxBackjumps (\v flags -> flags { installMaxBackjumps = v })
13401348
installMaxScore (\v flags -> flags { installMaxScore = v })
1349+
installFindBestSolution (\v flags -> flags { installFindBestSolution = v })
13411350
installReorderGoals (\v flags -> flags { installReorderGoals = v })
13421351
installCountConflicts (\v flags -> flags { installCountConflicts = v })
13431352
installIndependentGoals (\v flags -> flags { installIndependentGoals = v })
@@ -2105,13 +2114,14 @@ optionSolver get set =
21052114
optionSolverFlags :: ShowOrParseArgs
21062115
-> (flags -> Flag Int ) -> (Flag Int -> flags -> flags)
21072116
-> (flags -> Flag InstallPlanScore) -> (Flag InstallPlanScore -> flags -> flags)
2117+
-> (flags -> Flag FindBestSolution) -> (Flag FindBestSolution -> flags -> flags)
21082118
-> (flags -> Flag ReorderGoals) -> (Flag ReorderGoals -> flags -> flags)
21092119
-> (flags -> Flag CountConflicts) -> (Flag CountConflicts -> flags -> flags)
21102120
-> (flags -> Flag IndependentGoals) -> (Flag IndependentGoals -> flags -> flags)
21112121
-> (flags -> Flag ShadowPkgs) -> (Flag ShadowPkgs -> flags -> flags)
21122122
-> (flags -> Flag StrongFlags) -> (Flag StrongFlags -> flags -> flags)
21132123
-> [OptionField flags]
2114-
optionSolverFlags showOrParseArgs getmbj setmbj getms setms getrg setrg getcc setcc _getig _setig getsip setsip getstrfl setstrfl =
2124+
optionSolverFlags showOrParseArgs getmbj setmbj getms setms getfb setfb getrg setrg getcc setcc _getig _setig getsip setsip getstrfl setstrfl =
21152125
[ option [] ["max-backjumps"]
21162126
("Maximum number of backjumps allowed while solving (default: " ++ show defaultMaxBackjumps ++ "). Use a negative number to enable unlimited backtracking. Use 0 to disable backtracking completely.")
21172127
getmbj setmbj
@@ -2124,6 +2134,11 @@ optionSolverFlags showOrParseArgs getmbj setmbj getms setms getrg setrg getcc se
21242134
(reqArg "NUM" (readP_to_E ("Cannot parse number: "++)
21252135
(fmap toFlag (Parse.readS_to_P reads)))
21262136
(map show . flagToList))
2137+
, option [] ["find-best-solution"]
2138+
"Find the best-scoring solution within the backjump limit."
2139+
(fmap asBool . getfb)
2140+
(setfb . fmap FindBestSolution)
2141+
(yesNoOpt showOrParseArgs)
21272142
, option [] ["reorder-goals"]
21282143
"Try to reorder goals according to certain heuristics. Slows things down on average, but may make backtracking faster for some packages."
21292144
(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)