|
1 |
| -use std::{collections::BTreeMap as Map, iter}; |
| 1 | +use crate::utils::{operation::Operation, upcast::UpcastFrom}; |
2 | 2 |
|
3 |
| -use itertools::Itertools as _; |
4 |
| - |
5 |
| -use crate::{ |
6 |
| - arity::two_powers, |
7 |
| - utils::{dependent_array::CheckedArray, operation::Operation, upcast::UpcastFrom}, |
8 |
| -}; |
9 |
| - |
10 |
| -use super::{ |
11 |
| - evaluation::Evaluable, |
12 |
| - notation::FunctionNotation, |
13 |
| - truth_table::{Row, TruthTable}, |
14 |
| -}; |
| 3 | +use super::{evaluation::Evaluable, notation::FunctionNotation}; |
15 | 4 |
|
16 | 5 | #[auto_impl::auto_impl(&, Box)]
|
17 | 6 | /// Enables the ability to combine propositional [`Evaluable`] into a single one.
|
|
61 | 50 | }
|
62 | 51 |
|
63 | 52 | /// Special case of [`TruthFn`] dealing with plain `bool` values.
|
64 |
| -pub trait BoolFn<const ARITY: usize>: TruthFn<ARITY, bool> { |
65 |
| - /// Generate a [truth table](https://en.wikipedia.org/wiki/Truth_table) |
66 |
| - /// for a [`BoolFn`] as the **key** (boolean arguments)-**value** (function result) |
67 |
| - /// ordered map. |
68 |
| - fn get_truth_table(&self) -> TruthTable<ARITY> |
69 |
| - where |
70 |
| - two_powers::D: CheckedArray<ARITY>; |
71 |
| -} |
| 53 | +pub trait BoolFn<const ARITY: usize>: TruthFn<ARITY, bool> {} |
72 | 54 |
|
73 |
| -/// Use [`TruthTable`] to determine if two functions are equivalent. |
74 |
| -/// |
75 |
| -/// Separated from the [parent trait][BoolFn] to allow for the latter |
76 |
| -/// to be dyn-compatible. |
77 |
| -pub trait EquivalentBoolFn<const ARITY: usize>: BoolFn<ARITY> { |
78 |
| - /// Checks whether the two functions are equivalent. |
79 |
| - fn is_equivalent<Rhs>(&self, other: &Rhs) -> bool |
80 |
| - where |
81 |
| - Rhs: BoolFn<ARITY>; |
82 |
| -} |
83 |
| - |
84 |
| -impl<const ARITY: usize, F> EquivalentBoolFn<ARITY> for F |
85 |
| -where |
86 |
| - F: BoolFn<ARITY>, |
87 |
| - two_powers::D: CheckedArray<ARITY>, |
88 |
| -{ |
89 |
| - fn is_equivalent<Rhs>(&self, other: &Rhs) -> bool |
90 |
| - where |
91 |
| - Rhs: BoolFn<ARITY>, |
92 |
| - { |
93 |
| - self.get_truth_table().into_values() == other.get_truth_table().into_values() |
94 |
| - } |
95 |
| -} |
96 |
| - |
97 |
| -impl<const ARITY: usize, T> BoolFn<ARITY> for T |
98 |
| -where |
99 |
| - T: TruthFn<ARITY, bool>, |
100 |
| -{ |
101 |
| - fn get_truth_table(&self) -> TruthTable<ARITY> |
102 |
| - where |
103 |
| - two_powers::D: CheckedArray<ARITY>, |
104 |
| - { |
105 |
| - let table: Map<_, _> = iter::repeat([false, true]) |
106 |
| - .take(ARITY) |
107 |
| - .multi_cartesian_product() |
108 |
| - .map(|assignment| { |
109 |
| - let assignment = assignment |
110 |
| - .try_into() |
111 |
| - .expect("The array size is guaranteed by Itertools::multi_cartesian_product"); |
112 |
| - (assignment, self.compose(assignment)) |
113 |
| - }) |
114 |
| - .collect(); |
115 |
| - |
116 |
| - let table = if ARITY == 0 { |
117 |
| - assert!(table.is_empty()); |
118 |
| - let dummy_empty_array = [false; ARITY]; |
119 |
| - let row: Row<ARITY> = (dummy_empty_array, self.compose(dummy_empty_array)); |
120 |
| - vec![row] |
121 |
| - } else { |
122 |
| - table.into_iter().collect() |
123 |
| - }; |
124 |
| - |
125 |
| - assert_eq!(table.len(), 1 << ARITY); |
126 |
| - table |
127 |
| - .try_into() |
128 |
| - .map_or_else(|_| panic!("Size checked before"), TruthTable::new) |
129 |
| - } |
130 |
| -} |
| 55 | +impl<const ARITY: usize, T> BoolFn<ARITY> for T where T: TruthFn<ARITY, bool> {} |
131 | 56 |
|
132 | 57 | #[auto_impl::auto_impl(&, Box)]
|
133 | 58 | /// A [logical constant](https://en.wikipedia.org/wiki/Logical_constant)
|
|
0 commit comments