mirror of
https://gitlab.kit.edu/uskyk/kv.git
synced 2024-11-12 20:23:42 +00:00
Full solution calculation
This commit is contained in:
parent
388ac6c412
commit
d5e3da78f9
111
src/lib.rs
111
src/lib.rs
@ -1,6 +1,8 @@
|
|||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
pub type Variable = usize;
|
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 A: Variable = 1 << 0;
|
||||||
pub const B: Variable = 1 << 1;
|
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;
|
let mut fits = true;
|
||||||
for input in 0..func.len() {
|
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() {
|
if func[input] == typ.invert() {
|
||||||
fits = false;
|
fits = false;
|
||||||
break;
|
break;
|
||||||
@ -82,10 +84,10 @@ 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)]> {
|
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));
|
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)
|
.map(block_to_mask)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
@ -95,8 +97,8 @@ pub fn find_prime<'a>(func: &FunctionSpec, vars: &[Variable], typ: Output, block
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let mut matched = None;
|
let mut matched = None;
|
||||||
for (i, (mask, inv_mask)) in block_masks.iter().enumerate() {
|
for (i, &(mask, inv_mask)) in block_masks.iter().enumerate() {
|
||||||
if input | mask == input && input & inv_mask == input {
|
if check_mask(input, mask, inv_mask) {
|
||||||
if matched.is_none() {
|
if matched.is_none() {
|
||||||
matched = Some(i);
|
matched = Some(i);
|
||||||
} else {
|
} 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()
|
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
|
/// 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) {
|
fn block_to_mask<T: AsRef<[(Variable, Output)]>>(block: T) -> (Variable, Variable) {
|
||||||
let mut mask = 0;
|
let mut mask = 0;
|
||||||
let mut inv_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 };
|
mask |= if out == One { var } else { 0 };
|
||||||
inv_mask ^= if out == Zero { var } else { 0 };
|
inv_mask ^= if out == Zero { var } else { 0 };
|
||||||
}
|
}
|
||||||
(mask, inv_mask)
|
(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 {
|
pub fn print_implicate(vars: &[(Variable, Output)]) -> String {
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
for i in 0..vars.len() {
|
for i in 0..vars.len() {
|
||||||
@ -141,6 +205,21 @@ pub fn print_implicate(vars: &[(Variable, Output)]) -> String {
|
|||||||
s
|
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 {
|
fn print_var(var: Variable) -> &'static str {
|
||||||
match var {
|
match var {
|
||||||
A => "a",
|
A => "a",
|
||||||
@ -148,4 +227,20 @@ fn print_var(var: Variable) -> &'static str {
|
|||||||
C => "c",
|
C => "c",
|
||||||
_ => "?"
|
_ => "?"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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::*;
|
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, 1, 1, 1, 1, 0].into_iter().map(Into::into).collect();
|
||||||
let groups = find_groups(&function, &mut [A, B, C], Zero);
|
let groups = find_groups(&function, &[A, B, C], One);
|
||||||
println!("all:");
|
println!("all:");
|
||||||
for x in &groups {
|
for x in &groups {
|
||||||
println!("{}", print_implicate(x));
|
println!("{}", print_implicant(x));
|
||||||
}
|
}
|
||||||
println!("prime:");
|
println!("prime:");
|
||||||
let prime = find_prime(&function, &mut [A, B, C], Zero, &groups);
|
let prime = find_prime(&function, &[A, B, C], One, &groups);
|
||||||
for x in prime {
|
for x in &prime {
|
||||||
println!("{}", print_implicate(&x));
|
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