VariableChromosome.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-4.4.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;
021 
022 import static java.lang.String.format;
023 import static java.util.Objects.requireNonNull;
024 import static io.jenetics.internal.util.Hashes.hash;
025 
026 import java.util.Objects;
027 
028 import io.jenetics.util.ISeq;
029 import io.jenetics.util.IntRange;
030 
031 /**
032  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
033  @version 4.0
034  @since 4.0
035  */
036 abstract class VariableChromosome<G extends Gene<?, G>>
037     extends AbstractChromosome<G>
038 {
039     private static final long serialVersionUID = 1L;
040 
041     private final IntRange _lengthRange;
042 
043     /**
044      * Create a new {@code VariableChromosome} from the given {@code genes}
045      * and the allowed length range of the chromosome.
046      *
047      @param genes the genes that form the chromosome.
048      @param lengthRange the allowed length range of the chromosome
049      @throws NullPointerException if one of the arguments is {@code null}.
050      @throws IllegalArgumentException if the length of the gene sequence is
051      *         empty or doesn't match with the allowed length range.
052      @throws IllegalArgumentException if the minimum or maximum of the range
053      *         is smaller or equal zero
054      @throws IllegalArgumentException if the given range size is zero
055      */
056     protected VariableChromosome(
057         final ISeq<? extends G> genes,
058         final IntRange lengthRange
059     ) {
060         super(genes);
061         _lengthRange = checkLengthRange(lengthRange, genes.size());
062     }
063 
064     static IntRange checkLengthRange(final IntRange lengthRange, final int length) {
065         requireNonNull(lengthRange);
066         if (lengthRange.getMin() <= 0) {
067             throw new IllegalArgumentException(format(
068                 "Minimum length must be positive: %d", lengthRange.getMin()
069             ));
070         }
071         if (lengthRange.getMax() <= 0) {
072             throw new IllegalArgumentException(format(
073                 "Maximum length must be positive: %d", lengthRange.getMin()
074             ));
075         }
076         if (lengthRange.size() <= 0) {
077             throw new IllegalArgumentException(format(
078                 "Maximal length must be positive: %d", lengthRange.size()
079             ));
080         }
081         if (length < lengthRange.getMin() ||
082             length >= lengthRange.getMax())
083         {
084             throw new IllegalArgumentException(format(
085                 "Number of genes (%d) not within the allowed range: %s",
086                 length,
087                 lengthRange
088             ));
089         }
090 
091         return lengthRange;
092     }
093 
094     /**
095      * Return the allowed length range of the chromosome. The minimum value of
096      * the range is included and the maximum value is excluded.
097      *
098      @return the allowed length range of the chromosome
099      */
100     public IntRange lengthRange() {
101         return _lengthRange;
102     }
103 
104     @Override
105     public int hashCode() {
106         return hash(super.hashCode(), hash(_lengthRange));
107     }
108 
109     @Override
110     public boolean equals(final Object obj) {
111         return obj == this ||
112             obj != null &&
113             getClass() == obj.getClass() &&
114             Objects.equals(_lengthRange, ((VariableChromosome)obj)._lengthRange&&
115             super.equals(obj);
116     }
117 
118 }