Browse Source
IntegerBound class for convenient handling of lower/upper bounds and intervals. [Joachim Klein]
IntegerBound class for convenient handling of lower/upper bounds and intervals. [Joachim Klein]
git-svn-id: https://www.prismmodelchecker.org/svn/prism/prism/trunk@9564 bbc10eb1-c90d-0410-af57-cb519fbb1720master
1 changed files with 224 additions and 0 deletions
@ -0,0 +1,224 @@ |
|||
//============================================================================== |
|||
// |
|||
// Copyright (c) 2014- |
|||
// Authors: |
|||
// * Joachim Klein <klein@tcs.inf.tu-dresden.de> (TU Dresden) |
|||
// |
|||
//------------------------------------------------------------------------------ |
|||
// |
|||
// This file is part of PRISM. |
|||
// |
|||
// PRISM is free software; you can redistribute it and/or modify |
|||
// it under the terms of the GNU General Public License as published by |
|||
// the Free Software Foundation; either version 2 of the License, or |
|||
// (at your option) any later version. |
|||
// |
|||
// PRISM is distributed in the hope that it will be useful, |
|||
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
// GNU General Public License for more details. |
|||
// |
|||
// You should have received a copy of the GNU General Public License |
|||
// along with PRISM; if not, write to the Free Software Foundation, |
|||
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|||
// |
|||
//============================================================================== |
|||
|
|||
|
|||
package prism; |
|||
|
|||
import parser.Values; |
|||
import parser.ast.ExpressionTemporal; |
|||
|
|||
/** |
|||
* Canonical representation of an integer bound, with strict/non-strict lower and upper bound. |
|||
*/ |
|||
public class IntegerBound |
|||
{ |
|||
/** The lowest integer that is included in the bound. {@code null} for "no bound". */ |
|||
private Integer lowest; |
|||
/** The highest integer that is included in the bound. {@code null} for "no bound". */ |
|||
private Integer highest; |
|||
|
|||
|
|||
/** Create new bounds. |
|||
* @param lower: The lower bound, {@code null} represents "no lower bound" |
|||
* @param lower_strict: Is the lower bound strict (> lower) or non-strict (>= lower) |
|||
* @param upper: The upper bound, {@code null} represents "no upper bound" |
|||
* @param upper_strict: Is the upper bound strict (< upper) or non-strict (<= upper) |
|||
*/ |
|||
public IntegerBound(Integer lower, boolean lower_strict, Integer upper, boolean upper_strict) |
|||
{ |
|||
// normalize |
|||
if (lower_strict && lower != null) { |
|||
lowest = new Integer(lower+1); |
|||
} else { |
|||
lowest = lower; |
|||
} |
|||
if (upper_strict && upper != null) { |
|||
highest = new Integer(upper-1); |
|||
} else { |
|||
highest = upper; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* Extract the bounds from an {@code ExpressionTemporal} expression |
|||
* and create the corresponding {@code IntegerBound}. |
|||
* |
|||
* Expects that constants for the upper and lower bounds have already been resolved. |
|||
* |
|||
* If {@code check} is {@code true}, throws an exception for negative or empty bounds. |
|||
* |
|||
* @param expression the expression |
|||
* @param check check for non-negative bounds / non-emptiness? |
|||
* @return the {@code IntegerBound} for the expression |
|||
* @throws PrismException |
|||
*/ |
|||
public static IntegerBound fromExpressionTemporal(ExpressionTemporal expression, boolean check) throws PrismException |
|||
{ |
|||
return fromExpressionTemporal(expression, null, check); |
|||
} |
|||
|
|||
/** |
|||
* Extract the bounds from an {@code ExpressionTemporal} expression |
|||
* and create the corresponding {@code IntegerBound}, resolving constants |
|||
* via {@code constantValues}. |
|||
* |
|||
* If {@code check} is {@code true}, throws an exception for negative or empty bounds. |
|||
* |
|||
* @param expression the expression |
|||
* @param values the values for constants (may be {@code null}) |
|||
* @param check check for non-negative bounds / non-emptiness? |
|||
* @return the {@code IntegerBound} for the expression |
|||
* @throws PrismException |
|||
*/ |
|||
public static IntegerBound fromExpressionTemporal(ExpressionTemporal expression, Values constantValues, boolean check) throws PrismException |
|||
{ |
|||
IntegerBound bounds = new IntegerBound(expression.getLowerBound() == null ? null : expression.getLowerBound().evaluateInt(constantValues), |
|||
expression.lowerBoundIsStrict(), |
|||
expression.getUpperBound() == null ? null : expression.getUpperBound().evaluateInt(constantValues), |
|||
expression.upperBoundIsStrict()); |
|||
|
|||
if (check) { |
|||
if (bounds.hasNegativeBound()) { |
|||
throw new PrismException("Negative bound in "+expression.toString()); |
|||
} |
|||
if (bounds.isEmpty()) { |
|||
throw new PrismException("Empty bound in "+expression.toString()); |
|||
} |
|||
} |
|||
|
|||
return bounds; |
|||
} |
|||
|
|||
/** Returns {@code true} if there exists some lower bound. */ |
|||
public boolean hasLowerBound() |
|||
{ |
|||
return lowest != null; |
|||
} |
|||
|
|||
/** Returns {@code true} if there exists some upper bound. */ |
|||
public boolean hasUpperBound() |
|||
{ |
|||
return highest != null; |
|||
} |
|||
|
|||
/** |
|||
* Returns the lowest integer included in the bounds. {@code null} = "no bound". |
|||
* Assumes that {@code isEmpty()} is {@code false}. |
|||
**/ |
|||
public Integer getLowestInteger() |
|||
{ |
|||
return lowest; |
|||
} |
|||
|
|||
/** |
|||
* Returns the highest integer included in the bounds. {@code null} = "no bound". |
|||
* Assumes that {@code isEmpty} is {@code false}. |
|||
**/ |
|||
public Integer getHighestInteger() |
|||
{ |
|||
return highest; |
|||
} |
|||
|
|||
/** Returns {@code true} if the lower or upper bound is negative. */ |
|||
public boolean hasNegativeBound() |
|||
{ |
|||
if (lowest != null && lowest < 0 || |
|||
highest != null && highest < 0) { |
|||
return true; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
/** Returns {@code true} if the lower bound is higher than the upper bound. */ |
|||
public boolean isEmpty() |
|||
{ |
|||
if (hasLowerBound() && hasUpperBound()) return getLowestInteger()>getHighestInteger(); |
|||
return false; |
|||
} |
|||
|
|||
/** Returns true if {@code value} is in the bounds. */ |
|||
public boolean isInBounds(int value) |
|||
{ |
|||
if (lowest!=null) { |
|||
if (value >= lowest) { |
|||
// continue |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
if (highest!=null) { |
|||
if (value <= highest) { |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
// no bound (upper=lower=null) |
|||
return true; |
|||
} |
|||
|
|||
/** Get the maximal interesting value, i.e., the value v such that |
|||
* for _all_ i>=v either isInBound(i)=true or isInBound(i)=false */ |
|||
public int getMaximalInterestingValue() |
|||
{ |
|||
int max = 0; |
|||
|
|||
if (isEmpty()) return 0; |
|||
|
|||
if (lowest != null) { |
|||
max = lowest; |
|||
} |
|||
|
|||
if (highest != null) { |
|||
max = highest + 1; |
|||
} |
|||
|
|||
return max; |
|||
} |
|||
|
|||
/** String representation */ |
|||
public String toString() |
|||
{ |
|||
if (hasLowerBound()) { |
|||
if (hasUpperBound()) { |
|||
if (getLowestInteger().equals(getHighestInteger())) { |
|||
return "="+getLowestInteger(); |
|||
} |
|||
return "["+getLowestInteger()+","+getHighestInteger()+"]"; |
|||
} else { |
|||
return ">="+getLowestInteger(); |
|||
} |
|||
} else { |
|||
if (hasUpperBound()) { |
|||
return "<="+getHighestInteger(); |
|||
} else { |
|||
return ""; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue