IntegerChromosome.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-3.7.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 java.io.IOException;
023 import java.io.ObjectInputStream;
024 import java.io.ObjectOutputStream;
025 import java.io.Serializable;
026 import java.util.List;
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.XmlElement;
032 import javax.xml.bind.annotation.XmlRootElement;
033 import javax.xml.bind.annotation.XmlType;
034 import javax.xml.bind.annotation.adapters.XmlAdapter;
035 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
036 
037 import org.jenetics.internal.util.Equality;
038 import org.jenetics.internal.util.Hash;
039 
040 import org.jenetics.util.ISeq;
041 import org.jenetics.util.IntRange;
042 import org.jenetics.util.MSeq;
043 
044 /**
045  * Numeric chromosome implementation which holds 32 bit integer numbers.
046  *
047  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz  Wilhelmstötter</a>
048  @since 2.0
049  @version 3.2
050  */
051 @XmlJavaTypeAdapter(IntegerChromosome.Model.Adapter.class)
052 public class IntegerChromosome
053     extends AbstractBoundedChromosome<Integer, IntegerGene>
054     implements
055             NumericChromosome<Integer, IntegerGene>,
056             Serializable
057 {
058     private static final long serialVersionUID = 1L;
059 
060     /**
061      * Create a new chromosome from the given genes array.
062      *
063      @param genes the genes of the new chromosome.
064      @throws IllegalArgumentException if the gene sequence is empty
065      @throws NullPointerException if the {@code genes} are {@code null}.
066      */
067     protected IntegerChromosome(final ISeq<IntegerGene> genes) {
068         super(genes);
069     }
070 
071     /**
072      * Create a new random {@code IntegerChromosome}.
073      *
074      @param min the min value of the {@link IntegerGene}s (inclusively).
075      @param max the max value of the {@link IntegerGene}s (inclusively).
076      @param length the length of the chromosome.
077      @throws NullPointerException if one of the arguments is {@code null}.
078      @throws IllegalArgumentException if the {@code length} is smaller than
079      *         one.
080      */
081     public IntegerChromosome(
082         final Integer min,
083         final Integer max,
084         final int length
085     ) {
086         this(IntegerGene.seq(min, max, length));
087         _valid = true;
088     }
089 
090     /**
091      * Create a new random {@code IntegerChromosome} of length one.
092      *
093      @param min the minimal value of this chromosome (inclusively).
094      @param max the maximal value of this chromosome (inclusively).
095      @throws NullPointerException if one of the arguments is {@code null}.
096      */
097     public IntegerChromosome(final Integer min, final Integer max) {
098         this(min, max, 1);
099     }
100 
101     /**
102      * Returns an int array containing all of the elements in this chromosome
103      * in proper sequence.  If the chromosome fits in the specified array, it is
104      * returned therein. Otherwise, a new array is allocated with the length of
105      * this chromosome.
106      *
107      @since 3.0
108      *
109      @param array the array into which the elements of this chromosomes are to
110      *        be stored, if it is big enough; otherwise, a new array is
111      *        allocated for this purpose.
112      @return an array containing the elements of this chromosome
113      @throws NullPointerException if the given {@code array} is {@code null}
114      */
115     public int[] toArray(final int[] array) {
116         final int[] a = array.length >= length() ?
117             array : new int[length()];
118 
119         for (int i = length(); --i >= 0;) {
120             a[i= intValue(i);
121         }
122 
123         return a;
124     }
125 
126     /**
127      * Returns an int array containing all of the elements in this chromosome
128      * in proper sequence.
129      *
130      @since 3.0
131      *
132      @return an array containing the elements of this chromosome
133      */
134     public int[] toArray() {
135         return toArray(new int[length()]);
136     }
137 
138     /**
139      * Create a new {@code IntegerChromosome} with the given genes.
140      *
141      @param genes the genes of the chromosome.
142      @return a new chromosome with the given genes.
143      @throws IllegalArgumentException if the length of the genes array is
144      *         empty.
145      */
146     public static IntegerChromosome of(final IntegerGene... genes) {
147         return new IntegerChromosome(ISeq.of(genes));
148     }
149 
150     /**
151      * Create a new random {@code IntegerChromosome}.
152      *
153      @param min the min value of the {@link IntegerGene}s (inclusively).
154      @param max the max value of the {@link IntegerGene}s (inclusively).
155      @param length the length of the chromosome.
156      @return a new random {@code IntegerChromosome}
157      @throws IllegalArgumentException if the length is smaller than one
158      */
159     public static IntegerChromosome of(
160         final int min,
161         final int max,
162         final int length
163     ) {
164         return new IntegerChromosome(min, max, length);
165     }
166 
167     /**
168      * Create a new random {@code IntegerChromosome}.
169      *
170      @since 3.2
171      *
172      @param range the integer range of the chromosome.
173      @param length the length of the chromosome.
174      @return a new random {@code IntegerChromosome}
175      @throws NullPointerException if the given {@code range} is {@code null}
176      @throws IllegalArgumentException if the length is smaller than one
177      */
178     public static IntegerChromosome of(final IntRange range, final int length) {
179         return new IntegerChromosome(range.getMin(), range.getMax(), length);
180     }
181 
182     /**
183      * Create a new random {@code IntegerChromosome} of length one.
184      *
185      @param min the minimal value of this chromosome (inclusively).
186      @param max the maximal value of this chromosome (inclusively).
187      @return a new random {@code IntegerChromosome} of length one
188      */
189     public static IntegerChromosome of(final int min, final int max) {
190         return new IntegerChromosome(min, max);
191     }
192 
193     /**
194      * Create a new random {@code IntegerChromosome} of length one.
195      *
196      @since 3.2
197      *
198      @param range the integer range of the chromosome.
199      @return a new random {@code IntegerChromosome} of length one
200      @throws NullPointerException if the given {@code range} is {@code null}
201      */
202     public static IntegerChromosome of(final IntRange range) {
203         return new IntegerChromosome(range.getMin(), range.getMax());
204     }
205 
206     @Override
207     public IntegerChromosome newInstance(final ISeq<IntegerGene> genes) {
208         return new IntegerChromosome(genes);
209     }
210 
211     @Override
212     public IntegerChromosome newInstance() {
213         return new IntegerChromosome(_min, _max, length());
214     }
215 
216     @Override
217     public int hashCode() {
218         return Hash.of(getClass()).and(super.hashCode()).value();
219     }
220 
221     @Override
222     public boolean equals(final Object obj) {
223         return Equality.of(this, obj).test(super::equals);
224     }
225 
226     /* *************************************************************************
227      *  Java object serialization
228      * ************************************************************************/
229 
230     private void writeObject(final ObjectOutputStream out)
231         throws IOException
232     {
233         out.defaultWriteObject();
234 
235         out.writeInt(length());
236         out.writeInt(_min);
237         out.writeInt(_max);
238 
239         for (IntegerGene gene : _genes) {
240             out.writeInt(gene.getAllele());
241         }
242     }
243 
244     private void readObject(final ObjectInputStream in)
245         throws IOException, ClassNotFoundException
246     {
247         in.defaultReadObject();
248 
249         final MSeq<IntegerGene> genes = MSeq.ofLength(in.readInt());
250         _min = in.readInt();
251         _max = in.readInt();
252 
253         for (int i = 0; i < genes.length(); ++i) {
254             genes.set(i, new IntegerGene(in.readInt(), _min, _max));
255         }
256 
257         _genes = genes.toISeq();
258     }
259 
260     /* *************************************************************************
261      *  JAXB object serialization
262      * ************************************************************************/
263 
264     @XmlRootElement(name = "int-chromosome")
265     @XmlType(name = "org.jenetics.IntegerChromosome")
266     @XmlAccessorType(XmlAccessType.FIELD)
267     final static class Model {
268 
269         @XmlAttribute(name = "length", required = true)
270         public int length;
271 
272         @XmlAttribute(name = "min", required = true)
273         public int min;
274 
275         @XmlAttribute(name = "max", required = true)
276         public int max;
277 
278         @XmlElement(name = "allele", required = true, nillable = false)
279         public List<Integer> values;
280 
281         public final static class Adapter
282             extends XmlAdapter<Model, IntegerChromosome>
283         {
284             @Override
285             public Model marshal(final IntegerChromosome c) {
286                 final Model m = new Model();
287                 m.length = c.length();
288                 m.min = c._min;
289                 m.max = c._max;
290                 m.values = c.toSeq().map(IntegerGene::getAllele).asList();
291                 return m;
292             }
293 
294             @Override
295             public IntegerChromosome unmarshal(final Model model) {
296                 final Integer min = model.min;
297                 final Integer max = model.max;
298                 return new IntegerChromosome(
299                     ISeq.of(model.values)
300                         .map(a -> new IntegerGene(a, min, max))
301                 );
302             }
303         }
304 
305     }
306 }