1use bitvec::prelude::*;
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct TruthTable {
27 num_inputs: usize,
29 outputs: BitVec,
32}
33
34#[derive(Serialize, Deserialize)]
36struct TruthTableSerde {
37 num_inputs: usize,
38 outputs: Vec<bool>,
39}
40
41impl Serialize for TruthTable {
42 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
43 where
44 S: serde::Serializer,
45 {
46 let serde_repr = TruthTableSerde {
47 num_inputs: self.num_inputs,
48 outputs: self.outputs.iter().by_vals().collect(),
49 };
50 serde_repr.serialize(serializer)
51 }
52}
53
54impl<'de> Deserialize<'de> for TruthTable {
55 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
56 where
57 D: serde::Deserializer<'de>,
58 {
59 let serde_repr = TruthTableSerde::deserialize(deserializer)?;
60 Ok(TruthTable {
61 num_inputs: serde_repr.num_inputs,
62 outputs: serde_repr.outputs.into_iter().collect(),
63 })
64 }
65}
66
67impl TruthTable {
68 pub fn from_outputs(num_inputs: usize, outputs: Vec<bool>) -> Self {
73 let expected_len = 1 << num_inputs;
74 assert_eq!(
75 outputs.len(),
76 expected_len,
77 "outputs length must be 2^num_inputs = {}, got {}",
78 expected_len,
79 outputs.len()
80 );
81
82 let bits: BitVec = outputs.into_iter().collect();
83 Self { num_inputs, outputs: bits }
84 }
85
86 pub fn from_function<F>(num_inputs: usize, f: F) -> Self
90 where
91 F: Fn(&[bool]) -> bool,
92 {
93 let num_rows = 1 << num_inputs;
94 let mut outputs = BitVec::with_capacity(num_rows);
95
96 for i in 0..num_rows {
97 let input: Vec<bool> = (0..num_inputs).map(|j| (i >> j) & 1 == 1).collect();
98 outputs.push(f(&input));
99 }
100
101 Self { num_inputs, outputs }
102 }
103
104 pub fn num_inputs(&self) -> usize {
106 self.num_inputs
107 }
108
109 pub fn num_rows(&self) -> usize {
111 1 << self.num_inputs
112 }
113
114 pub fn evaluate(&self, input: &[bool]) -> bool {
116 assert_eq!(
117 input.len(),
118 self.num_inputs,
119 "input length must match num_inputs"
120 );
121
122 let index = Self::input_to_index(input);
123 self.outputs[index]
124 }
125
126 pub fn evaluate_config(&self, config: &[usize]) -> bool {
128 let input: Vec<bool> = config.iter().map(|&x| x != 0).collect();
129 self.evaluate(&input)
130 }
131
132 fn input_to_index(input: &[bool]) -> usize {
134 input
135 .iter()
136 .enumerate()
137 .map(|(i, &b)| if b { 1 << i } else { 0 })
138 .sum()
139 }
140
141 pub fn outputs(&self) -> &BitVec {
143 &self.outputs
144 }
145
146 pub fn outputs_vec(&self) -> Vec<bool> {
148 self.outputs.iter().by_vals().collect()
149 }
150
151 pub fn index_to_input(&self, index: usize) -> Vec<bool> {
153 (0..self.num_inputs).map(|j| (index >> j) & 1 == 1).collect()
154 }
155
156 pub fn count_ones(&self) -> usize {
158 self.outputs.count_ones()
159 }
160
161 pub fn count_zeros(&self) -> usize {
163 self.outputs.count_zeros()
164 }
165
166 pub fn is_satisfiable(&self) -> bool {
168 self.outputs.any()
169 }
170
171 pub fn is_tautology(&self) -> bool {
173 self.outputs.all()
174 }
175
176 pub fn is_contradiction(&self) -> bool {
178 self.outputs.not_any()
179 }
180
181 pub fn satisfying_assignments(&self) -> Vec<Vec<bool>> {
183 (0..self.num_rows())
184 .filter(|&i| self.outputs[i])
185 .map(|i| self.index_to_input(i))
186 .collect()
187 }
188
189 pub fn and(num_inputs: usize) -> Self {
191 Self::from_function(num_inputs, |input| input.iter().all(|&b| b))
192 }
193
194 pub fn or(num_inputs: usize) -> Self {
196 Self::from_function(num_inputs, |input| input.iter().any(|&b| b))
197 }
198
199 pub fn not() -> Self {
201 Self::from_outputs(1, vec![true, false])
202 }
203
204 pub fn xor(num_inputs: usize) -> Self {
206 Self::from_function(num_inputs, |input| {
207 input.iter().filter(|&&b| b).count() % 2 == 1
208 })
209 }
210
211 pub fn nand(num_inputs: usize) -> Self {
213 Self::from_function(num_inputs, |input| !input.iter().all(|&b| b))
214 }
215
216 pub fn nor(num_inputs: usize) -> Self {
218 Self::from_function(num_inputs, |input| !input.iter().any(|&b| b))
219 }
220
221 pub fn xnor(num_inputs: usize) -> Self {
223 Self::from_function(num_inputs, |input| {
224 input.iter().filter(|&&b| b).count() % 2 == 0
225 })
226 }
227
228 pub fn implies() -> Self {
231 Self::from_outputs(2, vec![true, false, true, true])
233 }
234
235 pub fn and_with(&self, other: &TruthTable) -> TruthTable {
237 assert_eq!(self.num_inputs, other.num_inputs);
238 let outputs: BitVec = self.outputs.iter().zip(other.outputs.iter())
239 .map(|(a, b)| *a && *b)
240 .collect();
241 TruthTable {
242 num_inputs: self.num_inputs,
243 outputs,
244 }
245 }
246
247 pub fn or_with(&self, other: &TruthTable) -> TruthTable {
249 assert_eq!(self.num_inputs, other.num_inputs);
250 let outputs: BitVec = self.outputs.iter().zip(other.outputs.iter())
251 .map(|(a, b)| *a || *b)
252 .collect();
253 TruthTable {
254 num_inputs: self.num_inputs,
255 outputs,
256 }
257 }
258
259 pub fn negate(&self) -> TruthTable {
261 let outputs: BitVec = self.outputs.iter().map(|b| !*b).collect();
262 TruthTable {
263 num_inputs: self.num_inputs,
264 outputs,
265 }
266 }
267}
268
269#[cfg(test)]
270mod tests {
271 use super::*;
272
273 #[test]
274 fn test_and_gate() {
275 let and = TruthTable::and(2);
276 assert!(!and.evaluate(&[false, false]));
277 assert!(!and.evaluate(&[true, false]));
278 assert!(!and.evaluate(&[false, true]));
279 assert!(and.evaluate(&[true, true]));
280 }
281
282 #[test]
283 fn test_or_gate() {
284 let or = TruthTable::or(2);
285 assert!(!or.evaluate(&[false, false]));
286 assert!(or.evaluate(&[true, false]));
287 assert!(or.evaluate(&[false, true]));
288 assert!(or.evaluate(&[true, true]));
289 }
290
291 #[test]
292 fn test_not_gate() {
293 let not = TruthTable::not();
294 assert!(not.evaluate(&[false]));
295 assert!(!not.evaluate(&[true]));
296 }
297
298 #[test]
299 fn test_xor_gate() {
300 let xor = TruthTable::xor(2);
301 assert!(!xor.evaluate(&[false, false]));
302 assert!(xor.evaluate(&[true, false]));
303 assert!(xor.evaluate(&[false, true]));
304 assert!(!xor.evaluate(&[true, true]));
305 }
306
307 #[test]
308 fn test_nand_gate() {
309 let nand = TruthTable::nand(2);
310 assert!(nand.evaluate(&[false, false]));
311 assert!(nand.evaluate(&[true, false]));
312 assert!(nand.evaluate(&[false, true]));
313 assert!(!nand.evaluate(&[true, true]));
314 }
315
316 #[test]
317 fn test_implies() {
318 let imp = TruthTable::implies();
319 assert!(imp.evaluate(&[false, false])); assert!(imp.evaluate(&[false, true])); assert!(!imp.evaluate(&[true, false])); assert!(imp.evaluate(&[true, true])); }
324
325 #[test]
326 fn test_from_function() {
327 let majority = TruthTable::from_function(3, |input| {
328 input.iter().filter(|&&b| b).count() >= 2
329 });
330 assert!(!majority.evaluate(&[false, false, false]));
331 assert!(!majority.evaluate(&[true, false, false]));
332 assert!(majority.evaluate(&[true, true, false]));
333 assert!(majority.evaluate(&[true, true, true]));
334 }
335
336 #[test]
337 fn test_evaluate_config() {
338 let and = TruthTable::and(2);
339 assert!(!and.evaluate_config(&[0, 0]));
340 assert!(!and.evaluate_config(&[1, 0]));
341 assert!(and.evaluate_config(&[1, 1]));
342 }
343
344 #[test]
345 fn test_satisfiable() {
346 let or = TruthTable::or(2);
347 assert!(or.is_satisfiable());
348
349 let contradiction = TruthTable::from_outputs(2, vec![false, false, false, false]);
350 assert!(!contradiction.is_satisfiable());
351 assert!(contradiction.is_contradiction());
352 }
353
354 #[test]
355 fn test_tautology() {
356 let tautology = TruthTable::from_outputs(2, vec![true, true, true, true]);
357 assert!(tautology.is_tautology());
358
359 let or = TruthTable::or(2);
360 assert!(!or.is_tautology());
361 }
362
363 #[test]
364 fn test_satisfying_assignments() {
365 let xor = TruthTable::xor(2);
366 let sat = xor.satisfying_assignments();
367 assert_eq!(sat.len(), 2);
368 assert!(sat.contains(&vec![true, false]));
369 assert!(sat.contains(&vec![false, true]));
370 }
371
372 #[test]
373 fn test_count() {
374 let and = TruthTable::and(2);
375 assert_eq!(and.count_ones(), 1);
376 assert_eq!(and.count_zeros(), 3);
377 }
378
379 #[test]
380 fn test_index_to_input() {
381 let tt = TruthTable::and(3);
382 assert_eq!(tt.index_to_input(0), vec![false, false, false]);
383 assert_eq!(tt.index_to_input(1), vec![true, false, false]);
384 assert_eq!(tt.index_to_input(7), vec![true, true, true]);
385 }
386
387 #[test]
388 fn test_outputs_vec() {
389 let and = TruthTable::and(2);
390 assert_eq!(and.outputs_vec(), vec![false, false, false, true]);
391 }
392
393 #[test]
394 fn test_and_with() {
395 let a = TruthTable::from_outputs(1, vec![false, true]);
396 let b = TruthTable::from_outputs(1, vec![true, false]);
397 let result = a.and_with(&b);
398 assert_eq!(result.outputs_vec(), vec![false, false]);
399 }
400
401 #[test]
402 fn test_or_with() {
403 let a = TruthTable::from_outputs(1, vec![false, true]);
404 let b = TruthTable::from_outputs(1, vec![true, false]);
405 let result = a.or_with(&b);
406 assert_eq!(result.outputs_vec(), vec![true, true]);
407 }
408
409 #[test]
410 fn test_negate() {
411 let and = TruthTable::and(2);
412 let nand = and.negate();
413 assert_eq!(nand.outputs_vec(), vec![true, true, true, false]);
414 }
415
416 #[test]
417 fn test_num_rows() {
418 let tt = TruthTable::and(3);
419 assert_eq!(tt.num_rows(), 8);
420 }
421
422 #[test]
423 fn test_3_input_and() {
424 let and3 = TruthTable::and(3);
425 assert!(!and3.evaluate(&[true, true, false]));
426 assert!(and3.evaluate(&[true, true, true]));
427 }
428
429 #[test]
430 fn test_xnor() {
431 let xnor = TruthTable::xnor(2);
432 assert!(xnor.evaluate(&[false, false]));
433 assert!(!xnor.evaluate(&[true, false]));
434 assert!(!xnor.evaluate(&[false, true]));
435 assert!(xnor.evaluate(&[true, true]));
436 }
437
438 #[test]
439 fn test_nor() {
440 let nor = TruthTable::nor(2);
441 assert!(nor.evaluate(&[false, false]));
442 assert!(!nor.evaluate(&[true, false]));
443 assert!(!nor.evaluate(&[false, true]));
444 assert!(!nor.evaluate(&[true, true]));
445 }
446}