Using partitioned_relabel_here

Put the new function to use in order to speed up
mealy machine minimization

* spot/twaalgos/mealy_machine.cc: Here
* spot/twaalgos/synthesis.cc
, spot/twaalgos/synthesis.hh: Helper function to relabel games
* tests/python/_mealy.ipynb
, tests/python/except.py
, tests/python/_partitioned_relabel.ipynb: Adapt/expand tests
This commit is contained in:
Philipp Schlehuber-Caissier 2022-11-29 14:58:26 +01:00
parent fb63dfc309
commit 6e2e7c942e
6 changed files with 1722 additions and 182 deletions

View file

@ -36,7 +36,9 @@
#include <spot/twaalgos/game.hh>
#include <spot/twaalgos/hoa.hh>
#include <spot/twaalgos/product.hh>
#include <spot/twaalgos/relabel.hh>
#include <spot/twaalgos/synthesis.hh>
#include <spot/priv/partitioned_relabel.hh>
#include <picosat/picosat.h>
@ -869,7 +871,7 @@ namespace
split_cstr_time, prob_init_build_time, sat_time,
build_time, refine_time, total_time;
long long n_classes, n_refinement, n_lit, n_clauses,
n_iteration, n_bisim_let, n_min_states, done;
n_iteration, n_letters_part, n_bisim_let, n_min_states, done;
std::string task;
const std::string instance;
@ -892,6 +894,7 @@ namespace
, n_lit{-1}
, n_clauses{-1}
, n_iteration{-1}
, n_letters_part{-1}
, n_bisim_let{-1}
, n_min_states{-1}
, done{-1}
@ -935,8 +938,8 @@ namespace
<< "player_incomp_time,incomp_time,split_all_let_time,"
<< "split_min_let_time,split_cstr_time,prob_init_build_time,"
<< "sat_time,build_time,refine_time,total_time,n_classes,"
<< "n_refinement,n_lit,n_clauses,n_iteration,n_bisim_let,"
<< "n_min_states,done\n";
<< "n_refinement,n_lit,n_clauses,n_iteration,n_letters_part,"
<< "n_bisim_let,n_min_states,done\n";
}
assert(!task.empty());
@ -965,6 +968,7 @@ namespace
f(ss, n_lit);
f(ss, n_clauses);
f(ss, n_iteration);
f(ss, n_letters_part);
f(ss, n_bisim_let);
f(ss, n_min_states);
f(ss, done, false);
@ -1280,8 +1284,8 @@ namespace
}
square_matrix<bool, true>
compute_incomp(const_twa_graph_ptr mm, const unsigned n_env,
satprob_info& si)
compute_incomp_impl_(const_twa_graph_ptr mm, const unsigned n_env,
satprob_info& si, bool is_partitioned)
{
const unsigned n_tot = mm->num_states();
@ -1292,20 +1296,6 @@ namespace
// Have two states already been checked for common pred
square_matrix<bool, true> checked_pred(n_env, false);
// We also need a transposed_graph
auto mm_t = make_twa_graph(mm->get_dict());
mm_t->copy_ap_of(mm);
mm_t->new_states(n_env);
for (unsigned s = 0; s < n_env; ++s)
{
for (const auto& e_env : mm->out(s))
{
unsigned dst_env = mm->out(e_env.dst).begin()->dst;
mm_t->new_edge(dst_env, s, e_env.cond);
}
}
// Utility function
auto get_cond = [&mm](unsigned s)->const bdd&
{return mm->out(s).begin()->cond; };
@ -1367,15 +1357,28 @@ namespace
#endif
// direct incomp: Two env states can reach incompatible player states
// under the same input
// The original graph mm is not sorted, and most of the
// sorting is not rentable
// However, bdd_have_common_assignment simply becomes equality
auto direct_incomp = [&](unsigned s1, unsigned s2)
{
for (const auto& e1 : mm->out(s1))
for (const auto& e2 : mm->out(s2))
{
if (is_partitioned && (e1.cond != e2.cond))
continue;
if (!is_p_incomp(e1.dst - n_env, e2.dst - n_env))
continue; //Compatible -> no prob
// Reachable under same letter?
if (bdd_have_common_assignment(e1.cond, e2.cond))
if (is_partitioned) // -> Yes
{
trace << s1 << " and " << s2 << " directly incomp "
"due to successors " << e1.dst << " and " << e2.dst
<< '\n';
return true;
}
else if (!is_partitioned
&& bdd_have_common_assignment(e1.cond, e2.cond))
{
trace << s1 << " and " << s2 << " directly incomp "
"due to successors " << e1.dst << " and " << e2.dst
@ -1388,7 +1391,27 @@ namespace
// If two states can reach an incompatible state
// under the same input, then they are incompatible as well
auto tag_predec = [&](unsigned s1, unsigned s2)
// Version if the input is not partitioned
// We also need a transposed_graph
twa_graph_ptr mm_t = nullptr;
if (!is_partitioned)
{
mm_t = make_twa_graph(mm->get_dict());
mm_t->copy_ap_of(mm);
mm_t->new_states(n_env);
for (unsigned s = 0; s < n_env; ++s)
{
for (const auto& e_env : mm->out(s))
{
unsigned dst_env = mm->out(e_env.dst).begin()->dst;
mm_t->new_edge(dst_env, s, e_env.cond);
}
}
}
auto tag_predec_unpart = [&](unsigned s1, unsigned s2)
{
static std::vector<std::pair<unsigned, unsigned>> todo_;
assert(todo_.empty());
@ -1422,17 +1445,98 @@ namespace
// Done tagging all pred
};
// Version of taging taking advantaged of partitioned conditions
struct S
{
};
struct T
{
int id;
};
std::unique_ptr<digraph<S, T>> mm_t_part;
if (is_partitioned)
{
mm_t_part = std::make_unique<digraph<S, T>>(n_env, mm->num_edges());
mm_t_part->new_states(n_env);
for (unsigned s = 0; s < n_env; ++s)
{
for (const auto& e_env : mm->out(s))
{
unsigned dst_env = mm->out(e_env.dst).begin()->dst;
mm_t_part->new_edge(dst_env, s, e_env.cond.id());
}
}
// Now we need to sort the edge to ensure that
// the next algo works correctly
mm_t_part->sort_edges_srcfirst_([](const auto& e1, const auto& e2)
{return e1.id < e2.id; });
mm_t_part->chain_edges_();
}
auto tag_predec_part = [&](unsigned s1, unsigned s2)
{
static std::vector<std::pair<unsigned, unsigned>> todo_;
assert(todo_.empty());
todo_.emplace_back(s1, s2);
while (!todo_.empty())
{
auto [i, j] = todo_.back();
todo_.pop_back();
if (checked_pred.get(i, j))
continue;
// If predecs are already marked incomp
auto e_it_i = mm_t_part->out(i);
auto e_it_j = mm_t_part->out(j);
auto e_it_i_e = e_it_i.end();
auto e_it_j_e = e_it_j.end();
auto e_i = e_it_i.begin();
auto e_j = e_it_j.begin();
// Joint iteration over both edge groups
while ((e_i != e_it_i_e) && (e_j != e_it_j_e))
{
if (e_i->id < e_j->id)
++e_i;
else if (e_j->id < e_i->id)
++e_j;
else
{
assert(e_j->id == e_i->id);
trace << e_i->dst << " and " << e_j->dst << " tagged incomp"
" due to " << e_i->id << '\n';
inc_env.set(e_i->dst, e_j->dst, true);
todo_.emplace_back(e_i->dst, e_j->dst);
++e_i;
++e_j;
}
}
checked_pred.set(i, j, true);
}
// Done tagging all pred
};
for (unsigned s1 = 0; s1 < n_env; ++s1)
for (unsigned s2 = s1 + 1; s2 < n_env; ++s2)
{
if (inc_env.get(s1, s2))
continue; // Already done
// Check if they are incompatible for some letter
// We have to check all pairs of edges
if (direct_incomp(s1, s2))
{
inc_env.set(s1, s2, true);
tag_predec(s1, s2);
if (is_partitioned)
tag_predec_part(s1, s2);
else
tag_predec_unpart(s1, s2);
}
}
@ -1442,9 +1546,38 @@ namespace
#endif
si.incomp_time = si.restart();
return inc_env;
} // incomp no partition
square_matrix<bool, true>
compute_incomp(const_twa_graph_ptr mm, const unsigned n_env,
satprob_info& si, int max_letter_mult)
{
// Try to generate a graph with partitioned env transitions
auto mm2 = make_twa_graph(mm, twa::prop_set::all());
set_state_players(mm2, get_state_players(mm));
set_synthesis_outputs(mm2, get_synthesis_outputs(mm));
// todo get a good value for cutoff
auto relabel_maps
= partitioned_game_relabel_here(mm2, true, false, true,
false, -1u, max_letter_mult);
bool succ = !relabel_maps.env_map.empty();
si.n_letters_part = relabel_maps.env_map.size();
#ifdef TRACE
if (succ)
std::cout << "Relabeling succesfull with " << relabel_maps.env_map.size()
<< " letters\n";
else
std::cout << "Relabeling aborted\n";
#endif
return compute_incomp_impl_(succ ? const_twa_graph_ptr(mm2) : mm,
n_env, si, succ);
}
struct part_sol_t
struct part_sol_t
{
std::vector<unsigned> psol;
std::vector<unsigned> is_psol;
@ -1602,6 +1735,11 @@ namespace
return std::make_pair(n_group, which_group);
}
// Helper function
// Computes the set of all original letters implied by the leaves
// This avoids transposing the graph
// Computes the letters of each group
// Letters here means bdds such that for all valid
// assignments of the bdd we go to the same dst from the same source
@ -1611,7 +1749,9 @@ namespace
{
//To avoid recalc
std::set<int> all_bdd;
std::set<int> treated_bdd;
std::vector<bdd> all_bdd_v;
std::unordered_map<unsigned, unsigned> node2idx;
std::unordered_multimap<size_t, std::pair<unsigned, std::set<int>>>
sigma_map;
@ -1649,6 +1789,11 @@ namespace
continue;
else
{
// Store bdds as vector for compatibility
all_bdd_v.clear(); // Note: sorted automatically by id
std::transform(all_bdd.begin(), all_bdd.end(),
std::back_inserter(all_bdd_v),
[](int i){return bdd_from_int(i); });
// Insert it already into the sigma_map
trace << "Group " << groupidx << " generates a new alphabet\n";
sigma_map.emplace(std::piecewise_construct,
@ -1658,62 +1803,60 @@ namespace
}
}
// Result
red.share_sigma_with.push_back(groupidx);
red.all_letters.emplace_back();
auto& group_letters = red.all_letters.back();
treated_bdd.clear();
// Compute it
auto this_part = try_partition_me(all_bdd_v, -1u);
assert(this_part.relabel_succ);
for (unsigned s = 0; s < n_env; ++s)
// Transform it
// group_letters is pair<new_letter, set of implied orig letters as id>
// There are as many new_letters as treated bdds in the partition
group_letters.clear();
group_letters.reserve(this_part.treated.size());
node2idx.clear();
node2idx.reserve(this_part.treated.size());
for (const auto& [label, node] : this_part.treated)
{
if (red.which_group[s] != groupidx)
continue;
for (const auto& e : mmw->out(s))
{
bdd rcond = e.cond;
const int econd_id = rcond.id();
trace << rcond << " - " << econd_id << std::endl;
if (treated_bdd.count(econd_id))
{
trace << "Already treated" << std::endl;
continue;
}
treated_bdd.insert(econd_id);
assert(rcond != bddfalse && "Deactivated edges are forbiden");
// Check against all currently used "letters"
const size_t osize = group_letters.size();
for (size_t i = 0; i < osize; ++i)
{
if (group_letters[i].first == rcond)
{
rcond = bddfalse;
group_letters[i].second.insert(econd_id);
break;
}
bdd inter = group_letters[i].first & rcond;
if (inter == bddfalse)
continue; // No intersection
if (group_letters[i].first == inter)
group_letters[i].second.insert(econd_id);
else
{
group_letters[i].first -= inter;
group_letters.emplace_back(inter,
group_letters[i].second);
group_letters.back().second.insert(econd_id);
}
rcond -= inter;
// Early exit?
if (rcond == bddfalse)
break;
}
// Leftovers?
if (rcond != bddfalse)
group_letters.emplace_back(rcond, std::set<int>{econd_id});
}
node2idx[node] = group_letters.size();
group_letters.emplace_back(std::piecewise_construct,
std::forward_as_tuple(label),
std::forward_as_tuple());
}
// Go through the graph for each original letter
auto search_leaves
= [&ig = *this_part.ig, &group_letters, &node2idx]
(int orig_letter_id, unsigned s, auto&& search_leaves_) -> void
{
if (ig.state_storage(s).succ == 0)
{
// Leaf
unsigned idx = node2idx[s];
auto& setidx = group_letters[idx].second;
setidx.emplace_hint(setidx.end(), orig_letter_id);
}
else
{
// Traverse
for (const auto& e : ig.out(s))
search_leaves_(orig_letter_id, e.dst, search_leaves_);
}
};
const unsigned Norig = all_bdd_v.size();
for (unsigned s = 0; s < Norig; ++s)
search_leaves(all_bdd_v[s].id(), s, search_leaves);
// Verify that all letters imply at least one original letter
assert(std::all_of(group_letters.begin(), group_letters.end(),
[](const auto& l){return !l.second.empty(); }));
#ifdef TRACE
trace << "this group letters" << std::endl;
auto sp = [&](const auto& c)
@ -3467,6 +3610,7 @@ namespace
for (unsigned letter_idx = 0; letter_idx < n_ml; ++letter_idx)
{
const auto& ml_list = group_map[letter_idx];
assert(ml_list.begin() != ml_list.end());
// Incompatibility is commutative
// new / new constraints
const auto it_end = ml_list.end();
@ -3794,12 +3938,9 @@ namespace
return minmach;
} // while loop
} // try_build_machine
} // namespace
namespace spot
{
twa_graph_ptr minimize_mealy(const const_twa_graph_ptr& mm,
int premin)
twa_graph_ptr minimize_mealy_(const const_twa_graph_ptr& mm,
int premin, int max_letter_mult)
{
bdd outputs = ensure_mealy("minimize_mealy", mm);
@ -3866,8 +4007,9 @@ namespace spot
si.reorg_time = si.restart();
// Compute incompatibility based on bdd
auto incompmat = compute_incomp(mmw, n_env, si);
auto incompmat = compute_incomp(mmw, n_env, si, max_letter_mult);
#ifdef TRACE
std::cerr << "Final incomp mat\n";
incompmat.print(std::cerr);
#endif
@ -3944,6 +4086,15 @@ namespace spot
minmachine));
return minmachine;
}
} // namespace
namespace spot
{
twa_graph_ptr minimize_mealy(const const_twa_graph_ptr& mm,
int premin)
{
return minimize_mealy_(mm, premin, 10);
}
twa_graph_ptr
minimize_mealy(const const_twa_graph_ptr& mm,
@ -3970,7 +4121,8 @@ namespace spot
sat_dimacs_file
= std::make_unique<fwrapper>(dimacsfile);
sat_instance_name = si.opt.get_str("satinstancename");
auto res = minimize_mealy(mm, si.minimize_lvl-4);
auto res = minimize_mealy_(mm, si.minimize_lvl-4,
si.opt.get("max_letter_mult", 10));
sat_csv_file.reset();
sat_dimacs_file.reset();
return res;
@ -4161,7 +4313,7 @@ namespace spot
reduce_mealy_here(m, minimize_lvl == 2);
}
else if (3 <= minimize_lvl)
m = minimize_mealy(m, minimize_lvl - 4);
m = minimize_mealy(m, si);
// Convert to demanded output format
bool is_split = m->get_named_prop<region_t>("state-player");

View file

@ -37,6 +37,7 @@
#include <algorithm>
#include <string>
// Helper function/structures for split_2step
namespace{
@ -1935,4 +1936,98 @@ namespace spot
return res;
}
namespace
{
const std::string in_mark_s("__AP_IN__");
const std::string out_mark_s("__AP_OUT__");
}
game_relabeling_map
partitioned_game_relabel_here(twa_graph_ptr& arena,
bool relabel_env,
bool relabel_play,
bool split_env,
bool split_play,
unsigned max_letter,
unsigned max_letter_mult)
{
if (!arena)
throw std::runtime_error("arena is null.");
auto& arena_r = *arena;
const auto& sp = get_state_players(arena);
bdd all_ap = arena->ap_vars();
if (std::find_if(arena->ap().cbegin(), arena->ap().cend(),
[](const auto& ap)
{
return ap.ap_name() == out_mark_s
|| ap.ap_name() == in_mark_s;
}) != arena->ap().cend())
throw std::runtime_error("partitioned_game_relabel_here(): "
"You can not use "
+ in_mark_s + " or " + out_mark_s +
" as propositions if relabeling.");
bdd out_mark = bdd_ithvar(arena_r.register_ap(out_mark_s));
bdd in_mark = bdd_ithvar(arena_r.register_ap(in_mark_s));
bdd outs = get_synthesis_outputs(arena) & out_mark;
bdd ins = bdd_exist(all_ap, outs) & in_mark;
for (auto& e : arena_r.edges())
e.cond = e.cond & (sp[e.src] ? out_mark : in_mark);
game_relabeling_map res;
if (relabel_env)
res.env_map
= partitioned_relabel_here(arena, split_env, max_letter,
max_letter_mult, ins, "__nv_in");
if (relabel_play)
res.player_map
= partitioned_relabel_here(arena, split_play, max_letter,
max_letter_mult, outs, "__nv_out");
return res;
}
void
relabel_game_here(twa_graph_ptr& arena,
game_relabeling_map& rel_maps)
{
if (!arena)
throw std::runtime_error("arena is null.");
auto& arena_r = *arena;
// Check that it was partitioned_game_relabel_here
if (!((std::find_if(arena->ap().cbegin(), arena->ap().cend(),
[](const auto& ap)
{ return ap.ap_name() == out_mark_s; })
!= arena->ap().cend())
&& (std::find_if(arena->ap().cbegin(), arena->ap().cend(),
[](const auto& ap)
{ return ap.ap_name() == in_mark_s; }))
!= arena->ap().cend()))
throw std::runtime_error("relabel_game_here(): " +
in_mark_s + " or " + out_mark_s +
" not registered with arena. "
"Not relabeled?");
if (!rel_maps.env_map.empty())
relabel_here(arena, &rel_maps.env_map);
if (!rel_maps.player_map.empty())
relabel_here(arena, &rel_maps.player_map);
bdd dummy_ap = bdd_ithvar(arena_r.register_ap(in_mark_s))
& bdd_ithvar(arena_r.register_ap(out_mark_s));
for (auto& e : arena_r.edges())
e.cond = bdd_exist(e.cond, dummy_ap);
arena_r.unregister_ap(arena_r.register_ap(in_mark_s));
arena_r.unregister_ap(arena_r.register_ap(out_mark_s));
return;
}
} // spot

