package dkohl.bayes.bayesnet;

import java.util.HashMap;
import java.util.LinkedList;

import com.google.common.base.Preconditions;

/**
 * A Graph: G(V, E) implemented as a |V| x |V| matrix.
 * 
 * Just one node type !!!!
 * 
 * @author Daniel Kohlsdorf
 */
public class NamedGraph {

	/**
	 * net[i][j]: variable i is connected to j.
	 */
	private boolean net[][];

	/**
	 * Mapping variable names to positions in the graph's matrix.
	 */
	private HashMap<String, Integer> variable2pos;

	/**
	 * Mapping positions in the graph to variable names.
	 */
	private HashMap<Integer, String> pos2variable;

	/**
	 * Initializes the graph of size: |VariableNames| x |VariableNames|
	 * 
	 * @param variableNames
	 *            The names of the variables
	 */
	public NamedGraph(String variableNames[]) {
		variable2pos = new HashMap<String, Integer>();
		pos2variable = new HashMap<Integer, String>();
		int num_nodes = variableNames.length;

		net = new boolean[num_nodes][num_nodes];

		for (int i = 0; i < num_nodes; i++) {
			variable2pos.put(variableNames[i], i);
			pos2variable.put(i, variableNames[i]);

			for (int j = 0; j < num_nodes; j++) {
				net[i][j] = false;
			}
		}
	}

	/**
	 * Connects two existing vertices in the graph.
	 * 
	 * @param x
	 *            the variable to connect
	 * @param y
	 *            the parent (or other node for undirected graphs)
	 */
	public void connect(String x, String y) {
		Preconditions.checkArgument(variable2pos.containsKey(x),
				"Variable not known: " + x);
		Preconditions.checkArgument(variable2pos.containsKey(y),
				"Variable not known: " + y);

		int variable_index = variable2pos.get(x);
		int bias_index = variable2pos.get(y);

		net[bias_index][variable_index] = true;
	}

	/**
	 * Returns the names of the variable's parents
	 * 
	 * @param variable
	 *            the target variable
	 * @return list of variable names
	 */
	public LinkedList<String> getParents(String variable) {
		Preconditions.checkArgument(variable2pos.containsKey(variable),
				"Variable not known: " + variable);

		LinkedList<String> parents = new LinkedList<String>();
		int variable_pos = variable2pos.get(variable);

		for (int i = 0; i < net.length; i++) {
			if (net[i][variable_pos]) {
				String variableName = pos2variable.get(i);
				parents.add(variableName);
			}
		}
		return parents;
	}

}
