001/*
002 * Copyright 2006 - 2013
003 *     Stefan Balev     <stefan.balev@graphstream-project.org>
004 *     Julien Baudry    <julien.baudry@graphstream-project.org>
005 *     Antoine Dutot    <antoine.dutot@graphstream-project.org>
006 *     Yoann Pigné      <yoann.pigne@graphstream-project.org>
007 *     Guilhelm Savin   <guilhelm.savin@graphstream-project.org>
008 * 
009 * This file is part of GraphStream <http://graphstream-project.org>.
010 * 
011 * GraphStream is a library whose purpose is to handle static or dynamic
012 * graph, create them from scratch, file or any source and display them.
013 * 
014 * This program is free software distributed under the terms of two licenses, the
015 * CeCILL-C license that fits European law, and the GNU Lesser General Public
016 * License. You can  use, modify and/ or redistribute the software under the terms
017 * of the CeCILL-C license as circulated by CEA, CNRS and INRIA at the following
018 * URL <http://www.cecill.info> or under the terms of the GNU LGPL as published by
019 * the Free Software Foundation, either version 3 of the License, or (at your
020 * option) any later version.
021 * 
022 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
023 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
024 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
025 * 
026 * You should have received a copy of the GNU Lesser General Public License
027 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
028 * 
029 * The fact that you are presently reading this means that you have had
030 * knowledge of the CeCILL-C and LGPL licenses and that you accept their terms.
031 */
032package org.graphstream.algorithm.measure;
033
034import org.graphstream.algorithm.Algorithm;
035import org.graphstream.algorithm.NotInitializedException;
036import org.graphstream.graph.Graph;
037
038/**
039 * Base class for centrality measures. Subclasses should implements a
040 * {@link #computeCentrality()} method where centrality values will be stored in
041 * {@link #data}.
042 */
043public abstract class AbstractCentrality implements Algorithm {
044        public static enum NormalizationMode {
045                NONE, SUM_IS_1, MAX_1_MIN_0
046        }
047
048        /**
049         * Attribute name where centrality value will be stored.
050         */
051        protected String centralityAttribute;
052
053        /**
054         * Flag indicating if centrality values should be normalized between 0 and
055         * 1.
056         */
057        protected NormalizationMode normalize;
058
059        /**
060         * Array containing centrality values computed by centrality algorithms.
061         */
062        protected double[] data;
063
064        /**
065         * Graph on which centrality is computed.
066         */
067        protected Graph graph;
068
069        /**
070         * Default contructor.
071         * 
072         * @param attribute
073         *            attribute where centrality will be stored
074         * @param normalize
075         *            define the normalization mode
076         */
077        protected AbstractCentrality(String attribute, NormalizationMode normalize) {
078                this.centralityAttribute = attribute;
079                this.normalize = normalize;
080        }
081
082        /*
083         * (non-Javadoc)
084         * 
085         * @see
086         * org.graphstream.algorithm.Algorithm#init(org.graphstream.graph.Graph)
087         */
088        public void init(Graph graph) {
089                if (graph == null)
090                        throw new NullPointerException();
091
092                this.graph = graph;
093        }
094
095        /*
096         * (non-Javadoc)
097         * 
098         * @see org.graphstream.algorithm.Algorithm#compute()
099         */
100        public void compute() {
101                if (graph == null)
102                        throw new NotInitializedException(this);
103
104                int count = graph.getNodeCount();
105
106                if (data == null || data.length != count)
107                        data = new double[count];
108
109                computeCentrality();
110                copyValuesTo(centralityAttribute, normalize);
111        }
112
113        /**
114         * Copy values previously computed to a specific attribute. The
115         * {@link #compute()} method needs to have been call before calling this
116         * one.
117         * 
118         * @param attribute
119         *            destination attribute where values of centrality will be
120         *            stored
121         */
122        public void copyValuesTo(String attribute) {
123                copyValuesTo(attribute, NormalizationMode.NONE);
124        }
125
126        /**
127         * Copy values previously computed to a specific attribute. The
128         * {@link #compute()} method needs to have been call before calling this
129         * one.
130         * 
131         * @param attribute
132         *            destination attribute where values of centrality will be
133         *            stored
134         * @param normalize
135         *            defines the way that values have to be normalized
136         */
137        public void copyValuesTo(String attribute, NormalizationMode normalize) {
138                int count = graph.getNodeCount();
139
140                switch (normalize) {
141                case SUM_IS_1:
142                        double s = 0;
143
144                        for (int idx = 0; idx < count; idx++)
145                                s += data[idx];
146                        for (int idx = 0; idx < count; idx++)
147                                graph.getNode(idx).setAttribute(attribute,
148                                                data[idx] / s);
149
150                        break;
151                case MAX_1_MIN_0:
152                        double max = data[0];
153                        double min = max;
154
155                        for (int idx = 1; idx < count; idx++) {
156                                max = max < data[idx] ? data[idx] : max;
157                                min = min > data[idx] ? data[idx] : min;
158                        }
159
160                        for (int idx = 0; idx < count; idx++) {
161                                graph.getNode(idx).setAttribute(attribute,
162                                                (data[idx] - min) / (max - min));
163                        }
164
165                        break;
166                case NONE:
167                        for (int idx = 0; idx < count; idx++)
168                                graph.getNode(idx).setAttribute(attribute, data[idx]);
169
170                        break;
171                }
172        }
173
174        /**
175         * Getter for {@link #centralityAttribute}.
176         * 
177         * @return {@link #centralityAttribute}
178         */
179        public String getCentralityAttribute() {
180                return centralityAttribute;
181        }
182
183        /**
184         * Setter for {@link #centralityAttribute}.
185         * 
186         * @param centralityAttribute
187         *            new value of {@link #centralityAttribute}
188         */
189        public void setCentralityAttribute(String centralityAttribute) {
190                this.centralityAttribute = centralityAttribute;
191        }
192
193        /**
194         * Getter for {@link #normalize}.
195         * 
196         * @return {@link #normalize}
197         */
198        public NormalizationMode getNormalizationMode() {
199                return normalize;
200        }
201
202        /**
203         * Setter for {@link #normalize}.
204         * 
205         * @param normalize
206         *            new value of {@link #normalize}
207         */
208        public void setNormalizationMode(NormalizationMode normalize) {
209                this.normalize = normalize;
210        }
211
212        /**
213         * Define the computation of centrality values. These values are stored in
214         * {@link #data} using node index.
215         */
216        protected abstract void computeCentrality();
217}