0001 /*
0002 * Java Genetic Algorithm Library (jenetics-5.1.0).
0003 * Copyright (c) 2007-2019 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
0041 import io.jenetics.xml.stream.AutoCloseableXMLStreamWriter;
0042 import io.jenetics.xml.stream.Writer;
0043 import io.jenetics.xml.stream.XML;
0044
0045 /**
0046 * This class contains static fields and methods, for creating chromosome- and
0047 * genotype writers for different gene types.
0048 *
0049 * <pre>{@code
0050 * final Writer<Genotype<BitGene> bgw =
0051 * Writers.Genotype.writer(Writers.BitChromosome.writer()));
0052 *
0053 * final Writer<Genotype<IntegerGene>> igw =
0054 * Writers.Genotype.writer(Writers.IntegerChromosome.writer()));
0055 *
0056 * final Writer<Genotype<DoubleGene>> dgw =
0057 * Writers.Genotype.writer(Writers.DoubleChromosome.writer()));
0058 * }</pre>
0059 *
0060 * This class also contains some helper methods, which makes it easier to write
0061 * Jenetics domain objects to a given output stream.
0062 * <pre>{@code
0063 * final List<Genotype<BitGene>> genotypes = ...;
0064 * try (OutputStream out = Files.newOutputStream(Paths.get("path"))) {
0065 * Writers.write(out, genotypes, Writers.BitChromosome.writer());
0066 * }
0067 * }</pre>
0068 *
0069 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
0070 * @version 3.9
0071 * @since 3.9
0072 */
0073 public final class Writers {
0074 private Writers() {}
0075
0076 /**
0077 * This class contains static writer methods for
0078 * {@link io.jenetics.BitChromosome} objects.
0079 * <p>
0080 * <b>Writer code</b>
0081 * <pre>{@code
0082 * final BitChromosome value = BitChromosome.of(20, 0.5);
0083 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) {
0084 * Writers.BitChromosome.writer().write(value, xml);
0085 * }
0086 * }</pre>
0087 *
0088 * <b>XML output</b>
0089 * <pre> {@code
0090 * <bit-chromosome length="20" ones-probability="0.5">11100011101011001010</bit-chromosome>
0091 * }</pre>
0092 *
0093 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
0094 * @version 3.9
0095 * @since 3.9
0096 */
0097 public static final class BitChromosome {
0098 private BitChromosome() {}
0099
0100 static final String ROOT_NAME = "bit-chromosome";
0101 static final String LENGTH_NAME = "length";
0102 static final String ONES_PROBABILITY_NAME = "ones-probability";
0103
0104 /**
0105 * Return a {@link Writer} for {@link io.jenetics.BitChromosome}
0106 * objects.
0107 *
0108 * @return a chromosome writer
0109 */
0110 public static Writer<io.jenetics.BitChromosome> writer() {
0111 return elem(ROOT_NAME,
0112 attr(LENGTH_NAME).map(io.jenetics.BitChromosome::length),
0113 attr(ONES_PROBABILITY_NAME).map(ch -> ch.getOneProbability()),
0114 text().map(io.jenetics.BitChromosome::toCanonicalString)
0115 );
0116 }
0117
0118 /**
0119 * Write the given {@link io.jenetics.BitChromosome} to the given
0120 * output stream.
0121 *
0122 * @param out the target output stream
0123 * @param data the bit-chromosome to write
0124 * @throws XMLStreamException if an error occurs while writing the
0125 * chromosome
0126 * @throws NullPointerException if one of the given arguments is
0127 * {@code null}
0128 */
0129 public static void write(
0130 final OutputStream out,
0131 final io.jenetics.BitChromosome data
0132 )
0133 throws XMLStreamException
0134 {
0135 requireNonNull(data);
0136 requireNonNull(out);
0137
0138 try (AutoCloseableXMLStreamWriter xml = XML.writer(out)) {
0139 writer().write(xml, data);
0140 }
0141 }
0142 }
0143
0144
0145 /**
0146 * This class contains static writer methods for
0147 * {@link io.jenetics.CharacterChromosome} objects.
0148 * <p>
0149 * <b>Writer code</b>
0150 * <pre>{@code
0151 * final CharacterChromosome value = CharacterChromosome.of("ASDF", CharSeq.of("A-Z"));
0152 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) {
0153 * Writers.CharacterChromosome.writer().write(value, xml);
0154 * }
0155 * }</pre>
0156 *
0157 * <b>XML output</b>
0158 * <pre> {@code
0159 * <character-chromosome length="4">
0160 * <valid-alleles>ABCDEFGHIJKLMNOPQRSTUVWXYZ<valid-alleles>
0161 * <alleles>ASDF</alleles>
0162 * </character-chromosome>
0163 * }</pre>
0164 */
0165 public static final class CharacterChromosome {
0166 private CharacterChromosome() {}
0167
0168 static final String ROOT_NAME = "character-chromosome";
0169 static final String LENGTH_NAME = "length";
0170 static final String VALID_ALLELES_NAME = "valid-alleles";
0171 static final String ALLELES_NAME = "alleles";
0172
0173 /**
0174 * Return a {@link Writer} for {@link io.jenetics.CharacterChromosome}
0175 * objects.
0176 *
0177 * @return a chromosome writer
0178 */
0179 public static Writer<io.jenetics.CharacterChromosome> writer() {
0180 return elem(ROOT_NAME,
0181 attr(LENGTH_NAME).map(io.jenetics.CharacterChromosome::length),
0182 elem(VALID_ALLELES_NAME,
0183 text().map(ch -> ch.getGene().getValidCharacters())),
0184 elem(ALLELES_NAME,
0185 text().map(io.jenetics.CharacterChromosome::toString))
0186 );
0187 }
0188
0189 /**
0190 * Write the given {@link io.jenetics.CharacterChromosome} to the given
0191 * output stream.
0192 *
0193 * @param out the target output stream
0194 * @param data the chromosome to write
0195 * @param indent the XML level indentation
0196 * @throws XMLStreamException if an error occurs while writing the
0197 * chromosome
0198 * @throws NullPointerException if the {@code chromosome} or output
0199 * stream is {@code null}
0200 */
0201 public static void write(
0202 final OutputStream out,
0203 final io.jenetics.CharacterChromosome data,
0204 final String indent
0205 )
0206 throws XMLStreamException
0207 {
0208 requireNonNull(data);
0209 requireNonNull(out);
0210
0211 try (AutoCloseableXMLStreamWriter xml = XML.writer(out, indent)) {
0212 writer().write(xml, data);
0213 }
0214 }
0215
0216 /**
0217 * Write the given {@link io.jenetics.CharacterChromosome} to the given
0218 * output stream.
0219 *
0220 * @param out the target output stream
0221 * @param data the chromosome to write
0222 * @throws XMLStreamException if an error occurs while writing the
0223 * chromosome
0224 * @throws NullPointerException if the {@code chromosome} or output
0225 * stream is {@code null}
0226 */
0227 public static void write(
0228 final OutputStream out,
0229 final io.jenetics.CharacterChromosome data
0230 )
0231 throws XMLStreamException
0232 {
0233 write(out, data, null);
0234 }
0235
0236 }
0237
0238 /**
0239 * This class contains static writer methods for
0240 * {@link io.jenetics.BoundedChromosome} objects.
0241 *
0242 * <p>
0243 * <b>XML template</b>
0244 * <pre> {@code
0245 * <root-name length="3">
0246 * <min>aaa</min>
0247 * <max>zzz</max>
0248 * <alleles>
0249 * <allele>iii</allele>
0250 * <allele>fff</allele>
0251 * <allele>ggg</allele>
0252 * </alleles>
0253 * </root-name>
0254 * }</pre>
0255 */
0256 public static final class BoundedChromosome {
0257 private BoundedChromosome() {}
0258
0259 static final String LENGTH_NAME = "length";
0260 static final String MIN_NAME = "min";
0261 static final String MAX_NAME = "max";
0262 static final String ALLELE_NAME = "allele";
0263 static final String ALLELES_NAME = "alleles";
0264
0265 /**
0266 * Create a bounded chromosome writer with the given configuration.
0267 *
0268 * @param rootName the name of the root element. E.g. {@code int-chromosome}
0269 * @param alleleWriter the XML writer used for the alleles
0270 * @param <A> the allele type
0271 * @param <G> the bounded gene type
0272 * @param <C> the bounded chromosome type
0273 * @return a bounded chromosome XML writer
0274 * @throws NullPointerException if one of the arguments is {@code null}
0275 */
0276 public static <
0277 A extends Comparable<? super A>,
0278 G extends BoundedGene<A, G>,
0279 C extends io.jenetics.BoundedChromosome<A, G>
0280 >
0281 Writer<C> writer(
0282 final String rootName,
0283 final Writer<? super A> alleleWriter
0284 ) {
0285 requireNonNull(rootName);
0286 requireNonNull(alleleWriter);
0287
0288 return elem(rootName,
0289 attr(LENGTH_NAME).map(ch -> ch.length()),
0290 elem(MIN_NAME, alleleWriter.map(ch -> ch.getMin())),
0291 elem(MAX_NAME, alleleWriter.map(ch -> ch.getMax())),
0292 elem(ALLELES_NAME,
0293 elems(ALLELE_NAME, alleleWriter)
0294 .map(ch -> ch.toSeq().map(G::getAllele))
0295 )
0296 );
0297 }
0298 }
0299
0300 /**
0301 * This class contains static writer methods for
0302 * {@link io.jenetics.IntegerChromosome} objects.
0303 * <p>
0304 * <b>Writer code</b>
0305 * <pre>{@code
0306 * final IntegerChromosome value = IntegerChromosome
0307 * .of(Integer.MIN_VALUE, Integer.MAX_VALUE, 3);
0308 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) {
0309 * Writers.IntegerChromosome.writer().write(value, xml);
0310 * }
0311 * }</pre>
0312 *
0313 * <b>XML output</b>
0314 * <pre> {@code
0315 * <int-chromosome length="3">
0316 * <min>-2147483648</min>
0317 * <max>2147483647</max>
0318 * <alleles>
0319 * <allele>-1878762439</allele>
0320 * <allele>-957346595</allele>
0321 * <allele>-88668137</allele>
0322 * </alleles>
0323 * </int-chromosome>
0324 * }</pre>
0325 */
0326 public static final class IntegerChromosome {
0327 private IntegerChromosome() {}
0328
0329 static final String ROOT_NAME = "int-chromosome";
0330
0331 /**
0332 * Return the default integer allele writer for the
0333 * {@code IntegerChromosome}.
0334 *
0335 * @return the default integer allele writer
0336 */
0337 public static Writer<Integer> alleleWriter() {
0338 return text();
0339 }
0340
0341 /**
0342 * Return a {@link Writer} for {@link io.jenetics.IntegerChromosome}
0343 * objects.
0344 *
0345 * @param alleleWriter the allele writer used for writing the integer
0346 * allele. Might be useful for using different integer
0347 * <i>encodings</i>.
0348 * @return a chromosome writer
0349 * @throws NullPointerException if the given {@code alleleWriter} is
0350 * {@code null}
0351 */
0352 public static Writer<io.jenetics.IntegerChromosome>
0353 writer(final Writer<? super Integer> alleleWriter) {
0354 requireNonNull(alleleWriter);
0355
0356 return BoundedChromosome.<
0357 Integer,
0358 IntegerGene,
0359 io.jenetics.IntegerChromosome
0360 >writer(ROOT_NAME, alleleWriter);
0361 }
0362
0363 /**
0364 * Return a {@link Writer} for {@link io.jenetics.IntegerChromosome}
0365 * objects.
0366 *
0367 * @return a chromosome writer
0368 */
0369 public static Writer<io.jenetics.IntegerChromosome> writer() {
0370 return writer(alleleWriter());
0371 }
0372
0373 /**
0374 * Write the given {@link io.jenetics.IntegerChromosome} to the given
0375 * output stream.
0376 *
0377 * @param out the target output stream
0378 * @param data the chromosome to write
0379 * @param indent the XML level indentation
0380 * @throws XMLStreamException if an error occurs while writing the
0381 * chromosome
0382 * @throws NullPointerException if the {@code chromosome} or output
0383 * stream is {@code null}
0384 */
0385 public static void write(
0386 final OutputStream out,
0387 final io.jenetics.IntegerChromosome data,
0388 final String indent
0389 )
0390 throws XMLStreamException
0391 {
0392 requireNonNull(data);
0393 requireNonNull(out);
0394
0395 try (AutoCloseableXMLStreamWriter xml = XML.writer(out, indent)) {
0396 writer().write(xml, data);
0397 }
0398 }
0399
0400 /**
0401 * Write the given {@link io.jenetics.IntegerChromosome} to the given
0402 * output stream.
0403 *
0404 * @param out the target output stream
0405 * @param data the chromosome to write
0406 * @throws XMLStreamException if an error occurs while writing the
0407 * chromosome
0408 * @throws NullPointerException if the {@code chromosome} or output
0409 * stream is {@code null}
0410 */
0411 public static void write(
0412 final OutputStream out,
0413 final io.jenetics.IntegerChromosome data
0414 )
0415 throws XMLStreamException
0416 {
0417 write(out, data, null);
0418 }
0419 }
0420
0421 /**
0422 * This class contains static writer methods for
0423 * {@link io.jenetics.LongChromosome} objects.
0424 * <p>
0425 * <b>Writer code</b>
0426 * <pre>{@code
0427 * final LongChromosome value = LongChromosome
0428 * .of(Long.MIN_VALUE, Long.MAX_VALUE, 3);
0429 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) {
0430 * Writers.LongChromosome.writer().write(value, xml);
0431 * }
0432 * }</pre>
0433 *
0434 * <b>XML output</b>
0435 * <pre> {@code
0436 * <long-chromosome length="3">
0437 * <min>-9223372036854775808</min>
0438 * <max>9223372036854775807</max>
0439 * <alleles>
0440 * <allele>-1345217698116542402</allele>
0441 * <allele>-7144755673073475303</allele>
0442 * <allele>6053786736809578435</allele>
0443 * </alleles>
0444 * </long-chromosome>
0445 * }</pre>
0446 */
0447 public static final class LongChromosome {
0448 private LongChromosome() {}
0449
0450 static final String ROOT_NAME = "long-chromosome";
0451
0452 /**
0453 * Return the default long allele writer for the
0454 * {@code IntegerChromosome}.
0455 *
0456 * @return the default long allele writer
0457 */
0458 public static Writer<Long> alleleWriter() {
0459 return Writer.text();
0460 }
0461
0462 /**
0463 * Return a {@link Writer} for {@link io.jenetics.LongChromosome}
0464 * objects.
0465 *
0466 * @param alleleWriter the allele writer used for writing the long
0467 * allele. Might be useful for using different long
0468 * <i>encodings</i>.
0469 * @return a chromosome writer
0470 * @throws NullPointerException if the given {@code alleleWriter} is
0471 * {@code null}
0472 */
0473 public static Writer<io.jenetics.LongChromosome>
0474 writer(final Writer<? super Long> alleleWriter) {
0475 return BoundedChromosome.<
0476 Long,
0477 LongGene,
0478 io.jenetics.LongChromosome
0479 >writer(ROOT_NAME, alleleWriter);
0480 }
0481
0482 /**
0483 * Return a {@link Writer} for {@link io.jenetics.LongChromosome}
0484 * objects.
0485 *
0486 * @return a chromosome writer
0487 */
0488 public static Writer<io.jenetics.LongChromosome> writer() {
0489 return writer(alleleWriter());
0490 }
0491
0492 /**
0493 * Write the given {@link io.jenetics.LongChromosome} to the given
0494 * output stream.
0495 *
0496 * @param out the target output stream
0497 * @param data the chromosome to write
0498 * @param indent the XML level indentation
0499 * @throws XMLStreamException if an error occurs while writing the
0500 * chromosome
0501 * @throws NullPointerException if the {@code chromosome} or output
0502 * stream is {@code null}
0503 */
0504 public static void write(
0505 final OutputStream out,
0506 final io.jenetics.LongChromosome data,
0507 final String indent
0508 )
0509 throws XMLStreamException
0510 {
0511 requireNonNull(data);
0512 requireNonNull(out);
0513
0514 try (AutoCloseableXMLStreamWriter xml = XML.writer(out, indent)) {
0515 writer().write(xml, data);
0516 }
0517 }
0518
0519 /**
0520 * Write the given {@link io.jenetics.LongChromosome} to the given
0521 * output stream.
0522 *
0523 * @param out the target output stream
0524 * @param data the chromosome to write
0525 * @throws XMLStreamException if an error occurs while writing the
0526 * chromosome
0527 * @throws NullPointerException if the {@code chromosome} or output
0528 * stream is {@code null}
0529 */
0530 public static void write(
0531 final OutputStream out,
0532 final io.jenetics.LongChromosome data
0533 )
0534 throws XMLStreamException
0535 {
0536 write(out, data, null);
0537 }
0538 }
0539
0540 /**
0541 * This class contains static writer methods for
0542 * {@link io.jenetics.DoubleChromosome} objects.
0543 * <p>
0544 * <b>Writer code</b>
0545 * <pre>{@code
0546 * final DoubleChromosome value = DoubleChromosome.of(0.0, 1.0, 3);
0547 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) {
0548 * Writers.DoubleChromosome.writer().write(value, xml);
0549 * }
0550 * }</pre>
0551 *
0552 * <b>XML output</b>
0553 * <pre> {@code
0554 * <double-chromosome length="3">
0555 * <min>0.0</min>
0556 * <max>1.0</max>
0557 * <alleles>
0558 * <allele>0.27251556008507416</allele>
0559 * <allele>0.003140816229067145</allele>
0560 * <allele>0.43947528327497376</allele>
0561 * </alleles>
0562 * </double-chromosome>
0563 * }</pre>
0564 */
0565 public static final class DoubleChromosome
0566 //extends WriterProvider<io.jenetics.DoubleChromosome>
0567 {
0568 private DoubleChromosome() {}
0569
0570 static final String ROOT_NAME = "double-chromosome";
0571
0572 /**
0573 * Return the default double allele writer for the
0574 * {@code DoubleChromosome}.
0575 *
0576 * @return the default double allele writer
0577 */
0578 public static Writer<Double> alleleWriter() {
0579 return text().map(Object::toString);
0580 }
0581
0582 /**
0583 * Return a {@link Writer} for {@link io.jenetics.DoubleChromosome}
0584 * objects.
0585 *
0586 * @param alleleWriter the allele writer used for writing the long
0587 * allele. Might be useful for using different long
0588 * <i>encodings</i>.
0589 * @return a chromosome writer
0590 * @throws NullPointerException if the given {@code alleleWriter} is
0591 * {@code null}
0592 */
0593 public static Writer<io.jenetics.DoubleChromosome>
0594 writer(final Writer<? super Double> alleleWriter) {
0595 return BoundedChromosome.<
0596 Double,
0597 DoubleGene,
0598 io.jenetics.DoubleChromosome
0599 >writer(ROOT_NAME, alleleWriter);
0600 }
0601
0602 /**
0603 * Return a {@link Writer} for {@link io.jenetics.DoubleChromosome}
0604 * objects.
0605 *
0606 * @return a chromosome writer
0607 */
0608 public static Writer<io.jenetics.DoubleChromosome> writer() {
0609 return writer(alleleWriter());
0610 }
0611
0612 public Class<io.jenetics.DoubleChromosome> type() {
0613 return io.jenetics.DoubleChromosome.class;
0614 }
0615
0616 /**
0617 * Write the given {@link io.jenetics.DoubleChromosome} to the given
0618 * output stream.
0619 *
0620 * @param out the target output stream
0621 * @param data the chromosome to write
0622 * @param indent the XML level indentation
0623 * @throws XMLStreamException if an error occurs while writing the
0624 * chromosome
0625 * @throws NullPointerException if the {@code chromosome} or output
0626 * stream is {@code null}
0627 */
0628 public static void write(
0629 final OutputStream out,
0630 final io.jenetics.DoubleChromosome data,
0631 final String indent
0632 )
0633 throws XMLStreamException
0634 {
0635 requireNonNull(data);
0636 requireNonNull(out);
0637
0638 try (AutoCloseableXMLStreamWriter xml = XML.writer(out, indent)) {
0639 writer().write(xml, data);
0640 }
0641 }
0642
0643 /**
0644 * Write the given {@link io.jenetics.DoubleChromosome} to the given
0645 * output stream.
0646 *
0647 * @param out the target output stream
0648 * @param data the chromosome to write
0649 * @throws XMLStreamException if an error occurs while writing the
0650 * chromosome
0651 * @throws NullPointerException if the {@code chromosome} or output
0652 * stream is {@code null}
0653 */
0654 public static void write(
0655 final OutputStream out,
0656 final io.jenetics.DoubleChromosome data
0657 )
0658 throws XMLStreamException
0659 {
0660 write(out, data, null);
0661 }
0662 }
0663
0664 /**
0665 * This class contains static writer methods for
0666 * {@link io.jenetics.PermutationChromosome} objects.
0667 * <p>
0668 * <b>Writer code</b>
0669 * <pre>{@code
0670 * final PermutationChromosome<Integer> value =
0671 * PermutationChromosome.ofInteger(5)
0672 *
0673 * final Writer<PermutationChromosome<Integer> writer =
0674 * Writers.PermutationChromosome.writer();
0675 *
0676 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) {
0677 * Writers.PermutationChromosome.writer().write(value, xml);
0678 * }
0679 * }</pre>
0680 *
0681 * <b>XML output</b>
0682 * <pre> {@code
0683 * <permutation-chromosome length="5">
0684 * <valid-alleles type="java.lang.Integer">
0685 * <allele>0</allele>
0686 * <allele>1</allele>
0687 * <allele>2</allele>
0688 * <allele>3</allele>
0689 * <allele>4</allele>
0690 * </valid-alleles>
0691 * <order>2 1 3 5 4</order>
0692 * </permutation-chromosome>
0693 * }</pre>
0694 */
0695 public static final class PermutationChromosome {
0696 private PermutationChromosome() {}
0697
0698 static final String ROOT_NAME = "permutation-chromosome";
0699 static final String LENGTH_NAME = "length";
0700 static final String VALID_ALLELES_NAME = "valid-alleles";
0701 static final String ALLELE_NAME = "allele";
0702 static final String ORDER_NAME = "order";
0703
0704 /**
0705 * Create a writer for permutation-chromosomes. How to write the valid
0706 * alleles is defined by the given {@link Writer}.
0707 *
0708 * @param alleleWriter the allele writer
0709 * @param <A> the allele type
0710 * @return a new permutation chromosome writer
0711 * @throws NullPointerException if the given allele {@code writer} is
0712 * {@code null}
0713 */
0714 public static <A> Writer<io.jenetics.PermutationChromosome<A>>
0715 writer(final Writer<? super A> alleleWriter) {
0716 return Writer.<io.jenetics.PermutationChromosome<A>>elem(
0717 ROOT_NAME,
0718 attr(LENGTH_NAME).map(io.jenetics.PermutationChromosome::length),
0719 elem(VALID_ALLELES_NAME,
0720 attr("type").map(PermutationChromosome::toAlleleTypeName),
0721 Writer.<A>elems(ALLELE_NAME, alleleWriter)
0722 .map(ch -> ch.getValidAlleles())
0723 ),
0724 elem(ORDER_NAME, text())
0725 .map(ch -> ch.stream()
0726 .map(g -> Integer.toString(g.getAlleleIndex()))
0727 .collect(Collectors.joining(" ")))
0728 );
0729 }
0730
0731 private static String toAlleleTypeName(
0732 final io.jenetics.PermutationChromosome<?> ch
0733 ) {
0734 return ch.getGene().getAllele().getClass().getCanonicalName();
0735 }
0736
0737 /**
0738 * Create a writer for permutation-chromosomes. The valid alleles are
0739 * serialized by calling the {@link Object#toString()} method. Calling
0740 * this method is equivalent with:
0741 * <pre>{@code
0742 * final Writer<PermutationChromosome<Double> writer =
0743 * PermutationChromosome.write(text().map(Objects::toString));
0744 * }</pre>
0745 *
0746 * Example output:
0747 * <pre> {@code
0748 * <permutation-chromosome length="15">
0749 * <valid-alleles type="java.lang.Double">
0750 * <allele>0.27251556008507416</allele>
0751 * <allele>0.003140816229067145</allele>
0752 * <allele>0.43947528327497376</allele>
0753 * <allele>0.10654807463069327</allele>
0754 * <allele>0.19696530915810317</allele>
0755 * <allele>0.7450003838065538</allele>
0756 * <allele>0.5594416969271359</allele>
0757 * <allele>0.02823782430152355</allele>
0758 * <allele>0.5741102315010789</allele>
0759 * <allele>0.4533651041367144</allele>
0760 * <allele>0.811148141800367</allele>
0761 * <allele>0.5710456351848858</allele>
0762 * <allele>0.30166768355230955</allele>
0763 * <allele>0.5455492865240272</allele>
0764 * <allele>0.21068427527733102</allele>
0765 * </valid-alleles>
0766 * <order>13 12 4 6 8 14 7 2 11 5 3 0 9 10 1</order>
0767 * </permutation-chromosome>
0768 * }</pre>
0769 *
0770 * @param <A> the allele type
0771 * @return a new permutation chromosome writer
0772 */
0773 public static <A> Writer<io.jenetics.PermutationChromosome<A>> writer() {
0774 return writer(text());
0775 }
0776
0777 /**
0778 * Write the given {@link io.jenetics.PermutationChromosome} to the
0779 * given output stream.
0780 *
0781 * @param <A> the allele type
0782 * @param out the target output stream
0783 * @param data the chromosome to write
0784 * @param indent the XML level indentation
0785 * @throws XMLStreamException if an error occurs while writing the
0786 * chromosome
0787 * @throws NullPointerException if the {@code chromosome} or output
0788 * stream is {@code null}
0789 */
0790 public static <A> void write(
0791 final OutputStream out,
0792 final io.jenetics.PermutationChromosome<A> data,
0793 final String indent
0794 )
0795 throws XMLStreamException
0796 {
0797 requireNonNull(data);
0798 requireNonNull(out);
0799
0800 try (AutoCloseableXMLStreamWriter writer = XML.writer(out, indent)) {
0801 PermutationChromosome.<A>writer().write(writer, data);
0802 }
0803 }
0804
0805 /**
0806 * Write the given {@link io.jenetics.PermutationChromosome} to the
0807 * given output stream.
0808 *
0809 * @param <A> the allele type
0810 * @param out the target output stream
0811 * @param data the chromosome to write
0812 * @param indent the XML level indentation
0813 * @param alleleWriter the allele writer of the permutation chromosome
0814 * @throws XMLStreamException if an error occurs while writing the
0815 * chromosome
0816 * @throws NullPointerException if the {@code chromosome} or output
0817 * stream is {@code null}
0818 */
0819 public static <A> void write(
0820 final OutputStream out,
0821 final io.jenetics.PermutationChromosome<A> data,
0822 final String indent,
0823 final Writer<? super A> alleleWriter
0824 )
0825 throws XMLStreamException
0826 {
0827 requireNonNull(data);
0828 requireNonNull(alleleWriter);
0829 requireNonNull(out);
0830
0831 try (AutoCloseableXMLStreamWriter xml = XML.writer(out, indent)) {
0832 PermutationChromosome.<A>writer(alleleWriter)
0833 .write(xml, data);
0834 }
0835 }
0836
0837 /**
0838 * Write the given {@link io.jenetics.PermutationChromosome} to the
0839 * given output stream.
0840 *
0841 * @param <A> the allele type
0842 * @param out the target output stream
0843 * @param data the chromosome to write
0844 * @throws XMLStreamException if an error occurs while writing the
0845 * chromosome
0846 * @throws NullPointerException if the {@code chromosome} or output
0847 * stream is {@code null}
0848 */
0849 public static <A> void write(
0850 final OutputStream out,
0851 final io.jenetics.PermutationChromosome<A> data
0852 )
0853 throws XMLStreamException
0854 {
0855 write(out, data, null, text());
0856 }
0857
0858 /**
0859 * Write the given {@link io.jenetics.PermutationChromosome} to the
0860 * given output stream.
0861 *
0862 * @param <A> the allele type
0863 * @param out the target output stream
0864 * @param data the chromosome to write
0865 * @param alleleWriter the allele writer used to write the chromosome
0866 * alleles
0867 * @throws XMLStreamException if an error occurs while writing the
0868 * chromosome
0869 * @throws NullPointerException if the {@code chromosome} or output
0870 * stream is {@code null}
0871 */
0872 public static <A> void write(
0873 final OutputStream out,
0874 final io.jenetics.PermutationChromosome<A> data,
0875 final Writer<? super A> alleleWriter
0876 )
0877 throws XMLStreamException
0878 {
0879 write(out, data, null, alleleWriter);
0880 }
0881
0882 }
0883
0884 /**
0885 * This class contains static writer methods for
0886 * {@link io.jenetics.Genotype} objects.
0887 * <p>
0888 * <b>Writer code</b>
0889 * <pre>{@code
0890 * final Genotype<DoubleGene> gt = Genotype.of(
0891 * DoubleChromosome.of(0.0, 1.0, 3),
0892 * DoubleChromosome.of(0.0, 1.0, 2)
0893 * );
0894 * final Writer<Genotype<DoubleGene>> writer =
0895 * Writers.Genotype.writer(Writers.DoubleChromosome.writer());
0896 *
0897 * try (AutoCloseableXMLStreamWriter xml = XML.writer(System.out, " ")) {
0898 * writer.write(value, xml);
0899 * }
0900 * }</pre>
0901 *
0902 * <b>XML output</b>
0903 * <pre> {@code
0904 * <genotype length="2" ngenes="5">
0905 * <double-chromosome length="3">
0906 * <min>0.0</min>
0907 * <max>1.0</max>
0908 * <alleles>
0909 * <allele>0.27251556008507416</allele>
0910 * <allele>0.003140816229067145</allele>
0911 * <allele>0.43947528327497376</allele>
0912 * </alleles>
0913 * </double-chromosome>
0914 * <double-chromosome length="2">
0915 * <min>0.0</min>
0916 * <max>1.0</max>
0917 * <alleles>
0918 * <allele>0.4026521545744768</allele>
0919 * <allele>0.36137605952663554</allele>
0920 * <alleles>
0921 * </double-chromosome>
0922 * </genotype>
0923 * }</pre>
0924 */
0925 public static final class Genotype {
0926 private Genotype() {}
0927
0928 static final String ROOT_NAME = "genotype";
0929 static final String LENGTH_NAME = "length";
0930 static final String NGENES_NAME = "ngenes";
0931
0932 /**
0933 * Create a writer for genotypes of arbitrary chromosomes. How to write the
0934 * genotypes chromosomes is defined by the given {@link Writer}.
0935 *
0936 * @param writer the chromosome writer
0937 * @param <A> the allele type
0938 * @param <G> the gene type
0939 * @param <C> the chromosome type
0940 * @return a new genotype writer
0941 * @throws NullPointerException if the given chromosome {@code writer} is
0942 * {@code null}
0943 */
0944 public static <
0945 A,
0946 G extends Gene<A, G>,
0947 C extends Chromosome<G>
0948 >
0949 Writer<io.jenetics.Genotype<G>> writer(final Writer<? super C> writer) {
0950 return elem(
0951 ROOT_NAME,
0952 attr(LENGTH_NAME).map(io.jenetics.Genotype<G>::length),
0953 attr(NGENES_NAME).map(io.jenetics.Genotype<G>::geneCount),
0954 elems(writer).map(gt -> cast(gt.toSeq()))
0955 );
0956 }
0957
0958 @SuppressWarnings("unchecked")
0959 private static <A, B> B cast(final A value) {
0960 return (B)value;
0961 }
0962
0963 /**
0964 * Write the given {@link io.jenetics.Genotype} to the given output
0965 * stream.
0966 *
0967 * @param <A> the allele type
0968 * @param <G> the gene type
0969 * @param <C> the chromosome type
0970 * @param out the target output stream
0971 * @param data the genotype to write
0972 * @param indent the XML level indentation
0973 * @param chromosomeWriter the chromosome writer used to write the
0974 * genotypes
0975 * @throws XMLStreamException if an error occurs while writing the
0976 * chromosome
0977 * @throws NullPointerException if the one of the arguments is
0978 * {@code null}
0979 */
0980 public static <
0981 A,
0982 G extends Gene<A, G>,
0983 C extends Chromosome<G>
0984 >
0985 void write(
0986 final OutputStream out,
0987 final io.jenetics.Genotype<G> data,
0988 final String indent,
0989 final Writer<? super C> chromosomeWriter
0990 )
0991 throws XMLStreamException
0992 {
0993 requireNonNull(data);
0994 requireNonNull(chromosomeWriter);
0995 requireNonNull(out);
0996
0997 try (AutoCloseableXMLStreamWriter writer = XML.writer(out, indent)) {
0998 Genotype.<A, G, C>writer(chromosomeWriter).write(writer, data);
0999 }
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 (AutoCloseableXMLStreamWriter 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 * <pre>{@code
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 * }</pre>
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 * genotypes chromosomes is defined by the given {@link Writer}. The
1093 * following writer allows to write double-gene chromosomes:
1094 * <pre>{@code
1095 * final Writer<Collection<Genotype<DoubleGene>>> writer =
1096 * Writers.Genotypes.writer(Writers.DoubleChromosome.writer());
1097 * }</pre>
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 (AutoCloseableXMLStreamWriter 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 (AutoCloseableXMLStreamWriter 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 }
|