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