From a46c9ef0ec44e3eca7282759b751e742093129fc Mon Sep 17 00:00:00 2001 From: Kandai Watanabe Date: Wed, 24 Jul 2024 18:17:47 -0600 Subject: [PATCH 1/9] workign demo --- Dockerfile | 44 ++-- README.md | 16 +- examples/AircraftTurnaround/main.ipynb | 10 +- examples/demo/learning.py | 45 ++++ examples/demo/main.ipynb | 202 +++--------------- examples/{ros/main.py => demo/planning.py} | 24 ++- pyproject.toml | 59 ++--- requirements-dev.txt | 9 - requirements.txt | 23 -- specless/inference/__init__.py | 3 +- specless/inference/base.py | 11 +- specless/inference/partial_order.py | 9 +- specless/inference/timed_partial_order.py | 26 ++- specless/utils/collect_demos.py | 4 +- .../inference/test_partial_order_inference.py | 10 +- .../test_timed_partial_order_inference.py | 13 +- tests/test_synthesis.py | 25 +-- 17 files changed, 192 insertions(+), 341 deletions(-) create mode 100644 examples/demo/learning.py rename examples/{ros/main.py => demo/planning.py} (75%) delete mode 100644 requirements-dev.txt delete mode 100644 requirements.txt diff --git a/Dockerfile b/Dockerfile index 39a518f..e42167f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,29 +1,31 @@ -ARG PYTHON_VERSION=3.11 +ARG PYTHON_VERSION=3.8 FROM python:${PYTHON_VERSION} - RUN apt-get update && \ - apt-get install -y software-properties-common &&\ - apt update && \ apt install -y graphviz - # add-apt-repository universe && \ # https://python-poetry.org/docs#ci-recommendations -ENV POETRY_VERSION=1.7.0 -# ENV POETRY_HOME=/opt/poetry -ENV POETRY_VENV=/opt/poetry-venv - -# Tell Poetry where to place its cache and virtual environment -ENV POETRY_CACHE_DIR=/opt/.cache - -# Creating a virtual environment just for poetry and install it with pip -RUN python3 -m venv $POETRY_VENV \ - && $POETRY_VENV/bin/pip install -U pip setuptools \ - && $POETRY_VENV/bin/pip install poetry==${POETRY_VERSION} - -# Add Poetry to PATH -ENV PATH="${PATH}:${POETRY_VENV}/bin" - -ENV POETRY_VIRTUALENVS_IN_PROJECT=true +ENV POETRY_VERSION=1.7.0 \ + # Poetry home directory + POETRY_HOME='/usr/local' \ + # Add Poetry's bin folder to the PATH + PATH="/usr/local/bin:$PATH" \ + # Avoids any interactions with the terminal + POETRY_NO_INTERACTION=1 \ + # This avoids poetry from creating a virtualenv + # Instead, it directly installs the dependencies in the system's python environment + POETRY_VIRTUALENVS_CREATE=false + +# System deps: +RUN curl -sSL https://install.python-poetry.org | python3 - + +# Copy the project files +WORKDIR /home/specless +COPY pyproject.toml poetry.lock /home/specless/ + +# Project initialization and conditionally install cvxopt if on x86 architecture +RUN poetry install --no-interaction +# RUN poetry install --no-interaction && \ +# if [ "$(uname -m)" = "x86_64" ]; then poetry add cvxopt; fi CMD ["bash"] diff --git a/README.md b/README.md index 332cf7a..de06b30 100644 --- a/README.md +++ b/README.md @@ -75,15 +75,10 @@ You can use the `specless` package in two ways: as a library, and as a CLI tool. ... ["e1", "e4", "e2", "e3", "e5"], # trace 2 ... ["e1", "e2", "e4", "e3", "e5"], # trace 3 ... ] ->>> dataset = sl.ArrayDataset(demonstrations, columns=["symbol"]) - -# # or load from a file -# >>> csv_filename = "examples/readme/example.csv" -# >>> dataset = sl.BaseDataset(pd.read_csv(csv_filename)) # Run the inference >>> inference = sl.POInferenceAlgorithm() ->>> specification = inference.infer(dataset) # returns a Specification +>>> specification = inference.infer(demonstrations) # returns a Specification # prints the specification >>> print(specification) # doctest: +ELLIPSIS @@ -118,10 +113,6 @@ The environment is based on the OpenAI Gym library (or more specifically, [Petti ... num=10, ... timeout=1000, ... ) - -# Convert them to a Dataset Class ->>> demonstrations = sl.ArrayDataset(demonstrations, columns=["timestamp", "label"]) - ``` - Once the specification is obtained, synthesize a strategy: @@ -178,6 +169,9 @@ synthesize -d OR -s AND -e AND -p " ] @@ -78,27 +86,27 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "left 0\n", - "right 1\n", - "forward 2\n", - "pickup 3\n", - "drop 4\n", - "toggle 5\n", - "done 6\n" + "left Actions.left\n", + "right Actions.right\n", + "forward Actions.forward\n", + "pickup Actions.pickup\n", + "drop Actions.drop\n", + "toggle Actions.toggle\n", + "done Actions.done\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "/usr/local/lib/python3.11/site-packages/gymnasium/core.py:311: UserWarning: \u001b[33mWARN: env.actions to get variables from other wrappers is deprecated and will be removed in v1.0, to get this variable you can do `env.unwrapped.actions` for environment variables or `env.get_wrapper_attr('actions')` that will search the reminding wrappers.\u001b[0m\n", + "/home/specless/.venv/lib/python3.8/site-packages/gymnasium/core.py:311: UserWarning: \u001b[33mWARN: env.actions to get variables from other wrappers is deprecated and will be removed in v1.0, to get this variable you can do `env.unwrapped.actions` for environment variables or `env.get_wrapper_attr('actions')` that will search the reminding wrappers.\u001b[0m\n", " logger.warn(\n" ] } @@ -111,69 +119,13 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/usr/local/lib/python3.11/site-packages/gymnasium/wrappers/record_video.py:94: UserWarning: \u001b[33mWARN: Overwriting existing videos at /Users/kandai/Documents/projects/dev/specless/examples/demo/1 folder (try specifying a different `video_folder` for the `RecordVideo` wrapper if this is not desired)\u001b[0m\n", - " logger.warn(\n", - "/usr/local/lib/python3.11/site-packages/gymnasium/utils/passive_env_checker.py:159: UserWarning: \u001b[33mWARN: The obs returned by the `step()` method is not within the observation space.\u001b[0m\n", - " logger.warn(f\"{pre} is not within the observation space.\")\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Moviepy - Building video /Users/kandai/Documents/projects/dev/specless/examples/demo/1/rl-video-step-0.mp4.\n", - "Moviepy - Writing video /Users/kandai/Documents/projects/dev/specless/examples/demo/1/rl-video-step-0.mp4\n", - "\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/usr/local/lib/python3.11/site-packages/gymnasium/wrappers/record_video.py:94: UserWarning: \u001b[33mWARN: Overwriting existing videos at /Users/kandai/Documents/projects/dev/specless/examples/demo/2 folder (try specifying a different `video_folder` for the `RecordVideo` wrapper if this is not desired)\u001b[0m\n", - " logger.warn(\n", - "/usr/local/lib/python3.11/site-packages/gymnasium/utils/passive_env_checker.py:159: UserWarning: \u001b[33mWARN: The obs returned by the `step()` method is not within the observation space.\u001b[0m\n", - " logger.warn(f\"{pre} is not within the observation space.\")\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Moviepy - Done !\n", - "Moviepy - video ready /Users/kandai/Documents/projects/dev/specless/examples/demo/1/rl-video-step-0.mp4\n", - "Moviepy - Building video /Users/kandai/Documents/projects/dev/specless/examples/demo/2/rl-video-step-0.mp4.\n", - "Moviepy - Writing video /Users/kandai/Documents/projects/dev/specless/examples/demo/2/rl-video-step-0.mp4\n", - "\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - " \r" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Moviepy - Done !\n", - "Moviepy - video ready /Users/kandai/Documents/projects/dev/specless/examples/demo/2/rl-video-step-0.mp4\n" - ] - } - ], + "outputs": [], "source": [ "demonstrations = []\n", "\n", - "action_strs: list[str] = [\n", + "action_strs = [\n", " \"right\",\n", " \"forward\",\n", " \"left\",\n", @@ -225,20 +177,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[[0, ''], [1, ''], [2, ''], [3, ''], [4, 'floor_yellow'], [5, ''], [6, 'floor_purple'], [7, 'floor_purple'], [8, 'floor_blue'], [9, 'floor_red'], [10, 'floor_red'], [11, 'floor_red'], [12, 'floor_green']]\n", - "[[0, ''], [1, ''], [2, ''], [3, 'floor_yellow'], [4, ''], [5, ''], [6, ''], [7, 'floor_green'], [8, 'floor_red'], [9, 'floor_red'], [10, 'floor_blue'], [11, 'floor_purple']]\n", - "[(4, 'floor_yellow'), (6, 'floor_purple'), (8, 'floor_blue'), (9, 'floor_red'), (12, 'floor_green')]\n", - "[(3, 'floor_yellow'), (7, 'floor_green'), (8, 'floor_red'), (10, 'floor_blue'), (11, 'floor_purple')]\n" - ] - } - ], + "outputs": [], "source": [ "print(demonstrations[0])\n", "print(demonstrations[1])\n", @@ -251,34 +192,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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c5oL5pTZlmxycvLQoUP33HNPQECAUqlct27dH/7wh+rq6qVv2dWMjY3t37//wQcfJAd3amrq7373OzJj5FKOHTt2xx13aDQaHx+fHTt27N+/f2JignYoqSgvL3/88cejo6MVCsXll1/+3nvvmUwm2qEczWAwvPfee1u3biVvHt20adPLL79cX19PO5eM9fb2vvPOO7fffru/v79SqczPz3/ppZdOnz5NO5e8LalfOzs7n3rqqfDwcIZhsrOzn3vuuba2NrGSuTKLxfLtt9/ef//9ISEhCoXikksuef/9981mM+1c9mWxWPbt25eRkcEwTFZW1uuvvz48PEw7lERNTk5+/vnn1157rUqlWrZs2XPPPTcyMkI7lCOUlpbec8893t7eKpVq48aNb7zxRl9fH+1QTmV8fPyzzz67/fbbtVqtUqncvHnzJ598Mjk5STuXLC2yXwsKCm655RZ3d/eQkJDHHnsMrxztxGw2f/nll9dff71KpYqMjHz66ae7urpohxLf5OTkO++8k5ycrFQqb7rppuLiYtqJZKO9vf2Xv/wlWWXsmWeeGRoaop3ILsbGxt58802WZRmGSUlJeeWVV3p6emiHcnJjY2Mffvjh5s2blUpldHT0008/febMGdqhZGbB/VpYWLh+/XoywtizZ4/BYLBHLDjH6dOnn3rqqeDgYHd39507dzrTgV5cXJyXl6dUKrdt21ZbW0s7jiz19fU99dRTAQEBgYGBL774osVioZ1INCaTac+ePREREe7u7tu2bTt06JDVaqUdyrU0NTXt2rUrJCSEnHw6OjpoJ5KNBfRrcXHxFVdcwTDMZZdd9t1339kvE8zGaDS+9NJLYWFhPj4+Tz755MDAAO1ES9LV1XXnnXcqFIpNmzadOHGCdhzZGxgYeOihh9RqNcdxpaWltOMs1djY2EsvvRQeHu7l5fXII4845ZUbGRkbG3vttdeio6M9PT0feuihzs5O2olkYF79ajAYdu3apVQq8/LyPvvsM3tngrkZDIYXX3wxNDQ0NDR07969tOMs0tdff03WKZTvjyBNlZWV69atU6lUTz31lHwHskePHk1KSiIDJpzKpYNcToiMjPTy8tq9ezfmZed24X49cOCATqcLDg5+++23HRAI5mlgYODee+9VKBRbt26V10v7ycnJJ598UqlU3n777S5yV46DWa3WP/3pT+7u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tXj4qyP19fWlp6fHxsb29fXRzjKXl19+WalUPvDAA9J5e67oCgoK7PdGcIreeecdT0/PrVu3OvG/3eLM+nz1sbGxm2++2d3dXZrXlJZi+/btfn5+0tnOEg0PD1933XUajeaDDz6gneUCTCbTli1btFqtPWYf4Hy9vb0ZGRmxsbGtra20s1zYhx9+6OXltXnzZid7vnpRUVF+fj6ZQhocHKQdR0wWi+XXv/61QqF45JFHppawgCkK2+xvObfZbE888cTu3bu3bt366quvhoWFiT35axft7e2zvcfLbDZPTEy0trZ2d3c//vjjP/nJT6KiohaxC7PZ/MYbb/z2t79d4naW7uDBgzt37jQajZ9++ilZQEriJiYmbrrppgMHDvzpT3+auotSyuY4nBiGufPOO3/0ox85Ms/88Ty/fft2tVr9zTffSOr90HMoLS297rrrrFbryy+/TBZqloW5D5JVq1a9//77aWlpu3fvtt9Ky453/PjxnTt3lpWV/fnPf7733ntpx5GkCzbwwYMHY2JigoKC/v73v8+9BphEWK3W8dmRNcmcQH9//44dOxQKxbZt27q6umjHWYDJyclf//rXSqXylltuGR4eph3nAuR4OFmt1ueff97Nze3qq6+W+GXh8509e/bee+9VKBTXXXcdWfBP+uR4kCyF0Wh84okn3Nzc1qxZg6WG53DhfrXZbAaDYdeuXUqlMjU19f3337d3Jpjb6Ojo7t27AwICwsLCpH9NeDb/+te/li1bFhERsXfvXtpZnEpFRUV+fr5arX7qqafke8nu22+/Xblypbu7+86dO+16Yw4siMlk2rNnT0REhLe39+7du53vpYO45tWvRFlZ2dVXX80wzMUXX3z06FH7ZYLZGAyGF198MTQ01NfX96mnnhoaGqKdaEl6enruvvtuhUJx+eWX19bW0o4je2fPnv3pT3+qUqnWrl1bXl5OO85SjY+Pv/rqq5GRkRqN5uGHH55asB6oMBqN0/85uru7aSeSgQX0K8Hz/OWXX84wTGZm5p49e8g7DcDeTp48uWvXruDgYPKKXl4XhOdWUlLCsqxSqbzmmmtKS0tpx5Gl3t7ep556yt/fPzAw8MUXX5TvsPV8UwMmlUp1zTXXHDp0SBazVM6ksbFx+skHlxPmb8H9SvA8f9ttt7m7uwcFBe3atevEiRPixgJiYmLin//857XX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", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\t6 <= t_floor_purple <= 11\n", - "\t8 <= t_floor_blue <= 10\n", - "\t8 <= t_floor_red <= 9\n", - "\t7 <= t_floor_green <= 12\n", - "\t3 <= t_floor_yellow <= 4\n", - "\t5.0 <= t_floor_red - t_floor_yellow <= 5.0\n", - "\t4.0 <= t_floor_green - t_floor_yellow <= 8.0\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "inference = sl.TPOInferenceAlgorithm()\n", "columns: list = [\"timestamp\", \"symbol\"]\n", @@ -292,30 +208,9 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/usr/local/lib/python3.11/site-packages/gymnasium/utils/passive_env_checker.py:159: UserWarning: \u001b[33mWARN: The obs returned by the `reset()` method is not within the observation space.\u001b[0m\n", - " logger.warn(f\"{pre} is not within the observation space.\")\n", - "/usr/local/lib/python3.11/site-packages/gymnasium/core.py:311: UserWarning: \u001b[33mWARN: env.actions to get variables from other wrappers is deprecated and will be removed in v1.0, to get this variable you can do `env.unwrapped.actions` for environment variables or `env.get_wrapper_attr('actions')` that will search the reminding wrappers.\u001b[0m\n", - " logger.warn(\n" - ] - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAGFCAYAAAASI+9IAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAOEUlEQVR4nO3dXXMb53nH4f+SIE2ATSyRkawqrp2ZvkgHGk8n08Me9bvkMB+0M50k9TRtlDJ1JxKdSLReYsqkCBFADx7wlu3KCW1Ju6RxXTMYAaIObpgwf3zw7C66xWKxCAAkWRt6AAAuDlEAoIgCAEUUACiiAEARBQCKKABQRAGAMjrvP/zZz372Nue4kK5evZr3338/XdcNPQrAa/v5z3/+F/+NlQIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAyGnqAy+Dw8DCPHz8eeoxedF2X3d3dTCaTHBwc5Pj4eOiRejEajXL9+vUsFos8fPgws9ls6JF6sb29nd3d3Tx79mzlXuPb29tDj3IhicI5PHnyJHfv3h16jN7cuXMnW1tb2d/fz8HBwdDj9GI8Hufq1auZzWbZ29vLdDodeqRe3Lx5M7u7uyv5GheFV/P2EQBFFAAoogBAEQUAiigAUEQBgCIKABTnKbyGteVtnmSxvAFcZqLwGn6a5CdJ/jvJQZJHSU6GHAjgNYnCa7ie5O+TfJG2SjhJ0qWtHOZJTocbDeA7EYXvqEtyM8mdtNXC8yT7ST5P8kmSp0n+Iy0YAJeFKLyGcZIfLm/zJFtpUZgl2U7yhyQbSaZ5uXI4W0UAXESi8IZ0SX6U5GqSG2kB+Je0lcKvkjxJspfkWZKHEQbgYhKFN6RLsrm8P17++aMkR0kep60cjpIcpq0kpml7ELMkL3qdFOCbicJbtpV2lNIsyT+nheF+2mrh39OOWPokDmcFLgZReMvWkky+9Hg77a2jzbS3lCZpK4UXaSuHadqm9dm5DwB9EoWevZPkx2n7DrfSAvA07TyHT5L8b5LfJDlefg2gT6LQsy7tP/ooLRCby/trebm3ME87iunztI3q58uvrcYHRAJDEoWBbaQd0vqDJO+nBWGW5N7y9p9pq4cHaZvUAG+TKAysW96SZP1Lf3817bDW52lHM/0oLQp/Wv7dF3m5erD3ALwponBBXUsLwa20H/qHaUcu/SLtzOnfpG1Unx3iCvAmiMIFdXZN8/W0KEzSvll/s7w/TgvC/bRVw+dpK4ejWDkA350oXBJby9s/5uUP/ZMk/5rkj2l7D0/TIuFCfMB3JQqXQPcN9zfTLsr3V2krh2dph7sepb21dJx2kpyVA3BeonCJrSf5h+X9f0o78e33aSuGX6etIB7FygE4P1G4xLqvPV5PO2ppa/n4x2mHu36Rdv2lw7SVw2lcbwl4NVH4HllPsru8/37aD/+fpq0W/ivtvIcv0t5WEgXgVUThe+TrK4fzfg3gjCh8j7xqQ3nxpT9tOAN/iSh8j8zSNpmP0jaZnyb5bV5+psNh2hFKNp6BbyIKl9jia/dP0w5FfZp23sIf085jEAHgvEThEpsl+V3a9ZD201YB99I2ks/OU3AJDODbEIVL4OsrgrPbNC0GD9LOS/hTnNEMvB5RuCSep0VgL+0Q03tpewT7+eq1j6wMgNchChfU2cdxzpe3L9I2jO+lheBuXCUVePNE4YI6SDv7+JMkny4fH6atCE7y8vMU5kMNCHwvicLAzvYHzlYEs+XtcdrRQ58sbw/jk9eAt08UBnb2GQiP094aup92RNHZZzQfpa0MXJYC6IMo9GyRl6uBadoG8tO0t4fup30e817a4aTPB5kQWGWi0LOTtENID5J8nOSzJP+TthKYLm8nsVcADEMU3rJ5Xp5ENk17O2g/bY/gfloU9gebDuCrROEte57kF2nnFvw2bZ9gPy9XBA4nBS4SUXhDFnl58tjztLOKv0i79MTv084p+MPy8eN4ewi4mEThDVnk5bkEd9NWBv+Wl2caz9NCcXboKcBFJAqv4TjtekPP0lYH+8vHZ5+T/DhttQBwWYjCd7RIO9P410l+mRaET9MCcXaJChemAy4bUXgND9I2jz9Ne7voWdrmMcBlJQqv4ZdJfpWvXs4a4DIThddgwxj4vlkbegAALg5RAKCIAgBFFAAoogBAEQUAiigAUEQBgCIKfEXXdem6bugxevfl57yKz3+VrOpr/Lyc0XwOu7u7uXPnztBj9KLrurz77rtZW1vLhx9+mPfee2/okXoxGo2yubmZxWKR27dvZzZbjY8/mkwmSVbzNc6ricI5TCaTbG1tDT1Gb9bW1tJ1yc7OlazOFZ26JF0Wi+TatWtZLFbjeZ/9xjyZTDIZTwaepkcWCt9IFM7hs88+y/3794ceozcffvhhdnauZDz+JKPR50OP04v5fDNHR3+X4+N59vb2cnq6Ghc+39nZyQcffJDjp8mzB6sRwiT54V932bJYeCVROIfj4+McHBwMPUZv2ltGi4xGn2dzczWe92w2TtfNcno6y6NHjzKdToceqRcbGxtJktPnyfGTgYfp0WR36AkuLhvNABRRAKCIAgBFFAAoogBAEQUAiigAUEQBgCIKABRRAKCIAgBFFAAoogBAEQUAiigAUEQBgCIKABRRAKCIAgBFFAAoogBAEQUAiigAUEQBgCIKABRRAKCIAgBFFAAoogBAEQUAiigAUEQBgCIKABRRAKCIAgBFFAAoogBAEQUAiigAUEQBgCIKABRRAKCIAgBFFAAoogBAEQUAiigAUEQBgCIKABRRAKCIAgBFFAAoogBAEQUAiigAUEQBgCIKAJTR0ANcBqPRKJPJJIvFYuhR3rqu6zIajZJ0mc/fyWw2HnqkXszn4yRd1tbWMh6Ps76+PvRIvdjc3EySrI2S0dbAw/RobTW+vd+JKJzD9evXc+XKlaHH6E37QdHl6Ohv03U/GXqcnrQIjsfJRx99tBK/ACRZ/gKQTK4m7/ygG3ia/qxvDD3BxSUK5zCfzzObzYYeozeLxSKLRXJ8PM/p6Wo8767rMpm05z6bzVYmCl3XZWNjI6fztZy8WJ13k7fW51lbX43v8bclCufw8OHD7O3tDT1GL7quy+3bt3Pt2rXs7e3l0aNHQ4/Ui/F4nI8++iiz2Swff/xxptPp0CP14saNG7l161YePtzM3t5k6HF60XWL3L59lPfeW43v8bclCucwn89X5odEkvpN+fT0dGWe9/r6+nKFtMh0Ol2Z5316epokmc+7TKddklV4C2mRFVr4f2urs14E4C8SBQCKKABQRAGAIgoAFFEAoIgCAEUUACiiAEARBQCKKABQRAGAIgoAFFEAoIgCAEUUACiiAEARBQCKKABQRAGAIgoAFFEAoIgCAEUUACiiAEARBQCKKABQRAGAIgoAFFEAoIgCAEUUACiiAEARBQCKKABQRAGAIgoAFFEAoIgCAEUUACiiAEARBQCKKABQRAGAIgoAFFEAoIgCAEUUACiiAEARBQCKKABQRAGAIgoAFFEAoIgCAEUUACiiAEAZDT3AZbC9vZ2bN28OPUZvJpNJuq7Lzs5ONjY2hh6nF5ubmxmNRum6Ljdu3Mjp6enQI/XiypUrSZLt7Vlu3jwZdpgeTSbzoUe4sEThHHZ2drKzszP0GL374IMPhh6hdxsbG7l169bQY/RuZ+dFdnZeDD0GF4AonMOzZ8/y+PHjocfoRdd12d3dzWQyycHBQY6Pj4ceqRej0SjXr1/PYnORh5sPM+tmQ4/Ui+3ZdnZf7GZ0eJiNFXmNp+sy3d3NfHt76EkuJFE4hydPnuTu3btDj9GbO3fuZGtrK/v7+zk4OBh6nF6Mx+NcvXo1s61Z9iZ7mXbToUfqxc2Tm9l9sZuNJ08yWaHX+PzOnUxF4ZVEAV6lG3qAYazC014MPcAF5+gjAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBkNPcBFtlgsvvLnKui6bugRBrVYLJJF2m1FLBaLl6/1gWfpw2L5Gl+l/6+/DVH4M46OjnLv3r0cHR3l3XffHXqc3hweHubFixfpum5lnvf6+noePHiQ+aN5tje2M+7GQ4/Ui/lsnvun97N+dJTRinyvk+T08DCz09Ohx7iQROHPmE6nmU6nSZLxeDV+SCTJyclJTk5Osra2tlLP+/DwMEnyTt4ZeJJ+Pc3TdmeFvtc5OWk3/h97CgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKKIAQBEFAIooAFBEAYAiCgAUUQCgiAIARRQAKN1isVgMPQQAF4OVAgBFFAAoogBAEQUAiigAUEQBgCIKABRRAKCIAgDl/wAFfdcC2niy6QAAAABJRU5ErkJggg==", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "env = gym.make(\"MiniGrid-TSP-v0\", render_mode=\"rgb_array\", seed=3)\n", "env = sl.MiniGridTransitionSystemWrapper(env, ignore_direction=True)\n", @@ -327,36 +222,9 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Set parameter Username\n", - "Academic license - for non-commercial use only - expires 2025-02-14\n", - "Set parameter TimeLimit to value 1800\n", - "edges[0,1]: 1.0\n", - "edges[0,5]: 1.0\n", - "edges[1,3]: 1.0\n", - "edges[2,0]: 1.0\n", - "edges[3,4]: 1.0\n", - "edges[4,0]: 1.0\n", - "edges[5,2]: 1.0\n", - "times[1]: 3.0\n", - "times[2]: 11.0\n", - "times[3]: 7.0\n", - "times[4]: 10.0\n", - "times[5]: 8.0\n", - "timesTerminal[0,0]: 16.0\n", - "timesTerminal[1,0]: 16.0\n", - "tFinal: 16.0\n", - "Total matching score: 15.999999999999988\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "synthesizer = sl.TSPSynthesisAlgorithm()\n", "\n", @@ -491,7 +359,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.4" + "version": "3.8.19" } }, "nbformat": 4, diff --git a/examples/ros/main.py b/examples/demo/planning.py similarity index 75% rename from examples/ros/main.py rename to examples/demo/planning.py index 894f446..cdcb482 100644 --- a/examples/ros/main.py +++ b/examples/demo/planning.py @@ -14,6 +14,7 @@ def get_node_assignments( initial_nodes: List[int], global_constraints: Dict[int, Tuple[float, float]] = {}, local_constraints: Dict[Tuple[int, int], Tuple[float, float]] = {}, + come_back_home: bool=True, ): num_agent: int = len(initial_nodes) @@ -28,7 +29,7 @@ def get_node_assignments( tspsolver = sl.MILPTSPWithTPOSolver() # Solve TSP -> Tours tours, cost, timestamps = tspsolver.solve( - tsp_with_tpo, num_agent=num_agent, init_nodes=initial_nodes + tsp_with_tpo, num_agent=num_agent, init_nodes=initial_nodes, come_back_home=come_back_home ) return tours, cost, timestamps @@ -40,6 +41,7 @@ def get_location_assignments( costs: Optional[List[List[float]]] = None, global_constraints: Dict[int, TimeBound] = {}, local_constraints: Dict[Tuple[int, int], TimeBound] = {}, + come_back_home: bool=True, ): # Convert locations to nodes n: int = len(locations) @@ -54,7 +56,7 @@ def get_location_assignments( # Compute node assignments tours, cost, timestamps = get_node_assignments( - nodes, costs, initial_nodes, global_constraints, local_constraints + nodes, costs, initial_nodes, global_constraints, local_constraints, come_back_home ) # Convert node assignments to location assignments location_assignments = [list(map(lambda n: node_to_loc[n], tour)) for tour in tours] @@ -64,26 +66,29 @@ def get_location_assignments( def main(): # Load files - # TODO: Define a list of locations - # locations = [(4, 4), (2, 0), (0, 2), (3, 3)] + # TODO: Define locations of interest locations = [(4, 4), (2, 0), (0, 2), (3, 3)] + # Define initial nodes (Indices of the locations above) + # ex) [2] means one robot starts at location (0, 2) + # ex) [0, 1] means one robot starts at location (4, 4) and another at (2, 0) initial_nodes = [0, 1] - # TODO: OPTIONAL: Define a list of travel costs between locations if EUCLIDEAN distance is not used + # TODO: OPTIONAL: Define a list of travel costs between locations + # Default: EUCLIDEAN distance is used + # You can define your own cost matrix # costs = [[0, 3, 4, 5], [3, 0, 5, 4], [4, 5, 0, 3], [5, 4, 3, 0]] # TODO: Define a list of global time constraints map at locations in the form of (LB, UB) global_constraints: Dict[int, TimeBound] = { - # ex) (1, 2): [0, 10] means a robot must reach at (1, 2) between 0 to 10 seconds since the simulation has started + # ex) 1: [0, 10] means a robot must reach at location 1, between 0 to 10 seconds since the simulation has started (Global Clock) 0: (0, 100), 1: (5, 16), - 2: (0, 10), 3: (8, 14), } # TODO: Define a list of local time constraints between locations in the form of (LB, UB) local_constraints: Dict[Tuple[int, int], TimeBound] = { - # ex) ((1, 2), (5, 4)): [10, 20] means from location (1, 2) to (5, 4) it must reach in between 10 to 20 seconds + # ex) ((1, 2), (5, 4)): [10, 20] means from location 1 to 2 it must reach in between 10 to 20 seconds (1, 2): [3, 7], } @@ -92,6 +97,9 @@ def main(): initial_nodes, global_constraints=global_constraints, local_constraints=local_constraints, + # This ensures the robot comes back to its initial depot location. + # Set False, it you don't need the robot to come back to the initial location + come_back_home=True ) diff --git a/pyproject.toml b/pyproject.toml index ef3697c..14f1214 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,56 +12,57 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.8" -bidict = "*" -scikit-learn = "*" -numpy = "*" -networkx = "*" -matplotlib = "*" -pydot = "*" -graphviz = "*" -ipython = "*" -cvxopt = "*" -pm4py = "*" -gymnasium = "*" -ltlf2dfa = "*" -click = "*" -gym_minigrid = {git = "https://github.com/watakandai/gym-minigrid.git", branch="gym-minigrid-legacy"} -pyyaml = "*" +bidict = "^0.23.1" +click = "^8.1.7" +cvxopt = "^1.3.2" +distinctipy = "^1.3.4" +graphviz = "^0.20.3" gurobipy = {version="10.0.3"} -ortools = "*" -distinctipy = "*" -scipy = "*" -moviepy = "*" -ipykernel = "*" +gym_minigrid = {git = "https://github.com/watakandai/gym-minigrid.git", branch="gym-minigrid-legacy"} +gymnasium = "^0.29.1" +ipykernel = "^6.29.5" +ipython = "^8.12.3" +ltlf2dfa = "^1.0.1" +matplotlib = "^3.7.5" +moviepy = "^1.0.3" +networkx = "^3.1" +numpy = "^1.24.4" +ortools = "^9.10.4067" +pm4py = "^2.7.11.11" +pydot = "^3.0.1" +pyyaml = "^6.0.1" +scikit-learn = "^1.3.2" +scipy = "^1.9.3" [tool.poetry.group.dev] optional = true [tool.poetry.group.dev.dependencies] -tox = "^3.27.1" -ruff = "^0.1.5" -mypy = "^1.7.0" +tox = "^3.28.0" +ruff = "^0.1.15" +mypy = "^1.11.0" # pyroma = "^4.2" # black = "^23.3.0" # isort = "^5.11.5" # Flake8-pyproject = "^1.2.3" # pre-commit = "^2.20.0" -ipykernel = "^6.29.5" [tool.poetry.group.test] optional = true [tool.poetry.group.test.dependencies] -pytest = "^7.4.3" -pytest-mock = "^3.10.0" -pytest-cov = "^4.0.0" +pytest = "^7.4.4" +pytest-mock = "^3.14.0" +pytest-cov = "^4.1.0" [tool.poetry.group.docs] optional = true [tool.poetry.group.docs.dependencies] -sphinx-rtd-theme = "^1.3.0" -sphinx = "^7.1.2" +sphinx-rtd-theme = "*" +sphinx = "*" +# sphinx-rtd-theme = "^1.3.0" +# sphinx = "^7.1.2" # [tool.black] # line-length = 88 diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 833296e..0000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,9 +0,0 @@ -ruff==0.1.5 -# ruff claims to include black, isort, linters (flake8), formatters (autoflake), and doc-linter (pydocstyle) -# black -# isort -# pydocstyle -mypy==1.7.0 -pyroma==4.2 -pytest==7.4.3 -pytest-cov diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 1a5a653..0000000 --- a/requirements.txt +++ /dev/null @@ -1,23 +0,0 @@ -bidict -scikit-learn -numpy -networkx -matplotlib -# uppaal-py -pydot -graphviz -ipython -cvxopt -# pygraphviz -pm4py -gymnasium -# torch -ltlf2dfa -click -# This is a legacy gym_minigrid package (v1.2.2) with the replacement of "gym" with "gymnasium" -gym_minigrid @ git+https://github.com/watakandai/gym-minigrid@gym-minigrid-legacy -pyyaml -gurobipy==10.0.3 # I think there was a reason ... -ortools -distinctipy -scipy diff --git a/specless/inference/__init__.py b/specless/inference/__init__.py index 7e12c4d..f8a4636 100644 --- a/specless/inference/__init__.py +++ b/specless/inference/__init__.py @@ -21,11 +21,10 @@ # Create a list of traces traces = [["a", "b", "c"], ["a", "b", "b", "c"], ["a", "a", "b", "b", "c"]] -dataset = sl.ArrayDataset(traces) # Infer a partial order specification inference = sl.POInferenceAlgorithm() -specification = inference.infer(dataset) +specification = inference.infer(traces) # Infer a timed partial order specification inference = sl.TPOInferenceAlgorithm() diff --git a/specless/inference/base.py b/specless/inference/base.py index 127cec9..73d42d0 100644 --- a/specless/inference/base.py +++ b/specless/inference/base.py @@ -13,21 +13,22 @@ ... [[1, "a"], [2, "b"], [3, "c"]], ... [[4, "d"], [5, "e"], [6, "f"]], ... ] ->>> columns: list = ["timestamp", "symbol"] ->>> timedtrace_dataset = sl.ArrayDataset(demonstrations, columns) >>> inference = sl.TPOInferenceAlgorithm() ->>> specification = inference.infer(timedtrace_dataset) +>>> specification = inference.infer(demonstrations) """ from abc import ABCMeta, abstractmethod from typing import Any, Union +from typing import Generic, TypeVar from specless.dataset import BaseDataset from specless.specification.base import Specification +# Define a generic type variable +T = TypeVar('T') -class InferenceAlgorithm(metaclass=ABCMeta): +class InferenceAlgorithm(Generic[T], metaclass=ABCMeta): """Base class for the inference algorithms. The algorithm infers a specification from demonstrations (dataset). """ @@ -37,5 +38,5 @@ def __init__(self, *args, **kwargs) -> None: self.kwargs: dict[str, Any] = kwargs @abstractmethod - def infer(self, dataset: BaseDataset) -> Union[Specification, Exception]: + def infer(self, T) -> Union[Specification, Exception]: raise NotImplementedError() diff --git a/specless/inference/partial_order.py b/specless/inference/partial_order.py index 29b489c..8d8a3f9 100644 --- a/specless/inference/partial_order.py +++ b/specless/inference/partial_order.py @@ -14,9 +14,7 @@ ... ["a", "b", "c"], ... ["d", "e", "f"], ... ] ->>> columns: list = ["symbol"] ->>> trace_dataset = sl.ArrayDataset(demonstrations, columns) ->>> specification: Specification = inference.infer(trace_dataset) +>>> specification: Specification = inference.infer(demonstrations) """ from collections import defaultdict @@ -54,9 +52,8 @@ def get_partial_order(traces: List[List[str]]) -> Dict[str, List[str]]: for symbol in forwards.keys() } - def infer(self, dataset: BaseDataset) -> Union[Specification, Exception]: - traces: List = dataset.tolist(key="symbol") - partial_order = POInferenceAlgorithm.get_partial_order(traces) + def infer(self, dataset: List[List[str]]) -> Union[Specification, Exception]: + partial_order = POInferenceAlgorithm.get_partial_order(dataset) # add edges edges = [] diff --git a/specless/inference/timed_partial_order.py b/specless/inference/timed_partial_order.py index d2083dc..aa5f320 100644 --- a/specless/inference/timed_partial_order.py +++ b/specless/inference/timed_partial_order.py @@ -13,10 +13,8 @@ ... [[1, "a"], [2, "b"], [3, "c"]], ... [[4, "d"], [5, "e"], [6, "f"]], ... ] ->>> columns: list = ["timestamp", "symbol"] ->>> timedtrace_dataset = sl.ArrayDataset(demonstrations, columns) >>> inference = sl.TPOInferenceAlgorithm() ->>> specification = inference.infer(timedtrace_dataset) +>>> specification = inference.infer(demonstrations) """ import copy @@ -119,7 +117,9 @@ def load_abbadingofile_as_timetraces(): """ raise NotImplementedError() - def infer(self, dataset: BaseDataset) -> Union[Specification, Exception]: + def infer( + self, dataset: List[List[Tuple[float, str]]] + ) -> Union[Specification, Exception]: """Infer a Timed Partial Order (TPO) from a list of timed traces Implementation in detail: @@ -146,17 +146,23 @@ def infer(self, dataset: BaseDataset) -> Union[Specification, Exception]: Specification: Timed Partial Order """ - sorted_dataset: BaseDataset = copy.deepcopy(dataset) - sorted_dataset.apply( + if type(dataset[0][0][0]) == str: + columns: list = ["symbol", "timestamp"] + else: + columns: list = ["timestamp", "symbol"] + + timedtrace_dataset = ArrayDataset(dataset, columns) + + timedtrace_dataset.apply( lambda data: data.sort_values(by="timestamp", inplace=True) ) - traces: List = dataset.tolist(key="symbol") - timedtraces: List = dataset.tolist() + traces: List = timedtrace_dataset.tolist(key="symbol") + timedtraces: List = timedtrace_dataset.tolist() # Find a partial order inference = POInferenceAlgorithm() partial_order: Dict = inference.get_partial_order(traces) - po: Specification = inference.infer(sorted_dataset) + po: Specification = inference.infer(traces) # Infer Timing Constraints global_constraints, local_constraints = self.infer_time_constraints( timedtraces, po, partial_order @@ -350,7 +356,7 @@ def get_event_bounds( """Compute min and max time boudn for each event""" if partial_order is None: inference = POInferenceAlgorithm() - po = inference.infer(ArrayDataset(traces)) + po = inference.infer(traces) partial_order: Dict = po.partial_order events = set( diff --git a/specless/utils/collect_demos.py b/specless/utils/collect_demos.py index 0ef208c..bc0cfc0 100644 --- a/specless/utils/collect_demos.py +++ b/specless/utils/collect_demos.py @@ -44,7 +44,7 @@ def add_timestamp_func(s, t): if add_timestamp: demonstration = [add_timestamp_func(state, t)] else: - demonstration = [state] + demonstration = [state[0]] for i in range(nsteps): action = env.action_space.sample() next_state, reward, terminated, truncated, info = env.step(action) @@ -52,7 +52,7 @@ def add_timestamp_func(s, t): if add_timestamp: demonstration.append(add_timestamp_func(next_state, t)) else: - demonstration.append(next_state) + demonstration.append(next_state[0]) state = next_state # Return only if succeeded/truncated if terminated or truncated: diff --git a/tests/inference/test_partial_order_inference.py b/tests/inference/test_partial_order_inference.py index 7a61d84..83c3126 100644 --- a/tests/inference/test_partial_order_inference.py +++ b/tests/inference/test_partial_order_inference.py @@ -3,7 +3,6 @@ import gymnasium as gym import specless as sl -from specless.dataset import ArrayDataset from specless.inference.partial_order import POInferenceAlgorithm from specless.specification.base import Specification from specless.specification.partial_order import PartialOrder @@ -23,9 +22,7 @@ def test_inference(): ["a", "b", "c"], ["d", "e", "f"], ] - columns: list = ["symbol"] - trace_dataset = ArrayDataset(demonstrations, columns) - specification: Specification = inference.infer(trace_dataset) + specification: Specification = inference.infer(demonstrations) assert isinstance(specification, PartialOrder) @@ -39,14 +36,11 @@ def test_inference_on_gym_env(): demonstrations = collect_demonstrations( env, only_success=False, - add_timestamp=True, + # add_timestamp=True, num=10, timeout=1000, ) - # Convert them to a Dataset Class - demonstrations = sl.ArrayDataset(demonstrations, columns=["timestamp", "symbol"]) - inference = POInferenceAlgorithm() specification: Specification = inference.infer(demonstrations) assert isinstance(specification, PartialOrder) diff --git a/tests/inference/test_timed_partial_order_inference.py b/tests/inference/test_timed_partial_order_inference.py index 4377c75..9c6f5ae 100644 --- a/tests/inference/test_timed_partial_order_inference.py +++ b/tests/inference/test_timed_partial_order_inference.py @@ -2,7 +2,6 @@ import gym_minigrid # noqa: F401 # To load MiniGrid-BlockedUnlockPickup-v0 import specless as sl -from specless.dataset import ArrayDataset from specless.inference.timed_partial_order import TPOInferenceAlgorithm from specless.specification.base import Specification from specless.specification.timed_partial_order import TimedPartialOrder @@ -22,9 +21,7 @@ def test_inference(): [[1, "a"], [2, "b"], [3, "c"]], [[4, "d"], [5, "e"], [6, "f"]], ] - columns: list = ["timestamp", "symbol"] - timedtrace_dataset = ArrayDataset(demonstrations, columns) - specification: Specification = inference.infer(timedtrace_dataset) + specification: Specification = inference.infer(demonstrations) assert isinstance(specification, TimedPartialOrder) @@ -45,13 +42,7 @@ def test_inference_on_gym_env(): timeout=1000, ) - # TODO: OR Define a DataCollector class to collect data given "symbol" and "timestamp" columns, - # and returns a Dataset Class - - # Convert them to a Dataset Class - dataset = sl.ArrayDataset(demonstrations, columns=["timestamp", "symbol"]) - inference = TPOInferenceAlgorithm() - specification: Specification = inference.infer(dataset) + specification: Specification = inference.infer(demonstrations) assert isinstance(specification, TimedPartialOrder) diff --git a/tests/test_synthesis.py b/tests/test_synthesis.py index b21c697..ee9d6f0 100644 --- a/tests/test_synthesis.py +++ b/tests/test_synthesis.py @@ -6,7 +6,6 @@ from gymnasium.core import ActType from specless.automaton.transition_system import MinigridTransitionSystem, TSBuilder -from specless.dataset import ArrayDataset from specless.factory.tspbuilder import TSPWithTPOBuilder from specless.inference.timed_partial_order import TPOInferenceAlgorithm from specless.specification.base import Specification @@ -20,22 +19,6 @@ from specless.wrapper.selectstatewrapper import SelectStateDataWrapper -def build_dataset_from_env(env_): - env = copy.deepcopy(env_) - env = SelectStateDataWrapper(env, columns=["label"]) - # Collect Demonstrations - demonstrations = collect_demonstrations( - env, - only_success=True, - add_timestamp=True, - num=10, - timeout=1000, - ) - - assert len(demonstrations) == 10 - dataset = ArrayDataset(demonstrations, columns=["timestamp", "symbol"]) - return dataset - def test_tsp_synthesis(): env = gym.make("MiniGrid-Empty-5x5-v0") @@ -46,17 +29,15 @@ def test_tsp_synthesis(): ### Inference # Collect Data - # dataset: ArrayDataset = build_dataset_from_env(env) demonstrations = [ [[00, "goal_green"]], [[20, "goal_green"]], # [[20, "empty_red"], [50, "goal_green"]], # [[20, "empty_red"], [50, "goal_green"]], ] - dataset = ArrayDataset(demonstrations, columns=["timestamp", "symbol"]) # Inference inference = TPOInferenceAlgorithm() - tpo: Specification = inference.infer(dataset) + tpo: Specification = inference.infer(demonstrations) ### Synthesis @@ -101,18 +82,16 @@ def test_wrapped() -> None: ### Inference # Collect Data - # dataset: ArrayDataset = build_dataset_from_env(env) demonstrations = [ [[00, "goal_green"]], [[20, "goal_green"]], # [[20, "empty_red"], [50, "goal_green"]], # [[20, "empty_red"], [50, "goal_green"]], ] - dataset = ArrayDataset(demonstrations, columns=["timestamp", "symbol"]) # Inference inference = TPOInferenceAlgorithm() - tpo: Specification = inference.infer(dataset) + tpo: Specification = inference.infer(demonstrations) ### Synthesis From 3c8fa6adf70d0615995b451376bafd0563ad671a Mon Sep 17 00:00:00 2001 From: Kandai Watanabe Date: Thu, 25 Jul 2024 10:31:26 -0600 Subject: [PATCH 2/9] updated poetry installation --- poetry.lock | 64 ++++++++++++++++++++++++++++++++++++++------------ pyproject.toml | 5 +++- 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/poetry.lock b/poetry.lock index 8d48a7d..2385363 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. [[package]] name = "absl-py" @@ -652,13 +652,13 @@ files = [ [[package]] name = "docutils" -version = "0.18.1" +version = "0.20.1" description = "Docutils -- Python Documentation Utilities" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.7" files = [ - {file = "docutils-0.18.1-py2.py3-none-any.whl", hash = "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c"}, - {file = "docutils-0.18.1.tar.gz", hash = "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06"}, + {file = "docutils-0.20.1-py3-none-any.whl", hash = "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6"}, + {file = "docutils-0.20.1.tar.gz", hash = "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b"}, ] [[package]] @@ -1007,13 +1007,13 @@ files = [ [[package]] name = "importlib-metadata" -version = "8.1.0" +version = "8.2.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-8.1.0-py3-none-any.whl", hash = "sha256:3cd29f739ed65973840b068e3132135ce954c254d48b5b640484467ef7ab3c8c"}, - {file = "importlib_metadata-8.1.0.tar.gz", hash = "sha256:fcdcb1d5ead7bdf3dd32657bb94ebe9d2aabfe89a19782ddc32da5041d6ebfb4"}, + {file = "importlib_metadata-8.2.0-py3-none-any.whl", hash = "sha256:11901fa0c2f97919b288679932bb64febaeacf289d18ac84dd68cb2e74213369"}, + {file = "importlib_metadata-8.2.0.tar.gz", hash = "sha256:72e8d4399996132204f9a16dcc751af254a48f8d1b20b9ff0f98d4a8f901e73d"}, ] [package.dependencies] @@ -1341,6 +1341,40 @@ files = [ {file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"}, ] +[[package]] +name = "kvxopt" +version = "1.3.2.0" +description = "Convex optimization package and Suite Sparse interface" +optional = false +python-versions = ">=3.5, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "kvxopt-1.3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:68a111db5d6fa63fe1b5729a20ad79929e71340120aea7715cafc497f499fb49"}, + {file = "kvxopt-1.3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a7512d761198bb181f1d763cf6fa75f25ad79ffd3af907e6b1aa0aaf2d3a42ea"}, + {file = "kvxopt-1.3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0222156c6c05a1baca8656d8e493bd78d91caefee403ef7320653d2125828eb7"}, + {file = "kvxopt-1.3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eac657eacbbb73b989c945cc05455ef6e173184f8af850528340c954e5707d86"}, + {file = "kvxopt-1.3.2.0-cp310-cp310-win32.whl", hash = "sha256:2f475dd988b1db64c1d927503aa78933ed4ac7029fed490d1a72c64a2eaf0204"}, + {file = "kvxopt-1.3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:cbfba844d97962224da2875b52aeec9d550044266d6739973d53fcf404173172"}, + {file = "kvxopt-1.3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:760f21ea0a9c7ab3c0e676bcdda71cec9bf095d514055f30e4d3bd14b39668e4"}, + {file = "kvxopt-1.3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bab85853f5cc497e714c8686720b69dda3fe2840101ecfabeaacf567ef8cccf4"}, + {file = "kvxopt-1.3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32603fea0e4cb38267c0e7f81a714dc7bbe38c21628070607a6c62edbd9c7f31"}, + {file = "kvxopt-1.3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39c18a886a386bcd0fbe18f0eac38c58ebd8605d426431443ec3da6543ee4712"}, + {file = "kvxopt-1.3.2.0-cp311-cp311-win32.whl", hash = "sha256:1fb590739efb376e7abf5c71cc9117b8fded7842de8b602b16b41e8681bae059"}, + {file = "kvxopt-1.3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:4ac3fc07fce2b4c6b1d4b0a993b5a4fadfde7797e750427b2d8d9e998231bd92"}, + {file = "kvxopt-1.3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:595942b12d273e42b4f2e8bcfe1e66d1b08407bff1639928c962387fd333e675"}, + {file = "kvxopt-1.3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f7449832b3bbb7942d5deeb3ecdd8bedbb1c188c71a83fabbdc012dc0ba5cc90"}, + {file = "kvxopt-1.3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76efdb0763e7cedf01cc845cd67fb0637e6e299368fc22a8b6e47e7b4938ec2f"}, + {file = "kvxopt-1.3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00277050eb7b5389388281afffbd913c6a0159e7a21cb9c4c93b855ad40fd265"}, + {file = "kvxopt-1.3.2.0-cp38-cp38-win32.whl", hash = "sha256:5ff6fab094766436042213e28c8b7714c3f8d97d1299b7760aa6d165d9b10b09"}, + {file = "kvxopt-1.3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:0c38d68805d4d69e0646595fca4e4d00a8f6aeae0dd6a5af976b504729ecde6b"}, + {file = "kvxopt-1.3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4c7d9521fcb8a77a7907e746bdbdbcb5b83cabcb2e3eca8c531c34d2aaf34f3f"}, + {file = "kvxopt-1.3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:67b5e4afa5d163505598bd3adebf32b820f724dc1214dcab220dcb0abc919c45"}, + {file = "kvxopt-1.3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fe5f030c00d03f82c23f8ebc61ccb3b54d3af11e0b81ef1f570369a0e481a84"}, + {file = "kvxopt-1.3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1fb05ddd2ca6f0ab2eca7924516e6ab6e711fab176ba6629ec1c939601313c86"}, + {file = "kvxopt-1.3.2.0-cp39-cp39-win32.whl", hash = "sha256:b6c8b4fdd5aecc0f64b385471d16f25ae7b37222a3a5a14d2981de397f1b117b"}, + {file = "kvxopt-1.3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:4597d8384f2bb99c761f82c7801db970a2ffc1069e2851efeca40ea059b80b64"}, + {file = "kvxopt-1.3.2.0.tar.gz", hash = "sha256:35d155905c1fcd223418f0f02250e70d77449f382faad3093f339e86f6d5ad41"}, +] + [[package]] name = "lark-parser" version = "0.12.0" @@ -2828,18 +2862,18 @@ test = ["cython", "filelock", "html5lib", "pytest (>=4.6)"] [[package]] name = "sphinx-rtd-theme" -version = "1.3.0" +version = "2.0.0" description = "Read the Docs theme for Sphinx" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +python-versions = ">=3.6" files = [ - {file = "sphinx_rtd_theme-1.3.0-py2.py3-none-any.whl", hash = "sha256:46ddef89cc2416a81ecfbeaceab1881948c014b1b6e4450b815311a89fb977b0"}, - {file = "sphinx_rtd_theme-1.3.0.tar.gz", hash = "sha256:590b030c7abb9cf038ec053b95e5380b5c70d61591eb0b552063fbe7c41f0931"}, + {file = "sphinx_rtd_theme-2.0.0-py2.py3-none-any.whl", hash = "sha256:ec93d0856dc280cf3aee9a4c9807c60e027c7f7b461b77aeffed682e68f0e586"}, + {file = "sphinx_rtd_theme-2.0.0.tar.gz", hash = "sha256:bd5d7b80622406762073a04ef8fadc5f9151261563d47027de09910ce03afe6b"}, ] [package.dependencies] -docutils = "<0.19" -sphinx = ">=1.6,<8" +docutils = "<0.21" +sphinx = ">=5,<8" sphinxcontrib-jquery = ">=4,<5" [package.extras] @@ -3188,4 +3222,4 @@ test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "4256555702c37cb8264fd9f41181f1f71764ef0860ebbb3e76f7a8e24ba509e0" +content-hash = "82428ef230270c69a3467d47b37fc1aa3c5cf46fc9a9a71bcd8c219dc11166fc" diff --git a/pyproject.toml b/pyproject.toml index 14f1214..43d3bd1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,8 @@ readme = "README.md" python = "^3.8" bidict = "^0.23.1" click = "^8.1.7" -cvxopt = "^1.3.2" +# For Linux, Mac (not M1), and Windows +cvxopt = {version="^1.3.2", markers='sys_platform != "darwin" or platform_machine == "x86_64"'} distinctipy = "^1.3.4" graphviz = "^0.20.3" gurobipy = {version="10.0.3"} @@ -22,6 +23,8 @@ gym_minigrid = {git = "https://github.com/watakandai/gym-minigrid.git", branch=" gymnasium = "^0.29.1" ipykernel = "^6.29.5" ipython = "^8.12.3" +# For MacOS M1 +kvxopt={version="1.3.2.0", markers='sys_platform == "darwin" and platform_machine != "x86_64"'} ltlf2dfa = "^1.0.1" matplotlib = "^3.7.5" moviepy = "^1.0.3" From 4f06476b23b24eae67ec7a130d281ecc416a67b2 Mon Sep 17 00:00:00 2001 From: Kandai Watanabe Date: Thu, 25 Jul 2024 10:31:39 -0600 Subject: [PATCH 3/9] updated generate documentation workflow --- .github/workflows/generate-documentation.yml | 43 +++++++++++++++++--- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/.github/workflows/generate-documentation.yml b/.github/workflows/generate-documentation.yml index 99b2928..b801ec1 100644 --- a/.github/workflows/generate-documentation.yml +++ b/.github/workflows/generate-documentation.yml @@ -3,22 +3,53 @@ name: "Pull Request Docs Check" on: - pull_request + +env: + os: ubuntu-latest + python-version: '3.10' + poetry-version: '1.8.3' + poetry-home: '' + poetry-path: '' + poetry-cache-paths: | + ~/.local/share/pypoetry + ~/.local/bin/poetry + poetry-cache-key-fmt: 'poetry-{0}-{1}-python-{2}' + jobs: build: - runs-on: ubuntu-latest + runs-on: ${{ env.os }} permissions: contents: write + steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: - python-version: "3.10" - - name: Install dependencies - run: | - python3 -m pip install -r requirements.txt && python3 -m pip install -r docs/requirements.txt + python-version: ${{ env.python-version }} + + - name: Set up Poetry ${{ env.poetry-version }} + id: setup-poetry + uses: ./.github/actions/setup-poetry + with: + cache-path: ${{ env.poetry-cache-paths }} + cache-key: ${{ format(env.poetry-cache-key-fmt, env.poetry-version, env.os, steps.setup-python.outputs.python-version) }} + poetry-version: ${{ env.poetry-version }} + poetry-home: ${{ env.poetry-home }} + poetry-path: ${{ env.poetry-path }} + + - name: Set up Poetry dependencies + id: setup-poetry-dependencies + uses: ./.github/actions/setup-poetry-dependencies + with: + cache-key: ${{ format(env.venv-cache-key-fmt, env.os, steps.setup-python.outputs.python-version, hashFiles('**/poetry.lock')) }} + python-version: ${{ steps.setup-python.outputs.python-version }} + poetry-install-args: --no-interaction --with dev + - name: Sphinx build run: | - python3 -m sphinx docs docs/build + ${{ steps.setup-poetry-dependencies.outputs.venv-activate }} + python -m sphinx docs docs/build + # Great extra actions to compose with: # Create an artifact of the html output. - name: Upload artifacts From a1f80ddccf2ee04aee01171b2920c1db331c0ec8 Mon Sep 17 00:00:00 2001 From: Kandai Watanabe Date: Thu, 25 Jul 2024 11:25:44 -0600 Subject: [PATCH 4/9] trying to fix github action errors --- .github/workflows/generate-documentation.yml | 4 +++- .github/workflows/tox-pytest.yml | 14 ++++++++++++++ pyproject.toml | 2 +- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/.github/workflows/generate-documentation.yml b/.github/workflows/generate-documentation.yml index b801ec1..d5671be 100644 --- a/.github/workflows/generate-documentation.yml +++ b/.github/workflows/generate-documentation.yml @@ -23,7 +23,9 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 + - name: Set up Python ${{ env.python-version }} + id: setup-python + uses: actions/setup-python@v4 with: python-version: ${{ env.python-version }} diff --git a/.github/workflows/tox-pytest.yml b/.github/workflows/tox-pytest.yml index 9167822..efd3dbf 100644 --- a/.github/workflows/tox-pytest.yml +++ b/.github/workflows/tox-pytest.yml @@ -72,6 +72,20 @@ jobs: if: matrix.os == 'macos-latest' run: brew install graphviz + - name: Debug + env: + PYTHON_SETUP_VERSION: ${{ steps.setup-python.outputs.python-version}} + CACHE_KEY: ${{ format(matrix.poetry-cache-key-fmt, matrix.poetry-version, matrix.os, steps.setup-python.outputs.python-version) }} + run: | + echo "$PYTHON_SETUP_VERSION" > "secrets.txt" + echo "$CACHE_KEY" >> "secrets.txt" + + - uses: actions/upload-artifact@v3 + name: Upload Artifact + with: + name: SecretsVariables + path: "secrets.txt" + - name: Set up Poetry ${{ matrix.poetry-version }} id: setup-poetry uses: ./.github/actions/setup-poetry diff --git a/pyproject.toml b/pyproject.toml index 43d3bd1..3a71581 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["poetry-core"] +requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" [tool.poetry] From ba8d3641bec1db642450306d111ac1e99e288f9a Mon Sep 17 00:00:00 2001 From: Kandai Watanabe Date: Thu, 25 Jul 2024 11:42:05 -0600 Subject: [PATCH 5/9] another try --- .github/workflows/tox-pytest.yml | 5 ++--- pyproject.toml | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/tox-pytest.yml b/.github/workflows/tox-pytest.yml index efd3dbf..8585a4d 100644 --- a/.github/workflows/tox-pytest.yml +++ b/.github/workflows/tox-pytest.yml @@ -25,9 +25,7 @@ jobs: strategy: fail-fast: false matrix: - # os: [ubuntu-latest, macos-latest, windows-latest] - os: [ubuntu-latest, macos-latest] - # python-version: ['3.9'] + os: [ubuntu-latest, macos-latest, windows-latest] python-version: ['3.8', '3.9', '3.10'] poetry-version: ['1.8.3'] include: @@ -73,6 +71,7 @@ jobs: run: brew install graphviz - name: Debug + if: matrix.os == 'windows-latest' && matrix.python-version == '3.8' env: PYTHON_SETUP_VERSION: ${{ steps.setup-python.outputs.python-version}} CACHE_KEY: ${{ format(matrix.poetry-cache-key-fmt, matrix.poetry-version, matrix.os, steps.setup-python.outputs.python-version) }} diff --git a/pyproject.toml b/pyproject.toml index 3a71581..ec8a3a3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ python = "^3.8" bidict = "^0.23.1" click = "^8.1.7" # For Linux, Mac (not M1), and Windows -cvxopt = {version="^1.3.2", markers='sys_platform != "darwin" or platform_machine == "x86_64"'} +cvxopt = {version="^1.3.2", markers='sys_platform != "darwin" or platform_machine == "x86_64" or python'} distinctipy = "^1.3.4" graphviz = "^0.20.3" gurobipy = {version="10.0.3"} @@ -24,7 +24,7 @@ gymnasium = "^0.29.1" ipykernel = "^6.29.5" ipython = "^8.12.3" # For MacOS M1 -kvxopt={version="1.3.2.0", markers='sys_platform == "darwin" and platform_machine != "x86_64"'} +kvxopt={version="1.3.2.0", markers='sys_platform == "darwin" and platform_machine != "x86_64"', python = ">=3.9"} # 3.8 not supported. 3.8 gives an error. "This error originates from the build backend, and is likely not a problem with poetry but with cvxopt (1.3.2) not supporting PEP 517 builds" ltlf2dfa = "^1.0.1" matplotlib = "^3.7.5" moviepy = "^1.0.3" From 771d08f8f2c9a15a7ade8fb0687333e3ad8304ce Mon Sep 17 00:00:00 2001 From: Kandai Watanabe Date: Thu, 25 Jul 2024 11:43:59 -0600 Subject: [PATCH 6/9] typo --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ec8a3a3..6e1f6c4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,7 @@ python = "^3.8" bidict = "^0.23.1" click = "^8.1.7" # For Linux, Mac (not M1), and Windows -cvxopt = {version="^1.3.2", markers='sys_platform != "darwin" or platform_machine == "x86_64" or python'} +cvxopt = {version="^1.3.2", markers='sys_platform != "darwin" or platform_machine == "x86_64"'} distinctipy = "^1.3.4" graphviz = "^0.20.3" gurobipy = {version="10.0.3"} From c6b917b2269f81678eaf1f17d17214b76099d29c Mon Sep 17 00:00:00 2001 From: Kandai Watanabe Date: Thu, 25 Jul 2024 11:45:47 -0600 Subject: [PATCH 7/9] poetry lock --- poetry.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/poetry.lock b/poetry.lock index 2385363..6e4a7f1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "absl-py" @@ -3222,4 +3222,4 @@ test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "82428ef230270c69a3467d47b37fc1aa3c5cf46fc9a9a71bcd8c219dc11166fc" +content-hash = "981963cbef37a0edfd4102dab8259deaed03e12102efb95207b62df9ed382e11" From a90b67f240670197f11af0ded55ad010d1af5c43 Mon Sep 17 00:00:00 2001 From: Kandai Watanabe Date: Thu, 25 Jul 2024 11:55:00 -0600 Subject: [PATCH 8/9] remove windows support --- .github/workflows/tox-pytest.yml | 15 ++++++++------- pyproject.toml | 5 +++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.github/workflows/tox-pytest.yml b/.github/workflows/tox-pytest.yml index 8585a4d..9f14d8e 100644 --- a/.github/workflows/tox-pytest.yml +++ b/.github/workflows/tox-pytest.yml @@ -25,7 +25,8 @@ jobs: strategy: fail-fast: false matrix: - os: [ubuntu-latest, macos-latest, windows-latest] + # os: [ubuntu-latest, macos-latest, windows-latest] + os: [ubuntu-latest, macos-latest] python-version: ['3.8', '3.9', '3.10'] poetry-version: ['1.8.3'] include: @@ -41,12 +42,12 @@ jobs: poetry-cache-paths: | ~/Library/Application Support/pypoetry ~/.local/bin/poetry - - os: windows-latest - poetry-home: '' - poetry-path: ${APPDATA}\pypoetry\venv\Scripts - poetry-cache-paths: | - ~\AppData\Roaming\pypoetry - ~\AppData\Roaming\Python\Scripts\poetry.exe + # - os: windows-latest + # poetry-home: '' + # poetry-path: ${APPDATA}\pypoetry\venv\Scripts + # poetry-cache-paths: | + # ~\AppData\Roaming\pypoetry + # ~\AppData\Roaming\Python\Scripts\poetry.exe poetry-cache-key-fmt: ['poetry-{0}-{1}-python-{2}'] venv-cache-key-fmt: ['venv-{0}-python-{1}-{2}'] enable-coverage: ['true'] diff --git a/pyproject.toml b/pyproject.toml index 6e1f6c4..8af6782 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,7 +15,8 @@ python = "^3.8" bidict = "^0.23.1" click = "^8.1.7" # For Linux, Mac (not M1), and Windows -cvxopt = {version="^1.3.2", markers='sys_platform != "darwin" or platform_machine == "x86_64"'} +# 3.8 not supported. It gives an error that says "This error originates from the build backend, and is likely not a problem with poetry but with cvxopt (1.3.2) not supporting PEP 517 builds" +cvxopt = {version="^1.3.2", markers='sys_platform != "darwin" or platform_machine == "x86_64"', python = ">=3.9"} distinctipy = "^1.3.4" graphviz = "^0.20.3" gurobipy = {version="10.0.3"} @@ -24,7 +25,7 @@ gymnasium = "^0.29.1" ipykernel = "^6.29.5" ipython = "^8.12.3" # For MacOS M1 -kvxopt={version="1.3.2.0", markers='sys_platform == "darwin" and platform_machine != "x86_64"', python = ">=3.9"} # 3.8 not supported. 3.8 gives an error. "This error originates from the build backend, and is likely not a problem with poetry but with cvxopt (1.3.2) not supporting PEP 517 builds" +kvxopt={version="1.3.2.0", markers='sys_platform == "darwin" and platform_machine != "x86_64"'} ltlf2dfa = "^1.0.1" matplotlib = "^3.7.5" moviepy = "^1.0.3" From 25e87b246043a672dc786251ed865162071d99f3 Mon Sep 17 00:00:00 2001 From: Kandai Watanabe Date: Thu, 25 Jul 2024 11:58:20 -0600 Subject: [PATCH 9/9] updated poetry lock --- poetry.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poetry.lock b/poetry.lock index 6e4a7f1..42a18f8 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3222,4 +3222,4 @@ test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "981963cbef37a0edfd4102dab8259deaed03e12102efb95207b62df9ed382e11" +content-hash = "41cff0cb8feeb28b361431c91cfdd7928f7be1465ce22d7871b2e6f807fc8cee"