Example #1
0
            public static int Compare(CardVar v1, CardVar v2)
            {
                if (v1 == v2)
                {
                    return(0);
                }

                var cmp = Microsoft.Formula.Common.Terms.Symbol.Compare(v1.Symbol, v2.Symbol);

                if (cmp != 0)
                {
                    return(cmp);
                }

                if (v1.IsLFPCard && v2.IsLFPCard)
                {
                    return(0);
                }
                else if (!v1.IsLFPCard)
                {
                    return(-1);
                }
                else
                {
                    return(1);
                }
            }
Example #2
0
        private Cardinality Eval(CardExpr expr, CardVar cvar, Cardinality val, bool evalOnLower)
        {
            switch (expr.Kind)
            {
            case CardExpr.ExprKind.Cnst:
                return(((CardCnst)expr).Value);

            case CardExpr.ExprKind.Var:
                if (expr == cvar)
                {
                    return(val);
                }
                else if (evalOnLower)
                {
                    return(GetRange((CardVar)expr).Lower);
                }
                else
                {
                    return(GetRange((CardVar)expr).Upper);
                }

            case CardExpr.ExprKind.Prod:
                return(Eval(expr[0], cvar, val, evalOnLower) * Eval(expr[1], cvar, val, evalOnLower));

            case CardExpr.ExprKind.Unn:
                return(Eval(expr[0], cvar, val, evalOnLower) + Eval(expr[1], cvar, val, evalOnLower));

            default:
                throw new NotImplementedException();
            }
        }
Example #3
0
 public CardConstraint(OpKind op, CardVar lhs, CardExpr rhs)
 {
     Contract.Requires(lhs != null && rhs != null);
     Op  = op;
     Lhs = lhs;
     Rhs = rhs;
     GetRHSVars(rhs);
 }
Example #4
0
        private LinkedList <CardConstraint> GetUseList(CardVar cvar)
        {
            LinkedList <CardConstraint> cons;

            if (!useLists.TryFindValue(cvar, out cons))
            {
                cons = new LinkedList <CardConstraint>();
                useLists.Add(cvar, cons);
            }

            return(cons);
        }
Example #5
0
        private void UpdateRange(CardVar cvar, CardRange newRange)
        {
            Contract.Requires(newRange.Lower != Cardinality.Infinity);
            MutableTuple <CardRange> range;

            if (solverState.Peek().TryFindValue(cvar, out range))
            {
                range.Item1 = newRange;
            }
            else
            {
                solverState.Peek().Add(cvar, new MutableTuple <CardRange>(newRange));
            }
        }
Example #6
0
        private CardRange GetRange(CardVar cvar)
        {
            MutableTuple <CardRange> range;

            foreach (var valuations in solverState)
            {
                if (valuations.TryFindValue(cvar, out range))
                {
                    return(range.Item1);
                }
            }

            return(CardRange.All);
        }
Example #7
0
        private void EnqueueConstraints(CardVar cvar, Stack <CardConstraint> stack)
        {
            LinkedList <CardConstraint> cons;

            if (useLists.TryFindValue(cvar, out cons))
            {
                foreach (var c in cons)
                {
                    if (!c.IsQueued)
                    {
                        c.IsQueued = true;
                        stack.Push(c);
                    }
                }
            }
        }
