Skip to content

Commit

Permalink
Revert backjumping
Browse files Browse the repository at this point in the history
  • Loading branch information
notatallshaw committed Nov 12, 2023
1 parent 044ab9f commit 58bf803
Showing 1 changed file with 11 additions and 36 deletions.
47 changes: 11 additions & 36 deletions src/resolvelib/resolvers.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,8 @@ def _attempt_to_pin_criterion(self, name: KT) -> list[Criterion[RT, CT]]:
# end, signal for backtracking.
return causes

def _backjump(self, causes: list[RequirementInformation[RT, CT]]) -> bool:
"""Perform backjumping.
def _backtrack(self) -> bool:
"""Perform backtracking.
When we enter here, the stack is like this::
Expand All @@ -286,47 +286,22 @@ def _backjump(self, causes: list[RequirementInformation[RT, CT]]) -> bool:
Each iteration of the loop will:
1. Identify Z. The incompatibility is not always caused by the latest
state. For example, given three requirements A, B and C, with
dependencies A1, B1 and C1, where A1 and B1 are incompatible: the
last state might be related to C, so we want to discard the
previous state.
2. Discard Z.
3. Discard Y but remember its incompatibility information gathered
1. Discard Z.
2. Discard Y but remember its incompatibility information gathered
previously, and the failure we're dealing with right now.
4. Push a new state Y' based on X, and apply the incompatibility
3. Push a new state Y' based on X, and apply the incompatibility
information from Y to Y'.
5a. If this causes Y' to conflict, we need to backtrack again. Make Y'
4a. If this causes Y' to conflict, we need to backtrack again. Make Y'
the new Z and go back to step 2.
5b. If the incompatibilities apply cleanly, end backtracking.
4b. If the incompatibilities apply cleanly, end backtracking.
"""
incompatible_reqs: Iterable[CT | RT] = itertools.chain(
(c.parent for c in causes if c.parent is not None),
(c.requirement for c in causes),
)
incompatible_deps = {self._p.identify(r) for r in incompatible_reqs}
while len(self._states) >= 3:
# Remove the state that triggered backtracking.
del self._states[-1]

# Ensure to backtrack to a state that caused the incompatibility
incompatible_state = False
broken_state = self.state
while not incompatible_state:
# Retrieve the last candidate pin and known incompatibilities.
try:
broken_state = self._states.pop()
name, candidate = broken_state.mapping.popitem()
except (IndexError, KeyError):
raise ResolutionImpossible(causes) from None
current_dependencies = {
self._p.identify(d)
for d in self._p.get_dependencies(candidate)
}
incompatible_state = not current_dependencies.isdisjoint(
incompatible_deps
)

# Retrieve the last candidate pin and known incompatibilities.
broken_state = self._states.pop()
name, candidate = broken_state.mapping.popitem()
incompatibilities_from_broken = [
(k, list(v.incompatibilities))
for k, v in broken_state.criteria.items()
Expand Down Expand Up @@ -436,7 +411,7 @@ def resolve(
# Backjump if pinning fails. The backjump process puts us in
# an unpinned state, so we can work on it in the next round.
self._r.resolving_conflicts(causes=causes)
success = self._backjump(causes)
success = self._backtrack()
self.state.backtrack_causes[:] = causes

# Dead ends everywhere. Give up.
Expand Down

0 comments on commit 58bf803

Please sign in to comment.