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 static java.lang.Math.clamp; 023 024import java.util.Comparator; 025 026/** 027 * The {@code Vec} interface represents the fitness result of a multi-objective 028 * fitness function. It also defines a set of static factory methods which 029 * allows you to create {@code Vec} instance from a given {@code int[]}, 030 * {@code long[]} or {@code double[]} array. 031 * 032 * {@snippet lang="java": 033 * final Vec<double[]> point2D = Vec.of(0.1, 5.4); 034 * final Vec<int[]> point3D = Vec.of(1, 2, 3); 035 * } 036 * 037 * The underlying array is <em>just</em> wrapped and <em>not</em> copied. This 038 * means you can change the values of the {@code Vec} once it is created, 039 * <em>Not copying the underlying array is done for performance reason. Changing 040 * the {@code Vec} data is, of course, never a good idea.</em> 041 * 042 * @implNote 043 * Although the {@code Vec} interface extends the {@link Comparable} interface, 044 * it violates its <em>general</em> contract. It <em>only</em> 045 * implements the pareto <em>dominance</em> relation, which defines a partial 046 * order. So, trying to sort a list of {@code Vec} objects, might lead 047 * to an exception (thrown by the sorting method) at runtime. 048 * 049 * @param <T> the underlying array type, like {@code int[]} or {@code double[]} 050 * 051 * @see VecFactory 052 * @see <a href="https://en.wikipedia.org/wiki/Pareto_efficiency"> 053 * Pareto efficiency</a> 054 * 055 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 056 * @version 4.1 057 * @since 4.1 058 */ 059public interface Vec<T> extends Comparable<Vec<T>> { 060 061 /** 062 * Return the underlying data structure. 063 * 064 * @return the underlying data structure 065 */ 066 T data(); 067 068 /** 069 * Return the number of vector elements. 070 * 071 * @return the number of vector elements 072 */ 073 int length(); 074 075 /** 076 * Return the comparator for comparing the elements of this MO vector. 077 * 078 * @return the comparator for comparing the elements of this MO vector 079 */ 080 ElementComparator<T> comparator(); 081 082 /** 083 * Return a function which calculates the element distance of a vector at a 084 * given element index. 085 * 086 * @return a function which calculates the element distance of a vector at a 087 * given element index 088 */ 089 ElementDistance<T> distance(); 090 091 /** 092 * Return the comparator which defines the (Pareto) dominance measure. 093 * 094 * @return the comparator which defines the (Pareto) dominance measure 095 */ 096 Comparator<T> dominance(); 097 098 099 /* ************************************************************************* 100 * Default methods derived from the methods above. 101 * ************************************************************************/ 102 103 /** 104 * Compares the {@code this} vector with the {@code other} at the given 105 * component {@code index}. 106 * 107 * @param other the other vector 108 * @param index the component index 109 * @return a negative integer, zero, or a positive integer as 110 * {@code this[index]} is less than, equal to, or greater than 111 * {@code other[index]} 112 * @throws NullPointerException if the {@code other} object is {@code null} 113 * @throws IllegalArgumentException if the {@code index} is out of the valid 114 * range {@code [0, length())} 115 */ 116 default int compare(final Vec<T> other, final int index) { 117 return comparator().compare(data(), other.data(), index); 118 } 119 120 /** 121 * Calculates the distance between two vector elements at the given 122 * {@code index}. 123 * 124 * @param other the second vector 125 * @param index the vector element index 126 * @return the distance between two vector elements 127 * @throws NullPointerException if the {@code other} vector is {@code null} 128 * @throws IllegalArgumentException if the {@code index} is out of the valid 129 * range {@code [0, length())} 130 */ 131 default double distance(final Vec<T> other, final int index) { 132 return distance().distance(data(), other.data(), index); 133 } 134 135 /** 136 * Calculates the <a href="https://en.wikipedia.org/wiki/Pareto_efficiency"> 137 * <b>Pareto Dominance</b></a> of vector {@code value()} and {@code other}. 138 * 139 * @param other the other vector 140 * @return {@code 1} if <b>value()</b> ≻ <b>other</b>, {@code -1} if 141 * <b>other</b> ≻ <b>value()</b> and {@code 0} otherwise 142 * @throws NullPointerException if the {@code other} vector is {@code null} 143 */ 144 default int dominance(final Vec<T> other) { 145 return dominance().compare(data(), other.data()); 146 } 147 148 /** 149 * The default implementation uses the {@link #dominance(Vec)} function 150 * for defining a <b>partial</b> order of two vectors. 151 * 152 * @param other the other vector 153 * @return {@code 1} if <b>value()</b> ≻ <b>other</b>, {@code -1} if 154 * <b>other</b> ≻ <b>value()</b> and {@code 0} otherwise 155 * @throws NullPointerException if the {@code other} vector is {@code null} 156 */ 157 @Override 158 default int compareTo(final Vec<T> other) { 159 return dominance(other); 160 } 161 162 163 /* ************************************************************************* 164 * Common 'dominance' methods. 165 * ************************************************************************/ 166 167 /** 168 * Calculates the <a href="https://en.wikipedia.org/wiki/Pareto_efficiency"> 169 * <b>Pareto Dominance</b></a> of the two vectors <b>u</b> and <b>v</b>. 170 * 171 * @see Pareto#dominance(Comparable[], Comparable[]) 172 * 173 * @param u the first vector 174 * @param v the second vector 175 * @param <C> the element type of vector <b>u</b> and <b>v</b> 176 * @return {@code 1} if <b>u</b> ≻ <b>v</b>, {@code -1} if <b>v</b> ≻ 177 * <b>u</b> and {@code 0} otherwise 178 * @throws NullPointerException if one of the arguments is {@code null} 179 * @throws IllegalArgumentException if {@code u.length != v.length} 180 */ 181 static <C extends Comparable<? super C>> int 182 dominance(final C[] u, final C[] v) { 183 return dominance(u, v, Comparator.naturalOrder()); 184 } 185 186 /** 187 * Calculates the <a href="https://en.wikipedia.org/wiki/Pareto_efficiency"> 188 * <b>Pareto Dominance</b></a> of the two vectors <b>u</b> and <b>v</b>. 189 * 190 * @see Pareto#dominance(Object[], Object[], Comparator) 191 * 192 * @param u the first vector 193 * @param v the second vector 194 * @param comparator the element comparator which is used for calculating 195 * the dominance 196 * @param <T> the element type of vector <b>u</b> and <b>v</b> 197 * @return {@code 1} if <b>u</b> ≻ <b>v</b>, {@code -1} if <b>v</b> ≻ 198 * <b>u</b> and {@code 0} otherwise 199 * @throws NullPointerException if one of the arguments is {@code null} 200 * @throws IllegalArgumentException if {@code u.length != v.length} 201 */ 202 static <T> int 203 dominance(final T[] u, final T[] v, final Comparator<? super T> comparator) { 204 return Pareto.dominance(u, v, comparator); 205 } 206 207 /** 208 * Calculates the <a href="https://en.wikipedia.org/wiki/Pareto_efficiency"> 209 * <b>Pareto Dominance</b></a> of the two vectors <b>u</b> and <b>v</b>. 210 * 211 * @see Pareto#dominance(int[], int[]) 212 * 213 * @param u the first vector 214 * @param v the second vector 215 * @return {@code 1} if <b>u</b> ≻ <b>v</b>, {@code -1} if <b>v</b> ≻ 216 * <b>u</b> and {@code 0} otherwise 217 * @throws NullPointerException if one of the arguments is {@code null} 218 * @throws IllegalArgumentException if {@code u.length != v.length} 219 */ 220 static int dominance(final int[] u, final int[] v) { 221 return Pareto.dominance(u, v); 222 } 223 224 /** 225 * Calculates the <a href="https://en.wikipedia.org/wiki/Pareto_efficiency"> 226 * <b>Pareto Dominance</b></a> of the two vectors <b>u</b> and <b>v</b>. 227 * 228 * @see Pareto#dominance(long[], long[]) 229 * 230 * @param u the first vector 231 * @param v the second vector 232 * @return {@code 1} if <b>u</b> ≻ <b>v</b>, {@code -1} if <b>v</b> ≻ 233 * <b>u</b> and {@code 0} otherwise 234 * @throws NullPointerException if one of the arguments is {@code null} 235 * @throws IllegalArgumentException if {@code u.length != v.length} 236 */ 237 static int dominance(final long[] u, final long[] v) { 238 return Pareto.dominance(u, v); 239 } 240 241 /** 242 * Calculates the <a href="https://en.wikipedia.org/wiki/Pareto_efficiency"> 243 * <b>Pareto Dominance</b></a> of the two vectors <b>u</b> and <b>v</b>. 244 * 245 * @see Pareto#dominance(double[], double[]) 246 * 247 * @param u the first vector 248 * @param v the second vector 249 * @return {@code 1} if <b>u</b> ≻ <b>v</b>, {@code -1} if <b>v</b> ≻ 250 * <b>u</b> and {@code 0} otherwise 251 * @throws NullPointerException if one of the arguments is {@code null} 252 * @throws IllegalArgumentException if {@code u.length != v.length} 253 */ 254 static int dominance(final double[] u, final double[] v) { 255 return Pareto.dominance(u, v); 256 } 257 258 /* ************************************************************************* 259 * Static factory functions for wrapping ordinary arrays. 260 * ************************************************************************/ 261 262 /** 263 * Wraps the given array into a {@code Vec} object. 264 * 265 * @param array the wrapped array 266 * @param <C> the array element type 267 * @return the given array wrapped into a {@code Vec} object. 268 * @throws NullPointerException if one of the arguments is {@code null} 269 * @throws IllegalArgumentException if the {@code array} length is zero 270 */ 271 static <C extends Comparable<? super C>> 272 Vec<C[]> of(final C[] array) { 273 return of( 274 array, 275 (u, v, i) -> clamp(u[i].compareTo(v[i]), -1, 1) 276 ); 277 } 278 279 /** 280 * Wraps the given array into a {@code Vec} object. 281 * 282 * @param array the wrapped array 283 * @param distance the array element distance measure 284 * @param <C> the array element type 285 * @return the given array wrapped into a {@code Vec} object. 286 * @throws NullPointerException if one of the arguments is {@code null} 287 * @throws IllegalArgumentException if the {@code array} length is zero 288 */ 289 static <C extends Comparable<? super C>> Vec<C[]> of( 290 final C[] array, 291 final ElementDistance<C[]> distance 292 ) { 293 return of(array, Comparator.naturalOrder(), distance); 294 } 295 296 /** 297 * Wraps the given array into a {@code Vec} object. 298 * 299 * @param array the wrapped array 300 * @param comparator the (natural order) comparator of the array elements 301 * @param distance the distance function between two vector elements 302 * @param <T> the array element type 303 * @return the given array wrapped into a {@code Vec} object. 304 * @throws NullPointerException if one of the arguments is {@code null} 305 * @throws IllegalArgumentException if the {@code array} length is zero 306 */ 307 static <T> Vec<T[]> of( 308 final T[] array, 309 final Comparator<? super T> comparator, 310 final ElementDistance<T[]> distance 311 ) { 312 return new SimpleObjectVec<>(array, comparator, distance); 313 } 314 315 /** 316 * Wraps the given array into a {@code Vec} object. 317 * 318 * @param array the wrapped array 319 * @return the given array wrapped into a {@code Vec} object. 320 * @throws NullPointerException if the given {@code array} is {@code null} 321 * @throws IllegalArgumentException if the {@code array} length is zero 322 */ 323 static Vec<int[]> of(final int... array) { 324 return new SimpleIntVec(array); 325 } 326 327 /** 328 * Wraps the given array into a {@code Vec} object. 329 * 330 * @param array the wrapped array 331 * @return the given array wrapped into a {@code Vec} object. 332 * @throws NullPointerException if the given {@code array} is {@code null} 333 * @throws IllegalArgumentException if the {@code array} length is zero 334 */ 335 static Vec<long[]> of(final long... array) { 336 return new SimpleLongVec(array); 337 } 338 339 /** 340 * Wraps the given array into a {@code Vec} object. 341 * 342 * @param array the wrapped array 343 * @return the given array wrapped into a {@code Vec} object. 344 * @throws NullPointerException if the given {@code array} is {@code null} 345 * @throws IllegalArgumentException if the {@code array} length is zero 346 */ 347 static Vec<double[]> of(final double... array) { 348 return new SimpleDoubleVec(array); 349 } 350 351}