001 /*
002 * Java Genetic Algorithm Library (jenetics-4.2.0).
003 * Copyright (c) 2007-2018 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.xml;
021
022 import static java.lang.String.format;
023 import static java.util.Objects.requireNonNull;
024 import static io.jenetics.xml.stream.Reader.attr;
025 import static io.jenetics.xml.stream.Reader.elem;
026 import static io.jenetics.xml.stream.Reader.elems;
027 import static io.jenetics.xml.stream.Reader.text;
028
029 import java.io.InputStream;
030 import java.util.List;
031 import java.util.function.Function;
032 import java.util.function.IntFunction;
033 import java.util.stream.Stream;
034
035 import javax.xml.stream.XMLStreamException;
036
037 import io.jenetics.BoundedGene;
038 import io.jenetics.Chromosome;
039 import io.jenetics.DoubleGene;
040 import io.jenetics.EnumGene;
041 import io.jenetics.Gene;
042 import io.jenetics.IntegerGene;
043 import io.jenetics.LongGene;
044 import io.jenetics.util.CharSeq;
045 import io.jenetics.util.ISeq;
046 import io.jenetics.util.MSeq;
047
048 import io.jenetics.xml.stream.AutoCloseableXMLStreamReader;
049 import io.jenetics.xml.stream.Reader;
050 import io.jenetics.xml.stream.XML;
051
052 /**
053 * This class contains static fields and methods, for creating chromosome- and
054 * genotype readers for different gene types.
055 *
056 * <pre>{@code
057 * final Reader<Genotype<BitGene> bgr =
058 * Readers.Genotype.reader(Readers.BitChromosome.reader()));
059 *
060 * final Reader<Genotype<IntegerGene>> igr =
061 * Writers.Genotype.reader(Readers.IntegerChromosome.reader()));
062 *
063 * final Reader<Genotype<DoubleGene>> dgr =
064 * Readers.Genotype.reader(Readers.DoubleChromosome.reader()));
065 * }</pre>
066 *
067 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
068 * @version 3.9
069 * @since 3.9
070 */
071 public final class Readers {
072 private Readers() {}
073
074 /**
075 * Bit chromosome reader methods, which reads XML-representations of
076 * bit-chromosomes.
077 * <p>
078 * <b>XML</b>
079 * <pre> {@code
080 * <bit-chromosome length="20" ones-probability="0.5">11100011101011001010</bit-chromosome>
081 * }</pre>
082 * }
083 */
084 public static final class BitChromosome {
085 private BitChromosome() {}
086
087 /**
088 * Return a XML reader for {@link io.jenetics.BitChromosome} objects.
089 *
090 * @return a chromosome reader
091 */
092 public static Reader<io.jenetics.BitChromosome> reader() {
093 return elem(
094 v -> io.jenetics.BitChromosome.of(
095 (String)v[2], (int)v[0], (double)v[1]
096 ),
097 Writers.BitChromosome.ROOT_NAME,
098 attr(Writers.BitChromosome.LENGTH_NAME)
099 .map(Integer::parseInt),
100 attr(Writers.BitChromosome.ONES_PROBABILITY_NAME)
101 .map(Double::parseDouble),
102 text()
103 );
104 }
105
106 /**
107 * Read a new {@link io.jenetics.BitChromosome} from the given input
108 * stream.
109 *
110 * @param in the data source of the bit-chromosome
111 * @return the bit-chromosome read from the input stream
112 * @throws XMLStreamException if reading the chromosome fails
113 * @throws NullPointerException if the given input stream is {@code null}
114 */
115 public static io.jenetics.BitChromosome read(final InputStream in)
116 throws XMLStreamException
117 {
118 try (AutoCloseableXMLStreamReader xml = XML.reader(in)) {
119 xml.next();
120 return reader().read(xml);
121 }
122 }
123 }
124
125 /**
126 * Reader methods for {@link io.jenetics.CharacterChromosome} objects.
127 * <p>
128 * <b>XML format</b>
129 * <pre> {@code
130 * <character-chromosome length="4">
131 * <valid-alleles>ABCDEFGHIJKLMNOPQRSTUVWXYZ<valid-alleles>
132 * <alleles>ASDF</alleles>
133 * </character-chromosome>
134 * }</pre>
135 */
136 public static final class CharacterChromosome {
137 private CharacterChromosome() {}
138
139 /**
140 * Return a XML reader for {@link io.jenetics.CharacterChromosome}
141 * objects.
142 *
143 * @return a chromosome reader
144 */
145 public static Reader<io.jenetics.CharacterChromosome> reader() {
146 return elem(
147 v -> io.jenetics.CharacterChromosome.of(
148 (String)v[2], (CharSeq)v[1]
149 ),
150 Writers.CharacterChromosome.ROOT_NAME,
151 attr(Writers.CharacterChromosome.LENGTH_NAME)
152 .map(Integer::parseInt),
153 elem(Writers.CharacterChromosome.VALID_ALLELES_NAME,
154 text().map(CharSeq::new)),
155 elem(Writers.CharacterChromosome.ALLELES_NAME, text())
156 );
157 }
158
159 /**
160 * Read a new {@link io.jenetics.CharacterChromosome} from the given
161 * input stream.
162 *
163 * @param in the data source of the chromosome
164 * @return the bit-chromosome read from the input stream
165 * @throws XMLStreamException if reading the chromosome fails
166 * @throws NullPointerException if the given input stream is {@code null}
167 */
168 public static io.jenetics.CharacterChromosome read(final InputStream in)
169 throws XMLStreamException
170 {
171 try (AutoCloseableXMLStreamReader xml = XML.reader(in)) {
172 xml.next();
173 return reader().read(xml);
174 }
175 }
176
177 }
178
179 /**
180 * Reader methods for {@link io.jenetics.BoundedChromosome} objects.
181 * <p>
182 * <b>XML format</b>
183 * <pre> {@code
184 * <root-name length="3">
185 * <min>aaa</min>
186 * <max>zzz</max>
187 * <alleles>
188 * <allele>iii</allele>
189 * <allele>fff</allele>
190 * <allele>ggg</allele>
191 * </alleles>
192 * </root-name>
193 * }</pre>
194 */
195 public static final class BoundedChromosome {
196 private BoundedChromosome() {}
197
198 /**
199 * Create a bounded chromosome reader with the given configuration.
200 *
201 * @param name the root element name
202 * @param gene the gene creator
203 * @param genes the gene array creator
204 * @param chromosome the chromosome creator
205 * @param alleleReader the allele reader
206 * @param <A> the allele type
207 * @param <G> the gene type
208 * @param <C> the chromosome type
209 * @return a bounded chromosome reader
210 * @throws NullPointerException if one of the arguments is {@code null}
211 */
212 public static <
213 A extends Comparable<? super A>,
214 G extends BoundedGene<A, G>,
215 C extends io.jenetics.BoundedChromosome<A, G>
216 >
217 Reader<C> reader(
218 final String name,
219 final BoundedGeneCreator<A, G> gene,
220 final IntFunction<G[]> genes,
221 final Function<G[], C> chromosome,
222 final Reader<? extends A> alleleReader
223 ) {
224 return elem(v -> {
225 final int length = (int)v[0];
226 @SuppressWarnings("unchecked")
227 final A min = (A)v[1];
228 @SuppressWarnings("unchecked")
229 final A max = (A)v[2];
230 @SuppressWarnings("unchecked")
231 final List<A> alleles = (List<A>)v[3];
232
233 if (alleles.size() != length) {
234 throw new IllegalArgumentException(format(
235 "Expected %d alleles, but got %d,",
236 length, alleles.size()
237 ));
238 }
239
240 return chromosome.apply(
241 alleles.stream()
242 .map(value -> gene.create(value, min, max))
243 .toArray(genes)
244 );
245 }, name,
246 attr(Writers.BoundedChromosome.LENGTH_NAME).map(Integer::parseInt),
247 elem(Writers.BoundedChromosome.MIN_NAME, alleleReader),
248 elem(Writers.BoundedChromosome.MAX_NAME, alleleReader),
249 elem(Writers.BoundedChromosome.ALLELES_NAME,
250 elems(elem(Writers.BoundedChromosome.ALLELE_NAME, alleleReader))
251 )
252 );
253 }
254
255 }
256
257 /**
258 * Reader methods for {@link io.jenetics.IntegerChromosome} objects.
259 * <p>
260 * <b>XML format</b>
261 * <pre> {@code
262 * <int-chromosome length="3">
263 * <min>-2147483648</min>
264 * <max>2147483647</max>
265 * <alleles>
266 * <allele>-1878762439</allele>
267 * <allele>-957346595</allele>
268 * <allele>-88668137</allele>
269 * </alleles>
270 * </int-chromosome>
271 * }</pre>
272 */
273 public static final class IntegerChromosome {
274 private IntegerChromosome() {}
275
276 /**
277 * Return the default allele reader for the {@code IntegerChromosome}.
278 *
279 * @return the default allele reader
280 */
281 public static Reader<Integer> alleleReader() {
282 return text().map(Integer::parseInt);
283 }
284
285 /**
286 * Return a {@link io.jenetics.IntegerChromosome} reader.
287 *
288 * @return a integer chromosome reader
289 */
290 public static Reader<io.jenetics.IntegerChromosome> reader() {
291 return BoundedChromosome.reader(
292 Writers.IntegerChromosome.ROOT_NAME,
293 IntegerGene::of,
294 IntegerGene[]::new,
295 io.jenetics.IntegerChromosome::of,
296 alleleReader()
297 );
298 }
299
300 /**
301 * Read a new {@link io.jenetics.IntegerChromosome} from the given
302 * input stream.
303 *
304 * @param in the data source of the chromosome
305 * @return a new chromosome
306 * @throws XMLStreamException if reading the chromosome fails
307 * @throws NullPointerException if the given input stream is {@code null}
308 */
309 public static io.jenetics.IntegerChromosome read(final InputStream in)
310 throws XMLStreamException
311 {
312 try (AutoCloseableXMLStreamReader reader = XML.reader(in)) {
313 reader.next();
314 return reader().read(reader);
315 }
316 }
317
318 }
319
320 /**
321 * Reader methods for {@link io.jenetics.LongChromosome} objects.
322 * <p>
323 * <b>XML format</b>
324 * <pre> {@code
325 * <long-chromosome length="3">
326 * <min>-9223372036854775808</min>
327 * <max>9223372036854775807</max>
328 * <alleles>
329 * <allele>-1345217698116542402</allele>
330 * <allele>-7144755673073475303</allele>
331 * <allele>6053786736809578435</allele>
332 * </alleles>
333 * </long-chromosome>
334 * }</pre>
335 */
336 public static final class LongChromosome {
337 private LongChromosome() {}
338
339 /**
340 * Return the default allele reader for the {@code LongChromosome}.
341 *
342 * @return the default allele reader
343 */
344 public static Reader<Long> alleleReader() {
345 return text().map(Long::parseLong);
346 }
347
348 /**
349 * Return a {@link io.jenetics.LongChromosome} reader.
350 *
351 * @return a long chromosome reader
352 */
353 public static Reader<io.jenetics.LongChromosome> reader() {
354 return BoundedChromosome.reader(
355 Writers.LongChromosome.ROOT_NAME,
356 LongGene::of,
357 LongGene[]::new,
358 io.jenetics.LongChromosome::of,
359 alleleReader()
360 );
361 }
362
363 /**
364 * Read a new {@link io.jenetics.LongChromosome} from the given
365 * input stream.
366 *
367 * @param in the data source of the chromosome
368 * @return a new chromosome
369 * @throws XMLStreamException if reading the chromosome fails
370 * @throws NullPointerException if the given input stream is {@code null}
371 */
372 public static io.jenetics.LongChromosome read(final InputStream in)
373 throws XMLStreamException
374 {
375 try (AutoCloseableXMLStreamReader reader = XML.reader(in)) {
376 reader.next();
377 return reader().read(reader);
378 }
379 }
380
381 }
382
383 /**
384 * Reader methods for {@link io.jenetics.DoubleChromosome} objects.
385 * <p>
386 * <b>XML format</b>
387 * <pre> {@code
388 * <double-chromosome length="3">
389 * <min>0.0</min>
390 * <max>1.0</max>
391 * <alleles>
392 * <allele>0.27251556008507416</allele>
393 * <allele>0.003140816229067145</allele>
394 * <allele>0.43947528327497376</allele>
395 * </alleles>
396 * </double-chromosome>
397 * }</pre>
398 */
399 public static final class DoubleChromosome {
400 private DoubleChromosome() {}
401
402 /**
403 * Return the default allele reader for the {@code DoubleChromosome}.
404 *
405 * @return the default allele reader
406 */
407 public static Reader<Double> alleleReader() {
408 return text().map(Double::parseDouble);
409 }
410
411 /**
412 * Return a {@link io.jenetics.DoubleChromosome} reader.
413 *
414 * @return a double chromosome reader
415 */
416 public static Reader<io.jenetics.DoubleChromosome> reader() {
417 return BoundedChromosome.reader(
418 Writers.DoubleChromosome.ROOT_NAME,
419 DoubleGene::of,
420 DoubleGene[]::new,
421 io.jenetics.DoubleChromosome::of,
422 alleleReader()
423 );
424 }
425
426 /**
427 * Read a new {@link io.jenetics.DoubleChromosome} from the given
428 * input stream.
429 *
430 * @param in the data source of the chromosome
431 * @return a new chromosome
432 * @throws XMLStreamException if reading the chromosome fails
433 * @throws NullPointerException if the given input stream is {@code null}
434 */
435 public static io.jenetics.DoubleChromosome read(final InputStream in)
436 throws XMLStreamException
437 {
438 try (AutoCloseableXMLStreamReader reader = XML.reader(in)) {
439 reader.next();
440 return reader().read(reader);
441 }
442 }
443
444 }
445
446 /**
447 * Reader methods for {@link io.jenetics.PermutationChromosome} objects.
448 * <p>
449 * <b>XML format</b>
450 * <pre> {@code
451 * <permutation-chromosome length="5">
452 * <valid-alleles type="java.lang.Integer">
453 * <allele>0</allele>
454 * <allele>1</allele>
455 * <allele>2</allele>
456 * <allele>3</allele>
457 * <allele>4</allele>
458 * </valid-alleles>
459 * <order>2 1 3 5 4</order>
460 * </permutation-chromosome>
461 * }</pre>
462 */
463 public static final class PermutationChromosome {
464 private PermutationChromosome() {}
465
466 /**
467 * Return a reader for permutation chromosomes with the given allele
468 * reader.
469 *
470 * @param alleleReader the allele reader
471 * @param <A> the allele type
472 * @return a permutation chromosome reader
473 * @throws NullPointerException if the given allele reader is
474 * {@code null}
475 */
476 public static <A> Reader<io.jenetics.PermutationChromosome<A>>
477 reader(final Reader<? extends A> alleleReader) {
478 requireNonNull(alleleReader);
479
480 return elem(v -> {
481 final int length = (int)v[0];
482 @SuppressWarnings("unchecked")
483 final ISeq<A> validAlleles = ISeq.of((List<A>)v[1]);
484
485 final int[] order = Stream.of(((String) v[2]).split("\\s"))
486 .mapToInt(Integer::parseInt)
487 .toArray();
488
489 final MSeq<EnumGene<A>> alleles = MSeq.ofLength(length);
490 for (int i = 0; i < length; ++i) {
491 final EnumGene<A> gene = EnumGene.of(order[i], validAlleles);
492 alleles.set(i, gene);
493 }
494
495 return new io.jenetics.PermutationChromosome<A>(alleles.toISeq());
496 },
497 Writers.PermutationChromosome.ROOT_NAME,
498 attr(Writers.PermutationChromosome.LENGTH_NAME).map(Integer::parseInt),
499 elem(Writers.PermutationChromosome.VALID_ALLELES_NAME,
500 elems(elem(Writers.PermutationChromosome.ALLELE_NAME, alleleReader))
501 ),
502 elem(Writers.PermutationChromosome.ORDER_NAME, text())
503 );
504 }
505
506 /**
507 * Reads a new {@link io.jenetics.PermutationChromosome} from the given
508 * input stream.
509 *
510 * @param <A> the allele type
511 * @param in the data source of the chromosome
512 * @param alleleReader the allele reader
513 * @return a new permutation chromosome
514 * @throws XMLStreamException if reading the chromosome fails
515 * @throws NullPointerException if one of the arguments is {@code null}
516 */
517 public static <A> io.jenetics.PermutationChromosome<A>
518 read(final InputStream in, final Reader<? extends A> alleleReader)
519 throws XMLStreamException
520 {
521 requireNonNull(alleleReader);
522 requireNonNull(in);
523
524 try (AutoCloseableXMLStreamReader xml = XML.reader(in)) {
525 xml.next();
526 return PermutationChromosome.<A>reader(alleleReader).read(xml);
527 }
528 }
529
530 }
531
532 /**
533 * Writer methods for {@link io.jenetics.Genotype} objects.
534 * <p>
535 * <b>XML format</b>
536 * <pre> {@code
537 * <genotype length="2" ngenes="5">
538 * <double-chromosome length="3">
539 * <min>0.0</min>
540 * <max>1.0</max>
541 * <alleles>
542 * <allele>0.27251556008507416</allele>
543 * <allele>0.003140816229067145</allele>
544 * <allele>0.43947528327497376</allele>
545 * </alleles>
546 * </double-chromosome>
547 * <double-chromosome length="2">
548 * <min>0.0</min>
549 * <max>1.0</max>
550 * <alleles>
551 * <allele>0.4026521545744768</allele>
552 * <allele>0.36137605952663554</allele>
553 * <alleles>
554 * </double-chromosome>
555 * </genotype>
556 * }</pre>
557 */
558 public static final class Genotype {
559 private Genotype() {}
560
561 /**
562 * Create a genotype reader with he given chromosome reader.
563 *
564 * @param chromosomeReader the underlying chromosome reader
565 * @param <A> the allele type
566 * @param <G> the gene type
567 * @param <C> the chromosome type
568 * @return a genotype reader with he given chromosome reader
569 * @throws NullPointerException if the given {@code chromosomeReader} is
570 * {@code null}
571 */
572 public static <
573 A,
574 G extends Gene<A, G>,
575 C extends Chromosome<G>
576 >
577 Reader<io.jenetics.Genotype<G>>
578 reader(final Reader<? extends C> chromosomeReader) {
579 requireNonNull(chromosomeReader);
580
581 return elem(v -> {
582 @SuppressWarnings("unchecked")
583 final List<C> chromosomes = (List<C>)v[2];
584 final io.jenetics.Genotype<G> genotype =
585 io.jenetics.Genotype.of(chromosomes);
586
587 final int length = (int)v[0];
588 final int ngenes = (int)v[1];
589 if (length != genotype.length()) {
590 throw new IllegalArgumentException(format(
591 "Expected %d chromosome, but read %d.",
592 length, genotype.length()
593 ));
594 }
595 if (ngenes != genotype.geneCount()) {
596 throw new IllegalArgumentException(format(
597 "Expected %d genes, but read %d.",
598 ngenes, genotype.geneCount()
599 ));
600 }
601
602 return genotype;
603 },
604 Writers.Genotype.ROOT_NAME,
605 attr(Writers.Genotype.LENGTH_NAME).map(Integer::parseInt),
606 attr(Writers.Genotype.NGENES_NAME).map(Integer::parseInt),
607 elems(chromosomeReader)
608 );
609 }
610
611 /**
612 * Reads a genotype by using the given chromosome reader.
613 *
614 * @param <A> the allele type
615 * @param <G> the gene type
616 * @param <C> the chromosome type
617 * @param in the input stream to read the genotype from
618 * @param chromosomeReader the used chromosome reader
619 * @return a genotype by using the given chromosome reader
620 * @throws XMLStreamException if reading the genotype fails
621 * @throws NullPointerException if one of the arguments is {@code null}
622 */
623 public static <
624 A,
625 G extends Gene<A, G>,
626 C extends Chromosome<G>
627 >
628 io.jenetics.Genotype<G>
629 read(final InputStream in, final Reader<? extends C> chromosomeReader)
630 throws XMLStreamException
631 {
632 requireNonNull(chromosomeReader);
633 requireNonNull(in);
634
635 try (AutoCloseableXMLStreamReader xml = XML.reader(in)) {
636 xml.next();
637 return reader(chromosomeReader).read(xml);
638 }
639 }
640 }
641
642 /**
643 * This class contains static reader methods for
644 * {@link io.jenetics.Genotype} objects.
645 * <p>
646 * <b>XML format</b>
647 * <pre> {@code
648 * <genotypes length="1">
649 * <genotype length="2" ngenes="5">
650 * <double-chromosome length="3">
651 * <min>0.0</min>
652 * <max>1.0</max>
653 * <alleles>
654 * <allele>0.27251556008507416</allele>
655 * <allele>0.003140816229067145</allele>
656 * <allele>0.43947528327497376</allele>
657 * </alleles>
658 * </double-chromosome>
659 * <double-chromosome length="2">
660 * <min>0.0</min>
661 * <max>1.0</max>
662 * <alleles>
663 * <allele>0.4026521545744768</allele>
664 * <allele>0.36137605952663554</allele>
665 * <alleles>
666 * </double-chromosome>
667 * </genotype>
668 * </genotypes>
669 * }</pre>
670 */
671 public static final class Genotypes {
672 private Genotypes() {}
673
674 /**
675 * Return a genotypes reader using the given chromosome reader.
676 *
677 * @param chromosomeReader the underlying chromosome reader
678 * @param <A> the allele type
679 * @param <G> the gene type
680 * @param <C> the chromosome type
681 * @return a genotypes reader using the given chromosome reader
682 * @throws NullPointerException if the given {@code chromosomeReader} is
683 * {@code null}
684 */
685 @SuppressWarnings("unchecked")
686 public static <
687 A,
688 G extends Gene<A, G>,
689 C extends Chromosome<G>
690 >
691 Reader<List<io.jenetics.Genotype<G>>>
692 reader(final Reader<C> chromosomeReader) {
693 return elem(
694 p -> (List<io.jenetics.Genotype<G>>)p[0],
695 Writers.Genotypes.ROOT_NAME,
696 elems(Genotype.reader(chromosomeReader))
697 );
698 }
699
700 /**
701 * Reads the genotypes by using the given chromosome reader.
702 *
703 * @param <A> the allele type
704 * @param <G> the gene type
705 * @param <C> the chromosome type
706 * @param in the input stream to read the genotype from
707 * @param chromosomeReader the used chromosome reader
708 * @return a genotype by using the given chromosome reader
709 * @throws XMLStreamException if reading the genotype fails
710 * @throws NullPointerException if one of the arguments is {@code null}
711 */
712 public static <
713 A,
714 G extends Gene<A, G>,
715 C extends Chromosome<G>
716 >
717 List<io.jenetics.Genotype<G>>
718 read(final InputStream in, final Reader<? extends C> chromosomeReader)
719 throws XMLStreamException
720 {
721 requireNonNull(chromosomeReader);
722 requireNonNull(in);
723
724 try (AutoCloseableXMLStreamReader xml = XML.reader(in)) {
725 xml.next();
726 return reader(chromosomeReader).read(xml);
727 }
728 }
729
730 }
731
732 /**
733 * Reads the genotypes by using the given chromosome reader.
734 *
735 * @see Genotypes#read(InputStream, Reader)
736 *
737 * @param <A> the allele type
738 * @param <G> the gene type
739 * @param <C> the chromosome type
740 * @param in the input stream to read the genotype from
741 * @param chromosomeReader the used chromosome reader
742 * @return a genotype by using the given chromosome reader
743 * @throws XMLStreamException if reading the genotype fails
744 * @throws NullPointerException if one of the arguments is {@code null}
745 */
746 public static <
747 A,
748 G extends Gene<A, G>,
749 C extends Chromosome<G>
750 >
751 List<io.jenetics.Genotype<G>>
752 read(final InputStream in, final Reader<? extends C> chromosomeReader)
753 throws XMLStreamException
754 {
755 return Genotypes.read(in, chromosomeReader);
756 }
757
758 }
|