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