001 /*
002 * Java Genetic Algorithm Library (jenetics-5.1.0).
003 * Copyright (c) 2007-2019 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.engine;
021
022 import static java.util.Objects.requireNonNull;
023
024 import java.util.function.Predicate;
025
026 import io.jenetics.Gene;
027 import io.jenetics.Genotype;
028 import io.jenetics.Phenotype;
029 import io.jenetics.util.Factory;
030
031 /**
032 * This simple {@code Constraint} implementation <em>repairs</em> an invalid
033 * phenotype by creating new individuals until a valid one has been created.
034 *
035 * @apiNote
036 * This class is part of the more advanced API and is not needed for default use
037 * cases.
038 *
039 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
040 * @version 5.0
041 * @since 5.0
042 */
043 public final class RetryConstraint<
044 G extends Gene<?, G>,
045 C extends Comparable<? super C>
046 >
047 implements Constraint<G, C>
048 {
049
050 /**
051 * The default retry-count for creating new, valid phenotypes.
052 */
053 public static final int DEFAULT_RETRY_COUNT = 10;
054
055 private final Predicate<? super Phenotype<G, C>> _validator;
056 private final Factory<Genotype<G>> _genotypeFactory;
057 private final int _retryLimit;
058
059 /**
060 * Create a new retry-constraint with the given parameters.
061 *
062 * @param validator the phenotype validator
063 * @param genotypeFactory the genotype factory used for creating new
064 * phenotypes. The genotype factory may be {@code null}. In this case,
065 * the phenotype to be repaired is used as template.
066 * @param retryLimit the limit of the phenotype creation retries. If more
067 * re-creation tries are necessary, an invalid phenotype is returned.
068 * This limit guarantees the termination of the
069 * {@link #repair(Phenotype,long)} method.
070 * @throws NullPointerException if the {@code validator} is {@code null}
071 */
072 public RetryConstraint(
073 final Predicate<? super Phenotype<G, C>> validator,
074 final Factory<Genotype<G>> genotypeFactory,
075 final int retryLimit
076 ) {
077 _validator = requireNonNull(validator);
078 _genotypeFactory = genotypeFactory;
079 _retryLimit = retryLimit;
080 }
081
082 @Override
083 public boolean test(final Phenotype<G, C> individual) {
084 return _validator.test(individual);
085 }
086
087 @Override
088 public Phenotype<G, C> repair(
089 final Phenotype<G, C> individual,
090 final long generation
091 ) {
092 final Factory<Genotype<G>> gtf = _genotypeFactory != null
093 ? _genotypeFactory
094 : individual.getGenotype();
095
096 int count = 0;
097 Phenotype<G, C> phenotype;
098 do {
099 phenotype = Phenotype.of(gtf.newInstance(), generation);
100 } while (++count < _retryLimit && !test(phenotype));
101
102 return phenotype;
103 }
104
105 /**
106 * Return a new constraint with the given genotype factory. The phenotype
107 * validator is set to {@link Phenotype#isValid()} and the retry count to
108 * {@link #DEFAULT_RETRY_COUNT}.
109 *
110 * @param genotypeFactory the genotype factory used for creating new
111 * phenotypes
112 * @param <G> the gene type
113 * @param <C> the fitness value type
114 * @return a new constraint strategy
115 */
116 public static <G extends Gene<?, G>, C extends Comparable<? super C>>
117 RetryConstraint<G, C> of(final Factory<Genotype<G>> genotypeFactory) {
118 return new RetryConstraint<>(
119 Phenotype::isValid,
120 genotypeFactory,
121 DEFAULT_RETRY_COUNT
122 );
123 }
124
125 /**
126 * Return a new constraint with the given {@code validator} and the
127 * {@link #DEFAULT_RETRY_COUNT}.
128 *
129 * @param validator the phenotype validator
130 * @param <G> the gene type
131 * @param <C> the fitness value type
132 * @return a new constraint strategy
133 */
134 public static <G extends Gene<?, G>, C extends Comparable<? super C>>
135 RetryConstraint<G, C> of(final Predicate<? super Phenotype<G, C>> validator) {
136 return new RetryConstraint<>(
137 validator,
138 null,
139 DEFAULT_RETRY_COUNT
140 );
141 }
142
143 /**
144 * Return a new constraint with the given {@code validator} and
145 * {@code retryLimit}.
146 *
147 * @param validator the phenotype validator
148 * @param retryLimit the limit of the phenotype creation retries. If more
149 * re-creation tries are necessary, an invalid phenotype is returned.
150 * This limit guarantees the termination of the
151 * {@link #repair(Phenotype, long)} method.
152 * @param <G> the gene type
153 * @param <C> the fitness value type
154 * @return a new constraint strategy
155 */
156 public static <G extends Gene<?, G>, C extends Comparable<? super C>>
157 RetryConstraint<G, C> of(
158 final Predicate<? super Phenotype<G, C>> validator,
159 final int retryLimit
160 ) {
161 return new RetryConstraint<>(
162 validator,
163 null,
164 retryLimit
165 );
166 }
167
168 }
|