0001 /*
0002 * Java Genetic Algorithm Library (jenetics-6.1.0).
0003 * Copyright (c) 2007-2020 Franz Wilhelmstötter
0004 *
0005 * Licensed under the Apache License, Version 2.0 (the "License");
0006 * you may not use this file except in compliance with the License.
0007 * You may obtain a copy of the License at
0008 *
0009 * http://www.apache.org/licenses/LICENSE-2.0
0010 *
0011 * Unless required by applicable law or agreed to in writing, software
0012 * distributed under the License is distributed on an "AS IS" BASIS,
0013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014 * See the License for the specific language governing permissions and
0015 * limitations under the License.
0016 *
0017 * Author:
0018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
0019 */
0020 package io.jenetics.xml;
0021
0022 import static java.util.Objects.requireNonNull;
0023 import static io.jenetics.xml.stream.Writer.attr;
0024 import static io.jenetics.xml.stream.Writer.elem;
0025 import static io.jenetics.xml.stream.Writer.elems;
0026 import static io.jenetics.xml.stream.Writer.text;
0027
0028 import java.io.OutputStream;
0029 import java.util.Collection;
0030 import java.util.stream.Collectors;
0031
0032 import javax.xml.stream.XMLStreamException;
0033
0034 import io.jenetics.BoundedGene;
0035 import io.jenetics.Chromosome;
0036 import io.jenetics.DoubleGene;
0037 import io.jenetics.Gene;
0038 import io.jenetics.IntegerGene;
0039 import io.jenetics.LongGene;
0040 import io.jenetics.util.ISeq;
0041 import io.jenetics.xml.stream.Writer;
0042 import io.jenetics.xml.stream.XML;
0043
0044 /**
0045 * This class contains static fields and methods, for creating chromosome- and
0046 * genotype writers for different gene types.
0047 *
0048 * <pre>{@code
0049 * final Writer<Genotype<BitGene> bgw =
0050 * Writers.Genotype.writer(Writers.BitChromosome.writer()));
0051 *
0052 * final Writer<Genotype<IntegerGene>> igw =
0053 * Writers.Genotype.writer(Writers.IntegerChromosome.writer()));
0054 *
0055 * final Writer<Genotype<DoubleGene>> dgw =
0056 * Writers.Genotype.writer(Writers.DoubleChromosome.writer()));
0057 * }</pre>
0058 *
0059 * This class also contains some helper methods, which makes it easier to write
0060 * Jenetics domain objects to a given output stream.
0061 * <pre>{@code
0062 * final List<Genotype<BitGene>> genotypes = ...;
0063 * try (OutputStream out = Files.newOutputStream(Paths.get("path"))) {
0064 * Writers.write(out, genotypes, Writers.BitChromosome.writer());
0065 * }
0066 * }</pre>
0067 *
0068 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
0069 * @version 3.9
0070 * @since 3.9
0071 */
0072 public final class Writers {
0073 private Writers() {}
0074
0075 /**
0076 * This class contains static writer methods for
0077 * {@link io.jenetics.BitChromosome} objects.
0078 * <p>
0079 * <b>Writer code</b>
0080 * <pre>{@code
0081 * final BitChromosome value = BitChromosome.of(20, 0.5);
0082 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) {
0083 * Writers.BitChromosome.writer().write(value, xml);
0084 * }
0085 * }</pre>
0086 *
0087 * <b>XML output</b>
0088 * <pre> {@code
0089 * <bit-chromosome length="20" ones-probability="0.5">11100011101011001010</bit-chromosome>
0090 * }</pre>
0091 *
0092 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
0093 * @version 3.9
0094 * @since 3.9
0095 */
0096 public static final class BitChromosome {
0097 private BitChromosome() {}
0098
0099 static final String ROOT_NAME = "bit-chromosome";
0100 static final String LENGTH_NAME = "length";
0101 static final String ONES_PROBABILITY_NAME = "ones-probability";
0102
0103 /**
0104 * Return a {@link Writer} for {@link io.jenetics.BitChromosome}
0105 * objects.
0106 *
0107 * @return a chromosome writer
0108 */
0109 public static Writer<io.jenetics.BitChromosome> writer() {
0110 return elem(ROOT_NAME,
0111 attr(LENGTH_NAME).map(io.jenetics.BitChromosome::length),
0112 attr(ONES_PROBABILITY_NAME).map(ch -> ch.oneProbability()),
0113 text().map(io.jenetics.BitChromosome::toCanonicalString)
0114 );
0115 }
0116
0117 /**
0118 * Write the given {@link io.jenetics.BitChromosome} to the given
0119 * output stream.
0120 *
0121 * @param out the target output stream
0122 * @param data the bit-chromosome to write
0123 * @throws XMLStreamException if an error occurs while writing the
0124 * chromosome
0125 * @throws NullPointerException if one of the given arguments is
0126 * {@code null}
0127 */
0128 public static void write(
0129 final OutputStream out,
0130 final io.jenetics.BitChromosome data
0131 )
0132 throws XMLStreamException
0133 {
0134 requireNonNull(data);
0135 requireNonNull(out);
0136
0137 try (var xml = XML.writer(out)) {
0138 writer().write(xml, data);
0139 }
0140 }
0141 }
0142
0143
0144 /**
0145 * This class contains static writer methods for
0146 * {@link io.jenetics.CharacterChromosome} objects.
0147 * <p>
0148 * <b>Writer code</b>
0149 * <pre>{@code
0150 * final CharacterChromosome value = CharacterChromosome.of("ASDF", CharSeq.of("A-Z"));
0151 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) {
0152 * Writers.CharacterChromosome.writer().write(value, xml);
0153 * }
0154 * }</pre>
0155 *
0156 * <b>XML output</b>
0157 * <pre> {@code
0158 * <character-chromosome length="4">
0159 * <valid-alleles>ABCDEFGHIJKLMNOPQRSTUVWXYZ<valid-alleles>
0160 * <alleles>ASDF</alleles>
0161 * </character-chromosome>
0162 * }</pre>
0163 */
0164 public static final class CharacterChromosome {
0165 private CharacterChromosome() {}
0166
0167 static final String ROOT_NAME = "character-chromosome";
0168 static final String LENGTH_NAME = "length";
0169 static final String VALID_ALLELES_NAME = "valid-alleles";
0170 static final String ALLELES_NAME = "alleles";
0171
0172 /**
0173 * Return a {@link Writer} for {@link io.jenetics.CharacterChromosome}
0174 * objects.
0175 *
0176 * @return a chromosome writer
0177 */
0178 public static Writer<io.jenetics.CharacterChromosome> writer() {
0179 return elem(ROOT_NAME,
0180 attr(LENGTH_NAME).map(io.jenetics.CharacterChromosome::length),
0181 elem(VALID_ALLELES_NAME,
0182 text().map(ch -> ch.gene().validChars())),
0183 elem(ALLELES_NAME,
0184 text().map(io.jenetics.CharacterChromosome::toString))
0185 );
0186 }
0187
0188 /**
0189 * Write the given {@link io.jenetics.CharacterChromosome} to the given
0190 * output stream.
0191 *
0192 * @param out the target output stream
0193 * @param data the chromosome to write
0194 * @param indent the XML level indentation
0195 * @throws XMLStreamException if an error occurs while writing the
0196 * chromosome
0197 * @throws NullPointerException if the {@code chromosome} or output
0198 * stream is {@code null}
0199 */
0200 public static void write(
0201 final OutputStream out,
0202 final io.jenetics.CharacterChromosome data,
0203 final String indent
0204 )
0205 throws XMLStreamException
0206 {
0207 requireNonNull(data);
0208 requireNonNull(out);
0209
0210 try (var xml = XML.writer(out, indent)) {
0211 writer().write(xml, data);
0212 }
0213 }
0214
0215 /**
0216 * Write the given {@link io.jenetics.CharacterChromosome} to the given
0217 * output stream.
0218 *
0219 * @param out the target output stream
0220 * @param data the chromosome to write
0221 * @throws XMLStreamException if an error occurs while writing the
0222 * chromosome
0223 * @throws NullPointerException if the {@code chromosome} or output
0224 * stream is {@code null}
0225 */
0226 public static void write(
0227 final OutputStream out,
0228 final io.jenetics.CharacterChromosome data
0229 )
0230 throws XMLStreamException
0231 {
0232 write(out, data, null);
0233 }
0234
0235 }
0236
0237 /**
0238 * This class contains static writer methods for
0239 * {@link io.jenetics.BoundedChromosome} objects.
0240 *
0241 * <p>
0242 * <b>XML template</b>
0243 * <pre> {@code
0244 * <root-name length="3">
0245 * <min>aaa</min>
0246 * <max>zzz</max>
0247 * <alleles>
0248 * <allele>iii</allele>
0249 * <allele>fff</allele>
0250 * <allele>ggg</allele>
0251 * </alleles>
0252 * </root-name>
0253 * }</pre>
0254 */
0255 public static final class BoundedChromosome {
0256 private BoundedChromosome() {}
0257
0258 static final String LENGTH_NAME = "length";
0259 static final String MIN_NAME = "min";
0260 static final String MAX_NAME = "max";
0261 static final String ALLELE_NAME = "allele";
0262 static final String ALLELES_NAME = "alleles";
0263
0264 /**
0265 * Create a bounded chromosome writer with the given configuration.
0266 *
0267 * @param rootName the name of the root element. E.g. {@code int-chromosome}
0268 * @param alleleWriter the XML writer used for the alleles
0269 * @param <A> the allele type
0270 * @param <G> the bounded gene type
0271 * @param <C> the bounded chromosome type
0272 * @return a bounded chromosome XML writer
0273 * @throws NullPointerException if one of the arguments is {@code null}
0274 */
0275 public static <
0276 A extends Comparable<? super A>,
0277 G extends BoundedGene<A, G>,
0278 C extends io.jenetics.BoundedChromosome<A, G>
0279 >
0280 Writer<C> writer(
0281 final String rootName,
0282 final Writer<? super A> alleleWriter
0283 ) {
0284 requireNonNull(rootName);
0285 requireNonNull(alleleWriter);
0286
0287 return elem(rootName,
0288 attr(LENGTH_NAME).map(ch -> ch.length()),
0289 elem(MIN_NAME, alleleWriter.map(ch -> ch.min())),
0290 elem(MAX_NAME, alleleWriter.map(ch -> ch.max())),
0291 elem(ALLELES_NAME,
0292 elems(ALLELE_NAME, alleleWriter)
0293 .map(ch -> ISeq.of(ch).map(G::allele))
0294 )
0295 );
0296 }
0297 }
0298
0299 /**
0300 * This class contains static writer methods for
0301 * {@link io.jenetics.IntegerChromosome} objects.
0302 * <p>
0303 * <b>Writer code</b>
0304 * <pre>{@code
0305 * final IntegerChromosome value = IntegerChromosome
0306 * .of(Integer.MIN_VALUE, Integer.MAX_VALUE, 3);
0307 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) {
0308 * Writers.IntegerChromosome.writer().write(value, xml);
0309 * }
0310 * }</pre>
0311 *
0312 * <b>XML output</b>
0313 * <pre> {@code
0314 * <int-chromosome length="3">
0315 * <min>-2147483648</min>
0316 * <max>2147483647</max>
0317 * <alleles>
0318 * <allele>-1878762439</allele>
0319 * <allele>-957346595</allele>
0320 * <allele>-88668137</allele>
0321 * </alleles>
0322 * </int-chromosome>
0323 * }</pre>
0324 */
0325 public static final class IntegerChromosome {
0326 private IntegerChromosome() {}
0327
0328 static final String ROOT_NAME = "int-chromosome";
0329
0330 /**
0331 * Return the default integer allele writer for the
0332 * {@code IntegerChromosome}.
0333 *
0334 * @return the default integer allele writer
0335 */
0336 public static Writer<Integer> alleleWriter() {
0337 return text();
0338 }
0339
0340 /**
0341 * Return a {@link Writer} for {@link io.jenetics.IntegerChromosome}
0342 * objects.
0343 *
0344 * @param alleleWriter the allele writer used for writing the integer
0345 * allele. Might be useful for using different integer
0346 * <i>encodings</i>.
0347 * @return a chromosome writer
0348 * @throws NullPointerException if the given {@code alleleWriter} is
0349 * {@code null}
0350 */
0351 public static Writer<io.jenetics.IntegerChromosome>
0352 writer(final Writer<? super Integer> alleleWriter) {
0353 requireNonNull(alleleWriter);
0354
0355 return BoundedChromosome.<
0356 Integer,
0357 IntegerGene,
0358 io.jenetics.IntegerChromosome
0359 >writer(ROOT_NAME, alleleWriter);
0360 }
0361
0362 /**
0363 * Return a {@link Writer} for {@link io.jenetics.IntegerChromosome}
0364 * objects.
0365 *
0366 * @return a chromosome writer
0367 */
0368 public static Writer<io.jenetics.IntegerChromosome> writer() {
0369 return writer(alleleWriter());
0370 }
0371
0372 /**
0373 * Write the given {@link io.jenetics.IntegerChromosome} to the given
0374 * output stream.
0375 *
0376 * @param out the target output stream
0377 * @param data the chromosome to write
0378 * @param indent the XML level indentation
0379 * @throws XMLStreamException if an error occurs while writing the
0380 * chromosome
0381 * @throws NullPointerException if the {@code chromosome} or output
0382 * stream is {@code null}
0383 */
0384 public static void write(
0385 final OutputStream out,
0386 final io.jenetics.IntegerChromosome data,
0387 final String indent
0388 )
0389 throws XMLStreamException
0390 {
0391 requireNonNull(data);
0392 requireNonNull(out);
0393
0394 try (var xml = XML.writer(out, indent)) {
0395 writer().write(xml, data);
0396 }
0397 }
0398
0399 /**
0400 * Write the given {@link io.jenetics.IntegerChromosome} to the given
0401 * output stream.
0402 *
0403 * @param out the target output stream
0404 * @param data the chromosome to write
0405 * @throws XMLStreamException if an error occurs while writing the
0406 * chromosome
0407 * @throws NullPointerException if the {@code chromosome} or output
0408 * stream is {@code null}
0409 */
0410 public static void write(
0411 final OutputStream out,
0412 final io.jenetics.IntegerChromosome data
0413 )
0414 throws XMLStreamException
0415 {
0416 write(out, data, null);
0417 }
0418 }
0419
0420 /**
0421 * This class contains static writer methods for
0422 * {@link io.jenetics.LongChromosome} objects.
0423 * <p>
0424 * <b>Writer code</b>
0425 * <pre>{@code
0426 * final LongChromosome value = LongChromosome
0427 * .of(Long.MIN_VALUE, Long.MAX_VALUE, 3);
0428 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) {
0429 * Writers.LongChromosome.writer().write(value, xml);
0430 * }
0431 * }</pre>
0432 *
0433 * <b>XML output</b>
0434 * <pre> {@code
0435 * <long-chromosome length="3">
0436 * <min>-9223372036854775808</min>
0437 * <max>9223372036854775807</max>
0438 * <alleles>
0439 * <allele>-1345217698116542402</allele>
0440 * <allele>-7144755673073475303</allele>
0441 * <allele>6053786736809578435</allele>
0442 * </alleles>
0443 * </long-chromosome>
0444 * }</pre>
0445 */
0446 public static final class LongChromosome {
0447 private LongChromosome() {}
0448
0449 static final String ROOT_NAME = "long-chromosome";
0450
0451 /**
0452 * Return the default long allele writer for the
0453 * {@code IntegerChromosome}.
0454 *
0455 * @return the default long allele writer
0456 */
0457 public static Writer<Long> alleleWriter() {
0458 return Writer.text();
0459 }
0460
0461 /**
0462 * Return a {@link Writer} for {@link io.jenetics.LongChromosome}
0463 * objects.
0464 *
0465 * @param alleleWriter the allele writer used for writing the long
0466 * allele. Might be useful for using different long
0467 * <i>encodings</i>.
0468 * @return a chromosome writer
0469 * @throws NullPointerException if the given {@code alleleWriter} is
0470 * {@code null}
0471 */
0472 public static Writer<io.jenetics.LongChromosome>
0473 writer(final Writer<? super Long> alleleWriter) {
0474 return BoundedChromosome.<
0475 Long,
0476 LongGene,
0477 io.jenetics.LongChromosome
0478 >writer(ROOT_NAME, alleleWriter);
0479 }
0480
0481 /**
0482 * Return a {@link Writer} for {@link io.jenetics.LongChromosome}
0483 * objects.
0484 *
0485 * @return a chromosome writer
0486 */
0487 public static Writer<io.jenetics.LongChromosome> writer() {
0488 return writer(alleleWriter());
0489 }
0490
0491 /**
0492 * Write the given {@link io.jenetics.LongChromosome} to the given
0493 * output stream.
0494 *
0495 * @param out the target output stream
0496 * @param data the chromosome to write
0497 * @param indent the XML level indentation
0498 * @throws XMLStreamException if an error occurs while writing the
0499 * chromosome
0500 * @throws NullPointerException if the {@code chromosome} or output
0501 * stream is {@code null}
0502 */
0503 public static void write(
0504 final OutputStream out,
0505 final io.jenetics.LongChromosome data,
0506 final String indent
0507 )
0508 throws XMLStreamException
0509 {
0510 requireNonNull(data);
0511 requireNonNull(out);
0512
0513 try (var xml = XML.writer(out, indent)) {
0514 writer().write(xml, data);
0515 }
0516 }
0517
0518 /**
0519 * Write the given {@link io.jenetics.LongChromosome} to the given
0520 * output stream.
0521 *
0522 * @param out the target output stream
0523 * @param data the chromosome to write
0524 * @throws XMLStreamException if an error occurs while writing the
0525 * chromosome
0526 * @throws NullPointerException if the {@code chromosome} or output
0527 * stream is {@code null}
0528 */
0529 public static void write(
0530 final OutputStream out,
0531 final io.jenetics.LongChromosome data
0532 )
0533 throws XMLStreamException
0534 {
0535 write(out, data, null);
0536 }
0537 }
0538
0539 /**
0540 * This class contains static writer methods for
0541 * {@link io.jenetics.DoubleChromosome} objects.
0542 * <p>
0543 * <b>Writer code</b>
0544 * <pre>{@code
0545 * final DoubleChromosome value = DoubleChromosome.of(0.0, 1.0, 3);
0546 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) {
0547 * Writers.DoubleChromosome.writer().write(value, xml);
0548 * }
0549 * }</pre>
0550 *
0551 * <b>XML output</b>
0552 * <pre> {@code
0553 * <double-chromosome length="3">
0554 * <min>0.0</min>
0555 * <max>1.0</max>
0556 * <alleles>
0557 * <allele>0.27251556008507416</allele>
0558 * <allele>0.003140816229067145</allele>
0559 * <allele>0.43947528327497376</allele>
0560 * </alleles>
0561 * </double-chromosome>
0562 * }</pre>
0563 */
0564 public static final class DoubleChromosome
0565 //extends WriterProvider<io.jenetics.DoubleChromosome>
0566 {
0567 private DoubleChromosome() {}
0568
0569 static final String ROOT_NAME = "double-chromosome";
0570
0571 /**
0572 * Return the default double allele writer for the
0573 * {@code DoubleChromosome}.
0574 *
0575 * @return the default double allele writer
0576 */
0577 public static Writer<Double> alleleWriter() {
0578 return text().map(Object::toString);
0579 }
0580
0581 /**
0582 * Return a {@link Writer} for {@link io.jenetics.DoubleChromosome}
0583 * objects.
0584 *
0585 * @param alleleWriter the allele writer used for writing the long
0586 * allele. Might be useful for using different long
0587 * <i>encodings</i>.
0588 * @return a chromosome writer
0589 * @throws NullPointerException if the given {@code alleleWriter} is
0590 * {@code null}
0591 */
0592 public static Writer<io.jenetics.DoubleChromosome>
0593 writer(final Writer<? super Double> alleleWriter) {
0594 return BoundedChromosome.<
0595 Double,
0596 DoubleGene,
0597 io.jenetics.DoubleChromosome
0598 >writer(ROOT_NAME, alleleWriter);
0599 }
0600
0601 /**
0602 * Return a {@link Writer} for {@link io.jenetics.DoubleChromosome}
0603 * objects.
0604 *
0605 * @return a chromosome writer
0606 */
0607 public static Writer<io.jenetics.DoubleChromosome> writer() {
0608 return writer(alleleWriter());
0609 }
0610
0611 public Class<io.jenetics.DoubleChromosome> type() {
0612 return io.jenetics.DoubleChromosome.class;
0613 }
0614
0615 /**
0616 * Write the given {@link io.jenetics.DoubleChromosome} to the given
0617 * output stream.
0618 *
0619 * @param out the target output stream
0620 * @param data the chromosome to write
0621 * @param indent the XML level indentation
0622 * @throws XMLStreamException if an error occurs while writing the
0623 * chromosome
0624 * @throws NullPointerException if the {@code chromosome} or output
0625 * stream is {@code null}
0626 */
0627 public static void write(
0628 final OutputStream out,
0629 final io.jenetics.DoubleChromosome data,
0630 final String indent
0631 )
0632 throws XMLStreamException
0633 {
0634 requireNonNull(data);
0635 requireNonNull(out);
0636
0637 try (var xml = XML.writer(out, indent)) {
0638 writer().write(xml, data);
0639 }
0640 }
0641
0642 /**
0643 * Write the given {@link io.jenetics.DoubleChromosome} to the given
0644 * output stream.
0645 *
0646 * @param out the target output stream
0647 * @param data the chromosome to write
0648 * @throws XMLStreamException if an error occurs while writing the
0649 * chromosome
0650 * @throws NullPointerException if the {@code chromosome} or output
0651 * stream is {@code null}
0652 */
0653 public static void write(
0654 final OutputStream out,
0655 final io.jenetics.DoubleChromosome data
0656 )
0657 throws XMLStreamException
0658 {
0659 write(out, data, null);
0660 }
0661 }
0662
0663 /**
0664 * This class contains static writer methods for
0665 * {@link io.jenetics.PermutationChromosome} objects.
0666 * <p>
0667 * <b>Writer code</b>
0668 * <pre>{@code
0669 * final PermutationChromosome<Integer> value =
0670 * PermutationChromosome.ofInteger(5)
0671 *
0672 * final Writer<PermutationChromosome<Integer> writer =
0673 * Writers.PermutationChromosome.writer();
0674 *
0675 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) {
0676 * Writers.PermutationChromosome.writer().write(value, xml);
0677 * }
0678 * }</pre>
0679 *
0680 * <b>XML output</b>
0681 * <pre> {@code
0682 * <permutation-chromosome length="5">
0683 * <valid-alleles type="java.lang.Integer">
0684 * <allele>0</allele>
0685 * <allele>1</allele>
0686 * <allele>2</allele>
0687 * <allele>3</allele>
0688 * <allele>4</allele>
0689 * </valid-alleles>
0690 * <order>2 1 3 5 4</order>
0691 * </permutation-chromosome>
0692 * }</pre>
0693 */
0694 public static final class PermutationChromosome {
0695 private PermutationChromosome() {}
0696
0697 static final String ROOT_NAME = "permutation-chromosome";
0698 static final String LENGTH_NAME = "length";
0699 static final String VALID_ALLELES_NAME = "valid-alleles";
0700 static final String ALLELE_NAME = "allele";
0701 static final String ORDER_NAME = "order";
0702
0703 /**
0704 * Create a writer for permutation-chromosomes. How to write the valid
0705 * alleles is defined by the given {@link Writer}.
0706 *
0707 * @param alleleWriter the allele writer
0708 * @param <A> the allele type
0709 * @return a new permutation chromosome writer
0710 * @throws NullPointerException if the given allele {@code writer} is
0711 * {@code null}
0712 */
0713 public static <A> Writer<io.jenetics.PermutationChromosome<A>>
0714 writer(final Writer<? super A> alleleWriter) {
0715 return Writer.<io.jenetics.PermutationChromosome<A>>elem(
0716 ROOT_NAME,
0717 attr(LENGTH_NAME).map(io.jenetics.PermutationChromosome::length),
0718 elem(VALID_ALLELES_NAME,
0719 attr("type").map(PermutationChromosome::toAlleleTypeName),
0720 Writer.<A>elems(ALLELE_NAME, alleleWriter)
0721 .map(io.jenetics.PermutationChromosome::validAlleles)
0722 ),
0723 elem(ORDER_NAME, text())
0724 .map(ch -> ch.stream()
0725 .map(g -> Integer.toString(g.alleleIndex()))
0726 .collect(Collectors.joining(" ")))
0727 );
0728 }
0729
0730 private static String toAlleleTypeName(
0731 final io.jenetics.PermutationChromosome<?> ch
0732 ) {
0733 return ch.gene().allele().getClass().getCanonicalName();
0734 }
0735
0736 /**
0737 * Create a writer for permutation-chromosomes. The valid alleles are
0738 * serialized by calling the {@link Object#toString()} method. Calling
0739 * this method is equivalent with:
0740 * <pre>{@code
0741 * final Writer<PermutationChromosome<Double> writer =
0742 * PermutationChromosome.write(text().map(Objects::toString));
0743 * }</pre>
0744 *
0745 * Example output:
0746 * <pre> {@code
0747 * <permutation-chromosome length="15">
0748 * <valid-alleles type="java.lang.Double">
0749 * <allele>0.27251556008507416</allele>
0750 * <allele>0.003140816229067145</allele>
0751 * <allele>0.43947528327497376</allele>
0752 * <allele>0.10654807463069327</allele>
0753 * <allele>0.19696530915810317</allele>
0754 * <allele>0.7450003838065538</allele>
0755 * <allele>0.5594416969271359</allele>
0756 * <allele>0.02823782430152355</allele>
0757 * <allele>0.5741102315010789</allele>
0758 * <allele>0.4533651041367144</allele>
0759 * <allele>0.811148141800367</allele>
0760 * <allele>0.5710456351848858</allele>
0761 * <allele>0.30166768355230955</allele>
0762 * <allele>0.5455492865240272</allele>
0763 * <allele>0.21068427527733102</allele>
0764 * </valid-alleles>
0765 * <order>13 12 4 6 8 14 7 2 11 5 3 0 9 10 1</order>
0766 * </permutation-chromosome>
0767 * }</pre>
0768 *
0769 * @param <A> the allele type
0770 * @return a new permutation chromosome writer
0771 */
0772 public static <A> Writer<io.jenetics.PermutationChromosome<A>> writer() {
0773 return writer(text());
0774 }
0775
0776 /**
0777 * Write the given {@link io.jenetics.PermutationChromosome} to the
0778 * given output stream.
0779 *
0780 * @param <A> the allele type
0781 * @param out the target output stream
0782 * @param data the chromosome to write
0783 * @param indent the XML level indentation
0784 * @throws XMLStreamException if an error occurs while writing the
0785 * chromosome
0786 * @throws NullPointerException if the {@code chromosome} or output
0787 * stream is {@code null}
0788 */
0789 public static <A> void write(
0790 final OutputStream out,
0791 final io.jenetics.PermutationChromosome<A> data,
0792 final String indent
0793 )
0794 throws XMLStreamException
0795 {
0796 requireNonNull(data);
0797 requireNonNull(out);
0798
0799 try (var writer = XML.writer(out, indent)) {
0800 PermutationChromosome.<A>writer().write(writer, data);
0801 }
0802 }
0803
0804 /**
0805 * Write the given {@link io.jenetics.PermutationChromosome} to the
0806 * given output stream.
0807 *
0808 * @param <A> the allele type
0809 * @param out the target output stream
0810 * @param data the chromosome to write
0811 * @param indent the XML level indentation
0812 * @param alleleWriter the allele writer of the permutation chromosome
0813 * @throws XMLStreamException if an error occurs while writing the
0814 * chromosome
0815 * @throws NullPointerException if the {@code chromosome} or output
0816 * stream is {@code null}
0817 */
0818 public static <A> void write(
0819 final OutputStream out,
0820 final io.jenetics.PermutationChromosome<A> data,
0821 final String indent,
0822 final Writer<? super A> alleleWriter
0823 )
0824 throws XMLStreamException
0825 {
0826 requireNonNull(data);
0827 requireNonNull(alleleWriter);
0828 requireNonNull(out);
0829
0830 try (var xml = XML.writer(out, indent)) {
0831 PermutationChromosome.<A>writer(alleleWriter)
0832 .write(xml, data);
0833 }
0834 }
0835
0836 /**
0837 * Write the given {@link io.jenetics.PermutationChromosome} to the
0838 * given output stream.
0839 *
0840 * @param <A> the allele type
0841 * @param out the target output stream
0842 * @param data the chromosome to write
0843 * @throws XMLStreamException if an error occurs while writing the
0844 * chromosome
0845 * @throws NullPointerException if the {@code chromosome} or output
0846 * stream is {@code null}
0847 */
0848 public static <A> void write(
0849 final OutputStream out,
0850 final io.jenetics.PermutationChromosome<A> data
0851 )
0852 throws XMLStreamException
0853 {
0854 write(out, data, null, text());
0855 }
0856
0857 /**
0858 * Write the given {@link io.jenetics.PermutationChromosome} to the
0859 * given output stream.
0860 *
0861 * @param <A> the allele type
0862 * @param out the target output stream
0863 * @param data the chromosome to write
0864 * @param alleleWriter the allele writer used to write the chromosome
0865 * alleles
0866 * @throws XMLStreamException if an error occurs while writing the
0867 * chromosome
0868 * @throws NullPointerException if the {@code chromosome} or output
0869 * stream is {@code null}
0870 */
0871 public static <A> void write(
0872 final OutputStream out,
0873 final io.jenetics.PermutationChromosome<A> data,
0874 final Writer<? super A> alleleWriter
0875 )
0876 throws XMLStreamException
0877 {
0878 write(out, data, null, alleleWriter);
0879 }
0880
0881 }
0882
0883 /**
0884 * This class contains static writer methods for
0885 * {@link io.jenetics.Genotype} objects.
0886 * <p>
0887 * <b>Writer code</b>
0888 * <pre>{@code
0889 * final Genotype<DoubleGene> gt = Genotype.of(
0890 * DoubleChromosome.of(0.0, 1.0, 3),
0891 * DoubleChromosome.of(0.0, 1.0, 2)
0892 * );
0893 * final Writer<Genotype<DoubleGene>> writer =
0894 * Writers.Genotype.writer(Writers.DoubleChromosome.writer());
0895 *
0896 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) {
0897 * writer.write(value, xml);
0898 * }
0899 * }</pre>
0900 *
0901 * <b>XML output</b>
0902 * <pre> {@code
0903 * <genotype length="2" ngenes="5">
0904 * <double-chromosome length="3">
0905 * <min>0.0</min>
0906 * <max>1.0</max>
0907 * <alleles>
0908 * <allele>0.27251556008507416</allele>
0909 * <allele>0.003140816229067145</allele>
0910 * <allele>0.43947528327497376</allele>
0911 * </alleles>
0912 * </double-chromosome>
0913 * <double-chromosome length="2">
0914 * <min>0.0</min>
0915 * <max>1.0</max>
0916 * <alleles>
0917 * <allele>0.4026521545744768</allele>
0918 * <allele>0.36137605952663554</allele>
0919 * <alleles>
0920 * </double-chromosome>
0921 * </genotype>
0922 * }</pre>
0923 */
0924 public static final class Genotype {
0925 private Genotype() {}
0926
0927 static final String ROOT_NAME = "genotype";
0928 static final String LENGTH_NAME = "length";
0929 static final String NGENES_NAME = "ngenes";
0930
0931 /**
0932 * Create a writer for genotypes of arbitrary chromosomes. How to write the
0933 * genotypes chromosomes is defined by the given {@link Writer}.
0934 *
0935 * @param writer the chromosome writer
0936 * @param <A> the allele type
0937 * @param <G> the gene type
0938 * @param <C> the chromosome type
0939 * @return a new genotype writer
0940 * @throws NullPointerException if the given chromosome {@code writer} is
0941 * {@code null}
0942 */
0943 public static <
0944 A,
0945 G extends Gene<A, G>,
0946 C extends Chromosome<G>
0947 >
0948 Writer<io.jenetics.Genotype<G>> writer(final Writer<? super C> writer) {
0949 return elem(
0950 ROOT_NAME,
0951 attr(LENGTH_NAME).map(io.jenetics.Genotype::length),
0952 attr(NGENES_NAME).map(io.jenetics.Genotype::geneCount),
0953 elems(writer).map(gt -> cast(ISeq.of(gt)))
0954 );
0955 }
0956
0957 @SuppressWarnings("unchecked")
0958 private static <A, B> B cast(final A value) {
0959 return (B)value;
0960 }
0961
0962 /**
0963 * Write the given {@link io.jenetics.Genotype} to the given output
0964 * stream.
0965 *
0966 * @param <A> the allele type
0967 * @param <G> the gene type
0968 * @param <C> the chromosome type
0969 * @param out the target output stream
0970 * @param data the genotype to write
0971 * @param indent the XML level indentation
0972 * @param chromosomeWriter the chromosome writer used to write the
0973 * genotypes
0974 * @throws XMLStreamException if an error occurs while writing the
0975 * chromosome
0976 * @throws NullPointerException if the one of the arguments is
0977 * {@code null}
0978 */
0979 public static <
0980 A,
0981 G extends Gene<A, G>,
0982 C extends Chromosome<G>
0983 >
0984 void write(
0985 final OutputStream out,
0986 final io.jenetics.Genotype<G> data,
0987 final String indent,
0988 final Writer<? super C> chromosomeWriter
0989 )
0990 throws XMLStreamException
0991 {
0992 requireNonNull(data);
0993 requireNonNull(chromosomeWriter);
0994 requireNonNull(out);
0995
0996 try (var writer = XML.writer(out, indent)) {
0997 Genotype.<A, G, C>writer(chromosomeWriter).write(writer, data);
0998 }
0999 }
1000
1001 /**
1002 * Write the given {@link io.jenetics.Genotype} to the given output
1003 * stream.
1004 *
1005 * @param <A> the allele type
1006 * @param <G> the gene type
1007 * @param <C> the chromosome type
1008 * @param out the target output stream
1009 * @param data the genotype to write
1010 * @param chromosomeWriter the chromosome writer used to write the
1011 * genotypes
1012 * @throws XMLStreamException if an error occurs while writing the
1013 * chromosome
1014 * @throws NullPointerException if the one of the arguments is
1015 * {@code null}
1016 */
1017 public static <
1018 A,
1019 G extends Gene<A, G>,
1020 C extends Chromosome<G>
1021 >
1022 void write(
1023 final OutputStream out,
1024 final io.jenetics.Genotype<G> data,
1025 final Writer<? super C> chromosomeWriter
1026 )
1027 throws XMLStreamException
1028 {
1029 requireNonNull(data);
1030 requireNonNull(chromosomeWriter);
1031 requireNonNull(out);
1032
1033 try (var xml = XML.writer(out)) {
1034 Genotype.<A, G, C>writer(chromosomeWriter).write(xml, data);
1035 }
1036 }
1037
1038 }
1039
1040 /**
1041 * This class contains static writer methods for
1042 * {@link io.jenetics.Genotype} objects.
1043 * <p>
1044 * <b>Writer code</b>
1045 * <pre>{@code
1046 * final Genotype<DoubleGene> gt = Genotype.of(
1047 * DoubleChromosome.of(0.0, 1.0, 3),
1048 * DoubleChromosome.of(0.0, 1.0, 2)
1049 * );
1050 *
1051 * final Writer<Collection<Genotype<DoubleGene>>> writer =
1052 * Writers.Genotypes.writer(Writers.DoubleChromosome.writer());
1053 *
1054 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) {
1055 * writer.write(asList(value), xml);
1056 * }
1057 * }</pre>
1058 *
1059 * <pre> {@code
1060 * <genotypes length="1">
1061 * <genotype length="2" ngenes="5">
1062 * <double-chromosome length="3">
1063 * <min>0.0</min>
1064 * <max>1.0</max>
1065 * <alleles>
1066 * <allele>0.27251556008507416</allele>
1067 * <allele>0.003140816229067145</allele>
1068 * <allele>0.43947528327497376</allele>
1069 * </alleles>
1070 * </double-chromosome>
1071 * <double-chromosome length="2">
1072 * <min>0.0</min>
1073 * <max>1.0</max>
1074 * <alleles>
1075 * <allele>0.4026521545744768</allele>
1076 * <allele>0.36137605952663554</allele>
1077 * <alleles>
1078 * </double-chromosome>
1079 * </genotype>
1080 * </genotypes>
1081 * }</pre>
1082 */
1083 public static final class Genotypes {
1084 private Genotypes() {}
1085
1086 static final String ROOT_NAME = "genotypes";
1087 static final String LENGTH_NAME = "length";
1088
1089 /**
1090 * Create a writer for genotypes of arbitrary chromosomes. How to write the
1091 * genotypes chromosomes is defined by the given {@link Writer}. The
1092 * following writer allows to write double-gene chromosomes:
1093 * <pre>{@code
1094 * final Writer<Collection<Genotype<DoubleGene>>> writer =
1095 * Writers.Genotypes.writer(Writers.DoubleChromosome.writer());
1096 * }</pre>
1097 *
1098 * @param writer the chromosome writer
1099 * @param <A> the allele type
1100 * @param <G> the gene type
1101 * @param <C> the chromosome type
1102 * @return a new genotype writer
1103 * @throws NullPointerException if the given chromosome {@code writer} is
1104 * {@code null}
1105 */
1106 public static <
1107 A,
1108 G extends Gene<A, G>,
1109 C extends Chromosome<G>
1110 >
1111 Writer<Collection<io.jenetics.Genotype<G>>>
1112 writer(final Writer<? super C> writer) {
1113 return elem(
1114 ROOT_NAME,
1115 attr(LENGTH_NAME).map(Collection::size),
1116 elems(Genotype.writer(writer))
1117 );
1118 }
1119
1120 /**
1121 * Write the given {@link io.jenetics.Genotype} to the given output
1122 * stream.
1123 *
1124 * @param <A> the allele type
1125 * @param <G> the gene type
1126 * @param <C> the chromosome type
1127 * @param out the target output stream
1128 * @param data the genotypes to write
1129 * @param indent the XML level indentation
1130 * @param chromosomeWriter the chromosome writer used to write the
1131 * genotypes
1132 * @throws XMLStreamException if an error occurs while writing the
1133 * chromosome
1134 * @throws NullPointerException if the one of the arguments is
1135 * {@code null}
1136 */
1137 public static <
1138 A,
1139 G extends Gene<A, G>,
1140 C extends Chromosome<G>
1141 >
1142 void write(
1143 final OutputStream out,
1144 final Collection<io.jenetics.Genotype<G>> data,
1145 final String indent,
1146 final Writer<? super C> chromosomeWriter
1147 )
1148 throws XMLStreamException
1149 {
1150 requireNonNull(data);
1151 requireNonNull(chromosomeWriter);
1152 requireNonNull(out);
1153
1154 try (var xml = XML.writer(out, indent)) {
1155 Genotypes.<A, G, C>writer(chromosomeWriter).write(xml, data);
1156 }
1157 }
1158
1159 /**
1160 * Write the given {@link io.jenetics.Genotype} to the given output
1161 * stream.
1162 *
1163 * @param <A> the allele type
1164 * @param <G> the gene type
1165 * @param <C> the chromosome type
1166 * @param out the target output stream
1167 * @param data the genotypes to write
1168 * @param chromosomeWriter the chromosome writer used to write the
1169 * genotypes
1170 * @throws XMLStreamException if an error occurs while writing the
1171 * chromosome
1172 * @throws NullPointerException if the one of the arguments is
1173 * {@code null}
1174 */
1175 public static <
1176 A,
1177 G extends Gene<A, G>,
1178 C extends Chromosome<G>
1179 >
1180 void write(
1181 final OutputStream out,
1182 final Collection<io.jenetics.Genotype<G>> data,
1183 final Writer<? super C> chromosomeWriter
1184 )
1185 throws XMLStreamException
1186 {
1187 requireNonNull(data);
1188 requireNonNull(chromosomeWriter);
1189 requireNonNull(out);
1190
1191 try (var xml = XML.writer(out)) {
1192 Genotypes.<A, G, C>writer(chromosomeWriter).write(xml, data);
1193 }
1194 }
1195
1196 }
1197
1198
1199 /**
1200 * Write the given {@link io.jenetics.Genotype} to the given output
1201 * stream.
1202 *
1203 * @see Genotypes#write(OutputStream, Collection, Writer)
1204 *
1205 * @param <A> the allele type
1206 * @param <G> the gene type
1207 * @param <C> the chromosome type
1208 * @param out the target output stream
1209 * @param data the genotypes to write
1210 * @param chromosomeWriter the chromosome writer used to write the
1211 * genotypes
1212 * @throws XMLStreamException if an error occurs while writing the
1213 * chromosome
1214 * @throws NullPointerException if the one of the arguments is
1215 * {@code null}
1216 */
1217 public static <
1218 A,
1219 G extends Gene<A, G>,
1220 C extends Chromosome<G>
1221 >
1222 void write(
1223 final OutputStream out,
1224 final Collection<io.jenetics.Genotype<G>> data,
1225 final Writer<? super C> chromosomeWriter
1226 )
1227 throws XMLStreamException
1228 {
1229 Genotypes.write(out, data, chromosomeWriter);
1230 }
1231
1232 }
|