Propagate colors in split_2step

Reduce the amount of uncolored transitions
after split_2step by trying to color the env transitions.
This is currently only supported for parity like
acceptance conditions.

* spot/twaalgos/game.cc: Determinizatio of "colored"
game can created trivial self-loops. Fix them
* spot/twaalgos/synthesis.cc: Here
* tests/core/ltlsynt.test,
tests/python/_synthesis.ipynb,
tests/python/games.ipynb,
tests/python/synthesis.ipynb,
tests/python/synthesis.py: New and adjusted tests
This commit is contained in:
Philipp Schlehuber-Caissier 2022-04-04 08:47:11 +02:00
parent dfb75632ba
commit 524edea8da
7 changed files with 1896 additions and 1821 deletions

View file

@ -867,7 +867,7 @@ namespace spot
todo.pop_back(); todo.pop_back();
seen[src] = true; seen[src] = true;
bdd missing = bddtrue; bdd missing = bddtrue;
for (const auto& e: arena->out(src)) for (auto& e: arena->out(src))
{ {
bool osrc = (*owner)[src]; bool osrc = (*owner)[src];
if (complete0 && !osrc) if (complete0 && !osrc)
@ -878,6 +878,21 @@ namespace spot
(*owner)[e.dst] = !osrc; (*owner)[e.dst] = !osrc;
todo.push_back(e.dst); todo.push_back(e.dst);
} }
else if (e.src == e.dst)
{
if (e.cond == bddtrue)
{
// Fix trivial self-loop
// No need to add it to seen
auto inter = arena->new_state();
owner->push_back(!osrc);
e.dst = inter;
arena->new_edge(inter, src, bddtrue, e.acc);
}
else
throw std::runtime_error("alternate_players(): "
"Nontrivial selfloop");
}
else if ((*owner)[e.dst] == osrc) else if ((*owner)[e.dst] == osrc)
{ {
delete owner; delete owner;

View file

@ -447,9 +447,13 @@ namespace spot
split_2step(const const_twa_graph_ptr& aut, split_2step(const const_twa_graph_ptr& aut,
const bdd& output_bdd, bool complete_env) const bdd& output_bdd, bool complete_env)
{ {
assert(!aut->get_named_prop<region_t>("state-player")
&& "aut is already split!");
auto split = make_twa_graph(aut->get_dict()); auto split = make_twa_graph(aut->get_dict());
auto [has_unsat, unsat_mark] = aut->acc().unsat_mark(); auto [has_unsat, unsat_mark] = aut->acc().unsat_mark();
bool max_par, odd_par, color_env;
color_env = aut->acc().is_parity(max_par, odd_par, true);
split->copy_ap_of(aut); split->copy_ap_of(aut);
split->new_states(aut->num_states()); split->new_states(aut->num_states());
@ -457,6 +461,7 @@ namespace spot
set_synthesis_outputs(split, output_bdd); set_synthesis_outputs(split, output_bdd);
const auto use_color = has_unsat; const auto use_color = has_unsat;
color_env &= use_color;
if (has_unsat) if (has_unsat)
split->copy_acceptance_of(aut); split->copy_acceptance_of(aut);
else else
@ -490,8 +495,10 @@ namespace spot
// So we can first loop over the aut // So we can first loop over the aut
// and then deduce the owner // and then deduce the owner
// a sort of hash-map for all new intermediate states // a sort of hash-map for all new intermediate stat
std::unordered_multimap<size_t, unsigned> env_hash; // second is the color of the incoming env trans
std::unordered_multimap<size_t,
std::pair<unsigned, acc_cond::mark_t>> env_hash;
env_hash.reserve((int) (1.5 * aut->num_states())); env_hash.reserve((int) (1.5 * aut->num_states()));
// a local map for edges leaving the current src // a local map for edges leaving the current src
// this avoids creating and then combining edges for each minterm // this avoids creating and then combining edges for each minterm
@ -590,7 +597,7 @@ namespace spot
auto range_h = env_hash.equal_range(h); auto range_h = env_hash.equal_range(h);
for (auto it_h = range_h.first; it_h != range_h.second; ++it_h) for (auto it_h = range_h.first; it_h != range_h.second; ++it_h)
{ {
unsigned i = it_h->second; const auto& [i, this_color] = it_h->second;
auto out = split->out(i); auto out = split->out(i);
if (std::equal(out.begin(), out.end(), if (std::equal(out.begin(), out.end(),
dests.begin(), dests.end(), dests.begin(), dests.end(),
@ -612,9 +619,10 @@ namespace spot
if (it != env_edge_hash.end()) if (it != env_edge_hash.end())
it->second.second |= one_letter; it->second.second |= one_letter;
else else
// Uncolored
env_edge_hash.emplace(i, env_edge_hash.emplace(i,
eeh_t(split->new_edge(src, i, bddtrue), one_letter)); eeh_t(split->new_edge(src, i, bddtrue,
this_color),
one_letter));
break; break;
} }
} }
@ -622,12 +630,31 @@ namespace spot
if (to_add) if (to_add)
{ {
unsigned d = split->new_state(); unsigned d = split->new_state();
unsigned n_e = split->new_edge(src, d, bddtrue); auto this_color = acc_cond::mark_t({});
env_hash.emplace(h, d); bool has_uncolored = false;
env_edge_hash.emplace(d, eeh_t(n_e, one_letter));
for (const auto &t: dests) for (const auto &t: dests)
{
split->new_edge(d, t->dst, t->econdout, split->new_edge(d, t->dst, t->econdout,
use_color ? t->acc : acc_cond::mark_t({})); use_color ? t->acc
: acc_cond::mark_t({}));
this_color |= t->acc;
has_uncolored |= !t->acc;
}
if (!color_env | has_uncolored)
this_color = acc_cond::mark_t({});
else if (max_par)
this_color =
acc_cond::mark_t({this_color.min_set()-1});
else // min_par
this_color =
acc_cond::mark_t({this_color.max_set()-1});
unsigned n_e = split->new_edge(src, d, bddtrue, this_color);
env_hash.emplace(std::piecewise_construct,
std::forward_as_tuple(h),
std::forward_as_tuple(d, this_color));
env_edge_hash.emplace(d, eeh_t(n_e, one_letter));
} }
} // letters } // letters
// save locally stored condition // save locally stored condition

View file

@ -25,23 +25,23 @@ set -e
cat >exp <<EOF cat >exp <<EOF
parity 17; parity 17;
0 1 0 7,8 "INIT"; 0 1 0 7,8 "INIT";
8 3 1 2; 8 1 1 2;
2 1 0 11,12; 2 3 0 11,12;
12 5 1 2,3; 12 3 1 2,3;
3 1 0 13,14; 3 2 0 13,14;
14 4 1 2,3; 14 2 1 2,3;
13 4 1 1,4; 13 2 1 1,4;
4 1 0 8,15; 4 1 0 8,15;
15 3 1 5,6; 15 1 1 5,6;
6 1 0 8,15; 6 1 0 8,15;
5 1 0 16,17; 5 2 0 16,17;
17 4 1 2; 17 2 1 2;
16 4 1 5,6; 16 2 1 5,6;
1 1 0 9,10; 1 1 0 9,10;
10 3 1 2,3; 10 1 1 2,3;
9 3 1 1,5; 9 1 1 1,5;
11 5 1 1,4; 11 3 1 1,4;
7 3 1 1,2; 7 1 1 1,2;
parity 13; parity 13;
0 1 0 1,2 "INIT"; 0 1 0 1,2 "INIT";
2 1 1 3; 2 1 1 3;

View file

@ -8,7 +8,8 @@
"outputs": [], "outputs": [],
"source": [ "source": [
"import spot, buddy\n", "import spot, buddy\n",
"spot.setup()" "spot.setup()\n",
"from spot.jupyter import display_inline"
] ]
}, },
{ {

View file

@ -774,7 +774,7 @@
"<path fill=\"none\" stroke=\"black\" d=\"M263.84,-69.53C269.36,-57.32 278.74,-41.62 292.66,-34.2 305.05,-27.61 320.17,-33.47 331.57,-40.37\"/>\n", "<path fill=\"none\" stroke=\"black\" d=\"M263.84,-69.53C269.36,-57.32 278.74,-41.62 292.66,-34.2 305.05,-27.61 320.17,-33.47 331.57,-40.37\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"337.48,-44.24 329.9,-43.04 334.55,-42.32 331.62,-40.41 331.62,-40.41 331.62,-40.41 334.55,-42.32 333.35,-37.77 337.48,-44.24 337.48,-44.24\"/>\n", "<polygon fill=\"black\" stroke=\"black\" points=\"337.48,-44.24 329.9,-43.04 334.55,-42.32 331.62,-40.41 331.62,-40.41 331.62,-40.41 334.55,-42.32 333.35,-37.77 337.48,-44.24 337.48,-44.24\"/>\n",
"<text text-anchor=\"start\" x=\"297.16\" y=\"-53\" font-family=\"Lato\" font-size=\"14.00\">a</text>\n", "<text text-anchor=\"start\" x=\"297.16\" y=\"-53\" font-family=\"Lato\" font-size=\"14.00\">a</text>\n",
"<text text-anchor=\"start\" x=\"292.66\" y=\"-38\" font-family=\"Lato\" font-size=\"14.00\" fill=\"#ff4da0\">❶</text>\n", "<text text-anchor=\"start\" x=\"292.66\" y=\"-38\" font-family=\"Lato\" font-size=\"14.00\" fill=\"#ff7f00\">❷</text>\n",
"</g>\n", "</g>\n",
"<!-- 5&#45;&gt;0 -->\n", "<!-- 5&#45;&gt;0 -->\n",
"<g id=\"edge10\" class=\"edge\">\n", "<g id=\"edge10\" class=\"edge\">\n",
@ -804,7 +804,7 @@
"<path fill=\"none\" stroke=\"black\" d=\"M429.13,-67.92C422.9,-62.64 414.93,-57.03 406.62,-54.2 397.16,-50.98 386.28,-50.18 376.63,-50.39\"/>\n", "<path fill=\"none\" stroke=\"black\" d=\"M429.13,-67.92C422.9,-62.64 414.93,-57.03 406.62,-54.2 397.16,-50.98 386.28,-50.18 376.63,-50.39\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"369.54,-50.71 376.39,-47.24 373.04,-50.55 376.53,-50.39 376.53,-50.39 376.53,-50.39 373.04,-50.55 376.68,-53.54 369.54,-50.71 369.54,-50.71\"/>\n", "<polygon fill=\"black\" stroke=\"black\" points=\"369.54,-50.71 376.39,-47.24 373.04,-50.55 376.53,-50.39 376.53,-50.39 376.53,-50.39 373.04,-50.55 376.68,-53.54 369.54,-50.71 369.54,-50.71\"/>\n",
"<text text-anchor=\"start\" x=\"395.12\" y=\"-73\" font-family=\"Lato\" font-size=\"14.00\">a</text>\n", "<text text-anchor=\"start\" x=\"395.12\" y=\"-73\" font-family=\"Lato\" font-size=\"14.00\">a</text>\n",
"<text text-anchor=\"start\" x=\"390.62\" y=\"-58\" font-family=\"Lato\" font-size=\"14.00\" fill=\"#ff4da0\">❶</text>\n", "<text text-anchor=\"start\" x=\"390.62\" y=\"-58\" font-family=\"Lato\" font-size=\"14.00\" fill=\"#ff7f00\">❷</text>\n",
"</g>\n", "</g>\n",
"<!-- 7 -->\n", "<!-- 7 -->\n",
"<g id=\"node7\" class=\"node\">\n", "<g id=\"node7\" class=\"node\">\n",
@ -818,7 +818,7 @@
"<path fill=\"none\" stroke=\"black\" d=\"M458.24,-70.56C474.17,-60.06 499.65,-43.25 516.75,-31.98\"/>\n", "<path fill=\"none\" stroke=\"black\" d=\"M458.24,-70.56C474.17,-60.06 499.65,-43.25 516.75,-31.98\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"522.63,-28.09 518.52,-34.58 519.71,-30.02 516.79,-31.95 516.79,-31.95 516.79,-31.95 519.71,-30.02 515.06,-29.32 522.63,-28.09 522.63,-28.09\"/>\n", "<polygon fill=\"black\" stroke=\"black\" points=\"522.63,-28.09 518.52,-34.58 519.71,-30.02 516.79,-31.95 516.79,-31.95 516.79,-31.95 519.71,-30.02 515.06,-29.32 522.63,-28.09 522.63,-28.09\"/>\n",
"<text text-anchor=\"start\" x=\"481.12\" y=\"-75\" font-family=\"Lato\" font-size=\"14.00\">!a</text>\n", "<text text-anchor=\"start\" x=\"481.12\" y=\"-75\" font-family=\"Lato\" font-size=\"14.00\">!a</text>\n",
"<text text-anchor=\"start\" x=\"478.62\" y=\"-60\" font-family=\"Lato\" font-size=\"14.00\" fill=\"#ff4da0\">❶</text>\n", "<text text-anchor=\"start\" x=\"478.62\" y=\"-60\" font-family=\"Lato\" font-size=\"14.00\" fill=\"#ff7f00\">❷</text>\n",
"</g>\n", "</g>\n",
"<!-- 7&#45;&gt;0 -->\n", "<!-- 7&#45;&gt;0 -->\n",
"<g id=\"edge12\" class=\"edge\">\n", "<g id=\"edge12\" class=\"edge\">\n",
@ -928,7 +928,7 @@
"</svg>\n" "</svg>\n"
], ],
"text/plain": [ "text/plain": [
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7f80642eee70> >" "<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7f202420db10> >"
] ]
}, },
"execution_count": 8, "execution_count": 8,
@ -972,10 +972,10 @@
"--BODY--\n", "--BODY--\n",
"State: 0\n", "State: 0\n",
"[!1] 5 {1}\n", "[!1] 5 {1}\n",
"[1] 6 {1}\n", "[1] 6 {2}\n",
"State: 1\n", "State: 1\n",
"[1] 6 {1}\n", "[1] 6 {2}\n",
"[!1] 7 {1}\n", "[!1] 7 {2}\n",
"State: 2\n", "State: 2\n",
"[t] 8 {1}\n", "[t] 8 {1}\n",
"State: 3\n", "State: 3\n",
@ -1134,7 +1134,7 @@
"<path fill=\"none\" stroke=\"#e31a1c\" stroke-width=\"2\" d=\"M263.84,-69.53C269.36,-57.32 278.74,-41.62 292.66,-34.2 305.05,-27.61 320.17,-33.47 331.57,-40.37\"/>\n", "<path fill=\"none\" stroke=\"#e31a1c\" stroke-width=\"2\" d=\"M263.84,-69.53C269.36,-57.32 278.74,-41.62 292.66,-34.2 305.05,-27.61 320.17,-33.47 331.57,-40.37\"/>\n",
"<polygon fill=\"#e31a1c\" stroke=\"#e31a1c\" stroke-width=\"2\" points=\"337.48,-44.24 329.9,-43.04 334.28,-42.74 331.35,-40.83 331.62,-40.41 331.9,-39.99 334.82,-41.9 333.35,-37.77 337.48,-44.24 337.48,-44.24\"/>\n", "<polygon fill=\"#e31a1c\" stroke=\"#e31a1c\" stroke-width=\"2\" points=\"337.48,-44.24 329.9,-43.04 334.28,-42.74 331.35,-40.83 331.62,-40.41 331.9,-39.99 334.82,-41.9 333.35,-37.77 337.48,-44.24 337.48,-44.24\"/>\n",
"<text text-anchor=\"start\" x=\"297.16\" y=\"-53\" font-family=\"Lato\" font-size=\"14.00\">a</text>\n", "<text text-anchor=\"start\" x=\"297.16\" y=\"-53\" font-family=\"Lato\" font-size=\"14.00\">a</text>\n",
"<text text-anchor=\"start\" x=\"292.66\" y=\"-38\" font-family=\"Lato\" font-size=\"14.00\" fill=\"#ff4da0\">❶</text>\n", "<text text-anchor=\"start\" x=\"292.66\" y=\"-38\" font-family=\"Lato\" font-size=\"14.00\" fill=\"#ff7f00\">❷</text>\n",
"</g>\n", "</g>\n",
"<!-- 5&#45;&gt;0 -->\n", "<!-- 5&#45;&gt;0 -->\n",
"<g id=\"edge10\" class=\"edge\">\n", "<g id=\"edge10\" class=\"edge\">\n",
@ -1164,7 +1164,7 @@
"<path fill=\"none\" stroke=\"#e31a1c\" stroke-width=\"2\" d=\"M429.13,-67.92C422.9,-62.64 414.93,-57.03 406.62,-54.2 397.16,-50.98 386.28,-50.18 376.63,-50.39\"/>\n", "<path fill=\"none\" stroke=\"#e31a1c\" stroke-width=\"2\" d=\"M429.13,-67.92C422.9,-62.64 414.93,-57.03 406.62,-54.2 397.16,-50.98 386.28,-50.18 376.63,-50.39\"/>\n",
"<polygon fill=\"#e31a1c\" stroke=\"#e31a1c\" stroke-width=\"2\" points=\"369.54,-50.71 376.39,-47.24 373.02,-50.05 376.51,-49.89 376.53,-50.39 376.56,-50.89 373.06,-51.05 376.68,-53.54 369.54,-50.71 369.54,-50.71\"/>\n", "<polygon fill=\"#e31a1c\" stroke=\"#e31a1c\" stroke-width=\"2\" points=\"369.54,-50.71 376.39,-47.24 373.02,-50.05 376.51,-49.89 376.53,-50.39 376.56,-50.89 373.06,-51.05 376.68,-53.54 369.54,-50.71 369.54,-50.71\"/>\n",
"<text text-anchor=\"start\" x=\"395.12\" y=\"-73\" font-family=\"Lato\" font-size=\"14.00\">a</text>\n", "<text text-anchor=\"start\" x=\"395.12\" y=\"-73\" font-family=\"Lato\" font-size=\"14.00\">a</text>\n",
"<text text-anchor=\"start\" x=\"390.62\" y=\"-58\" font-family=\"Lato\" font-size=\"14.00\" fill=\"#ff4da0\">❶</text>\n", "<text text-anchor=\"start\" x=\"390.62\" y=\"-58\" font-family=\"Lato\" font-size=\"14.00\" fill=\"#ff7f00\">❷</text>\n",
"</g>\n", "</g>\n",
"<!-- 7 -->\n", "<!-- 7 -->\n",
"<g id=\"node7\" class=\"node\">\n", "<g id=\"node7\" class=\"node\">\n",
@ -1178,7 +1178,7 @@
"<path fill=\"none\" stroke=\"black\" d=\"M458.24,-70.56C474.17,-60.06 499.65,-43.25 516.75,-31.98\"/>\n", "<path fill=\"none\" stroke=\"black\" d=\"M458.24,-70.56C474.17,-60.06 499.65,-43.25 516.75,-31.98\"/>\n",
"<polygon fill=\"black\" stroke=\"black\" points=\"522.63,-28.09 518.52,-34.58 519.71,-30.02 516.79,-31.95 516.79,-31.95 516.79,-31.95 519.71,-30.02 515.06,-29.32 522.63,-28.09 522.63,-28.09\"/>\n", "<polygon fill=\"black\" stroke=\"black\" points=\"522.63,-28.09 518.52,-34.58 519.71,-30.02 516.79,-31.95 516.79,-31.95 516.79,-31.95 519.71,-30.02 515.06,-29.32 522.63,-28.09 522.63,-28.09\"/>\n",
"<text text-anchor=\"start\" x=\"481.12\" y=\"-75\" font-family=\"Lato\" font-size=\"14.00\">!a</text>\n", "<text text-anchor=\"start\" x=\"481.12\" y=\"-75\" font-family=\"Lato\" font-size=\"14.00\">!a</text>\n",
"<text text-anchor=\"start\" x=\"478.62\" y=\"-60\" font-family=\"Lato\" font-size=\"14.00\" fill=\"#ff4da0\">❶</text>\n", "<text text-anchor=\"start\" x=\"478.62\" y=\"-60\" font-family=\"Lato\" font-size=\"14.00\" fill=\"#ff7f00\">❷</text>\n",
"</g>\n", "</g>\n",
"<!-- 7&#45;&gt;0 -->\n", "<!-- 7&#45;&gt;0 -->\n",
"<g id=\"edge12\" class=\"edge\">\n", "<g id=\"edge12\" class=\"edge\">\n",
@ -1288,7 +1288,7 @@
"</svg>\n" "</svg>\n"
], ],
"text/plain": [ "text/plain": [
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7f806443b1b0> >" "<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7f202420df90> >"
] ]
}, },
"execution_count": 11, "execution_count": 11,
@ -1324,7 +1324,7 @@
"name": "python", "name": "python",
"nbconvert_exporter": "python", "nbconvert_exporter": "python",
"pygments_lexer": "ipython3", "pygments_lexer": "ipython3",
"version": "3.9.2" "version": "3.8.10"
} }
}, },
"nbformat": 4, "nbformat": 4,

File diff suppressed because it is too large Load diff

View file

@ -37,16 +37,16 @@ Start: 0
AP: 1 "a" AP: 1 "a"
acc-name: Streett 1 acc-name: Streett 1
Acceptance: 2 Fin(0) | Inf(1) Acceptance: 2 Fin(0) | Inf(1)
properties: trans-labels explicit-labels state-acc colored complete properties: trans-labels explicit-labels trans-acc colored complete
properties: deterministic properties: deterministic
spot-state-player: 0 1 1 spot-state-player: 0 1 1
controllable-AP: controllable-AP:
--BODY-- --BODY--
State: 0 {0} State: 0
[!0] 1 [!0] 1 {0}
[0] 2 [0] 2 {1}
State: 1 {0} State: 1
[t] 0 [t] 0 {0}
State: 2 {1} State: 2
[t] 0 [t] 0 {1}
--END--""") --END--""")