Skip to main content

omega_automata/
lib.rs

1//! # Omega Automata
2//! 
3//!This crate implements decision procedures and algorithms on
4//!__omega-automata__. __Omega-automata__ are similar to the better-known finite
5//!automata (NFA/DFA/...) except they operate on *infinite* words. They are
6//!commonly used to model systems that can run for an infinite time, such as most
7//!algorithms, protocols, and more.
8
9//!For example, model checking temporal logic properties (commonly used in formal
10//!hardware verification) can be implemented with an optimal worst-case time
11//!complexity via omega automata.
12
13//!## Features
14
15//!Currently, this crate supports the following:
16
17//!- LTL to VWABW (*very weak alternating Büchi automaton*) translation.
18//!- VWABW to GBW (*generalized Büchi automaton*) translation.
19//!- GBW to NBW (*non-deterministic Büchi automaton*) translation.
20//!- NBW emptiness check.
21
22//!### Checking LTL formula satsifiability
23
24//!1. Construct an LTL formula
25//!2. Convert it to a VWABW $\mathit{AM}$
26//!3. Convert *AM* to a GBW *GM*
27//!4. Convert *GM* to an NWB *NM*
28//!5. Check the emptyness of *NM*: It is non-empty iff. the LTL formula is satisfiable.
29
30//!## Examples
31
32//! Let's start with the LTL formula `φ = (□◇x₁ ∧ ◇x₁) ∧ (◇(x₃ ∧ □x₂))`.
33//! Intuitively, `φ` states that any sequence `w = s₁, s₂, s₃, … ∈ X^ω`
34//! of variable assignments (the structure LTL is interpreted over) must
35//! first have infinite `x₁ ∈ sᵢ` (also pronounced `w` *must have infinitely
36//! often* `x₁`), and second it must eventually reach a position `sₖ` such that
37//! `x₃, x₂ ∈ sₖ` and `x₂ ∈ sⱼ` for all `sⱼ` following `sₖ` (also
38//! pronounced `x₂` must hold from `sₖ`).
39//! 
40//!```
41//!use omega_automata::{ltl::*, automata::{*,abw::*,gbw::*,nbw::*}};
42//!let mut formulas = Formulas::default();
43//!let p = formulas.atom(1);
44//!let r = formulas.atom(2);
45//!let q = formulas.atom(3);
46//!let Gr = formulas.globally(r);
47//!let q_and_Gr = formulas.and(q, Gr);
48//!let Fq_and_Gr = formulas.finally(q_and_Gr);
49//!let Fp = formulas.finally(p);
50//!let GFp = formulas.globally(Fp);
51//!let intermediate = formulas.and(GFp, Fp);
52//!let notp = formulas.neg(p);
53//!let Fnotp = formulas.finally(notp);
54//!let GFnotp = formulas.globally(Fnotp);
55//!let res = formulas.and(intermediate, Fq_and_Gr);
56//!let res = formulas.and(res, GFnotp);
57//!let normalized = formulas.normalize(res);
58//!let automata = ltl_to_abw(formulas.access(normalized));
59//!let gbw = vwabw_to_gbw(&automata);
60//!let nbw = gbw_to_nbw(&gbw);
61//!let sat = is_nonempty(&nbw);
62//!assert!(sat)
63//! ```
64#![allow(dead_code)]
65#![cfg_attr(test, allow(non_snake_case))]
66pub mod automata;
67pub mod ltl;
68
69#[cfg(test)]
70mod tests {
71    use crate::automata::{
72        abw::ltl_to_abw,
73        gbw::vwabw_to_gbw,
74        nbw::{gbw_to_nbw, is_nonempty},
75    };
76
77    use super::*;
78    #[test]
79    fn example_test() {
80        println!("It Works!")
81    }
82
83    #[test]
84    fn test_sat2() {
85        let mut formulas = ltl::Formulas::default();
86        let p = formulas.atom(1);
87        let r = formulas.atom(2);
88        let q = formulas.atom(3);
89        let Gr = formulas.globally(r);
90        let q_and_Gr = formulas.and(q, Gr);
91        let Fq_and_Gr = formulas.finally(q_and_Gr);
92        let Fp = formulas.finally(p);
93        let GFp = formulas.globally(Fp);
94        let intermediate = formulas.and(GFp, Fp);
95        let notp = formulas.neg(p);
96        let Fnotp = formulas.finally(notp);
97        let GFnotp = formulas.globally(Fnotp);
98        let res = formulas.and(intermediate, Fq_and_Gr);
99        let res = formulas.and(res, GFnotp);
100        let normalized = formulas.normalize(res);
101        let automata = ltl_to_abw(formulas.access(normalized));
102        let gbw = vwabw_to_gbw(&automata);
103        let nbw = gbw_to_nbw(&gbw);
104        let sat = is_nonempty(&nbw);
105        assert!(sat)
106    }
107}