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);
        }