RetryConstraint.java
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     extends Gene<?, G>,
045     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 }