public static IEnumerable <Expr> GetAll(Expr e) { var v = new GetVarsVisitor(); v.Visit(e); return(v.variables); }
protected override ICode VisitDoLoop(StmtDoLoop s) { var ctx = s.Ctx; var body = (Stmt)this.Visit(s.Body); var @while = (Expr)this.Visit(s.While); // This order matters - body must be visited before while GetVarsVisitor.GetAll(@while); this.AddKnownTrue(ctx.ExprGen.Not(@while)); if (body != s.Body || @while != s.While) { return(new StmtDoLoop(ctx, body, @while)); } else { return(s); } }
public static Expr QuineMcCluskey(Expr e, IEnumerable <Expr> knownTrue) { HashSet <Expr> variables = new HashSet <Expr>(); Action <Expr> findVars = null; findVars = x => { bool isVar = true; switch (x.ExprType) { case Expr.NodeType.Unary: var eUnary = (ExprUnary)x; if (eUnary.Op == UnaryOp.Not) { findVars(eUnary.Expr); isVar = false; } break; case Expr.NodeType.Binary: var eBinary = (ExprBinary)x; if (eBinary.Op == BinaryOp.And || eBinary.Op == BinaryOp.Or) { findVars(eBinary.Left); findVars(eBinary.Right); isVar = false; } break; case Expr.NodeType.Literal: isVar = false; break; } if (isVar) { variables.Add(x); } }; findVars(e); var useKnownTrue = knownTrue.Where(x => GetVarsVisitor.GetAll(x).All(y => variables.Contains(y))).ToArray(); var exprs = variables.ToArray(); var exprMap = exprs.Select((x, i) => new { x, i }).ToDictionary(x => x.x, x => x.i); var truthTable = EnumBits(exprs) .Select(bits => { foreach (var known in useKnownTrue) { var knownResult = EvalVisitor.Eval(bits, exprMap, known); if (!knownResult) { return(null); } } return((bool?)EvalVisitor.Eval(bits, exprMap, e)); }) .ToArray(); var nextStageImplicants = new HashSet <Implicant>(truthTable .Select((x, i) => new { bits = new Bits(i), x }) .Where(x => !x.x.HasValue || x.x.Value) .Select(x => new Implicant(x.bits, 0, new[] { x.bits.Value })), Implicant.EqComparerInstance); var primeImplicants = new List <Implicant>(); while (nextStageImplicants.Any()) { var minTerms = nextStageImplicants .GroupBy(x => x.Bits.BitCount) .OrderBy(x => x.Key) .ToArray(); nextStageImplicants.Clear(); Implicant[] sameBitCount1 = minTerms[0].OrderBy(x => x.DoesntMatter).ThenBy(x => x.Bits.Value).ToArray(), sameBitCount0 = null; for (var sameBitCountIdx = 1; sameBitCountIdx < minTerms.Length; sameBitCountIdx++) { sameBitCount0 = sameBitCount1; sameBitCount1 = minTerms[sameBitCountIdx].OrderBy(x => x.DoesntMatter).ThenBy(x => x.Bits.Value).ToArray(); for (int i = 0; i < sameBitCount0.Length; i++) { for (int j = 0; j < sameBitCount1.Length; j++) { var minTerm0 = sameBitCount0[i]; var minTerm1 = sameBitCount1[j]; if (minTerm0.DoesntMatter == minTerm1.DoesntMatter) { var diff = new Bits(minTerm0.Bits.Value ^ minTerm1.Bits.Value); if (diff.BitCount == 1) { var combinedBits = minTerm0.Bits.Value & minTerm1.Bits.Value; var combinedDoesntMatter = minTerm0.DoesntMatter | diff.Value; var combinedCovers = minTerm0.Covers.Concat(minTerm1.Covers).OrderBy(x => x).ToArray(); var combined = new Implicant(new Bits(combinedBits), combinedDoesntMatter, combinedCovers); nextStageImplicants.Add(combined); sameBitCount0[i].Combined = true; sameBitCount1[j].Combined = true; } } } } primeImplicants.AddRange(sameBitCount0.Where(x => !x.Combined)); } primeImplicants.AddRange(sameBitCount1.Where(x => !x.Combined)); } primeImplicants = primeImplicants.OrderBy(x => x.Bits.Value).ThenBy(x => x.DoesntMatter).ToList(); var requiredMinTerms = truthTable .Select((x, i) => new { x, i }) .Where(x => x.x.HasValue && x.x.Value) .Select(x => x.i) .ToArray(); var essentialPrimeImplicants = new HashSet <Implicant>(); for (int i = 0; i < requiredMinTerms.Length; i++) { var requiredMinTerm = requiredMinTerms[i]; var covers = primeImplicants.Where(x => x.Covers.Contains(requiredMinTerm)).ToArray(); if (covers.Length == 1) { essentialPrimeImplicants.Add(covers[0]); } } var requiredPrimeImplicants = essentialPrimeImplicants.ToArray(); var nonEssentialMinTerms = requiredMinTerms.Where(x => !essentialPrimeImplicants.Any(y => y.Covers.Contains(x))).ToArray(); var nonEssentialPrimeImplicants = primeImplicants.Except(essentialPrimeImplicants).ToArray(); if (nonEssentialMinTerms.Any() && nonEssentialPrimeImplicants.Any()) { var extraPrimeImplicants = FindOptimalImplicants(nonEssentialPrimeImplicants, nonEssentialMinTerms); requiredPrimeImplicants = requiredPrimeImplicants.Concat(extraPrimeImplicants).ToArray(); } var ctx = e.Ctx; Expr eResult; if (!requiredPrimeImplicants.Any()) { eResult = ctx.Literal(false); } else { var requiredAndExprs = requiredPrimeImplicants .Select(x => { var toOr = Enumerable.Range(0, exprs.Length).Select(i => { var mask = 1 << i; if ((x.DoesntMatter & mask) != 0) { return(null); } var needNot = (x.Bits.Value & mask) == 0; if (needNot) { return(ctx.ExprGen.Not(exprs[i])); } else { return(exprs[i]); } }) .Where(y => y != null) .ToArray(); if (toOr.Any()) { var orExpr = toOr.Aggregate((a, b) => ctx.ExprGen.And(a, b)); return(orExpr); } else { return(ctx.Literal(true)); } }) .ToArray(); eResult = requiredAndExprs.Aggregate((a, b) => ctx.ExprGen.Or(a, b)); } if (e.DoesEqual(eResult)) { return(e); } else { return(eResult); } }