All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.jenetics.ext.util.TreeFormatter Maven / Gradle / Ivy

The newest version!
/*
 * Java Genetic Algorithm Library (jenetics-8.1.0).
 * Copyright (c) 2007-2024 Franz Wilhelmstötter
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Author:
 *    Franz Wilhelmstötter ([email protected])
 */
package io.jenetics.ext.util;

import static java.util.Objects.requireNonNull;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * Definition of different tree formatter strategies.
 *
 * @author Franz Wilhelmstötter
 * @version 5.0
 * @since 5.0
 */
public abstract class TreeFormatter {

	/**
	 * Formats a given tree to a tree string representation.
	 * 
	 *     mul
	 *     ├── div
	 *     │   ├── cos
	 *     │   │   └── 1.0
	 *     │   └── cos
	 *     │       └── π
	 *     └── sin
	 *         └── mul
	 *             ├── 1.0
	 *             └── z
	 *  
*/ public static final TreeFormatter TREE = new TreeFormatter() { @Override public String format( final Tree tree, final Function mapper ) { requireNonNull(tree); requireNonNull(mapper); return toStrings(tree, mapper).stream() .map(StringBuilder::toString) .collect(Collectors.joining("\n")); } private List toStrings( final Tree tree, final Function mapper ) { final List result = new ArrayList<>(); result.add(new StringBuilder().append(mapper.apply(tree.value()))); final Iterator> it = tree.childIterator(); while (it.hasNext()) { final List subtree = toStrings(it.next(), mapper); if (it.hasNext()) { subtree(result, subtree); } else { lastSubtree(result, subtree); } } return result; } private void subtree( final List result, final List subtree ) { final Iterator it = subtree.iterator(); result.add(it.next().insert(0, "├── ")); while (it.hasNext()) { result.add(it.next().insert(0, "│ ")); } } private void lastSubtree( final List result, final List subtree ) { final Iterator it = subtree.iterator(); result.add(it.next().insert(0, "└── ")); while (it.hasNext()) { result.add(it.next().insert(0, " ")); } } }; /** * Formats a given tree to a parentheses string representation. *
	 *     mul(div(cos(1.0),cos(π)),sin(mul(1.0,z)))
	 * 
*/ public static final TreeFormatter PARENTHESES = new TreeFormatter() { @Override public String format( final Tree tree, final Function mapper ) { requireNonNull(tree); requireNonNull(mapper); return ParenthesesTrees.toString(tree, mapper); } }; /** * Formats a given tree to a lisp string representation. *
	 *     (mul (div (cos 1.0) (cos π)) (sin (mul 1.0 z)))
	 * 
*/ public static final TreeFormatter LISP = new TreeFormatter() { @Override public String format( final Tree tree, final Function mapper ) { final CharSequence value = mapper.apply(tree.value()); if (tree.isLeaf()) { return value.toString(); } else { final String children = tree.childStream() .map(child -> format(child, mapper)) .collect(Collectors.joining(" ")); return "(" + value + " " + children + ")"; } } }; /** * A tree formatter for .dot string representations. This strings can be * used to create nice looking tree images. The tree *
	 *     mul(div(cos(1.0),cos(π)),sin(mul(1.0,z)))
	 * 
* is rendered into this dot string *
	 * digraph Tree {
	 *     node_001 [label="div"];
	 *     node_002 [label="cos"];
	 *     node_003 [label="1.0"];
	 *     node_004 [label="cos"];
	 *     node_000 [label="mul"];
	 *     node_009 [label="z"];
	 *     node_005 [label="π"];
	 *     node_006 [label="sin"];
	 *     node_007 [label="mul"];
	 *     node_008 [label="1.0"];
	 *     node_000 -> node_001;
	 *     node_001 -> node_002;
	 *     node_002 -> node_003;
	 *     node_001 -> node_004;
	 *     node_004 -> node_005;
	 *     node_000 -> node_006;
	 *     node_006 -> node_007;
	 *     node_007 -> node_008;
	 *     node_007 -> node_009;
	 * }
	 * 
* This dot string can be rendered into the following graph: *

* Dot-tree *

*/ public static final TreeFormatter DOT = dot("Tree"); protected TreeFormatter() { } /** * Formats the given {@code tree} to its string representation. The given * {@code mapper} is used for converting the node type {@code V} to a string * value. * * @param tree the input tree to format * @param mapper the tree node value mapper * @param the tree node type * @return the string representation of the given {@code tree} * @throws NullPointerException if one of the arguments is {@code null} */ public abstract String format( final Tree tree, final Function mapper ); /** * Formats the given {@code tree} to its string representation. * * @param tree the input tree to format * @return the string representation of the given {@code tree} * @throws NullPointerException if the {@code tree} is {@code null} */ public String format(final Tree tree) { return format(tree, Objects::toString); } /** * A tree formatter for .dot string representations. This strings can be * used to create nice looking tree images. The tree *
	 *     mul(div(cos(1.0),cos(π)),sin(mul(1.0,z)))
	 * 
* is rendered into this dot string *
	 * digraph Tree {
	 *     node_001 [label="div"];
	 *     node_002 [label="cos"];
	 *     node_003 [label="1.0"];
	 *     node_004 [label="cos"];
	 *     node_000 [label="mul"];
	 *     node_009 [label="z"];
	 *     node_005 [label="π"];
	 *     node_006 [label="sin"];
	 *     node_007 [label="mul"];
	 *     node_008 [label="1.0"];
	 *     node_000 -> node_001;
	 *     node_001 -> node_002;
	 *     node_002 -> node_003;
	 *     node_001 -> node_004;
	 *     node_004 -> node_005;
	 *     node_000 -> node_006;
	 *     node_006 -> node_007;
	 *     node_007 -> node_008;
	 *     node_007 -> node_009;
	 * }
	 * 
* This dot string can be rendered into the following graph: *

* Dot-tree *

* * @param treeName the name of the digraph * @return a dot string formatter * @throws NullPointerException if the given tree name is {@code null} */ public static TreeFormatter dot(final String treeName) { return new Dotty(treeName); } /* ************************************************************************* * Some helper classes. * ************************************************************************/ /** * This formatter converts a tree to the .dot representation. */ private static final class Dotty extends TreeFormatter { private final String _name; Dotty(final String name) { _name = requireNonNull(name); } @Override public String format( final Tree tree, final Function mapper ) { return new Helper<>(_name, tree, mapper).draw(); } private static final class Helper { private final String _name; private final Function _mapper; private final Map _labels = new HashMap<>(); private final List _edges = new ArrayList<>(); Helper( final String name, final Tree tree, final Function mapper ) { _name = requireNonNull(name); _mapper = requireNonNull(mapper); init(tree, null, 0); } private int init( final Tree tree, final String parentLabel, final int index ) { int idx = index; final CharSequence value = _mapper.apply(tree.value()); final String label = String.format("node_%03d", idx); _labels.put(label, value); if (parentLabel != null) { _edges.add(parentLabel + " -> " + label); } for (int i = 0; i < tree.childCount(); ++i) { final Tree child = tree.childAt(i); idx = init(child, label, idx + 1); } return idx; } String draw() { final StringBuilder builder = new StringBuilder(); builder .append("digraph ") .append(_name) .append(" {\n"); _labels.forEach((key, value) -> builder .append(" ") .append(key) .append(" [label=\"") .append(value.toString().replace("\"", "\\\"")) .append("\"];\n") ); _edges.forEach(edge -> builder .append(" ") .append(edge) .append(";\n") ); builder.append("}\n"); return builder.toString(); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy