Browse Source
param: Wrap result as ParamResult, support testing (for single region result)
param: Wrap result as ParamResult, support testing (for single region result)
We wrap the RegionValues returned by ParamModelChecker in a ParamResult object, which stores additional meta-information that allow for the result to be tested. In test mode, if there is only a single region, tests against the given expected RESULT expression. git-svn-id: https://www.prismmodelchecker.org/svn/prism/prism/trunk@11639 bbc10eb1-c90d-0410-af57-cb519fbb1720master
4 changed files with 204 additions and 18 deletions
-
2prism/src/param/ParamModelChecker.java
-
194prism/src/param/ParamResult.java
-
6prism/src/parser/ast/Property.java
-
20prism/src/prism/Prism.java
@ -0,0 +1,194 @@ |
|||||
|
//============================================================================== |
||||
|
// |
||||
|
// Copyright (c) 2016- |
||||
|
// Authors: |
||||
|
// * Dave Parker <d.a.parker@cs.bham.ac.uk> (University of Birmingham/Oxford) |
||||
|
// * 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 param; |
||||
|
|
||||
|
import parser.Values; |
||||
|
import parser.ast.ConstantList; |
||||
|
import parser.ast.Expression; |
||||
|
import parser.ast.ExpressionIdent; |
||||
|
import parser.type.Type; |
||||
|
import parser.type.TypeBool; |
||||
|
import parser.type.TypeDouble; |
||||
|
import prism.Prism; |
||||
|
import prism.PrismException; |
||||
|
import prism.PrismLangException; |
||||
|
import prism.PrismNotSupportedException; |
||||
|
|
||||
|
/** |
||||
|
* Stores the result of a ParamModelChecker run (a RegionValues object) |
||||
|
* as well as additional information (ModelBuilder, FunctionFactory) |
||||
|
* that is needed to test the actual result against an expected result |
||||
|
* (test mode). |
||||
|
*/ |
||||
|
public class ParamResult |
||||
|
{ |
||||
|
/** The actual result */ |
||||
|
private RegionValues regionValues; |
||||
|
/** The model builder (for accessing expr2func) */ |
||||
|
private ModelBuilder modelBuilder; |
||||
|
/** The function factory used for model checking */ |
||||
|
private FunctionFactory factory; |
||||
|
|
||||
|
/** |
||||
|
* Constructor |
||||
|
* @param regionValues the actual result |
||||
|
* @param modelBuilder the model builder used during checking |
||||
|
* @param factory the function factory used during checking |
||||
|
*/ |
||||
|
public ParamResult(RegionValues regionValues, ModelBuilder modelBuilder, FunctionFactory factory) |
||||
|
{ |
||||
|
this.regionValues = regionValues; |
||||
|
this.modelBuilder = modelBuilder; |
||||
|
this.factory = factory; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get the region values result. |
||||
|
*/ |
||||
|
public RegionValues getRegionValues() |
||||
|
{ |
||||
|
return regionValues; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Returns the result (region values) as a String. |
||||
|
*/ |
||||
|
@Override |
||||
|
public String toString() |
||||
|
{ |
||||
|
return regionValues.toString(); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* If ParamModelChecker ran in exact mode (no parametric constants), |
||||
|
* the result will consist of a single region and a single value instead |
||||
|
* of a function. |
||||
|
* <br> |
||||
|
* This method returns this single value (either a Boolean or a BigRational). |
||||
|
* @param propertyType the type of the checked property |
||||
|
* @return Boolean/BigRational result (for the initial state) |
||||
|
* @throws PrismException if there are multiple regions or the value is a function |
||||
|
*/ |
||||
|
public Object getSimpleResult(Type propertyType) throws PrismException |
||||
|
{ |
||||
|
if (regionValues.getNumRegions() != 1) |
||||
|
throw new PrismException("Unexpected result from parametric model checker"); |
||||
|
|
||||
|
if (propertyType.equals(TypeBool.getInstance())) { |
||||
|
// boolean result |
||||
|
boolean boolResult = regionValues.getResult(0).getInitStateValueAsBoolean(); |
||||
|
return boolResult; |
||||
|
} else { |
||||
|
// numeric result |
||||
|
param.Function func = regionValues.getResult(0).getInitStateValueAsFunction(); |
||||
|
// Evaluate the function at an arbitrary point (should not depend on parameter values) |
||||
|
BigRational rat = func.evaluate(new param.Point(new BigRational[] { new BigRational(0) })); |
||||
|
return rat; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Test the result against the given expected result string. |
||||
|
* <br> |
||||
|
* Returns true if the test succeeds, throws a PrismException |
||||
|
* with an explanation otherwise. |
||||
|
* @param propertyType the type of the checked property |
||||
|
* @param strExpected the expected result (as a String) |
||||
|
* @param constValues the model/property constants used during the checking |
||||
|
* @return true if the test succeeds |
||||
|
* @throws PrismException on test failure |
||||
|
*/ |
||||
|
public boolean test(Type propertyType, String strExpected, Values constValues) throws PrismException |
||||
|
{ |
||||
|
Expression exprExcepted = null; |
||||
|
try { |
||||
|
exprExcepted = Prism.parseSingleExpressionString(strExpected); |
||||
|
|
||||
|
// the constants that can be used in the expected result expression: |
||||
|
// defined constants |
||||
|
ConstantList constantList = new ConstantList(constValues); |
||||
|
// and parametric constants |
||||
|
for (String p : modelBuilder.getParameterNames()) { |
||||
|
constantList.addConstant(new ExpressionIdent(p), null, TypeDouble.getInstance()); |
||||
|
} |
||||
|
exprExcepted.findAllConstants(constantList); |
||||
|
exprExcepted.typeCheck(); |
||||
|
|
||||
|
// replace constants in the expression that have a value |
||||
|
// with the value |
||||
|
exprExcepted = (Expression) exprExcepted.evaluatePartially(constValues, null); |
||||
|
} catch (PrismLangException e) { |
||||
|
throw new PrismException("Invalid RESULT specification \"" + strExpected + "\" for property: " + e.getMessage()); |
||||
|
} |
||||
|
return test(propertyType, exprExcepted, strExpected); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Test the result against the given expression. |
||||
|
* <br> |
||||
|
* Returns true if the test succeeds, throws a PrismException |
||||
|
* with an explanation otherwise. |
||||
|
* @param expected expression for the expected result |
||||
|
* @param strExpected the expected result (as a String, for display in error messages) |
||||
|
* @param propertyType the type of the checked property |
||||
|
* @return true if the test succeeds |
||||
|
* @throws PrismException on test failure |
||||
|
*/ |
||||
|
private boolean test(Type propertyType, Expression expected, String strExpected) throws PrismException |
||||
|
{ |
||||
|
if (regionValues.getNumRegions() != 1) { |
||||
|
throw new PrismNotSupportedException("Testing parametric results with multiple regions not supported"); |
||||
|
} |
||||
|
|
||||
|
if (propertyType.equals(TypeBool.getInstance())) { |
||||
|
// boolean result |
||||
|
boolean boolResult = regionValues.getResult(0).getInitStateValueAsBoolean(); |
||||
|
boolean boolExpected = expected.evaluateBoolean(); |
||||
|
|
||||
|
if (boolResult != boolExpected) { |
||||
|
throw new PrismException("Wrong result (expected " + strExpected + ", got " + boolResult + ")"); |
||||
|
} |
||||
|
} else { |
||||
|
// numeric result |
||||
|
Function funcExpected; |
||||
|
try { |
||||
|
funcExpected = modelBuilder.expr2function(factory, expected); |
||||
|
} catch (PrismException e) { |
||||
|
throw new PrismException("Invalid (or unsupported) RESULT specification \"" + strExpected + "\" for parametric property"); |
||||
|
} |
||||
|
param.Function func = regionValues.getResult(0).getInitStateValueAsFunction(); |
||||
|
|
||||
|
if (!func.equals(funcExpected)) { |
||||
|
throw new PrismException("Wrong result (expected " + strExpected + " = " + funcExpected + ", got " + func + ")"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue