sccinfo: store live states in a separate stack
Suggested by Etienne. The command in #96 now takes 9min 35s. * src/twaalgos/sccinfo.cc, src/twaalgos/sccinfo.hh: Here.
This commit is contained in:
parent
c8cf86b081
commit
b13b591f11
2 changed files with 22 additions and 19 deletions
|
|
@ -52,6 +52,7 @@ namespace spot
|
||||||
sccof_.resize(n, -1U);
|
sccof_.resize(n, -1U);
|
||||||
|
|
||||||
typedef std::list<scc> stack_type;
|
typedef std::list<scc> stack_type;
|
||||||
|
std::deque<unsigned> live;
|
||||||
stack_type root_; // Stack of SCC roots.
|
stack_type root_; // Stack of SCC roots.
|
||||||
std::vector<int> h_(n, 0);
|
std::vector<int> h_(n, 0);
|
||||||
// Map of visited states. Values > 0 designate maximal SCC.
|
// Map of visited states. Values > 0 designate maximal SCC.
|
||||||
|
|
@ -80,6 +81,7 @@ namespace spot
|
||||||
h_[init] = num_;
|
h_[init] = num_;
|
||||||
root_.emplace_front(num_, bddfalse, 0U);
|
root_.emplace_front(num_, bddfalse, 0U);
|
||||||
todo_.emplace(init, aut->out(init).begin());
|
todo_.emplace(init, aut->out(init).begin());
|
||||||
|
live.emplace_back(init);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!todo_.empty())
|
while (!todo_.empty())
|
||||||
|
|
@ -96,11 +98,6 @@ namespace spot
|
||||||
// Backtrack TODO_.
|
// Backtrack TODO_.
|
||||||
todo_.pop();
|
todo_.pop();
|
||||||
|
|
||||||
// Fill STATES with any state removed, so that
|
|
||||||
// remove_component() does not have to traverse the SCC
|
|
||||||
// again.
|
|
||||||
root_.front().node.states_.push_front(curr);
|
|
||||||
|
|
||||||
// When backtracking the root of an SCC, we must also
|
// When backtracking the root of an SCC, we must also
|
||||||
// remove that SCC from the ARC/ROOT stacks. We must
|
// remove that SCC from the ARC/ROOT stacks. We must
|
||||||
// discard from H all reachable states from this SCC.
|
// discard from H all reachable states from this SCC.
|
||||||
|
|
@ -108,17 +105,27 @@ namespace spot
|
||||||
if (root_.front().index == h_[curr])
|
if (root_.front().index == h_[curr])
|
||||||
{
|
{
|
||||||
int num = node_.size();
|
int num = node_.size();
|
||||||
for (auto s: root_.front().node.states_)
|
|
||||||
{
|
|
||||||
sccof_[s] = num;
|
|
||||||
h_[s] = num + 1;
|
|
||||||
}
|
|
||||||
bdd cond = root_.front().in_cond;
|
bdd cond = root_.front().in_cond;
|
||||||
auto acc = root_.front().node.acc_marks();
|
auto acc = root_.front().node.acc_marks();
|
||||||
bool triv = root_.front().node.is_trivial();
|
bool triv = root_.front().node.is_trivial();
|
||||||
node_.emplace_back(acc, triv);
|
node_.emplace_back(acc, triv);
|
||||||
|
|
||||||
|
// Move all elements of this SCC from the live stack
|
||||||
|
// to the the node.
|
||||||
|
auto i = std::find(live.rbegin(), live.rend(), curr);
|
||||||
|
assert(i != live.rend());
|
||||||
|
++i; // Because base() does -1
|
||||||
|
auto& nbs = node_.back().states_;
|
||||||
|
nbs.insert(nbs.end(), i.base(), live.end());
|
||||||
|
live.erase(i.base(), live.end());
|
||||||
|
|
||||||
|
for (unsigned s: nbs)
|
||||||
|
{
|
||||||
|
sccof_[s] = num;
|
||||||
|
h_[s] = num + 1;
|
||||||
|
}
|
||||||
|
|
||||||
std::swap(node_.back().succ_, root_.front().node.succ_);
|
std::swap(node_.back().succ_, root_.front().node.succ_);
|
||||||
std::swap(node_.back().states_, root_.front().node.states_);
|
|
||||||
node_.back().accepting_ =
|
node_.back().accepting_ =
|
||||||
!triv && root_.front().node.accepting_;
|
!triv && root_.front().node.accepting_;
|
||||||
node_.back().rejecting_ =
|
node_.back().rejecting_ =
|
||||||
|
|
@ -150,6 +157,7 @@ namespace spot
|
||||||
h_[dest] = --num_;
|
h_[dest] = --num_;
|
||||||
root_.emplace_front(num_, cond, acc);
|
root_.emplace_front(num_, cond, acc);
|
||||||
todo_.emplace(dest, aut->out(dest).begin());
|
todo_.emplace(dest, aut->out(dest).begin());
|
||||||
|
live.emplace_back(dest);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -181,7 +189,6 @@ namespace spot
|
||||||
// top of ROOT that have an index lesser than the one of
|
// top of ROOT that have an index lesser than the one of
|
||||||
// the SCC of S2 (called the "threshold").
|
// the SCC of S2 (called the "threshold").
|
||||||
int threshold = spi;
|
int threshold = spi;
|
||||||
std::list<unsigned> states;
|
|
||||||
scc_succs succs;
|
scc_succs succs;
|
||||||
bool is_accepting = false;
|
bool is_accepting = false;
|
||||||
// If this is a self-loop, check its acceptance alone.
|
// If this is a self-loop, check its acceptance alone.
|
||||||
|
|
@ -194,8 +201,6 @@ namespace spot
|
||||||
acc |= root_.front().node.acc_;
|
acc |= root_.front().node.acc_;
|
||||||
acc |= root_.front().in_acc;
|
acc |= root_.front().in_acc;
|
||||||
is_accepting |= root_.front().node.accepting_;
|
is_accepting |= root_.front().node.accepting_;
|
||||||
states.splice(states.end(), root_.front().node.states_);
|
|
||||||
|
|
||||||
succs.insert(succs.end(),
|
succs.insert(succs.end(),
|
||||||
root_.front().node.succ_.begin(),
|
root_.front().node.succ_.begin(),
|
||||||
root_.front().node.succ_.end());
|
root_.front().node.succ_.end());
|
||||||
|
|
@ -213,8 +218,6 @@ namespace spot
|
||||||
root_.front().node.acc_ |= acc;
|
root_.front().node.acc_ |= acc;
|
||||||
root_.front().node.accepting_ |= is_accepting
|
root_.front().node.accepting_ |= is_accepting
|
||||||
|| aut->acc().accepting(root_.front().node.acc_);
|
|| aut->acc().accepting(root_.front().node.acc_);
|
||||||
root_.front().node.states_.splice(root_.front().node.states_.end(),
|
|
||||||
states);
|
|
||||||
root_.front().node.succ_.insert(root_.front().node.succ_.end(),
|
root_.front().node.succ_.insert(root_.front().node.succ_.end(),
|
||||||
succs.begin(), succs.end());
|
succs.begin(), succs.end());
|
||||||
// This SCC is no longer trivial.
|
// This SCC is no longer trivial.
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ namespace spot
|
||||||
protected:
|
protected:
|
||||||
scc_succs succ_;
|
scc_succs succ_;
|
||||||
acc_cond::mark_t acc_;
|
acc_cond::mark_t acc_;
|
||||||
std::list<unsigned> states_; // States of the component
|
std::vector<unsigned> states_; // States of the component
|
||||||
bool trivial_:1;
|
bool trivial_:1;
|
||||||
bool accepting_:1; // Necessarily accepting
|
bool accepting_:1; // Necessarily accepting
|
||||||
bool rejecting_:1; // Necessarily rejecting
|
bool rejecting_:1; // Necessarily rejecting
|
||||||
|
|
@ -86,7 +86,7 @@ namespace spot
|
||||||
return acc_;
|
return acc_;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::list<unsigned>& states() const
|
const std::vector<unsigned>& states() const
|
||||||
{
|
{
|
||||||
return states_;
|
return states_;
|
||||||
}
|
}
|
||||||
|
|
@ -149,7 +149,7 @@ namespace spot
|
||||||
auto rend() const
|
auto rend() const
|
||||||
SPOT_RETURN(node_.rend());
|
SPOT_RETURN(node_.rend());
|
||||||
|
|
||||||
const std::list<unsigned>& states_of(unsigned scc) const
|
const std::vector<unsigned>& states_of(unsigned scc) const
|
||||||
{
|
{
|
||||||
return node(scc).states();
|
return node(scc).states();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue