Exemple #1
0
            public static IEnumerable <Expr> GetAll(Expr e)
            {
                var v = new GetVarsVisitor();

                v.Visit(e);
                return(v.variables);
            }
Exemple #2
0
        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);
            }
        }
Exemple #3
0
        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);
            }
        }