001/* 002 * Java Genetic Algorithm Library (jenetics-7.1.0). 003 * Copyright (c) 2007-2022 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 */ 020package io.jenetics.xml; 021 022import static java.util.Objects.requireNonNull; 023import static io.jenetics.xml.stream.Writer.attr; 024import static io.jenetics.xml.stream.Writer.elem; 025import static io.jenetics.xml.stream.Writer.elems; 026import static io.jenetics.xml.stream.Writer.text; 027 028import java.io.OutputStream; 029import java.util.Collection; 030import java.util.stream.Collectors; 031 032import javax.xml.stream.XMLStreamException; 033 034import io.jenetics.BoundedGene; 035import io.jenetics.Chromosome; 036import io.jenetics.DoubleGene; 037import io.jenetics.Gene; 038import io.jenetics.IntegerGene; 039import io.jenetics.LongGene; 040import io.jenetics.util.ISeq; 041import io.jenetics.xml.stream.Writer; 042import io.jenetics.xml.stream.XML; 043 044/** 045 * This class contains static fields and methods, for creating chromosome- and 046 * genotype writers for different gene types. 047 * 048 * <pre>{@code 049 * final Writer<Genotype<BitGene> bgw = 050 * Writers.Genotype.writer(Writers.BitChromosome.writer())); 051 * 052 * final Writer<Genotype<IntegerGene>> igw = 053 * Writers.Genotype.writer(Writers.IntegerChromosome.writer())); 054 * 055 * final Writer<Genotype<DoubleGene>> dgw = 056 * Writers.Genotype.writer(Writers.DoubleChromosome.writer())); 057 * }</pre> 058 * 059 * This class also contains some helper methods, which makes it easier to write 060 * Jenetics domain objects to a given output stream. 061 * <pre>{@code 062 * final List<Genotype<BitGene>> genotypes = ...; 063 * try (OutputStream out = Files.newOutputStream(Paths.get("path"))) { 064 * Writers.write(out, genotypes, Writers.BitChromosome.writer()); 065 * } 066 * }</pre> 067 * 068 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 069 * @version 3.9 070 * @since 3.9 071 */ 072public final class Writers { 073 private Writers() {} 074 075 /** 076 * This class contains static writer methods for 077 * {@link io.jenetics.BitChromosome} objects. 078 * <p> 079 * <b>Writer code</b> 080 * <pre>{@code 081 * final BitChromosome value = BitChromosome.of(20, 0.5); 082 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) { 083 * Writers.BitChromosome.writer().write(value, xml); 084 * } 085 * }</pre> 086 * 087 * <b>XML output</b> 088 * <pre> {@code 089 * <bit-chromosome length="20" ones-probability="0.5">11100011101011001010</bit-chromosome> 090 * }</pre> 091 * 092 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 093 * @version 3.9 094 * @since 3.9 095 */ 096 public static final class BitChromosome { 097 private BitChromosome() {} 098 099 static final String ROOT_NAME = "bit-chromosome"; 100 static final String LENGTH_NAME = "length"; 101 static final String ONES_PROBABILITY_NAME = "ones-probability"; 102 103 /** 104 * Return a {@link Writer} for {@link io.jenetics.BitChromosome} 105 * objects. 106 * 107 * @return a chromosome writer 108 */ 109 public static Writer<io.jenetics.BitChromosome> writer() { 110 return elem(ROOT_NAME, 111 attr(LENGTH_NAME).map(io.jenetics.BitChromosome::length), 112 attr(ONES_PROBABILITY_NAME).map(ch -> ch.oneProbability()), 113 text().map(io.jenetics.BitChromosome::toCanonicalString) 114 ); 115 } 116 117 /** 118 * Write the given {@link io.jenetics.BitChromosome} to the given 119 * output stream. 120 * 121 * @param out the target output stream 122 * @param data the bit-chromosome to write 123 * @throws XMLStreamException if an error occurs while writing the 124 * chromosome 125 * @throws NullPointerException if one of the given arguments is 126 * {@code null} 127 */ 128 public static void write( 129 final OutputStream out, 130 final io.jenetics.BitChromosome data 131 ) 132 throws XMLStreamException 133 { 134 requireNonNull(data); 135 requireNonNull(out); 136 137 try (var xml = XML.writer(out)) { 138 writer().write(xml, data); 139 } 140 } 141 } 142 143 144 /** 145 * This class contains static writer methods for 146 * {@link io.jenetics.CharacterChromosome} objects. 147 * <p> 148 * <b>Writer code</b> 149 * <pre>{@code 150 * final CharacterChromosome value = CharacterChromosome.of("ASDF", CharSeq.of("A-Z")); 151 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) { 152 * Writers.CharacterChromosome.writer().write(value, xml); 153 * } 154 * }</pre> 155 * 156 * <b>XML output</b> 157 * <pre> {@code 158 * <character-chromosome length="4"> 159 * <valid-alleles>ABCDEFGHIJKLMNOPQRSTUVWXYZ<valid-alleles> 160 * <alleles>ASDF</alleles> 161 * </character-chromosome> 162 * }</pre> 163 */ 164 public static final class CharacterChromosome { 165 private CharacterChromosome() {} 166 167 static final String ROOT_NAME = "character-chromosome"; 168 static final String LENGTH_NAME = "length"; 169 static final String VALID_ALLELES_NAME = "valid-alleles"; 170 static final String ALLELES_NAME = "alleles"; 171 172 /** 173 * Return a {@link Writer} for {@link io.jenetics.CharacterChromosome} 174 * objects. 175 * 176 * @return a chromosome writer 177 */ 178 public static Writer<io.jenetics.CharacterChromosome> writer() { 179 return elem(ROOT_NAME, 180 attr(LENGTH_NAME).map(io.jenetics.CharacterChromosome::length), 181 elem(VALID_ALLELES_NAME, 182 text().map(ch -> ch.gene().validChars())), 183 elem(ALLELES_NAME, 184 text().map(io.jenetics.CharacterChromosome::toString)) 185 ); 186 } 187 188 /** 189 * Write the given {@link io.jenetics.CharacterChromosome} to the given 190 * output stream. 191 * 192 * @param out the target output stream 193 * @param data the chromosome to write 194 * @param indent the XML level indentation 195 * @throws XMLStreamException if an error occurs while writing the 196 * chromosome 197 * @throws NullPointerException if the {@code chromosome} or output 198 * stream is {@code null} 199 */ 200 public static void write( 201 final OutputStream out, 202 final io.jenetics.CharacterChromosome data, 203 final String indent 204 ) 205 throws XMLStreamException 206 { 207 requireNonNull(data); 208 requireNonNull(out); 209 210 try (var xml = XML.writer(out, indent)) { 211 writer().write(xml, data); 212 } 213 } 214 215 /** 216 * Write the given {@link io.jenetics.CharacterChromosome} to the given 217 * output stream. 218 * 219 * @param out the target output stream 220 * @param data the chromosome to write 221 * @throws XMLStreamException if an error occurs while writing the 222 * chromosome 223 * @throws NullPointerException if the {@code chromosome} or output 224 * stream is {@code null} 225 */ 226 public static void write( 227 final OutputStream out, 228 final io.jenetics.CharacterChromosome data 229 ) 230 throws XMLStreamException 231 { 232 write(out, data, null); 233 } 234 235 } 236 237 /** 238 * This class contains static writer methods for 239 * {@link io.jenetics.BoundedChromosome} objects. 240 * 241 * <p> 242 * <b>XML template</b> 243 * <pre> {@code 244 * <root-name length="3"> 245 * <min>aaa</min> 246 * <max>zzz</max> 247 * <alleles> 248 * <allele>iii</allele> 249 * <allele>fff</allele> 250 * <allele>ggg</allele> 251 * </alleles> 252 * </root-name> 253 * }</pre> 254 */ 255 public static final class BoundedChromosome { 256 private BoundedChromosome() {} 257 258 static final String LENGTH_NAME = "length"; 259 static final String MIN_NAME = "min"; 260 static final String MAX_NAME = "max"; 261 static final String ALLELE_NAME = "allele"; 262 static final String ALLELES_NAME = "alleles"; 263 264 /** 265 * Create a bounded chromosome writer with the given configuration. 266 * 267 * @param rootName the name of the root element. E.g. {@code int-chromosome} 268 * @param alleleWriter the XML writer used for the alleles 269 * @param <A> the allele type 270 * @param <G> the bounded gene type 271 * @param <C> the bounded chromosome type 272 * @return a bounded chromosome XML writer 273 * @throws NullPointerException if one of the arguments is {@code null} 274 */ 275 public static < 276 A extends Comparable<? super A>, 277 G extends BoundedGene<A, G>, 278 C extends io.jenetics.BoundedChromosome<A, G> 279 > 280 Writer<C> writer( 281 final String rootName, 282 final Writer<? super A> alleleWriter 283 ) { 284 requireNonNull(rootName); 285 requireNonNull(alleleWriter); 286 287 return elem(rootName, 288 attr(LENGTH_NAME).map(ch -> ch.length()), 289 elem(MIN_NAME, alleleWriter.map(ch -> ch.min())), 290 elem(MAX_NAME, alleleWriter.map(ch -> ch.max())), 291 elem(ALLELES_NAME, 292 elems(ALLELE_NAME, alleleWriter) 293 .map(ch -> ISeq.of(ch).map(G::allele)) 294 ) 295 ); 296 } 297 } 298 299 /** 300 * This class contains static writer methods for 301 * {@link io.jenetics.IntegerChromosome} objects. 302 * <p> 303 * <b>Writer code</b> 304 * <pre>{@code 305 * final IntegerChromosome value = IntegerChromosome 306 * .of(Integer.MIN_VALUE, Integer.MAX_VALUE, 3); 307 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) { 308 * Writers.IntegerChromosome.writer().write(value, xml); 309 * } 310 * }</pre> 311 * 312 * <b>XML output</b> 313 * <pre> {@code 314 * <int-chromosome length="3"> 315 * <min>-2147483648</min> 316 * <max>2147483647</max> 317 * <alleles> 318 * <allele>-1878762439</allele> 319 * <allele>-957346595</allele> 320 * <allele>-88668137</allele> 321 * </alleles> 322 * </int-chromosome> 323 * }</pre> 324 */ 325 public static final class IntegerChromosome { 326 private IntegerChromosome() {} 327 328 static final String ROOT_NAME = "int-chromosome"; 329 330 /** 331 * Return the default integer allele writer for the 332 * {@code IntegerChromosome}. 333 * 334 * @return the default integer allele writer 335 */ 336 public static Writer<Integer> alleleWriter() { 337 return text(); 338 } 339 340 /** 341 * Return a {@link Writer} for {@link io.jenetics.IntegerChromosome} 342 * objects. 343 * 344 * @param alleleWriter the allele writer used for writing the integer 345 * allele. Might be useful for using different integer 346 * <i>encodings</i>. 347 * @return a chromosome writer 348 * @throws NullPointerException if the given {@code alleleWriter} is 349 * {@code null} 350 */ 351 public static Writer<io.jenetics.IntegerChromosome> 352 writer(final Writer<? super Integer> alleleWriter) { 353 requireNonNull(alleleWriter); 354 355 return BoundedChromosome.< 356 Integer, 357 IntegerGene, 358 io.jenetics.IntegerChromosome 359 >writer(ROOT_NAME, alleleWriter); 360 } 361 362 /** 363 * Return a {@link Writer} for {@link io.jenetics.IntegerChromosome} 364 * objects. 365 * 366 * @return a chromosome writer 367 */ 368 public static Writer<io.jenetics.IntegerChromosome> writer() { 369 return writer(alleleWriter()); 370 } 371 372 /** 373 * Write the given {@link io.jenetics.IntegerChromosome} to the given 374 * output stream. 375 * 376 * @param out the target output stream 377 * @param data the chromosome to write 378 * @param indent the XML level indentation 379 * @throws XMLStreamException if an error occurs while writing the 380 * chromosome 381 * @throws NullPointerException if the {@code chromosome} or output 382 * stream is {@code null} 383 */ 384 public static void write( 385 final OutputStream out, 386 final io.jenetics.IntegerChromosome data, 387 final String indent 388 ) 389 throws XMLStreamException 390 { 391 requireNonNull(data); 392 requireNonNull(out); 393 394 try (var xml = XML.writer(out, indent)) { 395 writer().write(xml, data); 396 } 397 } 398 399 /** 400 * Write the given {@link io.jenetics.IntegerChromosome} to the given 401 * output stream. 402 * 403 * @param out the target output stream 404 * @param data the chromosome to write 405 * @throws XMLStreamException if an error occurs while writing the 406 * chromosome 407 * @throws NullPointerException if the {@code chromosome} or output 408 * stream is {@code null} 409 */ 410 public static void write( 411 final OutputStream out, 412 final io.jenetics.IntegerChromosome data 413 ) 414 throws XMLStreamException 415 { 416 write(out, data, null); 417 } 418 } 419 420 /** 421 * This class contains static writer methods for 422 * {@link io.jenetics.LongChromosome} objects. 423 * <p> 424 * <b>Writer code</b> 425 * <pre>{@code 426 * final LongChromosome value = LongChromosome 427 * .of(Long.MIN_VALUE, Long.MAX_VALUE, 3); 428 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) { 429 * Writers.LongChromosome.writer().write(value, xml); 430 * } 431 * }</pre> 432 * 433 * <b>XML output</b> 434 * <pre> {@code 435 * <long-chromosome length="3"> 436 * <min>-9223372036854775808</min> 437 * <max>9223372036854775807</max> 438 * <alleles> 439 * <allele>-1345217698116542402</allele> 440 * <allele>-7144755673073475303</allele> 441 * <allele>6053786736809578435</allele> 442 * </alleles> 443 * </long-chromosome> 444 * }</pre> 445 */ 446 public static final class LongChromosome { 447 private LongChromosome() {} 448 449 static final String ROOT_NAME = "long-chromosome"; 450 451 /** 452 * Return the default long allele writer for the 453 * {@code IntegerChromosome}. 454 * 455 * @return the default long allele writer 456 */ 457 public static Writer<Long> alleleWriter() { 458 return Writer.text(); 459 } 460 461 /** 462 * Return a {@link Writer} for {@link io.jenetics.LongChromosome} 463 * objects. 464 * 465 * @param alleleWriter the allele writer used for writing the long 466 * allele. Might be useful for using different long 467 * <i>encodings</i>. 468 * @return a chromosome writer 469 * @throws NullPointerException if the given {@code alleleWriter} is 470 * {@code null} 471 */ 472 public static Writer<io.jenetics.LongChromosome> 473 writer(final Writer<? super Long> alleleWriter) { 474 return BoundedChromosome.< 475 Long, 476 LongGene, 477 io.jenetics.LongChromosome 478 >writer(ROOT_NAME, alleleWriter); 479 } 480 481 /** 482 * Return a {@link Writer} for {@link io.jenetics.LongChromosome} 483 * objects. 484 * 485 * @return a chromosome writer 486 */ 487 public static Writer<io.jenetics.LongChromosome> writer() { 488 return writer(alleleWriter()); 489 } 490 491 /** 492 * Write the given {@link io.jenetics.LongChromosome} to the given 493 * output stream. 494 * 495 * @param out the target output stream 496 * @param data the chromosome to write 497 * @param indent the XML level indentation 498 * @throws XMLStreamException if an error occurs while writing the 499 * chromosome 500 * @throws NullPointerException if the {@code chromosome} or output 501 * stream is {@code null} 502 */ 503 public static void write( 504 final OutputStream out, 505 final io.jenetics.LongChromosome data, 506 final String indent 507 ) 508 throws XMLStreamException 509 { 510 requireNonNull(data); 511 requireNonNull(out); 512 513 try (var xml = XML.writer(out, indent)) { 514 writer().write(xml, data); 515 } 516 } 517 518 /** 519 * Write the given {@link io.jenetics.LongChromosome} to the given 520 * output stream. 521 * 522 * @param out the target output stream 523 * @param data the chromosome to write 524 * @throws XMLStreamException if an error occurs while writing the 525 * chromosome 526 * @throws NullPointerException if the {@code chromosome} or output 527 * stream is {@code null} 528 */ 529 public static void write( 530 final OutputStream out, 531 final io.jenetics.LongChromosome data 532 ) 533 throws XMLStreamException 534 { 535 write(out, data, null); 536 } 537 } 538 539 /** 540 * This class contains static writer methods for 541 * {@link io.jenetics.DoubleChromosome} objects. 542 * <p> 543 * <b>Writer code</b> 544 * <pre>{@code 545 * final DoubleChromosome value = DoubleChromosome.of(0.0, 1.0, 3); 546 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) { 547 * Writers.DoubleChromosome.writer().write(value, xml); 548 * } 549 * }</pre> 550 * 551 * <b>XML output</b> 552 * <pre> {@code 553 * <double-chromosome length="3"> 554 * <min>0.0</min> 555 * <max>1.0</max> 556 * <alleles> 557 * <allele>0.27251556008507416</allele> 558 * <allele>0.003140816229067145</allele> 559 * <allele>0.43947528327497376</allele> 560 * </alleles> 561 * </double-chromosome> 562 * }</pre> 563 */ 564 public static final class DoubleChromosome 565 //extends WriterProvider<io.jenetics.DoubleChromosome> 566 { 567 private DoubleChromosome() {} 568 569 static final String ROOT_NAME = "double-chromosome"; 570 571 /** 572 * Return the default double allele writer for the 573 * {@code DoubleChromosome}. 574 * 575 * @return the default double allele writer 576 */ 577 public static Writer<Double> alleleWriter() { 578 return text().map(Object::toString); 579 } 580 581 /** 582 * Return a {@link Writer} for {@link io.jenetics.DoubleChromosome} 583 * objects. 584 * 585 * @param alleleWriter the allele writer used for writing the long 586 * allele. Might be useful for using different long 587 * <i>encodings</i>. 588 * @return a chromosome writer 589 * @throws NullPointerException if the given {@code alleleWriter} is 590 * {@code null} 591 */ 592 public static Writer<io.jenetics.DoubleChromosome> 593 writer(final Writer<? super Double> alleleWriter) { 594 return BoundedChromosome.< 595 Double, 596 DoubleGene, 597 io.jenetics.DoubleChromosome 598 >writer(ROOT_NAME, alleleWriter); 599 } 600 601 /** 602 * Return a {@link Writer} for {@link io.jenetics.DoubleChromosome} 603 * objects. 604 * 605 * @return a chromosome writer 606 */ 607 public static Writer<io.jenetics.DoubleChromosome> writer() { 608 return writer(alleleWriter()); 609 } 610 611 public Class<io.jenetics.DoubleChromosome> type() { 612 return io.jenetics.DoubleChromosome.class; 613 } 614 615 /** 616 * Write the given {@link io.jenetics.DoubleChromosome} to the given 617 * output stream. 618 * 619 * @param out the target output stream 620 * @param data the chromosome to write 621 * @param indent the XML level indentation 622 * @throws XMLStreamException if an error occurs while writing the 623 * chromosome 624 * @throws NullPointerException if the {@code chromosome} or output 625 * stream is {@code null} 626 */ 627 public static void write( 628 final OutputStream out, 629 final io.jenetics.DoubleChromosome data, 630 final String indent 631 ) 632 throws XMLStreamException 633 { 634 requireNonNull(data); 635 requireNonNull(out); 636 637 try (var xml = XML.writer(out, indent)) { 638 writer().write(xml, data); 639 } 640 } 641 642 /** 643 * Write the given {@link io.jenetics.DoubleChromosome} to the given 644 * output stream. 645 * 646 * @param out the target output stream 647 * @param data the chromosome to write 648 * @throws XMLStreamException if an error occurs while writing the 649 * chromosome 650 * @throws NullPointerException if the {@code chromosome} or output 651 * stream is {@code null} 652 */ 653 public static void write( 654 final OutputStream out, 655 final io.jenetics.DoubleChromosome data 656 ) 657 throws XMLStreamException 658 { 659 write(out, data, null); 660 } 661 } 662 663 /** 664 * This class contains static writer methods for 665 * {@link io.jenetics.PermutationChromosome} objects. 666 * <p> 667 * <b>Writer code</b> 668 * <pre>{@code 669 * final PermutationChromosome<Integer> value = 670 * PermutationChromosome.ofInteger(5) 671 * 672 * final Writer<PermutationChromosome<Integer> writer = 673 * Writers.PermutationChromosome.writer(); 674 * 675 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) { 676 * Writers.PermutationChromosome.writer().write(value, xml); 677 * } 678 * }</pre> 679 * 680 * <b>XML output</b> 681 * <pre> {@code 682 * <permutation-chromosome length="5"> 683 * <valid-alleles type="java.lang.Integer"> 684 * <allele>0</allele> 685 * <allele>1</allele> 686 * <allele>2</allele> 687 * <allele>3</allele> 688 * <allele>4</allele> 689 * </valid-alleles> 690 * <order>2 1 3 5 4</order> 691 * </permutation-chromosome> 692 * }</pre> 693 */ 694 public static final class PermutationChromosome { 695 private PermutationChromosome() {} 696 697 static final String ROOT_NAME = "permutation-chromosome"; 698 static final String LENGTH_NAME = "length"; 699 static final String VALID_ALLELES_NAME = "valid-alleles"; 700 static final String ALLELE_NAME = "allele"; 701 static final String ORDER_NAME = "order"; 702 703 /** 704 * Create a writer for permutation-chromosomes. How to write the valid 705 * alleles is defined by the given {@link Writer}. 706 * 707 * @param alleleWriter the allele writer 708 * @param <A> the allele type 709 * @return a new permutation chromosome writer 710 * @throws NullPointerException if the given allele {@code writer} is 711 * {@code null} 712 */ 713 public static <A> Writer<io.jenetics.PermutationChromosome<A>> 714 writer(final Writer<? super A> alleleWriter) { 715 return Writer.<io.jenetics.PermutationChromosome<A>>elem( 716 ROOT_NAME, 717 attr(LENGTH_NAME).map(io.jenetics.PermutationChromosome::length), 718 elem(VALID_ALLELES_NAME, 719 attr("type").map(PermutationChromosome::toAlleleTypeName), 720 Writer.<A>elems(ALLELE_NAME, alleleWriter) 721 .map(io.jenetics.PermutationChromosome::validAlleles) 722 ), 723 elem(ORDER_NAME, text()) 724 .map(ch -> ch.stream() 725 .map(g -> Integer.toString(g.alleleIndex())) 726 .collect(Collectors.joining(" "))) 727 ); 728 } 729 730 private static String toAlleleTypeName( 731 final io.jenetics.PermutationChromosome<?> ch 732 ) { 733 return ch.gene().allele().getClass().getCanonicalName(); 734 } 735 736 /** 737 * Create a writer for permutation-chromosomes. The valid alleles are 738 * serialized by calling the {@link Object#toString()} method. Calling 739 * this method is equivalent with: 740 * <pre>{@code 741 * final Writer<PermutationChromosome<Double> writer = 742 * PermutationChromosome.write(text().map(Objects::toString)); 743 * }</pre> 744 * 745 * Example output: 746 * <pre> {@code 747 * <permutation-chromosome length="15"> 748 * <valid-alleles type="java.lang.Double"> 749 * <allele>0.27251556008507416</allele> 750 * <allele>0.003140816229067145</allele> 751 * <allele>0.43947528327497376</allele> 752 * <allele>0.10654807463069327</allele> 753 * <allele>0.19696530915810317</allele> 754 * <allele>0.7450003838065538</allele> 755 * <allele>0.5594416969271359</allele> 756 * <allele>0.02823782430152355</allele> 757 * <allele>0.5741102315010789</allele> 758 * <allele>0.4533651041367144</allele> 759 * <allele>0.811148141800367</allele> 760 * <allele>0.5710456351848858</allele> 761 * <allele>0.30166768355230955</allele> 762 * <allele>0.5455492865240272</allele> 763 * <allele>0.21068427527733102</allele> 764 * </valid-alleles> 765 * <order>13 12 4 6 8 14 7 2 11 5 3 0 9 10 1</order> 766 * </permutation-chromosome> 767 * }</pre> 768 * 769 * @param <A> the allele type 770 * @return a new permutation chromosome writer 771 */ 772 public static <A> Writer<io.jenetics.PermutationChromosome<A>> writer() { 773 return writer(text()); 774 } 775 776 /** 777 * Write the given {@link io.jenetics.PermutationChromosome} to the 778 * given output stream. 779 * 780 * @param <A> the allele type 781 * @param out the target output stream 782 * @param data the chromosome to write 783 * @param indent the XML level indentation 784 * @throws XMLStreamException if an error occurs while writing the 785 * chromosome 786 * @throws NullPointerException if the {@code chromosome} or output 787 * stream is {@code null} 788 */ 789 public static <A> void write( 790 final OutputStream out, 791 final io.jenetics.PermutationChromosome<A> data, 792 final String indent 793 ) 794 throws XMLStreamException 795 { 796 requireNonNull(data); 797 requireNonNull(out); 798 799 try (var writer = XML.writer(out, indent)) { 800 PermutationChromosome.<A>writer().write(writer, data); 801 } 802 } 803 804 /** 805 * Write the given {@link io.jenetics.PermutationChromosome} to the 806 * given output stream. 807 * 808 * @param <A> the allele type 809 * @param out the target output stream 810 * @param data the chromosome to write 811 * @param indent the XML level indentation 812 * @param alleleWriter the allele writer of the permutation chromosome 813 * @throws XMLStreamException if an error occurs while writing the 814 * chromosome 815 * @throws NullPointerException if the {@code chromosome} or output 816 * stream is {@code null} 817 */ 818 public static <A> void write( 819 final OutputStream out, 820 final io.jenetics.PermutationChromosome<A> data, 821 final String indent, 822 final Writer<? super A> alleleWriter 823 ) 824 throws XMLStreamException 825 { 826 requireNonNull(data); 827 requireNonNull(alleleWriter); 828 requireNonNull(out); 829 830 try (var xml = XML.writer(out, indent)) { 831 PermutationChromosome.<A>writer(alleleWriter) 832 .write(xml, data); 833 } 834 } 835 836 /** 837 * Write the given {@link io.jenetics.PermutationChromosome} to the 838 * given output stream. 839 * 840 * @param <A> the allele type 841 * @param out the target output stream 842 * @param data the chromosome to write 843 * @throws XMLStreamException if an error occurs while writing the 844 * chromosome 845 * @throws NullPointerException if the {@code chromosome} or output 846 * stream is {@code null} 847 */ 848 public static <A> void write( 849 final OutputStream out, 850 final io.jenetics.PermutationChromosome<A> data 851 ) 852 throws XMLStreamException 853 { 854 write(out, data, null, text()); 855 } 856 857 /** 858 * Write the given {@link io.jenetics.PermutationChromosome} to the 859 * given output stream. 860 * 861 * @param <A> the allele type 862 * @param out the target output stream 863 * @param data the chromosome to write 864 * @param alleleWriter the allele writer used to write the chromosome 865 * alleles 866 * @throws XMLStreamException if an error occurs while writing the 867 * chromosome 868 * @throws NullPointerException if the {@code chromosome} or output 869 * stream is {@code null} 870 */ 871 public static <A> void write( 872 final OutputStream out, 873 final io.jenetics.PermutationChromosome<A> data, 874 final Writer<? super A> alleleWriter 875 ) 876 throws XMLStreamException 877 { 878 write(out, data, null, alleleWriter); 879 } 880 881 } 882 883 /** 884 * This class contains static writer methods for 885 * {@link io.jenetics.Genotype} objects. 886 * <p> 887 * <b>Writer code</b> 888 * <pre>{@code 889 * final Genotype<DoubleGene> gt = Genotype.of( 890 * DoubleChromosome.of(0.0, 1.0, 3), 891 * DoubleChromosome.of(0.0, 1.0, 2) 892 * ); 893 * final Writer<Genotype<DoubleGene>> writer = 894 * Writers.Genotype.writer(Writers.DoubleChromosome.writer()); 895 * 896 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) { 897 * writer.write(value, xml); 898 * } 899 * }</pre> 900 * 901 * <b>XML output</b> 902 * <pre> {@code 903 * <genotype length="2" ngenes="5"> 904 * <double-chromosome length="3"> 905 * <min>0.0</min> 906 * <max>1.0</max> 907 * <alleles> 908 * <allele>0.27251556008507416</allele> 909 * <allele>0.003140816229067145</allele> 910 * <allele>0.43947528327497376</allele> 911 * </alleles> 912 * </double-chromosome> 913 * <double-chromosome length="2"> 914 * <min>0.0</min> 915 * <max>1.0</max> 916 * <alleles> 917 * <allele>0.4026521545744768</allele> 918 * <allele>0.36137605952663554</allele> 919 * <alleles> 920 * </double-chromosome> 921 * </genotype> 922 * }</pre> 923 */ 924 public static final class Genotype { 925 private Genotype() {} 926 927 static final String ROOT_NAME = "genotype"; 928 static final String LENGTH_NAME = "length"; 929 static final String NGENES_NAME = "ngenes"; 930 931 /** 932 * Create a writer for genotypes of arbitrary chromosomes. How to write the 933 * genotypes chromosomes is defined by the given {@link Writer}. 934 * 935 * @param writer the chromosome writer 936 * @param <A> the allele type 937 * @param <G> the gene type 938 * @param <C> the chromosome type 939 * @return a new genotype writer 940 * @throws NullPointerException if the given chromosome {@code writer} is 941 * {@code null} 942 */ 943 public static < 944 A, 945 G extends Gene<A, G>, 946 C extends Chromosome<G> 947 > 948 Writer<io.jenetics.Genotype<G>> writer(final Writer<? super C> writer) { 949 return elem( 950 ROOT_NAME, 951 attr(LENGTH_NAME).map(io.jenetics.Genotype::length), 952 attr(NGENES_NAME).map(io.jenetics.Genotype::geneCount), 953 elems(writer).map(gt -> cast(ISeq.of(gt))) 954 ); 955 } 956 957 @SuppressWarnings("unchecked") 958 private static <A, B> B cast(final A value) { 959 return (B)value; 960 } 961 962 /** 963 * Write the given {@link io.jenetics.Genotype} to the given output 964 * stream. 965 * 966 * @param <A> the allele type 967 * @param <G> the gene type 968 * @param <C> the chromosome type 969 * @param out the target output stream 970 * @param data the genotype to write 971 * @param indent the XML level indentation 972 * @param chromosomeWriter the chromosome writer used to write the 973 * genotypes 974 * @throws XMLStreamException if an error occurs while writing the 975 * chromosome 976 * @throws NullPointerException if the one of the arguments is 977 * {@code null} 978 */ 979 public static < 980 A, 981 G extends Gene<A, G>, 982 C extends Chromosome<G> 983 > 984 void write( 985 final OutputStream out, 986 final io.jenetics.Genotype<G> data, 987 final String indent, 988 final Writer<? super C> chromosomeWriter 989 ) 990 throws XMLStreamException 991 { 992 requireNonNull(data); 993 requireNonNull(chromosomeWriter); 994 requireNonNull(out); 995 996 try (var writer = XML.writer(out, indent)) { 997 Genotype.<A, G, C>writer(chromosomeWriter).write(writer, data); 998 } 999 } 1000 1001 /** 1002 * Write the given {@link io.jenetics.Genotype} to the given output 1003 * stream. 1004 * 1005 * @param <A> the allele type 1006 * @param <G> the gene type 1007 * @param <C> the chromosome type 1008 * @param out the target output stream 1009 * @param data the genotype to write 1010 * @param chromosomeWriter the chromosome writer used to write the 1011 * genotypes 1012 * @throws XMLStreamException if an error occurs while writing the 1013 * chromosome 1014 * @throws NullPointerException if the one of the arguments is 1015 * {@code null} 1016 */ 1017 public static < 1018 A, 1019 G extends Gene<A, G>, 1020 C extends Chromosome<G> 1021 > 1022 void write( 1023 final OutputStream out, 1024 final io.jenetics.Genotype<G> data, 1025 final Writer<? super C> chromosomeWriter 1026 ) 1027 throws XMLStreamException 1028 { 1029 requireNonNull(data); 1030 requireNonNull(chromosomeWriter); 1031 requireNonNull(out); 1032 1033 try (var xml = XML.writer(out)) { 1034 Genotype.<A, G, C>writer(chromosomeWriter).write(xml, data); 1035 } 1036 } 1037 1038 } 1039 1040 /** 1041 * This class contains static writer methods for 1042 * {@link io.jenetics.Genotype} objects. 1043 * <p> 1044 * <b>Writer code</b> 1045 * <pre>{@code 1046 * final Genotype<DoubleGene> gt = Genotype.of( 1047 * DoubleChromosome.of(0.0, 1.0, 3), 1048 * DoubleChromosome.of(0.0, 1.0, 2) 1049 * ); 1050 * 1051 * final Writer<Collection<Genotype<DoubleGene>>> writer = 1052 * Writers.Genotypes.writer(Writers.DoubleChromosome.writer()); 1053 * 1054 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) { 1055 * writer.write(asList(value), xml); 1056 * } 1057 * }</pre> 1058 * 1059 * <pre> {@code 1060 * <genotypes length="1"> 1061 * <genotype length="2" ngenes="5"> 1062 * <double-chromosome length="3"> 1063 * <min>0.0</min> 1064 * <max>1.0</max> 1065 * <alleles> 1066 * <allele>0.27251556008507416</allele> 1067 * <allele>0.003140816229067145</allele> 1068 * <allele>0.43947528327497376</allele> 1069 * </alleles> 1070 * </double-chromosome> 1071 * <double-chromosome length="2"> 1072 * <min>0.0</min> 1073 * <max>1.0</max> 1074 * <alleles> 1075 * <allele>0.4026521545744768</allele> 1076 * <allele>0.36137605952663554</allele> 1077 * <alleles> 1078 * </double-chromosome> 1079 * </genotype> 1080 * </genotypes> 1081 * }</pre> 1082 */ 1083 public static final class Genotypes { 1084 private Genotypes() {} 1085 1086 static final String ROOT_NAME = "genotypes"; 1087 static final String LENGTH_NAME = "length"; 1088 1089 /** 1090 * Create a writer for genotypes of arbitrary chromosomes. How to write the 1091 * genotypes chromosomes is defined by the given {@link Writer}. The 1092 * following writer allows to write double-gene chromosomes: 1093 * <pre>{@code 1094 * final Writer<Collection<Genotype<DoubleGene>>> writer = 1095 * Writers.Genotypes.writer(Writers.DoubleChromosome.writer()); 1096 * }</pre> 1097 * 1098 * @param writer the chromosome writer 1099 * @param <A> the allele type 1100 * @param <G> the gene type 1101 * @param <C> the chromosome type 1102 * @return a new genotype writer 1103 * @throws NullPointerException if the given chromosome {@code writer} is 1104 * {@code null} 1105 */ 1106 public static < 1107 A, 1108 G extends Gene<A, G>, 1109 C extends Chromosome<G> 1110 > 1111 Writer<Collection<io.jenetics.Genotype<G>>> 1112 writer(final Writer<? super C> writer) { 1113 return elem( 1114 ROOT_NAME, 1115 attr(LENGTH_NAME).map(Collection::size), 1116 elems(Genotype.writer(writer)) 1117 ); 1118 } 1119 1120 /** 1121 * Write the given {@link io.jenetics.Genotype} to the given output 1122 * stream. 1123 * 1124 * @param <A> the allele type 1125 * @param <G> the gene type 1126 * @param <C> the chromosome type 1127 * @param out the target output stream 1128 * @param data the genotypes to write 1129 * @param indent the XML level indentation 1130 * @param chromosomeWriter the chromosome writer used to write the 1131 * genotypes 1132 * @throws XMLStreamException if an error occurs while writing the 1133 * chromosome 1134 * @throws NullPointerException if the one of the arguments is 1135 * {@code null} 1136 */ 1137 public static < 1138 A, 1139 G extends Gene<A, G>, 1140 C extends Chromosome<G> 1141 > 1142 void write( 1143 final OutputStream out, 1144 final Collection<io.jenetics.Genotype<G>> data, 1145 final String indent, 1146 final Writer<? super C> chromosomeWriter 1147 ) 1148 throws XMLStreamException 1149 { 1150 requireNonNull(data); 1151 requireNonNull(chromosomeWriter); 1152 requireNonNull(out); 1153 1154 try (var xml = XML.writer(out, indent)) { 1155 Genotypes.<A, G, C>writer(chromosomeWriter).write(xml, data); 1156 } 1157 } 1158 1159 /** 1160 * Write the given {@link io.jenetics.Genotype} to the given output 1161 * stream. 1162 * 1163 * @param <A> the allele type 1164 * @param <G> the gene type 1165 * @param <C> the chromosome type 1166 * @param out the target output stream 1167 * @param data the genotypes to write 1168 * @param chromosomeWriter the chromosome writer used to write the 1169 * genotypes 1170 * @throws XMLStreamException if an error occurs while writing the 1171 * chromosome 1172 * @throws NullPointerException if the one of the arguments is 1173 * {@code null} 1174 */ 1175 public static < 1176 A, 1177 G extends Gene<A, G>, 1178 C extends Chromosome<G> 1179 > 1180 void write( 1181 final OutputStream out, 1182 final Collection<io.jenetics.Genotype<G>> data, 1183 final Writer<? super C> chromosomeWriter 1184 ) 1185 throws XMLStreamException 1186 { 1187 requireNonNull(data); 1188 requireNonNull(chromosomeWriter); 1189 requireNonNull(out); 1190 1191 try (var xml = XML.writer(out)) { 1192 Genotypes.<A, G, C>writer(chromosomeWriter).write(xml, data); 1193 } 1194 } 1195 1196 } 1197 1198 1199 /** 1200 * Write the given {@link io.jenetics.Genotype} to the given output 1201 * stream. 1202 * 1203 * @see Genotypes#write(OutputStream, Collection, Writer) 1204 * 1205 * @param <A> the allele type 1206 * @param <G> the gene type 1207 * @param <C> the chromosome type 1208 * @param out the target output stream 1209 * @param data the genotypes to write 1210 * @param chromosomeWriter the chromosome writer used to write the 1211 * genotypes 1212 * @throws XMLStreamException if an error occurs while writing the 1213 * chromosome 1214 * @throws NullPointerException if the one of the arguments is 1215 * {@code null} 1216 */ 1217 public static < 1218 A, 1219 G extends Gene<A, G>, 1220 C extends Chromosome<G> 1221 > 1222 void write( 1223 final OutputStream out, 1224 final Collection<io.jenetics.Genotype<G>> data, 1225 final Writer<? super C> chromosomeWriter 1226 ) 1227 throws XMLStreamException 1228 { 1229 Genotypes.write(out, data, chromosomeWriter); 1230 } 1231 1232}