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.
 
 
 
 
 
 

386 lines
9.9 KiB

/*
* This file is part of a Java port of the program ltl2dstar
* (http://www.ltl2dstar.de/) for PRISM (http://www.prismmodelchecker.org/)
* Copyright (C) 2005-2007 Joachim Klein <j.klein@ltl2dstar.de>
* Copyright (c) 2007 Carlos Bederian
* Copyright (c) 2011- Hongyang Qu
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package jltl2dstar;
import java.io.PrintStream;
import java.util.*;
import jltl2ba.APElement;
import jltl2ba.APSet;
import prism.PrismException;
import prism.PrismNotSupportedException;
public class DA {
/**
* A class representing a deterministic omega automaton.
* <p>
* The template parameters:<br>
* Label: the type of the labeling on the edges<br>
* EdgeContainer: a template (taking the DA_State class as parameter)
* providing an EdgeContainer for holding the edges in
* the states.<br>
* </p>
* <p>
* Each state is identified by an index.<br>
* There exists one start state.<br>
* There exists an acceptance condition <br>
* The DA is <i>compact</i>, if there are no holes in the indexes of the
* states and the acceptance condition is compact as well.
* </p>
*/
/** The storage index for the states. */
private Vector<DA_State> _index;
/** The underlying APset. */
private APSet _ap_set;
/** The start state. */
private DA_State _start_state;
/** Flag to mark that the automaton is compact. */
private boolean _is_compact;
/** A comment */
private String _comment;
/** The acceptance condition for this automaton. */
private RabinAcceptance _acceptance;
/**
* Constructor.
* @param ap_set the underlying APSet.
*/
public DA(APSet ap_set)
{
_ap_set = ap_set;
_start_state = null;
_is_compact = true;
_comment = "";
_index = new Vector<DA_State>();
_acceptance = new RabinAcceptance();
}
public static DA newInstance(APSet ap_set) {
return new DA(ap_set);
}
/**
* Create a new state.
* @return a pointer to the new state.
*/
public DA_State newState()
{
DA_State state = new DA_State(this);
int name = _index.size();
state.setName(name);
_index.add(state);
_acceptance.addState(name);
return state;
}
/** Make this automaton into an never accepting automaton */
public void constructEmpty() {
DA_State n = newState();
setStartState(n);
for (Iterator<APElement> it = getAPSet().elementIterator(); it.hasNext(); ){
n.edges().put(it.next(), n);
}
}
/** The number of states in the automaton.*/
public int size()
{
return _index.size();
}
/** The type of an iterator over the states */
public Iterator<DA_State> iterator()
{
return _index.iterator();
}
/**
* Array index operator, get the state with index i.
*/
public DA_State get(int i)
{
return _index.get(i);
}
/**
* Get the size of the underlying APSet.
*/
public int getAPSize()
{
return _ap_set.size();
}
/**
* Get a const reference to the underlying APSet.
*/
public APSet getAPSet()
{
return _ap_set;
}
/**
* Switch the APSet to another with the same number of APs.
*/
public void switchAPSet(APSet new_apset) throws PrismException
{
if (new_apset.size() != _ap_set.size()) {
throw new PrismException("New APSet has to have the same size as the old APSet!");
}
_ap_set=new_apset;
}
/**
* Get the index for a state.
*/
public int getIndexForState(DA_State state)
{
return _index.indexOf(state);
}
/** Set the start state. */
public void setStartState(DA_State state)
{
_start_state=state;
}
/**
* Get the start state.
* @return the start state, or NULL if it wasn't set.
*/
public DA_State getStartState()
{
return _start_state;
}
/** Checks if the automaton is compact. */
public boolean isCompact()
{
return _is_compact && acceptance().isCompact();
}
/** Set a comment for the automaton. */
public void setComment(String comment)
{
_comment=comment;
}
/** Get the comment for the automaton. */
public String getComment()
{
return _comment;
}
/** Return reference to the acceptance condition for this automaton.
* @return reference to the acceptance condition
*/
public RabinAcceptance acceptance()
{
return _acceptance;
}
/**
* Reorder states and acceptance conditions so that
* the automaton becomes compact.
*/
public void makeCompact() throws PrismException {
acceptance().makeCompact();
if (!_is_compact) {
int i, j;
boolean moved = false;
Vector<Integer> mapping = new Vector<Integer>(_index.size());
for (i = 0, j = 0; i < _index.size(); i++) {
if (_index.get(i) != null) {
mapping.set(i, new Integer(j));
if (j != i) {
_index.set(j, _index.get(i));
_index.set(i, null);
moved = true;
}
j++;
}
else {
while (_index.get(i) == null && i < _index.size()) {
i++;
}
if (i < _index.size())
break;
}
}
if (moved) {
_index.setSize(j);
acceptance().moveStates(mapping);
}
_is_compact=true;
}
}
/**
* Print the DA in v2 format to the output stream.
* This functions expects that the DA is compact.
* @param da_type a string specifying the type of automaton ("DRA", "DSA").
* @param out the output stream
*/
public void print(String da_type, PrintStream out) throws PrismException {
// Ensure that this DA is compact...
if (!this.isCompact()) {
throw new PrismException("DA is not compact!");
}
if (this.getStartState() == null) {
// No start state!
throw new PrismException("No start state in DA!");
}
out.println(da_type+" v2 explicit");
if (_comment != "") {
out.println("Comment: \"" + _comment + "\"");
}
out.println("States: " + _index.size());
_acceptance.outputAcceptanceHeader(out);
int start_state = this.getStartState().getName();
out.println("Start: " + start_state);
// Enumerate APSet
out.print("AP: " + getAPSize());
for (int ap_i = 0; ap_i < getAPSize(); ap_i++) {
out.print(" \"" + getAPSet().getAP(ap_i) + "\"");
}
out.println();
out.println("---");
for (int i_state = 0; i_state < _index.size(); i_state++) {
DA_State cur_state = _index.get(i_state);
out.print("State: " + i_state);
if (cur_state.hasDescription()) {
out.print(" \"" + cur_state.getDescription() + "\"");
}
out.println();
_acceptance.outputAcceptanceForState(out, i_state);
Iterator<APElement> it = _ap_set.elementIterator();
while (it.hasNext()) {
APElement e = it.next();
DA_State to = cur_state.edges().get(e);
out.println(to.getName());
}
}
}
/**
* Print the DA in HOA format to the output stream.
* This functions expects that the DA is compact.
* @param da_type a string specifying the type of automaton ("DRA", "DSA").
* @param out the output stream
*/
public void printHOA(String da_type, PrintStream out) throws PrismException {
if (!da_type.equals("DRA")) throw new PrismNotSupportedException("HOA printing for "+da_type+" currently not supported");
out.println("HOA: v1");
out.println("States: "+size());
_ap_set.print_hoa(out);
out.println("Start: "+getStartState().getName());
_acceptance.outputAcceptanceHeaderHOA(out);
out.println("properties: trans-labels explicit-labels state-acc no-univ-branch deterministic");
out.println("--BODY--");
for (DA_State state : _index) {
out.print("State: "+state.getName()+ " "); // id
_acceptance.outputAcceptanceForStateHOA(out, state.getName());
for (Map.Entry<APElement, DA_State> edge : state.edges().entrySet()) {
APElement label = edge.getKey();
String labelString = "["+label.toStringHOA(_ap_set.size())+"]";
DA_State to = edge.getValue();
out.print(labelString);
out.print(" ");
out.println(to);
}
}
out.println("--END--");
}
/**
* Print the DA in dot format to the output stream.
* This functions expects that the DA is compact.
* @param da_type a string specifying the type of automaton ("DRA", "DSA").
* @param out the output stream
*/
public void printDot(String da_type, PrintStream out) throws PrismException {
// Ensure that this DA is compact...
if (!this.isCompact()) {
throw new PrismException("DA is not compact!");
}
if (this.getStartState() == null) {
// No start state!
throw new PrismException("No start state in DA!");
}
int start_state = this.getStartState().getName();
out.println("digraph model {");
for (int i_state = 0; i_state < _index.size(); i_state++) {
if(i_state == start_state)
out.println(" " + i_state + " [label=\"" + i_state + "\", shape=ellipse]");
else {
boolean isAcceptance = false;
for (int ap_i = 0; ap_i < _acceptance.size(); ap_i++) {
if(_acceptance.isStateInAcceptance_L(ap_i, i_state)) {
out.println(" " + i_state + " [label=\"" + i_state + "\", shape=doublecircle]");
isAcceptance = true;
break;
} else if(_acceptance.isStateInAcceptance_U(ap_i, i_state)) {
out.println(" " + i_state + " [label=\"" + i_state + "\", shape=box]");
isAcceptance = true;
break;
}
}
if(!isAcceptance)
out.println(" " + i_state + " [label=\"" + i_state + "\", shape=circle]");
}
}
for (int i_state = 0; i_state < _index.size(); i_state++) {
DA_State cur_state = _index.get(i_state);
for (Map.Entry<APElement, DA_State> transition : cur_state.edges().entrySet()) {
out.println(" " + i_state + " -> " + transition.getValue().getName() +
" [label=\"" + transition.getKey().toString(_ap_set, true) + "\"]");
}
}
out.println("}");
}
}