rename pg_print() as print_pg() and add it to to_str()

* NEWS: Mention those change.
* spot/twaalgos/game.hh (print_pg): New function.
(pg_print): Mark as deprecated.
* spot/twaalgos/game.cc (pg_print): Redirect to print_pg().
(print_pg): Update to output state names.
* python/spot/__init__.py: Teach to_str() about print_pg().
* bin/ltlsynt.cc: Adjust to call print_pg().
* tests/python/games.ipynb: Add an example.
* tests/core/ltlsynt.test: Adjust to remove the "INIT" note.
This commit is contained in:
Alexandre Duret-Lutz 2022-07-22 16:52:03 +02:00
parent b3e994c249
commit 8b93b6967d
7 changed files with 145 additions and 68 deletions

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2017-2018, 2020-2021 Laboratoire de Recherche et
// Copyright (C) 2017-2018, 2020-2022 Laboratoire de Recherche et
// Développement de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
@ -23,7 +23,7 @@
#include <spot/misc/timer.hh>
#include <spot/twaalgos/game.hh>
#include <spot/misc/bddlt.hh>
#include <spot/misc/escape.hh>
#include <spot/twaalgos/sccinfo.hh>
namespace spot
@ -834,66 +834,71 @@ namespace spot
return solve_parity_game(arena);
}
// backward compatibility
void pg_print(std::ostream& os, const const_twa_graph_ptr& arena)
{
ensure_parity_game(arena, "pg_print");
print_pg(os, arena);
}
auto do_print = [&os](const const_twa_graph_ptr& arena)
{
const region_t& owner = get_state_players(arena);
unsigned ns = arena->num_states();
unsigned init = arena->get_init_state_number();
os << "parity " << ns - 1 << ";\n";
std::vector<bool> seen(ns, false);
std::vector<unsigned> todo({init});
while (!todo.empty())
{
unsigned src = todo.back();
todo.pop_back();
if (seen[src])
continue;
seen[src] = true;
os << src << ' ';
os << arena->out(src).begin()->acc.max_set() - 1 << ' ';
os << owner[src] << ' ';
bool first = true;
for (auto& e: arena->out(src))
{
if (!first)
os << ',';
first = false;
os << e.dst;
if (!seen[e.dst])
todo.push_back(e.dst);
}
if (src == init)
os << " \"INIT\"";
os << ";\n";
}
};
// Ensure coloring
// PGSolver format expects max odd and colored
std::ostream& print_pg(std::ostream& os, const const_twa_graph_ptr& arena)
{
bool is_par, max, odd;
is_par = arena->acc().is_parity(max, odd, true);
assert(is_par && "pg_printer needs parity condition");
bool is_colored = (max & odd) ? std::all_of(arena->edges().begin(),
arena->edges().end(),
[](const auto& e)
{
return (bool) e.acc;
})
: false;
if (is_colored)
do_print(arena);
else
if (!is_par)
throw std::runtime_error("print_pg: arena must have a parity acceptance");
const region_t& owner = *ensure_game(arena, "print_pg");
bool max_odd_colored =
max && odd && std::all_of(arena->edges().begin(),
arena->edges().end(),
[](const auto& e)
{
return (bool) e.acc;
});
const_twa_graph_ptr towork = arena;
if (!max_odd_colored)
{
auto arena2 = change_parity(arena, parity_kind_max, parity_style_odd);
colorize_parity_here(arena2, true);
set_state_players(arena2,
get_state_players(arena));
do_print(arena2);
twa_graph_ptr tmp =
change_parity(arena, parity_kind_max, parity_style_odd);
colorize_parity_here(tmp, true);
towork = tmp;
}
auto sn = arena->get_named_prop<std::vector<std::string>>("state-names");
unsigned ns = towork->num_states();
unsigned init = towork->get_init_state_number();
os << "parity " << ns - 1 << ";\n";
std::vector<bool> seen(ns, false);
std::vector<unsigned> todo({init});
while (!todo.empty())
{
unsigned src = todo.back();
todo.pop_back();
if (seen[src])
continue;
seen[src] = true;
os << src << ' ';
os << towork->out(src).begin()->acc.max_set() - 1 << ' ';
os << owner[src] << ' ';
bool first = true;
for (auto& e: arena->out(src))
{
if (!first)
os << ',';
first = false;
os << e.dst;
if (!seen[e.dst])
todo.push_back(e.dst);
}
if (sn && sn->size() > src && !(*sn)[src].empty())
{
os << " \"";
escape_str(os, (*sn)[src]);
os << '"';
}
os << ";\n";
}
return os;
}
void alternate_players(spot::twa_graph_ptr& arena,

View file

@ -1,5 +1,5 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2017-2021 Laboratoire de Recherche et Développement
// Copyright (C) 2017-2022 Laboratoire de Recherche et Développement
// de l'Epita (LRDE).
//
// This file is part of Spot, a model checking library.
@ -112,10 +112,26 @@ namespace spot
/// \ingroup games
/// \brief Print a max odd parity game using PG-solver syntax
/// \brief Print a parity game using PG-solver syntax
///
/// The input automaton should have parity acceptance and should
/// define state owner. Since the PG solver format want player 1 to
/// solve a max odd condition, the acceptance condition will be
/// adapted to max odd if necessary.
///
/// The output will list the initial state as first state (because
/// that is the convention of our parser), and list only reachable
/// states.
///
/// If states are named, the names will be output as well.
/// @{
SPOT_API
std::ostream& print_pg(std::ostream& os, const const_twa_graph_ptr& arena);
SPOT_DEPRECATED("use print_pg() instead")
SPOT_API
void pg_print(std::ostream& os, const const_twa_graph_ptr& arena);
/// @}
/// \ingroup games
/// \brief Highlight the edges of a strategy on an automaton.