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

org.jgrapht.alg.isomorphism.GraphOrdering Maven / Gradle / Ivy

The newest version!
/*
 * (C) Copyright 2015-2023, by Fabian Späh and Contributors.
 *
 * JGraphT : a free Java graph-theory library
 *
 * See the CONTRIBUTORS.md file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0, or the
 * GNU Lesser General Public License v2.1 or later
 * which is available at
 * http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR LGPL-2.1-or-later
 */
package org.jgrapht.alg.isomorphism;

import org.jgrapht.*;
import org.jgrapht.alg.util.*;
import org.jgrapht.util.*;

import java.util.*;

/**
 * This class represents the order on the graph vertices. There are also some helper-functions for
 * receiving outgoing/incoming edges, etc.
 *
 * @param  the type of the vertices
 * @param  the type of the edges
 */

final class GraphOrdering
{
    private final Graph graph;

    private final Map mapVertexToOrder;
    private final List mapOrderToVertex;
    private final int vertexCount;

    private final int[][] outgoingEdges;
    private final int[][] incomingEdges;
    private final E[] edgeCache;
    /**
     * if caching is enabled, adjMatrix contains cached information on existing edges, valid values:
     * 
    *
  • 0 - no cached value
  • *
  • 1 - edge exists
  • *
  • -1 - no edge exists
  • *
*/ private final byte[] adjMatrix; private final boolean cacheEdges; /** * @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. */ @SuppressWarnings("unchecked") public GraphOrdering(Graph graph, boolean orderByDegree, boolean cacheEdges) { this.graph = graph; this.cacheEdges = cacheEdges; List vertexList = new ArrayList<>(graph.vertexSet()); if (orderByDegree) { vertexList.sort(VertexDegreeComparator.of(graph)); } vertexCount = vertexList.size(); mapVertexToOrder = new VertexToIntegerMapping<>(vertexList).getVertexMap(); mapOrderToVertex = vertexList; if (cacheEdges) { outgoingEdges = new int[vertexCount][]; incomingEdges = new int[vertexCount][]; edgeCache = (E[]) new Object[vertexCount * vertexCount]; adjMatrix = new byte[vertexCount * vertexCount]; } else { outgoingEdges = null; incomingEdges = null; edgeCache = null; adjMatrix = null; } } /** * @param graph the graph to be ordered */ public GraphOrdering(Graph graph) { this(graph, false, true); } /** * @return returns the number of vertices in the graph. */ public int getVertexCount() { return this.vertexCount; } /** * @param vertexNumber the number which identifies the vertex $v$ in this order. * * @return the identifying numbers of all vertices which are connected to $v$ by an edge * outgoing from $v$. */ public int[] getOutEdges(int vertexNumber) { if (cacheEdges && (outgoingEdges[vertexNumber] != null)) { return outgoingEdges[vertexNumber]; } V v = getVertex(vertexNumber); Set edgeSet = graph.outgoingEdgesOf(v); int[] vertexArray = new int[edgeSet.size()]; int i = 0; for (E edge : edgeSet) { V source = graph.getEdgeSource(edge), target = graph.getEdgeTarget(edge); vertexArray[i++] = mapVertexToOrder.get(source.equals(v) ? target : source); } if (cacheEdges) { outgoingEdges[vertexNumber] = vertexArray; } return vertexArray; } /** * @param vertexNumber the number which identifies the vertex $v$ in this order. * * @return the identifying numbers of all vertices which are connected to $v$ by an edge * incoming to $v$. */ public int[] getInEdges(int vertexNumber) { if (cacheEdges && (incomingEdges[vertexNumber] != null)) { return incomingEdges[vertexNumber]; } V v = getVertex(vertexNumber); Set edgeSet = graph.incomingEdgesOf(v); int[] vertexArray = new int[edgeSet.size()]; int i = 0; for (E edge : edgeSet) { V source = graph.getEdgeSource(edge), target = graph.getEdgeTarget(edge); vertexArray[i++] = mapVertexToOrder.get(source.equals(v) ? target : source); } if (cacheEdges) { incomingEdges[vertexNumber] = vertexArray; } return vertexArray; } /** * @param v1Number the number of the first vertex $v_1$ * @param v2Number the number of the second vertex $v_2$ * * @return exists the edge from $v_1$ to $v_2$ */ public boolean hasEdge(int v1Number, int v2Number) { int cacheIndex = 0; if (cacheEdges) { cacheIndex = v1Number * vertexCount + v2Number; final byte cache = adjMatrix[cacheIndex]; if (cache != 0) { return cache > 0; } else { // initialize both the adjacency matrix as well as the edge cache final V v1 = getVertex(v1Number); final V v2 = getVertex(v2Number); final E edge = graph.getEdge(v1, v2); if (edge == null) { adjMatrix[cacheIndex] = (byte) -1; return false; } else { adjMatrix[cacheIndex] = (byte) 1; edgeCache[cacheIndex] = edge; return true; } } } V v1 = getVertex(v1Number); V v2 = getVertex(v2Number); boolean containsEdge = graph.containsEdge(v1, v2); return containsEdge; } /** * be careful: there's no check against an invalid vertexNumber * * @param vertexNumber the number identifying the vertex $v$ * * @return $v$ */ public V getVertex(int vertexNumber) { return mapOrderToVertex.get(vertexNumber); } /** * @param v1Number the number identifying the vertex $v_1$ * @param v2Number the number identifying the vertex $v_2$ * * @return the edge from $v_1$ to $v_2$ */ public E getEdge(int v1Number, int v2Number) { if (cacheEdges) { final int cacheIndex = v1Number * vertexCount + v2Number; final byte containsEdge = adjMatrix[cacheIndex]; if (containsEdge == 0) { // edge cache has not been initialized yet for this element hasEdge(v1Number, v2Number); } final E edge = edgeCache[cacheIndex]; return edge; } V v1 = getVertex(v1Number), v2 = getVertex(v2Number); E edge = graph.getEdge(v1, v2); return edge; } public int getVertexNumber(V v) { return mapVertexToOrder.get(v); } public int[] getEdgeNumbers(E e) { V v1 = graph.getEdgeSource(e), v2 = graph.getEdgeTarget(e); int[] edge = new int[2]; edge[0] = mapVertexToOrder.get(v1); edge[1] = mapVertexToOrder.get(v2); return edge; } public Graph getGraph() { return graph; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy