001/* 002 * Java Genetic Algorithm Library (jenetics-8.1.0). 003 * Copyright (c) 2007-2024 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 */ 020package io.jenetics.ext.moea; 021 022import java.util.Comparator; 023import java.util.List; 024 025import io.jenetics.Optimize; 026 027/** 028 * This interface allows creating a vector object from a given array type 029 * {@code T}. It is useful if you need some additional parametrization of the 030 * created vectors. 031 * <p> 032 * As the following example shows, only one {@code VecFactory} instance should 033 * be used for creating the vectors for a given multi-objective <em>problem</em>. 034 * {@snippet lang="java": 035 * private static final VecFactory<double[]> FACTORY = VecFactory.ofDoubleVec( 036 * Optimize.MAXIMUM, 037 * Optimize.MINIMUM, 038 * Optimize.MINIMUM, 039 * Optimize.MAXIMUM 040 * ); 041 * 042 * // The fitness function. 043 * static Vec<double[]> fitness(final double[] x) { 044 * final double[] result = new double[4]; 045 * // ... 046 * return FACTORY.newVec(result); 047 * } 048 * } 049 * In the example above, the first dimension of the created vector is maximized, 050 * the following two are minimized, and the last vector component is again 051 * maximized. 052 * 053 * @see Vec 054 * 055 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 056 * @version 6.0 057 * @since 5.2 058 */ 059@FunctionalInterface 060public interface VecFactory<T> { 061 062 /** 063 * Create a new {@link Vec} object from the given {@code array}. 064 * 065 * @param array the array used in the created vector 066 * @return a new {@link Vec} object from the given {@code array} 067 * @throws NullPointerException if the given {@code array} is {@code null} 068 * @throws IllegalArgumentException if the {@code array} length is zero or 069 * doesn't match the required length of the actual factory 070 */ 071 Vec<T> newVec(final T array); 072 073 /** 074 * Create a new factory for {@code int[]} vectors. Additionally, you can 075 * specify the optimization direction (maximization or minimization) for 076 * each dimension. The dimensionality of the created vectors must be exactly 077 * the same as the given length of the given {@code optimizes}. If the 078 * lengths don't match, an {@link IllegalArgumentException} is thrown. 079 * 080 * @see #ofIntVec(Optimize...) 081 * 082 * @apiNote 083 * Only one factory instance should be used for a given multi-objective 084 * <em>problem</em>. 085 * 086 * @param optimizes the optimization <em>direction</em> for each dimension 087 * @return a new factory for {@code int[]} vectors 088 * @throws NullPointerException if the given {@code optimizes} is 089 * {@code null} 090 * @throws IllegalArgumentException if the {@code optimizes} length is zero 091 */ 092 static VecFactory<int[]> ofIntVec(final List<Optimize> optimizes) { 093 return new GeneralIntVecFactory(optimizes); 094 } 095 096 /** 097 * Create a new factory for {@code int[]} vectors. Additionally, you can 098 * specify the optimization direction (maximization or minimization) for 099 * each dimension. The dimensionality of the created vectors must be exactly 100 * the same as the given length of the given {@code optimizes}. If the 101 * lengths don't match, an {@link IllegalArgumentException} is thrown. 102 * 103 * @see #ofIntVec(List) 104 * 105 * @apiNote 106 * Only one factory instance should be used for a given multi-objective 107 * <em>problem</em>. 108 * 109 * @param optimizes the optimization <em>direction</em> for each dimension 110 * @return a new factory for {@code int[]} vectors 111 * @throws NullPointerException if the given {@code optimizes} is 112 * {@code null} 113 * @throws IllegalArgumentException if the {@code optimizes} length is zero 114 */ 115 static VecFactory<int[]> ofIntVec(final Optimize... optimizes) { 116 return ofIntVec(List.of(optimizes)); 117 } 118 119 /** 120 * Create a new factory for {@code int[]} vectors, where all dimensions are 121 * maximized. 122 * 123 * @see Vec#of(int...) 124 * 125 * @return a new factory for {@code int[]} vectors, where all dimensions are 126 * maximized 127 */ 128 static VecFactory<int[]> ofIntVec() { 129 return Vec::of; 130 } 131 132 /** 133 * Create a new factory for {@code long[]} vectors. Additionally, you can 134 * specify the optimization direction (maximization or minimization) for 135 * each dimension. The dimensionality of the created vectors must be exactly 136 * the same as the given length of the given {@code optimizes}. If the 137 * lengths don't match, an {@link IllegalArgumentException} is thrown. 138 * 139 * @see #ofLongVec(Optimize...) 140 * 141 * @apiNote 142 * Only one factory instance should be used for a given multi-objective 143 * <em>problem</em>. 144 * 145 * @param optimizes the optimization <em>direction</em> for each dimension 146 * @return a new factory for {@code long[]} vectors 147 * @throws NullPointerException if the given {@code optimizes} is 148 * {@code null} 149 * @throws IllegalArgumentException if the {@code optimizes} length is zero 150 */ 151 static VecFactory<long[]> ofLongVec(final List<Optimize> optimizes) { 152 return new GeneralLongVecFactory(optimizes); 153 } 154 155 /** 156 * Create a new factory for {@code long[]} vectors. Additionally, you can 157 * specify the optimization direction (maximization or minimization) for 158 * each dimension. The dimensionality of the created vectors must be exactly 159 * the same as the given length of the given {@code optimizes}. If the 160 * lengths don't match, an {@link IllegalArgumentException} is thrown. 161 * 162 * @see #ofLongVec(List) 163 * 164 * @apiNote 165 * Only one factory instance should be used for a given multi-objective 166 * <em>problem</em>. 167 * 168 * @param optimizes the optimization <em>direction</em> for each dimension 169 * @return a new factory for {@code long[]} vectors 170 * @throws NullPointerException if the given {@code optimizes} is 171 * {@code null} 172 * @throws IllegalArgumentException if the {@code optimizes} length is zero 173 */ 174 static VecFactory<long[]> ofLongVec(final Optimize... optimizes) { 175 return ofLongVec(List.of(optimizes)); 176 } 177 178 /** 179 * Create a new factory for {@code long[]} vectors, where all dimensions are 180 * maximized. 181 * 182 * @see Vec#of(long...) 183 * 184 * @return a new factory for {@code long[]} vectors, where all dimensions are 185 * maximized 186 */ 187 static VecFactory<long[]> ofLongVec() { 188 return Vec::of; 189 } 190 191 /** 192 * Create a new factory for {@code double[]} vectors. Additionally, you can 193 * specify the optimization direction (maximization or minimization) for 194 * each dimension. The dimensionality of the created vectors must be exactly 195 * the same as the given length of the given {@code optimizes}. If the 196 * lengths don't match, an {@link IllegalArgumentException} is thrown. 197 * 198 * @see #ofDoubleVec(Optimize...) 199 * 200 * @apiNote 201 * Only one factory instance should be used for a given multi-objective 202 * <em>problem</em>. 203 * 204 * @param optimizes the optimization <em>direction</em> for each dimension 205 * @return a new factory for {@code double[]} vectors 206 * @throws NullPointerException if the given {@code optimizes} is 207 * {@code null} 208 * @throws IllegalArgumentException if the {@code optimizes} length is zero 209 */ 210 static VecFactory<double[]> ofDoubleVec(final List<Optimize> optimizes) { 211 return new GeneralDoubleVecFactory(optimizes); 212 } 213 214 /** 215 * Create a new factory for {@code double[]} vectors. Additionally, you can 216 * specify the optimization direction (maximization or minimization) for 217 * each dimension. The dimensionality of the created vectors must be exactly 218 * the same as the given length of the given {@code optimizes}. If the 219 * lengths don't match, an {@link IllegalArgumentException} is thrown. 220 * 221 * @see #ofDoubleVec(List) 222 * 223 * @apiNote 224 * Only one factory instance should be used for a given multi-objective 225 * <em>problem</em>. 226 * 227 * @param optimizes the optimization <em>direction</em> for each dimension 228 * @return a new factory for {@code double[]} vectors 229 * @throws NullPointerException if the given {@code optimizes} is 230 * {@code null} 231 * @throws IllegalArgumentException if the {@code optimizes} length is zero 232 */ 233 static VecFactory<double[]> ofDoubleVec(final Optimize... optimizes) { 234 return ofDoubleVec(List.of(optimizes)); 235 } 236 237 /** 238 * Create a new factory for {@code double[]} vectors, where all dimensions 239 * are maximized. 240 * 241 * @see Vec#of(double...) 242 * 243 * @return a new factory for {@code double[]} vectors, where all dimensions 244 * are maximized 245 */ 246 static VecFactory<double[]> ofDoubleVec() { 247 return Vec::of; 248 } 249 250 /** 251 * Create a new factory for {@code T[]} vectors. Additionally, you can 252 * specify the optimization direction (maximization or minimization) for 253 * each dimension. The dimensionality of the created vectors must be exactly 254 * the same as the given length of the given {@code optimizes}. If the 255 * lengths don't match, an {@link IllegalArgumentException} is thrown. 256 * 257 * @see #ofObjectVec(Comparator, ElementDistance, Optimize...) 258 * 259 * @param comparator the array element comparator 260 * @param distance the element distance function 261 * @param optimizes the optimization <em>direction</em> for each dimension 262 * @param <T> the array element type 263 * @return a new factory for {@code T[]} vectors 264 * @throws NullPointerException if one of the arguments is {@code null} 265 * @throws IllegalArgumentException if the {@code optimizes} length is zero 266 */ 267 static <T> VecFactory<T[]> ofObjectVec( 268 final Comparator<? super T> comparator, 269 final ElementDistance<T[]> distance, 270 final List<Optimize> optimizes 271 ) { 272 return new GeneralObjectVecFactory<>(comparator, distance, optimizes); 273 } 274 275 /** 276 * Create a new factory for {@code T[]} vectors. Additionally, you can 277 * specify the optimization direction (maximization or minimization) for 278 * each dimension. The dimensionality of the created vectors must be exactly 279 * the same as the given length of the given {@code optimizes}. If the 280 * lengths don't match, an {@link IllegalArgumentException} is thrown. 281 * 282 * @see #ofObjectVec(Comparator, ElementDistance, List) 283 * 284 * @param comparator the array element comparator 285 * @param distance the element distance function 286 * @param optimizes the optimization <em>direction</em> for each dimension 287 * @param <T> the array element type 288 * @return a new factory for {@code T[]} vectors 289 * @throws NullPointerException if one of the arguments is {@code null} 290 * @throws IllegalArgumentException if the {@code optimizes} length is zero 291 */ 292 static <T> VecFactory<T[]> ofObjectVec( 293 final Comparator<? super T> comparator, 294 final ElementDistance<T[]> distance, 295 final Optimize... optimizes 296 ) { 297 return ofObjectVec(comparator, distance, List.of(optimizes)); 298 } 299 300 /** 301 * Create a new factory for {@code T[]} vectors with comparable element 302 * types. Additionally, you can specify the optimization direction 303 * (maximization or minimization) for each dimension. The dimensionality of 304 * the created vectors must be exactly the same as the given length of the 305 * given {@code optimizes}. If the lengths don't match, an 306 * {@link IllegalArgumentException} is thrown. 307 * 308 * @since 6.0 309 * 310 * @see #ofObjectVec(Comparator, ElementDistance, List) 311 * 312 * @param distance the element distance function 313 * @param optimizes the optimization <em>direction</em> for each dimension 314 * @param <T> the array element type 315 * @return a new factory for {@code T[]} vectors 316 * @throws NullPointerException if one of the arguments is {@code null} 317 * @throws IllegalArgumentException if the {@code optimizes} length is zero 318 */ 319 static <T extends Comparable<? super T>> VecFactory<T[]> ofObjectVec( 320 final ElementDistance<T[]> distance, 321 final List<Optimize> optimizes 322 ) { 323 return ofObjectVec( 324 Comparator.naturalOrder(), 325 distance, 326 optimizes 327 ); 328 } 329 330 /** 331 * Create a new factory for {@code T[]} vectors with comparable element 332 * types. Additionally, you can specify the optimization direction 333 * (maximization or minimization) for each dimension. The dimensionality of 334 * the created vectors must be exactly the same as the given length of the 335 * given {@code optimizes}. If the lengths don't match, an 336 * {@link IllegalArgumentException} is thrown. 337 * 338 * @since 6.0 339 * 340 * @see #ofObjectVec(Comparator, ElementDistance, List) 341 * 342 * @param distance the element distance function 343 * @param optimizes the optimization <em>direction</em> for each dimension 344 * @param <T> the array element type 345 * @return a new factory for {@code T[]} vectors 346 * @throws NullPointerException if one of the arguments is {@code null} 347 * @throws IllegalArgumentException if the {@code optimizes} length is zero 348 */ 349 static <T extends Comparable<? super T>> VecFactory<T[]> ofObjectVec( 350 final ElementDistance<T[]> distance, 351 final Optimize... optimizes 352 ) { 353 return ofObjectVec( 354 Comparator.naturalOrder(), 355 distance, 356 optimizes 357 ); 358 } 359 360 /** 361 * Create a new factory for {@code T[]} vectors with comparable element 362 * types. Additionally, you can specify the optimization direction 363 * (maximization or minimization) for each dimension. The dimensionality of 364 * the created vectors must be exactly the same as the given length of the 365 * given {@code optimizes}. If the lengths don't match, an 366 * {@link IllegalArgumentException} is thrown. 367 * 368 * @since 6.0 369 * 370 * @see #ofObjectVec(Comparator, ElementDistance, List) 371 * 372 * @param optimizes the optimization <em>direction</em> for each dimension 373 * @param <T> the array element type 374 * @return a new factory for {@code T[]} vectors 375 * @throws NullPointerException if one of the arguments is {@code null} 376 * @throws IllegalArgumentException if the {@code optimizes} length is zero 377 */ 378 static <T extends Comparable<? super T>> VecFactory<T[]> 379 ofObjectVec(final List<Optimize> optimizes) { 380 return ofObjectVec(VecFactory::dist, optimizes); 381 } 382 383 private static <T extends Comparable<? super T>> 384 double dist(final T[] u, final T[] v, final int i) { 385 return Integer.compare(u[i].compareTo(v[i]), 0); 386 } 387 388 /** 389 * Create a new factory for {@code T[]} vectors with comparable element 390 * types. Additionally, you can specify the optimization direction 391 * (maximization or minimization) for each dimension. The dimensionality of 392 * the created vectors must be exactly the same as the given length of the 393 * given {@code optimizes}. If the lengths don't match, an 394 * {@link IllegalArgumentException} is thrown. 395 * 396 * @since 6.0 397 * 398 * @see #ofObjectVec(Comparator, ElementDistance, List) 399 * 400 * @param optimizes the optimization <em>direction</em> for each dimension 401 * @param <T> the array element type 402 * @return a new factory for {@code T[]} vectors 403 * @throws NullPointerException if one of the arguments is {@code null} 404 * @throws IllegalArgumentException if the {@code optimizes} length is zero 405 */ 406 static <T extends Comparable<? super T>> VecFactory<T[]> 407 ofObjectVec(final Optimize... optimizes) { 408 return ofObjectVec(VecFactory::dist, optimizes); 409 } 410 411 /** 412 * Create a new factory for {@code T[]} vectors with comparable element 413 * types. Additionally, you can specify the optimization direction 414 * (maximization or minimization) for each dimension. The dimensionality of 415 * the created vectors must be exactly the same as the given length of the 416 * given {@code optimizes}. If the lengths don't match, an 417 * {@link IllegalArgumentException} is thrown. 418 * 419 * @since 6.0 420 * 421 * @see Vec#of(Comparable[]) 422 * 423 * @param <T> the array element type 424 * @return a new factory for {@code T[]} vectors 425 * @throws NullPointerException if one of the arguments is {@code null} 426 * @throws IllegalArgumentException if the {@code optimizes} length is zero 427 */ 428 static <T extends Comparable<? super T>> VecFactory<T[]> ofObjectVec() { 429 return Vec::of; 430 } 431 432}