From 365ff664d3556d91490470b6c2848b39860aec86 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Tue, 5 Mar 2024 00:05:45 -0500 Subject: [PATCH 01/33] Fix tests and bugs --- src/level_gen.cpp | 10 ++++++---- src/mgr.cpp | 6 +++--- tests/bicyclemodel.cpp | 16 +++++++++++++--- tests/observationTest.cpp | 2 +- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/level_gen.cpp b/src/level_gen.cpp index f3c6a70e..d839ef38 100755 --- a/src/level_gen.cpp +++ b/src/level_gen.cpp @@ -29,10 +29,9 @@ static inline void resetAgent(Engine &ctx, Entity agent) { auto speed = ctx.get(agent).velocities[0].length(); auto heading = ctx.get(agent).headings[0]; - Position center{{.x = xCoord + ctx.get(agent).d0, .y = yCoord + ctx.get(agent).d1, .z = 1}}; ctx.get(agent) = { - .position = {.x = center.x, .y = center.y}, .heading = heading, .speed = speed}; - ctx.get(agent) = center; + .position = {.x = xCoord, .y = yCoord}, .heading = heading, .speed = speed}; + ctx.get(agent) = Vector3{.x = xCoord, .y = yCoord, .z = 1}; ctx.get(agent) = Quat::angleAxis(heading, madrona::math::up); ctx.get(agent) = { Vector3{.x = xVelocity, .y = yVelocity, .z = 0}, Vector3::zero()}; @@ -86,9 +85,11 @@ static inline Entity createAgent(Engine &ctx, const MapObject &agentInit) { // values are retained so that on an episode reset they can be restored to // their initial values. auto &trajectory = ctx.get(agent); + auto length = agentInit.length/2; + auto width = agentInit.width/2; for(CountT i = 0; i < agentInit.numPositions; i++) { - trajectory.positions[i] = Vector2{.x = agentInit.position[i].x - ctx.data().mean.x, .y = agentInit.position[i].y - ctx.data().mean.y}; + trajectory.positions[i] = Vector2{.x = agentInit.position[i].x - ctx.data().mean.x + length, .y = agentInit.position[i].y - ctx.data().mean.y + width}; trajectory.velocities[i] = Vector2{.x = agentInit.velocity[i].x, .y = agentInit.velocity[i].y}; trajectory.headings[i] = toRadians(agentInit.heading[i]); trajectory.valids[i] = agentInit.valid[i]; @@ -306,6 +307,7 @@ void createPersistentEntities(Engine &ctx, Map *map) { ctx.data().mean = {0, 0}; ctx.data().mean.x = map->mean.x; ctx.data().mean.y = map->mean.y; + ctx.data().numControlledVehicles = 0; CountT agentIdx; for (agentIdx = 0; agentIdx < map->numObjects; ++agentIdx) { diff --git a/src/mgr.cpp b/src/mgr.cpp index 6cb23e70..412e6e51 100755 --- a/src/mgr.cpp +++ b/src/mgr.cpp @@ -550,7 +550,7 @@ Tensor Manager::shapeTensor() const { Tensor Manager::controlledStateTensor() const { return impl_->exportTensor(ExportID::ControlledState, Tensor::ElementType::Int32, - {impl_->cfg.numWorlds,consts::kMaxAgentCount, 1}); + {impl_->cfg.numWorlds,impl_->agentRoadCounts.first, 1}); } void Manager::triggerReset(int32_t world_idx) @@ -579,7 +579,7 @@ void Manager::setAction(int32_t world_idx, int32_t agent_idx, .headAngle = headAngle}; auto *action_ptr = - impl_->agentActionsBuffer + world_idx * consts::kMaxAgentCount + agent_idx; + impl_->agentActionsBuffer + world_idx * impl_->agentRoadCounts.first + agent_idx; if (impl_->cfg.execMode == ExecMode::CUDA) { #ifdef MADRONA_CUDA_SUPPORT @@ -593,7 +593,7 @@ void Manager::setAction(int32_t world_idx, int32_t agent_idx, Tensor Manager::collisionTensor() const { return impl_->exportTensor( ExportID::Collision, Tensor::ElementType::Int32, - {impl_->cfg.numWorlds, consts::kMaxAgentCount, 1}); + {impl_->cfg.numWorlds, impl_->agentRoadCounts.first, 1}); } std::vector diff --git a/tests/bicyclemodel.cpp b/tests/bicyclemodel.cpp index 8ddebf77..5899c32e 100644 --- a/tests/bicyclemodel.cpp +++ b/tests/bicyclemodel.cpp @@ -38,6 +38,7 @@ class BicycleKinematicModelTest : public ::testing::Test { std::pair mean = {0, 0}; std::unordered_map agent_length_map; + std::unordered_map agent_width_map; std::ifstream data = std::ifstream("testJsons/test.json"); std::vector initialState; std::default_random_engine generator; @@ -57,15 +58,24 @@ class BicycleKinematicModelTest : public ::testing::Test { if (obj["type"] != "vehicle") { continue; } - initialState.push_back(float(obj["position"][0]["x"]) - mean.first); - initialState.push_back(float(obj["position"][0]["y"]) - mean.second); + agent_length_map[n_agents] = (float)obj["length"]; + agent_width_map[n_agents] = (float)obj["width"]; + auto length = agent_length_map[n_agents] / 2; + auto width = agent_width_map[n_agents] / 2; + auto x = float(obj["position"][0]["x"]); + initialState.push_back(float(obj["position"][0]["x"]) - mean.first + length); + initialState.push_back(float(obj["position"][0]["y"]) - mean.second + width); initialState.push_back(test_utils::degreesToRadians(obj["heading"][0])); initialState.push_back(math::Vector2{.x = obj["velocity"][0]["x"], .y = obj["velocity"][0]["y"]}.length()); - agent_length_map[n_agents++] = obj["length"]; + n_agents++; } acc_distribution = std::uniform_real_distribution(-3.0, 2.0); steering_distribution = std::uniform_real_distribution(-0.7, 0.7); generator = std::default_random_engine(42); + + auto shape_tensor = mgr.shapeTensor(); + int32_t *ptr = static_cast(shape_tensor.devicePtr()); + num_agents = ptr[0]; } }; diff --git a/tests/observationTest.cpp b/tests/observationTest.cpp index 4acda6a4..8713a6f5 100755 --- a/tests/observationTest.cpp +++ b/tests/observationTest.cpp @@ -93,7 +93,7 @@ TEST_F(ObservationsTest, TestObservations) { auto obs = mgr.mapObservationTensor(); auto flat_obs = test_utils::flatten_obs(obs); - int64_t idx = 4; // Skip the first 4 points which are garbage for some reason. + int64_t idx = 0; for(int64_t i = 0; i < roadGeoms.size(); i++) { std::vector> roadGeom = roadGeoms[i]; From 63ee2afa53cd794149adbf7d59eeeb0b58920207 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Tue, 5 Mar 2024 15:00:02 -0500 Subject: [PATCH 02/33] init all types of agent --- src/json_serialization.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/json_serialization.hpp b/src/json_serialization.hpp index f872f379..39e262a5 100644 --- a/src/json_serialization.hpp +++ b/src/json_serialization.hpp @@ -215,8 +215,6 @@ namespace gpudrive { if (i < MAX_OBJECTS) { - if(obj.at("type") != "vehicle") - continue; obj.get_to(map.objects[i]); size_t objPoints = map.objects[i].numPositions; map.mean.x = ((map.mean.x * totalPoints) + (map.objects[i].mean.x * objPoints)) / (totalPoints + objPoints); @@ -237,7 +235,6 @@ namespace gpudrive { if (i < MAX_ROADS) { - // road.get_to(map.roads[i]); from_json(road, map.roads[i], polylineReductionThreshold); size_t roadPoints = map.roads[i].numPoints; map.mean.x = ((map.mean.x * totalPoints) + (map.roads[i].mean.x * roadPoints)) / (totalPoints + roadPoints); From 5bc9efc40f57c2aef36a4612ddbc4bba562b35fe Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Sat, 9 Mar 2024 16:17:50 -0500 Subject: [PATCH 03/33] Removed submodule json --- .gitmodules | 3 --- external/nlohmann_json | 1 - 2 files changed, 4 deletions(-) delete mode 160000 external/nlohmann_json diff --git a/.gitmodules b/.gitmodules index f68bb4f2..2f7c1e26 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "external/madrona"] path = external/madrona url = https://github.com/shacklettbp/madrona.git -[submodule "external/json"] - path = external/json - url = https://github.com/nlohmann/json.git diff --git a/external/nlohmann_json b/external/nlohmann_json deleted file mode 160000 index 58d6aa58..00000000 --- a/external/nlohmann_json +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 58d6aa58316a84fc770bdd0409934cdfdf0697dc From 3f2cca732898defa13d4f008442b6e1b4f1b8817 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Sat, 9 Mar 2024 16:19:00 -0500 Subject: [PATCH 04/33] Add Json submodule --- .gitmodules | 3 +++ external/json | 1 + 2 files changed, 4 insertions(+) create mode 160000 external/json diff --git a/.gitmodules b/.gitmodules index 2f7c1e26..f68bb4f2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "external/madrona"] path = external/madrona url = https://github.com/shacklettbp/madrona.git +[submodule "external/json"] + path = external/json + url = https://github.com/nlohmann/json.git diff --git a/external/json b/external/json new file mode 160000 index 00000000..0457de21 --- /dev/null +++ b/external/json @@ -0,0 +1 @@ +Subproject commit 0457de21cffb298c22b629e538036bfeb96130b7 From 07356303a669bd27b67340f75dbeac293166162f Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Sat, 9 Mar 2024 22:15:08 -0500 Subject: [PATCH 05/33] Introduce poetry --- README.md | 21 ++- build.py | 28 +++ environment.yml | 67 +++++++ poetry.lock | 470 ++++++++++++++++++++++++++++++++++++++++++++++++ pyproject.toml | 20 ++- 5 files changed, 602 insertions(+), 4 deletions(-) create mode 100644 build.py create mode 100644 environment.yml create mode 100644 poetry.lock diff --git a/README.md b/README.md index 653e7cbe..0bf34a7e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Madrona Escape Room +GPUDrive ============================ This is an example RL environment simulator built on the [Madrona Engine](https://madrona-engine.github.io). @@ -57,10 +57,12 @@ The built-in training functionality requires [PyTorch 2.0](https://pytorch.org/g Now that you have the required dependencies, fetch the repo (don't forget `--recursive`!): ```bash -git clone --recursive https://github.com/shacklettbp/madrona_escape_room.git -cd madrona_escape_room +git clone --recursive https://github.com/Emerge-Lab/gpudrive.git +cd gpudrive ``` +# Manual Install + Next, for Linux and MacOS: Run `cmake` and then `make` to build the simulator: ```bash mkdir build @@ -89,6 +91,19 @@ Or test the PyTorch training integration: python scripts/train.py --num-worlds 1024 --num-updates 100 --ckpt-dir build/ckpts ``` +# Poetry install + +### Conda + +Create a conda environment using `environment.yml` and then run `poetry install` + +```bash +conda env create -f environment.yml` +poetry install +``` + + + Simulator Code Walkthrough (Learning the Madrona ECS APIs) ----------------------------------------------------------- diff --git a/build.py b/build.py new file mode 100644 index 00000000..98bc022f --- /dev/null +++ b/build.py @@ -0,0 +1,28 @@ +import subprocess +import os +import sys +import logging +import shutil + +logging.basicConfig(level=logging.INFO) + +def main(): + # Cloning the repository, although typically you would not do this in the build step + # as the code should already be present. Including it just for completeness. + subprocess.check_call(['git', 'submodule', 'update', '--init', '--recursive', '--force']) + + # Create and enter the build directory + if not os.path.exists('build'): + os.mkdir('build') + os.chdir('build') + + # Run CMake and Make + subprocess.check_call(['cmake', '..']) + subprocess.check_call(['make', f"-j{os.cpu_count()}"]) # Utilize all available cores + + # Going back to the root directory + os.chdir('..') + +if __name__ == '__main__': + logging.info("Building the C++ code and installing the Python package") + main() \ No newline at end of file diff --git a/environment.yml b/environment.yml new file mode 100644 index 00000000..f79ad921 --- /dev/null +++ b/environment.yml @@ -0,0 +1,67 @@ +name: madrona +channels: + - defaults +dependencies: + - _libgcc_mutex=0.1=main + - _openmp_mutex=5.1=1_gnu + - bzip2=1.0.8=h5eee18b_5 + - ca-certificates=2023.12.12=h06a4308_0 + - ld_impl_linux-64=2.38=h1181459_1 + - libffi=3.4.4=h6a678d5_0 + - libgcc-ng=11.2.0=h1234567_1 + - libgomp=11.2.0=h1234567_1 + - libstdcxx-ng=11.2.0=h1234567_1 + - libuuid=1.41.5=h5eee18b_0 + - ncurses=6.4=h6a678d5_0 + - openssl=3.0.13=h7f8727e_0 + - pip=23.3.1=py311h06a4308_0 + - python=3.11.8=h955ad1f_0 + - readline=8.2=h5eee18b_0 + - setuptools=68.2.2=py311h06a4308_0 + - sqlite=3.41.2=h5eee18b_0 + - tk=8.6.12=h1ccaba5_0 + - tzdata=2024a=h04d1e81_0 + - wheel=0.41.2=py311h06a4308_0 + - xz=5.4.6=h5eee18b_0 + - zlib=1.2.13=h5eee18b_0 + - pip: + - build==1.1.1 + - cachecontrol==0.14.0 + - certifi==2024.2.2 + - cffi==1.16.0 + - charset-normalizer==3.3.2 + - cleo==2.1.0 + - crashtest==0.4.1 + - cryptography==42.0.5 + - distlib==0.3.8 + - dulwich==0.21.7 + - fastjsonschema==2.19.1 + - filelock==3.13.1 + - idna==3.6 + - importlib-metadata==7.0.2 + - installer==0.7.0 + - jaraco-classes==3.3.1 + - jeepney==0.8.0 + - keyring==24.3.1 + - more-itertools==10.2.0 + - msgpack==1.0.8 + - packaging==23.2 + - pexpect==4.9.0 + - pkginfo==1.10.0 + - platformdirs==4.2.0 + - poetry==1.8.2 + - poetry-core==1.9.0 + - poetry-plugin-export==1.6.0 + - ptyprocess==0.7.0 + - pycparser==2.21 + - pyproject-hooks==1.0.0 + - rapidfuzz==3.6.2 + - requests==2.31.0 + - requests-toolbelt==1.0.0 + - secretstorage==3.3.3 + - shellingham==1.5.4 + - tomlkit==0.12.4 + - trove-classifiers==2024.3.3 + - urllib3==2.2.1 + - virtualenv==20.25.1 + - zipp==3.17.0 \ No newline at end of file diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 00000000..fcd473e4 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,470 @@ +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. + +[[package]] +name = "filelock" +version = "3.13.1" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.8" +files = [ + {file = "filelock-3.13.1-py3-none-any.whl", hash = "sha256:57dbda9b35157b05fb3e58ee91448612eb674172fab98ee235ccb0b5bee19a1c"}, + {file = "filelock-3.13.1.tar.gz", hash = "sha256:521f5f56c50f8426f5e03ad3b281b490a87ef15bc6c526f168290f0c7148d44e"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +typing = ["typing-extensions (>=4.8)"] + +[[package]] +name = "fsspec" +version = "2024.2.0" +description = "File-system specification" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fsspec-2024.2.0-py3-none-any.whl", hash = "sha256:817f969556fa5916bc682e02ca2045f96ff7f586d45110fcb76022063ad2c7d8"}, + {file = "fsspec-2024.2.0.tar.gz", hash = "sha256:b6ad1a679f760dda52b1168c859d01b7b80648ea6f7f7c7f5a8a91dc3f3ecb84"}, +] + +[package.extras] +abfs = ["adlfs"] +adl = ["adlfs"] +arrow = ["pyarrow (>=1)"] +dask = ["dask", "distributed"] +devel = ["pytest", "pytest-cov"] +dropbox = ["dropbox", "dropboxdrivefs", "requests"] +full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"] +fuse = ["fusepy"] +gcs = ["gcsfs"] +git = ["pygit2"] +github = ["requests"] +gs = ["gcsfs"] +gui = ["panel"] +hdfs = ["pyarrow (>=1)"] +http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)"] +libarchive = ["libarchive-c"] +oci = ["ocifs"] +s3 = ["s3fs"] +sftp = ["paramiko"] +smb = ["smbprotocol"] +ssh = ["paramiko"] +tqdm = ["tqdm"] + +[[package]] +name = "jinja2" +version = "3.1.3" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, + {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "markupsafe" +version = "2.1.5" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, +] + +[[package]] +name = "mpmath" +version = "1.3.0" +description = "Python library for arbitrary-precision floating-point arithmetic" +optional = false +python-versions = "*" +files = [ + {file = "mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c"}, + {file = "mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f"}, +] + +[package.extras] +develop = ["codecov", "pycodestyle", "pytest (>=4.6)", "pytest-cov", "wheel"] +docs = ["sphinx"] +gmpy = ["gmpy2 (>=2.1.0a4)"] +tests = ["pytest (>=4.6)"] + +[[package]] +name = "networkx" +version = "3.2.1" +description = "Python package for creating and manipulating graphs and networks" +optional = false +python-versions = ">=3.9" +files = [ + {file = "networkx-3.2.1-py3-none-any.whl", hash = "sha256:f18c69adc97877c42332c170849c96cefa91881c99a7cb3e95b7c659ebdc1ec2"}, + {file = "networkx-3.2.1.tar.gz", hash = "sha256:9f1bb5cf3409bf324e0a722c20bdb4c20ee39bf1c30ce8ae499c8502b0b5e0c6"}, +] + +[package.extras] +default = ["matplotlib (>=3.5)", "numpy (>=1.22)", "pandas (>=1.4)", "scipy (>=1.9,!=1.11.0,!=1.11.1)"] +developer = ["changelist (==0.4)", "mypy (>=1.1)", "pre-commit (>=3.2)", "rtoml"] +doc = ["nb2plots (>=0.7)", "nbconvert (<7.9)", "numpydoc (>=1.6)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.14)", "sphinx (>=7)", "sphinx-gallery (>=0.14)", "texext (>=0.6.7)"] +extra = ["lxml (>=4.6)", "pydot (>=1.4.2)", "pygraphviz (>=1.11)", "sympy (>=1.10)"] +test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"] + +[[package]] +name = "numpy" +version = "1.26.4" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"}, + {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"}, + {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"}, + {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"}, + {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"}, + {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"}, + {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"}, + {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"}, + {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"}, + {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"}, + {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"}, + {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"}, + {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"}, + {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"}, + {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"}, + {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"}, + {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"}, + {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"}, + {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"}, + {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"}, + {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"}, + {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"}, + {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"}, +] + +[[package]] +name = "nvidia-cublas-cu12" +version = "12.1.3.1" +description = "CUBLAS native runtime libraries" +optional = false +python-versions = ">=3" +files = [ + {file = "nvidia_cublas_cu12-12.1.3.1-py3-none-manylinux1_x86_64.whl", hash = "sha256:ee53ccca76a6fc08fb9701aa95b6ceb242cdaab118c3bb152af4e579af792728"}, + {file = "nvidia_cublas_cu12-12.1.3.1-py3-none-win_amd64.whl", hash = "sha256:2b964d60e8cf11b5e1073d179d85fa340c120e99b3067558f3cf98dd69d02906"}, +] + +[[package]] +name = "nvidia-cuda-cupti-cu12" +version = "12.1.105" +description = "CUDA profiling tools runtime libs." +optional = false +python-versions = ">=3" +files = [ + {file = "nvidia_cuda_cupti_cu12-12.1.105-py3-none-manylinux1_x86_64.whl", hash = "sha256:e54fde3983165c624cb79254ae9818a456eb6e87a7fd4d56a2352c24ee542d7e"}, + {file = "nvidia_cuda_cupti_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:bea8236d13a0ac7190bd2919c3e8e6ce1e402104276e6f9694479e48bb0eb2a4"}, +] + +[[package]] +name = "nvidia-cuda-nvrtc-cu12" +version = "12.1.105" +description = "NVRTC native runtime libraries" +optional = false +python-versions = ">=3" +files = [ + {file = "nvidia_cuda_nvrtc_cu12-12.1.105-py3-none-manylinux1_x86_64.whl", hash = "sha256:339b385f50c309763ca65456ec75e17bbefcbbf2893f462cb8b90584cd27a1c2"}, + {file = "nvidia_cuda_nvrtc_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:0a98a522d9ff138b96c010a65e145dc1b4850e9ecb75a0172371793752fd46ed"}, +] + +[[package]] +name = "nvidia-cuda-runtime-cu12" +version = "12.1.105" +description = "CUDA Runtime native Libraries" +optional = false +python-versions = ">=3" +files = [ + {file = "nvidia_cuda_runtime_cu12-12.1.105-py3-none-manylinux1_x86_64.whl", hash = "sha256:6e258468ddf5796e25f1dc591a31029fa317d97a0a94ed93468fc86301d61e40"}, + {file = "nvidia_cuda_runtime_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:dfb46ef84d73fababab44cf03e3b83f80700d27ca300e537f85f636fac474344"}, +] + +[[package]] +name = "nvidia-cudnn-cu12" +version = "8.9.2.26" +description = "cuDNN runtime libraries" +optional = false +python-versions = ">=3" +files = [ + {file = "nvidia_cudnn_cu12-8.9.2.26-py3-none-manylinux1_x86_64.whl", hash = "sha256:5ccb288774fdfb07a7e7025ffec286971c06d8d7b4fb162525334616d7629ff9"}, +] + +[package.dependencies] +nvidia-cublas-cu12 = "*" + +[[package]] +name = "nvidia-cufft-cu12" +version = "11.0.2.54" +description = "CUFFT native runtime libraries" +optional = false +python-versions = ">=3" +files = [ + {file = "nvidia_cufft_cu12-11.0.2.54-py3-none-manylinux1_x86_64.whl", hash = "sha256:794e3948a1aa71fd817c3775866943936774d1c14e7628c74f6f7417224cdf56"}, + {file = "nvidia_cufft_cu12-11.0.2.54-py3-none-win_amd64.whl", hash = "sha256:d9ac353f78ff89951da4af698f80870b1534ed69993f10a4cf1d96f21357e253"}, +] + +[[package]] +name = "nvidia-curand-cu12" +version = "10.3.2.106" +description = "CURAND native runtime libraries" +optional = false +python-versions = ">=3" +files = [ + {file = "nvidia_curand_cu12-10.3.2.106-py3-none-manylinux1_x86_64.whl", hash = "sha256:9d264c5036dde4e64f1de8c50ae753237c12e0b1348738169cd0f8a536c0e1e0"}, + {file = "nvidia_curand_cu12-10.3.2.106-py3-none-win_amd64.whl", hash = "sha256:75b6b0c574c0037839121317e17fd01f8a69fd2ef8e25853d826fec30bdba74a"}, +] + +[[package]] +name = "nvidia-cusolver-cu12" +version = "11.4.5.107" +description = "CUDA solver native runtime libraries" +optional = false +python-versions = ">=3" +files = [ + {file = "nvidia_cusolver_cu12-11.4.5.107-py3-none-manylinux1_x86_64.whl", hash = "sha256:8a7ec542f0412294b15072fa7dab71d31334014a69f953004ea7a118206fe0dd"}, + {file = "nvidia_cusolver_cu12-11.4.5.107-py3-none-win_amd64.whl", hash = "sha256:74e0c3a24c78612192a74fcd90dd117f1cf21dea4822e66d89e8ea80e3cd2da5"}, +] + +[package.dependencies] +nvidia-cublas-cu12 = "*" +nvidia-cusparse-cu12 = "*" +nvidia-nvjitlink-cu12 = "*" + +[[package]] +name = "nvidia-cusparse-cu12" +version = "12.1.0.106" +description = "CUSPARSE native runtime libraries" +optional = false +python-versions = ">=3" +files = [ + {file = "nvidia_cusparse_cu12-12.1.0.106-py3-none-manylinux1_x86_64.whl", hash = "sha256:f3b50f42cf363f86ab21f720998517a659a48131e8d538dc02f8768237bd884c"}, + {file = "nvidia_cusparse_cu12-12.1.0.106-py3-none-win_amd64.whl", hash = "sha256:b798237e81b9719373e8fae8d4f091b70a0cf09d9d85c95a557e11df2d8e9a5a"}, +] + +[package.dependencies] +nvidia-nvjitlink-cu12 = "*" + +[[package]] +name = "nvidia-nccl-cu12" +version = "2.19.3" +description = "NVIDIA Collective Communication Library (NCCL) Runtime" +optional = false +python-versions = ">=3" +files = [ + {file = "nvidia_nccl_cu12-2.19.3-py3-none-manylinux1_x86_64.whl", hash = "sha256:a9734707a2c96443331c1e48c717024aa6678a0e2a4cb66b2c364d18cee6b48d"}, +] + +[[package]] +name = "nvidia-nvjitlink-cu12" +version = "12.4.99" +description = "Nvidia JIT LTO Library" +optional = false +python-versions = ">=3" +files = [ + {file = "nvidia_nvjitlink_cu12-12.4.99-py3-none-manylinux2014_x86_64.whl", hash = "sha256:c6428836d20fe7e327191c175791d38570e10762edc588fb46749217cd444c74"}, + {file = "nvidia_nvjitlink_cu12-12.4.99-py3-none-win_amd64.whl", hash = "sha256:991905ffa2144cb603d8ca7962d75c35334ae82bf92820b6ba78157277da1ad2"}, +] + +[[package]] +name = "nvidia-nvtx-cu12" +version = "12.1.105" +description = "NVIDIA Tools Extension" +optional = false +python-versions = ">=3" +files = [ + {file = "nvidia_nvtx_cu12-12.1.105-py3-none-manylinux1_x86_64.whl", hash = "sha256:dc21cf308ca5691e7c04d962e213f8a4aa9bbfa23d95412f452254c2caeb09e5"}, + {file = "nvidia_nvtx_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:65f4d98982b31b60026e0e6de73fbdfc09d08a96f4656dd3665ca616a11e1e82"}, +] + +[[package]] +name = "sympy" +version = "1.12" +description = "Computer algebra system (CAS) in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sympy-1.12-py3-none-any.whl", hash = "sha256:c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5"}, + {file = "sympy-1.12.tar.gz", hash = "sha256:ebf595c8dac3e0fdc4152c51878b498396ec7f30e7a914d6071e674d49420fb8"}, +] + +[package.dependencies] +mpmath = ">=0.19" + +[[package]] +name = "torch" +version = "2.2.1" +description = "Tensors and Dynamic neural networks in Python with strong GPU acceleration" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "torch-2.2.1-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:8d3bad336dd2c93c6bcb3268e8e9876185bda50ebde325ef211fb565c7d15273"}, + {file = "torch-2.2.1-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:5297f13370fdaca05959134b26a06a7f232ae254bf2e11a50eddec62525c9006"}, + {file = "torch-2.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:5f5dee8433798888ca1415055f5e3faf28a3bad660e4c29e1014acd3275ab11a"}, + {file = "torch-2.2.1-cp310-none-macosx_10_9_x86_64.whl", hash = "sha256:b6d78338acabf1fb2e88bf4559d837d30230cf9c3e4337261f4d83200df1fcbe"}, + {file = "torch-2.2.1-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:6ab3ea2e29d1aac962e905142bbe50943758f55292f1b4fdfb6f4792aae3323e"}, + {file = "torch-2.2.1-cp311-cp311-manylinux1_x86_64.whl", hash = "sha256:d86664ec85902967d902e78272e97d1aff1d331f7619d398d3ffab1c9b8e9157"}, + {file = "torch-2.2.1-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:d6227060f268894f92c61af0a44c0d8212e19cb98d05c20141c73312d923bc0a"}, + {file = "torch-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:77e990af75fb1675490deb374d36e726f84732cd5677d16f19124934b2409ce9"}, + {file = "torch-2.2.1-cp311-none-macosx_10_9_x86_64.whl", hash = "sha256:46085e328d9b738c261f470231e987930f4cc9472d9ffb7087c7a1343826ac51"}, + {file = "torch-2.2.1-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:2d9e7e5ecbb002257cf98fae13003abbd620196c35f85c9e34c2adfb961321ec"}, + {file = "torch-2.2.1-cp312-cp312-manylinux1_x86_64.whl", hash = "sha256:ada53aebede1c89570e56861b08d12ba4518a1f8b82d467c32665ec4d1f4b3c8"}, + {file = "torch-2.2.1-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:be21d4c41ecebed9e99430dac87de1439a8c7882faf23bba7fea3fea7b906ac1"}, + {file = "torch-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:79848f46196750367dcdf1d2132b722180b9d889571e14d579ae82d2f50596c5"}, + {file = "torch-2.2.1-cp312-none-macosx_10_9_x86_64.whl", hash = "sha256:7ee804847be6be0032fbd2d1e6742fea2814c92bebccb177f0d3b8e92b2d2b18"}, + {file = "torch-2.2.1-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:84b2fb322ab091039fdfe74e17442ff046b258eb5e513a28093152c5b07325a7"}, + {file = "torch-2.2.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:5c0c83aa7d94569997f1f474595e808072d80b04d34912ce6f1a0e1c24b0c12a"}, + {file = "torch-2.2.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:91a1b598055ba06b2c386415d2e7f6ac818545e94c5def597a74754940188513"}, + {file = "torch-2.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:8f93ddf3001ecec16568390b507652644a3a103baa72de3ad3b9c530e3277098"}, + {file = "torch-2.2.1-cp38-none-macosx_10_9_x86_64.whl", hash = "sha256:0e8bdd4c77ac2584f33ee14c6cd3b12767b4da508ec4eed109520be7212d1069"}, + {file = "torch-2.2.1-cp38-none-macosx_11_0_arm64.whl", hash = "sha256:6a21bcd7076677c97ca7db7506d683e4e9db137e8420eb4a68fb67c3668232a7"}, + {file = "torch-2.2.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f1b90ac61f862634039265cd0f746cc9879feee03ff962c803486301b778714b"}, + {file = "torch-2.2.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:ed9e29eb94cd493b36bca9cb0b1fd7f06a0688215ad1e4b3ab4931726e0ec092"}, + {file = "torch-2.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:c47bc25744c743f3835831a20efdcfd60aeb7c3f9804a213f61e45803d16c2a5"}, + {file = "torch-2.2.1-cp39-none-macosx_10_9_x86_64.whl", hash = "sha256:0952549bcb43448c8d860d5e3e947dd18cbab491b14638e21750cb3090d5ad3e"}, + {file = "torch-2.2.1-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:26bd2272ec46fc62dcf7d24b2fb284d44fcb7be9d529ebf336b9860350d674ed"}, +] + +[package.dependencies] +filelock = "*" +fsspec = "*" +jinja2 = "*" +networkx = "*" +nvidia-cublas-cu12 = {version = "12.1.3.1", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-cuda-cupti-cu12 = {version = "12.1.105", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-cuda-nvrtc-cu12 = {version = "12.1.105", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-cuda-runtime-cu12 = {version = "12.1.105", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-cudnn-cu12 = {version = "8.9.2.26", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-cufft-cu12 = {version = "11.0.2.54", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-curand-cu12 = {version = "10.3.2.106", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-cusolver-cu12 = {version = "11.4.5.107", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-cusparse-cu12 = {version = "12.1.0.106", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-nccl-cu12 = {version = "2.19.3", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +nvidia-nvtx-cu12 = {version = "12.1.105", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} +sympy = "*" +triton = {version = "2.2.0", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and python_version < \"3.12\""} +typing-extensions = ">=4.8.0" + +[package.extras] +opt-einsum = ["opt-einsum (>=3.3)"] +optree = ["optree (>=0.9.1)"] + +[[package]] +name = "triton" +version = "2.2.0" +description = "A language and compiler for custom Deep Learning operations" +optional = false +python-versions = "*" +files = [ + {file = "triton-2.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2294514340cfe4e8f4f9e5c66c702744c4a117d25e618bd08469d0bfed1e2e5"}, + {file = "triton-2.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da58a152bddb62cafa9a857dd2bc1f886dbf9f9c90a2b5da82157cd2b34392b0"}, + {file = "triton-2.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af58716e721460a61886668b205963dc4d1e4ac20508cc3f623aef0d70283d5"}, + {file = "triton-2.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e8fe46d3ab94a8103e291bd44c741cc294b91d1d81c1a2888254cbf7ff846dab"}, + {file = "triton-2.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8ce26093e539d727e7cf6f6f0d932b1ab0574dc02567e684377630d86723ace"}, + {file = "triton-2.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:227cc6f357c5efcb357f3867ac2a8e7ecea2298cd4606a8ba1e931d1d5a947df"}, +] + +[package.dependencies] +filelock = "*" + +[package.extras] +build = ["cmake (>=3.20)", "lit"] +tests = ["autopep8", "flake8", "isort", "numpy", "pytest", "scipy (>=1.7.1)", "torch"] +tutorials = ["matplotlib", "pandas", "tabulate", "torch"] + +[[package]] +name = "typing-extensions" +version = "4.10.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"}, + {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.11" +content-hash = "97b2806066f6e80bd92d4441827c4f8143e924af4bcddfce52ea1d84162b42f3" diff --git a/pyproject.toml b/pyproject.toml index 4739474f..2f91e255 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = [] +requires = ["poetry-core"] build-backend = "madrona-py-build" backend-path = ["external/madrona/py"] @@ -14,3 +14,21 @@ ext-out-dir = "build" # This module includes the PPO implementation for the training demo [tool.madrona.packages.gpudrive_learn] path = "train_src/gpudrive_learn" + +[tool.poetry.build] +script = "build.py" + +[tool.poetry.dependencies] +python = "^3.11" +torch = "^2.2.1" +numpy = "^1.26.4" + +[tool.poetry] +name = "gpudrive" +version = "0.1.0" +description = "" +authors = ["Sébastien Eustace "] +readme = "README.md" +packages = [ + {include = "gpudrive.cpython-311-x86_64-linux-gnu.so", from = "build", to = "gpudrive"} +] \ No newline at end of file From 63f63985671d988f64296e5a779f75a26b6e08c3 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Sun, 10 Mar 2024 19:07:52 -0400 Subject: [PATCH 06/33] Define the action and observation space --- README.md | 55 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 0bf34a7e..086f1541 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,45 @@ GPUDrive ============================ -This is an example RL environment simulator built on the [Madrona Engine](https://madrona-engine.github.io). -The goal of this repository is to provide a simple reference that demonstrates how to use Madrona's ECS APIs and -how to interface with the engine's rigid body physics and rendering functionality. -This example also demonstrates how to integrate the simulator with python code for evaluating agent polices and/or policy learning. Specifically, this codebase includes a simple PyTorch PPO training loop integrated with the simulator that can train agents in under an hour on a high end GPU. - -If you're interested in using Madrona to implement a high-performance batch simulator for a new environment or RL training task, we highly recommend forking this repo and adding/removing code as needed, rather than starting from scratch. This will ensure the build system and backends are setup correctly. +This is an Batch RL environment simulator of Nocturne built on the [Madrona Engine](https://madrona-engine.github.io). It supports loading multiple worlds with multi agent support. Python bindings are exposed for easy integration with RL algorithms. The Environment and Learning Task -------------- -https://github.com/shacklettbp/madrona_escape_room/assets/1111429/ec6231c8-a74b-4f0a-8a1a-b1bcdc7111cd +The codebase trains a shared policy that controls agents individually with direct engine inputs rather than pixel observations. Agents interact with the simulator as follows: -As shown above, the simulator implements a 3D environment consisting of two agents and a row of three rooms. All agents start in the first room, and must navigate to as many new rooms as possible. The agents must step on buttons or push movable blocks over buttons to trigger the opening of doors that lead to new rooms. Agents are rewarded based on their progress along the length of the level. +### Action Space: + * Acceleration: Continuous float values for acceleration applied to the agents. + * Steering angle: Continuous float values for steering angle applied according to the bicycle kinematic model. + * Heading angle (currently unused): Continuous float values for heading angle. This controls where the agent is looking. -The codebase trains a shared policy that controls agents individually with direct engine inputs rather than pixel observations. Agents interact with the simulator as follows: +### Observation Space: + +**SelfObservation** + +The `SelfObservation` tensor of shape `(5,)` for each agent provides information about the agent's own state. The respective values are + +- `SelfObservation[0]`: Represents the current *speed* of the agent. +- `SelfObservation[1:3]` : *length* and *width* of the agent. +- `SelfObservation[3:5]`: *Coordinates (x,y)* of the goal relative to the agent. + +**PartnerObservation** + +The `PartnerObservation` tensor of shape `(num_agents-1,7)` for each agent provides information about other agents in the range `params.observationRadius`. All the values in this tensor are *relative to the ego agent*. The respective values for each `PartnerObservation` are + +- `PartnerObservation[0]`: The *speed* of the observed neighboring agent. +- `PartnerObservation[1:3]`: The *position (x,y)* of the observed neighbouring agent. +- `PartnerObservation[3]`: The *orientation* of the neighboring agent. +- `PartnerObservation[4:6]`: The *length* and *width* of the neighbouring agent. +- `PartnerObservation[6]`: The type of agent. + +**AgentMapObservations** + +The `AgentMapObservations` tensor of shape (num_road_objs, 4) for each agent provides information about the road objects in the range `params.observationRadius`. All the values in this tensor are *relative to the ego agent*. The respective values for each `AgentMapObservations` are -**Action Space:** - * Movement amount: Egocentric polar coordinates for the direction and amount to move, translated to XY forces in the physics engine. - * Rotation amount: Torque applied to the agent to turn. - * Grab: Boolean, true to grab if possible or release if already holding an object. - -**Observation Space:** - * Global position. - * Position within the current room. - * Distance and direction to all the buttons and cubes in the current room (egocentric polar coordinates). - * 30 Lidar samples arrayed in a circle around the agent, giving distance to the nearest object along a direction. - * Whether the current room's door is open (boolean). - * Whether an object is currently grabbed (boolean). - * The max distance achieved so far in the level. - * The number of steps remaining in the episode. +- `AgentMapObservations[0:2]`: The position coordinates for the road object. +- `AgentMapObservations[2]`: The relative orientation of the road object. +- `AgentMapObservations[3]`: The road object type. **Rewards:** Agents are rewarded for the max distance achieved along the Y axis (the length of the level). Each step, new reward is assigned if the agents have progressed further in the level, or a small penalty reward is assigned if not. From e41c113eacac309e11518fd0e2d3b87f7bcf1851 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Mon, 11 Mar 2024 17:25:01 -0400 Subject: [PATCH 07/33] Cover the export size behind static asserts --- src/consts.hpp | 4 ++-- src/mgr.cpp | 10 +++++----- src/types.hpp | 27 ++++++++++++++++++++++++++- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/consts.hpp b/src/consts.hpp index e5e0e5ea..02fa32d3 100644 --- a/src/consts.hpp +++ b/src/consts.hpp @@ -8,8 +8,8 @@ namespace gpudrive { namespace consts { -inline constexpr madrona::CountT kMaxAgentCount = 100; -inline constexpr madrona::CountT kMaxRoadEntityCount = 500; +inline constexpr madrona::CountT kMaxAgentCount = 5; +inline constexpr madrona::CountT kMaxRoadEntityCount = 160; // Various world / entity size parameters inline constexpr float worldLength = 40.f; diff --git a/src/mgr.cpp b/src/mgr.cpp index da4e7168..4cd68e63 100755 --- a/src/mgr.cpp +++ b/src/mgr.cpp @@ -461,7 +461,7 @@ Tensor Manager::bicycleModelTensor() const { impl_->cfg.numWorlds, impl_->agentRoadCounts.first, - 4, // Number of states for the bicycle model + BicycleModelExportSize, // Number of states for the bicycle model }); } @@ -493,7 +493,7 @@ Tensor Manager::selfObservationTensor() const { impl_->cfg.numWorlds, impl_->agentRoadCounts.first, - 8 + SelfObservationExportSize }); } @@ -504,7 +504,7 @@ Tensor Manager::mapObservationTensor() const { impl_->cfg.numWorlds, impl_->agentRoadCounts.second, - 4 + MapObservationExportSize }); } @@ -516,7 +516,7 @@ Tensor Manager::partnerObservationsTensor() const impl_->cfg.numWorlds, impl_->agentRoadCounts.first, consts::kMaxAgentCount-1, - 7, + PartnerObservationExportSize, }); } @@ -528,7 +528,7 @@ Tensor Manager::agentMapObservationsTensor() const impl_->cfg.numWorlds, impl_->agentRoadCounts.first, consts::kMaxRoadEntityCount, - 4, + AgentMapObservationExportSize, }); } diff --git a/src/types.hpp b/src/types.hpp index 86b979be..773d8c65 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -26,6 +26,10 @@ struct BicycleModel { float speed; }; +const int BicycleModelExportSize = 4; + +static_assert(sizeof(BicycleModel) == sizeof(float) * BicycleModelExportSize); + struct VehicleSize { float length; float width; @@ -71,12 +75,24 @@ struct SelfObservation { Goal goal; }; +const int SelfObservationExportSize = 5; + +// SelfObservation is exported as a +// [N, A, 5] float tensor to pytorch +static_assert(sizeof(SelfObservation) == sizeof(float) * SelfObservationExportSize); + struct MapObservation { madrona::math::Vector2 position; float heading; float type; }; +const int MapObservationExportSize = 4; + +// MapObservation is exported as a +// [N, numRoadEntities, 4] float tensor to pytorch +static_assert(sizeof(MapObservation) == sizeof(float) * MapObservationExportSize); + struct PartnerObservation { float speed; madrona::math::Vector2 position; @@ -90,15 +106,24 @@ struct PartnerObservations { PartnerObservation obs[consts::kMaxAgentCount - 1]; }; +const int PartnerObservationExportSize = 7; + // PartnerObservations is exported as a // [N, A, consts::numAgents - 1, 3] // tensor to pytorch static_assert(sizeof(PartnerObservations) == sizeof(float) * - (consts::kMaxAgentCount - 1) * 7); + (consts::kMaxAgentCount - 1) * PartnerObservationExportSize); struct AgentMapObservations { MapObservation obs[consts::kMaxRoadEntityCount]; }; +const int AgentMapObservationExportSize = 4; + +// AgentMapObservations is exported as a +// [N, A, numRoadEntities, 4] float tensor to pytorch + +static_assert(sizeof(AgentMapObservations) == sizeof(float) * + consts::kMaxRoadEntityCount * AgentMapObservationExportSize); struct LidarSample { From 4b18816bb528679af00383dcfac4c3b65b574a9c Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Mon, 11 Mar 2024 17:47:20 -0400 Subject: [PATCH 08/33] Ignore collisions for bicycle test --- src/bindings.cpp | 5 +++++ src/consts.hpp | 2 +- src/init.hpp | 8 ++++++++ src/mgr.cpp | 5 +++++ src/sim.cpp | 2 +- tests/bicyclemodel.cpp | 3 ++- 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/bindings.cpp b/src/bindings.cpp index 0aa36f10..5cc51b30 100644 --- a/src/bindings.cpp +++ b/src/bindings.cpp @@ -38,6 +38,11 @@ namespace gpudrive .def_rw("observationRadius", &Parameters::observationRadius) .def_rw("rewardParams", &Parameters::rewardParams); + // Define CollisionBehaviour enum + nb::enum_(m, "CollisionBehaviour") + .value("AgentStop", CollisionBehaviour::AgentStop) + .value("AgentRemoved", CollisionBehaviour::AgentRemoved) + .value("Ignore", CollisionBehaviour::Ignore); // Bindings for Manager class nb::class_(m, "SimManager") diff --git a/src/consts.hpp b/src/consts.hpp index 02fa32d3..9e4dacc9 100644 --- a/src/consts.hpp +++ b/src/consts.hpp @@ -9,7 +9,7 @@ namespace gpudrive { namespace consts { inline constexpr madrona::CountT kMaxAgentCount = 5; -inline constexpr madrona::CountT kMaxRoadEntityCount = 160; +inline constexpr madrona::CountT kMaxRoadEntityCount = 6000; // Various world / entity size parameters inline constexpr float worldLength = 40.f; diff --git a/src/init.hpp b/src/init.hpp index d69277de..d5eca222 100755 --- a/src/init.hpp +++ b/src/init.hpp @@ -98,6 +98,13 @@ namespace gpudrive Dense // negative distance to expert trajectory }; + enum class CollisionBehaviour: uint32_t + { + AgentStop, + AgentRemoved, // Unimplemented + Ignore + }; + struct RewardParams { RewardType rewardType; @@ -110,6 +117,7 @@ namespace gpudrive float polylineReductionThreshold; float observationRadius; RewardParams rewardParams; + CollisionBehaviour collisionBehaviour = CollisionBehaviour::AgentStop; // Default: AgentStop uint32_t maxNumControlledVehicles = 10000; // Arbitrary high number to by default control all vehicles }; diff --git a/src/mgr.cpp b/src/mgr.cpp index 4cd68e63..baeb483a 100755 --- a/src/mgr.cpp +++ b/src/mgr.cpp @@ -266,6 +266,11 @@ Manager::Impl * Manager::Impl::init( 0 // kMaxRoadEntityCount }; + if(mgr_cfg.params.collisionBehaviour == CollisionBehaviour::AgentRemoved) + { + FATAL("AgentRemoved collision behaviour is not implemented yet."); + } + switch (mgr_cfg.execMode) { case ExecMode::CUDA: { #ifdef MADRONA_CUDA_SUPPORT diff --git a/src/sim.cpp b/src/sim.cpp index 3588e695..be44c4d6 100755 --- a/src/sim.cpp +++ b/src/sim.cpp @@ -227,7 +227,7 @@ inline void movementSystem(Engine &e, return; } - if (collisionEvent.hasCollided.load_relaxed()) + if (collisionEvent.hasCollided.load_relaxed() && e.data().params.collisionBehaviour == CollisionBehaviour::AgentStop) { return; } diff --git a/tests/bicyclemodel.cpp b/tests/bicyclemodel.cpp index 5899c32e..2f041dc6 100644 --- a/tests/bicyclemodel.cpp +++ b/tests/bicyclemodel.cpp @@ -25,7 +25,8 @@ class BicycleKinematicModelTest : public ::testing::Test { .jsonPath = "testJsons", .params = { .polylineReductionThreshold = 0.0, - .observationRadius = 100.0 + .observationRadius = 100.0, + .collisionBehaviour = gpudrive::CollisionBehaviour::Ignore, } }); From 5d02a4a2eedac7748ed29f16d13ac2324438a469 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Mon, 11 Mar 2024 18:19:32 -0400 Subject: [PATCH 09/33] Change conda env name to gpudrive add prepush hook --- environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/environment.yml b/environment.yml index f79ad921..913858eb 100644 --- a/environment.yml +++ b/environment.yml @@ -1,4 +1,4 @@ -name: madrona +name: gpudrive channels: - defaults dependencies: From b9e37e22c3c59d0916a6d1382f144b535611d2b4 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Mon, 11 Mar 2024 18:33:26 -0400 Subject: [PATCH 10/33] Create manual.yml --- .github/workflows/manual.yml | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/manual.yml diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml new file mode 100644 index 00000000..abe0cfed --- /dev/null +++ b/.github/workflows/manual.yml @@ -0,0 +1,36 @@ +name: Run C++ tests + +on: + pull_request: + +jobs: + build-and-test: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Install system dependencies + run: | + sudo apt update + sudo apt install -y libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev mesa-common-dev libc++1 + + - name: Setup Conda environment. + uses: conda-incubator/setup-miniconda@v2 + with: + activate-environment: gpudrive + environment-file: environment.yml + python-version: 3.8.11 + - name: Install Poetry + run: | + pip install poetry + + - name: Install dependencies and build the project with Poetry + run: | + poetry install + + - name: Run tests + run: | + cd build/ + ctest From c874b573ca3e583fa65e7e381bb80fc6556fda0b Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Mon, 11 Mar 2024 18:39:51 -0400 Subject: [PATCH 11/33] Update manual.yml --- .github/workflows/manual.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml index abe0cfed..5686c2fd 100644 --- a/.github/workflows/manual.yml +++ b/.github/workflows/manual.yml @@ -21,7 +21,6 @@ jobs: with: activate-environment: gpudrive environment-file: environment.yml - python-version: 3.8.11 - name: Install Poetry run: | pip install poetry From e7fad94d40cc33fb315c1dd01651412513f25ce7 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Mon, 11 Mar 2024 18:43:04 -0400 Subject: [PATCH 12/33] Update manual.yml --- .github/workflows/manual.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml index 5686c2fd..03b5876a 100644 --- a/.github/workflows/manual.yml +++ b/.github/workflows/manual.yml @@ -21,9 +21,6 @@ jobs: with: activate-environment: gpudrive environment-file: environment.yml - - name: Install Poetry - run: | - pip install poetry - name: Install dependencies and build the project with Poetry run: | From dd8d66856609620a378ec514d783bd1cc4f44d60 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Mon, 11 Mar 2024 18:45:11 -0400 Subject: [PATCH 13/33] Update manual.yml --- .github/workflows/manual.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml index 03b5876a..e0cda354 100644 --- a/.github/workflows/manual.yml +++ b/.github/workflows/manual.yml @@ -24,6 +24,7 @@ jobs: - name: Install dependencies and build the project with Poetry run: | + conda activate gpudrive poetry install - name: Run tests From e44556b74dc1f5b11cbc0e3673bd1548009282e3 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Mon, 11 Mar 2024 18:51:17 -0400 Subject: [PATCH 14/33] Update manual.yml --- .github/workflows/manual.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml index e0cda354..66f3217c 100644 --- a/.github/workflows/manual.yml +++ b/.github/workflows/manual.yml @@ -5,8 +5,11 @@ on: jobs: build-and-test: - runs-on: ubuntu-latest + runs-on: ubuntu-latest + defaults: + run: + shell: bash -l {0} steps: - name: Checkout code uses: actions/checkout@v2 @@ -24,7 +27,6 @@ jobs: - name: Install dependencies and build the project with Poetry run: | - conda activate gpudrive poetry install - name: Run tests From 14936901a39b4539ce5c5dc4a8157aa5f93c337c Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Mon, 11 Mar 2024 19:05:52 -0400 Subject: [PATCH 15/33] Make a release build on poetry install --- build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.py b/build.py index 98bc022f..ee1dd4b9 100644 --- a/build.py +++ b/build.py @@ -17,7 +17,7 @@ def main(): os.chdir('build') # Run CMake and Make - subprocess.check_call(['cmake', '..']) + subprocess.check_call(['cmake', '..', '-DCMAKE_BUILD_TYPE=Release']) subprocess.check_call(['make', f"-j{os.cpu_count()}"]) # Utilize all available cores # Going back to the root directory From 1d91b55f3426999720045c8bc757f005bbb53cd9 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Mon, 11 Mar 2024 19:12:00 -0400 Subject: [PATCH 16/33] Update manual.yml --- .github/workflows/manual.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/manual.yml b/.github/workflows/manual.yml index 66f3217c..d2e010d9 100644 --- a/.github/workflows/manual.yml +++ b/.github/workflows/manual.yml @@ -32,4 +32,4 @@ jobs: - name: Run tests run: | cd build/ - ctest + ctest --rerun-failed --output-on-failure From e465cfb1a62825e1d1c15affed78a0c322735c83 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Wed, 13 Mar 2024 15:45:27 -0400 Subject: [PATCH 17/33] Fix export size --- src/types.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types.hpp b/src/types.hpp index 9446c675..1400bc4a 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -76,7 +76,7 @@ struct SelfObservation { float collisionState; }; -const int SelfObservationExportSize = 5; +const int SelfObservationExportSize = 6; // SelfObservation is exported as a // [N, A, 5] float tensor to pytorch From 1df6094fa7db3236c30bf7ff334b1990fa1097d8 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Wed, 13 Mar 2024 18:04:16 -0400 Subject: [PATCH 18/33] Ignore Collisions --- src/sim.cpp | 21 ++++++++++++++++++++- src/sim.hpp | 13 +++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/sim.cpp b/src/sim.cpp index dacee3d9..5d286c3d 100755 --- a/src/sim.cpp +++ b/src/sim.cpp @@ -499,6 +499,24 @@ void collisionDetectionSystem(Engine &ctx, if (not hasCollided) { return; } + + EntityType aEntitytype = ctx.get(candidateCollision.aEntity); + EntityType bEntitytype = ctx.get(candidateCollision.bEntity); + + // Ignore collisions between certain entity types + if(aEntitytype == EntityType::Padding || bEntitytype == EntityType::Padding) + { + return; + } + + for(auto &pair : ctx.data().collisionPairs) + { + if((pair.first == aEntitytype && pair.second == bEntitytype) || + (pair.first == bEntitytype && pair.second == aEntitytype)) + { + return; + } + } auto maybeCollisionEventA = ctx.getSafe(candidateCollision.aEntity); @@ -680,7 +698,8 @@ Sim::Sim(Engine &ctx, episodeMgr(init.episodeMgr), params(*init.params), MaxAgentCount(cfg.kMaxAgentCount), - MaxRoadEntityCount(cfg.kMaxRoadEntityCount) + MaxRoadEntityCount(cfg.kMaxRoadEntityCount), + collisionPairs(initializeCollisionPairs()) { // Below check is used to ensure that the map is not empty due to incorrect WorldInit copy to GPU assert(init.map->numObjects); diff --git a/src/sim.hpp b/src/sim.hpp index f49ef4d4..563c96e6 100755 --- a/src/sim.hpp +++ b/src/sim.hpp @@ -68,6 +68,19 @@ struct Sim : public madrona::WorldBase { static void setupTasks(madrona::TaskGraphBuilder &builder, const Config &cfg); + // Function to initialize your collision pairs array + static madrona::InlineArray, 64> initializeCollisionPairs() { + madrona::InlineArray, 64> collisionPairs; + collisionPairs.push_back({EntityType::Pedestrian, EntityType::Pedestrian}); + collisionPairs.push_back({EntityType::Pedestrian, EntityType::Cube}); + collisionPairs.push_back({EntityType::Cyclist, EntityType::Pedestrian}); + collisionPairs.push_back({EntityType::Cyclist, EntityType::Cube}); + // TODO: Break Cube into road types for better control over collisions + return collisionPairs; + } + + + const madrona::InlineArray, 64> collisionPairs; // The constructor is called for each world during initialization. // Config is global across all worlds, while WorldInit (src/init.hpp) // can contain per-world initialization data, created in (src/mgr.cpp) From d267db9b87edc0b88297ef23aba8db3378819f98 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Wed, 13 Mar 2024 18:10:58 -0400 Subject: [PATCH 19/33] Handle collision behaviour --- src/sim.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/sim.cpp b/src/sim.cpp index 5d286c3d..6a2aa85d 100755 --- a/src/sim.cpp +++ b/src/sim.cpp @@ -229,9 +229,24 @@ inline void movementSystem(Engine &e, return; } - if (collisionEvent.hasCollided.load_relaxed() && e.data().params.collisionBehaviour == CollisionBehaviour::AgentStop) + if (collisionEvent.hasCollided.load_relaxed()) { - return; + if(e.data().params.collisionBehaviour == CollisionBehaviour::AgentStop) + return; + else if(e.data().params.collisionBehaviour == CollisionBehaviour::AgentRemoved) + { + position = consts::kPaddingPosition; + velocity.linear.x = 0; + velocity.linear.y = 0; + velocity.linear.z = fminf(velocity.linear.z, 0); + velocity.angular = Vector3::zero(); + external_force = Vector3::zero(); + external_torque = Vector3::zero(); + } + else if(e.data().params.collisionBehaviour == CollisionBehaviour::Ignore) + { + // Do nothing. + } } if (type == EntityType::Vehicle && controlledState.controlledState == ControlMode::BICYCLE) From 728585bc126f338468d3f9ca5f616c9a9cd070ee Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Wed, 13 Mar 2024 18:12:00 -0400 Subject: [PATCH 20/33] Bigger consts for tests --- src/consts.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/consts.hpp b/src/consts.hpp index 9e4dacc9..728324fd 100644 --- a/src/consts.hpp +++ b/src/consts.hpp @@ -9,7 +9,7 @@ namespace gpudrive { namespace consts { inline constexpr madrona::CountT kMaxAgentCount = 5; -inline constexpr madrona::CountT kMaxRoadEntityCount = 6000; +inline constexpr madrona::CountT kMaxRoadEntityCount = 5000; // Various world / entity size parameters inline constexpr float worldLength = 40.f; From 95834c641bf0ecc62318ef4015a8afd198857d48 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Wed, 13 Mar 2024 18:48:43 -0400 Subject: [PATCH 21/33] Refactor to merge entity types --- src/MapReader.hpp | 2 +- src/init.hpp | 86 +------------------------------------- src/json_serialization.hpp | 29 ++++++------- src/level_gen.cpp | 38 ++++++----------- src/mgr.cpp | 4 +- src/sim.hpp | 4 +- src/types.hpp | 86 ++++++++++++++++++++++++++++++++------ tests/observationTest.cpp | 14 +++---- 8 files changed, 114 insertions(+), 149 deletions(-) diff --git a/src/MapReader.hpp b/src/MapReader.hpp index 6341495a..5c7b13bf 100644 --- a/src/MapReader.hpp +++ b/src/MapReader.hpp @@ -4,7 +4,7 @@ #include #include -#include "init.hpp" +#include "types.hpp" namespace gpudrive { diff --git a/src/init.hpp b/src/init.hpp index d5eca222..38f99ae5 100755 --- a/src/init.hpp +++ b/src/init.hpp @@ -1,91 +1,10 @@ #pragma once #include -#include -#include -#include -#include - -namespace madrona::viz { -struct VizECSBridge; -} +#include "types.hpp" namespace gpudrive { - // Constants computed from train files. - constexpr size_t MAX_OBJECTS = 515; - constexpr size_t MAX_ROADS = 956; - constexpr size_t MAX_POSITIONS = 91; - constexpr size_t MAX_GEOMETRY = 1746; - - enum class MapObjectType : uint32_t - { - Vehicle, - Pedestrian, - Cyclist, - Invalid - }; - - enum class MapRoadType : uint32_t - { - RoadEdge, - RoadLine, - Lane, - CrossWalk, - SpeedBump, - StopSign, - Invalid - }; - - // Cannot use Madrona::math::Vector2 because it is not a POD type. - // Getting all zeros if using any madrona types. - struct MapVector2 - { - float x; - float y; - }; - - struct MapObject - { - MapVector2 position[MAX_POSITIONS]; - float width; - float length; - float heading[MAX_POSITIONS]; - MapVector2 velocity[MAX_POSITIONS]; - bool valid[MAX_POSITIONS]; - MapVector2 goalPosition; - MapObjectType type; - - uint32_t numPositions; - uint32_t numHeadings; - uint32_t numVelocities; - uint32_t numValid; - MapVector2 mean; - }; - - struct MapRoad - { - // std::array geometry; - MapVector2 geometry[MAX_GEOMETRY]; - MapRoadType type; - uint32_t numPoints; - MapVector2 mean; - }; - - struct Map - { - MapObject objects[MAX_OBJECTS]; - MapRoad roads[MAX_ROADS]; - - uint32_t numObjects; - uint32_t numRoads; - uint32_t numRoadSegments; - MapVector2 mean; - - // Constructor - Map() = default; - }; - struct EpisodeManager { madrona::AtomicU32 curEpisode; @@ -126,8 +45,7 @@ namespace gpudrive EpisodeManager *episodeMgr; madrona::phys::ObjectManager *rigidBodyObjMgr; const madrona::viz::VizECSBridge *vizBridge; - Map *map; - madrona::ExecMode mode; + gpudrive::Map *map; const Parameters *params; }; diff --git a/src/json_serialization.hpp b/src/json_serialization.hpp index 39e262a5..5f380ed3 100644 --- a/src/json_serialization.hpp +++ b/src/json_serialization.hpp @@ -1,6 +1,7 @@ #pragma once #include "init.hpp" +#include "types.hpp" #include #include @@ -85,13 +86,13 @@ namespace gpudrive from_json(j.at("goalPosition"), obj.goalPosition); std::string type = j.at("type"); if(type == "vehicle") - obj.type = MapObjectType::Vehicle; + obj.type = EntityType::Vehicle; else if(type == "pedestrian") - obj.type = MapObjectType::Pedestrian; + obj.type = EntityType::Pedestrian; else if(type == "cyclist") - obj.type = MapObjectType::Cyclist; + obj.type = EntityType::Cyclist; else - obj.type = MapObjectType::Invalid; + obj.type = EntityType::None; } void from_json(const nlohmann::json &j, MapRoad &road, float polylineReductionThreshold = 0.0) @@ -99,19 +100,19 @@ namespace gpudrive road.mean = {0,0}; std::string type = j.at("type"); if(type == "road_edge") - road.type = MapRoadType::RoadEdge; + road.type = EntityType::RoadEdge; else if(type == "road_line") - road.type = MapRoadType::RoadLine; + road.type = EntityType::RoadLine; else if(type == "lane") - road.type = MapRoadType::Lane; + road.type = EntityType::RoadLane; else if(type == "crosswalk") - road.type = MapRoadType::CrossWalk; + road.type = EntityType::CrossWalk; else if(type == "speed_bump") - road.type = MapRoadType::SpeedBump; + road.type = EntityType::SpeedBump; else if(type == "stop_sign") - road.type = MapRoadType::StopSign; + road.type = EntityType::StopSign; else - road.type = MapRoadType::Invalid; + road.type = EntityType::None; std::vector geometry_points_; for(const auto &point: j.at("geometry")) @@ -124,7 +125,7 @@ namespace gpudrive const int64_t num_segments = j["geometry"].size() - 1; const int64_t sample_every_n_ = 1; const int64_t num_sampled_points = (num_segments + sample_every_n_ - 1) / sample_every_n_ + 1; - if (num_segments >= 10 && (road.type == MapRoadType::Lane || road.type == MapRoadType::RoadEdge || road.type == MapRoadType::RoadLine)) + if (num_segments >= 10 && (road.type == EntityType::RoadLane || road.type == EntityType::RoadEdge || road.type == EntityType::RoadLine)) { std::vector skip(num_sampled_points, false); // This list tracks the points that are skipped int64_t k = 0; @@ -240,9 +241,9 @@ namespace gpudrive map.mean.x = ((map.mean.x * totalPoints) + (map.roads[i].mean.x * roadPoints)) / (totalPoints + roadPoints); map.mean.y = ((map.mean.y * totalPoints) + (map.roads[i].mean.y * roadPoints)) / (totalPoints + roadPoints); totalPoints += roadPoints; - if(map.roads[i].type <= MapRoadType::Lane) + if(map.roads[i].type <= EntityType::RoadLane) count_road_points += roadPoints - 1; - else if(map.roads[i].type > MapRoadType::Lane) + else if(map.roads[i].type > EntityType::RoadLane) count_road_points += 1; ++i; } diff --git a/src/level_gen.cpp b/src/level_gen.cpp index d839ef38..1a5dbbeb 100755 --- a/src/level_gen.cpp +++ b/src/level_gen.cpp @@ -54,24 +54,10 @@ static inline Entity createAgent(Engine &ctx, const MapObject &agentInit) { ctx.get(agent) = Diag3x3{.d0 = agentInit.length/2, .d1 = agentInit.width/2, .d2 = 1}; ctx.get(agent) = ObjectID{(int32_t)SimObject::Agent}; ctx.get(agent) = ResponseType::Dynamic; - if(agentInit.type == MapObjectType::Vehicle) - { - ctx.get(agent) = EntityType::Vehicle; - } - else if(agentInit.type == MapObjectType::Pedestrian) - { - ctx.get(agent) = EntityType::Pedestrian; - } - else if(agentInit.type == MapObjectType::Cyclist) - { - ctx.get(agent) = EntityType::Cyclist; - } - else - { - MADRONA_UNREACHABLE(); - } + assert(agentInit.type >= EntityType::Vehicle || agentInit.type == EntityType::None); + ctx.get(agent) = agentInit.type; ctx.get(agent)= Goal{.position = Vector2{.x = agentInit.goalPosition.x - ctx.data().mean.x, .y = agentInit.goalPosition.y - ctx.data().mean.y}}; - if(ctx.data().numControlledVehicles < ctx.data().params.maxNumControlledVehicles && agentInit.type == MapObjectType::Vehicle && agentInit.valid[0]) + if(ctx.data().numControlledVehicles < ctx.data().params.maxNumControlledVehicles && agentInit.type == EntityType::Vehicle && agentInit.valid[0]) { ctx.get(agent) = ControlledState{.controlledState = ControlMode::BICYCLE}; ctx.data().numControlledVehicles++; @@ -102,7 +88,7 @@ static inline Entity createAgent(Engine &ctx, const MapObject &agentInit) { } static Entity makeRoadEdge(Engine &ctx, const MapVector2 &p1, - const MapVector2 &p2, const MapRoadType &type) { + const MapVector2 &p2, const EntityType &type) { float x1 = p1.x; float y1 = p1.y; float x2 = p2.x; @@ -115,7 +101,7 @@ static Entity makeRoadEdge(Engine &ctx, const MapVector2 &p1, ctx.get(road_edge) = Vector3{.x = (start.x + end.x)/2, .y = (start.y + end.y)/2, .z = 1}; ctx.get(road_edge) = Quat::angleAxis(atan2(end.y - start.y, end.x - start.x), madrona::math::up); ctx.get(road_edge) = Diag3x3{.d0 = distance/2, .d1 = 0.1, .d2 = 0.1}; - ctx.get(road_edge) = EntityType::Cube; + ctx.get(road_edge) = type; ctx.get(road_edge) = ObjectID{(int32_t)SimObject::Cube}; registerRigidBodyEntity(ctx, road_edge, SimObject::Cube); ctx.get(road_edge) = ResponseType::Static; @@ -185,11 +171,11 @@ static Entity makeSpeedBump(Engine &ctx, const MapVector2 &p1, const MapVector2 ctx.get(speed_bump) = Vector3{.x = (x1 + x2 + x3 + x4)/4 - ctx.data().mean.x, .y = (y1 + y2 + y3 + y4)/4 - ctx.data().mean.y, .z = 1}; ctx.get(speed_bump) = Quat::angleAxis(angle, madrona::math::up); ctx.get(speed_bump) = Diag3x3{.d0 = lengths[maxLength_i]/2, .d1 = lengths[minLength_i]/2, .d2 = 0.1}; - ctx.get(speed_bump) = EntityType::Cube; + ctx.get(speed_bump) = EntityType::SpeedBump; ctx.get(speed_bump) = ObjectID{(int32_t)SimObject::SpeedBump}; registerRigidBodyEntity(ctx, speed_bump, SimObject::SpeedBump); ctx.get(speed_bump) = ResponseType::Static; - ctx.get(speed_bump) = MapObservation{.position = Vector2{.x = (x1 + x2 + x3 + x4)/4 - ctx.data().mean.x, .y = (y1 + y2 + y3 + y4)/4 - ctx.data().mean.y}, .heading = angle, .type = (float)MapRoadType::SpeedBump}; + ctx.get(speed_bump) = MapObservation{.position = Vector2{.x = (x1 + x2 + x3 + x4)/4 - ctx.data().mean.x, .y = (y1 + y2 + y3 + y4)/4 - ctx.data().mean.y}, .heading = angle, .type = (float)EntityType::SpeedBump}; return speed_bump; } @@ -201,16 +187,16 @@ static Entity makeStopSign(Engine &ctx, const MapVector2 &p1) { ctx.get(stop_sign) = Vector3{.x = x1 - ctx.data().mean.x, .y = y1 - ctx.data().mean.y, .z = 0.5}; ctx.get(stop_sign) = Quat::angleAxis(0, madrona::math::up); ctx.get(stop_sign) = Diag3x3{.d0 = 0.2, .d1 = 0.2, .d2 = 0.5}; - ctx.get(stop_sign) = EntityType::Cube; + ctx.get(stop_sign) = EntityType::StopSign; ctx.get(stop_sign) = ObjectID{(int32_t)SimObject::StopSign}; registerRigidBodyEntity(ctx, stop_sign, SimObject::StopSign); ctx.get(stop_sign) = ResponseType::Static; - ctx.get(stop_sign) = MapObservation{.position = Vector2{.x = x1 - ctx.data().mean.x, .y = y1 - ctx.data().mean.y}, .heading = 0, .type = (float)MapRoadType::StopSign}; + ctx.get(stop_sign) = MapObservation{.position = Vector2{.x = x1 - ctx.data().mean.x, .y = y1 - ctx.data().mean.y}, .heading = 0, .type = (float)EntityType::StopSign}; return stop_sign; } static inline void createRoadEntities(Engine &ctx, const MapRoad &roadInit, CountT &idx) { - if (roadInit.type == MapRoadType::RoadEdge || roadInit.type == MapRoadType::RoadLine || roadInit.type == MapRoadType::Lane) + if (roadInit.type == EntityType::RoadEdge || roadInit.type == EntityType::RoadLine || roadInit.type == EntityType::RoadLane) { size_t numPoints = roadInit.numPoints; for(size_t j = 1; j <= numPoints - 1; j++) @@ -219,13 +205,13 @@ static inline void createRoadEntities(Engine &ctx, const MapRoad &roadInit, Coun return; ctx.data().roads[idx++] = makeRoadEdge(ctx, roadInit.geometry[j-1], roadInit.geometry[j], roadInit.type); } - } else if (roadInit.type == MapRoadType::SpeedBump) { + } else if (roadInit.type == EntityType::SpeedBump) { assert(roadInit.numPoints >= 4); // TODO: Speed Bump are not guranteed to have 4 points. Need to handle this case. if(idx >= ctx.data().MaxRoadEntityCount) return; ctx.data().roads[idx++] = makeSpeedBump(ctx, roadInit.geometry[0], roadInit.geometry[1], roadInit.geometry[2], roadInit.geometry[3]); - } else if (roadInit.type == MapRoadType::StopSign) { + } else if (roadInit.type == EntityType::StopSign) { assert(roadInit.numPoints >= 1); // TODO: Stop Sign are not guranteed to have 1 point. Need to handle this case. if(idx >= ctx.data().MaxRoadEntityCount) diff --git a/src/mgr.cpp b/src/mgr.cpp index 3e8a6417..eec350f7 100755 --- a/src/mgr.cpp +++ b/src/mgr.cpp @@ -295,7 +295,7 @@ Manager::Impl * Manager::Impl::init( { auto [map_, mapCounts] = MapReader::parseAndWriteOut(mapFile.path(), mgr_cfg.execMode, mgr_cfg.params.polylineReductionThreshold); world_inits[worldIdx++] = WorldInit{episode_mgr, phys_obj_mgr, - viz_bridge, map_, mgr_cfg.execMode, paramsDevicePtr}; + viz_bridge, map_, paramsDevicePtr}; sim_cfg.kMaxAgentCount = std::max(mapCounts.first, sim_cfg.kMaxAgentCount); sim_cfg.kMaxRoadEntityCount = std::max(mapCounts.second, sim_cfg.kMaxRoadEntityCount); } @@ -365,7 +365,7 @@ Manager::Impl * Manager::Impl::init( { auto [map_, mapCounts] = MapReader::parseAndWriteOut(mapFile.path(), mgr_cfg.execMode, mgr_cfg.params.polylineReductionThreshold); world_inits[worldIdx++] = WorldInit{episode_mgr, phys_obj_mgr, - viz_bridge, map_, mgr_cfg.execMode, &(mgr_cfg.params)}; + viz_bridge, map_, &(mgr_cfg.params)}; sim_cfg.kMaxAgentCount = std::max(mapCounts.first, sim_cfg.kMaxAgentCount); sim_cfg.kMaxRoadEntityCount = std::max(mapCounts.second, sim_cfg.kMaxRoadEntityCount); } diff --git a/src/sim.hpp b/src/sim.hpp index 563c96e6..971b2b01 100755 --- a/src/sim.hpp +++ b/src/sim.hpp @@ -72,9 +72,9 @@ struct Sim : public madrona::WorldBase { static madrona::InlineArray, 64> initializeCollisionPairs() { madrona::InlineArray, 64> collisionPairs; collisionPairs.push_back({EntityType::Pedestrian, EntityType::Pedestrian}); - collisionPairs.push_back({EntityType::Pedestrian, EntityType::Cube}); + collisionPairs.push_back({EntityType::Pedestrian, EntityType::RoadEdge}); collisionPairs.push_back({EntityType::Cyclist, EntityType::Pedestrian}); - collisionPairs.push_back({EntityType::Cyclist, EntityType::Cube}); + collisionPairs.push_back({EntityType::Cyclist, EntityType::RoadEdge}); // TODO: Break Cube into road types for better control over collisions return collisionPairs; } diff --git a/src/types.hpp b/src/types.hpp index 1400bc4a..d0958cf6 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -20,6 +20,79 @@ using madrona::phys::ResponseType; using madrona::phys::ExternalForce; using madrona::phys::ExternalTorque; +// This enum is used to track the type of each entity +// The order of the enum is important and should not be changed +// The order is {Road types that can be reduced, Road types that cannot be reduced, agent types, other types} +enum class EntityType : uint32_t { + None, + RoadEdge, + RoadLine, + RoadLane, + CrossWalk, + SpeedBump, + StopSign, + Vehicle, + Pedestrian, + Cyclist, + Padding, + NumTypes, +}; + +// Constants computed from train files. +constexpr size_t MAX_OBJECTS = 515; +constexpr size_t MAX_ROADS = 956; +constexpr size_t MAX_POSITIONS = 91; +constexpr size_t MAX_GEOMETRY = 1746; + +// Cannot use Madrona::math::Vector2 because it is not a POD type. +// Getting all zeros if using any madrona types. +struct MapVector2 +{ + float x; + float y; +}; + +struct MapObject +{ + MapVector2 position[MAX_POSITIONS]; + float width; + float length; + float heading[MAX_POSITIONS]; + MapVector2 velocity[MAX_POSITIONS]; + bool valid[MAX_POSITIONS]; + MapVector2 goalPosition; + EntityType type; + + uint32_t numPositions; + uint32_t numHeadings; + uint32_t numVelocities; + uint32_t numValid; + MapVector2 mean; +}; + +struct MapRoad +{ + // std::array geometry; + MapVector2 geometry[MAX_GEOMETRY]; + EntityType type; + uint32_t numPoints; + MapVector2 mean; +}; + +struct Map +{ + MapObject objects[MAX_OBJECTS]; + MapRoad roads[MAX_ROADS]; + + uint32_t numObjects; + uint32_t numRoads; + uint32_t numRoadSegments; + MapVector2 mean; + + // Constructor + Map() = default; +}; + struct BicycleModel { madrona::math::Vector2 position; float heading; @@ -154,19 +227,6 @@ struct OtherAgents { madrona::Entity e[consts::kMaxAgentCount - 1]; }; -// This enum is used to track the type of each entity for the purposes of -// classifying the objects hit by each lidar sample. -enum class EntityType : uint32_t { - None, - Button, - Cube, - Vehicle, - Pedestrian, - Cyclist, - Padding, - NumTypes, -}; - struct Trajectory { madrona::math::Vector2 positions[consts::kTrajectoryLength]; madrona::math::Vector2 velocities[consts::kTrajectoryLength]; diff --git a/tests/observationTest.cpp b/tests/observationTest.cpp index 8713a6f5..39d978db 100755 --- a/tests/observationTest.cpp +++ b/tests/observationTest.cpp @@ -59,31 +59,31 @@ class ObservationsTest : public ::testing::Test { if(obj["type"] == "road_edge") { - roadTypes.push_back(0); + roadTypes.push_back((float)gpudrive::EntityType::RoadEdge); } else if(obj["type"] == "road_line") { - roadTypes.push_back(1); + roadTypes.push_back((float)gpudrive::EntityType::RoadLine); } else if(obj["type"] == "lane") { - roadTypes.push_back(2); + roadTypes.push_back((float)gpudrive::EntityType::RoadLane); } else if(obj["type"] == "crosswalk") { - roadTypes.push_back(3); + roadTypes.push_back((float)gpudrive::EntityType::CrossWalk); } else if(obj["type"] == "speed_bump") { - roadTypes.push_back(4); + roadTypes.push_back((float)gpudrive::EntityType::SpeedBump); } else if(obj["type"] == "stop_sign") { - roadTypes.push_back(5); + roadTypes.push_back((float)gpudrive::EntityType::StopSign); } else if(obj["type"] == "invalid") { - roadTypes.push_back(6); + roadTypes.push_back(0); } } } From 019729d47a36f74fde904ba8fca704cc03049e60 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Wed, 13 Mar 2024 18:53:26 -0400 Subject: [PATCH 22/33] Remove comment --- src/init.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/init.hpp b/src/init.hpp index 38f99ae5..3d4e0a3b 100755 --- a/src/init.hpp +++ b/src/init.hpp @@ -20,7 +20,7 @@ namespace gpudrive enum class CollisionBehaviour: uint32_t { AgentStop, - AgentRemoved, // Unimplemented + AgentRemoved, Ignore }; From 17a60129783978e64d5c6ec9dc2a13f7bd61d760 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Wed, 13 Mar 2024 19:40:38 -0400 Subject: [PATCH 23/33] Add bindings --- src/bindings.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bindings.cpp b/src/bindings.cpp index 12f4d9ba..1a55290a 100644 --- a/src/bindings.cpp +++ b/src/bindings.cpp @@ -36,7 +36,9 @@ namespace gpudrive .def(nb::init<>()) // Default constructor .def_rw("polylineReductionThreshold", &Parameters::polylineReductionThreshold) .def_rw("observationRadius", &Parameters::observationRadius) - .def_rw("rewardParams", &Parameters::rewardParams); + .def_rw("rewardParams", &Parameters::rewardParams) + .def_rw("collisionBehaviour", &Parameters::collisionBehaviour) + .def_rw("maxNumControlledVehicles", &Parameters::maxNumControlledVehicles); // Define CollisionBehaviour enum nb::enum_(m, "CollisionBehaviour") From 688adb902b6dff65dce8439c7fcbf701998841e2 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Wed, 13 Mar 2024 23:01:49 -0400 Subject: [PATCH 24/33] Init Benchmarking machinery --- build.py | 4 +-- config.py | 31 +++++++++++++++++ config.yml | 17 +++++++++ poetry.lock | 62 ++++++++++++++++++++++++++++++++- pyproject.toml | 7 +++- scripts/benchmark.py | 27 +++++++++++++++ scripts/sim_utils/create.py | 38 ++++++++++++++++++++ scripts/test.py | 4 +-- src/bindings.cpp | 10 +++++- src/consts.hpp | 4 +-- src/headless.cpp | 5 +-- src/init.hpp | 9 +++++ src/mgr.cpp | 69 ++++++++++++++++++++++++++++++++++--- 13 files changed, 271 insertions(+), 16 deletions(-) create mode 100644 config.py create mode 100644 config.yml create mode 100644 scripts/benchmark.py create mode 100644 scripts/sim_utils/create.py diff --git a/build.py b/build.py index 98bc022f..0490ba93 100644 --- a/build.py +++ b/build.py @@ -6,7 +6,7 @@ logging.basicConfig(level=logging.INFO) -def main(): +def build(): # Cloning the repository, although typically you would not do this in the build step # as the code should already be present. Including it just for completeness. subprocess.check_call(['git', 'submodule', 'update', '--init', '--recursive', '--force']) @@ -25,4 +25,4 @@ def main(): if __name__ == '__main__': logging.info("Building the C++ code and installing the Python package") - main() \ No newline at end of file + build() \ No newline at end of file diff --git a/config.py b/config.py new file mode 100644 index 00000000..74324d84 --- /dev/null +++ b/config.py @@ -0,0 +1,31 @@ +import re +import os + +from scripts.sim_utils.create import SimCreator +import build + +def update_constants(filepath, new_max_agent_count, new_max_road_entity_count): + with open(filepath, 'r') as file: + content = file.read() + + content = re.sub( + r"(inline constexpr madrona::CountT kMaxAgentCount = )\d+;", + r"\g<1>{};".format(new_max_agent_count), + content) + + content = re.sub( + r"(inline constexpr madrona::CountT kMaxRoadEntityCount = )\d+;", + r"\g<1>{};".format(new_max_road_entity_count), + content) + + # Write the updated content back to the file + with open(filepath, 'w') as file: + file.write(content) + + build.build() + +def main(): + print("Hello World!") + +if __name__ == "__main__": + update_constants("src/consts.hpp", 200, 2000) \ No newline at end of file diff --git a/config.yml b/config.yml new file mode 100644 index 00000000..262d0f1d --- /dev/null +++ b/config.yml @@ -0,0 +1,17 @@ +reward_params: + rewardType: DistanceBased + distanceToGoalThreshold: 1.0 + distanceToExpertThreshold: 1.0 + +parameters: + polylineReductionThreshold: 0.5 + observationRadius: 10.0 + datasetInitOptions: FirstN + rewardParams: reward_params + +sim_manager: + exec_mode: CPU + gpu_id: 0 + num_worlds: 1 + auto_reset: true + json_path: /home/aarav/gpudrive/valid_nocturne diff --git a/poetry.lock b/poetry.lock index fcd473e4..600108d4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -358,6 +358,66 @@ files = [ {file = "nvidia_nvtx_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:65f4d98982b31b60026e0e6de73fbdfc09d08a96f4656dd3665ca616a11e1e82"}, ] +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + [[package]] name = "sympy" version = "1.12" @@ -467,4 +527,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "97b2806066f6e80bd92d4441827c4f8143e924af4bcddfce52ea1d84162b42f3" +content-hash = "7194030eae82d61f2ea53c977a29252bb3d9c27bbb0aa6b36864904d5ed7a418" diff --git a/pyproject.toml b/pyproject.toml index 2f91e255..f218ceba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,10 +18,14 @@ path = "train_src/gpudrive_learn" [tool.poetry.build] script = "build.py" +[tool.poetry.scripts] +config = "config:main" + [tool.poetry.dependencies] python = "^3.11" torch = "^2.2.1" numpy = "^1.26.4" +pyyaml = "^6.0.1" [tool.poetry] name = "gpudrive" @@ -30,5 +34,6 @@ description = "" authors = ["Sébastien Eustace "] readme = "README.md" packages = [ - {include = "gpudrive.cpython-311-x86_64-linux-gnu.so", from = "build", to = "gpudrive"} + {include = "gpudrive.cpython-311-x86_64-linux-gnu.so", from = "build", to = "gpudrive"}, + {include = "gpudrive_learn", from = "train_src", to = "gpudrive_learn"}, ] \ No newline at end of file diff --git a/scripts/benchmark.py b/scripts/benchmark.py new file mode 100644 index 00000000..de922a84 --- /dev/null +++ b/scripts/benchmark.py @@ -0,0 +1,27 @@ +import gpudrive +from sim_utils.create import SimCreator +# Create an instance of RewardParams +reward_params = gpudrive.RewardParams() +reward_params.rewardType = gpudrive.RewardType.DistanceBased # Or any other value from the enum +reward_params.distanceToGoalThreshold = 1.0 # Set appropriate values +reward_params.distanceToExpertThreshold = 1.0 # Set appropriate values + +# Create an instance of Parameters +params = gpudrive.Parameters() +params.polylineReductionThreshold = 0.5 # Set appropriate value +params.observationRadius = 10.0 # Set appropriate value +params.datasetInitOptions = gpudrive.DatasetInitOptions.FirstN +params.rewardParams = reward_params # Set the rewardParams attribute to the instance created above + +# Now use the 'params' instance when creating SimManager +sim = gpudrive.SimManager( + exec_mode=gpudrive.madrona.ExecMode.CPU, + gpu_id=0, + num_worlds=1, + auto_reset=True, + json_path="/home/aarav/gpudrive/valid_nocturne", + params=params +) + +print(sim.controlled_state_tensor().to_torch().shape) + diff --git a/scripts/sim_utils/create.py b/scripts/sim_utils/create.py new file mode 100644 index 00000000..ae7578bf --- /dev/null +++ b/scripts/sim_utils/create.py @@ -0,0 +1,38 @@ +import yaml +import gpudrive + +def SimCreator(config_path: str) -> gpudrive.SimManager: + # Load the YAML config file + with open(config_path, 'r') as file: + config = yaml.safe_load(file) + + # Initialize RewardParams + reward_params_config = config['reward_params'] + reward_params = gpudrive.RewardParams() + reward_params.rewardType = getattr(gpudrive.RewardType, reward_params_config['rewardType']) + reward_params.distanceToGoalThreshold = reward_params_config['distanceToGoalThreshold'] + reward_params.distanceToExpertThreshold = reward_params_config['distanceToExpertThreshold'] + + # Initialize Parameters + params_config = config['parameters'] + params = gpudrive.Parameters() + params.polylineReductionThreshold = params_config['polylineReductionThreshold'] + params.observationRadius = params_config['observationRadius'] + params.datasetInitOptions = getattr(gpudrive.DatasetInitOptions, params_config['datasetInitOptions']) + params.rewardParams = reward_params + + # Initialize SimManager with parameters from the config + sim_manager_config = config['sim_manager'] + sim = gpudrive.SimManager( + exec_mode=getattr(gpudrive.madrona.ExecMode, sim_manager_config['exec_mode']), + gpu_id=sim_manager_config['gpu_id'], + num_worlds=sim_manager_config['num_worlds'], + auto_reset=sim_manager_config['auto_reset'], + json_path=sim_manager_config['json_path'], + params=params + ) + return sim + +if __name__ == "__main__": + sim = SimCreator("/home/aarav/gpudrive/config.yml") + print(sim.controlled_state_tensor().to_torch().shape) diff --git a/scripts/test.py b/scripts/test.py index 53ab61d2..f42e5781 100644 --- a/scripts/test.py +++ b/scripts/test.py @@ -15,11 +15,11 @@ # Now use the 'params' instance when creating SimManager sim = gpudrive.SimManager( - exec_mode=gpudrive.madrona.ExecMode.CUDA, + exec_mode=gpudrive.madrona.ExecMode.CPU, gpu_id=0, num_worlds=1, auto_reset=True, - json_path="tests/test.json", + json_path="build/tests/testJsons", params=params ) diff --git a/src/bindings.cpp b/src/bindings.cpp index 94ee037d..4da2422a 100644 --- a/src/bindings.cpp +++ b/src/bindings.cpp @@ -18,6 +18,12 @@ namespace gpudrive // like madrona::py::Tensor and madrona::py::PyExecMode. madrona::py::setupMadronaSubmodule(m); + nb::enum_(m, "DatasetInitOptions") + .value("FirstN", DatasetInitOptions::FirstN) + .value("RandomN", DatasetInitOptions::RandomN) + .value("PadN", DatasetInitOptions::PadN) + .value("ExactN", DatasetInitOptions::ExactN); + // Define RewardType enum nb::enum_(m, "RewardType") .value("DistanceBased", RewardType::DistanceBased) @@ -36,6 +42,7 @@ namespace gpudrive .def(nb::init<>()) // Default constructor .def_rw("polylineReductionThreshold", &Parameters::polylineReductionThreshold) .def_rw("observationRadius", &Parameters::observationRadius) + .def_rw("datasetInitOptions", &Parameters::datasetInitOptions) .def_rw("rewardParams", &Parameters::rewardParams); @@ -68,7 +75,8 @@ namespace gpudrive .def("partner_observations_tensor", &Manager::partnerObservationsTensor) .def("lidar_tensor", &Manager::lidarTensor) .def("steps_remaining_tensor", &Manager::stepsRemainingTensor) - .def("shape_tensor", &Manager::shapeTensor); + .def("shape_tensor", &Manager::shapeTensor) + .def("controlled_state_tensor", &Manager::controlledStateTensor); } } diff --git a/src/consts.hpp b/src/consts.hpp index e5e0e5ea..42c2609f 100644 --- a/src/consts.hpp +++ b/src/consts.hpp @@ -8,8 +8,8 @@ namespace gpudrive { namespace consts { -inline constexpr madrona::CountT kMaxAgentCount = 100; -inline constexpr madrona::CountT kMaxRoadEntityCount = 500; +inline constexpr madrona::CountT kMaxAgentCount = 200; +inline constexpr madrona::CountT kMaxRoadEntityCount = 2000; // Various world / entity size parameters inline constexpr float worldLength = 40.f; diff --git a/src/headless.cpp b/src/headless.cpp index 5eb36762..18095ec5 100755 --- a/src/headless.cpp +++ b/src/headless.cpp @@ -62,7 +62,7 @@ int main(int argc, char *argv[]) .gpuID = 0, .numWorlds = (uint32_t)num_worlds, .autoReset = false, - .jsonPath = "/home/samk/gpudrive/maps.small", + .jsonPath = "/home/aarav/gpudrive/valid_nocturne", .params = { .polylineReductionThreshold = 1.0, .observationRadius = 100.0, @@ -70,7 +70,8 @@ int main(int argc, char *argv[]) .rewardType = RewardType::DistanceBased, .distanceToGoalThreshold = 0.5, .distanceToExpertThreshold = 0.5 - } + }, + .datasetInitOptions = DatasetInitOptions::FirstN } }); diff --git a/src/init.hpp b/src/init.hpp index d69277de..6659d53d 100755 --- a/src/init.hpp +++ b/src/init.hpp @@ -91,6 +91,14 @@ namespace gpudrive madrona::AtomicU32 curEpisode; }; + enum class DatasetInitOptions : uint32_t + { + FirstN, + RandomN, + PadN, // Pad the worlds by repeating the first world. + ExactN, // Will fail if N != NumWorlds + }; + enum class RewardType : uint32_t { DistanceBased, // negative distance to goal @@ -110,6 +118,7 @@ namespace gpudrive float polylineReductionThreshold; float observationRadius; RewardParams rewardParams; + DatasetInitOptions datasetInitOptions; uint32_t maxNumControlledVehicles = 10000; // Arbitrary high number to by default control all vehicles }; diff --git a/src/mgr.cpp b/src/mgr.cpp index a9186d2b..fb89e134 100755 --- a/src/mgr.cpp +++ b/src/mgr.cpp @@ -8,6 +8,8 @@ #include #include +#include + #include #include #include @@ -16,6 +18,8 @@ #include #include #include +#include + #ifdef MADRONA_CUDA_SUPPORT #include @@ -255,6 +259,59 @@ static void loadPhysicsObjects(PhysicsLoader &loader) free(rigid_body_data); } +static std::vector getMapFiles(const Manager::Config &cfg) +{ + std::filesystem::path path(cfg.jsonPath); + auto validFilesJsonPath = path / "valid_files.json"; + assert(std::filesystem::exists(validFilesJsonPath)); + // check if validFiles.json exists + + std::ifstream validFilesJson(validFilesJsonPath); + assert(validFilesJson.good()); + + nlohmann::json validFiles; + validFilesJson >> validFiles; + + std::vector mapFiles; + for (auto& [key, value] : validFiles.items()) { + std::filesystem::path fullPath = path / key; + mapFiles.emplace_back(fullPath.string()); + } + assert(mapFiles.size() != 0); + + if(cfg.params.datasetInitOptions == DatasetInitOptions::FirstN) + { + assert(cfg.numWorlds <= mapFiles.size()); + mapFiles.resize(cfg.numWorlds); + } + else if(cfg.params.datasetInitOptions == DatasetInitOptions::RandomN) + { + assert(cfg.numWorlds <= mapFiles.size()); + std::random_device rd; + std::mt19937 g(rd()); + std::shuffle(mapFiles.begin(), mapFiles.end(), g); + mapFiles.resize(cfg.numWorlds); + } + else if(cfg.params.datasetInitOptions == DatasetInitOptions::PadN) + { + assert(cfg.numWorlds >= mapFiles.size()); + for(int i = 0; i < cfg.numWorlds; i++) + { + mapFiles.push_back(mapFiles[0]); + } + } + else if(cfg.params.datasetInitOptions == DatasetInitOptions::ExactN) + { + // Do nothing + } + else + { + FATAL("Invalid datasetInitOptions"); + } + + return mapFiles; +} + Manager::Impl * Manager::Impl::init( const Manager::Config &mgr_cfg, const viz::VizECSBridge *viz_bridge) @@ -266,6 +323,8 @@ Manager::Impl * Manager::Impl::init( 0 // kMaxRoadEntityCount }; + std::vector mapFiles = getMapFiles(mgr_cfg); + switch (mgr_cfg.execMode) { case ExecMode::CUDA: { #ifdef MADRONA_CUDA_SUPPORT @@ -280,21 +339,21 @@ Manager::Impl * Manager::Impl::init( HeapArray world_inits(mgr_cfg.numWorlds); - Parameters* paramsDevicePtr = (Parameters*)cu::allocGPU(sizeof(Parameters)); REQ_CUDA(cudaMemcpy(paramsDevicePtr, &(mgr_cfg.params), sizeof(Parameters), cudaMemcpyHostToDevice)); int64_t worldIdx{0}; - for (auto const &mapFile : std::filesystem::directory_iterator(mgr_cfg.jsonPath)) + for (auto const &mapFile : mapFiles) { - auto [map_, mapCounts] = MapReader::parseAndWriteOut(mapFile.path(), mgr_cfg.execMode, mgr_cfg.params.polylineReductionThreshold); + auto [map_, mapCounts] = MapReader::parseAndWriteOut(mapFile, mgr_cfg.execMode, mgr_cfg.params.polylineReductionThreshold); world_inits[worldIdx++] = WorldInit{episode_mgr, phys_obj_mgr, viz_bridge, map_, mgr_cfg.execMode, paramsDevicePtr}; sim_cfg.kMaxAgentCount = std::max(mapCounts.first, sim_cfg.kMaxAgentCount); sim_cfg.kMaxRoadEntityCount = std::max(mapCounts.second, sim_cfg.kMaxRoadEntityCount); } + assert(worldIdx == static_cast(mgr_cfg.numWorlds)); // Bounds on the maxagent and maxroadentity counts. assert(sim_cfg.kMaxAgentCount <= consts::kMaxAgentCount); @@ -356,9 +415,9 @@ Manager::Impl * Manager::Impl::init( int64_t worldIdx{0}; - for (auto const &mapFile : std::filesystem::directory_iterator(mgr_cfg.jsonPath)) + for (auto const &mapFile : mapFiles) { - auto [map_, mapCounts] = MapReader::parseAndWriteOut(mapFile.path(), mgr_cfg.execMode, mgr_cfg.params.polylineReductionThreshold); + auto [map_, mapCounts] = MapReader::parseAndWriteOut(mapFile, mgr_cfg.execMode, mgr_cfg.params.polylineReductionThreshold); world_inits[worldIdx++] = WorldInit{episode_mgr, phys_obj_mgr, viz_bridge, map_, mgr_cfg.execMode, &(mgr_cfg.params)}; sim_cfg.kMaxAgentCount = std::max(mapCounts.first, sim_cfg.kMaxAgentCount); From e00808cd73b03c53c689fd514c872885ef3bf966 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Thu, 14 Mar 2024 13:59:16 -0400 Subject: [PATCH 25/33] Wire config to get constants --- config.py | 13 +++++++++++-- config.yml | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/config.py b/config.py index 74324d84..663b9cd7 100644 --- a/config.py +++ b/config.py @@ -1,9 +1,17 @@ import re import os - +import yaml from scripts.sim_utils.create import SimCreator import build + +def get_constants(): + fullpath = os.path.join(os.path.dirname(__file__), "config.yml") + sim = SimCreator(fullpath) + consts = sim.shape_tensor().to_torch().flatten().tolist() + print(consts) + return consts + def update_constants(filepath, new_max_agent_count, new_max_road_entity_count): with open(filepath, 'r') as file: content = file.read() @@ -25,7 +33,8 @@ def update_constants(filepath, new_max_agent_count, new_max_road_entity_count): build.build() def main(): - print("Hello World!") + new_max_agent_count, new_max_road_entity_count = get_constants() + update_constants("src/consts.hpp", new_max_agent_count, new_max_road_entity_count+1) if __name__ == "__main__": update_constants("src/consts.hpp", 200, 2000) \ No newline at end of file diff --git a/config.yml b/config.yml index 262d0f1d..b09e81d1 100644 --- a/config.yml +++ b/config.yml @@ -4,7 +4,7 @@ reward_params: distanceToExpertThreshold: 1.0 parameters: - polylineReductionThreshold: 0.5 + polylineReductionThreshold: 1.0 observationRadius: 10.0 datasetInitOptions: FirstN rewardParams: reward_params From 020a7ec696402ed5b5be170031cc56aa3060ca2c Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Thu, 14 Mar 2024 17:53:12 -0400 Subject: [PATCH 26/33] Add crosswalk support --- src/level_gen.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/level_gen.cpp b/src/level_gen.cpp index 1a5dbbeb..21a6ba23 100755 --- a/src/level_gen.cpp +++ b/src/level_gen.cpp @@ -113,8 +113,8 @@ float calculateDistance(float x1, float y1, float x2, float y2) { return sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2)); } -static Entity makeSpeedBump(Engine &ctx, const MapVector2 &p1, const MapVector2 &p2, const MapVector2 &p3, - const MapVector2 &p4) { +static Entity makeCube(Engine &ctx, const MapVector2 &p1, const MapVector2 &p2, const MapVector2 &p3, + const MapVector2 &p4, const EntityType &type) { float x1 = p1.x; float y1 = p1.y; float x2 = p2.x; @@ -171,11 +171,11 @@ static Entity makeSpeedBump(Engine &ctx, const MapVector2 &p1, const MapVector2 ctx.get(speed_bump) = Vector3{.x = (x1 + x2 + x3 + x4)/4 - ctx.data().mean.x, .y = (y1 + y2 + y3 + y4)/4 - ctx.data().mean.y, .z = 1}; ctx.get(speed_bump) = Quat::angleAxis(angle, madrona::math::up); ctx.get(speed_bump) = Diag3x3{.d0 = lengths[maxLength_i]/2, .d1 = lengths[minLength_i]/2, .d2 = 0.1}; - ctx.get(speed_bump) = EntityType::SpeedBump; + ctx.get(speed_bump) = type; ctx.get(speed_bump) = ObjectID{(int32_t)SimObject::SpeedBump}; registerRigidBodyEntity(ctx, speed_bump, SimObject::SpeedBump); ctx.get(speed_bump) = ResponseType::Static; - ctx.get(speed_bump) = MapObservation{.position = Vector2{.x = (x1 + x2 + x3 + x4)/4 - ctx.data().mean.x, .y = (y1 + y2 + y3 + y4)/4 - ctx.data().mean.y}, .heading = angle, .type = (float)EntityType::SpeedBump}; + ctx.get(speed_bump) = MapObservation{.position = Vector2{.x = (x1 + x2 + x3 + x4)/4 - ctx.data().mean.x, .y = (y1 + y2 + y3 + y4)/4 - ctx.data().mean.y}, .heading = angle, .type = (float)type}; return speed_bump; } @@ -205,12 +205,12 @@ static inline void createRoadEntities(Engine &ctx, const MapRoad &roadInit, Coun return; ctx.data().roads[idx++] = makeRoadEdge(ctx, roadInit.geometry[j-1], roadInit.geometry[j], roadInit.type); } - } else if (roadInit.type == EntityType::SpeedBump) { + } else if (roadInit.type == EntityType::SpeedBump || roadInit.type == EntityType::CrossWalk) { assert(roadInit.numPoints >= 4); // TODO: Speed Bump are not guranteed to have 4 points. Need to handle this case. if(idx >= ctx.data().MaxRoadEntityCount) return; - ctx.data().roads[idx++] = makeSpeedBump(ctx, roadInit.geometry[0], roadInit.geometry[1], roadInit.geometry[2], roadInit.geometry[3]); + ctx.data().roads[idx++] = makeCube(ctx, roadInit.geometry[0], roadInit.geometry[1], roadInit.geometry[2], roadInit.geometry[3], roadInit.type); } else if (roadInit.type == EntityType::StopSign) { assert(roadInit.numPoints >= 1); // TODO: Stop Sign are not guranteed to have 1 point. Need to handle this case. From 98b4b7a5288909da79c938fb533937634d81c43c Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Thu, 14 Mar 2024 18:13:33 -0400 Subject: [PATCH 27/33] Fix tests --- tests/observationTest.cpp | 13 ++++++++++++- tests/test_utils.cpp | 4 ---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/tests/observationTest.cpp b/tests/observationTest.cpp index 39d978db..0b735f6d 100755 --- a/tests/observationTest.cpp +++ b/tests/observationTest.cpp @@ -100,14 +100,25 @@ TEST_F(ObservationsTest, TestObservations) { float roadType = roadTypes[i]; for(int64_t j = 0; j < roadGeom.size() - 1; j++) { - if(roadType > 2) + if(roadType > (float)gpudrive::EntityType::RoadLane && roadType < (float)gpudrive::EntityType::StopSign) { float x = (roadGeom[j].first + roadGeom[j+1].first + roadGeom[j+2].first + roadGeom[j+3].first)/4 - mean.first; float y = (roadGeom[j].second + roadGeom[j+1].second + roadGeom[j+2].second + roadGeom[j+3].second)/4 - mean.second; ASSERT_NEAR(flat_obs[idx], x, test_utils::EPSILON); ASSERT_NEAR(flat_obs[idx+1], y, test_utils::EPSILON); + ASSERT_EQ(flat_obs[idx+3], roadType); + idx += 4; + break; + } + else if(roadType == (float)gpudrive::EntityType::StopSign) + { + float x = roadGeom[j].first - mean.first; + float y = roadGeom[j].second - mean.second; + ASSERT_NEAR(flat_obs[idx], x, test_utils::EPSILON); + ASSERT_NEAR(flat_obs[idx+1], y, test_utils::EPSILON); + ASSERT_EQ(flat_obs[idx+3], roadType); idx += 4; break; } diff --git a/tests/test_utils.cpp b/tests/test_utils.cpp index 60e19f38..519d10ce 100644 --- a/tests/test_utils.cpp +++ b/tests/test_utils.cpp @@ -29,10 +29,6 @@ namespace test_utils int64_t numEntities = 0; for (const auto &obj : rawJson["objects"]) { - if (obj["type"] != "vehicle") - { - continue; - } for (const auto &pos : obj["position"]) { numEntities++; From 74ccf6588cfed175f60ae2661defafd1cf02eef9 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Thu, 14 Mar 2024 18:28:33 -0400 Subject: [PATCH 28/33] Add more collision scenarios --- src/sim.hpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/sim.hpp b/src/sim.hpp index 971b2b01..b02aa7a5 100755 --- a/src/sim.hpp +++ b/src/sim.hpp @@ -73,8 +73,24 @@ struct Sim : public madrona::WorldBase { madrona::InlineArray, 64> collisionPairs; collisionPairs.push_back({EntityType::Pedestrian, EntityType::Pedestrian}); collisionPairs.push_back({EntityType::Pedestrian, EntityType::RoadEdge}); + collisionPairs.push_back({EntityType::Pedestrian, EntityType::Cyclist}); + collisionPairs.push_back({EntityType::Pedestrian, EntityType::RoadLine}); + collisionPairs.push_back({EntityType::Pedestrian, EntityType::RoadLane}); + collisionPairs.push_back({EntityType::Pedestrian, EntityType::CrossWalk}); + collisionPairs.push_back({EntityType::Pedestrian, EntityType::SpeedBump}); + collisionPairs.push_back({EntityType::Pedestrian, EntityType::StopSign}); collisionPairs.push_back({EntityType::Cyclist, EntityType::Pedestrian}); collisionPairs.push_back({EntityType::Cyclist, EntityType::RoadEdge}); + collisionPairs.push_back({EntityType::Cyclist, EntityType::Cyclist}); + collisionPairs.push_back({EntityType::Cyclist, EntityType::RoadLine}); + collisionPairs.push_back({EntityType::Cyclist, EntityType::RoadLane}); + collisionPairs.push_back({EntityType::Cyclist, EntityType::CrossWalk}); + collisionPairs.push_back({EntityType::Cyclist, EntityType::SpeedBump}); + collisionPairs.push_back({EntityType::Cyclist, EntityType::StopSign}); + collisionPairs.push_back({EntityType::Vehicle, EntityType::CrossWalk}); + collisionPairs.push_back({EntityType::Vehicle, EntityType::SpeedBump}); + collisionPairs.push_back({EntityType::Vehicle, EntityType::RoadLine}); + collisionPairs.push_back({EntityType::Vehicle, EntityType::RoadLane}); // TODO: Break Cube into road types for better control over collisions return collisionPairs; } From b7882260d8bfe70e075fc015d832e0dfc67a312c Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Fri, 15 Mar 2024 12:11:37 -0400 Subject: [PATCH 29/33] Run benchmarks --- config.py | 2 +- config.yml | 10 ++--- nocturne_data/example.json | 60 ----------------------------- run_bench.sh | 13 +++++++ scripts/benchmark.py | 75 ++++++++++++++++++++++++------------- scripts/sim_utils/create.py | 11 ++---- 6 files changed, 73 insertions(+), 98 deletions(-) delete mode 100644 nocturne_data/example.json create mode 100755 run_bench.sh diff --git a/config.py b/config.py index 663b9cd7..c5640594 100644 --- a/config.py +++ b/config.py @@ -8,7 +8,7 @@ def get_constants(): fullpath = os.path.join(os.path.dirname(__file__), "config.yml") sim = SimCreator(fullpath) - consts = sim.shape_tensor().to_torch().flatten().tolist() + consts = sim.shape_tensor().to_torch()[0].flatten().tolist() print(consts) return consts diff --git a/config.yml b/config.yml index b09e81d1..6b4a6ab9 100644 --- a/config.yml +++ b/config.yml @@ -5,13 +5,13 @@ reward_params: parameters: polylineReductionThreshold: 1.0 - observationRadius: 10.0 + observationRadius: 1000.0 datasetInitOptions: FirstN - rewardParams: reward_params + rewardParams: reward_params sim_manager: - exec_mode: CPU + exec_mode: CUDA gpu_id: 0 - num_worlds: 1 + num_worlds: 5 auto_reset: true - json_path: /home/aarav/gpudrive/valid_nocturne + json_path: /home/aarav/nocturne_data/formatted_json_v2_no_tl_valid \ No newline at end of file diff --git a/nocturne_data/example.json b/nocturne_data/example.json deleted file mode 100644 index 74bc1906..00000000 --- a/nocturne_data/example.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "name": "tfrecord-00100-of-00150_139.json", - "objects": [ - { - "position": [ - { - "x": 0, - "y": 0 - } - ], - "width": 1, - "length": 1, - "heading": [ - 0.0 - ], - "velocity": [ - { - "x": 0, - "y": 0 - } - ], - "valid": [ - true - ], - "goalPosition": { - "x": 606.9762573242188, - "y": -4803.1611328125 - }, - "type": "vehicle" - }, - { - "position": [ - { - "x": 3, - "y": 4 - } - ], - "width": 1, - "length": 1, - "heading": [ - 45.0 - ], - "velocity": [ - { - "x": 1.0, - "y": 1.0 - } - ], - "valid": [ - true - ], - "goalPosition": { - "x": 606.9762573242188, - "y": -4803.1611328125 - }, - "type": "vehicle" - } - ], - "tl_states": {} -} diff --git a/run_bench.sh b/run_bench.sh new file mode 100755 index 00000000..0d82ae21 --- /dev/null +++ b/run_bench.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# Loop from 1 to 30 to set the numEnvs value +for numEnvs in {1..30}; do + echo "Running benchmarks for numEnvs = $numEnvs" + + # Inner loop to run the command 20 times for each numEnvs value + for run in {1..20}; do + echo "Iteration $run for numEnvs = $numEnvs" + python scripts/benchmark.py --numEnvs "$numEnvs" + done + +done diff --git a/scripts/benchmark.py b/scripts/benchmark.py index de922a84..2c9a0e85 100644 --- a/scripts/benchmark.py +++ b/scripts/benchmark.py @@ -1,27 +1,52 @@ -import gpudrive +from gpudrive import SimManager from sim_utils.create import SimCreator -# Create an instance of RewardParams -reward_params = gpudrive.RewardParams() -reward_params.rewardType = gpudrive.RewardType.DistanceBased # Or any other value from the enum -reward_params.distanceToGoalThreshold = 1.0 # Set appropriate values -reward_params.distanceToExpertThreshold = 1.0 # Set appropriate values - -# Create an instance of Parameters -params = gpudrive.Parameters() -params.polylineReductionThreshold = 0.5 # Set appropriate value -params.observationRadius = 10.0 # Set appropriate value -params.datasetInitOptions = gpudrive.DatasetInitOptions.FirstN -params.rewardParams = reward_params # Set the rewardParams attribute to the instance created above - -# Now use the 'params' instance when creating SimManager -sim = gpudrive.SimManager( - exec_mode=gpudrive.madrona.ExecMode.CPU, - gpu_id=0, - num_worlds=1, - auto_reset=True, - json_path="/home/aarav/gpudrive/valid_nocturne", - params=params -) - -print(sim.controlled_state_tensor().to_torch().shape) +from time import perf_counter +import argparse +import csv +import yaml + +def run_benchmark(sim: SimManager, config: dict): + shape = sim.shape_tensor().to_torch() + num_agents, num_roads = shape[0].flatten().tolist() + num_envs = shape.shape[0] + + start = perf_counter() + for i in range(0): + sim.reset(i) + time_to_reset = perf_counter() - start + + start = perf_counter() + for i in range(91): + sim.step() + time_to_step = perf_counter() - start + + fps = (91 / time_to_step) * num_envs + afps = fps * num_agents + + + print(f"num_agents: {num_agents}, num_roads: {num_roads}, num_envs: {num_envs}, time_to_reset: {time_to_reset}, time_to_step: {time_to_step}, fps: {fps}, afps: {afps}, exec_mode: {config['sim_manager']['exec_mode']}, datasetInitOptions: {config['parameters']['datasetInitOptions']}") + # check if benchmark_results.csv exists + try: + with open('benchmark_results.csv', mode='r') as file: + pass + except FileNotFoundError: + with open('benchmark_results.csv', mode='w') as file: + writer = csv.writer(file) + writer.writerow(['num_agents', 'num_roads', 'num_envs', 'time_to_reset', 'time_to_step', 'fps', 'afps', 'exec_mode', 'datasetInitOptions']) + + with open('benchmark_results.csv', mode='a') as file: + writer = csv.writer(file) + writer.writerow([num_agents, num_roads, num_envs, time_to_reset, time_to_step, fps, afps, config['sim_manager']['exec_mode'], config['parameters']['datasetInitOptions']]) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='GPUDrive Benchmarking Tool') + parser.add_argument('--datasetPath', type=str, help='Path to the dataset', default='/home/aarav/gpudrive/config.yml') + parser.add_argument('--numEnvs', type=int, help='Number of environments', default=1) + args = parser.parse_args() + with open(args.datasetPath, 'r') as file: + config = yaml.safe_load(file) + config['sim_manager']['num_worlds'] = args.numEnvs + sim = SimCreator(config) + run_benchmark(sim, config) \ No newline at end of file diff --git a/scripts/sim_utils/create.py b/scripts/sim_utils/create.py index ae7578bf..6c9be810 100644 --- a/scripts/sim_utils/create.py +++ b/scripts/sim_utils/create.py @@ -1,11 +1,7 @@ import yaml import gpudrive -def SimCreator(config_path: str) -> gpudrive.SimManager: - # Load the YAML config file - with open(config_path, 'r') as file: - config = yaml.safe_load(file) - +def SimCreator(config: dict) -> gpudrive.SimManager: # Initialize RewardParams reward_params_config = config['reward_params'] reward_params = gpudrive.RewardParams() @@ -34,5 +30,6 @@ def SimCreator(config_path: str) -> gpudrive.SimManager: return sim if __name__ == "__main__": - sim = SimCreator("/home/aarav/gpudrive/config.yml") - print(sim.controlled_state_tensor().to_torch().shape) + with open("/home/aarav/gpudrive/config.yml", 'r') as file: + config = yaml.safe_load(file) + sim = SimCreator(config) From 2e9cc23753c888f1063423d4125b3349ae14eade Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Sun, 17 Mar 2024 21:20:48 -0400 Subject: [PATCH 30/33] benchmarking --- config.yml | 18 +- poetry.lock | 556 ++++++++++++++++++++++++++++++++++++++++++- pyproject.toml | 2 + scripts/benchmark.py | 20 +- scripts/run_bench.py | 47 ++++ src/consts.hpp | 4 +- 6 files changed, 627 insertions(+), 20 deletions(-) create mode 100644 scripts/run_bench.py diff --git a/config.yml b/config.yml index 6b4a6ab9..720022fb 100644 --- a/config.yml +++ b/config.yml @@ -1,17 +1,15 @@ -reward_params: - rewardType: DistanceBased - distanceToGoalThreshold: 1.0 - distanceToExpertThreshold: 1.0 - parameters: - polylineReductionThreshold: 1.0 + datasetInitOptions: RandomN observationRadius: 1000.0 - datasetInitOptions: FirstN + polylineReductionThreshold: 1.0 rewardParams: reward_params - +reward_params: + distanceToExpertThreshold: 1.0 + distanceToGoalThreshold: 1.0 + rewardType: DistanceBased sim_manager: + auto_reset: true exec_mode: CUDA gpu_id: 0 + json_path: /home/aarav/nocturne_data/formatted_json_v2_no_tl_valid num_worlds: 5 - auto_reset: true - json_path: /home/aarav/nocturne_data/formatted_json_v2_no_tl_valid \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 600108d4..a0e9e9c0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,83 @@ # This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +[[package]] +name = "contourpy" +version = "1.2.0" +description = "Python library for calculating contours of 2D quadrilateral grids" +optional = false +python-versions = ">=3.9" +files = [ + {file = "contourpy-1.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0274c1cb63625972c0c007ab14dd9ba9e199c36ae1a231ce45d725cbcbfd10a8"}, + {file = "contourpy-1.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ab459a1cbbf18e8698399c595a01f6dcc5c138220ca3ea9e7e6126232d102bb4"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fdd887f17c2f4572ce548461e4f96396681212d858cae7bd52ba3310bc6f00f"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d16edfc3fc09968e09ddffada434b3bf989bf4911535e04eada58469873e28e"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c203f617abc0dde5792beb586f827021069fb6d403d7f4d5c2b543d87edceb9"}, + {file = "contourpy-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b69303ceb2e4d4f146bf82fda78891ef7bcd80c41bf16bfca3d0d7eb545448aa"}, + {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:884c3f9d42d7218304bc74a8a7693d172685c84bd7ab2bab1ee567b769696df9"}, + {file = "contourpy-1.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4a1b1208102be6e851f20066bf0e7a96b7d48a07c9b0cfe6d0d4545c2f6cadab"}, + {file = "contourpy-1.2.0-cp310-cp310-win32.whl", hash = "sha256:34b9071c040d6fe45d9826cbbe3727d20d83f1b6110d219b83eb0e2a01d79488"}, + {file = "contourpy-1.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:bd2f1ae63998da104f16a8b788f685e55d65760cd1929518fd94cd682bf03e41"}, + {file = "contourpy-1.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dd10c26b4eadae44783c45ad6655220426f971c61d9b239e6f7b16d5cdaaa727"}, + {file = "contourpy-1.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5c6b28956b7b232ae801406e529ad7b350d3f09a4fde958dfdf3c0520cdde0dd"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebeac59e9e1eb4b84940d076d9f9a6cec0064e241818bcb6e32124cc5c3e377a"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:139d8d2e1c1dd52d78682f505e980f592ba53c9f73bd6be102233e358b401063"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e9dc350fb4c58adc64df3e0703ab076f60aac06e67d48b3848c23647ae4310e"}, + {file = "contourpy-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18fc2b4ed8e4a8fe849d18dce4bd3c7ea637758c6343a1f2bae1e9bd4c9f4686"}, + {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:16a7380e943a6d52472096cb7ad5264ecee36ed60888e2a3d3814991a0107286"}, + {file = "contourpy-1.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8d8faf05be5ec8e02a4d86f616fc2a0322ff4a4ce26c0f09d9f7fb5330a35c95"}, + {file = "contourpy-1.2.0-cp311-cp311-win32.whl", hash = "sha256:67b7f17679fa62ec82b7e3e611c43a016b887bd64fb933b3ae8638583006c6d6"}, + {file = "contourpy-1.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:99ad97258985328b4f207a5e777c1b44a83bfe7cf1f87b99f9c11d4ee477c4de"}, + {file = "contourpy-1.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:575bcaf957a25d1194903a10bc9f316c136c19f24e0985a2b9b5608bdf5dbfe0"}, + {file = "contourpy-1.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9e6c93b5b2dbcedad20a2f18ec22cae47da0d705d454308063421a3b290d9ea4"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:464b423bc2a009088f19bdf1f232299e8b6917963e2b7e1d277da5041f33a779"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:68ce4788b7d93e47f84edd3f1f95acdcd142ae60bc0e5493bfd120683d2d4316"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d7d1f8871998cdff5d2ff6a087e5e1780139abe2838e85b0b46b7ae6cc25399"}, + {file = "contourpy-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e739530c662a8d6d42c37c2ed52a6f0932c2d4a3e8c1f90692ad0ce1274abe0"}, + {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:247b9d16535acaa766d03037d8e8fb20866d054d3c7fbf6fd1f993f11fc60ca0"}, + {file = "contourpy-1.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:461e3ae84cd90b30f8d533f07d87c00379644205b1d33a5ea03381edc4b69431"}, + {file = "contourpy-1.2.0-cp312-cp312-win32.whl", hash = "sha256:1c2559d6cffc94890b0529ea7eeecc20d6fadc1539273aa27faf503eb4656d8f"}, + {file = "contourpy-1.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:491b1917afdd8638a05b611a56d46587d5a632cabead889a5440f7c638bc6ed9"}, + {file = "contourpy-1.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5fd1810973a375ca0e097dee059c407913ba35723b111df75671a1976efa04bc"}, + {file = "contourpy-1.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:999c71939aad2780f003979b25ac5b8f2df651dac7b38fb8ce6c46ba5abe6ae9"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7caf9b241464c404613512d5594a6e2ff0cc9cb5615c9475cc1d9b514218ae8"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:266270c6f6608340f6c9836a0fb9b367be61dde0c9a9a18d5ece97774105ff3e"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbd50d0a0539ae2e96e537553aff6d02c10ed165ef40c65b0e27e744a0f10af8"}, + {file = "contourpy-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11f8d2554e52f459918f7b8e6aa20ec2a3bce35ce95c1f0ef4ba36fbda306df5"}, + {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ce96dd400486e80ac7d195b2d800b03e3e6a787e2a522bfb83755938465a819e"}, + {file = "contourpy-1.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6d3364b999c62f539cd403f8123ae426da946e142312a514162adb2addd8d808"}, + {file = "contourpy-1.2.0-cp39-cp39-win32.whl", hash = "sha256:1c88dfb9e0c77612febebb6ac69d44a8d81e3dc60f993215425b62c1161353f4"}, + {file = "contourpy-1.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:78e6ad33cf2e2e80c5dfaaa0beec3d61face0fb650557100ee36db808bfa6843"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:be16975d94c320432657ad2402f6760990cb640c161ae6da1363051805fa8108"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b95a225d4948b26a28c08307a60ac00fb8671b14f2047fc5476613252a129776"}, + {file = "contourpy-1.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:0d7e03c0f9a4f90dc18d4e77e9ef4ec7b7bbb437f7f675be8e530d65ae6ef956"}, + {file = "contourpy-1.2.0.tar.gz", hash = "sha256:171f311cb758de7da13fc53af221ae47a5877be5a0843a9fe150818c51ed276a"}, +] + +[package.dependencies] +numpy = ">=1.20,<2.0" + +[package.extras] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] +mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.6.1)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "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 = "filelock" version = "3.13.1" @@ -16,6 +94,71 @@ docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1 testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] typing = ["typing-extensions (>=4.8)"] +[[package]] +name = "fonttools" +version = "4.50.0" +description = "Tools to manipulate font files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fonttools-4.50.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:effd303fb422f8ce06543a36ca69148471144c534cc25f30e5be752bc4f46736"}, + {file = "fonttools-4.50.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7913992ab836f621d06aabac118fc258b9947a775a607e1a737eb3a91c360335"}, + {file = "fonttools-4.50.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e0a1c5bd2f63da4043b63888534b52c5a1fd7ae187c8ffc64cbb7ae475b9dab"}, + {file = "fonttools-4.50.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d40fc98540fa5360e7ecf2c56ddf3c6e7dd04929543618fd7b5cc76e66390562"}, + {file = "fonttools-4.50.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9fff65fbb7afe137bac3113827855e0204482727bddd00a806034ab0d3951d0d"}, + {file = "fonttools-4.50.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b1aeae3dd2ee719074a9372c89ad94f7c581903306d76befdaca2a559f802472"}, + {file = "fonttools-4.50.0-cp310-cp310-win32.whl", hash = "sha256:e9623afa319405da33b43c85cceb0585a6f5d3a1d7c604daf4f7e1dd55c03d1f"}, + {file = "fonttools-4.50.0-cp310-cp310-win_amd64.whl", hash = "sha256:778c5f43e7e654ef7fe0605e80894930bc3a7772e2f496238e57218610140f54"}, + {file = "fonttools-4.50.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3dfb102e7f63b78c832e4539969167ffcc0375b013080e6472350965a5fe8048"}, + {file = "fonttools-4.50.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9e58fe34cb379ba3d01d5d319d67dd3ce7ca9a47ad044ea2b22635cd2d1247fc"}, + {file = "fonttools-4.50.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c673ab40d15a442a4e6eb09bf007c1dda47c84ac1e2eecbdf359adacb799c24"}, + {file = "fonttools-4.50.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b3ac35cdcd1a4c90c23a5200212c1bb74fa05833cc7c14291d7043a52ca2aaa"}, + {file = "fonttools-4.50.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8844e7a2c5f7ecf977e82eb6b3014f025c8b454e046d941ece05b768be5847ae"}, + {file = "fonttools-4.50.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f849bd3c5c2249b49c98eca5aaebb920d2bfd92b3c69e84ca9bddf133e9f83f0"}, + {file = "fonttools-4.50.0-cp311-cp311-win32.whl", hash = "sha256:39293ff231b36b035575e81c14626dfc14407a20de5262f9596c2cbb199c3625"}, + {file = "fonttools-4.50.0-cp311-cp311-win_amd64.whl", hash = "sha256:c33d5023523b44d3481624f840c8646656a1def7630ca562f222eb3ead16c438"}, + {file = "fonttools-4.50.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b4a886a6dbe60100ba1cd24de962f8cd18139bd32808da80de1fa9f9f27bf1dc"}, + {file = "fonttools-4.50.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b2ca1837bfbe5eafa11313dbc7edada79052709a1fffa10cea691210af4aa1fa"}, + {file = "fonttools-4.50.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0493dd97ac8977e48ffc1476b932b37c847cbb87fd68673dee5182004906828"}, + {file = "fonttools-4.50.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77844e2f1b0889120b6c222fc49b2b75c3d88b930615e98893b899b9352a27ea"}, + {file = "fonttools-4.50.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3566bfb8c55ed9100afe1ba6f0f12265cd63a1387b9661eb6031a1578a28bad1"}, + {file = "fonttools-4.50.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:35e10ddbc129cf61775d58a14f2d44121178d89874d32cae1eac722e687d9019"}, + {file = "fonttools-4.50.0-cp312-cp312-win32.whl", hash = "sha256:cc8140baf9fa8f9b903f2b393a6c413a220fa990264b215bf48484f3d0bf8710"}, + {file = "fonttools-4.50.0-cp312-cp312-win_amd64.whl", hash = "sha256:0ccc85fd96373ab73c59833b824d7a73846670a0cb1f3afbaee2b2c426a8f931"}, + {file = "fonttools-4.50.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e270a406219af37581d96c810172001ec536e29e5593aa40d4c01cca3e145aa6"}, + {file = "fonttools-4.50.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac2463de667233372e9e1c7e9de3d914b708437ef52a3199fdbf5a60184f190c"}, + {file = "fonttools-4.50.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47abd6669195abe87c22750dbcd366dc3a0648f1b7c93c2baa97429c4dc1506e"}, + {file = "fonttools-4.50.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:074841375e2e3d559aecc86e1224caf78e8b8417bb391e7d2506412538f21adc"}, + {file = "fonttools-4.50.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0743fd2191ad7ab43d78cd747215b12033ddee24fa1e088605a3efe80d6984de"}, + {file = "fonttools-4.50.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3d7080cce7be5ed65bee3496f09f79a82865a514863197ff4d4d177389e981b0"}, + {file = "fonttools-4.50.0-cp38-cp38-win32.whl", hash = "sha256:a467ba4e2eadc1d5cc1a11d355abb945f680473fbe30d15617e104c81f483045"}, + {file = "fonttools-4.50.0-cp38-cp38-win_amd64.whl", hash = "sha256:f77e048f805e00870659d6318fd89ef28ca4ee16a22b4c5e1905b735495fc422"}, + {file = "fonttools-4.50.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b6245eafd553c4e9a0708e93be51392bd2288c773523892fbd616d33fd2fda59"}, + {file = "fonttools-4.50.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a4062cc7e8de26f1603323ef3ae2171c9d29c8a9f5e067d555a2813cd5c7a7e0"}, + {file = "fonttools-4.50.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34692850dfd64ba06af61e5791a441f664cb7d21e7b544e8f385718430e8f8e4"}, + {file = "fonttools-4.50.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:678dd95f26a67e02c50dcb5bf250f95231d455642afbc65a3b0bcdacd4e4dd38"}, + {file = "fonttools-4.50.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4f2ce7b0b295fe64ac0a85aef46a0f2614995774bd7bc643b85679c0283287f9"}, + {file = "fonttools-4.50.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d346f4dc2221bfb7ab652d1e37d327578434ce559baf7113b0f55768437fe6a0"}, + {file = "fonttools-4.50.0-cp39-cp39-win32.whl", hash = "sha256:a51eeaf52ba3afd70bf489be20e52fdfafe6c03d652b02477c6ce23c995222f4"}, + {file = "fonttools-4.50.0-cp39-cp39-win_amd64.whl", hash = "sha256:8639be40d583e5d9da67795aa3eeeda0488fb577a1d42ae11a5036f18fb16d93"}, + {file = "fonttools-4.50.0-py3-none-any.whl", hash = "sha256:48fa36da06247aa8282766cfd63efff1bb24e55f020f29a335939ed3844d20d3"}, + {file = "fonttools-4.50.0.tar.gz", hash = "sha256:fa5cf61058c7dbb104c2ac4e782bf1b2016a8cf2f69de6e4dd6a865d2c969bb5"}, +] + +[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 = "fsspec" version = "2024.2.0" @@ -68,6 +211,119 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "kiwisolver" +version = "1.4.5" +description = "A fast implementation of the Cassowary constraint solver" +optional = false +python-versions = ">=3.7" +files = [ + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3a2b053a0ab7a3960c98725cfb0bf5b48ba82f64ec95fe06f1d06c99b552e130"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cd32d6c13807e5c66a7cbb79f90b553642f296ae4518a60d8d76243b0ad2898"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59ec7b7c7e1a61061850d53aaf8e93db63dce0c936db1fda2658b70e4a1be709"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da4cfb373035def307905d05041c1d06d8936452fe89d464743ae7fb8371078b"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2400873bccc260b6ae184b2b8a4fec0e4082d30648eadb7c3d9a13405d861e89"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1b04139c4236a0f3aff534479b58f6f849a8b351e1314826c2d230849ed48985"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4e66e81a5779b65ac21764c295087de82235597a2293d18d943f8e9e32746265"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7931d8f1f67c4be9ba1dd9c451fb0eeca1a25b89e4d3f89e828fe12a519b782a"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b3f7e75f3015df442238cca659f8baa5f42ce2a8582727981cbfa15fee0ee205"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:bbf1d63eef84b2e8c89011b7f2235b1e0bf7dacc11cac9431fc6468e99ac77fb"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4c380469bd3f970ef677bf2bcba2b6b0b4d5c75e7a020fb863ef75084efad66f"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win32.whl", hash = "sha256:9408acf3270c4b6baad483865191e3e582b638b1654a007c62e3efe96f09a9a3"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win_amd64.whl", hash = "sha256:5b94529f9b2591b7af5f3e0e730a4e0a41ea174af35a4fd067775f9bdfeee01a"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:11c7de8f692fc99816e8ac50d1d1aef4f75126eefc33ac79aac02c099fd3db71"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:53abb58632235cd154176ced1ae8f0d29a6657aa1aa9decf50b899b755bc2b93"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:88b9f257ca61b838b6f8094a62418421f87ac2a1069f7e896c36a7d86b5d4c29"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3195782b26fc03aa9c6913d5bad5aeb864bdc372924c093b0f1cebad603dd712"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc579bf0f502e54926519451b920e875f433aceb4624a3646b3252b5caa9e0b6"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a580c91d686376f0f7c295357595c5a026e6cbc3d77b7c36e290201e7c11ecb"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cfe6ab8da05c01ba6fbea630377b5da2cd9bcbc6338510116b01c1bc939a2c18"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d2e5a98f0ec99beb3c10e13b387f8db39106d53993f498b295f0c914328b1333"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a51a263952b1429e429ff236d2f5a21c5125437861baeed77f5e1cc2d2c7c6da"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3edd2fa14e68c9be82c5b16689e8d63d89fe927e56debd6e1dbce7a26a17f81b"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:74d1b44c6cfc897df648cc9fdaa09bc3e7679926e6f96df05775d4fb3946571c"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:76d9289ed3f7501012e05abb8358bbb129149dbd173f1f57a1bf1c22d19ab7cc"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:92dea1ffe3714fa8eb6a314d2b3c773208d865a0e0d35e713ec54eea08a66250"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win32.whl", hash = "sha256:5c90ae8c8d32e472be041e76f9d2f2dbff4d0b0be8bd4041770eddb18cf49a4e"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win_amd64.whl", hash = "sha256:c7940c1dc63eb37a67721b10d703247552416f719c4188c54e04334321351ced"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0dc9db8e79f0036e8173c466d21ef18e1befc02de8bf8aa8dc0813a6dc8a7046"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cdc8a402aaee9a798b50d8b827d7ecf75edc5fb35ea0f91f213ff927c15f4ff0"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6c3bd3cde54cafb87d74d8db50b909705c62b17c2099b8f2e25b461882e544ff"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:955e8513d07a283056b1396e9a57ceddbd272d9252c14f154d450d227606eb54"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:346f5343b9e3f00b8db8ba359350eb124b98c99efd0b408728ac6ebf38173958"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9098e0049e88c6a24ff64545cdfc50807818ba6c1b739cae221bbbcbc58aad3"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7b8b454bac16428b22560d0a1cf0a09875339cab69df61d7805bf48919415901"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f1d072c2eb0ad60d4c183f3fb44ac6f73fb7a8f16a2694a91f988275cbf352f9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:31a82d498054cac9f6d0b53d02bb85811185bcb477d4b60144f915f3b3126342"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6512cb89e334e4700febbffaaa52761b65b4f5a3cf33f960213d5656cea36a77"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win32.whl", hash = "sha256:9db8ea4c388fdb0f780fe91346fd438657ea602d58348753d9fb265ce1bca67f"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win_amd64.whl", hash = "sha256:59415f46a37f7f2efeec758353dd2eae1b07640d8ca0f0c42548ec4125492635"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee"}, + {file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"}, +] + [[package]] name = "markupsafe" version = "2.1.5" @@ -137,6 +393,54 @@ files = [ {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, ] +[[package]] +name = "matplotlib" +version = "3.8.3" +description = "Python plotting package" +optional = false +python-versions = ">=3.9" +files = [ + {file = "matplotlib-3.8.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:cf60138ccc8004f117ab2a2bad513cc4d122e55864b4fe7adf4db20ca68a078f"}, + {file = "matplotlib-3.8.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5f557156f7116be3340cdeef7f128fa99b0d5d287d5f41a16e169819dcf22357"}, + {file = "matplotlib-3.8.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f386cf162b059809ecfac3bcc491a9ea17da69fa35c8ded8ad154cd4b933d5ec"}, + {file = "matplotlib-3.8.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3c5f96f57b0369c288bf6f9b5274ba45787f7e0589a34d24bdbaf6d3344632f"}, + {file = "matplotlib-3.8.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:83e0f72e2c116ca7e571c57aa29b0fe697d4c6425c4e87c6e994159e0c008635"}, + {file = "matplotlib-3.8.3-cp310-cp310-win_amd64.whl", hash = "sha256:1c5c8290074ba31a41db1dc332dc2b62def469ff33766cbe325d32a3ee291aea"}, + {file = "matplotlib-3.8.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5184e07c7e1d6d1481862ee361905b7059f7fe065fc837f7c3dc11eeb3f2f900"}, + {file = "matplotlib-3.8.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d7e7e0993d0758933b1a241a432b42c2db22dfa37d4108342ab4afb9557cbe3e"}, + {file = "matplotlib-3.8.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:04b36ad07eac9740fc76c2aa16edf94e50b297d6eb4c081e3add863de4bb19a7"}, + {file = "matplotlib-3.8.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c42dae72a62f14982f1474f7e5c9959fc4bc70c9de11cc5244c6e766200ba65"}, + {file = "matplotlib-3.8.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bf5932eee0d428192c40b7eac1399d608f5d995f975cdb9d1e6b48539a5ad8d0"}, + {file = "matplotlib-3.8.3-cp311-cp311-win_amd64.whl", hash = "sha256:40321634e3a05ed02abf7c7b47a50be50b53ef3eaa3a573847431a545585b407"}, + {file = "matplotlib-3.8.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:09074f8057917d17ab52c242fdf4916f30e99959c1908958b1fc6032e2d0f6d4"}, + {file = "matplotlib-3.8.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5745f6d0fb5acfabbb2790318db03809a253096e98c91b9a31969df28ee604aa"}, + {file = "matplotlib-3.8.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b97653d869a71721b639714b42d87cda4cfee0ee74b47c569e4874c7590c55c5"}, + {file = "matplotlib-3.8.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:242489efdb75b690c9c2e70bb5c6550727058c8a614e4c7716f363c27e10bba1"}, + {file = "matplotlib-3.8.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:83c0653c64b73926730bd9ea14aa0f50f202ba187c307a881673bad4985967b7"}, + {file = "matplotlib-3.8.3-cp312-cp312-win_amd64.whl", hash = "sha256:ef6c1025a570354297d6c15f7d0f296d95f88bd3850066b7f1e7b4f2f4c13a39"}, + {file = "matplotlib-3.8.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c4af3f7317f8a1009bbb2d0bf23dfaba859eb7dd4ccbd604eba146dccaaaf0a4"}, + {file = "matplotlib-3.8.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4c6e00a65d017d26009bac6808f637b75ceade3e1ff91a138576f6b3065eeeba"}, + {file = "matplotlib-3.8.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7b49ab49a3bea17802df6872f8d44f664ba8f9be0632a60c99b20b6db2165b7"}, + {file = "matplotlib-3.8.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6728dde0a3997396b053602dbd907a9bd64ec7d5cf99e728b404083698d3ca01"}, + {file = "matplotlib-3.8.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:813925d08fb86aba139f2d31864928d67511f64e5945ca909ad5bc09a96189bb"}, + {file = "matplotlib-3.8.3-cp39-cp39-win_amd64.whl", hash = "sha256:cd3a0c2be76f4e7be03d34a14d49ded6acf22ef61f88da600a18a5cd8b3c5f3c"}, + {file = "matplotlib-3.8.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:fa93695d5c08544f4a0dfd0965f378e7afc410d8672816aff1e81be1f45dbf2e"}, + {file = "matplotlib-3.8.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9764df0e8778f06414b9d281a75235c1e85071f64bb5d71564b97c1306a2afc"}, + {file = "matplotlib-3.8.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5e431a09e6fab4012b01fc155db0ce6dccacdbabe8198197f523a4ef4805eb26"}, + {file = "matplotlib-3.8.3.tar.gz", hash = "sha256:7b416239e9ae38be54b028abbf9048aff5054a9aba5416bef0bd17f9162ce161"}, +] + +[package.dependencies] +contourpy = ">=1.0.1" +cycler = ">=0.10" +fonttools = ">=4.22.0" +kiwisolver = ">=1.3.1" +numpy = ">=1.21,<2" +packaging = ">=20.0" +pillow = ">=8" +pyparsing = ">=2.3.1" +python-dateutil = ">=2.7" + [[package]] name = "mpmath" version = "1.3.0" @@ -358,6 +662,213 @@ files = [ {file = "nvidia_nvtx_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:65f4d98982b31b60026e0e6de73fbdfc09d08a96f4656dd3665ca616a11e1e82"}, ] +[[package]] +name = "packaging" +version = "24.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, + {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, +] + +[[package]] +name = "pandas" +version = "2.2.1" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pandas-2.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8df8612be9cd1c7797c93e1c5df861b2ddda0b48b08f2c3eaa0702cf88fb5f88"}, + {file = "pandas-2.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0f573ab277252ed9aaf38240f3b54cfc90fff8e5cab70411ee1d03f5d51f3944"}, + {file = "pandas-2.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f02a3a6c83df4026e55b63c1f06476c9aa3ed6af3d89b4f04ea656ccdaaaa359"}, + {file = "pandas-2.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c38ce92cb22a4bea4e3929429aa1067a454dcc9c335799af93ba9be21b6beb51"}, + {file = "pandas-2.2.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c2ce852e1cf2509a69e98358e8458775f89599566ac3775e70419b98615f4b06"}, + {file = "pandas-2.2.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:53680dc9b2519cbf609c62db3ed7c0b499077c7fefda564e330286e619ff0dd9"}, + {file = "pandas-2.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:94e714a1cca63e4f5939cdce5f29ba8d415d85166be3441165edd427dc9f6bc0"}, + {file = "pandas-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f821213d48f4ab353d20ebc24e4faf94ba40d76680642fb7ce2ea31a3ad94f9b"}, + {file = "pandas-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c70e00c2d894cb230e5c15e4b1e1e6b2b478e09cf27cc593a11ef955b9ecc81a"}, + {file = "pandas-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e97fbb5387c69209f134893abc788a6486dbf2f9e511070ca05eed4b930b1b02"}, + {file = "pandas-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101d0eb9c5361aa0146f500773395a03839a5e6ecde4d4b6ced88b7e5a1a6403"}, + {file = "pandas-2.2.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7d2ed41c319c9fb4fd454fe25372028dfa417aacb9790f68171b2e3f06eae8cd"}, + {file = "pandas-2.2.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:af5d3c00557d657c8773ef9ee702c61dd13b9d7426794c9dfeb1dc4a0bf0ebc7"}, + {file = "pandas-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:06cf591dbaefb6da9de8472535b185cba556d0ce2e6ed28e21d919704fef1a9e"}, + {file = "pandas-2.2.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:88ecb5c01bb9ca927ebc4098136038519aa5d66b44671861ffab754cae75102c"}, + {file = "pandas-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:04f6ec3baec203c13e3f8b139fb0f9f86cd8c0b94603ae3ae8ce9a422e9f5bee"}, + {file = "pandas-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a935a90a76c44fe170d01e90a3594beef9e9a6220021acfb26053d01426f7dc2"}, + {file = "pandas-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c391f594aae2fd9f679d419e9a4d5ba4bce5bb13f6a989195656e7dc4b95c8f0"}, + {file = "pandas-2.2.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9d1265545f579edf3f8f0cb6f89f234f5e44ba725a34d86535b1a1d38decbccc"}, + {file = "pandas-2.2.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:11940e9e3056576ac3244baef2fedade891977bcc1cb7e5cc8f8cc7d603edc89"}, + {file = "pandas-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:4acf681325ee1c7f950d058b05a820441075b0dd9a2adf5c4835b9bc056bf4fb"}, + {file = "pandas-2.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9bd8a40f47080825af4317d0340c656744f2bfdb6819f818e6ba3cd24c0e1397"}, + {file = "pandas-2.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:df0c37ebd19e11d089ceba66eba59a168242fc6b7155cba4ffffa6eccdfb8f16"}, + {file = "pandas-2.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:739cc70eaf17d57608639e74d63387b0d8594ce02f69e7a0b046f117974b3019"}, + {file = "pandas-2.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9d3558d263073ed95e46f4650becff0c5e1ffe0fc3a015de3c79283dfbdb3df"}, + {file = "pandas-2.2.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4aa1d8707812a658debf03824016bf5ea0d516afdea29b7dc14cf687bc4d4ec6"}, + {file = "pandas-2.2.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:76f27a809cda87e07f192f001d11adc2b930e93a2b0c4a236fde5429527423be"}, + {file = "pandas-2.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:1ba21b1d5c0e43416218db63037dbe1a01fc101dc6e6024bcad08123e48004ab"}, + {file = "pandas-2.2.1.tar.gz", hash = "sha256:0ab90f87093c13f3e8fa45b48ba9f39181046e8f3317d3aadb2fffbb1b978572"}, +] + +[package.dependencies] +numpy = [ + {version = ">=1.23.2,<2", markers = "python_version == \"3.11\""}, + {version = ">=1.26.0,<2", markers = "python_version >= \"3.12\""}, +] +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.7" + +[package.extras] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] +aws = ["s3fs (>=2022.11.0)"] +clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] +compression = ["zstandard (>=0.19.0)"] +computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] +consortium-standard = ["dataframe-api-compat (>=0.1.7)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] +feather = ["pyarrow (>=10.0.1)"] +fss = ["fsspec (>=2022.11.0)"] +gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] +hdf5 = ["tables (>=3.8.0)"] +html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] +mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] +parquet = ["pyarrow (>=10.0.1)"] +performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] +plot = ["matplotlib (>=3.6.3)"] +postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] +pyarrow = ["pyarrow (>=10.0.1)"] +spss = ["pyreadstat (>=1.2.0)"] +sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] +test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.9.2)"] + +[[package]] +name = "pillow" +version = "10.2.0" +description = "Python Imaging Library (Fork)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pillow-10.2.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:7823bdd049099efa16e4246bdf15e5a13dbb18a51b68fa06d6c1d4d8b99a796e"}, + {file = "pillow-10.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:83b2021f2ade7d1ed556bc50a399127d7fb245e725aa0113ebd05cfe88aaf588"}, + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fad5ff2f13d69b7e74ce5b4ecd12cc0ec530fcee76356cac6742785ff71c452"}, + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da2b52b37dad6d9ec64e653637a096905b258d2fc2b984c41ae7d08b938a67e4"}, + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:47c0995fc4e7f79b5cfcab1fc437ff2890b770440f7696a3ba065ee0fd496563"}, + {file = "pillow-10.2.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:322bdf3c9b556e9ffb18f93462e5f749d3444ce081290352c6070d014c93feb2"}, + {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:51f1a1bffc50e2e9492e87d8e09a17c5eea8409cda8d3f277eb6edc82813c17c"}, + {file = "pillow-10.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69ffdd6120a4737710a9eee73e1d2e37db89b620f702754b8f6e62594471dee0"}, + {file = "pillow-10.2.0-cp310-cp310-win32.whl", hash = "sha256:c6dafac9e0f2b3c78df97e79af707cdc5ef8e88208d686a4847bab8266870023"}, + {file = "pillow-10.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:aebb6044806f2e16ecc07b2a2637ee1ef67a11840a66752751714a0d924adf72"}, + {file = "pillow-10.2.0-cp310-cp310-win_arm64.whl", hash = "sha256:7049e301399273a0136ff39b84c3678e314f2158f50f517bc50285fb5ec847ad"}, + {file = "pillow-10.2.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:35bb52c37f256f662abdfa49d2dfa6ce5d93281d323a9af377a120e89a9eafb5"}, + {file = "pillow-10.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9c23f307202661071d94b5e384e1e1dc7dfb972a28a2310e4ee16103e66ddb67"}, + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:773efe0603db30c281521a7c0214cad7836c03b8ccff897beae9b47c0b657d61"}, + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11fa2e5984b949b0dd6d7a94d967743d87c577ff0b83392f17cb3990d0d2fd6e"}, + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:716d30ed977be8b37d3ef185fecb9e5a1d62d110dfbdcd1e2a122ab46fddb03f"}, + {file = "pillow-10.2.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a086c2af425c5f62a65e12fbf385f7c9fcb8f107d0849dba5839461a129cf311"}, + {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c8de2789052ed501dd829e9cae8d3dcce7acb4777ea4a479c14521c942d395b1"}, + {file = "pillow-10.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:609448742444d9290fd687940ac0b57fb35e6fd92bdb65386e08e99af60bf757"}, + {file = "pillow-10.2.0-cp311-cp311-win32.whl", hash = "sha256:823ef7a27cf86df6597fa0671066c1b596f69eba53efa3d1e1cb8b30f3533068"}, + {file = "pillow-10.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:1da3b2703afd040cf65ec97efea81cfba59cdbed9c11d8efc5ab09df9509fc56"}, + {file = "pillow-10.2.0-cp311-cp311-win_arm64.whl", hash = "sha256:edca80cbfb2b68d7b56930b84a0e45ae1694aeba0541f798e908a49d66b837f1"}, + {file = "pillow-10.2.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:1b5e1b74d1bd1b78bc3477528919414874748dd363e6272efd5abf7654e68bef"}, + {file = "pillow-10.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0eae2073305f451d8ecacb5474997c08569fb4eb4ac231ffa4ad7d342fdc25ac"}, + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7c2286c23cd350b80d2fc9d424fc797575fb16f854b831d16fd47ceec078f2c"}, + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e23412b5c41e58cec602f1135c57dfcf15482013ce6e5f093a86db69646a5aa"}, + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:52a50aa3fb3acb9cf7213573ef55d31d6eca37f5709c69e6858fe3bc04a5c2a2"}, + {file = "pillow-10.2.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:127cee571038f252a552760076407f9cff79761c3d436a12af6000cd182a9d04"}, + {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:8d12251f02d69d8310b046e82572ed486685c38f02176bd08baf216746eb947f"}, + {file = "pillow-10.2.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54f1852cd531aa981bc0965b7d609f5f6cc8ce8c41b1139f6ed6b3c54ab82bfb"}, + {file = "pillow-10.2.0-cp312-cp312-win32.whl", hash = "sha256:257d8788df5ca62c980314053197f4d46eefedf4e6175bc9412f14412ec4ea2f"}, + {file = "pillow-10.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:154e939c5f0053a383de4fd3d3da48d9427a7e985f58af8e94d0b3c9fcfcf4f9"}, + {file = "pillow-10.2.0-cp312-cp312-win_arm64.whl", hash = "sha256:f379abd2f1e3dddb2b61bc67977a6b5a0a3f7485538bcc6f39ec76163891ee48"}, + {file = "pillow-10.2.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8373c6c251f7ef8bda6675dd6d2b3a0fcc31edf1201266b5cf608b62a37407f9"}, + {file = "pillow-10.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:870ea1ada0899fd0b79643990809323b389d4d1d46c192f97342eeb6ee0b8483"}, + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b4b6b1e20608493548b1f32bce8cca185bf0480983890403d3b8753e44077129"}, + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3031709084b6e7852d00479fd1d310b07d0ba82765f973b543c8af5061cf990e"}, + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:3ff074fc97dd4e80543a3e91f69d58889baf2002b6be64347ea8cf5533188213"}, + {file = "pillow-10.2.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:cb4c38abeef13c61d6916f264d4845fab99d7b711be96c326b84df9e3e0ff62d"}, + {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b1b3020d90c2d8e1dae29cf3ce54f8094f7938460fb5ce8bc5c01450b01fbaf6"}, + {file = "pillow-10.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:170aeb00224ab3dc54230c797f8404507240dd868cf52066f66a41b33169bdbe"}, + {file = "pillow-10.2.0-cp38-cp38-win32.whl", hash = "sha256:c4225f5220f46b2fde568c74fca27ae9771536c2e29d7c04f4fb62c83275ac4e"}, + {file = "pillow-10.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:0689b5a8c5288bc0504d9fcee48f61a6a586b9b98514d7d29b840143d6734f39"}, + {file = "pillow-10.2.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:b792a349405fbc0163190fde0dc7b3fef3c9268292586cf5645598b48e63dc67"}, + {file = "pillow-10.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c570f24be1e468e3f0ce7ef56a89a60f0e05b30a3669a459e419c6eac2c35364"}, + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8ecd059fdaf60c1963c58ceb8997b32e9dc1b911f5da5307aab614f1ce5c2fb"}, + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c365fd1703040de1ec284b176d6af5abe21b427cb3a5ff68e0759e1e313a5e7e"}, + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:70c61d4c475835a19b3a5aa42492409878bbca7438554a1f89d20d58a7c75c01"}, + {file = "pillow-10.2.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b6f491cdf80ae540738859d9766783e3b3c8e5bd37f5dfa0b76abdecc5081f13"}, + {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9d189550615b4948f45252d7f005e53c2040cea1af5b60d6f79491a6e147eef7"}, + {file = "pillow-10.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:49d9ba1ed0ef3e061088cd1e7538a0759aab559e2e0a80a36f9fd9d8c0c21591"}, + {file = "pillow-10.2.0-cp39-cp39-win32.whl", hash = "sha256:babf5acfede515f176833ed6028754cbcd0d206f7f614ea3447d67c33be12516"}, + {file = "pillow-10.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:0304004f8067386b477d20a518b50f3fa658a28d44e4116970abfcd94fac34a8"}, + {file = "pillow-10.2.0-cp39-cp39-win_arm64.whl", hash = "sha256:0fb3e7fc88a14eacd303e90481ad983fd5b69c761e9e6ef94c983f91025da869"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:322209c642aabdd6207517e9739c704dc9f9db943015535783239022002f054a"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3eedd52442c0a5ff4f887fab0c1c0bb164d8635b32c894bc1faf4c618dd89df2"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb28c753fd5eb3dd859b4ee95de66cc62af91bcff5db5f2571d32a520baf1f04"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:33870dc4653c5017bf4c8873e5488d8f8d5f8935e2f1fb9a2208c47cdd66efd2"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3c31822339516fb3c82d03f30e22b1d038da87ef27b6a78c9549888f8ceda39a"}, + {file = "pillow-10.2.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a2b56ba36e05f973d450582fb015594aaa78834fefe8dfb8fcd79b93e64ba4c6"}, + {file = "pillow-10.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d8e6aeb9201e655354b3ad049cb77d19813ad4ece0df1249d3c793de3774f8c7"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:2247178effb34a77c11c0e8ac355c7a741ceca0a732b27bf11e747bbc950722f"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15587643b9e5eb26c48e49a7b33659790d28f190fc514a322d55da2fb5c2950e"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753cd8f2086b2b80180d9b3010dd4ed147efc167c90d3bf593fe2af21265e5a5"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:7c8f97e8e7a9009bcacbe3766a36175056c12f9a44e6e6f2d5caad06dcfbf03b"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d1b35bcd6c5543b9cb547dee3150c93008f8dd0f1fef78fc0cd2b141c5baf58a"}, + {file = "pillow-10.2.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe4c15f6c9285dc54ce6553a3ce908ed37c8f3825b5a51a15c91442bb955b868"}, + {file = "pillow-10.2.0.tar.gz", hash = "sha256:e87f0b2c78157e12d7686b27d63c070fd65d994e8ddae6f328e0dcf4a0cd007e"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "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 = "pyparsing" +version = "3.1.2" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +optional = false +python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.1.2-py3-none-any.whl", hash = "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"}, + {file = "pyparsing-3.1.2.tar.gz", hash = "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + +[[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 = "pytz" +version = "2024.1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, +] + [[package]] name = "pyyaml" version = "6.0.1" @@ -418,6 +929,38 @@ files = [ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] +[[package]] +name = "seaborn" +version = "0.13.2" +description = "Statistical data visualization" +optional = false +python-versions = ">=3.8" +files = [ + {file = "seaborn-0.13.2-py3-none-any.whl", hash = "sha256:636f8336facf092165e27924f223d3c62ca560b1f2bb5dff7ab7fad265361987"}, + {file = "seaborn-0.13.2.tar.gz", hash = "sha256:93e60a40988f4d65e9f4885df477e2fdaff6b73a9ded434c1ab356dd57eefff7"}, +] + +[package.dependencies] +matplotlib = ">=3.4,<3.6.1 || >3.6.1" +numpy = ">=1.20,<1.24.0 || >1.24.0" +pandas = ">=1.2" + +[package.extras] +dev = ["flake8", "flit", "mypy", "pandas-stubs", "pre-commit", "pytest", "pytest-cov", "pytest-xdist"] +docs = ["ipykernel", "nbconvert", "numpydoc", "pydata_sphinx_theme (==0.10.0rc2)", "pyyaml", "sphinx (<6.0.0)", "sphinx-copybutton", "sphinx-design", "sphinx-issues"] +stats = ["scipy (>=1.7)", "statsmodels (>=0.12)"] + +[[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 = "sympy" version = "1.12" @@ -524,7 +1067,18 @@ files = [ {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"}, ] +[[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"}, +] + [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "7194030eae82d61f2ea53c977a29252bb3d9c27bbb0aa6b36864904d5ed7a418" +content-hash = "1108345c24c1b7267e0885e7f52c43aa483a82b17443795a9745a03147fbc654" diff --git a/pyproject.toml b/pyproject.toml index f218ceba..be55d75e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,6 +26,8 @@ python = "^3.11" torch = "^2.2.1" numpy = "^1.26.4" pyyaml = "^6.0.1" +matplotlib = "^3.8.3" +seaborn = "^0.13.2" [tool.poetry] name = "gpudrive" diff --git a/scripts/benchmark.py b/scripts/benchmark.py index 2c9a0e85..734fef1b 100644 --- a/scripts/benchmark.py +++ b/scripts/benchmark.py @@ -7,10 +7,14 @@ import yaml def run_benchmark(sim: SimManager, config: dict): + shape = sim.shape_tensor().to_torch() - num_agents, num_roads = shape[0].flatten().tolist() + useful_num_agents, useful_num_roads = shape[0].flatten().tolist() num_envs = shape.shape[0] + actual_num_agents = sim.self_observation_tensor().to_torch().shape[1] + actual_num_roads = sim.map_observation_tensor().to_torch().shape[1] + start = perf_counter() for i in range(0): sim.reset(i) @@ -22,10 +26,10 @@ def run_benchmark(sim: SimManager, config: dict): time_to_step = perf_counter() - start fps = (91 / time_to_step) * num_envs - afps = fps * num_agents + afps = fps * actual_num_agents - print(f"num_agents: {num_agents}, num_roads: {num_roads}, num_envs: {num_envs}, time_to_reset: {time_to_reset}, time_to_step: {time_to_step}, fps: {fps}, afps: {afps}, exec_mode: {config['sim_manager']['exec_mode']}, datasetInitOptions: {config['parameters']['datasetInitOptions']}") + print(f"num_agents: {actual_num_agents}, num_roads: {actual_num_roads}, num_envs: {num_envs}, time_to_reset: {time_to_reset}, time_to_step: {time_to_step}, fps: {fps}, afps: {afps}, exec_mode: {config['sim_manager']['exec_mode']}, datasetInitOptions: {config['parameters']['datasetInitOptions']}") # check if benchmark_results.csv exists try: with open('benchmark_results.csv', mode='r') as file: @@ -33,17 +37,19 @@ def run_benchmark(sim: SimManager, config: dict): except FileNotFoundError: with open('benchmark_results.csv', mode='w') as file: writer = csv.writer(file) - writer.writerow(['num_agents', 'num_roads', 'num_envs', 'time_to_reset', 'time_to_step', 'fps', 'afps', 'exec_mode', 'datasetInitOptions']) + writer.writerow(['actual_num_agents', 'actual_num_roads', 'useful_num_agents', 'useful_num_roads', 'num_envs', 'time_to_reset', 'time_to_step', 'fps', 'afps', 'exec_mode', 'datasetInitOptions']) with open('benchmark_results.csv', mode='a') as file: writer = csv.writer(file) - writer.writerow([num_agents, num_roads, num_envs, time_to_reset, time_to_step, fps, afps, config['sim_manager']['exec_mode'], config['parameters']['datasetInitOptions']]) + writer.writerow([actual_num_agents, actual_num_roads, useful_num_agents, useful_num_roads, num_envs, time_to_reset, time_to_step, fps, afps, config['sim_manager']['exec_mode'], config['parameters']['datasetInitOptions']]) if __name__ == "__main__": + # Export the parser = argparse.ArgumentParser(description='GPUDrive Benchmarking Tool') - parser.add_argument('--datasetPath', type=str, help='Path to the dataset', default='/home/aarav/gpudrive/config.yml') - parser.add_argument('--numEnvs', type=int, help='Number of environments', default=1) + parser.add_argument('--datasetPath', type=str, help='Path to the config file', default='/home/aarav/gpudrive/config.yml', required=False) + parser.add_argument('--numEnvs', type=int, help='Number of environments', default=2, required=False) + parser.add_argument('--randomized', type=bool, help='Randomize the dataset', default=False, required=False) args = parser.parse_args() with open(args.datasetPath, 'r') as file: config = yaml.safe_load(file) diff --git a/scripts/run_bench.py b/scripts/run_bench.py new file mode 100644 index 00000000..74e4b108 --- /dev/null +++ b/scripts/run_bench.py @@ -0,0 +1,47 @@ +import os +import argparse +import subprocess +from tqdm import tqdm +import yaml + +# def run_bench(total_num_envs: int): +# for numEnvs in tqdm(range(1, total_num_envs + 1), desc="Overall progress", unit="env"): +# if(args.randomized): +# for _ in range(1,100): +# command = f"MADRONA_MWGPU_KERNEL_CACHE=./gpudrive_cache python scripts/benchmark.py --numEnvs {numEnvs} --datasetPath config.yml" +# subprocess.run(command, shell=True, check=True) +# else: +# command = f"MADRONA_MWGPU_KERNEL_CACHE=./gpudrive_cache python scripts/benchmark.py --numEnvs {numEnvs} --datasetPath config.yml" +# subprocess.run(command, shell=True, check=True) + +def run_bench(total_num_envs: int, args): + for numEnvs in tqdm(range(1, total_num_envs + 1), desc="Overall progress", unit="env", position=0): + if args.randomized: + with tqdm(total=99, desc=f"Inner progress for numEnvs={numEnvs}", unit="run", leave=False, position=1) as pbar: + for _ in range(1, 100): + command = f"MADRONA_MWGPU_KERNEL_CACHE=./gpudrive_cache python scripts/benchmark.py --numEnvs {numEnvs} --datasetPath config.yml" + try: + subprocess.run(command, shell=True, check=True) + except subprocess.CalledProcessError: + pass + pbar.update(1) + else: + command = f"MADRONA_MWGPU_KERNEL_CACHE=./gpudrive_cache python scripts/benchmark.py --numEnvs {numEnvs} --datasetPath config.yml" + subprocess.run(command, shell=True, check=True) + + +def modifyConfigToRandomize(config_path: str): + with open(config_path, 'r') as file: + config = yaml.safe_load(file) + config['parameters']['datasetInitOptions'] = "RandomN" + with open(config_path, 'w') as file: + yaml.dump(config, file) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='GPUDrive Benchmarking Tool') + parser.add_argument('--totalNumEnvs', type=int, help='Number of environments', default=150, required=False) + parser.add_argument('--randomized', help='Randomize the dataset', action='store_true', required=False) + args = parser.parse_args() + if(args.randomized): + modifyConfigToRandomize('config.yml') + run_bench(args.totalNumEnvs, args) \ No newline at end of file diff --git a/src/consts.hpp b/src/consts.hpp index 73301805..5d422275 100644 --- a/src/consts.hpp +++ b/src/consts.hpp @@ -8,8 +8,8 @@ namespace gpudrive { namespace consts { -inline constexpr madrona::CountT kMaxAgentCount = 200; -inline constexpr madrona::CountT kMaxRoadEntityCount = 2000; +inline constexpr madrona::CountT kMaxAgentCount = 360; +inline constexpr madrona::CountT kMaxRoadEntityCount = 2400; // Various world / entity size parameters inline constexpr float worldLength = 40.f; From 52f247c79cb2bd3c68e365edc5b1af2665303fe4 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Sun, 17 Mar 2024 21:43:23 -0400 Subject: [PATCH 31/33] run bench --- scripts/run_bench.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/scripts/run_bench.py b/scripts/run_bench.py index 74e4b108..3afba833 100644 --- a/scripts/run_bench.py +++ b/scripts/run_bench.py @@ -30,18 +30,25 @@ def run_bench(total_num_envs: int, args): subprocess.run(command, shell=True, check=True) -def modifyConfigToRandomize(config_path: str): - with open(config_path, 'r') as file: - config = yaml.safe_load(file) - config['parameters']['datasetInitOptions'] = "RandomN" - with open(config_path, 'w') as file: - yaml.dump(config, file) +def modifyConfigToRandomize(randomize: bool): + if(randomize): + with open(config_path, 'r') as file: + config = yaml.safe_load(file) + config['parameters']['datasetInitOptions'] = "RandomN" + with open(config_path, 'w') as file: + yaml.dump(config, file) + else: + with open(config_path, 'r') as file: + config = yaml.safe_load(file) + config['parameters']['datasetInitOptions'] = "FirstN" + with open(config_path, 'w') as file: + yaml.dump(config, file) + if __name__ == "__main__": parser = argparse.ArgumentParser(description='GPUDrive Benchmarking Tool') parser.add_argument('--totalNumEnvs', type=int, help='Number of environments', default=150, required=False) parser.add_argument('--randomized', help='Randomize the dataset', action='store_true', required=False) args = parser.parse_args() - if(args.randomized): - modifyConfigToRandomize('config.yml') + modifyConfigToRandomize(args.randomized) run_bench(args.totalNumEnvs, args) \ No newline at end of file From 812d631041451ee7810075c1bdb2bb07c81e0c81 Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Sun, 17 Mar 2024 21:45:07 -0400 Subject: [PATCH 32/33] fix run bench --- run_bench.sh | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/run_bench.sh b/run_bench.sh index 0d82ae21..61da9726 100755 --- a/run_bench.sh +++ b/run_bench.sh @@ -1,13 +1,28 @@ #!/bin/bash +# FOR FIRSTN # Loop from 1 to 30 to set the numEnvs value -for numEnvs in {1..30}; do +for numEnvs in {1..150}; do echo "Running benchmarks for numEnvs = $numEnvs" - - # Inner loop to run the command 20 times for each numEnvs value - for run in {1..20}; do - echo "Iteration $run for numEnvs = $numEnvs" - python scripts/benchmark.py --numEnvs "$numEnvs" - done - + + MADRONA_MWGPU_KERNEL_CACHE=./gpudrive_cache python scripts/benchmark.py --numEnvs "$numEnvs" done + + +#For RANDOMN +# echo "1..$numEnvsRange" | pv -p -s $numEnvsRange | while read numEnvs; do +# echo "Running benchmarks for numEnvs = $numEnvs" +# for i in $(seq 1 100); do +# MADRONA_MWGPU_KERNEL_CACHE=./gpudrive_cache python scripts/benchmark.py --numEnvs "$numEnvs" +# done +# done + +#!/bin/bash + +# Use seq to generate a range and pipe it through tqdm for the progress bar +# seq 1 150 | tqdm --total=150 | while read numEnvs; do +# echo "Running benchmarks for numEnvs = $numEnvs" +# for i in {1..100}; do +# MADRONA_MWGPU_KERNEL_CACHE=./gpudrive_cache python scripts/benchmark.py --numEnvs "$numEnvs" +# done +# done From f024679836c75ac192eb194dc5f6274150b4defa Mon Sep 17 00:00:00 2001 From: Aarav Pandya Date: Tue, 19 Mar 2024 14:32:16 -0400 Subject: [PATCH 33/33] Save progress --- config.py | 13 +++-- config.yml | 6 +- poetry.lock | 2 +- pyproject.toml | 1 + scripts/dataset_binning.py | 110 +++++++++++++++++++++++++++++++++++++ scripts/run_bench.py | 16 ++++++ 6 files changed, 140 insertions(+), 8 deletions(-) create mode 100644 scripts/dataset_binning.py diff --git a/config.py b/config.py index c5640594..4e430c3b 100644 --- a/config.py +++ b/config.py @@ -3,14 +3,19 @@ import yaml from scripts.sim_utils.create import SimCreator import build - +import torch def get_constants(): fullpath = os.path.join(os.path.dirname(__file__), "config.yml") - sim = SimCreator(fullpath) - consts = sim.shape_tensor().to_torch()[0].flatten().tolist() + with open(fullpath, 'r') as file: + config = yaml.safe_load(file) + sim = SimCreator(config) + consts = sim.shape_tensor().to_torch() + max_agents = torch.max(consts[:, 0], 0).values.item() + max_roads = torch.max(consts[:, 1], 0).values.item() print(consts) - return consts + print(max_agents, max_roads) + return max_agents, max_roads def update_constants(filepath, new_max_agent_count, new_max_road_entity_count): with open(filepath, 'r') as file: diff --git a/config.yml b/config.yml index 720022fb..3738e94c 100644 --- a/config.yml +++ b/config.yml @@ -1,5 +1,5 @@ parameters: - datasetInitOptions: RandomN + datasetInitOptions: FirstN observationRadius: 1000.0 polylineReductionThreshold: 1.0 rewardParams: reward_params @@ -11,5 +11,5 @@ sim_manager: auto_reset: true exec_mode: CUDA gpu_id: 0 - json_path: /home/aarav/nocturne_data/formatted_json_v2_no_tl_valid - num_worlds: 5 + json_path: /home/aarav/nocturne_data/binned_jsons/bin_0 + num_worlds: 100 diff --git a/poetry.lock b/poetry.lock index a0e9e9c0..a11d02c5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1081,4 +1081,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.11" -content-hash = "1108345c24c1b7267e0885e7f52c43aa483a82b17443795a9745a03147fbc654" +content-hash = "34476c99046ff1c956b95930d99728125f0cbc8097bc95ef9e64ccdda6357b26" diff --git a/pyproject.toml b/pyproject.toml index be55d75e..d2ff9b39 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,6 +28,7 @@ numpy = "^1.26.4" pyyaml = "^6.0.1" matplotlib = "^3.8.3" seaborn = "^0.13.2" +pandas = "^2.2.1" [tool.poetry] name = "gpudrive" diff --git a/scripts/dataset_binning.py b/scripts/dataset_binning.py new file mode 100644 index 00000000..65a4d1c3 --- /dev/null +++ b/scripts/dataset_binning.py @@ -0,0 +1,110 @@ +from gpudrive import SimManager +from sim_utils.create import SimCreator + +import json +import os +import shutil +import yaml +import csv +from tqdm import tqdm +import pandas as pd + +VALID_FILES_PATH = "/home/aarav/nocturne_data/formatted_json_v2_no_tl_valid" +BINNING_TEMP_PATH = "/home/aarav/nocturne_data/binning_temp" +FINAL_BINNED_JSON_PATHS = "/home/aarav/nocturne_data/binned_jsons" +CSV_PATH = "/home/aarav/nocturne_data/datacsv.csv" + +def modify_valid_files_json(valid_files_path: str, file_path: str): + if(os.path.exists(valid_files_path + "/valid_files.json") == False): + with open(valid_files_path + "/valid_files.json", 'w') as file: + json.dump({}, file) + with open(valid_files_path + "/valid_files.json", 'r') as file: + valid_files = json.load(file) + valid_files.clear() + valid_files[file_path] = [] + with open(valid_files_path + "/valid_files.json", 'w') as file: + json.dump(valid_files, file) + +def delete_file_from_dest(file_path: str): + os.remove(file_path) + +def copy_file_to_dest(file_path: str, dest_path: str): + shutil.copy(file_path, dest_path) + return os.path.join(dest_path, os.path.basename(file_path)) + +def return_list_of_files(valid_files_path: str): + with open(valid_files_path + "/valid_files.json", 'r') as file: + valid_files = json.load(file) + file_list = [] + for file in valid_files: + file_list.append(os.path.join(valid_files_path, file)) + return file_list + +# def return_agent_numbers(sim: SimManager): +# shape = sim.shape_tensor().to_torch() +# num_agents, num_roads = shape[0].flatten().tolist() +# return num_agents, num_roads + +def return_agent_numbers(file_path: str): + with open(file_path, 'r') as file: + data = json.load(file) + num_agents = len(data['objects']) + num_roads = len(data['roads']) + num_road_segments = 0 + for road in data['roads']: + if(road['type'] == "road_edge" or road['type'] == "road_line" or road['type'] == "lane"): + num_road_segments += len(road['geometry']) - 1 + else: + num_road_segments += 1 + return num_agents, num_road_segments + +if __name__ == "__main__": + # with open("config.yml", 'r') as file: + # config = yaml.safe_load(file) + # config['sim_manager']['num_worlds'] = 1 + # config['sim_manager']['exec_mode'] = "CPU" + # config['sim_manager']['json_path'] = BINNING_TEMP_PATH + # file_list = return_list_of_files(VALID_FILES_PATH) + # file_meta_data = [] + # file_meta_data.append(["File Path", "Number of Agents", "Number of Roads"]) + # for file in tqdm(file_list): + # # currfile = copy_file_to_dest(file, BINNING_TEMP_PATH) + # # modify_valid_files_json(BINNING_TEMP_PATH, file) + # num_entities = return_agent_numbers(file) + # file_meta_data.append([file, num_entities[0], num_entities[1]]) + # # delete_file_from_dest(currfile) + + # with open(CSV_PATH, 'w') as file: + # writer = csv.writer(file) + # writer.writerows(file_meta_data) + + data = pd.read_csv(CSV_PATH) + sorted_data = data.sort_values('Number of Agents') + + bins = [] + bin_size = 100 + number_of_bins = len(sorted_data) // bin_size + (1 if len(sorted_data) % bin_size > 0 else 0) + + # Create bins of 100 files each + for i in range(number_of_bins): + bin_start = i * bin_size + bin_end = min((i + 1) * bin_size, len(sorted_data)) + bins.append(sorted_data.iloc[bin_start:bin_end]) + + if not os.path.exists(FINAL_BINNED_JSON_PATHS): + os.makedirs(FINAL_BINNED_JSON_PATHS) + + for i, bin in enumerate(bins): + if not os.path.exists(FINAL_BINNED_JSON_PATHS + f"/bin_{i}"): + os.makedirs(FINAL_BINNED_JSON_PATHS + f"/bin_{i}") + bin_folder = FINAL_BINNED_JSON_PATHS + f"/bin_{i}" + print(bin_folder) + d = {} + for index, row in bin.iterrows(): + file_path = row['File Path'] + d[file_path] = [row['Number of Agents'], row['Number of Roads']] + filepath = os.path.join(bin_folder, f"valid_files.json") + print(filepath) + with open(filepath, 'w') as file: + json.dump(d, file) + print("Binning complete") \ No newline at end of file diff --git a/scripts/run_bench.py b/scripts/run_bench.py index 3afba833..8a1cd742 100644 --- a/scripts/run_bench.py +++ b/scripts/run_bench.py @@ -15,6 +15,12 @@ # subprocess.run(command, shell=True, check=True) def run_bench(total_num_envs: int, args): + if args.binned: + num_bins = len(os.listdir("/home/aarav/nocturne_data/binned_jsons")) + for bin in range(1, num_bins + 1): + modifyConfigToBinned(bin) + command = f"MADRONA_MWGPU_KERNEL_CACHE=./gpudrive_cache python scripts/benchmark.py --numEnvs {total_num_envs} --datasetPath config.yml" + subprocess.run(command, shell=True, check=True) for numEnvs in tqdm(range(1, total_num_envs + 1), desc="Overall progress", unit="env", position=0): if args.randomized: with tqdm(total=99, desc=f"Inner progress for numEnvs={numEnvs}", unit="run", leave=False, position=1) as pbar: @@ -31,6 +37,7 @@ def run_bench(total_num_envs: int, args): def modifyConfigToRandomize(randomize: bool): + config_path = "config.yml" if(randomize): with open(config_path, 'r') as file: config = yaml.safe_load(file) @@ -44,11 +51,20 @@ def modifyConfigToRandomize(randomize: bool): with open(config_path, 'w') as file: yaml.dump(config, file) +def modifyConfigToBinned(bin: int): + config_path = "config.yml" + with open(config_path, 'r') as file: + config = yaml.safe_load(file) + config['sim_manager']['json_path'] = f"/home/aarav/nocturne_data/binned_jsons/bin_{bin}" + with open(config_path, 'w') as file: + yaml.dump(config, file) + if __name__ == "__main__": parser = argparse.ArgumentParser(description='GPUDrive Benchmarking Tool') parser.add_argument('--totalNumEnvs', type=int, help='Number of environments', default=150, required=False) parser.add_argument('--randomized', help='Randomize the dataset', action='store_true', required=False) + parser.add_argument('--binned', help='Use binned dataset', action='store_true', required=False) args = parser.parse_args() modifyConfigToRandomize(args.randomized) run_bench(args.totalNumEnvs, args) \ No newline at end of file