是否可以创建具有特定冗余级别的连接图?

时间:2014-03-26 21:49:50

标签: java jgrapht

我正在看jgraphT,但我不是很有经验,而且缺少一些文档。

我有一些节点,我想创建一个连接的拓扑,提供一些冗余。 例如:

我从n1,n2,n3,n4开始

我希望能够与每个节点进行通信,但仍然有多个可能的路径,这样如果一个节点落下,其他节点仍然可以进行通信。

jgraphT可以为我创建一个好的拓扑吗?也许给出一些权重,以便它比其他节点更重视某个节点?

或者您知道其他图书馆可以获得相同的成就吗? 此外,如果我能够生成某种记录我创建的拓扑的网页,那就太好了......

1 个答案:

答案 0 :(得分:2)

发表评论的时间太长了:

我认为你所寻找的形式特征并没有明确说明。您显然正在寻找具有特定连接性的图表(http://en.wikipedia.org/wiki/Connectivity_%28graph_theory%29),但根据当前问题,您可以建议使用CompleteGraphGenerator

关键点可能就是你提到的那些"一些冗余"和#34;一些重量" (和#34;一些网页"记录拓扑结构)。

据推测,您需要最小的冗余。也就是说,您可能希望插入最小个附加边,以便在删除k个任意顶点后图形仍然连接。

我不知道一个可以开箱即用的库。

基于JGraphT提供的两个粗略想法:


编辑:


添加了基于上述第一个想法的实现。 ensureConnectivity方法将确保给定图形具有如下特定连接:它使用StoerWagnerMinimumCut类计算最小切割。此类的输出是顶点列表,这些顶点是剪切创建的组件之一。 computeCutVertices方法将计算实际必须删除的顶点,以便将图形划分为多个组件。对于这些顶点中的每一个,将计算邻居集。这些邻居中的任何两个(尚未连接)将与新边连接。整个过程将重复,直到"切割顶点的数量为#34;大于所需的连接性。

请注意,这尚未经过广泛测试,可能会有更优雅或更有效的解决方案,但......它应该可以正常使用

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.jgrapht.Graph;
import org.jgrapht.UndirectedGraph;
import org.jgrapht.alg.StoerWagnerMinimumCut;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.SimpleGraph;

public class GraphConnectivityTest
{
    public static void main(String[] args)
    {
        UndirectedGraph<String, DefaultEdge> graph =
            new SimpleGraph<String, DefaultEdge>(DefaultEdge.class);

        String v0 = "0";
        String v1 = "1";
        String v2 = "2";
        String v3 = "3";
        String v4 = "4";
        String v5 = "5";
        String v6 = "6";
        String v7 = "7";
        graph.addVertex(v0);
        graph.addVertex(v1);
        graph.addVertex(v2);
        graph.addVertex(v3);
        graph.addVertex(v4);
        graph.addVertex(v5);
        graph.addVertex(v6);
        graph.addVertex(v7);

        graph.addEdge(v0, v1);
        graph.addEdge(v0, v2);
        graph.addEdge(v0, v3);
        graph.addEdge(v1, v2);
        graph.addEdge(v1, v3);
        graph.addEdge(v2, v3);

        graph.addEdge(v4, v5);
        graph.addEdge(v4, v6);
        graph.addEdge(v4, v7);
        graph.addEdge(v5, v6);
        graph.addEdge(v5, v7);
        graph.addEdge(v6, v7);

        graph.addEdge(v1, v4);
        //graph.addEdge(v3, v6);

        ensureConnectivity(graph, 2);
    }

    /**
     * Make sure that the given graph has the specified connectivity.
     * That is: Make sure that more than the given number of vertices
     * have to be removed in order to split the graph into two
     * components.
     * 
     * @param graph The graph
     * @param connectivity The desired connectivity
     */
    private static <V, E> void ensureConnectivity(
        UndirectedGraph<V, E> graph, int connectivity)
    {
        System.out.println("Desired connectivity is "+connectivity);
        while (true)
        {
            StoerWagnerMinimumCut<V, E> m = 
                new StoerWagnerMinimumCut<V, E>(graph);
            Set<V> minCut = m.minCut();

            Set<V> cutVertices = 
                computeCutVertices(graph, minCut);
            System.out.println("Removing "+cutVertices+" will create two components");
            if (cutVertices.size() > connectivity)
            {
                System.out.println("Reached desired connectivity");
                return;
            }
            for (V cutVertex : cutVertices)
            {
                E edge = addBridgeEdge(graph, cutVertex);
                System.out.println("Added edge "+edge);
            }
        }
    }


    /**
     * Creates an edge between two arbitrary neighbors of the
     * given vertex in the given graph that have not yet
     * been connected.
     * 
     * @param graph The graph
     * @param v The vertex
     */
    private static <V, E> E addBridgeEdge(Graph<V, E> graph, V v)
    {
        Set<E> edges = graph.edgesOf(v);
        Set<V> neighbors = new LinkedHashSet<V>();
        for (E edge : edges)
        {
            V v0 = graph.getEdgeSource(edge);
            V v1 = graph.getEdgeTarget(edge);
            neighbors.add(v0);
            neighbors.add(v1);
        }
        neighbors.remove(v);

        List<V> neighborsList = new ArrayList<V>(neighbors);
        for (int i=0; i<neighborsList.size(); i++)
        {
            for (int j=i+1; j<neighborsList.size(); j++)
            {
                V n0 = neighborsList.get(i);
                V n1 = neighborsList.get(j);
                E present = graph.getEdge(n0, n1);
                if (present == null)
                {
                    return graph.addEdge(n0, n1);
                }
            }
        }
        return null;
    }


    /**
     * Compute the vertices in the given graph that have to be 
     * removed from the graph in order to split it into two 
     * components (of which one only contains the given 
     * "minCut" vertices)
     * 
     * @param graph The graph
     * @param minCut The set of vertices on one side of the cut
     * @return The vertices that have to be removed 
     */
    private static <V, E> Set<V> computeCutVertices(
        Graph<V, E> graph, Set<V> minCut)
    {
        Set<V> cutVertices = new LinkedHashSet<V>();
        for (V v : minCut)
        {
            Set<E> edges = graph.edgesOf(v);
            for (E edge : edges)
            {
                V v0 = graph.getEdgeSource(edge);
                V v1 = graph.getEdgeTarget(edge);
                if (minCut.contains(v0) && !minCut.contains(v1))
                {
                    cutVertices.add(v1);
                }
                if (!minCut.contains(v0) && minCut.contains(v1))
                {
                    cutVertices.add(v0);
                }
            }
        }
        return cutVertices;
    }
}