Expand description
Why, by the verities on thee made good, may they not be my oracles as well, and set me up in hope
Banquo is an offline monitor for Signal Temporal Logic (STL). The name Banquo comes from a character in Shakespeare’s tragedy MacBeth who’s role is to observe in place of the audience.
This library provides expressions and operators to create temporal logic Formula
s to
evaluate timed sequences of system states called Trace
s. Temporal logic formulas are a
system for the evaluation of logical propositions over time are are useful for evaluating the
behaviors of complex systems over time. Behavioral requirements can be something as simple as
The aircraft altitude should always be greater than zero or something more complex like The
vehicle should always brake within 3 seconds if a pedestrian is detected inside of a 60 degree
cone of the front of the vehicle. To determine if a system violates a behavioral requirement,
we can provide a set of system states along with the times each state was recorded called a
Trace
, which the formula can evaluate into a metric value. This process is called monitoring,
making Banquo
a temporal logic monitor. The computed metric value is useful because it can
not only indicate if the requirement was satisfied, it can also provide a measure of distance of
the system from a violation. This enables the use of search-based testing techniques to find
examples of violating inputs by trying to minimize the distance from violation. The most common
type of metric value for evaluating formulas is called robustness, which is a real number
representing the distance of the system state from the polytope representing the set of states
that violate the requirement.
As an example, consider the automatic transmission system in a car. We might create the following requirement when testing the vehicle:
[] ((gear = 3 /\ rpm >= 4000) -> <>[0,3] gear = 4)
This formula reads At every time, if the gear is equal to 3 and the rpm is greater than or equal to 4000, then within the next 3 time-steps the gear should be equal to 4. With a requirement like this, we could attempt to find some combination of system inputs in which the system does not behave properly.
§Examples
A formula is constructed by combining expressions (like a Predicate
), which evaluate states
into metric values, and operators
, which manipulate metric values. An example formula might
look as follows:
use banquo::predicate;
use banquo::operators::{Always, Not, Or};
let p1 = predicate!{ x <= 10.0 };// Expression
let p2 = predicate!{ y <= 3.0 }; // Expression
let formula = Always::unbounded(Or::new(p1, Not::new(p2))); // Operators
In order to evaluate a formula you must provide a Trace
, which is a set of value where each
value has an associated time. A trace is constructed like so:
use banquo::Trace;
let mut t1 = Trace::new();
t1.insert(0.0, 99);
t1.insert(1.0, 100);
t1.insert(2.0, 107);
t1.insert(3.0, 111);
t1.insert(4.0, 115);
let t2 = Trace::from([
(0.0, 99),
(1.0, 100),
(2.0, 107),
(3.0, 111),
(4.0, 115),
]);
Given a Trace
, the formula can be evaluated using the Formula::evaluate
method into a
Result
containing either a Trace
of metric values, or an error.
use std::collections::HashMap;
use banquo::{Formula, Trace, predicate};
use banquo::operators::Always;
// A predicate can only evaluate a named variable set, so we define a helper function to create
// hash maps for a single variable instead of repeating ourselves.
fn state(value: f64) -> HashMap<&'static str, f64> {
HashMap::from([("x", value)])
}
let trace = Trace::from([
(0.0, state(99.0)),
(1.0, state(100.0)),
(2.0, state(107.0)),
(3.0, state(111.0)),
(4.0, state(115.0)),
]);
let phi = Always::unbounded(predicate!{ x <= 110.0 });
let result: Result<Trace<f64>, _> = phi.evaluate(&trace);
Formulas can also be evaluated using the evaluate
function, which returns the first metric
in the output trace on successful evaluation.
use std::collections::HashMap;
use banquo::{EvaluationError, Trace, evaluate, predicate};
use banquo::operators::Always;
// A predicate can only evaluate a named variable set, so we define a helper function to create
// hash maps for a single variable instead of repeating ourselves.
fn state(value: f64) -> HashMap<&'static str, f64> {
HashMap::from([("x", value)])
}
let trace = Trace::from([
(0.0, state(99.0)),
(1.0, state(100.0)),
(2.0, state(107.0)),
(3.0, state(111.0)),
(4.0, state(115.0)),
]);
let phi = Always::unbounded(predicate!{ x <= 110.0 });
let result: Result<f64, EvaluationError> = evaluate(&trace, &phi);
Modules§
- Combinatorial operators for constructing formulas.
- System requirements expressed as the inequality
ax
≤ b
. - A set of values where each value is associated with a time.
Macros§
- Create a
Predicate
from a given algebraic expression.
Structs§
- System requirements expressed as the inequality
ax
≤ b
. - A set of values where each value is associated with a time.
Traits§
- Trait representing a type with a global minimum.
- Trait representing a temporal logic formula that can evaluate a timed set of system states called a
Trace
. - Trait representing a type that can compute the supremum of two values.
- Trait representing a type that can compute the infimum of two values.
- Trait representing a type with a global maximum.