{ "info": { "author": "Henry Wilde", "author_email": "henrydavidwilde@gmail.com", "bugtrack_url": null, "classifiers": [], "description": "Matching\n========\n\n.. image:: https://img.shields.io/pypi/v/matching.svg\n :target: https://pypi.org/project/matching/\n\n.. image:: https://coveralls.io/repos/github/daffidwilde/matching/badge.svg?branch=master\n :target: https://coveralls.io/github/daffidwilde/matching?branch=master\n\n.. image:: https://travis-ci.com/daffidwilde/matching.svg?branch=master\n :target: https://travis-ci.com/daffidwilde/matching\n\n.. image:: https://img.shields.io/badge/code%20style-black-000000.svg\n :target: https://github.com/ambv/black\n\n.. image:: https://zenodo.org/badge/119597240.svg\n :target: https://zenodo.org/badge/latestdoi/119597240\n\n\nA package for solving matching games.\n-------------------------------------\n\nA matching game is defined by two sets of players. Each player in one set has a\nranked preference list of those in the other, and the objective is to find some\nmapping between the two sets such that no pair of players are unhappy. The\ncontext of the terms \"mapping\" and \"unhappy\" are dependent on the framework of\nthe particular game being played but are largely to do with the stability of the\npairings.\n\nIn ``matching``, we deal with three types of matching game:\n\n- the stable marriage problem (SM);\n- the hospital-resident assignment problem (HR);\n- the student-allocation problem (SA).\n\n\nUsing the `Player` class\n------------------------\n\nWith all of these games, ``matching`` uses a ``Player`` class to represent the\nmembers of the \"applying\" party, i.e. residents and students. For HR and SA,\nthere are specific classes to represent the roles of ``Hospital``, ``Project``\nand ``Supervisor``.\n\nFor instances of SM, we require two lists of ``Player`` instances -- one for\neach party detailing their preferences.\n\nConsider the following problem which is represented on a bipartite graph.\n\n.. image:: ./img/stable_marriage.png\n :align: center\n :width: 10cm\n\nWe construct the players in this game in the following way:\n\n>>> from matching import Player\n\n>>> suitors = [Player(name=\"A\"), Player(name=\"B\"), Player(name=\"C\")]\n>>> reviewers = [Player(name=\"D\"), Player(name=\"E\"), Player(name=\"F\")]\n>>> (A, B, C), (D, E, F) = suitors, reviewers\n\n>>> A.set_prefs([D, E, F])\n>>> B.set_prefs([D, F, E])\n>>> C.set_prefs([F, D, E])\n\n>>> D.set_prefs([B, C, A])\n>>> E.set_prefs([A, C, B])\n>>> F.set_prefs([C, B, A])\n\nThen to solve this matching game, we make use of the ``StableMarriage`` class,\nlike so:\n\n>>> from matching.games import StableMarriage\n>>> game = StableMarriage(suitors, reviewers)\n>>> game.solve()\n{A: E, B: D, C: F}\n\n\nNote\n++++\n\nThis matching is not a standard Python dictionary, though it does largely look\nand behave like one. It is in fact an instance of the ``Matching`` class:\n\n>>> matching = game.matching\n>>> type(matching)\nmatching.matching.Matching\n\nThis dictionary-like object is primarily useful as a teaching device that eases\nthe process of manipulating a matching after a solution has been found. \n\n\nUsing dictionaries\n------------------\n\nFor larger game instances, creating players directly (as above) could be\nunreasonably tedious. An alternative approach is to create an instance of a game\nfrom Python dictionaries. For example, consider the following instance of HR:\n\nThere are five residents -- Ada, Sam, Jo, Luc, Dani -- applying to work at three\nhospitals: Mercy, City, General. Each hospital has two available positions, and\nthe players' preferences of one another are as follows:\n\n.. image:: ./img/hospital_resident.png\n :align: center\n :width: 10cm\n\nThis information can be conveyed as a few dictionaries like so:\n\n>>> resident_prefs = {\n... \"A\": [\"C\"],\n... \"S\": [\"C\", \"M\"],\n... \"D\": [\"C\", \"M\", \"G\"],\n... \"J\": [\"C\", \"G\", \"M\"],\n... \"L\": [\"M\", \"C\", \"G\"],\n... }\n>>> hospital_prefs = {\n... \"M\": [\"D\", \"J\"],\n... \"C\": [\"D\", \"A\", \"S\", \"L\", \"J\"],\n... \"G\": [\"D\", \"A\", \"J\", \"L\"],\n... }\n>>> capacities = {hosp: 2 for hosp in hospital_prefs}\n\nThen, similarly, this game is solved using the ``HospitalResident`` class but an\ninstance is created using the ``create_from_dictionaries`` class method:\n\n>>> game = HospitalResident.create_from_dictionaries(\n... resident_prefs, hospital_prefs, capacities\n... )\n>>> game.solve()\n{M: [L, S], C: [D, A], G[J]}\n\nNote\n++++\n\nDespite passing dictionaries of strings here, the matching displays instances of\n``matching`` players:\n\n>>> matching = game.matching\n>>> for hospital in matching:\n... print(type(hospital))\n\n\n\n\nThis is because ``create_from_dictionaries`` creates instances of the appropriate\nplayer classes first and passes them to the game class. Using dictionaries like\nthis can be an efficient way of creating large games but it does require the\nnames of the players in each party to be unique.\n\n\nGet in contact!\n---------------\n\nI hope this package is useful, and feel free to contact me here (or on Twitter:\n`@daffidwilde `_) with any issues or\nrecommendations. PRs always welcome!", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/daffidwilde/matching", "keywords": "game-theory gale-shapley matching-games", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "matching", "package_url": "https://pypi.org/project/matching/", "platform": "", "project_url": "https://pypi.org/project/matching/", "project_urls": { "Homepage": "https://github.com/daffidwilde/matching" }, "release_url": "https://pypi.org/project/matching/1.1/", "requires_dist": null, "requires_python": "", "summary": "A package for solving matching games.", "version": "1.1" }, "last_serial": 5252546, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "4651fa14ca0f0b5e08aca5a8e697dfeb", "sha256": "2aae2fa6520272976dacc1e03a2340af977c32dfcf0afaf712ee211ca2ad57f2" }, "downloads": -1, "filename": "matching-0.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "4651fa14ca0f0b5e08aca5a8e697dfeb", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 9289, "upload_time": "2018-03-22T15:28:33", "url": "https://files.pythonhosted.org/packages/82/95/5a929964fe303efeddb78065fe4a3c0d005f6ab593ba408555fb31c41cec/matching-0.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "73e0757f6fe8873a67fb036473c6c00b", "sha256": "96894d7831d61ce7953b50227a9355c5fb50a5251f8333060434be2bc1f2352c" }, "downloads": -1, "filename": "matching-0.1.tar.gz", "has_sig": false, "md5_digest": "73e0757f6fe8873a67fb036473c6c00b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5686, "upload_time": "2018-03-22T15:28:35", "url": "https://files.pythonhosted.org/packages/7a/3e/178ddea8e23d3658a98714bebce900bb8886b41c0ec7d90efe4a4e70ed08/matching-0.1.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "84db39dfea5377f16414135c8a06a4b9", "sha256": "d6b5315d4df4c808132b3b548d6ec150df0a5b496bd7b34fd4f8752847ed4b01" }, "downloads": -1, "filename": "matching-0.1.1.tar.gz", "has_sig": false, "md5_digest": "84db39dfea5377f16414135c8a06a4b9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5888, "upload_time": "2018-08-24T16:23:42", "url": "https://files.pythonhosted.org/packages/2c/97/1175e7250ad3d10cce415c4b63f6672a625e282f6d86a7e20d09f8926329/matching-0.1.1.tar.gz" } ], "1.0": [ { "comment_text": "", "digests": { "md5": "fc569464257bbe9c9e27650165bbc21e", "sha256": "2660322245ed99f0d9bf78b971a53cb948b7dbef0a0cddd85e738413f6e4f0bc" }, "downloads": -1, "filename": "matching-1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "fc569464257bbe9c9e27650165bbc21e", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 13640, "upload_time": "2019-01-22T11:04:25", "url": "https://files.pythonhosted.org/packages/d9/ed/e89608a0736ba38a8ae72b420eeaf10a436f1649e623128199b7dbdac5fe/matching-1.0-py2.py3-none-any.whl" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "ab6875f85566ac6b0cb1f54f15572f6b", "sha256": "b005cfbf85734af87dbc8b3eb771eec34246c7c6bcf3882f05d8974a49052d2e" }, "downloads": -1, "filename": "matching-1.0.1.tar.gz", "has_sig": false, "md5_digest": "ab6875f85566ac6b0cb1f54f15572f6b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13782, "upload_time": "2019-01-28T10:36:23", "url": "https://files.pythonhosted.org/packages/03/14/e954ae797d06ffd8c183cac38dd1abf06be33160f8e77ac3acbff5f43f2f/matching-1.0.1.tar.gz" } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "6344149420242b9a364cca3997b514be", "sha256": "fec8aa1bca1df77630db8670f75179df6868d2c9a84e2cd7e31d91093358eee9" }, "downloads": -1, "filename": "matching-1.0.2.tar.gz", "has_sig": false, "md5_digest": "6344149420242b9a364cca3997b514be", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13790, "upload_time": "2019-01-30T09:57:35", "url": "https://files.pythonhosted.org/packages/28/38/70032ee3335cae714d747d6a4e1b176635ce9eeb6f1fe789be033813caed/matching-1.0.2.tar.gz" } ], "1.1": [ { "comment_text": "", "digests": { "md5": "9e2567ad709f5eb3ce2f5d87a2f95a3b", "sha256": "4912192ce96b8b525b2d0096a1651f69b983f399295121a8e223aef846c85f56" }, "downloads": -1, "filename": "matching-1.1.tar.gz", "has_sig": false, "md5_digest": "9e2567ad709f5eb3ce2f5d87a2f95a3b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15859, "upload_time": "2019-05-10T14:36:34", "url": "https://files.pythonhosted.org/packages/87/d7/03f697a7ea55448e6c66a767e8c609519352fea02df8181d2eaa32d41fa4/matching-1.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "9e2567ad709f5eb3ce2f5d87a2f95a3b", "sha256": "4912192ce96b8b525b2d0096a1651f69b983f399295121a8e223aef846c85f56" }, "downloads": -1, "filename": "matching-1.1.tar.gz", "has_sig": false, "md5_digest": "9e2567ad709f5eb3ce2f5d87a2f95a3b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 15859, "upload_time": "2019-05-10T14:36:34", "url": "https://files.pythonhosted.org/packages/87/d7/03f697a7ea55448e6c66a767e8c609519352fea02df8181d2eaa32d41fa4/matching-1.1.tar.gz" } ] }