From f2f11bfc3ccc92f7d044fe688b080b775c69963e Mon Sep 17 00:00:00 2001 From: WeetHet Date: Sun, 8 Sep 2024 21:36:16 +0300 Subject: [PATCH 01/23] wip --- poetry.lock | 475 ++++++++++--------- tests/test_dafny_generate copy.py | 26 + tests/test_nagini_generate.py | 26 + verified_cogen/main.py | 3 + verified_cogen/runners/__init__.py | 85 ++-- verified_cogen/runners/generate.py | 39 +- verified_cogen/runners/generic.py | 15 +- verified_cogen/runners/invariants.py | 18 +- verified_cogen/runners/languages/__init__.py | 8 + verified_cogen/runners/languages/dafny.py | 21 + verified_cogen/runners/languages/language.py | 78 +++ verified_cogen/runners/languages/nagini.py | 19 + verified_cogen/runners/validating.py | 86 +--- 13 files changed, 515 insertions(+), 384 deletions(-) create mode 100644 tests/test_dafny_generate copy.py create mode 100644 tests/test_nagini_generate.py create mode 100644 verified_cogen/runners/languages/__init__.py create mode 100644 verified_cogen/runners/languages/dafny.py create mode 100644 verified_cogen/runners/languages/language.py create mode 100644 verified_cogen/runners/languages/nagini.py diff --git a/poetry.lock b/poetry.lock index 152c79b..639ff71 100644 --- a/poetry.lock +++ b/poetry.lock @@ -116,13 +116,13 @@ test = ["coverage (>=7)", "hypothesis", "pytest"] [[package]] name = "certifi" -version = "2024.7.4" +version = "2024.8.30" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, - {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, + {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, + {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, ] [[package]] @@ -251,13 +251,13 @@ test = ["pytest (>=6)"] [[package]] name = "grazie-api-gateway-client" -version = "0.1.3" +version = "0.1.7" description = "Api client for Grazie services" optional = false python-versions = ">=3.8" files = [ - {file = "grazie_api_gateway_client-0.1.3-py3-none-any.whl", hash = "sha256:1563fdaed062788624e19f4a0f6063937799134a12d621548a591ef43f01c569"}, - {file = "grazie_api_gateway_client-0.1.3.tar.gz", hash = "sha256:9cc033f5507255fc18cb080fd8afd8f4aaf90bb417d8966690cbc12df5038fde"}, + {file = "grazie_api_gateway_client-0.1.7-py3-none-any.whl", hash = "sha256:8d3ff4a5293df8949280a77edfa00ba16c40fc239a0be6089eec7f7a6636215c"}, + {file = "grazie_api_gateway_client-0.1.7.tar.gz", hash = "sha256:317806f5403a00b03973cd38f1f9066a3e8279bd022606a786720df7675e664a"}, ] [package.dependencies] @@ -307,13 +307,13 @@ trio = ["trio (>=0.22.0,<0.26.0)"] [[package]] name = "httpx" -version = "0.27.0" +version = "0.27.2" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" files = [ - {file = "httpx-0.27.0-py3-none-any.whl", hash = "sha256:71d5465162c13681bff01ad59b2cc68dd838ea1f10e51574bac27103f00c91a5"}, - {file = "httpx-0.27.0.tar.gz", hash = "sha256:a0cb88a46f32dc874e04ee956e4c2764aba2aa228f650b06788ba6bda2962ab5"}, + {file = "httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0"}, + {file = "httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2"}, ] [package.dependencies] @@ -328,16 +328,17 @@ brotli = ["brotli", "brotlicffi"] cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] +zstd = ["zstandard (>=0.18.0)"] [[package]] name = "idna" -version = "3.7" +version = "3.8" description = "Internationalized Domain Names in Applications (IDNA)" optional = false -python-versions = ">=3.5" +python-versions = ">=3.6" files = [ - {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, - {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, + {file = "idna-3.8-py3-none-any.whl", hash = "sha256:050b4e5baadcd44d760cedbd2b8e639f2ff89bbc7a5730fcc662954303377aac"}, + {file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"}, ] [[package]] @@ -428,122 +429,123 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pydantic" -version = "2.8.2" +version = "2.9.0" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.8.2-py3-none-any.whl", hash = "sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8"}, - {file = "pydantic-2.8.2.tar.gz", hash = "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a"}, + {file = "pydantic-2.9.0-py3-none-any.whl", hash = "sha256:f66a7073abd93214a20c5f7b32d56843137a7a2e70d02111f3be287035c45370"}, + {file = "pydantic-2.9.0.tar.gz", hash = "sha256:c7a8a9fdf7d100afa49647eae340e2d23efa382466a8d177efcd1381e9be5598"}, ] [package.dependencies] annotated-types = ">=0.4.0" -pydantic-core = "2.20.1" +pydantic-core = "2.23.2" typing-extensions = [ {version = ">=4.12.2", markers = "python_version >= \"3.13\""}, {version = ">=4.6.1", markers = "python_version < \"3.13\""}, ] +tzdata = {version = "*", markers = "python_version >= \"3.9\""} [package.extras] email = ["email-validator (>=2.0.0)"] [[package]] name = "pydantic-core" -version = "2.20.1" +version = "2.23.2" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3acae97ffd19bf091c72df4d726d552c473f3576409b2a7ca36b2f535ffff4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41f4c96227a67a013e7de5ff8f20fb496ce573893b7f4f2707d065907bffdbd6"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f239eb799a2081495ea659d8d4a43a8f42cd1fe9ff2e7e436295c38a10c286a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53e431da3fc53360db73eedf6f7124d1076e1b4ee4276b36fb25514544ceb4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1f62b2413c3a0e846c3b838b2ecd6c7a19ec6793b2a522745b0869e37ab5bc1"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d41e6daee2813ecceea8eda38062d69e280b39df793f5a942fa515b8ed67953"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d482efec8b7dc6bfaedc0f166b2ce349df0011f5d2f1f25537ced4cfc34fd98"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e93e1a4b4b33daed65d781a57a522ff153dcf748dee70b40c7258c5861e1768a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7c4ea22b6739b162c9ecaaa41d718dfad48a244909fe7ef4b54c0b530effc5a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4f2790949cf385d985a31984907fecb3896999329103df4e4983a4a41e13e840"}, - {file = "pydantic_core-2.20.1-cp310-none-win32.whl", hash = "sha256:5e999ba8dd90e93d57410c5e67ebb67ffcaadcea0ad973240fdfd3a135506250"}, - {file = "pydantic_core-2.20.1-cp310-none-win_amd64.whl", hash = "sha256:512ecfbefef6dac7bc5eaaf46177b2de58cdf7acac8793fe033b24ece0b9566c"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d2a8fa9d6d6f891f3deec72f5cc668e6f66b188ab14bb1ab52422fe8e644f312"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:175873691124f3d0da55aeea1d90660a6ea7a3cfea137c38afa0a5ffabe37b88"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37eee5b638f0e0dcd18d21f59b679686bbd18917b87db0193ae36f9c23c355fc"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25e9185e2d06c16ee438ed39bf62935ec436474a6ac4f9358524220f1b236e43"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:150906b40ff188a3260cbee25380e7494ee85048584998c1e66df0c7a11c17a6"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ad4aeb3e9a97286573c03df758fc7627aecdd02f1da04516a86dc159bf70121"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f3ed29cd9f978c604708511a1f9c2fdcb6c38b9aae36a51905b8811ee5cbf1"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0dae11d8f5ded51699c74d9548dcc5938e0804cc8298ec0aa0da95c21fff57b"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b"}, - {file = "pydantic_core-2.20.1-cp311-none-win32.whl", hash = "sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a"}, - {file = "pydantic_core-2.20.1-cp311-none-win_amd64.whl", hash = "sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd"}, - {file = "pydantic_core-2.20.1-cp312-none-win32.whl", hash = "sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688"}, - {file = "pydantic_core-2.20.1-cp312-none-win_amd64.whl", hash = "sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0"}, - {file = "pydantic_core-2.20.1-cp313-none-win32.whl", hash = "sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e"}, - {file = "pydantic_core-2.20.1-cp313-none-win_amd64.whl", hash = "sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:4745f4ac52cc6686390c40eaa01d48b18997cb130833154801a442323cc78f91"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a8ad4c766d3f33ba8fd692f9aa297c9058970530a32c728a2c4bfd2616d3358b"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41e81317dd6a0127cabce83c0c9c3fbecceae981c8391e6f1dec88a77c8a569a"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04024d270cf63f586ad41fff13fde4311c4fc13ea74676962c876d9577bcc78f"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaad4ff2de1c3823fddf82f41121bdf453d922e9a238642b1dedb33c4e4f98ad"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26ab812fa0c845df815e506be30337e2df27e88399b985d0bb4e3ecfe72df31c"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c5ebac750d9d5f2706654c638c041635c385596caf68f81342011ddfa1e5598"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2aafc5a503855ea5885559eae883978c9b6d8c8993d67766ee73d82e841300dd"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4868f6bd7c9d98904b748a2653031fc9c2f85b6237009d475b1008bfaeb0a5aa"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa2f457b4af386254372dfa78a2eda2563680d982422641a85f271c859df1987"}, - {file = "pydantic_core-2.20.1-cp38-none-win32.whl", hash = "sha256:225b67a1f6d602de0ce7f6c1c3ae89a4aa25d3de9be857999e9124f15dab486a"}, - {file = "pydantic_core-2.20.1-cp38-none-win_amd64.whl", hash = "sha256:6b507132dcfc0dea440cce23ee2182c0ce7aba7054576efc65634f080dbe9434"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b03f7941783b4c4a26051846dea594628b38f6940a2fdc0df00b221aed39314c"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1eedfeb6089ed3fad42e81a67755846ad4dcc14d73698c120a82e4ccf0f1f9f6"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:635fee4e041ab9c479e31edda27fcf966ea9614fff1317e280d99eb3e5ab6fe2"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77bf3ac639c1ff567ae3b47f8d4cc3dc20f9966a2a6dd2311dcc055d3d04fb8a"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ed1b0132f24beeec5a78b67d9388656d03e6a7c837394f99257e2d55b461611"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6514f963b023aeee506678a1cf821fe31159b925c4b76fe2afa94cc70b3222b"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10d4204d8ca33146e761c79f83cc861df20e7ae9f6487ca290a97702daf56006"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d036c7187b9422ae5b262badb87a20a49eb6c5238b2004e96d4da1231badef1"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9ebfef07dbe1d93efb94b4700f2d278494e9162565a54f124c404a5656d7ff09"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6b9d9bb600328a1ce523ab4f454859e9d439150abb0906c5a1983c146580ebab"}, - {file = "pydantic_core-2.20.1-cp39-none-win32.whl", hash = "sha256:784c1214cb6dd1e3b15dd8b91b9a53852aed16671cc3fbe4786f4f1db07089e2"}, - {file = "pydantic_core-2.20.1-cp39-none-win_amd64.whl", hash = "sha256:d2fe69c5434391727efa54b47a1e7986bb0186e72a41b203df8f5b0a19a4f669"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a45f84b09ac9c3d35dfcf6a27fd0634d30d183205230a0ebe8373a0e8cfa0906"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d02a72df14dfdbaf228424573a07af10637bd490f0901cee872c4f434a735b94"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2b27e6af28f07e2f195552b37d7d66b150adbaa39a6d327766ffd695799780f"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084659fac3c83fd674596612aeff6041a18402f1e1bc19ca39e417d554468482"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:242b8feb3c493ab78be289c034a1f659e8826e2233786e36f2893a950a719bb6"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:38cf1c40a921d05c5edc61a785c0ddb4bed67827069f535d794ce6bcded919fc"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e0bbdd76ce9aa5d4209d65f2b27fc6e5ef1312ae6c5333c26db3f5ade53a1e99"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:254ec27fdb5b1ee60684f91683be95e5133c994cc54e86a0b0963afa25c8f8a6"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:407653af5617f0757261ae249d3fba09504d7a71ab36ac057c938572d1bc9331"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c693e916709c2465b02ca0ad7b387c4f8423d1db7b4649c551f27a529181c5ad"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b5ff4911aea936a47d9376fd3ab17e970cc543d1b68921886e7f64bd28308d1"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177f55a886d74f1808763976ac4efd29b7ed15c69f4d838bbd74d9d09cf6fa86"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:964faa8a861d2664f0c7ab0c181af0bea66098b1919439815ca8803ef136fc4e"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4dd484681c15e6b9a977c785a345d3e378d72678fd5f1f3c0509608da24f2ac0"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f6d6cff3538391e8486a431569b77921adfcdef14eb18fbf19b7c0a5294d4e6a"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a6d511cc297ff0883bc3708b465ff82d7560193169a8b93260f74ecb0a5e08a7"}, - {file = "pydantic_core-2.20.1.tar.gz", hash = "sha256:26ca695eeee5f9f1aeeb211ffc12f10bcb6f71e2989988fda61dabd65db878d4"}, + {file = "pydantic_core-2.23.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7d0324a35ab436c9d768753cbc3c47a865a2cbc0757066cb864747baa61f6ece"}, + {file = "pydantic_core-2.23.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:276ae78153a94b664e700ac362587c73b84399bd1145e135287513442e7dfbc7"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:964c7aa318da542cdcc60d4a648377ffe1a2ef0eb1e996026c7f74507b720a78"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1cf842265a3a820ebc6388b963ead065f5ce8f2068ac4e1c713ef77a67b71f7c"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae90b9e50fe1bd115b24785e962b51130340408156d34d67b5f8f3fa6540938e"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ae65fdfb8a841556b52935dfd4c3f79132dc5253b12c0061b96415208f4d622"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c8aa40f6ca803f95b1c1c5aeaee6237b9e879e4dfb46ad713229a63651a95fb"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c53100c8ee5a1e102766abde2158077d8c374bee0639201f11d3032e3555dfbc"}, + {file = "pydantic_core-2.23.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d6b9dd6aa03c812017411734e496c44fef29b43dba1e3dd1fa7361bbacfc1354"}, + {file = "pydantic_core-2.23.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b18cf68255a476b927910c6873d9ed00da692bb293c5b10b282bd48a0afe3ae2"}, + {file = "pydantic_core-2.23.2-cp310-none-win32.whl", hash = "sha256:e460475719721d59cd54a350c1f71c797c763212c836bf48585478c5514d2854"}, + {file = "pydantic_core-2.23.2-cp310-none-win_amd64.whl", hash = "sha256:5f3cf3721eaf8741cffaf092487f1ca80831202ce91672776b02b875580e174a"}, + {file = "pydantic_core-2.23.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7ce8e26b86a91e305858e018afc7a6e932f17428b1eaa60154bd1f7ee888b5f8"}, + {file = "pydantic_core-2.23.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7e9b24cca4037a561422bf5dc52b38d390fb61f7bfff64053ce1b72f6938e6b2"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:753294d42fb072aa1775bfe1a2ba1012427376718fa4c72de52005a3d2a22178"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:257d6a410a0d8aeb50b4283dea39bb79b14303e0fab0f2b9d617701331ed1515"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c8319e0bd6a7b45ad76166cc3d5d6a36c97d0c82a196f478c3ee5346566eebfd"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7a05c0240f6c711eb381ac392de987ee974fa9336071fb697768dfdb151345ce"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d5b0ff3218858859910295df6953d7bafac3a48d5cd18f4e3ed9999efd2245f"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:96ef39add33ff58cd4c112cbac076726b96b98bb8f1e7f7595288dcfb2f10b57"}, + {file = "pydantic_core-2.23.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0102e49ac7d2df3379ef8d658d3bc59d3d769b0bdb17da189b75efa861fc07b4"}, + {file = "pydantic_core-2.23.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a6612c2a844043e4d10a8324c54cdff0042c558eef30bd705770793d70b224aa"}, + {file = "pydantic_core-2.23.2-cp311-none-win32.whl", hash = "sha256:caffda619099cfd4f63d48462f6aadbecee3ad9603b4b88b60cb821c1b258576"}, + {file = "pydantic_core-2.23.2-cp311-none-win_amd64.whl", hash = "sha256:6f80fba4af0cb1d2344869d56430e304a51396b70d46b91a55ed4959993c0589"}, + {file = "pydantic_core-2.23.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:4c83c64d05ffbbe12d4e8498ab72bdb05bcc1026340a4a597dc647a13c1605ec"}, + {file = "pydantic_core-2.23.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6294907eaaccf71c076abdd1c7954e272efa39bb043161b4b8aa1cd76a16ce43"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a801c5e1e13272e0909c520708122496647d1279d252c9e6e07dac216accc41"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cc0c316fba3ce72ac3ab7902a888b9dc4979162d320823679da270c2d9ad0cad"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b06c5d4e8701ac2ba99a2ef835e4e1b187d41095a9c619c5b185c9068ed2a49"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:82764c0bd697159fe9947ad59b6db6d7329e88505c8f98990eb07e84cc0a5d81"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b1a195efd347ede8bcf723e932300292eb13a9d2a3c1f84eb8f37cbbc905b7f"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b7efb12e5071ad8d5b547487bdad489fbd4a5a35a0fc36a1941517a6ad7f23e0"}, + {file = "pydantic_core-2.23.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5dd0ec5f514ed40e49bf961d49cf1bc2c72e9b50f29a163b2cc9030c6742aa73"}, + {file = "pydantic_core-2.23.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:820f6ee5c06bc868335e3b6e42d7ef41f50dfb3ea32fbd523ab679d10d8741c0"}, + {file = "pydantic_core-2.23.2-cp312-none-win32.whl", hash = "sha256:3713dc093d5048bfaedbba7a8dbc53e74c44a140d45ede020dc347dda18daf3f"}, + {file = "pydantic_core-2.23.2-cp312-none-win_amd64.whl", hash = "sha256:e1895e949f8849bc2757c0dbac28422a04be031204df46a56ab34bcf98507342"}, + {file = "pydantic_core-2.23.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:da43cbe593e3c87d07108d0ebd73771dc414488f1f91ed2e204b0370b94b37ac"}, + {file = "pydantic_core-2.23.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:64d094ea1aa97c6ded4748d40886076a931a8bf6f61b6e43e4a1041769c39dd2"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:084414ffe9a85a52940b49631321d636dadf3576c30259607b75516d131fecd0"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:043ef8469f72609c4c3a5e06a07a1f713d53df4d53112c6d49207c0bd3c3bd9b"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3649bd3ae6a8ebea7dc381afb7f3c6db237fc7cebd05c8ac36ca8a4187b03b30"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6db09153d8438425e98cdc9a289c5fade04a5d2128faff8f227c459da21b9703"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5668b3173bb0b2e65020b60d83f5910a7224027232c9f5dc05a71a1deac9f960"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1c7b81beaf7c7ebde978377dc53679c6cba0e946426fc7ade54251dfe24a7604"}, + {file = "pydantic_core-2.23.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:ae579143826c6f05a361d9546446c432a165ecf1c0b720bbfd81152645cb897d"}, + {file = "pydantic_core-2.23.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:19f1352fe4b248cae22a89268720fc74e83f008057a652894f08fa931e77dced"}, + {file = "pydantic_core-2.23.2-cp313-none-win32.whl", hash = "sha256:e1a79ad49f346aa1a2921f31e8dbbab4d64484823e813a002679eaa46cba39e1"}, + {file = "pydantic_core-2.23.2-cp313-none-win_amd64.whl", hash = "sha256:582871902e1902b3c8e9b2c347f32a792a07094110c1bca6c2ea89b90150caac"}, + {file = "pydantic_core-2.23.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:743e5811b0c377eb830150d675b0847a74a44d4ad5ab8845923d5b3a756d8100"}, + {file = "pydantic_core-2.23.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6650a7bbe17a2717167e3e23c186849bae5cef35d38949549f1c116031b2b3aa"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56e6a12ec8d7679f41b3750ffa426d22b44ef97be226a9bab00a03365f217b2b"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:810ca06cca91de9107718dc83d9ac4d2e86efd6c02cba49a190abcaf33fb0472"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:785e7f517ebb9890813d31cb5d328fa5eda825bb205065cde760b3150e4de1f7"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ef71ec876fcc4d3bbf2ae81961959e8d62f8d74a83d116668409c224012e3af"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d50ac34835c6a4a0d456b5db559b82047403c4317b3bc73b3455fefdbdc54b0a"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16b25a4a120a2bb7dab51b81e3d9f3cde4f9a4456566c403ed29ac81bf49744f"}, + {file = "pydantic_core-2.23.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:41ae8537ad371ec018e3c5da0eb3f3e40ee1011eb9be1da7f965357c4623c501"}, + {file = "pydantic_core-2.23.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:07049ec9306ec64e955b2e7c40c8d77dd78ea89adb97a2013d0b6e055c5ee4c5"}, + {file = "pydantic_core-2.23.2-cp38-none-win32.whl", hash = "sha256:086c5db95157dc84c63ff9d96ebb8856f47ce113c86b61065a066f8efbe80acf"}, + {file = "pydantic_core-2.23.2-cp38-none-win_amd64.whl", hash = "sha256:67b6655311b00581914aba481729971b88bb8bc7996206590700a3ac85e457b8"}, + {file = "pydantic_core-2.23.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:358331e21a897151e54d58e08d0219acf98ebb14c567267a87e971f3d2a3be59"}, + {file = "pydantic_core-2.23.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c4d9f15ffe68bcd3898b0ad7233af01b15c57d91cd1667f8d868e0eacbfe3f87"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0123655fedacf035ab10c23450163c2f65a4174f2bb034b188240a6cf06bb123"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e6e3ccebdbd6e53474b0bb7ab8b88e83c0cfe91484b25e058e581348ee5a01a5"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc535cb898ef88333cf317777ecdfe0faac1c2a3187ef7eb061b6f7ecf7e6bae"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aab9e522efff3993a9e98ab14263d4e20211e62da088298089a03056980a3e69"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05b366fb8fe3d8683b11ac35fa08947d7b92be78ec64e3277d03bd7f9b7cda79"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7568f682c06f10f30ef643a1e8eec4afeecdafde5c4af1b574c6df079e96f96c"}, + {file = "pydantic_core-2.23.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cdd02a08205dc90238669f082747612cb3c82bd2c717adc60f9b9ecadb540f80"}, + {file = "pydantic_core-2.23.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1a2ab4f410f4b886de53b6bddf5dd6f337915a29dd9f22f20f3099659536b2f6"}, + {file = "pydantic_core-2.23.2-cp39-none-win32.whl", hash = "sha256:0448b81c3dfcde439551bb04a9f41d7627f676b12701865c8a2574bcea034437"}, + {file = "pydantic_core-2.23.2-cp39-none-win_amd64.whl", hash = "sha256:4cebb9794f67266d65e7e4cbe5dcf063e29fc7b81c79dc9475bd476d9534150e"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e758d271ed0286d146cf7c04c539a5169a888dd0b57026be621547e756af55bc"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f477d26183e94eaafc60b983ab25af2a809a1b48ce4debb57b343f671b7a90b6"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da3131ef2b940b99106f29dfbc30d9505643f766704e14c5d5e504e6a480c35e"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:329a721253c7e4cbd7aad4a377745fbcc0607f9d72a3cc2102dd40519be75ed2"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7706e15cdbf42f8fab1e6425247dfa98f4a6f8c63746c995d6a2017f78e619ae"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e64ffaf8f6e17ca15eb48344d86a7a741454526f3a3fa56bc493ad9d7ec63936"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:dd59638025160056687d598b054b64a79183f8065eae0d3f5ca523cde9943940"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:12625e69b1199e94b0ae1c9a95d000484ce9f0182f9965a26572f054b1537e44"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5d813fd871b3d5c3005157622ee102e8908ad6011ec915a18bd8fde673c4360e"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1eb37f7d6a8001c0f86dc8ff2ee8d08291a536d76e49e78cda8587bb54d8b329"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ce7eaf9a98680b4312b7cebcdd9352531c43db00fca586115845df388f3c465"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f087879f1ffde024dd2788a30d55acd67959dcf6c431e9d3682d1c491a0eb474"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ce883906810b4c3bd90e0ada1f9e808d9ecf1c5f0b60c6b8831d6100bcc7dd6"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:a8031074a397a5925d06b590121f8339d34a5a74cfe6970f8a1124eb8b83f4ac"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:23af245b8f2f4ee9e2c99cb3f93d0e22fb5c16df3f2f643f5a8da5caff12a653"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c57e493a0faea1e4c38f860d6862ba6832723396c884fbf938ff5e9b224200e2"}, + {file = "pydantic_core-2.23.2.tar.gz", hash = "sha256:95d6bf449a1ac81de562d65d180af5d8c19672793c81877a2eda8fde5d08f2fd"}, ] [package.dependencies] @@ -551,13 +553,13 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pytest" -version = "8.3.1" +version = "8.3.2" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.3.1-py3-none-any.whl", hash = "sha256:e9600ccf4f563976e2c99fa02c7624ab938296551f280835ee6516df8bc4ae8c"}, - {file = "pytest-8.3.1.tar.gz", hash = "sha256:7e8e5c5abd6e93cb1cc151f23e57adc31fcf8cfd2a3ff2da63e23f732de35db6"}, + {file = "pytest-8.3.2-py3-none-any.whl", hash = "sha256:4ba08f9ae7dcf84ded419494d229b48d0903ea6407b030eaec46df5e6a73bba5"}, + {file = "pytest-8.3.2.tar.gz", hash = "sha256:c132345d12ce551242c87269de812483f5bcc87cdbb4722e48487ba194f9fdce"}, ] [package.dependencies] @@ -609,137 +611,141 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "rpds-py" -version = "0.19.0" +version = "0.20.0" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.8" files = [ - {file = "rpds_py-0.19.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:fb37bd599f031f1a6fb9e58ec62864ccf3ad549cf14bac527dbfa97123edcca4"}, - {file = "rpds_py-0.19.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3384d278df99ec2c6acf701d067147320b864ef6727405d6470838476e44d9e8"}, - {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e54548e0be3ac117595408fd4ca0ac9278fde89829b0b518be92863b17ff67a2"}, - {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8eb488ef928cdbc05a27245e52de73c0d7c72a34240ef4d9893fdf65a8c1a955"}, - {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5da93debdfe27b2bfc69eefb592e1831d957b9535e0943a0ee8b97996de21b5"}, - {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:79e205c70afddd41f6ee79a8656aec738492a550247a7af697d5bd1aee14f766"}, - {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:959179efb3e4a27610e8d54d667c02a9feaa86bbabaf63efa7faa4dfa780d4f1"}, - {file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a6e605bb9edcf010f54f8b6a590dd23a4b40a8cb141255eec2a03db249bc915b"}, - {file = "rpds_py-0.19.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9133d75dc119a61d1a0ded38fb9ba40a00ef41697cc07adb6ae098c875195a3f"}, - {file = "rpds_py-0.19.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dd36b712d35e757e28bf2f40a71e8f8a2d43c8b026d881aa0c617b450d6865c9"}, - {file = "rpds_py-0.19.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:354f3a91718489912f2e0fc331c24eaaf6a4565c080e00fbedb6015857c00582"}, - {file = "rpds_py-0.19.0-cp310-none-win32.whl", hash = "sha256:ebcbf356bf5c51afc3290e491d3722b26aaf5b6af3c1c7f6a1b757828a46e336"}, - {file = "rpds_py-0.19.0-cp310-none-win_amd64.whl", hash = "sha256:75a6076289b2df6c8ecb9d13ff79ae0cad1d5fb40af377a5021016d58cd691ec"}, - {file = "rpds_py-0.19.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6d45080095e585f8c5097897313def60caa2046da202cdb17a01f147fb263b81"}, - {file = "rpds_py-0.19.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5c9581019c96f865483d031691a5ff1cc455feb4d84fc6920a5ffc48a794d8a"}, - {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1540d807364c84516417115c38f0119dfec5ea5c0dd9a25332dea60b1d26fc4d"}, - {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9e65489222b410f79711dc3d2d5003d2757e30874096b2008d50329ea4d0f88c"}, - {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9da6f400eeb8c36f72ef6646ea530d6d175a4f77ff2ed8dfd6352842274c1d8b"}, - {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:37f46bb11858717e0efa7893c0f7055c43b44c103e40e69442db5061cb26ed34"}, - {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:071d4adc734de562bd11d43bd134330fb6249769b2f66b9310dab7460f4bf714"}, - {file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9625367c8955e4319049113ea4f8fee0c6c1145192d57946c6ffcd8fe8bf48dd"}, - {file = "rpds_py-0.19.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e19509145275d46bc4d1e16af0b57a12d227c8253655a46bbd5ec317e941279d"}, - {file = "rpds_py-0.19.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d438e4c020d8c39961deaf58f6913b1bf8832d9b6f62ec35bd93e97807e9cbc"}, - {file = "rpds_py-0.19.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90bf55d9d139e5d127193170f38c584ed3c79e16638890d2e36f23aa1630b952"}, - {file = "rpds_py-0.19.0-cp311-none-win32.whl", hash = "sha256:8d6ad132b1bc13d05ffe5b85e7a01a3998bf3a6302ba594b28d61b8c2cf13aaf"}, - {file = "rpds_py-0.19.0-cp311-none-win_amd64.whl", hash = "sha256:7ec72df7354e6b7f6eb2a17fa6901350018c3a9ad78e48d7b2b54d0412539a67"}, - {file = "rpds_py-0.19.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:5095a7c838a8647c32aa37c3a460d2c48debff7fc26e1136aee60100a8cd8f68"}, - {file = "rpds_py-0.19.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f2f78ef14077e08856e788fa482107aa602636c16c25bdf59c22ea525a785e9"}, - {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7cc6cb44f8636fbf4a934ca72f3e786ba3c9f9ba4f4d74611e7da80684e48d2"}, - {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf902878b4af334a09de7a45badbff0389e7cf8dc2e4dcf5f07125d0b7c2656d"}, - {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:688aa6b8aa724db1596514751ffb767766e02e5c4a87486ab36b8e1ebc1aedac"}, - {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57dbc9167d48e355e2569346b5aa4077f29bf86389c924df25c0a8b9124461fb"}, - {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b4cf5a9497874822341c2ebe0d5850fed392034caadc0bad134ab6822c0925b"}, - {file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8a790d235b9d39c70a466200d506bb33a98e2ee374a9b4eec7a8ac64c2c261fa"}, - {file = "rpds_py-0.19.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1d16089dfa58719c98a1c06f2daceba6d8e3fb9b5d7931af4a990a3c486241cb"}, - {file = "rpds_py-0.19.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bc9128e74fe94650367fe23f37074f121b9f796cabbd2f928f13e9661837296d"}, - {file = "rpds_py-0.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c8f77e661ffd96ff104bebf7d0f3255b02aa5d5b28326f5408d6284c4a8b3248"}, - {file = "rpds_py-0.19.0-cp312-none-win32.whl", hash = "sha256:5f83689a38e76969327e9b682be5521d87a0c9e5a2e187d2bc6be4765f0d4600"}, - {file = "rpds_py-0.19.0-cp312-none-win_amd64.whl", hash = "sha256:06925c50f86da0596b9c3c64c3837b2481337b83ef3519e5db2701df695453a4"}, - {file = "rpds_py-0.19.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:52e466bea6f8f3a44b1234570244b1cff45150f59a4acae3fcc5fd700c2993ca"}, - {file = "rpds_py-0.19.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e21cc693045fda7f745c790cb687958161ce172ffe3c5719ca1764e752237d16"}, - {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b31f059878eb1f5da8b2fd82480cc18bed8dcd7fb8fe68370e2e6285fa86da6"}, - {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1dd46f309e953927dd018567d6a9e2fb84783963650171f6c5fe7e5c41fd5666"}, - {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34a01a4490e170376cd79258b7f755fa13b1a6c3667e872c8e35051ae857a92b"}, - {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bcf426a8c38eb57f7bf28932e68425ba86def6e756a5b8cb4731d8e62e4e0223"}, - {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f68eea5df6347d3f1378ce992d86b2af16ad7ff4dcb4a19ccdc23dea901b87fb"}, - {file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dab8d921b55a28287733263c0e4c7db11b3ee22aee158a4de09f13c93283c62d"}, - {file = "rpds_py-0.19.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:6fe87efd7f47266dfc42fe76dae89060038f1d9cb911f89ae7e5084148d1cc08"}, - {file = "rpds_py-0.19.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:535d4b52524a961d220875688159277f0e9eeeda0ac45e766092bfb54437543f"}, - {file = "rpds_py-0.19.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:8b1a94b8afc154fbe36978a511a1f155f9bd97664e4f1f7a374d72e180ceb0ae"}, - {file = "rpds_py-0.19.0-cp38-none-win32.whl", hash = "sha256:7c98298a15d6b90c8f6e3caa6457f4f022423caa5fa1a1ca7a5e9e512bdb77a4"}, - {file = "rpds_py-0.19.0-cp38-none-win_amd64.whl", hash = "sha256:b0da31853ab6e58a11db3205729133ce0df26e6804e93079dee095be3d681dc1"}, - {file = "rpds_py-0.19.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5039e3cef7b3e7a060de468a4a60a60a1f31786da94c6cb054e7a3c75906111c"}, - {file = "rpds_py-0.19.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab1932ca6cb8c7499a4d87cb21ccc0d3326f172cfb6a64021a889b591bb3045c"}, - {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2afd2164a1e85226fcb6a1da77a5c8896c18bfe08e82e8ceced5181c42d2179"}, - {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b1c30841f5040de47a0046c243fc1b44ddc87d1b12435a43b8edff7e7cb1e0d0"}, - {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f757f359f30ec7dcebca662a6bd46d1098f8b9fb1fcd661a9e13f2e8ce343ba1"}, - {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15e65395a59d2e0e96caf8ee5389ffb4604e980479c32742936ddd7ade914b22"}, - {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb0f6eb3a320f24b94d177e62f4074ff438f2ad9d27e75a46221904ef21a7b05"}, - {file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b228e693a2559888790936e20f5f88b6e9f8162c681830eda303bad7517b4d5a"}, - {file = "rpds_py-0.19.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2575efaa5d949c9f4e2cdbe7d805d02122c16065bfb8d95c129372d65a291a0b"}, - {file = "rpds_py-0.19.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:5c872814b77a4e84afa293a1bee08c14daed1068b2bb1cc312edbf020bbbca2b"}, - {file = "rpds_py-0.19.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:850720e1b383df199b8433a20e02b25b72f0fded28bc03c5bd79e2ce7ef050be"}, - {file = "rpds_py-0.19.0-cp39-none-win32.whl", hash = "sha256:ce84a7efa5af9f54c0aa7692c45861c1667080814286cacb9958c07fc50294fb"}, - {file = "rpds_py-0.19.0-cp39-none-win_amd64.whl", hash = "sha256:1c26da90b8d06227d7769f34915913911222d24ce08c0ab2d60b354e2d9c7aff"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:75969cf900d7be665ccb1622a9aba225cf386bbc9c3bcfeeab9f62b5048f4a07"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8445f23f13339da640d1be8e44e5baf4af97e396882ebbf1692aecd67f67c479"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5a7c1062ef8aea3eda149f08120f10795835fc1c8bc6ad948fb9652a113ca55"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:462b0c18fbb48fdbf980914a02ee38c423a25fcc4cf40f66bacc95a2d2d73bc8"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3208f9aea18991ac7f2b39721e947bbd752a1abbe79ad90d9b6a84a74d44409b"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3444fe52b82f122d8a99bf66777aed6b858d392b12f4c317da19f8234db4533"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88cb4bac7185a9f0168d38c01d7a00addece9822a52870eee26b8d5b61409213"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6b130bd4163c93798a6b9bb96be64a7c43e1cec81126ffa7ffaa106e1fc5cef5"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:a707b158b4410aefb6b054715545bbb21aaa5d5d0080217290131c49c2124a6e"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:dc9ac4659456bde7c567107556ab065801622396b435a3ff213daef27b495388"}, - {file = "rpds_py-0.19.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:81ea573aa46d3b6b3d890cd3c0ad82105985e6058a4baed03cf92518081eec8c"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3f148c3f47f7f29a79c38cc5d020edcb5ca780020fab94dbc21f9af95c463581"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0906357f90784a66e89ae3eadc2654f36c580a7d65cf63e6a616e4aec3a81be"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f629ecc2db6a4736b5ba95a8347b0089240d69ad14ac364f557d52ad68cf94b0"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c6feacd1d178c30e5bc37184526e56740342fd2aa6371a28367bad7908d454fc"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae8b6068ee374fdfab63689be0963333aa83b0815ead5d8648389a8ded593378"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78d57546bad81e0da13263e4c9ce30e96dcbe720dbff5ada08d2600a3502e526"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8b6683a37338818646af718c9ca2a07f89787551057fae57c4ec0446dc6224b"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e8481b946792415adc07410420d6fc65a352b45d347b78fec45d8f8f0d7496f0"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:bec35eb20792ea64c3c57891bc3ca0bedb2884fbac2c8249d9b731447ecde4fa"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:aa5476c3e3a402c37779e95f7b4048db2cb5b0ed0b9d006983965e93f40fe05a"}, - {file = "rpds_py-0.19.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:19d02c45f2507b489fd4df7b827940f1420480b3e2e471e952af4d44a1ea8e34"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a3e2fd14c5d49ee1da322672375963f19f32b3d5953f0615b175ff7b9d38daed"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:93a91c2640645303e874eada51f4f33351b84b351a689d470f8108d0e0694210"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5b9fc03bf76a94065299d4a2ecd8dfbae4ae8e2e8098bbfa6ab6413ca267709"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a4b07cdf3f84310c08c1de2c12ddadbb7a77568bcb16e95489f9c81074322ed"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba0ed0dc6763d8bd6e5de5cf0d746d28e706a10b615ea382ac0ab17bb7388633"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:474bc83233abdcf2124ed3f66230a1c8435896046caa4b0b5ab6013c640803cc"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:329c719d31362355a96b435f4653e3b4b061fcc9eba9f91dd40804ca637d914e"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef9101f3f7b59043a34f1dccbb385ca760467590951952d6701df0da9893ca0c"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:0121803b0f424ee2109d6e1f27db45b166ebaa4b32ff47d6aa225642636cd834"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:8344127403dea42f5970adccf6c5957a71a47f522171fafaf4c6ddb41b61703a"}, - {file = "rpds_py-0.19.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:443cec402ddd650bb2b885113e1dcedb22b1175c6be223b14246a714b61cd521"}, - {file = "rpds_py-0.19.0.tar.gz", hash = "sha256:4fdc9afadbeb393b4bbbad75481e0ea78e4469f2e1d713a90811700830b553a9"}, + {file = "rpds_py-0.20.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3ad0fda1635f8439cde85c700f964b23ed5fc2d28016b32b9ee5fe30da5c84e2"}, + {file = "rpds_py-0.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9bb4a0d90fdb03437c109a17eade42dfbf6190408f29b2744114d11586611d6f"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6377e647bbfd0a0b159fe557f2c6c602c159fc752fa316572f012fc0bf67150"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb851b7df9dda52dc1415ebee12362047ce771fc36914586b2e9fcbd7d293b3e"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e0f80b739e5a8f54837be5d5c924483996b603d5502bfff79bf33da06164ee2"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a8c94dad2e45324fc74dce25e1645d4d14df9a4e54a30fa0ae8bad9a63928e3"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8e604fe73ba048c06085beaf51147eaec7df856824bfe7b98657cf436623daf"}, + {file = "rpds_py-0.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:df3de6b7726b52966edf29663e57306b23ef775faf0ac01a3e9f4012a24a4140"}, + {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf258ede5bc22a45c8e726b29835b9303c285ab46fc7c3a4cc770736b5304c9f"}, + {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:55fea87029cded5df854ca7e192ec7bdb7ecd1d9a3f63d5c4eb09148acf4a7ce"}, + {file = "rpds_py-0.20.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ae94bd0b2f02c28e199e9bc51485d0c5601f58780636185660f86bf80c89af94"}, + {file = "rpds_py-0.20.0-cp310-none-win32.whl", hash = "sha256:28527c685f237c05445efec62426d285e47a58fb05ba0090a4340b73ecda6dee"}, + {file = "rpds_py-0.20.0-cp310-none-win_amd64.whl", hash = "sha256:238a2d5b1cad28cdc6ed15faf93a998336eb041c4e440dd7f902528b8891b399"}, + {file = "rpds_py-0.20.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ac2f4f7a98934c2ed6505aead07b979e6f999389f16b714448fb39bbaa86a489"}, + {file = "rpds_py-0.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:220002c1b846db9afd83371d08d239fdc865e8f8c5795bbaec20916a76db3318"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d7919548df3f25374a1f5d01fbcd38dacab338ef5f33e044744b5c36729c8db"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:758406267907b3781beee0f0edfe4a179fbd97c0be2e9b1154d7f0a1279cf8e5"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3d61339e9f84a3f0767b1995adfb171a0d00a1185192718a17af6e124728e0f5"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1259c7b3705ac0a0bd38197565a5d603218591d3f6cee6e614e380b6ba61c6f6"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c1dc0f53856b9cc9a0ccca0a7cc61d3d20a7088201c0937f3f4048c1718a209"}, + {file = "rpds_py-0.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7e60cb630f674a31f0368ed32b2a6b4331b8350d67de53c0359992444b116dd3"}, + {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dbe982f38565bb50cb7fb061ebf762c2f254ca3d8c20d4006878766e84266272"}, + {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:514b3293b64187172bc77c8fb0cdae26981618021053b30d8371c3a902d4d5ad"}, + {file = "rpds_py-0.20.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d0a26ffe9d4dd35e4dfdd1e71f46401cff0181c75ac174711ccff0459135fa58"}, + {file = "rpds_py-0.20.0-cp311-none-win32.whl", hash = "sha256:89c19a494bf3ad08c1da49445cc5d13d8fefc265f48ee7e7556839acdacf69d0"}, + {file = "rpds_py-0.20.0-cp311-none-win_amd64.whl", hash = "sha256:c638144ce971df84650d3ed0096e2ae7af8e62ecbbb7b201c8935c370df00a2c"}, + {file = "rpds_py-0.20.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a84ab91cbe7aab97f7446652d0ed37d35b68a465aeef8fc41932a9d7eee2c1a6"}, + {file = "rpds_py-0.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:56e27147a5a4c2c21633ff8475d185734c0e4befd1c989b5b95a5d0db699b21b"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2580b0c34583b85efec8c5c5ec9edf2dfe817330cc882ee972ae650e7b5ef739"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b80d4a7900cf6b66bb9cee5c352b2d708e29e5a37fe9bf784fa97fc11504bf6c"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:50eccbf054e62a7b2209b28dc7a22d6254860209d6753e6b78cfaeb0075d7bee"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:49a8063ea4296b3a7e81a5dfb8f7b2d73f0b1c20c2af401fb0cdf22e14711a96"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea438162a9fcbee3ecf36c23e6c68237479f89f962f82dae83dc15feeceb37e4"}, + {file = "rpds_py-0.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:18d7585c463087bddcfa74c2ba267339f14f2515158ac4db30b1f9cbdb62c8ef"}, + {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d4c7d1a051eeb39f5c9547e82ea27cbcc28338482242e3e0b7768033cb083821"}, + {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e4df1e3b3bec320790f699890d41c59d250f6beda159ea3c44c3f5bac1976940"}, + {file = "rpds_py-0.20.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2cf126d33a91ee6eedc7f3197b53e87a2acdac63602c0f03a02dd69e4b138174"}, + {file = "rpds_py-0.20.0-cp312-none-win32.whl", hash = "sha256:8bc7690f7caee50b04a79bf017a8d020c1f48c2a1077ffe172abec59870f1139"}, + {file = "rpds_py-0.20.0-cp312-none-win_amd64.whl", hash = "sha256:0e13e6952ef264c40587d510ad676a988df19adea20444c2b295e536457bc585"}, + {file = "rpds_py-0.20.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:aa9a0521aeca7d4941499a73ad7d4f8ffa3d1affc50b9ea11d992cd7eff18a29"}, + {file = "rpds_py-0.20.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4a1f1d51eccb7e6c32ae89243cb352389228ea62f89cd80823ea7dd1b98e0b91"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a86a9b96070674fc88b6f9f71a97d2c1d3e5165574615d1f9168ecba4cecb24"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6c8ef2ebf76df43f5750b46851ed1cdf8f109d7787ca40035fe19fbdc1acc5a7"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b74b25f024b421d5859d156750ea9a65651793d51b76a2e9238c05c9d5f203a9"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57eb94a8c16ab08fef6404301c38318e2c5a32216bf5de453e2714c964c125c8"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1940dae14e715e2e02dfd5b0f64a52e8374a517a1e531ad9412319dc3ac7879"}, + {file = "rpds_py-0.20.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d20277fd62e1b992a50c43f13fbe13277a31f8c9f70d59759c88f644d66c619f"}, + {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:06db23d43f26478303e954c34c75182356ca9aa7797d22c5345b16871ab9c45c"}, + {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b2a5db5397d82fa847e4c624b0c98fe59d2d9b7cf0ce6de09e4d2e80f8f5b3f2"}, + {file = "rpds_py-0.20.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5a35df9f5548fd79cb2f52d27182108c3e6641a4feb0f39067911bf2adaa3e57"}, + {file = "rpds_py-0.20.0-cp313-none-win32.whl", hash = "sha256:fd2d84f40633bc475ef2d5490b9c19543fbf18596dcb1b291e3a12ea5d722f7a"}, + {file = "rpds_py-0.20.0-cp313-none-win_amd64.whl", hash = "sha256:9bc2d153989e3216b0559251b0c260cfd168ec78b1fac33dd485750a228db5a2"}, + {file = "rpds_py-0.20.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:f2fbf7db2012d4876fb0d66b5b9ba6591197b0f165db8d99371d976546472a24"}, + {file = "rpds_py-0.20.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1e5f3cd7397c8f86c8cc72d5a791071431c108edd79872cdd96e00abd8497d29"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce9845054c13696f7af7f2b353e6b4f676dab1b4b215d7fe5e05c6f8bb06f965"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c3e130fd0ec56cb76eb49ef52faead8ff09d13f4527e9b0c400307ff72b408e1"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b16aa0107ecb512b568244ef461f27697164d9a68d8b35090e9b0c1c8b27752"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa7f429242aae2947246587d2964fad750b79e8c233a2367f71b554e9447949c"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af0fc424a5842a11e28956e69395fbbeab2c97c42253169d87e90aac2886d751"}, + {file = "rpds_py-0.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b8c00a3b1e70c1d3891f0db1b05292747f0dbcfb49c43f9244d04c70fbc40eb8"}, + {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:40ce74fc86ee4645d0a225498d091d8bc61f39b709ebef8204cb8b5a464d3c0e"}, + {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:4fe84294c7019456e56d93e8ababdad5a329cd25975be749c3f5f558abb48253"}, + {file = "rpds_py-0.20.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:338ca4539aad4ce70a656e5187a3a31c5204f261aef9f6ab50e50bcdffaf050a"}, + {file = "rpds_py-0.20.0-cp38-none-win32.whl", hash = "sha256:54b43a2b07db18314669092bb2de584524d1ef414588780261e31e85846c26a5"}, + {file = "rpds_py-0.20.0-cp38-none-win_amd64.whl", hash = "sha256:a1862d2d7ce1674cffa6d186d53ca95c6e17ed2b06b3f4c476173565c862d232"}, + {file = "rpds_py-0.20.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:3fde368e9140312b6e8b6c09fb9f8c8c2f00999d1823403ae90cc00480221b22"}, + {file = "rpds_py-0.20.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9824fb430c9cf9af743cf7aaf6707bf14323fb51ee74425c380f4c846ea70789"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11ef6ce74616342888b69878d45e9f779b95d4bd48b382a229fe624a409b72c5"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c52d3f2f82b763a24ef52f5d24358553e8403ce05f893b5347098014f2d9eff2"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d35cef91e59ebbeaa45214861874bc6f19eb35de96db73e467a8358d701a96c"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d72278a30111e5b5525c1dd96120d9e958464316f55adb030433ea905866f4de"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4c29cbbba378759ac5786730d1c3cb4ec6f8ababf5c42a9ce303dc4b3d08cda"}, + {file = "rpds_py-0.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6632f2d04f15d1bd6fe0eedd3b86d9061b836ddca4c03d5cf5c7e9e6b7c14580"}, + {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d0b67d87bb45ed1cd020e8fbf2307d449b68abc45402fe1a4ac9e46c3c8b192b"}, + {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ec31a99ca63bf3cd7f1a5ac9fe95c5e2d060d3c768a09bc1d16e235840861420"}, + {file = "rpds_py-0.20.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22e6c9976e38f4d8c4a63bd8a8edac5307dffd3ee7e6026d97f3cc3a2dc02a0b"}, + {file = "rpds_py-0.20.0-cp39-none-win32.whl", hash = "sha256:569b3ea770c2717b730b61998b6c54996adee3cef69fc28d444f3e7920313cf7"}, + {file = "rpds_py-0.20.0-cp39-none-win_amd64.whl", hash = "sha256:e6900ecdd50ce0facf703f7a00df12374b74bbc8ad9fe0f6559947fb20f82364"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:617c7357272c67696fd052811e352ac54ed1d9b49ab370261a80d3b6ce385045"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9426133526f69fcaba6e42146b4e12d6bc6c839b8b555097020e2b78ce908dcc"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deb62214c42a261cb3eb04d474f7155279c1a8a8c30ac89b7dcb1721d92c3c02"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fcaeb7b57f1a1e071ebd748984359fef83ecb026325b9d4ca847c95bc7311c92"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d454b8749b4bd70dd0a79f428731ee263fa6995f83ccb8bada706e8d1d3ff89d"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d807dc2051abe041b6649681dce568f8e10668e3c1c6543ebae58f2d7e617855"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3c20f0ddeb6e29126d45f89206b8291352b8c5b44384e78a6499d68b52ae511"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b7f19250ceef892adf27f0399b9e5afad019288e9be756d6919cb58892129f51"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4f1ed4749a08379555cebf4650453f14452eaa9c43d0a95c49db50c18b7da075"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:dcedf0b42bcb4cfff4101d7771a10532415a6106062f005ab97d1d0ab5681c60"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:39ed0d010457a78f54090fafb5d108501b5aa5604cc22408fc1c0c77eac14344"}, + {file = "rpds_py-0.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:bb273176be34a746bdac0b0d7e4e2c467323d13640b736c4c477881a3220a989"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f918a1a130a6dfe1d7fe0f105064141342e7dd1611f2e6a21cd2f5c8cb1cfb3e"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f60012a73aa396be721558caa3a6fd49b3dd0033d1675c6d59c4502e870fcf0c"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d2b1ad682a3dfda2a4e8ad8572f3100f95fad98cb99faf37ff0ddfe9cbf9d03"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:614fdafe9f5f19c63ea02817fa4861c606a59a604a77c8cdef5aa01d28b97921"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa518bcd7600c584bf42e6617ee8132869e877db2f76bcdc281ec6a4113a53ab"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f0475242f447cc6cb8a9dd486d68b2ef7fbee84427124c232bff5f63b1fe11e5"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f90a4cd061914a60bd51c68bcb4357086991bd0bb93d8aa66a6da7701370708f"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:def7400461c3a3f26e49078302e1c1b38f6752342c77e3cf72ce91ca69fb1bc1"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:65794e4048ee837494aea3c21a28ad5fc080994dfba5b036cf84de37f7ad5074"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:faefcc78f53a88f3076b7f8be0a8f8d35133a3ecf7f3770895c25f8813460f08"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:5b4f105deeffa28bbcdff6c49b34e74903139afa690e35d2d9e3c2c2fba18cec"}, + {file = "rpds_py-0.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fdfc3a892927458d98f3d55428ae46b921d1f7543b89382fdb483f5640daaec8"}, + {file = "rpds_py-0.20.0.tar.gz", hash = "sha256:d72a210824facfdaf8768cf2d7ca25a042c30320b3020de2fa04640920d4e121"}, ] [[package]] name = "ruff" -version = "0.5.4" +version = "0.5.7" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.5.4-py3-none-linux_armv6l.whl", hash = "sha256:82acef724fc639699b4d3177ed5cc14c2a5aacd92edd578a9e846d5b5ec18ddf"}, - {file = "ruff-0.5.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:da62e87637c8838b325e65beee485f71eb36202ce8e3cdbc24b9fcb8b99a37be"}, - {file = "ruff-0.5.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e98ad088edfe2f3b85a925ee96da652028f093d6b9b56b76fc242d8abb8e2059"}, - {file = "ruff-0.5.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c55efbecc3152d614cfe6c2247a3054cfe358cefbf794f8c79c8575456efe19"}, - {file = "ruff-0.5.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f9b85eaa1f653abd0a70603b8b7008d9e00c9fa1bbd0bf40dad3f0c0bdd06793"}, - {file = "ruff-0.5.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0cf497a47751be8c883059c4613ba2f50dd06ec672692de2811f039432875278"}, - {file = "ruff-0.5.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:09c14ed6a72af9ccc8d2e313d7acf7037f0faff43cde4b507e66f14e812e37f7"}, - {file = "ruff-0.5.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:628f6b8f97b8bad2490240aa84f3e68f390e13fabc9af5c0d3b96b485921cd60"}, - {file = "ruff-0.5.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3520a00c0563d7a7a7c324ad7e2cde2355733dafa9592c671fb2e9e3cd8194c1"}, - {file = "ruff-0.5.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93789f14ca2244fb91ed481456f6d0bb8af1f75a330e133b67d08f06ad85b516"}, - {file = "ruff-0.5.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:029454e2824eafa25b9df46882f7f7844d36fd8ce51c1b7f6d97e2615a57bbcc"}, - {file = "ruff-0.5.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:9492320eed573a13a0bc09a2957f17aa733fff9ce5bf00e66e6d4a88ec33813f"}, - {file = "ruff-0.5.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a6e1f62a92c645e2919b65c02e79d1f61e78a58eddaebca6c23659e7c7cb4ac7"}, - {file = "ruff-0.5.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:768fa9208df2bec4b2ce61dbc7c2ddd6b1be9fb48f1f8d3b78b3332c7d71c1ff"}, - {file = "ruff-0.5.4-py3-none-win32.whl", hash = "sha256:e1e7393e9c56128e870b233c82ceb42164966f25b30f68acbb24ed69ce9c3a4e"}, - {file = "ruff-0.5.4-py3-none-win_amd64.whl", hash = "sha256:58b54459221fd3f661a7329f177f091eb35cf7a603f01d9eb3eb11cc348d38c4"}, - {file = "ruff-0.5.4-py3-none-win_arm64.whl", hash = "sha256:bd53da65f1085fb5b307c38fd3c0829e76acf7b2a912d8d79cadcdb4875c1eb7"}, - {file = "ruff-0.5.4.tar.gz", hash = "sha256:2795726d5f71c4f4e70653273d1c23a8182f07dd8e48c12de5d867bfb7557eed"}, + {file = "ruff-0.5.7-py3-none-linux_armv6l.whl", hash = "sha256:548992d342fc404ee2e15a242cdbea4f8e39a52f2e7752d0e4cbe88d2d2f416a"}, + {file = "ruff-0.5.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:00cc8872331055ee017c4f1071a8a31ca0809ccc0657da1d154a1d2abac5c0be"}, + {file = "ruff-0.5.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:eaf3d86a1fdac1aec8a3417a63587d93f906c678bb9ed0b796da7b59c1114a1e"}, + {file = "ruff-0.5.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a01c34400097b06cf8a6e61b35d6d456d5bd1ae6961542de18ec81eaf33b4cb8"}, + {file = "ruff-0.5.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fcc8054f1a717e2213500edaddcf1dbb0abad40d98e1bd9d0ad364f75c763eea"}, + {file = "ruff-0.5.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f70284e73f36558ef51602254451e50dd6cc479f8b6f8413a95fcb5db4a55fc"}, + {file = "ruff-0.5.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:a78ad870ae3c460394fc95437d43deb5c04b5c29297815a2a1de028903f19692"}, + {file = "ruff-0.5.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9ccd078c66a8e419475174bfe60a69adb36ce04f8d4e91b006f1329d5cd44bcf"}, + {file = "ruff-0.5.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e31c9bad4ebf8fdb77b59cae75814440731060a09a0e0077d559a556453acbb"}, + {file = "ruff-0.5.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d796327eed8e168164346b769dd9a27a70e0298d667b4ecee6877ce8095ec8e"}, + {file = "ruff-0.5.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4a09ea2c3f7778cc635e7f6edf57d566a8ee8f485f3c4454db7771efb692c499"}, + {file = "ruff-0.5.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a36d8dcf55b3a3bc353270d544fb170d75d2dff41eba5df57b4e0b67a95bb64e"}, + {file = "ruff-0.5.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9369c218f789eefbd1b8d82a8cf25017b523ac47d96b2f531eba73770971c9e5"}, + {file = "ruff-0.5.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b88ca3db7eb377eb24fb7c82840546fb7acef75af4a74bd36e9ceb37a890257e"}, + {file = "ruff-0.5.7-py3-none-win32.whl", hash = "sha256:33d61fc0e902198a3e55719f4be6b375b28f860b09c281e4bdbf783c0566576a"}, + {file = "ruff-0.5.7-py3-none-win_amd64.whl", hash = "sha256:083bbcbe6fadb93cd86709037acc510f86eed5a314203079df174c40bbbca6b3"}, + {file = "ruff-0.5.7-py3-none-win_arm64.whl", hash = "sha256:2dca26154ff9571995107221d0aeaad0e75a77b5a682d6236cf89a58c70b76f4"}, + {file = "ruff-0.5.7.tar.gz", hash = "sha256:8dfc0a458797f5d9fb622dd0efc52d796f23f0a1493a9527f4e49a550ae9a7e5"}, ] [[package]] @@ -775,6 +781,17 @@ files = [ {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] +[[package]] +name = "tzdata" +version = "2024.1" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, + {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, +] + [[package]] name = "urllib3" version = "2.2.2" diff --git a/tests/test_dafny_generate copy.py b/tests/test_dafny_generate copy.py new file mode 100644 index 0000000..eec7b9a --- /dev/null +++ b/tests/test_dafny_generate copy.py @@ -0,0 +1,26 @@ +from textwrap import dedent +from verified_cogen.runners.languages import LanguageDatabase, init_basic_languages + +init_basic_languages() + + +def test_dafny_generate(): + dafny_lang = LanguageDatabase().get("dafny") + code = dedent( + """\ + method main(value: int) returns (result: int) + requires value >= 10 + ensures result >= 20 + { + assert value * 2 >= 20; // assert-line + result := value * 2; + }""" + ) + assert dafny_lang.generate_validators(code) == dedent( + """\ + method main_valid(value: int) returns (result: int) + requires value >= 10 + ensures result >= 20 + { var ret := main(value); return ret; } + """ + ) diff --git a/tests/test_nagini_generate.py b/tests/test_nagini_generate.py new file mode 100644 index 0000000..086d28c --- /dev/null +++ b/tests/test_nagini_generate.py @@ -0,0 +1,26 @@ +# from textwrap import dedent +# from verified_cogen.runners.languages import LanguageDatabase, init_basic_languages + +# init_basic_languages() + + +# def test_nagini_generate(): +# nagini_lang = LanguageDatabase().get("nagini") +# code = dedent( +# """\ +# def main(value: int) -> int: +# Requires(value >= 10) +# Ensures(Result() >= 20) +# Assert(value * 2 >= 20) // assert-line +# return value * 2""" +# ) +# assert nagini_lang.generate_validators(code) == dedent( +# """\ +# def main_valid(value: int) -> int: +# Requires(value >= 10) +# Ensures(Result() >= 20) +# ret = main(value) +# return ret""" +# ) + +# print(nagini_lang.generate_validators(code)) diff --git a/verified_cogen/main.py b/verified_cogen/main.py index d7ffc00..ada38e4 100644 --- a/verified_cogen/main.py +++ b/verified_cogen/main.py @@ -5,6 +5,7 @@ from verified_cogen.runners.generate import GenerateRunner from verified_cogen.runners.generic import GenericRunner from verified_cogen.runners.invariants import InvariantRunner +from verified_cogen.runners.languages import init_basic_languages from verified_cogen.runners.validating import ValidatingRunner from verified_cogen.tools import pprint_stat, rename_file, tabulate_list from verified_cogen.tools.modes import Mode @@ -66,6 +67,8 @@ def run_once(files, args, runner, verifier, mode, is_once) -> tuple[int, int, in def main(): + init_basic_languages() + args = get_args() mode = Mode(args.insert_conditions_mode) if mode == Mode.REGEX: diff --git a/verified_cogen/runners/__init__.py b/verified_cogen/runners/__init__.py index 3e7aef7..d1a7087 100644 --- a/verified_cogen/runners/__init__.py +++ b/verified_cogen/runners/__init__.py @@ -1,4 +1,3 @@ -from abc import ABC from logging import Logger from typing import Optional import pathlib @@ -11,103 +10,95 @@ LLM_GENERATED_DIR = pathlib.Path(get_cache_dir()) / "llm-generated" -class Runner(ABC): - @classmethod - def rewrite(cls, llm: LLM, prg: str) -> str: +class Runner: + llm: LLM + logger: Logger + verifier: Verifier + + def __init__(self, llm: LLM, logger: Logger, verifier: Verifier): + self.llm = llm + self.logger = logger + self.verifier = verifier + + def rewrite(self, prg: str) -> str: """Rewrite the program with additional checks in one step.""" ... - @classmethod - def produce(cls, llm: LLM, prg: str) -> str: + def produce(self, prg: str) -> str: """Produce the additional checks for the program.""" ... - @classmethod - def insert(cls, llm: LLM, prg: str, checks: str, mode: Mode) -> str: + def insert(self, prg: str, checks: str, mode: Mode) -> str: """Insert the additional checks into the program.""" ... - @classmethod - def precheck(cls, prg: str, mode: Mode): + def precheck(self, prg: str, mode: Mode): pass - @classmethod - def preprocess(cls, prg: str, mode: Mode) -> str: + def preprocess(self, prg: str, mode: Mode) -> str: return prg - @classmethod - def invoke(cls, logger: Logger, llm: LLM, prg: str, mode: Mode) -> str: - logger.info("Invoking LLM") + def invoke(self, prg: str, mode: Mode) -> str: + self.logger.info("Invoking LLM") if mode.is_singlestep: - inv_prg = cls.rewrite(llm, prg) + inv_prg = self.rewrite(prg) else: raise ValueError(f"Unexpected mode: {mode}") - logger.info("Invocation done") + self.logger.info("Invocation done") return inv_prg - @classmethod - def verify_program(cls, verifier: Verifier, name: str, prg: str): + def verify_program(self, name: str, prg: str): LLM_GENERATED_DIR.mkdir(parents=True, exist_ok=True) output = LLM_GENERATED_DIR / name with open(output, "w") as f: f.write(prg) - return verifier.verify(output) + return self.verifier.verify(output) - @classmethod def try_fixing( - cls, - logger: Logger, - verifier: Verifier, - llm: LLM, + self, total_tries: int, inv_prg: str, name: str, ) -> Optional[int]: tries = total_tries while tries > 0: - verification_result = cls.verify_program(verifier, name, inv_prg) + verification_result = self.verify_program(name, inv_prg) if verification_result is None: - logger.info("Verification timed out") + self.logger.info("Verification timed out") tries -= 1 if tries > 0: - inv_prg = llm.ask_for_timeout() + inv_prg = self.llm.ask_for_timeout() else: verified_inv, out_inv, err_inv = verification_result if verified_inv: return total_tries - tries + 1 else: - logger.info("Verification failed:") - logger.info(out_inv) - logger.info(err_inv) - logger.info("Retrying...") + self.logger.info("Verification failed:") + self.logger.info(out_inv) + self.logger.info(err_inv) + self.logger.info("Retrying...") tries -= 1 if tries > 0: - inv_prg = llm.ask_for_fixed(out_inv + err_inv) + inv_prg = self.llm.ask_for_fixed(out_inv + err_inv) return None - @classmethod def run_on_file( - cls, - logger: Logger, - verifier: Verifier, + self, mode: Mode, - llm: LLM, total_tries: int, file: str, ) -> Optional[int]: name = basename(file) - logger.info(f"Running on {file}") + self.logger.info(f"Running on {file}") with open(file, "r") as f: - prg = cls.preprocess(f.read(), mode) + prg = self.preprocess(f.read(), mode) - verification_result = cls.verify_program(verifier, name, prg) + verification_result = self.verify_program(name, prg) if verification_result is not None and verification_result[0]: return 0 elif verification_result is None: - logger.info("Verification timed out") - cls.precheck(prg, mode) - inv_prg = cls.invoke(logger, llm, prg, mode) - return cls.try_fixing( - logger, verifier, llm, total_tries, inv_prg, name - ) + self.logger.info("Verification timed out") + self.precheck(prg, mode) + inv_prg = self.invoke(prg, mode) + return self.try_fixing(total_tries, inv_prg, name) diff --git a/verified_cogen/runners/generate.py b/verified_cogen/runners/generate.py index 1333ab4..4163f6f 100644 --- a/verified_cogen/runners/generate.py +++ b/verified_cogen/runners/generate.py @@ -4,9 +4,7 @@ from verified_cogen.tools.modes import Mode -from verified_cogen.llm import LLM from verified_cogen.runners import Runner -from verified_cogen.tools.verifier import Verifier from verified_cogen.tools import basename, get_cache_dir @@ -16,24 +14,17 @@ class GenerateRunner(Runner): - @classmethod - def rewrite(cls, llm: LLM, prg: str) -> str: - return llm.rewrite(prg) + def rewrite(self, prg: str) -> str: + return self.llm.rewrite(prg) - @classmethod - def produce(cls, llm: LLM, prg: str) -> str: + def produce(self, prg: str) -> str: raise ValueError("Produce not supported for generate") - @classmethod - def insert(cls, llm: LLM, prg: str, checks: str, mode: Mode) -> str: + def insert(self, prg: str, checks: str, mode: Mode) -> str: raise ValueError("Insert not supported for generate") - @classmethod def try_fixing( - cls, - logger: logging.Logger, - verifier: Verifier, - llm: LLM, + self, total_tries: int, inv_prg: str, name: str, @@ -44,12 +35,12 @@ def try_fixing( output = LLM_GENERATED_DIR / f"{name[:-7]}.dfy" with open(output, "w") as f: f.write(inv_prg) - verification_result = verifier.verify(output) + verification_result = self.verifier.verify(output) if verification_result is None: logger.info("Verification timed out") tries -= 1 if tries > 0: - inv_prg = llm.ask_for_timeout() + inv_prg = self.llm.ask_for_timeout() else: verified_inv, out_inv, err_inv = verification_result if verified_inv: @@ -61,16 +52,12 @@ def try_fixing( logger.info("Retrying...") tries -= 1 if tries > 0: - inv_prg = llm.ask_for_fixed(out_inv + err_inv) + inv_prg = self.llm.ask_for_fixed(out_inv + err_inv) return None - @classmethod def run_on_file( - cls, - logger: logging.Logger, - verifier: Verifier, + self, mode: Mode, - llm: LLM, total_tries: int, file: str, ) -> Optional[int]: @@ -78,8 +65,6 @@ def run_on_file( with open(file, "r") as f: prg = f.read() - cls.precheck(prg, mode) - inv_prg = cls.invoke(logger, llm, prg, mode) - return cls.try_fixing( - logger, verifier, llm, total_tries, inv_prg, basename(file) - ) + self.precheck(prg, mode) + inv_prg = self.invoke(prg, mode) + return self.try_fixing(total_tries, inv_prg, basename(file)) diff --git a/verified_cogen/runners/generic.py b/verified_cogen/runners/generic.py index d641647..ceff102 100644 --- a/verified_cogen/runners/generic.py +++ b/verified_cogen/runners/generic.py @@ -9,16 +9,13 @@ class GenericRunner(Runner): - @classmethod - def rewrite(cls, llm: LLM, prg: str) -> str: - return llm.rewrite(prg) + def rewrite(self, prg: str) -> str: + return self.llm.rewrite(prg) - @classmethod - def produce(cls, llm: LLM, prg: str) -> str: - return llm.produce(prg) + def produce(self, prg: str) -> str: + return self.llm.produce(prg) - @classmethod - def insert(cls, llm: LLM, prg: str, checks: str, mode: Mode) -> str: + def insert(self, prg: str, checks: str, mode: Mode) -> str: if mode == Mode.REGEX: raise ValueError("Regex mode not supported for generic") - return llm.add(prg, checks) + return self.llm.add(prg, checks) diff --git a/verified_cogen/runners/invariants.py b/verified_cogen/runners/invariants.py index ef7332d..7586dc7 100644 --- a/verified_cogen/runners/invariants.py +++ b/verified_cogen/runners/invariants.py @@ -43,20 +43,16 @@ def insert_invariants(llm: LLM, prg: str, inv: str, mode: Mode): class InvariantRunner(Runner): - @classmethod - def rewrite(cls, llm: LLM, prg: str) -> str: - return llm.rewrite(prg) + def rewrite(self, prg: str) -> str: + return self.llm.rewrite(prg) - @classmethod - def produce(cls, llm: LLM, prg: str) -> str: - return llm.produce(prg) + def produce(self, prg: str) -> str: + return self.llm.produce(prg) - @classmethod - def insert(cls, llm: LLM, prg: str, checks: str, mode: Mode) -> str: - return insert_invariants(llm, prg, checks, mode) + def insert(self, prg: str, checks: str, mode: Mode) -> str: + return insert_invariants(self.llm, prg, checks, mode) - @classmethod - def precheck(cls, prg: str, mode: Mode): + def precheck(self, prg: str, mode: Mode): if mode == Mode.REGEX: while_count = prg.count("while") if while_count == 0: diff --git a/verified_cogen/runners/languages/__init__.py b/verified_cogen/runners/languages/__init__.py new file mode 100644 index 0000000..2685c41 --- /dev/null +++ b/verified_cogen/runners/languages/__init__.py @@ -0,0 +1,8 @@ +from verified_cogen.runners.languages.dafny import DafnyLanguage +from verified_cogen.runners.languages.language import LanguageDatabase +from verified_cogen.runners.languages.nagini import NaginiLanguage + + +def init_basic_languages(): + LanguageDatabase().add("dafny", ["dfy"], DafnyLanguage()) + LanguageDatabase().add("nagini", ["py", "python"], NaginiLanguage()) diff --git a/verified_cogen/runners/languages/dafny.py b/verified_cogen/runners/languages/dafny.py new file mode 100644 index 0000000..0fca6cf --- /dev/null +++ b/verified_cogen/runners/languages/dafny.py @@ -0,0 +1,21 @@ +from typing import Pattern +from verified_cogen.runners.languages.language import GenericLanguage +import re + +DAFNY_VALIDATOR_TEMPLATE = """\ +def {method_name}_valid({parameters}) -> ({returns}):{specs}\ + ret = {method_name}({param_names}) + return ret +""" + + +class DafnyLanguage(GenericLanguage): + method_regex: Pattern[str] + + def __init__(self): + super().__init__( + re.compile( + r"method\s+(\w+)\s*\((.*?)\)\s*returns\s*\((.*?)\)(.*?)\{", re.DOTALL + ), + DAFNY_VALIDATOR_TEMPLATE, + ) diff --git a/verified_cogen/runners/languages/language.py b/verified_cogen/runners/languages/language.py new file mode 100644 index 0000000..002e472 --- /dev/null +++ b/verified_cogen/runners/languages/language.py @@ -0,0 +1,78 @@ +from abc import abstractmethod +from typing import Pattern + + +class Language: + _instance = None + + def __new__(cls, *args, **kwargs): + if not isinstance(cls._instance, cls): + cls._instance = super().__new__(cls, *args, **kwargs) + return cls._instance + + @abstractmethod + def __init__(self): ... + + @abstractmethod + def generate_validators(self, code: str) -> str: ... + + +class GenericLanguage(Language): + method_regex: Pattern[str] + validator_template: str + + def __init__(self, method_regex: Pattern[str], validator_template: str): + self.method_regex = method_regex + self.validator_template = validator_template + + def generate_validators(self, code: str) -> str: + methods = self.method_regex.finditer(code) + + validators = [] + + for match in methods: + method_name, parameters, returns, specs = ( + match.group(1), + match.group(2), + match.group(3), + match.group(4), + ) + + validators.append( + self.validator_template.replace("{method_name}", method_name) + .replace("{parameters}", parameters) + .replace("{returns}", returns) + .replace("{specs}", specs) + .replace( + "{param_names}", + ", ".join( + param.split(":")[0].strip() + for param in parameters.split(",") + if param.strip() + ), + ) + ) + + return "\n".join(validators) + + +class LanguageDatabase: + _instance = None + languages: dict[str, Language] = dict() + regularise: dict[str, str] = dict() + + def __new__(cls, *args, **kwargs): + if not isinstance(cls._instance, cls): + cls._instance = super().__new__(cls, *args, **kwargs) + return cls._instance + + def add(self, name: str, aliases: list[str], definition: Language): + self.languages[name] = definition + self.regularise[name] = name + for alias in aliases: + self.regularise[alias] = name + + def get(self, name: str): + if name not in self.regularise: + raise ValueError(f"language {name} not found, has it been registered?") + return self.languages[self.regularise[name]] diff --git a/verified_cogen/runners/languages/nagini.py b/verified_cogen/runners/languages/nagini.py new file mode 100644 index 0000000..bddea3d --- /dev/null +++ b/verified_cogen/runners/languages/nagini.py @@ -0,0 +1,19 @@ +from typing import Pattern +from verified_cogen.runners.languages.language import GenericLanguage +import re + +NAGINI_VALIDATOR_TEMPLATE = """\ +def {method_name}_valid({parameters}) -> ({returns}):{specs} + ret = {method_name}({param_names}) + return ret +""" + + +class NaginiLanguage(GenericLanguage): + method_regex: Pattern[str] + + def __init__(self): + super().__init__( + re.compile(r"def\s+(\w+)\s*\((.*?)\)\s*->\s*(.*?):(.*?)", re.DOTALL), + NAGINI_VALIDATOR_TEMPLATE, + ) diff --git a/verified_cogen/runners/validating.py b/verified_cogen/runners/validating.py index 63fa5b9..a441e60 100644 --- a/verified_cogen/runners/validating.py +++ b/verified_cogen/runners/validating.py @@ -1,53 +1,13 @@ import re +from logging import Logger +from verified_cogen.runners.languages.language import Language from verified_cogen.tools.modes import Mode from verified_cogen.llm import LLM from verified_cogen.runners import Runner from verified_cogen.runners.invariants import InvariantRunner - -# Regular expression to match Dafny method definitions -method_pattern = re.compile( - r"method\s+(\w+)\s*\((.*?)\)\s*returns\s*\((.*?)\)(.*?)\{", re.DOTALL -) - - -def generate_validators(dafny_code: str) -> str: - """ - Create validator-methods for every method in dafny program - - Example: - Input: - method xor(a : char, b : char) returns (result : char) - ensures result == (if a == b then '0' else '1') - { if (a == b) { result := '0'; } else { result := '1'; } } - Output: - method xor_valid(a : char, b : char) returns (result : char) - ensures result == (if a == b then '0' else '1') - { var ret := xor(a, b); return ret; } - """ - methods = method_pattern.finditer(dafny_code) - - validators = [] - - for match in methods: - method_name = match.group(1) - parameters = match.group(2) - returns = match.group(3) - specs = match.group(4) - - validator = ( - f"method {method_name}_valid({parameters}) returns ({returns}){specs}" - ) - validator += "{ var ret := " - - validator += f"{method_name}({', '.join(param.split(':')[0].strip() for param in parameters.split(',') if param.strip())});" - - validator += " return ret; }\n" - - validators.append(validator) - - return "\n".join(validators) +from verified_cogen.tools.verifier import Verifier def remove_asserts_and_invariants(dafny_code: str) -> str: @@ -64,30 +24,34 @@ def remove_asserts_and_invariants(dafny_code: str) -> str: class ValidatingRunner(Runner): - @classmethod - def _add_validators(cls, prg: str, inv_prg: str): - validators = generate_validators(prg) + invariant_runner: InvariantRunner + language: Language + + def __init__( + self, llm: LLM, logger: Logger, verifier: Verifier, language: Language + ): + super().__init__(llm, logger, verifier) + self.invariant_runner = InvariantRunner(llm, logger, verifier) + self.language = language + + def _add_validators(self, prg: str, inv_prg: str): + validators = self.language.generate_validators(prg) val_prg = inv_prg + "\n// ==== verifiers ==== //\n" + validators return val_prg - @classmethod - def preprocess(cls, prg: str, mode: Mode) -> str: + def preprocess(self, prg: str, mode: Mode) -> str: return remove_asserts_and_invariants(prg) - @classmethod - def rewrite(cls, llm: LLM, prg: str) -> str: - return ValidatingRunner._add_validators(prg, InvariantRunner.rewrite(llm, prg)) + def rewrite(self, prg: str) -> str: + return self._add_validators(prg, self.invariant_runner.rewrite(prg)) - @classmethod - def produce(cls, llm: LLM, prg: str) -> str: - return ValidatingRunner._add_validators(prg, InvariantRunner.produce(llm, prg)) + def produce(self, prg: str) -> str: + return self._add_validators(prg, self.invariant_runner.produce(prg)) - @classmethod - def insert(cls, llm: LLM, prg: str, checks: str, mode: Mode) -> str: - return ValidatingRunner._add_validators( - prg, InvariantRunner.insert(llm, prg, checks, mode) + def insert(self, prg: str, checks: str, mode: Mode) -> str: + return self._add_validators( + prg, self.invariant_runner.insert(prg, checks, mode) ) - @classmethod - def precheck(cls, prg: str, mode: Mode): - return InvariantRunner.precheck(prg, mode) + def precheck(self, prg: str, mode: Mode): + return self.invariant_runner.precheck(prg, mode) From 7f616365bf33cab36ea9c451b38f787d44e6acfe Mon Sep 17 00:00:00 2001 From: WeetHet Date: Mon, 9 Sep 2024 10:55:37 +0300 Subject: [PATCH 02/23] fix dafny codegen --- ...{test_dafny_generate copy.py => test_dafny_generate.py} | 1 + verified_cogen/runners/languages/dafny.py | 5 ++--- verified_cogen/runners/languages/language.py | 7 ------- verified_cogen/runners/languages/nagini.py | 2 +- 4 files changed, 4 insertions(+), 11 deletions(-) rename tests/{test_dafny_generate copy.py => test_dafny_generate.py} (93%) diff --git a/tests/test_dafny_generate copy.py b/tests/test_dafny_generate.py similarity index 93% rename from tests/test_dafny_generate copy.py rename to tests/test_dafny_generate.py index eec7b9a..bc1c24b 100644 --- a/tests/test_dafny_generate copy.py +++ b/tests/test_dafny_generate.py @@ -16,6 +16,7 @@ def test_dafny_generate(): result := value * 2; }""" ) + result = dafny_lang.generate_validators(code) assert dafny_lang.generate_validators(code) == dedent( """\ method main_valid(value: int) returns (result: int) diff --git a/verified_cogen/runners/languages/dafny.py b/verified_cogen/runners/languages/dafny.py index 0fca6cf..22aee45 100644 --- a/verified_cogen/runners/languages/dafny.py +++ b/verified_cogen/runners/languages/dafny.py @@ -3,9 +3,8 @@ import re DAFNY_VALIDATOR_TEMPLATE = """\ -def {method_name}_valid({parameters}) -> ({returns}):{specs}\ - ret = {method_name}({param_names}) - return ret +method {method_name}_valid({parameters}) returns ({returns}){specs}\ +{ var ret := {method_name}({param_names}); return ret; } """ diff --git a/verified_cogen/runners/languages/language.py b/verified_cogen/runners/languages/language.py index 002e472..04927cb 100644 --- a/verified_cogen/runners/languages/language.py +++ b/verified_cogen/runners/languages/language.py @@ -3,13 +3,6 @@ class Language: - _instance = None - - def __new__(cls, *args, **kwargs): - if not isinstance(cls._instance, cls): - cls._instance = super().__new__(cls, *args, **kwargs) - return cls._instance - @abstractmethod def __init__(self): ... diff --git a/verified_cogen/runners/languages/nagini.py b/verified_cogen/runners/languages/nagini.py index bddea3d..d002448 100644 --- a/verified_cogen/runners/languages/nagini.py +++ b/verified_cogen/runners/languages/nagini.py @@ -3,7 +3,7 @@ import re NAGINI_VALIDATOR_TEMPLATE = """\ -def {method_name}_valid({parameters}) -> ({returns}):{specs} +def {method_name}_valid({parameters}) -> {returns}:{specs} ret = {method_name}({param_names}) return ret """ From 4312549b45f6fca226bffc2da5f31f572f522368 Mon Sep 17 00:00:00 2001 From: WeetHet Date: Mon, 9 Sep 2024 11:42:45 +0300 Subject: [PATCH 03/23] implement nagini codegen --- tests/test_nagini_generate.py | 45 ++++++++++---------- verified_cogen/runners/languages/language.py | 8 ++++ verified_cogen/runners/languages/nagini.py | 9 ++-- 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/tests/test_nagini_generate.py b/tests/test_nagini_generate.py index 086d28c..a405861 100644 --- a/tests/test_nagini_generate.py +++ b/tests/test_nagini_generate.py @@ -1,26 +1,25 @@ -# from textwrap import dedent -# from verified_cogen.runners.languages import LanguageDatabase, init_basic_languages +import re +from textwrap import dedent +from verified_cogen.runners.languages import LanguageDatabase, init_basic_languages -# init_basic_languages() +init_basic_languages() -# def test_nagini_generate(): -# nagini_lang = LanguageDatabase().get("nagini") -# code = dedent( -# """\ -# def main(value: int) -> int: -# Requires(value >= 10) -# Ensures(Result() >= 20) -# Assert(value * 2 >= 20) // assert-line -# return value * 2""" -# ) -# assert nagini_lang.generate_validators(code) == dedent( -# """\ -# def main_valid(value: int) -> int: -# Requires(value >= 10) -# Ensures(Result() >= 20) -# ret = main(value) -# return ret""" -# ) - -# print(nagini_lang.generate_validators(code)) +def test_nagini_generate(): + nagini_lang = LanguageDatabase().get("nagini") + code = dedent( + """\ + def main(value: int) -> int: + Requires(value >= 10) + Ensures(Result() >= 20) + Assert(value * 2 >= 20) // assert-line + return value * 2""" + ) + assert nagini_lang.generate_validators(code) == dedent( + """\ + def main_valid(value: int) -> int: + Requires(value >= 10) + Ensures(Result() >= 20) + ret = main(value) + return ret""" + ) diff --git a/verified_cogen/runners/languages/language.py b/verified_cogen/runners/languages/language.py index 04927cb..c52bda5 100644 --- a/verified_cogen/runners/languages/language.py +++ b/verified_cogen/runners/languages/language.py @@ -3,6 +3,13 @@ class Language: + _instance = None + + def __new__(cls, *args, **kwargs): + if not isinstance(cls._instance, cls): + cls._instance = super().__new__(cls, *args, **kwargs) + return cls._instance + @abstractmethod def __init__(self): ... @@ -24,6 +31,7 @@ def generate_validators(self, code: str) -> str: validators = [] for match in methods: + print(match.groups()) method_name, parameters, returns, specs = ( match.group(1), match.group(2), diff --git a/verified_cogen/runners/languages/nagini.py b/verified_cogen/runners/languages/nagini.py index d002448..4bc1f00 100644 --- a/verified_cogen/runners/languages/nagini.py +++ b/verified_cogen/runners/languages/nagini.py @@ -3,9 +3,9 @@ import re NAGINI_VALIDATOR_TEMPLATE = """\ -def {method_name}_valid({parameters}) -> {returns}:{specs} +def {method_name}_valid({parameters}) -> {returns}:{specs}\ ret = {method_name}({param_names}) - return ret + return ret\ """ @@ -14,6 +14,9 @@ class NaginiLanguage(GenericLanguage): def __init__(self): super().__init__( - re.compile(r"def\s+(\w+)\s*\((.*?)\)\s*->\s*(.*?):(.*?)", re.DOTALL), + re.compile( + r"def\s+(\w+)\s*\((.*?)\)\s*->\s*(.*?):((?:\r\n|\r|\n) *(?:Requires|Ensures)\(.*\)(?:\r\n|\r|\n))*", + re.DOTALL, + ), NAGINI_VALIDATOR_TEMPLATE, ) From 4d4ee8927cde308e2df86ca9a178a41ca01d1d56 Mon Sep 17 00:00:00 2001 From: WeetHet Date: Tue, 10 Sep 2024 11:39:05 +0300 Subject: [PATCH 04/23] implement assert and invariant removal --- tests/{test_remove.py => test_dafny.py} | 41 +++++- tests/test_dafny_generate.py | 27 ---- tests/test_nagini.py | 138 +++++++++++++++++++ tests/test_nagini_generate.py | 25 ---- verified_cogen/runners/languages/dafny.py | 5 + verified_cogen/runners/languages/language.py | 27 +++- verified_cogen/runners/languages/nagini.py | 5 + verified_cogen/runners/validating.py | 15 +- 8 files changed, 210 insertions(+), 73 deletions(-) rename tests/{test_remove.py => test_dafny.py} (66%) delete mode 100644 tests/test_dafny_generate.py create mode 100644 tests/test_nagini.py delete mode 100644 tests/test_nagini_generate.py diff --git a/tests/test_remove.py b/tests/test_dafny.py similarity index 66% rename from tests/test_remove.py rename to tests/test_dafny.py index 975ee75..0cf2dee 100644 --- a/tests/test_remove.py +++ b/tests/test_dafny.py @@ -1,15 +1,40 @@ from textwrap import dedent -from verified_cogen.runners.validating import remove_asserts_and_invariants +from verified_cogen.runners.languages import LanguageDatabase, init_basic_languages + +init_basic_languages() + + +def test_dafny_generate(): + dafny_lang = LanguageDatabase().get("dafny") + code = dedent( + """\ + method main(value: int) returns (result: int) + requires value >= 10 + ensures result >= 20 + { + assert value * 2 >= 20; // assert-line + result := value * 2; + }""" + ) + assert dafny_lang.generate_validators(code) == dedent( + """\ + method main_valid(value: int) returns (result: int) + requires value >= 10 + ensures result >= 20 + { var ret := main(value); return ret; } + """ + ) def test_remove_line(): + dafny_lang = LanguageDatabase().get("dafny") code = dedent( """\ method main() { assert a == 1; // assert-line }""" ) - assert remove_asserts_and_invariants(code) == dedent( + assert dafny_lang.remove_asserts_and_invariants(code) == dedent( """\ method main() { }""" @@ -17,6 +42,8 @@ def test_remove_line(): def test_remove_multiline_assert(): + dafny_lang = LanguageDatabase().get("dafny") + code = dedent( """\ method main() { @@ -27,7 +54,7 @@ def test_remove_multiline_assert(): // assert-end }""" ) - assert remove_asserts_and_invariants(code) == dedent( + assert dafny_lang.remove_asserts_and_invariants(code) == dedent( """\ method main() { }""" @@ -35,6 +62,8 @@ def test_remove_multiline_assert(): def test_remove_invariants(): + dafny_lang = LanguageDatabase().get("dafny") + code = dedent( """\ method main() { @@ -47,7 +76,7 @@ def test_remove_invariants(): } }""" ) - assert remove_asserts_and_invariants(code) == dedent( + assert dafny_lang.remove_asserts_and_invariants(code) == dedent( """\ method main() { while true @@ -58,6 +87,8 @@ def test_remove_invariants(): def test_remove_all(): + dafny_lang = LanguageDatabase().get("dafny") + code = dedent( """\ method is_prime(k: int) returns (result: bool) @@ -87,7 +118,7 @@ def test_remove_all(): } }""" ) - assert remove_asserts_and_invariants(code) == dedent( + assert dafny_lang.remove_asserts_and_invariants(code) == dedent( """\ method is_prime(k: int) returns (result: bool) requires k >= 2 diff --git a/tests/test_dafny_generate.py b/tests/test_dafny_generate.py deleted file mode 100644 index bc1c24b..0000000 --- a/tests/test_dafny_generate.py +++ /dev/null @@ -1,27 +0,0 @@ -from textwrap import dedent -from verified_cogen.runners.languages import LanguageDatabase, init_basic_languages - -init_basic_languages() - - -def test_dafny_generate(): - dafny_lang = LanguageDatabase().get("dafny") - code = dedent( - """\ - method main(value: int) returns (result: int) - requires value >= 10 - ensures result >= 20 - { - assert value * 2 >= 20; // assert-line - result := value * 2; - }""" - ) - result = dafny_lang.generate_validators(code) - assert dafny_lang.generate_validators(code) == dedent( - """\ - method main_valid(value: int) returns (result: int) - requires value >= 10 - ensures result >= 20 - { var ret := main(value); return ret; } - """ - ) diff --git a/tests/test_nagini.py b/tests/test_nagini.py new file mode 100644 index 0000000..d5e427f --- /dev/null +++ b/tests/test_nagini.py @@ -0,0 +1,138 @@ +import re +from textwrap import dedent +from verified_cogen.runners.languages import LanguageDatabase, init_basic_languages + +init_basic_languages() + + +def test_nagini_generate(): + nagini_lang = LanguageDatabase().get("nagini") + code = dedent( + """\ + def main(value: int) -> int: + Requires(value >= 10) + Ensures(Result() >= 20) + Assert(value * 2 >= 20) # assert-line + return value * 2""" + ) + assert nagini_lang.generate_validators(code) == dedent( + """\ + def main_valid(value: int) -> int: + Requires(value >= 10) + Ensures(Result() >= 20) + ret = main(value) + return ret""" + ) + + +def test_remove_line(): + nagini_lang = LanguageDatabase().get("nagini") + code = dedent( + """\ + def main(): + Assert(a == 1) # assert-line + """ + ) + assert nagini_lang.remove_asserts_and_invariants(code) == dedent( + """\ + def main():""" + ) + + +def test_remove_multiline_assert(): + nagini_lang = LanguageDatabase().get("nagini") + + code = dedent( + """\ + def main(): + # assert-start + Assert( + a == 1 + ) + # assert-end""" + ) + assert nagini_lang.remove_asserts_and_invariants(code) == dedent( + """\ + def main():""" + ) + + +def test_remove_invariants(): + nagini_lang = LanguageDatabase().get("nagini") + + code = dedent( + """\ + def main(): + while True: + # invariants-start + Invariant(false) + Invariant(true) + # invariants-end""" + ) + assert nagini_lang.remove_asserts_and_invariants(code) == dedent( + """\ + def main(): + while True:""" + ) + + +def test_remove_all(): + nagini_lang = LanguageDatabase().get("nagini") + + code = dedent( + """\ + def is_prime(k : int) -> bool: + # pre-conditions-start + Requires((k) >= (2)) + # pre-conditions-end + # post-conditions-start + Ensures(not (Result()) or (Forall(int, lambda d_0_i_: + not (((2) <= (d_0_i_)) and ((d_0_i_) < (k))) or ((k % d_0_i_) != (0))))) + Ensures(not (not(Result())) or (Exists(int, lambda d_1_j_: + (((2) <= (d_1_j_)) and ((d_1_j_) < (k))) and (((k % d_1_j_)) == (0))))) + # post-conditions-end + result = False # type : bool + d_2_i_ = int(0) # type : int + d_2_i_ = 2 + result = True + while (d_2_i_) < (k): + # invariants-start + Invariant(((2) <= (d_2_i_)) and ((d_2_i_) <= (k))) + Invariant(not (not(result)) or (Exists(int, lambda d_3_j_: + (((2) <= (d_3_j_)) and ((d_3_j_) < (d_2_i_))) and (((k % d_3_j_)) == (0))))) + Invariant(not (result) or (Forall(int, lambda d_4_j_: + not (((2) <= (d_4_j_)) and ((d_4_j_) < (d_2_i_))) or (((k % d_4_j_)) != (0))))) + # invariants-end + if ((k % d_2_i_)) == (0): + result = False + Assert((not result) or Forall(int, lambda j : 2 <= j < i ==> k % j != 0)) # assert-line + # assert-start + Assert(result + or Exists(int, + lamdbda j : 2 <= j < i && k % j == 0) + # assert-end + d_2_i_ = (d_2_i_) + (1) + return result""" + ) + assert nagini_lang.remove_asserts_and_invariants(code) == dedent( + """\ + def is_prime(k : int) -> bool: + # pre-conditions-start + Requires((k) >= (2)) + # pre-conditions-end + # post-conditions-start + Ensures(not (Result()) or (Forall(int, lambda d_0_i_: + not (((2) <= (d_0_i_)) and ((d_0_i_) < (k))) or ((k % d_0_i_) != (0))))) + Ensures(not (not(Result())) or (Exists(int, lambda d_1_j_: + (((2) <= (d_1_j_)) and ((d_1_j_) < (k))) and (((k % d_1_j_)) == (0))))) + # post-conditions-end + result = False # type : bool + d_2_i_ = int(0) # type : int + d_2_i_ = 2 + result = True + while (d_2_i_) < (k): + if ((k % d_2_i_)) == (0): + result = False + d_2_i_ = (d_2_i_) + (1) + return result""" + ) diff --git a/tests/test_nagini_generate.py b/tests/test_nagini_generate.py deleted file mode 100644 index a405861..0000000 --- a/tests/test_nagini_generate.py +++ /dev/null @@ -1,25 +0,0 @@ -import re -from textwrap import dedent -from verified_cogen.runners.languages import LanguageDatabase, init_basic_languages - -init_basic_languages() - - -def test_nagini_generate(): - nagini_lang = LanguageDatabase().get("nagini") - code = dedent( - """\ - def main(value: int) -> int: - Requires(value >= 10) - Ensures(Result() >= 20) - Assert(value * 2 >= 20) // assert-line - return value * 2""" - ) - assert nagini_lang.generate_validators(code) == dedent( - """\ - def main_valid(value: int) -> int: - Requires(value >= 10) - Ensures(Result() >= 20) - ret = main(value) - return ret""" - ) diff --git a/verified_cogen/runners/languages/dafny.py b/verified_cogen/runners/languages/dafny.py index 22aee45..a1a2e50 100644 --- a/verified_cogen/runners/languages/dafny.py +++ b/verified_cogen/runners/languages/dafny.py @@ -17,4 +17,9 @@ def __init__(self): r"method\s+(\w+)\s*\((.*?)\)\s*returns\s*\((.*?)\)(.*?)\{", re.DOTALL ), DAFNY_VALIDATOR_TEMPLATE, + [ + r" *// assert-start.*?// assert-end\n", + r" *// invariants-start.*?// invariants-end\n", + ], + "// assert-line", ) diff --git a/verified_cogen/runners/languages/language.py b/verified_cogen/runners/languages/language.py index c52bda5..5c93099 100644 --- a/verified_cogen/runners/languages/language.py +++ b/verified_cogen/runners/languages/language.py @@ -16,14 +16,27 @@ def __init__(self): ... @abstractmethod def generate_validators(self, code: str) -> str: ... + @abstractmethod + def remove_asserts_and_invariants(self, code: str) -> str: ... + class GenericLanguage(Language): method_regex: Pattern[str] validator_template: str - - def __init__(self, method_regex: Pattern[str], validator_template: str): + assert_invariant_patterns: list[str] + inline_assert_comment: str + + def __init__( + self, + method_regex: Pattern[str], + validator_template: str, + assert_invariants_pattern: list[str], + inline_assert_comment: str, + ): self.method_regex = method_regex self.validator_template = validator_template + self.assert_invariant_patterns = assert_invariants_pattern + self.inline_assert_comment = inline_assert_comment def generate_validators(self, code: str) -> str: methods = self.method_regex.finditer(code) @@ -56,6 +69,16 @@ def generate_validators(self, code: str) -> str: return "\n".join(validators) + def remove_asserts_and_invariants(self, code: str) -> str: + import re + + combined_pattern = "|".join(self.assert_invariant_patterns) + cleaned_code = re.sub(combined_pattern, "", code, flags=re.DOTALL) + cleaned_code = re.sub(r"\n\s*\n", "\n", cleaned_code) + lines = cleaned_code.split("\n") + lines = [line for line in lines if self.inline_assert_comment not in line] + return "\n".join(lines).strip() + class LanguageDatabase: _instance = None diff --git a/verified_cogen/runners/languages/nagini.py b/verified_cogen/runners/languages/nagini.py index 4bc1f00..0b294da 100644 --- a/verified_cogen/runners/languages/nagini.py +++ b/verified_cogen/runners/languages/nagini.py @@ -19,4 +19,9 @@ def __init__(self): re.DOTALL, ), NAGINI_VALIDATOR_TEMPLATE, + [ + r" *# assert-start.*?# assert-end\n?", + r" *# invariants-start.*?# invariants-end\n?", + ], + "# assert-line", ) diff --git a/verified_cogen/runners/validating.py b/verified_cogen/runners/validating.py index a441e60..ab917a9 100644 --- a/verified_cogen/runners/validating.py +++ b/verified_cogen/runners/validating.py @@ -10,19 +10,6 @@ from verified_cogen.tools.verifier import Verifier -def remove_asserts_and_invariants(dafny_code: str) -> str: - patterns = [ - r" *// assert-start.*?// assert-end\n", - r" *// invariants-start.*?// invariants-end\n", - ] - combined_pattern = "|".join(patterns) - cleaned_code = re.sub(combined_pattern, "", dafny_code, flags=re.DOTALL) - cleaned_code = re.sub(r"\n\s*\n", "\n", cleaned_code) - lines = cleaned_code.split("\n") - lines = [line for line in lines if "// assert-line" not in line] - return "\n".join(lines).strip() - - class ValidatingRunner(Runner): invariant_runner: InvariantRunner language: Language @@ -40,7 +27,7 @@ def _add_validators(self, prg: str, inv_prg: str): return val_prg def preprocess(self, prg: str, mode: Mode) -> str: - return remove_asserts_and_invariants(prg) + return self.language.remove_asserts_and_invariants(prg) def rewrite(self, prg: str) -> str: return self._add_validators(prg, self.invariant_runner.rewrite(prg)) From 91ea77cc01d3390bedb2fcac425d7fd56f8e1dbc Mon Sep 17 00:00:00 2001 From: WeetHet Date: Tue, 10 Sep 2024 12:42:59 +0300 Subject: [PATCH 05/23] sort imports, fix run --- tests/test_dafny.py | 4 +-- tests/test_nagini.py | 4 +-- verified_cogen/__init__.py | 3 +- verified_cogen/args.py | 3 +- verified_cogen/experiments/incremental_run.py | 20 +++++++++---- verified_cogen/experiments/use_houdini.py | 5 ++-- verified_cogen/main.py | 6 ++-- verified_cogen/runners/__init__.py | 4 +-- verified_cogen/runners/generate.py | 6 ++-- verified_cogen/runners/generic.py | 4 +-- verified_cogen/runners/invariants.py | 3 +- verified_cogen/runners/languages/__init__.py | 6 ++-- verified_cogen/runners/languages/dafny.py | 3 +- verified_cogen/runners/languages/language.py | 2 +- verified_cogen/runners/languages/nagini.py | 3 +- verified_cogen/runners/validating.py | 28 ++++++------------- verified_cogen/tools/__init__.py | 1 + verified_cogen/tools/verifier.py | 5 ++-- 18 files changed, 53 insertions(+), 57 deletions(-) diff --git a/tests/test_dafny.py b/tests/test_dafny.py index 0cf2dee..a8809df 100644 --- a/tests/test_dafny.py +++ b/tests/test_dafny.py @@ -1,7 +1,7 @@ from textwrap import dedent -from verified_cogen.runners.languages import LanguageDatabase, init_basic_languages +from verified_cogen.runners.languages import LanguageDatabase, register_basic_languages -init_basic_languages() +register_basic_languages() def test_dafny_generate(): diff --git a/tests/test_nagini.py b/tests/test_nagini.py index d5e427f..013a611 100644 --- a/tests/test_nagini.py +++ b/tests/test_nagini.py @@ -1,8 +1,8 @@ import re from textwrap import dedent -from verified_cogen.runners.languages import LanguageDatabase, init_basic_languages +from verified_cogen.runners.languages import LanguageDatabase, register_basic_languages -init_basic_languages() +register_basic_languages() def test_nagini_generate(): diff --git a/verified_cogen/__init__.py b/verified_cogen/__init__.py index 46b30ff..ae12c33 100644 --- a/verified_cogen/__init__.py +++ b/verified_cogen/__init__.py @@ -1,8 +1,9 @@ import logging import os -from verified_cogen.tools import get_cache_dir import pathlib +from verified_cogen.tools import get_cache_dir + def init_logging(): log_dir = pathlib.Path(get_cache_dir()) / "log" diff --git a/verified_cogen/args.py b/verified_cogen/args.py index 2278440..3f38a6c 100644 --- a/verified_cogen/args.py +++ b/verified_cogen/args.py @@ -1,7 +1,8 @@ import argparse -from verified_cogen.tools.modes import VALID_MODES import os +from verified_cogen.tools.modes import VALID_MODES + def get_args(): parser = argparse.ArgumentParser() diff --git a/verified_cogen/experiments/incremental_run.py b/verified_cogen/experiments/incremental_run.py index 35d7654..c289cb5 100644 --- a/verified_cogen/experiments/incremental_run.py +++ b/verified_cogen/experiments/incremental_run.py @@ -1,15 +1,21 @@ -import pathlib import logging +import pathlib + +from verified_cogen.llm.llm import LLM from verified_cogen.main import get_args, rename_file +from verified_cogen.runners.invariants import InvariantRunner +from verified_cogen.runners.languages import register_basic_languages +from verified_cogen.runners.languages.language import LanguageDatabase +from verified_cogen.runners.validating import ValidatingRunner from verified_cogen.tools.modes import Mode from verified_cogen.tools.verifier import Verifier -from verified_cogen.llm.llm import LLM -from verified_cogen.runners.validating import ValidatingRunner logger = logging.getLogger(__name__) def main(): + register_basic_languages() + args = get_args() mode = Mode(args.insert_conditions_mode) assert mode != Mode.REGEX @@ -31,6 +37,10 @@ def main(): args.prompts_directory, args.temperature, ) + runner = ValidatingRunner( + wrapping=InvariantRunner(llm, logger, verifier), + language=LanguageDatabase().get("dfy"), + ) display_name = rename_file(file) marker_file = marker_directory.joinpath(file.relative_to(directory)) if marker_file.exists(): @@ -38,9 +48,7 @@ def main(): continue print("Processing:", display_name) try: - tries = ValidatingRunner.run_on_file( - logger, verifier, mode, llm, args.tries, str(file) - ) + tries = runner.run_on_file(mode, args.tries, str(file)) except KeyboardInterrupt: return except Exception as e: diff --git a/verified_cogen/experiments/use_houdini.py b/verified_cogen/experiments/use_houdini.py index 31fef28..1465ae8 100644 --- a/verified_cogen/experiments/use_houdini.py +++ b/verified_cogen/experiments/use_houdini.py @@ -2,14 +2,13 @@ import json import logging import os - from typing import Optional + +from verified_cogen.llm import LLM from verified_cogen.runners import LLM_GENERATED_DIR from verified_cogen.tools import basename from verified_cogen.tools.verifier import Verifier -from verified_cogen.llm import LLM - log = logging.getLogger(__name__) diff --git a/verified_cogen/main.py b/verified_cogen/main.py index ada38e4..d7b8e64 100644 --- a/verified_cogen/main.py +++ b/verified_cogen/main.py @@ -1,16 +1,16 @@ import logging import pathlib +from verified_cogen.args import get_args from verified_cogen.llm import LLM from verified_cogen.runners.generate import GenerateRunner from verified_cogen.runners.generic import GenericRunner from verified_cogen.runners.invariants import InvariantRunner -from verified_cogen.runners.languages import init_basic_languages +from verified_cogen.runners.languages import register_basic_languages from verified_cogen.runners.validating import ValidatingRunner from verified_cogen.tools import pprint_stat, rename_file, tabulate_list from verified_cogen.tools.modes import Mode from verified_cogen.tools.verifier import Verifier -from verified_cogen.args import get_args logger = logging.getLogger(__name__) @@ -67,7 +67,7 @@ def run_once(files, args, runner, verifier, mode, is_once) -> tuple[int, int, in def main(): - init_basic_languages() + register_basic_languages() args = get_args() mode = Mode(args.insert_conditions_mode) diff --git a/verified_cogen/runners/__init__.py b/verified_cogen/runners/__init__.py index d1a7087..cdb3a2a 100644 --- a/verified_cogen/runners/__init__.py +++ b/verified_cogen/runners/__init__.py @@ -1,11 +1,11 @@ +import pathlib from logging import Logger from typing import Optional -import pathlib +from verified_cogen.llm import LLM from verified_cogen.tools import basename, get_cache_dir from verified_cogen.tools.modes import Mode from verified_cogen.tools.verifier import Verifier -from verified_cogen.llm import LLM LLM_GENERATED_DIR = pathlib.Path(get_cache_dir()) / "llm-generated" diff --git a/verified_cogen/runners/generate.py b/verified_cogen/runners/generate.py index 4163f6f..630400c 100644 --- a/verified_cogen/runners/generate.py +++ b/verified_cogen/runners/generate.py @@ -1,12 +1,10 @@ import logging -from typing import Optional import pathlib - -from verified_cogen.tools.modes import Mode +from typing import Optional from verified_cogen.runners import Runner from verified_cogen.tools import basename, get_cache_dir - +from verified_cogen.tools.modes import Mode LLM_GENERATED_DIR = pathlib.Path(get_cache_dir()) / "llm-generated" diff --git a/verified_cogen/runners/generic.py b/verified_cogen/runners/generic.py index ceff102..a98ff89 100644 --- a/verified_cogen/runners/generic.py +++ b/verified_cogen/runners/generic.py @@ -1,9 +1,7 @@ import logging -from verified_cogen.tools.modes import Mode - -from verified_cogen.llm import LLM from verified_cogen.runners import Runner +from verified_cogen.tools.modes import Mode logger = logging.getLogger(__name__) diff --git a/verified_cogen/runners/invariants.py b/verified_cogen/runners/invariants.py index 7586dc7..8bd08f7 100644 --- a/verified_cogen/runners/invariants.py +++ b/verified_cogen/runners/invariants.py @@ -2,10 +2,9 @@ import re import textwrap -from verified_cogen.tools.modes import Mode - from verified_cogen.llm import LLM from verified_cogen.runners import Runner +from verified_cogen.tools.modes import Mode logger = logging.getLogger(__name__) diff --git a/verified_cogen/runners/languages/__init__.py b/verified_cogen/runners/languages/__init__.py index 2685c41..2ee70a2 100644 --- a/verified_cogen/runners/languages/__init__.py +++ b/verified_cogen/runners/languages/__init__.py @@ -3,6 +3,6 @@ from verified_cogen.runners.languages.nagini import NaginiLanguage -def init_basic_languages(): - LanguageDatabase().add("dafny", ["dfy"], DafnyLanguage()) - LanguageDatabase().add("nagini", ["py", "python"], NaginiLanguage()) +def register_basic_languages(): + LanguageDatabase().register("dafny", ["dfy"], DafnyLanguage()) + LanguageDatabase().register("nagini", ["py", "python"], NaginiLanguage()) diff --git a/verified_cogen/runners/languages/dafny.py b/verified_cogen/runners/languages/dafny.py index a1a2e50..b9c12e8 100644 --- a/verified_cogen/runners/languages/dafny.py +++ b/verified_cogen/runners/languages/dafny.py @@ -1,6 +1,7 @@ +import re from typing import Pattern + from verified_cogen.runners.languages.language import GenericLanguage -import re DAFNY_VALIDATOR_TEMPLATE = """\ method {method_name}_valid({parameters}) returns ({returns}){specs}\ diff --git a/verified_cogen/runners/languages/language.py b/verified_cogen/runners/languages/language.py index 5c93099..a1c6850 100644 --- a/verified_cogen/runners/languages/language.py +++ b/verified_cogen/runners/languages/language.py @@ -90,7 +90,7 @@ def __new__(cls, *args, **kwargs): cls._instance = super().__new__(cls, *args, **kwargs) return cls._instance - def add(self, name: str, aliases: list[str], definition: Language): + def register(self, name: str, aliases: list[str], definition: Language): self.languages[name] = definition self.regularise[name] = name for alias in aliases: diff --git a/verified_cogen/runners/languages/nagini.py b/verified_cogen/runners/languages/nagini.py index 0b294da..76d3f03 100644 --- a/verified_cogen/runners/languages/nagini.py +++ b/verified_cogen/runners/languages/nagini.py @@ -1,6 +1,7 @@ +import re from typing import Pattern + from verified_cogen.runners.languages.language import GenericLanguage -import re NAGINI_VALIDATOR_TEMPLATE = """\ def {method_name}_valid({parameters}) -> {returns}:{specs}\ diff --git a/verified_cogen/runners/validating.py b/verified_cogen/runners/validating.py index ab917a9..247dccd 100644 --- a/verified_cogen/runners/validating.py +++ b/verified_cogen/runners/validating.py @@ -1,24 +1,16 @@ -import re -from logging import Logger +from verified_cogen.runners import Runner from verified_cogen.runners.languages.language import Language from verified_cogen.tools.modes import Mode -from verified_cogen.llm import LLM -from verified_cogen.runners import Runner -from verified_cogen.runners.invariants import InvariantRunner -from verified_cogen.tools.verifier import Verifier - class ValidatingRunner(Runner): - invariant_runner: InvariantRunner + wrapped_runner: Runner language: Language - def __init__( - self, llm: LLM, logger: Logger, verifier: Verifier, language: Language - ): - super().__init__(llm, logger, verifier) - self.invariant_runner = InvariantRunner(llm, logger, verifier) + def __init__(self, wrapping: Runner, language: Language): + super().__init__(wrapping.llm, wrapping.logger, wrapping.verifier) + self.wrapped_runner = wrapping self.language = language def _add_validators(self, prg: str, inv_prg: str): @@ -30,15 +22,13 @@ def preprocess(self, prg: str, mode: Mode) -> str: return self.language.remove_asserts_and_invariants(prg) def rewrite(self, prg: str) -> str: - return self._add_validators(prg, self.invariant_runner.rewrite(prg)) + return self._add_validators(prg, self.wrapped_runner.rewrite(prg)) def produce(self, prg: str) -> str: - return self._add_validators(prg, self.invariant_runner.produce(prg)) + return self._add_validators(prg, self.wrapped_runner.produce(prg)) def insert(self, prg: str, checks: str, mode: Mode) -> str: - return self._add_validators( - prg, self.invariant_runner.insert(prg, checks, mode) - ) + return self._add_validators(prg, self.wrapped_runner.insert(prg, checks, mode)) def precheck(self, prg: str, mode: Mode): - return self.invariant_runner.precheck(prg, mode) + return self.wrapped_runner.precheck(prg, mode) diff --git a/verified_cogen/tools/__init__.py b/verified_cogen/tools/__init__.py index a98349c..10a9ef0 100644 --- a/verified_cogen/tools/__init__.py +++ b/verified_cogen/tools/__init__.py @@ -1,5 +1,6 @@ import pathlib import re + import appdirs diff --git a/verified_cogen/tools/verifier.py b/verified_cogen/tools/verifier.py index ea23760..1873d13 100644 --- a/verified_cogen/tools/verifier.py +++ b/verified_cogen/tools/verifier.py @@ -1,8 +1,7 @@ -from pathlib import Path +import logging import subprocess +from pathlib import Path from typing import Optional -import logging - log = logging.getLogger(__name__) From ddeee1ce1b06bbf05a4cca1505b81ec7c0b4429c Mon Sep 17 00:00:00 2001 From: WeetHet Date: Tue, 10 Sep 2024 14:08:43 +0300 Subject: [PATCH 06/23] add ruff checks --- .github/workflows/{test-pytest.yml => test-pytest-ruff.yml} | 6 +++++- verified_cogen/runners/validating.py | 1 - 2 files changed, 5 insertions(+), 2 deletions(-) rename .github/workflows/{test-pytest.yml => test-pytest-ruff.yml} (86%) diff --git a/.github/workflows/test-pytest.yml b/.github/workflows/test-pytest-ruff.yml similarity index 86% rename from .github/workflows/test-pytest.yml rename to .github/workflows/test-pytest-ruff.yml index 82a3786..fdbd8ff 100644 --- a/.github/workflows/test-pytest.yml +++ b/.github/workflows/test-pytest-ruff.yml @@ -1,4 +1,4 @@ -name: Run pytest +name: Run pytest and ruff on: [push] @@ -34,5 +34,9 @@ jobs: echo "$HOME/.local/bin" >> $GITHUB_PATH - name: Install Dependencies run: poetry install + - name: Run ruff format check + run: poetry run ruff format verified_cogen --check + - name: Run ruff linter + run: poetry run ruff check verified_cogen - name: Run pytest run: poetry run pytest diff --git a/verified_cogen/runners/validating.py b/verified_cogen/runners/validating.py index 247dccd..efa4e82 100644 --- a/verified_cogen/runners/validating.py +++ b/verified_cogen/runners/validating.py @@ -1,4 +1,3 @@ - from verified_cogen.runners import Runner from verified_cogen.runners.languages.language import Language from verified_cogen.tools.modes import Mode From 911343cd6adf32eddf4fc06bb5c82ea4b04bdd43 Mon Sep 17 00:00:00 2001 From: WeetHet Date: Tue, 10 Sep 2024 16:47:22 +0300 Subject: [PATCH 07/23] return lost two step generation --- verified_cogen/runners/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/verified_cogen/runners/__init__.py b/verified_cogen/runners/__init__.py index cdb3a2a..a2a1049 100644 --- a/verified_cogen/runners/__init__.py +++ b/verified_cogen/runners/__init__.py @@ -40,8 +40,11 @@ def preprocess(self, prg: str, mode: Mode) -> str: def invoke(self, prg: str, mode: Mode) -> str: self.logger.info("Invoking LLM") - if mode.is_singlestep: + if mode == Mode.LLM_SINGLE_STEP: inv_prg = self.rewrite(prg) + elif mode == Mode.LLM or mode == Mode.REGEX: + checks = self.produce(prg) + inv_prg = self.insert(prg, checks, mode) else: raise ValueError(f"Unexpected mode: {mode}") self.logger.info("Invocation done") From 4c1a4564dcec997b7ba8d08e70d131550d4a65c4 Mon Sep 17 00:00:00 2001 From: WeetHet Date: Wed, 11 Sep 2024 09:53:33 +0300 Subject: [PATCH 08/23] pre-run prep --- .gitmodules | 4 ++++ benches/HumanEval-Dafny | 1 + prompts/humaneval-dafny/add.txt | 6 +++++ prompts/humaneval-dafny/ask_for_fixed.txt | 4 ++++ .../ask_for_fixed_had_errors.txt | 4 ++++ prompts/humaneval-dafny/produce.txt | 2 ++ prompts/humaneval-dafny/rewrite.txt | 5 +++++ prompts/humaneval-dafny/sys.txt | 4 ++++ pyproject.toml | 1 + results/tries_HumanEval-Dafny.json | 5 +++++ run_validating.sh | 11 ++++++++++ run_with_houdini.sh | 4 +--- verified_cogen/experiments/incremental_run.py | 22 ++++++++++++++----- verified_cogen/runners/invariants.py | 4 ++-- verified_cogen/runners/validating.py | 2 +- verified_cogen/tools/modes.py | 10 ++++----- 16 files changed, 71 insertions(+), 18 deletions(-) create mode 160000 benches/HumanEval-Dafny create mode 100644 prompts/humaneval-dafny/add.txt create mode 100644 prompts/humaneval-dafny/ask_for_fixed.txt create mode 100644 prompts/humaneval-dafny/ask_for_fixed_had_errors.txt create mode 100644 prompts/humaneval-dafny/produce.txt create mode 100644 prompts/humaneval-dafny/rewrite.txt create mode 100644 prompts/humaneval-dafny/sys.txt create mode 100644 results/tries_HumanEval-Dafny.json create mode 100755 run_validating.sh diff --git a/.gitmodules b/.gitmodules index 85b2332..cb6a2f1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,7 @@ [submodule "Nagini-Conversion"] path = Nagini-Conversion url = https://github.com/alex28sh/Nagini-Convertion + +[submodule "benches/HumanEval-Dafny"] + path = benches/HumanEval-Dafny + url = https://github.com/JetBrains-Research/HumanEval-Dafny diff --git a/benches/HumanEval-Dafny b/benches/HumanEval-Dafny new file mode 160000 index 0000000..197aca2 --- /dev/null +++ b/benches/HumanEval-Dafny @@ -0,0 +1 @@ +Subproject commit 197aca2480d30357e97dd087df64cd8808c97a5c diff --git a/prompts/humaneval-dafny/add.txt b/prompts/humaneval-dafny/add.txt new file mode 100644 index 0000000..4e69bb8 --- /dev/null +++ b/prompts/humaneval-dafny/add.txt @@ -0,0 +1,6 @@ +Given the following danfy program, and a set of invariants and assertions, output the program with invariants inserted into the correct place. +The program: +{program} +– +The invariants: +{checks} diff --git a/prompts/humaneval-dafny/ask_for_fixed.txt b/prompts/humaneval-dafny/ask_for_fixed.txt new file mode 100644 index 0000000..d5c6c30 --- /dev/null +++ b/prompts/humaneval-dafny/ask_for_fixed.txt @@ -0,0 +1,4 @@ +The following errors occurred during verification: +{error} + +Please fix the error by adding, removing or modifying the invariants and/or assertions and return the fixed program. diff --git a/prompts/humaneval-dafny/ask_for_fixed_had_errors.txt b/prompts/humaneval-dafny/ask_for_fixed_had_errors.txt new file mode 100644 index 0000000..e2cb9ad --- /dev/null +++ b/prompts/humaneval-dafny/ask_for_fixed_had_errors.txt @@ -0,0 +1,4 @@ +There are still some errors: +{error} + +Could you please fix them? diff --git a/prompts/humaneval-dafny/produce.txt b/prompts/humaneval-dafny/produce.txt new file mode 100644 index 0000000..386fdcb --- /dev/null +++ b/prompts/humaneval-dafny/produce.txt @@ -0,0 +1,2 @@ +Given the following dafny program, output invariants and assertions which are required to prove the program correct. +{program} diff --git a/prompts/humaneval-dafny/rewrite.txt b/prompts/humaneval-dafny/rewrite.txt new file mode 100644 index 0000000..5501d5f --- /dev/null +++ b/prompts/humaneval-dafny/rewrite.txt @@ -0,0 +1,5 @@ +Rewrite the following dafny program, adding correct invariants into `while` loops. +Also add assertions in nessesary places. +Do not change the code, only add invariants and assertions. Don't remove any helper functions, they are there to help you. +The program: +{program} diff --git a/prompts/humaneval-dafny/sys.txt b/prompts/humaneval-dafny/sys.txt new file mode 100644 index 0000000..a86fd57 --- /dev/null +++ b/prompts/humaneval-dafny/sys.txt @@ -0,0 +1,4 @@ +You are an expert in Dafny. +You will be given tasks dealing with Dafny programs including precise docstrings and specifications. +Do not provide explanations. Do not repeat given programs, answer with new content only. +Respond only in dafny code. diff --git a/pyproject.toml b/pyproject.toml index fcb2748..2320531 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,6 +7,7 @@ readme = "README.md" [tool.poetry.scripts] verified-cogen = "verified_cogen.main:main" +incremental_run = "verified_cogen.experiments.incremental_run:main" [tool.isort] profile = "black" diff --git a/results/tries_HumanEval-Dafny.json b/results/tries_HumanEval-Dafny.json new file mode 100644 index 0000000..f3d800a --- /dev/null +++ b/results/tries_HumanEval-Dafny.json @@ -0,0 +1,5 @@ +{ + "002-truncate.dfy": 0, + "083-starts_one_ends.dfy": 0, + "159-eat.dfy": 0 +} \ No newline at end of file diff --git a/run_validating.sh b/run_validating.sh new file mode 100755 index 0000000..e2417a8 --- /dev/null +++ b/run_validating.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +source .venv/bin/activate + +PYLOG_LEVEL=INFO NOFILE=1 incremental_run \ + --grazie-token=$GRAZIE_JWT_TOKEN \ + --llm-profile="anthropic-claude-3.5-sonnet" \ + --prompts-directory=prompts/humaneval-dafny \ + --verifier-command="dafny verify --allow-warnings --verification-time-limit 10" \ + --insert-conditions-mode=llm-single-step \ + --dir="Benches/HumanEval-Dafny" diff --git a/run_with_houdini.sh b/run_with_houdini.sh index 4d1d147..e2f51dd 100755 --- a/run_with_houdini.sh +++ b/run_with_houdini.sh @@ -3,10 +3,8 @@ source .venv/bin/activate source .envrc -export PYTHONPATH=PYTHONPATH:"$(pwd)/src" - PYLOG_LEVEL=INFO NOFILE=1 poetry run python verified_cogen/experiments/use_houdini.py \ - --grazie-token=$GRAZIE_TOKEN \ + --grazie-token=$GRAZIE_JWT_TOKEN \ --profile="anthropic-claude-3.5-sonnet" \ --prompt-dir=prompts/rust_invariants \ --verifier-command="verus --multiple-errors=100" \ diff --git a/verified_cogen/experiments/incremental_run.py b/verified_cogen/experiments/incremental_run.py index c289cb5..47176c2 100644 --- a/verified_cogen/experiments/incremental_run.py +++ b/verified_cogen/experiments/incremental_run.py @@ -1,5 +1,6 @@ import logging import pathlib +import json from verified_cogen.llm.llm import LLM from verified_cogen.main import get_args, rename_file @@ -25,8 +26,15 @@ def main(): assert args.retries == 0 directory = pathlib.Path(args.dir) - marker_directory = pathlib.Path(f"results/tries_{directory.name}") - marker_directory.mkdir(exist_ok=True, parents=True) + results_directory = pathlib.Path("results") + results_directory.mkdir(exist_ok=True) + json_results = pathlib.Path("results") / f"tries_{directory.name}.json" + if not json_results.exists(): + with open(json_results, "w") as f: + json.dump({}, f) + with open(json_results, "r") as f: + results = json.load(f) + files = list(directory.glob("[!.]*.dfy")) verifier = Verifier(args.shell, args.verifier_command) @@ -42,8 +50,8 @@ def main(): language=LanguageDatabase().get("dfy"), ) display_name = rename_file(file) - marker_file = marker_directory.joinpath(file.relative_to(directory)) - if marker_file.exists(): + marker_name = str(file.relative_to(directory)) + if marker_name in results and isinstance(results[marker_name], int): print("Skipping:", display_name) continue print("Processing:", display_name) @@ -54,8 +62,10 @@ def main(): except Exception as e: print(e) tries = None - with marker_file.open("w") as f: - f.write(str(tries)) + if tries is not None: + results[marker_name] = tries + with open(json_results, "w") as f: + json.dump(results, f, indent=2) if __name__ == "__main__": diff --git a/verified_cogen/runners/invariants.py b/verified_cogen/runners/invariants.py index 8bd08f7..4f11407 100644 --- a/verified_cogen/runners/invariants.py +++ b/verified_cogen/runners/invariants.py @@ -35,10 +35,10 @@ def insert_invariants(llm: LLM, prg: str, inv: str, mode: Mode): return insert_invariants_regex(prg, inv) elif mode == Mode.LLM: return insert_invariants_llm(llm, prg, inv) - elif mode.is_singlestep: + elif mode == Mode.LLM_SINGLE_STEP: raise ValueError("Single-step mode does not require insertion") else: - raise ValueError(f"Unexpected mode: {mode}") + raise ValueError(f"insert_invariants: Unexpected mode: {mode}") class InvariantRunner(Runner): diff --git a/verified_cogen/runners/validating.py b/verified_cogen/runners/validating.py index efa4e82..44ace0f 100644 --- a/verified_cogen/runners/validating.py +++ b/verified_cogen/runners/validating.py @@ -24,7 +24,7 @@ def rewrite(self, prg: str) -> str: return self._add_validators(prg, self.wrapped_runner.rewrite(prg)) def produce(self, prg: str) -> str: - return self._add_validators(prg, self.wrapped_runner.produce(prg)) + return self.wrapped_runner.produce(prg) def insert(self, prg: str, checks: str, mode: Mode) -> str: return self._add_validators(prg, self.wrapped_runner.insert(prg, checks, mode)) diff --git a/verified_cogen/tools/modes.py b/verified_cogen/tools/modes.py index 651fcaf..e327fbf 100644 --- a/verified_cogen/tools/modes.py +++ b/verified_cogen/tools/modes.py @@ -2,15 +2,13 @@ class Mode(Enum): - REGEX = "regex", False - LLM = "llm", False - LLM_SINGLE_STEP = "llm-single-step", True - is_singlestep: bool + REGEX = "regex" + LLM = "llm" + LLM_SINGLE_STEP = "llm-single-step" - def __new__(cls, id: str, is_singlestep: bool): + def __new__(cls, id: str): obj = object.__new__(cls) obj._value_ = id - obj.is_singlestep = is_singlestep return obj def __repr__(self): From 561b8d3d682efc1274d21b133477804a07987075 Mon Sep 17 00:00:00 2001 From: WeetHet Date: Wed, 11 Sep 2024 12:11:59 +0300 Subject: [PATCH 09/23] run with dafny --- .gitignore | 2 + poetry.lock | 1288 ++++++++++++++++- prompts/humaneval-dafny/rewrite.txt | 35 + prompts/humaneval-dafny/sys.txt | 3 +- pyproject.toml | 2 + results/tries_HumanEval-Dafny.json | 5 - run_validating.sh | 1 + scripts/generate_result_graph.py | 25 + verified_cogen/experiments/incremental_run.py | 8 +- verified_cogen/runners/__init__.py | 2 +- verified_cogen/runners/languages/language.py | 1 - 11 files changed, 1360 insertions(+), 12 deletions(-) delete mode 100644 results/tries_HumanEval-Dafny.json create mode 100644 scripts/generate_result_graph.py diff --git a/.gitignore b/.gitignore index 4671105..74d8be1 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,5 @@ run.sh **/.pytest_cache run_nagini.py /tmp +results +results/* diff --git a/poetry.lock b/poetry.lock index 639ff71..17a6c21 100644 --- a/poetry.lock +++ b/poetry.lock @@ -44,6 +44,35 @@ files = [ {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, ] +[[package]] +name = "appnope" +version = "0.1.4" +description = "Disable App Nap on macOS >= 10.9" +optional = false +python-versions = ">=3.6" +files = [ + {file = "appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c"}, + {file = "appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"}, +] + +[[package]] +name = "asttokens" +version = "2.4.1" +description = "Annotate AST trees with source code positions" +optional = false +python-versions = "*" +files = [ + {file = "asttokens-2.4.1-py2.py3-none-any.whl", hash = "sha256:051ed49c3dcae8913ea7cd08e46a606dba30b79993209636c4875bc1d637bc24"}, + {file = "asttokens-2.4.1.tar.gz", hash = "sha256:b03869718ba9a6eb027e134bfdf69f38a236d681c83c160d510768af11254ba0"}, +] + +[package.dependencies] +six = ">=1.12.0" + +[package.extras] +astroid = ["astroid (>=1,<2)", "astroid (>=2,<4)"] +test = ["astroid (>=1,<2)", "astroid (>=2,<4)", "pytest"] + [[package]] name = "attrs" version = "23.2.0" @@ -125,6 +154,85 @@ files = [ {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, ] +[[package]] +name = "cffi" +version = "1.17.1" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, +] + +[package.dependencies] +pycparser = "*" + [[package]] name = "charset-normalizer" version = "3.3.2" @@ -235,6 +343,164 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "comm" +version = "0.2.2" +description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." +optional = false +python-versions = ">=3.8" +files = [ + {file = "comm-0.2.2-py3-none-any.whl", hash = "sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3"}, + {file = "comm-0.2.2.tar.gz", hash = "sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e"}, +] + +[package.dependencies] +traitlets = ">=4" + +[package.extras] +test = ["pytest"] + +[[package]] +name = "contourpy" +version = "1.3.0" +description = "Python library for calculating contours of 2D quadrilateral grids" +optional = false +python-versions = ">=3.9" +files = [ + {file = "contourpy-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:880ea32e5c774634f9fcd46504bf9f080a41ad855f4fef54f5380f5133d343c7"}, + {file = "contourpy-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:76c905ef940a4474a6289c71d53122a4f77766eef23c03cd57016ce19d0f7b42"}, + {file = "contourpy-1.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92f8557cbb07415a4d6fa191f20fd9d2d9eb9c0b61d1b2f52a8926e43c6e9af7"}, + {file = "contourpy-1.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:36f965570cff02b874773c49bfe85562b47030805d7d8360748f3eca570f4cab"}, + {file = "contourpy-1.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cacd81e2d4b6f89c9f8a5b69b86490152ff39afc58a95af002a398273e5ce589"}, + {file = "contourpy-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69375194457ad0fad3a839b9e29aa0b0ed53bb54db1bfb6c3ae43d111c31ce41"}, + {file = "contourpy-1.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7a52040312b1a858b5e31ef28c2e865376a386c60c0e248370bbea2d3f3b760d"}, + {file = "contourpy-1.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3faeb2998e4fcb256542e8a926d08da08977f7f5e62cf733f3c211c2a5586223"}, + {file = "contourpy-1.3.0-cp310-cp310-win32.whl", hash = "sha256:36e0cff201bcb17a0a8ecc7f454fe078437fa6bda730e695a92f2d9932bd507f"}, + {file = "contourpy-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:87ddffef1dbe5e669b5c2440b643d3fdd8622a348fe1983fad7a0f0ccb1cd67b"}, + {file = "contourpy-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0fa4c02abe6c446ba70d96ece336e621efa4aecae43eaa9b030ae5fb92b309ad"}, + {file = "contourpy-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:834e0cfe17ba12f79963861e0f908556b2cedd52e1f75e6578801febcc6a9f49"}, + {file = "contourpy-1.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dbc4c3217eee163fa3984fd1567632b48d6dfd29216da3ded3d7b844a8014a66"}, + {file = "contourpy-1.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4865cd1d419e0c7a7bf6de1777b185eebdc51470800a9f42b9e9decf17762081"}, + {file = "contourpy-1.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:303c252947ab4b14c08afeb52375b26781ccd6a5ccd81abcdfc1fafd14cf93c1"}, + {file = "contourpy-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:637f674226be46f6ba372fd29d9523dd977a291f66ab2a74fbeb5530bb3f445d"}, + {file = "contourpy-1.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:76a896b2f195b57db25d6b44e7e03f221d32fe318d03ede41f8b4d9ba1bff53c"}, + {file = "contourpy-1.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e1fd23e9d01591bab45546c089ae89d926917a66dceb3abcf01f6105d927e2cb"}, + {file = "contourpy-1.3.0-cp311-cp311-win32.whl", hash = "sha256:d402880b84df3bec6eab53cd0cf802cae6a2ef9537e70cf75e91618a3801c20c"}, + {file = "contourpy-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:6cb6cc968059db9c62cb35fbf70248f40994dfcd7aa10444bbf8b3faeb7c2d67"}, + {file = "contourpy-1.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:570ef7cf892f0afbe5b2ee410c507ce12e15a5fa91017a0009f79f7d93a1268f"}, + {file = "contourpy-1.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:da84c537cb8b97d153e9fb208c221c45605f73147bd4cadd23bdae915042aad6"}, + {file = "contourpy-1.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0be4d8425bfa755e0fd76ee1e019636ccc7c29f77a7c86b4328a9eb6a26d0639"}, + {file = "contourpy-1.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9c0da700bf58f6e0b65312d0a5e695179a71d0163957fa381bb3c1f72972537c"}, + {file = "contourpy-1.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eb8b141bb00fa977d9122636b16aa67d37fd40a3d8b52dd837e536d64b9a4d06"}, + {file = "contourpy-1.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3634b5385c6716c258d0419c46d05c8aa7dc8cb70326c9a4fb66b69ad2b52e09"}, + {file = "contourpy-1.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0dce35502151b6bd35027ac39ba6e5a44be13a68f55735c3612c568cac3805fd"}, + {file = "contourpy-1.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:aea348f053c645100612b333adc5983d87be69acdc6d77d3169c090d3b01dc35"}, + {file = "contourpy-1.3.0-cp312-cp312-win32.whl", hash = "sha256:90f73a5116ad1ba7174341ef3ea5c3150ddf20b024b98fb0c3b29034752c8aeb"}, + {file = "contourpy-1.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:b11b39aea6be6764f84360fce6c82211a9db32a7c7de8fa6dd5397cf1d079c3b"}, + {file = "contourpy-1.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3e1c7fa44aaae40a2247e2e8e0627f4bea3dd257014764aa644f319a5f8600e3"}, + {file = "contourpy-1.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:364174c2a76057feef647c802652f00953b575723062560498dc7930fc9b1cb7"}, + {file = "contourpy-1.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32b238b3b3b649e09ce9aaf51f0c261d38644bdfa35cbaf7b263457850957a84"}, + {file = "contourpy-1.3.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d51fca85f9f7ad0b65b4b9fe800406d0d77017d7270d31ec3fb1cc07358fdea0"}, + {file = "contourpy-1.3.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:732896af21716b29ab3e988d4ce14bc5133733b85956316fb0c56355f398099b"}, + {file = "contourpy-1.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d73f659398a0904e125280836ae6f88ba9b178b2fed6884f3b1f95b989d2c8da"}, + {file = "contourpy-1.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c6c7c2408b7048082932cf4e641fa3b8ca848259212f51c8c59c45aa7ac18f14"}, + {file = "contourpy-1.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f317576606de89da6b7e0861cf6061f6146ead3528acabff9236458a6ba467f8"}, + {file = "contourpy-1.3.0-cp313-cp313-win32.whl", hash = "sha256:31cd3a85dbdf1fc002280c65caa7e2b5f65e4a973fcdf70dd2fdcb9868069294"}, + {file = "contourpy-1.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:4553c421929ec95fb07b3aaca0fae668b2eb5a5203d1217ca7c34c063c53d087"}, + {file = "contourpy-1.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:345af746d7766821d05d72cb8f3845dfd08dd137101a2cb9b24de277d716def8"}, + {file = "contourpy-1.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3bb3808858a9dc68f6f03d319acd5f1b8a337e6cdda197f02f4b8ff67ad2057b"}, + {file = "contourpy-1.3.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:420d39daa61aab1221567b42eecb01112908b2cab7f1b4106a52caaec8d36973"}, + {file = "contourpy-1.3.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4d63ee447261e963af02642ffcb864e5a2ee4cbfd78080657a9880b8b1868e18"}, + {file = "contourpy-1.3.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:167d6c890815e1dac9536dca00828b445d5d0df4d6a8c6adb4a7ec3166812fa8"}, + {file = "contourpy-1.3.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:710a26b3dc80c0e4febf04555de66f5fd17e9cf7170a7b08000601a10570bda6"}, + {file = "contourpy-1.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:75ee7cb1a14c617f34a51d11fa7524173e56551646828353c4af859c56b766e2"}, + {file = "contourpy-1.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:33c92cdae89ec5135d036e7218e69b0bb2851206077251f04a6c4e0e21f03927"}, + {file = "contourpy-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a11077e395f67ffc2c44ec2418cfebed032cd6da3022a94fc227b6faf8e2acb8"}, + {file = "contourpy-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e8134301d7e204c88ed7ab50028ba06c683000040ede1d617298611f9dc6240c"}, + {file = "contourpy-1.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e12968fdfd5bb45ffdf6192a590bd8ddd3ba9e58360b29683c6bb71a7b41edca"}, + {file = "contourpy-1.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fd2a0fc506eccaaa7595b7e1418951f213cf8255be2600f1ea1b61e46a60c55f"}, + {file = "contourpy-1.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4cfb5c62ce023dfc410d6059c936dcf96442ba40814aefbfa575425a3a7f19dc"}, + {file = "contourpy-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68a32389b06b82c2fdd68276148d7b9275b5f5cf13e5417e4252f6d1a34f72a2"}, + {file = "contourpy-1.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:94e848a6b83da10898cbf1311a815f770acc9b6a3f2d646f330d57eb4e87592e"}, + {file = "contourpy-1.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d78ab28a03c854a873787a0a42254a0ccb3cb133c672f645c9f9c8f3ae9d0800"}, + {file = "contourpy-1.3.0-cp39-cp39-win32.whl", hash = "sha256:81cb5ed4952aae6014bc9d0421dec7c5835c9c8c31cdf51910b708f548cf58e5"}, + {file = "contourpy-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:14e262f67bd7e6eb6880bc564dcda30b15e351a594657e55b7eec94b6ef72843"}, + {file = "contourpy-1.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:fe41b41505a5a33aeaed2a613dccaeaa74e0e3ead6dd6fd3a118fb471644fd6c"}, + {file = "contourpy-1.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eca7e17a65f72a5133bdbec9ecf22401c62bcf4821361ef7811faee695799779"}, + {file = "contourpy-1.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1ec4dc6bf570f5b22ed0d7efba0dfa9c5b9e0431aeea7581aa217542d9e809a4"}, + {file = "contourpy-1.3.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:00ccd0dbaad6d804ab259820fa7cb0b8036bda0686ef844d24125d8287178ce0"}, + {file = "contourpy-1.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ca947601224119117f7c19c9cdf6b3ab54c5726ef1d906aa4a69dfb6dd58102"}, + {file = "contourpy-1.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c6ec93afeb848a0845a18989da3beca3eec2c0f852322efe21af1931147d12cb"}, + {file = "contourpy-1.3.0.tar.gz", hash = "sha256:7ffa0db17717a8ffb127efd0c95a4362d996b892c2904db72428d5b52e1938a4"}, +] + +[package.dependencies] +numpy = ">=1.23" + +[package.extras] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] +mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.11.1)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "pytest-rerunfailures", "pytest-xdist", "wurlitzer"] + +[[package]] +name = "cycler" +version = "0.12.1" +description = "Composable style cycles" +optional = false +python-versions = ">=3.8" +files = [ + {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, + {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, +] + +[package.extras] +docs = ["ipython", "matplotlib", "numpydoc", "sphinx"] +tests = ["pytest", "pytest-cov", "pytest-xdist"] + +[[package]] +name = "debugpy" +version = "1.8.5" +description = "An implementation of the Debug Adapter Protocol for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "debugpy-1.8.5-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:7e4d594367d6407a120b76bdaa03886e9eb652c05ba7f87e37418426ad2079f7"}, + {file = "debugpy-1.8.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4413b7a3ede757dc33a273a17d685ea2b0c09dbd312cc03f5534a0fd4d40750a"}, + {file = "debugpy-1.8.5-cp310-cp310-win32.whl", hash = "sha256:dd3811bd63632bb25eda6bd73bea8e0521794cda02be41fa3160eb26fc29e7ed"}, + {file = "debugpy-1.8.5-cp310-cp310-win_amd64.whl", hash = "sha256:b78c1250441ce893cb5035dd6f5fc12db968cc07f91cc06996b2087f7cefdd8e"}, + {file = "debugpy-1.8.5-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:606bccba19f7188b6ea9579c8a4f5a5364ecd0bf5a0659c8a5d0e10dcee3032a"}, + {file = "debugpy-1.8.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db9fb642938a7a609a6c865c32ecd0d795d56c1aaa7a7a5722d77855d5e77f2b"}, + {file = "debugpy-1.8.5-cp311-cp311-win32.whl", hash = "sha256:4fbb3b39ae1aa3e5ad578f37a48a7a303dad9a3d018d369bc9ec629c1cfa7408"}, + {file = "debugpy-1.8.5-cp311-cp311-win_amd64.whl", hash = "sha256:345d6a0206e81eb68b1493ce2fbffd57c3088e2ce4b46592077a943d2b968ca3"}, + {file = "debugpy-1.8.5-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:5b5c770977c8ec6c40c60d6f58cacc7f7fe5a45960363d6974ddb9b62dbee156"}, + {file = "debugpy-1.8.5-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0a65b00b7cdd2ee0c2cf4c7335fef31e15f1b7056c7fdbce9e90193e1a8c8cb"}, + {file = "debugpy-1.8.5-cp312-cp312-win32.whl", hash = "sha256:c9f7c15ea1da18d2fcc2709e9f3d6de98b69a5b0fff1807fb80bc55f906691f7"}, + {file = "debugpy-1.8.5-cp312-cp312-win_amd64.whl", hash = "sha256:28ced650c974aaf179231668a293ecd5c63c0a671ae6d56b8795ecc5d2f48d3c"}, + {file = "debugpy-1.8.5-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:3df6692351172a42af7558daa5019651f898fc67450bf091335aa8a18fbf6f3a"}, + {file = "debugpy-1.8.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1cd04a73eb2769eb0bfe43f5bfde1215c5923d6924b9b90f94d15f207a402226"}, + {file = "debugpy-1.8.5-cp38-cp38-win32.whl", hash = "sha256:8f913ee8e9fcf9d38a751f56e6de12a297ae7832749d35de26d960f14280750a"}, + {file = "debugpy-1.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:a697beca97dad3780b89a7fb525d5e79f33821a8bc0c06faf1f1289e549743cf"}, + {file = "debugpy-1.8.5-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:0a1029a2869d01cb777216af8c53cda0476875ef02a2b6ff8b2f2c9a4b04176c"}, + {file = "debugpy-1.8.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84c276489e141ed0b93b0af648eef891546143d6a48f610945416453a8ad406"}, + {file = "debugpy-1.8.5-cp39-cp39-win32.whl", hash = "sha256:ad84b7cde7fd96cf6eea34ff6c4a1b7887e0fe2ea46e099e53234856f9d99a34"}, + {file = "debugpy-1.8.5-cp39-cp39-win_amd64.whl", hash = "sha256:7b0fe36ed9d26cb6836b0a51453653f8f2e347ba7348f2bbfe76bfeb670bfb1c"}, + {file = "debugpy-1.8.5-py2.py3-none-any.whl", hash = "sha256:55919dce65b471eff25901acf82d328bbd5b833526b6c1364bd5133754777a44"}, + {file = "debugpy-1.8.5.zip", hash = "sha256:b2112cfeb34b4507399d298fe7023a16656fc553ed5246536060ca7bd0e668d0"}, +] + +[[package]] +name = "decorator" +version = "5.1.1" +description = "Decorators for Humans" +optional = false +python-versions = ">=3.5" +files = [ + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, +] + [[package]] name = "exceptiongroup" version = "1.2.2" @@ -249,6 +515,85 @@ files = [ [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "executing" +version = "2.1.0" +description = "Get the currently executing AST node of a frame, and other information" +optional = false +python-versions = ">=3.8" +files = [ + {file = "executing-2.1.0-py2.py3-none-any.whl", hash = "sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf"}, + {file = "executing-2.1.0.tar.gz", hash = "sha256:8ea27ddd260da8150fa5a708269c4a10e76161e2496ec3e587da9e3c0fe4b9ab"}, +] + +[package.extras] +tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich"] + +[[package]] +name = "fonttools" +version = "4.53.1" +description = "Tools to manipulate font files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fonttools-4.53.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0679a30b59d74b6242909945429dbddb08496935b82f91ea9bf6ad240ec23397"}, + {file = "fonttools-4.53.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e8bf06b94694251861ba7fdeea15c8ec0967f84c3d4143ae9daf42bbc7717fe3"}, + {file = "fonttools-4.53.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b96cd370a61f4d083c9c0053bf634279b094308d52fdc2dd9a22d8372fdd590d"}, + {file = "fonttools-4.53.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1c7c5aa18dd3b17995898b4a9b5929d69ef6ae2af5b96d585ff4005033d82f0"}, + {file = "fonttools-4.53.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e013aae589c1c12505da64a7d8d023e584987e51e62006e1bb30d72f26522c41"}, + {file = "fonttools-4.53.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9efd176f874cb6402e607e4cc9b4a9cd584d82fc34a4b0c811970b32ba62501f"}, + {file = "fonttools-4.53.1-cp310-cp310-win32.whl", hash = "sha256:c8696544c964500aa9439efb6761947393b70b17ef4e82d73277413f291260a4"}, + {file = "fonttools-4.53.1-cp310-cp310-win_amd64.whl", hash = "sha256:8959a59de5af6d2bec27489e98ef25a397cfa1774b375d5787509c06659b3671"}, + {file = "fonttools-4.53.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:da33440b1413bad53a8674393c5d29ce64d8c1a15ef8a77c642ffd900d07bfe1"}, + {file = "fonttools-4.53.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ff7e5e9bad94e3a70c5cd2fa27f20b9bb9385e10cddab567b85ce5d306ea923"}, + {file = "fonttools-4.53.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6e7170d675d12eac12ad1a981d90f118c06cf680b42a2d74c6c931e54b50719"}, + {file = "fonttools-4.53.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bee32ea8765e859670c4447b0817514ca79054463b6b79784b08a8df3a4d78e3"}, + {file = "fonttools-4.53.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6e08f572625a1ee682115223eabebc4c6a2035a6917eac6f60350aba297ccadb"}, + {file = "fonttools-4.53.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b21952c092ffd827504de7e66b62aba26fdb5f9d1e435c52477e6486e9d128b2"}, + {file = "fonttools-4.53.1-cp311-cp311-win32.whl", hash = "sha256:9dfdae43b7996af46ff9da520998a32b105c7f098aeea06b2226b30e74fbba88"}, + {file = "fonttools-4.53.1-cp311-cp311-win_amd64.whl", hash = "sha256:d4d0096cb1ac7a77b3b41cd78c9b6bc4a400550e21dc7a92f2b5ab53ed74eb02"}, + {file = "fonttools-4.53.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d92d3c2a1b39631a6131c2fa25b5406855f97969b068e7e08413325bc0afba58"}, + {file = "fonttools-4.53.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3b3c8ebafbee8d9002bd8f1195d09ed2bd9ff134ddec37ee8f6a6375e6a4f0e8"}, + {file = "fonttools-4.53.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32f029c095ad66c425b0ee85553d0dc326d45d7059dbc227330fc29b43e8ba60"}, + {file = "fonttools-4.53.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10f5e6c3510b79ea27bb1ebfcc67048cde9ec67afa87c7dd7efa5c700491ac7f"}, + {file = "fonttools-4.53.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f677ce218976496a587ab17140da141557beb91d2a5c1a14212c994093f2eae2"}, + {file = "fonttools-4.53.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9e6ceba2a01b448e36754983d376064730690401da1dd104ddb543519470a15f"}, + {file = "fonttools-4.53.1-cp312-cp312-win32.whl", hash = "sha256:791b31ebbc05197d7aa096bbc7bd76d591f05905d2fd908bf103af4488e60670"}, + {file = "fonttools-4.53.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ed170b5e17da0264b9f6fae86073be3db15fa1bd74061c8331022bca6d09bab"}, + {file = "fonttools-4.53.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c818c058404eb2bba05e728d38049438afd649e3c409796723dfc17cd3f08749"}, + {file = "fonttools-4.53.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:651390c3b26b0c7d1f4407cad281ee7a5a85a31a110cbac5269de72a51551ba2"}, + {file = "fonttools-4.53.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e54f1bba2f655924c1138bbc7fa91abd61f45c68bd65ab5ed985942712864bbb"}, + {file = "fonttools-4.53.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9cd19cf4fe0595ebdd1d4915882b9440c3a6d30b008f3cc7587c1da7b95be5f"}, + {file = "fonttools-4.53.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2af40ae9cdcb204fc1d8f26b190aa16534fcd4f0df756268df674a270eab575d"}, + {file = "fonttools-4.53.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:35250099b0cfb32d799fb5d6c651220a642fe2e3c7d2560490e6f1d3f9ae9169"}, + {file = "fonttools-4.53.1-cp38-cp38-win32.whl", hash = "sha256:f08df60fbd8d289152079a65da4e66a447efc1d5d5a4d3f299cdd39e3b2e4a7d"}, + {file = "fonttools-4.53.1-cp38-cp38-win_amd64.whl", hash = "sha256:7b6b35e52ddc8fb0db562133894e6ef5b4e54e1283dff606fda3eed938c36fc8"}, + {file = "fonttools-4.53.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75a157d8d26c06e64ace9df037ee93a4938a4606a38cb7ffaf6635e60e253b7a"}, + {file = "fonttools-4.53.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4824c198f714ab5559c5be10fd1adf876712aa7989882a4ec887bf1ef3e00e31"}, + {file = "fonttools-4.53.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:becc5d7cb89c7b7afa8321b6bb3dbee0eec2b57855c90b3e9bf5fb816671fa7c"}, + {file = "fonttools-4.53.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:84ec3fb43befb54be490147b4a922b5314e16372a643004f182babee9f9c3407"}, + {file = "fonttools-4.53.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:73379d3ffdeecb376640cd8ed03e9d2d0e568c9d1a4e9b16504a834ebadc2dfb"}, + {file = "fonttools-4.53.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:02569e9a810f9d11f4ae82c391ebc6fb5730d95a0657d24d754ed7763fb2d122"}, + {file = "fonttools-4.53.1-cp39-cp39-win32.whl", hash = "sha256:aae7bd54187e8bf7fd69f8ab87b2885253d3575163ad4d669a262fe97f0136cb"}, + {file = "fonttools-4.53.1-cp39-cp39-win_amd64.whl", hash = "sha256:e5b708073ea3d684235648786f5f6153a48dc8762cdfe5563c57e80787c29fbb"}, + {file = "fonttools-4.53.1-py3-none-any.whl", hash = "sha256:f1f8758a2ad110bd6432203a344269f445a2907dc24ef6bccfd0ac4e14e0d71d"}, + {file = "fonttools-4.53.1.tar.gz", hash = "sha256:e128778a8e9bc11159ce5447f76766cefbd876f44bd79aff030287254e4752c4"}, +] + +[package.extras] +all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "pycairo", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.1.0)", "xattr", "zopfli (>=0.1.4)"] +graphite = ["lz4 (>=1.7.4.2)"] +interpolatable = ["munkres", "pycairo", "scipy"] +lxml = ["lxml (>=4.0)"] +pathops = ["skia-pathops (>=0.5.0)"] +plot = ["matplotlib"] +repacker = ["uharfbuzz (>=0.23.0)"] +symfont = ["sympy"] +type1 = ["xattr"] +ufo = ["fs (>=2.2.0,<3)"] +unicode = ["unicodedata2 (>=15.1.0)"] +woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] + [[package]] name = "grazie-api-gateway-client" version = "0.1.7" @@ -341,6 +686,47 @@ files = [ {file = "idna-3.8.tar.gz", hash = "sha256:d838c2c0ed6fced7693d5e8ab8e734d5f8fda53a039c0164afb0b82e771e3603"}, ] +[[package]] +name = "importlib-metadata" +version = "8.4.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-8.4.0-py3-none-any.whl", hash = "sha256:66f342cc6ac9818fc6ff340576acd24d65ba0b3efabb2b4ac08b598965a4a2f1"}, + {file = "importlib_metadata-8.4.0.tar.gz", hash = "sha256:9a547d3bc3608b025f93d403fdd1aae741c24fbb8314df4b155675742ce303c5"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] + +[[package]] +name = "importlib-resources" +version = "6.4.5" +description = "Read resources from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_resources-6.4.5-py3-none-any.whl", hash = "sha256:ac29d5f956f01d5e4bb63102a5a19957f1b9175e45649977264a1416783bb717"}, + {file = "importlib_resources-6.4.5.tar.gz", hash = "sha256:980862a1d16c9e147a59603677fa2aa5fd82b87f223b6cb870695bcfce830065"}, +] + +[package.dependencies] +zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["jaraco.test (>=5.4)", "pytest (>=6,!=8.1.*)", "zipp (>=3.17)"] +type = ["pytest-mypy"] + [[package]] name = "iniconfig" version = "2.0.0" @@ -352,6 +738,76 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +[[package]] +name = "ipykernel" +version = "6.29.5" +description = "IPython Kernel for Jupyter" +optional = false +python-versions = ">=3.8" +files = [ + {file = "ipykernel-6.29.5-py3-none-any.whl", hash = "sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5"}, + {file = "ipykernel-6.29.5.tar.gz", hash = "sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215"}, +] + +[package.dependencies] +appnope = {version = "*", markers = "platform_system == \"Darwin\""} +comm = ">=0.1.1" +debugpy = ">=1.6.5" +ipython = ">=7.23.1" +jupyter-client = ">=6.1.12" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +matplotlib-inline = ">=0.1" +nest-asyncio = "*" +packaging = "*" +psutil = "*" +pyzmq = ">=24" +tornado = ">=6.1" +traitlets = ">=5.4.0" + +[package.extras] +cov = ["coverage[toml]", "curio", "matplotlib", "pytest-cov", "trio"] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "trio"] +pyqt5 = ["pyqt5"] +pyside6 = ["pyside6"] +test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.23.5)", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "ipython" +version = "8.18.1" +description = "IPython: Productive Interactive Computing" +optional = false +python-versions = ">=3.9" +files = [ + {file = "ipython-8.18.1-py3-none-any.whl", hash = "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397"}, + {file = "ipython-8.18.1.tar.gz", hash = "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +decorator = "*" +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} +jedi = ">=0.16" +matplotlib-inline = "*" +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} +prompt-toolkit = ">=3.0.41,<3.1.0" +pygments = ">=2.4.0" +stack-data = "*" +traitlets = ">=5" +typing-extensions = {version = "*", markers = "python_version < \"3.10\""} + +[package.extras] +all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +black = ["black"] +doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +kernel = ["ipykernel"] +nbconvert = ["nbconvert"] +nbformat = ["nbformat"] +notebook = ["ipywidgets", "notebook"] +parallel = ["ipyparallel"] +qtconsole = ["qtconsole"] +test = ["pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath", "trio"] + [[package]] name = "isort" version = "5.13.2" @@ -366,6 +822,25 @@ files = [ [package.extras] colors = ["colorama (>=0.4.6)"] +[[package]] +name = "jedi" +version = "0.19.1" +description = "An autocompletion tool for Python that can be used for text editors." +optional = false +python-versions = ">=3.6" +files = [ + {file = "jedi-0.19.1-py2.py3-none-any.whl", hash = "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0"}, + {file = "jedi-0.19.1.tar.gz", hash = "sha256:cf0496f3651bc65d7174ac1b7d043eff454892c708a87d1b683e57b569927ffd"}, +] + +[package.dependencies] +parso = ">=0.8.3,<0.9.0" + +[package.extras] +docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"] + [[package]] name = "jsonschema" version = "4.23.0" @@ -401,6 +876,315 @@ files = [ [package.dependencies] referencing = ">=0.31.0" +[[package]] +name = "jupyter-client" +version = "8.6.2" +description = "Jupyter protocol implementation and client libraries" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_client-8.6.2-py3-none-any.whl", hash = "sha256:50cbc5c66fd1b8f65ecb66bc490ab73217993632809b6e505687de18e9dea39f"}, + {file = "jupyter_client-8.6.2.tar.gz", hash = "sha256:2bda14d55ee5ba58552a8c53ae43d215ad9868853489213f37da060ced54d8df"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +python-dateutil = ">=2.8.2" +pyzmq = ">=23.0" +tornado = ">=6.2" +traitlets = ">=5.3" + +[package.extras] +docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest (<8.2.0)", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] + +[[package]] +name = "jupyter-core" +version = "5.7.2" +description = "Jupyter core package. A base package on which Jupyter projects rely." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_core-5.7.2-py3-none-any.whl", hash = "sha256:4f7315d2f6b4bcf2e3e7cb6e46772eba760ae459cd1f59d29eb57b0a01bd7409"}, + {file = "jupyter_core-5.7.2.tar.gz", hash = "sha256:aa5f8d32bbf6b431ac830496da7392035d6f61b4f54872f15c4bd2a9c3f536d9"}, +] + +[package.dependencies] +platformdirs = ">=2.5" +pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} +traitlets = ">=5.3" + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "traitlets"] +test = ["ipykernel", "pre-commit", "pytest (<8)", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "kiwisolver" +version = "1.4.7" +description = "A fast implementation of the Cassowary constraint solver" +optional = false +python-versions = ">=3.8" +files = [ + {file = "kiwisolver-1.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8a9c83f75223d5e48b0bc9cb1bf2776cf01563e00ade8775ffe13b0b6e1af3a6"}, + {file = "kiwisolver-1.4.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:58370b1ffbd35407444d57057b57da5d6549d2d854fa30249771775c63b5fe17"}, + {file = "kiwisolver-1.4.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:aa0abdf853e09aff551db11fce173e2177d00786c688203f52c87ad7fcd91ef9"}, + {file = "kiwisolver-1.4.7-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8d53103597a252fb3ab8b5845af04c7a26d5e7ea8122303dd7a021176a87e8b9"}, + {file = "kiwisolver-1.4.7-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:88f17c5ffa8e9462fb79f62746428dd57b46eb931698e42e990ad63103f35e6c"}, + {file = "kiwisolver-1.4.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88a9ca9c710d598fd75ee5de59d5bda2684d9db36a9f50b6125eaea3969c2599"}, + {file = "kiwisolver-1.4.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f4d742cb7af1c28303a51b7a27aaee540e71bb8e24f68c736f6f2ffc82f2bf05"}, + {file = "kiwisolver-1.4.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e28c7fea2196bf4c2f8d46a0415c77a1c480cc0724722f23d7410ffe9842c407"}, + {file = "kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e968b84db54f9d42046cf154e02911e39c0435c9801681e3fc9ce8a3c4130278"}, + {file = "kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0c18ec74c0472de033e1bebb2911c3c310eef5649133dd0bedf2a169a1b269e5"}, + {file = "kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8f0ea6da6d393d8b2e187e6a5e3fb81f5862010a40c3945e2c6d12ae45cfb2ad"}, + {file = "kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:f106407dda69ae456dd1227966bf445b157ccc80ba0dff3802bb63f30b74e895"}, + {file = "kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:84ec80df401cfee1457063732d90022f93951944b5b58975d34ab56bb150dfb3"}, + {file = "kiwisolver-1.4.7-cp310-cp310-win32.whl", hash = "sha256:71bb308552200fb2c195e35ef05de12f0c878c07fc91c270eb3d6e41698c3bcc"}, + {file = "kiwisolver-1.4.7-cp310-cp310-win_amd64.whl", hash = "sha256:44756f9fd339de0fb6ee4f8c1696cfd19b2422e0d70b4cefc1cc7f1f64045a8c"}, + {file = "kiwisolver-1.4.7-cp310-cp310-win_arm64.whl", hash = "sha256:78a42513018c41c2ffd262eb676442315cbfe3c44eed82385c2ed043bc63210a"}, + {file = "kiwisolver-1.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d2b0e12a42fb4e72d509fc994713d099cbb15ebf1103545e8a45f14da2dfca54"}, + {file = "kiwisolver-1.4.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2a8781ac3edc42ea4b90bc23e7d37b665d89423818e26eb6df90698aa2287c95"}, + {file = "kiwisolver-1.4.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:46707a10836894b559e04b0fd143e343945c97fd170d69a2d26d640b4e297935"}, + {file = "kiwisolver-1.4.7-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef97b8df011141c9b0f6caf23b29379f87dd13183c978a30a3c546d2c47314cb"}, + {file = "kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab58c12a2cd0fc769089e6d38466c46d7f76aced0a1f54c77652446733d2d02"}, + {file = "kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:803b8e1459341c1bb56d1c5c010406d5edec8a0713a0945851290a7930679b51"}, + {file = "kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9a9e8a507420fe35992ee9ecb302dab68550dedc0da9e2880dd88071c5fb052"}, + {file = "kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18077b53dc3bb490e330669a99920c5e6a496889ae8c63b58fbc57c3d7f33a18"}, + {file = "kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6af936f79086a89b3680a280c47ea90b4df7047b5bdf3aa5c524bbedddb9e545"}, + {file = "kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3abc5b19d24af4b77d1598a585b8a719beb8569a71568b66f4ebe1fb0449460b"}, + {file = "kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:933d4de052939d90afbe6e9d5273ae05fb836cc86c15b686edd4b3560cc0ee36"}, + {file = "kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:65e720d2ab2b53f1f72fb5da5fb477455905ce2c88aaa671ff0a447c2c80e8e3"}, + {file = "kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3bf1ed55088f214ba6427484c59553123fdd9b218a42bbc8c6496d6754b1e523"}, + {file = "kiwisolver-1.4.7-cp311-cp311-win32.whl", hash = "sha256:4c00336b9dd5ad96d0a558fd18a8b6f711b7449acce4c157e7343ba92dd0cf3d"}, + {file = "kiwisolver-1.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:929e294c1ac1e9f615c62a4e4313ca1823ba37326c164ec720a803287c4c499b"}, + {file = "kiwisolver-1.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:e33e8fbd440c917106b237ef1a2f1449dfbb9b6f6e1ce17c94cd6a1e0d438376"}, + {file = "kiwisolver-1.4.7-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:5360cc32706dab3931f738d3079652d20982511f7c0ac5711483e6eab08efff2"}, + {file = "kiwisolver-1.4.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:942216596dc64ddb25adb215c3c783215b23626f8d84e8eff8d6d45c3f29f75a"}, + {file = "kiwisolver-1.4.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:48b571ecd8bae15702e4f22d3ff6a0f13e54d3d00cd25216d5e7f658242065ee"}, + {file = "kiwisolver-1.4.7-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad42ba922c67c5f219097b28fae965e10045ddf145d2928bfac2eb2e17673640"}, + {file = "kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:612a10bdae23404a72941a0fc8fa2660c6ea1217c4ce0dbcab8a8f6543ea9e7f"}, + {file = "kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e838bba3a3bac0fe06d849d29772eb1afb9745a59710762e4ba3f4cb8424483"}, + {file = "kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:22f499f6157236c19f4bbbd472fa55b063db77a16cd74d49afe28992dff8c258"}, + {file = "kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693902d433cf585133699972b6d7c42a8b9f8f826ebcaf0132ff55200afc599e"}, + {file = "kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4e77f2126c3e0b0d055f44513ed349038ac180371ed9b52fe96a32aa071a5107"}, + {file = "kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:657a05857bda581c3656bfc3b20e353c232e9193eb167766ad2dc58b56504948"}, + {file = "kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4bfa75a048c056a411f9705856abfc872558e33c055d80af6a380e3658766038"}, + {file = "kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:34ea1de54beef1c104422d210c47c7d2a4999bdecf42c7b5718fbe59a4cac383"}, + {file = "kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:90da3b5f694b85231cf93586dad5e90e2d71b9428f9aad96952c99055582f520"}, + {file = "kiwisolver-1.4.7-cp312-cp312-win32.whl", hash = "sha256:18e0cca3e008e17fe9b164b55735a325140a5a35faad8de92dd80265cd5eb80b"}, + {file = "kiwisolver-1.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:58cb20602b18f86f83a5c87d3ee1c766a79c0d452f8def86d925e6c60fbf7bfb"}, + {file = "kiwisolver-1.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:f5a8b53bdc0b3961f8b6125e198617c40aeed638b387913bf1ce78afb1b0be2a"}, + {file = "kiwisolver-1.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2e6039dcbe79a8e0f044f1c39db1986a1b8071051efba3ee4d74f5b365f5226e"}, + {file = "kiwisolver-1.4.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a1ecf0ac1c518487d9d23b1cd7139a6a65bc460cd101ab01f1be82ecf09794b6"}, + {file = "kiwisolver-1.4.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7ab9ccab2b5bd5702ab0803676a580fffa2aa178c2badc5557a84cc943fcf750"}, + {file = "kiwisolver-1.4.7-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f816dd2277f8d63d79f9c8473a79fe54047bc0467754962840782c575522224d"}, + {file = "kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf8bcc23ceb5a1b624572a1623b9f79d2c3b337c8c455405ef231933a10da379"}, + {file = "kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dea0bf229319828467d7fca8c7c189780aa9ff679c94539eed7532ebe33ed37c"}, + {file = "kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c06a4c7cf15ec739ce0e5971b26c93638730090add60e183530d70848ebdd34"}, + {file = "kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:913983ad2deb14e66d83c28b632fd35ba2b825031f2fa4ca29675e665dfecbe1"}, + {file = "kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5337ec7809bcd0f424c6b705ecf97941c46279cf5ed92311782c7c9c2026f07f"}, + {file = "kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4c26ed10c4f6fa6ddb329a5120ba3b6db349ca192ae211e882970bfc9d91420b"}, + {file = "kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c619b101e6de2222c1fcb0531e1b17bbffbe54294bfba43ea0d411d428618c27"}, + {file = "kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:073a36c8273647592ea332e816e75ef8da5c303236ec0167196793eb1e34657a"}, + {file = "kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3ce6b2b0231bda412463e152fc18335ba32faf4e8c23a754ad50ffa70e4091ee"}, + {file = "kiwisolver-1.4.7-cp313-cp313-win32.whl", hash = "sha256:f4c9aee212bc89d4e13f58be11a56cc8036cabad119259d12ace14b34476fd07"}, + {file = "kiwisolver-1.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:8a3ec5aa8e38fc4c8af308917ce12c536f1c88452ce554027e55b22cbbfbff76"}, + {file = "kiwisolver-1.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:76c8094ac20ec259471ac53e774623eb62e6e1f56cd8690c67ce6ce4fcb05650"}, + {file = "kiwisolver-1.4.7-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5d5abf8f8ec1f4e22882273c423e16cae834c36856cac348cfbfa68e01c40f3a"}, + {file = "kiwisolver-1.4.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:aeb3531b196ef6f11776c21674dba836aeea9d5bd1cf630f869e3d90b16cfade"}, + {file = "kiwisolver-1.4.7-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7d755065e4e866a8086c9bdada157133ff466476a2ad7861828e17b6026e22c"}, + {file = "kiwisolver-1.4.7-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:08471d4d86cbaec61f86b217dd938a83d85e03785f51121e791a6e6689a3be95"}, + {file = "kiwisolver-1.4.7-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7bbfcb7165ce3d54a3dfbe731e470f65739c4c1f85bb1018ee912bae139e263b"}, + {file = "kiwisolver-1.4.7-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d34eb8494bea691a1a450141ebb5385e4b69d38bb8403b5146ad279f4b30fa3"}, + {file = "kiwisolver-1.4.7-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9242795d174daa40105c1d86aba618e8eab7bf96ba8c3ee614da8302a9f95503"}, + {file = "kiwisolver-1.4.7-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a0f64a48bb81af7450e641e3fe0b0394d7381e342805479178b3d335d60ca7cf"}, + {file = "kiwisolver-1.4.7-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8e045731a5416357638d1700927529e2b8ab304811671f665b225f8bf8d8f933"}, + {file = "kiwisolver-1.4.7-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:4322872d5772cae7369f8351da1edf255a604ea7087fe295411397d0cfd9655e"}, + {file = "kiwisolver-1.4.7-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e1631290ee9271dffe3062d2634c3ecac02c83890ada077d225e081aca8aab89"}, + {file = "kiwisolver-1.4.7-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:edcfc407e4eb17e037bca59be0e85a2031a2ac87e4fed26d3e9df88b4165f92d"}, + {file = "kiwisolver-1.4.7-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:4d05d81ecb47d11e7f8932bd8b61b720bf0b41199358f3f5e36d38e28f0532c5"}, + {file = "kiwisolver-1.4.7-cp38-cp38-win32.whl", hash = "sha256:b38ac83d5f04b15e515fd86f312479d950d05ce2368d5413d46c088dda7de90a"}, + {file = "kiwisolver-1.4.7-cp38-cp38-win_amd64.whl", hash = "sha256:d83db7cde68459fc803052a55ace60bea2bae361fc3b7a6d5da07e11954e4b09"}, + {file = "kiwisolver-1.4.7-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3f9362ecfca44c863569d3d3c033dbe8ba452ff8eed6f6b5806382741a1334bd"}, + {file = "kiwisolver-1.4.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e8df2eb9b2bac43ef8b082e06f750350fbbaf2887534a5be97f6cf07b19d9583"}, + {file = "kiwisolver-1.4.7-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f32d6edbc638cde7652bd690c3e728b25332acbadd7cad670cc4a02558d9c417"}, + {file = "kiwisolver-1.4.7-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e2e6c39bd7b9372b0be21456caab138e8e69cc0fc1190a9dfa92bd45a1e6e904"}, + {file = "kiwisolver-1.4.7-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dda56c24d869b1193fcc763f1284b9126550eaf84b88bbc7256e15028f19188a"}, + {file = "kiwisolver-1.4.7-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79849239c39b5e1fd906556c474d9b0439ea6792b637511f3fe3a41158d89ca8"}, + {file = "kiwisolver-1.4.7-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5e3bc157fed2a4c02ec468de4ecd12a6e22818d4f09cde2c31ee3226ffbefab2"}, + {file = "kiwisolver-1.4.7-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3da53da805b71e41053dc670f9a820d1157aae77b6b944e08024d17bcd51ef88"}, + {file = "kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8705f17dfeb43139a692298cb6637ee2e59c0194538153e83e9ee0c75c2eddde"}, + {file = "kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:82a5c2f4b87c26bb1a0ef3d16b5c4753434633b83d365cc0ddf2770c93829e3c"}, + {file = "kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce8be0466f4c0d585cdb6c1e2ed07232221df101a4c6f28821d2aa754ca2d9e2"}, + {file = "kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:409afdfe1e2e90e6ee7fc896f3df9a7fec8e793e58bfa0d052c8a82f99c37abb"}, + {file = "kiwisolver-1.4.7-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5b9c3f4ee0b9a439d2415012bd1b1cc2df59e4d6a9939f4d669241d30b414327"}, + {file = "kiwisolver-1.4.7-cp39-cp39-win32.whl", hash = "sha256:a79ae34384df2b615eefca647a2873842ac3b596418032bef9a7283675962644"}, + {file = "kiwisolver-1.4.7-cp39-cp39-win_amd64.whl", hash = "sha256:cf0438b42121a66a3a667de17e779330fc0f20b0d97d59d2f2121e182b0505e4"}, + {file = "kiwisolver-1.4.7-cp39-cp39-win_arm64.whl", hash = "sha256:764202cc7e70f767dab49e8df52c7455e8de0df5d858fa801a11aa0d882ccf3f"}, + {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:94252291e3fe68001b1dd747b4c0b3be12582839b95ad4d1b641924d68fd4643"}, + {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5b7dfa3b546da08a9f622bb6becdb14b3e24aaa30adba66749d38f3cc7ea9706"}, + {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd3de6481f4ed8b734da5df134cd5a6a64fe32124fe83dde1e5b5f29fe30b1e6"}, + {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a91b5f9f1205845d488c928e8570dcb62b893372f63b8b6e98b863ebd2368ff2"}, + {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40fa14dbd66b8b8f470d5fc79c089a66185619d31645f9b0773b88b19f7223c4"}, + {file = "kiwisolver-1.4.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:eb542fe7933aa09d8d8f9d9097ef37532a7df6497819d16efe4359890a2f417a"}, + {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bfa1acfa0c54932d5607e19a2c24646fb4c1ae2694437789129cf099789a3b00"}, + {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:eee3ea935c3d227d49b4eb85660ff631556841f6e567f0f7bda972df6c2c9935"}, + {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f3160309af4396e0ed04db259c3ccbfdc3621b5559b5453075e5de555e1f3a1b"}, + {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:a17f6a29cf8935e587cc8a4dbfc8368c55edc645283db0ce9801016f83526c2d"}, + {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10849fb2c1ecbfae45a693c070e0320a91b35dd4bcf58172c023b994283a124d"}, + {file = "kiwisolver-1.4.7-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:ac542bf38a8a4be2dc6b15248d36315ccc65f0743f7b1a76688ffb6b5129a5c2"}, + {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:8b01aac285f91ca889c800042c35ad3b239e704b150cfd3382adfc9dcc780e39"}, + {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:48be928f59a1f5c8207154f935334d374e79f2b5d212826307d072595ad76a2e"}, + {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f37cfe618a117e50d8c240555331160d73d0411422b59b5ee217843d7b693608"}, + {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:599b5c873c63a1f6ed7eead644a8a380cfbdf5db91dcb6f85707aaab213b1674"}, + {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:801fa7802e5cfabe3ab0c81a34c323a319b097dfb5004be950482d882f3d7225"}, + {file = "kiwisolver-1.4.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0c6c43471bc764fad4bc99c5c2d6d16a676b1abf844ca7c8702bdae92df01ee0"}, + {file = "kiwisolver-1.4.7.tar.gz", hash = "sha256:9893ff81bd7107f7b685d3017cc6583daadb4fc26e4a888350df530e41980a60"}, +] + +[[package]] +name = "matplotlib" +version = "3.9.2" +description = "Python plotting package" +optional = false +python-versions = ">=3.9" +files = [ + {file = "matplotlib-3.9.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:9d78bbc0cbc891ad55b4f39a48c22182e9bdaea7fc0e5dbd364f49f729ca1bbb"}, + {file = "matplotlib-3.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c375cc72229614632c87355366bdf2570c2dac01ac66b8ad048d2dabadf2d0d4"}, + {file = "matplotlib-3.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d94ff717eb2bd0b58fe66380bd8b14ac35f48a98e7c6765117fe67fb7684e64"}, + {file = "matplotlib-3.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab68d50c06938ef28681073327795c5db99bb4666214d2d5f880ed11aeaded66"}, + {file = "matplotlib-3.9.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:65aacf95b62272d568044531e41de26285d54aec8cb859031f511f84bd8b495a"}, + {file = "matplotlib-3.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:3fd595f34aa8a55b7fc8bf9ebea8aa665a84c82d275190a61118d33fbc82ccae"}, + {file = "matplotlib-3.9.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d8dd059447824eec055e829258ab092b56bb0579fc3164fa09c64f3acd478772"}, + {file = "matplotlib-3.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c797dac8bb9c7a3fd3382b16fe8f215b4cf0f22adccea36f1545a6d7be310b41"}, + {file = "matplotlib-3.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d719465db13267bcef19ea8954a971db03b9f48b4647e3860e4bc8e6ed86610f"}, + {file = "matplotlib-3.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8912ef7c2362f7193b5819d17dae8629b34a95c58603d781329712ada83f9447"}, + {file = "matplotlib-3.9.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7741f26a58a240f43bee74965c4882b6c93df3e7eb3de160126d8c8f53a6ae6e"}, + {file = "matplotlib-3.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:ae82a14dab96fbfad7965403c643cafe6515e386de723e498cf3eeb1e0b70cc7"}, + {file = "matplotlib-3.9.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ac43031375a65c3196bee99f6001e7fa5bdfb00ddf43379d3c0609bdca042df9"}, + {file = "matplotlib-3.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:be0fc24a5e4531ae4d8e858a1a548c1fe33b176bb13eff7f9d0d38ce5112a27d"}, + {file = "matplotlib-3.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf81de2926c2db243c9b2cbc3917619a0fc85796c6ba4e58f541df814bbf83c7"}, + {file = "matplotlib-3.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6ee45bc4245533111ced13f1f2cace1e7f89d1c793390392a80c139d6cf0e6c"}, + {file = "matplotlib-3.9.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:306c8dfc73239f0e72ac50e5a9cf19cc4e8e331dd0c54f5e69ca8758550f1e1e"}, + {file = "matplotlib-3.9.2-cp312-cp312-win_amd64.whl", hash = "sha256:5413401594cfaff0052f9d8b1aafc6d305b4bd7c4331dccd18f561ff7e1d3bd3"}, + {file = "matplotlib-3.9.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:18128cc08f0d3cfff10b76baa2f296fc28c4607368a8402de61bb3f2eb33c7d9"}, + {file = "matplotlib-3.9.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4876d7d40219e8ae8bb70f9263bcbe5714415acfdf781086601211335e24f8aa"}, + {file = "matplotlib-3.9.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d9f07a80deab4bb0b82858a9e9ad53d1382fd122be8cde11080f4e7dfedb38b"}, + {file = "matplotlib-3.9.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7c0410f181a531ec4e93bbc27692f2c71a15c2da16766f5ba9761e7ae518413"}, + {file = "matplotlib-3.9.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:909645cce2dc28b735674ce0931a4ac94e12f5b13f6bb0b5a5e65e7cea2c192b"}, + {file = "matplotlib-3.9.2-cp313-cp313-win_amd64.whl", hash = "sha256:f32c7410c7f246838a77d6d1eff0c0f87f3cb0e7c4247aebea71a6d5a68cab49"}, + {file = "matplotlib-3.9.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:37e51dd1c2db16ede9cfd7b5cabdfc818b2c6397c83f8b10e0e797501c963a03"}, + {file = "matplotlib-3.9.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b82c5045cebcecd8496a4d694d43f9cc84aeeb49fe2133e036b207abe73f4d30"}, + {file = "matplotlib-3.9.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f053c40f94bc51bc03832a41b4f153d83f2062d88c72b5e79997072594e97e51"}, + {file = "matplotlib-3.9.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbe196377a8248972f5cede786d4c5508ed5f5ca4a1e09b44bda889958b33f8c"}, + {file = "matplotlib-3.9.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5816b1e1fe8c192cbc013f8f3e3368ac56fbecf02fb41b8f8559303f24c5015e"}, + {file = "matplotlib-3.9.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:cef2a73d06601437be399908cf13aee74e86932a5ccc6ccdf173408ebc5f6bb2"}, + {file = "matplotlib-3.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e0830e188029c14e891fadd99702fd90d317df294c3298aad682739c5533721a"}, + {file = "matplotlib-3.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:03ba9c1299c920964e8d3857ba27173b4dbb51ca4bab47ffc2c2ba0eb5e2cbc5"}, + {file = "matplotlib-3.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1cd93b91ab47a3616b4d3c42b52f8363b88ca021e340804c6ab2536344fad9ca"}, + {file = "matplotlib-3.9.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6d1ce5ed2aefcdce11904fc5bbea7d9c21fff3d5f543841edf3dea84451a09ea"}, + {file = "matplotlib-3.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:b2696efdc08648536efd4e1601b5fd491fd47f4db97a5fbfd175549a7365c1b2"}, + {file = "matplotlib-3.9.2-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:d52a3b618cb1cbb769ce2ee1dcdb333c3ab6e823944e9a2d36e37253815f9556"}, + {file = "matplotlib-3.9.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:039082812cacd6c6bec8e17a9c1e6baca230d4116d522e81e1f63a74d01d2e21"}, + {file = "matplotlib-3.9.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6758baae2ed64f2331d4fd19be38b7b4eae3ecec210049a26b6a4f3ae1c85dcc"}, + {file = "matplotlib-3.9.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:050598c2b29e0b9832cde72bcf97627bf00262adbc4a54e2b856426bb2ef0697"}, + {file = "matplotlib-3.9.2.tar.gz", hash = "sha256:96ab43906269ca64a6366934106fa01534454a69e471b7bf3d79083981aaab92"}, +] + +[package.dependencies] +contourpy = ">=1.0.1" +cycler = ">=0.10" +fonttools = ">=4.22.0" +importlib-resources = {version = ">=3.2.0", markers = "python_version < \"3.10\""} +kiwisolver = ">=1.3.1" +numpy = ">=1.23" +packaging = ">=20.0" +pillow = ">=8" +pyparsing = ">=2.3.1" +python-dateutil = ">=2.7" + +[package.extras] +dev = ["meson-python (>=0.13.1)", "numpy (>=1.25)", "pybind11 (>=2.6)", "setuptools (>=64)", "setuptools_scm (>=7)"] + +[[package]] +name = "matplotlib-inline" +version = "0.1.7" +description = "Inline Matplotlib backend for Jupyter" +optional = false +python-versions = ">=3.8" +files = [ + {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"}, + {file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"}, +] + +[package.dependencies] +traitlets = "*" + +[[package]] +name = "nest-asyncio" +version = "1.6.0" +description = "Patch asyncio to allow nested event loops" +optional = false +python-versions = ">=3.5" +files = [ + {file = "nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c"}, + {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, +] + +[[package]] +name = "numpy" +version = "2.0.2" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "numpy-2.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:51129a29dbe56f9ca83438b706e2e69a39892b5eda6cedcb6b0c9fdc9b0d3ece"}, + {file = "numpy-2.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f15975dfec0cf2239224d80e32c3170b1d168335eaedee69da84fbe9f1f9cd04"}, + {file = "numpy-2.0.2-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:8c5713284ce4e282544c68d1c3b2c7161d38c256d2eefc93c1d683cf47683e66"}, + {file = "numpy-2.0.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:becfae3ddd30736fe1889a37f1f580e245ba79a5855bff5f2a29cb3ccc22dd7b"}, + {file = "numpy-2.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2da5960c3cf0df7eafefd806d4e612c5e19358de82cb3c343631188991566ccd"}, + {file = "numpy-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:496f71341824ed9f3d2fd36cf3ac57ae2e0165c143b55c3a035ee219413f3318"}, + {file = "numpy-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a61ec659f68ae254e4d237816e33171497e978140353c0c2038d46e63282d0c8"}, + {file = "numpy-2.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d731a1c6116ba289c1e9ee714b08a8ff882944d4ad631fd411106a30f083c326"}, + {file = "numpy-2.0.2-cp310-cp310-win32.whl", hash = "sha256:984d96121c9f9616cd33fbd0618b7f08e0cfc9600a7ee1d6fd9b239186d19d97"}, + {file = "numpy-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:c7b0be4ef08607dd04da4092faee0b86607f111d5ae68036f16cc787e250a131"}, + {file = "numpy-2.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:49ca4decb342d66018b01932139c0961a8f9ddc7589611158cb3c27cbcf76448"}, + {file = "numpy-2.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:11a76c372d1d37437857280aa142086476136a8c0f373b2e648ab2c8f18fb195"}, + {file = "numpy-2.0.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:807ec44583fd708a21d4a11d94aedf2f4f3c3719035c76a2bbe1fe8e217bdc57"}, + {file = "numpy-2.0.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8cafab480740e22f8d833acefed5cc87ce276f4ece12fdaa2e8903db2f82897a"}, + {file = "numpy-2.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a15f476a45e6e5a3a79d8a14e62161d27ad897381fecfa4a09ed5322f2085669"}, + {file = "numpy-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13e689d772146140a252c3a28501da66dfecd77490b498b168b501835041f951"}, + {file = "numpy-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9ea91dfb7c3d1c56a0e55657c0afb38cf1eeae4544c208dc465c3c9f3a7c09f9"}, + {file = "numpy-2.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c1c9307701fec8f3f7a1e6711f9089c06e6284b3afbbcd259f7791282d660a15"}, + {file = "numpy-2.0.2-cp311-cp311-win32.whl", hash = "sha256:a392a68bd329eafac5817e5aefeb39038c48b671afd242710b451e76090e81f4"}, + {file = "numpy-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:286cd40ce2b7d652a6f22efdfc6d1edf879440e53e76a75955bc0c826c7e64dc"}, + {file = "numpy-2.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:df55d490dea7934f330006d0f81e8551ba6010a5bf035a249ef61a94f21c500b"}, + {file = "numpy-2.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8df823f570d9adf0978347d1f926b2a867d5608f434a7cff7f7908c6570dcf5e"}, + {file = "numpy-2.0.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:9a92ae5c14811e390f3767053ff54eaee3bf84576d99a2456391401323f4ec2c"}, + {file = "numpy-2.0.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:a842d573724391493a97a62ebbb8e731f8a5dcc5d285dfc99141ca15a3302d0c"}, + {file = "numpy-2.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c05e238064fc0610c840d1cf6a13bf63d7e391717d247f1bf0318172e759e692"}, + {file = "numpy-2.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0123ffdaa88fa4ab64835dcbde75dcdf89c453c922f18dced6e27c90d1d0ec5a"}, + {file = "numpy-2.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:96a55f64139912d61de9137f11bf39a55ec8faec288c75a54f93dfd39f7eb40c"}, + {file = "numpy-2.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ec9852fb39354b5a45a80bdab5ac02dd02b15f44b3804e9f00c556bf24b4bded"}, + {file = "numpy-2.0.2-cp312-cp312-win32.whl", hash = "sha256:671bec6496f83202ed2d3c8fdc486a8fc86942f2e69ff0e986140339a63bcbe5"}, + {file = "numpy-2.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:cfd41e13fdc257aa5778496b8caa5e856dc4896d4ccf01841daee1d96465467a"}, + {file = "numpy-2.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9059e10581ce4093f735ed23f3b9d283b9d517ff46009ddd485f1747eb22653c"}, + {file = "numpy-2.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:423e89b23490805d2a5a96fe40ec507407b8ee786d66f7328be214f9679df6dd"}, + {file = "numpy-2.0.2-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:2b2955fa6f11907cf7a70dab0d0755159bca87755e831e47932367fc8f2f2d0b"}, + {file = "numpy-2.0.2-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:97032a27bd9d8988b9a97a8c4d2c9f2c15a81f61e2f21404d7e8ef00cb5be729"}, + {file = "numpy-2.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e795a8be3ddbac43274f18588329c72939870a16cae810c2b73461c40718ab1"}, + {file = "numpy-2.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26b258c385842546006213344c50655ff1555a9338e2e5e02a0756dc3e803dd"}, + {file = "numpy-2.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fec9451a7789926bcf7c2b8d187292c9f93ea30284802a0ab3f5be8ab36865d"}, + {file = "numpy-2.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9189427407d88ff25ecf8f12469d4d39d35bee1db5d39fc5c168c6f088a6956d"}, + {file = "numpy-2.0.2-cp39-cp39-win32.whl", hash = "sha256:905d16e0c60200656500c95b6b8dca5d109e23cb24abc701d41c02d74c6b3afa"}, + {file = "numpy-2.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:a3f4ab0caa7f053f6797fcd4e1e25caee367db3112ef2b6ef82d749530768c73"}, + {file = "numpy-2.0.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7f0a0c6f12e07fa94133c8a67404322845220c06a9e80e85999afe727f7438b8"}, + {file = "numpy-2.0.2-pp39-pypy39_pp73-macosx_14_0_x86_64.whl", hash = "sha256:312950fdd060354350ed123c0e25a71327d3711584beaef30cdaa93320c392d4"}, + {file = "numpy-2.0.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26df23238872200f63518dd2aa984cfca675d82469535dc7162dc2ee52d9dd5c"}, + {file = "numpy-2.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a46288ec55ebbd58947d31d72be2c63cbf839f0a63b49cb755022310792a3385"}, + {file = "numpy-2.0.2.tar.gz", hash = "sha256:883c987dee1880e2a864ab0dc9892292582510604156762362d9326444636e78"}, +] + [[package]] name = "packaging" version = "24.1" @@ -412,6 +1196,148 @@ files = [ {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] +[[package]] +name = "parso" +version = "0.8.4" +description = "A Python Parser" +optional = false +python-versions = ">=3.6" +files = [ + {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"}, + {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"}, +] + +[package.extras] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["docopt", "pytest"] + +[[package]] +name = "pexpect" +version = "4.9.0" +description = "Pexpect allows easy control of interactive console applications." +optional = false +python-versions = "*" +files = [ + {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, + {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, +] + +[package.dependencies] +ptyprocess = ">=0.5" + +[[package]] +name = "pillow" +version = "10.4.0" +description = "Python Imaging Library (Fork)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pillow-10.4.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:4d9667937cfa347525b319ae34375c37b9ee6b525440f3ef48542fcf66f2731e"}, + {file = "pillow-10.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:543f3dc61c18dafb755773efc89aae60d06b6596a63914107f75459cf984164d"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7928ecbf1ece13956b95d9cbcfc77137652b02763ba384d9ab508099a2eca856"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d49b85c4348ea0b31ea63bc75a9f3857869174e2bf17e7aba02945cd218e6f"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:6c762a5b0997f5659a5ef2266abc1d8851ad7749ad9a6a5506eb23d314e4f46b"}, + {file = "pillow-10.4.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a985e028fc183bf12a77a8bbf36318db4238a3ded7fa9df1b9a133f1cb79f8fc"}, + {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:812f7342b0eee081eaec84d91423d1b4650bb9828eb53d8511bcef8ce5aecf1e"}, + {file = "pillow-10.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ac1452d2fbe4978c2eec89fb5a23b8387aba707ac72810d9490118817d9c0b46"}, + {file = "pillow-10.4.0-cp310-cp310-win32.whl", hash = "sha256:bcd5e41a859bf2e84fdc42f4edb7d9aba0a13d29a2abadccafad99de3feff984"}, + {file = "pillow-10.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:ecd85a8d3e79cd7158dec1c9e5808e821feea088e2f69a974db5edf84dc53141"}, + {file = "pillow-10.4.0-cp310-cp310-win_arm64.whl", hash = "sha256:ff337c552345e95702c5fde3158acb0625111017d0e5f24bf3acdb9cc16b90d1"}, + {file = "pillow-10.4.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0a9ec697746f268507404647e531e92889890a087e03681a3606d9b920fbee3c"}, + {file = "pillow-10.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe91cb65544a1321e631e696759491ae04a2ea11d36715eca01ce07284738be"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dc6761a6efc781e6a1544206f22c80c3af4c8cf461206d46a1e6006e4429ff3"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e84b6cc6a4a3d76c153a6b19270b3526a5a8ed6b09501d3af891daa2a9de7d6"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:bbc527b519bd3aa9d7f429d152fea69f9ad37c95f0b02aebddff592688998abe"}, + {file = "pillow-10.4.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:76a911dfe51a36041f2e756b00f96ed84677cdeb75d25c767f296c1c1eda1319"}, + {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59291fb29317122398786c2d44427bbd1a6d7ff54017075b22be9d21aa59bd8d"}, + {file = "pillow-10.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:416d3a5d0e8cfe4f27f574362435bc9bae57f679a7158e0096ad2beb427b8696"}, + {file = "pillow-10.4.0-cp311-cp311-win32.whl", hash = "sha256:7086cc1d5eebb91ad24ded9f58bec6c688e9f0ed7eb3dbbf1e4800280a896496"}, + {file = "pillow-10.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cbed61494057c0f83b83eb3a310f0bf774b09513307c434d4366ed64f4128a91"}, + {file = "pillow-10.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:f5f0c3e969c8f12dd2bb7e0b15d5c468b51e5017e01e2e867335c81903046a22"}, + {file = "pillow-10.4.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:673655af3eadf4df6b5457033f086e90299fdd7a47983a13827acf7459c15d94"}, + {file = "pillow-10.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:866b6942a92f56300012f5fbac71f2d610312ee65e22f1aa2609e491284e5597"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29dbdc4207642ea6aad70fbde1a9338753d33fb23ed6956e706936706f52dd80"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf2342ac639c4cf38799a44950bbc2dfcb685f052b9e262f446482afaf4bffca"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:f5b92f4d70791b4a67157321c4e8225d60b119c5cc9aee8ecf153aace4aad4ef"}, + {file = "pillow-10.4.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:86dcb5a1eb778d8b25659d5e4341269e8590ad6b4e8b44d9f4b07f8d136c414a"}, + {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:780c072c2e11c9b2c7ca37f9a2ee8ba66f44367ac3e5c7832afcfe5104fd6d1b"}, + {file = "pillow-10.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37fb69d905be665f68f28a8bba3c6d3223c8efe1edf14cc4cfa06c241f8c81d9"}, + {file = "pillow-10.4.0-cp312-cp312-win32.whl", hash = "sha256:7dfecdbad5c301d7b5bde160150b4db4c659cee2b69589705b6f8a0c509d9f42"}, + {file = "pillow-10.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:1d846aea995ad352d4bdcc847535bd56e0fd88d36829d2c90be880ef1ee4668a"}, + {file = "pillow-10.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:e553cad5179a66ba15bb18b353a19020e73a7921296a7979c4a2b7f6a5cd57f9"}, + {file = "pillow-10.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8bc1a764ed8c957a2e9cacf97c8b2b053b70307cf2996aafd70e91a082e70df3"}, + {file = "pillow-10.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6209bb41dc692ddfee4942517c19ee81b86c864b626dbfca272ec0f7cff5d9fb"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bee197b30783295d2eb680b311af15a20a8b24024a19c3a26431ff83eb8d1f70"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ef61f5dd14c300786318482456481463b9d6b91ebe5ef12f405afbba77ed0be"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:297e388da6e248c98bc4a02e018966af0c5f92dfacf5a5ca22fa01cb3179bca0"}, + {file = "pillow-10.4.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:e4db64794ccdf6cb83a59d73405f63adbe2a1887012e308828596100a0b2f6cc"}, + {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bd2880a07482090a3bcb01f4265f1936a903d70bc740bfcb1fd4e8a2ffe5cf5a"}, + {file = "pillow-10.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b35b21b819ac1dbd1233317adeecd63495f6babf21b7b2512d244ff6c6ce309"}, + {file = "pillow-10.4.0-cp313-cp313-win32.whl", hash = "sha256:551d3fd6e9dc15e4c1eb6fc4ba2b39c0c7933fa113b220057a34f4bb3268a060"}, + {file = "pillow-10.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:030abdbe43ee02e0de642aee345efa443740aa4d828bfe8e2eb11922ea6a21ea"}, + {file = "pillow-10.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b001114dd152cfd6b23befeb28d7aee43553e2402c9f159807bf55f33af8a8d"}, + {file = "pillow-10.4.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8d4d5063501b6dd4024b8ac2f04962d661222d120381272deea52e3fc52d3736"}, + {file = "pillow-10.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7c1ee6f42250df403c5f103cbd2768a28fe1a0ea1f0f03fe151c8741e1469c8b"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15e02e9bb4c21e39876698abf233c8c579127986f8207200bc8a8f6bb27acf2"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a8d4bade9952ea9a77d0c3e49cbd8b2890a399422258a77f357b9cc9be8d680"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:43efea75eb06b95d1631cb784aa40156177bf9dd5b4b03ff38979e048258bc6b"}, + {file = "pillow-10.4.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:950be4d8ba92aca4b2bb0741285a46bfae3ca699ef913ec8416c1b78eadd64cd"}, + {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d7480af14364494365e89d6fddc510a13e5a2c3584cb19ef65415ca57252fb84"}, + {file = "pillow-10.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:73664fe514b34c8f02452ffb73b7a92c6774e39a647087f83d67f010eb9a0cf0"}, + {file = "pillow-10.4.0-cp38-cp38-win32.whl", hash = "sha256:e88d5e6ad0d026fba7bdab8c3f225a69f063f116462c49892b0149e21b6c0a0e"}, + {file = "pillow-10.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:5161eef006d335e46895297f642341111945e2c1c899eb406882a6c61a4357ab"}, + {file = "pillow-10.4.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0ae24a547e8b711ccaaf99c9ae3cd975470e1a30caa80a6aaee9a2f19c05701d"}, + {file = "pillow-10.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:298478fe4f77a4408895605f3482b6cc6222c018b2ce565c2b6b9c354ac3229b"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:134ace6dc392116566980ee7436477d844520a26a4b1bd4053f6f47d096997fd"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:930044bb7679ab003b14023138b50181899da3f25de50e9dbee23b61b4de2126"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c76e5786951e72ed3686e122d14c5d7012f16c8303a674d18cdcd6d89557fc5b"}, + {file = "pillow-10.4.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b2724fdb354a868ddf9a880cb84d102da914e99119211ef7ecbdc613b8c96b3c"}, + {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dbc6ae66518ab3c5847659e9988c3b60dc94ffb48ef9168656e0019a93dbf8a1"}, + {file = "pillow-10.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:06b2f7898047ae93fad74467ec3d28fe84f7831370e3c258afa533f81ef7f3df"}, + {file = "pillow-10.4.0-cp39-cp39-win32.whl", hash = "sha256:7970285ab628a3779aecc35823296a7869f889b8329c16ad5a71e4901a3dc4ef"}, + {file = "pillow-10.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:961a7293b2457b405967af9c77dcaa43cc1a8cd50d23c532e62d48ab6cdd56f5"}, + {file = "pillow-10.4.0-cp39-cp39-win_arm64.whl", hash = "sha256:32cda9e3d601a52baccb2856b8ea1fc213c90b340c542dcef77140dfa3278a9e"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5b4815f2e65b30f5fbae9dfffa8636d992d49705723fe86a3661806e069352d4"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8f0aef4ef59694b12cadee839e2ba6afeab89c0f39a3adc02ed51d109117b8da"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f4727572e2918acaa9077c919cbbeb73bd2b3ebcfe033b72f858fc9fbef0026"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff25afb18123cea58a591ea0244b92eb1e61a1fd497bf6d6384f09bc3262ec3e"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dc3e2db6ba09ffd7d02ae9141cfa0ae23393ee7687248d46a7507b75d610f4f5"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:02a2be69f9c9b8c1e97cf2713e789d4e398c751ecfd9967c18d0ce304efbf885"}, + {file = "pillow-10.4.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:0755ffd4a0c6f267cccbae2e9903d95477ca2f77c4fcf3a3a09570001856c8a5"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a02364621fe369e06200d4a16558e056fe2805d3468350df3aef21e00d26214b"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1b5dea9831a90e9d0721ec417a80d4cbd7022093ac38a568db2dd78363b00908"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b885f89040bb8c4a1573566bbb2f44f5c505ef6e74cec7ab9068c900047f04b"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87dd88ded2e6d74d31e1e0a99a726a6765cda32d00ba72dc37f0651f306daaa8"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:2db98790afc70118bd0255c2eeb465e9767ecf1f3c25f9a1abb8ffc8cfd1fe0a"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f7baece4ce06bade126fb84b8af1c33439a76d8a6fd818970215e0560ca28c27"}, + {file = "pillow-10.4.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:cfdd747216947628af7b259d274771d84db2268ca062dd5faf373639d00113a3"}, + {file = "pillow-10.4.0.tar.gz", hash = "sha256:166c1cd4d24309b30d61f79f4a9114b7b2313d7450912277855ff5dfd7cd4a06"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=7.3)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] +fpx = ["olefile"] +mic = ["olefile"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +typing = ["typing-extensions"] +xmp = ["defusedxml"] + +[[package]] +name = "platformdirs" +version = "4.3.2" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.3.2-py3-none-any.whl", hash = "sha256:eb1c8582560b34ed4ba105009a4badf7f6f85768b30126f351328507b2beb617"}, + {file = "platformdirs-4.3.2.tar.gz", hash = "sha256:9e5e27a08aa095dd127b9f2e764d74254f482fef22b0970773bfba79d091ab8c"}, +] + +[package.extras] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.11.2)"] + [[package]] name = "pluggy" version = "1.5.0" @@ -427,6 +1353,85 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "prompt-toolkit" +version = "3.0.47" +description = "Library for building powerful interactive command lines in Python" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "prompt_toolkit-3.0.47-py3-none-any.whl", hash = "sha256:0d7bfa67001d5e39d02c224b663abc33687405033a8c422d0d675a5a13361d10"}, + {file = "prompt_toolkit-3.0.47.tar.gz", hash = "sha256:1e1b29cb58080b1e69f207c893a1a7bf16d127a5c30c9d17a25a5d77792e5360"}, +] + +[package.dependencies] +wcwidth = "*" + +[[package]] +name = "psutil" +version = "6.0.0" +description = "Cross-platform lib for process and system monitoring in Python." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "psutil-6.0.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a021da3e881cd935e64a3d0a20983bda0bb4cf80e4f74fa9bfcb1bc5785360c6"}, + {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:1287c2b95f1c0a364d23bc6f2ea2365a8d4d9b726a3be7294296ff7ba97c17f0"}, + {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:a9a3dbfb4de4f18174528d87cc352d1f788b7496991cca33c6996f40c9e3c92c"}, + {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6ec7588fb3ddaec7344a825afe298db83fe01bfaaab39155fa84cf1c0d6b13c3"}, + {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1e7c870afcb7d91fdea2b37c24aeb08f98b6d67257a5cb0a8bc3ac68d0f1a68c"}, + {file = "psutil-6.0.0-cp27-none-win32.whl", hash = "sha256:02b69001f44cc73c1c5279d02b30a817e339ceb258ad75997325e0e6169d8b35"}, + {file = "psutil-6.0.0-cp27-none-win_amd64.whl", hash = "sha256:21f1fb635deccd510f69f485b87433460a603919b45e2a324ad65b0cc74f8fb1"}, + {file = "psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132"}, + {file = "psutil-6.0.0-cp36-cp36m-win32.whl", hash = "sha256:fc8c9510cde0146432bbdb433322861ee8c3efbf8589865c8bf8d21cb30c4d14"}, + {file = "psutil-6.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:34859b8d8f423b86e4385ff3665d3f4d94be3cdf48221fbe476e883514fdb71c"}, + {file = "psutil-6.0.0-cp37-abi3-win32.whl", hash = "sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d"}, + {file = "psutil-6.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3"}, + {file = "psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0"}, + {file = "psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2"}, +] + +[package.extras] +test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +description = "Run a subprocess in a pseudo terminal" +optional = false +python-versions = "*" +files = [ + {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, + {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, +] + +[[package]] +name = "pure-eval" +version = "0.2.3" +description = "Safely evaluate AST nodes without side effects" +optional = false +python-versions = "*" +files = [ + {file = "pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0"}, + {file = "pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42"}, +] + +[package.extras] +tests = ["pytest"] + +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, +] + [[package]] name = "pydantic" version = "2.9.0" @@ -551,6 +1556,34 @@ files = [ [package.dependencies] typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" +[[package]] +name = "pygments" +version = "2.18.0" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pyparsing" +version = "3.1.4" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +optional = false +python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.1.4-py3-none-any.whl", hash = "sha256:a6a7ee4235a3f944aa1fa2249307708f893fe5717dc603503c6c7969c070fb7c"}, + {file = "pyparsing-3.1.4.tar.gz", hash = "sha256:f86ec8d1a83f11977c9a6ea7598e8c27fc5cddfa5b07ea2241edbbde1d7bc032"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + [[package]] name = "pytest" version = "8.3.2" @@ -573,6 +1606,164 @@ tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "pywin32" +version = "306" +description = "Python for Window Extensions" +optional = false +python-versions = "*" +files = [ + {file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"}, + {file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"}, + {file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"}, + {file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"}, + {file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"}, + {file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"}, + {file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"}, + {file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"}, + {file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"}, + {file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"}, + {file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"}, + {file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"}, + {file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"}, + {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"}, +] + +[[package]] +name = "pyzmq" +version = "26.2.0" +description = "Python bindings for 0MQ" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyzmq-26.2.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:ddf33d97d2f52d89f6e6e7ae66ee35a4d9ca6f36eda89c24591b0c40205a3629"}, + {file = "pyzmq-26.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dacd995031a01d16eec825bf30802fceb2c3791ef24bcce48fa98ce40918c27b"}, + {file = "pyzmq-26.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89289a5ee32ef6c439086184529ae060c741334b8970a6855ec0b6ad3ff28764"}, + {file = "pyzmq-26.2.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5506f06d7dc6ecf1efacb4a013b1f05071bb24b76350832c96449f4a2d95091c"}, + {file = "pyzmq-26.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ea039387c10202ce304af74def5021e9adc6297067f3441d348d2b633e8166a"}, + {file = "pyzmq-26.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:a2224fa4a4c2ee872886ed00a571f5e967c85e078e8e8c2530a2fb01b3309b88"}, + {file = "pyzmq-26.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:28ad5233e9c3b52d76196c696e362508959741e1a005fb8fa03b51aea156088f"}, + {file = "pyzmq-26.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:1c17211bc037c7d88e85ed8b7d8f7e52db6dc8eca5590d162717c654550f7282"}, + {file = "pyzmq-26.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b8f86dd868d41bea9a5f873ee13bf5551c94cf6bc51baebc6f85075971fe6eea"}, + {file = "pyzmq-26.2.0-cp310-cp310-win32.whl", hash = "sha256:46a446c212e58456b23af260f3d9fb785054f3e3653dbf7279d8f2b5546b21c2"}, + {file = "pyzmq-26.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:49d34ab71db5a9c292a7644ce74190b1dd5a3475612eefb1f8be1d6961441971"}, + {file = "pyzmq-26.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:bfa832bfa540e5b5c27dcf5de5d82ebc431b82c453a43d141afb1e5d2de025fa"}, + {file = "pyzmq-26.2.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:8f7e66c7113c684c2b3f1c83cdd3376103ee0ce4c49ff80a648643e57fb22218"}, + {file = "pyzmq-26.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3a495b30fc91db2db25120df5847d9833af237546fd59170701acd816ccc01c4"}, + {file = "pyzmq-26.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77eb0968da535cba0470a5165468b2cac7772cfb569977cff92e240f57e31bef"}, + {file = "pyzmq-26.2.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ace4f71f1900a548f48407fc9be59c6ba9d9aaf658c2eea6cf2779e72f9f317"}, + {file = "pyzmq-26.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:92a78853d7280bffb93df0a4a6a2498cba10ee793cc8076ef797ef2f74d107cf"}, + {file = "pyzmq-26.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:689c5d781014956a4a6de61d74ba97b23547e431e9e7d64f27d4922ba96e9d6e"}, + {file = "pyzmq-26.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0aca98bc423eb7d153214b2df397c6421ba6373d3397b26c057af3c904452e37"}, + {file = "pyzmq-26.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:1f3496d76b89d9429a656293744ceca4d2ac2a10ae59b84c1da9b5165f429ad3"}, + {file = "pyzmq-26.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5c2b3bfd4b9689919db068ac6c9911f3fcb231c39f7dd30e3138be94896d18e6"}, + {file = "pyzmq-26.2.0-cp311-cp311-win32.whl", hash = "sha256:eac5174677da084abf378739dbf4ad245661635f1600edd1221f150b165343f4"}, + {file = "pyzmq-26.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:5a509df7d0a83a4b178d0f937ef14286659225ef4e8812e05580776c70e155d5"}, + {file = "pyzmq-26.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:c0e6091b157d48cbe37bd67233318dbb53e1e6327d6fc3bb284afd585d141003"}, + {file = "pyzmq-26.2.0-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:ded0fc7d90fe93ae0b18059930086c51e640cdd3baebdc783a695c77f123dcd9"}, + {file = "pyzmq-26.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:17bf5a931c7f6618023cdacc7081f3f266aecb68ca692adac015c383a134ca52"}, + {file = "pyzmq-26.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55cf66647e49d4621a7e20c8d13511ef1fe1efbbccf670811864452487007e08"}, + {file = "pyzmq-26.2.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4661c88db4a9e0f958c8abc2b97472e23061f0bc737f6f6179d7a27024e1faa5"}, + {file = "pyzmq-26.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea7f69de383cb47522c9c208aec6dd17697db7875a4674c4af3f8cfdac0bdeae"}, + {file = "pyzmq-26.2.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:7f98f6dfa8b8ccaf39163ce872bddacca38f6a67289116c8937a02e30bbe9711"}, + {file = "pyzmq-26.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e3e0210287329272539eea617830a6a28161fbbd8a3271bf4150ae3e58c5d0e6"}, + {file = "pyzmq-26.2.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6b274e0762c33c7471f1a7471d1a2085b1a35eba5cdc48d2ae319f28b6fc4de3"}, + {file = "pyzmq-26.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:29c6a4635eef69d68a00321e12a7d2559fe2dfccfa8efae3ffb8e91cd0b36a8b"}, + {file = "pyzmq-26.2.0-cp312-cp312-win32.whl", hash = "sha256:989d842dc06dc59feea09e58c74ca3e1678c812a4a8a2a419046d711031f69c7"}, + {file = "pyzmq-26.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:2a50625acdc7801bc6f74698c5c583a491c61d73c6b7ea4dee3901bb99adb27a"}, + {file = "pyzmq-26.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:4d29ab8592b6ad12ebbf92ac2ed2bedcfd1cec192d8e559e2e099f648570e19b"}, + {file = "pyzmq-26.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9dd8cd1aeb00775f527ec60022004d030ddc51d783d056e3e23e74e623e33726"}, + {file = "pyzmq-26.2.0-cp313-cp313-macosx_10_15_universal2.whl", hash = "sha256:28c812d9757fe8acecc910c9ac9dafd2ce968c00f9e619db09e9f8f54c3a68a3"}, + {file = "pyzmq-26.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d80b1dd99c1942f74ed608ddb38b181b87476c6a966a88a950c7dee118fdf50"}, + {file = "pyzmq-26.2.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c997098cc65e3208eca09303630e84d42718620e83b733d0fd69543a9cab9cb"}, + {file = "pyzmq-26.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ad1bc8d1b7a18497dda9600b12dc193c577beb391beae5cd2349184db40f187"}, + {file = "pyzmq-26.2.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:bea2acdd8ea4275e1278350ced63da0b166421928276c7c8e3f9729d7402a57b"}, + {file = "pyzmq-26.2.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:23f4aad749d13698f3f7b64aad34f5fc02d6f20f05999eebc96b89b01262fb18"}, + {file = "pyzmq-26.2.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:a4f96f0d88accc3dbe4a9025f785ba830f968e21e3e2c6321ccdfc9aef755115"}, + {file = "pyzmq-26.2.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ced65e5a985398827cc9276b93ef6dfabe0273c23de8c7931339d7e141c2818e"}, + {file = "pyzmq-26.2.0-cp313-cp313-win32.whl", hash = "sha256:31507f7b47cc1ead1f6e86927f8ebb196a0bab043f6345ce070f412a59bf87b5"}, + {file = "pyzmq-26.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:70fc7fcf0410d16ebdda9b26cbd8bf8d803d220a7f3522e060a69a9c87bf7bad"}, + {file = "pyzmq-26.2.0-cp313-cp313-win_arm64.whl", hash = "sha256:c3789bd5768ab5618ebf09cef6ec2b35fed88709b104351748a63045f0ff9797"}, + {file = "pyzmq-26.2.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:034da5fc55d9f8da09015d368f519478a52675e558c989bfcb5cf6d4e16a7d2a"}, + {file = "pyzmq-26.2.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:c92d73464b886931308ccc45b2744e5968cbaade0b1d6aeb40d8ab537765f5bc"}, + {file = "pyzmq-26.2.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:794a4562dcb374f7dbbfb3f51d28fb40123b5a2abadee7b4091f93054909add5"}, + {file = "pyzmq-26.2.0-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aee22939bb6075e7afededabad1a56a905da0b3c4e3e0c45e75810ebe3a52672"}, + {file = "pyzmq-26.2.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ae90ff9dad33a1cfe947d2c40cb9cb5e600d759ac4f0fd22616ce6540f72797"}, + {file = "pyzmq-26.2.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:43a47408ac52647dfabbc66a25b05b6a61700b5165807e3fbd40063fcaf46386"}, + {file = "pyzmq-26.2.0-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:25bf2374a2a8433633c65ccb9553350d5e17e60c8eb4de4d92cc6bd60f01d306"}, + {file = "pyzmq-26.2.0-cp313-cp313t-musllinux_1_1_i686.whl", hash = "sha256:007137c9ac9ad5ea21e6ad97d3489af654381324d5d3ba614c323f60dab8fae6"}, + {file = "pyzmq-26.2.0-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:470d4a4f6d48fb34e92d768b4e8a5cc3780db0d69107abf1cd7ff734b9766eb0"}, + {file = "pyzmq-26.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3b55a4229ce5da9497dd0452b914556ae58e96a4381bb6f59f1305dfd7e53fc8"}, + {file = "pyzmq-26.2.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9cb3a6460cdea8fe8194a76de8895707e61ded10ad0be97188cc8463ffa7e3a8"}, + {file = "pyzmq-26.2.0-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8ab5cad923cc95c87bffee098a27856c859bd5d0af31bd346035aa816b081fe1"}, + {file = "pyzmq-26.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ed69074a610fad1c2fda66180e7b2edd4d31c53f2d1872bc2d1211563904cd9"}, + {file = "pyzmq-26.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:cccba051221b916a4f5e538997c45d7d136a5646442b1231b916d0164067ea27"}, + {file = "pyzmq-26.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:0eaa83fc4c1e271c24eaf8fb083cbccef8fde77ec8cd45f3c35a9a123e6da097"}, + {file = "pyzmq-26.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:9edda2df81daa129b25a39b86cb57dfdfe16f7ec15b42b19bfac503360d27a93"}, + {file = "pyzmq-26.2.0-cp37-cp37m-win32.whl", hash = "sha256:ea0eb6af8a17fa272f7b98d7bebfab7836a0d62738e16ba380f440fceca2d951"}, + {file = "pyzmq-26.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:4ff9dc6bc1664bb9eec25cd17506ef6672d506115095411e237d571e92a58231"}, + {file = "pyzmq-26.2.0-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:2eb7735ee73ca1b0d71e0e67c3739c689067f055c764f73aac4cc8ecf958ee3f"}, + {file = "pyzmq-26.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a534f43bc738181aa7cbbaf48e3eca62c76453a40a746ab95d4b27b1111a7d2"}, + {file = "pyzmq-26.2.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:aedd5dd8692635813368e558a05266b995d3d020b23e49581ddd5bbe197a8ab6"}, + {file = "pyzmq-26.2.0-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8be4700cd8bb02cc454f630dcdf7cfa99de96788b80c51b60fe2fe1dac480289"}, + {file = "pyzmq-26.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fcc03fa4997c447dce58264e93b5aa2d57714fbe0f06c07b7785ae131512732"}, + {file = "pyzmq-26.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:402b190912935d3db15b03e8f7485812db350d271b284ded2b80d2e5704be780"}, + {file = "pyzmq-26.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8685fa9c25ff00f550c1fec650430c4b71e4e48e8d852f7ddcf2e48308038640"}, + {file = "pyzmq-26.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:76589c020680778f06b7e0b193f4b6dd66d470234a16e1df90329f5e14a171cd"}, + {file = "pyzmq-26.2.0-cp38-cp38-win32.whl", hash = "sha256:8423c1877d72c041f2c263b1ec6e34360448decfb323fa8b94e85883043ef988"}, + {file = "pyzmq-26.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:76589f2cd6b77b5bdea4fca5992dc1c23389d68b18ccc26a53680ba2dc80ff2f"}, + {file = "pyzmq-26.2.0-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:b1d464cb8d72bfc1a3adc53305a63a8e0cac6bc8c5a07e8ca190ab8d3faa43c2"}, + {file = "pyzmq-26.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4da04c48873a6abdd71811c5e163bd656ee1b957971db7f35140a2d573f6949c"}, + {file = "pyzmq-26.2.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d049df610ac811dcffdc147153b414147428567fbbc8be43bb8885f04db39d98"}, + {file = "pyzmq-26.2.0-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05590cdbc6b902101d0e65d6a4780af14dc22914cc6ab995d99b85af45362cc9"}, + {file = "pyzmq-26.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c811cfcd6a9bf680236c40c6f617187515269ab2912f3d7e8c0174898e2519db"}, + {file = "pyzmq-26.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6835dd60355593de10350394242b5757fbbd88b25287314316f266e24c61d073"}, + {file = "pyzmq-26.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc6bee759a6bddea5db78d7dcd609397449cb2d2d6587f48f3ca613b19410cfc"}, + {file = "pyzmq-26.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c530e1eecd036ecc83c3407f77bb86feb79916d4a33d11394b8234f3bd35b940"}, + {file = "pyzmq-26.2.0-cp39-cp39-win32.whl", hash = "sha256:367b4f689786fca726ef7a6c5ba606958b145b9340a5e4808132cc65759abd44"}, + {file = "pyzmq-26.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:e6fa2e3e683f34aea77de8112f6483803c96a44fd726d7358b9888ae5bb394ec"}, + {file = "pyzmq-26.2.0-cp39-cp39-win_arm64.whl", hash = "sha256:7445be39143a8aa4faec43b076e06944b8f9d0701b669df4af200531b21e40bb"}, + {file = "pyzmq-26.2.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:706e794564bec25819d21a41c31d4df2d48e1cc4b061e8d345d7fb4dd3e94072"}, + {file = "pyzmq-26.2.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b435f2753621cd36e7c1762156815e21c985c72b19135dac43a7f4f31d28dd1"}, + {file = "pyzmq-26.2.0-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:160c7e0a5eb178011e72892f99f918c04a131f36056d10d9c1afb223fc952c2d"}, + {file = "pyzmq-26.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c4a71d5d6e7b28a47a394c0471b7e77a0661e2d651e7ae91e0cab0a587859ca"}, + {file = "pyzmq-26.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:90412f2db8c02a3864cbfc67db0e3dcdbda336acf1c469526d3e869394fe001c"}, + {file = "pyzmq-26.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2ea4ad4e6a12e454de05f2949d4beddb52460f3de7c8b9d5c46fbb7d7222e02c"}, + {file = "pyzmq-26.2.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fc4f7a173a5609631bb0c42c23d12c49df3966f89f496a51d3eb0ec81f4519d6"}, + {file = "pyzmq-26.2.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:878206a45202247781472a2d99df12a176fef806ca175799e1c6ad263510d57c"}, + {file = "pyzmq-26.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17c412bad2eb9468e876f556eb4ee910e62d721d2c7a53c7fa31e643d35352e6"}, + {file = "pyzmq-26.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:0d987a3ae5a71c6226b203cfd298720e0086c7fe7c74f35fa8edddfbd6597eed"}, + {file = "pyzmq-26.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:39887ac397ff35b7b775db7201095fc6310a35fdbae85bac4523f7eb3b840e20"}, + {file = "pyzmq-26.2.0-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fdb5b3e311d4d4b0eb8b3e8b4d1b0a512713ad7e6a68791d0923d1aec433d919"}, + {file = "pyzmq-26.2.0-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:226af7dcb51fdb0109f0016449b357e182ea0ceb6b47dfb5999d569e5db161d5"}, + {file = "pyzmq-26.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bed0e799e6120b9c32756203fb9dfe8ca2fb8467fed830c34c877e25638c3fc"}, + {file = "pyzmq-26.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:29c7947c594e105cb9e6c466bace8532dc1ca02d498684128b339799f5248277"}, + {file = "pyzmq-26.2.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cdeabcff45d1c219636ee2e54d852262e5c2e085d6cb476d938aee8d921356b3"}, + {file = "pyzmq-26.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35cffef589bcdc587d06f9149f8d5e9e8859920a071df5a2671de2213bef592a"}, + {file = "pyzmq-26.2.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18c8dc3b7468d8b4bdf60ce9d7141897da103c7a4690157b32b60acb45e333e6"}, + {file = "pyzmq-26.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7133d0a1677aec369d67dd78520d3fa96dd7f3dcec99d66c1762870e5ea1a50a"}, + {file = "pyzmq-26.2.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6a96179a24b14fa6428cbfc08641c779a53f8fcec43644030328f44034c7f1f4"}, + {file = "pyzmq-26.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:4f78c88905461a9203eac9faac157a2a0dbba84a0fd09fd29315db27be40af9f"}, + {file = "pyzmq-26.2.0.tar.gz", hash = "sha256:070672c258581c8e4f640b5159297580a9974b026043bd4ab0470be9ed324f1f"}, +] + +[package.dependencies] +cffi = {version = "*", markers = "implementation_name == \"pypy\""} + [[package]] name = "referencing" version = "0.35.1" @@ -748,6 +1939,17 @@ files = [ {file = "ruff-0.5.7.tar.gz", hash = "sha256:8dfc0a458797f5d9fb622dd0efc52d796f23f0a1493a9527f4e49a550ae9a7e5"}, ] +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + [[package]] name = "sniffio" version = "1.3.1" @@ -759,6 +1961,25 @@ files = [ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] +[[package]] +name = "stack-data" +version = "0.6.3" +description = "Extract data from python stack frames and tracebacks for informative displays" +optional = false +python-versions = "*" +files = [ + {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, + {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, +] + +[package.dependencies] +asttokens = ">=2.1.0" +executing = ">=1.2.0" +pure-eval = "*" + +[package.extras] +tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] + [[package]] name = "tomli" version = "2.0.1" @@ -770,6 +1991,41 @@ files = [ {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, ] +[[package]] +name = "tornado" +version = "6.4.1" +description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +optional = false +python-versions = ">=3.8" +files = [ + {file = "tornado-6.4.1-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:163b0aafc8e23d8cdc3c9dfb24c5368af84a81e3364745ccb4427669bf84aec8"}, + {file = "tornado-6.4.1-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6d5ce3437e18a2b66fbadb183c1d3364fb03f2be71299e7d10dbeeb69f4b2a14"}, + {file = "tornado-6.4.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4"}, + {file = "tornado-6.4.1-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ae50a504a740365267b2a8d1a90c9fbc86b780a39170feca9bcc1787ff80842"}, + {file = "tornado-6.4.1-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:613bf4ddf5c7a95509218b149b555621497a6cc0d46ac341b30bd9ec19eac7f3"}, + {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25486eb223babe3eed4b8aecbac33b37e3dd6d776bc730ca14e1bf93888b979f"}, + {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:454db8a7ecfcf2ff6042dde58404164d969b6f5d58b926da15e6b23817950fc4"}, + {file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a02a08cc7a9314b006f653ce40483b9b3c12cda222d6a46d4ac63bb6c9057698"}, + {file = "tornado-6.4.1-cp38-abi3-win32.whl", hash = "sha256:d9a566c40b89757c9aa8e6f032bcdb8ca8795d7c1a9762910c722b1635c9de4d"}, + {file = "tornado-6.4.1-cp38-abi3-win_amd64.whl", hash = "sha256:b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7"}, + {file = "tornado-6.4.1.tar.gz", hash = "sha256:92d3ab53183d8c50f8204a51e6f91d18a15d5ef261e84d452800d4ff6fc504e9"}, +] + +[[package]] +name = "traitlets" +version = "5.14.3" +description = "Traitlets Python configuration system" +optional = false +python-versions = ">=3.8" +files = [ + {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"}, + {file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"}, +] + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"] + [[package]] name = "typing-extensions" version = "4.12.2" @@ -809,7 +2065,37 @@ h2 = ["h2 (>=4,<5)"] socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] zstd = ["zstandard (>=0.18.0)"] +[[package]] +name = "wcwidth" +version = "0.2.13" +description = "Measures the displayed width of unicode strings in a terminal" +optional = false +python-versions = "*" +files = [ + {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, + {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, +] + +[[package]] +name = "zipp" +version = "3.20.1" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.20.1-py3-none-any.whl", hash = "sha256:9960cd8967c8f85a56f920d5d507274e74f9ff813a0ab8889a5b5be2daf44064"}, + {file = "zipp-3.20.1.tar.gz", hash = "sha256:c22b14cc4763c5a5b04134207736c107db42e9d3ef2d9779d465f5f1bcba572b"}, +] + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-ignore-flaky"] +type = ["pytest-mypy"] + [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "b50c36e9a7de2af832b4fc2e6188aa6baef3879effa9096cc82f0e41c91c7d41" +content-hash = "72bf76447f90eb7f302ff9af0f506757e3fc33ba462905493b7194845a01e331" diff --git a/prompts/humaneval-dafny/rewrite.txt b/prompts/humaneval-dafny/rewrite.txt index 5501d5f..12b9245 100644 --- a/prompts/humaneval-dafny/rewrite.txt +++ b/prompts/humaneval-dafny/rewrite.txt @@ -1,5 +1,40 @@ Rewrite the following dafny program, adding correct invariants into `while` loops. Also add assertions in nessesary places. Do not change the code, only add invariants and assertions. Don't remove any helper functions, they are there to help you. +You might need to work with accumulating functions, such as sum, so here's an example of how to do that: +```dafny +function sum(s: seq) : int { + if |s| == 0 then 0 else s[0] + sum(s[1..]) +} + +lemma sum_prop(s: seq) + requires |s| > 0 + ensures sum(s) == sum(s[..|s| - 1]) + s[ |s| - 1 ] +{ + if (|s| > 1) { + assert (s[1..][..|s[1..]| - 1]) == s[1..|s| - 1]; + } +} + +method sum_loop(numbers: seq) returns (s: int) + ensures s == sum(numbers) + { + assert numbers[..|numbers|] == numbers; + s := 0; + var i := 0; + while (i < |numbers|) + invariant 0 <= i <= |numbers| + invariant s == sum(numbers[..i]) + { + assert sum(numbers[..i + 1]) == sum(numbers[..i]) + numbers[i] by { + assert numbers[..i+1][..i] == numbers[..i]; + sum_prop(numbers[..i + 1]); + } + s := s + numbers[i]; + + i := i + 1; + } +} +``` The program: {program} diff --git a/prompts/humaneval-dafny/sys.txt b/prompts/humaneval-dafny/sys.txt index a86fd57..8619fee 100644 --- a/prompts/humaneval-dafny/sys.txt +++ b/prompts/humaneval-dafny/sys.txt @@ -1,4 +1,3 @@ You are an expert in Dafny. You will be given tasks dealing with Dafny programs including precise docstrings and specifications. -Do not provide explanations. Do not repeat given programs, answer with new content only. -Respond only in dafny code. +Do not provide explanations. Respond only in dafny code. diff --git a/pyproject.toml b/pyproject.toml index 2320531..371b467 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,6 +31,8 @@ appdirs = "^1.4.4" isort = "^5.10.1" ruff = "^0.5.4" pytest = "^8.3.1" +matplotlib = "^3.9.2" +ipykernel = "^6.29.5" [build-system] requires = ["poetry-core"] diff --git a/results/tries_HumanEval-Dafny.json b/results/tries_HumanEval-Dafny.json deleted file mode 100644 index f3d800a..0000000 --- a/results/tries_HumanEval-Dafny.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "002-truncate.dfy": 0, - "083-starts_one_ends.dfy": 0, - "159-eat.dfy": 0 -} \ No newline at end of file diff --git a/run_validating.sh b/run_validating.sh index e2417a8..1ffaf5b 100755 --- a/run_validating.sh +++ b/run_validating.sh @@ -8,4 +8,5 @@ PYLOG_LEVEL=INFO NOFILE=1 incremental_run \ --prompts-directory=prompts/humaneval-dafny \ --verifier-command="dafny verify --allow-warnings --verification-time-limit 10" \ --insert-conditions-mode=llm-single-step \ + --tries 10 \ --dir="Benches/HumanEval-Dafny" diff --git a/scripts/generate_result_graph.py b/scripts/generate_result_graph.py new file mode 100644 index 0000000..a3bab94 --- /dev/null +++ b/scripts/generate_result_graph.py @@ -0,0 +1,25 @@ +# %% +import matplotlib.pyplot as plt +import json +from itertools import accumulate +import pathlib + +# %% +path = "../results/tries_HumanEval-Dafny.json" +bench = pathlib.Path("../benches/HumanEval-Dafny") +file_cnt = len(list(bench.glob("*.dfy"))) +with open(path) as f: + data = json.load(f) + +tries = data.values() +max_tries = max(tries) +cnt = [0] * (max_tries + 1) +for t in tries: + cnt[t] += 1 +cnt = list(accumulate(cnt)) +cnt = [c / file_cnt for c in cnt] +plt.plot(cnt) +plt.show() + +# %% +f"{cnt[-1] * 100}% of the files were successfully verified" diff --git a/verified_cogen/experiments/incremental_run.py b/verified_cogen/experiments/incremental_run.py index 47176c2..818ee4a 100644 --- a/verified_cogen/experiments/incremental_run.py +++ b/verified_cogen/experiments/incremental_run.py @@ -36,6 +36,7 @@ def main(): results = json.load(f) files = list(directory.glob("[!.]*.dfy")) + files.sort() verifier = Verifier(args.shell, args.verifier_command) for file in files: @@ -52,9 +53,9 @@ def main(): display_name = rename_file(file) marker_name = str(file.relative_to(directory)) if marker_name in results and isinstance(results[marker_name], int): - print("Skipping:", display_name) + logger.info(f"Skipping: {display_name} as it has already been verified") continue - print("Processing:", display_name) + logger.info(f"Processing: {display_name}") try: tries = runner.run_on_file(mode, args.tries, str(file)) except KeyboardInterrupt: @@ -64,6 +65,9 @@ def main(): tries = None if tries is not None: results[marker_name] = tries + logger.info(f"Verified {display_name} in {tries} tries") + else: + logger.info(f"Failed to verify {display_name}") with open(json_results, "w") as f: json.dump(results, f, indent=2) diff --git a/verified_cogen/runners/__init__.py b/verified_cogen/runners/__init__.py index a2a1049..69f0de7 100644 --- a/verified_cogen/runners/__init__.py +++ b/verified_cogen/runners/__init__.py @@ -79,9 +79,9 @@ def try_fixing( self.logger.info("Verification failed:") self.logger.info(out_inv) self.logger.info(err_inv) - self.logger.info("Retrying...") tries -= 1 if tries > 0: + self.logger.info(f"Retrying with {tries} tries left...") inv_prg = self.llm.ask_for_fixed(out_inv + err_inv) return None diff --git a/verified_cogen/runners/languages/language.py b/verified_cogen/runners/languages/language.py index a1c6850..def935a 100644 --- a/verified_cogen/runners/languages/language.py +++ b/verified_cogen/runners/languages/language.py @@ -44,7 +44,6 @@ def generate_validators(self, code: str) -> str: validators = [] for match in methods: - print(match.groups()) method_name, parameters, returns, specs = ( match.group(1), match.group(2), From b90055e07ba3bf67f8d92e8c731530858091e155 Mon Sep 17 00:00:00 2001 From: WeetHet Date: Thu, 12 Sep 2024 10:54:47 +0300 Subject: [PATCH 10/23] multilang incremental run --- run_validating.sh | 14 ++++++---- verified_cogen/args.py | 8 ++++-- verified_cogen/experiments/incremental_run.py | 27 ++++++++++++++++--- 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/run_validating.sh b/run_validating.sh index 1ffaf5b..3dc2b7f 100755 --- a/run_validating.sh +++ b/run_validating.sh @@ -1,12 +1,16 @@ #!/bin/bash -source .venv/bin/activate +vcmd=${1:-"dafny verify --allow-warnings --verification-time-limit 10"} +prompts_dir=${2:-"prompts/humaneval-dafny"} +dir=${3:-"benches/HumanEval-Dafny"} +ext=${4:-"dfy"} -PYLOG_LEVEL=INFO NOFILE=1 incremental_run \ +PYLOG_LEVEL=INFO NOFILE=1 poetry run incremental_run \ --grazie-token=$GRAZIE_JWT_TOKEN \ --llm-profile="anthropic-claude-3.5-sonnet" \ - --prompts-directory=prompts/humaneval-dafny \ - --verifier-command="dafny verify --allow-warnings --verification-time-limit 10" \ --insert-conditions-mode=llm-single-step \ --tries 10 \ - --dir="Benches/HumanEval-Dafny" + --verifier-command="$vcmd" \ + --prompts-directory="$prompts_dir" \ + --dir="$dir" \ + --filter-by-ext="$ext" diff --git a/verified_cogen/args.py b/verified_cogen/args.py index 3f38a6c..deadea7 100644 --- a/verified_cogen/args.py +++ b/verified_cogen/args.py @@ -4,7 +4,7 @@ from verified_cogen.tools.modes import VALID_MODES -def get_args(): +def get_default_parser(): parser = argparse.ArgumentParser() parser.add_argument("-i", "--input", help="input file", required=False) parser.add_argument("-d", "--dir", help="directory to run on", required=False) @@ -50,4 +50,8 @@ def get_args(): parser.add_argument( "-s", "--output-style", choices=["stats", "full"], default="full" ) - return parser.parse_args() + return parser + + +def get_args(): + return get_default_parser().parse_args() diff --git a/verified_cogen/experiments/incremental_run.py b/verified_cogen/experiments/incremental_run.py index 818ee4a..999dfb5 100644 --- a/verified_cogen/experiments/incremental_run.py +++ b/verified_cogen/experiments/incremental_run.py @@ -3,7 +3,8 @@ import json from verified_cogen.llm.llm import LLM -from verified_cogen.main import get_args, rename_file +from verified_cogen.args import get_default_parser +from verified_cogen.tools import rename_file from verified_cogen.runners.invariants import InvariantRunner from verified_cogen.runners.languages import register_basic_languages from verified_cogen.runners.languages.language import LanguageDatabase @@ -17,7 +18,10 @@ def main(): register_basic_languages() - args = get_args() + parser = get_default_parser() + parser.add_argument("--filter-by-ext", help="filter by extension", default=None) + + args = parser.parse_args() mode = Mode(args.insert_conditions_mode) assert mode != Mode.REGEX assert args.dir is not None @@ -35,8 +39,23 @@ def main(): with open(json_results, "r") as f: results = json.load(f) - files = list(directory.glob("[!.]*.dfy")) + if args.filter_by_ext is not None: + files = list(directory.glob(f"[!.]*.{args.filter_by_ext}")) + else: + files = list(directory.glob("[!.]*")) + assert len(files) > 0, "No files found in the directory" files.sort() + + extension = files[0].suffix[1:] + if ( + different := next((f for f in files if f.suffix[1:] != extension), None) + ) is not None: + logger.error( + f"Found files different extensions: {files[0].name} and {different.name}, please use a single extension" + ) + return + + language = LanguageDatabase().get(extension) verifier = Verifier(args.shell, args.verifier_command) for file in files: @@ -48,7 +67,7 @@ def main(): ) runner = ValidatingRunner( wrapping=InvariantRunner(llm, logger, verifier), - language=LanguageDatabase().get("dfy"), + language=language, ) display_name = rename_file(file) marker_name = str(file.relative_to(directory)) From 95c5a1556f1526e8a99bbe882e1758e6b57e8066 Mon Sep 17 00:00:00 2001 From: WeetHet Date: Thu, 12 Sep 2024 14:09:01 +0300 Subject: [PATCH 11/23] make incremental run work with gui --- gui/Cargo.lock | 12 + gui/Cargo.toml | 1 + gui/src/helpers.rs | 18 +- gui/src/main.rs | 431 +----------------- gui/src/ui/display.rs | 49 ++ gui/src/ui/file_picker.rs | 75 +++ gui/src/ui/mod.rs | 8 + gui/src/ui/output.rs | 86 ++++ gui/src/ui/plot.rs | 31 ++ gui/src/ui/run.rs | 159 +++++++ gui/src/ui/settings.rs | 87 ++++ gui/src/ui/token_input.rs | 21 + gui/src/ui/verifier_details.rs | 53 +++ prompts/dafny_invariants/timeout.txt | 3 + prompts/humaneval-dafny/timeout.txt | 3 + run_validating.sh | 1 + verified_cogen/args.py | 1 + verified_cogen/experiments/incremental_run.py | 27 +- verified_cogen/main.py | 81 +++- verified_cogen/tools/__init__.py | 18 + 20 files changed, 717 insertions(+), 448 deletions(-) create mode 100644 gui/src/ui/display.rs create mode 100644 gui/src/ui/file_picker.rs create mode 100644 gui/src/ui/mod.rs create mode 100644 gui/src/ui/output.rs create mode 100644 gui/src/ui/plot.rs create mode 100644 gui/src/ui/run.rs create mode 100644 gui/src/ui/settings.rs create mode 100644 gui/src/ui/token_input.rs create mode 100644 gui/src/ui/verifier_details.rs create mode 100644 prompts/dafny_invariants/timeout.txt create mode 100644 prompts/humaneval-dafny/timeout.txt diff --git a/gui/Cargo.lock b/gui/Cargo.lock index 7666ec5..91220c4 100644 --- a/gui/Cargo.lock +++ b/gui/Cargo.lock @@ -1173,6 +1173,17 @@ dependencies = [ "winit", ] +[[package]] +name = "egui_plot" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7acc4fe778c41b91d57e04c1a2cf5765b3dc977f9f8384d2bb2eb4254855365" +dependencies = [ + "ahash", + "egui", + "emath", +] + [[package]] name = "emath" version = "0.28.1" @@ -1696,6 +1707,7 @@ dependencies = [ "directories", "eframe", "egui_extras", + "egui_plot", "env_logger", "log", "once_cell", diff --git a/gui/Cargo.toml b/gui/Cargo.toml index 99ab041..b547c04 100644 --- a/gui/Cargo.toml +++ b/gui/Cargo.toml @@ -8,6 +8,7 @@ anyhow = "1.0.86" directories = "5.0.1" eframe = { version = "0.28.1", features = ["persistence"] } egui_extras = { version = "0.28.1", features = ["syntect"] } +egui_plot = "0.28.1" env_logger = "0.11.3" log = "0.4.22" once_cell = "1.19.0" diff --git a/gui/src/helpers.rs b/gui/src/helpers.rs index 3db3d59..f44a529 100644 --- a/gui/src/helpers.rs +++ b/gui/src/helpers.rs @@ -3,7 +3,7 @@ use std::{ process::{Command, Output}, }; -use eframe::egui::{self, TextEdit}; +use eframe::egui::{self, TextEdit, Ui}; use crate::Settings; @@ -59,12 +59,20 @@ fn add_common_arguments<'a>( token: &str, settings: &Settings, ) -> &'a mut Command { + let bench_type = if settings.incremental_run { + String::from("validating") + } else { + settings.bench_type.to_string() + }; + if settings.do_filter { + cmd.args(["--filter-by-ext", &settings.filter_by_ext]); + } cmd.args(["--verifier-command", &settings.verifier_command]) .args(["--prompts-directory", &settings.prompts_directory]) .args(["--insert-conditions-mode", "llm-single-step"]) .args(["--llm-profile", settings.llm_profile.as_grazie()]) .args(["--grazie-token", token]) - .args(["--bench-type", &settings.bench_type.to_string()]) + .args(["--bench-type", &bench_type]) .args(["--tries", &make_tries(&settings.tries)]) .args(["--retries", &make_retries(&settings.retries)]) .args(["--verifier-timeout", &make_timeout(&settings.timeout)]) @@ -130,3 +138,9 @@ pub fn integer_edit_field( } res } + +pub(crate) fn paint_code(ui: &mut Ui, code: &str, lang: &str) { + let theme = egui_extras::syntax_highlighting::CodeTheme::from_memory(ui.ctx()); + + egui_extras::syntax_highlighting::code_view_ui(ui, &theme, code, lang); +} diff --git a/gui/src/main.rs b/gui/src/main.rs index 70a480f..58d762e 100644 --- a/gui/src/main.rs +++ b/gui/src/main.rs @@ -1,19 +1,24 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] mod helpers; +mod ui; -use eframe::egui::{self, Separator, TextEdit, Ui}; +use eframe::egui::{self}; use std::{ + collections::HashMap, fmt::Display, fs::File, path::PathBuf, - sync::{atomic::AtomicBool, Arc, RwLock}, + sync::{ + atomic::{AtomicBool, AtomicUsize}, + Arc, RwLock, + }, }; use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; -use helpers::{basename, extension, integer_edit_field, run_on_directory, run_on_file}; +use helpers::basename; static APP_DIRS: Lazy = Lazy::new(|| { directories::ProjectDirs::from("", "", "verified-cogen").expect("Failed to get app directories") @@ -79,7 +84,9 @@ enum BenchMode { impl BenchMode { fn llm_generated_path(&self, path: &str) -> PathBuf { let name = match self { - BenchMode::Invariants | BenchMode::Generic | BenchMode::Validating => basename(path).to_string(), + BenchMode::Invariants | BenchMode::Generic | BenchMode::Validating => { + basename(path).to_string() + } BenchMode::Generate => { let base = basename(path); base.chars() @@ -98,11 +105,13 @@ impl Display for BenchMode { BenchMode::Invariants => write!(f, "invariants"), BenchMode::Generic => write!(f, "generic"), BenchMode::Generate => write!(f, "generate"), - BenchMode::Validating => write!(f, "validating") + BenchMode::Validating => write!(f, "validating"), } } } +type IncrementalRunResults = HashMap; + #[derive(Default)] struct AppState { settings: Settings, @@ -113,6 +122,8 @@ struct AppState { running: Arc, last_verified_code: Arc>>, last_verified_extension: Arc>>, + incremental_run_results: Arc>>, + incremental_file_count: Arc, output: Arc>>, log: Arc>>, } @@ -170,6 +181,9 @@ struct Settings { file_mode: FileMode, runs: String, timeout: String, + do_filter: bool, + filter_by_ext: String, + incremental_run: bool, } impl Default for Settings { @@ -187,6 +201,9 @@ impl Default for Settings { file_mode: FileMode::SingleFile, runs: String::from("1"), timeout: String::from("60"), + incremental_run: false, + do_filter: false, + filter_by_ext: String::new(), } } } @@ -223,407 +240,3 @@ impl eframe::App for AppState { storage.set_string("settings_json", settings); } } - -impl AppState { - fn run(&mut self) { - let running = Arc::clone(&self.running); - let output = Arc::clone(&self.output); - let last_verified_code = Arc::clone(&self.last_verified_code); - let last_verified_ext = Arc::clone(&self.last_verified_extension); - - let settings = self.settings.clone(); - let file_mode = self.settings.file_mode.clone(); - let path = self.path.clone(); - let log = Arc::clone(&self.log); - - _ = std::thread::spawn(move || { - let result = std::panic::catch_unwind(|| { - running.store(true, std::sync::atomic::Ordering::SeqCst); - if let Ok(mut output) = output.write() { - *output = None; - } - let log_dir = APP_DIRS.cache_dir().join("log"); - _ = File::create(log_dir.join("llm.log")).expect("Failed to clean log file"); - match file_mode { - FileMode::SingleFile => { - if let Some(path) = path { - let extension = extension(&path); - if let Some(path) = path.to_str() { - let py_output = run_on_file(path, &settings); - if let Ok(mut output) = output.write() { - *output = Some(py_output); - } - - let llm_generated_path = - settings.bench_type.llm_generated_path(path); - let llm_code = std::fs::read_to_string(llm_generated_path).ok(); - if let Ok(mut last_verified_code) = last_verified_code.write() { - *last_verified_code = llm_code; - } - - if let Ok(mut last_verified_extension) = last_verified_ext.write() { - *last_verified_extension = Some(String::from(extension)); - } - } - } - } - FileMode::Directory => { - if let Ok(mut last_verified_code) = last_verified_code.write() { - *last_verified_code = None; - } - - if let Ok(mut last_verified_extension) = last_verified_ext.write() { - *last_verified_extension = None; - } - - if let Some(directory) = path { - if let Some(directory) = directory.to_str() { - let py_output = run_on_directory(directory, &settings); - if let Ok(mut output) = output.write() { - *output = Some(py_output); - } - } - } - } - } - if let Ok(mut log) = log.write() { - if let Ok(mut output) = output.write() { - if let Some((_, stderr)) = output.as_mut() { - if let Some(log) = log.as_ref() { - *stderr += &format!("\nLog:\n{}", log) - } - } - } - *log = None; - } - }); - if let Err(err) = result { - if let Ok(mut output) = output.write() { - *output = Some((String::from("Error"), format!("{:?}", err))); - } - } - running.store(false, std::sync::atomic::Ordering::SeqCst); - }); - - let running = Arc::clone(&self.running); - let log = Arc::clone(&self.log); - _ = std::thread::spawn(move || { - let log_file = APP_DIRS.cache_dir().join("log").join("llm.log"); - while running.load(std::sync::atomic::Ordering::SeqCst) { - let log_output = std::fs::read_to_string(&log_file).unwrap_or_default(); - if let Ok(mut log) = log.write() { - *log = Some(log_output); - } - std::thread::sleep(std::time::Duration::from_millis(100)); - } - }); - } - - fn file_picker(&mut self, ui: &mut Ui) { - ui.label("File mode: "); - if ui - .radio_value( - &mut self.settings.file_mode, - FileMode::SingleFile, - "Single file", - ) - .clicked() - { - self.files = None; - } - if ui - .radio_value( - &mut self.settings.file_mode, - FileMode::Directory, - "Directory", - ) - .clicked() - { - self.code = None; - } - - if ui.button("Open").clicked() { - match self.settings.file_mode { - FileMode::SingleFile => { - if let Some(file) = rfd::FileDialog::new().pick_file() { - self.code = Some( - std::fs::read_to_string(&file).expect("Failed to read file content"), - ); - self.path = Some(file); - } - } - FileMode::Directory => { - if let Some(dir) = rfd::FileDialog::new().pick_folder() { - self.files = Some( - std::fs::read_dir(&dir) - .expect("Failed to read directory content") - .filter_map(|entry| { - let path = - entry.expect("Failed to read directory entry").path(); - let s = path.to_string_lossy().to_string(); - let is_hidden = path - .file_name() - .map(|name| name.to_string_lossy().starts_with('.')) - .unwrap_or(true); - (!is_hidden).then_some(s) - }) - .collect(), - ); - self.path = Some(dir); - } - } - } - } - } - - fn runner(&mut self, ui: &mut Ui) { - ui.horizontal(|ui| { - self.file_picker(ui); - - let is_running = self.running.load(std::sync::atomic::Ordering::SeqCst); - - if ui.button("Run").clicked() && !is_running { - self.run(); - } - - if is_running { - ui.spinner(); - } - }); - } - - fn token_input(&mut self, ui: &mut Ui) { - let label = ui.heading("Grazie and verifier: "); - - ui.label("Grazie token: "); - ui.horizontal(|ui| { - let token = ui - .add( - TextEdit::singleline(&mut self.settings.grazie_token) - .hint_text("Enter your Grazie token") - .password(!self.token_hovered), - ) - .labelled_by(label.id); - self.token_hovered = token.hovered(); - }); - } - - fn verifier_details(&mut self, ui: &mut Ui) { - ui.label("Prompts directory: "); - ui.horizontal(|ui| { - ui.add( - TextEdit::singleline(&mut self.settings.prompts_directory) - .hint_text("Enter the prompts directory"), - ); - if ui.button("Select").clicked() { - if let Some(dir) = rfd::FileDialog::new().pick_folder() { - self.settings.prompts_directory = dir.to_string_lossy().to_string(); - } - } - }); - - ui.columns(2, |cols| { - let [left_ui, right_ui] = cols else { return }; - - left_ui.vertical(|ui| { - ui.label("Verifier command: "); - ui.add( - TextEdit::singleline(&mut self.settings.verifier_command) - .hint_text("Enter the verifier command"), - ); - }); - - right_ui.vertical(|ui| { - ui.label("Timeout: "); - let mut tmp_value = self.settings.timeout.clone(); - ui.add(TextEdit::singleline(&mut tmp_value).hint_text("Enter the timeout")); - if tmp_value.parse::().is_ok() || tmp_value.is_empty() { - self.settings.timeout = tmp_value; - } - }); - }); - - ui.label("Generate code: "); - ui.columns(2, |cols| { - let [left_ui, right_ui] = cols else { return }; - - left_ui.add( - TextEdit::singleline(&mut self.settings.generate_command) - .hint_text("Enter the command to generate code"), - ); - - right_ui.checkbox(&mut self.settings.use_poetry, "Use poetry"); - }); - } - - fn settings_ui(&mut self, ui: &mut Ui) { - ui.vertical(|ui| { - self.verifier_details(ui); - ui.separator(); - - ui.heading("Settings:"); - - egui::ComboBox::from_label("LLM Profile") - .selected_text(format!("{}", self.settings.llm_profile)) - .show_ui(ui, |ui| { - for profile in LLMProfile::all() { - ui.selectable_value( - &mut self.settings.llm_profile, - profile, - format!("{}", profile), - ); - } - }); - - ui.horizontal(|ui| { - ui.label("Bench mode: "); - ui.radio_value( - &mut self.settings.bench_type, - BenchMode::Invariants, - "Invariants", - ); - ui.radio_value(&mut self.settings.bench_type, BenchMode::Generic, "Generic"); - ui.radio_value( - &mut self.settings.bench_type, - BenchMode::Generate, - "Generate", - ); - ui.radio_value( - &mut self.settings.bench_type, - BenchMode::Validating, - "Validating" - ); - }); - ui.horizontal(|ui| { - let max_rect = ui.max_rect(); - let is_dir_mode = matches!(self.settings.file_mode, FileMode::Directory); - let div = if is_dir_mode { 5.0 } else { 3.0 }; - let size = [max_rect.width() / div, max_rect.height()]; - ui.label("Tries: "); - integer_edit_field(ui, "Tries", &mut self.settings.tries, size); - - ui.label("Retries: "); - integer_edit_field(ui, "Retries", &mut self.settings.retries, size); - - if is_dir_mode { - ui.label("Runs: "); - integer_edit_field(ui, "Retries", &mut self.settings.runs, size); - } - }); - }); - } - - fn display(&mut self, ui: &mut Ui) { - if self.settings.file_mode == FileMode::SingleFile { - if let Some(code) = self.code.as_ref() { - let path = self.path.as_ref().expect("Code and path should be in sync"); - egui::ScrollArea::vertical().show(ui, |ui| { - paint_code(ui, code, extension(path)); - }); - } else { - ui.label("No file selected"); - } - } else if let Some(files) = self.files.as_mut() { - let mut reset = false; - - egui::ScrollArea::vertical().show(ui, |ui| { - ui.heading("Files"); - ui.separator(); - - for file in files.iter() { - ui.horizontal(|ui| { - ui.label(basename(file)); - - if ui.button("Open").clicked() { - self.code = Some( - std::fs::read_to_string(file).expect("Failed to read file content"), - ); - self.path = Some(file.into()); - self.settings.file_mode = FileMode::SingleFile; - reset = true; - } - }); - } - }); - - if reset { - self.files = None; - } - } else { - ui.label("No directory selected"); - } - } - - fn output_ui(&mut self, ui: &mut Ui, panel_height: f32) { - let output_width = ui.available_width(); - let part = match self.settings.file_mode { - FileMode::SingleFile => 4.0, - FileMode::Directory => 2.0, - }; - ui.horizontal(|ui| { - ui.set_height(panel_height); - ui.add(Separator::default().vertical().grow(panel_height)); - - ui.vertical(|ui| { - if let Ok(output) = self.output.read() { - if let Some(output) = output.as_ref() { - let (stdout, stderr) = &output; - ui.heading("Stdout:"); - ui.push_id("stdout", |ui| { - ui.set_max_height(panel_height / part); - egui::ScrollArea::vertical().show(ui, |ui| { - ui.set_min_width(output_width); - ui.monospace(stdout); - }); - }); - - ui.separator(); - - ui.heading("Stderr:"); - ui.push_id("stderr", |ui| { - ui.set_max_height(panel_height / part); - egui::ScrollArea::vertical().show(ui, |ui| { - ui.set_min_width(output_width); - ui.monospace(stderr); - }); - }); - - if let Ok(code) = self.last_verified_code.read() { - if let Ok(ext) = self.last_verified_extension.read() { - if let Some(code) = code.as_ref() { - if let Some(ext) = ext.as_ref() { - ui.separator(); - ui.heading("Last verified code:"); - ui.push_id("llm-code", |ui| { - egui::ScrollArea::vertical().show(ui, |ui| { - ui.set_min_width(output_width); - paint_code(ui, code, ext); - }); - }); - } - } - } - } - } - } - - if let Ok(log) = self.log.read() { - if let Some(log) = log.as_ref() { - ui.heading("Log:"); - ui.push_id("log", |ui| { - egui::ScrollArea::vertical().show(ui, |ui| { - ui.monospace(log); - }); - }); - } - } - }); - }); - } -} - -fn paint_code(ui: &mut Ui, code: &str, lang: &str) { - let theme = egui_extras::syntax_highlighting::CodeTheme::from_memory(ui.ctx()); - - egui_extras::syntax_highlighting::code_view_ui(ui, &theme, code, lang); -} diff --git a/gui/src/ui/display.rs b/gui/src/ui/display.rs new file mode 100644 index 0000000..b4e7d74 --- /dev/null +++ b/gui/src/ui/display.rs @@ -0,0 +1,49 @@ +use eframe::egui::{self, Ui}; + +use crate::{ + helpers::{basename, extension, paint_code}, + AppState, FileMode, +}; + +impl AppState { + pub(crate) fn display(&mut self, ui: &mut Ui) { + if self.settings.file_mode == FileMode::SingleFile { + if let Some(code) = self.code.as_ref() { + let path = self.path.as_ref().expect("Code and path should be in sync"); + egui::ScrollArea::vertical().show(ui, |ui| { + paint_code(ui, code, extension(path)); + }); + } else { + ui.label("No file selected"); + } + } else if let Some(files) = self.files.as_mut() { + let mut reset = false; + + egui::ScrollArea::vertical().show(ui, |ui| { + ui.heading("Files"); + ui.separator(); + + for file in files.iter() { + ui.horizontal(|ui| { + ui.label(basename(file)); + + if !self.settings.incremental_run && ui.button("Open").clicked() { + self.code = Some( + std::fs::read_to_string(file).expect("Failed to read file content"), + ); + self.path = Some(file.into()); + self.settings.file_mode = FileMode::SingleFile; + reset = true; + } + }); + } + }); + + if reset { + self.files = None; + } + } else { + ui.label("No directory selected"); + } + } +} diff --git a/gui/src/ui/file_picker.rs b/gui/src/ui/file_picker.rs new file mode 100644 index 0000000..e9fd597 --- /dev/null +++ b/gui/src/ui/file_picker.rs @@ -0,0 +1,75 @@ +use std::ffi::OsString; + +use eframe::egui::Ui; + +use crate::{AppState, FileMode}; + +impl AppState { + pub(crate) fn file_picker(&mut self, ui: &mut Ui) { + ui.label("File mode: "); + if !self.settings.incremental_run + && ui + .radio_value( + &mut self.settings.file_mode, + FileMode::SingleFile, + "Single file", + ) + .clicked() + { + self.settings.incremental_run = false; + self.files = None; + } + if ui + .radio_value( + &mut self.settings.file_mode, + FileMode::Directory, + "Directory", + ) + .clicked() + { + self.code = None; + } + + if ui.button("Open").clicked() { + match self.settings.file_mode { + FileMode::SingleFile => { + if let Some(file) = rfd::FileDialog::new().pick_file() { + self.code = Some( + std::fs::read_to_string(&file).expect("Failed to read file content"), + ); + self.path = Some(file); + } + } + FileMode::Directory => { + if let Some(dir) = rfd::FileDialog::new().pick_folder() { + let do_filter = self.settings.do_filter; + let filter_by_ext: OsString = self.settings.filter_by_ext.clone().into(); + self.files = { + let mut files: Vec<_> = std::fs::read_dir(&dir) + .expect("Failed to read directory content") + .filter_map(|entry| { + let path = + entry.expect("Failed to read directory entry").path(); + if do_filter + && path.extension().map_or(true, |ext| ext != filter_by_ext) + { + return None; + } + let s = path.to_string_lossy().to_string(); + let is_hidden = path + .file_name() + .map(|name| name.to_string_lossy().starts_with('.')) + .unwrap_or(true); + (!is_hidden).then_some(s) + }) + .collect(); + files.sort(); + Some(files) + }; + self.path = Some(dir); + } + } + } + } + } +} diff --git a/gui/src/ui/mod.rs b/gui/src/ui/mod.rs new file mode 100644 index 0000000..2fb16c5 --- /dev/null +++ b/gui/src/ui/mod.rs @@ -0,0 +1,8 @@ +mod display; +mod file_picker; +mod output; +mod plot; +mod run; +mod settings; +mod token_input; +mod verifier_details; diff --git a/gui/src/ui/output.rs b/gui/src/ui/output.rs new file mode 100644 index 0000000..455001d --- /dev/null +++ b/gui/src/ui/output.rs @@ -0,0 +1,86 @@ +use eframe::egui::{self, Separator, Ui}; + +use crate::{helpers::paint_code, AppState, FileMode}; + +impl AppState { + pub(crate) fn output_ui(&mut self, ui: &mut Ui, panel_height: f32) { + let output_width = ui.available_width(); + let mut part = match self.settings.file_mode { + FileMode::SingleFile => 4.0, + FileMode::Directory => 2.0, + }; + + ui.horizontal(|ui| { + ui.set_height(panel_height); + ui.add(Separator::default().vertical().grow(panel_height)); + + ui.vertical(|ui| { + if let Ok(incremental_run_results) = self.incremental_run_results.read() { + part += 1.0; + if let Some(results) = incremental_run_results.as_ref() { + let cnt = self + .incremental_file_count + .load(std::sync::atomic::Ordering::SeqCst); + ui.push_id("plot", |ui| { + ui.set_max_height(panel_height / part); + self.plot(results, cnt, ui); + }); + } + } + + if let Ok(output) = self.output.read() { + if let Some(output) = output.as_ref() { + let (stdout, stderr) = &output; + ui.heading("Stdout:"); + ui.push_id("stdout", |ui| { + ui.set_max_height(panel_height / part); + egui::ScrollArea::vertical().show(ui, |ui| { + ui.set_min_width(output_width); + ui.monospace(stdout); + }); + }); + + ui.separator(); + + ui.heading("Stderr:"); + ui.push_id("stderr", |ui| { + ui.set_max_height(panel_height / part); + egui::ScrollArea::vertical().show(ui, |ui| { + ui.set_min_width(output_width); + ui.monospace(stderr); + }); + }); + + if let Ok(code) = self.last_verified_code.read() { + if let Ok(ext) = self.last_verified_extension.read() { + if let Some(code) = code.as_ref() { + if let Some(ext) = ext.as_ref() { + ui.separator(); + ui.heading("Last verified code:"); + ui.push_id("llm-code", |ui| { + egui::ScrollArea::vertical().show(ui, |ui| { + ui.set_min_width(output_width); + paint_code(ui, code, ext); + }); + }); + } + } + } + } + } + } + + if let Ok(log) = self.log.read() { + if let Some(log) = log.as_ref() { + ui.heading("Log:"); + ui.push_id("log", |ui| { + egui::ScrollArea::vertical().show(ui, |ui| { + ui.monospace(log); + }); + }); + } + } + }); + }); + } +} diff --git a/gui/src/ui/plot.rs b/gui/src/ui/plot.rs new file mode 100644 index 0000000..425b5af --- /dev/null +++ b/gui/src/ui/plot.rs @@ -0,0 +1,31 @@ +use eframe::egui::Ui; +use egui_plot::{uniform_grid_spacer, Line, Plot}; + +use crate::{AppState, IncrementalRunResults}; + +impl AppState { + pub fn plot(&self, results: &IncrementalRunResults, file_cnt: usize, ui: &mut Ui) { + let tries: Vec<_> = results.values().copied().collect(); + let max_tries = *tries + .iter() + .max() + .expect("results should contain at least one file"); + let mut cnt = vec![0; max_tries + 1]; + for t in tries { + cnt[t] += 1; + } + let percent = cnt + .into_iter() + .enumerate() + .scan(0, |state, (i, x)| { + *state += x; + Some([i as f64, *state as f64 / file_cnt as f64 * 100.0]) + }) + .collect::>(); + + Plot::new("results_plot") + .x_grid_spacer(uniform_grid_spacer(|_| [5.0, 1.0, 1.0])) + // .view_aspect(1.0) + .show(ui, |plot_ui| plot_ui.line(Line::new(percent))); + } +} diff --git a/gui/src/ui/run.rs b/gui/src/ui/run.rs new file mode 100644 index 0000000..6187001 --- /dev/null +++ b/gui/src/ui/run.rs @@ -0,0 +1,159 @@ +use std::{fs::File, io::Read, path::PathBuf, sync::Arc}; + +use eframe::egui::{TextEdit, Ui}; + +use crate::{ + helpers::{basename, extension, run_on_directory, run_on_file}, + AppState, FileMode, APP_DIRS, +}; + +impl AppState { + pub(crate) fn runner(&mut self, ui: &mut Ui) { + ui.horizontal(|ui| { + self.file_picker(ui); + + let is_running = self.running.load(std::sync::atomic::Ordering::SeqCst); + + if ui.button("Run").clicked() && !is_running { + self.run(); + } + + if is_running { + ui.spinner(); + } + }); + if matches!(self.settings.file_mode, FileMode::Directory) { + ui.horizontal(|ui| { + ui.checkbox(&mut self.settings.do_filter, "Filter by extension"); + ui.add_space(5.0); + ui.add( + TextEdit::singleline(&mut self.settings.filter_by_ext) + .hint_text("enter the extension here") + .interactive(self.settings.do_filter), + ); + }); + } + } + + pub(crate) fn run(&mut self) { + let running = Arc::clone(&self.running); + let output = Arc::clone(&self.output); + let last_verified_code = Arc::clone(&self.last_verified_code); + let last_verified_ext = Arc::clone(&self.last_verified_extension); + let incremental_run = self.settings.incremental_run; + let incremental_file_count = Arc::clone(&self.incremental_file_count); + let cnt = self.files.as_ref().map(|f| f.len()); + let incremental_run_results = Arc::clone(&self.incremental_run_results); + + let settings = self.settings.clone(); + let file_mode = self.settings.file_mode.clone(); + let path = self.path.clone(); + let log = Arc::clone(&self.log); + + _ = std::thread::spawn(move || { + let _path = path.clone(); + let result = std::panic::catch_unwind(|| { + running.store(true, std::sync::atomic::Ordering::SeqCst); + if let Ok(mut output) = output.write() { + *output = None; + } + if let Ok(mut results) = incremental_run_results.write() { + *results = None; + } + let log_dir = APP_DIRS.cache_dir().join("log"); + _ = File::create(log_dir.join("llm.log")).expect("Failed to clean log file"); + match file_mode { + FileMode::SingleFile => { + if let Some(path) = _path { + let extension = extension(&path); + if let Some(path) = path.to_str() { + let py_output = run_on_file(path, &settings); + if let Ok(mut output) = output.write() { + *output = Some(py_output); + } + + let llm_generated_path = + settings.bench_type.llm_generated_path(path); + let llm_code = std::fs::read_to_string(llm_generated_path).ok(); + if let Ok(mut last_verified_code) = last_verified_code.write() { + *last_verified_code = llm_code; + } + + if let Ok(mut last_verified_extension) = last_verified_ext.write() { + *last_verified_extension = Some(String::from(extension)); + } + } + } + } + FileMode::Directory => { + if let Ok(mut last_verified_code) = last_verified_code.write() { + *last_verified_code = None; + } + + if let Ok(mut last_verified_extension) = last_verified_ext.write() { + *last_verified_extension = None; + } + + if let Some(directory) = _path { + if let Some(directory) = directory.to_str() { + let py_output = run_on_directory(directory, &settings); + if let Ok(mut output) = output.write() { + *output = Some(py_output); + } + } + } + } + } + if let Ok(mut log) = log.write() { + if let Ok(mut output) = output.write() { + if let Some((_, stderr)) = output.as_mut() { + if let Some(log) = log.as_ref() { + *stderr += &format!("\nLog:\n{}", log) + } + } + } + *log = None; + } + let p = path.as_ref().map(|p| p.to_string_lossy()); + if let (true, Ok(mut results), Some(path)) = + (incremental_run, incremental_run_results.write(), p) + { + let mut results_contents = String::new(); + let name = basename(&path); + File::open(PathBuf::from("results").join(format!("tries_{name}.json"))) + .expect("results are not where they should be") + .read_to_string(&mut results_contents) + .expect("failed read"); + + *results = Some( + serde_json::from_str(&results_contents) + .expect("results must contain a valid json"), + ); + incremental_file_count.store( + cnt.expect("should be dir"), + std::sync::atomic::Ordering::SeqCst, + ); + } + }); + if let Err(err) = result { + if let Ok(mut output) = output.write() { + *output = Some((String::from("Error"), format!("{:?}", err))); + } + } + running.store(false, std::sync::atomic::Ordering::SeqCst); + }); + + let running = Arc::clone(&self.running); + let log = Arc::clone(&self.log); + _ = std::thread::spawn(move || { + let log_file = APP_DIRS.cache_dir().join("log").join("llm.log"); + while running.load(std::sync::atomic::Ordering::SeqCst) { + let log_output = std::fs::read_to_string(&log_file).unwrap_or_default(); + if let Ok(mut log) = log.write() { + *log = Some(log_output); + } + std::thread::sleep(std::time::Duration::from_millis(100)); + } + }); + } +} diff --git a/gui/src/ui/settings.rs b/gui/src/ui/settings.rs new file mode 100644 index 0000000..ae3a451 --- /dev/null +++ b/gui/src/ui/settings.rs @@ -0,0 +1,87 @@ +use eframe::egui::{self, Ui}; + +use crate::helpers::integer_edit_field; +use crate::{AppState, BenchMode, FileMode, LLMProfile}; + +impl AppState { + pub(crate) fn settings_ui(&mut self, ui: &mut Ui) { + ui.vertical(|ui| { + self.verifier_details(ui); + ui.separator(); + + ui.heading("Settings:"); + + egui::ComboBox::from_label("LLM Profile") + .selected_text(format!("{}", self.settings.llm_profile)) + .show_ui(ui, |ui| { + for profile in LLMProfile::all() { + ui.selectable_value( + &mut self.settings.llm_profile, + profile, + format!("{}", profile), + ); + } + }); + + ui.separator(); + + if ui + .checkbox( + &mut self.settings.incremental_run, + "Incremental run (experimental validating mode)", + ) + .clicked() + && self.settings.incremental_run + { + _ = self.code.take(); + self.settings.file_mode = FileMode::Directory; + } + ui.add_space(2.0); + if !self.settings.incremental_run { + ui.horizontal(|ui| { + ui.label("Bench mode: "); + ui.radio_value( + &mut self.settings.bench_type, + BenchMode::Invariants, + "Invariants", + ); + ui.radio_value(&mut self.settings.bench_type, BenchMode::Generic, "Generic"); + ui.radio_value( + &mut self.settings.bench_type, + BenchMode::Generate, + "Generate", + ); + ui.radio_value( + &mut self.settings.bench_type, + BenchMode::Validating, + "Validating", + ); + }); + } + + ui.separator(); + ui.horizontal(|ui| { + let max_rect = ui.max_rect(); + let is_dir_mode = matches!(self.settings.file_mode, FileMode::Directory); + let div = match (self.settings.incremental_run, is_dir_mode) { + (true, _) => 1.5, + (false, true) => 5.0, + (false, false) => 3.0, + }; + let size = [max_rect.width() / div, max_rect.height()]; + ui.label("Tries: "); + integer_edit_field(ui, "Tries", &mut self.settings.tries, size); + + if !self.settings.incremental_run { + ui.label("Retries: "); + integer_edit_field(ui, "Retries", &mut self.settings.retries, size); + } + + if !self.settings.incremental_run && is_dir_mode { + ui.label("Runs: "); + integer_edit_field(ui, "Retries", &mut self.settings.runs, size); + } + }); + }); + } +} diff --git a/gui/src/ui/token_input.rs b/gui/src/ui/token_input.rs new file mode 100644 index 0000000..06d00df --- /dev/null +++ b/gui/src/ui/token_input.rs @@ -0,0 +1,21 @@ +use eframe::egui::{TextEdit, Ui}; + +use crate::AppState; + +impl AppState { + pub(crate) fn token_input(&mut self, ui: &mut Ui) { + let label = ui.heading("Grazie and verifier: "); + + ui.label("Grazie token: "); + ui.horizontal(|ui| { + let token = ui + .add( + TextEdit::singleline(&mut self.settings.grazie_token) + .hint_text("Enter your Grazie token") + .password(!self.token_hovered), + ) + .labelled_by(label.id); + self.token_hovered = token.hovered(); + }); + } +} diff --git a/gui/src/ui/verifier_details.rs b/gui/src/ui/verifier_details.rs new file mode 100644 index 0000000..492a785 --- /dev/null +++ b/gui/src/ui/verifier_details.rs @@ -0,0 +1,53 @@ +use eframe::egui::{TextEdit, Ui}; + +use crate::AppState; + +impl AppState { + pub(crate) fn verifier_details(&mut self, ui: &mut Ui) { + ui.label("Prompts directory: "); + ui.horizontal(|ui| { + ui.add( + TextEdit::singleline(&mut self.settings.prompts_directory) + .hint_text("Enter the prompts directory"), + ); + if ui.button("Select").clicked() { + if let Some(dir) = rfd::FileDialog::new().pick_folder() { + self.settings.prompts_directory = dir.to_string_lossy().to_string(); + } + } + }); + + ui.columns(2, |cols| { + let [left_ui, right_ui] = cols else { return }; + + left_ui.vertical(|ui| { + ui.label("Verifier command: "); + ui.add( + TextEdit::singleline(&mut self.settings.verifier_command) + .hint_text("Enter the verifier command"), + ); + }); + + right_ui.vertical(|ui| { + ui.label("Timeout: "); + let mut tmp_value = self.settings.timeout.clone(); + ui.add(TextEdit::singleline(&mut tmp_value).hint_text("Enter the timeout")); + if tmp_value.parse::().is_ok() || tmp_value.is_empty() { + self.settings.timeout = tmp_value; + } + }); + }); + + ui.label("Generate code: "); + ui.columns(2, |cols| { + let [left_ui, right_ui] = cols else { return }; + + left_ui.add( + TextEdit::singleline(&mut self.settings.generate_command) + .hint_text("Enter the command to generate code"), + ); + + right_ui.checkbox(&mut self.settings.use_poetry, "Use poetry"); + }); + } +} diff --git a/prompts/dafny_invariants/timeout.txt b/prompts/dafny_invariants/timeout.txt new file mode 100644 index 0000000..f69fd69 --- /dev/null +++ b/prompts/dafny_invariants/timeout.txt @@ -0,0 +1,3 @@ +The verifier timed out during the verification. +This usually means that the provided invariants were too broad or were difficult to check. +Could you please try to improve the invariants and try again? diff --git a/prompts/humaneval-dafny/timeout.txt b/prompts/humaneval-dafny/timeout.txt new file mode 100644 index 0000000..f69fd69 --- /dev/null +++ b/prompts/humaneval-dafny/timeout.txt @@ -0,0 +1,3 @@ +The verifier timed out during the verification. +This usually means that the provided invariants were too broad or were difficult to check. +Could you please try to improve the invariants and try again? diff --git a/run_validating.sh b/run_validating.sh index 3dc2b7f..42be58c 100755 --- a/run_validating.sh +++ b/run_validating.sh @@ -10,6 +10,7 @@ PYLOG_LEVEL=INFO NOFILE=1 poetry run incremental_run \ --llm-profile="anthropic-claude-3.5-sonnet" \ --insert-conditions-mode=llm-single-step \ --tries 10 \ + --bench-type=validating \ --verifier-command="$vcmd" \ --prompts-directory="$prompts_dir" \ --dir="$dir" \ diff --git a/verified_cogen/args.py b/verified_cogen/args.py index deadea7..70da8c8 100644 --- a/verified_cogen/args.py +++ b/verified_cogen/args.py @@ -50,6 +50,7 @@ def get_default_parser(): parser.add_argument( "-s", "--output-style", choices=["stats", "full"], default="full" ) + parser.add_argument("--filter-by-ext", help="filter by extension", default=None) return parser diff --git a/verified_cogen/experiments/incremental_run.py b/verified_cogen/experiments/incremental_run.py index 999dfb5..ad2b2d8 100644 --- a/verified_cogen/experiments/incremental_run.py +++ b/verified_cogen/experiments/incremental_run.py @@ -3,8 +3,8 @@ import json from verified_cogen.llm.llm import LLM -from verified_cogen.args import get_default_parser -from verified_cogen.tools import rename_file +from verified_cogen.args import get_args +from verified_cogen.tools import rename_file, ext_glob, extension_from_file_list from verified_cogen.runners.invariants import InvariantRunner from verified_cogen.runners.languages import register_basic_languages from verified_cogen.runners.languages.language import LanguageDatabase @@ -18,14 +18,11 @@ def main(): register_basic_languages() - parser = get_default_parser() - parser.add_argument("--filter-by-ext", help="filter by extension", default=None) - - args = parser.parse_args() + args = get_args() mode = Mode(args.insert_conditions_mode) assert mode != Mode.REGEX assert args.dir is not None - assert args.bench_type == "invariants" + assert args.bench_type == "validating", args.bench_type assert args.runs == 1 assert args.retries == 0 @@ -39,23 +36,11 @@ def main(): with open(json_results, "r") as f: results = json.load(f) - if args.filter_by_ext is not None: - files = list(directory.glob(f"[!.]*.{args.filter_by_ext}")) - else: - files = list(directory.glob("[!.]*")) + files = list(directory.glob(ext_glob(args.filter_by_ext))) assert len(files) > 0, "No files found in the directory" files.sort() - extension = files[0].suffix[1:] - if ( - different := next((f for f in files if f.suffix[1:] != extension), None) - ) is not None: - logger.error( - f"Found files different extensions: {files[0].name} and {different.name}, please use a single extension" - ) - return - - language = LanguageDatabase().get(extension) + language = LanguageDatabase().get(extension_from_file_list(files)) verifier = Verifier(args.shell, args.verifier_command) for file in files: diff --git a/verified_cogen/main.py b/verified_cogen/main.py index d7b8e64..c97a225 100644 --- a/verified_cogen/main.py +++ b/verified_cogen/main.py @@ -7,15 +7,33 @@ from verified_cogen.runners.generic import GenericRunner from verified_cogen.runners.invariants import InvariantRunner from verified_cogen.runners.languages import register_basic_languages +from verified_cogen.runners.languages.language import LanguageDatabase from verified_cogen.runners.validating import ValidatingRunner -from verified_cogen.tools import pprint_stat, rename_file, tabulate_list +from verified_cogen.tools import ( + ext_glob, + pprint_stat, + rename_file, + tabulate_list, + extension_from_file_list, +) from verified_cogen.tools.modes import Mode from verified_cogen.tools.verifier import Verifier +from pathlib import Path +from typing import Callable +from verified_cogen.runners import Runner +from logging import Logger logger = logging.getLogger(__name__) -def run_once(files, args, runner, verifier, mode, is_once) -> tuple[int, int, int]: +def run_once( + files: list[Path], + args, + runner_cls: Callable[[LLM, Logger, Verifier], Runner], + verifier: Verifier, + mode: Mode, + is_once: bool, +) -> tuple[int, int, int]: success, success_zero_tries, failed = [], [], [] for file in files: @@ -26,12 +44,12 @@ def run_once(files, args, runner, verifier, mode, is_once) -> tuple[int, int, in args.temperature, ) + runner = runner_cls(llm, logger, verifier) + retries = args.retries + 1 tries = None while retries > 0 and tries is None: - tries = runner.run_on_file( - logger, verifier, mode, llm, args.tries, str(file) - ) + tries = runner.run_on_file(mode, args.tries, str(file)) retries -= 1 name = rename_file(file) @@ -66,6 +84,28 @@ def run_once(files, args, runner, verifier, mode, is_once) -> tuple[int, int, in return len(success_zero_tries), len(success), len(failed) +def make_runner_cls( + bench_type: str, extension: str +) -> Callable[[LLM, Logger, Verifier], Runner]: + def runner_cls(llm: LLM, logger: Logger, verifier: Verifier): + match bench_type: + case "invariants": + return InvariantRunner(llm, logger, verifier) + case "generic": + return GenericRunner(llm, logger, verifier) + case "generate": + return GenerateRunner(llm, logger, verifier) + case "validating": + return ValidatingRunner( + InvariantRunner(llm, logger, verifier), + LanguageDatabase().get(extension), + ) + case _: + raise ValueError(f"Unexpected bench_type: {bench_type}") + + return runner_cls + + def main(): register_basic_languages() @@ -81,26 +121,32 @@ def main(): if args.input is None and args.dir is None: args.input = input("Input file: ").strip() - runner = { - "invariants": InvariantRunner, - "generic": GenericRunner, - "generate": GenerateRunner, - "validating": ValidatingRunner, - }[args.bench_type] - verifier = Verifier(args.shell, args.verifier_command, args.verifier_timeout) if args.dir is not None: - files = list(pathlib.Path(args.dir).glob("[!.]*")) + files = sorted(list(pathlib.Path(args.dir).glob(ext_glob(args.filter_by_ext)))) + runner_cls = make_runner_cls(args.bench_type, extension_from_file_list(files)) + runner = runner_cls( + LLM( + args.grazie_token, + args.llm_profile, + args.prompts_directory, + args.temperature, + ), + logger, + verifier, + ) for file in files: with open(file) as f: runner.precheck(f.read(), mode) if args.runs == 1: - run_once(files, args, runner, verifier, mode, is_once=True) + run_once(files, args, runner_cls, verifier, mode, is_once=True) else: success_zero_tries, success, failed = 0, 0, 0 for _ in range(args.runs): - s0, s, f = run_once(files, args, runner, verifier, mode, is_once=False) + s0, s, f = run_once( + files, args, runner_cls, verifier, mode, is_once=False + ) success_zero_tries += s0 success += s failed += f @@ -120,7 +166,10 @@ def main(): args.prompts_directory, args.temperature, ) - tries = runner.run_on_file(logger, verifier, mode, llm, args.tries, args.input) + runner = make_runner_cls(args.bench_type, Path(args.input).suffix[1:])( + llm, logger, verifier + ) + tries = runner.run_on_file(mode, args.tries, args.input) if tries == 0: print("Verified without modification") elif tries is not None: diff --git a/verified_cogen/tools/__init__.py b/verified_cogen/tools/__init__.py index 10a9ef0..3ecf268 100644 --- a/verified_cogen/tools/__init__.py +++ b/verified_cogen/tools/__init__.py @@ -1,5 +1,6 @@ import pathlib import re +from typing import Optional import appdirs @@ -16,6 +17,23 @@ def rename_file(file: pathlib.Path) -> str: return " ".join(file.stem.split("_")).title() +def ext_glob(filter_by_ext: Optional[str]) -> str: + if filter_by_ext is None: + return "[!.]*" + return f"[!.]*.{filter_by_ext}" + + +def extension_from_file_list(files: list[pathlib.Path]) -> str: + extension = files[0].suffix[1:] + if ( + different := next((f for f in files if f.suffix[1:] != extension), None) + ) is not None: + raise ValueError( + f"Found files different extensions: {files[0].name} and {different.name}, please use a single extension" + ) + return extension + + def pprint_stat(name: str, stat: int, total: int, runs=1): print(f"{name}: {stat / runs} ({stat / (total * runs) * 100:.2f}%)") From a1e8a2eb77071fa23b338f3c1c5f3499adecd90a Mon Sep 17 00:00:00 2001 From: AlexShefY Date: Wed, 18 Sep 2024 23:04:51 +0200 Subject: [PATCH 12/23] bench + prompts + results --- .gitmodules | 3 ++ benches/HumanEval-Nagini | 1 + benchesResults/Nagini-Bench/tries_16_09.json | 43 +++++++++++++++++++ prompts/humaneval-nagini/add.txt | 8 ++++ prompts/humaneval-nagini/ask_for_fixed.txt | 6 +++ .../ask_for_fixed_had_errors.txt | 6 +++ prompts/humaneval-nagini/produce.txt | 7 +++ prompts/humaneval-nagini/rewrite.txt | 42 ++++++++++++++++++ prompts/humaneval-nagini/sys.txt | 4 ++ prompts/humaneval-nagini/timeout.txt | 3 ++ 10 files changed, 123 insertions(+) create mode 160000 benches/HumanEval-Nagini create mode 100644 benchesResults/Nagini-Bench/tries_16_09.json create mode 100644 prompts/humaneval-nagini/add.txt create mode 100644 prompts/humaneval-nagini/ask_for_fixed.txt create mode 100644 prompts/humaneval-nagini/ask_for_fixed_had_errors.txt create mode 100644 prompts/humaneval-nagini/produce.txt create mode 100644 prompts/humaneval-nagini/rewrite.txt create mode 100644 prompts/humaneval-nagini/sys.txt create mode 100644 prompts/humaneval-nagini/timeout.txt diff --git a/.gitmodules b/.gitmodules index cb6a2f1..d0350e6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,6 @@ [submodule "benches/HumanEval-Dafny"] path = benches/HumanEval-Dafny url = https://github.com/JetBrains-Research/HumanEval-Dafny +[submodule "benches/HumanEval-Nagini"] + path = benches/HumanEval-Nagini + url = https://github.com/JetBrains-Research/HumanEval-Nagini diff --git a/benches/HumanEval-Nagini b/benches/HumanEval-Nagini new file mode 160000 index 0000000..35d7203 --- /dev/null +++ b/benches/HumanEval-Nagini @@ -0,0 +1 @@ +Subproject commit 35d7203b4378359559f1f505b484962a33476ddd diff --git a/benchesResults/Nagini-Bench/tries_16_09.json b/benchesResults/Nagini-Bench/tries_16_09.json new file mode 100644 index 0000000..ed720cb --- /dev/null +++ b/benchesResults/Nagini-Bench/tries_16_09.json @@ -0,0 +1,43 @@ +{ + "005-intersperse.py": 4, + "009-rolling-max.py": 3, + "011-string_xor.py": 2, + "016-count_distinct_characters.py": 2, + "023-strlen.py": 0, + "024-largest-divisor.py": 2, + "027-flip_case.py": 3, + "029-filter_by_prefix.py": 3, + "035-max-element.py": 4, + "041-car_race_collision.py": 0, + "042-incr-list.py": 2, + "046-fib4.py": 3, + "050-encode_shift.py": 2, + "052-below-threshold.py": 2, + "053-add.py": 0, + "054-same-chars.py": 0, + "055-fib.py": 2, + "059-largest-prime-factor.py": 2, + "060-sum-to-n.py": 5, + "062-derivative.py": 2, + "063-fibfib.py": 4, + "066-digitSum.py": 4, + "082-prime-length.py": 2, + "083-starts_one_ends.py": 0, + "084-solve.py": 2, + "085-add.py": 2, + "092-any_int.py": 0, + "093-encode.py": 2, + "097-multiply.py": 0, + "098-count_upper.py": 3, + "100-make_a_pile.py": 3, + "110-exchange.py": 0, + "121-solution.py": 2, + "127-intersection.py": 0, + "134-check_if_last_char_is_a_letter.py": 0, + "138_is_equal_to_sum_even.py": 0, + "139-special_factorial.py": 3, + "146_specialFilter.py": 5, + "150-x_or_y.py": 4, + "157-right_angle_triangle.py": 0, + "159-eat.py": 0 +} \ No newline at end of file diff --git a/prompts/humaneval-nagini/add.txt b/prompts/humaneval-nagini/add.txt new file mode 100644 index 0000000..7cf6f4b --- /dev/null +++ b/prompts/humaneval-nagini/add.txt @@ -0,0 +1,8 @@ +Given the following Python program, and a set of Nagini invariants, output the program with invariants inserted into the correct place. +Don't add any additional text comments, your response must contain only program with invariants. +Do not provide ANY explanations. Don't include markdown backticks. Respond only in Python code, nothing else. +The program: +{program} +– +The invariants: +{checks} \ No newline at end of file diff --git a/prompts/humaneval-nagini/ask_for_fixed.txt b/prompts/humaneval-nagini/ask_for_fixed.txt new file mode 100644 index 0000000..38f5c7b --- /dev/null +++ b/prompts/humaneval-nagini/ask_for_fixed.txt @@ -0,0 +1,6 @@ +The following errors occurred during verification: +{error} + +Please fix the error by adding, removing or modifying the invariants and return the fixed program. +Don't add any additional text comments, your response must contain only program with invariants. +Do not provide ANY explanations. Don't include markdown backticks. Respond only in Python code, nothing else. \ No newline at end of file diff --git a/prompts/humaneval-nagini/ask_for_fixed_had_errors.txt b/prompts/humaneval-nagini/ask_for_fixed_had_errors.txt new file mode 100644 index 0000000..9e6f1ab --- /dev/null +++ b/prompts/humaneval-nagini/ask_for_fixed_had_errors.txt @@ -0,0 +1,6 @@ +There are still some errors: +{error} + +Could you please fix them? +Don't add any additional text comments, your response must contain only program with invariants. +Do not provide ANY explanations. Don't include markdown backticks. Respond only in Python code, nothing else. \ No newline at end of file diff --git a/prompts/humaneval-nagini/produce.txt b/prompts/humaneval-nagini/produce.txt new file mode 100644 index 0000000..284edfc --- /dev/null +++ b/prompts/humaneval-nagini/produce.txt @@ -0,0 +1,7 @@ +Given the following Python program, output Nagini invariants that should go into the `while` loop. +Ensure that the invariants are as comprehensive as they can be. +Even if you think some invariant is not totally necessary, better add it than not. +Don't add any additional text comments, your response must contain only program with invariants. +Do not provide ANY explanations. Don't include markdown backticks. Respond only in Python code, nothing else. +The program: +{program} \ No newline at end of file diff --git a/prompts/humaneval-nagini/rewrite.txt b/prompts/humaneval-nagini/rewrite.txt new file mode 100644 index 0000000..61be8aa --- /dev/null +++ b/prompts/humaneval-nagini/rewrite.txt @@ -0,0 +1,42 @@ +Rewrite the following Python program, adding correct Nagini invariants into `while` loops. +Do not change the code, only add the invariants. +Ensure that the invariants are as comprehensive as they can be. +Even if you think some invariant is not totally necessary, better add it than not. +Don't add any additional text comments, your response must contain only program with invariants. +Do not provide ANY explanations. Don't include markdown backticks. Respond only in Python code, nothing else. +Also add assertions in necessary places. +Do not change the code, only add invariants and assertions. Don't remove any helper functions, they are there to help you. +You might need to work with accumulating functions, such as sum, so here's an example of how to do that: +``` +from typing import cast, List, Dict, Set, Optional, Union +from nagini_contracts.contracts import * + +@Pure +def Sum(a : List[int], s : int, t : int) -> int : + Requires(Acc(list_pred(a))) + Requires(((0) <= (s)) and ((s) <= (t)) and ((t) <= (len(a)))) + + if s == t: + return 0 + else: + return (a)[t - 1] + (Sum(a, s, t - 1)) + +def sum_loop(numbers: List[int]) -> int: + Requires(Acc(list_pred(numbers))) + Ensures(Acc(list_pred(numbers))) + Ensures(Result() == Sum(numbers, 0, len(numbers))) + s = int(0) + i = int(0) + while (i) < (len(numbers)): + Invariant(Acc(list_pred(numbers))) + Invariant(0 <= i and i <= len(numbers)) + Invariant(Forall(int, lambda d_1_p_: + (Implies(0 <= d_1_p_ and d_1_p_ < len(numbers), Sum(numbers, 0, d_1_p_ + 1) == Sum(numbers, 0, d_1_p_) + numbers[d_1_p_]), [[Sum(numbers, 0, d_1_p_ + 1)]]))) + Invariant(s == Sum(numbers, 0, i)) + Assert(Sum(numbers, 0, i + 1) == Sum(numbers, 0, i) + numbers[i]) + s = s + (numbers)[i] + i = i + 1 + return s +``` +The program: +{program} diff --git a/prompts/humaneval-nagini/sys.txt b/prompts/humaneval-nagini/sys.txt new file mode 100644 index 0000000..e9979b1 --- /dev/null +++ b/prompts/humaneval-nagini/sys.txt @@ -0,0 +1,4 @@ +You are an expert in a Python verification framework Nagini. +You will be given tasks dealing with Python programs including precise docstrings and specifications. +Do not provide ANY explanations. Don't include markdown backticks. Respond only in Python code, nothing else. +Take into account that arrays inside the invariants are indexed by type `int`. \ No newline at end of file diff --git a/prompts/humaneval-nagini/timeout.txt b/prompts/humaneval-nagini/timeout.txt new file mode 100644 index 0000000..1c50276 --- /dev/null +++ b/prompts/humaneval-nagini/timeout.txt @@ -0,0 +1,3 @@ +The verifier timed out during the verification. +This usually means that the provided invariants were too broad or were difficult to check. +Could you please try to improve the invariants and try again? \ No newline at end of file From e7da184f85a41f0d38774d0a95f59e069ffa9dd1 Mon Sep 17 00:00:00 2001 From: AlexShefY Date: Thu, 19 Sep 2024 00:24:16 +0200 Subject: [PATCH 13/23] smth --- verified_cogen/experiments/incremental_run.py | 7 +++++++ verified_cogen/runners/languages/dafny.py | 1 + verified_cogen/runners/languages/language.py | 3 +++ verified_cogen/runners/languages/nagini.py | 1 + verified_cogen/runners/validating.py | 2 +- 5 files changed, 13 insertions(+), 1 deletion(-) diff --git a/verified_cogen/experiments/incremental_run.py b/verified_cogen/experiments/incremental_run.py index 41c4fe4..2b8fb36 100644 --- a/verified_cogen/experiments/incremental_run.py +++ b/verified_cogen/experiments/incremental_run.py @@ -12,7 +12,14 @@ from verified_cogen.tools.modes import Mode from verified_cogen.tools.verifier import Verifier +import sys + logger = logging.getLogger(__name__) +handler = logging.StreamHandler(sys.stdout) + +formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') +handler.setFormatter(formatter) +logger.addHandler(handler) def main(): diff --git a/verified_cogen/runners/languages/dafny.py b/verified_cogen/runners/languages/dafny.py index b9c12e8..cca0aaa 100644 --- a/verified_cogen/runners/languages/dafny.py +++ b/verified_cogen/runners/languages/dafny.py @@ -23,4 +23,5 @@ def __init__(self): r" *// invariants-start.*?// invariants-end\n", ], "// assert-line", + "//", ) diff --git a/verified_cogen/runners/languages/language.py b/verified_cogen/runners/languages/language.py index 72be824..2b9cb81 100644 --- a/verified_cogen/runners/languages/language.py +++ b/verified_cogen/runners/languages/language.py @@ -5,6 +5,7 @@ class Language: _instance = None + simple_comment = None def __new__(cls, *args, **kwargs): if not isinstance(cls._instance, cls): @@ -33,7 +34,9 @@ def __init__( validator_template: str, assert_invariants_pattern: list[str], inline_assert_comment: str, + simple_comment: str, ): + self.simple_comment = simple_comment self.method_regex = method_regex self.validator_template = validator_template self.assert_invariant_patterns = assert_invariants_pattern diff --git a/verified_cogen/runners/languages/nagini.py b/verified_cogen/runners/languages/nagini.py index 0a76df9..559ec72 100644 --- a/verified_cogen/runners/languages/nagini.py +++ b/verified_cogen/runners/languages/nagini.py @@ -25,4 +25,5 @@ def __init__(self): r" *# invariants-start.*?# invariants-end\n?", ], "# assert-line", + "#", ) diff --git a/verified_cogen/runners/validating.py b/verified_cogen/runners/validating.py index 88f8c74..6296100 100644 --- a/verified_cogen/runners/validating.py +++ b/verified_cogen/runners/validating.py @@ -16,7 +16,7 @@ def __init__(self, wrapping: Runner, language: Language): def _add_validators(self, prg: str, inv_prg: str): validators = self.language.generate_validators(prg) - val_prg = inv_prg + "\n// ==== verifiers ==== //\n" + validators + val_prg = inv_prg + "\n" + self.language.simple_comment + " ==== verifiers ==== \n" + validators return val_prg def preprocess(self, prg: str, mode: Mode) -> str: From 10e97ffc5239cf4634e3e7e5dc950be9df0bdf44 Mon Sep 17 00:00:00 2001 From: AlexShefY Date: Thu, 19 Sep 2024 09:32:40 +0200 Subject: [PATCH 14/23] fix parsing --- .gitmodules | 1 + tests/test_nagini.py | 16 +++++++++++++++- verified_cogen/runners/languages/language.py | 1 - verified_cogen/runners/languages/nagini.py | 2 +- 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index d0350e6..e049f86 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,6 +5,7 @@ [submodule "benches/HumanEval-Dafny"] path = benches/HumanEval-Dafny url = https://github.com/JetBrains-Research/HumanEval-Dafny + [submodule "benches/HumanEval-Nagini"] path = benches/HumanEval-Nagini url = https://github.com/JetBrains-Research/HumanEval-Nagini diff --git a/tests/test_nagini.py b/tests/test_nagini.py index 1e994a1..0679ac8 100644 --- a/tests/test_nagini.py +++ b/tests/test_nagini.py @@ -11,8 +11,10 @@ def test_nagini_generate(): def main(value: int) -> int: Requires(value >= 10) Ensures(Result() >= 20) + # impl-start Assert(value * 2 >= 20) # assert-line - return value * 2""" + return value * 2 + # impl-end""" ) assert nagini_lang.generate_validators(code) == dedent( """\ @@ -43,8 +45,12 @@ def main(value: int) -> int: assert nagini_lang.generate_validators(code) == dedent( """\ def main_valid(value: int) -> int: + # pre-conditions-start Requires(value >= 10) + # pre-conditions-end + # post-conditions-start Ensures(Result() >= 20) + # post-conditions-end ret = main(value) return ret""" ) @@ -247,17 +253,23 @@ def alpha_valid(c : int) -> bool : ret = alpha(c) return ret def flip__char_valid(c : int) -> int : + # pre-conditions-start Ensures(lower(c) == upper(Result())) Ensures(upper(c) == lower(Result())) + # pre-conditions-end ret = flip__char(c) return ret def flip__case_valid(s : List[int]) -> List[int] : + # pre-conditions-start Requires(Acc(list_pred(s))) + # pre-conditions-end + # post-conditions-start Ensures(Acc(list_pred(s))) Ensures(Acc(list_pred(Result()))) Ensures((len(Result())) == (len(s))) Ensures(Forall(int, lambda d_0_i_: (Implies(((0) <= (d_0_i_)) and ((d_0_i_) < (len(s))), lower((s)[d_0_i_]) == upper((Result())[d_0_i_]))))) Ensures(Forall(int, lambda d_0_i_: (Implies(((0) <= (d_0_i_)) and ((d_0_i_) < (len(s))), upper((s)[d_0_i_]) == lower((Result())[d_0_i_]))))) + # post-conditions-end ret = flip__case(s) return ret""" ) @@ -287,8 +299,10 @@ def flip__char(c : int) -> int : assert nagini_lang.generate_validators(code) == dedent( """\ def flip__char_valid(c : int) -> int : + # pre-conditions-start Ensures(lower(c) == upper(Result())) Ensures(upper(c) == lower(Result())) + # pre-conditions-end ret = flip__char(c) return ret""" ) diff --git a/verified_cogen/runners/languages/language.py b/verified_cogen/runners/languages/language.py index 2b9cb81..6e9d6db 100644 --- a/verified_cogen/runners/languages/language.py +++ b/verified_cogen/runners/languages/language.py @@ -43,7 +43,6 @@ def __init__( self.inline_assert_comment = inline_assert_comment def generate_validators(self, code: str) -> str: - code = re.sub(r"^ *#.*(\r\n|\r|\n)?", "", code, flags=re.MULTILINE) methods = self.method_regex.finditer(code) validators = [] diff --git a/verified_cogen/runners/languages/nagini.py b/verified_cogen/runners/languages/nagini.py index 559ec72..044d7e8 100644 --- a/verified_cogen/runners/languages/nagini.py +++ b/verified_cogen/runners/languages/nagini.py @@ -16,7 +16,7 @@ class NaginiLanguage(GenericLanguage): def __init__(self): super().__init__( re.compile( - r"def\s+(\w+)\s*\((.*?)\)\s*->\s*(.*?):(:?(?:\r\n|\r|\n)?( *(?:Requires|Ensures)\([^\r\n]*\)(?:\r\n|\r|\n)?)*)", + r"def\s+(\w+)\s*\((.*?)\)\s*->\s*(.*?):(.*?(\r\n|\r|\n))\s+# impl-start", re.DOTALL, ), NAGINI_VALIDATOR_TEMPLATE, From 8dc4bb71737715f86a4bbe77b82493e96f977fb1 Mon Sep 17 00:00:00 2001 From: AlexShefY Date: Thu, 19 Sep 2024 09:52:27 +0200 Subject: [PATCH 15/23] reformatting + optional output logging --- verified_cogen/args.py | 3 +++ verified_cogen/experiments/incremental_run.py | 16 ++++++++++------ verified_cogen/runners/validating.py | 3 ++- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/verified_cogen/args.py b/verified_cogen/args.py index 29d57b9..58e35ab 100644 --- a/verified_cogen/args.py +++ b/verified_cogen/args.py @@ -54,6 +54,9 @@ def get_default_parser(): parser.add_argument( "--log-tries", help="Save output of every try to given dir", default=None ) + parser.add_argument( + "--output-logging", help="Print logs to standard output", default=False + ) return parser diff --git a/verified_cogen/experiments/incremental_run.py b/verified_cogen/experiments/incremental_run.py index 2b8fb36..5d6fd2c 100644 --- a/verified_cogen/experiments/incremental_run.py +++ b/verified_cogen/experiments/incremental_run.py @@ -1,5 +1,6 @@ import logging import pathlib +import sys import json from verified_cogen.llm.llm import LLM @@ -12,14 +13,14 @@ from verified_cogen.tools.modes import Mode from verified_cogen.tools.verifier import Verifier -import sys - logger = logging.getLogger(__name__) -handler = logging.StreamHandler(sys.stdout) -formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') -handler.setFormatter(formatter) -logger.addHandler(handler) + +def register_output_handler(): + handler = logging.StreamHandler(sys.stdout) + formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s") + handler.setFormatter(formatter) + logger.addHandler(handler) def main(): @@ -33,6 +34,9 @@ def main(): assert args.runs == 1 assert args.retries == 0 + if args.output_logging: + register_output_handler() + directory = pathlib.Path(args.dir) log_tries = pathlib.Path(args.log_tries) if args.log_tries is not None else None results_directory = pathlib.Path("results") diff --git a/verified_cogen/runners/validating.py b/verified_cogen/runners/validating.py index 6296100..fe8d8f4 100644 --- a/verified_cogen/runners/validating.py +++ b/verified_cogen/runners/validating.py @@ -16,7 +16,8 @@ def __init__(self, wrapping: Runner, language: Language): def _add_validators(self, prg: str, inv_prg: str): validators = self.language.generate_validators(prg) - val_prg = inv_prg + "\n" + self.language.simple_comment + " ==== verifiers ==== \n" + validators + comment = self.language.simple_comment + val_prg = inv_prg + "\n" + comment + " ==== verifiers ==== \n" + validators return val_prg def preprocess(self, prg: str, mode: Mode) -> str: From ecdb6bea0dab8c1c9b09b7bc06351924d8e1e7f5 Mon Sep 17 00:00:00 2001 From: AlexShefY Date: Thu, 19 Sep 2024 10:01:18 +0200 Subject: [PATCH 16/23] reformatting --- verified_cogen/runners/languages/language.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/verified_cogen/runners/languages/language.py b/verified_cogen/runners/languages/language.py index 6e9d6db..ed52378 100644 --- a/verified_cogen/runners/languages/language.py +++ b/verified_cogen/runners/languages/language.py @@ -1,11 +1,10 @@ from abc import abstractmethod from typing import Pattern -import re class Language: _instance = None - simple_comment = None + simple_comment: str def __new__(cls, *args, **kwargs): if not isinstance(cls._instance, cls): From a07712c0544050b07285c42fb36ce73308fdc367 Mon Sep 17 00:00:00 2001 From: AlexShefY Date: Sun, 22 Sep 2024 10:24:43 +0200 Subject: [PATCH 17/23] changes in gitignore --- .gitignore | 2 + benchesResults/Nagini-Bench/tries_16_09.json | 43 -------------------- verified_cogen/tools/verifier.py | 23 +++++++---- 3 files changed, 17 insertions(+), 51 deletions(-) delete mode 100644 benchesResults/Nagini-Bench/tries_16_09.json diff --git a/.gitignore b/.gitignore index 908fcb0..e359ec8 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,5 @@ run_nagini.py /tmp results results/* +/log_tries/ +/log_tries/* diff --git a/benchesResults/Nagini-Bench/tries_16_09.json b/benchesResults/Nagini-Bench/tries_16_09.json deleted file mode 100644 index ed720cb..0000000 --- a/benchesResults/Nagini-Bench/tries_16_09.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "005-intersperse.py": 4, - "009-rolling-max.py": 3, - "011-string_xor.py": 2, - "016-count_distinct_characters.py": 2, - "023-strlen.py": 0, - "024-largest-divisor.py": 2, - "027-flip_case.py": 3, - "029-filter_by_prefix.py": 3, - "035-max-element.py": 4, - "041-car_race_collision.py": 0, - "042-incr-list.py": 2, - "046-fib4.py": 3, - "050-encode_shift.py": 2, - "052-below-threshold.py": 2, - "053-add.py": 0, - "054-same-chars.py": 0, - "055-fib.py": 2, - "059-largest-prime-factor.py": 2, - "060-sum-to-n.py": 5, - "062-derivative.py": 2, - "063-fibfib.py": 4, - "066-digitSum.py": 4, - "082-prime-length.py": 2, - "083-starts_one_ends.py": 0, - "084-solve.py": 2, - "085-add.py": 2, - "092-any_int.py": 0, - "093-encode.py": 2, - "097-multiply.py": 0, - "098-count_upper.py": 3, - "100-make_a_pile.py": 3, - "110-exchange.py": 0, - "121-solution.py": 2, - "127-intersection.py": 0, - "134-check_if_last_char_is_a_letter.py": 0, - "138_is_equal_to_sum_even.py": 0, - "139-special_factorial.py": 3, - "146_specialFilter.py": 5, - "150-x_or_y.py": 4, - "157-right_angle_triangle.py": 0, - "159-eat.py": 0 -} \ No newline at end of file diff --git a/verified_cogen/tools/verifier.py b/verified_cogen/tools/verifier.py index 274a14b..b11aa5a 100644 --- a/verified_cogen/tools/verifier.py +++ b/verified_cogen/tools/verifier.py @@ -15,13 +15,20 @@ def __init__(self, shell: str, verifier_cmd: str, timeout: int = 60): self.timeout = timeout def verify(self, file_path: Path) -> Optional[tuple[bool, str, str]]: - proc = subprocess.Popen( - [self.shell, "-i", "-l", "-c", f'{self.verifier_cmd} "{file_path}"'], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) try: - out, err = proc.communicate(timeout=self.timeout) - return proc.returncode == 0, out.decode(), err.decode() + res = subprocess.run( + '{} -i -l -c "{} "{}""; exit'.format( + self.shell, self.verifier_cmd, file_path + ), + capture_output=True, + shell=True, + timeout=self.timeout, + ) except subprocess.TimeoutExpired: - os.killpg(os.getpgid(proc.pid), signal.SIGTERM) + os.system("killall z3") + return None + return ( + res.returncode == 0, + res.stdout.decode("utf-8"), + res.stderr.decode("utf-8"), + ) From 77e68d534b19226c1720ede9812b056863f76bac Mon Sep 17 00:00:00 2001 From: AlexShefY Date: Sun, 22 Sep 2024 10:26:13 +0200 Subject: [PATCH 18/23] change logs --- verified_cogen/experiments/incremental_run.py | 3 ++- verified_cogen/runners/validating.py | 10 ++++++++-- verified_cogen/tools/verifier.py | 1 - 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/verified_cogen/experiments/incremental_run.py b/verified_cogen/experiments/incremental_run.py index 5d6fd2c..dcdfb73 100644 --- a/verified_cogen/experiments/incremental_run.py +++ b/verified_cogen/experiments/incremental_run.py @@ -63,8 +63,9 @@ def main(): args.temperature, ) runner = ValidatingRunner( - wrapping=InvariantRunner(llm, logger, verifier, log_tries), + wrapping=InvariantRunner(llm, logger, verifier), language=language, + log_tries=log_tries, ) display_name = rename_file(file) marker_name = str(file.relative_to(directory)) diff --git a/verified_cogen/runners/validating.py b/verified_cogen/runners/validating.py index fe8d8f4..28f6d02 100644 --- a/verified_cogen/runners/validating.py +++ b/verified_cogen/runners/validating.py @@ -1,3 +1,4 @@ +import pathlib from typing import Optional from verified_cogen.runners import Runner from verified_cogen.runners.languages.language import Language @@ -9,8 +10,13 @@ class ValidatingRunner(Runner): language: Language prg: Optional[str] = None - def __init__(self, wrapping: Runner, language: Language): - super().__init__(wrapping.llm, wrapping.logger, wrapping.verifier) + def __init__( + self, + wrapping: Runner, + language: Language, + log_tries: Optional[pathlib.Path] = None, + ): + super().__init__(wrapping.llm, wrapping.logger, wrapping.verifier, log_tries) self.wrapped_runner = wrapping self.language = language diff --git a/verified_cogen/tools/verifier.py b/verified_cogen/tools/verifier.py index b11aa5a..d3b0002 100644 --- a/verified_cogen/tools/verifier.py +++ b/verified_cogen/tools/verifier.py @@ -1,6 +1,5 @@ import logging import os -import signal import subprocess from pathlib import Path from typing import Optional From 1d892b83e4e95b1114c9e56cb9c500c799ef832c Mon Sep 17 00:00:00 2001 From: AlexShefY Date: Sun, 22 Sep 2024 11:06:51 +0200 Subject: [PATCH 19/23] fix output logging --- verified_cogen/args.py | 1 + 1 file changed, 1 insertion(+) diff --git a/verified_cogen/args.py b/verified_cogen/args.py index a3ec771..f692683 100644 --- a/verified_cogen/args.py +++ b/verified_cogen/args.py @@ -26,6 +26,7 @@ class ProgramArgs: @no_type_check def __init__(self, args): + self.output_logging = args.output_logging self.input = args.input self.dir = args.dir self.runs = args.runs From e9ac8566458a0b28930584bf905ba1c5854da6dd Mon Sep 17 00:00:00 2001 From: AlexShefY Date: Sun, 22 Sep 2024 11:09:12 +0200 Subject: [PATCH 20/23] fix args --- verified_cogen/args.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/verified_cogen/args.py b/verified_cogen/args.py index f692683..22a604c 100644 --- a/verified_cogen/args.py +++ b/verified_cogen/args.py @@ -23,10 +23,10 @@ class ProgramArgs: output_style: str filter_by_ext: Optional[str] log_tries: Optional[str] + output_logging: bool @no_type_check def __init__(self, args): - self.output_logging = args.output_logging self.input = args.input self.dir = args.dir self.runs = args.runs @@ -44,6 +44,7 @@ def __init__(self, args): self.output_style = args.output_style self.filter_by_ext = args.filter_by_ext self.log_tries = args.log_tries + self.output_logging = args.output_logging def get_default_parser(): From 2aebc92e77a4ade8b0586522ff3f8487fc979925 Mon Sep 17 00:00:00 2001 From: WeetHet Date: Wed, 25 Sep 2024 11:52:05 +0300 Subject: [PATCH 21/23] add humaneval-rustbench --- .gitignore | 2 + .../000-has_close_elements.rs | 59 ++++ .../001-separate-paren-groups.rs | 155 ++++++++ .../004-mean_absolute_derivation.rs | 332 ++++++++++++++++++ .../HumanEval-RustBench/005-intersperse.rs | 105 ++++++ .../007-filter_by_substring.rs | 92 +++++ .../HumanEval-RustBench/008-sum_product.rs | 55 +++ .../HumanEval-RustBench/009-rolling_max.rs | 41 +++ benches/HumanEval-RustBench/011-string_xor.rs | 48 +++ benches/HumanEval-RustBench/012-longest.rs | 42 +++ .../HumanEval-RustBench/014-all_prefixes.rs | 54 +++ benches/HumanEval-RustBench/023-strlen.rs | 14 + .../024-largest-divisor.rs | 85 +++++ .../HumanEval-RustBench/030-get-positive.rs | 29 ++ benches/HumanEval-RustBench/033-sort_third.rs | 120 +++++++ benches/HumanEval-RustBench/034-unique.rs | 183 ++++++++++ .../HumanEval-RustBench/035-max-element.rs | 26 ++ benches/HumanEval-RustBench/037-sort_even.rs | 146 ++++++++ benches/HumanEval-RustBench/042-incr-list.rs | 26 ++ .../043-pairs-sum-to-zero.rs | 41 +++ .../HumanEval-RustBench/045-triangle_area.rs | 24 ++ .../HumanEval-RustBench/048-is-palindrome.rs | 24 ++ benches/HumanEval-RustBench/049-modp.rs | 44 +++ .../HumanEval-RustBench/050-encode_shift.rs | 97 +++++ .../052-below-threshold.rs | 21 ++ benches/HumanEval-RustBench/053-add.rs | 13 + benches/HumanEval-RustBench/054-same-chars.rs | 89 +++++ benches/HumanEval-RustBench/057-monotonic.rs | 37 ++ .../059-largest-prime-factor.rs | 62 ++++ benches/HumanEval-RustBench/060-sum_to_n.rs | 35 ++ benches/HumanEval-RustBench/062-derivative.rs | 35 ++ benches/HumanEval-RustBench/063-fibfib.rs | 32 ++ .../HumanEval-RustBench/064-vowel_count.rs | 57 +++ benches/HumanEval-RustBench/068-pluck.rs | 55 +++ .../070-strange_sort_list.rs | 157 +++++++++ .../HumanEval-RustBench/072-will_it_fly.rs | 124 +++++++ .../073-smallest_change.rs | 50 +++ .../HumanEval-RustBench/074-total_match.rs | 87 +++++ .../075-is_multiply_prime.rs | 121 +++++++ .../076-is_simple_power.rs | 37 ++ benches/HumanEval-RustBench/077-is_cube.rs | 131 +++++++ benches/HumanEval-RustBench/080-is_happy.rs | 45 +++ .../134-check_if_last_char_is_a_letter.rs | 40 +++ .../136-largest_smallest_integers.rs | 46 +++ benches/HumanEval-RustBench/abs.rs | 26 ++ .../HumanEval-RustBench/arithmetic_weird.rs | 29 ++ benches/HumanEval-RustBench/array_append.rs | 33 ++ benches/HumanEval-RustBench/array_concat.rs | 47 +++ benches/HumanEval-RustBench/array_copy.rs | 32 ++ benches/HumanEval-RustBench/array_product.rs | 36 ++ benches/HumanEval-RustBench/barrier.rs | 53 +++ benches/HumanEval-RustBench/binary_search.rs | 44 +++ .../binary_search_recursive.rs | 46 +++ benches/HumanEval-RustBench/cubes.rs | 52 +++ .../HumanEval-RustBench/has_close_elements.rs | 65 ++++ .../has_only_one_distinct_element.rs | 39 ++ .../index_wise_addition.rs | 62 ++++ .../integer_square_root.rs | 49 +++ benches/HumanEval-RustBench/intersperse.rs | 38 ++ benches/HumanEval-RustBench/is_non_prime.rs | 35 ++ benches/HumanEval-RustBench/is_sorted.rs | 39 ++ .../largest_prime_factor.rs | 66 ++++ benches/HumanEval-RustBench/last_position.rs | 38 ++ benches/HumanEval-RustBench/max_array.rs | 38 ++ benches/HumanEval-RustBench/max_dafny_lsp.rs | 48 +++ .../HumanEval-RustBench/remove_duplicates.rs | 66 ++++ benches/HumanEval-RustBench/remove_element.rs | 50 +++ .../HumanEval-RustBench/remove_elements.rs | 62 ++++ benches/HumanEval-RustBench/replace.rs | 35 ++ benches/HumanEval-RustBench/replace_chars.rs | 31 ++ benches/HumanEval-RustBench/reverse.rs | 31 ++ benches/HumanEval-RustBench/rolling_max.rs | 50 +++ .../smallest_list_length.rs | 38 ++ .../smallest_missing_number.rs | 46 +++ benches/HumanEval-RustBench/string_xor.rs | 40 +++ benches/HumanEval-RustBench/two_sum.rs | 57 +++ benches/HumanEval-RustBench/two_way_sort.rs | 67 ++++ benches/HumanEval-RustBench/unique.rs | 43 +++ benches/HumanEval-RustBench/unique_better.rs | 46 +++ flake.nix | 15 +- scripts/process_files.fish | 5 + scripts/process_verus_task.py | 46 +++ .../run_validating.sh | 0 .../run_with_houdini.sh | 0 84 files changed, 4756 insertions(+), 5 deletions(-) create mode 100644 benches/HumanEval-RustBench/000-has_close_elements.rs create mode 100644 benches/HumanEval-RustBench/001-separate-paren-groups.rs create mode 100644 benches/HumanEval-RustBench/004-mean_absolute_derivation.rs create mode 100644 benches/HumanEval-RustBench/005-intersperse.rs create mode 100644 benches/HumanEval-RustBench/007-filter_by_substring.rs create mode 100644 benches/HumanEval-RustBench/008-sum_product.rs create mode 100644 benches/HumanEval-RustBench/009-rolling_max.rs create mode 100644 benches/HumanEval-RustBench/011-string_xor.rs create mode 100644 benches/HumanEval-RustBench/012-longest.rs create mode 100644 benches/HumanEval-RustBench/014-all_prefixes.rs create mode 100644 benches/HumanEval-RustBench/023-strlen.rs create mode 100644 benches/HumanEval-RustBench/024-largest-divisor.rs create mode 100644 benches/HumanEval-RustBench/030-get-positive.rs create mode 100644 benches/HumanEval-RustBench/033-sort_third.rs create mode 100644 benches/HumanEval-RustBench/034-unique.rs create mode 100644 benches/HumanEval-RustBench/035-max-element.rs create mode 100644 benches/HumanEval-RustBench/037-sort_even.rs create mode 100644 benches/HumanEval-RustBench/042-incr-list.rs create mode 100644 benches/HumanEval-RustBench/043-pairs-sum-to-zero.rs create mode 100644 benches/HumanEval-RustBench/045-triangle_area.rs create mode 100644 benches/HumanEval-RustBench/048-is-palindrome.rs create mode 100644 benches/HumanEval-RustBench/049-modp.rs create mode 100644 benches/HumanEval-RustBench/050-encode_shift.rs create mode 100644 benches/HumanEval-RustBench/052-below-threshold.rs create mode 100644 benches/HumanEval-RustBench/053-add.rs create mode 100644 benches/HumanEval-RustBench/054-same-chars.rs create mode 100644 benches/HumanEval-RustBench/057-monotonic.rs create mode 100644 benches/HumanEval-RustBench/059-largest-prime-factor.rs create mode 100644 benches/HumanEval-RustBench/060-sum_to_n.rs create mode 100644 benches/HumanEval-RustBench/062-derivative.rs create mode 100644 benches/HumanEval-RustBench/063-fibfib.rs create mode 100644 benches/HumanEval-RustBench/064-vowel_count.rs create mode 100644 benches/HumanEval-RustBench/068-pluck.rs create mode 100644 benches/HumanEval-RustBench/070-strange_sort_list.rs create mode 100644 benches/HumanEval-RustBench/072-will_it_fly.rs create mode 100644 benches/HumanEval-RustBench/073-smallest_change.rs create mode 100644 benches/HumanEval-RustBench/074-total_match.rs create mode 100644 benches/HumanEval-RustBench/075-is_multiply_prime.rs create mode 100644 benches/HumanEval-RustBench/076-is_simple_power.rs create mode 100644 benches/HumanEval-RustBench/077-is_cube.rs create mode 100644 benches/HumanEval-RustBench/080-is_happy.rs create mode 100644 benches/HumanEval-RustBench/134-check_if_last_char_is_a_letter.rs create mode 100644 benches/HumanEval-RustBench/136-largest_smallest_integers.rs create mode 100644 benches/HumanEval-RustBench/abs.rs create mode 100644 benches/HumanEval-RustBench/arithmetic_weird.rs create mode 100644 benches/HumanEval-RustBench/array_append.rs create mode 100644 benches/HumanEval-RustBench/array_concat.rs create mode 100644 benches/HumanEval-RustBench/array_copy.rs create mode 100644 benches/HumanEval-RustBench/array_product.rs create mode 100644 benches/HumanEval-RustBench/barrier.rs create mode 100644 benches/HumanEval-RustBench/binary_search.rs create mode 100644 benches/HumanEval-RustBench/binary_search_recursive.rs create mode 100644 benches/HumanEval-RustBench/cubes.rs create mode 100644 benches/HumanEval-RustBench/has_close_elements.rs create mode 100644 benches/HumanEval-RustBench/has_only_one_distinct_element.rs create mode 100644 benches/HumanEval-RustBench/index_wise_addition.rs create mode 100644 benches/HumanEval-RustBench/integer_square_root.rs create mode 100644 benches/HumanEval-RustBench/intersperse.rs create mode 100644 benches/HumanEval-RustBench/is_non_prime.rs create mode 100644 benches/HumanEval-RustBench/is_sorted.rs create mode 100644 benches/HumanEval-RustBench/largest_prime_factor.rs create mode 100644 benches/HumanEval-RustBench/last_position.rs create mode 100644 benches/HumanEval-RustBench/max_array.rs create mode 100644 benches/HumanEval-RustBench/max_dafny_lsp.rs create mode 100644 benches/HumanEval-RustBench/remove_duplicates.rs create mode 100644 benches/HumanEval-RustBench/remove_element.rs create mode 100644 benches/HumanEval-RustBench/remove_elements.rs create mode 100644 benches/HumanEval-RustBench/replace.rs create mode 100644 benches/HumanEval-RustBench/replace_chars.rs create mode 100644 benches/HumanEval-RustBench/reverse.rs create mode 100644 benches/HumanEval-RustBench/rolling_max.rs create mode 100644 benches/HumanEval-RustBench/smallest_list_length.rs create mode 100644 benches/HumanEval-RustBench/smallest_missing_number.rs create mode 100644 benches/HumanEval-RustBench/string_xor.rs create mode 100644 benches/HumanEval-RustBench/two_sum.rs create mode 100644 benches/HumanEval-RustBench/two_way_sort.rs create mode 100644 benches/HumanEval-RustBench/unique.rs create mode 100644 benches/HumanEval-RustBench/unique_better.rs create mode 100644 scripts/process_files.fish create mode 100644 scripts/process_verus_task.py rename run_validating.sh => scripts/run_validating.sh (100%) rename run_with_houdini.sh => scripts/run_with_houdini.sh (100%) diff --git a/.gitignore b/.gitignore index 776b95e..6edb45a 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,5 @@ results/* /log_tries/ /log_tries/* .direnv +scripts/processed +scripts/processed/* diff --git a/benches/HumanEval-RustBench/000-has_close_elements.rs b/benches/HumanEval-RustBench/000-has_close_elements.rs new file mode 100644 index 0000000..bc65e22 --- /dev/null +++ b/benches/HumanEval-RustBench/000-has_close_elements.rs @@ -0,0 +1,59 @@ +use vstd::math::abs; +use vstd::prelude::*; +use vstd::slice::*; + +verus! { +fn has_close_elements(numbers: &[i64], threshold: i64) -> (result: bool) + ensures + result == exists|i: int, j: int| + 0 <= i < j < numbers@.len() && abs(numbers[i] - numbers[j]) < threshold, +{ + if threshold <= 0 { + assert(forall|i: int, j: int| + 0 <= i < j < numbers@.len() ==> abs(numbers[i] - numbers[j]) >= 0 >= threshold); + return false; + } + let max_minus_threshold: i64 = i64::MAX - threshold; + let numbers_len: usize = numbers.len(); + for x in 0..numbers_len + invariant + max_minus_threshold == i64::MAX - threshold, + numbers_len == numbers@.len(), + forall|i: int, j: int| + 0 <= i < j < numbers@.len() && i < x ==> abs(numbers[i] - numbers[j]) >= threshold, + { + let numbers_x: i64 = *slice_index_get(numbers, x); + for y in x + 1..numbers_len + invariant + max_minus_threshold == i64::MAX - threshold, + numbers_len == numbers@.len(), + x < numbers@.len(), + numbers_x == numbers[x as int], + forall|i: int, j: int| + 0 <= i < j < numbers@.len() && i < x ==> abs(numbers[i] - numbers[j]) + >= threshold, + forall|j: int| x < j < y ==> abs(numbers_x - numbers[j]) >= threshold, + { + let numbers_y = *slice_index_get(numbers, y); + if numbers_x > numbers_y { + if numbers_y > max_minus_threshold { + return true; + } + if numbers_x < numbers_y + threshold { + return true; + } + } else { + if numbers_x > max_minus_threshold { + return true; + } + if numbers_y < numbers_x + threshold { + return true; + } + } + } + } + false +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/001-separate-paren-groups.rs b/benches/HumanEval-RustBench/001-separate-paren-groups.rs new file mode 100644 index 0000000..705368b --- /dev/null +++ b/benches/HumanEval-RustBench/001-separate-paren-groups.rs @@ -0,0 +1,155 @@ +use vstd::prelude::*; + +verus! { +pub open spec fn nesting_level(input: Seq) -> int + decreases input.len(), +{ + if input.len() == 0 { + 0 + } else { + let prev_nesting_level = nesting_level(input.drop_last()); + let c = input.last(); + if c == '(' { + prev_nesting_level + 1 + } else if c == ')' { + prev_nesting_level - 1 + } else { + prev_nesting_level + } + } +} + +pub open spec fn is_paren_char(c: char) -> bool { + c == '(' || c == ')' +} +pub open spec fn is_balanced_group(input: Seq) -> bool { + &&& input.len() > 0 + &&& nesting_level(input) == 0 + &&& forall|i| 0 <= i < input.len() ==> is_paren_char(#[trigger] input[i]) + &&& forall|i| 0 < i < input.len() ==> nesting_level(#[trigger] input.take(i)) > 0 +} +pub open spec fn is_sequence_of_balanced_groups(input: Seq) -> bool { + &&& nesting_level(input) == 0 + &&& forall|i| 0 < i < input.len() ==> nesting_level(#[trigger] input.take(i)) >= 0 +} + +pub open spec fn vecs_to_seqs(s: Seq>) -> Seq> { + s.map(|_i, ss: Vec| ss@) +} + +pub open spec fn remove_nonparens(s: Seq) -> Seq { + s.filter(|c| is_paren_char(c)) +} +proof fn lemma_remove_nonparens_maintained_by_push(s: Seq, pos: int) + requires + 0 <= pos < s.len(), + ensures + ({ + let s1 = remove_nonparens(s.take(pos as int)); + let s2 = remove_nonparens(s.take((pos + 1) as int)); + if is_paren_char(s[pos]) { + s2 == s1.push(s[pos]) + } else { + s2 == s1 + } + }), + decreases pos, +{ + reveal(Seq::filter); + assert(s.take((pos + 1) as int).drop_last() =~= s.take(pos as int)); + if pos != 0 { + lemma_remove_nonparens_maintained_by_push(s, pos - 1); + } +} +fn separate_paren_groups(input: &Vec) -> (groups: Vec>) + requires + is_sequence_of_balanced_groups(input@), + ensures + forall|i: int| + #![trigger groups[i]] + 0 <= i < groups.len() ==> is_balanced_group(groups[i]@), + vecs_to_seqs(groups@).flatten() == remove_nonparens(input@), +{ + let mut groups: Vec> = Vec::new(); + let mut current_group: Vec = Vec::new(); + let input_len = input.len(); + let ghost mut ghost_groups: Seq> = Seq::empty(); + proof { + assert(vecs_to_seqs(groups@) =~= ghost_groups); + assert(remove_nonparens(input@.take(0)) =~= Seq::::empty()); + assert(ghost_groups.flatten() + current_group@ =~= Seq::::empty()); + } + let mut current_nesting_level: usize = 0; + for pos in 0..input_len + invariant + input_len == input.len(), + ghost_groups == vecs_to_seqs(groups@), + ghost_groups.flatten() + current_group@ == remove_nonparens(input@.take(pos as int)), + forall|i: int| + #![trigger groups[i]] + 0 <= i < ghost_groups.len() ==> is_balanced_group(ghost_groups[i]), + current_nesting_level == nesting_level(input@.take(pos as int)), + current_nesting_level == nesting_level(current_group@), + current_nesting_level <= pos, + current_group@.len() == 0 <==> current_nesting_level == 0, + forall|i| 0 <= i < current_group@.len() ==> is_paren_char(#[trigger] current_group@[i]), + forall|i| + 0 < i < current_group@.len() ==> nesting_level(#[trigger] current_group@.take(i)) + > 0, + is_sequence_of_balanced_groups(input@), + { + let ghost prev_group = current_group@; + let ghost prev_groups = ghost_groups; + let c = input[pos]; + proof { + assert(input@.take((pos + 1) as int) == input@.take(pos as int).push(c)); + assert(input@.take((pos + 1) as int).drop_last() == input@.take(pos as int)); + lemma_remove_nonparens_maintained_by_push(input@, pos as int); + } + if c == '(' { + current_nesting_level = current_nesting_level + 1; + current_group.push('('); + assert(current_group@.drop_last() == prev_group); + assert(ghost_groups.flatten() + current_group@ =~= (ghost_groups.flatten() + + prev_group).push('(')); + assert(forall|i| + 0 < i < prev_group.len() ==> #[trigger] current_group@.take(i) == prev_group.take( + i, + )); + } else if c == ')' { + current_nesting_level = current_nesting_level - 1; + current_group.push(')'); + assert(current_group@.drop_last() == prev_group); + assert(ghost_groups.flatten() + current_group@ =~= (ghost_groups.flatten() + + prev_group).push(')')); + assert(forall|i| + 0 < i < prev_group.len() ==> #[trigger] current_group@.take(i) == prev_group.take( + i, + )); + if current_nesting_level == 0 { + proof { + ghost_groups = ghost_groups.push(current_group@); + assert(vecs_to_seqs(groups@.push(current_group)) =~= vecs_to_seqs(groups@).push( + current_group@, + )); + assert(ghost_groups.drop_last() == prev_groups); + assert(ghost_groups.flatten() =~= prev_groups.flatten() + current_group@) by { + prev_groups.lemma_flatten_and_flatten_alt_are_equivalent(); + ghost_groups.lemma_flatten_and_flatten_alt_are_equivalent(); + } + } + groups.push(current_group); + current_group = Vec::::new(); + assert(ghost_groups.flatten() + current_group@ =~= remove_nonparens( + input@.take((pos + 1) as int), + )); + } + } + } + assert(input@.take(input_len as int) =~= input@); + assert(ghost_groups.flatten() + current_group@ == ghost_groups.flatten()); + groups +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/004-mean_absolute_derivation.rs b/benches/HumanEval-RustBench/004-mean_absolute_derivation.rs new file mode 100644 index 0000000..31daf3c --- /dev/null +++ b/benches/HumanEval-RustBench/004-mean_absolute_derivation.rs @@ -0,0 +1,332 @@ +use vstd::arithmetic::div_mod::{ + lemma_div_is_ordered, lemma_div_is_ordered_by_denominator, lemma_div_multiples_vanish, + lemma_fundamental_div_mod, lemma_fundamental_div_mod_converse, +}; +use vstd::arithmetic::mul::{ + lemma_mul_inequality, lemma_mul_is_distributive_add, lemma_mul_is_distributive_add_other_way, + lemma_mul_unary_negation, +}; +use vstd::prelude::*; + +verus! { +pub open spec fn sum(numbers: Seq) -> int { + numbers.fold_left(0, |acc: int, x| acc + x) +} +pub open spec fn mean(values: Seq) -> int + recommends + values.len() > 0, +{ + sum(values) / (values.len() as int) +} +pub open spec fn abs(n: int) -> int { + if n >= 0 { + n + } else { + -n + } +} +pub open spec fn spec_mean_absolute_deviation(numbers: Seq) -> int + recommends + numbers.len() > 0, +{ + let avg = mean(numbers); + sum(numbers.map(|_index, n: int| abs(n - avg))) / (numbers.len() as int) +} +proof fn lemma_sum_bound(numbers: Seq, min: int, max: int) + requires + forall|i| 0 <= i < numbers.len() ==> min <= #[trigger] numbers[i] <= max, + ensures + numbers.len() * min <= sum(numbers) <= numbers.len() * max, + decreases numbers.len(), +{ + if numbers.len() != 0 { + lemma_sum_bound(numbers.drop_last(), min, max); + lemma_mul_is_distributive_add_other_way(min, numbers.len() - 1, 1); + lemma_mul_is_distributive_add_other_way(max, numbers.len() - 1, 1); + } +} +proof fn lemma_sum_ratio_bound(numbers: Seq, denominator: int, min: int, max: int) + requires + forall|i| 0 <= i < numbers.len() ==> min <= #[trigger] numbers[i] <= max, + denominator >= numbers.len(), + denominator > 0, + min <= 0, + max >= 0, + ensures + min <= sum(numbers) / denominator <= max, +{ + lemma_sum_bound(numbers, min, max); + assert(denominator * min <= numbers.len() * min) by { + lemma_mul_unary_negation(denominator, -min); + lemma_mul_unary_negation(numbers.len() as int, -min); + lemma_mul_inequality(numbers.len() as int, denominator, -min); + } + assert(numbers.len() * max <= denominator * max) by { + lemma_mul_inequality(numbers.len() as int, denominator, max); + } + lemma_div_multiples_vanish(min, denominator); + lemma_div_multiples_vanish(max, denominator); + lemma_div_is_ordered(denominator * min, sum(numbers), denominator); + lemma_div_is_ordered(sum(numbers), denominator * max, denominator); +} +proof fn lemma_how_to_update_running_sum(s: Seq, i: int) + requires + 0 <= i < s.len(), + ensures + sum(s.take(i + 1)) == sum(s.take(i)) + s[i], +{ + let q1 = s.take(i); + let q2 = s.take(i + 1); + assert(q2.last() == s[i]); + assert(q2.drop_last() == q1); +} +proof fn lemma_how_to_add_then_divide(x: int, y: int, d: int) + requires + d > 0, + ensures + if (x % d) + (y % d) >= d { + &&& (x + y) / d == (x / d) + (y / d) + 1 + &&& (x + y) % d == (x % d) + (y % d) - d + } else { + &&& (x + y) / d == (x / d) + (y / d) + &&& (x + y) % d == (x % d) + (y % d) + }, +{ + lemma_fundamental_div_mod(x, d); + lemma_fundamental_div_mod(y, d); + lemma_mul_is_distributive_add(d, x / d, y / d); + if (x % d) + (y % d) >= d { + lemma_mul_is_distributive_add(d, (x / d) + (y / d), 1); + lemma_fundamental_div_mod_converse(x + y, d, (x / d) + (y / d) + 1, (x % d) + (y % d) - d); + } else { + lemma_fundamental_div_mod_converse(x + y, d, (x / d) + (y / d), (x % d) + (y % d)); + } +} +proof fn lemma_effect_of_dividing_by_two_or_more(x: int, d: int) + requires + d >= 2, + ensures + x > 0 ==> x / d < x, + x < 0 ==> x / d < 0, +{ + lemma_fundamental_div_mod(x, d); + if x > 0 { + lemma_div_is_ordered_by_denominator(x, 2, d); + } +} +fn divide_i32_by_u32(x: i32, d: u32) -> (qr: (i32, u32)) + requires + d > 0, + ensures + ({ + let (q, r) = qr; + q == x as int / d as int && r == x as int % d as int + }), +{ + if x >= 0 { + return ((x as u32 / d) as i32, x as u32 % d); + } + let neg_x: u32; + if x == i32::MIN { + if d == 1 { + return (x, 0); + } else { + neg_x = 0x80000000u32; + } + } else { + neg_x = (-x) as u32; + } + assert(neg_x == -x); + let neg_x_div_d = neg_x / d; + let neg_x_mod_d = neg_x % d; + assert(neg_x == d * neg_x_div_d + neg_x_mod_d) by { + lemma_fundamental_div_mod(neg_x as int, d as int); + } + assert(neg_x_div_d <= i32::MAX) by { + if x == i32::MIN { + lemma_mul_inequality(2, d as int, neg_x_div_d as int); + } + } + if neg_x_mod_d == 0 { + proof { + lemma_mul_unary_negation(d as int, neg_x_div_d as int); + assert(x == d * -neg_x_div_d); + lemma_fundamental_div_mod_converse(x as int, d as int, -(neg_x_div_d as int), 0int); + } + (-(neg_x_div_d as i32), 0u32) + } else { + proof { + lemma_mul_unary_negation(d as int, (neg_x_div_d + 1) as int); + lemma_mul_is_distributive_add(d as int, neg_x_div_d as int, 1); + assert(x == d as int * (-neg_x_div_d - 1) + (d - neg_x_mod_d) as int); + lemma_fundamental_div_mod_converse( + x as int, + d as int, + -(neg_x_div_d as int) - 1, + (d - neg_x_mod_d) as int, + ); + } + (-(neg_x_div_d as i32) - 1, d - neg_x_mod_d) + } +} +fn divide_i32_by_usize(x: i32, d: usize) -> (qr: (i32, usize)) + requires + d > 0, + ensures + ({ + let (q, r) = qr; + q == x as int / d as int && r == x as int % d as int + }), +{ + if d <= u32::MAX as usize { + let (q, r) = divide_i32_by_u32(x, d as u32); + (q, r as usize) + } else if x >= 0 { + assert(0 == x as int / d as int && x == x as int % d as int) by { + lemma_fundamental_div_mod_converse(x as int, d as int, 0, x as int); + } + (0, x as usize) + } else { + assert(-1 == x as int / d as int && d + x == x as int % d as int) by { + lemma_fundamental_div_mod_converse(x as int, d as int, -1, d + x); + } + let neg_x: usize = if x == i32::MIN { + 0x80000000usize + } else { + (-x) as usize + }; + (-1, d - neg_x) + } +} +fn compute_mean_of_i32s(numbers: &[i32]) -> (result: i32) + requires + numbers.len() > 0, + ensures + result == mean(numbers@.map(|_index, n: i32| n as int)), +{ + let ghost nums = numbers@.map(|_index, n: i32| n as int); + let mut quotient: i32 = 0; + let mut remainder: usize = 0; + let numbers_len: usize = numbers.len(); + for i in 0..numbers_len + invariant + quotient == sum(nums.take(i as int)) / numbers_len as int, + remainder == sum(nums.take(i as int)) % numbers_len as int, + numbers_len == numbers.len(), + nums == numbers@.map(|_index, n: i32| n as int), + { + let n = numbers[i]; + proof { + lemma_how_to_update_running_sum(nums, i as int); + lemma_sum_ratio_bound( + nums.take(i + 1), + numbers_len as int, + i32::MIN as int, + i32::MAX as int, + ); + lemma_how_to_add_then_divide(sum(nums.take(i as int)), n as int, numbers_len as int); + } + + let (q, r) = divide_i32_by_usize(n, numbers_len); + + if r >= numbers_len - remainder { + assert(q < i32::MAX) by { + lemma_effect_of_dividing_by_two_or_more(n as int, numbers_len as int); + } + remainder -= (numbers_len - r); + quotient += (q + 1); + } else { + remainder += r; + quotient += q; + } + } + assert(nums == nums.take(nums.len() as int)); + quotient +} +fn compute_absolute_difference(x: i32, y: i32) -> (z: u32) + ensures + z == abs(x - y), +{ + if x >= y { + if y >= 0 || x < 0 { + (x - y) as u32 + } else { + let neg_y: u32 = if y == i32::MIN { + 0x80000000u32 + } else { + (-y) as u32 + }; + x as u32 + neg_y + } + } else { + if x >= 0 || y < 0 { + (y - x) as u32 + } else { + let neg_x: u32 = if x == i32::MIN { + 0x80000000u32 + } else { + (-x) as u32 + }; + y as u32 + neg_x + } + } +} +pub fn mean_absolute_deviation(numbers: &[i32]) -> (result: u32) + requires + numbers.len() > 0, + ensures + result == spec_mean_absolute_deviation(numbers@.map(|_index, n: i32| n as int)), +{ + let numbers_mean: i32 = compute_mean_of_i32s(numbers); + let ghost deviations = numbers@.map(|_index, n: i32| n as int).map( + |_index, n: int| abs(n - numbers_mean), + ); + let mut quotient: u32 = 0; + let mut remainder: usize = 0; + let numbers_len: usize = numbers.len(); + for i in 0..numbers_len + invariant + quotient == sum(deviations.take(i as int)) / numbers_len as int, + remainder == sum(deviations.take(i as int)) % numbers_len as int, + numbers_len == numbers.len(), + numbers_mean == mean(numbers@.map(|_index, n: i32| n as int)), + deviations == numbers@.map(|_index, n: i32| n as int).map( + |_index, n: int| abs(n - numbers_mean), + ), + { + let n: u32 = compute_absolute_difference(numbers[i], numbers_mean); + proof { + lemma_how_to_update_running_sum(deviations, i as int); + lemma_sum_ratio_bound( + deviations.take(i + 1), + numbers_len as int, + u32::MIN as int, + u32::MAX as int, + ); + lemma_how_to_add_then_divide( + sum(deviations.take(i as int)), + n as int, + numbers_len as int, + ); + } + + let q: u32 = (n as usize / numbers_len) as u32; + let r: usize = n as usize % numbers_len; + + if r >= numbers_len - remainder { + assert(q < u32::MAX) by { + lemma_effect_of_dividing_by_two_or_more(n as int, numbers_len as int); + } + remainder -= (numbers_len - r); + quotient += (q + 1); + } else { + remainder += r; + quotient += q; + } + } + assert(deviations == deviations.take(deviations.len() as int)); + quotient +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/005-intersperse.rs b/benches/HumanEval-RustBench/005-intersperse.rs new file mode 100644 index 0000000..b3bfa03 --- /dev/null +++ b/benches/HumanEval-RustBench/005-intersperse.rs @@ -0,0 +1,105 @@ +use vstd::assert_seqs_equal; +use vstd::prelude::*; + +verus! { +pub open spec fn intersperse_spec(numbers: Seq, delimiter: u64) -> Seq + decreases numbers.len(), +{ + if numbers.len() <= 1 { + numbers + } else { + intersperse_spec(numbers.drop_last(), delimiter) + seq![delimiter, numbers.last()] + } +} +spec fn even(i: int) -> int { + 2 * i +} + +spec fn odd(i: int) -> int { + 2 * i + 1 +} +spec fn intersperse_quantified(numbers: Seq, delimiter: u64, interspersed: Seq) -> bool { + (if numbers.len() == 0 { + interspersed.len() == 0 + } else { + interspersed.len() == 2 * numbers.len() - 1 + }) && (forall|i: int| 0 <= i < numbers.len() ==> #[trigger] interspersed[even(i)] == numbers[i]) + && (forall|i: int| + 0 <= i < numbers.len() - 1 ==> #[trigger] interspersed[odd(i)] == delimiter) +} + +proof fn intersperse_spec_len(numbers: Seq, delimiter: u64) + ensures + numbers.len() > 0 ==> intersperse_spec(numbers, delimiter).len() == 2 * numbers.len() - 1, + decreases numbers.len(), +{ + if numbers.len() > 0 { + intersperse_spec_len(numbers.drop_last(), delimiter); + } +} +proof fn intersperse_quantified_is_spec(numbers: Seq, delimiter: u64, interspersed: Seq) + requires + intersperse_quantified(numbers, delimiter, interspersed), + ensures + interspersed == intersperse_spec(numbers, delimiter), + decreases numbers.len(), +{ + let is = intersperse_spec(numbers, delimiter); + if numbers.len() == 0 { + } else if numbers.len() == 1 { + assert(interspersed.len() == 1); + assert(interspersed[even(0)] == numbers[0]); + } else { + intersperse_quantified_is_spec( + numbers.drop_last(), + delimiter, + interspersed.take(interspersed.len() - 2), + ); + intersperse_spec_len(numbers, delimiter); + assert_seqs_equal!(is == interspersed, i => { + if i < is.len() - 2 { + } else { + if i % 2 == 0 { + assert(is[i] == numbers.last()); + assert(interspersed[even(i/2)] == numbers[i / 2]); + assert(i / 2 == numbers.len() - 1); + } else { + assert(is[i] == delimiter); + assert(interspersed[odd((i-1)/2)] == delimiter); + } + } + }); + } + assert(interspersed =~= intersperse_spec(numbers, delimiter)); +} +pub fn intersperse(numbers: Vec, delimiter: u64) -> (result: Vec) + ensures + result@ == intersperse_spec(numbers@, delimiter), +{ + if numbers.len() <= 1 { + numbers + } else { + let mut result = Vec::new(); + let mut index = 0; + while index < numbers.len() - 1 + invariant + numbers.len() > 1, + 0 <= index < numbers.len(), + result.len() == 2 * index, + forall|i: int| 0 <= i < index ==> #[trigger] result[even(i)] == numbers[i], + forall|i: int| 0 <= i < index ==> #[trigger] result[odd(i)] == delimiter, + { + result.push(numbers[index]); + result.push(delimiter); + index += 1; + } + result.push(numbers[numbers.len() - 1]); + proof { + intersperse_quantified_is_spec(numbers@, delimiter, result@); + } + result + } +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/007-filter_by_substring.rs b/benches/HumanEval-RustBench/007-filter_by_substring.rs new file mode 100644 index 0000000..06f0295 --- /dev/null +++ b/benches/HumanEval-RustBench/007-filter_by_substring.rs @@ -0,0 +1,92 @@ +use vstd::prelude::*; + +verus! { + +fn string_eq(s1: &str, s2: &str) -> (result: bool) + ensures + result <==> s1@ == s2@, +{ + let s1_len = s1.unicode_len(); + let s2_len = s2.unicode_len(); + if s1_len != s2_len { + return false; + } + for i in 0..s1_len + invariant + s1@.subrange(0, i as int) =~= s2@.subrange(0, i as int), + i <= s1_len == s2_len == s1@.len() == s2@.len(), + { + let c = s1.get_char(i); + if c != s2.get_char(i) { + return false; + } + assert(s1@.subrange(0, i + 1) == s1@.subrange(0, i as int).push(c)); + assert(s1@.subrange(0, i as int).push(c) == s2@.subrange(0, i as int).push(c)); + assert(s2@.subrange(0, i as int).push(c) == s2@.subrange(0, i + 1)); + } + assert(s1@ == s1@.subrange(0, s1_len as int)); + assert(s2@ == s2@.subrange(0, s2_len as int)); + true +} + +fn check_substring(s: &str, sub: &str) -> (result: bool) + ensures + result <==> exists|i: int| + 0 <= i <= s@.len() - sub@.len() && s@.subrange(i, #[trigger] (i + sub@.len())) == sub@, +{ + let s_len = s.unicode_len(); + let sub_len = sub.unicode_len(); + if (s_len < sub_len) { + return false; + } + if sub_len == 0 { + assert(s@.subrange(0, (0 + sub@.len()) as int) == sub@); + return true; + } + for i in 0..s_len - sub_len + 1 + invariant + forall|j: int| 0 <= j < i ==> s@.subrange(j, #[trigger] (j + sub@.len())) != sub@, + i <= s_len - sub_len + 1, + sub_len == sub@.len() <= s_len == s@.len(), + sub_len > 0, + { + if string_eq(sub, s.substring_char(i, i + sub_len)) { + assert(0 <= i <= s@.len() - sub@.len()); + assert(s@.subrange(i as int, i + sub@.len()) == sub@); + return true; + } + } + false +} + +fn filter_by_substring<'a>(strings: &Vec<&'a str>, substring: &str) -> (res: Vec<&'a str>) + ensures + forall|i: int| + 0 <= i < strings@.len() && (exists|j: int| + 0 <= j <= strings@[i]@.len() - substring@.len() && strings[i]@.subrange( + j, + #[trigger] (j + substring@.len()), + ) == substring@) ==> res@.contains(#[trigger] (strings[i])), +{ + let mut res = Vec::new(); + for n in 0..strings.len() + invariant + forall|i: int| + 0 <= i < n && (exists|j: int| + 0 <= j <= strings@[i]@.len() - substring@.len() && strings[i]@.subrange( + j, + #[trigger] (j + substring@.len()), + ) == substring@) ==> res@.contains(#[trigger] (strings[i])), + { + if check_substring(strings[n], substring) { + let ghost res_old = res; + res.push(strings[n]); + assert(res@.last() == strings[n as int]); + assert(res@.drop_last() == res_old@); + } + } + res +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/008-sum_product.rs b/benches/HumanEval-RustBench/008-sum_product.rs new file mode 100644 index 0000000..f02906a --- /dev/null +++ b/benches/HumanEval-RustBench/008-sum_product.rs @@ -0,0 +1,55 @@ +use vstd::prelude::*; + +verus! { +pub open spec fn sum(numbers: Seq) -> int { + numbers.fold_left(0, |acc: int, x| acc + x) +} +pub open spec fn product(numbers: Seq) -> int { + numbers.fold_left(1, |acc: int, x| acc * x) +} +proof fn sum_bound(numbers: Seq) + ensures + sum(numbers) <= numbers.len() * u32::MAX, + decreases numbers.len(), +{ + if numbers.len() == 0 { + } else { + sum_bound(numbers.drop_last()); + } +} +fn sum_product(numbers: Vec) -> (result: (u64, Option)) + requires + numbers.len() < u32::MAX, + ensures + result.0 == sum(numbers@), + result.1 matches Some(v) ==> v == product(numbers@), +{ + let mut sum_value: u64 = 0; + let mut prod_value: Option = Some(1); + for index in 0..numbers.len() + invariant + numbers.len() < u32::MAX, + sum_value == sum(numbers@.take(index as int)), + prod_value matches Some(v) ==> v == product(numbers@.take(index as int)), + index <= numbers.len(), + index >= 0, + { + proof { + sum_bound(numbers@.take(index as int)); + assert(sum_value <= index * u32::MAX); + } + assert(numbers@.take(index as int + 1).drop_last() =~= numbers@.take(index as int)); + assert(numbers[index as int] == numbers@.take(index as int + 1).last()); + sum_value += numbers[index] as u64; + prod_value = + match prod_value { + Some(v) => v.checked_mul(numbers[index]), + None => None, + }; + } + assert(numbers@.take(numbers@.len() as int) =~= numbers@); + (sum_value, prod_value) +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/009-rolling_max.rs b/benches/HumanEval-RustBench/009-rolling_max.rs new file mode 100644 index 0000000..b1203a5 --- /dev/null +++ b/benches/HumanEval-RustBench/009-rolling_max.rs @@ -0,0 +1,41 @@ +use vstd::prelude::*; + +verus! { + +spec fn seq_max(a: Seq) -> i32 + decreases a.len(), +{ + if a.len() == 0 { + i32::MIN + } else if a.last() > seq_max(a.drop_last()) { + a.last() + } else { + seq_max(a.drop_last()) + } +} + +fn rolling_max(numbers: Vec) -> (result: Vec) + ensures + result.len() == numbers.len(), + forall|i: int| 0 <= i < numbers.len() ==> result[i] == seq_max(numbers@.take(i + 1)), +{ + let mut max_so_far = i32::MIN; + let mut result = Vec::with_capacity(numbers.len()); + for pos in 0..numbers.len() + invariant + result.len() == pos, + max_so_far == seq_max(numbers@.take(pos as int)), + forall|i: int| 0 <= i < pos ==> result[i] == seq_max(numbers@.take(i + 1)), + { + let number = numbers[pos]; + if number > max_so_far { + max_so_far = number; + } + result.push(max_so_far); + assert(numbers@.take((pos + 1) as int).drop_last() =~= numbers@.take(pos as int)); + } + result +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/011-string_xor.rs b/benches/HumanEval-RustBench/011-string_xor.rs new file mode 100644 index 0000000..7a9cef4 --- /dev/null +++ b/benches/HumanEval-RustBench/011-string_xor.rs @@ -0,0 +1,48 @@ +use vstd::prelude::*; +use vstd::slice::*; + +verus! { +spec fn is_binary_digit(c: char) -> bool { + c == '0' || c == '1' +} +spec fn xor_char(a: char, b: char) -> (result: char) + recommends + is_binary_digit(a), + is_binary_digit(b), +{ + if a == b { + '0' + } else { + '1' + } +} + +fn string_xor(a: &[char], b: &[char]) -> (result: Vec) + requires + a@.len() == b@.len(), + forall|i: int| 0 <= i < a@.len() as int ==> is_binary_digit(#[trigger] a[i]), + forall|i: int| 0 <= i < b@.len() as int ==> is_binary_digit(#[trigger] b[i]), + ensures + result.len() == a@.len(), + forall|i: int| + 0 <= i < result.len() as int ==> #[trigger] result[i] == xor_char(a[i], b[i]), +{ + let a_len = a.len(); + let mut result = Vec::with_capacity(a_len); + #[verifier::loop_isolation(false)] + for pos in 0..a_len + invariant + result.len() == pos, + forall|i: int| 0 <= i < pos ==> #[trigger] result[i] == xor_char(a[i], b[i]), + { + if *slice_index_get(a, pos) == *slice_index_get(b, pos) { + result.push('0'); + } else { + result.push('1'); + } + } + result +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/012-longest.rs b/benches/HumanEval-RustBench/012-longest.rs new file mode 100644 index 0000000..e12aaab --- /dev/null +++ b/benches/HumanEval-RustBench/012-longest.rs @@ -0,0 +1,42 @@ +use vstd::prelude::*; + +verus! { + +fn longest(strings: &Vec>) -> (result: Option<&Vec>) + ensures + match result { + None => strings.len() == 0, + Some(s) => { + (forall|i: int| #![auto] 0 <= i < strings.len() ==> s.len() >= strings[i].len()) + && (exists|i: int| + #![auto] + (0 <= i < strings.len() && s == strings[i] && (forall|j: int| + #![auto] + 0 <= j < i ==> strings[j].len() < s.len()))) + }, + }, +{ + if strings.len() == 0 { + return None; + } + let mut result: &Vec = &strings[0]; + let mut pos = 0; + + for i in 1..strings.len() + invariant + 0 <= pos < i, + result == &strings[pos as int], + exists|i: int| 0 <= i < strings.len() && strings[i] == result, + forall|j: int| #![auto] 0 <= j < i ==> strings[j].len() <= result.len(), + forall|j: int| #![auto] 0 <= j < pos ==> strings[j].len() < result.len(), + { + if result.len() < strings[i].len() { + result = &strings[i]; + pos = i; + } + } + Some(result) +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/014-all_prefixes.rs b/benches/HumanEval-RustBench/014-all_prefixes.rs new file mode 100644 index 0000000..56b977b --- /dev/null +++ b/benches/HumanEval-RustBench/014-all_prefixes.rs @@ -0,0 +1,54 @@ +use vstd::prelude::*; + +verus! { + +fn all_prefixes(s: &Vec) -> (prefixes: Vec>) + ensures + prefixes.len() == s.len(), + forall|i: int| #![auto] 0 <= i < s.len() ==> prefixes[i]@ == s@.subrange(0, i + 1), +{ + let mut prefixes: Vec> = vec![]; + let mut prefix = vec![]; + assert(forall|i: int| + #![auto] + 0 <= i < prefix.len() ==> prefix@.index(i) == prefix@.subrange( + 0, + prefix.len() as int, + ).index(i)); + + assert(prefix@ == prefix@.subrange(0, 0)); + assert(forall|i: int| + #![auto] + 0 <= i < prefix.len() ==> prefix@.index(i) == s@.subrange(0, prefix.len() as int).index(i)); + assert(prefix@ == s@.subrange(0, 0)); + for i in 0..s.len() + invariant + prefixes.len() == i, + prefix.len() == i, + forall|j: int| #![auto] 0 <= j < i ==> prefixes[j]@ == s@.subrange(0, j + 1), + prefix@ == s@.subrange(0, i as int), + prefix@ == prefix@.subrange(0, i as int), + { + let ghost pre_prefix = prefix; + prefix.push(s[i]); + assert(pre_prefix@.subrange(0, i as int) == pre_prefix@ && prefix@.subrange(0, i as int) + == pre_prefix@.subrange(0, i as int)); + assert(prefix@.subrange(0, i as int) == s@.subrange(0, i as int)); + assert(prefix[i as int] == s@.subrange(0, i + 1).index(i as int)); + + assert(forall|j: int| + #![auto] + 0 <= j < i + 1 ==> prefix@.index(j) == prefix@.subrange(0, (i + 1) as int).index(j)); + assert(prefix@ == prefix@.subrange(0, (i + 1) as int)); + assert(forall|j: int| + #![auto] + 0 <= j < i + 1 ==> prefix@.index(j) == s@.subrange(0, (i + 1) as int).index(j)); + assert(prefix@ == s@.subrange(0, (i + 1) as int)); + + prefixes.push(prefix.clone()); + } + return prefixes; +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/023-strlen.rs b/benches/HumanEval-RustBench/023-strlen.rs new file mode 100644 index 0000000..a9e0d4e --- /dev/null +++ b/benches/HumanEval-RustBench/023-strlen.rs @@ -0,0 +1,14 @@ +use vstd::prelude::*; + +verus! { + +fn strlen(string: &Vec) -> (length: usize) + ensures + length + == string.len(), +{ + string.len() +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/024-largest-divisor.rs b/benches/HumanEval-RustBench/024-largest-divisor.rs new file mode 100644 index 0000000..e5f6108 --- /dev/null +++ b/benches/HumanEval-RustBench/024-largest-divisor.rs @@ -0,0 +1,85 @@ +use vstd::arithmetic::div_mod::{ + lemma_fundamental_div_mod, lemma_fundamental_div_mod_converse_div, +}; +use vstd::prelude::*; + +verus! { + +pub open spec fn mul(a: nat, b: nat) -> nat { + builtin::mul(a, b) +} +pub open spec fn divides(factor: nat, candidate: nat) -> bool { + exists|k: nat| mul(factor, k) == candidate +} +proof fn lemma_mod_zero(a: nat, b: nat) + requires + a > 0 && b > 0, + a % b == 0, + ensures + divides(b, a), +{ + lemma_fundamental_div_mod(a as int, b as int); + assert(mul(b, (a / b)) == a); +} +proof fn lemma_mod_zero_reversed(a: nat, b: nat) + requires + a > 0 && b > 0, + divides(b, a), + ensures + a % b == 0, +{ + let k_wit = choose|k: nat| mul(b, k) == a; + assert(k_wit == a / b) by { + lemma_fundamental_div_mod_converse_div(a as int, b as int, k_wit as int, 0 as int); + } + lemma_fundamental_div_mod(a as int, b as int); +} +proof fn lemma_one_divides_all() + ensures + forall|v: nat| divides(1 as nat, v), +{ + assert forall|v: nat| divides(1 as nat, v) by { + assert(mul(1 as nat, v) == v); + } +} +fn largest_divisor(n: u32) -> (ret: u32) + requires + n > 1, + ensures + divides(ret as nat, n as nat), + ret < n, + forall|k: u32| (0 < k < n && divides(k as nat, n as nat)) ==> ret >= k, +{ + let mut i = n - 1; + while i >= 2 + invariant + n > 0, + i < n, + forall|k: u32| i < k < n ==> !divides(k as nat, n as nat), + { + if n % i == 0 { + assert(divides(i as nat, n as nat)) by { + lemma_mod_zero(n as nat, i as nat); + } + return i; + } + i -= 1; + + assert forall|k: u32| i < k < n implies !divides(k as nat, n as nat) by { + if k == i + 1 { + assert(!divides(k as nat, n as nat)) by { + if (divides(k as nat, n as nat)) { + lemma_mod_zero_reversed(n as nat, k as nat); + } + } + } + } + } + assert(divides(1 as nat, n as nat)) by { + lemma_one_divides_all(); + } + 1 +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/030-get-positive.rs b/benches/HumanEval-RustBench/030-get-positive.rs new file mode 100644 index 0000000..18c71fb --- /dev/null +++ b/benches/HumanEval-RustBench/030-get-positive.rs @@ -0,0 +1,29 @@ +use vstd::prelude::*; + +verus! { + +fn get_positive(input: Vec) -> (positive_list: Vec) + ensures + positive_list@ == input@.filter(|x: i32| x > 0), +{ + let mut positive_list = Vec::::new(); + let input_len = input.len(); + assert(input@.take(0int).filter(|x: i32| x > 0) == Seq::::empty()); + for pos in 0..input_len + invariant + input_len == input.len(), + positive_list@ == input@.take(pos as int).filter(|x: i32| x > 0), + { + let n = input[pos]; + if n > 0 { + positive_list.push(n); + } + assert(input@.take((pos + 1) as int).drop_last() == input@.take(pos as int)); + reveal(Seq::filter); + } + assert(input@ == input@.take(input_len as int)); + positive_list +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/033-sort_third.rs b/benches/HumanEval-RustBench/033-sort_third.rs new file mode 100644 index 0000000..a946a36 --- /dev/null +++ b/benches/HumanEval-RustBench/033-sort_third.rs @@ -0,0 +1,120 @@ +use vstd::prelude::*; + +verus! { +spec fn count(s: Seq, x: T) -> int + decreases s.len(), +{ + if s.len() == 0 { + 0 + } else { + count(s.skip(1), x) + if s[0] == x { + 1int + } else { + 0int + } + } +} +spec fn permutes(s1: Seq, s2: Seq) -> bool { + forall|x: T| count(s1, x) == count(s2, x) +} +proof fn lemma_update_effect_on_count(s: Seq, i: int, v: T, x: T) + requires + 0 <= i < s.len(), + ensures + count(s.update(i, v), x) == if v == x && s[i] != x { + count(s, x) + 1 + } else if v != x && s[i] == x { + count(s, x) - 1 + } else { + count(s, x) + }, + decreases s.len(), +{ + if s.len() == 0 { + return ; + } + if i == 0 { + assert(s.update(i, v) =~= seq![v] + s.skip(1)); + assert(s.update(i, v).skip(1) =~= s.skip(1)); + } else { + assert(s.update(i, v) =~= seq![s[0]] + s.skip(1).update(i - 1, v)); + assert(s.update(i, v).skip(1) =~= s.skip(1).update(i - 1, v)); + lemma_update_effect_on_count(s.skip(1), i - 1, v, x); + } +} +proof fn lemma_swapping_produces_a_permutation(s: Seq, i: int, j: int) + requires + 0 <= i < s.len(), + 0 <= j < s.len(), + ensures + permutes(s.update(i, s[j]).update(j, s[i]), s), +{ + assert forall|x: T| #[trigger] count(s.update(i, s[j]).update(j, s[i]), x) == count(s, x) by { + lemma_update_effect_on_count(s, i, s[j], x); + lemma_update_effect_on_count(s.update(i, s[j]), j, s[i], x); + } +} +fn sort_third(l: Vec) -> (l_prime: Vec) + ensures + l_prime.len() == l.len(), + forall|i: int| 0 <= i < l.len() && i % 3 != 0 ==> l_prime[i] == l[i], + forall|i: int, j: int| + 0 <= i < j < l.len() && i % 3 == 0 && j % 3 == 0 ==> l_prime[i] <= l_prime[j], + permutes(l_prime@, l@), +{ + let ghost old_l = l@; + let l_len = l.len(); + let mut pos_being_set_to_smallest: usize = 0; + let mut l_prime: Vec = l; + while pos_being_set_to_smallest < l_len + invariant + l_len == l.len() == l_prime.len(), + pos_being_set_to_smallest % 3 == 0, + forall|i: int| 0 <= i < l_len && i % 3 != 0 ==> l_prime[i] == l[i], + permutes(l_prime@, l@), + forall|i: int, j: int| + 0 <= i < pos_being_set_to_smallest && i < j < l_len && i % 3 == 0 && j % 3 == 0 + ==> l_prime[i] <= l_prime[j], + { + let mut pos_of_smallest_found_so_far: usize = pos_being_set_to_smallest; + let mut pos_during_scan_for_smallest: usize = pos_being_set_to_smallest; + while pos_during_scan_for_smallest < l_len + invariant + l_len == l.len() == l_prime.len(), + pos_being_set_to_smallest % 3 == 0, + pos_during_scan_for_smallest % 3 == 0, + pos_of_smallest_found_so_far % 3 == 0, + pos_being_set_to_smallest <= pos_during_scan_for_smallest, + pos_being_set_to_smallest <= pos_of_smallest_found_so_far < l_len, + forall|i: int| 0 <= i < l_len && i % 3 != 0 ==> l_prime[i] == l[i], + permutes(l_prime@, l@), + forall|i: int| + pos_being_set_to_smallest <= i < pos_during_scan_for_smallest && i % 3 == 0 + ==> l_prime[pos_of_smallest_found_so_far as int] <= l_prime[i], + forall|i: int, j: int| + 0 <= i < pos_being_set_to_smallest && i < j < l_len && i % 3 == 0 && j % 3 == 0 + ==> l_prime[i] <= l_prime[j], + { + if l_prime[pos_during_scan_for_smallest] < l_prime[pos_of_smallest_found_so_far] { + pos_of_smallest_found_so_far = pos_during_scan_for_smallest; + } + pos_during_scan_for_smallest = pos_during_scan_for_smallest + 3; + } + proof { + lemma_swapping_produces_a_permutation( + l_prime@, + pos_being_set_to_smallest as int, + pos_of_smallest_found_so_far as int, + ); + } + let v1 = l_prime[pos_being_set_to_smallest]; + let v2 = l_prime[pos_of_smallest_found_so_far]; + l_prime.set(pos_being_set_to_smallest, v2); + l_prime.set(pos_of_smallest_found_so_far, v1); + pos_being_set_to_smallest = pos_being_set_to_smallest + 3; + } + l_prime +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/034-unique.rs b/benches/HumanEval-RustBench/034-unique.rs new file mode 100644 index 0000000..f4c8c90 --- /dev/null +++ b/benches/HumanEval-RustBench/034-unique.rs @@ -0,0 +1,183 @@ +use vstd::calc; +use vstd::prelude::*; +use vstd::seq_lib::lemma_multiset_commutative; +use vstd::seq_lib::lemma_seq_contains_after_push; + +verus! { + +proof fn swap_preserves_multiset_helper(s: Seq, i: int, j: int) + requires + 0 <= i < j < s.len(), + ensures + (s.take(j + 1)).to_multiset() =~= s.take(i).to_multiset().add( + s.subrange(i + 1, j).to_multiset(), + ).insert(s.index(j)).insert(s.index(i)), +{ + let fst = s.take(i); + let snd = s.subrange(i + 1, j); + + assert((s.take(j + 1)).to_multiset() =~= fst.to_multiset().insert(s.index(i)).add( + snd.to_multiset().insert(s.index(j)), + )) by { + assert(s.take(i + 1).to_multiset() =~= fst.to_multiset().insert(s.index(i))) by { + fst.to_multiset_ensures(); + assert(fst.push(s.index(i)) =~= s.take(i + 1)); + } + assert(s.subrange(i + 1, j + 1).to_multiset() =~= snd.to_multiset().insert(s.index(j))) by { + snd.to_multiset_ensures(); + assert(snd.push(s.index(j)) =~= s.subrange(i + 1, j + 1)); + } + lemma_multiset_commutative(s.take(i + 1), s.subrange(i + 1, j + 1)); + assert(s.take(i + 1) + s.subrange(i + 1, j + 1) =~= s.take(j + 1)); + } +} +proof fn swap_preserves_multiset(s1: Seq, s2: Seq, i: int, j: int) + requires + 0 <= i < j < s1.len() == s2.len(), + forall|x: int| 0 <= x < s1.len() && x != i && x != j ==> s1.index(x) == s2.index(x), + s1.index(i) == s2.index(j), + s1.index(j) == s2.index(i), + ensures + s1.to_multiset() == s2.to_multiset(), +{ + calc! { + (==) + s1.to_multiset(); { + lemma_multiset_commutative(s1.take(j + 1), s1.skip(j + 1)); + assert(s1 =~= s1.take(j + 1) + s1.skip(j + 1)); + } + s1.take(j + 1).to_multiset().add(s1.skip(j + 1).to_multiset()); { + assert(s1.take(j + 1).to_multiset() =~= s2.take(j + 1).to_multiset()) by { + assert(s1.take(i) == s2.take(i)); + assert(s1.subrange(i + 1, j) =~= (s2.subrange(i + 1, j))); + swap_preserves_multiset_helper(s1, i, j); + swap_preserves_multiset_helper(s2, i, j); + } + assert(s1.skip(j + 1).to_multiset() =~= s2.skip(j + 1).to_multiset()) by { + assert(s1.skip(j + 1) =~= s2.skip(j + 1)); + } + } + s2.take(j + 1).to_multiset().add(s2.skip(j + 1).to_multiset()); { + lemma_multiset_commutative(s2.take(j + 1), s2.skip(j + 1)); + assert(s2 =~= s2.take(j + 1) + s2.skip(j + 1)); + } + s2.to_multiset(); + } +} + +fn sort_seq(s: &Vec) -> (ret: Vec) + ensures + forall|i: int, j: int| 0 <= i < j < ret@.len() ==> ret@.index(i) <= ret@.index(j), + ret@.len() == s@.len(), + s@.to_multiset() == ret@.to_multiset(), +{ + let mut sorted = s.clone(); + let mut i: usize = 0; + while i < sorted.len() + invariant + i <= sorted.len(), + forall|j: int, k: int| 0 <= j < k < i ==> sorted@.index(j) <= sorted@.index(k), + s@.to_multiset() == sorted@.to_multiset(), + forall|j: int, k: int| + 0 <= j < i <= k < sorted@.len() ==> sorted@.index(j) <= sorted@.index(k), + sorted@.len() == s@.len(), + { + let mut min_index: usize = i; + let mut j: usize = i + 1; + while j < sorted.len() + invariant + i <= min_index < j <= sorted.len(), + forall|k: int| i <= k < j ==> sorted@.index(min_index as int) <= sorted@.index(k), + { + if sorted[j] < sorted[min_index] { + min_index = j; + } + j += 1; + } + if min_index != i { + let ghost old_sorted = sorted@; + let curr_val = sorted[i]; + let min_val = sorted[min_index]; + sorted.set(i, min_val); + + sorted.set(min_index, curr_val); + + proof { + swap_preserves_multiset(old_sorted, sorted@, i as int, min_index as int); + assert(old_sorted.to_multiset() =~= sorted@.to_multiset()); + } + } + i += 1; + } + sorted +} + +fn unique_sorted(s: Vec) -> (result: Vec) + requires + forall|i: int, j: int| 0 <= i < j < s.len() ==> s[i] <= s[j], + ensures + forall|i: int, j: int| 0 <= i < j < result.len() ==> result[i] < result[j], + forall|i: int| #![auto] 0 <= i < result.len() ==> s@.contains(result[i]), + forall|i: int| #![trigger s[i]] 0 <= i < s.len() ==> result@.contains(s[i]), +{ + let mut result: Vec = vec![]; + for i in 0..s.len() + invariant + forall|i: int, j: int| 0 <= i < j < s.len() ==> s[i] <= s[j], + forall|k: int, l: int| 0 <= k < l < result.len() ==> result[k] < result[l], + forall|k: int| + #![trigger result[k]] + 0 <= k < result.len() ==> (exists|m: int| 0 <= m < i && result[k] == s[m]), + forall|m: int| #![trigger s[m]] 0 <= m < i ==> result@.contains(s[m]), + { + let ghost pre = result; + if result.len() == 0 || result[result.len() - 1] != s[i] { + assert(result.len() == 0 || result[result.len() - 1] < s[i as int]); + result.push(s[i]); + assert forall|m: int| #![trigger s[m]] 0 <= m < i implies result@.contains(s[m]) by { + assert(pre@.contains(s@[m])); + lemma_seq_contains_after_push(pre@, s@[i as int], s@[m]); + }; + } + assert(forall|m: int| + #![trigger result@[m], pre@[m]] + 0 <= m < pre.len() ==> pre@.contains(result@[m]) ==> result@.contains(pre@[m])) by { + assert(forall|m: int| 0 <= m < pre.len() ==> result@[m] == pre@[m]); + } + assert(result@.contains(s[i as int])) by { + assert(result[result.len() - 1] == s[i as int]); + } + } + result +} + +fn unique(s: Vec) -> (result: Vec) + ensures + forall|i: int, j: int| 0 <= i < j < result.len() ==> result[i] < result[j], + forall|i: int| #![auto] 0 <= i < result.len() ==> s@.contains(result[i]), + forall|i: int| #![trigger s[i]] 0 <= i < s.len() ==> result@.contains(s[i]), +{ + let sorted = sort_seq(&s); + assert(forall|i: int| #![auto] 0 <= i < sorted.len() ==> s@.contains(sorted[i])) by { + assert(forall|i: int| + #![auto] + 0 <= i < sorted.len() ==> sorted@.to_multiset().contains(sorted[i])) by { + sorted@.to_multiset_ensures(); + } + assert(forall|i: int| + #![auto] + 0 <= i < sorted.len() ==> s@.to_multiset().contains(sorted[i])); + s@.to_multiset_ensures(); + } + assert(forall|i: int| #![trigger s[i]] 0 <= i < s.len() ==> sorted@.contains(s[i])) by { + assert(forall|i: int| #![auto] 0 <= i < s.len() ==> s@.to_multiset().contains(s[i])) by { + s@.to_multiset_ensures(); + } + assert(forall|i: int| #![auto] 0 <= i < s.len() ==> sorted@.to_multiset().contains(s[i])); + sorted@.to_multiset_ensures(); + } + unique_sorted(sorted) +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/035-max-element.rs b/benches/HumanEval-RustBench/035-max-element.rs new file mode 100644 index 0000000..5b6dda5 --- /dev/null +++ b/benches/HumanEval-RustBench/035-max-element.rs @@ -0,0 +1,26 @@ +use vstd::prelude::*; + +verus! { + +fn max_element(a: &Vec) -> (max: i32) + requires + a.len() > 0, + ensures + forall|i: int| 0 <= i < a.len() ==> a[i] <= max, + exists|i: int| 0 <= i < a.len() && a[i] == max, +{ + let mut max = a[0]; + for i in 1..a.len() + invariant + forall|j: int| 0 <= j < i ==> a[j] <= max, + exists|j: int| 0 <= j < i && a[j] == max, + { + if a[i] > max { + max = a[i]; + } + } + max +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/037-sort_even.rs b/benches/HumanEval-RustBench/037-sort_even.rs new file mode 100644 index 0000000..4cf1fe8 --- /dev/null +++ b/benches/HumanEval-RustBench/037-sort_even.rs @@ -0,0 +1,146 @@ +use vstd::prelude::*; + +verus! { +spec fn count(s: Seq, x: T) -> int + decreases s.len(), +{ + if s.len() == 0 { + 0 + } else { + count(s.skip(1), x) + if s[0] == x { + 1int + } else { + 0int + } + } +} +spec fn permutes(s1: Seq, s2: Seq) -> bool { + forall|x: T| count(s1, x) == count(s2, x) +} +proof fn lemma_update_effect_on_count(s: Seq, i: int, v: T, x: T) + requires + 0 <= i < s.len(), + ensures + count(s.update(i, v), x) == if v == x && s[i] != x { + count(s, x) + 1 + } else if v != x && s[i] == x { + count(s, x) - 1 + } else { + count(s, x) + }, + decreases s.len(), +{ + if s.len() == 0 { + return ; + } + if i == 0 { + assert(s.update(i, v) =~= seq![v] + s.skip(1)); + assert(s.update(i, v).skip(1) =~= s.skip(1)); + } else { + assert(s.update(i, v) =~= seq![s[0]] + s.skip(1).update(i - 1, v)); + assert(s.update(i, v).skip(1) =~= s.skip(1).update(i - 1, v)); + lemma_update_effect_on_count(s.skip(1), i - 1, v, x); + } +} +proof fn lemma_swapping_produces_a_permutation(s: Seq, i: int, j: int) + requires + 0 <= i < s.len(), + 0 <= j < s.len(), + ensures + permutes(s.update(i, s[j]).update(j, s[i]), s), +{ + assert forall|x: T| #[trigger] count(s.update(i, s[j]).update(j, s[i]), x) == count(s, x) by { + lemma_update_effect_on_count(s, i, s[j], x); + lemma_update_effect_on_count(s.update(i, s[j]), j, s[i], x); + } +} + +#[verifier::loop_isolation(false)] +fn sort_pred(l: Vec, p: Vec) -> (l_prime: Vec) + requires + l.len() == p.len(), + ensures + l_prime.len() == l.len(), + forall|i: int| 0 <= i < l.len() && !p[i] ==> l_prime[i] == l[i], + forall|i: int, j: int| + #![auto] + 0 <= i < j < l.len() && p[i] && p[j] ==> l_prime[i] <= l_prime[j], + permutes(l_prime@, l@), +{ + let ghost old_l = l@; + let l_len = l.len(); + let mut pos_replace: usize = 0; + let mut l_prime: Vec = l; + while pos_replace < l_len + invariant + l_len == l.len() == l_prime.len(), + forall|i: int| 0 <= i < l_len && !p[i] ==> l_prime[i] == l[i], + permutes(l_prime@, l@), + forall|i: int, j: int| + #![auto] + 0 <= i < pos_replace && i < j < l_len && p[i] && p[j] ==> l_prime[i] <= l_prime[j], + { + if p[pos_replace] { + let mut pos_cur: usize = pos_replace; + let mut pos: usize = pos_replace; + while pos < l_len + invariant + l_len == l.len() == l_prime.len(), + pos_replace <= pos, + pos_replace <= pos_cur < l_len, + p[pos_replace as int], + p[pos_cur as int], + forall|i: int| 0 <= i < l_len && !p[i] ==> l_prime[i] == l[i], + permutes(l_prime@, l@), + forall|i: int| + #![auto] + pos_replace <= i < pos && p[i] ==> l_prime[pos_cur as int] <= l_prime[i], + forall|i: int, j: int| + #![auto] + 0 <= i < pos_replace && i < j < l_len && p[i] && p[j] ==> l_prime[i] + <= l_prime[j], + { + if p[pos] && l_prime[pos] < l_prime[pos_cur] { + pos_cur = pos; + } + pos = pos + 1; + } + proof { + lemma_swapping_produces_a_permutation(l_prime@, pos_replace as int, pos_cur as int); + } + let v1 = l_prime[pos_replace]; + let v2 = l_prime[pos_cur]; + l_prime.set(pos_replace, v2); + l_prime.set(pos_cur, v1); + } + pos_replace = pos_replace + 1; + } + l_prime +} + +#[verifier::loop_isolation(false)] +fn sort_even(l: Vec) -> (result: Vec) + ensures + l.len() == result.len(), + permutes(result@, l@), + forall|i: int| 0 <= i < l.len() && i % 2 == 1 ==> result[i] == l[i], + forall|i: int, j: int| + #![auto] + 0 <= i < j < l.len() && i % 2 == 0 && j % 2 == 0 ==> result[i] <= result[j], +{ + let mut p: Vec = vec![]; + for i in 0..l.len() + invariant + p.len() == i, + forall|j: int| 0 <= j < i ==> p[j] == (j % 2 == 0), + { + p.push(i % 2 == 0); + } + assert(forall|i: int, j: int| + #![auto] + 0 <= i < j < l.len() && i % 2 == 0 && j % 2 == 0 ==> p[i] && p[j]); + sort_pred(l, p) +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/042-incr-list.rs b/benches/HumanEval-RustBench/042-incr-list.rs new file mode 100644 index 0000000..cf7de96 --- /dev/null +++ b/benches/HumanEval-RustBench/042-incr-list.rs @@ -0,0 +1,26 @@ +use vstd::prelude::*; + +verus! { + +fn incr_list(l: Vec) -> (result: Vec) + requires + forall|i: int| 0 <= i < l.len() ==> l[i] + 1 <= i32::MAX, + + ensures + result.len() == l.len(), + forall|i: int| 0 <= i < l.len() ==> #[trigger] result[i] == l[i] + 1, +{ + let mut result = Vec::with_capacity(l.len()); + for i in 0..l.len() + invariant + forall|i: int| 0 <= i < l.len() ==> l[i] + 1 <= i32::MAX, + result.len() == i, + forall|j: int| 0 <= j < i ==> #[trigger] result[j] == l[j] + 1, + { + result.push(l[i] + 1); + } + result +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/043-pairs-sum-to-zero.rs b/benches/HumanEval-RustBench/043-pairs-sum-to-zero.rs new file mode 100644 index 0000000..78381ce --- /dev/null +++ b/benches/HumanEval-RustBench/043-pairs-sum-to-zero.rs @@ -0,0 +1,41 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn pairs_sum_to_zero(nums: &[i32], target: i32) -> (found: bool) + requires + nums.len() >= 2, + forall|i: int, j: int| + 0 <= i < j < nums.len() ==> nums[i] + nums[j] <= i32::MAX && nums[i] + nums[j] + >= i32::MIN, + ensures + found <==> exists|i: int, j: int| 0 <= i < j < nums.len() && nums[i] + nums[j] == target, +{ + let mut i = 0; + + while i < nums.len() + invariant + 0 <= i <= nums.len(), + forall|u: int, v: int| 0 <= u < v < nums.len() && u < i ==> nums[u] + nums[v] != target, + { + let mut j = i + 1; + while j < nums.len() + invariant + 0 <= i < j <= nums.len(), + forall|u: int, v: int| + 0 <= u < v < nums.len() && u < i ==> nums[u] + nums[v] != target, + forall|u: int| i < u < j ==> nums[i as int] + nums[u] != target, + { + if nums[i] + nums[j] == target { + return true; + } + j = j + 1; + } + i = i + 1; + } + false +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/045-triangle_area.rs b/benches/HumanEval-RustBench/045-triangle_area.rs new file mode 100644 index 0000000..1a745d9 --- /dev/null +++ b/benches/HumanEval-RustBench/045-triangle_area.rs @@ -0,0 +1,24 @@ +use vstd::prelude::*; + +verus! { + +fn triangle_area(a: u64, h: u64) -> (area: u64) + requires + a > 0, + h > 0, + a * h / 2 <= u64::MAX + , + ensures + area == a * h / 2, +{ + if a % 2 == 0 { + assert(a % 2 == 0 ==> (a / 2) * h == a * h / 2) by (nonlinear_arith); + (a / 2) * h + } else { + assert(a % 2 == 1 ==> (a / 2) * h + (h / 2) == a * h / 2) by (nonlinear_arith); + (a / 2) * h + (h / 2) + } +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/048-is-palindrome.rs b/benches/HumanEval-RustBench/048-is-palindrome.rs new file mode 100644 index 0000000..34fa1fc --- /dev/null +++ b/benches/HumanEval-RustBench/048-is-palindrome.rs @@ -0,0 +1,24 @@ +use vstd::prelude::*; + +verus! { + +fn is_palindrome(text: &str) -> (result: bool) + ensures + result == forall|i: int| + 0 <= i < text@.len() ==> #[trigger] text@[i] == text@[text@.len() - 1 - i], +{ + let text_len: usize = text.unicode_len(); + for pos in 0..text_len / 2 + invariant + text_len == text@.len(), + forall|i: int| 0 <= i < pos ==> #[trigger] text@[i] == text@[text_len - 1 - i], + { + if text.get_char(pos) != text.get_char(text_len - 1 - pos) { + return false; + } + } + true +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/049-modp.rs b/benches/HumanEval-RustBench/049-modp.rs new file mode 100644 index 0000000..836e338 --- /dev/null +++ b/benches/HumanEval-RustBench/049-modp.rs @@ -0,0 +1,44 @@ +use vstd::prelude::*; + +verus! { + +spec fn modp_rec(n: nat, p: nat) -> nat + decreases n, +{ + if n == 0 { + 1nat % p + } else { + (modp_rec((n - 1) as nat, p) * 2) % p + } +} + +fn modmul(a: u32, b: u32, p: u32) -> (mul: u32) + by (nonlinear_arith) + requires + p > 0, + ensures + mul == ((a as int) * (b as int)) % (p as int), +{ + (((a as u64) * (b as u64)) % (p as u64)) as u32 +} + +#[verifier::loop_isolation(false)] +fn modp(n: u32, p: u32) -> (r: u32) + by (nonlinear_arith) + requires + p > 0, + ensures + r == modp_rec(n as nat, p as nat), +{ + let mut r = 1u32 % p; + for i in 0..n + invariant + r == modp_rec(i as nat, p as nat), + { + r = modmul(r, 2, p); + } + r +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/050-encode_shift.rs b/benches/HumanEval-RustBench/050-encode_shift.rs new file mode 100644 index 0000000..9fa06a2 --- /dev/null +++ b/benches/HumanEval-RustBench/050-encode_shift.rs @@ -0,0 +1,97 @@ +use vstd::prelude::*; + +verus! { + +spec fn encode_char_spec(c: int) -> int + recommends + 65 <= c <= 90, +{ + (c - 65 + 5) % 26 + 65 +} + +fn encode_char(c: u8) -> (r: u8) + requires + 65 <= c <= 90, + ensures + r == encode_char_spec(c as int), + 65 <= r <= 90, +{ + (c - 65 + 5) % 26 + 65 +} + +spec fn decode_char_spec(c: int) -> int + recommends + 65 <= c <= 90, +{ + (c - 65 + 26 - 5) % 26 + 65 +} + +fn decode_char(c: u8) -> (r: u8) + requires + 65 <= c <= 90, + ensures + r == decode_char_spec(c as int), + 65 <= r <= 90, +{ + (c - 65 + 26 - 5) % 26 + 65 +} + +proof fn opposite_encode_decode(c: int) + requires + 65 <= c <= 90, + ensures + encode_char_spec(decode_char_spec(c)) == c, + decode_char_spec(encode_char_spec(c)) == c, +{ +} + +#[verifier::loop_isolation(false)] +fn encode_shift(s: &Vec) -> (t: Vec) + requires + forall|i: int| #![trigger s[i]] 0 <= i < s.len() ==> 65 <= s[i] <= 90, + ensures + s.len() == t.len(), + forall|i: int| #![auto] 0 <= i < t.len() ==> t[i] == encode_char_spec(s[i] as int), + forall|i: int| #![auto] 0 <= i < t.len() ==> decode_char_spec(t[i] as int) == s[i], +{ + let mut t: Vec = vec![]; + for i in 0..s.len() + invariant + t.len() == i, + forall|j: int| #![auto] 0 <= j < i ==> t[j] == encode_char_spec(s[j] as int), + forall|j: int| #![auto] 0 <= j < i ==> decode_char_spec(t[j] as int) == s[j], + { + t.push(encode_char(s[i])); + proof { + opposite_encode_decode(s[i as int] as int); + } + } + t +} + +#[verifier::loop_isolation(false)] +fn decode_shift(s: &Vec) -> (t: Vec) + requires + forall|i: int| #![trigger s[i]] 0 <= i < s.len() ==> 65 <= s[i] <= 90, + ensures + s.len() == t.len(), + forall|i: int| #![auto] 0 <= i < t.len() ==> t[i] == decode_char_spec(s[i] as int), + forall|i: int| #![auto] 0 <= i < t.len() ==> encode_char_spec(t[i] as int) == s[i], +{ + let mut t: Vec = vec![]; + for i in 0..s.len() + invariant + t.len() == i, + forall|j: int| #![auto] 0 <= j < i ==> t[j] == decode_char_spec(s[j] as int), + forall|j: int| #![auto] 0 <= j < i ==> encode_char_spec(t[j] as int) == s[j], + { + t.push(decode_char(s[i])); + proof { + opposite_encode_decode(s[i as int] as int); + } + } + t +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/052-below-threshold.rs b/benches/HumanEval-RustBench/052-below-threshold.rs new file mode 100644 index 0000000..0beb0b1 --- /dev/null +++ b/benches/HumanEval-RustBench/052-below-threshold.rs @@ -0,0 +1,21 @@ +use vstd::prelude::*; + +verus! { + +fn below_threshold(l: &[i32], t: i32) -> (result: bool) + ensures + result == forall|i: int| 0 <= i < l.len() ==> l[i] < t, +{ + for i in 0..l.len() + invariant + forall|j: int| 0 <= j < i ==> l[j] < t, + { + if l[i] >= t { + return false; + } + } + true +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/053-add.rs b/benches/HumanEval-RustBench/053-add.rs new file mode 100644 index 0000000..12a09ea --- /dev/null +++ b/benches/HumanEval-RustBench/053-add.rs @@ -0,0 +1,13 @@ +use vstd::prelude::*; + +verus! { + +fn add(x: i32, y: i32) -> (res: Option) + ensures + res.is_some() ==> res.unwrap() == x + y, +{ + x.checked_add(y) +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/054-same-chars.rs b/benches/HumanEval-RustBench/054-same-chars.rs new file mode 100644 index 0000000..5ec16d8 --- /dev/null +++ b/benches/HumanEval-RustBench/054-same-chars.rs @@ -0,0 +1,89 @@ +use vstd::hash_set::HashSetWithView; +use vstd::prelude::*; +use vstd::std_specs::hash::axiom_u8_obeys_hash_table_key_model; + +verus! { + +broadcast use axiom_u8_obeys_hash_table_key_model; + +fn hash_set_from(s: &Vec) -> (res: HashSetWithView) + ensures + forall|i: int| #![auto] 0 <= i < s.len() ==> res@.contains(s[i]), + forall|x: int| + 0 <= x < 256 ==> #[trigger] res@.contains(x as u8) ==> #[trigger] s@.contains(x as u8), +{ + let mut res: HashSetWithView = HashSetWithView::new(); + for i in 0..s.len() + invariant + forall|j: int| #![auto] 0 <= j < i ==> res@.contains(s[j]), + forall|x: int| + 0 <= x < 256 ==> #[trigger] res@.contains(x as u8) ==> (exists|j: int| + 0 <= j < i && s[j] == x), + { + res.insert(s[i]); + } + res +} + +proof fn implies_contains(s0: Seq, s1: Seq, hs1: Set) + requires + forall|i: int| #![trigger s0[i]] 0 <= i < s0.len() ==> 0 <= s0[i] < 256, + forall|x: int| + 0 <= x < 256 ==> #[trigger] hs1.contains(x as u8) ==> #[trigger] s1.contains(x as u8), + ensures + forall|i: int| + #![auto] + 0 <= i < s0.len() && 0 <= s0[i] < 256 && hs1.contains(s0[i]) ==> s1.contains(s0[i]), +{ + assert forall|i: int| + #![auto] + 0 <= i < s0.len() && 0 <= s0[i] < 256 && hs1.contains(s0[i]) implies s1.contains(s0[i]) by { + let x = s0[i]; + assert(0 <= x < 256); + assert(hs1.contains(x as u8)); + assert(s1.contains(x as u8)); + }; +} + +#[verifier::loop_isolation(false)] +fn same_chars(s0: &Vec, s1: &Vec) -> (same: bool) + ensures + same <==> (forall|i: int| #![auto] 0 <= i < s0.len() ==> s1@.contains(s0[i])) && (forall| + i: int, + | + #![auto] + 0 <= i < s1.len() ==> s0@.contains(s1[i])), +{ + let hs0 = hash_set_from(s0); + let hs1 = hash_set_from(s1); + + proof { + implies_contains(s0@, s1@, hs1@); + implies_contains(s1@, s0@, hs0@); + } + + let mut contains_s0 = true; + for i in 0..s0.len() + invariant + contains_s0 <==> forall|j: int| #![auto] 0 <= j < i ==> s1@.contains(s0[j]), + { + if !hs1.contains(&s0[i]) { + contains_s0 = false; + assert(!s1@.contains(s0[i as int])); + } + } + let mut contains_s1 = true; + for i in 0..s1.len() + invariant + contains_s1 <==> forall|j: int| #![auto] 0 <= j < i ==> s0@.contains(s1[j]), + { + if !hs0.contains(&s1[i]) { + contains_s1 = false; + assert(!s0@.contains(s1[i as int])); + } + } + contains_s0 && contains_s1 +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/057-monotonic.rs b/benches/HumanEval-RustBench/057-monotonic.rs new file mode 100644 index 0000000..ec8fdcd --- /dev/null +++ b/benches/HumanEval-RustBench/057-monotonic.rs @@ -0,0 +1,37 @@ +use vstd::prelude::*; + +verus! { + +fn monotonic(l: Vec) -> (ret: bool) + ensures + ret <==> (forall|i: int, j: int| 0 <= i < j < l@.len() ==> l@.index(i) <= l@.index(j)) || ( + forall|i: int, j: int| 0 <= i < j < l@.len() ==> l@.index(i) >= l@.index(j)), +{ + if l.len() == 0 || l.len() == 1 { + return true; + } + let mut increasing = true; + let mut decreasing = true; + + let mut n = 0; + while n < l.len() - 1 + invariant + l.len() > 1, + n <= l.len() - 1, + increasing <==> forall|i: int, j: int| + 0 <= i < j < n + 1 ==> l@.index(i) <= l@.index(j), + decreasing <==> forall|i: int, j: int| + 0 <= i < j < n + 1 ==> l@.index(i) >= l@.index(j), + { + if l[n] < l[n + 1] { + decreasing = false; + } else if l[n] > l[n + 1] { + increasing = false; + } + n += 1; + } + increasing || decreasing +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/059-largest-prime-factor.rs b/benches/HumanEval-RustBench/059-largest-prime-factor.rs new file mode 100644 index 0000000..66de5cd --- /dev/null +++ b/benches/HumanEval-RustBench/059-largest-prime-factor.rs @@ -0,0 +1,62 @@ +use vstd::prelude::*; + +verus! { +spec fn spec_prime_helper(num: int, limit: int) -> bool { + forall|j: int| 2 <= j < limit ==> (#[trigger] (num % j)) != 0 +} + +spec fn spec_prime(num: int) -> bool { + spec_prime_helper(num, num) +} + +fn is_prime(num: u32) -> (result: bool) + requires + num >= 2, + ensures + result <==> spec_prime(num as int), +{ + let mut i = 2; + let mut result = true; + while i < num + invariant + 2 <= i <= num, + result <==> spec_prime_helper(num as int, i as int), + { + if num % i == 0 { + result = false; + } + i += 1; + } + result +} + +fn largest_prime_factor(n: u32) -> (largest: u32) + requires + n >= 2, + ensures + 1 <= largest <= n, + spec_prime(largest as int), +{ + let mut largest = 1; + let mut j = 1; + while j < n + invariant + 1 <= largest <= j <= n, + spec_prime(largest as int), + { + j += 1; + let flag = is_prime(j); + if n % j == 0 && flag { + largest = + if largest > j { + largest + } else { + j + }; + } + } + largest +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/060-sum_to_n.rs b/benches/HumanEval-RustBench/060-sum_to_n.rs new file mode 100644 index 0000000..984e35b --- /dev/null +++ b/benches/HumanEval-RustBench/060-sum_to_n.rs @@ -0,0 +1,35 @@ +use vstd::prelude::*; + +verus! { + +spec fn spec_sum_to_n(n: nat) -> nat + decreases n, +{ + if (n == 0) { + 0 + } else { + n + spec_sum_to_n((n - 1) as nat) + } +} + +fn sum_to_n(n: u32) -> (sum: Option) + ensures + sum.is_some() ==> sum.unwrap() == spec_sum_to_n(n as nat), +{ + let mut res: u32 = 0; + let mut sum: u32 = 0; + let mut i: u32 = 0; + while i < n + invariant + i <= n, + res == spec_sum_to_n(i as nat), + res <= u32::MAX, + { + i += 1; + res = i.checked_add(res)?; + } + Some(res) +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/062-derivative.rs b/benches/HumanEval-RustBench/062-derivative.rs new file mode 100644 index 0000000..b9748f6 --- /dev/null +++ b/benches/HumanEval-RustBench/062-derivative.rs @@ -0,0 +1,35 @@ +use vstd::prelude::*; + +verus! { + +fn derivative(xs: &Vec) -> (ret: Option>) + ensures + ret.is_some() ==> xs@.len() == 0 || xs@.map(|i: int, x| i * x).skip(1) + =~= ret.unwrap()@.map_values(|x| x as int), +{ + let mut ret = Vec::new(); + if xs.len() == 0 { + return Some(ret); + } + let mut i = 1; + while i < xs.len() + invariant + xs@.map(|i: int, x| i * x).subrange(1, i as int) =~= ret@.map_values(|x| x as int), + 1 <= i <= xs.len(), + { + ret.push(xs[i].checked_mul(i)?); + + let ghost prods = xs@.map(|i: int, x| i * x); + assert(prods.subrange(1, i as int).push(prods.index(i as int)) =~= prods.subrange( + 1, + i + 1 as int, + )); + + i += 1; + } + assert(xs@.map(|i: int, x| i * x).subrange(1, i as int) =~= xs@.map(|i: int, x| i * x).skip(1)); + Some(ret) +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/063-fibfib.rs b/benches/HumanEval-RustBench/063-fibfib.rs new file mode 100644 index 0000000..b0f010c --- /dev/null +++ b/benches/HumanEval-RustBench/063-fibfib.rs @@ -0,0 +1,32 @@ +use vstd::prelude::*; + +verus! { + +spec fn spec_fibfib(n: nat) -> nat + decreases n, +{ + if (n == 0) { + 0 + } else if (n == 1) { + 0 + } else if (n == 2) { + 1 + } else { + spec_fibfib((n - 1) as nat) + spec_fibfib((n - 2) as nat) + spec_fibfib((n - 3) as nat) + } +} + +fn fibfib(x: u32) -> (ret: Option) + ensures + ret.is_some() ==> spec_fibfib(x as nat) == ret.unwrap(), +{ + match (x) { + 0 => Some(0), + 1 => Some(0), + 2 => Some(1), + _ => fibfib(x - 1)?.checked_add(fibfib(x - 2)?)?.checked_add(fibfib(x - 3)?), + } +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/064-vowel_count.rs b/benches/HumanEval-RustBench/064-vowel_count.rs new file mode 100644 index 0000000..b278f25 --- /dev/null +++ b/benches/HumanEval-RustBench/064-vowel_count.rs @@ -0,0 +1,57 @@ +use vstd::prelude::*; + +verus! { + +spec fn is_vowel(c: char) -> bool { + c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'A' || c == 'E' || c == 'I' + || c == 'O' || c == 'U' +} + +spec fn vowels(s: Seq) -> Seq { + s.filter(|c| is_vowel(c)) +} + +fn vowels_count(s: &str) -> (ret: u32) + requires + s@.len() <= u32::MAX, + ensures + ret == vowels(s@).len() + if (s@.len() > 0 && (s@.last() == 'y' || s@.last() == 'Y')) { + 1int + + } else { + 0int + }, +{ + let mut ctr = 0; + let len = s.unicode_len(); + if len == 0 { + return ctr; + } + assert(len > 0); + let mut i = 0; + for i in 0..len + invariant + ctr == vowels(s@.subrange(0, i as int)).len(), + ctr <= i <= s@.len() == len <= u32::MAX, + ctr < u32::MAX || is_vowel(s@.last()), + { + let c = s.get_char(i); + reveal_with_fuel(Seq::filter, 2); + assert(s@.subrange(0, i + 1 as int).drop_last() =~= s@.subrange(0, i as int)); + if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'A' || c == 'E' || c + == 'I' || c == 'O' || c == 'U') { + ctr += 1; + } + } + assert(ctr == vowels(s@).len()) by { + assert(s@.subrange(0, len as int) =~= s@); + } + let c = s.get_char(len - 1); + if (c == 'y' || c == 'Y') { + ctr += 1 + } + ctr +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/068-pluck.rs b/benches/HumanEval-RustBench/068-pluck.rs new file mode 100644 index 0000000..d5532fa --- /dev/null +++ b/benches/HumanEval-RustBench/068-pluck.rs @@ -0,0 +1,55 @@ +use vstd::prelude::*; + +verus! { + +fn pluck_smallest_even(nodes: &Vec) -> (result: Vec) + requires + nodes@.len() <= u32::MAX, + ensures + result@.len() == 0 || result@.len() == 2, + result@.len() == 0 ==> forall|i: int| 0 <= i < nodes@.len() ==> nodes@[i] % 2 != 0, + result@.len() == 2 ==> { + let node = result@[0]; + let index = result@[1]; + &&& 0 <= index < nodes@.len() + &&& nodes@[index as int] == node + &&& node % 2 == 0 + &&& forall|i: int| + 0 <= i < nodes@.len() && nodes@[i] % 2 == 0 ==> node <= nodes@[i] && forall|i: int| + 0 <= i < result@[1] ==> nodes@[i] % 2 != 0 || nodes@[i] > node + }, +{ + let mut smallest_even: Option = None; + let mut smallest_index: Option = None; + + for i in 0..nodes.len() + invariant + 0 <= i <= nodes@.len(), + nodes@.len() <= u32::MAX, + smallest_even.is_none() == smallest_index.is_none(), + smallest_index.is_none() ==> forall|j: int| 0 <= j < i ==> nodes@[j] % 2 != 0, + smallest_index.is_some() ==> { + &&& 0 <= smallest_index.unwrap() < i as int + &&& nodes@[smallest_index.unwrap() as int] == smallest_even.unwrap() + &&& smallest_even.unwrap() % 2 == 0 + &&& forall|j: int| + 0 <= j < i ==> nodes@[j] % 2 == 0 ==> smallest_even.unwrap() <= nodes@[j] + &&& forall|j: int| + 0 <= j < smallest_index.unwrap() ==> nodes@[j] % 2 != 0 || nodes@[j] + > smallest_even.unwrap() + }, + { + if nodes[i] % 2 == 0 && (smallest_even.is_none() || nodes[i] < smallest_even.unwrap()) { + smallest_even = Some(nodes[i]); + smallest_index = Some((i as u32)); + } + } + if smallest_index.is_none() { + Vec::new() + } else { + vec![smallest_even.unwrap(), smallest_index.unwrap()] + } +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/070-strange_sort_list.rs b/benches/HumanEval-RustBench/070-strange_sort_list.rs new file mode 100644 index 0000000..bba839d --- /dev/null +++ b/benches/HumanEval-RustBench/070-strange_sort_list.rs @@ -0,0 +1,157 @@ +use vstd::calc; +use vstd::prelude::*; +use vstd::seq_lib::lemma_multiset_commutative; + +verus! { + +proof fn swap_preserves_multiset_helper(s: Seq, i: int, j: int) + requires + 0 <= i < j < s.len(), + ensures + (s.take(j + 1)).to_multiset() =~= s.take(i).to_multiset().add( + s.subrange(i + 1, j).to_multiset(), + ).insert(s.index(j)).insert(s.index(i)), +{ + let fst = s.take(i); + let snd = s.subrange(i + 1, j); + + assert((s.take(j + 1)).to_multiset() =~= fst.to_multiset().insert(s.index(i)).add( + snd.to_multiset().insert(s.index(j)), + )) by { + assert(s.take(i + 1).to_multiset() =~= fst.to_multiset().insert(s.index(i))) by { + fst.to_multiset_ensures(); + assert(fst.push(s.index(i)) =~= s.take(i + 1)); + } + assert(s.subrange(i + 1, j + 1).to_multiset() =~= snd.to_multiset().insert(s.index(j))) by { + snd.to_multiset_ensures(); + assert(snd.push(s.index(j)) =~= s.subrange(i + 1, j + 1)); + } + lemma_multiset_commutative(s.take(i + 1), s.subrange(i + 1, j + 1)); + assert(s.take(i + 1) + s.subrange(i + 1, j + 1) =~= s.take(j + 1)); + } +} +proof fn swap_preserves_multiset(s1: Seq, s2: Seq, i: int, j: int) + requires + 0 <= i < j < s1.len() == s2.len(), + forall|x: int| 0 <= x < s1.len() && x != i && x != j ==> s1.index(x) == s2.index(x), + s1.index(i) == s2.index(j), + s1.index(j) == s2.index(i), + ensures + s1.to_multiset() == s2.to_multiset(), +{ + calc! { + (==) + s1.to_multiset(); { + lemma_multiset_commutative(s1.take(j + 1), s1.skip(j + 1)); + assert(s1 =~= s1.take(j + 1) + s1.skip(j + 1)); + } + s1.take(j + 1).to_multiset().add(s1.skip(j + 1).to_multiset()); { + assert(s1.take(j + 1).to_multiset() =~= s2.take(j + 1).to_multiset()) by { + assert(s1.take(i) == s2.take(i)); + assert(s1.subrange(i + 1, j) =~= (s2.subrange(i + 1, j))); + swap_preserves_multiset_helper(s1, i, j); + swap_preserves_multiset_helper(s2, i, j); + } + assert(s1.skip(j + 1).to_multiset() =~= s2.skip(j + 1).to_multiset()) by { + assert(s1.skip(j + 1) =~= s2.skip(j + 1)); + } + } + s2.take(j + 1).to_multiset().add(s2.skip(j + 1).to_multiset()); { + lemma_multiset_commutative(s2.take(j + 1), s2.skip(j + 1)); + assert(s2 =~= s2.take(j + 1) + s2.skip(j + 1)); + } + s2.to_multiset(); + } +} + +fn sort_seq(s: &Vec) -> (ret: Vec) + ensures + forall|i: int, j: int| 0 <= i < j < ret@.len() ==> ret@.index(i) <= ret@.index(j), + ret@.len() == s@.len(), + s@.to_multiset() == ret@.to_multiset(), +{ + let mut sorted = s.clone(); + let mut i: usize = 0; + while i < sorted.len() + invariant + i <= sorted.len(), + forall|j: int, k: int| 0 <= j < k < i ==> sorted@.index(j) <= sorted@.index(k), + s@.to_multiset() == sorted@.to_multiset(), + forall|j: int, k: int| + 0 <= j < i <= k < sorted@.len() ==> sorted@.index(j) <= sorted@.index(k), + sorted@.len() == s@.len(), + { + let mut min_index: usize = i; + let mut j: usize = i + 1; + while j < sorted.len() + invariant + i <= min_index < j <= sorted.len(), + forall|k: int| i <= k < j ==> sorted@.index(min_index as int) <= sorted@.index(k), + { + if sorted[j] < sorted[min_index] { + min_index = j; + } + j += 1; + } + if min_index != i { + let ghost old_sorted = sorted@; + let curr_val = sorted[i]; + let min_val = sorted[min_index]; + sorted.set(i, min_val); + + sorted.set(min_index, curr_val); + + proof { + swap_preserves_multiset(old_sorted, sorted@, i as int, min_index as int); + assert(old_sorted.to_multiset() =~= sorted@.to_multiset()); + } + } + i += 1; + } + sorted +} +fn strange_sort_list_helper(s: &Vec) -> (ret: (Vec, Vec)) + ensures + s@.to_multiset() == (ret.0)@.to_multiset(), + s@.len() == (ret.0)@.len() == (ret.1)@.len(), + forall|i: int| + 0 <= i < s@.len() && i % 2 == 0 ==> (ret.1)@.index(i) == (ret.0)@.index(i / 2), + forall|i: int| + 0 <= i < s@.len() && i % 2 == 1 ==> (ret.1)@.index(i) == (ret.0)@.index( + s@.len() - (i - 1) / 2 - 1, + ), +{ + let sorted = sort_seq(s); + let mut strange = Vec::new(); + let mut i: usize = 0; + while i < sorted.len() + invariant + i <= sorted.len() == s@.len(), + strange@.len() == i, + forall|j: int| 0 <= j < i && j % 2 == 0 ==> strange@.index(j) == sorted@.index(j / 2), + forall|j: int| + 0 < j < i && j % 2 == 1 ==> strange@.index(j) == sorted@.index( + sorted@.len() - (j / 2) - 1, + ), + { + if i % 2 == 0 { + strange.push(sorted[i / 2]); + } else { + let r = (i - 1) / 2; + strange.push(sorted[s.len() - r - 1]); + } + i += 1; + } + (sorted, strange) +} + +fn strange_sort_list(s: &Vec) -> (ret: Vec) + ensures + s@.len() == ret@.len(), +{ + let (_, strange) = strange_sort_list_helper(s); + strange +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/072-will_it_fly.rs b/benches/HumanEval-RustBench/072-will_it_fly.rs new file mode 100644 index 0000000..7becaf3 --- /dev/null +++ b/benches/HumanEval-RustBench/072-will_it_fly.rs @@ -0,0 +1,124 @@ +use vstd::prelude::*; + +verus! { +proof fn lemma_increasing_sum_params(s: Seq, i: int, j: int) + requires + 0 <= i <= j <= s.len(), + ensures + spec_sum(s.subrange(0, i)) <= spec_sum(s.subrange(0, j)), + decreases j - i, +{ + if (i < j) { + assert(spec_sum(s.subrange(0, j - 1)) <= spec_sum(s.subrange(0, j))) by { + assert(s.subrange(0, j).drop_last() == s.subrange(0, j - 1)); + } + lemma_increasing_sum_params(s, i, j - 1); + } +} + +proof fn lemma_increasing_sum(s: Seq) + ensures + forall|i: int, j: int| + #![trigger spec_sum(s.subrange(0, i)), spec_sum(s.subrange(0, j))] + 0 <= i <= j <= s.len() ==> spec_sum(s.subrange(0, i)) <= spec_sum(s.subrange(0, j)), +{ + assert forall|i: int, j: int| + #![trigger spec_sum(s.subrange(0, i)), spec_sum(s.subrange(0, j))] + 0 <= i <= j <= s.len() ==> spec_sum(s.subrange(0, i)) <= spec_sum(s.subrange(0, j)) by { + if (0 <= i <= j <= s.len()) { + lemma_increasing_sum_params(s, i, j); + } + } +} + +spec fn spec_sum(s: Seq) -> int { + s.fold_left(0, |x: int, y| x + y) +} + +fn sum_lesser_than_limit(qs: &Vec, w: u32) -> (ret: bool) + ensures + ret <==> spec_sum(qs@) <= w, +{ + let mut sum: u32 = 0; + for i in 0..qs.len() + invariant + sum == spec_sum(qs@.subrange(0, i as int)), + i <= qs.len(), + sum <= w, + { + proof { + assert(spec_sum(qs@.subrange(0, i + 1)) <= spec_sum(qs@)) by { + assert(qs@ == qs@.subrange(0, qs@.len() as int)); + lemma_increasing_sum(qs@); + } + assert(spec_sum(qs@.subrange(0, i as int)) + qs[i as int] == spec_sum( + qs@.subrange(0, i + 1), + )) by { + assert(qs@.subrange(0, i + 1).drop_last() == qs@.subrange(0, i as int)); + } + } + let sum_opt = sum.checked_add(qs[i]); + if sum_opt.is_none() { + assert(spec_sum(qs@.subrange(0, i + 1)) > u32::MAX >= w); + return false; + } else { + sum = sum_opt.unwrap(); + if sum > w { + assert(spec_sum(qs@.subrange(0, i + 1)) > w); + return false; + } + } + } + assume(sum == spec_sum(qs@)); + true +} + +fn palindrome(qs: &Vec) -> (ret: bool) + ensures + ret <==> qs@ =~= qs@.reverse(), +{ + let mut ret = true; + let mut i: usize = 0; + while i < qs.len() / 2 + invariant + i <= qs@.len() / 2, + ret <==> qs@.subrange(0, i as int) =~= qs@.subrange( + qs@.len() - i, + qs@.len() as int, + ).reverse(), + { + assert(qs@.subrange(qs@.len() - (i + 1), qs@.len() as int).reverse().drop_last() + =~= qs@.subrange(qs@.len() - i, qs@.len() as int).reverse()); + assert(qs@.subrange(qs@.len() - (i + 1), qs@.len() as int).reverse() =~= qs@.subrange( + qs@.len() - i, + qs@.len() as int, + ).reverse().push(qs@.index(qs@.len() - (i + 1)))); + if qs[i] != qs[qs.len() - i - 1] { + ret = false; + } + i += 1; + } + let ghost fst_half = qs@.subrange(0, (qs@.len() / 2) as int); + let ghost snd_half = qs@.subrange(qs@.len() - qs@.len() / 2, qs@.len() as int); + proof { + if (qs.len() % 2) == 1 { + assert(qs@ =~= fst_half + qs@.subrange( + (qs@.len() / 2) as int, + qs@.len() - qs@.len() / 2, + ) + snd_half); + } else { + assert(qs@ =~= fst_half + snd_half); + } + } + ret +} + +fn will_it_fly(qs: &Vec, w: u32) -> (ret: bool) + ensures + ret <==> qs@ =~= qs@.reverse() && spec_sum(qs@) <= w, +{ + palindrome(qs) && sum_lesser_than_limit(qs, w) +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/073-smallest_change.rs b/benches/HumanEval-RustBench/073-smallest_change.rs new file mode 100644 index 0000000..911e1b9 --- /dev/null +++ b/benches/HumanEval-RustBench/073-smallest_change.rs @@ -0,0 +1,50 @@ +use vstd::prelude::*; + +verus! { + +spec fn zip_halves(v: Seq) -> (ret: Seq<(T, T)>) { + v.take((v.len() / 2) as int).zip_with(v.skip(((v.len() + 1) / 2) as int).reverse()) +} + +spec fn diff(s: Seq<(i32, i32)>) -> int { + s.fold_left( + 0, + |acc: int, x: (i32, i32)| + if (x.0 != x.1) { + acc + 1 + } else { + acc + }, + ) +} + +fn smallest_change(v: Vec) -> (change: usize) + requires + v@.len() < usize::MAX, + ensures + change == diff(zip_halves(v@)), +{ + let mut ans: usize = 0; + let ghost zipped = Seq::<(i32, i32)>::empty(); + for i in 0..v.len() / 2 + invariant + ans <= i <= v@.len() / 2 < usize::MAX, + ans == diff(zipped), + zipped =~= zip_halves(v@).take(i as int), + { + proof { + let ghost pair = (v[i as int], v[v.len() - i - 1]); + let ghost zipped_old = zipped; + zipped = zipped.push(pair); + assert(zipped.drop_last() =~= zipped_old); + } + if v[i] != v[v.len() - i - 1] { + ans += 1; + } + } + assert(zip_halves(v@).take((v@.len() / 2) as int) =~= zip_halves(v@)); + ans +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/074-total_match.rs b/benches/HumanEval-RustBench/074-total_match.rs new file mode 100644 index 0000000..6858cf2 --- /dev/null +++ b/benches/HumanEval-RustBench/074-total_match.rs @@ -0,0 +1,87 @@ +use vstd::prelude::*; + +verus! { + +spec fn spec_sum(s: Seq) -> int { + s.fold_left(0, |x: int, y| x + y) +} +proof fn lemma_increasing_sum(s: Seq, i: int, j: int) + requires + 0 <= i <= j <= s.len(), + ensures + spec_sum(s.subrange(0, i)) <= spec_sum(s.subrange(0, j)), + decreases j - i, +{ + if (i < j) { + assert(spec_sum(s.subrange(0, j - 1)) <= spec_sum(s.subrange(0, j))) by { + assert(s.subrange(0, j).drop_last() == s.subrange(0, j - 1)); + } + lemma_increasing_sum(s, i, j - 1); + } +} + +spec fn total_str_len(strings: Seq<&str>) -> int { + spec_sum(strings.map_values(|s: &str| s@.len())) +} + +fn checked_total_str_len(lst: &Vec<&str>) -> (ret: Option) + ensures + ret.is_some() <==> total_str_len(lst@) <= usize::MAX, + ret.is_some() <==> ret.unwrap() == total_str_len(lst@), +{ + let ghost lens = Seq::::empty(); + let mut sum: usize = 0; + for i in 0..lst.len() + invariant + sum == lst@.subrange(0, i as int).map_values(|s: &str| s@.len()).fold_left( + 0, + |x: int, y| x + y, + ), + spec_sum(lens) == sum, + lens =~= lst@.map_values(|s: &str| s@.len()).take(i as int), + lens =~= lst@.take(i as int).map_values(|s: &str| s@.len()), + { + let x = lst[i].unicode_len(); + proof { + assert(lens.push(x as nat).drop_last() == lens); + lens = lens.push(x as nat); + assert(lens =~= lst@.map_values(|s: &str| s@.len()).take(i + 1)); + + lemma_increasing_sum(lst@.map_values(|s: &str| s@.len()), i + 1, lst@.len() as int); + assert(total_str_len(lst@) >= spec_sum(lens)) by { + assert(lst@.map_values(|s: &str| s@.len()) =~= lst@.map_values( + |s: &str| s@.len(), + ).take(lst@.len() as int)); + } + if x + sum > usize::MAX { + assert(sum.checked_add(x).is_none()); + assert(total_str_len(lst@) > usize::MAX); + } + } + sum = sum.checked_add(x)?; + assert(lst@.take(i + 1).map_values(|s: &str| s@.len()).drop_last() == lst@.take( + i as int, + ).map_values(|s: &str| s@.len())); + } + assert(lst@ == lst@.subrange(0, lst.len() as int)); + return Some(sum); +} + +fn total_match<'a>(lst1: Vec<&'a str>, lst2: Vec<&'a str>) -> (ret: Option>) + ensures + ret.is_some() <== total_str_len(lst1@) <= usize::MAX && total_str_len(lst2@) <= usize::MAX, + ret.is_some() ==> ret.unwrap() == if total_str_len(lst1@) <= total_str_len(lst2@) { + lst1 + } else { + lst2 + }, +{ + if checked_total_str_len(&lst1)? <= checked_total_str_len(&lst2)? { + Some(lst1) + } else { + Some(lst2) + } +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/075-is_multiply_prime.rs b/benches/HumanEval-RustBench/075-is_multiply_prime.rs new file mode 100644 index 0000000..388a121 --- /dev/null +++ b/benches/HumanEval-RustBench/075-is_multiply_prime.rs @@ -0,0 +1,121 @@ +use vstd::arithmetic::mul::*; +use vstd::prelude::*; + +verus! { + +spec fn spec_prime(p: int) -> bool { + p > 1 && forall|k: int| 1 < k < p ==> #[trigger] (p % k) != 0 +} + +fn prime(p: u32) -> (ret: bool) + ensures + ret <==> spec_prime(p as int), +{ + if p <= 1 { + return false; + } + for k in 2..p + invariant + forall|j: int| 1 < j < k ==> #[trigger] (p as int % j) != 0, + k <= p, + { + if p % k == 0 { + return false; + } + } + true +} + +fn checked_mul_thrice(x: u32, y: u32, z: u32) -> (ret: Option) + ensures + ret.is_some() ==> ret.unwrap() == x * y * z, + ret.is_none() ==> x * y * z > u32::MAX, +{ + if (x == 0 || y == 0 || z == 0) { + return Some(0); + } + assert(x > 0 && y > 0 && z > 0); + let prod2 = x.checked_mul(y); + if prod2.is_some() { + let prod3 = prod2.unwrap().checked_mul(z); + if prod3.is_some() { + let ans = prod3.unwrap(); + assert(ans == x * y * z); + Some(ans) + } else { + assert(x * y * z > u32::MAX); + None + } + } else { + broadcast use group_mul_properties; + + assert(x * y * z >= y * z); + None + } +} + +fn is_multiply_prime(x: u32) -> (ans: bool) + requires + x > 1, + ensures + ans <==> exists|a: int, b: int, c: int| + spec_prime(a) && spec_prime(b) && spec_prime(c) && x == a * b * c, +{ + let mut a = 1; + while a < x + invariant + forall|i: int, j: int, k: int| + (spec_prime(i) && spec_prime(j) && spec_prime(k) && i <= a && j <= x && k <= x) + ==> x != i * j * k, + a <= x, + { + a += 1; + if prime(a) { + let mut b = 1; + while b < x + invariant + forall|j: int, k: int| + (spec_prime(j) && spec_prime(k) && j <= b && k <= x) ==> x != (a as int) * j + * k, + spec_prime(a as int), + a <= x, + b <= x, + { + b += 1; + if prime(b) { + let mut c = 1; + while c < x + invariant + forall|k: int| (spec_prime(k) && k <= c as int) ==> x != a * b * k, + spec_prime(a as int), + spec_prime(b as int), + a <= x, + b <= x, + c <= x, + { + c += 1; + let prod = checked_mul_thrice(a, b, c); + if prime(c) && prod.is_some() && x == prod.unwrap() { + return true; + } + } + } + } + } + } + assert(forall|i: int, j: int, k: int| + i <= x && j <= x && k <= x && spec_prime(i) && spec_prime(j) && spec_prime(k) ==> x != i * j + * k); + assert forall|i: int, j: int, k: int| + spec_prime(i) && spec_prime(j) && spec_prime(k) ==> x != i * j * k by { + if (i > 1 && j > 1 && k > 1 && (i > x || j > x || k > x)) { + broadcast use group_mul_properties; + + assert(i * j * k > x); + } + } + false +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/076-is_simple_power.rs b/benches/HumanEval-RustBench/076-is_simple_power.rs new file mode 100644 index 0000000..2c18d2a --- /dev/null +++ b/benches/HumanEval-RustBench/076-is_simple_power.rs @@ -0,0 +1,37 @@ +use vstd::arithmetic::logarithm::log; +use vstd::arithmetic::power::pow; +use vstd::prelude::*; +verus! { +#[verifier::external_fn_specification] +pub fn ex_ilog(x: u32, base: u32) -> (ret: u32) + requires + x > 0, + base > 1, + ensures + ret == log(base as int, x as int), +{ + x.ilog(base) +} + +#[verifier::external_fn_specification] +pub fn ex_checked_pow(x: u32, exp: u32) -> (ret: Option) + ensures + ret.is_some() <==> ret.unwrap() == pow(x as int, exp as nat), + ret.is_none() <==> pow(x as int, exp as nat) > u32::MAX, +{ + x.checked_pow(exp) +} + +fn is_simple_power(x: u32, n: u32) -> (ret: bool) + requires + x > 0, + n > 1, + ensures + ret <==> x == pow(n as int, log(n as int, x as int) as nat), +{ + let maybe_x = n.checked_pow(x.ilog(n)); + return maybe_x.is_some() && maybe_x.unwrap() == x; +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/077-is_cube.rs b/benches/HumanEval-RustBench/077-is_cube.rs new file mode 100644 index 0000000..ca0fe21 --- /dev/null +++ b/benches/HumanEval-RustBench/077-is_cube.rs @@ -0,0 +1,131 @@ +use vstd::arithmetic::mul::*; +use vstd::math::abs; +use vstd::prelude::*; + +verus! { + +proof fn lemma_cube_increases_helper(i: int) + ensures + i >= 0 ==> (i * i * i) <= (i + 1) * (i + 1) * (i + 1), +{ + broadcast use group_mul_properties; + + if (i > 0) { + assert((i + 1) * (i + 1) * (i + 1) == i * i * i + 3 * i * i + 3 * i + 1); + assert(i * i * i + 3 * i * i + 3 * i + 1 > i * i * i); + } +} + +proof fn lemma_cube_increases_params(i: int, j: int) + ensures + 0 <= i <= j ==> (i * i * i) <= (j * j * j), + decreases j - i, +{ + if (i == j) { + } + else if (i < j) { + lemma_cube_increases_params(i, j - 1); + lemma_cube_increases_helper(j - 1); + + } +} + +proof fn lemma_cube_increases() + ensures + forall|i: int, j: int| 0 <= i <= j ==> #[trigger] (i * i * i) <= #[trigger] (j * j * j), +{ + assert forall|i: int, j: int| + 0 <= i <= j ==> #[trigger] (i * i * i) <= #[trigger] (j * j * j) by { + lemma_cube_increases_params(i, j); + } +} + +fn checked_cube(x: i32) -> (ret: Option) + requires + x >= 0, + ensures + ret.is_some() ==> ret.unwrap() == x * x * x, + ret.is_none() ==> x * x * x > i32::MAX, +{ + if x == 0 { + return Some(0); + } + let sqr = x.checked_mul(x); + if sqr.is_some() { + let cube = sqr.unwrap().checked_mul(x); + if cube.is_some() { + let ans = cube.unwrap(); + assert(ans == x * x * x); + Some(ans) + } else { + assert(x * x * x > i32::MAX); + None + } + } else { + assert(x > 0); + assert(x * x > i32::MAX); + proof { + lemma_mul_increases(x as int, x * x); + } + assert(x * x * x >= x * x); + None + } +} + +#[verifier::external_fn_specification] +pub fn ex_abs(x: i32) -> (ret: i32) + requires + x != i32::MIN, + + ensures + ret == abs(x as int), +{ + x.abs() +} + +fn is_cube(x: i32) -> (ret: bool) + requires + x != i32::MIN, + + ensures + ret <==> exists|i: int| 0 <= i && abs(x as int) == #[trigger] (i * i * i), +{ + let x_abs = x.abs(); + if x_abs == 0 { + assert(abs(x as int) == 0 * 0 * 0); + return true; + } else if (x_abs == 1) { + assert(abs(x as int) == 1 * 1 * 1); + return true; + } + assert(-1 > x || x > 1); + let mut i = 2; + while i < x_abs + invariant + forall|j: int| 2 <= j < i ==> abs(x as int) != #[trigger] (j * j * j), + 2 <= i <= abs(x as int) == x_abs, + { + let prod = checked_cube(i); + if prod.is_some() && prod.unwrap() == x.abs() { + return true; + } + i += 1; + } + assert(forall|j: int| 2 <= j ==> abs(x as int) != #[trigger] (j * j * j)) by { + assert(forall|j: int| 2 <= j < i ==> abs(x as int) != #[trigger] (j * j * j)); + + assert(forall|j: int| i <= j ==> abs(x as int) < #[trigger] (j * j * j)) by { + assert(abs(x as int) < #[trigger] (i * i * i)) by { + broadcast use group_mul_properties; + + assert(i <= i * i <= i * i * i); + } + lemma_cube_increases(); + assert(forall|j: int| i <= j ==> (i * i * i) <= #[trigger] (j * j * j)); + } + } + false +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/080-is_happy.rs b/benches/HumanEval-RustBench/080-is_happy.rs new file mode 100644 index 0000000..803cd6c --- /dev/null +++ b/benches/HumanEval-RustBench/080-is_happy.rs @@ -0,0 +1,45 @@ +use vstd::prelude::*; + +verus! { + +spec fn three_distinct_spec(s: Seq, i: int) -> bool + recommends + 0 < i && i + 1 < s.len(), +{ + (s[i - 1] != s[i]) && (s[i] != s[i + 1]) && (s[i] != s[i + 1]) +} + +fn three_distinct(s: &Vec, i: usize) -> (is: bool) + requires + 0 < i && i + 1 < s.len(), + ensures + is <==> three_distinct_spec(s@, i as int), +{ + (s[i - 1] != s[i]) && (s[i] != s[i + 1]) && (s[i] != s[i + 1]) +} + +spec fn happy_spec(s: Seq) -> bool { + s.len() >= 3 && (forall|i: int| 0 < i && i + 1 < s.len() ==> three_distinct_spec(s, i)) +} + +#[verifier::loop_isolation(false)] +fn is_happy(s: &Vec) -> (happy: bool) + ensures + happy <==> happy_spec(s@), +{ + if s.len() < 3 { + return false; + } + for i in 1..(s.len() - 1) + invariant + forall|j: int| 0 < j < i ==> three_distinct_spec(s@, j), + { + if !three_distinct(s, i) { + return false; + } + } + return true; +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/134-check_if_last_char_is_a_letter.rs b/benches/HumanEval-RustBench/134-check_if_last_char_is_a_letter.rs new file mode 100644 index 0000000..2d148e7 --- /dev/null +++ b/benches/HumanEval-RustBench/134-check_if_last_char_is_a_letter.rs @@ -0,0 +1,40 @@ +use vstd::prelude::*; + +verus! { + +pub spec fn is_alphabetic(c: char) -> (result: bool); + +#[verifier::external_fn_specification] +#[verifier::when_used_as_spec(is_alphabetic)] +pub fn ex_is_alphabetic(c: char) -> (result: bool) + ensures + result <==> (c.is_alphabetic()), +{ + c.is_alphabetic() +} + +pub spec fn is_whitespace(c: char) -> (result: bool); + +#[verifier::external_fn_specification] +#[verifier::when_used_as_spec(is_whitespace)] +pub fn ex_is_whitespace(c: char) -> (result: bool) + ensures + result <==> (c.is_whitespace()), +{ + c.is_whitespace() +} + +fn check_if_last_char_is_a_letter(txt: &str) -> (result: bool) + ensures + result <==> (txt@.len() > 0 && txt@.last().is_alphabetic() && (txt@.len() == 1 + || txt@.index(txt@.len() - 2).is_whitespace())), +{ + let len = txt.unicode_len(); + if len == 0 { + return false; + } + txt.get_char(len - 1).is_alphabetic() && (len == 1 || txt.get_char(len - 2).is_whitespace()) +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/136-largest_smallest_integers.rs b/benches/HumanEval-RustBench/136-largest_smallest_integers.rs new file mode 100644 index 0000000..d6c8f66 --- /dev/null +++ b/benches/HumanEval-RustBench/136-largest_smallest_integers.rs @@ -0,0 +1,46 @@ +use vstd::prelude::*; + +verus! { + +fn largest_smallest_integers(arr: &Vec) -> (res: (Option, Option)) + ensures + ({ + let a = res.0; + let b = res.1; + &&& a.is_none() ==> forall|i: int| 0 <= i < arr@.len() ==> arr@[i] >= 0 + &&& a.is_some() ==> arr@.contains(a.unwrap()) && a.unwrap() < 0 + &&& a.is_some() ==> forall|i: int| + 0 <= i < arr@.len() && arr@[i] < 0 ==> arr@[i] <= a.unwrap() + &&& b.is_none() ==> forall|i: int| 0 <= i < arr@.len() ==> arr@[i] <= 0 + &&& b.is_some() ==> arr@.contains(b.unwrap()) && b.unwrap() > 0 + &&& b.is_some() ==> forall|i: int| + 0 <= i < arr@.len() && arr@[i] > 0 ==> arr@[i] >= b.unwrap() + }), +{ + let mut i: usize = 0; + let mut a = None; + let mut b = None; + + while i < arr.len() + invariant + 0 <= i <= arr@.len(), + a.is_none() ==> forall|j: int| 0 <= j < i ==> arr@[j] >= 0, + a.is_some() ==> arr@.contains(a.unwrap()) && a.unwrap() < 0, + a.is_some() ==> forall|j: int| 0 <= j < i && arr@[j] < 0 ==> arr@[j] <= a.unwrap(), + b.is_none() ==> forall|j: int| 0 <= j < i ==> arr@[j] <= 0, + b.is_some() ==> arr@.contains(b.unwrap()) && b.unwrap() > 0, + b.is_some() ==> forall|j: int| 0 <= j < i && arr@[j] > 0 ==> arr@[j] >= b.unwrap(), + { + if arr[i] < 0 && (a.is_none() || arr[i] >= a.unwrap()) { + a = Some(arr[i]); + } + if arr[i] > 0 && (b.is_none() || arr[i] <= b.unwrap()) { + b = Some(arr[i]); + } + i = i + 1; + } + (a, b) +} + +} +fn main() {} diff --git a/benches/HumanEval-RustBench/abs.rs b/benches/HumanEval-RustBench/abs.rs new file mode 100644 index 0000000..b33282e --- /dev/null +++ b/benches/HumanEval-RustBench/abs.rs @@ -0,0 +1,26 @@ +use vstd::prelude::*; + +verus! { + +fn abs(x: i32) -> (result: i32) + // pre-conditions-start + requires + x != i32::MIN, + // pre-conditions-end + // post-conditions-start + ensures + result >= 0, + result == x || result == -x, + // post-conditions-end +{ + // impl-start + if x < 0 { + -x + } else { + x + } + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/arithmetic_weird.rs b/benches/HumanEval-RustBench/arithmetic_weird.rs new file mode 100644 index 0000000..2ba2848 --- /dev/null +++ b/benches/HumanEval-RustBench/arithmetic_weird.rs @@ -0,0 +1,29 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn arithmetic_weird() -> (result: i32) + // post-conditions-start + ensures + result < 10 + // post-conditions-end +{ + // impl-start + let mut x = 0; + let mut y = 0; + while x <= 10 + // invariants-start + invariant + (x == 0 && y == 0) || y == 10 - x + 1 + // invariants-end + { + y = 10 - x; + x = x + 1; + } + y + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/array_append.rs b/benches/HumanEval-RustBench/array_append.rs new file mode 100644 index 0000000..3fe6e57 --- /dev/null +++ b/benches/HumanEval-RustBench/array_append.rs @@ -0,0 +1,33 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn array_append(a: Vec, b: i32) -> (result: Vec) + // post-conditions-start + ensures + result.len() == a.len() + 1, + forall|i: int| #![auto] 0 <= i && i < result.len() ==> result[i] == (if i < a.len() { a[i] } else { b }), + // post-conditions-end +{ + // impl-start + let mut result: Vec = Vec::new(); + let mut i = 0; + while i < a.len() + // invariants-start + invariant + 0 <= i && i <= a.len(), + result.len() == i, + forall|j: int| 0 <= j && j < i ==> result[j] == a[j], + // invariants-end + { + result.push(a[i]); + i = i + 1; + } + result.push(b); + result + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/array_concat.rs b/benches/HumanEval-RustBench/array_concat.rs new file mode 100644 index 0000000..102c16e --- /dev/null +++ b/benches/HumanEval-RustBench/array_concat.rs @@ -0,0 +1,47 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn array_concat(a: Vec, b: Vec) -> (result: Vec) + // post-conditions-start + ensures + result.len() == a.len() + b.len(), + forall|i: int| 0 <= i && i < a.len() ==> result[i] == a[i], + forall|i: int| 0 <= i && i < b.len() ==> result[i + a.len()] == b[i], + // post-conditions-end +{ + // impl-start + let mut result: Vec = Vec::new(); + let mut i = 0; + while i < a.len() + // invariants-start + invariant + 0 <= i && i <= a.len(), + result.len() == i, + forall|j: int| 0 <= j && j < i ==> result[j] == a[j], + // invariants-end + { + result.push(a[i]); + i = i + 1; + } + let mut j = 0; + while j < b.len() + // invariants-start + invariant + 0 <= i && i <= a.len(), + 0 <= j && j <= b.len(), + result.len() == i + j, + forall|k: int| 0 <= k && k < i ==> result[k] == a[k], + forall|k: int| 0 <= k && k < j ==> result[k + i] == b[k], + // invariants-end + { + result.push(b[j]); + j = j + 1; + } + result + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/array_copy.rs b/benches/HumanEval-RustBench/array_copy.rs new file mode 100644 index 0000000..a51a4b5 --- /dev/null +++ b/benches/HumanEval-RustBench/array_copy.rs @@ -0,0 +1,32 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn array_copy(a: Vec) -> (result: Vec) + // post-conditions-start + ensures + result.len() == a.len(), + forall|i: int| 0 <= i && i < a.len() ==> result[i] == a[i], + // post-conditions-end +{ + // impl-start + let mut result: Vec = Vec::new(); + let mut i = 0; + while i < a.len() + // invariants-start + invariant + 0 <= i && i <= a.len(), + result.len() == i, + forall|j: int| 0 <= j && j < i ==> result[j] == a[j], + // invariants-end + { + result.push(a[i]); + i = i + 1; + } + result + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/array_product.rs b/benches/HumanEval-RustBench/array_product.rs new file mode 100644 index 0000000..57fd41f --- /dev/null +++ b/benches/HumanEval-RustBench/array_product.rs @@ -0,0 +1,36 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn array_product(a: Vec, b: Vec) -> (result: Vec) by (nonlinear_arith) + // pre-conditions-start + requires + a.len() == b.len(), + // pre-conditions-end + // post-conditions-start + ensures + result.len() == a.len(), + forall|i: int| #![auto] 0 <= i && i < a.len() ==> result[i] == (a[i] as i64) * (b[i] as i64), + // post-conditions-end +{ + // impl-start + let mut result: Vec = Vec::new(); + let mut i = 0; + while i < a.len() + // invariants-start + invariant + 0 <= i && i <= a.len(), + result.len() == i, + forall|j: int| #![auto] 0 <= j && j < i ==> result[j] == (a[j] as i64) * (b[j] as i64), + // invariants-end + { + result.push(a[i] as i64 * b[i] as i64); + i = i + 1; + } + result + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/barrier.rs b/benches/HumanEval-RustBench/barrier.rs new file mode 100644 index 0000000..55d6b90 --- /dev/null +++ b/benches/HumanEval-RustBench/barrier.rs @@ -0,0 +1,53 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn barrier(arr: &[i32], p: usize) -> (result: bool) + // pre-conditions-start + requires + arr.len() > 0, + 0 <= p < arr.len(), + // pre-conditions-end + // post-conditions-start + ensures + result == forall|k: int, l: int| 0 <= k <= p && p < l < arr.len() ==> arr[k] < arr[l], + // post-conditions-end +{ + // impl-start + let mut i = 1; + let mut max: usize = 0; + while i <= p + // invariants-start + invariant + 0 <= i <= p + 1, + 0 <= max < i, + forall|k: int| 0 <= k < i ==> arr[max as int] >= arr[k], + // invariants-end + { + if arr[i] > arr[max] { + max = i; + } + i = i + 1; + } + + let mut result = true; + while i < arr.len() + // invariants-start + invariant + p < i <= arr.len(), + forall|k: int| 0 <= k <= p ==> arr[max as int] >= arr[k], + result == forall|k: int, l: int| 0 <= k <= p && p < l < i ==> arr[k] < arr[l], + // invariants-end + { + if arr[max] >= arr[i] { + result = false; + } + i = i + 1; + } + result + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/binary_search.rs b/benches/HumanEval-RustBench/binary_search.rs new file mode 100644 index 0000000..a6dbd25 --- /dev/null +++ b/benches/HumanEval-RustBench/binary_search.rs @@ -0,0 +1,44 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn binary_search(arr: &[i32], target: i32) -> (result: Option) + // pre-conditions-start + requires + forall|i: int, j: int| 0 <= i && i < j && j < arr.len() ==> arr[i] <= arr[j], + // pre-conditions-end + // post-conditions-start + ensures + match result { + Some(index) => arr[index as int] == target && arr.len() > 0 && index < arr.len(), + None => forall|i: int| 0 <= i && i < arr.len() ==> arr[i] != target, + }, + // post-conditions-end +{ + // impl-start + let mut low = 0; + let mut high = arr.len(); + while low < high + // invariants-start + invariant + low <= high && high <= arr.len(), + forall|i: int| 0 <= i && i < low ==> arr[i] < target, + forall|i: int| high <= i && i < arr.len() ==> arr[i] > target, + // invariants-end + { + let mid = low + (high - low) / 2; + if arr[mid] == target { + return Some(mid); + } else if arr[mid] < target { + low = mid; + } else { + high = mid; + } + } + None + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/binary_search_recursive.rs b/benches/HumanEval-RustBench/binary_search_recursive.rs new file mode 100644 index 0000000..d29748c --- /dev/null +++ b/benches/HumanEval-RustBench/binary_search_recursive.rs @@ -0,0 +1,46 @@ +use vstd::prelude::*; + +verus! { + +fn binary_search_recursive(v: &[i32], elem: i32, c: isize, f: isize) -> (p: isize) + // pre-conditions-start + requires + v.len() <= 100_000, + forall|i: int, j: int| 0 <= i < j < v.len() ==> v[i] <= v[j], + 0 <= c <= f + 1 <= v.len(), + forall|k: int| 0 <= k < c ==> v[k] <= elem, + forall|k: int| f < k < v.len() ==> v[k] > elem, + // pre-conditions-end + // post-conditions-start + ensures + -1 <= p < v.len(), + forall|u: int| 0 <= u <= p ==> v[u] <= elem, + forall|w: int| p < w < v.len() ==> v[w] > elem, + // post-conditions-end + decreases f - c + 1 +{ + // impl-start + if c == f + 1 { + return c as isize - 1; + } else { + let m = ((c + f) as usize / 2) as isize; + // assert-start + assert(m < v.len()) by { + assert(c <= f); + assert(f < v.len()) by { + assert(f + 1 <= v.len()); + }; + }; + // assert-end + if v[m as usize] <= elem { + return binary_search_recursive(v, elem, m + 1, f); + } else { + return binary_search_recursive(v, elem, c, m - 1); + } + } + // impl-end +} + + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/cubes.rs b/benches/HumanEval-RustBench/cubes.rs new file mode 100644 index 0000000..cdbec2b --- /dev/null +++ b/benches/HumanEval-RustBench/cubes.rs @@ -0,0 +1,52 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::external_body] +fn add(a: i32, b: i32) -> (result: i32) + ensures + result == a + b, +{ + a + b +} + +#[verifier::loop_isolation(false)] +fn cubes(len: usize) -> (result: Vec) by (nonlinear_arith) + // post-conditions-start + ensures + result.len() == len, + forall|i: int| 0 <= i && i < len ==> result[i] == i * i * i + // post-conditions-end +{ + // impl-start + let mut result: Vec = Vec::new(); + + let mut c = 0; + let mut k = 1; + let mut m = 6; + + let mut n = 0; + while n < len + // invariants-start + invariant + 0 <= n && n <= len, + result.len() == n, + forall|i: int| 0 <= i && i < n ==> result[i] == i * i * i, + c == n * n * n, + k == 3 * n * n + 3 * n + 1, + m == 6 * n + 6, + // invariants-end + { + result.push(c); + + c = add(c, k); + k = add(k, m); + m = add(m, 6); + n = n + 1; + } + result + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/has_close_elements.rs b/benches/HumanEval-RustBench/has_close_elements.rs new file mode 100644 index 0000000..1ad9e52 --- /dev/null +++ b/benches/HumanEval-RustBench/has_close_elements.rs @@ -0,0 +1,65 @@ +use vstd::prelude::*; + +verus! { + +spec fn abs_spec(i: int) -> int { + if i < 0 { -i } else { i } +} + +fn abs(i: i32) -> (res: i32) + requires + i != i32::MIN, + ensures + i < 0 ==> res == -i, + i >= 0 ==> res == i +{ + if i < 0 { -i } else { i } +} + +#[verifier::loop_isolation(false)] +fn has_close_elements(numbers: &[i32], threshold: i32) -> (flag: bool) + // pre-conditions-start + requires + threshold > 0, + forall|i: int, j: int| 0 <= i && i < numbers.len() && 0 <= j && j < numbers.len() ==> numbers[i] - numbers[j] < i32::MAX && -(numbers[i] - numbers[j]) < i32::MAX + // pre-conditions-end + // post-conditions-start + ensures + flag == exists|i: int, j: int| 0 <= i && 0 <= j && i < numbers.len() && j < numbers.len() && i != j && abs_spec(numbers[i] - numbers[j]) < threshold + // post-conditions-end +{ + // impl-start + let mut flag = false; + let mut i = 0; + while i < numbers.len() + // invariants-start + invariant + 0 <= i && i <= numbers.len(), + flag == exists|i1: int, j1: int| 0 <= i1 && 0 <= j1 && i1 < i && j1 < numbers.len() && i1 != j1 && abs_spec(numbers[i1] - numbers[j1]) < threshold, + // invariants-end + { + let mut j = 0; + while j < numbers.len() + // invariants-start + invariant + 0 <= i && i < numbers.len(), + 0 <= j && j <= numbers.len(), + flag == exists|i1: int, j1: int| 0 <= i1 && 0 <= j1 && ((i1 < i && j1 < numbers.len()) || (i1 == i && j1 < j)) && i1 != j1 && abs_spec(numbers[i1] - numbers[j1]) < threshold, + // invariants-end + { + if i != j { + let distance = abs(numbers[i] - numbers[j]); + if distance < threshold { + flag = true; + } + } + j = j + 1; + } + i = i + 1; + } + flag + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/has_only_one_distinct_element.rs b/benches/HumanEval-RustBench/has_only_one_distinct_element.rs new file mode 100644 index 0000000..e58c64b --- /dev/null +++ b/benches/HumanEval-RustBench/has_only_one_distinct_element.rs @@ -0,0 +1,39 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn has_only_one_distinct_element(a: &[i32]) -> (result: bool) + // pre-conditions-start + // pre-conditions-end + // post-conditions-start + ensures + result ==> forall|i: int, j: int| 0 <= i < a.len() && 0 <= j < a.len() ==> a[i] == a[j], + !result ==> exists|i: int, j: int| 0 <= i < a.len() && 0 <= j < a.len() && a[i] != a[j], + // post-conditions-end +{ + // impl-start + if a.len() == 0 { + return true; + } + + let first = a[0]; + let mut i = 1; + while i < a.len() + // invariants-start + invariant + 0 <= i <= a.len(), + forall|k: int, l: int| 0 <= k < i && 0 <= l < i ==> a[k] == a[l], + // invariants-end + { + if a[i] != first { + return false; + } + i = i + 1; + } + true + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/index_wise_addition.rs b/benches/HumanEval-RustBench/index_wise_addition.rs new file mode 100644 index 0000000..82d4320 --- /dev/null +++ b/benches/HumanEval-RustBench/index_wise_addition.rs @@ -0,0 +1,62 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn index_wise_addition(a: &Vec>, b: &Vec>) -> (c: Vec>) + // pre-conditions-start + requires + a.len() == b.len(), + forall|i: int| #![auto] 0 <= i < a.len() ==> a[i].len() == b[i].len(), + forall|i: int| #![trigger a[i], b[i]] + 0 <= i < a.len() + ==> forall|j: int| 0 <= j < a[i].len() ==> a[i][j] + b[i][j] <= i32::MAX, + forall|i: int| #![trigger a[i], b[i]] + 0 <= i < a.len() + ==> forall|j: int| 0 <= j < a[i].len() ==> a[i][j] + b[i][j] >= i32::MIN, + // pre-conditions-end + // post-conditions-start + ensures + c.len() == a.len(), + forall|i: int| #![auto] 0 <= i < c.len() ==> c[i].len() == a[i].len(), + forall|i: int| #![trigger a[i], b[i], c[i]] + 0 <= i < c.len() + ==> forall|j: int| #![auto] 0 <= j < c[i].len() ==> c[i][j] == a[i][j] + b[i][j], + // post-conditions-end +{ + // impl-start + let mut c: Vec> = Vec::new(); + let mut i = 0; + while i < a.len() + // invariants-start + invariant + 0 <= i <= a.len(), + c.len() == i, + forall|j: int| #![auto] 0 <= j < i ==> c[j].len() == a[j].len(), + forall|j: int| #![trigger a[j], b[j], c[j]] + 0 <= j < i + ==> forall|k: int| #![auto] 0 <= k < c[j].len() ==> c[j][k] == a[j][k] + b[j][k], + // invariants-end + { + let mut sub_c: Vec = Vec::new(); + let mut j = 0; + while j < a[i].len() + // invariants-start + invariant + 0 <= j <= a[i as int].len(), + sub_c.len() == j, + forall|k: int| #![auto] 0 <= k < j ==> sub_c[k] == a[i as int][k] + b[i as int][k], + // invariants-end + { + sub_c.push(a[i][j] + b[i][j]); + j = j + 1; + } + c.push(sub_c); + i = i + 1; + } + c + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/integer_square_root.rs b/benches/HumanEval-RustBench/integer_square_root.rs new file mode 100644 index 0000000..dd56c13 --- /dev/null +++ b/benches/HumanEval-RustBench/integer_square_root.rs @@ -0,0 +1,49 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::external_body] +fn add_one(n: i32) -> (result: i32) + ensures + result == n + 1, +{ + n + 1 +} + +#[verifier::external_body] +fn square(n: i32) -> (result: i32) + ensures + n * n == result, +{ + n * n +} + +fn integer_square_root(n: i32) -> (result: i32) + // pre-conditions-start + requires + n >= 1, + // pre-conditions-end + // post-conditions-start + ensures + 0 <= result * result, + result * result <= n, + n < (result + 1) * (result + 1) + // post-conditions-end +{ + // impl-start + let mut result = 0; + while square(add_one(result)) <= n + // invariants-start + invariant + 0 <= result, + 0 <= result * result <= n + // invariants-end + { + result = add_one(result); + } + result + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/intersperse.rs b/benches/HumanEval-RustBench/intersperse.rs new file mode 100644 index 0000000..8cdcadb --- /dev/null +++ b/benches/HumanEval-RustBench/intersperse.rs @@ -0,0 +1,38 @@ +use vstd::prelude::*; + +verus! { + +fn intersperse(numbers: &[i32], delim: i32) -> (res: Vec) + // post-conditions-start + ensures + numbers.len() == 0 ==> res.len() == 0, + numbers.len() != 0 ==> res.len() == 2 * numbers.len() - 1, + forall|i: int| 0 <= i && i < res.len() && i % 2 == 0 ==> res[i] == numbers[i / 2], + forall|i: int| 0 <= i && i < res.len() && i % 2 == 1 ==> res[i] == delim + // post-conditions-end +{ + // impl-start + let mut res = Vec::new(); + if numbers.len() != 0 { + let mut i = 0; + while i + 1 < numbers.len() + // invariants-start + invariant + 0 <= i && i < numbers.len(), + res.len() == 2 * i, + forall|j: int| 0 <= j && j < res.len() && j % 2 == 0 ==> res[j] == numbers[j / 2], + forall|j: int| 0 <= j && j < res.len() && j % 2 == 1 ==> res[j] == delim + // invariants-end + { + res.push(numbers[i]); + res.push(delim); + i += 1; + } + res.push(numbers[i]); + } + res + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/is_non_prime.rs b/benches/HumanEval-RustBench/is_non_prime.rs new file mode 100644 index 0000000..436b237 --- /dev/null +++ b/benches/HumanEval-RustBench/is_non_prime.rs @@ -0,0 +1,35 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn is_non_prime(n: u32) -> (result: bool) + // pre-conditions-start + requires + n >= 2, + // pre-conditions-end + // post-conditions-start + ensures + result == exists|k: int| 2 <= k < n && #[trigger] (n as int % k) == 0, + // post-conditions-end +{ + // impl-start + let mut i = 2; + while i < n + // invariants-start + invariant + 2 <= i <= n, + forall|k: int| 2 <= k < i ==> #[trigger] (n as int % k) != 0, + // invariants-end + { + if n % i == 0 { + return true; + } + i = i + 1; + } + false + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/is_sorted.rs b/benches/HumanEval-RustBench/is_sorted.rs new file mode 100644 index 0000000..f4f632a --- /dev/null +++ b/benches/HumanEval-RustBench/is_sorted.rs @@ -0,0 +1,39 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn is_sorted(lst: &[i32]) -> (result: bool) + // pre-conditions-start + requires + lst.len() >= 1, + // pre-conditions-end + // post-conditions-start + ensures + result <== forall|i: int, j: int| 0 <= i && i < j && j < lst.len() ==> lst[i] <= lst[j], + !result ==> exists|i: int, j: int| 0 <= i && i < j && j < lst.len() && lst[i] > lst[j], + // post-conditions-end +{ + // impl-start + let mut result = true; + let mut i = 0; + while i + 1 < lst.len() + // invariants-start + invariant + 0 <= i && i < lst.len(), + result <== forall|k: int, l: int| 0 <= k < l < i ==> lst[k] <= lst[l], + !result ==> exists|k: int, l: int| 0 <= k < l < i && lst[k] > lst[l], + // invariants-end + { + if lst[i] > lst[i + 1] { + result = false; + break; + } + i = i + 1; + } + result + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/largest_prime_factor.rs b/benches/HumanEval-RustBench/largest_prime_factor.rs new file mode 100644 index 0000000..d67982d --- /dev/null +++ b/benches/HumanEval-RustBench/largest_prime_factor.rs @@ -0,0 +1,66 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn is_prime(n: u32) -> (result: bool) + // pre-conditions-start + requires + n >= 2, + // pre-conditions-end + // post-conditions-start + ensures + result ==> (forall|k: int| 2 <= k < n ==> #[trigger] (n as int % k) != 0), + !result ==> exists|k: int| 2 <= k < n && #[trigger] (n as int % k) == 0, + // post-conditions-end +{ + // impl-start + let mut i = 2; + let mut result = true; + while i < n + // invariants-start + invariant + 2 <= i <= n, + result ==> forall|k: int| 2 <= k < i ==> #[trigger] (n as int % k) != 0, + !result ==> exists|k: int| 2 <= k < i && #[trigger] (n as int % k) == 0, + // invariants-end + { + if n % i == 0 { + result = false; + } + i = i + 1; + } + result + // impl-end +} + +spec fn is_prime_pred(n: u32) -> bool { + forall|k: int| 2 <= k < n ==> #[trigger] (n as int % k) != 0 +} + +#[verifier::loop_isolation(false)] +fn largest_prime_factor(n: u32) -> (result: u32) + requires + 2 <= n <= u32::MAX - 1, + ensures + 1 <= result <= n, + result == 1 || (result > 1 && is_prime_pred(result)) +{ + let mut largest = 1; + let mut i = 2; + while i <= n + invariant + 2 <= i <= n + 1, + 1 <= largest < i, + largest == 1 || (largest > 1 && is_prime_pred(largest)), + { + if n % i == 0 && is_prime(i) { + largest = i; + } + i = i + 1; + } + largest +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/last_position.rs b/benches/HumanEval-RustBench/last_position.rs new file mode 100644 index 0000000..d509291 --- /dev/null +++ b/benches/HumanEval-RustBench/last_position.rs @@ -0,0 +1,38 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn last_position(a: &[i32], elem: i32) -> (result: usize) + // pre-conditions-start + requires + 0 < a.len() < 100_000, + exists|i: int| 0 <= i < a.len() && a[i] == elem, + // pre-conditions-end + // post-conditions-start + ensures + 0 <= result < a.len(), + forall|i: int| result < i < a.len() ==> a[i] != elem, + a[result as int] == elem, + // post-conditions-end +{ + // impl-start + let mut i = a.len() as isize - 1; + while i >= 0 + // invariants-start + invariant + 0 <= i + 1 <= a.len() as isize, + forall|k: int| i < k < a.len() ==> a[k] != elem, + // invariants-end + { + if a[i as usize] == elem { + return i as usize; + } + i = i - 1; + } + a.len() + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/max_array.rs b/benches/HumanEval-RustBench/max_array.rs new file mode 100644 index 0000000..c9c6127 --- /dev/null +++ b/benches/HumanEval-RustBench/max_array.rs @@ -0,0 +1,38 @@ +use vstd::prelude::*; + +verus! { + +fn max_array(nums: &[i32]) -> (idx: usize) + // pre-conditions-start + requires + nums.len() >= 1, + // pre-conditions-end + // post-conditions-start + ensures + 0 <= idx && idx < nums.len(), + forall|i: int| 0 <= i && i < nums.len() ==> nums[i] <= nums[idx as int], + // post-conditions-end +{ + // impl-start + let mut idx = 0; + + let mut i = 1; + while i < nums.len() + // invariants-start + invariant + 0 < i <= nums.len(), + 0 <= idx && idx < i, + forall|j: int| 0 <= j && j < i ==> nums[j] <= nums[idx as int], + // invariants-end + { + if nums[i] > nums[idx] { + idx = i; + } + i = i + 1; + } + idx + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/max_dafny_lsp.rs b/benches/HumanEval-RustBench/max_dafny_lsp.rs new file mode 100644 index 0000000..46bfacc --- /dev/null +++ b/benches/HumanEval-RustBench/max_dafny_lsp.rs @@ -0,0 +1,48 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn max_dafny_lsp(a: &[i32]) -> (x: usize) + // pre-conditions-start + requires + a.len() > 0, + // pre-conditions-end + // post-conditions-start + ensures + 0 <= x < a.len(), + forall|k: int| 0 <= k < a.len() ==> a[k] <= a[x as int], + // post-conditions-end +{ + // impl-start + let mut x = 0; + let mut y = a.len() - 1; + + let ghost mut m = 0; + while x != y + // invariants-start + invariant + 0 <= x <= y < a.len(), + m == x || m == y, + forall|i: int| 0 <= i < x ==> a[i] <= a[m], + forall|i: int| y < i < a.len() ==> a[i] <= a[m], + // invariants-end + { + if a[x] <= a[y] { + x = x + 1; + proof { + m = y as int; + } + } else { + y = y - 1; + proof { + m = x as int; + } + } + } + x + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/remove_duplicates.rs b/benches/HumanEval-RustBench/remove_duplicates.rs new file mode 100644 index 0000000..358b266 --- /dev/null +++ b/benches/HumanEval-RustBench/remove_duplicates.rs @@ -0,0 +1,66 @@ +use vstd::prelude::*; + +verus! { + +spec fn in_array(a: Seq, x: i32) -> bool { + exists|i: int| 0 <= i < a.len() && a[i] == x +} + +fn in_array_exec(a: &Vec, x: i32) -> (result: bool) + // post-conditions-start + ensures + result == in_array(a@, x), + // post-conditions-end +{ + // impl-start + let mut i = 0; + while i < a.len() + // invariants-start + invariant + 0 <= i <= a.len(), + forall|k: int| 0 <= k < i ==> a[k] != x, + // invariants-end + { + if a[i] == x { + return true; + } + i = i + 1; + } + false + // impl-end +} + +#[verifier::loop_isolation(false)] +fn remove_duplicates(a: &[i32]) -> (result: Vec) + // pre-conditions-start + requires + a.len() >= 1, + // pre-conditions-end + // post-conditions-start + ensures + forall|i: int| #![auto] 0 <= i < result.len() ==> in_array(a@, result[i]), + forall|i: int, j: int| 0 <= i < j < result.len() ==> result[i] != result[j], + // post-conditions-end +{ + // impl-start + let mut result: Vec = Vec::new(); + let mut i = 0; + while i < a.len() + // invariants-start + invariant + 0 <= i <= a.len(), + forall|k: int| #![auto] 0 <= k < result.len() ==> in_array(a@, result[k]), + forall|k: int, l: int| 0 <= k < l < result.len() ==> result[k] != result[l], + // invariants-end + { + if !in_array_exec(&result, a[i]) { + result.push(a[i]); + } + i = i + 1; + } + result + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/remove_element.rs b/benches/HumanEval-RustBench/remove_element.rs new file mode 100644 index 0000000..58fa4d6 --- /dev/null +++ b/benches/HumanEval-RustBench/remove_element.rs @@ -0,0 +1,50 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn remove_element(a: &[i32], pos: usize) -> (result: Vec) + // pre-conditions-start + requires + 0 <= pos < a.len(), + // pre-conditions-end + // post-conditions-start + ensures + result.len() == a.len() - 1, + forall|i: int| 0 <= i < pos ==> result[i] == a[i], + forall|i: int| pos <= i < result.len() ==> result[i] == a[i + 1], + // post-conditions-end +{ + // impl-start + let mut result: Vec = Vec::new(); + let mut i = 0; + while i < pos + // invariants-start + invariant + 0 <= i <= pos, + forall|k: int| 0 <= k < i ==> result[k] == a[k], + result.len() == i, + // invariants-end + { + result.push(a[i]); + i = i + 1; + } + + while i + 1 < a.len() + // invariants-start + invariant + pos <= i < a.len(), + result.len() == i, + forall|k: int| 0 <= k < pos ==> result[k] == a[k], + forall|k: int| pos <= k < i ==> result[k] == a[k + 1], + // invariants-end + { + result.push(a[i + 1]); + i = i + 1; + } + result + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/remove_elements.rs b/benches/HumanEval-RustBench/remove_elements.rs new file mode 100644 index 0000000..bc7f28f --- /dev/null +++ b/benches/HumanEval-RustBench/remove_elements.rs @@ -0,0 +1,62 @@ +use vstd::prelude::*; + +verus! { + +spec fn in_array(a: Seq, x: i32) -> bool { + exists|i: int| 0 <= i < a.len() && a[i] == x +} + +fn in_array_exec(a: &Vec, x: i32) -> (result: bool) + // post-conditions-start + ensures + result == in_array(a@, x), + // post-conditions-end +{ + // impl-start + let mut i = 0; + while i < a.len() + // invariants-start + invariant + 0 <= i <= a.len(), + forall|k: int| 0 <= k < i ==> a[k] != x, + // invariants-end + { + if a[i] == x { + return true; + } + i = i + 1; + } + false + // impl-end +} + +#[verifier::loop_isolation(false)] +fn remove_elements(a: &Vec, b: &Vec) -> (c: Vec) + // post-conditions-start + ensures + forall|k: int| #![auto] 0 <= k < c.len() ==> in_array(a@, c[k]) && !in_array(b@, c[k]), + forall|i: int, j: int| 0 <= i < j < c.len() ==> c[i] != c[j], + // post-conditions-end +{ + // impl-start + let mut c: Vec = Vec::new(); + let mut i = 0; + while i < a.len() + // invariants-start + invariant + 0 <= i <= a.len(), + forall|k: int| #![auto] 0 <= k < c.len() ==> in_array(a@, c[k]) && !in_array(b@, c[k]), + forall|i: int, j: int| 0 <= i < j < c.len() ==> c[i] != c[j], + // invariants-end + { + if !in_array_exec(b, a[i]) && !in_array_exec(&c, a[i]) { + c.push(a[i]); + } + i = i + 1; + } + c + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/replace.rs b/benches/HumanEval-RustBench/replace.rs new file mode 100644 index 0000000..828c617 --- /dev/null +++ b/benches/HumanEval-RustBench/replace.rs @@ -0,0 +1,35 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn replace(a: &mut Vec, x: i32, y: i32) + // post-conditions-start + ensures + a.len() == old(a).len(), + forall|k: int| 0 <= k < old(a).len() && old(a)[k] == x ==> a[k] == y, + forall|k: int| 0 <= k < old(a).len() && old(a)[k] != x ==> a[k] == old(a)[k], + // post-conditions-end +{ + // impl-start + let mut i = 0; + while i < a.len() + // invariants-start + invariant + 0 <= i <= a.len(), + a.len() == old(a).len(), + forall|k: int| 0 <= k < i && old(a)[k] == x ==> a[k] == y, + forall|k: int| 0 <= k < i && old(a)[k] != x ==> a[k] == old(a)[k], + forall|k: int| i <= k < a.len() ==> a[k] == old(a)[k], + // invariants-end + { + if a[i] == x { + a.set(i, y); + } + i = i + 1; + } + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/replace_chars.rs b/benches/HumanEval-RustBench/replace_chars.rs new file mode 100644 index 0000000..3d7acbe --- /dev/null +++ b/benches/HumanEval-RustBench/replace_chars.rs @@ -0,0 +1,31 @@ +use vstd::prelude::*; + +verus! { + +fn replace_chars(s: &[char], old: char, new: char) -> (result: Vec) + // post-conditions-start + ensures + result.len() == s.len(), + forall|i: int| 0 <= i && i < result.len() ==> result[i] == (if s[i] == old { new } else { s[i] }), + // post-conditions-end +{ + // impl-start + let mut result: Vec = Vec::new(); + let mut i = 0; + while i < s.len() + // invariants-start + invariant + 0 <= i && i <= s.len(), + result.len() == i, + forall|j: int| 0 <= j && j < i ==> result[j] == (if s[j] == old { new } else { s[j] }), + // invariants-end + { + result.push(if s[i] == old { new } else { s[i] }); + i = i + 1; + } + result + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/reverse.rs b/benches/HumanEval-RustBench/reverse.rs new file mode 100644 index 0000000..151741d --- /dev/null +++ b/benches/HumanEval-RustBench/reverse.rs @@ -0,0 +1,31 @@ +use vstd::prelude::*; + +verus! { + +fn reverse(a: &[i32]) -> (result: Vec) + // post-conditions-start + ensures + result.len() == a.len(), + forall|i: int| 0 <= i && i < result.len() ==> result[i] == a[a.len() - 1 - i], + // post-conditions-end +{ + // impl-start + let mut result: Vec = Vec::new(); + let mut i = 0; + while i < a.len() + // invariants-start + invariant + 0 <= i && i <= a.len(), + result.len() == i, + forall|j: int| 0 <= j && j < i ==> result[j] == a[a.len() - 1 - j] + // invariants-end + { + result.push(a[a.len() - 1 - i]); + i += 1; + } + result + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/rolling_max.rs b/benches/HumanEval-RustBench/rolling_max.rs new file mode 100644 index 0000000..78c979b --- /dev/null +++ b/benches/HumanEval-RustBench/rolling_max.rs @@ -0,0 +1,50 @@ +use vstd::prelude::*; + +verus! { + +spec fn seq_max(a: Seq) -> i32 + decreases a.len(), +{ + if a.len() == 0 { + i32::MIN + } else if a.last() > seq_max(a.drop_last()) { + a.last() + } else { + seq_max(a.drop_last()) + } +} + +fn rolling_max(numbers: Vec) -> (result: Vec) + // post-conditions-start + ensures + result.len() == numbers.len(), + forall|i: int| 0 <= i < numbers.len() ==> result[i] == seq_max(numbers@.take(i + 1)), + // post-conditions-end +{ + // impl-start + let mut max_so_far = i32::MIN; + let mut result = Vec::with_capacity(numbers.len()); + let mut pos = 0; + while pos < numbers.len() + // invariants-start + invariant + 0 <= pos <= numbers.len(), + result.len() == pos, + max_so_far == seq_max(numbers@.take(pos as int)), + forall|i: int| 0 <= i < pos ==> result[i] == seq_max(numbers@.take(i + 1)), + pos < numbers.len() ==> numbers@.take((pos + 1) as int).drop_last() =~= numbers@.take(pos as int) + // invariants-end + { + let number = numbers[pos]; + if number > max_so_far { + max_so_far = number; + } + result.push(max_so_far); + pos += 1; + } + result + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/smallest_list_length.rs b/benches/HumanEval-RustBench/smallest_list_length.rs new file mode 100644 index 0000000..18979bb --- /dev/null +++ b/benches/HumanEval-RustBench/smallest_list_length.rs @@ -0,0 +1,38 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn smallest_list_length(lists: Vec>) -> (result: usize) + // pre-conditions-start + requires + lists.len() > 0, + // pre-conditions-end + // post-conditions-start + ensures + exists|i: int| #![auto] 0 <= i < lists.len() && result == lists[i].len(), + forall|i: int| #![auto] 0 <= i < lists.len() ==> result <= lists[i].len(), + // post-conditions-end +{ + // impl-start + let mut result = lists[0].len(); + let mut i = 1; + while i < lists.len() + // invariants-start + invariant + 0 <= i <= lists.len(), + forall|j: int| #![auto] 0 <= j < i ==> result <= lists[j].len(), + exists|j: int| #![auto] 0 <= j < i && result == lists[j].len(), + // invariants-end + { + if lists[i].len() < result { + result = lists[i].len(); + } + i = i + 1; + } + result + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/smallest_missing_number.rs b/benches/HumanEval-RustBench/smallest_missing_number.rs new file mode 100644 index 0000000..c177665 --- /dev/null +++ b/benches/HumanEval-RustBench/smallest_missing_number.rs @@ -0,0 +1,46 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn smallest_missing_number(s: &[i32]) -> (v: i32) + // pre-conditions-start + requires + forall|i: int, j: int| 0 <= i < j < s.len() ==> s[i] <= s[j], + forall|i: int| 0 <= i < s.len() ==> s[i] >= 0, + s.len() <= 100_000, + // pre-conditions-end + // post-conditions-start + ensures + 0 <= v, + forall|i: int| 0 <= i < s.len() ==> s[i] != v, + forall|k: int| 0 <= k < v && s[k] != v ==> exists|j: int| 0 <= j < s.len() && s[j] == k, + // post-conditions-end +{ + // impl-start + let mut v = 0; + let mut i = 0; + while i < s.len() + // invariants-start + invariant + 0 <= i <= s.len(), + 0 <= v <= i, + forall|k: int| 0 <= k < i ==> s[k] != v, + forall|k: int| 0 <= k < v && s[k] != v ==> exists|j: int| 0 <= j < i && s[j] == k, + // invariants-end + { + if s[i] > v { + break; + } else { + if s[i] == v { + v = v + 1; + } + } + i = i + 1; + } + v + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/string_xor.rs b/benches/HumanEval-RustBench/string_xor.rs new file mode 100644 index 0000000..be3d979 --- /dev/null +++ b/benches/HumanEval-RustBench/string_xor.rs @@ -0,0 +1,40 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn string_xor(a: &[char], b: &[char]) -> (result: Vec) + // pre-conditions-start + requires + a.len() == b.len(), + forall|i: int| 0 <= i && i < a.len() ==> a[i] == '0' || a[i] == '1', + forall|i: int| 0 <= i && i < b.len() ==> b[i] == '0' || b[i] == '1', + // pre-conditions-end + // post-conditions-start + ensures + result.len() == a.len(), + forall|i: int| 0 <= i && i < result.len() ==> (result[i] == '0' || result[i] == '1'), + forall|i: int| 0 <= i && i < result.len() ==> result[i] == (if a[i] == b[i] { '0' } else { '1' }) + // post-conditions-end +{ + // impl-start + let mut result: Vec = Vec::new(); + let mut i = 0; + while i < a.len() + // invariants-start + invariant + 0 <= i && i <= a.len(), + result.len() == i, + forall|j: int| 0 <= j && j < i ==> result[j] == (if a[j] == b[j] { '0' } else { '1' }) + // invariants-end + { + let bit = if a[i] == b[i] { '0' } else { '1' }; + result.push(bit); + i += 1; + } + result + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/two_sum.rs b/benches/HumanEval-RustBench/two_sum.rs new file mode 100644 index 0000000..6707924 --- /dev/null +++ b/benches/HumanEval-RustBench/two_sum.rs @@ -0,0 +1,57 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn two_sum(nums: &[i32], target: i32) -> (result: (usize, usize)) + // pre-conditions-start + requires + nums.len() >= 2, + exists|i: int, j: int| 0 <= i < j < nums.len() && nums[i] + nums[j] == target, + forall|i: int, j: int| + 0 <= i < nums.len() && 0 <= j < nums.len() + ==> nums[i] + nums[j] <= i32::MAX + && nums[i] + nums[j] >= i32::MIN, + // pre-conditions-end + // post-conditions-start + ensures + ({ let (i, j) = result; 0 <= i < nums.len() }), + ({ let (i, j) = result; 0 <= j < nums.len() }), + ({ let (i, j) = result; i != j }), + ({ let (i, j) = result; nums[i as int] + nums[j as int] == target }) + // post-conditions-end +{ + // impl-start + let mut i = 0; + + while i < nums.len() + // invariants-start + invariant + 0 <= i <= nums.len(), + forall|u: int, v: int| 0 <= u < v < nums.len() && u < i ==> nums[u] + nums[v] != target, + exists|u: int, v: int| i <= u < v < nums.len() && nums[u] + nums[v] == target, + // invariants-end + { + let mut j = i + 1; + while j < nums.len() + // invariants-start + invariant + 0 <= i < j <= nums.len(), + forall|u: int, v: int| 0 <= u < v < nums.len() && u < i ==> nums[u] + nums[v] != target, + exists|u: int, v: int| i <= u < v < nums.len() && nums[u] + nums[v] == target, + forall|u: int| i < u < j ==> nums[i as int] + nums[u] != target, + // invariants-end + { + if nums[i] + nums[j] == target { + return (i, j); + } + j = j + 1; + } + i = i + 1; + } + (0, 0) + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/two_way_sort.rs b/benches/HumanEval-RustBench/two_way_sort.rs new file mode 100644 index 0000000..207ad10 --- /dev/null +++ b/benches/HumanEval-RustBench/two_way_sort.rs @@ -0,0 +1,67 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::external_body] +fn swap(a: &mut Vec, i: usize, j: usize) + // pre-conditions-start + requires + 0 <= i < j < old(a).len(), + // pre-conditions-end + // post-conditions-start + ensures + a[i as int] == old(a)[j as int], + a[j as int] == old(a)[i as int], + forall|k: int| 0 <= k < a.len() && k != i && k != j ==> a[k] == old(a)[k], + a.len() == old(a).len(), + a@.to_multiset() =~~= old(a)@.to_multiset(), + // post-conditions-end +{ + // impl-start + let tmp = a[i]; + a.set(i, a[j]); + a.set(j, tmp); + // impl-end +} + +#[verifier::loop_isolation(false)] +fn two_way_sort(a: &mut Vec) + // pre-conditions-start + requires + old(a).len() <= 100_000, + // pre-conditions-end + // post-conditions-start + ensures + a.len() == old(a).len(), + a@.to_multiset() == old(a)@.to_multiset(), + forall|i: int, j: int| 0 <= i < j < a.len() ==> !a[i] || a[j], + // post-conditions-end +{ + // impl-start + let mut i = 0isize; + let mut j = a.len() as isize - 1; + while i <= j + // invariants-start + invariant + 0 <= i <= j + 1 <= a.len(), + forall|k: int| 0 <= k < i ==> !a[k], + forall|k: int| j < k < a.len() ==> a[k], + a.len() == old(a).len(), + a@.to_multiset() == old(a)@.to_multiset(), + // invariants-end + { + if !a[i as usize] { + i = i + 1; + } else if a[j as usize] { + j = j - 1; + } else { + swap(a, i as usize, j as usize); + i = i + 1; + j = j - 1; + } + } + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/unique.rs b/benches/HumanEval-RustBench/unique.rs new file mode 100644 index 0000000..f066cc7 --- /dev/null +++ b/benches/HumanEval-RustBench/unique.rs @@ -0,0 +1,43 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn unique(a: &[i32]) -> (result: Vec) + // pre-conditions-start + requires + forall|i: int, j: int| + #![trigger a[i], a[j]] + 0 <= i && i < j && j < a.len() ==> a[i] <= a[j], + // pre-conditions-end + // post-conditions-start + ensures + forall|i: int, j: int| + #![trigger result[i], result[j]] + 0 <= i && i < j && j < result.len() ==> result[i] < result[j], + // post-conditions-end +{ + // impl-start + let mut result: Vec = Vec::new(); + let mut i = 0; + while i < a.len() + // invariants-start + invariant + 0 <= i && i <= a.len(), + forall|i: int, j: int| 0 <= i && i < j && j < a.len() ==> a[i] <= a[j], + forall|i: int, j: int| 0 <= i && i < j && j < result.len() ==> #[trigger] result[i] < #[trigger] result[j], + result.len() == 0 || i == a.len() || result[result.len() - 1] <= a[i as int] + // invariants-end + { + if result.len() == 0 || result[result.len() - 1] != a[i] { + assert(result.len() == 0 || result[result.len() - 1] < a[i as int]); // assert-line + result.push(a[i]); + } + i = i + 1; + } + result + // impl-end +} + +fn main() {} +} diff --git a/benches/HumanEval-RustBench/unique_better.rs b/benches/HumanEval-RustBench/unique_better.rs new file mode 100644 index 0000000..8d61865 --- /dev/null +++ b/benches/HumanEval-RustBench/unique_better.rs @@ -0,0 +1,46 @@ +use vstd::prelude::*; + +verus! { + +#[verifier::loop_isolation(false)] +fn unique_better(a: &[i32]) -> (result: Vec) + // pre-conditions-start + requires + forall|i: int, j: int| + #![trigger a[i], a[j]] + 0 <= i && i < j && j < a.len() ==> a[i] <= a[j], + // pre-conditions-end + // post-conditions-start + ensures + forall|i: int, j: int| + #![trigger result[i], result[j]] + 0 <= i && i < j && j < result.len() ==> result[i] < result[j], + // post-conditions-end +{ + // impl-start + let mut result: Vec = Vec::new(); + let mut i = 0; + while i < a.len() + // invariants-start + invariant + 0 <= i <= a.len(), + forall|k: int, l: int| + #![trigger result[k], result[l]] + 0 <= k && k < l && l < result.len() ==> result[k] < result[l], + forall|k: int| + #![trigger result[k]] + 0 <= k && k < result.len() ==> exists|m: int| 0 <= m < i && result[k] == a[m], + // invariants-end + { + if result.len() == 0 || result[result.len() - 1] != a[i] { + assert(result.len() == 0 || result[result.len() - 1] < a[i as int]); // assert-line + result.push(a[i]); + } + i = i + 1; + } + result + // impl-end +} + +fn main() {} +} diff --git a/flake.nix b/flake.nix index 9416483..a8eb780 100644 --- a/flake.nix +++ b/flake.nix @@ -7,10 +7,15 @@ inherit inputs; systems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; - devShell.packages = pkgs: with pkgs; [ - poetry - dafny - ]; - formatter = pkgs: with pkgs; [ nixpkgs-fmt ]; + devShell = pkgs: { + packages = pkgs: (with pkgs; [ + poetry + dafny + ]) ++ (pkgs.lib.optionals pkgs.stdenv.isDarwin (with pkgs.darwin.apple_sdk.frameworks; [ + AppKit + pkgs.libiconv + ])); + }; + formatter = pkgs: pkgs.nixpkgs-fmt; }; } diff --git a/scripts/process_files.fish b/scripts/process_files.fish new file mode 100644 index 0000000..ac09d27 --- /dev/null +++ b/scripts/process_files.fish @@ -0,0 +1,5 @@ +set VERUS_TASKS_DIR "/Users/Stanislav.Alekseev/Projects/human-eval-verus/tasks" + +for f in $VERUS_TASKS_DIR/*.rs + python process_verus_task.py $f +end diff --git a/scripts/process_verus_task.py b/scripts/process_verus_task.py new file mode 100644 index 0000000..05d0a4a --- /dev/null +++ b/scripts/process_verus_task.py @@ -0,0 +1,46 @@ +from sys import argv +from pathlib import Path + +dafny_files = Path( + "/Users/Stanislav.Alekseev/Projects/verified-cogen/benches/HumanEval-Dafny" +).glob("*.dfy") +dafny_files = [x.stem for x in dafny_files] +# print(dafny_files) + +with open(argv[1]) as task_file: + code = task_file.read() + if "TODO" in code: + exit(1) + else: + import re + + # Remove single-line comments + code = re.sub(r"//.*", "", code) + + code = re.sub(r"^\s+\n", "", code, flags=re.MULTILINE) + + # Remove multi-line comments + code = re.sub(r"/\*[\s\S]*?\*/", "", code, flags=re.MULTILINE) + + code = re.sub(r"^\s+", "", code) + code = re.sub(r"\s+$", "", code) + + code += "\n" + + # Create 'processed' folder if it doesn't exist + + processed_dir = Path("processed") + processed_dir.mkdir(exist_ok=True) + + number = Path(argv[1]).stem[-3:] + print(number) + result_name = None + for file in dafny_files: + if file.startswith(number): + result_name = file + + assert result_name is not None + # Save processed code to file in 'processed' folder + output_file = processed_dir / f"{result_name}.rs" + if not output_file.exists(): + output_file.write_text(code) diff --git a/run_validating.sh b/scripts/run_validating.sh similarity index 100% rename from run_validating.sh rename to scripts/run_validating.sh diff --git a/run_with_houdini.sh b/scripts/run_with_houdini.sh similarity index 100% rename from run_with_houdini.sh rename to scripts/run_with_houdini.sh From ffc525d2bcbdc4914c2a2619d34e1e6497129fcf Mon Sep 17 00:00:00 2001 From: WeetHet Date: Wed, 25 Sep 2024 12:33:39 +0300 Subject: [PATCH 22/23] annotate humaneval-verus files --- .../000-has_close_elements.rs | 16 ++- .../001-separate-paren-groups.rs | 53 +++++++-- .../004-mean_absolute_derivation.rs | 102 ++++++++++++++++-- .../HumanEval-RustBench/005-intersperse.rs | 30 +++++- .../007-filter_by_substring.rs | 40 +++++-- .../HumanEval-RustBench/008-sum_product.rs | 18 +++- .../HumanEval-RustBench/009-rolling_max.rs | 12 ++- benches/HumanEval-RustBench/011-string_xor.rs | 12 ++- benches/HumanEval-RustBench/012-longest.rs | 8 +- .../HumanEval-RustBench/014-all_prefixes.rs | 28 +++-- benches/HumanEval-RustBench/023-strlen.rs | 9 +- .../024-largest-divisor.rs | 38 ++++++- .../HumanEval-RustBench/030-get-positive.rs | 14 ++- benches/HumanEval-RustBench/033-sort_third.rs | 38 +++++-- benches/HumanEval-RustBench/034-unique.rs | 26 ++++- .../HumanEval-RustBench/035-max-element.rs | 10 +- benches/HumanEval-RustBench/037-sort_even.rs | 10 +- benches/HumanEval-RustBench/042-incr-list.rs | 12 ++- .../043-pairs-sum-to-zero.rs | 12 ++- .../HumanEval-RustBench/045-triangle_area.rs | 20 ++-- .../HumanEval-RustBench/048-is-palindrome.rs | 8 +- benches/HumanEval-RustBench/049-modp.rs | 16 ++- .../HumanEval-RustBench/050-encode_shift.rs | 22 +++- .../052-below-threshold.rs | 8 +- benches/HumanEval-RustBench/053-add.rs | 6 +- benches/HumanEval-RustBench/054-same-chars.rs | 30 +++++- benches/HumanEval-RustBench/057-monotonic.rs | 8 +- .../059-largest-prime-factor.rs | 18 +++- benches/HumanEval-RustBench/060-sum_to_n.rs | 8 +- benches/HumanEval-RustBench/062-derivative.rs | 12 ++- benches/HumanEval-RustBench/063-fibfib.rs | 6 +- .../HumanEval-RustBench/064-vowel_count.rs | 18 +++- benches/HumanEval-RustBench/068-pluck.rs | 10 +- .../070-strange_sort_list.rs | 12 ++- .../HumanEval-RustBench/072-will_it_fly.rs | 28 ++++- .../073-smallest_change.rs | 14 ++- .../HumanEval-RustBench/074-total_match.rs | 18 +++- .../075-is_multiply_prime.rs | 37 ++++++- .../076-is_simple_power.rs | 8 +- benches/HumanEval-RustBench/077-is_cube.rs | 57 +++++++--- benches/HumanEval-RustBench/080-is_happy.rs | 14 ++- .../134-check_if_last_char_is_a_letter.rs | 6 +- .../136-largest_smallest_integers.rs | 8 +- 43 files changed, 746 insertions(+), 134 deletions(-) diff --git a/benches/HumanEval-RustBench/000-has_close_elements.rs b/benches/HumanEval-RustBench/000-has_close_elements.rs index bc65e22..64a5a7b 100644 --- a/benches/HumanEval-RustBench/000-has_close_elements.rs +++ b/benches/HumanEval-RustBench/000-has_close_elements.rs @@ -4,26 +4,34 @@ use vstd::slice::*; verus! { fn has_close_elements(numbers: &[i64], threshold: i64) -> (result: bool) + // post-conditions-start ensures result == exists|i: int, j: int| 0 <= i < j < numbers@.len() && abs(numbers[i] - numbers[j]) < threshold, + // post-conditions-end { + // impl-start if threshold <= 0 { + // assert-start assert(forall|i: int, j: int| 0 <= i < j < numbers@.len() ==> abs(numbers[i] - numbers[j]) >= 0 >= threshold); + // assert-end return false; } let max_minus_threshold: i64 = i64::MAX - threshold; let numbers_len: usize = numbers.len(); for x in 0..numbers_len + // invariants-start invariant max_minus_threshold == i64::MAX - threshold, numbers_len == numbers@.len(), forall|i: int, j: int| 0 <= i < j < numbers@.len() && i < x ==> abs(numbers[i] - numbers[j]) >= threshold, + // invariants-end { - let numbers_x: i64 = *slice_index_get(numbers, x); + let numbers_x: i64 = *slice_index_get(numbers, x); for y in x + 1..numbers_len + // invariants-start invariant max_minus_threshold == i64::MAX - threshold, numbers_len == numbers@.len(), @@ -33,8 +41,9 @@ fn has_close_elements(numbers: &[i64], threshold: i64) -> (result: bool) 0 <= i < j < numbers@.len() && i < x ==> abs(numbers[i] - numbers[j]) >= threshold, forall|j: int| x < j < y ==> abs(numbers_x - numbers[j]) >= threshold, + // invariants-end { - let numbers_y = *slice_index_get(numbers, y); + let numbers_y = *slice_index_get(numbers, y); if numbers_x > numbers_y { if numbers_y > max_minus_threshold { return true; @@ -53,7 +62,8 @@ fn has_close_elements(numbers: &[i64], threshold: i64) -> (result: bool) } } false + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/001-separate-paren-groups.rs b/benches/HumanEval-RustBench/001-separate-paren-groups.rs index 705368b..9b71633 100644 --- a/benches/HumanEval-RustBench/001-separate-paren-groups.rs +++ b/benches/HumanEval-RustBench/001-separate-paren-groups.rs @@ -4,6 +4,7 @@ verus! { pub open spec fn nesting_level(input: Seq) -> int decreases input.len(), { + // impl-start if input.len() == 0 { 0 } else { @@ -17,6 +18,7 @@ pub open spec fn nesting_level(input: Seq) -> int prev_nesting_level } } + // impl-end } pub open spec fn is_paren_char(c: char) -> bool { @@ -41,8 +43,11 @@ pub open spec fn remove_nonparens(s: Seq) -> Seq { s.filter(|c| is_paren_char(c)) } proof fn lemma_remove_nonparens_maintained_by_push(s: Seq, pos: int) + // pre-conditions-start requires 0 <= pos < s.len(), + // pre-conditions-end + // post-conditions-start ensures ({ let s1 = remove_nonparens(s.take(pos as int)); @@ -53,34 +58,45 @@ proof fn lemma_remove_nonparens_maintained_by_push(s: Seq, pos: int) s2 == s1 } }), + // post-conditions-end decreases pos, { + // impl-start reveal(Seq::filter); - assert(s.take((pos + 1) as int).drop_last() =~= s.take(pos as int)); + assert(s.take((pos + 1) as int).drop_last() =~= s.take(pos as int)); // assert-line if pos != 0 { lemma_remove_nonparens_maintained_by_push(s, pos - 1); } + // impl-end } fn separate_paren_groups(input: &Vec) -> (groups: Vec>) + // pre-conditions-start requires is_sequence_of_balanced_groups(input@), + // pre-conditions-end + // post-conditions-start ensures forall|i: int| #![trigger groups[i]] 0 <= i < groups.len() ==> is_balanced_group(groups[i]@), vecs_to_seqs(groups@).flatten() == remove_nonparens(input@), + // post-conditions-end { + // impl-start let mut groups: Vec> = Vec::new(); let mut current_group: Vec = Vec::new(); let input_len = input.len(); let ghost mut ghost_groups: Seq> = Seq::empty(); + // assert-start proof { assert(vecs_to_seqs(groups@) =~= ghost_groups); assert(remove_nonparens(input@.take(0)) =~= Seq::::empty()); assert(ghost_groups.flatten() + current_group@ =~= Seq::::empty()); } + // assert-end let mut current_nesting_level: usize = 0; for pos in 0..input_len + // invariants-start invariant input_len == input.len(), ghost_groups == vecs_to_seqs(groups@), @@ -90,66 +106,83 @@ fn separate_paren_groups(input: &Vec) -> (groups: Vec>) 0 <= i < ghost_groups.len() ==> is_balanced_group(ghost_groups[i]), current_nesting_level == nesting_level(input@.take(pos as int)), current_nesting_level == nesting_level(current_group@), - current_nesting_level <= pos, + current_nesting_level <= pos, current_group@.len() == 0 <==> current_nesting_level == 0, forall|i| 0 <= i < current_group@.len() ==> is_paren_char(#[trigger] current_group@[i]), forall|i| 0 < i < current_group@.len() ==> nesting_level(#[trigger] current_group@.take(i)) > 0, is_sequence_of_balanced_groups(input@), + // invariants-end { let ghost prev_group = current_group@; let ghost prev_groups = ghost_groups; let c = input[pos]; proof { - assert(input@.take((pos + 1) as int) == input@.take(pos as int).push(c)); - assert(input@.take((pos + 1) as int).drop_last() == input@.take(pos as int)); + assert(input@.take((pos + 1) as int) == input@.take(pos as int).push(c)); // assert-line + assert(input@.take((pos + 1) as int).drop_last() == input@.take(pos as int)); // assert-line lemma_remove_nonparens_maintained_by_push(input@, pos as int); } if c == '(' { current_nesting_level = current_nesting_level + 1; current_group.push('('); - assert(current_group@.drop_last() == prev_group); + assert(current_group@.drop_last() == prev_group); // assert-line + // assert-start assert(ghost_groups.flatten() + current_group@ =~= (ghost_groups.flatten() + prev_group).push('(')); + )); + // assert-end + // assert-start assert(forall|i| 0 < i < prev_group.len() ==> #[trigger] current_group@.take(i) == prev_group.take( i, )); + // assert-end } else if c == ')' { current_nesting_level = current_nesting_level - 1; current_group.push(')'); - assert(current_group@.drop_last() == prev_group); + assert(current_group@.drop_last() == prev_group); // assert-line + // assert-start assert(ghost_groups.flatten() + current_group@ =~= (ghost_groups.flatten() + prev_group).push(')')); + // assert-end + // assert-start assert(forall|i| 0 < i < prev_group.len() ==> #[trigger] current_group@.take(i) == prev_group.take( i, )); + // assert-end if current_nesting_level == 0 { proof { ghost_groups = ghost_groups.push(current_group@); + // assert-start assert(vecs_to_seqs(groups@.push(current_group)) =~= vecs_to_seqs(groups@).push( current_group@, )); - assert(ghost_groups.drop_last() == prev_groups); + // assert-end + assert(ghost_groups.drop_last() == prev_groups); // assert-line + // assert-start assert(ghost_groups.flatten() =~= prev_groups.flatten() + current_group@) by { prev_groups.lemma_flatten_and_flatten_alt_are_equivalent(); ghost_groups.lemma_flatten_and_flatten_alt_are_equivalent(); } + // assert-end } groups.push(current_group); current_group = Vec::::new(); + // assert-start assert(ghost_groups.flatten() + current_group@ =~= remove_nonparens( input@.take((pos + 1) as int), )); + // assert-end } } } - assert(input@.take(input_len as int) =~= input@); - assert(ghost_groups.flatten() + current_group@ == ghost_groups.flatten()); + assert(input@.take(input_len as int) =~= input@); // assert-line + assert(ghost_groups.flatten() + current_group@ == ghost_groups.flatten()); // assert-line groups + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/004-mean_absolute_derivation.rs b/benches/HumanEval-RustBench/004-mean_absolute_derivation.rs index 31daf3c..4d964bb 100644 --- a/benches/HumanEval-RustBench/004-mean_absolute_derivation.rs +++ b/benches/HumanEval-RustBench/004-mean_absolute_derivation.rs @@ -33,56 +33,81 @@ pub open spec fn spec_mean_absolute_deviation(numbers: Seq) -> int sum(numbers.map(|_index, n: int| abs(n - avg))) / (numbers.len() as int) } proof fn lemma_sum_bound(numbers: Seq, min: int, max: int) + // pre-conditions-start requires forall|i| 0 <= i < numbers.len() ==> min <= #[trigger] numbers[i] <= max, + // pre-conditions-end + // post-conditions-start ensures numbers.len() * min <= sum(numbers) <= numbers.len() * max, + // post-conditions-end decreases numbers.len(), { + // impl-start if numbers.len() != 0 { lemma_sum_bound(numbers.drop_last(), min, max); lemma_mul_is_distributive_add_other_way(min, numbers.len() - 1, 1); lemma_mul_is_distributive_add_other_way(max, numbers.len() - 1, 1); } + // impl-end } proof fn lemma_sum_ratio_bound(numbers: Seq, denominator: int, min: int, max: int) + // pre-conditions-start requires forall|i| 0 <= i < numbers.len() ==> min <= #[trigger] numbers[i] <= max, denominator >= numbers.len(), denominator > 0, min <= 0, max >= 0, + // pre-conditions-end + // post-conditions-start ensures min <= sum(numbers) / denominator <= max, + // post-conditions-end { + // impl-start lemma_sum_bound(numbers, min, max); + // assert-start assert(denominator * min <= numbers.len() * min) by { lemma_mul_unary_negation(denominator, -min); lemma_mul_unary_negation(numbers.len() as int, -min); lemma_mul_inequality(numbers.len() as int, denominator, -min); } + // assert-end + // assert-start assert(numbers.len() * max <= denominator * max) by { lemma_mul_inequality(numbers.len() as int, denominator, max); } + // assert-end lemma_div_multiples_vanish(min, denominator); lemma_div_multiples_vanish(max, denominator); lemma_div_is_ordered(denominator * min, sum(numbers), denominator); lemma_div_is_ordered(sum(numbers), denominator * max, denominator); + // impl-end } proof fn lemma_how_to_update_running_sum(s: Seq, i: int) + // pre-conditions-start requires 0 <= i < s.len(), + // pre-conditions-end + // post-conditions-start ensures sum(s.take(i + 1)) == sum(s.take(i)) + s[i], + // post-conditions-end { + // impl-start let q1 = s.take(i); let q2 = s.take(i + 1); - assert(q2.last() == s[i]); - assert(q2.drop_last() == q1); + assert(q2.last() == s[i]); // assert-line + assert(q2.drop_last() == q1); // assert-line + // impl-end } proof fn lemma_how_to_add_then_divide(x: int, y: int, d: int) + // pre-conditions-start requires d > 0, + // pre-conditions-end + // post-conditions-start ensures if (x % d) + (y % d) >= d { &&& (x + y) / d == (x / d) + (y / d) + 1 @@ -91,7 +116,9 @@ proof fn lemma_how_to_add_then_divide(x: int, y: int, d: int) &&& (x + y) / d == (x / d) + (y / d) &&& (x + y) % d == (x % d) + (y % d) }, + // post-conditions-end { + // impl-start lemma_fundamental_div_mod(x, d); lemma_fundamental_div_mod(y, d); lemma_mul_is_distributive_add(d, x / d, y / d); @@ -101,28 +128,40 @@ proof fn lemma_how_to_add_then_divide(x: int, y: int, d: int) } else { lemma_fundamental_div_mod_converse(x + y, d, (x / d) + (y / d), (x % d) + (y % d)); } + // impl-end } proof fn lemma_effect_of_dividing_by_two_or_more(x: int, d: int) + // pre-conditions-start requires d >= 2, + // pre-conditions-end + // post-conditions-start ensures x > 0 ==> x / d < x, x < 0 ==> x / d < 0, + // post-conditions-end { + // impl-start lemma_fundamental_div_mod(x, d); if x > 0 { lemma_div_is_ordered_by_denominator(x, 2, d); } + // impl-end } fn divide_i32_by_u32(x: i32, d: u32) -> (qr: (i32, u32)) + // pre-conditions-start requires d > 0, + // pre-conditions-end + // post-conditions-start ensures ({ let (q, r) = qr; q == x as int / d as int && r == x as int % d as int }), + // post-conditions-end { + // impl-start if x >= 0 { return ((x as u32 / d) as i32, x as u32 % d); } @@ -136,29 +175,36 @@ fn divide_i32_by_u32(x: i32, d: u32) -> (qr: (i32, u32)) } else { neg_x = (-x) as u32; } - assert(neg_x == -x); + assert(neg_x == -x); // assert-line let neg_x_div_d = neg_x / d; let neg_x_mod_d = neg_x % d; + // assert-start assert(neg_x == d * neg_x_div_d + neg_x_mod_d) by { lemma_fundamental_div_mod(neg_x as int, d as int); } + // assert-end + // assert-start assert(neg_x_div_d <= i32::MAX) by { if x == i32::MIN { lemma_mul_inequality(2, d as int, neg_x_div_d as int); } } + // assert-end if neg_x_mod_d == 0 { + // assert-start proof { lemma_mul_unary_negation(d as int, neg_x_div_d as int); - assert(x == d * -neg_x_div_d); + assert(x == d * -neg_x_div_d); // assert-line lemma_fundamental_div_mod_converse(x as int, d as int, -(neg_x_div_d as int), 0int); } + // assert-end (-(neg_x_div_d as i32), 0u32) } else { + // assert-start proof { lemma_mul_unary_negation(d as int, (neg_x_div_d + 1) as int); lemma_mul_is_distributive_add(d as int, neg_x_div_d as int, 1); - assert(x == d as int * (-neg_x_div_d - 1) + (d - neg_x_mod_d) as int); + assert(x == d as int * (-neg_x_div_d - 1) + (d - neg_x_mod_d) as int); // assert-line lemma_fundamental_div_mod_converse( x as int, d as int, @@ -166,30 +212,41 @@ fn divide_i32_by_u32(x: i32, d: u32) -> (qr: (i32, u32)) (d - neg_x_mod_d) as int, ); } + // assert-end (-(neg_x_div_d as i32) - 1, d - neg_x_mod_d) } + // impl-end } fn divide_i32_by_usize(x: i32, d: usize) -> (qr: (i32, usize)) + // pre-conditions-start requires d > 0, + // pre-conditions-end + // post-conditions-start ensures ({ let (q, r) = qr; q == x as int / d as int && r == x as int % d as int }), + // post-conditions-end { + // impl-start if d <= u32::MAX as usize { let (q, r) = divide_i32_by_u32(x, d as u32); (q, r as usize) } else if x >= 0 { + // assert-start assert(0 == x as int / d as int && x == x as int % d as int) by { lemma_fundamental_div_mod_converse(x as int, d as int, 0, x as int); } + // assert-end (0, x as usize) } else { + // assert-start assert(-1 == x as int / d as int && d + x == x as int % d as int) by { lemma_fundamental_div_mod_converse(x as int, d as int, -1, d + x); } + // assert-end let neg_x: usize = if x == i32::MIN { 0x80000000usize } else { @@ -197,25 +254,34 @@ fn divide_i32_by_usize(x: i32, d: usize) -> (qr: (i32, usize)) }; (-1, d - neg_x) } + // impl-end } fn compute_mean_of_i32s(numbers: &[i32]) -> (result: i32) + // pre-conditions-start requires numbers.len() > 0, + // pre-conditions-end + // post-conditions-start ensures result == mean(numbers@.map(|_index, n: i32| n as int)), + // post-conditions-end { + // impl-start let ghost nums = numbers@.map(|_index, n: i32| n as int); let mut quotient: i32 = 0; let mut remainder: usize = 0; let numbers_len: usize = numbers.len(); for i in 0..numbers_len + // invariants-start invariant quotient == sum(nums.take(i as int)) / numbers_len as int, remainder == sum(nums.take(i as int)) % numbers_len as int, numbers_len == numbers.len(), nums == numbers@.map(|_index, n: i32| n as int), + // invariants-end { let n = numbers[i]; + // assert-start proof { lemma_how_to_update_running_sum(nums, i as int); lemma_sum_ratio_bound( @@ -226,13 +292,16 @@ fn compute_mean_of_i32s(numbers: &[i32]) -> (result: i32) ); lemma_how_to_add_then_divide(sum(nums.take(i as int)), n as int, numbers_len as int); } + // assert-end let (q, r) = divide_i32_by_usize(n, numbers_len); if r >= numbers_len - remainder { + // assert-start assert(q < i32::MAX) by { lemma_effect_of_dividing_by_two_or_more(n as int, numbers_len as int); } + // assert-end remainder -= (numbers_len - r); quotient += (q + 1); } else { @@ -240,13 +309,17 @@ fn compute_mean_of_i32s(numbers: &[i32]) -> (result: i32) quotient += q; } } - assert(nums == nums.take(nums.len() as int)); + assert(nums == nums.take(nums.len() as int)); // assert-line quotient + // impl-end } fn compute_absolute_difference(x: i32, y: i32) -> (z: u32) + // post-conditions-start ensures z == abs(x - y), + // post-conditions-end { + // impl-start if x >= y { if y >= 0 || x < 0 { (x - y) as u32 @@ -270,13 +343,19 @@ fn compute_absolute_difference(x: i32, y: i32) -> (z: u32) y as u32 + neg_x } } + // impl-end } pub fn mean_absolute_deviation(numbers: &[i32]) -> (result: u32) + // pre-conditions-start requires numbers.len() > 0, + // pre-conditions-end + // post-conditions-start ensures result == spec_mean_absolute_deviation(numbers@.map(|_index, n: i32| n as int)), + // post-conditions-end { + // impl-start let numbers_mean: i32 = compute_mean_of_i32s(numbers); let ghost deviations = numbers@.map(|_index, n: i32| n as int).map( |_index, n: int| abs(n - numbers_mean), @@ -285,6 +364,7 @@ pub fn mean_absolute_deviation(numbers: &[i32]) -> (result: u32) let mut remainder: usize = 0; let numbers_len: usize = numbers.len(); for i in 0..numbers_len + // invariants-start invariant quotient == sum(deviations.take(i as int)) / numbers_len as int, remainder == sum(deviations.take(i as int)) % numbers_len as int, @@ -293,8 +373,10 @@ pub fn mean_absolute_deviation(numbers: &[i32]) -> (result: u32) deviations == numbers@.map(|_index, n: i32| n as int).map( |_index, n: int| abs(n - numbers_mean), ), + // invariants-end { let n: u32 = compute_absolute_difference(numbers[i], numbers_mean); + // assert-start proof { lemma_how_to_update_running_sum(deviations, i as int); lemma_sum_ratio_bound( @@ -309,14 +391,17 @@ pub fn mean_absolute_deviation(numbers: &[i32]) -> (result: u32) numbers_len as int, ); } + // assert-end let q: u32 = (n as usize / numbers_len) as u32; let r: usize = n as usize % numbers_len; if r >= numbers_len - remainder { + // assert-start assert(q < u32::MAX) by { lemma_effect_of_dividing_by_two_or_more(n as int, numbers_len as int); } + // assert-end remainder -= (numbers_len - r); quotient += (q + 1); } else { @@ -324,9 +409,10 @@ pub fn mean_absolute_deviation(numbers: &[i32]) -> (result: u32) quotient += q; } } - assert(deviations == deviations.take(deviations.len() as int)); + assert(deviations == deviations.take(deviations.len() as int)); // assert-line quotient + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/005-intersperse.rs b/benches/HumanEval-RustBench/005-intersperse.rs index b3bfa03..d60f053 100644 --- a/benches/HumanEval-RustBench/005-intersperse.rs +++ b/benches/HumanEval-RustBench/005-intersperse.rs @@ -5,11 +5,13 @@ verus! { pub open spec fn intersperse_spec(numbers: Seq, delimiter: u64) -> Seq decreases numbers.len(), { + // impl-start if numbers.len() <= 1 { numbers } else { intersperse_spec(numbers.drop_last(), delimiter) + seq![delimiter, numbers.last()] } + // impl-end } spec fn even(i: int) -> int { 2 * i @@ -29,26 +31,35 @@ spec fn intersperse_quantified(numbers: Seq, delimiter: u64, interspersed: } proof fn intersperse_spec_len(numbers: Seq, delimiter: u64) + // post-conditions-start ensures numbers.len() > 0 ==> intersperse_spec(numbers, delimiter).len() == 2 * numbers.len() - 1, + // post-conditions-end decreases numbers.len(), { + // impl-start if numbers.len() > 0 { intersperse_spec_len(numbers.drop_last(), delimiter); } + // impl-end } proof fn intersperse_quantified_is_spec(numbers: Seq, delimiter: u64, interspersed: Seq) + // pre-conditions-start requires intersperse_quantified(numbers, delimiter, interspersed), + // pre-conditions-end + // post-conditions-start ensures interspersed == intersperse_spec(numbers, delimiter), + // post-conditions-end decreases numbers.len(), { + // impl-start let is = intersperse_spec(numbers, delimiter); if numbers.len() == 0 { } else if numbers.len() == 1 { - assert(interspersed.len() == 1); - assert(interspersed[even(0)] == numbers[0]); + assert(interspersed.len() == 1); // assert-line + assert(interspersed[even(0)] == numbers[0]); // assert-line } else { intersperse_quantified_is_spec( numbers.drop_last(), @@ -56,6 +67,7 @@ proof fn intersperse_quantified_is_spec(numbers: Seq, delimiter: u64, inter interspersed.take(interspersed.len() - 2), ); intersperse_spec_len(numbers, delimiter); + // assert-start assert_seqs_equal!(is == interspersed, i => { if i < is.len() - 2 { } else { @@ -69,37 +81,47 @@ proof fn intersperse_quantified_is_spec(numbers: Seq, delimiter: u64, inter } } }); + // assert-end } - assert(interspersed =~= intersperse_spec(numbers, delimiter)); + assert(interspersed =~= intersperse_spec(numbers, delimiter)); // assert-line + // impl-end } pub fn intersperse(numbers: Vec, delimiter: u64) -> (result: Vec) + // post-conditions-start ensures result@ == intersperse_spec(numbers@, delimiter), + // post-conditions-end { + // impl-start if numbers.len() <= 1 { numbers } else { let mut result = Vec::new(); let mut index = 0; while index < numbers.len() - 1 + // invariants-start invariant numbers.len() > 1, 0 <= index < numbers.len(), result.len() == 2 * index, forall|i: int| 0 <= i < index ==> #[trigger] result[even(i)] == numbers[i], forall|i: int| 0 <= i < index ==> #[trigger] result[odd(i)] == delimiter, + // invariants-end { result.push(numbers[index]); result.push(delimiter); index += 1; } result.push(numbers[numbers.len() - 1]); + // assert-start proof { intersperse_quantified_is_spec(numbers@, delimiter, result@); } + // assert-end result } + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/007-filter_by_substring.rs b/benches/HumanEval-RustBench/007-filter_by_substring.rs index 06f0295..a169676 100644 --- a/benches/HumanEval-RustBench/007-filter_by_substring.rs +++ b/benches/HumanEval-RustBench/007-filter_by_substring.rs @@ -3,63 +3,76 @@ use vstd::prelude::*; verus! { fn string_eq(s1: &str, s2: &str) -> (result: bool) + // post-conditions-start ensures result <==> s1@ == s2@, + // post-conditions-end { + // impl-start let s1_len = s1.unicode_len(); let s2_len = s2.unicode_len(); if s1_len != s2_len { return false; } for i in 0..s1_len + // invariants-start invariant s1@.subrange(0, i as int) =~= s2@.subrange(0, i as int), i <= s1_len == s2_len == s1@.len() == s2@.len(), + // invariants-end { let c = s1.get_char(i); if c != s2.get_char(i) { return false; } - assert(s1@.subrange(0, i + 1) == s1@.subrange(0, i as int).push(c)); - assert(s1@.subrange(0, i as int).push(c) == s2@.subrange(0, i as int).push(c)); - assert(s2@.subrange(0, i as int).push(c) == s2@.subrange(0, i + 1)); + assert(s1@.subrange(0, i + 1) == s1@.subrange(0, i as int).push(c)); // assert-line + assert(s1@.subrange(0, i as int).push(c) == s2@.subrange(0, i as int).push(c)); // assert-line + assert(s2@.subrange(0, i as int).push(c) == s2@.subrange(0, i + 1)); // assert-line } - assert(s1@ == s1@.subrange(0, s1_len as int)); - assert(s2@ == s2@.subrange(0, s2_len as int)); + assert(s1@ == s1@.subrange(0, s1_len as int)); // assert-line + assert(s2@ == s2@.subrange(0, s2_len as int)); // assert-line true + // impl-end } fn check_substring(s: &str, sub: &str) -> (result: bool) + // post-conditions-start ensures result <==> exists|i: int| 0 <= i <= s@.len() - sub@.len() && s@.subrange(i, #[trigger] (i + sub@.len())) == sub@, + // post-conditions-end { + // impl-start let s_len = s.unicode_len(); let sub_len = sub.unicode_len(); if (s_len < sub_len) { return false; } if sub_len == 0 { - assert(s@.subrange(0, (0 + sub@.len()) as int) == sub@); + assert(s@.subrange(0, (0 + sub@.len()) as int) == sub@); // assert-line return true; } for i in 0..s_len - sub_len + 1 + // invariants-start invariant forall|j: int| 0 <= j < i ==> s@.subrange(j, #[trigger] (j + sub@.len())) != sub@, i <= s_len - sub_len + 1, sub_len == sub@.len() <= s_len == s@.len(), sub_len > 0, + // invariants-end { if string_eq(sub, s.substring_char(i, i + sub_len)) { - assert(0 <= i <= s@.len() - sub@.len()); - assert(s@.subrange(i as int, i + sub@.len()) == sub@); + assert(0 <= i <= s@.len() - sub@.len()); // assert-line + assert(s@.subrange(i as int, i + sub@.len()) == sub@); // assert-line return true; } } false + // impl-end } fn filter_by_substring<'a>(strings: &Vec<&'a str>, substring: &str) -> (res: Vec<&'a str>) + // post-conditions-start ensures forall|i: int| 0 <= i < strings@.len() && (exists|j: int| @@ -67,9 +80,12 @@ fn filter_by_substring<'a>(strings: &Vec<&'a str>, substring: &str) -> (res: Vec j, #[trigger] (j + substring@.len()), ) == substring@) ==> res@.contains(#[trigger] (strings[i])), + // post-conditions-end { + // impl-start let mut res = Vec::new(); for n in 0..strings.len() + // invariants-start invariant forall|i: int| 0 <= i < n && (exists|j: int| @@ -77,16 +93,18 @@ fn filter_by_substring<'a>(strings: &Vec<&'a str>, substring: &str) -> (res: Vec j, #[trigger] (j + substring@.len()), ) == substring@) ==> res@.contains(#[trigger] (strings[i])), + // invariants-end { if check_substring(strings[n], substring) { let ghost res_old = res; res.push(strings[n]); - assert(res@.last() == strings[n as int]); - assert(res@.drop_last() == res_old@); + assert(res@.last() == strings[n as int]); // assert-line + assert(res@.drop_last() == res_old@); // assert-line } } res + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/008-sum_product.rs b/benches/HumanEval-RustBench/008-sum_product.rs index f02906a..7bbe3fb 100644 --- a/benches/HumanEval-RustBench/008-sum_product.rs +++ b/benches/HumanEval-RustBench/008-sum_product.rs @@ -18,28 +18,37 @@ proof fn sum_bound(numbers: Seq) } } fn sum_product(numbers: Vec) -> (result: (u64, Option)) + // pre-conditions-start requires numbers.len() < u32::MAX, + // pre-conditions-end + // post-conditions-start ensures result.0 == sum(numbers@), result.1 matches Some(v) ==> v == product(numbers@), + // post-conditions-end { + // impl-start let mut sum_value: u64 = 0; let mut prod_value: Option = Some(1); for index in 0..numbers.len() + // invariants-start invariant numbers.len() < u32::MAX, sum_value == sum(numbers@.take(index as int)), prod_value matches Some(v) ==> v == product(numbers@.take(index as int)), index <= numbers.len(), index >= 0, + // invariants-end { + // assert-start proof { sum_bound(numbers@.take(index as int)); assert(sum_value <= index * u32::MAX); } - assert(numbers@.take(index as int + 1).drop_last() =~= numbers@.take(index as int)); - assert(numbers[index as int] == numbers@.take(index as int + 1).last()); + // assert-end + assert(numbers@.take(index as int + 1).drop_last() =~= numbers@.take(index as int)); // assert-line + assert(numbers[index as int] == numbers@.take(index as int + 1).last()); // assert-line sum_value += numbers[index] as u64; prod_value = match prod_value { @@ -47,9 +56,10 @@ fn sum_product(numbers: Vec) -> (result: (u64, Option)) None => None, }; } - assert(numbers@.take(numbers@.len() as int) =~= numbers@); + assert(numbers@.take(numbers@.len() as int) =~= numbers@); // assert-line (sum_value, prod_value) + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/009-rolling_max.rs b/benches/HumanEval-RustBench/009-rolling_max.rs index b1203a5..1516427 100644 --- a/benches/HumanEval-RustBench/009-rolling_max.rs +++ b/benches/HumanEval-RustBench/009-rolling_max.rs @@ -15,27 +15,33 @@ spec fn seq_max(a: Seq) -> i32 } fn rolling_max(numbers: Vec) -> (result: Vec) + // post-conditions-start ensures - result.len() == numbers.len(), + result.len() == numbers.len(), forall|i: int| 0 <= i < numbers.len() ==> result[i] == seq_max(numbers@.take(i + 1)), + // post-conditions-end { + // impl-start let mut max_so_far = i32::MIN; let mut result = Vec::with_capacity(numbers.len()); for pos in 0..numbers.len() + // invariants-start invariant result.len() == pos, max_so_far == seq_max(numbers@.take(pos as int)), forall|i: int| 0 <= i < pos ==> result[i] == seq_max(numbers@.take(i + 1)), + // invariants-end { let number = numbers[pos]; if number > max_so_far { max_so_far = number; } result.push(max_so_far); - assert(numbers@.take((pos + 1) as int).drop_last() =~= numbers@.take(pos as int)); + assert(numbers@.take((pos + 1) as int).drop_last() =~= numbers@.take(pos as int)); // assert-line } result + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/011-string_xor.rs b/benches/HumanEval-RustBench/011-string_xor.rs index 7a9cef4..00709ed 100644 --- a/benches/HumanEval-RustBench/011-string_xor.rs +++ b/benches/HumanEval-RustBench/011-string_xor.rs @@ -18,22 +18,29 @@ spec fn xor_char(a: char, b: char) -> (result: char) } fn string_xor(a: &[char], b: &[char]) -> (result: Vec) + // pre-conditions-start requires - a@.len() == b@.len(), + a@.len() == b@.len(), forall|i: int| 0 <= i < a@.len() as int ==> is_binary_digit(#[trigger] a[i]), forall|i: int| 0 <= i < b@.len() as int ==> is_binary_digit(#[trigger] b[i]), + // pre-conditions-end + // post-conditions-start ensures result.len() == a@.len(), forall|i: int| 0 <= i < result.len() as int ==> #[trigger] result[i] == xor_char(a[i], b[i]), + // post-conditions-end { + // impl-start let a_len = a.len(); let mut result = Vec::with_capacity(a_len); #[verifier::loop_isolation(false)] for pos in 0..a_len + // invariants-start invariant result.len() == pos, forall|i: int| 0 <= i < pos ==> #[trigger] result[i] == xor_char(a[i], b[i]), + // invariants-end { if *slice_index_get(a, pos) == *slice_index_get(b, pos) { result.push('0'); @@ -42,7 +49,8 @@ fn string_xor(a: &[char], b: &[char]) -> (result: Vec) } } result + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/012-longest.rs b/benches/HumanEval-RustBench/012-longest.rs index e12aaab..96b7335 100644 --- a/benches/HumanEval-RustBench/012-longest.rs +++ b/benches/HumanEval-RustBench/012-longest.rs @@ -3,6 +3,7 @@ use vstd::prelude::*; verus! { fn longest(strings: &Vec>) -> (result: Option<&Vec>) + // post-conditions-start ensures match result { None => strings.len() == 0, @@ -15,7 +16,9 @@ fn longest(strings: &Vec>) -> (result: Option<&Vec>) 0 <= j < i ==> strings[j].len() < s.len()))) }, }, + // post-conditions-end { + // impl-start if strings.len() == 0 { return None; } @@ -23,12 +26,14 @@ fn longest(strings: &Vec>) -> (result: Option<&Vec>) let mut pos = 0; for i in 1..strings.len() + // invariants-start invariant 0 <= pos < i, result == &strings[pos as int], exists|i: int| 0 <= i < strings.len() && strings[i] == result, forall|j: int| #![auto] 0 <= j < i ==> strings[j].len() <= result.len(), forall|j: int| #![auto] 0 <= j < pos ==> strings[j].len() < result.len(), + // invariants-end { if result.len() < strings[i].len() { result = &strings[i]; @@ -36,7 +41,8 @@ fn longest(strings: &Vec>) -> (result: Option<&Vec>) } } Some(result) + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/014-all_prefixes.rs b/benches/HumanEval-RustBench/014-all_prefixes.rs index 56b977b..cbd0d1e 100644 --- a/benches/HumanEval-RustBench/014-all_prefixes.rs +++ b/benches/HumanEval-RustBench/014-all_prefixes.rs @@ -3,52 +3,68 @@ use vstd::prelude::*; verus! { fn all_prefixes(s: &Vec) -> (prefixes: Vec>) + // post-conditions-start ensures prefixes.len() == s.len(), forall|i: int| #![auto] 0 <= i < s.len() ==> prefixes[i]@ == s@.subrange(0, i + 1), + // post-conditions-end { + // impl-start let mut prefixes: Vec> = vec![]; let mut prefix = vec![]; + // assert-start assert(forall|i: int| #![auto] 0 <= i < prefix.len() ==> prefix@.index(i) == prefix@.subrange( 0, prefix.len() as int, ).index(i)); + // assert-end - assert(prefix@ == prefix@.subrange(0, 0)); + assert(prefix@ == prefix@.subrange(0, 0)); // assert-line + // assert-start assert(forall|i: int| #![auto] 0 <= i < prefix.len() ==> prefix@.index(i) == s@.subrange(0, prefix.len() as int).index(i)); - assert(prefix@ == s@.subrange(0, 0)); + // assert-end + assert(prefix@ == s@.subrange(0, 0)); // assert-line for i in 0..s.len() + // invariants-start invariant prefixes.len() == i, prefix.len() == i, forall|j: int| #![auto] 0 <= j < i ==> prefixes[j]@ == s@.subrange(0, j + 1), prefix@ == s@.subrange(0, i as int), prefix@ == prefix@.subrange(0, i as int), + // invariants-end { let ghost pre_prefix = prefix; prefix.push(s[i]); + // assert-start assert(pre_prefix@.subrange(0, i as int) == pre_prefix@ && prefix@.subrange(0, i as int) == pre_prefix@.subrange(0, i as int)); - assert(prefix@.subrange(0, i as int) == s@.subrange(0, i as int)); - assert(prefix[i as int] == s@.subrange(0, i + 1).index(i as int)); + // assert-end + assert(prefix@.subrange(0, i as int) == s@.subrange(0, i as int)); // assert-line + assert(prefix[i as int] == s@.subrange(0, i + 1).index(i as int)); // assert-line + // assert-start assert(forall|j: int| #![auto] 0 <= j < i + 1 ==> prefix@.index(j) == prefix@.subrange(0, (i + 1) as int).index(j)); + // assert-end assert(prefix@ == prefix@.subrange(0, (i + 1) as int)); + // assert-start assert(forall|j: int| #![auto] 0 <= j < i + 1 ==> prefix@.index(j) == s@.subrange(0, (i + 1) as int).index(j)); - assert(prefix@ == s@.subrange(0, (i + 1) as int)); + // assert-end + assert(prefix@ == s@.subrange(0, (i + 1) as int)); // assert-line prefixes.push(prefix.clone()); } return prefixes; + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/023-strlen.rs b/benches/HumanEval-RustBench/023-strlen.rs index a9e0d4e..25b921a 100644 --- a/benches/HumanEval-RustBench/023-strlen.rs +++ b/benches/HumanEval-RustBench/023-strlen.rs @@ -3,12 +3,15 @@ use vstd::prelude::*; verus! { fn strlen(string: &Vec) -> (length: usize) + // post-conditions-start ensures - length - == string.len(), + length == string.len(), + // post-conditions-end { + // impl-start string.len() + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/024-largest-divisor.rs b/benches/HumanEval-RustBench/024-largest-divisor.rs index e5f6108..3637e73 100644 --- a/benches/HumanEval-RustBench/024-largest-divisor.rs +++ b/benches/HumanEval-RustBench/024-largest-divisor.rs @@ -12,59 +12,89 @@ pub open spec fn divides(factor: nat, candidate: nat) -> bool { exists|k: nat| mul(factor, k) == candidate } proof fn lemma_mod_zero(a: nat, b: nat) + // pre-conditions-start requires a > 0 && b > 0, a % b == 0, + // pre-conditions-end + // post-conditions-start ensures divides(b, a), + // post-conditions-end { + // impl-start lemma_fundamental_div_mod(a as int, b as int); - assert(mul(b, (a / b)) == a); + assert(mul(b, (a / b)) == a); // assert-line + // impl-end } proof fn lemma_mod_zero_reversed(a: nat, b: nat) + // pre-conditions-start requires a > 0 && b > 0, divides(b, a), + // pre-conditions-end + // post-conditions-start ensures a % b == 0, + // post-conditions-end { + // impl-start let k_wit = choose|k: nat| mul(b, k) == a; + // assert-start assert(k_wit == a / b) by { lemma_fundamental_div_mod_converse_div(a as int, b as int, k_wit as int, 0 as int); } + // assert-end lemma_fundamental_div_mod(a as int, b as int); + // impl-end } proof fn lemma_one_divides_all() + // post-conditions-start ensures forall|v: nat| divides(1 as nat, v), + // post-conditions-end { + // impl-start + // assert-start assert forall|v: nat| divides(1 as nat, v) by { assert(mul(1 as nat, v) == v); } + // assert-end + // impl-end } fn largest_divisor(n: u32) -> (ret: u32) + // pre-conditions-start requires n > 1, + // pre-conditions-end + // post-conditions-start ensures divides(ret as nat, n as nat), ret < n, forall|k: u32| (0 < k < n && divides(k as nat, n as nat)) ==> ret >= k, + // post-conditions-end { + // impl-start let mut i = n - 1; while i >= 2 + // invariants-start invariant n > 0, i < n, forall|k: u32| i < k < n ==> !divides(k as nat, n as nat), + // invariants-end { if n % i == 0 { + // assert-start assert(divides(i as nat, n as nat)) by { lemma_mod_zero(n as nat, i as nat); } + // assert-end return i; } i -= 1; + // assert-start assert forall|k: u32| i < k < n implies !divides(k as nat, n as nat) by { if k == i + 1 { assert(!divides(k as nat, n as nat)) by { @@ -74,12 +104,16 @@ fn largest_divisor(n: u32) -> (ret: u32) } } } + // assert-end } + // assert-start assert(divides(1 as nat, n as nat)) by { lemma_one_divides_all(); } + // assert-end 1 + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/030-get-positive.rs b/benches/HumanEval-RustBench/030-get-positive.rs index 18c71fb..a85afd1 100644 --- a/benches/HumanEval-RustBench/030-get-positive.rs +++ b/benches/HumanEval-RustBench/030-get-positive.rs @@ -3,27 +3,33 @@ use vstd::prelude::*; verus! { fn get_positive(input: Vec) -> (positive_list: Vec) + // post-conditions-start ensures positive_list@ == input@.filter(|x: i32| x > 0), + // post-conditions-end { + // impl-start let mut positive_list = Vec::::new(); let input_len = input.len(); - assert(input@.take(0int).filter(|x: i32| x > 0) == Seq::::empty()); + assert(input@.take(0int).filter(|x: i32| x > 0) == Seq::::empty()); // assert-line for pos in 0..input_len + // invariants-start invariant input_len == input.len(), positive_list@ == input@.take(pos as int).filter(|x: i32| x > 0), + // invariants-end { let n = input[pos]; if n > 0 { positive_list.push(n); } - assert(input@.take((pos + 1) as int).drop_last() == input@.take(pos as int)); + assert(input@.take((pos + 1) as int).drop_last() == input@.take(pos as int)); // assert-line reveal(Seq::filter); } - assert(input@ == input@.take(input_len as int)); + assert(input@ == input@.take(input_len as int)); // assert-line positive_list + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/033-sort_third.rs b/benches/HumanEval-RustBench/033-sort_third.rs index a946a36..a21f222 100644 --- a/benches/HumanEval-RustBench/033-sort_third.rs +++ b/benches/HumanEval-RustBench/033-sort_third.rs @@ -18,8 +18,11 @@ spec fn permutes(s1: Seq, s2: Seq) -> bool { forall|x: T| count(s1, x) == count(s2, x) } proof fn lemma_update_effect_on_count(s: Seq, i: int, v: T, x: T) + // pre-conditions-start requires 0 <= i < s.len(), + // pre-conditions-end + // post-conditions-start ensures count(s.update(i, v), x) == if v == x && s[i] != x { count(s, x) + 1 @@ -28,45 +31,60 @@ proof fn lemma_update_effect_on_count(s: Seq, i: int, v: T, x: T) } else { count(s, x) }, + // post-conditions-end decreases s.len(), { + // impl-start if s.len() == 0 { return ; } if i == 0 { - assert(s.update(i, v) =~= seq![v] + s.skip(1)); - assert(s.update(i, v).skip(1) =~= s.skip(1)); + assert(s.update(i, v) =~= seq![v] + s.skip(1)); // assert-line + assert(s.update(i, v).skip(1) =~= s.skip(1)); // assert-line } else { - assert(s.update(i, v) =~= seq![s[0]] + s.skip(1).update(i - 1, v)); - assert(s.update(i, v).skip(1) =~= s.skip(1).update(i - 1, v)); + assert(s.update(i, v) =~= seq![s[0]] + s.skip(1).update(i - 1, v)); // assert-line + assert(s.update(i, v).skip(1) =~= s.skip(1).update(i - 1, v)); // assert-line lemma_update_effect_on_count(s.skip(1), i - 1, v, x); } + // impl-end } proof fn lemma_swapping_produces_a_permutation(s: Seq, i: int, j: int) + // pre-conditions-start requires 0 <= i < s.len(), 0 <= j < s.len(), + // pre-conditions-end + // post-conditions-start ensures permutes(s.update(i, s[j]).update(j, s[i]), s), + // post-conditions-end { + // impl-start + // assert-start assert forall|x: T| #[trigger] count(s.update(i, s[j]).update(j, s[i]), x) == count(s, x) by { lemma_update_effect_on_count(s, i, s[j], x); lemma_update_effect_on_count(s.update(i, s[j]), j, s[i], x); } + // assert-end + // impl-end } fn sort_third(l: Vec) -> (l_prime: Vec) + // post-conditions-start ensures l_prime.len() == l.len(), - forall|i: int| 0 <= i < l.len() && i % 3 != 0 ==> l_prime[i] == l[i], + forall|i: int| 0 <= i < l.len() && i % 3 != 0 ==> l_prime[i] == l[i], forall|i: int, j: int| 0 <= i < j < l.len() && i % 3 == 0 && j % 3 == 0 ==> l_prime[i] <= l_prime[j], - permutes(l_prime@, l@), + permutes(l_prime@, l@), + // post-conditions-end { + // impl-start let ghost old_l = l@; let l_len = l.len(); let mut pos_being_set_to_smallest: usize = 0; let mut l_prime: Vec = l; while pos_being_set_to_smallest < l_len + // invariants-start invariant l_len == l.len() == l_prime.len(), pos_being_set_to_smallest % 3 == 0, @@ -75,10 +93,12 @@ fn sort_third(l: Vec) -> (l_prime: Vec) forall|i: int, j: int| 0 <= i < pos_being_set_to_smallest && i < j < l_len && i % 3 == 0 && j % 3 == 0 ==> l_prime[i] <= l_prime[j], + // invariants-end { let mut pos_of_smallest_found_so_far: usize = pos_being_set_to_smallest; let mut pos_during_scan_for_smallest: usize = pos_being_set_to_smallest; while pos_during_scan_for_smallest < l_len + // invariants-start invariant l_len == l.len() == l_prime.len(), pos_being_set_to_smallest % 3 == 0, @@ -94,12 +114,14 @@ fn sort_third(l: Vec) -> (l_prime: Vec) forall|i: int, j: int| 0 <= i < pos_being_set_to_smallest && i < j < l_len && i % 3 == 0 && j % 3 == 0 ==> l_prime[i] <= l_prime[j], + // invariants-end { if l_prime[pos_during_scan_for_smallest] < l_prime[pos_of_smallest_found_so_far] { pos_of_smallest_found_so_far = pos_during_scan_for_smallest; } pos_during_scan_for_smallest = pos_during_scan_for_smallest + 3; } + // assert-start proof { lemma_swapping_produces_a_permutation( l_prime@, @@ -107,6 +129,7 @@ fn sort_third(l: Vec) -> (l_prime: Vec) pos_of_smallest_found_so_far as int, ); } + // assert-end let v1 = l_prime[pos_being_set_to_smallest]; let v2 = l_prime[pos_of_smallest_found_so_far]; l_prime.set(pos_being_set_to_smallest, v2); @@ -114,7 +137,8 @@ fn sort_third(l: Vec) -> (l_prime: Vec) pos_being_set_to_smallest = pos_being_set_to_smallest + 3; } l_prime + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/034-unique.rs b/benches/HumanEval-RustBench/034-unique.rs index f4c8c90..3ef7eb5 100644 --- a/benches/HumanEval-RustBench/034-unique.rs +++ b/benches/HumanEval-RustBench/034-unique.rs @@ -113,15 +113,21 @@ fn sort_seq(s: &Vec) -> (ret: Vec) } fn unique_sorted(s: Vec) -> (result: Vec) + // pre-conditions-start requires forall|i: int, j: int| 0 <= i < j < s.len() ==> s[i] <= s[j], + // pre-conditions-end + // post-conditions-start ensures forall|i: int, j: int| 0 <= i < j < result.len() ==> result[i] < result[j], forall|i: int| #![auto] 0 <= i < result.len() ==> s@.contains(result[i]), forall|i: int| #![trigger s[i]] 0 <= i < s.len() ==> result@.contains(s[i]), + // post-conditions-end { + // impl-start let mut result: Vec = vec![]; for i in 0..s.len() + // invariants-start invariant forall|i: int, j: int| 0 <= i < j < s.len() ==> s[i] <= s[j], forall|k: int, l: int| 0 <= k < l < result.len() ==> result[k] < result[l], @@ -129,35 +135,47 @@ fn unique_sorted(s: Vec) -> (result: Vec) #![trigger result[k]] 0 <= k < result.len() ==> (exists|m: int| 0 <= m < i && result[k] == s[m]), forall|m: int| #![trigger s[m]] 0 <= m < i ==> result@.contains(s[m]), + // invariants-end { let ghost pre = result; if result.len() == 0 || result[result.len() - 1] != s[i] { - assert(result.len() == 0 || result[result.len() - 1] < s[i as int]); + assert(result.len() == 0 || result[result.len() - 1] < s[i as int]); // assert-line result.push(s[i]); + // assert-start assert forall|m: int| #![trigger s[m]] 0 <= m < i implies result@.contains(s[m]) by { assert(pre@.contains(s@[m])); lemma_seq_contains_after_push(pre@, s@[i as int], s@[m]); }; + // assert-end } + // assert-start assert(forall|m: int| #![trigger result@[m], pre@[m]] 0 <= m < pre.len() ==> pre@.contains(result@[m]) ==> result@.contains(pre@[m])) by { assert(forall|m: int| 0 <= m < pre.len() ==> result@[m] == pre@[m]); } + // assert-end + // assert-start assert(result@.contains(s[i as int])) by { assert(result[result.len() - 1] == s[i as int]); } + // assert-end } result + // impl-end } fn unique(s: Vec) -> (result: Vec) + // post-conditions-start ensures forall|i: int, j: int| 0 <= i < j < result.len() ==> result[i] < result[j], forall|i: int| #![auto] 0 <= i < result.len() ==> s@.contains(result[i]), forall|i: int| #![trigger s[i]] 0 <= i < s.len() ==> result@.contains(s[i]), + // post-conditions-end { + // impl-start let sorted = sort_seq(&s); + // assert-start assert(forall|i: int| #![auto] 0 <= i < sorted.len() ==> s@.contains(sorted[i])) by { assert(forall|i: int| #![auto] @@ -169,6 +187,8 @@ fn unique(s: Vec) -> (result: Vec) 0 <= i < sorted.len() ==> s@.to_multiset().contains(sorted[i])); s@.to_multiset_ensures(); } + // assert-end + // assert-start assert(forall|i: int| #![trigger s[i]] 0 <= i < s.len() ==> sorted@.contains(s[i])) by { assert(forall|i: int| #![auto] 0 <= i < s.len() ==> s@.to_multiset().contains(s[i])) by { s@.to_multiset_ensures(); @@ -176,8 +196,10 @@ fn unique(s: Vec) -> (result: Vec) assert(forall|i: int| #![auto] 0 <= i < s.len() ==> sorted@.to_multiset().contains(s[i])); sorted@.to_multiset_ensures(); } + // assert-end unique_sorted(sorted) + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/035-max-element.rs b/benches/HumanEval-RustBench/035-max-element.rs index 5b6dda5..c09398f 100644 --- a/benches/HumanEval-RustBench/035-max-element.rs +++ b/benches/HumanEval-RustBench/035-max-element.rs @@ -3,24 +3,32 @@ use vstd::prelude::*; verus! { fn max_element(a: &Vec) -> (max: i32) + // pre-conditions-start requires a.len() > 0, + // pre-conditions-end + // post-conditions-start ensures forall|i: int| 0 <= i < a.len() ==> a[i] <= max, exists|i: int| 0 <= i < a.len() && a[i] == max, + // post-conditions-end { + // impl-start let mut max = a[0]; for i in 1..a.len() + // invariants-start invariant forall|j: int| 0 <= j < i ==> a[j] <= max, exists|j: int| 0 <= j < i && a[j] == max, + // invariants-end { if a[i] > max { max = a[i]; } } max + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/037-sort_even.rs b/benches/HumanEval-RustBench/037-sort_even.rs index 4cf1fe8..886d44b 100644 --- a/benches/HumanEval-RustBench/037-sort_even.rs +++ b/benches/HumanEval-RustBench/037-sort_even.rs @@ -120,6 +120,7 @@ fn sort_pred(l: Vec, p: Vec) -> (l_prime: Vec) #[verifier::loop_isolation(false)] fn sort_even(l: Vec) -> (result: Vec) + // post-conditions-start ensures l.len() == result.len(), permutes(result@, l@), @@ -127,20 +128,27 @@ fn sort_even(l: Vec) -> (result: Vec) forall|i: int, j: int| #![auto] 0 <= i < j < l.len() && i % 2 == 0 && j % 2 == 0 ==> result[i] <= result[j], + // post-conditions-end { + // impl-start let mut p: Vec = vec![]; for i in 0..l.len() + // invariants-start invariant p.len() == i, forall|j: int| 0 <= j < i ==> p[j] == (j % 2 == 0), + // invariants-end { p.push(i % 2 == 0); } + // assert-start assert(forall|i: int, j: int| #![auto] 0 <= i < j < l.len() && i % 2 == 0 && j % 2 == 0 ==> p[i] && p[j]); + // assert-end sort_pred(l, p) + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/042-incr-list.rs b/benches/HumanEval-RustBench/042-incr-list.rs index cf7de96..781318f 100644 --- a/benches/HumanEval-RustBench/042-incr-list.rs +++ b/benches/HumanEval-RustBench/042-incr-list.rs @@ -3,24 +3,32 @@ use vstd::prelude::*; verus! { fn incr_list(l: Vec) -> (result: Vec) + // pre-conditions-start requires - forall|i: int| 0 <= i < l.len() ==> l[i] + 1 <= i32::MAX, + forall|i: int| 0 <= i < l.len() ==> l[i] + 1 <= i32::MAX, + // pre-conditions-end + // post-conditions-start ensures result.len() == l.len(), forall|i: int| 0 <= i < l.len() ==> #[trigger] result[i] == l[i] + 1, + // post-conditions-end { + // impl-start let mut result = Vec::with_capacity(l.len()); for i in 0..l.len() + // invariants-start invariant forall|i: int| 0 <= i < l.len() ==> l[i] + 1 <= i32::MAX, result.len() == i, forall|j: int| 0 <= j < i ==> #[trigger] result[j] == l[j] + 1, + // invariants-end { result.push(l[i] + 1); } result + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/043-pairs-sum-to-zero.rs b/benches/HumanEval-RustBench/043-pairs-sum-to-zero.rs index 78381ce..dc35b82 100644 --- a/benches/HumanEval-RustBench/043-pairs-sum-to-zero.rs +++ b/benches/HumanEval-RustBench/043-pairs-sum-to-zero.rs @@ -4,28 +4,37 @@ verus! { #[verifier::loop_isolation(false)] fn pairs_sum_to_zero(nums: &[i32], target: i32) -> (found: bool) + // pre-conditions-start requires nums.len() >= 2, forall|i: int, j: int| 0 <= i < j < nums.len() ==> nums[i] + nums[j] <= i32::MAX && nums[i] + nums[j] >= i32::MIN, + // pre-conditions-end + // post-conditions-start ensures found <==> exists|i: int, j: int| 0 <= i < j < nums.len() && nums[i] + nums[j] == target, + // post-conditions-end { + // impl-start let mut i = 0; while i < nums.len() + // invariants-start invariant 0 <= i <= nums.len(), forall|u: int, v: int| 0 <= u < v < nums.len() && u < i ==> nums[u] + nums[v] != target, + // invariants-end { let mut j = i + 1; while j < nums.len() + // invariants-start invariant 0 <= i < j <= nums.len(), forall|u: int, v: int| 0 <= u < v < nums.len() && u < i ==> nums[u] + nums[v] != target, forall|u: int| i < u < j ==> nums[i as int] + nums[u] != target, + // invariants-end { if nums[i] + nums[j] == target { return true; @@ -35,7 +44,8 @@ fn pairs_sum_to_zero(nums: &[i32], target: i32) -> (found: bool) i = i + 1; } false + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/045-triangle_area.rs b/benches/HumanEval-RustBench/045-triangle_area.rs index 1a745d9..16821e0 100644 --- a/benches/HumanEval-RustBench/045-triangle_area.rs +++ b/benches/HumanEval-RustBench/045-triangle_area.rs @@ -3,22 +3,28 @@ use vstd::prelude::*; verus! { fn triangle_area(a: u64, h: u64) -> (area: u64) + // pre-conditions-start requires - a > 0, - h > 0, - a * h / 2 <= u64::MAX + a > 0, + h > 0, + a * h / 2 <= u64::MAX , + // pre-conditions-end + // post-conditions-start ensures - area == a * h / 2, + area == a * h / 2, + // post-conditions-end { + // impl-start if a % 2 == 0 { - assert(a % 2 == 0 ==> (a / 2) * h == a * h / 2) by (nonlinear_arith); + assert(a % 2 == 0 ==> (a / 2) * h == a * h / 2) by (nonlinear_arith); // assert-line (a / 2) * h } else { - assert(a % 2 == 1 ==> (a / 2) * h + (h / 2) == a * h / 2) by (nonlinear_arith); + assert(a % 2 == 1 ==> (a / 2) * h + (h / 2) == a * h / 2) by (nonlinear_arith); // assert-line (a / 2) * h + (h / 2) } + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/048-is-palindrome.rs b/benches/HumanEval-RustBench/048-is-palindrome.rs index 34fa1fc..cbceccd 100644 --- a/benches/HumanEval-RustBench/048-is-palindrome.rs +++ b/benches/HumanEval-RustBench/048-is-palindrome.rs @@ -3,22 +3,28 @@ use vstd::prelude::*; verus! { fn is_palindrome(text: &str) -> (result: bool) + // post-conditions-start ensures result == forall|i: int| 0 <= i < text@.len() ==> #[trigger] text@[i] == text@[text@.len() - 1 - i], + // post-conditions-end { + // impl-start let text_len: usize = text.unicode_len(); for pos in 0..text_len / 2 + // invariants-start invariant text_len == text@.len(), forall|i: int| 0 <= i < pos ==> #[trigger] text@[i] == text@[text_len - 1 - i], + // invariants-end { if text.get_char(pos) != text.get_char(text_len - 1 - pos) { return false; } } true + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/049-modp.rs b/benches/HumanEval-RustBench/049-modp.rs index 836e338..4c90fa3 100644 --- a/benches/HumanEval-RustBench/049-modp.rs +++ b/benches/HumanEval-RustBench/049-modp.rs @@ -14,31 +14,45 @@ spec fn modp_rec(n: nat, p: nat) -> nat fn modmul(a: u32, b: u32, p: u32) -> (mul: u32) by (nonlinear_arith) + // pre-conditions-start requires p > 0, + // pre-conditions-end + // post-conditions-start ensures mul == ((a as int) * (b as int)) % (p as int), + // post-conditions-end { + // impl-start (((a as u64) * (b as u64)) % (p as u64)) as u32 + // impl-end } #[verifier::loop_isolation(false)] fn modp(n: u32, p: u32) -> (r: u32) by (nonlinear_arith) + // pre-conditions-start requires p > 0, + // pre-conditions-end + // post-conditions-start ensures r == modp_rec(n as nat, p as nat), + // post-conditions-end { + // impl-start let mut r = 1u32 % p; for i in 0..n + // invariants-start invariant r == modp_rec(i as nat, p as nat), + // invariants-end { r = modmul(r, 2, p); } r + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/050-encode_shift.rs b/benches/HumanEval-RustBench/050-encode_shift.rs index 9fa06a2..f9d6f26 100644 --- a/benches/HumanEval-RustBench/050-encode_shift.rs +++ b/benches/HumanEval-RustBench/050-encode_shift.rs @@ -47,51 +47,71 @@ proof fn opposite_encode_decode(c: int) #[verifier::loop_isolation(false)] fn encode_shift(s: &Vec) -> (t: Vec) + // pre-conditions-start requires forall|i: int| #![trigger s[i]] 0 <= i < s.len() ==> 65 <= s[i] <= 90, + // pre-conditions-end + // post-conditions-start ensures s.len() == t.len(), forall|i: int| #![auto] 0 <= i < t.len() ==> t[i] == encode_char_spec(s[i] as int), forall|i: int| #![auto] 0 <= i < t.len() ==> decode_char_spec(t[i] as int) == s[i], + // post-conditions-end { + // impl-start let mut t: Vec = vec![]; for i in 0..s.len() + // invariants-start invariant t.len() == i, forall|j: int| #![auto] 0 <= j < i ==> t[j] == encode_char_spec(s[j] as int), forall|j: int| #![auto] 0 <= j < i ==> decode_char_spec(t[j] as int) == s[j], + // invariants-end { t.push(encode_char(s[i])); + // assert-start proof { opposite_encode_decode(s[i as int] as int); } + // assert-end } t + // impl-end } #[verifier::loop_isolation(false)] fn decode_shift(s: &Vec) -> (t: Vec) + // pre-conditions-start requires forall|i: int| #![trigger s[i]] 0 <= i < s.len() ==> 65 <= s[i] <= 90, + // pre-conditions-end + // post-conditions-start ensures s.len() == t.len(), forall|i: int| #![auto] 0 <= i < t.len() ==> t[i] == decode_char_spec(s[i] as int), forall|i: int| #![auto] 0 <= i < t.len() ==> encode_char_spec(t[i] as int) == s[i], + // post-conditions-end { + // impl-start let mut t: Vec = vec![]; for i in 0..s.len() + // invariants-start invariant t.len() == i, forall|j: int| #![auto] 0 <= j < i ==> t[j] == decode_char_spec(s[j] as int), forall|j: int| #![auto] 0 <= j < i ==> encode_char_spec(t[j] as int) == s[j], + // invariants-end { t.push(decode_char(s[i])); + // assert-start proof { opposite_encode_decode(s[i as int] as int); } + // assert-end } t + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/052-below-threshold.rs b/benches/HumanEval-RustBench/052-below-threshold.rs index 0beb0b1..656c9a6 100644 --- a/benches/HumanEval-RustBench/052-below-threshold.rs +++ b/benches/HumanEval-RustBench/052-below-threshold.rs @@ -3,19 +3,25 @@ use vstd::prelude::*; verus! { fn below_threshold(l: &[i32], t: i32) -> (result: bool) + // post-conditions-start ensures result == forall|i: int| 0 <= i < l.len() ==> l[i] < t, + // post-conditions-end { + // impl-start for i in 0..l.len() + // invariants-start invariant forall|j: int| 0 <= j < i ==> l[j] < t, + // invariants-end { if l[i] >= t { return false; } } true + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/053-add.rs b/benches/HumanEval-RustBench/053-add.rs index 12a09ea..c4a220c 100644 --- a/benches/HumanEval-RustBench/053-add.rs +++ b/benches/HumanEval-RustBench/053-add.rs @@ -3,11 +3,15 @@ use vstd::prelude::*; verus! { fn add(x: i32, y: i32) -> (res: Option) + // post-conditions-start ensures res.is_some() ==> res.unwrap() == x + y, + // post-conditions-end { + // impl-start x.checked_add(y) + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/054-same-chars.rs b/benches/HumanEval-RustBench/054-same-chars.rs index 5ec16d8..28f1a61 100644 --- a/benches/HumanEval-RustBench/054-same-chars.rs +++ b/benches/HumanEval-RustBench/054-same-chars.rs @@ -7,34 +7,46 @@ verus! { broadcast use axiom_u8_obeys_hash_table_key_model; fn hash_set_from(s: &Vec) -> (res: HashSetWithView) + // post-conditions-start ensures forall|i: int| #![auto] 0 <= i < s.len() ==> res@.contains(s[i]), forall|x: int| 0 <= x < 256 ==> #[trigger] res@.contains(x as u8) ==> #[trigger] s@.contains(x as u8), + // post-conditions-end { + // impl-start let mut res: HashSetWithView = HashSetWithView::new(); for i in 0..s.len() + // invariants-start invariant forall|j: int| #![auto] 0 <= j < i ==> res@.contains(s[j]), forall|x: int| 0 <= x < 256 ==> #[trigger] res@.contains(x as u8) ==> (exists|j: int| 0 <= j < i && s[j] == x), + // invariants-end { res.insert(s[i]); } res + // impl-end } proof fn implies_contains(s0: Seq, s1: Seq, hs1: Set) + // pre-conditions-start requires forall|i: int| #![trigger s0[i]] 0 <= i < s0.len() ==> 0 <= s0[i] < 256, forall|x: int| 0 <= x < 256 ==> #[trigger] hs1.contains(x as u8) ==> #[trigger] s1.contains(x as u8), + // pre-conditions-end + // post-conditions-start ensures forall|i: int| #![auto] 0 <= i < s0.len() && 0 <= s0[i] < 256 && hs1.contains(s0[i]) ==> s1.contains(s0[i]), + // post-conditions-end { + // impl-start + // assert-start assert forall|i: int| #![auto] 0 <= i < s0.len() && 0 <= s0[i] < 256 && hs1.contains(s0[i]) implies s1.contains(s0[i]) by { @@ -43,47 +55,59 @@ proof fn implies_contains(s0: Seq, s1: Seq, hs1: Set) assert(hs1.contains(x as u8)); assert(s1.contains(x as u8)); }; + // assert-end + // impl-end } #[verifier::loop_isolation(false)] fn same_chars(s0: &Vec, s1: &Vec) -> (same: bool) + // post-conditions-start ensures same <==> (forall|i: int| #![auto] 0 <= i < s0.len() ==> s1@.contains(s0[i])) && (forall| i: int, | #![auto] 0 <= i < s1.len() ==> s0@.contains(s1[i])), + // post-conditions-end { + // impl-start let hs0 = hash_set_from(s0); let hs1 = hash_set_from(s1); + // assert-start proof { implies_contains(s0@, s1@, hs1@); implies_contains(s1@, s0@, hs0@); } + // assert-end let mut contains_s0 = true; for i in 0..s0.len() + // invariants-start invariant contains_s0 <==> forall|j: int| #![auto] 0 <= j < i ==> s1@.contains(s0[j]), + // invariants-end { if !hs1.contains(&s0[i]) { contains_s0 = false; - assert(!s1@.contains(s0[i as int])); + assert(!s1@.contains(s0[i as int])); // assert-line } } let mut contains_s1 = true; for i in 0..s1.len() + // invariants-start invariant contains_s1 <==> forall|j: int| #![auto] 0 <= j < i ==> s0@.contains(s1[j]), + // invariants-end { if !hs0.contains(&s1[i]) { contains_s1 = false; - assert(!s0@.contains(s1[i as int])); + assert(!s0@.contains(s1[i as int])); // assert-line } } contains_s0 && contains_s1 + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/057-monotonic.rs b/benches/HumanEval-RustBench/057-monotonic.rs index ec8fdcd..34f3956 100644 --- a/benches/HumanEval-RustBench/057-monotonic.rs +++ b/benches/HumanEval-RustBench/057-monotonic.rs @@ -3,10 +3,13 @@ use vstd::prelude::*; verus! { fn monotonic(l: Vec) -> (ret: bool) + // post-conditions-start ensures ret <==> (forall|i: int, j: int| 0 <= i < j < l@.len() ==> l@.index(i) <= l@.index(j)) || ( forall|i: int, j: int| 0 <= i < j < l@.len() ==> l@.index(i) >= l@.index(j)), + // post-conditions-end { + // impl-start if l.len() == 0 || l.len() == 1 { return true; } @@ -15,6 +18,7 @@ fn monotonic(l: Vec) -> (ret: bool) let mut n = 0; while n < l.len() - 1 + // invariants-start invariant l.len() > 1, n <= l.len() - 1, @@ -22,6 +26,7 @@ fn monotonic(l: Vec) -> (ret: bool) 0 <= i < j < n + 1 ==> l@.index(i) <= l@.index(j), decreasing <==> forall|i: int, j: int| 0 <= i < j < n + 1 ==> l@.index(i) >= l@.index(j), + // invariants-end { if l[n] < l[n + 1] { decreasing = false; @@ -31,7 +36,8 @@ fn monotonic(l: Vec) -> (ret: bool) n += 1; } increasing || decreasing + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/059-largest-prime-factor.rs b/benches/HumanEval-RustBench/059-largest-prime-factor.rs index 66de5cd..f827e49 100644 --- a/benches/HumanEval-RustBench/059-largest-prime-factor.rs +++ b/benches/HumanEval-RustBench/059-largest-prime-factor.rs @@ -10,17 +10,24 @@ spec fn spec_prime(num: int) -> bool { } fn is_prime(num: u32) -> (result: bool) + // pre-conditions-start requires num >= 2, + // pre-conditions-end + // post-conditions-start ensures result <==> spec_prime(num as int), + // post-conditions-end { + // impl-start let mut i = 2; let mut result = true; while i < num + // invariants-start invariant 2 <= i <= num, result <==> spec_prime_helper(num as int, i as int), + // invariants-end { if num % i == 0 { result = false; @@ -28,21 +35,29 @@ fn is_prime(num: u32) -> (result: bool) i += 1; } result + // impl-end } fn largest_prime_factor(n: u32) -> (largest: u32) + // pre-conditions-start requires n >= 2, + // pre-conditions-end + // post-conditions-start ensures 1 <= largest <= n, spec_prime(largest as int), + // post-conditions-end { + // impl-start let mut largest = 1; let mut j = 1; while j < n + // invariants-start invariant 1 <= largest <= j <= n, spec_prime(largest as int), + // invariants-end { j += 1; let flag = is_prime(j); @@ -56,7 +71,8 @@ fn largest_prime_factor(n: u32) -> (largest: u32) } } largest + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/060-sum_to_n.rs b/benches/HumanEval-RustBench/060-sum_to_n.rs index 984e35b..cde66cb 100644 --- a/benches/HumanEval-RustBench/060-sum_to_n.rs +++ b/benches/HumanEval-RustBench/060-sum_to_n.rs @@ -13,23 +13,29 @@ spec fn spec_sum_to_n(n: nat) -> nat } fn sum_to_n(n: u32) -> (sum: Option) + // post-conditions-start ensures sum.is_some() ==> sum.unwrap() == spec_sum_to_n(n as nat), + // post-conditions-end { + // impl-start let mut res: u32 = 0; let mut sum: u32 = 0; let mut i: u32 = 0; while i < n + // invariants-start invariant i <= n, res == spec_sum_to_n(i as nat), res <= u32::MAX, + // invariants-end { i += 1; res = i.checked_add(res)?; } Some(res) + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/062-derivative.rs b/benches/HumanEval-RustBench/062-derivative.rs index b9748f6..6f93ab8 100644 --- a/benches/HumanEval-RustBench/062-derivative.rs +++ b/benches/HumanEval-RustBench/062-derivative.rs @@ -3,19 +3,24 @@ use vstd::prelude::*; verus! { fn derivative(xs: &Vec) -> (ret: Option>) + // post-conditions-start ensures ret.is_some() ==> xs@.len() == 0 || xs@.map(|i: int, x| i * x).skip(1) =~= ret.unwrap()@.map_values(|x| x as int), + // post-conditions-end { + // impl-start let mut ret = Vec::new(); if xs.len() == 0 { return Some(ret); } let mut i = 1; while i < xs.len() + // invariants-start invariant xs@.map(|i: int, x| i * x).subrange(1, i as int) =~= ret@.map_values(|x| x as int), 1 <= i <= xs.len(), + // invariants-end { ret.push(xs[i].checked_mul(i)?); @@ -23,13 +28,14 @@ fn derivative(xs: &Vec) -> (ret: Option>) assert(prods.subrange(1, i as int).push(prods.index(i as int)) =~= prods.subrange( 1, i + 1 as int, - )); + )); // assert-line i += 1; } - assert(xs@.map(|i: int, x| i * x).subrange(1, i as int) =~= xs@.map(|i: int, x| i * x).skip(1)); + assert(xs@.map(|i: int, x| i * x).subrange(1, i as int) =~= xs@.map(|i: int, x| i * x).skip(1)); // assert-line Some(ret) + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/063-fibfib.rs b/benches/HumanEval-RustBench/063-fibfib.rs index b0f010c..1494d56 100644 --- a/benches/HumanEval-RustBench/063-fibfib.rs +++ b/benches/HumanEval-RustBench/063-fibfib.rs @@ -17,16 +17,20 @@ spec fn spec_fibfib(n: nat) -> nat } fn fibfib(x: u32) -> (ret: Option) + // post-conditions-start ensures ret.is_some() ==> spec_fibfib(x as nat) == ret.unwrap(), + // post-conditions-end { + // impl-start match (x) { 0 => Some(0), 1 => Some(0), 2 => Some(1), _ => fibfib(x - 1)?.checked_add(fibfib(x - 2)?)?.checked_add(fibfib(x - 3)?), } + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/064-vowel_count.rs b/benches/HumanEval-RustBench/064-vowel_count.rs index b278f25..a6cdc5a 100644 --- a/benches/HumanEval-RustBench/064-vowel_count.rs +++ b/benches/HumanEval-RustBench/064-vowel_count.rs @@ -12,46 +12,56 @@ spec fn vowels(s: Seq) -> Seq { } fn vowels_count(s: &str) -> (ret: u32) + // pre-conditions-start requires s@.len() <= u32::MAX, + // pre-conditions-end + // post-conditions-start ensures ret == vowels(s@).len() + if (s@.len() > 0 && (s@.last() == 'y' || s@.last() == 'Y')) { - 1int + 1int } else { 0int }, + // post-conditions-end { + // impl-start let mut ctr = 0; let len = s.unicode_len(); if len == 0 { return ctr; } - assert(len > 0); + assert(len > 0); // assert-line let mut i = 0; for i in 0..len + // invariants-start invariant ctr == vowels(s@.subrange(0, i as int)).len(), ctr <= i <= s@.len() == len <= u32::MAX, ctr < u32::MAX || is_vowel(s@.last()), + // invariants-end { let c = s.get_char(i); reveal_with_fuel(Seq::filter, 2); - assert(s@.subrange(0, i + 1 as int).drop_last() =~= s@.subrange(0, i as int)); + assert(s@.subrange(0, i + 1 as int).drop_last() =~= s@.subrange(0, i as int)); // assert-line if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U') { ctr += 1; } } + // assert-start assert(ctr == vowels(s@).len()) by { assert(s@.subrange(0, len as int) =~= s@); } + // assert-end let c = s.get_char(len - 1); if (c == 'y' || c == 'Y') { ctr += 1 } ctr + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/068-pluck.rs b/benches/HumanEval-RustBench/068-pluck.rs index d5532fa..546bf76 100644 --- a/benches/HumanEval-RustBench/068-pluck.rs +++ b/benches/HumanEval-RustBench/068-pluck.rs @@ -3,8 +3,11 @@ use vstd::prelude::*; verus! { fn pluck_smallest_even(nodes: &Vec) -> (result: Vec) + // pre-conditions-start requires nodes@.len() <= u32::MAX, + // pre-conditions-end + // post-conditions-start ensures result@.len() == 0 || result@.len() == 2, result@.len() == 0 ==> forall|i: int| 0 <= i < nodes@.len() ==> nodes@[i] % 2 != 0, @@ -18,11 +21,14 @@ fn pluck_smallest_even(nodes: &Vec) -> (result: Vec) 0 <= i < nodes@.len() && nodes@[i] % 2 == 0 ==> node <= nodes@[i] && forall|i: int| 0 <= i < result@[1] ==> nodes@[i] % 2 != 0 || nodes@[i] > node }, + // post-conditions-end { + // impl-start let mut smallest_even: Option = None; let mut smallest_index: Option = None; for i in 0..nodes.len() + // invariants-start invariant 0 <= i <= nodes@.len(), nodes@.len() <= u32::MAX, @@ -38,6 +44,7 @@ fn pluck_smallest_even(nodes: &Vec) -> (result: Vec) 0 <= j < smallest_index.unwrap() ==> nodes@[j] % 2 != 0 || nodes@[j] > smallest_even.unwrap() }, + // invariants-end { if nodes[i] % 2 == 0 && (smallest_even.is_none() || nodes[i] < smallest_even.unwrap()) { smallest_even = Some(nodes[i]); @@ -49,7 +56,8 @@ fn pluck_smallest_even(nodes: &Vec) -> (result: Vec) } else { vec![smallest_even.unwrap(), smallest_index.unwrap()] } + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/070-strange_sort_list.rs b/benches/HumanEval-RustBench/070-strange_sort_list.rs index bba839d..05333ff 100644 --- a/benches/HumanEval-RustBench/070-strange_sort_list.rs +++ b/benches/HumanEval-RustBench/070-strange_sort_list.rs @@ -111,6 +111,7 @@ fn sort_seq(s: &Vec) -> (ret: Vec) sorted } fn strange_sort_list_helper(s: &Vec) -> (ret: (Vec, Vec)) + // post-conditions-start ensures s@.to_multiset() == (ret.0)@.to_multiset(), s@.len() == (ret.0)@.len() == (ret.1)@.len(), @@ -120,11 +121,14 @@ fn strange_sort_list_helper(s: &Vec) -> (ret: (Vec, Vec)) 0 <= i < s@.len() && i % 2 == 1 ==> (ret.1)@.index(i) == (ret.0)@.index( s@.len() - (i - 1) / 2 - 1, ), + // post-conditions-end { + // impl-start let sorted = sort_seq(s); let mut strange = Vec::new(); let mut i: usize = 0; while i < sorted.len() + // invariants-start invariant i <= sorted.len() == s@.len(), strange@.len() == i, @@ -133,6 +137,7 @@ fn strange_sort_list_helper(s: &Vec) -> (ret: (Vec, Vec)) 0 < j < i && j % 2 == 1 ==> strange@.index(j) == sorted@.index( sorted@.len() - (j / 2) - 1, ), + // invariants-end { if i % 2 == 0 { strange.push(sorted[i / 2]); @@ -143,15 +148,20 @@ fn strange_sort_list_helper(s: &Vec) -> (ret: (Vec, Vec)) i += 1; } (sorted, strange) + // impl-end } fn strange_sort_list(s: &Vec) -> (ret: Vec) + // post-conditions-start ensures s@.len() == ret@.len(), + // post-conditions-end { + // impl-start let (_, strange) = strange_sort_list_helper(s); strange + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/072-will_it_fly.rs b/benches/HumanEval-RustBench/072-will_it_fly.rs index 7becaf3..4417be3 100644 --- a/benches/HumanEval-RustBench/072-will_it_fly.rs +++ b/benches/HumanEval-RustBench/072-will_it_fly.rs @@ -36,16 +36,22 @@ spec fn spec_sum(s: Seq) -> int { } fn sum_lesser_than_limit(qs: &Vec, w: u32) -> (ret: bool) + // post-conditions-start ensures ret <==> spec_sum(qs@) <= w, + // post-conditions-end { + // impl-start let mut sum: u32 = 0; for i in 0..qs.len() + // invariants-start invariant sum == spec_sum(qs@.subrange(0, i as int)), i <= qs.len(), sum <= w, + // invariants-end { + // assert-start proof { assert(spec_sum(qs@.subrange(0, i + 1)) <= spec_sum(qs@)) by { assert(qs@ == qs@.subrange(0, qs@.len() as int)); @@ -57,42 +63,51 @@ fn sum_lesser_than_limit(qs: &Vec, w: u32) -> (ret: bool) assert(qs@.subrange(0, i + 1).drop_last() == qs@.subrange(0, i as int)); } } + // assert-end let sum_opt = sum.checked_add(qs[i]); if sum_opt.is_none() { - assert(spec_sum(qs@.subrange(0, i + 1)) > u32::MAX >= w); + assert(spec_sum(qs@.subrange(0, i + 1)) > u32::MAX >= w); // assert-line return false; } else { sum = sum_opt.unwrap(); if sum > w { - assert(spec_sum(qs@.subrange(0, i + 1)) > w); + assert(spec_sum(qs@.subrange(0, i + 1)) > w); // assert-line return false; } } } assume(sum == spec_sum(qs@)); true + // impl-end } fn palindrome(qs: &Vec) -> (ret: bool) + // post-conditions-start ensures ret <==> qs@ =~= qs@.reverse(), + // post-conditions-end { + // impl-start let mut ret = true; let mut i: usize = 0; while i < qs.len() / 2 + // invariants-start invariant i <= qs@.len() / 2, ret <==> qs@.subrange(0, i as int) =~= qs@.subrange( qs@.len() - i, qs@.len() as int, ).reverse(), + // invariants-end { + // assert-start assert(qs@.subrange(qs@.len() - (i + 1), qs@.len() as int).reverse().drop_last() =~= qs@.subrange(qs@.len() - i, qs@.len() as int).reverse()); assert(qs@.subrange(qs@.len() - (i + 1), qs@.len() as int).reverse() =~= qs@.subrange( qs@.len() - i, qs@.len() as int, ).reverse().push(qs@.index(qs@.len() - (i + 1)))); + // assert-end if qs[i] != qs[qs.len() - i - 1] { ret = false; } @@ -100,6 +115,7 @@ fn palindrome(qs: &Vec) -> (ret: bool) } let ghost fst_half = qs@.subrange(0, (qs@.len() / 2) as int); let ghost snd_half = qs@.subrange(qs@.len() - qs@.len() / 2, qs@.len() as int); + // assert-start proof { if (qs.len() % 2) == 1 { assert(qs@ =~= fst_half + qs@.subrange( @@ -110,15 +126,21 @@ fn palindrome(qs: &Vec) -> (ret: bool) assert(qs@ =~= fst_half + snd_half); } } + // assert-end ret + // impl-end } fn will_it_fly(qs: &Vec, w: u32) -> (ret: bool) + // post-conditions-start ensures ret <==> qs@ =~= qs@.reverse() && spec_sum(qs@) <= w, + // post-conditions-end { + // impl-start palindrome(qs) && sum_lesser_than_limit(qs, w) + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/073-smallest_change.rs b/benches/HumanEval-RustBench/073-smallest_change.rs index 911e1b9..9fff78a 100644 --- a/benches/HumanEval-RustBench/073-smallest_change.rs +++ b/benches/HumanEval-RustBench/073-smallest_change.rs @@ -19,32 +19,42 @@ spec fn diff(s: Seq<(i32, i32)>) -> int { } fn smallest_change(v: Vec) -> (change: usize) + // pre-conditions-start requires v@.len() < usize::MAX, + // pre-conditions-end + // post-conditions-start ensures change == diff(zip_halves(v@)), + // post-conditions-end { + // impl-start let mut ans: usize = 0; let ghost zipped = Seq::<(i32, i32)>::empty(); for i in 0..v.len() / 2 + // invariants-start invariant ans <= i <= v@.len() / 2 < usize::MAX, ans == diff(zipped), zipped =~= zip_halves(v@).take(i as int), + // invariants-end { + // assert-start proof { let ghost pair = (v[i as int], v[v.len() - i - 1]); let ghost zipped_old = zipped; zipped = zipped.push(pair); assert(zipped.drop_last() =~= zipped_old); } + // assert-end if v[i] != v[v.len() - i - 1] { ans += 1; } } - assert(zip_halves(v@).take((v@.len() / 2) as int) =~= zip_halves(v@)); + assert(zip_halves(v@).take((v@.len() / 2) as int) =~= zip_halves(v@)); // assert-line ans + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/074-total_match.rs b/benches/HumanEval-RustBench/074-total_match.rs index 6858cf2..6276c8a 100644 --- a/benches/HumanEval-RustBench/074-total_match.rs +++ b/benches/HumanEval-RustBench/074-total_match.rs @@ -25,13 +25,17 @@ spec fn total_str_len(strings: Seq<&str>) -> int { } fn checked_total_str_len(lst: &Vec<&str>) -> (ret: Option) + // post-conditions-start ensures ret.is_some() <==> total_str_len(lst@) <= usize::MAX, ret.is_some() <==> ret.unwrap() == total_str_len(lst@), + // post-conditions-end { + // impl-start let ghost lens = Seq::::empty(); let mut sum: usize = 0; for i in 0..lst.len() + // invariants-start invariant sum == lst@.subrange(0, i as int).map_values(|s: &str| s@.len()).fold_left( 0, @@ -40,8 +44,10 @@ fn checked_total_str_len(lst: &Vec<&str>) -> (ret: Option) spec_sum(lens) == sum, lens =~= lst@.map_values(|s: &str| s@.len()).take(i as int), lens =~= lst@.take(i as int).map_values(|s: &str| s@.len()), + // invariants-end { let x = lst[i].unicode_len(); + // assert-start proof { assert(lens.push(x as nat).drop_last() == lens); lens = lens.push(x as nat); @@ -58,16 +64,19 @@ fn checked_total_str_len(lst: &Vec<&str>) -> (ret: Option) assert(total_str_len(lst@) > usize::MAX); } } + // assert-end sum = sum.checked_add(x)?; assert(lst@.take(i + 1).map_values(|s: &str| s@.len()).drop_last() == lst@.take( i as int, - ).map_values(|s: &str| s@.len())); + ).map_values(|s: &str| s@.len())); // assert-line } - assert(lst@ == lst@.subrange(0, lst.len() as int)); + assert(lst@ == lst@.subrange(0, lst.len() as int)); // assert-line return Some(sum); + // impl-end } fn total_match<'a>(lst1: Vec<&'a str>, lst2: Vec<&'a str>) -> (ret: Option>) + // post-conditions-start ensures ret.is_some() <== total_str_len(lst1@) <= usize::MAX && total_str_len(lst2@) <= usize::MAX, ret.is_some() ==> ret.unwrap() == if total_str_len(lst1@) <= total_str_len(lst2@) { @@ -75,13 +84,16 @@ fn total_match<'a>(lst1: Vec<&'a str>, lst2: Vec<&'a str>) -> (ret: Option bool { } fn prime(p: u32) -> (ret: bool) + // post-conditions-start ensures ret <==> spec_prime(p as int), + // post-conditions-end { + // impl-start if p <= 1 { return false; } for k in 2..p + // invariants-start invariant forall|j: int| 1 < j < k ==> #[trigger] (p as int % j) != 0, k <= p, + // invariants-end { if p % k == 0 { return false; } } true + // impl-end } fn checked_mul_thrice(x: u32, y: u32, z: u32) -> (ret: Option) + // post-conditions-start ensures ret.is_some() ==> ret.unwrap() == x * y * z, ret.is_none() ==> x * y * z > u32::MAX, + // post-conditions-end { + // impl-start if (x == 0 || y == 0 || z == 0) { return Some(0); } - assert(x > 0 && y > 0 && z > 0); + assert(x > 0 && y > 0 && z > 0); // assert-line let prod2 = x.checked_mul(y); if prod2.is_some() { let prod3 = prod2.unwrap().checked_mul(z); if prod3.is_some() { let ans = prod3.unwrap(); - assert(ans == x * y * z); + assert(ans == x * y * z); // assert-line Some(ans) } else { - assert(x * y * z > u32::MAX); + assert(x * y * z > u32::MAX); // assert-line None } } else { + // assert-start broadcast use group_mul_properties; assert(x * y * z >= y * z); + // assert-end None } + // impl-end } fn is_multiply_prime(x: u32) -> (ans: bool) + // pre-conditions-start requires x > 1, + // pre-conditions-end + // post-conditions-start ensures ans <==> exists|a: int, b: int, c: int| spec_prime(a) && spec_prime(b) && spec_prime(c) && x == a * b * c, + // post-conditions-end { + // impl-start let mut a = 1; while a < x + // invariants-start invariant forall|i: int, j: int, k: int| (spec_prime(i) && spec_prime(j) && spec_prime(k) && i <= a && j <= x && k <= x) ==> x != i * j * k, a <= x, + // invariants-end { a += 1; if prime(a) { let mut b = 1; while b < x + // invariants-start invariant forall|j: int, k: int| (spec_prime(j) && spec_prime(k) && j <= b && k <= x) ==> x != (a as int) * j @@ -80,11 +100,13 @@ fn is_multiply_prime(x: u32) -> (ans: bool) spec_prime(a as int), a <= x, b <= x, + // invariants-end { b += 1; if prime(b) { let mut c = 1; while c < x + // invariants-start invariant forall|k: int| (spec_prime(k) && k <= c as int) ==> x != a * b * k, spec_prime(a as int), @@ -92,6 +114,7 @@ fn is_multiply_prime(x: u32) -> (ans: bool) a <= x, b <= x, c <= x, + // invariants-end { c += 1; let prod = checked_mul_thrice(a, b, c); @@ -103,19 +126,23 @@ fn is_multiply_prime(x: u32) -> (ans: bool) } } } + // assert-start assert(forall|i: int, j: int, k: int| i <= x && j <= x && k <= x && spec_prime(i) && spec_prime(j) && spec_prime(k) ==> x != i * j * k); + // assert-end + // assert-start assert forall|i: int, j: int, k: int| spec_prime(i) && spec_prime(j) && spec_prime(k) ==> x != i * j * k by { if (i > 1 && j > 1 && k > 1 && (i > x || j > x || k > x)) { broadcast use group_mul_properties; - assert(i * j * k > x); } } + // assert-end false + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/076-is_simple_power.rs b/benches/HumanEval-RustBench/076-is_simple_power.rs index 2c18d2a..f6d2d89 100644 --- a/benches/HumanEval-RustBench/076-is_simple_power.rs +++ b/benches/HumanEval-RustBench/076-is_simple_power.rs @@ -23,15 +23,21 @@ pub fn ex_checked_pow(x: u32, exp: u32) -> (ret: Option) } fn is_simple_power(x: u32, n: u32) -> (ret: bool) + // pre-conditions-start requires x > 0, n > 1, + // pre-conditions-end + // post-conditions-start ensures ret <==> x == pow(n as int, log(n as int, x as int) as nat), + // post-conditions-end { + // impl-start let maybe_x = n.checked_pow(x.ilog(n)); return maybe_x.is_some() && maybe_x.unwrap() == x; + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/077-is_cube.rs b/benches/HumanEval-RustBench/077-is_cube.rs index ca0fe21..bcc58b6 100644 --- a/benches/HumanEval-RustBench/077-is_cube.rs +++ b/benches/HumanEval-RustBench/077-is_cube.rs @@ -5,22 +5,29 @@ use vstd::prelude::*; verus! { proof fn lemma_cube_increases_helper(i: int) + // post-conditions-start ensures i >= 0 ==> (i * i * i) <= (i + 1) * (i + 1) * (i + 1), + // post-conditions-end { + // impl-start broadcast use group_mul_properties; if (i > 0) { - assert((i + 1) * (i + 1) * (i + 1) == i * i * i + 3 * i * i + 3 * i + 1); - assert(i * i * i + 3 * i * i + 3 * i + 1 > i * i * i); + assert((i + 1) * (i + 1) * (i + 1) == i * i * i + 3 * i * i + 3 * i + 1); // assert-line + assert(i * i * i + 3 * i * i + 3 * i + 1 > i * i * i); // assert-line } + // impl-end } proof fn lemma_cube_increases_params(i: int, j: int) + // post-conditions-start ensures 0 <= i <= j ==> (i * i * i) <= (j * j * j), + // post-conditions-end decreases j - i, { + // impl-start if (i == j) { } else if (i < j) { @@ -28,25 +35,35 @@ proof fn lemma_cube_increases_params(i: int, j: int) lemma_cube_increases_helper(j - 1); } + // impl-end } proof fn lemma_cube_increases() + // post-conditions-start ensures forall|i: int, j: int| 0 <= i <= j ==> #[trigger] (i * i * i) <= #[trigger] (j * j * j), + // post-conditions-end { + // impl-start assert forall|i: int, j: int| 0 <= i <= j ==> #[trigger] (i * i * i) <= #[trigger] (j * j * j) by { lemma_cube_increases_params(i, j); } + // impl-end } fn checked_cube(x: i32) -> (ret: Option) + // pre-conditions-start requires x >= 0, + // pre-conditions-end + // post-conditions-start ensures ret.is_some() ==> ret.unwrap() == x * x * x, ret.is_none() ==> x * x * x > i32::MAX, + // post-conditions-end { + // impl-start if x == 0 { return Some(0); } @@ -55,27 +72,30 @@ fn checked_cube(x: i32) -> (ret: Option) let cube = sqr.unwrap().checked_mul(x); if cube.is_some() { let ans = cube.unwrap(); - assert(ans == x * x * x); + assert(ans == x * x * x); // assert-line Some(ans) } else { - assert(x * x * x > i32::MAX); + assert(x * x * x > i32::MAX); // assert-line None } } else { - assert(x > 0); - assert(x * x > i32::MAX); + assert(x > 0); // assert-line + assert(x * x > i32::MAX); // assert-line + // assert-start proof { lemma_mul_increases(x as int, x * x); } - assert(x * x * x >= x * x); + // assert-end + assert(x * x * x >= x * x); // assert-line None } + // impl-end } #[verifier::external_fn_specification] pub fn ex_abs(x: i32) -> (ret: i32) requires - x != i32::MIN, + x != i32::MIN, ensures ret == abs(x as int), @@ -84,26 +104,32 @@ pub fn ex_abs(x: i32) -> (ret: i32) } fn is_cube(x: i32) -> (ret: bool) + // pre-conditions-start requires - x != i32::MIN, - + x != i32::MIN, + // pre-conditions-end + // post-conditions-start ensures ret <==> exists|i: int| 0 <= i && abs(x as int) == #[trigger] (i * i * i), + // post-conditions-end { + // impl-start let x_abs = x.abs(); if x_abs == 0 { - assert(abs(x as int) == 0 * 0 * 0); + assert(abs(x as int) == 0 * 0 * 0); // assert-line return true; } else if (x_abs == 1) { - assert(abs(x as int) == 1 * 1 * 1); + assert(abs(x as int) == 1 * 1 * 1); // assert-line return true; } - assert(-1 > x || x > 1); + assert(-1 > x || x > 1); // assert-line let mut i = 2; while i < x_abs + // invariants-start invariant forall|j: int| 2 <= j < i ==> abs(x as int) != #[trigger] (j * j * j), 2 <= i <= abs(x as int) == x_abs, + // invariants-end { let prod = checked_cube(i); if prod.is_some() && prod.unwrap() == x.abs() { @@ -111,6 +137,7 @@ fn is_cube(x: i32) -> (ret: bool) } i += 1; } + // assert-start assert(forall|j: int| 2 <= j ==> abs(x as int) != #[trigger] (j * j * j)) by { assert(forall|j: int| 2 <= j < i ==> abs(x as int) != #[trigger] (j * j * j)); @@ -124,8 +151,10 @@ fn is_cube(x: i32) -> (ret: bool) assert(forall|j: int| i <= j ==> (i * i * i) <= #[trigger] (j * j * j)); } } + // assert-end false + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/080-is_happy.rs b/benches/HumanEval-RustBench/080-is_happy.rs index 803cd6c..5aa5ee8 100644 --- a/benches/HumanEval-RustBench/080-is_happy.rs +++ b/benches/HumanEval-RustBench/080-is_happy.rs @@ -10,12 +10,18 @@ spec fn three_distinct_spec(s: Seq, i: int) -> bool } fn three_distinct(s: &Vec, i: usize) -> (is: bool) + // pre-conditions-start requires 0 < i && i + 1 < s.len(), + // pre-conditions-end + // post-conditions-start ensures is <==> three_distinct_spec(s@, i as int), + // post-conditions-end { + // impl-start (s[i - 1] != s[i]) && (s[i] != s[i + 1]) && (s[i] != s[i + 1]) + // impl-end } spec fn happy_spec(s: Seq) -> bool { @@ -24,22 +30,28 @@ spec fn happy_spec(s: Seq) -> bool { #[verifier::loop_isolation(false)] fn is_happy(s: &Vec) -> (happy: bool) + // post-conditions-start ensures happy <==> happy_spec(s@), + // post-conditions-end { + // impl-start if s.len() < 3 { return false; } for i in 1..(s.len() - 1) + // invariants-start invariant forall|j: int| 0 < j < i ==> three_distinct_spec(s@, j), + // invariants-end { if !three_distinct(s, i) { return false; } } return true; + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/134-check_if_last_char_is_a_letter.rs b/benches/HumanEval-RustBench/134-check_if_last_char_is_a_letter.rs index 2d148e7..e1cd676 100644 --- a/benches/HumanEval-RustBench/134-check_if_last_char_is_a_letter.rs +++ b/benches/HumanEval-RustBench/134-check_if_last_char_is_a_letter.rs @@ -25,16 +25,20 @@ pub fn ex_is_whitespace(c: char) -> (result: bool) } fn check_if_last_char_is_a_letter(txt: &str) -> (result: bool) + // post-conditions-start ensures result <==> (txt@.len() > 0 && txt@.last().is_alphabetic() && (txt@.len() == 1 || txt@.index(txt@.len() - 2).is_whitespace())), + // post-conditions-end { + // impl-start let len = txt.unicode_len(); if len == 0 { return false; } txt.get_char(len - 1).is_alphabetic() && (len == 1 || txt.get_char(len - 2).is_whitespace()) + // impl-end } -} +} fn main() {} diff --git a/benches/HumanEval-RustBench/136-largest_smallest_integers.rs b/benches/HumanEval-RustBench/136-largest_smallest_integers.rs index d6c8f66..4b0ed70 100644 --- a/benches/HumanEval-RustBench/136-largest_smallest_integers.rs +++ b/benches/HumanEval-RustBench/136-largest_smallest_integers.rs @@ -3,6 +3,7 @@ use vstd::prelude::*; verus! { fn largest_smallest_integers(arr: &Vec) -> (res: (Option, Option)) + // post-conditions-start ensures ({ let a = res.0; @@ -16,12 +17,15 @@ fn largest_smallest_integers(arr: &Vec) -> (res: (Option, Option) &&& b.is_some() ==> forall|i: int| 0 <= i < arr@.len() && arr@[i] > 0 ==> arr@[i] >= b.unwrap() }), + // post-conditions-end { + // impl-start let mut i: usize = 0; let mut a = None; let mut b = None; while i < arr.len() + // invariants-start invariant 0 <= i <= arr@.len(), a.is_none() ==> forall|j: int| 0 <= j < i ==> arr@[j] >= 0, @@ -30,6 +34,7 @@ fn largest_smallest_integers(arr: &Vec) -> (res: (Option, Option) b.is_none() ==> forall|j: int| 0 <= j < i ==> arr@[j] <= 0, b.is_some() ==> arr@.contains(b.unwrap()) && b.unwrap() > 0, b.is_some() ==> forall|j: int| 0 <= j < i && arr@[j] > 0 ==> arr@[j] >= b.unwrap(), + // invariants-end { if arr[i] < 0 && (a.is_none() || arr[i] >= a.unwrap()) { a = Some(arr[i]); @@ -40,7 +45,8 @@ fn largest_smallest_integers(arr: &Vec) -> (res: (Option, Option) i = i + 1; } (a, b) + // impl-end } -} +} fn main() {} From b2b267a54192b680c1b68e36af22f54fc5dfea50 Mon Sep 17 00:00:00 2001 From: WeetHet Date: Wed, 25 Sep 2024 16:22:37 +0300 Subject: [PATCH 23/23] complete verus support --- .../004-mean_absolute_derivation.rs | 2 +- .../HumanEval-RustBench/005-intersperse.rs | 2 +- .../076-is_simple_power.rs | 4 +- benches/HumanEval-RustBench/077-is_cube.rs | 2 +- .../134-check_if_last_char_is_a_letter.rs | 4 +- prompts/humaneval-verus/add.txt | 6 + prompts/humaneval-verus/ask_for_fixed.txt | 4 + .../ask_for_fixed_had_errors.txt | 4 + prompts/humaneval-verus/produce.txt | 2 + prompts/humaneval-verus/rewrite.txt | 46 +++++ prompts/humaneval-verus/sys.txt | 3 + prompts/humaneval-verus/timeout.txt | 3 + tests/test_verus.py | 185 ++++++++++++++++++ verified_cogen/runners/languages/__init__.py | 2 + verified_cogen/runners/languages/language.py | 2 +- verified_cogen/runners/languages/verus.py | 32 +++ 16 files changed, 295 insertions(+), 8 deletions(-) create mode 100644 prompts/humaneval-verus/add.txt create mode 100644 prompts/humaneval-verus/ask_for_fixed.txt create mode 100644 prompts/humaneval-verus/ask_for_fixed_had_errors.txt create mode 100644 prompts/humaneval-verus/produce.txt create mode 100644 prompts/humaneval-verus/rewrite.txt create mode 100644 prompts/humaneval-verus/sys.txt create mode 100644 prompts/humaneval-verus/timeout.txt create mode 100644 tests/test_verus.py create mode 100644 verified_cogen/runners/languages/verus.py diff --git a/benches/HumanEval-RustBench/004-mean_absolute_derivation.rs b/benches/HumanEval-RustBench/004-mean_absolute_derivation.rs index 4d964bb..bc7d1d3 100644 --- a/benches/HumanEval-RustBench/004-mean_absolute_derivation.rs +++ b/benches/HumanEval-RustBench/004-mean_absolute_derivation.rs @@ -345,7 +345,7 @@ fn compute_absolute_difference(x: i32, y: i32) -> (z: u32) } // impl-end } -pub fn mean_absolute_deviation(numbers: &[i32]) -> (result: u32) +fn mean_absolute_deviation(numbers: &[i32]) -> (result: u32) // pre-conditions-start requires numbers.len() > 0, diff --git a/benches/HumanEval-RustBench/005-intersperse.rs b/benches/HumanEval-RustBench/005-intersperse.rs index d60f053..5d7077d 100644 --- a/benches/HumanEval-RustBench/005-intersperse.rs +++ b/benches/HumanEval-RustBench/005-intersperse.rs @@ -86,7 +86,7 @@ proof fn intersperse_quantified_is_spec(numbers: Seq, delimiter: u64, inter assert(interspersed =~= intersperse_spec(numbers, delimiter)); // assert-line // impl-end } -pub fn intersperse(numbers: Vec, delimiter: u64) -> (result: Vec) +fn intersperse(numbers: Vec, delimiter: u64) -> (result: Vec) // post-conditions-start ensures result@ == intersperse_spec(numbers@, delimiter), diff --git a/benches/HumanEval-RustBench/076-is_simple_power.rs b/benches/HumanEval-RustBench/076-is_simple_power.rs index f6d2d89..4172b6a 100644 --- a/benches/HumanEval-RustBench/076-is_simple_power.rs +++ b/benches/HumanEval-RustBench/076-is_simple_power.rs @@ -3,7 +3,7 @@ use vstd::arithmetic::power::pow; use vstd::prelude::*; verus! { #[verifier::external_fn_specification] -pub fn ex_ilog(x: u32, base: u32) -> (ret: u32) +fn ex_ilog(x: u32, base: u32) -> (ret: u32) requires x > 0, base > 1, @@ -14,7 +14,7 @@ pub fn ex_ilog(x: u32, base: u32) -> (ret: u32) } #[verifier::external_fn_specification] -pub fn ex_checked_pow(x: u32, exp: u32) -> (ret: Option) +fn ex_checked_pow(x: u32, exp: u32) -> (ret: Option) ensures ret.is_some() <==> ret.unwrap() == pow(x as int, exp as nat), ret.is_none() <==> pow(x as int, exp as nat) > u32::MAX, diff --git a/benches/HumanEval-RustBench/077-is_cube.rs b/benches/HumanEval-RustBench/077-is_cube.rs index bcc58b6..966de25 100644 --- a/benches/HumanEval-RustBench/077-is_cube.rs +++ b/benches/HumanEval-RustBench/077-is_cube.rs @@ -93,7 +93,7 @@ fn checked_cube(x: i32) -> (ret: Option) } #[verifier::external_fn_specification] -pub fn ex_abs(x: i32) -> (ret: i32) +fn ex_abs(x: i32) -> (ret: i32) requires x != i32::MIN, diff --git a/benches/HumanEval-RustBench/134-check_if_last_char_is_a_letter.rs b/benches/HumanEval-RustBench/134-check_if_last_char_is_a_letter.rs index e1cd676..e519a05 100644 --- a/benches/HumanEval-RustBench/134-check_if_last_char_is_a_letter.rs +++ b/benches/HumanEval-RustBench/134-check_if_last_char_is_a_letter.rs @@ -6,7 +6,7 @@ pub spec fn is_alphabetic(c: char) -> (result: bool); #[verifier::external_fn_specification] #[verifier::when_used_as_spec(is_alphabetic)] -pub fn ex_is_alphabetic(c: char) -> (result: bool) +fn ex_is_alphabetic(c: char) -> (result: bool) ensures result <==> (c.is_alphabetic()), { @@ -17,7 +17,7 @@ pub spec fn is_whitespace(c: char) -> (result: bool); #[verifier::external_fn_specification] #[verifier::when_used_as_spec(is_whitespace)] -pub fn ex_is_whitespace(c: char) -> (result: bool) +fn ex_is_whitespace(c: char) -> (result: bool) ensures result <==> (c.is_whitespace()), { diff --git a/prompts/humaneval-verus/add.txt b/prompts/humaneval-verus/add.txt new file mode 100644 index 0000000..a419ffb --- /dev/null +++ b/prompts/humaneval-verus/add.txt @@ -0,0 +1,6 @@ +Given the following verus program, and a set of invariants and assertions, output the program with invariants inserted into the correct place. +The program: +{program} +– +The invariants: +{checks} diff --git a/prompts/humaneval-verus/ask_for_fixed.txt b/prompts/humaneval-verus/ask_for_fixed.txt new file mode 100644 index 0000000..d5c6c30 --- /dev/null +++ b/prompts/humaneval-verus/ask_for_fixed.txt @@ -0,0 +1,4 @@ +The following errors occurred during verification: +{error} + +Please fix the error by adding, removing or modifying the invariants and/or assertions and return the fixed program. diff --git a/prompts/humaneval-verus/ask_for_fixed_had_errors.txt b/prompts/humaneval-verus/ask_for_fixed_had_errors.txt new file mode 100644 index 0000000..e2cb9ad --- /dev/null +++ b/prompts/humaneval-verus/ask_for_fixed_had_errors.txt @@ -0,0 +1,4 @@ +There are still some errors: +{error} + +Could you please fix them? diff --git a/prompts/humaneval-verus/produce.txt b/prompts/humaneval-verus/produce.txt new file mode 100644 index 0000000..4311b02 --- /dev/null +++ b/prompts/humaneval-verus/produce.txt @@ -0,0 +1,2 @@ +Given the following verus program, output invariants and assertions which are required to prove the program correct. +{program} diff --git a/prompts/humaneval-verus/rewrite.txt b/prompts/humaneval-verus/rewrite.txt new file mode 100644 index 0000000..4c7b9a1 --- /dev/null +++ b/prompts/humaneval-verus/rewrite.txt @@ -0,0 +1,46 @@ +Rewrite the following verus program, adding correct invariants into `while` loops. +Also add assertions in nessesary places. +Do not change the code, only add invariants and assertions. Don't remove any helper functions, they are there to help you. +You might need to work with accumulating functions, such as sum, so here's an example of how to do that: +```verus +pub open spec fn sum(numbers: Seq) -> int { + numbers.fold_left(0, |acc: int, x| acc + x) +} +proof fn sum_bound(numbers: Seq) + ensures + sum(numbers) <= numbers.len() * u32::MAX, + decreases numbers.len(), +{ + if numbers.len() == 0 { + } else { + sum_bound(numbers.drop_last()); + } +} +fn sum_numbers(numbers: Vec) -> (result: u64) + requires + numbers.len() < u32::MAX, + ensures + result.0 == sum(numbers@), +{ + let mut sum_value: u64 = 0; + for index in 0..numbers.len() + invariant + numbers.len() < u32::MAX, + sum_value == sum(numbers@.take(index as int)), + index <= numbers.len(), + index >= 0, + { + proof { + sum_bound(numbers@.take(index as int)); + assert(sum_value <= index * u32::MAX); + } + assert(numbers@.take(index as int + 1).drop_last() =~= numbers@.take(index as int)); + assert(numbers[index as int] == numbers@.take(index as int + 1).last()); + sum_value += numbers[index] as u64; + } + assert(numbers@.take(numbers@.len() as int) =~= numbers@); + sum_value +} +``` +The program: +{program} diff --git a/prompts/humaneval-verus/sys.txt b/prompts/humaneval-verus/sys.txt new file mode 100644 index 0000000..a21bcb8 --- /dev/null +++ b/prompts/humaneval-verus/sys.txt @@ -0,0 +1,3 @@ +You are an expert in Verus. +You will be given tasks dealing with Verus programs including precise docstrings and specifications. +Do not provide explanations. Respond only in verus code. diff --git a/prompts/humaneval-verus/timeout.txt b/prompts/humaneval-verus/timeout.txt new file mode 100644 index 0000000..f69fd69 --- /dev/null +++ b/prompts/humaneval-verus/timeout.txt @@ -0,0 +1,3 @@ +The verifier timed out during the verification. +This usually means that the provided invariants were too broad or were difficult to check. +Could you please try to improve the invariants and try again? diff --git a/tests/test_verus.py b/tests/test_verus.py new file mode 100644 index 0000000..195e188 --- /dev/null +++ b/tests/test_verus.py @@ -0,0 +1,185 @@ +from textwrap import dedent +from verified_cogen.runners.languages import LanguageDatabase, register_basic_languages + +register_basic_languages() + + +def test_verus_generate(): + verus_lang = LanguageDatabase().get("verus") + code = dedent( + """\ + fn main(value: i32) -> (result: i32) + requires + value >= 10, + ensures + result >= 20, + { + assert(value * 2 >= 20); // assert-line + value * 2 + } + + spec fn test() {} + + fn is_prime(num: u32) -> (result: bool) + requires + num >= 2, + ensures + result <==> spec_prime(num as int), + { + let mut i = 2; + let mut result = true; + while i < num + // invariants-start + invariant + 2 <= i <= num, + result <==> spec_prime_helper(num as int, i as int), + // invariants-end + { + if num % i == 0 { + result = false; + assert(result <==> spec_prime_helper(num as int, i as int)); // assert-line + } + // assert-start + assert(result <==> spec_prime_helper(num as int, i as int)) by { + assert(true); + } + // assert-end + i += 1; + } + result + }""" + ) + assert verus_lang.generate_validators(code) == dedent( + """\ + verus!{ + fn main_valid(value: i32) -> (result: i32) + requires + value >= 10, + ensures + result >= 20, + { let ret = main(value); ret } + + fn is_prime_valid(num: u32) -> (result: bool) + requires + num >= 2, + ensures + result <==> spec_prime(num as int), + { let ret = is_prime(num); ret } + }""" + ) + + +def test_remove_line(): + verus_lang = LanguageDatabase().get("verus") + code = dedent( + """\ + fn main() { + assert a == 1; // assert-line + }""" + ) + assert verus_lang.remove_asserts_and_invariants(code) == dedent( + """\ + fn main() { + }""" + ) + + +def test_remove_multiline_assert(): + verus_lang = LanguageDatabase().get("verus") + + code = dedent( + """\ + fn main() { + // assert-start + assert a == 1 by { + + } + // assert-end + }""" + ) + assert verus_lang.remove_asserts_and_invariants(code) == dedent( + """\ + fn main() { + }""" + ) + + +def test_remove_invariants(): + verus_lang = LanguageDatabase().get("verus") + + code = dedent( + """\ + fn main() { + while true + // invariants-start + invariant false + invariant true + // invariants-end + { + } + }""" + ) + assert verus_lang.remove_asserts_and_invariants(code) == dedent( + """\ + fn main() { + while true + { + } + }""" + ) + + +def test_remove_all(): + verus_lang = LanguageDatabase().get("verus") + + code = dedent( + """\ + fn is_prime(num: u32) -> (result: bool) + requires + num >= 2, + ensures + result <==> spec_prime(num as int), + { + let mut i = 2; + let mut result = true; + while i < num + // invariants-start + invariant + 2 <= i <= num, + result <==> spec_prime_helper(num as int, i as int), + // invariants-end + { + if num % i == 0 { + result = false; + assert(result <==> spec_prime_helper(num as int, i as int)); // assert-line + } + // assert-start + assert(result <==> spec_prime_helper(num as int, i as int)) by { + assert(true); + } + // assert-end + i += 1; + } + result + }""" + ) + assert verus_lang.remove_asserts_and_invariants(code) == dedent( + """\ + fn is_prime(num: u32) -> (result: bool) + requires + num >= 2, + ensures + result <==> spec_prime(num as int), + { + let mut i = 2; + let mut result = true; + while i < num + { + if num % i == 0 { + result = false; + } + i += 1; + } + result + }""" + ) diff --git a/verified_cogen/runners/languages/__init__.py b/verified_cogen/runners/languages/__init__.py index 2ee70a2..ccce6a7 100644 --- a/verified_cogen/runners/languages/__init__.py +++ b/verified_cogen/runners/languages/__init__.py @@ -1,8 +1,10 @@ from verified_cogen.runners.languages.dafny import DafnyLanguage from verified_cogen.runners.languages.language import LanguageDatabase from verified_cogen.runners.languages.nagini import NaginiLanguage +from verified_cogen.runners.languages.verus import VerusLanguage def register_basic_languages(): LanguageDatabase().register("dafny", ["dfy"], DafnyLanguage()) + LanguageDatabase().register("verus", ["rs"], VerusLanguage()) LanguageDatabase().register("nagini", ["py", "python"], NaginiLanguage()) diff --git a/verified_cogen/runners/languages/language.py b/verified_cogen/runners/languages/language.py index 9182631..3895f6f 100644 --- a/verified_cogen/runners/languages/language.py +++ b/verified_cogen/runners/languages/language.py @@ -42,7 +42,7 @@ def __init__( # type: ignore self.inline_assert_comment = inline_assert_comment def generate_validators(self, code: str) -> str: - methods = self.method_regex.finditer(code) + methods = list(self.method_regex.finditer(code)) validators: list[str] = [] diff --git a/verified_cogen/runners/languages/verus.py b/verified_cogen/runners/languages/verus.py new file mode 100644 index 0000000..6bef493 --- /dev/null +++ b/verified_cogen/runners/languages/verus.py @@ -0,0 +1,32 @@ +import re +from typing import Pattern + +from verified_cogen.runners.languages.language import GenericLanguage + +VERUS_VALIDATOR_TEMPLATE = """\ +fn {method_name}_valid({parameters}) -> ({returns}){specs}\ +{ let ret = {method_name}({param_names}); ret } +""" + + +class VerusLanguage(GenericLanguage): + method_regex: Pattern[str] + + def __init__(self): # type: ignore + super().__init__( + re.compile( + r"^\s*fn\s+(\w+)\s*\((.*?)\)\s*->\s*\((.*?)\)(.*?)\{", + flags=re.DOTALL | re.MULTILINE, + ), + VERUS_VALIDATOR_TEMPLATE, + [ + r" *// assert-start.*?// assert-end\n", + r" *// invariants-start.*?// invariants-end\n", + ], + "// assert-line", + "//", + ) + + def generate_validators(self, code: str) -> str: + result = super().generate_validators(code) + return "verus!{{\n{}}}".format(result)