VecFactory.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-5.2.0).
003  * Copyright (c) 2007-2020 Franz Wilhelmstötter
004  *
005  * Licensed under the Apache License, Version 2.0 (the "License");
006  * you may not use this file except in compliance with the License.
007  * 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  * Author:
018  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019  */
020 package io.jenetics.ext.moea;
021 
022 import java.util.Arrays;
023 import java.util.Comparator;
024 import java.util.List;
025 
026 import io.jenetics.Optimize;
027 
028 /**
029  * This interface allows to create vector object from a given array type
030  * {@code T}. It is useful if you need some additional parametrization of the
031  * created vectors.
032  <p>
033  * As the following example shows, only one {@code VecFactory} instance should
034  * be used for creating the vectors for a given multi-objective <em>problem</em>.
035  <pre>{@code
036  * private static final VecFactory<double[]> FACTORY = VecFactory.ofDoubleVec(
037  *     Optimize.MAXIMUM,
038  *     Optimize.MINIMUM,
039  *     Optimize.MINIMUM,
040  *     Optimize.MAXIMUM
041  * );
042  *
043  * // The fitness function.
044  * static Vec<double[]> fitness(final double[] x) {
045  *     final double[] result = new double[4];
046  *     // ...
047  *     return FACTORY.newVec(result);
048  * }
049  * }</pre>
050  * In the example above, the first dimension of the created vector is maximized,
051  * the following two are minimized and the last vector component is again
052  * maximized.
053  *
054  @see Vec
055  *
056  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
057  @version 5.2
058  @since 5.2
059  */
060 @FunctionalInterface
061 public interface VecFactory<T> {
062 
063     /**
064      * Create a new {@link Vec} object from the given {@code array}.
065      *
066      @param array the array used in the created vector
067      @return a new {@link Vec} object from the given {@code array}
068      @throws NullPointerException if the given {@code array} is {@code null}
069      @throws IllegalArgumentException if the {@code array} length is zero or
070      *         doesn't match the required length of the actual factory
071      */
072     Vec<T> newVec(final T array);
073 
074     /**
075      * Create a new factory for {@code int[]} vectors. Additionally you can
076      * specify the optimization direction (maximization or minimization) for
077      * each dimension. The dimensionality of the created vectors must be exactly
078      * the same as the given length of the given {@code optimizes}. If the
079      * lengths doesn't match, an {@link IllegalArgumentException} is thrown.
080      *
081      @see #ofIntVec(Optimize...)
082      *
083      * @apiNote
084      * Only one factory instance should be used for a given multi-objective
085      <em>problem</em>.
086      *
087      @param optimizes the optimization <em>direction</em> for each dimension
088      @return a new factory for {@code int[]} vectors
089      @throws NullPointerException if the given {@code optimizes} is
090      *         {@code null}
091      @throws IllegalArgumentException if the {@code optimizes} length is zero
092      */
093     static VecFactory<int[]> ofIntVec(final List<Optimize> optimizes) {
094         return new GeneralIntVecFactory(optimizes);
095     }
096 
097     /**
098      * Create a new factory for {@code int[]} vectors. Additionally you can
099      * specify the optimization direction (maximization or minimization) for
100      * each dimension. The dimensionality of the created vectors must be exactly
101      * the same as the given length of the given {@code optimizes}. If the
102      * lengths doesn't match, an {@link IllegalArgumentException} is thrown.
103      *
104      @see #ofIntVec(List)
105      *
106      * @apiNote
107      * Only one factory instance should be used for a given multi-objective
108      <em>problem</em>.
109      *
110      @param optimizes the optimization <em>direction</em> for each dimension
111      @return a new factory for {@code int[]} vectors
112      @throws NullPointerException if the given {@code optimizes} is
113      *         {@code null}
114      @throws IllegalArgumentException if the {@code optimizes} length is zero
115      */
116     static VecFactory<int[]> ofIntVec(final Optimize... optimizes) {
117         return ofIntVec(Arrays.asList(optimizes));
118     }
119 
120     /**
121      * Create a new factory for {@code int[]} vectors, where all dimensions are
122      * maximized.
123      *
124      @see Vec#of(int...)
125      *
126      @return a new factory for {@code int[]} vectors, where all dimensions are
127      *            maximized
128      */
129     static VecFactory<int[]> ofIntVec() {
130         return Vec::of;
131     }
132 
133     /**
134      * Create a new factory for {@code long[]} vectors. Additionally you can
135      * specify the optimization direction (maximization or minimization) for
136      * each dimension. The dimensionality of the created vectors must be exactly
137      * the same as the given length of the given {@code optimizes}. If the
138      * lengths doesn't match, an {@link IllegalArgumentException} is thrown.
139      *
140      @see #ofLongVec(Optimize...)
141      *
142      * @apiNote
143      * Only one factory instance should be used for a given multi-objective
144      <em>problem</em>.
145      *
146      @param optimizes the optimization <em>direction</em> for each dimension
147      @return a new factory for {@code long[]} vectors
148      @throws NullPointerException if the given {@code optimizes} is
149      *         {@code null}
150      @throws IllegalArgumentException if the {@code optimizes} length is zero
151      */
152     static VecFactory<long[]> ofLongVec(final List<Optimize> optimizes) {
153         return new GeneralLongVecFactory(optimizes);
154     }
155 
156     /**
157      * Create a new factory for {@code long[]} vectors. Additionally you can
158      * specify the optimization direction (maximization or minimization) for
159      * each dimension. The dimensionality of the created vectors must be exactly
160      * the same as the given length of the given {@code optimizes}. If the
161      * lengths doesn't match, an {@link IllegalArgumentException} is thrown.
162      *
163      @see #ofLongVec(List)
164      *
165      * @apiNote
166      * Only one factory instance should be used for a given multi-objective
167      <em>problem</em>.
168      *
169      @param optimizes the optimization <em>direction</em> for each dimension
170      @return a new factory for {@code long[]} vectors
171      @throws NullPointerException if the given {@code optimizes} is
172      *         {@code null}
173      @throws IllegalArgumentException if the {@code optimizes} length is zero
174      */
175     static VecFactory<long[]> ofLongVec(final Optimize... optimizes) {
176         return ofLongVec(Arrays.asList(optimizes));
177     }
178 
179     /**
180      * Create a new factory for {@code long[]} vectors, where all dimensions are
181      * maximized.
182      *
183      @see Vec#of(long...)
184      *
185      @return a new factory for {@code long[]} vectors, where all dimensions are
186      *            maximized
187      */
188     static VecFactory<long[]> ofLongVec() {
189         return Vec::of;
190     }
191 
192     /**
193      * Create a new factory for {@code double[]} vectors. Additionally you can
194      * specify the optimization direction (maximization or minimization) for
195      * each dimension. The dimensionality of the created vectors must be exactly
196      * the same as the given length of the given {@code optimizes}. If the
197      * lengths doesn't match, an {@link IllegalArgumentException} is thrown.
198      *
199      @see #ofDoubleVec(Optimize...)
200      *
201      * @apiNote
202      * Only one factory instance should be used for a given multi-objective
203      <em>problem</em>.
204      *
205      @param optimizes the optimization <em>direction</em> for each dimension
206      @return a new factory for {@code double[]} vectors
207      @throws NullPointerException if the given {@code optimizes} is
208      *         {@code null}
209      @throws IllegalArgumentException if the {@code optimizes} length is zero
210      */
211     static VecFactory<double[]> ofDoubleVec(final List<Optimize> optimizes) {
212         return new GeneralDoubleVecFactory(optimizes);
213     }
214 
215     /**
216      * Create a new factory for {@code double[]} vectors. Additionally you can
217      * specify the optimization direction (maximization or minimization) for
218      * each dimension. The dimensionality of the created vectors must be exactly
219      * the same as the given length of the given {@code optimizes}. If the
220      * lengths doesn't match, an {@link IllegalArgumentException} is thrown.
221      *
222      @see #ofDoubleVec(List)
223      *
224      * @apiNote
225      * Only one factory instance should be used for a given multi-objective
226      <em>problem</em>.
227      *
228      @param optimizes the optimization <em>direction</em> for each dimension
229      @return a new factory for {@code double[]} vectors
230      @throws NullPointerException if the given {@code optimizes} is
231      *         {@code null}
232      @throws IllegalArgumentException if the {@code optimizes} length is zero
233      */
234     static VecFactory<double[]> ofDoubleVec(final Optimize... optimizes) {
235         return ofDoubleVec(Arrays.asList(optimizes));
236     }
237 
238     /**
239      * Create a new factory for {@code double[]} vectors, where all dimensions
240      * are maximized.
241      *
242      @see Vec#of(double...)
243      *
244      @return a new factory for {@code double[]} vectors, where all dimensions
245      *         are maximized
246      */
247     static VecFactory<double[]> ofDoubleVec() {
248         return Vec::of;
249     }
250 
251     /**
252      * Create a new factory for {@code T[]} vectors. Additionally you can
253      * specify the optimization direction (maximization or minimization) for
254      * each dimension. The dimensionality of the created vectors must be exactly
255      * the same as the given length of the given {@code optimizes}. If the
256      * lengths doesn't match, an {@link IllegalArgumentException} is thrown.
257      *
258      @see #ofObjectVec(Comparator, ElementDistance, Optimize...)
259      *
260      @param comparator the array element comparator
261      @param distance the element distance function
262      @param optimizes the optimization <em>direction</em> for each dimension
263      @param <T> the array element type
264      @return  a new factory for {@code T[]} vectors
265      @throws NullPointerException if one of the arguments is {@code null}
266      @throws IllegalArgumentException if the {@code optimizes} length is zero
267      */
268     static <T> VecFactory<T[]> ofObjectVec(
269         final Comparator<? super T> comparator,
270         final ElementDistance<T[]> distance,
271         final List<Optimize> optimizes
272     ) {
273         return new GeneralObjectVecFactory<>(comparator, distance, optimizes);
274     }
275 
276     /**
277      * Create a new factory for {@code T[]} vectors. Additionally you can
278      * specify the optimization direction (maximization or minimization) for
279      * each dimension. The dimensionality of the created vectors must be exactly
280      * the same as the given length of the given {@code optimizes}. If the
281      * lengths doesn't match, an {@link IllegalArgumentException} is thrown.
282      *
283      @see #ofObjectVec(Comparator, ElementDistance, List)
284      *
285      @param comparator the array element comparator
286      @param distance the element distance function
287      @param optimizes the optimization <em>direction</em> for each dimension
288      @param <T> the array element type
289      @return  a new factory for {@code T[]} vectors
290      @throws NullPointerException if one of the arguments is {@code null}
291      @throws IllegalArgumentException if the {@code optimizes} length is zero
292      */
293     static <T> VecFactory<T[]> ofObjectVec(
294         final Comparator<? super T> comparator,
295         final ElementDistance<T[]> distance,
296         final Optimize... optimizes
297     ) {
298         return ofObjectVec(comparator, distance, Arrays.asList(optimizes));
299     }
300 
301 }