View file

@ -21,6 +21,7 @@
#include <spot/twa/twagraph.hh>
#include <spot/twaalgos/game.hh>
#include <spot/twaalgos/relabel.hh>
#include <bddx.h>
namespace spot
@ -256,4 +257,39 @@ namespace spot
SPOT_API bool
solve_game(twa_graph_ptr arena, synthesis_info& gi);
struct SPOT_API game_relabeling_map
{
relabeling_map env_map;
relabeling_map player_map;
};
/// \ingroup synthesis
/// \brief Tries to relabel a SPLIT game \a arena using fresh propositions.
/// Can be applied to env or player depending on \a relabel_env
/// and \a relabel_play. The arguments \a split_env and \a split_play
/// determine whether or not env and player edges are to
/// be split into several transitions labelled by letters not conditions.
///
/// \return pair of relabeling_map, first is for env, second is for player.
/// The maps are empty if no relabeling was performed
/// \note Can also be applied to split mealy machine.
/// \note partitioned_relabel_here can not be used directly if there are
/// T (true conditions)
SPOT_API game_relabeling_map
partitioned_game_relabel_here(twa_graph_ptr& arena,
bool relabel_env,
bool relabel_play,
bool split_env = false,
bool split_play = false,
unsigned max_letter = -1u,
unsigned max_letter_mult = -1u);
/// \ingroup synthesis
/// \brief Undoes a relabeling done by partitioned_game_relabel_here.
/// A dedicated function is necessary in order to remove the
/// variables tagging env and player conditions
SPOT_API void
relabel_game_here(twa_graph_ptr& arena,
game_relabeling_map& rel_maps);
}

