001/**
002 * Copyright (c) 2011, The University of Southampton and the individual contributors.
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without modification,
006 * are permitted provided that the following conditions are met:
007 *
008 *   *  Redistributions of source code must retain the above copyright notice,
009 *      this list of conditions and the following disclaimer.
010 *
011 *   *  Redistributions in binary form must reproduce the above copyright notice,
012 *      this list of conditions and the following disclaimer in the documentation
013 *      and/or other materials provided with the distribution.
014 *
015 *   *  Neither the name of the University of Southampton nor the names of its
016 *      contributors may be used to endorse or promote products derived from this
017 *      software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package org.openimaj.ml.clustering.spectral;
031
032import org.openimaj.ml.clustering.SpatialClusterer;
033import org.openimaj.ml.clustering.SpatialClusters;
034import org.openimaj.util.function.Function;
035import org.openimaj.util.pair.IndependentPair;
036
037/**
038 * @author Sina Samangooei (ss@ecs.soton.ac.uk)
039 * @param <DATATYPE>
040 *
041 */
042public class SpectralClusteringConf<DATATYPE> {
043        /**
044         * A function which can represent itself as a string
045         *
046         * @param <DATATYPE>
047         * @author Sina Samangooei (ss@ecs.soton.ac.uk)
048         */
049        public static interface ClustererProvider<DATATYPE>
050                        extends
051                                Function<IndependentPair<double[], double[][]>, SpatialClusterer<? extends SpatialClusters<DATATYPE>, DATATYPE>>
052        {
053                @Override
054                public String toString();
055        }
056
057        protected static class DefaultClustererFunction<DATATYPE> implements ClustererProvider<DATATYPE> {
058
059                private SpatialClusterer<? extends SpatialClusters<DATATYPE>, DATATYPE> internal;
060
061                public DefaultClustererFunction(SpatialClusterer<? extends SpatialClusters<DATATYPE>, DATATYPE> internal) {
062                        this.internal = internal;
063                }
064
065                @Override
066                public SpatialClusterer<? extends SpatialClusters<DATATYPE>, DATATYPE> apply(
067                                IndependentPair<double[], double[][]> in)
068                {
069                        return internal;
070                }
071
072                @Override
073                public String toString() {
074                        return internal.toString();
075                }
076
077        }
078
079        /**
080         * The internal clusterer
081         */
082
083        ClustererProvider<DATATYPE> internal;
084
085        /**
086         * The graph laplacian creator
087         */
088        public GraphLaplacian laplacian;
089
090        /**
091         * The method used to select the number of eigen vectors from the lower
092         * valued eigenvalues
093         */
094        public EigenChooser eigenChooser;
095
096        /**
097         *
098         */
099        public int skipEigenVectors = 0;
100
101        /**
102         *
103         */
104        public boolean eigenValueScale = false;
105
106        /**
107         * @param internal
108         *            the internal clusterer
109         * @param eigK
110         *            the value handed to {@link HardCodedEigenChooser}
111         *
112         */
113        public SpectralClusteringConf(SpatialClusterer<? extends SpatialClusters<DATATYPE>, DATATYPE> internal, int eigK) {
114                this.internal = new DefaultClustererFunction<DATATYPE>(internal);
115                this.laplacian = new GraphLaplacian.Normalised();
116                this.eigenChooser = new HardCodedEigenChooser(eigK);
117
118        }
119
120        /**
121         * The underlying {@link EigenChooser} is set to an
122         * {@link ChangeDetectingEigenChooser} which looks for a 100x gap between
123         * eigen vectors to select number of clusters. It also insists upon a
124         * maximum of 0.1 * number of data items (so 10 items per cluster)
125         *
126         * @param internal
127         *            the internal clusterer
128         *
129         */
130        public SpectralClusteringConf(SpatialClusterer<? extends SpatialClusters<DATATYPE>, DATATYPE> internal) {
131                this.internal = new DefaultClustererFunction<DATATYPE>(internal);
132                this.laplacian = new GraphLaplacian.Normalised();
133                this.eigenChooser = new ChangeDetectingEigenChooser(100, 0.1);
134
135        }
136
137        /**
138         * @param internal
139         *            an internal clusterer
140         * @param lap
141         *            the laplacian
142         * @param top
143         *            the top eigen vectors
144         */
145        public SpectralClusteringConf(SpatialClusterer<? extends SpatialClusters<DATATYPE>, DATATYPE> internal,
146                        GraphLaplacian lap, int top)
147        {
148                this.internal = new DefaultClustererFunction<DATATYPE>(internal);
149                this.laplacian = lap;
150                this.eigenChooser = new HardCodedEigenChooser(top);
151        }
152
153        /**
154         * The underlying {@link EigenChooser} is set to an
155         * {@link ChangeDetectingEigenChooser} which looks for a 100x gap between
156         * eigen vectors to select number of clusters. It also insists upon a
157         * maximum of 0.1 * number of data items (so 10 items per cluster)
158         *
159         * @param internal
160         *            the internal clusterer
161         * @param laplacian
162         *            the graph laplacian
163         *
164         */
165        public SpectralClusteringConf(SpatialClusterer<? extends SpatialClusters<DATATYPE>, DATATYPE> internal,
166                        GraphLaplacian laplacian)
167        {
168                this.internal = new DefaultClustererFunction<DATATYPE>(internal);
169                this.laplacian = laplacian;
170                this.eigenChooser = new ChangeDetectingEigenChooser(100, 0.1);
171
172        }
173
174        /**
175         * The underlying {@link EigenChooser} is set to an
176         * {@link ChangeDetectingEigenChooser} which looks for a 100x gap between
177         * eigen vectors to select number of clusters. It also insists upon a
178         * maximum of 0.1 * number of data items (so 10 items per cluster)
179         * 
180         * @param internal
181         *            the internal clusterer
182         *
183         */
184        public SpectralClusteringConf(ClustererProvider<DATATYPE> internal) {
185                this.internal = internal;
186                this.laplacian = new GraphLaplacian.Normalised();
187                this.eigenChooser = new ChangeDetectingEigenChooser(100, 0.1);
188
189        }
190
191}