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

New disjoint method for provider #179

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
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
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
Loading