source: src/main/java/weka/clusterers/forMetisMQI/MQI.java @ 23

Last change on this file since 23 was 22, checked in by gnappo, 14 years ago

Implementata ricorsione corretta di MQI. Aggiunto parametro a linea di comando per la bisezione casuale.

File size: 6.7 KB
Line 
1package weka.clusterers.forMetisMQI;
2
3import java.util.Collection;
4import java.util.HashMap;
5import java.util.HashSet;
6import java.util.Iterator;
7import java.util.Map;
8import java.util.Set;
9import java.util.Stack;
10
11import org.apache.commons.collections15.Factory;
12import org.apache.commons.collections15.Transformer;
13
14import weka.clusterers.forMetisMQI.graph.Bisection;
15import weka.clusterers.forMetisMQI.graph.Edge;
16import weka.clusterers.forMetisMQI.graph.Node;
17import weka.clusterers.forMetisMQI.graph.Subgraph;
18import edu.uci.ics.jung.algorithms.flows.EdmondsKarpMaxFlow;
19import edu.uci.ics.jung.graph.DirectedGraph;
20import edu.uci.ics.jung.graph.DirectedSparseGraph;
21import weka.clusterers.forMetisMQI.util.Util;
22
23public class MQI {
24
25        static int i = -1;
26
27        static private Set<Node> DFSReversed(Node currentNode,
28                        DirectedGraph<Node, Edge> g, Map<Edge, Number> edgeFlowMap,
29                        Set<Node> marked) {
30                Collection<Edge> inEdges = g.getInEdges(currentNode);
31                Set<Node> result = new HashSet<Node>();
32                result.add(currentNode);
33                Iterator<Edge> inEdgesIterator = inEdges.iterator();
34                while (inEdgesIterator.hasNext()) {
35                        Edge edge = inEdgesIterator.next();
36                        Node src = g.getSource(edge);
37                        Edge reverseEdge = g.findEdge(src, currentNode);
38                        if (reverseEdge != null && !marked.contains(src)) {
39                                int flow = (Integer) edgeFlowMap.get(reverseEdge);
40                                int capacity = reverseEdge.getCapacity();
41                                if (flow < capacity) {
42                                        marked.add(src);
43                                        result.addAll(DFSReversed(src, g, edgeFlowMap, marked));
44                                }
45                        }
46                }
47                return result;
48        }
49
50        static private Set<Node> BFSReversed(Node sink,
51                        DirectedGraph<Node, Edge> g, Map<Edge, Number> edgeFlowMap) {
52                Set<Node> result = new HashSet<Node>();
53                Set<Node> visitedNodes = new HashSet<Node>();
54                Stack<Node> nodesToVisit = new Stack<Node>();
55                result.add(sink);
56                nodesToVisit.push(sink);
57                while (!nodesToVisit.empty()) {
58                        Node currentNode = nodesToVisit.pop();
59                        visitedNodes.add(currentNode);
60                        Collection<Edge> inEdges = g.getInEdges(currentNode);
61                        Iterator<Edge> inEdgesIterator = inEdges.iterator();
62                        while (inEdgesIterator.hasNext()) {
63                                Edge edge = inEdgesIterator.next();
64                                Node src = g.getSource(edge);
65                                Edge reverseEdge = g.findEdge(src, currentNode);
66                                if (reverseEdge != null) {
67                                        int flow = (Integer) edgeFlowMap.get(reverseEdge);
68                                        int capacity = reverseEdge.getCapacity();
69                                        if (flow < capacity) {
70                                                if (!nodesToVisit.contains(src)
71                                                                && !visitedNodes.contains(src)) {
72                                                        nodesToVisit.push(src);
73                                                }
74                                                result.add(src);
75                                        }
76                                }
77                        }
78                }
79                return result;
80        }
81
82        static private DirectedGraph<Node, Edge> prepareDirectedGraph(
83                        Bisection bisection, Node source, Node sink, boolean forConductance) {
84                Subgraph B = bisection.getLargerSubgraph();
85                Subgraph A = bisection.getSmallerSubgraph();
86                int a = 0;
87                if (!forConductance)
88                        a = A.getVertexCount();
89                else {
90//                      a = Math.min(B.totalDegree(),A.totalDegree());
91                        a = A.totalDegree();
92                }
93                int c = bisection.edgeCut() / 2;
94
95                DirectedGraph<Node, Edge> g = new DirectedSparseGraph<Node, Edge>();
96                Iterator<Node> nodes = A.iterator();
97                while (nodes.hasNext()) {
98                        Node u = nodes.next();
99                        g.addVertex(u);
100                }
101                nodes = A.iterator();
102                int id = 0;
103                while (nodes.hasNext()) {
104                        Node u = nodes.next();
105                        Iterator<Node> neighbors = A.getNeighbors(u).iterator();
106                        while (neighbors.hasNext()) {
107                                Node v = neighbors.next();
108                                g.addEdge(new Edge(Integer.toString(id), A.getWeight(u, v), a),
109                                                u, v);
110                                id++;
111                        }
112                }
113
114                g.addVertex(source);
115                g.addVertex(sink);
116
117                // build the edges from source to each node of A which previously was
118                // connected
119                // with a node of B.
120                nodes = B.iterator();
121                while (nodes.hasNext()) {
122                        Node u = nodes.next();
123                        Iterator<Node> neighbors = B.getGraph().getNeighbors(u).iterator();
124                        while (neighbors.hasNext()) {
125                                Node v = neighbors.next();
126                                if (A.contains(v)) {
127                                        Edge e = g.findEdge(source, v);
128                                        if (e != null) {
129                                                e.setCapacity(e.getCapacity() + a);
130                                        } else {
131                                                g.addEdge(new Edge(Integer.toString(id), 1, a), source,
132                                                                v);
133                                                id++;
134                                        }
135                                }
136                        }
137                }
138
139                nodes = A.iterator();
140                while (nodes.hasNext()) {
141                        Node u = nodes.next();
142                        if(forConductance)
143                                g.addEdge(new Edge(Integer.toString(id), 1, c * bisection.getGraph().degree(u)), u, sink);
144                        else
145                                g.addEdge(new Edge(Integer.toString(id), 1, c), u, sink);
146                        id++;
147                }
148                return g;
149        }
150
151        /**
152         * Given a partion of a graph, execute the Max-Flow Quotient-cut Improvement
153         * algorithm, to find an improved cut and then returns the cluster which
154         * yields the best quotient cut.
155         *
156         * @param partition
157         * @return
158         */
159        static public Set<Node> mqi(Bisection partition, boolean forConductance) {
160//              System.out.println("INITIAL BISECTION: " + partition.toString());
161                boolean finished = false;
162                Bisection bisection = partition;
163                Set<Node> cluster = new HashSet<Node>(partition.getSmallerSubgraph()
164                                .createInducedSubgraph().getVertices());
165//              System.out.println("IMPROVING SUBGRAPH: " + cluster);
166                int maxFlowThreshold = Integer.MAX_VALUE;
167                while (!finished) {
168                        Node source = new Node("$$$$S");
169                        Node sink = new Node("$$$$T");
170                        DirectedGraph<Node, Edge> directedGraph = prepareDirectedGraph(
171                                        bisection, source, sink, true);
172                        Transformer<Edge, Number> capTransformer = new Transformer<Edge, Number>() {
173                                public Double transform(Edge e) {
174                                        return (double) e.getCapacity();
175                                }
176                        };
177                        Map<Edge, Number> edgeFlowMap = new HashMap<Edge, Number>();
178                        i = -1;
179                        // This Factory produces new edges for use by the algorithm
180                        Factory<Edge> edgeFactory = new Factory<Edge>() {
181                                public Edge create() {
182                                        i++;
183                                        return new Edge("$$$$" + Integer.toString(i), 1, 1);
184                                }
185                        };
186                        EdmondsKarpMaxFlow<Node, Edge> alg = new EdmondsKarpMaxFlow<Node, Edge>(
187                                        directedGraph, source, sink, capTransformer, edgeFlowMap,
188                                        edgeFactory);
189
190                        if (!forConductance)
191                                maxFlowThreshold = bisection.getLargerSubgraph()
192                                                .getVertexCount()
193                                                * bisection.edgeCut() / 2;
194                        else {
195//                              maxFlowThreshold = Math.min(bisection.getLargerSubgraph().totalDegree(), bisection.getSmallerSubgraph().totalDegree());
196                                maxFlowThreshold = bisection.getSmallerSubgraph().totalDegree();
197                                maxFlowThreshold = maxFlowThreshold
198                                                * (bisection.edgeCut() / 2);
199                        }
200                        alg.evaluate();
201//                      Util.viewFlowGraph(directedGraph, edgeFlowMap);
202                        System.out.println("MAX FLOW: " + alg.getMaxFlow() + " THRESHOLD: "
203                                        + maxFlowThreshold);
204                        if (alg.getMaxFlow() < maxFlowThreshold) {
205                                Set<Node> dfsResult = DFSReversed(sink, directedGraph,
206                                                edgeFlowMap, new HashSet<Node>());
207                                dfsResult.remove(sink);
208                                cluster = dfsResult;
209                                bisection = new Bisection(new Subgraph(
210                                        bisection.getGraph(), cluster));
211//                              System.out.println("REFINED BISECTION: " + bisection.toString());
212                        } else
213                                finished = true;
214                }
215                return cluster;
216        }
217
218}
Note: See TracBrowser for help on using the repository browser.