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.
305 lines
8.5 KiB
305 lines
8.5 KiB
/*
|
|
* 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
|