diff --git a/benchmark/draw.ipynb b/benchmark/draw.ipynb index 03d768d..9fbe29b 100644 --- a/benchmark/draw.ipynb +++ b/benchmark/draw.ipynb @@ -156,8 +156,8 @@ "Requirement already satisfied: arrow>=0.15.0 in /opt/conda/lib/python3.10/site-packages (from isoduration->jsonschema>=2.6->nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets) (1.2.3)\r\n", "Downloading rbo-0.1.3-py3-none-any.whl (7.8 kB)\r\n", "Downloading openskill-6.0.0-py3-none-any.whl (50 kB)\r\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m50.9/50.9 kB\u001b[0m \u001b[31m1.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\r\n", - "\u001b[?25hInstalling collected packages: rbo, openskill\r\n", + "\u001B[2K \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m50.9/50.9 kB\u001B[0m \u001B[31m1.9 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\r\n", + "\u001B[?25hInstalling collected packages: rbo, openskill\r\n", "Successfully installed openskill-6.0.0 rbo-0.1.3\r\n", "Note: you may need to restart the kernel to use updated packages.\n" ] @@ -210,14 +210,17 @@ "source": [ "import gc\n", "from dataclasses import dataclass\n", + "from enum import Enum\n", + "from pathlib import Path\n", "from typing import Dict, List\n", "\n", "import ipywidgets as widgets\n", - "import numpy as np\n", "import pandas as pd\n", "import rich\n", + "from pooch import DOIDownloader\n", "from rbo import rbo\n", "from rich.table import Table\n", + "from sklearn.model_selection import train_test_split\n", "from tqdm.notebook import tqdm\n", "\n", "import openskill\n", @@ -227,12 +230,7 @@ " PlackettLuce,\n", " ThurstoneMostellerFull,\n", " ThurstoneMostellerPart,\n", - ")\n", - "\n", - "from pooch import DOIDownloader\n", - "from pathlib import Path\n", - "from sklearn.model_selection import train_test_split\n", - "from enum import Enum" + ")" ] }, { @@ -1139,12 +1137,12 @@ "\n" ], "text/plain": [ - "\u001b[3m Benchmark Results \u001b[0m\n", + "\u001B[3m Benchmark Results \u001B[0m\n", "┏━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓\n", - "┃\u001b[1m \u001b[0m\u001b[1m Information\u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mValue \u001b[0m\u001b[1m \u001b[0m┃\n", + "┃\u001B[1m \u001B[0m\u001B[1m Information\u001B[0m\u001B[1m \u001B[0m┃\u001B[1m \u001B[0m\u001B[1mValue \u001B[0m\u001B[1m \u001B[0m┃\n", "┡━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩\n", - "│\u001b[36m \u001b[0m\u001b[36m Available Matches\u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m20064 \u001b[0m\u001b[35m \u001b[0m│\n", - "│\u001b[36m \u001b[0m\u001b[36mPlackettLuce Accuracy\u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m19335/729 [ 96.37%]\u001b[0m\u001b[35m \u001b[0m│\n", + "│\u001B[36m \u001B[0m\u001B[36m Available Matches\u001B[0m\u001B[36m \u001B[0m│\u001B[35m \u001B[0m\u001B[35m20064 \u001B[0m\u001B[35m \u001B[0m│\n", + "│\u001B[36m \u001B[0m\u001B[36mPlackettLuce Accuracy\u001B[0m\u001B[36m \u001B[0m│\u001B[35m \u001B[0m\u001B[35m19335/729 [ 96.37%]\u001B[0m\u001B[35m \u001B[0m│\n", "└───────────────────────┴─────────────────────┘\n" ] }, diff --git a/benchmark/rank.ipynb b/benchmark/rank.ipynb index 70792fa..ffde1b9 100644 --- a/benchmark/rank.ipynb +++ b/benchmark/rank.ipynb @@ -54,8 +54,8 @@ "Requirement already satisfied: numpy in /opt/conda/lib/python3.10/site-packages (1.26.4)\r\n", "Collecting numpy\r\n", " Downloading numpy-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (60 kB)\r\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m60.9/60.9 kB\u001b[0m \u001b[31m1.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\r\n", - "\u001b[?25hRequirement already satisfied: tqdm in /opt/conda/lib/python3.10/site-packages (4.66.4)\r\n", + "\u001B[2K \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m60.9/60.9 kB\u001B[0m \u001B[31m1.9 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\r\n", + "\u001B[?25hRequirement already satisfied: tqdm in /opt/conda/lib/python3.10/site-packages (4.66.4)\r\n", "Requirement already satisfied: pooch in /opt/conda/lib/python3.10/site-packages (1.8.2)\r\n", "Requirement already satisfied: ipywidgets in /opt/conda/lib/python3.10/site-packages (7.7.1)\r\n", "Collecting ipywidgets\r\n", @@ -96,16 +96,16 @@ "Requirement already satisfied: six>=1.12.0 in /opt/conda/lib/python3.10/site-packages (from asttokens>=2.1.0->stack-data->ipython>=6.1.0->ipywidgets) (1.16.0)\r\n", "Downloading rbo-0.1.3-py3-none-any.whl (7.8 kB)\r\n", "Downloading rich-13.7.1-py3-none-any.whl (240 kB)\r\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m240.7/240.7 kB\u001b[0m \u001b[31m9.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\r\n", - "\u001b[?25hDownloading ipywidgets-8.1.3-py3-none-any.whl (139 kB)\r\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m139.4/139.4 kB\u001b[0m \u001b[31m6.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\r\n", - "\u001b[?25hDownloading openskill-6.0.0-py3-none-any.whl (50 kB)\r\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m50.9/50.9 kB\u001b[0m \u001b[31m2.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\r\n", - "\u001b[?25hDownloading jupyterlab_widgets-3.0.11-py3-none-any.whl (214 kB)\r\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m214.4/214.4 kB\u001b[0m \u001b[31m8.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\r\n", - "\u001b[?25hDownloading widgetsnbextension-4.0.11-py3-none-any.whl (2.3 MB)\r\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.3/2.3 MB\u001b[0m \u001b[31m42.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\r\n", - "\u001b[?25hInstalling collected packages: widgetsnbextension, rbo, openskill, jupyterlab-widgets, rich, ipywidgets\r\n", + "\u001B[2K \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m240.7/240.7 kB\u001B[0m \u001B[31m9.1 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\r\n", + "\u001B[?25hDownloading ipywidgets-8.1.3-py3-none-any.whl (139 kB)\r\n", + "\u001B[2K \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m139.4/139.4 kB\u001B[0m \u001B[31m6.3 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\r\n", + "\u001B[?25hDownloading openskill-6.0.0-py3-none-any.whl (50 kB)\r\n", + "\u001B[2K \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m50.9/50.9 kB\u001B[0m \u001B[31m2.2 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\r\n", + "\u001B[?25hDownloading jupyterlab_widgets-3.0.11-py3-none-any.whl (214 kB)\r\n", + "\u001B[2K \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m214.4/214.4 kB\u001B[0m \u001B[31m8.9 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\r\n", + "\u001B[?25hDownloading widgetsnbextension-4.0.11-py3-none-any.whl (2.3 MB)\r\n", + "\u001B[2K \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m2.3/2.3 MB\u001B[0m \u001B[31m42.2 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\r\n", + "\u001B[?25hInstalling collected packages: widgetsnbextension, rbo, openskill, jupyterlab-widgets, rich, ipywidgets\r\n", " Attempting uninstall: widgetsnbextension\r\n", " Found existing installation: widgetsnbextension 3.6.7\r\n", " Uninstalling widgetsnbextension-3.6.7:\r\n", @@ -122,10 +122,10 @@ " Found existing installation: ipywidgets 7.7.1\r\n", " Uninstalling ipywidgets-7.7.1:\r\n", " Successfully uninstalled ipywidgets-7.7.1\r\n", - "\u001b[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\r\n", + "\u001B[31mERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.\r\n", "tensorflow-decision-forests 1.8.1 requires wurlitzer, which is not installed.\r\n", - "tensorflow 2.15.0 requires keras<2.16,>=2.15.0, but you have keras 3.4.1 which is incompatible.\u001b[0m\u001b[31m\r\n", - "\u001b[0mSuccessfully installed ipywidgets-8.1.3 jupyterlab-widgets-3.0.11 openskill-6.0.0 rbo-0.1.3 rich-13.7.1 widgetsnbextension-4.0.11\r\n", + "tensorflow 2.15.0 requires keras<2.16,>=2.15.0, but you have keras 3.4.1 which is incompatible.\u001B[0m\u001B[31m\r\n", + "\u001B[0mSuccessfully installed ipywidgets-8.1.3 jupyterlab-widgets-3.0.11 openskill-6.0.0 rbo-0.1.3 rich-13.7.1 widgetsnbextension-4.0.11\r\n", "Note: you may need to restart the kernel to use updated packages.\n" ] } @@ -175,15 +175,17 @@ }, "outputs": [], "source": [ - "import time\n", "import gc\n", + "import time\n", "from dataclasses import dataclass\n", + "from pathlib import Path\n", "from typing import Dict\n", "\n", "import ipywidgets as widgets\n", "import numpy as np\n", "import polars as pl\n", "import rich\n", + "from pooch import DOIDownloader\n", "from rbo import rbo\n", "from rich.table import Table\n", "from tqdm.notebook import tqdm\n", @@ -195,10 +197,7 @@ " PlackettLuce,\n", " ThurstoneMostellerFull,\n", " ThurstoneMostellerPart,\n", - ")\n", - "\n", - "from pooch import DOIDownloader\n", - "from pathlib import Path" + ")" ] }, { @@ -1307,13 +1306,13 @@ "\n" ], "text/plain": [ - "\u001b[3m Benchmark Results \u001b[0m\n", + "\u001B[3m Benchmark Results \u001B[0m\n", "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓\n", - "┃\u001b[1m \u001b[0m\u001b[1m Information\u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mValue \u001b[0m\u001b[1m \u001b[0m┃\n", + "┃\u001B[1m \u001B[0m\u001B[1m Information\u001B[0m\u001B[1m \u001B[0m┃\u001B[1m \u001B[0m\u001B[1mValue \u001B[0m\u001B[1m \u001B[0m┃\n", "┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩\n", - "│\u001b[36m \u001b[0m\u001b[36m Available Matches\u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m145994 \u001b[0m\u001b[35m \u001b[0m│\n", - "│\u001b[36m \u001b[0m\u001b[36m PlackettLuce Accuracy\u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m134323/11671 [ 92.01%]\u001b[0m\u001b[35m \u001b[0m│\n", - "│\u001b[36m \u001b[0m\u001b[36m Rank-Biased Overlap Score:\u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m 64.46 \u001b[0m\u001b[35m \u001b[0m│\n", + "│\u001B[36m \u001B[0m\u001B[36m Available Matches\u001B[0m\u001B[36m \u001B[0m│\u001B[35m \u001B[0m\u001B[35m145994 \u001B[0m\u001B[35m \u001B[0m│\n", + "│\u001B[36m \u001B[0m\u001B[36m PlackettLuce Accuracy\u001B[0m\u001B[36m \u001B[0m│\u001B[35m \u001B[0m\u001B[35m134323/11671 [ 92.01%]\u001B[0m\u001B[35m \u001B[0m│\n", + "│\u001B[36m \u001B[0m\u001B[36m Rank-Biased Overlap Score:\u001B[0m\u001B[36m \u001B[0m│\u001B[35m \u001B[0m\u001B[35m 64.46 \u001B[0m\u001B[35m \u001B[0m│\n", "└─────────────────────────────┴────────────────────────┘\n" ] }, @@ -1624,13 +1623,13 @@ "description": "", "description_allow_html": false, "layout": "IPY_MODEL_0d1a94edd9e4441f800b85c272cd4174", - "max": 51704546.0, + "max": 5.1704546E7, "min": 0.0, "orientation": "horizontal", "style": "IPY_MODEL_c05b6b0fe0b14f8dba8c8532d5becad1", "tabbable": null, "tooltip": null, - "value": 51704546.0 + "value": 5.1704546E7 } }, "1fa24287923243499d42735aa608dff0": { @@ -2076,13 +2075,13 @@ "description": "", "description_allow_html": false, "layout": "IPY_MODEL_5f83e32b011b4503b1e67a736ec1153f", - "max": 11487236.0, + "max": 1.1487236E7, "min": 0.0, "orientation": "horizontal", "style": "IPY_MODEL_e87634fce8704dd3824c2a8685c5fd3b", "tabbable": null, "tooltip": null, - "value": 11487236.0 + "value": 1.1487236E7 } }, "6eb3fa3d7ca84770ab2d24b2f6a694f0": { @@ -2666,13 +2665,13 @@ "description": "", "description_allow_html": false, "layout": "IPY_MODEL_f2d82cacecc9493295741ae970381eea", - "max": 51704546.0, + "max": 5.1704546E7, "min": 0.0, "orientation": "horizontal", "style": "IPY_MODEL_651e7062e6e94d4495ccd2f06cb05c2a", "tabbable": null, "tooltip": null, - "value": 51703476.0 + "value": 5.1703476E7 } }, "bdfb5a775ba04c458828718e6926edc7": { diff --git a/benchmark/win.ipynb b/benchmark/win.ipynb index f30cf03..c65f66c 100644 --- a/benchmark/win.ipynb +++ b/benchmark/win.ipynb @@ -154,8 +154,8 @@ "Downloading rbo-0.1.3-py3-none-any.whl (7.8 kB)\r\n", "Downloading jsonlines-4.0.0-py3-none-any.whl (8.7 kB)\r\n", "Downloading openskill-6.0.0-py3-none-any.whl (50 kB)\r\n", - "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m50.9/50.9 kB\u001b[0m \u001b[31m3.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\r\n", - "\u001b[?25hInstalling collected packages: rbo, openskill, jsonlines\r\n", + "\u001B[2K \u001B[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001B[0m \u001B[32m50.9/50.9 kB\u001B[0m \u001B[31m3.3 MB/s\u001B[0m eta \u001B[36m0:00:00\u001B[0m\r\n", + "\u001B[?25hInstalling collected packages: rbo, openskill, jsonlines\r\n", "Successfully installed jsonlines-4.0.0 openskill-6.0.0 rbo-0.1.3\r\n", "Note: you may need to restart the kernel to use updated packages.\n" ] @@ -207,22 +207,21 @@ "outputs": [], "source": [ "import gc\n", - "from dataclasses import dataclass\n", - "from typing import Dict, List\n", - "\n", - "import ipywidgets as widgets\n", "import itertools\n", "import math\n", - "import numpy as np\n", + "import time\n", + "from pathlib import Path\n", + "\n", + "import ipywidgets as widgets\n", "import jsonlines\n", "import rich\n", - "import time\n", - "from trueskill import TrueSkill\n", "import trueskill\n", - "\n", + "from pooch import DOIDownloader\n", "from rbo import rbo\n", "from rich.table import Table\n", + "from sklearn.model_selection import train_test_split\n", "from tqdm.notebook import tqdm\n", + "from trueskill import TrueSkill\n", "\n", "import openskill\n", "from openskill.models import (\n", @@ -231,11 +230,7 @@ " PlackettLuce,\n", " ThurstoneMostellerFull,\n", " ThurstoneMostellerPart,\n", - ")\n", - "\n", - "from pooch import DOIDownloader\n", - "from pathlib import Path\n", - "from sklearn.model_selection import train_test_split" + ")" ] }, { @@ -1473,18 +1468,18 @@ "\n" ], "text/plain": [ - "\u001b[3m Benchmark Results \u001b[0m\n", + "\u001B[3m Benchmark Results \u001B[0m\n", "┏━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓\n", - "┃\u001b[1m \u001b[0m\u001b[1m Information\u001b[0m\u001b[1m \u001b[0m┃\u001b[1m \u001b[0m\u001b[1mValue \u001b[0m\u001b[1m \u001b[0m┃\n", + "┃\u001B[1m \u001B[0m\u001B[1m Information\u001B[0m\u001B[1m \u001B[0m┃\u001B[1m \u001B[0m\u001B[1mValue \u001B[0m\u001B[1m \u001B[0m┃\n", "┡━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩\n", - "│\u001b[36m \u001b[0m\u001b[36m Available Matches\u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m5661 \u001b[0m\u001b[35m \u001b[0m│\n", - "│\u001b[36m \u001b[0m\u001b[36m Valid Matches\u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m635 \u001b[0m\u001b[35m \u001b[0m│\n", - "│\u001b[36m \u001b[0m\u001b[36mPlackettLuce Accuracy\u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m556/79 [ 87.56%] \u001b[0m\u001b[35m \u001b[0m│\n", - "│\u001b[36m \u001b[0m\u001b[36m OpenSkill Duration\u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m1.6120915412902832\u001b[0m\u001b[35m \u001b[0m│\n", - "│\u001b[36m \u001b[0m\u001b[36m TrueSkill Accuracy\u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m587/48 [ 92.44%] \u001b[0m\u001b[35m \u001b[0m│\n", - "│\u001b[36m \u001b[0m\u001b[36m TrueSkill Duration\u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m4.9943461418151855\u001b[0m\u001b[35m \u001b[0m│\n", - "│\u001b[36m \u001b[0m\u001b[36m Speedup (%)\u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m 309.81 \u001b[0m\u001b[35m \u001b[0m│\n", - "│\u001b[36m \u001b[0m\u001b[36m Accuracy Bump (%)\u001b[0m\u001b[36m \u001b[0m│\u001b[35m \u001b[0m\u001b[35m-5.28 \u001b[0m\u001b[35m \u001b[0m│\n", + "│\u001B[36m \u001B[0m\u001B[36m Available Matches\u001B[0m\u001B[36m \u001B[0m│\u001B[35m \u001B[0m\u001B[35m5661 \u001B[0m\u001B[35m \u001B[0m│\n", + "│\u001B[36m \u001B[0m\u001B[36m Valid Matches\u001B[0m\u001B[36m \u001B[0m│\u001B[35m \u001B[0m\u001B[35m635 \u001B[0m\u001B[35m \u001B[0m│\n", + "│\u001B[36m \u001B[0m\u001B[36mPlackettLuce Accuracy\u001B[0m\u001B[36m \u001B[0m│\u001B[35m \u001B[0m\u001B[35m556/79 [ 87.56%] \u001B[0m\u001B[35m \u001B[0m│\n", + "│\u001B[36m \u001B[0m\u001B[36m OpenSkill Duration\u001B[0m\u001B[36m \u001B[0m│\u001B[35m \u001B[0m\u001B[35m1.6120915412902832\u001B[0m\u001B[35m \u001B[0m│\n", + "│\u001B[36m \u001B[0m\u001B[36m TrueSkill Accuracy\u001B[0m\u001B[36m \u001B[0m│\u001B[35m \u001B[0m\u001B[35m587/48 [ 92.44%] \u001B[0m\u001B[35m \u001B[0m│\n", + "│\u001B[36m \u001B[0m\u001B[36m TrueSkill Duration\u001B[0m\u001B[36m \u001B[0m│\u001B[35m \u001B[0m\u001B[35m4.9943461418151855\u001B[0m\u001B[35m \u001B[0m│\n", + "│\u001B[36m \u001B[0m\u001B[36m Speedup (%)\u001B[0m\u001B[36m \u001B[0m│\u001B[35m \u001B[0m\u001B[35m 309.81 \u001B[0m\u001B[35m \u001B[0m│\n", + "│\u001B[36m \u001B[0m\u001B[36m Accuracy Bump (%)\u001B[0m\u001B[36m \u001B[0m│\u001B[35m \u001B[0m\u001B[35m-5.28 \u001B[0m\u001B[35m \u001B[0m│\n", "└───────────────────────┴────────────────────┘\n" ] }, diff --git a/changes/166.bugfix.rst b/changes/166.bugfix.rst new file mode 100644 index 0000000..f07ebcb --- /dev/null +++ b/changes/166.bugfix.rst @@ -0,0 +1 @@ +Fix ties not being respected in scores diff --git a/docs/source/ordinal.ipynb b/docs/source/ordinal.ipynb index dcb690e..f526c97 100644 --- a/docs/source/ordinal.ipynb +++ b/docs/source/ordinal.ipynb @@ -43,9 +43,10 @@ "\n", "# Import openskill.py and plotting libraries.\n", "import matplotlib.pyplot as plt\n", - "import pandas as pd\n", "import numpy as np\n", + "import pandas as pd\n", "from scipy.stats import norm\n", + "\n", "from openskill.models import PlackettLuce\n", "\n", "# Initialize Default/Starter Rating\n", diff --git a/openskill/models/weng_lin/bradley_terry_full.py b/openskill/models/weng_lin/bradley_terry_full.py index 3393b2d..d190ca7 100644 --- a/openskill/models/weng_lin/bradley_terry_full.py +++ b/openskill/models/weng_lin/bradley_terry_full.py @@ -607,7 +607,8 @@ def rate( # Convert Score to Ranks if not ranks and scores: - ranks = [float(r) for r in self._calculate_rankings(teams, scores)] + ranks = [-s for s in scores] + ranks = self._calculate_rankings(teams, ranks) # Normalize Weights if weights: @@ -770,10 +771,19 @@ def _compute( if q == i: continue + margin_factor = 1.0 + if scores and i in score_mapping and q in score_mapping and i != q: + score_diff = abs(score_mapping[i] - score_mapping[q]) + if score_diff > 0 and team_q.rank < team_i.rank: + if score_diff > self.margin and self.margin > 0.0: + margin_factor = math.log1p(score_diff / self.margin) + c_iq = math.sqrt( team_i.sigma_squared + team_q.sigma_squared + (2 * beta**2) ) - piq = 1 / (1 + math.exp((team_q.mu - team_i.mu) / c_iq)) + piq = 1 / ( + 1 + math.exp(((team_q.mu - team_i.mu) * margin_factor) / c_iq) + ) sigma_squared_to_ciq = team_i.sigma_squared / c_iq s = 0.0 @@ -782,14 +792,7 @@ def _compute( elif team_q.rank == team_i.rank: s = 0.5 - margin_factor = 1.0 - if scores and i in score_mapping and q in score_mapping and i != q: - score_diff = score_mapping[i] - score_mapping[q] - if score_diff > 0 and team_q.rank < team_i.rank: - if score_diff > self.margin and self.margin > 0.0: - margin_factor = 1.0 + math.log1p(score_diff) - - omega += sigma_squared_to_ciq * (s - piq) * margin_factor + omega += sigma_squared_to_ciq * (s - piq) if weights: gamma_value = self.gamma( c_iq, @@ -810,12 +813,7 @@ def _compute( team_i.rank, None, ) - delta += ( - ((gamma_value * sigma_squared_to_ciq) / c_iq) - * piq - * (1 - piq) - * margin_factor - ) + delta += ((gamma_value * sigma_squared_to_ciq) / c_iq) * piq * (1 - piq) intermediate_result_per_team = [] for j, j_players in enumerate(team_i.team): @@ -1044,7 +1042,7 @@ def _calculate_team_ratings( sigma_squared_summed += (player.sigma * balance_weight) ** 2 result.append( BradleyTerryFullTeamRating( - mu_summed, sigma_squared_summed, team, rank[index] + mu_summed, sigma_squared_summed, team, int(rank[index]) ) ) return result @@ -1053,12 +1051,13 @@ def _calculate_rankings( self, game: Sequence[Sequence[BradleyTerryFullRating]], ranks: Optional[List[float]] = None, - ) -> List[int]: + ) -> List[float]: """ Calculates the rankings based on the scores or ranks of the teams. It assigns a rank to each team based on their score, with the team with - the highest score being ranked first. + the highest score being ranked first. Ties are broken by a team's prior + averaged :math:`mu` values. :param game: A list of teams, where teams are lists of :class:`BradleyTerryFullRating` objects. @@ -1067,21 +1066,39 @@ def _calculate_rankings( :return: A list of ranks for each team in the game. """ - if ranks: - team_scores = [] - for index, _ in enumerate(game): - if isinstance(ranks[index], int): - team_scores.append(ranks[index]) - else: - team_scores.append(index) - else: - team_scores = [i for i, _ in enumerate(game)] - - rank_output = {} - s = 0 - for index, value in enumerate(team_scores): - if index > 0: - if team_scores[index - 1] < team_scores[index]: - s = index - rank_output[index] = s - return list(rank_output.values()) + if not game: + return [] + + if ranks is None: + return list(range(len(game))) + + team_data = [] + for index, rank in enumerate(ranks): + team = game[index] + average_ordinal = sum(player.ordinal() for player in team) / len(team) + team_data.append((rank, average_ordinal, index)) + + # Lower Ranks (Better), Higher Skill (Breaks Ties) + team_data.sort(key=lambda data: (data[0], -data[1])) # Rank, -(Average Skill) + + # Assign Final Ranks: Preserve Ranks for Identical Skill + final_ranks = [0.0] * len(game) + current_rank = 0 + + for team_index, ( + original_rank, + average_ordinal, + original_team_index, + ) in enumerate(team_data): + if team_index > 0: + preceding_original_rank, preceding_average_ordinal, _ = team_data[ + team_index - 1 + ] + # Advance Rank: Performance Changes OR Rank Changes + if ( + original_rank != preceding_original_rank + or average_ordinal != preceding_average_ordinal + ): + current_rank = original_team_index + final_ranks[original_team_index] = float(current_rank) + return final_ranks diff --git a/openskill/models/weng_lin/bradley_terry_part.py b/openskill/models/weng_lin/bradley_terry_part.py index 1fdc3b2..71cb1ae 100644 --- a/openskill/models/weng_lin/bradley_terry_part.py +++ b/openskill/models/weng_lin/bradley_terry_part.py @@ -617,7 +617,8 @@ def rate( # Convert Score to Ranks if not ranks and scores: - ranks = [float(r) for r in self._calculate_rankings(teams, scores)] + ranks = [-s for s in scores] + ranks = self._calculate_rankings(teams, ranks) # Normalize Weights if weights: @@ -780,10 +781,20 @@ def _compute( continue team_q = team_ratings[q] + + margin_factor = 1.0 + if scores and i in score_mapping and q in score_mapping and i != q: + score_diff = abs(score_mapping[i] - score_mapping[q]) + if score_diff > 0 and team_q.rank < team_i.rank: + if score_diff > self.margin and self.margin > 0.0: + margin_factor = math.log1p(score_diff / self.margin) + c_iq = math.sqrt( team_i.sigma_squared + team_q.sigma_squared + (2 * beta**2) ) - p_iq = 1 / (1 + math.exp((team_q.mu - team_i.mu) / c_iq)) + p_iq = 1 / ( + 1 + math.exp(((team_q.mu - team_i.mu) * margin_factor) / c_iq) + ) sigma_to_ciq = team_i.sigma_squared / c_iq s = 0.0 @@ -792,14 +803,7 @@ def _compute( elif team_q.rank == team_i.rank: s = 0.5 - margin_factor = 1.0 - if scores and i in score_mapping and q in score_mapping and i != q: - score_diff = score_mapping[i] - score_mapping[q] - if score_diff > 0 and team_q.rank < team_i.rank: - if score_diff > self.margin and self.margin > 0.0: - margin_factor = 1.0 + math.log1p(score_diff) - - omega_sum += (sigma_to_ciq * (s - p_iq)) * margin_factor + omega_sum += sigma_to_ciq * (s - p_iq) current_weights = weights[i] if weights else None gamma_value = self.gamma( c_iq, @@ -810,9 +814,7 @@ def _compute( team_i.rank, current_weights, ) - delta_sum += ( - (gamma_value * sigma_to_ciq / c_iq) * p_iq * (1 - p_iq) - ) * margin_factor + delta_sum += (gamma_value * sigma_to_ciq / c_iq) * p_iq * (1 - p_iq) comparisons += 1 if comparisons > 0: @@ -1036,7 +1038,7 @@ def _calculate_team_ratings( sigma_squared_summed += (player.sigma * balance_weight) ** 2 result.append( BradleyTerryPartTeamRating( - mu_summed, sigma_squared_summed, team, rank[index] + mu_summed, sigma_squared_summed, team, int(rank[index]) ) ) return result @@ -1045,12 +1047,13 @@ def _calculate_rankings( self, game: Sequence[Sequence[BradleyTerryPartRating]], ranks: Optional[List[float]] = None, - ) -> List[int]: + ) -> List[float]: """ Calculates the rankings based on the scores or ranks of the teams. It assigns a rank to each team based on their score, with the team with - the highest score being ranked first. + the highest score being ranked first. Ties are broken by a team's prior + averaged :math:`mu` values. :param game: A list of teams, where teams are lists of :class:`BradleyTerryPartRating` objects. @@ -1059,21 +1062,39 @@ def _calculate_rankings( :return: A list of ranks for each team in the game. """ - if ranks: - team_scores = [] - for index, _ in enumerate(game): - if isinstance(ranks[index], int): - team_scores.append(ranks[index]) - else: - team_scores.append(index) - else: - team_scores = [i for i, _ in enumerate(game)] - - rank_output = {} - s = 0 - for index, value in enumerate(team_scores): - if index > 0: - if team_scores[index - 1] < team_scores[index]: - s = index - rank_output[index] = s - return list(rank_output.values()) + if not game: + return [] + + if ranks is None: + return list(range(len(game))) + + team_data = [] + for index, rank in enumerate(ranks): + team = game[index] + average_ordinal = sum(player.ordinal() for player in team) / len(team) + team_data.append((rank, average_ordinal, index)) + + # Lower Ranks (Better), Higher Skill (Breaks Ties) + team_data.sort(key=lambda data: (data[0], -data[1])) # Rank, -(Average Skill) + + # Assign Final Ranks: Preserve Ranks for Identical Skill + final_ranks = [0.0] * len(game) + current_rank = 0 + + for team_index, ( + original_rank, + average_ordinal, + original_team_index, + ) in enumerate(team_data): + if team_index > 0: + preceding_original_rank, preceding_average_ordinal, _ = team_data[ + team_index - 1 + ] + # Advance Rank: Performance Changes OR Rank Changes + if ( + original_rank != preceding_original_rank + or average_ordinal != preceding_average_ordinal + ): + current_rank = original_team_index + final_ranks[original_team_index] = float(current_rank) + return final_ranks diff --git a/openskill/models/weng_lin/plackett_luce.py b/openskill/models/weng_lin/plackett_luce.py index 2a15be5..70dad07 100644 --- a/openskill/models/weng_lin/plackett_luce.py +++ b/openskill/models/weng_lin/plackett_luce.py @@ -607,7 +607,8 @@ def rate( # Convert Score to Ranks if not ranks and scores: - ranks = [float(r) for r in self._calculate_rankings(teams, scores)] + ranks = [-s for s in scores] + ranks = self._calculate_rankings(teams, ranks) # Normalize Weights if weights: @@ -772,10 +773,10 @@ def _compute( for q, team_q in enumerate(team_ratings): margin_factor = 1.0 if scores and i in score_mapping and q in score_mapping and i != q: - score_diff = score_mapping[i] - score_mapping[q] + score_diff = abs(score_mapping[i] - score_mapping[q]) if score_diff > 0 and team_q.rank < team_i.rank: if score_diff > self.margin and self.margin > 0.0: - margin_factor = 1.0 + math.log1p(score_diff) + margin_factor = math.log1p(score_diff / self.margin) i_mu_over_ce_over_sum_q = i_mu_over_c / sum_q[q] if team_q.rank <= team_i.rank: @@ -1039,7 +1040,7 @@ def _calculate_team_ratings( sigma_squared_summed += (player.sigma * balance_weight) ** 2 result.append( PlackettLuceTeamRating( - mu_summed, sigma_squared_summed, team, rank[index] + mu_summed, sigma_squared_summed, team, int(rank[index]) ) ) return result @@ -1048,12 +1049,13 @@ def _calculate_rankings( self, game: Sequence[Sequence[PlackettLuceRating]], ranks: Optional[List[float]] = None, - ) -> List[int]: + ) -> List[float]: """ Calculates the rankings based on the scores or ranks of the teams. It assigns a rank to each team based on their score, with the team with - the highest score being ranked first. + the highest score being ranked first. Ties are broken by a team's prior + averaged :math:`mu` values. :param game: A list of teams, where teams are lists of :class:`PlackettLuceRating` objects. @@ -1062,21 +1064,39 @@ def _calculate_rankings( :return: A list of ranks for each team in the game. """ - if ranks: - team_scores = [] - for index, _ in enumerate(game): - if isinstance(ranks[index], int): - team_scores.append(ranks[index]) - else: - team_scores.append(index) - else: - team_scores = [i for i, _ in enumerate(game)] - - rank_output = {} - s = 0 - for index, value in enumerate(team_scores): - if index > 0: - if team_scores[index - 1] < team_scores[index]: - s = index - rank_output[index] = s - return list(rank_output.values()) + if not game: + return [] + + if ranks is None: + return list(range(len(game))) + + team_data = [] + for index, rank in enumerate(ranks): + team = game[index] + average_ordinal = sum(player.ordinal() for player in team) / len(team) + team_data.append((rank, average_ordinal, index)) + + # Lower Ranks (Better), Higher Skill (Breaks Ties) + team_data.sort(key=lambda data: (data[0], -data[1])) # Rank, -(Average Skill) + + # Assign Final Ranks: Preserve Ranks for Identical Skill + final_ranks = [0.0] * len(game) + current_rank = 0 + + for team_index, ( + original_rank, + average_ordinal, + original_team_index, + ) in enumerate(team_data): + if team_index > 0: + preceding_original_rank, preceding_average_ordinal, _ = team_data[ + team_index - 1 + ] + # Advance Rank: Performance Changes OR Rank Changes + if ( + original_rank != preceding_original_rank + or average_ordinal != preceding_average_ordinal + ): + current_rank = original_team_index + final_ranks[original_team_index] = float(current_rank) + return final_ranks diff --git a/openskill/models/weng_lin/thurstone_mosteller_full.py b/openskill/models/weng_lin/thurstone_mosteller_full.py index 4cb7257..146e6a8 100644 --- a/openskill/models/weng_lin/thurstone_mosteller_full.py +++ b/openskill/models/weng_lin/thurstone_mosteller_full.py @@ -628,7 +628,8 @@ def rate( # Convert Score to Ranks if not ranks and scores: - ranks = [float(r) for r in self._calculate_rankings(teams, scores)] + ranks = [-s for s in scores] + ranks = self._calculate_rankings(teams, ranks) # Normalize Weights if weights: @@ -821,10 +822,10 @@ def _compute( margin_factor = 1.0 if scores and i in score_mapping and q in score_mapping and i != q: - score_diff = score_mapping[i] - score_mapping[q] + score_diff = abs(score_mapping[i] - score_mapping[q]) if score_diff > 0 and team_q.rank < team_i.rank: if score_diff > self.margin and self.margin > 0.0: - margin_factor = 1.0 + math.log1p(score_diff) + margin_factor = math.log1p(score_diff / self.margin) if team_q.rank > team_i.rank: omega += sigma_squared_to_ciq * v( @@ -1088,7 +1089,7 @@ def _calculate_team_ratings( sigma_squared_summed += (player.sigma * balance_weight) ** 2 result.append( ThurstoneMostellerFullTeamRating( - mu_summed, sigma_squared_summed, team, rank[index] + mu_summed, sigma_squared_summed, team, int(rank[index]) ) ) return result @@ -1097,12 +1098,13 @@ def _calculate_rankings( self, game: Sequence[Sequence[ThurstoneMostellerFullRating]], ranks: Optional[List[float]] = None, - ) -> List[int]: + ) -> List[float]: """ Calculates the rankings based on the scores or ranks of the teams. It assigns a rank to each team based on their score, with the team with - the highest score being ranked first. + the highest score being ranked first. Ties are broken by a team's prior + averaged :math:`mu` values. :param game: A list of teams, where teams are lists of :class:`ThurstoneMostellerFullRating` objects. @@ -1111,21 +1113,39 @@ def _calculate_rankings( :return: A list of ranks for each team in the game. """ - if ranks: - team_scores = [] - for index, _ in enumerate(game): - if isinstance(ranks[index], int): - team_scores.append(ranks[index]) - else: - team_scores.append(index) - else: - team_scores = [i for i, _ in enumerate(game)] - - rank_output = {} - s = 0 - for index, value in enumerate(team_scores): - if index > 0: - if team_scores[index - 1] < team_scores[index]: - s = index - rank_output[index] = s - return list(rank_output.values()) + if not game: + return [] + + if ranks is None: + return list(range(len(game))) + + team_data = [] + for index, rank in enumerate(ranks): + team = game[index] + average_ordinal = sum(player.ordinal() for player in team) / len(team) + team_data.append((rank, average_ordinal, index)) + + # Lower Ranks (Better), Higher Skill (Breaks Ties) + team_data.sort(key=lambda data: (data[0], -data[1])) # Rank, -(Average Skill) + + # Assign Final Ranks: Preserve Ranks for Identical Skill + final_ranks = [0.0] * len(game) + current_rank = 0 + + for team_index, ( + original_rank, + average_ordinal, + original_team_index, + ) in enumerate(team_data): + if team_index > 0: + preceding_original_rank, preceding_average_ordinal, _ = team_data[ + team_index - 1 + ] + # Advance Rank: Performance Changes OR Rank Changes + if ( + original_rank != preceding_original_rank + or average_ordinal != preceding_average_ordinal + ): + current_rank = original_team_index + final_ranks[original_team_index] = float(current_rank) + return final_ranks diff --git a/openskill/models/weng_lin/thurstone_mosteller_part.py b/openskill/models/weng_lin/thurstone_mosteller_part.py index ec6c2e4..ad0861d 100644 --- a/openskill/models/weng_lin/thurstone_mosteller_part.py +++ b/openskill/models/weng_lin/thurstone_mosteller_part.py @@ -634,7 +634,8 @@ def rate( # Convert Score to Ranks if not ranks and scores: - ranks = [float(r) for r in self._calculate_rankings(teams, scores)] + ranks = [-s for s in scores] + ranks = self._calculate_rankings(teams, ranks) # Normalize Weights if weights: @@ -828,10 +829,10 @@ def _compute( margin_factor = 1.0 if scores and i in score_mapping and q in score_mapping and i != q: - score_diff = score_mapping[i] - score_mapping[q] + score_diff = abs(score_mapping[i] - score_mapping[q]) if score_diff > 0 and team_q.rank < team_i.rank: if score_diff > self.margin and self.margin > 0.0: - margin_factor = 1.0 + math.log1p(score_diff) + margin_factor = math.log1p(score_diff / self.margin) if team_q.rank > team_i.rank: omega_sum += sigma_sq_to_c_iq * v( @@ -1080,7 +1081,7 @@ def _calculate_team_ratings( sigma_squared_summed += (player.sigma * balance_weight) ** 2 result.append( ThurstoneMostellerPartTeamRating( - mu_summed, sigma_squared_summed, team, rank[index] + mu_summed, sigma_squared_summed, team, int(rank[index]) ) ) return result @@ -1089,12 +1090,13 @@ def _calculate_rankings( self, game: Sequence[Sequence[ThurstoneMostellerPartRating]], ranks: Optional[List[float]] = None, - ) -> List[int]: + ) -> List[float]: """ Calculates the rankings based on the scores or ranks of the teams. It assigns a rank to each team based on their score, with the team with - the highest score being ranked first. + the highest score being ranked first. Ties are broken by a team's prior + averaged :math:`mu` values. :param game: A list of teams, where teams are lists of :class:`ThurstoneMostellerPartRating` objects. @@ -1103,21 +1105,39 @@ def _calculate_rankings( :return: A list of ranks for each team in the game. """ - if ranks: - team_scores = [] - for index, _ in enumerate(game): - if isinstance(ranks[index], int): - team_scores.append(ranks[index]) - else: - team_scores.append(index) - else: - team_scores = [i for i, _ in enumerate(game)] - - rank_output = {} - s = 0 - for index, value in enumerate(team_scores): - if index > 0: - if team_scores[index - 1] < team_scores[index]: - s = index - rank_output[index] = s - return list(rank_output.values()) + if not game: + return [] + + if ranks is None: + return list(range(len(game))) + + team_data = [] + for index, rank in enumerate(ranks): + team = game[index] + average_ordinal = sum(player.ordinal() for player in team) / len(team) + team_data.append((rank, average_ordinal, index)) + + # Lower Ranks (Better), Higher Skill (Breaks Ties) + team_data.sort(key=lambda data: (data[0], -data[1])) # Rank, -(Average Skill) + + # Assign Final Ranks: Preserve Ranks for Identical Skill + final_ranks = [0.0] * len(game) + current_rank = 0 + + for team_index, ( + original_rank, + average_ordinal, + original_team_index, + ) in enumerate(team_data): + if team_index > 0: + preceding_original_rank, preceding_average_ordinal, _ = team_data[ + team_index - 1 + ] + # Advance Rank: Performance Changes OR Rank Changes + if ( + original_rank != preceding_original_rank + or average_ordinal != preceding_average_ordinal + ): + current_rank = original_team_index + final_ranks[original_team_index] = float(current_rank) + return final_ranks diff --git a/pyproject.toml b/pyproject.toml index c6a2425..a8be4ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,7 +53,7 @@ description = "Multiplayer Rating System. No Friction." readme = "README.md" requires-python = "~=3.10" keywords = ["ranking", "trueskill", "statistics", "rating", "math", "rank"] -license = "MIT" +license = {"text" = "MIT"} classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", @@ -106,7 +106,7 @@ build = [ "isort~=6.0", "mypy[mypyc]~=1.15", "black[jupyter]~=25.1", - "towncrier~=23.11", + "towncrier~=24.8", "bump-my-version~=1.1", ] benchmark = [ diff --git a/tests/models/data/bradleyterryfull.json b/tests/models/data/bradleyterryfull.json index 047ca0b..56518e5 100644 --- a/tests/models/data/bradleyterryfull.json +++ b/tests/models/data/bradleyterryfull.json @@ -1,229 +1,263 @@ { "model": { - "mu": 33.93520996667812, - "sigma": 9.863910103294474 + "mu": 45.50776542407209, + "sigma": 7.030475996313497 }, "normal": { "team_1": [ { - "mu": 38.60492430454205, - "sigma": 9.771557303944002 + "mu": 49.039598991691356, + "sigma": 7.014998905352588 } ], "team_2": [ { - "mu": 29.265495628814193, - "sigma": 9.73289909385935 + "mu": 41.975931856452824, + "sigma": 7.008372859217962 }, { - "mu": 29.265495628814193, - "sigma": 9.73289909385935 + "mu": 41.975931856452824, + "sigma": 7.008372859217962 } ] }, "ranks": { "team_1": [ { - "mu": 41.10340607203985, - "sigma": 9.324153823645602 + "mu": 51.05589486393953, + "sigma": 6.797347609461401 } ], "team_2": [ { - "mu": 37.72654974043671, - "sigma": 9.400642042862893 + "mu": 47.373355253002806, + "sigma": 6.861927936468345 }, { - "mu": 37.72654974043671, - "sigma": 9.400642042862893 + "mu": 47.373355253002806, + "sigma": 6.861927936468345 } ], "team_3": [ { - "mu": 29.29409518126862, - "sigma": 9.324153823645602 + "mu": 43.12482555907567, + "sigma": 6.797347609461401 } ], "team_4": [ { - "mu": 27.61678887296731, - "sigma": 9.400642042862893 + "mu": 40.47698602027036, + "sigma": 6.861927936468345 }, { - "mu": 27.61678887296731, - "sigma": 9.400642042862893 + "mu": 40.47698602027036, + "sigma": 6.861927936468345 } ] }, "scores": { "team_1": [ { - "mu": 38.60492430454205, - "sigma": 9.771557303944002 + "mu": 47.212574875757014, + "sigma": 7.014998905352588 } ], "team_2": [ { - "mu": 29.265495628814193, - "sigma": 9.73289909385935 + "mu": 43.80295597238717, + "sigma": 7.008372859217962 }, { - "mu": 29.265495628814193, - "sigma": 9.73289909385935 + "mu": 43.80295597238717, + "sigma": 7.008372859217962 } ] }, "margins": { "team_1": [ { - "mu": 38.60492430454205, - "sigma": 9.771557303944002 + "mu": 51.99240742579961, + "sigma": 6.525226804217515 + }, + { + "mu": 58.47704942752714, + "sigma": 5.9768413492222425 } ], "team_2": [ { - "mu": 22.791896974192728, - "sigma": 9.547802296711161 + "mu": 48.75008642493585, + "sigma": 5.9768413492222425 + }, + { + "mu": 47.128925924503974, + "sigma": 6.525226804217515 + } + ], + "team_3": [ + { + "mu": 47.128925924503974, + "sigma": 6.525226804217515 + }, + { + "mu": 48.75008642493585, + "sigma": 5.9768413492222425 + } + ], + "team_4": [ + { + "mu": 43.886604923640206, + "sigma": 6.782813650162572 + }, + { + "mu": 42.26544442320833, + "sigma": 6.525226804217515 + } + ], + "team_5": [ + { + "mu": 39.02312342234457, + "sigma": 6.525226804217515 }, { - "mu": 22.791896974192728, - "sigma": 9.547802296711161 + "mu": 42.26544442320833, + "sigma": 6.782813650162572 } ] }, "limit_sigma": { "team_1": [ { - "mu": 37.77813395646485, - "sigma": 9.752692687721002 + "mu": 48.61960741854648, + "sigma": 7.01412035576635 } ], "team_2": [ { - "mu": 38.12520496286507, - "sigma": 9.646741941115268 + "mu": 48.39070594250492, + "sigma": 6.986923403967418 }, { - "mu": 38.12520496286507, - "sigma": 9.646741941115268 + "mu": 48.39070594250492, + "sigma": 6.986923403967418 } ], "team_3": [ { - "mu": 25.90229098070445, - "sigma": 9.7273209243063 + "mu": 39.51298291116487, + "sigma": 7.003251473183846 }, { - "mu": 25.90229098070445, - "sigma": 9.7273209243063 + "mu": 39.51298291116487, + "sigma": 7.003251473183846 }, { - "mu": 25.90229098070445, - "sigma": 9.7273209243063 + "mu": 39.51298291116487, + "sigma": 7.003251473183846 } ] }, "ties": { "team_1": [ { - "mu": 40.79914153848189, - "sigma": 9.752692687721002 + "mu": 50.65249514998328, + "sigma": 7.01412035576635 } ], "team_2": [ { - "mu": 28.47931237854228, - "sigma": 9.646741941115268 + "mu": 41.792325182917814, + "sigma": 6.986923403967418 }, { - "mu": 28.47931237854228, - "sigma": 9.646741941115268 + "mu": 41.792325182917814, + "sigma": 6.986923403967418 } ], "team_3": [ { - "mu": 32.527175983010196, - "sigma": 9.7273209243063 + "mu": 44.078475939315176, + "sigma": 7.003251473183846 }, { - "mu": 32.527175983010196, - "sigma": 9.7273209243063 + "mu": 44.078475939315176, + "sigma": 7.003251473183846 }, { - "mu": 32.527175983010196, - "sigma": 9.7273209243063 + "mu": 44.078475939315176, + "sigma": 7.003251473183846 } ] }, "weights": { "team_1": [ { - "mu": 33.56851090112285, - "sigma": 9.69248609852505 + "mu": 44.898160010736625, + "sigma": 6.9606078457350495 }, { - "mu": 33.201811835567575, - "sigma": 9.517610339254462 + "mu": 44.28855459740116, + "sigma": 6.88952726861807 }, { - "mu": 33.201811835567575, - "sigma": 9.517610339254462 + "mu": 44.28855459740116, + "sigma": 6.88952726861807 } ], "team_2": [ { - "mu": 43.24969570892833, - "sigma": 9.496386988251478 + "mu": 52.6503776328708, + "sigma": 6.864413021823323 }, { - "mu": 52.56418145117854, - "sigma": 9.113674598697537 + "mu": 59.79298984166951, + "sigma": 6.693713101797125 } ], "team_3": [ { - "mu": 25.027439377411454, - "sigma": 9.517610339254462 + "mu": 38.628405361727786, + "sigma": 6.88952726861807 }, { - "mu": 25.027439377411454, - "sigma": 9.517610339254462 + "mu": 38.628405361727786, + "sigma": 6.88952726861807 }, { - "mu": 29.48132467204479, - "sigma": 9.69248609852505 + "mu": 42.06808539289994, + "sigma": 6.9606078457350495 } ], "team_4": [ { - "mu": 34.26189294480513, - "sigma": 9.496386988251478 + "mu": 46.46372410428861, + "sigma": 6.864413021823323 }, { - "mu": 34.588575922932144, - "sigma": 9.113674598697537 + "mu": 47.419682784505135, + "sigma": 6.693713101797125 } ] }, "balance": { "team_1": [ { - "mu": 36.29812772849557, - "sigma": 9.670612970033678 + "mu": 47.128925924503974, + "sigma": 6.9080061592335165 }, { - "mu": 36.29812772849557, - "sigma": 9.670612970033678 + "mu": 47.128925924503974, + "sigma": 6.9080061592335165 } ], "team_2": [ { - "mu": 31.57229220486067, - "sigma": 9.670612970033678 + "mu": 43.886604923640206, + "sigma": 6.9080061592335165 }, { - "mu": 31.57229220486067, - "sigma": 9.670612970033678 + "mu": 43.886604923640206, + "sigma": 6.9080061592335165 } ] } diff --git a/tests/models/data/bradleyterrypart.json b/tests/models/data/bradleyterrypart.json index d863a61..a0fa696 100644 --- a/tests/models/data/bradleyterrypart.json +++ b/tests/models/data/bradleyterrypart.json @@ -1,229 +1,263 @@ { "model": { - "mu": 27.33014457764121, - "sigma": 6.556703812160652 + "mu": 42.645712212108165, + "sigma": 10.505514170387926 }, "normal": { "team_1": [ { - "mu": 30.335575279647333, - "sigma": 6.515404123904633 + "mu": 47.85579742671254, + "sigma": 10.429233601920815 } ], "team_2": [ { - "mu": 24.324713875635084, - "sigma": 6.497999021941496 + "mu": 37.43562699750379, + "sigma": 10.397334918754632 }, { - "mu": 24.324713875635084, - "sigma": 6.497999021941496 + "mu": 37.43562699750379, + "sigma": 10.397334918754632 } ] }, "ranks": { "team_1": [ { - "mu": 28.86585115770157, - "sigma": 6.470787270697601 + "mu": 45.346504272238334, + "sigma": 10.329160443014173 } ], "team_2": [ { - "mu": 28.065261993380442, - "sigma": 6.480821418639879 + "mu": 43.86231078973398, + "sigma": 10.36384303116896 }, { - "mu": 28.065261993380442, - "sigma": 6.480821418639879 + "mu": 43.86231078973398, + "sigma": 10.36384303116896 } ], "team_3": [ { - "mu": 26.441223267560517, - "sigma": 6.470787270697601 + "mu": 41.12116599986879, + "sigma": 10.329160443014173 } ], "team_4": [ { - "mu": 25.94824189192231, - "sigma": 6.480821418639879 + "mu": 40.25286778659155, + "sigma": 10.36384303116896 }, { - "mu": 25.94824189192231, - "sigma": 6.480821418639879 + "mu": 40.25286778659155, + "sigma": 10.36384303116896 } ] }, "scores": { "team_1": [ { - "mu": 30.335575279647333, - "sigma": 6.515404123904633 + "mu": 44.97053020758836, + "sigma": 10.429233601920815 } ], "team_2": [ { - "mu": 24.324713875635084, - "sigma": 6.497999021941496 + "mu": 40.32089421662797, + "sigma": 10.397334918754632 }, { - "mu": 24.324713875635084, - "sigma": 6.497999021941496 + "mu": 40.32089421662797, + "sigma": 10.397334918754632 } ] }, "margins": { "team_1": [ { - "mu": 30.335575279647333, - "sigma": 6.515404123904633 + "mu": 45.174609497697624, + "sigma": 10.296532440517023 + }, + { + "mu": 47.70350678328708, + "sigma": 10.082875986967851 } ], "team_2": [ { - "mu": 20.1583022407074, - "sigma": 6.414978164960343 + "mu": 43.9101608549029, + "sigma": 10.082875986967851 + }, + { + "mu": 43.27793653350553, + "sigma": 10.296532440517023 + } + ], + "team_3": [ + { + "mu": 43.27793653350553, + "sigma": 10.296532440517023 + }, + { + "mu": 43.9101608549029, + "sigma": 10.082875986967851 + } + ], + "team_4": [ + { + "mu": 42.0134878907108, + "sigma": 10.401715068374191 + }, + { + "mu": 41.38126356931343, + "sigma": 10.296532440517023 + } + ], + "team_5": [ + { + "mu": 40.11681492651871, + "sigma": 10.296532440517023 }, { - "mu": 20.1583022407074, - "sigma": 6.414978164960343 + "mu": 41.38126356931343, + "sigma": 10.401715068374191 } ] }, "limit_sigma": { "team_1": [ { - "mu": 28.615272962564624, - "sigma": 6.5330180387148875 + "mu": 44.84462468636991, + "sigma": 10.461934003896628 } ], "team_2": [ { - "mu": 28.66318766033115, - "sigma": 6.506357225951255 + "mu": 44.87027895306455, + "sigma": 10.413516208610908 }, { - "mu": 28.66318766033115, - "sigma": 6.506357225951255 + "mu": 44.87027895306455, + "sigma": 10.413516208610908 } ], "team_3": [ { - "mu": 24.711973110027856, - "sigma": 6.525442292304767 + "mu": 38.222232996890035, + "sigma": 10.449425129618103 }, { - "mu": 24.711973110027856, - "sigma": 6.525442292304767 + "mu": 38.222232996890035, + "sigma": 10.449425129618103 }, { - "mu": 24.711973110027856, - "sigma": 6.525442292304767 + "mu": 38.222232996890035, + "sigma": 10.449425129618103 } ] }, "ties": { "team_1": [ { - "mu": 29.547849635992403, - "sigma": 6.5330180387148875 + "mu": 46.46544326269937, + "sigma": 10.461934003896628 } ], "team_2": [ { - "mu": 25.62247285676864, - "sigma": 6.506357225951255 + "mu": 39.70642230624498, + "sigma": 10.413516208610908 }, { - "mu": 25.62247285676864, - "sigma": 6.506357225951255 + "mu": 39.70642230624498, + "sigma": 10.413516208610908 } ], "team_3": [ { - "mu": 26.82011124016259, - "sigma": 6.525442292304767 + "mu": 41.765271067380155, + "sigma": 10.449425129618103 }, { - "mu": 26.82011124016259, - "sigma": 6.525442292304767 + "mu": 41.765271067380155, + "sigma": 10.449425129618103 }, { - "mu": 26.82011124016259, - "sigma": 6.525442292304767 + "mu": 41.765271067380155, + "sigma": 10.449425129618103 } ] }, "weights": { "team_1": [ { - "mu": 27.222719042103126, - "sigma": 6.5265340126552545 + "mu": 42.45741312385392, + "sigma": 10.450825235493314 }, { - "mu": 27.115293506565042, - "sigma": 6.49568957939381 + "mu": 42.26911403559967, + "sigma": 10.395514598949962 }, { - "mu": 27.115293506565042, - "sigma": 6.49568957939381 + "mu": 42.26911403559967, + "sigma": 10.395514598949962 } ], "team_2": [ { - "mu": 29.369286151603863, - "sigma": 6.491992786786046 + "mu": 46.081134146150504, + "sigma": 10.38548205880239 }, { - "mu": 31.408427725566515, - "sigma": 6.426089896859335 + "mu": 49.51655608019285, + "sigma": 10.263708041382838 } ], "team_3": [ { - "mu": 25.37057202727288, - "sigma": 6.49568957939381 + "mu": 39.35645766272188, + "sigma": 10.395514598949962 }, { - "mu": 25.37057202727288, - "sigma": 6.49568957939381 + "mu": 39.35645766272188, + "sigma": 10.395514598949962 }, { - "mu": 26.350358302457046, - "sigma": 6.5265340126552545 + "mu": 41.00108493741502, + "sigma": 10.450825235493314 } ], "team_4": [ { - "mu": 27.465426625123058, - "sigma": 6.491992786786046 + "mu": 42.87614300396061, + "sigma": 10.38548205880239 }, { - "mu": 27.600708672604906, - "sigma": 6.426089896859335 + "mu": 43.10657379581305, + "sigma": 10.263708041382838 } ] }, "balance": { "team_1": [ { - "mu": 28.825446896814153, - "sigma": 6.4463288934554805 + "mu": 45.174609497697624, + "sigma": 10.296532440517023 }, { - "mu": 28.825446896814153, - "sigma": 6.4463288934554805 + "mu": 45.174609497697624, + "sigma": 10.296532440517023 } ], "team_2": [ { - "mu": 25.834842258468267, - "sigma": 6.4463288934554805 + "mu": 40.11681492651871, + "sigma": 10.296532440517023 }, { - "mu": 25.834842258468267, - "sigma": 6.4463288934554805 + "mu": 40.11681492651871, + "sigma": 10.296532440517023 } ] } diff --git a/tests/models/data/plackettluce.json b/tests/models/data/plackettluce.json index 89a31b8..8143f49 100644 --- a/tests/models/data/plackettluce.json +++ b/tests/models/data/plackettluce.json @@ -1,229 +1,263 @@ { "model": { - "mu": 24.02471607940542, - "sigma": 4.028556121494977 + "mu": 30.9227929079249, + "sigma": 6.478417585666653 }, "normal": { "team_1": [ { - "mu": 25.682781474841377, - "sigma": 4.018558726527398 + "mu": 33.969011487326654, + "sigma": 6.446958847986065 } ], "team_2": [ { - "mu": 22.36665068396946, - "sigma": 4.014052092032948 + "mu": 27.876574328523148, + "sigma": 6.433659614219379 }, { - "mu": 22.36665068396946, - "sigma": 4.014052092032948 + "mu": 27.876574328523148, + "sigma": 6.433659614219379 } ] }, "ranks": { "team_1": [ { - "mu": 25.047739320215243, - "sigma": 4.019165027353355 + "mu": 32.77994443000071, + "sigma": 6.450747134006956 } ], "team_2": [ { - "mu": 24.737839721558487, - "sigma": 4.008133932387805 + "mu": 32.2707505138986, + "sigma": 6.425889055872058 }, { - "mu": 24.737839721558487, - "sigma": 4.008133932387805 + "mu": 32.2707505138986, + "sigma": 6.425889055872058 } ], "team_3": [ { - "mu": 23.621492035909107, - "sigma": 4.012012083023697 + "mu": 30.08402921805331, + "sigma": 6.430997477977663 } ], "team_4": [ { - "mu": 22.69179323993884, - "sigma": 3.982173259114489 + "mu": 28.556447469746985, + "sigma": 6.355257645226833 }, { - "mu": 22.69179323993884, - "sigma": 3.982173259114489 + "mu": 28.556447469746985, + "sigma": 6.355257645226833 } ] }, "scores": { "team_1": [ { - "mu": 25.682781474841377, - "sigma": 4.018558726527398 + "mu": 33.969011487326654, + "sigma": 6.446958847986065 } ], "team_2": [ { - "mu": 22.36665068396946, - "sigma": 4.014052092032948 + "mu": 31.18838623572639, + "sigma": 6.433659614219379 }, { - "mu": 22.36665068396946, - "sigma": 4.014052092032948 + "mu": 31.18838623572639, + "sigma": 6.433659614219379 } ] }, "margins": { "team_1": [ { - "mu": 25.682781474841377, - "sigma": 4.018558726527398 + "mu": 32.41482544225496, + "sigma": 6.461445094088843 + }, + { + "mu": 33.906857976585016, + "sigma": 6.443889085725339 } ], "team_2": [ { - "mu": 20.068083975908568, - "sigma": 3.99265270242558 + "mu": 32.78577235639426, + "sigma": 6.393602822832939 + }, + { + "mu": 31.85428263215958, + "sigma": 6.436419653613984 + } + ], + "team_3": [ + { + "mu": 31.85428263215958, + "sigma": 6.436419653613984 + }, + { + "mu": 32.78577235639426, + "sigma": 6.393602822832939 + } + ], + "team_4": [ + { + "mu": 30.87527142416397, + "sigma": 6.441728888395351 + }, + { + "mu": 30.827749940403038, + "sigma": 6.404287882696643 + } + ], + "team_5": [ + { + "mu": 28.842148520695776, + "sigma": 6.398820323712304 }, { - "mu": 20.068083975908568, - "sigma": 3.99265270242558 + "mu": 29.88247071431034, + "sigma": 6.439011585401637 } ] }, "limit_sigma": { "team_1": [ { - "mu": 25.304525835662112, - "sigma": 4.026853575805652 + "mu": 33.20529342367193, + "sigma": 6.470524927271524 } ], "team_2": [ { - "mu": 25.192124425698527, - "sigma": 4.018568530844114 + "mu": 32.98962167464573, + "sigma": 6.450310652727856 }, { - "mu": 25.192124425698527, - "sigma": 4.018568530844114 + "mu": 32.98962167464573, + "sigma": 6.450310652727856 } ], "team_3": [ { - "mu": 21.577497976855618, - "sigma": 4.012182440165858 + "mu": 26.573463625457038, + "sigma": 6.431144842504635 }, { - "mu": 21.577497976855618, - "sigma": 4.012182440165858 + "mu": 26.573463625457038, + "sigma": 6.431144842504635 }, { - "mu": 21.577497976855618, - "sigma": 4.012182440165858 + "mu": 26.573463625457038, + "sigma": 6.431144842504635 } ] }, "ties": { "team_1": [ { - "mu": 25.33011385330141, - "sigma": 4.028216905728839 + "mu": 33.272693527214706, + "sigma": 6.475053163232783 } ], "team_2": [ { - "mu": 23.8642311205417, - "sigma": 4.018568530844114 + "mu": 30.581864525704084, + "sigma": 6.450310652727856 }, { - "mu": 23.8642311205417, - "sigma": 4.018568530844114 + "mu": 30.581864525704084, + "sigma": 6.450310652727856 } ], "team_3": [ { - "mu": 24.207696569529976, - "sigma": 4.01455213290113 + "mu": 31.321577819797557, + "sigma": 6.439033925885197 }, { - "mu": 24.207696569529976, - "sigma": 4.01455213290113 + "mu": 31.321577819797557, + "sigma": 6.439033925885197 }, { - "mu": 24.207696569529976, - "sigma": 4.01455213290113 + "mu": 31.321577819797557, + "sigma": 6.439033925885197 } ] }, "weights": { "team_1": [ { - "mu": 24.306917885011785, - "sigma": 3.9654537804918712 + "mu": 31.507472034621117, + "sigma": 6.3400576778117985 }, { - "mu": 24.165816982208604, - "sigma": 3.9975637927177825 + "mu": 31.21513247127301, + "sigma": 6.409881832635439 }, { - "mu": 24.165816982208604, - "sigma": 3.9975637927177825 + "mu": 31.21513247127301, + "sigma": 6.409881832635439 } ], "team_2": [ { - "mu": 24.999897343121507, - "sigma": 4.025284281144545 + "mu": 32.6326356594894, + "sigma": 6.468668612896749 }, { - "mu": 25.975078606837595, - "sigma": 4.021146381267366 + "mu": 34.342478411053904, + "sigma": 6.45836731598875 } ], "team_3": [ { - "mu": 22.215454454776424, - "sigma": 3.988306518458802 + "mu": 27.79544696814401, + "sigma": 6.387195276245987 }, { - "mu": 22.215454454776424, - "sigma": 3.988306518458802 + "mu": 27.79544696814401, + "sigma": 6.387195276245987 }, { - "mu": 23.12008526709092, - "sigma": 4.008914925117522 + "mu": 29.359119938034453, + "sigma": 6.433238001023219 } ], "team_4": [ { - "mu": 24.71769553751514, - "sigma": 4.013285533233096 + "mu": 32.04795653279319, + "sigma": 6.438991131708303 }, { - "mu": 25.410674995624863, - "sigma": 3.9970880243043205 + "mu": 33.17312015766147, + "sigma": 6.398779159317576 } ] }, "balance": { "team_1": [ { - "mu": 24.837881337028442, - "sigma": 3.9823079383378506 + "mu": 32.39723701778626, + "sigma": 6.370046544578141 }, { - "mu": 24.837881337028442, - "sigma": 3.9823079383378506 + "mu": 32.39723701778626, + "sigma": 6.370046544578141 } ], "team_2": [ { - "mu": 23.211550821782396, - "sigma": 3.9823079383378506 + "mu": 29.44834879806354, + "sigma": 6.370046544578141 }, { - "mu": 23.211550821782396, - "sigma": 3.9823079383378506 + "mu": 29.44834879806354, + "sigma": 6.370046544578141 } ] } diff --git a/tests/models/data/thurstonemostellerfull.json b/tests/models/data/thurstonemostellerfull.json index 2e9aafe..daa2df0 100644 --- a/tests/models/data/thurstonemostellerfull.json +++ b/tests/models/data/thurstonemostellerfull.json @@ -1,229 +1,263 @@ { "model": { - "mu": 29.12722456570572, - "sigma": 6.562844145445665 + "mu": 28.75617884369352, + "sigma": 0.9338654230911185 }, "normal": { "team_1": [ { - "mu": 37.96086340358235, - "sigma": 6.152277750609326 + "mu": 29.46334934789379, + "sigma": 0.9359435466825379 } ], "team_2": [ { - "mu": 20.293585727829086, - "sigma": 5.9737160820448185 + "mu": 28.04900833949325, + "sigma": 0.9352664576008098 }, { - "mu": 20.293585727829086, - "sigma": 5.9737160820448185 + "mu": 28.04900833949325, + "sigma": 0.9352664576008098 } ] }, "ranks": { "team_1": [ { - "mu": 41.00582818695858, - "sigma": 5.620138298963776 + "mu": 29.581011249884348, + "sigma": 0.9348182374340642 } ], "team_2": [ { - "mu": 31.737226150904345, - "sigma": 6.1824452499653715 + "mu": 28.87107186795716, + "sigma": 0.9360956393462009 }, { - "mu": 31.737226150904345, - "sigma": 6.1824452499653715 + "mu": 28.87107186795716, + "sigma": 0.9360956393462009 } ], "team_3": [ { - "mu": 25.770300535378404, - "sigma": 6.033344534530772 + "mu": 28.638514038707537, + "sigma": 0.9364527683061787 } ], "team_4": [ { - "mu": 17.995543389581556, - "sigma": 5.604710370468662 + "mu": 27.93411821822503, + "sigma": 0.9337823415371486 }, { - "mu": 17.995543389581556, - "sigma": 5.604710370468662 + "mu": 27.93411821822503, + "sigma": 0.9337823415371486 } ] }, "scores": { "team_1": [ { - "mu": 37.96086340358235, - "sigma": 6.152277750609326 + "mu": 29.43044577651642, + "sigma": 0.9361365658319689 } ], "team_2": [ { - "mu": 20.293585727829086, - "sigma": 5.9737160820448185 + "mu": 28.081911910870616, + "sigma": 0.9355396137957434 }, { - "mu": 20.293585727829086, - "sigma": 5.9737160820448185 + "mu": 28.081911910870616, + "sigma": 0.9355396137957434 } ] }, "margins": { "team_1": [ { - "mu": 37.96086340358235, - "sigma": 6.152277750609326 + "mu": 29.215743199426957, + "sigma": 0.9316405410154508 + }, + { + "mu": 29.67530755516039, + "sigma": 0.9256668528350388 } ], "team_2": [ { - "mu": 10.256137138652935, - "sigma": 5.925065178320822 + "mu": 28.985961021560236, + "sigma": 0.9239811585603523 + }, + { + "mu": 28.871069932626877, + "sigma": 0.93080348470129 + } + ], + "team_3": [ + { + "mu": 28.871069932626877, + "sigma": 0.93080348470129 + }, + { + "mu": 28.985961021560236, + "sigma": 0.9239811585603523 + } + ], + "team_4": [ + { + "mu": 28.64128775476016, + "sigma": 0.9346130671441418 + }, + { + "mu": 28.526396665826802, + "sigma": 0.9316405410154508 + } + ], + "team_5": [ + { + "mu": 28.29661448796008, + "sigma": 0.9316405410154508 }, { - "mu": 10.256137138652935, - "sigma": 5.925065178320822 + "mu": 28.526396665826802, + "sigma": 0.9346130671441418 } ] }, "limit_sigma": { "team_1": [ { - "mu": 41.832906302456095, - "sigma": 6.226077989930365 + "mu": 30.0806073786196, + "sigma": 0.9338654230911185 } ], "team_2": [ { - "mu": 35.330963832232015, - "sigma": 6.219283300424943 + "mu": 29.43274560674161, + "sigma": 0.9338654230911185 }, { - "mu": 35.330963832232015, - "sigma": 6.219283300424943 + "mu": 29.43274560674161, + "sigma": 0.9338654230911185 } ], "team_3": [ { - "mu": 10.217803562429054, - "sigma": 5.6255322186273045 + "mu": 26.755183545719344, + "sigma": 0.932096744399693 }, { - "mu": 10.217803562429054, - "sigma": 5.6255322186273045 + "mu": 26.755183545719344, + "sigma": 0.932096744399693 }, { - "mu": 10.217803562429054, - "sigma": 5.6255322186273045 + "mu": 26.755183545719344, + "sigma": 0.932096744399693 } ] }, "ties": { "team_1": [ { - "mu": 50.06116277752814, - "sigma": 5.830070776369612 + "mu": 30.783181123345365, + "sigma": 0.9338654230911185 } ], "team_2": [ { - "mu": 20.08502092735997, - "sigma": 5.920115411455275 + "mu": 28.04900678975664, + "sigma": 0.9338654230911185 }, { - "mu": 20.08502092735997, - "sigma": 5.920115411455275 + "mu": 28.04900678975664, + "sigma": 0.9338654230911185 } ], "team_3": [ { - "mu": 17.235489992229056, - "sigma": 5.967409516614499 + "mu": 27.436348617978553, + "sigma": 0.9338654230911185 }, { - "mu": 17.235489992229056, - "sigma": 5.967409516614499 + "mu": 27.436348617978553, + "sigma": 0.9338654230911185 }, { - "mu": 17.235489992229056, - "sigma": 5.967409516614499 + "mu": 27.436348617978553, + "sigma": 0.9338654230911185 } ] }, "weights": { "team_1": [ { - "mu": 27.18998016642687, - "sigma": 6.2458472071224165 + "mu": 28.474049542772935, + "sigma": 0.9338654230911185 }, { - "mu": 25.25273576714802, - "sigma": 5.911289787143148 + "mu": 28.191920241852348, + "sigma": 0.9332394006709405 }, { - "mu": 25.25273576714802, - "sigma": 5.911289787143148 + "mu": 28.191920241852348, + "sigma": 0.9332394006709405 } ], "team_2": [ { - "mu": 43.72875902135547, - "sigma": 5.63531678000208 + "mu": 30.22420152339278, + "sigma": 0.931778909363131 }, { - "mu": 58.33029347700523, - "sigma": 4.520588755913454 + "mu": 31.69222420309204, + "sigma": 0.9259453542074142 } ], "team_3": [ { - "mu": 14.911019612104749, - "sigma": 5.572337506720964 + "mu": 27.29074160912245, + "sigma": 0.9305902634254436 }, { - "mu": 14.911019612104749, - "sigma": 5.572337506720964 + "mu": 27.29074160912245, + "sigma": 0.9305902634254436 }, { - "mu": 22.019122088905235, - "sigma": 6.088054410510147 + "mu": 28.023460226407984, + "sigma": 0.9338654230911185 } ], "team_4": [ { - "mu": 32.61638386221464, - "sigma": 5.910577624645423 + "mu": 29.3178520004065, + "sigma": 0.9338654230911185 }, { - "mu": 36.105543158723556, - "sigma": 5.176097757197344 + "mu": 29.87952515711948, + "sigma": 0.9302890781825661 } ] }, "balance": { "team_1": [ { - "mu": 31.529253319603615, - "sigma": 6.275993562043107 + "mu": 28.871069932626877, + "sigma": 0.9360957905487499 }, { - "mu": 31.529253319603615, - "sigma": 6.275993562043107 + "mu": 28.871069932626877, + "sigma": 0.9360957905487499 } ], "team_2": [ { - "mu": 26.725195811807826, - "sigma": 6.275993562043107 + "mu": 28.64128775476016, + "sigma": 0.9360957905487499 }, { - "mu": 26.725195811807826, - "sigma": 6.275993562043107 + "mu": 28.64128775476016, + "sigma": 0.9360957905487499 } ] } diff --git a/tests/models/data/thurstonemostellerpart.json b/tests/models/data/thurstonemostellerpart.json index 0b1a3ac..04daf3c 100644 --- a/tests/models/data/thurstonemostellerpart.json +++ b/tests/models/data/thurstonemostellerpart.json @@ -1,229 +1,263 @@ { "model": { - "mu": 44.70411669210681, - "sigma": 9.541053038890395 + "mu": 22.158869793113254, + "sigma": 9.207604226120866 }, "normal": { "team_1": [ { - "mu": 49.247005102883875, - "sigma": 9.461440418692224 + "mu": 25.29063703988812, + "sigma": 9.138663008288278 } ], "team_2": [ { - "mu": 40.16122828132974, - "sigma": 9.428114348805359 + "mu": 19.027102546338387, + "sigma": 9.1097959351949 }, { - "mu": 40.16122828132974, - "sigma": 9.428114348805359 + "mu": 19.027102546338387, + "sigma": 9.1097959351949 } ] }, "ranks": { "team_1": [ { - "mu": 46.871610492395895, - "sigma": 9.470833255077274 + "mu": 23.631630410403655, + "sigma": 9.137601283805878 } ], "team_2": [ { - "mu": 45.653991966774306, - "sigma": 9.495470432454749 + "mu": 23.46759792606686, + "sigma": 9.148387289130703 }, { - "mu": 45.653991966774306, - "sigma": 9.495470432454749 + "mu": 23.46759792606686, + "sigma": 9.148387289130703 } ], "team_3": [ { - "mu": 43.53717971797718, - "sigma": 9.48819273074394 + "mu": 20.64342381823429, + "sigma": 9.146281576818899 } ], "team_4": [ { - "mu": 42.75368459127985, - "sigma": 9.470929971938707 + "mu": 20.892827017748218, + "sigma": 9.136111914824914 }, { - "mu": 42.75368459127985, - "sigma": 9.470929971938707 + "mu": 20.892827017748218, + "sigma": 9.136111914824914 } ] }, "scores": { "team_1": [ { - "mu": 49.247005102883875, - "sigma": 9.461440418692224 + "mu": 23.783642799601427, + "sigma": 9.116111125590736 } ], "team_2": [ { - "mu": 40.16122828132974, - "sigma": 9.428114348805359 + "mu": 20.53409678662508, + "sigma": 9.07778492879049 }, { - "mu": 40.16122828132974, - "sigma": 9.428114348805359 + "mu": 20.53409678662508, + "sigma": 9.07778492879049 } ] }, "margins": { "team_1": [ { - "mu": 49.247005102883875, - "sigma": 9.461440418692224 + "mu": 23.911838645613688, + "sigma": 9.15180373389109 + }, + { + "mu": 25.664807498114122, + "sigma": 9.09527916767828 } ], "team_2": [ { - "mu": 36.08297929045919, - "sigma": 9.414327667547628 + "mu": 23.03535421936347, + "sigma": 9.079122154605212 + }, + { + "mu": 22.597112006238362, + "sigma": 9.143778735500067 + } + ], + "team_3": [ + { + "mu": 22.597112006238362, + "sigma": 9.143778735500067 + }, + { + "mu": 23.03535421936347, + "sigma": 9.079122154605212 + } + ], + "team_4": [ + { + "mu": 21.720627579988147, + "sigma": 9.179935501216393 + }, + { + "mu": 21.28238536686304, + "sigma": 9.15180373389109 + } + ], + "team_5": [ + { + "mu": 20.40590094061282, + "sigma": 9.15180373389109 }, { - "mu": 36.08297929045919, - "sigma": 9.414327667547628 + "mu": 21.28238536686304, + "sigma": 9.179935501216393 } ] }, "limit_sigma": { "team_1": [ { - "mu": 47.39669468315993, - "sigma": 9.498142147196612 + "mu": 23.419323263442923, + "sigma": 9.160856531452701 } ], "team_2": [ { - "mu": 46.53921133663478, - "sigma": 9.494472048769344 + "mu": 23.845827745051448, + "sigma": 9.15350792343279 }, { - "mu": 46.53921133663478, - "sigma": 9.494472048769344 + "mu": 23.845827745051448, + "sigma": 9.15350792343279 } ], "team_3": [ { - "mu": 40.17644405652572, - "sigma": 9.45723291082959 + "mu": 19.211458370845392, + "sigma": 9.134586759919452 }, { - "mu": 40.17644405652572, - "sigma": 9.45723291082959 + "mu": 19.211458370845392, + "sigma": 9.134586759919452 }, { - "mu": 40.17644405652572, - "sigma": 9.45723291082959 + "mu": 19.211458370845392, + "sigma": 9.134586759919452 } ] }, "ties": { "team_1": [ { - "mu": 49.526344532469324, - "sigma": 9.46880809681838 + "mu": 24.981058164252886, + "sigma": 9.142141169297767 } ], "team_2": [ { - "mu": 42.13982524677902, - "sigma": 9.472419888532936 + "mu": 20.096644686983666, + "sigma": 9.142429816031566 }, { - "mu": 42.13982524677902, - "sigma": 9.472419888532936 + "mu": 20.096644686983666, + "sigma": 9.142429816031566 } ], "team_3": [ { - "mu": 42.44618029707208, - "sigma": 9.469607622637062 + "mu": 21.39890652810321, + "sigma": 9.133663447997913 }, { - "mu": 42.44618029707208, - "sigma": 9.469607622637062 + "mu": 21.39890652810321, + "sigma": 9.133663447997913 }, { - "mu": 42.44618029707208, - "sigma": 9.469607622637062 + "mu": 21.39890652810321, + "sigma": 9.133663447997913 } ] }, "weights": { "team_1": [ { - "mu": 44.52721198262341, - "sigma": 9.518446682441564 + "mu": 22.264762809695196, + "sigma": 9.115700685581762 }, { - "mu": 44.35030727314002, - "sigma": 9.495420841521536 + "mu": 22.211816301404223, + "sigma": 9.161957187698462 }, { - "mu": 44.35030727314002, - "sigma": 9.495420841521536 + "mu": 22.211816301404223, + "sigma": 9.161957187698462 } ], "team_2": [ { - "mu": 47.41579907845663, - "sigma": 9.485588771757103 + "mu": 24.26806483107753, + "sigma": 9.157490238577536 }, { - "mu": 50.12748146480645, - "sigma": 9.429430054802081 + "mu": 26.377259869041804, + "sigma": 9.106719217696481 } ], "team_3": [ { - "mu": 42.09670762607672, - "sigma": 9.48337889088161 + "mu": 20.149509475954194, + "sigma": 9.15598480499873 }, { - "mu": 42.09670762607672, - "sigma": 9.48337889088161 + "mu": 20.149509475954194, + "sigma": 9.15598480499873 }, { - "mu": 43.400412159091765, - "sigma": 9.512442187035436 + "mu": 21.154189634533722, + "sigma": 9.18201986979692 } ], "team_4": [ { - "mu": 44.95365279075386, - "sigma": 9.495419839077567 + "mu": 22.00608856401707, + "sigma": 9.16236615905026 }, { - "mu": 45.20318888940091, - "sigma": 9.44919881817139 + "mu": 22.082479178565162, + "sigma": 9.185202057163268 } ] }, "balance": { "team_1": [ { - "mu": 46.52626389457685, - "sigma": 9.482643653066138 + "mu": 23.911838645613688, + "sigma": 9.15180373389109 }, { - "mu": 46.52626389457685, - "sigma": 9.482643653066138 + "mu": 23.911838645613688, + "sigma": 9.15180373389109 } ], "team_2": [ { - "mu": 42.88196948963677, - "sigma": 9.482643653066138 + "mu": 20.40590094061282, + "sigma": 9.15180373389109 }, { - "mu": 42.88196948963677, - "sigma": 9.482643653066138 + "mu": 20.40590094061282, + "sigma": 9.15180373389109 } ] } diff --git a/tests/models/generate.py b/tests/models/generate.py index ac63330..0b856b3 100644 --- a/tests/models/generate.py +++ b/tests/models/generate.py @@ -77,7 +77,12 @@ def generate_expected_test_data() -> None: score_data = generate_model_data(game_result) model.margin = 2.0 - game_result = model.rate(teams=[team_1, team_2], scores=[1, 4]) + game = [[r(), r()], [r(), r()], [r(), r()], [r(), r()], [r(), r()]] + game_result = model.rate( + teams=game, + scores=[10, 5, 5, 2, 1], + weights=[[1, 2], [2, 1], [1, 2], [3, 1], [1, 2]], + ) margin_data = generate_model_data(game_result) model.margin = 0.0 diff --git a/tests/models/weng_lin/test_bradley_terry_full.py b/tests/models/weng_lin/test_bradley_terry_full.py index 56ae083..7d1f4cc 100644 --- a/tests/models/weng_lin/test_bradley_terry_full.py +++ b/tests/models/weng_lin/test_bradley_terry_full.py @@ -343,7 +343,12 @@ def test_rate() -> None: check_expected(data, "scores", results_scores) model.margin = 2.0 - results_margins = model.rate(teams=[team_1, team_2], scores=[1, 4]) + game = [[r(), r()], [r(), r()], [r(), r()], [r(), r()], [r(), r()]] + results_margins = model.rate( + teams=game, + scores=[10, 5, 5, 2, 1], + weights=[[1, 2], [2, 1], [1, 2], [3, 1], [1, 2]], + ) check_expected(data, "margins", results_margins) team_1 = [r()] diff --git a/tests/models/weng_lin/test_bradley_terry_part.py b/tests/models/weng_lin/test_bradley_terry_part.py index 393ded6..2e65d09 100644 --- a/tests/models/weng_lin/test_bradley_terry_part.py +++ b/tests/models/weng_lin/test_bradley_terry_part.py @@ -347,7 +347,12 @@ def test_rate() -> None: check_expected(data, "scores", results_scores) model.margin = 2.0 - results_margins = model.rate(teams=[team_1, team_2], scores=[1, 4]) + game = [[r(), r()], [r(), r()], [r(), r()], [r(), r()], [r(), r()]] + results_margins = model.rate( + teams=game, + scores=[10, 5, 5, 2, 1], + weights=[[1, 2], [2, 1], [1, 2], [3, 1], [1, 2]], + ) check_expected(data, "margins", results_margins) team_1 = [r()] diff --git a/tests/models/weng_lin/test_common.py b/tests/models/weng_lin/test_common.py index 49968eb..f16ca59 100644 --- a/tests/models/weng_lin/test_common.py +++ b/tests/models/weng_lin/test_common.py @@ -80,7 +80,6 @@ def test_calculate_rankings(model) -> None: # Conduct Tests assert model._calculate_rankings([]) == [] assert model._calculate_rankings([], []) == [] - assert model._calculate_rankings([a], [a]) == [0] # type: ignore assert model._calculate_rankings([a, b, c, d]) == [0, 1, 2, 3] assert model._calculate_rankings([a, b], [0, 0]) == [0, 0] assert model._calculate_rankings([a, b, c, d], [1, 2, 3, 4]) == [0, 1, 2, 3] diff --git a/tests/models/weng_lin/test_plackett_luce.py b/tests/models/weng_lin/test_plackett_luce.py index 6104ffd..fcd677c 100644 --- a/tests/models/weng_lin/test_plackett_luce.py +++ b/tests/models/weng_lin/test_plackett_luce.py @@ -340,7 +340,12 @@ def test_rate() -> None: check_expected(data, "scores", results_scores) model.margin = 2.0 - results_margins = model.rate(teams=[team_1, team_2], scores=[1, 4]) + game = [[r(), r()], [r(), r()], [r(), r()], [r(), r()], [r(), r()]] + results_margins = model.rate( + teams=game, + scores=[10, 5, 5, 2, 1], + weights=[[1, 2], [2, 1], [1, 2], [3, 1], [1, 2]], + ) check_expected(data, "margins", results_margins) team_1 = [r()] diff --git a/tests/models/weng_lin/test_thurstone_mosteller_full.py b/tests/models/weng_lin/test_thurstone_mosteller_full.py index 7376657..ad393b3 100644 --- a/tests/models/weng_lin/test_thurstone_mosteller_full.py +++ b/tests/models/weng_lin/test_thurstone_mosteller_full.py @@ -350,7 +350,12 @@ def test_rate() -> None: check_expected(data, "scores", results_scores) model.margin = 2.0 - results_margins = model.rate(teams=[team_1, team_2], scores=[1, 4]) + game = [[r(), r()], [r(), r()], [r(), r()], [r(), r()], [r(), r()]] + results_margins = model.rate( + teams=game, + scores=[10, 5, 5, 2, 1], + weights=[[1, 2], [2, 1], [1, 2], [3, 1], [1, 2]], + ) check_expected(data, "margins", results_margins) team_1 = [r()] diff --git a/tests/models/weng_lin/test_thurstone_mosteller_part.py b/tests/models/weng_lin/test_thurstone_mosteller_part.py index 087122d..c16647d 100644 --- a/tests/models/weng_lin/test_thurstone_mosteller_part.py +++ b/tests/models/weng_lin/test_thurstone_mosteller_part.py @@ -355,7 +355,12 @@ def test_rate() -> None: check_expected(data, "scores", results_scores) model.margin = 2.0 - results_margins = model.rate(teams=[team_1, team_2], scores=[1, 4]) + game = [[r(), r()], [r(), r()], [r(), r()], [r(), r()], [r(), r()]] + results_margins = model.rate( + teams=game, + scores=[10, 5, 5, 2, 1], + weights=[[1, 2], [2, 1], [1, 2], [3, 1], [1, 2]], + ) check_expected(data, "margins", results_margins) team_1 = [r()] diff --git a/uv.lock b/uv.lock index c7b5b6f..bfd4af2 100644 --- a/uv.lock +++ b/uv.lock @@ -773,19 +773,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a0/d9/a1e041c5e7caa9a05c925f4bdbdfb7f006d1f74996af53467bc394c97be7/importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b", size = 26514 }, ] -[[package]] -name = "incremental" -version = "24.7.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "setuptools" }, - { name = "tomli", version = "2.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/27/87/156b374ff6578062965afe30cc57627d35234369b3336cf244b240c8d8e6/incremental-24.7.2.tar.gz", hash = "sha256:fb4f1d47ee60efe87d4f6f0ebb5f70b9760db2b2574c59c8e8912be4ebd464c9", size = 28157 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0d/38/221e5b2ae676a3938c2c1919131410c342b6efc2baffeda395dd66eeca8f/incremental-24.7.2-py3-none-any.whl", hash = "sha256:8cb2c3431530bec48ad70513931a760f446ad6c25e8333ca5d95e24b0ed7b8fe", size = 20516 }, -] - [[package]] name = "iniconfig" version = "2.0.0" @@ -1520,7 +1507,7 @@ wheels = [ [[package]] name = "openskill" -version = "6.1.0a1" +version = "6.1.0" source = { editable = "." } [package.optional-dependencies] @@ -1595,7 +1582,7 @@ requires-dist = [ { name = "sphinx-intl", marker = "extra == 'docs'", specifier = "~=2.3" }, { name = "sphinxcontrib-bibtex", marker = "extra == 'docs'", specifier = "~=2.6" }, { name = "sphinxext-opengraph", marker = "extra == 'docs'", specifier = "~=0.9" }, - { name = "towncrier", marker = "extra == 'build'", specifier = "~=23.11" }, + { name = "towncrier", marker = "extra == 'build'", specifier = "~=24.8" }, { name = "tox", marker = "extra == 'tests'", specifier = "~=4.24" }, { name = "tqdm", marker = "extra == 'benchmark'", specifier = "~=4.67" }, { name = "twine", marker = "extra == 'build'", specifier = "~=6.1" }, @@ -2799,17 +2786,16 @@ wheels = [ [[package]] name = "towncrier" -version = "23.11.0" +version = "24.8.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "click" }, - { name = "incremental" }, { name = "jinja2" }, { name = "tomli", version = "2.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e0/43/bb5161b32c538a099e1e1a8b79eedd4556dca925facc3b11e0ea7ab96d40/towncrier-23.11.0.tar.gz", hash = "sha256:13937c247e3f8ae20ac44d895cf5f96a60ad46cfdcc1671759530d7837d9ee5d", size = 51483 } +sdist = { url = "https://files.pythonhosted.org/packages/69/d7/a5183f788cf4fabf03f7c767ae0b968249b0c737eb64b4d87a07ae01fea7/towncrier-24.8.0.tar.gz", hash = "sha256:013423ee7eed102b2f393c287d22d95f66f1a3ea10a4baa82d298001a7f18af3", size = 61635 } wheels = [ - { url = "https://files.pythonhosted.org/packages/36/5a/6546c8ea2bee64c9e9552e06fdb31118a4f23a12aa161581b5fefd070152/towncrier-23.11.0-py3-none-any.whl", hash = "sha256:2e519ca619426d189e3c98c99558fe8be50c9ced13ea1fc20a4a353a95d2ded7", size = 49327 }, + { url = "https://files.pythonhosted.org/packages/93/1b/2f7b88506e22d9798c139261af4946865c0787cfa345514ca3c70173a9cc/towncrier-24.8.0-py3-none-any.whl", hash = "sha256:9343209592b839209cdf28c339ba45792fbfe9775b5f9c177462fd693e127d8d", size = 56981 }, ] [[package]]