diff --git a/.gitignore b/.gitignore index 7f93ebf..9dc6b51 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ +# python / VS Code venv __pycache__ +.ruff_cache +.vscode +build diff --git a/poetry.lock b/poetry.lock index 26f4816..3897c84 100644 --- a/poetry.lock +++ b/poetry.lock @@ -26,52 +26,6 @@ files = [ astroid = ["astroid (>=2,<4)"] test = ["astroid (>=2,<4)", "pytest", "pytest-cov", "pytest-xdist"] -[[package]] -name = "black" -version = "24.10.0" -description = "The uncompromising code formatter." -optional = false -python-versions = ">=3.9" -files = [ - {file = "black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812"}, - {file = "black-24.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1c536fcf674217e87b8cc3657b81809d3c085d7bf3ef262ead700da345bfa6ea"}, - {file = "black-24.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f"}, - {file = "black-24.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e"}, - {file = "black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad"}, - {file = "black-24.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f9da3333530dbcecc1be13e69c250ed8dfa67f43c4005fb537bb426e19200d50"}, - {file = "black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392"}, - {file = "black-24.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175"}, - {file = "black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3"}, - {file = "black-24.10.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d37d422772111794b26757c5b55a3eade028aa3fde43121ab7b673d050949d65"}, - {file = "black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f"}, - {file = "black-24.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8"}, - {file = "black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981"}, - {file = "black-24.10.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1f93102e0c5bb3907451063e08b9876dbeac810e7da5a8bfb7aeb5a9ef89066b"}, - {file = "black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2"}, - {file = "black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b"}, - {file = "black-24.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:17374989640fbca88b6a448129cd1745c5eb8d9547b464f281b251dd00155ccd"}, - {file = "black-24.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:63f626344343083322233f175aaf372d326de8436f5928c042639a4afbbf1d3f"}, - {file = "black-24.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfa1d0cb6200857f1923b602f978386a3a2758a65b52e0950299ea014be6800"}, - {file = "black-24.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cd9c95431d94adc56600710f8813ee27eea544dd118d45896bb734e9d7a0dc7"}, - {file = "black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d"}, - {file = "black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875"}, -] - -[package.dependencies] -click = ">=8.0.0" -mypy-extensions = ">=0.4.3" -packaging = ">=22.0" -pathspec = ">=0.9.0" -platformdirs = ">=2" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} - -[package.extras] -colorama = ["colorama (>=0.4.3)"] -d = ["aiohttp (>=3.10)"] -jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] -uvloop = ["uvloop (>=0.15.2)"] - [[package]] name = "cffi" version = "1.17.1" @@ -151,20 +105,6 @@ files = [ [package.dependencies] pycparser = "*" -[[package]] -name = "click" -version = "8.1.7" -description = "Composable command line interface toolkit" -optional = false -python-versions = ">=3.7" -files = [ - {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, - {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, -] - -[package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} - [[package]] name = "colorama" version = "0.4.6" @@ -267,41 +207,6 @@ files = [ [package.extras] tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] -[[package]] -name = "flake8" -version = "7.1.1" -description = "the modular source code checker: pep8 pyflakes and co" -optional = false -python-versions = ">=3.8.1" -files = [ - {file = "flake8-7.1.1-py2.py3-none-any.whl", hash = "sha256:597477df7860daa5aa0fdd84bf5208a043ab96b8e96ab708770ae0364dd03213"}, - {file = "flake8-7.1.1.tar.gz", hash = "sha256:049d058491e228e03e67b390f311bbf88fce2dbaa8fa673e7aea87b7198b8d38"}, -] - -[package.dependencies] -mccabe = ">=0.7.0,<0.8.0" -pycodestyle = ">=2.12.0,<2.13.0" -pyflakes = ">=3.2.0,<3.3.0" - -[[package]] -name = "flake8-black" -version = "0.3.6" -description = "flake8 plugin to call black as a code style validator" -optional = false -python-versions = ">=3.7" -files = [ - {file = "flake8-black-0.3.6.tar.gz", hash = "sha256:0dfbca3274777792a5bcb2af887a4cad72c72d0e86c94e08e3a3de151bb41c34"}, - {file = "flake8_black-0.3.6-py3-none-any.whl", hash = "sha256:fe8ea2eca98d8a504f22040d9117347f6b367458366952862ac3586e7d4eeaca"}, -] - -[package.dependencies] -black = ">=22.1.0" -flake8 = ">=3" -tomli = {version = "*", markers = "python_version < \"3.11\""} - -[package.extras] -develop = ["build", "twine"] - [[package]] name = "ipykernel" version = "6.29.5" @@ -373,20 +278,6 @@ qtconsole = ["qtconsole"] test = ["packaging", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath"] test-extra = ["curio", "ipython[test]", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "trio"] -[[package]] -name = "isort" -version = "5.13.2" -description = "A Python utility / library to sort Python imports." -optional = false -python-versions = ">=3.8.0" -files = [ - {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, - {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, -] - -[package.extras] -colors = ["colorama (>=0.4.6)"] - [[package]] name = "jedi" version = "0.19.2" @@ -462,17 +353,6 @@ files = [ [package.dependencies] traitlets = "*" -[[package]] -name = "mccabe" -version = "0.7.0" -description = "McCabe checker, plugin for flake8" -optional = false -python-versions = ">=3.6" -files = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, -] - [[package]] name = "mpmath" version = "1.3.0" @@ -490,70 +370,6 @@ docs = ["sphinx"] gmpy = ["gmpy2 (>=2.1.0a4)"] tests = ["pytest (>=4.6)"] -[[package]] -name = "mypy" -version = "1.13.0" -description = "Optional static typing for Python" -optional = false -python-versions = ">=3.8" -files = [ - {file = "mypy-1.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6607e0f1dd1fb7f0aca14d936d13fd19eba5e17e1cd2a14f808fa5f8f6d8f60a"}, - {file = "mypy-1.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a21be69bd26fa81b1f80a61ee7ab05b076c674d9b18fb56239d72e21d9f4c80"}, - {file = "mypy-1.13.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7b2353a44d2179846a096e25691d54d59904559f4232519d420d64da6828a3a7"}, - {file = "mypy-1.13.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0730d1c6a2739d4511dc4253f8274cdd140c55c32dfb0a4cf8b7a43f40abfa6f"}, - {file = "mypy-1.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:c5fc54dbb712ff5e5a0fca797e6e0aa25726c7e72c6a5850cfd2adbc1eb0a372"}, - {file = "mypy-1.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:581665e6f3a8a9078f28d5502f4c334c0c8d802ef55ea0e7276a6e409bc0d82d"}, - {file = "mypy-1.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3ddb5b9bf82e05cc9a627e84707b528e5c7caaa1c55c69e175abb15a761cec2d"}, - {file = "mypy-1.13.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20c7ee0bc0d5a9595c46f38beb04201f2620065a93755704e141fcac9f59db2b"}, - {file = "mypy-1.13.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3790ded76f0b34bc9c8ba4def8f919dd6a46db0f5a6610fb994fe8efdd447f73"}, - {file = "mypy-1.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51f869f4b6b538229c1d1bcc1dd7d119817206e2bc54e8e374b3dfa202defcca"}, - {file = "mypy-1.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5c7051a3461ae84dfb5dd15eff5094640c61c5f22257c8b766794e6dd85e72d5"}, - {file = "mypy-1.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:39bb21c69a5d6342f4ce526e4584bc5c197fd20a60d14a8624d8743fffb9472e"}, - {file = "mypy-1.13.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:164f28cb9d6367439031f4c81e84d3ccaa1e19232d9d05d37cb0bd880d3f93c2"}, - {file = "mypy-1.13.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4c1bfcdbce96ff5d96fc9b08e3831acb30dc44ab02671eca5953eadad07d6d0"}, - {file = "mypy-1.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:a0affb3a79a256b4183ba09811e3577c5163ed06685e4d4b46429a271ba174d2"}, - {file = "mypy-1.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a7b44178c9760ce1a43f544e595d35ed61ac2c3de306599fa59b38a6048e1aa7"}, - {file = "mypy-1.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d5092efb8516d08440e36626f0153b5006d4088c1d663d88bf79625af3d1d62"}, - {file = "mypy-1.13.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de2904956dac40ced10931ac967ae63c5089bd498542194b436eb097a9f77bc8"}, - {file = "mypy-1.13.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:7bfd8836970d33c2105562650656b6846149374dc8ed77d98424b40b09340ba7"}, - {file = "mypy-1.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:9f73dba9ec77acb86457a8fc04b5239822df0c14a082564737833d2963677dbc"}, - {file = "mypy-1.13.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:100fac22ce82925f676a734af0db922ecfea991e1d7ec0ceb1e115ebe501301a"}, - {file = "mypy-1.13.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7bcb0bb7f42a978bb323a7c88f1081d1b5dee77ca86f4100735a6f541299d8fb"}, - {file = "mypy-1.13.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bde31fc887c213e223bbfc34328070996061b0833b0a4cfec53745ed61f3519b"}, - {file = "mypy-1.13.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:07de989f89786f62b937851295ed62e51774722e5444a27cecca993fc3f9cd74"}, - {file = "mypy-1.13.0-cp38-cp38-win_amd64.whl", hash = "sha256:4bde84334fbe19bad704b3f5b78c4abd35ff1026f8ba72b29de70dda0916beb6"}, - {file = "mypy-1.13.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0246bcb1b5de7f08f2826451abd947bf656945209b140d16ed317f65a17dc7dc"}, - {file = "mypy-1.13.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7f5b7deae912cf8b77e990b9280f170381fdfbddf61b4ef80927edd813163732"}, - {file = "mypy-1.13.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7029881ec6ffb8bc233a4fa364736789582c738217b133f1b55967115288a2bc"}, - {file = "mypy-1.13.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3e38b980e5681f28f033f3be86b099a247b13c491f14bb8b1e1e134d23bb599d"}, - {file = "mypy-1.13.0-cp39-cp39-win_amd64.whl", hash = "sha256:a6789be98a2017c912ae6ccb77ea553bbaf13d27605d2ca20a76dfbced631b24"}, - {file = "mypy-1.13.0-py3-none-any.whl", hash = "sha256:9c250883f9fd81d212e0952c92dbfcc96fc237f4b7c92f56ac81fd48460b3e5a"}, - {file = "mypy-1.13.0.tar.gz", hash = "sha256:0291a61b6fbf3e6673e3405cfcc0e7650bebc7939659fdca2702958038bd835e"}, -] - -[package.dependencies] -mypy-extensions = ">=1.0.0" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = ">=4.6.0" - -[package.extras] -dmypy = ["psutil (>=4.0)"] -faster-cache = ["orjson"] -install-types = ["pip"] -mypyc = ["setuptools (>=50)"] -reports = ["lxml"] - -[[package]] -name = "mypy-extensions" -version = "1.0.0" -description = "Type system extensions for programs checked with the mypy type checker." -optional = false -python-versions = ">=3.5" -files = [ - {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, - {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, -] - [[package]] name = "nest-asyncio" version = "1.6.0" @@ -810,17 +626,6 @@ files = [ {file = "pastel-0.2.1.tar.gz", hash = "sha256:e6581ac04e973cac858828c6202c1e1e81fee1dc7de7683f3e1ffe0bfd8a573d"}, ] -[[package]] -name = "pathspec" -version = "0.12.1" -description = "Utility library for gitignore style pattern matching of file paths." -optional = false -python-versions = ">=3.8" -files = [ - {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, - {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, -] - [[package]] name = "pexpect" version = "4.9.0" @@ -853,18 +658,19 @@ type = ["mypy (>=1.11.2)"] [[package]] name = "poethepoet" -version = "0.24.4" +version = "0.31.1" description = "A task runner that works well with poetry." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "poethepoet-0.24.4-py3-none-any.whl", hash = "sha256:fb4ea35d7f40fe2081ea917d2e4102e2310fda2cde78974050ca83896e229075"}, - {file = "poethepoet-0.24.4.tar.gz", hash = "sha256:ff4220843a87c888cbcb5312c8905214701d0af60ac7271795baa8369b428fef"}, + {file = "poethepoet-0.31.1-py3-none-any.whl", hash = "sha256:7fdfa0ac6074be9936723e7231b5bfaad2923e96c674a9857e81d326cf8ccdc2"}, + {file = "poethepoet-0.31.1.tar.gz", hash = "sha256:d6b66074edf85daf115bb916eae0afd6387d19e1562e1c9ef7d61d5c585696aa"}, ] [package.dependencies] pastel = ">=0.2.1,<0.3.0" -tomli = ">=1.2.2" +pyyaml = ">=6.0.2,<7.0.0" +tomli = {version = ">=1.2.2", markers = "python_version < \"3.11\""} [package.extras] poetry-plugin = ["poetry (>=1.0,<2.0)"] @@ -938,17 +744,6 @@ files = [ [package.extras] tests = ["pytest"] -[[package]] -name = "pycodestyle" -version = "2.12.1" -description = "Python style guide checker" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pycodestyle-2.12.1-py2.py3-none-any.whl", hash = "sha256:46f0fb92069a7c28ab7bb558f05bfc0110dac69a0cd23c61ea0040283a9d78b3"}, - {file = "pycodestyle-2.12.1.tar.gz", hash = "sha256:6838eae08bbce4f6accd5d5572075c63626a15ee3e6f842df996bf62f6d73521"}, -] - [[package]] name = "pycparser" version = "2.22" @@ -960,17 +755,6 @@ files = [ {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, ] -[[package]] -name = "pyflakes" -version = "3.2.0" -description = "passive checker of Python programs" -optional = false -python-versions = ">=3.8" -files = [ - {file = "pyflakes-3.2.0-py2.py3-none-any.whl", hash = "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a"}, - {file = "pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f"}, -] - [[package]] name = "pygments" version = "2.18.0" @@ -1057,6 +841,68 @@ files = [ {file = "pywin32-308-cp39-cp39-win_amd64.whl", hash = "sha256:71b3322d949b4cc20776436a9c9ba0eeedcbc9c650daa536df63f0ff111bb920"}, ] +[[package]] +name = "pyyaml" +version = "6.0.2" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, +] + [[package]] name = "pyzmq" version = "26.2.0" @@ -1180,28 +1026,29 @@ cffi = {version = "*", markers = "implementation_name == \"pypy\""} [[package]] name = "ruff" -version = "0.1.15" +version = "0.8.1" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.1.15-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:5fe8d54df166ecc24106db7dd6a68d44852d14eb0729ea4672bb4d96c320b7df"}, - {file = "ruff-0.1.15-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6f0bfbb53c4b4de117ac4d6ddfd33aa5fc31beeaa21d23c45c6dd249faf9126f"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0d432aec35bfc0d800d4f70eba26e23a352386be3a6cf157083d18f6f5881c8"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9405fa9ac0e97f35aaddf185a1be194a589424b8713e3b97b762336ec79ff807"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c66ec24fe36841636e814b8f90f572a8c0cb0e54d8b5c2d0e300d28a0d7bffec"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:6f8ad828f01e8dd32cc58bc28375150171d198491fc901f6f98d2a39ba8e3ff5"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86811954eec63e9ea162af0ffa9f8d09088bab51b7438e8b6488b9401863c25e"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fd4025ac5e87d9b80e1f300207eb2fd099ff8200fa2320d7dc066a3f4622dc6b"}, - {file = "ruff-0.1.15-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b17b93c02cdb6aeb696effecea1095ac93f3884a49a554a9afa76bb125c114c1"}, - {file = "ruff-0.1.15-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ddb87643be40f034e97e97f5bc2ef7ce39de20e34608f3f829db727a93fb82c5"}, - {file = "ruff-0.1.15-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:abf4822129ed3a5ce54383d5f0e964e7fef74a41e48eb1dfad404151efc130a2"}, - {file = "ruff-0.1.15-py3-none-musllinux_1_2_i686.whl", hash = "sha256:6c629cf64bacfd136c07c78ac10a54578ec9d1bd2a9d395efbee0935868bf852"}, - {file = "ruff-0.1.15-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1bab866aafb53da39c2cadfb8e1c4550ac5340bb40300083eb8967ba25481447"}, - {file = "ruff-0.1.15-py3-none-win32.whl", hash = "sha256:2417e1cb6e2068389b07e6fa74c306b2810fe3ee3476d5b8a96616633f40d14f"}, - {file = "ruff-0.1.15-py3-none-win_amd64.whl", hash = "sha256:3837ac73d869efc4182d9036b1405ef4c73d9b1f88da2413875e34e0d6919587"}, - {file = "ruff-0.1.15-py3-none-win_arm64.whl", hash = "sha256:9a933dfb1c14ec7a33cceb1e49ec4a16b51ce3c20fd42663198746efc0427360"}, - {file = "ruff-0.1.15.tar.gz", hash = "sha256:f6dfa8c1b21c913c326919056c390966648b680966febcb796cc9d1aaab8564e"}, + {file = "ruff-0.8.1-py3-none-linux_armv6l.whl", hash = "sha256:fae0805bd514066f20309f6742f6ee7904a773eb9e6c17c45d6b1600ca65c9b5"}, + {file = "ruff-0.8.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b8a4f7385c2285c30f34b200ca5511fcc865f17578383db154e098150ce0a087"}, + {file = "ruff-0.8.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:cd054486da0c53e41e0086e1730eb77d1f698154f910e0cd9e0d64274979a209"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2029b8c22da147c50ae577e621a5bfbc5d1fed75d86af53643d7a7aee1d23871"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2666520828dee7dfc7e47ee4ea0d928f40de72056d929a7c5292d95071d881d1"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:333c57013ef8c97a53892aa56042831c372e0bb1785ab7026187b7abd0135ad5"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:288326162804f34088ac007139488dcb43de590a5ccfec3166396530b58fb89d"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b12c39b9448632284561cbf4191aa1b005882acbc81900ffa9f9f471c8ff7e26"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:364e6674450cbac8e998f7b30639040c99d81dfb5bbc6dfad69bc7a8f916b3d1"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b22346f845fec132aa39cd29acb94451d030c10874408dbf776af3aaeb53284c"}, + {file = "ruff-0.8.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b2f2f7a7e7648a2bfe6ead4e0a16745db956da0e3a231ad443d2a66a105c04fa"}, + {file = "ruff-0.8.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:adf314fc458374c25c5c4a4a9270c3e8a6a807b1bec018cfa2813d6546215540"}, + {file = "ruff-0.8.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a885d68342a231b5ba4d30b8c6e1b1ee3a65cf37e3d29b3c74069cdf1ee1e3c9"}, + {file = "ruff-0.8.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d2c16e3508c8cc73e96aa5127d0df8913d2290098f776416a4b157657bee44c5"}, + {file = "ruff-0.8.1-py3-none-win32.whl", hash = "sha256:93335cd7c0eaedb44882d75a7acb7df4b77cd7cd0d2255c93b28791716e81790"}, + {file = "ruff-0.8.1-py3-none-win_amd64.whl", hash = "sha256:2954cdbe8dfd8ab359d4a30cd971b589d335a44d444b6ca2cb3d1da21b75e4b6"}, + {file = "ruff-0.8.1-py3-none-win_arm64.whl", hash = "sha256:55873cc1a473e5ac129d15eccb3c008c096b94809d693fc7053f588b67822737"}, + {file = "ruff-0.8.1.tar.gz", hash = "sha256:3583db9a6450364ed5ca3f3b4225958b24f78178908d5c4bc0f46251ccca898f"}, ] [[package]] @@ -1434,4 +1281,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "f30e6716b379f51af355d186d036726fb112457b561862a73c58c2ea47cb2a2a" +content-hash = "b643261f91a781d77735e05f6d2ac1002867600c2df6393a9d1a15f5e1189109" diff --git a/pyproject.toml b/pyproject.toml index 8c29bfa..e991388 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,35 +17,25 @@ sympy = "^1.13.3" networkx = "^3.4.2" pandas = "^2.2.3" +[tool.poetry.group.dev.dependencies] +pyright = "^1.1.389" +ruff = "^0.8.1" +poethepoet = "^0.31.1" +ipykernel = "^6.29.5" +networkx-stubs = "^0.0.1" + [tool.poetry.scripts] holt59-aoc = "holt59.aoc.__main__:main" [tool.poe.tasks] -lint-black = "black --check --diff src tests typings" -lint-isort = "isort -c src tests typings" -lint-ruff = "ruff src tests typings" -lint-flake8 = "flake8 src tests typings" -lint-pyright = "pyright src tests" -lint-all.sequence = [ - "lint-black", - "lint-isort", - "lint-flake8", - "lint-ruff", - "lint-pyright", -] -lint-all.ignore_fail = "return_non_zero" - -[tool.poetry.group.dev.dependencies] -flake8 = "^7.1.1" -flake8-black = "^0.3.6" -black = "^24.10.0" -pyright = "^1.1.389" -mypy = "^1.13.0" -isort = "^5.13.2" -ruff = "^0.1.8" -poethepoet = "^0.24.4" -ipykernel = "^6.29.5" -networkx-stubs = "^0.0.1" +format-imports = "ruff check --select I src --fix" +format-ruff = "ruff format src" +format.sequence = ["format-imports", "format-ruff"] +lint-ruff = "ruff check src" +lint-ruff-format = "ruff format --check src" +lint-pyright = "pyright src" +lint.sequence = ["lint-ruff", "lint-ruff-format", "lint-pyright"] +lint.ignore_fail = "return_non_zero" [build-system] requires = ["poetry-core"] diff --git a/src/holt59/aoc/2015/day22.py b/src/holt59/aoc/2015/day22.py index 7ef1f62..0c488ec 100644 --- a/src/holt59/aoc/2015/day22.py +++ b/src/holt59/aoc/2015/day22.py @@ -2,7 +2,7 @@ from __future__ import annotations import heapq import sys -from typing import Literal, TypeAlias +from typing import Literal, TypeAlias, cast PlayerType: TypeAlias = Literal["player", "boss"] SpellType: TypeAlias = Literal["magic missile", "drain", "shield", "poison", "recharge"] @@ -18,6 +18,16 @@ Node: TypeAlias = tuple[ tuple[tuple[SpellType, int], ...], ] +ATTACK_SPELLS: list[tuple[SpellType, int, int, int]] = [ + ("magic missile", 53, 4, 0), + ("drain", 73, 2, 2), +] +BUFF_SPELLS: list[tuple[BuffType, int, int]] = [ + ("shield", 113, 6), + ("poison", 173, 6), + ("recharge", 229, 5), +] + def play( player_hp: int, @@ -97,10 +107,7 @@ def play( else: buff_types = {b for b, _ in buffs} - for spell, cost, damage, regeneration in ( - ("magic missile", 53, 4, 0), - ("drain", 73, 2, 2), - ): + for spell, cost, damage, regeneration in ATTACK_SPELLS: if player_mana < cost: continue @@ -114,15 +121,11 @@ def play( player_armor, max(0, boss_hp - damage), buffs, - spells + ((spell, cost),), + spells + cast("tuple[tuple[SpellType, int]]", ((spell, cost),)), ), ) - for buff_type, buff_cost, buff_length in ( - ("shield", 113, 6), - ("poison", 173, 6), - ("recharge", 229, 5), - ): + for buff_type, buff_cost, buff_length in BUFF_SPELLS: if buff_type in buff_types: continue @@ -138,8 +141,14 @@ def play( player_mana - buff_cost, player_armor + 7 * (buff_type == "shield"), boss_hp, - buffs + ((buff_type, buff_length),), - spells + ((buff_type, buff_cost),), + buffs + + cast( + "tuple[tuple[BuffType, int]]", ((buff_type, buff_length),) + ), + spells + + cast( + "tuple[tuple[SpellType, int]]", ((buff_type, buff_cost),) + ), ), ) diff --git a/src/holt59/aoc/2015/day9.py b/src/holt59/aoc/2015/day9.py index df8e5e0..f6e7176 100644 --- a/src/holt59/aoc/2015/day9.py +++ b/src/holt59/aoc/2015/day9.py @@ -10,7 +10,8 @@ lines = sys.stdin.read().splitlines() distances: dict[str, dict[str, int]] = defaultdict(dict) for line in lines: origin, destination, length = cast( - tuple[str, str, int], parse.parse("{} to {} = {:d}", line) # type: ignore + tuple[str, str, int], + parse.parse("{} to {} = {:d}", line), # type: ignore ) distances[origin][destination] = distances[destination][origin] = length diff --git a/src/holt59/aoc/2021/day10.py b/src/holt59/aoc/2021/day10.py index 992bf35..dbaa94d 100644 --- a/src/holt59/aoc/2021/day10.py +++ b/src/holt59/aoc/2021/day10.py @@ -1,6 +1,4 @@ import sys -from collections import defaultdict -from dataclasses import dataclass lines = sys.stdin.read().splitlines() diff --git a/src/holt59/aoc/2021/day11.py b/src/holt59/aoc/2021/day11.py index 992bf35..dbaa94d 100644 --- a/src/holt59/aoc/2021/day11.py +++ b/src/holt59/aoc/2021/day11.py @@ -1,6 +1,4 @@ import sys -from collections import defaultdict -from dataclasses import dataclass lines = sys.stdin.read().splitlines() diff --git a/src/holt59/aoc/2021/day12.py b/src/holt59/aoc/2021/day12.py index 992bf35..dbaa94d 100644 --- a/src/holt59/aoc/2021/day12.py +++ b/src/holt59/aoc/2021/day12.py @@ -1,6 +1,4 @@ import sys -from collections import defaultdict -from dataclasses import dataclass lines = sys.stdin.read().splitlines() diff --git a/src/holt59/aoc/2021/day13.py b/src/holt59/aoc/2021/day13.py index 992bf35..dbaa94d 100644 --- a/src/holt59/aoc/2021/day13.py +++ b/src/holt59/aoc/2021/day13.py @@ -1,6 +1,4 @@ import sys -from collections import defaultdict -from dataclasses import dataclass lines = sys.stdin.read().splitlines() diff --git a/src/holt59/aoc/2021/day14.py b/src/holt59/aoc/2021/day14.py index 992bf35..dbaa94d 100644 --- a/src/holt59/aoc/2021/day14.py +++ b/src/holt59/aoc/2021/day14.py @@ -1,6 +1,4 @@ import sys -from collections import defaultdict -from dataclasses import dataclass lines = sys.stdin.read().splitlines() diff --git a/src/holt59/aoc/2021/day15.py b/src/holt59/aoc/2021/day15.py index 992bf35..dbaa94d 100644 --- a/src/holt59/aoc/2021/day15.py +++ b/src/holt59/aoc/2021/day15.py @@ -1,6 +1,4 @@ import sys -from collections import defaultdict -from dataclasses import dataclass lines = sys.stdin.read().splitlines() diff --git a/src/holt59/aoc/2021/day16.py b/src/holt59/aoc/2021/day16.py index 992bf35..dbaa94d 100644 --- a/src/holt59/aoc/2021/day16.py +++ b/src/holt59/aoc/2021/day16.py @@ -1,6 +1,4 @@ import sys -from collections import defaultdict -from dataclasses import dataclass lines = sys.stdin.read().splitlines() diff --git a/src/holt59/aoc/2021/day17.py b/src/holt59/aoc/2021/day17.py index 992bf35..dbaa94d 100644 --- a/src/holt59/aoc/2021/day17.py +++ b/src/holt59/aoc/2021/day17.py @@ -1,6 +1,4 @@ import sys -from collections import defaultdict -from dataclasses import dataclass lines = sys.stdin.read().splitlines() diff --git a/src/holt59/aoc/2021/day18.py b/src/holt59/aoc/2021/day18.py index 992bf35..dbaa94d 100644 --- a/src/holt59/aoc/2021/day18.py +++ b/src/holt59/aoc/2021/day18.py @@ -1,6 +1,4 @@ import sys -from collections import defaultdict -from dataclasses import dataclass lines = sys.stdin.read().splitlines() diff --git a/src/holt59/aoc/2021/day19.py b/src/holt59/aoc/2021/day19.py index 992bf35..dbaa94d 100644 --- a/src/holt59/aoc/2021/day19.py +++ b/src/holt59/aoc/2021/day19.py @@ -1,6 +1,4 @@ import sys -from collections import defaultdict -from dataclasses import dataclass lines = sys.stdin.read().splitlines() diff --git a/src/holt59/aoc/2021/day2.py b/src/holt59/aoc/2021/day2.py index dbec539..6a8db61 100644 --- a/src/holt59/aoc/2021/day2.py +++ b/src/holt59/aoc/2021/day2.py @@ -1,12 +1,13 @@ import sys from math import prod -from typing import Literal, cast +from typing import Literal, TypeAlias, cast lines = sys.stdin.read().splitlines() -commands = [ - (cast(Literal["forward", "up", "down"], (p := line.split())[0]), int(p[1])) - for line in lines +Command: TypeAlias = Literal["forward", "up", "down"] + +commands: list[tuple[Command, int]] = [ + (cast(Command, (p := line.split())[0]), int(p[1])) for line in lines ] diff --git a/src/holt59/aoc/2021/day20.py b/src/holt59/aoc/2021/day20.py index 992bf35..dbaa94d 100644 --- a/src/holt59/aoc/2021/day20.py +++ b/src/holt59/aoc/2021/day20.py @@ -1,6 +1,4 @@ import sys -from collections import defaultdict -from dataclasses import dataclass lines = sys.stdin.read().splitlines() diff --git a/src/holt59/aoc/2021/day21.py b/src/holt59/aoc/2021/day21.py index 992bf35..dbaa94d 100644 --- a/src/holt59/aoc/2021/day21.py +++ b/src/holt59/aoc/2021/day21.py @@ -1,6 +1,4 @@ import sys -from collections import defaultdict -from dataclasses import dataclass lines = sys.stdin.read().splitlines() diff --git a/src/holt59/aoc/2021/day22.py b/src/holt59/aoc/2021/day22.py index 992bf35..dbaa94d 100644 --- a/src/holt59/aoc/2021/day22.py +++ b/src/holt59/aoc/2021/day22.py @@ -1,6 +1,4 @@ import sys -from collections import defaultdict -from dataclasses import dataclass lines = sys.stdin.read().splitlines() diff --git a/src/holt59/aoc/2021/day23.py b/src/holt59/aoc/2021/day23.py index 992bf35..dbaa94d 100644 --- a/src/holt59/aoc/2021/day23.py +++ b/src/holt59/aoc/2021/day23.py @@ -1,6 +1,4 @@ import sys -from collections import defaultdict -from dataclasses import dataclass lines = sys.stdin.read().splitlines() diff --git a/src/holt59/aoc/2021/day24.py b/src/holt59/aoc/2021/day24.py index 992bf35..dbaa94d 100644 --- a/src/holt59/aoc/2021/day24.py +++ b/src/holt59/aoc/2021/day24.py @@ -1,6 +1,4 @@ import sys -from collections import defaultdict -from dataclasses import dataclass lines = sys.stdin.read().splitlines() diff --git a/src/holt59/aoc/2021/day25.py b/src/holt59/aoc/2021/day25.py index 992bf35..dbaa94d 100644 --- a/src/holt59/aoc/2021/day25.py +++ b/src/holt59/aoc/2021/day25.py @@ -1,6 +1,4 @@ import sys -from collections import defaultdict -from dataclasses import dataclass lines = sys.stdin.read().splitlines() diff --git a/src/holt59/aoc/2021/day7.py b/src/holt59/aoc/2021/day7.py index eb4d4f7..2532edb 100644 --- a/src/holt59/aoc/2021/day7.py +++ b/src/holt59/aoc/2021/day7.py @@ -1,21 +1,19 @@ import sys -import numpy as np +positions = [int(c) for c in sys.stdin.read().strip().split(",")] -positions = np.asarray([int(c) for c in sys.stdin.read().strip().split(",")]) - -min_position, max_position = positions.min(), positions.max() +min_position, max_position = min(positions), max(positions) # part 1 answer_1 = min( - np.sum(np.abs(positions - position)) + sum(abs(p - position) for p in positions) for position in range(min_position, max_position + 1) ) print(f"answer 1 is {answer_1}") # part 2 answer_2 = min( - np.sum(abs(positions - position) * (abs(positions - position) + 1) // 2) + sum(abs(p - position) * (abs(p - position) + 1) // 2 for p in positions) for position in range(min_position, max_position + 1) ) print(f"answer 2 is {answer_2}") diff --git a/src/holt59/aoc/2022/day12.py b/src/holt59/aoc/2022/day12.py index 66d1752..35a7116 100644 --- a/src/holt59/aoc/2022/day12.py +++ b/src/holt59/aoc/2022/day12.py @@ -122,8 +122,8 @@ lines = sys.stdin.read().splitlines() grid = [[ord(cell) - ord("a") for cell in line] for line in lines] -start: tuple[int, int] -end: tuple[int, int] +start: tuple[int, int] | None = None +end: tuple[int, int] | None = None # for part 2 start_s: list[tuple[int, int]] = [] @@ -138,6 +138,9 @@ for i_row, row in enumerate(grid): elif col == 0: start_s.append((i_row, i_col)) +assert start is not None +assert end is not None + # fix values grid[start[0]][start[1]] = 0 grid[end[0]][end[1]] = ord("z") - ord("a") diff --git a/src/holt59/aoc/2022/day15.py b/src/holt59/aoc/2022/day15.py index fd0fb0d..ba537aa 100644 --- a/src/holt59/aoc/2022/day15.py +++ b/src/holt59/aoc/2022/day15.py @@ -1,20 +1,22 @@ import sys +from typing import Any import numpy as np -import parse +import parse # type: ignore +from numpy.typing import NDArray def part1(sensor_to_beacon: dict[tuple[int, int], tuple[int, int]], row: int) -> int: - no_beacons_row_l: list[np.ndarray] = [] + no_beacons_row_l: list[NDArray[np.floating[Any]]] = [] for (sx, sy), (bx, by) in sensor_to_beacon.items(): d = abs(sx - bx) + abs(sy - by) # closest - no_beacons_row_l.append(sx - np.arange(0, d - abs(sy - row) + 1)) - no_beacons_row_l.append(sx + np.arange(0, d - abs(sy - row) + 1)) + no_beacons_row_l.append(sx - np.arange(0, d - abs(sy - row) + 1)) # type: ignore + no_beacons_row_l.append(sx + np.arange(0, d - abs(sy - row) + 1)) # type: ignore beacons_at_row = set(bx for (bx, by) in sensor_to_beacon.values() if by == row) - no_beacons_row = set(np.concatenate(no_beacons_row_l)).difference(beacons_at_row) + no_beacons_row = set(np.concatenate(no_beacons_row_l)).difference(beacons_at_row) # type: ignore return len(no_beacons_row) @@ -56,11 +58,12 @@ def part2_cplex( for (sx, sy), (bx, by) in sensor_to_beacon.items(): d = abs(sx - bx) + abs(sy - by) - m.add_constraint(m.abs(x - sx) + m.abs(y - sy) >= d + 1, ctname=f"ct_{sx}_{sy}") + m.add_constraint(m.abs(x - sx) + m.abs(y - sy) >= d + 1, ctname=f"ct_{sx}_{sy}") # type: ignore m.set_objective("min", x + y) s = m.solve() + assert s is not None vx = int(s.get_value(x)) vy = int(s.get_value(y)) @@ -72,7 +75,7 @@ lines = sys.stdin.read().splitlines() sensor_to_beacon: dict[tuple[int, int], tuple[int, int]] = {} for line in lines: - r = parse.parse( + r: dict[str, str] = parse.parse( # type: ignore "Sensor at x={sx}, y={sy}: closest beacon is at x={bx}, y={by}", line ) sensor_to_beacon[int(r["sx"]), int(r["sy"])] = (int(r["bx"]), int(r["by"])) diff --git a/src/holt59/aoc/2022/day18.py b/src/holt59/aoc/2022/day18.py index 9feff8b..c8d0f9a 100644 --- a/src/holt59/aoc/2022/day18.py +++ b/src/holt59/aoc/2022/day18.py @@ -1,5 +1,4 @@ import sys -from typing import FrozenSet import numpy as np diff --git a/src/holt59/aoc/2022/day19.py b/src/holt59/aoc/2022/day19.py index cd7860c..7d888fa 100644 --- a/src/holt59/aoc/2022/day19.py +++ b/src/holt59/aoc/2022/day19.py @@ -1,9 +1,9 @@ import sys -from typing import Literal +from typing import Any, Literal import numpy as np -import parse -from tqdm import tqdm +import parse # pyright: ignore[reportMissingTypeStubs] +from numpy.typing import NDArray Reagent = Literal["ore", "clay", "obsidian", "geode"] REAGENTS: tuple[Reagent, ...] = ( @@ -35,7 +35,7 @@ class State: self.robots = robots self.reagents = reagents - def __eq__(self, other) -> bool: + def __eq__(self, other: object) -> bool: return ( isinstance(other, State) and self.robots == other.robots @@ -66,7 +66,7 @@ lines = sys.stdin.read().splitlines() blueprints: list[dict[Reagent, IntOfReagent]] = [] for line in lines: - r = parse.parse( + r: list[int] = parse.parse( # type: ignore "Blueprint {}: " "Each ore robot costs {:d} ore. " "Each clay robot costs {:d} ore. " @@ -94,11 +94,12 @@ def run(blueprint: dict[Reagent, dict[Reagent, int]], max_time: int) -> int: name: max(blueprint[r].get(name, 0) for r in REAGENTS) for name in REAGENTS } - state_after_t: dict[int, set[State]] = {0: [State()]} + state_after_t: dict[int, set[State]] = {0: {State()}} for t in range(1, max_time + 1): # list of new states at the end of step t that we are going to prune later states_for_t: set[State] = set() + robots_that_can_be_built: list[Reagent] for state in state_after_t[t - 1]: robots_that_can_be_built = [ @@ -132,7 +133,7 @@ def run(blueprint: dict[Reagent, dict[Reagent, int]], max_time: int) -> int: for robot in robots_that_can_be_built: robots = state.robots.copy() robots[robot] += 1 - reagents = { + reagents: IntOfReagent = { reagent: state.reagents[reagent] + state.robots[reagent] - blueprint[robot].get(reagent, 0) @@ -151,7 +152,7 @@ def run(blueprint: dict[Reagent, dict[Reagent, int]], max_time: int) -> int: ] ) - to_keep = [] + to_keep: list[NDArray[np.integer[Any]]] = [] while len(np_states) > 0: first_dom = (np_states[1:] >= np_states[0]).all(axis=1).any() diff --git a/src/holt59/aoc/2023/day16.py b/src/holt59/aoc/2023/day16.py index 798f03c..2b986e1 100644 --- a/src/holt59/aoc/2023/day16.py +++ b/src/holt59/aoc/2023/day16.py @@ -56,7 +56,7 @@ def propagate( [() for _ in range(len(layout[0]))] for _ in range(len(layout)) ] - queue = [(start, direction)] + queue: list[tuple[tuple[int, int], Direction]] = [(start, direction)] while queue: (row, col), direction = queue.pop() diff --git a/src/holt59/aoc/2023/day19.py b/src/holt59/aoc/2023/day19.py index 4d63c65..b41b326 100644 --- a/src/holt59/aoc/2023/day19.py +++ b/src/holt59/aoc/2023/day19.py @@ -114,11 +114,12 @@ for workflow_s in workflows_s.split("\n"): for block in block_s[:-1].split(","): check: Check if (i := block.find(":")) >= 0: - check, target = ( + check = ( cast(Category, block[0]), cast(Literal["<", ">"], block[1]), int(block[2:i]), - ), block[i + 1 :] + ) + target = block[i + 1 :] else: check, target = None, block workflows[name].append((check, target)) diff --git a/src/holt59/aoc/2023/day22.py b/src/holt59/aoc/2023/day22.py index 1ee51cf..64199ea 100644 --- a/src/holt59/aoc/2023/day22.py +++ b/src/holt59/aoc/2023/day22.py @@ -19,7 +19,7 @@ def _name(i: int) -> str: def build_supports( - bricks: list[tuple[tuple[int, int, int], tuple[int, int, int]]] + bricks: list[tuple[tuple[int, int, int], tuple[int, int, int]]], ) -> tuple[dict[int, set[int]], dict[int, set[int]]]: # 1. compute locations where a brick of sand will land after falling by processing # them in sorted order of bottom z location diff --git a/src/holt59/aoc/2023/day23.py b/src/holt59/aoc/2023/day23.py index a9577c7..dd0e135 100644 --- a/src/holt59/aoc/2023/day23.py +++ b/src/holt59/aoc/2023/day23.py @@ -2,24 +2,34 @@ import logging import os import sys from collections import defaultdict +from typing import Literal, Sequence, TypeAlias, cast VERBOSE = os.getenv("AOC_VERBOSE") == "True" logging.basicConfig(level=logging.INFO if VERBOSE else logging.WARNING) -Direction = { +DirectionType: TypeAlias = Literal[">", "<", "^", "v", ".", "#"] + +Direction: dict[DirectionType, tuple[int, int]] = { ">": (0, +1), "<": (0, -1), "^": (-1, 0), "v": (+1, 0), } -Neighbors = {".": ((+1, 0), (-1, 0), (0, +1), (0, -1)), "#": ()} | { - k: (v,) for k, v in Direction.items() -} +Neighbors = cast( + "dict[DirectionType, tuple[tuple[int, int], ...]]", + { + ".": ((+1, 0), (-1, 0), (0, +1), (0, -1)), + "#": (), + } + | {k: (v,) for k, v in Direction.items()}, +) def neighbors( - grid: list[str], node: tuple[int, int], ignore: set[tuple[int, int]] = set() + grid: list[Sequence[DirectionType]], + node: tuple[int, int], + ignore: set[tuple[int, int]] = set(), ): """ Compute neighbors of the given node, ignoring the given set of nodes and considering @@ -51,7 +61,7 @@ def neighbors( def reachable( - grid: list[str], start: tuple[int, int], target: tuple[int, int] + grid: list[Sequence[DirectionType]], start: tuple[int, int], target: tuple[int, int] ) -> tuple[tuple[int, int], int]: """ Compute the next 'reachable' node in the grid, starting at the given node. @@ -75,7 +85,7 @@ def reachable( def compute_direct_links( - grid: list[str], start: tuple[int, int], target: tuple[int, int] + grid: list[Sequence[DirectionType]], start: tuple[int, int], target: tuple[int, int] ) -> dict[tuple[int, int], list[tuple[tuple[int, int], int]]]: if start == target: return {} @@ -85,7 +95,7 @@ def compute_direct_links( i, j = neighbor di, dj = Direction[grid[i][j]] - reach, distance = reachable(lines, (i + di, j + dj), target) + reach, distance = reachable(grid, (i + di, j + dj), target) direct[start].append((reach, distance + 2)) direct.update(compute_direct_links(grid, reach, target)) @@ -124,7 +134,7 @@ def longest_path_length( return max_distance -lines = sys.stdin.read().splitlines() +lines = cast(list[Sequence[DirectionType]], sys.stdin.read().splitlines()) n_rows, n_cols = len(lines), len(lines[0]) start = (0, 1) target = (len(lines) - 1, len(lines[0]) - 2) diff --git a/typings/docplex/__init__.pyi b/typings/docplex/__init__.pyi new file mode 100644 index 0000000..e69de29 diff --git a/typings/docplex/mp/__init__.pyi b/typings/docplex/mp/__init__.pyi new file mode 100644 index 0000000..e69de29 diff --git a/typings/docplex/mp/basic.pyi b/typings/docplex/mp/basic.pyi new file mode 100644 index 0000000..fa91c30 --- /dev/null +++ b/typings/docplex/mp/basic.pyi @@ -0,0 +1,8 @@ +from __future__ import annotations + +from typing import Literal + +from docplex.mp.operand import Operand + +class Expr(Operand): + def __pow__(self, power: Literal[0, 1, 2]) -> Expr: ... diff --git a/typings/docplex/mp/constants.pyi b/typings/docplex/mp/constants.pyi new file mode 100644 index 0000000..2197419 --- /dev/null +++ b/typings/docplex/mp/constants.pyi @@ -0,0 +1,25 @@ +from __future__ import annotations + +from enum import Enum + +class ObjectiveSense(Enum): + Minimize = ... + Maximize = ... + +class EffortLevel(Enum): + Auto = ... + CheckFeas = ... + SolveFixed = ... + SolveMIP = ... + Repair = ... + NoCheck = ... + +class WriteLevel(Enum): + Auto = ... + AllVars = ... + DiscreteVars = ... + NonZeroVars = ... + NonZeroDiscreteVars = ... + + def filter_zeros(self) -> bool: ... + def filter_nondiscrete(self) -> bool: ... diff --git a/typings/docplex/mp/constr.pyi b/typings/docplex/mp/constr.pyi new file mode 100644 index 0000000..8db8bd7 --- /dev/null +++ b/typings/docplex/mp/constr.pyi @@ -0,0 +1,15 @@ +from __future__ import annotations + +from docplex.mp.operand import LinearOperand + +class AbstractConstraint: ... +class BinaryConstraint(AbstractConstraint): ... +class LinearConstraint(BinaryConstraint, LinearOperand): ... +class RangeConstraint(AbstractConstraint): ... +class NotEqualConstraint(LinearConstraint): ... +class LogicalConstraint(AbstractConstraint): ... +class IndicatorConstraint(LogicalConstraint): ... +class EquivalenceConstraint(LogicalConstraint): ... +class IfThenConstraint(IndicatorConstraint): ... +class QuadraticConstraint(BinaryConstraint): ... +class PwlConstraint(AbstractConstraint): ... diff --git a/typings/docplex/mp/context.pyi b/typings/docplex/mp/context.pyi new file mode 100644 index 0000000..4f72eae --- /dev/null +++ b/typings/docplex/mp/context.pyi @@ -0,0 +1,3 @@ +from __future__ import annotations + +class Context: ... diff --git a/typings/docplex/mp/dvar.pyi b/typings/docplex/mp/dvar.pyi new file mode 100644 index 0000000..c86f8e7 --- /dev/null +++ b/typings/docplex/mp/dvar.pyi @@ -0,0 +1,49 @@ +from __future__ import annotations + +from typing import Final, overload + +from docplex.mp.basic import Expr +from docplex.mp.linear import LinearExpr, MonomialExpr +from docplex.mp.model import Model +from docplex.mp.operand import LinearOperand +from docplex.mp.quad import QuadExpr +from docplex.mp.vartype import VarType + +class Var(LinearOperand): + lb: float + ub: float + vartype: Final[VarType] + + def __init__( + self, + model: Model, + vartype: VarType, + name: str, + lb: float | None = None, + ub: float | None = None, + ) -> None: ... + def has_free_lb(self) -> bool: ... + def has_free_ub(self) -> bool: ... + def is_free(self) -> bool: ... + def set_lb(self, ub: float | None) -> None: ... + def set_ub(self, ub: float | None) -> None: ... + def is_binary(self) -> bool: ... + def is_integer(self) -> bool: ... + def is_continuous(self) -> bool: ... + def is_discrete(self) -> bool: ... + def __sub__(self, e: Var | float) -> LinearExpr: ... + def __rsub__(self, e: Var | float) -> LinearExpr: ... + def __neg__(self) -> MonomialExpr: ... + def __add__(self, other: Var | float) -> LinearExpr: ... + def __radd__(self, other: Var | float) -> LinearExpr: ... + @overload + def __mul__(self, other: float) -> MonomialExpr: ... + @overload + def __mul__(self, other: Var) -> QuadExpr: ... + @overload + def __mul__(self, other: Expr) -> Expr: ... + @overload + def __rmul__(self, other: float) -> MonomialExpr: ... + @overload + def __rmul__(self, other: Expr) -> Expr: ... + def __truediv__(self, other: float) -> MonomialExpr: ... diff --git a/typings/docplex/mp/functional.pyi b/typings/docplex/mp/functional.pyi new file mode 100644 index 0000000..2d61374 --- /dev/null +++ b/typings/docplex/mp/functional.pyi @@ -0,0 +1,39 @@ +from __future__ import annotations + +from typing import overload + +from docplex.mp.basic import Expr +from docplex.mp.dvar import Var +from docplex.mp.linear import LinearExpr +from docplex.mp.operand import LinearOperand +from docplex.mp.quad import QuadExpr + +class _FunctionalExpr(Expr, LinearOperand): + def __sub__(self, e: Var | float) -> LinearExpr: ... + def __rsub__(self, e: Var | float) -> LinearExpr: ... + def __neg__(self) -> LinearExpr: ... + def __add__(self, other: Var | float) -> LinearExpr: ... + def __radd__(self, other: Var | float) -> LinearExpr: ... + @overload + def __mul__(self, other: float) -> LinearExpr: ... + @overload + def __mul__(self, other: Var) -> QuadExpr: ... + @overload + def __mul__(self, other: Expr) -> LinearExpr: ... + @overload + def __rmul__(self, other: float) -> LinearExpr: ... + @overload + def __rmul__(self, other: Expr) -> LinearExpr: ... + def __div__(self, other: float) -> LinearExpr: ... + def __truediv__(self, other: float) -> LinearExpr: ... + +class UnaryFunctionalExpr(_FunctionalExpr): ... +class AbsExpr(UnaryFunctionalExpr): ... +class _SequenceExpr(_FunctionalExpr): ... +class MinimumExpr(_SequenceExpr): ... +class MaximumExpr(_SequenceExpr): ... +class LogicalNotExpr(UnaryFunctionalExpr): ... +class _LogicalSequenceExpr(_SequenceExpr): ... +class LogicalAndExpr(_LogicalSequenceExpr): ... +class LogicalOrExpr(_LogicalSequenceExpr): ... +class PwlExpr(UnaryFunctionalExpr): ... diff --git a/typings/docplex/mp/linear.pyi b/typings/docplex/mp/linear.pyi new file mode 100644 index 0000000..c01f934 --- /dev/null +++ b/typings/docplex/mp/linear.pyi @@ -0,0 +1,86 @@ +from __future__ import annotations + +from typing import overload + +from docplex.mp.basic import Expr +from docplex.mp.operand import LinearOperand +from docplex.mp.quad import QuadExpr + +class AbstractLinearExpr(LinearOperand, Expr): ... + +class MonomialExpr(AbstractLinearExpr): + def __sub__(self, e: LinearOperand | float) -> LinearExpr: ... + def __rsub__(self, e: LinearOperand | float) -> LinearExpr: ... + def __neg__(self) -> MonomialExpr: ... + def __add__(self, other: LinearOperand | float) -> LinearExpr: ... + def __radd__(self, other: LinearOperand | float) -> LinearExpr: ... + @overload + def __mul__(self, other: float) -> MonomialExpr: ... + @overload + def __mul__(self, other: LinearExpr) -> QuadExpr: ... + def __rmul__(self, other: float) -> MonomialExpr: ... + def __div__(self, other: float) -> MonomialExpr: ... + def __truediv__(self, e: float) -> MonomialExpr: ... + +class LinearExpr(AbstractLinearExpr): + def __sub__(self, e: LinearOperand | float) -> LinearExpr: ... + def __rsub__(self, e: LinearOperand | float) -> LinearExpr: ... + def __neg__(self) -> LinearExpr: ... + def __add__(self, e: LinearOperand | float) -> LinearExpr: ... + def __radd__(self, e: LinearOperand | float) -> LinearExpr: ... + @overload + def __mul__(self, e: float) -> LinearExpr: ... + @overload + def __mul__(self, e: LinearOperand) -> QuadExpr: ... + def __rmul__(self, e: float) -> LinearExpr: ... + def __div__(self, e: float) -> LinearExpr: ... + def __truediv__(self, e: float) -> LinearExpr: ... + +class ZeroExpr(AbstractLinearExpr): + @overload + def __sub__(self, e: float) -> ConstantExpr: ... + @overload + def __sub__(self, e: LinearOperand) -> LinearExpr: ... + @overload + def __rsub__(self, e: float) -> ConstantExpr: ... + @overload + def __rsub__(self, e: LinearOperand) -> LinearExpr: ... + @overload + def __add__(self, e: float) -> ConstantExpr: ... + @overload + def __add__(self, e: LinearOperand) -> LinearExpr: ... + @overload + def __radd__(self, e: float) -> ConstantExpr: ... + @overload + def __radd__(self, e: LinearOperand) -> LinearExpr: ... + def __neg__(self) -> ZeroExpr: ... + def __mul__(self, e: float | LinearOperand) -> ZeroExpr: ... + def __rmul__(self, e: float | LinearOperand) -> ZeroExpr: ... + def __div__(self, e: float) -> ZeroExpr: ... + def __truediv__(self, e: float) -> ZeroExpr: ... + +class ConstantExpr(AbstractLinearExpr): + @overload + def __sub__(self, e: float) -> ConstantExpr: ... + @overload + def __sub__(self, e: LinearOperand) -> LinearExpr: ... + @overload + def __rsub__(self, e: float) -> ConstantExpr: ... + @overload + def __rsub__(self, e: LinearOperand) -> LinearExpr: ... + @overload + def __add__(self, e: float) -> ConstantExpr: ... + @overload + def __add__(self, e: LinearOperand) -> LinearExpr: ... + @overload + def __radd__(self, e: float) -> ConstantExpr: ... + @overload + def __radd__(self, e: LinearOperand) -> LinearExpr: ... + def __neg__(self) -> ConstantExpr: ... + @overload + def __mul__(self, e: float) -> ConstantExpr: ... + @overload + def __mul__(self, e: LinearOperand) -> LinearExpr: ... + def __rmul__(self, e: float | LinearOperand) -> ConstantExpr: ... + def __div__(self, e: float) -> ConstantExpr: ... + def __truediv__(self, e: float) -> ConstantExpr: ... diff --git a/typings/docplex/mp/model.pyi b/typings/docplex/mp/model.pyi new file mode 100644 index 0000000..d9962d9 --- /dev/null +++ b/typings/docplex/mp/model.pyi @@ -0,0 +1,177 @@ +from __future__ import annotations + +from collections.abc import Callable, Iterable +from typing import Any, Iterator, Literal, Sequence, TextIO, TypeVar, overload + +from docplex.mp.basic import Expr +from docplex.mp.constants import EffortLevel, ObjectiveSense, WriteLevel +from docplex.mp.constr import AbstractConstraint +from docplex.mp.context import Context +from docplex.mp.dvar import Var +from docplex.mp.functional import ( + AbsExpr, + LogicalAndExpr, + LogicalNotExpr, + LogicalOrExpr, + MaximumExpr, + MinimumExpr, +) +from docplex.mp.linear import AbstractLinearExpr, ConstantExpr, LinearExpr, ZeroExpr +from docplex.mp.operand import LinearOperand +from docplex.mp.params.parameters import RootParameterGroup +from docplex.mp.progress import ProgressListener +from docplex.mp.solution import SolveSolution +from typing_extensions import TypeAlias + +_Key = TypeVar("_Key") +_Val = TypeVar("_Val") + +_MethodDictArg: TypeAlias = ( + dict[_Key, _Val] | list[_Val] | Callable[[_Key], _Val] | _Val +) +_ObjectiveSense: TypeAlias = ( + ObjectiveSense | Literal["min", "max", "minimize", "maximize", -1, 1] +) + +class Model: + def __init__( + self, name: str | None = None, context: Context | None = None, **kwargs: Any + ) -> None: ... + def binary_var(self, name: str | None = None) -> Var: ... + def binary_var_list( + self, + keys: int | Sequence[_Key], + name: _MethodDictArg[_Key, str] | None = None, + key_format: str | None = None, + ) -> list[Var]: ... + def binary_var_dict( + self, + keys: Iterable[_Key], + name: _MethodDictArg[_Key, str] | None = None, + key_format: str | None = None, + ) -> dict[_Key, Var]: ... + def integer_var( + self, lb: int | None = None, ub: int | None = None, name: str | None = None + ) -> Var: ... + def integer_var_list( + self, + keys: int | Sequence[_Key], + lb: _MethodDictArg[_Key, int] | None = None, + ub: _MethodDictArg[_Key, int] | None = None, + name: _MethodDictArg[_Key, str] | None = None, + key_format: str | None = None, + ) -> list[Var]: ... + def integer_var_dict( + self, + keys: Iterable[_Key], + lb: _MethodDictArg[_Key, int] | None = None, + ub: _MethodDictArg[_Key, int] | None = None, + name: _MethodDictArg[_Key, str] | None = None, + key_format: str | None = None, + ) -> dict[_Key, Var]: ... + def continuous_var( + self, lb: float | None = None, ub: float | None = None, name: str | None = None + ) -> Var: ... + def continuous_var_list( + self, + keys: int | Sequence[_Key], + lb: _MethodDictArg[_Key, float] | None = None, + ub: _MethodDictArg[_Key, float] | None = None, + name: _MethodDictArg[_Key, str] | None = None, + key_format: str | None = None, + ) -> list[Var]: ... + def continuous_var_dict( + self, + keys: Iterable[_Key], + lb: _MethodDictArg[_Key, float] | None = None, + ub: _MethodDictArg[_Key, float] | None = None, + name: _MethodDictArg[_Key, str] | None = None, + key_format: str | None = None, + ) -> dict[_Key, Var]: ... + def sum(self, args: Iterable[LinearOperand | float]) -> LinearExpr | ZeroExpr: ... + def sums(self, *args: LinearOperand | float) -> LinearExpr | ZeroExpr: ... + def add_constraint( + self, ct: AbstractConstraint, ctname: str | None = None + ) -> AbstractConstraint: ... + def add_constraints( + self, ct: Iterable[AbstractConstraint], names: Iterable[str] | None = None + ) -> list[AbstractConstraint]: ... + def remove_constraints( + self, + cts: Iterable[AbstractConstraint], + error: Literal["raise", "warn"] = "warn", + ) -> list[AbstractConstraint]: ... + @overload + def add( + self, ct: AbstractConstraint, name: str | None = None + ) -> AbstractConstraint: ... + @overload + def add( + self, ct: Iterable[AbstractConstraint], name: Iterable[str] | None = None + ) -> list[AbstractConstraint]: ... + def solve(self, **kwargs: Any) -> SolveSolution | None: ... + def set_objective(self, sense: _ObjectiveSense, expr: Expr | Var) -> None: ... + def set_objective_sense(self, sense: _ObjectiveSense) -> None: ... + def set_objective_expr(self, expr: Expr | Var) -> None: ... + def set_lex_multi_objective( + self, + sense: _ObjectiveSense, + exprs: Iterable[Expr | Var], + abstols: float | None = None, + reltols: float | None = None, + names: Iterable[str] | None = None, + ) -> None: ... + def get_objective_expr(self) -> Expr: ... + def add_mip_start( + self, + mip_start_sol: SolveSolution, + effort_level: EffortLevel | None = None, + write_level: WriteLevel | None = None, + complete_vars: bool = False, + eps_zero: float = 1e-6, + ) -> SolveSolution: ... + @property + def log_output(self) -> TextIO | bool: ... + @log_output.setter + def log_output(self, out: TextIO | bool) -> None: ... + def set_log_output(self, out: TextIO) -> None: ... + @property + def parameters(self) -> RootParameterGroup: ... + def problem_type(self) -> Literal["LP", "MILP", "QP", "MIQP", "QCP", "MIQCP"]: ... + def print_information(self) -> None: ... + def logical_and( + self, *args: Var | Expr | LinearOperand + ) -> Var | AbstractLinearExpr | ConstantExpr | LogicalAndExpr: ... + def logical_or( + self, *args: Var | Expr | LinearOperand + ) -> Var | AbstractLinearExpr | ConstantExpr | LogicalOrExpr: ... + def logical_not(self, other: Var | Expr) -> LogicalNotExpr: ... + def abs(self, e: Var | Expr | float) -> AbsExpr: ... + def min(self, *args: Var | Expr | Sequence[Var | Expr]) -> MinimumExpr: ... + def max(self, *args: Var | Expr | Sequence[Var | Expr]) -> MaximumExpr: ... + def if_then( + self, + if_ct: AbstractConstraint, + then_ct: AbstractConstraint, + negate: bool = ..., + ) -> AbstractConstraint: ... + def indicator_constraint( + self, + binary_var: Var, + linear_ct: AbstractConstraint, + active_value: Literal[0, 1] = ..., + name: str | None = ..., + ) -> AbstractConstraint: ... + def add_indicator( + self, + binary_var: Var, + linear_ct: AbstractConstraint, + active_value: Literal[0, 1] = ..., + name: str | None = ..., + ) -> AbstractConstraint: ... + def add_progress_listener(self, listener: ProgressListener) -> None: ... + def remove_progress_listener(self, listener: ProgressListener) -> None: ... + @property + def number_of_progress_listeners(self) -> int: ... + def iter_progress_listeners(self) -> Iterator[ProgressListener]: ... + def clear_progress_listeners(self) -> None: ... diff --git a/typings/docplex/mp/operand.pyi b/typings/docplex/mp/operand.pyi new file mode 100644 index 0000000..ba1dd42 --- /dev/null +++ b/typings/docplex/mp/operand.pyi @@ -0,0 +1,12 @@ +from __future__ import annotations + +from docplex.mp.constr import BinaryConstraint, NotEqualConstraint + +class Operand: + def negate(self) -> Operand: ... + def __le__(self, other: Operand | float) -> BinaryConstraint: ... + def __ge__(self, other: Operand | float) -> BinaryConstraint: ... + def __eq__(self, other: Operand | float) -> BinaryConstraint: ... # type: ignore + +class LinearOperand(Operand): + def __ne__(self, other: Operand | float) -> NotEqualConstraint: ... # type: ignore diff --git a/typings/docplex/mp/params/__init__.pyi b/typings/docplex/mp/params/__init__.pyi new file mode 100644 index 0000000..e69de29 diff --git a/typings/docplex/mp/params/parameters.pyi b/typings/docplex/mp/params/parameters.pyi new file mode 100644 index 0000000..1940437 --- /dev/null +++ b/typings/docplex/mp/params/parameters.pyi @@ -0,0 +1,272 @@ +from __future__ import annotations + +class ParameterGroup: + def __init__( + self, name: str, parent_group: ParameterGroup | None = None + ) -> None: ... + +class _BarrierGroup(ParameterGroup): + class _BarrierLimitsGroup(ParameterGroup): + corrections: int = ... + growth: float = ... + iteration: int = ... + objrange: float = ... + + algorithm: int = ... + colnonzeros: int = ... + convergetol: float = ... + crossover: int = ... + display: int = ... + ordering: int = ... + qcpconvergetol: float = ... + startalg: int = ... + + limits: _BarrierLimitsGroup = ... + +class _BendersGroup(ParameterGroup): + class _BendersTolerancesGroup(ParameterGroup): + feasibilitycut: float = ... + optimalitycut: float = ... + + strategy: int = ... + workeralgorithm: int = ... + + tolerances: _BendersTolerancesGroup = ... + +class _ConflictGroup(ParameterGroup): + algorithm: int = ... + display: int = ... + +class _EmphasisGroup(ParameterGroup): + memory: bool = ... + mip: int = ... + numerical: bool = ... + +class _FeasoptGroup(ParameterGroup): + mode: int = ... + tolerance: float = ... + +class _MipGroup(ParameterGroup): + class _MipCutsGroup(ParameterGroup): + bqp: int = ... + cliques: int = ... + covers: int = ... + disjunctive: int = ... + flowcovers: int = ... + gomory: int = ... + gubcovers: int = ... + implied: int = ... + liftproj: int = ... + localimplied: int = ... + mcfcut: int = ... + mircut: int = ... + nodecuts: int = ... + pathcut: int = ... + rlt: int = ... + zerohalfcut: int = ... + + class _MipLimitsGroup(ParameterGroup): + aggforcut: int = ... + auxrootthreads: int = ... + lowerobjstop: float = ... + cutpasses: int = ... + cutsfactor: float = ... + eachcutlimit: int = ... + gomorycand: int = ... + gomorypass: int = ... + nodes: int = ... + populate: int = ... + probedettime: float = ... + probetime: float = ... + repairtries: int = ... + solutions: int = ... + strongcand: int = ... + strongit: int = ... + treememory: float = ... + upperobjstop: float = ... + + class _MipPolishafterGroup(ParameterGroup): + absmipgap: float = ... + dettime: float = ... + mipgap: float = ... + nodes: int = ... + solutions: int = ... + time: float = ... + + class _MipPoolGroup(ParameterGroup): + absgap: float = ... + capacity: int = ... + intensity: int = ... + relgap: float = ... + replace: int = ... + + class _MipstrategyGroup(ParameterGroup): + backtrack: float = ... + bbinterval: int = ... + branch: int = ... + dive: int = ... + file: int = ... + fpheur: int = ... + heuristiceffort: float = ... + heuristicfreq: int = ... + kappastats: int = ... + lbheur: bool = ... + miqcpstrat: int = ... + nodeselect: int = ... + order: bool = ... + presolvenode: int = ... + probe: int = ... + rinsheur: int = ... + search: int = ... + startalgorithm: int = ... + subalgorithm: int = ... + variableselect: int = ... + + class _MipSubmipGroup(ParameterGroup): + startalg: int = ... + subalg: int = ... + nodelimit: int = ... + scale: int = ... + + class _MipTolerancesGroup(ParameterGroup): + absmipgap: float = ... + linearization: float = ... + integrality: float = ... + lowercutoff: float = ... + mipgap: float = ... + objdifference: float = ... + relobjdifference: float = ... + uppercutoff: float = ... + + display: int = ... + interval: int = ... + ordertype: int = ... + + cuts: _MipCutsGroup = ... + limits: _MipLimitsGroup = ... + polishafter: _MipPolishafterGroup = ... + pool: _MipPoolGroup = ... + strategy: _MipstrategyGroup = ... + submip: _MipSubmipGroup = ... + tolerances: _MipTolerancesGroup = ... + +class _MultiobjectiveGroup(ParameterGroup): + display: int = ... + +class _NetworkGroup(ParameterGroup): + class _NetworkTolerancesGroup(ParameterGroup): + feasibility: float = ... + optimality: float = ... + + display: int = ... + iterations: int = ... + netfind: int = ... + pricing: int = ... + + tolerances: _NetworkTolerancesGroup = ... + +class _OutputGroup(ParameterGroup): + intsolfileprefix: str = ... + mpslong: bool = ... + writelevel: int = ... + +class _PreprocessingGroup(ParameterGroup): + aggregator: int = ... + boundstrength: int = ... + coeffreduce: int = ... + dependency: int = ... + dual: int = ... + fill: int = ... + folding: int = ... + numpass: int = ... + presolve: bool = ... + qcpduals: int = ... + qpmakepsd: bool = ... + qtolin: int = ... + reduce: int = ... + reformulations: int = ... + relax: int = ... + repeatpresolve: int = ... + sos1reform: int = ... + sos2reform: int = ... + symmetry: int = ... + +class _ReadGroup(ParameterGroup): + datacheck: int = ... + fileencoding: str = ... + scale: int = ... + warninglimit: int = ... + +class _SiftingGroup(ParameterGroup): + algorithm: int = ... + simplex: bool = ... + display: int = ... + iterations: int = ... + +class _SimplexGroup(ParameterGroup): + class _SimplexLimitsGroup(ParameterGroup): + iterations: int = ... + lowerobj: float = ... + perturbation: int = ... + singularity: int = ... + upperobj: float = ... + + class _SimplexPerturbationGroup(ParameterGroup): + constant: float = ... + indicator: bool = ... + + class _SimplexTolerancesGroup(ParameterGroup): + feasibility: float = ... + markowitz: float = ... + optimality: float = ... + + crash: int = ... + dgradient: int = ... + display: int = ... + dynamicrows: int = ... + pgradient: int = ... + pricing: int = ... + refactor: int = ... + + limits: _SimplexLimitsGroup = ... + perturbation: _SimplexPerturbationGroup = ... + tolerances: _SimplexTolerancesGroup = ... + +class _TuneGroup(ParameterGroup): + dettimelimit: float = ... + display: int = ... + measure: int = ... + repeat: int = ... + timelimit: float = ... + +class RootParameterGroup(ParameterGroup): + advance: int = ... + clocktype: int = ... + dettimelimit: float = ... + lpmethod: int = ... + optimalitytarget: int = ... + parallel: int = ... + paramdisplay: bool = ... + qpmethod: int = ... + randomseed: int = ... + record: bool = ... + solutiontype: int = ... + threads: int = ... + timelimit: float = ... + workdir: str = ... + workmem: float = ... + + barrier: _BarrierGroup = ... + benders: _BendersGroup = ... + conflict: _ConflictGroup = ... + emphasis: _EmphasisGroup = ... + feasopt: _FeasoptGroup = ... + mip: _MipGroup = ... + multiobjective: _MultiobjectiveGroup = ... + network: _NetworkGroup = ... + output: _OutputGroup = ... + preprocessing: _PreprocessingGroup = ... + read: _ReadGroup = ... + sifting: _SiftingGroup = ... + simplex: _SimplexGroup = ... + tune: _TuneGroup = ... diff --git a/typings/docplex/mp/progress.pyi b/typings/docplex/mp/progress.pyi new file mode 100644 index 0000000..fa11e8b --- /dev/null +++ b/typings/docplex/mp/progress.pyi @@ -0,0 +1,192 @@ +from collections.abc import Mapping, Sequence +from enum import Enum +from typing import Callable, Iterator, Literal, NamedTuple, Protocol + +from docplex.mp.model import Model +from docplex.mp.solution import SolveSolution + +class ProgressData(NamedTuple): + has_incumbent: bool + current_objective: float | None + best_bound: float + mip_gap: float | None + current_nb_iterations: int + current_nb_nodes: int + remaining_nb_nodes: int + time: float + det_time: float + +class ProgressClock(Enum): + All = ... + Solutions = ... + BestBound = ... + Objective = ... + Gap = ... + + @property + def listens_to_solution(self) -> bool: ... + +class _Filter(Protocol): + def accept(self, data: ProgressData) -> bool: ... + def reset(self) -> None: ... + +class _AbstractProgressListener: + def abort(self) -> None: ... + def notify_start(self) -> None: ... + +class ProgressListener(_AbstractProgressListener): + """The base class for progress listeners.""" + + def __init__( + self, + clock_ar: ProgressClock = ..., + absdiff: float | None = None, + reldiff: float | None = None, + ) -> None: ... + @property + def clock(self) -> ProgressClock: ... + @property + def abs_diff(self) -> float: ... + @property + def relative_diff(self) -> float: ... + @property + def current_progress_data(self) -> ProgressData | None: ... + def accept(self, pdata: ProgressData) -> bool: ... + def requires_solution(self) -> bool: ... + def notify_solution(self, s: SolveSolution) -> None: ... + def notify_jobid(self, jobid: int) -> None: ... + def notify_end(self, status: int, objective: float | None) -> None: ... + def notify_progress(self, progress_data: ProgressData) -> None: ... + +class FilterAcceptAll: + def accept(self, pdata: ProgressData) -> bool: ... + def reset(self) -> None: ... + +class FilterAcceptAllSolutions(object): + def accept(self, pdata: ProgressData) -> bool: ... + def reset(self) -> None: ... + +class Watcher: + def __init__( + self, + name: str, + absdiff: float, + reldiff: float, + update_fn: Callable[[ProgressData], bool], + ) -> None: ... + def reset(self) -> None: ... + def accept(self, progress_data: ProgressData) -> bool: ... + def sync(self, pdata: ProgressData) -> None: ... + +class ClockFilter: + def __init__( + self, + level: ProgressClock, + obj_absdiff: float, + bbound_absdiff: float, + obj_reldiff: float = ..., + bbound_reldiff: float = ..., + node_delta: int = ..., + ) -> None: ... + def accept(self, progress_data: ProgressData) -> bool: ... + def peek(self, progress_data: ProgressData) -> Watcher | None: ... + def reset(self) -> None: ... + +class TextProgressListener(ProgressListener): + def __init__( + self, + clock: ProgressClock = ..., + gap_fmt: str | None = ..., + obj_fmt: str | None = ..., + absdiff: float | None = ..., + reldiff: float | None = ..., + ) -> None: ... + def notify_start(self) -> None: ... + def notify_progress(self, progress_data: ProgressData) -> None: ... + +class ProgressDataRecorder(ProgressListener): + """A specialized class of ProgressListener, which collects all ProgressData it receives.""" + + def __init__( + self, + clock: ProgressClock = ..., + absdiff: float | None = ..., + reldiff: float | None = ..., + ) -> None: ... + def notify_start(self) -> None: ... + def notify_progress(self, progress_data: ProgressData) -> None: ... + @property + def number_of_records(self) -> int: ... + @property + def iter_recorded(self) -> Iterator[ProgressData]: ... + @property + def recorded(self) -> Sequence[ProgressData]: ... + +class SolutionListener(ProgressListener): + def __init__( + self, + clock: Literal[ + ProgressClock.Solutions, ProgressClock.Objective, ProgressClock.Gap + ] = ..., + absdiff: float | None = ..., + reldiff: float | None = ..., + ) -> None: ... + def requires_solution(self) -> bool: ... + def notify_solution(self, s: SolveSolution) -> None: ... + def notify_start(self) -> None: ... + def accept(self, pdata: ProgressData) -> bool: ... + +class SolutionRecorder(SolutionListener): + def __init__( + self, + clock: Literal[ + ProgressClock.Solutions, ProgressClock.Objective, ProgressClock.Gap + ] = ..., + absdiff: float | None = ..., + reldiff: float | None = ..., + ) -> None: ... + def notify_start(self) -> None: ... + def notify_solution(self, s: SolveSolution) -> None: ... + def iter_solutions(self) -> Iterator[SolveSolution]: ... + @property + def number_of_solutions(self) -> int: ... + @property + def current_solution(self) -> SolveSolution | None: ... + +class FunctionalSolutionListener(SolutionListener): + def __init__( + self, + solution_fn: Callable[[SolveSolution], None], + clock: Literal[ + ProgressClock.Solutions, ProgressClock.Objective, ProgressClock.Gap + ] = ..., + absdiff: float | None = ..., + reldiff: float | None = ..., + ) -> None: ... + def notify_solution(self, s: SolveSolution) -> None: ... + +class KpiListener(SolutionListener): + def __init__( + self, + model: Model, + clock: Literal[ + ProgressClock.Solutions, ProgressClock.Objective, ProgressClock.Gap + ] = ..., + absdiff: float | None = ..., + reldiff: float | None = ..., + ) -> None: ... + def publish(self, kpi_dict: Mapping[str, float | str]) -> None: ... + def notify_solution(self, s: SolveSolution) -> None: ... + +class KpiPrinter(KpiListener): + def __init__( + self, + model: Model, + clock: Literal[ + ProgressClock.Solutions, ProgressClock.Objective, ProgressClock.Gap + ] = ..., + absdiff: float | None = ..., + reldiff: float | None = ..., + kpi_format: str = ..., + ) -> None: ... + def publish(self, kpi_dict: Mapping[str, float | str]) -> None: ... diff --git a/typings/docplex/mp/quad.pyi b/typings/docplex/mp/quad.pyi new file mode 100644 index 0000000..18b55e7 --- /dev/null +++ b/typings/docplex/mp/quad.pyi @@ -0,0 +1,5 @@ +from __future__ import annotations + +from docplex.mp.basic import Expr + +class QuadExpr(Expr): ... diff --git a/typings/docplex/mp/sdetails.pyi b/typings/docplex/mp/sdetails.pyi new file mode 100644 index 0000000..b68fd4c --- /dev/null +++ b/typings/docplex/mp/sdetails.pyi @@ -0,0 +1,29 @@ +from __future__ import annotations + +class SolveDetails: + @property + def time(self) -> float: ... + @property + def status_code(self) -> int: ... + @property + def status(self) -> str: ... + @property + def problem_type(self) -> str: ... + @property + def columns(self) -> int: ... + @property + def nb_linear_nonzeros(self) -> int: ... + @property + def mip_relative_gap(self) -> float: ... + + gap = mip_relative_gap + + @property + def best_bound(self) -> float: ... + @property + def nb_iterations(self) -> int | tuple[int, ...]: ... + @property + def nb_nodes_processed(self) -> int | tuple[int, ...]: ... + def print_information(self) -> None: ... + def to_string(self) -> str: ... + def has_hit_limit(self) -> bool: ... diff --git a/typings/docplex/mp/solution.pyi b/typings/docplex/mp/solution.pyi new file mode 100644 index 0000000..0feeb13 --- /dev/null +++ b/typings/docplex/mp/solution.pyi @@ -0,0 +1,49 @@ +from __future__ import annotations + +from collections.abc import Iterable, Mapping +from typing import Literal, Sequence, TypeVar + +from docplex.mp.constants import WriteLevel +from docplex.mp.dvar import Var +from docplex.mp.model import Model +from docplex.mp.sdetails import SolveDetails +from typing_extensions import TypeAlias + +_Key = TypeVar("_Key") +_SolvedBy: TypeAlias = Literal["cplex_local", "cplex_cloud"] | None + +class SolveSolution: + def __init__( + self, + model: Model, + var_value_map: Mapping[Var, float] | None = None, + obj: Sequence[float] | float | None = None, + blended_obj_by_priority: Sequence[float] | None = None, + name: str | None = None, + solved_by: _SolvedBy = None, + keep_zeros: bool = True, + ) -> None: ... + @property + def problem_name(self) -> str: ... + @property + def solved_by(self) -> _SolvedBy: ... + @property + def name(self) -> str: ... + @property + def solve_details(self) -> SolveDetails: ... + def get_objective_value(self) -> float | list[float]: ... + def get_value(self, arg: Var) -> float: ... + def get_values(self, var_seq: Iterable[Var]) -> list[float]: ... + def get_value_list(self, dvars: Iterable[Var]) -> list[float]: ... + def get_value_dict( + self, + var_dict: Mapping[_Key, Var], + keep_zeros: bool = True, + precision: float = 1e-6, + ) -> dict[_Key, float]: ... + def as_mip_start( + self, + write_level: WriteLevel = ..., + complete_vars: bool = False, + eps_zero: float = 1e-6, + ) -> SolveSolution: ... diff --git a/typings/docplex/mp/vartype.pyi b/typings/docplex/mp/vartype.pyi new file mode 100644 index 0000000..6f7c762 --- /dev/null +++ b/typings/docplex/mp/vartype.pyi @@ -0,0 +1,11 @@ +from __future__ import annotations + +class VarType: + def is_semi_type(self) -> bool: ... + def is_discrete(self) -> bool: ... + +class BinaryVarType(VarType): ... +class ContinuousVarType(VarType): ... +class IntegerVarType(VarType): ... +class SemiContinuousVarType(VarType): ... +class SemiDiscreteVarType(VarType): ...