001/* 002 * Java Genetic Algorithm Library (jenetics-7.2.0). 003 * Copyright (c) 2007-2023 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.engine; 021 022import static java.util.Objects.requireNonNull; 023 024import java.util.function.Function; 025 026import io.jenetics.Gene; 027 028/** 029 * The evolution interceptor allows updating the {@link EvolutionStart} object, 030 * <em>before</em> the evolution start, and update the {@link EvolutionResult} 031 * object <em>after</em> the evolution. 032 * 033 * @see EvolutionResult#toUniquePopulation() 034 * @see Engine.Builder#interceptor(EvolutionInterceptor) 035 * 036 * @param <G> the gene type 037 * @param <C> the fitness result type 038 * 039 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 040 * @since 6.0 041 * @version 6.0 042 */ 043public interface EvolutionInterceptor< 044 G extends Gene<?, G>, 045 C extends Comparable<? super C> 046> { 047 048 /** 049 * This method is called right before the evaluation of a generation is 050 * started. 051 * 052 * @param start the evolution start object 053 * @return the possible <em>update</em> evolution start object 054 * @throws NullPointerException if the evolution {@code start} object is 055 * {@code null} 056 */ 057 default EvolutionStart<G, C> before(final EvolutionStart<G, C> start) { 058 return start; 059 } 060 061 /** 062 * This method is called after the evaluation of a generation. If this 063 * method alters the evolution result object, the population within this 064 * result object is re-evaluated. 065 * 066 * @param result the evolution result object to update 067 * @return the possible <em>updated</em> evolution result object 068 * @throws NullPointerException if the evolution {@code result} object is 069 * {@code null} 070 */ 071 default EvolutionResult<G, C> after(final EvolutionResult<G, C> result) { 072 return result; 073 } 074 075 /** 076 * Composes {@code this} interceptor with the {@code other} one. The 077 * {@link #before(EvolutionStart)} of {@code this} interceptor is called 078 * <em>after</em> the {@code before} method of the {@code other} interceptor. 079 * And the {@link #after(EvolutionResult)} of {@code this} interceptor is 080 * called <em>before</em> the {@code after} method of the {@code other} 081 * interceptor. 082 * 083 * @param other the other, composing interceptor 084 * @return a new, composed interceptor 085 * @throws NullPointerException if the {@code other} interceptor is 086 * {@code null} 087 */ 088 default EvolutionInterceptor<G, C> 089 compose(final EvolutionInterceptor<G, C> other) { 090 requireNonNull(other); 091 return EvolutionInterceptor.of( 092 start -> before(other.before(start)), 093 result -> other.after(after(result)) 094 ); 095 } 096 097 /** 098 * Create a new interceptor instance with the given {@code before} and 099 * {@code after} functions. 100 * 101 * @param before the function executed before each evolution step 102 * @param after the function executed after each evolution step 103 * @param <G> the gene type 104 * @param <C> the fitness result type 105 * @return a new interceptor instance with the given interceptor functions 106 * @throws NullPointerException if one of the functions is {@code null} 107 */ 108 static <G extends Gene<?, G>, C extends Comparable<? super C>> 109 EvolutionInterceptor<G, C> of( 110 final Function<? super EvolutionStart<G, C>, EvolutionStart<G, C>> before, 111 final Function<? super EvolutionResult<G, C>, EvolutionResult<G, C>> after 112 ) { 113 requireNonNull(before); 114 requireNonNull(after); 115 116 return new EvolutionInterceptor<>() { 117 @Override 118 public EvolutionStart<G, C> before(final EvolutionStart<G, C> start) { 119 return before.apply(start); 120 } 121 122 @Override 123 public EvolutionResult<G, C> after(final EvolutionResult<G, C> result) { 124 return after.apply(result); 125 } 126 }; 127 } 128 129 /** 130 * Create a new interceptor instance with the given {@code before} function. 131 * 132 * @param before the function executed before each evolution step 133 * @param <G> the gene type 134 * @param <C> the fitness result type 135 * @return a new interceptor instance with the given interceptor function 136 * @throws NullPointerException if the function is {@code null} 137 */ 138 static <G extends Gene<?, G>, C extends Comparable<? super C>> 139 EvolutionInterceptor<G, C> 140 ofBefore(final Function<? super EvolutionStart<G, C>, EvolutionStart<G, C>> before) { 141 return EvolutionInterceptor.of(before, Function.identity()); 142 } 143 144 /** 145 * Create a new interceptor instance with the given {@code after} function. 146 * 147 * @param after the function executed after each evolution step 148 * @param <G> the gene type 149 * @param <C> the fitness result type 150 * @return a new interceptor instance with the given interceptor function 151 * @throws NullPointerException if the function is {@code null} 152 */ 153 static <G extends Gene<?, G>, C extends Comparable<? super C>> 154 EvolutionInterceptor<G, C> 155 ofAfter(final Function<? super EvolutionResult<G, C>, EvolutionResult<G, C>> after) { 156 return EvolutionInterceptor.of(Function.identity(), after); 157 } 158 159 /** 160 * Return an interceptor object which does nothing. 161 * 162 * @param <G> the gene type 163 * @param <C> the fitness result type 164 * @return a new <em>identity</em> interceptor 165 */ 166 static <G extends Gene<?, G>, C extends Comparable<? super C>> 167 EvolutionInterceptor<G, C> identity() { 168 return EvolutionInterceptor.of(Function.identity(), Function.identity()); 169 } 170 171}