/** * A proxy method that adds the node {@code n} to the graph being tested. In case of Immutable * graph implementations, this method should add {@code n} to the graph builder and build a new * graph with the current builder state. * * @return {@code true} iff the graph was modified as a result of this call */ @CanIgnoreReturnValue protected boolean addNode(Integer n) { return network.addNode(n); }
/** * A proxy method that adds the edge {@code e} to the graph being tested. In case of Immutable * graph implementations, this method should add {@code e} to the graph builder and build a new * graph with the current builder state. * * <p>This method should be used in tests of specific implementations if you want to ensure * uniform behavior (including side effects) with how edges are added elsewhere in the tests. For * example, the existing implementations of this method explicitly add the supplied nodes to the * graph, and then call {@code graph.addEdge()} to connect the edge to the nodes; this is not part * of the contract of {@code graph.addEdge()} and is done for convenience. In cases where you want * to avoid such side effects (e.g., if you're testing what happens in your implementation if you * add an edge whose end-points don't already exist in the graph), you should <b>not</b> use this * method. * * TODO(user): remove the addNode() calls, that's now contractually guaranteed * * @return {@code true} iff the graph was modified as a result of this call */ @CanIgnoreReturnValue protected boolean addEdge(Integer n1, Integer n2, String e) { network.addNode(n1); network.addNode(n2); return network.addEdge(n1, n2, e); }
@Test public void edgesConnecting_checkReturnedSetMutability() { network.addNode(N1); network.addNode(N2); Set<String> edgesConnecting = network.edgesConnecting(N1, N2); try { edgesConnecting.add(E23); fail(ERROR_MODIFIABLE_COLLECTION); } catch (UnsupportedOperationException e) { network.addEdge(N1, N2, E12); assertThat(networkForTest.edgesConnecting(N1, N2)).containsExactlyElementsIn(edgesConnecting); } }
@Test public void immutableNetwork() { MutableNetwork<String, Integer> mutableNetwork = NetworkBuilder.directed().build(); mutableNetwork.addNode("A"); ImmutableNetwork<String, Integer> immutableNetwork = ImmutableNetwork.copyOf(mutableNetwork); assertThat(immutableNetwork.asGraph()).isInstanceOf(ImmutableGraph.class); assertThat(immutableNetwork).isNotInstanceOf(MutableNetwork.class); assertThat(immutableNetwork).isEqualTo(mutableNetwork); mutableNetwork.addNode("B"); assertThat(immutableNetwork).isNotEqualTo(mutableNetwork); }
private static <N> ImmutableNetwork<N, N> networkWithNode(N node) { MutableNetwork<N, N> network = NetworkBuilder.directed().build(); network.addNode(node); return ImmutableNetwork.copyOf(network); } }
/** Creates a mutable copy of {@code network} with the same nodes and edges. */ public static <N, E> MutableNetwork<N, E> copyOf(Network<N, E> network) { MutableNetwork<N, E> copy = NetworkBuilder.from(network) .expectedNodeCount(network.nodes().size()) .expectedEdgeCount(network.edges().size()) .build(); for (N node : network.nodes()) { copy.addNode(node); } for (E edge : network.edges()) { EndpointPair<N> endpointPair = network.incidentNodes(edge); copy.addEdge(endpointPair.nodeU(), endpointPair.nodeV(), edge); } return copy; }
/** * Returns the subgraph of {@code network} induced by {@code nodes}. This subgraph is a new graph * that contains all of the nodes in {@code nodes}, and all of the {@link Network#edges() edges} * from {@code network} for which the {@link Network#incidentNodes(Object) incident nodes} are * both contained by {@code nodes}. * * @throws IllegalArgumentException if any element in {@code nodes} is not a node in the graph */ public static <N, E> MutableNetwork<N, E> inducedSubgraph( Network<N, E> network, Iterable<? extends N> nodes) { MutableNetwork<N, E> subgraph = (nodes instanceof Collection) ? NetworkBuilder.from(network).expectedNodeCount(((Collection) nodes).size()).build() : NetworkBuilder.from(network).build(); for (N node : nodes) { subgraph.addNode(node); } for (N node : subgraph.nodes()) { for (E edge : network.outEdges(node)) { N successorNode = network.incidentNodes(edge).adjacentNode(node); if (subgraph.nodes().contains(successorNode)) { subgraph.addEdge(node, successorNode, edge); } } } return subgraph; }
/** Creates a mutable copy of {@code network} with the same nodes and edges. */ public static <N, E> MutableNetwork<N, E> copyOf(Network<N, E> network) { MutableNetwork<N, E> copy = NetworkBuilder.from(network) .expectedNodeCount(network.nodes().size()) .expectedEdgeCount(network.edges().size()) .build(); for (N node : network.nodes()) { copy.addNode(node); } for (E edge : network.edges()) { EndpointPair<N> endpointPair = network.incidentNodes(edge); copy.addEdge(endpointPair.nodeU(), endpointPair.nodeV(), edge); } return copy; }
/** Creates a mutable copy of {@code network} with the same nodes and edges. */ public static <N, E> MutableNetwork<N, E> copyOf(Network<N, E> network) { MutableNetwork<N, E> copy = NetworkBuilder.from(network) .expectedNodeCount(network.nodes().size()) .expectedEdgeCount(network.edges().size()) .build(); for (N node : network.nodes()) { copy.addNode(node); } for (E edge : network.edges()) { EndpointPair<N> endpointPair = network.incidentNodes(edge); copy.addEdge(endpointPair.nodeU(), endpointPair.nodeV(), edge); } return copy; }
@Test public void edgesConnecting_nodesNotInGraph() { network.addNode(N1); network.addNode(N2); try { networkForTest.edgesConnecting(N1, NODE_NOT_IN_GRAPH); fail(ERROR_NODE_NOT_IN_GRAPH); } catch (IllegalArgumentException e) { assertNodeNotInGraphErrorMessage(e); } try { networkForTest.edgesConnecting(NODE_NOT_IN_GRAPH, N2); fail(ERROR_NODE_NOT_IN_GRAPH); } catch (IllegalArgumentException e) { assertNodeNotInGraphErrorMessage(e); } try { networkForTest.edgesConnecting(NODE_NOT_IN_GRAPH, NODE_NOT_IN_GRAPH); fail(ERROR_NODE_NOT_IN_GRAPH); } catch (IllegalArgumentException e) { assertNodeNotInGraphErrorMessage(e); } }
/** * Returns the subgraph of {@code network} induced by {@code nodes}. This subgraph is a new graph * that contains all of the nodes in {@code nodes}, and all of the {@link Network#edges() edges} * from {@code network} for which the {@link Network#incidentNodes(Object) incident nodes} are * both contained by {@code nodes}. * * @throws IllegalArgumentException if any element in {@code nodes} is not a node in the graph */ public static <N, E> MutableNetwork<N, E> inducedSubgraph( Network<N, E> network, Iterable<? extends N> nodes) { MutableNetwork<N, E> subgraph = (nodes instanceof Collection) ? NetworkBuilder.from(network).expectedNodeCount(((Collection) nodes).size()).build() : NetworkBuilder.from(network).build(); for (N node : nodes) { subgraph.addNode(node); } for (N node : subgraph.nodes()) { for (E edge : network.outEdges(node)) { N successorNode = network.incidentNodes(edge).adjacentNode(node); if (subgraph.nodes().contains(successorNode)) { subgraph.addEdge(node, successorNode, edge); } } } return subgraph; }
/** * This test checks an implementation dependent feature. It tests that the method {@code addEdge} * will silently add the missing nodes to the graph, then add the edge connecting them. We are not * using the proxy methods here as we want to test {@code addEdge} when the end-points are not * elements of the graph. */ @Test public void addEdge_nodesNotInGraph() { network.addNode(N1); assertTrue(network.addEdge(N1, N5, E15)); assertTrue(network.addEdge(N4, N1, E41)); assertTrue(network.addEdge(N2, N3, E23)); assertThat(network.nodes()).containsExactly(N1, N5, N4, N2, N3).inOrder(); assertThat(network.edges()).containsExactly(E15, E41, E23).inOrder(); assertThat(network.edgesConnecting(N1, N5)).containsExactly(E15); assertThat(network.edgesConnecting(N4, N1)).containsExactly(E41); assertThat(network.edgesConnecting(N2, N3)).containsExactly(E23); assertThat(network.edgesConnecting(N3, N2)).containsExactly(E23); } }
/** * This test checks an implementation dependent feature. It tests that the method {@code addEdge} * will silently add the missing nodes to the graph, then add the edge connecting them. We are not * using the proxy methods here as we want to test {@code addEdge} when the end-points are not * elements of the graph. */ @Test public void addEdge_nodesNotInGraph() { network.addNode(N1); assertTrue(network.addEdge(N1, N5, E15)); assertTrue(network.addEdge(N4, N1, E41)); assertTrue(network.addEdge(N2, N3, E23)); assertThat(network.nodes()).containsExactly(N1, N5, N4, N2, N3).inOrder(); assertThat(network.edges()).containsExactly(E15, E41, E23).inOrder(); assertThat(network.edgesConnecting(N1, N5)).containsExactly(E15); assertThat(network.edgesConnecting(N4, N1)).containsExactly(E41); assertThat(network.edgesConnecting(N2, N3)).containsExactly(E23); // Direction of the added edge is correctly handled assertThat(network.edgesConnecting(N3, N2)).isEmpty(); } }
private static class TransposedNetwork<N, E> extends ForwardingNetwork<N, E> { private final Network<N, E> network; TransposedNetwork(Network<N, E> network) { this.network = network; } @Override protected Network<N, E> delegate() { return network; } @Override public Set<N> predecessors(N node) { return delegate().successors(node); // transpose } @Override public Set<N> successors(N node) { return delegate().predecessors(node); // transpose } @Override public int inDegree(N node) { return delegate().outDegree(node); // transpose } @Override public int outDegree(N node) { return delegate().inDegree(node); // transpose
@Test public void endpointPair_undirectedNetwork() { MutableNetwork<Integer, String> undirectedNetwork = NetworkBuilder.undirected().allowsParallelEdges(true).allowsSelfLoops(true).build(); undirectedNetwork.addNode(N0); undirectedNetwork.addEdge(N1, N2, E12); undirectedNetwork.addEdge(N2, N1, E12_A); // adds parallel edge, won't be in Graph edges undirectedNetwork.addEdge(N1, N3, E13); undirectedNetwork.addEdge(N4, N4, E44); containsExactlySanityCheck( undirectedNetwork.asGraph().edges(), EndpointPair.unordered(N1, N2), EndpointPair.unordered(N1, N3), EndpointPair.unordered(N4, N4)); }
@Test public void endpointPair_directedNetwork() { MutableNetwork<Integer, String> directedNetwork = NetworkBuilder.directed().allowsSelfLoops(true).build(); directedNetwork.addNode(N0); directedNetwork.addEdge(N1, N2, E12); directedNetwork.addEdge(N2, N1, E21); directedNetwork.addEdge(N1, N3, E13); directedNetwork.addEdge(N4, N4, E44); containsExactlySanityCheck( directedNetwork.asGraph().edges(), EndpointPair.ordered(N1, N2), EndpointPair.ordered(N2, N1), EndpointPair.ordered(N1, N3), EndpointPair.ordered(N4, N4)); }