Commit b13b591f authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz
Browse files

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.
parent c8cf86b0
...@@ -52,6 +52,7 @@ namespace spot ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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();
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment