Prime blocks finder + implicate printer

This commit is contained in:
Arne Keller 2021-03-15 15:00:24 +01:00
parent 2fc0445901
commit 388ac6c412
2 changed files with 72 additions and 2 deletions

View File

@ -82,6 +82,70 @@ pub fn find_groups(func: &FunctionSpec, vars: &[Variable], typ: Output) -> Vec<V
groups groups
} }
pub fn find_prime<'a>(func: &FunctionSpec, vars: &[Variable], typ: Output, blocks: &'a [Vec<(Variable, Output)>]) -> Vec<&'a [(Variable, Output)]> {
assert_eq!(func.len(), 2usize.pow(vars.len() as u32));
let block_masks = blocks.iter().map(|x| &**x)
.map(block_to_mask)
.collect::<Vec<_>>();
let mut prime = vec![false; blocks.len()];
'input: for input in 0..func.len() {
if func[input] != typ {
continue;
}
let mut matched = None;
for (i, (mask, inv_mask)) in block_masks.iter().enumerate() {
if input | mask == input && input & inv_mask == input {
if matched.is_none() {
matched = Some(i);
} else {
continue 'input;
}
}
}
if let Some(i) = matched {
prime[i] = true;
}
}
prime.into_iter().enumerate().filter(|&(_, prime)| prime).map(|(i, _)| &*blocks[i]).collect()
}
/// a ⊆ b
fn subset_of<T: Eq>(a: &[T], b: &[T]) -> bool { fn subset_of<T: Eq>(a: &[T], b: &[T]) -> bool {
a.iter().all(|x| b.contains(x)) a.iter().all(|x| b.contains(x))
}
fn block_to_mask(block: &[(Variable, Output)]) -> (Variable, Variable) {
let mut mask = 0;
let mut inv_mask = !0;
for &(var, out) in block {
mask |= if out == One { var } else { 0 };
inv_mask ^= if out == Zero { var } else { 0 };
}
(mask, inv_mask)
}
pub fn print_implicate(vars: &[(Variable, Output)]) -> String {
let mut s = String::new();
for i in 0..vars.len() {
let (var, out) = vars[i];
if out == One {
s += "~";
}
s += print_var(var);
if i != vars.len() - 1 {
s += " v ";
}
}
s
}
fn print_var(var: Variable) -> &'static str {
match var {
A => "a",
B => "b",
C => "c",
_ => "?"
}
} }

View File

@ -4,7 +4,13 @@ use kv::Output::*;
fn main() { fn main() {
let function = vec![0, 0, 1, 0, 0, 1, 1, 1].into_iter().map(Into::into).collect(); let function = vec![0, 0, 1, 0, 0, 1, 1, 1].into_iter().map(Into::into).collect();
let groups = find_groups(&function, &mut [A, B, C], Zero); let groups = find_groups(&function, &mut [A, B, C], Zero);
for x in groups { println!("all:");
println!("{:?}", x); for x in &groups {
println!("{}", print_implicate(x));
}
println!("prime:");
let prime = find_prime(&function, &mut [A, B, C], Zero, &groups);
for x in prime {
println!("{}", print_implicate(&x));
} }
} }