static public bool TryRefine_KLessEqualThanRight <Variable, Expression, NType, IType>( bool isSigned, IType k, Variable right, ISetOfNumbersAbstraction <Variable, Expression, NType, IType> iquery, out IType refinedIntv) where IType : IntervalBase <IType, NType> { if (k.IsNormal) { var GreaterThanK = iquery.IntervalRightOpen(k.LowerBound); IType oldValueForRight; if (iquery.TryGetValue(right, isSigned, out oldValueForRight)) { refinedIntv = oldValueForRight.Meet(GreaterThanK); } else { refinedIntv = GreaterThanK; } return(true); } refinedIntv = default(IType); return(false); }
/// <summary> /// left \lt k /// </summary> static public bool TryRefine_LeftLessThanK <Variable, Expression, IType>( bool isSigned, Variable left, IType k, ISetOfNumbersAbstraction <Variable, Expression, Rational, IType> iquery, out IType refinedIntv) where IType : IntervalBase <IType, Rational> { var result = new List <Pair <Variable, IType> >(); if (k.IsNormal) { var upperBound = k.UpperBound.IsInteger ? k.UpperBound - 1 : k.UpperBound; var LessEquanThanK = iquery.IntervalLeftOpen(upperBound); IType oldValueForLeft; if (iquery.TryGetValue(left, isSigned, out oldValueForLeft)) { refinedIntv = oldValueForLeft.Meet(LessEquanThanK); } else { refinedIntv = LessEquanThanK; } return(true); } refinedIntv = default(IType); return(false); }
private static void NewMethod2 <Variable, Expression, IType>( Polynomial <Variable, Expression> tmpLeftPoly, Polynomial <Variable, Expression> tmpRightPoly, ISetOfNumbersAbstraction <Variable, Expression, Rational, IType> iquery, ref bool isBottom, List <Pair <Variable, IType> > resultLeft) where IType : IntervalBase <IType, Rational> { Polynomial <Variable, Expression> guardInCanonicalForm; if (Polynomial <Variable, Expression> .TryToPolynomialForm(ExpressionOperator.LessThan, tmpLeftPoly, tmpRightPoly, out guardInCanonicalForm)) { // First, we consider only the case when there is at MOST one variable on the left, i.e. a * x < b if (guardInCanonicalForm.IsLinear) { if (guardInCanonicalForm.Left.Length == 1) { resultLeft = HelperFortestTrueLessThan_AxLtK(guardInCanonicalForm, iquery, resultLeft, out isBottom); } // Then, we consider the case when it is in the form a*x + b*y < k else if (guardInCanonicalForm.Left.Length == 2) { resultLeft = HelperFortestTrueLessThan_AxByLtK(guardInCanonicalForm, iquery, resultLeft, out isBottom); } } } }
static public bool TryRefine_LeftLessEqualThanK <Variable, Expression, NType, IType>( bool isSigned, Variable left, IType k, ISetOfNumbersAbstraction <Variable, Expression, NType, IType> iquery, out IType refinedIntv) where IType : IntervalBase <IType, NType> { if (k.IsNormal) { var LessEquanThanK = iquery.IntervalLeftOpen(k.UpperBound); IType oldValueForLeft; if (iquery.TryGetValue(left, isSigned, out oldValueForLeft)) { refinedIntv = oldValueForLeft.Meet(LessEquanThanK); } else { refinedIntv = LessEquanThanK; } return(true); } refinedIntv = default(IType); return(false); }
private static void NewMethod <Variable, Expression, IType>( Rational succ, ISetOfNumbersAbstraction <Variable, Expression, Rational, IType> iquery, IType kLeft, IType kRight, Variable rightVar, Variable leftVar, List <Pair <Variable, IType> > result) where IType : IntervalBase <IType, Rational> { IType refinedIntv; if (TryRefine_KLessThanRight(true, kLeft, rightVar, succ, iquery, out refinedIntv)) { result.Add(rightVar, refinedIntv); } if (TryRefine_LeftLessThanK(true, leftVar, kRight, iquery, out refinedIntv)) { result.Add(leftVar, refinedIntv); } }
static public void InferConstraints_NotEq <Variable, Expression, IType>( Expression left, Expression right, IExpressionDecoder <Variable, Expression> decoder, ISetOfNumbersAbstraction <Variable, Expression, Rational, IType> iquery, out List <Pair <Variable, IType> > resultLeft, out List <Pair <Variable, IType> > resultRight, out bool isBottomLeft, out bool isBottomRight) where IType : IntervalBase <IType, Rational> { isBottomLeft = false; // False untils someone proves the contrary isBottomRight = false; resultLeft = new List <Pair <Variable, IType> >(); resultRight = new List <Pair <Variable, IType> >(); var kLeft = iquery.Eval(left); var kRight = iquery.Eval(right); var rightVar = decoder.UnderlyingVariable(right); var leftVar = decoder.UnderlyingVariable(left); var succ = IsFloat(left, decoder) || IsFloat(right, decoder) ? Rational.For(0) : Rational.For(1); NewMethod <Variable, Expression, IType>(succ, iquery, kLeft, kRight, rightVar, leftVar, resultLeft); NewMethod <Variable, Expression, IType>(succ, iquery, kRight, kLeft, leftVar, rightVar, resultRight); // Try to infer some more fact Polynomial <Variable, Expression> tmpLeftPoly, tmpRightPoly; if (Polynomial <Variable, Expression> .TryToPolynomialForm(left, decoder, out tmpLeftPoly) && Polynomial <Variable, Expression> .TryToPolynomialForm(right, decoder, out tmpRightPoly)) { NewMethod2 <Variable, Expression, IType>(tmpLeftPoly, tmpRightPoly, iquery, ref isBottomLeft, resultLeft); NewMethod2 <Variable, Expression, IType>(tmpRightPoly, tmpLeftPoly, iquery, ref isBottomRight, resultRight); } }
/// <summary> /// Handles the case when the guard is in the form of "A*x + B*y < k" /// </summary> /// <param name="guardInCanonicalForm">A polynomial that must have been already put into canonical form</param> static private List <Pair <Variable, IType> > HelperFortestTrueLessThan_AxByLtK <Variable, Expression, IType>( Polynomial <Variable, Expression> guardInCanonicalForm, ISetOfNumbersAbstraction <Variable, Expression, Rational, IType> iquery, List <Pair <Variable, IType> > result, out bool isBottom) where IType : IntervalBase <IType, Rational> { Contract.Requires(!object.ReferenceEquals(guardInCanonicalForm, null)); Contract.Requires(iquery != null); Contract.Requires(result != null); Contract.Requires(guardInCanonicalForm.Left.Length == 2); Contract.Requires(guardInCanonicalForm.Right.Length == 1); Contract.Ensures(Contract.Result <List <Pair <Variable, IType> > >() != null); isBottom = false; // False, unless another proof var monomialForX = guardInCanonicalForm.Left[0]; var monomialForY = guardInCanonicalForm.Left[1]; var X = monomialForX.VariableAt(0); var Y = monomialForY.VariableAt(0); var K = guardInCanonicalForm.Right[0].K; var A = monomialForX.K; var B = monomialForY.K; var intervalForA = iquery.For(A); var intervalForB = iquery.For(B); var intervalForK = iquery.For(K); var intervalForX = iquery.Eval(X); var intervalForY = iquery.Eval(Y); // 1. Handle the case for x // evalForX =(k - b * y) / a var evalForX = iquery.Interval_Div((iquery.Interval_Sub(intervalForK, (iquery.Interval_Mul(intervalForB, intervalForY)))), intervalForA); if (A > 0) { // x < (k - b * y) / a var upperBound = evalForX.UpperBound; IType gt; if (upperBound.IsInteger) { gt = iquery.IntervalLeftOpen(upperBound - 1); } else { gt = iquery.IntervalLeftOpen(upperBound.PreviousInt32); } var intv = intervalForX.Meet(gt); if (intv.IsBottom) { isBottom = true; return(result); } result.Add(X, intv); } else if (A < 0) { // x > (k - b * y) / a var lowerBound = evalForX.LowerBound; IType lt; if (lowerBound.IsInteger) { lt = iquery.IntervalRightOpen(lowerBound + 1); } else { lt = iquery.IntervalRightOpen(lowerBound.NextInt32); } var intv = intervalForX.Meet(lt); if (intv.IsBottom) { isBottom = true; return(result); } result.Add(X, intv); } else { Contract.Assert(false, "Cannot have a == 0"); } // 2. Handle the case for y // evalForY =(k - a * x) / b var evalForY = iquery.Interval_Div((iquery.Interval_Sub(intervalForK, (iquery.Interval_Mul(intervalForA, intervalForX)))), intervalForB); if (B > 0) { // y < (k - a * x) / b var upperBound = evalForY.UpperBound; IType gt; if (upperBound.IsInteger) { gt = iquery.IntervalLeftOpen(upperBound - 1); } else { gt = iquery.IntervalLeftOpen(upperBound.PreviousInt32); } var intv = intervalForY.Meet(gt); if (intv.IsBottom) { isBottom = true; return(result); } result.Add(Y, intv); } else if (B < 0) { // x > (k - a * x) / b var lowerBound = evalForY.LowerBound; IType lt; if (lowerBound.IsInteger) { lt = iquery.IntervalRightOpen(lowerBound + 1); } else { lt = iquery.IntervalRightOpen(lowerBound.NextInt32); } var intv = intervalForY.Meet(lt); if (intv.IsBottom) { isBottom = true; return(result); } result.Add(Y, intv); } else { Contract.Assert(false, "Cannot have b == 0"); } return(result); }
/// <summary> /// Handles the case when the guard is in the form of "A*x < k" /// </summary> /// <param name="guardInCanonicalForm">A polynomial that must have been already put into canonical form</param> static private List <Pair <Variable, IType> > HelperFortestTrueLessThan_AxLtK <Variable, Expression, IType>( Polynomial <Variable, Expression> guardInCanonicalForm, ISetOfNumbersAbstraction <Variable, Expression, Rational, IType> iquery, List <Pair <Variable, IType> > result, out bool isBottom) where IType : IntervalBase <IType, Rational> { Contract.Requires(!object.ReferenceEquals(guardInCanonicalForm, null)); Contract.Requires(guardInCanonicalForm.Right.Length == 1); Contract.Requires(iquery != null); Contract.Requires(result != null); Contract.Ensures(Contract.Result <List <Pair <Variable, IType> > >() != null); isBottom = false; var MonomialForX = guardInCanonicalForm.Left[0]; var MonomilaForB = guardInCanonicalForm.Right[0]; Contract.Assert(MonomilaForB.IsConstant); // 1. We have a case a < b if (MonomialForX.IsConstant) { var a = MonomialForX.K; var b = MonomilaForB.K; if (a >= b) { isBottom = true; } } else // 2. We have the case a * x < b { var x = MonomialForX.VariableAt(0); Rational k; if (!Rational.TryDiv(MonomilaForB.K, MonomialForX.K, out k)) //var k = MonomilaForB.K / MonomialForX.K; { return(result); } var oldValueForX = iquery.Eval(x); IType newConstraint; if (MonomialForX.K.Sign == 1) { // The constraint is x < k, but if k is a rational, we approximate it with x \leq k if (k.IsInteger) { newConstraint = iquery.IntervalLeftOpen(k - 1); } else { newConstraint = iquery.IntervalLeftOpen(k.PreviousInt32); } } else { // The constraint is x > k, but if k is a rational, we approximate it with k \leq x if (k.IsInteger) { newConstraint = iquery.IntervalRightOpen(k + 1); } else { newConstraint = iquery.IntervalRightOpen(k.NextInt32); } } var newValueForX = oldValueForX.Meet(newConstraint); if (newValueForX.IsBottom) { isBottom = true; } else { result.Add(x, newValueForX); } } return(result); }
static private List <Pair <Variable, IType> > HelperFortestTrueLessEqualThan_AxLeqK <Variable, Expression, IType>( Polynomial <Variable, Expression> guardInCanonicalForm, ISetOfNumbersAbstraction <Variable, Expression, Rational, IType> iquery, List <Pair <Variable, IType> > result, out bool isBottom) where IType : IntervalBase <IType, Rational> { Contract.Requires(!object.ReferenceEquals(guardInCanonicalForm, null)); Contract.Requires(result != null); Contract.Requires(guardInCanonicalForm.Right.Length == 1); Contract.Ensures(Contract.Result <List <Pair <Variable, IType> > >() != null); var MonomialForX = guardInCanonicalForm.Left[0]; var MonomilaForB = guardInCanonicalForm.Right[0]; Contract.Assert(MonomilaForB.IsConstant); isBottom = false; // 1. We have a case a <= b if (MonomialForX.IsConstant) { var a = MonomialForX.K; var b = MonomilaForB.K; if (a > b) { isBottom = true; } } else // 2. We have the case a * x \leq b { var x = MonomialForX.VariableAt(0); Rational k; if ( MonomialForX.K.IsInteger && Rational.TryDiv(MonomilaForB.K, MonomialForX.K, out k)) { var oldValueForX = iquery.Eval(x); IType newValueForX; if (MonomialForX.K.Sign == 1) { // The constraint is x \leq k newValueForX = oldValueForX.Meet(iquery.IntervalLeftOpen(k)); } else { // The constraint is x \geq k newValueForX = oldValueForX.Meet(iquery.IntervalRightOpen(k)); } if (newValueForX.IsBottom) { isBottom = true; } else { Contract.Assert(isBottom == false); result.Add(x, newValueForX); } } } return(result); }
static public List <Pair <Variable, IType> > InferConstraints_LT <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.Ensures(Contract.Result <List <Pair <Variable, IType> > >() != null); isBottom = false; // False untils someone proves the contrary var result = new List <Pair <Variable, IType> >(); var kLeft = iquery.Eval(left); var kRight = iquery.Eval(right); if (!isSignedComparison && !IsFloat(left, decoder) && !IsFloat(right, decoder)) { kLeft = kLeft.ToUnsigned(); kRight = kRight.ToUnsigned(); } IType refinedIntv; var rightVar = decoder.UnderlyingVariable(right); var succ = IsFloat(left, decoder) || IsFloat(right, decoder) ? Rational.For(0) : Rational.For(1); if (TryRefine_KLessThanRight(isSignedComparison, kLeft, rightVar, succ, 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); } } if (IsFloat(left, decoder) || IsFloat(right, decoder)) { return(result); } var leftVar = decoder.UnderlyingVariable(left); if (TryRefine_LeftLessThanK(isSignedComparison, leftVar, kRight, iquery, out refinedIntv)) { // As above // unsigned ==> right is not a constant if (isSignedComparison || !kLeft.IsSingleton) { result.Add(leftVar, refinedIntv); } } if (isSignedComparison) { // Try to infer some more fact Polynomial <Variable, Expression> guardInCanonicalForm; if (Polynomial <Variable, Expression> .TryToPolynomialForm(ExpressionOperator.LessThan, left, right, decoder, out guardInCanonicalForm) && guardInCanonicalForm.IsLinear) { // First, we consider only the case when there is at MOST one variable on the left, i.e. a * x < b { if (guardInCanonicalForm.Left.Length == 1) { result = HelperFortestTrueLessThan_AxLtK(guardInCanonicalForm, iquery, result, out isBottom); } // Then, we consider the case when it is in the form a*x + b*y < k else if (guardInCanonicalForm.Left.Length == 2) { return(HelperFortestTrueLessThan_AxByLtK(guardInCanonicalForm, iquery, result, out isBottom)); } } } else { #region Try to infer something else... switch (decoder.OperatorFor(left)) { case ExpressionOperator.And: // case "(leftLeft && leftRight) < right var leftRight = decoder.RightExpressionFor(left); Int32 valueLeft; if (decoder.IsConstantInt(leftRight, out valueLeft)) { if (IsPowerOfTwoMinusOne(valueLeft)) { // add the constraint " 0 <= right < valueLeft " var oldVal = iquery.Eval(right); var evalVal = iquery.Eval(left); var newVal = iquery.For(Rational.For(0), Rational.For(valueLeft - 1)); // [0, valueLeft-1], "-1" as we know it is an integer result.Add(rightVar, oldVal.Meet(newVal).Meet(evalVal)); } } break; default: // do nothing... break; } #endregion } } return(result); }
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); }
/// <summary> /// Infer exp \in [0, +oo], and if exp is a compound expression also some other constraints /// </summary> static public List <Pair <Variable, IType> > InferConstraints_GeqZero <Variable, Expression, IType>( Expression exp, IExpressionDecoder <Variable, Expression> decoder, ISetOfNumbersAbstraction <Variable, Expression, Rational, IType> iquery) where IType : IntervalBase <IType, Rational> { Contract.Requires(decoder != null); Contract.Requires(iquery != null); Contract.Ensures(Contract.Result <List <Pair <Variable, IType> > >() != null); var result = new List <Pair <Variable, IType> >(); var expVar = decoder.UnderlyingVariable(exp); result.Add(expVar, iquery.Eval(exp).Meet(iquery.Interval_Positive)); if (!decoder.IsVariable(exp)) { Polynomial <Variable, Expression> zero; // = 0 if (!Polynomial <Variable, Expression> .TryToPolynomialForm(new Monomial <Variable>[] { new Monomial <Variable>(0) }, out zero)) { throw new AbstractInterpretationException("It can never be the case that the conversion of a list of monomials into a polynomial fails"); } Polynomial <Variable, Expression> expAsPolynomial, newPolynomial; if (Polynomial <Variable, Expression> .TryToPolynomialForm(exp, decoder, out expAsPolynomial) && Polynomial <Variable, Expression> .TryToPolynomialForm(ExpressionOperator.LessEqualThan, zero, expAsPolynomial, out newPolynomial)) // 0 <= exp { if (newPolynomial.IsIntervalForm) { // if it is in the form of k1 * x <= k2 var k1 = newPolynomial.Left[0].K; var x = newPolynomial.Left[0].VariableAt(0); var k2 = newPolynomial.Right[0].K; Rational bound; if (Rational.TryDiv(k2, k1, out bound)) //var bound = k2 / k1; { if (k1 > 0) { var intv = iquery.Eval(x).Meet(iquery.IntervalLeftOpen(bound)); result.Add(x, intv); } else if (k1 < 0) { var intv = iquery.Eval(x).Meet(iquery.IntervalRightOpen(bound)); result.Add(x, intv); } else { throw new AbstractInterpretationException("Impossible case"); } } } } } return(result); }