help in the Donalds B. Johnson's algorithm, i cannot understand the pseudo code (PART II)

前端 未结 4 1229
后悔当初
后悔当初 2020-11-29 11:50

i cannot understand a certain part of the paper published by Donald Johnson about finding cycles (Circuits) in a graph.

More specific i cannot understand what is the

相关标签:
4条回答
  • 2020-11-29 12:09

    @trashgod, your sample output contains cycle which are cyclic permutation. For example 0-1-0 and 1-0-1 are same Actually the output should contains only 5 cycle i.e. 0 1 0, 0 2 0, 0 1 2 0, 0 2 1 0, 1 2 1,

    Johnson paper explain what a cycle is: 'Two elementary circuits are distinct if one is not a cyclic permutation of the other. ' One can also check wolfram page: This also output 5 cycle for the same input.

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

    0 讨论(0)
  • 2020-11-29 12:18

    The following variation produces unique cycles. Based on this example, it is adapted from an answer supplied by @user1406062.

    Code:

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

    Output:

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

    All cycles, for reference:

    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
    
    0 讨论(0)
  • 2020-11-29 12:20

    It works! In an earlier iteration of the Johnson algorithm, I had supposed that A was an adjacency matrix. Instead, it appears to represent an adjacency list. In that example, implemented below, the vertices {a, b, c} are numbered {0, 1, 2}, yielding the following circuits.

    Addendum: As noted in this proposed edit and helpful answer, the algorithm specifies that unblock() should remove the element having the value w, not the element having the index w.

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

    Sample 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
    

    By default, the program starts with s = 0; implementing s := least vertex in V as an optimization remains. A variation that produces only unique cycles is shown here.

    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;
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-29 12:25

    I had sumbitted an edit request to @trashgod's code to fix the exception thrown in unblock(). Essentially, the algorithm states that the element w (which is not an index) is to be removed from the list. The code above used list.remove(w), which treats w as an index.

    My edit request was rejected! Not sure why, because I have tested the above with my modification on a network of 20,000 nodes and 70,000 edges and it doesn't crash.

    I have also modified Johnson's algorithm to be more adapted to undirected graphs. If anybody wants these modifications please contact me.

    Below is my code for 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);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题