Skip to content

Commit 6030bdc

Browse files
committed
generic TruthTable
1 parent 3d9f901 commit 6030bdc

16 files changed

+217
-151
lines changed

examples/truth_table.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
//! Print truth tables for all the binary functions.
22
#![allow(clippy::wildcard_imports)]
33

4-
use prop_logic::{connective::*, two_powers, CheckedArray};
4+
use prop_logic::{connective::*, two_powers, CheckedArray, TruthTabled as _};
55

66
fn print_stat<const ARITY: usize>(f: &dyn StoredBoolFn<ARITY>)
77
where
8-
TruthTable<ARITY>: std::fmt::Display,
8+
FixedTruthTable<ARITY>: std::fmt::Display,
99
two_powers::D: CheckedArray<ARITY>,
1010
{
1111
print!("{}", f.notation());

src/connective/functions/binary/and.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -128,18 +128,16 @@ where
128128

129129
#[cfg(test)]
130130
mod tests {
131+
use crate::truth_table::TruthTabled;
132+
131133
use super::{
132-
super::super::{
133-
super::{EquivalentBoolFn, InitFn as _},
134-
ternary::Ternary,
135-
LogicalIdentity, Truth,
136-
},
134+
super::super::{super::InitFn as _, ternary::Ternary, LogicalIdentity, Truth},
137135
*,
138136
};
139137

140138
#[test]
141139
fn any_equivalences() {
142-
assert!(<Truth as EquivalentBoolFn<0>>::is_equivalent(
140+
assert!(<Truth as TruthTabled<0>>::is_equivalent(
143141
&Truth,
144142
&ConjunctionAny::init()
145143
));

src/connective/functions/binary/or.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -127,18 +127,16 @@ where
127127

128128
#[cfg(test)]
129129
mod tests {
130+
use crate::truth_table::TruthTabled;
131+
130132
use super::{
131-
super::super::{
132-
super::{EquivalentBoolFn, InitFn as _},
133-
ternary::Ternary,
134-
Falsity, LogicalIdentity,
135-
},
133+
super::super::{super::InitFn as _, ternary::Ternary, Falsity, LogicalIdentity},
136134
*,
137135
};
138136

139137
#[test]
140138
fn any_equivalences() {
141-
assert!(<Falsity as EquivalentBoolFn<0>>::is_equivalent(
139+
assert!(<Falsity as TruthTabled<0>>::is_equivalent(
142140
&Falsity,
143141
&DisjunctionAny::init()
144142
));

src/connective/functions/binary/xnor.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -169,22 +169,20 @@ where
169169

170170
#[cfg(test)]
171171
mod tests {
172+
use crate::truth_table::TruthTabled;
173+
172174
use super::{
173-
super::super::{
174-
super::{EquivalentBoolFn, InitFn as _},
175-
ternary::Ternary,
176-
Truth,
177-
},
175+
super::super::{super::InitFn as _, ternary::Ternary, Truth},
178176
*,
179177
};
180178

181179
#[test]
182180
fn any_equivalences() {
183-
assert!(<Truth as EquivalentBoolFn<0>>::is_equivalent(
181+
assert!(<Truth as TruthTabled<0>>::is_equivalent(
184182
&Truth,
185183
&AllEquivalent::init()
186184
));
187-
assert!(<Truth as EquivalentBoolFn<1>>::is_equivalent(
185+
assert!(<Truth as TruthTabled<1>>::is_equivalent(
188186
&Truth,
189187
&AllEquivalent::init()
190188
));

src/connective/functions/binary/xor.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -139,18 +139,16 @@ where
139139

140140
#[cfg(test)]
141141
mod tests {
142+
use crate::truth_table::TruthTabled;
143+
142144
use super::{
143-
super::super::{
144-
super::{EquivalentBoolFn, InitFn as _},
145-
ternary::Ternary,
146-
Falsity, LogicalIdentity,
147-
},
145+
super::super::{super::InitFn as _, ternary::Ternary, Falsity, LogicalIdentity},
148146
*,
149147
};
150148

151149
#[test]
152150
fn any_equivalences() {
153-
assert!(<Falsity as EquivalentBoolFn<0>>::is_equivalent(
151+
assert!(<Falsity as TruthTabled<0>>::is_equivalent(
154152
&Falsity,
155153
&ExclusiveDisjunctionAny::init()
156154
));

src/connective/functions/ternary.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
//! Generic ternary function as the composition of two binary functions.
22
//!
33
//! <https://en.wikipedia.org/wiki/Ternary_operation>
4-
use super::super::{ops::Associativity as _, EquivalentBoolFn, Evaluable, TruthFn};
4+
use crate::truth_table::TruthTabled;
5+
6+
use super::super::{ops::Associativity, Evaluable, TruthFn};
57

68
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Default)]
79
/// Wrapper for a ternary boolean function which applies
@@ -21,8 +23,8 @@ impl<const LEFT: bool, Op1, Op2> Ternary<LEFT, Op1, Op2> {
2123
impl<const LEFT: bool, E, Op1, Op2> TruthFn<3, E> for Ternary<LEFT, Op1, Op2>
2224
where
2325
E: Evaluable + Clone, // TODO: try to get rid of this `Clone` requirement
24-
Op1: TruthFn<2, E> + EquivalentBoolFn<2>,
25-
Op2: TruthFn<2, E> + EquivalentBoolFn<2>,
26+
Op1: TruthFn<2, E> + TruthTabled<2> + Associativity,
27+
Op2: TruthFn<2, E> + TruthTabled<2, TT = <Op1 as TruthTabled<2>>::TT> + Associativity,
2628
{
2729
fn fold(&self, values: [E; 3]) -> Result<E, [E; 3]> {
2830
let try_fold = |left| {

src/connective/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ pub use self::{
2121
priority::{Prioritized, Priority},
2222
properties::{is_basis, is_complete, BoolFnExt},
2323
storage::{AllFunctions, StoredBoolFn, BINARY_FUNCTIONS, NULLARY_FUNCTIONS, UNARY_FUNCTIONS},
24-
traits::{BoolFn, Connective, EquivalentBoolFn, InitFn, TruthFn, TruthFnConnector},
25-
truth_table::TruthTable,
24+
traits::{BoolFn, Connective, InitFn, TruthFn, TruthFnConnector},
25+
truth_table::FixedTruthTable,
2626
};
2727

2828
#[allow(path_statements, clippy::no_effect)]
@@ -70,6 +70,8 @@ mod tests {
7070
F: TruthFn<ARITY, Formula<()>> + BoolFn<ARITY>,
7171
two_powers::D: CheckedArray<ARITY>,
7272
{
73+
use crate::truth_table::TruthTabled as _;
74+
7375
let truth_table = f.get_truth_table().into_iter();
7476
let eval_variants = truth_table.map(|(assignment, eval)| {
7577
let formulas = assignment

src/connective/ops.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
//! Unary operations and properties of the [`BoolFn`]-s.
22
use std::{collections::HashMap as Map, ops::Not};
33

4+
use crate::truth_table::TruthTabled as _;
5+
46
#[allow(clippy::wildcard_imports)]
5-
use super::{functions::*, ternary::Ternary, BoolFn, EquivalentBoolFn as _, InitFn as _};
7+
use super::{functions::*, ternary::Ternary, BoolFn, InitFn as _};
68

79
/// Easily convert a `BoolFn` into its counterpart in terms
810
/// of switching all the bits in its truth table.
@@ -161,6 +163,8 @@ where
161163
F: BoolFn<2>,
162164
{
163165
fn is_commutative(&self) -> bool {
166+
use crate::truth_table::TruthTabled as _;
167+
164168
let table: Map<_, _> = self.get_truth_table().into_iter().collect();
165169

166170
table.iter().all(|(args, val)| {
@@ -196,7 +200,11 @@ where
196200
mod tests {
197201
use std::collections::HashMap;
198202

199-
use crate::{arity::two_powers, utils::dependent_array::CheckedArray};
203+
use crate::{
204+
arity::two_powers,
205+
truth_table::{TruthTable as _, TruthTabled as _},
206+
utils::dependent_array::CheckedArray,
207+
};
200208

201209
use super::{super::InitFn, *};
202210

@@ -206,8 +214,8 @@ mod tests {
206214
N::Not: BoolFn<ARITY> + InitFn,
207215
two_powers::D: CheckedArray<ARITY>,
208216
{
209-
let table = N::init().get_truth_table().into_values();
210-
let table_neg = N::Not::init().get_truth_table().into_values();
217+
let table = N::init().get_truth_table().values();
218+
let table_neg = N::Not::init().get_truth_table().values();
211219

212220
dbg!(std::any::type_name::<N>());
213221
dbg!(std::any::type_name::<N::Not>());
@@ -222,8 +230,8 @@ mod tests {
222230
N2: BoolFn<ARITY>,
223231
two_powers::D: CheckedArray<ARITY>,
224232
{
225-
let table = x.get_truth_table().into_values();
226-
let table_neg = (!x).get_truth_table().into_values();
233+
let table = x.get_truth_table().values();
234+
let table_neg = (!x).get_truth_table().values();
227235

228236
dbg!(std::any::type_name::<N>());
229237
for (x, y) in table.into_iter().zip(table_neg) {

src/connective/ordering.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use std::cmp::Ordering;
22

33
#[allow(clippy::wildcard_imports)]
4-
use super::{functions::*, truth_table, BoolFn, InitFn as _};
4+
use super::{functions::*, BoolFn, InitFn as _};
55

66
use crate::{
77
arity::two_powers::D,
8+
truth_table::{TruthTable as _, TruthTabled as _},
89
utils::{cartesian_diag, dependent_array::CheckedArray},
910
};
1011

@@ -18,10 +19,9 @@ where
1819
Op1: BoolFn<ARITY> + Default,
1920
Op2: BoolFn<ARITY> + Default,
2021
D: CheckedArray<ARITY>,
21-
<D as CheckedArray<ARITY>>::Array<truth_table::Row<ARITY>>: Clone,
2222
{
23-
let op1_truth_table = Op1::init().get_truth_table().into_values();
24-
let op2_truth_table = Op2::init().get_truth_table().into_values();
23+
let op1_truth_table = Op1::init().get_truth_table().values();
24+
let op2_truth_table = Op2::init().get_truth_table().values();
2525

2626
let mut set_ordering = Ordering::Equal;
2727
for (&val1, &val2) in op1_truth_table.iter().zip(&op2_truth_table) {

src/connective/properties.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ use super::BoolFn;
66

77
use crate::{
88
arity::two_powers,
9+
truth_table::TruthTabled as _,
910
utils::{
1011
dependent_array::{CheckedArray, Discriminant as _},
1112
upcast::UpcastFrom,
1213
},
1314
};
1415

1516
/// Defines the important properies of a [`BoolFn`]
16-
/// based on its [`TruthTable`][crate::connective::TruthTable].
17+
/// based on its [`TruthTable`][crate::truth_table::TruthTable].
1718
///
1819
/// The most important of the properies are the includeness
1920
/// of a boolean function in some of the

src/connective/storage.rs

+2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ pub const BINARY_FUNCTIONS: AllFunctions<2> = CheckedStorage::new([
6868

6969
#[cfg(test)]
7070
mod tests_ordering {
71+
use crate::truth_table::TruthTabled as _;
72+
7173
use super::*;
7274

7375
#[test]

src/connective/traits.rs

+4-79
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
1-
use std::{collections::BTreeMap as Map, iter};
1+
use crate::utils::{operation::Operation, upcast::UpcastFrom};
22

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};
154

165
#[auto_impl::auto_impl(&, Box)]
176
/// Enables the ability to combine propositional [`Evaluable`] into a single one.
@@ -61,73 +50,9 @@ where
6150
}
6251

6352
/// 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> {}
7254

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> {}
13156

13257
#[auto_impl::auto_impl(&, Box)]
13358
/// A [logical constant](https://en.wikipedia.org/wiki/Logical_constant)

0 commit comments

Comments
 (0)