// -*- coding: utf-8 -*-
// Copyright (C) 2012-2017 Laboratoire de Recherche et Développement
// de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
//
// Spot 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 3 of the License, or
// (at your option) any later version.
//
// Spot 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, see .
#pragma once
#include
namespace spot
{
class option_map;
/// \addtogroup twa_reduction
/// @{
/// \brief Wrap TGBA/BA/Monitor post-processing algorithms in an
/// easy interface.
///
/// This class is a shell around scc_filter(),
/// minimize_obligation(), simulation(), iterated_simulations(),
/// degeneralize(), to_generalized_buchi(), tgba_determinize(), and
/// other algorithms. These different algorithms will be combined
/// depending on the various options set with set_type(),
/// set_pref(), and set_level().
///
/// This helps hiding some of the logic required to combine these
/// simplifications efficiently (e.g., there is no point calling
/// degeneralize() or any simulation when minimize_obligation()
/// succeeded.)
///
/// Use set_type() to select desired output type.
///
/// Use the set_pref() method to specify whether you favor
/// deterministic automata or small automata. If you don't care,
/// less post processing will be done.
///
/// The set_level() method lets you set the optimization level.
/// A higher level enables more costly post-processings. For instance
/// pref=Small,level=High will try two different post-processings
/// (one with minimize_obligation(), and one with
/// iterated_simulations()) an keep the smallest result.
/// pref=Small,level=Medium will only try the iterated_simulations()
/// when minimized_obligation failed to produce an automaton smaller
/// than its input. pref=Small,level=Low will only run
/// simulation().
///
/// The handling of alternating automata should change in the
/// future, but currently \c Generic, \c Low, \c Any is the only
/// configuration where alternation is preserved. In any other
/// configuration, \c remove_alternation() will be called.
class SPOT_API postprocessor
{
public:
/// \brief Construct a postprocessor.
///
/// The \a opt argument can be used to pass extra fine-tuning
/// options used for debugging or benchmarking.
postprocessor(const option_map* opt = nullptr);
enum output_type { TGBA, BA, Monitor, Generic };
/// \brief Select the desired output type.
///
/// \c TGBA requires transition-based generalized Büchi acceptance
/// while \c BA requests state-based Büchi acceptance. In both
/// cases, automata with more complex acceptance conditions will
/// be converted into these simpler acceptance. For references
/// about the algorithms used behind these options, see section 5
/// of "LTL translation improvements in Spot 1.0" (Alexandre
/// Duret-Lutz. Int. J. on Critical Computer-Based Systems,
/// 5(1/2), pp. 31–54, March 2014).
///
/// \c Monitor requests an automaton where all paths are
/// accepting: this is less expressive than Büchi automata, and
/// may output automata that recognize a larger language than the
/// input (the output recognizes the smallest safety property
/// containing the input). The algorithm used to obtain monitors
/// comes from "Efficient monitoring of ω-languages" (Marcelo
/// d’Amorim and Grigoire Roşu, Proceedings of CAV’05, LNCS 3576)
/// but is better described in "Optimized Temporal Monitors for
/// SystemC" (Deian Tabakov and Moshe Y. Vardi, Proceedings of
/// RV’10, LNCS 6418).
///
/// Finally \c Generic remove all constraints about the acceptance
/// condition. Using \c Generic can be needed to force the
/// determinization of some automata (e.g., not all TGBA can be
/// degeneralized, using \c Generic will allow parity acceptance
/// to be used instead).
///
/// If set_type() is not called, the default \c output_type is \c TGBA.
void
set_type(output_type type)
{
type_ = type;
}
enum
{
Any = 0,
Small = 1, // Small and Deterministic
Deterministic = 2, // are exclusive choices.
Complete = 4,
SBAcc = 8, // State-based acceptance.
Unambiguous = 16,
};
typedef int output_pref;
/// \brief Select the desired characteristics of the output automaton.
///
/// Use \c Any if you do not care about any feature of the output
/// automaton: less processing will be done.
///
/// \c Small and \c Deterministic are exclusive choices and indicate
/// whether a smaller non-deterministic automaton should be preferred
/// over a deterministic automaton. These are preferences. The \c Small
/// option does not guarantee that the resulting automaton will be minimal.
/// The \c Deterministic option may not manage to produce a deterministic
/// automaton if the target acceptance set with set_type() is TGBA or BA
/// (and even if such automaton exists).
///
/// Use
/// \code
/// set_type(postprocessor::Generic);
/// set_pref(postprocessor::Deterministic);
/// \endcode
/// if you absolutely want a deterministic automaton. The
/// resulting deterministic automaton may have generalized Büchi
/// acceptance or parity acceptance.
///
/// The above options can be combined with \c Complete and \c
/// SBAcc, to request a complete automaton, and an automaton with
/// state-based acceptance.
///
/// Note 1: the \c Unambiguous option is not actually supported by
/// spot::postprocessor; it is only honored by spot::translator.
///
/// Note 2: for historical reasons, option \c SBAcc is implied
/// when the output type is set to \c BA.
///
/// Note 3: while setting the output type to \c Monitor requests
/// automata with \c t as acceptance condition, combining \c
/// Monitor with \c Complete may produce Büchi automata in case a
/// sink state (which should be rejecting) is added.
///
/// If set_pref() is not called, the default \c output_type is \c Small.
void
set_pref(output_pref pref)
{
pref_ = pref;
}
enum optimization_level { Low, Medium, High };
/// \brief Set the optimization level
///
/// At \c Low level, very few simplifications are performed on the
/// automaton. Use this level if you need a result that matches
/// the other constraints, but want it fast.
///
/// At \c High level, several simplifications are chained, but
/// also the result of different algorithms may be compared to
/// pick the best result. This might be slow.
///
/// At \c Medium level, several simplifications are chained, but
/// only one such "pipeline" is used.
///
/// If set_level() is not called, the default \c output_type is \c High.
void
set_level(optimization_level level)
{
level_ = level;
}
/// \brief Optimize an automaton.
///
/// The returned automaton might be a new automaton,
/// or an in-place modification of the \a input automaton.
twa_graph_ptr run(twa_graph_ptr input, formula f = nullptr);
protected:
twa_graph_ptr do_simul(const twa_graph_ptr& input, int opt);
twa_graph_ptr do_sba_simul(const twa_graph_ptr& input, int opt);
twa_graph_ptr do_degen(const twa_graph_ptr& input);
twa_graph_ptr do_scc_filter(const twa_graph_ptr& a, bool arg);
twa_graph_ptr do_scc_filter(const twa_graph_ptr& a);
output_type type_ = TGBA;
int pref_ = Small;
optimization_level level_ = High;
// Fine-tuning options fetched from the option_map.
bool degen_reset_ = true;
bool degen_order_ = false;
int degen_cache_ = 1;
bool degen_lskip_ = true;
bool degen_lowinit_ = false;
bool det_scc_ = true;
bool det_simul_ = true;
bool det_stutter_ = true;
int simul_ = -1;
int scc_filter_ = -1;
int ba_simul_ = -1;
bool tba_determinisation_ = false;
int sat_minimize_ = 0;
int sat_incr_steps_ = 0;
bool sat_langmap_ = false;
int sat_acc_ = 0;
int sat_states_ = 0;
bool state_based_ = false;
bool wdba_minimize_ = true;
};
/// @}
}