Skip to content

Commit

Permalink
Merge pull request #5680 from grayjay/find-minimal-conflict-set
Browse files Browse the repository at this point in the history
Solver: Improve error message by finding a minimal conflict set (issue #5647).
  • Loading branch information
23Skidoo authored Dec 5, 2018
2 parents c25a223 + 76adde4 commit 009fb61
Show file tree
Hide file tree
Showing 22 changed files with 436 additions and 108 deletions.
15 changes: 15 additions & 0 deletions Cabal/doc/nix-local-build.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2073,6 +2073,21 @@ Most users generally won't need these.
The command line variant of this field is
``--(no-)count-conflicts``.

.. cfg-field:: minimize-conflict-set: boolean
--minimize-conflict-set
--no-minimize-conflict-set
:synopsis: Try to improve the solver error message when there is no
solution.

:default: False

When there is no solution, try to improve the solver error message
by finding a minimal conflict set. This option may increase run
time significantly, so it is off by default.

The command line variant of this field is
``--(no-)minimize-conflict-set``.

.. cfg-field:: strong-flags: boolean
--strong-flags
--no-strong-flags
Expand Down
1 change: 1 addition & 0 deletions cabal-install/Distribution/Client/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ instance Semigroup SavedConfig where
installMaxBackjumps = combine installMaxBackjumps,
installReorderGoals = combine installReorderGoals,
installCountConflicts = combine installCountConflicts,
installMinimizeConflictSet = combine installMinimizeConflictSet,
installIndependentGoals = combine installIndependentGoals,
installShadowPkgs = combine installShadowPkgs,
installStrongFlags = combine installStrongFlags,
Expand Down
21 changes: 16 additions & 5 deletions cabal-install/Distribution/Client/Dependency.hs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ module Distribution.Client.Dependency (
setPreferenceDefault,
setReorderGoals,
setCountConflicts,
setMinimizeConflictSet,
setIndependentGoals,
setAvoidReinstalls,
setShadowPkgs,
Expand Down Expand Up @@ -158,6 +159,7 @@ data DepResolverParams = DepResolverParams {
depResolverSourcePkgIndex :: PackageIndex.PackageIndex UnresolvedSourcePackage,
depResolverReorderGoals :: ReorderGoals,
depResolverCountConflicts :: CountConflicts,
depResolverMinimizeConflictSet :: MinimizeConflictSet,
depResolverIndependentGoals :: IndependentGoals,
depResolverAvoidReinstalls :: AvoidReinstalls,
depResolverShadowPkgs :: ShadowPkgs,
Expand Down Expand Up @@ -195,6 +197,7 @@ showDepResolverParams p =
++ "\nstrategy: " ++ show (depResolverPreferenceDefault p)
++ "\nreorder goals: " ++ show (asBool (depResolverReorderGoals p))
++ "\ncount conflicts: " ++ show (asBool (depResolverCountConflicts p))
++ "\nminimize conflict set: " ++ show (asBool (depResolverMinimizeConflictSet p))
++ "\nindependent goals: " ++ show (asBool (depResolverIndependentGoals p))
++ "\navoid reinstalls: " ++ show (asBool (depResolverAvoidReinstalls p))
++ "\nshadow packages: " ++ show (asBool (depResolverShadowPkgs p))
Expand Down Expand Up @@ -251,6 +254,7 @@ basicDepResolverParams installedPkgIndex sourcePkgIndex =
depResolverSourcePkgIndex = sourcePkgIndex,
depResolverReorderGoals = ReorderGoals False,
depResolverCountConflicts = CountConflicts True,
depResolverMinimizeConflictSet = MinimizeConflictSet False,
depResolverIndependentGoals = IndependentGoals False,
depResolverAvoidReinstalls = AvoidReinstalls False,
depResolverShadowPkgs = ShadowPkgs False,
Expand Down Expand Up @@ -306,6 +310,12 @@ setCountConflicts count params =
depResolverCountConflicts = count
}

setMinimizeConflictSet :: MinimizeConflictSet -> DepResolverParams -> DepResolverParams
setMinimizeConflictSet minimize params =
params {
depResolverMinimizeConflictSet = minimize
}

setIndependentGoals :: IndependentGoals -> DepResolverParams -> DepResolverParams
setIndependentGoals indep params =
params {
Expand Down Expand Up @@ -745,8 +755,7 @@ resolveDependencies platform comp pkgConfigDB solver params =

Step (showDepResolverParams finalparams)
$ fmap (validateSolverResult platform comp indGoals)
$ runSolver solver (SolverConfig reordGoals cntConflicts
indGoals noReinstalls
$ runSolver solver (SolverConfig reordGoals cntConflicts minimize indGoals noReinstalls
shadowing strFlags allowBootLibs onlyConstrained_ maxBkjumps enableBj
solveExes order verbosity (PruneAfterFirstSuccess False))
platform comp installedPkgIndex sourcePkgIndex
Expand All @@ -760,6 +769,7 @@ resolveDependencies platform comp pkgConfigDB solver params =
sourcePkgIndex
reordGoals
cntConflicts
minimize
indGoals
noReinstalls
shadowing
Expand Down Expand Up @@ -1005,9 +1015,10 @@ resolveWithoutDependencies :: DepResolverParams
-> Either [ResolveNoDepsError] [UnresolvedSourcePackage]
resolveWithoutDependencies (DepResolverParams targets constraints
prefs defpref installedPkgIndex sourcePkgIndex
_reorderGoals _countConflicts _indGoals _avoidReinstalls
_shadowing _strFlags _maxBjumps _enableBj
_solveExes _allowBootLibInstalls _onlyConstrained _order _verbosity) =
_reorderGoals _countConflicts _minimizeConflictSet
_indGoals _avoidReinstalls _shadowing _strFlags
_maxBjumps _enableBj _solveExes
_allowBootLibInstalls _onlyConstrained _order _verbosity) =
collectEithers $ map selectPackage (Set.toList targets)
where
selectPackage :: PackageName -> Either ResolveNoDepsError UnresolvedSourcePackage
Expand Down
3 changes: 3 additions & 0 deletions cabal-install/Distribution/Client/Fetch.hs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ planPackages verbosity comp platform fetchFlags

. setCountConflicts countConflicts

. setMinimizeConflictSet minimizeConflictSet

. setShadowPkgs shadowPkgs

. setStrongFlags strongFlags
Expand Down Expand Up @@ -197,6 +199,7 @@ planPackages verbosity comp platform fetchFlags

reorderGoals = fromFlag (fetchReorderGoals fetchFlags)
countConflicts = fromFlag (fetchCountConflicts fetchFlags)
minimizeConflictSet = fromFlag (fetchMinimizeConflictSet fetchFlags)
independentGoals = fromFlag (fetchIndependentGoals fetchFlags)
shadowPkgs = fromFlag (fetchShadowPkgs fetchFlags)
strongFlags = fromFlag (fetchStrongFlags fetchFlags)
Expand Down
3 changes: 3 additions & 0 deletions cabal-install/Distribution/Client/Freeze.hs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ planPackages verbosity comp platform mSandboxPkgInfo freezeFlags

. setCountConflicts countConflicts

. setMinimizeConflictSet minimizeConflictSet

. setShadowPkgs shadowPkgs

. setStrongFlags strongFlags
Expand Down Expand Up @@ -205,6 +207,7 @@ planPackages verbosity comp platform mSandboxPkgInfo freezeFlags

reorderGoals = fromFlag (freezeReorderGoals freezeFlags)
countConflicts = fromFlag (freezeCountConflicts freezeFlags)
minimizeConflictSet = fromFlag (freezeMinimizeConflictSet freezeFlags)
independentGoals = fromFlag (freezeIndependentGoals freezeFlags)
shadowPkgs = fromFlag (freezeShadowPkgs freezeFlags)
strongFlags = fromFlag (freezeStrongFlags freezeFlags)
Expand Down
3 changes: 3 additions & 0 deletions cabal-install/Distribution/Client/Install.hs
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,8 @@ planPackages verbosity comp platform mSandboxPkgInfo solver

. setCountConflicts countConflicts

. setMinimizeConflictSet minimizeConflictSet

. setAvoidReinstalls avoidReinstalls

. setShadowPkgs shadowPkgs
Expand Down Expand Up @@ -455,6 +457,7 @@ planPackages verbosity comp platform mSandboxPkgInfo solver
fromFlag (installReinstall installFlags)
reorderGoals = fromFlag (installReorderGoals installFlags)
countConflicts = fromFlag (installCountConflicts installFlags)
minimizeConflictSet = fromFlag (installMinimizeConflictSet installFlags)
independentGoals = fromFlag (installIndependentGoals installFlags)
avoidReinstalls = fromFlag (installAvoidReinstalls installFlags)
shadowPkgs = fromFlag (installShadowPkgs installFlags)
Expand Down
2 changes: 2 additions & 0 deletions cabal-install/Distribution/Client/ProjectConfig.hs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ resolveSolverSettings ProjectConfig{
| otherwise -> Just n
solverSettingReorderGoals = fromFlag projectConfigReorderGoals
solverSettingCountConflicts = fromFlag projectConfigCountConflicts
solverSettingMinimizeConflictSet = fromFlag projectConfigMinimizeConflictSet
solverSettingStrongFlags = fromFlag projectConfigStrongFlags
solverSettingAllowBootLibInstalls = fromFlag projectConfigAllowBootLibInstalls
solverSettingOnlyConstrained = fromFlag projectConfigOnlyConstrained
Expand All @@ -258,6 +259,7 @@ resolveSolverSettings ProjectConfig{
projectConfigMaxBackjumps = Flag defaultMaxBackjumps,
projectConfigReorderGoals = Flag (ReorderGoals False),
projectConfigCountConflicts = Flag (CountConflicts True),
projectConfigMinimizeConflictSet = Flag (MinimizeConflictSet False),
projectConfigStrongFlags = Flag (StrongFlags False),
projectConfigAllowBootLibInstalls = Flag (AllowBootLibInstalls False),
projectConfigOnlyConstrained = Flag OnlyConstrainedNone,
Expand Down
5 changes: 4 additions & 1 deletion cabal-install/Distribution/Client/ProjectConfig/Legacy.hs
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ convertLegacyAllPackageFlags globalFlags configFlags
--installUpgradeDeps = projectConfigUpgradeDeps,
installReorderGoals = projectConfigReorderGoals,
installCountConflicts = projectConfigCountConflicts,
installMinimizeConflictSet = projectConfigMinimizeConflictSet,
installPerComponent = projectConfigPerComponent,
installIndependentGoals = projectConfigIndependentGoals,
--installShadowPkgs = projectConfigShadowPkgs,
Expand Down Expand Up @@ -577,6 +578,7 @@ convertToLegacySharedConfig
installUpgradeDeps = mempty, --projectConfigUpgradeDeps,
installReorderGoals = projectConfigReorderGoals,
installCountConflicts = projectConfigCountConflicts,
installMinimizeConflictSet = projectConfigMinimizeConflictSet,
installIndependentGoals = projectConfigIndependentGoals,
installShadowPkgs = mempty, --projectConfigShadowPkgs,
installStrongFlags = projectConfigStrongFlags,
Expand Down Expand Up @@ -954,7 +956,8 @@ legacySharedConfigFieldDescrs =
, "remote-build-reporting", "report-planning-failure"
, "one-shot", "jobs", "keep-going", "offline", "per-component"
-- solver flags:
, "max-backjumps", "reorder-goals", "count-conflicts", "independent-goals"
, "max-backjumps", "reorder-goals", "count-conflicts"
, "minimize-conflict-set", "independent-goals"
, "strong-flags" , "allow-boot-library-installs", "reject-unconstrained-dependencies", "index-state"
]
. commandOptionsToFields
Expand Down
2 changes: 2 additions & 0 deletions cabal-install/Distribution/Client/ProjectConfig/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ data ProjectConfigShared
projectConfigMaxBackjumps :: Flag Int,
projectConfigReorderGoals :: Flag ReorderGoals,
projectConfigCountConflicts :: Flag CountConflicts,
projectConfigMinimizeConflictSet :: Flag MinimizeConflictSet,
projectConfigStrongFlags :: Flag StrongFlags,
projectConfigAllowBootLibInstalls :: Flag AllowBootLibInstalls,
projectConfigOnlyConstrained :: Flag OnlyConstrained,
Expand Down Expand Up @@ -383,6 +384,7 @@ data SolverSettings
solverSettingMaxBackjumps :: Maybe Int,
solverSettingReorderGoals :: ReorderGoals,
solverSettingCountConflicts :: CountConflicts,
solverSettingMinimizeConflictSet :: MinimizeConflictSet,
solverSettingStrongFlags :: StrongFlags,
solverSettingAllowBootLibInstalls :: AllowBootLibInstalls,
solverSettingOnlyConstrained :: OnlyConstrained,
Expand Down
2 changes: 2 additions & 0 deletions cabal-install/Distribution/Client/ProjectPlanning.hs
Original file line number Diff line number Diff line change
Expand Up @@ -951,6 +951,8 @@ planPackages verbosity comp platform solver SolverSettings{..}

. setCountConflicts solverSettingCountConflicts

. setMinimizeConflictSet solverSettingMinimizeConflictSet

--TODO: [required eventually] should only be configurable for
--custom installs
-- . setAvoidReinstalls solverSettingAvoidReinstalls
Expand Down
22 changes: 20 additions & 2 deletions cabal-install/Distribution/Client/Setup.hs
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,7 @@ data FetchFlags = FetchFlags {
fetchMaxBackjumps :: Flag Int,
fetchReorderGoals :: Flag ReorderGoals,
fetchCountConflicts :: Flag CountConflicts,
fetchMinimizeConflictSet :: Flag MinimizeConflictSet,
fetchIndependentGoals :: Flag IndependentGoals,
fetchShadowPkgs :: Flag ShadowPkgs,
fetchStrongFlags :: Flag StrongFlags,
Expand All @@ -992,6 +993,7 @@ defaultFetchFlags = FetchFlags {
fetchMaxBackjumps = Flag defaultMaxBackjumps,
fetchReorderGoals = Flag (ReorderGoals False),
fetchCountConflicts = Flag (CountConflicts True),
fetchMinimizeConflictSet = Flag (MinimizeConflictSet False),
fetchIndependentGoals = Flag (IndependentGoals False),
fetchShadowPkgs = Flag (ShadowPkgs False),
fetchStrongFlags = Flag (StrongFlags False),
Expand Down Expand Up @@ -1053,6 +1055,7 @@ fetchCommand = CommandUI {
fetchMaxBackjumps (\v flags -> flags { fetchMaxBackjumps = v })
fetchReorderGoals (\v flags -> flags { fetchReorderGoals = v })
fetchCountConflicts (\v flags -> flags { fetchCountConflicts = v })
fetchMinimizeConflictSet (\v flags -> flags { fetchMinimizeConflictSet = v })
fetchIndependentGoals (\v flags -> flags { fetchIndependentGoals = v })
fetchShadowPkgs (\v flags -> flags { fetchShadowPkgs = v })
fetchStrongFlags (\v flags -> flags { fetchStrongFlags = v })
Expand All @@ -1073,6 +1076,7 @@ data FreezeFlags = FreezeFlags {
freezeMaxBackjumps :: Flag Int,
freezeReorderGoals :: Flag ReorderGoals,
freezeCountConflicts :: Flag CountConflicts,
freezeMinimizeConflictSet :: Flag MinimizeConflictSet,
freezeIndependentGoals :: Flag IndependentGoals,
freezeShadowPkgs :: Flag ShadowPkgs,
freezeStrongFlags :: Flag StrongFlags,
Expand All @@ -1090,6 +1094,7 @@ defaultFreezeFlags = FreezeFlags {
freezeMaxBackjumps = Flag defaultMaxBackjumps,
freezeReorderGoals = Flag (ReorderGoals False),
freezeCountConflicts = Flag (CountConflicts True),
freezeMinimizeConflictSet = Flag (MinimizeConflictSet False),
freezeIndependentGoals = Flag (IndependentGoals False),
freezeShadowPkgs = Flag (ShadowPkgs False),
freezeStrongFlags = Flag (StrongFlags False),
Expand Down Expand Up @@ -1142,6 +1147,7 @@ freezeCommand = CommandUI {
freezeMaxBackjumps (\v flags -> flags { freezeMaxBackjumps = v })
freezeReorderGoals (\v flags -> flags { freezeReorderGoals = v })
freezeCountConflicts (\v flags -> flags { freezeCountConflicts = v })
freezeMinimizeConflictSet (\v flags -> flags { freezeMinimizeConflictSet = v })
freezeIndependentGoals (\v flags -> flags { freezeIndependentGoals = v })
freezeShadowPkgs (\v flags -> flags { freezeShadowPkgs = v })
freezeStrongFlags (\v flags -> flags { freezeStrongFlags = v })
Expand Down Expand Up @@ -1711,6 +1717,7 @@ data InstallFlags = InstallFlags {
installMaxBackjumps :: Flag Int,
installReorderGoals :: Flag ReorderGoals,
installCountConflicts :: Flag CountConflicts,
installMinimizeConflictSet :: Flag MinimizeConflictSet,
installIndependentGoals :: Flag IndependentGoals,
installShadowPkgs :: Flag ShadowPkgs,
installStrongFlags :: Flag StrongFlags,
Expand Down Expand Up @@ -1757,6 +1764,7 @@ defaultInstallFlags = InstallFlags {
installMaxBackjumps = Flag defaultMaxBackjumps,
installReorderGoals = Flag (ReorderGoals False),
installCountConflicts = Flag (CountConflicts True),
installMinimizeConflictSet = Flag (MinimizeConflictSet False),
installIndependentGoals= Flag (IndependentGoals False),
installShadowPkgs = Flag (ShadowPkgs False),
installStrongFlags = Flag (StrongFlags False),
Expand Down Expand Up @@ -1968,6 +1976,7 @@ installOptions showOrParseArgs =
installMaxBackjumps (\v flags -> flags { installMaxBackjumps = v })
installReorderGoals (\v flags -> flags { installReorderGoals = v })
installCountConflicts (\v flags -> flags { installCountConflicts = v })
installMinimizeConflictSet (\v flags -> flags { installMinimizeConflictSet = v })
installIndependentGoals (\v flags -> flags { installIndependentGoals = v })
installShadowPkgs (\v flags -> flags { installShadowPkgs = v })
installStrongFlags (\v flags -> flags { installStrongFlags = v })
Expand Down Expand Up @@ -2778,14 +2787,16 @@ optionSolverFlags :: ShowOrParseArgs
-> (flags -> Flag Int ) -> (Flag Int -> flags -> flags)
-> (flags -> Flag ReorderGoals) -> (Flag ReorderGoals -> flags -> flags)
-> (flags -> Flag CountConflicts) -> (Flag CountConflicts -> flags -> flags)
-> (flags -> Flag MinimizeConflictSet) -> (Flag MinimizeConflictSet -> flags -> flags)
-> (flags -> Flag IndependentGoals) -> (Flag IndependentGoals -> flags -> flags)
-> (flags -> Flag ShadowPkgs) -> (Flag ShadowPkgs -> flags -> flags)
-> (flags -> Flag StrongFlags) -> (Flag StrongFlags -> flags -> flags)
-> (flags -> Flag AllowBootLibInstalls) -> (Flag AllowBootLibInstalls -> flags -> flags)
-> (flags -> Flag OnlyConstrained) -> (Flag OnlyConstrained -> flags -> flags)
-> [OptionField flags]
optionSolverFlags showOrParseArgs getmbj setmbj getrg setrg getcc setcc getig setig
getsip setsip getstrfl setstrfl getib setib getoc setoc =
optionSolverFlags showOrParseArgs getmbj setmbj getrg setrg getcc setcc
getmc setmc getig setig getsip setsip getstrfl setstrfl
getib setib getoc setoc =
[ option [] ["max-backjumps"]
("Maximum number of backjumps allowed while solving (default: " ++ show defaultMaxBackjumps ++ "). Use a negative number to enable unlimited backtracking. Use 0 to disable backtracking completely.")
getmbj setmbj
Expand All @@ -2801,6 +2812,13 @@ optionSolverFlags showOrParseArgs getmbj setmbj getrg setrg getcc setcc getig se
(fmap asBool . getcc)
(setcc . fmap CountConflicts)
(yesNoOpt showOrParseArgs)
, option [] ["minimize-conflict-set"]
("When there is no solution, try to improve the error message by finding "
++ "a minimal conflict set (default: false). May increase run time "
++ "significantly.")
(fmap asBool . getmc)
(setmc . fmap MinimizeConflictSet)
(yesNoOpt showOrParseArgs)
, option [] ["independent-goals"]
"Treat several goals on the command line as independent. If several goals depend on the same package, different versions can be chosen."
(fmap asBool . getig)
Expand Down
Loading

0 comments on commit 009fb61

Please sign in to comment.