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