关于在N×N网格图中借助Jung获取对称不同节点对的技术问询
Absolutely, this is totally doable! Let’s break this down step by step—your instinct to handle the matrix/coordinate logic first before mapping to Jung’s graph structure is spot-on, since grid symmetry is fundamentally a geometric transformation problem.
第一步:先搞定矩阵层面的对称计算
First, let’s ground every vertex in grid coordinates. Assuming your N×N grid’s vertices are numbered row-wise (e.g., 3×3 grid: 0(0,0), 1(0,1), 2(0,2), 3(1,0), ..., 8(2,2)), you can convert any vertex ID to its (x,y) coordinates with simple arithmetic:
int x = vertexId / N; int y = vertexId % N;
Next, define the symmetry transformations you care about (matching your examples like 8→0 and 5→3, which are central symmetry). Here are formulas for common axes:
- Central symmetry (your example case): Symmetric point is
(N-1 - x, N-1 - y). Convert back to ID:(N-1 - x)*N + (N-1 - y) - Vertical midline symmetry:
(x, N-1 - y)→ ID:x*N + (N-1 - y) - Horizontal midline symmetry:
(N-1 - x, y)→ ID:(N-1 - x)*N + y - Main diagonal symmetry:
(y, x)→ ID:y*N + x - Anti-diagonal symmetry:
(N-1 - y, N-1 - x)→ ID:(N-1 - y)*N + (N-1 - x)
第二步:映射到Jung框架
Jung works great with this—you can either use Integer directly as your vertex type (since you’re using IDs) or create a custom vertex class that stores both the ID and coordinates. Here’s a quick utility method to get the symmetric vertex ID, which you can plug into your Jung workflow:
// First, define an enum for symmetry axes to keep things clean enum SymmetryAxis { CENTER, VERTICAL_MIDLINE, HORIZONTAL_MIDLINE, MAIN_DIAGONAL, ANTI_DIAGONAL } public static int getSymmetricVertex(int vertexId, int gridSize, SymmetryAxis axis) { int x = vertexId / gridSize; int y = vertexId % gridSize; int symX, symY; switch(axis) { case CENTER: symX = gridSize - 1 - x; symY = gridSize - 1 - y; break; case VERTICAL_MIDLINE: symX = x; symY = gridSize - 1 - y; break; case HORIZONTAL_MIDLINE: symX = gridSize - 1 - x; symY = y; break; case MAIN_DIAGONAL: symX = y; symY = x; break; case ANTI_DIAGONAL: symX = gridSize - 1 - y; symY = gridSize - 1 - x; break; default: throw new IllegalArgumentException("Unknown symmetry axis"); } return symX * gridSize + symY; }
第三步:分组等价节点对
To handle equivalent pairs like (4,1)/(4,7) or (1,3)/(3,7), you need to standardize each pair to a "representative" form that captures all symmetrically identical pairs. Here’s how:
- Standardize individual pairs: For any pair
(a,b), store it as(min(a,b), max(a,b))to avoid duplicates like(4,1)and(1,4). - Generate symmetric variants: For a given pair, generate all possible pairs you can get by applying every symmetry transformation.
- Pick the canonical representative: From all variants, select the lexicographically smallest pair as the group’s representative—this way, symmetrically identical pairs will map to the same representative.
Here’s a code snippet to implement this:
// Use a Pair class (e.g., from Apache Commons Lang, or your own) public static Pair<Integer, Integer> getCanonicalPair(Pair<Integer, Integer> originalPair, int gridSize) { Set<Pair<Integer, Integer>> transformedPairs = new HashSet<>(); int a = originalPair.getLeft(); int b = originalPair.getRight(); // Generate all symmetric transformations of the pair for (SymmetryAxis axis : SymmetryAxis.values()) { int symA = getSymmetricVertex(a, gridSize, axis); int symB = getSymmetricVertex(b, gridSize, axis); // Standardize the transformed pair int min = Math.min(symA, symB); int max = Math.max(symA, symB); transformedPairs.add(new Pair<>(min, max)); } // Return the lexicographically smallest pair as the canonical representative return transformedPairs.stream() .min(Comparator.comparing(Pair::getLeft).thenComparing(Pair::getRight)) .orElse(originalPair); }
Now, you can iterate over all possible vertex pairs, compute their canonical representative, and group them using a Map<Pair<Integer, Integer>, List<Pair<Integer, Integer>>>. This will give you distinct groups of equivalent pairs, exactly what you’re looking for.
整合到Jung的工作流
- Bind coordinates to Jung vertices: If you’re using custom vertices, add
xandyfields. If usingIntegerIDs, store aMap<Integer, int[]>to map IDs to coordinates. - Lookup symmetric vertices: Use the
getSymmetricVertexmethod whenever you need to find a vertex’s symmetric counterpart in your Jung graph. - Group equivalent pairs: Run your vertex pairs through
getCanonicalPairand group them to avoid redundant pairs in your analysis or visualization.
This approach keeps the geometric logic clean and separate from Jung’s graph handling, making your code easier to maintain and extend.
内容的提问来源于stack exchange,提问作者Casper

