View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.math4.neuralnet.sofm;
19  
20  import org.apache.commons.math4.neuralnet.sofm.util.ExponentialDecayFunction;
21  import org.apache.commons.math4.neuralnet.sofm.util.QuasiSigmoidDecayFunction;
22  
23  /**
24   * Factory for creating instances of {@link NeighbourhoodSizeFunction}.
25   *
26   * @since 3.3
27   */
28  public final class NeighbourhoodSizeFunctionFactory {
29      /** Class contains only static methods. */
30      private NeighbourhoodSizeFunctionFactory() {}
31  
32      /**
33       * Creates an exponential decay {@link NeighbourhoodSizeFunction function}.
34       * It will compute <code>a e<sup>-x / b</sup></code>,
35       * where {@code x} is the (integer) independent variable and
36       * <ul>
37       *  <li><code>a = initValue</code>
38       *  <li><code>b = -numCall / ln(valueAtNumCall / initValue)</code>
39       * </ul>
40       *
41       * @param initValue Initial value, i.e.
42       * {@link NeighbourhoodSizeFunction#value(long) value(0)}.
43       * @param valueAtNumCall Value of the function at {@code numCall}.
44       * @param numCall Argument for which the function returns
45       * {@code valueAtNumCall}.
46       * @return the neighbourhood size function.
47       * @throws IllegalArgumentException if {@code initValue <= 0},
48       * {@code valueAtNumCall <= 0}, {@code valueAtNumCall >= initValue}
49       * or {@code numCall <= 0}.
50       */
51      public static NeighbourhoodSizeFunction exponentialDecay(final double initValue,
52                                                               final double valueAtNumCall,
53                                                               final long numCall) {
54          return new NeighbourhoodSizeFunction() {
55              /** DecayFunction. */
56              private final ExponentialDecayFunction decay
57                  = new ExponentialDecayFunction(initValue, valueAtNumCall, numCall);
58  
59              /** {@inheritDoc} */
60              @Override
61              public int value(long n) {
62                  return (int) Math.rint(decay.applyAsDouble(n));
63              }
64          };
65      }
66  
67      /**
68       * Creates an sigmoid-like {@code NeighbourhoodSizeFunction function}.
69       * The function {@code f} will have the following properties:
70       * <ul>
71       *  <li>{@code f(0) = initValue}</li>
72       *  <li>{@code numCall} is the inflexion point</li>
73       *  <li>{@code slope = f'(numCall)}</li>
74       * </ul>
75       *
76       * @param initValue Initial value, i.e.
77       * {@link NeighbourhoodSizeFunction#value(long) value(0)}.
78       * @param slope Value of the function derivative at {@code numCall}.
79       * @param numCall Inflexion point.
80       * @return the neighbourhood size function.
81       * @throws IllegalArgumentException if {@code initValue <= 0},
82       * {@code slope >= 0} or {@code numCall <= 0}.
83       */
84      public static NeighbourhoodSizeFunction quasiSigmoidDecay(final double initValue,
85                                                                final double slope,
86                                                                final long numCall) {
87          return new NeighbourhoodSizeFunction() {
88              /** DecayFunction. */
89              private final QuasiSigmoidDecayFunction decay
90                  = new QuasiSigmoidDecayFunction(initValue, slope, numCall);
91  
92              /** {@inheritDoc} */
93              @Override
94              public int value(long n) {
95                  return (int) Math.rint(decay.applyAsDouble(n));
96              }
97          };
98      }
99  }