| 1 | #[derive (Eq, Clone)] |
| 2 | pub enum Bool { |
| 3 | True, |
| 4 | False, |
| 5 | /// can be any number in `0..32`, anything else will cause panics or wrong results |
| 6 | Term(u8), |
| 7 | /// needs to contain at least two elements |
| 8 | And(Vec<Bool>), |
| 9 | /// needs to contain at least two elements |
| 10 | Or(Vec<Bool>), |
| 11 | Not(Box<Bool>), |
| 12 | } |
| 13 | |
| 14 | #[cfg (feature="quickcheck" )] |
| 15 | extern crate quickcheck; |
| 16 | |
| 17 | #[cfg (feature="quickcheck" )] |
| 18 | impl quickcheck::Arbitrary for Bool { |
| 19 | fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Self { |
| 20 | let mut terms = 0; |
| 21 | arbitrary_bool(g, 10, &mut terms) |
| 22 | } |
| 23 | fn shrink(&self) -> Box<Iterator<Item=Self>> { |
| 24 | match *self { |
| 25 | Bool::And(ref v) => Box::new(v.shrink().filter(|v| v.len() > 2).map(Bool::And)), |
| 26 | Bool::Or(ref v) => Box::new(v.shrink().filter(|v| v.len() > 2).map(Bool::Or)), |
| 27 | Bool::Not(ref inner) => Box::new(inner.shrink().map(|b| Bool::Not(Box::new(b)))), |
| 28 | _ => quickcheck::empty_shrinker(), |
| 29 | } |
| 30 | } |
| 31 | } |
| 32 | |
| 33 | #[cfg (feature="quickcheck" )] |
| 34 | fn arbitrary_bool<G: quickcheck::Gen>(g: &mut G, depth: usize, terms: &mut u8) -> Bool { |
| 35 | if depth == 0 { |
| 36 | match g.gen_range(0, 3) { |
| 37 | 0 => Bool::True, |
| 38 | 1 => Bool::False, |
| 39 | 2 => arbitrary_term(g, terms), |
| 40 | _ => unreachable!(), |
| 41 | } |
| 42 | } else { |
| 43 | match g.gen_range(0, 6) { |
| 44 | 0 => Bool::True, |
| 45 | 1 => Bool::False, |
| 46 | 2 => arbitrary_term(g, terms), |
| 47 | 3 => Bool::And(arbitrary_vec(g, depth - 1, terms)), |
| 48 | 4 => Bool::Or(arbitrary_vec(g, depth - 1, terms)), |
| 49 | 5 => Bool::Not(Box::new(arbitrary_bool(g, depth - 1, terms))), |
| 50 | _ => unreachable!(), |
| 51 | } |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | #[cfg (feature="quickcheck" )] |
| 56 | fn arbitrary_term<G: quickcheck::Gen>(g: &mut G, terms: &mut u8) -> Bool { |
| 57 | if *terms == 0 { |
| 58 | Bool::Term(*terms) |
| 59 | } else if *terms < 32 && g.gen_weighted_bool(3) { |
| 60 | *terms += 1; |
| 61 | // every term needs to show up at least once |
| 62 | Bool::Term(*terms - 1) |
| 63 | } else { |
| 64 | Bool::Term(g.gen_range(0, *terms)) |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | #[cfg (feature="quickcheck" )] |
| 69 | fn arbitrary_vec<G: quickcheck::Gen>(g: &mut G, depth: usize, terms: &mut u8) -> Vec<Bool> { |
| 70 | (0..g.gen_range(2, 20)).map(|_| arbitrary_bool(g, depth, terms)).collect() |
| 71 | } |
| 72 | |
| 73 | impl PartialEq for Bool { |
| 74 | fn eq(&self, other: &Self) -> bool { |
| 75 | use self::Bool::*; |
| 76 | match (self, other) { |
| 77 | (&True, &True) | |
| 78 | (&False, &False) => true, |
| 79 | (&Term(a: u8), &Term(b: u8)) => a == b, |
| 80 | (&Not(ref a: &Box), &Not(ref b: &Box)) => a == b, |
| 81 | (&And(ref a: &Vec), &And(ref b: &Vec)) | |
| 82 | (&Or(ref a: &Vec), &Or(ref b: &Vec)) => { |
| 83 | if a.len() != b.len() { |
| 84 | return false; |
| 85 | } |
| 86 | for a: &Bool in a { |
| 87 | if !b.iter().any(|b: &Bool| b == a) { |
| 88 | return false; |
| 89 | } |
| 90 | } |
| 91 | true |
| 92 | }, |
| 93 | _ => false, |
| 94 | } |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | impl std::ops::Not for Bool { |
| 99 | type Output = Bool; |
| 100 | fn not(self) -> Bool { |
| 101 | use self::Bool::*; |
| 102 | match self { |
| 103 | True => False, |
| 104 | False => True, |
| 105 | t: Bool @ Term(_) => Not(Box::new(t)), |
| 106 | And(mut v: Vec) => { |
| 107 | for el: &mut Bool in &mut v { |
| 108 | *el = !std::mem::replace(dest:el, src:False); |
| 109 | } |
| 110 | Or(v) |
| 111 | }, |
| 112 | Or(mut v: Vec) => { |
| 113 | for el: &mut Bool in &mut v { |
| 114 | *el = !std::mem::replace(dest:el, src:False); |
| 115 | } |
| 116 | And(v) |
| 117 | }, |
| 118 | Not(inner: Box) => *inner, |
| 119 | } |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | impl std::ops::BitAnd for Bool { |
| 124 | type Output = Self; |
| 125 | fn bitand(self, rhs: Bool) -> Bool { |
| 126 | use self::Bool::*; |
| 127 | match (self, rhs) { |
| 128 | (And(mut v: Vec), And(rhs: Vec)) => { |
| 129 | v.extend(iter:rhs); |
| 130 | And(v) |
| 131 | }, |
| 132 | (False, _) | |
| 133 | (_, False) => False, |
| 134 | (b: Bool, True) | |
| 135 | (True, b: Bool) => b, |
| 136 | (other: Bool, And(mut v: Vec)) | |
| 137 | (And(mut v: Vec), other: Bool) => { |
| 138 | v.push(other); |
| 139 | And(v) |
| 140 | }, |
| 141 | (a: Bool, b: Bool) => And(vec![a, b]), |
| 142 | } |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | impl std::ops::BitOr for Bool { |
| 147 | type Output = Self; |
| 148 | fn bitor(self, rhs: Bool) -> Bool { |
| 149 | use self::Bool::*; |
| 150 | match (self, rhs) { |
| 151 | (Or(mut v: Vec), Or(rhs: Vec)) => { |
| 152 | v.extend(iter:rhs); |
| 153 | Or(v) |
| 154 | }, |
| 155 | (False, b: Bool) | |
| 156 | (b: Bool, False) => b, |
| 157 | (_, True) | |
| 158 | (True, _) => True, |
| 159 | (other: Bool, Or(mut v: Vec)) | |
| 160 | (Or(mut v: Vec), other: Bool) => { |
| 161 | v.push(other); |
| 162 | Or(v) |
| 163 | }, |
| 164 | (a: Bool, b: Bool) => Or(vec![a, b]), |
| 165 | } |
| 166 | } |
| 167 | } |
| 168 | |
| 169 | impl Bool { |
| 170 | pub fn terms(&self) -> u32 { |
| 171 | use self::Bool::*; |
| 172 | match *self { |
| 173 | Term(u) => 1 << u, |
| 174 | Or(ref a) | |
| 175 | And(ref a) => a.iter().fold(0, |state, item| { state | item.terms() }), |
| 176 | Not(ref a) => a.terms(), |
| 177 | True | False => 0, |
| 178 | } |
| 179 | } |
| 180 | |
| 181 | pub fn eval(&self, terms: u32) -> bool { |
| 182 | use self::Bool::*; |
| 183 | match *self { |
| 184 | True => true, |
| 185 | False => false, |
| 186 | Term(i) => (terms & (1 << i)) != 0, |
| 187 | And(ref a) => a.iter().all(|item| item.eval(terms)), |
| 188 | Or(ref a) => a.iter().any(|item| item.eval(terms)), |
| 189 | Not(ref a) => !a.eval(terms), |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | pub fn minterms(&self) -> Vec<Term> { |
| 194 | let terms = self.terms(); |
| 195 | let number_of_terms = terms.count_ones(); |
| 196 | assert!((0..number_of_terms).all(|i| (terms & (1 << i)) != 0), "non-continuous naming scheme" ); |
| 197 | (0..(1 << number_of_terms)).filter(|&i| self.eval(i)).map(Term::new).collect() |
| 198 | } |
| 199 | |
| 200 | pub fn simplify(&self) -> Vec<Bool> { |
| 201 | let minterms = self.minterms(); |
| 202 | if minterms.is_empty() { |
| 203 | return vec![Bool::False]; |
| 204 | } |
| 205 | let variables = self.terms().count_ones(); |
| 206 | if variables == 0 { |
| 207 | return vec![Bool::True]; |
| 208 | } |
| 209 | let essentials = essential_minterms(minterms); |
| 210 | let expr = essentials.prime_implicant_expr(); |
| 211 | let simple = simplify_prime_implicant_expr(expr); |
| 212 | let shortest = simple.iter().map(Vec::len).min().unwrap(); |
| 213 | simple.into_iter() |
| 214 | .filter(|v| v.len() == shortest) |
| 215 | .map(|v| { |
| 216 | let mut v = v.into_iter() |
| 217 | .map(|i| essentials.essentials[i as usize] |
| 218 | .to_bool_expr(variables)); |
| 219 | if v.len() == 1 { |
| 220 | v.next().unwrap() |
| 221 | } else { |
| 222 | Bool::Or(v.collect()) |
| 223 | } |
| 224 | }).collect() |
| 225 | } |
| 226 | } |
| 227 | |
| 228 | impl std::fmt::Debug for Bool { |
| 229 | fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { |
| 230 | use self::Bool::*; |
| 231 | match *self { |
| 232 | True => write!(fmt, "T" ), |
| 233 | False => write!(fmt, "F" ), |
| 234 | Term(i) if i > 32 => write!(fmt, "<bad term id {}>" , i), |
| 235 | Term(i) => write!(fmt, " {}" , "abcdefghijklmnopqrstuvwxyzαβγδεζη" .chars().nth(i as usize).unwrap()), |
| 236 | Not(ref a) => match **a { |
| 237 | And(_) | Or(_) => write!(fmt, "( {:?})'" , a), |
| 238 | _ => write!(fmt, " {:?}'" , a), |
| 239 | }, |
| 240 | And(ref a) => { |
| 241 | for a in a { |
| 242 | match *a { |
| 243 | And(_) | Or(_) => try!(write!(fmt, "( {:?})" , a)), |
| 244 | _ => try!(write!(fmt, " {:?}" , a)), |
| 245 | } |
| 246 | } |
| 247 | Ok(()) |
| 248 | }, |
| 249 | Or(ref a) => { |
| 250 | try!(write!(fmt, " {:?}" , a[0])); |
| 251 | for a in &a[1..] { |
| 252 | match *a { |
| 253 | Or(_) => try!(write!(fmt, " + ( {:?})" , a)), |
| 254 | _ => try!(write!(fmt, " + {:?}" , a)), |
| 255 | } |
| 256 | } |
| 257 | Ok(()) |
| 258 | } |
| 259 | } |
| 260 | } |
| 261 | } |
| 262 | |
| 263 | #[derive (Debug)] |
| 264 | pub struct Essentials { |
| 265 | pub minterms: Vec<Term>, |
| 266 | pub essentials: Vec<Term>, |
| 267 | } |
| 268 | |
| 269 | pub fn simplify_prime_implicant_expr(mut e: Vec<Vec<Vec<u32>>>) -> Vec<Vec<u32>> { |
| 270 | loop { |
| 271 | let a: Vec> = e.pop().unwrap(); |
| 272 | if let Some(b: Vec>) = e.pop() { |
| 273 | let distributed: Vec> = distribute(&a, &b); |
| 274 | let simplified: Vec> = simplify(distributed); |
| 275 | e.push(simplified); |
| 276 | } else { |
| 277 | return a; |
| 278 | } |
| 279 | } |
| 280 | } |
| 281 | |
| 282 | // AA -> A |
| 283 | // A + AB -> A |
| 284 | // A + A -> A |
| 285 | fn simplify(mut e: Vec<Vec<u32>>) -> Vec<Vec<u32>> { |
| 286 | for e in &mut e { |
| 287 | e.sort(); |
| 288 | e.dedup(); |
| 289 | } |
| 290 | e.sort(); |
| 291 | e.dedup(); |
| 292 | let mut del = Vec::new(); |
| 293 | for (i, a) in e.iter().enumerate() { |
| 294 | for (j, b) in e[i..].iter().enumerate() { |
| 295 | if a.len() < b.len() { |
| 296 | // A + AB -> delete AB |
| 297 | if a.iter().all(|x| b.iter().any(|y| y == x)) { |
| 298 | del.push(j + i); |
| 299 | } |
| 300 | } else if b.len() < a.len() && b.iter().all(|x| a.iter().any(|y| y == x)) { |
| 301 | // AB + A -> delete AB |
| 302 | del.push(i); |
| 303 | } |
| 304 | } |
| 305 | } |
| 306 | del.sort(); |
| 307 | del.dedup(); |
| 308 | for del in del.into_iter().rev() { |
| 309 | e.swap_remove(del); |
| 310 | } |
| 311 | e |
| 312 | } |
| 313 | |
| 314 | // (AB + CD)(EF + GH) -> ABEF + ABGH + CDEF + CDGH |
| 315 | fn distribute(l: &[Vec<u32>], r: &[Vec<u32>]) -> Vec<Vec<u32>> { |
| 316 | let mut ret: Vec> = Vec::new(); |
| 317 | assert!(!l.is_empty()); |
| 318 | assert!(!r.is_empty()); |
| 319 | for l: &Vec in l { |
| 320 | for r: &Vec in r { |
| 321 | ret.push(l.iter().chain(r).cloned().collect()); |
| 322 | } |
| 323 | } |
| 324 | ret |
| 325 | } |
| 326 | |
| 327 | |
| 328 | impl Essentials { |
| 329 | pub fn prime_implicant_expr(&self) -> Vec<Vec<Vec<u32>>> { |
| 330 | let mut v: Vec>> = Vec::new(); |
| 331 | for t: &Term in &self.minterms { |
| 332 | let mut w: Vec> = Vec::new(); |
| 333 | for (i: usize, e: &Term) in self.essentials.iter().enumerate() { |
| 334 | if e.contains(t) { |
| 335 | assert_eq!(i as u32 as usize, i); |
| 336 | w.push(vec![i as u32]); |
| 337 | } |
| 338 | } |
| 339 | v.push(w); |
| 340 | } |
| 341 | v |
| 342 | } |
| 343 | } |
| 344 | |
| 345 | #[derive (Clone, Eq, Ord)] |
| 346 | pub struct Term { |
| 347 | dontcare: u32, |
| 348 | term: u32, |
| 349 | } |
| 350 | |
| 351 | #[cfg (feature="quickcheck" )] |
| 352 | impl quickcheck::Arbitrary for Term { |
| 353 | fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Self { |
| 354 | Term { |
| 355 | dontcare: u32::arbitrary(g), |
| 356 | term: u32::arbitrary(g), |
| 357 | } |
| 358 | } |
| 359 | } |
| 360 | |
| 361 | impl std::cmp::PartialOrd for Term { |
| 362 | fn partial_cmp(&self, rhs: &Self) -> Option<std::cmp::Ordering> { |
| 363 | use std::cmp::Ordering::*; |
| 364 | match self.dontcare.partial_cmp(&rhs.dontcare) { |
| 365 | Some(Equal) => {}, |
| 366 | other: Option => return other, |
| 367 | } |
| 368 | let l: u32 = self.term & !self.dontcare; |
| 369 | let r: u32 = rhs.term & !rhs.dontcare; |
| 370 | l.partial_cmp(&r) |
| 371 | } |
| 372 | } |
| 373 | |
| 374 | impl std::fmt::Debug for Term { |
| 375 | fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { |
| 376 | for i: i32 in (0..32).rev() { |
| 377 | if (self.dontcare & (1 << i)) == 0 { |
| 378 | if (self.term & (1 << i)) == 0 { |
| 379 | try!(write!(fmt, "0" )); |
| 380 | } else { |
| 381 | try!(write!(fmt, "1" )); |
| 382 | } |
| 383 | } else { |
| 384 | try!(write!(fmt, "-" )); |
| 385 | } |
| 386 | } |
| 387 | Ok(()) |
| 388 | } |
| 389 | } |
| 390 | |
| 391 | impl std::cmp::PartialEq for Term { |
| 392 | fn eq(&self, other: &Self) -> bool { |
| 393 | (self.dontcare == other.dontcare) && ((self.term & !self.dontcare) == (other.term & !other.dontcare)) |
| 394 | } |
| 395 | } |
| 396 | |
| 397 | #[derive (Debug, Eq, PartialEq)] |
| 398 | pub enum TermFromStrError { |
| 399 | Only32TermsSupported, |
| 400 | UnsupportedCharacter(char), |
| 401 | } |
| 402 | |
| 403 | impl std::str::FromStr for Term { |
| 404 | type Err = TermFromStrError; |
| 405 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
| 406 | if s.len() > 32 { |
| 407 | return Err(TermFromStrError::Only32TermsSupported); |
| 408 | } |
| 409 | let mut term: Term = Term::new(0); |
| 410 | for (i: usize, c: char) in s.chars().rev().enumerate() { |
| 411 | match c { |
| 412 | '-' => term.dontcare |= 1 << i, |
| 413 | '1' => term.term |= 1 << i, |
| 414 | '0' => {}, |
| 415 | c: char => return Err(TermFromStrError::UnsupportedCharacter(c)), |
| 416 | } |
| 417 | } |
| 418 | Ok(term) |
| 419 | } |
| 420 | } |
| 421 | |
| 422 | impl Term { |
| 423 | pub fn new(i: u32) -> Self { |
| 424 | Term { |
| 425 | dontcare: 0, |
| 426 | term: i, |
| 427 | } |
| 428 | } |
| 429 | |
| 430 | pub fn with_dontcare(term: u32, dontcare: u32) -> Self { |
| 431 | Term { |
| 432 | dontcare: dontcare, |
| 433 | term: term, |
| 434 | } |
| 435 | } |
| 436 | |
| 437 | pub fn combine(&self, other: &Term) -> Option<Term> { |
| 438 | let dc = self.dontcare ^ other.dontcare; |
| 439 | let term = self.term ^ other.term; |
| 440 | let dc_mask = self.dontcare | other.dontcare; |
| 441 | match (dc.count_ones(), (!dc_mask & term).count_ones()) { |
| 442 | (0, 1) | |
| 443 | (1, 0) => Some(Term { |
| 444 | dontcare: dc_mask | term, |
| 445 | term: self.term, |
| 446 | }), |
| 447 | _ => None, |
| 448 | } |
| 449 | } |
| 450 | |
| 451 | pub fn contains(&self, other: &Self) -> bool { |
| 452 | ((self.dontcare | other.dontcare) == self.dontcare) && |
| 453 | (((self.term ^ other.term) & !self.dontcare) == 0) |
| 454 | } |
| 455 | |
| 456 | pub fn to_bool_expr(&self, n_variables: u32) -> Bool { |
| 457 | assert!(self.dontcare < (1 << n_variables)); |
| 458 | assert!(self.term < (1 << n_variables)); |
| 459 | let mut v = Vec::new(); |
| 460 | for bit in 0..n_variables { |
| 461 | if (self.dontcare & (1 << bit)) == 0 { |
| 462 | if (self.term & (1 << bit)) == 0 { |
| 463 | v.push(Bool::Not(Box::new(Bool::Term(bit as u8)))) |
| 464 | } else { |
| 465 | v.push(Bool::Term(bit as u8)) |
| 466 | } |
| 467 | } |
| 468 | } |
| 469 | match v.len() { |
| 470 | 0 => Bool::True, |
| 471 | 1 => v.into_iter().next().unwrap(), |
| 472 | _ => Bool::And(v), |
| 473 | } |
| 474 | } |
| 475 | } |
| 476 | |
| 477 | pub fn essential_minterms(mut minterms: Vec<Term>) -> Essentials { |
| 478 | minterms.sort(); |
| 479 | let minterms = minterms; |
| 480 | let mut terms = minterms.clone(); |
| 481 | let mut essentials: Vec<Term> = Vec::new(); |
| 482 | while !terms.is_empty() { |
| 483 | let old = std::mem::replace(&mut terms, Vec::new()); |
| 484 | let mut combined_terms = std::collections::BTreeSet::new(); |
| 485 | for (i, term) in old.iter().enumerate() { |
| 486 | for (other_i, other) in old[i..].iter().enumerate() { |
| 487 | if let Some(new_term) = term.combine(other) { |
| 488 | terms.push(new_term); |
| 489 | combined_terms.insert(other_i + i); |
| 490 | combined_terms.insert(i); |
| 491 | } |
| 492 | } |
| 493 | if !combined_terms.contains(&i) { |
| 494 | essentials.push(term.clone()); |
| 495 | } |
| 496 | } |
| 497 | terms.sort(); |
| 498 | terms.dedup(); |
| 499 | } |
| 500 | Essentials { |
| 501 | minterms: minterms, |
| 502 | essentials: essentials, |
| 503 | } |
| 504 | } |
| 505 | |