/*
* JaamSim Discrete Event Simulation
* Copyright (C) 2016 JaamSim Software Inc.
*
* Licensed 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 com.jaamsim.DirectedGraph;
import java.util.ArrayList;
import com.jaamsim.basicsim.ErrorException;
public class Digraph {
private final ArrayList<DigraphVertex> vertexList; // list of the vertices in the graph
private final ArrayList<DigraphEdge> edgeList; // list of the edges in the graph
private final ArrayList<DigraphVertex> sourceList; // list of the vertices that are sources
private final ArrayList<DigraphVertex> sinkList; // list of the vertices that are sinks
public Digraph() {
vertexList = new ArrayList<>();
edgeList = new ArrayList<>();
sourceList = new ArrayList<>();
sinkList = new ArrayList<>();
}
public void init() {
sourceList.clear();
sinkList.clear();
for (DigraphVertex vert : vertexList) {
if (vert.isSource())
sourceList.add(vert);
else if (vert.isSink())
sinkList.add(vert);
}
}
public void clear() {
vertexList.clear();
edgeList.clear();
sourceList.clear();
sinkList.clear();
}
public void addVertex(DigraphVertex vert) {
vertexList.add(vert);
}
public void addEdge(DigraphEdge edge) {
edgeList.add(edge);
}
/**
* Returns an unsorted list of all the paths that start at the specified vertex and end at a
* sink. The paths are found using a recursive depth-first search. The directed graph is
* assumed to be acyclic - if a closed loop is found, it is excluded from the returned list.
* @param start - first vertex in all the paths
* @return unsorted list of paths
* @throws Exception
*/
public static ArrayList<DigraphPath> findAllPathsFromVertex(DigraphVertex start) {
ArrayList<DigraphPath> ret = new ArrayList<>();
if (start.getOutList() == null)
throw new ErrorException("OutputList is null. Start=%s", start);
// Loop though the vertices that connect to the starting vertex
for (DigraphEdge edge : start.getOutList()) {
DigraphVertex vert = edge.getHead();
if (vert == null)
throw new ErrorException("Head vertex for edge is null. Edge=%s", edge);
// Find the paths that start from the next vertex
ArrayList<DigraphPath> pathList = Digraph.findAllPathsFromVertex(vert);
// If no paths start from the next vertex, then create a new path to that vertex
if (pathList.isEmpty()) {
DigraphPath newPath = new DigraphPath();
newPath.append(edge);
ret.add(newPath);
continue;
}
// If paths do start from the next vertex then turn them into paths from the
// starting vertex
for (DigraphPath path : pathList) {
// Ignore any closed loops
if (path.getEdgeList().contains(edge))
continue;
// Form the path from the starting vertex by adding the out-going edge
path.prepend(edge);
ret.add(path);
}
}
return ret;
}
}