From 4f24c75365a1990e327648ef9ba908276bab5e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Wolski?= Date: Thu, 16 Jul 2026 10:19:02 +0200 Subject: [PATCH] Sort graph string output in GraphElement and update tests - Implement local sorted formatter in `GraphElement` to avoid delegating to JGraphT's `toStringFromSets` - Sort vertices and edges by string representation for deterministic output - Update graph test expectations in test-rsc/plugin-tests/graph to match new deterministic order Co-authored-by: GitHub Copilot --- .../network/plugins/graph/GraphElement.java | 53 ++++++++++++++++++- .../graph/TestGraph2_dijkstra.casm | 2 +- .../graph/TestGraph3_connectedSet.casm | 2 +- .../graph/TestGraph4_isConnected.casm | 4 +- .../graph/TestGraph5_hasCycle.casm | 4 +- .../TestGraph6_findCyclesWithVertex.casm | 4 +- .../graph/TestGraph7_subgraph.casm | 8 +-- .../graph/TestGraph8_asUndirectedGraph.casm | 4 +- 8 files changed, 66 insertions(+), 15 deletions(-) diff --git a/org.coreasm.engine/src/org/coreasm/network/plugins/graph/GraphElement.java b/org.coreasm.engine/src/org/coreasm/network/plugins/graph/GraphElement.java index a4b747fb..efc153e6 100644 --- a/org.coreasm.engine/src/org/coreasm/network/plugins/graph/GraphElement.java +++ b/org.coreasm.engine/src/org/coreasm/network/plugins/graph/GraphElement.java @@ -12,6 +12,11 @@ */ package org.coreasm.network.plugins.graph; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; + import org.jgrapht.Graph; import org.coreasm.engine.absstorage.Element; @@ -55,7 +60,53 @@ public String getBackground() { @Override public String toString() { - return getGraph().toString(); + Graph graph = getGraph(); + return toStringFromSets(graph, graph.vertexSet(), graph.edgeSet(), isDirected()); + } + + /** + * Returns a string of the parenthesized pair (V, E) representing this G=(V,E) graph. 'V' is the + * string representation of the vertex set, and 'E' is the string representation of the edge + * set. The vertex and edge order is sorted by their string representations. + * + * @param vertexSet the vertex set V to be printed + * @param edgeSet the edge set E to be printed + * @param directed true to use parens for each edge (representing directed); false to use curly + * braces (representing undirected) + * + * @return a string representation of (V,E) + */ + protected String toStringFromSets(Graph graph, + Collection vertexSet, Collection edgeSet, boolean directed) { + List sortedVertices = new ArrayList<>(vertexSet); + sortedVertices.sort(Comparator.comparing(String::valueOf)); + + List sortedEdges = new ArrayList<>(edgeSet); + sortedEdges.sort(Comparator.comparing(String::valueOf)); + + List renderedEdges = new ArrayList<>(); + for (Element e : sortedEdges) { + StringBuilder sb = new StringBuilder(); + sb.append(e); + sb.append("="); + if (directed) { + sb.append("("); + } else { + sb.append("{"); + } + sb.append(graph.getEdgeSource(e)); + sb.append(","); + sb.append(graph.getEdgeTarget(e)); + if (directed) { + sb.append(")"); + } else { + sb.append("}"); + } + + renderedEdges.add(sb.toString()); + } + + return "(" + sortedVertices + ", " + renderedEdges + ")"; } /** diff --git a/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph2_dijkstra.casm b/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph2_dijkstra.casm index bb6beb74..15d7c8f9 100644 --- a/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph2_dijkstra.casm +++ b/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph2_dijkstra.casm @@ -10,7 +10,7 @@ function g : -> GRAPH * @minsteps 1 * @maxsteps 1 * - * @require "g: ([a, b, c, x], [(a:b)=(a,b), (b:c)=(b,c), (a:c)=(a,c), (c:x)=(c,x)])" + * @require "g: ([a, b, c, x], [(a:b)=(a,b), (a:c)=(a,c), (b:c)=(b,c), (c:x)=(c,x)])" * @require "dijkstraShortestPath(g, a, c): [(a:c)]" * @require "dijkstraShortestPath(g, a, x): [(a:c), (c:x)]" * @require "dijkstraShortestPath(g, b, x): [(b:c), (c:x)]" diff --git a/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph3_connectedSet.casm b/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph3_connectedSet.casm index 997aad5b..ae3ca191 100644 --- a/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph3_connectedSet.casm +++ b/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph3_connectedSet.casm @@ -10,7 +10,7 @@ function g : -> GRAPH * @minsteps 1 * @maxsteps 1 * - * @require "g: ([a, b, c, x, y], [(a:b)=(a,b), (b:c)=(b,c), (a:c)=(a,c), (x:y)=(x,y)])" + * @require "g: ([a, b, c, x, y], [(a:b)=(a,b), (a:c)=(a,c), (b:c)=(b,c), (x:y)=(x,y)])" * @require "connectedSet(g, a): {a, b, c}" * @require "connectedSet(g, y): {x, y}" */ diff --git a/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph4_isConnected.casm b/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph4_isConnected.casm index 507772e1..e3097779 100644 --- a/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph4_isConnected.casm +++ b/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph4_isConnected.casm @@ -11,8 +11,8 @@ function g2 : -> GRAPH * @minsteps 1 * @maxsteps 1 * - * @require "g1: ([a, b, c], [(a:b)=(a,b), (b:c)=(b,c), (a:c)=(a,c)])" - * @require "g2: ([a, b, c, x, y], [(a:b)=(a,b), (b:c)=(b,c), (a:c)=(a,c), (x:y)=(x,y)])" + * @require "g1: ([a, b, c], [(a:b)=(a,b), (a:c)=(a,c), (b:c)=(b,c)])" + * @require "g2: ([a, b, c, x, y], [(a:b)=(a,b), (a:c)=(a,c), (b:c)=(b,c), (x:y)=(x,y)])" * @require "isConnected(g1): true" * @require "isConnected(g2): false" */ diff --git a/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph5_hasCycle.casm b/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph5_hasCycle.casm index 019b7afb..a05c0cf1 100644 --- a/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph5_hasCycle.casm +++ b/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph5_hasCycle.casm @@ -11,8 +11,8 @@ function g2 : -> GRAPH * @minsteps 1 * @maxsteps 1 * - * @require "g1: ([a, b, c], [(a:b)=(a,b), (b:c)=(b,c), (a:c)=(a,c)])" - * @require "g2: ([a, b, c], [(a:b)=(a,b), (b:c)=(b,c), (a:c)=(a,c), (c:a)=(c,a)])" + * @require "g1: ([a, b, c], [(a:b)=(a,b), (a:c)=(a,c), (b:c)=(b,c)])" + * @require "g2: ([a, b, c], [(a:b)=(a,b), (a:c)=(a,c), (b:c)=(b,c), (c:a)=(c,a)])" * @require "hasCycle(g1): false" * @require "hasCycle(g2): true" */ diff --git a/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph6_findCyclesWithVertex.casm b/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph6_findCyclesWithVertex.casm index e695491d..2f73d283 100644 --- a/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph6_findCyclesWithVertex.casm +++ b/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph6_findCyclesWithVertex.casm @@ -11,8 +11,8 @@ function g2 : -> GRAPH * @minsteps 1 * @maxsteps 1 * - * @require "g1: ([a, b, c], [(a:b)=(a,b), (b:c)=(b,c), (a:c)=(a,c), (c:a)=(c,a)])" - * @require "g2: ([a, b, c, x, y], [(a:b)=(a,b), (b:c)=(b,c), (a:c)=(a,c), (c:a)=(c,a), (x:y)=(x,y), (y:x)=(y,x)])" + * @require "g1: ([a, b, c], [(a:b)=(a,b), (a:c)=(a,c), (b:c)=(b,c), (c:a)=(c,a)])" + * @require "g2: ([a, b, c, x, y], [(a:b)=(a,b), (a:c)=(a,c), (b:c)=(b,c), (c:a)=(c,a), (x:y)=(x,y), (y:x)=(y,x)])" * @require "findCyclesWithVertex(g1, a): {a, b, c}" * @require "findCyclesWithVertex(g2, a): {a, b, c}" * @require "findCyclesWithVertex(g2, x): {x, y}" diff --git a/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph7_subgraph.casm b/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph7_subgraph.casm index c1d71e6f..a7047ad7 100644 --- a/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph7_subgraph.casm +++ b/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph7_subgraph.casm @@ -11,12 +11,12 @@ function g2 : -> GRAPH * @minsteps 1 * @maxsteps 1 * - * @require "g1: ([a, b, c], [(a:b)=(a,b), (b:c)=(b,c), (a:c)=(a,c), (c:a)=(c,a)])" - * @require "g2: ([a, b, c, x, y], [(a:b)=(a,b), (b:c)=(b,c), (a:c)=(a,c), (c:a)=(c,a), (x:y)=(x,y), (y:x)=(y,x)])" + * @require "g1: ([a, b, c], [(a:b)=(a,b), (a:c)=(a,c), (b:c)=(b,c), (c:a)=(c,a)])" + * @require "g2: ([a, b, c, x, y], [(a:b)=(a,b), (a:c)=(a,c), (b:c)=(b,c), (c:a)=(c,a), (x:y)=(x,y), (y:x)=(y,x)])" * @require "subgraph(g1, {a}): ([a], [])" * @require "subgraph(g1, {a, b}): ([a, b], [(a:b)=(a,b)])" - * @require "subgraph(g1, {a, b, c}): ([a, b, c], [(a:b)=(a,b), (b:c)=(b,c), (a:c)=(a,c), (c:a)=(c,a)])" - * @require "subgraph(g2, {a, b, c}): ([a, b, c], [(a:b)=(a,b), (b:c)=(b,c), (a:c)=(a,c), (c:a)=(c,a)])" + * @require "subgraph(g1, {a, b, c}): ([a, b, c], [(a:b)=(a,b), (a:c)=(a,c), (b:c)=(b,c), (c:a)=(c,a)])" + * @require "subgraph(g2, {a, b, c}): ([a, b, c], [(a:b)=(a,b), (a:c)=(a,c), (b:c)=(b,c), (c:a)=(c,a)])" * @require "subgraph(g2, {x, y}): ([x, y], [(x:y)=(x,y), (y:x)=(y,x)])" */ rule Start = diff --git a/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph8_asUndirectedGraph.casm b/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph8_asUndirectedGraph.casm index dd017a8e..b69dc75b 100644 --- a/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph8_asUndirectedGraph.casm +++ b/org.coreasm.engine/test-rsc/plugin-tests/graph/TestGraph8_asUndirectedGraph.casm @@ -10,8 +10,8 @@ function g : -> GRAPH * @minsteps 1 * @maxsteps 1 * - * @require "g: ([a, b, c], [(a:b)=(a,b), (b:c)=(b,c), (a:c)=(a,c), (c:a)=(c,a)])" - * @require "asUndirectedGraph(g): ([a, b, c], [(a:b)={a,b}, (b:c)={b,c}, (a:c)={a,c}, (c:a)={c,a}])" + * @require "g: ([a, b, c], [(a:b)=(a,b), (a:c)=(a,c), (b:c)=(b,c), (c:a)=(c,a)])" + * @require "asUndirectedGraph(g): ([a, b, c], [(a:b)={a,b}, (a:c)={a,c}, (b:c)={b,c}, (c:a)={c,a}])" * @require "dijkstraShortestPath(g, c, b): [(c:a), (a:b)]" * @require "dijkstraShortestPath(asUndirectedGraph(g), c, b): [(b:c)]" */