()
| 134 | type Nodeset map[ast.PredicateSym]struct{} |
| 135 | |
| 136 | func (dep depGraph) sccs() []Nodeset { |
| 137 | // Kosaraju's algorithm |
| 138 | // Forward pass. |
| 139 | S := make(nodelist, 0, len(dep)) // postorder stack |
| 140 | seen := make(Nodeset) |
| 141 | var visit func(node ast.PredicateSym) |
| 142 | visit = func(node ast.PredicateSym) { |
| 143 | if _, ok := seen[node]; !ok { |
| 144 | seen[node] = struct{}{} |
| 145 | for e := range dep[node] { |
| 146 | visit(e) |
| 147 | } |
| 148 | S = append(S, node) |
| 149 | } |
| 150 | } |
| 151 | for node := range dep { |
| 152 | visit(node) |
| 153 | } |
| 154 | |
| 155 | // Reverse pass. |
| 156 | rev := dep.transpose() |
| 157 | var scc Nodeset |
| 158 | seen = make(Nodeset) |
| 159 | var rvisit func(node ast.PredicateSym) |
| 160 | rvisit = func(node ast.PredicateSym) { |
| 161 | if _, ok := seen[node]; !ok { |
| 162 | seen[node] = struct{}{} |
| 163 | scc[node] = struct{}{} |
| 164 | for e := range rev[node] { |
| 165 | rvisit(e) |
| 166 | } |
| 167 | } |
| 168 | } |
| 169 | var sccs []Nodeset |
| 170 | for len(S) > 0 { |
| 171 | top := S[len(S)-1] |
| 172 | S = S[:len(S)-1] // pop |
| 173 | if _, ok := seen[top]; !ok { |
| 174 | scc = make(Nodeset) |
| 175 | rvisit(top) |
| 176 | sccs = append(sccs, scc) |
| 177 | } |
| 178 | } |
| 179 | return sccs |
| 180 | } |
| 181 | |
| 182 | // sortResult sorts the strata topologically (ignoring cycles). |
| 183 | func (dep depGraph) sortResult(strata []Nodeset, predToStratumMap map[ast.PredicateSym]int) ([]Nodeset, map[ast.PredicateSym]int) { |
no test coverage detected