{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from IPython.display import display\n", "import spot\n", "spot.setup(show_default='.bans')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This notebook demonstrates how to use the `decompose_scc()` function to split an automaton in up to three automata capturing different behaviors. This is based on the paper [Strength-based decomposition of the property Büchi automaton for faster model checking](https://www.lrde.epita.fr/~adl/dl/adl/renault.13.tacas.pdf) (TACAS'13).\n", "\n", "This page uses the Python bindings, but the same decompositions can be performed from the shell using [`autfilt`](https://spot.lrde.epita.fr/autfilt.html) and its `--decompose-scc` option.\n", "\n", "# Basics\n", "\n", "Let's define the following strengths of accepting SCCs:\n", "\n", "- an accepting SCC is **inherently weak** if it does not contain any rejecting cycle\n", "- an accepting SCC is **inherently terminal** if it is *inherently weak* and complete (i.e. from any state, you can stay in the SCC by reading any word)\n", "- an accepting SCC is **strictly inherently weak** if it is *inherently weak* and not complete (in other words: *weak* but not *terminal*)\n", "- an accepting SCC is **strong** if it is not inherently weak.\n", "\n", "The strengths **strong**, **strictly inherently weak**, and **inherently terminal** define a partition of all accepting SCCs. The following Büchi automaton has 4 SCCs, and its 3 accepting SCCs show an example of each strength.\n", "\n", "Note: the reason we use the word *inherently* is that the *weak* and *terminal* properties are usually defined syntactically: an accepting SCC would be weak if all its transitions belong to the same acceptance sets. This syntactic criterion is a sufficient condition for an accepting SCC to not have any rejecting cycle, but it is not necessary. Hence a *weak* SCC is *inherently weak*; but while an *inherently weak* SCC is not necessarily *weak*, it can be modified to be *weak* without altering the language." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "4->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "a\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "b\n", "\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "4->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "a\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "b\n", "\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7cffd80> >" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "aut = spot.translate('(Ga -> Gb) W c')\n", "aut" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The `decompose_strength()` function takes an automaton, and a string specifying which strength to preserve. \n", "\n", "The letters used for this specification are as follows:\n", "\n", "- `t`: (inherently) terminal\n", "- `w`: (strictly inherently) weak\n", "- `s`: strong\n", "\n", "For instance if we want to preserve only the **strictly inherently weak** part of this automaton, we should get only the SCC with the self-loop on $b$, and the SCC above it so that we can reach it. However the SCC above is not strictly weak, so it should not accept any word in the new automaton." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "b\n", "\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "b\n", "\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d10240> >" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spot.decompose_scc(aut, 'w')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Similarly, we can extract all the behaviors captured by the **inherently terminal** part of the automaton:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d103f0> >" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spot.decompose_scc(aut, 't')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here is the **strong** part:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d10600> >" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "strong = spot.decompose_scc(aut, 's'); strong" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The union of these three automata recognize the same language as the original automaton.\n", "\n", "\n", "The application proposed in the aforementioned TACAS'13 paper is for parallelizing model checking. Instead of testing the emptiness of the product between `aut` and a system, one could test the emptiness **3** products in parallel: each with a sub-automaton of different strength. Model checking using weak and terminal automata can be done with much more simpler emptiness check procedures than needed for the general case. So in effect, we have isolated the \"hard\" (i.e. strong) part of the original automaton in a smaller automaton, and we only need to use a full-fledged emptiness check for this case.\n", "\n", "An additional bonus is that it is possible that the simplification algorithms will do a better job at simplifying the sub-automata than at simplifying the original `aut`. For instance here the `strong` automaton can be further simplified:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\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", "a & !c\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\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", "a & !c\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d10a80> >" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "strong.postprocess('small')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Multi-strength extraction\n", "\n", "The string passed to `decompose_strength()` can include multiple letters to extract multiple strengths at once." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "option: sw\n", "\n", "option: sw\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "b\n", "\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "option: sw\n", "\n", "option: sw\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "b\n", "\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d110e0> >" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "option: st\n", "\n", "option: st\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "option: st\n", "\n", "option: st\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7cffde0> >" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "option: wt\n", "\n", "option: wt\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "4->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "a\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "b\n", "\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "option: wt\n", "\n", "option: wt\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "4->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "a\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "b\n", "\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7cfff60> >" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for opt in ('sw', 'st', 'wt'):\n", " a = spot.decompose_scc(aut, opt)\n", " a.set_name(\"option: \" + opt)\n", " display(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Generalized acceptance\n", "\n", "There is nothing that prevents the above decomposition to work with other types of acceptance.\n", "\n", "## Rabin\n", "\n", "The following Rabin automaton was generated with\n", "\n", " ltldo -f '(Ga -> Gb) W c' 'ltl2dstar --ltl2nba=spin:ltl2tgba@-Ds' -H | autfilt -H --merge-transitions\n", " \n", "(The `autfilt -H --merge-transitions` pass is just here to reduce the size of the file and make the automaton more readable.)" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "(Fin(\n", "\n", ") & Inf(\n", "\n", ")) | (Fin(\n", "\n", ") & Inf(\n", "\n", "))\n", "[Rabin 2]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\n", "\n", "cluster_4\n", "\n", "\n", "\n", "cluster_5\n", "\n", "\n", "\n", "cluster_6\n", "\n", "\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "\n", "I->2\n", "\n", "\n", "\n", "\n", "\n", "6\n", "\n", "6\n", "\n", "\n", "\n", "\n", "\n", "2->6\n", "\n", "\n", "c\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "\n", "\n", "2->5\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "6->6\n", "\n", "\n", "1\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "1->6\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a\n", "\n", "\n", "\n", "8\n", "\n", "8\n", "\n", "\n", "\n", "\n", "8->6\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "8->1\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "8->8\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "0->6\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "0->5\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "5->6\n", "\n", "\n", "c\n", "\n", "\n", "\n", "5->0\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "5->5\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "7\n", "\n", "7\n", "\n", "\n", "\n", "\n", "5->7\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "7->6\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "7->1\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "7->8\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "7->0\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "7->5\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "7->7\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "3->6\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "3->0\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "3->5\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "4->6\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "4->1\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "4->8\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "4->0\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "4->5\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "4->7\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "(Fin(\n", "\n", ") & Inf(\n", "\n", ")) | (Fin(\n", "\n", ") & Inf(\n", "\n", "))\n", "[Rabin 2]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\n", "\n", "cluster_4\n", "\n", "\n", "\n", "cluster_5\n", "\n", "\n", "\n", "cluster_6\n", "\n", "\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "\n", "I->2\n", "\n", "\n", "\n", "\n", "\n", "6\n", "\n", "6\n", "\n", "\n", "\n", "\n", "\n", "2->6\n", "\n", "\n", "c\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "\n", "\n", "2->5\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "6->6\n", "\n", "\n", "1\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "1->6\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a\n", "\n", "\n", "\n", "8\n", "\n", "8\n", "\n", "\n", "\n", "\n", "8->6\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "8->1\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "8->8\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "0->6\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "0->5\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "5->6\n", "\n", "\n", "c\n", "\n", "\n", "\n", "5->0\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "5->5\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "7\n", "\n", "7\n", "\n", "\n", "\n", "\n", "5->7\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "7->6\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "7->1\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "7->8\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "7->0\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "7->5\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "7->7\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "3->6\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "3->0\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "3->5\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "4->6\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "4->1\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "4->8\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "4->0\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "4->5\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "4->7\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d115f0> >" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "aut = spot.automaton(\"\"\"\n", "HOA: v1 States: 9 Start: 2 AP: 3 \"a\" \"b\" \"c\" acc-name: Rabin 2 Acceptance:\n", "4 (Fin(0) & Inf(1)) | (Fin(2) & Inf(3)) properties: trans-labels\n", "explicit-labels state-acc complete properties: deterministic --BODY--\n", "State: 0 {2} [0&!2] 0 [0&2] 1 [!0&!2] 5 [!0&2] 6 State: 1 {2} [0] 1 [!0]\n", "6 State: 2 {2} [0&!1&!2] 3 [0&1&!2] 4 [!0&!2] 5 [2] 6 State: 3 {1 2}\n", "[0&!2] 0 [0&2] 1 [!0&!2] 5 [!0&2] 6 State: 4 {1 2} [0&!1&!2] 0 [0&!1&2]\n", "1 [!0&!2] 5 [!0&2] 6 [0&1&!2] 7 [0&1&2] 8 State: 5 {1 2} [0&!1&!2] 0\n", "[!0&!2] 5 [2] 6 [0&1&!2] 7 State: 6 {1 2} [t] 6 State: 7 {3} [0&!1&!2]\n", "0 [0&!1&2] 1 [!0&!2] 5 [!0&2] 6 [0&1&!2] 7 [0&1&2] 8 State: 8 {3} [0&!1]\n", "1 [!0] 6 [0&1] 8 --END--\"\"\")\n", "aut" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's decompose it into three strengths:" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "terminal\n", "\n", "terminal\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\n", "\n", "cluster_4\n", "\n", "\n", "\n", "cluster_5\n", "\n", "\n", "\n", "cluster_6\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "\n", "0->4\n", "\n", "\n", "c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "1\n", "\n", "\n", "\n", "7\n", "\n", "7\n", "\n", "\n", "\n", "7->4\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "7->7\n", "\n", "\n", "a\n", "\n", "\n", "\n", "8\n", "\n", "8\n", "\n", "\n", "\n", "8->4\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "8->7\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "8->8\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "5->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "5->7\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "5->5\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "5->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "c\n", "\n", "\n", "\n", "3->5\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "6\n", "\n", "6\n", "\n", "\n", "\n", "3->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "6->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "6->7\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "6->8\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "6->5\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "6->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "6->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "1->7\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "1->5\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->7\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "2->8\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "2->5\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "terminal\n", "\n", "terminal\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\n", "\n", "cluster_4\n", "\n", "\n", "\n", "cluster_5\n", "\n", "\n", "\n", "cluster_6\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "\n", "0->4\n", "\n", "\n", "c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "1\n", "\n", "\n", "\n", "7\n", "\n", "7\n", "\n", "\n", "\n", "7->4\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "7->7\n", "\n", "\n", "a\n", "\n", "\n", "\n", "8\n", "\n", "8\n", "\n", "\n", "\n", "8->4\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "8->7\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "8->8\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "5->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "5->7\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "5->5\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "5->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "c\n", "\n", "\n", "\n", "3->5\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "6\n", "\n", "6\n", "\n", "\n", "\n", "3->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "6->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "6->7\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "6->8\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "6->5\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "6->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "6->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "1->7\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "1->5\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->7\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "2->8\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "2->5\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d10c00> >" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "strictly weak\n", "\n", "strictly weak\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\n", "\n", "cluster_4\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "6\n", "\n", "6\n", "\n", "\n", "\n", "\n", "6->6\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "4->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "3->5\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "5->6\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "5->4\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "5->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "5->5\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->6\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->5\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "strictly weak\n", "\n", "strictly weak\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\n", "\n", "cluster_4\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "6\n", "\n", "6\n", "\n", "\n", "\n", "\n", "6->6\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "4->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "3->5\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "5->6\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "5->4\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "5->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "5->5\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->6\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->5\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7cfff60> >" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "strong\n", "\n", "strong\n", "(Fin(\n", "\n", ") & Inf(\n", "\n", ")) | (Fin(\n", "\n", ") & Inf(\n", "\n", "))\n", "[Rabin 2]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "4->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "\n", "3->5\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "5->4\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "5->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "5->5\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->5\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "strong\n", "\n", "strong\n", "(Fin(\n", "\n", ") & Inf(\n", "\n", ")) | (Fin(\n", "\n", ") & Inf(\n", "\n", "))\n", "[Rabin 2]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "4->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "\n", "3->5\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "5->4\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "5->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "5->5\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->5\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d10c00> >" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for (name, opt) in (('terminal', 't'), ('strictly weak', 'w'), ('strong', 's')):\n", " a = spot.decompose_scc(aut, opt)\n", " a.set_name(name)\n", " display(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note how the two weak automata (i.e., strictly weak and terminal) are now using a Büchi acceptance condition (because that is sufficient for weak automata) while the strong automaton inherited the original acceptance condition.\n", "\n", "When extracting multiple strengths and one of the strength is **strong**, we preserve the original acceptance. For instance extracting **strong** and **inherently terminal** gives the following automaton, where only **strictly inherently weak** SCCs have become rejecting." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "(Fin(\n", "\n", ") & Inf(\n", "\n", ")) | (Fin(\n", "\n", ") & Inf(\n", "\n", "))\n", "[Rabin 2]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\n", "\n", "cluster_4\n", "\n", "\n", "\n", "cluster_5\n", "\n", "\n", "\n", "cluster_6\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "\n", "\n", "0->4\n", "\n", "\n", "c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "1\n", "\n", "\n", "\n", "7\n", "\n", "7\n", "\n", "\n", "\n", "7->4\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "7->7\n", "\n", "\n", "a\n", "\n", "\n", "\n", "8\n", "\n", "8\n", "\n", "\n", "\n", "8->4\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "8->7\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "8->8\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "\n", "5->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "5->7\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "5->5\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "5->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "c\n", "\n", "\n", "\n", "3->5\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "6\n", "\n", "6\n", "\n", "\n", "\n", "\n", "3->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "6->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "6->7\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "6->8\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "6->5\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "6->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "6->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "1->7\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "1->5\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->7\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "2->8\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "2->5\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "(Fin(\n", "\n", ") & Inf(\n", "\n", ")) | (Fin(\n", "\n", ") & Inf(\n", "\n", "))\n", "[Rabin 2]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\n", "\n", "cluster_4\n", "\n", "\n", "\n", "cluster_5\n", "\n", "\n", "\n", "cluster_6\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "\n", "\n", "0->4\n", "\n", "\n", "c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "1\n", "\n", "\n", "\n", "7\n", "\n", "7\n", "\n", "\n", "\n", "7->4\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "7->7\n", "\n", "\n", "a\n", "\n", "\n", "\n", "8\n", "\n", "8\n", "\n", "\n", "\n", "8->4\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "8->7\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "8->8\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "\n", "5->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "5->7\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "5->5\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "5->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "c\n", "\n", "\n", "\n", "3->5\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "6\n", "\n", "6\n", "\n", "\n", "\n", "\n", "3->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "6->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "6->7\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "6->8\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "6->5\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "6->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "6->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "1->7\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "1->5\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->7\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "2->8\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "2->5\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d10a20> >" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spot.decompose_scc(aut, \"st\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The weak automata seem to be good candidates for further simplification. Let's add a call to `postprocess()` to our decomposition loop, trying to preserve the determinism and state-based acceptance of the original automaton." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "inherently terminal\n", "\n", "inherently terminal\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "I->2\n", "\n", "\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "1\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a\n", "\n", "\n", "\n", "3->2\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->0\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "inherently terminal\n", "\n", "inherently terminal\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "I->2\n", "\n", "\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "1\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a\n", "\n", "\n", "\n", "3->2\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->0\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d10b40> >" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "strictly inherently weak\n", "\n", "strictly inherently weak\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "I->2\n", "\n", "\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "3->2\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->0\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "strictly inherently weak\n", "\n", "strictly inherently weak\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "I->2\n", "\n", "\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "3->2\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->0\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d119e0> >" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "strong\n", "\n", "strong\n", "Inf(\n", "\n", ") | (Fin(\n", "\n", ") & Inf(\n", "\n", "))\n", "[parity min even 3]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "(b & !c) | (!a & !c)\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "1->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->2\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "strong\n", "\n", "strong\n", "Inf(\n", "\n", ") | (Fin(\n", "\n", ") & Inf(\n", "\n", "))\n", "[parity min even 3]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "(b & !c) | (!a & !c)\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "1->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->2\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d114d0> >" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for (name, opt) in (('inherently terminal', 't'), ('strictly inherently weak', 'w'), ('strong', 's')):\n", " a = spot.decompose_scc(aut, opt).postprocess('deterministic', 'SBAcc')\n", " a.set_name(name)\n", " display(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Streett\n", "\n", "Since this notebook also serves as a test suite, let's try a Streett automaton. This one was generated with\n", "\n", " ltldo -f '(Ga -> Gb) W c' 'ltl2dstar --automata=streett --ltl2nba=spin:ltl2tgba@-Ds' -H | \n", " autfilt -H --merge-transitions" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "(Fin(\n", "\n", ") | Inf(\n", "\n", ")) & (Fin(\n", "\n", ") | Inf(\n", "\n", "))\n", "[Streett 2]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\n", "\n", "cluster_4\n", "\n", "\n", "\n", "\n", "\n", "7\n", "\n", "7\n", "\n", "\n", "\n", "\n", "I->7\n", "\n", "\n", "\n", "\n", "\n", "7->7\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "\n", "\n", "7->4\n", "\n", "\n", "c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "\n", "7->2\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "6\n", "\n", "6\n", "\n", "\n", "\n", "\n", "7->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "1\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "0->4\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "\n", "5->4\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "5->3\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "5->5\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "2->7\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1->7\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "1->3\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "6->7\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "6->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "6->3\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "6->5\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "6->2\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "6->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "(Fin(\n", "\n", ") | Inf(\n", "\n", ")) & (Fin(\n", "\n", ") | Inf(\n", "\n", "))\n", "[Streett 2]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\n", "\n", "cluster_4\n", "\n", "\n", "\n", "\n", "\n", "7\n", "\n", "7\n", "\n", "\n", "\n", "\n", "I->7\n", "\n", "\n", "\n", "\n", "\n", "7->7\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "\n", "\n", "7->4\n", "\n", "\n", "c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "\n", "7->2\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "6\n", "\n", "6\n", "\n", "\n", "\n", "\n", "7->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "1\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "0->4\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "\n", "5->4\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "5->3\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "5->5\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "2->7\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1->7\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "1->3\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "6->7\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "6->4\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "6->3\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "6->5\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "6->2\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "6->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d11c20> >" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "aut = spot.automaton(\"\"\"\n", "HOA: v1 States: 8 Start: 7 AP: 3 \"a\" \"b\" \"c\" acc-name: Streett\n", "2 Acceptance: 4 (Fin(0) | Inf(1)) & (Fin(2) | Inf(3)) properties:\n", "trans-labels explicit-labels state-acc complete properties: deterministic\n", "--BODY-- State: 0 {2} [0&1] 0 [0&!1] 3 [!0] 4 State: 1 {2} [0&1&2]\n", "0 [0&1&!2] 1 [0&!1&!2] 2 [0&!1&2] 3 [!0&2] 4 [!0&!2] 7 State: 2 {2}\n", "[0&1&!2] 1 [0&!1&!2] 2 [0&2] 3 [!0&2] 4 [!0&!2] 7 State: 3 {0 3} [0] 3\n", "[!0] 4 State: 4 {1 3} [t] 4 State: 5 {3} [0&!1] 3 [!0] 4 [0&1] 5 State:\n", "6 {3} [0&!1&!2] 2 [0&!1&2] 3 [!0&2] 4 [0&1&2] 5 [0&1&!2] 6 [!0&!2]\n", "7 State: 7 {3} [0&!1&!2] 2 [2] 4 [0&1&!2] 6 [!0&!2] 7 --END--\"\"\")\n", "aut" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "inherently terminal\n", "\n", "inherently terminal\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\n", "\n", "cluster_4\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "1\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "\n", "4->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "a\n", "\n", "\n", "\n", "7\n", "\n", "7\n", "\n", "\n", "\n", "\n", "7->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "7->4\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "7->7\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "\n", "5->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "5->4\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "5->5\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "6\n", "\n", "6\n", "\n", "\n", "\n", "\n", "1->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "6->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "6->2\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "6->4\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "6->7\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "6->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "6->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "3->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->2\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "3->5\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "inherently terminal\n", "\n", "inherently terminal\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\n", "\n", "cluster_4\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "1\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "\n", "4->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "a\n", "\n", "\n", "\n", "7\n", "\n", "7\n", "\n", "\n", "\n", "\n", "7->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "7->4\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "7->7\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "\n", "5->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "5->4\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "5->5\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "6\n", "\n", "6\n", "\n", "\n", "\n", "\n", "1->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "6->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "6->2\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "6->4\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "6->7\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "6->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "6->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "3->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->2\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "3->5\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d12460> >" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "strictly inherently weak\n", "\n", "strictly inherently weak\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "4->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "4->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "strictly inherently weak\n", "\n", "strictly inherently weak\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "4->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "4->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d114d0> >" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "strong\n", "\n", "strong\n", "(Fin(\n", "\n", ") | Inf(\n", "\n", ")) & (Fin(\n", "\n", ") | Inf(\n", "\n", "))\n", "[Streett 2]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "1->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "3->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "strong\n", "\n", "strong\n", "(Fin(\n", "\n", ") | Inf(\n", "\n", ")) & (Fin(\n", "\n", ") | Inf(\n", "\n", "))\n", "[Streett 2]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "1->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "3->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d12460> >" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for (name, opt) in (('inherently terminal', 't'), ('strictly inherently weak', 'w'), ('strong', 's')):\n", " a = spot.decompose_strength(aut, opt)\n", " a.set_name(name)\n", " display(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The subtlety of Streett acceptance is that a path that does not visit any accepting set infinitely often *is* accepting. So when disabling SCCs, we must be careful to label them with a combination of rejecting acceptance sets.\n", "\n", "This is easy to understand using an example. In the following extraction of the **strong** and **inherently terminal** parts, the rejecting SCCs (that were either rejecting or strictly inherently weak originally) have been labeled by the same acceptance sets, to ensure that they are rejected." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "(Fin(\n", "\n", ") | Inf(\n", "\n", ")) & (Fin(\n", "\n", ") | Inf(\n", "\n", "))\n", "[Streett 2]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\n", "\n", "cluster_4\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "1\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "\n", "4->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "a\n", "\n", "\n", "\n", "7\n", "\n", "7\n", "\n", "\n", "\n", "\n", "7->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "7->4\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "7->7\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "\n", "5->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "5->4\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "5->5\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "6\n", "\n", "6\n", "\n", "\n", "\n", "\n", "1->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "6->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "6->2\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "6->4\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "6->7\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "6->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "6->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "3->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->2\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "3->5\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "(Fin(\n", "\n", ") | Inf(\n", "\n", ")) & (Fin(\n", "\n", ") | Inf(\n", "\n", "))\n", "[Streett 2]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\n", "\n", "cluster_4\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "1\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "\n", "4->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "a\n", "\n", "\n", "\n", "7\n", "\n", "7\n", "\n", "\n", "\n", "\n", "7->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "7->4\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "7->7\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "5\n", "\n", "5\n", "\n", "\n", "\n", "\n", "5->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "5->4\n", "\n", "\n", "a & !b\n", "\n", "\n", "\n", "5->5\n", "\n", "\n", "a & b\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "1->4\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "6\n", "\n", "6\n", "\n", "\n", "\n", "\n", "1->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "6->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "6->2\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "6->4\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "6->7\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "6->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "6->6\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "3->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "3->2\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "3->4\n", "\n", "\n", "a & !b & c\n", "\n", "\n", "\n", "3->5\n", "\n", "\n", "a & b & c\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "a & !b & !c\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d12160> >" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spot.decompose_scc(aut, 'st')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Corner cases\n", "\n", "When the acceptance condition is always satisfiable, all non-trivial SCCs are accepting, and inherently weak.\n", "\n", "This include acceptances like `Acceptance: 0 t`, but also trickier ones like `Acceptance: 1 Inf(0) | Fin(0)` that you can make as complex as you fancy.\n", "\n", "### `Acceptance: 0 t`\n", "\n", "This occur frequently when translating LTL formulas that are safety properties:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "t\n", "[all]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\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", "a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "b\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "t\n", "[all]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\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", "a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "b\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d11c80> >" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "aut = spot.translate('(Gb|c) R a', 'any'); aut" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "# There is no strong part for this automaton\n", "assert spot.decompose_scc(aut, 's') is None" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "b\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "\n", "\n", "0\n", "\n", "0\n", "\n", "\n", "\n", "\n", "I->0\n", "\n", "\n", "\n", "\n", "\n", "0->0\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "b\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d120d0> >" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\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", "a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\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", "a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d11290> >" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for opt in ('w', 't'):\n", " display(spot.decompose_scc(aut, opt))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we try to extract multiple strengths and include the (empty) strong part, this request will simply be ignored:" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\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", "a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\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", "a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d11e60> >" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spot.decompose_scc(aut, 'st')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that the above is exactly the output of `decompose_strength(aut, 't')`. The `'s'` flag was actively ignored. If `'s'` had not been ignored an the automaton processed as if its strong part had to be preserved, the original acceptance conditions would have been used, and this would have prevented the disabling of the initial SCC." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### `Acceptance: 1 Inf(0) | Fin(0)`\n", "\n", "This acceptance could be replaced by `Acceptance: 0 t` without altering the language of the automaton. However its use of acceptance sets allows us to define some automata with SCCs that are *inherently weak* but not *weak*." ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ") | Fin(\n", "\n", ")\n", "[Streett-like 1]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\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", "a\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "a\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ") | Fin(\n", "\n", ")\n", "[Streett-like 1]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\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", "a\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "a\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d10180> >" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "aut = spot.automaton(\"\"\"\n", "HOA: v1\n", "States: 4\n", "Start: 0\n", "AP: 1 \"a\"\n", "Acceptance: 1 Inf(0) | Fin(0)\n", "--BODY--\n", "State: 0\n", "[0] 0 \n", "[!0] 1\n", "State: 1\n", "[0] 1 \n", "[!0] 2 {0}\n", "State: 2\n", "[0] 1\n", "[!0] 3\n", "State: 3\n", "[t] 3 {0}\n", "--END--\n", "\"\"\")\n", "aut" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "By our definitions, SCC $\\{0\\}$ and $\\{1,2\\}$ are inherently weak, and SCC $\\{3\\}$ is terminal." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "terminal\n", "\n", "terminal\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\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", "a\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "a\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "terminal\n", "\n", "terminal\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\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", "a\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "a\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d137b0> >" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "strictly weak\n", "\n", "strictly weak\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\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", "a\n", "\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a\n", "\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "a\n", "\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "strictly weak\n", "\n", "strictly weak\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\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", "a\n", "\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a\n", "\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "a\n", "\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d12460> >" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "no output for strong\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "all strengths\n", "\n", "all strengths\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\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", "a\n", "\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a\n", "\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "a\n", "\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "all strengths\n", "\n", "all strengths\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\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", "a\n", "\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a\n", "\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "1->2\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "a\n", "\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d137b0> >" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "for (name, opt) in (('terminal', 't'), ('strictly weak', 'w'), ('strong', 's'), ('all strengths', 'swt')):\n", " a = spot.decompose_scc(aut, opt)\n", " if a:\n", " a.set_name(name)\n", " display(a)\n", " else:\n", " print(\"no output for \" + name)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# `decompose_scc()` by SCC number\n", "\n", "Decompose SCC can also be called by SCC numbers.\n", "The example below show the different SCC numbers and the state they contains, before extracting the sub-automaton containing SCC 0 and 1 (i.e., anything leading to states 1 and 4 of the original automaton). This example also shows that when an `scc_info` is available for to automaton to decompose, it can be passed to `decompose_scc()` in lieu of the automaton: doing so is faster because `decompose_scc()` does not need to rebuild this object. " ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "SCC #0 contains states (1,)\n", "SCC #1 contains states (4,)\n", "SCC #2 contains states (3,)\n", "SCC #3 contains states (0, 2)\n" ] }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "4->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "a\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "b\n", "\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\n", "\n", "cluster_3\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "c\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "0->3\n", "\n", "\n", "a & b & !c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "4\n", "\n", "4\n", "\n", "\n", "\n", "4->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "4->4\n", "\n", "\n", "a\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "b\n", "\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->4\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d124c0> >" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\n", "\n", "cluster_1\n", "\n", "\n", "\n", "cluster_2\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "c\n", "\n", "\n", "\n", "2\n", "\n", "2\n", "\n", "\n", "\n", "0->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "1\n", "\n", "\n", "\n", "\n", "3\n", "\n", "3\n", "\n", "\n", "\n", "3->1\n", "\n", "\n", "!a\n", "\n", "\n", "\n", "3->3\n", "\n", "\n", "a\n", "\n", "\n", "\n", "2->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "2->1\n", "\n", "\n", "!a & c\n", "\n", "\n", "\n", "2->3\n", "\n", "\n", "a & c\n", "\n", "\n", "\n", "2->2\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d117d0> >" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "aut = spot.translate('(Ga -> Gb) W c')\n", "si = spot.scc_info(aut)\n", "for scc in range(si.scc_count()):\n", " print(f\"SCC #{scc} contains states {si.states_of(scc)}\")\n", "display(aut)\n", "spot.decompose_scc(si, '0,1')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If an SCC number N is prefixed by `a`, it signifies that we want to extract the (N+1)th *accepting* SCC. In the above example SCC 1 is rejecting so `a0`, `a1`, and `a2` denote respectively SCCs 0, 2, and 3." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Inf(\n", "\n", ")\n", "[Büchi]\n", "\n", "cluster_0\n", "\n", "\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", "!a & !c\n", "\n", "\n", "\n", "\n", "1\n", "\n", "1\n", "\n", "\n", "\n", "0->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n", "1->0\n", "\n", "\n", "!a & !c\n", "\n", "\n", "\n", "\n", "1->1\n", "\n", "\n", "a & !c\n", "\n", "\n", "\n" ], "text/plain": [ " *' at 0x7faaf7d13420> >" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "spot.decompose_scc(si, 'a2')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.8" } }, "nbformat": 4, "nbformat_minor": 4 }