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

marytts.cart.DirectedGraph Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2009 DFKI GmbH.
 * All Rights Reserved.  Use is subject to license terms.
 *
 * This file is part of MARY TTS.
 *
 * MARY TTS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 *
 */

package marytts.cart;

import java.util.Iterator;
import java.util.Properties;

import marytts.features.FeatureDefinition;
import marytts.features.FeatureVector;
import marytts.unitselection.select.Target;
import marytts.util.MaryUtils;

import org.apache.log4j.Logger;

/**
 * A directed graph is a layered structure of nodes, in which there are mother-daughter relationships between the node. There is a
 * single root node. Each node can have multiple daughters and/or multiple mothers. Three types of nodes are allowed:
 * DirectedGraphNode (which can have multiple mothers, a leaf and a decision node), LeafNodes (which carry data), and
 * DecisionNodes (which can have multiple daughters).
 * 
 * @author marc
 *
 */
public class DirectedGraph {
	protected Logger logger = MaryUtils.getLogger(this.getClass().getName());

	protected Node rootNode;

	// knows the index numbers and types of the features used in DecisionNodes
	protected FeatureDefinition featDef;

	protected Properties properties;

	/**
	 * Build a new empty directed graph
	 * 
	 */
	public DirectedGraph() {
	}

	/**
	 * Build a new empty graph with the given feature definition.
	 * 
	 * @param featDef
	 *            the feature definition used for interpreting the meaning of decision node criteria.
	 */
	public DirectedGraph(FeatureDefinition featDef) {
		this(null, featDef);
	}

	/**
	 * Build a new graph with the given node as the root node
	 * 
	 * @param rootNode
	 *            the root node of the graph
	 * @param featDef
	 *            the feature definition used for interpreting the meaning of decision node criteria.
	 */
	public DirectedGraph(Node rootNode, FeatureDefinition featDef) {
		this(rootNode, featDef, null);
	}

	/**
	 * Build a new graph with the given node as the root node
	 * 
	 * @param rootNode
	 *            the root node of the graph
	 * @param featDef
	 *            the feature definition used for interpreting the meaning of decision node criteria.
	 * @param properties
	 *            a generic properties object, which can be used to encode information about the tree and the way the data in it
	 *            should be represented.
	 */
	public DirectedGraph(Node rootNode, FeatureDefinition featDef, Properties properties) {
		this.rootNode = rootNode;
		this.featDef = featDef;
		this.properties = properties;
	}

	public Object interpret(Target t) {
		return interpret(t.getFeatureVector());
	}

	/**
	 * Walk down the graph as far as possible according to the features in fv, and return the data in the leaf node found there.
	 * 
	 * @param fv
	 *            a feature vector which must be consistent with the graph's feature definition. (@see #getFeatureDefinition()).
	 * @return the most specific non-null leaf node data that can be retrieved, or null if there is no non-null leaf node data
	 *         along the fv's path.
	 */
	public Object interpret(FeatureVector fv) {
		return interpret(rootNode, fv);
	}

	/**
	 * Follow the directed graph down to the most specific leaf with data, starting from node n. This is recursively calling
	 * itself.
	 * 
	 * @param n
	 *            n
	 * @param fv
	 *            fv
	 * @return null if n=null, n.getAllData if n.isLeafNode, interpret (next, fv) if next = ((DecisionNode) n).getNextNode(fv),
	 *         data if data != null, interpret(g.getLeafNode(), fv) otherwise
	 */
	protected Object interpret(Node n, FeatureVector fv) {
		if (n == null)
			return null;
		else if (n.isLeafNode()) {
			return n.getAllData();
		} else if (n.isDecisionNode()) {
			Node next = ((DecisionNode) n).getNextNode(fv);
			return interpret(next, fv);
		} else if (n.isDirectedGraphNode()) {
			DirectedGraphNode g = (DirectedGraphNode) n;
			Object data = interpret(g.getDecisionNode(), fv);
			if (data != null) { // OK, found something more specific
				return data;
			}
			return interpret(g.getLeafNode(), fv);
		}
		throw new IllegalArgumentException("Unknown node type: " + n.getClass());
	}

	/**
	 * Return an iterator which returns all nodes in the tree exactly once. Search is done in a depth-first way.
	 * 
	 * @return a new NodeIterator(Node)
	 */
	public Iterator getNodeIterator() {
		return new NodeIterator(this, true, true, true);
	}

	/**
	 * Return an iterator which returns all leaf nodes in the tree exactly once. Search is done in a depth-first way.
	 * 
	 * @return a new NodeIterator(LeafNode)
	 */
	public Iterator getLeafNodeIterator() {
		return new NodeIterator(this, true, false, false);
	}

	/**
	 * Return an iterator which returns all decision nodes in the tree exactly once. Search is done in a depth-first way.
	 * 
	 * @return a new NodeIterator(DecisionNode)
	 */
	public Iterator getDecisionNodeIterator() {
		return new NodeIterator(this, false, true, false);
	}

	/**
	 * Return an iterator which returns all directed graph nodes in the tree exactly once. Search is done in a depth-first way.
	 * 
	 * @return a new NodeIterator(DirectedGraphNode)
	 */
	public Iterator getDirectedGraphNodeIterator() {
		return new NodeIterator(this, false, false, true);
	}

	/**
	 * A representation of the corresponding node iterator that can be used in extended for() statements.
	 * 
	 * @return a new Iterable(Node)
	 */
	public Iterable getNodes() {
		return new Iterable() {
			public Iterator iterator() {
				return getNodeIterator();
			}
		};
	}

	/**
	 * A representation of the corresponding node iterator that can be used in extended for() statements.
	 * 
	 * @return a new Iterable(LeafNode)
	 */
	public Iterable getLeafNodes() {
		return new Iterable() {
			public Iterator iterator() {
				return getLeafNodeIterator();
			}
		};
	}

	/**
	 * A representation of the corresponding node iterator that can be used in extended for() statements.
	 * 
	 * @return a new Iterable(DecisionNode)
	 */
	public Iterable getDecisionNodes() {
		return new Iterable() {
			public Iterator iterator() {
				return getDecisionNodeIterator();
			}
		};
	}

	/**
	 * A representation of the corresponding node iterator that can be used in extended for() statements.
	 * 
	 * @return a new Iterable(DirectedGraphNode)
	 */
	public Iterable getDirectedGraphNodes() {
		return new Iterable() {
			public Iterator iterator() {
				return getDirectedGraphNodeIterator();
			}
		};
	}

	/**
	 * Get the properties object associated with this tree, or null if there is no such object.
	 * 
	 * @return the properties
	 */
	public Properties getProperties() {
		return properties;
	}

	/**
	 * Get the root node of this CART
	 * 
	 * @return the root node
	 */
	public Node getRootNode() {
		return rootNode;
	}

	/**
	 * Set the root node of this CART
	 * 
	 * @param rNode
	 *            root node
	 */
	public void setRootNode(Node rNode) {
		rootNode = rNode;
	}

	public FeatureDefinition getFeatureDefinition() {
		return featDef;
	}

	/**
	 * Get the number of nodes in this CART
	 * 
	 * @return the number of nodes
	 */
	public int getNumNodes() {
		if (rootNode == null)
			return 0;
		return rootNode.getNumberOfNodes();
	}

	public String toString() {
		return this.rootNode.toString("");
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy