1mod numset;
2
3use crate::{Oracle, Time};
4use numset::NumSet;
5use std::hash::Hash;
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
9pub enum Pmtl<V>
10where
11 V: Clone,
12{
13 True,
15 False,
17 Atom(V),
19 And(Vec<Pmtl<V>>),
21 Or(Vec<Pmtl<V>>),
23 Not(Box<Pmtl<V>>),
25 Implies(Box<(Pmtl<V>, Pmtl<V>)>),
27 Historically(Box<Pmtl<V>>, Time, Time),
29 Once(Box<Pmtl<V>>, Time, Time),
31 Since(Box<(Pmtl<V>, Pmtl<V>)>, Time, Time),
33}
34
35#[derive(Debug, Clone, PartialEq, Eq)]
36enum ValPmtl {
37 True,
38 False,
39 Atom(usize, bool),
40 And(Vec<ValPmtl>),
41 Or(Vec<ValPmtl>),
42 Not(Box<ValPmtl>),
43 Implies(Box<(ValPmtl, ValPmtl)>),
44 Historically(Box<ValPmtl>, Time, Time, NumSet),
45 Once(Box<ValPmtl>, Time, Time, NumSet),
46 Since(Box<(ValPmtl, ValPmtl)>, Time, Time, NumSet),
47}
48
49impl From<&Pmtl<usize>> for ValPmtl {
50 fn from(value: &Pmtl<usize>) -> Self {
51 match value {
52 Pmtl::True => ValPmtl::True,
53 Pmtl::False => ValPmtl::False,
54 Pmtl::Atom(a) => ValPmtl::Atom(*a, false),
55 Pmtl::And(pmtls) => ValPmtl::And(pmtls.iter().map(|f| f.into()).collect()),
56 Pmtl::Or(pmtls) => ValPmtl::Or(pmtls.iter().map(|f| f.into()).collect()),
57 Pmtl::Not(pmtl) => ValPmtl::Not(Box::new(pmtl.as_ref().into())),
58 Pmtl::Implies(pmtls) => {
59 ValPmtl::Implies(Box::new(((&pmtls.0).into(), (&pmtls.1).into())))
60 }
61 Pmtl::Historically(pmtl, lb, ub) => {
62 ValPmtl::Historically(Box::new(pmtl.as_ref().into()), *lb, *ub, NumSet::empty())
63 }
64 Pmtl::Once(pmtl, lb, ub) => {
65 ValPmtl::Once(Box::new(pmtl.as_ref().into()), *lb, *ub, NumSet::empty())
66 }
67 Pmtl::Since(pmtls, lb, ub) => ValPmtl::Since(
68 Box::new(((&pmtls.0).into(), (&pmtls.1).into())),
69 *lb,
70 *ub,
71 NumSet::empty(),
72 ),
73 }
74 }
75}
76
77impl ValPmtl {
78 #[inline(always)]
80 pub fn output(&self, time: Time) -> bool {
81 match self {
82 ValPmtl::True => true,
83 ValPmtl::False => false,
84 ValPmtl::Atom(_atom, b) => *b,
85 ValPmtl::And(subs) => subs.iter().all(|f| f.output(time)),
86 ValPmtl::Or(subs) => subs.iter().any(|f| f.output(time)),
87 ValPmtl::Not(subformula) => !subformula.output(time),
88 ValPmtl::Implies(subformulae) => {
89 let (lhs, rhs) = subformulae.as_ref();
90 rhs.output(time) || !lhs.output(time)
91 }
92 ValPmtl::Historically(_sub, _lower_bound, _upper_bound, valuation) => {
93 !valuation.contains(time)
94 }
95 ValPmtl::Once(_sub, _lower_bound, _upper_bound, valuation) => valuation.contains(time),
96 ValPmtl::Since(_subformulae, _lower_bound, _upper_bound, valuation) => {
97 valuation.contains(time)
98 }
99 }
100 }
101
102 pub fn update_state(&mut self, state: &[bool], time: Time) {
103 match self {
104 ValPmtl::Atom(atom, b) => {
105 *b = state[*atom];
106 }
107 ValPmtl::And(subs) | ValPmtl::Or(subs) => {
108 subs.iter_mut().for_each(|f| f.update_state(state, time));
110 }
111 ValPmtl::Not(subformula) => {
112 subformula.update_state(state, time);
113 }
114 ValPmtl::Implies(subformulae) => {
115 let (lhs, rhs) = subformulae.as_mut();
116 lhs.update_state(state, time);
118 rhs.update_state(state, time);
119 }
120 ValPmtl::Historically(sub, lower_bound, upper_bound, valuation) => {
121 sub.update_state(state, time);
122 if !sub.output(time) {
123 valuation.add_interval(
124 lower_bound.saturating_add(time),
125 upper_bound.saturating_add(time),
126 );
127 }
128 }
129 ValPmtl::Once(sub, lower_bound, upper_bound, valuation) => {
130 sub.update_state(state, time);
131 if sub.output(time) {
132 valuation.add_interval(
133 lower_bound.saturating_add(time),
134 upper_bound.saturating_add(time),
135 );
136 }
137 }
138 ValPmtl::Since(subformulae, lower_bound, upper_bound, valuation) => {
139 let (lhs, rhs) = subformulae.as_mut();
140 lhs.update_state(state, time);
142 let out_lhs = lhs.output(time);
143 rhs.update_state(state, time);
144 let out_rhs = rhs.output(time);
145 if out_lhs {
146 if out_rhs {
147 valuation.add_interval(
148 lower_bound.saturating_add(time),
149 upper_bound.saturating_add(time),
150 );
151 }
152 } else if out_rhs {
153 *valuation = NumSet::from_range(
154 lower_bound.saturating_add(time),
155 upper_bound.saturating_add(time),
156 );
157 } else {
158 *valuation = NumSet::empty();
159 }
160 }
161 _ => {
162 }
164 }
165 }
166
167 pub fn update_time(&mut self, time: Time) {
168 match self {
169 ValPmtl::And(subs) | ValPmtl::Or(subs) => {
170 subs.iter_mut().for_each(|f| f.update_time(time));
172 }
173 ValPmtl::Not(subformula) => {
174 subformula.update_time(time);
175 }
176 ValPmtl::Implies(subformulae) => {
177 let (lhs, rhs) = subformulae.as_mut();
178 lhs.update_time(time);
180 rhs.update_time(time);
181 }
182 ValPmtl::Historically(sub, lower_bound, upper_bound, valuation) => {
183 sub.update_time(time);
184 if !sub.output(time) {
185 valuation.add_interval(
186 lower_bound.saturating_add(time),
187 upper_bound.saturating_add(time),
188 );
189 }
190 }
191 ValPmtl::Once(sub, lower_bound, upper_bound, valuation) => {
192 sub.update_time(time);
193 if sub.output(time) {
194 valuation.add_interval(
195 lower_bound.saturating_add(time),
196 upper_bound.saturating_add(time),
197 );
198 }
199 }
200 ValPmtl::Since(subformulae, lower_bound, upper_bound, valuation) => {
201 let (lhs, rhs) = subformulae.as_mut();
202 lhs.update_time(time);
204 let out_lhs = lhs.output(time);
205 rhs.update_time(time);
206 let out_rhs = rhs.output(time);
207 if out_lhs {
208 if out_rhs {
209 valuation.add_interval(
210 lower_bound.saturating_add(time),
211 upper_bound.saturating_add(time),
212 );
213 }
214 } else if out_rhs {
215 *valuation = NumSet::from_range(
216 lower_bound.saturating_add(time),
217 upper_bound.saturating_add(time),
218 );
219 } else {
220 *valuation = NumSet::empty();
221 }
222 }
223 _ => {
224 }
226 }
227 }
228
229 pub fn valuation(&self, time: Time) -> Option<bool> {
231 match self {
232 ValPmtl::True => Some(true),
233 ValPmtl::False => Some(false),
234 ValPmtl::Atom(_, _) => None,
235 ValPmtl::And(items) => items
236 .iter()
237 .try_fold(true, |b, f| f.valuation(time).map(|v| b && v)),
238 ValPmtl::Or(items) => items
239 .iter()
240 .try_fold(false, |b, f| f.valuation(time).map(|v| b || v)),
241 ValPmtl::Not(f) => f.valuation(time).map(|b| !b),
242 ValPmtl::Implies(subformulae) => {
243 let lhs_val = subformulae.0.valuation(time);
244 let rhs_val = subformulae.1.valuation(time);
245 if rhs_val.is_some_and(|b| b) || lhs_val.is_some_and(|b| !b) {
246 Some(true)
247 } else if rhs_val.is_some_and(|b| !b) && lhs_val.is_some_and(|b| b) {
248 Some(false)
249 } else {
250 None
251 }
252 }
253 ValPmtl::Historically(subformula, lb, _, valuation) => subformula
257 .valuation(time)
258 .and_then(|v| (*lb == 0 || v).then_some(v))
259 .or_else(|| valuation.contains_unbounded_interval(time).then_some(false)),
260 ValPmtl::Once(subformula, lb, _, valuation) => subformula
264 .valuation(time)
265 .and_then(|v| (*lb == 0 || !v).then_some(v))
266 .or_else(|| valuation.contains_unbounded_interval(time).then_some(true)),
267 ValPmtl::Since(subformulae, lb, _, valuation) => {
272 if let Some(false) = subformulae.1.valuation(time) {
273 Some(false)
274 } else if valuation.contains_unbounded_interval(time) {
275 subformulae
276 .0
277 .valuation(time)
278 .and_then(|v| (*lb == 0 || v).then_some(v))
279 } else {
280 None
281 }
282 }
283 }
284 }
285}
286
287#[derive(Debug, Clone)]
289pub struct PmtlOracle {
290 assumes: Vec<ValPmtl>,
291 guarantees: Vec<ValPmtl>,
292 time: Time,
293}
294
295impl PmtlOracle {
296 pub fn new(assumes: &[Pmtl<usize>], guarantees: &[Pmtl<usize>]) -> Self {
298 Self {
299 assumes: assumes.iter().map(|f| f.into()).collect(),
300 guarantees: guarantees.iter().map(|f| f.into()).collect(),
301 time: 0,
302 }
303 }
304}
305
306impl Oracle for PmtlOracle {
307 fn output_assumes(&self) -> impl Iterator<Item = Option<bool>> {
308 self.assumes.iter().map(|f| f.valuation(self.time))
309 }
310
311 fn output_guarantees(&self) -> impl Iterator<Item = Option<bool>> {
312 self.guarantees.iter().map(|f| f.valuation(self.time))
313 }
314
315 fn final_output_assumes(&self) -> impl Iterator<Item = bool> {
316 self.assumes.iter().map(|f| f.output(self.time))
317 }
318
319 fn final_output_guarantees(&self) -> impl Iterator<Item = bool> {
320 self.guarantees.iter().map(|f| f.output(self.time))
321 }
322
323 fn update_state(&mut self, state: &[bool]) {
325 self.assumes
326 .iter_mut()
327 .for_each(|f| f.update_state(state, self.time));
328 self.guarantees
329 .iter_mut()
330 .for_each(|f| f.update_state(state, self.time));
331 }
332
333 fn update_time(&mut self, time: Time) {
335 assert!(self.time <= time);
336 self.assumes.iter_mut().for_each(|f| f.update_time(time));
337 self.guarantees.iter_mut().for_each(|f| f.update_time(time));
338 self.time = time;
339 }
340}
341
342#[cfg(test)]
343mod tests {
344 use super::*;
345
346 #[test]
347 fn since_1() {
348 let formula = Pmtl::Since(Box::new((Pmtl::Atom(0), Pmtl::Atom(1))), 0, Time::MAX);
349 let mut oracle = PmtlOracle::new(&[], &[formula]);
350 oracle.update_state(&[false, true]);
351 assert!(oracle.final_output_guarantees().any(|b| b));
352 oracle.update_state(&[false, true]);
353 assert!(oracle.final_output_guarantees().any(|b| b));
354 oracle.update_time(1);
355 assert!(oracle.final_output_guarantees().any(|b| b));
356 oracle.update_state(&[true, true]);
357 assert!(oracle.final_output_guarantees().any(|b| b));
358 oracle.update_time(2);
359 assert!(oracle.final_output_guarantees().any(|b| b));
360 oracle.update_state(&[true, true]);
361 assert!(oracle.final_output_guarantees().any(|b| b));
362 oracle.update_time(3);
363 assert!(oracle.final_output_guarantees().any(|b| b));
364 oracle.update_state(&[true, false]);
365 assert!(oracle.final_output_guarantees().any(|b| b));
366 oracle.update_time(4);
367 assert!(oracle.final_output_guarantees().any(|b| b));
368 oracle.update_state(&[false, false]);
369 assert!(oracle.final_output_guarantees().any(|b| !b));
370 }
371
372 #[test]
373 fn since_2() {
374 let formula = Pmtl::Since(Box::new((Pmtl::Atom(0), Pmtl::Atom(1))), 0, 2);
375 let mut oracle = PmtlOracle::new(&[], &[formula]);
376 oracle.update_state(&[false, true]);
377 assert!(oracle.final_output_guarantees().any(|b| b));
378 oracle.update_state(&[false, true]);
379 assert!(oracle.final_output_guarantees().any(|b| b));
380 oracle.update_time(1);
381 assert!(oracle.final_output_guarantees().any(|b| b));
382 oracle.update_state(&[true, true]);
383 assert!(oracle.final_output_guarantees().any(|b| b));
384 oracle.update_time(2);
385 assert!(oracle.final_output_guarantees().any(|b| b));
386 oracle.update_state(&[true, false]);
387 assert!(oracle.final_output_guarantees().any(|b| b));
388 oracle.update_time(3);
389 assert!(oracle.final_output_guarantees().any(|b| b));
390 oracle.update_state(&[true, false]);
391 assert!(oracle.final_output_guarantees().any(|b| b));
392 oracle.update_time(4);
393 assert!(oracle.final_output_guarantees().any(|b| b));
394 oracle.update_state(&[true, false]);
395 assert!(oracle.final_output_guarantees().any(|b| b));
396 oracle.update_time(5);
397 assert!(oracle.final_output_guarantees().any(|b| !b));
398 }
399
400 #[test]
401 fn since_3() {
402 let formula = Pmtl::Since(Box::new((Pmtl::Atom(0), Pmtl::Atom(1))), 1, 2);
403 let mut oracle = PmtlOracle::new(&[], &[formula]);
404 oracle.update_state(&[false, true]);
405 assert!(oracle.final_output_guarantees().any(|b| !b));
406 oracle.update_state(&[false, true]);
407 assert!(oracle.final_output_guarantees().any(|b| !b));
408 oracle.update_time(1);
409 assert!(oracle.final_output_guarantees().any(|b| !b));
410 oracle.update_state(&[true, true]);
411 assert!(oracle.final_output_guarantees().any(|b| !b));
412 oracle.update_time(2);
413 assert!(oracle.final_output_guarantees().any(|b| b));
414 oracle.update_state(&[true, false]);
415 assert!(oracle.final_output_guarantees().any(|b| b));
416 oracle.update_time(3);
417 assert!(oracle.final_output_guarantees().any(|b| b));
418 oracle.update_state(&[true, false]);
419 assert!(oracle.final_output_guarantees().any(|b| b));
420 oracle.update_time(4);
421 assert!(oracle.final_output_guarantees().any(|b| b));
422 oracle.update_state(&[true, false]);
423 assert!(oracle.final_output_guarantees().any(|b| b));
424 oracle.update_time(5);
425 assert!(oracle.final_output_guarantees().any(|b| !b));
426 }
427
428 }