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

com.google.common.graph.ConfigurableMutableNetwork Maven / Gradle / Ivy

There is a newer version: 30.1
Show newest version
/*
 * Copyright (C) 2016 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.common.graph;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.graph.GraphConstants.PARALLEL_EDGES_NOT_ALLOWED;
import static com.google.common.graph.GraphConstants.REUSING_EDGE;
import static com.google.common.graph.GraphConstants.SELF_LOOPS_NOT_ALLOWED;

import com.google.common.collect.ImmutableList;


/**
 * Configurable implementation of {@link MutableNetwork} that supports both directed and undirected
 * graphs. Instances of this class should be constructed with {@link NetworkBuilder}.
 *
 * 

Time complexities for mutation methods are all O(1) except for {@code removeNode(N node)}, * which is in O(d_node) where d_node is the degree of {@code node}. * * @author James Sexton * @author Joshua O'Madadhain * @author Omar Darwish * @param Node parameter type * @param Edge parameter type */ final class ConfigurableMutableNetwork extends ConfigurableNetwork implements MutableNetwork { /** Constructs a mutable graph with the properties specified in {@code builder}. */ ConfigurableMutableNetwork(NetworkBuilder builder) { super(builder); } @Override public boolean addNode(N node) { checkNotNull(node, "node"); if (containsNode(node)) { return false; } addNodeInternal(node); return true; } /** * Adds {@code node} to the graph and returns the associated {@link NetworkConnections}. * * @throws IllegalStateException if {@code node} is already present */ private NetworkConnections addNodeInternal(N node) { NetworkConnections connections = newConnections(); checkState(nodeConnections.put(node, connections) == null); return connections; } @Override public boolean addEdge(N nodeU, N nodeV, E edge) { checkNotNull(nodeU, "nodeU"); checkNotNull(nodeV, "nodeV"); checkNotNull(edge, "edge"); if (containsEdge(edge)) { EndpointPair existingIncidentNodes = incidentNodes(edge); EndpointPair newIncidentNodes = EndpointPair.of(this, nodeU, nodeV); checkArgument( existingIncidentNodes.equals(newIncidentNodes), REUSING_EDGE, edge, existingIncidentNodes, newIncidentNodes); return false; } NetworkConnections connectionsU = nodeConnections.get(nodeU); if (!allowsParallelEdges()) { checkArgument( !(connectionsU != null && connectionsU.successors().contains(nodeV)), PARALLEL_EDGES_NOT_ALLOWED, nodeU, nodeV); } boolean isSelfLoop = nodeU.equals(nodeV); if (!allowsSelfLoops()) { checkArgument(!isSelfLoop, SELF_LOOPS_NOT_ALLOWED, nodeU); } if (connectionsU == null) { connectionsU = addNodeInternal(nodeU); } connectionsU.addOutEdge(edge, nodeV); NetworkConnections connectionsV = nodeConnections.get(nodeV); if (connectionsV == null) { connectionsV = addNodeInternal(nodeV); } connectionsV.addInEdge(edge, nodeU, isSelfLoop); edgeToReferenceNode.put(edge, nodeU); return true; } @Override public boolean addEdge(EndpointPair endpoints, E edge) { validateEndpoints(endpoints); return addEdge(endpoints.nodeU(), endpoints.nodeV(), edge); } @Override public boolean removeNode(N node) { checkNotNull(node, "node"); NetworkConnections connections = nodeConnections.get(node); if (connections == null) { return false; } // Since views are returned, we need to copy the edges that will be removed. // Thus we avoid modifying the underlying view while iterating over it. for (E edge : ImmutableList.copyOf(connections.incidentEdges())) { removeEdge(edge); } nodeConnections.remove(node); return true; } @Override public boolean removeEdge(E edge) { checkNotNull(edge, "edge"); N nodeU = edgeToReferenceNode.get(edge); if (nodeU == null) { return false; } NetworkConnections connectionsU = nodeConnections.get(nodeU); N nodeV = connectionsU.adjacentNode(edge); NetworkConnections connectionsV = nodeConnections.get(nodeV); connectionsU.removeOutEdge(edge); connectionsV.removeInEdge(edge, allowsSelfLoops() && nodeU.equals(nodeV)); edgeToReferenceNode.remove(edge); return true; } private NetworkConnections newConnections() { return isDirected() ? allowsParallelEdges() ? DirectedMultiNetworkConnections.of() : DirectedNetworkConnections.of() : allowsParallelEdges() ? UndirectedMultiNetworkConnections.of() : UndirectedNetworkConnections.of(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy