product: add a product_or variant
* src/twaalgos/product.cc, src/twaalgos/product.hh: Implement the variance. * src/bin/autfilt.cc: Expose it. * src/tests/prodor.test: New file. * src/tests/Makefile.am: Add it. * NEWS: Mention it.
This commit is contained in:
parent
b77f7e24c3
commit
51a3cfcede
6 changed files with 331 additions and 84 deletions
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "product.hh"
|
||||
#include "twa/twagraph.hh"
|
||||
#include "twaalgos/complete.hh"
|
||||
#include <deque>
|
||||
#include <unordered_map>
|
||||
#include "misc/hash.hh"
|
||||
|
|
@ -37,77 +38,115 @@ namespace spot
|
|||
return wang32_hash(s.first ^ wang32_hash(s.second));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static
|
||||
twa_graph_ptr product_aux(const const_twa_graph_ptr& left,
|
||||
const const_twa_graph_ptr& right,
|
||||
unsigned left_state,
|
||||
unsigned right_state,
|
||||
bool and_acc)
|
||||
{
|
||||
std::unordered_map<product_state, unsigned, product_state_hash> s2n;
|
||||
std::deque<std::pair<product_state, unsigned>> todo;
|
||||
|
||||
twa_graph_ptr product(const const_twa_graph_ptr& left,
|
||||
const const_twa_graph_ptr& right,
|
||||
unsigned left_state,
|
||||
unsigned right_state)
|
||||
{
|
||||
std::unordered_map<product_state, unsigned, product_state_hash> s2n;
|
||||
std::deque<std::pair<product_state, unsigned>> todo;
|
||||
assert(left->get_dict() == right->get_dict());
|
||||
auto res = make_twa_graph(left->get_dict());
|
||||
res->copy_ap_of(left);
|
||||
res->copy_ap_of(right);
|
||||
auto left_num = left->num_sets();
|
||||
auto right_acc = right->get_acceptance();
|
||||
right_acc.shift_left(left_num);
|
||||
if (and_acc)
|
||||
right_acc.append_and(left->get_acceptance());
|
||||
else
|
||||
right_acc.append_or(acc_cond::acc_code(left->get_acceptance()));
|
||||
res->set_acceptance(left_num + right->num_sets(), right_acc);
|
||||
|
||||
assert(left->get_dict() == right->get_dict());
|
||||
auto res = make_twa_graph(left->get_dict());
|
||||
res->copy_ap_of(left);
|
||||
res->copy_ap_of(right);
|
||||
auto left_num = left->num_sets();
|
||||
auto right_acc = right->get_acceptance();
|
||||
right_acc.shift_left(left_num);
|
||||
right_acc.append_and(left->get_acceptance());
|
||||
res->set_acceptance(left_num + right->num_sets(), right_acc);
|
||||
auto v = new product_states;
|
||||
res->set_named_prop("product-states", v);
|
||||
|
||||
auto v = new product_states;
|
||||
res->set_named_prop("product-states", v);
|
||||
|
||||
auto new_state =
|
||||
[&](unsigned left_state, unsigned right_state) -> unsigned
|
||||
{
|
||||
product_state x(left_state, right_state);
|
||||
auto p = s2n.emplace(x, 0);
|
||||
if (p.second) // This is a new state
|
||||
{
|
||||
p.first->second = res->new_state();
|
||||
todo.emplace_back(x, p.first->second);
|
||||
assert(p.first->second == v->size());
|
||||
v->push_back(x);
|
||||
}
|
||||
return p.first->second;
|
||||
};
|
||||
|
||||
res->set_init_state(new_state(left_state, right_state));
|
||||
if (right_acc.is_false())
|
||||
// Do not bother doing any work if the resulting acceptance is
|
||||
// false.
|
||||
return res;
|
||||
while (!todo.empty())
|
||||
{
|
||||
auto top = todo.front();
|
||||
todo.pop_front();
|
||||
for (auto& l: left->out(top.first.first))
|
||||
for (auto& r: right->out(top.first.second))
|
||||
auto new_state =
|
||||
[&](unsigned left_state, unsigned right_state) -> unsigned
|
||||
{
|
||||
product_state x(left_state, right_state);
|
||||
auto p = s2n.emplace(x, 0);
|
||||
if (p.second) // This is a new state
|
||||
{
|
||||
auto cond = l.cond & r.cond;
|
||||
if (cond == bddfalse)
|
||||
continue;
|
||||
auto dst = new_state(l.dst, r.dst);
|
||||
res->new_edge(top.second, dst, cond,
|
||||
res->acc().join(left->acc(), l.acc,
|
||||
right->acc(), r.acc));
|
||||
// If right is deterministic, we can abort immediately!
|
||||
p.first->second = res->new_state();
|
||||
todo.emplace_back(x, p.first->second);
|
||||
assert(p.first->second == v->size());
|
||||
v->push_back(x);
|
||||
}
|
||||
}
|
||||
return p.first->second;
|
||||
};
|
||||
|
||||
return res;
|
||||
res->set_init_state(new_state(left_state, right_state));
|
||||
if (right_acc.is_false())
|
||||
// Do not bother doing any work if the resulting acceptance is
|
||||
// false.
|
||||
return res;
|
||||
while (!todo.empty())
|
||||
{
|
||||
auto top = todo.front();
|
||||
todo.pop_front();
|
||||
for (auto& l: left->out(top.first.first))
|
||||
for (auto& r: right->out(top.first.second))
|
||||
{
|
||||
auto cond = l.cond & r.cond;
|
||||
if (cond == bddfalse)
|
||||
continue;
|
||||
auto dst = new_state(l.dst, r.dst);
|
||||
res->new_edge(top.second, dst, cond,
|
||||
res->acc().join(left->acc(), l.acc,
|
||||
right->acc(), r.acc));
|
||||
// If right is deterministic, we can abort immediately!
|
||||
}
|
||||
}
|
||||
|
||||
res->prop_deterministic(left->is_deterministic()
|
||||
&& right->is_deterministic());
|
||||
res->prop_stutter_invariant(left->is_stutter_invariant()
|
||||
&& right->is_stutter_invariant());
|
||||
res->prop_stutter_sensitive(left->is_stutter_sensitive()
|
||||
&& right->is_stutter_sensitive());
|
||||
res->prop_state_based_acc(left->has_state_based_acc()
|
||||
&& right->has_state_based_acc());
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
twa_graph_ptr product(const const_twa_graph_ptr& left,
|
||||
const const_twa_graph_ptr& right)
|
||||
const const_twa_graph_ptr& right,
|
||||
unsigned left_state,
|
||||
unsigned right_state)
|
||||
{
|
||||
return product_aux(left, right, left_state, right_state, true);
|
||||
}
|
||||
|
||||
twa_graph_ptr product(const const_twa_graph_ptr& left,
|
||||
const const_twa_graph_ptr& right)
|
||||
{
|
||||
return product(left, right,
|
||||
left->get_init_state_number(),
|
||||
right->get_init_state_number());
|
||||
}
|
||||
|
||||
twa_graph_ptr product_or(const const_twa_graph_ptr& left,
|
||||
const const_twa_graph_ptr& right,
|
||||
unsigned left_state,
|
||||
unsigned right_state)
|
||||
{
|
||||
return product_aux(tgba_complete(left),
|
||||
tgba_complete(right),
|
||||
left_state, right_state, false);
|
||||
}
|
||||
|
||||
twa_graph_ptr product_or(const const_twa_graph_ptr& left,
|
||||
const const_twa_graph_ptr& right)
|
||||
{
|
||||
return product_or(left, right,
|
||||
left->get_init_state_number(),
|
||||
right->get_init_state_number());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// -*- coding: utf-8 -*-
|
||||
// Copyright (C) 2014 Laboratoire de Recherche et
|
||||
// Copyright (C) 2014, 2015 Laboratoire de Recherche et
|
||||
// Développement de l'Epita (LRDE).
|
||||
//
|
||||
// This file is part of Spot, a model checking library.
|
||||
|
|
@ -32,11 +32,22 @@ namespace spot
|
|||
|
||||
SPOT_API
|
||||
twa_graph_ptr product(const const_twa_graph_ptr& left,
|
||||
const const_twa_graph_ptr& right);
|
||||
const const_twa_graph_ptr& right);
|
||||
|
||||
SPOT_API
|
||||
twa_graph_ptr product(const const_twa_graph_ptr& left,
|
||||
const const_twa_graph_ptr& right,
|
||||
unsigned left_state,
|
||||
unsigned right_state);
|
||||
|
||||
SPOT_API
|
||||
twa_graph_ptr product_or(const const_twa_graph_ptr& left,
|
||||
const const_twa_graph_ptr& right);
|
||||
|
||||
SPOT_API
|
||||
twa_graph_ptr product_or(const const_twa_graph_ptr& left,
|
||||
const const_twa_graph_ptr& right,
|
||||
unsigned left_state,
|
||||
unsigned right_state);
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue