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.
 
 
 
 
 
 

316 lines
7.3 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
*
* 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.util.*;
import prism.PrismException;
import java.io.PrintStream;
import jltl2ba.APElement;
import jltl2ba.APSet;
import jltl2ba.MyBitSet;
/** @file
* Provides class NBA to store a nondeterministic B�chi automaton.
*/
/**
* A nondeterministic B�chi automaton.
* See class DA for description of template parameters.
*/
public class NBA implements Iterable<NBA_State> {
/** Number of states */
private int _state_count;
/** Storage for the states */
private Vector<NBA_State> _index;
/** The underlying APSet */
private APSet _apset;
/** The start states */
private NBA_State _start_state;
/** The states that are accepting (final) */
private MyBitSet _final_states;
/**
* Constructor.
* @param apset The underlying APSet
*/
public NBA (APSet apset)
{
_state_count = 0;
_start_state = null;
_apset = apset;
_index = new Vector<NBA_State>();
_final_states = new MyBitSet();
}
/**
* Add a new state.
* @return a pointer to the newly generated state
*/
public NBA_State newState()
{
_state_count++;
NBA_State state = new NBA_State(this);
_index.add(state);
return state;
}
/** Get number of states. */
public int size()
{
return _index.size();
}
//FIXME: ref_iterator
/** Array index operator, get the state with index i. */
public NBA_State get(int i)
{
return _index.get(i);
}
/** Get the size of the underlying APSet. */
public int getAPSize()
{
return _apset.size();
}
/** Get a const reference to the underlying APSet. */
public APSet getAPSet()
{
return _apset;
}
/** Switch the APSet to another with the same number of APs. */
public void switchAPSet(APSet new_apset) throws PrismException
{
if (new_apset.size() != _apset.size()) {
throw new PrismException("New APSet has to have the same size as the old APSet!");
}
_apset = new_apset;
}
/** Get the index for a state. */
public int getIndexForState(NBA_State state)
{
return _index.indexOf(state);
}
/** Set the start state. */
public void setStartState(NBA_State state)
{
_start_state = state;
}
/**
* Get the start state.
* @return the start state, or NULL if it wasn't set.
*/
public NBA_State getStartState()
{
return _start_state;
}
/** Get the set of final (accepting) states in the NBA */
public MyBitSet getFinalStates()
{
return _final_states;
}
// public MyBitSet calculateFinalTrueLoops(SCCs sccs);
/**
* Remove states from the set of accepting (final) states when this is redundant.
* @param sccs the SCCs of the NBA
*/
public void removeRedundantFinalStates(SCCs sccs) {
for (int scc = 0; scc < sccs.countSCCs(); ++scc) {
if (sccs.get(scc).cardinality() == 1) {
int state_id = sccs.get(scc).nextSetBit(0);
NBA_State state = this.get(state_id);
if (state.isFinal()) {
if (!sccs.stateIsReachable(state_id, state_id)) {
// The state is final and has no self-loop
// -> the final flag is redundant
state.setFinal(false);
}
}
}
}
}
/**
* Checks if the NBA is deterministic (every edge has at most one target state).
*/
public boolean isDeterministic() {
for (NBA_State state : _index) {
for (Map.Entry<APElement, MyBitSet> edge : state) {
if (edge.getValue().cardinality() > 1) {
return false;
}
}
}
return true;
}
public NBA product_automaton(NBA nba_2) {
NBA nba_1 = this;
NBA product_nba = new NBA(nba_1.getAPSet());
APSet apset = nba_1.getAPSet();
for (int s_1 = 0; s_1 < nba_1.size(); s_1++) {
for (int s_2 = 0; s_2 < nba_2.size(); s_2++) {
for (int copy = 0; copy < 2; copy++) {
int s_r = product_nba.nba_i_newState();
int to_copy = copy;
if (copy == 0 && nba_1.get(s_1).isFinal()) {
to_copy=1;
}
if (copy == 1 && nba_2.get(s_2).isFinal()) {
product_nba.get(s_r).setFinal(true);
to_copy = 0;
}
APElement label = new APElement(apset.size());
for (int i = 0; i < (1<<apset.size()); i++) {
MyBitSet to_s1 = nba_1.get(s_1).getEdge(label);
MyBitSet to_s2 = nba_2.get(s_2).getEdge(label);
MyBitSet to_set = new MyBitSet();
for (int it_e_1 = to_s1.nextSetBit(0); it_e_1 != -1; it_e_1 = to_s1.nextSetBit(it_e_1)) {
for (int it_e_2 = to_s2.nextSetBit(0); it_e_2 != -1; it_e_2 = to_s2.nextSetBit(it_e_2)) {
int to = 2 * (it_e_1 * nba_2.size() + it_e_2) + to_copy;
to_set.set(to);
}
}
product_nba.get(s_r).addEdges(label, to_set);
label.increment();
}
}
}
}
int start_1 = nba_1.getStartState().getName();
int start_2 = nba_2.getStartState().getName();
product_nba.setStartState(product_nba.get(start_1 * nba_2.size() + start_2));
return product_nba;
}
/**
* Print the NBA on the output stream.
*/
public void print(PrintStream out) {
for (NBA_State state : _index){
out.print("State " + state.getName());
if (getStartState() == state) {
out.print(" *");
}
if (state.isFinal()) {
out.print(" !");
}
out.println();
for (Map.Entry<APElement, MyBitSet> edge : state) {
APElement label = edge.getKey();
MyBitSet to_states = edge.getValue();
out.println(" " + label.toString(getAPSet(),true) + " -> " + to_states.toString());
}
}
}
// public void print_lbtt(std::ostream& out);
// public void print_dot(std::ostream& out);
/** Return number of states. */
public int getStateCount()
{
return _state_count;
}
/**
* Create a new state.
* @return the index of the new state
*/
public int nba_i_newState()
{
return newState().getName();
}
/**
* Add an edge from state <i>from</i> to state <i>to</i>
* for the edges covered by the APMonom.
* @param from the index of the 'from' state
* @param m the APMonom
* @param to the index of the 'to' state
*/
public void nba_i_addEdge(int from, APMonom m, int to)
{
this.get(from).addEdge(m, this.get(to));
}
/**
* Get the underlying APSet
* @return a const pointer to the APSet
*/
public APSet nba_i_getAPSet()
{
return getAPSet();
}
/**
* Set the final flag (accepting) for a state.
* @param state the state index
* @param final the flag
*/
public void nba_i_setFinal(int state, boolean f)
{
this.get(state).setFinal(f);
}
/**
* Set the state as the start state.
* @param state the state index
*/
public void nba_i_setStartState(int state)
{
setStartState(this.get(state));
}
public Iterator<NBA_State> iterator()
{
return _index.iterator();
}
}