001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.math.optimization.fitting;
019    
020    import java.io.Serializable;
021    
022    import org.apache.commons.math.analysis.DifferentiableUnivariateRealFunction;
023    import org.apache.commons.math.analysis.UnivariateRealFunction;
024    import org.apache.commons.math.exception.DimensionMismatchException;
025    import org.apache.commons.math.exception.util.LocalizedFormats;
026    import org.apache.commons.math.exception.ZeroException;
027    import org.apache.commons.math.exception.NullArgumentException;
028    
029    /**
030     * A Gaussian function.  Specifically:
031     * <p>
032     * <tt>f(x) = a + b*exp(-((x - c)^2 / (2*d^2)))</tt>
033     * <p>
034     * Notation key:
035     * <ul>
036     * <li><tt>x^n</tt>: <tt>x</tt> raised to the power of <tt>n</tt>
037     * <li><tt>exp(x)</tt>: <i>e</i><tt>^x</tt>
038     * </ul>
039     * References:
040     * <ul>
041     * <li><a href="http://en.wikipedia.org/wiki/Gaussian_function">Wikipedia:
042     *   Gaussian function</a>
043     * </ul>
044     *
045     * @see GaussianDerivativeFunction
046     * @see ParametricGaussianFunction
047     * @since 2.2
048     * @version $Revision: 1037327 $ $Date: 2010-11-20 21:57:37 +0100 (sam. 20 nov. 2010) $
049     */
050    public class GaussianFunction implements DifferentiableUnivariateRealFunction, Serializable {
051    
052        /** Serializable version identifier. */
053        private static final long serialVersionUID = -3195385616125629512L;
054    
055        /** Parameter a of this function. */
056        private final double a;
057    
058        /** Parameter b of this function. */
059        private final double b;
060    
061        /** Parameter c of this function. */
062        private final double c;
063    
064        /** Parameter d of this function. */
065        private final double d;
066    
067        /**
068         * Constructs an instance with the specified parameters.
069         *
070         * @param a <tt>a</tt> parameter value
071         * @param b <tt>b</tt> parameter value
072         * @param c <tt>c</tt> parameter value
073         * @param d <tt>d</tt> parameter value
074         *
075         * @throws IllegalArgumentException if <code>d</code> is 0
076         */
077        public GaussianFunction(double a, double b, double c, double d) {
078            if (d == 0.0) {
079                throw new ZeroException();
080            }
081            this.a = a;
082            this.b = b;
083            this.c = c;
084            this.d = d;
085        }
086    
087        /**
088         * Constructs an instance with the specified parameters.
089         *
090         * @param parameters <tt>a</tt>, <tt>b</tt>, <tt>c</tt>, and <tt>d</tt>
091         *        parameter values
092         *
093         * @throws IllegalArgumentException if <code>parameters</code> is null,
094         *         <code>parameters</code> length is not 4, or if
095         *         <code>parameters[3]</code> is 0
096         */
097        public GaussianFunction(double[] parameters) {
098            if (parameters == null) {
099                throw new NullArgumentException(LocalizedFormats.INPUT_ARRAY);
100            }
101            if (parameters.length != 4) {
102                throw new DimensionMismatchException(4, parameters.length);
103            }
104            if (parameters[3] == 0.0) {
105                throw new ZeroException();
106            }
107            this.a = parameters[0];
108            this.b = parameters[1];
109            this.c = parameters[2];
110            this.d = parameters[3];
111        }
112    
113        /** {@inheritDoc} */
114        public UnivariateRealFunction derivative() {
115            return new GaussianDerivativeFunction(b, c, d);
116        }
117    
118        /** {@inheritDoc} */
119        public double value(double x) {
120            final double xMc = x - c;
121            return a + b * Math.exp(-xMc * xMc / (2.0 * (d * d)));
122        }
123    
124        /**
125         * Gets <tt>a</tt> parameter value.
126         *
127         * @return <tt>a</tt> parameter value
128         */
129        public double getA() {
130            return a;
131        }
132    
133        /**
134         * Gets <tt>b</tt> parameter value.
135         *
136         * @return <tt>b</tt> parameter value
137         */
138        public double getB() {
139            return b;
140        }
141    
142        /**
143         * Gets <tt>c</tt> parameter value.
144         *
145         * @return <tt>c</tt> parameter value
146         */
147        public double getC() {
148            return c;
149        }
150    
151        /**
152         * Gets <tt>d</tt> parameter value.
153         *
154         * @return <tt>d</tt> parameter value
155         */
156        public double getD() {
157            return d;
158        }
159    }