Commit b2ea24ef authored by Björn Richerzhagen's avatar Björn Richerzhagen
Browse files

A cleaner (manual) merge of the API

- to contain all graph-related updates
- leaving other elements untouched (whitespace-commits excluded)
parent 02337f03
......@@ -6,7 +6,7 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<classpathentry exported="true" kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
......
/org.eclipse.core.resources.prefs
......@@ -21,7 +21,14 @@
package de.tudarmstadt.maki.simonstrator.api;
import de.tudarmstadt.maki.simonstrator.api.common.graph.BasicGraph;
import de.tudarmstadt.maki.simonstrator.api.common.graph.DirectedEdge;
import de.tudarmstadt.maki.simonstrator.api.common.graph.EdgeID;
import de.tudarmstadt.maki.simonstrator.api.common.graph.GenericGraphElementProperties;
import de.tudarmstadt.maki.simonstrator.api.common.graph.Graph;
import de.tudarmstadt.maki.simonstrator.api.common.graph.IEdge;
import de.tudarmstadt.maki.simonstrator.api.common.graph.INode;
import de.tudarmstadt.maki.simonstrator.api.common.graph.INodeID;
import de.tudarmstadt.maki.simonstrator.api.common.graph.Node;
import de.tudarmstadt.maki.simonstrator.api.component.ComponentNotAvailableException;
import de.tudarmstadt.maki.simonstrator.api.component.core.GraphComponent;
......@@ -79,4 +86,51 @@ public final class Graphs {
}
public static Graph createGraph(Iterable<? extends INode> nodes,
Iterable<? extends IEdge> edges) {
Graph graph = getGraphComponent().createGraph();
graph.addElements(nodes);
graph.addElements(edges);
return graph;
}
public static IEdge createDirectedWeightedEdge(final INodeID source,
final INodeID target, final Double weight) {
DirectedEdge edge = new DirectedEdge(source, target);
if (weight != null && !Double.isNaN(weight)) {
edge.setProperty(GenericGraphElementProperties.WEIGHT, weight);
}
return edge;
}
public static IEdge createDirectedWeightedEdge(final INode source,
final INode target, final double weight) {
return createDirectedWeightedEdge(source.getId(), target.getId(),
weight);
}
public static IEdge createDirectedWeightedEdge(final INodeID source,
final INodeID target, final EdgeID edgeId, final double weight) {
final DirectedEdge directedEdge = new DirectedEdge(source, target,
edgeId);
directedEdge.setProperty(GenericGraphElementProperties.WEIGHT, weight);
return directedEdge;
}
public static IEdge createDirectedEdge(INode n1, INode n2) {
return new DirectedEdge(n1.getId(), n2.getId());
}
public static IEdge createDirectedEdge(INodeID sourceId, INodeID targetId) {
return new DirectedEdge(sourceId, targetId);
}
public static Node createNode(long id) {
return new Node(INodeID.get(id));
}
public static Node createNode(String id) {
return new Node(INodeID.get(id));
}
}
......@@ -38,6 +38,7 @@ package de.tudarmstadt.maki.simonstrator.api.common;
*/
public interface UniqueID extends Transmitable, Comparable<UniqueID> {
// TODO BR: The documentation is outdated (rkluge)
/**
* Representation as a BigInteger, from which you might derive
* representations as double, etc. Usually, there should be no need to
......@@ -52,4 +53,6 @@ public interface UniqueID extends Transmitable, Comparable<UniqueID> {
*/
public long value();
public String valueAsString();
}
......@@ -20,9 +20,14 @@
package de.tudarmstadt.maki.simonstrator.api.common.graph;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
......@@ -31,23 +36,98 @@ import de.tudarmstadt.maki.simonstrator.api.Graphs;
/**
* A basic class realizing the Graph-Interface
*
* @author Michael Stein
* @author Roland Kluge
* @author Bjoern Richerzhagen
*
*/
public class BasicGraph implements Graph {
private final Set<IEdge> edges = new LinkedHashSet<>();
private final Set<INode> nodes = new LinkedHashSet<>();
private Map<INodeID, INode> nodesById = new LinkedHashMap<>();
private final Set<IEdge> edges = new LinkedHashSet<>();
// The list of all edges. For performance reasons
private final Map<EdgeID, IEdge> edgesById = new LinkedHashMap<>();
// Assigns to each node the set of outgoing edges of this node
private final Map<INodeID, Set<IEdge>> outgoingAdjacencyList = new HashMap<>();
// Assigns to each node the set of incoming edges of this node
private final Map<INodeID, Set<IEdge>> incomingAdjacencyList = new HashMap<>();
/**
* Creates an empty graph. Components should create new graphs by using the
* {@link Graphs} class in the api.
* {@link Graphs} class in the API
*/
public BasicGraph() {
//
}
/**
* Creates a graph from the given nodes and edges.
*
* Duplicate nodes and edges will be ignored
*
* @param nodes
* The set of nodes contained in the graph.
* @param edges
* Set of edges contained in the graph. Assumes that every start
* and end node in the edges is also contained in the nodes set
*/
public BasicGraph(Iterable<? extends INode> nodes,
Iterable<? extends IEdge> edges) {
this();
for (final INode node : nodes)
this.addNode(node);
for (final IEdge edge : edges)
this.addEdge(edge);
}
/**
* Creates an edge-induced graph.
*
* The nodes are derived from the edges.
*
* @param edges
* the edges of the graph
*/
public BasicGraph(Iterable<? extends IEdge> edges) {
this();
for (final IEdge edge : edges) {
this.addNode(this.createNode(edge.fromId()));
this.addNode(this.createNode(edge.toId()));
}
this.addElements(edges);
}
public static BasicGraph createGraphFromNodeIdsAndEdges(
Iterable<? extends INodeID> nodes,
Iterable<? extends IEdge> edges) {
final BasicGraph graph = new BasicGraph();
for (INodeID nodeId : nodes) {
graph.addNode(new Node(nodeId));
}
for (IEdge edge : edges) {
graph.addEdge(edge);
}
return graph;
}
/**
* Creates an edge-induced graph.
*
* The nodes are derived from the end nodes of the edges.
*
* @param edges
* the edges of the graph
*/
@SafeVarargs
public BasicGraph(IEdge... edges) {
this(Arrays.asList(edges));
}
@Override
......@@ -60,70 +140,127 @@ public class BasicGraph implements Graph {
public IEdge createEdge(INodeID from, INodeID to, double weight) {
IEdge edge = createEdge(from, to);
if (edge == null) {
return new DirectedEdge(from, to, weight);
return Graphs.createDirectedWeightedEdge(from, to, weight);
} else {
edge.setProperty(DirectedEdge.WEIGHT, weight);
edge.setProperty(GenericGraphElementProperties.WEIGHT, weight);
return edge;
}
}
@Override
public INode createNode(INodeID id) {
INode node = getNode(id);
return node != null ? node : new Node(id);
if (this.containsNode(id)) {
return this.getNode(id);
} else {
Node newNode = new Node(id);
this.addNode(newNode);
return newNode;
}
}
@Override
public boolean addElement(IElement element) {
if (element instanceof INode) {
INode node = (INode) element;
if (nodes.add(node)) {
// new node
nodesById.put(node.getId(), node);
return this.addNode((Node) element);
} else if (element instanceof IEdge) {
return this.addEdge((IEdge) element);
} else {
throw new AssertionError("Unknown graph element type.");
}
}
@Override
public boolean add(IElement element) {
return this.addElement(element);
}
@Override
public boolean addEdge(IEdge edge) {
this.ensureThatNodeIsInGraph(edge.toId());
this.ensureThatNodeIsInGraph(edge.fromId());
if (!this.containsEdge(edge)) {
this.edges.add(edge);
this.edgesById.put(edge.getId(), edge);
this.outgoingAdjacencyList.get(edge.fromId()).add(edge);
this.incomingAdjacencyList.get(edge.toId()).add(edge);
return true;
}
} else {
return false;
} else if (element instanceof IEdge) {
IEdge edge = (IEdge) element;
if (edges.add(edge)) {
// new edge, nodes needed?
if (getNode(edge.fromId()) == null) {
addElement(createNode(edge.fromId()));
}
if (getNode(edge.toId()) == null) {
addElement(createNode(edge.toId()));
}
@Override
public boolean addNode(INode node) {
if (!this.containsNode(node)) {
this.nodes.add(node);
this.nodesById.put(node.getId(), node);
this.incomingAdjacencyList.put(node.getId(), new HashSet<IEdge>());
this.outgoingAdjacencyList.put(node.getId(), new HashSet<IEdge>());
return true;
}
return false;
} else {
throw new AssertionError("Unknown graph element type.");
return false;
}
}
@Override
public void createAndAddNode(INodeID nodeId) {
this.addNode(this.createNode(nodeId));
}
@Override
public void createAndAddNodes(Iterable<INodeID> nodeIds) {
for (final INodeID nodeId : nodeIds)
this.createAndAddNode(nodeId);
}
@Override
public boolean removeElement(IElement element) {
if (element instanceof INode) {
INode node = (INode) element;
nodesById.remove(node.getId());
if (nodes.remove(node)) {
// deleted orphaned edges
Iterator<IEdge> it = edges.iterator();
while (it.hasNext()) {
IEdge edge = it.next();
if (edge.fromId().equals(node.getId())
|| edge.toId().equals(node.getId())) {
it.remove();
return removeNode((INode) element);
} else if (element instanceof IEdge) {
return removeEdge((IEdge) element);
} else {
throw new AssertionError("Unknown graph element type.");
}
}
@Override
public boolean removeNode(INodeID node) {
if (this.containsNode(node))
return this.removeNode(this.getNode(node));
return false;
}
private boolean removeNode(INode node) {
if (!this.containsNode(node.getId()))
return false;
final List<IEdge> edgesToRemove = new ArrayList<>();
for (final IEdge edge : this.getOutgoingEdges(node.getId()))
edgesToRemove.add(edge);
for (final IEdge edge : this.getIncomingEdges(node.getId()))
edgesToRemove.add(edge);
for (final IEdge edgeToRemove : edgesToRemove)
this.removeEdge(edgeToRemove);
nodesById.remove(node.getId());
nodes.remove(node);
return true;
}
@Override
public boolean removeEdge(IEdge edge) {
if (!this.containsEdge(edge))
return false;
} else if (element instanceof IEdge) {
return edges.remove(element);
} else {
throw new AssertionError("Unknown graph element type.");
}
this.incomingAdjacencyList.get(edge.toId()).remove(edge);
this.outgoingAdjacencyList.get(edge.fromId()).remove(edge);
this.edges.remove(edge);
this.edgesById.remove(edge.getId());
return true;
}
@Override
......@@ -131,9 +268,40 @@ public class BasicGraph implements Graph {
return nodes;
}
@Override
public Iterable<INodeID> getNodeIds() {
return this.nodesById.keySet();
}
@Override
public Set<EdgeID> getEdgeIds() {
return this.edgesById.keySet();
}
@Override
public int getNodeCount() {
return this.getNodes().size();
}
@Override
public Set<IEdge> getEdges() {
return this.edges;
return Collections.unmodifiableSet(this.edges);
}
@Override
public int getEdgeCount() {
return this.getEdges().size();
}
@Override
public boolean contains(IElement element) {
if (element instanceof INode)
return containsNode((INode) element);
else if (element instanceof IEdge)
return containsEdge((IEdge) element);
else
throw new IllegalArgumentException(
"Unsupported kind of element: " + element);
}
@Override
......@@ -141,6 +309,11 @@ public class BasicGraph implements Graph {
return nodesById.containsKey(nodeId);
}
@Override
public boolean containsNode(INode node) {
return this.containsNode(node.getId());
}
@Override
public INode getNode(INodeID nodeId) {
return nodesById.get(nodeId);
......@@ -156,6 +329,11 @@ public class BasicGraph implements Graph {
return null;
}
@Override
public IEdge getEdge(EdgeID edgeID) {
return this.edgesById.get(edgeID);
}
/**
* Computes subgraph of the currently known local view. This operation
* changes the current graph instead of cloning it.
......@@ -178,31 +356,39 @@ public class BasicGraph implements Graph {
Set<INodeID> kHopNodes = getNeighbors(center, k, false);
// determine edges
Set<IEdge> kHopEdges = new LinkedHashSet<IEdge>();
for (IEdge edge : g.edges) {
if (kHopNodes.contains(edge.fromId())
&& kHopNodes.contains(edge.toId())) {
kHopEdges.add(edge);
Set<IEdge> kHopEdges = new LinkedHashSet<>();
for (final INodeID kHopNode : kHopNodes) {
for (final IEdge outgoingEdge : this.getOutgoingEdges(kHopNode)) {
if (kHopNodes.contains(outgoingEdge.toId())) {
kHopEdges.add(outgoingEdge);
}
}
}
// modify g accordingly
Iterator<INode> itNodes = g.nodes.iterator();
while (itNodes.hasNext()) {
INode node = itNodes.next();
List<INode> nodesToBeRemoved = new ArrayList<>();
for (final INode node : this.getNodes()) {
if (!kHopNodes.contains(node.getId())) {
itNodes.remove();
g.nodesById.remove(node.getId());
nodesToBeRemoved.add(node);
}
}
for (final INode node : nodesToBeRemoved) {
g.removeElement(node);
}
g.edges.retainAll(kHopEdges);
assert checkGraphConsistency();
return g;
}
@Override
public void clear() {
this.nodes.clear();
this.edgesById.clear();
this.edges.clear();
this.incomingAdjacencyList.clear();
this.outgoingAdjacencyList.clear();
}
/**
* Returns the nodes contained in the k-hop neighborhood of the specified
* node. This includes the node itself.
......@@ -236,7 +422,8 @@ public class BasicGraph implements Graph {
private Set<INodeID> getNeighbors(INodeID node, int k,
boolean directedNeighborhood, LinkedHashSet<INodeID> visited) {
assert k >= 0;
if (k < 0)
throw new IllegalArgumentException("k must be >=0, but was " + k);
if (k == 0) {
visited.add(node);
......@@ -259,79 +446,51 @@ public class BasicGraph implements Graph {
return neighbors;
}
/**
* For the given node, compute the outgoing edges in the graph
*
* @param node
* a node contained in the graph
*
* @return
*/
@Override
public Set<IEdge> getOutgoingEdges(INodeID node) {
assert getNode(node) != null;
Set<IEdge> outgoingEdges = new LinkedHashSet<IEdge>();
for (IEdge directedEdge : this.edges) {
if (directedEdge.fromId().equals(node)) {
outgoingEdges.add(directedEdge);
ensureThatNodeIsInGraph(node);
return Collections
.unmodifiableSet(this.outgoingAdjacencyList.get(node));
}
}
return outgoingEdges;
}
/**
* For the given node, compute the incoming edges in the graph
*
* @param node
* a node contained in the graph
*
* @return
*/
@Override
public Set<IEdge> getIncomingEdges(INodeID node) {
assert getNode(node) != null;
Set<IEdge> incomingEdges = new LinkedHashSet<IEdge>();
for (IEdge directedEdge : this.edges) {
if (directedEdge.toId().equals(node)) {
incomingEdges.add(directedEdge);
ensureThatNodeIsInGraph(node);
return Collections
.unmodifiableSet(this.incomingAdjacencyList.get(node));
}
}
return incomingEdges;
}
/**
* returns the strict 1-hop neighbors of the specified node.
*
* If the directedNeighborhood flag is true, edge directions are considered
* for the neighborhood
*
*/
@Override
public Set<INodeID> getNeighbors(INodeID node, boolean directedNeighborhood) {
public Set<INodeID> getNeighbors(INodeID node,
boolean directedNeighborhood) {
Set<INodeID> neighbors = new LinkedHashSet<INodeID>();
for (IEdge edge : edges) {
if (edge.fromId().equals(node)) {
for (final IEdge edge : this.getOutgoingEdges(node))
neighbors.add(edge.toId());
} else if (!directedNeighborhood && edge.toId().equals(node)) {
// Also add start nodes of incoming links
if (!directedNeighborhood)
for (final IEdge edge : this.getIncomingEdges(node))
neighbors.add(edge.fromId());
return Collections.unmodifiableSet(neighbors);
}
}
return neighbors;
}
/**
* Returns the strict 1-hop neighbors of the specified node, considering
* nodes reachable via directed edges only.
*
* @see #getNeighbors(Node, int, boolean)
*/
@Override
public Set<INodeID> getNeighbors(INodeID node) {
return getNeighbors(node, true);
}
@Override
public Set<INodeID> getNeighbors(INode node) {
return getNeighbors(node.getId());
}
private void ensureThatNodeIsInGraph(INodeID node) {
if (!this.nodesById.containsKey(node))
throw new IllegalStateException(
"Node " + node + " is not contained in the graph");
}
@Override
public BasicGraph clone() {
/*
......@@ -339,18 +498,185 @@ public class BasicGraph implements Graph {
* cloned graph is just a new view.
*/
BasicGraph g = new BasicGraph();
for (INode node : this.nodes) {
g.addElement(node);
g.addNodes(this.nodes);
g.addEdges(this.edges);
return g;
}
@Override
public void addEdges(Iterable<? extends IEdge> edges) {
for (IEdge edge : edges) {
this.addEdge(edge);
}
for (IEdge directedEdge : this.edges) {
g.addElement(directedEdge);
}
return g;
@Override
public void addNodes(Iterable<? extends INode> nodes) {
for (INode node : nodes) {
this.addNode(node);
}
}
@Override
public String toString() {
return nodes.toString();
StringBuilder sb = new StringBuilder();
sb.append("Graph [V= ");
sb.append(this.nodes);
sb.append(", E= ");
sb.append(this.edgesById);
sb.append("]");
return sb.toString();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((edges == null) ? 0 : edges.hashCode());
result = prime * result + ((nodes == null) ? 0 : nodes.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
BasicGraph other = (BasicGraph) obj;
if (edges == null) {
if (other.edges != null)
return false;
} else if (!edges.equals(other.edges))
return false;
if (nodes == null) {
if (other.nodes != null)
return false;
} else if (!nodes.equals(other.nodes))
return false;
return true;
}
@Override
public void addElements(Iterable<? extends IElement> elements) {
for (final IElement element : elements) {
if (element instanceof INode)
this.addNode((INode) element);
}
for (final IElement element : elements) {
if (element instanceof IEdge)
this.addEdge((IEdge) element);
}
}
@Override
public boolean containsEdge(IEdge edge) {
return this.edges.contains(edge);
}
@Override
public int getOutdegree(INodeID id) {
return this.getOutgoingEdges(id).size();
}
@Override
public int getIndegree(INodeID node) {
return this.getIncomingEdges(node).size();
}
@Override
public Set<INodeID> getNeighbors(INode node, int k,
boolean directedNeighborhood) {
return getNeighbors(node.getId(), k, directedNeighborhood);
}
@Override
public Set<INodeID> getNeighbors(INode node, boolean directedNeighborhood) {
return getNeighbors(node.getId(), directedNeighborhood);
}
@Override
public boolean equalsAttributes(Graph otherGraph) {
if (otherGraph.getNodeCount() != this.getNodeCount()
|| otherGraph.getEdgeCount() != this.getEdgeCount())
return false;
for (final INode node : this.getNodes()) {
if (!otherGraph.containsNode(node))
return false;
}
for (final IEdge edge : this.getEdges()) {
if (!otherGraph.containsEdge(edge))
return false;
}
return false;
}
@Override
public boolean isBidirectional() {
if (this.getEdgeCount() % 2 != 0)
return false;
Set<IEdge> reverseEdgeSet = new HashSet<>();
for (final IEdge edge : this.getEdges()) {
reverseEdgeSet.add(new DirectedEdge(edge.toId(), edge.fromId()));
}
for (final IEdge edge : this.getEdges()) {
if (!this
.containsEdge(new DirectedEdge(edge.fromId(), edge.toId())))
return false;
}
return true;
}
@Override
public Iterable<INodeID> getIsolatedNodes() {
final List<INodeID> isolatedNodes = new ArrayList<>();
for (final INode node : this.getNodes()) {
if (this.getOutdegree(node.getId()) == 0
&& this.getIndegree(node.getId()) == 0) {
isolatedNodes.add(node.getId());
}
}
return isolatedNodes;
}
@Override
public Iterable<INodeID> getRootNodes() {
final List<INodeID> rootNodes = new ArrayList<>();
for (final INode node : this.getNodes()) {
if (this.getIndegree(node.getId()) == 0) {
rootNodes.add(node.getId());
}
}
return rootNodes;
}
@Override
public Iterable<INodeID> getLeafNodes() {
final List<INodeID> leafNodes = new ArrayList<>();
for (final INode node : this.getNodes()) {
if (this.getOutdegree(node.getId()) == 0) {
leafNodes.add(node.getId());
}
}
return leafNodes;
}
@Override
public Set<IEdge> getOutgoingEdges(INode node) {
return this.getOutgoingEdges(node.getId());
}
@Override
public Set<IEdge> getIncomingEdges(INode node) {
return this.getIncomingEdges(node.getId());
}
@Override
public boolean remove(IElement element) {
return this.removeElement(element);
}
}
......@@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import de.tudarmstadt.maki.simonstrator.api.Graphs;
import de.tudarmstadt.maki.simonstrator.api.component.sis.type.SiSType;
/**
......@@ -33,10 +34,15 @@ import de.tudarmstadt.maki.simonstrator.api.component.sis.type.SiSType;
*/
public class DirectedEdge implements IEdge {
public static final GraphElementProperty<Double> WEIGHT = new GraphElementProperty<>(
"WEIGHT", Double.class);
/**
* @deprecated Use {@link GenericGraphElementProperties#WEIGHT}
*/
@Deprecated
public static final GraphElementProperty<Double> WEIGHT = GenericGraphElementProperties.WEIGHT;
private final INodeID startNode, endNode;
private final INodeID startNode;
private final INodeID endNode;
private final EdgeID edgeId;
/**
* Node properties (attached objects)
......@@ -47,18 +53,75 @@ public class DirectedEdge implements IEdge {
* Creates an unweighted, directed edge
*/
public DirectedEdge(INodeID startNode, INodeID endNode) {
this(startNode, endNode, EdgeID.get(startNode, endNode));
}
public DirectedEdge(INodeID startNode, INodeID endNode, EdgeID edgeId) {
this.startNode = startNode;
this.endNode = endNode;
this.edgeId = edgeId;
}
/**
* @deprecated Only during the reconciliaiton
* @param startNode
* @param endNode
*/
public DirectedEdge(INode startNode, INode endNode) {
this(startNode.getId(), endNode.getId());
}
/**
* @deprecated Only during the reconciliaiton
* @param startNode
* @param endNode
*/
public DirectedEdge(INode startNode, INodeID endNode) {
this(startNode.getId(), endNode);
}
/**
* @deprecated Only during the reconciliaiton
* @param startNode
* @param endNode
*/
public DirectedEdge(INodeID startNode, INode endNode) {
this(startNode, endNode.getId());
}
/**
* Creates an unweighted, directed edge
*/
public DirectedEdge(Node startNode, Node endNode, String id) {
this(startNode.getId(), endNode.getId(), EdgeID.get(id));
}
/**
* Creates an weighted, directed edge
*
* @deprecated Use
* {@link Graphs#createDirectedWeightedEdge(INodeID, INodeID, double)}
*/
public DirectedEdge(INodeID startNode, INodeID endNode, double weight) {
@Deprecated
public DirectedEdge(INodeID startNode, INodeID endNode, Double weight) {
this(startNode, endNode);
if (!Double.isNaN(weight)) {
this.properties.put(WEIGHT, weight);
if (weight != null && !Double.isNaN(weight)) {
this.properties.put(GenericGraphElementProperties.WEIGHT, weight);
}
}
/**
* @deprecated Only for reconciliation
* @param startNode
* @param endNode
* @param weight
*/
public DirectedEdge(INode startNode, INode endNode, double weight) {
this(startNode.getId(), endNode.getId(), weight);
}
public DirectedEdge(INodeID startNode, INodeID endNode, String id) {
this(startNode, endNode, EdgeID.get(id));
}
@Override
......@@ -71,6 +134,11 @@ public class DirectedEdge implements IEdge {
return endNode;
}
@Override
public EdgeID getId() {
return this.edgeId;
}
@SuppressWarnings("unchecked")
@Override
public <T> T getProperty(SiSType<T> property) {
......@@ -102,12 +170,14 @@ public class DirectedEdge implements IEdge {
properties.clear();
}
@Override
public boolean isWeighted() {
return properties.containsKey(WEIGHT);
return properties.containsKey(GenericGraphElementProperties.WEIGHT);
}
public double getWeight() {
return (double) properties.get(WEIGHT);
@Override
public Double getWeight() {
return (Double) properties.get(GenericGraphElementProperties.WEIGHT);
}
......
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of Simonstrator.KOM.
*
* Simonstrator.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tudarmstadt.maki.simonstrator.api.common.graph;
import java.util.LinkedHashMap;
import java.util.Map;
import de.tudarmstadt.maki.simonstrator.api.common.UniqueID;
public class EdgeID implements UniqueID {
private static final long serialVersionUID = 1L;
private final long id;
private String stringId;
private final transient static Map<Long, EdgeID> ids = new LinkedHashMap<>();
private final transient static Map<String, EdgeID> stringIds = new LinkedHashMap<>();
public static EdgeID get(long longId) {
EdgeID id = ids.get(longId);
if (id == null) {
id = new EdgeID(longId);
ids.put(longId, id);
}
return id;
}
public static EdgeID get(String str) {
EdgeID id = stringIds.get(str);
if (id == null) {
id = new EdgeID(str);
stringIds.put(str, id);
}
return id;
}
public static EdgeID get(INodeID startNode, INodeID endNode) {
return get(startNode.valueAsString() + "->" + endNode.valueAsString());
}
/**
* Private constructor
*
* @param id
*/
protected EdgeID(long id) {
this.id = id;
this.stringId = Long.toString(this.id);
}
public EdgeID(String stringId) {
this.id = stringId.hashCode();
this.stringId = stringId;
}
@Override
public long value() {
return id;
}
@Override
public String valueAsString() {
return this.stringId;
}
@Override
public int getTransmissionSize() {
// a long ID
return 8;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (id ^ (id >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
EdgeID other = (EdgeID) obj;
if (id != other.id)
return false;
return true;
}
@Override
public String toString() {
return this.stringId;
}
@Override
public int compareTo(UniqueID o) {
return Long.compare(id, o.value());
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of Simonstrator.KOM.
*
* Simonstrator.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tudarmstadt.maki.simonstrator.api.common.graph;
import java.util.function.Function;
public class EdgeIDToEdgeMapper implements Function<EdgeID, IEdge> {
private Graph graph;
public EdgeIDToEdgeMapper(final Graph graph) {
this.graph = graph;
}
@Override
public IEdge apply(EdgeID edgeId) {
return this.graph.getEdge(edgeId);
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of Simonstrator.KOM.
*
* Simonstrator.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tudarmstadt.maki.simonstrator.api.common.graph;
/**
* This interface collects widely used graph element properties
*/
public interface GenericGraphElementProperties {
/**
* Edge weight
*/
public static final GraphElementProperty<Double> WEIGHT = new GraphElementProperty<>(
"WEIGHT", Double.class);
}
......@@ -20,6 +20,7 @@
package de.tudarmstadt.maki.simonstrator.api.common.graph;
import java.util.Collection;
import java.util.Set;
/**
......@@ -47,15 +48,16 @@ public interface Graph extends Cloneable {
* graph, that edge is returned instead and no new instance is created.
*
* @param from
* the ID of the source node
* @param to
* the ID of the target node
* @return
*/
public IEdge createEdge(INodeID from, INodeID to);
/**
* Create and return a weighted edge. The edge is <strong>not</strong> yet
* added to the graph. In case the same edge already exists in the graph,
* that edge is returned instead.
* added to the graph.
*
* @param from
* @param to
......@@ -81,6 +83,61 @@ public interface Graph extends Cloneable {
*/
public boolean addElement(IElement element);
/**
* @deprecated Only during the reconciliation phase for the new graph API
*/
public boolean add(IElement element);
/**
* Adds the given elements to the graph.
*
* An implementation should typically call {@link #addElement(IElement)} on
* each element of the given sequence.
*
*/
public void addElements(Iterable<? extends IElement> elements);
/**
* Adds the given edge to the graph.
*
* @param edge
*
* @precondition the graph needs to contain the source and target nodes
* already
*/
boolean addEdge(IEdge edge);
/**
* Adds all of the given edges to the graph.
*
* The result should be equal to adding all contained edges via
* {@link #addEdge(IEdge)}
*
* @param edges
*
* @precondition the graph needs to contain the source and target nodes
* already
*/
void addEdges(Iterable<? extends IEdge> edges);
/**
* Adds the given node to the graph
*
* @param node
*/
boolean addNode(INode node);
/**
* Adds all of the given nodes to the graph
*
* @param nodes
*/
void addNodes(Iterable<? extends INode> nodes);
void createAndAddNodes(Iterable<INodeID> nodeIds);
void createAndAddNode(INodeID nodeId);
/**
* Remove the given {@link IElement} from the graph. In case of nodes, all
* edges referring to the given node are also deleted. Orphaned nodes, e.g.,
......@@ -92,6 +149,33 @@ public interface Graph extends Cloneable {
*/
public boolean removeElement(IElement element);
/**
* @deprecated
* @param element
* @return
*/
public boolean remove(IElement element);
/**
* Removes the node with the given id from the graph. If no such node
* exists, nothing happens.
*
* @return whether the graph has changed
*/
public boolean removeNode(final INodeID node);
public boolean removeEdge(final IEdge edgeID);
/**
* Removes all nodes and edges from the graph
*/
public void clear();
/**
* Returns whether the element is contained in the graph
*/
public boolean contains(IElement element);
/**
* True, if the given node is contained in the graph
*
......@@ -100,6 +184,22 @@ public interface Graph extends Cloneable {
*/
public boolean containsNode(INodeID nodeId);
/**
* True, if the given node is contained in the graph
*
* @param nodeId
* @return
*/
boolean containsNode(INode node);
/**
* True, if the given edge is contained in the graph
*
* @param edge
* @return
*/
public boolean containsEdge(IEdge edge);
/*
* Graph Interface and convenience methods
*/
......@@ -109,14 +209,17 @@ public interface Graph extends Cloneable {
*
* @return
*/
public Set<IEdge> getEdges();
public Set<? extends IEdge> getEdges();
/**
* Returns all nodes in the graph
* HEAD Returns the number of edges in this graph.
*
* Should be equal to calling {@link Collection#size()} on the result of
* {@link #getEdges()}.
*
* @return
*/
public Set<INode> getNodes();
public int getEdgeCount();
/**
* Returns the node with the given ID if existent in the graph. null
......@@ -136,10 +239,38 @@ public interface Graph extends Cloneable {
*/
public IEdge getEdge(INodeID from, INodeID to);
/**
* Returns the edge with the given ID.
*
* @param edgeID
* @return
*/
public IEdge getEdge(EdgeID edgeID);
/*
* Convenience methods
*/
/**
* Returns the unmodifiable set of nodes of this graph
*
* @return the nodes
*/
public Set<? extends INode> getNodes();
/**
* Returns the number of nodes in this graph.
*
* Should be equal to calling {@link Collection#size()} on the result of
* {@link #getNodes()}.
*
* @return
*/
public int getNodeCount();
/*
* Convenience methods
*/
/**
* Computes subgraph of the currently known local view. This operation
* changes the current graph instead of cloning it.
......@@ -163,6 +294,20 @@ public interface Graph extends Cloneable {
*/
public Set<IEdge> getOutgoingEdges(INodeID node);
/**
* @deprecated
* @param node
* @return
*/
public Set<IEdge> getOutgoingEdges(INode node);
/**
* Returns the number of outgoing links of this node. Should be equal to
* calling {@link Set#size()} on the result of
* {@link #getOutgoingEdges(Node)}.
*/
public int getOutdegree(INodeID node);
/**
* For the given node, compute the incoming edges in the graph
*
......@@ -173,6 +318,20 @@ public interface Graph extends Cloneable {
*/
public Set<IEdge> getIncomingEdges(INodeID node);
/**
* @deprecated
* @param node
* @return
*/
public Set<IEdge> getIncomingEdges(INode node);
/**
* Returns the number of incoming links to this node. Should be equal to
* calling {@link Set#size()} on the result of
* {@link #getIncomingEdges(Node)}.
*/
public int getIndegree(INodeID node);
/**
* Returns the nodes contained in the k-hop neighborhood of the specified
* node. This includes the node itself.
......@@ -184,22 +343,45 @@ public interface Graph extends Cloneable {
boolean directedNeighborhood);
/**
* returns the strict 1-hop neighbors of the specified node.
* Returns the nodes contained in the k-hop neighborhood of the specified
* node. This includes the node itself.
*
* If the directedNeighborhood flag is true, edge directions are considered
* for the neighborhood
*/
public Set<INodeID> getNeighbors(INode node, int k,
boolean directedNeighborhood);
/**
* returns the strict 1-hop neighbors of the specified node.
*
* If the directedNeighborhood flag is true, only outgoing neighbors are
* considered. If the directedNeighborhood flag is false, incoming and
* outgoing neighbors are considered.
*
* @precondition node is contained in the graph
*/
public Set<INodeID> getNeighbors(INodeID node,
boolean directedNeighborhood);
public Set<INodeID> getNeighbors(INode node, boolean directedNeighborhood);
/**
* Returns the union of all graph elemtents, that is, all nodes and edges.
*/
public Set<INodeID> getNeighbors(INodeID node, boolean directedNeighborhood);
/**
* Returns the strict 1-hop neighbors of the specified node, considering
* nodes reachable via directed edges only.
*
* @see #getNeighbors(Node, int, boolean)
*/
public Set<INodeID> getNeighbors(INodeID node);
/**
* Returns the strict 1-hop neighbors of the specified node, considering
* nodes reachable via directed edges only.
*/
public Set<INodeID> getNeighbors(INode node);
/**
* Clones the graph (returns a new view that can be modified). Please note:
* the underlying objects (nodes, edges) are <strong>NOT</strong> cloned!
......@@ -211,4 +393,53 @@ public interface Graph extends Cloneable {
*/
public Graph clone();
/**
* The equals() method checks only equality based on the equal method in the
* Node and DirectedEdge implementations. These implementations do not
* compare all attributes. This method compares two graphs based on the
*
* @deprecated This functionality should be implemented using a comparator
*/
public boolean equalsAttributes(Graph otherGraph);
/**
* Returns true if for each directed edge there exists an edge into the
* reverse direction (does not consider edge weight or other attributes)
*
* @deprecated Use GraphUtil#isSymmetric instead
*/
public boolean isBidirectional();
/**
* Returns a sequence of isolated nodes, that is, nodes that have incident
* edges.
*/
public Iterable<INodeID> getIsolatedNodes();
/**
* Returns the set of nodes that have only incoming edges.
*/
public Iterable<INodeID> getLeafNodes();
/**
* Returns the sequence of nodes that have only outgoing edges.
*
* @return
*/
Iterable<INodeID> getRootNodes();
/**
* Returns the sequence of node IDs of this graph.
*/
public Iterable<INodeID> getNodeIds();
/**
* Returns the sequence of node IDs
*
* @return
*/
public Set<EdgeID> getEdgeIds();
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of Simonstrator.KOM.
*
* Simonstrator.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tudarmstadt.maki.simonstrator.api.common.graph;
import de.tudarmstadt.maki.simonstrator.api.Graphs;
public class GraphBuilder {
private Graph graph;
private GraphBuilder() {
this.graph = Graphs.createGraph();
}
public static GraphBuilder create() {
return new GraphBuilder();
}
public Graph done() {
return this.graph;
}
public GraphBuilder addEdge(String sourceId, String targetId) {
this.graph.addEdge(
new DirectedEdge(INodeID.get(sourceId), INodeID.get(targetId)));
return this;
}
public GraphBuilder addEdge(String sourceId, String targetId,
String edgeId) {
INodeID sourceNodeId = INodeID.get(sourceId);
INodeID targetNodeId = INodeID.get(targetId);
if (!this.graph.containsNode(sourceNodeId)) {
this.graph.createAndAddNode(sourceNodeId);
}
if (!this.graph.containsNode(targetNodeId)) {
this.graph.createAndAddNode(targetNodeId);
}
this.graph.addEdge(new DirectedEdge(sourceNodeId, targetNodeId,
EdgeID.get(targetId)));
return this;
}
public GraphBuilder addEdge(String sourceId, String targetId, String edgeId,
double weight) {
INodeID sourceNodeId = INodeID.get(sourceId);
INodeID targetNodeId = INodeID.get(targetId);
if (!this.graph.containsNode(sourceNodeId)) {
this.graph.createAndAddNode(sourceNodeId);
}
if (!this.graph.containsNode(targetNodeId)) {
this.graph.createAndAddNode(targetNodeId);
}
this.graph.addEdge(Graphs.createDirectedWeightedEdge(
INodeID.get(sourceId), INodeID.get(targetId), weight));
return this;
}
}
......@@ -47,4 +47,22 @@ public interface IEdge extends IElement {
*/
public INodeID toId();
public EdgeID getId();
/**
* Only during transition phase
*
* @return
*/
@Deprecated
public Double getWeight();
/**
* Only during transition phase
*
* @return
*/
@Deprecated
public boolean isWeighted();
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of Simonstrator.KOM.
*
* Simonstrator.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tudarmstadt.maki.simonstrator.api.common.graph;
import de.tudarmstadt.maki.simonstrator.api.component.sis.type.SiSType;
/**
* Graph element property. In most cases you should be able to use the available
* {@link SiSType}s. If no matching type is registered, or you need custom
* properties, just create an instance of this class. The resulting
* {@link SiSType} is <strong>NOT</strong> added to the global SiS namespace
* (SiSTypes).
*
* @author Bjoern Richerzhagen
*
*/
public class IElementProperty<T> extends SiSType<T> {
public IElementProperty(String name, Class<T> valueType) {
/*
* To avoid collisions, a name prefix is added.
*/
super("IElementProperty-" + name, valueType, null);
}
}
......@@ -39,8 +39,10 @@ public class INodeID implements UniqueID {
private static final long serialVersionUID = 1L;
private final long id;
private String stringId;
private final transient static Map<Long, INodeID> ids = new LinkedHashMap<>();
protected final transient static Map<Long, INodeID> ids = new LinkedHashMap<>();
protected final transient static Map<String, INodeID> stringIds = new LinkedHashMap<>();
public static INodeID get(long longId) {
INodeID id = ids.get(longId);
......@@ -51,6 +53,15 @@ public class INodeID implements UniqueID {
return id;
}
public static INodeID get(String str) {
INodeID id = stringIds.get(str);
if (id == null) {
id = new INodeID(str);
stringIds.put(str, id);
}
return id;
}
/**
* Private constructor
*
......@@ -58,17 +69,24 @@ public class INodeID implements UniqueID {
*/
protected INodeID(long id) {
this.id = id;
this.stringId = Long.toString(this.id);
}
/**
* Numerical value of this ID as long
*
* @return
*/
public INodeID(String stringId) {
this.id = stringId.hashCode();
this.stringId = stringId;
}
@Override
public long value() {
return id;
}
@Override
public String valueAsString() {
return this.stringId;
}
@Override
public int getTransmissionSize() {
// a long ID
......@@ -99,7 +117,7 @@ public class INodeID implements UniqueID {
@Override
public String toString() {
return Long.toString(id);
return this.stringId;
}
@Override
......
......@@ -54,6 +54,24 @@ public class Node implements INode {
this.id = id;
}
/**
* @deprecated Only during the reconciliation
* @param id
*/
// TODO MS
public Node(int id) {
this(INodeID.get(id));
}
/**
* @deprecated Only during the reconciliation
* @param str
*/
// TODO MS
public Node(String str) {
this(INodeID.get(str.hashCode())); // TODO@rkluge FIXME
}
@Override
public INodeID getId() {
return id;
......
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of Simonstrator.KOM.
*
* Simonstrator.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tudarmstadt.maki.simonstrator.api.common.graph;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
/******************************************************************************
* Compilation: javac TarjanSCC.java
* Execution: Java TarjanSCC V E
* Dependencies: Graph.java Stack.java TransitiveClosure.java StdOut.java
*
* Compute the strongly-connected components of a Graph using
* Tarjan's algorithm.
*
* Runs in O(E + V) time.
*
* % java TarjanSCC tinyDG.txt
* 5 components
* 1
* 0 2 3 4 5
* 9 10 11 12
* 6 8
* 7
*
******************************************************************************/
/**
* The <tt>TarjanSCC</tt> class represents a data type for determining the
* strong components in a Graph. The <em>id</em> operation determines in which
* strong component a given vertex lies; the <em>areStronglyConnected</em>
* operation determines whether two vertices are in the same strong component;
* and the <em>count</em> operation determines the number of strong components.
*
* The <em>component identifier</em> of a component is one of the vertices in
* the strong component: two vertices have the same component identifier if and
* only if they are in the same strong component.
*
* <p>
* This implementation uses Tarjan's algorithm. The constructor takes time
* proportional to <em>V</em> + <em>E</em> (in the worst case), where <em>V</em>
* is the number of vertices and <em>E</em> is the number of edges. Afterwards,
* the <em>id</em>, <em>count</em>, and <em>areStronglyConnected</em> operations
* take constant time. For alternate implementations of the same API, see
* {@link KosarajuSharirSCC} and {@link GabowSCC}.
* <p>
* For additional documentation, see <a href="/algs4/42Graph">Section 4.2</a> of
* <i>Algorithms, 4th Edition</i> by Robert Sedgewick and Kevin Wayne.
*
* @author Robert Sedgewick
* @author Kevin Wayne
*
* @see http://algs4.cs.princeton.edu/42directed/TarjanSCC.java.html
*/
public class TarjanSCC {
private boolean[] marked; // marked[v] = has v been visited?
private int[] sccId; // id[v] = id of strong component containing v
private int[] low; // low[v] = low number of v
private int pre; // preorder number counter
private int count; // number of strongly-connected components
private Stack<Integer> stack;
private Map<INodeID, Integer> nodeToId = new HashMap<>();
/**
* Computes the strong components of the Graph <tt>G</tt>.
*
* @param graph
* the Graph
*/
public TarjanSCC(Graph graph) {
int nodeCount = graph.getNodeCount();
marked = new boolean[nodeCount];
stack = new Stack<Integer>();
sccId = new int[nodeCount];
low = new int[nodeCount];
for (final INode node : graph.getNodes()) {
nodeToId.put(node.getId(), nodeToId.size());
}
for (final INode node : graph.getNodes()) {
int v = this.nodeToId.get(node.getId());
if (!marked[v])
dfs(graph, node.getId());
}
}
private void dfs(Graph graph, INodeID node) {
int v = this.nodeToId.get(node);
marked[v] = true;
low[v] = pre++;
int min = low[v];
stack.push(v);
for (final INodeID neighbor : graph.getNeighbors(node)) {
int w = this.nodeToId.get(neighbor);
if (!marked[w])
dfs(graph, neighbor);
if (low[w] < min)
min = low[w];
}
if (min < low[v]) {
low[v] = min;
return;
}
int w;
do {
w = stack.pop();
sccId[w] = count;
low[w] = graph.getNodeCount();
} while (w != v);
count++;
}
/**
* Returns the number of strong components.
*
* @return the number of strong components
*/
public int getNumberOfSccs() {
return count;
}
/**
* Are vertices <tt>v</tt> and <tt>w</tt> in the same strong component?
*
* @param v
* one vertex
* @param w
* the other vertex
* @return <tt>true</tt> if vertices <tt>v</tt> and <tt>w</tt> are in the
* same strong component, and <tt>false</tt> otherwise
*/
public boolean stronglyConnected(Node v, Node w) {
return sccId[this.nodeToId.get(v)] == sccId[this.nodeToId.get(w)];
}
/**
* Returns the component id of the strong component containing vertex
* <tt>v</tt>.
*
* @param v
* the vertex
* @return the component id of the strong component containing vertex
* <tt>v</tt>
*/
public int getSccId(INodeID v) {
return sccId[this.nodeToId.get(v)];
}
public Iterable<Set<INodeID>> getSCCs() {
Map<Integer, Set<INodeID>> sccIdToNodes = new HashMap<>();
for (int scc = 0; scc < this.getNumberOfSccs(); ++scc) {
sccIdToNodes.put(scc, new HashSet<INodeID>());
}
for (final INodeID v : this.nodeToId.keySet()) {
sccIdToNodes.get(this.getSccId(v)).add(v);
}
return sccIdToNodes.values();
}
}
/*
* Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
*
* This file is part of Simonstrator.KOM.
*
* Simonstrator.KOM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* PeerfactSim.KOM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PeerfactSim.KOM. If not, see <http://www.gnu.org/licenses/>.
*
*/
package de.tudarmstadt.maki.simonstrator.api.component.topology;
public interface ITopologyChangedEvent {
public TopologyProvider getTopologyProvider();
public TopologyID getTopologyIdentifier();
}
......@@ -20,7 +20,9 @@
package de.tudarmstadt.maki.simonstrator.api.component.topology;
import de.tudarmstadt.maki.simonstrator.api.Graphs;
import de.tudarmstadt.maki.simonstrator.api.common.graph.DirectedEdge;
import de.tudarmstadt.maki.simonstrator.api.common.graph.GenericGraphElementProperties;
import de.tudarmstadt.maki.simonstrator.api.common.graph.IEdge;
import de.tudarmstadt.maki.simonstrator.api.common.graph.INodeID;
......@@ -72,7 +74,9 @@ public class OperationalEdge extends DirectedEdge {
private EdgeOperationType type;
public OperationalEdge(IEdge edge, EdgeOperationType type) {
super(edge.fromId(), edge.toId(), edge.getProperty(DirectedEdge.WEIGHT));
super(edge.fromId(), edge.toId());
this.setProperty(GenericGraphElementProperties.WEIGHT,
edge.getProperty(GenericGraphElementProperties.WEIGHT));
this.type = type;
}
......@@ -90,8 +94,8 @@ public class OperationalEdge extends DirectedEdge {
this.type = type;
}
public DirectedEdge getEdge() {
return new DirectedEdge(this.fromId(), this.toId(),
public IEdge getEdge() {
return Graphs.createDirectedWeightedEdge(this.fromId(), this.toId(),
this.getWeight());
}
......
package de.tudarmstadt.maki.simonstrator.api.component.topology;
/**
* This event signals that a local topology has changed.
*
* Clients may query the topology provider and the changed topology (via its identifier) from the event.
*/
public class TopologyChangedEvent implements ITopologyChangedEvent {
public final TopologyProvider topology;
public final TopologyID topologyIdentifier;
public TopologyChangedEvent(final TopologyProvider topology, final TopologyID topologyIdentifier) {
this.topology = topology;
this.topologyIdentifier = topologyIdentifier;
}
public TopologyProvider getTopologyProvider() {
return topology;
}
public TopologyID getTopologyIdentifier() {
return topologyIdentifier;
}
@Override
public String toString() {
return "TopologyChangedEvent";
}
}
......@@ -33,6 +33,7 @@ import java.util.LinkedHashMap;
* @author Bjoern Richerzhagen
*
*/
// TODO BR: It would be nice to have an explicit "getId" method here (rkluge)
public final class TopologyID {
private final String stringRepresentation;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment