001 /*
002 * Java Genetic Algorithm Library (jenetics-8.0.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 */
020 package io.jenetics;
021
022 import java.util.Comparator;
023 import 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 */
033 public 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 }
|