mirror of
https://gitlab.kit.edu/uskyk/kv.git
synced 2024-11-28 11:46:04 +00:00
Full solution calculation
This commit is contained in:
parent
388ac6c412
commit
d5e3da78f9
109
src/lib.rs
109
src/lib.rs
@ -1,6 +1,8 @@
|
||||
use itertools::Itertools;
|
||||
|
||||
pub type Variable = usize;
|
||||
pub type Block = Vec<(Variable, Output)>;
|
||||
pub type BlockRef<'a> = &'a [(Variable, Output)];
|
||||
|
||||
pub const A: Variable = 1 << 0;
|
||||
pub const B: Variable = 1 << 1;
|
||||
@ -66,7 +68,7 @@ pub fn find_groups(func: &FunctionSpec, vars: &[Variable], typ: Output) -> Vec<V
|
||||
}
|
||||
let mut fits = true;
|
||||
for input in 0..func.len() {
|
||||
if input | mask == input && input & inv_mask == input {
|
||||
if check_mask(input, mask, inv_mask) {
|
||||
if func[input] == typ.invert() {
|
||||
fits = false;
|
||||
break;
|
||||
@ -82,10 +84,10 @@ pub fn find_groups(func: &FunctionSpec, vars: &[Variable], typ: Output) -> Vec<V
|
||||
groups
|
||||
}
|
||||
|
||||
pub fn find_prime<'a>(func: &FunctionSpec, vars: &[Variable], typ: Output, blocks: &'a [Vec<(Variable, Output)>]) -> Vec<&'a [(Variable, Output)]> {
|
||||
pub fn find_prime<'a>(func: &FunctionSpec, vars: &[Variable], typ: Output, blocks: &'a [Block]) -> Vec<&'a [(Variable, Output)]> {
|
||||
assert_eq!(func.len(), 2usize.pow(vars.len() as u32));
|
||||
|
||||
let block_masks = blocks.iter().map(|x| &**x)
|
||||
let block_masks = blocks.iter()
|
||||
.map(block_to_mask)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@ -95,8 +97,8 @@ pub fn find_prime<'a>(func: &FunctionSpec, vars: &[Variable], typ: Output, block
|
||||
continue;
|
||||
}
|
||||
let mut matched = None;
|
||||
for (i, (mask, inv_mask)) in block_masks.iter().enumerate() {
|
||||
if input | mask == input && input & inv_mask == input {
|
||||
for (i, &(mask, inv_mask)) in block_masks.iter().enumerate() {
|
||||
if check_mask(input, mask, inv_mask) {
|
||||
if matched.is_none() {
|
||||
matched = Some(i);
|
||||
} else {
|
||||
@ -111,21 +113,83 @@ pub fn find_prime<'a>(func: &FunctionSpec, vars: &[Variable], typ: Output, block
|
||||
prime.into_iter().enumerate().filter(|&(_, prime)| prime).map(|(i, _)| &*blocks[i]).collect()
|
||||
}
|
||||
|
||||
pub fn all_solutions(mut func: FunctionSpec, vars: &[Variable], typ: Output, prime: &[BlockRef], other: &[Block]) -> Vec<Vec<Block>> {
|
||||
assert_eq!(func.len(), 2usize.pow(vars.len() as u32));
|
||||
|
||||
// first mark all inputs covered by prime blocks as Any
|
||||
let prime_masks = prime.iter()
|
||||
.map(block_to_mask)
|
||||
.collect::<Vec<_>>();
|
||||
'input: for input in 0..func.len() {
|
||||
if func[input] != typ {
|
||||
continue;
|
||||
}
|
||||
for &(mask, inv_mask) in prime_masks.iter() {
|
||||
if check_mask(input, mask, inv_mask) {
|
||||
func[input] = Any;
|
||||
continue 'input;
|
||||
}
|
||||
}
|
||||
}
|
||||
// then start recursive search
|
||||
let other_masks = other.iter()
|
||||
.map(block_to_mask)
|
||||
.collect::<Vec<_>>();
|
||||
all_recursive(func, vars, typ, other, &other_masks)
|
||||
}
|
||||
|
||||
fn all_recursive(func: FunctionSpec, vars: &[Variable], typ: Output, other: &[Block], other_masks: &[(Variable, Variable)]) -> Vec<Vec<Block>> {
|
||||
let mut all = Vec::new();
|
||||
for i in 0..other.len() {
|
||||
let block = &other[i];
|
||||
let (mask, inv_mask) = other_masks[i];
|
||||
for input in 0..func.len() {
|
||||
if func[input] != typ {
|
||||
continue;
|
||||
}
|
||||
if check_mask(input, mask, inv_mask) {
|
||||
// this block is useful
|
||||
// mark inputs as done
|
||||
let mut func = func.clone();
|
||||
for input in 0..func.len() {
|
||||
if check_mask(input, mask, inv_mask) {
|
||||
func[input] = Any;
|
||||
}
|
||||
}
|
||||
let extensions = all_recursive(func, vars, typ, other, other_masks);
|
||||
if extensions.is_empty() {
|
||||
all.push(vec![block.clone()]);
|
||||
}
|
||||
for mut extension in extensions {
|
||||
extension.push(block.clone());
|
||||
all.push(extension);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
all
|
||||
}
|
||||
|
||||
/// a ⊆ b
|
||||
fn subset_of<T: Eq>(a: &[T], b: &[T]) -> bool {
|
||||
a.iter().all(|x| b.contains(x))
|
||||
}
|
||||
|
||||
fn block_to_mask(block: &[(Variable, Output)]) -> (Variable, Variable) {
|
||||
fn block_to_mask<T: AsRef<[(Variable, Output)]>>(block: T) -> (Variable, Variable) {
|
||||
let mut mask = 0;
|
||||
let mut inv_mask = !0;
|
||||
for &(var, out) in block {
|
||||
for &(var, out) in block.as_ref() {
|
||||
mask |= if out == One { var } else { 0 };
|
||||
inv_mask ^= if out == Zero { var } else { 0 };
|
||||
}
|
||||
(mask, inv_mask)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn check_mask(input: usize, mask: usize, inv_mask: usize) -> bool {
|
||||
input | mask == input && input & inv_mask == input
|
||||
}
|
||||
|
||||
pub fn print_implicate(vars: &[(Variable, Output)]) -> String {
|
||||
let mut s = String::new();
|
||||
for i in 0..vars.len() {
|
||||
@ -141,6 +205,21 @@ pub fn print_implicate(vars: &[(Variable, Output)]) -> String {
|
||||
s
|
||||
}
|
||||
|
||||
pub fn print_implicant(vars: &[(Variable, Output)]) -> String {
|
||||
let mut s = String::new();
|
||||
for i in 0..vars.len() {
|
||||
let (var, out) = vars[i];
|
||||
if out == Zero {
|
||||
s += "~";
|
||||
}
|
||||
s += print_var(var);
|
||||
if i != vars.len() - 1 {
|
||||
s += " ";
|
||||
}
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
fn print_var(var: Variable) -> &'static str {
|
||||
match var {
|
||||
A => "a",
|
||||
@ -149,3 +228,19 @@ fn print_var(var: Variable) -> &'static str {
|
||||
_ => "?"
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_3var() {
|
||||
let fun: FunctionSpec = vec![0, 0, 1, 0, 0, 1, 1, 1].into_iter().map(Into::into).collect();
|
||||
let groups = find_groups(&fun, &mut [A, B, C], Zero);
|
||||
assert_eq!(groups, vec![
|
||||
vec![(A, Zero), (B, Zero)],
|
||||
vec![(A, One), (C, Zero)],
|
||||
vec![(B, Zero), (C, Zero)],
|
||||
]);
|
||||
let prime = find_prime(&fun, &mut [A, B, C], Zero, &groups);
|
||||
assert_eq!(prime, vec![
|
||||
vec![(A, Zero), (B, Zero)],
|
||||
vec![(A, One), (C, Zero)],
|
||||
]);
|
||||
}
|
||||
|
23
src/main.rs
23
src/main.rs
@ -2,15 +2,26 @@ use kv::*;
|
||||
use kv::Output::*;
|
||||
|
||||
fn main() {
|
||||
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 function = vec![0, 0, 1, 1, 1, 1, 1, 0].into_iter().map(Into::into).collect();
|
||||
let groups = find_groups(&function, &[A, B, C], One);
|
||||
println!("all:");
|
||||
for x in &groups {
|
||||
println!("{}", print_implicate(x));
|
||||
println!("{}", print_implicant(x));
|
||||
}
|
||||
println!("prime:");
|
||||
let prime = find_prime(&function, &mut [A, B, C], Zero, &groups);
|
||||
for x in prime {
|
||||
println!("{}", print_implicate(&x));
|
||||
let prime = find_prime(&function, &[A, B, C], One, &groups);
|
||||
for x in &prime {
|
||||
println!("{}", print_implicant(x));
|
||||
}
|
||||
println!("solutions:");
|
||||
let solutions = all_solutions(function, &[A, B, C], One, &prime, &groups);
|
||||
for sol in solutions {
|
||||
for x in &prime {
|
||||
print!("{} | ", print_implicant(x));
|
||||
}
|
||||
for x in &sol {
|
||||
print!("{} | ", print_implicant(x));
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user