All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.drill.common.graph.GraphAlgos Maven / Gradle / Ivy

There is a newer version: 1.21.2
Show newest version
/*
 * 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