Algoritmus tranzitivní redukce: pseudocode?

hlasů
30

Hledala jsem na algoritmu provádět snížení přenositelný na grafu, ale bez úspěchu. Na tom není nic ve svých algoritmech bible (Úvod do algoritmů CORMEN kol), a zatímco jsem viděl spoustu uzavření tranzitivní pseudokódu jsem nebyl schopen vypátrat něco pro snížení. Nejbližší mám, je, že existuje jedna „Algorithmische Graphentheorie“ Volker Turau (ISBN: 978-3-486-59057-9), ale bohužel nemám přístup k této knize! Wikipedia je neužitečné a Google se teprve objeví cokoli. : ^ (

Ví někdo, algoritmu pro provádění tranzitivní redukce?

Položena 06/11/2009 v 23:33
zdroj uživatelem
V jiných jazycích...                            


7 odpovědí

hlasů
3

Wikipedia článek o přechodných bodů redukčních k realizaci v rámci Graphviz (což je open source). Ne tak docela pseudocode, ale možná, že někde začít?

LEDA obsahuje algoritmus tranzitivní redukce . Nemám kopii LEDA knihy už, a tato funkce mohla být přidána poté, co kniha vyšla. Ale jestli je to tam, pak bude dobrý popis algoritmu.

Google poukazuje na algoritmu , který někdo navrhl pro zařazení do basů. Nesnažil jsem si ji přečíst, takže možná není správné?

Také to může být stojí za to podívat.

Odpovězeno 07/11/2009 v 16:42
zdroj uživatelem

hlasů
7

Základní podstata tranzitivní algoritmu redukce I použitého


foreach x in graph.vertices
   foreach y in graph.vertices
      foreach z in graph.vertices
         delete edge xz if edges xy and yz exist

Tranzitivní algoritmus uzávěr jsem použil ve stejném skriptu je velmi podobná, ale poslední řádek


         add edge xz if edges xy and yz OR edge xz exist
Odpovězeno 03/03/2010 v 15:49
zdroj uživatelem

hlasů
3

Algoritmus „girlwithglasses“ zapomene, že redundantní hrana mohla překlenout řetězec tří hran. Chcete-li, spočítat Q = R x R +, kde R + je tranzitivní uzávěr a odstraňte všechny okraje z R, které se objevují v Q. Viz také článek Wikipedia.

Odpovězeno 08/12/2010 v 20:42
zdroj uživatelem

hlasů
13

Viz Harry Hsu. „Algoritmus pro nalezení minimální ekvivalentní graf digraph.“, Journal of ACM, 22 (1): 11 až 16, leden 1975. Jednoduchý krychlový algoritmus níže (za použití N x N dráhy matice) postačuje pro DAGs, ale Hsu zobecňuje cyklickým grafů.

// reflexive reduction
for (int i = 0; i < N; ++i)
  m[i][i] = false;

// transitive reduction
for (int j = 0; j < N; ++j)
  for (int i = 0; i < N; ++i)
    if (m[i][j])
      for (int k = 0; k < N; ++k)
        if (m[j][k])
          m[i][k] = false;
Odpovězeno 15/07/2011 v 03:47
zdroj uživatelem

hlasů
1

Hloubky algoritmus v pseudo-python:

for vertex0 in vertices:
    done = set()
    for child in vertex0.children:
        df(edges, vertex0, child, done)

df = function(edges, vertex0, child0, done)
    if child0 in done:
        return
    for child in child0.children:
        edge.discard((vertex0, child))
        df(edges, vertex0, child, done)
    done.add(child0)

Algoritmus není optimální, ale zabývá problémem multi-edge-Span předchozích řešení. Výsledky jsou velmi podobné tomu, co tred z graphviz produkuje.

Odpovězeno 28/06/2012 v 03:04
zdroj uživatelem

hlasů
3

na odkaz poskytnutých Alan Donovan, který říká, že byste měli použít matici cesty (která má hodnotu 1, pokud existuje cesta z uzlu i do uzlu j) na místo přilehlosti matice (která má hodnotu 1 pouze tehdy, pokud existuje hrana z uzlu i do uzlu j).

Některé vzorek python kódu následuje níže ukazují rozdíly mezi roztoků

def prima(m, title=None):
    """ Prints a matrix to the terminal """
    if title:
        print title
    for row in m:
        print ', '.join([str(x) for x in row])
    print ''

def path(m):
    """ Returns a path matrix """
    p = [list(row) for row in m]
    n = len(p)
    for i in xrange(0, n):
        for j in xrange(0, n):
            if i == j:
                continue
            if p[j][i]:
                for k in xrange(0, n):
                    if p[j][k] == 0:
                        p[j][k] = p[i][k]
    return p

def hsu(m):
    """ Transforms a given directed acyclic graph into its minimal equivalent """
    n = len(m)
    for j in xrange(n):
        for i in xrange(n):
            if m[i][j]:
                for k in xrange(n):
                    if m[j][k]:
                        m[i][k] = 0

m = [   [0, 1, 1, 0, 0],
        [0, 0, 0, 0, 0],
        [0, 0, 0, 1, 1],
        [0, 0, 0, 0, 1],
        [0, 1, 0, 0, 0]]

prima(m, 'Original matrix')
hsu(m)
prima(m, 'After Hsu')

p = path(m)
prima(p, 'Path matrix')
hsu(p)
prima(p, 'After Hsu')

Výstup:

Adjacency matrix
0, 1, 1, 0, 0
0, 0, 0, 0, 0
0, 0, 0, 1, 1
0, 0, 0, 0, 1
0, 1, 0, 0, 0

After Hsu
0, 1, 1, 0, 0
0, 0, 0, 0, 0
0, 0, 0, 1, 0
0, 0, 0, 0, 1
0, 1, 0, 0, 0

Path matrix
0, 1, 1, 1, 1
0, 0, 0, 0, 0
0, 1, 0, 1, 1
0, 1, 0, 0, 1
0, 1, 0, 0, 0

After Hsu
0, 0, 1, 0, 0
0, 0, 0, 0, 0
0, 0, 0, 1, 0
0, 0, 0, 0, 1
0, 1, 0, 0, 0
Odpovězeno 03/05/2013 v 12:16
zdroj uživatelem

hlasů
0

portován na Java / jgrapht, vzorek python na této stránce od @Michael Clerx:

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

import org.jgrapht.DirectedGraph;

public class TransitiveReduction<V, E> {

    final private List<V> vertices;
    final private int [][] pathMatrix;

    private final DirectedGraph<V, E> graph;

    public TransitiveReduction(DirectedGraph<V, E> graph) {
        super();
        this.graph = graph;
        this.vertices = new ArrayList<V>(graph.vertexSet());
        int n = vertices.size();
        int[][] original = new int[n][n];

        // initialize matrix with zeros
        // --> 0 is the default value for int arrays

        // initialize matrix with edges
        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);

            original[v_1][v_2] = 1;
        }

        this.pathMatrix = original;
        transformToPathMatrix(this.pathMatrix);
    }

    // (package visible for unit testing)
    static void transformToPathMatrix(int[][] matrix) {
        // compute path matrix 
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix.length; j++) { 
                if (i == j) {
                    continue;
                }
                if (matrix[j][i] > 0 ){
                    for (int k = 0; k < matrix.length; k++) {
                        if (matrix[j][k] == 0) {
                            matrix[j][k] = matrix[i][k];
                        }
                    }
                }
            }
        }
    }

    // (package visible for unit testing)
    static void transitiveReduction(int[][] pathMatrix) {
        // transitively reduce
        for (int j = 0; j < pathMatrix.length; j++) { 
            for (int i = 0; i < pathMatrix.length; i++) {
                if (pathMatrix[i][j] > 0){
                    for (int k = 0; k < pathMatrix.length; k++) {
                        if (pathMatrix[j][k] > 0) {
                            pathMatrix[i][k] = 0;
                        }
                    }
                }
            }
        }
    }

    public void reduce() {

        int n = pathMatrix.length;
        int[][] transitivelyReducedMatrix = new int[n][n];
        System.arraycopy(pathMatrix, 0, transitivelyReducedMatrix, 0, pathMatrix.length);
        transitiveReduction(transitivelyReducedMatrix);

        for (int i = 0; i <n; i++) {
            for (int j = 0; j < n; j++) { 
                if (transitivelyReducedMatrix[i][j] == 0) {
                    // System.out.println("removing "+vertices.get(i)+" -> "+vertices.get(j));
                    graph.removeEdge(graph.getEdge(vertices.get(i), vertices.get(j)));
                }
            }
        }
    }
}

Jednotka test:

import java.util.Arrays;

import org.junit.Assert;
import org.junit.Test;

public class TransitiveReductionTest {

    @Test
    public void test() {

        int[][] matrix = new int[][] {
            {0, 1, 1, 0, 0},
            {0, 0, 0, 0, 0},
            {0, 0, 0, 1, 1},
            {0, 0, 0, 0, 1},
            {0, 1, 0, 0, 0}
        };

        int[][] expected_path_matrix = new int[][] {
            {0, 1, 1, 1, 1},
            {0, 0, 0, 0, 0},
            {0, 1, 0, 1, 1},
            {0, 1, 0, 0, 1},
            {0, 1, 0, 0, 0}
        };

        int[][] expected_transitively_reduced_matrix = new int[][] {
            {0, 0, 1, 0, 0},
            {0, 0, 0, 0, 0},
            {0, 0, 0, 1, 0},
            {0, 0, 0, 0, 1},
            {0, 1, 0, 0, 0}
        };

        System.out.println(Arrays.deepToString(matrix) + " original matrix");

        int n = matrix.length;

        // calc path matrix
        int[][] path_matrix = new int[n][n];
        {
            System.arraycopy(matrix, 0, path_matrix, 0, matrix.length);

            TransitiveReduction.transformToPathMatrix(path_matrix);
            System.out.println(Arrays.deepToString(path_matrix) + " path matrix");
            Assert.assertArrayEquals(expected_path_matrix, path_matrix);
        }

        // calc transitive reduction
        {
            int[][] transitively_reduced_matrix = new int[n][n];
            System.arraycopy(path_matrix, 0, transitively_reduced_matrix, 0, matrix.length);

            TransitiveReduction.transitiveReduction(transitively_reduced_matrix);
            System.out.println(Arrays.deepToString(transitively_reduced_matrix) + " transitive reduction");
            Assert.assertArrayEquals(expected_transitively_reduced_matrix, transitively_reduced_matrix);
        }
    }
}

Test ouput

[[0, 1, 1, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 1, 1], [0, 0, 0, 0, 1], [0, 1, 0, 0, 0]] original matrix
[[0, 1, 1, 1, 1], [0, 0, 0, 0, 0], [0, 1, 0, 1, 1], [0, 1, 0, 0, 1], [0, 1, 0, 0, 0]] path matrix
[[0, 0, 1, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1], [0, 1, 0, 0, 0]] transitive reduction
Odpovězeno 25/07/2015 v 14:31
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more