1 | package weka.clusterers.forMetisMQI; |
---|
2 | |
---|
3 | import java.awt.Dimension; |
---|
4 | import java.util.HashMap; |
---|
5 | import java.util.Iterator; |
---|
6 | import java.util.Map; |
---|
7 | import java.util.Set; |
---|
8 | |
---|
9 | import javax.swing.JFrame; |
---|
10 | |
---|
11 | import org.apache.commons.collections15.Factory; |
---|
12 | import org.apache.commons.collections15.Transformer; |
---|
13 | |
---|
14 | import weka.clusterers.forMetisMQI.graph.Bisection; |
---|
15 | import weka.clusterers.forMetisMQI.graph.Edge; |
---|
16 | import weka.clusterers.forMetisMQI.graph.Node; |
---|
17 | import weka.clusterers.forMetisMQI.graph.Subgraph; |
---|
18 | import weka.clusterers.forMetisMQI.graph.UndirectedGraph; |
---|
19 | import edu.uci.ics.jung.algorithms.flows.EdmondsKarpMaxFlow; |
---|
20 | import edu.uci.ics.jung.algorithms.layout.KKLayout; |
---|
21 | import edu.uci.ics.jung.algorithms.layout.Layout; |
---|
22 | import edu.uci.ics.jung.graph.DirectedGraph; |
---|
23 | import edu.uci.ics.jung.graph.DirectedSparseGraph; |
---|
24 | import edu.uci.ics.jung.graph.Graph; |
---|
25 | import edu.uci.ics.jung.visualization.BasicVisualizationServer; |
---|
26 | import edu.uci.ics.jung.visualization.decorators.ToStringLabeller; |
---|
27 | |
---|
28 | public class MQI { |
---|
29 | |
---|
30 | static int i = -1; |
---|
31 | |
---|
32 | public static void viewGraph(Graph<Node, Edge> g){ |
---|
33 | Layout<Node, Edge> layout = new KKLayout<Node, Edge>(g); |
---|
34 | layout.setSize(new Dimension(800,600)); // sets the initial size of the space |
---|
35 | // The BasicVisualizationServer<V,E> is parameterized by the edge types |
---|
36 | BasicVisualizationServer<Node,Edge> vv = |
---|
37 | new BasicVisualizationServer<Node,Edge>(layout); |
---|
38 | vv.setPreferredSize(new Dimension(800,600)); //Sets the viewing area size |
---|
39 | vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<Node>()); |
---|
40 | vv.getRenderContext().setEdgeLabelTransformer(new ToStringLabeller<Edge>()); |
---|
41 | |
---|
42 | JFrame frame = new JFrame("Simple Graph View"); |
---|
43 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); |
---|
44 | frame.getContentPane().add(vv); |
---|
45 | frame.pack(); |
---|
46 | frame.setVisible(true); |
---|
47 | } |
---|
48 | |
---|
49 | /** |
---|
50 | * Given a bisection, returns the cardinality of the larger subgraph. |
---|
51 | * @param b |
---|
52 | * @return |
---|
53 | */ |
---|
54 | static private int getMaxCardinality(Bisection b) { |
---|
55 | Subgraph A = null; |
---|
56 | if(b.getSubgraph().getVertexCount() > b.getComplement().getVertexCount()) { |
---|
57 | A = b.getSubgraph(); |
---|
58 | } |
---|
59 | else { |
---|
60 | A = b.getComplement(); |
---|
61 | } |
---|
62 | return A.getVertexCount(); |
---|
63 | } |
---|
64 | |
---|
65 | static private DirectedGraph<Node, Edge> prepareDirectedGraph(Bisection partition, Node source, Node sink) { |
---|
66 | Subgraph A = null; |
---|
67 | Subgraph B = null; |
---|
68 | if(partition.getSubgraph().getVertexCount() > partition.getComplement().getVertexCount()) { |
---|
69 | A = partition.getSubgraph(); |
---|
70 | B = partition.getComplement(); |
---|
71 | } |
---|
72 | else { |
---|
73 | A = partition.getComplement(); |
---|
74 | B = partition.getSubgraph(); |
---|
75 | } |
---|
76 | int a = A.getVertexCount(); |
---|
77 | int c = partition.edgeCut() / 2; |
---|
78 | |
---|
79 | |
---|
80 | DirectedGraph<Node,Edge> g = new DirectedSparseGraph<Node, Edge>(); |
---|
81 | Iterator<Node> nodes = A.iterator(); |
---|
82 | while(nodes.hasNext()) { |
---|
83 | Node u = nodes.next(); |
---|
84 | g.addVertex(u); |
---|
85 | } |
---|
86 | |
---|
87 | nodes = A.iterator(); |
---|
88 | int id = 0; |
---|
89 | while(nodes.hasNext()) { |
---|
90 | Node u = nodes.next(); |
---|
91 | Iterator<Node> neighbors = A.getNeighbors(u).iterator(); |
---|
92 | while(neighbors.hasNext()) { |
---|
93 | Node v = neighbors.next(); |
---|
94 | g.addEdge(new Edge(Integer.toString(id),A.getWeight(u, v),a),u,v); |
---|
95 | id++; |
---|
96 | } |
---|
97 | } |
---|
98 | |
---|
99 | g.addVertex(source); |
---|
100 | g.addVertex(sink); |
---|
101 | |
---|
102 | |
---|
103 | nodes = B.iterator(); |
---|
104 | while(nodes.hasNext()) { |
---|
105 | Node u = nodes.next(); |
---|
106 | Iterator<Node> neighbors = B.getGraph().getNeighbors(u).iterator(); |
---|
107 | while(neighbors.hasNext()) { |
---|
108 | Node v = neighbors.next(); |
---|
109 | if(A.contains(v)) { |
---|
110 | g.addEdge(new Edge(Integer.toString(id),1,a),source,v); |
---|
111 | id++; |
---|
112 | } |
---|
113 | } |
---|
114 | } |
---|
115 | |
---|
116 | nodes = A.iterator(); |
---|
117 | while(nodes.hasNext()) { |
---|
118 | Node u = nodes.next(); |
---|
119 | g.addEdge(new Edge(Integer.toString(id),1,c),u,sink); |
---|
120 | id++; |
---|
121 | } |
---|
122 | return g; |
---|
123 | } |
---|
124 | |
---|
125 | static public Bisection mqi(Bisection partition) { |
---|
126 | boolean finished = false; |
---|
127 | Bisection bisection = partition; |
---|
128 | int maxFlowThreshold = Integer.MAX_VALUE; |
---|
129 | while (!finished) { |
---|
130 | UndirectedGraph startingGraph = partition.getGraph(); |
---|
131 | Node source = new Node("S"); |
---|
132 | Node sink = new Node("T"); |
---|
133 | DirectedGraph<Node, Edge> g = prepareDirectedGraph(bisection, source, sink); |
---|
134 | Transformer<Edge, Number> capTransformer = new Transformer<Edge, Number>() { |
---|
135 | public Double transform(Edge e) { |
---|
136 | return (double) e.getCapacity(); |
---|
137 | } |
---|
138 | }; |
---|
139 | Map<Edge, Number> edgeFlowMap = new HashMap<Edge, Number>(); |
---|
140 | // This Factory produces new edges for use by the algorithm |
---|
141 | i=-1; |
---|
142 | Factory<Edge> edgeFactory = new Factory<Edge>() { |
---|
143 | public Edge create() { |
---|
144 | i++; |
---|
145 | return new Edge(Integer.toString(i), 1, 1); |
---|
146 | } |
---|
147 | }; |
---|
148 | EdmondsKarpMaxFlow<Node, Edge> alg = new EdmondsKarpMaxFlow<Node, Edge>( |
---|
149 | g, source, sink, capTransformer, edgeFlowMap, edgeFactory); |
---|
150 | |
---|
151 | maxFlowThreshold = getMaxCardinality(bisection) * bisection.edgeCut() / 2; |
---|
152 | alg.evaluate(); |
---|
153 | if(alg.getMaxFlow() < maxFlowThreshold) { |
---|
154 | Set<Node> sinkPartition = alg.getNodesInSinkPartition(); |
---|
155 | Set<Node> sourcePartition = alg.getNodesInSourcePartition(); |
---|
156 | bisection = prepareBisection(startingGraph, sourcePartition, sinkPartition); |
---|
157 | } else |
---|
158 | finished = true; |
---|
159 | } |
---|
160 | return bisection; |
---|
161 | } |
---|
162 | |
---|
163 | private static Bisection prepareBisection(UndirectedGraph g, Set<Node> sourcePartition, Set<Node> sinkPartition) { |
---|
164 | Bisection b = null; |
---|
165 | Subgraph sourceSubgraph = new Subgraph(g, sourcePartition); |
---|
166 | Subgraph sinkSubgraph = new Subgraph(g, sinkPartition); |
---|
167 | Subgraph subgraph = null; |
---|
168 | if(sourceSubgraph.getVertexCount() > sinkSubgraph.getVertexCount()) |
---|
169 | subgraph =sourceSubgraph; |
---|
170 | else |
---|
171 | subgraph = sinkSubgraph; |
---|
172 | b = new Bisection(subgraph); |
---|
173 | return b; |
---|
174 | } |
---|
175 | |
---|
176 | } |
---|