ajuta în algoritmul Donalds B. Johnson, eu nu pot înțelege codul pseudo (partea II)

voturi
6

Nu pot să înțeleg o anumită parte a lucrării publicate de Donald Johnson despre găsirea de cicluri (Circuite) într-un grafic.

Mai specific nu pot înțelege ce este matricea Ak care este menționată în următoarea linie a codului pseudo:

Ak: = structura adiacenta a componentei puternice K cu cel puțin vertex în subgraf al lui G indus de {s, s + 1, .... n};

pentru a face lucrurile mai rău unele linii după ce mentins „pentru i în Vk face“ fără a declara ceea ce este Vk ...

În ceea ce am înțelege faptul că avem următoarele: 1), în general, o puternică componentă este un subgraf al unui grafic, în care, pentru fiecare nod al acestei sub-grafic există o cale de la orice nod al subgraful ( cu alte cuvinte, puteți accesa orice nod al subgraful de orice alt nod al subgraful)

2) un subgraf indus de o listă de noduri este un grafic care conține toate aceste noduri plus toate muchiile de legătură aceste noduri. în hârtie definiția matematică este F este un subgraf al lui G indus de W dacă W este subset al V și F = (W, {u, y) | u, y în W și (u, y) în E)}) unde u, y sunt muchii, e este mulțimea tuturor marginilor din grafic, W este un set de noduri.

3) în implementarea codului nodurile sunt numite de numere întregi 1 ... n.

4) Am suspecta că Vk este setul de noduri ale componentei puternice K.

acum la întrebare. Să presupunem că avem un grafic G = (V, E) cu V = {1,2,3,4,5,6,7,8,9} care poate fi împărțit în 3 componente puternice SC1 = {1, 4,7,8} SC2 = {2,3,9} SC3 = {5,6} (și marginile lor)

Poate cineva da-mi un exemplu pentru s = 1, s = 2, s = 5 ce se întâmplă dacă va fi Vk și Ak în conformitate cu codul?

Codul pseudo este întrebarea mea anterioară în Înțelegerea pseudocod în algoritmul Donald B. Johnson

și hârtia pot fi găsite la Înțelegerea pseudocod în algoritmul Donald B. Johnson

multumesc anticipat

Întrebat 30/05/2010 la 19:50
sursa de către utilizator
În alte limbi...                            


4 răspunsuri

voturi
10

Functioneaza! Într - o iterație anterioară a algoritmului Johnson , am presupus că Aera o matrice de adiacență . In schimb, se pare să reprezinte o listă adiacență . În acest exemplu, implementată de mai jos, nodurile {a, b, c} sunt numerotate {0, 1, 2}, rezultând următoarele circuite.

Addendum: După cum sa menționat în acest propus de editare și de ajutor răspuns , algoritmul specifică faptul că unblock()ar trebui să elimine elementul având valoarea w , nu elementul având indicele w .

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

Exemplu de ieșire:

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

În mod implicit, programul începe cu s = 0; de punere în aplicare s := least vertex in Vca o optimizare în continuare. O variantă care produce numai cicluri unice , este prezentată aici .

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;
            }
        }
    }
}
Publicat 01/06/2010 la 18:30
sursa de către utilizator

voturi
1

Am avut o sumbitted de editare cerere de cod @ trashgod de a stabili excepția aruncată în unblock(). În esență, algoritmul afirmă că elementul w(care este nu un index) trebuie să fie eliminată din listă. Codul de mai sus utilizat list.remove(w), care trateaza wca index.

Mea edita cerere a fost respinsă! Nu sunt sigur de ce, pentru că am testat mai sus cu modificarea mea într - o rețea de 20.000 de noduri și 70.000 de margini și nu accident.

Am modificat, de asemenea, algoritmul lui Johnson pentru a fi mai bine adaptate la grafice neorientate. Dacă cineva dorește ca aceste modificări vă rugăm să contactați-mă.

Mai jos este codul meu pentru 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);
        }
    }
}
Publicat 12/02/2013 la 04:05
sursa de către utilizator

voturi
1

@trashgod, ieșire probă conține ciclu care sunt permutări ciclice. De exemplu, 0-1-0 și 1-0-1 sunt același fapt ieșire trebuie conține doar 5 ciclu adică 0 1 0, 0 2 0, 0 1 2 0, 0 2 1 0, 1 2 1,

hârtie Johnson explica ce un ciclu este: „Două circuite elementare sunt distincte, dacă nu este o permutare ciclică a celuilalt. "Se poate verifica, de asemenea, pagina de wolframul: Aceasta, de asemenea, de ieșire 5 ciclu pentru aceeași intrare.

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

Publicat 08/04/2015 la 12:14
sursa de către utilizator

voturi
1

Variația următoare produce cicluri unice. Pe baza acestui exemplu , este adaptat la un răspuns furnizat de @ user1406062 .

Cod:

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;
            }
        }
    }
}

ieşire:

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

Toate ciclurile de referință, pentru:

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
Publicat 10/03/2016 la 17:09
sursa de către utilizator

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