Skip to content

Commit

Permalink
chore: Update scala-graph to 2.0.1 (DEV-3072)
Browse files Browse the repository at this point in the history
  • Loading branch information
siers committed Feb 7, 2024
1 parent 2ffd702 commit be4d30b
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

package org.knora.webapi.util.search.gravsearch.prequery

import scalax.collection.Graph
import scalax.collection.GraphEdge.*
import scalax.collection.hyperedges.DiHyperEdge
import scalax.collection.immutable.Graph

import org.knora.webapi.CoreSpec
import org.knora.webapi.messages.util.search.gravsearch.prequery.TopologicalSortUtil
Expand All @@ -15,15 +15,16 @@ import org.knora.webapi.messages.util.search.gravsearch.prequery.TopologicalSort
* Tests [[TopologicalSortUtil]].
*/
class TopologicalSortUtilSpec extends CoreSpec {
type NodeT = Graph[Int, DiHyperEdge]#NodeT
type GraphT = Graph[Int, DiHyperEdge[Int]]
type NodeT = GraphT#NodeT

private def nodesToValues(orders: Set[Vector[NodeT]]): Set[Vector[Int]] = orders.map(_.map(_.value))
private def nodesToValues(orders: Set[Vector[NodeT]]): Set[Vector[Int]] = orders.map(_.map(_.outer))

"TopologicalSortUtilSpec" should {

"return all topological orders of a graph with one leaf" in {
val graph: Graph[Int, DiHyperEdge] =
Graph[Int, DiHyperEdge](DiHyperEdge[Int](2, 4), DiHyperEdge[Int](2, 7), DiHyperEdge[Int](4, 5))
val graph: GraphT =
Graph.from(List(DiHyperEdge[Int](2)(4), DiHyperEdge[Int](2)(7), DiHyperEdge[Int](4)(5)))

val allOrders: Set[Vector[Int]] = nodesToValues(
TopologicalSortUtil
Expand All @@ -38,13 +39,15 @@ class TopologicalSortUtilSpec extends CoreSpec {
}

"return all topological orders of a graph with multiple leaves" in {
val graph: Graph[Int, DiHyperEdge] =
Graph[Int, DiHyperEdge](
DiHyperEdge[Int](2, 4),
DiHyperEdge[Int](2, 7),
DiHyperEdge[Int](2, 8),
DiHyperEdge[Int](4, 5),
DiHyperEdge[Int](7, 3)
val graph: GraphT =
Graph.from(
List(
DiHyperEdge[Int](2)(4),
DiHyperEdge[Int](2)(7),
DiHyperEdge[Int](2)(8),
DiHyperEdge[Int](4)(5),
DiHyperEdge[Int](7)(3)
)
)

val allOrders: Set[Vector[Int]] = nodesToValues(
Expand All @@ -61,7 +64,7 @@ class TopologicalSortUtilSpec extends CoreSpec {
}

"return an empty set of orders for an empty graph" in {
val graph: Graph[Int, DiHyperEdge] = Graph[Int, DiHyperEdge]()
val graph: GraphT = Graph.empty

val allOrders: Set[Vector[Int]] = nodesToValues(
TopologicalSortUtil
Expand All @@ -72,8 +75,8 @@ class TopologicalSortUtilSpec extends CoreSpec {
}

"return an empty set of orders for a cyclic graph" in {
val graph: Graph[Int, DiHyperEdge] =
Graph[Int, DiHyperEdge](DiHyperEdge[Int](2, 4), DiHyperEdge[Int](4, 7), DiHyperEdge[Int](7, 2))
val graph: GraphT =
Graph.from(List(DiHyperEdge[Int](2)(4), DiHyperEdge[Int](4)(7), DiHyperEdge[Int](7)(2)))

val allOrders: Set[Vector[Int]] = nodesToValues(
TopologicalSortUtil
Expand Down
2 changes: 1 addition & 1 deletion project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ object Dependencies {
val rdf4jClient = "org.eclipse.rdf4j" % "rdf4j-client" % "4.3.9"
val rdf4jShacl = "org.eclipse.rdf4j" % "rdf4j-shacl" % "4.3.9"
val saxonHE = "net.sf.saxon" % "Saxon-HE" % "12.4"
val scalaGraph = "org.scala-graph" %% "graph-core" % "1.13.6" // Scala 3 incompatible
val scalaGraph = "org.scala-graph" %% "graph-core" % "2.0.1" // Should be Scala 3 compatible
val titaniumJSONLD = "com.apicatalog" % "titanium-json-ld" % "1.3.3"
val xmlunitCore = "org.xmlunit" % "xmlunit-core" % "2.9.1"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

package org.knora.webapi.messages.util.search.gravsearch.prequery

import scalax.collection.Graph
import scalax.collection.GraphEdge.DiHyperEdge
import scalax.collection.hyperedges.DiHyperEdge
import scalax.collection.immutable.Graph

import org.knora.webapi.messages.OntologyConstants
import org.knora.webapi.messages.SmartIri
Expand All @@ -18,10 +18,13 @@ import org.knora.webapi.messages.util.search.gravsearch.types.GravsearchTypeInsp
import org.knora.webapi.messages.util.search.gravsearch.types.GravsearchTypeInspectionUtil
import org.knora.webapi.messages.util.search.gravsearch.types.TypeableEntity

import GravsearchQueryOptimisation.StringHyperGraph

/**
* A feature factory that constructs Gravsearch query optimisation algorithms.
*/
object GravsearchQueryOptimisation {
type StringHyperGraph = Graph[String, DiHyperEdge[String]]

def optimiseQueryPatterns(
patterns: Seq[QueryPattern],
Expand Down Expand Up @@ -191,11 +194,10 @@ private object ReorderPatternsByDependency {
*/
private def createAndSortGraph(statementPatterns: Seq[StatementPattern]): Seq[QueryPattern] = {
@scala.annotation.tailrec
def makeGraphWithoutCycles(graphComponents: Seq[(String, String)]): Graph[String, DiHyperEdge] = {
val graph: Graph[String, DiHyperEdge] = graphComponents.foldLeft(Graph.empty[String, DiHyperEdge]) {
(graph, edgeDef) =>
val edge: DiHyperEdge[String] = DiHyperEdge(edgeDef._1, edgeDef._2)
graph ++ Vector(edge) // add nodes and edges to graph
def makeGraphWithoutCycles(graphComponents: Seq[(String, String)]): StringHyperGraph = {
val graph: StringHyperGraph = graphComponents.foldLeft(Graph.empty: StringHyperGraph) { (graph, edgeDef) =>
val edge = DiHyperEdge(edgeDef._1)(edgeDef._2)

Check warning on line 199 in webapi/src/main/scala/org/knora/webapi/messages/util/search/gravsearch/prequery/GravsearchQueryOptimisation.scala

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

webapi/src/main/scala/org/knora/webapi/messages/util/search/gravsearch/prequery/GravsearchQueryOptimisation.scala#L199

Found unnamed result or parameter
graph ++ Vector(edge) // add nodes and edges to graph
}

if (graph.isCyclic) {
Expand All @@ -205,8 +207,8 @@ private object ReorderPatternsByDependency {
// the cyclic node is the one that cycle starts and ends with
val cyclicNode: graph.NodeT = cycle.endNode
val cyclicEdge: graph.EdgeT = cyclicNode.edges.last
val originNodeOfCyclicEdge: String = cyclicEdge._1.value
val TargetNodeOfCyclicEdge: String = cyclicEdge._2.value
val originNodeOfCyclicEdge: String = cyclicEdge.node1.outer
val TargetNodeOfCyclicEdge: String = cyclicEdge.node2.outer

Check notice on line 211 in webapi/src/main/scala/org/knora/webapi/messages/util/search/gravsearch/prequery/GravsearchQueryOptimisation.scala

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

webapi/src/main/scala/org/knora/webapi/messages/util/search/gravsearch/prequery/GravsearchQueryOptimisation.scala#L211

Field name 'TargetNodeOfCyclicEdge' does not match the regular expression '^[a-z][A-Za-z0-9]*$'
val graphComponentsWithOutCycle =
graphComponents.filterNot(edgeDef => edgeDef.equals((originNodeOfCyclicEdge, TargetNodeOfCyclicEdge)))

Expand All @@ -216,7 +218,7 @@ private object ReorderPatternsByDependency {
}
}

def createGraph: Graph[String, DiHyperEdge] = {
def createGraph: StringHyperGraph = {
val graphComponents: Seq[(String, String)] = statementPatterns.map { statementPattern =>
// transform every statementPattern to pair of nodes that will consist an edge.
val node1 = statementPattern.subj.toSparql
Expand All @@ -235,10 +237,10 @@ private object ReorderPatternsByDependency {
* @return the filtered topological orders.
*/
def findOrdersNotEndingWithObjectOfRdfType(
orders: Set[Vector[Graph[String, DiHyperEdge]#NodeT]],
orders: Set[Vector[StringHyperGraph#NodeT]],
statementPatterns: Seq[StatementPattern]
): Set[Vector[Graph[String, DiHyperEdge]#NodeT]] = {
type NodeT = Graph[String, DiHyperEdge]#NodeT
): Set[Vector[StringHyperGraph#NodeT]] = {
type NodeT = StringHyperGraph#NodeT

// Find the nodes that are objects of rdf:type in the statement patterns.
val nodesThatAreObjectsOfRdfType: Set[String] = statementPatterns.filter { statementPattern =>
Expand All @@ -252,7 +254,7 @@ private object ReorderPatternsByDependency {

// Filter out the topological orders that end with any of those nodes.
orders.filterNot { (order: Vector[NodeT]) =>
nodesThatAreObjectsOfRdfType.contains(order.last.value)
nodesThatAreObjectsOfRdfType.contains(order.last.outer)
}
}

Expand All @@ -265,16 +267,16 @@ private object ReorderPatternsByDependency {
* @return a topological order.
*/
def findBestTopologicalOrder(
graph: Graph[String, DiHyperEdge],
graph: StringHyperGraph,
statementPatterns: Seq[StatementPattern]
): Vector[Graph[String, DiHyperEdge]#NodeT] = {
type NodeT = Graph[String, DiHyperEdge]#NodeT
): Vector[StringHyperGraph#NodeT] = {
type NodeT = StringHyperGraph#NodeT

/**
* An ordering for sorting topological orders.
*/
object TopologicalOrderOrdering extends Ordering[Vector[NodeT]] {
private def orderToString(order: Vector[NodeT]) = order.map(_.value).mkString("|")
private def orderToString(order: Vector[NodeT]) = order.map(_.outer).mkString("|")

override def compare(left: Vector[NodeT], right: Vector[NodeT]): Int =
orderToString(left).compare(orderToString(right))
Expand Down Expand Up @@ -313,10 +315,10 @@ private object ReorderPatternsByDependency {
}

def sortStatementPatterns(
createdGraph: Graph[String, DiHyperEdge],
createdGraph: StringHyperGraph,
statementPatterns: Seq[StatementPattern]
): Seq[QueryPattern] = {
type NodeT = Graph[String, DiHyperEdge]#NodeT
type NodeT = StringHyperGraph#NodeT

// Try to find the best topological order for the graph.
val topologicalOrder: Vector[NodeT] =
Expand All @@ -326,7 +328,7 @@ private object ReorderPatternsByDependency {
if (topologicalOrder.nonEmpty) {
// Yes. Sort the statement patterns according to the reverse topological order.
topologicalOrder.foldRight(Vector.empty[QueryPattern]) { (node, sortedStatements) =>
val nextStatements = statementPatterns.filter(_.obj.toSparql.equals(node.value)).toVector
val nextStatements = statementPatterns.filter(_.obj.toSparql.equals(node.outer)).toVector
nextStatements ++ sortedStatements
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

package org.knora.webapi.messages.util.search.gravsearch.prequery

import scalax.collection.Graph
import scalax.collection.GraphEdge.DiHyperEdge
import scalax.collection.hyperedges.DiHyperEdge
import scalax.collection.immutable.Graph

/**
* A utility for finding all topological orders of a graph.
Expand All @@ -20,8 +20,10 @@ object TopologicalSortUtil {
* @param graph the graph to be sorted.
* @tparam T the type of the nodes in the graph.
*/
def findAllTopologicalOrderPermutations[T](graph: Graph[T, DiHyperEdge]): Set[Vector[Graph[T, DiHyperEdge]#NodeT]] = {
type NodeT = Graph[T, DiHyperEdge]#NodeT
def findAllTopologicalOrderPermutations[T](
graph: Graph[T, DiHyperEdge[T]]
): Set[Vector[Graph[T, DiHyperEdge[T]]#NodeT]] = {
type NodeT = Graph[T, DiHyperEdge[T]]#NodeT

/**
* Finds all possible topological order permutations of a graph using layer information. This method considers all
Expand Down Expand Up @@ -55,7 +57,9 @@ object TopologicalSortUtil {
// Get those nodes within a layer that are origins of outgoing edges to the nodes already in set of ordered nodes.
val origins: Set[NodeT] = acc.foldRight(Set.empty[NodeT]) { (node, originsAcc) =>
val maybeOriginNode: Option[NodeT] =
layerNodes.find(layerNode => graph.edges.contains(DiHyperEdge(layerNode, node)))
layerNodes.find { layerNode =>
graph.edges.find(DiHyperEdge(layerNode.outer)(node.outer)).isDefined
}
// Is there any edge which has its origin in this layer and target in already visited layers?
maybeOriginNode match {
// Yes. Add the origin node to the topological order
Expand Down

0 comments on commit be4d30b

Please sign in to comment.