Welcome to \(\Psi\)-TaLiRo

\(\Psi\)-TaLiRo is a python toolbox for search-based test generation, typically at the system level. The objective of this library is to make writing and testing requirements for systems fast and easy in order to help facilitate the adoption of formal and semi-formal methods for verifying systems of all kinds. To this end, \(\Psi\)-TaLiRo defines several testing interfaces and multiple ready-to-use implementations so that users can quickly set up tests to ensure no bugs or behavioral violations hide in their systems.

Motivation

Consider that we are designing a simple switching thermostat system described by the following state machine:

_images/thermostat.svg

Source: An Algebra of Hybrid Systems by Bernhard Moller and Peter Hofner (2009).

When designing a system such as this one, we may be curious if there are any system inputs that cause the system to violate its operating bounds. A naive approach would be to test all possible inputs, but in a continuous input space like ours this approach is infeasible. Furthermore, for more complex systems the input space may be very large, making a brute force approach even more intractable. Therefore, we will instead leverage search techniques to test a subset of inputs, using the results from each test to try and select inputs that will put the system closer to violating its operating bounds. In order to do this, we must first create a representation of our system that we can use to simulate its behavior. One possible representation of this system is the following Python class:

import enum

class Thermostat:
    class Mode(enum.IntEnum):
        HEATING = 1
        COOLING = 2

    def __init__(self, initial_temp: float):
        self.temp = initial_temp
        self.mode = Thermostat.Mode.COOLING

    def step(self, step_size: float):
        if self.mode is Thermostat.Mode.COOLING and self.temp < 19:
            self.mode = Thermostat.Mode.HEATING

        if self.mode is Thermostat.Mode.COOLING and self.temp > 21:
            self.mode = Thermostat.Mode.COOLING

        temp_dot = -0.1 * self.temp

        if self.mode is Thermostat.Mode.HEATING:
            temp_dot = 5 + temp_dot

        self.temp = self.temp + temp_dot * step_size

Using this definition, we can define a model component that is responsible for encapsulating the execution logic of the model given a set of inputs.

from staliro import models

STEP_SIZE = 0.1

@models.model()
def thermostat(inputs: models.Sample) -> models.Trace[list[float]]:
    system = Thermostat(inputs.static["temp"])
    states = {}

    for step in range(100):
        time = step * STEP_SIZE
        states[time] = [system.temp]
        system.step(STEP_SIZE)

    return models.Trace(states)

Then we can represent a requirement of our system (in this case that the temperature of the system stays within the interval \([18.0, 22.0]\)) using Signal Temporal Logic.

from staliro import specifications

req = specifications.RTAMTDense("(always (temp >= 18.0 and temp <= 22.0)", {"temp": 0})

Finally, we can instantiate an optimizer and define the test parameters in order to begin executing tests

from staliro import TestOptions, optimizers, staliro

optimizer = optimizers.UniformRandom()
options = TestOptions(
    runs=1,
    iterations=100,
    static_inputs={
        "temp": (18.0, 22.0),
    }
)

runs = staliro(thermostat, req, optimizer, options)

The optimizer we have chosen to use is the Uniform Random optimizer which will generate samples uniformly across the input space. For our test parameters, we run a single optimization attempt, with a sample budget of 100 samples, and we generate a single system input called \(temp\) which will be within the interval \([18.0, 22.0]\). We execute the test by calling the staliro() function, which returns a set of Run values containing all the samples generated by the optimizer, as well as their associated cost values.

To quickly begin setting up your own tests, please refer to the Quickstart and Examples pages. For more in-depth descriptions of the interfaces and components provided by \(\Psi\)-TaLiRo please refer to the API documentation.

Citing this project

To cite our work, please include a reference to the following paper or include our \(Bib\TeX\) entry in your bibliography file.

PSY-TaLiRo: A Python Toolbox for Search-Based Test Generation for Cyber-Physical Systems

@InProceedings{10.1007/978-3-030-85248-1_15,
    author="Thibeault, Quinn and Anderson, Jacob and Chandratre, Aniruddh and Pedrielli, Giulia and Fainekos, Georgios",
    editor="Lluch Lafuente, Alberto and Mavridou, Anastasia",
    title="PSY-TaLiRo: A Python Toolbox for Search-Based Test Generation for Cyber-Physical Systems",
    booktitle="Formal Methods for Industrial Critical Systems",
    year="2021",
    publisher="Springer International Publishing",
    address="Cham",
    pages="223--231",
    isbn="978-3-030-85248-1"
}