Skip to content

Commit

Permalink
Add pre-commit hooks.
Browse files Browse the repository at this point in the history
  • Loading branch information
jtilly committed Sep 19, 2024
1 parent 26ed1f6 commit 7993a74
Show file tree
Hide file tree
Showing 11 changed files with 126 additions and 103 deletions.
21 changes: 21 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
repos:
- repo: https://github.com/Quantco/pre-commit-mirrors-prettier
rev: 3.2.5
hooks:
- id: prettier-conda
files: \.(md|yml|yaml)$
- repo: https://github.com/Quantco/pre-commit-mirrors-pre-commit-hooks
rev: 4.6.0
hooks:
- id: trailing-whitespace-conda
- id: end-of-file-fixer-conda
- id: check-merge-conflict-conda
args: ["--assume-in-merge"]
- repo: https://github.com/Quantco/pre-commit-mirrors-typos
rev: 1.24.5
hooks:
- id: typos-conda
- repo: https://github.com/Quantco/pre-commit-mirrors-clang-format
rev: 18.1.8
hooks:
- id: clang-format-conda
67 changes: 33 additions & 34 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,69 +1,68 @@
# matchingR 1.3.3

* Fixed unit test for validate functions that caused a CRAN check to fail.
- Fixed unit test for validate functions that caused a CRAN check to fail.

# matchingR 1.3.2

* Fix vignette index.
- Fix vignette index.

# matchingR 1.3.1

