|
1 | 1 | use std::rc::Rc; |
2 | 2 |
|
| 3 | +use itertools::Itertools; |
| 4 | + |
3 | 5 | use crate::{ |
4 | 6 | algos::{atoms, create_initial_cache, enumeration::aux::enum_aux}, |
5 | 7 | formula::{rebuild_formula, tree::FormulaTree}, |
@@ -37,7 +39,13 @@ macro_rules! helper_ops_binary { |
37 | 39 | }; |
38 | 40 | } |
39 | 41 |
|
40 | | -helper_ops_unary!(Globally as G, Finally as F, WeakNext as X, StrongNext as SX); |
| 42 | +helper_ops_unary!( |
| 43 | + Not as Not, |
| 44 | + Globally as G, |
| 45 | + Finally as F, |
| 46 | + WeakNext as X, |
| 47 | + StrongNext as SX |
| 48 | +); |
41 | 49 | helper_ops_binary!(Until as U, Release as R, Or as OR, And as AND); |
42 | 50 | fn build_atom(s: &str, i: usize) -> FormulaTree { |
43 | 51 | FormulaTree::Atom(AtomicProposition(s.into(), i)) |
@@ -74,75 +82,229 @@ fn test_ltl_search(instance: &str, expected: FormulaTree) { |
74 | 82 | assert!(f.size() <= expected.size()); |
75 | 83 | } |
76 | 84 |
|
| 85 | +/// Converts an array of array of array of ints (yes) |
| 86 | +/// to a json string that looks like this: |
| 87 | +/// ```json |
| 88 | +/// [ |
| 89 | +/// { |
| 90 | +/// "a": ["1", "1", "1", "0"], |
| 91 | +/// "b": ["0", "0", "0", "0"] |
| 92 | +/// }, |
| 93 | +/// { |
| 94 | +/// "a": ["0", "1"], |
| 95 | +/// "b": ["0", "0"] |
| 96 | +/// }, |
| 97 | +/// { |
| 98 | +/// "a": ["0", "0", "1", "1"], |
| 99 | +/// "b": ["1", "0", "0", "0"] |
| 100 | +/// }, |
| 101 | +/// ] |
| 102 | +/// ``` |
| 103 | +/// The names ("a", "b" above) are given in the atomic_props array. |
| 104 | +fn to_traces_str(traces: &[&[&[i32]]], atomic_props: &[&str]) -> String { |
| 105 | + format!( |
| 106 | + "[{}]", |
| 107 | + traces |
| 108 | + .iter() |
| 109 | + .map(|ts| { |
| 110 | + format!( |
| 111 | + "{{ {} }}", |
| 112 | + ts.iter() |
| 113 | + .zip(atomic_props) |
| 114 | + .map(|(t, a)| { |
| 115 | + format!( |
| 116 | + r#""{a}": [{}]"#, |
| 117 | + t.iter().map(|s| format!(r#""{s}""#)).join(", ") |
| 118 | + ) |
| 119 | + }) |
| 120 | + .join(", ") |
| 121 | + ) |
| 122 | + }) |
| 123 | + .join(", ") |
| 124 | + ) |
| 125 | +} |
| 126 | + |
| 127 | +fn instance_str( |
| 128 | + positive_traces: &[&[&[i32]]], |
| 129 | + negative_traces: &[&[&[i32]]], |
| 130 | + atomic_props: &[&str], |
| 131 | +) -> String { |
| 132 | + let positive_traces_str: String = to_traces_str(positive_traces, atomic_props); |
| 133 | + let negative_traces_str: String = to_traces_str(negative_traces, atomic_props); |
| 134 | + |
| 135 | + format!( |
| 136 | + r#"{{ |
| 137 | + "positive_traces": {}, |
| 138 | + "negative_traces": {}, |
| 139 | + "atomic_propositions": {:?}, |
| 140 | + "number_atomic_propositions": {}, |
| 141 | + "number_traces": {}, |
| 142 | + "number_positive_traces": {}, |
| 143 | + "number_negative_traces": {}, |
| 144 | + "max_length_traces": {} |
| 145 | + }}"#, |
| 146 | + positive_traces_str, |
| 147 | + negative_traces_str, |
| 148 | + atomic_props, |
| 149 | + atomic_props.len(), |
| 150 | + positive_traces.len() + negative_traces.len(), |
| 151 | + positive_traces.len(), |
| 152 | + negative_traces.len(), |
| 153 | + positive_traces |
| 154 | + .iter() |
| 155 | + .filter_map(|s| s.iter().map(|s2| s2.len()).max()) |
| 156 | + .chain( |
| 157 | + negative_traces |
| 158 | + .iter() |
| 159 | + .filter_map(|s| s.iter().map(|s2| s2.len()).max()) |
| 160 | + ) |
| 161 | + .max() |
| 162 | + .unwrap() |
| 163 | + ) |
| 164 | +} |
| 165 | + |
| 166 | +macro_rules! make_instance { |
| 167 | + (pos : [$( { $( $name:ident : [$($v:literal),*]),* }), *], |
| 168 | + neg: [$( { $( $name2:ident : [$($v2:literal),*]),* }), *]) => { |
| 169 | + &instance_str( |
| 170 | + &[ $( &[ $( &[ $( $v),* ]),* ]),*], |
| 171 | + &[ $( &[ $( &[ $( $v2),* ]),* ]),*], |
| 172 | + & helper!{ $([ $( $name ),* ]),* } |
| 173 | + ) |
| 174 | + }; |
| 175 | +} |
| 176 | + |
| 177 | +macro_rules! helper { |
| 178 | + ([ $( $values:ident ),*] $(, [ $( $v:ident ),*] )*) => { [$( stringify!($values) ),*]}; |
| 179 | +} |
| 180 | + |
77 | 181 | #[test] |
78 | | -fn globally_a() { |
79 | | - let example = r#"{ |
80 | | - "positive_traces": [ |
| 182 | +fn strong_next_not_a() { |
| 183 | + let example = make_instance!(pos: [ |
| 184 | + { |
| 185 | + a: [1, 0, 1, 1] |
| 186 | + }, |
81 | 187 | { |
82 | | - "a": ["1", "1", "1", "1"] |
| 188 | + a: [0, 0, 1] |
| 189 | + }, |
| 190 | + { |
| 191 | + a: [1, 0, 1, 0] |
83 | 192 | } |
84 | 193 | ], |
85 | | - "negative_traces": [ |
| 194 | + neg: [ |
| 195 | + { |
| 196 | + a: [1, 1, 1, 0] |
| 197 | + }, |
86 | 198 | { |
87 | | - "a": ["1", "1", "1", "0"] |
| 199 | + a: [0] |
88 | 200 | }, |
89 | 201 | { |
90 | | - "a": ["0", "1"] |
| 202 | + a: [1] |
91 | 203 | }, |
92 | 204 | { |
93 | | - "a": ["0", "0", "1", "1"] |
| 205 | + a: [0, 1, 1, 0, 1] |
94 | 206 | }, |
95 | 207 | { |
96 | | - "a": ["1", "0", "1", "0"] |
| 208 | + a: [1, 1, 1, 1] |
| 209 | + } |
| 210 | + ]); |
| 211 | + |
| 212 | + let exp = SX(Not(build_atom("a", 0))); |
| 213 | + test_ltl_search(example, exp); |
| 214 | +} |
| 215 | + |
| 216 | +#[test] |
| 217 | +fn globally_a() { |
| 218 | + let example = make_instance!(pos: [ |
| 219 | + { |
| 220 | + a: [1, 1, 1, 1] |
97 | 221 | } |
98 | 222 | ], |
99 | | - "atomic_propositions": ["a"], |
100 | | - "number_atomic_propositions": 1, |
101 | | - "number_traces": 5, |
102 | | - "number_positive_traces": 1, |
103 | | - "number_negative_traces": 4, |
104 | | - "max_length_traces": 4 |
105 | | -}"#; |
| 223 | + neg: [ |
| 224 | + { |
| 225 | + a: [1, 1, 1, 0] |
| 226 | + }, |
| 227 | + { |
| 228 | + a: [0, 1] |
| 229 | + }, |
| 230 | + { |
| 231 | + a: [0, 0, 1, 1] |
| 232 | + }, |
| 233 | + { |
| 234 | + a: [1, 0, 1, 0] |
| 235 | + } |
| 236 | + ]); |
106 | 237 |
|
107 | 238 | let exp = G(build_atom("a", 0)); |
108 | 239 | test_ltl_search(example, exp); |
109 | 240 | } |
110 | 241 |
|
111 | 242 | #[test] |
112 | 243 | fn globally_a_or_b() { |
113 | | - let example = r#"{ |
114 | | - "positive_traces": [ |
| 244 | + let example = make_instance!( |
| 245 | + pos: [ |
115 | 246 | { |
116 | | - "a": ["0", "1", "1", "1"], |
117 | | - "b": ["1", "0", "0", "0"] |
| 247 | + a: [0, 1, 1, 1], |
| 248 | + b: [1, 0, 0, 0] |
118 | 249 | } |
119 | 250 | ], |
120 | | - "negative_traces": [ |
| 251 | + neg: [ |
121 | 252 | { |
122 | | - "a": ["1", "1", "1", "0"], |
123 | | - "b": ["0", "0", "0", "0"] |
| 253 | + a: [1, 1, 1, 0], |
| 254 | + b: [0, 0, 0, 0] |
124 | 255 | }, |
125 | 256 | { |
126 | | - "a": ["0", "1"], |
127 | | - "b": ["0", "0"] |
| 257 | + a: [0, 1], |
| 258 | + b: [0, 0] |
128 | 259 | }, |
129 | 260 | { |
130 | | - "a": ["0", "0", "1", "1"], |
131 | | - "b": ["1", "0", "0", "0"] |
| 261 | + a: [0, 0, 1, 1], |
| 262 | + b: [1, 0, 0, 0] |
132 | 263 | }, |
133 | 264 | { |
134 | | - "b": ["1", "1", "0", "0", "0"], |
135 | | - "a": ["1", "0", "1", "0", "1"] |
| 265 | + b: [1, 1, 0, 0, 0], |
| 266 | + a: [1, 0, 1, 0, 1] |
136 | 267 | } |
137 | | - ], |
138 | | - "atomic_propositions": ["a", "b"], |
139 | | - "number_atomic_propositions": 2, |
140 | | - "number_traces": 5, |
141 | | - "number_positive_traces": 1, |
142 | | - "number_negative_traces": 4, |
143 | | - "max_length_traces": 5 |
144 | | -}"#; |
145 | | - |
| 268 | + ]); |
146 | 269 | let exp = G(OR(build_atom("a", 0), build_atom("b", 1))); |
147 | 270 | test_ltl_search(example, exp); |
148 | 271 | } |
| 272 | + |
| 273 | +#[test] |
| 274 | +fn finally_a_and_b() { |
| 275 | + let example = make_instance!( |
| 276 | + pos: [ |
| 277 | + { |
| 278 | + a: [0, 0, 1, 1], |
| 279 | + b: [1, 0, 1, 0] |
| 280 | + }, |
| 281 | + { |
| 282 | + a: [1, 0, 1, 1], |
| 283 | + b: [0, 1, 0, 1] |
| 284 | + }, |
| 285 | + { |
| 286 | + a: [1, 1, 1], |
| 287 | + b: [0, 1, 1] |
| 288 | + } |
| 289 | + ], |
| 290 | + neg: [ |
| 291 | + { |
| 292 | + a: [1, 0, 1, 0], |
| 293 | + b: [0, 1, 0, 1] |
| 294 | + }, |
| 295 | + { |
| 296 | + a: [0, 1], |
| 297 | + b: [1, 0] |
| 298 | + }, |
| 299 | + { |
| 300 | + a: [0, 0, 1, 1], |
| 301 | + b: [1, 0, 0, 0] |
| 302 | + }, |
| 303 | + { |
| 304 | + b: [1, 1, 0, 0, 0], |
| 305 | + a: [0, 0, 1, 0, 1] |
| 306 | + } |
| 307 | + ]); |
| 308 | + let exp = F(AND(build_atom("a", 0), build_atom("b", 1))); |
| 309 | + test_ltl_search(example, exp); |
| 310 | +} |
0 commit comments