Compare commits
9 Commits
a4004fc6f7
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 66da8c9939 | |||
| cdc64afd1f | |||
| b1a1fb7c94 | |||
| 7a29ea46c0 | |||
| 508ece6074 | |||
| f50a36c4d0 | |||
| 6ea763f914 | |||
| 4a5ced1172 | |||
| ed876c9f91 |
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
__pycache__
|
||||||
|
.venv
|
||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
__pycache__
|
__pycache__
|
||||||
|
.venv
|
||||||
|
|||||||
9
.vscode/settings.json
vendored
Normal file
9
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"[python]": {
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.defaultFormatter": "charliermarsh.ruff",
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.organizeImports": "explicit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
9
Dockerfile
Normal file
9
Dockerfile
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
FROM python:3.12-slim
|
||||||
|
COPY --from=ghcr.io/astral-sh/uv:0.4.10 /uv /bin/uv
|
||||||
|
|
||||||
|
COPY uv.lock pyproject.toml ./
|
||||||
|
RUN uv sync --frozen
|
||||||
|
|
||||||
|
COPY ./simulation simulation
|
||||||
|
|
||||||
|
ENTRYPOINT [ "uv", "run", "python", "-m", "simulation.app" ]
|
||||||
19
Makefile
Normal file
19
Makefile
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
GIT_COMMIT_HASH := $(shell git rev-parse --short HEAD)
|
||||||
|
DOCKER_REGISTRY = registry.crapts.org
|
||||||
|
|
||||||
|
all: run
|
||||||
|
|
||||||
|
run:
|
||||||
|
uv run python -m simulation.app
|
||||||
|
|
||||||
|
docker/build:
|
||||||
|
docker build -t simulation:latest .
|
||||||
|
|
||||||
|
docker/run: docker/build
|
||||||
|
docker run -it --rm simulation
|
||||||
|
|
||||||
|
docker/push: docker/build
|
||||||
|
docker buildx rm builder
|
||||||
|
docker buildx create --name builder --driver docker-container --use
|
||||||
|
docker buildx build --platform linux/amd64,linux/arm64 --push -t $(DOCKER_REGISTRY)/simulation:latest .
|
||||||
|
docker buildx build --platform linux/amd64,linux/arm64 --push -t $(DOCKER_REGISTRY)/simulation:$(GIT_COMMIT_HASH) .
|
||||||
101
poetry.lock
generated
101
poetry.lock
generated
@@ -1,101 +0,0 @@
|
|||||||
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "numpy"
|
|
||||||
version = "2.0.1"
|
|
||||||
description = "Fundamental package for array computing in Python"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.9"
|
|
||||||
files = [
|
|
||||||
{file = "numpy-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0fbb536eac80e27a2793ffd787895242b7f18ef792563d742c2d673bfcb75134"},
|
|
||||||
{file = "numpy-2.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:69ff563d43c69b1baba77af455dd0a839df8d25e8590e79c90fcbe1499ebde42"},
|
|
||||||
{file = "numpy-2.0.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:1b902ce0e0a5bb7704556a217c4f63a7974f8f43e090aff03fcf262e0b135e02"},
|
|
||||||
{file = "numpy-2.0.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:f1659887361a7151f89e79b276ed8dff3d75877df906328f14d8bb40bb4f5101"},
|
|
||||||
{file = "numpy-2.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4658c398d65d1b25e1760de3157011a80375da861709abd7cef3bad65d6543f9"},
|
|
||||||
{file = "numpy-2.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4127d4303b9ac9f94ca0441138acead39928938660ca58329fe156f84b9f3015"},
|
|
||||||
{file = "numpy-2.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e5eeca8067ad04bc8a2a8731183d51d7cbaac66d86085d5f4766ee6bf19c7f87"},
|
|
||||||
{file = "numpy-2.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9adbd9bb520c866e1bfd7e10e1880a1f7749f1f6e5017686a5fbb9b72cf69f82"},
|
|
||||||
{file = "numpy-2.0.1-cp310-cp310-win32.whl", hash = "sha256:7b9853803278db3bdcc6cd5beca37815b133e9e77ff3d4733c247414e78eb8d1"},
|
|
||||||
{file = "numpy-2.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:81b0893a39bc5b865b8bf89e9ad7807e16717f19868e9d234bdaf9b1f1393868"},
|
|
||||||
{file = "numpy-2.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:75b4e316c5902d8163ef9d423b1c3f2f6252226d1aa5cd8a0a03a7d01ffc6268"},
|
|
||||||
{file = "numpy-2.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6e4eeb6eb2fced786e32e6d8df9e755ce5be920d17f7ce00bc38fcde8ccdbf9e"},
|
|
||||||
{file = "numpy-2.0.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:a1e01dcaab205fbece13c1410253a9eea1b1c9b61d237b6fa59bcc46e8e89343"},
|
|
||||||
{file = "numpy-2.0.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:a8fc2de81ad835d999113ddf87d1ea2b0f4704cbd947c948d2f5513deafe5a7b"},
|
|
||||||
{file = "numpy-2.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a3d94942c331dd4e0e1147f7a8699a4aa47dffc11bf8a1523c12af8b2e91bbe"},
|
|
||||||
{file = "numpy-2.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15eb4eca47d36ec3f78cde0a3a2ee24cf05ca7396ef808dda2c0ddad7c2bde67"},
|
|
||||||
{file = "numpy-2.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b83e16a5511d1b1f8a88cbabb1a6f6a499f82c062a4251892d9ad5d609863fb7"},
|
|
||||||
{file = "numpy-2.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f87fec1f9bc1efd23f4227becff04bd0e979e23ca50cc92ec88b38489db3b55"},
|
|
||||||
{file = "numpy-2.0.1-cp311-cp311-win32.whl", hash = "sha256:36d3a9405fd7c511804dc56fc32974fa5533bdeb3cd1604d6b8ff1d292b819c4"},
|
|
||||||
{file = "numpy-2.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:08458fbf403bff5e2b45f08eda195d4b0c9b35682311da5a5a0a0925b11b9bd8"},
|
|
||||||
{file = "numpy-2.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6bf4e6f4a2a2e26655717a1983ef6324f2664d7011f6ef7482e8c0b3d51e82ac"},
|
|
||||||
{file = "numpy-2.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6fddc5fe258d3328cd8e3d7d3e02234c5d70e01ebe377a6ab92adb14039cb4"},
|
|
||||||
{file = "numpy-2.0.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:5daab361be6ddeb299a918a7c0864fa8618af66019138263247af405018b04e1"},
|
|
||||||
{file = "numpy-2.0.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:ea2326a4dca88e4a274ba3a4405eb6c6467d3ffbd8c7d38632502eaae3820587"},
|
|
||||||
{file = "numpy-2.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:529af13c5f4b7a932fb0e1911d3a75da204eff023ee5e0e79c1751564221a5c8"},
|
|
||||||
{file = "numpy-2.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6790654cb13eab303d8402354fabd47472b24635700f631f041bd0b65e37298a"},
|
|
||||||
{file = "numpy-2.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cbab9fc9c391700e3e1287666dfd82d8666d10e69a6c4a09ab97574c0b7ee0a7"},
|
|
||||||
{file = "numpy-2.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:99d0d92a5e3613c33a5f01db206a33f8fdf3d71f2912b0de1739894668b7a93b"},
|
|
||||||
{file = "numpy-2.0.1-cp312-cp312-win32.whl", hash = "sha256:173a00b9995f73b79eb0191129f2455f1e34c203f559dd118636858cc452a1bf"},
|
|
||||||
{file = "numpy-2.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:bb2124fdc6e62baae159ebcfa368708867eb56806804d005860b6007388df171"},
|
|
||||||
{file = "numpy-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bfc085b28d62ff4009364e7ca34b80a9a080cbd97c2c0630bb5f7f770dae9414"},
|
|
||||||
{file = "numpy-2.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8fae4ebbf95a179c1156fab0b142b74e4ba4204c87bde8d3d8b6f9c34c5825ef"},
|
|
||||||
{file = "numpy-2.0.1-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:72dc22e9ec8f6eaa206deb1b1355eb2e253899d7347f5e2fae5f0af613741d06"},
|
|
||||||
{file = "numpy-2.0.1-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:ec87f5f8aca726117a1c9b7083e7656a9d0d606eec7299cc067bb83d26f16e0c"},
|
|
||||||
{file = "numpy-2.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f682ea61a88479d9498bf2091fdcd722b090724b08b31d63e022adc063bad59"},
|
|
||||||
{file = "numpy-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8efc84f01c1cd7e34b3fb310183e72fcdf55293ee736d679b6d35b35d80bba26"},
|
|
||||||
{file = "numpy-2.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3fdabe3e2a52bc4eff8dc7a5044342f8bd9f11ef0934fcd3289a788c0eb10018"},
|
|
||||||
{file = "numpy-2.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:24a0e1befbfa14615b49ba9659d3d8818a0f4d8a1c5822af8696706fbda7310c"},
|
|
||||||
{file = "numpy-2.0.1-cp39-cp39-win32.whl", hash = "sha256:f9cf5ea551aec449206954b075db819f52adc1638d46a6738253a712d553c7b4"},
|
|
||||||
{file = "numpy-2.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:e9e81fa9017eaa416c056e5d9e71be93d05e2c3c2ab308d23307a8bc4443c368"},
|
|
||||||
{file = "numpy-2.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:61728fba1e464f789b11deb78a57805c70b2ed02343560456190d0501ba37b0f"},
|
|
||||||
{file = "numpy-2.0.1-pp39-pypy39_pp73-macosx_14_0_x86_64.whl", hash = "sha256:12f5d865d60fb9734e60a60f1d5afa6d962d8d4467c120a1c0cda6eb2964437d"},
|
|
||||||
{file = "numpy-2.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eacf3291e263d5a67d8c1a581a8ebbcfd6447204ef58828caf69a5e3e8c75990"},
|
|
||||||
{file = "numpy-2.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2c3a346ae20cfd80b6cfd3e60dc179963ef2ea58da5ec074fd3d9e7a1e7ba97f"},
|
|
||||||
{file = "numpy-2.0.1.tar.gz", hash = "sha256:485b87235796410c3519a699cfe1faab097e509e90ebb05dcd098db2ae87e7b3"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "polars"
|
|
||||||
version = "1.4.1"
|
|
||||||
description = "Blazingly fast DataFrame library"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "polars-1.4.1-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:f02fc6a5c63dd86cfeb159caa66112e477c69fc7800a28e64609ac2780554865"},
|
|
||||||
{file = "polars-1.4.1-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:bd2acd8b1977f61b9587c8d47d16f101e7e73edd8cdeb3a8a725f15f181cd120"},
|
|
||||||
{file = "polars-1.4.1-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cf834a328e292c31c06eb606496becb6d8a795e927c826e26e2af27087950f1"},
|
|
||||||
{file = "polars-1.4.1-cp38-abi3-manylinux_2_24_aarch64.whl", hash = "sha256:64eabf0ef7ac0d17fe15361e7daaeb4425a875d2d760c17d96803e9ac8bee244"},
|
|
||||||
{file = "polars-1.4.1-cp38-abi3-win_amd64.whl", hash = "sha256:2313d63ecfa1d9f1e740b9fcabb8ae45d9d0b5acf1ddb401951daba4c0f3f74f"},
|
|
||||||
{file = "polars-1.4.1.tar.gz", hash = "sha256:ed8009aff8cf91f94db5a38d947185603ad5bee48a28b764cf5a52048c7c4756"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
adbc = ["adbc-driver-manager[dbapi]", "adbc-driver-sqlite[dbapi]"]
|
|
||||||
all = ["polars[async,cloudpickle,database,deltalake,excel,fsspec,graph,iceberg,numpy,pandas,plot,pyarrow,pydantic,style,timezone]"]
|
|
||||||
async = ["gevent"]
|
|
||||||
calamine = ["fastexcel (>=0.9)"]
|
|
||||||
cloudpickle = ["cloudpickle"]
|
|
||||||
connectorx = ["connectorx (>=0.3.2)"]
|
|
||||||
database = ["nest-asyncio", "polars[adbc,connectorx,sqlalchemy]"]
|
|
||||||
deltalake = ["deltalake (>=0.15.0)"]
|
|
||||||
excel = ["polars[calamine,openpyxl,xlsx2csv,xlsxwriter]"]
|
|
||||||
fsspec = ["fsspec"]
|
|
||||||
gpu = ["cudf-polars-cu12"]
|
|
||||||
graph = ["matplotlib"]
|
|
||||||
iceberg = ["pyiceberg (>=0.5.0)"]
|
|
||||||
numpy = ["numpy (>=1.16.0)"]
|
|
||||||
openpyxl = ["openpyxl (>=3.0.0)"]
|
|
||||||
pandas = ["pandas", "polars[pyarrow]"]
|
|
||||||
plot = ["hvplot (>=0.9.1)", "polars[pandas]"]
|
|
||||||
pyarrow = ["pyarrow (>=7.0.0)"]
|
|
||||||
pydantic = ["pydantic"]
|
|
||||||
sqlalchemy = ["polars[pandas]", "sqlalchemy"]
|
|
||||||
style = ["great-tables (>=0.8.0)"]
|
|
||||||
timezone = ["backports-zoneinfo", "tzdata"]
|
|
||||||
xlsx2csv = ["xlsx2csv (>=0.8.0)"]
|
|
||||||
xlsxwriter = ["xlsxwriter"]
|
|
||||||
|
|
||||||
[metadata]
|
|
||||||
lock-version = "2.0"
|
|
||||||
python-versions = "^3.10"
|
|
||||||
content-hash = "3b5f1c763a56f03ec547b2513ce2ef1a9935ac6df8a8caca8288795aee44cbbf"
|
|
||||||
@@ -1,16 +1,12 @@
|
|||||||
[tool.poetry]
|
[project]
|
||||||
name = "simulation"
|
name = "simulation"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
description = ""
|
description = "Add your description here"
|
||||||
authors = ["Marco Crapts <mcrapts@gmail.com>"]
|
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.12"
|
||||||
[tool.poetry.dependencies]
|
dependencies = [
|
||||||
python = "^3.10"
|
"numpy>=2.1.1",
|
||||||
numpy = "^2.0.1"
|
"polars>=1.7.1",
|
||||||
polars = "^1.4.1"
|
"pydantic-settings>=2.5.2",
|
||||||
|
"tqdm>=4.66.5",
|
||||||
|
]
|
||||||
[build-system]
|
|
||||||
requires = ["poetry-core"]
|
|
||||||
build-backend = "poetry.core.masonry.api"
|
|
||||||
|
|||||||
@@ -1,61 +1,149 @@
|
|||||||
from dataclasses import asdict, dataclass
|
import os
|
||||||
|
import random
|
||||||
|
from concurrent.futures import ProcessPoolExecutor, as_completed
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import polars as pl
|
import polars as pl
|
||||||
|
from pydantic import Field, field_validator
|
||||||
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
from simulation.lib import Process, Simulation
|
from simulation.lib import Process, Simulation
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
class Settings(BaseSettings):
|
||||||
class Customer:
|
model_config = SettingsConfigDict(cli_parse_args=True)
|
||||||
arrived_at: float
|
|
||||||
started_at: float | None = None
|
workers: int = Field(default="auto")
|
||||||
handling_time: float | None = None
|
|
||||||
finished_at: float | None = None
|
@field_validator("workers", mode="before")
|
||||||
|
def check_workers(cls, value):
|
||||||
|
if value == "auto":
|
||||||
|
return max((os.cpu_count() or 0) - 1, 1)
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
customers_unhandled: list[Customer] = []
|
print("Settings: ", Settings().model_dump())
|
||||||
customers_in_progress: list[Customer] = []
|
|
||||||
customers_handled: list[Customer] = []
|
|
||||||
|
|
||||||
|
|
||||||
class Server(Process):
|
def run_simulation(n_servers=2, lam=40):
|
||||||
def run(self):
|
@dataclass
|
||||||
while True:
|
class Customer:
|
||||||
if len(customers_unhandled) > 0:
|
arrived_at: float
|
||||||
customer = customers_unhandled[0]
|
started_at: float | None = None
|
||||||
customers_unhandled.remove(customer)
|
handling_time: float | None = None
|
||||||
customers_in_progress.append(customer)
|
finished_at: float | None = None
|
||||||
customer.started_at = self.simulation.clock
|
|
||||||
handling_time = float(max(0, np.random.normal(5, 2.5, size=1)[0]))
|
customers_unhandled: list[Customer] = []
|
||||||
yield from self.hold(handling_time)
|
customers_in_progress: list[Customer] = []
|
||||||
customer.handling_time = handling_time
|
customers_handled: list[Customer] = []
|
||||||
customer.finished_at = self.simulation.clock
|
|
||||||
customers_in_progress.remove(customer)
|
class Server(Process):
|
||||||
customers_handled.append(customer)
|
def run(self):
|
||||||
self.simulation.log(f"unhandled customers: {len(customers_unhandled)}")
|
while True:
|
||||||
else:
|
if len(customers_unhandled) > 0:
|
||||||
yield from self.suspend()
|
customer = customers_unhandled[0]
|
||||||
|
customers_unhandled.remove(customer)
|
||||||
|
customers_in_progress.append(customer)
|
||||||
|
customer.started_at = self.simulation.clock
|
||||||
|
handling_time = float(max(0, np.random.normal(5, 2.5, size=1)[0]))
|
||||||
|
yield from self.hold(handling_time)
|
||||||
|
customer.handling_time = handling_time
|
||||||
|
customer.finished_at = self.simulation.clock
|
||||||
|
customers_in_progress.remove(customer)
|
||||||
|
customers_handled.append(customer)
|
||||||
|
self.simulation.log(
|
||||||
|
f"unhandled customers: {len(customers_unhandled)}"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
yield from self.suspend()
|
||||||
|
|
||||||
|
class CustomerGenerator(Process):
|
||||||
|
def __init__(self, lam=40, servers=[]):
|
||||||
|
self.lam = lam
|
||||||
|
self.servers = servers
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
while True:
|
||||||
|
wait_for = float(
|
||||||
|
max(0, (np.random.poisson(lam=self.lam, size=1) / 10)[0])
|
||||||
|
)
|
||||||
|
customer = Customer(arrived_at=self.simulation.clock)
|
||||||
|
customers_unhandled.append(customer)
|
||||||
|
for server in self.servers:
|
||||||
|
server.resume()
|
||||||
|
yield from self.hold(wait_for)
|
||||||
|
|
||||||
|
servers = [Server() for _ in range(n_servers)]
|
||||||
|
simulation = Simulation(
|
||||||
|
processes=[CustomerGenerator(servers=servers, lam=lam), *servers],
|
||||||
|
enable_logging=False,
|
||||||
|
)
|
||||||
|
simulation.start()
|
||||||
|
|
||||||
|
df_customers = pl.DataFrame(
|
||||||
|
[customer.__dict__ for customer in customers_handled]
|
||||||
|
).with_columns(queue_time=pl.col("started_at") - pl.col("arrived_at"))
|
||||||
|
|
||||||
|
df_servers = pl.DataFrame([server.__dict__ for server in servers])
|
||||||
|
|
||||||
|
utilization = {
|
||||||
|
f"utilization_server_{key}": value
|
||||||
|
for key, value in dict(
|
||||||
|
zip(df_servers["id"].to_list(), df_servers["utilization"].to_list())
|
||||||
|
).items()
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
"n_servers": n_servers,
|
||||||
|
"lam": lam,
|
||||||
|
"queue_time": df_customers["queue_time"].mean(),
|
||||||
|
"handling_time": df_customers["handling_time"].mean(),
|
||||||
|
**utilization,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class CustomerGenerator(Process):
|
if __name__ == "__main__":
|
||||||
def run(self):
|
with ProcessPoolExecutor(max_workers=Settings().workers) as executor:
|
||||||
while True:
|
n_servers = [n + 1 for n in range(10)]
|
||||||
wait_for = float(max(0, (np.random.poisson(lam=40, size=1) / 10)[0]))
|
lam = [(n + 1) * 4 for n in range(10)]
|
||||||
customer = Customer(arrived_at=self.simulation.clock)
|
parameter_values = [
|
||||||
customers_unhandled.append(customer)
|
{"lam": m, "n_servers": n}
|
||||||
for server in servers:
|
for m in lam
|
||||||
server.resume()
|
for n in n_servers
|
||||||
yield from self.hold(wait_for)
|
for _ in range(100)
|
||||||
|
]
|
||||||
|
futures = [
|
||||||
|
executor.submit(run_simulation, **parameters)
|
||||||
|
for parameters in random.sample(parameter_values, len(parameter_values))
|
||||||
|
]
|
||||||
|
|
||||||
|
results = []
|
||||||
|
for future in tqdm(as_completed(futures), total=len(parameter_values)):
|
||||||
|
result = future.result()
|
||||||
|
results.append(result)
|
||||||
|
|
||||||
servers = [Server() for _ in range(2)]
|
df = (
|
||||||
simulation = Simulation(processes=[CustomerGenerator(), *servers])
|
pl.DataFrame(results)
|
||||||
simulation.start()
|
.fill_null(0)
|
||||||
|
.group_by(["n_servers", "lam"])
|
||||||
|
.agg(pl.all().mean())
|
||||||
|
.sort(["n_servers", "lam"])
|
||||||
|
)
|
||||||
|
|
||||||
df = pl.DataFrame([asdict(customer) for customer in customers_handled]).with_columns(
|
df_queue_time = df.pivot("lam", index="n_servers", values="queue_time").sort(
|
||||||
queue_time=pl.col('started_at') - pl.col('arrived_at')
|
"n_servers"
|
||||||
)
|
)
|
||||||
|
|
||||||
print(f"\nservers: {len(servers)}")
|
def stats(column):
|
||||||
print(df[["queue_time", "handling_time"]].mean())
|
return (
|
||||||
|
df.pivot("lam", index="n_servers", values=column)
|
||||||
|
.sort("n_servers")
|
||||||
|
.with_columns(pl.all().round(2))
|
||||||
|
)
|
||||||
|
|
||||||
|
pl.Config.set_tbl_cols(20)
|
||||||
|
print(df)
|
||||||
|
print(stats("queue_time"))
|
||||||
|
print(stats("utilization_server_1"))
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ from typing import Any, Generator, Protocol
|
|||||||
|
|
||||||
class BaseSimulation:
|
class BaseSimulation:
|
||||||
clock: float
|
clock: float
|
||||||
|
enable_logging: bool
|
||||||
|
|
||||||
def log(self, msg):
|
def log(self, msg):
|
||||||
print(f"{'{:.2f}'.format(self.clock)}: {msg}")
|
if self.enable_logging:
|
||||||
pass
|
print(f"{'{:.2f}'.format(self.clock)}: {msg}")
|
||||||
|
|
||||||
|
|
||||||
class BaseProcess(Protocol):
|
class BaseProcess(Protocol):
|
||||||
@@ -17,19 +18,33 @@ class Process(BaseProcess):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.id: int = 1
|
self.id: int = 1
|
||||||
self.simulation = BaseSimulation()
|
self.simulation = BaseSimulation()
|
||||||
|
self.started_at: float = 0
|
||||||
self.resume_at: float = 0
|
self.resume_at: float = 0
|
||||||
|
self.time_active: float = 0
|
||||||
|
self.utilization: float = 0
|
||||||
self.suspended = False
|
self.suspended = False
|
||||||
self._gen = self.run()
|
self._gen = self.run()
|
||||||
|
|
||||||
@property
|
def start(self, simulation, id):
|
||||||
def name(self):
|
self.id = id
|
||||||
return f"{self.__class__.__name__} {self.id}"
|
self.started_at = simulation.clock
|
||||||
|
self.simulation = simulation
|
||||||
|
|
||||||
def hold(self, hold_for: float):
|
def hold(self, hold_for: float):
|
||||||
hold_for_formatted = "{:.2f}".format(hold_for)
|
hold_for_formatted = "{:.2f}".format(hold_for)
|
||||||
self.simulation.log(f"holding {self.name} for {hold_for_formatted} seconds")
|
self.simulation.log(f"holding {self.name} for {hold_for_formatted} seconds")
|
||||||
self.resume_at = self.simulation.clock + hold_for
|
self.resume_at = self.simulation.clock + hold_for
|
||||||
|
t_start = self.simulation.clock
|
||||||
yield
|
yield
|
||||||
|
t_end = self.simulation.clock
|
||||||
|
self.time_active += t_end - t_start
|
||||||
|
try:
|
||||||
|
self.utilization = self.time_active / (
|
||||||
|
self.simulation.clock - self.started_at
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
if self.simulation.enable_logging:
|
||||||
|
print(e)
|
||||||
|
|
||||||
def suspend(self):
|
def suspend(self):
|
||||||
self.suspended = True
|
self.suspended = True
|
||||||
@@ -42,11 +57,16 @@ class Process(BaseProcess):
|
|||||||
self.suspended = False
|
self.suspended = False
|
||||||
next(self._gen)
|
next(self._gen)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return f"{self.__class__.__name__} {self.id}"
|
||||||
|
|
||||||
|
|
||||||
class Simulation(BaseSimulation):
|
class Simulation(BaseSimulation):
|
||||||
def __init__(self, processes: list[Process]):
|
def __init__(self, processes: list[Process], enable_logging=True):
|
||||||
self.clock = 0
|
self.clock = 0
|
||||||
self.processes = []
|
self.processes = []
|
||||||
|
self.enable_logging = enable_logging
|
||||||
for process in processes:
|
for process in processes:
|
||||||
self.register_process(process)
|
self.register_process(process)
|
||||||
|
|
||||||
@@ -56,8 +76,7 @@ class Simulation(BaseSimulation):
|
|||||||
for p in self.processes
|
for p in self.processes
|
||||||
if p.__class__.__name__ == process.__class__.__name__
|
if p.__class__.__name__ == process.__class__.__name__
|
||||||
]
|
]
|
||||||
process.id = 1 + len(processes_with_same_class)
|
process.start(simulation=self, id=1 + len(processes_with_same_class))
|
||||||
process.simulation = self
|
|
||||||
self.processes.append(process)
|
self.processes.append(process)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|||||||
184
uv.lock
generated
Normal file
184
uv.lock
generated
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
version = 1
|
||||||
|
requires-python = ">=3.12"
|
||||||
|
resolution-markers = [
|
||||||
|
"python_full_version < '3.13'",
|
||||||
|
"python_full_version >= '3.13'",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "annotated-types"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorama"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "numpy"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/59/5f/9003bb3e632f2b58f5e3a3378902dcc73c5518070736c6740fe52454e8e1/numpy-2.1.1.tar.gz", hash = "sha256:d0cf7d55b1051387807405b3898efafa862997b4cba8aa5dbe657be794afeafd", size = 18874860 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/36/11/c573ef66c004f991989c2c6218229d9003164525549409aec5ec9afc0285/numpy-2.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c803b7934a7f59563db459292e6aa078bb38b7ab1446ca38dd138646a38203e", size = 20884403 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6b/6c/a9fbef5fd2f9685212af2a9e47485cde9357c3e303e079ccf85127516f2d/numpy-2.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6435c48250c12f001920f0751fe50c0348f5f240852cfddc5e2f97e007544cbe", size = 13493375 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/34/f2/1316a6b08ad4c161d793abe81ff7181e9ae2e357a5b06352a383b9f8e800/numpy-2.1.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:3269c9eb8745e8d975980b3a7411a98976824e1fdef11f0aacf76147f662b15f", size = 5088823 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/be/15/fabf78a6d4a10c250e87daf1cd901af05e71501380532ac508879cc46a7e/numpy-2.1.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:fac6e277a41163d27dfab5f4ec1f7a83fac94e170665a4a50191b545721c6521", size = 6619825 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9f/8a/76ddef3e621541ddd6984bc24d256a4e3422d036790cbbe449e6cad439ee/numpy-2.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcd8f556cdc8cfe35e70efb92463082b7f43dd7e547eb071ffc36abc0ca4699b", size = 13696705 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cb/22/2b840d297183916a95847c11f82ae11e248fa98113490b2357f774651e1d/numpy-2.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b9cd92c8f8e7b313b80e93cedc12c0112088541dcedd9197b5dee3738c1201", size = 16041649 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c7/e8/6f4825d8f576cfd5e4d6515b9eec22bd618868bdafc8a8c08b446dcb65f0/numpy-2.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:afd9c680df4de71cd58582b51e88a61feed4abcc7530bcd3d48483f20fc76f2a", size = 16409358 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bf/f8/5edf1105b0dc24fd66fc3e9e7f3bca3d920cde571caaa4375ec1566073c3/numpy-2.1.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8661c94e3aad18e1ea17a11f60f843a4933ccaf1a25a7c6a9182af70610b2313", size = 14172488 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f4/c2/dddca3e69a024d2f249a5b68698328163cbdafb7e65fbf6d36373bbabf12/numpy-2.1.1-cp312-cp312-win32.whl", hash = "sha256:950802d17a33c07cba7fd7c3dcfa7d64705509206be1606f196d179e539111ed", size = 6237195 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b7/98/5640a09daa3abf0caeaefa6e7bf0d10c0aa28a77c84e507d6a716e0e23df/numpy-2.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:3fc5eabfc720db95d68e6646e88f8b399bfedd235994016351b1d9e062c4b270", size = 12568082 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6b/9e/8bc6f133bc6d359ccc9ec051853aded45504d217685191f31f46d36b7065/numpy-2.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:046356b19d7ad1890c751b99acad5e82dc4a02232013bd9a9a712fddf8eb60f5", size = 20834810 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/32/1b/429519a2fa28681814c511574017d35f3aab7136d554cc65f4c1526dfbf5/numpy-2.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6e5a9cb2be39350ae6c8f79410744e80154df658d5bea06e06e0ac5bb75480d5", size = 13507739 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/25/18/c732d7dd9896d11e4afcd487ac65e62f9fa0495563b7614eb850765361fa/numpy-2.1.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:d4c57b68c8ef5e1ebf47238e99bf27657511ec3f071c465f6b1bccbef12d4136", size = 5074465 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3e/37/838b7ae9262c370ab25312bab365492016f11810ffc03ebebbd54670b669/numpy-2.1.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:8ae0fd135e0b157365ac7cc31fff27f07a5572bdfc38f9c2d43b2aff416cc8b0", size = 6606418 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8b/b9/7ff3bfb71e316a5b43a124c4b7a5881ab12f3c32636014bef1f757f19dbd/numpy-2.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:981707f6b31b59c0c24bcda52e5605f9701cb46da4b86c2e8023656ad3e833cb", size = 13692464 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/42/78/75bcf16e6737cd196ff7ecf0e1fd3f953293a34dff4fd93fb488e8308536/numpy-2.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ca4b53e1e0b279142113b8c5eb7d7a877e967c306edc34f3b58e9be12fda8df", size = 16037763 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/23/99/36bf5ffe034d06df307bc783e25cf164775863166dcd878879559fe0379f/numpy-2.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e097507396c0be4e547ff15b13dc3866f45f3680f789c1a1301b07dadd3fbc78", size = 16410374 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7f/16/04c5dab564887d4cd31a9ed30e51467fa70d52a4425f5a9bd1eed5b3d34c/numpy-2.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7506387e191fe8cdb267f912469a3cccc538ab108471291636a96a54e599556", size = 14169873 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/09/e0/d1b5adbf1731886c4186c59a9fa208585df9452a43a2b60e79af7c649717/numpy-2.1.1-cp313-cp313-win32.whl", hash = "sha256:251105b7c42abe40e3a689881e1793370cc9724ad50d64b30b358bbb3a97553b", size = 6234118 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d0/9c/2391ee6e9ebe77232ddcab29d92662b545e99d78c3eb3b4e26d59b9ca1ca/numpy-2.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:f212d4f46b67ff604d11fff7cc62d36b3e8714edf68e44e9760e19be38c03eb0", size = 12561742 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/38/0e/c4f754f9e73f9bb520e8bf418c646f2c4f70c5d5f2bc561e90f884593193/numpy-2.1.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:920b0911bb2e4414c50e55bd658baeb78281a47feeb064ab40c2b66ecba85553", size = 20858403 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/32/fc/d69092b9171efa0cb8079577e71ce0cac0e08f917d33f6e99c916ed51d44/numpy-2.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:bab7c09454460a487e631ffc0c42057e3d8f2a9ddccd1e60c7bb8ed774992480", size = 13519851 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/14/2a/d7cf2cd9f15b23f623075546ea64a2c367cab703338ca22aaaecf7e704df/numpy-2.1.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:cea427d1350f3fd0d2818ce7350095c1a2ee33e30961d2f0fef48576ddbbe90f", size = 5115444 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8e/00/e87b2cb4afcecca3b678deefb8fa53005d7054f3b5c39596e5554e5d98f8/numpy-2.1.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:e30356d530528a42eeba51420ae8bf6c6c09559051887196599d96ee5f536468", size = 6628903 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ab/9d/337ae8721b3beec48c3413d71f2d44b2defbf3c6f7a85184fc18b7b61f4a/numpy-2.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8dfa9e94fc127c40979c3eacbae1e61fda4fe71d84869cc129e2721973231ef", size = 13665945 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c0/90/ee8668e84c5d5cc080ef3beb622c016adf19ca3aa51afe9dbdcc6a9baf59/numpy-2.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:910b47a6d0635ec1bd53b88f86120a52bf56dcc27b51f18c7b4a2e2224c29f0f", size = 16023473 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/38/a0/57c24b2131879183051dc698fbb53fd43b77c3fa85b6e6311014f2bc2973/numpy-2.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:13cc11c00000848702322af4de0147ced365c81d66053a67c2e962a485b3717c", size = 16400624 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bb/4c/14a41eb5c9548c6cee6af0936eabfd985c69230ffa2f2598321431a9aa0a/numpy-2.1.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53e27293b3a2b661c03f79aa51c3987492bd4641ef933e366e0f9f6c9bf257ec", size = 14155072 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "polars"
|
||||||
|
version = "1.7.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/3e/d3/54a4f13c3423db2d09b7b8a29cdee0509b2470cccbd210c7f506deee402c/polars-1.7.1.tar.gz", hash = "sha256:3323bf6b3f1cf55212ddd35f044af8a1aa02033bca17d06f3852325e0da93a80", size = 3971988 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ae/53/7daa3dd2fd6d8728c3363b342fbf1f804a5612ecf33aef74fb63dea5e276/polars-1.7.1-cp38-abi3-macosx_10_12_x86_64.whl", hash = "sha256:589c1b5a9b5167f3c49713212cbeccc39e3a0e12577e21331c50dbf7178e32ed", size = 30844815 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8a/2e/f34c0acdbfcd4c9a3cf21c1bf8ecacb68dae7147d0854b131feea027726d/polars-1.7.1-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c955cca9d109ed5d79f4498915ec80590aa2e4619bc40bafbbeb5a160fcb166e", size = 27184877 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d5/f4/8cd6d454fcf6e1f5f0a17265a3acca19731f79c65c7432bafbb24492bf73/polars-1.7.1-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5cd675e4a306b2da57a1b688e65382aaa9e992dd7156b485fbd7f39892a3d784", size = 32202182 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a4/db/de0bcbb437e5246d6ae79c634b5b58167a978cef6cbfa66858174b8577a6/polars-1.7.1-cp38-abi3-manylinux_2_24_aarch64.whl", hash = "sha256:45c255749b49bee244d10baeb69057580a0a397125b014bc8854b73ba5bdf45e", size = 28867666 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/69/12/6b4b87ff17e2129952604f24d5d052c6ab2c7089547174939e0cb8824fbc/polars-1.7.1-cp38-abi3-win_amd64.whl", hash = "sha256:a9004a907fc8e923dda27879f7e6eea8e06a753e160d08e606c8b9b5f914f911", size = 32095724 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pydantic"
|
||||||
|
version = "2.9.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "annotated-types" },
|
||||||
|
{ name = "pydantic-core" },
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/14/15/3d989541b9c8128b96d532cfd2dd10131ddcc75a807330c00feb3d42a5bd/pydantic-2.9.1.tar.gz", hash = "sha256:1363c7d975c7036df0db2b4a61f2e062fbc0aa5ab5f2772e0ffc7191a4f4bce2", size = 768511 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e4/28/fff23284071bc1ba419635c7e86561c8b9b8cf62a5bcb459b92d7625fd38/pydantic-2.9.1-py3-none-any.whl", hash = "sha256:7aff4db5fdf3cf573d4b3c30926a510a10e19a0774d38fc4967f78beb6deb612", size = 434363 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pydantic-core"
|
||||||
|
version = "2.23.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/5c/cc/07bec3fb337ff80eacd6028745bd858b9642f61ee58cfdbfb64451c1def0/pydantic_core-2.23.3.tar.gz", hash = "sha256:3cb0f65d8b4121c1b015c60104a685feb929a29d7cf204387c7f2688c7974690", size = 402277 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8f/35/6d81bc4aa7d06e716f39e2bffb0eabcbcebaf7bab94c2f8278e277ded0ea/pydantic_core-2.23.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:e0ec50663feedf64d21bad0809f5857bac1ce91deded203efc4a84b31b2e4305", size = 1845250 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/18/42/0821cd46f76406e0fe57df7a89d6af8fddb22cce755bcc2db077773c7d1a/pydantic_core-2.23.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:db6e6afcb95edbe6b357786684b71008499836e91f2a4a1e55b840955b341dbb", size = 1769993 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e5/55/b969088e48bd8ea588548a7194d425de74370b17b385cee4d28f5a79013d/pydantic_core-2.23.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98ccd69edcf49f0875d86942f4418a4e83eb3047f20eb897bffa62a5d419c8fa", size = 1791250 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/43/c1/1d460d09c012ac76b68b2a1fd426ad624724f93b40e24a9a993763f12c61/pydantic_core-2.23.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a678c1ac5c5ec5685af0133262103defb427114e62eafeda12f1357a12140162", size = 1802530 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/70/8e/fd3c9eda00fbdadca726f17a0f863ecd871a65b3a381b77277ae386d3bcd/pydantic_core-2.23.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:01491d8b4d8db9f3391d93b0df60701e644ff0894352947f31fff3e52bd5c801", size = 1997848 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f0/67/13fa22d7b09395e83721edc31bae2bd5c5e2c36a09d470c18f5d1de46958/pydantic_core-2.23.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fcf31facf2796a2d3b7fe338fe8640aa0166e4e55b4cb108dbfd1058049bf4cb", size = 2662790 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fa/1b/1d689c53d15ab67cb0df1c3a2b1df873b50409581e93e4848289dce57e2f/pydantic_core-2.23.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7200fd561fb3be06827340da066df4311d0b6b8eb0c2116a110be5245dceb326", size = 2074114 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3d/d9/b565048609db77760b9a0900f6e0a3b2f33be47cd3c4a433f49653a0d2b5/pydantic_core-2.23.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dc1636770a809dee2bd44dd74b89cc80eb41172bcad8af75dd0bc182c2666d4c", size = 1918153 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/41/94/8ee55c51333ed8df3a6f1e73c6530c724a9a37d326e114c9e3b24faacff9/pydantic_core-2.23.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:67a5def279309f2e23014b608c4150b0c2d323bd7bccd27ff07b001c12c2415c", size = 1969019 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f7/49/0233bae5778a5526cef000447a93e8d462f4f13e2214c13c5b23d379cb25/pydantic_core-2.23.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:748bdf985014c6dd3e1e4cc3db90f1c3ecc7246ff5a3cd4ddab20c768b2f1dab", size = 2121325 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/42/a1/2f262db2fd6f9c2c9904075a067b1764cc6f71c014be5c6c91d9de52c434/pydantic_core-2.23.3-cp312-none-win32.whl", hash = "sha256:255ec6dcb899c115f1e2a64bc9ebc24cc0e3ab097775755244f77360d1f3c06c", size = 1725252 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9a/00/a57937080b49500df790c4853d3e7bc605bd0784e4fcaf1a159456f37ef1/pydantic_core-2.23.3-cp312-none-win_amd64.whl", hash = "sha256:40b8441be16c1e940abebed83cd006ddb9e3737a279e339dbd6d31578b802f7b", size = 1920660 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e1/3c/32958c0a5d1935591b58337037a1695782e61261582d93d5a7f55441f879/pydantic_core-2.23.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:6daaf5b1ba1369a22c8b050b643250e3e5efc6a78366d323294aee54953a4d5f", size = 1845068 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/92/a1/7e628e19b78e6ffdb2c92cccbb7eca84bfd3276cee4cafcae8833452f458/pydantic_core-2.23.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d015e63b985a78a3d4ccffd3bdf22b7c20b3bbd4b8227809b3e8e75bc37f9cb2", size = 1770095 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bb/17/d15fd8ce143cd1abb27be924eeff3c5c0fe3b0582f703c5a5273c11e67ce/pydantic_core-2.23.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3fc572d9b5b5cfe13f8e8a6e26271d5d13f80173724b738557a8c7f3a8a3791", size = 1790964 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/24/cc/37feff1792f09dc33207fbad3897373229279d1973c211f9562abfdf137d/pydantic_core-2.23.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f6bd91345b5163ee7448bee201ed7dd601ca24f43f439109b0212e296eb5b423", size = 1802384 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/44/d8/ca9acd7f5f044d9ff6e43d7f35aab4b1d5982b4773761eabe3317fc68e30/pydantic_core-2.23.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc379c73fd66606628b866f661e8785088afe2adaba78e6bbe80796baf708a63", size = 1997824 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/35/0f/146269dba21b10d5bf86f9a7a7bbeab4ce1db06f466a1ab5ec3dec68b409/pydantic_core-2.23.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbdce4b47592f9e296e19ac31667daed8753c8367ebb34b9a9bd89dacaa299c9", size = 2662907 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5a/7d/9573f006e39cd1a7b7716d1a264e3f4f353cf0a6042c04c01c6e31666f62/pydantic_core-2.23.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc3cf31edf405a161a0adad83246568647c54404739b614b1ff43dad2b02e6d5", size = 2073953 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7e/a5/25200aaafd1e97e2ec3c1eb4b357669dd93911f2eba252bc60b6ba884fff/pydantic_core-2.23.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8e22b477bf90db71c156f89a55bfe4d25177b81fce4aa09294d9e805eec13855", size = 1917822 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3e/b4/ac069c58e3cee70c69f03693222cc173fdf740d20d53167bceafc1efc7ca/pydantic_core-2.23.3-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:0a0137ddf462575d9bce863c4c95bac3493ba8e22f8c28ca94634b4a1d3e2bb4", size = 1968838 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d1/3d/9f96bbd6212b4b0a6dc6d037e446208d3420baba2b2b81e544094b18a859/pydantic_core-2.23.3-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:203171e48946c3164fe7691fc349c79241ff8f28306abd4cad5f4f75ed80bc8d", size = 2121468 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ac/50/7399d536d6600d69059a87fff89861332c97a7b3471327a3663c7576e707/pydantic_core-2.23.3-cp313-none-win32.whl", hash = "sha256:76bdab0de4acb3f119c2a4bff740e0c7dc2e6de7692774620f7452ce11ca76c8", size = 1725373 },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/24/ba/9ac8744ab636c1161c598cc5e8261379b6b0f1d63c31242bf9d5ed41ed32/pydantic_core-2.23.3-cp313-none-win_amd64.whl", hash = "sha256:37ba321ac2a46100c578a92e9a6aa33afe9ec99ffa084424291d84e456f490c1", size = 1920594 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pydantic-settings"
|
||||||
|
version = "2.5.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "pydantic" },
|
||||||
|
{ name = "python-dotenv" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/68/27/0bed9dd26b93328b60a1402febc780e7be72b42847fa8b5c94b7d0aeb6d1/pydantic_settings-2.5.2.tar.gz", hash = "sha256:f90b139682bee4d2065273d5185d71d37ea46cfe57e1b5ae184fc6a0b2484ca0", size = 70938 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/29/8d/29e82e333f32d9e2051c10764b906c2a6cd140992910b5f49762790911ba/pydantic_settings-2.5.2-py3-none-any.whl", hash = "sha256:2c912e55fd5794a59bf8c832b9de832dcfdf4778d79ff79b708744eed499a907", size = 26864 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "python-dotenv"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simulation"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = { virtual = "." }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "numpy" },
|
||||||
|
{ name = "polars" },
|
||||||
|
{ name = "pydantic-settings" },
|
||||||
|
{ name = "tqdm" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.metadata]
|
||||||
|
requires-dist = [
|
||||||
|
{ name = "numpy", specifier = ">=2.1.1" },
|
||||||
|
{ name = "polars", specifier = ">=1.7.1" },
|
||||||
|
{ name = "pydantic-settings", specifier = ">=2.5.2" },
|
||||||
|
{ name = "tqdm", specifier = ">=4.66.5" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tqdm"
|
||||||
|
version = "4.66.5"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "colorama", marker = "platform_system == 'Windows'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/58/83/6ba9844a41128c62e810fddddd72473201f3eacde02046066142a2d96cc5/tqdm-4.66.5.tar.gz", hash = "sha256:e1020aef2e5096702d8a025ac7d16b1577279c9d63f8375b63083e9a5f0fcbad", size = 169504 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/48/5d/acf5905c36149bbaec41ccf7f2b68814647347b72075ac0b1fe3022fdc73/tqdm-4.66.5-py3-none-any.whl", hash = "sha256:90279a3770753eafc9194a0364852159802111925aa30eb3f9d85b0e805ac7cd", size = 78351 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typing-extensions"
|
||||||
|
version = "4.12.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 },
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user