* Add dummy roommate when number of roommates is odd [#37](https://github.com/jtilly/matchingR/issues/37)
* Run code base through `styler` and `lintr`
- Add dummy roommate when number of roommates is odd [#37](https://github.com/jtilly/matchingR/issues/37)
- Run code base through `styler` and `lintr`

# matchingR 1.3.0

* Allow colleges to have different numbers of slots [#31](https://github.com/jtilly/matchingR/issues/31)
* Change row names in vignette [#34](https://github.com/jtilly/matchingR/issues/34)
* Remove need for microbenchmark package [#35](https://github.com/jtilly/matchingR/issues/35)
* Registration of entry points in compiled code
- Allow colleges to have different numbers of slots [#31](https://github.com/jtilly/matchingR/issues/31)
- Change row names in vignette [#34](https://github.com/jtilly/matchingR/issues/34)
- Remove need for microbenchmark package [#35](https://github.com/jtilly/matchingR/issues/35)
- Registration of entry points in compiled code

# matchingR 1.2.2

This is a minor update.
This is a minor update.

* Colleges may have different numbers of slots in the college admissions problem ([#30](https://github.com/jtilly/matchingR/issues/30))
- Colleges may have different numbers of slots in the college admissions problem ([#30](https://github.com/jtilly/matchingR/issues/30))

# matchingR 1.2.1

This is a minor update.
This is a minor update.

* Fixed bug in galeShapley.checkStability that resulted in UBSAN throwing an error
- Fixed bug in galeShapley.checkStability that resulted in UBSAN throwing an error

# matchingR 1.2

* Fixed a bug in the stable roommate matching algorithm that caused
problems on Mac OS X / clang
* Changed function names throughout the package (deprecated old function names)
* Updated documentation
* Added tests
* Removed option to define preferences in row major order
- Fixed a bug in the stable roommate matching algorithm that caused
problems on Mac OS X / clang
- Changed function names throughout the package (deprecated old function names)
- Updated documentation
- Added tests
- Removed option to define preferences in row major order

# matchingR 1.1.1

This is a minor update.

* It fixes a memory leak warning in the stable roommate algorithm.
* It includes minor edits of the vignettes and documentation.
* We have substantially shortened the computational performance vignette
so that the package can be built and checked faster
This is a minor update.

- It fixes a memory leak warning in the stable roommate algorithm.
- It includes minor edits of the vignettes and documentation.
- We have substantially shortened the computational performance vignette
so that the package can be built and checked faster

# matchingR 1.1

This is a major update that added additional algorithms to the package.

* Added algorithm to compute a solution to the stable roommate problem
(`roommate`)
* Added top trading cycle algorithm (`toptrading`)
* Switched the layout of preference matrices from row order to column order
to make the code faster
* Added two vignettes: An introductory vignette to the package in general
and a computational performance vignette
- Added algorithm to compute a solution to the stable roommate problem
(`roommate`)
- Added top trading cycle algorithm (`toptrading`)
- Switched the layout of preference matrices from row order to column order
to make the code faster
- Added two vignettes: An introductory vignette to the package in general
and a computational performance vignette

# matchingR 1.0.1

Initial release that computes two versions of the Gale-Shapley algorithm:
* Stable Marriage Problem
* College Admissions Problem

- Stable Marriage Problem
- College Admissions Problem
5 changes: 2 additions & 3 deletions R/RcppExports.R
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ cpp_wrapper_galeshapley_check_stability <- function(proposerUtils, reviewerUtils
#' This is the C++ wrapper for the stable roommate problem. Users should not
#' call this function directly, but instead use
#' \code{\link{roommate}}.
#'
#'
#' @param pref is a matrix with the preference order of each individual in the
#' market. If there are \code{n} individuals, then this matrix will be of
#' dimension \code{n-1} by \code{n}. The \code{i,j}th element refers to
Expand Down Expand Up @@ -115,7 +115,7 @@ cpp_wrapper_irving_check_stability <- function(pref, matchings) {
}

#' Computes the top trading cycle algorithm
#'
#'
#' This is the C++ wrapper for the top trading cycle algorithm. Users should not
#' call this function directly, but instead use
#' \code{\link{toptrading}}.
Expand Down Expand Up @@ -195,4 +195,3 @@ sortIndexOneSided <- function(u) {
rankIndex <- function(sortedIdx) {
.Call('_matchingR_rankIndex', PACKAGE = 'matchingR', sortedIdx)
}

35 changes: 20 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
Matching Algorithms in R and C++
===============
# Matching Algorithms in R and C++

[![GitHub Actions](https://github.com/jtilly/matchingR/workflows/Test%20Package/badge.svg)](https://github.com/jtilly/matchingR/actions)
[![Coverage Status](https://coveralls.io/repos/jtilly/matchingR/badge.svg?branch=master)](https://coveralls.io/github/jtilly/matchingR)
[![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/matchingR)](https://cran.r-project.org/package=matchingR)
[![CRAN_Downloads](https://cranlogs.r-pkg.org/badges/grand-total/matchingR?color=brightgreen)](https://cran.r-project.org/package=matchingR)


[!["You know that I'll never leave you. Not as long as she's with someone."](https://imgs.xkcd.com/comics/all_the_girls.png)](https://xkcd.com/770/ "You know that I'll never leave you. Not as long as she's with someone.")


`matchingR` is an R package which quickly computes the [Gale-Shapley algorithm](https://www.jstor.org/stable/2312726), [Irving's algorithm for the stable roommate problem](https://www.sciencedirect.com/science/article/pii/0196677485900331/), and the [top trading cycle algorithm](https://www.sciencedirect.com/science/article/abs/pii/0304406874900330/) for large matching markets. The package provides functions to compute the solutions to the
[stable marriage problem](https://en.wikipedia.org/wiki/Stable_matching), the
[college admission problem](https://en.wikipedia.org/wiki/Hospital_resident), the
[stable roommates problem](https://en.wikipedia.org/wiki/Stable_roommates_problem), and the
[house allocation problem](https://web.stanford.edu/~niederle/HouseAllocation.pdf).
[stable marriage problem](https://en.wikipedia.org/wiki/Stable_matching), the
[college admission problem](https://en.wikipedia.org/wiki/Hospital_resident), the
[stable roommates problem](https://en.wikipedia.org/wiki/Stable_roommates_problem), and the
[house allocation problem](https://web.stanford.edu/~niederle/HouseAllocation.pdf).

The package may be useful when the number of market participants is large or when many matchings need to be computed (e.g., for simulation or estimation purposes). It has been used in practice to compute the Gale-Shapley stable matching with 30,000 participants on each side of the market.

Matching markets are common in practice and widely studied by economists. Popular examples include

* the [National Resident Matching Program](https://www.nrmp.org/) which matches graduates from medical school to residency programs at teaching hospitals throughout the United States
* the matching of students to schools including the [New York City High School Match](https://www.jstor.org/stable/4132848) or the [Boston Public School Match](https://www.jstor.org/stable/4132849) (and many more)
* the matching of kidney donors to recipients in [kidney exchanges](https://www.jstor.org/stable/4132851).
- the [National Resident Matching Program](https://www.nrmp.org/) which matches graduates from medical school to residency programs at teaching hospitals throughout the United States
- the matching of students to schools including the [New York City High School Match](https://www.jstor.org/stable/4132848) or the [Boston Public School Match](https://www.jstor.org/stable/4132849) (and many more)
- the matching of kidney donors to recipients in [kidney exchanges](https://www.jstor.org/stable/4132851).

Installation
------------
## Installation

`matchingR` may be installed from [CRAN](https://cran.r-project.org/package=matchingR):

```r
install.packages("matchingR")
```

The latest development release is available from GitHub:

```r
devtools::install_github("jtilly/matchingR")
```
Expand All @@ -40,6 +40,7 @@ devtools::install_github("jtilly/matchingR")
### Gale-Shapley Algorithm for Two-Sided Markets

**Stable Marriage Problem**

```r
library(matchingR)

Expand All @@ -63,6 +64,7 @@ galeShapley.checkStability(uM, uW, matching$proposals, matching$engagements)
```

**College Admissions Problem**

```r
library(matchingR)

Expand Down Expand Up @@ -100,6 +102,7 @@ galeShapley.checkStability(uStudents, uColleges, matching$matched.students, matc
```

### Irving's Algorithm for the Stable Roommate Problem

```r
library(matchingR)

Expand All @@ -123,6 +126,7 @@ results
```

### Top-Trading Cycle Algorithm

```r
library(matchingR)

Expand All @@ -146,5 +150,6 @@ results
```

## Documentation
* [Reference Manual](https://jtilly.io/matchingR/matchingR.pdf "Matching Algorithms in R and C++: Reference Manual")
* [Vignette: Matching Algorithms in R and C++: An Introduction to matchingR](https://jtilly.io/matchingR/vignettes/matchingR-intro.html "Matching Algorithms in R and C++: An Introduction to matchingR")

- [Reference Manual](https://jtilly.io/matchingR/matchingR.pdf "Matching Algorithms in R and C++: Reference Manual")
- [Vignette: Matching Algorithms in R and C++: An Introduction to matchingR](https://jtilly.io/matchingR/vignettes/matchingR-intro.html "Matching Algorithms in R and C++: An Introduction to matchingR")
1 change: 0 additions & 1 deletion man/matchingR-deprecated.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/Makevars
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CXX_STD = CXX11
PKG_CPPFLAGS = -I../inst/include
PKG_CXXFLAGS = $(SHLIB_OPENMP_CXXFLAGS)
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
56 changes: 28 additions & 28 deletions src/galeshapley.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,74 +60,74 @@ List cpp_wrapper_galeshapley(const umat& proposerPref, const mat& reviewerUtils)

// number of proposers (men)
int M = proposerPref.n_cols;

// number of reviewers (women)
int N = proposerPref.n_rows;

// initialize engagements, proposals
vec engagements(N), proposals(M);
// create an integer queue of bachelors

// create an integer queue of bachelors
// the idea of using queues for this problem is borrowed from
// http://rosettacode.org/wiki/Stable_marriage_problem#C.2B.2B
queue<int> bachelors;

// set all proposals to N (aka no proposals)
proposals.fill(N);

// set all engagements to M (aka no engagements)
engagements.fill(M);

// every proposer starts out as a bachelor
for(int iX=M-1; iX >= 0; iX--) {
bachelors.push(iX);
}

// loop until there are no more proposals to be made
while (!bachelors.empty()) {

// get the index of the proposer
int proposer = bachelors.front();
// get the proposer's preferences: we use a raw pointer to the memory

// get the proposer's preferences: we use a raw pointer to the memory
// used by the column `proposer` for performance reasons (this is to avoid
// making a copy of the proposers vector of preferences)
const uword * proposerPrefcol = proposerPref.colptr(proposer);

// find the best available match for proposer
for(int jX=0; jX<N; jX++) {

// get the index of the reviewer that the proposer is interested in
// by dereferencing the pointer; increment the pointer after use (not its value)
const uword wX = *proposerPrefcol++;

// check if wX is available (`M` means unmatched)
if(engagements(wX)==M) {

// if available, then form a match
engagements(wX) = proposer;
proposals(proposer) = wX;

// go to the next proposer
break;
}

// wX is already matched, let's see if wX can be poached
if(reviewerUtils(proposer, wX) > reviewerUtils(engagements(wX), wX)) {

// wX's previous partner becomes unmatched (`N` means unmatched)
proposals(engagements(wX)) = N;
bachelors.push(engagements(wX));

// proposer and wX form a match
engagements(wX) = proposer;
proposals(proposer) = wX;

// go to the next proposer
break;
}
}

// remove proposer from bachelor queue: proposer will remain unmatched
bachelors.pop();
}
Expand Down Expand Up @@ -171,13 +171,13 @@ bool cpp_wrapper_galeshapley_check_stability(mat proposerUtils, mat reviewerUtil

// number of workers
const int M = proposerUtils.n_cols;

// number of firms
const int N = proposerUtils.n_rows;

// number of slots per firm
const int slotsReviewers = engagements.n_cols;

// number of slots per worker
const int slotsProposers = proposals.n_cols;

Expand All @@ -191,19 +191,19 @@ bool cpp_wrapper_galeshapley_check_stability(mat proposerUtils, mat reviewerUtil
proposerUtils.insert_rows(N, 1);
proposerUtils.row(N).fill(-1e10);
}

// loop over workers
for(int wX=0; wX<M; wX++) {

// loop over firms
for(int fX=0; fX<N; fX++) {

// loop over multiple "slots" at the same worker
for(int swX=0;swX<slotsProposers;swX++) {

// loop over multiple slots at the same firm
for(int sfX=0;sfX<slotsReviewers;sfX++) {

// check if wX and fX would rather be matched with each other than with their actual matches
if(reviewerUtils(wX, fX) > reviewerUtils(engagements(fX, sfX), fX) && proposerUtils(fX, wX) > proposerUtils(proposals(wX, swX), wX)) {
::Rf_warning("matching is not stable; worker %d would rather be matched to firm %d and vice versa.\n", wX, fX);
Expand Down
2 changes: 1 addition & 1 deletion src/roommate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
//' This is the C++ wrapper for the stable roommate problem. Users should not
//' call this function directly, but instead use
//' \code{\link{roommate}}.
//'
//'
//' @param pref is a matrix with the preference order of each individual in the
//' market. If there are \code{n} individuals, then this matrix will be of
//' dimension \code{n-1} by \code{n}. The \code{i,j}th element refers to
Expand Down
Loading

0 comments on commit 7993a74

Please sign in to comment.