IntegerGene.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-3.4.0).
003  * Copyright (c) 2007-2016 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@gmx.at)
019  */
020 package org.jenetics;
021 
022 import static org.jenetics.internal.math.random.nextInt;
023 import static org.jenetics.util.RandomRegistry.getRandom;
024 
025 import java.io.Serializable;
026 import java.util.Random;
027 
028 import javax.xml.bind.annotation.XmlAccessType;
029 import javax.xml.bind.annotation.XmlAccessorType;
030 import javax.xml.bind.annotation.XmlAttribute;
031 import javax.xml.bind.annotation.XmlRootElement;
032 import javax.xml.bind.annotation.XmlType;
033 import javax.xml.bind.annotation.XmlValue;
034 import javax.xml.bind.annotation.adapters.XmlAdapter;
035 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
036 
037 import org.jenetics.util.ISeq;
038 import org.jenetics.util.IntRange;
039 import org.jenetics.util.MSeq;
040 import org.jenetics.util.Mean;
041 
042 /**
043  * NumericGene implementation which holds a 32 bit integer number.
044  *
045  <p>This is a <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/doc-files/ValueBased.html">
046  * value-based</a> class; use of identity-sensitive operations (including
047  * reference equality ({@code ==}), identity hash code, or synchronization) on
048  * instances of {@code IntegerGene} may have unpredictable results and should
049  * be avoided.
050  *
051  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
052  @since 2.0
053  @version 3.2
054  */
055 @XmlJavaTypeAdapter(IntegerGene.Model.Adapter.class)
056 public final class IntegerGene
057     extends AbstractNumericGene<Integer, IntegerGene>
058     implements
059         NumericGene<Integer, IntegerGene>,
060         Mean<IntegerGene>,
061         Comparable<IntegerGene>,
062         Serializable
063 {
064 
065     private static final long serialVersionUID = 1L;
066 
067     /**
068      * Create a new random {@code IntegerGene} with the given value and the
069      * given range. If the {@code value} isn't within the interval [min, max],
070      * no exception is thrown. In this case the method
071      {@link IntegerGene#isValid()} returns {@code false}.
072      *
073      @param value the value of the gene.
074      @param min the minimal valid value of this gene (inclusively).
075      @param max the maximal valid value of this gene (inclusively).
076      @throws NullPointerException if one of the arguments is {@code null}.
077      */
078     IntegerGene(final Integer value, final Integer min, final Integer max) {
079         super(value, min, max);
080     }
081 
082     @Override
083     public int compareTo(final IntegerGene other) {
084         return _value.compareTo(other._value);
085     }
086 
087     /**
088      * Create a new random {@code IntegerGene} with the given value and the
089      * given range. If the {@code value} isn't within the interval [min, max],
090      * no exception is thrown. In this case the method
091      {@link IntegerGene#isValid()} returns {@code false}.
092      *
093      @param value the value of the gene.
094      @param min the minimal valid value of this gene (inclusively).
095      @param max the maximal valid value of this gene (inclusively).
096      @return a new random {@code IntegerGene}
097      */
098     public static IntegerGene of(final int value, final int min, final int max) {
099         return new IntegerGene(value, min, max);
100     }
101 
102     /**
103      * Create a new random {@code IntegerGene} with the given value and the
104      * given range. If the {@code value} isn't within the interval [min, max],
105      * no exception is thrown. In this case the method
106      {@link IntegerGene#isValid()} returns {@code false}.
107      *
108      @since 3.2
109      *
110      @param value the value of the gene.
111      @param range the integer range to use
112      @return a new random {@code IntegerGene}
113      @throws NullPointerException if the given {@code range} is {@code null}.
114      */
115     public static IntegerGene of(final int value, final IntRange range) {
116         return new IntegerGene(value, range.getMin(), range.getMax());
117     }
118 
119     /**
120      * Create a new random {@code IntegerGene}. It is guaranteed that the value of
121      * the {@code IntegerGene} lies in the interval [min, max].
122      *
123      @param min the minimal valid value of this gene (inclusively).
124      @param max the maximal valid value of this gene (inclusively).
125      @return a new random {@code IntegerGene}
126      */
127     public static IntegerGene of(final int min, final int max) {
128         return of(nextInt(getRandom(), min, max), min, max);
129     }
130 
131     /**
132      * Create a new random {@code IntegerGene}. It is guaranteed that the value of
133      * the {@code IntegerGene} lies in the interval [min, max].
134      *
135      @since 3.2
136      *
137      @param range the integer range to use
138      @return a new random {@code IntegerGene}
139      @throws NullPointerException if the given {@code range} is {@code null}.
140      */
141     public static IntegerGene of(final IntRange range) {
142         return of(nextInt(getRandom(), range.getMin(), range.getMax()), range);
143     }
144 
145     static ISeq<IntegerGene> seq(
146         final Integer minimum,
147         final Integer maximum,
148         final int length
149     ) {
150         final int min = minimum;
151         final int max = maximum;
152         final Random r = getRandom();
153 
154         return MSeq.<IntegerGene>ofLength(length)
155             .fill(() -> new IntegerGene(nextInt(r, min, max), minimum, maximum))
156             .toISeq();
157     }
158 
159     @Override
160     public IntegerGene newInstance(final Number number) {
161         return new IntegerGene(number.intValue(), _min, _max);
162     }
163 
164     @Override
165     public IntegerGene newInstance() {
166         return new IntegerGene(
167             nextInt(getRandom(), _min, _max), _min, _max
168         );
169     }
170 
171     @Override
172     public IntegerGene mean(final IntegerGene that) {
173         return new IntegerGene(_value + (that._value - _value)/2, _min, _max);
174     }
175 
176     /* *************************************************************************
177      *  JAXB object serialization
178      * ************************************************************************/
179 
180     @XmlRootElement(name = "int-gene")
181     @XmlType(name = "org.jenetics.IntegerGene")
182     @XmlAccessorType(XmlAccessType.FIELD)
183     final static class Model {
184 
185         @XmlAttribute(name = "min", required = true)
186         public int min;
187 
188         @XmlAttribute(name = "max", required = true)
189         public int max;
190 
191         @XmlValue
192         public int value;
193 
194         public final static class Adapter
195             extends XmlAdapter<Model, IntegerGene>
196         {
197             @Override
198             public Model marshal(final IntegerGene value) {
199                 final Model m = new Model();
200                 m.min = value.getMin();
201                 m.max = value.getMax();
202                 m.value = value.getAllele();
203                 return m;
204             }
205 
206             @Override
207             public IntegerGene unmarshal(final Model m) {
208                 return IntegerGene.of(m.value, m.min, m.max);
209             }
210         }
211     }
212 
213 }