package automenta.netention.graph; import com.syncleus.dann.graph.DirectedEdge; /** BidirectedGraph that can be edited dynamically: adding and removing both nodes and edges. Contains code adapted from JUNG2's DirectedSparseMultigraph and its ancestry. */ public class DynamicDirectedGraph<N, E extends DirectedEdge<N>> /*extends AbstractBidirectedGraph<N, E> */{ // //Original dANN fields: // // final private HashSet<N> nodes; // // final private HashSet<E> edges; // // final private Map<N, Set<E>> neighborEdges = new HashMap<N, Set<E>>(); // // final private Map<N, List<N>> neighborNodes = new HashMap<N, List<N>>(); // // //JUNG2's DirectedSparseMultigraph fields, for comparison: // protected Map<N, Pair<Set<E>>> vertices; // Map of vertices to Pair of adjacency sets {incoming, outgoing} // //protected Map<E, Pair<N>> edges; // Map of edges to incident vertex pairs // protected Set<E> edges; // // // public DynamicDirectedGraph() { // super(); // vertices = new HashMap(); // edges = new HashSet(); // } // // public boolean addNode(N vertex) { // if (vertex == null) { // throw new IllegalArgumentException("vertex may not be null"); // } // if (!containsVertex(vertex)) { // vertices.put(vertex, new Pair<Set<E>>(new HashSet<E>(), new HashSet<E>())); // return true; // } else { // return false; // } // } // // public boolean removeVertex(N vertex) { // if (!containsVertex(vertex)) { // return false; // } // // // copy to avoid concurrent modification in removeEdge // Set<E> incident = new HashSet<E>(getIncoming_internal(vertex)); // incident.addAll(getOutgoing_internal(vertex)); // // for (E edge : incident) { // removeEdge(edge); // } // // vertices.remove(vertex); // // return true; // } // // // public boolean addEdge(E edge) { // final Pair<N> endpoints = new Pair<N>(edge.getSourceNode(), edge.getDestinationNode()); // final Pair<N> new_endpoints = getValidatedEndpoints(edge, endpoints); // if (new_endpoints == null) { // return false; // } // // edges.add(edge); // // N source = new_endpoints.getFirst(); // N dest = new_endpoints.getSecond(); // // if (!containsVertex(source)) { // this.addNode(source); // } // // if (!containsVertex(dest)) { // this.addNode(dest); // } // // getIncoming_internal(dest).add(edge); // getOutgoing_internal(source).add(edge); // // return true; // } // // public boolean removeEdge(E edge) { // if (!containsEdge(edge)) { // return false; // } // // Pair<N> endpoints = this.getEndpoints(edge); // N source = endpoints.getFirst(); // N dest = endpoints.getSecond(); // // // remove edge from incident vertices' adjacency sets // getOutgoing_internal(source).remove(edge); // getIncoming_internal(dest).remove(edge); // // edges.remove(edge); // return true; // } // // public boolean containsVertex(N vertex) { // return vertices.keySet().contains(vertex); // } // // public boolean containsEdge(E edge) { // return edges.contains(edge); // } // // // protected Pair<N> getValidatedEndpoints(E edge, Pair<? extends N> endpoints) // { // if (edge == null) // throw new IllegalArgumentException("input edge may not be null"); // // if (endpoints == null) // throw new IllegalArgumentException("endpoints may not be null"); // // Pair<N> new_endpoints = new Pair<N>(endpoints.getFirst(), endpoints.getSecond()); // if (containsEdge(edge)) // { // Pair<N> existing_endpoints = getEndpoints(edge); // if (!existing_endpoints.equals(new_endpoints)) { // throw new IllegalArgumentException("edge " + edge + // " already exists in this graph with endpoints " + existing_endpoints + // " and cannot be added with endpoints " + endpoints); // } else { // return null; // } // } // return new_endpoints; // } // // public Pair<N> getEndpoints(E edge) { // if (edges.contains(edge)) { // return new Pair(edge.getSourceNode(), edge.getDestinationNode()); // } // return null; // } // // protected Set<E> getIncoming_internal(N vertex) // { // return vertices.get(vertex).getFirst(); // } // // protected Collection<E> getOutgoing_internal(N vertex) // { // return vertices.get(vertex).getSecond(); // } // // public Set<N> getNodes() { // return Collections.unmodifiableSet(this.vertices.keySet()); // } // // @Override // public Set<E> getEdges() { // return Collections.unmodifiableSet(this.edges); // } // // public Set<E> getAdjacentEdges(N node) { // //return Collections.unmodifiableSet(this.neighborEdges.get(node)); // if (!containsVertex(node)) // return null; // // Set<E> incident = new HashSet<E>(); // incident.addAll(getIncoming_internal(node)); // incident.addAll(getOutgoing_internal(node)); // return Collections.unmodifiableSet(incident); // } // // public Set<E> getTraversableEdges(N node) { // final Set<E> traversableEdges = new HashSet<E>(); // for (E edge : edges) { // if (edge.getSourceNode() == node) { // traversableEdges.add(edge); // } // } // return Collections.unmodifiableSet(traversableEdges); // } // // public Set<E> getOutEdges(N node) { // return this.getTraversableEdges(node); // } // // public Set<E> getInEdges(N node) { // return getIncoming_internal(node); //// final Set<E> inEdges = new HashSet<E>(); //// for (E edge : edges) { //// if (edge.getDestinationNode() == node) { //// inEdges.add(edge); //// } //// } //// return Collections.unmodifiableSet(inEdges); // } // // public int getIndegree(N node) { // return this.getInEdges(node).size(); // } // // public int getOutdegree(N node) { // return this.getOutEdges(node).size(); // } // // public List<N> getAdjacentNodes(N vertex) { // if (!containsVertex(vertex)) // return null; // // List<N> neighbors = new LinkedList<N>(); // for (E edge : getIncoming_internal(vertex)) // neighbors.add(this.getSource(edge)); // for (E edge : getOutgoing_internal(vertex)) // neighbors.add(this.getDest(edge)); // return Collections.unmodifiableList(neighbors); // } // // public List<N> getTraversableNodes(N node) { // Set<E> traversableEdges = this.getTraversableEdges(node); // List<N> traversableNeighbors = new ArrayList<N>(); // for (E traversableEdge : traversableEdges) { // traversableNeighbors.add(traversableEdge.getDestinationNode()); // } // return Collections.unmodifiableList(traversableNeighbors); // } // // public N getSource(E edge) { // if (!containsEdge(edge)) // return null; // return this.getEndpoints(edge).getFirst(); // } // // public N getDest(E edge) { // if (!containsEdge(edge)) // return null; // return this.getEndpoints(edge).getSecond(); // } // }