From 822b7491668f60a5d50b9e362f75fa4d9115f296 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Sat, 16 May 2020 16:20:39 +0200 Subject: [PATCH 01/30] product: add product_xor() and product_xnor() * spot/twaalgos/product.cc, spot/twaalgos/product.hh: Add those functions. * tests/python/_product_weak.ipynb, tests/python/except.py: Test them. * NEWS: Mention them. --- NEWS | 11 +- spot/twaalgos/product.cc | 384 +- spot/twaalgos/product.hh | 45 +- tests/python/_product_weak.ipynb | 8706 +++++++++++++++++++++++++++++- tests/python/except.py | 29 + 5 files changed, 8975 insertions(+), 200 deletions(-) diff --git a/NEWS b/NEWS index cc58fede5..a78117cb4 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,13 @@ New in spot 2.9.0.dev (not yet released) - Nothing yet. + Library: + + - product_xor() and product_xnor() are two new versions of the + synchronized product. They only work with operands that are + deterministic automata, and build automata whose language are + respectively the symmetric difference of the operands, and the + complement of that. + New in spot 2.9 (2020-04-30) @@ -19,7 +26,7 @@ New in spot 2.9 (2020-04-30) spot-rejected-word: "!a; !a; cycle{a}" - autfilt learned the --partial-degeneralize option, to remove - conjunctions of Inf, or disjunction of Fin that appears in + conjunctions of Inf, or disjunctions of Fin that appears in arbitrary conditions. - ltlfilt and autfilt learned a --nth=RANGE (a.k.a. -N) option to diff --git a/spot/twaalgos/product.cc b/spot/twaalgos/product.cc index 84efbcf32..7fb70ddd6 100644 --- a/spot/twaalgos/product.cc +++ b/spot/twaalgos/product.cc @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,6 @@ namespace spot } }; - template static void product_main(const const_twa_graph_ptr& left, @@ -100,12 +100,15 @@ namespace spot } } + enum acc_op { and_acc, or_acc, xor_acc, xnor_acc }; + + static twa_graph_ptr product_aux(const const_twa_graph_ptr& left, const const_twa_graph_ptr& right, unsigned left_state, unsigned right_state, - bool and_acc, + acc_op aop, const output_aborter* aborter) { if (SPOT_UNLIKELY(!(left->is_existential() && right->is_existential()))) @@ -122,164 +125,271 @@ namespace spot bool leftweak = left->prop_weak().is_true(); bool rightweak = right->prop_weak().is_true(); // We have optimization to the standard product in case one - // of the arguments is weak. However these optimizations - // are pointless if the said arguments are "t" or "f". - if ((leftweak || rightweak) - && (left->num_sets() > 0) && (right->num_sets() > 0)) + // of the arguments is weak. + if (leftweak || rightweak) { // If both automata are weak, we can restrict the result to - // Büchi or co-Büchi. We will favor Büchi unless the two - // operands are co-Büchi. + // t, f, Büchi or co-Büchi. We use co-Büchi only when + // t and f cannot be used, and both acceptance conditions + // are in {t,f,co-Büchi}. if (leftweak && rightweak) { weak_weak: + res->prop_weak(true); acc_cond::mark_t accmark = {0}; acc_cond::mark_t rejmark = {}; - if (left->acc().is_co_buchi() && right->acc().is_co_buchi()) + auto& lacc = left->acc(); + auto& racc = right->acc(); + if ((lacc.is_co_buchi() && (racc.is_co_buchi() + || racc.num_sets() == 0)) + || (lacc.num_sets() == 0 && racc.is_co_buchi())) { res->set_co_buchi(); std::swap(accmark, rejmark); } + else if ((aop == and_acc && lacc.is_t() && racc.is_t()) + || (aop == or_acc && (lacc.is_t() || racc.is_t())) + || (aop == xnor_acc && ((lacc.is_t() && racc.is_t()) || + (lacc.is_f() && racc.is_f()))) + || (aop == xor_acc && ((lacc.is_t() && racc.is_f()) || + (lacc.is_f() && racc.is_t())))) + { + res->set_acceptance(0, acc_cond::acc_code::t()); + accmark = {}; + } + else if ((aop == and_acc && (lacc.is_f() || racc.is_f())) + || (aop == or_acc && lacc.is_f() && racc.is_f()) + || (aop == xor_acc && ((lacc.is_t() && racc.is_t()) || + (lacc.is_f() && racc.is_f()))) + || (aop == xnor_acc && ((lacc.is_t() && racc.is_f()) || + (lacc.is_f() && racc.is_t())))) + { + res->set_acceptance(0, acc_cond::acc_code::f()); + accmark = {}; + } else { res->set_buchi(); } - res->prop_weak(true); - auto& lacc = left->acc(); - auto& racc = right->acc(); - if (and_acc) - product_main(left, right, left_state, right_state, res, - [&] (acc_cond::mark_t ml, acc_cond::mark_t mr) - { - if (lacc.accepting(ml) && racc.accepting(mr)) - return accmark; - else - return rejmark; - }, aborter); - else - product_main(left, right, left_state, right_state, res, - [&] (acc_cond::mark_t ml, acc_cond::mark_t mr) - { - if (lacc.accepting(ml) || racc.accepting(mr)) - return accmark; - else - return rejmark; - }, aborter); + switch (aop) + { + case and_acc: + product_main(left, right, left_state, right_state, res, + [&] (acc_cond::mark_t ml, acc_cond::mark_t mr) + { + if (lacc.accepting(ml) && racc.accepting(mr)) + return accmark; + else + return rejmark; + }, aborter); + break; + case or_acc: + product_main(left, right, left_state, right_state, res, + [&] (acc_cond::mark_t ml, acc_cond::mark_t mr) + { + if (lacc.accepting(ml) || racc.accepting(mr)) + return accmark; + else + return rejmark; + }, aborter); + break; + case xor_acc: + product_main(left, right, left_state, right_state, res, + [&] (acc_cond::mark_t ml, acc_cond::mark_t mr) + { + if (lacc.accepting(ml) ^ racc.accepting(mr)) + return accmark; + else + return rejmark; + }, aborter); + break; + case xnor_acc: + product_main(left, right, left_state, right_state, res, + [&] (acc_cond::mark_t ml, acc_cond::mark_t mr) + { + if (lacc.accepting(ml) == racc.accepting(mr)) + return accmark; + else + return rejmark; + }, aborter); + break; + } } else if (!rightweak) { - if (and_acc) + switch (aop) { - auto rightunsatmark = right->acc().unsat_mark(); - if (!rightunsatmark.first) - { - // Left is weak. Right was not weak, but it is - // always accepting. We can therefore pretend - // that right is weak. - goto weak_weak; - } - res->copy_acceptance_of(right); - acc_cond::mark_t rejmark = rightunsatmark.second; - auto& lacc = left->acc(); - product_main(left, right, left_state, right_state, res, - [&] (acc_cond::mark_t ml, acc_cond::mark_t mr) - { - if (lacc.accepting(ml)) - return mr; - else - return rejmark; - }, aborter); - } - else - { - auto rightsatmark = right->acc().sat_mark(); - if (!rightsatmark.first) - { - // Left is weak. Right was not weak, but it is - // always rejecting. We can therefore pretend - // that right is weak. - goto weak_weak; - } - res->copy_acceptance_of(right); - acc_cond::mark_t accmark = rightsatmark.second; - auto& lacc = left->acc(); - product_main(left, right, left_state, right_state, res, - [&] (acc_cond::mark_t ml, acc_cond::mark_t mr) - { - if (!lacc.accepting(ml)) - return mr; - else - return accmark; - }, aborter); - + case and_acc: + { + auto rightunsatmark = right->acc().unsat_mark(); + if (!rightunsatmark.first) + { + // Left is weak. Right was not weak, but it is + // always accepting. We can therefore pretend + // that right is weak. + goto weak_weak; + } + res->copy_acceptance_of(right); + acc_cond::mark_t rejmark = rightunsatmark.second; + auto& lacc = left->acc(); + product_main(left, right, left_state, right_state, res, + [&] (acc_cond::mark_t ml, acc_cond::mark_t mr) + { + if (lacc.accepting(ml)) + return mr; + else + return rejmark; + }, aborter); + break; + } + case or_acc: + { + auto rightsatmark = right->acc().sat_mark(); + if (!rightsatmark.first) + { + // Left is weak. Right was not weak, but it is + // always rejecting. We can therefore pretend + // that right is weak. + goto weak_weak; + } + res->copy_acceptance_of(right); + acc_cond::mark_t accmark = rightsatmark.second; + auto& lacc = left->acc(); + product_main(left, right, left_state, right_state, res, + [&] (acc_cond::mark_t ml, acc_cond::mark_t mr) + { + if (!lacc.accepting(ml)) + return mr; + else + return accmark; + }, aborter); + break; + } + case xor_acc: + case xnor_acc: + { + auto rightsatmark = right->acc().sat_mark(); + auto rightunsatmark = right->acc().unsat_mark(); + if (!rightunsatmark.first || !rightsatmark.first) + { + // Left is weak. Right was not weak, but it + // is either always rejecting or always + // accepting. We can therefore pretend that + // right is weak. + goto weak_weak; + } + goto generalcase; + break; + } } } - else + else // right weak { assert(!leftweak); - if (and_acc) + switch (aop) { - auto leftunsatmark = left->acc().unsat_mark(); - if (!leftunsatmark.first) - { - // Right is weak. Left was not weak, but it is - // always accepting. We can therefore pretend - // that left is weak. - goto weak_weak; - } - res->copy_acceptance_of(left); - acc_cond::mark_t rejmark = leftunsatmark.second; - auto& racc = right->acc(); - product_main(left, right, left_state, right_state, res, - [&] (acc_cond::mark_t ml, acc_cond::mark_t mr) - { - if (racc.accepting(mr)) - return ml; - else - return rejmark; - }, aborter); - } - else - { - auto leftsatmark = left->acc().sat_mark(); - if (!leftsatmark.first) - { - // Right is weak. Left was not weak, but it is - // always rejecting. We can therefore pretend - // that left is weak. - goto weak_weak; - } - res->copy_acceptance_of(left); - acc_cond::mark_t accmark = leftsatmark.second; - auto& racc = right->acc(); - product_main(left, right, left_state, right_state, res, - [&] (acc_cond::mark_t ml, acc_cond::mark_t mr) - { - if (!racc.accepting(mr)) - return ml; - else - return accmark; - }, aborter); + case and_acc: + { + auto leftunsatmark = left->acc().unsat_mark(); + if (!leftunsatmark.first) + { + // Right is weak. Left was not weak, but it is + // always accepting. We can therefore pretend + // that left is weak. + goto weak_weak; + } + res->copy_acceptance_of(left); + acc_cond::mark_t rejmark = leftunsatmark.second; + auto& racc = right->acc(); + product_main(left, right, left_state, right_state, res, + [&] (acc_cond::mark_t ml, acc_cond::mark_t mr) + { + if (racc.accepting(mr)) + return ml; + else + return rejmark; + }, aborter); + break; + } + case or_acc: + { + auto leftsatmark = left->acc().sat_mark(); + if (!leftsatmark.first) + { + // Right is weak. Left was not weak, but it is + // always rejecting. We can therefore pretend + // that left is weak. + goto weak_weak; + } + res->copy_acceptance_of(left); + acc_cond::mark_t accmark = leftsatmark.second; + auto& racc = right->acc(); + product_main(left, right, left_state, right_state, res, + [&] (acc_cond::mark_t ml, acc_cond::mark_t mr) + { + if (!racc.accepting(mr)) + return ml; + else + return accmark; + }, aborter); + break; + } + case xor_acc: + case xnor_acc: + { + auto leftsatmark = left->acc().sat_mark(); + auto leftunsatmark = left->acc().unsat_mark(); + if (!leftunsatmark.first || !leftsatmark.first) + { + // Right is weak. Left was not weak, but it + // is either always rejecting or always + // accepting. We can therefore pretend that + // left is weak. + goto weak_weak; + } + goto generalcase; + break; + } } } } else // general case { + generalcase: auto left_num = left->num_sets(); + auto& left_acc = left->get_acceptance(); auto right_acc = right->get_acceptance() << left_num; - if (and_acc) - right_acc &= left->get_acceptance(); - else - right_acc |= left->get_acceptance(); + switch (aop) + { + case and_acc: + right_acc &= left_acc; + break; + case or_acc: + right_acc |= left_acc; + break; + case xor_acc: + { + auto tmp = right_acc.complement() & left_acc; + right_acc &= left_acc.complement(); + right_acc |= tmp; + break; + } + case xnor_acc: + { + auto tmp = right_acc.complement() & left_acc.complement(); + right_acc &= left_acc; + tmp |= right_acc; + std::swap(tmp, right_acc); + break; + } + } res->set_acceptance(left_num + right->num_sets(), right_acc); - product_main(left, right, left_state, right_state, res, [&] (acc_cond::mark_t ml, acc_cond::mark_t mr) { return ml | (mr << left_num); }, aborter); - } if (!res) // aborted @@ -323,7 +433,7 @@ namespace spot unsigned right_state, const output_aborter* aborter) { - return product_aux(left, right, left_state, right_state, true, aborter); + return product_aux(left, right, left_state, right_state, and_acc, aborter); } twa_graph_ptr product(const const_twa_graph_ptr& left, @@ -341,7 +451,7 @@ namespace spot unsigned right_state) { return product_aux(complete(left), complete(right), - left_state, right_state, false, nullptr); + left_state, right_state, or_acc, nullptr); } twa_graph_ptr product_or(const const_twa_graph_ptr& left, @@ -352,6 +462,32 @@ namespace spot right->get_init_state_number()); } + twa_graph_ptr product_xor(const const_twa_graph_ptr& left, + const const_twa_graph_ptr& right) + { + if (SPOT_UNLIKELY(!is_deterministic(left) || !is_deterministic(right))) + throw std::runtime_error + ("product_xor() only works with deterministic automata"); + + return product_aux(complete(left), complete(right), + left->get_init_state_number(), + right->get_init_state_number(), + xor_acc, nullptr); + } + + twa_graph_ptr product_xnor(const const_twa_graph_ptr& left, + const const_twa_graph_ptr& right) + { + if (SPOT_UNLIKELY(!is_deterministic(left) || !is_deterministic(right))) + throw std::runtime_error + ("product_xnor() only works with deterministic automata"); + + return product_aux(complete(left), complete(right), + left->get_init_state_number(), + right->get_init_state_number(), + xnor_acc, nullptr); + } + namespace { diff --git a/spot/twaalgos/product.hh b/spot/twaalgos/product.hh index e78b18f7c..49ee9acdf 100644 --- a/spot/twaalgos/product.hh +++ b/spot/twaalgos/product.hh @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2014, 2015, 2018, 2019 Laboratoire de Recherche et +// Copyright (C) 2014-2015, 2018-2020 Laboratoire de Recherche et // Développement de l'Epita (LRDE). // // This file is part of Spot, a model checking library. @@ -127,6 +127,45 @@ namespace spot unsigned left_state, unsigned right_state); + /// \ingroup twa_algorithms + /// \brief XOR two deterministic automata using a synchronous product + /// + /// The two operands must be deterministic. + /// + /// The resulting automaton will accept the symmetric difference of + /// both languages and have an acceptance condition that is the xor + /// of the acceptance conditions of the two input automata. In case + /// both operands are weak, the acceptance condition of the result + /// is made simpler. + /// + /// The algorithm also defines a named property called + /// "product-states" with type spot::product_states. This stores + /// the pair of original state numbers associated to each state of + /// the product. + SPOT_API + twa_graph_ptr product_xor(const const_twa_graph_ptr& left, + const const_twa_graph_ptr& right); + + /// \ingroup twa_algorithms + /// \brief XNOR two automata using a synchronous product + /// + /// The two operands must be deterministic. + /// + /// The resulting automaton will accept words that are either in + /// both input languages, or not in both languages. (The XNOR gate + /// it the logical complement of XOR. XNOR is also known as logical + /// equivalence.) The output will have an acceptance condition that + /// is the XNOR of the acceptance conditions of the two input + /// automata. In case both the operands are weak, the acceptance + /// condition of the result is made simpler. + /// + /// The algorithm also defines a named property called + /// "product-states" with type spot::product_states. This stores + /// the pair of original state numbers associated to each state of + /// the product. + SPOT_API + twa_graph_ptr product_xnor(const const_twa_graph_ptr& left, + const const_twa_graph_ptr& right); /// \ingroup twa_algorithms /// \brief Build the product of an automaton with a suspendable @@ -136,7 +175,7 @@ namespace spot /// languages of both input automata. /// /// This function *assumes* that \a right_susp is a suspendable - /// automaton, i.e., it its language L satisfies L = Σ*.L. + /// automaton, i.e., its language L satisfies L = Σ*.L. /// Therefore the product between the two automata need only be done /// with the accepting SCCs of left. /// @@ -155,7 +194,7 @@ namespace spot /// both input automata. /// /// This function *assumes* that \a right_susp is a suspendable - /// automaton, i.e., it its language L satisfies L = Σ*.L. + /// automaton, i.e., its language L satisfies L = Σ*.L. /// Therefore, after left has been completed (this will be done by /// product_or_susp) the product between the two automata need only /// be done with the SCCs of left that contains some rejecting cycles. diff --git a/tests/python/_product_weak.ipynb b/tests/python/_product_weak.ipynb index 093d5d022..5e4a2a4a0 100644 --- a/tests/python/_product_weak.ipynb +++ b/tests/python/_product_weak.ipynb @@ -189,7 +189,7 @@ "\n" ], "text/plain": [ - " *' at 0x7f7dbc0e99f0> >" + " *' at 0x7fd90c347ba0> >" ] }, "metadata": {}, @@ -1410,64 +1410,64 @@ "\n", "\n", - "\n", - "\n", - "\n", - "Inf(\n", - "\n", - ") | Fin(\n", - "\n", - ")\n", - "[Streett-like 1]\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", "\n", "\n", "\n", "0\n", - "\n", - "1,0\n", + "\n", + "1,0\n", "\n", "\n", "\n", "I->0\n", - "\n", - "\n", + "\n", + "\n", "\n", "\n", "\n", "1\n", - "\n", - "0,0\n", + "\n", + "0,0\n", "\n", "\n", "\n", "0->1\n", - "\n", - "\n", - "a & !d\n", - "\n", + "\n", + "\n", + "a & !d\n", + "\n", "\n", "\n", "\n", "0->1\n", - "\n", - "\n", - "a & d\n", + "\n", + "\n", + "a & d\n", + "\n", "\n", "\n", "\n", "1->1\n", - "\n", - "\n", - "!d\n", - "\n", + "\n", + "\n", + "!d\n", + "\n", "\n", "\n", "\n", "1->1\n", - "\n", - "\n", - "d\n", + "\n", + "\n", + "d\n", + "\n", "\n", "\n", "\n", @@ -1660,7 +1660,7 @@ "\n" ], "text/plain": [ - " *' at 0x7f7dbc0e9900> >" + " *' at 0x7fd90c347bd0> >" ] }, "metadata": {}, @@ -3000,7 +3000,7 @@ "\n" ], "text/plain": [ - " *' at 0x7f7dbc0e9660> >" + " *' at 0x7fd90c347cf0> >" ] }, "metadata": {}, @@ -4331,7 +4331,7 @@ "\n" ], "text/plain": [ - " *' at 0x7f7dbc0e99c0> >" + " *' at 0x7fd90c347d50> >" ] }, "metadata": {}, @@ -5611,7 +5611,7 @@ "\n" ], "text/plain": [ - " *' at 0x7f7dbc0e9ae0> >" + " *' at 0x7fd90c347d80> >" ] }, "metadata": {}, @@ -6872,7 +6872,7 @@ "\n" ], "text/plain": [ - " *' at 0x7f7dbc0e9b10> >" + " *' at 0x7fd90c347e40> >" ] }, "metadata": {}, @@ -6935,64 +6935,64 @@ "\n", "\n", - "\n", - "\n", - "\n", - "Inf(\n", - "\n", - ") | Fin(\n", - "\n", - ")\n", - "[Streett-like 1]\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", "\n", "\n", "\n", "0\n", - "\n", - "0,1\n", + "\n", + "0,1\n", "\n", "\n", "\n", "I->0\n", - "\n", - "\n", + "\n", + "\n", "\n", "\n", "\n", "1\n", - "\n", - "0,0\n", + "\n", + "0,0\n", "\n", "\n", "\n", "0->1\n", - "\n", - "\n", - "a & !d\n", - "\n", + "\n", + "\n", + "a & !d\n", + "\n", "\n", "\n", "\n", "0->1\n", - "\n", - "\n", - "a & d\n", + "\n", + "\n", + "a & d\n", + "\n", "\n", "\n", "\n", "1->1\n", - "\n", - "\n", - "!d\n", - "\n", + "\n", + "\n", + "!d\n", + "\n", "\n", "\n", "\n", "1->1\n", - "\n", - "\n", - "d\n", + "\n", + "\n", + "d\n", + "\n", "\n", "\n", "\n", @@ -8076,10 +8076,8574 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] + "execution_count": 10, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "a\n", + "\n", + "t\n", + "[all]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fd90c347ba0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "a\n", + "\n", + "t\n", + "[all]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2,2\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "2,2\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Fb\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "\n", + "2,0\n", + "\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "2,1\n", + "\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "2,0\n", + "\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "\n", + "2,1\n", + "\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Fb\n", + "\n", + "[co-Büchi]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "\n", + "2,0\n", + "\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "2,1\n", + "\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "2,0\n", + "\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "\n", + "2,1\n", + "\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "2->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "4->3\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "GFc\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + "))\n", + "[Rabin-like 2]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2,0\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Fin(\n", + "\n", + "))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2,0\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ")\n", + "[Rabin-like 1]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & d\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2,0\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !d\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & d\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2,0\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & !d\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")\n", + "[Streett-like 1]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !d\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & d\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2,0\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & !d\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & d\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "2,0\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "left = auts[0]\n", + "display(left)\n", + "for right in auts:\n", + " display_inline(right, spot.product_xor(left, right), spot.product_xnor(left, right))" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Fb\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fd90c347bd0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "a\n", + "\n", + "t\n", + "[all]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "0,2\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "1,2\n", + "\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "0,2\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "\n", + "1,2\n", + "\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Fb\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Fb\n", + "\n", + "[co-Büchi]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "GFc\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + "))\n", + "[Rabin-like 2]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Fin(\n", + "\n", + "))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ")\n", + "[Rabin-like 1]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !d\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & d\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !d\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & d\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")\n", + "[Streett-like 1]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & d\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !d\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & d\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !d\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "left = auts[1]\n", + "display(left)\n", + "for right in auts:\n", + " display_inline(right, spot.product_xor(left, right), spot.product_xnor(left, right))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Fb\n", + "\n", + "[co-Büchi]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fd90c347cf0> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "a\n", + "\n", + "t\n", + "[all]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "\n", + "0,2\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "1,2\n", + "\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & b\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "0,2\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & b\n", + "\n", + "\n", + "\n", + "3\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "0->3\n", + "\n", + "\n", + "a & !b\n", + "\n", + "\n", + "\n", + "4\n", + "\n", + "\n", + "1,2\n", + "\n", + "\n", + "\n", + "0->4\n", + "\n", + "\n", + "!a & !b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "3->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "3->3\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "4->2\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "4->4\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Fb\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Fb\n", + "\n", + "[co-Büchi]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[co-Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "[co-Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "GFc\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Fin(\n", + "\n", + ") & Fin(\n", + "\n", + ")) | (Inf(\n", + "\n", + ")&Inf(\n", + "\n", + "))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Fin(\n", + "\n", + ") & Inf(\n", + "\n", + ")) | (Inf(\n", + "\n", + ") & Fin(\n", + "\n", + "))\n", + "[Rabin-like 2]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ")\n", + "[Rabin-like 1]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !d\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & d\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !d\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & d\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")\n", + "[Streett-like 1]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & d\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "1,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !d\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & d\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !d\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "left = auts[2]\n", + "display(left)\n", + "for right in auts:\n", + " display_inline(right, spot.product_xor(left, right), spot.product_xnor(left, right))" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "GFc\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fd90c347d50> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "a\n", + "\n", + "t\n", + "[all]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + "))\n", + "[Rabin-like 2]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "0,2\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Fin(\n", + "\n", + "))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !c\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "0,2\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & !c\n", + "\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Fb\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + "))\n", + "[Rabin-like 2]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Fin(\n", + "\n", + "))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Fb\n", + "\n", + "[co-Büchi]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Fin(\n", + "\n", + "))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + "))\n", + "[Rabin-like 2]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !c\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !c\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "GFc\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + "))\n", + "[Rabin-like 2]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Fin(\n", + "\n", + "))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ")\n", + "[Rabin-like 1]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Inf(\n", + "\n", + ") & (Fin(\n", + "\n", + ") | Inf(\n", + "\n", + "))) | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + ") & Fin(\n", + "\n", + "))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c & d\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c & !d\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c & d\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "((Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")) & Fin(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & (Fin(\n", + "\n", + ") | Inf(\n", + "\n", + ")))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c & d\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c & !d\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c & d\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")\n", + "[Streett-like 1]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "((Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")) & Fin(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c & d\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c & !d\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c & d\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Inf(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | Fin(\n", + "\n", + "))) | (Fin(\n", + "\n", + ") & Fin(\n", + "\n", + ") & Inf(\n", + "\n", + "))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c & d\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c & !d\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c & d\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "left = auts[3]\n", + "display(left)\n", + "for right in auts:\n", + " display_inline(right, spot.product_xor(left, right), spot.product_xnor(left, right))" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ")\n", + "[Rabin-like 1]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fd90c347d80> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "a\n", + "\n", + "t\n", + "[all]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & d\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "0,2\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !d\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & d\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "0,2\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & !d\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Fb\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !d\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & d\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !d\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & d\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Fb\n", + "\n", + "[co-Büchi]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !d\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & d\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !d\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & d\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "GFc\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ") & Fin(\n", + "\n", + ")) | ((Fin(\n", + "\n", + ") | Inf(\n", + "\n", + ")) & Inf(\n", + "\n", + "))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c & !d\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c & d\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c & d\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "((Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")) & Fin(\n", + "\n", + ")) | ((Fin(\n", + "\n", + ") | Inf(\n", + "\n", + ")) & Fin(\n", + "\n", + "))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c & !d\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c & d\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c & d\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ")\n", + "[Rabin-like 1]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ") & (Fin(\n", + "\n", + ") | Inf(\n", + "\n", + "))) | ((Fin(\n", + "\n", + ") | Inf(\n", + "\n", + ")) & Inf(\n", + "\n", + ") & Fin(\n", + "\n", + "))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "((Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")) & Fin(\n", + "\n", + ") & Fin(\n", + "\n", + ")) | ((Fin(\n", + "\n", + ") | Inf(\n", + "\n", + ")) & (Fin(\n", + "\n", + ") | Inf(\n", + "\n", + ")))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")\n", + "[Streett-like 1]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "((Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")) & Fin(\n", + "\n", + ") & Fin(\n", + "\n", + ")) | ((Fin(\n", + "\n", + ") | Inf(\n", + "\n", + ")) & (Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "(Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | Fin(\n", + "\n", + "))) | ((Fin(\n", + "\n", + ") | Inf(\n", + "\n", + ")) & Fin(\n", + "\n", + ") & Inf(\n", + "\n", + "))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "left = auts[4]\n", + "display(left)\n", + "for right in auts:\n", + " display_inline(right, spot.product_xor(left, right), spot.product_xnor(left, right))" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")\n", + "[Streett-like 1]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + " *' at 0x7fd90c347e40> >" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "a\n", + "\n", + "t\n", + "[all]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !d\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & d\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "0,2\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & !d\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "a & d\n", + "\n", + "\n", + "\n", + "\n", + "2\n", + "\n", + "0,2\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->2\n", + "\n", + "\n", + "!a & d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "2->2\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Fb\n", + "\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & d\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !d\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & d\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !d\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Fb\n", + "\n", + "[co-Büchi]\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "I->1\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!b\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "1->0\n", + "\n", + "\n", + "b\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "1\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & d\n", + "\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,1\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & !d\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!b & d\n", + "\n", + "\n", + "\n", + "1\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & !d\n", + "\n", + "\n", + "\n", + "0->1\n", + "\n", + "\n", + "b & d\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "1->1\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "GFc\n", + "\n", + "Inf(\n", + "\n", + ")\n", + "[Büchi]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "((Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")) & Fin(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c & !d\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c & d\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c & d\n", + "\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "((Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")) & Inf(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + ") & Fin(\n", + "\n", + "))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c & !d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c & !d\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!c & d\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "c & d\n", + "\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ")\n", + "[Rabin-like 1]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "((Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")) & (Fin(\n", + "\n", + ") | Inf(\n", + "\n", + "))) | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")) & Fin(\n", + "\n", + "))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "((Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")) & Inf(\n", + "\n", + ") & Fin(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + ") & (Fin(\n", + "\n", + ") | Inf(\n", + "\n", + ")))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")\n", + "[Streett-like 1]\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "((Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")) & Fin(\n", + "\n", + ") & Inf(\n", + "\n", + ")) | (Fin(\n", + "\n", + ") & Inf(\n", + "\n", + ") & (Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "((Inf(\n", + "\n", + ") | Fin(\n", + "\n", + ")) & (Inf(\n", + "\n", + ") | Fin(\n", + "\n", + "))) | (Fin(\n", + "\n", + ") & (Inf(\n", + "\n", + ")&Inf(\n", + "\n", + ")) & Fin(\n", + "\n", + "))\n", + "\n", + "\n", + "\n", + "0\n", + "\n", + "0,0\n", + "\n", + "\n", + "\n", + "I->0\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "!d\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "0->0\n", + "\n", + "\n", + "d\n", + "\n", + "\n", + "\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "left = auts[5]\n", + "display(left)\n", + "for right in auts:\n", + " display_inline(right, spot.product_xor(left, right), spot.product_xnor(left, right))" + ] } ], "metadata": { @@ -8098,7 +16662,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.2" + "version": "3.8.3rc1" } }, "nbformat": 4, diff --git a/tests/python/except.py b/tests/python/except.py index 926aa864d..f911474e8 100644 --- a/tests/python/except.py +++ b/tests/python/except.py @@ -188,3 +188,32 @@ except ValueError as e: assert 'any' in s else: report_missing_exception() + +a1 = spot.translate('FGa') +a2 = spot.translate('Gb') +assert not spot.is_deterministic(a1) +assert spot.is_deterministic(a2) +try: + spot.product_xor(a1, a2) +except RuntimeError as e: + assert "product_xor() only works with deterministic automata" +else: + report_missing_exception() +try: + spot.product_xor(a2, a1) +except RuntimeError as e: + assert "product_xor() only works with deterministic automata" +else: + report_missing_exception() +try: + spot.product_xnor(a1, a2) +except RuntimeError as e: + assert "product_xnor() only works with deterministic automata" +else: + report_missing_exception() +try: + spot.product_xnor(a2, a1) +except RuntimeError as e: + assert "product_xnor() only works with deterministic automata" +else: + report_missing_exception() From 6ec6150462dcf946bf8a5c55a4b471de904213d8 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Sat, 16 May 2020 18:03:38 +0200 Subject: [PATCH 02/30] translate: improve handling of Xor and Equiv at top-level for -G -D * spot/tl/formula.hh: Add variant of formula::is that support 4 arguments. * spot/tl/simplify.hh, spot/tl/simplify.cc: Add option keep_top_xor to preserve Xor and Equiv at the top-level. * spot/twaalgos/translate.cc: Adjust ltl-split to deal with Xor and Equiv for the -D -G case. * NEWS: Mention that. * tests/core/ltl2tgba2.test: Add test case. * tests/python/simstate.py: Adjust expected result. --- NEWS | 12 +++++++++ spot/tl/formula.hh | 29 ++++++++++++++++++--- spot/tl/simplify.cc | 52 +++++++++++++++++++++++++------------- spot/tl/simplify.hh | 26 +++++++++++-------- spot/twaalgos/translate.cc | 37 ++++++++++++++++++++------- tests/core/ltl2tgba2.test | 7 +++++ tests/python/simstate.py | 6 ++--- 7 files changed, 127 insertions(+), 42 deletions(-) diff --git a/NEWS b/NEWS index a78117cb4..0ec0b0afc 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,12 @@ New in spot 2.9.0.dev (not yet released) + Command-line tools: + + - 'ltl2tgba -G -D' is now better at handling formulas that use + '<->' and 'xor' operators at the top level. For instance + ltl2tgba -D -G '(Fa & Fb & Fc & Fd) <-> GFe' + now produces a 16-state automaton (instead of 31 in Spot 2.9). + Library: - product_xor() and product_xnor() are two new versions of the @@ -8,6 +15,11 @@ New in spot 2.9.0.dev (not yet released) respectively the symmetric difference of the operands, and the complement of that. + - tl_simplifier_options::keep_top_xor is a new option to keep Xor + and Equiv operator that appear at the top of LTL formulas (maybe + below other Boolean or X operators). This is used by the + spot::translator class when creating deterministic automata with + generic acceptance. New in spot 2.9 (2020-04-30) diff --git a/spot/tl/formula.hh b/spot/tl/formula.hh index 22f48edd4..8b1340aaa 100644 --- a/spot/tl/formula.hh +++ b/spot/tl/formula.hh @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2015-2019 Laboratoire de Recherche et Développement +// Copyright (C) 2015-2020 Laboratoire de Recherche et Développement // de l'Epita (LRDE). // // This file is part of Spot, a model checking library. @@ -186,18 +186,27 @@ namespace spot std::string kindstr() const; /// \see formula::is + /// @{ bool is(op o) const { return op_ == o; } - /// \see formula::is bool is(op o1, op o2) const { return op_ == o1 || op_ == o2; } - /// \see formula::is + bool is(op o1, op o2, op o3) const + { + return op_ == o1 || op_ == o2 || op_ == o3; + } + + bool is(op o1, op o2, op o3, op o4) const + { + return op_ == o1 || op_ == o2 || op_ == o3 || op_ == o4; + } + bool is(std::initializer_list l) const { const fnode* n = this; @@ -209,6 +218,7 @@ namespace spot } return true; } + /// @} /// \see formula::get_child_of const fnode* get_child_of(op o) const @@ -1333,6 +1343,19 @@ namespace spot return ptr_->is(o1, o2); } + /// Return true if the formula is of kind \a o1 or \a o2 or \a o3 + bool is(op o1, op o2, op o3) const + { + return ptr_->is(o1, o2, o3); + } + + /// Return true if the formula is of kind \a o1 or \a o2 or \a o3 + /// or \a a4. + bool is(op o1, op o2, op o3, op o4) const + { + return ptr_->is(o1, o2, o3, o4); + } + /// Return true if the formulas nests all the operators in \a l. bool is(std::initializer_list l) const { diff --git a/spot/tl/simplify.cc b/spot/tl/simplify.cc index 0f4c34218..00fac4c9e 100644 --- a/spot/tl/simplify.cc +++ b/spot/tl/simplify.cc @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2011-2019 Laboratoire de Recherche et Developpement +// Copyright (C) 2011-2020 Laboratoire de Recherche et Developpement // de l'Epita (LRDE). // // This file is part of Spot, a model checking library. @@ -417,22 +417,25 @@ namespace spot ////////////////////////////////////////////////////////////////////// formula - nenoform_rec(formula f, bool negated, tl_simplifier_cache* c); + nenoform_rec(formula f, bool negated, tl_simplifier_cache* c, + bool deep); formula equiv_or_xor(bool equiv, formula f1, formula f2, - tl_simplifier_cache* c) + tl_simplifier_cache* c, bool deep) { - auto rec = [c](formula f, bool negated) + auto rec = [c, deep](formula f, bool negated) { - return nenoform_rec(f, negated, c); + return nenoform_rec(f, negated, c, deep); }; if (equiv) { // Rewrite a<=>b as (a&b)|(!a&!b) auto recurse_f1_true = rec(f1, true); - auto recurse_f1_false = rec(f1, false); auto recurse_f2_true = rec(f2, true); + if (!deep && c->options.keep_top_xor) + return formula::Equiv(recurse_f1_true, recurse_f2_true); + auto recurse_f1_false = rec(f1, false); auto recurse_f2_false = rec(f2, false); auto left = formula::And({recurse_f1_false, recurse_f2_false}); auto right = formula::And({recurse_f1_true, recurse_f2_true}); @@ -442,8 +445,10 @@ namespace spot { // Rewrite a^b as (a&!b)|(!a&b) auto recurse_f1_true = rec(f1, true); - auto recurse_f1_false = rec(f1, false); auto recurse_f2_true = rec(f2, true); + if (!deep && c->options.keep_top_xor) + return formula::Xor(recurse_f1_true, recurse_f2_true); + auto recurse_f1_false = rec(f1, false); auto recurse_f2_false = rec(f2, false); auto left = formula::And({recurse_f1_false, recurse_f2_true}); auto right = formula::And({recurse_f1_true, recurse_f2_false}); @@ -451,8 +456,11 @@ namespace spot } } + // The deep argument indicate whether we are under a temporal + // operator (except X). formula - nenoform_rec(formula f, bool negated, tl_simplifier_cache* c) + nenoform_rec(formula f, bool negated, tl_simplifier_cache* c, + bool deep) { if (f.is(op::Not)) { @@ -474,9 +482,9 @@ namespace spot } else { - auto rec = [c](formula f, bool neg) + auto rec = [c, &deep](formula f, bool neg) { - return nenoform_rec(f, neg, c); + return nenoform_rec(f, neg, c, deep); }; switch (op o = f.kind()) @@ -504,21 +512,25 @@ namespace spot break; case op::F: // !Fa == G!a + deep = true; result = formula::unop(negated ? op::G : op::F, rec(f[0], negated)); break; case op::G: // !Ga == F!a + deep = true; result = formula::unop(negated ? op::F : op::G, rec(f[0], negated)); break; case op::Closure: + deep = true; result = formula::unop(negated ? op::NegClosure : op::Closure, rec(f[0], false)); break; case op::NegClosure: case op::NegClosureMarked: + deep = true; result = formula::unop(negated ? op::Closure : o, rec(f[0], false)); break; @@ -539,17 +551,18 @@ namespace spot case op::Xor: { // !(a ^ b) == a <=> b - result = equiv_or_xor(negated, f[0], f[1], c); + result = equiv_or_xor(negated, f[0], f[1], c, deep); break; } case op::Equiv: { // !(a <=> b) == a ^ b - result = equiv_or_xor(!negated, f[0], f[1], c); + result = equiv_or_xor(!negated, f[0], f[1], c, deep); break; } case op::U: { + deep = true; // !(a U b) == !a R !b auto f1 = rec(f[0], negated); auto f2 = rec(f[1], negated); @@ -558,6 +571,7 @@ namespace spot } case op::R: { + deep = true; // !(a R b) == !a U !b auto f1 = rec(f[0], negated); auto f2 = rec(f[1], negated); @@ -566,6 +580,7 @@ namespace spot } case op::W: { + deep = true; // !(a W b) == !a M !b auto f1 = rec(f[0], negated); auto f2 = rec(f[1], negated); @@ -574,6 +589,7 @@ namespace spot } case op::M: { + deep = true; // !(a M b) == !a W !b auto f1 = rec(f[0], negated); auto f2 = rec(f[1], negated); @@ -604,15 +620,16 @@ namespace spot // !(a*) etc. should never occur. { assert(!negated); - result = f.map([c](formula f) + result = f.map([c, deep](formula f) { - return nenoform_rec(f, false, c); + return nenoform_rec(f, false, c, deep); }); break; } case op::EConcat: case op::EConcatMarked: { + deep = true; // !(a <>-> b) == a[]-> !b auto f1 = f[0]; auto f2 = f[1]; @@ -622,6 +639,7 @@ namespace spot } case op::UConcat: { + deep = true; // !(a []-> b) == a<>-> !b auto f1 = f[0]; auto f2 = f[1]; @@ -4048,9 +4066,9 @@ namespace spot if (f2.is_sere_formula() && !f2.is_boolean()) return false; if (right) - f2 = nenoform_rec(f2, true, this); + f2 = nenoform_rec(f2, true, this, false); else - f1 = nenoform_rec(f1, true, this); + f1 = nenoform_rec(f1, true, this, false); return syntactic_implication(f1, f2); } @@ -4085,7 +4103,7 @@ namespace spot formula tl_simplifier::negative_normal_form(formula f, bool negated) { - return nenoform_rec(f, negated, cache_); + return nenoform_rec(f, negated, cache_, false); } bool diff --git a/spot/tl/simplify.hh b/spot/tl/simplify.hh index 725255745..34377ff62 100644 --- a/spot/tl/simplify.hh +++ b/spot/tl/simplify.hh @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2011-2017, 2019 Laboratoire de Recherche et Developpement +// Copyright (C) 2011-2017, 2019, 2020 Laboratoire de Recherche et Developpement // de l'Epita (LRDE). // // This file is part of Spot, a model checking library. @@ -30,14 +30,15 @@ namespace spot { public: tl_simplifier_options(bool basics = true, - bool synt_impl = true, - bool event_univ = true, - bool containment_checks = false, - bool containment_checks_stronger = false, - bool nenoform_stop_on_boolean = false, - bool reduce_size_strictly = false, - bool boolean_to_isop = false, - bool favor_event_univ = false) + bool synt_impl = true, + bool event_univ = true, + bool containment_checks = false, + bool containment_checks_stronger = false, + bool nenoform_stop_on_boolean = false, + bool reduce_size_strictly = false, + bool boolean_to_isop = false, + bool favor_event_univ = false, + bool keep_top_xor = false) : reduce_basics(basics), synt_impl(synt_impl), event_univ(event_univ), @@ -46,7 +47,8 @@ namespace spot nenoform_stop_on_boolean(nenoform_stop_on_boolean), reduce_size_strictly(reduce_size_strictly), boolean_to_isop(boolean_to_isop), - favor_event_univ(favor_event_univ) + favor_event_univ(favor_event_univ), + keep_top_xor(keep_top_xor) { } @@ -87,6 +89,10 @@ namespace spot bool boolean_to_isop; // Try to isolate subformulae that are eventual and universal. bool favor_event_univ; + // Keep Xor and Equiv at the top of the formula, possibly under + // &,|, and X operators. Only rewrite Xor and Equiv under + // temporal operators. + bool keep_top_xor; }; // fwd declaration to hide technical details. diff --git a/spot/twaalgos/translate.cc b/spot/twaalgos/translate.cc index 7ef799662..878bcaa43 100644 --- a/spot/twaalgos/translate.cc +++ b/spot/twaalgos/translate.cc @@ -108,6 +108,8 @@ namespace spot } if (comp_susp_ > 0 || (ltl_split_ && type_ == Generic)) options.favor_event_univ = true; + if (type_ == Generic && ltl_split_ && (pref_ & Deterministic)) + options.keep_top_xor = true; simpl_owned_ = simpl_ = new tl_simplifier(options, dict); } @@ -167,15 +169,16 @@ namespace spot r2 = formula::multop(op2, susp); } } - if (r2.is_syntactic_obligation() || !r2.is(op::And, op::Or) || + if (r2.is_syntactic_obligation() || !r2.is(op::And, op::Or, + op::Xor, op::Equiv) || // For TGBA/BA we only do conjunction. There is nothing wrong // with disjunction, but it seems to generate larger automata // in many cases and it needs to be further investigated. Maybe // this could be relaxed in the case of deterministic output. - (r2.is(op::Or) && (type_ == TGBA || type_ == BA))) + (!r2.is(op::And) && (type_ == TGBA || type_ == BA))) goto nosplit; - bool is_and = r2.is(op::And); + op topop = r2.kind(); // Let's classify subformulas. std::vector oblg; std::vector susp; @@ -270,10 +273,16 @@ namespace spot twa_graph_ptr rest_aut = transrun(rest_f); if (aut == nullptr) aut = rest_aut; - else if (is_and) + else if (topop == op::And) aut = product(aut, rest_aut); - else + else if (topop == op::Or) aut = product_or(aut, rest_aut); + else if (topop == op::Xor) + aut = product_xor(aut, rest_aut); + else if (topop == op::Equiv) + aut = product_xnor(aut, rest_aut); + else + SPOT_UNREACHABLE(); } if (!susp.empty()) { @@ -285,10 +294,16 @@ namespace spot twa_graph_ptr one = transrun(f); if (!susp_aut) susp_aut = one; - else if (is_and) + else if (topop == op::And) susp_aut = product(susp_aut, one); - else + else if (topop == op::Or) susp_aut = product_or(susp_aut, one); + else if (topop == op::Xor) + susp_aut = product_xor(susp_aut, one); + else if (topop == op::Equiv) + susp_aut = product_xnor(susp_aut, one); + else + SPOT_UNREACHABLE(); } if (susp_aut->prop_universal().is_true()) { @@ -311,10 +326,14 @@ namespace spot } if (aut == nullptr) aut = susp_aut; - else if (is_and) + else if (topop == op::And) aut = product_susp(aut, susp_aut); - else + else if (topop == op::Or) aut = product_or_susp(aut, susp_aut); + else if (topop == op::Xor) // No suspension here + aut = product_xor(aut, susp_aut); + else if (topop == op::Equiv) // No suspension here + aut = product_xnor(aut, susp_aut); //if (aut && susp_aut) // { // print_hoa(std::cerr << "AUT\n", aut) << '\n'; diff --git a/tests/core/ltl2tgba2.test b/tests/core/ltl2tgba2.test index 22c005146..3e50df480 100755 --- a/tests/core/ltl2tgba2.test +++ b/tests/core/ltl2tgba2.test @@ -451,4 +451,11 @@ f='(GFp0 | FGp1) & (GF!p1 | FGp2) & (GF!p2 | FG!p0)' test 1,8,3 = `ltl2tgba -G -D "$f" --stats=%s,%e,%a` test 1,3,2 = `ltl2tgba -G -D "(GFp0 | FGp1)" --stats=%s,%e,%a` +# Handling of Xor and <-> by ltl-split and -D -G. +res=`ltl2tgba -D -G 'X((Fa & Fb & Fc & Fd) <-> GFe)' --stats='%s %g'` +test "$res" = "17 (Inf(0) & Fin(1)) | (Fin(0) & Inf(1))" +res=`ltl2tgba -D -G 'X((Fa & Fb & Fc & Fd) ^ GFe)' --stats='%s %g'` +test "$res" = "17 (Inf(0)&Inf(1)) | (Fin(0) & Fin(1))" +ltlcross 'ltl2tgba -D -G' 'ltl2tgba -G' -f '(Fa & Fb & Fc & Fd) ^ GFe' + : diff --git a/tests/python/simstate.py b/tests/python/simstate.py index 8e5e1c712..1be3d9a94 100644 --- a/tests/python/simstate.py +++ b/tests/python/simstate.py @@ -178,13 +178,13 @@ b.copy_state_names_from(a) assert b.to_str() == """HOA: v1 States: 1 Start: 0 -AP: 2 "p0" "p1" +AP: 2 "p1" "p0" acc-name: Buchi Acceptance: 1 Inf(0) properties: trans-labels explicit-labels trans-acc complete properties: deterministic stutter-invariant --BODY-- State: 0 "[1,7]" -[!1] 0 {0} -[1] 0 +[!0] 0 {0} +[0] 0 --END--""" From fc1c17b91c70009e3338e0bac0d97c13c4357f86 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Sat, 16 May 2020 19:22:28 +0200 Subject: [PATCH 03/30] ltlsynt: make sure the previous Xor optimization actually works * spot/tl/simplify.hh, spot/tl/simplify.cc, spot/twaalgos/translate.cc: Update the tl_simplification options after all preferences have been given. * bin/ltlsynt.cc: Display the size of the translation output. * tests/core/ltlsynt.test: Add test case. --- bin/ltlsynt.cc | 8 ++++++-- spot/tl/simplify.cc | 6 ++++++ spot/tl/simplify.hh | 8 ++++++++ spot/twaalgos/translate.cc | 16 ++++++++++++---- tests/core/ltlsynt.test | 16 ++++++++++++++++ 5 files changed, 48 insertions(+), 6 deletions(-) diff --git a/bin/ltlsynt.cc b/bin/ltlsynt.cc index aeed8b499..e805a9f3e 100644 --- a/bin/ltlsynt.cc +++ b/bin/ltlsynt.cc @@ -384,8 +384,12 @@ namespace if (want_time) trans_time = sw.stop(); if (verbose) - std::cerr << "translating formula done in " - << trans_time << " seconds\n"; + { + std::cerr << "translating formula done in " + << trans_time << " seconds\n"; + std::cerr << "automaton has " << aut->num_states() + << " states and " << aut->num_sets() << " colors\n"; + } spot::twa_graph_ptr dpa = nullptr; switch (opt_solver) diff --git a/spot/tl/simplify.cc b/spot/tl/simplify.cc index 00fac4c9e..24f94d5eb 100644 --- a/spot/tl/simplify.cc +++ b/spot/tl/simplify.cc @@ -4100,6 +4100,12 @@ namespace spot return simplify_recursively(f, cache_); } + tl_simplifier_options& + tl_simplifier::options() + { + return cache_->options; + } + formula tl_simplifier::negative_normal_form(formula f, bool negated) { diff --git a/spot/tl/simplify.hh b/spot/tl/simplify.hh index 34377ff62..7ecde7498 100644 --- a/spot/tl/simplify.hh +++ b/spot/tl/simplify.hh @@ -112,6 +112,14 @@ namespace spot /// constructor). formula simplify(formula f); +#ifndef SWIG + /// The simplifier options. + /// + /// Those should can still be changed before the first formula is + /// simplified. + tl_simplifier_options& options(); +#endif + /// Build the negative normal form of formula \a f. /// All negations of the formula are pushed in front of the /// atomic propositions. Operators <=>, =>, xor are all removed diff --git a/spot/twaalgos/translate.cc b/spot/twaalgos/translate.cc index 878bcaa43..5ada74631 100644 --- a/spot/twaalgos/translate.cc +++ b/spot/twaalgos/translate.cc @@ -106,10 +106,6 @@ namespace spot throw std::runtime_error ("tls-impl should take a value between 0 and 3"); } - if (comp_susp_ > 0 || (ltl_split_ && type_ == Generic)) - options.favor_event_univ = true; - if (type_ == Generic && ltl_split_ && (pref_ & Deterministic)) - options.keep_top_xor = true; simpl_owned_ = simpl_ = new tl_simplifier(options, dict); } @@ -419,6 +415,18 @@ namespace spot twa_graph_ptr translator::run(formula* f) { + if (simpl_owned_) + { + // Modify the options according to set_pref() and set_type(). + // We do it for all translation, but really only the first one + // matters. + auto& opt = simpl_owned_->options(); + if (comp_susp_ > 0 || (ltl_split_ && type_ == Generic)) + opt.favor_event_univ = true; + if (type_ == Generic && ltl_split_ && (pref_ & Deterministic)) + opt.keep_top_xor = true; + } + // Do we want to relabel Boolean subformulas? // If we have a huge formula such as // (a1 & a2 & ... & an) U (b1 | b2 | ... | bm) diff --git a/tests/core/ltlsynt.test b/tests/core/ltlsynt.test index 805bcd348..1584b8bf5 100644 --- a/tests/core/ltlsynt.test +++ b/tests/core/ltlsynt.test @@ -103,6 +103,7 @@ diff out exp cat >exp < GFb' --verbose --realizability 2> out sed 's/ [0-9.e-]* seconds/ X seconds/g' out > outx diff outx exp +cat >exp < GFe' \ + --verbose --realizability --algo=lar 2> out +sed 's/ [0-9.e-]* seconds/ X seconds/g' out > outx +diff outx exp + for r in '' '--real'; do opts="$r --ins=a --outs=b -f" ltlsynt --algo=ds $opts 'GFa <-> GFb' --csv=FILE || : From 4608d9a5b124acb67811a59f354abbffa8884495 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Mon, 18 May 2020 19:25:14 +0200 Subject: [PATCH 04/30] [buddy] avoid cache errors in bdd_satcount() and friends * src/bddop.c (bdd_satcount, bdd_satcountln): If the number of declared variables changed since we last used it, reset misccache. Otherwise, bdd_satcount() and friends might return incorrect results after the number of variable is changed. These is needed for the next patch in Spot to pass all tests. (misccache_varnum): New global variable to track that. (bdd_satcountset): Make sure that bdd_satcountset(bddtrue, bddtrue) return 1.0 and not 0.0. --- buddy/src/bddop.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/buddy/src/bddop.c b/buddy/src/bddop.c index afd2ce266..625290105 100644 --- a/buddy/src/bddop.c +++ b/buddy/src/bddop.c @@ -125,6 +125,7 @@ static BddCache quantcache; /* Cache for exist/forall results */ static BddCache appexcache; /* Cache for appex/appall results */ static BddCache replacecache; /* Cache for replace results */ static BddCache misccache; /* Cache for other results */ +static int misccache_varnum; /* if this changes, invalidate misccache */ static int cacheratio; static BDD satPolarity; static int firstReorder; /* Used instead of local variable in order @@ -214,6 +215,7 @@ int bdd_operator_init(int cachesize) if (BddCache_init(&misccache,cachesize) < 0) return bdd_error(BDD_MEMORY); + misccache_varnum = bddvarnum; quantvarsetID = 0; quantvarset = NULL; @@ -249,6 +251,7 @@ void bdd_operator_reset(void) BddCache_reset(&appexcache); BddCache_reset(&replacecache); BddCache_reset(&misccache); + misccache_varnum = bddvarnum; } @@ -2805,6 +2808,14 @@ double bdd_satcount(BDD r) CHECKa(r, 0.0); + // Invalidate misccache if the number of variable changed since we + // last used it. + if (misccache_varnum != bddvarnum) + { + BddCache_reset(&misccache); + misccache_varnum = bddvarnum; + } + miscid = CACHEID_SATCOU; size = pow(2.0, (double)LEVEL(r)); @@ -2817,8 +2828,10 @@ double bdd_satcountset(BDD r, BDD varset) double unused = bddvarnum; BDD n; - if (ISCONST(varset) || ISZERO(r)) /* empty set */ - return 0.0; + if (ISZERO(r)) + return 0.0; + if (ISCONST(varset)) /* empty set */ + return ISONE(r) ? 1.0 : 0.0; for (n=varset ; !ISCONST(n) ; n=HIGH(n)) unused--; @@ -2839,7 +2852,7 @@ static double satcount_rec(int root) return root; entry = BddCache_lookup(&misccache, SATCOUHASH(root)); - if (entry->d.a == root && entry->d.c == miscid) + if (entry->d.a == root && entry->d.c == miscid) return entry->d.res; node = &bddnodes[root]; @@ -2886,6 +2899,14 @@ double bdd_satcountln(BDD r) CHECKa(r, 0.0); + // Invalidate misccache if the number of variable changed since we + // last used it. + if (misccache_varnum != bddvarnum) + { + BddCache_reset(&misccache); + misccache_varnum = bddvarnum; + } + miscid = CACHEID_SATCOULN; size = satcountln_rec(r); From d25fcb23eb4270a3e286b7b35db2384924b7cccf Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Mon, 18 May 2020 16:52:31 +0200 Subject: [PATCH 05/30] stats: speed up the computation of transitions Juraj Major reported a case with 32 APs where ltlcross would take forever to gather statistics. It turns out that for each edge, twa_sub_statistics was enumerating all compatible assignments of 32 APs. This uses bdd_satcountset() instead, and also store the result in a long long to avoid overflows. * spot/twaalgos/stats.cc (twa_sub_statistics): Improve the code for counting transitions. * bin/common_aoutput.hh, bin/ltlcross.cc, spot/twaalgos/stats.hh: Store transition counts are long long. * tests/core/readsave.test: Add test case. * NEWS: Mention the bug. --- NEWS | 8 ++++++++ bin/common_aoutput.hh | 6 +++--- bin/ltlcross.cc | 2 +- spot/twaalgos/stats.cc | 19 +++++-------------- spot/twaalgos/stats.hh | 6 +++--- tests/core/readsave.test | 25 +++++++++++++++++++++++++ 6 files changed, 45 insertions(+), 21 deletions(-) diff --git a/NEWS b/NEWS index 0ec0b0afc..4bc09d312 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,14 @@ New in spot 2.9.0.dev (not yet released) spot::translator class when creating deterministic automata with generic acceptance. + Bugs fixed: + + - spot::twa_sub_statistics was very slow at computing the number of + transitons, and could overflow. It is now avoiding some costly + loop of BDD operations, and storing the result using at least 64 + bits. This affects the output of "ltlcross --csv" and + "--stats=%t" for many tools. + New in spot 2.9 (2020-04-30) Command-line tools: diff --git a/bin/common_aoutput.hh b/bin/common_aoutput.hh index 0f1103152..1b2e7ae41 100644 --- a/bin/common_aoutput.hh +++ b/bin/common_aoutput.hh @@ -1,6 +1,6 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2014-2018 Laboratoire de Recherche et Développement -// de l'Epita (LRDE). +// Copyright (C) 2014-2018, 2020 Laboratoire de Recherche et +// Développement de l'Epita (LRDE). // // This file is part of Spot, a model checking library. // @@ -167,7 +167,7 @@ private: spot::printable_acc_cond haut_gen_acc_; spot::printable_value haut_states_; spot::printable_value haut_edges_; - spot::printable_value haut_trans_; + spot::printable_value haut_trans_; spot::printable_value haut_acc_; printable_varset haut_ap_; printable_varset aut_ap_; diff --git a/bin/ltlcross.cc b/bin/ltlcross.cc index d588217d7..a7f9fa1da 100644 --- a/bin/ltlcross.cc +++ b/bin/ltlcross.cc @@ -296,7 +296,7 @@ struct statistics double time; unsigned states; unsigned edges; - unsigned transitions; + unsigned long long transitions; unsigned acc; unsigned scc; unsigned nonacc_scc; diff --git a/spot/twaalgos/stats.cc b/spot/twaalgos/stats.cc index 2d0a7a849..ddccba5db 100644 --- a/spot/twaalgos/stats.cc +++ b/spot/twaalgos/stats.cc @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2008, 2011-2018 Laboratoire de Recherche et +// Copyright (C) 2008, 2011-2018, 2020 Laboratoire de Recherche et // Développement de l'Epita (LRDE). // Copyright (C) 2004 Laboratoire d'Informatique de Paris 6 (LIP6), // département Systèmes Répartis Coopératifs (SRC), Université Pierre @@ -64,7 +64,7 @@ namespace spot { public: sub_stats_bfs(const const_twa_ptr& a, twa_sub_statistics& s) - : stats_bfs(a, s), s_(s), seen_(a->ap_vars()) + : stats_bfs(a, s), s_(s), apvars_(a->ap_vars()) { } @@ -73,17 +73,12 @@ namespace spot const twa_succ_iterator* it) override { ++s_.edges; - bdd cond = it->cond(); - while (cond != bddfalse) - { - cond -= bdd_satoneset(cond, seen_, bddtrue); - ++s_.transitions; - } + s_.transitions += bdd_satcountset(it->cond(), apvars_); } private: twa_sub_statistics& s_; - bdd seen_; + bdd apvars_; }; @@ -180,11 +175,7 @@ namespace spot [&s, &ge](bdd cond) { ++s.edges; - while (cond != bddfalse) - { - cond -= bdd_satoneset(cond, ge->ap_vars(), bddtrue); - ++s.transitions; - } + s.transitions += bdd_satcountset(cond, ge->ap_vars()); }); } return s; diff --git a/spot/twaalgos/stats.hh b/spot/twaalgos/stats.hh index 6f8655134..1caa8324b 100644 --- a/spot/twaalgos/stats.hh +++ b/spot/twaalgos/stats.hh @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2008, 2011-2017 Laboratoire de Recherche et +// Copyright (C) 2008, 2011-2017, 2020 Laboratoire de Recherche et // Développement de l'Epita (LRDE). // Copyright (C) 2004 Laboratoire d'Informatique de Paris 6 (LIP6), // département Systèmes Répartis Coopératifs (SRC), Université Pierre @@ -44,7 +44,7 @@ namespace spot struct SPOT_API twa_sub_statistics: public twa_statistics { - unsigned transitions; + unsigned long long transitions; twa_sub_statistics() { transitions = 0; } std::ostream& dump(std::ostream& out) const; @@ -125,7 +125,7 @@ namespace spot printable_formula form_; printable_value states_; printable_value edges_; - printable_value trans_; + printable_value trans_; printable_value acc_; printable_scc_info scc_; printable_value nondetstates_; diff --git a/tests/core/readsave.test b/tests/core/readsave.test index 010398468..2f9b424f9 100755 --- a/tests/core/readsave.test +++ b/tests/core/readsave.test @@ -1119,3 +1119,28 @@ f="{{!a;!b}:{{c <-> d} && {e xor f} && {m | {l && {k | {j <-> {i xor {g && h}" f="$f}}}}} && {{n && o} | {!n && p}} && {q -> {r <-> s}}}:{[*0..1];t}}[]-> u" ltl2tgba -f "$f" --dot=bar > out.dot grep 'label too long' out.dot + + +# genltl --and-fg=32 | ltlfilt --relabel=abc | ltldo ltl3ba produces a +# few edges equivalent to a lot of transitions. The code used to +# count those transitions used to be very inefficient. +cat >andfg32.hoa < Date: Mon, 18 May 2020 17:08:40 +0200 Subject: [PATCH 06/30] * doc/org/satmin.org: Remove extra newlines (fixes #410). --- doc/org/satmin.org | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/org/satmin.org b/doc/org/satmin.org index e316b81c6..51b8fd9d8 100644 --- a/doc/org/satmin.org +++ b/doc/org/satmin.org @@ -190,7 +190,7 @@ dstar2tgba -D --stats='input(states=%S) output(states=%s, acc-sets=%a, det=%d)' #+BEGIN_SRC sh :exports none ltlfilt --remove-wm -f 'G(F(!b & (X!a M (F!a & F!b))) U !b)' -l | ltl2dstar --ltl2nba=spin:ltl2tgba@-Ds - - | -dstar2tgba -D --stats=$arg +dstar2tgba -D --stats=$arg | tr -d '\n' #+END_SRC In the above command, =ltldo= is used to convert the LTL formula into From 64aee87d76767e72230bdc4b9c512adf2a9ded69 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Thu, 21 May 2020 15:42:05 +0200 Subject: [PATCH 07/30] postproc: option to wdba-minimize only when sure Fixes #15. * spot/twaalgos/minimize.hh, spot/twaalgos/minimize.cc (minimize_obligation_garanteed_to_work): New function. * spot/twaalgos/postproc.hh, spot/twaalgos/postproc.cc: Use it if wdba-minimize=1. Handle new default for wdba-minimize. * NEWS, bin/spot-x.cc: Document those changes. * tests/core/ltl2tgba2.test: Add some test cases. * tests/core/genltl.test: Improve expected results. --- NEWS | 11 +++++++++++ bin/spot-x.cc | 6 ++++-- spot/twaalgos/minimize.cc | 19 ++++++++++++------- spot/twaalgos/minimize.hh | 22 ++++++++++++++++++++-- spot/twaalgos/postproc.cc | 18 ++++++++++++++---- spot/twaalgos/postproc.hh | 2 +- tests/core/genltl.test | 12 ++++++------ tests/core/ltl2tgba2.test | 11 +++++++++++ 8 files changed, 79 insertions(+), 22 deletions(-) diff --git a/NEWS b/NEWS index 4bc09d312..f4a827054 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,17 @@ New in spot 2.9.0.dev (not yet released) ltl2tgba -D -G '(Fa & Fb & Fc & Fd) <-> GFe' now produces a 16-state automaton (instead of 31 in Spot 2.9). + - Option '-x wdba-minize=N' used to accept N=0 (off), or N=1 (on). + It can now take three values: + 0: never attempt this optimization, + 1: always try to determinize and minimize automata as WDBA, + and check (if needed) that the result is correct, + 2: determinize and minimize automata as WDBA only if it is known + beforehand (by cheap syntactic means) that the result will be + correct (e.g., the input formula is a syntactic obligation). + The default is 1 in "--high" mode, 2 in "--medium" mode or in + "--deterministic --low" mode, and 0 in other "--low" modes. + Library: - product_xor() and product_xnor() are two new versions of the diff --git a/bin/spot-x.cc b/bin/spot-x.cc index 90c6eec3d..007e23233 100644 --- a/bin/spot-x.cc +++ b/bin/spot-x.cc @@ -152,8 +152,10 @@ abstracted as atomic propositions during the translation to automaton. \ This relabeling can speeds the translation if a few Boolean subformulas \ use a large number of atomic propositions. By default N=4. Setting \ this value to 0 will disable the rewriting.") }, - { DOC("wdba-minimize", "Set to 0 to disable WDBA-minimization. \ -Enabled by default.") }, + { DOC("wdba-minimize", "Set to 0 to disable WDBA-minimization, to 1 to \ +always try it, or 2 to attempt it only on syntactic obligations or on automata \ +that are weak and deterministic. The default is 1 in --high mode, else 2 in \ +--medium or --deterministic modes, else 0 in --low mode.") }, { DOC("tba-det", "Set to 1 to attempt a powerset determinization \ if the TGBA is not already deterministic. Doing so will degeneralize \ the automaton. This is disabled by default, unless sat-minimize is set.") }, diff --git a/spot/twaalgos/minimize.cc b/spot/twaalgos/minimize.cc index e637e3fe8..f9188f0b1 100644 --- a/spot/twaalgos/minimize.cc +++ b/spot/twaalgos/minimize.cc @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2010-2019 Laboratoire de Recherche et Développement +// Copyright (C) 2010-2020 Laboratoire de Recherche et Développement // de l'Epita (LRDE). // // This file is part of Spot, a model checking library. @@ -567,6 +567,16 @@ namespace spot return product(min_aut, aut_neg)->is_empty(); } + bool minimize_obligation_garanteed_to_work(const const_twa_graph_ptr& aut_f, + formula f) + { + // WDBA-minimization necessarily work for obligations + return ((f && f.is_syntactic_obligation()) + // Weak deterministic automata are obligations + || (aut_f->prop_weak().is_true() && is_deterministic(aut_f)) + // Guarantee automata are obligations as well. + || is_terminal_automaton(aut_f)); + } twa_graph_ptr minimize_obligation(const const_twa_graph_ptr& aut_f, @@ -580,12 +590,7 @@ namespace spot ("minimize_obligation() does not support alternation"); bool minimization_will_be_correct = false; - // WDBA-minimization necessarily work for obligations - if ((f && f.is_syntactic_obligation()) - // Weak deterministic automata are obligations - || (aut_f->prop_weak() && is_deterministic(aut_f)) - // Guarantee automata are obligations as well. - || is_terminal_automaton(aut_f)) + if (minimize_obligation_garanteed_to_work(aut_f, f)) { minimization_will_be_correct = true; } diff --git a/spot/twaalgos/minimize.hh b/spot/twaalgos/minimize.hh index 9bf1f796b..0b454654a 100644 --- a/spot/twaalgos/minimize.hh +++ b/spot/twaalgos/minimize.hh @@ -1,6 +1,6 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2018, 2019 -// Laboratoire de Recherche et Développement de l'Epita (LRDE). +// Copyright (C) 2009-2016, 2018-2020 Laboratoire de Recherche et +// Développement de l'Epita (LRDE). // // This file is part of Spot, a model checking library. // @@ -116,5 +116,23 @@ namespace spot const_twa_graph_ptr aut_neg_f = nullptr, bool reject_bigger = false, const output_aborter* aborter = nullptr); + + /// \brief Whether calling minimize_obligation is sure to work + /// + /// This checks whether \a f is a syntactic obligation, or if \a + /// aut_f obviously corresponds to an obligation (for instance if + /// this is a terminal automaton, or if it is both weak and + /// deterministic). In this case, calling minimize_obligation() + /// should not be a waste of time, as it will return a new + /// automaton. + /// + /// If this function returns false, the input property might still + /// be a pathological obligation. The only way to know is to call + /// minimize_obligation(), but as it is less likely, you might + /// decide to save time. + SPOT_API + bool minimize_obligation_garanteed_to_work(const const_twa_graph_ptr& aut_f, + formula f = nullptr); + /// @} } diff --git a/spot/twaalgos/postproc.cc b/spot/twaalgos/postproc.cc index 3d9df7e1f..36d0345bf 100644 --- a/spot/twaalgos/postproc.cc +++ b/spot/twaalgos/postproc.cc @@ -83,7 +83,7 @@ namespace spot sat_acc_ = opt->get("sat-acc", 0); sat_states_ = opt->get("sat-states", 0); state_based_ = opt->get("state-based", 0); - wdba_minimize_ = opt->get("wdba-minimize", 1); + wdba_minimize_ = opt->get("wdba-minimize", -1); gen_reduce_parity_ = opt->get("gen-reduce-parity", 1); if (sat_acc_ && sat_minimize_ == 0) @@ -371,9 +371,19 @@ namespace spot output_aborter* aborter = (det_max_states_ >= 0 || det_max_edges_ >= 0) ? &aborter_ : nullptr; - // (Small,Low) is the only configuration where we do not run - // WDBA-minimization. - if ((PREF_ != Small || level_ != Low) && wdba_minimize_) + int wdba_minimize = wdba_minimize_; + if (wdba_minimize == -1) + { + if (level_ == High) + wdba_minimize = 1; + else if (level_ == Medium || PREF_ == Deterministic) + wdba_minimize = 2; + else + wdba_minimize = 0; + } + if (wdba_minimize == 2) + wdba_minimize = minimize_obligation_garanteed_to_work(a, f); + if (wdba_minimize) { bool reject_bigger = (PREF_ == Small) && (level_ <= Medium); dba = minimize_obligation(a, f, nullptr, reject_bigger, aborter); diff --git a/spot/twaalgos/postproc.hh b/spot/twaalgos/postproc.hh index 5b739e5b7..3fbd07060 100644 --- a/spot/twaalgos/postproc.hh +++ b/spot/twaalgos/postproc.hh @@ -253,7 +253,7 @@ namespace spot int sat_states_ = 0; int gen_reduce_parity_ = 1; bool state_based_ = false; - bool wdba_minimize_ = true; + int wdba_minimize_ = -1; }; /// @} } diff --git a/tests/core/genltl.test b/tests/core/genltl.test index 4a85c7c66..271820d8d 100755 --- a/tests/core/genltl.test +++ b/tests/core/genltl.test @@ -132,12 +132,12 @@ genltl --kr-n2=1..2 --kr-nlogn=1..2 --kr-n=1..2 --gxf-and=0..3 --fxg-or=0..3 \ --pps-arbiter-standard=2..3 --pps-arbiter-strict=2..3 --format=%F=%L,%f | ltl2tgba --low --det -F-/2 --stats='%<,%s' > out cat >exp< Date: Fri, 22 May 2020 15:33:40 +0200 Subject: [PATCH 08/30] fixpool: allocate a new chunk on creation Allocate the first chunk when the fixpool is created. This avoid a undefined behavior reported in issue #413 without requiring an extra comparison in allocate(). * spot/misc/fixpool.hh, spot/misc/fixpool.cc (new_chunk_): New method extracted from allocate(). Use it in the constructor as well. * NEWS: Mention the bug. --- NEWS | 2 ++ spot/misc/fixpool.cc | 21 +++++++++++++++++---- spot/misc/fixpool.hh | 14 ++++---------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/NEWS b/NEWS index f4a827054..f8ab2a8df 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,8 @@ New in spot 2.9.0.dev (not yet released) Bugs fixed: + - Work around undefined behavior reported by clang 10.0.0's UBsan. + - spot::twa_sub_statistics was very slow at computing the number of transitons, and could overflow. It is now avoiding some costly loop of BDD operations, and storing the result using at least 64 diff --git a/spot/misc/fixpool.cc b/spot/misc/fixpool.cc index 30e0e45c3..06dbd55d8 100644 --- a/spot/misc/fixpool.cc +++ b/spot/misc/fixpool.cc @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2017-2018 Laboratoire de Recherche et +// Copyright (C) 2017-2018, 2020 Laboratoire de Recherche et // Développement de l'Epita (LRDE) // // This file is part of Spot, a model checking library. @@ -106,7 +106,20 @@ namespace spot return (size + mask) & ~mask; } }(size)), - freelist_(nullptr), free_start_(nullptr), - free_end_(nullptr), chunklist_(nullptr) - {} + freelist_(nullptr), + chunklist_(nullptr) + { + new_chunk_(); + } + + void fixed_size_pool::new_chunk_() + { + const size_t requested = (size_ > 128 ? size_ : 128) * 8192 - 64; + chunk_* c = reinterpret_cast(::operator new(requested)); + c->prev = chunklist_; + chunklist_ = c; + + free_start_ = c->data_ + size_; + free_end_ = c->data_ + requested; + } } diff --git a/spot/misc/fixpool.hh b/spot/misc/fixpool.hh index 4d79a192f..4d2068205 100644 --- a/spot/misc/fixpool.hh +++ b/spot/misc/fixpool.hh @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2011, 2015-2018 Laboratoire de Recherche et +// Copyright (C) 2011, 2015-2018, 2020 Laboratoire de Recherche et // Développement de l'Epita (LRDE) // // This file is part of Spot, a model checking library. @@ -68,15 +68,7 @@ namespace spot // If all the last chunk has been used, allocate one more. if (free_start_ + size_ > free_end_) - { - const size_t requested = (size_ > 128 ? size_ : 128) * 8192 - 64; - chunk_* c = reinterpret_cast(::operator new(requested)); - c->prev = chunklist_; - chunklist_ = c; - - free_start_ = c->data_ + size_; - free_end_ = c->data_ + requested; - } + new_chunk_(); void* res = free_start_; free_start_ += size_; @@ -105,6 +97,8 @@ namespace spot } private: + void new_chunk_(); + const size_t size_; struct block_ { block_* next; }* freelist_; char* free_start_; From c005041e53199b6f6737bde6b3a4f82ea1da23df Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Fri, 22 May 2020 16:09:26 +0200 Subject: [PATCH 09/30] improve fuse_marks_here by detecting more patterns This remove some restrictions that prevented fuse_marks_here from simplifying certain patterns, as noted in the first comment of issue #405. * spot/twaalgos/cleanacc.cc (find_interm_rec, find_fusable): Remove some unnecessary restrictions to singleton marks, and replace the hack put one non-singleton mark at the beginning of the singleton list by a sort. * tests/python/simplacc.py: Add two test cases. * tests/python/automata.ipynb, tests/core/remfin.test: Improve expected results. * NEWS: Mention the bug. --- NEWS | 6 +++ spot/twaalgos/cleanacc.cc | 26 ++++++------- tests/core/remfin.test | 37 +++++++++---------- tests/python/automata.ipynb | 74 ++++++++++++++++++------------------- tests/python/simplacc.py | 14 +++++++ 5 files changed, 87 insertions(+), 70 deletions(-) diff --git a/NEWS b/NEWS index f8ab2a8df..4b549715e 100644 --- a/NEWS +++ b/NEWS @@ -42,6 +42,12 @@ New in spot 2.9.0.dev (not yet released) bits. This affects the output of "ltlcross --csv" and "--stats=%t" for many tools. + - simplify_acceptance() missed some patterns it should have been + able to simplify. For instance Fin(0)&(Fin(1)|Fin(2)|Fin(4)) + should simplify to Fin(1)|Fin(2)|Fin(4) adter adding {1,2,4} to + every place where 0 occur, and then the acceptance would be + renumbered to Fin(0)|Fin(1)|Fin(2). This is now fixed. + New in spot 2.9 (2020-04-30) Command-line tools: diff --git a/spot/twaalgos/cleanacc.cc b/spot/twaalgos/cleanacc.cc index ee47edc84..667f2e59e 100644 --- a/spot/twaalgos/cleanacc.cc +++ b/spot/twaalgos/cleanacc.cc @@ -390,7 +390,7 @@ namespace spot case acc_cond::acc_op::FinNeg: { auto m = pos[-1].mark; - if (op == wanted && m.is_singleton()) + if (op == wanted) { res |= m; } @@ -427,7 +427,7 @@ namespace spot if (op == wanted) { auto m = pos[-1].mark; - if (!seen && m.is_singleton()) + if (!seen) { seen = true; res |= m; @@ -512,9 +512,9 @@ namespace spot case acc_cond::acc_op::Inf: case acc_cond::acc_op::Fin: { - auto m = pos[-1].mark; - if (op == wanted && m.is_singleton()) - singletons.emplace_back(m, pos); + if (op == wanted) + singletons.emplace_back(pos[-1].mark, + pos); pos -= 2; } break; @@ -526,20 +526,20 @@ namespace spot // {b,d} can receive {a} if they // (b and d) are both used once. if (auto m = find_interm_rec(pos)) - { - singletons.emplace_back(m, pos); - // move this to the front, to - // be sure it is the first - // recipient tried. - swap(singletons.front(), - singletons.back()); - } + singletons.emplace_back(m, pos); pos -= pos->sub.size + 1; break; } } while (pos > rend); + // sort the singletons vector: we want + // those that are not really singleton to + // be first to they can become recipient + std::partition(singletons.begin(), singletons.end(), + [&] (auto s) + { return !s.first.is_singleton(); }); + acc_cond::mark_t can_receive = {}; for (auto p: singletons) if ((p.first & once) == p.first) diff --git a/tests/core/remfin.test b/tests/core/remfin.test index 73d7eec28..52ca43b89 100755 --- a/tests/core/remfin.test +++ b/tests/core/remfin.test @@ -292,8 +292,6 @@ State: 1 --END-- EOF -acctwelve='Inf(0)&Inf(1)&Inf(2)&Inf(3)&Inf(4)&Inf(5)' -acctwelve=$acctwelve'&Inf(6)&Inf(7)&Inf(8)&Inf(9)&Inf(10)&Inf(11)' cat >expected <\n" ], "text/plain": [ - " *' at 0x7fbc2c2c2bd0> >" + " *' at 0x7f9f5d7cbd50> >" ] }, "execution_count": 2, @@ -657,7 +657,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c2c9270> >" + " *' at 0x7f9f5d7cf480> >" ] }, "execution_count": 6, @@ -733,7 +733,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c2c9a20> >" + " *' at 0x7f9f5d7cfc00> >" ] }, "execution_count": 7, @@ -816,7 +816,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c2ce600> >" + " *' at 0x7f9f5d7cf3f0> >" ] }, "execution_count": 8, @@ -1349,7 +1349,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c2de5d0> >" + " *' at 0x7f9f5d7d4930> >" ] }, "execution_count": 12, @@ -1463,7 +1463,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c2defc0> >" + " *' at 0x7f9f5d7d4cc0> >" ] }, "execution_count": 13, @@ -1594,7 +1594,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c2e4270> >" + " *' at 0x7f9f5d7d4990> >" ] }, "execution_count": 14, @@ -1816,7 +1816,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c2e4180> >" + " *' at 0x7f9f5d7d4b70> >" ] }, "metadata": {}, @@ -1835,16 +1835,14 @@ " viewBox=\"0.00 0.00 482.00 315.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", "\n", "\n", - "Inf(\n", - "\n", - ") | Inf(\n", - "\n", - ") | (Inf(\n", - "\n", - ")&Inf(\n", - "\n", - "))\n", - "[Fin-less 4]\n", + "Inf(\n", + "\n", + ") | (Inf(\n", + "\n", + ")&Inf(\n", + "\n", + "))\n", + "[Fin-less 3]\n", "\n", "\n", "\n", @@ -1864,7 +1862,7 @@ "\n", "\n", "1\n", - "\n", + "\n", "\n", "\n", "\n", @@ -1879,7 +1877,7 @@ "\n", "a\n", "\n", - "\n", + "\n", "\n", "\n", "\n", @@ -1893,7 +1891,7 @@ "\n", "\n", "!a\n", - "\n", + "\n", "\n", "\n", "\n", @@ -1914,7 +1912,7 @@ "\n", "\n", "b\n", - "\n", + "\n", "\n", "\n", "\n", @@ -1922,7 +1920,7 @@ "\n", "\n", "a & b\n", - "\n", + "\n", "\n", "\n", "\n", @@ -1930,8 +1928,8 @@ "\n", "\n", "!a & b\n", - "\n", - "\n", + "\n", + "\n", "\n", "\n", "\n", @@ -2014,7 +2012,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c2e94e0> >" + " *' at 0x7f9f5d7d4e40> >" ] }, "metadata": {}, @@ -2193,7 +2191,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c2e4300> >" + " *' at 0x7f9f5d7d4c00> >" ] }, "metadata": {}, @@ -2341,7 +2339,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c2e9ed0> >" + " *' at 0x7f9f658bbc90> >" ] }, "metadata": {}, @@ -2530,7 +2528,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c2f4060> >" + " *' at 0x7f9f5d7d4c00> >" ] }, "execution_count": 19, @@ -2606,7 +2604,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c2f4de0> >" + " *' at 0x7f9f5d7e2f90> >" ] }, "execution_count": 20, @@ -3156,7 +3154,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c2f4840> >" + " *' at 0x7f9f5d7f18d0> >" ] }, "metadata": {}, @@ -3256,7 +3254,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c279390> >" + " *' at 0x7f9f5d7d4b70> >" ] }, "execution_count": 24, @@ -3329,7 +3327,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c280c60> >" + " *' at 0x7f9f5d7f1330> >" ] }, "execution_count": 25, @@ -3500,7 +3498,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c287cc0> >" + " *' at 0x7f9f5d7f1450> >" ] }, "execution_count": 27, @@ -3583,7 +3581,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c2f4840> >" + " *' at 0x7f9f5d7f18d0> >" ] }, "metadata": {}, @@ -3648,7 +3646,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c2f4840> >" + " *' at 0x7f9f5d7f18d0> >" ] }, "metadata": {}, @@ -3735,7 +3733,7 @@ "\n" ], "text/plain": [ - " *' at 0x7fbc2c2f4840> >" + " *' at 0x7f9f5d7f18d0> >" ] }, "execution_count": 29, @@ -3768,7 +3766,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.2" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/tests/python/simplacc.py b/tests/python/simplacc.py index e4e902dbd..a6bcc29ae 100644 --- a/tests/python/simplacc.py +++ b/tests/python/simplacc.py @@ -50,6 +50,16 @@ State: 5 [!0&1] 4 {3 5} [!0&1] 3 {2 4} [!0&1] 2 {2 3} [!0&!1] 0 {0} [!0&1] 7 {0 4 5} [0&1] 5 {2} State: 6 [0&!1] 7 [0&!1] 1 {1 4} [0&1] 4 {1 4} State: 7 [0&1] 3 {2 3} [0&1] 0 [!0&!1] 6 [0&1] 1 State: 8 [0&1] 3 [!0&!1] 0 [0&1] 9 State: 9 [0&!1] 7 {4 5} [!0&1] 8 {0} [0&1] 9 --END-- +/* Derived from issue #405. */ +HOA: v1 States: 2 Start: 0 AP: 2 "p0" "p1" Acceptance: 4 Fin(0) & +(Fin(1)|Fin(2)|Fin(3)) properties: trans-labels explicit-labels trans-acc +--BODY-- State: 0 [!0&!1] 0 {0 1 3} [0&1] 1 {0 2} [0&!1] 0 {2} State: +1 [0&1] 0 {0 2} [0&1] 1 {1} [0&!1] 1 --END-- +/* More complex version of the previous automaton */ +HOA: v1 States: 2 Start: 0 AP: 2 "p0" "p1" Acceptance: 5 Fin(0) & +(((Fin(1)|Fin(2)|Fin(3))&Inf(4)|Fin(3))) properties: trans-labels +explicit-labels trans-acc --BODY-- State: 0 [!0&!1] 0 {0 1 3} [0&1] 1 +{0 2} [0&!1] 0 {2} State: 1 [0&1] 0 {0 2} [0&1] 1 {1} [0&!1] 1 {4} --END-- """)) res = [] @@ -80,4 +90,8 @@ assert res == [ '((Inf(1) & Fin(2)) | Fin(5)) & (Inf(0) | (Inf(1) & (Inf(3) | Fin(4))))', 'Inf(0)', 'Fin(0)', + 'Fin(0)|Fin(1)|Fin(2)', + 'Inf(0)&Inf(1)&Inf(2)', + '((Fin(0)|Fin(1)) & Inf(3)) | Fin(2)', + '((Inf(0)&Inf(1)) | Fin(3)) & Inf(2)', ] From b762f54228e6c3c8305606416820cb7907257d59 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Sat, 23 May 2020 11:56:16 +0200 Subject: [PATCH 10/30] remfin: do not clone transitions that are accepting in main * spot/twaalgos/remfin.cc (default_strategy): Detect transitions from the main copy that are completely accepting and that do not need to be repeated in the clones. * tests/python/remfin.py: Add a test case. * tests/core/ltl2dstar4.test: Improve expected results. * NEWS: Mention the change. --- NEWS | 3 +++ spot/twaalgos/remfin.cc | 26 ++++++++++++++++++++++++-- tests/core/ltl2dstar4.test | 4 ++-- tests/python/remfin.py | 30 ++++++++++++++++++++++++++++-- 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 4b549715e..20e3a024c 100644 --- a/NEWS +++ b/NEWS @@ -32,6 +32,9 @@ New in spot 2.9.0.dev (not yet released) spot::translator class when creating deterministic automata with generic acceptance. + - remove_fin() learned a trick to remove some superfluous + transitions. + Bugs fixed: - Work around undefined behavior reported by clang 10.0.0's UBsan. diff --git a/spot/twaalgos/remfin.cc b/spot/twaalgos/remfin.cc index d34110e62..38774f60b 100644 --- a/spot/twaalgos/remfin.cc +++ b/spot/twaalgos/remfin.cc @@ -667,6 +667,20 @@ namespace spot trace << "main_sets " << main_sets << "\nmain_add " << main_add << '\n'; + // If the SCC is rejecting, there is no need for clone. + // Pretend we don't interesect any Fin. + if (si.is_rejecting_scc(n)) + intersects_fin = false; + + // Edges that are already satisfying the acceptance of the + // main copy do not need to be duplicated in the clones, so + // we fill allacc_edge to remember those. Of course this is + // only needed if the main copy can be accepting and if we + // will create clones. + std::vector allacc_edge(aut->edge_vector().size(), false); + auto main_acc = res->acc().restrict_to(main_sets | main_add); + bool check_main_acc = intersects_fin && !main_acc.is_f(); + // Create the main copy for (auto s: states) for (auto& t: aut->out(s)) @@ -675,11 +689,14 @@ namespace spot if (sbacc || SPOT_LIKELY(si.scc_of(t.dst) == n)) a = (t.acc & main_sets) | main_add; res->new_edge(s, t.dst, t.cond, a); + // remember edges that are completely accepting + if (check_main_acc && main_acc.accepting(a)) + allacc_edge[aut->edge_number(t)] = true; } // We do not need any other copy if the SCC is non-accepting, // of if it does not intersect any Fin. - if (!intersects_fin || si.is_rejecting_scc(n)) + if (!intersects_fin) continue; // Create clones @@ -698,7 +715,12 @@ namespace spot auto ns = state_map[s]; for (auto& t: aut->out(s)) { - if ((t.acc & r) || si.scc_of(t.dst) != n) + if ((t.acc & r) || si.scc_of(t.dst) != n + // edges that are already accepting in the + // main copy need not be copied in the + // clone, since cycles going through them + // are already accepted. + || allacc_edge[aut->edge_number(t)]) continue; auto nd = state_map[t.dst]; res->new_edge(ns, nd, t.cond, (t.acc & k) | a); diff --git a/tests/core/ltl2dstar4.test b/tests/core/ltl2dstar4.test index a0db47ec4..dfa004805 100755 --- a/tests/core/ltl2dstar4.test +++ b/tests/core/ltl2dstar4.test @@ -1,6 +1,6 @@ #!/bin/sh # -*- coding: utf-8 -*- -# Copyright (C) 2013, 2014, 2015, 2017 Laboratoire de Recherche et +# Copyright (C) 2013-2015, 2017, 2020 Laboratoire de Recherche et # Développement de l'Epita (LRDE). # # This file is part of Spot, a model checking library. @@ -34,7 +34,7 @@ ltlfilt -f '(GFa -> GFb) & (GFc -> GFd)' -l | ltl2dstar --ltl2nba=spin:ltl2tgba@-s $STR - - | autfilt --tgba --stats '%S %E %A %s %e %t %a %d' | tee out -test "`cat out`" = '9 144 4 25 149 416 2 0' +test "`cat out`" = '9 144 4 18 98 202 2 0' ltlfilt -f '(GFa -> GFb) & (GFc -> GFd)' -l | ltl2dstar --ltl2nba=spin:ltl2tgba@-s $STR - - | diff --git a/tests/python/remfin.py b/tests/python/remfin.py index b6f53d453..7eb9ab4d2 100644 --- a/tests/python/remfin.py +++ b/tests/python/remfin.py @@ -1,6 +1,6 @@ # -*- mode: python; coding: utf-8 -*- -# Copyright (C) 2015-2018 Laboratoire de Recherche et Développement -# de l'Epita +# Copyright (C) 2015-2018, 2020 Laboratoire de Recherche et Développement de +# l'Epita # # This file is part of Spot, a model checking library. # @@ -67,3 +67,29 @@ assert(a.prop_universal().is_maybe()) assert(a.prop_unambiguous().is_maybe()) assert(a.is_deterministic() == True) assert(a.is_unambiguous() == True) + +a = spot.automaton(""" +HOA: v1 +States: 3 +Start: 0 +AP: 2 "a" "b" +acc-name: Buchi +Acceptance: 5 Inf(0)&Fin(4) | Inf(2)&Inf(3) | Inf(1) +--BODY-- +State: 0 {3} +[t] 0 +[0] 1 {1} +[!0] 2 {0 4} +State: 1 {3} +[1] 0 +[0&1] 1 {0} +[!0&1] 2 {2 4} +State: 2 +[!1] 0 +[0&!1] 1 {0} +[!0&!1] 2 {0 4} +--END-- +""") +b = spot.remove_fin(a) +size = (b.num_states(), b.num_edges()) +assert size == (5, 17); From b434ac7f8a4c1394b3333771258af54eced9389c Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Sat, 23 May 2020 12:00:56 +0200 Subject: [PATCH 11/30] simplify_acc: perform unit-propagation earlier Closes #405. This shows no difference on the test suite, but that is thanks to the previous patch: without it, an example in automata.ipynb would have an extra edge. * spot/twaalgos/cleanacc.cc (simplify_acceptance): Call unit_propagation() before simplify_complementary_marks_here() and fuse_marks_here(), because that is simpler to perform. --- spot/twaalgos/cleanacc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spot/twaalgos/cleanacc.cc b/spot/twaalgos/cleanacc.cc index 667f2e59e..5a59dad6d 100644 --- a/spot/twaalgos/cleanacc.cc +++ b/spot/twaalgos/cleanacc.cc @@ -622,9 +622,9 @@ namespace spot if (aut->acc().is_generalized_buchi()) break; acc_cond::acc_code old = aut->get_acceptance(); + aut->set_acceptance(aut->acc().unit_propagation()); simplify_complementary_marks_here(aut); fuse_marks_here(aut); - aut->set_acceptance(aut->acc().unit_propagation()); if (old == aut->get_acceptance()) break; } From 16540869d47c3a488ae5e1c07dc2c5dc646e4b0e Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Sun, 24 May 2020 09:45:35 +0200 Subject: [PATCH 12/30] ltlsynt: add --algo=ps * bin/ltlsynt.cc: Implement this. * tests/core/ltlsynt.test: Add a test case. * NEWS: Mention it. --- NEWS | 3 +++ bin/ltlsynt.cc | 47 +++++++++++++++++++++++++++++++++++++---- tests/core/ltlsynt.test | 19 +++++++++++++++-- 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 20e3a024c..12d94cfd8 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,9 @@ New in spot 2.9.0.dev (not yet released) The default is 1 in "--high" mode, 2 in "--medium" mode or in "--deterministic --low" mode, and 0 in other "--low" modes. + - ltlsynt learned --algo=ps to use the default conversion to + deterministic parity automata (the same as ltl2tgba -DP'max odd'). + Library: - product_xor() and product_xnor() are two new versions of the diff --git a/bin/ltlsynt.cc b/bin/ltlsynt.cc index e805a9f3e..0c1ce9aae 100644 --- a/bin/ltlsynt.cc +++ b/bin/ltlsynt.cc @@ -74,10 +74,11 @@ static const argp_option options[] = " propositions", 0}, /**************************************************/ { nullptr, 0, nullptr, 0, "Fine tuning:", 10 }, - { "algo", OPT_ALGO, "ds|sd|lar|lar.old", 0, + { "algo", OPT_ALGO, "sd|ds|ps|lar|lar.old", 0, "choose the algorithm for synthesis:\n" - " - sd: split then determinize with Safra (default)\n" - " - ds: determinize (Safra) then split\n" + " - sd: translate to tgba, split, then determinize (default)\n" + " - ds: translate to tgba, determinize, then split\n" + " - ps: translate to dpa, then split\n" " - lar: translate to a deterministic automaton with arbitrary" " acceptance condition, then use LAR to turn to parity," " then split\n" @@ -136,6 +137,7 @@ enum solver { DET_SPLIT, SPLIT_DET, + DPA_SPLIT, LAR, LAR_OLD, }; @@ -144,6 +146,7 @@ static char const *const solver_names[] = { "ds", "sd", + "ps", "lar", "lar.old" }; @@ -152,6 +155,7 @@ static char const *const solver_args[] = { "detsplit", "ds", "splitdet", "sd", + "dpasplit", "ps", "lar", "lar.old", nullptr @@ -160,6 +164,7 @@ static solver const solver_types[] = { DET_SPLIT, DET_SPLIT, SPLIT_DET, SPLIT_DET, + DPA_SPLIT, DPA_SPLIT, LAR, LAR_OLD, }; @@ -354,10 +359,21 @@ namespace spot::stopwatch sw; bool want_time = verbose || opt_csv; - if (opt_solver == LAR || opt_solver == LAR_OLD) + switch (opt_solver) { + case LAR: + case LAR_OLD: trans_.set_type(spot::postprocessor::Generic); trans_.set_pref(spot::postprocessor::Deterministic); + break; + case DPA_SPLIT: + trans_.set_type(spot::postprocessor::ParityMaxOdd); + trans_.set_pref(spot::postprocessor::Deterministic + | spot::postprocessor::Colored); + break; + case DET_SPLIT: + case SPLIT_DET: + break; } if (want_time) @@ -423,6 +439,29 @@ namespace << tmp->num_states() << " states\n"; break; } + case DPA_SPLIT: + { + if (want_time) + sw.start(); + aut->merge_states(); + if (want_time) + paritize_time = sw.stop(); + if (verbose) + std::cerr << "simplification done in " << paritize_time + << " seconds\nDPA has " << aut->num_states() + << " states\n"; + if (want_time) + sw.start(); + dpa = split_2step(aut, all_inputs); + spot::colorize_parity_here(dpa, true); + if (want_time) + split_time = sw.stop(); + if (verbose) + std::cerr << "split inputs and outputs done in " << split_time + << " seconds\nautomaton has " + << dpa->num_states() << " states\n"; + break; + } case SPLIT_DET: { if (want_time) diff --git a/tests/core/ltlsynt.test b/tests/core/ltlsynt.test index 1584b8bf5..d677cf6fc 100644 --- a/tests/core/ltlsynt.test +++ b/tests/core/ltlsynt.test @@ -118,6 +118,20 @@ ltlsynt --ins='a' --outs='b' -f 'GFa <-> GFb' --verbose --realizability 2> out sed 's/ [0-9.e-]* seconds/ X seconds/g' out > outx diff outx exp +cat >exp < GFb' --verbose --algo=ps 2> out +sed 's/ [0-9.e-]* seconds/ X seconds/g' out > outx +diff outx exp + cat >exp < GFb' --csv=FILE || : ltlsynt --algo=sd $opts 'FGa <-> GF(b&XXb)' --csv='>>FILE' || : + ltlsynt --algo=ps $opts 'FGa <-> GF(b&XXb)' --csv='>>FILE' || : ltlsynt --algo=lar $opts 'FGc <-> GF(!b&XXb)' --csv='>>FILE' || : ltlsynt --algo=lar.old $opts 'FGa <-> GF(c&a)' --csv='>>FILE' || : - test 5 = `wc -l < FILE` + test 6 = `wc -l < FILE` # Make sure all lines in FILE have the same number of comas sed 's/[^,]//g' < FILE | ( read first @@ -242,7 +257,7 @@ for i in 2 3 4 5 6 10; do ltl2tgba -f "!($F)" > negf_aut$i # test ltlsynt - for algo in sd ds lar lar.old; do + for algo in sd ds ps lar lar.old; do ltlsynt -f "$F" --ins="$IN" --outs="$OUT" --algo=$algo > out$i || true REAL=`head -1 out$i` test $REAL = $EXP From e06f8a3ece4f4cfc26c5905e29840e41c40cd61f Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Sun, 24 May 2020 14:05:46 +0200 Subject: [PATCH 13/30] work around diagnostic changes in Bison 3.6 Bison <3.6 used to complain about "$undefined", while Bison >=3.6 now write "invalid token". * tests/core/parseaut.test, tests/core/parseerr.test, tests/core/sugar.test: Adjust expected diagnostics to match Bison pre and post 3.6. --- tests/core/parseaut.test | 15 +++++++++------ tests/core/parseerr.test | 8 ++++---- tests/core/sugar.test | 9 +++++---- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/tests/core/parseaut.test b/tests/core/parseaut.test index 338eb39c8..b4fba6d96 100755 --- a/tests/core/parseaut.test +++ b/tests/core/parseaut.test @@ -1,6 +1,6 @@ #!/bin/sh # -*- coding: utf-8 -*- -# Copyright (C) 2014-2018 Laboratoire de Recherche et Développement de +# Copyright (C) 2014-2018, 2020 Laboratoire de Recherche et Développement de # l'Epita (LRDE). # # This file is part of Spot, a model checking library. @@ -31,7 +31,9 @@ expecterr() # If autfilt is compiled statically, the '.../lt-' parse of # its name is not stripped, and the error message show the # full path. - sed 's:^\.\./\.\./bin/::' $1.err-t >$1.err + # Also work around differences between Bison >=3.6 (invalid token) + # end Bison <3.6 ($undefined). + sed 's:^\.\./\.\./bin/::;s/[$]undefined/invalid token/' $1.err-t >$1.err cat $1.err diff $1.err $1.exp } @@ -1226,21 +1228,22 @@ garbage EOF se='syntax error, unexpected' # this is just to keep lines short +undefined='invalid token' expecterr input <output +run 1 ../ltl2text input | sed 's/[$]undefined/invalid token/g' > output sed 's/$$//' >expected<<\EOF >>> $ @@ -53,7 +53,7 @@ ignoring trailing garbage >>> /2/3/4/5 a + b /6/7/8/ ^ -syntax error, unexpected $undefined +syntax error, unexpected invalid token >>> /2/3/4/5 a + b /6/7/8/ ^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ ignoring trailing garbage >>> a - b ^ -syntax error, unexpected $undefined +syntax error, unexpected invalid token >>> a - b ^^^ diff --git a/tests/core/sugar.test b/tests/core/sugar.test index de6d89f38..92c2095e0 100755 --- a/tests/core/sugar.test +++ b/tests/core/sugar.test @@ -1,7 +1,7 @@ #! /bin/sh # -*- coding: utf-8 -*- -# Copyright (C) 2018, 2019 Laboratoire de Recherche et Développement -# de l'Epita (LRDE). +# Copyright (C) 2018-2020 Laboratoire de Recherche et Développement de +# l'Epita (LRDE). # # This file is part of Spot, a model checking library. # @@ -135,11 +135,12 @@ EOF num="number for square bracket operator" numoreof="$num or end of formula" sep="separator for square bracket operator" -undefined='$undefined' +undefined='invalid token' closingbkt='square bracket operator, expecting closing bracket' eclosingbkt='expecting closing bracket or closing !]' ltlfilt -F err.in 2>err && exit 1 +sed 's/[$]undefined/invalid token/' err >err2 cat >expect2 <>> F[ @@ -329,4 +330,4 @@ syntax error, unexpected closing brace missing right operand for "SVA delay operator" EOF -diff -u err expect2 +diff -u err2 expect2 From 7c09f64c49742e416a0f72638eef6e8e015f3593 Mon Sep 17 00:00:00 2001 From: Florian Renkin Date: Sat, 23 May 2020 14:13:33 +0200 Subject: [PATCH 14/30] ltlsynt: Add -x option for translation * bin/ltlsynt.cc: ltlsynt can use extra options for translator. --- bin/ltlsynt.cc | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/bin/ltlsynt.cc b/bin/ltlsynt.cc index 0c1ce9aae..f672d9f3f 100644 --- a/bin/ltlsynt.cc +++ b/bin/ltlsynt.cc @@ -99,6 +99,8 @@ static const argp_option options[] = "not output)", 0 }, /**************************************************/ { nullptr, 0, nullptr, 0, "Miscellaneous options:", -1 }, + { "extra-options", 'x', "OPTS", 0, + "fine-tuning options (see spot-x (7))", 0 }, { nullptr, 0, nullptr, 0, nullptr, 0 }, }; @@ -125,6 +127,7 @@ static const char* opt_csv = nullptr; static bool opt_print_pg = false; static bool opt_real = false; static bool opt_print_aiger = false; +static spot::option_map extra_options; static double trans_time = 0.0; static double split_time = 0.0; @@ -643,6 +646,13 @@ parse_opt(int key, char* arg, struct argp_state*) case OPT_VERBOSE: verbose = true; break; + case 'x': + { + const char* opt = extra_options.parse_options(arg); + if (opt) + error(2, 0, "failed to parse --options near '%s'", opt); + } + break; } END_EXCEPTION_PROTECT; return 0; @@ -661,8 +671,11 @@ main(int argc, char **argv) // Setup the dictionary now, so that BuDDy's initialization is // not measured in our timings. spot::bdd_dict_ptr dict = spot::make_bdd_dict(); - spot::translator trans(dict); + spot::translator trans(dict, &extra_options); ltl_processor processor(trans, input_aps, output_aps); + + // Diagnose unused -x options + extra_options.report_unused_options(); return processor.run(); }); } From 8ac24acbf8cdab95307d2496a249fc405d3c5910 Mon Sep 17 00:00:00 2001 From: Florian Renkin Date: Sat, 23 May 2020 14:29:48 +0200 Subject: [PATCH 15/30] ltlsynt: Add more elements in csv * bin/ltlsynt.cc: Add the number of states of the dpa and of the parity game in the csv. --- bin/ltlsynt.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/bin/ltlsynt.cc b/bin/ltlsynt.cc index f672d9f3f..4df94a77d 100644 --- a/bin/ltlsynt.cc +++ b/bin/ltlsynt.cc @@ -135,6 +135,8 @@ static double paritize_time = 0.0; static double bgame_time = 0.0; static double solve_time = 0.0; static double strat2aut_time = 0.0; +static unsigned nb_states_dpa = 0; +static unsigned nb_states_parity_game = 0; enum solver { @@ -318,7 +320,8 @@ namespace out << ",\"strat2aut_time\""; out << ",\"realizable\""; } - out << '\n'; + out << ",\"dpa_num_states\",\"parity_game_num_states\"" + << '\n'; } std::ostringstream os; os << f; @@ -335,7 +338,9 @@ namespace out << ',' << strat2aut_time; out << ',' << realizable; } - out << '\n'; + out << ',' << nb_states_dpa + << ',' << nb_states_parity_game + << '\n'; outf.close(opt_csv); } @@ -532,6 +537,7 @@ namespace break; } } + nb_states_dpa = dpa->num_states(); if (want_time) sw.start(); auto owner = complete_env(dpa); @@ -557,6 +563,7 @@ namespace solve_time = sw.stop(); if (verbose) std::cerr << "parity game solved in " << solve_time << " seconds\n"; + nb_states_parity_game = pg.num_states(); timer.stop(); if (winning_region[1].count(pg.get_init_state_number())) { From 56c8d690bab68f2ac4a054a1b4a86cd60d883c9d Mon Sep 17 00:00:00 2001 From: Florian Renkin Date: Sat, 23 May 2020 14:31:59 +0200 Subject: [PATCH 16/30] ltlsynt: Change default options * bin/ltlsynt.cc: Change default options. * tests/core/ltlsynt.test: Add test. --- bin/ltlsynt.cc | 3 + tests/core/ltlsynt.test | 125 ++++++++++++++++++++++++++++------------ 2 files changed, 92 insertions(+), 36 deletions(-) diff --git a/bin/ltlsynt.cc b/bin/ltlsynt.cc index 4df94a77d..630ed12f5 100644 --- a/bin/ltlsynt.cc +++ b/bin/ltlsynt.cc @@ -669,6 +669,9 @@ int main(int argc, char **argv) { return protected_main(argv, [&] { + extra_options.set("simul", 0); + extra_options.set("det-simul", 0); + extra_options.set("tls-impl", 1); const argp ap = { options, parse_opt, nullptr, argp_program_doc, children, nullptr, nullptr }; if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr)) diff --git a/tests/core/ltlsynt.test b/tests/core/ltlsynt.test index d677cf6fc..8a0d10a6c 100644 --- a/tests/core/ltlsynt.test +++ b/tests/core/ltlsynt.test @@ -23,50 +23,62 @@ set -e cat >exp < GFb' --print-pg >out diff out exp cat >exp <exp < out +diff out exp + +cat >exp < out +diff out exp + +ltlsynt -f '!XXF(p0 & (p0 M Gp0))' > out +diff out exp From 37d0b0d04535a436a8298f7266179f4609e97b0b Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Sun, 24 May 2020 20:32:27 +0200 Subject: [PATCH 17/30] ltlsynt: use wdba-minimize=2 and ba-simul=0 * bin/ltlsynt.cc: Here. * tests/core/ltlsynt.test: Add extra test case. * NEWS: Mention ltlsynt -x and related defaults. --- NEWS | 4 ++++ bin/ltlsynt.cc | 2 ++ tests/core/ltlsynt.test | 6 ++++++ 3 files changed, 12 insertions(+) diff --git a/NEWS b/NEWS index 12d94cfd8..a485d33f9 100644 --- a/NEWS +++ b/NEWS @@ -21,6 +21,10 @@ New in spot 2.9.0.dev (not yet released) - ltlsynt learned --algo=ps to use the default conversion to deterministic parity automata (the same as ltl2tgba -DP'max odd'). + - ltlsynt now has a -x option to fine-tune the translation. See the + spot-x(7) man page for detail. Unlike ltl2tgba, ltlsynt defaults + to simul=0,ba-simul=0,det-simul=0,tls-impl=1,wdba-minimize=2. + Library: - product_xor() and product_xnor() are two new versions of the diff --git a/bin/ltlsynt.cc b/bin/ltlsynt.cc index 630ed12f5..c82afb00d 100644 --- a/bin/ltlsynt.cc +++ b/bin/ltlsynt.cc @@ -670,8 +670,10 @@ main(int argc, char **argv) { return protected_main(argv, [&] { extra_options.set("simul", 0); + extra_options.set("ba-simul", 0); extra_options.set("det-simul", 0); extra_options.set("tls-impl", 1); + extra_options.set("wdba-minimize", 2); const argp ap = { options, parse_opt, nullptr, argp_program_doc, children, nullptr, nullptr }; if (int err = argp_parse(&ap, argc, argv, ARGP_NO_HELP, nullptr, nullptr)) diff --git a/tests/core/ltlsynt.test b/tests/core/ltlsynt.test index 8a0d10a6c..86da4626d 100644 --- a/tests/core/ltlsynt.test +++ b/tests/core/ltlsynt.test @@ -321,3 +321,9 @@ diff out exp ltlsynt -f '!XXF(p0 & (p0 M Gp0))' > out diff out exp + +f='Fp0 U XX((p0 & F!p1) | (!p0 & Gp1))' +ltlsynt --verbose --algo=ps --outs=p1 --ins=p0 -f "$f" 2>err +grep 'DPA has 14 states' err +ltlsynt --verbose -x wdba-minimize=1 --algo=ps --outs=p1 --ins=p0 -f "$f" 2>err +grep 'DPA has 12 states' err From 9e075e7312a4bca272e6945a0613ed85974f3f0a Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Mon, 25 May 2020 10:51:44 +0200 Subject: [PATCH 18/30] twa: get rid of set_num_sets_() * spot/twa/twa.hh (set_num_sets_): Remove, and adjust all uses. This fixes #414. --- spot/twa/twa.hh | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/spot/twa/twa.hh b/spot/twa/twa.hh index 5b957b902..7a5fa2897 100644 --- a/spot/twa/twa.hh +++ b/spot/twa/twa.hh @@ -929,16 +929,6 @@ namespace spot private: acc_cond acc_; - void set_num_sets_(unsigned num) - { - if (num < acc_.num_sets()) - { - acc_.~acc_cond(); - new (&acc_) acc_cond; - } - acc_.add_sets(num - acc_.num_sets()); - } - public: /// Number of acceptance sets used by the automaton. unsigned num_sets() const @@ -958,8 +948,7 @@ namespace spot /// \param c the acceptance formula void set_acceptance(unsigned num, const acc_cond::acc_code& c) { - set_num_sets_(num); - acc_.set_acceptance(c); + acc_ = acc_cond(num, c); } /// \brief Set the acceptance condition of the automaton. @@ -997,8 +986,7 @@ namespace spot /// property is automatically turned on. void set_generalized_buchi(unsigned num) { - set_num_sets_(num); - acc_.set_generalized_buchi(); + acc_ = acc_cond(num, acc_cond::acc_code::generalized_buchi(num)); } /// \brief Set generalized co-Büchi acceptance @@ -1015,8 +1003,7 @@ namespace spot /// property is automatically turned on. void set_generalized_co_buchi(unsigned num) { - set_num_sets_(num); - acc_.set_generalized_co_buchi(); + acc_ = acc_cond(num, acc_cond::acc_code::generalized_co_buchi(num)); } /// \brief Set Büchi acceptance. @@ -1036,8 +1023,8 @@ namespace spot /// \see prop_state_acc acc_cond::mark_t set_buchi() { - set_generalized_buchi(1); - return acc_.mark(0); + acc_ = acc_cond(1, acc_cond::acc_code::buchi()); + return {0}; } /// \brief Set co-Büchi acceptance. @@ -1057,8 +1044,8 @@ namespace spot /// \see prop_state_acc acc_cond::mark_t set_co_buchi() { - set_generalized_co_buchi(1); - return acc_.mark(0); + acc_ = acc_cond(1, acc_cond::acc_code::cobuchi()); + return {0}; } private: From f16bc8a58b135982210978c9e8126f9c72af4610 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Fri, 29 May 2020 17:14:17 +0200 Subject: [PATCH 19/30] sccinfo: fix doc * spot/twaalgos/sccinfo.hh (scc_info_options::NONE): Fix doxygen doc. --- spot/twaalgos/sccinfo.hh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/spot/twaalgos/sccinfo.hh b/spot/twaalgos/sccinfo.hh index ff10c9d89..3c31c3dcd 100644 --- a/spot/twaalgos/sccinfo.hh +++ b/spot/twaalgos/sccinfo.hh @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2014-2019 Laboratoire de Recherche et Développement +// Copyright (C) 2014-2020 Laboratoire de Recherche et Développement // de l'Epita (LRDE). // // This file is part of Spot, a model checking library. @@ -304,8 +304,9 @@ namespace spot /// \brief Options to alter the behavior of scc_info enum class scc_info_options { - /// Stop exploring when an accepting SCC is found, and do not track - /// the states of each SCC. + /// Explore all SCCs, but do not track the states of each SCC and + /// the successor SCC of each SCC. This is enough to call the + /// scc_of() method. NONE = 0, /// Stop exploring after an accepting SCC has been found. /// Using this option forbids future uses of is_useful_scc() and From 3368b4b99facbde9906398ad1862ba12ba9021f7 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Sat, 30 May 2020 14:28:50 +0200 Subject: [PATCH 20/30] * tests/sanity/80columns.test: Force LC_ALL. --- tests/sanity/80columns.test | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/sanity/80columns.test b/tests/sanity/80columns.test index 93e9a4ed8..9942946d8 100755 --- a/tests/sanity/80columns.test +++ b/tests/sanity/80columns.test @@ -1,6 +1,6 @@ #! /bin/sh # -*- coding: utf-8 -*- -# Copyright (C) 2012, 2016-2017, 2019 Laboratoire de Recherche et +# Copyright (C) 2012, 2016-2017, 2019-2020 Laboratoire de Recherche et # Développement de l'Epita (LRDE). # Copyright (C) 2004, 2005 Laboratoire d'Informatique de Paris 6 # (LIP6), département Systèmes Répartis Coopératifs (SRC), Université @@ -27,14 +27,14 @@ set -e rm -f failures.80 -LANG=en_US.UTF-8 -export LANG +LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 +export LANG LC_ALL if [ "`echo '{r₁|r₂|r₃}' | wc -m`" != 11 ]; then - LANG=C - export LANG # The current locale does not grok unicode. # We still run this test, but only on lines that are purely ascii. + LANG=C LC_ALL=C + export LANG LC_ALL x='[^ -~]' # This blank is a tab. else x='.' From 4cfa253830a02d571999d383fda46f82eed6ad70 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Sun, 31 May 2020 16:19:51 +0200 Subject: [PATCH 21/30] ltldo: improve error messages Use ltldo:... instead of error:... and warning:... and also improve the diagnostic displayed after a translation failure to mention the tool and formula. Incidentally, this fixes a spurious test case failure observed by Philipp Schlehuber on CentOS7.7 where glibc 2.17 is installed. With this system, when posix_spawn() starts a binary that does not exist, it returns success and let the child die with exit code 127. On more recent glibc, posix_spawn() manages to return execve()'s errno, as if the child had not been created. We handle those two different ways to fail, but before this patch one used to print "error:..." and the other "ltldo:...". * bin/ltldo.cc: Display the program_name in error message. Display the command name and formula on translation failure. * tests/core/ltldo.test: Adjust test case. * NEWS: Mention the fix. --- NEWS | 3 +++ bin/ltldo.cc | 39 +++++++++++++++++++-------------------- tests/core/ltldo.test | 16 +++++++++------- 3 files changed, 31 insertions(+), 27 deletions(-) diff --git a/NEWS b/NEWS index a485d33f9..eb833532f 100644 --- a/NEWS +++ b/NEWS @@ -58,6 +58,9 @@ New in spot 2.9.0.dev (not yet released) every place where 0 occur, and then the acceptance would be renumbered to Fin(0)|Fin(1)|Fin(2). This is now fixed. + - Improve ltldo diagnostics to fix spurious test-suite failure on + systems with antique GNU libc. + New in spot 2.9 (2020-04-30) Command-line tools: diff --git a/bin/ltldo.cc b/bin/ltldo.cc index fdb634450..f57a528b2 100644 --- a/bin/ltldo.cc +++ b/bin/ltldo.cc @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2015-2019 Laboratoire de Recherche et Développement +// Copyright (C) 2015-2020 Laboratoire de Recherche et Développement // de l'Epita (LRDE). // // This file is part of Spot, a model checking library. @@ -39,6 +39,7 @@ #include "common_hoaread.hh" #include +#include #include #include #include @@ -233,18 +234,13 @@ namespace problem = false; if (timed_out) { - // A timeout is considered benign + // A timeout is considered benign, unless --fail-on-timeout. if (fail_on_timeout) - { - std::cerr << "error:"; - problem = true; - } + problem = true; else - { - std::cerr << "warning:"; - ++timeout_count; - } - std::cerr << " timeout during execution of command \"" + ++timeout_count; + std::cerr << program_name + << ": timeout during execution of command \"" << cmd << "\"\n"; } else if (WIFSIGNALED(es)) @@ -253,7 +249,7 @@ namespace { problem = true; es = WTERMSIG(es); - std::cerr << "error: execution of command \"" << cmd + std::cerr << program_name << ": execution of command \"" << cmd << "\" terminated by signal " << es << ".\n"; } } @@ -263,7 +259,7 @@ namespace { problem = true; es = WEXITSTATUS(es); - std::cerr << "error: execution of command \"" << cmd + std::cerr << program_name << ": execution of command \"" << cmd << "\" returned exit code " << es << ".\n"; } } @@ -275,14 +271,14 @@ namespace if (!aut->errors.empty() && errors_opt != errors_ignore) { problem = true; - std::cerr << "error: failed to parse the automaton " + std::cerr << program_name << ": failed to parse the automaton " "produced by \"" << cmd << "\".\n"; aut->format_errors(std::cerr); } else if (aut->aborted && errors_opt != errors_ignore) { problem = true; - std::cerr << "error: command \"" << cmd + std::cerr << program_name << ": command \"" << cmd << "\" aborted its output.\n"; } else @@ -410,11 +406,14 @@ namespace auto aut = runner.translate(t, problem, timer); if (problem) { - if (errors_opt == errors_abort) - error_at_line(2, 0, filename, linenum, "aborting here"); - else - error_at_line(0, 0, filename, linenum, - "failed to translate this input"); + // An error message already occurred about the problem, + // but this additional one will print filename & + // linenum, and possibly exit. + std::string sf = spot::str_psl(f); + error_at_line(errors_opt == errors_abort ? 2 : 0, 0, + filename, linenum, + "failed to run `%s' on `%s'", + tools[t].name, sf.c_str()); } if (aut) { diff --git a/tests/core/ltldo.test b/tests/core/ltldo.test index 601f9329d..ce02dfb04 100755 --- a/tests/core/ltldo.test +++ b/tests/core/ltldo.test @@ -1,6 +1,6 @@ #!/bin/sh # -*- coding: utf-8 -*- -# Copyright (C) 2015-2019 Laboratoire de Recherche et Développement de +# Copyright (C) 2015-2020 Laboratoire de Recherche et Développement de # l'Epita (LRDE). # # This file is part of Spot, a model checking library. @@ -43,21 +43,23 @@ genltl --or-g=1..2 | run 0 ltldo -t 'sleep 10; echo %f' -T1 -t 'sleep 10; echo %f' \ >output 2>stderr test -z "`cat output`" -test 4 = `grep -c warning: stderr` +test 4 = `grep -c ltldo: stderr` +grep -q 'failed to' stderr && exit 1 genltl --or-g=1..2 | run 0 ltldo -t 'sleep 10; echo %f' -T1 -t 'sleep 10; echo %f' \ --fail-on-timeout --error=warn >output 2>stderr test -z "`cat output`" -test 4 = `grep -c error: stderr` -grep -q 'aborting here' stderr && exit 1 +test 8 = `grep -c ltldo: stderr` +test 4 = `grep -c ltldo:-: stderr` +grep -q 'failed to' stderr genltl --or-g=1..2 | run 2 ltldo -t 'sleep 10; echo %f' -T1 -t 'sleep 10; echo %f' \ --fail-on-timeout >output 2>stderr test -z "`cat output`" -test 1 = `grep -c error: stderr` -grep -q 'aborting here' stderr +test 2 = `grep -c ltldo: stderr` +grep -q 'failed to' stderr test "`echo 1,a,3,4 | ltldo -F-/2 ltl2tgba --stats='%<,%s,%>'`" = '1,2,3,4' @@ -143,7 +145,7 @@ diff output expected ltldo ': %s; true>%O' -f GFa 2>stderr && exit 1 test $? = 2 grep ':.*empty input' stderr -grep 'ltldo: aborting' stderr +grep 'ltldo: failed to run' stderr ltldo ': %s; true>%O' --errors=ignore -f GFa 2>stderr test $? = 0 From e20bae6609def7c07cfd325aad96f736f0d30ee5 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Tue, 9 Jun 2020 00:14:36 +0200 Subject: [PATCH 22/30] swig: search for swig4.0 * configure.ac: Use swig4.0 when available. * HACKING: Update. --- HACKING | 4 +++- configure.ac | 7 ++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/HACKING b/HACKING index 7cc609c1d..1b37af6aa 100644 --- a/HACKING +++ b/HACKING @@ -32,7 +32,9 @@ since the generated files they produce are distributed.) a separate and more recent org-mode package, or you can simply upgrade from ELPA). Groff (a.k.a. GNU troff) >= 1.20 - SWIG >= 3.0 (for its better C++11/C++14 support) + SWIG >= 3.0.2 (for its better C++11/C++14 support) + Note that if you use Macports you should consider to install the + swig-python package in addition to the swig package. Doxygen >= 1.4.0 R used by some examples in the documentation Perl, with its Gettext module (it might be called something like diff --git a/configure.ac b/configure.ac index a898e735f..30d621866 100644 --- a/configure.ac +++ b/configure.ac @@ -195,9 +195,10 @@ AC_CHECK_PROG([EMACS], [emacs], [emacs]) AC_CHECK_PROGS([IPYTHON], [ipython3 ipython], [ipython]) AC_CHECK_PROG([LBTT_TRANSLATE], [lbtt-translate], [lbtt-translate]) AX_CHECK_VALGRIND -# Debian has a binary for SWIG 3.0 named swig3.0 and they kept swig as -# an alias for swig-2.0. Let's use the former when available. -AC_CHECK_PROGS([SWIG], [swig3.0 swig], [swig]) +# Debian used to reserve the name 'swig' for swig-2.0. So prefer +# swig4.0 (available in Debian bullseye) to swig3.0 (available in Debian buster) +# ti swig. +AC_CHECK_PROGS([SWIG], [swig4.0 swig3.0 swig], [swig]) AC_SUBST([CROSS_COMPILING], [$cross_compiling]) From a3769dfd81c8454fec3e7c49bf9f996b33740338 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Tue, 9 Jun 2020 00:32:48 +0200 Subject: [PATCH 23/30] address a new g++-10 warnings * spot/twa/twa.hh (set_named_prop): Declare the lambda as noexcept. * spot/twaalgos/couvreurnew.cc (acss_states): Likewise. --- spot/twa/twa.hh | 3 ++- spot/twaalgos/couvreurnew.cc | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/spot/twa/twa.hh b/spot/twa/twa.hh index 7a5fa2897..426d44b31 100644 --- a/spot/twa/twa.hh +++ b/spot/twa/twa.hh @@ -1120,7 +1120,8 @@ namespace spot template void set_named_prop(std::string s, T* val) { - set_named_prop(s, val, [](void *p) { delete static_cast(p); }); + set_named_prop(s, val, + [](void *p) noexcept { delete static_cast(p); }); } /// \brief Erase a named property diff --git a/spot/twaalgos/couvreurnew.cc b/spot/twaalgos/couvreurnew.cc index 1414060ef..ee6130226 100644 --- a/spot/twaalgos/couvreurnew.cc +++ b/spot/twaalgos/couvreurnew.cc @@ -360,7 +360,7 @@ namespace spot { int scc_root = ecs_->root.top().index; return T::h_count(ecs_->h, - [scc_root](int s) { return s >= scc_root; }); + [scc_root](int s) noexcept { return s >= scc_root; }); } twa_run_ptr From 9caba8bfe8e509e414ae310ab95741ea1379b9ed Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Thu, 18 Jun 2020 15:32:54 +0200 Subject: [PATCH 24/30] genem: replace one recursive call by a loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * spot/twaalgos/genem.cc: In the spot29 implementation for the generic case, when Fin(fo)=true and Fin(fo)=false have to be tested separately, the second test can be done by a loop instead of a recursion, to avoid unnecessary processing of the acceptance condition. Suggested by Jan Strejček. --- spot/twaalgos/genem.cc | 73 ++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/spot/twaalgos/genem.cc b/spot/twaalgos/genem.cc index 80d096533..72d3dddda 100644 --- a/spot/twaalgos/genem.cc +++ b/spot/twaalgos/genem.cc @@ -84,40 +84,35 @@ namespace spot acc_cond acc = autacc.restrict_to(sets); acc = acc.remove(si.common_sets_of(scc), false); - auto generic_recurse = - [&] (const acc_cond& subacc) - { - int fo = (SPOT_UNLIKELY(genem_version == spot28) - ? acc.fin_one() : subacc.fin_one()); - assert(fo >= 0); - // Try to accept when Fin(fo) == true - acc_cond::mark_t fo_m = {(unsigned) fo}; - if (!scc_split_check - (si, scc, subacc.remove(fo_m, true), run, fo_m)) - return false; - // Try to accept when Fin(fo) == false - if (!is_scc_empty(si, scc, subacc.force_inf(fo_m), run, tocut)) - return false; - return true; - }; - if (SPOT_LIKELY(genem_version == spot29)) - { - acc_cond::acc_code rest = acc_cond::acc_code::f(); - for (const acc_cond& disjunct: acc.top_disjuncts()) - if (acc_cond::mark_t fu = disjunct.fin_unit()) - { - if (!scc_split_check - (si, scc, disjunct.remove(fu, true), run, fu)) - return false; - } - else - { - rest |= disjunct.get_acceptance(); - } - if (!rest.is_f() && !generic_recurse(acc_cond(acc.num_sets(), rest))) - return false; - } + do + { + acc_cond::acc_code rest = acc_cond::acc_code::f(); + for (const acc_cond& disjunct: acc.top_disjuncts()) + if (acc_cond::mark_t fu = disjunct.fin_unit()) + { + if (!scc_split_check + (si, scc, disjunct.remove(fu, true), run, fu)) + return false; + } + else + { + rest |= disjunct.get_acceptance(); + } + if (rest.is_f()) + break; + acc_cond subacc(acc.num_sets(), std::move(rest)); + int fo = subacc.fin_one(); + assert(fo >= 0); + // Try to accept when Fin(fo) == true + acc_cond::mark_t fo_m = {(unsigned) fo}; + if (!scc_split_check + (si, scc, subacc.remove(fo_m, true), run, fo_m)) + return false; + // Try to accept when Fin(fo) == false + acc = subacc.force_inf(fo_m); + } + while (!acc.is_f()); else { for (const acc_cond& disjunct: acc.top_disjuncts()) @@ -129,7 +124,17 @@ namespace spot } else { - if (!generic_recurse(disjunct)) + int fo = (SPOT_UNLIKELY(genem_version == spot28) + ? acc.fin_one() : disjunct.fin_one()); + assert(fo >= 0); + // Try to accept when Fin(fo) == true + acc_cond::mark_t fo_m = {(unsigned) fo}; + if (!scc_split_check + (si, scc, disjunct.remove(fo_m, true), run, fo_m)) + return false; + // Try to accept when Fin(fo) == false + if (!is_scc_empty(si, scc, disjunct.force_inf(fo_m), + run, tocut)) return false; } } From f2403c91dcebf4d8c43cb0faaf07a9eeea9a5f10 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Fri, 10 Jul 2020 18:05:18 +0200 Subject: [PATCH 25/30] run: fix reduce on automata with Fin Reported by Florian Renkin. * spot/twaalgos/emptiness.cc (reduce): If the automaton uses Fin acceptance, check the reduced cycle and revert to the original cycle if necessary. * tests/python/intrun.py: New file. * tests/Makefile.am: Add it. * spot/twaalgos/emptiness.hh: Improve documentation. --- NEWS | 5 +++++ spot/twaalgos/emptiness.cc | 37 +++++++++++++++++++++++++++++-------- spot/twaalgos/emptiness.hh | 8 +++++++- tests/Makefile.am | 1 + tests/python/intrun.py | 38 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 80 insertions(+), 9 deletions(-) create mode 100644 tests/python/intrun.py diff --git a/NEWS b/NEWS index eb833532f..7d8adbe84 100644 --- a/NEWS +++ b/NEWS @@ -61,6 +61,11 @@ New in spot 2.9.0.dev (not yet released) - Improve ltldo diagnostics to fix spurious test-suite failure on systems with antique GNU libc. + - twa_run::reduce() could reduce accepting runs incorrectly on + automata using Fin in their acceptance condition. This caused + issues in intersecting_run(), exclusive_run(), + intersecting_word(), exclusive_word(), which all call reduce(). + New in spot 2.9 (2020-04-30) Command-line tools: diff --git a/spot/twaalgos/emptiness.cc b/spot/twaalgos/emptiness.cc index d07fd938f..5ca65224d 100644 --- a/spot/twaalgos/emptiness.cc +++ b/spot/twaalgos/emptiness.cc @@ -304,11 +304,7 @@ namespace spot { state_set::const_iterator i = seen.begin(); while (i != seen.end()) - { - const state* ptr = *i; - ++i; - ptr->destroy(); - } + (*i++)->destroy(); } void @@ -353,17 +349,19 @@ namespace spot { ensure_non_empty_cycle("twa_run::reduce()"); auto& a = aut; + auto& acc = a->acc(); auto res = std::make_shared(a); state_set ss; shortest_path shpath(a); shpath.set_target(&ss); // We want to find a short segment of the original cycle that - // contains all acceptance conditions. + // satisfies the acceptance condition. const state* segment_start; // The initial state of the segment. const state* segment_next; // The state immediately after the segment. + // Start from the end of the original cycle, and rewind until all // acceptance sets have been seen. acc_cond::mark_t seen_acc = {}; @@ -374,7 +372,7 @@ namespace spot --seg; seen_acc |= seg->acc; } - while (!a->acc().accepting(seen_acc)); + while (!acc.accepting(seen_acc)); segment_start = seg->s; // Now go forward and ends the segment as soon as we have seen all @@ -390,7 +388,7 @@ namespace spot ++seg; } - while (!a->acc().accepting(seen_acc)); + while (!acc.accepting(seen_acc)); segment_next = seg == cycle.end() ? cycle.front().s : seg->s; // Close this cycle if needed, that is, compute a cycle going @@ -402,6 +400,29 @@ namespace spot ss.clear(); assert(s->compare(segment_start) == 0); (void)s; + + // If the acceptance condition uses Fin, it's possible (and + // even quite likely) that the cycle we have constructed this + // way is now rejecting, because the closing steps might add + // unwanted colors. If that is the case, throw the reduced + // cycle away and simply preserve the original one verbatim. + if (acc.uses_fin_acceptance()) + { + acc_cond::mark_t seen = {}; + for (auto& st: res->cycle) + seen |= st.acc; + if (!acc.accepting(seen)) + { + for (auto& st: res->cycle) + st.s->destroy(); + res->cycle.clear(); + for (auto& st: cycle) + { + twa_run::step st2 = { st.s->clone(), st.label, st.acc }; + res->cycle.emplace_back(st2); + } + } + } } // Compute the prefix: it's the shortest path from the initial diff --git a/spot/twaalgos/emptiness.hh b/spot/twaalgos/emptiness.hh index 0ddda3f6d..78eb88477 100644 --- a/spot/twaalgos/emptiness.hh +++ b/spot/twaalgos/emptiness.hh @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2011, 2013, 2014, 2015, 2016, 2017, 2018 Laboratoire de +// Copyright (C) 2011, 2013-2018, 2020 Laboratoire de // Recherche et Developpement de l'Epita (LRDE). // Copyright (C) 2004, 2005 Laboratoire d'Informatique de Paris 6 (LIP6), // département Systèmes Répartis Coopératifs (SRC), Université Pierre @@ -413,6 +413,12 @@ namespace spot /// /// Return a run which is still accepting for aut, /// but is no longer than this one. + /// + /// This is done by trying to find a fragment of the accepting + /// single that is accepting, and trying to close a cycle around + /// this fragment with fewer edges than in the original cycle. + /// (This step works best in Fin-less automata.) And then trying + /// to find a shorter prefix leading to any state of the cycle. twa_run_ptr reduce() const; /// \brief Project an accepting run diff --git a/tests/Makefile.am b/tests/Makefile.am index b39a54be8..77b8f8ece 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -383,6 +383,7 @@ TESTS_python = \ python/genem.py \ python/implies.py \ python/interdep.py \ + python/intrun.py \ python/kripke.py \ python/ltl2tgba.test \ python/ltlf.py \ diff --git a/tests/python/intrun.py b/tests/python/intrun.py new file mode 100644 index 000000000..c86c6d643 --- /dev/null +++ b/tests/python/intrun.py @@ -0,0 +1,38 @@ +# -*- mode: python; coding: utf-8 -*- +# Copyright (C) 2020 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 . + +import spot + +# This issue was reported by Florian Renkin. The reduce() call used in +# intersecting_run() was bogus, and could incorrectly reduce a word +# intersecting the product into a word not intersecting the product if the +# acceptance condition uses some Fin. +a, b = spot.automata("""HOA: v1 States: 5 Start: 0 AP: 2 "p0" "p1" acc-name: +Rabin 2 Acceptance: 4 (Fin(0) & Inf(1)) | (Fin(2) & Inf(3)) properties: +trans-labels explicit-labels trans-acc complete properties: deterministic +--BODY-- State: 0 [t] 3 State: 1 [t] 4 {1} State: 2 [0] 2 {1} [!0] 1 {0} State: +3 [t] 1 {1} State: 4 [!0&1] 4 {3} [!0&!1] 3 [0] 2 {0} --END-- HOA: v1 States: 5 +Start: 0 AP: 2 "p0" "p1" Acceptance: 3 Inf(2) | (Fin(0) & Inf(1)) properties: +trans-labels explicit-labels trans-acc complete properties: deterministic +--BODY-- State: 0 [t] 3 State: 1 [t] 4 {1 2} State: 2 [0] 2 {1 2} [!0] 1 {0 2} +State: 3 [t] 1 {1 2} State: 4 [!0&1] 4 {2} [!0&!1] 3 {2} [0] 2 {0 2} --END--""") +r = b.intersecting_run(spot.complement(a)); +c = spot.twa_word(r).as_automaton() +assert c.intersects(b) +assert not c.intersects(a) From 1fa048fe8a8b65d05460b93a1fe4064983fe5ad1 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Mon, 13 Jul 2020 17:59:55 +0200 Subject: [PATCH 26/30] ltlcross: diagnose complementations requiring too many colors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #411 reported by Frantiček Blahoudek. * bin/ltlcross.cc: Catch the issue. * tests/core/ltlcross6.test: New file. * tests/Makefile.am: Add it. * NEWS: Mention it. --- NEWS | 5 + bin/ltlcross.cc | 50 +++--- tests/Makefile.am | 1 + tests/core/ltlcross6.test | 314 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 351 insertions(+), 19 deletions(-) create mode 100755 tests/core/ltlcross6.test diff --git a/NEWS b/NEWS index 7d8adbe84..d04256d35 100644 --- a/NEWS +++ b/NEWS @@ -66,6 +66,11 @@ New in spot 2.9.0.dev (not yet released) issues in intersecting_run(), exclusive_run(), intersecting_word(), exclusive_word(), which all call reduce(). + - ltlcross used to crash with "Too many acceptance sets used. The + limit is 32." when complementing an automaton would require more + acceptance sets than supported by Spot. This is now diagnosed + with --verbose, but does not prevent ltlcross from continuing. + New in spot 2.9 (2020-04-30) Command-line tools: diff --git a/bin/ltlcross.cc b/bin/ltlcross.cc index a7f9fa1da..fd8deb228 100644 --- a/bin/ltlcross.cc +++ b/bin/ltlcross.cc @@ -1336,25 +1336,37 @@ namespace && !spot::is_universal(from[i])) missing_complement = true; else - to[i] = spot::complement(from[i], aborter); - if (verbose) - { - if (to[i]) - { - std::cerr << "\t("; - printsize(from[i]); - std::cerr << ") -> ("; - printsize(to[i]); - std::cerr << ")\tComp(" << prefix << i << ")\n"; - } - else - { - std::cerr << "\tnot complemented"; - if (aborter) - aborter->print_reason(std::cerr << " (") << ')'; - std::cerr << '\n'; - } - } + try + { + to[i] = spot::complement(from[i], aborter); + if (verbose) + { + if (to[i]) + { + std::cerr << "\t("; + printsize(from[i]); + std::cerr << ") -> ("; + printsize(to[i]); + std::cerr << ")\tComp(" << prefix + << i << ")\n"; + } + else + { + std::cerr << "\tnot complemented"; + if (aborter) + aborter->print_reason(std::cerr + << " (") << ')'; + std::cerr << '\n'; + } + } + } + catch (const std::runtime_error& re) + { + missing_complement = true; + if (verbose) + std::cerr << "\tnot complemented (" + << re.what() << ")\n"; + } } }; missing_complement = false; diff --git a/tests/Makefile.am b/tests/Makefile.am index 77b8f8ece..95ac98c1e 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -310,6 +310,7 @@ TESTS_twa = \ core/ltlcross.test \ core/spotlbtt2.test \ core/ltlcross2.test \ + core/ltlcross6.test \ core/autcross.test \ core/autcross2.test \ core/autcross3.test \ diff --git a/tests/core/ltlcross6.test b/tests/core/ltlcross6.test new file mode 100755 index 000000000..4b0a4b188 --- /dev/null +++ b/tests/core/ltlcross6.test @@ -0,0 +1,314 @@ +#!/bin/sh +# -*- coding: utf-8 -*- +# Copyright (C) 2020 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 . + +. ./defs +set -e + +cat >fake <<\EOF +#!/bin/sh +cat <<\FOO +HOA: v1 States: 137 Start: 0 AP: 4 "a" "b" "c" "d" acc-name: Buchi +Acceptance: 1 Inf(0) properties: trans-labels explicit-labels state-acc +--BODY-- State: 0 [!0&!1&!2&!3] 0 [!0&!1&!2&!3] 1 [!0&!1&!2&!3] 2 +[0&!1&!2&!3] 0 [0&!1&!2&!3] 3 [0&!1&!2&!3] 4 [0&!1&!2&!3] 5 [0&!1&!2&!3] 6 +[0&!1&!2&!3] 7 [0&!1&!2&!3] 8 [0&!1&!2&!3] 9 [!0&1&!2&!3] 0 [!0&1&!2&!3] +10 [!0&1&!2&!3] 11 [!0&1&!2&!3] 12 [0&1&!2&!3] 0 [0&1&!2&!3] 13 +[0&1&!2&!3] 14 [0&1&!2&!3] 15 [0&1&!2&!3] 16 [0&1&!2&!3] 17 [0&1&!2&!3] 18 +[0&1&!2&!3] 19 [!0&!1&2&!3] 0 [!0&!1&2&!3] 20 [!0&!1&2&!3] 21 [0&!1&2&!3] +0 [0&!1&2&!3] 22 [0&!1&2&!3] 23 [0&!1&2&!3] 24 [0&!1&2&!3] 25 [0&!1&2&!3] +26 [0&!1&2&!3] 27 [!0&1&2&!3] 0 [!0&1&2&!3] 28 [!0&1&2&!3] 29 [!0&1&2&!3] +30 [0&1&2&!3] 0 [0&1&2&!3] 31 [0&1&2&!3] 32 [0&1&2&!3] 33 [0&1&2&!3] 34 +[0&1&2&!3] 35 [0&1&2&!3] 36 [0&1&2&!3] 37 [!0&!1&!2&3] 0 [!0&!1&!2&3] 38 +[!0&!1&!2&3] 39 [!0&!1&!2&3] 40 [0&!1&!2&3] 0 [0&!1&!2&3] 41 [0&!1&!2&3] +42 [0&!1&!2&3] 43 [0&!1&!2&3] 44 [0&!1&!2&3] 45 [0&!1&!2&3] 46 [0&!1&!2&3] +47 [0&!1&!2&3] 48 [0&!1&!2&3] 49 [!0&1&!2&3] 0 [!0&1&!2&3] 50 [!0&1&!2&3] +51 [0&1&!2&3] 0 [0&1&!2&3] 52 [0&1&!2&3] 53 [0&1&!2&3] 54 [0&1&!2&3] 55 +[0&1&!2&3] 56 [0&1&!2&3] 57 [0&1&!2&3] 58 [0&1&!2&3] 59 [0&1&!2&3] 60 +[0&1&!2&3] 61 [!0&!1&2&3] 0 [!0&!1&2&3] 62 [!0&!1&2&3] 63 [!0&!1&2&3] +64 [0&!1&2&3] 0 [0&!1&2&3] 65 [0&!1&2&3] 66 [0&!1&2&3] 67 [0&!1&2&3] +68 [0&!1&2&3] 69 [0&!1&2&3] 70 [0&!1&2&3] 71 [0&!1&2&3] 72 [0&!1&2&3] +73 [!0&1&2&3] 0 [!0&1&2&3] 74 [!0&1&2&3] 75 [0&1&2&3] 0 [0&1&2&3] 76 +[0&1&2&3] 77 [0&1&2&3] 78 [0&1&2&3] 79 [0&1&2&3] 80 [0&1&2&3] 81 [0&1&2&3] +82 [0&1&2&3] 83 State: 1 [!0&!1&!2&3] 1 [0&!1&!2&3] 1 [!0&!1&2&3] 20 +[0&!1&2&3] 20 State: 2 [!0&!1&!2&3] 2 [0&!1&!2&3] 2 [!0&!1&2&3] 21 +[0&!1&2&3] 21 State: 3 [0&!1&!2&!3] 3 [0&!1&!2&!3] 4 [0&1&!2&!3] 3 +[0&1&!2&!3] 4 [0&!1&2&!3] 3 [0&!1&2&!3] 4 [0&1&2&!3] 3 [0&1&2&!3] 4 +[0&!1&!2&3] 3 [0&!1&!2&3] 4 [0&1&!2&3] 3 [0&1&!2&3] 4 [0&!1&2&3] 84 +[0&1&2&3] 3 [0&1&2&3] 4 State: 4 {0} [0&!1&!2&!3] 3 [0&1&!2&!3] 13 +[0&!1&2&!3] 22 [0&1&2&!3] 31 [0&!1&!2&3] 41 [0&1&!2&3] 52 [0&!1&2&3] +65 [0&1&2&3] 76 State: 5 [!0&!1&!2&3] 1 [0&!1&!2&3] 5 [!0&!1&2&3] +20 [0&!1&2&3] 23 State: 6 [!0&!1&!2&3] 2 [0&!1&!2&3] 6 [!0&!1&2&3] +21 [0&!1&2&3] 24 State: 7 [0&!1&!2&!3] 7 [0&1&!2&!3] 7 [0&!1&2&!3] 7 +[0&1&2&!3] 7 [0&!1&!2&3] 7 [0&1&!2&3] 7 [0&!1&2&3] 25 [0&1&2&3] 7 State: +8 [0&!1&!2&!3] 8 [0&1&!2&!3] 8 [0&!1&2&!3] 8 [0&1&2&!3] 8 [0&!1&!2&3] 8 +[0&1&!2&3] 8 [0&!1&2&3] 85 [0&!1&2&3] 86 [0&1&2&3] 8 State: 9 [0&!1&!2&!3] +9 [0&1&!2&!3] 9 [0&!1&2&!3] 9 [0&1&2&!3] 9 [0&!1&!2&3] 9 [0&1&!2&3] +9 [0&!1&2&3] 27 [0&1&2&3] 9 State: 10 [!0&!1&!2&!3] 1 [0&!1&!2&!3] 1 +[!0&1&!2&!3] 10 [!0&1&!2&!3] 11 [0&1&!2&!3] 10 [0&1&!2&!3] 11 [!0&!1&2&!3] +20 [0&!1&2&!3] 20 [!0&1&2&!3] 28 [0&1&2&!3] 28 [!0&1&!2&3] 10 [!0&1&!2&3] +11 [0&1&!2&3] 10 [0&1&!2&3] 11 [!0&1&2&3] 28 [0&1&2&3] 28 State: 11 {0} +[!0&!1&!2&!3] 1 [0&!1&!2&!3] 5 [!0&1&!2&!3] 10 [0&1&!2&!3] 14 [!0&!1&2&!3] +20 [0&!1&2&!3] 23 [!0&1&2&!3] 28 [0&1&2&!3] 32 State: 12 [!0&!1&!2&!3] 2 +[0&!1&!2&!3] 2 [!0&1&!2&!3] 12 [0&1&!2&!3] 12 [!0&!1&2&!3] 21 [0&!1&2&!3] +21 [!0&1&2&!3] 29 [!0&1&2&!3] 30 [0&1&2&!3] 29 [0&1&2&!3] 30 [!0&1&!2&3] +12 [0&1&!2&3] 12 [!0&1&2&3] 29 [!0&1&2&3] 30 [0&1&2&3] 29 [0&1&2&3] +30 State: 13 [0&!1&!2&!3] 3 [0&!1&!2&!3] 4 [0&1&!2&!3] 13 [0&!1&2&!3] +22 [0&1&2&!3] 31 [0&!1&!2&3] 3 [0&!1&!2&3] 4 [0&1&!2&3] 13 [0&!1&2&3] +22 [0&1&2&3] 31 State: 14 [!0&!1&!2&!3] 1 [0&!1&!2&!3] 5 [!0&1&!2&!3] 10 +[!0&1&!2&!3] 11 [0&1&!2&!3] 14 [!0&!1&2&!3] 20 [0&!1&2&!3] 23 [!0&1&2&!3] +28 [0&1&2&!3] 32 [!0&1&!2&3] 10 [!0&1&!2&3] 11 [0&1&!2&3] 14 [!0&1&2&3] +28 [0&1&2&3] 32 State: 15 [!0&!1&!2&!3] 2 [0&!1&!2&!3] 6 [!0&1&!2&!3] 12 +[0&1&!2&!3] 15 [!0&!1&2&!3] 21 [0&!1&2&!3] 24 [!0&1&2&!3] 29 [!0&1&2&!3] +30 [0&1&2&!3] 33 [!0&1&!2&3] 12 [0&1&!2&3] 15 [!0&1&2&3] 29 [!0&1&2&3] +30 [0&1&2&3] 33 State: 16 [0&!1&!2&!3] 7 [0&1&!2&!3] 16 [0&1&!2&!3] 17 +[0&!1&2&!3] 25 [0&1&2&!3] 34 [0&!1&!2&3] 7 [0&1&!2&3] 16 [0&1&!2&3] 17 +[0&!1&2&3] 7 [0&1&2&3] 34 State: 17 {0} [0&!1&!2&!3] 7 [0&1&!2&!3] 16 +[0&!1&2&!3] 25 [0&1&2&!3] 34 [0&!1&!2&3] 45 [0&1&!2&3] 54 [0&!1&2&3] +68 [0&1&2&3] 77 State: 18 [0&!1&!2&!3] 8 [0&1&!2&!3] 18 [0&!1&2&!3] +26 [0&1&2&!3] 35 [0&!1&!2&3] 8 [0&1&!2&3] 18 [0&!1&2&3] 26 [0&1&2&3] +35 State: 19 [0&!1&!2&!3] 9 [0&1&!2&!3] 19 [0&!1&2&!3] 27 [0&1&2&!3] +36 [0&1&2&!3] 37 [0&!1&!2&3] 9 [0&1&!2&3] 19 [0&!1&2&3] 9 [0&1&2&3] +36 [0&1&2&3] 37 State: 20 [!0&!1&!2&3] 1 [0&!1&!2&3] 1 [!0&1&!2&3] 10 +[!0&1&!2&3] 11 [0&1&!2&3] 10 [0&1&!2&3] 11 [!0&!1&2&3] 20 [0&!1&2&3] +20 [!0&1&2&3] 28 [0&1&2&3] 28 State: 21 [!0&!1&!2&3] 2 [0&!1&!2&3] 2 +[!0&1&!2&3] 12 [0&1&!2&3] 12 [!0&!1&2&3] 21 [0&!1&2&3] 21 [!0&1&2&3] +29 [!0&1&2&3] 30 [0&1&2&3] 29 [0&1&2&3] 30 State: 22 [0&!1&!2&!3] 3 +[0&!1&!2&!3] 4 [0&1&!2&!3] 3 [0&1&!2&!3] 4 [0&!1&2&!3] 3 [0&!1&2&!3] +4 [0&1&2&!3] 3 [0&1&2&!3] 4 [0&!1&!2&3] 3 [0&!1&!2&3] 4 [0&1&!2&3] +13 [0&!1&2&3] 84 [0&1&2&3] 31 State: 23 [!0&!1&!2&3] 1 [0&!1&!2&3] 5 +[!0&1&!2&3] 10 [!0&1&!2&3] 11 [0&1&!2&3] 14 [!0&!1&2&3] 20 [0&!1&2&3] +23 [!0&1&2&3] 28 [0&1&2&3] 32 State: 24 [!0&!1&!2&3] 2 [0&!1&!2&3] 6 +[!0&1&!2&3] 12 [0&1&!2&3] 15 [!0&!1&2&3] 21 [0&!1&2&3] 24 [!0&1&2&3] +29 [!0&1&2&3] 30 [0&1&2&3] 33 State: 25 [0&!1&!2&!3] 7 [0&1&!2&!3] +7 [0&!1&2&!3] 7 [0&1&2&!3] 7 [0&!1&!2&3] 7 [0&1&!2&3] 16 [0&1&!2&3] +17 [0&!1&2&3] 25 [0&1&2&3] 34 State: 26 [0&!1&!2&!3] 8 [0&1&!2&!3] +8 [0&!1&2&!3] 8 [0&1&2&!3] 8 [0&!1&!2&3] 8 [0&1&!2&3] 18 [0&!1&2&3] +85 [0&!1&2&3] 86 [0&1&2&3] 35 State: 27 [0&!1&!2&!3] 9 [0&1&!2&!3] +9 [0&!1&2&!3] 9 [0&1&2&!3] 9 [0&!1&!2&3] 9 [0&1&!2&3] 19 [0&!1&2&3] +27 [0&1&2&3] 36 [0&1&2&3] 37 State: 28 [!0&!1&!2&!3] 1 [0&!1&!2&!3] 1 +[!0&1&!2&!3] 10 [!0&1&!2&!3] 11 [0&1&!2&!3] 10 [0&1&!2&!3] 11 [!0&!1&2&!3] +20 [0&!1&2&!3] 20 [!0&1&2&!3] 28 [0&1&2&!3] 28 State: 29 [!0&!1&!2&!3] 2 +[0&!1&!2&!3] 2 [!0&1&!2&!3] 12 [0&1&!2&!3] 12 [!0&!1&2&!3] 21 [0&!1&2&!3] +21 [!0&1&2&!3] 29 [!0&1&2&!3] 30 [0&1&2&!3] 29 [0&1&2&!3] 30 State: +30 {0} [!0&!1&!2&!3] 2 [0&!1&!2&!3] 6 [!0&1&!2&!3] 12 [0&1&!2&!3] 15 +[!0&!1&2&!3] 21 [0&!1&2&!3] 24 [!0&1&2&!3] 29 [0&1&2&!3] 33 State: 31 +[0&!1&!2&!3] 3 [0&!1&!2&!3] 4 [0&1&!2&!3] 13 [0&!1&2&!3] 22 [0&1&2&!3] +31 [0&!1&!2&3] 3 [0&!1&!2&3] 4 [0&1&!2&3] 3 [0&1&!2&3] 4 [0&!1&2&3] +22 [0&1&2&3] 3 [0&1&2&3] 4 State: 32 [!0&!1&!2&!3] 1 [0&!1&!2&!3] 5 +[!0&1&!2&!3] 10 [!0&1&!2&!3] 11 [0&1&!2&!3] 14 [!0&!1&2&!3] 20 [0&!1&2&!3] +23 [!0&1&2&!3] 28 [0&1&2&!3] 32 State: 33 [!0&!1&!2&!3] 2 [0&!1&!2&!3] 6 +[!0&1&!2&!3] 12 [0&1&!2&!3] 15 [!0&!1&2&!3] 21 [0&!1&2&!3] 24 [!0&1&2&!3] +29 [!0&1&2&!3] 30 [0&1&2&!3] 33 State: 34 [0&!1&!2&!3] 7 [0&1&!2&!3] 16 +[0&1&!2&!3] 17 [0&!1&2&!3] 25 [0&1&2&!3] 34 [0&!1&!2&3] 7 [0&1&!2&3] +7 [0&!1&2&3] 7 [0&1&2&3] 7 State: 35 [0&!1&!2&!3] 8 [0&1&!2&!3] 18 +[0&!1&2&!3] 26 [0&1&2&!3] 35 [0&!1&!2&3] 8 [0&1&!2&3] 8 [0&!1&2&3] 26 +[0&1&2&3] 8 State: 36 [0&!1&!2&!3] 9 [0&1&!2&!3] 19 [0&!1&2&!3] 27 +[0&1&2&!3] 36 [0&1&2&!3] 37 [0&!1&!2&3] 9 [0&1&!2&3] 9 [0&!1&2&3] 9 +[0&1&2&3] 9 State: 37 {0} [0&!1&!2&!3] 9 [0&1&!2&!3] 19 [0&!1&2&!3] 27 +[0&1&2&!3] 36 [0&!1&!2&3] 48 [0&1&!2&3] 59 [0&!1&2&3] 72 [0&1&2&3] 81 +State: 38 [!0&!1&!2&3] 38 [!0&!1&!2&3] 39 [0&!1&!2&3] 38 [0&!1&!2&3] 39 +[!0&!1&2&3] 62 [0&!1&2&3] 62 State: 39 {0} [!0&!1&!2&3] 38 [0&!1&!2&3] +42 [!0&!1&2&3] 62 [0&!1&2&3] 66 State: 40 [!0&!1&!2&3] 40 [0&!1&!2&3] +40 [!0&!1&2&3] 63 [!0&!1&2&3] 64 [0&!1&2&3] 63 [0&!1&2&3] 64 State: 41 +[0&!1&!2&!3] 3 [0&!1&!2&!3] 4 [0&1&!2&!3] 3 [0&1&!2&!3] 4 [0&!1&2&!3] +3 [0&!1&2&!3] 4 [0&1&2&!3] 3 [0&1&2&!3] 4 [0&!1&!2&3] 41 [0&1&!2&3] 3 +[0&1&!2&3] 4 [0&!1&2&3] 65 [0&1&2&3] 3 [0&1&2&3] 4 State: 42 [!0&!1&!2&3] +38 [!0&!1&!2&3] 39 [0&!1&!2&3] 42 [!0&!1&2&3] 62 [0&!1&2&3] 66 State: 43 +[0&!1&!2&3] 43 [0&!1&!2&3] 44 [0&!1&2&3] 67 State: 44 {0} [0&!1&!2&3] +43 [0&!1&2&3] 67 State: 45 [0&!1&!2&!3] 7 [0&1&!2&!3] 7 [0&!1&2&!3] +7 [0&1&2&!3] 7 [0&!1&!2&3] 45 [0&1&!2&3] 7 [0&!1&2&3] 87 [0&1&2&3] +7 State: 46 [!0&!1&!2&3] 40 [0&!1&!2&3] 46 [!0&!1&2&3] 63 [!0&!1&2&3] +64 [0&!1&2&3] 69 State: 47 [0&!1&!2&!3] 8 [0&1&!2&!3] 8 [0&!1&2&!3] 8 +[0&1&2&!3] 8 [0&!1&!2&3] 47 [0&1&!2&3] 8 [0&!1&2&3] 70 [0&1&2&3] 8 State: +48 [0&!1&!2&!3] 9 [0&1&!2&!3] 9 [0&!1&2&!3] 9 [0&1&2&!3] 9 [0&!1&!2&3] +48 [0&1&!2&3] 9 [0&!1&2&3] 88 [0&1&2&3] 9 State: 49 [0&!1&!2&3] 49 +[0&!1&2&3] 71 [0&!1&2&3] 73 State: 50 [!0&!1&!2&!3] 89 [0&!1&!2&!3] +89 [!0&1&!2&!3] 50 [0&1&!2&!3] 50 [!0&!1&2&!3] 90 [!0&!1&2&!3] 91 +[0&!1&2&!3] 90 [0&!1&2&!3] 91 [!0&1&2&!3] 74 [0&1&2&!3] 74 [!0&1&!2&3] +50 [0&1&!2&3] 50 [!0&1&2&3] 74 [0&1&2&3] 74 State: 51 [!0&!1&!2&!3] 92 +[0&!1&!2&!3] 92 [!0&1&!2&!3] 94 [!0&1&!2&!3] 95 [0&1&!2&!3] 94 [0&1&!2&!3] +95 [!0&!1&2&!3] 93 [0&!1&2&!3] 93 [!0&1&2&!3] 75 [0&1&2&!3] 75 [!0&1&!2&3] +51 [0&1&!2&3] 51 [!0&1&2&3] 75 [0&1&2&3] 75 State: 52 [0&!1&!2&!3] 41 +[0&1&!2&!3] 52 [0&!1&2&!3] 96 [0&1&2&!3] 76 [0&!1&!2&3] 3 [0&!1&!2&3] +4 [0&1&!2&3] 52 [0&!1&2&3] 22 [0&1&2&3] 76 State: 53 [0&!1&!2&!3] 97 +[0&1&!2&!3] 99 [0&1&!2&!3] 100 [0&!1&2&!3] 98 [0&1&2&!3] 82 [0&1&!2&3] +53 [0&1&2&3] 82 State: 54 [0&!1&!2&!3] 45 [0&1&!2&!3] 54 [0&!1&2&!3] +87 [0&1&2&!3] 77 [0&!1&!2&3] 7 [0&1&!2&3] 54 [0&!1&2&3] 7 [0&1&2&3] 77 +State: 55 [!0&!1&!2&!3] 89 [0&!1&!2&!3] 101 [!0&1&!2&!3] 50 [0&1&!2&!3] +55 [!0&!1&2&!3] 90 [!0&!1&2&!3] 91 [0&!1&2&!3] 102 [!0&1&2&!3] 74 +[0&1&2&!3] 78 [!0&1&!2&3] 50 [0&1&!2&3] 55 [!0&1&2&3] 74 [0&1&2&3] 78 +State: 56 [!0&!1&!2&!3] 92 [0&!1&!2&!3] 103 [!0&1&!2&!3] 94 [!0&1&!2&!3] +95 [0&1&!2&!3] 104 [!0&!1&2&!3] 93 [0&!1&2&!3] 105 [!0&1&2&!3] 75 +[0&1&2&!3] 79 [!0&1&!2&3] 51 [0&1&!2&3] 56 [!0&1&2&3] 75 [0&1&2&3] 79 +State: 57 [0&!1&!2&!3] 106 [0&1&!2&!3] 57 [0&!1&2&!3] 107 [0&!1&2&!3] +108 [0&1&2&!3] 83 [0&1&!2&3] 57 [0&1&2&3] 83 State: 58 [0&!1&!2&!3] 47 +[0&1&!2&!3] 58 [0&!1&2&!3] 70 [0&1&2&!3] 80 [0&!1&!2&3] 8 [0&1&!2&3] +58 [0&!1&2&3] 8 [0&1&2&3] 80 State: 59 [0&!1&!2&!3] 48 [0&1&!2&!3] 59 +[0&!1&2&!3] 72 [0&1&2&!3] 81 [0&!1&!2&3] 9 [0&1&!2&3] 59 [0&!1&2&3] +109 [0&1&2&3] 81 State: 60 [0&1&!2&3] 60 [0&1&!2&3] 61 State: 61 {0} +[0&1&!2&3] 60 State: 62 [!0&!1&!2&3] 38 [!0&!1&!2&3] 39 [0&!1&!2&3] 38 +[0&!1&!2&3] 39 [!0&1&!2&3] 110 [0&1&!2&3] 110 [!0&!1&2&3] 62 [0&!1&2&3] +62 [!0&1&2&3] 111 [0&1&2&3] 111 State: 63 [!0&!1&!2&3] 40 [0&!1&!2&3] 40 +[!0&1&!2&3] 112 [0&1&!2&3] 112 [!0&!1&2&3] 63 [!0&!1&2&3] 64 [0&!1&2&3] +63 [0&!1&2&3] 64 [!0&1&2&3] 113 [0&1&2&3] 113 State: 64 {0} [!0&!1&!2&3] +40 [0&!1&!2&3] 46 [!0&!1&2&3] 63 [0&!1&2&3] 69 State: 65 [0&!1&!2&!3] +3 [0&!1&!2&!3] 4 [0&1&!2&!3] 3 [0&1&!2&!3] 4 [0&!1&2&!3] 3 [0&!1&2&!3] +4 [0&1&2&!3] 3 [0&1&2&!3] 4 [0&!1&!2&3] 41 [0&1&!2&3] 114 [0&!1&2&3] 65 +[0&1&2&3] 115 State: 66 [!0&!1&!2&3] 38 [!0&!1&!2&3] 39 [0&!1&!2&3] 42 +[!0&1&!2&3] 110 [0&1&!2&3] 116 [!0&!1&2&3] 62 [0&!1&2&3] 66 [!0&1&2&3] +111 [0&1&2&3] 117 State: 67 [0&!1&!2&3] 43 [0&!1&!2&3] 44 [0&1&!2&3] +118 [0&!1&2&3] 67 [0&1&2&3] 119 State: 68 [0&!1&!2&!3] 7 [0&1&!2&!3] 7 +[0&!1&2&!3] 7 [0&1&2&!3] 7 [0&!1&!2&3] 45 [0&1&!2&3] 120 [0&!1&2&3] 87 +[0&1&2&3] 121 State: 69 [!0&!1&!2&3] 40 [0&!1&!2&3] 46 [!0&1&!2&3] 112 +[0&1&!2&3] 122 [!0&!1&2&3] 63 [!0&!1&2&3] 64 [0&!1&2&3] 69 [!0&1&2&3] +113 [0&1&2&3] 123 State: 70 [0&!1&!2&!3] 8 [0&1&!2&!3] 8 [0&!1&2&!3] +8 [0&1&2&!3] 8 [0&!1&!2&3] 47 [0&1&!2&3] 58 [0&!1&2&3] 70 [0&1&2&3] +80 State: 71 {0} [0&!1&!2&3] 49 [0&!1&2&3] 73 State: 72 [0&!1&!2&!3] +9 [0&1&!2&!3] 9 [0&!1&2&!3] 9 [0&1&2&!3] 9 [0&!1&!2&3] 48 [0&1&!2&3] +59 [0&!1&2&3] 88 [0&1&2&3] 81 State: 73 [0&!1&!2&3] 49 [0&1&!2&3] 124 +[0&!1&2&3] 71 [0&!1&2&3] 73 [0&1&2&3] 125 State: 74 [!0&!1&!2&!3] +89 [0&!1&!2&!3] 89 [!0&1&!2&!3] 50 [0&1&!2&!3] 50 [!0&!1&2&!3] 90 +[!0&!1&2&!3] 91 [0&!1&2&!3] 90 [0&!1&2&!3] 91 [!0&1&2&!3] 74 [0&1&2&!3] 74 +State: 75 [!0&!1&!2&!3] 92 [0&!1&!2&!3] 92 [!0&1&!2&!3] 94 [!0&1&!2&!3] 95 +[0&1&!2&!3] 94 [0&1&!2&!3] 95 [!0&!1&2&!3] 93 [0&!1&2&!3] 93 [!0&1&2&!3] +75 [0&1&2&!3] 75 State: 76 [0&!1&!2&!3] 41 [0&1&!2&!3] 52 [0&!1&2&!3] +96 [0&1&2&!3] 76 [0&!1&!2&3] 3 [0&!1&!2&3] 4 [0&1&!2&3] 3 [0&1&!2&3] +4 [0&!1&2&3] 22 [0&1&2&3] 3 [0&1&2&3] 4 State: 77 [0&!1&!2&!3] 45 +[0&1&!2&!3] 54 [0&!1&2&!3] 87 [0&1&2&!3] 77 [0&!1&!2&3] 7 [0&1&!2&3] +7 [0&!1&2&3] 7 [0&1&2&3] 7 State: 78 [!0&!1&!2&!3] 89 [0&!1&!2&!3] 101 +[!0&1&!2&!3] 50 [0&1&!2&!3] 55 [!0&!1&2&!3] 90 [!0&!1&2&!3] 91 [0&!1&2&!3] +102 [!0&1&2&!3] 74 [0&1&2&!3] 78 State: 79 [!0&!1&!2&!3] 92 [0&!1&!2&!3] +103 [!0&1&!2&!3] 94 [!0&1&!2&!3] 95 [0&1&!2&!3] 104 [!0&!1&2&!3] 93 +[0&!1&2&!3] 105 [!0&1&2&!3] 75 [0&1&2&!3] 79 State: 80 [0&!1&!2&!3] 47 +[0&1&!2&!3] 58 [0&!1&2&!3] 70 [0&1&2&!3] 80 [0&!1&!2&3] 8 [0&1&!2&3] +8 [0&!1&2&3] 8 [0&1&2&3] 8 State: 81 [0&!1&!2&!3] 48 [0&1&!2&!3] 59 +[0&!1&2&!3] 72 [0&1&2&!3] 81 [0&!1&!2&3] 9 [0&1&!2&3] 9 [0&!1&2&3] 109 +[0&1&2&3] 9 State: 82 [0&!1&!2&!3] 97 [0&1&!2&!3] 99 [0&1&!2&!3] 100 +[0&!1&2&!3] 98 [0&1&2&!3] 82 State: 83 [0&!1&!2&!3] 106 [0&1&!2&!3] 57 +[0&!1&2&!3] 107 [0&!1&2&!3] 108 [0&1&2&!3] 83 State: 84 [0&!1&!2&!3] 3 +[0&!1&!2&!3] 4 [0&1&!2&!3] 3 [0&1&!2&!3] 4 [0&!1&2&!3] 3 [0&!1&2&!3] 4 +[0&1&2&!3] 3 [0&1&2&!3] 4 [0&!1&!2&3] 3 [0&!1&!2&3] 4 [0&1&!2&3] 127 +[0&!1&2&3] 84 [0&1&2&3] 126 State: 85 [0&!1&!2&!3] 8 [0&1&!2&!3] 8 +[0&!1&2&!3] 8 [0&1&2&!3] 8 [0&!1&!2&3] 8 [0&1&!2&3] 128 [0&!1&2&3] 85 +[0&!1&2&3] 86 [0&1&2&3] 129 State: 86 {0} [0&!1&!2&!3] 8 [0&1&!2&!3] 18 +[0&!1&2&!3] 26 [0&1&2&!3] 35 [0&!1&!2&3] 47 [0&1&!2&3] 58 [0&!1&2&3] +70 [0&1&2&3] 80 State: 87 [0&!1&!2&!3] 7 [0&1&!2&!3] 7 [0&!1&2&!3] +7 [0&1&2&!3] 7 [0&!1&!2&3] 45 [0&1&!2&3] 54 [0&!1&2&3] 87 [0&1&2&3] +77 State: 88 [0&!1&!2&!3] 9 [0&1&!2&!3] 9 [0&!1&2&!3] 9 [0&1&2&!3] 9 +[0&!1&!2&3] 48 [0&1&!2&3] 130 [0&!1&2&3] 88 [0&1&2&3] 131 State: 89 +[!0&!1&!2&3] 89 [0&!1&!2&3] 89 [!0&!1&2&3] 90 [!0&!1&2&3] 91 [0&!1&2&3] +90 [0&!1&2&3] 91 State: 90 [!0&!1&!2&3] 89 [0&!1&!2&3] 89 [!0&1&!2&3] +50 [0&1&!2&3] 50 [!0&!1&2&3] 90 [!0&!1&2&3] 91 [0&!1&2&3] 90 [0&!1&2&3] +91 [!0&1&2&3] 74 [0&1&2&3] 74 State: 91 {0} [!0&1&!2&3] 50 [0&1&!2&3] +55 [!0&1&2&3] 74 [0&1&2&3] 78 State: 92 [!0&!1&!2&3] 92 [0&!1&!2&3] 92 +[!0&!1&2&3] 93 [0&!1&2&3] 93 State: 93 [!0&!1&!2&3] 92 [0&!1&!2&3] 92 +[!0&1&!2&3] 94 [!0&1&!2&3] 95 [0&1&!2&3] 94 [0&1&!2&3] 95 [!0&!1&2&3] +93 [0&!1&2&3] 93 [!0&1&2&3] 75 [0&1&2&3] 75 State: 94 [!0&!1&!2&!3] +92 [0&!1&!2&!3] 92 [!0&1&!2&!3] 94 [!0&1&!2&!3] 95 [0&1&!2&!3] 94 +[0&1&!2&!3] 95 [!0&!1&2&!3] 93 [0&!1&2&!3] 93 [!0&1&2&!3] 75 [0&1&2&!3] +75 [!0&1&!2&3] 94 [!0&1&!2&3] 95 [0&1&!2&3] 94 [0&1&!2&3] 95 [!0&1&2&3] +75 [0&1&2&3] 75 State: 95 {0} [!0&1&!2&3] 51 [0&1&!2&3] 56 [!0&1&2&3] +75 [0&1&2&3] 79 State: 96 [0&!1&!2&!3] 3 [0&!1&!2&!3] 4 [0&1&!2&!3] +3 [0&1&!2&!3] 4 [0&!1&2&!3] 3 [0&!1&2&!3] 4 [0&1&2&!3] 3 [0&1&2&!3] +4 [0&!1&!2&3] 41 [0&1&!2&3] 52 [0&!1&2&3] 65 [0&1&2&3] 76 State: 97 +[0&!1&!2&3] 97 [0&!1&2&3] 98 State: 98 [0&!1&!2&3] 97 [0&1&!2&3] 99 +[0&1&!2&3] 100 [0&!1&2&3] 98 [0&1&2&3] 82 State: 99 [0&!1&!2&!3] 97 +[0&1&!2&!3] 99 [0&1&!2&!3] 100 [0&!1&2&!3] 98 [0&1&2&!3] 82 [0&1&!2&3] +99 [0&1&!2&3] 100 [0&1&2&3] 82 State: 100 {0} [0&1&!2&3] 53 [0&1&2&3] +82 State: 101 [!0&!1&!2&3] 89 [0&!1&!2&3] 101 [!0&!1&2&3] 90 [!0&!1&2&3] +91 [0&!1&2&3] 102 State: 102 [!0&!1&!2&3] 89 [0&!1&!2&3] 101 [!0&1&!2&3] +50 [0&1&!2&3] 55 [!0&!1&2&3] 90 [!0&!1&2&3] 91 [0&!1&2&3] 102 [!0&1&2&3] +74 [0&1&2&3] 78 State: 103 [!0&!1&!2&3] 92 [0&!1&!2&3] 103 [!0&!1&2&3] 93 +[0&!1&2&3] 105 State: 104 [!0&!1&!2&!3] 92 [0&!1&!2&!3] 103 [!0&1&!2&!3] +94 [!0&1&!2&!3] 95 [0&1&!2&!3] 104 [!0&!1&2&!3] 93 [0&!1&2&!3] 105 +[!0&1&2&!3] 75 [0&1&2&!3] 79 [!0&1&!2&3] 94 [!0&1&!2&3] 95 [0&1&!2&3] 104 +[!0&1&2&3] 75 [0&1&2&3] 79 State: 105 [!0&!1&!2&3] 92 [0&!1&!2&3] 103 +[!0&1&!2&3] 94 [!0&1&!2&3] 95 [0&1&!2&3] 104 [!0&!1&2&3] 93 [0&!1&2&3] +105 [!0&1&2&3] 75 [0&1&2&3] 79 State: 106 [0&!1&!2&3] 106 [0&!1&2&3] +107 [0&!1&2&3] 108 State: 107 [0&!1&!2&3] 106 [0&1&!2&3] 57 [0&!1&2&3] +107 [0&!1&2&3] 108 [0&1&2&3] 83 State: 108 {0} [0&1&!2&3] 57 [0&1&2&3] +83 State: 109 [0&!1&!2&!3] 9 [0&1&!2&!3] 9 [0&!1&2&!3] 9 [0&1&2&!3] 9 +[0&!1&!2&3] 9 [0&1&!2&3] 132 [0&!1&2&3] 27 [0&1&2&3] 133 State: 110 +[!0&!1&!2&!3] 38 [!0&!1&!2&!3] 39 [0&!1&!2&!3] 38 [0&!1&!2&!3] +39 [!0&1&!2&!3] 110 [0&1&!2&!3] 110 [!0&!1&2&!3] 62 [0&!1&2&!3] +62 [!0&1&2&!3] 111 [0&1&2&!3] 111 [!0&1&!2&3] 110 [0&1&!2&3] 110 +[!0&1&2&3] 111 [0&1&2&3] 111 State: 111 [!0&!1&!2&!3] 38 [!0&!1&!2&!3] +39 [0&!1&!2&!3] 38 [0&!1&!2&!3] 39 [!0&1&!2&!3] 110 [0&1&!2&!3] 110 +[!0&!1&2&!3] 62 [0&!1&2&!3] 62 [!0&1&2&!3] 111 [0&1&2&!3] 111 State: +112 [!0&!1&!2&!3] 40 [0&!1&!2&!3] 40 [!0&1&!2&!3] 112 [0&1&!2&!3] +112 [!0&!1&2&!3] 63 [!0&!1&2&!3] 64 [0&!1&2&!3] 63 [0&!1&2&!3] +64 [!0&1&2&!3] 113 [0&1&2&!3] 113 [!0&1&!2&3] 112 [0&1&!2&3] 112 +[!0&1&2&3] 113 [0&1&2&3] 113 State: 113 [!0&!1&!2&!3] 40 [0&!1&!2&!3] +40 [!0&1&!2&!3] 112 [0&1&!2&!3] 112 [!0&!1&2&!3] 63 [!0&!1&2&!3] 64 +[0&!1&2&!3] 63 [0&!1&2&!3] 64 [!0&1&2&!3] 113 [0&1&2&!3] 113 State: +114 [0&!1&!2&!3] 41 [0&1&!2&!3] 114 [0&!1&2&!3] 65 [0&1&2&!3] 115 +[0&!1&!2&3] 3 [0&!1&!2&3] 4 [0&1&!2&3] 114 [0&!1&2&3] 3 [0&!1&2&3] 4 +[0&1&2&3] 115 State: 115 [0&!1&!2&!3] 41 [0&1&!2&!3] 114 [0&!1&2&!3] +65 [0&1&2&!3] 115 [0&!1&!2&3] 3 [0&!1&!2&3] 4 [0&1&!2&3] 3 [0&1&!2&3] 4 +[0&!1&2&3] 3 [0&!1&2&3] 4 [0&1&2&3] 3 [0&1&2&3] 4 State: 116 [!0&!1&!2&!3] +38 [!0&!1&!2&!3] 39 [0&!1&!2&!3] 42 [!0&1&!2&!3] 110 [0&1&!2&!3] 116 +[!0&!1&2&!3] 62 [0&!1&2&!3] 66 [!0&1&2&!3] 111 [0&1&2&!3] 117 [!0&1&!2&3] +110 [0&1&!2&3] 116 [!0&1&2&3] 111 [0&1&2&3] 117 State: 117 [!0&!1&!2&!3] +38 [!0&!1&!2&!3] 39 [0&!1&!2&!3] 42 [!0&1&!2&!3] 110 [0&1&!2&!3] 116 +[!0&!1&2&!3] 62 [0&!1&2&!3] 66 [!0&1&2&!3] 111 [0&1&2&!3] 117 State: +118 [0&!1&!2&!3] 43 [0&!1&!2&!3] 44 [0&1&!2&!3] 118 [0&!1&2&!3] 67 +[0&1&2&!3] 119 [0&1&!2&3] 118 [0&1&2&3] 119 State: 119 [0&!1&!2&!3] 43 +[0&!1&!2&!3] 44 [0&1&!2&!3] 118 [0&!1&2&!3] 67 [0&1&2&!3] 119 State: 120 +[0&!1&!2&!3] 45 [0&1&!2&!3] 120 [0&!1&2&!3] 68 [0&1&2&!3] 121 [0&!1&!2&3] +7 [0&1&!2&3] 120 [0&!1&2&3] 134 [0&1&2&3] 121 State: 121 [0&!1&!2&!3] 45 +[0&1&!2&!3] 120 [0&!1&2&!3] 68 [0&1&2&!3] 121 [0&!1&!2&3] 7 [0&1&!2&3] +7 [0&!1&2&3] 134 [0&1&2&3] 7 State: 122 [!0&!1&!2&!3] 40 [0&!1&!2&!3] +46 [!0&1&!2&!3] 112 [0&1&!2&!3] 122 [!0&!1&2&!3] 63 [!0&!1&2&!3] 64 +[0&!1&2&!3] 69 [!0&1&2&!3] 113 [0&1&2&!3] 123 [!0&1&!2&3] 112 [0&1&!2&3] +122 [!0&1&2&3] 113 [0&1&2&3] 123 State: 123 [!0&!1&!2&!3] 40 [0&!1&!2&!3] +46 [!0&1&!2&!3] 112 [0&1&!2&!3] 122 [!0&!1&2&!3] 63 [!0&!1&2&!3] 64 +[0&!1&2&!3] 69 [!0&1&2&!3] 113 [0&1&2&!3] 123 State: 124 [0&!1&!2&!3] 49 +[0&1&!2&!3] 124 [0&!1&2&!3] 71 [0&!1&2&!3] 73 [0&1&2&!3] 125 [0&1&!2&3] +124 [0&1&2&3] 125 State: 125 [0&!1&!2&!3] 49 [0&1&!2&!3] 124 [0&!1&2&!3] +71 [0&!1&2&!3] 73 [0&1&2&!3] 125 State: 126 [0&!1&!2&!3] 3 [0&!1&!2&!3] 4 +[0&1&!2&!3] 127 [0&!1&2&!3] 84 [0&1&2&!3] 126 [0&!1&!2&3] 3 [0&!1&!2&3] 4 +[0&1&!2&3] 3 [0&1&!2&3] 4 [0&!1&2&3] 3 [0&!1&2&3] 4 [0&1&2&3] 3 [0&1&2&3] +4 State: 127 [0&!1&!2&!3] 3 [0&!1&!2&!3] 4 [0&1&!2&!3] 127 [0&!1&2&!3] +84 [0&1&2&!3] 126 [0&!1&!2&3] 3 [0&!1&!2&3] 4 [0&1&!2&3] 127 [0&!1&2&3] +3 [0&!1&2&3] 4 [0&1&2&3] 126 State: 128 [0&!1&!2&!3] 8 [0&1&!2&!3] 128 +[0&!1&2&!3] 85 [0&!1&2&!3] 86 [0&1&2&!3] 129 [0&!1&!2&3] 8 [0&1&!2&3] +128 [0&!1&2&3] 8 [0&1&2&3] 129 State: 129 [0&!1&!2&!3] 8 [0&1&!2&!3] 128 +[0&!1&2&!3] 85 [0&!1&2&!3] 86 [0&1&2&!3] 129 [0&!1&!2&3] 8 [0&1&!2&3] +8 [0&!1&2&3] 8 [0&1&2&3] 8 State: 130 [0&!1&!2&!3] 48 [0&1&!2&!3] 130 +[0&!1&2&!3] 88 [0&1&2&!3] 131 [0&!1&!2&3] 9 [0&1&!2&3] 130 [0&!1&2&3] +9 [0&1&2&3] 131 State: 131 [0&!1&!2&!3] 48 [0&1&!2&!3] 130 [0&!1&2&!3] +88 [0&1&2&!3] 131 [0&!1&!2&3] 9 [0&1&!2&3] 9 [0&!1&2&3] 9 [0&1&2&3] +9 State: 132 [0&!1&!2&!3] 9 [0&1&!2&!3] 132 [0&!1&2&!3] 109 [0&1&2&!3] +133 [0&!1&!2&3] 9 [0&1&!2&3] 132 [0&!1&2&3] 109 [0&1&2&3] 133 State: 133 +[0&!1&!2&!3] 9 [0&1&!2&!3] 132 [0&!1&2&!3] 109 [0&1&2&!3] 133 [0&!1&!2&3] +9 [0&1&!2&3] 9 [0&!1&2&3] 109 [0&1&2&3] 9 State: 134 [0&!1&!2&!3] 7 +[0&1&!2&!3] 7 [0&!1&2&!3] 7 [0&1&2&!3] 7 [0&!1&!2&3] 7 [0&1&!2&3] 135 +[0&!1&2&3] 25 [0&1&2&3] 136 State: 135 [0&!1&!2&!3] 7 [0&1&!2&!3] 135 +[0&!1&2&!3] 134 [0&1&2&!3] 136 [0&!1&!2&3] 7 [0&1&!2&3] 135 [0&!1&2&3] +134 [0&1&2&3] 136 State: 136 [0&!1&!2&!3] 7 [0&1&!2&!3] 135 [0&!1&2&!3] +134 [0&1&2&!3] 136 [0&!1&!2&3] 7 [0&1&!2&3] 7 [0&!1&2&3] 134 [0&1&2&3] +7 --END-- +FOO +EOF + +chmod +x fake + +ltlcross -f 1 "./fake %f >%O" --verbose --csv=out.csv && exit 1 +test 2 = `grep '"ok"' out.csv | wc -l` From b214fd75d6032a5dceb5a26dc0774acb6efbd2a8 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Wed, 15 Jul 2020 11:30:52 +0200 Subject: [PATCH 27/30] scc_info: honor filters in edges_of() and inner_edges_of() * spot/twaalgos/sccinfo.hh: Honor filters in edges_of() and inner_edges_of(). * tests/core/sccif.test: Adjust expected output. * NEWS: Mention the bug. --- NEWS | 3 + spot/twaalgos/sccinfo.hh | 128 ++++++++++++++++++++++++++------------- tests/core/sccif.test | 4 +- 3 files changed, 90 insertions(+), 45 deletions(-) diff --git a/NEWS b/NEWS index d04256d35..a775fa78f 100644 --- a/NEWS +++ b/NEWS @@ -71,6 +71,9 @@ New in spot 2.9.0.dev (not yet released) acceptance sets than supported by Spot. This is now diagnosed with --verbose, but does not prevent ltlcross from continuing. + - scc_info::edges_of() and scc_info::inner_edges_of() now correctly + honor any filter passed to scc_info. + New in spot 2.9 (2020-04-30) Command-line tools: diff --git a/spot/twaalgos/sccinfo.hh b/spot/twaalgos/sccinfo.hh index 3c31c3dcd..a76ca3612 100644 --- a/spot/twaalgos/sccinfo.hh +++ b/spot/twaalgos/sccinfo.hh @@ -27,6 +27,38 @@ namespace spot { class scc_info; + /// @{ + /// \ingroup twa_misc + /// \brief An edge_filter may be called on each edge to decide what + /// to do with it. + /// + /// The edge filter is called with an edge and a destination. (In + /// existential automata the destination is already given by the + /// edge, but in alternating automata, one edge may have several + /// destinations, and in this case the filter will be called for + /// each destination.) The filter should return a value from + /// edge_filter_choice. + /// + /// \c keep means to use the edge normally, as if no filter had + /// been given. \c ignore means to pretend the edge does not + /// exist (if the destination is only reachable through this edge, + /// it will not be visited). \c cut also ignores the edge, but + /// it remembers to visit the destination state (as if it were an + /// initial state) in case it is not reachable otherwise. + /// + /// Note that successors between SCCs can only be maintained for + /// edges that are kept. If some edges are ignored or cut, the + /// SCC graph that you can explore with scc_info::initial() and + /// scc_info::succ() will be restricted to the portion reachable + /// with "keep" edges. Additionally SCCs might be created when + /// edges are cut, but those will not be reachable from + /// scc_info::initial().. + enum class edge_filter_choice { keep, ignore, cut }; + typedef edge_filter_choice + (*edge_filter)(const twa_graph::edge_storage_t& e, unsigned dst, + void* filter_data); + /// @} + namespace internal { struct keep_all @@ -100,6 +132,9 @@ namespace spot dv_t* dv_; Filter filt_; + edge_filter efilter_; + void* efilter_data_; + void inc_state_maybe_() { @@ -113,21 +148,49 @@ namespace spot inc_state_maybe_(); } + // Do we ignore the current transition? bool ignore_current() { unsigned dst = (*this)->dst; if ((int)dst >= 0) - // Non-universal branching => a single destination. - return !filt_(&(*this)->dst, 1 + &(*this)->dst); - // Universal branching => multiple destinations. - const unsigned* d = dv_->data() + ~dst; - return !filt_(d + 1, d + *d + 1); + { + // Non-universal branching => a single destination. + if (!filt_(&(*this)->dst, 1 + &(*this)->dst)) + return true; + if (efilter_) + return efilter_((*tv_)[t_], dst, efilter_data_) + != edge_filter_choice::keep; + return false; + } + else + { + // Universal branching => multiple destinations. + const unsigned* d = dv_->data() + ~dst; + if (!filt_(d + 1, d + *d + 1)) + return true; + if (efilter_) + { + // Keep the transition if at least one destination + // is not filtered. + const unsigned* end = d + *d + 1; + for (const unsigned* i = d + 1; i != end; ++i) + { + if (efilter_((*tv_)[t_], *i, efilter_data_) + == edge_filter_choice::keep) + return false; + return true; + } + } + return false; + } } public: scc_edge_iterator(state_iterator begin, state_iterator end, - tv_t* tv, sv_t* sv, dv_t* dv, Filter filt) noexcept - : pos_(begin), end_(end), t_(0), tv_(tv), sv_(sv), dv_(dv), filt_(filt) + tv_t* tv, sv_t* sv, dv_t* dv, Filter filt, + edge_filter efilter, void* efilter_data) noexcept + : pos_(begin), end_(end), t_(0), tv_(tv), sv_(sv), dv_(dv), filt_(filt), + efilter_(efilter), efilter_data_(efilter_data) { if (pos_ == end_) return; @@ -191,22 +254,26 @@ namespace spot sv_t* sv_; dv_t* dv_; Filter filt_; + edge_filter efilter_; + void* efilter_data_; public: scc_edges(state_iterator begin, state_iterator end, - tv_t* tv, sv_t* sv, dv_t* dv, Filter filt) noexcept - : begin_(begin), end_(end), tv_(tv), sv_(sv), dv_(dv), filt_(filt) + tv_t* tv, sv_t* sv, dv_t* dv, Filter filt, + edge_filter efilter, void* efilter_data) noexcept + : begin_(begin), end_(end), tv_(tv), sv_(sv), dv_(dv), filt_(filt), + efilter_(efilter), efilter_data_(efilter_data) { } iter_t begin() const { - return {begin_, end_, tv_, sv_, dv_, filt_}; + return {begin_, end_, tv_, sv_, dv_, filt_, efilter_, efilter_data_}; } iter_t end() const { - return {end_, end_, nullptr, nullptr, nullptr, filt_}; + return {end_, end_, nullptr, nullptr, nullptr, filt_, nullptr, nullptr}; } }; } @@ -378,36 +445,10 @@ namespace spot // support that yet. typedef scc_info_node scc_node; typedef scc_info_node::scc_succs scc_succs; - /// @{ - /// \brief An edge_filter may be called on each edge to decide what - /// to do with it. - /// - /// The edge filter is called with an edge and a destination. (In - /// existential automata the destination is already given by the - /// edge, but in alternating automata, one edge may have several - /// destinations, and in this case the filter will be called for - /// each destination.) The filter should return a value from - /// edge_filter_choice. - /// - /// \c keep means to use the edge normally, as if no filter had - /// been given. \c ignore means to pretend the edge does not - /// exist (if the destination is only reachable through this edge, - /// it will not be visited). \c cut also ignores the edge, but - /// it remembers to visit the destination state (as if it were an - /// initial state) in case it is not reachable otherwise. - /// - /// Note that successors between SCCs can only be maintained for - /// edges that are kept. If some edges are ignored or cut, the - /// SCC graph that you can explore with scc_info::initial() and - /// scc_info::succ() will be restricted to the portion reachable - /// with "keep" edges. Additionally SCCs might be created when - /// edges are cut, but those will not be reachable from - /// scc_info::initial().. - enum class edge_filter_choice { keep, ignore, cut }; - typedef edge_filter_choice - (*edge_filter)(const twa_graph::edge_storage_t& e, unsigned dst, - void* filter_data); - /// @} + + // These types used to be defined here in Spot up to 2.9. + typedef spot::edge_filter_choice edge_filter_choice; + typedef spot::edge_filter edge_filter; protected: @@ -559,7 +600,7 @@ namespace spot return {states.begin(), states.end(), &aut_->edge_vector(), &aut_->states(), &aut_->get_graph().dests_vector(), - internal::keep_all()}; + internal::keep_all(), filter_, const_cast(filter_data_)}; } /// \brief A fake container to iterate over all edges between @@ -576,7 +617,8 @@ namespace spot return {states.begin(), states.end(), &aut_->edge_vector(), &aut_->states(), &aut_->get_graph().dests_vector(), - internal::keep_inner_scc(sccof_, scc)}; + internal::keep_inner_scc(sccof_, scc), filter_, + const_cast(filter_data_)}; } unsigned one_state_of(unsigned scc) const diff --git a/tests/core/sccif.test b/tests/core/sccif.test index 2ee7f314c..2f3441f66 100755 --- a/tests/core/sccif.test +++ b/tests/core/sccif.test @@ -1,6 +1,6 @@ #!/bin/sh # -*- coding: utf-8 -*- -# Copyright (C) 2017 Laboratoire de Recherche et Développement +# Copyright (C) 2017, 2020 Laboratoire de Recherche et Développement # de l'Epita (LRDE). # # This file is part of Spot, a model checking library. @@ -79,7 +79,7 @@ SCC#1 succs: 0 SCC#2 states: 2 - edges: 2->2 + edges: succs: 0 1 EOF From 94c189b29d56083b33386abc98ea75f5e0f797c9 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Wed, 15 Jul 2020 11:41:14 +0200 Subject: [PATCH 28/30] remfin: simplify, thanks to previous patch * spot/twaalgos/remfin.cc: Get rid of for_each_edge since edges_of() and inner_edges_of() are now honoring the filters. --- spot/twaalgos/remfin.cc | 50 +++++++++++------------------------------ 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/spot/twaalgos/remfin.cc b/spot/twaalgos/remfin.cc index 38774f60b..647675610 100644 --- a/spot/twaalgos/remfin.cc +++ b/spot/twaalgos/remfin.cc @@ -38,22 +38,6 @@ namespace spot { namespace { - using EdgeMask = std::vector; - - template< typename Edges, typename Apply > - void for_each_edge(const const_twa_graph_ptr& aut, - const Edges& edges, - const EdgeMask& mask, - Apply apply) - { - for (const auto& e: edges) - { - unsigned edge_id = aut->edge_number(e); - if (mask[edge_id]) - apply(edge_id); - } - } - // Transforms automaton from transition based acceptance to state based // acceptance. void make_state_acc(twa_graph_ptr & aut) @@ -87,7 +71,6 @@ namespace spot bool is_scc_tba_type(const_twa_graph_ptr aut, const scc_info& si, const unsigned scc, - const std::vector& keep, const rs_pairs_view& aut_pairs, std::vector& final) { @@ -101,10 +84,8 @@ namespace spot auto aut_fin_alone = aut_pairs.fins_alone(); if ((scc_acc & aut_fin_alone) != aut_fin_alone) { - for_each_edge(aut, si.edges_of(scc), keep, [&](unsigned e) - { - final[e] = true; - }); + for (auto& e: si.edges_of(scc)) + final[aut->edge_number(e)] = true; return true; } @@ -126,14 +107,14 @@ namespace spot // final. Otherwise we do not know: it is possible that there is // a non-accepting cycle in the SCC that does not visit Fᵢ. std::set unknown; - for_each_edge(aut, si.inner_edges_of(scc), keep, [&](unsigned e) + for (auto& ed: si.inner_edges_of(scc)) { - const auto& ed = aut->edge_data(e); + unsigned e = aut->edge_number(ed); if (ed.acc & scc_infs_alone) - final[e] = true; + final[e] = true; else - unknown.insert(e); - }); + unknown.insert(e); + } // Erase edges that cannot belong to a cycle, i.e., the edges // whose 'dst' is not 'src' of any unknown edges. @@ -182,13 +163,11 @@ namespace spot for (unsigned uscc = 0; uscc < si.scc_count(); ++uscc) { - for_each_edge(aut, si.edges_of(uscc), keep, [&](unsigned e) - { - unknown.erase(e); - }); + for (auto& e: si.edges_of(uscc)) + unknown.erase(aut->edge_number(e)); if (si.is_rejecting_scc(uscc)) continue; - if (!is_scc_tba_type(aut, si, uscc, keep, aut_pairs, final)) + if (!is_scc_tba_type(aut, si, uscc, aut_pairs, final)) return false; } } @@ -229,10 +208,9 @@ namespace spot scc_info si(aut, scc_info_options::TRACK_STATES); std::vector scc_is_tba_type(si.scc_count(), false); std::vector final(aut->edge_vector().size(), false); - std::vector keep(aut->edge_vector().size(), true); for (unsigned scc = 0; scc < si.scc_count(); ++scc) - scc_is_tba_type[scc] = is_scc_tba_type(aut, si, scc, keep, + scc_is_tba_type[scc] = is_scc_tba_type(aut, si, scc, aut_pairs, final); auto res = make_twa_graph(aut->get_dict()); @@ -804,10 +782,9 @@ namespace spot // if is TBA type scc_info si(aut, scc_info_options::TRACK_STATES); std::vector final(aut->edge_vector().size(), false); - std::vector keep(aut->edge_vector().size(), true); for (unsigned scc = 0; scc < si.scc_count(); ++scc) - if (!is_scc_tba_type(aut, si, scc, keep, aut_pairs, final)) + if (!is_scc_tba_type(aut, si, scc, aut_pairs, final)) return false; return true; @@ -827,10 +804,9 @@ namespace spot scc_info si(aut, scc_info_options::TRACK_STATES); std::vector final(aut->edge_vector().size(), false); - std::vector keep(aut->edge_vector().size(), true); for (unsigned scc = 0; scc < si.scc_count(); ++scc) - if (!is_scc_tba_type(aut, si, scc, keep, aut_pairs, final)) + if (!is_scc_tba_type(aut, si, scc, aut_pairs, final)) return nullptr; auto res = make_twa_graph(aut, twa::prop_set::all()); From 62056642970531b4ce991ac4ef347d81d9714449 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Wed, 15 Jul 2020 13:40:59 +0200 Subject: [PATCH 29/30] Release Spot 2.9.1 * configure.ac, NEWS, doc/org/setup.org: Set version to 2.9.1. --- NEWS | 2 +- configure.ac | 2 +- doc/org/setup.org | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index a775fa78f..a10a993bb 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -New in spot 2.9.0.dev (not yet released) +New in spot 2.9.1 (2020-07-15) Command-line tools: diff --git a/configure.ac b/configure.ac index 30d621866..396b507ce 100644 --- a/configure.ac +++ b/configure.ac @@ -21,7 +21,7 @@ # along with this program. If not, see . AC_PREREQ([2.63]) -AC_INIT([spot], [2.9.0.dev], [spot@lrde.epita.fr]) +AC_INIT([spot], [2.9.1], [spot@lrde.epita.fr]) AC_CONFIG_AUX_DIR([tools]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([1.11 gnu tar-ustar color-tests parallel-tests]) diff --git a/doc/org/setup.org b/doc/org/setup.org index ad0283119..d94c663e7 100644 --- a/doc/org/setup.org +++ b/doc/org/setup.org @@ -1,10 +1,10 @@ #+OPTIONS: H:2 num:nil toc:t html-postamble:nil ^:nil #+EMAIL: spot@lrde.epita.fr #+HTML_LINK_HOME: index.html -#+MACRO: SPOTVERSION 2.9 -#+MACRO: LASTRELEASE 2.9 -#+MACRO: LASTTARBALL [[http://www.lrde.epita.fr/dload/spot/spot-2.9.tar.gz][=spot-2.9.tar.gz=]] -#+MACRO: LASTNEWS [[https://gitlab.lrde.epita.fr/spot/spot/blob/spot-2-9/NEWS][summary of the changes]] +#+MACRO: SPOTVERSION 2.9.1 +#+MACRO: LASTRELEASE 2.9.1 +#+MACRO: LASTTARBALL [[http://www.lrde.epita.fr/dload/spot/spot-2.9.1.tar.gz][=spot-2.9.1.tar.gz=]] +#+MACRO: LASTNEWS [[https://gitlab.lrde.epita.fr/spot/spot/blob/spot-2-9-1/NEWS][summary of the changes]] #+MACRO: LASTDATE 2020-04-30 #+ATTR_HTML: :id spotlogo From cf1550c352e01294f2b40724391776a88a3d5a98 Mon Sep 17 00:00:00 2001 From: Alexandre Duret-Lutz Date: Wed, 15 Jul 2020 13:43:15 +0200 Subject: [PATCH 30/30] * NEWS, configure.ac: Bump version to 2.9.1.dev. --- NEWS | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index a10a993bb..debc196c7 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +New in spot 2.9.1.dev (not yet released) + + Nothing yet. + New in spot 2.9.1 (2020-07-15) Command-line tools: diff --git a/configure.ac b/configure.ac index 396b507ce..d9fefdac2 100644 --- a/configure.ac +++ b/configure.ac @@ -21,7 +21,7 @@ # along with this program. If not, see . AC_PREREQ([2.63]) -AC_INIT([spot], [2.9.1], [spot@lrde.epita.fr]) +AC_INIT([spot], [2.9.1.dev], [spot@lrde.epita.fr]) AC_CONFIG_AUX_DIR([tools]) AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([1.11 gnu tar-ustar color-tests parallel-tests])