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;
021
022import java.util.Comparator;
023import java.util.function.BinaryOperator;
024
025/**
026 * This {@code enum} determines whether the GA should maximize or minimize the
027 * fitness function.
028 *
029 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
030 * @since 1.0
031 * @version 6.2
032 */
033public enum Optimize {
034
035        /**
036         * GA minimization
037         */
038        MINIMUM {
039                @Override
040                public <T extends Comparable<? super T>>
041                int compare(final T a, final T b) {
042                        return b.compareTo(a);
043                }
044        },
045
046        /**
047         * GA maximization
048         */
049        MAXIMUM {
050                @Override
051                public <T extends Comparable<? super T>>
052                int compare(final T a, final T b) {
053                        return a.compareTo(b);
054                }
055        };
056
057        /**
058         * Compares two comparable objects. Returns a negative integer, zero, or a
059         * positive integer as the first argument is better than, equal to, or worse
060         * than the second. This compare method is {@code null}-hostile. If you need
061         * to make it {@code null}-friendly, you can wrap it with the
062         * {@link Comparator#nullsFirst(Comparator)} method.
063         * <p>
064         * {@snippet lang="java":
065         * final Comparator<Integer> comparator = nullsFirst(Optimize.MAXIMUM::compare);
066         * assertEquals(comparator.compare(null, null), 0);
067         * assertEquals(comparator.compare(null, 4), -1);
068         * assertEquals(comparator.compare(4, null), 1);
069         * }
070         * or
071         * {@snippet lang="java":
072         * final Comparator<Integer> comparator = nullsFirst(Optimize.MINIMUM::compare);
073         * assertEquals(comparator.compare(null, null), 0);
074         * assertEquals(comparator.compare(null, 4), -1);
075         * assertEquals(comparator.compare(4, null), 1);
076         * }
077         *
078         * @param <T> the comparable type
079         * @param a the first object to be compared.
080         * @param b the second object to be compared.
081         * @return a negative integer, zero, or a positive integer as the first
082         *          argument is better than, equal to, or worse than the second.
083         * @throws NullPointerException if one of the arguments is {@code null}.
084         */
085        public abstract <T extends Comparable<? super T>>
086        int compare(final T a, final T b);
087
088        /**
089         * Create an appropriate comparator of the given optimization strategy. A
090         * collection of comparable objects with the returned comparator will be
091         * sorted in <b>descending</b> order, according to the given definition
092         * of <i>better</i> and <i>worse</i>.
093         * <p>
094         * {@snippet lang="java":
095         * final Population<DoubleGene, Double> population = null; // @replace substring='null' replacement="..."
096         * population.sort(Optimize.MINIMUM.<Double>descending());
097         * }
098         *
099         * The code example above will populationSort the population according its
100         * fitness values in ascending order, since lower values are <i>better</i>
101         * in this case.
102         *
103         * @param <T> the type of the objects to compare.
104         * @return a new {@link Comparator} for the type {@code T}.
105         */
106        public <T extends Comparable<? super T>> Comparator<T> descending() {
107                return (a, b) -> compare(b, a);
108        }
109
110        /**
111         * Create an appropriate comparator of the given optimization strategy. A
112         * collection of comparable objects with the returned comparator will be
113         * sorted in <b>ascending</b> order, according to the given definition
114         * of <i>better</i> and <i>worse</i>.
115         * <p>
116         * {@snippet lang="java":
117         * final Population<DoubleGene, Double> population = null; // @replace substring='null' replacement="..."
118         * population.sort(Optimize.MINIMUM.<Double>ascending());
119         * }
120         *
121         * The code example above will populationSort the population according its
122         * fitness values in descending order, since lower values are <i>better</i>
123         * in this case.
124         *
125         * @param <T> the type of the objects to compare.
126         * @return a new {@link Comparator} for the type {@code T}.
127         */
128        public <T extends Comparable<? super T>> Comparator<T> ascending() {
129                return this::compare;
130        }
131
132        /**
133         * Return the best value, according to this optimization direction.
134         *
135         * @see #best()
136         *
137         * @param <C> the fitness value type.
138         * @param a the first value.
139         * @param b the second value.
140         * @return the best value. If both values are equal, the first one is returned.
141         * @throws NullPointerException if one of the given arguments is {@code null}
142         */
143        public <C extends Comparable<? super C>> C best(final C a, final C b) {
144                return compare(b, a) > 0 ? b : a;
145        }
146
147        /**
148         * Return a {@code null}-friendly function which returns the best element of
149         * two values. E.g.
150         *
151         * {@snippet lang="java":
152         * assertNull(Optimize.MAXIMUM.<Integer>best().apply(null, null));
153         * assertEquals(Optimize.MAXIMUM.<Integer>best().apply(null, 4), (Integer)4);
154         * assertEquals(Optimize.MAXIMUM.<Integer>best().apply(6, null), (Integer)6);
155         * }
156         *
157         * @see #best(Comparable, Comparable)
158         *
159         * @since 6.2
160         *
161         * @param <C> the comparable argument type
162         * @return a {@code null}-friendly method which returns the best element of
163         *             two values
164         */
165        public <C extends Comparable<? super C>> BinaryOperator<C> best() {
166                return (a, b) -> switch (cmp(a, b)) {
167                        case 2 -> best(a, b);
168                        case -1 -> b;
169                        default -> a;
170                };
171        }
172
173        /**
174         * Return the worst value, according to this optimization direction.
175         *
176         * @see #worst()
177         *
178         * @param <C> the fitness value type.
179         * @param a the first value.
180         * @param b the second value.
181         * @return the worst value. If both values are equal, the first one is returned.
182         * @throws NullPointerException if one of the given arguments is {@code null}
183         */
184        public <C extends Comparable<? super C>> C worst(final C a, final C b) {
185                return compare(b, a) < 0 ? b : a;
186        }
187
188        /**
189         * Return a {@code null}-friendly function which returns the worst element
190         * of two values. E.g.
191         *
192         * {@snippet lang="java":
193         * assertNull(Optimize.MAXIMUM.<Integer>worst().apply(null, null));
194         * assertEquals(Optimize.MAXIMUM.<Integer>worst().apply(null, 4), (Integer)4);
195         * assertEquals(Optimize.MAXIMUM.<Integer>worst().apply(6, null), (Integer)6);
196         * }
197         *
198         * @see #worst(Comparable, Comparable)
199         *
200         * @since 6.2
201         *
202         * @param <C> the comparable argument type
203         * @return a {@code null}-friendly method which returns the worst element of
204         *             two values
205         */
206        public <C extends Comparable<? super C>> BinaryOperator<C> worst() {
207                return (a, b) -> switch (cmp(a, b)) {
208                        case 2 -> worst(a, b);
209                        case -1 -> b;
210                        default -> a;
211                };
212        }
213
214        private static <T extends Comparable<? super T>>
215        int cmp(final T a, final T b) {
216                if (a != null) {
217                        if (b != null) {
218                                return 2;
219                        } else {
220                                return 1;
221                        }
222                } else {
223                        if (b != null) {
224                                return -1;
225                        } else {
226                                return 0;
227                        }
228                }
229        }
230
231}