001/*
002 * Java Genetic Algorithm Library (jenetics-8.3.0).
003 * Copyright (c) 2007-2025 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         * {@snippet lang="java":
151         * assertNull(Optimize.MAXIMUM.<Integer>best().apply(null, null));
152         * assertEquals(Optimize.MAXIMUM.<Integer>best().apply(null, 4), (Integer)4);
153         * assertEquals(Optimize.MAXIMUM.<Integer>best().apply(6, null), (Integer)6);
154         * }
155         *
156         * @see #best(Comparable, Comparable)
157         *
158         * @since 6.2
159         *
160         * @param <C> the comparable argument type
161         * @return a {@code null}-friendly method which returns the best element of
162         *             two values
163         */
164        public <C extends Comparable<? super C>> BinaryOperator<C> best() {
165                return (a, b) -> switch (cmp(a, b)) {
166                        case 2 -> best(a, b);
167                        case -1 -> b;
168                        default -> a;
169                };
170        }
171
172        /**
173         * Return the worst value, according to this optimization direction.
174         *
175         * @see #worst()
176         *
177         * @param <C> the fitness value type.
178         * @param a the first value.
179         * @param b the second value.
180         * @return the worst value. If both values are equal, the first one is returned.
181         * @throws NullPointerException if one of the given arguments is {@code null}
182         */
183        public <C extends Comparable<? super C>> C worst(final C a, final C b) {
184                return compare(b, a) < 0 ? b : a;
185        }
186
187        /**
188         * Return a {@code null}-friendly function which returns the worst element
189         * of two values. E.g.
190         * {@snippet lang="java":
191         * assertNull(Optimize.MAXIMUM.<Integer>worst().apply(null, null));
192         * assertEquals(Optimize.MAXIMUM.<Integer>worst().apply(null, 4), (Integer)4);
193         * assertEquals(Optimize.MAXIMUM.<Integer>worst().apply(6, null), (Integer)6);
194         * }
195         *
196         * @see #worst(Comparable, Comparable)
197         *
198         * @since 6.2
199         *
200         * @param <C> the comparable argument type
201         * @return a {@code null}-friendly method which returns the worst element of
202         *             two values
203         */
204        public <C extends Comparable<? super C>> BinaryOperator<C> worst() {
205                return (a, b) -> switch (cmp(a, b)) {
206                        case 2 -> worst(a, b);
207                        case -1 -> b;
208                        default -> a;
209                };
210        }
211
212        private static <T extends Comparable<? super T>>
213        int cmp(final T a, final T b) {
214                if (a != null) {
215                        if (b != null) {
216                                return 2;
217                        } else {
218                                return 1;
219                        }
220                } else {
221                        if (b != null) {
222                                return -1;
223                        } else {
224                                return 0;
225                        }
226                }
227        }
228
229}