Skip to content

Commit 7082893

Browse files
author
Peter Empen
committed
new: Traverser, deprecations
1 parent d51870c commit 7082893

8 files changed

Lines changed: 504 additions & 138 deletions

File tree

core/src/main/scala/scalax/collection/GraphEdge.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import edge.LBase.LEdge
1313
* {{{
1414
* import scalax.collection.GraphPredef._, scalax.collection.GraphEdge,_
1515
* }}}
16+
* @define SHORTCUT Allows to replace the edge object with it's shortcut like
1617
* @author Peter Empen
1718
*/
1819
object GraphEdge {
@@ -23,11 +24,10 @@ object GraphEdge {
2324
* are immutable.
2425
*
2526
* @tparam N the user type of the nodes (ends) of this edge.
26-
* @author Peter Empen
2727
* @define CalledByValidate This function is called on every edge-instantiation
2828
* by `validate` that throws EdgeException if this method returns `false`.
29-
* @define SHORTCUT Allows to replace the edge object with it's shortcut like
3029
* @define ISAT In case this edge is undirected this method maps to `isAt`
30+
* @author Peter Empen
3131
*/
3232
sealed trait EdgeLike[+N] extends Iterable[N] with Eq with Serializable
3333
{

core/src/main/scala/scalax/collection/GraphPredef.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,16 @@ object GraphPredef {
9292
implicit def edgeSetToSeq[N, E[X]<:EdgeLikeIn[X]](edges: Graph[N,E]#EdgeSetT)
9393
: Seq[OutParam[N,E]] = new SeqFacade(edges)
9494

95-
/** @tparam NI the type of the nodes (vertices) this graph is passed to by the user.
96-
* @tparam EI the kind of the edges (links) this graph is passed to by the user.
95+
/** @tparam N the type of the nodes (vertices) this graph is passed to by the user.
96+
* @tparam E the kind of the edges (links) this graph is passed to by the user.
9797
*/
98-
sealed trait InParam [NI, +EI[X<:NI] <: EdgeLike[X]] extends Param[NI,EI] {
98+
sealed trait InParam[N, +E[X<:N] <: EdgeLike[X]] extends Param[N,E] {
9999
def isIn = true
100100
def isOut = false
101101
}
102+
/** Same as `InParam`. */
103+
type OuterElem[N, +E[X<:N] <: EdgeLike[X]] = InParam[N,E]
104+
102105
sealed trait OutParam[NO, +EO[X<:NO] <: EdgeLike[X]] extends Param[NO,EO] {
103106
def isIn = false
104107
def isOut = true

core/src/main/scala/scalax/collection/GraphTraversal.scala

Lines changed: 427 additions & 12 deletions
Large diffs are not rendered by default.

core/src/main/scala/scalax/collection/immutable/EqSet.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import scalax.collection.mutable.EqHashMap
55
/** Wrapper class mimicking a `scala.collection.immutable.Set`
66
* without copying the contents of the underlying `EqHashMap`.
77
*
8-
* #define ON Creates a new `Set` as an O(N) operation
8+
* @define ON Creates a new `Set` as an O(N) operation
99
*/
1010
final class EqSet[K <: AnyRef](map: EqHashMap[K,_]) extends Set[K] {
1111

core/src/main/scala/scalax/collection/mutable/ArraySet.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ trait ArraySet[A]
2828
/** Compacts the current representation depending on [[ArraySet.Hints.compactUpToUsed]]. */
2929
def compact: Unit
3030
def find(elem: A): Option[A]
31-
/** The valid hints or `None` for an underlining [[ArraySet.empty]]. */
31+
/** The hints valid for this [[ArraySet!]]. */
3232
def hints: ArraySet.Hints
3333
/** For `isArray == true`, the current capacity of the internal array else 0. */
3434
def capacity: Int

core/src/main/scala/scalax/collection/mutable/SimpleArraySet.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import immutable.SortedArraySet
1616
* Element removal could be optimized by another implementation.
1717
*
1818
* @param hints Optimization hints controlling the growth of the underlying
19-
* [[scala.collection.mutable.ArrayBuffer]].
19+
* [[scala.collection.mutable.ArrayBuffer!]].
2020
* @define OPT Optimized by use of unchecked insertions.
2121
* @author Peter Empen
2222
*/

core/src/test/scala/scalax/collection/TTraversal.scala

Lines changed: 62 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import language.{higherKinds, postfixOps}
44
import collection.mutable.{ListBuffer, Set, Stack}
55

66
import GraphPredef._, GraphEdge._
7+
import GraphTraversal._
78
import GraphTraversal.VisitorReturn._
89
import generic.GraphCoreCompanion
910
import edge.WDiEdge, edge.WUnDiEdge, edge.Implicits._
@@ -276,9 +277,8 @@ private class TTraversal[CC[N,E[X] <: EdgeLikeIn[X]] <: Graph[N,E] with GraphLik
276277
def n(outer: Int) = UnDi_1.node(outer)
277278

278279
var lastCount = 0
279-
n(1) pathTo (
280-
n(4),
281-
nodeVisitor = ExtendedNodeVisitor((node, count, depth, informer) => {
280+
n(1).innerNodeTraverser.withKind(DepthFirst) foreach {
281+
ExtendedNodeVisitor((node, count, depth, informer) => {
282282
count should be (lastCount + 1)
283283
lastCount += 1
284284

@@ -294,8 +294,9 @@ private class TTraversal[CC[N,E[X] <: EdgeLikeIn[X]] <: Graph[N,E] with GraphLik
294294
case _ => fail
295295
}
296296
Continue
297-
})
298-
)
297+
}
298+
)
299+
}
299300
}
300301
def test_shortestPathFunctional {
301302
import custom.flight._, custom.flight.Helper._, custom.flight.FlightImplicits._
@@ -357,50 +358,20 @@ private class TTraversal[CC[N,E[X] <: EdgeLikeIn[X]] <: Graph[N,E] with GraphLik
357358
val expectedSumLayer2ExclGt4 = 9
358359
}
359360
{ import UnDi_1._
360-
var sum = 0
361-
def add(visited: g.NodeT) = { sum += visited; Continue }
362-
363-
sum = 0
364-
node(4).traverseNodes() { add(_) }
365-
sum should be (expectedSumAll)
366-
367-
sum = 0
368-
node(4).traverseNodes(maxDepth = 1) { add }
369-
sum should be (expectedSumLayer1)
370-
371-
sum = 0
372-
node(4).traverseNodes(maxDepth = 2) { add }
373-
sum should be (expectedSumLayer2)
374-
375-
sum = 0
376-
node(4).traverseNodes(breadthFirst = false, maxDepth = 1) { add }
377-
sum should be (expectedSumLayer1)
378361

379-
sum = 0
380-
node(4).traverseNodes(breadthFirst = false, maxDepth = 2) { add }
381-
sum should be (expectedSumLayer2)
362+
val bfs_4 = node(4).outerNodeTraverser
363+
bfs_4 .sum should be (expectedSumAll)
364+
bfs_4.withMaxDepth(1).sum should be (expectedSumLayer1)
365+
bfs_4.withMaxDepth(2).sum should be (expectedSumLayer2)
382366

383-
sum = 0
384-
node(4).traverseNodes(nodeFilter = _ <= 4) { add }
385-
sum should be (expectedSumAllExclGt4)
367+
val dfs_4 = bfs_4.withKind(DepthFirst)
368+
dfs_4.withMaxDepth(1).sum should be (expectedSumLayer1)
369+
dfs_4.withMaxDepth(2).sum should be (expectedSumLayer2)
386370

387-
sum = 0
388-
node(4).traverseNodes(nodeFilter = _ <= 4, maxDepth = 2) { add }
389-
sum should be (expectedSumLayer2ExclGt4)
390-
391-
val traversal = g.newTraversal(nodeFilter = _ <= 4,
392-
nodeVisitor = add)
393-
sum = 0
394-
traversal bfs node(4)
395-
sum should be (expectedSumAllExclGt4)
396-
397-
sum = 0
398-
traversal (node(4), maxDepth = 2)
399-
sum should be (expectedSumLayer2ExclGt4)
400-
401-
sum = 0
402-
traversal dfs node(4)
403-
sum should be (expectedSumAllExclGt4)
371+
val sub_4 = bfs_4.withSubgraph(nodes = _ <= 4)
372+
sub_4 .sum should be (expectedSumAllExclGt4)
373+
sub_4.withMaxDepth(2) .sum should be (expectedSumLayer2ExclGt4)
374+
sub_4.withKind(DepthFirst).sum should be (expectedSumAllExclGt4)
404375
}
405376
}
406377
def test_DownUp {
@@ -457,7 +428,6 @@ private class TTraversal[CC[N,E[X] <: EdgeLikeIn[X]] <: Graph[N,E] with GraphLik
457428
}}
458429
}
459430
def test_TraversalDirection {
460-
import scalax.collection.GraphTraversal._
461431
// https://groups.google.com/forum/?fromgroups=#!topic/scala-internals/9NMPfU4xdhU
462432
object DDi_1 extends TGraph[Int, DiEdge](factory(elementsOfDi_1: _*)) {
463433
val expectedSumSuccessorsOf_4 = 12
@@ -471,95 +441,72 @@ private class TTraversal[CC[N,E[X] <: EdgeLikeIn[X]] <: Graph[N,E] with GraphLik
471441
val expectedSumLayer1AnyConnectedsOf_2 = 6
472442
}
473443
{ import DDi_1._
474-
var sum = 0
475-
def add(visited: g.NodeT) = { sum += visited; Continue }
476-
477-
sum = 0
478-
node(4).traverseNodes(Successors) { add }
479-
sum should be (expectedSumSuccessorsOf_4)
480-
481-
sum = 0
482-
node(4).traverseNodes(Predecessors) { add }
483-
sum should be (expectedSumPredecessorsOf_4)
484-
485-
sum = 0
486-
node(2).traverseNodes(Successors) { add }
487-
sum should be (expectedSumSuccessorsOf_2)
488-
489-
sum = 0
490-
node(2).traverseNodes(Predecessors) { add }
491-
sum should be (expectedSumPredecessorsOf_2)
492-
493-
sum = 0
494-
node(2).traverseNodes(AnyConnected) { add }
495-
sum should be (expectedSumAnyConnected)
496-
497-
sum = 0
498-
node(2).traverseNodes(Successors, maxDepth = 1) { add }
499-
sum should be (expectedSumLayer1SuccessorsOf_2)
500-
501-
sum = 0
502-
node(2).traverseNodes(Predecessors, maxDepth = 1) { add }
503-
sum should be (expectedSumLayer1PredecessorsOf_2)
504-
505-
sum = 0
506-
node(2).traverseNodes(AnyConnected, maxDepth = 1) { add }
507-
sum should be (expectedSumLayer1AnyConnectedsOf_2)
444+
val predecessors = Parameters(direction = Predecessors)
445+
val anyConnected = Parameters(direction = AnyConnected)
446+
val maxDepth_1 = Parameters(maxDepth = 1)
447+
448+
node(4).outerNodeTraverser .sum should be (expectedSumSuccessorsOf_4)
449+
node(4).outerNodeTraverser(predecessors).sum should be (expectedSumPredecessorsOf_4)
450+
451+
node(2).outerNodeTraverser .sum should be (expectedSumSuccessorsOf_2)
452+
node(2).outerNodeTraverser(predecessors).sum should be (expectedSumPredecessorsOf_2)
453+
node(2).outerNodeTraverser(anyConnected).sum should be (expectedSumAnyConnected)
454+
455+
node(2).outerNodeTraverser(maxDepth_1) .sum should be (expectedSumLayer1SuccessorsOf_2)
456+
node(2).outerNodeTraverser(maxDepth_1.withDirection(Predecessors)).
457+
sum should be (expectedSumLayer1PredecessorsOf_2)
458+
node(2).outerNodeTraverser(maxDepth_1.withDirection(AnyConnected)).
459+
sum should be (expectedSumLayer1AnyConnectedsOf_2)
508460
}
509461
}
510462
def test_NodeOrdering {
511-
val root = 0
512463
val g = factory(0~>4, 0~>2, 0~>3, 0~>1,
513464
1~>13, 1~>11, 1~>12,
514465
2~>22, 2~>21, 2~>23,
515466
3~>32, 3~>33, 3~>31,
516467
4~>42, 4~>41, 4~>43)
517-
val resultOrder = new Array[Int](g.order)
468+
val root = g get 0
518469
val nodeOrdering = g.NodeOrdering(Ordering.Int.compare(_,_))
519-
var i = 0
520-
def add(visited: g.NodeT) = {
521-
resultOrder(i) = visited.value
522-
i += 1
523-
Continue
524-
}
525470

526-
(g get root).traverseNodes(ordering = nodeOrdering)(add)
527-
resultOrder should be (
471+
val orderedTraverser = root.outerNodeTraverser.withOrdering(nodeOrdering)
472+
orderedTraverser.toList should be (
528473
List(0 to 4: _*) ++
529474
List(11 to 13: _*) ++ List(21 to 23: _*) ++
530-
List(31 to 33: _*) ++ List(41 to 43: _*) toArray)
475+
List(31 to 33: _*) ++ List(41 to 43: _*))
531476

532-
i = 0
533-
(g get root).traverseNodes(breadthFirst = false,
534-
ordering = nodeOrdering)(add)
535-
resultOrder should be ((0 ::
477+
orderedTraverser.withKind(DepthFirst).toList should be ((0 ::
536478
List(1) ::: List(11 to 13: _*) ::: List(2) ::: List(21 to 23: _*) :::
537-
List(3) ::: List(31 to 33: _*) ::: List(4) ::: List(41 to 43: _*)) toArray)
479+
List(3) ::: List(31 to 33: _*) ::: List(4) ::: List(41 to 43: _*)))
538480
}
539481
def test_EdgeOrdering {
540-
val root = 1
541-
val outerEdges = Seq[InParam[Int,WDiEdge]](
542-
root~>4 % 2, root~>2 % 5, root~>3 % 4,
543-
3~>6 % 4, 3~>5 % 5, 3~>7 % 2)
482+
val outerEdges = List[InParam[Int,WDiEdge]](
483+
1~>4 % 2, 1~>2 % 5, 1~>3 % 4,
484+
3~>6 % 4, 3~>5 % 5, 3~>7 % 2)
544485
val g = factory(outerEdges: _*)
486+
val root = g get 1
545487
def edgeOrdering = g EdgeOrdering(g.Edge.WeightOrdering.reverse.compare)
546-
val resultOrder = new Array[Int](g.order)
547-
var i = 0
548-
def add(visited: g.NodeT) = {
549-
resultOrder(i) = visited.value
550-
i += 1
551-
Continue
552-
}
553488

554-
(g get root).traverseNodes(ordering = edgeOrdering)(add)
555-
resultOrder should be (List(1 to 7: _*) toArray)
489+
val orderedTraverser = root.outerNodeTraverser.withOrdering(edgeOrdering)
490+
orderedTraverser .toList should be (List(1 to 7: _*))
491+
orderedTraverser.withKind(DepthFirst).toList should be (List(1,2,3,5,6,7,4))
492+
}
493+
def test_mapTraverser {
494+
val t = Di_1.g.nodes.head.outerNodeTraverser
495+
t map (_ + 1) should be (t.toList map (_ + 1))
496+
}
497+
def test_elemTraverser {
498+
import Di_1._
499+
import g.{InnerNode, InnerEdge}
556500

557-
i = 0
558-
(g get root).traverseNodes(breadthFirst = false,
559-
ordering = edgeOrdering)(add)
560-
resultOrder should be (List(1,2,3,5,6,7,4) toArray)
501+
val t = g.nodes.head.innerElemTraverser
502+
def nodePred(n: g.NodeT) = n.degree > 1
503+
def edgePred(e: g.EdgeT) = e forall nodePred
504+
505+
val nodes = t collect { case InnerNode(n) if nodePred(n) => n }
506+
val edges = t collect { case InnerEdge(e) if edgePred(e) => e }
507+
nodes.toSet should be (g.nodes filter nodePred)
508+
edges.toSet should be (g.edges filter edgePred)
561509
}
562-
563510
def test_ShortestPathExistsIfPathExists {
564511
import org.scalacheck._
565512
import Arbitrary.arbitrary

project/GraphBuild.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,16 @@ object GraphBuild extends Build {
6767
unmanagedSourceDirectories in Compile <<= (scalaSource in Compile)(Seq(_)),
6868
unmanagedSourceDirectories in Test <<= (scalaSource in Test) (Seq(_)),
6969
scalacOptions in (Compile, doc) += "-diagrams",
70+
autoAPIMappings := true,
7071
// scalacOptions in doc ++= Seq(
7172
// "-doc-root-content", "src/main/scala/rootdoc.txt"
7273
// ),
7374
testOptions in Test := Seq(Tests.Filter(s => s.endsWith("Test"))),
7475
libraryDependencies ++= Seq(
75-
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
76+
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
7677
"junit" % "junit" % "4.8.2" % "test",
77-
"org.scalatest" %% "scalatest" % "1.9.2" % "test",
78-
"org.scalacheck" %% "scalacheck" % "1.10.1" % "test"
78+
"org.scalatest" %% "scalatest" % "1.9.2" % "test",
79+
"org.scalacheck" %% "scalacheck" % "1.10.1" % "test"
7980
)
8081
) ++ GraphSonatype.settings ++ (
8182
if (Version.compilerIsRC) Seq(

0 commit comments

Comments
 (0)