source: src/main/java/weka/clusterers/MetisMQIClusterer.java @ 22

Last change on this file since 22 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: 5.3 KB
Line 
1package weka.clusterers;
2
3import java.util.Enumeration;
4import java.util.HashMap;
5import java.util.Iterator;
6import java.util.Map;
7import java.util.Set;
8import java.util.Vector;
9
10import weka.clusterers.forMetisMQI.GraphAlgorithms;
11import weka.clusterers.forMetisMQI.graph.Node;
12import weka.clusterers.forMetisMQI.graph.UndirectedGraph;
13import weka.core.Attribute;
14import weka.core.Capabilities;
15import weka.core.Instance;
16import weka.core.Instances;
17import weka.core.Option;
18import weka.core.OptionHandler;
19import weka.core.Utils;
20import weka.core.Capabilities.Capability;
21
22public class MetisMQIClusterer extends AbstractClusterer implements
23                OptionHandler {
24
25        private int numberOfClusters = 2;
26
27        private int sizeFinerGraph = 10;
28
29        /**
30         * It maps each cluster with an integer id.
31         */
32        private Map<Set<Node>, Integer> clustersMap = null;
33
34        /**
35         * Holds the cluster membership for each node.
36         */
37        private Map<Node, Integer> nodeMap = null;
38       
39        /**
40         * True if a random bisection must be used.
41         */
42        private boolean randomBisection = false;
43
44        /**
45         *
46         */
47        private static final long serialVersionUID = 1L;
48
49        @Override
50        public void buildClusterer(Instances data) throws Exception {
51                getCapabilities().testWithFail(data);
52                UndirectedGraph g = new UndirectedGraph();
53                g.loadFromInstance(data);
54                Set<Set<Node>> clusters = GraphAlgorithms.metisMqi(g, numberOfClusters,
55                                sizeFinerGraph, randomBisection);
56                setNumClusters(clusters.size());
57                int i = 0;
58                Iterator<Set<Node>> clusterIterator = clusters.iterator();
59                clustersMap = new HashMap<Set<Node>, Integer>();
60                nodeMap = new HashMap<Node, Integer>();
61                while (clusterIterator.hasNext()) {
62                        Set<Node> cluster = clusterIterator.next();
63                        clustersMap.put(cluster, i);
64                        Iterator<Node> nodeIterator = cluster.iterator();
65                        while (nodeIterator.hasNext()) {
66                                Node n = nodeIterator.next();
67                                if (nodeMap.get(n) == null) {
68                                        nodeMap.put(n, i);
69                                }
70                        }
71                        i++;
72                }
73        }
74
75        @Override
76        public int clusterInstance(Instance instance) throws Exception {
77                Attribute from = instance.dataset().attribute("from");
78                Attribute to = instance.dataset().attribute("to");
79                Instance edge = instance;
80                Node node1 = new Node(Integer.toString(((int) Math.round(edge
81                                .value(from)))));
82                Node node2 = new Node(Integer.toString(((int) Math
83                                .round(edge.value(to)))));
84                if (nodeMap.get(node1) == nodeMap.get(node2))
85                        return nodeMap.get(node1);
86                else
87                        throw new Exception();
88        }
89
90        /**
91         * Parses a given list of options.
92         * <p/>
93         *
94         * <!-- options-start --> Valid options are:
95         * <p/>
96         *
97         * <pre>
98         * -N &lt;num&gt;
99         *  number of clusters.
100         *  (default 2).
101         * </pre>
102         *
103         * <pre>
104         * -S
105         *  Maximum size of the finer graph during the coarsening phase.
106         * </pre>
107         *
108         * <!-- options-end -->
109         *
110         * @param options
111         *            the list of options as an array of strings
112         * @throws Exception
113         *             if an option is not supported
114         */
115        @Override
116        public void setOptions(String[] options) throws Exception {
117                String optionString = Utils.getOption('N', options);
118                if (optionString.length() != 0) {
119                        setNumClusters(Integer.parseInt(optionString));
120                }
121                optionString = Utils.getOption('S', options);
122                if (optionString.length() != 0) {
123                        setSizeFinerGraph(Integer.parseInt(optionString));
124                }
125                optionString = Utils.getOption('R', options);
126                setRandomBisection(Boolean.parseBoolean(optionString));
127        }
128
129        private void setRandomBisection(boolean b) {
130                this.randomBisection = b;
131        }
132
133        /**
134         * Gets the current settings of MetisMQIClusterer
135         *
136         * @return an array of strings suitable for passing to setOptions()
137         */
138        @SuppressWarnings("unchecked")
139        @Override
140        public String[] getOptions() {
141                Vector result;
142                result = new Vector();
143                result.add("-N");
144                result.add("" + getNumClusters());
145                result.add("-S");
146                result.add("" + getSizeFinerGraph());
147                result.add("-R");
148                return (String[]) result.toArray(new String[result.size()]);
149        }
150
151        private int getSizeFinerGraph() {
152                return sizeFinerGraph;
153        }
154
155        private int getNumClusters() {
156                return numberOfClusters;
157        }
158
159        /**
160         * Returns an enumeration describing the available options.
161         *
162         * @return an enumeration of all the available options.
163         */
164        @SuppressWarnings("unchecked")
165        @Override
166        public Enumeration listOptions() {
167                Vector result = new Vector();
168                result.addElement(new Option("\tnumber of clusters.\n"
169                                + "\t(default 2).", "N", 1, "-N <num>"));
170                result.addElement(new Option("\tsize of finer graph.\n"
171                                + "\t(default 10).", "S", 1, "-S <num>"));
172                return result.elements();
173        }
174
175        private void setSizeFinerGraph(int size) {
176                this.sizeFinerGraph = size;
177        }
178
179        private void setNumClusters(int n) {
180                this.numberOfClusters = n;
181        }
182
183        @Override
184        public double[] distributionForInstance(Instance instance) throws Exception {
185                double[] d = new double[numberOfClusters()];
186                d[clusterInstance(instance)] = 1.0;
187                return d;
188        }
189
190        @Override
191        public Capabilities getCapabilities() {
192                Capabilities result = super.getCapabilities();
193                result.enable(Capability.NUMERIC_ATTRIBUTES);
194                result.enable(Capability.NO_CLASS);
195                return result;
196        }
197
198        @Override
199        public int numberOfClusters() throws Exception {
200                return numberOfClusters;
201        }
202
203        /**
204         * Main method for executing this clusterer.
205         *
206         * @param args
207         *            the options, use "-h" to display options
208         */
209        public static void main(String[] args) {
210                AbstractClusterer.runClusterer(new MetisMQIClusterer(), args);
211        }
212
213}
Note: See TracBrowser for help on using the repository browser.