Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor getAllUniqueCombinations avoid nested loops #432

Merged
merged 5 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Switched from `osm4scala` to `openstreetmap.osmosis` [#409](https://github.com/ie3-institute/OSMoGrid/issues/409)
- Changed transformer input parameter to PSDM requirements [#417](https://github.com/ie3-institute/OSMoGrid/issues/417)
- Adapted run initialization [#404](https://github.com/ie3-institute/OSMoGrid/issues/404)
- Refactoring of 'getAllUniqueCombinations' to avoid nested loops [#431](https://github.com/ie3-institute/OSMoGrid/issues/431)

### Fixed
- Fixed bug in `LvGridGeneratorSupport` [#388](https://github.com/ie3-institute/OSMoGrid/issues/388)
Expand Down
45 changes: 29 additions & 16 deletions src/main/scala/utils/Connections.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

package utils

import com.typesafe.scalalogging.LazyLogging
import edu.ie3.datamodel.graph.{DistanceWeightedEdge, DistanceWeightedGraph}
import edu.ie3.datamodel.models.input.NodeInput
import edu.ie3.datamodel.models.input.connector.LineInput
Expand All @@ -26,6 +27,7 @@ import utils.OsmoGridUtils.getAllUniqueCombinations

import javax.measure.quantity.Length
import scala.collection.mutable
import scala.collection.parallel.CollectionConverters._
import scala.jdk.CollectionConverters._

/** This utility object contains all known [[Connection]]s.
Expand Down Expand Up @@ -101,7 +103,7 @@ case class Connections[T](
}
}

object Connections {
object Connections extends LazyLogging {
val log: Logger = LoggerFactory.getLogger(Connections.getClass)

/** Utility object for connections.
Expand Down Expand Up @@ -201,23 +203,34 @@ object Connections {
val vertexes = graph.vertexSet().asScala
val paths = vertexes.map { v => v -> shortestPath.getPaths(v) }.toMap

getAllUniqueCombinations(graph.vertexSet().asScala.toList).map {
case (nodeA, nodeB) =>
val path = paths(nodeA).getPath(nodeB)
if (vertexes.size > 1000)
logger.info(
s"Needs to find shortest path connections for ${vertexes.size} vertices. This may take a while."
)
val connections =
getAllUniqueCombinations(graph.vertexSet().asScala.toList).par.map {
case (nodeA, nodeB) =>
val path = paths(nodeA).getPath(nodeB)

if (path == null) {
throw GridException(
s"No path could be found between $nodeA and $nodeB, because either node is not connected to the graph."
)
}

if (path == null) {
throw GridException(
s"No path could be found between $nodeA and $nodeB, because either node is not connected to the graph."
Connection(
nodeA,
nodeB,
Quantities.getQuantity(path.getWeight, Units.METRE),
Some(path)
)
}

Connection(
nodeA,
nodeB,
Quantities.getQuantity(path.getWeight, Units.METRE),
Some(path)
)
}

}.toList
if (vertexes.size > 1000)
logger.info(
s"Finished search for shortest path connections for ${vertexes.size} vertices."
)
connections
}

/** Method for creating undirected [[Connection]]s. Excluding connections that
Expand Down
32 changes: 5 additions & 27 deletions src/main/scala/utils/OsmoGridUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -139,36 +139,14 @@ object OsmoGridUtils {
* @return
* a list of all unique connections
*/
def getAllUniqueCombinations[T](
nodes: List[T]
): List[(T, T)] = {
def getAllUniqueCombinations[T](nodes: List[T]): List[(T, T)] = {
if (nodes.size < 2) {
List.empty
} else if (nodes.size == 2) {
List((nodes(0), nodes(1)))
} else {
val connections: util.List[(T, T)] =
new util.ArrayList[(T, T)]

// algorithm to find all unique combinations
nodes.foreach(nodeA => {
nodes.foreach(nodeB => {
// it makes no sense to connect a node to itself => nodeA and nodeB cannot be the same
if (nodeA != nodeB) {
// two combinations possible
val t1 = (nodeA, nodeB)
val t2 = (nodeB, nodeA)

// if none of the combinations is already added, the first combination is added
if (!connections.contains(t1) && !connections.contains(t2)) {
connections.add(t1)
}
}
})
})

// returns all unique connections
connections.asScala.toList
for {
(a, i) <- nodes.zipWithIndex
b <- nodes.drop(i + 1)
danielfeismann marked this conversation as resolved.
Show resolved Hide resolved
} yield (a, b)
}
}

Expand Down