You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
197 lines
6.9 KiB
197 lines
6.9 KiB
//==============================================================================
|
|
//
|
|
// 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 computation mode (parametric / exact) */
|
|
private ParamMode mode;
|
|
/** 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(ParamMode mode, RegionValues regionValues, ModelBuilder modelBuilder, FunctionFactory factory)
|
|
{
|
|
this.mode = mode;
|
|
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 " + mode + " 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 " + mode + " results with multiple regions not supported");
|
|
}
|
|
|
|
if (propertyType.equals(TypeBool.getInstance())) {
|
|
// boolean result
|
|
boolean boolResult = regionValues.getResult(0).getInitStateValueAsBoolean();
|
|
boolean boolExpected = expected.evaluateExact().toBoolean();
|
|
|
|
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 " + mode + " property");
|
|
}
|
|
param.Function func = regionValues.getResult(0).getInitStateValueAsFunction();
|
|
|
|
if (!func.equals(funcExpected)) {
|
|
throw new PrismException("Wrong result (expected " + strExpected + " = " + funcExpected + ", got " + func + ")");
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|