View file

@ -129,7 +129,7 @@
"</svg>\n"
],
"text/plain": [
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7fcc35aaa030> >"
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7f86481a2690> >"
]
},
"execution_count": 4,
@ -209,7 +209,7 @@
"</svg>\n"
],
"text/plain": [
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7fcc35aaa900> >"
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7f85f45cbb70> >"
]
},
"execution_count": 6,
@ -283,7 +283,7 @@
"</svg>\n"
],
"text/plain": [
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7fcc35aaa900> >"
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7f85f45cbb70> >"
]
},
"execution_count": 8,
@ -387,7 +387,7 @@
"</svg>\n"
],
"text/plain": [
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7fcc35ac20c0> >"
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7f861bfc8ae0> >"
]
},
"execution_count": 9,
@ -532,7 +532,7 @@
"</svg>\n"
],
"text/plain": [
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7fcc35ac2720> >"
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7f85f45efde0> >"
]
},
"execution_count": 10,
@ -584,13 +584,13 @@
" <th>split_cstr_time</th>\n",
" <th>prob_init_build_time</th>\n",
" <th>...</th>\n",
" <th>refine_time</th>\n",
" <th>total_time</th>\n",
" <th>n_classes</th>\n",
" <th>n_refinement</th>\n",
" <th>n_lit</th>\n",
" <th>n_clauses</th>\n",
" <th>n_iteration</th>\n",
" <th>n_letters_part</th>\n",
" <th>n_bisim_let</th>\n",
" <th>n_min_states</th>\n",
" <th>done</th>\n",
@ -600,15 +600,15 @@
" <tr>\n",
" <th>0</th>\n",
" <td>presat</td>\n",
" <td>25643.3</td>\n",
" <td>1.112e-06</td>\n",
" <td>4.588e-06</td>\n",
" <td>9.888e-06</td>\n",
" <td>4.549e-06</td>\n",
" <td>1.5929e-05</td>\n",
" <td>9.338e-06</td>\n",
" <td>5.901e-06</td>\n",
" <td>6.7276e-05</td>\n",
" <td>3868.95</td>\n",
" <td>3.282e-06</td>\n",
" <td>1.4388e-05</td>\n",
" <td>0.000129765</td>\n",
" <td>1.3759e-05</td>\n",
" <td>9.499e-06</td>\n",
" <td>8.73e-06</td>\n",
" <td>9.01e-06</td>\n",
" <td>6.6209e-05</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
@ -616,7 +616,7 @@
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
@ -634,40 +634,40 @@
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>0.000282709</td>\n",
" <td>0.000743251</td>\n",
" <td>2</td>\n",
" <td>0</td>\n",
" <td>7</td>\n",
" <td>12</td>\n",
" <td>0</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>4</td>\n",
" <td>1</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>2 rows × 22 columns</p>\n",
"<p>2 rows × 23 columns</p>\n",
"</div>"
],
"text/plain": [
" task premin_time reorg_time partsol_time player_incomp_time incomp_time \\\n",
"0 presat 25643.3 1.112e-06 4.588e-06 9.888e-06 4.549e-06 \n",
"0 presat 3868.95 3.282e-06 1.4388e-05 0.000129765 1.3759e-05 \n",
"1 sat NaN NaN NaN NaN NaN \n",
"\n",
" split_all_let_time split_min_let_time split_cstr_time prob_init_build_time \\\n",
"0 1.5929e-05 9.338e-06 5.901e-06 6.7276e-05 \n",
"0 9.499e-06 8.73e-06 9.01e-06 6.6209e-05 \n",
"1 NaN NaN NaN NaN \n",
"\n",
" ... refine_time total_time n_classes n_refinement n_lit n_clauses \\\n",
"0 ... NaN NaN NaN NaN NaN NaN \n",
"1 ... NaN 0.000282709 2 0 7 12 \n",
" ... total_time n_classes n_refinement n_lit n_clauses n_iteration \\\n",
"0 ... NaN NaN NaN NaN NaN NaN \n",
"1 ... 0.000743251 2 0 7 12 0 \n",
"\n",
" n_iteration n_bisim_let n_min_states done \n",
"0 NaN 2 NaN NaN \n",
"1 0 NaN 4 1 \n",
" n_letters_part n_bisim_let n_min_states done \n",
"0 3 2 NaN NaN \n",
"1 NaN NaN 4 1 \n",
"\n",
"[2 rows x 22 columns]"
"[2 rows x 23 columns]"
]
},
"metadata": {},
@ -758,7 +758,7 @@
"</svg>\n"
],
"text/plain": [
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7fcc88735f00> >"
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7f861bfc8630> >"
]
},
"execution_count": 11,
@ -861,7 +861,7 @@
"</svg>\n"
],
"text/plain": [
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7fcc6157fe40> >"
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7f861bf9fb40> >"
]
},
"execution_count": 12,
@ -1000,7 +1000,7 @@
"</svg>\n"
],
"text/plain": [
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7fcc6157f210> >"
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7f861bf9f210> >"
]
},
"execution_count": 13,
@ -1051,13 +1051,13 @@
" <th>split_cstr_time</th>\n",
" <th>prob_init_build_time</th>\n",
" <th>...</th>\n",
" <th>refine_time</th>\n",
" <th>total_time</th>\n",
" <th>n_classes</th>\n",
" <th>n_refinement</th>\n",
" <th>n_lit</th>\n",
" <th>n_clauses</th>\n",
" <th>n_iteration</th>\n",
" <th>n_letters_part</th>\n",
" <th>n_bisim_let</th>\n",
" <th>n_min_states</th>\n",
" <th>done</th>\n",
@ -1067,15 +1067,15 @@
" <tr>\n",
" <th>0</th>\n",
" <td>presat</td>\n",
" <td>25643.4</td>\n",
" <td>1.683e-06</td>\n",
" <td>5.611e-06</td>\n",
" <td>2.66e-05</td>\n",
" <td>1.2e-07</td>\n",
" <td>3.647e-06</td>\n",
" <td>8.365e-06</td>\n",
" <td>3.747e-06</td>\n",
" <td>2.5538e-05</td>\n",
" <td>3869.08</td>\n",
" <td>3.213e-06</td>\n",
" <td>9.079e-06</td>\n",
" <td>9.5752e-05</td>\n",
" <td>5.168e-06</td>\n",
" <td>5.727e-06</td>\n",
" <td>7.543e-06</td>\n",
" <td>1.5784e-05</td>\n",
" <td>4.0507e-05</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
@ -1083,7 +1083,7 @@
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
@ -1102,7 +1102,6 @@
" <td>NaN</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>3</td>\n",
@ -1111,6 +1110,7 @@
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
@ -1125,7 +1125,6 @@
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>...</td>\n",
" <td>4.4884e-05</td>\n",
" <td>NaN</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
@ -1135,6 +1134,7 @@
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
@ -1149,48 +1149,48 @@
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>0.000200344</td>\n",
" <td>0.000399073</td>\n",
" <td>2</td>\n",
" <td>0</td>\n",
" <td>17</td>\n",
" <td>29</td>\n",
" <td>1</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>4</td>\n",
" <td>1</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>4 rows × 22 columns</p>\n",
"<p>4 rows × 23 columns</p>\n",
"</div>"
],
"text/plain": [
" task premin_time reorg_time partsol_time player_incomp_time \\\n",
"0 presat 25643.4 1.683e-06 5.611e-06 2.66e-05 \n",
"0 presat 3869.08 3.213e-06 9.079e-06 9.5752e-05 \n",
"1 sat NaN NaN NaN NaN \n",
"2 refinement NaN NaN NaN NaN \n",
"3 sat NaN NaN NaN NaN \n",
"\n",
" incomp_time split_all_let_time split_min_let_time split_cstr_time \\\n",
"0 1.2e-07 3.647e-06 8.365e-06 3.747e-06 \n",
"0 5.168e-06 5.727e-06 7.543e-06 1.5784e-05 \n",
"1 NaN NaN NaN NaN \n",
"2 NaN NaN NaN NaN \n",
"3 NaN NaN NaN NaN \n",
"\n",
" prob_init_build_time ... refine_time total_time n_classes n_refinement \\\n",
"0 2.5538e-05 ... NaN NaN NaN NaN \n",
"1 NaN ... NaN NaN 1 0 \n",
"2 NaN ... 4.4884e-05 NaN 1 1 \n",
"3 NaN ... NaN 0.000200344 2 0 \n",
" prob_init_build_time ... total_time n_classes n_refinement n_lit \\\n",
"0 4.0507e-05 ... NaN NaN NaN NaN \n",
"1 NaN ... NaN 1 0 3 \n",
"2 NaN ... NaN 1 1 10 \n",
"3 NaN ... 0.000399073 2 0 17 \n",
"\n",
" n_lit n_clauses n_iteration n_bisim_let n_min_states done \n",
"0 NaN NaN NaN 1 NaN NaN \n",
"1 3 6 0 NaN NaN NaN \n",
"2 10 16 NaN NaN NaN NaN \n",
"3 17 29 1 NaN 4 1 \n",
" n_clauses n_iteration n_letters_part n_bisim_let n_min_states done \n",
"0 NaN NaN 1 1 NaN NaN \n",
"1 6 0 NaN NaN NaN NaN \n",
"2 16 NaN NaN NaN NaN NaN \n",
"3 29 1 NaN NaN 4 1 \n",
"\n",
"[4 rows x 22 columns]"
"[4 rows x 23 columns]"
]
},
"metadata": {},
@ -1200,6 +1200,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Number of variables\n",
"0 NaN\n",
"1 3\n",
"2 10\n",
@ -1285,7 +1286,7 @@
"</svg>\n"
],
"text/plain": [
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7fcc35ac22a0> >"
"<spot.twa_graph; proxy of <Swig Object of type 'std::shared_ptr< spot::twa_graph > *' at 0x7f861bfcdc00> >"
]
},
"execution_count": 14,
@ -1297,6 +1298,7 @@
"si = spot.synthesis_info()\n",
"si.minimize_lvl = 3\n",
"aut_ms, table = spot.minimize_mealy(aut_s, si, display_log=True, return_log=True)\n",
"print(\"Number of variables\")\n",
"print(table[\"n_lit\"])\n",
"aut_ms"
]
@ -1347,13 +1349,13 @@
" <th>split_cstr_time</th>\n",
" <th>prob_init_build_time</th>\n",
" <th>...</th>\n",
" <th>refine_time</th>\n",
" <th>total_time</th>\n",
" <th>n_classes</th>\n",
" <th>n_refinement</th>\n",
" <th>n_lit</th>\n",
" <th>n_clauses</th>\n",
" <th>n_iteration</th>\n",
" <th>n_letters_part</th>\n",
" <th>n_bisim_let</th>\n",
" <th>n_min_states</th>\n",
" <th>done</th>\n",
@ -1363,15 +1365,15 @@
" <tr>\n",
" <th>0</th>\n",
" <td>presat</td>\n",
" <td>25643.5</td>\n",
" <td>1.563e-06</td>\n",
" <td>5.4e-06</td>\n",
" <td>2.0519e-05</td>\n",
" <td>1.3e-07</td>\n",
" <td>3.968e-06</td>\n",
" <td>9.698e-06</td>\n",
" <td>7.624e-06</td>\n",
" <td>3.211e-05</td>\n",
" <td>3869.14</td>\n",
" <td>2.863e-06</td>\n",
" <td>9.08e-06</td>\n",
" <td>6.0622e-05</td>\n",
" <td>4.679e-06</td>\n",
" <td>5.308e-06</td>\n",
" <td>8.59e-06</td>\n",
" <td>7.962e-06</td>\n",
" <td>4.0159e-05</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
@ -1379,7 +1381,7 @@
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
@ -1398,7 +1400,6 @@
" <td>NaN</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>3</td>\n",
@ -1407,6 +1408,7 @@
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
@ -1421,7 +1423,6 @@
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>...</td>\n",
" <td>4.4633e-05</td>\n",
" <td>NaN</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
@ -1431,6 +1432,7 @@
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
@ -1445,48 +1447,48 @@
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>...</td>\n",
" <td>NaN</td>\n",
" <td>0.000280675</td>\n",
" <td>0.000416464</td>\n",
" <td>2</td>\n",
" <td>0</td>\n",
" <td>17</td>\n",
" <td>29</td>\n",
" <td>1</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>4</td>\n",
" <td>1</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>4 rows × 22 columns</p>\n",
"<p>4 rows × 23 columns</p>\n",
"</div>"
],
"text/plain": [
" task premin_time reorg_time partsol_time player_incomp_time \\\n",
"0 presat 25643.5 1.563e-06 5.4e-06 2.0519e-05 \n",
"0 presat 3869.14 2.863e-06 9.08e-06 6.0622e-05 \n",
"1 sat NaN NaN NaN NaN \n",
"2 refinement NaN NaN NaN NaN \n",
"3 sat NaN NaN NaN NaN \n",
"\n",
" incomp_time split_all_let_time split_min_let_time split_cstr_time \\\n",
"0 1.3e-07 3.968e-06 9.698e-06 7.624e-06 \n",
"0 4.679e-06 5.308e-06 8.59e-06 7.962e-06 \n",
"1 NaN NaN NaN NaN \n",
"2 NaN NaN NaN NaN \n",
"3 NaN NaN NaN NaN \n",
"\n",
" prob_init_build_time ... refine_time total_time n_classes n_refinement \\\n",
"0 3.211e-05 ... NaN NaN NaN NaN \n",
"1 NaN ... NaN NaN 1 0 \n",
"2 NaN ... 4.4633e-05 NaN 1 1 \n",
"3 NaN ... NaN 0.000280675 2 0 \n",
" prob_init_build_time ... total_time n_classes n_refinement n_lit \\\n",
"0 4.0159e-05 ... NaN NaN NaN NaN \n",
"1 NaN ... NaN 1 0 3 \n",
"2 NaN ... NaN 1 1 10 \n",
"3 NaN ... 0.000416464 2 0 17 \n",
"\n",
" n_lit n_clauses n_iteration n_bisim_let n_min_states done \n",
"0 NaN NaN NaN 1 NaN NaN \n",
"1 3 6 0 NaN NaN NaN \n",
"2 10 16 NaN NaN NaN NaN \n",
"3 17 29 1 NaN 4 1 \n",
" n_clauses n_iteration n_letters_part n_bisim_let n_min_states done \n",
"0 NaN NaN 1 1 NaN NaN \n",
"1 6 0 NaN NaN NaN NaN \n",
"2 16 NaN NaN NaN NaN NaN \n",
"3 29 1 NaN NaN 4 1 \n",
"\n",
"[4 rows x 22 columns]"
"[4 rows x 23 columns]"
]
},
"metadata": {},
@ -1570,10 +1572,118 @@
" "
]
},
{
"cell_type": "markdown",
"id": "b10213b8",
"metadata": {},
"source": [
"# Testing partitioned relabeling"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "fd5ca506",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Conditions in orig machine: 8\n",
"Conditions in relabeled machine: 13\n"
]
}
],
"source": [
"def get_mealy():\n",
" return spot.split_2step(spot.automaton(\"\"\"HOA: v1\n",
"States: 2\n",
"Start: 0\n",
"AP: 11 \"u0accel0accel\" \"u0accel0f1dcon23p81b\" \"u0accel0f1dcon231b\" \"u0gear0f1dmin0f1dcon61b0f1dadd0gear0f1dcon241b1b1b\" \"u0gear0gear\" \"u0gear0f1dmax0f1dcon241b0f1dsub0gear0f1dcon241b1b1b\" \"u0steer0f1dsteering0angle0trackpos1b\" \"u0steer0steer\" \"p0p0gt0rpm0f1dcon5523231b\" \"p0p0lt0rpm0f1dcon32323231b\" \"p0p0lt0speed0f1dsub0target2speed0f1dmultp0f1dabs0steer1b0f1dcon248881b1b1b\"\n",
"acc-name: all\n",
"Acceptance: 0 t\n",
"properties: trans-labels explicit-labels state-acc deterministic\n",
"controllable-AP: 0 1 2 3 4 5 6 7\n",
"--BODY--\n",
"State: 0\n",
"[!0&!1&2&!3&4&!5&6&!7&!8&!9&!10] 0\n",
"[!0&1&!2&!3&4&!5&6&!7&!8&!9&10] 0\n",
"[!0&!1&2&!3&!4&5&6&!7&!8&9&!10] 0\n",
"[!0&1&!2&!3&!4&5&6&!7&!8&9&10] 0\n",
"[!0&!1&2&3&!4&!5&6&!7&8&!9&!10] 0\n",
"[!0&1&!2&3&!4&!5&6&!7&8&!9&10] 0\n",
"[!0&!1&2&!3&!4&5&!6&7&8&9 | !0&!1&2&!3&!4&5&6&!7&8&9 | !0&!1&2&!3&4&!5&!6&7&8&9 | !0&!1&2&!3&4&!5&6&!7&8&9 | !0&!1&2&3&!4&!5&!6&7&8&9 | !0&!1&2&3&!4&!5&6&!7&8&9 | !0&1&!2&!3&!4&5&!6&7&8&9 | !0&1&!2&!3&!4&5&6&!7&8&9 | !0&1&!2&!3&4&!5&!6&7&8&9 | !0&1&!2&!3&4&!5&6&!7&8&9 | !0&1&!2&3&!4&!5&!6&7&8&9 | !0&1&!2&3&!4&!5&6&!7&8&9 | 0&!1&!2&!3&!4&5&!6&7&8&9 | 0&!1&!2&!3&!4&5&6&!7&8&9 | 0&!1&!2&!3&4&!5&!6&7&8&9 | 0&!1&!2&!3&4&!5&6&!7&8&9 | 0&!1&!2&3&!4&!5&!6&7&8&9 | 0&!1&!2&3&!4&!5&6&!7&8&9] 1\n",
"State: 1\n",
"[!0&!1&2&!3&!4&5&!6&7 | !0&!1&2&!3&!4&5&6&!7 | !0&!1&2&!3&4&!5&!6&7 | !0&!1&2&!3&4&!5&6&!7 | !0&!1&2&3&!4&!5&!6&7 | !0&!1&2&3&!4&!5&6&!7 | !0&1&!2&!3&!4&5&!6&7 | !0&1&!2&!3&!4&5&6&!7 | !0&1&!2&!3&4&!5&!6&7 | !0&1&!2&!3&4&!5&6&!7 | !0&1&!2&3&!4&!5&!6&7 | !0&1&!2&3&!4&!5&6&!7 | 0&!1&!2&!3&!4&5&!6&7 | 0&!1&!2&!3&!4&5&6&!7 | 0&!1&!2&!3&4&!5&!6&7 | 0&!1&!2&!3&4&!5&6&!7 | 0&!1&!2&3&!4&!5&!6&7 | 0&!1&!2&3&!4&!5&6&!7] 1\n",
"--END--\"\"\"))\n",
"\n",
"def env_conditions(m):\n",
" sp = spot.get_state_players(m)\n",
" conds = []\n",
" for e in m.edges():\n",
" if sp[e.src]:\n",
" continue\n",
" if not e.cond in conds:\n",
" conds.append(e.cond)\n",
" return conds\n",
"print(\"Conditions in orig machine: \", len(env_conditions(get_mealy())))\n",
"ms = get_mealy()\n",
"# Relabel only env\n",
"spot.partitioned_game_relabel_here(ms, True, False, True, False)\n",
"print(\"Conditions in relabeled machine: \", len(env_conditions(ms)))"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "ee29da67",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Partitioned env letters: 13\n"
]
}
],
"source": [
"si = spot.synthesis_info()\n",
"si.minimize_lvl = 3\n",
"# Turn on relabeling\n",
"si.opt.set(\"max_letter_mult\", 100000)\n",
"\n",
"mm, log = spot.minimize_mealy(get_mealy(), si, return_log=True)\n",
"print(\"Partitioned env letters:\", log[\"n_letters_part\"][0])"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "0aec8019",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Partitioned env letters: 0\n"
]
}
],
"source": [
"# Turn off relabeling\n",
"si.opt.set(\"max_letter_mult\", 0)\n",
"\n",
"mm, log = spot.minimize_mealy(get_mealy(), si, return_log=True)\n",
"print(\"Partitioned env letters:\", log[\"n_letters_part\"][0])"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5c9fe115",
"id": "a92f4f43",
"metadata": {},
"outputs": [],
"source": []

File diff suppressed because it is too large Load diff

View file

@ -374,3 +374,21 @@ except RuntimeError as e:
str(e))
else:
report_missing_exception()
# Relabeling games must not use the
# globally reserved aps
aut = spot.make_twa_graph()
aut.new_states(2)
apin = buddy.bdd_ithvar(aut.register_ap("__AP_IN__"))
apout = buddy.bdd_ithvar(aut.register_ap("__AP_OUT__"))
aut.new_edge(0,1,apin & apout)
aut.new_edge(1,0,buddy.bdd_not(apin & apout))
spot.set_state_players(aut, [False, True])
try:
spot.partitioned_game_relabel_here(aut, True, True)
except RuntimeError as e:
tc.assertIn("You can not use __AP_IN__ or __AP_OUT__",
str(e))
else:
report_missing_exception()