Skip to main content

Colley Matrix NuGet Package

· 3 min read
Scottie Enriquez
Senior Solutions Developer at Amazon Web Services

Overview

It's very well documented that I'm a huge college football fan. We're presently in the College Football Playoff era of Division I football, which involves a selection committee choosing four playoff teams to compete to be the national champion. The previous era, known as the Bowl Championship Series era, involved a combined poll of human experts and computer algorithms choosing the two best teams to play in the national championship game. One such algorithm is known as the Colley Matrix. Though not a factor in the post-season selection process anymore, it's still referred to at times, particularly when debating the selection committee’s decisions. Based on the whitepaper written by Colley himself and [an existing JavaScript implementation](an existing JavaScript implementation), I developed this NuGet package for simulating head-to-head matchups and applying the Colley algorithm. This algorithm can be applied to any sport or competitions without tie games.

Usage

The ColleyMatrix client exposes two methods: SimulateGame and Solve. The client constructor takes one argument: numberOfTeams.

ColleyMatrix colleyMatrix = new ColleyMatrix(numberOfTeams);

This will create a client with an underlying sparse matrix where the dimensions span from 0 to numberOfTeams - 1 corresponding to each team's ID. Next, we can simulate matchups.

colleyMatrix.SimulateGame(winnerId, loserId);

Note that if the winnerId or loserId is not valid respective to the sparse matrix's dimensions, an exception will be thrown.

You can solve the sparse matrix at any point without modifying the internal state. The solved vector that is returned is a list of scores with the highest score indicating the best team.

IEnumerable<double> solvedVector = colleyMatrix.Solve();

Basics of Implementation

SimulateGame updates the matrix state which is wrapped by an interface called IMatrixProvider. This removes the dependency on a specific matrix implementation from the underlying domain logic. For reference, the ColleyMatrix client ultimately injects a Math.NET SparseMatrix. The updates to the matrix state are very simple.

src/ColleyMatrix/Service/ColleyMatrixService.cs
double gameCount = _matrixProvider.GetValue(winnerId, loserId);
_matrixProvider.SetValue(winnerId, loserId, gameCount - 1);
_matrixProvider.SetValue(loserId, winnerId, gameCount - 1);
_matrixProvider.SetValue(winnerId, winnerId, _matrixProvider.GetValue(winnerId, winnerId) + 1);
_matrixProvider.SetValue(loserId, loserId, _matrixProvider.GetValue(loserId, loserId) + 1);

A list of teams and their corresponding ratings are also maintained.

src/ColleyMatrix/Service/ColleyMatrixService.cs
_teams[winnerId].Wins++;
_teams[loserId].Losses++;
_teams[winnerId].ColleyRating = ComputeColleyRating(_teams[winnerId].Wins, _teams[winnerId].Losses);
_teams[loserId].ColleyRating = ComputeColleyRating(_teams[loserId].Wins, _teams[loserId].Losses);

The formula for computing the Colley rating is very simple.

src/ColleyMatrix/Service/ColleyMatrixService.cs
1 + (wins - losses) / 2;

For the Solve method, the matrix is lower-upper factorized then solved for the vector of the teams' Colley ratings.

src/ColleyMatrix/Service/ColleyMatrixService.cs
IEnumerable<double> colleyRatings = _teams.Select(team => team.ColleyRating);
IEnumerable<double> solvedVector = _matrixProvider.LowerUpperFactorizeAndSolve(colleyRatings);

Build Status

Build status