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 all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
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
43 changes: 9 additions & 34 deletions src/main/scala/utils/OsmoGridUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,7 @@ package utils

import edu.ie3.datamodel.models.OperationTime
import edu.ie3.datamodel.models.input.connector.Transformer2WInput
import edu.ie3.datamodel.models.input.container.{
GraphicElements,
JointGridContainer,
RawGridElements,
SystemParticipants
}
import edu.ie3.datamodel.models.input.container.JointGridContainer
import edu.ie3.datamodel.models.input.{NodeInput, OperatorInput}
import edu.ie3.datamodel.models.voltagelevels.VoltageLevel
import edu.ie3.osmogrid.cfg.OsmoGridConfig.Voltage
Expand All @@ -34,7 +29,6 @@ import org.locationtech.jts.geom.{Coordinate, Polygon}
import tech.units.indriya.ComparableQuantity
import tech.units.indriya.unit.Units

import java.util
import java.util.UUID
import javax.measure.quantity.{Area, Power}
import scala.collection.parallel.ParSeq
Expand Down Expand Up @@ -139,36 +133,17 @@ 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 {
// Loops through all nodes as a and combines each node a with each b
// of the same nodes list. Nodes as b are restricted to those that
// occur later in the list than each node a respectively.
(a, i) <- nodes.zipWithIndex
b <- nodes.drop(i + 1)
danielfeismann marked this conversation as resolved.
Show resolved Hide resolved
} yield (a, b)
}
}

Expand Down