public override IntervalEnvironment <Variable, Expression> TestNotEqual(Expression e1, Expression e2)
        {
            bool isBottomLT, isBottomGT;
            List <Pair <Variable, Interval> > constraintsLT, constraintsGT;

            IntervalInference.InferConstraints_NotEq(e1, e2, this.ExpressionManager.Decoder, this,
                                                     out constraintsLT, out constraintsGT, out isBottomLT, out isBottomGT);

            if (isBottomLT)
            {
                // Bottom join Bottom = Bottom
                if (isBottomGT)
                {
                    return(this.Bottom);
                }
                this.TestTrueListOfFacts(constraintsGT);
            }
            else if (isBottomGT)
            {
                this.TestTrueListOfFacts(constraintsLT);
            }
            else
            {
                var join = JoinConstraints(constraintsLT, constraintsGT);

                this.TestTrueListOfFacts(join);
            }

            return(this);
        }
        protected override void AssumeLeftLessThanK(Variable left, DisInterval k)
        {
            DisInterval refined;

            if (IntervalInference.TryRefine_LeftLessThanK(true, left, k, this, out refined))
            {
                this[left] = refined;
            }
        }
        protected override void AssumeKLessThanRight(DisInterval k, Variable right)
        {
            DisInterval refined;

            if (IntervalInference.TryRefine_KLessThanRight(true, k, right, Rational.For(1), this, out refined))
            {
                this[right] = refined;
            }
        }
        public override DisIntervalEnvironment <Variable, Expression> TestTrueGeqZero(Expression exp)
        {
            var newConstraints = IntervalInference.InferConstraints_GeqZero(exp, this.ExpressionManager.Decoder, this);

            foreach (var pair in newConstraints)
            {
                this[pair.One] = pair.Two;
            }

            return(this);
        }
        private DisIntervalEnvironment <Variable, Expression> HelperForTestTrueLessEqualThanSignedOrUnsigned(bool isSigned, Expression exp1, Expression exp2)
        {
            bool isBottom;
            var  newConstraints = IntervalInference.InferConstraints_Leq(isSigned, exp1, exp2, this.ExpressionManager.Decoder, this, out isBottom);

            if (isBottom)
            {
                return(this.Bottom);
            }

            Assume(newConstraints);

            return(this);
        }
        /// <summary>
        /// We handle just expressions (that after being normalized) become "  a * x \lt b ", where {a, b} are constants and "x" is a variable
        /// </summary>
        private IntervalEnvironment <Variable, Expression> HelperForTestTrueLessThanSignedOrUnsigned(bool isSigned, Expression left, Expression right)
        {
            bool isBottom;
            var  constraints = IntervalInference.InferConstraints_LT(isSigned, left, right, this.ExpressionManager.Decoder, this, out isBottom);

            if (isBottom)
            {
                return(this.Bottom);
            }

            foreach (var pair in constraints)
            {
                this.RefineWith(pair.One, pair.Two);
            }
            return(this);
        }
        public override DisIntervalEnvironment <Variable, Expression> TestNotEqual(Expression e1, Expression e2)
        {
            var v2 = this.Eval(e2);

            if (v2.IsSingleton)
            {
                var notV2 = DisInterval.NotInThisInterval(v2);

                var e1Var = this.ExpressionManager.Decoder.UnderlyingVariable(this.ExpressionManager.Decoder.Stripped(e1));

                this.RefineWith(e1Var, notV2);
            }

            bool isBottomLT, isBottomGT;

            var constraintsLT = IntervalInference.InferConstraints_LT(true, e1, e2, this.ExpressionManager.Decoder, this, out isBottomLT);
            var constraintsGT = IntervalInference.InferConstraints_LT(true, e2, e1, this.ExpressionManager.Decoder, this, out isBottomGT);

            if (isBottomLT)
            {
                // Bottom join Bottom = Bottom
                if (isBottomGT)
                {
                    return(this.Bottom);
                }
                this.TestTrueListOfFacts(constraintsGT);
            }
            else if (isBottomGT)
            {
                this.TestTrueListOfFacts(constraintsLT);
            }
            else
            {
                var join = JoinConstraints(constraintsLT, constraintsGT);

                this.TestTrueListOfFacts(join);
            }

            return(this);
        }
        static public List <Pair <Variable, IType> > InferConstraints_Leq <Variable, Expression, IType>(
            bool isSignedComparison,
            Expression left, Expression right,
            IExpressionDecoder <Variable, Expression> decoder,
            ISetOfNumbersAbstraction <Variable, Expression, Rational, IType> iquery,
            out bool isBottom)
            where IType : IntervalBase <IType, Rational>
        {
            Contract.Requires(iquery != null);
            Contract.Ensures(Contract.Result <List <Pair <Variable, IType> > >() != null);

            isBottom = false; // false, unless someine proves the contrary

            var result = new List <Pair <Variable, IType> >();

            if (IsFloat(left, decoder) || IsFloat(right, decoder))
            {
                return(result);
            }

            var kLeft  = iquery.Eval(left);
            var kRight = iquery.Eval(right);

            // We have to take into account the polymorphism of constants
            if (!isSignedComparison)
            {
                kLeft  = kLeft.ToUnsigned();
                kRight = kRight.ToUnsigned();
            }

            //AssumeKLessEqualThanRight(kLeft, this.Decoder.UnderlyingVariable(right))

            IType refinedIntv;
            var   rightVar = decoder.UnderlyingVariable(right);

            if (IntervalInference.TryRefine_KLessEqualThanRight(isSignedComparison, kLeft, rightVar, iquery, out refinedIntv))
            {
                // If it is an unsigned comparison, and it is a constant, then we should avoid generating the constraint
                // Example: left <={un} right, with right == -1 then we do not want to generate the constraint right == 2^{32}-1 which is wrong!

                // unsigned ==> right is not a constant
                if (isSignedComparison || !kRight.IsSingleton)
                {
                    result.Add(rightVar, refinedIntv);
                }
            }

            //AssumeLeftLessEqualThanK(this.Decoder.UnderlyingVariable(left), kRight);
            var leftVar = decoder.UnderlyingVariable(left);

            if (IntervalInference.TryRefine_LeftLessEqualThanK(isSignedComparison, leftVar, kRight, iquery, out refinedIntv))
            {
                // unsigned ==> left is not a constant
                if (isSignedComparison || !kLeft.IsSingleton)
                {
                    result.Add(leftVar, refinedIntv);
                }
            }

            if (isSignedComparison)
            {
                Polynomial <Variable, Expression> guardInCanonicalForm;

                if (Polynomial <Variable, Expression> .TryToPolynomialForm(ExpressionOperator.LessEqualThan, left, right, decoder, out guardInCanonicalForm) &&
                    guardInCanonicalForm.IsLinear)
                {
                    // We consider only the case when there is at MOST one variable on the left, i.e. a * x \leq b, or TWO, i.e. a*x +b*y <= c
                    if (guardInCanonicalForm.Left.Length == 1)
                    {
                        return(HelperFortestTrueLessEqualThan_AxLeqK(guardInCanonicalForm, iquery, result, out isBottom));
                    }
                    else if (guardInCanonicalForm.Left.Length == 2)
                    {
                        return(HelperFortestTrueLessEqualThan_AxByLtK(guardInCanonicalForm, iquery, result, out isBottom));
                    }
                }
            }

            return(result);
        }