From 9f651a92360c385379fb35d2c1cdb5b8cc5e1978 Mon Sep 17 00:00:00 2001 From: Andreas Marek Date: Tue, 18 Apr 2023 14:28:34 +1000 Subject: [PATCH 1/6] reuse the parent mapping available target vertices --- .../java/graphql/schema/diffing/DiffImpl.java | 52 ++++++++++--------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/src/main/java/graphql/schema/diffing/DiffImpl.java b/src/main/java/graphql/schema/diffing/DiffImpl.java index dbeba3748..4281bbb7f 100644 --- a/src/main/java/graphql/schema/diffing/DiffImpl.java +++ b/src/main/java/graphql/schema/diffing/DiffImpl.java @@ -46,6 +46,11 @@ private static class MappingEntry { public boolean siblingsFinished; public LinkedBlockingQueue mappingEntriesSiblings; public int[] assignments; + + /** + * These are the available vertices, relative to the parent mapping. + * Meaning the last mapped element is NOT contained in it. + */ public List availableTargetVertices; Mapping partialMapping; @@ -112,7 +117,12 @@ OptimalEdit diffImpl(Mapping startMapping, List allSources, List int fixedEditorialCost = baseEditorialCostForMapping(startMapping, completeSourceGraph, completeTargetGraph); int level = startMapping.size(); + + List allNonFixedTargets = new ArrayList<>(allTargets); + startMapping.forEachTarget(allNonFixedTargets::remove); + MappingEntry firstMappingEntry = new MappingEntry(startMapping, level, fixedEditorialCost); + firstMappingEntry.availableTargetVertices = allNonFixedTargets; OptimalEdit optimalEdit = new OptimalEdit(completeSourceGraph, completeTargetGraph); PriorityQueue queue = new PriorityQueue<>((mappingEntry1, mappingEntry2) -> { @@ -129,8 +139,6 @@ OptimalEdit diffImpl(Mapping startMapping, List allSources, List // System.out.println("graph size: " + this.completeSourceGraph.size() + " non mapped vertices " + (completeSourceGraph.size() - startMapping.size())); // System.out.println("start mapping at level: " + firstMappingEntry.level); - List allNonFixedTargets = new ArrayList<>(allTargets); - startMapping.forEachTarget(allNonFixedTargets::remove); int count = 0; while (!queue.isEmpty()) { @@ -140,9 +148,7 @@ OptimalEdit diffImpl(Mapping startMapping, List allSources, List continue; } -// if (count % 100 == 0) { -// System.out.println(" level: " + mappingEntry.level + " with cost: " + mappingEntry.lowerBoundCost + " queue size: " + queue.size()); -// } +// System.out.println(" level: " + mappingEntry.level + " with cost: " + mappingEntry.lowerBoundCost + " queue size: " + queue.size()); if (mappingEntry.level > 0 && !mappingEntry.siblingsFinished) { addSiblingToQueue( @@ -161,8 +167,7 @@ OptimalEdit diffImpl(Mapping startMapping, List allSources, List queue, optimalEdit, allSources, - allTargets, - allNonFixedTargets + allTargets ); } @@ -179,19 +184,21 @@ private void addChildToQueue(int fixedEditorialCost, PriorityQueue queue, OptimalEdit optimalEdit, List allSources, - List allTargets, - List allNonFixedTargets) { - Mapping partialMapping = parentEntry.partialMapping; + List allTargets + ) { + Mapping parentPartialMapping = parentEntry.partialMapping; int level = parentEntry.level; - assertTrue(level == partialMapping.size()); + assertTrue(level == parentPartialMapping.size()); - // not great: we iterate over all targets, which can be huge - ArrayList availableTargetVertices = new ArrayList<>(allNonFixedTargets); - partialMapping.forEachNonFixedTarget(availableTargetVertices::remove); - assertTrue(availableTargetVertices.size() + partialMapping.size() == allTargets.size()); + // the available target vertices are the parent queue entry ones plus + // minus the additional mapped element in parentPartialMapping + ArrayList availableTargetVertices = new ArrayList<>(parentEntry.availableTargetVertices); + availableTargetVertices.remove(parentPartialMapping.getTarget(level - 1)); + assertTrue(availableTargetVertices.size() + parentPartialMapping.size() == allTargets.size()); Vertex v_i = allSources.get(level); + // the cost matrix is for the non mapped vertices int costMatrixSize = allSources.size() - level; @@ -208,7 +215,7 @@ private void addChildToQueue(int fixedEditorialCost, Vertex v = allSources.get(i); int j = 0; for (Vertex u : availableTargetVertices) { - double cost = calcLowerBoundMappingCost(v, u, partialMapping, deletionCostsCache); + double cost = calcLowerBoundMappingCost(v, u, parentPartialMapping, deletionCostsCache); costMatrixForHungarianAlgo[i - level].set(j, cost); costMatrix[i - level].set(j, cost); j++; @@ -219,14 +226,14 @@ private void addChildToQueue(int fixedEditorialCost, // System.out.println("size2: " + allCount + " vs sqrt of realSize:" + Math.sqrt(realSize)); HungarianAlgorithm hungarianAlgorithm = new HungarianAlgorithm(costMatrixForHungarianAlgo); int[] assignments = hungarianAlgorithm.execute(); - int editorialCostForMapping = editorialCostForMapping(fixedEditorialCost, partialMapping, completeSourceGraph, completeTargetGraph); + int editorialCostForMapping = editorialCostForMapping(fixedEditorialCost, parentPartialMapping, completeSourceGraph, completeTargetGraph); // System.out.println("editorial cost for partial mapping: " + editorialCostForMapping + " for level " + (level - (allSources.size() - allNonFixedTargets.size()))); -// System.out.println("last source vertex " + partialMapping.getSource(partialMapping.size() - 1) + " -> " + partialMapping.getTarget(partialMapping.size() - 1)); +// System.out.println("last source vertex " + parentPartialMapping.getSource(parentPartialMapping.size() - 1) + " -> " + parentPartialMapping.getTarget(parentPartialMapping.size() - 1)); double costMatrixSum = getCostMatrixSum(costMatrix, assignments); double lowerBoundForPartialMapping = editorialCostForMapping + costMatrixSum; int v_i_target_IndexSibling = assignments[0]; Vertex bestExtensionTargetVertexSibling = availableTargetVertices.get(v_i_target_IndexSibling); - Mapping newMappingSibling = partialMapping.extendMapping(v_i, bestExtensionTargetVertexSibling); + Mapping newMappingSibling = parentPartialMapping.extendMapping(v_i, bestExtensionTargetVertexSibling); if (lowerBoundForPartialMapping >= optimalEdit.ged) { @@ -239,7 +246,7 @@ private void addChildToQueue(int fixedEditorialCost, newMappingEntry.availableTargetVertices = availableTargetVertices; queue.add(newMappingEntry); - Mapping fullMapping = partialMapping.copy(); + Mapping fullMapping = parentPartialMapping.copy(); for (int i = 0; i < assignments.length; i++) { fullMapping.add(allSources.get(level + i), availableTargetVertices.get(assignments[i])); } @@ -254,7 +261,7 @@ private void addChildToQueue(int fixedEditorialCost, hungarianAlgorithm, costMatrix, editorialCostForMapping, - partialMapping, + parentPartialMapping, v_i, optimalEdit.ged, level + 1, @@ -282,9 +289,7 @@ private void calculateRestOfChildren(List availableTargetVertices, int level, LinkedBlockingQueue siblings ) { -// System.out.println("level : " + level + " max children count calculate: " + (availableTargetVertices.size() - 1)); // starting from 1 as we already generated the first one - int oldSiblingsSize = siblings.size(); for (int child = 1; child < availableTargetVertices.size(); child++) { int[] assignments = hungarianAlgorithm.nextChild(); if (hungarianAlgorithm.costMatrix[0].get(assignments[0]) == Integer.MAX_VALUE) { @@ -310,7 +315,6 @@ private void calculateRestOfChildren(List availableTargetVertices, runningCheck.check(); } -// System.out.println("calculated " + (siblings.size() - oldSiblingsSize) + " children / " + (availableTargetVertices.size())); siblings.add(MappingEntry.DUMMY); } From 3ebf2def7b80d5362266bd2a2ceae4efa8f5b321 Mon Sep 17 00:00:00 2001 From: Andreas Marek Date: Wed, 19 Apr 2023 03:22:48 +1000 Subject: [PATCH 2/6] use primitive array instead of AtomicDouble --- .../java/graphql/schema/diffing/DiffImpl.java | 25 +++++++------- .../schema/diffing/HungarianAlgorithm.java | 33 +++++++++---------- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/main/java/graphql/schema/diffing/DiffImpl.java b/src/main/java/graphql/schema/diffing/DiffImpl.java index 4281bbb7f..f6a45f4db 100644 --- a/src/main/java/graphql/schema/diffing/DiffImpl.java +++ b/src/main/java/graphql/schema/diffing/DiffImpl.java @@ -3,11 +3,9 @@ import com.google.common.collect.HashMultiset; import com.google.common.collect.Multiset; import com.google.common.collect.Multisets; -import com.google.common.util.concurrent.AtomicDoubleArray; import graphql.Internal; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedHashSet; @@ -148,7 +146,9 @@ OptimalEdit diffImpl(Mapping startMapping, List allSources, List continue; } -// System.out.println(" level: " + mappingEntry.level + " with cost: " + mappingEntry.lowerBoundCost + " queue size: " + queue.size()); +// if (count % 1000 == 0) { +// System.out.println(mappingEntry.lowerBoundCost + " vs ged " + optimalEdit.ged + " count " + count); +// } if (mappingEntry.level > 0 && !mappingEntry.siblingsFinished) { addSiblingToQueue( @@ -203,10 +203,8 @@ private void addChildToQueue(int fixedEditorialCost, int costMatrixSize = allSources.size() - level; // costMatrix gets modified by the hungarian algorithm ... therefore we create two of them - AtomicDoubleArray[] costMatrixForHungarianAlgo = new AtomicDoubleArray[costMatrixSize]; - Arrays.setAll(costMatrixForHungarianAlgo, (index) -> new AtomicDoubleArray(costMatrixSize)); - AtomicDoubleArray[] costMatrix = new AtomicDoubleArray[costMatrixSize]; - Arrays.setAll(costMatrix, (index) -> new AtomicDoubleArray(costMatrixSize)); + double[][] costMatrixForHungarianAlgo = new double[costMatrixSize][costMatrixSize]; + double[][] costMatrix = new double[costMatrixSize][costMatrixSize]; Map deletionCostsCache = new LinkedHashMap<>(); @@ -216,8 +214,8 @@ private void addChildToQueue(int fixedEditorialCost, int j = 0; for (Vertex u : availableTargetVertices) { double cost = calcLowerBoundMappingCost(v, u, parentPartialMapping, deletionCostsCache); - costMatrixForHungarianAlgo[i - level].set(j, cost); - costMatrix[i - level].set(j, cost); + costMatrixForHungarianAlgo[i - level][j] = cost; + costMatrix[i - level][j] = cost; j++; } runningCheck.check(); @@ -281,7 +279,7 @@ private void updateOptimalEdit(OptimalEdit optimalEdit, int newGed, Mapping mapp // generate all children mappings and save in MappingEntry.sibling private void calculateRestOfChildren(List availableTargetVertices, HungarianAlgorithm hungarianAlgorithm, - AtomicDoubleArray[] costMatrixCopy, + double[][] costMatrixCopy, double editorialCostForMapping, Mapping partialMapping, Vertex v_i, @@ -292,7 +290,7 @@ private void calculateRestOfChildren(List availableTargetVertices, // starting from 1 as we already generated the first one for (int child = 1; child < availableTargetVertices.size(); child++) { int[] assignments = hungarianAlgorithm.nextChild(); - if (hungarianAlgorithm.costMatrix[0].get(assignments[0]) == Integer.MAX_VALUE) { + if (hungarianAlgorithm.costMatrix[0][assignments[0]] == Integer.MAX_VALUE) { break; } @@ -315,6 +313,7 @@ private void calculateRestOfChildren(List availableTargetVertices, runningCheck.check(); } +// System.out.println("overall children count " + (siblings.size()+1) + " vs possible mappings " + possibleMappings.possibleMappings.get(v_i).size() ); siblings.add(MappingEntry.DUMMY); } @@ -351,10 +350,10 @@ private void addSiblingToQueue( } - private double getCostMatrixSum(AtomicDoubleArray[] costMatrix, int[] assignments) { + private double getCostMatrixSum(double[][] costMatrix, int[] assignments) { double costMatrixSum = 0; for (int i = 0; i < assignments.length; i++) { - costMatrixSum += costMatrix[i].get(assignments[i]); + costMatrixSum += costMatrix[i][assignments[i]]; } return costMatrixSum; } diff --git a/src/main/java/graphql/schema/diffing/HungarianAlgorithm.java b/src/main/java/graphql/schema/diffing/HungarianAlgorithm.java index 647635279..7818d2987 100644 --- a/src/main/java/graphql/schema/diffing/HungarianAlgorithm.java +++ b/src/main/java/graphql/schema/diffing/HungarianAlgorithm.java @@ -1,6 +1,5 @@ package graphql.schema.diffing; -import com.google.common.util.concurrent.AtomicDoubleArray; import graphql.Internal; import java.util.Arrays; @@ -53,7 +52,7 @@ @Internal public class HungarianAlgorithm { // changed by reduce - public final AtomicDoubleArray[] costMatrix; + public final double[][] costMatrix; // constant always private final int rows; @@ -85,10 +84,10 @@ public class HungarianAlgorithm { * irregular in the sense that all rows must be the same length; in * addition, all entries must be non-infinite numbers. */ - public HungarianAlgorithm(AtomicDoubleArray[] costMatrix) { - this.dim = Math.max(costMatrix.length, costMatrix[0].length()); + public HungarianAlgorithm(double[][] costMatrix) { + this.dim = Math.max(costMatrix.length, costMatrix[0].length); this.rows = costMatrix.length; - this.cols = costMatrix[0].length(); + this.cols = costMatrix[0].length; this.costMatrix = costMatrix; // for (int w = 0; w < this.dim; w++) { // if (w < costMatrix.length) { @@ -131,8 +130,8 @@ protected void computeInitialFeasibleSolution() { } for (int w = 0; w < dim; w++) { for (int j = 0; j < dim; j++) { - if (costMatrix[w].get(j) < labelByJob[j]) { - labelByJob[j] = costMatrix[w].get(j); + if (costMatrix[w][j] < labelByJob[j]) { + labelByJob[j] = costMatrix[w][j]; } } } @@ -241,7 +240,7 @@ protected void executePhase() { committedWorkers[worker] = true; for (int j = 0; j < dim; j++) { if (parentWorkerByCommittedJob[j] == -1) { - double slack = costMatrix[worker].get(j) - labelByWorker[worker] + double slack = costMatrix[worker][j] - labelByWorker[worker] - labelByJob[j]; if (minSlackValueByJob[j] > slack) { minSlackValueByJob[j] = slack; @@ -274,7 +273,7 @@ protected void greedyMatch() { for (int w = 0; w < dim; w++) { for (int j = 0; j < dim; j++) { if (matchJobByWorker[w] == -1 && matchWorkerByJob[j] == -1 - && costMatrix[w].get(j) - labelByWorker[w] - labelByJob[j] == 0) { + && costMatrix[w][j] - labelByWorker[w] - labelByJob[j] == 0) { match(w, j); } } @@ -293,7 +292,7 @@ protected void initializePhase(int w) { Arrays.fill(parentWorkerByCommittedJob, -1); committedWorkers[w] = true; for (int j = 0; j < dim; j++) { - minSlackValueByJob[j] = costMatrix[w].get(j) - labelByWorker[w] - labelByJob[j]; + minSlackValueByJob[j] = costMatrix[w][j] - labelByWorker[w] - labelByJob[j]; minSlackWorkerByJob[j] = w; } } @@ -316,12 +315,12 @@ protected void reduce() { for (int w = 0; w < dim; w++) { double min = Double.POSITIVE_INFINITY; for (int j = 0; j < dim; j++) { - if (costMatrix[w].get(j) < min) { - min = costMatrix[w].get(j); + if (costMatrix[w][j] < min) { + min = costMatrix[w][j]; } } for (int j = 0; j < dim; j++) { - costMatrix[w].set(j, costMatrix[w].get(j) - min); + costMatrix[w][j] = costMatrix[w][j] - min; } } double[] min = new double[dim]; @@ -330,14 +329,14 @@ protected void reduce() { } for (int w = 0; w < dim; w++) { for (int j = 0; j < dim; j++) { - if (costMatrix[w].get(j) < min[j]) { - min[j] = costMatrix[w].get(j); + if (costMatrix[w][j] < min[j]) { + min[j] = costMatrix[w][j]; } } } for (int w = 0; w < dim; w++) { for (int j = 0; j < dim; j++) { - costMatrix[w].set(j, costMatrix[w].get(j) - min[j]); + costMatrix[w][j] = costMatrix[w][j] - min[j]; } } } @@ -365,7 +364,7 @@ protected void updateLabeling(double slack) { public int[] nextChild() { int currentJobAssigned = matchJobByWorker[0]; // we want to make currentJobAssigned not allowed,meaning we set the size to Infinity - costMatrix[0].set(currentJobAssigned, Integer.MAX_VALUE); + costMatrix[0][currentJobAssigned] = Integer.MAX_VALUE; matchWorkerByJob[currentJobAssigned] = -1; matchJobByWorker[0] = -1; minSlackValueByJob[currentJobAssigned] = Integer.MAX_VALUE; From d2e4d16b9e2e3ebcfc67ac06aa5d68d3ea383790 Mon Sep 17 00:00:00 2001 From: Andreas Marek Date: Wed, 19 Apr 2023 05:04:37 +1000 Subject: [PATCH 3/6] improve lower bound cost for isolated vertices --- .../java/graphql/schema/diffing/DiffImpl.java | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/main/java/graphql/schema/diffing/DiffImpl.java b/src/main/java/graphql/schema/diffing/DiffImpl.java index f6a45f4db..802927bda 100644 --- a/src/main/java/graphql/schema/diffing/DiffImpl.java +++ b/src/main/java/graphql/schema/diffing/DiffImpl.java @@ -250,6 +250,7 @@ private void addChildToQueue(int fixedEditorialCost, } int costForFullMapping = editorialCostForMapping(fixedEditorialCost, fullMapping, completeSourceGraph, completeTargetGraph); + assertTrue(lowerBoundForPartialMapping <= costForFullMapping); if (costForFullMapping < optimalEdit.ged) { updateOptimalEdit(optimalEdit, costForFullMapping, fullMapping); } @@ -343,6 +344,7 @@ private void addSiblingToQueue( } assertTrue(fullMapping.size() == this.completeSourceGraph.size()); int costForFullMapping = editorialCostForMapping(fixedEditorialCost, fullMapping, completeSourceGraph, completeTargetGraph); + assertTrue(sibling.lowerBoundCost <= costForFullMapping); if (costForFullMapping < optimalEdit.ged) { updateOptimalEdit(optimalEdit, costForFullMapping, fullMapping); } @@ -534,27 +536,15 @@ private double calcLowerBoundMappingCostForIsolated(Vertex vertex, SchemaGraph schemaGraph = sourceOrTarget ? completeSourceGraph : completeTargetGraph; Collection adjacentEdges = schemaGraph.getAdjacentEdgesNonCopy(vertex); - int innerEdgesCount = 0; - int labeledEdgesFromAnchoredVertex = 0; - for (Edge edge : adjacentEdges) { - if (!partialMapping.contains(edge.getTo(), sourceOrTarget)) { - innerEdgesCount++; - } else { - if (edge.getLabel() != null) { - labeledEdgesFromAnchoredVertex++; - } - } - } + int labeledEdgesFromAnchoredVertexInverse = 0; Collection adjacentEdgesInverse = schemaGraph.getAdjacentEdgesInverseNonCopy(vertex); for (Edge edge : adjacentEdgesInverse) { if (partialMapping.contains(edge.getFrom(), sourceOrTarget)) { - if (edge.getLabel() != null) { - labeledEdgesFromAnchoredVertex++; - } + labeledEdgesFromAnchoredVertexInverse++; } } - return 1 + innerEdgesCount + labeledEdgesFromAnchoredVertex; + return 1 + adjacentEdges.size() + labeledEdgesFromAnchoredVertexInverse; } From 15f52c0ea61197e287cd57f230b3ae6a03366b31 Mon Sep 17 00:00:00 2001 From: Andreas Marek Date: Wed, 19 Apr 2023 05:08:38 +1000 Subject: [PATCH 4/6] cleanup --- .../java/graphql/schema/diffing/DiffImpl.java | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main/java/graphql/schema/diffing/DiffImpl.java b/src/main/java/graphql/schema/diffing/DiffImpl.java index 802927bda..f816c7a92 100644 --- a/src/main/java/graphql/schema/diffing/DiffImpl.java +++ b/src/main/java/graphql/schema/diffing/DiffImpl.java @@ -207,13 +207,13 @@ private void addChildToQueue(int fixedEditorialCost, double[][] costMatrix = new double[costMatrixSize][costMatrixSize]; - Map deletionCostsCache = new LinkedHashMap<>(); + Map isolatedVerticesCache = new LinkedHashMap<>(); for (int i = level; i < allSources.size(); i++) { Vertex v = allSources.get(i); int j = 0; for (Vertex u : availableTargetVertices) { - double cost = calcLowerBoundMappingCost(v, u, parentPartialMapping, deletionCostsCache); + double cost = calcLowerBoundMappingCost(v, u, parentPartialMapping, isolatedVerticesCache); costMatrixForHungarianAlgo[i - level][j] = cost; costMatrix[i - level][j] = cost; j++; @@ -392,24 +392,24 @@ private double getCostMatrixSum(double[][] costMatrix, int[] assignments) { private double calcLowerBoundMappingCost(Vertex v, Vertex u, Mapping partialMapping, - Map deletionCostsCache) { + Map isolatedVerticesCache) { if (!possibleMappings.mappingPossible(v, u)) { return Integer.MAX_VALUE; } if (u.isOfType(SchemaGraph.ISOLATED)) { - if (deletionCostsCache.containsKey(v)) { - return deletionCostsCache.get(v); + if (isolatedVerticesCache.containsKey(v)) { + return isolatedVerticesCache.get(v); } double result = calcLowerBoundMappingCostForIsolated(v, partialMapping, true); - deletionCostsCache.put(v, result); + isolatedVerticesCache.put(v, result); return result; } if (v.isOfType(SchemaGraph.ISOLATED)) { - if (deletionCostsCache.containsKey(u)) { - return deletionCostsCache.get(u); + if (isolatedVerticesCache.containsKey(u)) { + return isolatedVerticesCache.get(u); } double result = calcLowerBoundMappingCostForIsolated(u, partialMapping, false); - deletionCostsCache.put(u, result); + isolatedVerticesCache.put(u, result); return result; } @@ -535,16 +535,18 @@ private double calcLowerBoundMappingCostForIsolated(Vertex vertex, ) { SchemaGraph schemaGraph = sourceOrTarget ? completeSourceGraph : completeTargetGraph; + // every adjacent edge is inserted/deleted for an isolated vertex Collection adjacentEdges = schemaGraph.getAdjacentEdgesNonCopy(vertex); - int labeledEdgesFromAnchoredVertexInverse = 0; + // for the inverse adjacent edges we only count the anchored ones + int anchoredInverseEdges = 0; Collection adjacentEdgesInverse = schemaGraph.getAdjacentEdgesInverseNonCopy(vertex); for (Edge edge : adjacentEdgesInverse) { if (partialMapping.contains(edge.getFrom(), sourceOrTarget)) { - labeledEdgesFromAnchoredVertexInverse++; + anchoredInverseEdges++; } } - return 1 + adjacentEdges.size() + labeledEdgesFromAnchoredVertexInverse; + return 1 + adjacentEdges.size() + anchoredInverseEdges; } From 8f5e2853713e27e182bc9cbe02d437c120f5e1f0 Mon Sep 17 00:00:00 2001 From: Andreas Marek Date: Wed, 19 Apr 2023 05:19:04 +1000 Subject: [PATCH 5/6] change sorting algo --- .../java/graphql/schema/diffing/SchemaDiffing.java | 14 +++++++++----- .../java/graphql/schema/diffing/SchemaGraph.java | 4 ++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/java/graphql/schema/diffing/SchemaDiffing.java b/src/main/java/graphql/schema/diffing/SchemaDiffing.java index 60e0264bd..11dcdb90f 100644 --- a/src/main/java/graphql/schema/diffing/SchemaDiffing.java +++ b/src/main/java/graphql/schema/diffing/SchemaDiffing.java @@ -71,7 +71,7 @@ private DiffImpl.OptimalEdit diffImpl(SchemaGraph sourceGraph, SchemaGraph targe runningCheck.check(); - sortListBasedOnPossibleMapping(nonMappedSource, possibleMappings); + sortSourceVertices(nonMappedSource, possibleMappings); // the non mapped vertices go to the end List sourceVertices = new ArrayList<>(); @@ -87,12 +87,16 @@ private DiffImpl.OptimalEdit diffImpl(SchemaGraph sourceGraph, SchemaGraph targe return optimalEdit; } - private void sortListBasedOnPossibleMapping(List sourceVertices, PossibleMappingsCalculator.PossibleMappings possibleMappings) { + private void sortSourceVertices(List sourceVertices, PossibleMappingsCalculator.PossibleMappings possibleMappings) { Collections.sort(sourceVertices, (v1, v2) -> { - int v1Count = possibleMappings.possibleMappings.get(v1).size(); - int v2Count = possibleMappings.possibleMappings.get(v2).size(); - return Integer.compare(v1Count, v2Count); +// int v1Count = possibleMappings.possibleMappings.get(v1).size(); +// int v2Count = possibleMappings.possibleMappings.get(v2).size(); +// int result = Integer.compare(v1Count, v2Count); +// if(result == 0) { + return Integer.compare(sourceGraph.adjacentEdgesAndInverseCount(v2), sourceGraph.adjacentEdgesAndInverseCount(v1)); +// } +// return result; }); } diff --git a/src/main/java/graphql/schema/diffing/SchemaGraph.java b/src/main/java/graphql/schema/diffing/SchemaGraph.java index 63f306abc..bd3d55426 100644 --- a/src/main/java/graphql/schema/diffing/SchemaGraph.java +++ b/src/main/java/graphql/schema/diffing/SchemaGraph.java @@ -99,6 +99,10 @@ public Iterable getAdjacentEdgesAndInverseNonCopy(Vertex fromAndTo) { return Iterables.concat(edges, edgesInverse); } + public int adjacentEdgesAndInverseCount(Vertex fromAndTo) { + return edgesByInverseDirection.row(fromAndTo).size() + edgesByDirection.row(fromAndTo).size(); + } + public List getAdjacentVertices(Vertex from) { return getAdjacentVertices(from, x -> true); } From 119999d6906a52e3eb705d37b7a37b488d6ec080 Mon Sep 17 00:00:00 2001 From: Andreas Marek Date: Wed, 19 Apr 2023 08:38:50 +1000 Subject: [PATCH 6/6] fix edit operation analyzer --- .../java/graphql/schema/diffing/DiffImpl.java | 4 +--- .../diffing/ana/EditOperationAnalyzer.java | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/main/java/graphql/schema/diffing/DiffImpl.java b/src/main/java/graphql/schema/diffing/DiffImpl.java index f816c7a92..350ee2b67 100644 --- a/src/main/java/graphql/schema/diffing/DiffImpl.java +++ b/src/main/java/graphql/schema/diffing/DiffImpl.java @@ -146,9 +146,7 @@ OptimalEdit diffImpl(Mapping startMapping, List allSources, List continue; } -// if (count % 1000 == 0) { -// System.out.println(mappingEntry.lowerBoundCost + " vs ged " + optimalEdit.ged + " count " + count); -// } +// System.out.println(mappingEntry.lowerBoundCost + " vs ged " + optimalEdit.ged + " count " + count); if (mappingEntry.level > 0 && !mappingEntry.siblingsFinished) { addSiblingToQueue( diff --git a/src/main/java/graphql/schema/diffing/ana/EditOperationAnalyzer.java b/src/main/java/graphql/schema/diffing/ana/EditOperationAnalyzer.java index 382520b10..b450c8294 100644 --- a/src/main/java/graphql/schema/diffing/ana/EditOperationAnalyzer.java +++ b/src/main/java/graphql/schema/diffing/ana/EditOperationAnalyzer.java @@ -660,6 +660,10 @@ private void handleInputFieldChange(EditOperation editOperation) { return; } + if (isInputObjectAdded(inputObject.getName())) { + return; + } + getInputObjectModification(inputObject.getName()).getDetails().add(new InputObjectFieldRename(oldName, newName)); } @@ -786,11 +790,21 @@ private void fieldChanged(EditOperation editOperation) { if (fieldsContainerForField.isOfType(SchemaGraph.OBJECT)) { Vertex object = fieldsContainerForField; + + if (isObjectAdded(object.getName())) { + return; + } + ObjectModification objectModification = getObjectModification(object.getName()); objectModification.getDetails().add(new ObjectFieldRename(oldName, newName)); } else { assertTrue(fieldsContainerForField.isOfType(SchemaGraph.INTERFACE)); Vertex interfaze = fieldsContainerForField; + + if (isInterfaceAdded(interfaze.getName())) { + return; + } + InterfaceModification interfaceModification = getInterfaceModification(interfaze.getName()); interfaceModification.getDetails().add(new InterfaceFieldRename(oldName, newName)); } @@ -1159,6 +1173,11 @@ private void inputFieldTypeOrDefaultValueChanged(EditOperation editOperation) { Edge targetEdge = editOperation.getTargetEdge(); Vertex inputField = targetEdge.getFrom(); Vertex inputObject = newSchemaGraph.getInputObjectForInputField(inputField); + + if (isInputObjectAdded(inputObject.getName())) { + return; + } + String oldDefaultValue = getDefaultValueFromEdgeLabel(editOperation.getSourceEdge()); String newDefaultValue = getDefaultValueFromEdgeLabel(editOperation.getTargetEdge()); if (!oldDefaultValue.equals(newDefaultValue)) {