Beispiel #1
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));
            }
        }
Beispiel #2
0
        public bool TryIntersect(CardRange r, out CardRange intersection)
        {
            var min = Cardinality.Max(lower, r.lower);
            var max = Cardinality.Min(upper, r.upper);

            if (max < min)
            {
                intersection = all;
                return(false);
            }
            else
            {
                intersection = new CardRange(min, max);
                return(true);
            }
        }
Beispiel #3
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);
        }