Skip to content

Commit

Permalink
New disjoint method for provider
Browse files Browse the repository at this point in the history
  • Loading branch information
notatallshaw committed Nov 10, 2024
1 parent 51dbc92 commit 92c7d17
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 4 deletions.
27 changes: 27 additions & 0 deletions src/resolvelib/providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,3 +194,30 @@ def narrow_requirement_selection(
Iterable[KT]: A non-empty subset of `identifiers`.
"""
return identifiers

def disjoint(
self, backtrack_causes: Sequence[RequirementInformation[RT, CT]]
) -> Sequence[RequirementInformation[RT, CT]]:
"""Filter backtrack causes to retain only disjoint instances.
Given a sequence of backtrack causes, return those that are disjoint.
This filtered sequence will attached to the resolution state, passed to
the provider methods `get_preference` and `narrow_requirement_selection`,
and the reporter method `resolving_conflicts`.
:param backtrack_causes: A sequence of *requirement information* that are
the requirements causing the resolver to most recently
backtrack.
A *requirement information* instance is a named tuple with two members:
* ``requirement`` specifies a requirement contributing to the current
list of candidates.
* ``parent`` specifies the candidate that provides (is depended on for)
the requirement, or ``None`` to indicate a root requirement.
Returns:
Sequence[RequirementInformation[RT, CT]]: A subset of at least two
disjoint `backtrack_causes`.
"""
return backtrack_causes
15 changes: 11 additions & 4 deletions src/resolvelib/resolvers/resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import collections
import itertools
import operator
from typing import TYPE_CHECKING, Collection, Generic, Iterable, Mapping
from typing import TYPE_CHECKING, Collection, Generic, Iterable, Mapping, Sequence

from ..structs import (
CT,
Expand Down Expand Up @@ -274,7 +274,7 @@ def _patch_criteria(
)
return True

def _backjump(self, causes: list[RequirementInformation[RT, CT]]) -> bool:
def _backjump(self, causes: Sequence[RequirementInformation[RT, CT]]) -> bool:
"""Perform backjumping.
When we enter here, the stack is like this::
Expand Down Expand Up @@ -365,9 +365,16 @@ def _backjump(self, causes: list[RequirementInformation[RT, CT]]) -> bool:

def _extract_causes(
self, criteron: list[Criterion[RT, CT]]
) -> list[RequirementInformation[RT, CT]]:
) -> Sequence[RequirementInformation[RT, CT]]:
"""Extract causes from list of criterion and deduplicate"""
return list({id(i): i for c in criteron for i in c.information}.values())
causes = list({id(i): i for c in criteron for i in c.information}.values())

# Two causes *should* always be disjoint, so only check for
# disjoint causes when there are more than two
if len(causes) > 2:
return self._p.disjoint(causes)

return causes

def resolve(self, requirements: Iterable[RT], max_rounds: int) -> State[RT, CT, KT]:
if self._states:
Expand Down

0 comments on commit 92c7d17

Please sign in to comment.