zlktree: replace std::vector<bool> by bitvect in ACD
On the example from previous patch, the number of instruction fetches goes from 18490399159 down to 18248898077. * spot/twaalgos/zlktree.cc, spot/twaalgos/zlktree.hh (acd): Use bitvect instead of std::vector<bool> in nodes. This make is easier to update an edge of a bitvector shared by multiple nodes set after pruning non-maximal sets from an SCC. Also compute the set of states hit by the edges at the very end, once all nodes are known. * spot/twaalgos/sccinfo.cc, spot/twaalgos/sccinfo.hh, spot/twaalgos/genem.cc, spot/twaalgos/genem.hh: Adjust to work with bitvect as filter.
This commit is contained in:
parent
6aa2079079
commit
2d1cb0ddcd
6 changed files with 41 additions and 33 deletions
|
|
@ -271,7 +271,7 @@ namespace spot
|
|||
bool
|
||||
maximal_accepting_loops_for_scc(const scc_info& si, unsigned scc,
|
||||
const acc_cond& forced_acc,
|
||||
const std::vector<bool>& keep,
|
||||
const bitvect& keep,
|
||||
std::function<void(const scc_info&,
|
||||
unsigned)> callback)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <spot/twaalgos/emptiness.hh>
|
||||
#include <spot/twaalgos/sccinfo.hh>
|
||||
#include <spot/misc/bitvect.hh>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
|
@ -73,13 +74,13 @@ namespace spot
|
|||
/// `si->inner_edges_of(num)` lists the relevant edges.
|
||||
///
|
||||
/// The search is restricted to a set of edges of the given SCC
|
||||
/// for which \a keep (an array indexed by edge numbers) is true.
|
||||
/// for which \a keep (a bitvect indexed by edge numbers) is true.
|
||||
///
|
||||
/// Returns false iff no accepting loop where found.
|
||||
SPOT_API bool
|
||||
maximal_accepting_loops_for_scc(const scc_info& si, unsigned scc,
|
||||
const acc_cond& forced_acc,
|
||||
const std::vector<bool>& keep,
|
||||
const bitvect& keep,
|
||||
std::function<void(const scc_info&,
|
||||
unsigned)> callback);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -888,7 +888,7 @@ namespace spot
|
|||
if (auto choice = f(e, e.dst, si->get_filter_data());
|
||||
choice != edge_filter_choice::keep)
|
||||
return choice;
|
||||
if (!(*d.keep_)[d.aut_->edge_number(e)] || (d.cut_sets_ & e.acc))
|
||||
if (!(*d.keep_).get(d.aut_->edge_number(e)) || (d.cut_sets_ & e.acc))
|
||||
return edge_filter_choice::cut;
|
||||
return edge_filter_choice::keep;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include <vector>
|
||||
#include <spot/twa/twagraph.hh>
|
||||
#include <spot/twaalgos/emptiness.hh>
|
||||
#include <spot/misc/bitvect.hh>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
|
@ -792,7 +793,7 @@ namespace spot
|
|||
const_twa_graph_ptr aut_;
|
||||
acc_cond old_acc_;
|
||||
bool restore_old_acc_ = false;
|
||||
const std::vector<bool>* keep_ = nullptr;
|
||||
const bitvect* keep_ = nullptr;
|
||||
|
||||
static scc_info::edge_filter_choice
|
||||
filter_scc_and_mark_(const twa_graph::edge_storage_t& e,
|
||||
|
|
@ -833,7 +834,7 @@ namespace spot
|
|||
scc_and_mark_filter(const scc_info& lower_si,
|
||||
unsigned lower_scc,
|
||||
acc_cond::mark_t cut_sets,
|
||||
const std::vector<bool>& keep)
|
||||
const bitvect& keep)
|
||||
: scc_and_mark_filter(lower_si, lower_scc, cut_sets)
|
||||
{
|
||||
keep_ = &keep;
|
||||
|
|
|
|||
|
|
@ -20,11 +20,9 @@
|
|||
#include "config.h"
|
||||
#include <iostream>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <spot/twaalgos/zlktree.hh>
|
||||
#include <spot/twaalgos/genem.hh>
|
||||
#include <spot/misc/escape.hh>
|
||||
#include <spot/misc/bitvect.hh>
|
||||
|
||||
namespace spot
|
||||
{
|
||||
|
|
@ -380,16 +378,16 @@ namespace spot
|
|||
{
|
||||
if (bitvectors.size() > 2 * n)
|
||||
return;
|
||||
bitvectors.emplace_back(nedges, false);
|
||||
bitvectors.emplace_back(nstates, false);
|
||||
bitvectors.emplace_back(std::unique_ptr<bitvect>(make_bitvect(nedges)));
|
||||
bitvectors.emplace_back(std::unique_ptr<bitvect>(make_bitvect(nstates)));
|
||||
};
|
||||
auto edge_vector = [&] (unsigned n) -> std::vector<bool>&
|
||||
auto edge_vector = [&] (unsigned n) -> bitvect&
|
||||
{
|
||||
return bitvectors[2 * n];
|
||||
return *bitvectors[2 * n];
|
||||
};
|
||||
auto state_vector = [&] (unsigned n) -> std::vector<bool>&
|
||||
auto state_vector = [&] (unsigned n) -> bitvect&
|
||||
{
|
||||
return bitvectors[2 * n + 1];
|
||||
return *bitvectors[2 * n + 1];
|
||||
};
|
||||
allocate_vectors_maybe(0);
|
||||
|
||||
|
|
@ -416,8 +414,8 @@ namespace spot
|
|||
n.scc = scc;
|
||||
for (auto& e: si_->inner_edges_of(scc))
|
||||
{
|
||||
n.edges[aut->edge_number(e)] = true;
|
||||
n.states[e.src] = true;
|
||||
n.edges.set(aut->edge_number(e));
|
||||
n.states.set(e.src);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -482,11 +480,7 @@ namespace spot
|
|||
n.parent = node;
|
||||
n.level = lvl + 1;
|
||||
n.scc = scc;
|
||||
bv->foreach_set_index([&](unsigned e)
|
||||
{
|
||||
n.edges[e] = true;
|
||||
n.states[aut->edge_storage(e).src] = true;
|
||||
});
|
||||
n.edges |= *bv;
|
||||
}
|
||||
unsigned after_size = nodes_.size();
|
||||
unsigned children = after_size - before_size;
|
||||
|
|
@ -534,6 +528,16 @@ namespace spot
|
|||
++node.level;
|
||||
trees_[scc].max_level = std::max(trees_[scc].max_level, node.level);
|
||||
}
|
||||
// Compute the set of states hit by each edge vector.
|
||||
// Skip the first ones, because they are used in the roots of each tree
|
||||
// and have already been filled.
|
||||
unsigned nv = bitvectors.size();
|
||||
for (unsigned n = 2; n < nv; n += 2)
|
||||
bitvectors[n]->foreach_set_index([&aut,
|
||||
&states=*bitvectors[n+1]](unsigned e)
|
||||
{
|
||||
states.set(aut->edge_storage(e).src);
|
||||
});
|
||||
}
|
||||
|
||||
unsigned acd::leftmost_branch_(unsigned n, unsigned state) const
|
||||
|
|
@ -546,7 +550,7 @@ namespace spot
|
|||
unsigned child = first_child;
|
||||
do
|
||||
{
|
||||
if (nodes_[child].states[state])
|
||||
if (nodes_[child].states.get(state))
|
||||
{
|
||||
n = child;
|
||||
goto loop;
|
||||
|
|
@ -567,7 +571,7 @@ namespace spot
|
|||
if (trees_[scc].trivial) // the branch is irrelevant for transiant SCCs
|
||||
return 0;
|
||||
unsigned n = trees_[scc].root;
|
||||
assert(nodes_[n].states[s]);
|
||||
assert(nodes_[n].states.get(s));
|
||||
return leftmost_branch_(n, s);
|
||||
}
|
||||
|
||||
|
|
@ -582,7 +586,7 @@ namespace spot
|
|||
|
||||
unsigned child = 0;
|
||||
unsigned dst = aut_->edge_storage(edge).dst;
|
||||
while (!nodes_[branch].edges[edge])
|
||||
while (!nodes_[branch].edges.get(edge))
|
||||
{
|
||||
unsigned parent = nodes_[branch].parent;
|
||||
if (SPOT_UNLIKELY(branch == parent))
|
||||
|
|
@ -604,7 +608,7 @@ namespace spot
|
|||
do
|
||||
{
|
||||
child = nodes_[child].next_sibling;
|
||||
if (nodes_[child].states[dst])
|
||||
if (nodes_[child].states.get(dst))
|
||||
return {leftmost_branch_(child, dst), lvl};
|
||||
}
|
||||
while (child != start_child);
|
||||
|
|
@ -643,7 +647,7 @@ namespace spot
|
|||
const char* sep = "T: ";
|
||||
for (unsigned n = 1; n <= nedges; ++n)
|
||||
{
|
||||
bool val = n < nedges && edges[n]
|
||||
bool val = n < nedges && edges.get(n)
|
||||
&& si_->scc_of(aut_->edge_storage(n).dst) == scc;
|
||||
if (val != lastval)
|
||||
{
|
||||
|
|
@ -675,7 +679,7 @@ namespace spot
|
|||
sep = "\nQ: ";
|
||||
for (unsigned n = 0; n <= nstates; ++n)
|
||||
{
|
||||
bool val = n < nstates && states[n] && si_->scc_of(n) == scc;
|
||||
bool val = n < nstates && states.get(n) && si_->scc_of(n) == scc;
|
||||
if (val != lastval)
|
||||
{
|
||||
if (lastval)
|
||||
|
|
@ -708,7 +712,7 @@ namespace spot
|
|||
os << " class=\"";
|
||||
const char* sep = "";
|
||||
for (unsigned n = 0; n < nstates; ++n)
|
||||
if (states[n] && si_->scc_of(n) == scc)
|
||||
if (states.get(n) && si_->scc_of(n) == scc)
|
||||
{
|
||||
os << sep << "acdS" << n << '\n';
|
||||
sep = " ";
|
||||
|
|
@ -746,7 +750,7 @@ namespace spot
|
|||
auto& edges = nodes_[n].edges;
|
||||
unsigned nedges = edges.size();
|
||||
for (unsigned e = 1; e < nedges; ++e)
|
||||
if (edges[e] && si_->scc_of(aut_->edge_storage(e).dst) == scc)
|
||||
if (edges.get(e) && si_->scc_of(aut_->edge_storage(e).dst) == scc)
|
||||
res.push_back(e);
|
||||
return res;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
#include <iosfwd>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <spot/misc/bitvect.hh>
|
||||
#include <spot/twa/twagraph.hh>
|
||||
#include <spot/twaalgos/sccinfo.hh>
|
||||
|
||||
|
|
@ -285,9 +287,9 @@ namespace spot
|
|||
unsigned first_child = 0;
|
||||
unsigned level;
|
||||
unsigned scc;
|
||||
std::vector<bool>& edges;
|
||||
std::vector<bool>& states;
|
||||
acd_node(std::vector<bool>& e, std::vector<bool>& s) noexcept
|
||||
bitvect& edges;
|
||||
bitvect& states;
|
||||
acd_node(bitvect& e, bitvect& s) noexcept
|
||||
: edges(e), states(s)
|
||||
{
|
||||
}
|
||||
|
|
@ -297,7 +299,7 @@ namespace spot
|
|||
std::deque<acd_node> nodes_;
|
||||
// Likewise for bitvectors: this is the support for all edge vectors
|
||||
// and state vectors used in acd_node.
|
||||
std::deque<std::vector<bool>> bitvectors;
|
||||
std::deque<std::unique_ptr<bitvect>> bitvectors;
|
||||
// Information about a tree of the ACD. Each tree correspond
|
||||
// to an SCC.
|
||||
struct scc_data
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue