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 }