game: rewrite, document, and rename solve_reachability_game
* spot/twaalgos/game.hh, spot/twaalgos/game.cc: Rename solve_reachability_game() as solve_safety_game(), rewrite it (the old implementation incorrectly marked dead states as winning for their owner). * tests/python/paritygame.ipynb: Rename as... * tests/python/games.ipynb: ... this, and illustrate solve_safety_game(). * tests/Makefile.am, NEWS, doc/org/tut.org: Adjust. * tests/python/except.py: Add more tests.
This commit is contained in:
parent
05449a42d3
commit
9a17f5676c
7 changed files with 784 additions and 87 deletions
4
NEWS
4
NEWS
|
|
@ -148,8 +148,8 @@ New in spot 2.9.5.dev (not yet released)
|
|||
|
||||
Python:
|
||||
|
||||
- Bindings for functions related to parity games.
|
||||
See https://spot.lrde.epita.fr/ipynb/paritygame.html for examples.
|
||||
- Bindings for functions related to games.
|
||||
See https://spot.lrde.epita.fr/ipynb/games.html for examples.
|
||||
|
||||
Bugs fixed:
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ real notebooks instead.
|
|||
automata
|
||||
- [[https://spot.lrde.epita.fr/ipynb/parity.html][=parity.ipynb=]] documents algorithms for manipulating parity automata
|
||||
in Python
|
||||
- [[https://spot.lrde.epita.fr/ipynb/paritygame.html][=paritygame.ipynb=]] illustrates support for parity games
|
||||
- [[https://spot.lrde.epita.fr/ipynb/games.html][=games.ipynb=]] illustrates support for games
|
||||
- [[https://spot.lrde.epita.fr/ipynb/product.html][=product.ipynb=]] shows how to re-implement the product of two automata
|
||||
in Python
|
||||
- [[https://spot.lrde.epita.fr/ipynb/randltl.html][=randltl.ipynb=]] demonstrates a Python-version of [[file:randltl.org][=randltl=]]
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <spot/twaalgos/game.hh>
|
||||
#include <spot/misc/bddlt.hh>
|
||||
#include <spot/twaalgos/sccinfo.hh>
|
||||
|
|
@ -958,52 +957,90 @@ namespace spot
|
|||
return (*owners)[state] ? 1 : 0;
|
||||
}
|
||||
|
||||
bool solve_reachability_game(twa_graph_ptr game)
|
||||
bool solve_safety_game(twa_graph_ptr game)
|
||||
{
|
||||
if (!game->acc().is_t())
|
||||
throw std::runtime_error
|
||||
("solve_safety_game(): arena should have true acceptance");
|
||||
|
||||
auto owners = get_state_players(game);
|
||||
|
||||
auto winners = new region_t(game->num_states(), true);
|
||||
unsigned ns = game->num_states();
|
||||
auto winners = new region_t(ns, true);
|
||||
game->set_named_prop("state-winner", winners);
|
||||
auto strategy = new strategy_t(game->num_states(), 0);
|
||||
auto strategy = new strategy_t(ns, 0);
|
||||
game->set_named_prop("strategy", strategy);
|
||||
|
||||
std::vector<bool> seen(game->num_states(), false);
|
||||
std::vector<unsigned> todo;
|
||||
todo.reserve(game->num_states());
|
||||
|
||||
auto& g = game->get_graph();
|
||||
todo.push_back(game->get_init_state_number());
|
||||
|
||||
while (!todo.empty())
|
||||
// transposed is a reversed copy of game to compute predecessors
|
||||
// more easily. It also keep track of the original edge iindex.
|
||||
struct edge_data {
|
||||
unsigned edgeidx;
|
||||
};
|
||||
digraph<void, edge_data> transposed;
|
||||
// Reverse the automaton, compute the out degree of
|
||||
// each state, and save dead-states in queue.
|
||||
transposed.new_states(ns);
|
||||
std::vector<unsigned> out_degree;
|
||||
out_degree.reserve(ns);
|
||||
std::vector<unsigned> queue;
|
||||
for (unsigned s = 0; s < ns; ++s)
|
||||
{
|
||||
unsigned cur = todo.back();
|
||||
auto edges = game->out(cur);
|
||||
|
||||
if (!seen[cur])
|
||||
unsigned deg = 0;
|
||||
for (auto& e: game->out(s))
|
||||
{
|
||||
for (const auto& e : edges)
|
||||
todo.push_back(e.dst);
|
||||
seen[cur] = true;
|
||||
transposed.new_edge(e.dst, e.src, game->edge_number(e));
|
||||
++deg;
|
||||
}
|
||||
else
|
||||
out_degree.push_back(deg);
|
||||
if (deg == 0)
|
||||
{
|
||||
todo.pop_back();
|
||||
bool player = owners[cur];
|
||||
|
||||
auto it = std::find_if(edges.begin(), edges.end(),
|
||||
[&winners, player](auto& e)
|
||||
{
|
||||
return (*winners)[e.dst] == player;
|
||||
});
|
||||
|
||||
if (it != edges.end())
|
||||
{
|
||||
(*strategy)[cur] = g.index_of_edge(*it);
|
||||
(*winners)[cur] = player;
|
||||
(*winners)[s] = false;
|
||||
queue.push_back(s);
|
||||
}
|
||||
else
|
||||
(*winners)[cur] = !player;
|
||||
}
|
||||
// queue is initially filled with dead-states, which are winning
|
||||
// for player 0. Any predecessor owned by player 0 is therefore
|
||||
// winning as well (check 1), and any predecessor owned by player
|
||||
// 1 that has all its successors winning for player 0 (check 2) is
|
||||
// also winning. Use queue to propagate everything.
|
||||
// For the second check, we decrease out_degree by each edge leading
|
||||
// to a state winning for player 0, so if out_degree reaches 0,
|
||||
// we have ensured that all outgoing transitions are winning for 0.
|
||||
//
|
||||
// We use queue as a stack, to propagate bad states in DFS.
|
||||
// However it would be ok to replace the vector by a std::deque
|
||||
// to implement a BFS and build shorter strategies for player 0.
|
||||
// Right no we are assuming that strategies for player 0 have
|
||||
// limited uses, so we just avoid the overhead of std::deque in
|
||||
// favor of the simpler std::vector.
|
||||
while (!queue.empty())
|
||||
{
|
||||
unsigned s = queue.back();
|
||||
queue.pop_back();
|
||||
for (auto& e: transposed.out(s))
|
||||
{
|
||||
unsigned pred = e.dst;
|
||||
if (!(*winners)[pred])
|
||||
continue;
|
||||
// check 1 || check 2
|
||||
bool check1 = owners[pred] == false;
|
||||
if (check1 || --out_degree[pred] == 0)
|
||||
{
|
||||
(*winners)[pred] = false;
|
||||
queue.push_back(pred);
|
||||
if (check1)
|
||||
(*strategy)[pred] = e.edgeidx;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Let's fill in the strategy for Player 1.
|
||||
for (unsigned s = 0; s < ns; ++s)
|
||||
if (owners[s] && (*winners)[s])
|
||||
for (auto& e: game->out(s))
|
||||
if ((*winners)[e.dst])
|
||||
{
|
||||
(*strategy)[s] = game->edge_number(e);
|
||||
break;
|
||||
}
|
||||
|
||||
return (*winners)[game->get_init_state_number()];
|
||||
|
|
|
|||
|
|
@ -58,9 +58,11 @@ namespace spot
|
|||
/// The arena is a deterministic max odd parity automaton with a
|
||||
/// "state-player" property.
|
||||
///
|
||||
/// This computes the winning strategy and winning region of this
|
||||
/// game for player 1 using Zielonka's recursive algorithm.
|
||||
/// \cite zielonka.98.tcs
|
||||
/// Player 1 tries to satisfy the acceptance condition, while player
|
||||
/// 0 tries to prevent that.
|
||||
///
|
||||
/// This computes the winning strategy and winning region using
|
||||
/// Zielonka's recursive algorithm. \cite zielonka.98.tcs
|
||||
///
|
||||
/// Also includes some inspiration from Oink.
|
||||
/// \cite vandijk.18.tacas
|
||||
|
|
@ -70,6 +72,22 @@ namespace spot
|
|||
SPOT_API
|
||||
bool solve_parity_game(const twa_graph_ptr& arena);
|
||||
|
||||
/// \brief Solve a safety game.
|
||||
///
|
||||
/// The arena should be represented by an automaton with true
|
||||
/// acceptance.
|
||||
///
|
||||
/// Player 1 tries to satisfy the acceptance condition, while player
|
||||
/// 0 tries to prevent that. The only way for player 0 to win is
|
||||
/// to find a way to move the play toward a state without successor.
|
||||
/// If there no state without successors, then the game is necessarily
|
||||
/// winning for player 1.
|
||||
///
|
||||
/// Returns the player winning in the initial state, and sets
|
||||
/// the state-winner and strategy named properties.
|
||||
SPOT_API
|
||||
bool solve_safety_game(twa_graph_ptr game);
|
||||
|
||||
/// \brief Print a max odd parity game using PG-solver syntax
|
||||
SPOT_API
|
||||
void pg_print(std::ostream& os, const const_twa_graph_ptr& arena);
|
||||
|
|
@ -100,8 +118,4 @@ namespace spot
|
|||
/// \brief Get the owner of a state.
|
||||
SPOT_API
|
||||
unsigned get_state_player(const_twa_graph_ptr arena, unsigned state);
|
||||
|
||||
/// \brief Solve a reachability game.
|
||||
SPOT_API
|
||||
bool solve_reachability_game(twa_graph_ptr game);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -357,12 +357,12 @@ TESTS_ipython = \
|
|||
python/contains.ipynb \
|
||||
python/decompose.ipynb \
|
||||
python/formulas.ipynb \
|
||||
python/games.ipynb \
|
||||
python/gen.ipynb \
|
||||
python/highlighting.ipynb \
|
||||
python/ltsmin-dve.ipynb \
|
||||
python/ltsmin-pml.ipynb \
|
||||
python/parity.ipynb \
|
||||
python/paritygame.ipynb \
|
||||
python/product.ipynb \
|
||||
python/randaut.ipynb \
|
||||
python/randltl.ipynb \
|
||||
|
|
|
|||
|
|
@ -196,24 +196,39 @@ assert spot.is_deterministic(a2)
|
|||
try:
|
||||
spot.product_xor(a1, a2)
|
||||
except RuntimeError as e:
|
||||
assert "product_xor() only works with deterministic automata"
|
||||
assert "product_xor() only works with deterministic automata" in str(e)
|
||||
else:
|
||||
report_missing_exception()
|
||||
try:
|
||||
spot.product_xor(a2, a1)
|
||||
except RuntimeError as e:
|
||||
assert "product_xor() only works with deterministic automata"
|
||||
assert "product_xor() only works with deterministic automata" in str(e)
|
||||
else:
|
||||
report_missing_exception()
|
||||
try:
|
||||
spot.product_xnor(a1, a2)
|
||||
except RuntimeError as e:
|
||||
assert "product_xnor() only works with deterministic automata"
|
||||
assert "product_xnor() only works with deterministic automata" in str(e)
|
||||
else:
|
||||
report_missing_exception()
|
||||
try:
|
||||
spot.product_xnor(a2, a1)
|
||||
except RuntimeError as e:
|
||||
assert "product_xnor() only works with deterministic automata"
|
||||
assert "product_xnor() only works with deterministic automata" in str(e)
|
||||
else:
|
||||
report_missing_exception()
|
||||
|
||||
try:
|
||||
spot.solve_safety_game(a1)
|
||||
except RuntimeError as e:
|
||||
assert "solve_safety_game(): arena should have true acceptance" in str(e)
|
||||
else:
|
||||
report_missing_exception()
|
||||
|
||||
try:
|
||||
spot.solve_parity_game(a1)
|
||||
except RuntimeError as e:
|
||||
assert "solve_parity_game(): arena must have max-odd acceptance condition" \
|
||||
in str(e)
|
||||
else:
|
||||
report_missing_exception()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
"outputs": [],
|
||||
"source": [
|
||||
"import spot\n",
|
||||
"from buddy import bddtrue\n",
|
||||
"spot.setup()"
|
||||
]
|
||||
},
|
||||
|
|
@ -14,14 +15,653 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Support for parity games\n",
|
||||
"# Support for games\n",
|
||||
"\n",
|
||||
"The support for parity games is currently quite rudimentary, as Spot currently only uses those games in `ltlsynt`.\n",
|
||||
"The support for games is currently quite rudimentary, as Spot currently only uses those games in `ltlsynt`.\n",
|
||||
"\n",
|
||||
"In essence, a parity game is just a parity automaton with a property named `state-player` that stores the player owning each state. The players are named 0 and 1.\n",
|
||||
"In essence, agame is just an ω-automaton with a property named `state-player` that stores the player owning each state. The players are named 0 and 1. The player owning a state can decide what the next transition from this state should be. The goal for player 1 is to force the play to be infinite and to satisfy the acceptance condition of the automaton, while the goal for player 0 is to prevent it by either forcing a finite play, or forcing an infinite play that does not satisfy the acceptance condition.\n",
|
||||
"\n",
|
||||
"Player 1 is winning if it has a strategy to satisfy the acceptance condition regardless of player 0's moves.\n",
|
||||
"Player 0 is winning if it has a strategy to not satisfy the acceptance codition regardless of player 1's moves."
|
||||
"The support is currently restricted to games that use:\n",
|
||||
"- `t` acceptance: all infinite run are accepting, and player 0 can only win if it manages to force a finite play (this requires reaching states without successors).\n",
|
||||
"- max odd parity acceptance: player 0 can win if the maximal value seen infinitely often is even"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Creating games from scratch\n",
|
||||
"\n",
|
||||
"Games can be [created like any automaton](https://spot.lrde.epita.fr/tut22.html). \n",
|
||||
"Using `set_state_players()` will fix the state owners."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/svg+xml": [
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
|
||||
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
|
||||
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
|
||||
"<!-- Generated by graphviz version 2.43.0 (0)\n",
|
||||
" -->\n",
|
||||
"<!-- Pages: 1 -->\n",
|
||||
"<svg width=\"495pt\" height=\"190pt\"\n",
|
||||
" viewBox=\"0.00 0.00 495.00 190.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
|
||||
"<g id=\"graph0\" class=\"graph\" transform=\"scale(1.0 1.0) rotate(0) translate(4 186)\">\n",
|
||||
"<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-186 491,-186 491,4 -4,4\"/>\n",
|
||||
"<text text-anchor=\"start\" x=\"240.5\" y=\"-166.8\" font-family=\"Lato\" font-size=\"14.00\">t</text>\n",
|
||||
"<text text-anchor=\"start\" x=\"232.5\" y=\"-151.8\" font-family=\"Lato\" font-size=\"14.00\">[all]</text>\n",
|
||||
"<!-- I -->\n",
|
||||
"<!-- 0 -->\n",
|
||||
"<g id=\"node2\" class=\"node\">\n",
|
||||
"<title>0</title>\n",
|
||||
"<polygon fill=\"#ffffaa\" stroke=\"black\" points=\"64,-144 37,-126 64,-108 91,-126 64,-144\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"64\" y=\"-122.3\" font-family=\"Lato\" font-size=\"14.00\">0</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- I->0 -->\n",
|
||||
"<g id=\"edge1\" class=\"edge\">\n",
|
||||
"<title>I->0</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M1.04,-126C1.93,-126 15.66,-126 29.98,-126\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"37,-126 30,-129.15 33.5,-126 30,-126 30,-126 30,-126 33.5,-126 30,-122.85 37,-126 37,-126\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 1 -->\n",
|
||||
"<g id=\"node3\" class=\"node\">\n",
|
||||
"<title>1</title>\n",
|
||||
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"145\" cy=\"-126\" rx=\"18\" ry=\"18\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"145\" y=\"-122.3\" font-family=\"Lato\" font-size=\"14.00\">1</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 0->1 -->\n",
|
||||
"<g id=\"edge2\" class=\"edge\">\n",
|
||||
"<title>0->1</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M82.53,-120.28C93.75,-119.1 108.43,-118.93 120.64,-119.78\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"127.86,-120.43 120.61,-122.94 124.38,-120.12 120.89,-119.8 120.89,-119.8 120.89,-119.8 124.38,-120.12 121.17,-116.66 127.86,-120.43 127.86,-120.43\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 3 -->\n",
|
||||
"<g id=\"node4\" class=\"node\">\n",
|
||||
"<title>3</title>\n",
|
||||
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"145\" cy=\"-72\" rx=\"18\" ry=\"18\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"145\" y=\"-68.3\" font-family=\"Lato\" font-size=\"14.00\">3</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 0->3 -->\n",
|
||||
"<g id=\"edge3\" class=\"edge\">\n",
|
||||
"<title>0->3</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M78.05,-117.08C90.47,-108.59 109.36,-95.68 123.74,-85.85\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"129.6,-81.85 125.59,-88.4 126.71,-83.82 123.82,-85.8 123.82,-85.8 123.82,-85.8 126.71,-83.82 122.04,-83.2 129.6,-81.85 129.6,-81.85\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 1->0 -->\n",
|
||||
"<g id=\"edge4\" class=\"edge\">\n",
|
||||
"<title>1->0</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M127.86,-131.57C116.84,-132.84 102.04,-133.09 89.56,-132.3\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"82.53,-131.72 89.77,-129.16 86.02,-132.01 89.51,-132.3 89.51,-132.3 89.51,-132.3 86.02,-132.01 89.25,-135.44 82.53,-131.72 82.53,-131.72\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 2 -->\n",
|
||||
"<g id=\"node5\" class=\"node\">\n",
|
||||
"<title>2</title>\n",
|
||||
"<polygon fill=\"#ffffaa\" stroke=\"black\" points=\"226,-144 199,-126 226,-108 253,-126 226,-144\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"226\" y=\"-122.3\" font-family=\"Lato\" font-size=\"14.00\">2</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 1->2 -->\n",
|
||||
"<g id=\"edge5\" class=\"edge\">\n",
|
||||
"<title>1->2</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M162.37,-120.41C173.4,-119.15 188.15,-118.92 200.56,-119.71\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"207.56,-120.29 200.32,-122.85 204.07,-120 200.58,-119.71 200.58,-119.71 200.58,-119.71 204.07,-120 200.84,-116.57 207.56,-120.29 207.56,-120.29\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 3->2 -->\n",
|
||||
"<g id=\"edge8\" class=\"edge\">\n",
|
||||
"<title>3->2</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M160.49,-81.9C173.24,-90.62 191.89,-103.37 205.86,-112.92\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"211.91,-117.05 204.36,-115.7 209.02,-115.08 206.13,-113.1 206.13,-113.1 206.13,-113.1 209.02,-115.08 207.91,-110.5 211.91,-117.05 211.91,-117.05\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 4 -->\n",
|
||||
"<g id=\"node7\" class=\"node\">\n",
|
||||
"<title>4</title>\n",
|
||||
"<polygon fill=\"#ffffaa\" stroke=\"black\" points=\"226,-90 199,-72 226,-54 253,-72 226,-90\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"226\" y=\"-68.3\" font-family=\"Lato\" font-size=\"14.00\">4</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 3->4 -->\n",
|
||||
"<g id=\"edge9\" class=\"edge\">\n",
|
||||
"<title>3->4</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M163.14,-72C171.54,-72 181.95,-72 191.82,-72\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"198.87,-72 191.87,-75.15 195.37,-72 191.87,-72 191.87,-72 191.87,-72 195.37,-72 191.87,-68.85 198.87,-72 198.87,-72\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 6 -->\n",
|
||||
"<g id=\"node8\" class=\"node\">\n",
|
||||
"<title>6</title>\n",
|
||||
"<polygon fill=\"#ffffaa\" stroke=\"black\" points=\"226,-36 199,-18 226,0 253,-18 226,-36\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"226\" y=\"-14.3\" font-family=\"Lato\" font-size=\"14.00\">6</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 3->6 -->\n",
|
||||
"<g id=\"edge10\" class=\"edge\">\n",
|
||||
"<title>3->6</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M160.49,-62.1C173.24,-53.38 191.89,-40.63 205.86,-31.08\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"211.91,-26.95 207.91,-33.5 209.02,-28.92 206.13,-30.9 206.13,-30.9 206.13,-30.9 209.02,-28.92 204.36,-28.3 211.91,-26.95 211.91,-26.95\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 2->1 -->\n",
|
||||
"<g id=\"edge6\" class=\"edge\">\n",
|
||||
"<title>2->1</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M207.56,-131.71C196.4,-132.89 181.78,-133.07 169.59,-132.24\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"162.37,-131.59 169.62,-129.08 165.85,-131.9 169.34,-132.22 169.34,-132.22 169.34,-132.22 165.85,-131.9 169.06,-135.35 162.37,-131.59 162.37,-131.59\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 5 -->\n",
|
||||
"<g id=\"node6\" class=\"node\">\n",
|
||||
"<title>5</title>\n",
|
||||
"<polygon fill=\"#ffffaa\" stroke=\"black\" points=\"460,-90 433,-72 460,-54 487,-72 460,-90\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"460\" y=\"-68.3\" font-family=\"Lato\" font-size=\"14.00\">5</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 2->5 -->\n",
|
||||
"<g id=\"edge7\" class=\"edge\">\n",
|
||||
"<title>2->5</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M246.38,-121.49C287.92,-111.82 385.57,-89.09 432.67,-78.13\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"439.51,-76.54 433.41,-81.19 436.1,-77.33 432.69,-78.12 432.69,-78.12 432.69,-78.12 436.1,-77.33 431.98,-75.06 439.51,-76.54 439.51,-76.54\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 7 -->\n",
|
||||
"<g id=\"node9\" class=\"node\">\n",
|
||||
"<title>7</title>\n",
|
||||
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"307\" cy=\"-18\" rx=\"18\" ry=\"18\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"307\" y=\"-14.3\" font-family=\"Lato\" font-size=\"14.00\">7</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 6->7 -->\n",
|
||||
"<g id=\"edge11\" class=\"edge\">\n",
|
||||
"<title>6->7</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M244.53,-12.28C255.75,-11.1 270.43,-10.93 282.64,-11.78\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"289.86,-12.43 282.61,-14.94 286.38,-12.12 282.89,-11.8 282.89,-11.8 282.89,-11.8 286.38,-12.12 283.17,-8.66 289.86,-12.43 289.86,-12.43\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 7->6 -->\n",
|
||||
"<g id=\"edge12\" class=\"edge\">\n",
|
||||
"<title>7->6</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M289.86,-23.57C278.84,-24.84 264.04,-25.09 251.56,-24.3\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"244.53,-23.72 251.77,-21.16 248.02,-24.01 251.51,-24.3 251.51,-24.3 251.51,-24.3 248.02,-24.01 251.25,-27.44 244.53,-23.72 244.53,-23.72\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 8 -->\n",
|
||||
"<g id=\"node10\" class=\"node\">\n",
|
||||
"<title>8</title>\n",
|
||||
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"379\" cy=\"-49\" rx=\"18\" ry=\"18\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"379\" y=\"-45.3\" font-family=\"Lato\" font-size=\"14.00\">8</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 7->8 -->\n",
|
||||
"<g id=\"edge13\" class=\"edge\">\n",
|
||||
"<title>7->8</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M323.88,-25.03C333.28,-29.2 345.33,-34.53 355.67,-39.11\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"362.18,-41.99 354.5,-42.04 358.98,-40.58 355.78,-39.16 355.78,-39.16 355.78,-39.16 358.98,-40.58 357.05,-36.28 362.18,-41.99 362.18,-41.99\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 8->5 -->\n",
|
||||
"<g id=\"edge14\" class=\"edge\">\n",
|
||||
"<title>8->5</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M396.37,-53.77C407.17,-56.91 421.54,-61.1 433.79,-64.66\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"440.72,-66.68 433.12,-67.75 437.36,-65.7 434,-64.72 434,-64.72 434,-64.72 437.36,-65.7 434.88,-61.7 440.72,-66.68 440.72,-66.68\"/>\n",
|
||||
"</g>\n",
|
||||
"</g>\n",
|
||||
"</svg>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<spot.jupyter.SVG object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"bdict = spot.make_bdd_dict();\n",
|
||||
"game = spot.make_twa_graph(bdict)\n",
|
||||
"game.new_states(9)\n",
|
||||
"for (s, d) in ((0,1), (0, 3), \n",
|
||||
" (1, 0), (1, 2),\n",
|
||||
" (2, 1), (2, 5),\n",
|
||||
" (3, 2), (3, 4), (3, 6),\n",
|
||||
" (6, 7),\n",
|
||||
" (7, 6), (7, 8),\n",
|
||||
" (8, 5)):\n",
|
||||
" game.new_edge(s, d, bddtrue)\n",
|
||||
"spot.set_state_players(game, [True, False, True, False, True, True, True, False, False])\n",
|
||||
"game.show('.g') # Use \"g\" to hide the irrelevant edge labels."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The `set_state_players()` function takes a list of owner for each of the states in the automaton. In the output,\n",
|
||||
"states from player 0 use circles, ellispes, or rectangle with rounded corners (mnemonic: 0 is round) while states from player 1 have a losanse shape (1 has only straight lines). \n",
|
||||
"\n",
|
||||
"\n",
|
||||
"State ownership can also be manipulated by the following functions:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"(True, False, True, False, True, True, True, False, False)"
|
||||
]
|
||||
},
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"spot.get_state_players(game)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"1"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"spot.get_state_player(game, 4)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/svg+xml": [
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
|
||||
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
|
||||
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
|
||||
"<!-- Generated by graphviz version 2.43.0 (0)\n",
|
||||
" -->\n",
|
||||
"<!-- Pages: 1 -->\n",
|
||||
"<svg width=\"495pt\" height=\"190pt\"\n",
|
||||
" viewBox=\"0.00 0.00 495.00 190.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
|
||||
"<g id=\"graph0\" class=\"graph\" transform=\"scale(1.0 1.0) rotate(0) translate(4 186)\">\n",
|
||||
"<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-186 491,-186 491,4 -4,4\"/>\n",
|
||||
"<text text-anchor=\"start\" x=\"240.5\" y=\"-166.8\" font-family=\"Lato\" font-size=\"14.00\">t</text>\n",
|
||||
"<text text-anchor=\"start\" x=\"232.5\" y=\"-151.8\" font-family=\"Lato\" font-size=\"14.00\">[all]</text>\n",
|
||||
"<!-- I -->\n",
|
||||
"<!-- 0 -->\n",
|
||||
"<g id=\"node2\" class=\"node\">\n",
|
||||
"<title>0</title>\n",
|
||||
"<polygon fill=\"#ffffaa\" stroke=\"black\" points=\"64,-144 37,-126 64,-108 91,-126 64,-144\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"64\" y=\"-122.3\" font-family=\"Lato\" font-size=\"14.00\">0</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- I->0 -->\n",
|
||||
"<g id=\"edge1\" class=\"edge\">\n",
|
||||
"<title>I->0</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M1.04,-126C1.93,-126 15.66,-126 29.98,-126\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"37,-126 30,-129.15 33.5,-126 30,-126 30,-126 30,-126 33.5,-126 30,-122.85 37,-126 37,-126\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 1 -->\n",
|
||||
"<g id=\"node3\" class=\"node\">\n",
|
||||
"<title>1</title>\n",
|
||||
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"145\" cy=\"-126\" rx=\"18\" ry=\"18\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"145\" y=\"-122.3\" font-family=\"Lato\" font-size=\"14.00\">1</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 0->1 -->\n",
|
||||
"<g id=\"edge2\" class=\"edge\">\n",
|
||||
"<title>0->1</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M82.53,-120.28C93.75,-119.1 108.43,-118.93 120.64,-119.78\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"127.86,-120.43 120.61,-122.94 124.38,-120.12 120.89,-119.8 120.89,-119.8 120.89,-119.8 124.38,-120.12 121.17,-116.66 127.86,-120.43 127.86,-120.43\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 3 -->\n",
|
||||
"<g id=\"node4\" class=\"node\">\n",
|
||||
"<title>3</title>\n",
|
||||
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"145\" cy=\"-72\" rx=\"18\" ry=\"18\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"145\" y=\"-68.3\" font-family=\"Lato\" font-size=\"14.00\">3</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 0->3 -->\n",
|
||||
"<g id=\"edge3\" class=\"edge\">\n",
|
||||
"<title>0->3</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M78.05,-117.08C90.47,-108.59 109.36,-95.68 123.74,-85.85\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"129.6,-81.85 125.59,-88.4 126.71,-83.82 123.82,-85.8 123.82,-85.8 123.82,-85.8 126.71,-83.82 122.04,-83.2 129.6,-81.85 129.6,-81.85\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 1->0 -->\n",
|
||||
"<g id=\"edge4\" class=\"edge\">\n",
|
||||
"<title>1->0</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M127.86,-131.57C116.84,-132.84 102.04,-133.09 89.56,-132.3\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"82.53,-131.72 89.77,-129.16 86.02,-132.01 89.51,-132.3 89.51,-132.3 89.51,-132.3 86.02,-132.01 89.25,-135.44 82.53,-131.72 82.53,-131.72\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 2 -->\n",
|
||||
"<g id=\"node5\" class=\"node\">\n",
|
||||
"<title>2</title>\n",
|
||||
"<polygon fill=\"#ffffaa\" stroke=\"black\" points=\"226,-144 199,-126 226,-108 253,-126 226,-144\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"226\" y=\"-122.3\" font-family=\"Lato\" font-size=\"14.00\">2</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 1->2 -->\n",
|
||||
"<g id=\"edge5\" class=\"edge\">\n",
|
||||
"<title>1->2</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M162.37,-120.41C173.4,-119.15 188.15,-118.92 200.56,-119.71\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"207.56,-120.29 200.32,-122.85 204.07,-120 200.58,-119.71 200.58,-119.71 200.58,-119.71 204.07,-120 200.84,-116.57 207.56,-120.29 207.56,-120.29\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 3->2 -->\n",
|
||||
"<g id=\"edge8\" class=\"edge\">\n",
|
||||
"<title>3->2</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M160.49,-81.9C173.24,-90.62 191.89,-103.37 205.86,-112.92\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"211.91,-117.05 204.36,-115.7 209.02,-115.08 206.13,-113.1 206.13,-113.1 206.13,-113.1 209.02,-115.08 207.91,-110.5 211.91,-117.05 211.91,-117.05\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 4 -->\n",
|
||||
"<g id=\"node7\" class=\"node\">\n",
|
||||
"<title>4</title>\n",
|
||||
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"226\" cy=\"-72\" rx=\"18\" ry=\"18\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"226\" y=\"-68.3\" font-family=\"Lato\" font-size=\"14.00\">4</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 3->4 -->\n",
|
||||
"<g id=\"edge9\" class=\"edge\">\n",
|
||||
"<title>3->4</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M163.14,-72C174.12,-72 188.52,-72 200.67,-72\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"207.89,-72 200.89,-75.15 204.39,-72 200.89,-72 200.89,-72 200.89,-72 204.39,-72 200.89,-68.85 207.89,-72 207.89,-72\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 6 -->\n",
|
||||
"<g id=\"node8\" class=\"node\">\n",
|
||||
"<title>6</title>\n",
|
||||
"<polygon fill=\"#ffffaa\" stroke=\"black\" points=\"226,-36 199,-18 226,0 253,-18 226,-36\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"226\" y=\"-14.3\" font-family=\"Lato\" font-size=\"14.00\">6</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 3->6 -->\n",
|
||||
"<g id=\"edge10\" class=\"edge\">\n",
|
||||
"<title>3->6</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M160.49,-62.1C173.24,-53.38 191.89,-40.63 205.86,-31.08\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"211.91,-26.95 207.91,-33.5 209.02,-28.92 206.13,-30.9 206.13,-30.9 206.13,-30.9 209.02,-28.92 204.36,-28.3 211.91,-26.95 211.91,-26.95\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 2->1 -->\n",
|
||||
"<g id=\"edge6\" class=\"edge\">\n",
|
||||
"<title>2->1</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M207.56,-131.71C196.4,-132.89 181.78,-133.07 169.59,-132.24\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"162.37,-131.59 169.62,-129.08 165.85,-131.9 169.34,-132.22 169.34,-132.22 169.34,-132.22 165.85,-131.9 169.06,-135.35 162.37,-131.59 162.37,-131.59\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 5 -->\n",
|
||||
"<g id=\"node6\" class=\"node\">\n",
|
||||
"<title>5</title>\n",
|
||||
"<polygon fill=\"#ffffaa\" stroke=\"black\" points=\"460,-90 433,-72 460,-54 487,-72 460,-90\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"460\" y=\"-68.3\" font-family=\"Lato\" font-size=\"14.00\">5</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 2->5 -->\n",
|
||||
"<g id=\"edge7\" class=\"edge\">\n",
|
||||
"<title>2->5</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M246.38,-121.49C287.92,-111.82 385.57,-89.09 432.67,-78.13\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"439.51,-76.54 433.41,-81.19 436.1,-77.33 432.69,-78.12 432.69,-78.12 432.69,-78.12 436.1,-77.33 431.98,-75.06 439.51,-76.54 439.51,-76.54\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 7 -->\n",
|
||||
"<g id=\"node9\" class=\"node\">\n",
|
||||
"<title>7</title>\n",
|
||||
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"307\" cy=\"-18\" rx=\"18\" ry=\"18\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"307\" y=\"-14.3\" font-family=\"Lato\" font-size=\"14.00\">7</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 6->7 -->\n",
|
||||
"<g id=\"edge11\" class=\"edge\">\n",
|
||||
"<title>6->7</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M244.53,-12.28C255.75,-11.1 270.43,-10.93 282.64,-11.78\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"289.86,-12.43 282.61,-14.94 286.38,-12.12 282.89,-11.8 282.89,-11.8 282.89,-11.8 286.38,-12.12 283.17,-8.66 289.86,-12.43 289.86,-12.43\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 7->6 -->\n",
|
||||
"<g id=\"edge12\" class=\"edge\">\n",
|
||||
"<title>7->6</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M289.86,-23.57C278.84,-24.84 264.04,-25.09 251.56,-24.3\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"244.53,-23.72 251.77,-21.16 248.02,-24.01 251.51,-24.3 251.51,-24.3 251.51,-24.3 248.02,-24.01 251.25,-27.44 244.53,-23.72 244.53,-23.72\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 8 -->\n",
|
||||
"<g id=\"node10\" class=\"node\">\n",
|
||||
"<title>8</title>\n",
|
||||
"<ellipse fill=\"#ffffaa\" stroke=\"black\" cx=\"379\" cy=\"-49\" rx=\"18\" ry=\"18\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"379\" y=\"-45.3\" font-family=\"Lato\" font-size=\"14.00\">8</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 7->8 -->\n",
|
||||
"<g id=\"edge13\" class=\"edge\">\n",
|
||||
"<title>7->8</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M323.88,-25.03C333.28,-29.2 345.33,-34.53 355.67,-39.11\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"362.18,-41.99 354.5,-42.04 358.98,-40.58 355.78,-39.16 355.78,-39.16 355.78,-39.16 358.98,-40.58 357.05,-36.28 362.18,-41.99 362.18,-41.99\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 8->5 -->\n",
|
||||
"<g id=\"edge14\" class=\"edge\">\n",
|
||||
"<title>8->5</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M396.37,-53.77C407.17,-56.91 421.54,-61.1 433.79,-64.66\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"440.72,-66.68 433.12,-67.75 437.36,-65.7 434,-64.72 434,-64.72 434,-64.72 437.36,-65.7 434.88,-61.7 440.72,-66.68 440.72,-66.68\"/>\n",
|
||||
"</g>\n",
|
||||
"</g>\n",
|
||||
"</svg>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<spot.jupyter.SVG object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"spot.set_state_player(game, 4, False)\n",
|
||||
"game.show('.g')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Solving a game\n",
|
||||
"\n",
|
||||
"Solving a game is done my calling `solve_safety_game()` or `solve_parity_game()`. This will attach two additional vectors into the game automaton: one vector stores the winner of each state, and one vector stores (memory-less) strategy for each state, i.e., the transition that should always be taken by the owner of this state in order to win. \n",
|
||||
"\n",
|
||||
"The return value of those function is simply the winner for the initial state."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"True"
|
||||
]
|
||||
},
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"spot.solve_safety_game(game)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Calling the `highlight_strategy()` function can be used to decorate the `game` automaton using the winning regions and strategies. Below, green represent the winning region/strategy for player 1 and red those for player 0."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/svg+xml": [
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n",
|
||||
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
|
||||
" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
|
||||
"<!-- Generated by graphviz version 2.43.0 (0)\n",
|
||||
" -->\n",
|
||||
"<!-- Pages: 1 -->\n",
|
||||
"<svg width=\"495pt\" height=\"190pt\"\n",
|
||||
" viewBox=\"0.00 0.00 495.00 190.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n",
|
||||
"<g id=\"graph0\" class=\"graph\" transform=\"scale(1.0 1.0) rotate(0) translate(4 186)\">\n",
|
||||
"<polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-186 491,-186 491,4 -4,4\"/>\n",
|
||||
"<text text-anchor=\"start\" x=\"240.5\" y=\"-166.8\" font-family=\"Lato\" font-size=\"14.00\">t</text>\n",
|
||||
"<text text-anchor=\"start\" x=\"232.5\" y=\"-151.8\" font-family=\"Lato\" font-size=\"14.00\">[all]</text>\n",
|
||||
"<!-- I -->\n",
|
||||
"<!-- 0 -->\n",
|
||||
"<g id=\"node2\" class=\"node\">\n",
|
||||
"<title>0</title>\n",
|
||||
"<polygon fill=\"#ffffaa\" stroke=\"#33a02c\" stroke-width=\"2\" points=\"64,-144 37,-126 64,-108 91,-126 64,-144\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"64\" y=\"-122.3\" font-family=\"Lato\" font-size=\"14.00\">0</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- I->0 -->\n",
|
||||
"<g id=\"edge1\" class=\"edge\">\n",
|
||||
"<title>I->0</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M1.04,-126C1.93,-126 15.66,-126 29.98,-126\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"37,-126 30,-129.15 33.5,-126 30,-126 30,-126 30,-126 33.5,-126 30,-122.85 37,-126 37,-126\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 1 -->\n",
|
||||
"<g id=\"node3\" class=\"node\">\n",
|
||||
"<title>1</title>\n",
|
||||
"<ellipse fill=\"#ffffaa\" stroke=\"#33a02c\" stroke-width=\"2\" cx=\"145\" cy=\"-126\" rx=\"18\" ry=\"18\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"145\" y=\"-122.3\" font-family=\"Lato\" font-size=\"14.00\">1</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 0->1 -->\n",
|
||||
"<g id=\"edge2\" class=\"edge\">\n",
|
||||
"<title>0->1</title>\n",
|
||||
"<path fill=\"none\" stroke=\"#33a02c\" stroke-width=\"2\" d=\"M82.53,-120.28C93.75,-119.1 108.43,-118.93 120.64,-119.78\"/>\n",
|
||||
"<polygon fill=\"#33a02c\" stroke=\"#33a02c\" stroke-width=\"2\" points=\"127.86,-120.43 120.61,-122.94 124.33,-120.62 120.84,-120.3 120.89,-119.8 120.94,-119.3 124.42,-119.62 121.17,-116.66 127.86,-120.43 127.86,-120.43\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 3 -->\n",
|
||||
"<g id=\"node4\" class=\"node\">\n",
|
||||
"<title>3</title>\n",
|
||||
"<ellipse fill=\"#ffffaa\" stroke=\"#e31a1c\" stroke-width=\"2\" cx=\"145\" cy=\"-72\" rx=\"18\" ry=\"18\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"145\" y=\"-68.3\" font-family=\"Lato\" font-size=\"14.00\">3</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 0->3 -->\n",
|
||||
"<g id=\"edge3\" class=\"edge\">\n",
|
||||
"<title>0->3</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M78.05,-117.08C90.47,-108.59 109.36,-95.68 123.74,-85.85\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"129.6,-81.85 125.59,-88.4 126.71,-83.82 123.82,-85.8 123.82,-85.8 123.82,-85.8 126.71,-83.82 122.04,-83.2 129.6,-81.85 129.6,-81.85\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 1->0 -->\n",
|
||||
"<g id=\"edge4\" class=\"edge\">\n",
|
||||
"<title>1->0</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M127.86,-131.57C116.84,-132.84 102.04,-133.09 89.56,-132.3\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"82.53,-131.72 89.77,-129.16 86.02,-132.01 89.51,-132.3 89.51,-132.3 89.51,-132.3 86.02,-132.01 89.25,-135.44 82.53,-131.72 82.53,-131.72\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 2 -->\n",
|
||||
"<g id=\"node5\" class=\"node\">\n",
|
||||
"<title>2</title>\n",
|
||||
"<polygon fill=\"#ffffaa\" stroke=\"#33a02c\" stroke-width=\"2\" points=\"226,-144 199,-126 226,-108 253,-126 226,-144\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"226\" y=\"-122.3\" font-family=\"Lato\" font-size=\"14.00\">2</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 1->2 -->\n",
|
||||
"<g id=\"edge5\" class=\"edge\">\n",
|
||||
"<title>1->2</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M162.37,-120.41C173.4,-119.15 188.15,-118.92 200.56,-119.71\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"207.56,-120.29 200.32,-122.85 204.07,-120 200.58,-119.71 200.58,-119.71 200.58,-119.71 204.07,-120 200.84,-116.57 207.56,-120.29 207.56,-120.29\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 3->2 -->\n",
|
||||
"<g id=\"edge8\" class=\"edge\">\n",
|
||||
"<title>3->2</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M160.49,-81.9C173.24,-90.62 191.89,-103.37 205.86,-112.92\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"211.91,-117.05 204.36,-115.7 209.02,-115.08 206.13,-113.1 206.13,-113.1 206.13,-113.1 209.02,-115.08 207.91,-110.5 211.91,-117.05 211.91,-117.05\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 4 -->\n",
|
||||
"<g id=\"node7\" class=\"node\">\n",
|
||||
"<title>4</title>\n",
|
||||
"<ellipse fill=\"#ffffaa\" stroke=\"#e31a1c\" stroke-width=\"2\" cx=\"226\" cy=\"-72\" rx=\"18\" ry=\"18\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"226\" y=\"-68.3\" font-family=\"Lato\" font-size=\"14.00\">4</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 3->4 -->\n",
|
||||
"<g id=\"edge9\" class=\"edge\">\n",
|
||||
"<title>3->4</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M163.14,-72C174.12,-72 188.52,-72 200.67,-72\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"207.89,-72 200.89,-75.15 204.39,-72 200.89,-72 200.89,-72 200.89,-72 204.39,-72 200.89,-68.85 207.89,-72 207.89,-72\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 6 -->\n",
|
||||
"<g id=\"node8\" class=\"node\">\n",
|
||||
"<title>6</title>\n",
|
||||
"<polygon fill=\"#ffffaa\" stroke=\"#e31a1c\" stroke-width=\"2\" points=\"226,-36 199,-18 226,0 253,-18 226,-36\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"226\" y=\"-14.3\" font-family=\"Lato\" font-size=\"14.00\">6</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 3->6 -->\n",
|
||||
"<g id=\"edge10\" class=\"edge\">\n",
|
||||
"<title>3->6</title>\n",
|
||||
"<path fill=\"none\" stroke=\"#e31a1c\" stroke-width=\"2\" d=\"M160.49,-62.1C173.24,-53.38 191.89,-40.63 205.86,-31.08\"/>\n",
|
||||
"<polygon fill=\"#e31a1c\" stroke=\"#e31a1c\" stroke-width=\"2\" points=\"211.91,-26.95 207.91,-33.5 209.31,-29.33 206.42,-31.31 206.13,-30.9 205.85,-30.48 208.74,-28.51 204.36,-28.3 211.91,-26.95 211.91,-26.95\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 2->1 -->\n",
|
||||
"<g id=\"edge6\" class=\"edge\">\n",
|
||||
"<title>2->1</title>\n",
|
||||
"<path fill=\"none\" stroke=\"#33a02c\" stroke-width=\"2\" d=\"M207.56,-131.71C196.4,-132.89 181.78,-133.07 169.59,-132.24\"/>\n",
|
||||
"<polygon fill=\"#33a02c\" stroke=\"#33a02c\" stroke-width=\"2\" points=\"162.37,-131.59 169.62,-129.08 165.9,-131.41 169.39,-131.72 169.34,-132.22 169.3,-132.71 165.81,-132.4 169.06,-135.35 162.37,-131.59 162.37,-131.59\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 5 -->\n",
|
||||
"<g id=\"node6\" class=\"node\">\n",
|
||||
"<title>5</title>\n",
|
||||
"<polygon fill=\"#ffffaa\" stroke=\"#e31a1c\" stroke-width=\"2\" points=\"460,-90 433,-72 460,-54 487,-72 460,-90\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"460\" y=\"-68.3\" font-family=\"Lato\" font-size=\"14.00\">5</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 2->5 -->\n",
|
||||
"<g id=\"edge7\" class=\"edge\">\n",
|
||||
"<title>2->5</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M246.38,-121.49C287.92,-111.82 385.57,-89.09 432.67,-78.13\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"439.51,-76.54 433.41,-81.19 436.1,-77.33 432.69,-78.12 432.69,-78.12 432.69,-78.12 436.1,-77.33 431.98,-75.06 439.51,-76.54 439.51,-76.54\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 7 -->\n",
|
||||
"<g id=\"node9\" class=\"node\">\n",
|
||||
"<title>7</title>\n",
|
||||
"<ellipse fill=\"#ffffaa\" stroke=\"#e31a1c\" stroke-width=\"2\" cx=\"307\" cy=\"-18\" rx=\"18\" ry=\"18\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"307\" y=\"-14.3\" font-family=\"Lato\" font-size=\"14.00\">7</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 6->7 -->\n",
|
||||
"<g id=\"edge11\" class=\"edge\">\n",
|
||||
"<title>6->7</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M244.53,-12.28C255.75,-11.1 270.43,-10.93 282.64,-11.78\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"289.86,-12.43 282.61,-14.94 286.38,-12.12 282.89,-11.8 282.89,-11.8 282.89,-11.8 286.38,-12.12 283.17,-8.66 289.86,-12.43 289.86,-12.43\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 7->6 -->\n",
|
||||
"<g id=\"edge12\" class=\"edge\">\n",
|
||||
"<title>7->6</title>\n",
|
||||
"<path fill=\"none\" stroke=\"black\" d=\"M289.86,-23.57C278.84,-24.84 264.04,-25.09 251.56,-24.3\"/>\n",
|
||||
"<polygon fill=\"black\" stroke=\"black\" points=\"244.53,-23.72 251.77,-21.16 248.02,-24.01 251.51,-24.3 251.51,-24.3 251.51,-24.3 248.02,-24.01 251.25,-27.44 244.53,-23.72 244.53,-23.72\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 8 -->\n",
|
||||
"<g id=\"node10\" class=\"node\">\n",
|
||||
"<title>8</title>\n",
|
||||
"<ellipse fill=\"#ffffaa\" stroke=\"#e31a1c\" stroke-width=\"2\" cx=\"379\" cy=\"-49\" rx=\"18\" ry=\"18\"/>\n",
|
||||
"<text text-anchor=\"middle\" x=\"379\" y=\"-45.3\" font-family=\"Lato\" font-size=\"14.00\">8</text>\n",
|
||||
"</g>\n",
|
||||
"<!-- 7->8 -->\n",
|
||||
"<g id=\"edge13\" class=\"edge\">\n",
|
||||
"<title>7->8</title>\n",
|
||||
"<path fill=\"none\" stroke=\"#e31a1c\" stroke-width=\"2\" d=\"M323.88,-25.03C333.28,-29.2 345.33,-34.53 355.67,-39.11\"/>\n",
|
||||
"<polygon fill=\"#e31a1c\" stroke=\"#e31a1c\" stroke-width=\"2\" points=\"362.18,-41.99 354.5,-42.04 358.78,-41.03 355.58,-39.62 355.78,-39.16 355.98,-38.7 359.18,-40.12 357.05,-36.28 362.18,-41.99 362.18,-41.99\"/>\n",
|
||||
"</g>\n",
|
||||
"<!-- 8->5 -->\n",
|
||||
"<g id=\"edge14\" class=\"edge\">\n",
|
||||
"<title>8->5</title>\n",
|
||||
"<path fill=\"none\" stroke=\"#e31a1c\" stroke-width=\"2\" d=\"M396.37,-53.77C407.17,-56.91 421.54,-61.1 433.79,-64.66\"/>\n",
|
||||
"<polygon fill=\"#e31a1c\" stroke=\"#e31a1c\" stroke-width=\"2\" points=\"440.72,-66.68 433.12,-67.75 437.22,-66.18 433.86,-65.2 434,-64.72 434.14,-64.24 437.5,-65.22 434.88,-61.7 440.72,-66.68 440.72,-66.68\"/>\n",
|
||||
"</g>\n",
|
||||
"</g>\n",
|
||||
"</svg>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<spot.jupyter.SVG object>"
|
||||
]
|
||||
},
|
||||
"execution_count": 7,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"spot.highlight_strategy(game)\n",
|
||||
"game.show('.g')"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -35,7 +675,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -272,10 +912,10 @@
|
|||
"</svg>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7f9bf8477330> >"
|
||||
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7fa3979355d0> >"
|
||||
]
|
||||
},
|
||||
"execution_count": 2,
|
||||
"execution_count": 8,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -296,7 +936,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"execution_count": 9,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -353,19 +993,12 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Solving games"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The `solve_parity_game()` function returns the player winning from the initial state (`False` for player 0, and `True` for player 1)."
|
||||
"Here is the solution of this particular game."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -374,7 +1007,7 @@
|
|||
"True"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -383,18 +1016,9 @@
|
|||
"spot.solve_parity_game(game)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Additional information about the player winning in each state, and the strategy have been stored in the automaton but are not displayed by default.\n",
|
||||
"\n",
|
||||
"Calling the `highlight_strategy` function will decorate the game's automaton with colors showing the winning regions (states from which a player has a strategy to win), and strategy (which transition should be used for each winning state owned by that player) of a given player. Here green corresponds to player 1 (who tries to satisfy the acceptance condition), and red to player 0 (who tries not to)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
|
|
@ -631,10 +1255,10 @@
|
|||
"</svg>\n"
|
||||
],
|
||||
"text/plain": [
|
||||
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7f9bf83e1060> >"
|
||||
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7fa37f087db0> >"
|
||||
]
|
||||
},
|
||||
"execution_count": 5,
|
||||
"execution_count": 11,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -642,6 +1266,13 @@
|
|||
"source": [
|
||||
"spot.highlight_strategy(game)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
|
|
@ -660,7 +1291,7 @@
|
|||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.8.6rc1"
|
||||
"version": "3.9.1rc1"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
Loading…
Add table
Add a link
Reference in a new issue