|
|
/*
* This file is part of the program ltl2dstar (http://www.ltl2dstar.de/).
* Copyright (C) 2005-2007 Joachim Klein <j.klein@ltl2dstar.de> * * 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 */
#ifndef DRA_H
#define DRA_H
/** @file
* Provide class DRA<> which can store a deterministic Rabin or Streett automaton. */
#include "DA.hpp"
#include "DA_State.hpp"
#include "RabinAcceptance.hpp"
#include "APSet.hpp"
#include "APElement.hpp"
#include "DAUnionAlgorithm.hpp"
#include "common/Index.hpp"
#include "common/Exceptions.hpp"
#include <iterator>
#include <iostream>
#include <map>
#include <string>
#include <memory>
/**
* A class representing a deterministic Rabin automaton. * <p> * For details on the template parameters, see class DA. * </p> * The DRA can be considered as a Streett automaton, if * a flag is set. */ template <typename Label, template <typename N> class EdgeContainer > class DRA : public DA<Label, EdgeContainer, RabinAcceptance> { public: DRA(APSet_cp ap_set); virtual ~DRA(); /** The type of the states of the DRA. */ typedef typename DA<Label,EdgeContainer,RabinAcceptance>::state_type state_type;
/** The type of the label on the edges. */ typedef typename DA<Label,EdgeContainer,RabinAcceptance>::label_type label_type;
/** The type of an iterator over the states. */ typedef typename DA<Label,EdgeContainer,RabinAcceptance>::iterator iterator;
/** The type of an iterator over the edges of a state. */ typedef typename DA<Label,EdgeContainer,RabinAcceptance>::edge_iterator edge_iterator;
/** Type of an iterator over the index of acceptance pairs. */ typedef typename RabinAcceptance::acceptance_pair_iterator acceptance_pair_iterator;
typedef RabinAcceptance acceptance_condition_type;
/** Type of a reference counted pointer to the DRA (std::shared_ptr) */ typedef std::shared_ptr< DRA<Label,EdgeContainer> > shared_ptr;
/** Create a new instance of the automaton. */ virtual DA<Label,EdgeContainer,RabinAcceptance> *createInstance(APSet_cp ap_set) { return new DRA<Label,EdgeContainer>(ap_set); }
/** Make this automaton into an never accepting automaton */ void constructEmpty() { state_type* n=DA<Label,EdgeContainer,RabinAcceptance>::newState(); this->setStartState(n); for (APSet::element_iterator it_elem= DA<Label,EdgeContainer,RabinAcceptance>::getAPSet().all_elements_begin(); it_elem!=DA<Label,EdgeContainer,RabinAcceptance>::getAPSet().all_elements_end(); ++it_elem) { APElement label=(*it_elem); n->edges().addEdge(label, n); } }
/**
* Print the DRA/DSA in v2 format to the output stream. * This function can compact the automaton, which may invalidate iterators! */ void print_explicit_v2(std::ostream& out) { if (!this->isCompact()) { this->makeCompact(); }
this->print_da_explicit_v2(typeID(), out); }
/**
* Print the DRA/DSA in DOT format to the output stream. * This function can compact the automaton, which may invalidate iterators! */ void print_dot(std::ostream& out) { if (!this->isCompact()) { this->makeCompact(); }
this->print_da_dot(typeID(), out); }
/**
* Output operator for the DRA/DSA. */ friend std::ostream& operator<<(std::ostream& out, DRA& dra) { dra.print_explicit_v2(out); return out; }
/** Output state label for DOT printing.
* @param out the output stream * @param state_index the state index */ virtual void formatStateForDOT(std::ostream& out, unsigned int state_index) { state_type* cur_state=this->get(state_index);
bool is_html=false;
bool has_pos=false, has_neg=false;
std::ostringstream acc_sig; for (unsigned int pair_index=0;pair_index<this->acceptance().size();pair_index++) { if (this->acceptance().isStateInAcceptance_L(pair_index, state_index)) { acc_sig << " +" << pair_index; has_pos=true; }
if (this->acceptance().isStateInAcceptance_U(pair_index, state_index)) { acc_sig << " -" << pair_index; has_neg=true; } } std::string label;
if (cur_state->hasDescription()) { std::string description=cur_state->getDescription(); is_html=true; std::string acc_color; if (has_pos) { if (has_neg) { acc_color="BGCOLOR=\"lightblue\""; } else { acc_color="BGCOLOR=\"green\""; } } else { if (has_neg) { acc_color="BGCOLOR=\"red\""; } }
StringAlgorithms::replace_all(description, "<TABLE>", "<TABLE BORDER=\"0\" CELLBORDER=\"1\">");
out << "label= < "; out << "<TABLE BORDER=\"0\"><TR><TD BORDER=\"1\">"; out << state_index; out << "</TD><TD " << acc_color << ">"; out << acc_sig.str(); out << "</TD></TR><TR><TD COLSPAN=\"2\">"; out << description; out << "</TD></TR></TABLE>"; out << " >, shape=box";
} else { out << "label= \"" << state_index; if (acc_sig.str().length()!=0) { out << "\\n" << acc_sig.str(); } out << "\"";
if (!has_pos && !has_neg) { out << ", shape=circle"; } else { out << ", shape=box"; } } if (this->getStartState() == cur_state) { out << ", style=filled, color=black, fillcolor=grey"; } }
/**
* Optimizes the acceptance condition. * This function may delete acceptance pairs, * which can invalidate iterators. */ void optimizeAcceptanceCondition() { RabinAcceptance::acceptance_pair_iterator it=this->acceptance().acceptance_pair_begin(); while (it!=this->acceptance().acceptance_pair_end()) { unsigned int id=*it;
// increment iterator here so we can eventually delete
// acceptance pair without side effects
++it;
// L = L \ U
if (this->acceptance().getAcceptance_L(id).intersects(this->acceptance().getAcceptance_U(id))) { BitSet L_minus_U=this->acceptance().getAcceptance_L(id); L_minus_U.Minus(this->acceptance().getAcceptance_U(id)); this->acceptance().getAcceptance_L(id)=L_minus_U; }
// remove if L is empty
if (this->acceptance().getAcceptance_L(id).isEmpty()) { // no state is in L(id) -> remove
this->acceptance().removeAcceptancePair(id); } } }
/** Is this DRA considered as a Streett automaton? */ bool isStreett() const {return _isStreett;} /** Consider this DRA as a Streett automaton. */ void considerAsStreett(bool flag=true) {_isStreett=flag;}
static shared_ptr calculateUnion(DRA& dra1, DRA& dra2, bool trueloop_check=true, bool detailed_states=false) { if (dra1.isStreett() || dra2.isStreett()) { THROW_EXCEPTION(Exception, "Can not calculate union for Streett automata"); }
return DAUnionAlgorithm<DRA>::calculateUnion(dra1, dra2, trueloop_check, detailed_states); }
static shared_ptr calculateUnionStuttered(DRA& dra1, DRA& dra2, StutterSensitivenessInformation::ptr stutter_information, bool trueloop_check=true, bool detailed_states=false) { if (dra1.isStreett() || dra2.isStreett()) { THROW_EXCEPTION(Exception, "Can not calculate union for Streett automata"); }
return DAUnionAlgorithm<DRA>::calculateUnionStuttered(dra1, dra2, stutter_information, trueloop_check, detailed_states); }
private: /** Return a string giving the type of the automaton. */ std::string typeID() const { if (isStreett()) { return std::string("DSA"); } else { return std::string("DRA"); } } /** Marker, is this DRA considered as a Streett automaton? */ bool _isStreett; };
/**
* Constructor. * @param ap_set the underlying APSet */ template <typename Label, template <typename N> class EdgeContainer > DRA<Label, EdgeContainer>::DRA(APSet_cp ap_set) : DA<Label,EdgeContainer,RabinAcceptance>(ap_set), _isStreett(false) { }
/**
* Destructor. */ template <typename Label, template <typename N> class EdgeContainer > DRA<Label, EdgeContainer>::~DRA() {
}
#endif
|