docs(pyargus): create initial documentation for pyargus
This commit is contained in:
parent
d39e3d3e12
commit
69c6c6abc2
7 changed files with 241 additions and 2 deletions
|
|
@ -6,6 +6,11 @@ repos:
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: check-yaml
|
- id: check-yaml
|
||||||
- id: check-added-large-files
|
- id: check-added-large-files
|
||||||
|
- repo: https://github.com/rstcheck/rstcheck
|
||||||
|
rev: 'v6.2.0' # Use the sha / tag you want to point at
|
||||||
|
hooks:
|
||||||
|
- id: rstcheck
|
||||||
|
additional_dependencies: ["sphinx>=4.0"]
|
||||||
- repo: local
|
- repo: local
|
||||||
hooks:
|
hooks:
|
||||||
- id: nox (python)
|
- id: nox (python)
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
|
|
||||||
57
docs/conf.py
Normal file
57
docs/conf.py
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
# Configuration file for the Sphinx documentation builder.
|
||||||
|
#
|
||||||
|
# For the full list of built-in configuration values, see the documentation:
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||||
|
|
||||||
|
# -- Project information -----------------------------------------------------
|
||||||
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||||
|
|
||||||
|
project = "Argus"
|
||||||
|
copyright = "2023, Anand Balakrishnan"
|
||||||
|
author = "Anand Balakrishnan"
|
||||||
|
|
||||||
|
version = "v0.1.0"
|
||||||
|
release = "0.1.0"
|
||||||
|
|
||||||
|
extensions = [
|
||||||
|
"autoapi.extension",
|
||||||
|
"sphinx.ext.doctest",
|
||||||
|
"myst_parser",
|
||||||
|
"sphinx_copybutton",
|
||||||
|
"sphinx.ext.inheritance_diagram",
|
||||||
|
]
|
||||||
|
|
||||||
|
templates_path = ["_templates"]
|
||||||
|
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
|
||||||
|
|
||||||
|
html_theme = "pydata_sphinx_theme"
|
||||||
|
html_static_path = ["_static"]
|
||||||
|
html_theme_options = {"use_edit_page_button": True, "github_url": "https://github.com/anand-bala/argus"}
|
||||||
|
html_context = {
|
||||||
|
"github_user": "anand-bala",
|
||||||
|
"github_repo": "argus",
|
||||||
|
"github_version": "v0.1.0",
|
||||||
|
"doc_path": "docs",
|
||||||
|
}
|
||||||
|
|
||||||
|
source_suffix = {
|
||||||
|
".rst": "restructuredtext",
|
||||||
|
".txt": "markdown",
|
||||||
|
".md": "markdown",
|
||||||
|
}
|
||||||
|
|
||||||
|
autoapi_dirs = ["../pyargus/argus"]
|
||||||
|
autoapi_root = "api"
|
||||||
|
|
||||||
|
|
||||||
|
def skip_members(app, what, name: str, obj, skip, options):
|
||||||
|
# print(f"{what} -> {name}")
|
||||||
|
if what == "data" and name.endswith("__doc__"):
|
||||||
|
skip = True
|
||||||
|
elif name.startswith("argus._argus"):
|
||||||
|
skip = True
|
||||||
|
return skip
|
||||||
|
|
||||||
|
|
||||||
|
def setup(sphinx):
|
||||||
|
sphinx.connect("autoapi-skip-member", skip_members)
|
||||||
98
docs/getting_started.rst
Normal file
98
docs/getting_started.rst
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
Getting Started
|
||||||
|
===============
|
||||||
|
|
||||||
|
The only import required for using ``argus`` is the following:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import argus
|
||||||
|
|
||||||
|
While the core of the library is written in Rust, the ``argus`` package exports all the
|
||||||
|
features in the core library into the top level namespace.
|
||||||
|
|
||||||
|
|
||||||
|
Writing specifications
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
There are two ways to write specifications in ``argus``:
|
||||||
|
|
||||||
|
1. Using the Python API.
|
||||||
|
2. Using a string-based parser.
|
||||||
|
|
||||||
|
For using the Python API, you have access to all the subclasses of :py:class:`argus.Expr`.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
x = argus.VarFloat("x")
|
||||||
|
y = argus.VarFloat("y")
|
||||||
|
print(x > y)
|
||||||
|
# Cmp(Cmp { op: Greater { strict: true }, lhs: FloatVar(FloatVar { name: "x" }), rhs: FloatVar(FloatVar { name: "y" }) })
|
||||||
|
|
||||||
|
Similarly, you can create arithmetic expressions using the builtin Python operators
|
||||||
|
(``+,-,*,/``) on numeric expressions, and Boolean expressions using the builtin Python
|
||||||
|
operators (``&,|,~``). Moreover, you can build temporal expressions as follows:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
phi1 = argus.Eventually(x > y)
|
||||||
|
phi2 = argus.Always(y < argus.ConstFloat(10.0), interval=(0, 10))
|
||||||
|
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
In the above code block, the argument for ``interval`` implies inclusive bounds
|
||||||
|
always. While Signal Temporal Logic supports exclusive bounds, with real-valued
|
||||||
|
signals it is practically impossible to exclude the boundaries of an interval.
|
||||||
|
|
||||||
|
|
||||||
|
On the otherhand, the string-based API uses :py:func:`argus.parse_expr` to generate the
|
||||||
|
expression directly.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
phi1 = argus.parse_expr("F (x > y)")
|
||||||
|
phi2 = argus.parse_expr("G[0, 10] (y < 10.0)")
|
||||||
|
phi3 = argus.parse_expr("G[0..10] (y < 10.0)")
|
||||||
|
# phi2 and phi3 are the same here, just different notation.
|
||||||
|
|
||||||
|
|
||||||
|
Creating signal traces
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
To create signal traces using :py:class:`Trace`:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import random
|
||||||
|
data = dict(
|
||||||
|
x=argus.FloatSignal.from_samples([(i, random.random()) for i in range(20)]),
|
||||||
|
y=argus.FloatSignal.constant(10.0),
|
||||||
|
)
|
||||||
|
trace = argus.Trace(data)
|
||||||
|
|
||||||
|
In the above, ``x`` and ``y`` are both signals that represent ``float``s. Here, ``x`` is
|
||||||
|
created using :py:func:`argus.FloatSignal.from_samples`, which creates a signal from
|
||||||
|
a list of 2-tuples containing the "timestamp" (``i`` here) and the sampled value
|
||||||
|
(``random.random()``).
|
||||||
|
Similarly, ``y`` is a constant signal, i.e., it has a constant value throughout it's
|
||||||
|
domain.
|
||||||
|
|
||||||
|
|
||||||
|
Monitoring traces
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
To monitor traces, one can use either the builtin qualitative semantics (:py:func:`argus.eval_bool_semantics`) or quantitative semantics (:py:func:`argus.eval_robust_semantics`).
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
check: argus.BoolSignal = argus.eval_bool_semantics(phi1, trace)
|
||||||
|
rob: argus.FloatSignal = argus.eval_robust_semantics(phi2, trace)
|
||||||
|
|
||||||
|
The above functions return signals (either Boolean or floating point), and the output of
|
||||||
|
the functions can be found at different points in the time domain where the
|
||||||
|
specifications are defined by using:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
assert check.at(0) == False # x is never > y
|
||||||
|
assert rob.at(0) == 0.0 # y is always == 10.0
|
||||||
60
docs/index.rst
Normal file
60
docs/index.rst
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
Argus: Temporal Logic Monitoring Tool
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
Argus aims to be a tool to generate monitors for Signal Temporal Logic (STL), and its
|
||||||
|
different semantics.
|
||||||
|
|
||||||
|
This library is a direct successor of my `signal-temporal-logic
|
||||||
|
<https://github.com/anand-bala/signal-temporal-logic/>`_ tool, and is inspired by the
|
||||||
|
following projects:
|
||||||
|
|
||||||
|
- `py-metric-temporal-logic`_ is a tool written in pure Python, and provides an elegant
|
||||||
|
interface for evaluating discrete time signals using Metric Temporal Logic (MTL).
|
||||||
|
- `RTAMT`_ is a Python library for offline and online
|
||||||
|
monitoring of STL specifications.
|
||||||
|
- `Breach`_ and `S-TaLiRo`_ are Matlab toolboxes designed for falsification and
|
||||||
|
simulation-based testing of cyber-physical systems with STL and MTL specifications,
|
||||||
|
respectively. One of their various features includes the ability to evaluate the
|
||||||
|
robustness of signals against STL/MTL specifications.
|
||||||
|
|
||||||
|
The goal of this tool is to provide offline and online monitors for Signal Temporal
|
||||||
|
Logic (STL) and its semantics, focussing on performance and ease of use in controllers
|
||||||
|
synthesis and analysis (for training and monitoring them).
|
||||||
|
|
||||||
|
The project name is inspired from `Argus Panoptes`_.
|
||||||
|
|
||||||
|
.. _Argus Panoptes: https://www.britannica.com/topic/Argus-Greek-mythology
|
||||||
|
.. _py-metric-temporal-logic: https://github.com/mvcisback/py-metric-temporal-logic/
|
||||||
|
.. _Breach: https://github.com/decyphir/breach
|
||||||
|
.. _S-TaLiRo: https://sites.google.com/a/asu.edu/s-taliro/s-taliro
|
||||||
|
.. _RTAMT: https://github.com/nickovic/rtamt
|
||||||
|
|
||||||
|
Installing
|
||||||
|
----------
|
||||||
|
|
||||||
|
Currently, I am not publishing the library to PyPI, so you will have to install the
|
||||||
|
package directly from the wheel files in the `latest Github release
|
||||||
|
<https://github.com/anand-bala/argus/releases/latest>`_. For example, to install version
|
||||||
|
``0.1.0`` of the library for Python 3.10 on a Linux distribution running on a 64-bit
|
||||||
|
Intel/AMD machine, you just need to do:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
pip install https://github.com/anand-bala/argus/releases/download/v0.1.0/pyargus-0.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
|
||||||
|
|
||||||
|
|
||||||
|
Contents
|
||||||
|
--------
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
getting_started
|
||||||
|
|
||||||
|
|
||||||
|
Indices and tables
|
||||||
|
==================
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`modindex`
|
||||||
|
* :ref:`search`
|
||||||
|
|
@ -6,6 +6,7 @@ channels:
|
||||||
dependencies:
|
dependencies:
|
||||||
- python>=3.8
|
- python>=3.8
|
||||||
- maturin
|
- maturin
|
||||||
|
- patchelf
|
||||||
- nox
|
- nox
|
||||||
- mypy
|
- mypy
|
||||||
- black
|
- black
|
||||||
|
|
@ -13,7 +14,12 @@ dependencies:
|
||||||
- pytest
|
- pytest
|
||||||
- pytest-cov
|
- pytest-cov
|
||||||
- hypothesis
|
- hypothesis
|
||||||
- pdoc
|
|
||||||
- pip
|
- pip
|
||||||
|
- sphinx
|
||||||
|
- pydata-sphinx-theme
|
||||||
|
- sphinx-copybutton
|
||||||
|
- myst-parser
|
||||||
|
- pip:
|
||||||
|
- sphinx-autoapi
|
||||||
|
|
||||||
category: dev
|
category: dev
|
||||||
|
|
|
||||||
14
noxfile.py
14
noxfile.py
|
|
@ -37,6 +37,20 @@ def dev(session: nox.Session):
|
||||||
session.run("pre-commit", "install")
|
session.run("pre-commit", "install")
|
||||||
|
|
||||||
|
|
||||||
|
@nox.session
|
||||||
|
def docs(session: nox.Session):
|
||||||
|
session.conda_install(
|
||||||
|
"sphinx",
|
||||||
|
"pydata-sphinx-theme",
|
||||||
|
"sphinx-copybutton",
|
||||||
|
"myst-parser",
|
||||||
|
)
|
||||||
|
session.install("sphinx-autoapi")
|
||||||
|
with session.chdir(CURRENT_DIR / "pyargus"):
|
||||||
|
session.install("-e", ".")
|
||||||
|
session.run("sphinx-build", "-b", "html", "docs", "docs/_build/html")
|
||||||
|
|
||||||
|
|
||||||
@nox.session(tags=["style", "fix", "rust"], python=False)
|
@nox.session(tags=["style", "fix", "rust"], python=False)
|
||||||
def rustfmt(session: nox.Session):
|
def rustfmt(session: nox.Session):
|
||||||
if len(session.posargs) > 0:
|
if len(session.posargs) > 0:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue