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}