001/* 002 * Java Genetic Algorithm Library (jenetics-9.1.0). 003 * Copyright (c) 2007-2026 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.BaseSeq; 041import io.jenetics.util.ISeq; 042import io.jenetics.xml.stream.Writer; 043import io.jenetics.xml.stream.XML; 044 045/** 046 * This class contains static fields and methods for creating chromosome- and 047 * genotype writers for different gene types. 048 * {@snippet lang="java": 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 * } 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 * {@snippet lang="java": 062 * final List<Genotype<BitGene>> genotypes = null; // @replace substring='null' replacement="..." 063 * try (OutputStream out = Files.newOutputStream(Paths.get("path"))) { 064 * Writers.write(out, genotypes, Writers.BitChromosome.writer()); 065 * } 066 * } 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 * {@snippet lang="java": 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 * } 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(io.jenetics.BitChromosome::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 * {@snippet lang="java": 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 * } 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(BaseSeq::length), 289 elem(MIN_NAME, alleleWriter.map(io.jenetics.BoundedChromosome::min)), 290 elem(MAX_NAME, alleleWriter.map(io.jenetics.BoundedChromosome::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 * {@snippet lang="java": 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 * } 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 * {@snippet lang="java": 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 * } 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 * {@snippet lang="java": 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 * } 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 * {@snippet lang="java": 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 * } 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.elem( 716 ROOT_NAME, 717 attr(LENGTH_NAME) 718 .map(io.jenetics.PermutationChromosome::length), 719 elem(VALID_ALLELES_NAME, 720 attr("type").map(PermutationChromosome::toAlleleTypeName), 721 Writer.<A>elems(ALLELE_NAME, alleleWriter) 722 .map(io.jenetics.PermutationChromosome::validAlleles) 723 ), 724 elem(ORDER_NAME, text()) 725 .map(ch -> ch.stream() 726 .map(g -> Integer.toString(g.alleleIndex())) 727 .collect(Collectors.joining(" "))) 728 ); 729 } 730 731 private static String toAlleleTypeName( 732 final io.jenetics.PermutationChromosome<?> ch 733 ) { 734 return ch.gene().allele().getClass().getCanonicalName(); 735 } 736 737 /** 738 * Create a writer for permutation-chromosomes. The valid alleles are 739 * serialized by calling the {@link Object#toString()} method. Calling 740 * this method is equivalent to: 741 * {@snippet lang="java": 742 * final Writer<PermutationChromosome<Double>> writer = 743 * PermutationChromosome.write(text().map(Objects::toString)); 744 * } 745 * 746 * Example output: 747 * <pre> {@code 748 * <permutation-chromosome length="15"> 749 * <valid-alleles type="java.lang.Double"> 750 * <allele>0.27251556008507416</allele> 751 * <allele>0.003140816229067145</allele> 752 * <allele>0.43947528327497376</allele> 753 * <allele>0.10654807463069327</allele> 754 * <allele>0.19696530915810317</allele> 755 * <allele>0.7450003838065538</allele> 756 * <allele>0.5594416969271359</allele> 757 * <allele>0.02823782430152355</allele> 758 * <allele>0.5741102315010789</allele> 759 * <allele>0.4533651041367144</allele> 760 * <allele>0.811148141800367</allele> 761 * <allele>0.5710456351848858</allele> 762 * <allele>0.30166768355230955</allele> 763 * <allele>0.5455492865240272</allele> 764 * <allele>0.21068427527733102</allele> 765 * </valid-alleles> 766 * <order>13 12 4 6 8 14 7 2 11 5 3 0 9 10 1</order> 767 * </permutation-chromosome> 768 * } </pre> 769 * 770 * @param <A> the allele type 771 * @return a new permutation chromosome writer 772 */ 773 public static <A> Writer<io.jenetics.PermutationChromosome<A>> writer() { 774 return writer(text()); 775 } 776 777 /** 778 * Write the given {@link io.jenetics.PermutationChromosome} to the 779 * given output stream. 780 * 781 * @param <A> the allele type 782 * @param out the target output stream 783 * @param data the chromosome to write 784 * @param indent the XML level indentation 785 * @throws XMLStreamException if an error occurs while writing the 786 * chromosome 787 * @throws NullPointerException if the {@code chromosome} or output 788 * stream is {@code null} 789 */ 790 public static <A> void write( 791 final OutputStream out, 792 final io.jenetics.PermutationChromosome<A> data, 793 final String indent 794 ) 795 throws XMLStreamException 796 { 797 requireNonNull(data); 798 requireNonNull(out); 799 800 try (var writer = XML.writer(out, indent)) { 801 PermutationChromosome.<A>writer().write(writer, data); 802 } 803 } 804 805 /** 806 * Write the given {@link io.jenetics.PermutationChromosome} to the 807 * given output stream. 808 * 809 * @param <A> the allele type 810 * @param out the target output stream 811 * @param data the chromosome to write 812 * @param indent the XML level indentation 813 * @param alleleWriter the allele writer of the permutation chromosome 814 * @throws XMLStreamException if an error occurs while writing the 815 * chromosome 816 * @throws NullPointerException if the {@code chromosome} or output 817 * stream is {@code null} 818 */ 819 public static <A> void write( 820 final OutputStream out, 821 final io.jenetics.PermutationChromosome<A> data, 822 final String indent, 823 final Writer<? super A> alleleWriter 824 ) 825 throws XMLStreamException 826 { 827 requireNonNull(data); 828 requireNonNull(alleleWriter); 829 requireNonNull(out); 830 831 try (var xml = XML.writer(out, indent)) { 832 PermutationChromosome.<A>writer(alleleWriter) 833 .write(xml, data); 834 } 835 } 836 837 /** 838 * Write the given {@link io.jenetics.PermutationChromosome} to the 839 * given output stream. 840 * 841 * @param <A> the allele type 842 * @param out the target output stream 843 * @param data the chromosome to write 844 * @throws XMLStreamException if an error occurs while writing the 845 * chromosome 846 * @throws NullPointerException if the {@code chromosome} or output 847 * stream is {@code null} 848 */ 849 public static <A> void write( 850 final OutputStream out, 851 final io.jenetics.PermutationChromosome<A> data 852 ) 853 throws XMLStreamException 854 { 855 write(out, data, null, text()); 856 } 857 858 /** 859 * Write the given {@link io.jenetics.PermutationChromosome} to the 860 * given output stream. 861 * 862 * @param <A> the allele type 863 * @param out the target output stream 864 * @param data the chromosome to write 865 * @param alleleWriter the allele writer used to write the chromosome 866 * alleles 867 * @throws XMLStreamException if an error occurs while writing the 868 * chromosome 869 * @throws NullPointerException if the {@code chromosome} or output 870 * stream is {@code null} 871 */ 872 public static <A> void write( 873 final OutputStream out, 874 final io.jenetics.PermutationChromosome<A> data, 875 final Writer<? super A> alleleWriter 876 ) 877 throws XMLStreamException 878 { 879 write(out, data, null, alleleWriter); 880 } 881 882 } 883 884 /** 885 * This class contains static writer methods for 886 * {@link io.jenetics.Genotype} objects. 887 * <p> 888 * <b>Writer code</b> 889 * {@snippet lang="java": 890 * final Genotype<DoubleGene> gt = Genotype.of( 891 * DoubleChromosome.of(0.0, 1.0, 3), 892 * DoubleChromosome.of(0.0, 1.0, 2) 893 * ); 894 * final Writer<Genotype<DoubleGene>> writer = 895 * Writers.Genotype.writer(Writers.DoubleChromosome.writer()); 896 * 897 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) { 898 * writer.write(value, xml); 899 * } 900 * } 901 * 902 * <b>XML output</b> 903 * <pre> {@code 904 * <genotype length="2" ngenes="5"> 905 * <double-chromosome length="3"> 906 * <min>0.0</min> 907 * <max>1.0</max> 908 * <alleles> 909 * <allele>0.27251556008507416</allele> 910 * <allele>0.003140816229067145</allele> 911 * <allele>0.43947528327497376</allele> 912 * </alleles> 913 * </double-chromosome> 914 * <double-chromosome length="2"> 915 * <min>0.0</min> 916 * <max>1.0</max> 917 * <alleles> 918 * <allele>0.4026521545744768</allele> 919 * <allele>0.36137605952663554</allele> 920 * <alleles> 921 * </double-chromosome> 922 * </genotype> 923 * } </pre> 924 */ 925 public static final class Genotype { 926 private Genotype() {} 927 928 static final String ROOT_NAME = "genotype"; 929 static final String LENGTH_NAME = "length"; 930 static final String NGENES_NAME = "ngenes"; 931 932 /** 933 * Create a writer for genotypes of arbitrary chromosomes. How to write the 934 * genotype chromosomes is defined by the given {@link Writer}. 935 * 936 * @param writer the chromosome writer 937 * @param <A> the allele type 938 * @param <G> the gene type 939 * @param <C> the chromosome type 940 * @return a new genotype writer 941 * @throws NullPointerException if the given chromosome {@code writer} is 942 * {@code null} 943 */ 944 public static < 945 A, 946 G extends Gene<A, G>, 947 C extends Chromosome<G> 948 > 949 Writer<io.jenetics.Genotype<G>> writer(final Writer<? super C> writer) { 950 return elem( 951 ROOT_NAME, 952 attr(LENGTH_NAME).map(io.jenetics.Genotype::length), 953 attr(NGENES_NAME).map(io.jenetics.Genotype::geneCount), 954 elems(writer).map(gt -> cast(ISeq.of(gt))) 955 ); 956 } 957 958 @SuppressWarnings("unchecked") 959 private static <A, B> B cast(final A value) { 960 return (B)value; 961 } 962 963 /** 964 * Write the given {@link io.jenetics.Genotype} to the given output 965 * stream. 966 * 967 * @param <A> the allele type 968 * @param <G> the gene type 969 * @param <C> the chromosome type 970 * @param out the target output stream 971 * @param data the genotype to write 972 * @param indent the XML level indentation 973 * @param chromosomeWriter the chromosome writer used to write the 974 * genotypes 975 * @throws XMLStreamException if an error occurs while writing the 976 * chromosome 977 * @throws NullPointerException if the one of the arguments is 978 * {@code null} 979 */ 980 public static < 981 A, 982 G extends Gene<A, G>, 983 C extends Chromosome<G> 984 > 985 void write( 986 final OutputStream out, 987 final io.jenetics.Genotype<G> data, 988 final String indent, 989 final Writer<? super C> chromosomeWriter 990 ) 991 throws XMLStreamException 992 { 993 requireNonNull(data); 994 requireNonNull(chromosomeWriter); 995 requireNonNull(out); 996 997 try (var writer = XML.writer(out, indent)) { 998 Genotype.<A, G, C>writer(chromosomeWriter).write(writer, data); 999 } 1000 } 1001 1002 /** 1003 * Write the given {@link io.jenetics.Genotype} to the given output 1004 * stream. 1005 * 1006 * @param <A> the allele type 1007 * @param <G> the gene type 1008 * @param <C> the chromosome type 1009 * @param out the target output stream 1010 * @param data the genotype to write 1011 * @param chromosomeWriter the chromosome writer used to write the 1012 * genotypes 1013 * @throws XMLStreamException if an error occurs while writing the 1014 * chromosome 1015 * @throws NullPointerException if the one of the arguments is 1016 * {@code null} 1017 */ 1018 public static < 1019 A, 1020 G extends Gene<A, G>, 1021 C extends Chromosome<G> 1022 > 1023 void write( 1024 final OutputStream out, 1025 final io.jenetics.Genotype<G> data, 1026 final Writer<? super C> chromosomeWriter 1027 ) 1028 throws XMLStreamException 1029 { 1030 requireNonNull(data); 1031 requireNonNull(chromosomeWriter); 1032 requireNonNull(out); 1033 1034 try (var xml = XML.writer(out)) { 1035 Genotype.<A, G, C>writer(chromosomeWriter).write(xml, data); 1036 } 1037 } 1038 1039 } 1040 1041 /** 1042 * This class contains static writer methods for 1043 * {@link io.jenetics.Genotype} objects. 1044 * <p> 1045 * <b>Writer code</b> 1046 * {@snippet lang="java": 1047 * final Genotype<DoubleGene> gt = Genotype.of( 1048 * DoubleChromosome.of(0.0, 1.0, 3), 1049 * DoubleChromosome.of(0.0, 1.0, 2) 1050 * ); 1051 * 1052 * final Writer<Collection<Genotype<DoubleGene>>> writer = 1053 * Writers.Genotypes.writer(Writers.DoubleChromosome.writer()); 1054 * 1055 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) { 1056 * writer.write(asList(value), xml); 1057 * } 1058 * } 1059 * 1060 * <pre> {@code 1061 * <genotypes length="1"> 1062 * <genotype length="2" ngenes="5"> 1063 * <double-chromosome length="3"> 1064 * <min>0.0</min> 1065 * <max>1.0</max> 1066 * <alleles> 1067 * <allele>0.27251556008507416</allele> 1068 * <allele>0.003140816229067145</allele> 1069 * <allele>0.43947528327497376</allele> 1070 * </alleles> 1071 * </double-chromosome> 1072 * <double-chromosome length="2"> 1073 * <min>0.0</min> 1074 * <max>1.0</max> 1075 * <alleles> 1076 * <allele>0.4026521545744768</allele> 1077 * <allele>0.36137605952663554</allele> 1078 * <alleles> 1079 * </double-chromosome> 1080 * </genotype> 1081 * </genotypes> 1082 * } </pre> 1083 */ 1084 public static final class Genotypes { 1085 private Genotypes() {} 1086 1087 static final String ROOT_NAME = "genotypes"; 1088 static final String LENGTH_NAME = "length"; 1089 1090 /** 1091 * Create a writer for genotypes of arbitrary chromosomes. How to write the 1092 * genotype chromosomes is defined by the given {@link Writer}. The 1093 * following writer allows writing double-gene chromosomes: 1094 * {@snippet lang="java": 1095 * final Writer<Collection<Genotype<DoubleGene>>> writer = 1096 * Writers.Genotypes.writer(Writers.DoubleChromosome.writer()); 1097 * } 1098 * 1099 * @param writer the chromosome writer 1100 * @param <A> the allele type 1101 * @param <G> the gene type 1102 * @param <C> the chromosome type 1103 * @return a new genotype writer 1104 * @throws NullPointerException if the given chromosome {@code writer} is 1105 * {@code null} 1106 */ 1107 public static < 1108 A, 1109 G extends Gene<A, G>, 1110 C extends Chromosome<G> 1111 > 1112 Writer<Collection<io.jenetics.Genotype<G>>> 1113 writer(final Writer<? super C> writer) { 1114 return elem( 1115 ROOT_NAME, 1116 attr(LENGTH_NAME).map(Collection::size), 1117 elems(Genotype.writer(writer)) 1118 ); 1119 } 1120 1121 /** 1122 * Write the given {@link io.jenetics.Genotype} to the given output 1123 * stream. 1124 * 1125 * @param <A> the allele type 1126 * @param <G> the gene type 1127 * @param <C> the chromosome type 1128 * @param out the target output stream 1129 * @param data the genotypes to write 1130 * @param indent the XML level indentation 1131 * @param chromosomeWriter the chromosome writer used to write the 1132 * genotypes 1133 * @throws XMLStreamException if an error occurs while writing the 1134 * chromosome 1135 * @throws NullPointerException if the one of the arguments is 1136 * {@code null} 1137 */ 1138 public static < 1139 A, 1140 G extends Gene<A, G>, 1141 C extends Chromosome<G> 1142 > 1143 void write( 1144 final OutputStream out, 1145 final Collection<io.jenetics.Genotype<G>> data, 1146 final String indent, 1147 final Writer<? super C> chromosomeWriter 1148 ) 1149 throws XMLStreamException 1150 { 1151 requireNonNull(data); 1152 requireNonNull(chromosomeWriter); 1153 requireNonNull(out); 1154 1155 try (var xml = XML.writer(out, indent)) { 1156 Genotypes.<A, G, C>writer(chromosomeWriter).write(xml, data); 1157 } 1158 } 1159 1160 /** 1161 * Write the given {@link io.jenetics.Genotype} to the given output 1162 * stream. 1163 * 1164 * @param <A> the allele type 1165 * @param <G> the gene type 1166 * @param <C> the chromosome type 1167 * @param out the target output stream 1168 * @param data the genotypes to write 1169 * @param chromosomeWriter the chromosome writer used to write the 1170 * genotypes 1171 * @throws XMLStreamException if an error occurs while writing the 1172 * chromosome 1173 * @throws NullPointerException if the one of the arguments is 1174 * {@code null} 1175 */ 1176 public static < 1177 A, 1178 G extends Gene<A, G>, 1179 C extends Chromosome<G> 1180 > 1181 void write( 1182 final OutputStream out, 1183 final Collection<io.jenetics.Genotype<G>> data, 1184 final Writer<? super C> chromosomeWriter 1185 ) 1186 throws XMLStreamException 1187 { 1188 requireNonNull(data); 1189 requireNonNull(chromosomeWriter); 1190 requireNonNull(out); 1191 1192 try (var xml = XML.writer(out)) { 1193 Genotypes.<A, G, C>writer(chromosomeWriter).write(xml, data); 1194 } 1195 } 1196 1197 } 1198 1199 1200 /** 1201 * Write the given {@link io.jenetics.Genotype} to the given output 1202 * stream. 1203 * 1204 * @see Genotypes#write(OutputStream, Collection, Writer) 1205 * 1206 * @param <A> the allele type 1207 * @param <G> the gene type 1208 * @param <C> the chromosome type 1209 * @param out the target output stream 1210 * @param data the genotypes to write 1211 * @param chromosomeWriter the chromosome writer used to write the 1212 * genotypes 1213 * @throws XMLStreamException if an error occurs while writing the 1214 * chromosome 1215 * @throws NullPointerException if the one of the arguments is 1216 * {@code null} 1217 */ 1218 public static < 1219 A, 1220 G extends Gene<A, G>, 1221 C extends Chromosome<G> 1222 > 1223 void write( 1224 final OutputStream out, 1225 final Collection<io.jenetics.Genotype<G>> data, 1226 final Writer<? super C> chromosomeWriter 1227 ) 1228 throws XMLStreamException 1229 { 1230 Genotypes.write(out, data, chromosomeWriter); 1231 } 1232 1233}