org.apache.drill.common.graph.GraphAlgos Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.drill.common.graph;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class GraphAlgos {
static final Logger logger = LoggerFactory.getLogger(GraphAlgos.class);
public static class TopoSorter> {
final List.Node> sorted = new LinkedList.Node>();
final AdjacencyList rGraph;
private TopoSorter(AdjacencyList graph, boolean reverse) {
graph.clearVisited();
if (reverse) {
this.rGraph = graph.getReversedList();
} else {
this.rGraph = graph;
}
Collection.Node> sourceNodes = rGraph.getInternalRootNodes();
for (AdjacencyList.Node n : sourceNodes) {
visit(n);
}
}
private void visit(AdjacencyList.Node n) {
if (n.visited) {
return;
}
n.visited = true;
List.Node>> edges = rGraph.getAdjacent(n);
if (edges != null) {
for (Edge.Node> e : edges) {
visit(e.to);
}
}
sorted.add(n);
}
/**
* Execute a depth-first sort on the reversed DAG.
*
* @param graph
* The adjacency list for the DAG.
* @param sourceNodes
* List of nodes that
* @return
*/
static > List.Node> sortInternal(AdjacencyList graph, boolean reverse) {
TopoSorter ts = new TopoSorter(graph, reverse);
return ts.sorted;
}
public static > List sort(Graph graph) {
AdjacencyList l = graph.getAdjList();
return l.convert(sortInternal(l, true));
}
public static > List sortLogical(Graph graph) {
AdjacencyList l = graph.getAdjList();
return l.convert(sortInternal(l, false));
}
}
static > List.Node>> checkDirected(AdjacencyList graph) {
Tarjan t = new Tarjan();
List.Node>> subgraphs = t.executeTarjan(graph);
for (Iterator.Node>> i = subgraphs.iterator(); i.hasNext();) {
List.Node> l = i.next();
if (l.size() == 1) {
i.remove();
}
}
return subgraphs;
}
public static > List.Node>> checkDirected(Graph graph) {
return checkDirected(graph.getAdjList());
}
public static class Tarjan> {
private int index = 0;
private List.Node> stack = new LinkedList.Node>();
private List.Node>> SCC = new LinkedList.Node>>();
public List.Node>> executeTarjan(AdjacencyList graph) {
SCC.clear();
index = 0;
stack.clear();
if (graph != null) {
List.Node> nodeList = new LinkedList.Node>(graph.getNodeSet());
for (AdjacencyList.Node node : nodeList) {
if (node.index == -1) {
tarjan(node, graph);
}
}
}
return SCC;
}
private List.Node>> tarjan(AdjacencyList.Node v, AdjacencyList list) {
v.index = index;
v.lowlink = index;
index++;
stack.add(0, v);
List.Node>> l = list.getAdjacent(v);
if (l != null) {
for (Edge.Node> e : l) {
AdjacencyList.Node n = e.to;
if (n.index == -1) {
tarjan(n, list);
v.lowlink = Math.min(v.lowlink, n.lowlink);
} else if (stack.contains(n)) {
v.lowlink = Math.min(v.lowlink, n.index);
}
}
}
if (v.lowlink == v.index) {
AdjacencyList.Node n;
List.Node> component = new LinkedList.Node>();
do {
n = stack.remove(0);
component.add(n);
} while (n != v);
SCC.add(component);
}
return SCC;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy