Skip to content

Commit 76dcea9

Browse files
committed
Add option to find best install plan before backjump limit
1 parent c16e174 commit 76dcea9

File tree

17 files changed

+356
-131
lines changed

17 files changed

+356
-131
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 targets defpref prefs
643653

@@ -863,7 +873,8 @@ resolveWithoutDependencies :: DepResolverParams
863873
resolveWithoutDependencies (DepResolverParams targets constraints
864874
prefs defpref installedPkgIndex sourcePkgIndex
865875
_reorderGoals _countConflicts _indGoals _avoidReinstalls
866-
_shadowing _strFlags _maxBjumps _enableBj _order _maxScore) =
876+
_shadowing _strFlags _maxBjumps _enableBj _order _maxScore
877+
_findBest) =
867878
collectEithers $ map selectPackage (Set.toList targets)
868879
where
869880
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
@@ -640,6 +640,7 @@ data FetchFlags = FetchFlags {
640640
fetchSolver :: Flag PreSolver,
641641
fetchMaxBackjumps :: Flag Int,
642642
fetchMaxScore :: Flag InstallPlanScore,
643+
fetchFindBestSolution :: Flag FindBestSolution,
643644
fetchReorderGoals :: Flag ReorderGoals,
644645
fetchCountConflicts :: Flag CountConflicts,
645646
fetchIndependentGoals :: Flag IndependentGoals,
@@ -656,6 +657,7 @@ defaultFetchFlags = FetchFlags {
656657
fetchSolver = Flag defaultSolver,
657658
fetchMaxBackjumps = Flag defaultMaxBackjumps,
658659
fetchMaxScore = mempty,
660+
fetchFindBestSolution = Flag (FindBestSolution False),
659661
fetchReorderGoals = Flag (ReorderGoals False),
660662
fetchCountConflicts = Flag (CountConflicts True),
661663
fetchIndependentGoals = Flag (IndependentGoals False),
@@ -704,6 +706,7 @@ fetchCommand = CommandUI {
704706
optionSolverFlags showOrParseArgs
705707
fetchMaxBackjumps (\v flags -> flags { fetchMaxBackjumps = v })
706708
fetchMaxScore (\v flags -> flags { fetchMaxScore = v })
709+
fetchFindBestSolution (\v flags -> flags { fetchFindBestSolution = v })
707710
fetchReorderGoals (\v flags -> flags { fetchReorderGoals = v })
708711
fetchCountConflicts (\v flags -> flags { fetchCountConflicts = v })
709712
fetchIndependentGoals (\v flags -> flags { fetchIndependentGoals = v })
@@ -723,6 +726,7 @@ data FreezeFlags = FreezeFlags {
723726
freezeSolver :: Flag PreSolver,
724727
freezeMaxBackjumps :: Flag Int,
725728
freezeMaxScore :: Flag InstallPlanScore,
729+
freezeFindBestSolution :: Flag FindBestSolution,
726730
freezeReorderGoals :: Flag ReorderGoals,
727731
freezeCountConflicts :: Flag CountConflicts,
728732
freezeIndependentGoals :: Flag IndependentGoals,
@@ -739,6 +743,7 @@ defaultFreezeFlags = FreezeFlags {
739743
freezeSolver = Flag defaultSolver,
740744
freezeMaxBackjumps = Flag defaultMaxBackjumps,
741745
freezeMaxScore = mempty,
746+
freezeFindBestSolution = Flag (FindBestSolution False),
742747
freezeReorderGoals = Flag (ReorderGoals False),
743748
freezeCountConflicts = Flag (CountConflicts True),
744749
freezeIndependentGoals = Flag (IndependentGoals False),
@@ -786,6 +791,7 @@ freezeCommand = CommandUI {
786791
optionSolverFlags showOrParseArgs
787792
freezeMaxBackjumps (\v flags -> flags { freezeMaxBackjumps = v })
788793
freezeMaxScore (\v flags -> flags { freezeMaxScore = v })
794+
freezeFindBestSolution (\v flags -> flags { freezeFindBestSolution = v })
789795
freezeReorderGoals (\v flags -> flags { freezeReorderGoals = v })
790796
freezeCountConflicts (\v flags -> flags { freezeCountConflicts = v })
791797
freezeIndependentGoals (\v flags -> flags { freezeIndependentGoals = v })
@@ -1190,6 +1196,7 @@ data InstallFlags = InstallFlags {
11901196
installDryRun :: Flag Bool,
11911197
installMaxBackjumps :: Flag Int,
11921198
installMaxScore :: Flag InstallPlanScore,
1199+
installFindBestSolution :: Flag FindBestSolution,
11931200
installReorderGoals :: Flag ReorderGoals,
11941201
installCountConflicts :: Flag CountConflicts,
11951202
installIndependentGoals :: Flag IndependentGoals,
@@ -1224,6 +1231,7 @@ defaultInstallFlags = InstallFlags {
12241231
installDryRun = Flag False,
12251232
installMaxBackjumps = Flag defaultMaxBackjumps,
12261233
installMaxScore = mempty,
1234+
installFindBestSolution= Flag (FindBestSolution False),
12271235
installReorderGoals = Flag (ReorderGoals False),
12281236
installCountConflicts = Flag (CountConflicts True),
12291237
installIndependentGoals= Flag (IndependentGoals False),
@@ -1371,6 +1379,7 @@ installOptions showOrParseArgs =
13711379
optionSolverFlags showOrParseArgs
13721380
installMaxBackjumps (\v flags -> flags { installMaxBackjumps = v })
13731381
installMaxScore (\v flags -> flags { installMaxScore = v })
1382+
installFindBestSolution (\v flags -> flags { installFindBestSolution = v })
13741383
installReorderGoals (\v flags -> flags { installReorderGoals = v })
13751384
installCountConflicts (\v flags -> flags { installCountConflicts = v })
13761385
installIndependentGoals (\v flags -> flags { installIndependentGoals = v })
@@ -2138,13 +2147,14 @@ optionSolver get set =
21382147
optionSolverFlags :: ShowOrParseArgs
21392148
-> (flags -> Flag Int ) -> (Flag Int -> flags -> flags)
21402149
-> (flags -> Flag InstallPlanScore) -> (Flag InstallPlanScore -> flags -> flags)
2150+
-> (flags -> Flag FindBestSolution) -> (Flag FindBestSolution -> flags -> flags)
21412151
-> (flags -> Flag ReorderGoals) -> (Flag ReorderGoals -> flags -> flags)
21422152
-> (flags -> Flag CountConflicts) -> (Flag CountConflicts -> flags -> flags)
21432153
-> (flags -> Flag IndependentGoals) -> (Flag IndependentGoals -> flags -> flags)
21442154
-> (flags -> Flag ShadowPkgs) -> (Flag ShadowPkgs -> flags -> flags)
21452155
-> (flags -> Flag StrongFlags) -> (Flag StrongFlags -> flags -> flags)
21462156
-> [OptionField flags]
2147-
optionSolverFlags showOrParseArgs getmbj setmbj getms setms getrg setrg getcc setcc _getig _setig getsip setsip getstrfl setstrfl =
2157+
optionSolverFlags showOrParseArgs getmbj setmbj getms setms getfb setfb getrg setrg getcc setcc _getig _setig getsip setsip getstrfl setstrfl =
21482158
[ option [] ["max-backjumps"]
21492159
("Maximum number of backjumps allowed while solving (default: " ++ show defaultMaxBackjumps ++ "). Use a negative number to enable unlimited backtracking. Use 0 to disable backtracking completely.")
21502160
getmbj setmbj
@@ -2157,6 +2167,11 @@ optionSolverFlags showOrParseArgs getmbj setmbj getms setms getrg setrg getcc se
21572167
(reqArg "NUM" (readP_to_E ("Cannot parse number: "++)
21582168
(fmap toFlag (Parse.readS_to_P reads)))
21592169
(map show . flagToList))
2170+
, option [] ["find-best-solution"]
2171+
"Find the best-scoring solution within the backjump limit."
2172+
(fmap asBool . getfb)
2173+
(setfb . fmap FindBestSolution)
2174+
(yesNoOpt showOrParseArgs)
21602175
, option [] ["reorder-goals"]
21612176
"Try to reorder goals according to certain heuristics. Slows things down on average, but may make backtracking faster for some packages."
21622177
(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)