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}