Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Looking for feedback on narrow backtrack causes approach #140

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions src/resolvelib/resolvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,34 @@ def _attempt_to_pin_criterion(self, name):
# end, signal for backtracking.
return causes

def _narrow_causes(self, causes):
"""Return a narrowed causes list
"""
# Causes are often duplicates, first dedup them
deduped_causes = list({id(c): c for c in causes}.values())

# For each cause check if it actually contradicts with another cause
# and put them both in "narrowed causes", or otherwise disregard it
narrowed_causes = []
while deduped_causes:
cause = deduped_causes.pop()
for i, alternative_cause in enumerate(deduped_causes):
if cause.requirement.name != alternative_cause.requirement.name:
continue

specifier = (
alternative_cause.requirement.get_candidate_lookup()[1].specifier
)
alternative_specifier = (
alternative_cause.requirement.get_candidate_lookup()[1].specifier
)
specifier_intersection = specifier and alternative_specifier
if not str(specifier_intersection):
narrowed_causes.append(cause)
narrowed_causes.append(deduped_causes.pop(i))

return narrowed_causes

def _backjump(self, causes):
"""Perform backjumping.

Expand Down Expand Up @@ -315,7 +343,7 @@ def _backjump(self, causes):
broken_state = self._states.pop()
name, candidate = broken_state.mapping.popitem()
except (IndexError, KeyError):
raise ResolutionImpossible(causes) from None
raise ResolutionImpossible(causes)
current_dependencies = {
self._p.identify(d)
for d in self._p.get_dependencies(candidate)
Expand Down Expand Up @@ -432,7 +460,7 @@ def resolve(self, requirements, max_rounds):
# an unpinned state, so we can work on it in the next round.
self._r.resolving_conflicts(causes=causes)
success = self._backjump(causes)
self.state.backtrack_causes[:] = causes
self.state.backtrack_causes[:] = self._narrow_causes(causes)

# Dead ends everywhere. Give up.
if not success:
Expand Down
Loading