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

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

Aggiunto metodo per stampare i grafi in formato utile per kmetis; modificato politica di azione di mqi, ora agisce sulla partizione piu` grande.

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 weka.clusterers.forMetisMQI.util.Util;
19import edu.uci.ics.jung.algorithms.flows.EdmondsKarpMaxFlow;
20import edu.uci.ics.jung.graph.DirectedGraph;
21import edu.uci.ics.jung.graph.DirectedSparseGraph;
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 A = bisection.getLargerSubgraph();
85                Subgraph B = bisection.getSmallerSubgraph();
86                int a = 0;
87                if (!forConductance)
88                        a = A.getVertexCount();
89                else {
90                        Iterator<Node> aIterator = A.iterator();
91                        while(aIterator.hasNext()) {
92                                a += bisection.getGraph().degree(aIterator.next());
93                        }
94                }
95                int c = bisection.edgeCut() / 2;
96
97                DirectedGraph<Node, Edge> g = new DirectedSparseGraph<Node, Edge>();
98                Iterator<Node> nodes = A.iterator();
99                while (nodes.hasNext()) {
100                        Node u = nodes.next();
101                        g.addVertex(u);
102                }
103                nodes = A.iterator();
104                int id = 0;
105                while (nodes.hasNext()) {
106                        Node u = nodes.next();
107                        Iterator<Node> neighbors = A.getNeighbors(u).iterator();
108                        while (neighbors.hasNext()) {
109                                Node v = neighbors.next();
110                                g.addEdge(new Edge(Integer.toString(id), A.getWeight(u, v), a),
111                                                u, v);
112                                id++;
113                        }
114                }
115
116                g.addVertex(source);
117                g.addVertex(sink);
118
119                // build the edges from source to each node of A which previously was
120                // connected
121                // with a node of B.
122                nodes = B.iterator();
123                while (nodes.hasNext()) {
124                        Node u = nodes.next();
125                        Iterator<Node> neighbors = B.getGraph().getNeighbors(u).iterator();
126                        while (neighbors.hasNext()) {
127                                Node v = neighbors.next();
128                                if (A.contains(v)) {
129                                        Edge e = g.findEdge(source, v);
130                                        if (e != null) {
131                                                e.setCapacity(e.getCapacity() + a);
132                                        } else {
133                                                g.addEdge(new Edge(Integer.toString(id), 1, a), source,
134                                                                v);
135                                                id++;
136                                        }
137                                }
138                        }
139                }
140
141                nodes = A.iterator();
142                while (nodes.hasNext()) {
143                        Node u = nodes.next();
144                        if(forConductance)
145                                //FIXME: CONTROLLAMI
146                                g.addEdge(new Edge(Integer.toString(id), 1, c * bisection.getGraph().degree(u)), u, sink);
147                        else
148                                g.addEdge(new Edge(Integer.toString(id), 1, c), u, sink);
149                        id++;
150                }
151                return g;
152        }
153
154        /**
155         * Given a partion of a graph, execute the Max-Flow Quotient-cut Improvement
156         * algorithm, to find an improved cut and then returns the cluster which
157         * yields the best quotient cut.
158         *
159         * @param partition
160         * @return
161         */
162        static public Set<Node> mqi(Bisection partition, boolean forConductance) {
163//              System.out.println("INITIAL BISECTION: " + partition.toString());
164                boolean finished = false;
165                Bisection bisection = partition;
166                Set<Node> cluster = new HashSet<Node>(partition.getLargerSubgraph()
167                                .createInducedSubgraph().getVertices());
168                int maxFlowThreshold = Integer.MAX_VALUE;
169                while (!finished) {
170                        Node source = new Node("$$$$S");
171                        Node sink = new Node("$$$$T");
172                        DirectedGraph<Node, Edge> directedGraph = prepareDirectedGraph(
173                                        bisection, source, sink, true);
174                        Transformer<Edge, Number> capTransformer = new Transformer<Edge, Number>() {
175                                public Double transform(Edge e) {
176                                        return (double) e.getCapacity();
177                                }
178                        };
179                        Map<Edge, Number> edgeFlowMap = new HashMap<Edge, Number>();
180                        i = -1;
181                        // This Factory produces new edges for use by the algorithm
182                        Factory<Edge> edgeFactory = new Factory<Edge>() {
183                                public Edge create() {
184                                        i++;
185                                        return new Edge("$$$$" + Integer.toString(i), 1, 1);
186                                }
187                        };
188                        EdmondsKarpMaxFlow<Node, Edge> alg = new EdmondsKarpMaxFlow<Node, Edge>(
189                                        directedGraph, source, sink, capTransformer, edgeFlowMap,
190                                        edgeFactory);
191
192                        if (!forConductance)
193                                maxFlowThreshold = bisection.getLargerSubgraph()
194                                                .getVertexCount()
195                                                * bisection.edgeCut() / 2;
196                        else {
197                                Iterator<Node> aIterator = bisection.getLargerSubgraph().iterator();
198                                maxFlowThreshold = 0;
199                                while(aIterator.hasNext())
200                                        maxFlowThreshold += partition.getGraph().degree(aIterator.next());
201                                maxFlowThreshold = maxFlowThreshold
202                                                * (bisection.edgeCut() / 2);
203                        }
204                        alg.evaluate();
205//                      Util.viewFlowGraph(directedGraph, edgeFlowMap);
206                        System.out.println("MAX FLOW: " + alg.getMaxFlow() + " THRESHOLD: "
207                                        + maxFlowThreshold);
208                        if (alg.getMaxFlow() < maxFlowThreshold) {
209                                Set<Node> dfsResult = DFSReversed(sink, directedGraph,
210                                                edgeFlowMap, new HashSet<Node>());
211                                dfsResult.remove(sink);
212                                cluster = dfsResult;
213                                bisection = new Bisection(new Subgraph(
214                                        bisection.getGraph(), cluster));
215                        } else
216                                finished = true;
217                }
218                return cluster;
219        }
220
221}
Note: See TracBrowser for help on using the repository browser.