twa_graph: do not order BDDs by IDs in merge_edges()

Fixes #282.

* spot/misc/bddlt.hh (bdd_less_than_stable): New function.
* spot/twa/twagraph.cc (merge_edges): Use it.
* tests/core/genltl.test: Adjust, and add an extra test
for the behavior of #282.
* tests/core/complement.test, tests/core/degenid.test,
tests/core/ltldo.test, tests/core/prodor.test,
tests/core/readsave.test, tests/core/sbacc.test,
tests/python/atva16-fig2a.ipynb, tests/python/automata.ipynb,
tests/python/decompose.ipynb, tests/python/dualize.py,
tests/python/highlighting.ipynb, tests/python/piperead.ipynb,
tests/python/product.ipynb, tests/python/simstate.py,
tests/python/tra2tba.py: Adjust all expected outputs.
* NEWS: Mention the bug.
This commit is contained in:
Alexandre Duret-Lutz 2017-09-24 16:06:41 +02:00
parent 2bca21f7f8
commit 5e5a69488e
19 changed files with 798 additions and 735 deletions

View file

@ -1,6 +1,6 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2011, 2014 Laboratoire de Recherche et Developpement de
// l'Epita (LRDE).
// Copyright (C) 2011, 2014, 2017 Laboratoire de Recherche et
// Developpement de l'Epita (LRDE).
// Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
// et Marie Curie.
@ -29,6 +29,10 @@ namespace spot
{
/// \ingroup misc_tools
/// \brief Comparison functor for BDDs.
///
/// This comparison function use BDD ids for efficiency. An
/// algorithm depending on this order may return different results
/// depending on how the BDD library has been used before.
struct bdd_less_than :
public std::binary_function<const bdd&, const bdd&, bool>
{
@ -39,6 +43,43 @@ namespace spot
}
};
/// \ingroup misc_tools
/// \brief Comparison functor for BDDs.
///
/// This comparison function actually check for BDD variables, so as
/// long as the variable order is the same, the output of this
/// comparison will be stable and independent on previous BDD
/// operations.
struct bdd_less_than_stable :
public std::binary_function<const bdd&, const bdd&, bool>
{
bool
operator()(const bdd& left, const bdd& right) const
{
int li = left.id();
int ri = right.id();
if (li == ri)
return false;
if (li <= 1 || ri <= 1)
return li < ri;
{
int vl = bdd_var(left);
int vr = bdd_var(right);
if (vl != vr)
return vl < vr;
}
// We check the high side before low, this way
// !a&b comes before a&!b and a&b
{
bdd hl = bdd_high(left);
bdd hr = bdd_high(right);
if (hl != hr)
return operator()(hl, hr);
return operator()(bdd_low(left), bdd_low(right));
}
}
};
/// \ingroup misc_tools
/// \brief Hash functor for BDDs.
struct bdd_hash :

View file

@ -19,6 +19,7 @@
#include <spot/twa/twagraph.hh>
#include <spot/tl/print.hh>
#include <spot/misc/bddlt.hh>
#include <vector>
#include <deque>
@ -79,11 +80,11 @@ namespace spot
delete namer;
}
/// \brief Merge universal destinations
///
/// If several states have the same universal destination, merge
/// them all. Also remove unused destination, and any redundant
/// state in each destination.
/// \brief Merge universal destinations
///
/// If several states have the same universal destination, merge
/// them all. Also remove unused destination, and any redundant
/// state in each destination.
void twa_graph::merge_univ_dests()
{
auto& g = get_graph();
@ -198,7 +199,8 @@ namespace spot
return true;
if (lhs.dst > rhs.dst)
return false;
return lhs.cond.id() < rhs.cond.id();
bdd_less_than_stable lt;
return lt(lhs.cond, rhs.cond);
// Do not sort on acceptance, we'll merge
// them.
});