Skip to content

Commit 8362d04

Browse files
committed
Add option to find best install plan before backjump limit
1 parent 26445e1 commit 8362d04

File tree

17 files changed

+358
-127
lines changed

17 files changed

+358
-127
lines changed

cabal-install/Distribution/Client/Config.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ instance Semigroup SavedConfig where
240240
installDryRun = combine installDryRun,
241241
installMaxBackjumps = combine installMaxBackjumps,
242242
installMaxScore = combine installMaxScore,
243+
installFindBestSolution = combine installFindBestSolution,
243244
installReorderGoals = combine installReorderGoals,
244245
installCountConflicts = combine installCountConflicts,
245246
installIndependentGoals = combine installIndependentGoals,

cabal-install/Distribution/Client/Dependency.hs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ module Distribution.Client.Dependency (
5858
setGoalOrder,
5959
setSolverVerbosity,
6060
setMaxScore,
61+
setFindBestSolution,
6162
removeLowerBounds,
6263
removeUpperBounds,
6364
addDefaultSetupDependencies,
@@ -178,7 +179,8 @@ data DepResolverParams = DepResolverParams {
178179
-- | Function to override the solver's goal-ordering heuristics.
179180
depResolverGoalOrder :: Maybe (Variable QPN -> Variable QPN -> Ordering),
180181
depResolverVerbosity :: Verbosity,
181-
depResolverMaxScore :: Maybe InstallPlanScore
182+
depResolverMaxScore :: Maybe InstallPlanScore,
183+
depResolverFindBestSolution :: FindBestSolution
182184
}
183185

184186
showDepResolverParams :: DepResolverParams -> String
@@ -258,7 +260,8 @@ basicDepResolverParams installedPkgIndex sourcePkgIndex =
258260
depResolverSolveExecutables = SolveExecutables True,
259261
depResolverGoalOrder = Nothing,
260262
depResolverVerbosity = normal,
261-
depResolverMaxScore = Nothing
263+
depResolverMaxScore = Nothing,
264+
depResolverFindBestSolution = FindBestSolution False
262265
}
263266

264267
addTargets :: [PackageName]
@@ -371,6 +374,12 @@ setMaxScore n params =
371374
depResolverMaxScore = n
372375
}
373376

377+
setFindBestSolution :: FindBestSolution -> DepResolverParams -> DepResolverParams
378+
setFindBestSolution findBest params =
379+
params {
380+
depResolverFindBestSolution = findBest
381+
}
382+
374383
-- | Some packages are specific to a given compiler version and should never be
375384
-- upgraded.
376385
dontUpgradeNonUpgradeablePackages :: DepResolverParams -> DepResolverParams
@@ -680,7 +689,7 @@ resolveDependencies platform comp pkgConfigDB solver params =
680689
$ runSolver solver (SolverConfig reordGoals cntConflicts
681690
indGoals noReinstalls
682691
shadowing strFlags allowBootLibs maxBkjumps enableBj
683-
solveExes order verbosity mScore)
692+
solveExes order verbosity mScore findBest)
684693
platform comp installedPkgIndex sourcePkgIndex
685694
pkgConfigDB preferences constraints targets
686695
where
@@ -702,7 +711,8 @@ resolveDependencies platform comp pkgConfigDB solver params =
702711
solveExes
703712
order
704713
verbosity
705-
mScore) =
714+
mScore
715+
findBest) =
706716
if asBool (depResolverAllowBootLibInstalls params)
707717
then params
708718
else dontUpgradeNonUpgradeablePackages params
@@ -940,7 +950,7 @@ resolveWithoutDependencies (DepResolverParams targets constraints
940950
_reorderGoals _countConflicts _indGoals _avoidReinstalls
941951
_shadowing _strFlags _maxBjumps _enableBj
942952
_solveExes _allowBootLibInstalls _order _verbosity
943-
_maxScore) =
953+
_maxScore _findBest) =
944954
collectEithers $ map selectPackage (Set.toList targets)
945955
where
946956
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 verbosity comp platform mSandboxPkgInfo solver
382382

383383
. setMaxScore maxScore
384384

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

387389
. setReorderGoals reorderGoals
@@ -459,6 +461,7 @@ planPackages verbosity comp platform mSandboxPkgInfo solver
459461
maxBackjumps = fromFlag (installMaxBackjumps installFlags)
460462
allowBootLibInstalls = fromFlag (installAllowBootLibInstalls installFlags)
461463
maxScore = flagToMaybe (installMaxScore installFlags)
464+
findBest = fromFlag (installFindBestSolution installFlags)
462465
upgradeDeps = fromFlag (installUpgradeDeps installFlags)
463466
onlyDeps = fromFlag (installOnlyDeps installFlags)
464467
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
@@ -500,6 +500,7 @@ convertToLegacySharedConfig
500500
installMaxBackjumps = projectConfigMaxBackjumps,
501501
installMaxScore = mempty, --projectConfigMaxScore,
502502
installUpgradeDeps = mempty, --projectConfigUpgradeDeps,
503+
installFindBestSolution = mempty, --projectConfigFindBestSolution,
503504
installReorderGoals = projectConfigReorderGoals,
504505
installCountConflicts = projectConfigCountConflicts,
505506
installIndependentGoals = mempty, --projectConfigIndependentGoals,

cabal-install/Distribution/Client/Setup.hs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,7 @@ data FetchFlags = FetchFlags {
682682
fetchSolver :: Flag PreSolver,
683683
fetchMaxBackjumps :: Flag Int,
684684
fetchMaxScore :: Flag InstallPlanScore,
685+
fetchFindBestSolution :: Flag FindBestSolution,
685686
fetchReorderGoals :: Flag ReorderGoals,
686687
fetchCountConflicts :: Flag CountConflicts,
687688
fetchIndependentGoals :: Flag IndependentGoals,
@@ -699,6 +700,7 @@ defaultFetchFlags = FetchFlags {
699700
fetchSolver = Flag defaultSolver,
700701
fetchMaxBackjumps = Flag defaultMaxBackjumps,
701702
fetchMaxScore = mempty,
703+
fetchFindBestSolution = Flag (FindBestSolution False),
702704
fetchReorderGoals = Flag (ReorderGoals False),
703705
fetchCountConflicts = Flag (CountConflicts True),
704706
fetchIndependentGoals = Flag (IndependentGoals False),
@@ -748,6 +750,7 @@ fetchCommand = CommandUI {
748750
optionSolverFlags showOrParseArgs
749751
fetchMaxBackjumps (\v flags -> flags { fetchMaxBackjumps = v })
750752
fetchMaxScore (\v flags -> flags { fetchMaxScore = v })
753+
fetchFindBestSolution (\v flags -> flags { fetchFindBestSolution = v })
751754
fetchReorderGoals (\v flags -> flags { fetchReorderGoals = v })
752755
fetchCountConflicts (\v flags -> flags { fetchCountConflicts = v })
753756
fetchIndependentGoals (\v flags -> flags { fetchIndependentGoals = v })
@@ -768,6 +771,7 @@ data FreezeFlags = FreezeFlags {
768771
freezeSolver :: Flag PreSolver,
769772
freezeMaxBackjumps :: Flag Int,
770773
freezeMaxScore :: Flag InstallPlanScore,
774+
freezeFindBestSolution :: Flag FindBestSolution,
771775
freezeReorderGoals :: Flag ReorderGoals,
772776
freezeCountConflicts :: Flag CountConflicts,
773777
freezeIndependentGoals :: Flag IndependentGoals,
@@ -785,6 +789,7 @@ defaultFreezeFlags = FreezeFlags {
785789
freezeSolver = Flag defaultSolver,
786790
freezeMaxBackjumps = Flag defaultMaxBackjumps,
787791
freezeMaxScore = mempty,
792+
freezeFindBestSolution = Flag (FindBestSolution False),
788793
freezeReorderGoals = Flag (ReorderGoals False),
789794
freezeCountConflicts = Flag (CountConflicts True),
790795
freezeIndependentGoals = Flag (IndependentGoals False),
@@ -837,6 +842,7 @@ freezeCommand = CommandUI {
837842
optionSolverFlags showOrParseArgs
838843
freezeMaxBackjumps (\v flags -> flags { freezeMaxBackjumps = v })
839844
freezeMaxScore (\v flags -> flags { freezeMaxScore = v })
845+
freezeFindBestSolution (\v flags -> flags { freezeFindBestSolution = v })
840846
freezeReorderGoals (\v flags -> flags { freezeReorderGoals = v })
841847
freezeCountConflicts (\v flags -> flags { freezeCountConflicts = v })
842848
freezeIndependentGoals (\v flags -> flags { freezeIndependentGoals = v })
@@ -1403,6 +1409,7 @@ data InstallFlags = InstallFlags {
14031409
installDryRun :: Flag Bool,
14041410
installMaxBackjumps :: Flag Int,
14051411
installMaxScore :: Flag InstallPlanScore,
1412+
installFindBestSolution :: Flag FindBestSolution,
14061413
installReorderGoals :: Flag ReorderGoals,
14071414
installCountConflicts :: Flag CountConflicts,
14081415
installIndependentGoals :: Flag IndependentGoals,
@@ -1447,6 +1454,7 @@ defaultInstallFlags = InstallFlags {
14471454
installDryRun = Flag False,
14481455
installMaxBackjumps = Flag defaultMaxBackjumps,
14491456
installMaxScore = mempty,
1457+
installFindBestSolution= Flag (FindBestSolution False),
14501458
installReorderGoals = Flag (ReorderGoals False),
14511459
installCountConflicts = Flag (CountConflicts True),
14521460
installIndependentGoals= Flag (IndependentGoals False),
@@ -1597,6 +1605,7 @@ installOptions showOrParseArgs =
15971605
optionSolverFlags showOrParseArgs
15981606
installMaxBackjumps (\v flags -> flags { installMaxBackjumps = v })
15991607
installMaxScore (\v flags -> flags { installMaxScore = v })
1608+
installFindBestSolution (\v flags -> flags { installFindBestSolution = v })
16001609
installReorderGoals (\v flags -> flags { installReorderGoals = v })
16011610
installCountConflicts (\v flags -> flags { installCountConflicts = v })
16021611
installIndependentGoals (\v flags -> flags { installIndependentGoals = v })
@@ -2384,15 +2393,17 @@ optionSolver get set =
23842393
optionSolverFlags :: ShowOrParseArgs
23852394
-> (flags -> Flag Int ) -> (Flag Int -> flags -> flags)
23862395
-> (flags -> Flag InstallPlanScore) -> (Flag InstallPlanScore -> flags -> flags)
2396+
-> (flags -> Flag FindBestSolution) -> (Flag FindBestSolution -> flags -> flags)
23872397
-> (flags -> Flag ReorderGoals) -> (Flag ReorderGoals -> flags -> flags)
23882398
-> (flags -> Flag CountConflicts) -> (Flag CountConflicts -> flags -> flags)
23892399
-> (flags -> Flag IndependentGoals) -> (Flag IndependentGoals -> flags -> flags)
23902400
-> (flags -> Flag ShadowPkgs) -> (Flag ShadowPkgs -> flags -> flags)
23912401
-> (flags -> Flag StrongFlags) -> (Flag StrongFlags -> flags -> flags)
23922402
-> (flags -> Flag AllowBootLibInstalls) -> (Flag AllowBootLibInstalls -> flags -> flags)
23932403
-> [OptionField flags]
2394-
optionSolverFlags showOrParseArgs getmbj setmbj getms setms getrg setrg getcc setcc _getig _setig
2395-
getsip setsip getstrfl setstrfl getib setib =
2404+
optionSolverFlags showOrParseArgs getmbj setmbj getms setms getfb setfb
2405+
getrg setrg getcc setcc _getig _setig getsip setsip
2406+
getstrfl setstrfl getib setib =
23962407
[ option [] ["max-backjumps"]
23972408
("Maximum number of backjumps allowed while solving (default: " ++ show defaultMaxBackjumps ++ "). Use a negative number to enable unlimited backtracking. Use 0 to disable backtracking completely.")
23982409
getmbj setmbj
@@ -2405,6 +2416,11 @@ optionSolverFlags showOrParseArgs getmbj setmbj getms setms getrg setrg getcc se
24052416
(reqArg "NUM" (readP_to_E ("Cannot parse number: "++)
24062417
(fmap toFlag (Parse.readS_to_P reads)))
24072418
(map show . flagToList))
2419+
, option [] ["find-best-solution"]
2420+
"Find the best-scoring solution within the backjump limit."
2421+
(fmap asBool . getfb)
2422+
(setfb . fmap FindBestSolution)
2423+
(yesNoOpt showOrParseArgs)
24082424
, option [] ["reorder-goals"]
24092425
"Try to reorder goals according to certain heuristics. Slows things down on average, but may make backtracking faster for some packages."
24102426
(fmap asBool . getrg)

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ module Distribution.Solver.Modular.Dependency (
1515
, CS.ConflictType(..)
1616
, ConflictMap
1717
, CS.showConflictSet
18+
-- * Install plan scoring
19+
, ScoringState(..)
1820
-- * Constrained instances
1921
, CI(..)
2022
, merge
@@ -64,11 +66,26 @@ import qualified Distribution.Solver.Modular.ConflictSet as CS
6466

6567
import Distribution.Solver.Types.ComponentDeps (Component(..))
6668
import Distribution.Solver.Types.PackagePath
69+
import Distribution.Solver.Types.Settings
6770

6871
#ifdef DEBUG_CONFLICT_SETS
6972
import GHC.Stack (CallStack)
7073
#endif
7174

75+
{-------------------------------------------------------------------------------
76+
Install plan scoring
77+
-------------------------------------------------------------------------------}
78+
79+
-- | State used for finding solutions based on score. Storing 'ScoringState' on
80+
-- nodes allows the nodes to be scored before the cutoff score is known.
81+
data ScoringState = ScoringState {
82+
-- | The sum of the scores of all nodes from the root to the current node.
83+
ssTotalScore :: InstallPlanScore
84+
85+
-- | The conflict set that should be used if a node exceeds the max score.
86+
, ssConflictSet :: ConflictSet
87+
}
88+
7289
{-------------------------------------------------------------------------------
7390
Constrained instances
7491
-------------------------------------------------------------------------------}

0 commit comments

Comments
 (0)