Optimize.java
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? 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 -> best(a, b);
168             case --> 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? 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 -> worst(a, b);
209             case --> 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 }