Example #8
0
        private bool Propagate(CardVar cvar)
        {
            Cardinality    cd;
            CardRange      lhs, rhs;
            CardRange      intr, intrp;
            CardConstraint con;
            var            stack = new Stack <CardConstraint>();

            EnqueueConstraints(cvar, stack);
            while (stack.Count > 0)
            {
                con          = stack.Pop();
                lhs          = GetRange(con.Lhs);
                rhs          = Eval(con.Rhs);
                con.IsQueued = false;

                switch (con.Op)
                {
                case CardConstraint.OpKind.LEq:
                    if ((cd = Cardinality.Min(lhs.Upper, rhs.Upper)) != lhs.Upper)
                    {
                        if (cd < lhs.Lower)
                        {
                            return(false);
                        }

                        UpdateRange(con.Lhs, lhs = new CardRange(lhs.Lower, cd));
                        EnqueueConstraints(con.Lhs, stack);
                    }

                    if (rhs.Lower < lhs.Lower)
                    {
                        foreach (var rhsvar in con.RhsVars)
                        {
                            rhs = GetRange(rhsvar);
                            if (Eval(con.Rhs, rhsvar, rhs.Lower, false) >= lhs.Lower)
                            {
                                continue;
                            }

                            intr = new CardRange(rhs.Lower, Cardinality.Min(lhs.Lower, rhs.Upper));
                            while (intr.Lower + 1 < intr.Upper)
                            {
                                intrp = intr.Bisect(true);
                                if (Eval(con.Rhs, rhsvar, intrp.Lower, false) >= lhs.Lower)
                                {
                                    intr = new CardRange(intr.Lower, intrp.Lower);
                                }
                                else
                                {
                                    intr = new CardRange(intrp.Lower, intr.Upper);
                                }
                            }

                            if (Eval(con.Rhs, rhsvar, intr.Lower, false) >= lhs.Lower)
                            {
                                if (intr.Lower > rhs.Lower)
                                {
                                    UpdateRange(rhsvar, new CardRange(intr.Lower, rhs.Upper));
                                    EnqueueConstraints(rhsvar, stack);
                                    continue;
                                }
                            }
                            else if (Eval(con.Rhs, rhsvar, intr.Upper, false) >= lhs.Lower)
                            {
                                if (intr.Upper > rhs.Lower)
                                {
                                    UpdateRange(rhsvar, new CardRange(intr.Upper, rhs.Upper));
                                    EnqueueConstraints(rhsvar, stack);
                                    continue;
                                }
                            }
                            else
                            {
                                return(false);
                            }
                        }
                    }

                    break;

                case CardConstraint.OpKind.GEq:
                    if ((cd = Cardinality.Max(lhs.Lower, rhs.Lower)) != lhs.Lower)
                    {
                        if (cd > lhs.Upper)
                        {
                            return(false);
                        }

                        UpdateRange(con.Lhs, lhs = new CardRange(cd, lhs.Upper));
                        EnqueueConstraints(con.Lhs, stack);
                    }

                    if (rhs.Upper > lhs.Upper)
                    {
                        foreach (var rhsvar in con.RhsVars)
                        {
                            rhs = GetRange(rhsvar);
                            if (Eval(con.Rhs, rhsvar, rhs.Upper, true) <= lhs.Upper)
                            {
                                continue;
                            }

                            intr = new CardRange(rhs.Lower, Cardinality.Min(rhs.Upper, lhs.Upper));
                            while (intr.Lower + 1 < intr.Upper)
                            {
                                intrp = intr.Bisect(false);
                                if (Eval(con.Rhs, rhsvar, intrp.Upper, true) <= lhs.Upper)
                                {
                                    intr = new CardRange(intrp.Upper, intr.Upper);
                                }
                                else
                                {
                                    intr = new CardRange(intr.Lower, intrp.Upper);
                                }
                            }

                            if (Eval(con.Rhs, rhsvar, intr.Upper, true) <= lhs.Upper)
                            {
                                if (intr.Upper < rhs.Upper)
                                {
                                    UpdateRange(rhsvar, new CardRange(rhs.Lower, intr.Upper));
                                    EnqueueConstraints(rhsvar, stack);
                                    continue;
                                }
                            }
                            else if (Eval(con.Rhs, rhsvar, intr.Lower, true) <= lhs.Upper)
                            {
                                if (intr.Lower < rhs.Upper)
                                {
                                    UpdateRange(rhsvar, new CardRange(rhs.Lower, intr.Lower));
                                    EnqueueConstraints(rhsvar, stack);
                                    continue;
                                }
                            }
                            else
                            {
                                return(false);
                            }
                        }
                    }

                    break;

                default:
                    throw new NotImplementedException();
                }
            }

            return(true);
        }