/** * @param graph the graph to be ordered * @param orderByDegree should the vertices be ordered by their degree. This speeds up the VF2 * algorithm. * @param cacheEdges if true, the class creates a adjacency matrix and two arrays for incoming and * outgoing edges for fast access. */ public GraphOrdering(Graph<V, E> graph, boolean orderByDegree, boolean cacheEdges) { this.graph = graph; this.cacheEdges = cacheEdges; List<V> vertexSet = new ArrayList<>(graph.vertexSet()); if (orderByDegree) { java.util.Collections.sort(vertexSet, new GeneralVertexDegreeComparator<>(graph)); } vertexCount = vertexSet.size(); mapVertexToOrder = new HashMap<>(); mapOrderToVertex = new ArrayList<>(vertexCount); if (cacheEdges) { outgoingEdges = new int[vertexCount][]; incomingEdges = new int[vertexCount][]; adjMatrix = new Boolean[vertexCount][vertexCount]; } Integer i = 0; for (V vertex : vertexSet) { mapVertexToOrder.put(vertex, i++); mapOrderToVertex.add(vertex); } }
/** {@inheritDoc} */ protected void encounterVertexAgain(V vertex, E edge) { super.encounterVertexAgain(vertex, edge); int i; if (root != null) { // For rooted detection, the path must either // double back to the root, or to a node of a cycle // which has already been detected. if (vertex.equals(root)) { i = 0; } else if ((cycleSet != null) && cycleSet.contains(vertex)) { i = 0; } else { return; } } else { i = path.indexOf(vertex); } if (i > -1) { if (cycleSet == null) { // we're doing yes/no cycle detection throw new CycleDetectedException(); } else { for (; i < path.size(); ++i) { cycleSet.add(path.get(i)); } } } }
/** Calculate the shortest paths (not done per default) */ private void lazyCalculatePaths() { // already we have calculated it once. if (paths != null) { return; } lazyCalculateMatrix(); Map<VertexPair<V>, GraphPath<V, E>> sps = new HashMap<VertexPair<V>, GraphPath<V, E>>(); int n = vertices.size(); nShortestPaths = 0; for (int i = 0; i < n; i++) { V v_i = vertices.get(i); for (int j = 0; j < n; j++) { // don't count this. if (i == j) { continue; } V v_j = vertices.get(j); GraphPath<V, E> path = getShortestPathImpl(v_i, v_j); // we got a path if (path != null) { sps.put(new VertexPair<V>(v_i, v_j), path); nShortestPaths++; } } } this.paths = sps; }
/** Calculates the matrix of all shortest paths, but does not populate the paths map. */ private void lazyCalculateMatrix() { if (d != null) { // already done return; } int n = vertices.size(); // init the backtrace matrix backtrace = new int[n][n]; for (int i = 0; i < n; i++) { Arrays.fill(backtrace[i], -1); } // initialize matrix, 0 d = new double[n][n]; for (int i = 0; i < n; i++) { Arrays.fill(d[i], Double.POSITIVE_INFINITY); } // initialize matrix, 1 for (int i = 0; i < n; i++) { d[i][i] = 0.0; } // initialize matrix, 2 Set<E> edges = graph.edgeSet(); for (E edge : edges) { V v1 = graph.getEdgeSource(edge); V v2 = graph.getEdgeTarget(edge); int v_1 = vertices.indexOf(v1); int v_2 = vertices.indexOf(v2); d[v_1][v_2] = graph.getEdgeWeight(edge); if (!(graph instanceof DirectedGraph<?, ?>)) { d[v_2][v_1] = graph.getEdgeWeight(edge); } } // run fw alg for (int k = 0; k < n; k++) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { double ik_kj = d[i][k] + d[k][j]; if (ik_kj < d[i][j]) { d[i][j] = ik_kj; backtrace[i][j] = k; } } } } }
private void shortestPathRecur(List<E> edges, int v_a, int v_b) { int k = backtrace[v_a][v_b]; if (k == -1) { E edge = graph.getEdge(vertices.get(v_a), vertices.get(v_b)); if (edge != null) { edges.add(edge); } } else { shortestPathRecur(edges, v_a, k); shortestPathRecur(edges, k, v_b); } }
/** {@inheritDoc} */ protected V provideNextVertex() { V v = super.provideNextVertex(); // backtrack for (int i = path.size() - 1; i >= 0; --i) { if (graph.containsEdge(path.get(i), v)) { break; } path.remove(i); } path.add(v); return v; }
/** * This method will return a list of vertices which represents the Eulerian circuit of the graph. * * @param g The graph to find an Eulerian circuit * @return null if no Eulerian circuit exists, or a list of vertices representing the Eulerian * circuit if one does exist */ public static <V, E> List<V> getEulerianCircuitVertices(UndirectedGraph<V, E> g) { // If the graph is not Eulerian then just return a null since no // Eulerian circuit exists if (!isEulerian(g)) { return null; } // The circuit will be represented by a linked list List<V> path = new LinkedList<V>(); UndirectedGraph<V, E> sg = new UndirectedSubgraph<V, E>(g, null, null); path.add(sg.vertexSet().iterator().next()); // Algorithm for finding an Eulerian circuit Basically this will find an // arbitrary circuit, then it will find another arbitrary circuit until // every edge has been traversed while (sg.edgeSet().size() > 0) { V v = null; // Find a vertex which has an edge that hasn't been traversed yet, // and keep its index position in the circuit list int index = 0; for (Iterator<V> iter = path.iterator(); iter.hasNext(); index++) { v = iter.next(); if (sg.degreeOf(v) > 0) { break; } } // Finds an arbitrary circuit of the current vertex and // appends this into the circuit list while (sg.degreeOf(v) > 0) { for (Iterator<V> iter = sg.vertexSet().iterator(); iter.hasNext(); ) { V temp = iter.next(); if (sg.containsEdge(v, temp)) { path.add(index, temp); sg.removeEdge(v, temp); v = temp; break; } } } } return path; }
/** * Compute the unique decomposition of the input graph G (atoms of G). Implementation of algorithm * Atoms as described in Berry et al. (2010), DOI:10.3390/a3020197, <a * href="http://www.mdpi.com/1999-4893/3/2/197">http://www.mdpi.com/1999-4893/3/2/197</a> */ private void computeAtoms() { if (chordalGraph == null) { computeMinimalTriangulation(); } separators = new HashSet<>(); // initialize g' as subgraph of graph (same vertices and edges) UndirectedGraph<V, E> gprime = copyAsSimpleGraph(graph); // initialize h' as subgraph of chordalGraph (same vertices and edges) UndirectedGraph<V, E> hprime = copyAsSimpleGraph(chordalGraph); atoms = new HashSet<>(); Iterator<V> iterator = meo.descendingIterator(); while (iterator.hasNext()) { V v = iterator.next(); if (generators.contains(v)) { Set<V> separator = new HashSet<>(Graphs.neighborListOf(hprime, v)); if (isClique(graph, separator)) { if (separator.size() > 0) { if (separators.contains(separator)) { fullComponentCount.put(separator, fullComponentCount.get(separator) + 1); } else { fullComponentCount.put(separator, 2); separators.add(separator); } } UndirectedGraph<V, E> tmpGraph = copyAsSimpleGraph(gprime); tmpGraph.removeAllVertices(separator); ConnectivityInspector<V, E> con = new ConnectivityInspector<>(tmpGraph); if (con.isGraphConnected()) { throw new RuntimeException("separator did not separate the graph"); } for (Set<V> component : con.connectedSets()) { if (component.contains(v)) { gprime.removeAllVertices(component); component.addAll(separator); atoms.add(new HashSet<>(component)); assert (component.size() > 0); break; } } } } hprime.removeVertex(v); } if (gprime.vertexSet().size() > 0) { atoms.add(new HashSet<>(gprime.vertexSet())); } }
private GraphPath<V, E> getShortestPathImpl(V a, V b) { int v_a = vertices.indexOf(a); int v_b = vertices.indexOf(b); List<E> edges = new ArrayList<E>(); shortestPathRecur(edges, v_a, v_b); // no path, return null if (edges.size() < 1) { return null; } double weight = 0.; for (E e : edges) { weight += graph.getEdgeWeight(e); } GraphPathImpl<V, E> path = new GraphPathImpl<V, E>(graph, a, b, edges, weight); return path; }
public Set<JavaClass> findClasses(Collection<File> changedFiles) { // First update class index List<String> changedClassesNames = new ArrayList<String>(); for (File changedFile : changedFiles) { String changedClassname = builder.classFileChanged(changedFile); if (changedClassname != null) { changedClassesNames.add(changedClassname); } } // Then find dependencies Set<JavaClass> changedClasses = newHashSet(); for (String changedClassesName : changedClassesNames) { JavaClass javaClass = builder.getClass(changedClassesName); if (javaClass != null) { addToIndex(javaClass); changedClasses.add(javaClass); } } builder.clear(); return changedClasses; }
/** * @return the diameter (longest of all the shortest paths) computed for the graph. If the graph * is vertexless, return 0.0. */ public double getDiameter() { lazyCalculateMatrix(); if (Double.isNaN(diameter)) { diameter = 0.0; int n = vertices.size(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (!Double.isInfinite(d[i][j]) && d[i][j] > diameter) { diameter = d[i][j]; } } } } return diameter; }
public void testNonSimplePath() { List<Integer> vertexList = Arrays.asList(0, 1, 2, 3, 2, 3, 4); List<DefaultEdge> edgeList = new ArrayList<>(); for (int i = 0; i < vertexList.size() - 1; i++) edgeList.add(completeGraph.getEdge(vertexList.get(i), vertexList.get(i + 1))); GraphPath<Integer, DefaultEdge> p1 = new GraphWalk<>(completeGraph, 0, 4, edgeList, 10); assertEquals(0, p1.getStartVertex().intValue()); assertEquals(4, p1.getEndVertex().intValue()); assertEquals(vertexList, p1.getVertexList()); assertEquals(edgeList.size(), p1.getLength()); assertEquals(10.0, p1.getWeight()); GraphPath<Integer, DefaultEdge> p2 = new GraphWalk<>(completeGraph, vertexList, 10); assertEquals(0, p2.getStartVertex().intValue()); assertEquals(4, p2.getEndVertex().intValue()); assertEquals(edgeList, p2.getEdgeList()); assertEquals(edgeList.size(), p2.getLength()); assertEquals(10.0, p2.getWeight()); }
/** * Get the length of a shortest path. * * @param a first vertex * @param b second vertex * @return shortest distance between a and b */ public double shortestDistance(V a, V b) { lazyCalculateMatrix(); return d[vertices.indexOf(a)][vertices.indexOf(b)]; }
/** * Compute the minimal triangulation of the graph. Implementation of Algorithm MCS-M+ as described * in Berry et al. (2010), DOI:10.3390/a3020197 <a href="http://www.mdpi.com/1999-4893/3/2/197"> * http://www.mdpi.com/1999-4893/3/2/197</a> */ private void computeMinimalTriangulation() { // initialize chordGraph with same vertices as graph chordalGraph = new SimpleGraph<>(graph.getEdgeFactory()); for (V v : graph.vertexSet()) { chordalGraph.addVertex(v); } // initialize g' as subgraph of graph (same vertices and edges) final UndirectedGraph<V, E> gprime = copyAsSimpleGraph(graph); int s = -1; generators = new ArrayList<>(); meo = new LinkedList<>(); final Map<V, Integer> vertexLabels = new HashMap<>(); for (V v : gprime.vertexSet()) { vertexLabels.put(v, 0); } for (int i = 1, n = graph.vertexSet().size(); i <= n; i++) { V v = getMaxLabelVertex(vertexLabels); LinkedList<V> Y = new LinkedList<>(Graphs.neighborListOf(gprime, v)); if (vertexLabels.get(v) <= s) { generators.add(v); } s = vertexLabels.get(v); // Mark x reached and all other vertices of gprime unreached HashSet<V> reached = new HashSet<>(); reached.add(v); // mark neighborhood of x reached and add to reach(label(y)) HashMap<Integer, HashSet<V>> reach = new HashMap<>(); // mark y reached and add y to reach for (V y : Y) { reached.add(y); addToReach(vertexLabels.get(y), y, reach); } for (int j = 0; j < graph.vertexSet().size(); j++) { if (!reach.containsKey(j)) { continue; } while (reach.get(j).size() > 0) { // remove a vertex y from reach(j) V y = reach.get(j).iterator().next(); reach.get(j).remove(y); for (V z : Graphs.neighborListOf(gprime, y)) { if (!reached.contains(z)) { reached.add(z); if (vertexLabels.get(z) > j) { Y.add(z); E fillEdge = graph.getEdgeFactory().createEdge(v, z); fillEdges.add(fillEdge); addToReach(vertexLabels.get(z), z, reach); } else { addToReach(j, z, reach); } } } } } for (V y : Y) { chordalGraph.addEdge(v, y); vertexLabels.put(y, vertexLabels.get(y) + 1); } meo.addLast(v); gprime.removeVertex(v); vertexLabels.remove(v); } }
/** * Reads the geometry and connectivity. * * @param filename the location of the gjf file */ public GJFfile(String filename) { super(filename); // read geometry String name = ""; List<Atom> contents = new ArrayList<>(); SimpleWeightedGraph<Atom, DefaultWeightedEdge> connectivity = new SimpleWeightedGraph<>(DefaultWeightedEdge.class); int blanks = 0; boolean lastBlank = false; boolean inGeometryBlock = false; for (List<String> line : fileContents) { // keep track of how many blanks we have seen if (line.size() == 1 && line.get(0).length() == 0) { if (lastBlank == false) { blanks++; lastBlank = true; } continue; } else lastBlank = false; // read the metadata if (blanks == 1) { for (String s : line) { String[] fields = s.split("@"); if (fields.length != 3) continue; String identifier = fields[1].toLowerCase(); String value = fields[2]; // System.out.println(s); // System.out.println(identifier + " : " + value); if (identifier.equals("o1")) O1Number = Integer.parseInt(value); else if (identifier.equals("o2")) O2Number = Integer.parseInt(value); else if (identifier.equals("n3")) N3Number = Integer.parseInt(value); else if (identifier.equals("cl1")) Cl1Number = Integer.parseInt(value); else if (identifier.equals("su2")) Su2Number = Integer.parseInt(value); else if (identifier.equals("ol3")) Ol3Number = Integer.parseInt(value); else if (identifier.equals("mem")) mem = Integer.parseInt(value); else if (identifier.equals("nprocshared")) nprocshared = Integer.parseInt(value); else if (identifier.equals("method")) method = value; else if (identifier.equals("basis")) basis = value; else System.out.println("unrecognized entry: " + s); } continue; } else if (blanks != 2) continue; // deal with the charge and multiplicity card (by ignoring it) if (line.size() == 2 && inGeometryBlock == false) { inGeometryBlock = true; continue; } if (line.size() != 4 && inGeometryBlock == false) throw new IllegalArgumentException( "unexpected text in geometry block in " + filename + ":\n" + line.toString()); // create atom // tinker atom types will be nonsense, of course Atom newAtom = new Atom( line.get(0), new Vector3D( Double.parseDouble(line.get(1)), Double.parseDouble(line.get(2)), Double.parseDouble(line.get(3))), 1); contents.add(newAtom); connectivity.addVertex(newAtom); } // read connectivity blanks = 0; lastBlank = false; for (List<String> line : fileContents) { // read the fourth block of text if (line.size() == 1 && line.get(0).length() == 0) { if (lastBlank == false) { blanks++; lastBlank = true; } continue; } else lastBlank = false; // only read connectivity lines if (blanks != 3) continue; Atom fromAtom = contents.get(Integer.parseInt(line.get(0)) - 1); for (int i = 1; i < line.size(); i += 2) { int toAtomIndex = Integer.parseInt(line.get(i)) - 1; Atom toAtom = contents.get(toAtomIndex); double bondOrder = Double.parseDouble(line.get(i + 1)); DefaultWeightedEdge thisEdge = connectivity.addEdge(fromAtom, toAtom); connectivity.setEdgeWeight(thisEdge, bondOrder); } } // create the molecule molecule = new Molecule(name, contents, connectivity, 0.0); }