diff --git a/src/main/java/com/syncleus/dann/attributes/hat/AbstractHierarchicalAttributePool.java b/src/main/java/com/syncleus/dann/attributes/hat/AbstractHierarchicalAttributePool.java
index 915107a128d3129de8fca31c35ab055895e8bee6..954a2eda2eb1233ba2fdd01f948ed3347b5fe1b9 100644
--- a/src/main/java/com/syncleus/dann/attributes/hat/AbstractHierarchicalAttributePool.java
+++ b/src/main/java/com/syncleus/dann/attributes/hat/AbstractHierarchicalAttributePool.java
@@ -46,7 +46,7 @@ public abstract class AbstractHierarchicalAttributePool<T> extends AbstractAttri
 	// TODO this has package level access because only a HAT graph should set parents. consider changing this to an event / listener model
 	final HierarchicalAttributePool<T> setParent(final HierarchicalAttributePool<T> newParent)
 	{
-		if( !this.owner.getNodes().contains(newParent) )
+		if( !this.owner.getTargets().contains(newParent) )
 			throw new IllegalArgumentException("newParent is not in owning graph");
 
 		final HierarchicalAttributePool<T> oldParent = this.parent;
diff --git a/src/main/java/com/syncleus/dann/graph/AbstractAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graph/AbstractAdjacencyGraph.java
index a816c1f793649f26ec61ada155a4d651e6a0cecd..a9e9515f4af9f72bfc8a924bffd711fab2590e8a 100644
--- a/src/main/java/com/syncleus/dann/graph/AbstractAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/AbstractAdjacencyGraph.java
@@ -18,22 +18,16 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import com.syncleus.dann.UnexpectedDannError;
-import com.syncleus.dann.graph.context.ContextGraphElement;
+import com.syncleus.dann.graph.search.pathfinding.DijkstraPathFinder;
+import com.syncleus.dann.graph.search.pathfinding.PathFinder;
 import com.syncleus.dann.graph.xml.*;
-import com.syncleus.dann.xml.NameXml;
 import com.syncleus.dann.xml.NamedValueXml;
 import com.syncleus.dann.xml.Namer;
 import com.syncleus.dann.xml.XmlSerializable;
 import org.apache.log4j.Logger;
+import javax.jnlp.ExtendedService;
 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import java.util.*;
 
 /**
  * An AbstractAdjacencyGraph is a Graph implemented using adjacency lists.
@@ -41,19 +35,38 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
  * @param <E> The type of edge for the given node type
  */
 @XmlJavaTypeAdapter( com.syncleus.dann.xml.XmlSerializableAdapter.class )
-public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Graph<N, E>
+public abstract class AbstractAdjacencyGraph<
+/*
+	  	PA,
+	  	N extends PA,
+	  	E extends Edge<? extends N,? extends Edge.Endpoint<? extends N, ? extends N>>,
+	  	NEP extends Graph.NodeEndpoint<? extends N,? extends N,? extends E>,
+	  	EEP extends Graph.EdgeEndpoint<? extends N,? extends E,? extends E>
+*/
+	  	PA,
+	  	N extends PA,
+	  	E extends Edge<N,? extends Edge.Endpoint<N>>,
+	  	NEP extends Graph.NodeEndpoint<PA, N, E>,
+	  	EEP extends Graph.EdgeEndpoint<PA, N, E>
+	  > extends AbstractEdge<PA,Graph.Endpoint<PA,N,E,PA>> implements Graph<PA, N, E, NEP, EEP>
 {
 	private static final Logger LOGGER = Logger.getLogger(AbstractAdjacencyGraph.class);
-	private Set<E> edges;
-	private Map<N, Set<E>> adjacentEdges = new HashMap<N, Set<E>>();
-	private Map<N, List<N>> adjacentNodes = new HashMap<N, List<N>>();
-	private final boolean contextEnabled;
-
-
+//	private Set<E> edges;
+//	private Map<N, Set<E>> adjacentEdges = new HashMap<N, Set<E>>();
+//	private Map<N, List<N>> adjacentNodes = new HashMap<N, List<N>>();
+/*
+	private Set<? extends EdgeEndpoint<? extends Object, N, E, E>> edges;
+	private Map<? extends NodeEndpoint<? extends Object, E, N, N>, Set<E>> adjacentEdges = new HashMap<NodeEndpoint<? extends Object, E, N, N>, Set<E>>();
+	private Map<? extends NodeEndpoint<? extends Object, E, N, N>, List<N>> adjacentNodes = new HashMap<NodeEndpoint<? extends Object, E, N, N>, List<N>>();
+*/
+//	private final boolean contextEnabled;
+
+
+/*
 	/**
 	 * Creates a new AbstractAdjacencyGraph with no edges and no adjacencies.
 	 * nodeContext and edgeContext is enabled.
-	 */
+	 *
 	protected AbstractAdjacencyGraph()
 	{
 		this(true);
@@ -61,30 +74,31 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 
 	/**
 	 * Creates a new AbstractAdjacencyGraph with no edges and no adjacencies.
-	 */
+	 *
 	protected AbstractAdjacencyGraph(final boolean contextEnabled)
 	{
-		this.edges = new HashSet<E>();
-		this.contextEnabled = contextEnabled;
+//		this.edges = new HashSet<E>();
+		this.edges = new HashSet<EdgeEndpoint<? extends Object, N, E, E>>();
+//		this.contextEnabled = contextEnabled;
 	}
 
 	/**
 	 * Creates a new AbstractAdjacencyGraph as a copy of the current Graph.
 	 * nodeContext is enabled.
 	 * @param copyGraph The Graph to copy
-	 */
+	 *
 	protected AbstractAdjacencyGraph(final Graph<N, E> copyGraph)
 	{
-		this(copyGraph.getNodes(), copyGraph.getEdges(), true);
+		this(copyGraph.getTargets(), copyGraph.getEdges(), true);
 	}
 
 	/**
 	 * Creates a new AbstractAdjacencyGraph as a copy of the current Graph.
 	 * @param copyGraph The Graph to copy
-	 */
+	 *
 	protected AbstractAdjacencyGraph(final Graph<N, E> copyGraph, final boolean contextEnabled)
 	{
-		this(copyGraph.getNodes(), copyGraph.getEdges(), contextEnabled);
+		this(copyGraph.getTargets(), copyGraph.getEdges(), contextEnabled);
 	}
 
 	/**
@@ -95,7 +109,7 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 	 *
 	 * @param nodes The set of all nodes
 	 * @param edges The set of all ourEdges
-	 */
+	 *
 	protected AbstractAdjacencyGraph(final Set<N> nodes, final Set<E> edges)
 	{
 		this(nodes, edges, true);
@@ -108,23 +122,23 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 	 *
 	 * @param attemptNodes The set of all nodes
 	 * @param attemptEdges The set of all ourEdges
-	 */
+	 *
 	protected AbstractAdjacencyGraph(final Set<N> attemptNodes, final Set<E> attemptEdges, final boolean contextEnabled)
 	{
 		if(attemptNodes == null)
 			throw new IllegalArgumentException("attemptNodes can not be null");
 		if(attemptEdges == null)
 			throw new IllegalArgumentException("attemptEdges can not be null");
-		//make sure all the edges only connect to contained nodes
+		//make sure all the edges only join to contained nodes
 		for( E attemptEdge : attemptEdges )
-			if( !attemptNodes.containsAll(attemptEdge.getNodes()) )
+			if( !attemptNodes.containsAll(attemptEdge.getTargets()) )
 			    throw new IllegalArgumentException("A node that is an end point in one of the attemptEdges was not in the nodes list");
 
 		this.contextEnabled = contextEnabled;
-
 		//add all the nodes before we worry about edges. check for NodeContext
 		for(final N attemptNode : attemptNodes)
 		{
+
 			// lets see if this ContextEdge will allow itself to join the graph
 			if(this.contextEnabled
 					&& (attemptNode instanceof ContextGraphElement)
@@ -150,10 +164,10 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 
 				this.edges.add(attemptEdge);
 				//populate adjacency maps
-				for(N currentNode : attemptEdge.getNodes())
+				for(N currentNode : attemptEdge.getTargets())
 				{
 					boolean passedCurrent = false;
-					for(N neighborNode : attemptEdge.getNodes())
+					for(N neighborNode : attemptEdge.getTargets())
 					{
 						if( !passedCurrent && (neighborNode == currentNode))
 						{
@@ -184,7 +198,7 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 	/**
 	 * Gets the internal edges of the list.
 	 * @return The set of internal edges
-	 */
+	 *
 	protected Set<E> getInternalEdges()
 	{
 		return this.edges;
@@ -193,7 +207,7 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 	/**
 	 * Gets the map of nodes to their associated set of edges.
 	 * @return The internal adjacency edges to nodes
-	 */
+	 *
 	protected Map<N, Set<E>> getInternalAdjacencyEdges()
 	{
 		return this.adjacentEdges;
@@ -202,7 +216,7 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 	/**
 	 * Gets each node's list of adjacent nodes.
 	 * @return The map of nodes to adjacent nodes
-	 */
+	 *
 	protected Map<N, List<N>> getInternalAdjacencyNodes()
 	{
 		return this.adjacentNodes;
@@ -217,9 +231,9 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 	/**
 	 * Gets all nodes in the map.
 	 * @return The unmodifiable set of nodes
-	 */
+	 *
 	@Override
-	public Set<N> getNodes()
+	public Set<N> getTargets()
 	{
 		return Collections.unmodifiableSet(this.adjacentEdges.keySet());
 	}
@@ -227,7 +241,7 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 	/**
 	 * Gets all edges in the map.
 	 * @return The unmodifiable set of edges
-	 */
+	 *
 	@Override
 	public Set<E> getEdges()
 	{
@@ -238,7 +252,7 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 	 * Gets all edges adjacent to a given node.
 	 * @param node the end point for all edges to retrieve.
 	 * @return The edges adjacent to that node.
-	 */
+	 *
 	@Override
 	public Set<E> getAdjacentEdges(final N node)
 	{
@@ -252,7 +266,7 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 	 * Gets all nodes adjacent to the given node.
 	 * @param node The whose neighbors are to be returned.
 	 * @return All adjacent nodes to the given node
-	 */
+	 *
 	@Override
 	public List<N> getAdjacentNodes(final N node)
 	{
@@ -264,9 +278,9 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 	 * @param node The whose traversable neighbors are to be returned.
 	 * @return The traversable nodes adjacent to the given node
 	 * @see com.syncleus.dann.graph.Edge#getTraversableNodes(Object)
-	 */
+	 *
 	@Override
-	public List<N> getTraversableNodes(final N node)
+	public List<N> getTraversableAdjacentNodes(final N node)
 	{
 		final List<N> traversableNodes = new ArrayList<N>();
 		for(final E adjacentEdge : this.getAdjacentEdges(node))
@@ -279,9 +293,9 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 	 * @param node edges returned will be traversable from this node.
 	 * @return The traversable edges from the given node
 	 * @see com.syncleus.dann.graph.Edge#isTraversable(Object)
-	 */
+	 *
 	@Override
-	public Set<E> getTraversableEdges(final N node)
+	public Set<E> getTraversableAdjacentEdges(final N node)
 	{
 		final Set<E> traversableEdges = new HashSet<E>();
 		for(final E adjacentEdge : this.getAdjacentEdges(node))
@@ -290,97 +304,164 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 		return Collections.unmodifiableSet(traversableEdges);
 	}
 
-	/**
-	 * Adds the given edge to a clone of this object. Returns null if the given
-	 * edge could not be added.
-	 * @param newEdge the edge to add to the cloned graph.
-	 * @return A clone, with the given edge added
-	 */
-	@Override
-	public AbstractAdjacencyGraph<N, E> cloneAdd(final E newEdge)
+	protected boolean add(final E newEdge)
 	{
 		if( newEdge == null )
 			throw new IllegalArgumentException("newEdge can not be null");
-		if( !this.getNodes().containsAll(newEdge.getNodes()) )
+		if( !this.getTargets().containsAll(newEdge.getTargets()) )
 			throw new IllegalArgumentException("newEdge has a node as an end point that is not part of the graph");
 
-		final Set<E> newEdges = new HashSet<E>(this.edges);
-		if( newEdges.add(newEdge) )
+		// if context is enabled lets check if it can join
+		if( this.isContextEnabled() && (newEdge instanceof ContextGraphElement)
+				&& !((ContextGraphElement)newEdge).joiningGraph(this) )
+			return false;
+
+		if( this.getInternalEdges().add(newEdge) )
 		{
-			final Map<N, Set<E>> newAdjacentEdges = new HashMap<N, Set<E>>();
-			for(final Map.Entry<N, Set<E>> neighborEdgeEntry : this.adjacentEdges.entrySet())
-				newAdjacentEdges.put(neighborEdgeEntry.getKey(), new HashSet<E>(neighborEdgeEntry.getValue()));
-			final Map<N, List<N>> newAdjacentNodes = new HashMap<N, List<N>>();
-			for(final Map.Entry<N, List<N>> neighborNodeEntry : this.adjacentNodes.entrySet())
-				newAdjacentNodes.put(neighborNodeEntry.getKey(), new ArrayList<N>(neighborNodeEntry.getValue()));
-
-			for(final N currentNode : newEdge.getNodes())
+			for(final N currentNode : newEdge.getTargets())
 			{
-				newAdjacentEdges.get(currentNode).add(newEdge);
+				this.getInternalAdjacencyEdges().get(currentNode).add(newEdge);
 
-				final List<N> currentAdjacentNodes = new ArrayList<N>(newEdge.getNodes());
-				currentAdjacentNodes.remove(currentNode);
-				for(final N currentAdjacentNode : currentAdjacentNodes)
-					newAdjacentNodes.get(currentNode).add(currentAdjacentNode);
+				final List<N> newAdjacentNodes = new ArrayList<N>(newEdge.getTargets());
+				newAdjacentNodes.remove(currentNode);
+				for(final N newAdjacentNode : newAdjacentNodes)
+					this.getInternalAdjacencyNodes().get(currentNode).add(newAdjacentNode);
 			}
-
-			final AbstractAdjacencyGraph<N, E> copy = this.clone();
-			copy.edges = newEdges;
-			copy.adjacentEdges = newAdjacentEdges;
-			copy.adjacentNodes = newAdjacentNodes;
-			return copy;
+			return true;
 		}
 
-		return null;
+		return false;
 	}
 
-	/**
-	 * Creates a clone of this graph with the given node added.
-	 * NOTE: Returns null.
-	 * @param newNode the node to add to the cloned graph.
-	 * @return null
-	 */
-	@Override
-	public AbstractAdjacencyGraph<N, E> cloneAdd(final N newNode)
+	public boolean add(final N newNode)
 	{
-		// TODO fill this in
-		return null;
-	}
+		if( newNode == null )
+			throw new IllegalArgumentException("newNode can not be null");
 
-	@Override
-	public AbstractAdjacencyGraph<N, E> cloneAdd(final Set<N> newNodes, final Set<E> newEdges)
-	{
-		// TODO fill this in
-		return null;
+		if( this.getInternalAdjacencyEdges().containsKey(newNode) )
+			return false;
+
+		// if context is enabled lets check if it can join
+		if( this.isContextEnabled() && (newNode instanceof ContextGraphElement)
+				&& !((ContextGraphElement)newNode).joiningGraph(this) )
+			return false;
+
+		this.getInternalAdjacencyEdges().put(newNode, new HashSet<E>());
+		this.getInternalAdjacencyNodes().put(newNode, new ArrayList<N>());
+		return true;
 	}
 
-	@Override
-	public AbstractAdjacencyGraph<N, E> cloneRemove(final E edgeToRemove)
+	protected boolean remove(final E edgeToRemove)
 	{
-		// TODO fill this in
-		return null;
+		if( edgeToRemove == null )
+			throw new IllegalArgumentException("removeSynapse can not be null");
+
+		if( !this.getInternalEdges().contains(edgeToRemove) )
+			return false;
+
+		// if context is enabled lets check if it can join
+		if( this.isContextEnabled()
+				&& (edgeToRemove instanceof ContextGraphElement)
+				&& !((ContextGraphElement)edgeToRemove).leavingGraph(this) )
+			return false;
+
+		if( !this.getInternalEdges().remove(edgeToRemove) )
+			throw new IllegalStateException("could not remove edge even though it is present");
+
+		for(final N removeNode : edgeToRemove.getTargets())
+		{
+			this.getInternalAdjacencyEdges().get(removeNode).remove(edgeToRemove);
+
+			final List<N> removeAdjacentNodes = new ArrayList<N>(edgeToRemove.getTargets());
+			removeAdjacentNodes.remove(removeNode);
+			for(final N removeAdjacentNode : removeAdjacentNodes)
+				this.getInternalAdjacencyNodes().get(removeNode).remove(removeAdjacentNode);
+		}
+		return true;
 	}
 
-	@Override
-	public AbstractAdjacencyGraph<N, E> cloneRemove(final N nodeToRemove)
+	protected boolean remove(final N nodeToRemove)
 	{
-		// TODO fill this in
-		return null;
+		if( nodeToRemove == null )
+			throw new IllegalArgumentException("node can not be null");
+
+		if( !this.getInternalAdjacencyEdges().containsKey(nodeToRemove) )
+			return false;
+
+		// if context is enabled lets check if it can join
+		if( this.isContextEnabled()
+				&& (nodeToRemove instanceof ContextGraphElement)
+				&& !((ContextGraphElement)nodeToRemove).leavingGraph(this) )
+			return false;
+
+		final Set<E> removeEdges = this.getInternalAdjacencyEdges().get(nodeToRemove);
+
+		//remove all the edges
+		for(final E removeEdge : removeEdges)
+			this.remove(removeEdge);
+
+		//modify edges by removing the node to remove
+		final Set<E> newEdges = new HashSet<E>();
+		for(final E removeEdge : removeEdges)
+		{
+			E newEdge = (E) removeEdge.disconnect(nodeToRemove);
+			while( (newEdge != null) && (newEdge.getTargets().contains(nodeToRemove)) )
+				newEdge = (E) removeEdge.disconnect(nodeToRemove);
+			if( newEdge != null )
+				newEdges.add(newEdge);
+		}
+
+		//add the modified edges
+		for(final E newEdge : newEdges)
+			this.add(newEdge);
+
+		//remove the node itself
+		this.getInternalAdjacencyEdges().remove(nodeToRemove);
+		this.getInternalAdjacencyNodes().remove(nodeToRemove);
+
+		return true;
 	}
 
-	@Override
-	public AbstractAdjacencyGraph<N, E> cloneRemove(final Set<N> deleteNodes, final Set<E> deleteEdges)
+	protected boolean clear()
 	{
-		// TODO fill this in
-		return null;
+		boolean removedSomething = false;
+
+		//first lets remove all the edges
+		for(E edge : this.getEdges())
+		{
+			//lets just make sure we arent some how getting an we dont actually own, this shouldnt be possible so its
+			//an assert. This ensures that if remove() comes back false it must be because the context didnt allow it.
+			assert this.getInternalEdges().contains(edge);
+
+			if( !this.remove(edge) )
+				throw new IllegalStateException("one of the edges will not allow itself to leave this graph");
+
+			removedSomething = true;
+		}
+
+		//now lets remove all the nodes
+		for(N node : this.getTargets())
+		{
+			//lets just make sure we arent some how getting an we dont actually own, this shouldnt be possible so its
+			//an assert. This ensures that if remove() comes back false it must be because the context didnt allow it.
+			assert ( !this.getInternalAdjacencyEdges().containsKey(node) );
+
+			if( !this.remove(node) )
+				throw new IllegalStateException("one of the nodes will not allow itself to leave this graph");
+
+			removedSomething = true;
+		}
+
+		return removedSomething;
 	}
 
+
 	/**
 	 * Clones the current object.
 	 * @return A clone of the current object, with no changes
-	 */
+	 *
 	@Override
-	public AbstractAdjacencyGraph<N, E> clone()
+	protected AbstractAdjacencyGraph<N, E> clone()
 	{
 		try
 		{
@@ -391,7 +472,7 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 			cloneGraph.adjacentNodes = new HashMap<N, List<N>>();
 
 			//add all the nodes before we worry about edges. check for NodeContext
-			for(N attemptNode : this.getNodes())
+			for(N attemptNode : this.getTargets())
 			{
 				// lets see if this ContextEdge will allow itself to join the graph
 				if(this.contextEnabled
@@ -417,10 +498,10 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 
 					cloneGraph.edges.add(attemptEdge);
 					//populate adjacency maps
-					for(N currentNode : attemptEdge.getNodes())
+					for(N currentNode : attemptEdge.getTargets())
 					{
 						boolean passedCurrent = false;
-						for(N neighborNode : attemptEdge.getNodes())
+						for(N neighborNode : attemptEdge.getTargets())
 						{
 							if( !passedCurrent && (neighborNode == currentNode))
 							{
@@ -455,6 +536,362 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 			throw new UnexpectedDannError("Unexpectedly could not clone graph", caught);
 		}
 	}
+*/
+
+	protected abstract Set<Graph.EdgeEndpoint<PA, N, E>> getAdjacentEdgeEndPoint(Graph.NodeEndpoint<PA, N, E> nodeEndPoint);
+
+	protected PathFinder<N,E> getPathFinder()
+	{
+		return new DijkstraPathFinder<N,E>(this);
+	}
+
+	@Override
+	public Set<N> getNodes()
+	{
+		final Set<N> nodes = new HashSet<N>();
+		for(NEP destinationEndpoint : this.getNodeEndpoints() )
+			nodes.add(destinationEndpoint.getTarget());
+		return Collections.unmodifiableSet(nodes);
+	}
+
+	@Override
+	public Set<E> getEdges()
+	{
+		final Set<E> edges = new HashSet<E>();
+		for(EEP destinationEndpoint : this.getEdgeEndpoints() )
+			edges.add(destinationEndpoint.getTarget());
+		return Collections.unmodifiableSet(edges);
+	}
+
+	@Override
+	public Set<Graph.Endpoint<PA,N,E,PA>> getEndPoints()
+	{
+		final Set<Graph.Endpoint<PA,N,E,PA>> endpoints = new HashSet<Graph.Endpoint<PA,N,E,PA>>();
+		endpoints.addAll(this.getNodeEndpoints());
+		endpoints.addAll(this.getEdgeEndpoints());
+		return Collections.unmodifiableSet(endpoints);
+	}
+
+	@Override
+	public Set<EEP> getEdgeEndpoints(E edge)
+	{
+		Set<EEP> matchingEndpoints  = new HashSet<EEP>();
+		for(final EEP endpoint : this.getEdgeEndpoints() )
+		{
+			if( endpoint.getTarget().equals(edge))
+				matchingEndpoints.add(endpoint);
+		}
+
+		return Collections.unmodifiableSet(matchingEndpoints);
+	}
+
+	@Override
+	public Set<NEP> getNodeEndpoints(N node)
+	{
+		Set<NEP> matchingEndpoints  = new HashSet<NEP>();
+		for(NEP endpoint : this.getNodeEndpoints() )
+		{
+			if( endpoint.getTarget().equals(node))
+				matchingEndpoints.add(endpoint);
+		}
+
+		return Collections.unmodifiableSet(matchingEndpoints);
+	}
+
+	@Override
+	public Set<N> getAdjacentNodes(N node)
+	{
+		final Set<N> sourceNodes = new HashSet<N>();
+
+		for(NEP destinationEndpoint : this.getNodeEndpoints(node) )
+			for(Graph.EdgeEndpoint<PA, N, E> sourceEndpoint : destinationEndpoint.getAdjacentEdges())
+				for(Graph.NodeEndpoint<PA, N, E> nodeEndpoint : sourceEndpoint.getAdjacentNodes())
+					sourceNodes.add(nodeEndpoint.getTarget());
+
+		return Collections.unmodifiableSet(sourceNodes);
+	}
+
+	@Override
+	public Set<E> getAdjacentEdges(N node)
+	{
+		final Set<E> sourceEdges = new HashSet<E>();
+
+		for(NEP destinationEndpoint : this.getNodeEndpoints(node) )
+			for(Graph.EdgeEndpoint<PA, N, E> sourceEndpoint : destinationEndpoint.getAdjacentEdges())
+				sourceEdges.add(sourceEndpoint.getTarget());
+
+		return Collections.unmodifiableSet(sourceEdges);
+	}
+
+	@Override
+	public boolean isTraversable(Object source, Object destination)
+	{
+		return this.isTraversable(source, destination, this.getPathFinder());
+	}
+
+	private boolean isTraversable(Object source, Object destination, final PathFinder pathFinder)
+	{
+		if(this.getNodes().contains(source) && this.getNodes().contains(destination))
+			return this.getPathFinder().isReachable((N)source, (N)destination);
+		//edges are handled recusively
+		else if(this.getEdges().contains(source))
+		{
+			final E sourceEdge = (E) source;
+			final Set<N> sourceNodes = new HashSet<N>();
+			for(Endpoint<? extends N> endpoint : sourceEdge.getEndPoints())
+				if((endpoint.getTraversableNeighborsFrom().size() > 0)&&(!sourceNodes.contains(endpoint.getTarget())))
+				{
+					if(this.isTraversable(endpoint.getTarget(), destination))
+						return true;
+					sourceNodes.add(endpoint.getTarget());
+				}
+			return false;
+		}
+		else if(this.getEdges().contains(destination))
+		{
+			final E destinationEdge = (E) destination;
+			final Set<N> destinationNodes = new HashSet<N>();
+			for(Endpoint<? extends N> endpoint : destinationEdge.getEndPoints())
+				if((endpoint.isTraversable())&&(!destinationNodes.contains(endpoint.getTarget())))
+				{
+					if(this.isTraversable(source, endpoint.getTarget()))
+						return true;
+					destinationNodes.add(endpoint.getTarget());
+				}
+			return false;
+		}
+		else
+			throw new IllegalArgumentException("both source and destination need to be contained within this graph");
+	}
+
+	@Override
+	public Set<E> getTraversableEdgesFrom(N source)
+	{
+		if( !this.getNodes().contains(source) )
+			throw new IllegalArgumentException("source does not belong to this graph");
+
+		final PathFinder<N,E> pathFinder = this.getPathFinder();
+
+		final Set<E> traversables = new HashSet<E>();
+		for(E neighbor : this.getEdges())
+			if( this.isTraversable(source, neighbor, pathFinder) )
+				traversables.add(neighbor);
+		return Collections.unmodifiableSet(traversables);
+	}
+
+	@Override
+	public Set<E> getTraversableEdgesFrom(E source)
+	{
+		if( !this.getEdges().contains(source) )
+			throw new IllegalArgumentException("source does not belong to this graph");
+
+		final PathFinder<N,E> pathFinder = this.getPathFinder();
+
+		final Set<E> traversables = new HashSet<E>();
+		for(E neighbor : this.getEdges())
+			if( this.isTraversable(source,neighbor,pathFinder) )
+				traversables.add(neighbor);
+		return Collections.unmodifiableSet(traversables);
+	}
+
+	@Override
+	public Set<E> getTraversableEdgesTo(N destination)
+	{
+		if( !this.getNodes().contains(destination) )
+			throw new IllegalArgumentException("source does not belong to this graph");
+
+		final PathFinder<N,E> pathFinder = this.getPathFinder();
+
+		final Set<E> traversables = new HashSet<E>();
+		for(E neighbor : this.getEdges())
+			if( this.isTraversable(neighbor,destination,pathFinder) )
+				traversables.add(neighbor);
+		return Collections.unmodifiableSet(traversables);
+	}
+
+	@Override
+	public Set<E> getTraversableEdgesTo(E destination)
+	{
+		if( !this.getEdges().contains(destination) )
+			throw new IllegalArgumentException("source does not belong to this graph");
+
+		final PathFinder<N,E> pathFinder = this.getPathFinder();
+
+		final Set<E> traversables = new HashSet<E>();
+		for(E neighbor : this.getEdges())
+			if( this.isTraversable(neighbor,destination,pathFinder) )
+				traversables.add(neighbor);
+		return Collections.unmodifiableSet(traversables);
+	}
+
+	@Override
+	public Set<N> getTraversableNodesFrom(N source)
+	{
+		if( !this.getNodes().contains(source) )
+			throw new IllegalArgumentException("source does not belong to this graph");
+
+		final PathFinder<N,E> pathFinder = this.getPathFinder();
+
+		final Set<N> traversables = new HashSet<N>();
+		for(N neighbor : this.getNodes())
+			if( this.isTraversable(source, neighbor, pathFinder) )
+				traversables.add(neighbor);
+		return Collections.unmodifiableSet(traversables);
+	}
+
+	@Override
+	public Set<N> getTraversableNodesFrom(E source)
+	{
+		if( !this.getEdges().contains(source) )
+			throw new IllegalArgumentException("source does not belong to this graph");
+
+		final PathFinder<N,E> pathFinder = this.getPathFinder();
+
+		final Set<N> traversables = new HashSet<N>();
+		for(N neighbor : this.getNodes())
+			if( this.isTraversable(source,neighbor,pathFinder) )
+				traversables.add(neighbor);
+		return Collections.unmodifiableSet(traversables);
+	}
+
+	@Override
+	public Set<N> getTraversableNodesTo(N destination)
+	{
+		if( !this.getNodes().contains(destination) )
+			throw new IllegalArgumentException("source does not belong to this graph");
+
+		final PathFinder<N,E> pathFinder = this.getPathFinder();
+
+		final Set<N> traversables = new HashSet<N>();
+		for(N neighbor : this.getNodes())
+			if( this.isTraversable(neighbor, destination, pathFinder) )
+				traversables.add(neighbor);
+		return Collections.unmodifiableSet(traversables);
+	}
+
+	@Override
+	public Set<N> getTraversableNodesTo(E destination)
+	{
+		if( !this.getEdges().contains(destination) )
+			throw new IllegalArgumentException("source does not belong to this graph");
+
+		final PathFinder<N,E> pathFinder = this.getPathFinder();
+
+		final Set<N> traversables = new HashSet<N>();
+		for(N neighbor : this.getNodes())
+			if( this.isTraversable(neighbor, destination, pathFinder) )
+				traversables.add(neighbor);
+		return Collections.unmodifiableSet(traversables);
+	}
+
+	@Override
+	public Set<E> getTraversableAdjacentEdgesFrom(N source)
+	{
+		final Set<E> destinationEdges = new HashSet<E>();
+
+		for(NEP sourceEndpoint : this.getNodeEndpoints(source) )
+			for(Graph.EdgeEndpoint<PA, N, E> destinationEndpoint : sourceEndpoint.getTraversableAdjacentEdgesFrom())
+				destinationEdges.add(destinationEndpoint.getTarget());
+
+		return Collections.unmodifiableSet(destinationEdges);
+	}
+
+	@Override
+	public Set<E> getTraversableAdjacentEdgesFrom(E source)
+	{
+		final Set<E> destinationEdges = new HashSet<E>();
+
+		for(EEP sourceEndpoint : this.getEdgeEndpoints(source) )
+			for(Graph.EdgeEndpoint<PA, N, E> destinationEndpoint : sourceEndpoint.getTraversableAdjacentEdgesFrom())
+				destinationEdges.add(destinationEndpoint.getTarget());
+
+		return Collections.unmodifiableSet(destinationEdges);
+	}
+
+
+	@Override
+	public Set<E> getTraversableAdjacentEdgesTo(N destination)
+	{
+		final Set<E> sourceEdges = new HashSet<E>();
+
+		for(NEP destinationEndpoint : this.getNodeEndpoints(destination) )
+			for(Graph.EdgeEndpoint<PA, N, E> sourceEndpoint : destinationEndpoint.getTraversableAdjacentEdgesTo())
+				sourceEdges.add(sourceEndpoint.getTarget());
+
+		return Collections.unmodifiableSet(sourceEdges);
+	}
+
+	@Override
+	public Set<E> getTraversableAdjacentEdgesTo(E destination)
+	{
+		final Set<E> destinationEdges = new HashSet<E>();
+
+		for(EEP destinationEndpoint : this.getEdgeEndpoints(destination) )
+			for(Graph.EdgeEndpoint<PA, N, E> sourceEndpoint : destinationEndpoint.getTraversableAdjacentEdgesFrom())
+				destinationEdges.add(sourceEndpoint.getTarget());
+
+		return Collections.unmodifiableSet(destinationEdges);
+	}
+
+	@Override
+	public Set<N> getTraversableAdjacentNodesFrom(N source)
+	{
+		final Set<N> destinationNodes = new HashSet<N>();
+
+		for(NEP sourceEndpoint : this.getNodeEndpoints(source) )
+			for(Graph.EdgeEndpoint<PA, N, E> destinationEndpoint : sourceEndpoint.getTraversableAdjacentEdgesTo())
+				for(Graph.NodeEndpoint<PA, N, E> nodeEndpoint : destinationEndpoint.getTraversableAdjacentNodesTo())
+					destinationNodes.add(nodeEndpoint.getTarget());
+
+		return Collections.unmodifiableSet(destinationNodes);
+	}
+
+	@Override
+	public Set<N> getTraversableAdjacentNodesFrom(E source)
+	{
+		final Set<N> destinationNodes = new HashSet<N>();
+
+		for(EEP sourceEndpoint : this.getEdgeEndpoints(source) )
+			for(Graph.NodeEndpoint<PA, N, E> destinationEndpoint : sourceEndpoint.getTraversableAdjacentNodesTo())
+					destinationNodes.add(destinationEndpoint.getTarget());
+
+		return Collections.unmodifiableSet(destinationNodes);
+	}
+
+	@Override
+	public Set<N> getTraversableAdjacentNodesTo(N destination)
+	{
+		final Set<N> sourceNodes = new HashSet<N>();
+
+		for(NEP destinationEndpoint : this.getNodeEndpoints(destination) )
+			for(Graph.EdgeEndpoint<PA, N, E> sourceEndpoint : destinationEndpoint.getTraversableAdjacentEdgesFrom())
+				for(Graph.NodeEndpoint<PA, N, E> nodeEndpoint : sourceEndpoint.getTraversableAdjacentNodesFrom())
+					sourceNodes.add(nodeEndpoint.getTarget());
+
+		return Collections.unmodifiableSet(sourceNodes);
+	}
+
+	@Override
+	public Set<N> getTraversableAdjacentNodesTo(E destination)
+	{
+		final Set<N> sourceNodes = new HashSet<N>();
+
+		for(EEP destinationEndpoint : this.getEdgeEndpoints(destination) )
+			for(Graph.NodeEndpoint<PA, N, E> sourceEndpoint : destinationEndpoint.getTraversableAdjacentNodesFrom())
+					sourceNodes.add(sourceEndpoint.getTarget());
+
+		return Collections.unmodifiableSet(sourceNodes);
+	}
+
+	/**
+	 * Clones the current object.
+	 * @return A clone of the current object, with no changes
+	 */
+	@Override
+	protected AbstractAdjacencyGraph<PA, N, E, NEP, EEP> clone()
+	{
+		return (AbstractAdjacencyGraph<PA, N, E, NEP, EEP>) super.clone();
+	}
 
 	/**
 	 * Converts the current AbstractAdjacencyGraph to a GraphXML.
@@ -467,7 +904,7 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 		final Namer<Object> namer = new Namer<Object>();
 
 		xml.setNodeInstances(new GraphElementXml.NodeInstances());
-		for(N node : this.adjacentEdges.keySet())
+		for(N node : this.getNodes())
 		{
 			final String nodeName = namer.getNameOrCreate(node);
 
@@ -504,12 +941,13 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 		this.toXml(xml, namer);
 		return xml;
 	}
-
+/*
 	/**
 	 * Adds a current Namer to the given GraphXML object.
 	 * @param jaxbObject The graph to add the object to
 	 * @param namer THe namer to add to the GraphXML
 	 */
+/*
 	@Override
 	public void toXml(final GraphXml jaxbObject, final Namer<Object> namer)
 	{
@@ -518,7 +956,7 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 		if(jaxbObject == null)
 			throw new IllegalArgumentException("jaxbObject can not be null");
 
-		for(N node : this.adjacentEdges.keySet())
+		for(N node : this.getNodes())
 		{
 			final String nodeName = namer.getNameOrCreate(node);
 
@@ -538,7 +976,7 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 			jaxbObject.getNodes().getNodes().add(encapsulation);
 		}
 
-		for(E edge : this.edges)
+		for(E edge : this.getEdges())
 		{
 			final EdgeXml edgeXml = edge.toXml(namer);
 
@@ -547,4 +985,166 @@ public abstract class AbstractAdjacencyGraph<N, E extends Edge<N>> implements Gr
 			jaxbObject.getEdges().getEdges().add(edgeXml);
 		}
 	}
+*/
+	protected abstract class AbstractNodeEndpoint extends AbstractEdge<N,Graph.Endpoint<PA,N,E,PA>>.AbstractEndpoint implements Graph.NodeEndpoint<PA,N,E>
+	{
+
+		@Override
+		public Set<Graph.EdgeEndpoint<PA, N, E>> getAdjacentEdges()
+		{
+			return getAdjacentEdgeEndPoint(this);
+		}
+
+		@Override
+		public Set<Graph.NodeEndpoint<PA, N, E>> getAdjacentNodes()
+		{
+			final Set<Graph.NodeEndpoint<PA, N, E>> adjacentNodes = new HashSet<Graph.NodeEndpoint<PA, N, E>>();
+
+			for(Graph.EdgeEndpoint<PA, N, E> adjacentEndpoint : this.getAdjacentEdges() )
+				for( Edge.Endpoint<? extends N> nodeEndpoint : adjacentEndpoint.getTarget().getEndPoints(this.getTarget()) )
+					for( Edge.Endpoint<? extends N> adjacentNodeEndpoint : nodeEndpoint.getNeighbors() )
+						adjacentNodes.addAll(AbstractAdjacencyGraph.this.getNodeEndpoints(adjacentNodeEndpoint.getTarget()));
+
+			return Collections.unmodifiableSet(adjacentNodes);
+		}
+
+		@Override
+		public Set<Graph.NodeEndpoint<PA, N, E>> getTraversableAdjacentNodesTo()
+		{
+			final Set<Graph.NodeEndpoint<PA, N, E>> adjacentNodes = new HashSet<Graph.NodeEndpoint<PA, N, E>>();
+
+			for(Graph.EdgeEndpoint<PA, N, E> adjacentEndpoint : this.getAdjacentEdges() )
+				for( Edge.Endpoint<? extends N> nodeEndpoint : adjacentEndpoint.getTarget().getEndPoints(this.getTarget()) )
+					for( Edge.Endpoint<? extends N> adjacentNodeEndpoint : nodeEndpoint.getTraversableNeighborsTo() )
+						adjacentNodes.addAll(AbstractAdjacencyGraph.this.getNodeEndpoints(adjacentNodeEndpoint.getTarget()));
+
+			return Collections.unmodifiableSet(adjacentNodes);
+		}
+
+		@Override
+		public Set<Graph.NodeEndpoint<PA, N, E>> getTraversableAdjacentNodesFrom()
+		{
+			final Set<Graph.NodeEndpoint<PA, N, E>> adjacentNodes = new HashSet<Graph.NodeEndpoint<PA, N, E>>();
+
+			for(Graph.EdgeEndpoint<PA, N, E> adjacentEndpoint : this.getAdjacentEdges() )
+				for( Edge.Endpoint<? extends N> nodeEndpoint : adjacentEndpoint.getTarget().getEndPoints(this.getTarget()) )
+					for( Edge.Endpoint<? extends N> adjacentNodeEndpoint : nodeEndpoint.getTraversableNeighborsFrom() )
+						adjacentNodes.addAll(AbstractAdjacencyGraph.this.getNodeEndpoints(adjacentNodeEndpoint.getTarget()));
+
+			return Collections.unmodifiableSet(adjacentNodes);
+		}
+
+		@Override
+		public Set<Graph.EdgeEndpoint<PA, N, E>> getTraversableAdjacentEdgesTo()
+		{
+			final Set<Graph.EdgeEndpoint<PA, N, E>> adjacentEdges = new HashSet<Graph.EdgeEndpoint<PA, N, E>>();
+
+			for(Graph.EdgeEndpoint<PA, N, E> adjacentEndpoint : this.getAdjacentEdges() )
+				for( Edge.Endpoint<? extends N> nodeEndpoint : adjacentEndpoint.getTarget().getEndPoints(this.getTarget()) )
+					if( nodeEndpoint.isTraversable() )
+						adjacentEdges.add(adjacentEndpoint);
+
+			return Collections.unmodifiableSet(adjacentEdges);
+		}
+
+		@Override
+		public Set<Graph.EdgeEndpoint<PA, N, E>> getTraversableAdjacentEdgesFrom()
+		{
+			final Set<Graph.EdgeEndpoint<PA, N, E>> adjacentEdges = new HashSet<Graph.EdgeEndpoint<PA, N, E>>();
+
+			for(Graph.EdgeEndpoint<PA, N, E> adjacentEndpoint : this.getAdjacentEdges() )
+				for( Edge.Endpoint<? extends N> nodeEndpoint : adjacentEndpoint.getTarget().getEndPoints(this.getTarget()) )
+					if( nodeEndpoint.isTraversable() )
+						adjacentEdges.add(adjacentEndpoint);
+
+			return Collections.unmodifiableSet(adjacentEdges);
+		}
+	};
+
+//	protected abstract class AbstractNodeEndpoint<MN extends N> extends AbstractEdge<PA,Graph.Endpoint<? extends PA,? extends PA,?>>.AbstractEndpoint<MN> implements Graph.NodeEndpoint<PA,N,MN,E,NEP,EEP>
+//	protected abstract class AbstractEdgeEndpoint<ME extends E> extends AbstractEdge<PA,Graph.Endpoint<? extends PA,? extends PA, ?>>.AbstractEndpoint<ME> implements Graph.EdgeEndpoint<N,E,ME>
+//	protected abstract class AbstractEdgeEndpoint<ME extends E> extends AbstractEdge<E,Graph.Endpoint<? extends PA,? extends PA, ?>>.AbstractEndpoint<E,ME> implements Graph.EdgeEndpoint<PA,N,E,E,NEP,EEP>
+
+//	protected abstract class AbstractEdgeEndpoint<ME extends E> extends AbstractEdge<PA,Graph.Endpoint<PA,PA>>.AbstractEndpoint<ME> implements Graph.EdgeEndpoint<PA,N,E,ME>
+//	protected abstract class AbstractEdgeEndpoint<ME extends E> implements Edge.Endpoint<PA,ME>, Graph.EdgeEndpoint<PA,N,E,ME>
+	protected abstract class AbstractEdgeEndpoint extends AbstractEdge<E,Graph.Endpoint<PA,N,E,PA>>.AbstractEndpoint implements Graph.EdgeEndpoint<PA,N,E>
+	{
+		@Override
+		public Set<Graph.NodeEndpoint<PA, N, E>> getAdjacentNodes()
+		{
+			final Set<Graph.NodeEndpoint<PA, N, E>> adjacentNodes = new HashSet<Graph.NodeEndpoint<PA, N, E>>();
+
+			for(Endpoint<? extends N> adjacentEndpoint : this.getTarget().getEndPoints())
+				adjacentNodes.addAll(AbstractAdjacencyGraph.this.getNodeEndpoints(adjacentEndpoint.getTarget()));
+
+			return Collections.unmodifiableSet(adjacentNodes);
+		}
+
+		@Override
+		public Set<Graph.EdgeEndpoint<PA, N, E>> getAdjacentEdges()
+		{
+			final Set<Graph.EdgeEndpoint<PA, N, E>> adjacentEdges = new HashSet<Graph.EdgeEndpoint<PA, N, E>>();
+
+			for(Endpoint<? extends N> sourceEndpoint : this.getTarget().getEndPoints())
+				for( NEP neighborNode : AbstractAdjacencyGraph.this.getNodeEndpoints(sourceEndpoint.getTarget()) )
+					adjacentEdges.addAll(AbstractAdjacencyGraph.this.getAdjacentEdgeEndPoint(neighborNode));
+
+			adjacentEdges.remove(this);
+			return Collections.unmodifiableSet(adjacentEdges);
+		}
+
+		@Override
+		public Set<Graph.EdgeEndpoint<PA, N, E>> getTraversableAdjacentEdgesTo()
+		{
+			final Set<Graph.EdgeEndpoint<PA, N, E>> adjacentEdges = new HashSet<Graph.EdgeEndpoint<PA, N, E>>();
+
+			for(Endpoint<? extends N> sourceEndpoint : this.getTarget().getEndPoints())
+				if( sourceEndpoint.getTraversableNeighborsFrom().size() > 0 )
+					for( NEP adjacentNode : AbstractAdjacencyGraph.this.getNodeEndpoints(sourceEndpoint.getTarget()))
+						for( Graph.EdgeEndpoint<PA, N, E> adjacentEdge : AbstractAdjacencyGraph.this.getAdjacentEdgeEndPoint(adjacentNode) )
+						 	if( adjacentEdge.getTarget().getTraversableFrom(adjacentNode.getTarget()).size() > 0 )
+								 adjacentEdges.add(adjacentEdge);
+
+			return Collections.unmodifiableSet(adjacentEdges);
+		}
+
+		@Override
+		public Set<Graph.EdgeEndpoint<PA, N, E>> getTraversableAdjacentEdgesFrom()
+		{
+			final Set<Graph.EdgeEndpoint<PA, N, E>> adjacentEdges = new HashSet<Graph.EdgeEndpoint<PA, N, E>>();
+
+			for(Endpoint<? extends N> sourceEndpoint : this.getTarget().getEndPoints())
+				if( sourceEndpoint.getTraversableNeighborsTo().size() > 0 )
+					for( NEP adjacentNode : AbstractAdjacencyGraph.this.getNodeEndpoints(sourceEndpoint.getTarget()))
+						for( Graph.EdgeEndpoint<PA, N, E> adjacentEdge : AbstractAdjacencyGraph.this.getAdjacentEdgeEndPoint(adjacentNode) )
+						 	if( adjacentEdge.getTarget().getTraversableTo(adjacentNode.getTarget()).size() > 0 )
+								 adjacentEdges.add(adjacentEdge);
+
+			return Collections.unmodifiableSet(adjacentEdges);
+		}
+
+		@Override
+		public Set<Graph.NodeEndpoint<PA, N, E>> getTraversableAdjacentNodesTo()
+		{
+			final Set<Graph.NodeEndpoint<PA, N, E>> adjacentNodes = new HashSet<Graph.NodeEndpoint<PA, N, E>>();
+
+			for(Endpoint<? extends N> sourceEndpoint : this.getTarget().getEndPoints())
+				if( sourceEndpoint.getTraversableNeighborsFrom().size() > 0 )
+					adjacentNodes.addAll(AbstractAdjacencyGraph.this.getNodeEndpoints(sourceEndpoint.getTarget()));
+
+			return Collections.unmodifiableSet(adjacentNodes);
+		}
+
+		@Override
+		public Set<Graph.NodeEndpoint<PA, N, E>> getTraversableAdjacentNodesFrom()
+		{
+			final Set<Graph.NodeEndpoint<PA, N, E>> adjacentNodes = new HashSet<Graph.NodeEndpoint<PA, N, E>>();
+
+			for(Endpoint<? extends N> sourceEndpoint : this.getTarget().getEndPoints())
+				if( sourceEndpoint.getTraversableNeighborsTo().size() > 0 )
+					adjacentNodes.addAll(AbstractAdjacencyGraph.this.getNodeEndpoints(sourceEndpoint.getTarget()));
+
+			return Collections.unmodifiableSet(adjacentNodes);
+		}
+	};
 }
diff --git a/src/main/java/com/syncleus/dann/graph/AbstractBidirectedAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graph/AbstractBidirectedAdjacencyGraph.java
index 1b38ece32b5ee155cdb3f3d68b753cddd11f6168..27c05024e5f776cfa7b76501f00c4cd237717c80 100644
--- a/src/main/java/com/syncleus/dann/graph/AbstractBidirectedAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/AbstractBidirectedAdjacencyGraph.java
@@ -33,7 +33,7 @@ public abstract class AbstractBidirectedAdjacencyGraph<N, E extends BidirectedEd
 
 	protected AbstractBidirectedAdjacencyGraph(final Graph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 
 	protected AbstractBidirectedAdjacencyGraph(final Set<N> nodes, final Set<E> edges)
@@ -47,7 +47,7 @@ public abstract class AbstractBidirectedAdjacencyGraph<N, E extends BidirectedEd
 		final Set<E> inEdges = new HashSet<E>();
 		for(final E edge : this.getEdges())
 		{
-			final List<N> adjacentNodes = new ArrayList<N>(edge.getNodes());
+			final List<N> adjacentNodes = new ArrayList<N>(edge.getTargets());
 			adjacentNodes.remove(node);
 			final N adjacentNode = adjacentNodes.get(0);
 
@@ -58,43 +58,7 @@ public abstract class AbstractBidirectedAdjacencyGraph<N, E extends BidirectedEd
 	}
 
 	@Override
-	public AbstractBidirectedAdjacencyGraph<N, E> cloneAdd(final E newEdge)
-	{
-		return (AbstractBidirectedAdjacencyGraph<N, E>) super.cloneAdd(newEdge);
-	}
-
-	@Override
-	public AbstractBidirectedAdjacencyGraph<N, E> cloneAdd(final N newNode)
-	{
-		return (AbstractBidirectedAdjacencyGraph<N, E>) super.cloneAdd(newNode);
-	}
-
-	@Override
-	public AbstractBidirectedAdjacencyGraph<N, E> cloneAdd(final Set<N> newNodes, final Set<E> newEdges)
-	{
-		return (AbstractBidirectedAdjacencyGraph<N, E>) super.cloneAdd(newNodes, newEdges);
-	}
-
-	@Override
-	public AbstractBidirectedAdjacencyGraph<N, E> cloneRemove(final E edgeToRemove)
-	{
-		return (AbstractBidirectedAdjacencyGraph<N, E>) super.cloneRemove(edgeToRemove);
-	}
-
-	@Override
-	public AbstractBidirectedAdjacencyGraph<N, E> cloneRemove(final N nodeToRemove)
-	{
-		return (AbstractBidirectedAdjacencyGraph<N, E>) super.cloneRemove(nodeToRemove);
-	}
-
-	@Override
-	public AbstractBidirectedAdjacencyGraph<N, E> cloneRemove(final Set<N> deleteNodes, final Set<E> deleteEdges)
-	{
-		return (AbstractBidirectedAdjacencyGraph<N, E>) super.cloneRemove(deleteNodes, deleteEdges);
-	}
-
-	@Override
-	public AbstractBidirectedAdjacencyGraph<N, E> clone()
+	protected AbstractBidirectedAdjacencyGraph<N, E> clone()
 	{
 		return (AbstractBidirectedAdjacencyGraph<N, E>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/AbstractBidirectedEdge.java b/src/main/java/com/syncleus/dann/graph/AbstractBidirectedEdge.java
index 7cad24353ab92356fec42e8fa1470b97df4c246d..f5f44033b340c2705e03cb065e2aec8773dbfded 100644
--- a/src/main/java/com/syncleus/dann/graph/AbstractBidirectedEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/AbstractBidirectedEdge.java
@@ -18,58 +18,24 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 import com.syncleus.dann.graph.xml.*;
 import com.syncleus.dann.xml.NamedValueXml;
 import com.syncleus.dann.xml.Namer;
 import com.syncleus.dann.xml.XmlSerializable;
 
-public abstract class AbstractBidirectedEdge<N> extends AbstractEdge<N> implements BidirectedEdge<N>
+public abstract class AbstractBidirectedEdge<N, LN extends N, RN extends N> extends AbstractEdge<N> implements MixableBidirectedEdge<N, LN,RN>
 {
-	private final N leftNode;
-	private final N rightNode;
-	private final EndState leftEndState;
-	private final EndState rightEndState;
-
-	protected AbstractBidirectedEdge()
-	{
-		this.leftNode = null;
-		this.rightNode = null;
-		this.leftEndState = null;
-		this.rightEndState = null;
-	}
-
-	protected AbstractBidirectedEdge(final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
-	{
-		super(allowJoiningMultipleGraphs, contextEnabled);
-
-		this.leftNode = null;
-		this.rightNode = null;
-		this.leftEndState = null;
-		this.rightEndState = null;
-	}
-
-	protected AbstractBidirectedEdge(final N newLeftNode, final EndState newLeftEndState, final N newRightNode, final EndState newRightEndState)
-	{
-		super(packNodes(newLeftNode, newRightNode));
+	@Override
+	public abstract AbstractEndpoint<LN,RN> getLeftEndPoint();
 
-		this.leftNode = newLeftNode;
-		this.rightNode = newRightNode;
-		this.leftEndState = newLeftEndState;
-		this.rightEndState = newRightEndState;
-	}
+	@Override
+	public abstract AbstractEndpoint<RN,LN> getRightEndPoint();
 
-	protected AbstractBidirectedEdge(final N newLeftNode, final EndState newLeftEndState, final N newRightNode, final EndState newRightEndState, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
+	@Override
+	public final Set<Endpoint<N, N>> getEndPoints()
 	{
-		super(packNodes(newLeftNode, newRightNode), allowJoiningMultipleGraphs, contextEnabled);
-
-		this.leftNode = newLeftNode;
-		this.rightNode = newRightNode;
-		this.leftEndState = newLeftEndState;
-		this.rightEndState = newRightEndState;
+		return new EndPointsSet();
 	}
 
 	private static <N> List<N> packNodes(final N leftNode, final N rightNode)
@@ -80,48 +46,24 @@ public abstract class AbstractBidirectedEdge<N> extends AbstractEdge<N> implemen
 		return pack;
 	}
 
-	@Override
-	public final N getLeftNode()
-	{
-		return this.leftNode;
-	}
-
-	@Override
-	public final N getRightNode()
-	{
-		return this.rightNode;
-	}
-
-	@Override
-	public final EndState getLeftEndState()
-	{
-		return this.leftEndState;
-	}
-
-	@Override
-	public final EndState getRightEndState()
-	{
-		return this.rightEndState;
-	}
-
 	@Override
 	public boolean isIntroverted()
 	{
-		return (this.rightEndState == BidirectedEdge.EndState.INWARD) && (this.leftEndState == BidirectedEdge.EndState.INWARD);
+		return (this.getRightEndPoint().getDirection() == MixableBidirectedEdge.Endpoint.Direction.INWARD) && (this.getLeftEndPoint().getDirection() == MixableBidirectedEdge.Endpoint.Direction.INWARD);
 	}
 
 	@Override
 	public boolean isExtroverted()
 	{
-		return (this.rightEndState == BidirectedEdge.EndState.OUTWARD) && (this.leftEndState == BidirectedEdge.EndState.OUTWARD);
+		return (this.getRightEndPoint().getDirection() == MixableBidirectedEdge.Endpoint.Direction.OUTWARD) && (this.getLeftEndPoint().getDirection() == MixableBidirectedEdge.Endpoint.Direction.OUTWARD);
 	}
 
 	@Override
 	public boolean isDirected()
 	{
-		if( (this.rightEndState == EndState.INWARD) && (this.leftEndState == EndState.OUTWARD) )
+		if( (this.getRightEndPoint().getDirection() == MixableBidirectedEdge.Endpoint.Direction.INWARD) && (this.getLeftEndPoint().getDirection() == MixableBidirectedEdge.Endpoint.Direction.OUTWARD) )
 			return true;
-		else if( (this.rightEndState == EndState.OUTWARD) && (this.leftEndState == EndState.INWARD) )
+		else if( (this.getRightEndPoint().getDirection() == MixableBidirectedEdge.Endpoint.Direction.OUTWARD) && (this.getLeftEndPoint().getDirection() == MixableBidirectedEdge.Endpoint.Direction.INWARD) )
 			return true;
 		return false;
 	}
@@ -129,9 +71,9 @@ public abstract class AbstractBidirectedEdge<N> extends AbstractEdge<N> implemen
 	@Override
 	public boolean isHalfEdge()
 	{
-		if( (this.rightEndState == EndState.NONE) && (this.leftEndState != EndState.NONE) )
+		if( (this.getRightEndPoint().getDirection() == MixableBidirectedEdge.Endpoint.Direction.NONE) && (this.getLeftEndPoint().getDirection() != MixableBidirectedEdge.Endpoint.Direction.NONE) )
 			return true;
-		else if( (this.rightEndState != EndState.NONE) && (this.leftEndState == EndState.NONE) )
+		else if( (this.getRightEndPoint().getDirection() != MixableBidirectedEdge.Endpoint.Direction.NONE) && (this.getLeftEndPoint().getDirection() == MixableBidirectedEdge.Endpoint.Direction.NONE) )
 			return true;
 		return false;
 	}
@@ -139,7 +81,7 @@ public abstract class AbstractBidirectedEdge<N> extends AbstractEdge<N> implemen
 	@Override
 	public boolean isLooseEdge()
 	{
-		return (this.rightEndState == BidirectedEdge.EndState.NONE) && (this.leftEndState == BidirectedEdge.EndState.NONE);
+		return (this.getRightEndPoint().getDirection() == MixableBidirectedEdge.Endpoint.Direction.NONE) && (this.getLeftEndPoint().getDirection() == MixableBidirectedEdge.Endpoint.Direction.NONE);
 	}
 
 	@Override
@@ -151,20 +93,20 @@ public abstract class AbstractBidirectedEdge<N> extends AbstractEdge<N> implemen
 	@Override
 	public boolean isLoop()
 	{
-		return this.leftEndState.equals(this.rightEndState);
+		return this.getLeftEndPoint().getDirection().equals(this.getRightEndPoint().getDirection());
 	}
 
 	@Override
 	public String toString()
 	{
-		return this.leftNode.toString()
-				+ endStateToString(this.leftEndState, true)
+		return this.getLeftEndPoint().getTarget().toString()
+				+ endStateToString(this.getLeftEndPoint().getDirection(), true)
 				+ '-'
-				+ endStateToString(this.rightEndState, false)
-				+ this.rightNode;
+				+ endStateToString(this.getRightEndPoint().getDirection(), false)
+				+ this.getRightEndPoint().getTarget();
 	}
 
-	private static String endStateToString(final EndState state, final boolean isLeft)
+	private static String endStateToString(final MixableBidirectedEdge.Endpoint.Direction state, final boolean isLeft)
 	{
 		switch(state)
 		{
@@ -178,9 +120,9 @@ public abstract class AbstractBidirectedEdge<N> extends AbstractEdge<N> implemen
 	}
 
 	@Override
-	public AbstractBidirectedEdge<N> clone()
+	protected AbstractBidirectedEdge<N, LN,RN> clone()
 	{
-		return (AbstractBidirectedEdge<N>) super.clone();
+		return (AbstractBidirectedEdge<N, LN,RN>) super.clone();
 	}
 
 	@Override
@@ -191,7 +133,7 @@ public abstract class AbstractBidirectedEdge<N> extends AbstractEdge<N> implemen
 
 		xml.setNodeInstances(new BidirectedEdgeElementXml.NodeInstances());
 		final Set<N> writtenNodes = new HashSet<N>();
-		for (N node : this.getNodes())
+		for (N node : this.getTargets())
 		{
 			if (writtenNodes.add(node))
 			{
@@ -241,10 +183,186 @@ public abstract class AbstractBidirectedEdge<N> extends AbstractEdge<N> implemen
 
 		if (jaxbObject instanceof BidirectedEdgeXml)
 		{
-			((BidirectedEdgeXml) jaxbObject).setLeftNode(nodeNames.getNameOrCreate(this.leftNode));
-			((BidirectedEdgeXml) jaxbObject).setRightNode(nodeNames.getNameOrCreate(this.rightNode));
-			((BidirectedEdgeXml) jaxbObject).setLeftDirection(this.leftEndState.toString().toLowerCase());
-			((BidirectedEdgeXml) jaxbObject).setRightDirection(this.rightEndState.toString().toLowerCase());
+			((BidirectedEdgeXml) jaxbObject).setLeftNode(nodeNames.getNameOrCreate(this.getLeftEndPoint().getTarget()));
+			((BidirectedEdgeXml) jaxbObject).setRightNode(nodeNames.getNameOrCreate(this.getRightEndPoint().getTarget()));
+			((BidirectedEdgeXml) jaxbObject).setLeftDirection(this.getLeftEndPoint().getDirection().toString().toLowerCase());
+			((BidirectedEdgeXml) jaxbObject).setRightDirection(this.getRightEndPoint().getDirection().toString().toLowerCase());
+		}
+	}
+
+	private final class EndPointsSet implements Set<Endpoint<N, N>>
+	{
+		public EndPointsSet()
+		{
+		}
+
+		@Override
+		public int size()
+		{
+			return 2;
+		}
+
+		@Override
+		public boolean isEmpty()
+		{
+			return false;
+		}
+
+		@Override
+		public boolean contains(Object o)
+		{
+			if( (getLeftEndPoint().equals(o)) || (getRightEndPoint().equals(o)) )
+				return true;
+			return false;
+		}
+
+		@Override
+		public Iterator<Endpoint<N, N>> iterator()
+		{
+			return new EndPointIterator();
+		}
+
+		@Override
+		public Endpoint<N, N>[] toArray()
+		{
+			return new Endpoint[]{getLeftEndPoint(),getRightEndPoint()};
+		}
+
+		@Override
+		public <T> T[] toArray(T[] a)
+		{
+			a[0] = (T) getLeftEndPoint();
+			a[1] = (T) getRightEndPoint();
+			return a;
+		}
+
+		@Override
+		public boolean add(Endpoint<N, N> nnEndpoint)
+		{
+			throw new UnsupportedOperationException("This Set is read-only!");
+		}
+
+		@Override
+		public boolean remove(Object o)
+		{
+			throw new UnsupportedOperationException("This Set is read-only!");
+		}
+
+		@Override
+		public boolean containsAll(Collection<?> c)
+		{
+			for(Object object : c)
+				if( !this.contains(object) )
+					return false;
+			return true;
+		}
+
+		@Override
+		public boolean addAll(Collection<? extends Endpoint<N, N>> c)
+		{
+			throw new UnsupportedOperationException("This Set is read-only!");
 		}
+
+		@Override
+		public boolean retainAll(Collection<?> c)
+		{
+			throw new UnsupportedOperationException("This Set is read-only!");
+		}
+
+		@Override
+		public boolean removeAll(Collection<?> c)
+		{
+			throw new UnsupportedOperationException("This Set is read-only!");
+		}
+
+		@Override
+		public void clear()
+		{
+			throw new UnsupportedOperationException("This Set is read-only!");
+		}
+
+		private class EndPointIterator implements Iterator<Endpoint<N, N>>
+		{
+			private Boolean stage = Boolean.TRUE;
+
+			public EndPointIterator()
+			{
+			}
+
+			@Override
+			public boolean hasNext()
+			{
+				if(stage == null)
+					return false;
+				return true;
+			}
+
+			@Override
+			public Endpoint<N, N> next()
+			{
+				if(stage == Boolean.TRUE)
+				{
+					stage = false;
+					return getLeftEndPoint();
+				}
+				else if(stage == Boolean.FALSE)
+				{
+					stage = null;
+					return getRightEndPoint();
+				}
+
+				throw new NoSuchElementException("no elements left!");
+			}
+
+			@Override
+			public void remove()
+			{
+				throw new UnsupportedOperationException("This iterator is read-only!");
+			}
+		};
 	}
+
+	protected abstract class AbstractEndpoint<EN extends N, ON extends N> extends AbstractEdge<N>.AbstractEndpoint<EN> implements MixableBidirectedEdge.Endpoint<N, EN,ON>
+	{
+		private EN node = null;
+		private Direction direction;
+
+		protected AbstractEndpoint(Direction direction)
+		{
+			super();
+
+			if( direction == null )
+				throw new IllegalArgumentException("direction can not be null!");
+			this.direction = direction;
+		}
+
+		protected AbstractEndpoint(EN node, Direction direction)
+		{
+			this(direction);
+
+			this.node = node;
+		}
+
+		@Override
+		public EN getTarget()
+		{
+			return this.node;
+		}
+
+		public void setTarget(final EN node)
+		{
+			this.node = node;
+		}
+
+		@Override
+		public Direction getDirection()
+		{
+			return this.direction;
+		}
+
+		public void setDirection(final Direction direction)
+		{
+			this.direction = direction;
+		}
+	};
 }
diff --git a/src/main/java/com/syncleus/dann/graph/AbstractDirectedAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graph/AbstractDirectedAdjacencyGraph.java
index 67a162bfe1245ba0a7d03ffeb868eee802425451..11bb95b582c3bf1de012208160e331bfbb51f8b5 100644
--- a/src/main/java/com/syncleus/dann/graph/AbstractDirectedAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/AbstractDirectedAdjacencyGraph.java
@@ -29,7 +29,7 @@ public abstract class AbstractDirectedAdjacencyGraph<N, E extends DirectedEdge<N
 
 	protected AbstractDirectedAdjacencyGraph(final Graph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 
 	protected AbstractDirectedAdjacencyGraph(final Set<N> nodes, final Set<E> edges)
@@ -38,43 +38,7 @@ public abstract class AbstractDirectedAdjacencyGraph<N, E extends DirectedEdge<N
 	}
 
 	@Override
-	public AbstractDirectedAdjacencyGraph<N, E> cloneAdd(final E newEdge)
-	{
-		return (AbstractDirectedAdjacencyGraph<N, E>) super.cloneAdd(newEdge);
-	}
-
-	@Override
-	public AbstractDirectedAdjacencyGraph<N, E> cloneAdd(final N newNode)
-	{
-		return (AbstractDirectedAdjacencyGraph<N, E>) super.cloneAdd(newNode);
-	}
-
-	@Override
-	public AbstractDirectedAdjacencyGraph<N, E> cloneAdd(final Set<N> newNodes, final Set<E> newEdges)
-	{
-		return (AbstractDirectedAdjacencyGraph<N, E>) super.cloneAdd(newNodes, newEdges);
-	}
-
-	@Override
-	public AbstractDirectedAdjacencyGraph<N, E> cloneRemove(final E edgeToRemove)
-	{
-		return (AbstractDirectedAdjacencyGraph<N, E>) super.cloneRemove(edgeToRemove);
-	}
-
-	@Override
-	public AbstractDirectedAdjacencyGraph<N, E> cloneRemove(final N nodeToRemove)
-	{
-		return (AbstractDirectedAdjacencyGraph<N, E>) super.cloneRemove(nodeToRemove);
-	}
-
-	@Override
-	public AbstractDirectedAdjacencyGraph<N, E> cloneRemove(final Set<N> deleteNodes, final Set<E> deleteEdges)
-	{
-		return (AbstractDirectedAdjacencyGraph<N, E>) super.cloneRemove(deleteNodes, deleteEdges);
-	}
-
-	@Override
-	public AbstractDirectedAdjacencyGraph<N, E> clone()
+	protected AbstractDirectedAdjacencyGraph<N, E> clone()
 	{
 		return (AbstractDirectedAdjacencyGraph<N, E>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/AbstractDirectedEdge.java b/src/main/java/com/syncleus/dann/graph/AbstractDirectedEdge.java
index bab69395cd2d231294463d5a1830a3221ac2f6f7..26584069551faabcf8e35ec42e8e0b4fa9295bd4 100644
--- a/src/main/java/com/syncleus/dann/graph/AbstractDirectedEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/AbstractDirectedEdge.java
@@ -18,45 +18,29 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
 
-public abstract class AbstractDirectedEdge<N> extends AbstractBidirectedEdge<N> implements DirectedEdge<N>
+public abstract class AbstractDirectedEdge<N, SN extends N, DN extends N> extends AbstractBidirectedEdge<N, SN,DN> implements MixableDirectedEdge<N, SN,DN>
 {
 	private static final long serialVersionUID = -7589242369886611386L;
 
-	protected AbstractDirectedEdge(final N source, final N destination)
-	{
-		super(source, EndState.INWARD, destination, EndState.OUTWARD);
-	}
-
-	protected AbstractDirectedEdge(final N source, final N destination, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
+	@Override
+	public final AbstractSourceEndpoint getLeftEndPoint()
 	{
-		super(source, EndState.INWARD, destination, EndState.OUTWARD, allowJoiningMultipleGraphs, contextEnabled);
+		return this.getSourceEndPoint();
 	}
 
 	@Override
-	public N getSourceNode()
+	public final AbstractDestinationEndpoint getRightEndPoint()
 	{
-		return this.getLeftNode();
+		return this.getDestinationEndPoint();
 	}
 
 	@Override
-	public N getDestinationNode()
-	{
-		return this.getRightNode();
-	}
+	public abstract AbstractSourceEndpoint getSourceEndPoint();
 
 	@Override
-	public List<N> getTraversableNodes(final N node)
-	{
-		if( this.getSourceNode().equals(node) )
-			return Collections.singletonList(this.getDestinationNode());
-		else if( this.getDestinationNode().equals(node) )
-			return Collections.emptyList();
-		else
-			throw new IllegalArgumentException("node is not one of the end points!");
-	}
+	public abstract AbstractDestinationEndpoint getDestinationEndPoint();
 
 	@Override
 	public final boolean isIntroverted()
@@ -97,32 +81,125 @@ public abstract class AbstractDirectedEdge<N> extends AbstractBidirectedEdge<N>
 	@Override
 	public String toString()
 	{
-		return this.getSourceNode() + "->" + this.getDestinationNode();
+		return this.getSourceEndPoint().getTarget() + "->" + this.getDestinationEndPoint().getTarget();
 	}
 
 	@Override
-	public AbstractDirectedEdge<N> disconnect(final N node)
+	protected AbstractDirectedEdge<N, SN,DN> clone()
 	{
-		if( node == null )
-			throw new IllegalArgumentException("node can not be null");
-		if( !this.getNodes().contains(node) )
-			throw new IllegalArgumentException("node is not currently connected to");
-		return (AbstractDirectedEdge<N>) this.remove(node);
+		return (AbstractDirectedEdge<N, SN,DN>) super.clone();
 	}
 
-	@Override
-	public AbstractDirectedEdge<N> disconnect(final List<N> nodes)
-	{
-		if( nodes == null )
-			throw new IllegalArgumentException("node can not be null");
-		if( !this.getNodes().containsAll(nodes) )
-			throw new IllegalArgumentException("node is not currently connected to");
-		return (AbstractDirectedEdge<N>) this.remove(nodes);
-	}
 
-	@Override
-	public AbstractDirectedEdge<N> clone()
+
+	protected abstract class AbstractSourceEndpoint extends AbstractEndpoint<SN,DN> implements MixableDirectedEdge.Endpoint<N, SN,DN>
 	{
-		return (AbstractDirectedEdge<N>) super.clone();
-	}
+		public AbstractSourceEndpoint()
+		{
+			super(Direction.INWARD);
+		}
+
+		public AbstractSourceEndpoint(SN node)
+		{
+			super(node, Direction.INWARD);
+		}
+
+		@Override
+		public final MixableBidirectedEdge.Endpoint<N, DN,SN> getNeighbor()
+		{
+			return getDestinationEndPoint();
+		}
+
+		@Override
+		public final Set<Endpoint<N, N>> getTraversableNeighborsTo()
+		{
+			return Collections.<Endpoint<N, N>>singleton(getDestinationEndPoint());
+		}
+
+		@Override
+		public final Set<Endpoint<N, N>> getTraversableNeighborsFrom()
+		{
+			return Collections.emptySet();
+		}
+
+		@Override
+		public final boolean isTraversable()
+		{
+			return true;
+		}
+
+		@Override
+		public final boolean isTraversable(Endpoint<N, N> destination)
+		{
+			if( destination == null )
+				throw new IllegalArgumentException("destination can not be null");
+
+			return destination.equals(this.getNeighbor());
+		}
+
+		@Override
+		public final boolean isTraversable(N destination)
+		{
+			if(destination == null)
+			{
+				if(this.getNeighbor().getTarget() == null)
+					return true;
+				else
+					return false;
+			}
+			else if(this.getNeighbor().getTarget() == null)
+				return false;
+
+			return destination.equals(this.getNeighbor().getTarget());
+		}
+	};
+
+	protected abstract class AbstractDestinationEndpoint extends AbstractEndpoint<DN,SN> implements MixableDirectedEdge.Endpoint<N, DN,SN>
+	{
+		public AbstractDestinationEndpoint()
+		{
+			super(Direction.OUTWARD);
+		}
+
+		public AbstractDestinationEndpoint(DN node)
+		{
+			super(node, Direction.OUTWARD);
+		}
+
+		@Override
+		public final MixableBidirectedEdge.Endpoint<N, SN,DN> getNeighbor()
+		{
+			return getDestinationEndPoint();
+		}
+
+		@Override
+		public final Set<Endpoint<N, N>> getTraversableNeighborsTo()
+		{
+			return Collections.emptySet();
+		}
+
+		@Override
+		public final Set<Endpoint<N, N>> getTraversableNeighborsFrom()
+		{
+			return Collections.<Endpoint<N, N>>singleton(getSourceEndPoint());
+		}
+
+		@Override
+		public final boolean isTraversable()
+		{
+			return false;
+		}
+
+		@Override
+		public final boolean isTraversable(Endpoint<N, N> destination)
+		{
+			return false;
+		}
+
+		@Override
+		public final boolean isTraversable(N destination)
+		{
+			return false;
+		}
+	};
 }
diff --git a/src/main/java/com/syncleus/dann/graph/AbstractEdge.java b/src/main/java/com/syncleus/dann/graph/AbstractEdge.java
index 3fedb0b60d1db1939d2098214c3e1789b0a2ed7a..849a6e5fb8f395bd2bd95d5b0ce5fe443c98490b 100644
--- a/src/main/java/com/syncleus/dann/graph/AbstractEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/AbstractEdge.java
@@ -18,15 +18,7 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import com.syncleus.dann.UnexpectedDannError;
-import com.syncleus.dann.graph.context.AbstractContextGraphElement;
-import com.syncleus.dann.graph.context.ContextNode;
+import java.util.*;
 import com.syncleus.dann.graph.xml.EdgeElementXml;
 import com.syncleus.dann.graph.xml.EdgeXml;
 import com.syncleus.dann.xml.NameXml;
@@ -35,157 +27,87 @@ import com.syncleus.dann.xml.Namer;
 import com.syncleus.dann.xml.XmlSerializable;
 import org.apache.log4j.Logger;
 
-public abstract class AbstractEdge<N> extends AbstractContextGraphElement<Graph<N, ?>> implements Edge<N>
+public abstract class AbstractEdge<
+	  	PA,
+	  	EP extends Edge.Endpoint<PA>
+	  > implements Edge<PA,EP>
 {
 	private static final Logger LOGGER = Logger.getLogger(AbstractEdge.class);
-	private final boolean contextEnabled;
-	private List<N> nodes;
-
-	protected AbstractEdge()
-	{
-		this(true, true);
-	}
-
-	protected AbstractEdge(final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
-	{
-		super(allowJoiningMultipleGraphs);
-		this.contextEnabled = contextEnabled;
-	}
-
-	protected AbstractEdge(final List<N> ourNodes)
-	{
-		this(ourNodes, true, true);
-	}
-
-	protected AbstractEdge(final List<N> ourNodes, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
-	{
-		super(allowJoiningMultipleGraphs);
-		this.contextEnabled = contextEnabled;
-
-		//make sure each node with context allows us to connect to it
-		if(contextEnabled)
-		{
-			final List<N> nodesCopy = new ArrayList<N>(ourNodes.size());
-			for(N ourNode : ourNodes)
-			{
-				if( this.contextEnabled && ( ourNode instanceof ContextNode ) && ( !((ContextNode)ourNode).connectingEdge(this) ))
-					continue;
-				nodesCopy.add(ourNode);
-			}
-			this.nodes = Collections.unmodifiableList(new ArrayList<N>(nodesCopy));
-		}
-		else
-			this.nodes = Collections.unmodifiableList(new ArrayList<N>(ourNodes));
-	}
-
-	protected AbstractEdge(final N... ourNodes)
-	{
-		this(true, true, ourNodes);
-	}
-
-	protected AbstractEdge(final boolean allowJoiningMultipleGraphs, final boolean contextEnabled, final N... ourNodes)
-	{
-		this(Arrays.asList(ourNodes), allowJoiningMultipleGraphs, contextEnabled);
-	}
 
 	@Override
-	public boolean isContextEnabled()
+	public boolean contains(final PA node)
 	{
-		return this.contextEnabled;
+		for( EP endpoint : this.getEndPoints() )
+			if( endpoint.getTarget().equals(node))
+				return true;
+		return false;
 	}
 
-	protected AbstractEdge<N> add(final N node)
+	@Override
+	public Set<PA> getTargets()
 	{
-		if( node == null )
-			throw new IllegalArgumentException("node can not be null");
-
-		final List<N> newNodes = new ArrayList<N>(this.nodes);
-		newNodes.add(node);
+		final Set<PA> nodes = new HashSet<PA>();
+		for( EP endpoint : this.getEndPoints() )
+			nodes.add(endpoint.getTarget());
 
-		return createDeepCopy(newNodes);
+		return Collections.unmodifiableSet(nodes);
 	}
 
-	protected AbstractEdge<N> add(final List<N> addNodes)
+	@Override
+	public Set<EP> getEndPoints(PA node)
 	{
-		if( addNodes == null )
-			throw new IllegalArgumentException("node can not be null");
-		final List<N> newNodes = new ArrayList<N>(this.nodes);
-		newNodes.addAll(addNodes);
+		final Set<EP> nodesEndpoints = new HashSet<EP>();
+		for( EP endpoint : this.getEndPoints() )
+			if( endpoint.getTarget().equals(node))
+				nodesEndpoints.add(endpoint);
 
-		return createDeepCopy(newNodes);
+		return Collections.unmodifiableSet(nodesEndpoints);
 	}
 
-	protected AbstractEdge<N> remove(final N node)
+	@Override
+	public Set<PA> getNeighbors(final PA source)
 	{
-		if( node == null )
-			throw new IllegalArgumentException("node can not be null");
-		if( !this.nodes.contains(node) )
-			throw new IllegalArgumentException("is not an endpoint");
+		final Set<PA> nodes = new HashSet<PA>();
+		for( final EP sourceEndpoint : this.getEndPoints(source) )
+			for( final Edge.Endpoint<PA> fromEndpoint : sourceEndpoint.getNeighbors())
+				nodes.add(fromEndpoint.getTarget());
 
-		final List<N> newNodes = new ArrayList<N>(this.nodes);
-		newNodes.remove(node);
-
-		return createDeepCopy(newNodes);
+		return Collections.unmodifiableSet(nodes);
 	}
 
-	protected AbstractEdge<N> remove(final List<N> removeNodes)
+	@Override
+	public Set<PA> getTraversableFrom(PA source)
 	{
-		if( removeNodes == null )
-			throw new IllegalArgumentException("removeNodes can not be null");
-		if( !this.nodes.containsAll(removeNodes) )
-			throw new IllegalArgumentException("removeNodes do not contain all valid end points");
-		final List<N> newNodes = new ArrayList<N>(this.nodes);
-		for(final N node : removeNodes)
-			newNodes.remove(node);
-
-		return createDeepCopy(newNodes);
-	}
+		final Set<PA> nodes = new HashSet<PA>();
+		for( final EP sourceEndpoint : this.getEndPoints(source) )
+			for( final Edge.Endpoint<PA> fromEndpoint : sourceEndpoint.getTraversableNeighborsFrom())
+				nodes.add(fromEndpoint.getTarget());
 
-	/**
-	 * Create a deep copy of this edge, but with a new set of nodes.
-	 * @param newNodes the set of nodes to use instead of the current ones.
-	 * @return a deep copy of this edge, but with a new set of nodes.
-	 */
-	private AbstractEdge<N> createDeepCopy(final List<N> newNodes)
-	{
-		try
-		{
-			final AbstractEdge<N> clonedEdge = (AbstractEdge<N>) super.clone();
-			final List<N> clonedNodes = new ArrayList<N>(this.nodes.size());
-			//add each node at a time to the clone considering context
-			for(N newNode : newNodes)
-			{
-				if( this.contextEnabled && (newNode instanceof ContextNode) && ( !((ContextNode)newNode).connectingEdge(clonedEdge) ) )
-					continue;
-				clonedNodes.add(newNode);
-			}
-			clonedEdge.nodes = Collections.unmodifiableList(clonedNodes);
-			return clonedEdge;
-		}
-		catch(CloneNotSupportedException caught)
-		{
-			LOGGER.error("Edge was unexpectidly not cloneable", caught);
-			throw new UnexpectedDannError("Edge was unexpectidly not cloneable", caught);
-		}
+		return Collections.unmodifiableSet(nodes);
 	}
 
 	@Override
-	public boolean isTraversable(final N node)
+	public Set<PA> getTraversableTo(PA destination)
 	{
-		return (!this.getTraversableNodes(node).isEmpty());
+		final Set<PA> nodes = new HashSet<PA>();
+		for( final EP destinationEndpoint : this.getEndPoints(destination) )
+			for( final Edge.Endpoint<PA> fromEndpoint : destinationEndpoint.getTraversableNeighborsTo())
+				nodes.add(fromEndpoint.getTarget());
+
+		return Collections.unmodifiableSet(nodes);
 	}
 
 	@Override
-	public final List<N> getNodes()
+	public int getDegree()
 	{
-		return this.nodes;
+		return this.getTargets().size();
 	}
 
 	@Override
 	public String toString()
 	{
-		final StringBuilder outString = new StringBuilder(this.nodes.size() * 10);
-		for(final N node : this.nodes)
+		final StringBuilder outString = new StringBuilder(this.getTargets().size() * 10);
+		for(final PA node : this.getTargets())
 		{
 			outString.append(':').append(node);
 		}
@@ -193,26 +115,16 @@ public abstract class AbstractEdge<N> extends AbstractContextGraphElement<Graph<
 	}
 
 	@Override
-	public AbstractEdge<N> clone()
+	protected AbstractEdge<PA,EP> clone()
 	{
 		try
 		{
-			final AbstractEdge<N> clonedEdge = (AbstractEdge<N>) super.clone();
-			final List<N> clonedNodes = new ArrayList<N>(this.nodes.size());
-			//add each node at a time to the clone considering context
-			for(N node : this.nodes)
-			{
-				if( this.contextEnabled && (node instanceof ContextNode) && ( !((ContextNode)node).connectingEdge(clonedEdge) ) )
-					continue;
-				clonedNodes.add(node);
-			}
-			clonedEdge.nodes = Collections.unmodifiableList(clonedNodes);
-			return clonedEdge;
+			return (AbstractEdge<PA,EP>) super.clone();
 		}
 		catch(CloneNotSupportedException caught)
 		{
 			LOGGER.error("Edge was unexpectidly not cloneable", caught);
-			throw new UnexpectedDannError("Edge was unexpectidly not cloneable", caught);
+			throw new Error("Edge was unexpectidly not cloneable", caught);
 		}
 	}
 
@@ -223,8 +135,8 @@ public abstract class AbstractEdge<N> extends AbstractContextGraphElement<Graph<
 		final EdgeElementXml xml = new EdgeElementXml();
 
 		xml.setNodeInstances(new EdgeElementXml.NodeInstances());
-		final Set<N> writtenNodes = new HashSet<N>();
-		for (N node : this.nodes)
+		final Set<PA> writtenNodes = new HashSet<PA>();
+		for (PA node : this.getTargets())
 		{
 			if (writtenNodes.add(node))
 			{
@@ -275,11 +187,192 @@ public abstract class AbstractEdge<N> extends AbstractContextGraphElement<Graph<
 		{
 			jaxbObject.setConnections(new EdgeXml.Connections());
 		}
-		for (N node : this.nodes)
+		for (PA node : this.getTargets())
 		{
 			final NameXml connection = new NameXml();
 			connection.setName(nodeNames.getNameOrCreate(node));
 			jaxbObject.getConnections().getNodes().add(connection);
 		}
 	}
+
+	protected abstract class AbstractEndpoint implements Edge.Endpoint<PA>
+	{
+		protected AbstractEndpoint()
+		{
+		}
+
+		@Override
+		public Set<Edge.Endpoint<PA>> getNeighbors()
+		{
+			return new NeighborSet();
+		}
+
+		@Override
+		public Set<Edge.Endpoint<PA>> getTraversableNeighborsTo()
+		{
+			final Set<Edge.Endpoint<PA>> traversables = new HashSet<Edge.Endpoint<PA>>();
+			for(Edge.Endpoint<PA> neighbor : this.getNeighbors())
+				if( AbstractEdge.this.isTraversable(this.getTarget(),neighbor.getTarget()) )
+					traversables.add(neighbor);
+			return Collections.unmodifiableSet(traversables);
+		}
+
+		@Override
+		public Set<Edge.Endpoint<PA>> getTraversableNeighborsFrom()
+		{
+			final Set<Edge.Endpoint<PA>> traversables = new HashSet<Edge.Endpoint<PA>>();
+			for(Edge.Endpoint<PA> neighbor : this.getNeighbors())
+				if( AbstractEdge.this.isTraversable(this.getTarget(),neighbor.getTarget()) )
+					traversables.add(neighbor);
+			return Collections.unmodifiableSet(traversables);
+		}
+
+		@Override
+		public boolean isTraversable()
+		{
+			return (this.getTraversableNeighborsTo().size() > 0);
+		}
+
+		@Override
+		public boolean isTraversable(Edge.Endpoint<PA> destination)
+		{
+			return AbstractEdge.this.isTraversable(this.getTarget(), destination.getTarget());
+		}
+
+		@Override
+		public boolean isTraversable(PA destination)
+		{
+			return AbstractEdge.this.isTraversable(this.getTarget(), destination);
+		}
+
+		private class NeighborSet implements Set<Edge.Endpoint<PA>>
+		{
+			@Override
+			public int size()
+			{
+				return getTargets().size() - 1;
+			}
+
+			@Override
+			public boolean isEmpty()
+			{
+				assert !getTargets().isEmpty();
+				return ( getEndPoints().size() <= 1 ? true : false );
+			}
+
+			@Override
+			public boolean contains(Object o)
+			{
+				if( getTarget().equals(o) )
+					return false;
+				return getEndPoints().contains(o);
+			}
+
+			@Override
+			public Iterator<Edge.Endpoint<PA>> iterator()
+			{
+				return new NeighborIterator();
+			}
+
+			@Override
+			public Object[] toArray()
+			{
+				final Set<EP> copiedNodes = new HashSet<EP>(getEndPoints());
+				copiedNodes.remove(getTarget());
+				return copiedNodes.toArray();
+			}
+
+			@Override
+			public <PA> PA[] toArray(PA[] a)
+			{
+				final Set<EP> copiedNodes = new HashSet<EP>(getEndPoints());
+				copiedNodes.remove(getTarget());
+				return copiedNodes.toArray(a);
+			}
+
+			@Override
+			public boolean add(Edge.Endpoint<PA> nEndpoint)
+			{
+				throw new UnsupportedOperationException("This set is read-only!");
+			}
+
+			@Override
+			public boolean remove(Object o)
+			{
+				throw new UnsupportedOperationException("This set is read-only!");
+			}
+
+			@Override
+			public boolean containsAll(Collection<?> c)
+			{
+				if( c.contains(AbstractEndpoint.this) )
+					return false;
+				return getEndPoints().containsAll(c);
+			}
+
+			@Override
+			public boolean addAll(Collection<? extends Edge.Endpoint<PA>> c)
+			{
+				throw new UnsupportedOperationException("This set is read-only!");
+			}
+
+			@Override
+			public boolean retainAll(Collection<?> c)
+			{
+				if( c.containsAll(this) )
+					return false;
+				throw new UnsupportedOperationException("This set is read-only!");
+			}
+
+			@Override
+			public boolean removeAll(Collection<?> c)
+			{
+				if( Collections.disjoint(this, c) )
+					return false;
+				throw new UnsupportedOperationException("This set is read-only!");
+			}
+
+			@Override
+			public void clear()
+			{
+				if( getEndPoints().size() <= 1 )
+					return;
+				throw new UnsupportedOperationException("This set is read-only!");
+			}
+
+			private class NeighborIterator implements Iterator<Edge.Endpoint<PA>>
+			{
+				private int nextLeft = (getEndPoints().size()-1);
+				final private Iterator<EP> iterator;
+
+				public NeighborIterator()
+				{
+					this.iterator = getEndPoints().iterator();
+				}
+
+				@Override
+				public boolean hasNext()
+				{
+					return (nextLeft > 0 ? true : false);
+				}
+
+				@Override
+				public Edge.Endpoint<PA> next()
+				{
+					Edge.Endpoint<PA> nextEndpoint = this.iterator.next();
+					this.nextLeft--;
+
+					if( !AbstractEndpoint.this.equals(nextEndpoint) )
+						return nextEndpoint;
+					return next();
+				}
+
+				@Override
+				public void remove()
+				{
+					throw new UnsupportedOperationException("This iterator is read-only!");
+				}
+			};
+		};
+	};
 }
diff --git a/src/main/java/com/syncleus/dann/graph/AbstractHyperAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graph/AbstractHyperAdjacencyGraph.java
index 973fb598546c1cdd06548e58f1fcffcb4ae1653f..639cecaef39b308ebab49a612242c8c445d03520 100644
--- a/src/main/java/com/syncleus/dann/graph/AbstractHyperAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/AbstractHyperAdjacencyGraph.java
@@ -29,7 +29,7 @@ public abstract class AbstractHyperAdjacencyGraph<N, E extends HyperEdge<N>> ext
 
 	protected AbstractHyperAdjacencyGraph(final Graph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 
 	protected AbstractHyperAdjacencyGraph(final Set<N> nodes, final Set<E> edges)
@@ -81,43 +81,7 @@ public abstract class AbstractHyperAdjacencyGraph<N, E extends HyperEdge<N>> ext
 	}
 
 	@Override
-	public AbstractHyperAdjacencyGraph<N, E> cloneAdd(final E newEdge)
-	{
-		return (AbstractHyperAdjacencyGraph<N, E>) super.cloneAdd(newEdge);
-	}
-
-	@Override
-	public AbstractHyperAdjacencyGraph<N, E> cloneAdd(final N newNode)
-	{
-		return (AbstractHyperAdjacencyGraph<N, E>) super.cloneAdd(newNode);
-	}
-
-	@Override
-	public AbstractHyperAdjacencyGraph<N, E> cloneAdd(final Set<N> newNodes, final Set<E> newEdges)
-	{
-		return (AbstractHyperAdjacencyGraph<N, E>) super.cloneAdd(newNodes, newEdges);
-	}
-
-	@Override
-	public AbstractHyperAdjacencyGraph<N, E> cloneRemove(final E edgeToRemove)
-	{
-		return (AbstractHyperAdjacencyGraph<N, E>) super.cloneRemove(edgeToRemove);
-	}
-
-	@Override
-	public AbstractHyperAdjacencyGraph<N, E> cloneRemove(final N nodeToRemove)
-	{
-		return (AbstractHyperAdjacencyGraph<N, E>) super.cloneRemove(nodeToRemove);
-	}
-
-	@Override
-	public AbstractHyperAdjacencyGraph<N, E> cloneRemove(final Set<N> deleteNodes, final Set<E> deleteEdges)
-	{
-		return (AbstractHyperAdjacencyGraph<N, E>) super.cloneRemove(deleteNodes, deleteEdges);
-	}
-
-	@Override
-	public AbstractHyperAdjacencyGraph<N, E> clone()
+	protected AbstractHyperAdjacencyGraph<N, E> clone()
 	{
 		return (AbstractHyperAdjacencyGraph<N, E>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/AbstractHyperEdge.java b/src/main/java/com/syncleus/dann/graph/AbstractHyperEdge.java
index c98af1fd7b9455e4c382dee772ac02c66279401b..671f103c61c0d5623056ae55c337cfaf7e3c76fd 100644
--- a/src/main/java/com/syncleus/dann/graph/AbstractHyperEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/AbstractHyperEdge.java
@@ -18,38 +18,87 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
 public abstract class AbstractHyperEdge<N> extends AbstractEdge<N> implements HyperEdge<N>
 {
 	private static final long serialVersionUID = -3657973823101515199L;
 
-	protected AbstractHyperEdge(final List<N> nodes)
+/*
+	protected AbstractHyperEdge(final List<N> nodes, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
 	{
-		super(nodes);
+		super(nodes, allowJoiningMultipleGraphs, contextEnabled);
+
+		if(this.contextEnabled)
+		{
+			this.nodes = new ArrayList<N>(ourNodes.size());
+			try
+			{
+				for( N node : ourNodes )
+				{
+					if( node instanceof ContextNode )
+						((ContextNode)node).connectingEdge(this);
+
+					this.nodes.add(node);
+					if( node instanceof ContextNode )
+						((ContextNode)node).connectedEdge(this);
+				}
+			}
+			catch(RejectedContextException caught)
+			{
+				//we need to remove any connections we established before we bail
+				for(N node : this.nodes)
+					if( node instanceof ContextNode )
+						((ContextNode)node).disconnectedEdge(this);
+				throw new InvalidContextException(caught);
+			}
+		}
+		else
+			this.nodes = new ArrayList<N>(ourNodes);
 	}
 
-	protected AbstractHyperEdge(final N... nodes)
+
+	protected AbstractHyperEdge(final boolean allowJoiningMultipleGraphs, final boolean contextEnabled, final N... nodes)
 	{
-		super(nodes);
+		super(allowJoiningMultipleGraphs, contextEnabled, nodes);
 	}
 
-	protected AbstractHyperEdge(final List<N> nodes, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
+	protected void addNode(final N node)
 	{
-		super(nodes, allowJoiningMultipleGraphs, contextEnabled);
+		try
+		{
+			if( this.contextEnabled && (node instanceof ContextNode) )
+				((ContextNode)node).connectingEdge(this);
+		}
+		catch(RejectedContextException caught)
+		{
+			throw new InvalidContextException(caught);
+		}
+
+		this.nodes.add(node);
+		if( this.contextEnabled && (node instanceof ContextNode) )
+			((ContextNode)node).connectedEdge(this);
 	}
 
-	protected AbstractHyperEdge(final boolean allowJoiningMultipleGraphs, final boolean contextEnabled, final N... nodes)
+	protected void removeNode(final N node)
 	{
-		super(allowJoiningMultipleGraphs, contextEnabled, nodes);
+		try
+		{
+			if( this.contextEnabled && (node instanceof ContextNode) )
+				((ContextNode)node).disconnectingEdge(this);
+		}
+		catch(RejectedContextException caught)
+		{
+			throw new InvalidContextException(caught);
+		}
+
+		this.nodes.remove(node);
+		if( this.contextEnabled && (node instanceof ContextNode) )
+			((ContextNode)node).disconnectedEdge(this);
 	}
 
 	@Override
 	public List<N> getTraversableNodes(final N node)
 	{
-		final List<N> traversableNodes = new ArrayList<N>(this.getNodes());
+		final List<N> traversableNodes = new ArrayList<N>(this.getTargets());
 		if( !traversableNodes.remove(node) )
 			throw new IllegalArgumentException("node is not one of the end points!");
 		return Collections.unmodifiableList(traversableNodes);
@@ -58,9 +107,10 @@ public abstract class AbstractHyperEdge<N> extends AbstractEdge<N> implements Hy
 	@Override
 	public int getDegree()
 	{
-		return this.getNodes().size();
+		return this.getTargets().size();
 	}
-
+*/
+	// TODO : Implement This!
 	@Override
 	public boolean isSymmetric(final HyperEdge symmetricEdge)
 	{
@@ -68,49 +118,65 @@ public abstract class AbstractHyperEdge<N> extends AbstractEdge<N> implements Hy
 	}
 
 	@Override
-	public AbstractHyperEdge<N> connect(final N node)
+	protected AbstractHyperEdge<N> clone()
 	{
-		if( node == null )
-			throw new IllegalArgumentException("node can not be null");
-		if( this.getNodes().contains(node) )
-			throw new IllegalArgumentException("node is already connected");
-		return (AbstractHyperEdge<N>) this.add(node);
-	}
+		return (AbstractHyperEdge<N>) super.clone();
+/*
+		final AbstractHyperEdge<N> clonedEdge = (AbstractHyperEdge<N>) super.clone();
 
-	@Override
-	public AbstractHyperEdge<N> connect(final List<N> nodes)
-	{
-		if( nodes == null )
-			throw new IllegalArgumentException("node can not be null");
-		for(final N node : nodes)
-			if( this.getNodes().contains(node) )
-				throw new IllegalArgumentException("node is already connected");
-		return (AbstractHyperEdge<N>) this.add(nodes);
-	}
+		if( !this.contextEnabled )
+			return clonedEdge;
 
-	@Override
-	public AbstractHyperEdge<N> disconnect(final N node)
-	{
-		if( node == null )
-			throw new IllegalArgumentException("node can not be null");
-		if( !this.getNodes().contains(node) )
-			throw new IllegalArgumentException("node is not currently connected to");
-		return (AbstractHyperEdge<N>) this.remove(node);
-	}
+		List<ContextNode> connectedNodes = new ArrayList<ContextNode>();
+		try
+		{
+			for(N node : this.nodes)
+			{
+				if( node instanceof ContextNode )
+				{
+					ContextNode contextNode = (ContextNode)node;
+					contextNode.connectingEdge(clonedEdge);
+					contextNode.connectedEdge(clonedEdge);
+					connectedNodes.add(contextNode);
+				}
+			}
+		}
+		catch(RejectedContextException caught)
+		{
+			//we need to leave all the connections we made
+			for(ContextNode connectedNode : connectedNodes)
+				connectedNode.disconnectedEdge(clonedEdge);
+			throw new InvalidContextException(caught);
+		}
 
-	@Override
-	public AbstractHyperEdge<N> disconnect(final List<N> nodes)
-	{
-		if( nodes == null )
-			throw new IllegalArgumentException("node can not be null");
-		if( !this.getNodes().containsAll(nodes) )
-			throw new IllegalArgumentException("node is not currently connected to");
-		return (AbstractHyperEdge<N>) this.remove(nodes);
+		return clonedEdge;
+*/
 	}
 
-	@Override
-	public AbstractHyperEdge<N> clone()
+	protected abstract class AbstractEndpoint<EN extends N, ON extends N> extends AbstractEdge.AbstractEndpoint<EN> implements HyperEdge.Endpoint<N, EN>
 	{
-		return (AbstractHyperEdge<N>) super.clone();
-	}
+		private EN node = null;
+
+		protected AbstractEndpoint()
+		{
+			super();
+		}
+
+		protected AbstractEndpoint(EN node)
+		{
+			super();
+			this.node = node;
+		}
+
+		@Override
+		public EN getTarget()
+		{
+			return this.node;
+		}
+
+		public void setTarget(final EN node)
+		{
+			this.node = node;
+		}
+	};
 }
diff --git a/src/main/java/com/syncleus/dann/graph/AbstractRootedTreeAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graph/AbstractRootedTreeAdjacencyGraph.java
index 398e66838cf4e546f682e56ea6c0f9bef2dd617a..468cd0c612373ef127a705cbadf6e68724e2dcea 100644
--- a/src/main/java/com/syncleus/dann/graph/AbstractRootedTreeAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/AbstractRootedTreeAdjacencyGraph.java
@@ -34,7 +34,7 @@ public abstract class AbstractRootedTreeAdjacencyGraph<N, E extends DirectedEdge
 
 	protected AbstractRootedTreeAdjacencyGraph(final DirectedGraph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 		if( !Trees.isRootedTree(copyGraph) )
 			throw new IllegalArgumentException("copyGraph is not a rooted tree");
 	}
@@ -61,52 +61,15 @@ public abstract class AbstractRootedTreeAdjacencyGraph<N, E extends DirectedEdge
 	@Override
 	public N getRoot()
 	{
-		if( this.getNodes().isEmpty() )
+		if( this.getTargets().isEmpty() )
 			return null;
 
 		final TopologicalSorter<N> sorter = new SimpleTopologicalRanker<N>();
 		return sorter.sort(this).get(0);
 	}
 
-	// TODO ensure these clones cant produce non-rooted trees
 	@Override
-	public AbstractRootedTreeAdjacencyGraph<N, E> cloneAdd(final E newEdge)
-	{
-		return (AbstractRootedTreeAdjacencyGraph<N, E>) super.cloneAdd(newEdge);
-	}
-
-	@Override
-	public AbstractRootedTreeAdjacencyGraph<N, E> cloneAdd(final N newNode)
-	{
-		return (AbstractRootedTreeAdjacencyGraph<N, E>) super.cloneAdd(newNode);
-	}
-
-	@Override
-	public AbstractRootedTreeAdjacencyGraph<N, E> cloneAdd(final Set<N> newNodes, final Set<E> newEdges)
-	{
-		return (AbstractRootedTreeAdjacencyGraph<N, E>) super.cloneAdd(newNodes, newEdges);
-	}
-
-	@Override
-	public AbstractRootedTreeAdjacencyGraph<N, E> cloneRemove(final E edgeToRemove)
-	{
-		return (AbstractRootedTreeAdjacencyGraph<N, E>) super.cloneRemove(edgeToRemove);
-	}
-
-	@Override
-	public AbstractRootedTreeAdjacencyGraph<N, E> cloneRemove(final N nodeToRemove)
-	{
-		return (AbstractRootedTreeAdjacencyGraph<N, E>) super.cloneRemove(nodeToRemove);
-	}
-
-	@Override
-	public AbstractRootedTreeAdjacencyGraph<N, E> cloneRemove(final Set<N> deleteNodes, final Set<E> deleteEdges)
-	{
-		return (AbstractRootedTreeAdjacencyGraph<N, E>) super.cloneRemove(deleteNodes, deleteEdges);
-	}
-
-	@Override
-	public AbstractRootedTreeAdjacencyGraph<N, E> clone()
+	protected AbstractRootedTreeAdjacencyGraph<N, E> clone()
 	{
 		return (AbstractRootedTreeAdjacencyGraph<N, E>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/AbstractTreeAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graph/AbstractTreeAdjacencyGraph.java
index 14b0ac2e76706ecc11fc5a4ef0e0bbb12b20cb08..1cbc171f5f7c09716fe118d628d6af08f448eda9 100644
--- a/src/main/java/com/syncleus/dann/graph/AbstractTreeAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/AbstractTreeAdjacencyGraph.java
@@ -34,7 +34,7 @@ public abstract class AbstractTreeAdjacencyGraph<N, E extends BidirectedEdge<N>>
 
 	protected AbstractTreeAdjacencyGraph(final BidirectedGraph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 		if( !Trees.isTree(copyGraph) )
 			throw new IllegalArgumentException("copyGraph is not a Tree");
 	}
@@ -73,51 +73,14 @@ public abstract class AbstractTreeAdjacencyGraph<N, E extends BidirectedEdge<N>>
 	@Override
 	public boolean isLeaf(final E edge)
 	{
-		for(final N node : edge.getNodes())
+		for(final N node : edge.getTargets())
 			if( this.isLeaf(node) )
 				return true;
 		return false;
 	}
 
-	// TODO make sure these clones cant produce non-tree graphs.
 	@Override
-	public AbstractTreeAdjacencyGraph<N, E> cloneAdd(final E newEdge)
-	{
-		return (AbstractTreeAdjacencyGraph<N, E>) super.cloneAdd(newEdge);
-	}
-
-	@Override
-	public AbstractTreeAdjacencyGraph<N, E> cloneAdd(final N newNode)
-	{
-		return (AbstractTreeAdjacencyGraph<N, E>) super.cloneAdd(newNode);
-	}
-
-	@Override
-	public AbstractTreeAdjacencyGraph<N, E> cloneAdd(final Set<N> newNodes, final Set<E> newEdges)
-	{
-		return (AbstractTreeAdjacencyGraph<N, E>) super.cloneAdd(newNodes, newEdges);
-	}
-
-	@Override
-	public AbstractTreeAdjacencyGraph<N, E> cloneRemove(final E edgeToRemove)
-	{
-		return (AbstractTreeAdjacencyGraph<N, E>) super.cloneRemove(edgeToRemove);
-	}
-
-	@Override
-	public AbstractTreeAdjacencyGraph<N, E> cloneRemove(final N nodeToRemove)
-	{
-		return (AbstractTreeAdjacencyGraph<N, E>) super.cloneRemove(nodeToRemove);
-	}
-
-	@Override
-	public AbstractTreeAdjacencyGraph<N, E> cloneRemove(final Set<N> deleteNodes, final Set<E> deleteEdges)
-	{
-		return (AbstractTreeAdjacencyGraph<N, E>) super.cloneRemove(deleteNodes, deleteEdges);
-	}
-
-	@Override
-	public AbstractTreeAdjacencyGraph<N, E> clone()
+	protected AbstractTreeAdjacencyGraph<N, E> clone()
 	{
 		return (AbstractTreeAdjacencyGraph<N, E>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/AbstractUndirectedEdge.java b/src/main/java/com/syncleus/dann/graph/AbstractUndirectedEdge.java
index c7970bb64cda8791a806971cb3a79736ae194ee3..dfbb73f467ccd281fd91d822d3f5cc8fe3df9149 100644
--- a/src/main/java/com/syncleus/dann/graph/AbstractUndirectedEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/AbstractUndirectedEdge.java
@@ -18,19 +18,18 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
 
-public abstract class AbstractUndirectedEdge<N> extends AbstractBidirectedEdge<N> implements UndirectedEdge<N>
+public abstract class AbstractUndirectedEdge<N, LN extends N, RN extends N> extends AbstractBidirectedEdge<N, LN,RN> implements MixableBidirectedEdge<N, LN,RN>
 {
 	private static final long serialVersionUID = 83475809132709850L;
 
-	protected AbstractUndirectedEdge(final N leftNode, final N rightNode)
+	protected AbstractUndirectedEdge(final LN leftNode, final RN rightNode)
 	{
 		super(leftNode, EndState.NONE, rightNode, EndState.NONE);
 	}
 
-	protected AbstractUndirectedEdge(final N leftNode, final N rightNode, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
+	protected AbstractUndirectedEdge(final LN leftNode, final RN rightNode, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
 	{
 		super(leftNode, EndState.NONE, rightNode, EndState.NONE, allowJoiningMultipleGraphs, contextEnabled);
 	}
@@ -83,28 +82,8 @@ public abstract class AbstractUndirectedEdge<N> extends AbstractBidirectedEdge<N
 	}
 
 	@Override
-	public AbstractUndirectedEdge<N> disconnect(final N node)
+	protected AbstractUndirectedEdge<N, LN,RN> clone()
 	{
-		if( node == null )
-			throw new IllegalArgumentException("node can not be null");
-		if( !this.getNodes().contains(node) )
-			throw new IllegalArgumentException("node is not currently connected to");
-		return (AbstractUndirectedEdge<N>) this.remove(node);
-	}
-
-	@Override
-	public AbstractUndirectedEdge<N> disconnect(final List<N> nodes)
-	{
-		if( nodes == null )
-			throw new IllegalArgumentException("node can not be null");
-		if( !this.getNodes().containsAll(nodes) )
-			throw new IllegalArgumentException("node is not currently connected to");
-		return (AbstractUndirectedEdge<N>) this.remove(nodes);
-	}
-
-	@Override
-	public AbstractUndirectedEdge<N> clone()
-	{
-		return (AbstractUndirectedEdge<N>) super.clone();
+		return (AbstractUndirectedEdge<N, LN,RN>) super.clone();
 	}
 }
diff --git a/src/main/java/com/syncleus/dann/graph/AbstractUniqueBidirectedEdge.java b/src/main/java/com/syncleus/dann/graph/AbstractUniqueBidirectedEdge.java
deleted file mode 100644
index 77c6d9dce95328dcaf2188da61a4921c998002aa..0000000000000000000000000000000000000000
--- a/src/main/java/com/syncleus/dann/graph/AbstractUniqueBidirectedEdge.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/******************************************************************************
- *                                                                             *
- *  Copyright: (c) Syncleus, Inc.                                              *
- *                                                                             *
- *  You may redistribute and modify this source code under the terms and       *
- *  conditions of the Open Source Community License - Type C version 1.0       *
- *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
- *  There should be a copy of the license included with this file. If a copy   *
- *  of the license is not included you are granted no right to distribute or   *
- *  otherwise use this file except through a legal and valid license. You      *
- *  should also contact Syncleus, Inc. at the information below if you cannot  *
- *  find a license:                                                            *
- *                                                                             *
- *  Syncleus, Inc.                                                             *
- *  2604 South 12th Street                                                     *
- *  Philadelphia, PA 19148                                                     *
- *                                                                             *
- ******************************************************************************/
-package com.syncleus.dann.graph;
-
-public abstract class AbstractUniqueBidirectedEdge<N> extends AbstractBidirectedEdge<N>
-{
-	protected AbstractUniqueBidirectedEdge()
-	{
-		super();
-	}
-
-	protected AbstractUniqueBidirectedEdge(final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
-	{
-		super(allowJoiningMultipleGraphs, contextEnabled);
-	}
-
-	protected AbstractUniqueBidirectedEdge(final N leftNode, final EndState leftEndState, final N rightNode, final EndState rightEndState)
-	{
-		super(leftNode, leftEndState, rightNode, rightEndState);
-	}
-
-	protected AbstractUniqueBidirectedEdge(final N leftNode, final EndState leftEndState, final N rightNode, final EndState rightEndState, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
-	{
-		super(leftNode, leftEndState, rightNode, rightEndState, allowJoiningMultipleGraphs, contextEnabled);
-	}
-
-	@Override
-	public boolean equals(final Object compareToObj)
-	{
-		if( compareToObj == null )
-			return false;
-
-		if( !(compareToObj instanceof BidirectedEdge) )
-			return false;
-
-		final BidirectedEdge compareTo = (BidirectedEdge) compareToObj;
-		return
-				(
-						(compareTo.getLeftNode().equals(this.getLeftNode()))
-								&& (compareTo.getRightNode().equals(this.getRightNode()))
-								&& (compareTo.getLeftEndState().equals(this.getLeftEndState()))
-								&& (compareTo.getRightEndState().equals(this.getRightEndState()))
-				)
-						|| (
-								(compareTo.getLeftNode().equals(this.getRightNode()))
-										&& (compareTo.getRightNode().equals(this.getLeftNode()))
-										&& (compareTo.getLeftEndState().equals(this.getRightEndState()))
-										&& (compareTo.getRightEndState().equals(this.getLeftEndState()))
-						);
-	}
-
-	@Override
-	public int hashCode()
-	{
-		final int leftNodeHash = this.getLeftNode().hashCode();
-		final int rightNodeHash = this.getRightNode().hashCode();
-		final int leftStateHash = this.getLeftEndState().hashCode();
-		final int rightStateHash = this.getRightEndState().hashCode();
-		return
-				leftNodeHash
-						+ (leftNodeHash * leftStateHash)
-						+ rightNodeHash
-						+ (rightNodeHash * rightStateHash);
-	}
-}
diff --git a/src/main/java/com/syncleus/dann/graph/AbstractWalk.java b/src/main/java/com/syncleus/dann/graph/AbstractWalk.java
index 599bddceaf3eb94596e33812c2d7b306f26e4baf..b5189de4a5460814b0bb41d1f64ca61b5e13c8a2 100644
--- a/src/main/java/com/syncleus/dann/graph/AbstractWalk.java
+++ b/src/main/java/com/syncleus/dann/graph/AbstractWalk.java
@@ -41,11 +41,11 @@ public abstract class AbstractWalk<N, E extends Edge<N>> implements Walk<N, E>
 		int nextNodeIndex = 0;
 		for(final E edgeStep : edgeSteps)
 		{
-			if( !edgeStep.getNodes().contains(nodeSteps.get(nextNodeIndex)) )
+			if( !edgeStep.getTargets().contains(nodeSteps.get(nextNodeIndex)) )
 				return false;
 			nextNodeIndex++;
 		}
-		return edgeSteps.get(edgeSteps.size() - 1).getNodes().contains(nodeSteps.get(nextNodeIndex));
+		return edgeSteps.get(edgeSteps.size() - 1).getTargets().contains(nodeSteps.get(nextNodeIndex));
 	}
 
 	@Override
diff --git a/src/main/java/com/syncleus/dann/graph/AbstractWeightedBidirectedEdge.java b/src/main/java/com/syncleus/dann/graph/AbstractWeightedBidirectedEdge.java
index d0c1d628d4c79812c1d9afda6139ddcbdf2d17f2..604767c04afc7dd3e4030b188af36da0283918cb 100644
--- a/src/main/java/com/syncleus/dann/graph/AbstractWeightedBidirectedEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/AbstractWeightedBidirectedEdge.java
@@ -18,7 +18,7 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-public abstract class AbstractWeightedBidirectedEdge<N> extends AbstractBidirectedEdge<N> implements WeightedBidirectedEdge<N>
+public abstract class AbstractWeightedBidirectedEdge<N, LN extends N, RN extends N> extends AbstractBidirectedEdge<N, LN,RN> implements WeightedMixableBidirectedEdge<LN,RN,N>
 {
 	private final double weight;
 
@@ -34,14 +34,14 @@ public abstract class AbstractWeightedBidirectedEdge<N> extends AbstractBidirect
 		this.weight = weight;
 	}
 
-	protected AbstractWeightedBidirectedEdge(final N leftNode, final EndState leftEndState, final N rightNode, final EndState rightEndState, final double ourWeight)
+	protected AbstractWeightedBidirectedEdge(final LN leftNode, final EndState leftEndState, final RN rightNode, final EndState rightEndState, final double ourWeight)
 	{
 		super(leftNode, leftEndState, rightNode, rightEndState);
 
 		this.weight = ourWeight;
 	}
 
-	protected AbstractWeightedBidirectedEdge(final N leftNode, final EndState leftEndState, final N rightNode, final EndState rightEndState, final double ourWeight, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
+	protected AbstractWeightedBidirectedEdge(final LN leftNode, final EndState leftEndState, final RN rightNode, final EndState rightEndState, final double ourWeight, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
 	{
 		super(leftNode, leftEndState, rightNode, rightEndState, allowJoiningMultipleGraphs, contextEnabled);
 
@@ -55,8 +55,8 @@ public abstract class AbstractWeightedBidirectedEdge<N> extends AbstractBidirect
 	}
 
 	@Override
-	public AbstractWeightedBidirectedEdge<N> clone()
+	protected AbstractWeightedBidirectedEdge<N, LN,RN> clone()
 	{
-		return (AbstractWeightedBidirectedEdge<N>) super.clone();
+		return (AbstractWeightedBidirectedEdge<N, LN,RN>) super.clone();
 	}
 }
diff --git a/src/main/java/com/syncleus/dann/graph/AbstractWeightedEdge.java b/src/main/java/com/syncleus/dann/graph/AbstractWeightedEdge.java
index e76155ef5c7c38b73291db74991d42960b4ac97c..195fa3723a4eaf3fcea5305c253d52b0a8abf2ef 100644
--- a/src/main/java/com/syncleus/dann/graph/AbstractWeightedEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/AbstractWeightedEdge.java
@@ -55,7 +55,7 @@ public abstract class AbstractWeightedEdge<N> extends AbstractEdge<N> implements
 	}
 
 	@Override
-	public AbstractWeightedEdge<N> clone()
+	protected AbstractWeightedEdge<N> clone()
 	{
 		return (AbstractWeightedEdge<N>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/AbstractUniqueEdge.java b/src/main/java/com/syncleus/dann/graph/AssignableGraph.java
similarity index 55%
rename from src/main/java/com/syncleus/dann/graph/AbstractUniqueEdge.java
rename to src/main/java/com/syncleus/dann/graph/AssignableGraph.java
index 2d3546165566f2a293148c57bcd694f1959f8e53..b2642989f154819601a643791535a90a9771a825 100644
--- a/src/main/java/com/syncleus/dann/graph/AbstractUniqueEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/AssignableGraph.java
@@ -18,60 +18,40 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.List;
+import java.util.Set;
+import com.syncleus.dann.neural.OutputNeuron;
 
-public abstract class AbstractUniqueEdge<N> extends AbstractEdge<N>
+public interface AssignableGraph<N, E extends Edge<N>> extends Graph<N,E>, MutableEdge<Object>
+//public interface AssignableGraph<P extends Edge<N>, N extends P, E extends P> extends Graph<N,E>, Edge<P>, MutableEdge<P>
+//public interface AssignableGraph<P extends AssignableGraph.Foo, N extends P, E extends Edge<N> & AssignableGraph.Foo> extends Graph<N,E>, Edge<P>, MutableEdge<P>
 {
-	protected AbstractUniqueEdge()
-	{
-		super();
-	}
+/*
+	@Override
+	Set<? extends Graph.EdgeEndpoint<? extends Foo, N, E, E>> getEdgeEndpoints();
 
-	protected AbstractUniqueEdge(final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
+	void test()
 	{
-		super(allowJoiningMultipleGraphs, contextEnabled);
+		Graph.EdgeEndpoint<? extends Object, N, E, E> test = ((Graph<N,E>)this).getEdgeEndpoints().iterator().next();
+		Graph.EdgeEndpoint<? extends Foo, N, E, E> test2 = this.getEdgeEndpoints().iterator().next();
 	}
 
-	protected AbstractUniqueEdge(final List<N> nodes)
+	interface Foo
 	{
-		super(nodes);
 	}
+*/
 
-	protected AbstractUniqueEdge(final N... nodes)
-	{
-		super(nodes);
-	}
 
-	protected AbstractUniqueEdge(final List<N> nodes, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
+	interface NodeEndpoint<ON, MN extends ON, OE extends Edge<? extends ON>> extends Graph.NodeEndpoint<ON,MN,OE>, MutableEdge.Endpoint<Object, MN>
 	{
-		super(nodes, allowJoiningMultipleGraphs, contextEnabled);
-	}
+	};
 
-	protected AbstractUniqueEdge(final boolean allowJoiningMultipleGraphs, final boolean contextEnabled, final N... nodes)
+	interface EdgeEndpoint<ON, OE extends Edge<? extends ON>, ME extends OE> extends Graph.EdgeEndpoint<ON, OE, ME>, MutableEdge.Endpoint<Object, ME>
 	{
-		super(allowJoiningMultipleGraphs, contextEnabled, nodes);
-	}
+	};
 
-	@Override
-	public boolean equals(final Object compareToObj)
+/*
+	interface Endpoint<PN, EN extends PN, NN extends PN, MN extends PN> extends Graph.Endpoint<MN,EN,NN,PN>, MutableEdge.Endpoint<PN, MN>
 	{
-		if( compareToObj == null )
-			return false;
-
-		if( !(compareToObj instanceof Edge) )
-			return false;
-
-		final Edge compareTo = (Edge) compareToObj;
-		return (compareTo.getNodes().equals(this.getNodes()))
-				&& (this.getNodes().equals(compareTo.getNodes()));
-	}
-
-	@Override
-	public int hashCode()
-	{
-		int hash = 0;
-		for(final N node : this.getNodes())
-			hash += node.hashCode();
-		return hash;
-	}
+	};
+*/
 }
diff --git a/src/main/java/com/syncleus/dann/graph/BidirectedEdge.java b/src/main/java/com/syncleus/dann/graph/BidirectedEdge.java
index 4baff40b2bde175b764cc46b720f479fe88d03b3..d9964c24a4175464693ef4561692aab8f35cc6a9 100644
--- a/src/main/java/com/syncleus/dann/graph/BidirectedEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/BidirectedEdge.java
@@ -18,29 +18,9 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.List;
-
-public interface BidirectedEdge<N> extends Edge<N>
+public interface BidirectedEdge<N> extends MixableBidirectedEdge<N, N, N>
 {
-	public enum EndState
+	interface Endpoint<NN, EN extends NN, ON extends NN> extends MixableBidirectedEdge.Endpoint<NN, EN,ON>
 	{
-		OUTWARD, INWARD, NONE
-	}
-	N getLeftNode();
-	N getRightNode();
-	EndState getLeftEndState();
-	EndState getRightEndState();
-	boolean isIntroverted();
-	boolean isExtroverted();
-	boolean isDirected();
-	boolean isHalfEdge();
-	boolean isLooseEdge();
-	boolean isOrdinaryEdge();
-	boolean isLoop();
-	@Override
-	BidirectedEdge<N> disconnect(N node);
-	@Override
-	BidirectedEdge<N> disconnect(List<N> node);
-	@Override
-	BidirectedEdge<N> clone();
+	};
 }
diff --git a/src/main/java/com/syncleus/dann/graph/DirectedEdge.java b/src/main/java/com/syncleus/dann/graph/DirectedEdge.java
index eca10ca4bcc469ae267f480e9a13f562a301498b..8b7ac458fcdb55fc9371d7417048649f6a9dd1a4 100644
--- a/src/main/java/com/syncleus/dann/graph/DirectedEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/DirectedEdge.java
@@ -18,16 +18,9 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.List;
-
-public interface DirectedEdge<N> extends BidirectedEdge<N>
+public interface DirectedEdge<N> extends BidirectedEdge<N>, MixableDirectedEdge<N, N,N>
 {
-	N getSourceNode();
-	N getDestinationNode();
-	@Override
-	DirectedEdge<N> disconnect(N node);
-	@Override
-	DirectedEdge<N> disconnect(List<N> node);
-	@Override
-	DirectedEdge<N> clone();
+	interface Endpoint<NN, EN extends NN, ON extends NN> extends MixableDirectedEdge.Endpoint<NN, EN,ON>, BidirectedEdge.Endpoint<NN, EN,ON>
+	{
+	};
 }
diff --git a/src/main/java/com/syncleus/dann/graph/Edge.java b/src/main/java/com/syncleus/dann/graph/Edge.java
index 5d23f6f5e1ed4631a77f190ba829651e2ec64f9f..4291df272e9d4ec3c11b453f7a7b3a090272469a 100644
--- a/src/main/java/com/syncleus/dann/graph/Edge.java
+++ b/src/main/java/com/syncleus/dann/graph/Edge.java
@@ -22,34 +22,33 @@ import com.syncleus.dann.graph.context.ContextReporter;
 import com.syncleus.dann.graph.xml.EdgeXml;
 import com.syncleus.dann.xml.XmlSerializable;
 import java.io.Serializable;
-import java.util.List;
+import java.util.Set;
 
-public interface Edge<N> extends Serializable, Cloneable, XmlSerializable<EdgeXml, Object>, ContextReporter
+public interface Edge<
+	  	T,
+	  	EP extends Edge.Endpoint<T>
+	  > extends Serializable, Cloneable, XmlSerializable<EdgeXml, Object>, ContextReporter
 {
-	List<N> getNodes();
-	List<N> getTraversableNodes(N node);
-	boolean isTraversable(N node);
+	interface Endpoint<
+		  	T
+		  >
+	{
+		Set<Edge.Endpoint<T>> getNeighbors();
+		Set<Edge.Endpoint<T>> getTraversableNeighborsTo();
+		Set<Edge.Endpoint<T>> getTraversableNeighborsFrom();
+		boolean isTraversable();
+		boolean isTraversable(final Edge.Endpoint<T> destination);
+		boolean isTraversable(final T destination);
+		T getTarget();
+	};
 
-	/**
-	 * Returns an edge with the specified node disconnected.
-	 *
-	 * @param node node to remove from the returned edge.
-	 * @return an edge with the specified node disconnected,
-	 *   <tt>null</tt> if the entire edge should be deleted as a result of
-	 *   removing the specified node.
-	 * @since 2.0
-	 */
-	Edge<N> disconnect(N node);
-
-	/**
-	 * Returns an edge with the specified nodes disconnected.
-	 *
-	 * @param node node to remove from the returned edge.
-	 * @return an edge with the specified nodes disconnected,
-	 *   <tt>null</tt> if the entire edge should be deleted as a result of
-	 *   removing the specified nodes.
-	 */
-	Edge<N> disconnect(List<N> node);
-
-	Edge<N> clone();
+	Set<EP> getEndPoints();
+	Set<EP> getEndPoints(final T node);
+	boolean contains(final T node);
+	Set<T> getTargets();
+	Set<T> getNeighbors(final T source);
+	Set<T> getTraversableFrom(final T source);
+	Set<T> getTraversableTo(final T destination);
+	boolean isTraversable(final T source, final T destination);
+	int getDegree();
 }
diff --git a/src/main/java/com/syncleus/dann/graph/Graph.java b/src/main/java/com/syncleus/dann/graph/Graph.java
index c55d19604cf5d2e32b99599d391190407fa03d23..b622914825189932a5a739665932cc80f61baafe 100644
--- a/src/main/java/com/syncleus/dann/graph/Graph.java
+++ b/src/main/java/com/syncleus/dann/graph/Graph.java
@@ -18,15 +18,12 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
+import javax.management.OperationsException;
 import com.syncleus.dann.graph.context.ContextReporter;
-import com.syncleus.dann.graph.xml.GraphXml;
-import com.syncleus.dann.xml.XmlSerializable;
+import com.syncleus.dann.neural.OutputNeuron;
 import java.io.Serializable;
-import java.util.List;
 import java.util.Set;
 
-// TODO consider making all nodes extend from a connectable interface so you can embed other graphs as nodes if they too are connectable.
-
 /**
  * Represents a graph as a collection of nodes connected by edges. A graph does
  * not need to contain any nodes or edges however if there is at least one edge
@@ -40,8 +37,96 @@ import java.util.Set;
  * @param <N> The node type
  * @param <E> The type of edge for the given node type
  */
-public interface Graph<N, E extends Edge<N>> extends Serializable, Cloneable, XmlSerializable<GraphXml, Object>, ContextReporter
+public interface Graph<
+	  	PA,
+	  	N extends PA,
+	  	E extends Edge<N,? extends Edge.Endpoint<N>>,
+	  	NEP extends Graph.NodeEndpoint<PA, N, E>,
+	  	EEP extends Graph.EdgeEndpoint<PA, N, E>
+	  > extends Edge<PA,Graph.Endpoint<PA,N,E,PA>>, Serializable, Cloneable, ContextReporter
 {
+/*
+	interface Endpoint<
+	  	PA
+	  > extends Edge.Endpoint<PA>
+	{
+		Set<Graph.Endpoint<PA>> getAdjacent();
+		Set<Graph.Endpoint<PA>> getTraversableAdjacentTo();
+		Set<Graph.Endpoint<PA>> getTraversableAdjacentFrom();
+	};
+
+	interface NodeEndpoint<
+	  	PA,
+	  	ON extends PA,
+	  	OE extends Edge<ON,? extends Edge.Endpoint<? extends ON>>
+	  > extends Graph.Endpoint<ON>
+	{
+		Set<Graph.NodeEndpoint<PA, ON, OE>> getAdjacentNodes();
+		Set<Graph.NodeEndpoint<PA, ON, OE>> getTraversableAdjacentNodesTo();
+		Set<Graph.NodeEndpoint<PA, ON, OE>> getTraversableAdjacentNodesFrom();
+
+		Set<Graph.EdgeEndpoint<PA, ON, OE>> getAdjacentEdges();
+		Set<Graph.EdgeEndpoint<PA, ON, OE>> getTraversableAdjacentEdgesTo();
+		Set<Graph.EdgeEndpoint<PA, ON, OE>> getTraversableAdjacentEdgesFrom();
+	};
+
+	interface EdgeEndpoint<
+	  	PA,
+	  	ON extends PA,
+	  	OE extends Edge<ON,? extends Edge.Endpoint<? extends ON>>
+			> extends Graph.Endpoint<OE>
+	{
+		Set<Graph.EdgeEndpoint<PA, ON, OE>> getAdjacentEdges();
+		Set<Graph.EdgeEndpoint<PA, ON, OE>> getTraversableAdjacentEdgesTo();
+		Set<Graph.EdgeEndpoint<PA, ON, OE>> getTraversableAdjacentEdgesFrom();
+
+		Set<Graph.NodeEndpoint<PA, ON, OE>> getAdjacentNodes();
+		Set<Graph.NodeEndpoint<PA, ON, OE>> getTraversableAdjacentNodesTo();
+		Set<Graph.NodeEndpoint<PA, ON, OE>> getTraversableAdjacentNodesFrom();
+	};
+*/
+	interface Endpoint<
+	  	PA,
+	  	ON extends PA,
+	  	OE extends Edge<ON,? extends Edge.Endpoint<? extends ON>>,
+	  	T
+	  > extends Edge.Endpoint<T>
+	{
+		Set<Graph.Endpoint<PA,ON,OE,T>> getAdjacent();
+		Set<Graph.Endpoint<PA,ON,OE,T>> getTraversableAdjacentTo();
+		Set<Graph.Endpoint<PA,ON,OE,T>> getTraversableAdjacentFrom();
+
+		Set<Graph.NodeEndpoint<PA, ON, OE>> getAdjacentNodes();
+		Set<Graph.NodeEndpoint<PA, ON, OE>> getTraversableAdjacentNodesTo();
+		Set<Graph.NodeEndpoint<PA, ON, OE>> getTraversableAdjacentNodesFrom();
+
+		Set<Graph.EdgeEndpoint<PA, ON, OE>> getAdjacentEdges();
+		Set<Graph.EdgeEndpoint<PA, ON, OE>> getTraversableAdjacentEdgesTo();
+		Set<Graph.EdgeEndpoint<PA, ON, OE>> getTraversableAdjacentEdgesFrom();
+	};
+
+	interface NodeEndpoint<
+	  	PA,
+	  	ON extends PA,
+	  	OE extends Edge<ON,? extends Edge.Endpoint<? extends ON>>
+	  > extends Graph.Endpoint<PA,ON,OE,ON>
+	{
+	};
+
+	interface EdgeEndpoint<
+	  	PA,
+	  	ON extends PA,
+	  	OE extends Edge<ON,? extends Edge.Endpoint<? extends ON>>
+			> extends Graph.Endpoint<PA,ON,OE,OE>
+	{
+	};
+
+	Set<EEP> getEdgeEndpoints();
+	Set<EEP> getEdgeEndpoints(E edge);
+
+	Set<NEP> getNodeEndpoints();
+	Set<NEP> getNodeEndpoints(N node);
+
 	/**
 	 * Get a set of all nodes in the graph.
 	 *
@@ -70,19 +155,37 @@ public interface Graph<N, E extends Edge<N>> extends Serializable, Cloneable, Xm
 	 *         node has no edges.
 	 * @since 2.0
 	 */
-	List<N> getAdjacentNodes(N node);
+	Set<N> getAdjacentNodes(N node);
 	/**
 	 * Get a set of all edges which is connected to node (adjacent). You may not be
 	 * able to traverse from the specified node to all of these edges returned. If
-	 * you only want edges you can traverse then see getTraversableEdges.
+	 * you only want edges you can traverse then see getTraversableAdjacentEdges.
 	 *
 	 * @param node the end point for all edges to retrieve.
 	 * @return An unmodifiable set of all edges that has node as an end point.
 	 * @throws IllegalArgumentException if specified node is not in the graph.
-	 * @see Graph#getTraversableEdges
 	 * @since 2.0
 	 */
 	Set<E> getAdjacentEdges(N node);
+
+	Set<E> getTraversableEdgesFrom(final N source);
+	Set<E> getTraversableEdgesFrom(final E source);
+	Set<E> getTraversableEdgesTo(final N destination);
+	Set<E> getTraversableEdgesTo(final E destination);
+
+	Set<N> getTraversableNodesFrom(final N source);
+	Set<N> getTraversableNodesFrom(final E source);
+	Set<N> getTraversableNodesTo(final N destination);
+	Set<N> getTraversableNodesTo(final E destination);
+
+	Set<E> getTraversableAdjacentEdgesFrom(final N source);
+	Set<E> getTraversableAdjacentEdgesFrom(final E source);
+	Set<E> getTraversableAdjacentEdgesTo(final N destination);
+	Set<E> getTraversableAdjacentEdgesTo(final E destination);
+
+	Set<N> getTraversableAdjacentNodesFrom(final N source);
+	Set<N> getTraversableAdjacentNodesFrom(final E source);
+
 	/**
 	 * Get a list of all reachable nodes adjacent to node. All edges connected to
 	 * node and is traversable from node will have its destination node(s) added to
@@ -91,74 +194,21 @@ public interface Graph<N, E extends Edge<N>> extends Serializable, Cloneable, Xm
 	 * the end point will appear multiple times in the list, once for each hop to
 	 * the end point.
 	 *
-	 * @param node The whose traversable neighbors are to be returned.
+	 * @param destination The whose traversable neighbors are to be returned.
 	 * @return A list of all nodes adjacent to the specified node and traversable
 	 *         from the spevified node, empty set if the node has no edges.
 	 * @since 2.0
 	 */
-	List<N> getTraversableNodes(N node);
+	Set<N> getTraversableAdjacentNodesTo(final N destination);
+
 	/**
 	 * Get a set of all edges which you can traverse from node. Of course node will
 	 * always be an end point for each edge returned. Throws an
 	 * IllegalArgumentException if node is not in the graph.
 	 *
-	 * @param node edges returned will be traversable from this node.
+	 * @param destination edges returned will be traversable from this node.
 	 * @return An unmodifiable set of all edges that can be traversed from node.
 	 * @since 2.0
 	 */
-	Set<E> getTraversableEdges(N node);
-	/**
-	 * Adds the specified edge to a clone of this class.
-	 *
-	 * @param newEdge the edge to add to the cloned graph.
-	 * @return a clone of this graph with the specified edge added to it. null if
-	 *         the edge already exists.
-	 * @since 2.0
-	 */
-	Graph<N, E> cloneAdd(E newEdge);
-	/**
-	 * Adds the specified node to a clone of this class.
-	 *
-	 * @param newNode the node to add to the cloned graph.
-	 * @return a clone of this graph with the specified node added to it.
-	 * @since 2.0
-	 */
-	Graph<N, E> cloneAdd(N newNode);
-	/**
-	 * Adds the specified nodes and edges to a clone of this class.
-	 *
-	 * @param newNodes the nodes to add to the cloned graph.
-	 * @param newEdges the edges to add to the cloned graph.
-	 * @return a clone of this graph with the specified nodes and edges added to
-	 *         it.
-	 * @since 2.0
-	 */
-	Graph<N, E> cloneAdd(Set<N> newNodes, Set<E> newEdges);
-	/**
-	 * Removed the specified edge from a clone of this class.
-	 *
-	 * @param edgeToRemove the edge to remove from the cloned graph.
-	 * @return a clone of this graph with the specified edge removed to it.
-	 * @since 2.0
-	 */
-	Graph<N, E> cloneRemove(E edgeToRemove);
-	/**
-	 * Removed the specified edge to a clone of this class.
-	 *
-	 * @param nodeToRemove the edge to remove from the cloned graph.
-	 * @return a clone of this graph with the specified edge removed from it.
-	 * @since 2.0
-	 */
-	Graph<N, E> cloneRemove(N nodeToRemove);
-	/**
-	 * Removed the specified nodes and edges from a clone of this class.
-	 *
-	 * @param deleteNodes the nodes to remove from the cloned graph.
-	 * @param deleteEdges the edges to remove from the cloned graph.
-	 * @return a clone of this graph with the specified nodes and edges removed
-	 *         from it.
-	 * @since 2.0
-	 */
-	Graph<N, E> cloneRemove(Set<N> deleteNodes, Set<E> deleteEdges);
-	Graph<N, E> clone();
+	Set<N> getTraversableAdjacentNodesTo(final E destination);
 }
diff --git a/src/main/java/com/syncleus/dann/graph/HyperEdge.java b/src/main/java/com/syncleus/dann/graph/HyperEdge.java
index 2877305f04dcc1a890119be75898dc3531e74d90..419d72b691b9e17378592f34b5cbac1266044814 100644
--- a/src/main/java/com/syncleus/dann/graph/HyperEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/HyperEdge.java
@@ -18,18 +18,11 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.List;
-
 public interface HyperEdge<N> extends Edge<N>
 {
-	int getDegree();
-	boolean isSymmetric(HyperEdge symmetricEdge);
-	HyperEdge<N> connect(N node);
-	HyperEdge<N> connect(List<N> node);
-	@Override
-	HyperEdge<N> disconnect(N node);
-	@Override
-	HyperEdge<N> disconnect(List<N> node);
-	@Override
-	HyperEdge<N> clone();
+	interface Endpoint<NN, EN extends NN> extends Edge.Endpoint<NN, EN>
+	{
+	};
+
+	boolean isSymmetric(HyperEdge<N> symmetricEdge);
 }
diff --git a/src/main/java/com/syncleus/dann/graph/ImmutableAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graph/ImmutableAdjacencyGraph.java
index 29369bb5276486c9348625e044868b95b3131984..e2ec14c2ae343ed8db46922849abb7b1498a1e03 100644
--- a/src/main/java/com/syncleus/dann/graph/ImmutableAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/ImmutableAdjacencyGraph.java
@@ -74,43 +74,7 @@ public class ImmutableAdjacencyGraph<N, E extends Edge<N>> extends AbstractAdjac
 	}
 
 	@Override
-	public ImmutableAdjacencyGraph<N, E> cloneAdd(final E newEdge)
-	{
-		return (ImmutableAdjacencyGraph<N, E>) super.cloneAdd(newEdge);
-	}
-
-	@Override
-	public ImmutableAdjacencyGraph<N, E> cloneAdd(final N newNode)
-	{
-		return (ImmutableAdjacencyGraph<N, E>) super.cloneAdd(newNode);
-	}
-
-	@Override
-	public ImmutableAdjacencyGraph<N, E> cloneAdd(final Set<N> newNodes, final Set<E> newEdges)
-	{
-		return (ImmutableAdjacencyGraph<N, E>) super.cloneAdd(newNodes, newEdges);
-	}
-
-	@Override
-	public ImmutableAdjacencyGraph<N, E> cloneRemove(final E edgeToRemove)
-	{
-		return (ImmutableAdjacencyGraph<N, E>) super.cloneRemove(edgeToRemove);
-	}
-
-	@Override
-	public ImmutableAdjacencyGraph<N, E> cloneRemove(final N nodeToRemove)
-	{
-		return (ImmutableAdjacencyGraph<N, E>) super.cloneRemove(nodeToRemove);
-	}
-
-	@Override
-	public ImmutableAdjacencyGraph<N, E> cloneRemove(final Set<N> deleteNodes, final Set<E> deleteEdges)
-	{
-		return (ImmutableAdjacencyGraph<N, E>) super.cloneRemove(deleteNodes, deleteEdges);
-	}
-
-	@Override
-	public ImmutableAdjacencyGraph<N, E> clone()
+	protected ImmutableAdjacencyGraph<N, E> clone()
 	{
 		return (ImmutableAdjacencyGraph<N, E>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/ImmutableDirectedAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graph/ImmutableDirectedAdjacencyGraph.java
index 1d1e6c0bf19f005a4f9b957f24d29e1074a5d07f..fc47aa8b8680b2031092e6d98c7b4c887ed97272 100644
--- a/src/main/java/com/syncleus/dann/graph/ImmutableDirectedAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/ImmutableDirectedAdjacencyGraph.java
@@ -71,43 +71,7 @@ public class ImmutableDirectedAdjacencyGraph<N, E extends DirectedEdge<N>> exten
 	}
 
 	@Override
-	public ImmutableDirectedAdjacencyGraph<N, E> cloneAdd(final E newEdge)
-	{
-		return (ImmutableDirectedAdjacencyGraph<N, E>) super.cloneAdd(newEdge);
-	}
-
-	@Override
-	public ImmutableDirectedAdjacencyGraph<N, E> cloneAdd(final N newNode)
-	{
-		return (ImmutableDirectedAdjacencyGraph<N, E>) super.cloneAdd(newNode);
-	}
-
-	@Override
-	public ImmutableDirectedAdjacencyGraph<N, E> cloneAdd(final Set<N> newNodes, final Set<E> newEdges)
-	{
-		return (ImmutableDirectedAdjacencyGraph<N, E>) super.cloneAdd(newNodes, newEdges);
-	}
-
-	@Override
-	public ImmutableDirectedAdjacencyGraph<N, E> cloneRemove(final E edgeToRemove)
-	{
-		return (ImmutableDirectedAdjacencyGraph<N, E>) super.cloneRemove(edgeToRemove);
-	}
-
-	@Override
-	public ImmutableDirectedAdjacencyGraph<N, E> cloneRemove(final N nodeToRemove)
-	{
-		return (ImmutableDirectedAdjacencyGraph<N, E>) super.cloneRemove(nodeToRemove);
-	}
-
-	@Override
-	public ImmutableDirectedAdjacencyGraph<N, E> cloneRemove(final Set<N> deleteNodes, final Set<E> deleteEdges)
-	{
-		return (ImmutableDirectedAdjacencyGraph<N, E>) super.cloneRemove(deleteNodes, deleteEdges);
-	}
-
-	@Override
-	public ImmutableDirectedAdjacencyGraph<N, E> clone()
+	protected ImmutableDirectedAdjacencyGraph<N, E> clone()
 	{
 		return (ImmutableDirectedAdjacencyGraph<N, E>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/ImmutableHyperAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graph/ImmutableHyperAdjacencyGraph.java
index 2f7c2dc191348f1ee5eac2aa4783ad862acabe9c..6af9657d686b69d00d077ef804f03b3cc507f347 100644
--- a/src/main/java/com/syncleus/dann/graph/ImmutableHyperAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/ImmutableHyperAdjacencyGraph.java
@@ -71,43 +71,7 @@ public class ImmutableHyperAdjacencyGraph<N, E extends HyperEdge<N>> extends Abs
 	}
 
 	@Override
-	public ImmutableHyperAdjacencyGraph<N, E> cloneAdd(final E newEdge)
-	{
-		return (ImmutableHyperAdjacencyGraph<N, E>) super.cloneAdd(newEdge);
-	}
-
-	@Override
-	public ImmutableHyperAdjacencyGraph<N, E> cloneAdd(final N newNode)
-	{
-		return (ImmutableHyperAdjacencyGraph<N, E>) super.cloneAdd(newNode);
-	}
-
-	@Override
-	public ImmutableHyperAdjacencyGraph<N, E> cloneAdd(final Set<N> newNodes, final Set<E> newEdges)
-	{
-		return (ImmutableHyperAdjacencyGraph<N, E>) super.cloneAdd(newNodes, newEdges);
-	}
-
-	@Override
-	public ImmutableHyperAdjacencyGraph<N, E> cloneRemove(final E edgeToRemove)
-	{
-		return (ImmutableHyperAdjacencyGraph<N, E>) super.cloneRemove(edgeToRemove);
-	}
-
-	@Override
-	public ImmutableHyperAdjacencyGraph<N, E> cloneRemove(final N nodeToRemove)
-	{
-		return (ImmutableHyperAdjacencyGraph<N, E>) super.cloneRemove(nodeToRemove);
-	}
-
-	@Override
-	public ImmutableHyperAdjacencyGraph<N, E> cloneRemove(final Set<N> deleteNodes, final Set<E> deleteEdges)
-	{
-		return (ImmutableHyperAdjacencyGraph<N, E>) super.cloneRemove(deleteNodes, deleteEdges);
-	}
-
-	@Override
-	public ImmutableHyperAdjacencyGraph<N, E> clone()
+	protected ImmutableHyperAdjacencyGraph<N, E> clone()
 	{
 		return (ImmutableHyperAdjacencyGraph<N, E>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/ImmutableHyperEdge.java b/src/main/java/com/syncleus/dann/graph/ImmutableHyperEdge.java
deleted file mode 100644
index 06cdea927a8360936756531d8dbe8cd5b1e18409..0000000000000000000000000000000000000000
--- a/src/main/java/com/syncleus/dann/graph/ImmutableHyperEdge.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/******************************************************************************
- *                                                                             *
- *  Copyright: (c) Syncleus, Inc.                                              *
- *                                                                             *
- *  You may redistribute and modify this source code under the terms and       *
- *  conditions of the Open Source Community License - Type C version 1.0       *
- *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
- *  There should be a copy of the license included with this file. If a copy   *
- *  of the license is not included you are granted no right to distribute or   *
- *  otherwise use this file except through a legal and valid license. You      *
- *  should also contact Syncleus, Inc. at the information below if you cannot  *
- *  find a license:                                                            *
- *                                                                             *
- *  Syncleus, Inc.                                                             *
- *  2604 South 12th Street                                                     *
- *  Philadelphia, PA 19148                                                     *
- *                                                                             *
- ******************************************************************************/
-package com.syncleus.dann.graph;
-
-import java.util.List;
-
-public final class ImmutableHyperEdge<N> extends AbstractHyperEdge<N>
-{
-	private static final long serialVersionUID = -3657973823101515199L;
-
-	public ImmutableHyperEdge(final List<N> nodes)
-	{
-		super(nodes);
-	}
-
-	public ImmutableHyperEdge(final N... nodes)
-	{
-		super(nodes);
-	}
-
-	public ImmutableHyperEdge(final List<N> nodes, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
-	{
-		super(nodes, allowJoiningMultipleGraphs, contextEnabled);
-	}
-
-	public ImmutableHyperEdge(final boolean allowJoiningMultipleGraphs, final boolean contextEnabled, final N... nodes)
-	{
-		super(allowJoiningMultipleGraphs, contextEnabled, nodes);
-	}
-
-	@Override
-	public ImmutableHyperEdge<N> connect(final N node)
-	{
-		return (ImmutableHyperEdge<N>) super.connect(node);
-	}
-
-	@Override
-	public ImmutableHyperEdge<N> connect(final List<N> nodes)
-	{
-		return (ImmutableHyperEdge<N>) super.connect(nodes);
-	}
-
-	@Override
-	public ImmutableHyperEdge<N> disconnect(final N node)
-	{
-		return (ImmutableHyperEdge<N>) super.disconnect(node);
-	}
-
-	@Override
-	public ImmutableHyperEdge<N> disconnect(final List<N> nodes)
-	{
-		return (ImmutableHyperEdge<N>) super.disconnect(nodes);
-	}
-
-	@Override
-	public ImmutableHyperEdge<N> clone()
-	{
-		return (ImmutableHyperEdge<N>) super.clone();
-	}
-}
diff --git a/src/main/java/com/syncleus/dann/graph/ImmutableRootedTreeAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graph/ImmutableRootedTreeAdjacencyGraph.java
index a2b7d1ae435fe00e90af35728c7ee9b145a2f0d0..f7511a65bd6768557e152f26aac006e67a1f78dc 100644
--- a/src/main/java/com/syncleus/dann/graph/ImmutableRootedTreeAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/ImmutableRootedTreeAdjacencyGraph.java
@@ -37,7 +37,7 @@ public class ImmutableRootedTreeAdjacencyGraph<N, E extends DirectedEdge<N>> ext
 
 	public ImmutableRootedTreeAdjacencyGraph(final Graph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 
 	public ImmutableRootedTreeAdjacencyGraph(final Set<N> nodes, final Set<E> edges)
@@ -70,43 +70,7 @@ public class ImmutableRootedTreeAdjacencyGraph<N, E extends DirectedEdge<N>> ext
 	}
 
 	@Override
-	public ImmutableRootedTreeAdjacencyGraph<N, E> cloneAdd(final E newEdge)
-	{
-		return (ImmutableRootedTreeAdjacencyGraph<N, E>) super.cloneAdd(newEdge);
-	}
-
-	@Override
-	public ImmutableRootedTreeAdjacencyGraph<N, E> cloneAdd(final N newNode)
-	{
-		return (ImmutableRootedTreeAdjacencyGraph<N, E>) super.cloneAdd(newNode);
-	}
-
-	@Override
-	public ImmutableRootedTreeAdjacencyGraph<N, E> cloneAdd(final Set<N> newNodes, final Set<E> newEdges)
-	{
-		return (ImmutableRootedTreeAdjacencyGraph<N, E>) super.cloneAdd(newNodes, newEdges);
-	}
-
-	@Override
-	public ImmutableRootedTreeAdjacencyGraph<N, E> cloneRemove(final E edgeToRemove)
-	{
-		return (ImmutableRootedTreeAdjacencyGraph<N, E>) super.cloneRemove(edgeToRemove);
-	}
-
-	@Override
-	public ImmutableRootedTreeAdjacencyGraph<N, E> cloneRemove(final N nodeToRemove)
-	{
-		return (ImmutableRootedTreeAdjacencyGraph<N, E>) super.cloneRemove(nodeToRemove);
-	}
-
-	@Override
-	public ImmutableRootedTreeAdjacencyGraph<N, E> cloneRemove(final Set<N> deleteNodes, final Set<E> deleteEdges)
-	{
-		return (ImmutableRootedTreeAdjacencyGraph<N, E>) super.cloneRemove(deleteNodes, deleteEdges);
-	}
-
-	@Override
-	public ImmutableRootedTreeAdjacencyGraph<N, E> clone()
+	protected ImmutableRootedTreeAdjacencyGraph<N, E> clone()
 	{
 		return (ImmutableRootedTreeAdjacencyGraph<N, E>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/ImmutableTreeAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graph/ImmutableTreeAdjacencyGraph.java
index efa197b5f9216d0eb86affd4dbcaaec32b336d64..21e12fa03c21902f7e688163074bb872713d2a86 100644
--- a/src/main/java/com/syncleus/dann/graph/ImmutableTreeAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/ImmutableTreeAdjacencyGraph.java
@@ -38,7 +38,7 @@ public class ImmutableTreeAdjacencyGraph<N, E extends BidirectedEdge<N>> extends
 
 	public ImmutableTreeAdjacencyGraph(final Graph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 
 	public ImmutableTreeAdjacencyGraph(final Set<N> nodes, final Set<E> edges)
@@ -71,43 +71,7 @@ public class ImmutableTreeAdjacencyGraph<N, E extends BidirectedEdge<N>> extends
 	}
 
 	@Override
-	public ImmutableTreeAdjacencyGraph<N, E> cloneAdd(final E newEdge)
-	{
-		return (ImmutableTreeAdjacencyGraph<N, E>) super.cloneAdd(newEdge);
-	}
-
-	@Override
-	public ImmutableTreeAdjacencyGraph<N, E> cloneAdd(final N newNode)
-	{
-		return (ImmutableTreeAdjacencyGraph<N, E>) super.cloneAdd(newNode);
-	}
-
-	@Override
-	public ImmutableTreeAdjacencyGraph<N, E> cloneAdd(final Set<N> newNodes, final Set<E> newEdges)
-	{
-		return (ImmutableTreeAdjacencyGraph<N, E>) super.cloneAdd(newNodes, newEdges);
-	}
-
-	@Override
-	public ImmutableTreeAdjacencyGraph<N, E> cloneRemove(final E edgeToRemove)
-	{
-		return (ImmutableTreeAdjacencyGraph<N, E>) super.cloneRemove(edgeToRemove);
-	}
-
-	@Override
-	public ImmutableTreeAdjacencyGraph<N, E> cloneRemove(final N nodeToRemove)
-	{
-		return (ImmutableTreeAdjacencyGraph<N, E>) super.cloneRemove(nodeToRemove);
-	}
-
-	@Override
-	public ImmutableTreeAdjacencyGraph<N, E> cloneRemove(final Set<N> deleteNodes, final Set<E> deleteEdges)
-	{
-		return (ImmutableTreeAdjacencyGraph<N, E>) super.cloneRemove(deleteNodes, deleteEdges);
-	}
-
-	@Override
-	public ImmutableTreeAdjacencyGraph<N, E> clone()
+	protected ImmutableTreeAdjacencyGraph<N, E> clone()
 	{
 		return (ImmutableTreeAdjacencyGraph<N, E>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/ImmutableWeightedDirectedEdge.java b/src/main/java/com/syncleus/dann/graph/ImmutableWeightedDirectedEdge.java
index 0fe340f3ad00012b33116f5dc985723190419b74..3fda9efdabe3634671c5d989e72b6e08a959bac4 100644
--- a/src/main/java/com/syncleus/dann/graph/ImmutableWeightedDirectedEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/ImmutableWeightedDirectedEdge.java
@@ -18,9 +18,7 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.List;
-
-public final class ImmutableWeightedDirectedEdge<N> extends AbstractDirectedEdge<N> implements WeightedDirectedEdge<N>
+public final class ImmutableWeightedDirectedEdge<N> extends AbstractDirectedEdge<N, N,N> implements WeightedDirectedEdge<N>
 {
 	private static final long serialVersionUID = -6843921044147012645L;
 	private final double weight;
@@ -44,19 +42,7 @@ public final class ImmutableWeightedDirectedEdge<N> extends AbstractDirectedEdge
 	}
 
 	@Override
-	public ImmutableWeightedDirectedEdge<N> disconnect(final N node)
-	{
-		return (ImmutableWeightedDirectedEdge<N>) super.disconnect(node);
-	}
-
-	@Override
-	public ImmutableWeightedDirectedEdge<N> disconnect(final List<N> nodes)
-	{
-		return (ImmutableWeightedDirectedEdge<N>) super.disconnect(nodes);
-	}
-
-	@Override
-	public ImmutableWeightedDirectedEdge<N> clone()
+	protected ImmutableWeightedDirectedEdge<N> clone()
 	{
 		return (ImmutableWeightedDirectedEdge<N>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/ImmutableWeightedHyperEdge.java b/src/main/java/com/syncleus/dann/graph/ImmutableWeightedHyperEdge.java
index 4ac6a256ffacaa5e366f760bac7304665eb1b837..9fab9454ebb2736d2d769ed0bb7408383f22ecb1 100644
--- a/src/main/java/com/syncleus/dann/graph/ImmutableWeightedHyperEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/ImmutableWeightedHyperEdge.java
@@ -44,19 +44,7 @@ public final class ImmutableWeightedHyperEdge<N> extends AbstractHyperEdge<N> im
 	}
 
 	@Override
-	public ImmutableWeightedHyperEdge<N> disconnect(final N node)
-	{
-		return (ImmutableWeightedHyperEdge<N>) super.remove(node);
-	}
-
-	@Override
-	public ImmutableWeightedHyperEdge<N> disconnect(final List<N> nodes)
-	{
-		return (ImmutableWeightedHyperEdge<N>) super.remove(nodes);
-	}
-
-	@Override
-	public ImmutableWeightedHyperEdge<N> clone()
+	protected ImmutableWeightedHyperEdge<N> clone()
 	{
 		return (ImmutableWeightedHyperEdge<N>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/ImmutableDirectedEdge.java b/src/main/java/com/syncleus/dann/graph/ImmutableWeightedMixableDirectedEdge.java
similarity index 67%
rename from src/main/java/com/syncleus/dann/graph/ImmutableDirectedEdge.java
rename to src/main/java/com/syncleus/dann/graph/ImmutableWeightedMixableDirectedEdge.java
index dacac5cb9056a1e6b672a0e464c89ab32962119a..07458e49c07f00b1a580e721fd57e7824d6385fa 100644
--- a/src/main/java/com/syncleus/dann/graph/ImmutableDirectedEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/ImmutableWeightedMixableDirectedEdge.java
@@ -18,37 +18,32 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.List;
-
-public final class ImmutableDirectedEdge<N> extends AbstractDirectedEdge<N>
+public final class ImmutableWeightedMixableDirectedEdge<N, SN extends N, DN extends N> extends AbstractDirectedEdge<N, SN,DN> implements WeightedMixableDirectedEdge<SN,DN,N>
 {
-	private static final long serialVersionUID = 94357801283489L;
+	private static final long serialVersionUID = -6842352444147012645L;
+	private final double weight;
 
-	public ImmutableDirectedEdge(final N source, final N destination)
+	public ImmutableWeightedMixableDirectedEdge(final SN source, final DN destination, final double ourWeight)
 	{
 		super(source, destination);
+		this.weight = ourWeight;
 	}
 
-	public ImmutableDirectedEdge(final N source, final N destination, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
+	public ImmutableWeightedMixableDirectedEdge(final SN source, final DN destination, final double ourWeight, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
 	{
 		super(source, destination, allowJoiningMultipleGraphs, contextEnabled);
+		this.weight = ourWeight;
 	}
 
 	@Override
-	public ImmutableDirectedEdge<N> disconnect(final N node)
-	{
-		return (ImmutableDirectedEdge<N>) super.disconnect(node);
-	}
-
-	@Override
-	public ImmutableDirectedEdge<N> disconnect(final List<N> nodes)
+	public double getWeight()
 	{
-		return (ImmutableDirectedEdge<N>) super.disconnect(nodes);
+		return this.weight;
 	}
 
 	@Override
-	public ImmutableDirectedEdge<N> clone()
+	protected ImmutableWeightedMixableDirectedEdge<N, SN,DN> clone()
 	{
-		return (ImmutableDirectedEdge<N>) super.clone();
+		return (ImmutableWeightedMixableDirectedEdge<N, SN,DN>) super.clone();
 	}
 }
diff --git a/src/main/java/com/syncleus/dann/graph/context/AbstractSignalingContextEdge.java b/src/main/java/com/syncleus/dann/graph/ImmutableWeightedMixableUndirectedEdge.java
similarity index 61%
rename from src/main/java/com/syncleus/dann/graph/context/AbstractSignalingContextEdge.java
rename to src/main/java/com/syncleus/dann/graph/ImmutableWeightedMixableUndirectedEdge.java
index 9360010de6b8033df67509ecba69c0e2927ed598..09e256ed1cd7e4da76723e954a12933c2185de6e 100644
--- a/src/main/java/com/syncleus/dann/graph/context/AbstractSignalingContextEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/ImmutableWeightedMixableUndirectedEdge.java
@@ -16,38 +16,34 @@
  *  Philadelphia, PA 19148                                                     *
  *                                                                             *
  ******************************************************************************/
-package com.syncleus.dann.graph.context;
+package com.syncleus.dann.graph;
 
-import com.syncleus.dann.graph.Graph;
-
-public abstract class AbstractSignalingContextEdge<N, S> extends AbstractContextGraphElement<Graph<N, ?>> implements SignalingContextEdge<N, S>
+public final class ImmutableWeightedMixableUndirectedEdge<N, LN extends N, RN extends N> extends AbstractUndirectedEdge<N, LN,RN> implements WeightedMixableBidirectedEdge<LN,RN,N>
 {
-	protected AbstractSignalingContextEdge(final boolean allowJoiningMultipleGraphs)
+	private static final long serialVersionUID = -298347598212765L;
+	private final double weight;
+
+	public ImmutableWeightedMixableUndirectedEdge(final LN left, final RN right, final double ourWeight)
 	{
-		super(allowJoiningMultipleGraphs);
+		super(left, right);
+		this.weight = ourWeight;
 	}
 
-	protected AbstractSignalingContextEdge()
+	public ImmutableWeightedMixableUndirectedEdge(final LN left, final RN right, final double ourWeight, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
 	{
-		super(true);
+		super(left, right, allowJoiningMultipleGraphs, contextEnabled);
+		this.weight = ourWeight;
 	}
 
-	/**
-	 * This method will retransmit the state to all traversable nodes even if context is disabled.
-	 */
 	@Override
-	public void nodeStateChanged(final N node, final S newState)
+	public double getWeight()
 	{
-		if( !this.getNodes().contains(node) )
-			throw new IllegalArgumentException("node is not an endpoint of this edge");
-
-		for(N traversableNode : this.getTraversableNodes(node))
-		{
-			if( traversableNode instanceof SignalContextNode)
-				((SignalContextNode)traversableNode).neighborNodeStateChanged(this, node, newState);
-		}
+		return this.weight;
 	}
 
 	@Override
-	public abstract AbstractSignalingContextEdge<N, S> clone();
+	protected ImmutableWeightedMixableUndirectedEdge<N, LN,RN> clone()
+	{
+		return (ImmutableWeightedMixableUndirectedEdge<N, LN,RN>) super.clone();
+	}
 }
diff --git a/src/main/java/com/syncleus/dann/graph/ImmutableWeightedUndirectedEdge.java b/src/main/java/com/syncleus/dann/graph/ImmutableWeightedUndirectedEdge.java
index 2afe38cbf4dbfd41feefa7226ba6197c952016c4..3481921ac51df6ac529f03fbb06bd488a951cc8d 100644
--- a/src/main/java/com/syncleus/dann/graph/ImmutableWeightedUndirectedEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/ImmutableWeightedUndirectedEdge.java
@@ -18,9 +18,7 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.List;
-
-public final class ImmutableWeightedUndirectedEdge<N> extends AbstractUndirectedEdge<N> implements WeightedBidirectedEdge<N>
+public final class ImmutableWeightedUndirectedEdge<N> extends AbstractUndirectedEdge<N, N,N> implements WeightedBidirectedEdge<N>
 {
 	private static final long serialVersionUID = 4622255810663472765L;
 	private final double weight;
@@ -44,19 +42,7 @@ public final class ImmutableWeightedUndirectedEdge<N> extends AbstractUndirected
 	}
 
 	@Override
-	public ImmutableWeightedUndirectedEdge<N> disconnect(final N node)
-	{
-		return (ImmutableWeightedUndirectedEdge<N>) this.remove(node);
-	}
-
-	@Override
-	public ImmutableWeightedUndirectedEdge<N> disconnect(final List<N> nodes)
-	{
-		return (ImmutableWeightedUndirectedEdge<N>) this.remove(nodes);
-	}
-
-	@Override
-	public ImmutableWeightedUndirectedEdge<N> clone()
+	protected ImmutableWeightedUndirectedEdge<N> clone()
 	{
 		return (ImmutableWeightedUndirectedEdge<N>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/InvalidEdgeDirectionException.java b/src/main/java/com/syncleus/dann/graph/InvalidEdgeDirectionException.java
new file mode 100644
index 0000000000000000000000000000000000000000..acbfb995d3ccf20d148066b2fb6251bd8971923a
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/InvalidEdgeDirectionException.java
@@ -0,0 +1,46 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph;
+
+import org.omg.CORBA.DynAnyPackage.Invalid;
+
+public class InvalidEdgeDirectionException extends InvalidEdgeException
+{
+	private static final long serialVersionUID = 10247021935792856L;
+
+	public InvalidEdgeDirectionException()
+	{
+		super();
+	}
+
+	public InvalidEdgeDirectionException(final String msg)
+	{
+		super(msg);
+	}
+
+	public InvalidEdgeDirectionException(final String msg, final Throwable cause)
+	{
+		super(msg, cause);
+	}
+
+	public InvalidEdgeDirectionException(final Throwable cause)
+	{
+		super(cause);
+	}
+}
diff --git a/src/main/java/com/syncleus/dann/graph/InvalidEdgeException.java b/src/main/java/com/syncleus/dann/graph/InvalidEdgeException.java
new file mode 100644
index 0000000000000000000000000000000000000000..0e630dc6b695ee1d595d4015436988dec9508a34
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/InvalidEdgeException.java
@@ -0,0 +1,44 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph;
+
+public class InvalidEdgeException extends Exception
+{
+	private static final long serialVersionUID = -2098345780925217513L;
+
+	public InvalidEdgeException()
+	{
+		super();
+	}
+
+	public InvalidEdgeException(final String msg)
+	{
+		super(msg);
+	}
+
+	public InvalidEdgeException(final String msg, final Throwable cause)
+	{
+		super(msg, cause);
+	}
+
+	public InvalidEdgeException(final Throwable cause)
+	{
+		super(cause);
+	}
+}
diff --git a/src/main/java/com/syncleus/dann/graph/InvalidEndPointDirectionException.java b/src/main/java/com/syncleus/dann/graph/InvalidEndPointDirectionException.java
new file mode 100644
index 0000000000000000000000000000000000000000..b769b2c4c171fd2d33427ab5a33f0000550f67ca
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/InvalidEndPointDirectionException.java
@@ -0,0 +1,44 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph;
+
+public class InvalidEndPointDirectionException extends InvalidEdgeDirectionException
+{
+	private static final long serialVersionUID = -82374502185211L;
+
+	public InvalidEndPointDirectionException()
+	{
+		super();
+	}
+
+	public InvalidEndPointDirectionException(final String msg)
+	{
+		super(msg);
+	}
+
+	public InvalidEndPointDirectionException(final String msg, final Throwable cause)
+	{
+		super(msg, cause);
+	}
+
+	public InvalidEndPointDirectionException(final Throwable cause)
+	{
+		super(cause);
+	}
+}
diff --git a/src/main/java/com/syncleus/dann/graph/MixableBidirectedEdge.java b/src/main/java/com/syncleus/dann/graph/MixableBidirectedEdge.java
new file mode 100644
index 0000000000000000000000000000000000000000..283d55251d83950bd98257994d284169ccf3d26a
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/MixableBidirectedEdge.java
@@ -0,0 +1,43 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph;
+
+public interface MixableBidirectedEdge<N, LN extends N, RN extends N> extends Edge<N>
+{
+	interface Endpoint<NN, EN extends NN, ON extends NN> extends Edge.Endpoint<NN, EN>
+	{
+		enum Direction
+		{
+			OUTWARD, INWARD, NONE
+		}
+
+		Direction getDirection();
+		Endpoint<NN, ON,EN> getNeighbor();
+	};
+
+	Endpoint<N, LN,RN> getLeftEndPoint();
+	Endpoint<N, RN,LN> getRightEndPoint();
+	boolean isIntroverted();
+	boolean isExtroverted();
+	boolean isDirected();
+	boolean isHalfEdge();
+	boolean isLooseEdge();
+	boolean isOrdinaryEdge();
+	boolean isLoop();
+}
diff --git a/src/main/java/com/syncleus/dann/graph/MixableDirectedEdge.java b/src/main/java/com/syncleus/dann/graph/MixableDirectedEdge.java
new file mode 100644
index 0000000000000000000000000000000000000000..b3a41d95a8832c39eef95b0d0401d0945b48bb4d
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/MixableDirectedEdge.java
@@ -0,0 +1,29 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph;
+
+public interface MixableDirectedEdge<N, SN extends N, DN extends N> extends MixableBidirectedEdge<N, SN, DN>
+{
+	interface Endpoint<NN, EN extends NN, ON extends NN> extends MixableBidirectedEdge.Endpoint<NN, EN,ON>
+	{
+	};
+
+	Endpoint<N, SN,DN> getSourceEndPoint();
+	Endpoint<N, DN,SN> getDestinationEndPoint();
+}
diff --git a/src/main/java/com/syncleus/dann/graph/MutableAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graph/MutableAdjacencyGraph.java
index 4e252e5978062fac3d5a0f6829deed1fd91e7dbc..8e1488eeb25e85ac9262fa9bdc7cb731a8135c0d 100644
--- a/src/main/java/com/syncleus/dann/graph/MutableAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/MutableAdjacencyGraph.java
@@ -18,16 +18,14 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 import com.syncleus.dann.graph.context.ContextGraphElement;
 
 public class MutableAdjacencyGraph<N, E extends Edge<N>> extends AbstractAdjacencyGraph<N, E> implements MutableGraph<N, E>
 {
 	private static final long serialVersionUID = -4613327727609060678L;
 
+/*
 	public MutableAdjacencyGraph()
 	{
 		super();
@@ -46,198 +44,98 @@ public class MutableAdjacencyGraph<N, E extends Edge<N>> extends AbstractAdjacen
 	@Override
 	public boolean add(final E newEdge)
 	{
-		if( newEdge == null )
-			throw new IllegalArgumentException("newEdge can not be null");
-		if( !this.getNodes().containsAll(newEdge.getNodes()) )
-			throw new IllegalArgumentException("newEdge has a node as an end point that is not part of the graph");
-
-		// if context is enabled lets check if it can join
-		if( this.isContextEnabled() && (newEdge instanceof ContextGraphElement)
-				&& !((ContextGraphElement)newEdge).joiningGraph(this) )
-			return false;
-
-		if( this.getInternalEdges().add(newEdge) )
-		{
-			for(final N currentNode : newEdge.getNodes())
-			{
-				this.getInternalAdjacencyEdges().get(currentNode).add(newEdge);
-
-				final List<N> newAdjacentNodes = new ArrayList<N>(newEdge.getNodes());
-				newAdjacentNodes.remove(currentNode);
-				for(final N newAdjacentNode : newAdjacentNodes)
-					this.getInternalAdjacencyNodes().get(currentNode).add(newAdjacentNode);
-			}
-			return true;
-		}
-
-		return false;
+		return super.add(newEdge);
 	}
 
 	@Override
 	public boolean add(final N newNode)
 	{
-		if( newNode == null )
-			throw new IllegalArgumentException("newNode can not be null");
-
-		if( this.getInternalAdjacencyEdges().containsKey(newNode) )
-			return false;
-
-		// if context is enabled lets check if it can join
-		if( this.isContextEnabled() && (newNode instanceof ContextGraphElement)
-				&& !((ContextGraphElement)newNode).joiningGraph(this) )
-			return false;
-
-		this.getInternalAdjacencyEdges().put(newNode, new HashSet<E>());
-		this.getInternalAdjacencyNodes().put(newNode, new ArrayList<N>());
-		return true;
+		return super.add(newNode);
 	}
 
 	@Override
 	public boolean remove(final E edgeToRemove)
 	{
-		if( edgeToRemove == null )
-			throw new IllegalArgumentException("removeSynapse can not be null");
-
-		if( !this.getInternalEdges().contains(edgeToRemove) )
-			return false;
-
-		// if context is enabled lets check if it can join
-		if( this.isContextEnabled()
-				&& (edgeToRemove instanceof ContextGraphElement)
-				&& !((ContextGraphElement)edgeToRemove).leavingGraph(this) )
-			return false;
-
-		if( !this.getInternalEdges().remove(edgeToRemove) )
-			throw new IllegalStateException("could not remove edge even though it is present");
-
-		for(final N removeNode : edgeToRemove.getNodes())
-		{
-			this.getInternalAdjacencyEdges().get(removeNode).remove(edgeToRemove);
-
-			final List<N> removeAdjacentNodes = new ArrayList<N>(edgeToRemove.getNodes());
-			removeAdjacentNodes.remove(removeNode);
-			for(final N removeAdjacentNode : removeAdjacentNodes)
-				this.getInternalAdjacencyNodes().get(removeNode).remove(removeAdjacentNode);
-		}
-		return true;
+		return super.remove(edgeToRemove);
 	}
 
 	@Override
 	public boolean remove(final N nodeToRemove)
 	{
-		if( nodeToRemove == null )
-			throw new IllegalArgumentException("node can not be null");
-
-		if( !this.getInternalAdjacencyEdges().containsKey(nodeToRemove) )
-			return false;
-
-		// if context is enabled lets check if it can join
-		if( this.isContextEnabled()
-				&& (nodeToRemove instanceof ContextGraphElement)
-				&& !((ContextGraphElement)nodeToRemove).leavingGraph(this) )
-			return false;
-
-		final Set<E> removeEdges = this.getInternalAdjacencyEdges().get(nodeToRemove);
-
-		//remove all the edges
-		for(final E removeEdge : removeEdges)
-			this.remove(removeEdge);
-
-		//modify edges by removing the node to remove
-		final Set<E> newEdges = new HashSet<E>();
-		for(final E removeEdge : removeEdges)
-		{
-			E newEdge = (E) removeEdge.disconnect(nodeToRemove);
-			while( (newEdge != null) && (newEdge.getNodes().contains(nodeToRemove)) )
-				newEdge = (E) removeEdge.disconnect(nodeToRemove);
-			if( newEdge != null )
-				newEdges.add(newEdge);
-		}
-
-		//add the modified edges
-		for(final E newEdge : newEdges)
-			this.add(newEdge);
-
-		//remove the node itself
-		this.getInternalAdjacencyEdges().remove(nodeToRemove);
-		this.getInternalAdjacencyNodes().remove(nodeToRemove);
-
-		return true;
+		return super.remove(nodeToRemove);
 	}
 
 	@Override
 	public boolean clear()
 	{
-		boolean removedSomething = false;
-
-		//first lets remove all the edges
-		for(E edge : this.getEdges())
-		{
-			//lets just make sure we arent some how getting an we dont actually own, this shouldnt be possible so its
-			//an assert. This ensures that if remove() comes back false it must be because the context didnt allow it.
-			assert this.getInternalEdges().contains(edge);
-
-			if( !this.remove(edge) )
-				throw new IllegalStateException("one of the edges will not allow itself to leave this graph");
-
-			removedSomething = true;
-		}
+		return super.clear();
+	}
 
-		//now lets remove all the nodes
-		for(N node : this.getNodes())
-		{
-			//lets just make sure we arent some how getting an we dont actually own, this shouldnt be possible so its
-			//an assert. This ensures that if remove() comes back false it must be because the context didnt allow it.
-			assert ( !this.getInternalAdjacencyEdges().containsKey(node) );
+	@Override
+	protected MutableAdjacencyGraph<N, E> clone()
+	{
+		return (MutableAdjacencyGraph<N, E>) super.clone();
+	}
+*/
+	final private Map<NodeEndpoint<N,N,E>,EdgeEndpoint<N, E, ? extends E>> nodeAdjacency = new HashMap<NodeEndpoint<N, N, E>, EdgeEndpoint<N, E, ? extends E>>();
 
-			if( !this.remove(node) )
-				throw new IllegalStateException("one of the nodes will not allow itself to leave this graph");
+	@Override
+	protected Set<EdgeEndpoint<N, E, ? extends E>> getAdjacentEdgeEndPoint(Graph.NodeEndpoint<N, ? extends N, E> nodeEndPoint)
+	{
+		return null;  //To change body of implemented methods use File | Settings | File Templates.
+	}
 
-			removedSomething = true;
-		}
+	@Override
+	public Set<? extends EdgeEndpoint<N, E, ? extends E>> getEdgeEndpoints()
+	{
+		return null;  //To change body of implemented methods use File | Settings | File Templates.
+	}
 
-		return removedSomething;
+	@Override
+	public Set<? extends NodeEndpoint<N, ? extends N, E>> getNodeEndpoints()
+	{
+		return null;  //To change body of implemented methods use File | Settings | File Templates.
 	}
 
 	@Override
-	public MutableAdjacencyGraph<N, E> cloneAdd(final E newEdge)
+	public MutableHyperEdge.Endpoint<Object, Object> join(Object node) throws InvalidEdgeException
 	{
-		return (MutableAdjacencyGraph<N, E>) super.cloneAdd(newEdge);
+		return null;  //To change body of implemented methods use File | Settings | File Templates.
 	}
 
 	@Override
-	public MutableAdjacencyGraph<N, E> cloneAdd(final N newNode)
+	public Map<Object, MutableHyperEdge.Endpoint<Object, Object>> join(Set<Object> nodes) throws InvalidEdgeException
 	{
-		return (MutableAdjacencyGraph<N, E>) super.cloneAdd(newNode);
+		return null;  //To change body of implemented methods use File | Settings | File Templates.
 	}
 
 	@Override
-	public MutableAdjacencyGraph<N, E> cloneAdd(final Set<N> newNodes, final Set<E> newEdges)
+	public void leave(MutableHyperEdge.Endpoint<Object, Object> endPoint) throws InvalidEdgeException
 	{
-		return (MutableAdjacencyGraph<N, E>) super.cloneAdd(newNodes, newEdges);
+		//To change body of implemented methods use File | Settings | File Templates.
 	}
 
 	@Override
-	public MutableAdjacencyGraph<N, E> cloneRemove(final E edgeToRemove)
+	public void leave(Set<MutableHyperEdge.Endpoint<Object, Object>> endPoint) throws InvalidEdgeException
 	{
-		return (MutableAdjacencyGraph<N, E>) super.cloneRemove(edgeToRemove);
+		//To change body of implemented methods use File | Settings | File Templates.
 	}
 
 	@Override
-	public MutableAdjacencyGraph<N, E> cloneRemove(final N nodeToRemove)
+	public void clear() throws InvalidEdgeException
 	{
-		return (MutableAdjacencyGraph<N, E>) super.cloneRemove(nodeToRemove);
+		//To change body of implemented methods use File | Settings | File Templates.
 	}
 
 	@Override
-	public MutableAdjacencyGraph<N, E> cloneRemove(final Set<N> deleteNodes, final Set<E> deleteEdges)
+	public Map<Object, MutableHyperEdge.Endpoint<Object, Object>> reconfigure(Set<Object> connectNodes, Set<MutableHyperEdge.Endpoint<Object, Object>> disconnectEndPoints) throws InvalidEdgeException
 	{
-		return (MutableAdjacencyGraph<N, E>) super.cloneRemove(deleteNodes, deleteEdges);
+		return null;  //To change body of implemented methods use File | Settings | File Templates.
 	}
 
 	@Override
-	public MutableAdjacencyGraph<N, E> clone()
+	public boolean isContextEnabled()
 	{
-		return (MutableAdjacencyGraph<N, E>) super.clone();
+		return false;  //To change body of implemented methods use File | Settings | File Templates.
 	}
 }
diff --git a/src/main/java/com/syncleus/dann/graph/UndirectedEdge.java b/src/main/java/com/syncleus/dann/graph/MutableBidirectedEdge.java
similarity index 85%
rename from src/main/java/com/syncleus/dann/graph/UndirectedEdge.java
rename to src/main/java/com/syncleus/dann/graph/MutableBidirectedEdge.java
index d4a9b4f7b06bf88f4c2a34a910512cdd1b36715b..8d8830bee8ba5a8a2de2465bc56c143ccf887b99 100644
--- a/src/main/java/com/syncleus/dann/graph/UndirectedEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/MutableBidirectedEdge.java
@@ -18,14 +18,9 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.List;
-
-public interface UndirectedEdge<N> extends BidirectedEdge<N>
+public interface MutableBidirectedEdge<N> extends MutableMixableBidirectedEdge<N, N,N>, BidirectedEdge<N>
 {
-	@Override
-	UndirectedEdge<N> disconnect(N node);
-	@Override
-	UndirectedEdge<N> disconnect(List<N> node);
-	@Override
-	UndirectedEdge<N> clone();
+	interface Endpoint<NN, EN extends NN, ON extends NN> extends MutableMixableBidirectedEdge.Endpoint<NN, EN,ON>, BidirectedEdge.Endpoint<NN, EN,ON>
+	{
+	};
 }
diff --git a/src/main/java/com/syncleus/dann/graph/MutableDirectedAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graph/MutableDirectedAdjacencyGraph.java
index ed8f003bd19292c10c6c5cb7d61736926092582c..3b2c1f631b597b1ae9930e78de57f2c64df25b13 100644
--- a/src/main/java/com/syncleus/dann/graph/MutableDirectedAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/MutableDirectedAdjacencyGraph.java
@@ -48,7 +48,7 @@ public class MutableDirectedAdjacencyGraph<N, E extends DirectedEdge<N>> extends
 	{
 		if( newEdge == null )
 			throw new IllegalArgumentException("newEdge can not be null");
-		if( !this.getNodes().containsAll(newEdge.getNodes()) )
+		if( !this.getTargets().containsAll(newEdge.getTargets()) )
 			throw new IllegalArgumentException("newEdge has a node as an end point that is not part of the graph");
 
 		// if context is enabled lets check if it can join
@@ -58,11 +58,11 @@ public class MutableDirectedAdjacencyGraph<N, E extends DirectedEdge<N>> extends
 
 		if( this.getInternalEdges().add(newEdge) )
 		{
-			for(final N currentNode : newEdge.getNodes())
+			for(final N currentNode : newEdge.getTargets())
 			{
 				this.getInternalAdjacencyEdges().get(currentNode).add(newEdge);
 
-				final List<N> newAdjacentNodes = new ArrayList<N>(newEdge.getNodes());
+				final List<N> newAdjacentNodes = new ArrayList<N>(newEdge.getTargets());
 				newAdjacentNodes.remove(currentNode);
 				for(final N newAdjacentNode : newAdjacentNodes)
 					this.getInternalAdjacencyNodes().get(currentNode).add(newAdjacentNode);
@@ -110,11 +110,11 @@ public class MutableDirectedAdjacencyGraph<N, E extends DirectedEdge<N>> extends
 		if( !this.getInternalEdges().remove(edgeToRemove) )
 			return false;
 
-		for(final N removeNode : edgeToRemove.getNodes())
+		for(final N removeNode : edgeToRemove.getTargets())
 		{
 			this.getInternalAdjacencyEdges().get(removeNode).remove(edgeToRemove);
 
-			final List<N> removeAdjacentNodes = new ArrayList<N>(edgeToRemove.getNodes());
+			final List<N> removeAdjacentNodes = new ArrayList<N>(edgeToRemove.getTargets());
 			removeAdjacentNodes.remove(removeNode);
 			for(final N removeAdjacentNode : removeAdjacentNodes)
 				this.getInternalAdjacencyNodes().get(removeNode).remove(removeAdjacentNode);
@@ -148,7 +148,7 @@ public class MutableDirectedAdjacencyGraph<N, E extends DirectedEdge<N>> extends
 		for(final E removeEdge : removeEdges)
 		{
 			E newEdge = (E) removeEdge.disconnect(nodeToRemove);
-			while( (newEdge != null) && (newEdge.getNodes().contains(nodeToRemove)) )
+			while( (newEdge != null) && (newEdge.getTargets().contains(nodeToRemove)) )
 				newEdge = (E) removeEdge.disconnect(nodeToRemove);
 			if( newEdge != null )
 				newEdges.add(newEdge);
@@ -184,7 +184,7 @@ public class MutableDirectedAdjacencyGraph<N, E extends DirectedEdge<N>> extends
 		}
 
 		//now lets remove all the nodes
-		for(N node : this.getNodes())
+		for(N node : this.getTargets())
 		{
 			//lets just make sure we arent some how getting an we dont actually own, this shouldnt be possible so its
 			//an assert. This ensures that if remove() comes back false it must be because the context didnt allow it.
@@ -200,43 +200,7 @@ public class MutableDirectedAdjacencyGraph<N, E extends DirectedEdge<N>> extends
 	}
 
 	@Override
-	public MutableDirectedAdjacencyGraph<N, E> cloneAdd(final E newEdge)
-	{
-		return (MutableDirectedAdjacencyGraph<N, E>) super.cloneAdd(newEdge);
-	}
-
-	@Override
-	public MutableDirectedAdjacencyGraph<N, E> cloneAdd(final N newNode)
-	{
-		return (MutableDirectedAdjacencyGraph<N, E>) super.cloneAdd(newNode);
-	}
-
-	@Override
-	public MutableDirectedAdjacencyGraph<N, E> cloneAdd(final Set<N> newNodes, final Set<E> newEdges)
-	{
-		return (MutableDirectedAdjacencyGraph<N, E>) super.cloneAdd(newNodes, newEdges);
-	}
-
-	@Override
-	public MutableDirectedAdjacencyGraph<N, E> cloneRemove(final E edgeToRemove)
-	{
-		return (MutableDirectedAdjacencyGraph<N, E>) super.cloneRemove(edgeToRemove);
-	}
-
-	@Override
-	public MutableDirectedAdjacencyGraph<N, E> cloneRemove(final N nodeToRemove)
-	{
-		return (MutableDirectedAdjacencyGraph<N, E>) super.cloneRemove(nodeToRemove);
-	}
-
-	@Override
-	public MutableDirectedAdjacencyGraph<N, E> cloneRemove(final Set<N> deleteNodes, final Set<E> deleteEdges)
-	{
-		return (MutableDirectedAdjacencyGraph<N, E>) super.cloneRemove(deleteNodes, deleteEdges);
-	}
-
-	@Override
-	public MutableDirectedAdjacencyGraph<N, E> clone()
+	protected MutableDirectedAdjacencyGraph<N, E> clone()
 	{
 		return (MutableDirectedAdjacencyGraph<N, E>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/MutableDirectedEdge.java b/src/main/java/com/syncleus/dann/graph/MutableDirectedEdge.java
new file mode 100644
index 0000000000000000000000000000000000000000..d59c355e23d1ddbbc2931482cb780aebae044855
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/MutableDirectedEdge.java
@@ -0,0 +1,26 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph;
+
+public interface MutableDirectedEdge<N> extends MutableBidirectedEdge<N>, DirectedEdge<N>, MutableMixableDirectedEdge<N, N,N>
+{
+	interface Endpoint<NN, EN extends NN, ON extends NN> extends MutableBidirectedEdge.Endpoint<NN, EN,ON>, DirectedEdge.Endpoint<NN, EN,ON>, MutableMixableDirectedEdge.Endpoint<NN, EN,ON>
+	{
+	};
+}
diff --git a/src/main/java/com/syncleus/dann/graph/context/SignalContextNode.java b/src/main/java/com/syncleus/dann/graph/MutableEdge.java
similarity index 87%
rename from src/main/java/com/syncleus/dann/graph/context/SignalContextNode.java
rename to src/main/java/com/syncleus/dann/graph/MutableEdge.java
index c40941d9a23595d2ec42914ec7440b3f3a3c1e39..e8ba19ef2e50795999927e68443f6cb4514eaa95 100644
--- a/src/main/java/com/syncleus/dann/graph/context/SignalContextNode.java
+++ b/src/main/java/com/syncleus/dann/graph/MutableEdge.java
@@ -16,12 +16,12 @@
  *  Philadelphia, PA 19148                                                     *
  *                                                                             *
  ******************************************************************************/
-package com.syncleus.dann.graph.context;
+package com.syncleus.dann.graph;
 
-import com.syncleus.dann.graph.Edge;
-
-public interface SignalContextNode<N, E extends Edge<N>, S>
+public interface MutableEdge<N> extends Edge<N>
 {
-	void neighborNodeStateChanged(E edge, N node, S newState);
-	S getState();
+	interface Endpoint<NN, EN extends NN> extends Edge.Endpoint<NN, EN>
+	{
+		void setTarget(EN newTarget) throws InvalidEdgeException;
+	};
 }
diff --git a/src/main/java/com/syncleus/dann/graph/MutableGraph.java b/src/main/java/com/syncleus/dann/graph/MutableGraph.java
index b402537ed5b7bf638a13d309515a8129fe7276ea..f8a166bc901976e798cbffefd824e9dc30f3a5b5 100644
--- a/src/main/java/com/syncleus/dann/graph/MutableGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/MutableGraph.java
@@ -18,11 +18,30 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-public interface MutableGraph<N, E extends Edge<N>> extends Graph<N, E>
+import java.util.Map;
+import java.util.Set;
+
+public interface MutableGraph<N, E extends Edge<N>> extends AssignableGraph<N,E>
 {
-	boolean add(E newEdge);
-	boolean add(N newNode);
-	boolean remove(E edgeToRemove);
-	boolean remove(N nodeToRemove);
-	boolean clear();
+	interface NodeEndpoint<ON, MN extends ON, OE extends Edge<? extends ON>> extends AssignableGraph.NodeEndpoint<ON,MN,OE>, MutableHyperEdge.Endpoint<Object, MN>
+	{
+	};
+
+	interface EdgeEndpoint<ON, OE extends Edge<? extends ON>, ME extends OE> extends AssignableGraph.EdgeEndpoint<ON,OE,ME>, MutableHyperEdge.Endpoint<Object, ME>
+	{
+	};
+
+	NodeEndpoint<N,? extends N,E> join(final N node) throws InvalidEdgeException;
+	Map<N, ? extends NodeEndpoint<N, ? extends N,E>> joinNodes(final Set<? extends N> nodes) throws InvalidEdgeException;
+	void leave(final NodeEndpoint<? extends N, ? extends N,? extends E> endPoint) throws InvalidEdgeException;
+	void leaveNodes(final Set<? extends NodeEndpoint<? extends N, ? extends N,? extends E>> endPoint) throws InvalidEdgeException;
+
+	EdgeEndpoint<N, E, ? extends E> join(final E edge) throws InvalidEdgeException;
+	Map<N, ? extends EdgeEndpoint<N, E, ? extends E>> joinEdges(final Set<? extends E> edges) throws InvalidEdgeException;
+	void leave(final EdgeEndpoint<? extends N, ? extends E, ? extends E> endPoint) throws InvalidEdgeException;
+	void leaveEdges(final Set<? extends EdgeEndpoint<? extends N, ? extends E, ? extends E>> endPoint) throws InvalidEdgeException;
+
+	void clear() throws InvalidEdgeException;
+
+	Map<? extends Object, ? extends Graph.Endpoint<? extends N, ? extends N>> reconfigure(final Set<? extends N> addNodes, final Set<? extends E> addEdges, final Set<? extends Graph.Endpoint<? extends N, ? extends N>> disconnectEndPoints) throws InvalidEdgeException;
 }
diff --git a/src/main/java/com/syncleus/dann/graph/MutableHyperAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graph/MutableHyperAdjacencyGraph.java
index bc6ae075fd82de475e937e4de25030b69c5dc6f3..b812b7537f4996f80fafd7d8b640a4c3a81b7b3d 100644
--- a/src/main/java/com/syncleus/dann/graph/MutableHyperAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/MutableHyperAdjacencyGraph.java
@@ -48,7 +48,7 @@ public class MutableHyperAdjacencyGraph<N, E extends HyperEdge<N>> extends Abstr
 	{
 		if( newEdge == null )
 			throw new IllegalArgumentException("newEdge can not be null");
-		if( !this.getNodes().containsAll(newEdge.getNodes()) )
+		if( !this.getTargets().containsAll(newEdge.getTargets()) )
 			throw new IllegalArgumentException("newEdge has a node as an end point that is not part of the graph");
 
 		// if context is enabled lets check if it can join
@@ -58,11 +58,11 @@ public class MutableHyperAdjacencyGraph<N, E extends HyperEdge<N>> extends Abstr
 
 		if( this.getInternalEdges().add(newEdge) )
 		{
-			for(final N currentNode : newEdge.getNodes())
+			for(final N currentNode : newEdge.getTargets())
 			{
 				this.getInternalAdjacencyEdges().get(currentNode).add(newEdge);
 
-				final List<N> newAdjacentNodes = new ArrayList<N>(newEdge.getNodes());
+				final List<N> newAdjacentNodes = new ArrayList<N>(newEdge.getTargets());
 				newAdjacentNodes.remove(currentNode);
 				for(final N newAdjacentNode : newAdjacentNodes)
 					this.getInternalAdjacencyNodes().get(currentNode).add(newAdjacentNode);
@@ -110,11 +110,11 @@ public class MutableHyperAdjacencyGraph<N, E extends HyperEdge<N>> extends Abstr
 		if( !this.getInternalEdges().remove(edgeToRemove) )
 			return false;
 
-		for(final N removeNode : edgeToRemove.getNodes())
+		for(final N removeNode : edgeToRemove.getTargets())
 		{
 			this.getInternalAdjacencyEdges().get(removeNode).remove(edgeToRemove);
 
-			final List<N> removeAdjacentNodes = new ArrayList<N>(edgeToRemove.getNodes());
+			final List<N> removeAdjacentNodes = new ArrayList<N>(edgeToRemove.getTargets());
 			removeAdjacentNodes.remove(removeNode);
 			for(final N removeAdjacentNode : removeAdjacentNodes)
 				this.getInternalAdjacencyNodes().get(removeNode).remove(removeAdjacentNode);
@@ -148,7 +148,7 @@ public class MutableHyperAdjacencyGraph<N, E extends HyperEdge<N>> extends Abstr
 		for(final E removeEdge : removeEdges)
 		{
 			E newEdge = (E) removeEdge.disconnect(nodeToRemove);
-			while( (newEdge != null) && (newEdge.getNodes().contains(nodeToRemove)) )
+			while( (newEdge != null) && (newEdge.getTargets().contains(nodeToRemove)) )
 				newEdge = (E) removeEdge.disconnect(nodeToRemove);
 			if( newEdge != null )
 				newEdges.add(newEdge);
@@ -184,7 +184,7 @@ public class MutableHyperAdjacencyGraph<N, E extends HyperEdge<N>> extends Abstr
 		}
 
 		//now lets remove all the nodes
-		for(N node : this.getNodes())
+		for(N node : this.getTargets())
 		{
 			//lets just make sure we arent some how getting an we dont actually own, this shouldnt be possible so its
 			//an assert. This ensures that if remove() comes back false it must be because the context didnt allow it.
@@ -200,43 +200,7 @@ public class MutableHyperAdjacencyGraph<N, E extends HyperEdge<N>> extends Abstr
 	}
 
 	@Override
-	public MutableHyperAdjacencyGraph<N, E> cloneAdd(final E newEdge)
-	{
-		return (MutableHyperAdjacencyGraph<N, E>) super.cloneAdd(newEdge);
-	}
-
-	@Override
-	public MutableHyperAdjacencyGraph<N, E> cloneAdd(final N newNode)
-	{
-		return (MutableHyperAdjacencyGraph<N, E>) super.cloneAdd(newNode);
-	}
-
-	@Override
-	public MutableHyperAdjacencyGraph<N, E> cloneAdd(final Set<N> newNodes, final Set<E> newEdges)
-	{
-		return (MutableHyperAdjacencyGraph<N, E>) super.cloneAdd(newNodes, newEdges);
-	}
-
-	@Override
-	public MutableHyperAdjacencyGraph<N, E> cloneRemove(final E edgeToRemove)
-	{
-		return (MutableHyperAdjacencyGraph<N, E>) super.cloneRemove(edgeToRemove);
-	}
-
-	@Override
-	public MutableHyperAdjacencyGraph<N, E> cloneRemove(final N nodeToRemove)
-	{
-		return (MutableHyperAdjacencyGraph<N, E>) super.cloneRemove(nodeToRemove);
-	}
-
-	@Override
-	public MutableHyperAdjacencyGraph<N, E> cloneRemove(final Set<N> deleteNodes, final Set<E> deleteEdges)
-	{
-		return (MutableHyperAdjacencyGraph<N, E>) super.cloneRemove(deleteNodes, deleteEdges);
-	}
-
-	@Override
-	public MutableHyperAdjacencyGraph<N, E> clone()
+	protected MutableHyperAdjacencyGraph<N, E> clone()
 	{
 		return (MutableHyperAdjacencyGraph<N, E>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/MutableHyperEdge.java b/src/main/java/com/syncleus/dann/graph/MutableHyperEdge.java
new file mode 100644
index 0000000000000000000000000000000000000000..620f81bfa3db8ab50d90b4584eadb8d921f7f7ee
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/MutableHyperEdge.java
@@ -0,0 +1,35 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph;
+
+import java.util.*;
+
+public interface MutableHyperEdge<N> extends HyperEdge<N>, MutableEdge<N>
+{
+	interface Endpoint<NN, EN extends NN> extends HyperEdge.Endpoint<NN, EN>, MutableEdge.Endpoint<NN, EN>
+	{
+	};
+
+	Endpoint<N, N> join(final N node) throws InvalidEdgeException;
+	Map<N,Endpoint<N, N>> join(final Set<N> nodes) throws InvalidEdgeException;
+	void leave(final Endpoint<N, N> endPoint) throws InvalidEdgeException;
+	void leave(final Set<Endpoint<N, N>> endPoint) throws InvalidEdgeException;
+	void clear() throws InvalidEdgeException;
+	Map<N,Endpoint<N, N>> reconfigure(final Set<N> connectNodes, final Set<Endpoint<N, N>> disconnectEndPoints) throws InvalidEdgeException;
+}
diff --git a/src/main/java/com/syncleus/dann/graph/MutableMixableBidirectedEdge.java b/src/main/java/com/syncleus/dann/graph/MutableMixableBidirectedEdge.java
new file mode 100644
index 0000000000000000000000000000000000000000..c52a32990d8dded77e74cbcdbf70028e1bb7c552
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/MutableMixableBidirectedEdge.java
@@ -0,0 +1,30 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph;
+
+public interface MutableMixableBidirectedEdge<N, LN extends N, RN extends N> extends MixableBidirectedEdge<N, LN,RN>, MutableEdge<N>
+{
+	interface Endpoint<NN, EN extends NN, ON extends NN> extends MixableBidirectedEdge.Endpoint<NN, EN,ON>, MutableEdge.Endpoint<NN, EN>
+	{
+		void setDirection(Direction newDirection) throws InvalidEndPointDirectionException;
+	};
+
+	void invertDirection() throws InvalidEdgeDirectionException;
+	void reassign(LN newLeftNode, Endpoint.Direction newLeftDirection, RN newRightNode, Endpoint.Direction newRightDirection) throws InvalidEdgeException;
+}
diff --git a/src/main/java/com/syncleus/dann/graph/MutableMixableDirectedEdge.java b/src/main/java/com/syncleus/dann/graph/MutableMixableDirectedEdge.java
new file mode 100644
index 0000000000000000000000000000000000000000..c6676ebbccd7a03e82b5c02e333cfea1d53b8349
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/MutableMixableDirectedEdge.java
@@ -0,0 +1,28 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph;
+
+public interface MutableMixableDirectedEdge<N, SN extends N, DN extends N> extends MixableDirectedEdge<N, SN, DN>, MutableMixableBidirectedEdge<N, SN,DN>
+{
+	interface Endpoint<NN, EN extends NN, ON extends NN> extends MixableDirectedEdge.Endpoint<NN, EN,ON>, MutableMixableBidirectedEdge.Endpoint<NN, EN,ON>
+	{
+	};
+
+	void reassign(SN newSourceNode, DN newDestinationNode) throws InvalidEdgeException;
+}
diff --git a/src/main/java/com/syncleus/dann/graph/MutableRootedTreeAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graph/MutableRootedTreeAdjacencyGraph.java
index 6c55382aa63c2a596fc4a542a1afdb866cbad8c8..274337c7b58465e374b6f7180d8722c3a8d22d22 100644
--- a/src/main/java/com/syncleus/dann/graph/MutableRootedTreeAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/MutableRootedTreeAdjacencyGraph.java
@@ -48,7 +48,7 @@ public class MutableRootedTreeAdjacencyGraph<N, E extends DirectedEdge<N>> exten
 	{
 		if( newEdge == null )
 			throw new IllegalArgumentException("newEdge can not be null");
-		if( !this.getNodes().containsAll(newEdge.getNodes()) )
+		if( !this.getTargets().containsAll(newEdge.getTargets()) )
 			throw new IllegalArgumentException("newEdge has a node as an end point that is not part of the graph");
 
 		// if context is enabled lets check if it can join
@@ -58,11 +58,11 @@ public class MutableRootedTreeAdjacencyGraph<N, E extends DirectedEdge<N>> exten
 
 		if( this.getInternalEdges().add(newEdge) )
 		{
-			for(final N currentNode : newEdge.getNodes())
+			for(final N currentNode : newEdge.getTargets())
 			{
 				this.getInternalAdjacencyEdges().get(currentNode).add(newEdge);
 
-				final List<N> newAdjacentNodes = new ArrayList<N>(newEdge.getNodes());
+				final List<N> newAdjacentNodes = new ArrayList<N>(newEdge.getTargets());
 				newAdjacentNodes.remove(currentNode);
 				for(final N newAdjacentNode : newAdjacentNodes)
 					this.getInternalAdjacencyNodes().get(currentNode).add(newAdjacentNode);
@@ -110,11 +110,11 @@ public class MutableRootedTreeAdjacencyGraph<N, E extends DirectedEdge<N>> exten
 		if( !this.getInternalEdges().remove(edgeToRemove) )
 			return false;
 
-		for(final N removeNode : edgeToRemove.getNodes())
+		for(final N removeNode : edgeToRemove.getTargets())
 		{
 			this.getInternalAdjacencyEdges().get(removeNode).remove(edgeToRemove);
 
-			final List<N> removeAdjacentNodes = new ArrayList<N>(edgeToRemove.getNodes());
+			final List<N> removeAdjacentNodes = new ArrayList<N>(edgeToRemove.getTargets());
 			removeAdjacentNodes.remove(removeNode);
 			for(final N removeAdjacentNode : removeAdjacentNodes)
 				this.getInternalAdjacencyNodes().get(removeNode).remove(removeAdjacentNode);
@@ -148,7 +148,7 @@ public class MutableRootedTreeAdjacencyGraph<N, E extends DirectedEdge<N>> exten
 		for(final E removeEdge : removeEdges)
 		{
 			E newEdge = (E) removeEdge.disconnect(nodeToRemove);
-			while( (newEdge != null) && (newEdge.getNodes().contains(nodeToRemove)) )
+			while( (newEdge != null) && (newEdge.getTargets().contains(nodeToRemove)) )
 				newEdge = (E) removeEdge.disconnect(nodeToRemove);
 			if( newEdge != null )
 				newEdges.add(newEdge);
@@ -184,7 +184,7 @@ public class MutableRootedTreeAdjacencyGraph<N, E extends DirectedEdge<N>> exten
 		}
 
 		//now lets remove all the nodes
-		for(N node : this.getNodes())
+		for(N node : this.getTargets())
 		{
 			//lets just make sure we arent some how getting an we dont actually own, this shouldnt be possible so its
 			//an assert. This ensures that if remove() comes back false it must be because the context didnt allow it.
@@ -200,43 +200,7 @@ public class MutableRootedTreeAdjacencyGraph<N, E extends DirectedEdge<N>> exten
 	}
 
 	@Override
-	public MutableRootedTreeAdjacencyGraph<N, E> cloneAdd(final E newEdge)
-	{
-		return (MutableRootedTreeAdjacencyGraph<N, E>) super.cloneAdd(newEdge);
-	}
-
-	@Override
-	public MutableRootedTreeAdjacencyGraph<N, E> cloneAdd(final N newNode)
-	{
-		return (MutableRootedTreeAdjacencyGraph<N, E>) super.cloneAdd(newNode);
-	}
-
-	@Override
-	public MutableRootedTreeAdjacencyGraph<N, E> cloneAdd(final Set<N> newNodes, final Set<E> newEdges)
-	{
-		return (MutableRootedTreeAdjacencyGraph<N, E>) super.cloneAdd(newNodes, newEdges);
-	}
-
-	@Override
-	public MutableRootedTreeAdjacencyGraph<N, E> cloneRemove(final E edgeToRemove)
-	{
-		return (MutableRootedTreeAdjacencyGraph<N, E>) super.cloneRemove(edgeToRemove);
-	}
-
-	@Override
-	public MutableRootedTreeAdjacencyGraph<N, E> cloneRemove(final N nodeToRemove)
-	{
-		return (MutableRootedTreeAdjacencyGraph<N, E>) super.cloneRemove(nodeToRemove);
-	}
-
-	@Override
-	public MutableRootedTreeAdjacencyGraph<N, E> cloneRemove(final Set<N> deleteNodes, final Set<E> deleteEdges)
-	{
-		return (MutableRootedTreeAdjacencyGraph<N, E>) super.cloneRemove(deleteNodes, deleteEdges);
-	}
-
-	@Override
-	public MutableRootedTreeAdjacencyGraph<N, E> clone()
+	protected MutableRootedTreeAdjacencyGraph<N, E> clone()
 	{
 		return (MutableRootedTreeAdjacencyGraph<N, E>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/MutableTreeAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graph/MutableTreeAdjacencyGraph.java
index 8e2b6746714cee10b2d68d00c584ebc7807662af..bc4a185ea70af52e533f4eb75e21035609353d0e 100644
--- a/src/main/java/com/syncleus/dann/graph/MutableTreeAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/MutableTreeAdjacencyGraph.java
@@ -49,14 +49,14 @@ public class MutableTreeAdjacencyGraph<N, E extends BidirectedEdge<N>> extends A
 	{
 		if( newEdge == null )
 			throw new IllegalArgumentException("newEdge can not be null");
-		if( !this.getNodes().containsAll(newEdge.getNodes()) )
+		if( !this.getTargets().containsAll(newEdge.getTargets()) )
 			throw new IllegalArgumentException("newEdge has a node as an end point that is not part of the graph");
 
 		//TODO make this more efficient
 		//make sure after we add thsi edge this will still be a tree
 		final Set<E> testEdges = new HashSet<E>(this.getEdges());
 		testEdges.add(newEdge);
-		final Graph<N, E> testGraph = new ImmutableAdjacencyGraph(this.getNodes(), testEdges);
+		final Graph<N, E> testGraph = new ImmutableAdjacencyGraph(this.getTargets(), testEdges);
 		if( !Trees.isTree(testGraph) )
 			throw new IllegalArgumentException("adding newEdge can not be added because this graph would no longer be a tree");
 
@@ -67,11 +67,11 @@ public class MutableTreeAdjacencyGraph<N, E extends BidirectedEdge<N>> extends A
 
 		if( this.getInternalEdges().add(newEdge) )
 		{
-			for(final N currentNode : newEdge.getNodes())
+			for(final N currentNode : newEdge.getTargets())
 			{
 				this.getInternalAdjacencyEdges().get(currentNode).add(newEdge);
 
-				final List<N> newAdjacentNodes = new ArrayList<N>(newEdge.getNodes());
+				final List<N> newAdjacentNodes = new ArrayList<N>(newEdge.getTargets());
 				newAdjacentNodes.remove(currentNode);
 				for(final N newAdjacentNode : newAdjacentNodes)
 					this.getInternalAdjacencyNodes().get(currentNode).add(newAdjacentNode);
@@ -119,11 +119,11 @@ public class MutableTreeAdjacencyGraph<N, E extends BidirectedEdge<N>> extends A
 		if( !this.getInternalEdges().remove(edgeToRemove) )
 			return false;
 
-		for(final N removeNode : edgeToRemove.getNodes())
+		for(final N removeNode : edgeToRemove.getTargets())
 		{
 			this.getInternalAdjacencyEdges().get(removeNode).remove(edgeToRemove);
 
-			final List<N> removeAdjacentNodes = new ArrayList<N>(edgeToRemove.getNodes());
+			final List<N> removeAdjacentNodes = new ArrayList<N>(edgeToRemove.getTargets());
 			removeAdjacentNodes.remove(removeNode);
 			for(final N removeAdjacentNode : removeAdjacentNodes)
 				this.getInternalAdjacencyNodes().get(removeNode).remove(removeAdjacentNode);
@@ -157,7 +157,7 @@ public class MutableTreeAdjacencyGraph<N, E extends BidirectedEdge<N>> extends A
 		for(final E removeEdge : removeEdges)
 		{
 			E newEdge = (E) removeEdge.disconnect(nodeToRemove);
-			while( (newEdge != null) && (newEdge.getNodes().contains(nodeToRemove)) )
+			while( (newEdge != null) && (newEdge.getTargets().contains(nodeToRemove)) )
 				newEdge = (E) removeEdge.disconnect(nodeToRemove);
 			if( newEdge != null )
 				newEdges.add(newEdge);
@@ -193,7 +193,7 @@ public class MutableTreeAdjacencyGraph<N, E extends BidirectedEdge<N>> extends A
 		}
 
 		//now lets remove all the nodes
-		for(N node : this.getNodes())
+		for(N node : this.getTargets())
 		{
 			//lets just make sure we arent some how getting an we dont actually own, this shouldnt be possible so its
 			//an assert. This ensures that if remove() comes back false it must be because the context didnt allow it.
@@ -208,45 +208,8 @@ public class MutableTreeAdjacencyGraph<N, E extends BidirectedEdge<N>> extends A
 		return removedSomething;
 	}
 
-	//TODO make sure these clone methods done generate a non-tree TreeGraoh
 	@Override
-	public MutableTreeAdjacencyGraph<N, E> cloneAdd(final E newEdge)
-	{
-		return (MutableTreeAdjacencyGraph<N, E>) super.cloneAdd(newEdge);
-	}
-
-	@Override
-	public MutableTreeAdjacencyGraph<N, E> cloneAdd(final N newNode)
-	{
-		return (MutableTreeAdjacencyGraph<N, E>) super.cloneAdd(newNode);
-	}
-
-	@Override
-	public MutableTreeAdjacencyGraph<N, E> cloneAdd(final Set<N> newNodes, final Set<E> newEdges)
-	{
-		return (MutableTreeAdjacencyGraph<N, E>) super.cloneAdd(newNodes, newEdges);
-	}
-
-	@Override
-	public MutableTreeAdjacencyGraph<N, E> cloneRemove(final E edgeToRemove)
-	{
-		return (MutableTreeAdjacencyGraph<N, E>) super.cloneRemove(edgeToRemove);
-	}
-
-	@Override
-	public MutableTreeAdjacencyGraph<N, E> cloneRemove(final N nodeToRemove)
-	{
-		return (MutableTreeAdjacencyGraph<N, E>) super.cloneRemove(nodeToRemove);
-	}
-
-	@Override
-	public MutableTreeAdjacencyGraph<N, E> cloneRemove(final Set<N> deleteNodes, final Set<E> deleteEdges)
-	{
-		return (MutableTreeAdjacencyGraph<N, E>) super.cloneRemove(deleteNodes, deleteEdges);
-	}
-
-	@Override
-	public MutableTreeAdjacencyGraph<N, E> clone()
+	protected MutableTreeAdjacencyGraph<N, E> clone()
 	{
 		return (MutableTreeAdjacencyGraph<N, E>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/MutableWeightedBidirectedEdge.java b/src/main/java/com/syncleus/dann/graph/MutableWeightedBidirectedEdge.java
new file mode 100644
index 0000000000000000000000000000000000000000..78d63a6be0c297b0844d23c3b17b292d8bf810f6
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/MutableWeightedBidirectedEdge.java
@@ -0,0 +1,26 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph;
+
+public interface MutableWeightedBidirectedEdge<N> extends MutableWeightedMixableBidirectedEdge<N, N,N>, WeightedBidirectedEdge<N>, MutableBidirectedEdge<N>
+{
+	interface Endpoint<NN, EN extends NN, ON extends NN> extends MutableWeightedMixableBidirectedEdge.Endpoint<NN, EN,ON>, WeightedBidirectedEdge.Endpoint<NN, EN,ON>, MutableBidirectedEdge.Endpoint<NN, EN,ON>
+	{
+	};
+}
\ No newline at end of file
diff --git a/src/main/java/com/syncleus/dann/graph/MutableWeightedDirectedEdge.java b/src/main/java/com/syncleus/dann/graph/MutableWeightedDirectedEdge.java
new file mode 100644
index 0000000000000000000000000000000000000000..ffa8235d1917f61e7bf03bf3adc7b764b1497d55
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/MutableWeightedDirectedEdge.java
@@ -0,0 +1,26 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph;
+
+public interface MutableWeightedDirectedEdge<N> extends MutableWeightedMixableDirectedEdge<N, N,N>, MutableWeightedBidirectedEdge<N>, WeightedDirectedEdge<N>, MutableDirectedEdge<N>
+{
+	interface Endpoint<NN, EN extends NN, ON extends NN> extends MutableWeightedMixableDirectedEdge.Endpoint<NN, EN,ON>, MutableWeightedBidirectedEdge.Endpoint<NN, EN,ON>, WeightedDirectedEdge.Endpoint<NN, EN,ON>, MutableDirectedEdge.Endpoint<NN, EN,ON>
+	{
+	};
+}
\ No newline at end of file
diff --git a/src/main/java/com/syncleus/dann/graph/context/SignalingContextEdge.java b/src/main/java/com/syncleus/dann/graph/MutableWeightedEdge.java
similarity index 88%
rename from src/main/java/com/syncleus/dann/graph/context/SignalingContextEdge.java
rename to src/main/java/com/syncleus/dann/graph/MutableWeightedEdge.java
index 69fd7a75276d293f1395b9f8c73c3e1bedc9bc54..1b21ae7b64504045fd3669786eede878d74a98cc 100644
--- a/src/main/java/com/syncleus/dann/graph/context/SignalingContextEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/MutableWeightedEdge.java
@@ -16,11 +16,11 @@
  *  Philadelphia, PA 19148                                                     *
  *                                                                             *
  ******************************************************************************/
-package com.syncleus.dann.graph.context;
+package com.syncleus.dann.graph;
 
-import com.syncleus.dann.graph.Edge;
-
-public interface SignalingContextEdge<N, S> extends Edge<N>
+public interface MutableWeightedEdge<N> extends WeightedEdge<N>, MutableWeighted
 {
-	void nodeStateChanged(N node, S newState);
-}
+	interface Endpoint<NN, EN extends NN> extends WeightedEdge.Endpoint<NN, EN>
+	{
+	};
+}
\ No newline at end of file
diff --git a/src/main/java/com/syncleus/dann/graph/MutableWeightedHyperEdge.java b/src/main/java/com/syncleus/dann/graph/MutableWeightedHyperEdge.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc4c552d11a8b1635091e84958572148269e329f
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/MutableWeightedHyperEdge.java
@@ -0,0 +1,26 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph;
+
+public interface MutableWeightedHyperEdge<N> extends MutableWeightedEdge<N>, WeightedHyperEdge<N>, MutableHyperEdge<N>
+{
+	interface Endpoint<NN, EN extends NN> extends MutableWeightedEdge.Endpoint<NN, EN>, WeightedHyperEdge.Endpoint<EN,NN>, MutableHyperEdge.Endpoint<NN, EN>
+	{
+	};
+}
\ No newline at end of file
diff --git a/src/main/java/com/syncleus/dann/graph/MutableWeightedMixableBidirectedEdge.java b/src/main/java/com/syncleus/dann/graph/MutableWeightedMixableBidirectedEdge.java
new file mode 100644
index 0000000000000000000000000000000000000000..67fc2720918c7ff992c02882784b893a1e221431
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/MutableWeightedMixableBidirectedEdge.java
@@ -0,0 +1,26 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph;
+
+public interface MutableWeightedMixableBidirectedEdge<N, LN extends N, RN extends N> extends MutableWeightedEdge<N>, WeightedMixableBidirectedEdge<LN,RN,N>, MutableMixableBidirectedEdge<N, LN,RN>
+{
+	interface Endpoint<NN, EN extends NN, ON extends NN> extends MutableWeightedEdge.Endpoint<NN, EN>, WeightedMixableBidirectedEdge.Endpoint<EN,ON,NN>, MutableMixableBidirectedEdge.Endpoint<NN, EN,ON>
+	{
+	};
+}
diff --git a/src/main/java/com/syncleus/dann/graph/MutableWeightedMixableDirectedEdge.java b/src/main/java/com/syncleus/dann/graph/MutableWeightedMixableDirectedEdge.java
new file mode 100644
index 0000000000000000000000000000000000000000..b29f65c86c6a3b1610b0227e4923ce96ff3e3f31
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/MutableWeightedMixableDirectedEdge.java
@@ -0,0 +1,26 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph;
+
+public interface MutableWeightedMixableDirectedEdge<N, SN extends N, DN extends N> extends MutableWeightedMixableBidirectedEdge<N, SN,DN>, WeightedMixableDirectedEdge<SN,DN,N>, MutableMixableDirectedEdge<N, SN,DN>
+{
+	interface Endpoint<NN, EN extends NN, ON extends NN> extends MutableWeightedMixableBidirectedEdge.Endpoint<NN, EN,ON>, WeightedMixableDirectedEdge.Endpoint<EN,ON,NN>, MutableMixableDirectedEdge.Endpoint<NN, EN,ON>
+	{
+	};
+}
diff --git a/src/main/java/com/syncleus/dann/graph/SimpleCycle.java b/src/main/java/com/syncleus/dann/graph/SimpleCycle.java
index 9e36f47fdd84617b5567c5f50a457f3df309f0fb..fe57535f372179b5b41914e6c7baf5877c7b15a6 100644
--- a/src/main/java/com/syncleus/dann/graph/SimpleCycle.java
+++ b/src/main/java/com/syncleus/dann/graph/SimpleCycle.java
@@ -46,14 +46,14 @@ public class SimpleCycle<N, E extends Edge<N>> extends SimpleWalk<N, E> implemen
 	private static <N, E extends Edge<N>> N startNodeFromSteps(final List<E> steps)
 	{
 		if( steps.size() == 1 )
-			return steps.get(0).getNodes().get(0);
+			return steps.get(0).getTargets().get(0);
 
-		final List<N> exclusiveFirstNodes = new ArrayList<N>(steps.get(0).getNodes());
-		exclusiveFirstNodes.removeAll(steps.get(1).getNodes());
+		final List<N> exclusiveFirstNodes = new ArrayList<N>(steps.get(0).getTargets());
+		exclusiveFirstNodes.removeAll(steps.get(1).getTargets());
 		if( exclusiveFirstNodes.size() == 1 )
 			return exclusiveFirstNodes.get(0);
 		else if( exclusiveFirstNodes.isEmpty() )
-			return steps.get(0).getNodes().get(0);
+			return steps.get(0).getTargets().get(0);
 		else
 			throw new IllegalArgumentException("steps does not form a path");
 	}
@@ -79,7 +79,7 @@ public class SimpleCycle<N, E extends Edge<N>> extends SimpleWalk<N, E> implemen
 			if( !(edgeStep instanceof BidirectedEdge) )
 				throw new IllegalArgumentException("all steps are not BidirectedEdge");
 			newNodeSteps.add(nextNodeStep);
-			final List<N> nextNodes = new ArrayList<N>(edgeStep.getNodes());
+			final List<N> nextNodes = new ArrayList<N>(edgeStep.getTargets());
 			nextNodes.remove(nextNodeStep);
 			nextNodeStep = nextNodes.get(0);
 		}
diff --git a/src/main/java/com/syncleus/dann/graph/SimpleDirectedEdge.java b/src/main/java/com/syncleus/dann/graph/SimpleDirectedEdge.java
new file mode 100644
index 0000000000000000000000000000000000000000..c06db8290ec9cf6e75c7c742548265bd987da8d9
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/SimpleDirectedEdge.java
@@ -0,0 +1,109 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph;
+
+public class SimpleDirectedEdge<N> extends AbstractDirectedEdge<N, N,N> implements MutableMixableDirectedEdge<N, N,N>
+{
+	private static final long serialVersionUID = 94357801283489L;
+
+	private final SimpleSourceEndpoint source;
+	private final SimpleDestinationEndpoint destination;
+
+	public SimpleDirectedEdge(final N source, final N destination)
+	{
+		super();
+		this.source = new SimpleSourceEndpoint(source);
+		this.destination = new SimpleDestinationEndpoint(destination);
+	}
+
+	public SimpleDirectedEdge(final N source, final N destination, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
+	{
+		super();
+		this.source = new SimpleSourceEndpoint(source);
+		this.destination = new SimpleDestinationEndpoint(destination);
+	}
+
+	@Override
+	public boolean isContextEnabled()
+	{
+		return false;
+	}
+
+	@Override
+	public AbstractSourceEndpoint getSourceEndPoint()
+	{
+		return this.source;
+	}
+
+	@Override
+	public AbstractDestinationEndpoint getDestinationEndPoint()
+	{
+		return this.destination;
+	}
+
+	@Override
+	protected SimpleDirectedEdge<N> clone()
+	{
+		return (SimpleDirectedEdge<N>) super.clone();
+	}
+
+	@Override
+	public void reassign(N newSourceNode, N newDestinationNode) throws InvalidEdgeException
+	{
+		return null;
+	}
+
+	@Override
+	public void invertDirection() throws InvalidEdgeDirectionException
+	{
+		return null;
+	}
+
+	@Override
+	public void reassign(N newLeftNode, MixableBidirectedEdge.Endpoint.Direction newLeftDirection, N newRightNode, MixableBidirectedEdge.Endpoint.Direction newRightDirection) throws InvalidEdgeException
+	{
+		return null;
+	}
+
+	private class SimpleSourceEndpoint extends AbstractSourceEndpoint implements MutableMixableDirectedEdge<N,N,N>.Endpoint
+	{
+		public SimpleSourceEndpoint()
+		{
+			super();
+		}
+
+		public SimpleSourceEndpoint(N node)
+		{
+			super(node);
+		}
+	};
+
+	private class SimpleDestinationEndpoint extends AbstractDestinationEndpoint implements MutableMixableDirectedEdge<N,N,N>.Endpoint
+	{
+		public SimpleDestinationEndpoint()
+		{
+			super();
+		}
+
+		public SimpleDestinationEndpoint(N node)
+		{
+			super(node);
+		}
+	};
+}
diff --git a/src/main/java/com/syncleus/dann/graph/SimpleHyperEdge.java b/src/main/java/com/syncleus/dann/graph/SimpleHyperEdge.java
new file mode 100644
index 0000000000000000000000000000000000000000..06a5d2f35c395c5a234dbcff4cd037e56fbec23e
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/SimpleHyperEdge.java
@@ -0,0 +1,165 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph;
+
+import java.util.*;
+
+public class SimpleHyperEdge<N> extends AbstractHyperEdge<N> implements MutableHyperEdge<N>
+{
+	private static final long serialVersionUID = -3657973823101515199L;
+	private final boolean contextEnabled;
+	private final Set<SimpleEndpoint> endPoints;
+
+	public SimpleHyperEdge()
+	{
+		this(false);
+	}
+
+	public SimpleHyperEdge(final Set<N> nodes)
+	{
+		this(nodes, false);
+	}
+
+	public SimpleHyperEdge(final N... nodes)
+	{
+		this(false, nodes);
+	}
+
+	public SimpleHyperEdge(final boolean contextEnabled)
+	{
+		super();
+		this.contextEnabled = contextEnabled;
+
+		this.endPoints = new HashSet<SimpleEndpoint>();
+	}
+
+	public SimpleHyperEdge(final Set<N> nodes, final boolean contextEnabled)
+	{
+		super();
+		this.contextEnabled = contextEnabled;
+
+		this.endPoints = new HashSet<SimpleEndpoint>(nodes.size());
+		for(N node : nodes)
+			this.endPoints.add(new SimpleEndpoint(node));
+	}
+
+	public SimpleHyperEdge(final boolean contextEnabled, final N... nodes)
+	{
+		super();
+		this.contextEnabled = contextEnabled;
+
+		this.endPoints = new HashSet<SimpleEndpoint>(nodes.length);
+		for(N node : nodes)
+			this.endPoints.add(new SimpleEndpoint(node));
+	}
+
+	@Override
+	public boolean isContextEnabled()
+	{
+		return false;
+	}
+
+/*
+	@Override
+	public SimpleHyperEdge<N> join(final N node)
+	{
+		return (SimpleHyperEdge<N>) super.join(node);
+	}
+
+	@Override
+	public SimpleHyperEdge<N> join(final List<N> nodes)
+	{
+		return (SimpleHyperEdge<N>) super.join(nodes);
+	}
+*/
+
+	@Override
+	protected SimpleHyperEdge<N> clone()
+	{
+		return (SimpleHyperEdge<N>) super.clone();
+	}
+
+	@Override
+	public MutableHyperEdge.Endpoint<N, N> join(N node) throws InvalidEdgeException
+	{
+	}
+
+	@Override
+	public Map<N, MutableHyperEdge.Endpoint<N, N>> join(Set<N> nodes) throws InvalidEdgeException
+	{
+	}
+
+	@Override
+	public void leave(MutableHyperEdge.Endpoint<N, N> nnEndPoint) throws InvalidEdgeException
+	{
+	}
+
+	@Override
+	public void leave(Set<MutableHyperEdge.Endpoint<N, N>> endPoint) throws InvalidEdgeException
+	{
+	}
+
+	@Override
+	public Map<N, MutableHyperEdge.Endpoint<N, N>> reconfigure(Set<N> connectNodes, Set<MutableHyperEdge.Endpoint<N, N>> disconnectEndPoints) throws InvalidEdgeException
+	{
+	}
+
+	@Override
+	public Set<Endpoint<N, N>> getEndPoints()
+	{
+	}
+
+	private class SimpleEndpoint extends AbstractEndpoint<N,N> implements MutableHyperEdge.Endpoint<N, N>
+	{
+		public SimpleEndpoint()
+		{
+			super();
+		}
+
+		public SimpleEndpoint(N node)
+		{
+			super(node);
+		}
+
+		@Override
+		public Set getTraversableNeighborsTo()
+		{
+		}
+
+		@Override
+		public Set getTraversableNeighborsFrom()
+		{
+		}
+
+		@Override
+		public boolean isTraversable()
+		{
+		}
+
+		@Override
+		public boolean isTraversable(Endpoint destination)
+		{
+		}
+
+		@Override
+		public boolean isTraversable(Object destination)
+		{
+		}
+	};
+}
diff --git a/src/main/java/com/syncleus/dann/graph/SimplePath.java b/src/main/java/com/syncleus/dann/graph/SimplePath.java
index 723ecde8eafb44474b849c8e98541d372deaf44b..8f9b9841289033194054802b32d7d6bbbc07c632 100644
--- a/src/main/java/com/syncleus/dann/graph/SimplePath.java
+++ b/src/main/java/com/syncleus/dann/graph/SimplePath.java
@@ -36,9 +36,9 @@ public class SimplePath<N, E extends Edge<N>> extends SimpleWalk<N, E> implement
 			throw new IllegalArgumentException("ourFirstNode can not be null");
 		if( ourLastNode == null )
 			throw new IllegalArgumentException("ourLastNode can not be null");
-		if( !ourSteps.get(0).getNodes().contains(ourFirstNode) )
+		if( !ourSteps.get(0).getTargets().contains(ourFirstNode) )
 			throw new IllegalArgumentException("ourFirstNode is not a end point in the first ourNodeSteps");
-		if( !ourSteps.get(ourSteps.size() - 1).getNodes().contains(ourLastNode) )
+		if( !ourSteps.get(ourSteps.size() - 1).getTargets().contains(ourLastNode) )
 			throw new IllegalArgumentException("ourLastNode is not a end point in the last ourNodeSteps");
 
 		this.firstNode = ourFirstNode;
@@ -70,7 +70,7 @@ public class SimplePath<N, E extends Edge<N>> extends SimpleWalk<N, E> implement
 
 			newNodeSteps.add(nextNodeStep);
 
-			final List<N> nextNodes = new ArrayList<N>(edgeStep.getNodes());
+			final List<N> nextNodes = new ArrayList<N>(edgeStep.getTargets());
 			nextNodes.remove(nextNodeStep);
 			nextNodeStep = nextNodes.get(0);
 		}
diff --git a/src/main/java/com/syncleus/dann/graph/ImmutableUndirectedEdge.java b/src/main/java/com/syncleus/dann/graph/SimpleUndirectedEdge.java
similarity index 70%
rename from src/main/java/com/syncleus/dann/graph/ImmutableUndirectedEdge.java
rename to src/main/java/com/syncleus/dann/graph/SimpleUndirectedEdge.java
index 7f23e46d419f8743f1ecd2641a33ebc056dde59a..9e81b8bd4da800641a0d2da37797aa6e336f0e21 100644
--- a/src/main/java/com/syncleus/dann/graph/ImmutableUndirectedEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/SimpleUndirectedEdge.java
@@ -18,37 +18,23 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.List;
-
-public final class ImmutableUndirectedEdge<N> extends AbstractUndirectedEdge<N>
+public final class SimpleUndirectedEdge<N> extends AbstractUndirectedEdge<N, N,N>
 {
 	private static final long serialVersionUID = -1803274027851230L;
 
-	public ImmutableUndirectedEdge(final N leftNode, final N rightNode)
+	public SimpleUndirectedEdge(final N leftNode, final N rightNode)
 	{
 		super(leftNode, rightNode);
 	}
 
-	public ImmutableUndirectedEdge(final N leftNode, final N rightNode, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
+	public SimpleUndirectedEdge(final N leftNode, final N rightNode, final boolean allowJoiningMultipleGraphs, final boolean contextEnabled)
 	{
 		super(leftNode, rightNode, allowJoiningMultipleGraphs, contextEnabled);
 	}
 
 	@Override
-	public ImmutableUndirectedEdge<N> disconnect(final N node)
-	{
-		return (ImmutableUndirectedEdge<N>) super.disconnect(node);
-	}
-
-	@Override
-	public ImmutableUndirectedEdge<N> disconnect(final List<N> nodes)
-	{
-		return (ImmutableUndirectedEdge<N>) super.disconnect(nodes);
-	}
-
-	@Override
-	public ImmutableUndirectedEdge<N> clone()
+	protected SimpleUndirectedEdge<N> clone()
 	{
-		return (ImmutableUndirectedEdge<N>) super.clone();
+		return (SimpleUndirectedEdge<N>) super.clone();
 	}
 }
diff --git a/src/main/java/com/syncleus/dann/graph/SimpleWeightedDirectedEdge.java b/src/main/java/com/syncleus/dann/graph/SimpleWeightedDirectedEdge.java
index a40d955603407ded83c6453abd9d022d08b77d79..2c7116eec5202fbc0ae27572e267668a5c9f71a3 100644
--- a/src/main/java/com/syncleus/dann/graph/SimpleWeightedDirectedEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/SimpleWeightedDirectedEdge.java
@@ -18,9 +18,7 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.List;
-
-public final class SimpleWeightedDirectedEdge<N> extends AbstractDirectedEdge<N> implements WeightedDirectedEdge<N>, MutableWeighted
+public final class SimpleWeightedDirectedEdge<N> extends AbstractDirectedEdge<N> implements MutableWeightedDirectedEdge<N>
 {
 	private static final long serialVersionUID = -6843921044147012645L;
 	private double weight;
@@ -50,19 +48,7 @@ public final class SimpleWeightedDirectedEdge<N> extends AbstractDirectedEdge<N>
 	}
 
 	@Override
-	public SimpleWeightedDirectedEdge<N> disconnect(final N node)
-	{
-		return (SimpleWeightedDirectedEdge<N>) super.disconnect(node);
-	}
-
-	@Override
-	public SimpleWeightedDirectedEdge<N> disconnect(final List<N> nodes)
-	{
-		return (SimpleWeightedDirectedEdge<N>) super.disconnect(nodes);
-	}
-
-	@Override
-	public SimpleWeightedDirectedEdge<N> clone()
+	protected SimpleWeightedDirectedEdge<N> clone()
 	{
 		return (SimpleWeightedDirectedEdge<N>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/SimpleWeightedHyperEdge.java b/src/main/java/com/syncleus/dann/graph/SimpleWeightedHyperEdge.java
index ba9d72ebe33abe4d10aa539c1a4689a174a12cbd..bc47b6063546006f074983b2d183d3c88f47d023 100644
--- a/src/main/java/com/syncleus/dann/graph/SimpleWeightedHyperEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/SimpleWeightedHyperEdge.java
@@ -20,7 +20,7 @@ package com.syncleus.dann.graph;
 
 import java.util.List;
 
-public final class SimpleWeightedHyperEdge<N> extends AbstractHyperEdge<N> implements WeightedEdge<N>, MutableWeighted
+public final class SimpleWeightedHyperEdge<N> extends AbstractHyperEdge<N> implements MutableWeightedHyperEdge<N>
 {
 	private static final long serialVersionUID = 2622882478754498808L;
 	private double weight;
@@ -50,19 +50,7 @@ public final class SimpleWeightedHyperEdge<N> extends AbstractHyperEdge<N> imple
 	}
 
 	@Override
-	public SimpleWeightedHyperEdge<N> disconnect(final N node)
-	{
-		return (SimpleWeightedHyperEdge<N>) super.disconnect(node);
-	}
-
-	@Override
-	public SimpleWeightedHyperEdge<N> disconnect(final List<N> nodes)
-	{
-		return (SimpleWeightedHyperEdge<N>) super.disconnect(nodes);
-	}
-
-	@Override
-	public SimpleWeightedHyperEdge<N> clone()
+	protected SimpleWeightedHyperEdge<N> clone()
 	{
 		return (SimpleWeightedHyperEdge<N>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/SimpleWeightedUndirectedEdge.java b/src/main/java/com/syncleus/dann/graph/SimpleWeightedUndirectedEdge.java
index d80afff788cf15b380a89e189f84fed4e7132ce3..fd475502615576e778370344778a30f8c1f752f3 100644
--- a/src/main/java/com/syncleus/dann/graph/SimpleWeightedUndirectedEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/SimpleWeightedUndirectedEdge.java
@@ -18,9 +18,7 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.List;
-
-public final class SimpleWeightedUndirectedEdge<N> extends AbstractUndirectedEdge<N> implements WeightedBidirectedEdge<N>, MutableWeighted
+public final class SimpleWeightedUndirectedEdge<N> extends AbstractUndirectedEdge<N> implements MutableWeightedBidirectedEdge<N>
 {
 	private static final long serialVersionUID = 4622255810663472765L;
 	private double weight;
@@ -50,19 +48,7 @@ public final class SimpleWeightedUndirectedEdge<N> extends AbstractUndirectedEdg
 	}
 
 	@Override
-	public SimpleWeightedUndirectedEdge<N> disconnect(final N node)
-	{
-		return (SimpleWeightedUndirectedEdge<N>) super.disconnect(node);
-	}
-
-	@Override
-	public SimpleWeightedUndirectedEdge<N> disconnect(final List<N> nodes)
-	{
-		return (SimpleWeightedUndirectedEdge<N>) super.disconnect(nodes);
-	}
-
-	@Override
-	public SimpleWeightedUndirectedEdge<N> clone()
+	protected SimpleWeightedUndirectedEdge<N> clone()
 	{
 		return (SimpleWeightedUndirectedEdge<N>) super.clone();
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/WeightedBidirectedEdge.java b/src/main/java/com/syncleus/dann/graph/WeightedBidirectedEdge.java
index 43c56ee81474dcbc5e95468a70bd1b4fa1b89c00..76733255d134dee73c06e419f98faffdf1e59783 100644
--- a/src/main/java/com/syncleus/dann/graph/WeightedBidirectedEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/WeightedBidirectedEdge.java
@@ -18,14 +18,9 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.List;
-
-public interface WeightedBidirectedEdge<N> extends BidirectedEdge<N>, Weighted
+public interface WeightedBidirectedEdge<N> extends BidirectedEdge<N>, WeightedMixableBidirectedEdge<N,N,N>
 {
-	@Override
-	WeightedBidirectedEdge<N> disconnect(N node);
-	@Override
-	WeightedBidirectedEdge<N> disconnect(List<N> node);
-	@Override
-	WeightedBidirectedEdge<N> clone();
+	interface Endpoint<NN, EN extends NN, ON extends NN> extends BidirectedEdge.Endpoint<NN, EN,ON>, WeightedMixableBidirectedEdge.Endpoint<EN,ON,NN>
+	{
+	};
 }
diff --git a/src/main/java/com/syncleus/dann/graph/WeightedDirectedEdge.java b/src/main/java/com/syncleus/dann/graph/WeightedDirectedEdge.java
index fb5678d572eac220ab84fac0f264dc8fbb6a662a..22f24a129738d3066ed5022f121f6b049a96a0b3 100644
--- a/src/main/java/com/syncleus/dann/graph/WeightedDirectedEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/WeightedDirectedEdge.java
@@ -18,14 +18,9 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.List;
-
-public interface WeightedDirectedEdge<N> extends DirectedEdge<N>, Weighted
+public interface WeightedDirectedEdge<N> extends WeightedBidirectedEdge<N>, DirectedEdge<N>, WeightedMixableDirectedEdge<N,N,N>
 {
-	@Override
-	WeightedDirectedEdge<N> disconnect(N node);
-	@Override
-	WeightedDirectedEdge<N> disconnect(List<N> node);
-	@Override
-	WeightedDirectedEdge<N> clone();
+	interface Endpoint<NN, EN extends NN, ON extends NN> extends WeightedBidirectedEdge.Endpoint<NN, EN,ON>, DirectedEdge.Endpoint<NN, EN,ON>, WeightedMixableDirectedEdge.Endpoint<EN,ON,NN>
+	{
+	};
 }
diff --git a/src/main/java/com/syncleus/dann/graph/WeightedEdge.java b/src/main/java/com/syncleus/dann/graph/WeightedEdge.java
index 2ac0ed82000e86359135981940a3cedc98a5ac85..6278ad67a6bc29d9149073b1f4f4a8b2e9c30454 100644
--- a/src/main/java/com/syncleus/dann/graph/WeightedEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/WeightedEdge.java
@@ -18,14 +18,9 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.List;
-
 public interface WeightedEdge<N> extends Edge<N>, Weighted
 {
-	@Override
-	WeightedEdge<N> disconnect(N node);
-	@Override
-	WeightedEdge<N> disconnect(List<N> node);
-	@Override
-	WeightedEdge<N> clone();
+	interface Endpoint<NN, EN extends NN> extends Edge.Endpoint<NN, EN>
+	{
+	};
 }
diff --git a/src/main/java/com/syncleus/dann/graph/WeightedHyperEdge.java b/src/main/java/com/syncleus/dann/graph/WeightedHyperEdge.java
index c242e4ee8580af9c8171f2310d534714664a3c23..e1ec3585ccde874f68081070797b9b07e6dc4072 100644
--- a/src/main/java/com/syncleus/dann/graph/WeightedHyperEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/WeightedHyperEdge.java
@@ -18,14 +18,9 @@
  ******************************************************************************/
 package com.syncleus.dann.graph;
 
-import java.util.List;
-
-public interface WeightedHyperEdge<N> extends HyperEdge<N>, Weighted
+public interface WeightedHyperEdge<N> extends WeightedEdge<N>, HyperEdge<N>
 {
-	@Override
-	WeightedHyperEdge<N> disconnect(N node);
-	@Override
-	WeightedHyperEdge<N> disconnect(List<N> node);
-	@Override
-	WeightedHyperEdge<N> clone();
+	interface Endpoint<EN extends NN, NN> extends WeightedEdge.Endpoint<NN, EN>, HyperEdge.Endpoint<NN, EN>
+	{
+	};
 }
diff --git a/src/main/java/com/syncleus/dann/graph/context/ContextEdge.java b/src/main/java/com/syncleus/dann/graph/WeightedMixableBidirectedEdge.java
similarity index 82%
rename from src/main/java/com/syncleus/dann/graph/context/ContextEdge.java
rename to src/main/java/com/syncleus/dann/graph/WeightedMixableBidirectedEdge.java
index c038d6f6f03be61f4f02c5de16c6894c61e6509c..c06a9e7888e511d6454863ad511288f97c31c631 100644
--- a/src/main/java/com/syncleus/dann/graph/context/ContextEdge.java
+++ b/src/main/java/com/syncleus/dann/graph/WeightedMixableBidirectedEdge.java
@@ -16,13 +16,11 @@
  *  Philadelphia, PA 19148                                                     *
  *                                                                             *
  ******************************************************************************/
-package com.syncleus.dann.graph.context;
+package com.syncleus.dann.graph;
 
-import com.syncleus.dann.graph.Edge;
-import com.syncleus.dann.graph.Graph;
-
-public interface ContextEdge<N, E extends Edge<N>, G extends Graph<N, E>> extends Edge<N>
+public interface WeightedMixableBidirectedEdge<LN extends N, RN extends N, N> extends MixableBidirectedEdge<N, LN,RN>, WeightedEdge<N>
 {
-	void nodeJoiningGraph(G graph, N node);
-	void nodeLeavingGraph(G graph, N node);
+	interface Endpoint<EN extends NN, ON extends NN, NN> extends MixableBidirectedEdge.Endpoint<NN, EN,ON>, WeightedEdge.Endpoint<NN, EN>
+	{
+	};
 }
diff --git a/src/main/java/com/syncleus/dann/graph/WeightedMixableDirectedEdge.java b/src/main/java/com/syncleus/dann/graph/WeightedMixableDirectedEdge.java
new file mode 100644
index 0000000000000000000000000000000000000000..897739fabbba228bccd388d1ce9631533778987a
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/WeightedMixableDirectedEdge.java
@@ -0,0 +1,26 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph;
+
+public interface WeightedMixableDirectedEdge<SN extends N, DN extends N, N> extends  MixableDirectedEdge<N, SN,DN>, WeightedMixableBidirectedEdge<SN,DN,N>
+{
+	interface Endpoint<EN extends NN, ON extends NN, NN> extends MixableDirectedEdge.Endpoint<NN, EN,ON>, WeightedMixableBidirectedEdge.Endpoint<EN,ON,NN>
+	{
+	};
+}
diff --git a/src/main/java/com/syncleus/dann/graph/context/AbstractContextGraphElement.java b/src/main/java/com/syncleus/dann/graph/context/AbstractContextGraphElement.java
index 150fe41cb37afb5948dbb3a26b7a41aa06d598d0..452de7794cad8b1ba7a3bd816fa4915e1b178dd2 100644
--- a/src/main/java/com/syncleus/dann/graph/context/AbstractContextGraphElement.java
+++ b/src/main/java/com/syncleus/dann/graph/context/AbstractContextGraphElement.java
@@ -34,45 +34,62 @@ public abstract class AbstractContextGraphElement<G extends Graph<?, ?>> impleme
 		this.allowJoiningMultipleGraphs = allowJoiningMultipleGraphs;
 	}
 
-	@Override
-	public boolean isGraphMember()
+	protected boolean isGraphMember()
 	{
 		return (!this.joinedGraphs.isEmpty());
 	}
 
-	@Override
-	public Set<G> getJoinedGraphs()
+	protected Set<G> getJoinedGraphs()
 	{
 		return Collections.unmodifiableSet(this.joinedGraphs);
 	}
 
-	@Override
-	public boolean joiningGraph(final G graph)
+	public void changingJoinedGraphs(Set<G> joiningGraphs, Set<G> leavingGraphs) throws RejectedContextException
 	{
-		if( graph == null )
-			throw new IllegalArgumentException("graph can not be null");
+		if( ((joiningGraphs == null)||(joiningGraphs.isEmpty())) && ((leavingGraphs == null)||(leavingGraphs.isEmpty())) )
+			throw new IllegalArgumentException("No graphs specified for joining or leaving!");
 
-		if( !this.allowJoiningMultipleGraphs && !joinedGraphs.isEmpty() )
-			return false;
+		if( (joiningGraphs != null) && (!joiningGraphs.isEmpty()) )
+		{
+			if( joiningGraphs.contains(null) )
+				throw new IllegalArgumentException("joiningGraphs can not have a null element!");
 
-		this.joinedGraphs.add(graph);
-		return true;
+			if( !this.allowJoiningMultipleGraphs && ((!this.joinedGraphs.isEmpty()) || (joiningGraphs.size() - leavingGraphs.size() > 1) ) )
+				throw new RejectedContextException("Can not join multiple graphs at the same time!");
+		}
+		if( (leavingGraphs != null) && (!leavingGraphs.isEmpty()) )
+		{
+			if( leavingGraphs.contains(null) )
+				throw new IllegalArgumentException("leavingGraphs can not have a null element!");
+
+			if( !this.joinedGraphs.containsAll(leavingGraphs) )
+				throw new IllegalArgumentException("One of the graphs being left has not been joined");
+		}
 	}
 
-	@Override
-	public boolean leavingGraph(final G graph)
+	public void changedJoinedGraphs(Set<G> newJoinedGraphs, Set<G> newLeftGraphs)
 	{
-		if( graph == null )
-			throw new IllegalArgumentException("graph can not be null");
-		if( !this.joinedGraphs.contains(graph) )
-			throw new IllegalArgumentException("graph was never joined");
+		if( ((newJoinedGraphs == null)||(newJoinedGraphs.isEmpty())) && ((newLeftGraphs == null)||(newLeftGraphs.isEmpty())) )
+			throw new IllegalArgumentException("No graphs specified for joining or leaving!");
+
+		if( (newJoinedGraphs != null) && (!newJoinedGraphs.isEmpty()) )
+		{
+			if( newJoinedGraphs.contains(null) )
+				throw new IllegalArgumentException("newJoinedGraphs can not have a null element!");
+
+			this.joinedGraphs.addAll(newJoinedGraphs);
+		}
+
+		if( (newLeftGraphs != null) && (!newLeftGraphs.isEmpty()) )
+		{
+			if( newLeftGraphs.contains(null) )
+				throw new IllegalArgumentException("newLeftGraphs can not have a null element!");
 
-		this.joinedGraphs.remove(graph);
-		return true;
+			this.joinedGraphs.removeAll(newLeftGraphs);
+		}
 	}
 
-	@Override
-	public boolean isAllowingMultipleGraphs()
+	protected boolean isAllowingMultipleGraphs()
 	{
 		return allowJoiningMultipleGraphs;
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/context/AbstractContextNode.java b/src/main/java/com/syncleus/dann/graph/context/AbstractContextNode.java
index 5319ca7c0aa7d52aeb53d5e0bacce161f91f4798..8d5ed4f3854a602f5fcfb726cb772796e9084621 100644
--- a/src/main/java/com/syncleus/dann/graph/context/AbstractContextNode.java
+++ b/src/main/java/com/syncleus/dann/graph/context/AbstractContextNode.java
@@ -27,65 +27,55 @@ import com.syncleus.dann.graph.Graph;
 public abstract class AbstractContextNode<N, E extends Edge<N>, G extends Graph<N, E>> extends AbstractContextGraphElement<G> implements ContextNode<N, E>
 {
 	private final Set<E> connectedEdges = new HashSet<E>();
-	private final Set<ContextEdge> contextEdges = new HashSet<ContextEdge>();
 
 	protected AbstractContextNode(final boolean allowJoiningMultipleGraphs)
 	{
 		super(allowJoiningMultipleGraphs);
 	}
 
-	@Override
-	public boolean joiningGraph(final G graph)
+	public void changingConnectedEdges(Set<E> connectingEdges, Set<E> disconnectingEdges) throws RejectedContextException
 	{
-		if(super.joiningGraph(graph))
+		if( ((connectingEdges == null)||(connectingEdges.isEmpty())) && ((disconnectingEdges == null)||(disconnectingEdges.isEmpty())) )
+			throw new IllegalArgumentException("No edges specified for joining or leaving!");
+
+		if( (connectingEdges != null) && (!connectingEdges.isEmpty()) )
 		{
-			//notify all context edges that this node has joined a graph
-			for(ContextEdge contextEdge : this.contextEdges)
-				contextEdge.nodeJoiningGraph(graph, this);
-			return true;
+			if( connectingEdges.contains(null) )
+				throw new IllegalArgumentException("connectingEdges can not have a null element!");
 		}
-		else return false;
-	}
-
-	@Override
-	public boolean leavingGraph(final G graph)
-	{
-		if( super.leavingGraph(graph) )
+		if( (disconnectingEdges != null) && (!disconnectingEdges.isEmpty()) )
 		{
-			//notify all context edges that this node is leaving a graph
-			for(ContextEdge contextEdge : this.contextEdges)
-				contextEdge.nodeLeavingGraph(graph, this);
-			return true;
+			if( disconnectingEdges.contains(null) )
+				throw new IllegalArgumentException("disconnectingEdges can not have a null element!");
+
+			if( !this.connectedEdges.containsAll(disconnectingEdges) )
+				throw new IllegalArgumentException("One of the graphs being left has not been joined");
 		}
-		else
-			return false;
 	}
 
-	@Override
-	public boolean connectingEdge(final E edge)
+	public void changedConnectedEdges(Set<E> newConnectedEdges, Set<E> newDisconnectedEdges)
 	{
-		if( edge == null )
-			throw new IllegalArgumentException("edge can not be null");
+		if( ((newConnectedEdges == null)||(newConnectedEdges.isEmpty())) && ((newDisconnectedEdges == null)||(newDisconnectedEdges.isEmpty())) )
+			throw new IllegalArgumentException("No edges specified for joining or leaving!");
 
-		this.connectedEdges.add(edge);
-		if(edge instanceof ContextEdge)
-			this.contextEdges.add((ContextEdge)edge);
-		return true;
-	}
+		if( (newConnectedEdges != null) && (!newConnectedEdges.isEmpty()) )
+		{
+			if( newConnectedEdges.contains(null) )
+				throw new IllegalArgumentException("newConnectedEdges can not have a null element!");
 
-	@Override
-	public boolean disconnectingEdge(final E edge)
-	{
-		if( edge == null )
-			throw new IllegalArgumentException("edge can not be null");
+			this.connectedEdges.addAll(newConnectedEdges);
+		}
 
-		//remove all refrences to thsi edge
-		this.connectedEdges.remove(edge);
-		this.contextEdges.remove(edge);
-		return true;
+		if( (newDisconnectedEdges != null) && (!newDisconnectedEdges.isEmpty()) )
+		{
+			if( newDisconnectedEdges.contains(null) )
+				throw new IllegalArgumentException("newDisconnectedEdges can not have a null element!");
+
+			this.connectedEdges.removeAll(newDisconnectedEdges);
+		}
 	}
 
-	public final Set<E> getConnectedEdges()
+	protected final Set<E> getConnectedEdges()
 	{
 		return Collections.unmodifiableSet(connectedEdges);
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/context/AbstractSignalContextNode.java b/src/main/java/com/syncleus/dann/graph/context/AbstractSignalContextNode.java
deleted file mode 100644
index 4e7084e1ac3165aadb531fbd3f7b88fe7ba94b32..0000000000000000000000000000000000000000
--- a/src/main/java/com/syncleus/dann/graph/context/AbstractSignalContextNode.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/******************************************************************************
- *                                                                             *
- *  Copyright: (c) Syncleus, Inc.                                              *
- *                                                                             *
- *  You may redistribute and modify this source code under the terms and       *
- *  conditions of the Open Source Community License - Type C version 1.0       *
- *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
- *  There should be a copy of the license included with this file. If a copy   *
- *  of the license is not included you are granted no right to distribute or   *
- *  otherwise use this file except through a legal and valid license. You      *
- *  should also contact Syncleus, Inc. at the information below if you cannot  *
- *  find a license:                                                            *
- *                                                                             *
- *  Syncleus, Inc.                                                             *
- *  2604 South 12th Street                                                     *
- *  Philadelphia, PA 19148                                                     *
- *                                                                             *
- ******************************************************************************/
-package com.syncleus.dann.graph.context;
-
-import java.util.HashSet;
-import java.util.Set;
-import com.syncleus.dann.graph.Edge;
-import com.syncleus.dann.graph.Graph;
-
-public abstract class AbstractSignalContextNode<N, E extends Edge<N>, S> extends AbstractContextNode<N, E, Graph<N, E>> implements SignalContextNode<N, E, S>
-{
-	private final Set<SignalingContextEdge<N, S>> contextEdges = new HashSet<SignalingContextEdge<N, S>>();
-	private transient S state = null;
-
-	protected AbstractSignalContextNode(final boolean allowJoiningMultipleGraphs)
-	{
-		super(allowJoiningMultipleGraphs);
-	}
-
-	protected AbstractSignalContextNode()
-	{
-		super(true);
-	}
-
-	@Override
-	public boolean connectingEdge(final E edge)
-	{
-		if( super.connectingEdge(edge) )
-		{
-			if(edge instanceof SignalingContextEdge)
-				this.contextEdges.add((SignalingContextEdge)edge);
-			return true;
-		}
-		else
-			return false;
-	}
-
-	@Override
-	public boolean disconnectingEdge(final E edge)
-	{
-		if( super.disconnectingEdge(edge) )
-		{
-			if(edge instanceof SignalingContextEdge)
-				this.contextEdges.remove(edge);
-			return true;
-		}
-		else
-			return false;
-	}
-
-	@Override
-	public S getState()
-	{
-		return this.state;
-	}
-
-	protected void setState(final S state)
-	{
-		this.state = state;
-
-		//lets notify all edges
-		for(SignalingContextEdge edge : this.contextEdges)
-		{
-			if( edge.isTraversable(this) )
-				edge.nodeStateChanged(this, state);
-		}
-	}
-}
diff --git a/src/main/java/com/syncleus/dann/graph/context/ContextGraphElement.java b/src/main/java/com/syncleus/dann/graph/context/ContextGraphElement.java
index 01c2e1b08c005106bf1a76b6b63616db9b74a02d..0d66b33938355890b56be38bcfa80b0b2d6517d3 100644
--- a/src/main/java/com/syncleus/dann/graph/context/ContextGraphElement.java
+++ b/src/main/java/com/syncleus/dann/graph/context/ContextGraphElement.java
@@ -23,9 +23,6 @@ import com.syncleus.dann.graph.Graph;
 
 public interface ContextGraphElement<G extends Graph<?, ?>>
 {
-	boolean isAllowingMultipleGraphs();
-	boolean joiningGraph(G graph);
-	boolean leavingGraph(G graph);
-	boolean isGraphMember();
-	Set<G> getJoinedGraphs();
+	void changingJoinedGraphs(Set<G> joiningGraphs, Set<G> leavingGraphs) throws RejectedContextException;
+	void changedJoinedGraphs(Set<G> joinedGraphs, Set<G> leftGraphs);
 }
diff --git a/src/main/java/com/syncleus/dann/graph/context/ContextNode.java b/src/main/java/com/syncleus/dann/graph/context/ContextNode.java
index e3a814f8a670500d73e9232496184fd5009906f4..65c4e6dba1d7dbfca18312fe97d94147ea3607fe 100644
--- a/src/main/java/com/syncleus/dann/graph/context/ContextNode.java
+++ b/src/main/java/com/syncleus/dann/graph/context/ContextNode.java
@@ -18,10 +18,11 @@
  ******************************************************************************/
 package com.syncleus.dann.graph.context;
 
+import java.util.Set;
 import com.syncleus.dann.graph.Edge;
 
 public interface ContextNode<N, E extends Edge<N>>
 {
-	boolean connectingEdge(E edge);
-	boolean disconnectingEdge(E edge);
+	void changingConnectedEdges(Set<E> connectingEdges, Set<E> disconnectingEdges) throws RejectedContextException;
+	void changedConnectedEdges(Set<E> connectedEdges, Set<E> disconnectedEdges);
 }
diff --git a/src/main/java/com/syncleus/dann/graph/context/InvalidContextException.java b/src/main/java/com/syncleus/dann/graph/context/InvalidContextException.java
new file mode 100644
index 0000000000000000000000000000000000000000..bbba5c74f3e5c1bb2d2faf1a614cf601de77c14b
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/context/InvalidContextException.java
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph.context;
+
+//This class is a runtime class to encapsulate the RejectedContextException. This allows the context to be optional
+//without having actions blocked by context events needing to explicitly handle exceptions (as you do with non-runtime
+//exceptions)
+public class InvalidContextException extends RuntimeException
+{
+	private static final long serialVersionUID = 1385401237548091754L;
+
+	public InvalidContextException(final String msg, final RejectedContextException cause)
+	{
+		super(msg, cause);
+	}
+
+	public InvalidContextException(final RejectedContextException cause)
+	{
+		super(cause);
+	}
+}
diff --git a/src/main/java/com/syncleus/dann/graph/context/RejectedContextException.java b/src/main/java/com/syncleus/dann/graph/context/RejectedContextException.java
new file mode 100644
index 0000000000000000000000000000000000000000..e43e93bc2e0be7bd741f2454108c0a5efca34d6b
--- /dev/null
+++ b/src/main/java/com/syncleus/dann/graph/context/RejectedContextException.java
@@ -0,0 +1,44 @@
+/******************************************************************************
+ *                                                                             *
+ *  Copyright: (c) Syncleus, Inc.                                              *
+ *                                                                             *
+ *  You may redistribute and modify this source code under the terms and       *
+ *  conditions of the Open Source Community License - Type C version 1.0       *
+ *  or any later version as published by Syncleus, Inc. at www.syncleus.com.   *
+ *  There should be a copy of the license included with this file. If a copy   *
+ *  of the license is not included you are granted no right to distribute or   *
+ *  otherwise use this file except through a legal and valid license. You      *
+ *  should also contact Syncleus, Inc. at the information below if you cannot  *
+ *  find a license:                                                            *
+ *                                                                             *
+ *  Syncleus, Inc.                                                             *
+ *  2604 South 12th Street                                                     *
+ *  Philadelphia, PA 19148                                                     *
+ *                                                                             *
+ ******************************************************************************/
+package com.syncleus.dann.graph.context;
+
+public class RejectedContextException extends Exception
+{
+	private static final long serialVersionUID = -2983740921347809174L;
+
+	public RejectedContextException()
+	{
+		super();
+	}
+
+	public RejectedContextException(final String msg)
+	{
+		super(msg);
+	}
+
+	public RejectedContextException(final String msg, final Throwable cause)
+	{
+		super(msg, cause);
+	}
+
+	public RejectedContextException(final Throwable cause)
+	{
+		super(cause);
+	}
+}
diff --git a/src/main/java/com/syncleus/dann/graph/cycle/ColoredDepthFirstSearchDetector.java b/src/main/java/com/syncleus/dann/graph/cycle/ColoredDepthFirstSearchDetector.java
index 086e3c9e5b46ffddc09c40e3b19b4907efe05ddc..79b7dfff2706027d9fa8bf68a162884fae5cbd38 100644
--- a/src/main/java/com/syncleus/dann/graph/cycle/ColoredDepthFirstSearchDetector.java
+++ b/src/main/java/com/syncleus/dann/graph/cycle/ColoredDepthFirstSearchDetector.java
@@ -37,7 +37,7 @@ public class ColoredDepthFirstSearchDetector implements CycleDetector
 
 		final Set<E> traversedEdges = new HashSet<E>();
 
-		for(final N node : graph.getNodes())
+		for(final N node : graph.getTargets())
 		{
 			if( !colorMap.containsKey(node)
 					&& visit(graph, colorMap, traversedEdges, node) )
@@ -51,13 +51,13 @@ public class ColoredDepthFirstSearchDetector implements CycleDetector
 	{
 		colorMap.put(node, Boolean.FALSE);
 
-		final Set<E> traversableEdges = graph.getTraversableEdges(node);
+		final Set<E> traversableEdges = graph.getTraversableAdjacentEdges(node);
 		for(final E neighborEdge : traversableEdges)
 		{
 			if( !ColoredDepthFirstSearchDetector.<E>traversed(traversedEdges, neighborEdge) )
 			{
 				traversedEdges.add(neighborEdge);
-				final List<N> neighborNodes = new ArrayList<N>(neighborEdge.getNodes());
+				final List<N> neighborNodes = new ArrayList<N>(neighborEdge.getTargets());
 				neighborNodes.remove(node);
 				for(final N neighborNode : neighborNodes)
 				{
diff --git a/src/main/java/com/syncleus/dann/graph/cycle/ExhaustiveDepthFirstSearchCycleFinder.java b/src/main/java/com/syncleus/dann/graph/cycle/ExhaustiveDepthFirstSearchCycleFinder.java
index bddcce41a8f9865338e7779b640429e14e652700..5b97db0b7505ceba4d0ae60d2e87b016a3ce6249 100644
--- a/src/main/java/com/syncleus/dann/graph/cycle/ExhaustiveDepthFirstSearchCycleFinder.java
+++ b/src/main/java/com/syncleus/dann/graph/cycle/ExhaustiveDepthFirstSearchCycleFinder.java
@@ -91,7 +91,7 @@ public class ExhaustiveDepthFirstSearchCycleFinder<N, E extends Edge<N>> extends
 
 	public Set<Cycle<N, E>> findCycles(final Graph<N, E> graph)
 	{
-		final Set<N> untouchedNodes = new HashSet<N>(graph.getNodes());
+		final Set<N> untouchedNodes = new HashSet<N>(graph.getTargets());
 		final Set<Cycle<N, E>> cycles = new HashSet<Cycle<N, E>>();
 		while( !untouchedNodes.isEmpty() )
 		{
@@ -112,7 +112,7 @@ public class ExhaustiveDepthFirstSearchCycleFinder<N, E extends Edge<N>> extends
 
 	private static <N, E extends Edge<N>> List<N> neighborsFromEdge(final E edge, final N sourceNode)
 	{
-		final List<N> destinations = new ArrayList<N>(edge.getNodes());
+		final List<N> destinations = new ArrayList<N>(edge.getTargets());
 		destinations.remove(sourceNode);
 		return destinations;
 	}
@@ -123,7 +123,7 @@ public class ExhaustiveDepthFirstSearchCycleFinder<N, E extends Edge<N>> extends
 		parentNodes.push(currentNode);
 		parentEdges.push(lastEdge);
 
-		final List<E> unexploredPaths = new ArrayList<E>(graph.getTraversableEdges(currentNode));
+		final List<E> unexploredPaths = new ArrayList<E>(graph.getTraversableAdjacentEdges(currentNode));
 		if( lastEdge != null )
 			unexploredPaths.remove(lastEdge);
 		int cyclesFound = 0;
diff --git a/src/main/java/com/syncleus/dann/graph/drawing/hyperassociativemap/HyperassociativeMap.java b/src/main/java/com/syncleus/dann/graph/drawing/hyperassociativemap/HyperassociativeMap.java
index 5048d015a8ef2b610dbd30a4cc4db2c3161d27ce..99e7405c9997bfff6b0f0f20a00c6b7e4e61349c 100644
--- a/src/main/java/com/syncleus/dann/graph/drawing/hyperassociativemap/HyperassociativeMap.java
+++ b/src/main/java/com/syncleus/dann/graph/drawing/hyperassociativemap/HyperassociativeMap.java
@@ -101,7 +101,7 @@ public class HyperassociativeMap<G extends Graph<N, ?>, N> implements GraphDrawe
 		this.useWeights = useWeights;
 
 		// refresh all nodes
-		for (final N node : this.graph.getNodes())
+		for (final N node : this.graph.getTargets())
 		{
 			this.coordinates.put(node, randomCoordinates(this.dimensions));
 		}
@@ -180,10 +180,10 @@ public class HyperassociativeMap<G extends Graph<N, ?>, N> implements GraphDrawe
 	public void align()
 	{
 		// refresh all nodes
-		if (!coordinates.keySet().equals(graph.getNodes()))
+		if (!coordinates.keySet().equals(graph.getTargets()))
 		{
 			final Map<N, Vector> newCoordinates = new HashMap<N, Vector>();
-			for (final N node : graph.getNodes())
+			for (final N node : graph.getTargets())
 			{
 				if (coordinates.containsKey(node))
 				{
@@ -229,7 +229,7 @@ public class HyperassociativeMap<G extends Graph<N, ?>, N> implements GraphDrawe
 		// points
 		for (int dimensionIndex = 1; dimensionIndex <= dimensions; dimensionIndex++)
 		{
-			center = center.setCoordinate(center.getCoordinate(dimensionIndex) / graph.getNodes().size(), dimensionIndex);
+			center = center.setCoordinate(center.getCoordinate(dimensionIndex) / graph.getTargets().size(), dimensionIndex);
 		}
 
 		recenterNodes(center);
@@ -249,7 +249,7 @@ public class HyperassociativeMap<G extends Graph<N, ?>, N> implements GraphDrawe
 
 	private void recenterNodes(final Vector center)
 	{
-		for (final N node : graph.getNodes())
+		for (final N node : graph.getTargets())
 		{
 			coordinates.put(node, coordinates.get(node).calculateRelativeTo(center));
 		}
@@ -266,7 +266,7 @@ public class HyperassociativeMap<G extends Graph<N, ?>, N> implements GraphDrawe
 		for (final Edge<N> neighborEdge : graph.getAdjacentEdges(nodeToQuery))
 		{
 			final Double currentWeight = (((neighborEdge instanceof Weighted) && useWeights) ? ((Weighted) neighborEdge).getWeight() : equilibriumDistance);
-			for (final N neighbor : neighborEdge.getNodes())
+			for (final N neighbor : neighborEdge.getTargets())
 			{
 				if (!neighbor.equals(nodeToQuery))
 				{
@@ -313,7 +313,7 @@ public class HyperassociativeMap<G extends Graph<N, ?>, N> implements GraphDrawe
 			compositeVector = compositeVector.add(neighborVector);
 		}
 		// calculate repulsion with all non-neighbors
-		for (final N node : graph.getNodes())
+		for (final N node : graph.getTargets())
 		{
 			if ((!neighbors.containsKey(node)) && (node != nodeToAlign)
 					&& (!graph.getAdjacentNodes(node).contains(nodeToAlign)))
@@ -396,7 +396,7 @@ public class HyperassociativeMap<G extends Graph<N, ?>, N> implements GraphDrawe
 	private List<Future<Vector>> submitFutureAligns()
 	{
 		final ArrayList<Future<Vector>> futures = new ArrayList<Future<Vector>>();
-		for (final N node : graph.getNodes())
+		for (final N node : graph.getTargets())
 		{
 			futures.add(threadExecutor.submit(new Align(node)));
 		}
@@ -406,7 +406,7 @@ public class HyperassociativeMap<G extends Graph<N, ?>, N> implements GraphDrawe
 	private Vector processLocally()
 	{
 		Vector pointSum = new Vector(dimensions);
-		for (final N node : graph.getNodes())
+		for (final N node : graph.getTargets())
 		{
 			final Vector newPoint = align(node);
 			for (int dimensionIndex = 1; dimensionIndex <= dimensions; dimensionIndex++)
diff --git a/src/main/java/com/syncleus/dann/graph/drawing/hyperassociativemap/LayeredBrainHyperassociativeMap.java b/src/main/java/com/syncleus/dann/graph/drawing/hyperassociativemap/LayeredBrainHyperassociativeMap.java
index 5e618a619055472b0a92b6cc7eeee11c34bfd5e9..b57db7421af03b38d6dfab25febd9eb2198cad3a 100644
--- a/src/main/java/com/syncleus/dann/graph/drawing/hyperassociativemap/LayeredBrainHyperassociativeMap.java
+++ b/src/main/java/com/syncleus/dann/graph/drawing/hyperassociativemap/LayeredBrainHyperassociativeMap.java
@@ -90,7 +90,7 @@ public class LayeredBrainHyperassociativeMap extends HyperassociativeMap<Feedfor
 		{
 			final Double currentWeight = (this.isUsingWeights() ? neighborEdge.getWeight() : this.getEquilibriumDistance());
 			//TODO fix this typing
-			for(final Object neighbor : neighborEdge.getNodes())
+			for(final Object neighbor : neighborEdge.getTargets())
 				if( !neighbor.equals(nodeToQuery) )
 					associations.put((BackpropNeuron)neighbor, currentWeight);
 		}
diff --git a/src/main/java/com/syncleus/dann/graph/drawing/hyperassociativemap/visualization/HyperassociativeMapVisualization.java b/src/main/java/com/syncleus/dann/graph/drawing/hyperassociativemap/visualization/HyperassociativeMapVisualization.java
index 9caded4cc126f8021aaa8edaa7273705092e3f54..00505a27f71f2e4ad60b0c29aca055e998df1752 100644
--- a/src/main/java/com/syncleus/dann/graph/drawing/hyperassociativemap/visualization/HyperassociativeMapVisualization.java
+++ b/src/main/java/com/syncleus/dann/graph/drawing/hyperassociativemap/visualization/HyperassociativeMapVisualization.java
@@ -90,7 +90,7 @@ public class HyperassociativeMapVisualization<D extends GraphDrawer<G, N>, G ext
 		boolean childrenRemoved = false;
 		final Map<N, TransformGroup> newGraphicalNodes = new HashMap<N, TransformGroup>();
 		final Map<N, Vector> coordinates = this.drawer.getCoordinates();
-		final Set<N> nodes = this.drawer.getGraph().getNodes();
+		final Set<N> nodes = this.drawer.getGraph().getTargets();
 		for(final N node : nodes)
 			if( this.nodeGraphics.containsKey(node) )
 			{
diff --git a/src/main/java/com/syncleus/dann/graph/search/optimization/HillClimbingLocalSearch.java b/src/main/java/com/syncleus/dann/graph/search/optimization/HillClimbingLocalSearch.java
index 2dc92b73ca3745fe0aabdbd2d1840c5eaa58c010..be69ae7170c3b9765fa355e35908766b509b3421 100644
--- a/src/main/java/com/syncleus/dann/graph/search/optimization/HillClimbingLocalSearch.java
+++ b/src/main/java/com/syncleus/dann/graph/search/optimization/HillClimbingLocalSearch.java
@@ -45,7 +45,7 @@ public class HillClimbingLocalSearch<G extends Graph<N, ?>, N extends Weighted>
 		do
 		{
 			N nextNode = null;
-			for(final N neighbor : graph.getTraversableNodes(currentNode))
+			for(final N neighbor : graph.getTraversableAdjacentNodes(currentNode))
 			{
 				if( (nextNode == null) || (neighbor.getWeight() > nextNode.getWeight()) )
 					nextNode = neighbor;
diff --git a/src/main/java/com/syncleus/dann/graph/search/pathfinding/AstarPathFinder.java b/src/main/java/com/syncleus/dann/graph/search/pathfinding/AstarPathFinder.java
index fa077314a180baf36a43c09f81813464a669ba6f..f16a70f7e8edf2500207e85aef98b68abad92d0a 100644
--- a/src/main/java/com/syncleus/dann/graph/search/pathfinding/AstarPathFinder.java
+++ b/src/main/java/com/syncleus/dann/graph/search/pathfinding/AstarPathFinder.java
@@ -31,106 +31,6 @@ import java.util.Set;
 
 public class AstarPathFinder<N, E extends Edge<N>> implements PathFinder<N, E>
 {
-	private final class PathedStep implements Comparable<PathedStep>
-	{
-		private final N node;
-		private final N goalNode;
-		private PathedStep parent;
-		private E parentEdge;
-		private double cachedPathWeight;
-
-		public PathedStep(final N node, final N goalNode)
-		{
-			if( node == null )
-				throw new IllegalArgumentException("node can not be null");
-			if( goalNode == null )
-				throw new IllegalArgumentException("goalNode can not be null");
-
-			this.goalNode = goalNode;
-			this.node = node;
-		}
-
-		private boolean updateParent(final PathedStep newParent, final E newParentEdge)
-		{
-			double newWeight = (newParentEdge instanceof Weighted ? ((Weighted) newParentEdge).getWeight() : 0.0);
-			if( this.node instanceof Weighted )
-				newWeight += ((Weighted) this.node).getWeight();
-			else
-				newWeight += 1.0;
-			if( (this.parent == null) || (newParent.cachedPathWeight + newWeight < this.cachedPathWeight) )
-			{
-				this.parent = newParent;
-				this.parentEdge = newParentEdge;
-				this.cachedPathWeight = newParent.cachedPathWeight + newWeight;
-				return true;
-			}
-			else
-				return false;
-		}
-
-		public N getNode()
-		{
-			return this.node;
-		}
-
-		public PathedStep getParent()
-		{
-			return this.parent;
-		}
-
-		public double getCachedPathWeight()
-		{
-			return this.cachedPathWeight;
-		}
-
-		public double getHeuristicCostToGoal()
-		{
-			return heuristicPathCost.getHeuristicPathCost(this.node, this.goalNode);
-		}
-
-		public double getHeuristicOverallCost()
-		{
-			return this.cachedPathWeight + this.getHeuristicCostToGoal();
-		}
-
-		@Override
-		public boolean equals(final Object compareToObj)
-		{
-			if( compareToObj == null )
-				return false;
-
-			if( !(compareToObj.getClass().isInstance(this)) )
-				return false;
-
-			final PathedStep compareTo = (PathedStep) compareToObj;
-			return ((this.node.equals(compareTo)) || (this.node.equals(compareTo.node)));
-		}
-
-		@Override
-		public int hashCode()
-		{
-			return this.node.hashCode();
-		}
-
-		@Override
-		public int compareTo(final PathedStep compareWith)
-		{
-			//the natural ordering is inverse cause the smallest path weight is
-			//the best weight.
-			if( this.getHeuristicOverallCost() < compareWith.getHeuristicOverallCost() )
-				return -1;
-			else if( this.getHeuristicOverallCost() > compareWith.getHeuristicOverallCost() )
-				return 1;
-			else
-				return 0;
-		}
-
-		public E getParentEdge()
-		{
-			return this.parentEdge;
-		}
-	}
-
 	private final Graph<N, E> graph;
 	private final HeuristicPathCost<N> heuristicPathCost;
 
@@ -178,9 +78,9 @@ public class AstarPathFinder<N, E extends Edge<N>> implements PathFinder<N, E>
 			if( currentStep.getNode().equals(end) )
 				return pathedStepToWalk(currentStep);
 
-			for(final E edge : this.graph.getTraversableEdges(currentStep.node))
+			for(final E edge : this.graph.getTraversableAdjacentEdgesTo(currentStep.node))
 			{
-				for(final N neighborNode : edge.getNodes())
+				for(final N neighborNode : edge.getTargets())
 				{
 					if( neighborNode.equals(currentStep.node) )
 						continue;
@@ -237,4 +137,104 @@ public class AstarPathFinder<N, E extends Edge<N>> implements PathFinder<N, E>
 
 		return edges;
 	}
+
+	private final class PathedStep implements Comparable<PathedStep>
+	{
+		private final N node;
+		private final N goalNode;
+		private PathedStep parent;
+		private E parentEdge;
+		private double cachedPathWeight;
+
+		public PathedStep(final N node, final N goalNode)
+		{
+			if( node == null )
+				throw new IllegalArgumentException("node can not be null");
+			if( goalNode == null )
+				throw new IllegalArgumentException("goalNode can not be null");
+
+			this.goalNode = goalNode;
+			this.node = node;
+		}
+
+		private boolean updateParent(final PathedStep newParent, final E newParentEdge)
+		{
+			double newWeight = (newParentEdge instanceof Weighted ? ((Weighted) newParentEdge).getWeight() : 0.0);
+			if( this.node instanceof Weighted )
+				newWeight += ((Weighted) this.node).getWeight();
+			else
+				newWeight += 1.0;
+			if( (this.parent == null) || (newParent.cachedPathWeight + newWeight < this.cachedPathWeight) )
+			{
+				this.parent = newParent;
+				this.parentEdge = newParentEdge;
+				this.cachedPathWeight = newParent.cachedPathWeight + newWeight;
+				return true;
+			}
+			else
+				return false;
+		}
+
+		public N getNode()
+		{
+			return this.node;
+		}
+
+		public PathedStep getParent()
+		{
+			return this.parent;
+		}
+
+		public double getCachedPathWeight()
+		{
+			return this.cachedPathWeight;
+		}
+
+		public double getHeuristicCostToGoal()
+		{
+			return heuristicPathCost.getHeuristicPathCost(this.node, this.goalNode);
+		}
+
+		public double getHeuristicOverallCost()
+		{
+			return this.cachedPathWeight + this.getHeuristicCostToGoal();
+		}
+
+		@Override
+		public boolean equals(final Object compareToObj)
+		{
+			if( compareToObj == null )
+				return false;
+
+			if( !(compareToObj.getClass().isInstance(this)) )
+				return false;
+
+			final PathedStep compareTo = (PathedStep) compareToObj;
+			return ((this.node.equals(compareTo)) || (this.node.equals(compareTo.node)));
+		}
+
+		@Override
+		public int hashCode()
+		{
+			return this.node.hashCode();
+		}
+
+		@Override
+		public int compareTo(final PathedStep compareWith)
+		{
+			//the natural ordering is inverse cause the smallest path weight is
+			//the best weight.
+			if( this.getHeuristicOverallCost() < compareWith.getHeuristicOverallCost() )
+				return -1;
+			else if( this.getHeuristicOverallCost() > compareWith.getHeuristicOverallCost() )
+				return 1;
+			else
+				return 0;
+		}
+
+		public E getParentEdge()
+		{
+			return this.parentEdge;
+		}
+	};
 }
diff --git a/src/main/java/com/syncleus/dann/graph/search/pathfinding/BellmanFordPathFinder.java b/src/main/java/com/syncleus/dann/graph/search/pathfinding/BellmanFordPathFinder.java
index 98f871420e4d92a6ea18729ee851ff39fced63aa..a9b4da050e640a9472e8ba55c5151f3288dcbd0b 100644
--- a/src/main/java/com/syncleus/dann/graph/search/pathfinding/BellmanFordPathFinder.java
+++ b/src/main/java/com/syncleus/dann/graph/search/pathfinding/BellmanFordPathFinder.java
@@ -58,7 +58,7 @@ public class BellmanFordPathFinder<N, E extends DirectedEdge<N>> implements Path
 
 	public void calculateSteps(final N begin)
 	{
-		final Set<? extends N> nodes = this.graph.getNodes();
+		final Set<? extends N> nodes = this.graph.getTargets();
 		final Set<? extends E> edges = this.graph.getEdges();
 		this.pathedSteps = new HashMap<N, PathedStep>(nodes.size());
 		//relax edges
diff --git a/src/main/java/com/syncleus/dann/graph/search/pathfinding/DijkstraPathFinder.java b/src/main/java/com/syncleus/dann/graph/search/pathfinding/DijkstraPathFinder.java
index 55727c622677c7f8b059561c160f03db94a60c95..fb01f04e151ebf0ec3613a0ff76fb7d38cbabaef 100644
--- a/src/main/java/com/syncleus/dann/graph/search/pathfinding/DijkstraPathFinder.java
+++ b/src/main/java/com/syncleus/dann/graph/search/pathfinding/DijkstraPathFinder.java
@@ -23,6 +23,11 @@ import com.syncleus.dann.graph.Graph;
 
 public class DijkstraPathFinder<N, E extends Edge<N>> extends AstarPathFinder<N, E>
 {
+	public DijkstraPathFinder(final Graph<N, E> graph)
+	{
+		super(graph, new ZeroHeuristicPathCost<N>());
+	}
+
 	public static final class ZeroHeuristicPathCost<N> implements HeuristicPathCost<N>
 	{
 		@Override
@@ -42,10 +47,5 @@ public class DijkstraPathFinder<N, E extends Edge<N>> extends AstarPathFinder<N,
 		{
 			return true;
 		}
-	}
-
-	public DijkstraPathFinder(final Graph<N, E> graph)
-	{
-		super(graph, new ZeroHeuristicPathCost<N>());
-	}
+	};
 }
diff --git a/src/main/java/com/syncleus/dann/graph/search/pathfinding/FloydWarshallPathFinder.java b/src/main/java/com/syncleus/dann/graph/search/pathfinding/FloydWarshallPathFinder.java
index 30fe24a27cc8c294e598ed3626b18346d4dc0504..34e1b72deca9314595632ccb7b4ef383147fd991 100644
--- a/src/main/java/com/syncleus/dann/graph/search/pathfinding/FloydWarshallPathFinder.java
+++ b/src/main/java/com/syncleus/dann/graph/search/pathfinding/FloydWarshallPathFinder.java
@@ -38,27 +38,27 @@ public class FloydWarshallPathFinder<N, E extends Edge<N>> implements PathFinder
 		this.graph = graph;
 
 		//initialize
-		this.walkWeight = new HashMap<N, Map<N, Double>>(this.graph.getNodes().size());
-		this.nextNode = new HashMap<N, Map<N, N>>(this.graph.getNodes().size());
-		for(final N nodeX : this.graph.getNodes())
+		this.walkWeight = new HashMap<N, Map<N, Double>>(this.graph.getTargets().size());
+		this.nextNode = new HashMap<N, Map<N, N>>(this.graph.getTargets().size());
+		for(final N nodeX : this.graph.getTargets())
 		{
-			final Map<N, Double> weightMapX = new HashMap<N, Double>(this.graph.getNodes().size());
+			final Map<N, Double> weightMapX = new HashMap<N, Double>(this.graph.getTargets().size());
 			this.walkWeight.put(nodeX, weightMapX);
 
-			final Map<N, N> nodeMapX = new HashMap<N, N>(this.graph.getNodes().size());
+			final Map<N, N> nodeMapX = new HashMap<N, N>(this.graph.getTargets().size());
 			this.nextNode.put(nodeX, nodeMapX);
 
-			for(final N nodeY : this.graph.getNodes())
+			for(final N nodeY : this.graph.getTargets())
 			{
 				double initialWeight = Double.POSITIVE_INFINITY;
 
 				if( nodeX.equals(nodeY) )
 					initialWeight = 0.0;
-				else if( this.graph.getTraversableNodes(nodeX).contains(nodeY) )
+				else if( this.graph.getTraversableAdjacentNodes(nodeX).contains(nodeY) )
 				{
 					E connectedEdge = null;
-					for(final E edge : this.graph.getTraversableEdges(nodeX))
-						if( edge.getNodes().contains(nodeY) )
+					for(final E edge : this.graph.getTraversableAdjacentEdges(nodeX))
+						if( edge.getTargets().contains(nodeY) )
 							connectedEdge = edge;
 					assert connectedEdge != null;
 					initialWeight = (connectedEdge instanceof WeightedEdge ? ((WeightedEdge) connectedEdge).getWeight() : 1.0);
@@ -76,9 +76,9 @@ public class FloydWarshallPathFinder<N, E extends Edge<N>> implements PathFinder
 
 	private void calculatePaths()
 	{
-		for(final N nodeK : this.graph.getNodes())
-			for(final N nodeX : this.graph.getNodes())
-				for(final N nodeY : this.graph.getNodes())
+		for(final N nodeK : this.graph.getTargets())
+			for(final N nodeX : this.graph.getTargets())
+				for(final N nodeY : this.graph.getTargets())
 				{
 					if( !Double.isInfinite(this.walkWeight.get(nodeX).get(nodeK))
 							&& !Double.isInfinite(this.walkWeight.get(nodeK).get(nodeY))
@@ -105,9 +105,9 @@ public class FloydWarshallPathFinder<N, E extends Edge<N>> implements PathFinder
 			final N toNode = nodePath.get(nodeIndex + 1);
 			E stepEdge = null;
 			double stepEdgeWeight = Double.MAX_VALUE;
-			for(final E edge : this.graph.getTraversableEdges(fromNode))
+			for(final E edge : this.graph.getTraversableAdjacentEdges(fromNode))
 			{
-				if( edge.getNodes().contains(toNode) )
+				if( edge.getTargets().contains(toNode) )
 				{
 					if( stepEdge == null )
 						stepEdge = edge;
diff --git a/src/main/java/com/syncleus/dann/graph/search/pathfinding/JohnsonGraphTransformer.java b/src/main/java/com/syncleus/dann/graph/search/pathfinding/JohnsonGraphTransformer.java
index c1506e1523067b2693165c616a2cb16c4d9e2ac2..4473ad444ce0f1375eb69bc067ac972e965e55df 100644
--- a/src/main/java/com/syncleus/dann/graph/search/pathfinding/JohnsonGraphTransformer.java
+++ b/src/main/java/com/syncleus/dann/graph/search/pathfinding/JohnsonGraphTransformer.java
@@ -22,14 +22,8 @@ import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-import com.syncleus.dann.graph.BidirectedGraph;
-import com.syncleus.dann.graph.Edge;
-import com.syncleus.dann.graph.Graph;
-import com.syncleus.dann.graph.ImmutableWeightedDirectedEdge;
-import com.syncleus.dann.graph.MutableDirectedAdjacencyGraph;
+import com.syncleus.dann.graph.*;
 import com.syncleus.dann.graph.SimpleWeightedDirectedEdge;
-import com.syncleus.dann.graph.Weighted;
-import com.syncleus.dann.graph.WeightedDirectedEdge;
 
 public class JohnsonGraphTransformer<N> implements GraphTransformer<BidirectedGraph<N, ? extends WeightedDirectedEdge<N>>>
 {
@@ -57,13 +51,13 @@ public class JohnsonGraphTransformer<N> implements GraphTransformer<BidirectedGr
 		final Set<WeightedDirectedEdge<Object>> originalEdges = new HashSet<WeightedDirectedEdge<Object>>();
 		for(final WeightedDirectedEdge<N> originalEdge : original.getEdges())
 			originalEdges.add((WeightedDirectedEdge<Object>) originalEdge);
-		final MutableDirectedAdjacencyGraph<Object, WeightedDirectedEdge<Object>> copyGraph = new MutableDirectedAdjacencyGraph<Object, WeightedDirectedEdge<Object>>(new HashSet<Object>(original.getNodes()), originalEdges);
-		final Set<Object> originalNodes = copyGraph.getNodes();
+		final MutableDirectedAdjacencyGraph<Object, WeightedDirectedEdge<Object>> copyGraph = new MutableDirectedAdjacencyGraph<Object, WeightedDirectedEdge<Object>>(new HashSet<Object>(original.getTargets()), originalEdges);
+		final Set<Object> originalNodes = copyGraph.getTargets();
 		copyGraph.add(BLANK_NODE);
 		for(final Object originalNode : originalNodes)
 			copyGraph.add(new ImmutableWeightedDirectedEdge<Object>(BLANK_NODE, originalNode, 0.0));
 		final BellmanFordPathFinder<Object, WeightedDirectedEdge<Object>> pathFinder = new BellmanFordPathFinder<Object, WeightedDirectedEdge<Object>>(copyGraph);
-		final MutableDirectedAdjacencyGraph johnsonGraph = new MutableDirectedAdjacencyGraph(original.getNodes(), new HashSet<WeightedDirectedEdge<N>>(original.getEdges()));
+		final MutableDirectedAdjacencyGraph johnsonGraph = new MutableDirectedAdjacencyGraph(original.getTargets(), new HashSet<WeightedDirectedEdge<N>>(original.getEdges()));
 		final List<WeightedDirectedEdge<N>> edges = new ArrayList<WeightedDirectedEdge<N>>(johnsonGraph.getEdges());
 		for(final WeightedDirectedEdge<N> edge : edges)
 		{
diff --git a/src/main/java/com/syncleus/dann/graph/topological/KnotOptimizedGraph.java b/src/main/java/com/syncleus/dann/graph/topological/KnotOptimizedGraph.java
index b9515e0394fd38dc39a6cf3745a5c8d87fecbd2e..13e0c3c1745e0205a6529e2ffdf3675d6165dd08 100644
--- a/src/main/java/com/syncleus/dann/graph/topological/KnotOptimizedGraph.java
+++ b/src/main/java/com/syncleus/dann/graph/topological/KnotOptimizedGraph.java
@@ -29,7 +29,7 @@ public interface KnotOptimizedGraph<N, E extends Edge<N>> extends Graph<N, E>
 	 * set, and once the set is entered there is no path to traverse outside of the
 	 * set. If the specified nodes each have atleast one traversable edge in the
 	 * specified edges, all specified traversable edges go to other nodes in the
-	 * knot, no traversable edges connect to a node outside of the knot (even if it
+	 * knot, no traversable edges join to a node outside of the knot (even if it
 	 * isnt specified, and there is atleast onentraversable edge from a node
 	 * outside of the knot to a node in the knot (obviously not specified in
 	 * knotedEdges). It is important to note that while the knot is not a maximally
@@ -49,7 +49,7 @@ public interface KnotOptimizedGraph<N, E extends Edge<N>> extends Graph<N, E>
 	 * set, and once the set is entered there is no path to traverse outside of the
 	 * set. if the specified nodes each have atleast one traversable edge, all
 	 * traversable edges go to other nodes in the knot, no traversable edges
-	 * connect to a node outside of the know, and there is atleast one traversable
+	 * join to a node outside of the know, and there is atleast one traversable
 	 * edge from a node outside of the knot to a node in the knot. It is important
 	 * to note that while the knot is not a maximally connected component of the
 	 * graph it is weakly connected amongst itself.
diff --git a/src/main/java/com/syncleus/dann/graph/topological/Topography.java b/src/main/java/com/syncleus/dann/graph/topological/Topography.java
index 2bb131276d1868ed87b7a0f3963702568a540da9..2af050ec3d0d6ad0e68ccb90cb373687d5dd81a2 100644
--- a/src/main/java/com/syncleus/dann/graph/topological/Topography.java
+++ b/src/main/java/com/syncleus/dann/graph/topological/Topography.java
@@ -35,7 +35,7 @@ import com.syncleus.dann.graph.Graph;
 import com.syncleus.dann.graph.HyperEdge;
 import com.syncleus.dann.graph.HyperGraph;
 import com.syncleus.dann.graph.ImmutableAdjacencyGraph;
-import com.syncleus.dann.graph.ImmutableHyperEdge;
+import com.syncleus.dann.graph.SimpleHyperEdge;
 import com.syncleus.dann.math.counting.Counters;
 
 public final class Topography
@@ -49,8 +49,8 @@ public final class Topography
 	/**
 	 * Gets the degree of a given node. The degree of a node is how many adjacent edges link to
 	 * this node, as opposed to how many nodes this node links to. A typical adjacent edge will
-	 * connect once to this edge and to one or more other nodes, counting once towards the
-	 * degree. However, loop edges can connect twice or more to this node counting multiple
+	 * join once to this edge and to one or more other nodes, counting once towards the
+	 * degree. However, loop edges can join twice or more to this node counting multiple
 	 * times.
 	 * @param node The node whose degree is to be returned
 	 * @return The degree of this node
@@ -88,7 +88,7 @@ public final class Topography
 			final Set<E> adjacentNodesEdges = graph.getAdjacentEdges(node);
 			int degree = 0;
 			for(final E adjacentEdge : adjacentNodesEdges)
-				for(final N adjacentNode : adjacentEdge.getNodes())
+				for(final N adjacentNode : adjacentEdge.getTargets())
 					if( adjacentNode.equals(node) )
 						degree++;
 			return degree;
@@ -115,7 +115,7 @@ public final class Topography
 			}
 		}
 
-		final Set<N> nodes = graph.getNodes();
+		final Set<N> nodes = graph.getTargets();
 		for(final N fromNode : nodes)
 			for(final N toNode : nodes)
 				if( (toNode != fromNode) && (!Topography.isStronglyConnected(graph, toNode, fromNode)) )
@@ -143,7 +143,7 @@ public final class Topography
 			}
 		}
 
-		final List<N> remainingNodes = new ArrayList<N>(graph.getNodes());
+		final List<N> remainingNodes = new ArrayList<N>(graph.getTargets());
 		while( remainingNodes.size() >= 2 )
 		{
 			final N fromNode = remainingNodes.get(0);
@@ -230,7 +230,7 @@ public final class Topography
 		final Set<N> visited = new HashSet<N>();
 		visited.add(leftNode);
 		final Set<N> toVisit = new HashSet<N>();
-		toVisit.addAll(graph.getTraversableNodes(leftNode));
+		toVisit.addAll(graph.getTraversableAdjacentNodes(leftNode));
 		while( !toVisit.isEmpty() )
 		{
 			final N node = toVisit.iterator().next();
@@ -238,7 +238,7 @@ public final class Topography
 				return true;
 			visited.add(node);
 			toVisit.remove(node);
-			toVisit.addAll(graph.getTraversableNodes(node));
+			toVisit.addAll(graph.getTraversableAdjacentNodes(node));
 			toVisit.removeAll(visited);
 		}
 		return false;
@@ -272,7 +272,7 @@ public final class Topography
 	/**
 	 * Determines whether the given graph is a maximal subgraph of the current graph.
 	 * A subgraph is maximal if none of the edges of the parent graph not in the subgraph
-	 * connect to any nodes in the subgraph.
+	 * join to any nodes in the subgraph.
 	 * @param subGraph A subgraph of this graph to be checked if maximally
 	 * connected.
 	 * @return Whether this is a maximal subgraph
@@ -299,10 +299,10 @@ public final class Topography
 		final Set<? extends E> subedges = subGraph.getEdges();
 		exclusiveParentEdges.removeAll(subedges);
 		//check to make sure none of the edges exclusive to the parent graph
-		//connect to any of the nodes in the subgraph.
-		final Set<? extends N> subnodes = subGraph.getNodes();
+		//join to any of the nodes in the subgraph.
+		final Set<? extends N> subnodes = subGraph.getTargets();
 		for(final E exclusiveParentEdge : exclusiveParentEdges)
-			for(final N exclusiveParentNode : exclusiveParentEdge.getNodes())
+			for(final N exclusiveParentNode : exclusiveParentEdge.getTargets())
 				if( subnodes.contains(exclusiveParentNode) )
 					return false;
 		//passed all the tests, must be maximal
@@ -460,13 +460,13 @@ public final class Topography
 			}
 		}
 
-		final Set<Set<N>> combinations = Counters.everyCombination(graph.getNodes());
+		final Set<Set<N>> combinations = Counters.everyCombination(graph.getTargets());
 		final SortedSet<Set<N>> sortedCombinations = new TreeSet<Set<N>>(new SizeComparator());
 		sortedCombinations.addAll(combinations);
 		for(final Set<N> cutNodes : sortedCombinations)
 			if( Topography.isCut(graph, cutNodes, Collections.<E>emptySet()) )
 				return cutNodes.size();
-		return graph.getNodes().size();
+		return graph.getTargets().size();
 	}
 
 	public static <N, E extends Edge<N>> int getEdgeConnectivity(final Graph<N, E> graph)
@@ -506,13 +506,13 @@ public final class Topography
 			}
 		}
 
-		final Set<Set<N>> combinations = Counters.everyCombination(graph.getNodes());
+		final Set<Set<N>> combinations = Counters.everyCombination(graph.getTargets());
 		final SortedSet<Set<N>> sortedCombinations = new TreeSet<Set<N>>(new SizeComparator());
 		sortedCombinations.addAll(combinations);
 		for(final Set<N> cutNodes : sortedCombinations)
 			if( Topography.isCut(graph, cutNodes, Collections.<E>emptySet(), begin, end) )
 				return cutNodes.size();
-		return graph.getNodes().size();
+		return graph.getTargets().size();
 	}
 
 	public static <N, E extends Edge<N>> int getEdgeConnectivity(final Graph<N, E> graph, final N begin, final N end)
@@ -554,9 +554,9 @@ public final class Topography
 
 		if( !Topography.isSimple(graph) )
 			return false;
-		for(final N startNode : graph.getNodes())
+		for(final N startNode : graph.getTargets())
 		{
-			for(final N endNode : graph.getNodes())
+			for(final N endNode : graph.getTargets())
 			{
 				if( !startNode.equals(endNode)
 						&& !graph.getAdjacentNodes(startNode).contains(endNode) )
@@ -580,7 +580,7 @@ public final class Topography
 			}
 		}
 
-		return graph.getNodes().size();
+		return graph.getTargets().size();
 	}
 
 	public static <N, E extends Edge<N>> boolean isSubGraph(final Graph<N, E> graph, final Graph<N, E> subgraph)
@@ -597,8 +597,8 @@ public final class Topography
 			}
 		}
 
-		final Set<N> nodes = graph.getNodes();
-		final Set<N> subnodes = subgraph.getNodes();
+		final Set<N> nodes = graph.getTargets();
+		final Set<N> subnodes = subgraph.getTargets();
 		for(final N subnode : subnodes)
 			if( !nodes.contains(subnode) )
 				return false;
@@ -623,10 +623,10 @@ public final class Topography
 			}
 		}
 
-		if( graph.getNodes().isEmpty() )
+		if( graph.getTargets().isEmpty() )
 			throw new IllegalStateException("This graph has no nodes!");
 		int minimumDegree = Integer.MAX_VALUE;
-		for(final N node : graph.getNodes())
+		for(final N node : graph.getTargets())
 			if( Topography.getDegree(graph, node) < minimumDegree )
 				minimumDegree = Topography.getDegree(graph, node);
 		return minimumDegree;
@@ -646,7 +646,7 @@ public final class Topography
 			}
 		}
 
-		for(final N currentNode : graph.getNodes())
+		for(final N currentNode : graph.getTargets())
 		{
 			final List<N> neighbors = new ArrayList<N>(graph.getAdjacentNodes(currentNode));
 			while( neighbors.remove(currentNode) )
@@ -691,8 +691,8 @@ public final class Topography
 			}
 		}
 
-		final Set<N> uncheckedNodes = new HashSet<N>(graph.getNodes());
-		final Set<N> homomorphicNodes = homomorphicGraph.getNodes();
+		final Set<N> uncheckedNodes = new HashSet<N>(graph.getTargets());
+		final Set<N> homomorphicNodes = homomorphicGraph.getTargets();
 
 		while( !uncheckedNodes.isEmpty() )
 		{
@@ -741,7 +741,7 @@ public final class Topography
 			}
 		}
 
-		for(final N currentNode : graph.getNodes())
+		for(final N currentNode : graph.getTargets())
 		{
 			final List<N> neighbors = graph.getAdjacentNodes(currentNode);
 			final Set<N> uniqueNeighbors = new HashSet<N>(neighbors);
@@ -775,7 +775,7 @@ public final class Topography
 		}
 
 		int degree = -1;
-		for(final N node : graph.getNodes())
+		for(final N node : graph.getTargets())
 		{
 			if( degree == -1 )
 				degree = Topography.getDegree(graph, node);
@@ -806,7 +806,7 @@ public final class Topography
 		}
 
 		int degree = -1;
-		for(final N node : graph.getNodes())
+		for(final N node : graph.getTargets())
 		{
 			if( degree == -1 )
 				degree = Topography.getDegree(graph, node);
@@ -879,13 +879,13 @@ public final class Topography
 		}
 
 		int multiplicity = 0;
-		final List<N> edgeNodes = edge.getNodes();
-		final Set<E> potentialMultiples = graph.getAdjacentEdges(edge.getNodes().get(0));
+		final List<N> edgeNodes = edge.getTargets();
+		final Set<E> potentialMultiples = graph.getAdjacentEdges(edge.getTargets().get(0));
 		for(final E potentialMultiple : potentialMultiples)
 		{
 			if( potentialMultiple.equals(edge) )
 				continue;
-			final List<N> potentialNodes = new ArrayList<N>(potentialMultiple.getNodes());
+			final List<N> potentialNodes = new ArrayList<N>(potentialMultiple.getTargets());
 			if( potentialNodes.size() != edgeNodes.size() )
 				continue;
 			for(final N edgeNode : edgeNodes)
@@ -923,13 +923,13 @@ public final class Topography
 			}
 		}
 
-		final List<N> edgeNodes = edge.getNodes();
-		final Set<E> potentialMultiples = graph.getAdjacentEdges(edge.getNodes().get(0));
+		final List<N> edgeNodes = edge.getTargets();
+		final Set<E> potentialMultiples = graph.getAdjacentEdges(edge.getTargets().get(0));
 		for(final E potentialMultiple : potentialMultiples)
 		{
 			if( potentialMultiple.equals(edge) )
 				continue;
-			final List<N> potentialNodes = new ArrayList<N>(potentialMultiple.getNodes());
+			final List<N> potentialNodes = new ArrayList<N>(potentialMultiple.getTargets());
 			if( potentialNodes.size() != edgeNodes.size() )
 				continue;
 			for(final N edgeNode : edgeNodes)
@@ -945,7 +945,7 @@ public final class Topography
 	 * set, and once the set is entered there is no path to traverse outside of the
 	 * set. if the specified nodes each have at least one traversable edge, all
 	 * traversable edges go to other nodes in the knot, no traversable edges
-	 * connect to a node outside of the knot, and there is at least one traversable
+	 * join to a node outside of the knot, and there is at least one traversable
 	 * edge from a node outside of the knot to a node in the knot. It is important
 	 * to note that while the knot is not a maximally connected component of the
 	 * graph it is weakly connected amongst itself.
@@ -1024,7 +1024,7 @@ public final class Topography
 			}
 		}
 
-		return graph.getTraversableEdges(node).size();
+		return graph.getTraversableAdjacentEdges(node).size();
 	}
 
 	public static <N, E extends HyperEdge<N>> int getRank(final HyperGraph<N, E> graph)
@@ -1128,26 +1128,26 @@ public final class Topography
 	private static <N, E extends Edge<N>> ImmutableAdjacencyGraph<N, Edge<N>> deleteFromGraph(final Graph<N, E> graph, final Set<N> deleteNodes, final Set<E> deleteEdges)
 	{
 		//remove the deleteNodes
-		final Set<N> cutNodes = graph.getNodes();
+		final Set<N> cutNodes = graph.getTargets();
 		cutNodes.removeAll(deleteNodes);
 		//remove the deleteEdges
 		final Set<Edge<N>> cutEdges = new HashSet<Edge<N>>(deleteEdges);
 		for(final E edge : deleteEdges)
 			cutEdges.remove(edge);
-		//remove any remaining deleteEdges which connect to removed deleteNodes
+		//remove any remaining deleteEdges which join to removed deleteNodes
 		//also replace deleteEdges that have one removed node but still have
 		//2 or more remaining deleteNodes with a new edge.
 		final Set<Edge<N>> removeEdges = new HashSet<Edge<N>>();
 		final Set<Edge<N>> addEdges = new HashSet<Edge<N>>();
 		for(final Edge<N> cutEdge : cutEdges)
 		{
-			final List<N> cutEdgeNeighbors = cutEdge.getNodes();
+			final List<N> cutEdgeNeighbors = cutEdge.getTargets();
 			cutEdgeNeighbors.removeAll(cutNodes);
-			if( cutEdgeNeighbors.size() != cutEdge.getNodes().size() )
+			if( cutEdgeNeighbors.size() != cutEdge.getTargets().size() )
 				removeEdges.add(cutEdge);
 			if( cutEdgeNeighbors.size() > 1 )
-				// TODO instead of ImmutableHyperEdge implement clone or something
-				addEdges.add(new ImmutableHyperEdge<N>(cutEdgeNeighbors));
+				// TODO instead of SimpleHyperEdge implement clone or something
+				addEdges.add(new SimpleHyperEdge<N>(cutEdgeNeighbors));
 		}
 		for(final Edge<N> removeEdge : removeEdges)
 			cutEdges.remove(removeEdge);
diff --git a/src/main/java/com/syncleus/dann/graph/topological/sorter/SimpleTopologicalRanker.java b/src/main/java/com/syncleus/dann/graph/topological/sorter/SimpleTopologicalRanker.java
index 1b88fd06c633d53afc15f1c2784453e929f8f8fa..8ce24fccb82780d20b583bec1500b8743d8e0f51 100644
--- a/src/main/java/com/syncleus/dann/graph/topological/sorter/SimpleTopologicalRanker.java
+++ b/src/main/java/com/syncleus/dann/graph/topological/sorter/SimpleTopologicalRanker.java
@@ -33,14 +33,14 @@ public class SimpleTopologicalRanker<N> implements TopologicalRanker<N>
 	public List<Set<N>> rank(final BidirectedGraph<? extends N, ? extends DirectedEdge<? extends N>> graph)
 	{
 		//initialize data structures
-		final Set<N> remainingNodes = new HashSet<N>(graph.getNodes());
+		final Set<N> remainingNodes = new HashSet<N>(graph.getTargets());
 		final Set<DirectedEdge<? extends N>> remainingEdges = new HashSet<DirectedEdge<? extends N>>(graph.getEdges());
 		final Map<N, Set<DirectedEdge<? extends N>>> remainingNeighborEdges = new HashMap<N, Set<DirectedEdge<? extends N>>>();
 
 		//construct the remainingNeighborEdges with the entire graphs adjacency
 		for(final DirectedEdge<? extends N> edge : remainingEdges )
 		{
-			for(final N edgeNode : edge.getNodes())
+			for(final N edgeNode : edge.getTargets())
 			{
 				if( !remainingNodes.contains(edgeNode) )
 					throw new IllegalArgumentException("A node that is an end point in one of the edges was not in the nodes list");
@@ -74,7 +74,7 @@ public class SimpleTopologicalRanker<N> implements TopologicalRanker<N>
 				final Set<DirectedEdge<? extends N>> neighbors = remainingNeighborEdges.get(node);
 				for(final DirectedEdge<? extends N> neighbor : neighbors)
 				{
-					final List<N> adjacentNodes = new ArrayList<N>(neighbor.getNodes());
+					final List<N> adjacentNodes = new ArrayList<N>(neighbor.getTargets());
 					adjacentNodes.remove(node);
 					final N adjacentNode = adjacentNodes.get(0);
 
@@ -101,7 +101,7 @@ public class SimpleTopologicalRanker<N> implements TopologicalRanker<N>
 		final List<Set<N>> rankedNodes = this.rank(graph);
 
 		//convert ranked nodes into sorted nodes
-		final List<N> sortedNodes = new ArrayList<N>(graph.getNodes().size());
+		final List<N> sortedNodes = new ArrayList<N>(graph.getTargets().size());
 		for(Set<N> levelNodes : rankedNodes)
 			sortedNodes.addAll(levelNodes);
 
diff --git a/src/main/java/com/syncleus/dann/graph/tree/Trees.java b/src/main/java/com/syncleus/dann/graph/tree/Trees.java
index 5f188c299210e988fc31314eca9b1b896e39c86c..5480bb873035a65976748bfe3cd15f14405cba54 100644
--- a/src/main/java/com/syncleus/dann/graph/tree/Trees.java
+++ b/src/main/java/com/syncleus/dann/graph/tree/Trees.java
@@ -57,7 +57,7 @@ public final class Trees
 
 		// TODO check if subgraph is actually a subgraph, another words that it is a subset of nodes and edges
 		// TODO in fact we probably want to rethink this entirely
-		return ((graph.getNodes().containsAll(subGraph.getNodes()))
+		return ((graph.getTargets().containsAll(subGraph.getTargets()))
 				&& (Topography.isWeaklyConnected(subGraph))
 				&& (Cycles.isAcyclic(subGraph)));
 	}
diff --git a/src/main/java/com/syncleus/dann/graph/tree/mst/KruskalMinimumSpanningTreeFinder.java b/src/main/java/com/syncleus/dann/graph/tree/mst/KruskalMinimumSpanningTreeFinder.java
index c0fd82cc183914ccb632eef6ab690dae6d7f57e2..251bad20ee38b479d8e24ee4aae381d1e6ba3064 100644
--- a/src/main/java/com/syncleus/dann/graph/tree/mst/KruskalMinimumSpanningTreeFinder.java
+++ b/src/main/java/com/syncleus/dann/graph/tree/mst/KruskalMinimumSpanningTreeFinder.java
@@ -47,7 +47,7 @@ public class KruskalMinimumSpanningTreeFinder<N, E extends Edge<N>> implements M
 	public Set<E> findMinimumSpanningTree(final Graph<N, E> graph)
 	{
 		final Set<Set<N>> componentNodeSets = new HashSet<Set<N>>();
-		for(final N node : graph.getNodes())
+		for(final N node : graph.getTargets())
 			componentNodeSets.add(Collections.singleton(node));
 		final Queue<E> edgeQueue = new PriorityQueue<E>(graph.getEdges().size(), new WeightComparator<E>());
 		edgeQueue.addAll(graph.getEdges());
@@ -62,7 +62,7 @@ public class KruskalMinimumSpanningTreeFinder<N, E extends Edge<N>> implements M
 			final Set<Set<N>> setContainingEndNodes = new HashSet<Set<N>>();
 			for(final Set<N> component : componentNodeSets)
 			{
-				for(final N endNode : queuedEdge.getNodes())
+				for(final N endNode : queuedEdge.getTargets())
 				{
 					if( component.contains(endNode) )
 					{
diff --git a/src/main/java/com/syncleus/dann/graph/tree/mst/PrimMinimumSpanningTreeFinder.java b/src/main/java/com/syncleus/dann/graph/tree/mst/PrimMinimumSpanningTreeFinder.java
index 8013da81215517f66566730fb07a3e24d71d2677..a5ac9b5989603d094b675552ad9be27e5b707ca3 100644
--- a/src/main/java/com/syncleus/dann/graph/tree/mst/PrimMinimumSpanningTreeFinder.java
+++ b/src/main/java/com/syncleus/dann/graph/tree/mst/PrimMinimumSpanningTreeFinder.java
@@ -61,7 +61,7 @@ public class PrimMinimumSpanningTreeFinder<N, E extends Edge<N>> implements Root
 		}
 		else
 		{
-			startNode = graph.getNodes().iterator().next();
+			startNode = graph.getTargets().iterator().next();
 		}
 
 		return this.primCalculate(graph, startNode);
@@ -77,7 +77,7 @@ public class PrimMinimumSpanningTreeFinder<N, E extends Edge<N>> implements Root
 	{
 		final Set<E> mst = new HashSet<E>();
 		final PrimMap<N, E> primMap = new PrimMap<N, E>();
-		for(final N node : graph.getNodes())
+		for(final N node : graph.getTargets())
 			primMap.put(node, null);
 
 		N currentNode = null;
@@ -95,10 +95,10 @@ public class PrimMinimumSpanningTreeFinder<N, E extends Edge<N>> implements Root
 				mst.add(currentEntry.getValue());
 			}
 
-			final Set<E> neighborEdges = graph.getTraversableEdges(currentNode);
+			final Set<E> neighborEdges = graph.getTraversableAdjacentEdges(currentNode);
 			for(final E neighborEdge : neighborEdges)
 			{
-				final List<N> neighborNodes = new ArrayList<N>(neighborEdge.getNodes());
+				final List<N> neighborNodes = new ArrayList<N>(neighborEdge.getTargets());
 				//remove all occurrences of currentNode, not just the first
 				while( neighborNodes.remove(currentNode) )
 				{
diff --git a/src/main/java/com/syncleus/dann/graphicalmodel/AbstractGraphicalModelAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graphicalmodel/AbstractGraphicalModelAdjacencyGraph.java
index fa5fa50b0f2075cc0b3d6cb529b444079168ff3f..5b33c8eac7654db0c82a9bca0761bef4ec1f57ae 100644
--- a/src/main/java/com/syncleus/dann/graphicalmodel/AbstractGraphicalModelAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graphicalmodel/AbstractGraphicalModelAdjacencyGraph.java
@@ -35,7 +35,7 @@ public abstract class AbstractGraphicalModelAdjacencyGraph<N extends GraphicalMo
 
 	protected AbstractGraphicalModelAdjacencyGraph(final Graph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 
 	protected AbstractGraphicalModelAdjacencyGraph(final Set<N> nodes, final Set<E> edges)
@@ -46,7 +46,7 @@ public abstract class AbstractGraphicalModelAdjacencyGraph<N extends GraphicalMo
 	@Override
 	public void learnStates()
 	{
-		for(final N node : this.getNodes())
+		for(final N node : this.getTargets())
 			node.learnState();
 	}
 
@@ -63,7 +63,7 @@ public abstract class AbstractGraphicalModelAdjacencyGraph<N extends GraphicalMo
 		//first we need to preserve a map of all the starting states so we can reset the network back to its starting
 		//point when we are done
 		Map<N, Object> startingStates = new HashMap<N, Object>();
-		for(N node : this.getNodes())
+		for(N node : this.getTargets())
 		{
 			//we wont be changing influences nodes, so we can skip those
 			if( !influences.contains(node) )
@@ -72,7 +72,7 @@ public abstract class AbstractGraphicalModelAdjacencyGraph<N extends GraphicalMo
 
 		try
 		{
-			List<N> varyingNodes = new ArrayList<N>(this.getNodes());
+			List<N> varyingNodes = new ArrayList<N>(this.getTargets());
 
 			//calculate numerator
 			varyingNodes.removeAll(influences);
@@ -86,7 +86,7 @@ public abstract class AbstractGraphicalModelAdjacencyGraph<N extends GraphicalMo
 			while( !incrementNodeStates(varyingNodes) );
 
 			//calculate denominator
-			varyingNodes = new ArrayList<N>(this.getNodes());
+			varyingNodes = new ArrayList<N>(this.getTargets());
 			varyingNodes.removeAll(influences);
 			resetNodeStates(varyingNodes);
 			double denominator = 0.0;
@@ -190,7 +190,7 @@ public abstract class AbstractGraphicalModelAdjacencyGraph<N extends GraphicalMo
 		networkXml.setNodeInstances(new GraphicalModelElementXml.NodeInstances());
 		networkXml.setStateInstances(new GraphicalModelElementXml.StateInstances());
 		final Set<Object> writtenStates = new HashSet<Object>();
-		for (N node : this.getNodes())
+		for (N node : this.getTargets())
 		{
 			//add the node
 			final NamedValueXml nodeXml = new NamedValueXml();
diff --git a/src/main/java/com/syncleus/dann/graphicalmodel/ImmutableGraphicalModelAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graphicalmodel/ImmutableGraphicalModelAdjacencyGraph.java
index ae0dbc497a796e1d9769ae53dd3bf58105f8e3ad..3b6ac8762c5e2c3d315431c47970ccb20a919bfd 100644
--- a/src/main/java/com/syncleus/dann/graphicalmodel/ImmutableGraphicalModelAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graphicalmodel/ImmutableGraphicalModelAdjacencyGraph.java
@@ -41,7 +41,7 @@ public class ImmutableGraphicalModelAdjacencyGraph<N extends GraphicalModelNode,
 	/*
 	public ImmutableMarkovRandomFieldAdjacencyGraph(final Graph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 	*/
 
diff --git a/src/main/java/com/syncleus/dann/graphicalmodel/MutableGraphicalModelAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graphicalmodel/MutableGraphicalModelAdjacencyGraph.java
index 87558f19a50f6c8de5a2e8a1ccfbfd15d63c9b2f..da3d0ed6dabc6173f44f090ecc6f02e65c27a81d 100644
--- a/src/main/java/com/syncleus/dann/graphicalmodel/MutableGraphicalModelAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graphicalmodel/MutableGraphicalModelAdjacencyGraph.java
@@ -37,7 +37,7 @@ public class MutableGraphicalModelAdjacencyGraph<N extends GraphicalModelNode, E
 
 	public MutableGraphicalModelAdjacencyGraph(final Graph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 
 	public MutableGraphicalModelAdjacencyGraph(final Set<N> nodes, final Set<E> edges)
@@ -50,21 +50,20 @@ public class MutableGraphicalModelAdjacencyGraph<N extends GraphicalModelNode, E
 	{
 		if( newEdge == null )
 			throw new IllegalArgumentException("newEdge can not be null");
-		if( !this.getNodes().containsAll(newEdge.getNodes()) )
+		if( !this.getTargets().containsAll(newEdge.getTargets()) )
 			throw new IllegalArgumentException("newEdge has a node as an end point that is not part of the graph");
 
 		// if context is enabled lets check if it can join
-		if( this.isContextEnabled() && (newEdge instanceof ContextGraphElement)
-				&& !((ContextGraphElement)newEdge).joiningGraph(this) )
-			return false;
+		if( this.isContextEnabled() && (newEdge instanceof ContextGraphElement) )
+			((ContextGraphElement)newEdge).joiningGraph(this);
 
 		if( this.getInternalEdges().add(newEdge) )
 		{
-			for(final N currentNode : newEdge.getNodes())
+			for(final N currentNode : newEdge.getTargets())
 			{
 				this.getInternalAdjacencyEdges().get(currentNode).add(newEdge);
 
-				final List<N> newAdjacentNodes = new ArrayList<N>(newEdge.getNodes());
+				final List<N> newAdjacentNodes = new ArrayList<N>(newEdge.getTargets());
 				newAdjacentNodes.remove(currentNode);
 				for(final N newAdjacentNode : newAdjacentNodes)
 					this.getInternalAdjacencyNodes().get(currentNode).add(newAdjacentNode);
@@ -112,11 +111,11 @@ public class MutableGraphicalModelAdjacencyGraph<N extends GraphicalModelNode, E
 		if( !this.getInternalEdges().remove(edgeToRemove) )
 			return false;
 
-		for(final N removeNode : edgeToRemove.getNodes())
+		for(final N removeNode : edgeToRemove.getTargets())
 		{
 			this.getInternalAdjacencyEdges().get(removeNode).remove(edgeToRemove);
 
-			final List<N> removeAdjacentNodes = new ArrayList<N>(edgeToRemove.getNodes());
+			final List<N> removeAdjacentNodes = new ArrayList<N>(edgeToRemove.getTargets());
 			removeAdjacentNodes.remove(removeNode);
 			for(final N removeAdjacentNode : removeAdjacentNodes)
 				this.getInternalAdjacencyNodes().get(removeNode).remove(removeAdjacentNode);
@@ -150,7 +149,7 @@ public class MutableGraphicalModelAdjacencyGraph<N extends GraphicalModelNode, E
 		for(final E removeEdge : removeEdges)
 		{
 			E newEdge = (E) removeEdge.disconnect(nodeToRemove);
-			while( (newEdge != null) && (newEdge.getNodes().contains(nodeToRemove)) )
+			while( (newEdge != null) && (newEdge.getTargets().contains(nodeToRemove)) )
 				newEdge = (E) removeEdge.disconnect(nodeToRemove);
 			if( newEdge != null )
 				newEdges.add(newEdge);
@@ -186,7 +185,7 @@ public class MutableGraphicalModelAdjacencyGraph<N extends GraphicalModelNode, E
 		}
 
 		//now lets remove all the nodes
-		for(N node : this.getNodes())
+		for(N node : this.getTargets())
 		{
 			//lets just make sure we arent some how getting an we dont actually own, this shouldnt be possible so its
 			//an assert. This ensures that if remove() comes back false it must be because the context didnt allow it.
diff --git a/src/main/java/com/syncleus/dann/graphicalmodel/SimpleGraphicalModelNode.java b/src/main/java/com/syncleus/dann/graphicalmodel/SimpleGraphicalModelNode.java
index 4e85acdc777e57fc9d73db88408b55203e5f1692..b42f4b0424363159f19b02baca96edee9563a8ba 100644
--- a/src/main/java/com/syncleus/dann/graphicalmodel/SimpleGraphicalModelNode.java
+++ b/src/main/java/com/syncleus/dann/graphicalmodel/SimpleGraphicalModelNode.java
@@ -153,7 +153,7 @@ public class SimpleGraphicalModelNode<S> extends AbstractContextNode<GraphicalMo
 		for(final BidirectedEdge<GraphicalModelNode<S>> inEdge : inEdges)
 		{
 			//if it is traversable to this node it is an influence
-			List<GraphicalModelNode<S>> otherNodes = new ArrayList<GraphicalModelNode<S>>(inEdge.getNodes());
+			List<GraphicalModelNode<S>> otherNodes = new ArrayList<GraphicalModelNode<S>>(inEdge.getTargets());
 			otherNodes.remove(this);
 			GraphicalModelNode<S> otherNode = otherNodes.get(0);
 			if( inEdge.isTraversable(otherNode) )
@@ -174,7 +174,7 @@ public class SimpleGraphicalModelNode<S> extends AbstractContextNode<GraphicalMo
 		for(final BidirectedEdge<GraphicalModelNode<S>> inEdge : inEdges)
 		{
 			//if it is traversable to this node it is an influence
-			List<GraphicalModelNode<S>> otherNodes = new ArrayList<GraphicalModelNode<S>>(inEdge.getNodes());
+			List<GraphicalModelNode<S>> otherNodes = new ArrayList<GraphicalModelNode<S>>(inEdge.getTargets());
 			otherNodes.remove(this);
 			GraphicalModelNode<S> otherNode = otherNodes.get(0);
 			if( inEdge.isTraversable(otherNode) )
diff --git a/src/main/java/com/syncleus/dann/graphicalmodel/bayesian/AbstractBayesianAdjacencyNetwork.java b/src/main/java/com/syncleus/dann/graphicalmodel/bayesian/AbstractBayesianAdjacencyNetwork.java
index f963973ab27af4e30dcde31e49191fbee704114f..4679d436ed0e4d5c1befd0fd5a6e3660c72e74db 100644
--- a/src/main/java/com/syncleus/dann/graphicalmodel/bayesian/AbstractBayesianAdjacencyNetwork.java
+++ b/src/main/java/com/syncleus/dann/graphicalmodel/bayesian/AbstractBayesianAdjacencyNetwork.java
@@ -33,7 +33,7 @@ public abstract class AbstractBayesianAdjacencyNetwork<N extends GraphicalModelN
 
 	protected AbstractBayesianAdjacencyNetwork(final Graph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 
 	protected AbstractBayesianAdjacencyNetwork(final Set<N> nodes, final Set<E> edges)
@@ -45,7 +45,7 @@ public abstract class AbstractBayesianAdjacencyNetwork<N extends GraphicalModelN
 	public double jointProbability()
 	{
 		double probabilityProduct = 1.0;
-		for(final N node : this.getNodes())
+		for(final N node : this.getTargets())
 			probabilityProduct *= node.stateProbability();
 		return probabilityProduct;
 	}
diff --git a/src/main/java/com/syncleus/dann/graphicalmodel/bayesian/ImmutableBayesianAdjacencyNetwork.java b/src/main/java/com/syncleus/dann/graphicalmodel/bayesian/ImmutableBayesianAdjacencyNetwork.java
index 424b4b7a10fad76cd9aea2f2c062c047c319a3d5..0951c7601b7facd4642f67fd65c4ba1b37a7fd29 100644
--- a/src/main/java/com/syncleus/dann/graphicalmodel/bayesian/ImmutableBayesianAdjacencyNetwork.java
+++ b/src/main/java/com/syncleus/dann/graphicalmodel/bayesian/ImmutableBayesianAdjacencyNetwork.java
@@ -42,7 +42,7 @@ public class ImmutableBayesianAdjacencyNetwork<N extends GraphicalModelNode, E e
 	/*
 	public ImmutableMarkovRandomFieldAdjacencyGraph(final Graph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 	*/
 
diff --git a/src/main/java/com/syncleus/dann/graphicalmodel/bayesian/MutableBayesianAdjacencyNetwork.java b/src/main/java/com/syncleus/dann/graphicalmodel/bayesian/MutableBayesianAdjacencyNetwork.java
index bd6e39cf2582a4a81616001f4ae6df5a1d11fc7e..4ab5960253590763fccc32fd1931161e4d078037 100644
--- a/src/main/java/com/syncleus/dann/graphicalmodel/bayesian/MutableBayesianAdjacencyNetwork.java
+++ b/src/main/java/com/syncleus/dann/graphicalmodel/bayesian/MutableBayesianAdjacencyNetwork.java
@@ -38,7 +38,7 @@ public class MutableBayesianAdjacencyNetwork<N extends GraphicalModelNode, E ext
 
 	public MutableBayesianAdjacencyNetwork(final Graph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 
 	public MutableBayesianAdjacencyNetwork(final Set<N> nodes, final Set<E> edges)
@@ -51,7 +51,7 @@ public class MutableBayesianAdjacencyNetwork<N extends GraphicalModelNode, E ext
 	{
 		if( newEdge == null )
 			throw new IllegalArgumentException("newEdge can not be null");
-		if( !this.getNodes().containsAll(newEdge.getNodes()) )
+		if( !this.getTargets().containsAll(newEdge.getTargets()) )
 			throw new IllegalArgumentException("newEdge has a node as an end point that is not part of the graph");
 
 		// if context is enabled lets check if it can join
@@ -61,11 +61,11 @@ public class MutableBayesianAdjacencyNetwork<N extends GraphicalModelNode, E ext
 
 		if( this.getInternalEdges().add(newEdge) )
 		{
-			for(final N currentNode : newEdge.getNodes())
+			for(final N currentNode : newEdge.getTargets())
 			{
 				this.getInternalAdjacencyEdges().get(currentNode).add(newEdge);
 
-				final List<N> newAdjacentNodes = new ArrayList<N>(newEdge.getNodes());
+				final List<N> newAdjacentNodes = new ArrayList<N>(newEdge.getTargets());
 				newAdjacentNodes.remove(currentNode);
 				for(final N newAdjacentNode : newAdjacentNodes)
 					this.getInternalAdjacencyNodes().get(currentNode).add(newAdjacentNode);
@@ -113,11 +113,11 @@ public class MutableBayesianAdjacencyNetwork<N extends GraphicalModelNode, E ext
 		if( !this.getInternalEdges().remove(edgeToRemove) )
 			return false;
 
-		for(final N removeNode : edgeToRemove.getNodes())
+		for(final N removeNode : edgeToRemove.getTargets())
 		{
 			this.getInternalAdjacencyEdges().get(removeNode).remove(edgeToRemove);
 
-			final List<N> removeAdjacentNodes = new ArrayList<N>(edgeToRemove.getNodes());
+			final List<N> removeAdjacentNodes = new ArrayList<N>(edgeToRemove.getTargets());
 			removeAdjacentNodes.remove(removeNode);
 			for(final N removeAdjacentNode : removeAdjacentNodes)
 				this.getInternalAdjacencyNodes().get(removeNode).remove(removeAdjacentNode);
@@ -151,7 +151,7 @@ public class MutableBayesianAdjacencyNetwork<N extends GraphicalModelNode, E ext
 		for(final E removeEdge : removeEdges)
 		{
 			E newEdge = (E) removeEdge.disconnect(nodeToRemove);
-			while( (newEdge != null) && (newEdge.getNodes().contains(nodeToRemove)) )
+			while( (newEdge != null) && (newEdge.getTargets().contains(nodeToRemove)) )
 				newEdge = (E) removeEdge.disconnect(nodeToRemove);
 			if( newEdge != null )
 				newEdges.add(newEdge);
@@ -187,7 +187,7 @@ public class MutableBayesianAdjacencyNetwork<N extends GraphicalModelNode, E ext
 		}
 
 		//now lets remove all the nodes
-		for(N node : this.getNodes())
+		for(N node : this.getTargets())
 		{
 			//lets just make sure we arent some how getting an we dont actually own, this shouldnt be possible so its
 			//an assert. This ensures that if remove() comes back false it must be because the context didnt allow it.
diff --git a/src/main/java/com/syncleus/dann/graphicalmodel/dynamic/AbstractDynamicGraphicalModel.java b/src/main/java/com/syncleus/dann/graphicalmodel/dynamic/AbstractDynamicGraphicalModel.java
index 328276525c4f16532d0964f4d9e5e9c845093652..926d5b17a54fa54e0c6434dd7bb0765fa68d1303 100644
--- a/src/main/java/com/syncleus/dann/graphicalmodel/dynamic/AbstractDynamicGraphicalModel.java
+++ b/src/main/java/com/syncleus/dann/graphicalmodel/dynamic/AbstractDynamicGraphicalModel.java
@@ -32,7 +32,7 @@ public abstract class AbstractDynamicGraphicalModel<N extends DynamicGraphicalMo
 
 	protected AbstractDynamicGraphicalModel(final Graph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 
 	protected AbstractDynamicGraphicalModel(final Set<N> nodes, final Set<E> edges)
@@ -43,7 +43,7 @@ public abstract class AbstractDynamicGraphicalModel<N extends DynamicGraphicalMo
 	@Override
 	public void learnStates(final boolean updateHistory)
 	{
-		for(final N node : this.getNodes())
+		for(final N node : this.getTargets())
 		{
 			node.learnState(updateHistory);
 		}
diff --git a/src/main/java/com/syncleus/dann/graphicalmodel/dynamic/ImmutableDynamicGraphicalModel.java b/src/main/java/com/syncleus/dann/graphicalmodel/dynamic/ImmutableDynamicGraphicalModel.java
index 6dbd17f2ce34ee7e3c84a6c211adce845c965750..288a175416a0e7f610f8f782ec5ed00614d78994 100644
--- a/src/main/java/com/syncleus/dann/graphicalmodel/dynamic/ImmutableDynamicGraphicalModel.java
+++ b/src/main/java/com/syncleus/dann/graphicalmodel/dynamic/ImmutableDynamicGraphicalModel.java
@@ -34,7 +34,7 @@ public class ImmutableDynamicGraphicalModel<N extends DynamicGraphicalModelNode,
 
 	public ImmutableDynamicGraphicalModel(final Graph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 
 	public ImmutableDynamicGraphicalModel(final Set<N> nodes, final Set<E> edges)
diff --git a/src/main/java/com/syncleus/dann/graphicalmodel/dynamic/MutableDynamicGraphicalModelAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graphicalmodel/dynamic/MutableDynamicGraphicalModelAdjacencyGraph.java
index 2d69c0057c914181793870d85ad378a3f78a8fb9..eb9cc969fd7b03398234a0df15607a03b446c9be 100644
--- a/src/main/java/com/syncleus/dann/graphicalmodel/dynamic/MutableDynamicGraphicalModelAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graphicalmodel/dynamic/MutableDynamicGraphicalModelAdjacencyGraph.java
@@ -34,7 +34,7 @@ public class MutableDynamicGraphicalModelAdjacencyGraph<N extends DynamicGraphic
 
 	public MutableDynamicGraphicalModelAdjacencyGraph(final Graph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 
 	public MutableDynamicGraphicalModelAdjacencyGraph(final Set<N> nodes, final Set<E> edges)
@@ -47,7 +47,7 @@ public class MutableDynamicGraphicalModelAdjacencyGraph<N extends DynamicGraphic
 	{
 		if( newEdge == null )
 			throw new IllegalArgumentException("newEdge can not be null");
-		if( !this.getNodes().containsAll(newEdge.getNodes()) )
+		if( !this.getTargets().containsAll(newEdge.getTargets()) )
 			throw new IllegalArgumentException("newEdge has a node as an end point that is not part of the graph");
 
 		// if context is enabled lets check if it can join
@@ -57,11 +57,11 @@ public class MutableDynamicGraphicalModelAdjacencyGraph<N extends DynamicGraphic
 
 		if( this.getInternalEdges().add(newEdge) )
 		{
-			for(final N currentNode : newEdge.getNodes())
+			for(final N currentNode : newEdge.getTargets())
 			{
 				this.getInternalAdjacencyEdges().get(currentNode).add(newEdge);
 
-				final List<N> newAdjacentNodes = new ArrayList<N>(newEdge.getNodes());
+				final List<N> newAdjacentNodes = new ArrayList<N>(newEdge.getTargets());
 				newAdjacentNodes.remove(currentNode);
 				for(final N newAdjacentNode : newAdjacentNodes)
 					this.getInternalAdjacencyNodes().get(currentNode).add(newAdjacentNode);
@@ -109,11 +109,11 @@ public class MutableDynamicGraphicalModelAdjacencyGraph<N extends DynamicGraphic
 		if( !this.getInternalEdges().remove(edgeToRemove) )
 			return false;
 
-		for(final N removeNode : edgeToRemove.getNodes())
+		for(final N removeNode : edgeToRemove.getTargets())
 		{
 			this.getInternalAdjacencyEdges().get(removeNode).remove(edgeToRemove);
 
-			final List<N> removeAdjacentNodes = new ArrayList<N>(edgeToRemove.getNodes());
+			final List<N> removeAdjacentNodes = new ArrayList<N>(edgeToRemove.getTargets());
 			removeAdjacentNodes.remove(removeNode);
 			for(final N removeAdjacentNode : removeAdjacentNodes)
 				this.getInternalAdjacencyNodes().get(removeNode).remove(removeAdjacentNode);
@@ -147,7 +147,7 @@ public class MutableDynamicGraphicalModelAdjacencyGraph<N extends DynamicGraphic
 		for(final E removeEdge : removeEdges)
 		{
 			E newEdge = (E) removeEdge.disconnect(nodeToRemove);
-			while( (newEdge != null) && (newEdge.getNodes().contains(nodeToRemove)) )
+			while( (newEdge != null) && (newEdge.getTargets().contains(nodeToRemove)) )
 				newEdge = (E) removeEdge.disconnect(nodeToRemove);
 			if( newEdge != null )
 				newEdges.add(newEdge);
@@ -183,7 +183,7 @@ public class MutableDynamicGraphicalModelAdjacencyGraph<N extends DynamicGraphic
 		}
 
 		//now lets remove all the nodes
-		for(N node : this.getNodes())
+		for(N node : this.getTargets())
 		{
 			//lets just make sure we arent some how getting an we dont actually own, this shouldnt be possible so its
 			//an assert. This ensures that if remove() comes back false it must be because the context didnt allow it.
diff --git a/src/main/java/com/syncleus/dann/graphicalmodel/markovrandomfield/AbstractMarkovRandomFieldAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graphicalmodel/markovrandomfield/AbstractMarkovRandomFieldAdjacencyGraph.java
index 829c666584b91cbd313cfaa1a83dacee124b1cc6..4d7ff711d0ab2923cb89a683259bef15d3fc009b 100644
--- a/src/main/java/com/syncleus/dann/graphicalmodel/markovrandomfield/AbstractMarkovRandomFieldAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graphicalmodel/markovrandomfield/AbstractMarkovRandomFieldAdjacencyGraph.java
@@ -32,7 +32,7 @@ public abstract class AbstractMarkovRandomFieldAdjacencyGraph<N extends Graphica
 
 	protected AbstractMarkovRandomFieldAdjacencyGraph(final Graph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 
 	protected AbstractMarkovRandomFieldAdjacencyGraph(final Set<N> nodes, final Set<E> edges)
@@ -45,7 +45,7 @@ public abstract class AbstractMarkovRandomFieldAdjacencyGraph<N extends Graphica
 	{
 		final Set<N> seenNodes = new HashSet<N>();
 		double probabilityProduct = 1.0;
-		for(final N node : this.getNodes())
+		for(final N node : this.getTargets())
 		{
 			assert !seenNodes.contains(node);
 
diff --git a/src/main/java/com/syncleus/dann/graphicalmodel/markovrandomfield/ImmutableMarkovRandomFieldAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graphicalmodel/markovrandomfield/ImmutableMarkovRandomFieldAdjacencyGraph.java
index 98d60051a13dfb76eaad3088591d4ba6a910dbe8..e590dac2604e508245149eb25a0ce89e8b5a6605 100644
--- a/src/main/java/com/syncleus/dann/graphicalmodel/markovrandomfield/ImmutableMarkovRandomFieldAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graphicalmodel/markovrandomfield/ImmutableMarkovRandomFieldAdjacencyGraph.java
@@ -36,7 +36,7 @@ public class ImmutableMarkovRandomFieldAdjacencyGraph<N extends GraphicalModelNo
 	/*
 	public ImmutableMarkovRandomFieldAdjacencyGraph(final Graph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 	*/
 
diff --git a/src/main/java/com/syncleus/dann/graphicalmodel/markovrandomfield/MutableMarkovRandomFieldAdjacencyGraph.java b/src/main/java/com/syncleus/dann/graphicalmodel/markovrandomfield/MutableMarkovRandomFieldAdjacencyGraph.java
index e09b20980f5e4f77a9fefddebfd25809b5d3b59f..aa991db69cab71afb5bd3b848916d2a0b3cef674 100644
--- a/src/main/java/com/syncleus/dann/graphicalmodel/markovrandomfield/MutableMarkovRandomFieldAdjacencyGraph.java
+++ b/src/main/java/com/syncleus/dann/graphicalmodel/markovrandomfield/MutableMarkovRandomFieldAdjacencyGraph.java
@@ -35,7 +35,7 @@ public class MutableMarkovRandomFieldAdjacencyGraph<N extends GraphicalModelNode
 
 	public MutableMarkovRandomFieldAdjacencyGraph(final Graph<N, E> copyGraph)
 	{
-		super(copyGraph.getNodes(), copyGraph.getEdges());
+		super(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 
 	public MutableMarkovRandomFieldAdjacencyGraph(final Set<N> nodes, final Set<E> edges)
@@ -48,7 +48,7 @@ public class MutableMarkovRandomFieldAdjacencyGraph<N extends GraphicalModelNode
 	{
 		if( newEdge == null )
 			throw new IllegalArgumentException("newEdge can not be null");
-		if( !this.getNodes().containsAll(newEdge.getNodes()) )
+		if( !this.getTargets().containsAll(newEdge.getNodes()) )
 			throw new IllegalArgumentException("newEdge has a node as an end point that is not part of the graph");
 
 		// if context is enabled lets check if it can join
@@ -184,7 +184,7 @@ public class MutableMarkovRandomFieldAdjacencyGraph<N extends GraphicalModelNode
 		}
 
 		//now lets remove all the nodes
-		for(N node : this.getNodes())
+		for(N node : this.getTargets())
 		{
 			//lets just make sure we arent some how getting an we dont actually own, this shouldnt be possible so its
 			//an assert. This ensures that if remove() comes back false it must be because the context didnt allow it.
diff --git a/src/main/java/com/syncleus/dann/neural/AbstractActivationNeuron.java b/src/main/java/com/syncleus/dann/neural/AbstractActivationNeuron.java
index ee7d1a68538287bba96fdc02432a3c6a7bdee2b6..bae980d844289f7743fb60c9112b9f381a04b548 100644
--- a/src/main/java/com/syncleus/dann/neural/AbstractActivationNeuron.java
+++ b/src/main/java/com/syncleus/dann/neural/AbstractActivationNeuron.java
@@ -134,15 +134,11 @@ public abstract class AbstractActivationNeuron extends AbstractNeuron
 		//TODO fix this!
 		//calculate the current input activity
 		this.activity = 0;
-//		for(final Synapse currentSynapse : this.getBrain().getInEdges(this))
-//			this.activity += currentSynapse.getInput() * currentSynapse.getWeight();
 		for(final Object currentSynapse : this.getBrain().getInEdges(this))
 			this.activity += ((Synapse)currentSynapse).getInput() * ((Synapse)currentSynapse).getWeight();
 		//calculate the activity function and set the result as the output
 		this.output = this.activate();
-//		for(final Synapse current : this.getBrain().getTraversableEdges(this))
-//			current.setInput(this.output);
-		for(final Object current : this.getBrain().getTraversableEdges(this))
+		for(final Object current : this.getBrain().getTraversableAdjacentEdges(this))
 			((Synapse)current).setInput(this.output);
 	}
 
diff --git a/src/main/java/com/syncleus/dann/neural/AbstractInputNeuron.java b/src/main/java/com/syncleus/dann/neural/AbstractInputNeuron.java
index 57bd77ef5f3beb7d24f0b87e8a072345d067719a..e6028efc193f54d208d677f5617d0719b9bbe301 100644
--- a/src/main/java/com/syncleus/dann/neural/AbstractInputNeuron.java
+++ b/src/main/java/com/syncleus/dann/neural/AbstractInputNeuron.java
@@ -53,9 +53,7 @@ public abstract class AbstractInputNeuron extends AbstractNeuron implements Inpu
 	public void tick()
 	{
 		//TODO fix this, bad typing
-//		for(final Synapse current : this.getBrain().getTraversableEdges(this))
-//			current.setInput(this.input);
-		for(final Object current : this.getBrain().getTraversableEdges(this))
+		for(final Object current : this.getBrain().getTraversableAdjacentEdges(this))
 			((Synapse)current).setInput(this.input);
 	}
 }
diff --git a/src/main/java/com/syncleus/dann/neural/AbstractLocalBrain.java b/src/main/java/com/syncleus/dann/neural/AbstractLocalBrain.java
index 3635ba2613c31adb3bbb7635360077db7b91fde0..f0a8f885c7844387b17db58e1707c2a43d561ec7 100644
--- a/src/main/java/com/syncleus/dann/neural/AbstractLocalBrain.java
+++ b/src/main/java/com/syncleus/dann/neural/AbstractLocalBrain.java
@@ -101,7 +101,7 @@ public abstract class AbstractLocalBrain<IN extends InputNeuron, ON extends Outp
 	{
 		if( newSynapse == null )
 			throw new IllegalArgumentException("newSynapse can not be null");
-		if( !this.neurons.containsAll(newSynapse.getNodes()) )
+		if( !this.neurons.containsAll(newSynapse.getTargets()) )
 			throw new IllegalArgumentException("newSynapse has a node as an end point that is not part of the graph");
 
 		if( this.synapses.add(newSynapse) )
@@ -181,7 +181,7 @@ public abstract class AbstractLocalBrain<IN extends InputNeuron, ON extends Outp
 	}
 
 	/*
-	protected boolean connect(final N source, final N destination, final double initialWeight)
+	protected boolean join(final N source, final N destination, final double initialWeight)
 	{
 		if( source == null )
 			throw new IllegalArgumentException("source can not be null");
@@ -196,7 +196,7 @@ public abstract class AbstractLocalBrain<IN extends InputNeuron, ON extends Outp
 	} */
 	protected boolean connect(final S synapse)
 	{
-		if( !this.neurons.containsAll(synapse.getNodes()) )
+		if( !this.neurons.containsAll(synapse.getTargets()) )
 			throw new IllegalArgumentException("the synapse contains nodes not in this brain");
 
 		return this.add(synapse);
@@ -204,7 +204,7 @@ public abstract class AbstractLocalBrain<IN extends InputNeuron, ON extends Outp
 
 
 	/*
-	protected boolean disconnect(final Neuron source, final Neuron destination)
+	protected boolean leave(final Neuron source, final Neuron destination)
 	{
 		if( source == null )
 			throw new IllegalArgumentException("source can not be null");
@@ -236,7 +236,7 @@ public abstract class AbstractLocalBrain<IN extends InputNeuron, ON extends Outp
 
 	/**
 	 * Removes the specified neuron from the brain. This only removes it from
-	 * the collection of neurons it does not disconnect it from other neurons.
+	 * the collection of neurons it does not leave it from other neurons.
 	 *
 	 * @param removeNeuron The neuron to remove.
 	 * @since 1.0
@@ -297,7 +297,7 @@ public abstract class AbstractLocalBrain<IN extends InputNeuron, ON extends Outp
 	 * @since 1.0
 	 */
 	@Override
-	public Set<N> getNodes()
+	public Set<N> getTargets()
 	{
 		return Collections.unmodifiableSet(this.neurons);
 	}
@@ -320,7 +320,7 @@ public abstract class AbstractLocalBrain<IN extends InputNeuron, ON extends Outp
 	}
 
 	@Override
-	public Set<S> getTraversableEdges(final N node)
+	public Set<S> getTraversableAdjacentEdges(final N node)
 	{
 		if( this.inMap.containsKey(node) )
 			return Collections.unmodifiableSet(this.outMap.get(node));
@@ -338,7 +338,7 @@ public abstract class AbstractLocalBrain<IN extends InputNeuron, ON extends Outp
 	@Override
 	public boolean isStronglyConnected(final N leftNode, final N rightNode)
 	{
-		final Set<S> outSet = this.getTraversableEdges(leftNode);
+		final Set<S> outSet = this.getTraversableAdjacentEdges(leftNode);
 		final Set<S> inSet = this.getInEdges(rightNode);
 		final Set<S> jointSet = new HashSet<S>(outSet);
 		jointSet.retainAll(inSet);
diff --git a/src/main/java/com/syncleus/dann/neural/AbstractStaticNeuron.java b/src/main/java/com/syncleus/dann/neural/AbstractStaticNeuron.java
index ad629e16b0671d88ed8242d18d805c01ba70bcf3..bed8edbb859592fe1ab52c7c56f9ff363bac3293 100644
--- a/src/main/java/com/syncleus/dann/neural/AbstractStaticNeuron.java
+++ b/src/main/java/com/syncleus/dann/neural/AbstractStaticNeuron.java
@@ -33,9 +33,7 @@ public abstract class AbstractStaticNeuron extends AbstractNeuron
 	public void tick()
 	{
 		//TODO fix this, bad typing
-//		for(final Synapse current : this.getBrain().getTraversableEdges(this))
-//			current.setInput(this.output);
-		for(final Object current : this.getBrain().getTraversableEdges(this))
+		for(final Object current : this.getBrain().getTraversableAdjacentEdges(this))
 			((Synapse)current).setInput(this.output);
 	}
 
diff --git a/src/main/java/com/syncleus/dann/neural/Neuron.java b/src/main/java/com/syncleus/dann/neural/Neuron.java
index 52bcce86502ddf4c5f0e4e1f69c2fdfdf74b8ad2..2e8e13a7b12765f50094262cb2b66104b4cdbb3b 100644
--- a/src/main/java/com/syncleus/dann/neural/Neuron.java
+++ b/src/main/java/com/syncleus/dann/neural/Neuron.java
@@ -22,7 +22,7 @@ import java.io.Serializable;
 
 /**
  * Interface representing the general methods common to all types of neurons.
- * All neurons will connect to other neurons as well as be able to disconnect.
+ * All neurons will join to other neurons as well as be able to leave.
  *
  * @author Jeffrey Phillips Freeman
  * @since 1.0
diff --git a/src/main/java/com/syncleus/dann/neural/backprop/AbstractBackpropNeuron.java b/src/main/java/com/syncleus/dann/neural/backprop/AbstractBackpropNeuron.java
index 689782fdfcd4955fcf1d4b61c0ff298c0b842c5d..4412c67c66ab6855124facf8462b616bca2e36ba 100644
--- a/src/main/java/com/syncleus/dann/neural/backprop/AbstractBackpropNeuron.java
+++ b/src/main/java/com/syncleus/dann/neural/backprop/AbstractBackpropNeuron.java
@@ -145,9 +145,9 @@ public abstract class AbstractBackpropNeuron extends AbstractActivationNeuron im
 	{
 		// TODO fix bad typing
 		double newDeltaTrain = 0.0;
-//		for(final Synapse currentSynapse : this.getBrain().getTraversableEdges(this))
+//		for(final Synapse currentSynapse : this.getBrain().getTraversableAdjacentEdges(this))
 //			this.deltaTrain += (currentSynapse.getWeight() * this.deltaTrainDestinations.get(currentSynapse));
-		for(final Object currentSynapse : this.getBrain().getTraversableEdges(this))
+		for(final Object currentSynapse : this.getBrain().getTraversableAdjacentEdges(this))
 			newDeltaTrain += (((Synapse)currentSynapse).getWeight() * this.deltaTrainDestinations.get(currentSynapse));
 		newDeltaTrain *= this.activateDerivitive();
 		setDeltaTrain(newDeltaTrain);
diff --git a/src/main/java/com/syncleus/dann/neural/backprop/AbstractBackpropStaticNeuron.java b/src/main/java/com/syncleus/dann/neural/backprop/AbstractBackpropStaticNeuron.java
index 200a853e7888d26f76dca8d1af739359e2c35ae6..0ae855805e593350b902e9e9e09dccf0be8b50ea 100644
--- a/src/main/java/com/syncleus/dann/neural/backprop/AbstractBackpropStaticNeuron.java
+++ b/src/main/java/com/syncleus/dann/neural/backprop/AbstractBackpropStaticNeuron.java
@@ -36,9 +36,9 @@ public abstract class AbstractBackpropStaticNeuron extends AbstractBackpropNeuro
 	public void tick()
 	{
 		//TODO fix this, bad typing
-//		for(final Synapse current : this.getBrain().getTraversableEdges(this))
+//		for(final Synapse current : this.getBrain().getTraversableAdjacentEdges(this))
 //			current.setInput(this.output);
-		for(final Object current : this.getBrain().getTraversableEdges(this))
+		for(final Object current : this.getBrain().getTraversableAdjacentEdges(this))
 			((Synapse)current).setInput(this.output);
 	}
 
diff --git a/src/main/java/com/syncleus/dann/neural/backprop/AbstractOutputBackpropNeuron.java b/src/main/java/com/syncleus/dann/neural/backprop/AbstractOutputBackpropNeuron.java
index bb417bb364a94726a890db417cc0d3d1e88ee5e2..b39542f7ab73ac242586d84bdec696f4ee64dee6 100644
--- a/src/main/java/com/syncleus/dann/neural/backprop/AbstractOutputBackpropNeuron.java
+++ b/src/main/java/com/syncleus/dann/neural/backprop/AbstractOutputBackpropNeuron.java
@@ -101,9 +101,9 @@ public abstract class AbstractOutputBackpropNeuron extends AbstractBackpropNeuro
 	{
 		double newDeltaTrain = 0.0;
 		// TODO fix this, bad typing
-//		for(final Synapse currentSynapse : super.getBrain().getTraversableEdges(this))
+//		for(final Synapse currentSynapse : super.getBrain().getTraversableAdjacentEdges(this))
 //			this.deltaTrain += (currentSynapse.getWeight() * this.deltaTrainDestinations.get(currentSynapse));
-		for(final Object currentSynapse : super.getBrain().getTraversableEdges(this))
+		for(final Object currentSynapse : super.getBrain().getTraversableAdjacentEdges(this))
 			newDeltaTrain += (((Synapse)currentSynapse).getWeight() * this.getDeltaTrainDestinations().get(currentSynapse));
 		newDeltaTrain += (this.desired - this.getOutput());
 		newDeltaTrain *= super.activateDerivitive();
diff --git a/src/main/java/com/syncleus/dann/neural/backprop/SimpleBackpropNeuron.java b/src/main/java/com/syncleus/dann/neural/backprop/SimpleBackpropNeuron.java
index aa9c94ae6fece1aa82de1da522bd5bea9106bec5..9da610ec4772302990d835f75b4220b893b0c7ed 100644
--- a/src/main/java/com/syncleus/dann/neural/backprop/SimpleBackpropNeuron.java
+++ b/src/main/java/com/syncleus/dann/neural/backprop/SimpleBackpropNeuron.java
@@ -24,7 +24,7 @@ import com.syncleus.dann.neural.activation.ActivationFunction;
 /**
  * The SimpleBackpropNeuron is the most fundamental component of a back-prop
  * network; it is also the processor of the system. One neuron will usually
- * connect to many other Neurons through synapses and receive input from many
+ * join to many other Neurons through synapses and receive input from many
  * other Neurons in the same way.
  *
  * @author Jeffrey Phillips Freeman
diff --git a/src/main/java/com/syncleus/dann/neural/backprop/brain/AbstractFullyConnectedFeedforwardBrain.java b/src/main/java/com/syncleus/dann/neural/backprop/brain/AbstractFullyConnectedFeedforwardBrain.java
index 2bccf1aaf1e90fdcd30a4b12d3d85fdc1953978b..6bbbd9510bc492150a337d3a607f60dd8135da02 100644
--- a/src/main/java/com/syncleus/dann/neural/backprop/brain/AbstractFullyConnectedFeedforwardBrain.java
+++ b/src/main/java/com/syncleus/dann/neural/backprop/brain/AbstractFullyConnectedFeedforwardBrain.java
@@ -73,7 +73,7 @@ public abstract class AbstractFullyConnectedFeedforwardBrain<IN extends InputBac
 		//makse sure the parent has a chance to create the unconnected network.
 		super.initalizeNetwork(neuronsPerLayer);
 
-		//iterate through all layers (except the last) and connect it to the
+		//iterate through all layers (except the last) and join it to the
 		//next layer
 		for(int layerIndex = 0; layerIndex < (this.getLayerCount() - 1); layerIndex++)
 		{
@@ -88,7 +88,7 @@ public abstract class AbstractFullyConnectedFeedforwardBrain<IN extends InputBac
 					this.connect((S) connection, true);
 				}
 		}
-		//create and connect biases
+		//create and join biases
 		for(int layerIndex = 1; layerIndex < this.getLayerCount(); layerIndex++)
 		{
 			for(final N destinationNeuron : this.getEditableLayers().get(layerIndex).getChildrenNeuronsRecursivly())
@@ -101,7 +101,7 @@ public abstract class AbstractFullyConnectedFeedforwardBrain<IN extends InputBac
 					this.getEditableLayers().get(layerIndex - 1).add((N)biasNeuron);
 					//TODO this is bad typing fix this!
 					this.add((N)biasNeuron);
-					//connect the new bias neuron to its destination neuron
+					//join the new bias neuron to its destination neuron
 					//TODO this is bad typing fix this!
 					final Synapse<N> connection = new SimpleSynapse<N>((N)biasNeuron, destinationNeuron);
 					//TODO this is bad typing fix this!
diff --git a/src/main/java/com/syncleus/dann/neural/som/SimpleSomNeuron.java b/src/main/java/com/syncleus/dann/neural/som/SimpleSomNeuron.java
index db24e744385c2f5b8d3f9a430a792023b45904ab..c1193ab5ea4183f28776f298a3c08766dd53739e 100644
--- a/src/main/java/com/syncleus/dann/neural/som/SimpleSomNeuron.java
+++ b/src/main/java/com/syncleus/dann/neural/som/SimpleSomNeuron.java
@@ -83,9 +83,9 @@ public class SimpleSomNeuron extends AbstractNeuron implements SomOutputNeuron
 
 		//calculate the activity function and set the result as the output
 		this.output = this.activationFunction.activate(activity);
-//		for(final Synapse current : this.getBrain().getTraversableEdges(this))
+//		for(final Synapse current : this.getBrain().getTraversableAdjacentEdges(this))
 //			current.setInput(this.output);
-		for(final Object current : this.getBrain().getTraversableEdges(this))
+		for(final Object current : this.getBrain().getTraversableAdjacentEdges(this))
 			((Synapse)current).setInput(this.output);
 	}
 
diff --git a/src/main/java/com/syncleus/dann/neural/som/brain/AbstractSomBrain.java b/src/main/java/com/syncleus/dann/neural/som/brain/AbstractSomBrain.java
index b93aa4315c5aa0f1f699f4e4337e7eb2fa6befc7..31477d13464c4dfc84f6fe9bb9acd641ec58ca00 100644
--- a/src/main/java/com/syncleus/dann/neural/som/brain/AbstractSomBrain.java
+++ b/src/main/java/com/syncleus/dann/neural/som/brain/AbstractSomBrain.java
@@ -196,7 +196,7 @@ public abstract class AbstractSomBrain<IN extends SomInputNeuron, ON extends Som
 		//TODO fix this it is type unsafe
 		this.add((N)outputNeuron);
 
-		//connect all inputs to the new neuron
+		//join all inputs to the new neuron
 		//TODO fix this it is type unsafe
 		for(final InputNeuron input : this.inputs)
 		{
diff --git a/src/main/resources/com.syncleus.dann.graph.xml.xsd b/src/main/resources/com.syncleus.dann.graph.xml.xsd
index f5237857bbc232bb5805d976f23fa16eae203a1c..d820e44b352c20cc6e0062fb114f571da7fa5699 100644
--- a/src/main/resources/com.syncleus.dann.graph.xml.xsd
+++ b/src/main/resources/com.syncleus.dann.graph.xml.xsd
@@ -79,6 +79,9 @@
     </xsd:element>
     <!-- Graph Type, contains references to instanced objects -->
     <xsd:complexType name="Graph">
+        <xsd:complexContent>
+            <xsd:extension base="Edge"/>
+        </xsd:complexContent>
         <xsd:sequence>
             <xsd:element name="nodes" maxOccurs="1">
                 <xsd:complexType>
diff --git a/src/test/java/com/syncleus/dann/graph/cycle/TestColoredDepthFirstSearchDetector.java b/src/test/java/com/syncleus/dann/graph/cycle/TestColoredDepthFirstSearchDetector.java
index f5091ff5d62878806624ab566a9cdd4fa2ff215f..f414364babefaff2c80ec8681055a6d08d4a4bba 100644
--- a/src/test/java/com/syncleus/dann/graph/cycle/TestColoredDepthFirstSearchDetector.java
+++ b/src/test/java/com/syncleus/dann/graph/cycle/TestColoredDepthFirstSearchDetector.java
@@ -38,11 +38,11 @@ public class TestColoredDepthFirstSearchDetector
 		nodes.add(rightNode);
 
 		final Set<DirectedEdge<Object>> edges = new HashSet<DirectedEdge<Object>>();
-		final DirectedEdge<Object> centerTopEdge = new ImmutableDirectedEdge<Object>(centerNode, topNode);
+		final DirectedEdge<Object> centerTopEdge = new SimpleDirectedEdge<Object>(centerNode, topNode);
 		edges.add(centerTopEdge);
-		final DirectedEdge<Object> centerLeftEdge = new ImmutableDirectedEdge<Object>(centerNode, leftNode);
+		final DirectedEdge<Object> centerLeftEdge = new SimpleDirectedEdge<Object>(centerNode, leftNode);
 		edges.add(centerLeftEdge);
-		final DirectedEdge<Object> centerRightEdge = new ImmutableDirectedEdge<Object>(centerNode, rightNode);
+		final DirectedEdge<Object> centerRightEdge = new SimpleDirectedEdge<Object>(centerNode, rightNode);
 		edges.add(centerRightEdge);
 
 		final BidirectedGraph<Object, DirectedEdge<Object>> graph = new ImmutableDirectedAdjacencyGraph<Object, DirectedEdge<Object>>(nodes, edges);
@@ -65,17 +65,17 @@ public class TestColoredDepthFirstSearchDetector
 		nodes.add(rightNode);
 
 		final Set<DirectedEdge<Object>> edges = new HashSet<DirectedEdge<Object>>();
-		final DirectedEdge<Object> centerTopEdge = new ImmutableDirectedEdge<Object>(centerNode, topNode);
+		final DirectedEdge<Object> centerTopEdge = new SimpleDirectedEdge<Object>(centerNode, topNode);
 		edges.add(centerTopEdge);
-		final DirectedEdge<Object> centerLeftEdge = new ImmutableDirectedEdge<Object>(centerNode, leftNode);
+		final DirectedEdge<Object> centerLeftEdge = new SimpleDirectedEdge<Object>(centerNode, leftNode);
 		edges.add(centerLeftEdge);
-		final DirectedEdge<Object> centerRightEdge = new ImmutableDirectedEdge<Object>(centerNode, rightNode);
+		final DirectedEdge<Object> centerRightEdge = new SimpleDirectedEdge<Object>(centerNode, rightNode);
 		edges.add(centerRightEdge);
-		final DirectedEdge<Object> topRightEdge = new ImmutableDirectedEdge<Object>(topNode, rightNode);
+		final DirectedEdge<Object> topRightEdge = new SimpleDirectedEdge<Object>(topNode, rightNode);
 		edges.add(topRightEdge);
-		final DirectedEdge<Object> rightLeftEdge = new ImmutableDirectedEdge<Object>(rightNode, leftNode);
+		final DirectedEdge<Object> rightLeftEdge = new SimpleDirectedEdge<Object>(rightNode, leftNode);
 		edges.add(rightLeftEdge);
-		final DirectedEdge<Object> leftTopEdge = new ImmutableDirectedEdge<Object>(leftNode, topNode);
+		final DirectedEdge<Object> leftTopEdge = new SimpleDirectedEdge<Object>(leftNode, topNode);
 		edges.add(leftTopEdge);
 
 		final BidirectedGraph<Object, DirectedEdge<Object>> graph = new ImmutableDirectedAdjacencyGraph<Object, DirectedEdge<Object>>(nodes, edges);
@@ -98,11 +98,11 @@ public class TestColoredDepthFirstSearchDetector
 		nodes.add(rightNode);
 
 		final Set<BidirectedEdge<Object>> edges = new HashSet<BidirectedEdge<Object>>();
-		final BidirectedEdge<Object> centerTopEdge = new ImmutableUndirectedEdge<Object>(centerNode, topNode);
+		final BidirectedEdge<Object> centerTopEdge = new SimpleUndirectedEdge<Object>(centerNode, topNode);
 		edges.add(centerTopEdge);
-		final BidirectedEdge<Object> centerLeftEdge = new ImmutableUndirectedEdge<Object>(centerNode, leftNode);
+		final BidirectedEdge<Object> centerLeftEdge = new SimpleUndirectedEdge<Object>(centerNode, leftNode);
 		edges.add(centerLeftEdge);
-		final BidirectedEdge<Object> centerRightEdge = new ImmutableUndirectedEdge<Object>(centerNode, rightNode);
+		final BidirectedEdge<Object> centerRightEdge = new SimpleUndirectedEdge<Object>(centerNode, rightNode);
 		edges.add(centerRightEdge);
 
 		final Graph<Object, BidirectedEdge<Object>> graph = new ImmutableAdjacencyGraph<Object, BidirectedEdge<Object>>(nodes, edges);
@@ -125,17 +125,17 @@ public class TestColoredDepthFirstSearchDetector
 		nodes.add(rightNode);
 
 		final Set<BidirectedEdge<Object>> edges = new HashSet<BidirectedEdge<Object>>();
-		final BidirectedEdge<Object> centerTopEdge = new ImmutableUndirectedEdge<Object>(centerNode, topNode);
+		final BidirectedEdge<Object> centerTopEdge = new SimpleUndirectedEdge<Object>(centerNode, topNode);
 		edges.add(centerTopEdge);
-		final BidirectedEdge<Object> centerLeftEdge = new ImmutableUndirectedEdge<Object>(centerNode, leftNode);
+		final BidirectedEdge<Object> centerLeftEdge = new SimpleUndirectedEdge<Object>(centerNode, leftNode);
 		edges.add(centerLeftEdge);
-		final BidirectedEdge<Object> centerRightEdge = new ImmutableUndirectedEdge<Object>(centerNode, rightNode);
+		final BidirectedEdge<Object> centerRightEdge = new SimpleUndirectedEdge<Object>(centerNode, rightNode);
 		edges.add(centerRightEdge);
-		final BidirectedEdge<Object> topRightEdge = new ImmutableUndirectedEdge<Object>(topNode, rightNode);
+		final BidirectedEdge<Object> topRightEdge = new SimpleUndirectedEdge<Object>(topNode, rightNode);
 		edges.add(topRightEdge);
-		final BidirectedEdge<Object> rightLeftEdge = new ImmutableUndirectedEdge<Object>(rightNode, leftNode);
+		final BidirectedEdge<Object> rightLeftEdge = new SimpleUndirectedEdge<Object>(rightNode, leftNode);
 		edges.add(rightLeftEdge);
-		final BidirectedEdge<Object> leftTopEdge = new ImmutableUndirectedEdge<Object>(leftNode, topNode);
+		final BidirectedEdge<Object> leftTopEdge = new SimpleUndirectedEdge<Object>(leftNode, topNode);
 		edges.add(leftTopEdge);
 
 		final Graph<Object, BidirectedEdge<Object>> graph = new ImmutableAdjacencyGraph<Object, BidirectedEdge<Object>>(nodes, edges);
@@ -158,13 +158,13 @@ public class TestColoredDepthFirstSearchDetector
 		nodes.add(rightNode);
 
 		final Set<BidirectedEdge<Object>> edges = new HashSet<BidirectedEdge<Object>>();
-		final BidirectedEdge<Object> centerTopEdge = new ImmutableUndirectedEdge<Object>(centerNode, topNode);
+		final BidirectedEdge<Object> centerTopEdge = new SimpleUndirectedEdge<Object>(centerNode, topNode);
 		edges.add(centerTopEdge);
-		final BidirectedEdge<Object> centerLeftEdge = new ImmutableUndirectedEdge<Object>(centerNode, leftNode);
+		final BidirectedEdge<Object> centerLeftEdge = new SimpleUndirectedEdge<Object>(centerNode, leftNode);
 		edges.add(centerLeftEdge);
-		final BidirectedEdge<Object> centerRightEdge = new ImmutableUndirectedEdge<Object>(centerNode, rightNode);
+		final BidirectedEdge<Object> centerRightEdge = new SimpleUndirectedEdge<Object>(centerNode, rightNode);
 		edges.add(centerRightEdge);
-		final BidirectedEdge<Object> centerRightEdge2 = new ImmutableUndirectedEdge<Object>(centerNode, rightNode);
+		final BidirectedEdge<Object> centerRightEdge2 = new SimpleUndirectedEdge<Object>(centerNode, rightNode);
 		edges.add(centerRightEdge2);
 
 		final Graph<Object, BidirectedEdge<Object>> graph = new ImmutableAdjacencyGraph<Object, BidirectedEdge<Object>>(nodes, edges);
diff --git a/src/test/java/com/syncleus/dann/graph/cycle/TestExhaustiveDepthFirstSearchFinder.java b/src/test/java/com/syncleus/dann/graph/cycle/TestExhaustiveDepthFirstSearchFinder.java
index 6832cf723a9ad0e4dd7d8e17bb2561e1618bc8e2..5dadfc77bd52a7e12a09326506bac919f504e885 100644
--- a/src/test/java/com/syncleus/dann/graph/cycle/TestExhaustiveDepthFirstSearchFinder.java
+++ b/src/test/java/com/syncleus/dann/graph/cycle/TestExhaustiveDepthFirstSearchFinder.java
@@ -39,11 +39,11 @@ public class TestExhaustiveDepthFirstSearchFinder
 		nodes.add(rightNode);
 
 		final Set<DirectedEdge<Object>> edges = new HashSet<DirectedEdge<Object>>();
-		final DirectedEdge<Object> topRightEdge = new ImmutableDirectedEdge<Object>(topNode, rightNode);
+		final DirectedEdge<Object> topRightEdge = new SimpleDirectedEdge<Object>(topNode, rightNode);
 		edges.add(topRightEdge);
-		final DirectedEdge<Object> rightLeftEdge = new ImmutableDirectedEdge<Object>(rightNode, leftNode);
+		final DirectedEdge<Object> rightLeftEdge = new SimpleDirectedEdge<Object>(rightNode, leftNode);
 		edges.add(rightLeftEdge);
-		final DirectedEdge<Object> topLeftEdge = new ImmutableDirectedEdge<Object>(topNode, leftNode);
+		final DirectedEdge<Object> topLeftEdge = new SimpleDirectedEdge<Object>(topNode, leftNode);
 		edges.add(topLeftEdge);
 
 		final BidirectedGraph<Object, DirectedEdge<Object>> graph = new ImmutableDirectedAdjacencyGraph<Object, DirectedEdge<Object>>(nodes, edges);
@@ -71,19 +71,19 @@ public class TestExhaustiveDepthFirstSearchFinder
 		nodes.add(bottomNode);
 
 		final Set<DirectedEdge<Object>> edges = new HashSet<DirectedEdge<Object>>();
-		final DirectedEdge<Object> bottomLeftEdge = new ImmutableDirectedEdge<Object>(bottomNode, leftNode);
+		final DirectedEdge<Object> bottomLeftEdge = new SimpleDirectedEdge<Object>(bottomNode, leftNode);
 		edges.add(bottomLeftEdge);
-		final DirectedEdge<Object> letRightEdge = new ImmutableDirectedEdge<Object>(leftNode, rightNode);
+		final DirectedEdge<Object> letRightEdge = new SimpleDirectedEdge<Object>(leftNode, rightNode);
 		edges.add(letRightEdge);
-		final DirectedEdge<Object> rightBottomEdge = new ImmutableDirectedEdge<Object>(rightNode, bottomNode);
+		final DirectedEdge<Object> rightBottomEdge = new SimpleDirectedEdge<Object>(rightNode, bottomNode);
 		edges.add(rightBottomEdge);
-		final DirectedEdge<Object> leftTopEdge = new ImmutableDirectedEdge<Object>(leftNode, topNode);
+		final DirectedEdge<Object> leftTopEdge = new SimpleDirectedEdge<Object>(leftNode, topNode);
 		edges.add(leftTopEdge);
-		final DirectedEdge<Object> topRightEdge = new ImmutableDirectedEdge<Object>(topNode, rightNode);
+		final DirectedEdge<Object> topRightEdge = new SimpleDirectedEdge<Object>(topNode, rightNode);
 		edges.add(topRightEdge);
-		final DirectedEdge<Object> leftTippyTopEdge = new ImmutableDirectedEdge<Object>(leftNode, tippyTopNode);
+		final DirectedEdge<Object> leftTippyTopEdge = new SimpleDirectedEdge<Object>(leftNode, tippyTopNode);
 		edges.add(leftTippyTopEdge);
-		final DirectedEdge<Object> tippyTopRightEdge = new ImmutableDirectedEdge<Object>(tippyTopNode, rightNode);
+		final DirectedEdge<Object> tippyTopRightEdge = new SimpleDirectedEdge<Object>(tippyTopNode, rightNode);
 		edges.add(tippyTopRightEdge);
 
 		final BidirectedGraph<Object, DirectedEdge<Object>> graph = new ImmutableDirectedAdjacencyGraph<Object, DirectedEdge<Object>>(nodes, edges);
@@ -109,11 +109,11 @@ public class TestExhaustiveDepthFirstSearchFinder
 		nodes.add(rightNode);
 
 		final Set<BidirectedEdge<Object>> edges = new HashSet<BidirectedEdge<Object>>();
-		final BidirectedEdge<Object> centerTopEdge = new ImmutableUndirectedEdge<Object>(centerNode, topNode);
+		final BidirectedEdge<Object> centerTopEdge = new SimpleUndirectedEdge<Object>(centerNode, topNode);
 		edges.add(centerTopEdge);
-		final BidirectedEdge<Object> centerLeftEdge = new ImmutableUndirectedEdge<Object>(centerNode, leftNode);
+		final BidirectedEdge<Object> centerLeftEdge = new SimpleUndirectedEdge<Object>(centerNode, leftNode);
 		edges.add(centerLeftEdge);
-		final BidirectedEdge<Object> centerRightEdge = new ImmutableUndirectedEdge<Object>(centerNode, rightNode);
+		final BidirectedEdge<Object> centerRightEdge = new SimpleUndirectedEdge<Object>(centerNode, rightNode);
 		edges.add(centerRightEdge);
 
 		final Graph<Object, BidirectedEdge<Object>> graph = new ImmutableAdjacencyGraph<Object, BidirectedEdge<Object>>(nodes, edges);
@@ -139,15 +139,15 @@ public class TestExhaustiveDepthFirstSearchFinder
 		nodes.add(rightNode);
 
 		final Set<BidirectedEdge<Object>> edges = new HashSet<BidirectedEdge<Object>>();
-		final BidirectedEdge<Object> rightBottomEdge = new ImmutableUndirectedEdge<Object>(rightNode, bottomNode);
+		final BidirectedEdge<Object> rightBottomEdge = new SimpleUndirectedEdge<Object>(rightNode, bottomNode);
 		edges.add(rightBottomEdge);
-		final BidirectedEdge<Object> bottomLeftEdge = new ImmutableUndirectedEdge<Object>(bottomNode, leftNode);
+		final BidirectedEdge<Object> bottomLeftEdge = new SimpleUndirectedEdge<Object>(bottomNode, leftNode);
 		edges.add(bottomLeftEdge);
-		final BidirectedEdge<Object> topRightEdge = new ImmutableUndirectedEdge<Object>(topNode, rightNode);
+		final BidirectedEdge<Object> topRightEdge = new SimpleUndirectedEdge<Object>(topNode, rightNode);
 		edges.add(topRightEdge);
-		final BidirectedEdge<Object> rightLeftEdge = new ImmutableUndirectedEdge<Object>(rightNode, leftNode);
+		final BidirectedEdge<Object> rightLeftEdge = new SimpleUndirectedEdge<Object>(rightNode, leftNode);
 		edges.add(rightLeftEdge);
-		final BidirectedEdge<Object> leftTopEdge = new ImmutableUndirectedEdge<Object>(leftNode, topNode);
+		final BidirectedEdge<Object> leftTopEdge = new SimpleUndirectedEdge<Object>(leftNode, topNode);
 		edges.add(leftTopEdge);
 
 		final Graph<Object, BidirectedEdge<Object>> graph = new ImmutableAdjacencyGraph<Object, BidirectedEdge<Object>>(nodes, edges);
@@ -173,13 +173,13 @@ public class TestExhaustiveDepthFirstSearchFinder
 		nodes.add(rightNode);
 
 		final Set<BidirectedEdge<Object>> edges = new HashSet<BidirectedEdge<Object>>();
-		final BidirectedEdge<Object> centerTopEdge = new ImmutableUndirectedEdge<Object>(centerNode, topNode);
+		final BidirectedEdge<Object> centerTopEdge = new SimpleUndirectedEdge<Object>(centerNode, topNode);
 		edges.add(centerTopEdge);
-		final BidirectedEdge<Object> centerLeftEdge = new ImmutableUndirectedEdge<Object>(centerNode, leftNode);
+		final BidirectedEdge<Object> centerLeftEdge = new SimpleUndirectedEdge<Object>(centerNode, leftNode);
 		edges.add(centerLeftEdge);
-		final BidirectedEdge<Object> centerRightEdge = new ImmutableUndirectedEdge<Object>(centerNode, rightNode);
+		final BidirectedEdge<Object> centerRightEdge = new SimpleUndirectedEdge<Object>(centerNode, rightNode);
 		edges.add(centerRightEdge);
-		final BidirectedEdge<Object> centerRightEdge2 = new ImmutableUndirectedEdge<Object>(centerNode, rightNode);
+		final BidirectedEdge<Object> centerRightEdge2 = new SimpleUndirectedEdge<Object>(centerNode, rightNode);
 		edges.add(centerRightEdge2);
 
 		final Graph<Object, BidirectedEdge<Object>> graph = new ImmutableAdjacencyGraph<Object, BidirectedEdge<Object>>(nodes, edges);
diff --git a/src/test/java/com/syncleus/dann/graph/drawing/hyperassociativemap/SimpleUndirectedGraph.java b/src/test/java/com/syncleus/dann/graph/drawing/hyperassociativemap/SimpleUndirectedGraph.java
index cd389793f317fa5093be33ca65dbdd435ec0b02f..d6a4569f063bc74b68340326ef87540e64b12e7a 100644
--- a/src/test/java/com/syncleus/dann/graph/drawing/hyperassociativemap/SimpleUndirectedGraph.java
+++ b/src/test/java/com/syncleus/dann/graph/drawing/hyperassociativemap/SimpleUndirectedGraph.java
@@ -45,13 +45,13 @@ public class SimpleUndirectedGraph extends AbstractBidirectedAdjacencyGraph<Simp
 				this.neighborNodes.put(this.nodes[layerIndex][nodeIndex], new ArrayList<SimpleNode>());
 			}
 		}
-		//connect nodes
+		//join nodes
 		for(int layerIndex = 0; layerIndex < (layers - 1); layerIndex++)
 			for(int nodeIndex = 0; nodeIndex < nodesPerLayer; nodeIndex++)
 			{
 				for(int nodeIndex2 = 0; nodeIndex2 < nodesPerLayer; nodeIndex2++)
 				{
-					final ImmutableUndirectedEdge<SimpleNode> newEdge = new ImmutableUndirectedEdge<SimpleNode>(this.nodes[layerIndex][nodeIndex], this.nodes[layerIndex + 1][nodeIndex2]);
+					final SimpleUndirectedEdge<SimpleNode> newEdge = new SimpleUndirectedEdge<SimpleNode>(this.nodes[layerIndex][nodeIndex], this.nodes[layerIndex + 1][nodeIndex2]);
 					this.edges.add(newEdge);
 					this.neighborEdges.get(this.nodes[layerIndex][nodeIndex]).add(newEdge);
 					this.neighborNodes.get(this.nodes[layerIndex][nodeIndex]).add(this.nodes[layerIndex + 1][nodeIndex2]);
@@ -73,7 +73,7 @@ public class SimpleUndirectedGraph extends AbstractBidirectedAdjacencyGraph<Simp
 		return this.nodes[layer][index];
 	}
 
-	public Set<SimpleNode> getNodes()
+	public Set<SimpleNode> getTargets()
 	{
 		return Collections.unmodifiableSet(this.nodeSet);
 	}
@@ -101,7 +101,7 @@ public class SimpleUndirectedGraph extends AbstractBidirectedAdjacencyGraph<Simp
 
 	public int getOutdegree(final SimpleNode node)
 	{
-		return this.getTraversableEdges(node).size();
+		return this.getTraversableAdjacentEdges(node).size();
 	}
 
 	public List<SimpleNode> getAdjacentNodes(final SimpleNode node)
diff --git a/src/test/java/com/syncleus/dann/graph/drawing/hyperassociativemap/TestHyperassociativeMap.java b/src/test/java/com/syncleus/dann/graph/drawing/hyperassociativemap/TestHyperassociativeMap.java
index 777ea0d96da653e219ee419935e7b5fe33566e8c..12ab62dab4d89dc2844d237863f323ea32d948a4 100644
--- a/src/test/java/com/syncleus/dann/graph/drawing/hyperassociativemap/TestHyperassociativeMap.java
+++ b/src/test/java/com/syncleus/dann/graph/drawing/hyperassociativemap/TestHyperassociativeMap.java
@@ -73,8 +73,8 @@ public class TestHyperassociativeMap
 			testMap = new TestMap(testBrain, 3, executor);
 			testMap.align();
 
-			Assert.assertTrue("neuron1 is not in the map", testMap.getGraph().getNodes().contains(neuron1));
-			Assert.assertTrue("neuron2 is not in the map", testMap.getGraph().getNodes().contains(neuron2));
+			Assert.assertTrue("neuron1 is not in the map", testMap.getGraph().getTargets().contains(neuron1));
+			Assert.assertTrue("neuron2 is not in the map", testMap.getGraph().getTargets().contains(neuron2));
 
 			Assert.assertTrue("neuron1 is not associated to neuron2", testMap.getGraph().getAdjacentNodes(neuron1).contains(neuron2));
 			Assert.assertTrue("neuron2 is not associated to neuron1", testMap.getGraph().getAdjacentNodes(neuron2).contains(neuron1));
diff --git a/src/test/java/com/syncleus/dann/graph/search/DirectedGrid.java b/src/test/java/com/syncleus/dann/graph/search/DirectedGrid.java
index 578129b1d28d5460d1b36d80fd8e0b721c66e26d..a719a124435130275aa2be7143a0690cb7dd0461 100644
--- a/src/test/java/com/syncleus/dann/graph/search/DirectedGrid.java
+++ b/src/test/java/com/syncleus/dann/graph/search/DirectedGrid.java
@@ -46,36 +46,36 @@ public class DirectedGrid extends AbstractBidirectedAdjacencyGraph<GridNode, Dir
 				this.outNeighborEdges.put(this.nodes[y][x], new HashSet<DirectedEdge<GridNode>>());
 				this.outNeighborNodes.put(this.nodes[y][x], new HashSet<GridNode>());
 			}
-		//connect nodes
+		//join nodes
 		for(int y = 0; y < nodes.length; y++)
 			for(int x = 0; x < this.nodes[0].length; x++)
 			{
-				//connect to the right
+				//join to the right
 				if( x < this.nodes[0].length - 1 )
 				{
-					ImmutableDirectedEdge<GridNode> newEdge = new ImmutableDirectedEdge<GridNode>(this.nodes[y][x], this.nodes[y][x + 1]);
+					SimpleDirectedEdge<GridNode> newEdge = new SimpleDirectedEdge<GridNode>(this.nodes[y][x], this.nodes[y][x + 1]);
 					this.edges.add(newEdge);
 					this.outNeighborEdges.get(this.nodes[y][x]).add(newEdge);
 					this.inNeighborEdges.get(this.nodes[y][x + 1]).add(newEdge);
 					this.outNeighborNodes.get(this.nodes[y][x]).add(this.nodes[y][x + 1]);
 					this.inNeighborNodes.get(this.nodes[y][x + 1]).add(this.nodes[y][x]);
-					newEdge = new ImmutableDirectedEdge<GridNode>(this.nodes[y][x + 1], this.nodes[y][x]);
+					newEdge = new SimpleDirectedEdge<GridNode>(this.nodes[y][x + 1], this.nodes[y][x]);
 					this.edges.add(newEdge);
 					this.inNeighborEdges.get(this.nodes[y][x]).add(newEdge);
 					this.outNeighborEdges.get(this.nodes[y][x + 1]).add(newEdge);
 					this.inNeighborNodes.get(this.nodes[y][x]).add(this.nodes[y][x + 1]);
 					this.outNeighborNodes.get(this.nodes[y][x + 1]).add(this.nodes[y][x]);
 				}
-				//connect to the bottom
+				//join to the bottom
 				if( y < nodes.length - 1 )
 				{
-					ImmutableDirectedEdge<GridNode> newEdge = new ImmutableDirectedEdge<GridNode>(this.nodes[y][x], this.nodes[y + 1][x]);
+					SimpleDirectedEdge<GridNode> newEdge = new SimpleDirectedEdge<GridNode>(this.nodes[y][x], this.nodes[y + 1][x]);
 					this.edges.add(newEdge);
 					this.outNeighborEdges.get(this.nodes[y][x]).add(newEdge);
 					this.inNeighborEdges.get(this.nodes[y + 1][x]).add(newEdge);
 					this.outNeighborNodes.get(this.nodes[y][x]).add(this.nodes[y + 1][x]);
 					this.inNeighborNodes.get(this.nodes[y + 1][x]).add(this.nodes[y][x]);
-					newEdge = new ImmutableDirectedEdge<GridNode>(this.nodes[y + 1][x], this.nodes[y][x]);
+					newEdge = new SimpleDirectedEdge<GridNode>(this.nodes[y + 1][x], this.nodes[y][x]);
 					this.edges.add(newEdge);
 					this.inNeighborEdges.get(this.nodes[y][x]).add(newEdge);
 					this.outNeighborEdges.get(this.nodes[y + 1][x]).add(newEdge);
@@ -92,7 +92,7 @@ public class DirectedGrid extends AbstractBidirectedAdjacencyGraph<GridNode, Dir
 		return this.nodes[y][x];
 	}
 
-	public Set<GridNode> getNodes()
+	public Set<GridNode> getTargets()
 	{
 		return Collections.unmodifiableSet(this.nodeSet);
 	}
@@ -110,7 +110,7 @@ public class DirectedGrid extends AbstractBidirectedAdjacencyGraph<GridNode, Dir
 		return Collections.unmodifiableSet(newEdges);
 	}
 
-	public Set<DirectedEdge<GridNode>> getTraversableEdges(final GridNode node)
+	public Set<DirectedEdge<GridNode>> getTraversableAdjacentEdges(final GridNode node)
 	{
 		final Set<DirectedEdge<GridNode>> newEdges = new HashSet<DirectedEdge<GridNode>>(this.outNeighborEdges.get(node));
 		return Collections.unmodifiableSet(newEdges);
@@ -118,7 +118,7 @@ public class DirectedGrid extends AbstractBidirectedAdjacencyGraph<GridNode, Dir
 
 	public Set<DirectedEdge<GridNode>> getOutEdges(final GridNode node)
 	{
-		return this.getTraversableEdges(node);
+		return this.getTraversableAdjacentEdges(node);
 	}
 
 	public Set<DirectedEdge<GridNode>> getInEdges(final GridNode node)
@@ -149,7 +149,7 @@ public class DirectedGrid extends AbstractBidirectedAdjacencyGraph<GridNode, Dir
 		return Collections.unmodifiableList(newNeighbors);
 	}
 
-	public List<GridNode> getTraversableNodes(final GridNode node)
+	public List<GridNode> getTraversableAdjacentNodes(final GridNode node)
 	{
 		final ArrayList<GridNode> newNeighbors = new ArrayList<GridNode>(this.outNeighborNodes.get(node));
 		return Collections.unmodifiableList(newNeighbors);
diff --git a/src/test/java/com/syncleus/dann/graph/search/Grid.java b/src/test/java/com/syncleus/dann/graph/search/Grid.java
index b6e27af6a47e13b75600efa2b1ed4249a31832b5..36c79878d01a085145ce16f6a324b363ffadc1a6 100644
--- a/src/test/java/com/syncleus/dann/graph/search/Grid.java
+++ b/src/test/java/com/syncleus/dann/graph/search/Grid.java
@@ -42,24 +42,24 @@ public class Grid extends AbstractBidirectedAdjacencyGraph<GridNode, BidirectedE
 				this.neighborEdges.put(this.nodes[y][x], new HashSet<BidirectedEdge<GridNode>>());
 				this.neighborNodes.put(this.nodes[y][x], new HashSet<GridNode>());
 			}
-		//connect nodes
+		//join nodes
 		for(int y = 0; y < nodes.length; y++)
 			for(int x = 0; x < this.nodes[0].length; x++)
 			{
-				//connect to the right
+				//join to the right
 				if( x < this.nodes[0].length - 1 )
 				{
-					final ImmutableUndirectedEdge<GridNode> newEdge = new ImmutableUndirectedEdge<GridNode>(this.nodes[y][x], this.nodes[y][x + 1]);
+					final SimpleUndirectedEdge<GridNode> newEdge = new SimpleUndirectedEdge<GridNode>(this.nodes[y][x], this.nodes[y][x + 1]);
 					this.edges.add(newEdge);
 					this.neighborEdges.get(this.nodes[y][x]).add(newEdge);
 					this.neighborEdges.get(this.nodes[y][x + 1]).add(newEdge);
 					this.neighborNodes.get(this.nodes[y][x]).add(this.nodes[y][x + 1]);
 					this.neighborNodes.get(this.nodes[y][x + 1]).add(this.nodes[y][x]);
 				}
-				//connect to the bottom
+				//join to the bottom
 				if( y < nodes.length - 1 )
 				{
-					final ImmutableUndirectedEdge<GridNode> newEdge = new ImmutableUndirectedEdge<GridNode>(this.nodes[y][x], this.nodes[y + 1][x]);
+					final SimpleUndirectedEdge<GridNode> newEdge = new SimpleUndirectedEdge<GridNode>(this.nodes[y][x], this.nodes[y + 1][x]);
 					this.edges.add(newEdge);
 					this.neighborEdges.get(this.nodes[y][x]).add(newEdge);
 					this.neighborEdges.get(this.nodes[y + 1][x]).add(newEdge);
@@ -76,7 +76,7 @@ public class Grid extends AbstractBidirectedAdjacencyGraph<GridNode, BidirectedE
 		return this.nodes[y][x];
 	}
 
-	public Set<GridNode> getNodes()
+	public Set<GridNode> getTargets()
 	{
 		return Collections.unmodifiableSet(this.nodeSet);
 	}
@@ -92,7 +92,7 @@ public class Grid extends AbstractBidirectedAdjacencyGraph<GridNode, BidirectedE
 		return Collections.unmodifiableSet(this.neighborEdges.get(node));
 	}
 
-	public Set<BidirectedEdge<GridNode>> getTraversableEdges(final GridNode node)
+	public Set<BidirectedEdge<GridNode>> getTraversableAdjacentEdges(final GridNode node)
 	{
 		return this.getAdjacentEdges(node);
 	}
@@ -127,7 +127,7 @@ public class Grid extends AbstractBidirectedAdjacencyGraph<GridNode, BidirectedE
 		return Collections.unmodifiableList(new ArrayList<GridNode>(this.neighborNodes.get(node)));
 	}
 
-	public List<GridNode> getTraversableNodes(final GridNode node)
+	public List<GridNode> getTraversableAdjacentNodes(final GridNode node)
 	{
 		return this.getAdjacentNodes(node);
 	}
diff --git a/src/test/java/com/syncleus/dann/graph/search/WeightedDirectedGrid.java b/src/test/java/com/syncleus/dann/graph/search/WeightedDirectedGrid.java
index cda6f079f84be0b598f304d3d7b2ed37746532b0..72e1d392a9fe6481501e4625b91dfee7a9931de2 100644
--- a/src/test/java/com/syncleus/dann/graph/search/WeightedDirectedGrid.java
+++ b/src/test/java/com/syncleus/dann/graph/search/WeightedDirectedGrid.java
@@ -46,11 +46,11 @@ public class WeightedDirectedGrid extends AbstractBidirectedAdjacencyGraph<GridN
 				this.outNeighborEdges.put(this.nodes[y][x], new HashSet<WeightedDirectedEdge<GridNode>>());
 				this.outNeighborNodes.put(this.nodes[y][x], new HashSet<GridNode>());
 			}
-		//connect nodes
+		//join nodes
 		for(int y = 0; y < nodes.length; y++)
 			for(int x = 0; x < this.nodes[0].length; x++)
 			{
-				//connect to the right
+				//join to the right
 				if( x < this.nodes[0].length - 1 )
 				{
 					SimpleWeightedDirectedEdge<GridNode> newEdge = new SimpleWeightedDirectedEdge<GridNode>(this.nodes[y][x], this.nodes[y][x + 1], this.nodes[y][x + 1].getWeight());
@@ -66,7 +66,7 @@ public class WeightedDirectedGrid extends AbstractBidirectedAdjacencyGraph<GridN
 					this.inNeighborNodes.get(this.nodes[y][x]).add(this.nodes[y][x + 1]);
 					this.outNeighborNodes.get(this.nodes[y][x + 1]).add(this.nodes[y][x]);
 				}
-				//connect to the bottom
+				//join to the bottom
 				if( y < nodes.length - 1 )
 				{
 					SimpleWeightedDirectedEdge<GridNode> newEdge = new SimpleWeightedDirectedEdge<GridNode>(this.nodes[y][x], this.nodes[y + 1][x], this.nodes[y + 1][x].getWeight());
@@ -92,7 +92,7 @@ public class WeightedDirectedGrid extends AbstractBidirectedAdjacencyGraph<GridN
 		return this.nodes[y][x];
 	}
 
-	public Set<GridNode> getNodes()
+	public Set<GridNode> getTargets()
 	{
 		return Collections.unmodifiableSet(this.nodeSet);
 	}
@@ -110,7 +110,7 @@ public class WeightedDirectedGrid extends AbstractBidirectedAdjacencyGraph<GridN
 		return Collections.unmodifiableSet(newEdges);
 	}
 
-	public Set<WeightedDirectedEdge<GridNode>> getTraversableEdges(final GridNode node)
+	public Set<WeightedDirectedEdge<GridNode>> getTraversableAdjacentEdges(final GridNode node)
 	{
 		final Set<WeightedDirectedEdge<GridNode>> newEdges = new HashSet<WeightedDirectedEdge<GridNode>>(this.outNeighborEdges.get(node));
 		return Collections.unmodifiableSet(newEdges);
@@ -118,7 +118,7 @@ public class WeightedDirectedGrid extends AbstractBidirectedAdjacencyGraph<GridN
 
 	public Set<WeightedDirectedEdge<GridNode>> getOutEdges(final GridNode node)
 	{
-		return this.getTraversableEdges(node);
+		return this.getTraversableAdjacentEdges(node);
 	}
 
 	public Set<WeightedDirectedEdge<GridNode>> getInEdges(final GridNode node)
@@ -149,7 +149,7 @@ public class WeightedDirectedGrid extends AbstractBidirectedAdjacencyGraph<GridN
 		return Collections.unmodifiableList(newNeighbors);
 	}
 
-	public List<GridNode> getTraversableNodes(final GridNode node)
+	public List<GridNode> getTraversableAdjacentNodes(final GridNode node)
 	{
 		final ArrayList<GridNode> newNeighbors = new ArrayList<GridNode>(this.outNeighborNodes.get(node));
 		return Collections.unmodifiableList(newNeighbors);
diff --git a/src/test/java/com/syncleus/dann/graph/topological/sorter/TestSimpleTopologialSort.java b/src/test/java/com/syncleus/dann/graph/topological/sorter/TestSimpleTopologialSort.java
index 39ddd1f25e87d0bec672db23ecb1e7ea9fc22154..fa84211dbb3233b0b3bce3f327e346ef9cc31f3b 100644
--- a/src/test/java/com/syncleus/dann/graph/topological/sorter/TestSimpleTopologialSort.java
+++ b/src/test/java/com/syncleus/dann/graph/topological/sorter/TestSimpleTopologialSort.java
@@ -40,13 +40,13 @@ public class TestSimpleTopologialSort
 		nodes.add(rightNode);
 
 		final Set<DirectedEdge<Object>> edges = new HashSet<DirectedEdge<Object>>();
-		final DirectedEdge<Object> centerTopEdge = new ImmutableDirectedEdge<Object>(centerNode, topNode);
+		final DirectedEdge<Object> centerTopEdge = new SimpleDirectedEdge<Object>(centerNode, topNode);
 		edges.add(centerTopEdge);
-		final DirectedEdge<Object> centerLeftEdge = new ImmutableDirectedEdge<Object>(centerNode, leftNode);
+		final DirectedEdge<Object> centerLeftEdge = new SimpleDirectedEdge<Object>(centerNode, leftNode);
 		edges.add(centerLeftEdge);
-		final DirectedEdge<Object> leftLeftiestEdge = new ImmutableDirectedEdge<Object>(leftNode, leftiestNode);
+		final DirectedEdge<Object> leftLeftiestEdge = new SimpleDirectedEdge<Object>(leftNode, leftiestNode);
 		edges.add(leftLeftiestEdge);
-		final DirectedEdge<Object> centerRightEdge = new ImmutableDirectedEdge<Object>(centerNode, rightNode);
+		final DirectedEdge<Object> centerRightEdge = new SimpleDirectedEdge<Object>(centerNode, rightNode);
 		edges.add(centerRightEdge);
 
 		final BidirectedGraph<Object, DirectedEdge<Object>> graph = new ImmutableDirectedAdjacencyGraph<Object, DirectedEdge<Object>>(nodes, edges);
diff --git a/src/test/java/com/syncleus/dann/graph/tree/mst/LinkedGraph.java b/src/test/java/com/syncleus/dann/graph/tree/mst/LinkedGraph.java
index eaa2189d2af5f8492d19530f4615207b293b9554..936e2a427d45329ccc8bbe0c1c3b2c63a0b82075 100644
--- a/src/test/java/com/syncleus/dann/graph/tree/mst/LinkedGraph.java
+++ b/src/test/java/com/syncleus/dann/graph/tree/mst/LinkedGraph.java
@@ -31,7 +31,7 @@ public class LinkedGraph<N, E extends Edge<N>> extends AbstractAdjacencyGraph<N,
 
 	public LinkedGraph(final Graph<N, E> copyGraph)
 	{
-		this(copyGraph.getNodes(), copyGraph.getEdges());
+		this(copyGraph.getTargets(), copyGraph.getEdges());
 	}
 
 	public LinkedGraph(final Set<N> nodes, final Set<E> edges)
@@ -40,7 +40,7 @@ public class LinkedGraph<N, E extends Edge<N>> extends AbstractAdjacencyGraph<N,
 		this.edges = new LinkedHashSet<E>(edges);
 		for(final E edge : edges)
 		{
-			final List<N> edgeNodes = edge.getNodes();
+			final List<N> edgeNodes = edge.getTargets();
 			for(int startNodeIndex = 0; startNodeIndex < edgeNodes.size(); startNodeIndex++)
 			{
 				if( !this.nodes.contains(edgeNodes.get(startNodeIndex)) )
@@ -72,7 +72,7 @@ public class LinkedGraph<N, E extends Edge<N>> extends AbstractAdjacencyGraph<N,
 		}
 	}
 
-	public Set<N> getNodes()
+	public Set<N> getTargets()
 	{
 		return Collections.unmodifiableSet(this.nodes);
 	}
diff --git a/src/test/java/com/syncleus/dann/graph/tree/mst/TestKruskalMinimumSpanningTreeFinder.java b/src/test/java/com/syncleus/dann/graph/tree/mst/TestKruskalMinimumSpanningTreeFinder.java
index 4bec6f04a93e50dbcc4cc07314f160f93608ba13..c72a19100a336a5cec8069408dc88b1633fddc99 100644
--- a/src/test/java/com/syncleus/dann/graph/tree/mst/TestKruskalMinimumSpanningTreeFinder.java
+++ b/src/test/java/com/syncleus/dann/graph/tree/mst/TestKruskalMinimumSpanningTreeFinder.java
@@ -44,24 +44,24 @@ public class TestKruskalMinimumSpanningTreeFinder
 		nodes.add(rightNode);
 
 		final Set<BidirectedEdge<Object>> edges = new HashSet<BidirectedEdge<Object>>();
-		final BidirectedEdge<Object> centerTopEdge = new ImmutableUndirectedEdge<Object>(centerNode, topNode);
+		final BidirectedEdge<Object> centerTopEdge = new SimpleUndirectedEdge<Object>(centerNode, topNode);
 		edges.add(centerTopEdge);
-		final BidirectedEdge<Object> centerLeftEdge = new ImmutableUndirectedEdge<Object>(centerNode, leftNode);
+		final BidirectedEdge<Object> centerLeftEdge = new SimpleUndirectedEdge<Object>(centerNode, leftNode);
 		edges.add(centerLeftEdge);
-		final BidirectedEdge<Object> centerRightEdge = new ImmutableUndirectedEdge<Object>(centerNode, rightNode);
+		final BidirectedEdge<Object> centerRightEdge = new SimpleUndirectedEdge<Object>(centerNode, rightNode);
 		edges.add(centerRightEdge);
-		final BidirectedEdge<Object> topRightEdge = new ImmutableUndirectedEdge<Object>(topNode, rightNode);
+		final BidirectedEdge<Object> topRightEdge = new SimpleUndirectedEdge<Object>(topNode, rightNode);
 		edges.add(topRightEdge);
-		final BidirectedEdge<Object> rightLeftEdge = new ImmutableUndirectedEdge<Object>(rightNode, leftNode);
+		final BidirectedEdge<Object> rightLeftEdge = new SimpleUndirectedEdge<Object>(rightNode, leftNode);
 		edges.add(rightLeftEdge);
-		final BidirectedEdge<Object> leftTopEdge = new ImmutableUndirectedEdge<Object>(leftNode, topNode);
+		final BidirectedEdge<Object> leftTopEdge = new SimpleUndirectedEdge<Object>(leftNode, topNode);
 		edges.add(leftTopEdge);
 
 		final Graph<Object, BidirectedEdge<Object>> graph = new ImmutableAdjacencyGraph<Object, BidirectedEdge<Object>>(nodes, edges);
 
 		final MinimumSpanningTreeFinder<Object, BidirectedEdge<Object>> finder = new KruskalMinimumSpanningTreeFinder<Object, BidirectedEdge<Object>>();
 		final Set<BidirectedEdge<Object>> mstEdges = finder.findMinimumSpanningTree(graph);
-		final TreeGraph<Object, BidirectedEdge<Object>> mst = new ImmutableTreeAdjacencyGraph<Object, BidirectedEdge<Object>>(graph.getNodes(), mstEdges);
+		final TreeGraph<Object, BidirectedEdge<Object>> mst = new ImmutableTreeAdjacencyGraph<Object, BidirectedEdge<Object>>(graph.getTargets(), mstEdges);
 
 		LOGGER.info("mst edges:");
 		for(final Edge edge : mst.getEdges())
@@ -70,11 +70,11 @@ public class TestKruskalMinimumSpanningTreeFinder
 		final CycleDetector detector = new ColoredDepthFirstSearchDetector();
 		LOGGER.info("mst is cyclic: " + detector.hasCycle(mst));
 		LOGGER.info("mst is connected: " + Topography.isStronglyConnected(mst));
-		LOGGER.info("mst is contains all nodes: " + mst.getNodes().containsAll(graph.getNodes()));
+		LOGGER.info("mst is contains all nodes: " + mst.getTargets().containsAll(graph.getTargets()));
 
 		Assert.assertTrue("mst was not acyclic", !detector.hasCycle(mst));
 		Assert.assertTrue("mst was not connected", Topography.isStronglyConnected(mst));
-		Assert.assertTrue("mst did not contain all the nodes of the paret graph", mst.getNodes().containsAll(graph.getNodes()));
+		Assert.assertTrue("mst did not contain all the nodes of the paret graph", mst.getTargets().containsAll(graph.getTargets()));
 	}
 
 	@Test
@@ -91,24 +91,24 @@ public class TestKruskalMinimumSpanningTreeFinder
 		nodes.add(rightNode);
 
 		final Set<BidirectedEdge<Object>> edges = new LinkedHashSet<BidirectedEdge<Object>>();
-		final BidirectedEdge<Object> centerRightEdge = new ImmutableUndirectedEdge<Object>(centerNode, rightNode);
+		final BidirectedEdge<Object> centerRightEdge = new SimpleUndirectedEdge<Object>(centerNode, rightNode);
 		edges.add(centerRightEdge);
-		final BidirectedEdge<Object> rightLeftEdge = new ImmutableUndirectedEdge<Object>(rightNode, leftNode);
+		final BidirectedEdge<Object> rightLeftEdge = new SimpleUndirectedEdge<Object>(rightNode, leftNode);
 		edges.add(rightLeftEdge);
-		final BidirectedEdge<Object> topRightEdge = new ImmutableUndirectedEdge<Object>(topNode, rightNode);
+		final BidirectedEdge<Object> topRightEdge = new SimpleUndirectedEdge<Object>(topNode, rightNode);
 		edges.add(topRightEdge);
-		final BidirectedEdge<Object> centerTopEdge = new ImmutableUndirectedEdge<Object>(centerNode, topNode);
+		final BidirectedEdge<Object> centerTopEdge = new SimpleUndirectedEdge<Object>(centerNode, topNode);
 		edges.add(centerTopEdge);
-		final BidirectedEdge<Object> centerLeftEdge = new ImmutableUndirectedEdge<Object>(centerNode, leftNode);
+		final BidirectedEdge<Object> centerLeftEdge = new SimpleUndirectedEdge<Object>(centerNode, leftNode);
 		edges.add(centerLeftEdge);
-		final BidirectedEdge<Object> leftTopEdge = new ImmutableUndirectedEdge<Object>(leftNode, topNode);
+		final BidirectedEdge<Object> leftTopEdge = new SimpleUndirectedEdge<Object>(leftNode, topNode);
 		edges.add(leftTopEdge);
 
 		final Graph<Object, BidirectedEdge<Object>> graph = new LinkedGraph<Object, BidirectedEdge<Object>>(nodes, edges);
 
 		final MinimumSpanningTreeFinder<Object, BidirectedEdge<Object>> finder = new KruskalMinimumSpanningTreeFinder<Object, BidirectedEdge<Object>>();
 		final Set<BidirectedEdge<Object>> mstEdges = finder.findMinimumSpanningTree(graph);
-		final TreeGraph<Object, BidirectedEdge<Object>> mst = new ImmutableTreeAdjacencyGraph<Object, BidirectedEdge<Object>>(graph.getNodes(), mstEdges);
+		final TreeGraph<Object, BidirectedEdge<Object>> mst = new ImmutableTreeAdjacencyGraph<Object, BidirectedEdge<Object>>(graph.getTargets(), mstEdges);
 
 		LOGGER.info("Linkedgraph objects:");
 		for(final Object node : nodes)
@@ -124,10 +124,10 @@ public class TestKruskalMinimumSpanningTreeFinder
 		final CycleDetector detector = new ColoredDepthFirstSearchDetector();
 		LOGGER.info("Linked mst is cyclic: " + detector.hasCycle(mst));
 		LOGGER.info("Linked mst is connected: " + Topography.isStronglyConnected(mst));
-		LOGGER.info("Linked mst is contains all nodes: " + mst.getNodes().containsAll(graph.getNodes()));
+		LOGGER.info("Linked mst is contains all nodes: " + mst.getTargets().containsAll(graph.getTargets()));
 
 		Assert.assertTrue("Linked mst was not acyclic", !detector.hasCycle(mst));
 		Assert.assertTrue("Linked mst was not connected", Topography.isStronglyConnected(mst));
-		Assert.assertTrue("Linked mst did not contain all the nodes of the paret graph", mst.getNodes().containsAll(graph.getNodes()));
+		Assert.assertTrue("Linked mst did not contain all the nodes of the paret graph", mst.getTargets().containsAll(graph.getTargets()));
 	}
 }
diff --git a/src/test/java/com/syncleus/dann/graph/tree/mst/TestPrimMinimumSpanningTreeFinder.java b/src/test/java/com/syncleus/dann/graph/tree/mst/TestPrimMinimumSpanningTreeFinder.java
index caca33e8cdba6018ae0165dc3ac0ac54e5c6c503..070490735660c13d70aadeb15a55b2f858936204 100644
--- a/src/test/java/com/syncleus/dann/graph/tree/mst/TestPrimMinimumSpanningTreeFinder.java
+++ b/src/test/java/com/syncleus/dann/graph/tree/mst/TestPrimMinimumSpanningTreeFinder.java
@@ -44,24 +44,24 @@ public class TestPrimMinimumSpanningTreeFinder
 		nodes.add(rightNode);
 
 		final Set<BidirectedEdge<Object>> edges = new HashSet<BidirectedEdge<Object>>();
-		final BidirectedEdge<Object> centerTopEdge = new ImmutableUndirectedEdge<Object>(centerNode, topNode);
+		final BidirectedEdge<Object> centerTopEdge = new SimpleUndirectedEdge<Object>(centerNode, topNode);
 		edges.add(centerTopEdge);
-		final BidirectedEdge<Object> centerLeftEdge = new ImmutableUndirectedEdge<Object>(centerNode, leftNode);
+		final BidirectedEdge<Object> centerLeftEdge = new SimpleUndirectedEdge<Object>(centerNode, leftNode);
 		edges.add(centerLeftEdge);
-		final BidirectedEdge<Object> centerRightEdge = new ImmutableUndirectedEdge<Object>(centerNode, rightNode);
+		final BidirectedEdge<Object> centerRightEdge = new SimpleUndirectedEdge<Object>(centerNode, rightNode);
 		edges.add(centerRightEdge);
-		final BidirectedEdge<Object> topRightEdge = new ImmutableUndirectedEdge<Object>(topNode, rightNode);
+		final BidirectedEdge<Object> topRightEdge = new SimpleUndirectedEdge<Object>(topNode, rightNode);
 		edges.add(topRightEdge);
-		final BidirectedEdge<Object> rightLeftEdge = new ImmutableUndirectedEdge<Object>(rightNode, leftNode);
+		final BidirectedEdge<Object> rightLeftEdge = new SimpleUndirectedEdge<Object>(rightNode, leftNode);
 		edges.add(rightLeftEdge);
-		final BidirectedEdge<Object> leftTopEdge = new ImmutableUndirectedEdge<Object>(leftNode, topNode);
+		final BidirectedEdge<Object> leftTopEdge = new SimpleUndirectedEdge<Object>(leftNode, topNode);
 		edges.add(leftTopEdge);
 
 		final Graph<Object, BidirectedEdge<Object>> graph = new ImmutableAdjacencyGraph<Object, BidirectedEdge<Object>>(nodes, edges);
 
 		final RootedMinimumSpanningTreeFinder<Object, BidirectedEdge<Object>> finder = new PrimMinimumSpanningTreeFinder<Object, BidirectedEdge<Object>>();
 		final Set<BidirectedEdge<Object>> mstEdges = finder.findMinimumSpanningTree(graph);
-		final TreeGraph<Object, BidirectedEdge<Object>> mst = new ImmutableTreeAdjacencyGraph<Object, BidirectedEdge<Object>>(graph.getNodes(), mstEdges);
+		final TreeGraph<Object, BidirectedEdge<Object>> mst = new ImmutableTreeAdjacencyGraph<Object, BidirectedEdge<Object>>(graph.getTargets(), mstEdges);
 
 		LOGGER.info("mst edges:");
 		for(final Edge edge : mst.getEdges())
@@ -70,10 +70,10 @@ public class TestPrimMinimumSpanningTreeFinder
 		final CycleDetector detector = new ColoredDepthFirstSearchDetector();
 		LOGGER.info("mst is cyclic: " + detector.hasCycle(mst));
 		LOGGER.info("mst is connected: " + Topography.isStronglyConnected(mst));
-		LOGGER.info("mst is contains all nodes: " + mst.getNodes().containsAll(graph.getNodes()));
+		LOGGER.info("mst is contains all nodes: " + mst.getTargets().containsAll(graph.getTargets()));
 
 		Assert.assertTrue("mst was not acyclic", !detector.hasCycle(mst));
 		Assert.assertTrue("mst was not connected", Topography.isStronglyConnected(mst));
-		Assert.assertTrue("mst did not contain all the nodes of the paret graph", mst.getNodes().containsAll(graph.getNodes()));
+		Assert.assertTrue("mst did not contain all the nodes of the paret graph", mst.getTargets().containsAll(graph.getTargets()));
 	}
 }
diff --git a/src/test/java/com/syncleus/dann/graphicalmodel/bayesian/TestSicknessBayesianNetwork.java b/src/test/java/com/syncleus/dann/graphicalmodel/bayesian/TestSicknessBayesianNetwork.java
index 7dfa9a16df9e79267a3cfcbc3ca5bd95251ba1ec..a3dcf74811368f67f4c9e73e94ea11abcb379836 100644
--- a/src/test/java/com/syncleus/dann/graphicalmodel/bayesian/TestSicknessBayesianNetwork.java
+++ b/src/test/java/com/syncleus/dann/graphicalmodel/bayesian/TestSicknessBayesianNetwork.java
@@ -21,7 +21,7 @@ package com.syncleus.dann.graphicalmodel.bayesian;
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.util.*;
-import com.syncleus.dann.graph.ImmutableDirectedEdge;
+import com.syncleus.dann.graph.SimpleDirectedEdge;
 import com.syncleus.dann.graphicalmodel.GraphicalModelNode;
 import com.syncleus.dann.graphicalmodel.SimpleGraphicalModelNode;
 import com.syncleus.dann.graphicalmodel.bayesian.xml.BayesianNetworkXml;
@@ -113,21 +113,21 @@ public class TestSicknessBayesianNetwork
 		network.add(this.fever);
 		network.add(this.tired);
 		network.add(this.sick);
-		//connect nodes
-		network.add(new ImmutableDirectedEdge<GraphicalModelNode>(this.season, this.stuffyNose));
-		network.add(new ImmutableDirectedEdge<GraphicalModelNode>(this.season, this.fever));
-		network.add(new ImmutableDirectedEdge<GraphicalModelNode>(this.season, this.tired));
-		network.add(new ImmutableDirectedEdge<GraphicalModelNode>(this.season, this.sick));
-		network.add(new ImmutableDirectedEdge<GraphicalModelNode>(this.age, this.stuffyNose));
-		network.add(new ImmutableDirectedEdge<GraphicalModelNode>(this.age, this.fever));
-		network.add(new ImmutableDirectedEdge<GraphicalModelNode>(this.age, this.tired));
-		network.add(new ImmutableDirectedEdge<GraphicalModelNode>(this.age, this.sick));
-		network.add(new ImmutableDirectedEdge<GraphicalModelNode>(this.tired, this.fever));
-		network.add(new ImmutableDirectedEdge<GraphicalModelNode>(this.tired, this.stuffyNose));
-		network.add(new ImmutableDirectedEdge<GraphicalModelNode>(this.tired, this.sick));
-		network.add(new ImmutableDirectedEdge<GraphicalModelNode>(this.stuffyNose, this.fever));
-		network.add(new ImmutableDirectedEdge<GraphicalModelNode>(this.stuffyNose, this.sick));
-		network.add(new ImmutableDirectedEdge<GraphicalModelNode>(this.fever, this.sick));
+		//join nodes
+		network.add(new SimpleDirectedEdge<GraphicalModelNode>(this.season, this.stuffyNose));
+		network.add(new SimpleDirectedEdge<GraphicalModelNode>(this.season, this.fever));
+		network.add(new SimpleDirectedEdge<GraphicalModelNode>(this.season, this.tired));
+		network.add(new SimpleDirectedEdge<GraphicalModelNode>(this.season, this.sick));
+		network.add(new SimpleDirectedEdge<GraphicalModelNode>(this.age, this.stuffyNose));
+		network.add(new SimpleDirectedEdge<GraphicalModelNode>(this.age, this.fever));
+		network.add(new SimpleDirectedEdge<GraphicalModelNode>(this.age, this.tired));
+		network.add(new SimpleDirectedEdge<GraphicalModelNode>(this.age, this.sick));
+		network.add(new SimpleDirectedEdge<GraphicalModelNode>(this.tired, this.fever));
+		network.add(new SimpleDirectedEdge<GraphicalModelNode>(this.tired, this.stuffyNose));
+		network.add(new SimpleDirectedEdge<GraphicalModelNode>(this.tired, this.sick));
+		network.add(new SimpleDirectedEdge<GraphicalModelNode>(this.stuffyNose, this.fever));
+		network.add(new SimpleDirectedEdge<GraphicalModelNode>(this.stuffyNose, this.sick));
+		network.add(new SimpleDirectedEdge<GraphicalModelNode>(this.fever, this.sick));
 		//let the network learn
 		for(int sampleCount = 0; sampleCount < 10; sampleCount++)
 			this.sampleState();
diff --git a/src/test/java/com/syncleus/dann/graphicalmodel/bayesian/TestSimpleBayesianNetwork.java b/src/test/java/com/syncleus/dann/graphicalmodel/bayesian/TestSimpleBayesianNetwork.java
index e74859d304f0a76759bb300d7084397ce0323cfd..5f613f96fd6e6ecdcd46b97f49f455236da3b804 100644
--- a/src/test/java/com/syncleus/dann/graphicalmodel/bayesian/TestSimpleBayesianNetwork.java
+++ b/src/test/java/com/syncleus/dann/graphicalmodel/bayesian/TestSimpleBayesianNetwork.java
@@ -20,7 +20,7 @@ package com.syncleus.dann.graphicalmodel.bayesian;
 
 import java.util.*;
 import com.syncleus.dann.graph.DirectedEdge;
-import com.syncleus.dann.graph.ImmutableDirectedEdge;
+import com.syncleus.dann.graph.SimpleDirectedEdge;
 import com.syncleus.dann.graphicalmodel.GraphicalModelNode;
 import com.syncleus.dann.graphicalmodel.SimpleGraphicalModelNode;
 import org.junit.*;
@@ -42,7 +42,7 @@ public class TestSimpleBayesianNetwork
 		network.add(parentNode);
 		network.add(childNode);
 
-		final DirectedEdge<GraphicalModelNode> testEdge = new ImmutableDirectedEdge<GraphicalModelNode>(parentNode, childNode);
+		final DirectedEdge<GraphicalModelNode> testEdge = new SimpleDirectedEdge<GraphicalModelNode>(parentNode, childNode);
 		network.add(testEdge);
 
 		parentNode.setState(SimpleEnum.TRUE);
@@ -93,7 +93,7 @@ public class TestSimpleBayesianNetwork
 		network.add(parentNode);
 		network.add(childNode);
 
-		final DirectedEdge<GraphicalModelNode> testEdge = new ImmutableDirectedEdge<GraphicalModelNode>(parentNode, childNode);
+		final DirectedEdge<GraphicalModelNode> testEdge = new SimpleDirectedEdge<GraphicalModelNode>(parentNode, childNode);
 		network.add(testEdge);
 
 		parentNode.setState(SimpleEnum.TRUE);
diff --git a/src/test/java/com/syncleus/dann/graphicalmodel/bayesian/TestSimpleBayesianNode.java b/src/test/java/com/syncleus/dann/graphicalmodel/bayesian/TestSimpleBayesianNode.java
index f9ea8e47f50788a827c67c3ff9550e4af54e96e0..a1429d234b356cb2282ccceb5c799294aa15d378 100644
--- a/src/test/java/com/syncleus/dann/graphicalmodel/bayesian/TestSimpleBayesianNode.java
+++ b/src/test/java/com/syncleus/dann/graphicalmodel/bayesian/TestSimpleBayesianNode.java
@@ -19,7 +19,7 @@
 package com.syncleus.dann.graphicalmodel.bayesian;
 
 import com.syncleus.dann.graph.DirectedEdge;
-import com.syncleus.dann.graph.ImmutableDirectedEdge;
+import com.syncleus.dann.graph.SimpleDirectedEdge;
 import com.syncleus.dann.graphicalmodel.GraphicalModelNode;
 import com.syncleus.dann.graphicalmodel.SimpleGraphicalModelNode;
 import org.junit.*;
@@ -67,7 +67,7 @@ public class TestSimpleBayesianNode
 		network.add(parentNode);
 		network.add(childNode);
 
-		final DirectedEdge<GraphicalModelNode<SimpleEnum>> testEdge = new ImmutableDirectedEdge<GraphicalModelNode<SimpleEnum>>(parentNode, childNode);
+		final DirectedEdge<GraphicalModelNode<SimpleEnum>> testEdge = new SimpleDirectedEdge<GraphicalModelNode<SimpleEnum>>(parentNode, childNode);
 		network.add(testEdge);
 
 		parentNode.setState(SimpleEnum.TRUE);
diff --git a/src/test/java/com/syncleus/dann/graphicalmodel/bayesian/TestSimpleBooleanNetwork.java b/src/test/java/com/syncleus/dann/graphicalmodel/bayesian/TestSimpleBooleanNetwork.java
index 78382125ccaa9281dae107133572735a352a7eb3..606a067e16145d9f9568f88b3fef957c36e0ed29 100644
--- a/src/test/java/com/syncleus/dann/graphicalmodel/bayesian/TestSimpleBooleanNetwork.java
+++ b/src/test/java/com/syncleus/dann/graphicalmodel/bayesian/TestSimpleBooleanNetwork.java
@@ -20,7 +20,7 @@ package com.syncleus.dann.graphicalmodel.bayesian;
 
 import java.util.HashSet;
 import com.syncleus.dann.graph.DirectedEdge;
-import com.syncleus.dann.graph.ImmutableDirectedEdge;
+import com.syncleus.dann.graph.SimpleDirectedEdge;
 import com.syncleus.dann.graphicalmodel.GraphicalModelNode;
 import com.syncleus.dann.graphicalmodel.SimpleGraphicalModelNode;
 import org.junit.*;
@@ -75,8 +75,8 @@ public class TestSimpleBooleanNetwork
 			//add nodes
 			add(this.influence);
 			add(this.goal);
-			//connect nodes
-			final DirectedEdge<GraphicalModelNode> testEdge = new ImmutableDirectedEdge<GraphicalModelNode>(this.influence, this.goal);
+			//join nodes
+			final DirectedEdge<GraphicalModelNode> testEdge = new SimpleDirectedEdge<GraphicalModelNode>(this.influence, this.goal);
 			this.add(testEdge);
 			goals.add(this.goal);
 			influences.add(this.influence);
diff --git a/src/test/java/com/syncleus/dann/graphicalmodel/markovrandomfield/TestSicknessRandomMarkovField.java b/src/test/java/com/syncleus/dann/graphicalmodel/markovrandomfield/TestSicknessRandomMarkovField.java
index 81b377567bc04cfd9f0b9934e44ec1b0c65cf902..d0aafbacecd1b176fec7f1245d60e7dc7d2a9863 100644
--- a/src/test/java/com/syncleus/dann/graphicalmodel/markovrandomfield/TestSicknessRandomMarkovField.java
+++ b/src/test/java/com/syncleus/dann/graphicalmodel/markovrandomfield/TestSicknessRandomMarkovField.java
@@ -23,7 +23,7 @@ import javax.xml.bind.annotation.XmlRootElement;
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.util.*;
-import com.syncleus.dann.graph.ImmutableUndirectedEdge;
+import com.syncleus.dann.graph.SimpleUndirectedEdge;
 import com.syncleus.dann.graphicalmodel.GraphicalModelNode;
 import com.syncleus.dann.graphicalmodel.SimpleGraphicalModelNode;
 import com.syncleus.dann.graphicalmodel.xml.GraphicalModelXml;
@@ -114,21 +114,21 @@ public class TestSicknessRandomMarkovField
 		network.add(this.fever);
 		network.add(this.tired);
 		network.add(this.sick);
-		//connect nodes
-		network.add(new ImmutableUndirectedEdge<GraphicalModelNode>(this.season, this.stuffyNose));
-		network.add(new ImmutableUndirectedEdge<GraphicalModelNode>(this.season, this.fever));
-		network.add(new ImmutableUndirectedEdge<GraphicalModelNode>(this.season, this.tired));
-		network.add(new ImmutableUndirectedEdge<GraphicalModelNode>(this.season, this.sick));
-		network.add(new ImmutableUndirectedEdge<GraphicalModelNode>(this.age, this.stuffyNose));
-		network.add(new ImmutableUndirectedEdge<GraphicalModelNode>(this.age, this.fever));
-		network.add(new ImmutableUndirectedEdge<GraphicalModelNode>(this.age, this.tired));
-		network.add(new ImmutableUndirectedEdge<GraphicalModelNode>(this.age, this.sick));
-		network.add(new ImmutableUndirectedEdge<GraphicalModelNode>(this.tired, this.fever));
-		network.add(new ImmutableUndirectedEdge<GraphicalModelNode>(this.tired, this.stuffyNose));
-		network.add(new ImmutableUndirectedEdge<GraphicalModelNode>(this.tired, this.sick));
-		network.add(new ImmutableUndirectedEdge<GraphicalModelNode>(this.stuffyNose, this.fever));
-		network.add(new ImmutableUndirectedEdge<GraphicalModelNode>(this.stuffyNose, this.sick));
-		network.add(new ImmutableUndirectedEdge<GraphicalModelNode>(this.fever, this.sick));
+		//join nodes
+		network.add(new SimpleUndirectedEdge<GraphicalModelNode>(this.season, this.stuffyNose));
+		network.add(new SimpleUndirectedEdge<GraphicalModelNode>(this.season, this.fever));
+		network.add(new SimpleUndirectedEdge<GraphicalModelNode>(this.season, this.tired));
+		network.add(new SimpleUndirectedEdge<GraphicalModelNode>(this.season, this.sick));
+		network.add(new SimpleUndirectedEdge<GraphicalModelNode>(this.age, this.stuffyNose));
+		network.add(new SimpleUndirectedEdge<GraphicalModelNode>(this.age, this.fever));
+		network.add(new SimpleUndirectedEdge<GraphicalModelNode>(this.age, this.tired));
+		network.add(new SimpleUndirectedEdge<GraphicalModelNode>(this.age, this.sick));
+		network.add(new SimpleUndirectedEdge<GraphicalModelNode>(this.tired, this.fever));
+		network.add(new SimpleUndirectedEdge<GraphicalModelNode>(this.tired, this.stuffyNose));
+		network.add(new SimpleUndirectedEdge<GraphicalModelNode>(this.tired, this.sick));
+		network.add(new SimpleUndirectedEdge<GraphicalModelNode>(this.stuffyNose, this.fever));
+		network.add(new SimpleUndirectedEdge<GraphicalModelNode>(this.stuffyNose, this.sick));
+		network.add(new SimpleUndirectedEdge<GraphicalModelNode>(this.fever, this.sick));
 		//let the network learn
 		for(int sampleCount = 0; sampleCount < 10; sampleCount++)
 			this.sampleState();
diff --git a/src/test/java/com/syncleus/dann/graphicalmodel/markovrandomfield/TestSimpleBooleanField.java b/src/test/java/com/syncleus/dann/graphicalmodel/markovrandomfield/TestSimpleBooleanField.java
index eff3183cbe0f4976b94407b7f7a8d7ece4a317dc..70d6416f1a0d9ba90451b323bd8e54950f08b5d4 100644
--- a/src/test/java/com/syncleus/dann/graphicalmodel/markovrandomfield/TestSimpleBooleanField.java
+++ b/src/test/java/com/syncleus/dann/graphicalmodel/markovrandomfield/TestSimpleBooleanField.java
@@ -75,8 +75,8 @@ public class TestSimpleBooleanField
 			//add nodes
 			add(this.influence);
 			add(this.goal);
-			//connect nodes
-			final UndirectedEdge<GraphicalModelNode> testEdge = new ImmutableUndirectedEdge<GraphicalModelNode>(this.influence, this.goal);
+			//join nodes
+			final UndirectedEdge<GraphicalModelNode> testEdge = new SimpleUndirectedEdge<GraphicalModelNode>(this.influence, this.goal);
 			this.add(testEdge);
 			goals.add(this.goal);
 			influences.add(this.influence);
diff --git a/src/test/java/com/syncleus/dann/graphicalmodel/markovrandomfield/TestSimpleMarkovRandomField.java b/src/test/java/com/syncleus/dann/graphicalmodel/markovrandomfield/TestSimpleMarkovRandomField.java
index d1002e1c0a6122cd3e2d64fb3965dc9fe5a76d47..5956b2221f60ae00e56db46e991495ea1945ac7e 100644
--- a/src/test/java/com/syncleus/dann/graphicalmodel/markovrandomfield/TestSimpleMarkovRandomField.java
+++ b/src/test/java/com/syncleus/dann/graphicalmodel/markovrandomfield/TestSimpleMarkovRandomField.java
@@ -43,7 +43,7 @@ public class TestSimpleMarkovRandomField
 		network.add(parentNode);
 		network.add(childNode);
 
-		final UndirectedEdge<GraphicalModelNode> testEdge = new ImmutableUndirectedEdge<GraphicalModelNode>(parentNode, childNode);
+		final UndirectedEdge<GraphicalModelNode> testEdge = new SimpleUndirectedEdge<GraphicalModelNode>(parentNode, childNode);
 		network.add(testEdge);
 
 		parentNode.setState(SimpleEnum.TRUE);
@@ -98,7 +98,7 @@ public class TestSimpleMarkovRandomField
 		network.add(parentNode);
 		network.add(childNode);
 
-		final UndirectedEdge<GraphicalModelNode> testEdge = new ImmutableUndirectedEdge<GraphicalModelNode>(parentNode, childNode);
+		final UndirectedEdge<GraphicalModelNode> testEdge = new SimpleUndirectedEdge<GraphicalModelNode>(parentNode, childNode);
 		network.add(testEdge);
 
 		parentNode.setState(SimpleEnum.TRUE);
diff --git a/src/test/java/com/syncleus/dann/graphicalmodel/markovrandomfield/TestSimpleMarkovRandomFieldNode.java b/src/test/java/com/syncleus/dann/graphicalmodel/markovrandomfield/TestSimpleMarkovRandomFieldNode.java
index 31f8dda2d2a46210f333f89c13a74e4b768e2a7c..ba4314726e2f7ef60ece204d8bb6efcf26610486 100644
--- a/src/test/java/com/syncleus/dann/graphicalmodel/markovrandomfield/TestSimpleMarkovRandomFieldNode.java
+++ b/src/test/java/com/syncleus/dann/graphicalmodel/markovrandomfield/TestSimpleMarkovRandomFieldNode.java
@@ -67,7 +67,7 @@ public class TestSimpleMarkovRandomFieldNode
 		network.add(parentNode);
 		network.add(childNode);
 
-		final UndirectedEdge<GraphicalModelNode<SimpleEnum>> testEdge = new ImmutableUndirectedEdge<GraphicalModelNode<SimpleEnum>>(parentNode, childNode);
+		final UndirectedEdge<GraphicalModelNode<SimpleEnum>> testEdge = new SimpleUndirectedEdge<GraphicalModelNode<SimpleEnum>>(parentNode, childNode);
 		network.add(testEdge);
 
 		parentNode.setState(SimpleEnum.TRUE);