Guida nella algoritmo del Donalds B. Johnson, non riesco a capire il codice pseudo (PARTE II)

voti
6

non riesco a capire una certa parte del documento pubblicato dalla Donald Johnson di cercare cicli (Circuits) in un grafico.

Più specifico non riesco a capire che cosa è la matrice Ak che è menzionato nella seguente riga di codice pseudo:

Ak: = struttura adiacenza della forte componente K con almeno vertice in sottografo di G indotto da {s, s + 1, .... n};

a peggiorare le cose alcune linee dopo l'mentins Io in Vk fare senza dichiarare ciò che il Vk è ...

Per quanto ho capire abbiamo la seguente: 1), in generale, una forte componente è un sub-grafico di un grafico, in cui per ogni nodo di questo sotto-grafo c'è un percorso a qualsiasi nodo del sub-grafico ( in altre parole si può accedere a qualsiasi nodo del sub-grafico da qualsiasi altro nodo del sub-grafico)

2) un sub-grafico indotta da una lista di nodi è un grafico che contiene tutti questi nodi più tutti gli archi che connettono questi nodi. in carta la definizione matematica è F è un sottografo di G indotto da W se W è sottoinsieme di V e F = (W, {u, y) | u, y in W e (u, y) in E)}) dove u, y sono bordi, E è l'insieme di tutti gli spigoli del grafo, W è un insieme di nodi.

3) per l'attuazione del codice i nodi sono nominati dai numeri interi 1 ... n.

4) I sospetto che il Vk è l'insieme di nodi della forte componente K.

ora alla questione. Supponiamo di avere un grafo G = (V, E) con V = {} 1,2,3,4,5,6,7,8,9 cui può essere divisa in 3 componenti forti SC1 = {1, 4,7,8} SC2 = {2,3,9} SC3 = {5,6} (e loro bordi)

Qualcuno mi può dare un esempio per s = 1, s = 2, s = 5 che cosa se sarà il Vk e Ak secondo il codice?

La pseudo codice è nella mia interrogazione precedente nella comprensione del pseudocodice nel algoritmo di Donald B. Johnson

e la carta può essere trovato alla comprensione del pseudocodice nel algoritmo di Donald B. Johnson

Grazie in anticipo

È pubblicato 30/05/2010 alle 19:50
fonte dall'utente
In altre lingue...                            


4 risposte

voti
10

Funziona! In un'iterazione precedente del algoritmo di Johnson , avevo supposto che Afosse una matrice di adiacenza . Invece, sembra rappresentare una lista di adiacenza . In tale esempio, attuato sotto, i vertici {a, b, c} sono numerati {0, 1, 2}, ottenendo i seguenti circuiti.

Addendum: Come notato in questa proposta di modifica e disponibile risposta , l'algoritmo specifica che unblock()dovrebbe rimuovere l'elemento avente il valore w , non è l'elemento che ha l' indice di w .

list.remove(Integer.valueOf(w));

Esempio di output:

0 1 0
0 1 2 0
0 2 0
0 2 1 0
1 0 1
1 0 2 1
1 2 0 1
1 2 1
2 0 1 2
2 0 2
2 1 0 2
2 1 2

Per impostazione predefinita, il programma inizia con s = 0; attuare s := least vertex in Vcome un'ottimizzazione rimane. Una variante che produce solo cicli unici è mostrato qui .

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;

/**
 * @see http://dutta.csc.ncsu.edu/csc791_spring07/wrap/circuits_johnson.pdf
 * @see https://stackoverflow.com/questions/2908575
 * @see https://stackoverflow.com/questions/2939877
 * @see http://en.wikipedia.org/wiki/Adjacency_matrix
 * @see http://en.wikipedia.org/wiki/Adjacency_list
 */
public final class CircuitFinding {

    final Stack<Integer> stack = new Stack<Integer>();
    final List<List<Integer>> a;
    final List<List<Integer>> b;
    final boolean[] blocked;
    final int n;
    int s;

    public static void main(String[] args) {
        List<List<Integer>> a = new ArrayList<List<Integer>>();
        a.add(new ArrayList<Integer>(Arrays.asList(1, 2)));
        a.add(new ArrayList<Integer>(Arrays.asList(0, 2)));
        a.add(new ArrayList<Integer>(Arrays.asList(0, 1)));
        CircuitFinding cf = new CircuitFinding(a);
        cf.find();
    }

    /**
     * @param a adjacency structure of strong component K with
     * least vertex in subgraph of G induced by {s, s + 1, n};
     */
    public CircuitFinding(List<List<Integer>> a) {
        this.a = a;
        n = a.size();
        blocked = new boolean[n];
        b = new ArrayList<List<Integer>>();
        for (int i = 0; i < n; i++) {
            b.add(new ArrayList<Integer>());
        }
    }

    private void unblock(int u) {
        blocked[u] = false;
        List<Integer> list = b.get(u);
        for (int w : list) {
            //delete w from B(u);
            list.remove(Integer.valueOf(w));
            if (blocked[w]) {
                unblock(w);
            }
        }
    }

    private boolean circuit(int v) {
        boolean f = false;
        stack.push(v);
        blocked[v] = true;
        L1:
        for (int w : a.get(v)) {
            if (w == s) {
                //output circuit composed of stack followed by s;
                for (int i : stack) {
                    System.out.print(i + " ");
                }
                System.out.println(s);
                f = true;
            } else if (!blocked[w]) {
                if (circuit(w)) {
                    f = true;
                }
            }
        }
        L2:
        if (f) {
            unblock(v);
        } else {
            for (int w : a.get(v)) {
                //if (v∉B(w)) put v on B(w);
                if (!b.get(w).contains(v)) {
                    b.get(w).add(v);
                }
            }
        }
        v = stack.pop();
        return f;
    }

    public void find() {
        while (s < n) {
            if (a != null) {
                //s := least vertex in V;
                L3:
                circuit(s);
                s++;
            } else {
                s = n;
            }
        }
    }
}
Risposto il 01/06/2010 a 18:30
fonte dall'utente

voti
1

Avevo sottopongono una modifica richiesta al codice di @ trashgod per fissare l'eccezione gettato in unblock(). Essenzialmente, l'algoritmo prevede che l'elemento w(che è non un indice) deve essere rimosso dalla lista. Il codice sopra utilizzato list.remove(w), che tratta wcome indice.

La mia modifica richiesta è stata rifiutata! Non so perché, perché ho provato quanto sopra con la mia modifica su una rete di 20.000 nodi e 70.000 bordi e non va in crash.

Ho modificato anche l'algoritmo di Johnson essere più adatto per grafi non orientati. Se qualcuno vuole queste modifiche si prega di contattare me.

Qui di seguito è il mio codice per unblock().

private void unblock(int u) {
    blocked[u] = false;
    List<Integer> list = b.get(u);
    int w;
    for (int iw=0; iw < list.size(); iw++) {
        w = Integer.valueOf(list.get(iw));
        //delete w from B(u);
        list.remove(iw);
        if (blocked[w]) {
            unblock(w);
        }
    }
}
Risposto il 12/02/2013 a 04:05
fonte dall'utente

voti
1

@trashgod, l'output di esempio contiene ciclo che sono permutazione ciclica. Per esempio 0-1-0 e 1-0-1 sono stessi effetti l'uscita dovrebbe contenere solo 5 ciclo cioè 0 1 0, 0 2 0, 0 1 2 0, 0 2 1 0, 1 2 1,

carta Johnson spiegare ciò che un ciclo è: 'Due circuiti elementari sono distinte se non si è una permutazione ciclica dell'altro. 'Si può anche controllare pagina wolframio: Questo anche l'uscita 5 di ciclo per lo stesso ingresso.

http://demonstrations.wolfram.com/EnumeratingCyclesOfADirectedGraph/

Risposto il 08/04/2015 a 12:14
fonte dall'utente

voti
1

La seguente variante produce cicli unici. Sulla base di questo esempio , si è adattato da una risposta fornita dal @ user1406062 .

Codice:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

/**
 * @see https://en.wikipedia.org/wiki/Johnson%27s_algorithm
 * @see https://stackoverflow.com/questions/2908575
 * @see https://stackoverflow.com/questions/2939877
 * @see http://en.wikipedia.org/wiki/Adjacency_matrix
 * @see http://en.wikipedia.org/wiki/Adjacency_list
 */
public final class CircuitFinding {

    final Stack<Integer> stack = new Stack<Integer>();
    final Map<Integer, List<Integer>> a;
    final List<List<Integer>> b;
    final boolean[] blocked;
    final int n;
    Integer s;

    public static void main(String[] args) {
        List<List<Integer>> a = new ArrayList<List<Integer>>();
        a.add(new ArrayList<Integer>(Arrays.asList(1, 2)));
        a.add(new ArrayList<Integer>(Arrays.asList(0, 2)));
        a.add(new ArrayList<Integer>(Arrays.asList(0, 1)));
        CircuitFinding cf = new CircuitFinding(a);
        cf.find();
    }

    /**
     * @param a adjacency structure of strong component K with least vertex in
     * subgraph of G induced by {s, s + 1, n};
     */
    public CircuitFinding(List<List<Integer>> A) {
        this.a = new HashMap<Integer, List<Integer>>(A.size());
        for (int i = 0; i < A.size(); i++) {
            this.a.put(i, new ArrayList<Integer>());
            for (int j : A.get(i)) {
                this.a.get(i).add(j);
            }
        }
        n = a.size();
        blocked = new boolean[n];
        b = new ArrayList<List<Integer>>();
        for (int i = 0; i < n; i++) {
            b.add(new ArrayList<Integer>());
        }
    }

    private void unblock(int u) {
        blocked[u] = false;
        List<Integer> list = b.get(u);
        for (int w : list) {
            //delete w from B(u);
            list.remove(Integer.valueOf(w));
            if (blocked[w]) {
                unblock(w);
            }
        }
    }

    private boolean circuit(int v) {
        boolean f = false;
        stack.push(v);
        blocked[v] = true;
        L1:
        for (int w : a.get(v)) {
            if (w == s) {
                //output circuit composed of stack followed by s;
                for (int i : stack) {
                    System.out.print(i + " ");
                }
                System.out.println(s);
                f = true;
            } else if (!blocked[w]) {
                if (circuit(w)) {
                    f = true;
                }
            }
        }
        L2:
        if (f) {
            unblock(v);
        } else {
            for (int w : a.get(v)) {
                //if (v∉B(w)) put v on B(w);
                if (!b.get(w).contains(v)) {
                    b.get(w).add(v);
                }
            }
        }
        v = stack.pop();
        return f;
    }

    public void find() {
        s = 0;
        while (s < n) {
            if (!a.isEmpty()) {
                //s := least vertex in V;
                L3:
                for (int i : a.keySet()) {
                    b.get(i).clear();
                    blocked[i] = false;
                }
                circuit(s);
                a.remove(s);
                for (Integer j : a.keySet()) {
                    if (a.get(j).contains(s)) {
                        a.get(j).remove(s);
                    }
                }
                s++;
            } else {
                s = n;
            }
        }
    }
}

Produzione:

0 1 0
0 1 2 0
0 2 0
0 2 1 0
1 2 1

Tutti i cicli, per riferimento:

0 1 0
0 1 2 0
0 2 0
0 2 1 0
1 0 1
1 0 2 1
1 2 0 1
1 2 1
2 0 1 2
2 0 2
2 1 0 2
2 1 2
Risposto il 10/03/2016 a 17:09
fonte dall'utente

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