Skip to content

Commit fbadf67

Browse files
committed
Updated the README. Getting close.
1 parent 3eb4ab7 commit fbadf67

File tree

2 files changed

+28
-28
lines changed

2 files changed

+28
-28
lines changed

README.md

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ You'll need to
4343
* choose or create a SemiringSupport implementation, like FewestNodes.
4444
* provide a function to convert from a (Node,Node,MaybeAnEdge) tuple to the Label defined by your SemiringSupport.
4545
** You can use net.walend.scalagraph.semiring.ConvertToLabelGraph to convert from a [scala-graph](http://www.scala-graph.org/) Graph.
46-
* choose an algorithm to perform the minimization. (You probably want to use Dijkstra's algorithm.)
46+
* choose an algorithm to perform the minimization. You probably want to use Dijkstra's algorithm.
4747
* arrange for your code to run the algorithm on your graph
4848

49-
Floyd-Warshall provides a Digraph[Node,Label] with your nodes and labels that contain the results of the minimization. Dijkstra provides a Seq[(Node,Node,Label)] where the labels contain the results of the minimization. Brandes provides that plus a Map[Node,Double] that holds each node's betweenness.
49+
Floyd-Warshall provides a Digraph[Node,Label] with your nodes and labels that contain the results of the minimization. Dijkstra provides a Seq[(Node,Node,Label)] where the labels contain the results of the minimization. Brandes provides that Seq plus a Map[Node,Double] that holds each node's betweenness.
5050

5151
import net.walend.graph.semiring.{OnePathFirstStep,FirstStep,FewestNodes,Dijkstra}
5252

@@ -61,25 +61,25 @@ Floyd-Warshall provides a Digraph[Node,Label] with your nodes and labels that co
6161
//this will be used to convert from the arc tuples to labels
6262
val labelForEdge = support.convertEdgeToLabelFunc[String](FewestNodes.convertEdgeToLabel)
6363

64-
//finds a shortest path for each pair of nodes if that path exists
65-
val shortestPaths:Seq[(String,String,Option[FirstStep[String,Int]])] =
64+
//find the first step in a shortest path for a pair of nodes if that path exists
65+
val firstSteps:Seq[(String,String,Option[FirstStep[String,Int]])] =
6666
Dijkstra.allPairsShortestPaths(edges = yourEdges,
6767
support = support,
6868
labelForArc = labelForArc)
6969

70+
//Find the shortest paths between any pair of nodes
71+
val shortestPath:Option[Seq[String]] = support.leastPath(start,end)
7072

7173
### Algorithms
7274

7375
For the second release, ScalaGraphMinimizer supplies
7476

77+
* FibonacciHeap -- a generic heap that supports an efficient changeKey operation.
7578
* The Floyd-Warshall algorithm
7679
* Dijkstra's algorithm with a Fibonacci Heap
7780
* Brandes' algorithm for betweenness
7881

79-
Peter Empen optimized scala-graph's internal representation in scala-graph to ensure that the graph algorithms scaled at their theoretical limits. I've tested with graphs with up to 1024 nodes. I've tested just the internal representation (todo size)
80-
81-
* FibonacciHeap is a generic heap that supports an efficient changeKey operation.
82-
82+
I've used a profiler to quench hotspots where I could find ways to speed up algorithms. I've tested performance up to 2048 nodes.
8383

8484
### Semirings
8585

@@ -106,25 +106,17 @@ FloydWarshall, Dijkstra, and Brandes each include a method that take sequences o
106106

107107
These are typically very straightforward to create. The decorator semirings listed above each include helper functions that require a similar function to convert the tuple to the core semiring's Label.
108108

109-
labelForArc:(Node,Node,ArcLabel)=>Label
109+
convertEdgeToLabelFunc:(Node,Node,ArcLabel)=>Label
110110

111-
These methods also allow for an optional extraNodes Seq. This Seq can contain both extra nodes and any nodes that already exist in the edges, and has some influence over the ordering of the algorithm's output.
111+
These methods also allow for an optional extraNodes Seq. This Seq can contain both extra nodes and any nodes that already exist in the edges, and can control the ordering of the algorithm's output.
112112

113-
FloydWarshall, Dijkstra, and Brandes each also include a method that takes a Digraph implementation. If you use this method then you are responsible for creating the labelDigraph correctly. I included it primarily for computational efficiency, and for a future lazy evaluator for Dijkstra's method.
113+
FloydWarshall, Dijkstra, and Brandes each also include a method that takes an IndexedDigraph implementation, mutable for FloydWarshall. If you use this method then you are responsible for creating the labelDigraph correctly. I included it primarily for computational efficiency, and for a future lazy evaluator for Dijkstra's method.
114114

115115
labelDigraph:IndexedDigraph[Node,Label]
116116

117-
You are very likely to need your own LabelGraphBuilder to create a label graph from your own specialized graph. The easiest way is to extend AbstractLabelGraphBuilder and fill in
118-
119-
def initialLabelFromGraphEdge[E[X] <: EdgeLikeIn[X]](originalGraph:Graph[N,E])
120-
(edgeT:originalGraph.EdgeT):Label
121-
122-
123117
### Creating A Custom Semiring and Other Support Classes
124118

125-
You will likely want to create your own Semirings to match the problems you are solving. That will be enough to run the Floyd-Warshall algorithm. However, Dijkstra's and Brandes' algorithms requires some extra for the heap. Implement SemiringSupport, which includes a Semiring, a HeapOrdering, and a function to convert from Labels to the heap's Keys. Here is an example that can find the most probable paths:
126-
127-
TODO update this with the latest
119+
You will likely want to create your own Semirings to match the problems you are solving. That will be enough to run the Floyd-Warshall algorithm. However, Dijkstra's and Brandes' algorithms requires some extra methods for the heap. Implement SemiringSupport, which includes a Semiring, a HeapOrdering, and a function to convert from Labels to the heap's Keys. Here is an example that can find the most probable paths:
128120

129121
object MostProbable extends SemiringSupport[Double,Double] {
130122

@@ -133,12 +125,12 @@ TODO update this with the latest
133125
def heapOrdering = MostProbableOrdering
134126

135127
def heapKeyForLabel = {label:Label => label}
136-
128+
137129
Sometimes it can be helpful to provide a possible convertArcToLabel function
130+
131+
def convertEdgeToLabel[Node, Label](start: Node, end: Node, label: Label): MostProbable.Label = semiring.I
138132

139-
def convertArcToLabel[Node, ArcLabel](start: Node, end: Node, arc: ArcLabel): MostProbable.Label = semiring.I
140-
141-
For your Semiring supply identity and annihilator values, and summary and extend operators. Here's an example:
133+
For your Semiring supply identity and annihilator values, a method to check that a label is in the domain, and summary and extend operators. Here's an example:
142134

143135
object MostProbableSemiring extends Semiring {
144136

@@ -165,7 +157,7 @@ For your Semiring supply identity and annihilator values, and summary and extend
165157
}
166158
}
167159

168-
The HeapOrdering is actually trickier to get right. The Heap needs a special Key, AlwaysTop, that will always be higher than the highest possible Label and AlwaysBottom, that will only be on the bottom of the heap. The identity and annihilator sometimes work as these special values. Watch out for strange behaviors of floating point infinities and wrap-around with integers.
160+
The HeapOrdering is actually trickier to get right than the Semiring. The Heap needs a special Key, AlwaysTop, that will always be higher than the highest possible Label and AlwaysBottom, that will only be on the bottom of the heap. The identity and annihilator sometimes work as these special values. Watch out for strange behaviors of floating point infinities and wrap-around with integers. In this example, I want a version that has the highest values on top of the heap. Note that I took a shortcut and made AlwaysTop outside of the Semiring's domain.
169161

170162
/**
171163
* A heap ordering that puts lower numbers on the top of the heap
@@ -210,8 +202,8 @@ The HeapOrdering is actually trickier to get right. The Heap needs a special Key
210202

211203
### Next release
212204

205+
* Louvain community detection
213206
* A*
214-
* MST using a heap and a GraphBuilder
215207
* Enron test set
216208
* Timing study with automatically generated graphs (in the test stage) (And comparison with Jung and scala-graph's own)
217209

@@ -224,9 +216,8 @@ The HeapOrdering is actually trickier to get right. The Heap needs a special Key
224216
### New Algorithms
225217

226218
* Lazy Dijkstra's
227-
* MST using that Heap
219+
* MST using a Heap
228220
* A* and some variations
229-
* Louvain community detection
230221

231222

232223
### More Semirings

src/main/scala/net/walend/graph/semiring/OnePathFirstStep.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ class OnePathFirstStep[Node,CoreLabel,Key](coreSupport:SemiringSupport[CoreLabel
1818

1919
def heapOrdering: HeapOrdering[Key] = coreSupport.heapOrdering
2020

21+
//todo use a fold
22+
// label.fold(coreSupport.heapOrdering.AlwaysBottom)(x => coreSupport.heapKeyForLabel(x.weight))
23+
2124
def heapKeyForLabel = {
2225
case Some(nextStep) => coreSupport.heapKeyForLabel(nextStep.weight)
2326
case None => coreSupport.heapOrdering.AlwaysBottom
@@ -101,6 +104,12 @@ class OnePathFirstStep[Node,CoreLabel,Key](coreSupport:SemiringSupport[CoreLabel
101104
}
102105
}
103106

107+
def leastPath(from:Node,to:Node,edges:Seq[(Node,Node,Label)]):Option[Seq[Node]] = {
108+
import net.walend.graph.AdjacencyLabelDigraph
109+
val leastPathDigraph = AdjacencyLabelDigraph(edges = edges,noEdgeExistsValue = semiring.O)
110+
leastPath(from,to)(leastPathDigraph).map(_.map(node => node.value))
111+
}
112+
104113
def leastPath(from:Node,to:Node)(leastPathDigraph:LabelDigraph[Node,Label]):Option[Seq[leastPathDigraph.InnerNodeType]] = {
105114

106115
def leastPathOfInnerNodes(fromInner:Option[leastPathDigraph.InnerNodeType],

0 commit comments

Comments
 (0)