Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Simonstrator
API
Commits
0b39dee1
Commit
0b39dee1
authored
Aug 17, 2016
by
Roland Kluge
Browse files
Extend Graph with data structures for storing inverse edge pairs
parent
8f0b330b
Changes
2
Hide whitespace changes
Inline
Side-by-side
src/de/tudarmstadt/maki/simonstrator/api/common/graph/BasicGraph.java
View file @
0b39dee1
...
...
@@ -32,6 +32,9 @@ import java.util.List;
import
java.util.Map
;
import
java.util.Set
;
import
com.google.common.collect.BiMap
;
import
com.google.common.collect.HashBiMap
;
import
de.tudarmstadt.maki.simonstrator.api.Graphs
;
/**
...
...
@@ -65,6 +68,10 @@ public class BasicGraph implements Graph {
// Assigns to each node the set of predecessors of this node
private
final
Map
<
INodeID
,
HashSet
<
INodeID
>>
predecessorNodes
=
new
HashMap
<>();
// Maps an edge to its inverse edge. Each pair of edges should only be
// contained once (i.e., check both directions).
private
BiMap
<
IEdge
,
IEdge
>
inverseEdgeMapping
=
HashBiMap
.
create
();
/**
* Creates an empty graph. Components should create new graphs by using the
* {@link Graphs} class in the API
...
...
@@ -83,8 +90,7 @@ public class BasicGraph implements Graph {
* 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
)
{
public
BasicGraph
(
Iterable
<?
extends
INode
>
nodes
,
Iterable
<?
extends
IEdge
>
edges
)
{
this
();
for
(
final
INode
node
:
nodes
)
...
...
@@ -111,8 +117,7 @@ public class BasicGraph implements Graph {
this
.
addElements
(
edges
);
}
public
static
BasicGraph
createGraphFromNodeIdsAndEdges
(
Iterable
<?
extends
INodeID
>
nodes
,
public
static
BasicGraph
createGraphFromNodeIdsAndEdges
(
Iterable
<?
extends
INodeID
>
nodes
,
Iterable
<?
extends
IEdge
>
edges
)
{
final
BasicGraph
graph
=
new
BasicGraph
();
for
(
INodeID
nodeId
:
nodes
)
{
...
...
@@ -190,11 +195,11 @@ public class BasicGraph implements Graph {
this
.
incomingAdjacencyList
.
get
(
edge
.
toId
()).
add
(
edge
);
this
.
successorNodes
.
get
(
edge
.
fromId
()).
add
(
edge
.
toId
());
this
.
predecessorNodes
.
get
(
edge
.
toId
()).
add
(
edge
.
fromId
());
return
true
;
return
true
;
}
else
{
return
false
;
}
}
}
}
@Override
public
boolean
addNode
(
INode
node
)
{
...
...
@@ -205,11 +210,11 @@ public class BasicGraph implements Graph {
this
.
outgoingAdjacencyList
.
put
(
node
.
getId
(),
new
HashSet
<
IEdge
>());
this
.
successorNodes
.
put
(
node
.
getId
(),
new
HashSet
<
INodeID
>());
this
.
predecessorNodes
.
put
(
node
.
getId
(),
new
HashSet
<
INodeID
>());
return
true
;
return
true
;
}
else
{
return
false
;
}
}
}
@Override
public
void
createAndAddNode
(
INodeID
nodeId
)
{
...
...
@@ -231,14 +236,14 @@ public class BasicGraph implements Graph {
}
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
()))
...
...
@@ -257,8 +262,8 @@ public class BasicGraph implements Graph {
nodesById
.
remove
(
node
.
getId
());
nodes
.
remove
(
node
);
return
true
;
}
return
true
;
}
@Override
public
boolean
removeEdge
(
IEdge
edge
)
{
...
...
@@ -315,8 +320,7 @@ public class BasicGraph implements Graph {
else
if
(
element
instanceof
IEdge
)
return
containsEdge
((
IEdge
)
element
);
else
throw
new
IllegalArgumentException
(
"Unsupported kind of element: "
+
element
);
throw
new
IllegalArgumentException
(
"Unsupported kind of element: "
+
element
);
}
@Override
...
...
@@ -378,6 +382,35 @@ public class BasicGraph implements Graph {
return
this
.
edgesById
.
get
(
edgeID
);
}
@Override
public
IEdge
getInverseEdge
(
EdgeID
edgeId
)
{
final
IEdge
edge
=
getEdge
(
edgeId
);
if
(
edge
==
null
)
throw
new
IllegalArgumentException
(
"Cannot retrieve inverse edge of "
+
edgeId
+
" because "
+
edgeId
+
" is not contained in this graph"
);
return
getInverseEdge
(
edge
);
}
@Override
public
IEdge
getInverseEdge
(
IEdge
edge
)
{
final
IEdge
forwardLookup
=
inverseEdgeMapping
.
get
(
edge
);
if
(
forwardLookup
==
null
)
{
return
inverseEdgeMapping
.
inverse
().
get
(
edge
);
}
return
forwardLookup
;
}
@Override
public
void
makeInverseEdges
(
EdgeID
forwardEdgeId
,
EdgeID
backwardEdgeId
)
{
this
.
makeInverseEdges
(
getEdge
(
forwardEdgeId
),
getEdge
(
backwardEdgeId
));
}
@Override
public
void
makeInverseEdges
(
IEdge
forwardEdge
,
IEdge
backwardEdge
)
{
if
(!
forwardEdge
.
equals
(
this
.
getInverseEdge
(
backwardEdge
)))
this
.
inverseEdgeMapping
.
put
(
forwardEdge
,
backwardEdge
);
}
/**
* Computes subgraph of the currently known local view. This operation
* changes the current graph instead of cloning it.
...
...
@@ -414,7 +447,7 @@ public class BasicGraph implements Graph {
if
(!
kHopNodes
.
contains
(
node
.
getId
()))
{
nodesToBeRemoved
.
add
(
node
);
}
}
}
for
(
final
INode
node
:
nodesToBeRemoved
)
{
g
.
removeElement
(
node
);
}
...
...
@@ -427,12 +460,14 @@ public class BasicGraph implements Graph {
@Override
public
void
clear
()
{
this
.
nodes
.
clear
();
this
.
edg
esById
.
clear
();
this
.
nod
esById
.
clear
();
this
.
edges
.
clear
();
this
.
edgesById
.
clear
();
this
.
incomingAdjacencyList
.
clear
();
this
.
outgoingAdjacencyList
.
clear
();
this
.
predecessorNodes
.
clear
();
this
.
successorNodes
.
clear
();
this
.
inverseEdgeMapping
.
clear
();
}
/**
...
...
@@ -443,8 +478,7 @@ public class BasicGraph implements Graph {
* for the neighborhood
*/
@Override
public
Set
<
INodeID
>
getNeighbors
(
INodeID
center
,
int
k
,
boolean
directedNeighborhood
)
{
public
Set
<
INodeID
>
getNeighbors
(
INodeID
center
,
int
k
,
boolean
directedNeighborhood
)
{
// assert (getNeighbors(center, k, directedNeighborhood, new
// LinkedHashSet<INodeID>())
// .equals(getNeighborsIter(center, k, directedNeighborhood)));
...
...
@@ -458,8 +492,7 @@ public class BasicGraph implements Graph {
*/
private
boolean
checkGraphConsistency
()
{
for
(
IEdge
directedEdge
:
edges
)
{
if
(!
nodesById
.
containsKey
(
directedEdge
.
fromId
())
||
!
nodesById
.
containsKey
(
directedEdge
.
toId
()))
{
if
(!
nodesById
.
containsKey
(
directedEdge
.
fromId
())
||
!
nodesById
.
containsKey
(
directedEdge
.
toId
()))
{
return
false
;
}
}
...
...
@@ -468,41 +501,39 @@ public class BasicGraph implements Graph {
}
// helper method
private
Set
<
INodeID
>
getNeighborsIter
(
INodeID
node
,
int
k
,
boolean
directedNeighborhood
)
{
private
Set
<
INodeID
>
getNeighborsIter
(
INodeID
node
,
int
k
,
boolean
directedNeighborhood
)
{
HashSet
<
INodeID
>
visited
=
new
HashSet
<
INodeID
>();
HashSet
<
INodeID
>
visited
=
new
HashSet
<
INodeID
>();
// visited.add(node);
if
(
k
<
0
)
throw
new
IllegalArgumentException
(
"k must be >=0, but was "
+
k
);
if
(
k
==
0
)
{
return
visited
;
}
if
(
k
<
0
)
throw
new
IllegalArgumentException
(
"k must be >=0, but was "
+
k
);
if
(
k
==
0
)
{
return
visited
;
}
HashSet
<
INodeID
>
neighbors
=
new
HashSet
<
INodeID
>();
HashSet
<
INodeID
>
newNeighbors
=
new
HashSet
<
INodeID
>();
neighbors
.
add
(
node
);
for
(
int
i
=
k
;
i
>
0
;
i
--)
{
for
(
INodeID
neighbor
:
neighbors
)
{
if
(
visited
.
add
(
neighbor
))
newNeighbors
.
addAll
(
getNeighbors
(
neighbor
,
directedNeighborhood
));
}
}
neighbors
=
new
HashSet
<
INodeID
>(
newNeighbors
);
newNeighbors
.
clear
();
}
visited
.
addAll
(
neighbors
);
return
visited
;
}
// helper method, replaced by getNeighborsIter which is thought to be more
// efficient
@SuppressWarnings
(
"unused"
)
private
Set
<
INodeID
>
getNeighbors
(
INodeID
node
,
int
k
,
boolean
directedNeighborhood
,
HashSet
<
INodeID
>
visited
)
{
private
Set
<
INodeID
>
getNeighbors
(
INodeID
node
,
int
k
,
boolean
directedNeighborhood
,
HashSet
<
INodeID
>
visited
)
{
if
(
k
<
0
)
throw
new
IllegalArgumentException
(
"k must be >=0, but was "
+
k
);
...
...
@@ -521,8 +552,7 @@ public class BasicGraph implements Graph {
for
(
INodeID
neighbor
:
getNeighbors
(
node
,
directedNeighborhood
))
{
if
(!
visited
.
contains
(
neighbor
))
neighbors
.
addAll
(
getNeighbors
(
neighbor
,
k
-
1
,
directedNeighborhood
,
visited
));
neighbors
.
addAll
(
getNeighbors
(
neighbor
,
k
-
1
,
directedNeighborhood
,
visited
));
}
return
neighbors
;
...
...
@@ -531,20 +561,17 @@ public class BasicGraph implements Graph {
@Override
public
Set
<
IEdge
>
getOutgoingEdges
(
INodeID
node
)
{
ensureThatNodeIsInGraph
(
node
);
return
Collections
.
unmodifiableSet
(
this
.
outgoingAdjacencyList
.
get
(
node
));
}
return
Collections
.
unmodifiableSet
(
this
.
outgoingAdjacencyList
.
get
(
node
));
}
@Override
public
Set
<
IEdge
>
getIncomingEdges
(
INodeID
node
)
{
ensureThatNodeIsInGraph
(
node
);
return
Collections
.
unmodifiableSet
(
this
.
incomingAdjacencyList
.
get
(
node
));
}
return
Collections
.
unmodifiableSet
(
this
.
incomingAdjacencyList
.
get
(
node
));
}
@Override
public
Set
<
INodeID
>
getNeighbors
(
INodeID
node
,
boolean
directedNeighborhood
)
{
public
Set
<
INodeID
>
getNeighbors
(
INodeID
node
,
boolean
directedNeighborhood
)
{
if
(
directedNeighborhood
)
return
Collections
.
unmodifiableSet
(
successorNodes
.
get
(
node
));
@SuppressWarnings
(
"unchecked"
)
...
...
@@ -565,8 +592,7 @@ public class BasicGraph implements Graph {
private
void
ensureThatNodeIsInGraph
(
INodeID
node
)
{
if
(!
this
.
nodesById
.
containsKey
(
node
))
throw
new
IllegalStateException
(
"Node "
+
node
+
" is not contained in the graph"
);
throw
new
IllegalStateException
(
"Node "
+
node
+
" is not contained in the graph"
);
}
@SuppressWarnings
(
"unused"
)
...
...
@@ -616,7 +642,7 @@ public class BasicGraph implements Graph {
for
(
IEdge
edge
:
edges
)
{
this
.
addEdge
(
edge
);
}
}
}
@Override
public
void
addNodes
(
Iterable
<?
extends
INode
>
nodes
)
{
...
...
@@ -700,8 +726,7 @@ public class BasicGraph implements Graph {
}
@Override
public
Set
<
INodeID
>
getNeighbors
(
INode
node
,
int
k
,
boolean
directedNeighborhood
)
{
public
Set
<
INodeID
>
getNeighbors
(
INode
node
,
int
k
,
boolean
directedNeighborhood
)
{
return
getNeighbors
(
node
.
getId
(),
k
,
directedNeighborhood
);
}
...
...
@@ -712,8 +737,7 @@ public class BasicGraph implements Graph {
@Override
public
boolean
equalsAttributes
(
Graph
otherGraph
)
{
if
(
otherGraph
.
getNodeCount
()
!=
this
.
getNodeCount
()
||
otherGraph
.
getEdgeCount
()
!=
this
.
getEdgeCount
())
if
(
otherGraph
.
getNodeCount
()
!=
this
.
getNodeCount
()
||
otherGraph
.
getEdgeCount
()
!=
this
.
getEdgeCount
())
return
false
;
for
(
final
INode
node
:
this
.
getNodes
())
{
if
(!
otherGraph
.
containsNode
(
node
))
...
...
@@ -736,8 +760,7 @@ public class BasicGraph implements Graph {
reverseEdgeSet
.
add
(
new
DirectedEdge
(
edge
.
toId
(),
edge
.
fromId
()));
}
for
(
final
IEdge
edge
:
this
.
getEdges
())
{
if
(!
this
.
containsEdge
(
new
DirectedEdge
(
edge
.
fromId
(),
edge
.
toId
())))
if
(!
this
.
containsEdge
(
new
DirectedEdge
(
edge
.
fromId
(),
edge
.
toId
())))
return
false
;
}
...
...
@@ -748,8 +771,7 @@ public class BasicGraph implements Graph {
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
)
{
if
(
this
.
getOutdegree
(
node
.
getId
())
==
0
&&
this
.
getIndegree
(
node
.
getId
())
==
0
)
{
isolatedNodes
.
add
(
node
.
getId
());
}
}
...
...
src/de/tudarmstadt/maki/simonstrator/api/common/graph/Graph.java
View file @
0b39dee1
...
...
@@ -119,7 +119,7 @@ public interface Graph extends Cloneable {
* already
*/
void
addEdges
(
Iterable
<?
extends
IEdge
>
edges
);
/**
* Adds the given node to the graph
*
...
...
@@ -251,11 +251,58 @@ public interface Graph extends Cloneable {
/**
* Returns the edge with the given ID.
*
* @param edgeID
* @return
* @return edge or null
*/
public
IEdge
getEdge
(
EdgeID
edgeID
);
/**
* Returns the inverse edg eof the edge with the given ID.
*
* @return the inverse edge if exists. Otherwise, null.
* @throws IllegalArgumentException
* if no edge with the given ID is known
* @since 2.5
*/
public
IEdge
getInverseEdge
(
EdgeID
edgeId
);
/**
* Returns the inverse edg eof the edge with the given ID.
*
* <b>Note</b> Edges need to be marked <b>explicitly</b> as inverse edge of
* one another by using {@link #makeInverseEdges(EdgeID, EdgeID)} or
* {@link #makeInverseEdges(IEdge, IEdge)}
*
* @return the inverse edge if exists. Otherwise, null.
* @throws IllegalArgumentException
* if no edge with the given ID is known
* @since 2.5
*/
public
IEdge
getInverseEdge
(
IEdge
edge
);
/**
* @see #makeInverseEdges(IEdge, IEdge)
* @throws IllegalArgumentException
* if one of the given IDs cannot be mapped to an edge
*
* @since 2.5
*/
public
void
makeInverseEdges
(
EdgeID
forwardEdgeId
,
EdgeID
backwardEdgeId
);
/**
* Marks the given pair of edges as inverse edges of each other
*
* Only edges that have been passed to
* {@link #makeInverseEdges(IEdge, IEdge)} will afterwards be returned by
* {@link #getInverseEdge(IEdge)}.
*
* @param forwardEdge
* the first edge
* @param backwardEdge
* the second edge
* @since 2.5
*/
public
void
makeInverseEdges
(
IEdge
forwardEdge
,
IEdge
backwardEdge
);
/*
* Convenience methods
*/
...
...
@@ -348,8 +395,7 @@ public interface Graph extends Cloneable {
* If the directedNeighborhood flag is true, edge directions are considered
* for the neighborhood
*/
public
Set
<
INodeID
>
getNeighbors
(
INodeID
node
,
int
k
,
boolean
directedNeighborhood
);
public
Set
<
INodeID
>
getNeighbors
(
INodeID
node
,
int
k
,
boolean
directedNeighborhood
);
/**
* Returns the nodes contained in the k-hop neighborhood of the specified
...
...
@@ -358,8 +404,7 @@ public interface Graph extends Cloneable {
* If the directedNeighborhood flag is true, edge directions are considered
* for the neighborhood
*/
public
Set
<
INodeID
>
getNeighbors
(
INode
node
,
int
k
,
boolean
directedNeighborhood
);
public
Set
<
INodeID
>
getNeighbors
(
INode
node
,
int
k
,
boolean
directedNeighborhood
);
/**
* returns the strict 1-hop neighbors of the specified node.
...
...
@@ -370,8 +415,7 @@ public interface Graph extends Cloneable {
*
* @precondition node is contained in the graph
*/
public
Set
<
INodeID
>
getNeighbors
(
INodeID
node
,
boolean
directedNeighborhood
);
public
Set
<
INodeID
>
getNeighbors
(
INodeID
node
,
boolean
directedNeighborhood
);
public
Set
<
INodeID
>
getNeighbors
(
INode
node
,
boolean
directedNeighborhood
);
...
...
@@ -458,5 +502,4 @@ public interface Graph extends Cloneable {
*/
public
int
getDegree
(
INodeID
nodeID
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment