Skip to main content

A library for manipulating and evaluating metric temporal logic.

Project description

py-metric-temporal logic logo
A library for manipulating and evaluating metric temporal logic.

Build Status codecov PyPI version License: MIT DOI

Table of Contents

About

Python library for working with Metric Temporal Logic (MTL). Metric Temporal Logic is an extension of Linear Temporal Logic (LTL) for specifying properties over time series (See Alur). Some practical examples are given in the usage.

Installation

If you just need to use metric-temporal-logic, you can just run:

$ pip install metric-temporal-logic

For developers, note that this project uses the poetry python package/dependency management tool. Please familarize yourself with it and then run:

$ poetry install

Usage

To begin, we import mtl.

import mtl

There are two APIs for interacting with the mtl module. Namely, one can specify the MTL expression using:

  1. Python Operators.
  2. Strings + The parse API.

We begin with the Python Operator API:

Python Operator API

Propositional logic (using python syntax)

a, b = mtl.parse('a'), mtl.parse('b')
phi0 = ~a
phi1 = a & b
phi2 = a | b
phi3 = a ^ b
phi4 = a.iff(b)
phi5 = a.implies(b)

Modal Logic (using python syntax)

a, b = mtl.parse('a'), mtl.parse('b')

# Eventually `a` will hold.
phi1 = a.eventually()

# `a & b` will always hold.
phi2 = (a & b).always()

# `a` until `b`
phi3 = a.until(b)

# `a` weak until `b`
phi4 = a.weak_until(b)

# Whenever `a` holds, then `b` holds in the next two time units.
phi5 = (a.implies(b.eventually(lo=0, hi=2))).always()

# We also support timed until.
phi6 = a.timed_until(b, lo=0, hi=2)

# `a` holds in two time steps.
phi7 = a >> 2

String based API

Propositional logic (parse api)

# - Lowercase strings denote atomic predicates.
phi0 = mtl.parse('atomicpred')

# - infix operators need to be surrounded by parens.
phi1 = mtl.parse('((a & b & c) | d | e)')
phi2 = mtl.parse('(a -> b) & (~a -> c)')
phi3 = mtl.parse('(a -> b -> c)')
phi4 = mtl.parse('(a <-> b <-> c)')
phi5 = mtl.parse('(x ^ y ^ z)')

# - Unary operators (negation)
phi6 = mtl.parse('~a')
phi7 = mtl.parse('~(a)')

Modal Logic (parser api)

# Eventually `x` will hold.
phi1 = mtl.parse('F x')

# `x & y` will always hold.
phi2 = mtl.parse('G(x & y)')

# `x` holds until `y` holds. 
# Note that since `U` is binary, it requires parens.
phi3 = mtl.parse('(x U y)')

# Weak until (`y` never has to hold).
phi4 = mtl.parse('(x W y)')

# Whenever `x` holds, then `y` holds in the next two time units.
phi5 = mtl.parse('G(x -> F[0, 2] y)')

# We also support timed until.
phi6 = mtl.parse('(a U[0, 2] b)')

# Finally, if time is discretized, we also support the next operator.
# Thus, LTL can also be modeled.
# `a` holds in two time steps.
phi7 = mtl.parse('XX a')

Quantitative Evaluate (Signal Temporal Logic)

Given a property phi, one can evaluate if a timeseries satisifies phi. Time Series can either be defined using a dictionary mapping atomic predicate names to lists of (time, val) pairs or using the DiscreteSignals API (used internally).

There are two types of evaluation. One uses the boolean semantics of MTL and the other uses Signal Temporal Logic like semantics.

# Assumes piece wise constant interpolation.
data = {
    'a': [(0, 100), (1, -1), (3, -2)],
    'b': [(0, 20), (0.2, 2), (4, -10)]
}

phi = mtl.parse('F(a | b)')
print(phi(data))
# output: 100

# Evaluate at t=3
print(phi(data, time=3))
# output: 2

# Evaluate with discrete time
phi = mtl.parse('X b')
print(phi(data, dt=0.2))
# output: 2

Boolean Evaluation

To Boolean semantics can be thought of as a special case of the quantitative semantics where True ↦ 1 and False ↦ -1. This conversion happens automatically using the quantitative=False flag.

# Assumes piece wise constant interpolation.
data = {
    'a': [(0, True), (1, False), (3, False)],
    'b': [(0, False), (0.2, True), (4, False)]
}

phi = mtl.parse('F(a | b)')
print(phi(data, quantitative=False))
# output: True

phi = mtl.parse('F(a | b)')
print(phi(data))
# output: True

# Note, quantitative parameter defaults to False

# Evaluate at t=3. 
print(phi(data, time=3, quantitative=False))
# output: False

# Compute sliding satisifaction.
print(phi(data, time=None, quantitative=False))
# output: [(0, True), (0.2, True), (4, False)]

# Evaluate with discrete time
phi = mtl.parse('X b')
print(phi(data, dt=0.2, quantitative=False))
# output: True

Utilities

import mtl
from mtl import utils

print(utils.scope(mtl.parse('XX a'), dt=0.1))
# output: 0.2

print(utils.discretize(mtl.parse('F[0, 0.2] a'), dt=0.1))
# output: (a | X a | XX a)

Similar Projects

Feel free to open up a pull-request to add other similar projects. This library was written to meet some of my unique needs, for example I wanted the AST to be immutable and wanted the library to just handle manipulating MTL. Many other similar projects exist with different goals.

  1. https://github.com/doganulus/python-monitors
  2. https://github.com/STLInspector/STLInspector

Citing

@misc{pyMTL,
  author       = {Marcell Vazquez-Chanlatte},
  title        = {mvcisback/py-metric-temporal-logic: v0.1.1},
  month        = jan,
  year         = 2019,
  doi          = {10.5281/zenodo.2548862},
  url          = {https://doi.org/10.5281/zenodo.2548862}
}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

metric_temporal_logic-0.4.1.tar.gz (15.8 kB view details)

Uploaded Source

Built Distribution

metric_temporal_logic-0.4.1-py3-none-any.whl (15.4 kB view details)

Uploaded Python 3

File details

Details for the file metric_temporal_logic-0.4.1.tar.gz.

File metadata

  • Download URL: metric_temporal_logic-0.4.1.tar.gz
  • Upload date:
  • Size: 15.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.3.0 CPython/3.10.9 Linux/6.0.12

File hashes

Hashes for metric_temporal_logic-0.4.1.tar.gz
Algorithm Hash digest
SHA256 1c4ba9acc5abe98bcd5ad0654c57af393e1fe207aacf6dedeb40e0e048145dd8
MD5 3de1e919acdf08446eb92727685a2088
BLAKE2b-256 f92f3efd6bfe4681563a5b4b7b6011133d7d356d1f72549c4c86566d5dd32d17

See more details on using hashes here.

File details

Details for the file metric_temporal_logic-0.4.1-py3-none-any.whl.

File metadata

File hashes

Hashes for metric_temporal_logic-0.4.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b06fadab5c4984512c405cb57cf373fddb2e258f5c3033c06e88da8a85ac4b6e
MD5 41c399f4ece3e53b47a1f0ea60084205
BLAKE2b-256 90743b45a6370211c186112666ebe1bee7bf9fe209217151ad1d4bb667162742

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page