1use super::functions::Decidable;
6use super::functions::*;
7use std::fmt;
8
9#[derive(Debug, Clone)]
11pub struct NamedDecision {
12 pub name: String,
14 pub decision: Decision<()>,
16}
17impl NamedDecision {
18 pub fn new(name: impl Into<String>, decision: Decision<()>) -> Self {
20 Self {
21 name: name.into(),
22 decision,
23 }
24 }
25 pub fn is_true(&self) -> bool {
27 self.decision.is_true()
28 }
29 pub fn summary(&self) -> String {
31 let verdict = if self.is_true() { "✓" } else { "✗" };
32 format!("[{verdict}] {}", self.name)
33 }
34}
35#[derive(Debug, Clone, PartialEq, Eq)]
40pub enum BoolReflect {
41 IsTrue,
43 IsFalse,
45}
46impl BoolReflect {
47 pub fn from_decision(d: &Decision<()>) -> Self {
49 if d.is_true() {
50 BoolReflect::IsTrue
51 } else {
52 BoolReflect::IsFalse
53 }
54 }
55 pub fn to_bool(&self) -> bool {
57 *self == BoolReflect::IsTrue
58 }
59}
60#[derive(Clone, Debug, Default)]
62pub struct DecidableCounter {
63 pub true_count: usize,
65 pub false_count: usize,
67}
68impl DecidableCounter {
69 pub fn new() -> Self {
71 Self::default()
72 }
73 pub fn record(&mut self, d: &Decision<()>) {
75 if d.is_true() {
76 self.true_count += 1;
77 } else {
78 self.false_count += 1;
79 }
80 }
81 pub fn total(&self) -> usize {
83 self.true_count + self.false_count
84 }
85 pub fn true_rate(&self) -> f64 {
87 if self.total() == 0 {
88 0.0
89 } else {
90 (self.true_count as f64 / self.total() as f64) * 100.0
91 }
92 }
93 pub fn all_true(&self) -> bool {
95 self.false_count == 0 && self.total() > 0
96 }
97 pub fn all_false(&self) -> bool {
99 self.true_count == 0 && self.total() > 0
100 }
101 pub fn reset(&mut self) {
103 self.true_count = 0;
104 self.false_count = 0;
105 }
106}
107#[derive(Debug, Clone, PartialEq, Eq)]
112pub enum Decision<P> {
113 IsTrue(P),
115 IsFalse(String),
117}
118impl<P> Decision<P> {
119 pub fn is_true(&self) -> bool {
121 matches!(self, Decision::IsTrue(_))
122 }
123 pub fn is_false(&self) -> bool {
125 matches!(self, Decision::IsFalse(_))
126 }
127 pub fn unwrap(self) -> P {
129 match self {
130 Decision::IsTrue(p) => p,
131 Decision::IsFalse(msg) => panic!("Decision::unwrap on IsFalse: {msg}"),
132 }
133 }
134 pub fn into_option(self) -> Option<P> {
136 match self {
137 Decision::IsTrue(p) => Some(p),
138 Decision::IsFalse(_) => None,
139 }
140 }
141 pub fn map<Q>(self, f: impl FnOnce(P) -> Q) -> Decision<Q> {
143 match self {
144 Decision::IsTrue(p) => Decision::IsTrue(f(p)),
145 Decision::IsFalse(msg) => Decision::IsFalse(msg),
146 }
147 }
148 pub fn and<Q>(self, other: Decision<Q>) -> Decision<(P, Q)> {
150 match (self, other) {
151 (Decision::IsTrue(p), Decision::IsTrue(q)) => Decision::IsTrue((p, q)),
152 (Decision::IsFalse(m), _) | (_, Decision::IsFalse(m)) => Decision::IsFalse(m),
153 }
154 }
155 pub fn or(self, other: Decision<P>) -> Decision<P> {
157 match self {
158 Decision::IsTrue(_) => self,
159 Decision::IsFalse(_) => other,
160 }
161 }
162 pub fn negate(self) -> Decision<String>
164 where
165 P: std::fmt::Debug,
166 {
167 match self {
168 Decision::IsTrue(p) => Decision::IsFalse(format!("expected false but got: {p:?}")),
169 Decision::IsFalse(msg) => Decision::IsTrue(msg),
170 }
171 }
172 pub fn flat_map<Q>(self, f: impl FnOnce(P) -> Decision<Q>) -> Decision<Q> {
174 match self {
175 Decision::IsTrue(p) => f(p),
176 Decision::IsFalse(msg) => Decision::IsFalse(msg),
177 }
178 }
179 pub fn unwrap_or(self, default: P) -> P {
181 match self {
182 Decision::IsTrue(p) => p,
183 Decision::IsFalse(_) => default,
184 }
185 }
186 pub fn unwrap_or_else(self, f: impl FnOnce(String) -> P) -> P {
188 match self {
189 Decision::IsTrue(p) => p,
190 Decision::IsFalse(msg) => f(msg),
191 }
192 }
193}
194impl Decision<bool> {
195 pub fn to_bool(&self) -> bool {
197 match self {
198 Decision::IsTrue(b) => *b,
199 Decision::IsFalse(_) => false,
200 }
201 }
202}
203#[derive(Clone, Debug)]
205pub struct DecisionChain {
206 steps: Vec<(String, Decision<()>)>,
207}
208impl DecisionChain {
209 pub fn new() -> Self {
211 Self { steps: Vec::new() }
212 }
213 pub fn step(mut self, name: impl Into<String>, d: Decision<()>) -> Self {
215 self.steps.push((name.into(), d));
216 self
217 }
218 pub fn all_passed(&self) -> bool {
220 self.steps.iter().all(|(_, d)| d.is_true())
221 }
222 pub fn first_failure(&self) -> Option<&str> {
224 self.steps
225 .iter()
226 .find(|(_, d)| d.is_false())
227 .map(|(name, _)| name.as_str())
228 }
229 pub fn len(&self) -> usize {
231 self.steps.len()
232 }
233 pub fn is_empty(&self) -> bool {
235 self.steps.is_empty()
236 }
237 pub fn passed_count(&self) -> usize {
239 self.steps.iter().filter(|(_, d)| d.is_true()).count()
240 }
241 pub fn failed_count(&self) -> usize {
243 self.steps.iter().filter(|(_, d)| d.is_false()).count()
244 }
245}
246#[allow(dead_code)]
248pub struct DecisionProcedureExt {
249 procedure_name: String,
251 complete: bool,
253 sound: bool,
255 complexity: String,
257}
258#[derive(Debug, Clone, PartialEq, Eq)]
262pub struct Not<P> {
263 pub message: String,
265 _marker: std::marker::PhantomData<P>,
266}
267impl<P> Not<P> {
268 pub fn new(message: impl Into<String>) -> Self {
270 Self {
271 message: message.into(),
272 _marker: std::marker::PhantomData,
273 }
274 }
275 pub fn message(&self) -> &str {
278 &self.message
279 }
280}
281#[allow(dead_code)]
283pub struct DecidablePropExt {
284 name: String,
286 constructive: bool,
288 bool_reflect: Option<bool>,
290}
291#[allow(dead_code)]
293pub struct DecidableSetExt<T: Eq> {
294 elements: Vec<T>,
295 dec_eq: std::marker::PhantomData<T>,
297}
298#[derive(Clone, Debug)]
300pub struct EqDecision<T> {
301 pub(super) lhs: T,
302 pub(super) rhs: T,
303}
304impl<T: PartialEq + std::fmt::Debug> EqDecision<T> {
305 pub fn new(lhs: T, rhs: T) -> Self {
307 Self { lhs, rhs }
308 }
309}
310#[derive(Debug, Clone, PartialEq, Eq)]
314pub struct FiniteSet<T: PartialEq> {
315 elems: Vec<T>,
316}
317impl<T: PartialEq> FiniteSet<T> {
318 pub fn new() -> Self {
320 Self { elems: Vec::new() }
321 }
322 pub fn insert(&mut self, x: T) -> bool {
324 if self.elems.contains(&x) {
325 false
326 } else {
327 self.elems.push(x);
328 true
329 }
330 }
331 pub fn contains(&self, x: &T) -> bool {
333 self.elems.contains(x)
334 }
335 pub fn remove(&mut self, x: &T) -> bool {
337 if let Some(pos) = self.elems.iter().position(|e| e == x) {
338 self.elems.remove(pos);
339 true
340 } else {
341 false
342 }
343 }
344 pub fn len(&self) -> usize {
346 self.elems.len()
347 }
348 pub fn is_empty(&self) -> bool {
350 self.elems.is_empty()
351 }
352 pub fn iter(&self) -> impl Iterator<Item = &T> {
354 self.elems.iter()
355 }
356 pub fn union(&self, other: &Self) -> Self
358 where
359 T: Clone,
360 {
361 let mut result = self.clone();
362 for x in &other.elems {
363 result.insert(x.clone());
364 }
365 result
366 }
367 pub fn intersection(&self, other: &Self) -> Self
369 where
370 T: Clone,
371 {
372 Self {
373 elems: self
374 .elems
375 .iter()
376 .filter(|x| other.contains(x))
377 .cloned()
378 .collect(),
379 }
380 }
381 pub fn difference(&self, other: &Self) -> Self
383 where
384 T: Clone,
385 {
386 Self {
387 elems: self
388 .elems
389 .iter()
390 .filter(|x| !other.contains(x))
391 .cloned()
392 .collect(),
393 }
394 }
395 pub fn is_subset(&self, other: &Self) -> bool {
397 self.elems.iter().all(|x| other.contains(x))
398 }
399}
400#[derive(Debug, Clone, Default)]
404pub struct DecisionTable {
405 entries: Vec<(String, Decision<()>)>,
406}
407impl DecisionTable {
408 pub fn new() -> Self {
410 Self::default()
411 }
412 pub fn insert(&mut self, name: impl Into<String>, d: Decision<()>) {
414 let name = name.into();
415 if let Some(entry) = self.entries.iter_mut().find(|(k, _)| k == &name) {
416 entry.1 = d;
417 } else {
418 self.entries.push((name, d));
419 }
420 }
421 pub fn lookup(&self, name: &str) -> Option<&Decision<()>> {
423 self.entries.iter().find(|(k, _)| k == name).map(|(_, v)| v)
424 }
425 pub fn len(&self) -> usize {
427 self.entries.len()
428 }
429 pub fn is_empty(&self) -> bool {
431 self.entries.is_empty()
432 }
433 pub fn iter(&self) -> impl Iterator<Item = (&str, &Decision<()>)> {
435 self.entries.iter().map(|(k, v)| (k.as_str(), v))
436 }
437}
438#[derive(Clone)]
440pub struct FnPred<A, F>(pub(super) F, pub(super) std::marker::PhantomData<A>)
441where
442 F: Fn(&A) -> bool;
443impl<A, F: Fn(&A) -> bool> FnPred<A, F> {
444 pub fn new(f: F) -> Self {
446 Self(f, std::marker::PhantomData)
447 }
448}
449#[allow(dead_code)]
451pub struct SemiDecidableExt<T> {
452 predicate: std::marker::PhantomData<T>,
454 is_total: bool,
456}
457#[derive(Clone, Debug)]
459pub struct LeDecision<T> {
460 pub(super) lhs: T,
461 pub(super) rhs: T,
462}
463impl<T: PartialOrd> LeDecision<T> {
464 pub fn new(lhs: T, rhs: T) -> Self {
466 Self { lhs, rhs }
467 }
468}
469#[allow(dead_code)]
471pub struct HaltingOracleExt {
472 oracle_name: String,
474 undecidable: bool,
476}
477#[derive(Clone, Copy, Debug, PartialEq, Eq)]
479pub struct Interval {
480 pub lo: i64,
482 pub hi: i64,
484}
485impl Interval {
486 pub fn new(lo: i64, hi: i64) -> Self {
488 Self { lo, hi }
489 }
490 pub fn point(x: i64) -> Self {
492 Self { lo: x, hi: x }
493 }
494 pub fn contains(&self, x: i64) -> bool {
496 x >= self.lo && x <= self.hi
497 }
498 pub fn is_empty(&self) -> bool {
500 self.lo > self.hi
501 }
502 pub fn len(&self) -> u64 {
504 if self.is_empty() {
505 0
506 } else {
507 (self.hi - self.lo) as u64 + 1
508 }
509 }
510 pub fn intersect(&self, other: &Interval) -> Interval {
512 Interval {
513 lo: self.lo.max(other.lo),
514 hi: self.hi.min(other.hi),
515 }
516 }
517 pub fn union(&self, other: &Interval) -> Interval {
519 Interval {
520 lo: self.lo.min(other.lo),
521 hi: self.hi.max(other.hi),
522 }
523 }
524 pub fn decide_contains(&self, x: i64) -> Decision<()> {
526 if self.contains(x) {
527 Decision::IsTrue(())
528 } else {
529 Decision::IsFalse(format!("{x} not in [{}, {}]", self.lo, self.hi))
530 }
531 }
532}