fix status of lbtt's subtree. Apparently it was messed up during the cvsimport

This commit is contained in:
Alexandre Duret-Lutz 2008-02-23 00:17:42 +01:00
parent 17f76e371f
commit 91df6cab77
77 changed files with 16272 additions and 6019 deletions

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,10 +17,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef __GNUC__
#pragma implementation
#endif /* __GNUC__ */
#include <config.h>
#ifdef HAVE_SSTREAM
#include <sstream>
@ -378,7 +374,7 @@ unsigned long int BitArray::find(const unsigned long int max_count) const
for (i = 0; i < bsize && bits[i] == 0; ++i)
;
if (i == max_count)
if (i == bsize)
return max_count;
unsigned char c = bits[i];

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -20,10 +20,6 @@
#ifndef BITARRAY_H
#define BITARRAY_H
#ifdef __GNUC__
#pragma interface
#endif /* __GNUC__ */
#include <config.h>
#include <cstring>
#include <string>
@ -363,7 +359,10 @@ inline void BitArray::set(const unsigned long int bit_count)
*
* ------------------------------------------------------------------------- */
{
memset(static_cast<void*>(bits), 0xFF, (bit_count + 7) >> 3);
unsigned long int bsize = bit_count >> 3;
memset(static_cast<void*>(bits), 0xFF, bsize);
if ((bit_count & 0x07) != 0)
bits[bsize] |= (1 << (bit_count & 7)) - 1;
}
/* ========================================================================= */
@ -394,7 +393,10 @@ inline void BitArray::clear(const unsigned long int bit_count)
*
* ------------------------------------------------------------------------- */
{
memset(static_cast<void*>(bits), 0, (bit_count + 7) >> 3);
unsigned long int bsize = bit_count >> 3;
memset(static_cast<void*>(bits), 0, bsize);
if ((bit_count & 0x07) != 0)
bits[bsize] &= ~((1 << (bit_count & 7)) - 1);
}
/* ========================================================================= */

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,10 +17,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef __GNUC__
#pragma implementation
#endif /* __GNUC__ */
#include <config.h>
#include <deque>
#include <stack>
@ -96,7 +92,9 @@ BuchiAutomaton::BuchiAutomaton(const BuchiAutomaton& automaton) :
++transition)
connect(state,
static_cast<const BuchiTransition*>(*transition)->targetNode(),
static_cast<const BuchiTransition*>(*transition)->guard());
static_cast<const BuchiTransition*>(*transition)->guard(),
static_cast<const BuchiTransition*>(*transition)
->acceptanceSets());
operator[](state).acceptanceSets().copy(automaton[state].acceptanceSets(),
number_of_acceptance_sets);
@ -133,7 +131,9 @@ BuchiAutomaton& BuchiAutomaton::operator=(const BuchiAutomaton& automaton)
++transition)
connect(state,
static_cast<const BuchiTransition*>(*transition)->targetNode(),
static_cast<const BuchiTransition*>(*transition)->guard());
static_cast<const BuchiTransition*>(*transition)->guard(),
static_cast<const BuchiTransition*>(*transition)
->acceptanceSets());
operator[](state).acceptanceSets().copy
(automaton[state].acceptanceSets(), number_of_acceptance_sets);
@ -194,113 +194,13 @@ BuchiAutomaton::size_type BuchiAutomaton::expand(size_type node_count)
return nodes.size() - 1;
}
/* ========================================================================= */
BuchiAutomaton* BuchiAutomaton::regularize() const
/* ----------------------------------------------------------------------------
*
* Description: Converts a generalized Büchi automaton (i.e., an automaton
* with any number of accepting state sets) into an automaton
* with only one set of accepting states.
*
* Arguments: None.
*
* Returns: A pointer to an equivalent BuchiAutomaton with exactly one
* set of accepting states.
*
* ------------------------------------------------------------------------- */
{
/*
* If `this' automaton already has exactly one set of accepting states,
* return a copy of `this' automaton.
*/
if (number_of_acceptance_sets == 1)
return new BuchiAutomaton(*this);
/*
* Otherwise construct the result using a depth-first search in `this'
* automaton.
*/
typedef pair<size_type, unsigned long int> ExpandedState;
BuchiAutomaton* result_automaton = new BuchiAutomaton(0, 0, 1);
if (empty())
return result_automaton;
stack<ExpandedState, deque<ExpandedState, ALLOC(ExpandedState) > >
states_to_process;
map<ExpandedState, size_type, less<ExpandedState>, ALLOC(size_type) >
state_mapping;
const GraphEdgeContainer* transitions;
size_type result_source_state, result_target_state;
map<ExpandedState, size_type, less<ExpandedState>, ALLOC(size_type) >
::const_iterator check_state;
ExpandedState state = make_pair(initial_state, 0);
states_to_process.push(state);
state_mapping[state] = result_automaton->expand();
while (!states_to_process.empty())
{
state = states_to_process.top();
states_to_process.pop();
result_source_state = state_mapping[state];
transitions = &operator[](state.first).edges();
if (number_of_acceptance_sets == 0
|| operator[](state.first).acceptanceSets().test(state.second))
{
if (state.second == 0)
(*result_automaton)[result_source_state].acceptanceSets().setBit(0);
if (number_of_acceptance_sets > 0)
{
++state.second;
state.second %= number_of_acceptance_sets;
}
}
for (GraphEdgeContainer::const_iterator transition = transitions->begin();
transition != transitions->end();
++transition)
{
state.first = (*transition)->targetNode();
check_state = state_mapping.find(state);
if (check_state == state_mapping.end())
{
result_target_state = result_automaton->expand();
state_mapping[state] = result_target_state;
states_to_process.push(state);
}
else
result_target_state = check_state->second;
result_automaton->connect(result_source_state, result_target_state,
static_cast<const BuchiTransition*>
(*transition)->guard());
}
}
return result_automaton;
}
/* ========================================================================= */
void BuchiAutomaton::read(istream& input_stream)
/* ----------------------------------------------------------------------------
*
* Description: Reads an automaton description (which may represent a
* generalized Büchi automaton) from a stream and stores it
* into the automaton object, converting it to a regular
* Büchi automaton if necessary.
* into the automaton object.
*
* Argument: input_stream -- A reference to an input stream.
*
@ -316,20 +216,63 @@ void BuchiAutomaton::read(istream& input_stream)
try
{
/*
* Read in the number of states in the generalized Büchi automaton.
*/
/* Read the number of states in the generalized Büchi automaton. */
einput_stream >> number_of_states;
/*
* If the automaton is empty, do nothing.
*/
/* If the automaton is empty, do nothing. */
if (number_of_states == 0)
return;
einput_stream >> number_of_acceptance_sets;
/*
* Determine the number and placement of acceptance sets.
* (Acceptance sets are described using strings described by the regular
* expression [0-9]+(s|S|t|T)*, where the [0-9]+ part corresponds to the
* number of the sets, and the (s|S|t|T)* part corresponds to the
* placement of the sets -- s or S for states, t or T for transitions.
* To retain compatibility with lbtt 1.0.x, the acceptance set placement
* defaults to acceptance sets on states if is not given explicitly.)
*/
bool acceptance_sets_on_states = false;
bool acceptance_sets_on_transitions = false;
string tok;
einput_stream >> tok;
string::size_type s_pos = string::npos;
string::size_type t_pos = string::npos;
string::size_type pos = tok.find_first_not_of("0123456789");
if (pos == 0)
throw AutomatonParseException
("invalid specification for acceptance sets");
number_of_acceptance_sets = strtoul(tok.substr(0, pos).c_str(), 0, 10);
for ( ; pos < tok.length(); ++pos)
{
if (tok[pos] == 's' || tok[pos] == 'S')
{
s_pos = pos;
acceptance_sets_on_states = true;
}
else if (tok[pos] == 't' || tok[pos] == 'T')
{
t_pos = pos;
acceptance_sets_on_transitions = true;
}
else
throw AutomatonParseException
("invalid specification for acceptance sets");
}
if (s_pos == string::npos && t_pos == string::npos)
{
acceptance_sets_on_states = true;
acceptance_sets_on_transitions = false;
}
BitArray acc_sets(number_of_acceptance_sets);
/*
* Allocate space for the regular Büchi automaton that will be constructed
@ -345,27 +288,20 @@ void BuchiAutomaton::read(istream& input_stream)
* to the interval [0...(number of states - 1)].
*/
map<long int, size_type, less<long int>, ALLOC(size_type) >
state_number_map;
map<long int, size_type> state_number_map;
pair<long int, size_type> state_mapping(0, 0);
pair<map<long int, size_type, less<long int>, ALLOC(size_type) >
::const_iterator,
bool>
state_finder;
pair<map<long int, size_type>::const_iterator, bool> state_finder;
/*
* Also the acceptance set numbers will be mapped to the interval
* [0...(number of acceptance sets - 1)].
*/
map<long int, unsigned long int, less<long int>, ALLOC(unsigned long int) >
acceptance_set_map;
map<long int, unsigned long int> acceptance_set_map;
pair<long int, unsigned long int> acceptance_set_mapping(0, 0);
pair<map<long int, unsigned long int, less<long int>,
ALLOC(unsigned long int) >::const_iterator,
bool>
pair<map<long int, unsigned long int>::const_iterator, bool>
acceptance_set_finder;
/*
@ -450,36 +386,41 @@ void BuchiAutomaton::read(istream& input_stream)
operator[](current_state).acceptanceSets().clear
(number_of_acceptance_sets);
while (1)
if (acceptance_sets_on_states)
{
einput_stream >> acceptance_set_mapping.first;
if (acceptance_set_mapping.first == -1)
break;
acceptance_set_finder =
acceptance_set_map.insert(acceptance_set_mapping);
if (!acceptance_set_finder.second)
acceptance_set = (acceptance_set_finder.first)->second;
else
while (1)
{
if (acceptance_set_mapping.second >= number_of_acceptance_sets)
throw AutomatonParseException("number of acceptance sets "
"does not match automaton state "
"definitions");
einput_stream >> acceptance_set_mapping.first;
acceptance_set = acceptance_set_mapping.second;
++acceptance_set_mapping.second;
}
if (acceptance_set_mapping.first == -1)
break;
operator[](current_state).acceptanceSets().setBit(acceptance_set);
acceptance_set_finder =
acceptance_set_map.insert(acceptance_set_mapping);
if (!acceptance_set_finder.second)
acceptance_set = (acceptance_set_finder.first)->second;
else
{
if (acceptance_set_mapping.second >= number_of_acceptance_sets)
throw AutomatonParseException("number of acceptance sets "
"does not match automaton state "
"definitions");
acceptance_set = acceptance_set_mapping.second;
++acceptance_set_mapping.second;
}
operator[](current_state).acceptanceSets().setBit(acceptance_set);
}
}
/*
* Process the transitions from the state to other states. Read a
* target state id and add a mapping for it in the translation table if
* necessary. Then, read the propositional formula guarding the
* necessary. If the automaton is allowed to have acceptance sets
* associated with transitions, read an additional list of acceptance
* sets. Finally, read the propositional formula guarding the
* transition and connect the current state to the target using the
* guard formula.
*/
@ -505,6 +446,42 @@ void BuchiAutomaton::read(istream& input_stream)
state_mapping.second++;
}
acc_sets.clear(number_of_acceptance_sets);
/*
* If automata with acceptance sets on transitions are accepted, read
* the acceptance sets associated with the transition.
*/
if (acceptance_sets_on_transitions)
{
while (1)
{
einput_stream >> acceptance_set_mapping.first;
if (acceptance_set_mapping.first == -1)
break;
acceptance_set_finder =
acceptance_set_map.insert(acceptance_set_mapping);
if (!acceptance_set_finder.second)
acceptance_set = (acceptance_set_finder.first)->second;
else
{
if (acceptance_set_mapping.second >= number_of_acceptance_sets)
throw AutomatonParseException("number of acceptance sets "
"does not match automaton state "
"definitions");
acceptance_set = acceptance_set_mapping.second;
++acceptance_set_mapping.second;
}
acc_sets.setBit(acceptance_set);
}
}
try
{
guard = ::Ltl::LtlFormula::read(input_stream);
@ -520,7 +497,7 @@ void BuchiAutomaton::read(istream& input_stream)
throw AutomatonParseException("illegal operators in guard formula");
}
connect(current_state, neighbor_state, guard);
connect(current_state, neighbor_state, guard, acc_sets);
}
processed_states.setBit(current_state);
@ -548,297 +525,6 @@ void BuchiAutomaton::read(istream& input_stream)
}
}
/* ========================================================================= */
BuchiAutomaton* BuchiAutomaton::intersect
(const BuchiAutomaton& a1, const BuchiAutomaton& a2,
map<size_type, StateIdPair, less<size_type>, ALLOC(StateIdPair) >*
intersection_state_mapping)
/* ----------------------------------------------------------------------------
*
* Description: Computes the intersection of two Büchi automata and returns
* a pointer to the intersection of the two automata.
*
* Arguments: a1, a2 -- References to two constant
* Büchi automata.
* intersection_state_mapping -- An (optional) pointer to a
* map which can be used to find
* out the state identifiers of
* the original automata to
* which a particular state in
* the intersection corresponds.
*
* Returns: A newly allocated BuchiAutomaton representing the
* intersection of the two automata.
*
* ------------------------------------------------------------------------- */
{
if (intersection_state_mapping != 0)
intersection_state_mapping->clear();
/*
* If either of the original automata is empty, the intersection is also
* empty.
*/
if (a1.empty() || a2.empty())
return new BuchiAutomaton(0, 0, 0);
BuchiAutomaton* automaton;
/*
* Determine the number of acceptance sets in the intersection.
*/
const bool a1_has_no_acceptance_sets = (a1.number_of_acceptance_sets == 0);
const bool a2_has_no_acceptance_sets = (a2.number_of_acceptance_sets == 0);
unsigned long int number_of_intersection_acceptance_sets;
if (a1_has_no_acceptance_sets && a2_has_no_acceptance_sets)
number_of_intersection_acceptance_sets = 0;
else
number_of_intersection_acceptance_sets = a1.number_of_acceptance_sets
+ a2.number_of_acceptance_sets;
automaton = new BuchiAutomaton(1, 0, number_of_intersection_acceptance_sets);
/*
* A stack for processing pairs of states of the original automata.
*/
stack<const StateIdPair*, deque<const StateIdPair*,
ALLOC(const StateIdPair*) > >
unprocessed_states;
/*
* `state_mapping' maps pairs of states of the original automata to the
* states of the new automaton.
*/
map<StateIdPair, size_type, less<StateIdPair>, ALLOC(size_type) >
state_mapping;
size_type first_free_id = 1; /* First free identifier for a
* new state in the intersection
* automaton.
*/
const StateIdPair* state_pair; /* Pointer to pair of two state
* identifiers of the original
* automata.
*/
size_type intersect_state; /* `Current' state in the
* intersection automaton.
*/
bool intersect_state_valid; /* True if the current state has
* been determined by using the
* mapping.
*/
BitArray* intersect_acceptance_sets; /* Pointers for accessing the */
const BitArray* acceptance_sets; /* acceptance sets of the new
* and the original automata.
*/
const GraphEdgeContainer* transitions1; /* Pointers for accessing the */
const GraphEdgeContainer* transitions2; /* transitions of the two
* original automata.
*/
::Ltl::LtlFormula* guard1; /* Pointers for accessing the */
::Ltl::LtlFormula* guard2; /* guard formulas of the */
::Ltl::LtlFormula* new_guard; /* transitions of the
* automata.
*/
/*
* Insert the initial state into the state mapping.
*/
state_mapping.insert(make_pair(make_pair(a1.initial_state, a2.initial_state),
0));
unprocessed_states.push(&(state_mapping.begin()->first));
/*
* Adjust the acceptance sets of the initial state of the intersection.
*/
intersect_acceptance_sets = &((*automaton)[0].acceptanceSets());
if (!a1_has_no_acceptance_sets)
{
acceptance_sets = &(a1[a1.initial_state].acceptanceSets());
for (unsigned long int accept_set = 0;
accept_set < a1.number_of_acceptance_sets;
accept_set++)
{
if (acceptance_sets->test(accept_set))
intersect_acceptance_sets->setBit(accept_set);
}
}
if (!a2_has_no_acceptance_sets)
{
acceptance_sets = &(a2[a2.initial_state].acceptanceSets());
for (unsigned long int accept_set = 0;
accept_set < a2.number_of_acceptance_sets;
accept_set++)
{
if (acceptance_sets->test(accept_set))
intersect_acceptance_sets->setBit(a1.number_of_acceptance_sets
+ accept_set);
}
}
/*
* Pop pairs of states of the two original automata until all states have
* been processed.
*/
try
{
while (!unprocessed_states.empty())
{
if (::user_break)
throw UserBreakException();
intersect_state_valid = false;
state_pair = unprocessed_states.top();
unprocessed_states.pop();
/*
* Loop through the transitions of the two original automata. If the
* conjunction of the guard formulae of any two transitions is
* satisfiable, insert a new transition into the intersection automaton.
* Create new states in the intersection automaton if necessary.
*/
transitions1 = &a1[state_pair->first].edges();
transitions2 = &a2[state_pair->second].edges();
for (GraphEdgeContainer::const_iterator tr1 = transitions1->begin();
tr1 != transitions1->end();
++tr1)
{
guard1 = &(static_cast<BuchiTransition*>(*tr1)->guard());
for (GraphEdgeContainer::const_iterator tr2 = transitions2->begin();
tr2 != transitions2->end();
++tr2)
{
guard2 = &(static_cast<BuchiTransition*>(*tr2)->guard());
new_guard = &Ltl::And::construct(*guard1, *guard2);
if (new_guard->satisfiable())
{
/*
* Determine the `current' state of the intersection automaton.
*/
if (!intersect_state_valid)
{
intersect_state = state_mapping[*state_pair];
intersect_state_valid = true;
}
/*
* Test whether the state pair pointed to by the two transitions
* is already in the intersection.
*/
pair<map<StateIdPair, size_type, less<StateIdPair>,
ALLOC(size_type) >::iterator, bool>
check_state;
check_state
= state_mapping.insert(make_pair(make_pair((*tr1)->targetNode(),
(*tr2)->targetNode()),
first_free_id));
if (check_state.second) /* insertion occurred? */
{
automaton->expand();
/*
* Determine the acceptance sets to which the new state in the
* intersection automaton belongs.
*/
intersect_acceptance_sets
= &((*automaton)[first_free_id].acceptanceSets());
if (!a1_has_no_acceptance_sets)
{
acceptance_sets = &(a1[check_state.first->first.first].
acceptanceSets());
for (unsigned long int accept_set = 0;
accept_set < a1.number_of_acceptance_sets;
accept_set++)
{
if (acceptance_sets->test(accept_set))
intersect_acceptance_sets->setBit(accept_set);
}
}
if (!a2_has_no_acceptance_sets)
{
acceptance_sets = &(a2[check_state.first->first.second].
acceptanceSets());
for (unsigned long int accept_set = 0;
accept_set < a2.number_of_acceptance_sets;
accept_set++)
{
if (acceptance_sets->test(accept_set))
intersect_acceptance_sets->setBit
(a1.number_of_acceptance_sets + accept_set);
}
}
/*
* Connect the `current' state of the intersection automaton to
* the new state.
*/
automaton->connect(intersect_state, first_free_id, new_guard);
first_free_id++;
unprocessed_states.push(&(check_state.first->first));
}
else
automaton->connect(intersect_state, check_state.first->second,
new_guard);
}
else
::Ltl::LtlFormula::destruct(new_guard);
}
}
}
if (intersection_state_mapping != 0)
{
for (map<StateIdPair, size_type, less<StateIdPair>, ALLOC(size_type) >
::const_iterator mapping = state_mapping.begin();
mapping != state_mapping.end();
++mapping)
intersection_state_mapping->insert(make_pair(mapping->second,
mapping->first));
}
}
catch (...)
{
delete automaton;
throw;
}
return automaton;
}
/* ========================================================================= */
void BuchiAutomaton::print
(ostream& stream, const int indent, const GraphOutputFormat fmt) const
@ -880,7 +566,7 @@ void BuchiAutomaton::print
<< " transitions.\n" + string(indent, ' ')
+ "The automaton has "
<< number_of_acceptance_sets
<< " sets of accepting states.\n" + string(indent, ' ')
<< " acceptance sets.\n" + string(indent, ' ')
+ "The reachable part of the automaton contains\n"
+ string(indent + 4, ' ')
<< reachable_part_statistics.first
@ -941,7 +627,8 @@ void BuchiAutomaton::print
++transition)
{
estream << string(indent + 2, ' ') + 'n' << state;
(*transition)->print(stream, indent, fmt);
static_cast<const BuchiTransition*>(*transition)
->print(stream, indent, fmt, number_of_acceptance_sets);
estream << ";\n";
}
}
@ -964,16 +651,23 @@ void BuchiAutomaton::print
/* ========================================================================= */
void BuchiAutomaton::BuchiTransition::print
(ostream& stream, const int indent, const GraphOutputFormat fmt) const
(ostream& stream, const int indent, const GraphOutputFormat fmt,
const unsigned long int number_of_acceptance_sets) const
/* ----------------------------------------------------------------------------
*
* Description: Writes information about a transition between two states of
* a Büchi automaton.
*
* Arguments: stream -- A reference to an output stream.
* indent -- Number of spaces to leave to the left of output.
* fmt -- Determines the format of output.
*
* Arguments: stream -- A reference to an output
* stream.
* indent -- Number of spaces to leave to
* the left of output.
* fmt -- Determines the format of
* output.
* number_of_acceptance_sets -- Number of acceptance sets in
* the automaton to which the
* transition belongs.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
@ -981,11 +675,9 @@ void BuchiAutomaton::BuchiTransition::print
Exceptional_ostream estream(&stream, ios::failbit | ios::badbit);
if (fmt == NORMAL)
{
estream << string(indent, ' ') + "Transition to state "
<< targetNode()
<< " [ guard: " << *guard_formula << " ]\n";
}
<< " [ acc.: ";
else if (fmt == DOT)
{
string formula(StringUtil::toString(*guard_formula));
@ -1006,9 +698,33 @@ void BuchiAutomaton::BuchiTransition::print
else
estream << formula[i];
}
estream << "\",fontsize=10,fontname=\"Courier-Bold\"]";
estream << "\\n";
}
estream << '{';
bool first_printed = false;
for (unsigned long int accept_set = 0;
accept_set < number_of_acceptance_sets;
++accept_set)
{
if (acceptance_sets[accept_set])
{
if (first_printed)
estream << ", ";
else
first_printed = true;
estream << accept_set;
}
}
estream << '}';
if (fmt == NORMAL)
estream << ", guard: " << *guard_formula << " ]\n";
else if (fmt == DOT)
estream << "\",fontsize=10,fontname=\"Courier-Bold\"]";
estream.flush();
}
@ -1073,7 +789,8 @@ void BuchiAutomaton::BuchiState::print
GraphEdgeContainer::const_iterator edge;
for (edge = edges().begin(); edge != edges().end(); ++edge)
(*edge)->print(stream, indent);
static_cast<const BuchiAutomaton::BuchiTransition*>(*edge)
->print(stream, indent, fmt, number_of_acceptance_sets);
} else
estream << string(indent, ' ') + "No transitions to other states.\n";

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -21,6 +21,7 @@
#define BUCHIAUTOMATON_H
#include <config.h>
#include <cstdlib>
#include <iostream>
#include <map>
#include <string>
@ -38,8 +39,7 @@ namespace Graph
/******************************************************************************
*
* A class for representing Büchi automata with a single set of accepting
* states.
* A class for representing generalized Büchi automata.
*
*****************************************************************************/
@ -139,15 +139,19 @@ public:
void connect /* Connects two states */
(const size_type father, /* of the automaton with */
const size_type child); /* an unguarded
* transition.
* transition with no
* associated acceptance
* sets.
*/
void connect /* Connects two states */
(const size_type father, const size_type child, /* of the automaton with */
::Ltl::LtlFormula& guard); /* a transition guarded */
void connect /* by a propositional */
(const size_type father, const size_type child, /* formula. */
::Ltl::LtlFormula* guard);
::Ltl::LtlFormula& guard, /* a transition guarded */
const BitArray& acc_sets); /* by a propositional */
void connect /* formula. */
(const size_type father, const size_type child,
::Ltl::LtlFormula* guard,
const BitArray& acc_sets);
/* `disconnect' inherited from Graph<GraphEdgeContainer> */
@ -167,12 +171,6 @@ public:
* automaton.
*/
BuchiAutomaton* regularize() const; /* Converts a generalized
* automaton to an
* automaton with one set
* of accepting states.
*/
void read(istream& input_stream); /* Reads the automaton
* from a stream.
*/
@ -181,17 +179,10 @@ public:
(ostream& stream = cout, /* about the automaton */
const int indent = 0, /* to a stream in */
const GraphOutputFormat fmt = NORMAL) const; /* various formats
* (determined by the
* `fmt' argument).
* (determined by the
* `fmt' argument).
*/
static BuchiAutomaton* intersect /* Computes the */
(const BuchiAutomaton& a1, /* intersection of two */
const BuchiAutomaton& a2, /* Büchi automata. */
map<size_type, StateIdPair,
less<size_type>, ALLOC(StateIdPair) >*
intersection_state_mapping = 0);
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
class AutomatonParseException; /* Class for reporting
@ -227,14 +218,12 @@ class BuchiAutomaton::BuchiTransition : public Graph<GraphEdgeContainer>::Edge
public:
BuchiTransition /* Constructor. */
(const size_type target,
::Ltl::LtlFormula* formula);
::Ltl::LtlFormula* formula,
const BitArray& acc_sets,
unsigned long int num_acc_sets);
~BuchiTransition(); /* Destructor. */
private:
public:
/* `targetNode' inherited from Graph<GraphEdgeContainer>::Edge */
bool enabled /* These functions test */
@ -249,14 +238,24 @@ public:
* propositional formula
* guarding the transition.
*/
BitArray& acceptanceSets(); /* Returns the */
const BitArray& acceptanceSets() const; /* acceptance sets
* associated with the
* the transition.
*/
void print /* Writes information */
(ostream& stream, /* about the transition */
const int indent, /* (as a plain graph */
const GraphOutputFormat fmt) const; /* edge) to a stream. */
void print /* Writes information */
(ostream& stream = cout, /* about the transition */
const int indent = 0, /* to a stream in */
const GraphOutputFormat fmt = NORMAL) const; /* various formats
* (determined by the
* `fmt' argument).
*/
(ostream& stream, /* about the transition */
const int indent, /* to a stream in */
const GraphOutputFormat fmt, /* various formats */
const unsigned long int /* (determined by the */
number_of_acceptance_sets) const; /* `fmt' argument). */
private:
BuchiTransition(const BuchiTransition&); /* Prevent copying and */
@ -281,6 +280,11 @@ private:
* formula guarding the
* transition.
*/
BitArray acceptance_sets; /* Acceptance sets
* associated with the
* transition.
*/
};
@ -372,7 +376,8 @@ inline void BuchiAutomaton::connect
*
* Description: Connects two states of a BuchiAutomaton to each other with an
* unguarded transition (actually, a transition with a guard
* that is always true).
* that is always true) with an empty set of acceptance
* conditions.
*
* Arguments: father -- Source state identifier.
* child -- Target state identifier.
@ -381,50 +386,59 @@ inline void BuchiAutomaton::connect
*
* ------------------------------------------------------------------------- */
{
connect(father, child, &(::Ltl::True::construct()));
BitArray acc_sets(number_of_acceptance_sets);
acc_sets.clear(number_of_acceptance_sets);
connect(father, child, &(::Ltl::True::construct()), acc_sets);
}
/* ========================================================================= */
inline void BuchiAutomaton::connect
(const size_type father, const size_type child, ::Ltl::LtlFormula& guard)
(const size_type father, const size_type child, ::Ltl::LtlFormula& guard,
const BitArray& acc_sets)
/* ----------------------------------------------------------------------------
*
* Description: Connects two states of a BuchiAutomaton to each other, using
* a LtlFormula (which is actually a propositional formula) to
* guard the transition between the states.
*
* Arguments: father -- Source state.
* child -- Target state.
* guard -- A reference to an LtlFormula (a propositional
* formula) guarding the transition.
* Arguments: father -- Source state.
* child -- Target state.
* guard -- A reference to an LtlFormula (a propositional
* formula) guarding the transition.
* acc_sets -- A reference to a BitArray giving the
* acceptance sets associated with the transition.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
connect(father, child, guard.clone());
connect(father, child, guard.clone(), acc_sets);
}
/* ========================================================================= */
inline void BuchiAutomaton::connect
(const size_type father, const size_type child, ::Ltl::LtlFormula* guard)
(const size_type father, const size_type child, ::Ltl::LtlFormula* guard,
const BitArray& acc_sets)
/* ----------------------------------------------------------------------------
*
* Description: Connects two states of a BuchiAutomaton to each other, using
* a LtlFormula (which is actually a propositional formula) to
* guard the transition between the states.
*
* Arguments: father -- Source state.
* child -- Target state.
* guard -- A pointer to an LtlFormula (a propositional
* formula) guarding the transition. The transition
* will "own" the guard formula.
* Arguments: father -- Source state.
* child -- Target state.
* guard -- A pointer to an LtlFormula (a propositional
* formula) guarding the transition. The
* transition will "own" the guard formula.
* acc_sets -- A reference to a BitArray giving the acceptance
* sets associated with the transition.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
BuchiTransition* new_buchi_transition = new BuchiTransition(child, guard);
BuchiTransition* new_buchi_transition
= new BuchiTransition(child, guard, acc_sets, number_of_acceptance_sets);
try
{
@ -512,39 +526,28 @@ inline istream& operator>>(istream& stream, BuchiAutomaton& automaton)
/* ========================================================================= */
inline BuchiAutomaton::BuchiTransition::BuchiTransition
(const size_type target, ::Ltl::LtlFormula* formula) :
Edge(target), guard_formula(formula)
(const size_type target, ::Ltl::LtlFormula* formula,
const BitArray& acc_sets, unsigned long int num_acc_sets) :
Edge(target), guard_formula(formula), acceptance_sets(num_acc_sets)
/* ----------------------------------------------------------------------------
*
* Description: Constructor for class BuchiAutomaton::BuchiTransition.
* Initializes a new transition to a BuchiState, guarded by an
* LtlFormula (which is actually a propositional formula).
*
* Arguments: target -- Identifier of the target state of the automaton.
* formula -- A pointer to a propositional formula guarding
* the transition.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
}
/* ========================================================================= */
inline BuchiAutomaton::BuchiTransition::BuchiTransition
(const BuchiTransition& transition) :
Edge(transition), guard_formula(transition.guard_formula->clone())
/* ----------------------------------------------------------------------------
*
* Description: Copy constructor for class BuchiAutomaton::BuchiTransition.
* Creates a copy of a BuchiTransition object.
*
* Arguments: transition -- BuchiTransition to be copied.
* Arguments: target -- Identifier of the target state of the
* automaton.
* formula -- A pointer to a propositional formula guarding
* the transition.
* acc_sets -- A reference to a constant BitArray containing
* the acceptance sets associated with the
* transition.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
acceptance_sets.copy(acc_sets, num_acc_sets);
}
/* ========================================================================= */
@ -688,6 +691,59 @@ inline ::Ltl::LtlFormula& BuchiAutomaton::BuchiTransition::guard() const
return *guard_formula;
}
/* ========================================================================= */
inline BitArray& BuchiAutomaton::BuchiTransition::acceptanceSets()
/* ----------------------------------------------------------------------------
*
* Description: Returns the acceptance sets associated with a
* BuchiTransition.
*
* Arguments: None.
*
* Returns: A reference to the BitArray storing the acceptance sets
* associated with the transition.
*
* ------------------------------------------------------------------------- */
{
return acceptance_sets;
}
/* ========================================================================= */
inline const BitArray& BuchiAutomaton::BuchiTransition::acceptanceSets() const
/* ----------------------------------------------------------------------------
*
* Description: Returns the acceptance sets associated with a
* BuchiTransition.
*
* Arguments: None.
*
* Returns: A constant reference to the BitArray storing the acceptance
* sets associated with the transition.
*
* ------------------------------------------------------------------------- */
{
return acceptance_sets;
}
/* ========================================================================= */
inline void BuchiAutomaton::BuchiTransition::print
(ostream& stream, const int indent, const GraphOutputFormat fmt) const
/* ----------------------------------------------------------------------------
*
* Description: Writes information about a transition (as a plain graph edge
* without any associated information) to a stream.
*
* Arguments: stream -- A reference to an output stream.
* indent -- Number of spaces to leave to the left of output.
* fmt -- Determines the output format of the transition.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
Graph<GraphEdgeContainer>::Edge::print(stream, indent, fmt);
}
/******************************************************************************

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -28,8 +28,7 @@ namespace Graph
*
*****************************************************************************/
map< ::Ltl::LtlFormula*, BuchiProduct::SatisfiabilityMapping,
less< ::Ltl::LtlFormula*>, ALLOC(BuchiProduct::SatisfiabilityMapping) >
map< ::Ltl::LtlFormula*, BuchiProduct::SatisfiabilityMapping>
BuchiProduct::sat_cache;
@ -73,8 +72,7 @@ bool BuchiProduct::synchronizable
guard_1 = swap_guard;
}
map<LtlFormula*, SatisfiabilityMapping, less<LtlFormula*>,
ALLOC(SatisfiabilityMapping) >::iterator
map<LtlFormula*, SatisfiabilityMapping>::iterator
sat_cache_element = sat_cache.find(guard_1);
if (sat_cache_element == sat_cache.end())

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -142,18 +142,16 @@ private:
* automata.
*/
typedef map< ::Ltl::LtlFormula*, bool, /* Type definition for */
less< ::Ltl::LtlFormula*>, /* storing information */
ALLOC(bool) > /* about the */
SatisfiabilityMapping; /* satisfiability of the
typedef map< ::Ltl::LtlFormula*, bool> /* Type definition for */
SatisfiabilityMapping; /* storing information
* about the
* satisfiability of the
* guards of product
* transitions.
*/
static map< ::Ltl::LtlFormula*, /* Result cache for */
SatisfiabilityMapping, /* satisfiability tests. */
less< ::Ltl::LtlFormula*>,
ALLOC(SatisfiabilityMapping) >
SatisfiabilityMapping> /* satisfiability tests. */
sat_cache;
};

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -19,11 +19,6 @@
%{
#include <config.h>
#include <cmath>
#include <climits>
#include <cstdlib>
#include <cstring>
#include <string>
#include "Configuration.h"
#include "Config-parse.h"
@ -34,225 +29,102 @@ extern int config_file_line_number;
%option case-insensitive
%option never-interactive
%option noyywrap
%option nounput
%x ATTR EQ VAL
SQSTR [^\'\n]*
DQSTR ([^\"\\\n]|\\.)*
UQC [^\'\"\\ \t\n]
UQSTR ({UQC}+|\\.)({UQC}*|\\.)*
OKVAL \'{SQSTR}\'|\"{DQSTR}\"|{UQSTR}
%%
[ \t]* { /* Skip whitespace. */ }
"#"[^\n]* { /* Skip comments. */ }
<*>[ \t]* { /* Skip whitespace everywhere. */ }
<*>"#".*$ { /* Skip comments everywhere. */ }
"\n" { /* Skip newlines, but update the line number. */
<INITIAL,ATTR>"\n" { /* Skip newlines, but update the line number. */
config_file_line_number++;
}
"{" { return CFG_LBRACE; }
"}" { return CFG_RBRACE; }
"=" { return CFG_EQUALS; }
algorithm { return CFG_ALGORITHM; }
enabled { return CFG_ENABLED; }
name { return CFG_NAME; }
parameters { return CFG_PARAMETERS; }
path { return CFG_PROGRAMPATH; }
"{" { BEGIN(ATTR); return CFG_LBRACE; }
algorithm|implementation|translator { return CFG_ALGORITHM; }
globaloptions { return CFG_GLOBALOPTIONS; }
comparisoncheck { return CFG_COMPARISONTEST; }
comparisontest { return CFG_COMPARISONTEST; }
consistencycheck { return CFG_CONSISTENCYTEST; }
consistencytest { return CFG_CONSISTENCYTEST; }
interactive { return CFG_INTERACTIVE; }
intersectioncheck { return CFG_INTERSECTIONTEST; }
intersectiontest { return CFG_INTERSECTIONTEST; }
modelcheck { return CFG_MODELCHECK; }
rounds { return CFG_ROUNDS; }
verbosity { return CFG_VERBOSITY; }
statespaceoptions { return CFG_STATESPACEOPTIONS; }
edgeprobability { return CFG_EDGEPROBABILITY; }
propositions { return CFG_PROPOSITIONS; }
size { return CFG_SIZE; }
truthprobability { return CFG_TRUTHPROBABILITY; }
changeinterval { return CFG_CHANGEINTERVAL; }
randomseed { return CFG_RANDOMSEED; }
formulaoptions { return CFG_FORMULAOPTIONS; }
abbreviatedoperators { return CFG_ABBREVIATEDOPERATORS; }
andpriority { return CFG_ANDPRIORITY; }
beforepriority { return CFG_BEFOREPRIORITY; }
defaultoperatorpriority { return CFG_DEFAULTOPERATORPRIORITY; }
equivalencepriority { return CFG_EQUIVALENCEPRIORITY; }
falsepriority { return CFG_FALSEPRIORITY; }
finallypriority { return CFG_FINALLYPRIORITY; }
generatemode { return CFG_GENERATEMODE; }
globallypriority { return CFG_GLOBALLYPRIORITY; }
implicationpriority { return CFG_IMPLICATIONPRIORITY; }
nextpriority { return CFG_NEXTPRIORITY; }
notpriority { return CFG_NOTPRIORITY; }
orpriority { return CFG_ORPRIORITY; }
outputmode { return CFG_OUTPUTMODE; }
propositionpriority { return CFG_PROPOSITIONPRIORITY; }
releasepriority { return CFG_RELEASEPRIORITY; }
strongreleasepriority { return CFG_STRONGRELEASEPRIORITY; }
truepriority { return CFG_TRUEPRIORITY; }
untilpriority { return CFG_UNTILPRIORITY; }
weakuntilpriority { return CFG_WEAKUNTILPRIORITY; }
xorpriority { return CFG_XORPRIORITY; }
true|yes {
yylval.truth_value = true;
return CFG_TRUTH_VALUE;
[^ \t\n]+ { return CFG_UNKNOWN; }
<ATTR>enabled { BEGIN(EQ); return CFG_ENABLED; }
<ATTR>name { BEGIN(EQ); return CFG_NAME; }
<ATTR>parameters { BEGIN(EQ); return CFG_PARAMETERS; }
<ATTR>path { BEGIN(EQ); return CFG_PROGRAMPATH; }
<ATTR>comparisoncheck { BEGIN(EQ); return CFG_COMPARISONTEST; }
<ATTR>comparisontest { BEGIN(EQ); return CFG_COMPARISONTEST; }
<ATTR>consistencycheck { BEGIN(EQ); return CFG_CONSISTENCYTEST; }
<ATTR>consistencytest { BEGIN(EQ); return CFG_CONSISTENCYTEST; }
<ATTR>interactive { BEGIN(EQ); return CFG_INTERACTIVE; }
<ATTR>intersectioncheck { BEGIN(EQ); return CFG_INTERSECTIONTEST; }
<ATTR>intersectiontest { BEGIN(EQ); return CFG_INTERSECTIONTEST; }
<ATTR>modelcheck { BEGIN(EQ); return CFG_MODELCHECK; }
<ATTR>rounds { BEGIN(EQ); return CFG_ROUNDS; }
<ATTR>translatortimeout { BEGIN(EQ); return CFG_TRANSLATORTIMEOUT; }
<ATTR>verbosity { BEGIN(EQ); return CFG_VERBOSITY; }
<ATTR>edgeprobability { BEGIN(EQ); return CFG_EDGEPROBABILITY; }
<ATTR>propositions { BEGIN(EQ); return CFG_PROPOSITIONS; }
<ATTR>size { BEGIN(EQ); return CFG_SIZE; }
<ATTR>truthprobability { BEGIN(EQ); return CFG_TRUTHPROBABILITY; }
<ATTR>changeinterval { BEGIN(EQ); return CFG_CHANGEINTERVAL; }
<ATTR>randomseed { BEGIN(EQ); return CFG_RANDOMSEED; }
<ATTR>abbreviatedoperators { BEGIN(EQ); return CFG_ABBREVIATEDOPERATORS; }
<ATTR>andpriority { BEGIN(EQ); return CFG_ANDPRIORITY; }
<ATTR>beforepriority { BEGIN(EQ); return CFG_BEFOREPRIORITY; }
<ATTR>defaultoperatorpriority {
BEGIN(EQ); return CFG_DEFAULTOPERATORPRIORITY;
}
<ATTR>equivalencepriority { BEGIN(EQ); return CFG_EQUIVALENCEPRIORITY; }
<ATTR>falsepriority { BEGIN(EQ); return CFG_FALSEPRIORITY; }
<ATTR>finallypriority { BEGIN(EQ); return CFG_FINALLYPRIORITY; }
<ATTR>generatemode { BEGIN(EQ); return CFG_GENERATEMODE; }
<ATTR>globallypriority { BEGIN(EQ); return CFG_GLOBALLYPRIORITY; }
<ATTR>implicationpriority { BEGIN(EQ); return CFG_IMPLICATIONPRIORITY; }
<ATTR>nextpriority { BEGIN(EQ); return CFG_NEXTPRIORITY; }
<ATTR>notpriority { BEGIN(EQ); return CFG_NOTPRIORITY; }
<ATTR>orpriority { BEGIN(EQ); return CFG_ORPRIORITY; }
<ATTR>outputmode { BEGIN(EQ); return CFG_OUTPUTMODE; }
<ATTR>propositionpriority { BEGIN(EQ); return CFG_PROPOSITIONPRIORITY; }
<ATTR>releasepriority { BEGIN(EQ); return CFG_RELEASEPRIORITY; }
<ATTR>strongreleasepriority { BEGIN(EQ); return CFG_STRONGRELEASEPRIORITY; }
<ATTR>truepriority { BEGIN(EQ); return CFG_TRUEPRIORITY; }
<ATTR>untilpriority { BEGIN(EQ); return CFG_UNTILPRIORITY; }
<ATTR>weakuntilpriority { BEGIN(EQ); return CFG_WEAKUNTILPRIORITY; }
<ATTR>xorpriority { BEGIN(EQ); return CFG_XORPRIORITY; }
<ATTR>"}" { BEGIN(INITIAL); return CFG_RBRACE; }
<ATTR>"="?[^= \t\n]* { return CFG_UNKNOWN; }
<EQ>"=" { BEGIN(VAL); return CFG_EQUALS; }
<EQ>. { return CFG_UNKNOWN; }
<VAL>\\|{OKVAL}+(\\)? {
yylval.value = yytext;
BEGIN(ATTR);
return CFG_VALUE;
}
false|no {
yylval.truth_value = false;
return CFG_TRUTH_VALUE;
}
always {
yylval.interactivity_value =
Configuration::ALWAYS;
return CFG_INTERACTIVITY_VALUE;
}
never {
yylval.interactivity_value =
Configuration::NEVER;
return CFG_INTERACTIVITY_VALUE;
}
onerror {
yylval.interactivity_value =
Configuration::ONERROR;
return CFG_INTERACTIVITY_VALUE;
}
normal {
yylval.formula_mode_value =
Configuration::NORMAL;
return CFG_FORMULA_MODE_VALUE;
}
nnf {
yylval.formula_mode_value = Configuration::NNF;
return CFG_FORMULA_MODE_VALUE;
}
local {
yylval.product_type_value = Configuration::LOCAL;
return CFG_PRODUCT_TYPE_VALUE;
}
global {
yylval.product_type_value =
Configuration::GLOBAL;
return CFG_PRODUCT_TYPE_VALUE;
}
randomgraph {
yylval.statespace_mode_value
= Configuration::RANDOMGRAPH;
return CFG_STATESPACE_MODE_VALUE;
}
randomconnectedgraph {
yylval.statespace_mode_value
= Configuration::RANDOMCONNECTEDGRAPH;
return CFG_STATESPACE_MODE_VALUE;
}
randompath {
yylval.statespace_mode_value
= Configuration::RANDOMPATH;
return CFG_STATESPACE_MODE_VALUE;
}
enumeratedpath {
yylval.statespace_mode_value
= Configuration::ENUMERATEDPATH;
return CFG_STATESPACE_MODE_VALUE;
}
"-"?[0-9]+"...""-"?[0-9]+ {
char* dot_ptr;
yylval.integer_interval.min
= strtol(yytext, &dot_ptr, 10);
if (yylval.integer_interval.min == LONG_MIN
|| yylval.integer_interval.min == LONG_MAX)
throw Configuration::ConfigurationException
(config_file_line_number,
"integer out of range");
dot_ptr += 3;
yylval.integer_interval.max
= strtol(dot_ptr, 0, 10);
if (yylval.integer_interval.max == LONG_MIN
|| yylval.integer_interval.max == LONG_MAX)
throw Configuration::ConfigurationException
(config_file_line_number,
"integer out of range");
return CFG_INTEGER_INTERVAL;
}
"-"?[0-9]+ {
yylval.integer = strtol(yytext, 0, 10);
if (yylval.integer == LONG_MIN
|| yylval.integer == LONG_MAX)
throw Configuration::ConfigurationException
(config_file_line_number,
"integer out of range");
return CFG_INTEGER;
}
"-"?[0-9]*"."[0-9]+ {
yylval.real = strtod(yytext, 0);
if (yylval.real == HUGE_VAL
|| yylval.real == -HUGE_VAL)
throw Configuration::ConfigurationException
(config_file_line_number,
"real number out of range");
return CFG_REAL;
}
\"([^\n\"\\]*(\\[^\n])?)*\" {
unsigned long int len = strlen(yytext);
bool escape = false;
yylval.str = new string;
for (unsigned long int i = 1; i < len - 1; i++)
{
if (!escape && yytext[i] == '\\')
escape = true;
else
{
escape = false;
(*yylval.str) += yytext[i];
}
}
return CFG_STRING_CONSTANT;
}
. {
return CFG_UNKNOWN;
<VAL>{OKVAL}*(\'{SQSTR}|\"{DQSTR})(\\)? {
throw Configuration::ConfigurationException
(config_file_line_number,
"unmatched quotes");
}
<EQ,VAL>"\n" { return CFG_UNKNOWN; }
%%
/* ========================================================================= */
int getCharacter()
/* ----------------------------------------------------------------------------
*
* Description: Reads the next character from the lexer input stream.
*
* Arguments: None.
*
* Returns: The next character in the lexer input stream or EOF if there
* are no more characters to read.
*
* ------------------------------------------------------------------------- */
{
return yyinput();
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -21,6 +21,7 @@
#define CONFIGURATION_H
#include <config.h>
#include <cstdio>
#include <iostream>
#include <map>
#include <set>
@ -35,8 +36,6 @@
using namespace std;
/******************************************************************************
*
* A class for storing program configuration information.
@ -63,21 +62,29 @@ public:
struct AlgorithmInformation; /* See below. */
string algorithmString /* Formats the the id */
(vector<AlgorithmInformation, /* of an algorithm and */
ALLOC(AlgorithmInformation) >::size_type/* the name of the */
algorithm_id) const; /* algorithm into a
(vector<AlgorithmInformation>::size_type /* of an algorithm and */
algorithm_id) const; /* the name of the
* algorithm into a
* string.
*/
bool isInternalAlgorithm(unsigned long int id) /* Tests whether a given */
const; /* algorithm identifier
* refers to lbtt's
* internal model
* checking algorithm.
*/
static void showCommandLineHelp /* Prints the list of */
(const char* program_name); /* command line options. */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
enum InteractionMode {NEVER, ALWAYS, ONERROR}; /* Enumeration constants
* affecting the behaviour
* of the program as
* regards user control.
enum InteractionMode {NEVER, ALWAYS, ONERROR, /* Enumeration constants */
ONBREAK}; /* affecting the
* behavior of the
* program as regards
* user control.
*/
enum FormulaMode {NORMAL, NNF}; /* Enumeration constants
@ -109,19 +116,23 @@ public:
* parameters).
*/
{
string* name; /* Name of the algorithm.
string name; /* Name of the algorithm.
*/
string* path_to_program; /* Path to the executable
char** parameters; /* Command-line parameters
* required for running
* the algorithm.
*/
string* extra_parameters; /* Additional command-line
* parameters required for
* running the executable.
* the executable. See
* the documentation for
* the registerAlgorithm
* function (in
* Configuration.cc) for
* more information.
*/
vector<string>::size_type num_parameters; /* Number of command-line
* parameters.
*/
bool enabled; /* Determines whether the
* algorithm is enabled
* (whether it will be used
@ -169,6 +180,12 @@ public:
* commands.
*/
bool handle_breaks; /* If true, pause testing
* also on interrupt
* signals instead of
* simply aborting.
*/
unsigned long int number_of_rounds; /* Number of test rounds.
*/
@ -278,6 +295,10 @@ public:
* formula generation
* algorithms.
*/
unsigned int translator_timeout; /* Timeout (in seconds) for
* translators.
*/
};
struct FormulaConfiguration /* A structure for storing
@ -290,11 +311,12 @@ public:
* LTL formula symbols.
*/
map<int, int, less<int>, ALLOC(int) > /* Priorities for LTL */
symbol_priority; /* formula symbols. */
map<int, int> symbol_priority; /* Priorities for LTL
* formula symbols.
*/
map<int, double, less<int>, ALLOC(double) > /* Expected numbers of */
symbol_distribution; /* occurrence for the
map<int, double> symbol_distribution; /* Expected numbers of
* occurrence for the
* different formula
* operators.
*/
@ -354,12 +376,18 @@ public:
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
vector<AlgorithmInformation, /* A vector containing */
ALLOC(AlgorithmInformation) > algorithms; /* information about the
vector<AlgorithmInformation> algorithms; /* A vector containing
* information about the
* algorithms used in
* the tests.
*/
map<string, unsigned long int> algorithm_names; /* Mapping between
* algorithm names and
* their numeric
* identifiers.
*/
GlobalConfiguration global_options; /* General configuration
* information.
*/
@ -376,15 +404,6 @@ public:
* algorithms.
*/
typedef pair<int, int> IntPair;
set<IntPair, less<IntPair>, ALLOC(IntPair) > /* Configuration options */
locked_options; /* the values of which
* should not be
* initialized from the
* configuration file.
*/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
class ConfigurationException : public Exception /* A class for reporting
@ -419,6 +438,9 @@ public:
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
private:
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
struct IntegerRange /* Data structure for
* representing integer-
* valued ranges of certain
@ -426,11 +448,11 @@ public:
* options.
*/
{
long int min; /* Lower bound. */
unsigned long int min; /* Lower bound. */
long int max; /* Upper bound. */
unsigned long int max; /* Upper bound. */
char* error_message; /* Error message to be
const char* error_message; /* Error message to be
* displayed if the value
* is not within the
* specified range.
@ -439,31 +461,30 @@ public:
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*
* Ranges for certain integer-valued configuration options.
*/
/* Ranges for certain integer-valued configuration options. */
static const struct IntegerRange
VERBOSITY_RANGE, ROUND_COUNT_RANGE, GENERATION_RANGE, PRIORITY_RANGE,
PROPOSITION_COUNT_RANGE, FORMULA_SIZE_RANGE, FORMULA_MAX_SIZE_RANGE,
STATESPACE_SIZE_RANGE, STATESPACE_MAX_SIZE_RANGE;
DEFAULT_RANGE, VERBOSITY_RANGE,
ROUND_COUNT_RANGE, RANDOM_SEED_RANGE,
ATOMIC_PRIORITY_RANGE, OPERATOR_PRIORITY_RANGE;
private:
enum CommandLineOptionType /* Command line options. */
{OPT_COMPARISONTEST = 10000, OPT_CONFIGFILE,
/* Command line options. */
enum CommandLineOptionType
{OPT_HELP = 'h', OPT_VERSION = 'V',
OPT_COMPARISONTEST = 10000, OPT_CONFIGFILE,
OPT_CONSISTENCYTEST, OPT_DISABLE, OPT_ENABLE,
OPT_FORMULACHANGEINTERVAL, OPT_FORMULAFILE,
OPT_FORMULARANDOMSEED, OPT_HELP = 'h',
OPT_GLOBALPRODUCT = 20000, OPT_INTERACTIVE,
OPT_FORMULACHANGEINTERVAL,
OPT_FORMULAFILE, OPT_FORMULARANDOMSEED,
OPT_GLOBALPRODUCT, OPT_INTERACTIVE,
OPT_INTERSECTIONTEST, OPT_LOGFILE,
OPT_MODELCHECK, OPT_NOCOMPARISONTEST,
OPT_NOCONSISTENCYTEST, OPT_NOINTERSECTIONTEST,
OPT_NOPAUSE, OPT_PAUSE, OPT_PAUSEONERROR,
OPT_PROFILE, OPT_QUIET, OPT_ROUNDS,
OPT_SHOWCONFIG, OPT_SHOWOPERATORDISTRIBUTION,
OPT_SKIP, OPT_STATESPACECHANGEINTERVAL,
OPT_STATESPACERANDOMSEED, OPT_VERBOSITY,
OPT_VERSION,
OPT_MODELCHECK, OPT_PROFILE, OPT_QUIET,
OPT_ROUNDS, OPT_SHOWCONFIG,
OPT_SHOWOPERATORDISTRIBUTION, OPT_SKIP,
OPT_STATESPACECHANGEINTERVAL,
OPT_STATESPACERANDOMSEED,
OPT_TRANSLATORTIMEOUT, OPT_VERBOSITY,
OPT_LOCALPRODUCT,
@ -476,7 +497,6 @@ private:
OPT_FORMULAPROPOSITIONS, OPT_FORMULASIZE,
OPT_GENERATENNF, OPT_GLOBALLYPRIORITY,
OPT_IMPLICATIONPRIORITY, OPT_NEXTPRIORITY,
OPT_NOABBREVIATEDOPERATORS,
OPT_NOGENERATENNF, OPT_NOOUTPUTNNF,
OPT_NOTPRIORITY, OPT_ORPRIORITY,
OPT_OUTPUTNNF, OPT_PROPOSITIONPRIORITY,
@ -492,17 +512,18 @@ private:
OPT_STATESPACEPROPOSITIONS,
OPT_STATESPACESIZE, OPT_TRUTHPROBABILITY};
typedef map<pair<int, int>, double, /* Type definitions for */
less<pair<int, int> >, /* the result cache used */
ALLOC(double) > /* for computing the */
ProbabilityMapElement; /* probability */
typedef map<int, ProbabilityMapElement, /* distribution of LTL */
less<int>, /* formula operators. */
ALLOC(ProbabilityMapElement) >
ProbabilityMap;
typedef map<pair<int, int>, double> /* Type definitions for */
ProbabilityMapElement; /* the result cache used */
/* for computing the */
typedef map<int, ProbabilityMapElement> /* probability */
ProbabilityMap; /* distribution of LTL
* formula operators.
*/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
friend int yyparse();
Configuration(const Configuration& cfg); /* Prevent copying and */
Configuration& operator= /* assignment of */
(const Configuration& cfg); /* Configuration
@ -514,10 +535,59 @@ private:
* to default values.
*/
long int parseCommandLineInteger /* Converts an integer */
(const string& option, const string& value) /* to a string with */
const; /* some additional
* validity checks.
void registerAlgorithm /* Adds a new algorithm */
(const string& name, const string& path, /* to the configuration. */
const string& parameters, bool enabled,
const int block_begin_line);
template<typename T> /* Reads an integer, */
void readInteger /* checks that it is */
(T& target, const string& value, /* within given bounds */
const IntegerRange& range = DEFAULT_RANGE); /* and stores it into
* an unsigned integer
* type variable.
*/
void readProbability /* Reads a probability */
(double& target, const string& value); /* and stores it into
* a given variable of
* type double.
*/
void readSize(int valtype, const string& value); /* Initializes formula or
* state space size
* ranges from a given
* string.
*/
void readTruthValue /* Interprets a symbolic */
(bool& target, const string& value); /* truth value. */
void readInteractivity(const string& value); /* Interprets a symbolic
* interactivity mode.
*/
void readProductType(const string& value); /* Interprets a symbolic
* model checking mode.
*/
void readFormulaMode /* Interprets a symbolic */
(FormulaMode& target, const string& mode); /* formula mode.
*/
void readStateSpaceMode(const string& mode); /* Initializes
* `global_options.
* statespace_generation
* _mode' from a
* symbolic mode
* identifier.
*/
void readTranslatorTimeout(const string& value); /* Initializes
* `global_options.
* translator_timeout'
* from a symbolic time
* specification.
*/
double operatorProbability /* Computes the */
@ -532,6 +602,97 @@ private:
/******************************************************************************
*
* Declarations for functions and variables provided by the parser.
*
*****************************************************************************/
extern int config_file_line_number; /* Number of the current
* line in the
* configuration file.
*/
extern int parseConfiguration /* Parser interface. */
(FILE*, Configuration&);
/******************************************************************************
*
* Inline function definitions for class Configuration.
*
*****************************************************************************/
/* ========================================================================= */
inline bool Configuration::isInternalAlgorithm(unsigned long int id) const
/* ----------------------------------------------------------------------------
*
* Description: Tests whether a given algorithm identifier refers to lbtt's
* internal model checking algorithm.
*
* Argument: id -- Identifier to test.
*
* Returns: True if `id' is the identifier of lbtt's internal model
* checking algorithm.
*
* ------------------------------------------------------------------------- */
{
return ((global_options.statespace_generation_mode & Configuration::PATH)
&& id == algorithms.size() - 1);
}
/******************************************************************************
*
* Template function definitions for class Configuration.
*
*****************************************************************************/
/* ========================================================================= */
template<typename T>
void Configuration::readInteger
(T& target, const string& value, const IntegerRange& range)
/* ----------------------------------------------------------------------------
*
* Description: Reads an integer and stores it into `target'.
*
* Arguments: target -- A reference to an unsigned integer type variable
* for storing the result.
* value -- The integer as a string.
* range -- A reference to a constant IntegerRange object
* giving the bounds for the value.
*
* Returns: Nothing; the result is stored into `target'. The function
* throws a ConfigurationException if `value' is not a valid
* integer within the bounds specified by `range'.
*
* ------------------------------------------------------------------------- */
{
string error;
unsigned long int val;
try
{
val = ::StringUtil::parseNumber(value);
}
catch (const ::StringUtil::NotANumberException&)
{
error = "`" + value + "' is not a valid nonnegative integer";
}
if (error.empty() && (val < range.min || val > range.max))
error = range.error_message;
if (!error.empty())
throw ConfigurationException(config_file_line_number, error);
target = val;
}
/******************************************************************************
*
* Inline function definitions for class Configuration::ConfigurationException.

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -32,10 +32,10 @@
namespace DispUtil
{
stack<StreamFormatting, /* Stack for storing the */
deque<StreamFormatting, /* previous states of an */
ALLOC(StreamFormatting) > > /* output stream. */
stream_formatting_stack;
stack<StreamFormatting, deque<StreamFormatting> > /* Stack for storing the */
stream_formatting_stack; /* previous states of an
* output stream.
*/
/* ========================================================================= */
void changeStreamFormatting

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -20,10 +20,6 @@
#ifndef DISPUTIL_H
#define DISPUTIL_H
#ifdef __GNUC__
#pragma interface
#endif /* __GNUC__ */
#include <config.h>
#include <iostream>
#include <string>
@ -62,6 +58,16 @@ void printTextBlock /* Writes an indented */
* a stream.
*/
bool printText /* "Verbosity-aware" */
(const char* text, /* functions for writing */
const int verbosity_threshold, /* text to standard */
const int indent); /* output. */
bool printText
(const string& text,
const int verbosity_threshold,
const int indent);
/******************************************************************************
@ -82,16 +88,6 @@ struct StreamFormatting
* e.g. the justification
* of output.
*/
bool printText /* "Verbosity-aware" */
(const char* text, /* functions for writing */
const int verbosity_threshold, /* text to standard */
const int indent); /* output. */
bool printText
(const string& text,
const int verbosity_threshold,
const int indent);
};

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -23,6 +23,7 @@
#include <config.h>
#include <string>
#include <exception>
#include <istream>
#include <iostream>
using namespace std;
@ -299,6 +300,16 @@ public:
template<class T> /* Operator for reading */
Exceptional_istream &operator>>(T &t); /* from the stream. */
Exceptional_istream& get(istream::char_type& C); /* Reads a character from
* the stream.
*/
Exceptional_istream& read /* Reads a given number */
(istream::char_type* buffer, streamsize count); /* of characters from
* the stream into a
* buffer.
*/
operator istream&(); /* Casts the exception-
* aware input stream into
* a regular input stream.
@ -992,6 +1003,47 @@ inline Exceptional_istream::~Exceptional_istream()
{
}
/* ========================================================================= */
inline Exceptional_istream& Exceptional_istream::get(istream::char_type& c)
/* ----------------------------------------------------------------------------
*
* Description: Reads a character from the input stream.
*
* Argument: c -- A reference to a character to extract.
*
* Returns: A reference to the stream.
*
* ------------------------------------------------------------------------- */
{
stream->get(c);
if (stream->rdstate() & exception_mask)
throw IOException("error reading from stream");
return *this;
}
/* ========================================================================= */
inline Exceptional_istream& Exceptional_istream::read
(istream::char_type* buffer, streamsize count)
/* ----------------------------------------------------------------------------
*
* Description: Reads a given number of characters from the stream into a
* buffer.
*
* Arguments: buffer -- A pointer to the buffer.
* count -- Number of characters to read.
*
* Returns: A reference to the stream.
*
* ------------------------------------------------------------------------- */
{
stream->read(buffer, count);
if (stream->rdstate() & exception_mask)
throw IOException("error reading from stream");
return *this;
}
/* ========================================================================= */
inline Exceptional_istream::operator istream&()
/* ----------------------------------------------------------------------------

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -18,12 +18,11 @@
*/
#include <config.h>
#include <csignal>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif /* HAVE_FCNTL_H */
@ -64,25 +63,30 @@ ExternalTranslator::~ExternalTranslator()
}
/* ========================================================================= */
ExternalTranslator::TempFileObject&
ExternalTranslator::registerTempFileObject
(const string& filename, TempFileObject::Type type)
const char* ExternalTranslator::registerTempFileObject
(const string& filename, const TempFsysName::NameType type,
const bool literal)
/* ----------------------------------------------------------------------------
*
* Description: Registers a temporary file or directory such that it will be
* automatically deleted when the ExternalTranslator object is
* destroyed.
*
* Arguments: filename -- Name of the temporary file or directory.
* Arguments: filename -- Name of the temporary file or directory. If
* empty, a new name will be created.
* type -- Type of the object (TempFileObject::FILE or
* TempFileObject::DIRECTORY).
* literal -- Tells whether the file name should be
* interpreted literally.
*
* Returns: A reference to the file object.
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
temporary_file_objects.push(new TempFileObject(filename, type));
return *temporary_file_objects.top();
TempFsysName* name = new TempFsysName;
name->allocate(filename.c_str(), type, literal);
temporary_file_objects.push(name);
return name->get();
}
/* ========================================================================= */
@ -101,21 +105,19 @@ void ExternalTranslator::translate
*
* ------------------------------------------------------------------------- */
{
TempFileObject& external_program_input_file = registerTempFileObject();
const char* external_program_input_file
= registerTempFileObject("lbtt-translate");
TempFileObject& external_program_output_file = registerTempFileObject();
const char* external_program_output_file
= registerTempFileObject("lbtt-translate");
string translated_formula;
translateFormula(formula, translated_formula);
std::cout << translated_formula << std::endl;
ofstream input_file;
input_file.open(external_program_input_file.getName().c_str(),
ios::out | ios::trunc);
input_file.open(external_program_input_file, ios::out | ios::trunc);
if (!input_file.good())
throw FileCreationException(string("`")
+ external_program_input_file.getName()
throw FileCreationException(string("`") + external_program_input_file
+ "'");
Exceptional_ostream einput_file(&input_file, ios::failbit | ios::badbit);
@ -125,106 +127,11 @@ void ExternalTranslator::translate
input_file.close();
string command_line = string(command_line_arguments[2])
+ commandLine(external_program_input_file.getName(),
external_program_output_file.getName());
+ commandLine(external_program_input_file,
external_program_output_file);
int exitcode = system(command_line.c_str());
/*
* system() blocks SIGINT and SIGQUIT. If the child was killed
* by such a signal, forward the signal to the current process.
*/
if (WIFSIGNALED(exitcode) &&
(WTERMSIG(exitcode) == SIGINT || WTERMSIG(exitcode) == SIGQUIT))
raise(WTERMSIG(exitcode));
if (!execSuccess(exitcode))
if (!execSuccess(system(command_line.c_str())))
throw ExecFailedException(command_line_arguments[2]);
parseAutomaton(external_program_output_file.getName(), filename);
}
/******************************************************************************
*
* Function definitions for class ExternalTranslator::TempFileObject.
*
*****************************************************************************/
/* ========================================================================= */
ExternalTranslator::TempFileObject::TempFileObject
(const string& filename, Type t)
/* ----------------------------------------------------------------------------
*
* Description: Constructor for class TempFileObject. Creates a temporary
* file or a directory and tests whether it can really be
* written to (if not, a FileCreationException is thrown).
*
* Arguments: filename -- Name of the temporary file or directory.
* If the filename is an empty string, the
* filename is obtained by a call to tmpnam(3).
* t -- Type of the object (TempFileObject::FILE or
* TempFileObject::DIRECTORY).
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
if (filename.empty())
{
char tempname[L_tmpnam + 1];
if (tmpnam(tempname) == 0)
throw FileCreationException("a temporary file");
name = tempname;
}
else
name = filename;
if (t == FILE)
{
ofstream tempfile;
tempfile.open(name.c_str(), ios::out | ios::trunc);
if (!tempfile.good())
throw FileCreationException("a temporary file");
tempfile.close();
}
else
{
if (mkdir(name.c_str(), 0700) != 0)
throw FileCreationException("a temporary directory");
}
type = t;
}
/* ========================================================================= */
ExternalTranslator::TempFileObject::~TempFileObject()
/* ----------------------------------------------------------------------------
*
* Description: Destructor for class TempFileObject. Deletes the file or
* the directory associated with the object (displays a warning
* if this fails).
*
* Arguments: None.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
if (remove(name.c_str()) != 0)
{
string msg("error removing temporary ");
if (type == TempFileObject::FILE)
msg += "file";
else
msg += "directory";
msg += " `" + name + "'";
printWarning(msg);
}
parseAutomaton(external_program_output_file, filename);
}

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,10 +17,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef __GNUC__
#pragma implementation
#endif /* __GNUC__ */
#include <config.h>
#include "FormulaRandomizer.h"
#include "Random.h"
@ -96,7 +92,7 @@ LtlFormula* FormulaRandomizer::recGenerate(unsigned long int target_size)
*
* ------------------------------------------------------------------------- */
{
vector<IntegerPair, ALLOC(IntegerPair) >::const_iterator symbol_priority;
vector<IntegerPair>::const_iterator symbol_priority;
LtlFormula* formula;
long int x;

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -21,6 +21,7 @@
#define FORMULARANDOMIZER_H
#include <config.h>
#include <map>
#include <vector>
#include <utility>
#include "LbttAlloc.h"
@ -86,16 +87,16 @@ public:
* `reset'.
*/
const map<unsigned long int, unsigned long int, /* Get the numbers of */
less<unsigned long int>, /* different atomic */
ALLOC(unsigned long int) >& /* propositions */
propositionStatistics() const; /* generated since the
const map<unsigned long int, unsigned long int>& /* Get the numbers of */
propositionStatistics() const; /* different atomic
* propositions
* generated since the
* last call to `reset'.
*/
const map<int, unsigned long int, less<int>, /* Get the numbers of */
ALLOC(unsigned long int) >& /* different symbols */
symbolStatistics() const; /* generated since the
const map<int, unsigned long int>& /* Get the numbers of */
symbolStatistics() const; /* different symbols
* generated since the
* last call to `reset'.
*/
@ -123,21 +124,20 @@ private:
typedef pair<int, int> IntegerPair;
vector<IntegerPair, ALLOC(IntegerPair) > /* Operand symbols and */
vector<IntegerPair> /* Operand symbols and */
propositional_symbol_priorities; /* their priorities in
* random formulae.
*/
vector<IntegerPair, ALLOC(IntegerPair) > /* Operators and their */
short_formula_operators; /* priorities in random
* formulae of size
* two.
vector<IntegerPair> short_formula_operators; /* Operators and their
* priorities in random
* formulae of size two.
*/
vector<IntegerPair, ALLOC(IntegerPair) > /* Operators and their */
long_formula_operators; /* priorities in random
* formulae of size
* greater than two.
vector<IntegerPair> long_formula_operators; /* Operators and their
* priorities in random
* formulae of size greater
* than two.
*/
unsigned long int number_of_generated_formulas; /* Number of generated
@ -145,14 +145,15 @@ private:
* last call to `reset'.
*/
map<unsigned long int, unsigned long int, /* Number of different */
less<unsigned long int>, /* atomic propositions */
ALLOC(unsigned long int) > /* generated since the */
proposition_statistics; /* last call to `reset' */
map<unsigned long int, unsigned long int> /* Number of different */
proposition_statistics; /* atomic propositions
* generated since the
* last call to `reset'
*/
map<int, unsigned long int, less<int>, /* Number of different */
ALLOC(unsigned long int) > /* formula symbols */
symbol_statistics; /* generated since the
map<int, unsigned long int> symbol_statistics; /* Number of different
* formula symbols
* generated since the
* last call to `reset'.
*/
};
@ -288,8 +289,7 @@ inline unsigned long int FormulaRandomizer::numberOfFormulas() const
}
/* ========================================================================= */
inline const map<unsigned long int, unsigned long int, less<unsigned long int>,
ALLOC(unsigned long int) >&
inline const map<unsigned long int, unsigned long int>&
FormulaRandomizer::propositionStatistics() const
/* ----------------------------------------------------------------------------
*
@ -307,7 +307,7 @@ FormulaRandomizer::propositionStatistics() const
}
/* ========================================================================= */
inline const map<int, unsigned long int, less<int>, ALLOC(unsigned long int) >&
inline const map<int, unsigned long int>&
FormulaRandomizer::symbolStatistics() const
/* ----------------------------------------------------------------------------
*

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -21,13 +21,11 @@
#define FORMULAWRITER_H
#include "Exception.h"
#include "LtlFormula.h"
namespace Ltl
{
class LtlFormula;
class Atom;
/******************************************************************************
*
* A function template class for writing the formula to a stream.

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -186,25 +186,38 @@ public:
* graph nodes.
*/
class PathElement; /* A class for representing
* (node, edge) pairs
*/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
protected:
vector<Node*, ALLOC(Node*) > nodes; /* Nodes of the graph.
vector<Node*> nodes; /* Nodes of the graph.
* Derived classes can
* access this vector
* directly.
*/
public:
typedef typename /* Type definition for */
vector<Node*, ALLOC(Node*) >::size_type /* the size of the */
size_type; /* graph. The size can
typedef typename vector<Node*>::size_type /* Type definition for */
size_type; /* the size of the
* graph. The size can
* be no greater than
* the maximum size of
* the vector containing
* the graph nodes.
*/
typedef EdgeContainer EdgeContainerType; /* Type definition for
* containers of graph
* edges.
*/
typedef deque<PathElement> Path; /* Type definition for
* paths in a graph.
*/
typedef pair<size_type, size_type> StateIdPair; /* Type definition for a
* pair of state
* identifiers in a graph.
@ -323,8 +336,8 @@ public:
/* default assignment operator */
Graph<EdgeContainer>::size_type targetNode() /* Returns the index of */
const; /* the target node of
size_type targetNode() const; /* Returns the index of */
/* the target node of
* the directed edge.
*/
@ -353,7 +366,7 @@ protected:
*/
private:
Graph<EdgeContainer>::size_type target_node; /* Identifier of the edge's
size_type target_node; /* Identifier of the edge's
* target node.
*/
};
@ -404,6 +417,62 @@ protected:
/******************************************************************************
*
* A template class for representing (node identifier, edge) pairs in a graph.
*
*****************************************************************************/
template <class EdgeContainer>
class Graph<EdgeContainer>::PathElement
{
public:
explicit PathElement /* Constructors. */
(const typename Graph<EdgeContainer>::size_type
n,
const typename Graph<EdgeContainer>::Edge*
e = 0);
PathElement
(const typename Graph<EdgeContainer>::size_type
n,
const typename Graph<EdgeContainer>::Edge& e);
/* default copy constructor */
~PathElement(); /* Destructor. */
/* default assignment operator */
size_type node() const; /* Returns the identifier
* of the node associated
* with the path element.
*/
bool hasEdge() const; /* Tells whether there is
* an edge associated with
* the path element.
*/
const Edge& edge() const; /* Returns the edge
* associated with the
* path element.
*/
private:
typename Graph<EdgeContainer>::size_type node_id; /* Identifier of the node
* associated with the path
* element.
*/
const typename Graph<EdgeContainer>::Edge* /* Pointer to the edge */
edge_pointer; /* associated with the
* path element.
*/
};
/******************************************************************************
*
* An exception class for reporting errors when indexing graph nodes.
@ -434,8 +503,7 @@ public:
*
*****************************************************************************/
class EdgeList : public list<Graph<EdgeList>::Edge*,
ALLOC(Graph<EdgeList>::Edge*) >
class EdgeList : public list<Graph<EdgeList>::Edge*>
{
public:
EdgeList(); /* Constructor. */
@ -450,14 +518,12 @@ public:
* the end of the list.
*/
list<Graph<EdgeList>::Edge*, /* Functions for finding */
ALLOC(Graph<EdgeList>::Edge*) > /* an element in the */
::const_iterator /* list. */
find(const Graph<EdgeList>::Edge* edge) const;
list<Graph<EdgeList>::Edge*,
ALLOC(Graph<EdgeList>::Edge*) >
::iterator
list<Graph<EdgeList>::Edge*>::const_iterator /* Functions for finding */
find(const Graph<EdgeList>::Edge* edge) const; /* an element in the
* list.
*/
list<Graph<EdgeList>::Edge*>::iterator
find(const Graph<EdgeList>::Edge* edge);
};
@ -472,8 +538,7 @@ public:
#ifdef HAVE_SLIST
class EdgeSlist : public slist<Graph<EdgeSlist>::Edge*,
ALLOC(Graph<EdgeSlist>::Edge*) >
class EdgeSlist : public slist<Graph<EdgeSlist>::Edge*>
{
public:
EdgeSlist(); /* Constructor. */
@ -489,14 +554,12 @@ public:
* list.
*/
slist<Graph<EdgeSlist>::Edge*, /* Functions for finding */
ALLOC(Graph<EdgeSlist>::Edge*) > /* an element in the */
::const_iterator /* list. */
find(const Graph<EdgeSlist>::Edge* edge) const;
slist<Graph<EdgeSlist>::Edge*>::const_iterator /* Functions for finding */
find(const Graph<EdgeSlist>::Edge* edge) const; /* an element in the
* list.
*/
slist<Graph<EdgeSlist>::Edge*,
ALLOC(Graph<EdgeSlist>::Edge*) >
::iterator
slist<Graph<EdgeSlist>::Edge*>::iterator
find(const Graph<EdgeSlist>::Edge* edge);
};
@ -510,8 +573,7 @@ public:
*
*****************************************************************************/
class EdgeVector : public vector<Graph<EdgeVector>::Edge*,
ALLOC(Graph<EdgeVector>::Edge*) >
class EdgeVector : public vector<Graph<EdgeVector>::Edge*>
{
public:
EdgeVector(); /* Constructor. */
@ -527,15 +589,11 @@ public:
* to edges.
*/
vector<Graph<EdgeVector>::Edge*, /* Functions for finding */
ALLOC(Graph<EdgeVector>::Edge*) > /* an element in the */
::const_iterator /* container. */
find(const Graph<EdgeVector>::Edge* edge)
const;
vector<Graph<EdgeVector>::Edge*>::const_iterator /* Functions for finding */
find(const Graph<EdgeVector>::Edge* edge) /* an element in the */
const; /* container. */
vector<Graph<EdgeVector>::Edge*,
ALLOC(Graph<EdgeVector>::Edge*) >
::iterator
vector<Graph<EdgeVector>::Edge*>::iterator
find(const Graph<EdgeVector>::Edge* edge);
};
@ -548,8 +606,7 @@ public:
*****************************************************************************/
class EdgeSet : public set<Graph<EdgeSet>::Edge*,
Graph<EdgeSet>::Edge::ptr_less,
ALLOC(Graph<EdgeSet>::Edge*) >
Graph<EdgeSet>::Edge::ptr_less>
{
};
@ -562,8 +619,7 @@ class EdgeSet : public set<Graph<EdgeSet>::Edge*,
*****************************************************************************/
class EdgeMultiSet : public multiset<Graph<EdgeMultiSet>::Edge*,
Graph<EdgeMultiSet>::Edge::ptr_less,
ALLOC(Graph<EdgeMultiSet>::Edge*) >
Graph<EdgeMultiSet>::Edge::ptr_less>
{
};
@ -689,7 +745,7 @@ Graph<EdgeContainer>::Graph(const size_type initial_number_of_nodes) :
{
nodes.reserve(initial_number_of_nodes);
for (typename vector<Node*, ALLOC(Node*) >::iterator node = nodes.begin();
for (typename vector<Node*>::iterator node = nodes.begin();
node != nodes.end();
++node)
*node = new Node();
@ -711,8 +767,7 @@ Graph<EdgeContainer>::Graph(const Graph<EdgeContainer>& graph)
* ------------------------------------------------------------------------- */
{
nodes.reserve(graph.nodes.size());
for (typename vector<Node*, ALLOC(Node*) >::const_iterator
node = graph.nodes.begin();
for (typename vector<Node*>::const_iterator node = graph.nodes.begin();
node != graph.nodes.end(); ++node)
nodes.push_back(new Node(**node));
}
@ -738,8 +793,7 @@ Graph<EdgeContainer>& Graph<EdgeContainer>::operator=
clear();
nodes.reserve(graph.nodes.size());
for (typename vector<Node*, ALLOC(Node*) >::const_iterator
node = graph.nodes.begin();
for (typename vector<Node*>::const_iterator node = graph.nodes.begin();
node != graph.nodes.end();
++node)
nodes.push_back(new Node(**node));
@ -782,8 +836,7 @@ void Graph<EdgeContainer>::clear()
*
* ------------------------------------------------------------------------- */
{
for (typename vector<Node*, ALLOC(Node*) >::reverse_iterator
node = nodes.rbegin();
for (typename vector<Node*>::reverse_iterator node = nodes.rbegin();
node != nodes.rend();
++node)
delete *node;
@ -924,13 +977,12 @@ Graph<EdgeContainer>::stats() const
*
* ------------------------------------------------------------------------- */
{
pair<Graph<EdgeContainer>::size_type, unsigned long int> result;
pair<size_type, unsigned long int> result;
result.first = nodes.size();
result.second = 0;
for (typename vector<Node*, ALLOC(Node*) >::const_iterator
node = nodes.begin();
for (typename vector<Node*>::const_iterator node = nodes.begin();
node != nodes.end(); ++node)
result.second += (*node)->edges().size();
@ -964,7 +1016,7 @@ Graph<EdgeContainer>::subgraphStats(const size_type index) const
if (index >= s)
throw NodeIndexException();
stack<size_type, deque<size_type, ALLOC(size_type) > > unprocessed_nodes;
stack<size_type, deque<size_type> > unprocessed_nodes;
BitArray visited_nodes(s);
visited_nodes.clear(s);
@ -1468,6 +1520,128 @@ void Graph<EdgeContainer>::Node::print
/******************************************************************************
*
* Inline function definitions for template class
* Graph<EdgeContainer>::PathElement.
*
*****************************************************************************/
/* ========================================================================= */
template <class EdgeContainer>
inline Graph<EdgeContainer>::PathElement::PathElement
(const typename Graph<EdgeContainer>::size_type n,
const typename Graph<EdgeContainer>::Edge* e) :
node_id(n), edge_pointer(e)
/* ----------------------------------------------------------------------------
*
* Description: Constructor for class Graph<EdgeContainer>::PathElement.
* Creates a (node identifier, edge) pair from a node identifier
* and a pointer to an edge.
*
* Arguments: n -- Numeric identifier of a graph node.
* e -- A constant pointer to a graph edge.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
}
/* ========================================================================= */
template <class EdgeContainer>
inline Graph<EdgeContainer>::PathElement::PathElement
(const typename Graph<EdgeContainer>::size_type n,
const typename Graph<EdgeContainer>::Edge& e) :
node_id(n), edge_pointer(&e)
/* ----------------------------------------------------------------------------
*
* Description: Constructor for class Graph<EdgeContainer>::PathElement.
* Creates a (node identifier, edge) pair from a node identifier
* and an edge.
*
* Arguments: n -- Numeric identifier of a graph node.
* e -- A constant reference to a graph edge.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
}
/* ========================================================================= */
template <class EdgeContainer>
inline Graph<EdgeContainer>::PathElement::~PathElement()
/* ----------------------------------------------------------------------------
*
* Description: Destructor for class Graph<EdgeContainer>::PathElement.
*
* Arguments: None.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
}
/* ========================================================================= */
template <class EdgeContainer>
inline typename Graph<EdgeContainer>::size_type
Graph<EdgeContainer>::PathElement::node() const
/* ----------------------------------------------------------------------------
*
* Description: Returns the identifier of the node associated with a
* Graph<EdgeContainer>::PathElement object.
*
* Arguments: None.
*
* Returns: Identifier of the node associated with the object.
*
* ------------------------------------------------------------------------- */
{
return node_id;
}
/* ========================================================================= */
template <class EdgeContainer>
inline bool Graph<EdgeContainer>::PathElement::hasEdge() const
/* ----------------------------------------------------------------------------
*
* Description: Tells whether there is an edge associated with a
* Graph<EdgeContainer>::PathElement object.
*
* Arguments: None.
*
* Returns: true iff there is an edge associated with the object.
*
* ------------------------------------------------------------------------- */
{
return (edge != 0);
}
/* ========================================================================= */
template <class EdgeContainer>
inline const typename Graph<EdgeContainer>::Edge&
Graph<EdgeContainer>::PathElement::edge() const
/* ----------------------------------------------------------------------------
*
* Description: Returns the edge associated with a
* Graph<EdgeContainer>::PathElement object. The function
* assumes that there is such an edge; it is an error to call
* this function for a PathElement object `element' for which
* `element.hasEdge() == false'.
*
* Arguments: None.
*
* Returns: The edge associated with the object.
*
* ------------------------------------------------------------------------- */
{
return *edge_pointer;
}
/******************************************************************************
*
* Inline function definitions for class NodeIndexException.
@ -1574,8 +1748,7 @@ inline void EdgeList::insert(Graph<EdgeList>::Edge* edge)
}
/* ========================================================================= */
inline list<Graph<EdgeList>::Edge*, ALLOC(Graph<EdgeList>::Edge*) >
::const_iterator
inline list<Graph<EdgeList>::Edge*>::const_iterator
EdgeList::find(const Graph<EdgeList>::Edge* edge) const
/* ----------------------------------------------------------------------------
*
@ -1586,9 +1759,9 @@ EdgeList::find(const Graph<EdgeList>::Edge* edge) const
* between the actual values of the edges (not the
* pointers).
*
* Returns: A list<Graph<EdgeList>::Edge*, ALLOC>::const_iterator
* Returns: A list<Graph<EdgeList>::Edge*>::const_iterator
* pointing to the edge in the list or
* list<Graph<EdgeList>::Edge*, ALLOC>::end() if the edge is
* list<Graph<EdgeList>::Edge*>::end() if the edge is
* not found in the list.
*
* ------------------------------------------------------------------------- */
@ -1603,7 +1776,7 @@ EdgeList::find(const Graph<EdgeList>::Edge* edge) const
}
/* ========================================================================= */
inline list<Graph<EdgeList>::Edge*, ALLOC(Graph<EdgeList>::Edge*) >::iterator
inline list<Graph<EdgeList>::Edge*>::iterator
EdgeList::find(const Graph<EdgeList>::Edge* edge)
/* ----------------------------------------------------------------------------
*
@ -1614,9 +1787,9 @@ EdgeList::find(const Graph<EdgeList>::Edge* edge)
* between the actual values of the edges (not the
* pointers).
*
* Returns: A list<Graph<EdgeList>::Edge*, ALLOC>::iterator pointing
* Returns: A list<Graph<EdgeList>::Edge*>::iterator pointing
* to the edge in the list or
* list<Graph<EdgeList>::Edge*, ALLOC>::end() if the edge is
* list<Graph<EdgeList>::Edge*>::end() if the edge is
* not found in the list.
*
* ------------------------------------------------------------------------- */
@ -1685,8 +1858,7 @@ inline void EdgeSlist::insert(Graph<EdgeSlist>::Edge* edge)
}
/* ========================================================================= */
inline slist<Graph<EdgeSlist>::Edge*, ALLOC(Graph<EdgeSlist>::Edge*) >
::const_iterator
inline slist<Graph<EdgeSlist>::Edge*>::const_iterator
EdgeSlist::find(const Graph<EdgeSlist>::Edge* edge) const
/* ----------------------------------------------------------------------------
*
@ -1697,9 +1869,9 @@ EdgeSlist::find(const Graph<EdgeSlist>::Edge* edge) const
* between the actual values of the edges (not the
* pointers).
*
* Returns: A slist<Graph<EdgeSlist>::Edge*, ALLOC>::const_iterator
* Returns: A slist<Graph<EdgeSlist>::Edge*>::const_iterator
* pointing to the edge in the list or
* slist<Graph<EdgeSlist>::Edge*, ALLOC>::end() if the edge
* slist<Graph<EdgeSlist>::Edge*>::end() if the edge
* is not found in the list.
*
* ------------------------------------------------------------------------- */
@ -1714,8 +1886,7 @@ EdgeSlist::find(const Graph<EdgeSlist>::Edge* edge) const
}
/* ========================================================================= */
inline slist<Graph<EdgeSlist>::Edge*, ALLOC(Graph<EdgeSlist>::Edge*) >
::iterator
inline slist<Graph<EdgeSlist>::Edge*>::iterator
EdgeSlist::find(const Graph<EdgeSlist>::Edge* edge)
/* ----------------------------------------------------------------------------
*
@ -1726,9 +1897,9 @@ EdgeSlist::find(const Graph<EdgeSlist>::Edge* edge)
* between the actual values of the edges (not the
* pointers).
*
* Returns: A slist<Graph<EdgeSlist>::Edge*, ALLOC>::iterator
* Returns: A slist<Graph<EdgeSlist>::Edge*>::iterator
* pointing to the edge in the list or
* slist<Graph<EdgeSlist>::Edge*, ALLOC>::end() if the edge
* slist<Graph<EdgeSlist>::Edge*>::end() if the edge
* is not found in the list.
*
* ------------------------------------------------------------------------- */
@ -1797,8 +1968,7 @@ inline void EdgeVector::insert(Graph<EdgeVector>::Edge* edge)
}
/* ========================================================================= */
inline vector<Graph<EdgeVector>::Edge*, ALLOC(Graph<EdgeVector>::Edge*) >
::const_iterator
inline vector<Graph<EdgeVector>::Edge*>::const_iterator
EdgeVector::find(const Graph<EdgeVector>::Edge* edge) const
/* ----------------------------------------------------------------------------
*
@ -1809,9 +1979,9 @@ EdgeVector::find(const Graph<EdgeVector>::Edge* edge) const
* between the actual values of the edges (not the
* pointers).
*
* Returns: A vector<Graph<EdgeVector>::Edge*, ALLOC>::const_iterator
* Returns: A vector<Graph<EdgeVector>::Edge*>::const_iterator
* pointing to the edge in the container or
* vector<Graph<EdgeVector>::Edge*, ALLOC>::end() if the
* vector<Graph<EdgeVector>::Edge*>::end() if the
* edge is not found in the container.
*
* ------------------------------------------------------------------------- */
@ -1826,8 +1996,7 @@ EdgeVector::find(const Graph<EdgeVector>::Edge* edge) const
}
/* ========================================================================= */
inline vector<Graph<EdgeVector>::Edge*, ALLOC(Graph<EdgeVector>::Edge*) >
::iterator
inline vector<Graph<EdgeVector>::Edge*>::iterator
EdgeVector::find(const Graph<EdgeVector>::Edge* edge)
/* ----------------------------------------------------------------------------
*
@ -1838,9 +2007,9 @@ EdgeVector::find(const Graph<EdgeVector>::Edge* edge)
* between the actual values of the edges (not the
* pointers).
*
* Returns: A vector<Graph<EdgeVector>::Edge*, ALLOC>::iterator
* Returns: A vector<Graph<EdgeVector>::Edge*>::iterator
* pointing to the edge in the container or
* vector<Graph<EdgeSlist>::Edge*, ALLOC>::end() if the edge
* vector<Graph<EdgeSlist>::Edge*>::end() if the edge
* is not found in the container.
*
* ------------------------------------------------------------------------- */

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -41,7 +41,7 @@ void IntervalList::merge(unsigned long int min, unsigned long int max)
if (min > max)
return;
list<Interval, ALLOC(Interval) >::iterator interval;
list<Interval>::iterator interval;
for (interval = intervals.begin();
interval != intervals.end() && interval->second + 1 < min;
++interval)
@ -68,14 +68,14 @@ void IntervalList::merge(unsigned long int min, unsigned long int max)
if (interval->second < max)
{
interval->second = max;
list<Interval, ALLOC(Interval) >::iterator interval2 = interval;
list<Interval>::iterator interval2 = interval;
++interval2;
while (interval2 != intervals.end()
&& interval2->first <= interval->second + 1)
{
if (interval->second < interval2->second)
interval->second = interval2->second;
list<Interval, ALLOC(Interval) >::iterator interval_to_erase = interval2;
list<Interval>::iterator interval_to_erase = interval2;
++interval2;
intervals.erase(interval_to_erase);
}
@ -97,7 +97,7 @@ void IntervalList::remove(unsigned long int min, unsigned long int max)
if (min > max)
return;
list<Interval, ALLOC(Interval) >::iterator interval;
list<Interval>::iterator interval;
for (interval = intervals.begin();
interval != intervals.end() && interval->second < min;
++interval)
@ -126,7 +126,7 @@ void IntervalList::remove(unsigned long int min, unsigned long int max)
}
else /* min <= imin <= imax <= max */
{
list<Interval, ALLOC(Interval) >::iterator interval_to_erase = interval;
list<Interval>::iterator interval_to_erase = interval;
++interval;
intervals.erase(interval_to_erase);
}
@ -148,7 +148,7 @@ bool IntervalList::covers(unsigned long int min, unsigned long int max) const
if (min > max)
return true; /* empty interval is always covered */
list<Interval, ALLOC(Interval) >::const_iterator interval;
list<Interval>::const_iterator interval;
for (interval = intervals.begin();
interval != intervals.end() && min > interval->second;
++interval)
@ -173,8 +173,7 @@ string IntervalList::toString() const
* ------------------------------------------------------------------------- */
{
string s;
for (list<Interval, ALLOC(Interval) >::const_iterator
interval = intervals.begin();
for (list<Interval>::const_iterator interval = intervals.begin();
interval != intervals.end();
++interval)
{

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -74,13 +74,15 @@ public:
unsigned long int operator++(int); /* Postfix increment. */
private:
const list<Interval, ALLOC(Interval) >* /* The interval list */
interval_list; /* associated with the */
/* iterator. */
const list<Interval>* interval_list; /* The interval list
* associated with the
* iterator.
*/
list<Interval, ALLOC(Interval) > /* An iterator pointing */
::const_iterator interval; /* at the current */
/* interval list. */
list<Interval>::const_iterator interval; /* An iterator pointing at
* the current intrerval
* list.
*/
unsigned long int element; /* Element currently
* pointed to by the
@ -143,8 +145,7 @@ public:
* iterators.
*/
typedef list<Interval, ALLOC(Interval) > /* Size type. */
::size_type size_type;
typedef list<Interval>::size_type size_type; /* Size type. */
size_type size() const; /* Tell the number of
* disjoint intervals in
@ -170,7 +171,7 @@ public:
*/
private:
list<Interval, ALLOC(Interval) > intervals; /* List of intervals. */
list<Interval> intervals; /* List of intervals. */
friend class const_iterator;
};

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -22,12 +22,6 @@
#include <config.h>
#ifdef HAVE_SINGLE_CLIENT_ALLOC
#define ALLOC(typename) single_client_alloc
#else
#define ALLOC(typename) allocator<typename>
#endif /* HAVE_SINGLE_CLIENT_ALLOC */
#ifdef HAVE_OBSTACK_H
/* GNU libc 2.3.2's copy of obstack.h uses a definition of __INT_TO_PTR

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -44,9 +44,9 @@ static LtlFormula* result; /* This variable stores the
* ltl_parse.
*/
static std::set<LtlFormula*, less<LtlFormula*>, /* Intermediate results. */
ALLOC(LtlFormula*) > /* (This set is used */
intermediate_results; /* for keeping track of
static std::set<LtlFormula*> intermediate_results; /* Intermediate results.
* (This set is used
* for keeping track of
* the subformulas of a
* partially constructed
* formula in case the
@ -426,8 +426,8 @@ LtlFormula* parseFormula(istream& stream)
}
catch (...)
{
for (std::set<LtlFormula*, less<LtlFormula*>, ALLOC(LtlFormula*) >
::const_iterator f = intermediate_results.begin();
for (std::set<LtlFormula*>::const_iterator
f = intermediate_results.begin();
f != intermediate_results.end();
++f)
LtlFormula::destruct(*f);

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,10 +17,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef __GNUC__
#pragma implementation
#endif /* __GNUC__ */
#include <config.h>
#include "FormulaWriter.h"
#include "LtlFormula.h"
@ -28,10 +24,8 @@
namespace Ltl
{
map<LtlFormula*, unsigned long int, /* Shared storage for */
LtlFormula::ptr_less, /* LTL formulae. */
ALLOC(unsigned long int) >
LtlFormula::formula_storage;
set<LtlFormula*, LtlFormula::ptr_less> /* Shared storage for */
LtlFormula::formula_storage; /* LTL formulae. */
unsigned long int /* Upper limit for the */
LtlFormula::eval_proposition_id_limit; /* atomic proposition
@ -42,8 +36,6 @@ unsigned long int /* Upper limit for the */
* truth assignment).
*/
/******************************************************************************
*
* Function for obtaining the infix symbol associated with a given
@ -147,12 +139,10 @@ public:
*/
private:
stack<LtlFormula*,
deque<LtlFormula*, ALLOC(LtlFormula*) > >
stack<LtlFormula*, deque<LtlFormula*> >
formula_stack;
stack<bool, deque<bool, ALLOC(bool) > >
negation_stack;
stack<bool, deque<bool> > negation_stack;
NnfConverter(const NnfConverter&); /* Prevent copying and */
NnfConverter& operator=(const NnfConverter&); /* assignment of
@ -203,8 +193,7 @@ class SubformulaCollector
public:
SubformulaCollector /* Constructor. */
(stack<const LtlFormula*,
deque<const LtlFormula*,
ALLOC(const LtlFormula*) > >&
deque<const LtlFormula*> >&
result_stack);
~SubformulaCollector(); /* Destructor. */
@ -216,8 +205,7 @@ public:
private:
stack<const LtlFormula*, /* Stack of subformulae. */
deque<const LtlFormula*,
ALLOC(const LtlFormula*) > >&
deque<const LtlFormula*> >&
subformula_stack;
SubformulaCollector(const SubformulaCollector&); /* Prevent copying and */
@ -389,9 +377,7 @@ inline void FormulaSizeCounter::operator()(const LtlFormula*, int)
/* ========================================================================= */
inline SubformulaCollector::SubformulaCollector
(stack<const LtlFormula*, deque<const LtlFormula*,
ALLOC(const LtlFormula*) > >&
result_stack) :
(stack<const LtlFormula*, deque<const LtlFormula*> >& result_stack) :
subformula_stack(result_stack)
/* ----------------------------------------------------------------------------
*
@ -773,9 +759,7 @@ unsigned long int LtlFormula::size() const
/* ========================================================================= */
void LtlFormula::collectSubformulae
(stack<const LtlFormula*, deque<const LtlFormula*,
ALLOC(const LtlFormula*) > >&
result_stack) const
(stack<const LtlFormula*, deque<const LtlFormula*> >& result_stack) const
/* ----------------------------------------------------------------------------
*
* Description: Collects the subformulae of a LtlFormula into a stack. After
@ -879,193 +863,6 @@ Bitset LtlFormula::findPropositionalModel(long int max_atom) const
return model;
}
/* ========================================================================= */
LtlFormula* LtlFormula::read(Exceptional_istream& stream)
/* ----------------------------------------------------------------------------
*
* Description: Recursively constructs an LtlFormula by parsing input from an
* exception-aware input stream.
*
* Argument: stream -- A reference to an exception-aware input stream.
*
* Returns: The constructed LtlFormula.
*
* ------------------------------------------------------------------------- */
{
string token;
LtlFormula* formula;
try
{
stream >> token;
}
catch (const IOException&)
{
if (static_cast<istream&>(stream).eof())
throw ParseErrorException("error parsing LTL formula (unexpected end of "
"input)");
else
throw ParseErrorException("error parsing LTL formula (I/O error)");
}
if (token[0] == 'p')
{
if (token.length() == 1)
throw ParseErrorException("error parsing LTL formula (unrecognized "
"token: `" + token + "')");
long int id;
char* endptr;
id = strtol(token.c_str() + 1, &endptr, 10);
if (*endptr != '\0' || id < 0 || id == LONG_MIN || id == LONG_MAX)
throw ParseErrorException("error parsing LTL formula (unrecognized "
"token: `" + token + "')");
formula = &Atom::construct(id);
}
else
{
if (token.length() > 1)
throw ParseErrorException("error parsing LTL formula (unrecognized "
"token: `" + token + "')");
switch (token[0])
{
case LTL_TRUE :
formula = &True::construct();
break;
case LTL_FALSE :
formula = &False::construct();
break;
case LTL_NEGATION :
case LTL_NEXT :
case LTL_FINALLY :
case LTL_GLOBALLY :
{
LtlFormula* g = read(stream);
try
{
switch (token[0])
{
case LTL_NEGATION :
formula = &Not::construct(g);
break;
case LTL_NEXT :
formula = &Next::construct(g);
break;
case LTL_FINALLY :
formula = &Finally::construct(g);
break;
default : /* LTL_GLOBALLY */
formula = &Globally::construct(g);
break;
}
}
catch (...)
{
LtlFormula::destruct(g);
throw;
}
break;
}
case LTL_CONJUNCTION :
case LTL_DISJUNCTION :
case LTL_IMPLICATION :
case LTL_EQUIVALENCE :
case LTL_XOR :
case LTL_UNTIL :
case LTL_V :
case LTL_WEAK_UNTIL :
case LTL_STRONG_RELEASE :
case LTL_BEFORE :
{
LtlFormula* g = read(stream);
LtlFormula* h;
try
{
h = read(stream);
}
catch (...)
{
LtlFormula::destruct(g);
throw;
}
try
{
switch (token[0])
{
case LTL_CONJUNCTION :
formula = &And::construct(g, h);
break;
case LTL_DISJUNCTION :
formula = &Or::construct(g, h);
break;
case LTL_IMPLICATION :
formula = &Imply::construct(g, h);
break;
case LTL_EQUIVALENCE :
formula = &Equiv::construct(g, h);
break;
case LTL_XOR :
formula = &Xor::construct(g, h);
break;
case LTL_UNTIL :
formula = &Until::construct(g, h);
break;
case LTL_V :
formula = &V::construct(g, h);
break;
case LTL_WEAK_UNTIL :
formula = &WeakUntil::construct(g, h);
break;
case LTL_STRONG_RELEASE :
formula = &StrongRelease::construct(g, h);
break;
default : /* LTL_BEFORE */
formula = &Before::construct(g, h);
break;
}
}
catch (...)
{
LtlFormula::destruct(g);
LtlFormula::destruct(h);
throw;
}
break;
}
default :
throw ParseErrorException("error parsing LTL formula (unrecognized "
"token: `" + token + "')");
}
}
return formula;
}
/* ========================================================================= */
void LtlFormula::print(Exceptional_ostream& estream, OutputMode mode) const
/* ----------------------------------------------------------------------------

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -23,7 +23,7 @@
#include <config.h>
#include <deque>
#include <iostream>
#include <map>
#include <set>
#include <stack>
#include <string>
#include "LbttAlloc.h"
@ -188,13 +188,6 @@ public:
* input stream.
*/
static LtlFormula* read /* Constructs an */
(Exceptional_istream& stream); /* LtlFormula by parsing
* input from an
* exception-aware input
* stream.
*/
void print /* Writes the formula to */
(ostream& stream = cout, /* an output stream. */
OutputMode mode = LTL_INFIX) const;
@ -250,6 +243,10 @@ protected:
unsigned int is_constant : 1; /* operators and atomic */
} info_flags; /* propositions. */
unsigned long int refcount; /* Number of references to
* `this' LtlFormula.
*/
static LtlFormula& /* Updates the shared */
insertToStorage(LtlFormula* f); /* formula storage with
* a new formula.
@ -264,21 +261,18 @@ private:
void collectSubformulae /* Builds a stack of the */
(stack<const LtlFormula*, /* subformulae of the */
deque<const LtlFormula*, /* formula. */
ALLOC(const LtlFormula*) > >&
deque<const LtlFormula*> >& /* formula. */
result_stack) const;
typedef pair<bool, const LtlFormula*> /* Shorthand type */
FormulaStackElement; /* definitions for the */
typedef stack<FormulaStackElement, /* propositional */
deque<FormulaStackElement, /* satisfiability */
ALLOC(FormulaStackElement) > >/* checking algorithm. */
FormulaStack;
deque<FormulaStackElement> > /* satisfiability */
FormulaStack; /* checking algorithm. */
typedef pair<FormulaStack, Bitset>
TableauStackElement;
typedef stack<TableauStackElement,
deque<TableauStackElement,
ALLOC(TableauStackElement) > >
deque<TableauStackElement> >
TableauStack;
bool sat_eval /* Helper function for */
@ -288,9 +282,8 @@ private:
* formula.
*/
static map<LtlFormula*, unsigned long int, /* Shared storage for */
ptr_less, ALLOC(unsigned long int) > /* LTL formulae. */
formula_storage;
static set<LtlFormula*, ptr_less> /* Shared storage for */
formula_storage; /* LTL formulae. */
static unsigned long int /* Upper limit for the */
eval_proposition_id_limit; /* atomic proposition
@ -330,6 +323,16 @@ private:
/******************************************************************************
*
* Interface to the formula parser.
*
*****************************************************************************/
extern LtlFormula* parseFormula(istream& stream);
/******************************************************************************
*
* A class for atomic propositions.
@ -474,7 +477,7 @@ private:
* to satisfy the
* LtlFormula member
* function interface.
*/
*/
};
@ -1076,7 +1079,7 @@ typedef BinaryFormula<LtlBefore> Before;
*****************************************************************************/
/* ========================================================================= */
inline LtlFormula::LtlFormula()
inline LtlFormula::LtlFormula() : refcount(1)
/* ----------------------------------------------------------------------------
*
* Description: Constructor for class LtlFormula. Initializes the attributes
@ -1088,8 +1091,6 @@ inline LtlFormula::LtlFormula()
*
* --------------------------------------------------------------------------*/
{
info_flags.is_propositional = 0;
info_flags.is_constant = 0;
}
/* ========================================================================= */
@ -1122,14 +1123,9 @@ inline void LtlFormula::destruct(LtlFormula* f)
*
* ------------------------------------------------------------------------- */
{
map<LtlFormula*, unsigned long int, LtlFormula::ptr_less,
ALLOC(unsigned long int) >::iterator
deleter;
deleter = formula_storage.find(f);
if (--deleter->second == 0)
if (--f->refcount == 0)
{
formula_storage.erase(deleter);
formula_storage.erase(f);
delete f;
}
}
@ -1147,7 +1143,7 @@ inline LtlFormula* LtlFormula::clone()
*
* ------------------------------------------------------------------------- */
{
formula_storage.find(this)->second++;
++refcount;
return this;
}
@ -1241,8 +1237,7 @@ inline LtlFormula* LtlFormula::read(istream& stream)
*
* ------------------------------------------------------------------------- */
{
Exceptional_istream estream(&stream, ios::badbit | ios::failbit);
return read(estream);
return parseFormula(stream);
}
/* ========================================================================= */
@ -1303,8 +1298,6 @@ inline Exceptional_ostream& operator<<
return stream;
}
/* ========================================================================= */
inline LtlFormula& LtlFormula::insertToStorage(LtlFormula* f)
/* ----------------------------------------------------------------------------
@ -1317,19 +1310,15 @@ inline LtlFormula& LtlFormula::insertToStorage(LtlFormula* f)
*
* ------------------------------------------------------------------------- */
{
map<LtlFormula*, unsigned long int, LtlFormula::ptr_less,
ALLOC(unsigned long int) >::iterator
inserter;
inserter = formula_storage.find(f);
set<LtlFormula*, ptr_less>::iterator inserter = formula_storage.find(f);
if (inserter != formula_storage.end())
{
delete f;
inserter->second++;
return *(inserter->first);
++(*inserter)->refcount;
return **inserter;
}
formula_storage.insert(make_pair(f, 1));
formula_storage.insert(f);
return *f;
}
@ -1571,8 +1560,7 @@ inline Atom& Atom::construct(long int a)
}
/* ========================================================================= */
inline Atom::Atom(long int a) :
LtlFormula(), atom(a)
inline Atom::Atom(long int a) : atom(a)
/* ----------------------------------------------------------------------------
*
* Description: Constructor for class Atom. Creates a new propositional atom.
@ -1886,8 +1874,7 @@ inline UnaryFormula<Operator>& UnaryFormula<Operator>::construct(LtlFormula& f)
/* ========================================================================= */
template<class Operator>
inline UnaryFormula<Operator>::UnaryFormula(LtlFormula* f) :
LtlFormula(), subformula(f)
inline UnaryFormula<Operator>::UnaryFormula(LtlFormula* f) : subformula(f)
/* ----------------------------------------------------------------------------
*
* Description: Constructs an LTL formula with a unary operator.
@ -2189,7 +2176,7 @@ BinaryFormula<Operator>::construct(LtlFormula& f1, LtlFormula* f2)
/* ========================================================================= */
template<class Operator>
inline BinaryFormula<Operator>::BinaryFormula(LtlFormula* f1, LtlFormula* f2) :
LtlFormula(), subformula1(f1), subformula2(f2)
subformula1(f1), subformula2(f2)
/* ----------------------------------------------------------------------------
*
* Description: Constructs a binary LTL formula.

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -30,6 +30,7 @@ extern int current_neverclaim_line_number;
%option never-interactive
%option noyywrap
%option nounput
%%

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,10 +17,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef __GNUC__
#pragma implementation
#endif /* __GNUC__ */
#include <config.h>
#include <cstdio>
#include <fstream>
@ -66,8 +62,7 @@ void NeverClaimAutomaton::clear()
*
* ------------------------------------------------------------------------- */
{
for (vector<StateInfo*, ALLOC(StateInfo*) >::iterator
state = state_list.begin();
for (vector<StateInfo*>::iterator state = state_list.begin();
state != state_list.end();
++state)
delete (*state);
@ -158,8 +153,7 @@ void NeverClaimAutomaton::write(const char* output_filename)
* `-1'.
*/
for (vector<StateInfo*, ALLOC(StateInfo*) >::const_iterator
state = state_list.begin();
for (vector<StateInfo*>::const_iterator state = state_list.begin();
state != state_list.end();
++state)
{
@ -167,7 +161,7 @@ void NeverClaimAutomaton::write(const char* output_filename)
+ ((*state)->initial() ? "1" : "0") + ' '
+ ((*state)->accepting() ? "0 " : "") + "-1\n";
for (multimap<Cstr, Cstr*, less<Cstr>, ALLOC(Cstr*) >::const_iterator
for (multimap<Cstr, Cstr*>::const_iterator
transition = (*state)->transitions().begin();
transition != (*state)->transitions().end(); ++transition)
{
@ -272,7 +266,7 @@ NeverClaimAutomaton::StateInfo::~StateInfo()
*
* ------------------------------------------------------------------------- */
{
for (multimap<Cstr, Cstr*, less<Cstr>, ALLOC(Cstr*) >::const_iterator
for (multimap<Cstr, Cstr*>::const_iterator
transition = state_transitions.begin();
transition != state_transitions.end();
++transition)
@ -312,7 +306,7 @@ ParseErrorException::ParseErrorException
else
{
string space_string(msg.substr(0, error_pos));
for (string::size_type c = 0; c < msg.length(); c++)
for (string::size_type c = 0; c < space_string.length(); c++)
if (space_string[c] != ' ' && space_string[c] != '\t')
space_string[c] = ' ';

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -93,12 +93,13 @@ public:
*/
private:
vector<StateInfo*, ALLOC(StateInfo*) > /* States of the */
state_list; /* automaton. */
vector<StateInfo*> state_list; /* States of the automaton.
*/
map<string, StateInfo*, less<string>, /* Mapping from state */
ALLOC(StateInfo*) > /* labels to the states */
label_mapping; /* itself. */
map<string, StateInfo*> label_mapping; /* Mapping from state
* labels to the states
* itself.
*/
StateInfo* current_state; /* Pointer to the state
* introduced most recently
@ -142,9 +143,9 @@ public:
/* of the state.
*/
const multimap<Cstr, Cstr*, less<Cstr>, /* Returns the labels of */
ALLOC(Cstr*) >& /* the state's successor */
transitions() const; /* states, including the
const multimap<Cstr, Cstr*>& transitions() const; /* Returns the labels of
* the state's successor
* states, including the
* conditions controlling
* the enabledness of the
* transition.
@ -174,8 +175,8 @@ private:
* accepting state?
*/
multimap<Cstr, Cstr*, less<Cstr>, ALLOC(Cstr*) > /* Labels of the state's */
state_transitions; /* successors, including
multimap<Cstr, Cstr*> state_transitions; /* Labels of the state's
* successors, including
* the guard formulae
* controlling the
* enabledness of the
@ -373,9 +374,7 @@ inline bool& NeverClaimAutomaton::StateInfo::accepting()
}
/* ========================================================================= */
inline const multimap<NeverClaimAutomaton::Cstr, NeverClaimAutomaton::Cstr*,
less<NeverClaimAutomaton::Cstr>,
ALLOC(NeverClaimAutomaton::Cstr*) >&
inline const multimap<NeverClaimAutomaton::Cstr, NeverClaimAutomaton::Cstr*>&
NeverClaimAutomaton::StateInfo::transitions() const
/* ----------------------------------------------------------------------------
*

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,10 +17,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef __GNUC__
#pragma implementation
#endif /* __GNUC__ */
#include <config.h>
#include <deque>
#include <stack>
@ -53,9 +49,8 @@ void PathEvaluator::reset()
current_loop_state = 0;
path_states.clear();
for (map<const LtlFormula*, BitArray*, LtlFormula::ptr_less,
ALLOC(BitArray*) >::iterator it
= eval_info.begin();
for (map<const LtlFormula*, BitArray*, LtlFormula::ptr_less>::iterator
it = eval_info.begin();
it != eval_info.end();
++it)
delete it->second;
@ -65,26 +60,25 @@ void PathEvaluator::reset()
/* ========================================================================= */
bool PathEvaluator::evaluate
(const LtlFormula& formula, const StateSpace& statespace,
const vector<StateSpace::size_type, ALLOC(StateSpace::size_type) >&
states_on_path,
StateSpace::size_type loop_state)
(const LtlFormula& formula, const StateSpace::Path& prefix,
const StateSpace::Path& cycle, const StateSpace& statespace)
/* ----------------------------------------------------------------------------
*
* Description: Evaluates an LTL formula in a state space in which the states
* are connected into a non-branching sequence that ends in a
* loop.
* Description: Evaluates an LTL formula in a path formed from a prefix and
* an infinitely repeating cycle of states in a state space.
*
* Arguments: formula -- Formula to be evaluated.
* statespace -- State space from which the path is
* extracted.
* states_on_path -- Mapping between states in the path and
* the states in `statespace' such that
* `statespace[states_on_path[i]]'
* corresponds to the ith state of the path.
* loop_state -- Number of the state in the path to which
* the ``last'' state of the path is
* connected.
* Arguments: formula -- Formula to be evaluated.
* prefix -- A StateSpace::Path object corresponding to
* the prefix of the path. Only the state
* identifiers in the path elements are used;
* the function will not require `prefix' to
* actually represent a path in `statespace'.
* cycle -- A StateSpace::Path object corresponding to
* the infinitely repeating cycle. Only the
* state identifiers in the path elements are
* relevant.
* statespace -- State space to which the state identifiers in
* `path' and `cycle' refer.
*
* Returns: `true' if and only if the LTL formula holds in the path.
*
@ -92,13 +86,21 @@ bool PathEvaluator::evaluate
{
reset();
if (states_on_path.empty() || loop_state >= states_on_path.size())
if (cycle.empty())
return false;
current_formula = &formula;
current_path = &statespace;
current_loop_state = loop_state;
path_states = states_on_path;
current_loop_state = prefix.size();
path_states.reserve(prefix.size() + cycle.size());
for (StateSpace::Path::const_iterator state = prefix.begin();
state != prefix.end();
++state)
path_states.push_back(state->node());
for (StateSpace::Path::const_iterator state = cycle.begin();
state != cycle.end();
++state)
path_states.push_back(state->node());
return eval();
}
@ -128,8 +130,7 @@ bool PathEvaluator::evaluate
current_formula = &formula;
current_path = &statespace;
map<StateSpace::size_type, StateSpace::size_type,
less<StateSpace::size_type>, ALLOC(StateSpace::size_type) > ordering;
map<StateSpace::size_type, StateSpace::size_type> ordering;
StateSpace::size_type state = statespace.initialState();
StateSpace::size_type state_count = 0;
@ -173,9 +174,7 @@ bool PathEvaluator::eval()
*
* ------------------------------------------------------------------------- */
{
stack<const LtlFormula*, deque<const LtlFormula*,
ALLOC(const LtlFormula*) > >
subformula_stack;
stack<const LtlFormula*, deque<const LtlFormula*> > subformula_stack;
const LtlFormula* f;
BitArray* val;

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -54,11 +54,11 @@ public:
bool evaluate /* Tests whether an */
(const LtlFormula& formula, /* LtlFormula holds in a */
const StateSpace& statespace, /* state space. */
const vector<StateSpace::size_type,
ALLOC(StateSpace::size_type) >&
states_on_path,
StateSpace::size_type loop_state);
const StateSpace::Path& prefix, /* path described by a */
const StateSpace::Path& cycle, /* prefix and a cycle of */
const StateSpace& statespace); /* states from a state
* space.
*/
bool evaluate /* Same as above. */
(const LtlFormula& formula,
@ -105,15 +105,15 @@ private:
* the current path.
*/
vector<StateSpace::size_type, /* Correspondence */
ALLOC(StateSpace::size_type) > /* between states of the */
path_states; /* path and the states
vector<StateSpace::size_type> path_states; /* Correspondence
* between states of the
* path and the states
* of the current state
* space.
*/
map<const LtlFormula*, BitArray*, /* Information about the */
LtlFormula::ptr_less, ALLOC(BitArray*) > /* truth values of the */
LtlFormula::ptr_less> /* truth values of the */
eval_info; /* subformulae of the
* formula to be
* evaluated.

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,10 +17,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef __GNUC__
#pragma implementation
#endif /* __GNUC__ */
#include <config.h>
#include "BitArray.h"
#include "PathIterator.h"

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -20,10 +20,6 @@
#ifndef PATHITERATOR_H
#define PATHITERATOR_H
#ifdef __GNUC__
#pragma interface
#endif /* __GNUC__ */
#include <config.h>
#include "StateSpace.h"

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -393,8 +393,8 @@ public:
typedef ProductEdgeCollection EdgeContainerType; /* required for making */
/* Product<Operations> */
struct PathElement; /* suitable for */
typedef deque<PathElement, ALLOC(PathElement) > /* instantiating the */
Path; /* SccCollection
typedef deque<PathElement> Path; /* instantiating the
* SccCollection
* template (see
* SccCollection.h).
*/
@ -419,9 +419,7 @@ private:
Graph<GraphEdgeContainer>::Path >& cycle, /* segment of the cycle */
size_type source_state_id, Edge transition, /* in a witness for the */
const size_type root_id, /* nonemptiness of the */
const map<size_type, PathElement, /* product. */
less<size_type>,
ALLOC(PathElement) >&
const map<size_type, PathElement>& /* product. */
predecessor) const;
Operations operations; /* Operations for
@ -524,8 +522,8 @@ public:
*/
private:
const Graph<GraphEdgeContainer>::Edge* edge_1; /* Components of the */
const Graph<GraphEdgeContainer>::Edge* edge_2; /* transition. */
GraphEdgeContainer::const_iterator edge_1; /* Components of the */
GraphEdgeContainer::const_iterator edge_2; /* transition. */
};
@ -655,9 +653,10 @@ protected:
* acceptance sets.
*/
typedef deque<AcceptanceStackElement, /* Stack formed from */
ALLOC(AcceptanceStackElement) > /* the above */
AcceptanceStack; /* associations. */
typedef deque<AcceptanceStackElement> /* Stack formed from */
AcceptanceStack; /* the above
* associations.
*/
AcceptanceStack acceptance_stack; /* Stack for storing the
* dfs numbers of roots
@ -877,9 +876,9 @@ private:
* reachable.
*/
set<size_type, less<size_type>, /* Set of states from */
ALLOC(size_type) > /* which an accepting */
reachability_info; /* component is known to
set<size_type> reachability_info; /* Set of states from
* which an accepting
* component is known to
* be reachable in the
* product.
*/
@ -928,9 +927,9 @@ public:
~AcceptingComponentFinder(); /* Destructor. */
typedef set<size_type, less<size_type>, /* Type definition for */
ALLOC(size_type) > /* the set of product */
SccType; /* state identifiers in
typedef set<size_type> SccType; /* Type definition for
* the set of product
* state identifiers in
* an accepting
* strongly connected
* component.
@ -1369,10 +1368,9 @@ void Product<Operations>::findWitness
unsigned long int number_of_collected_acceptance_sets
= collected_acceptance_sets.count(number_of_acceptance_sets);
deque<size_type, ALLOC(size_type) > search_queue;
set<size_type, less<size_type>, ALLOC(size_type) > visited;
map<size_type, PathElement, less<size_type>, ALLOC(PathElement) >
shortest_path_predecessor;
deque<size_type> search_queue;
set<size_type> visited;
map<size_type, PathElement> shortest_path_predecessor;
size_type bfs_root = search_start_state;
@ -1475,8 +1473,7 @@ void Product<Operations>::addCycleSegment
(pair<Graph<GraphEdgeContainer>::Path, Graph<GraphEdgeContainer>::Path>&
cycle,
size_type source_state_id, Edge transition, const size_type root_id,
const map<size_type, PathElement, less<size_type>, ALLOC(PathElement) >&
predecessor) const
const map<size_type, PathElement>& predecessor) const
/* ----------------------------------------------------------------------------
*
* Description: Helper function for constructing a segment of an accepting
@ -1598,7 +1595,7 @@ template <class Operations>
inline Product<Operations>::ProductEdge::ProductEdge
(const GraphEdgeContainer::const_iterator& e1,
const GraphEdgeContainer::const_iterator& e2)
: edge_1(*e1), edge_2(*e2)
: edge_1(e1), edge_2(e2)
/* ----------------------------------------------------------------------------
*
* Description: Constructor for class Product<Operations>::ProductEdge.
@ -1643,7 +1640,7 @@ Product<Operations>::ProductEdge::firstComponent() const
*
* ------------------------------------------------------------------------- */
{
return *edge_1;
return **edge_1;
}
/* ========================================================================= */
@ -1662,7 +1659,7 @@ Product<Operations>::ProductEdge::secondComponent() const
*
* ------------------------------------------------------------------------- */
{
return *edge_2;
return **edge_2;
}
/* ========================================================================= */
@ -1679,7 +1676,7 @@ Product<Operations>::ProductEdge::targetNode() const
*
* ------------------------------------------------------------------------- */
{
return product->stateId(edge_1->targetNode(), edge_2->targetNode());
return product->stateId((*edge_1)->targetNode(), (*edge_2)->targetNode());
}

1063
lbtt/src/ProductAutomaton.cc Normal file

File diff suppressed because it is too large Load diff

596
lbtt/src/ProductAutomaton.h Normal file
View file

@ -0,0 +1,596 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
*
* This program 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.
*
* 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 PRODUCTAUTOMATON_H
#define PRODUCTAUTOMATON_H
#include <config.h>
#include <deque>
#include <iostream>
#include <vector>
#include "LbttAlloc.h"
#include "BitArray.h"
#include "BuchiAutomaton.h"
#include "EdgeContainer.h"
#include "Exception.h"
#include "Graph.h"
#include "StateSpace.h"
using namespace std;
extern bool user_break;
namespace UserCommands
{
extern void printAutomatonAnalysisResults
(ostream&, int, unsigned long int, unsigned long int);
}
namespace Graph
{
/******************************************************************************
*
* A class for representing the synchronous product of a Büchi automaton and
* a state space.
*
*****************************************************************************/
class ProductAutomaton : public Graph<GraphEdgeContainer>
{
private:
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
class ProductState : /* A class for */
public Graph<GraphEdgeContainer>::Node /* representing the */
{ /* states of the product
* automaton.
*/
public:
explicit ProductState /* Constructor. */
(const size_type hash_val = 0);
~ProductState(); /* Destructor. */
/* `edges' inherited from Graph<GraphEdgeContainer>::Node */
size_type hashValue() const; /* Get or set the hash */
size_type& hashValue(); /* value for the product
* state (this value can
* be used to extract
* the identifiers of
* the original state
* space and the Büchi
* automaton with which
* the product state is
* associated).
*/
void print /* Writes information */
(ostream& stream = cout, /* about the product */
const int indent = 0, /* state to a stream. */
const GraphOutputFormat fmt = NORMAL) const;
private:
friend class ProductAutomaton;
ProductState(const ProductState&); /* Prevent copying and */
ProductState& operator=(const ProductState&); /* assignment of
* ProductState objects.
*/
size_type hash_value; /* Hash value for the
* product state (can be
* used to extract the
* identifiers of the
* original state space and
* the Büchi automaton with
* which the product state
* is associated).
*/
Edge* incoming_edge; /* The unique edge pointing
* to `this' ProductState.
*/
};
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
class ProductScc : /* A class for storing */
public vector<ProductAutomaton::size_type, /* maximal strongly */
ALLOC(ProductAutomaton::size_type) > /* connected components */
{ /* of the product.
*/
public:
ProductScc(); /* Constructor. */
/* default copy constructor */
~ProductScc(); /* Destructor. */
/* default assignment operator */
bool fair /* Tests whether the */
(const ProductAutomaton& product_automaton) /* component is fair, */
const; /* i.e. it is a
* nontrivial component
* with a state from
* each acceptance set
* of the Büchi
* automaton used for
* constructing a
* given product.
*/
void insert /* Inserts a state into */
(const ProductAutomaton::size_type /* the container. */
product_state);
};
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
public:
class ProductSizeException; /* An exception class for
* reporting the situation
* where the size of the
* product automaton may
* be too big.
*/
friend class ProductScc;
friend void UserCommands::printAutomatonAnalysisResults
(ostream&, int, unsigned long int, unsigned long int);
ProductAutomaton(); /* Constructor. */
~ProductAutomaton(); /* Destructor. */
ProductState& operator[](const size_type index) /* Indexing operator. No */
const; /* range check is performed
* on the argument.
*/
ProductState& node(const size_type index) const; /* Synonym for the indexing
* operator. This function
* also checks the range of
* the argument.
*/
/* `size' inherited from Graph<GraphEdgeContainer> */
/* `empty' inherited from Graph<GraphEdgeContainer> */
void clear(); /* Makes the automaton
* empty.
*/
void connect /* Connects two states */
(const size_type father, /* of the product */
const size_type child); /* automaton. */
void disconnect /* Disconnects two */
(const size_type father, /* states of the product */
const size_type child); /* automaton. */
/* `connected' inherited from Graph<GraphEdgeContainer> */
/* `stats' inherited from Graph<GraphEdgeContainer> */
/* `subgraphStats' inherited from Graph<GraphEdgeContainer> */
void computeProduct /* Function for */
(const BuchiAutomaton& automaton, /* initializing the */
const StateSpace& statespace, /* product automaton. */
const bool global_product);
StateSpace::size_type systemState /* Returns the */
(const size_type state) const; /* identifier of the
* state of the original
* state space with
* which a given product
* state is associated.
*/
BuchiAutomaton::size_type buchiState /* Returns the */
(const size_type state) const; /* identifier of the
* state of the original
* automaton with which
* a given product state
* is associated.
*/
void emptinessCheck(Bitset& result) const; /* Performs an emptiness
* check on the product.
*/
void findAcceptingExecution /* Extracts an accepting */
(const StateSpace::size_type initial_state, /* execution from the */
pair<deque<StateIdPair, ALLOC(StateIdPair) >, /* product automaton. */
deque<StateIdPair,
ALLOC(StateIdPair) > >&
execution) const;
void print /* Writes information */
(ostream& stream = cout, /* about the product */
const int indent = 0, /* automaton to a */
const GraphOutputFormat fmt = NORMAL) const; /* stream. */
private:
ProductAutomaton(const ProductAutomaton&); /* Prevent copying and */
ProductAutomaton& operator= /* assignment of */
(const ProductAutomaton&); /* ProductAutomaton
* objects.
*/
size_type expand(size_type node_count = 1); /* Inserts states to the
* product automaton.
*/
const BuchiAutomaton* buchi_automaton; /* A pointer to the
* Büchi automaton used for
* constructing the
* product.
*/
StateSpace::size_type statespace_size; /* Size of the state space
* used for constructing
* the product automaton.
*/
#ifdef HAVE_OBSTACK_H /* Storage for product */
ObstackAllocator store; /* states and */
#endif /* HAVE_OBSTACK_H */ /* transitions. */
};
/******************************************************************************
*
* An exception class for reporting the situation where the product may be too
* big to compute.
*
*****************************************************************************/
class ProductAutomaton::ProductSizeException : public Exception
{
public:
ProductSizeException(); /* Constructor. */
/* default copy constructor */
~ProductSizeException() throw(); /* Destructor. */
ProductSizeException& /* Assignment operator. */
operator=(const ProductSizeException& e);
/* `what' inherited from class Exception */
};
/******************************************************************************
*
* Inline function definitions for class ProductAutomaton.
*
*****************************************************************************/
/* ========================================================================= */
inline ProductAutomaton::ProductAutomaton() :
buchi_automaton(0), statespace_size(0)
#ifdef HAVE_OBSTACK_H
, store()
#endif /* HAVE_OBSTACK_H */
/* ----------------------------------------------------------------------------
*
* Description: Constructor for class ProductAutomaton. Initializes a
* new object for storing the product of a Büchi automaton and a
* state space. The product must then be explicitly initialized
* by calling the function `computeProduct' on the object.
*
* Arguments: None.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
}
/* ========================================================================= */
inline ProductAutomaton::~ProductAutomaton()
/* ----------------------------------------------------------------------------
*
* Description: Destructor for class ProductAutomaton.
*
* Arguments: None.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
clear();
}
/* ========================================================================= */
inline ProductAutomaton::ProductState&
ProductAutomaton::operator[](const size_type index) const
/* ----------------------------------------------------------------------------
*
* Description: Indexing operator for class ProductAutomaton. Can be used to
* refer to the individual states of the product automaton. No
* range check will be performed on the argument.
*
* Argument: index -- Index of a state of the product automaton.
*
* Returns: A reference to the product state corresponding to the index.
*
* ------------------------------------------------------------------------- */
{
return static_cast<ProductState&>(*nodes[index]);
}
/* ========================================================================= */
inline ProductAutomaton::ProductState&
ProductAutomaton::node(const size_type index) const
/* ----------------------------------------------------------------------------
*
* Description: Function for referring to a single state of a
* ProductAutomaton. This function will also check the range
* argument.
*
* Argument: index -- Index of a state of the product automaton.
*
* Returns: A reference to the corresponding product state.
*
* ------------------------------------------------------------------------- */
{
return static_cast<ProductState&>(Graph<GraphEdgeContainer>::node(index));
}
/* ========================================================================= */
inline StateSpace::size_type ProductAutomaton::systemState
(const size_type state) const
/* ----------------------------------------------------------------------------
*
* Description: Returns the identifier of the system state with which a
* given product state is associated. This function will perform
* no range checks on its argument.
*
* Argument: state -- Identifier of a product state.
*
* Returns: Identifier of a state in a state space.
*
* ------------------------------------------------------------------------- */
{
return operator[](state).hashValue() % statespace_size;
}
/* ========================================================================= */
inline StateSpace::size_type ProductAutomaton::buchiState
(const size_type state) const
/* ----------------------------------------------------------------------------
*
* Description: Returns the identifier of the state of the Büchi automaton
* with which a given product state is associated. This function
* will perform no range checks on its argument.
*
* Argument: state -- Identifier of a product state.
*
* Returns: Identifier of a state in a Büchi automaton.
*
* ------------------------------------------------------------------------- */
{
return operator[](state).hashValue() / statespace_size;
}
/******************************************************************************
*
* Inline function definitions for class ProductAutomaton::ProductState.
*
*****************************************************************************/
/* ========================================================================= */
inline ProductAutomaton::ProductState::ProductState(const size_type hash_val) :
Graph<GraphEdgeContainer>::Node(), hash_value(hash_val), incoming_edge(0)
/* ----------------------------------------------------------------------------
*
* Description: Constructor for class ProductAutomaton::ProductState. Creates
* a new object representing a synchronous product of a state of
* a Büchi automaton with a state of a state space.
*
* Arguments: hash_val -- Hash value for the product state.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
}
/* ========================================================================= */
inline ProductAutomaton::ProductState::~ProductState()
/* ----------------------------------------------------------------------------
*
* Description: Destructor for class ProductAutomaton::ProductState.
*
* Arguments: None.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
if (incoming_edge != 0)
{
#ifdef HAVE_OBSTACK_H
incoming_edge->~Edge();
#else
delete incoming_edge;
#endif /* HAVE_OBSTACK_H */
}
outgoing_edges.clear();
}
/* ========================================================================= */
inline ProductAutomaton::size_type ProductAutomaton::ProductState::hashValue()
const
/* ----------------------------------------------------------------------------
*
* Description: Returns the product state's hash value by value.
*
* Arguments: None.
*
* Returns: The hash value of the product state.
*
* ------------------------------------------------------------------------- */
{
return hash_value;
}
/* ========================================================================= */
inline ProductAutomaton::size_type& ProductAutomaton::ProductState::hashValue()
/* ----------------------------------------------------------------------------
*
* Description: Returns the product state's hash value by reference. (This
* function can therefore be used to change the value.)
*
* Arguments: None.
*
* Returns: A reference to the hash value of the product state.
*
* ------------------------------------------------------------------------- */
{
return hash_value;
}
/******************************************************************************
*
* Inline function definitions for class ProductAutomaton::ProductScc.
*
*****************************************************************************/
/* ========================================================================= */
inline ProductAutomaton::ProductScc::ProductScc()
/* ----------------------------------------------------------------------------
*
* Description: Constructor for class ProductAutomaton::ProductScc. Creates a
* new container for storing a maximal strongly connected
* component of a ProductAutomaton.
*
* Arguments: None.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
}
/* ========================================================================= */
inline ProductAutomaton::ProductScc::~ProductScc()
/* ----------------------------------------------------------------------------
*
* Description: Destructor for class ProductAutomaton::ProductScc.
*
* Arguments: None.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
}
/* ========================================================================= */
inline void ProductAutomaton::ProductScc::insert
(const ProductAutomaton::size_type product_state)
/* ----------------------------------------------------------------------------
*
* Description: Inserts a new product state identifier to the container.
*
* Argument: product_state -- Identifier of a product state.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
push_back(product_state);
}
/******************************************************************************
*
* Inline function definitions for class
* ProductAutomaton::ProductSizeException.
*
*****************************************************************************/
/* ========================================================================= */
inline ProductAutomaton::ProductSizeException::ProductSizeException() :
Exception("product may be too large")
/* ----------------------------------------------------------------------------
*
* Description: Constructor for class ProductAutomaton::ProductSizeException.
*
* Arguments: None.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
}
/* ========================================================================= */
inline ProductAutomaton::ProductSizeException::~ProductSizeException() throw()
/* ----------------------------------------------------------------------------
*
* Description: Destructor for class ProductAutomaton::ProductSizeException.
*
* Arguments: None.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
}
/* ========================================================================= */
inline ProductAutomaton::ProductSizeException&
ProductAutomaton::ProductSizeException::operator=
(const ProductAutomaton::ProductSizeException& e)
/* ----------------------------------------------------------------------------
*
* Description: Assignment operator for class
* ProductAutomaton::ProductSizeException. Assigns the value of
* another ProductAutomaton::ProductSizeException to `this' one.
*
* Arguments: e -- A reference to a constant
* ProductAutomaton::ProductSizeException.
*
* Returns: A reference to the object whose value was changed.
*
* ------------------------------------------------------------------------- */
{
Exception::operator=(e);
return *this;
}
}
#endif /* !PRODUCTAUTOMATON_H */

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -195,10 +195,8 @@ public:
/* default assignment operator */
typedef set<typename GraphType::size_type, /* Type definition for */
less<typename GraphType::size_type>, /* a set of node id's. */
ALLOC(typename GraphType::size_type) >
SccType;
typedef set<typename GraphType::size_type> /* Type definition for */
SccType; /* a set of node id's. */
const SccType& operator()() const; /* Returns the set of node
* identifiers in a
@ -338,10 +336,10 @@ public:
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
typedef map<typename GraphType::size_type, /* Type definition for a */
typename GraphType::size_type, /* mapping between node */
less<typename GraphType::size_type>, /* identifiers and the */
ALLOC(typename GraphType::size_type) >/* order in which they */
DfsOrdering; /* were encountered in
typename GraphType::size_type> /* mapping between node */
DfsOrdering; /* identifiers and the
* order in which they
* were encountered in
* the search for
* strongly connected
* components.
@ -433,18 +431,19 @@ public:
typename GraphType::size_type lowlink;
};
deque<NodeStackElement, /* Depth-first search */
ALLOC(NodeStackElement) > /* backtracking stack. */
node_stack;
deque<NodeStackElement> node_stack; /* Depth-first search
* backtracking stack.
*/
NodeStackElement* current_node; /* Pointer to the top
* element of the
* backtracking stack.
*/
deque<typename GraphType::size_type, /* Stack used for */
ALLOC(typename GraphType::size_type) > /* collecting the nodes */
scc_stack; /* in a strongly
deque<typename GraphType::size_type> scc_stack; /* Stack used for
* collecting the nodes
* in a strongly
* connected component,
* excluding the root
* nodes of the
@ -998,8 +997,7 @@ void SccCollection<GraphType, NodeVisitor>::iterator::getPath
* when exiting from this function).
*/
typename deque<NodeStackElement, ALLOC(NodeStackElement) >::const_iterator
n = node_stack.begin();
typename deque<NodeStackElement>::const_iterator n = node_stack.begin();
if (n != node_stack.end())
{
for (++n; n != node_stack.end(); ++n)

752
lbtt/src/SccIterator.h Normal file
View file

@ -0,0 +1,752 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
*
* This program 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.
*
* 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 SCCITERATOR_H
#define SCCITERATOR_H
#include <config.h>
#include <deque>
#include <set>
#include <stack>
#include <vector>
#include "LbttAlloc.h"
#include "Graph.h"
using namespace std;
namespace Graph
{
/******************************************************************************
*
* A template iterator class for computing the maximal strongly connected
* components of a graph represented as an object of class
* Graph<EdgeContainer>.
*
* The iterator class has three template arguments:
* class EdgeContainer -- Container class storing the edges in the
* graph with which the iterator is associated.
*
* class SccContainer -- Container for storing the identifiers of the
* nodes belonging to some maximal strongly
* connected component. The container class
* must be able to store elements of type
* Graph<EdgeContainer>::size_type. The container
* class interface must support the following
* operations:
*
* Default constructor which can be called
* without any arguments
* Copy constructor
* Assignment operator
* clear()
* [makes the container empty]
* insert(Graph<EdgeContainer>::size_type s)
* [inserts an element into the
* container]
*
* If the container class is left unspecified,
* it defaults to
* set<Graph<EdgeContainer>::size_type,
* less<Graph<EdgeContainer>::size_type>,
* ALLOC(Graph<EdgeContainer>::size_type)>.
*
* class Filter -- Class for representing function objects that
* can be used to restrict the iterator
* dereferencing operators to return only
* those nodes of a strongly connected component
* which satisfy a certain condition that can be
* tested using Filter::operator(). This function
* has to accept a single parameter of type
* Graph<EdgeContainer>::Node*. It must return a
* Boolean value. The nodes for which the
* function returns `false' will then not be
* included in the collection of nodes returned
* by the iterator dereferencing operators.
*
* If the Filter class is left unspecified, it
* defaults to the NullSccFilter<EdgeContainer>
* class, which does not restrict the set of
* nodes in any way.
*
*****************************************************************************/
template<class EdgeContainer>
class NullSccFilter;
template<class EdgeContainer,
class SccContainer
= set<typename Graph<EdgeContainer>::size_type,
less<typename Graph<EdgeContainer>::size_type>,
ALLOC(typename Graph<EdgeContainer>::size_type) >,
class Filter = NullSccFilter<EdgeContainer> >
class SccIterator
{
public:
SccIterator(const Graph<EdgeContainer>& g); /* Constructor. */
/* default copy constructor */
~SccIterator(); /* Destructor. */
/* default assignment operator */
bool operator== /* Equality test for */
(const SccIterator<EdgeContainer, /* two iterators. */
SccContainer,
Filter>& it) const;
bool operator!= /* Inequality test for */
(const SccIterator<EdgeContainer, /* two iterators. */
SccContainer,
Filter>& it) const;
bool operator< /* `Less than' relation */
(const SccIterator<EdgeContainer, /* between two */
SccContainer, /* iterators. */
Filter>& it) const;
bool operator<= /* `Less than or equal' */
(const SccIterator<EdgeContainer, /* relation between two */
SccContainer, /* iterators. */
Filter>& it) const;
bool operator> /* `Greater than' */
(const SccIterator<EdgeContainer, /* relation between two */
SccContainer, /* iterators. */
Filter>& it) const;
bool operator>= /* `Greater than or */
(const SccIterator<EdgeContainer, /* equal' relation */
SccContainer, /* between two */
Filter>& it) const; /* iterators. */
const SccContainer& operator*() const; /* Dereferencing */
const SccContainer* operator->() const; /* operators. */
const SccContainer& operator++(); /* Prefix and postfix */
const SccContainer operator++(int); /* increment operators. */
bool atEnd() const; /* Tests whether the
* iterator has scanned
* through all the
* strongly connected
* components of the
* graph.
*/
private:
const Graph<EdgeContainer>& graph; /* Reference to the graph
* with which the iterator
* is associated.
*/
typename Graph<EdgeContainer>::size_type /* Number of graph */
dfs_number; /* nodes processed by
* the iterator.
*/
vector<typename Graph<EdgeContainer>::size_type, /* dfs_ordering[i] */
ALLOC(typename Graph<EdgeContainer> /* indicates the */
::size_type) > /* position of graph */
dfs_ordering; /* node i in the depth-
* first search order.
* (If the node has not
* yet been visited,
* dfs_ordering[i]==0.)
*/
vector<typename Graph<EdgeContainer>::size_type, /* lowlink[i] indicates */
ALLOC(typename Graph<EdgeContainer> /* the least graph node */
::size_type) > /* (in the depth-first */
lowlink; /* search order) that
* is reachable from
* graph node i and
* does not belong to
* any strongly
* connected component
* which has already been
* processed.
*/
typedef pair<typename Graph<EdgeContainer>::size_type,
typename EdgeContainer::const_iterator>
NodeStackElement;
stack<NodeStackElement, /* Depth-first search */
deque<NodeStackElement, /* backtracking stack. */
ALLOC(NodeStackElement) > >
node_stack;
typename Graph<EdgeContainer>::size_type /* Current graph node */
current_node; /* the depth-first
* search.
*/
typename EdgeContainer::const_iterator edge; /* Iterator to scan
* through the successors
* of the current node.
*/
stack<typename Graph<EdgeContainer>::size_type, /* Stack used for */
deque<typename Graph<EdgeContainer> /* collecting the nodes */
::size_type, /* in a strongly */
ALLOC(typename Graph<EdgeContainer> /* connected component. */
::size_type)
>
>
scc_stack;
SccContainer current_scc; /* Container of nodes
* forming the maximal
* strongly connected
* graph component
* currently `pointed to'
* by the iterator.
*/
Filter cond; /* Function object for
* filtering out a subset
* of nodes in the
* strongly connected
* components.
*/
void reset(); /* Initializes the
* iterator to point to
* the first strongly
* connected component of
* the graph.
*/
void computeNextScc(); /* Updates the iterator to
* point to the next
* strongly connected
* component.
*/
};
/******************************************************************************
*
* Default test for collecting the nodes in a strongly connected component.
* (See documentation on class SccIterator for information about the purpose
* of the class.)
*
*****************************************************************************/
template<class EdgeContainer>
class NullSccFilter
{
public:
bool operator()(const typename Graph<EdgeContainer>::Node*) const;
};
/******************************************************************************
*
* Inline function definitions for template class
* SccIterator<EdgeContainer, SccContainer, Filter>.
*
*****************************************************************************/
/* ========================================================================= */
template<class EdgeContainer, class SccContainer, class Filter>
inline SccIterator<EdgeContainer, SccContainer, Filter>::SccIterator
(const Graph<EdgeContainer>& g) :
graph(g), dfs_ordering(graph.size()), lowlink(graph.size())
/* ----------------------------------------------------------------------------
*
* Description: Constructor for class
* SccIterator<EdgeContainer, SccContainer, Filter>.
* Initializes a new iterator for scanning the maximal strongly
* connected components of a graph.
*
* Arguments: g -- The graph with which the iterator is to be associated
* (a Graph<EdgeContainer> object).
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
reset();
computeNextScc();
}
/* ========================================================================= */
template<class EdgeContainer, class SccContainer, class Filter>
inline SccIterator<EdgeContainer, SccContainer, Filter>::~SccIterator()
/* ----------------------------------------------------------------------------
*
* Description: Destructor for class
* SccIterator<EdgeContainer, SccContainer, Filter>.
*
* Arguments: None.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
}
/* ========================================================================= */
template<class EdgeContainer, class SccContainer, class Filter>
inline bool SccIterator<EdgeContainer, SccContainer, Filter>::operator==
(const SccIterator<EdgeContainer, SccContainer, Filter>& it) const
/* ----------------------------------------------------------------------------
*
* Description: Equality test for two SccIterators. Two SccIterators are
* `equal' if and only if both of them are associated with
* exactly the same graph object in memory and the iterators
* have processed the same amount of graph nodes.
*
* Arguments: it -- A constant reference to another SccIterator.
*
* Returns: A truth value according to the result of the equality test.
*
* ------------------------------------------------------------------------- */
{
return (&graph == &(it.graph) && dfs_number == it.dfs_number);
}
/* ========================================================================= */
template<class EdgeContainer, class SccContainer, class Filter>
inline bool SccIterator<EdgeContainer, SccContainer, Filter>::operator!=
(const SccIterator<EdgeContainer, SccContainer, Filter>& it) const
/* ----------------------------------------------------------------------------
*
* Description: Inequality test for two SccIterators. Two SccIterators are
* not equal if and only if they are associated with different
* graphs or they are associated with the same graph object in
* memory but the iterators have processed a different number of
* graph nodes.
*
* Arguments: it -- A constant reference to another SccIterator.
*
* Returns: A truth value according to the result of the inequality test.
*
* ------------------------------------------------------------------------- */
{
return (&graph != &(it.graph) || dfs_number != it.dfs_number);
}
/* ========================================================================= */
template<class EdgeContainer, class SccContainer, class Filter>
inline bool SccIterator<EdgeContainer, SccContainer, Filter>::operator<
(const SccIterator<EdgeContainer, SccContainer, Filter>& it) const
/* ----------------------------------------------------------------------------
*
* Description: `Less than' relation between two SccIterators. An
* SccIterator is `less than' another if and only if the
* iterators relate to the same graph object in memory and
* the first iterator has processed a smaller number of nodes
* than the second one.
*
* Arguments: it -- A constant reference to another SccIterator.
*
* Returns: A truth value according to the result of the test.
*
* ------------------------------------------------------------------------- */
{
return (&graph == &(it.graph) && dfs_number < it.dfs_number);
}
/* ========================================================================= */
template<class EdgeContainer, class SccContainer, class Filter>
inline bool SccIterator<EdgeContainer, SccContainer, Filter>::operator<=
(const SccIterator<EdgeContainer, SccContainer, Filter>& it) const
/* ----------------------------------------------------------------------------
*
* Description: `Less than or equal' relation between two SccIterators. An
* SccIterator is `less than or equal to' another if and only
* if the iterators relate to the same graph object in memory
* and the first iterator has processed a number of nodes not
* exceeding the number of nodes the second iterator has
* processed.
*
* Arguments: it -- A constant reference to another SccIterator.
*
* Returns: A truth value according to the result of the test.
*
* ------------------------------------------------------------------------- */
{
return (&graph == &(it.graph) && dfs_number <= it.dfs_number);
}
/* ========================================================================= */
template<class EdgeContainer, class SccContainer, class Filter>
inline bool SccIterator<EdgeContainer, SccContainer, Filter>::operator>
(const SccIterator<EdgeContainer, SccContainer, Filter>& it) const
/* ----------------------------------------------------------------------------
*
* Description: `Greater than' relation between two SccIterators. An
* SccIterator is `greater than' another if and only if the
* iterators relate to the same graph object in memory and
* the first iterator has processed a greater number of nodes
* than the second one.
*
* Arguments: it -- A constant reference to another SccIterator.
*
* Returns: A truth value according to the result of the test.
*
* ------------------------------------------------------------------------- */
{
return (&graph == &(it.graph) && dfs_number > it.dfs_number);
}
/* ========================================================================= */
template<class EdgeContainer, class SccContainer, class Filter>
inline bool SccIterator<EdgeContainer, SccContainer, Filter>::operator>=
(const SccIterator<EdgeContainer, SccContainer, Filter>& it) const
/* ----------------------------------------------------------------------------
*
* Description: `Greater than or equal' relation between two SccIterators. An
* SccIterator is `greater than or equal to' another if and
* only if the iterators relate to the same graph object in
* memory and the first iterator has processed at least as many
* nodes as the second iterator has processed.
*
* Arguments: it -- A constant reference to another SccIterator.
*
* Returns: A truth value according to the result of the test.
*
* ------------------------------------------------------------------------- */
{
return (&graph == &(it.graph) && dfs_number >= it.dfs_number);
}
/* ========================================================================= */
template<class EdgeContainer, class SccContainer, class Filter>
inline const SccContainer&
SccIterator<EdgeContainer, SccContainer, Filter>::operator*() const
/* ----------------------------------------------------------------------------
*
* Description: Dereferencing operator for a SccIterator. Returns the
* collection of nodes which belong to the maximal strongly
* connected component that the iterator currently points to.
*
* Arguments: None.
*
* Returns: A collection of nodes representing some maximal strongly
* connected component.
*
* ------------------------------------------------------------------------- */
{
return current_scc;
}
/* ========================================================================= */
template<class EdgeContainer, class SccContainer, class Filter>
inline const SccContainer*
SccIterator<EdgeContainer, SccContainer, Filter>::operator->() const
/* ----------------------------------------------------------------------------
*
* Description: Dereferencing operator for a SccIterator. Returns the
* collection of nodes which belong to the maximal strongly
* connected component that the iterator currently points to.
*
* Arguments: None.
*
* Returns: A collection of nodes representing some maximal strongly
* connected component.
*
* ------------------------------------------------------------------------- */
{
return &current_scc;
}
/* ========================================================================= */
template<class EdgeContainer, class SccContainer, class Filter>
inline const SccContainer&
SccIterator<EdgeContainer, SccContainer, Filter>::operator++()
/* ----------------------------------------------------------------------------
*
* Description: Prefix increment operator for a SccIterator. Computes the
* next maximal strongly connected component of the graph and
* then returns it.
*
* Arguments: None.
*
* Returns: A collection of nodes representing some maximal strongly
* connected component.
*
* ------------------------------------------------------------------------- */
{
computeNextScc();
return current_scc;
}
/* ========================================================================= */
template<class EdgeContainer, class SccContainer, class Filter>
inline const SccContainer
SccIterator<EdgeContainer, SccContainer, Filter>::operator++(int)
/* ----------------------------------------------------------------------------
*
* Description: Postfix increment operator for a SccIterator. Effectively
* returns the maximal strongly connected component of the graph
* currently pointed to by the iterator and then updates the
* iterator to point to the next strongly connected component.
*
* Arguments: None (the `int' is only required to distinguish this operator
* from the prefix increment operator).
*
* Returns: A collection of nodes representing some maximal strongly
* connected component.
*
* ------------------------------------------------------------------------- */
{
SccContainer old_scc = current_scc;
computeNextScc();
return old_scc;
}
/* ========================================================================= */
template<class EdgeContainer, class SccContainer, class Filter>
inline bool SccIterator<EdgeContainer, SccContainer, Filter>::atEnd() const
/* ----------------------------------------------------------------------------
*
* Description: Tells whether there are still more strongly connected
* components in the graph for the iterator to process.
*
* Arguments: None.
*
* Returns: A truth value.
*
* ------------------------------------------------------------------------- */
{
return (current_node == graph.size());
}
/******************************************************************************
*
* Function definitions for template class
* SccIterator<EdgeContainer, SccContainer, Filter>.
*
*****************************************************************************/
/* ========================================================================= */
template<class EdgeContainer, class SccContainer, class Filter>
void SccIterator<EdgeContainer, SccContainer, Filter>::reset()
/* ----------------------------------------------------------------------------
*
* Description: Initializes the iterator to point to the first maximal
* strongly connected component of the graph with which the
* iterator it associated.
*
* Arguments: None.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
dfs_number = 0;
for (typename vector<typename Graph<EdgeContainer>::size_type,
ALLOC(typename Graph<EdgeContainer>::size_type) >
::iterator node = dfs_ordering.begin();
node != dfs_ordering.end();
++node)
*node = 0;
while (!node_stack.empty())
node_stack.pop();
while (!scc_stack.empty())
scc_stack.pop();
current_scc.clear();
}
/* ========================================================================= */
template<class EdgeContainer, class SccContainer, class Filter>
void SccIterator<EdgeContainer, SccContainer, Filter>::computeNextScc()
/* ----------------------------------------------------------------------------
*
* Description: Updates the state of the iterator to `point to' the next
* maximal strongly connected component of the graph, using the
* algorithm due to Tarjan [R. Tarjan. Depth-first search and
* linear graph algorithms. SIAM Journal on Computing,
* 1(2):146--160, June 1972] for computing the next maximal
* strongly connected component of the graph.
*
* Arguments: None.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
current_scc.clear();
if (scc_stack.empty() && node_stack.empty())
{
/*
* If both `scc_stack' and `node_stack' are empty (this holds if we have
* recently finished processing some component of the graph), try to find
* a graph node that has not yet been visited. If no such node is found,
* all nodes have been visited and there are no more strongly connected
* components to be found in the graph.
*/
current_node = 0;
for (typename vector<typename Graph<EdgeContainer>::size_type,
ALLOC(typename Graph<EdgeContainer>::size_type) >
::const_iterator node = dfs_ordering.begin();
node != dfs_ordering.end() && (*node) != 0;
++node)
++current_node;
if (current_node == graph.size())
return;
/*
* Prepare to continue the depth-first search in the unvisited node.
*/
edge = graph[current_node].edges().begin();
scc_stack.push(current_node);
++dfs_number;
dfs_ordering[current_node] = lowlink[current_node] = dfs_number;
}
typename Graph<EdgeContainer>::size_type child_node;
while (1)
{
/*
* If there are still nodes left in the depth-first search backtracking
* stack, pop a node and its next unprocessed outgoing edge off the stack.
* Before continuing the depth-first search in the popped node, update
* its lowlink value if necessary. (This has to be done if the lowlink of
* the current node---a successor of the popped node---is less than the
* lowlink of the popped node but not equal to zero.)
*/
if (!node_stack.empty())
{
typename Graph<EdgeContainer>::size_type father_node
= node_stack.top().first;
edge = node_stack.top().second;
node_stack.pop();
if (lowlink[current_node] < lowlink[father_node]
&& lowlink[current_node] != 0)
lowlink[father_node] = lowlink[current_node];
current_node = father_node;
}
/*
* Scan through the successors of the current node.
*
* If the current nodes has an unvisited successor node (a successor i
* with dfs_ordering[i] == 0), push the current node and its next
* unprocessed edge onto the backtracking stack and then continue the
* search in the successor node. Push also the successor node onto the
* strongly connected component stack.
*
* Otherwise, update the lowlink of the current node to the lowlink of
* its already visited successor if necessary.
*/
while (edge != graph[current_node].edges().end())
{
child_node = (*edge)->targetNode();
++edge;
if (dfs_ordering[child_node] == 0)
{
node_stack.push(make_pair(current_node, edge));
scc_stack.push(child_node);
++dfs_number;
dfs_ordering[child_node] = lowlink[child_node] = dfs_number;
current_node = child_node;
edge = graph[current_node].edges().begin();
}
else if (lowlink[child_node] < lowlink[current_node]
&& lowlink[child_node] != 0)
lowlink[current_node] = lowlink[child_node];
}
/*
* If the least node in the depth-first search order reachable from the
* current node is the current node itself at the end of the previous
* loop, we have found a maximal strongly connected component of the
* graph. In this case, collect the states satisfying `cond' in the
* strongly connected component stack to form the component and exit.
* (Otherwise, return to the start of the outermost while loop and
* continue by popping a state off the depth-first search backtracking
* stack.)
*/
if (dfs_ordering[current_node] == lowlink[current_node])
{
do
{
child_node = scc_stack.top();
scc_stack.pop();
if (cond(&graph[child_node]))
current_scc.insert(child_node);
lowlink[child_node] = 0;
}
while (child_node != current_node);
break;
}
}
}
/******************************************************************************
*
* Inline function definitions for template class NullSccFilter<EdgeContainer>.
*
*****************************************************************************/
/* ========================================================================= */
template<class EdgeContainer>
inline bool NullSccFilter<EdgeContainer>::operator()
(const typename Graph<EdgeContainer>::Node*) const
/* ----------------------------------------------------------------------------
*
* Description: Default test for filtering the nodes in a strongly connected
* graph component. The default is to simply include all nodes
* in the result.
*
* Arguments: A constant pointer to a Graph<EdgeContainer>::Node (required
* only to satisfy the class interface requirements).
*
* Returns: true, so the test will succeed for every node in the
* component.
*
* ------------------------------------------------------------------------- */
{
return true;
}
}
#endif /* !SCCITERATOR_H */

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -42,14 +42,14 @@ extern TestRoundInfo round_info; /* Data structure for
* round.
*/
extern vector<AlgorithmTestResults, /* Test results for each */
ALLOC(AlgorithmTestResults) > /* implementation. */
test_results;
extern vector<TestStatistics, /* Overall test */
ALLOC(TestStatistics) > /* statistics for each */
final_statistics; /* implementation. */
extern vector<AlgorithmTestResults> test_results; /* Test results for each
* implementation.
*/
extern vector<TestStatistics> final_statistics; /* Overall test
* statistics for each
* implementation.
*/
}
#endif /* !SHAREDTESTDATA_H */

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,10 +17,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef __GNUC__
#pragma implementation
#endif /* __GNUC__ */
#include <config.h>
#ifdef HAVE_SSTREAM
#include <sstream>

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -20,10 +20,6 @@
#ifndef SPINWRAPPER_H
#define SPINWRAPPER_H
#ifdef __GNUC__
#pragma interface
#endif /* __GNUC__ */
#include <config.h>
#include <string>
#include "ExternalTranslator.h"

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,14 +17,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef __GNUC__
#pragma implementation
#endif /* __GNUC__ */
#include <config.h>
#include <string>
#include "DispUtil.h"
#include "Exception.h"
#include "IntervalList.h"
#include "SharedTestData.h"
#include "StatDisplay.h"
#include "StringUtil.h"
@ -37,11 +34,51 @@ using namespace ::DispUtil;
using namespace ::SharedTestData;
using namespace ::StringUtil;
/* ========================================================================= */
void printStatTableHeader(ostream& stream, int indent)
/* ----------------------------------------------------------------------------
*
* Description: Displays a table header for test statistics (used in
* verbosity mode 2).
*
* Arguments: stream -- A reference to the output stream to which the
* header should be written.
* indent -- Number of spaces to leave on the left of the
* output.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
Exceptional_ostream estream(&stream, ios::failbit | ios::badbit);
int num_dashes = 39;
estream << string(indent, ' ') + " # F Elapsed Büchi Büchi Acc.";
if (configuration.global_options.do_cons_test
|| configuration.global_options.do_comp_test)
{
num_dashes += 31;
estream << " Product Product Acc.";
if (configuration.global_options.do_cons_test)
{
num_dashes += 3;
estream << " CC";
}
}
estream << '\n' + string(indent + 10, ' ')
+ "time states trans. sets";
if (configuration.global_options.do_cons_test
|| configuration.global_options.do_comp_test)
estream << " states trans. cycles";
estream << "\n" + string(indent, ' ') + string(num_dashes, '-') + '\n';
estream.flush();
}
/* ========================================================================= */
void printBuchiAutomatonStats
(ostream& stream, int indent,
vector<AlgorithmTestResults, ALLOC(AlgorithmTestResults) >::size_type
algorithm,
vector<AlgorithmTestResults>::size_type algorithm,
int result_id)
/* ----------------------------------------------------------------------------
*
@ -52,7 +89,7 @@ void printBuchiAutomatonStats
* Arguments: stream -- A reference to the output stream to which the
* information should be written.
* indent -- Number of spaces to leave on the left of the
* output.
* output in verbosity modes >= 3.
* algorithm -- Identifier of the algorithm used for
* generating the automaton.
* result_id -- Selects between the automata constructed from
@ -67,43 +104,75 @@ void printBuchiAutomatonStats
const AutomatonStats& automaton_stats =
test_results[algorithm].automaton_stats[result_id];
estream << string(indent, ' ');
if (!automaton_stats.buchiAutomatonComputed())
estream << "not computed";
if (configuration.global_options.verbosity <= 2)
{
if (!automaton_stats.buchiAutomatonComputed())
estream << " N/A N/A N/A N/A";
else
{
if (automaton_stats.buchi_generation_time >= 0.0)
{
changeStreamFormatting(stream, 9, 2, ios::fixed | ios::right);
estream << automaton_stats.buchi_generation_time;
restoreStreamFormatting(stream);
}
else
estream << " N/A";
estream << ' ';
changeStreamFormatting(stream, 9, 0, ios::right);
estream << automaton_stats.number_of_buchi_states;
restoreStreamFormatting(stream);
estream << ' ';
changeStreamFormatting(stream, 9, 0, ios::right);
estream << automaton_stats.number_of_buchi_transitions;
restoreStreamFormatting(stream);
estream << ' ';
changeStreamFormatting(stream, 4, 0, ios::right);
estream << automaton_stats.number_of_acceptance_sets;
restoreStreamFormatting(stream);
}
estream << ' ';
}
else
{
estream << "number of states:" + string(6, ' ')
+ toString(automaton_stats.number_of_buchi_states)
+ '\n' + string(indent, ' ') + "number of transitions: "
+ toString(automaton_stats.number_of_buchi_transitions)
+ '\n' + string(indent, ' ') + "acceptance sets:"
+ string(7, ' ')
+ toString(automaton_stats.number_of_acceptance_sets)
+ '\n' + string(indent, ' ') + "computation time:"
+ string(6, ' ');
if (automaton_stats.buchi_generation_time != -1.0)
{
changeStreamFormatting(stream, 9, 2, ios::fixed | ios::left);
estream << automaton_stats.buchi_generation_time;
restoreStreamFormatting(stream);
estream << string(indent, ' ');
estream << " seconds (user time)";
}
if (!automaton_stats.buchiAutomatonComputed())
estream << "not computed";
else
estream << "N/A";
{
estream << "number of states:" + string(6, ' ')
+ toString(automaton_stats.number_of_buchi_states)
+ '\n' + string(indent, ' ') + "number of transitions: "
+ toString(automaton_stats.number_of_buchi_transitions)
+ '\n' + string(indent, ' ') + "acceptance sets:"
+ string(7, ' ')
+ toString(automaton_stats.number_of_acceptance_sets)
+ '\n' + string(indent, ' ') + "computation time:"
+ string(6, ' ');
if (automaton_stats.buchi_generation_time != -1.0)
{
changeStreamFormatting(stream, 9, 2, ios::fixed | ios::left);
estream << automaton_stats.buchi_generation_time;
restoreStreamFormatting(stream);
estream << " seconds (user time)";
}
else
estream << "N/A";
}
estream << '\n';
}
estream << '\n';
estream.flush();
}
/* ========================================================================= */
void printProductAutomatonStats
(ostream& stream, int indent,
vector<AlgorithmTestResults, ALLOC(AlgorithmTestResults) >::size_type
algorithm,
vector<AlgorithmTestResults>::size_type algorithm,
int result_id)
/* ----------------------------------------------------------------------------
*
@ -114,7 +183,7 @@ void printProductAutomatonStats
* Arguments: stream -- A reference to the output stream to which the
* information should be written.
* indent -- Number of spaces to leave on the left of the
* output.
* output in verbosity modes >= 3.
* algorithm -- Identifier of the algorithm used for
* generating the product automaton.
* result_id -- Selects between the automata constructed from
@ -129,51 +198,71 @@ void printProductAutomatonStats
const AutomatonStats& automaton_stats =
test_results[algorithm].automaton_stats[result_id];
estream << string(indent, ' ');
if (!automaton_stats.productAutomatonComputed())
estream << "not computed";
if (configuration.global_options.verbosity <= 2)
{
if (!automaton_stats.productAutomatonComputed())
estream << " N/A N/A";
else
{
changeStreamFormatting(stream, 11, 0, ios::right);
estream << automaton_stats.number_of_product_states;
restoreStreamFormatting(stream);
estream << ' ';
changeStreamFormatting(stream, 11, 0, ios::right);
estream << automaton_stats.number_of_product_transitions;
restoreStreamFormatting(stream);
}
estream << ' ';
}
else
{
estream << "number of states:" + string(6, ' ');
estream << string(indent, ' ');
changeStreamFormatting(stream, 9, 0, ios::left);
estream << automaton_stats.number_of_product_states;
restoreStreamFormatting(stream);
estream << " [";
if (automaton_stats.number_of_product_states != 0)
if (!automaton_stats.productAutomatonComputed())
estream << "not computed";
else
{
changeStreamFormatting(stream, 0, 2, ios::fixed);
estream << static_cast<double>
(automaton_stats.number_of_product_states)
/ static_cast<double>(automaton_stats.number_of_buchi_states)
/ static_cast<double>(round_info.statespace->size())
* 100.0;
estream << "number of states:" + string(6, ' ');
changeStreamFormatting(stream, 9, 0, ios::left);
estream << automaton_stats.number_of_product_states;
restoreStreamFormatting(stream);
estream << "% of worst case ("
<< automaton_stats.number_of_buchi_states
* round_info.statespace->size()
<< ')';
}
else
estream << "empty automaton";
estream << " [";
estream << "]\n" + string(indent, ' ') + "number of transitions: "
+ toString(automaton_stats.number_of_product_transitions);
if (automaton_stats.number_of_product_states != 0)
{
changeStreamFormatting(stream, 0, 2, ios::fixed);
estream << static_cast<double>
(automaton_stats.number_of_product_states)
/ static_cast<double>
(automaton_stats.number_of_buchi_states)
/ static_cast<double>(round_info.statespace->size())
* 100.0;
restoreStreamFormatting(stream);
estream << "% of worst case ("
<< automaton_stats.number_of_buchi_states
* round_info.statespace->size()
<< ')';
}
else
estream << "empty automaton";
estream << "]\n" + string(indent, ' ') + "number of transitions: "
+ toString(automaton_stats.number_of_product_transitions);
}
estream << '\n';
}
estream << '\n';
estream.flush();
}
/* ========================================================================= */
void printAcceptanceCycleStats
(ostream& stream, int indent,
vector<AlgorithmTestResults, ALLOC(AlgorithmTestResults) >::size_type
algorithm,
vector<AlgorithmTestResults>::size_type algorithm,
int result_id)
/* ----------------------------------------------------------------------------
*
@ -185,7 +274,7 @@ void printAcceptanceCycleStats
* Arguments: stream -- A reference to the output stream to which the
* information should be written.
* indent -- Number of spaces to leave on the left of the
* output.
* output in verbosity mode >= 3.
* algorithm -- Identifier of the algorithm used for
* computing the Büchi automaton whose accepting
* cycles are to be considered.
@ -201,49 +290,64 @@ void printAcceptanceCycleStats
const AutomatonStats& automaton_stats =
test_results[algorithm].automaton_stats[result_id];
estream << string(indent, ' ');
if (!automaton_stats.emptiness_check_performed)
estream << "not computed";
else if (configuration.global_options.product_mode == Configuration::LOCAL)
if (configuration.global_options.verbosity <= 2)
{
estream << string("cycle ");
if (automaton_stats.emptiness_check_result[0])
estream << "reachable ";
if (!automaton_stats.emptiness_check_performed)
estream << " N/A";
else
estream << "not reachable";
estream << " (from the initial state)";
{
changeStreamFormatting(stream, 6, 0, ios::right);
estream << automaton_stats.emptiness_check_result.count();
restoreStreamFormatting(stream);
}
estream << ' ';
}
else
{
estream << "cycle reachable from ";
estream << string(indent, ' ');
changeStreamFormatting(stream, 9, 0, ios::left);
estream << automaton_stats.emptiness_check_result.count();
restoreStreamFormatting(stream);
if (!automaton_stats.emptiness_check_performed)
estream << "not computed";
else if (configuration.global_options.product_mode == Configuration::LOCAL)
{
estream << string("cycle ");
estream << " states\n" + string(indent, ' ')
+ "not reachable from ";
if (automaton_stats.emptiness_check_result[0])
estream << "reachable ";
else
estream << "not reachable";
changeStreamFormatting(stream, 9, 0, ios::left);
estream << (round_info.real_emptiness_check_size
- automaton_stats.emptiness_check_result.count());
restoreStreamFormatting(stream);
estream << " (from the initial state)";
}
else
{
estream << "cycle reachable from ";
estream << " states";
changeStreamFormatting(stream, 9, 0, ios::left);
estream << automaton_stats.emptiness_check_result.count();
restoreStreamFormatting(stream);
estream << " states\n" + string(indent, ' ')
+ "not reachable from ";
changeStreamFormatting(stream, 9, 0, ios::left);
estream << (round_info.real_emptiness_check_size
- automaton_stats.emptiness_check_result.count());
restoreStreamFormatting(stream);
estream << " states";
}
estream << '\n';
}
estream << '\n';
estream.flush();
}
/* ========================================================================= */
void printConsistencyCheckStats
(ostream& stream, int indent,
vector<AlgorithmTestResults, ALLOC(AlgorithmTestResults) >::size_type
algorithm)
vector<AlgorithmTestResults>::size_type algorithm)
/* ----------------------------------------------------------------------------
*
* Description: Displays information about the consistency check result for
@ -253,7 +357,7 @@ void printConsistencyCheckStats
* Arguments: stream -- A reference to an output stream to which the
* information should be written.
* indent -- Number of spaces to leave on the left of the
* output.
* output in verbosity mode >= 3.
* algorithm -- Identifier of the algorithm whose consistency
* check result should be displayed.
*
@ -264,100 +368,113 @@ void printConsistencyCheckStats
Exceptional_ostream estream(&stream, ios::failbit | ios::badbit);
const AlgorithmTestResults& test_result = test_results[algorithm];
estream << string(indent, ' ');
if (configuration.global_options.verbosity <= 2)
{
switch (test_result.consistency_check_result)
{
case -1 :
estream << "NA";
break;
if (test_result.consistency_check_result == -1)
estream << "not performed";
case 0 :
estream << " F";
break;
default:
estream << " P";
break;
}
}
else
{
estream << "result:" + string(18, ' ');
estream << string(indent, ' ');
if (test_result.consistency_check_result == 0)
{
estream << "failed ["
+ toString(test_result.failed_consistency_check_comparisons)
+ " (";
changeStreamFormatting(stream, 0, 2, ios::fixed);
estream << ((test_result.consistency_check_comparisons == 0)
? 0.0
: static_cast<double>
(test_result.failed_consistency_check_comparisons)
/ test_result.consistency_check_comparisons * 100.0);
restoreStreamFormatting(stream);
estream << "%) of "
+ toString(test_result.consistency_check_comparisons)
+ " test cases]";
}
if (test_result.consistency_check_result == -1)
estream << "not performed";
else
estream << "passed";
{
estream << "result:" + string(18, ' ');
if (test_result.consistency_check_result == 0)
{
estream << "failed ["
+ toString(test_result.failed_consistency_check_comparisons)
+ " (";
changeStreamFormatting(stream, 0, 2, ios::fixed);
estream << ((test_result.consistency_check_comparisons == 0)
? 0.0
: static_cast<double>
(test_result.failed_consistency_check_comparisons)
/ test_result.consistency_check_comparisons * 100.0);
restoreStreamFormatting(stream);
estream << "%) of "
+ toString(test_result.consistency_check_comparisons)
+ " test cases]";
}
else
estream << "passed";
}
estream << '\n';
}
estream << '\n';
estream.flush();
}
/* ========================================================================= */
void printCrossComparisonStats
(ostream& stream, int indent,
vector<AlgorithmTestResults, ALLOC(AlgorithmTestResults) >::size_type
algorithm)
(ostream& stream, int indent, const IntervalList& algorithms)
/* ----------------------------------------------------------------------------
*
* Description: Displays information about the model checking result cross-
* comparison check, extracting the information from a vector of
* TestStatistics structures stored in the UserInterface object.
*
* Arguments: stream -- A reference to an output stream to which the
* information should be written.
* indent -- Number of spaces to leave on the left of the
* output.
* algorithm -- If less than the number of algorithms, show
* only the results for the algorithm with this
* identifier.
* Arguments: stream -- A reference to an output stream to which the
* information should be written.
* indent -- Number of spaces to leave on the left of the
* output.
* algorithms -- A reference to a constant IntervalList
* storing the numeric identifiers of the
* algorithms for which the statistics should
* be shown.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
Exceptional_ostream estream(&stream, ios::failbit | ios::badbit);
bool no_errors_to_report = true;
if (algorithm < configuration.algorithms.size()
&& !configuration.algorithms[algorithm].enabled)
{
estream << string(indent, ' ') + "not performed\n\n";
estream.flush();
return;
}
estream << string(indent, ' ') + "result:";
bool no_errors_to_report = true, nothing_to_report = true;
const AutomatonStats* alg_1_pos_results;
const AutomatonStats* alg_1_neg_results;
for (vector<AlgorithmTestResults, ALLOC(AlgorithmTestResults) >::size_type
alg_1 = 0;
alg_1 < test_results.size();
alg_1++)
for (IntervalList::const_iterator alg_1 = algorithms.begin();
alg_1 != algorithms.end();
++alg_1)
{
alg_1_pos_results = &test_results[alg_1].automaton_stats[0];
alg_1_neg_results = &test_results[alg_1].automaton_stats[1];
alg_1_pos_results = &test_results[*alg_1].automaton_stats[0];
alg_1_neg_results = &test_results[*alg_1].automaton_stats[1];
for (vector<AlgorithmTestResults, ALLOC(AlgorithmTestResults) >::size_type
alg_2 = alg_1 + 1;
alg_2 < test_results.size();
for (vector<AlgorithmTestResults>::size_type alg_2 = 0;
alg_2 < round_info.number_of_translators;
alg_2++)
{
if ((algorithm >= configuration.algorithms.size()
|| alg_1 == algorithm
|| alg_2 == algorithm)
&& configuration.algorithms[alg_1].enabled
if (*alg_1 != alg_2
&& (alg_2 > *alg_1 || !algorithms.covers(alg_2))
&& configuration.algorithms[*alg_1].enabled
&& configuration.algorithms[alg_2].enabled)
{
bool pos_test, neg_test;
if (nothing_to_report)
{
nothing_to_report = false;
estream << string(indent, ' ') + "result:";
}
for (int counter = 0; counter < 2; counter++)
{
if (counter == 0)
@ -385,89 +502,75 @@ void printCrossComparisonStats
else
estream << "-) ";
estream << ' ';
if (alg_1 == round_info.number_of_translators)
estream << "lbtt";
else
estream << configuration.algorithmString(alg_1);
estream << ", ";
if (alg_2 == round_info.number_of_translators)
estream << "lbtt";
else
estream << configuration.algorithmString(alg_2);
estream << " " + configuration.algorithmString(*alg_1) + ", "
+ configuration.algorithmString(alg_2);
}
}
}
}
}
if (no_errors_to_report)
if (nothing_to_report)
estream << string(indent, ' ') + "not performed";
else if (no_errors_to_report)
estream << string(20, ' ') + "no failures detected";
estream << "\n\n";
estream.flush();
}
/* ========================================================================= */
void printBuchiIntersectionCheckStats
(ostream& stream, int indent,
vector<AlgorithmTestResults, ALLOC(AlgorithmTestResults) >::size_type
algorithm)
(ostream& stream, int indent, const IntervalList& algorithms)
/* ----------------------------------------------------------------------------
*
* Description: Displays information about the Büchi automaton intersection
* emptiness check results, extracting the information from a
* TestStatistics structure stored in the UserInterface object.
*
* Arguments: stream -- A reference to an output stream to which the
* information should be written.
* indent -- Number of spaces to leave on the left of the
* output.
* algorithm -- If less than the number of algorithms, show
* only the results for the algorithm with this
* identifier.
* Arguments: stream -- A reference to an output stream to which the
* information should be written.
* indent -- Number of spaces to leave on the left of the
* output.
* algorithms -- A reference to a constant IntervalList
* storing the numeric identifiers of the
* algorithms for which the statistics should
* be shown.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
Exceptional_ostream estream(&stream, ios::failbit | ios::badbit);
bool no_errors_to_report = true;
if (algorithm < round_info.number_of_translators
&& !configuration.algorithms[algorithm].enabled)
{
estream << string(indent, ' ') + "not performed\n\n";
estream.flush();
return;
}
estream << string(indent, ' ') + "result:";
bool no_errors_to_report = true, nothing_to_report = true;
const AutomatonStats* alg_1_pos_results;
const AutomatonStats* alg_1_neg_results;
for (vector<AlgorithmTestResults, ALLOC(AlgorithmTestResults) >::size_type
alg_1 = 0;
alg_1 < round_info.number_of_translators;
alg_1++)
for (IntervalList::const_iterator alg_1 = algorithms.begin();
alg_1 != algorithms.end();
++alg_1)
{
alg_1_pos_results = &test_results[alg_1].automaton_stats[0];
alg_1_neg_results = &test_results[alg_1].automaton_stats[1];
alg_1_pos_results = &test_results[*alg_1].automaton_stats[0];
alg_1_neg_results = &test_results[*alg_1].automaton_stats[1];
for (vector<AlgorithmTestResults, ALLOC(AlgorithmTestResults) >::size_type
alg_2 = alg_1;
for (vector<AlgorithmTestResults>::size_type alg_2 = 0;
alg_2 < round_info.number_of_translators;
alg_2++)
{
if ((algorithm >= round_info.number_of_translators
|| alg_1 == algorithm
|| alg_2 == algorithm)
&& configuration.algorithms[alg_1].enabled
&& configuration.algorithms[alg_2].enabled)
if (configuration.algorithms[*alg_1].enabled
&& configuration.algorithms[alg_2].enabled
&& (alg_2 >= *alg_1 || !algorithms.covers(alg_2))
&& !configuration.isInternalAlgorithm(*alg_1)
&& !configuration.isInternalAlgorithm(alg_2))
{
bool pos_test, neg_test;
if (nothing_to_report)
{
nothing_to_report = false;
estream << string(indent, ' ') + "result:";
}
for (int counter = -1; counter < 1; counter++)
{
pos_test = (alg_1_pos_results->buchi_intersection_check_stats[alg_2]
@ -482,7 +585,7 @@ void printBuchiIntersectionCheckStats
estream << string(counter == -1 ? "N/A " : "failed") + ' ';
if (alg_1 != alg_2)
if (*alg_1 != alg_2)
{
estream << '(';
if (pos_test)
@ -493,9 +596,9 @@ void printBuchiIntersectionCheckStats
else
estream << " ";
estream << ' ' + configuration.algorithmString(alg_1);
estream << ' ' + configuration.algorithmString(*alg_1);
if (alg_1 != alg_2)
if (*alg_1 != alg_2)
{
estream << ", (";
if (pos_test)
@ -511,18 +614,18 @@ void printBuchiIntersectionCheckStats
}
}
if (no_errors_to_report)
if (nothing_to_report)
estream << string(indent, ' ') + "not performed";
else if (no_errors_to_report)
estream << string(20, ' ') + "no failures detected";
estream << "\n\n";
estream << "\n";
estream.flush();
}
/* ========================================================================= */
void printAllStats
(ostream& stream, int indent,
vector<AlgorithmTestResults, ALLOC(AlgorithmTestResults) >::size_type
algorithm)
vector<AlgorithmTestResults>::size_type algorithm)
/* ----------------------------------------------------------------------------
*
* Description: Displays all test information (Büchi automaton and product
@ -541,30 +644,46 @@ void printAllStats
{
Exceptional_ostream estream(&stream, ios::failbit | ios::badbit);
estream << string(indent, ' ') + configuration.algorithmString(algorithm)
+ '\n';
estream.flush();
if (configuration.global_options.verbosity >= 3)
estream << string(indent, ' ') + configuration.algorithmString(algorithm)
+ '\n';
for (int counter = 0; counter < 2; counter++)
{
estream << string(indent + 2, ' ')
+ (counter == 0 ? "Positive" : "Negated") + " formula:\n"
+ string(indent + 4, ' ') + "Büchi automaton:\n";
if (configuration.global_options.verbosity <= 2)
{
if (counter == 1)
estream << '\n';
estream << string(indent, ' ');
changeStreamFormatting(stream, 2, 0, ios::right);
estream << algorithm << ' ';
restoreStreamFormatting(stream);
estream << (counter == 0 ? '+' : '-') << ' ';
}
else
{
estream << string(indent + 2, ' ')
+ (counter == 0 ? "Positive" : "Negated") + " formula:\n"
+ string(indent + 4, ' ') + "Büchi automaton:\n";
}
printBuchiAutomatonStats(stream, indent + 6, algorithm, counter);
if (configuration.global_options.do_comp_test
|| configuration.global_options.do_cons_test)
{
estream << string(indent + 4, ' ') + "Product automaton:\n";
if (configuration.global_options.verbosity >= 3)
estream << string(indent + 4, ' ') + "Product automaton:\n";
printProductAutomatonStats(stream, indent + 6, algorithm, counter);
estream << string(indent + 4, ' ') + "Accepting cycles:\n";
if (configuration.global_options.verbosity >= 3)
estream << string(indent + 4, ' ') + "Accepting cycles:\n";
printAcceptanceCycleStats(stream, indent + 6, algorithm, counter);
}
}
if (configuration.global_options.do_cons_test)
{
estream << string(indent + 2, ' ') + "Result consistency check:\n";
if (configuration.global_options.verbosity >= 3)
estream << string(indent + 2, ' ') + "Result consistency check:\n";
printConsistencyCheckStats(stream, indent + 4, algorithm);
}
@ -575,8 +694,8 @@ void printAllStats
/* ========================================================================= */
void printCollectiveCrossComparisonStats
(ostream& stream,
vector<TestStatistics, ALLOC(TestStatistics) >::size_type algorithm_y,
vector<TestStatistics, ALLOC(TestStatistics) >::size_type algorithm_x,
vector<TestStatistics>::size_type algorithm_y,
vector<TestStatistics>::size_type algorithm_x,
int data_type)
/* ----------------------------------------------------------------------------
*
@ -630,10 +749,8 @@ void printCollectiveCrossComparisonStats
break;
default :
if (configuration.global_options.statespace_generation_mode
& Configuration::PATH
&& (algorithm_x == round_info.number_of_translators
|| algorithm_y == round_info.number_of_translators))
if (configuration.isInternalAlgorithm(algorithm_x)
|| configuration.isInternalAlgorithm(algorithm_y))
{
estream << string(21, ' ');
return;
@ -768,13 +885,12 @@ void printCollectiveStats(ostream& stream, int indent)
if (round_info.num_processed_formulae > 0
&& configuration.global_options.formula_input_filename.empty())
{
const map<unsigned long int, unsigned long int, less<unsigned long int>,
ALLOC(unsigned long int) >&
const map<unsigned long int, unsigned long int>&
proposition_statistics
= configuration.formula_options.formula_generator.
propositionStatistics();
const map<int, unsigned long int, less<int>, ALLOC(unsigned long int) >
const map<int, unsigned long int>
symbol_statistics
= configuration.formula_options.formula_generator.symbolStatistics();
@ -820,9 +936,8 @@ void printCollectiveStats(ostream& stream, int indent)
number_of_symbols_printed++;
}
for (map<unsigned long int, unsigned long int,
less<unsigned long int>, ALLOC(unsigned long int) >
::const_iterator proposition = proposition_statistics.begin();
for (map<unsigned long int, unsigned long int>::const_iterator
proposition = proposition_statistics.begin();
proposition != proposition_statistics.end();
++proposition)
{
@ -869,8 +984,8 @@ void printCollectiveStats(ostream& stream, int indent)
= "";
number_of_symbols_printed = 0;
for (map<int, unsigned long int, less<int>, ALLOC(unsigned long int) >
::const_iterator op = symbol_statistics.begin();
for (map<int, unsigned long int>::const_iterator
op = symbol_statistics.begin();
op != symbol_statistics.end();
++op)
{
@ -912,6 +1027,8 @@ void printCollectiveStats(ostream& stream, int indent)
if (number_of_symbols_printed % 5 != 0)
{
if (number_of_symbols_printed > 5)
estream << '\n';
estream << ind + " operator " + symbol_name_string + '\n'
+ ind + " # " + symbol_number_string + '\n'
+ ind + " #/formula " + symbol_distribution_string
@ -953,8 +1070,11 @@ void printCollectiveStats(ostream& stream, int indent)
algorithm < round_info.number_of_translators;
++algorithm)
{
if (configuration.isInternalAlgorithm(algorithm))
continue;
estream << '\n' + string((i > 0 ? 4 : 2) + indent, ' ')
+ *(configuration.algorithms[algorithm].name) + '\n';
+ configuration.algorithms[algorithm].name + '\n';
switch (i)
{
@ -967,14 +1087,14 @@ void printCollectiveStats(ostream& stream, int indent)
unsigned long int failures_to_compute_automaton;
unsigned long int automaton_count;
unsigned long int number_of_successful_instances;
unsigned long int total_number_of_states;
unsigned long int total_number_of_transitions;
BIGUINT total_number_of_states;
BIGUINT total_number_of_transitions;
const TestStatistics& stats = final_statistics[algorithm];
estream << string(2 + indent, ' ')
+ string(configuration.algorithms[algorithm].name
->length(), '=');
+ string(configuration.algorithms[algorithm].name.
length(), '=');
for (int k = 0; k < 2; k++)
{
@ -1119,7 +1239,7 @@ void printCollectiveStats(ostream& stream, int indent)
if (k == 0)
{
unsigned long int total_number_of_acceptance_sets;
BIGUINT total_number_of_acceptance_sets;
double buchi_generation_time;
estream << '\n' + string(22 + indent, ' ')
@ -1339,8 +1459,7 @@ void printCollectiveStats(ostream& stream, int indent)
estream << ind + " Result inconsistency statistics\n"
+ ind + " " + string(31, '=') + '\n';
vector<TestStatistics, ALLOC(TestStatistics) >::size_type
algorithm_x, algorithm_y;
vector<TestStatistics>::size_type algorithm_x, algorithm_y;
for (algorithm_x = 0; algorithm_x < number_of_algorithms;
algorithm_x += 2)
@ -1352,7 +1471,7 @@ void printCollectiveStats(ostream& stream, int indent)
if (algorithm_x + i < number_of_algorithms)
{
algorithm_name =
(*(configuration.algorithms[algorithm_x + i].name)).substr(0, 20);
configuration.algorithms[algorithm_x + i].name.substr(0, 20);
estream << "| " + algorithm_name
+ string(21 - algorithm_name.length(), ' ');
}
@ -1362,6 +1481,9 @@ void printCollectiveStats(ostream& stream, int indent)
for (algorithm_y = 0; algorithm_y < number_of_algorithms;
algorithm_y++)
{
if (configuration.isInternalAlgorithm(algorithm_y))
continue;
estream << "\n " + ind + string(26, '-');
for (int i = 0; i < 2; ++i)
@ -1372,7 +1494,7 @@ void printCollectiveStats(ostream& stream, int indent)
estream << '+';
algorithm_name
= (*(configuration.algorithms[algorithm_y].name)).substr(0, 20);
= configuration.algorithms[algorithm_y].name.substr(0, 20);
bool algorithm_name_printed = false;
legend = 1;

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -42,65 +42,60 @@ extern Configuration configuration;
namespace StatDisplay
{
void printStatTableHeader /* Displays a table */
(ostream& stream, int indent); /* header for test
* statistics.
*/
void printBuchiAutomatonStats /* Displays information */
(ostream& stream, /* about a Büchi */
int indent, /* automaton. */
vector<AlgorithmTestResults,
ALLOC(AlgorithmTestResults) >::size_type
vector<AlgorithmTestResults>::size_type
algorithm,
int result_id);
void printProductAutomatonStats /* Displays information */
(ostream& stream, /* about a product */
int indent, /* automaton. */
vector<AlgorithmTestResults,
ALLOC(AlgorithmTestResults) >::size_type
vector<AlgorithmTestResults>::size_type
algorithm,
int result_id);
void printAcceptanceCycleStats /* Displays information */
(ostream& stream, /* about the acceptance */
int indent, /* cycles of a product */
vector<AlgorithmTestResults, /* automaton. */
ALLOC(AlgorithmTestResults) >::size_type
vector<AlgorithmTestResults>::size_type /* automaton. */
algorithm,
int result_id);
void printConsistencyCheckStats /* Displays the result */
(ostream& stream, /* of the consistency */
int indent, /* check for a given */
vector<AlgorithmTestResults, /* algorithm. */
ALLOC(AlgorithmTestResults) >::size_type
vector<AlgorithmTestResults>::size_type /* algorithm. */
algorithm);
void printCrossComparisonStats /* Displays information */
(ostream& stream, /* about the model */
int indent, /* checking result */
vector<AlgorithmTestResults, /* cross-comparison */
ALLOC(AlgorithmTestResults) >::size_type /* check. */
algorithm);
(ostream& stream, int indent, /* about the model */
const IntervalList& algorithms); /* checking result */
/* cross-comparison */
/* check. */
void printBuchiIntersectionCheckStats /* Displays the results */
(ostream& stream, int indent, /* of the Büchi automata */
vector<AlgorithmTestResults, /* intersection */
ALLOC(AlgorithmTestResults) >::size_type /* emptiness checks. */
algorithm);
const IntervalList& algorithms); /* intersection */
/* emptiness checks. */
void printAllStats /* A shorthand for */
(ostream& stream, /* showing all the */
int indent, /* information displayed */
vector<TestStatistics, /* by the previous five */
ALLOC(TestStatistics)>::size_type /* functions. */
algorithm);
vector<TestStatistics>::size_type algorithm); /* by the previous five
* functions.
*/
void printCollectiveCrossComparisonStats /* Displays a single */
(ostream& stream, /* `cell' of the final */
vector<TestStatistics, /* result cross- */
ALLOC(TestStatistics) >::size_type /* comparison table. */
algorithm_y,
vector<TestStatistics,
ALLOC(TestStatistics) >::size_type
algorithm_x,
vector<TestStatistics>::size_type algorithm_y, /* result cross- */
vector<TestStatistics>::size_type algorithm_x, /* comparison table. */
int data_type);
void printCollectiveStats /* Displays average test */

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,10 +17,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef __GNUC__
#pragma implementation
#endif /* __GNUC__ */
#include <config.h>
#include <map>
#include "DispUtil.h"
@ -148,8 +144,7 @@ void StateSpace::clear()
initial_state = 0;
#ifdef HAVE_OBSTACK_H
for (vector<Node*, ALLOC(Node*) >::iterator state = nodes.begin();
state != nodes.end();
for (vector<Node*>::iterator state = nodes.begin(); state != nodes.end();
++state)
static_cast<State*>(*state)->~State();

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -174,9 +174,7 @@ StateSpace* StateSpaceRandomizer::generateConnectedGraph() const
StateSpace::size_type first_unreachable_state = 1, random_node;
multimap<long int, StateSpace::size_type, less<long int>,
ALLOC(StateSpace::size_type) >
reachable_but_unprocessed;
multimap<long int, StateSpace::size_type> reachable_but_unprocessed;
reachable_but_unprocessed.insert(make_pair(0, 0));

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -20,10 +20,6 @@
#ifndef STATESPACERANDOMIZER_H
#define STATESPACERANDOMIZER_H
#ifdef __GNUC__
#pragma interface
#endif /* __GNUC__ */
#include <config.h>
#include "Random.h"
#include "StateSpace.h"

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,11 +17,9 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef __GNUC__
#pragma implementation
#endif /* __GNUC__ */
#include <config.h>
#include <cctype>
#include <climits>
#include <cstdlib>
#include "StringUtil.h"
@ -63,8 +61,7 @@ string toString(const double d, const int precision, const ios::fmtflags flags)
/* ========================================================================= */
void sliceString
(const string& s, const char* slice_chars,
vector<string, ALLOC(string) >& slices)
(const string& s, const char* slice_chars, vector<string>& slices)
/* ----------------------------------------------------------------------------
*
* Description: Slices a string into a vector of strings, using a given set
@ -104,6 +101,211 @@ void sliceString
while (last_non_slicechar_pos != s.npos && last_slicechar_pos != s.npos);
}
/* ========================================================================= */
string toLowerCase(const string& s)
/* ----------------------------------------------------------------------------
*
* Description: Converts a string to lower case.
*
* Argument: s -- String to process.
*
* Returns: The string in lower case.
*
* ------------------------------------------------------------------------- */
{
string result;
for (string::size_type pos = 0; pos < s.length(); ++pos)
result += tolower(s[pos]);
return result;
}
/* ========================================================================= */
bool interpretSpecialCharacters(const char c, bool& escape, char& quotechar)
/* ----------------------------------------------------------------------------
*
* Description: Updates the values of `escape' and `quotechar' based on their
* original values and the value of `c'. Used for scanning
* through a string possibly containing quotes and escaped
* characters.
*
* Arguments: c -- A character.
* escape -- A truth value telling whether `c' was escaped.
* quotechar -- 0 == `c' was read outside of quotes.
* `'' == `c' was read inside single quotes.
* `"' == `c' was read inside double quotes.
*
* Returns: True if `c' had a special meaning (for example, if it was a
* begin/end quote character) in the state determined by the
* original values of `escape' and `quotechar'.
*
* ------------------------------------------------------------------------- */
{
if (escape)
{
escape = false;
return false;
}
switch (c)
{
case '\\' :
if (quotechar != '\'')
{
escape = true;
return true;
}
break;
case '\'' : case '"' :
if (quotechar == 0)
{
quotechar = c;
return true;
}
else if (c == quotechar)
{
quotechar = 0;
return true;
}
break;
default :
break;
}
return false;
}
/* ========================================================================= */
string unquoteString(const string& s)
/* ----------------------------------------------------------------------------
*
* Description: Removes (unescaped) single and double quotes and escape
* characters from a string.
*
* Argument: s -- String to process.
*
* Returns: A string with the quotes and escape characters removed.
*
* ------------------------------------------------------------------------- */
{
string result;
char quotechar = 0;
bool escape = false;
for (string::size_type pos = 0; pos < s.size(); ++pos)
{
if (!interpretSpecialCharacters(s[pos], escape, quotechar))
result += s[pos];
}
return result;
}
/* ========================================================================= */
string::size_type findInQuotedString
(const string& s, const string& chars, QuoteMode type)
/* ----------------------------------------------------------------------------
*
* Description: Finds a character in a string (respecting quotes).
*
* Arguments: s -- String to process.
* chars -- A sting of characters to be searched in `s'.
* type -- The extent of the search.
* GLOBAL - Apply the search to the entire
* string.
* INSIDE_QUOTES - Restrict the search to
* unescaped characters between
* quotes.
* OUTSIDE_QUOTES - Restrict the search to
* unescaped characters outside
* quotes.
*
* Returns: If `s' contains one of the characters in `chars' in a part
* of the string that matches `type', the position of the
* character in `s', and string::npos otherwise.
*
* ------------------------------------------------------------------------- */
{
char quotechar = 0;
bool escape = false;
for (string::size_type pos = 0; pos < s.size(); ++pos)
{
if ((type == GLOBAL || (!escape &&
((type == INSIDE_QUOTES && quotechar != 0)
|| (type == OUTSIDE_QUOTES && quotechar == 0))))
&& chars.find_first_of(s[pos]) != string::npos)
return pos;
interpretSpecialCharacters(s[pos], escape, quotechar);
}
return string::npos;
}
/* ========================================================================= */
string substituteInQuotedString
(const string& s, const string& chars, const string& substitutions,
QuoteMode type)
/* ----------------------------------------------------------------------------
*
* Description: Substitutes characters in a string with other characters.
*
* Arguments: s -- String to process.
* chars -- A string of characters, each of which
* should be substituted in `s' with the
* character at the corresponding
* position of the string `substitutions'.
* substitutions -- Characters to substitute. The length of
* this string should equal the length of
* `chars'.
* type -- The extent of substitution.
* GLOBAL - Apply the substitutions
* globally (the default).
* INSIDE_QUOTES - Apply the substitutions
* to unescaped characters
* only inside quotes that
* have not been escaped
* with a backslash.
* OUTSIDE_QUOTES - Apply the substitutions
* to unescaped characters
* only outside quotes
* that have not been
* escaped with a
* backslash.
* It is not recommended to substitute the
* special characters ', " and \ with other
* characters if they have special meaning in
* `s'.
*
* Returns: A string with the substitutions.
*
* ------------------------------------------------------------------------- */
{
string result;
char quotechar = 0;
bool escape = false;
for (string::size_type pos = 0; pos < s.size(); ++pos)
{
char c = s[pos];
if (type == GLOBAL || (!escape &&
((type == INSIDE_QUOTES && quotechar != 0)
|| (type == OUTSIDE_QUOTES && quotechar == 0))))
{
string::size_type subst_pos = chars.find_first_of(c);
if (subst_pos != string::npos)
c = substitutions[subst_pos];
}
result += c;
interpretSpecialCharacters(s[pos], escape, quotechar);
}
return result;
}
/* ========================================================================= */
unsigned long int parseNumber(const string& number_string)
/* ----------------------------------------------------------------------------
@ -119,9 +321,11 @@ unsigned long int parseNumber(const string& number_string)
* ------------------------------------------------------------------------- */
{
char* endptr;
unsigned long int number = strtoul(number_string.c_str(), &endptr, 10);
if (*endptr != '\0')
if (*endptr != '\0' || number_string.empty()
|| number_string.find_first_of("-") != string::npos)
throw NotANumberException("expected a nonnegative integer, got `"
+ number_string + "'");
@ -129,98 +333,253 @@ unsigned long int parseNumber(const string& number_string)
}
/* ========================================================================= */
void parseInterval
(const string& token,
set<unsigned long int, less<unsigned long int>, ALLOC(unsigned long int) >&
number_set,
unsigned long int min, unsigned long int max)
int parseInterval
(const string& token, unsigned long int& min, unsigned long int& max)
/* ----------------------------------------------------------------------------
*
* Description: Parses a string for a list of number intervals, storing all
* the numbers into a set.
* Description: Reads the lower and upper bound from an "interval string"
* into two unsigned long integer variables.
*
* Arguments: token -- A reference to a constant string containing
* the list of intervals. A legal list of
* intervals has the following syntax:
* Arguments: token -- A reference to a constant "interval string" of
* the format
* <interval string>
* ::= "*" // 0
* | <ulong> // 1
* | <sep><ulong> // 2
* | <ulong><sep> // 3
* | <ulong><sep><ulong> // 4
* where <ulong> is an unsigned long integer (not
* containing a minus sign), and <sep> is either
* "-" or "...". The meaning of the various cases
* is as follows:
* 0 All integers between 0 and ULONG_MAX.
* 1 A point interval consisting of a single
* value.
* 2 An interval from 0 to a given upper
* bound.
* 3 An interval from a given lower bound to
* ULONG_MAX.
* 4 A bounded interval.
* min, max -- References to two unsigned long integers for
* storing the lower and upper bound of the
* interval.
*
* <interval_list>
* ::= <number>
* | '*' // all numbers in the
* // interval
* // [min, max]
* | '-'<number> // all numbers in the
* // interval
* // [min, number]
* | <number>'-' // all numbers in the
* // interval
* // [number, max]
* | <number>'-'<number>
* | <interval_list>','<interval_list>
*
* number_set -- A reference to a set of unsigned long
* integers for storing the result.
* min -- Minimum bound for the numbers.
* max -- Maximum bound for the numbers.
*
* Note: `min' and `max' are only used to determine the limits
* for only partially defined intervals. The check that
* the explicitly specified values in the interval list
* are within these bounds is left to the caller when
* examining the result set.
*
* Returns: Nothing.
* Returns: A value telling the type of the specified interval, which is
* a bitwise or of the values LEFT_BOUNDED and RIGHT_BOUNDED
* depending on which bounds were given explicitly for the
* interval. (The lower and upper bounds of the interval itself
* are stored in the variables `min' and `max', respectively.)
* The function will throw a NotANumberException if the
* interval string is of an invalid format.
*
* ------------------------------------------------------------------------- */
{
vector<string, ALLOC(string) > intervals;
unsigned long int tmp_min = 0;
unsigned long int tmp_max = ULONG_MAX;
int interval_type = UNBOUNDED;
sliceString(token, ",", intervals);
string::size_type dash_pos;
number_set.clear();
for (vector<string, ALLOC(string) >::const_iterator
interval = intervals.begin();
interval != intervals.end();
++interval)
if (token != "*")
{
if (*interval == "*")
string::size_type pos(token.find_first_of("-"));
if (pos == string::npos)
pos = token.find("...");
string value(token.substr(0, pos));
if (!value.empty())
{
for (unsigned long int i = min; i <= max; i++)
number_set.insert(i);
break;
tmp_min = parseNumber(value);
if (pos == string::npos)
tmp_max = tmp_min;
interval_type |= LEFT_BOUNDED;
}
dash_pos = (*interval).find_first_of("-");
if (pos != string::npos)
value = token.substr(pos + (token[pos] == '-' ? 1 : 3));
if (dash_pos == (*interval).npos)
number_set.insert(parseNumber(*interval));
else
if (!value.empty())
{
if (dash_pos == 0)
tmp_max = parseNumber(value);
interval_type |= RIGHT_BOUNDED;
}
else if (!(interval_type & LEFT_BOUNDED))
throw NotANumberException("invalid format for interval");
}
min = tmp_min;
max = tmp_max;
return interval_type;
}
/* ========================================================================= */
void parseIntervalList
(const string& token, IntervalList& intervals, unsigned long int min,
unsigned long int max, vector<string>* extra_tokens)
/* ----------------------------------------------------------------------------
*
* Description: Parses a string of number intervals into an IntervalList.
*
* Arguments: token -- A reference to a constant comma-separated
* list of interval strings (see documentation
* for the parseInterval function).
* intervals -- A reference to an IntervalList to be used
* for storing the result.
* min -- Absolute lower bound for the numbers.
* Numbers lower than this bound will not be
* stored in the result set.
* max -- Absolute upper bound for the numbers.
* Numbers greater than this bound will not be
* stored in the result set.
* extra_tokens -- If not 0, all tokens that cannot be
* recognized as valid interval strings will
* be stored in the vector of strings to which
* this variable points. Otherwise the
* function will throw a NotANumberException.
*
* Returns: Nothing. Throws an IntervalRangeException if any of the
* intervals in the list does not fit in the closed range
* [min,max].
*
* ------------------------------------------------------------------------- */
{
vector<string> interval_strings;
int interval_type;
intervals.clear();
sliceString(token, ",", interval_strings);
for (vector<string>::const_iterator i = interval_strings.begin();
i != interval_strings.end();
++i)
{
unsigned long int i_start, i_end;
try
{
interval_type = parseInterval(*i, i_start, i_end);
}
catch (const NotANumberException&)
{
if (extra_tokens != 0)
{
unsigned long int number = parseNumber((*interval).substr(1));
for (unsigned long int i = min; i <= number; i++)
number_set.insert(i);
}
else if (dash_pos == (*interval).length() - 1)
{
unsigned long int number =
parseNumber((*interval).substr(0, (*interval).length() - 1));
for (unsigned long int i = number; i <= max; i++)
number_set.insert(i);
extra_tokens->push_back(*i);
continue;
}
else
{
unsigned long int min_bound =
parseNumber((*interval).substr(0, dash_pos));
unsigned long int max_bound =
parseNumber((*interval).substr(dash_pos + 1));
for (unsigned long int i = min_bound; i <= max_bound; i++)
number_set.insert(i);
}
throw;
}
if (interval_type & LEFT_BOUNDED)
{
if (i_start < min || i_start > max)
throw IntervalRangeException(i_start);
}
else if (i_start < min)
i_start = min;
if (interval_type & RIGHT_BOUNDED)
{
if (i_end < min || i_end > max)
throw IntervalRangeException(i_end);
}
else if (i_end > max)
i_end = max;
intervals.merge(i_start, i_end);
}
}
/* ========================================================================= */
void parseTime
(const string& time_string, unsigned long int& hours,
unsigned long int& minutes, unsigned long int& seconds)
/* ----------------------------------------------------------------------------
*
* Description: Parses a "time string", i.e., a string of the form
* ([0-9]+"h")([0-9]+"min")?([0-9]+"s")?
* | ([0-9]+"min")([0-9]+"s")?
* | ([0-9]+"s")
* (where 'h', 'min' and 's' correspond to hours, minutes and
* seconds, respectively) and stores the numbers into three
* unsigned long integers. The case of the unit symbols is not
* relevant.
*
* Arguments: time_string -- String to process.
* hours -- A reference to an unsigned long integer for
* storing the number of hours.
* minutes -- A reference to an unsigned long integer for
* storing the number of minutes.
* seconds -- A reference to an unsigned long integer for
* storing the number of seconds.
*
* Time components left unspecified in `time_string' will get
* the value 0.
*
* Returns: Nothing. Throws an Exception if the given string is not of
* the correct format.
*
* ------------------------------------------------------------------------- */
{
bool hours_present = false, minutes_present = false, seconds_present = false;
hours = minutes = seconds = 0;
if (time_string.empty())
throw Exception("invalid time format");
string::size_type pos1 = 0;
string s;
while (pos1 < time_string.length())
{
string::size_type pos2 = time_string.find_first_not_of("0123456789", pos1);
if (pos2 >= time_string.length())
throw Exception("invalid time format");
unsigned long int val;
try
{
val = parseNumber(time_string.substr(pos1, pos2 - pos1));
}
catch (const NotANumberException&)
{
throw Exception("invalid time format");
}
switch (tolower(time_string[pos2]))
{
case 'h' :
if (hours_present || minutes_present || seconds_present)
throw Exception("invalid time format");
hours_present = true;
hours = val;
break;
case 'm' :
if (minutes_present
|| seconds_present
|| pos2 + 2 >= time_string.length()
|| tolower(time_string[pos2 + 1]) != 'i'
|| tolower(time_string[pos2 + 2]) != 'n')
throw Exception("invalid time format");
minutes_present = true;
minutes = val;
pos2 += 2;
break;
case 's' :
if (seconds_present)
throw Exception("invalid time format");
seconds_present = true;
seconds = val;
break;
default : /* 's' */
throw Exception("invalid time format");
break;
}
pos1 = pos2 + 1;
}
}

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -31,6 +31,7 @@
#include <vector>
#include "LbttAlloc.h"
#include "Exception.h"
#include "IntervalList.h"
using namespace std;
@ -57,22 +58,71 @@ template<typename T> string toString(const T& t); /* Template function for
void sliceString /* Breaks a string into */
(const string& s, const char* slice_chars, /* `slices', using a */
vector<string, ALLOC(string) >& slices); /* given set of
vector<string>& slices); /* given set of
* characters as
* separators.
*/
string toLowerCase(const string& s); /* Converts a string to
* lower case.
*/
string unquoteString(const string& s); /* Removes unescaped quotes
* from a string and
* interprets escaped
* characters.
*/
enum QuoteMode {GLOBAL, INSIDE_QUOTES, /* Enumeration type used */
OUTSIDE_QUOTES}; /* for controlling the
* behavior of the
* substitute function.
*/
string::size_type findInQuotedString /* Finds a character in */
(const string& s, const string& chars, /* a string (respecting */
QuoteMode type = GLOBAL); /* quotes). */
string substituteInQuotedString /* Replaces characters */
(const string& s, const string& chars, /* in a string with */
const string& substitutions, /* other characters. */
QuoteMode type = GLOBAL);
unsigned long int parseNumber /* Converts a string to */
(const string& number_string); /* an unsigned long
* integer.
*/
void parseInterval /* Converts a string of */
(const string& token, /* number intervals to */
set<unsigned long int, less<unsigned long int>, /* the corresponding set */
ALLOC(unsigned long int) >& number_set, /* of unsigned long */
unsigned long int min, /* integers. */
unsigned long int max);
enum IntervalStringType {UNBOUNDED = 0, /* Type for an interval */
LEFT_BOUNDED = 1, /* string (see the */
RIGHT_BOUNDED = 2}; /* documentation of
* the parseInterval
* function in
* StringUtil.cc).
*/
int parseInterval /* Reads the lower and */
(const string& token, /* upper bounds from a */
unsigned long int& min, /* "number interval */
unsigned long int& max); /* string" into two
* unsigned long integer
* variables.
*/
void parseIntervalList /* Converts a list of */
(const string& token, /* number intervals to */
IntervalList& intervals, /* the set of unsigned */
unsigned long int min, /* long integers */
unsigned long int max, /* corresponding to the */
vector<string>* extra_tokens = 0); /* union of the
* intervals.
*/
void parseTime /* Parses a time string. */
(const string& time_string,
unsigned long int& hours,
unsigned long int& minutes,
unsigned long int& seconds);
@ -133,6 +183,38 @@ public:
/******************************************************************************
*
* A class for reporting "out of range" errors for numbers when parsing
* intervals.
*
*****************************************************************************/
class IntervalRangeException : public Exception
{
public:
IntervalRangeException /* Constructor. */
(const unsigned long int number,
const string& message = "number out of range");
/* default copy constructor */
~IntervalRangeException() throw(); /* Destructor. */
IntervalRangeException& operator= /* Assignment operator. */
(const IntervalRangeException& e);
unsigned long int getNumber() const; /* Returns the number
* associated with the
* exception object.
*/
private:
const unsigned long int invalid_number;
};
/******************************************************************************
*
* Inline function definitions for class NotANumberException.
@ -189,6 +271,82 @@ inline NotANumberException& NotANumberException::operator=
return *this;
}
/******************************************************************************
*
* Inline function definitions for class IntervalRangeException.
*
*****************************************************************************/
/* ========================================================================= */
inline IntervalRangeException::IntervalRangeException
(const unsigned long int number, const string& message) :
Exception(message), invalid_number(number)
/* ----------------------------------------------------------------------------
*
* Description: Constructor for class IntervalRangeException. Creates an
* exception object.
*
* Arguments: number -- A constant unsigned long integer specifying a
* number that does not fit in an interval.
* message -- A reference to a constant string containing an
* error message.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
}
/* ========================================================================= */
inline IntervalRangeException::~IntervalRangeException() throw()
/* ----------------------------------------------------------------------------
*
* Description: Destructor for class IntervalRangeException.
*
* Arguments: None.
*
* Returns: Nothing.
*
* ------------------------------------------------------------------------- */
{
}
/* ========================================================================= */
inline unsigned long int IntervalRangeException::getNumber() const
/* ----------------------------------------------------------------------------
*
* Description: Returns the number associated with the IntervalRangeException
* object.
*
* Arguments: None.
*
* Returns: The number associated with the object.
*
* ------------------------------------------------------------------------- */
{
return invalid_number;
}
/* ========================================================================= */
inline IntervalRangeException& IntervalRangeException::operator=
(const IntervalRangeException& e)
/* ----------------------------------------------------------------------------
*
* Description: Assignment operator for class IntervalRangeException.
* Copies the contents of an exception object to another.
*
* Arguments: e -- A reference to a constant IntervalRangeException.
*
* Returns: A reference to the object assigned to.
*
* ------------------------------------------------------------------------- */
{
Exception::operator=(e);
return *this;
}
}
#endif /* !STRINGUTIL_H */

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -29,6 +29,7 @@
#include "Configuration.h"
#include "Exception.h"
#include "StateSpace.h"
#include "TestStatistics.h"
using namespace std;
@ -53,7 +54,11 @@ void openFile /* Opens a file for */
(const char* filename, ofstream& stream, /* writing. */
ios::openmode mode, int indent = 0);
void removeFile /* Removes a file. */
void openFile /* Opens a file for */
(const char* filename, int& fd, int flags, /* input/output using */
int indent = 0); /* file descriptors. */
void truncateFile /* Truncates a file. */
(const char* filename, int indent = 0);
void printFileContents /* Displays the contents */
@ -90,32 +95,25 @@ void writeFormulaeToFiles(); /* Writes LTL formulas */
void generateBuchiAutomaton /* Generates a Büchi */
(int f, /* automaton from a LTL */
vector<Configuration::AlgorithmInformation, /* formula stored in a */
ALLOC(Configuration::AlgorithmInformation) > /* given file, using a */
::size_type /* given LTL-to-Büchi */
algorithm_id); /* translation algorithm
vector<Configuration::AlgorithmInformation> /* formula stored in a */
::size_type /* given file, using a */
algorithm_id); /* given LTL-to-Büchi
* translation algorithm
* for the conversion.
*/
void generateProductAutomaton /* Computes the */
(int f, /* synchronous product */
vector<Configuration::AlgorithmInformation, /* of a Büchi automaton */
ALLOC(Configuration::AlgorithmInformation) > /* and a state space. */
::size_type
algorithm_id);
void performEmptinessCheck /* Performs an emptiness */
(int f, /* check on a product */
vector<Configuration::AlgorithmInformation, /* automaton. */
ALLOC(Configuration::AlgorithmInformation) >
vector<Configuration::AlgorithmInformation> /* automaton. */
::size_type
algorithm_id);
void performConsistencyCheck /* Performs a */
(vector<Configuration::AlgorithmInformation, /* consistency check on */
ALLOC(Configuration::AlgorithmInformation) > /* the test results */
::size_type /* for a formula and its */
algorithm_id); /* negation. */
(vector<Configuration::AlgorithmInformation> /* consistency check on */
::size_type /* the test results */
algorithm_id); /* for a formula and its
* negation.
*/
void compareResults(); /* Compares the model
* checking results

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -28,9 +28,9 @@
#include "LbttAlloc.h"
#include "Exception.h"
#include "LtlFormula.h"
#include "ProductAutomaton.h"
#include "PathIterator.h"
#include "StateSpace.h"
#include "TempFsysName.h"
using namespace std;
@ -55,7 +55,11 @@ public:
* stream for messages.
*/
ifstream formula_input_file; /* Stream for reading input
istream* formula_input_stream; /* Stream for reading input
* formulae.
*/
ifstream formula_input_file; /* File for reading input
* formulae.
*/
@ -90,6 +94,10 @@ public:
* current round.
*/
bool all_tests_successful; /* True if no errors have
* occurred during testing.
*/
bool skip; /* True if the current
* round is to be skipped.
*/
@ -122,11 +130,6 @@ public:
* paths as state spaces.
*/
const Graph::ProductAutomaton* product_automaton; /* Pointer to the product
* automaton used in the
* current test round.
*/
unsigned long int real_emptiness_check_size; /* Number of states in the
* state space where the
* emptiness check should
@ -150,9 +153,9 @@ public:
* current round.
*/
vector<class ::Ltl::LtlFormula*, /* Formulae used in the */
ALLOC(class ::Ltl::LtlFormula*) > /* current round: */
formulae; /* formulae[0]:
vector<class ::Ltl::LtlFormula*> formulae; /* Formulae used in the
* current round:
* formulae[0]:
* positive formula in
* negation normal
* form
@ -168,7 +171,7 @@ public:
* generated
*/
vector<bool, ALLOC(bool) > formula_in_file; /* The values in this
vector<bool> formula_in_file; /* The values in this
* vector will be set to
* true when the
* corresponding
@ -181,10 +184,10 @@ public:
* formula.
*/
char formula_file_name[2][L_tmpnam + 1]; /* Storage space for the */
char automaton_file_name[L_tmpnam + 1]; /* names of several */
char cout_capture_file[L_tmpnam + 1]; /* temporary files. */
char cerr_capture_file[L_tmpnam + 1];
TempFsysName* formula_file_name[2]; /* Names for temporary */
TempFsysName* automaton_file_name; /* files. */
TempFsysName* cout_capture_file;
TempFsysName* cerr_capture_file;
private:
TestRoundInfo(const TestRoundInfo& info); /* Prevent copying and */
@ -206,14 +209,15 @@ private:
inline TestRoundInfo::TestRoundInfo() :
cout(&std::cout, ios::failbit | ios::badbit), number_of_translators(0),
current_round(1), next_round_to_run(1), next_round_to_stop(1),
error_report_round(0), error(false), skip(false), abort(false),
num_generated_statespaces(0), total_statespace_states(0),
total_statespace_transitions(0), num_processed_formulae(0),
fresh_statespace(false), statespace(0), path_iterator(0),
product_automaton(0), real_emptiness_check_size(0),
error_report_round(0), error(false), all_tests_successful(true),
skip(false), abort(false), num_generated_statespaces(0),
total_statespace_states(0), total_statespace_transitions(0),
num_processed_formulae(0), fresh_statespace(false), statespace(0),
path_iterator(0), real_emptiness_check_size(0),
next_round_to_change_statespace(1), next_round_to_change_formula(1),
fresh_formula(false), formulae(4, static_cast<class ::Ltl::LtlFormula*>(0)),
formula_in_file(2, false)
formula_in_file(2, false), automaton_file_name(0), cout_capture_file(0),
cerr_capture_file(0)
/* ----------------------------------------------------------------------------
*
* Description: Constructor for class TestRoundInfo. Creates a new
@ -225,6 +229,7 @@ inline TestRoundInfo::TestRoundInfo() :
*
* ------------------------------------------------------------------------- */
{
formula_file_name[0] = formula_file_name[1] = 0;
}
/* ========================================================================= */

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,10 +17,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef __GNUC__
#pragma implementation
#endif /* __GNUC__ */
#include <config.h>
#include "TestStatistics.h"
@ -54,8 +50,7 @@ void AlgorithmTestResults::emptinessReset()
automaton_stats[i].emptiness_check_result.clear();
automaton_stats[i].emptiness_check_performed = false;
for (vector<AutomatonStats::CrossComparisonStats,
ALLOC(AutomatonStats::CrossComparisonStats) >::iterator it
for (vector<AutomatonStats::CrossComparisonStats>::iterator it
= automaton_stats[i].cross_comparison_stats.begin();
it != automaton_stats[i].cross_comparison_stats.end();
++it)
@ -91,7 +86,7 @@ void AlgorithmTestResults::fullReset()
automaton_stats[i].number_of_msccs = 0;
automaton_stats[i].buchi_generation_time = 0.0;
for (vector<int, ALLOC(int) >::iterator it
for (vector<int>::iterator it
= automaton_stats[i].buchi_intersection_check_stats.begin();
it != automaton_stats[i].buchi_intersection_check_stats.end();
++it)

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -23,16 +23,16 @@
#include <config.h>
#include <utility>
#include <vector>
#include "EdgeContainer.h"
#include "Graph.h"
#include "LbttAlloc.h"
#include "BuchiAutomaton.h"
#include "Configuration.h"
#include "ProductAutomaton.h"
#include "StateSpace.h"
using namespace std;
using Graph::BuchiAutomaton;
using Graph::StateSpace;
using Graph::ProductAutomaton;
/******************************************************************************
*
@ -43,9 +43,8 @@ using Graph::ProductAutomaton;
struct AutomatonStats
{
explicit AutomatonStats /* Constructor. */
(vector<Configuration::AlgorithmInformation,
ALLOC(Configuration::AlgorithmInformation) >
::size_type number_of_algorithms,
(vector<Configuration::AlgorithmInformation>
::size_type number_of_algorithms,
StateSpace::size_type max_statespace_size);
/* default copy constructor */
@ -107,7 +106,7 @@ struct AutomatonStats
* Büchi automaton.
*/
ProductAutomaton::size_type /* Number of stats in a */
::Graph::Graph<GraphEdgeContainer>::size_type /* Number of stats in a */
number_of_product_states; /* product automaton. */
unsigned long int number_of_product_transitions; /* Number of transitions in
@ -127,9 +126,9 @@ struct AutomatonStats
typedef pair<bool, unsigned long int>
CrossComparisonStats;
vector<CrossComparisonStats, /* Emptiness check */
ALLOC(CrossComparisonStats) > /* cross-comparison */
cross_comparison_stats; /* results. The `first'
vector<CrossComparisonStats> /* Emptiness check */
cross_comparison_stats; /* cross-comparison
* results. The `first'
* element of the pair
* tells whether a cross-
* comparison with a given
@ -142,8 +141,8 @@ struct AutomatonStats
* differ.
*/
vector<int, ALLOC(int) > /* Büchi automaton */
buchi_intersection_check_stats; /* intersection
vector<int> buchi_intersection_check_stats; /* Büchi automaton
* intersection
* emptiness check
* results. The elements
* of the vector tell
@ -173,8 +172,7 @@ struct AutomatonStats
struct AlgorithmTestResults
{
explicit AlgorithmTestResults /* Constructor. */
(vector<Configuration::AlgorithmInformation,
ALLOC(Configuration::AlgorithmInformation) >
(vector<Configuration::AlgorithmInformation>
::size_type
number_of_algorithms,
StateSpace::size_type max_statespace_size);
@ -214,8 +212,8 @@ struct AlgorithmTestResults
* check.
*/
vector<AutomatonStats, ALLOC(AutomatonStats) > /* A two-element vector */
automaton_stats; /* storing test results
vector<AutomatonStats> automaton_stats; /* A two-element vector
* storing test results
* for an algorithm.
*/
};
@ -232,8 +230,7 @@ struct AlgorithmTestResults
struct TestStatistics
{
explicit TestStatistics /* Constructor. */
(vector<TestStatistics,
ALLOC(TestStatistics) >::size_type
(vector<TestStatistics>::size_type
number_of_algorithms);
/* default copy constructor */
@ -270,29 +267,21 @@ struct TestStatistics
* checks performed.
*/
unsigned long int /* Total number of */
total_number_of_buchi_states[2]; /* states in all the
* generated Büchi
* automata.
BIGUINT total_number_of_buchi_states[2]; /* Total number of states
* in all the generated
* Büchi automata.
*/
unsigned long int /* Total number of */
total_number_of_buchi_transitions[2]; /* transitions in all
BIGUINT total_number_of_buchi_transitions[2]; /* Total number of
* transitions in all
* the generated Büchi
* automata.
*/
unsigned long int /* Total number of sets */
total_number_of_acceptance_sets[2]; /* of accepting states
* in all the generated
* Büchi automata.
*/
unsigned long int /* Total number of */
total_number_of_msccs[2]; /* maximal strongly
* connected components
* in the generated
* Büchi automata.
BIGUINT total_number_of_acceptance_sets[2]; /* Total number of sets of
* accepting states in all
* the generated Büchi
* automata.
*/
double total_buchi_generation_time[2]; /* Total time used when
@ -300,36 +289,37 @@ struct TestStatistics
* automata.
*/
unsigned long int /* Total number of */
total_number_of_product_states[2]; /* states in all the
BIGUINT total_number_of_product_states[2]; /* Total number of states
* in all the generated
* product automata.
*/
BIGUINT total_number_of_product_transitions[2]; /* Total number of
* transitions in all the
* generated product
* automata.
*/
unsigned long int /* Total number of */
total_number_of_product_transitions[2]; /* transitions in all the
* generated product
* automata.
vector<unsigned long int> /* Number of failed */
cross_comparison_mismatches; /* result cross-
* comparisons.
*/
vector<unsigned long int, /* Number of failed */
ALLOC(unsigned long int) > /* result cross- */
cross_comparison_mismatches; /* comparisons. */
vector<unsigned long int, /* Number of failed */
ALLOC(unsigned long int) > /* result cross- */
initial_cross_comparison_mismatches; /* comparisons in the
vector<unsigned long int> /* Number of failed */
initial_cross_comparison_mismatches; /* result cross-
* comparisons in the
* initial state of the
* state space.
*/
vector<unsigned long int, /* Number of result */
ALLOC(unsigned long int) > /* cross-comparisons */
cross_comparisons_performed; /* performed. */
vector<unsigned long int> /* Number of result */
cross_comparisons_performed; /* cross-comparisons
* performed.
*/
vector<unsigned long int, /* Number of failed */
ALLOC(unsigned long int) > /* Büchi automaton */
buchi_intersection_check_failures; /* emptiness checks
vector<unsigned long int> /* Number of failed */
buchi_intersection_check_failures; /* Büchi automaton
* emptiness checks
* against the automata
* constructed from the
* negated formula
@ -337,9 +327,9 @@ struct TestStatistics
* algorithms.
*/
vector<unsigned long int, /* Number of Büchi */
ALLOC(unsigned long int) > /* automaton emptiness */
buchi_intersection_checks_performed; /* checks performed
vector<unsigned long int> /* Number of Büchi */
buchi_intersection_checks_performed; /* automaton emptiness
* checks performed
* against the automata
* constructed from the
* negated formula using
@ -357,9 +347,7 @@ struct TestStatistics
/* ========================================================================= */
inline AutomatonStats::AutomatonStats
(vector<Configuration::AlgorithmInformation,
ALLOC(Configuration::AlgorithmInformation) >::size_type
number_of_algorithms,
(vector<Configuration::AlgorithmInformation>::size_type number_of_algorithms,
StateSpace::size_type max_statespace_size) :
buchi_automaton(0), number_of_buchi_states(0),
number_of_buchi_transitions(0), number_of_acceptance_sets(0),
@ -481,9 +469,7 @@ AutomatonStats::buchiIntersectionCheckPerformed(unsigned long int algorithm)
/* ========================================================================= */
inline AlgorithmTestResults::AlgorithmTestResults
(vector<Configuration::AlgorithmInformation,
ALLOC(Configuration::AlgorithmInformation) >::size_type
number_of_algorithms,
(vector<Configuration::AlgorithmInformation>::size_type number_of_algorithms,
StateSpace::size_type max_statespace_size) :
consistency_check_result(-1), consistency_check_comparisons(0),
failed_consistency_check_comparisons(0),
@ -528,8 +514,7 @@ inline AlgorithmTestResults::~AlgorithmTestResults()
/* ========================================================================= */
inline TestStatistics::TestStatistics
(vector<TestStatistics, ALLOC(TestStatistics) >::size_type
number_of_algorithms) :
(vector<TestStatistics>::size_type number_of_algorithms) :
consistency_check_failures(0), consistency_checks_performed(0),
cross_comparison_mismatches(number_of_algorithms, 0),
initial_cross_comparison_mismatches(number_of_algorithms, 0),
@ -556,7 +541,6 @@ inline TestStatistics::TestStatistics
total_number_of_buchi_states[i] = 0;
total_number_of_buchi_transitions[i] = 0;
total_number_of_acceptance_sets[i] = 0;
total_number_of_msccs[i] = 0;
total_number_of_product_states[i] = 0;
total_number_of_product_transitions[i] = 0;
total_buchi_generation_time[i] = 0.0;

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -17,10 +17,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifdef __GNUC__
#pragma implementation
#endif /* __GNUC__ */
#include <config.h>
#include <csignal>
#include <cstdio>
@ -32,7 +28,6 @@
#include <strstream>
#endif /* HAVE_SSTREAM */
#include "DispUtil.h"
#include "ProductAutomaton.h"
#include "SharedTestData.h"
#include "StatDisplay.h"
#include "StringUtil.h"
@ -50,6 +45,13 @@
#include <readline/history.h>
#endif /* HAVE_READLINE */
#ifdef HAVE_ISATTY
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#endif /* HAVE_ISATTY */
/******************************************************************************
*
@ -84,7 +86,7 @@ void executeUserCommands()
* ------------------------------------------------------------------------ */
{
string input_line;
vector<string, ALLOC(string) > input_tokens;
vector<string> input_tokens;
TokenType token;
bool formula_type = true;
@ -115,9 +117,6 @@ void executeUserCommands()
{
#endif /* HAVE_READLINE */
ProductAutomaton* product_automaton = 0;
pair<unsigned long int, bool> last_computed_product_automaton;
signal(SIGPIPE, SIG_IGN);
while (1)
@ -131,47 +130,86 @@ void executeUserCommands()
input_line = line;
else
{
round_info.cout << '\n';
round_info.cout.flush();
}
#else
round_info.cout << prompt;
round_info.cout.flush();
getline(cin, input_line, '\n');
if (cin.eof())
{
round_info.cout << '\n';
round_info.cout.flush();
cin.clear();
#endif /* HAVE_READLINE */
#ifdef HAVE_ISATTY
/*
* If standard input is not bound to a terminal, act on EOF as if the
* `continue' command had been issued. Otherwise act as if an empty
* line was given as input.
*/
if (!isatty(STDIN_FILENO))
input_line = "continue";
else
{
round_info.cout << '\n';
round_info.cout.flush();
}
#else
input_line = "continue";
round_info.cout << input_line << '\n';
round_info.cout.flush();
#endif /* HAVE_ISATTY */
}
#ifdef HAVE_ISATTY
if (!isatty(STDIN_FILENO))
{
round_info.cout << input_line << '\n';
round_info.cout.flush();
}
#endif /* HAVE_ISATTY */
#ifdef HAVE_READLINE
if (line != static_cast<char*>(0) /* line may be 0 on EOF */
&& input_line.find_first_not_of(" \t") != string::npos)
{
add_history(line);
free(line);
}
#endif /* HAVE_READLINE */
/*
* If the input line contains an unescaped pipe symbol ('|') outside
* quotes, extract an external command from the line.
*/
external_command = "";
string::size_type pipe_pos = input_line.find_first_of('|');
if (pipe_pos != string::npos)
string::size_type pos
= findInQuotedString(input_line, "|", OUTSIDE_QUOTES);
if (pos != string::npos)
{
string::size_type nonspace_pos
= input_line.find_first_not_of(" \t", pipe_pos + 1);
= input_line.find_first_not_of(" \t", pos + 1);
if (nonspace_pos != string::npos)
{
external_command = input_line.substr(nonspace_pos);
input_line = input_line.substr(0, pipe_pos);
input_line = input_line.substr(0, pos);
}
}
sliceString(input_line, " \t", input_tokens);
sliceString(substituteInQuotedString(input_line, " \t", "\n\n",
OUTSIDE_QUOTES),
"\n",
input_tokens);
user_break = false;
if (!input_tokens.empty() || !external_command.empty())
{
round_info.cout << '\n';
round_info.cout.flush();
}
if (!input_tokens.empty())
{
#ifdef HAVE_READLINE
add_history(line);
free(line);
#endif /* HAVE_READLINE */
round_info.cout << '\n';
round_info.cout.flush();
token = parseCommand(input_tokens[0]);
if (token == CONTINUE || token == SKIP)
@ -192,9 +230,7 @@ void executeUserCommands()
{
bool all_algorithms_disabled = true;
for (vector<Configuration::AlgorithmInformation,
ALLOC(Configuration::AlgorithmInformation) >
::const_iterator
for (vector<Configuration::AlgorithmInformation>::const_iterator
algorithm = configuration.algorithms.begin();
algorithm != configuration.algorithms.end();
++algorithm)
@ -379,8 +415,7 @@ void executeUserCommands()
case BUCHIANALYZE :
verifyArgumentCount(input_tokens, 2, 2);
printAutomatonAnalysisResults(*output_stream, indent,
parseNumber(input_tokens[1]),
parseNumber(input_tokens[2]));
input_tokens);
if (output_file != 0)
round_info.cout << " Büchi automaton intersection emptiness "
"check analysis";
@ -403,8 +438,8 @@ void executeUserCommands()
break;
case FORMULA :
verifyArgumentCount(input_tokens, 0, 0);
printFormula(*output_stream, indent, formula_type);
verifyArgumentCount(input_tokens, 0, 1);
printFormula(*output_stream, indent, formula_type, input_tokens);
if (output_file != 0)
round_info.cout << string(" ") + (formula_type
? "Formula"
@ -431,8 +466,7 @@ void executeUserCommands()
case RESULTANALYZE :
verifyArgumentCount(input_tokens, 2, 3);
printCrossComparisonAnalysisResults
(*output_stream, indent, formula_type, input_tokens,
product_automaton, last_computed_product_automaton);
(*output_stream, indent, formula_type, input_tokens);
if (output_file != 0)
round_info.cout << " Model checking result cross-comparison "
"analysis";
@ -474,8 +508,8 @@ void executeUserCommands()
break;
default :
throw CommandErrorException("Unknown command (`"
+ input_tokens[0] + "').");
throw CommandErrorException("Unknown command (`" + input_tokens[0]
+ "').");
}
if (output_string != 0)
@ -486,21 +520,17 @@ void executeUserCommands()
FILE* output_pipe = popen(external_command.c_str(), "w");
if (output_pipe == NULL)
throw ExecFailedException(external_command);
int status = fputs(outstring.c_str(), output_pipe);
if (status != EOF)
fflush(output_pipe);
fputs(outstring.c_str(), output_pipe);
pclose(output_pipe);
round_info.cout << '\n';
round_info.cout.flush();
if (status == EOF)
throw IOException("Error writing to pipe.");
}
else if (output_file != 0)
else
{
round_info.cout << string(redirection_info.second
? " appended"
: " written")
+ " to `" + redirection_info.first + "'.\n\n";
if (output_file != 0)
round_info.cout << string(redirection_info.second
? " appended"
: " written")
+ " to `" + redirection_info.first + "'.\n";
round_info.cout << '\n';
round_info.cout.flush();
}
}
@ -533,16 +563,6 @@ void executeUserCommands()
}
}
if (product_automaton != 0)
{
::DispUtil::printText
("<cleaning up memory allocated for product automaton>", 4, 2);
delete product_automaton;
::DispUtil::printText(" ok\n", 4);
}
#ifdef HAVE_READLINE
}
catch (...)
@ -555,7 +575,7 @@ void executeUserCommands()
#endif /* HAVE_READLINE */
signal(SIGPIPE, SIG_DFL);
}
}
/* ========================================================================= */
TokenType parseCommand(const string& token)
@ -570,19 +590,6 @@ TokenType parseCommand(const string& token)
*
* ------------------------------------------------------------------------- */
{
/*
* gcc versions prior to version 3 do not conform to the C++ standard in their
* support for the string::compare functions. Use a macro to fix this if
* necessary.
*/
#ifdef __GNUC__
#if __GNUC__ < 3
#define compare(start,end,str,dummy) compare(str,start,end)
#endif
#endif
TokenType token_type = UNKNOWN;
string::size_type len = token.length();
bool ambiguous = false;
@ -679,8 +686,19 @@ TokenType parseCommand(const string& token)
break;
case 'i' :
if (token.compare(1, len - 1, "nconsistencies", len - 1) == 0)
token_type = INCONSISTENCIES;
if (len < 2)
ambiguous = true;
else if (token[1] == 'm')
{
if (token.compare(2, len - 2, "plementations", len - 2) == 0)
token_type = ALGORITHMS;
}
else if (token[1] == 'n')
{
if (token.compare(2, len - 2, "consistencies", len - 2) == 0)
token_type = INCONSISTENCIES;
}
break;
case 'q' :
@ -760,6 +778,11 @@ TokenType parseCommand(const string& token)
}
break;
case 't' :
if (token.compare(1, len - 1, "ranslators", len - 1) == 0)
token_type = ALGORITHMS;
break;
case 'v' :
if (token.compare(1, len - 1, "erbosity", len - 1) == 0)
token_type = VERBOSITY;
@ -770,19 +793,12 @@ TokenType parseCommand(const string& token)
throw CommandErrorException("Ambiguous command.");
return token_type;
#ifdef __GNUC__
#if __GNUC__ < 3
#undef compare
#endif
#endif
}
/* ========================================================================= */
void verifyArgumentCount
(const vector<string, ALLOC(string) >& command,
vector<string, ALLOC(string) >::size_type min_arg_count,
vector<string, ALLOC(string) >::size_type max_arg_count)
(const vector<string>& command, vector<string>::size_type min_arg_count,
vector<string>::size_type max_arg_count)
/* ----------------------------------------------------------------------------
*
* Description: Verifies that the number of arguments given for a user
@ -805,8 +821,7 @@ void verifyArgumentCount
}
/* ========================================================================= */
pair<string, bool> parseRedirection
(vector<string, ALLOC(string) >& input_tokens)
pair<string, bool> parseRedirection(vector<string>& input_tokens)
/* ----------------------------------------------------------------------------
*
* Description: Tests whether the last argument to a user command specifies
@ -840,13 +855,13 @@ pair<string, bool> parseRedirection
if (token.length() > 2)
{
append = true;
filename = token.substr(2);
filename = unquoteString(token.substr(2));
input_tokens.pop_back();
}
}
else
{
filename = token.substr(1);
filename = unquoteString(token.substr(1));
input_tokens.pop_back();
}
}
@ -855,10 +870,9 @@ pair<string, bool> parseRedirection
{
string& token = *(input_tokens.rbegin() + 1);
if (token[0] == '>' && (token.length() == 1
|| (token.length() == 2 && token[1] == '>')))
if (token == ">" || token == ">>")
{
filename = input_tokens.back();
filename = unquoteString(input_tokens.back());
append = (token.length() == 2);
input_tokens.pop_back();
input_tokens.pop_back();
@ -870,7 +884,7 @@ pair<string, bool> parseRedirection
}
/* ========================================================================= */
bool parseFormulaType(vector<string, ALLOC(string) >& input_tokens)
bool parseFormulaType(vector<string>& input_tokens)
/* ----------------------------------------------------------------------------
*
* Description: Tests whether the first argument of a command specifies a
@ -894,8 +908,7 @@ bool parseFormulaType(vector<string, ALLOC(string) >& input_tokens)
{
formula_type = (input_tokens[1] != "-");
if (input_tokens[1].length() == 1
&& (input_tokens[1][0] == '+' || input_tokens[1][0] == '-'))
if (input_tokens[1] == "+" || input_tokens[1] == "-")
input_tokens.erase(input_tokens.begin());
}

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -65,22 +65,19 @@ TokenType parseCommand(const string& token); /* Translates a command
*/
void verifyArgumentCount /* Checks that the */
(const vector<string, ALLOC(string) >& /* number of arguments */
arguments, /* for a command is */
vector<string, ALLOC(string) >::size_type /* within given limits. */
min_arg_count,
vector<string, ALLOC(string) >::size_type
max_arg_count);
(const vector<string>& arguments, /* number of arguments */
vector<string>::size_type min_arg_count, /* for a command is */
vector<string>::size_type max_arg_count); /* within given limits. */
pair<string, bool> parseRedirection /* Checks whether an */
(vector<string, ALLOC(string) >& input_tokens); /* user command given
(vector<string>& input_tokens); /* user command given
* will require
* redirecting its
* output to a file.
*/
bool parseFormulaType /* Checks whether an */
(vector<string, ALLOC(string) >& input_tokens); /* user command
(vector<string>& input_tokens); /* user command
* specified a positive
* or a negative
* formula.

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -23,13 +23,17 @@
#include <config.h>
#include <deque>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <utility>
#include "LbttAlloc.h"
#include "BuchiAutomaton.h"
#include "Configuration.h"
#include "ProductAutomaton.h"
#include "EdgeContainer.h"
#include "Graph.h"
#include "IntervalList.h"
#include "Product.h"
#include "StateSpace.h"
using namespace std;
@ -45,119 +49,102 @@ extern Configuration configuration;
namespace UserCommands
{
void computeProductAutomaton /* Computes a product */
(ProductAutomaton*& product_automaton, /* automaton. */
const BuchiAutomaton& buchi_automaton,
pair<unsigned long int, bool>& last_automaton,
const pair<unsigned long int, bool>&
new_automaton);
unsigned long int parseAlgorithmId /* Parses an */
(const string& id); /* implementation
* identifier.
*/
void parseAlgorithmId /* Parses a list of */
(const string& ids, IntervalList& algorithms); /* implementation
* identifiers.
*/
void printAlgorithmList /* Displays a list of */
(ostream& stream, int indent); /* algorithms used in
* the tests.
*/
void synchronizePrefixAndCycle /* Synchronizes a prefix */
(deque<Graph::Graph<GraphEdgeContainer> /* with a cycle in a */
::size_type, /* sequence of graph */
ALLOC(Graph::Graph<GraphEdgeContainer> /* state identifiers. */
::size_type) >&
prefix,
deque<Graph::Graph<GraphEdgeContainer>
::size_type,
ALLOC(Graph::Graph<GraphEdgeContainer>
::size_type) >&
cycle);
void printCrossComparisonAnalysisResults /* Analyzes a */
(ostream& stream, int indent, /* contradiction between */
bool formula_type, /* test results of two */
const vector<string, ALLOC(string) >& /* implementations. */
input_tokens,
ProductAutomaton*& product_automaton,
pair<unsigned long int, bool>&
last_product_automaton);
const vector<string>& input_tokens); /* implementations. */
void printConsistencyAnalysisResults /* Analyzes a */
(ostream& stream, int indent, /* contradicition in the */
const vector<string, ALLOC(string) >& /* model checking result */
input_tokens); /* consistency check for
const vector<string>& input_tokens); /* model checking result
* consistency check for
* an implementation.
*/
void printAutomatonAnalysisResults /* Analyzes a */
(ostream& stream, int indent, /* contradiction in the */
unsigned long int algorithm1, /* Büchi automata */
unsigned long int algorithm2); /* intersection
const vector<string>& input_tokens); /* Büchi automata
* intersection
* emptiness check.
*/
void printPath /* Displays information */
(ostream& stream, int indent, /* about a single */
const deque<StateSpace::size_type, /* system execution. */
ALLOC(StateSpace::size_type) >&
prefix,
const deque<StateSpace::size_type,
ALLOC(StateSpace::size_type) >&
cycle,
const StateSpace::Path& prefix, /* system execution. */
const StateSpace::Path& cycle,
const StateSpace& path);
void printAcceptingCycle /* Displays information */
(ostream& stream, int indent, /* a single automaton */
vector<Configuration::AlgorithmInformation, /* execution. */
ALLOC(Configuration::AlgorithmInformation) >
vector<Configuration::AlgorithmInformation> /* execution. */
::size_type
algorithm_id,
const deque<StateSpace::size_type,
ALLOC(StateSpace::size_type) >&
prefix,
const deque<StateSpace::size_type,
ALLOC(StateSpace::size_type) >&
cycle,
const BuchiAutomaton& automaton);
const BuchiAutomaton::Path& aut_prefix,
const BuchiAutomaton::Path& aut_cycle,
const BuchiAutomaton& automaton,
const StateSpace::Path& path_prefix,
const StateSpace::Path& path_cycle,
const StateSpace& statespace);
void printBuchiAutomaton /* Displays information */
(ostream& stream, int indent, /* about a Büchi */
bool formula_type, /* automaton. */
vector<string, ALLOC(string) >& input_tokens,
vector<string>& input_tokens,
Graph::GraphOutputFormat fmt);
void evaluateFormula /* Displays information */
(ostream& stream, int indent, /* about existence of */
bool formula_type, /* accepting system */
vector<string, ALLOC(string) >& input_tokens); /* executions. */
vector<string>& input_tokens); /* executions. */
void printFormula /* Displays a formula */
(ostream& stream, int indent, /* used for testing. */
bool formula_type);
bool formula_type,
const vector<string>& input_tokens);
void printCommandHelp /* Displays help about */
(ostream& stream, int indent, /* user commands. */
const vector<string, ALLOC(string) >&
input_tokens);
const vector<string>& input_tokens);
void printInconsistencies /* Lists the system */
(ostream& stream, int indent, /* states failing the */
vector<string, ALLOC(string) >& input_tokens); /* consistency check
vector<string>& input_tokens); /* consistency check
* for an algorihm.
*/
void printTestResults /* Displays the test */
(ostream& stream, int indent, /* results of the last */
vector<string, ALLOC(string) >& input_tokens); /* round performed. */
vector<string>& input_tokens); /* round performed. */
void printStateSpace /* Displays information */
(ostream& stream, int indent, /* about a state space. */
vector<string, ALLOC(string) >& input_tokens,
vector<string>& input_tokens,
Graph::GraphOutputFormat fmt);
void changeVerbosity /* Displays or changes */
(const vector<string, ALLOC(string) >& /* the verbosity of */
input_tokens); /* output. */
(const vector<string>& input_tokens); /* the verbosity of
* output.
*/
void changeAlgorithmState /* Enables or disables a */
(vector<string, ALLOC(string) >& input_tokens, /* set of algorithms */
bool enable); /* used in the tests. */
(vector<string>& input_tokens, bool enable); /* set of algorithms
* used in the tests.
*/
}

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -21,6 +21,9 @@
#include <csignal>
#include <cstdlib>
#include <ctime>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif /* HAVE_SYS_TYPES_H */
#include <iostream>
#include <vector>
#ifdef HAVE_READLINE
@ -28,6 +31,11 @@
#include <readline/readline.h>
#include <readline/history.h>
#endif /* HAVE_READLINE */
#ifdef HAVE_ISATTY
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#endif /* HAVE_ISATTY */
#include "LbttAlloc.h"
#include "Configuration.h"
#include "DispUtil.h"
@ -36,6 +44,7 @@
#include "Random.h"
#include "SharedTestData.h"
#include "StatDisplay.h"
#include "TempFsysName.h"
#include "TestOperations.h"
#include "TestRoundInfo.h"
#include "TestStatistics.h"
@ -43,17 +52,6 @@
using namespace std;
/******************************************************************************
*
* Handler for the SIGINT signal.
*
*****************************************************************************/
RETSIGTYPE breakHandler(int)
{
user_break = true;
}
/******************************************************************************
@ -92,12 +90,12 @@ TestRoundInfo round_info; /* Data structure for
* round.
*/
vector<AlgorithmTestResults, /* Test results for each */
ALLOC(AlgorithmTestResults) > /* individual algorithm. */
test_results;
vector<AlgorithmTestResults> test_results; /* Test results for each
* individual algorithm.
*/
vector<TestStatistics, ALLOC(TestStatistics) > /* Overall test */
final_statistics; /* statistics for each
vector<TestStatistics> final_statistics; /* Overall test
* statistics for each
* algorithm.
*/
@ -105,13 +103,124 @@ vector<TestStatistics, ALLOC(TestStatistics) > /* Overall test */
/******************************************************************************
*
* Functions for allocating and deallocating temporary file names.
*
*****************************************************************************/
static void allocateTempFilenames()
{
using SharedTestData::round_info;
round_info.formula_file_name[0] = new TempFsysName;
round_info.formula_file_name[0]->allocate("lbtt");
round_info.formula_file_name[1] = new TempFsysName;
round_info.formula_file_name[1]->allocate("lbtt");
round_info.automaton_file_name = new TempFsysName;
round_info.automaton_file_name->allocate("lbtt");
round_info.cout_capture_file = new TempFsysName;
round_info.cout_capture_file->allocate("lbtt");
round_info.cerr_capture_file = new TempFsysName;
round_info.cerr_capture_file->allocate("lbtt");
}
static void deallocateTempFilenames()
{
using SharedTestData::round_info;
if (round_info.formula_file_name[0] != 0)
{
delete round_info.formula_file_name[0];
round_info.formula_file_name[0] = 0;
}
if (round_info.formula_file_name[1] != 0)
{
delete round_info.formula_file_name[1];
round_info.formula_file_name[1] = 0;
}
if (round_info.automaton_file_name != 0)
{
delete round_info.automaton_file_name;
round_info.automaton_file_name = 0;
}
if (round_info.cout_capture_file != 0)
{
delete round_info.cout_capture_file;
round_info.cout_capture_file = 0;
}
if (round_info.cerr_capture_file != 0)
{
delete round_info.cerr_capture_file;
round_info.cerr_capture_file = 0;
}
}
/******************************************************************************
*
* Handler for the SIGINT signal.
*
*****************************************************************************/
static void breakHandler(int)
{
user_break = true;
}
/******************************************************************************
*
* Default handler for signals that terminate the process.
*
*****************************************************************************/
pid_t translator_process = 0; /* Process group for translator process */
static void abortHandler(int signum)
{
deallocateTempFilenames();
if (translator_process != 0 && kill(translator_process, 0) == 0)
kill(-translator_process, SIGTERM);
struct sigaction s;
s.sa_handler = SIG_DFL;
sigemptyset(&s.sa_mask);
s.sa_flags = 0;
sigaction(signum, &s, static_cast<struct sigaction*>(0));
raise(signum);
}
/******************************************************************************
*
* Function for installing signal handlers.
*
*****************************************************************************/
static void installSignalHandler(int signum, void (*handler)(int))
{
struct sigaction s;
sigaction(signum, static_cast<struct sigaction*>(0), &s);
if (s.sa_handler != SIG_IGN)
{
s.sa_handler = handler;
sigemptyset(&s.sa_mask);
s.sa_flags = 0;
sigaction(signum, &s, static_cast<struct sigaction*>(0));
}
}
/******************************************************************************
*
* Test loop.
*
*****************************************************************************/
int testLoop()
bool testLoop()
{
using namespace DispUtil;
using namespace SharedTestData;
@ -119,9 +228,6 @@ int testLoop()
using namespace StringUtil;
using namespace TestOperations;
/* Return code. Will be set to 1 if any of the test fails. */
int exit_status = 0;
const Configuration::GlobalConfiguration& global_options
= configuration.global_options;
@ -139,13 +245,6 @@ int testLoop()
? round_info.next_round_to_run
: global_options.number_of_rounds + 1);
if (tmpnam(round_info.formula_file_name[0]) == 0
|| tmpnam(round_info.formula_file_name[1]) == 0
|| tmpnam(round_info.automaton_file_name) == 0
|| tmpnam(round_info.cout_capture_file) == 0
|| tmpnam(round_info.cerr_capture_file) == 0)
throw Exception("unable to allocate names for temporary files");
/*
* If a name for the error log file was given in the configuration, create
* the file.
@ -173,9 +272,9 @@ int testLoop()
try
{
round_info.transcript_file << "lbtt " PACKAGE_VERSION
" error log file, created on "
+ string(ctime(&current_time))
+ '\n';
" error log file, created on "
+ string(ctime(&current_time))
+ '\n';
configuration.print(round_info.transcript_file);
}
@ -187,16 +286,24 @@ int testLoop()
/*
* If a formula file name was given in the configuration, open the file for
* reading.
* reading. The special filename "-" refers to the standard input.
*/
try
{
if (!global_options.formula_input_filename.empty())
openFile(global_options.formula_input_filename.c_str(),
round_info.formula_input_file,
ios::in,
0);
{
if (global_options.formula_input_filename == "-")
round_info.formula_input_stream = &cin;
else
{
openFile(global_options.formula_input_filename.c_str(),
round_info.formula_input_file,
ios::in,
0);
round_info.formula_input_stream = &round_info.formula_input_file;
}
}
}
catch (const FileOpenException& e)
{
@ -224,19 +331,6 @@ int testLoop()
formula_random_state[i] = static_cast<short int>(LRAND(0, LONG_MAX));
#endif /* HAVE_RAND48 */
/*
* If using paths as state spaces, include the internal model checking
* algorithm in the set of algorithms.
*/
if (global_options.statespace_generation_mode & Configuration::PATH)
{
Configuration::AlgorithmInformation lbtt_info
= {new string("lbtt"), new string(), new string(), true};
configuration.algorithms.push_back(lbtt_info);
}
/*
* Intialize the vector for storing the test results for each
* implementation and the vector for collecting overall test statistics for
@ -265,30 +359,18 @@ int testLoop()
for (round_info.current_round = 1;
!round_info.abort
&& round_info.current_round <= global_options.number_of_rounds;
&& round_info.current_round <= global_options.number_of_rounds;
++round_info.current_round)
{
user_break = false;
round_info.error = false;
round_info.skip
= (round_info.current_round < round_info.next_round_to_run);
if (!round_info.skip)
{
if (!printText(string("Round ") + toString(round_info.current_round)
+ " of " + toString(global_options.number_of_rounds)
+ "\n\n",
2))
{
if (global_options.verbosity == 1)
{
if (round_info.current_round > 1)
round_info.cout << ' ';
round_info.cout << round_info.current_round;
round_info.cout.flush();
}
}
}
printText(string("Round ") + toString(round_info.current_round)
+ " of " + toString(global_options.number_of_rounds) + "\n\n",
2);
try
{
@ -299,7 +381,7 @@ int testLoop()
round_info.fresh_statespace
= ((global_options.do_comp_test || global_options.do_cons_test)
&& round_info.next_round_to_change_statespace
== round_info.current_round);
== round_info.current_round);
if (round_info.fresh_statespace)
{
@ -307,13 +389,13 @@ int testLoop()
seed48(statespace_random_state);
for (int i = 0; i < 3; i++)
statespace_random_state[i] = static_cast<short int>
(LRAND(0, LONG_MAX));
(LRAND(0, LONG_MAX));
#else
SRAND(global_options.statespace_random_seed);
configuration.global_options.statespace_random_seed
= LRAND(0, RAND_MAX);
#endif /* HAVE_RAND48 */
if (global_options.statespace_change_interval == 0)
round_info.next_round_to_change_statespace
= global_options.number_of_rounds + 1;
@ -321,8 +403,7 @@ int testLoop()
round_info.next_round_to_change_statespace
+= global_options.statespace_change_interval;
for (vector<AlgorithmTestResults, ALLOC(AlgorithmTestResults) >
::iterator it = test_results.begin();
for (vector<AlgorithmTestResults>::iterator it = test_results.begin();
it != test_results.end();
++it)
it->emptinessReset();
@ -352,7 +433,7 @@ int testLoop()
*/
round_info.fresh_formula
= (round_info.next_round_to_change_formula
= (round_info.next_round_to_change_formula
== round_info.current_round);
if (round_info.fresh_formula)
@ -375,8 +456,7 @@ int testLoop()
round_info.formula_in_file[0] = round_info.formula_in_file[1] = false;
for (vector<AlgorithmTestResults, ALLOC(AlgorithmTestResults) >
::iterator it = test_results.begin();
for (vector<AlgorithmTestResults>::iterator it = test_results.begin();
it != test_results.end();
++it)
it->fullReset();
@ -387,8 +467,8 @@ int testLoop()
{
try
{
generateFormulae(round_info.formula_input_file.is_open()
? &round_info.formula_input_file
generateFormulae(!global_options.formula_input_filename.empty()
? round_info.formula_input_stream
: 0);
}
catch (const FormulaGenerationException&)
@ -402,7 +482,7 @@ int testLoop()
if (user_break)
{
printText("[User break]\n\n", 2, 4);
printText("[User break]\n\n", 1, 4);
throw UserBreakException();
}
@ -417,12 +497,17 @@ int testLoop()
if (global_options.statespace_generation_mode & Configuration::PATH
&& (global_options.do_cons_test || global_options.do_comp_test)
&& (!test_results[round_info.number_of_translators].
automaton_stats[0].emptiness_check_performed))
&& (!test_results[round_info.number_of_translators - 1].
automaton_stats[0].emptiness_check_performed)
&& configuration.algorithms[round_info.number_of_translators - 1].
enabled)
verifyFormulaOnPath();
if (!round_info.error)
{
{
if (global_options.verbosity == 2)
::StatDisplay::printStatTableHeader(round_info.cout, 4);
unsigned long int num_enabled_implementations = 0;
for (unsigned long int algorithm_id = 0;
@ -434,81 +519,61 @@ int testLoop()
num_enabled_implementations++;
if (configuration.isInternalAlgorithm(algorithm_id))
continue;
printText(configuration.algorithmString(algorithm_id) + '\n',
2, 4);
3, 4);
for (int counter = 0; counter < 2; counter++)
{
if (user_break)
{
printText("[User break]\n\n", 2, 4);
printText("[User break]\n\n", 1, 4);
throw UserBreakException();
}
printText(string(counter == 1 ? "Negated" : "Positive")
+ " formula:\n",
2,
6);
if (global_options.verbosity == 1
|| global_options.verbosity == 2)
{
if (counter == 1)
round_info.cout << '\n';
if (global_options.verbosity == 1)
round_info.cout << round_info.current_round << ' ';
else
round_info.cout << string(4, ' ');
changeStreamFormatting(cout, 2, 0, ios::right);
round_info.cout << algorithm_id << ' ';
restoreStreamFormatting(cout);
round_info.cout << (counter == 0 ? '+' : '-') << ' ';
round_info.cout.flush();
}
else
printText(string(counter == 1 ? "Negated" : "Positive")
+ " formula:\n",
3,
6);
try
{
try
{
round_info.product_automaton = 0;
/*
* Generate a Büchi automaton using the current algorithm.
* `counter' determines the formula which is to be
* translated into an automaton; 0 denotes the positive and
* 1 the negated formula.
*/
generateBuchiAutomaton(counter, algorithm_id);
if (global_options.do_cons_test || global_options.do_comp_test)
{
/*
* Generate a Büchi automaton using the current algorithm.
* `counter' determines the formula which is to be
* translated into an automaton; 0 denotes the positive and
* 1 the negated formula.
* Find the system states from which an accepting
* execution cycle can be reached by checking the product
* automaton for emptiness.
*/
generateBuchiAutomaton(counter, algorithm_id);
if (global_options.do_cons_test
|| global_options.do_comp_test)
{
/*
* Compute the product of the Büchi automaton with the
* state space.
*/
generateProductAutomaton(counter, algorithm_id);
/*
* Find the system states from which an accepting
* execution cycle can be reached by checking the product
* automaton for emptiness.
*/
performEmptinessCheck(counter, algorithm_id);
/*
* If a product automaton was computed in this test round
* (it might have not if the emptiness checking result was
* already available), release the memory allocated for
* the product automaton.
*/
if (round_info.product_automaton != 0)
{
printText("<deallocating memory>", 4, 8);
delete round_info.product_automaton;
round_info.product_automaton = 0;
printText(" ok\n", 4);
}
}
}
catch (...)
{
if (round_info.product_automaton != 0)
{
delete round_info.product_automaton;
round_info.product_automaton = 0;
}
throw;
performEmptinessCheck(counter, algorithm_id);
}
}
catch (const BuchiAutomatonGenerationException&)
@ -544,7 +609,13 @@ int testLoop()
emptiness_check_performed)
performConsistencyCheck(algorithm_id);
printText("\n", 2);
printText("\n", 1);
}
if (global_options.verbosity == 2)
{
round_info.cout << '\n';
round_info.cout.flush();
}
if (num_enabled_implementations > 0)
@ -556,10 +627,7 @@ int testLoop()
* results obtained using the different algorithms.
*/
if (num_enabled_implementations >= 2
|| (num_enabled_implementations == 1
&& global_options.statespace_generation_mode
& Configuration::PATH))
if (num_enabled_implementations >= 2)
compareResults();
}
@ -590,33 +658,22 @@ int testLoop()
round_info.next_round_to_stop = round_info.current_round;
}
if (round_info.error)
exit_status = 1;
/*
* Determine from the program configuration and the error status whether
* the testing should be paused to wait for user commands.
*/
if (round_info.error)
round_info.all_tests_successful = false;
if (round_info.error
&& global_options.interactive == Configuration::ONERROR)
round_info.next_round_to_stop = round_info.current_round;
if (round_info.next_round_to_stop == round_info.current_round)
{
if (global_options.verbosity == 1)
{
round_info.cout << '\n';
round_info.cout.flush();
}
::UserCommandInterface::executeUserCommands();
}
}
for (int i = 0; i < 2; i++)
removeFile(round_info.formula_file_name[i], 2);
if (round_info.path_iterator != 0)
delete round_info.path_iterator;
else if (round_info.statespace != 0)
@ -628,8 +685,7 @@ int testLoop()
::Ltl::LtlFormula::destruct(round_info.formulae[f]);
}
for (vector<AlgorithmTestResults, ALLOC(AlgorithmTestResults) >
::iterator it = test_results.begin();
for (vector<AlgorithmTestResults>::iterator it = test_results.begin();
it != test_results.end();
++it)
it->fullReset();
@ -661,19 +717,19 @@ int testLoop()
time(&current_time);
round_info.transcript_file << "lbtt error log closed on "
+ string(ctime(&current_time))
+ string(ctime(&current_time))
<< endl;
round_info.transcript_file.close();
}
if (global_options.verbosity >= 1)
if (global_options.verbosity >= 2)
printCollectiveStats(cout, 0);
if (round_info.formula_input_file.is_open())
round_info.formula_input_file.close();
return exit_status;
return round_info.all_tests_successful;
}
@ -686,7 +742,7 @@ int testLoop()
int main(int argc, char* argv[])
{
try
try
{
configuration.read(argc, argv);
}
@ -697,15 +753,35 @@ int main(int argc, char* argv[])
cerr << ":" << configuration.global_options.cfg_filename << ":"
<< e.line_info;
cerr << ": " << e.what() << endl;
exit(-1);
exit(2);
}
#ifdef HAVE_ISATTY
if (configuration.global_options.formula_input_filename == "-"
&& !isatty(STDIN_FILENO))
{
configuration.global_options.interactive = Configuration::NEVER;
configuration.global_options.handle_breaks = false;
}
#endif /* HAVE_ISATTY */
if (configuration.global_options.verbosity >= 3)
configuration.print(cout);
user_break = false;
if (configuration.global_options.interactive != Configuration::NEVER)
signal(SIGINT, breakHandler);
installSignalHandler(SIGHUP, abortHandler);
installSignalHandler(SIGINT,
configuration.global_options.handle_breaks
? breakHandler
: abortHandler);
installSignalHandler(SIGQUIT, abortHandler);
installSignalHandler(SIGABRT, abortHandler);
installSignalHandler(SIGPIPE, abortHandler);
installSignalHandler(SIGALRM, abortHandler);
installSignalHandler(SIGTERM, abortHandler);
installSignalHandler(SIGUSR1, abortHandler);
installSignalHandler(SIGUSR2, abortHandler);
#ifdef HAVE_OBSTACK_H
obstack_alloc_failed_handler = &ObstackAllocator::failure;
@ -715,18 +791,28 @@ int main(int argc, char* argv[])
using_history();
#endif /* HAVE_READLINE */
try
try
{
return testLoop();
allocateTempFilenames();
if (!testLoop())
{
deallocateTempFilenames();
return 1;
}
}
catch (const Exception& e)
{
cerr << argv[0] << ": " << e.what() << endl;
exit(-1);
deallocateTempFilenames();
cerr << endl << argv[0] << ": " << e.what() << endl;
exit(3);
}
catch (const bad_alloc&)
{
cerr << argv[0] << ": out of memory" << endl;
exit(-1);
deallocateTempFilenames();
cerr << endl << argv[0] << ": out of memory" << endl;
exit(3);
}
deallocateTempFilenames();
return 0;
}

View file

@ -180,11 +180,11 @@ int main(int argc, char** argv)
case OPT_VERSION :
cout << "lbtt-translate " PACKAGE_VERSION "\n"
"lbtt-translate is free software; you may change and "
"redistribute it under the\n"
"terms of the GNU General Public License. lbtt-translate "
"comes with NO WARRANTY.\n"
"See the file COPYING for details.\n";
"lbtt-translate is free software; you may change and "
"redistribute it under the\n"
"terms of the GNU General Public License. lbtt-translate "
"comes with NO WARRANTY.\n"
"See the file COPYING for details.\n";
exit(0);
break;

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 1999, 2000, 2001, 2002
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
* Heikki Tauriainen <Heikki.Tauriainen@tkk.fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -20,10 +20,6 @@
#ifndef TRANSLATE_H
#define TRANSLATE_H
#ifdef __GNUC__
#pragma interface
#endif /* __GNUC__ */
#include <config.h>
#include <string>