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