transitive reduksjon algoritme: pseudo?

stemmer
31

Jeg har vært på jakt etter en algoritme for å utføre en transitive reduksjon på en graf, men uten å lykkes. Det er ingenting i mine algoritmer bibel (introduksjon til algoritmer Cormen m.fl.), og mens jeg har sett nok av transitive nedleggelse pseudokode, jeg har ikke vært i stand til å spore opp noe for en reduksjon. Det nærmeste jeg har fått er at det er en i Algorithmische Graphentheorie av Volker Turau (ISBN: 978-3-486-59057-9), men dessverre jeg ikke har tilgang til denne boken! Wikipedia er uhjelpsom og Google er likevel å skru opp noe. : ^ (

Vet noen om en algoritme for å utføre en transitive reduksjon?

Publisert på 06/11/2009 klokken 22:33
kilden bruker
På andre språk...                            


7 svar

stemmer
3

Den Wikipedia-artikkel på transitive reduksjons punkter til en implementering i Graphviz (som er åpen kilde). Ikke akkurat pseudokode, men kanskje et sted å begynne?

LEDA omfatter en transitive reduksjon algoritme . Jeg har ikke en kopi av LEDA boken lenger, og denne funksjonen kan ha blitt lagt til etter at boken ble utgitt. Men hvis det er der, så vil det være en god beskrivelse av algoritmen.

Google peker på en algoritme som noen foreslått for inkludering i Boost. Jeg forsøkte ikke å lese den, så kanskje ikke riktig?

Også dette kan være verdt en titt.

Svarte 07/11/2009 kl. 15:42
kilden bruker

stemmer
8

Den grunnleggende kjerne av transitive reduksjon algoritmen I anvendes er


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

Den transitive nedleggelse algoritmen jeg brukte i samme skriptet er svært like, men den siste linjen er


         add edge xz if edges xy and yz OR edge xz exist
Svarte 03/03/2010 kl. 14:49
kilden bruker

stemmer
3

Algoritmen av "girlwithglasses" glemmer at en overflødig kant kan strekke seg over en kjede med tre kanter. Å korrigere, beregne Q = R x R + hvor R + er den transitive nedleggelse og deretter slette alle kanter fra R som dukker opp i Q. Se også Wikipedia-artikkelen.

Svarte 08/12/2010 kl. 19:42
kilden bruker

stemmer
14

Se Harry Hsu. "En algoritme for å finne en minimal tilsvarende grafisk fremstilling av en digraph.", Journal of the ACM, 22 (1): 11-16, januar 1975. Den enkle kubiske algoritmen nedenfor (ved hjelp av en N x N bane matriks) tilstrekkelig for DAGS, men Hsu generaliserer det til sykliske grafer.

// 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;
Svarte 15/07/2011 kl. 02:47
kilden bruker

stemmer
1

Dybde-først algoritmen i 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)

Algoritmen er sub-optimal, men omhandler flerkant spenn problemet med de tidligere løsningene. Resultatene er svært likt det tred fra Graphviz produserer.

Svarte 28/06/2012 kl. 02:04
kilden bruker

stemmer
3

Basert på referanse gitt av Alan Donovan, som sier man må bruke banen matriksen (som har en 1 dersom det finnes en vei fra node i til node j) i stedet for naboskapsmatrisen (som har en 1 bare hvis det er en kant fra node til node i j).

Noen eksempel python kode følger nedenfor for å vise forskjellene mellom de løsninger

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')

Produksjon:

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
Svarte 03/05/2013 kl. 11:16
kilden bruker

stemmer
0

portet til java / jgrapht, python prøven på denne siden fra @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)));
                }
            }
        }
    }
}

enhet 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 utgang

[[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
Svarte 25/07/2015 kl. 14:31
kilden bruker

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