3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
8 * Full author contact details are available in file CREDITS.
23 bool Graph::bfs_init(int s, bool clear_visited)
31 vector<Vertex>::iterator it = vertices_.begin();
32 vector<Vertex>::iterator en = vertices_.end();
33 for (; it != en; ++it)
36 if (!vertices_[s].visited) {
38 vertices_[s].visited = true;
45 Graph::getReachableTo(int target, bool clear_visited)
48 if (!bfs_init(target, clear_visited))
51 // Here's the logic, which is shared by the other routines.
52 // Q_ holds a list of nodes we have been able to reach (in this
53 // case, reach backwards). It is initialized to the current node
54 // by bfs_init, and then we recurse, adding the nodes we can reach
55 // from the current node as we go. That makes it a breadth-first
58 int const current = Q_.front();
60 if (current != target || formats.get(target).name() != "lyx")
61 result.push_back(current);
63 vector<Arrow>::iterator it = vertices_[current].in_arrows.begin();
64 vector<Arrow>::iterator const end = vertices_[current].in_arrows.end();
65 for (; it != end; ++it) {
66 const int cv = it->vertex;
67 if (!vertices_[cv].visited) {
68 vertices_[cv].visited = true;
79 Graph::getReachable(int from, bool only_viewable,
83 if (!bfs_init(from, clear_visited))
87 int const current = Q_.front();
89 Format const & format = formats.get(current);
90 if (!only_viewable || !format.viewer().empty())
91 result.push_back(current);
92 else if (format.isChildFormat()) {
93 Format const * const parent =
94 formats.getFormat(format.parentFormat());
95 if (parent && !parent->viewer().empty())
96 result.push_back(current);
99 vector<Arrow>::const_iterator cit =
100 vertices_[current].out_arrows.begin();
101 vector<Arrow>::const_iterator end =
102 vertices_[current].out_arrows.end();
103 for (; cit != end; ++cit) {
104 int const cv = cit->vertex;
105 if (!vertices_[cv].visited) {
106 vertices_[cv].visited = true;
116 bool Graph::isReachable(int from, int to)
121 if (to < 0 || !bfs_init(from))
124 while (!Q_.empty()) {
125 int const current = Q_.front();
130 vector<Arrow>::const_iterator cit =
131 vertices_[current].out_arrows.begin();
132 vector<Arrow>::const_iterator end =
133 vertices_[current].out_arrows.end();
134 for (; cit != end; ++cit) {
135 int const cv = cit->vertex;
136 if (!vertices_[cv].visited) {
137 vertices_[cv].visited = true;
147 Graph::EdgePath const Graph::getPath(int from, int to)
153 if (to < 0 || !bfs_init(from))
156 // pair<vertex, edge>
157 vector<pair<int, int> > prev(vertices_.size());
160 while (!Q_.empty()) {
161 int const current = Q_.front();
164 vector<Arrow>::const_iterator const beg =
165 vertices_[current].out_arrows.begin();
166 vector<Arrow>::const_iterator cit = beg;
167 vector<Arrow>::const_iterator end =
168 vertices_[current].out_arrows.end();
169 for (; cit != end; ++cit) {
170 int const cv = cit->vertex;
171 if (!vertices_[cv].visited) {
172 vertices_[cv].visited = true;
174 // FIXME This will not do for finding multiple paths.
175 // Perhaps we need a vector, or a set. We'll also want
176 // to add this info, even if the node is visited, so
177 // outside this conditional.
178 prev[cv] = pair<int, int>(current, cit->edge);
190 path.push_back(prev[to].second);
193 reverse(path.begin(), path.end());
198 void Graph::init(int size)
200 vertices_ = vector<Vertex>(size);
205 void Graph::addEdge(int from, int to)
207 vertices_[to].in_arrows.push_back(Arrow(from, numedges_));
208 vertices_[from].out_arrows.push_back(Arrow(to, numedges_));