001 /*
002 * Java Genetic Algorithm Library (jenetics-6.2.0).
003 * Copyright (c) 2007-2021 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 *
064 * <pre>{@code
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 * }</pre>
070 * or
071 * <pre>{@code
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 * }</pre>
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 *
094 * <pre>{@code
095 * final Population<DoubleGene, Double> population = ...
096 * population.sort(Optimize.MINIMUM.<Double>descending());
097 * }</pre>
098 *
099 * The code example above will populationSort the population according it's fitness
100 * values in ascending order, since lower values are <i>better</i> in this
101 * 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 *
116 * <pre>{@code
117 * final Population<DoubleGene, Double> population = ...
118 * population.sort(Optimize.MINIMUM.<Double>ascending());
119 * }</pre>
120 *
121 * The code example above will populationSort the population according it's fitness
122 * values in descending order, since lower values are <i>better</i> in this
123 * 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 * <pre>{@code
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 * }</pre>
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) -> {
167 switch (cmp(a, b)) {
168 case 2: return best(a, b);
169 case -1: return b;
170 default: return a;
171 }
172 };
173 }
174
175 /**
176 * Return the worst value, according to this optimization direction.
177 *
178 * @see #worst()
179 *
180 * @param <C> the fitness value type.
181 * @param a the first value.
182 * @param b the second value.
183 * @return the worst value. If both values are equal the first one is returned.
184 * @throws NullPointerException if one of the given arguments is {@code null}
185 */
186 public <C extends Comparable<? super C>> C worst(final C a, final C b) {
187 return compare(b, a) < 0 ? b : a;
188 }
189
190 /**
191 * Return a {@code null}-friendly function which returns the worst element
192 * of two values. E.g.
193 *
194 * <pre>{@code
195 * assertNull(Optimize.MAXIMUM.<Integer>worst().apply(null, null));
196 * assertEquals(Optimize.MAXIMUM.<Integer>worst().apply(null, 4), (Integer)4);
197 * assertEquals(Optimize.MAXIMUM.<Integer>worst().apply(6, null), (Integer)6);
198 * }</pre>
199 *
200 * @see #worst(Comparable, Comparable)
201 *
202 * @since 6.2
203 *
204 * @param <C> the comparable argument type
205 * @return a {@code null}-friendly method which returns the worst element of
206 * two values
207 */
208 public <C extends Comparable<? super C>> BinaryOperator<C> worst() {
209 return (a, b) -> {
210 switch (cmp(a, b)) {
211 case 2: return worst(a, b);
212 case -1: return b;
213 default: return a;
214 }
215 };
216 }
217
218 private static <T extends Comparable<? super T>>
219 int cmp(final T a, final T b) {
220 if (a != null) {
221 if (b != null) {
222 return 2;
223 } else {
224 return 1;
225 }
226 } else {
227 if (b != null) {
228 return -1;
229 } else {
230 return 0;
231 }
232 }
233 }
234
235 }
|