Skip to main content

This package makes finding optimal combinations using the hungarian algorithm dead simple.

Project description

Hungarian Scorer

Often, it is important to find the optimal solution when pairing up items from two different lists. Here are some examples of situations where that is necessary:

  • Assigning gymnasts to each event to maximize the team's overall score
  • Choosing which worker(s) to hire based on your current team's skillset
  • Identifying which words in two different names have the highest coorelation
  • Allocating limited resources to the proper areas

Making it simple

The Hungarian algorithm makes this all possible in O(n3) time. However, it can be difficult to create the matrix necessary to execute this algorithm, especially when the two lists are not equivilant in length. This package is meant to make finding optimal combinations using the hungarian algorithm dead simple. No matrices, no mess- just pass in the two lists and the function to score pairs, and you're done.

Code

'But I already have the scores!'

If you already have scores, no worries! Just format your scores like so (making sure you don't miss an entry) and you can pass in a lambda to access the scores, as well as the scores themselves, as demonstrated below.

from HungarianScorer.HungarianScorer import HungarianScorer

players = ['wilhelm', 'dave', 'stewart', 'jordan']
events = ['pommel horse', 'floor', 'parallel bars']
scores = {
    ('wilhelm', 'pommel horse'): 90,
    ('wilhelm', 'floor'): 50,
    ('wilhelm', 'parallel bars'): 50,

    ('dave', 'pommel horse'): 70,
    ('dave', 'floor'): 82,
    ('dave', 'parallel bars'): 75,

    ('stewart', 'pommel horse'): 70,
    ('stewart', 'floor'): 79,
    ('stewart', 'parallel bars'): 70,

    ('jordan', 'pommel horse'): 85,
    ('jordan', 'floor'): 68,
    ('jordan', 'parallel bars'): 70,
}

accessScore = lambda player,event,scores: scores[(player, event)]
result = HungarianScorer.getBestCombo(players, events, accessScore, scores)
# [('wilhelm', 'pommel horse', 90.0), ('dave', 'parallel bars', 75.0), ('stewart', 'floor', 79.0)]

Note: Jordan is still an amazing athlete. It is advised to take into account risk and standard deviation into your scores, as Jordan may in fact be the better choice for his consistency.

Passing in functions that take only two arguments

Such simple functions are the easiest to implement. All you need provide are the lists and the function.

from HungarianScorer.HungarianScorer import HungarianScorer
from fuzzywuzzy import fuzz # fuzz.ratio is a simple function that rates how close two strings are from 0-100

listA = ['j', 'john', 'weymouth']
listB = ['steve', 'jon', 'jamison', 'waymouth']

bestCombo = HungarianScorer.getBestCombo(listA, listB, fuzz.ratio)
# [('j', 'jamison', 25.0), ('john', 'jon', 86.0), ('weymouth', 'waymouth', 88.0)]

Using more complex functions

Sometimes you will need to pass in more complex functions, that take more than just the two list item variables. All you have to do is make sure your function has itemA as its first argument, itemB as its second argument, and any other objects you need to use can be appended on at the end, as seen below.

from HungarianScorer.HungarianScorer import HungarianScorer

listA = ['j', 'john', 'weymouth']
listB = ['steve', 'jon', 'jamison', 'waymouth']
def exampleScoringFunc(itemA:str, itemB:str, wildCardLetter) -> float:
    score = 100 - abs(len(itemA) - len(itemB))
    score += itemA.count(wildCardLetter)
    return score

bestCombo = HungarianScorer.getBestCombo(listA, listB, exampleScoringFunc, 'j')
# [('j', 'jon', 99.0), ('john', 'steve', 100.0), ('weymouth', 'waymouth', 100.0)]

Indices

Sometimes it is meaningful to know the indices of the items in each pair. This is especially useful when some of the objects in one of the lists are identical. Here is the code to do that:

from HungarianScorer.HungarianScorer import HungarianScorer
from fuzzywuzzy import fuzz

listA = ['john', 'john', 'weymouth']
listB = ['steve', 'jon', 'jamison', 'waymouth']

bestCombo = HungarianScorer.getBestCombo(listA, listB, fuzz.ratio)
# [('john', 'jon', 86.0), ('john', 'jamison', 55.0), ('weymouth', 'waymouth', 88.0)]

bestComboIndices = HungarianScorer.getBestComboAsIndices(listA, listB, fuzz.ratio)
# [(0, 1, 86.0), (1, 2, 55.0), (2, 3, 88.0)]

Note

Remember that the two lists do not have to be items of the same type. For example, listA could be made of strings, while listB could be made of custom objects. All you need is a function that can return a float when comparing the two different objects.

Enjoy!

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hungarianscorer-1.0.0.tar.gz (4.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

HungarianScorer-1.0.0-py3-none-any.whl (4.9 kB view details)

Uploaded Python 3

File details

Details for the file hungarianscorer-1.0.0.tar.gz.

File metadata

  • Download URL: hungarianscorer-1.0.0.tar.gz
  • Upload date:
  • Size: 4.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.8.0 colorama/0.4.4 importlib-metadata/4.6.4 keyring/23.5.0 pkginfo/1.8.2 readme-renderer/34.0 requests-toolbelt/0.9.1 requests/2.25.1 rfc3986/1.5.0 tqdm/4.57.0 urllib3/1.26.5 CPython/3.10.12

File hashes

Hashes for hungarianscorer-1.0.0.tar.gz
Algorithm Hash digest
SHA256 377b2d33daaa7ee4ca6119dc1adf38c25154f6a02a7d539d33984b7b0c1b65b3
MD5 42843e69aba82bca0649c2733dc5bee3
BLAKE2b-256 51ced9a0ffd0705a0a7ab12f09632b2d7638a9cf654d36bab4e8889e8a46831a

See more details on using hashes here.

File details

Details for the file HungarianScorer-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: HungarianScorer-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 4.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.8.0 colorama/0.4.4 importlib-metadata/4.6.4 keyring/23.5.0 pkginfo/1.8.2 readme-renderer/34.0 requests-toolbelt/0.9.1 requests/2.25.1 rfc3986/1.5.0 tqdm/4.57.0 urllib3/1.26.5 CPython/3.10.12

File hashes

Hashes for HungarianScorer-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 72fffb0cb5eb71f18652a82f05f62dd4a6d4ebfcb6f1dccd11a38f2fb579e367
MD5 2d98b151ccd95baffe3908a2dcd7d7c4
BLAKE2b-256 cd2b10dd32b85c82e54cd0bea1f53dcfc4a4e7efe82108a0fa0f07fa1c83cc1e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page