Skip to content

Commit ba58c6f

Browse files
committed
Got rid of a lot of Option match statements
1 parent 0d344f5 commit ba58c6f

File tree

13 files changed

+83
-129
lines changed

13 files changed

+83
-129
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ The HeapOrdering is actually trickier to get right than the Semiring. The Heap n
173173
*/
174174
//todo look again for a version that handles NaNs and infinities
175175
def tryCompare(x: Double, y: Double): Option[Int] = {
176-
Some(x.compareTo(y))
176+
Option(x.compareTo(y))
177177
}
178178

179179
def keyDomainDescription = "between one and zero (the annihilator)"

build.sbt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ sonatypeSettings
66
//todo maybe remove release
77
releaseSettings
88

9-
name := "Graph4ScalaSemirings"
9+
name := "ScalaGraphMinimizer"
1010

1111
organization := "net.walend"
1212

@@ -53,7 +53,7 @@ scalacOptions ++= Seq("-feature")
5353

5454
// Your project orgnization (package name)
5555
organization := "net.walend"
56-
//todo organization := "net.walend.scalagraph"
56+
//todo organization := "net.walend.graph"
5757

5858
// Your profile name of the sonatype account. The default is the same with the organization
5959
profileName := "net.walend"

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

Lines changed: 28 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@ class AllPathsFirstSteps[Node,CoreLabel,Key](coreSupport:SemiringSupport[CoreLab
1717

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

20-
def heapKeyForLabel = {
21-
case Some(nextStep) => coreSupport.heapKeyForLabel(nextStep.weight)
22-
case None => coreSupport.heapOrdering.AlwaysBottom
23-
}
20+
def heapKeyForLabel:Label=>Key = _.fold(coreSupport.heapOrdering.AlwaysBottom)(x => coreSupport.heapKeyForLabel(x.weight))
2421

2522
//todo could be a Seq instead if just used in Dijkstra's algorithm
2623
case class FirstSteps(weight:CoreLabel,choices:Set[Node]) extends FirstStepsTrait[Node, CoreLabel] {
@@ -51,7 +48,7 @@ class AllPathsFirstSteps[Node,CoreLabel,Key](coreSupport:SemiringSupport[CoreLab
5148

5249
def convertEdgeToLabel[EdgeLabel](coreLabelForEdge:(Node,Node,EdgeLabel)=>CoreLabel)
5350
(start: Node, end: Node, edgeLabel: EdgeLabel):Label = {
54-
Some(FirstSteps(coreLabelForEdge(start,end,edgeLabel),Set(end)))
51+
Option(FirstSteps(coreLabelForEdge(start,end,edgeLabel),Set(end)))
5552
}
5653

5754
def convertEdgeToLabelFunc[EdgeLabel](coreLabelForEdge:(Node,Node,EdgeLabel)=>CoreLabel):((Node,Node,EdgeLabel) => Label) = convertEdgeToLabel(coreLabelForEdge)
@@ -62,14 +59,11 @@ class AllPathsFirstSteps[Node,CoreLabel,Key](coreSupport:SemiringSupport[CoreLab
6259
// val coreSemiring = coreSupport.semiring
6360

6461
def inDomain(label: Label): Boolean = {
65-
label match {
66-
case Some(steps:FirstSteps) => coreSupport.semiring.inDomain(steps.weight)
67-
case None => true
68-
}
62+
label.forall(steps => coreSupport.semiring.inDomain(steps.weight))
6963
}
7064

7165
//identity and annihilator
72-
val I = Some(FirstSteps(coreSupport.semiring.I,Set[Node]()))
66+
val I = Option(FirstSteps(coreSupport.semiring.I,Set[Node]()))
7367
val O = None
7468

7569
def summary(fromThroughToLabel:Label,currentLabel:Label):Label = {
@@ -80,7 +74,7 @@ class AllPathsFirstSteps[Node,CoreLabel,Key](coreSupport:SemiringSupport[CoreLab
8074
val fromThroughToSteps:FirstStepsTrait[Node,CoreLabel] = fromThroughToLabel.get
8175
val summ = coreSupport.semiring.summary(fromThroughToSteps.weight,currentSteps.weight)
8276
if((summ==fromThroughToSteps.weight)&&(summ==currentSteps.weight)) {
83-
Some(new FirstSteps(currentSteps.weight,
77+
Option(FirstSteps(currentSteps.weight,
8478
currentSteps.choices ++ fromThroughToSteps.choices))
8579
}
8680
else if (summ==fromThroughToSteps.weight) fromThroughToLabel
@@ -101,8 +95,8 @@ class AllPathsFirstSteps[Node,CoreLabel,Key](coreSupport:SemiringSupport[CoreLab
10195
val choices:Set[Node] = if(fromThroughLabel == I) throughToSteps.choices
10296
else fromThroughSteps.choices
10397

104-
Some(new FirstSteps(coreSupport.semiring.extend(fromThroughSteps.weight,throughToSteps.weight),
105-
choices))
98+
Option(FirstSteps(coreSupport.semiring.extend(fromThroughSteps.weight,throughToSteps.weight),
99+
choices))
106100
}
107101
else O
108102
}
@@ -114,26 +108,21 @@ class AllPathsFirstSteps[Node,CoreLabel,Key](coreSupport:SemiringSupport[CoreLab
114108

115109
def leastPathsOfInnerNodes(fromInner:Option[leastPathDigraph.InnerNodeType],
116110
toInner:Option[leastPathDigraph.InnerNodeType]):Seq[Path] = {
117-
(fromInner,toInner) match {
118-
case (Some(f),Some(t)) => {
119-
val label:Label = leastPathDigraph.label(f,t)
120-
label match {
121-
case Some(firstStep) => {
122-
if(firstStep.choices == Set.empty) Seq(Seq(t)) //No further steps. from should be to and the label should be I
123-
else {
124-
for (choice <- firstStep.choices.to[Seq]) yield {
125-
val tails: Seq[Path] = leastPathsOfInnerNodes(leastPathDigraph.innerNode(choice), toInner)
126-
for (tail <- tails) yield {
127-
Seq(f +: tail)
128-
}
129-
}.flatten
130-
}.flatten
131-
}
132-
case None => Seq() //No path from one to the other
133-
}
134-
}
135-
case _ => Seq() //One node or the other isn't in the graph
136-
}
111+
val fromToOption: Option[(leastPathDigraph.InnerNodeType, leastPathDigraph.InnerNodeType)] = for (f <- fromInner; t <- toInner) yield (f, t)
112+
fromToOption.fold(Seq.empty[Path])(fromTo => {
113+
val label: Label = leastPathDigraph.label(fromTo._1, fromTo._2)
114+
label.fold(Seq.empty[Path])(firstSteps => {
115+
if (firstSteps.choices == Set.empty) Seq(Seq(fromTo._2)) //No further steps. from should be to and the label should be I
116+
else {
117+
for (choice <- firstSteps.choices.to[Seq]) yield {
118+
val tails: Seq[Path] = leastPathsOfInnerNodes(leastPathDigraph.innerNode(choice), toInner)
119+
for (tail <- tails) yield {
120+
Seq(fromTo._1 +: tail)
121+
}
122+
}.flatten
123+
}.flatten
124+
})
125+
})
137126
}
138127

139128
val fromInner = leastPathDigraph.innerNode(from)
@@ -152,18 +141,15 @@ class AllPathsFirstSteps[Node,CoreLabel,Key](coreSupport:SemiringSupport[CoreLab
152141
//todo capture visited nodes and don't revisit them, by taking innerFrom as a Set, pulling out bits, passing in Sets of novel nodes to visit, and passing around another set of nodes already visited.
153142
def recurse(innerFrom:labelGraph.InnerNodeType,innerTo:labelGraph.InnerNodeType):Set[(labelGraph.InnerNodeType,labelGraph.InnerNodeType,Label)] = {
154143
val label:Label = labelGraph.label(innerFrom,innerTo)
155-
label match {
156-
case Some(firstSteps) => {
157144

158-
val innerChoices = firstSteps.choices.map(choice => labelGraph.innerNode(choice).get)
159-
val closeEdges:Set[(labelGraph.InnerNodeType,labelGraph.InnerNodeType,Label)] = innerChoices.map((innerFrom,_,label))
145+
label.fold(Set.empty[(labelGraph.InnerNodeType,labelGraph.InnerNodeType,Label)])(firstSteps => {
146+
val innerChoices = firstSteps.choices.map(choice => labelGraph.innerNode(choice).get)
147+
val closeEdges:Set[(labelGraph.InnerNodeType,labelGraph.InnerNodeType,Label)] = innerChoices.map((innerFrom,_,label))
160148

161-
val farEdges:Set[(labelGraph.InnerNodeType,labelGraph.InnerNodeType,Label)] = innerChoices.map(recurse(_,innerTo)).flatten
149+
val farEdges:Set[(labelGraph.InnerNodeType,labelGraph.InnerNodeType,Label)] = innerChoices.map(recurse(_,innerTo)).flatten
162150

163-
closeEdges ++ farEdges
164-
}
165-
case None => Set.empty
166-
}
151+
closeEdges ++ farEdges
152+
})
167153
}
168154
val innerFrom = labelGraph.innerNode(from).getOrElse(throw new IllegalArgumentException(s"$from not in labelGraph"))
169155

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

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -60,26 +60,24 @@ object Brandes {
6060
val edge = stack.pop() //w
6161
//figure out the partial betweenness to apply to that step
6262
val label: Label = edge._2
63-
label match {
64-
case None => //nothing to do
65-
case Some(sourceLabel: BrandesSteps[Node, CoreLabel]) => {
66-
val sourceCount: Double = sourceLabel.pathCount
67-
val partialFromSource: Double = partialBetweenness(edge._1.index)
68-
for (choiceIndex <- sourceLabel.choiceIndexes) {
69-
//only calculate betweenness for the between nodes, not arriving at the sink
70-
if (choiceIndex != sink.index) {
71-
val oldPartial: Double = partialBetweenness(choiceIndex)
72-
val choiceLabel: Label = shortestPathsToSink(choiceIndex)._3
73-
if (choiceLabel != None) {
74-
val choiceCount: Double = choiceLabel.get.pathCount
75-
//new value is the old value plus (value for coming through the source, plus the source)/number of choices
76-
val newPartial: Double = oldPartial + ((1.0 + partialFromSource) * (choiceCount / sourceCount))
77-
partialBetweenness(choiceIndex) = newPartial
78-
}
63+
64+
label.foreach(sourceLabel => {
65+
val sourceCount: Double = sourceLabel.pathCount
66+
val partialFromSource: Double = partialBetweenness(edge._1.index)
67+
for (choiceIndex <- sourceLabel.choiceIndexes) {
68+
//only calculate betweenness for the between nodes, not arriving at the sink
69+
if (choiceIndex != sink.index) {
70+
val oldPartial: Double = partialBetweenness(choiceIndex)
71+
val choiceLabel: Label = shortestPathsToSink(choiceIndex)._3
72+
if (choiceLabel != None) {
73+
val choiceCount: Double = choiceLabel.get.pathCount
74+
//new value is the old value plus (value for coming through the source, plus the source)/number of choices
75+
val newPartial: Double = oldPartial + ((1.0 + partialFromSource) * (choiceCount / sourceCount))
76+
partialBetweenness(choiceIndex) = newPartial
7977
}
8078
}
8179
}
82-
}
80+
})
8381
}
8482

8583
partialBetweenness
@@ -174,14 +172,11 @@ object Brandes {
174172

175173
def heapOrdering: HeapOrdering[Key] = coreSupport.heapOrdering
176174

177-
def heapKeyForLabel = {
178-
case Some(nextStep) => coreSupport.heapKeyForLabel(nextStep.weight)
179-
case None => coreSupport.heapOrdering.AlwaysBottom
180-
}
175+
def heapKeyForLabel:Label=>Key = _.fold(coreSupport.heapOrdering.AlwaysBottom)(x => coreSupport.heapKeyForLabel(x.weight))
181176

182177
def convertCoreLabelToLabel(labelDigraph:IndexedLabelDigraph[Node,CoreLabel])
183178
(edge:labelDigraph.InnerEdgeType): Label = {
184-
Some(BrandesSteps[Node, CoreLabel](edge._3, 1, Seq(edge._2.index)))
179+
Option(BrandesSteps[Node, CoreLabel](edge._3, 1, Seq(edge._2.index)))
185180
}
186181

187182
/**
@@ -190,14 +185,11 @@ object Brandes {
190185
object BrandesSemiring extends Semiring {
191186

192187
def inDomain(label: Label): Boolean = {
193-
label match {
194-
case Some(steps: BrandesSteps[Node, CoreLabel]) => coreSupport.semiring.inDomain(steps.weight)
195-
case None => true
196-
}
188+
label.forall(steps => coreSupport.semiring.inDomain(steps.weight))
197189
}
198190

199191
//identity and annihilator
200-
val I = Some(BrandesSteps[Node, CoreLabel](coreSupport.semiring.I, 1, Seq.empty))
192+
val I = Option(BrandesSteps[Node, CoreLabel](coreSupport.semiring.I, 1, Seq.empty))
201193
val O = None
202194

203195
def summary(fromThroughToLabel: Label, currentLabel: Label): Label = {
@@ -208,7 +200,7 @@ object Brandes {
208200
val fromThroughToSteps: BrandesSteps[Node, CoreLabel] = fromThroughToLabel.get
209201
val summ = coreSupport.semiring.summary(fromThroughToSteps.weight, currentSteps.weight)
210202
if ((summ == fromThroughToSteps.weight) && (summ == currentSteps.weight)) {
211-
Some(new BrandesSteps[Node, CoreLabel](currentSteps.weight,
203+
Option(BrandesSteps[Node, CoreLabel](currentSteps.weight,
212204
currentSteps.pathCount + fromThroughToSteps.pathCount,
213205
currentSteps.choiceIndexes ++ fromThroughToSteps.choiceIndexes))
214206
}
@@ -230,7 +222,7 @@ object Brandes {
230222
val choiceIndexes: Seq[Int] = if (fromThroughLabel == I) throughToSteps.choiceIndexes
231223
else fromThroughSteps.choiceIndexes
232224

233-
Some(new BrandesSteps[Node, CoreLabel](coreSupport.semiring.extend(fromThroughSteps.weight, throughToSteps.weight),
225+
Option(BrandesSteps[Node, CoreLabel](coreSupport.semiring.extend(fromThroughSteps.weight, throughToSteps.weight),
234226
fromThroughSteps.pathCount * throughToSteps.pathCount,
235227
choiceIndexes
236228
))

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ object FewestNodes extends SemiringSupport[Int,Int] {
5858
* @return Some negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second, or None if they can't be compared
5959
*/
6060
def tryCompare(x: Int, y: Int): Option[Int] = {
61-
Some(y-x)
61+
Option(y-x)
6262
}
6363

6464
def keyDomainDescription = "between zero and Int.MaxValue (the annihilator)"

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ object LeastWeights extends SemiringSupport[Double,Double] {
5858
*/
5959
//todo look again for a version that handles NaNs and infinities
6060
def tryCompare(x: Double, y: Double): Option[Int] = {
61-
Some(y.compareTo(x))
61+
Option(y.compareTo(x))
6262
}
6363

6464
def keyDomainDescription = "between zero and Double.PositiveInfinity (the annihilator)"

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ object MostProbable extends SemiringSupport[Double,Double] {
5858
*/
5959
//todo look again for a version that handles NaNs and infinities
6060
def tryCompare(x: Double, y: Double): Option[Int] = {
61-
Some(x.compareTo(y))
61+
Option(x.compareTo(y))
6262
}
6363

6464
def keyDomainDescription = "between one and zero (the annihilator)"

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

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class OnePathFirstStep[Node,CoreLabel,Key](coreSupport:SemiringSupport[CoreLabel
4646

4747
def convertEdgeToLabel[EdgeLabel](coreLabelForEdge:(Node,Node,EdgeLabel)=>CoreLabel)
4848
(start: Node, end: Node, coreLabel: EdgeLabel):Label = {
49-
Some(FirstStep(coreLabelForEdge(start,end,coreLabel),Some(end)))
49+
Option(FirstStep(coreLabelForEdge(start,end,coreLabel),Option(end)))
5050
}
5151

5252
def convertEdgeToLabelFunc[EdgeLabel](coreLabelForEdge:(Node,Node,EdgeLabel)=>CoreLabel):((Node,Node,EdgeLabel) => Label) = convertEdgeToLabel(coreLabelForEdge)
@@ -57,14 +57,11 @@ class OnePathFirstStep[Node,CoreLabel,Key](coreSupport:SemiringSupport[CoreLabel
5757
//val coreSemiring = coreSupport.semiring
5858

5959
def inDomain(label: Label): Boolean = {
60-
label match {
61-
case Some(step:FirstStep) => coreSupport.semiring.inDomain(step.weight)
62-
case None => true
63-
}
60+
label.forall(step => coreSupport.semiring.inDomain(step.weight))
6461
}
6562

6663
//identity and annihilator
67-
val I = Some(FirstStep(coreSupport.semiring.I,None))
64+
val I = Option(FirstStep(coreSupport.semiring.I,None))
6865
val O = None
6966

7067
def summary(fromThroughToLabel:Label,currentLabel:Label):Label = {
@@ -92,7 +89,7 @@ class OnePathFirstStep[Node,CoreLabel,Key](coreSupport:SemiringSupport[CoreLabel
9289
val step:Option[Node] = if(fromThroughLabel == I) throughToStep.step
9390
else fromThroughStep.step
9491

95-
Some(new FirstStep(coreSupport.semiring.extend(fromThroughStep.weight,throughToStep.weight),step))
92+
Option(FirstStep(coreSupport.semiring.extend(fromThroughStep.weight,throughToStep.weight),step))
9693
}
9794
else O
9895
}
@@ -108,30 +105,17 @@ class OnePathFirstStep[Node,CoreLabel,Key](coreSupport:SemiringSupport[CoreLabel
108105

109106
def leastPathOfInnerNodes(fromInner:Option[leastPathDigraph.InnerNodeType],
110107
toInner:Option[leastPathDigraph.InnerNodeType]):Option[Seq[leastPathDigraph.InnerNodeType]] = {
111-
(fromInner,toInner) match {
112-
case (Some(f),Some(t)) => {
113-
val label:Label = leastPathDigraph.label(f,t)
114-
label match {
115-
case Some(firstStep) => {
116-
firstStep.step match {
117-
case None => Some(Seq.empty[leastPathDigraph.InnerNodeType]) //No further steps. from should be to and the label should be I
118-
case Some(step) => {
119-
val tailOption:Option[Seq[leastPathDigraph.InnerNodeType]] = leastPathOfInnerNodes(leastPathDigraph.innerNode(step),toInner)
120-
tailOption match {
121-
case Some(tail) => {
122-
val innerStep:leastPathDigraph.InnerNodeType = leastPathDigraph.innerNode(step).get
123-
Some(innerStep +: tail)}
124-
case None => None //Following a broken path. Should never happen.
125-
}
126-
}
127-
}
128-
}
129-
case None => None //No path from one to the other
130-
}
131-
}
132-
case _ => None //One node or the other isn't in the graph
133-
}
134-
108+
val fromToOption: Option[(leastPathDigraph.InnerNodeType, leastPathDigraph.InnerNodeType)] = for (f <- fromInner; t <- toInner) yield (f, t)
109+
fromToOption.flatMap(fromTo => {
110+
val label:Label = leastPathDigraph.label(fromTo._1,fromTo._2)
111+
label.flatMap(firstStep => {
112+
firstStep.step.fold(Option(Seq.empty[leastPathDigraph.InnerNodeType]))(step => {
113+
val tailOption:Option[Seq[leastPathDigraph.InnerNodeType]] = leastPathOfInnerNodes(leastPathDigraph.innerNode(step),toInner)
114+
tailOption.flatMap(tail => {val iNodeOption = leastPathDigraph.innerNode(step)
115+
iNodeOption.map(iNode => iNode +: tail)})
116+
})
117+
})
118+
})
135119
}
136120

137121
val fromInner = leastPathDigraph.innerNode(from)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ object TransitiveClosure extends SemiringSupport[Boolean,TransitiveClosureHeapKe
4848
4949
*/
5050
def tryCompare(x: TransitiveClosureHeapKey, y: TransitiveClosureHeapKey): Option[Int] = {
51-
Some(x.state - y.state)
51+
Option(x.state - y.state)
5252
}
5353

5454
/**

src/main/scala/net/walend/heap/FibonacciHeap.scala

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -60,25 +60,19 @@ class FibonacciHeap[K,V](comparator:HeapOrdering[K]) extends Heap[K,V] {
6060

6161
private def changeKey(key:K,fibNode:FibonacciHeapMember):Unit = {
6262
comparator.checkKey(key)
63-
comparator.tryCompare(fibNode.key,key) match {
64-
case Some(x) if x < 0 => raiseKeyInternal(key,fibNode)
65-
case Some(x) if x == 0 => // the key hasn't changed
66-
case Some(x) if x > 0 => {
67-
remove(fibNode)
68-
reinsert(key,fibNode)
69-
}
70-
case None => throw new IllegalArgumentException("Can not compare "+fibNode.key+" and "+key)
63+
64+
if(comparator.lt(fibNode.key,key)) raiseKeyInternal(key,fibNode)
65+
else if (comparator.gt(fibNode.key,key)) {
66+
remove(fibNode)
67+
reinsert(key,fibNode)
7168
}
69+
//if they are equal then the key hasn't changed. Do nothing.
7270
}
7371

7472
private def raiseKey(key:K,fibNode:FibonacciHeapMember):Unit = {
7573
comparator.checkKey(key)
76-
comparator.tryCompare(fibNode.key,key) match {
77-
case Some(x) if x < 0 => raiseKeyInternal(key,fibNode)
78-
case Some(x) if x == 0 => // the key hasn't changed
79-
case Some(x) if x > 0 => // do nothing because the existing key is higher
80-
case None => throw new IllegalArgumentException("Can not compare "+fibNode.key+" and "+key)
81-
}
74+
if(comparator.lt(fibNode.key,key)) raiseKeyInternal(key,fibNode)
75+
//otherwise do nothing. The key is either unchanged or lower
8276
}
8377

8478
private def remove(fibNode:FibonacciHeapMember):Unit = {

0 commit comments

Comments
 (0)