JGraphT: Sustitución de subárbol en un gráfico acíclico dirigido por otro subárbol

CIOC:

Vamos a suponer que tengo los siguientes dos gráficos de árboles:

     a                               i
   /    \                          /    \
  b      c                        j      k
 / \    / \                      / \    / \
d   e  f   g                    l   m  n   o

Y necesito para extraer el subgrafo bdesde el primer gráfico y reemplazarlo en el segundo gráfico de esta manera:

     i
   /    \
  j      b
 / \    / \
l   m  d   e

¿Hay alguna API existente en JGraphT permitirlo?

Joris Kinable:

La siguiente respuesta se basa en los siguientes supuestos:

  • ambos gráficos de entrada, g1y g2son acíclicos gráficos dirigidos (árboles)
  • que desea reemplazar en un subárbol g2por un sub-árbol eng1
  • tanto g1y g2son vértice y el borde disjuntos, que es un vértice (borde) en g1no aparece en g2y viceversa.

JGraphT no tiene incorporado un método para reemplazos de subárbol, pero sería bastante simple de implementar dicho método:

/**
* Replaces the subtree rooted in root2 in graph g2 with the subtree rooted in root1 in graph g1. Graph g1 is left
* unchanged.
* @param g1 first graph
* @param g2 second graph
* @param root1 root of subtree in first graph
* @param root2 root of subtree in second graph
* @param <V> vertex type
* @param <E> edge type
*/
public static <V,E> void replaceSubtree(Graph<V, E> g1, Graph<V, E> g2, V root1, V root2){
    //1. Add subtree under root1 to graph g2 as a disconnected component
    BreadthFirstIterator<V, E> bfs = new BreadthFirstIterator<>(g1,root1);
    g2.addVertex(bfs.next());
    while (bfs.hasNext()){
        V vertex=bfs.next();
        V parent=bfs.getParent(vertex);
        g2.addVertex(vertex);
        g2.addEdge(parent,vertex,bfs.getSpanningTreeEdge(vertex));
    }

    //2. Get the edge (object) between root2 and its parent. A special case occurs if root2 is also the root of g2
    // in which case it does not have a parent.
    E treeEdge = (g2.incomingEdgesOf(root2).isEmpty() ? null : g2.incomingEdgesOf(root2).iterator().next());
    V parent= (treeEdge == null ? null : Graphs.getOppositeVertex(g2, treeEdge, root2));

    //3. Remove subtree rooted in vertex k
    bfs = new BreadthFirstIterator<>(g2,root2);
    while(bfs.hasNext())
        g2.removeVertex(bfs.next());

    //4. Reconnect the two components
    if(parent != null)
        g2.addEdge(parent, root1, treeEdge);
}

Aquí hay algo de código de prueba:

public static void main(String[] args){
    Graph<String, DefaultEdge> g1 = new SimpleDirectedGraph<>(DefaultEdge.class);
    Graphs.addAllVertices(g1, Arrays.asList("a", "b", "c", "d", "e", "f", "g"));
    g1.addEdge("a", "b");
    g1.addEdge("a", "c");
    g1.addEdge("b", "d");
    g1.addEdge("b", "e");
    g1.addEdge("c", "f");
    g1.addEdge("c", "g");

    Graph<String, DefaultEdge> g2 = new SimpleDirectedGraph<>(DefaultEdge.class);
    Graphs.addAllVertices(g2, Arrays.asList("i", "j", "k", "l", "m", "n", "o"));
    g2.addEdge("i", "j");
    g2.addEdge("i", "k");
    g2.addEdge("j", "l");
    g2.addEdge("j", "m");
    g2.addEdge("k", "n");
    g2.addEdge("k", "o");

    replaceSubtree(g1, g2, "b", "k");

    System.out.println(g2);
}
  • replaceSubtree(g1, g2, "b", "k"); da: ([i, j, l, m, b, d, e], [(i,j), (j,l), (j,m), (b,d), (b,e), (i,b)])
  • replaceSubtree(g1, g2, "b", "i"); da: ([b, d, e], [(b,d), (b,e)])

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=280796&siteId=1
Recomendado
Clasificación