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.
 
 
 
 
 
 

278 lines
8.3 KiB

//==============================================================================
//
// Copyright (c) 2002-
// Authors:
// * Dave Parker <david.parker@comlab.ox.ac.uk> (University of Oxford)
//
//------------------------------------------------------------------------------
//
// 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 pta;
import java.io.*;
import java.util.*;
import explicit.MDP;
import explicit.MDPModelChecker;
import prism.PrismException;
/**
* Command-line interface to PTA model checker.
*/
public class PTAModelCheckerCL
{
// Inputs
// List of PTA files
ArrayList<String> ptaFiles;
// Target info
String targetLocString, targetConstraintString;
// Flags, settings
// Compute min probabilities? (as opposed to max)
boolean min = false;
// Export the parallel composition PTA after construction?
boolean exportPTA = false;
// Do MDP forward reach rather than abstraction-refinement?
boolean mdpReach = false;
// Processed target info
String targetLocRegexp;
Constraint targetConstraint;
BitSet targetLocs;
// PTAs
PTA pta, pta2;
// Abstraction refinement object
PTAAbstractRefine abstractRefine;
/**
* Main method
*/
public static void main(String args[])
{
new PTAModelCheckerCL().go(args);
}
/**
* Main method
*/
public void go(String args[])
{
int i, n, z;
boolean found;
try {
// Build PTAAbstractRefine object
abstractRefine = new PTAAbstractRefine(null);
// Parse command-line arguments
parseCommandLineArgs(args);
// Process target info
// Strip any accidental quotes
targetLocString = targetLocString.replaceAll("['\"]", "");
targetConstraintString = targetConstraintString.replaceAll("['\"]", "");
// Build regexp for target location spec
String targetLocStringSplit[] = targetLocString.split(",");
targetLocRegexp = "";
for (String targetLocStringBit : targetLocStringSplit) {
if (!("".equals(targetLocRegexp)))
targetLocRegexp += "|";
targetLocRegexp += "(" + targetLocStringBit.replaceAll("\\*", "[a-zA-Z0-9_]*") + ")";
}
//System.out.print("Target locations regexp: " + targetLocRegexp);
// Display command-line arguments and settings:
System.out.print("Command:");
for (i = 0; i < args.length; i++)
System.out.print(" " + args[i]);
System.out.println();
abstractRefine.printSettings();
// Expand any input files that are lists of PTAs
processPTAFiles();
// Build PTA
System.out.println("\nBuilding PTA from \"" + ptaFiles.get(0) + "\"");
pta = PTA.buildPTAFromDesFile(ptaFiles.get(0));
System.out.println(pta.infoString());
//System.out.println(pta);
for (i = 1; i < ptaFiles.size(); i++) {
System.out.println("Building PTA from \"" + ptaFiles.get(i) + "\"");
pta2 = PTA.buildPTAFromDesFile(ptaFiles.get(i));
System.out.println(pta2.infoString());
//System.out.println(pta2);
pta = new PTAParallel().compose(pta, pta2);
//System.out.println(pta);
}
System.out.println("Final PTA: " + pta.infoString());
//System.out.println(pta);
// Do some checks on PTA
pta.check();
// Export PTA if required
if (exportPTA)
pta.writeToDesFile("par.des");
// Parse target clock constraint
if (targetConstraintString.equals("true")) {
targetConstraint = null;
} else {
z = pta.getOrAddClock(targetConstraintString.substring(0, 1));
if (targetConstraintString.indexOf(">=", 1) != -1)
targetConstraint = Constraint.buildGeq(z, Integer.parseInt(targetConstraintString.substring(3)));
else if (targetConstraintString.indexOf("<=", 1) != -1)
targetConstraint = Constraint.buildLeq(z, Integer.parseInt(targetConstraintString.substring(3)));
else if (targetConstraintString.indexOf(">", 1) != -1)
targetConstraint = Constraint.buildGt(z, Integer.parseInt(targetConstraintString.substring(2)));
else if (targetConstraintString.indexOf("<", 1) != -1)
targetConstraint = Constraint.buildLt(z, Integer.parseInt(targetConstraintString.substring(2)));
else
targetConstraint = null;
}
// Determine PTA locations satisfying target specification; check non-empty
n = pta.getNumLocations();
targetLocs = new BitSet(n);
found = false;
for (i = 0; i < n; i++) {
// Since we build from des files here, PTA names are strings
if (((String) pta.getLocationName(i)).matches(targetLocRegexp)) {
targetLocs.set(i);
found |= true;
}
}
if (!found)
throw new PrismException("No matches for PTA target location specification " + targetLocString);
// Display final target info
System.out.print("\nTarget locations: " + targetLocString);
System.out.println(" (" + targetLocs.cardinality() + " locations)");
System.out.println("Target constraint: "
+ (targetConstraint == null ? "true" : targetConstraint.toString(pta)));
// Do forward reach
// Default case: use game-based abstraction refinement
if (!mdpReach) {
abstractRefine.forwardsReachAbstractRefine(pta, targetLocs, targetConstraint, min);
}
// But we can also just do standard MDP-based forwards reachability
else {
ForwardsReach forwardsReach = new ForwardsReach();
ReachabilityGraph graph = forwardsReach.buildForwardsGraph(pta, targetLocs, targetConstraint);
MDP mdp = graph.buildMDP(forwardsReach.getInitialStates());
new MDPModelChecker(null).computeReachProbs(mdp, forwardsReach.getTarget(), min);
}
} catch (PrismException e) {
System.err.println("\nError: " + e.getMessage());
System.exit(1);
}
}
/**
* Parse command-line arguments
*/
private void parseCommandLineArgs(String args[]) throws PrismException
{
int i;
String s;
if (args.length < 3) {
System.err.println("Usage: ptamc [options] <des files> <target loc> <target constraint>");
System.exit(1);
}
ptaFiles = new ArrayList<String>();
for (i = 0; i < args.length; i++) {
s = args[i];
// Process a switch
if (s.charAt(0) == '-') {
s = s.substring(1);
// Local options
if (s.equals("min")) {
min = true;
} else if (s.equals("max")) {
min = false;
} else if (s.equals("exportpta")) {
exportPTA = true;
} else if (s.equals("mdp")) {
mdpReach = true;
}
// Otherwise, try passing to abstraction-refinement engine
else {
abstractRefine.parseOption(s);
}
}
// If not a switch, must be a PTA filename
else {
ptaFiles.add(s);
}
}
// Last two arguments are actually target info, not PTA files
targetLocString = ptaFiles.get(ptaFiles.size() - 2);
targetConstraintString = ptaFiles.get(ptaFiles.size() - 1);
ptaFiles.remove(ptaFiles.size() - 1);
ptaFiles.remove(ptaFiles.size() - 1);
}
/**
* Expand any input files that are lists of PTAs.
*/
private void processPTAFiles() throws PrismException
{
String s;
ArrayList<String> ptaFilesNew = new ArrayList<String>();
for (String ptaFile : ptaFiles) {
if (ptaFile.endsWith(".deslist")) {
try {
BufferedReader in = new BufferedReader(new FileReader(new File(ptaFile)));
while ((s = in.readLine()) != null) {
s = s.trim();
if (s.equals(""))
continue;
// Absolute filename
if (new File(s).isAbsolute()) {
ptaFilesNew.add(s);
}
// Relative filename
else if (new File(ptaFile).getParent() != null) {
ptaFilesNew.add(new File(ptaFile).getParent() + File.separator + s);
}
// Current directory
else {
ptaFilesNew.add(s);
}
}
} catch (IOException e) {
throw new PrismException("Could not read from file \"" + ptaFile + "\"");
}
} else {
ptaFilesNew.add(ptaFile);
}
}
ptaFiles = ptaFilesNew;
}
}