Toggle navigation
Toggle navigation
This project
Loading...
Sign in
홍길동
/
onos
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
tom
2014-09-10 12:10:03 -0700
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
0633d68dec87c6dc87d2c541dbbe3b4fa316beb6
0633d68d
1 parent
cbff9395
Added Tarjan SCC computation algorithm and associated tests.
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
353 additions
and
48 deletions
utils/misc/src/main/java/org/onlab/graph/TarjanGraphSearch.java
utils/misc/src/test/java/org/onlab/graph/BellmanFordGraphSearchTest.java
utils/misc/src/test/java/org/onlab/graph/BreadthFirstSearchTest.java
utils/misc/src/test/java/org/onlab/graph/DepthFirstSearchTest.java
utils/misc/src/test/java/org/onlab/graph/DijkstraGraphSearchTest.java
utils/misc/src/test/java/org/onlab/graph/GraphTest.java
utils/misc/src/test/java/org/onlab/graph/TarjanGraphSearchTest.java
utils/misc/src/main/java/org/onlab/graph/TarjanGraphSearch.java
0 → 100644
View file @
0633d68
package
org
.
onlab
.
graph
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
/**
* Tarjan algorithm for searching a graph and producing results describing
* the graph SCC (strongly-connected components).
*/
public
class
TarjanGraphSearch
<
V
extends
Vertex
,
E
extends
Edge
<
V
>>
implements
GraphSearch
<
V
,
E
>
{
/**
* {@inheritDoc}
* <p/>
* This implementation produces results augmented with information on
* SCCs within the graph.
* <p/>
* To prevent traversal of an edge, the {@link EdgeWeight#weight} should
* return a negative value as an edge weight.
*/
@Override
public
SCCResult
<
V
,
E
>
search
(
Graph
<
V
,
E
>
graph
,
EdgeWeight
<
V
,
E
>
weight
)
{
SCCResult
<
V
,
E
>
result
=
new
SCCResult
<>(
graph
);
for
(
V
vertex
:
graph
.
getVertexes
())
{
VertexData
data
=
result
.
data
(
vertex
);
if
(
data
==
null
)
{
connect
(
graph
,
vertex
,
weight
,
result
);
}
}
return
result
.
build
();
}
/**
* Scans the specified graph, using recursion, and produces SCC results.
*
* @param graph graph to search
* @param vertex current vertex to scan and connect
* @param weight optional edge weight
* @param result graph search result
* @return augmentation vertexData for the current vertex
*/
private
VertexData
<
V
>
connect
(
Graph
<
V
,
E
>
graph
,
V
vertex
,
EdgeWeight
<
V
,
E
>
weight
,
SCCResult
<
V
,
E
>
result
)
{
VertexData
<
V
>
data
=
result
.
addData
(
vertex
);
// Scan through all egress edges of the current vertex.
for
(
E
edge
:
graph
.
getEdgesFrom
(
vertex
))
{
V
nextVertex
=
edge
.
dst
();
// If edge weight is negative, skip it.
if
(
weight
!=
null
&&
weight
.
weight
(
edge
)
<
0
)
{
continue
;
}
// Attempt to get the augmentation vertexData for the next vertex.
VertexData
<
V
>
nextData
=
result
.
data
(
nextVertex
);
if
(
nextData
==
null
)
{
// Next vertex has not been visited yet, so do this now.
nextData
=
connect
(
graph
,
nextVertex
,
weight
,
result
);
data
.
lowLink
=
Math
.
min
(
data
.
lowLink
,
nextData
.
lowLink
);
}
else
if
(
result
.
visited
(
nextData
))
{
// Next vertex has been visited, which means it is in the
// same cluster as the current vertex.
data
.
lowLink
=
Math
.
min
(
data
.
lowLink
,
nextData
.
index
);
}
}
if
(
data
.
lowLink
==
data
.
index
)
{
result
.
addCluster
(
data
);
}
return
data
;
}
/**
* Graph search result augmented with SCC vertexData.
*/
public
static
final
class
SCCResult
<
V
extends
Vertex
,
E
extends
Edge
<
V
>>
implements
Result
{
private
final
Graph
<
V
,
E
>
graph
;
private
List
<
Set
<
V
>>
clusterVertexes
=
new
ArrayList
<>();
private
List
<
Set
<
E
>>
clusterEdges
=
new
ArrayList
<>();
private
int
index
=
0
;
private
final
Map
<
V
,
VertexData
<
V
>>
vertexData
=
new
HashMap
<>();
private
final
List
<
VertexData
<
V
>>
visited
=
new
ArrayList
<>();
private
SCCResult
(
Graph
<
V
,
E
>
graph
)
{
this
.
graph
=
graph
;
}
/**
* Returns the number of SCC clusters in the graph.
*
* @return number of clusters
*/
public
int
clusterCount
()
{
return
clusterEdges
.
size
();
}
/**
* Returns the list of strongly connected vertex clusters.
*
* @return list of strongly connected vertex sets
*/
public
List
<
Set
<
V
>>
clusterVertexes
()
{
return
clusterVertexes
;
}
/**
* Returns the list of edges linking strongly connected vertex clusters.
*
* @return list of strongly connected edge sets
*/
public
List
<
Set
<
E
>>
clusterEdges
()
{
return
clusterEdges
;
}
// Gets the augmentation vertexData for the specified vertex
private
VertexData
<
V
>
data
(
V
vertex
)
{
return
vertexData
.
get
(
vertex
);
}
// Adds augmentation vertexData for the specified vertex
private
VertexData
<
V
>
addData
(
V
vertex
)
{
VertexData
<
V
>
d
=
new
VertexData
<>(
vertex
,
index
);
vertexData
.
put
(
vertex
,
d
);
visited
.
add
(
0
,
d
);
index
++;
return
d
;
}
// Indicates whether the given vertex has been visited
private
boolean
visited
(
VertexData
data
)
{
return
visited
.
contains
(
data
);
}
// Adds a new cluster for the specified vertex
private
void
addCluster
(
VertexData
data
)
{
Set
<
V
>
vertexes
=
findClusterVertices
(
data
);
clusterVertexes
.
add
(
vertexes
);
clusterEdges
.
add
(
findClusterEdges
(
vertexes
));
}
private
Set
<
V
>
findClusterVertices
(
VertexData
data
)
{
VertexData
<
V
>
nextVertexData
;
Set
<
V
>
vertexes
=
new
HashSet
<>();
do
{
nextVertexData
=
visited
.
remove
(
0
);
vertexes
.
add
(
nextVertexData
.
vertex
);
}
while
(
data
!=
nextVertexData
);
return
Collections
.
unmodifiableSet
(
vertexes
);
}
private
Set
<
E
>
findClusterEdges
(
Set
<
V
>
vertexes
)
{
Set
<
E
>
edges
=
new
HashSet
<>();
for
(
V
vertex
:
vertexes
)
{
for
(
E
edge
:
graph
.
getEdgesFrom
(
vertex
))
{
if
(
vertexes
.
contains
((
edge
.
dst
())))
{
edges
.
add
(
edge
);
}
}
}
return
Collections
.
unmodifiableSet
(
edges
);
}
public
SCCResult
<
V
,
E
>
build
()
{
clusterVertexes
=
Collections
.
unmodifiableList
(
clusterVertexes
);
clusterEdges
=
Collections
.
unmodifiableList
(
clusterEdges
);
return
this
;
}
}
// Augments the vertex to assist in determining SCC clusters.
private
static
final
class
VertexData
<
V
extends
Vertex
>
{
final
V
vertex
;
int
index
;
int
lowLink
;
private
VertexData
(
V
vertex
,
int
index
)
{
this
.
vertex
=
vertex
;
this
.
index
=
index
;
this
.
lowLink
=
index
;
}
}
}
utils/misc/src/test/java/org/onlab/graph/BellmanFordGraphSearchTest.java
View file @
0633d68
...
...
@@ -31,17 +31,17 @@ public class BellmanFordGraphSearchTest extends BreadthFirstSearchTest {
@Test
public
void
searchGraphWithNegativeCycles
()
{
Set
<
TestVertex
>
vertexes
=
new
HashSet
<>(
vert
ic
es
());
Set
<
TestVertex
>
vertexes
=
new
HashSet
<>(
vert
ex
es
());
vertexes
.
add
(
Z
);
Set
<
TestEdge
>
edges
=
new
HashSet
<>(
edges
());
edges
.
add
(
new
TestEdge
(
G
,
Z
,
1.0
));
edges
.
add
(
new
TestEdge
(
Z
,
G
,
-
2.0
));
g
=
new
AdjacencyListsGraph
<>(
vertexes
,
edges
);
g
raph
=
new
AdjacencyListsGraph
<>(
vertexes
,
edges
);
GraphPathSearch
<
TestVertex
,
TestEdge
>
search
=
graphSearch
();
Set
<
Path
<
TestVertex
,
TestEdge
>>
paths
=
search
.
search
(
g
,
A
,
H
,
weight
).
paths
();
Set
<
Path
<
TestVertex
,
TestEdge
>>
paths
=
search
.
search
(
g
raph
,
A
,
H
,
weight
).
paths
();
assertEquals
(
"incorrect paths count"
,
1
,
paths
.
size
());
Path
p
=
paths
.
iterator
().
next
();
...
...
@@ -50,10 +50,10 @@ public class BellmanFordGraphSearchTest extends BreadthFirstSearchTest {
assertEquals
(
"incorrect path length"
,
5
,
p
.
edges
().
size
());
assertEquals
(
"incorrect path cost"
,
5.0
,
p
.
cost
(),
0.1
);
paths
=
search
.
search
(
g
,
A
,
G
,
weight
).
paths
();
paths
=
search
.
search
(
g
raph
,
A
,
G
,
weight
).
paths
();
assertEquals
(
"incorrect paths count"
,
0
,
paths
.
size
());
paths
=
search
.
search
(
g
,
A
,
null
,
weight
).
paths
();
paths
=
search
.
search
(
g
raph
,
A
,
null
,
weight
).
paths
();
printPaths
(
paths
);
assertEquals
(
"incorrect paths count"
,
6
,
paths
.
size
());
}
...
...
utils/misc/src/test/java/org/onlab/graph/BreadthFirstSearchTest.java
View file @
0633d68
...
...
@@ -29,10 +29,10 @@ public class BreadthFirstSearchTest extends AbstractGraphPathSearchTest {
// Executes the default test
protected
void
executeDefaultTest
(
int
pathCount
,
int
pathLength
,
double
pathCost
)
{
g
=
new
AdjacencyListsGraph
<>(
vertic
es
(),
edges
());
g
raph
=
new
AdjacencyListsGraph
<>(
vertex
es
(),
edges
());
GraphPathSearch
<
TestVertex
,
TestEdge
>
search
=
graphSearch
();
Set
<
Path
<
TestVertex
,
TestEdge
>>
paths
=
search
.
search
(
g
,
A
,
H
,
weight
).
paths
();
Set
<
Path
<
TestVertex
,
TestEdge
>>
paths
=
search
.
search
(
g
raph
,
A
,
H
,
weight
).
paths
();
assertEquals
(
"incorrect paths count"
,
1
,
paths
.
size
());
Path
p
=
paths
.
iterator
().
next
();
...
...
@@ -41,7 +41,7 @@ public class BreadthFirstSearchTest extends AbstractGraphPathSearchTest {
assertEquals
(
"incorrect path length"
,
pathLength
,
p
.
edges
().
size
());
assertEquals
(
"incorrect path cost"
,
pathCost
,
p
.
cost
(),
0.1
);
paths
=
search
.
search
(
g
,
A
,
null
,
weight
).
paths
();
paths
=
search
.
search
(
g
raph
,
A
,
null
,
weight
).
paths
();
printPaths
(
paths
);
assertEquals
(
"incorrect paths count"
,
pathCount
,
paths
.
size
());
}
...
...
utils/misc/src/test/java/org/onlab/graph/DepthFirstSearchTest.java
View file @
0633d68
...
...
@@ -33,11 +33,11 @@ public class DepthFirstSearchTest extends AbstractGraphPathSearchTest {
protected
void
executeDefaultTest
(
int
minLength
,
int
maxLength
,
double
minCost
,
double
maxCost
)
{
g
=
new
AdjacencyListsGraph
<>(
vertic
es
(),
edges
());
g
raph
=
new
AdjacencyListsGraph
<>(
vertex
es
(),
edges
());
DepthFirstSearch
<
TestVertex
,
TestEdge
>
search
=
graphSearch
();
DepthFirstSearch
<
TestVertex
,
TestEdge
>.
SpanningTreeResult
result
=
search
.
search
(
g
,
A
,
H
,
weight
);
search
.
search
(
g
raph
,
A
,
H
,
weight
);
Set
<
Path
<
TestVertex
,
TestEdge
>>
paths
=
result
.
paths
();
assertEquals
(
"incorrect path count"
,
1
,
paths
.
size
());
...
...
@@ -57,12 +57,12 @@ public class DepthFirstSearchTest extends AbstractGraphPathSearchTest {
}
public
void
executeBroadSearch
()
{
g
=
new
AdjacencyListsGraph
<>(
vertic
es
(),
edges
());
g
raph
=
new
AdjacencyListsGraph
<>(
vertex
es
(),
edges
());
DepthFirstSearch
<
TestVertex
,
TestEdge
>
search
=
graphSearch
();
// Perform narrow path search to a specific destination.
DepthFirstSearch
<
TestVertex
,
TestEdge
>.
SpanningTreeResult
result
=
search
.
search
(
g
,
A
,
null
,
weight
);
search
.
search
(
g
raph
,
A
,
null
,
weight
);
assertEquals
(
"incorrect paths count"
,
7
,
result
.
paths
().
size
());
int
[]
types
=
new
int
[]{
0
,
0
,
0
,
0
};
...
...
utils/misc/src/test/java/org/onlab/graph/DijkstraGraphSearchTest.java
View file @
0633d68
...
...
@@ -32,22 +32,22 @@ public class DijkstraGraphSearchTest extends BreadthFirstSearchTest {
@Test
public
void
noPath
()
{
g
=
new
AdjacencyListsGraph
<>(
of
(
A
,
B
,
C
,
D
),
of
(
new
TestEdge
(
A
,
B
,
1
),
new
TestEdge
(
B
,
A
,
1
),
new
TestEdge
(
C
,
D
,
1
),
new
TestEdge
(
D
,
C
,
1
)));
g
raph
=
new
AdjacencyListsGraph
<>(
of
(
A
,
B
,
C
,
D
),
of
(
new
TestEdge
(
A
,
B
,
1
),
new
TestEdge
(
B
,
A
,
1
),
new
TestEdge
(
C
,
D
,
1
),
new
TestEdge
(
D
,
C
,
1
)));
GraphPathSearch
<
TestVertex
,
TestEdge
>
gs
=
graphSearch
();
Set
<
Path
<
TestVertex
,
TestEdge
>>
paths
=
gs
.
search
(
g
,
A
,
B
,
weight
).
paths
();
Set
<
Path
<
TestVertex
,
TestEdge
>>
paths
=
gs
.
search
(
g
raph
,
A
,
B
,
weight
).
paths
();
printPaths
(
paths
);
assertEquals
(
"incorrect paths count"
,
1
,
paths
.
size
());
assertEquals
(
"incorrect path cost"
,
1.0
,
paths
.
iterator
().
next
().
cost
(),
0.1
);
paths
=
gs
.
search
(
g
,
A
,
D
,
weight
).
paths
();
paths
=
gs
.
search
(
g
raph
,
A
,
D
,
weight
).
paths
();
printPaths
(
paths
);
assertEquals
(
"incorrect paths count"
,
0
,
paths
.
size
());
paths
=
gs
.
search
(
g
,
A
,
null
,
weight
).
paths
();
paths
=
gs
.
search
(
g
raph
,
A
,
null
,
weight
).
paths
();
printPaths
(
paths
);
assertEquals
(
"incorrect paths count"
,
1
,
paths
.
size
());
assertEquals
(
"incorrect path cost"
,
1.0
,
paths
.
iterator
().
next
().
cost
(),
0.1
);
...
...
@@ -55,40 +55,40 @@ public class DijkstraGraphSearchTest extends BreadthFirstSearchTest {
@Test
public
void
simpleMultiplePath
()
{
g
=
new
AdjacencyListsGraph
<>(
of
(
A
,
B
,
C
,
D
),
of
(
new
TestEdge
(
A
,
B
,
1
),
new
TestEdge
(
A
,
C
,
1
),
new
TestEdge
(
B
,
D
,
1
),
new
TestEdge
(
C
,
D
,
1
)));
executeSearch
(
graphSearch
(),
g
,
A
,
D
,
weight
,
2
,
2.0
);
g
raph
=
new
AdjacencyListsGraph
<>(
of
(
A
,
B
,
C
,
D
),
of
(
new
TestEdge
(
A
,
B
,
1
),
new
TestEdge
(
A
,
C
,
1
),
new
TestEdge
(
B
,
D
,
1
),
new
TestEdge
(
C
,
D
,
1
)));
executeSearch
(
graphSearch
(),
g
raph
,
A
,
D
,
weight
,
2
,
2.0
);
}
@Test
public
void
denseMultiplePath
()
{
g
=
new
AdjacencyListsGraph
<>(
of
(
A
,
B
,
C
,
D
,
E
,
F
,
G
),
of
(
new
TestEdge
(
A
,
B
,
1
),
new
TestEdge
(
A
,
C
,
1
),
new
TestEdge
(
B
,
D
,
1
),
new
TestEdge
(
C
,
D
,
1
),
new
TestEdge
(
D
,
E
,
1
),
new
TestEdge
(
D
,
F
,
1
),
new
TestEdge
(
E
,
G
,
1
),
new
TestEdge
(
F
,
G
,
1
),
new
TestEdge
(
A
,
G
,
4
)));
executeSearch
(
graphSearch
(),
g
,
A
,
G
,
weight
,
5
,
4.0
);
g
raph
=
new
AdjacencyListsGraph
<>(
of
(
A
,
B
,
C
,
D
,
E
,
F
,
G
),
of
(
new
TestEdge
(
A
,
B
,
1
),
new
TestEdge
(
A
,
C
,
1
),
new
TestEdge
(
B
,
D
,
1
),
new
TestEdge
(
C
,
D
,
1
),
new
TestEdge
(
D
,
E
,
1
),
new
TestEdge
(
D
,
F
,
1
),
new
TestEdge
(
E
,
G
,
1
),
new
TestEdge
(
F
,
G
,
1
),
new
TestEdge
(
A
,
G
,
4
)));
executeSearch
(
graphSearch
(),
g
raph
,
A
,
G
,
weight
,
5
,
4.0
);
}
@Test
public
void
dualEdgeMultiplePath
()
{
g
=
new
AdjacencyListsGraph
<>(
of
(
A
,
B
,
C
,
D
,
E
,
F
,
G
,
H
),
of
(
new
TestEdge
(
A
,
B
,
1
),
new
TestEdge
(
A
,
C
,
3
),
new
TestEdge
(
B
,
D
,
2
),
new
TestEdge
(
B
,
C
,
1
),
new
TestEdge
(
B
,
E
,
4
),
new
TestEdge
(
C
,
E
,
1
),
new
TestEdge
(
D
,
H
,
5
),
new
TestEdge
(
D
,
E
,
1
),
new
TestEdge
(
E
,
F
,
1
),
new
TestEdge
(
F
,
D
,
1
),
new
TestEdge
(
F
,
G
,
1
),
new
TestEdge
(
F
,
H
,
1
),
new
TestEdge
(
A
,
E
,
3
),
new
TestEdge
(
B
,
D
,
1
)));
executeSearch
(
graphSearch
(),
g
,
A
,
E
,
weight
,
3
,
3.0
);
g
raph
=
new
AdjacencyListsGraph
<>(
of
(
A
,
B
,
C
,
D
,
E
,
F
,
G
,
H
),
of
(
new
TestEdge
(
A
,
B
,
1
),
new
TestEdge
(
A
,
C
,
3
),
new
TestEdge
(
B
,
D
,
2
),
new
TestEdge
(
B
,
C
,
1
),
new
TestEdge
(
B
,
E
,
4
),
new
TestEdge
(
C
,
E
,
1
),
new
TestEdge
(
D
,
H
,
5
),
new
TestEdge
(
D
,
E
,
1
),
new
TestEdge
(
E
,
F
,
1
),
new
TestEdge
(
F
,
D
,
1
),
new
TestEdge
(
F
,
G
,
1
),
new
TestEdge
(
F
,
H
,
1
),
new
TestEdge
(
A
,
E
,
3
),
new
TestEdge
(
B
,
D
,
1
)));
executeSearch
(
graphSearch
(),
g
raph
,
A
,
E
,
weight
,
3
,
3.0
);
}
}
...
...
utils/misc/src/test/java/org/onlab/graph/GraphTest.java
View file @
0633d68
...
...
@@ -19,7 +19,7 @@ public class GraphTest {
static
final
TestVertex
H
=
new
TestVertex
(
"H"
);
static
final
TestVertex
Z
=
new
TestVertex
(
"Z"
);
protected
Graph
<
TestVertex
,
TestEdge
>
g
;
protected
Graph
<
TestVertex
,
TestEdge
>
g
raph
;
protected
EdgeWeight
<
TestVertex
,
TestEdge
>
weight
=
new
EdgeWeight
<
TestVertex
,
TestEdge
>()
{
...
...
@@ -35,7 +35,7 @@ public class GraphTest {
}
}
protected
Set
<
TestVertex
>
vert
ic
es
()
{
protected
Set
<
TestVertex
>
vert
ex
es
()
{
return
of
(
A
,
B
,
C
,
D
,
E
,
F
,
G
,
H
);
}
...
...
utils/misc/src/test/java/org/onlab/graph/TarjanGraphSearchTest.java
0 → 100644
View file @
0633d68
package
org
.
onlab
.
graph
;
import
org.junit.Test
;
import
static
com
.
google
.
common
.
collect
.
ImmutableSet
.
of
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
onlab
.
graph
.
TarjanGraphSearch
.
SCCResult
;
/**
* Tarjan graph search tests.
*/
public
class
TarjanGraphSearchTest
extends
GraphTest
{
private
void
validate
(
SCCResult
<
TestVertex
,
TestEdge
>
result
,
int
cc
)
{
System
.
out
.
println
(
"Cluster count: "
+
result
.
clusterVertexes
().
size
());
System
.
out
.
println
(
"Clusters: "
+
result
.
clusterVertexes
());
assertEquals
(
"incorrect cluster count"
,
cc
,
result
.
clusterCount
());
}
private
void
validate
(
SCCResult
<
TestVertex
,
TestEdge
>
result
,
int
i
,
int
vc
,
int
ec
)
{
assertEquals
(
"incorrect cluster count"
,
vc
,
result
.
clusterVertexes
().
get
(
i
).
size
());
assertEquals
(
"incorrect edge count"
,
ec
,
result
.
clusterEdges
().
get
(
i
).
size
());
}
@Test
public
void
basic
()
{
graph
=
new
AdjacencyListsGraph
<>(
vertexes
(),
edges
());
TarjanGraphSearch
<
TestVertex
,
TestEdge
>
gs
=
new
TarjanGraphSearch
<>();
SCCResult
<
TestVertex
,
TestEdge
>
result
=
gs
.
search
(
graph
,
null
);
validate
(
result
,
6
);
}
@Test
public
void
singleCluster
()
{
graph
=
new
AdjacencyListsGraph
<>(
vertexes
(),
of
(
new
TestEdge
(
A
,
B
,
1
),
new
TestEdge
(
B
,
C
,
1
),
new
TestEdge
(
C
,
D
,
1
),
new
TestEdge
(
D
,
E
,
1
),
new
TestEdge
(
E
,
F
,
1
),
new
TestEdge
(
F
,
G
,
1
),
new
TestEdge
(
G
,
H
,
1
),
new
TestEdge
(
H
,
A
,
1
)));
TarjanGraphSearch
<
TestVertex
,
TestEdge
>
gs
=
new
TarjanGraphSearch
<>();
SCCResult
<
TestVertex
,
TestEdge
>
result
=
gs
.
search
(
graph
,
null
);
validate
(
result
,
1
);
validate
(
result
,
0
,
8
,
8
);
}
@Test
public
void
twoUnconnectedCluster
()
{
graph
=
new
AdjacencyListsGraph
<>(
vertexes
(),
of
(
new
TestEdge
(
A
,
B
,
1
),
new
TestEdge
(
B
,
C
,
1
),
new
TestEdge
(
C
,
D
,
1
),
new
TestEdge
(
D
,
A
,
1
),
new
TestEdge
(
E
,
F
,
1
),
new
TestEdge
(
F
,
G
,
1
),
new
TestEdge
(
G
,
H
,
1
),
new
TestEdge
(
H
,
E
,
1
)));
TarjanGraphSearch
<
TestVertex
,
TestEdge
>
gs
=
new
TarjanGraphSearch
<>();
SCCResult
<
TestVertex
,
TestEdge
>
result
=
gs
.
search
(
graph
,
null
);
validate
(
result
,
2
);
validate
(
result
,
0
,
4
,
4
);
validate
(
result
,
1
,
4
,
4
);
}
@Test
public
void
twoWeaklyConnectedClusters
()
{
graph
=
new
AdjacencyListsGraph
<>(
vertexes
(),
of
(
new
TestEdge
(
A
,
B
,
1
),
new
TestEdge
(
B
,
C
,
1
),
new
TestEdge
(
C
,
D
,
1
),
new
TestEdge
(
D
,
A
,
1
),
new
TestEdge
(
E
,
F
,
1
),
new
TestEdge
(
F
,
G
,
1
),
new
TestEdge
(
G
,
H
,
1
),
new
TestEdge
(
H
,
E
,
1
),
new
TestEdge
(
B
,
E
,
1
)));
TarjanGraphSearch
<
TestVertex
,
TestEdge
>
gs
=
new
TarjanGraphSearch
<>();
SCCResult
<
TestVertex
,
TestEdge
>
result
=
gs
.
search
(
graph
,
null
);
validate
(
result
,
2
);
validate
(
result
,
0
,
4
,
4
);
validate
(
result
,
1
,
4
,
4
);
}
@Test
public
void
twoClustersConnectedWithIgnoredEdges
()
{
graph
=
new
AdjacencyListsGraph
<>(
vertexes
(),
of
(
new
TestEdge
(
A
,
B
,
1
),
new
TestEdge
(
B
,
C
,
1
),
new
TestEdge
(
C
,
D
,
1
),
new
TestEdge
(
D
,
A
,
1
),
new
TestEdge
(
E
,
F
,
1
),
new
TestEdge
(
F
,
G
,
1
),
new
TestEdge
(
G
,
H
,
1
),
new
TestEdge
(
H
,
E
,
1
),
new
TestEdge
(
B
,
E
,
-
1
),
new
TestEdge
(
E
,
B
,
-
1
)));
TarjanGraphSearch
<
TestVertex
,
TestEdge
>
gs
=
new
TarjanGraphSearch
<>();
SCCResult
<
TestVertex
,
TestEdge
>
result
=
gs
.
search
(
graph
,
weight
);
validate
(
result
,
2
);
validate
(
result
,
0
,
4
,
4
);
validate
(
result
,
1
,
4
,
4
);
}
}
Please
register
or
login
to post a comment