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

Move to rank internals #174

Draft
wants to merge 4 commits into
base: dev-2.0.0
Choose a base branch
from
Draft
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
14 changes: 6 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,16 @@ jobs:
run:
shell: bash
strategy:
max-parallel: 10
matrix:
os: [ubuntu-latest, windows-latest]
python-version: [3.7, 3.8, 3.9, "3.10", "3.11"]
python-version: ["3.10", "3.11", "3.12"]

steps:
- name: Check out repository
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: "pip"
Expand All @@ -37,16 +36,15 @@ jobs:
- name: Run tests
run: |
python -m doctest README.md
python -m doctest paper.md
python -m pytest docs --nbval --nbval-current-env -p no:randomly
python -m pytest tests \
--cov=matching --cov-fail-under=100 --hypothesis-profile=ci

- name: Install and run linters (3.11-ubuntu only)
- name: Install and run linters (3.12-ubuntu only)
if: |
matrix.python-version == '3.11' &&
matrix.python-version == '3.12' &&
matrix.os == 'ubuntu-latest'
run: |
python -m pip install ".[lint]"
python -m black --check .
python -m ruff check .
python -m ruff format --check .
8 changes: 4 additions & 4 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ jobs:
contents: write
steps:
- name: Check out repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set up Quarto
uses: quarto-dev/quarto-actions/setup@v2
- name: Install Python and dependencies
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: "3.9"
python-version: "3.12"
cache: "pip"
- run: |
python -m pip install ".[dev]"
Expand All @@ -28,4 +28,4 @@ jobs:
with:
target: gh-pages
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18 changes: 18 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: check-added-large-files
name: Check for files larger than 5 MB
args: [ "--maxkb=5120" ]
- id: end-of-file-fixer
name: Check for a blank line at the end of scripts (auto-fixes)
exclude: '\.Rd'
- id: trailing-whitespace
name: Check for trailing whitespaces (auto-fixes)
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.7.0
hooks:
- id: ruff
args: [ --fix ]
- id: ruff-format
2 changes: 1 addition & 1 deletion CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ keywords:
- matching
- python
- game
license: MIT
license: MIT
46 changes: 14 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,60 +76,42 @@ We can construct these preferences using dictionaries:
Then to solve this matching game, we make use of the `StableMarriage`
class, like so:


```python
>>> from matching.games import StableMarriage
>>> game = StableMarriage.create_from_dictionaries(
>>> game = StableMarriage.from_preferences(
... suitor_preferences, reviewer_preferences
... )
>>> game.solve()
{A: E, B: D, C: F}
>>> matching = game.solve()
>>> dict(matching)
{'F': 'C', 'D': 'B', 'E': 'A'}

```

## The `Matching` object

This matching is not a standard Python dictionary, though it does
The matching itself is not a standard Python dictionary, though it does
largely look and behave like one. It is in fact an instance of the
`SingleMatching` class:

```python
>>> matching = game.matching
>>> type(matching)
<class 'matching.matchings.SingleMatching'>
<class 'matching.matchings.single.SingleMatching'>
>>> isinstance(matching, dict)
True
>>> matching
SingleMatching({'F': 'C', 'D': 'B', 'E': 'A'}, keys="reviewers", values="suitors")

```

This dictionary-like object is primarily useful as a teaching device
that eases the process of manipulating a matching after a solution has
been found.

## `Player` classes

Despite passing dictionaries of strings here, the matching displays
instances of `matching.player.Player`:
This object allows for straightforward manipulation of the underlying
dictionary, for instance by inverting it:

```python
>>> matching = game.matching
>>> for suitor in matching:
... print(type(suitor))
<class 'matching.players.player.Player'>
<class 'matching.players.player.Player'>
<class 'matching.players.player.Player'>
>>> dict(matching.invert())
{'C': 'F', 'B': 'D', 'A': 'E'}

```

This is because `create_from_dictionaries` creates instances of the
appropriate player classes first and passes them to the game class.
Using dictionaries like this can be an efficient way of creating large
games but it does require the names of the players in each party to be
unique.

With all games, Matching uses a `Player` class to represent the members
of the "applying" party, i.e. residents and students. For HR and SA,
there are specific classes to represent the roles of `Hospital`,
`Project` and `Supervisor`.

## A note on performance

One of the limitations of this library is the time complexities of the
Expand Down
6 changes: 3 additions & 3 deletions _quarto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ website:
contents: docs/discussion
- title: reference
contents: docs/reference


page-footer:
left: >
Expand All @@ -53,15 +53,15 @@ bibliography: docs/assets/bibliography.bib

toc: true

metadata-files:
metadata-files:
- docs/_sidebar.yml

quartodoc:
title: API reference
package: matching
dir: docs/reference
sidebar: docs/_sidebar.yml

sections:
- title: Games
desc: Objects for handling game instances.
Expand Down
6 changes: 3 additions & 3 deletions docs/discussion/stable_marriage.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ efficient, robust extension of the original algorithm, taken from
@GI89, is given below.

0. Assign all suitors and reviewers to be unmatched.
1. Take any suitor $s$ that is not currently matched, and consider
their favourite reviewer $r$.
1. Take any suitor $s$ that is not currently matched but has a non-empty
preference list, and consider their favourite reviewer $r$.
2. If $r$ is matched, get their current match $s' = M^{-1}(r)$ and
unmatch the pair.
unmatch them.
3. Match $s$ and $r$, i.e. set $M(s) = r$.
4. For each successor, $t$, to $s$ in $g(r)$, delete the pair $(t, r)$
from the game by removing $r$ from $f(t)$ and $t$ from $g(r)$.
Expand Down
14 changes: 7 additions & 7 deletions docs/how-to/choose_optimality.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
{
"data": {
"text/plain": [
"{A: X, B: Z, C: Y}"
"SingleMatching({'Y': 'C', 'Z': 'B', 'X': 'A'}, keys=\"reviewers\", values=\"suitors\")"
]
},
"execution_count": 2,
Expand All @@ -56,7 +56,7 @@
}
],
"source": [
"game = StableMarriage.create_from_dictionaries(\n",
"game = StableMarriage.from_preferences(\n",
" suitor_preferences, reviewer_preferences\n",
")\n",
"\n",
Expand All @@ -71,7 +71,7 @@
{
"data": {
"text/plain": [
"{A: Y, B: Z, C: X}"
"SingleMatching({'Y': 'A', 'Z': 'B', 'X': 'C'}, keys=\"reviewers\", values=\"suitors\")"
]
},
"execution_count": 3,
Expand All @@ -80,7 +80,7 @@
}
],
"source": [
"game = StableMarriage.create_from_dictionaries(\n",
"game = StableMarriage.from_preferences(\n",
" suitor_preferences, reviewer_preferences\n",
")\n",
"\n",
Expand All @@ -90,9 +90,9 @@
],
"metadata": {
"kernelspec": {
"display_name": "matching-docs",
"display_name": "matching",
"language": "python",
"name": "matching-docs"
"name": "python3"
},
"language_info": {
"codemirror_mode": {
Expand All @@ -104,7 +104,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.16"
"version": "3.11.10"
}
},
"nbformat": 4,
Expand Down
90 changes: 0 additions & 90 deletions docs/how-to/create_from_instances.ipynb

This file was deleted.

15 changes: 4 additions & 11 deletions docs/tutorials/hospital_resident.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -225,13 +225,6 @@
"unmatched_residents"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"metadata": {},
Expand All @@ -245,9 +238,9 @@
],
"metadata": {
"kernelspec": {
"display_name": "matching-docs",
"display_name": "matching",
"language": "python",
"name": "matching-docs"
"name": "python3"
},
"language_info": {
"codemirror_mode": {
Expand All @@ -259,7 +252,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.16"
"version": "3.11.10"
}
},
"nbformat": 4,
Expand Down
Loading