From fb71a3b21c8c70e8470ef16442384ca78c84c696 Mon Sep 17 00:00:00 2001 From: bibenga <{ID}+{username}@users.noreply.github.com> Date: Tue, 10 Mar 2026 11:43:52 +0000 Subject: [PATCH 1/7] add eclipse-collections --- pom.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pom.xml b/pom.xml index 9bef27f..d19f134 100644 --- a/pom.xml +++ b/pom.xml @@ -36,6 +36,19 @@ junit-jupiter test + + + org.eclipse.collections + eclipse-collections-api + 13.0.0 + test + + + org.eclipse.collections + eclipse-collections + 13.0.0 + test + From 416aefbd2b89e71cf6c722896ce7526a4157702b Mon Sep 17 00:00:00 2001 From: bibenga <{ID}+{username}@users.noreply.github.com> Date: Wed, 11 Mar 2026 10:28:22 +0000 Subject: [PATCH 2/7] simplify --- src/test/java/com/github/bibenga/alns/tsp/Tsp.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/github/bibenga/alns/tsp/Tsp.java b/src/test/java/com/github/bibenga/alns/tsp/Tsp.java index 67372ae..65e1895 100644 --- a/src/test/java/com/github/bibenga/alns/tsp/Tsp.java +++ b/src/test/java/com/github/bibenga/alns/tsp/Tsp.java @@ -7,9 +7,11 @@ import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Random; +import java.util.Set; import java.util.random.RandomGenerator; import java.util.stream.IntStream; @@ -281,9 +283,9 @@ public static State worstRemoval(State state, RandomGenerator rng) { static State greedyRepair(State state, RandomGenerator rng) { TspState cur = (TspState) state; - boolean[] visited = new boolean[cur.nodes.length]; + Set visited = new HashSet<>(); for (int v : cur.edges.values()) - visited[v] = true; + visited.add(v); int[] idx = IntStream.range(0, cur.nodes.length).toArray(); shuffleArray(idx, rng); @@ -305,7 +307,7 @@ static State greedyRepair(State state, RandomGenerator rng) { final int finalNode = node; List unvisited = new ArrayList<>(); for (int other : cur.nodes) { - if (other != finalNode && !visited[other] && !wouldFormSubcycle(finalNode, other, cur)) + if (other != finalNode && !visited.contains(other) && !wouldFormSubcycle(finalNode, other, cur)) unvisited.add(other); } if (unvisited.isEmpty()) @@ -316,7 +318,7 @@ static State greedyRepair(State state, RandomGenerator rng) { .orElseThrow(); cur.edges.put(node, nearest); - visited[nearest] = true; + visited.add(nearest); } return cur; } From 95885f002a4200ab893badce6486f76daba41e05 Mon Sep 17 00:00:00 2001 From: bibenga <{ID}+{username}@users.noreply.github.com> Date: Wed, 11 Mar 2026 10:29:42 +0000 Subject: [PATCH 3/7] cleanup --- src/test/java/com/github/bibenga/alns/tsp/Tsp.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/com/github/bibenga/alns/tsp/Tsp.java b/src/test/java/com/github/bibenga/alns/tsp/Tsp.java index 65e1895..b08c14c 100644 --- a/src/test/java/com/github/bibenga/alns/tsp/Tsp.java +++ b/src/test/java/com/github/bibenga/alns/tsp/Tsp.java @@ -304,17 +304,17 @@ static State greedyRepair(State state, RandomGenerator rng) { if (node == -1) throw new RuntimeException("node not found"); - final int finalNode = node; + final int fNode = node; List unvisited = new ArrayList<>(); for (int other : cur.nodes) { - if (other != finalNode && !visited.contains(other) && !wouldFormSubcycle(finalNode, other, cur)) + if (other != fNode && !visited.contains(other) && !wouldFormSubcycle(fNode, other, cur)) unvisited.add(other); } if (unvisited.isEmpty()) throw new RuntimeException("unvisited is empty"); int nearest = unvisited.stream() - .min(Comparator.comparingDouble(a -> cur.dists[finalNode][a])) + .min(Comparator.comparingDouble(a -> cur.dists[fNode][a])) .orElseThrow(); cur.edges.put(node, nearest); From 31010fda93343c4e0c6361fe2469833f2cab217b Mon Sep 17 00:00:00 2001 From: bibenga <{ID}+{username}@users.noreply.github.com> Date: Wed, 11 Mar 2026 10:32:47 +0000 Subject: [PATCH 4/7] simplify --- src/test/java/com/github/bibenga/alns/tsp/Tsp.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/java/com/github/bibenga/alns/tsp/Tsp.java b/src/test/java/com/github/bibenga/alns/tsp/Tsp.java index b08c14c..be5c86c 100644 --- a/src/test/java/com/github/bibenga/alns/tsp/Tsp.java +++ b/src/test/java/com/github/bibenga/alns/tsp/Tsp.java @@ -283,9 +283,7 @@ public static State worstRemoval(State state, RandomGenerator rng) { static State greedyRepair(State state, RandomGenerator rng) { TspState cur = (TspState) state; - Set visited = new HashSet<>(); - for (int v : cur.edges.values()) - visited.add(v); + Set visited = new HashSet<>(cur.edges.values()); int[] idx = IntStream.range(0, cur.nodes.length).toArray(); shuffleArray(idx, rng); From 9cbd1ffdb127861f92a82f402628f8987f016391 Mon Sep 17 00:00:00 2001 From: bibenga <{ID}+{username}@users.noreply.github.com> Date: Wed, 11 Mar 2026 10:37:44 +0000 Subject: [PATCH 5/7] use native collections --- .../java/com/github/bibenga/alns/tsp/Tsp.java | 20 +++++++++++-------- .../com/github/bibenga/alns/tsp/TspState.java | 9 ++++++--- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/test/java/com/github/bibenga/alns/tsp/Tsp.java b/src/test/java/com/github/bibenga/alns/tsp/Tsp.java index be5c86c..0987b92 100644 --- a/src/test/java/com/github/bibenga/alns/tsp/Tsp.java +++ b/src/test/java/com/github/bibenga/alns/tsp/Tsp.java @@ -6,15 +6,15 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Random; -import java.util.Set; import java.util.random.RandomGenerator; import java.util.stream.IntStream; +import org.eclipse.collections.impl.map.mutable.primitive.IntIntHashMap; +import org.eclipse.collections.impl.set.mutable.primitive.IntHashSet; + import com.github.bibenga.alns.ALNS; import com.github.bibenga.alns.Operator; import com.github.bibenga.alns.State; @@ -32,7 +32,7 @@ public static void main(String[] args) throws Exception { Random rng = new Random(42); - TspState initSol = new TspState(nodes, new HashMap<>(), dists); + TspState initSol = new TspState(nodes, new IntIntHashMap(), dists); initSol = (TspState) greedyRepair(initSol, rng); System.out.println("optimal solution: 564"); @@ -246,7 +246,7 @@ public static State randomRemoval(State state, RandomGenerator rng) { int removed = 0; while (removed < toRemove) { int node = destroyed.nodes[rng.nextInt(destroyed.nodes.length)]; - if (destroyed.edges.remove(node) != null) { + if (destroyed.edges.removeKeyIfAbsent(node, -1) != -1) { removed++; } } @@ -283,7 +283,11 @@ public static State worstRemoval(State state, RandomGenerator rng) { static State greedyRepair(State state, RandomGenerator rng) { TspState cur = (TspState) state; - Set visited = new HashSet<>(cur.edges.values()); + var visited = new IntHashSet(); + for (var it = cur.edges.values().intIterator(); it.hasNext();) { + var v = it.next(); + visited.add(v); + } int[] idx = IntStream.range(0, cur.nodes.length).toArray(); shuffleArray(idx, rng); @@ -332,8 +336,8 @@ static void shuffleArray(int[] arr, RandomGenerator rnd) { private static boolean wouldFormSubcycle(int fromNode, int toNode, TspState state) { for (int step = 1; step < state.nodes.length; step++) { - Integer next = state.edges.get(toNode); - if (next == null) + int next = state.edges.getIfAbsent(toNode, -1); + if (next == -1) return false; toNode = next; if (fromNode == toNode && step != state.nodes.length - 1) diff --git a/src/test/java/com/github/bibenga/alns/tsp/TspState.java b/src/test/java/com/github/bibenga/alns/tsp/TspState.java index a1f7e4b..0a91831 100644 --- a/src/test/java/com/github/bibenga/alns/tsp/TspState.java +++ b/src/test/java/com/github/bibenga/alns/tsp/TspState.java @@ -3,15 +3,18 @@ import java.util.HashMap; import java.util.Map; +import org.eclipse.collections.api.map.primitive.MutableIntIntMap; +import org.eclipse.collections.impl.map.mutable.primitive.IntIntHashMap; + import com.github.bibenga.alns.State; class TspState implements State { final int[] nodes; - final Map edges; + final MutableIntIntMap edges; final double[][] dists; private double objective = Double.NaN; - TspState(int[] nodes, Map edges, double[][] dists) { + TspState(int[] nodes, MutableIntIntMap edges, double[][] dists) { this.nodes = nodes; this.edges = edges; this.dists = dists; @@ -19,7 +22,7 @@ class TspState implements State { @Override public TspState clone() { - return new TspState(nodes, new HashMap<>(edges), dists); + return new TspState(nodes, new IntIntHashMap(edges), dists); } @Override From 09aa1ac71121e543fdfe064c8d2ba3934832a79d Mon Sep 17 00:00:00 2001 From: bibenga <{ID}+{username}@users.noreply.github.com> Date: Wed, 11 Mar 2026 10:37:53 +0000 Subject: [PATCH 6/7] cleanup --- src/test/java/com/github/bibenga/alns/tsp/TspState.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/test/java/com/github/bibenga/alns/tsp/TspState.java b/src/test/java/com/github/bibenga/alns/tsp/TspState.java index 0a91831..b7b5b55 100644 --- a/src/test/java/com/github/bibenga/alns/tsp/TspState.java +++ b/src/test/java/com/github/bibenga/alns/tsp/TspState.java @@ -1,8 +1,5 @@ package com.github.bibenga.alns.tsp; -import java.util.HashMap; -import java.util.Map; - import org.eclipse.collections.api.map.primitive.MutableIntIntMap; import org.eclipse.collections.impl.map.mutable.primitive.IntIntHashMap; From e07f3e7d87fb81bb8e4e31998b26849eb8c25c61 Mon Sep 17 00:00:00 2001 From: bibenga <{ID}+{username}@users.noreply.github.com> Date: Fri, 13 Mar 2026 20:56:49 +0000 Subject: [PATCH 7/7] fix --- src/test/java/com/github/bibenga/alns/tsp/Tsp.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/github/bibenga/alns/tsp/Tsp.java b/src/test/java/com/github/bibenga/alns/tsp/Tsp.java index c80ae7d..568cb11 100644 --- a/src/test/java/com/github/bibenga/alns/tsp/Tsp.java +++ b/src/test/java/com/github/bibenga/alns/tsp/Tsp.java @@ -7,11 +7,11 @@ import java.util.Arrays; import java.util.Comparator; import java.util.List; -import java.util.Map; import java.util.Random; import java.util.random.RandomGenerator; import java.util.stream.IntStream; +import org.eclipse.collections.api.map.primitive.IntIntMap; import org.eclipse.collections.impl.map.mutable.primitive.IntIntHashMap; import org.eclipse.collections.impl.set.mutable.primitive.IntHashSet; @@ -350,7 +350,7 @@ private static boolean wouldFormSubcycle(int fromNode, int toNode, TspState stat return false; } - static void writeDotFile(String filename, double[][] coords, Map edges) throws IOException { + static void writeDotFile(String filename, double[][] coords, IntIntMap edges) throws IOException { final double k = 3; double minX = Double.MAX_VALUE, minY = Double.MAX_VALUE; double maxX = -Double.MAX_VALUE, maxY = -Double.MAX_VALUE; @@ -371,8 +371,9 @@ static void writeDotFile(String filename, double[][] coords, Map e : edges.entrySet()) - w.printf(" %d -> %d [arrowsize=4, penwidth=3];%n", e.getKey(), e.getValue()); + edges.forEachKeyValue((key, value) -> { + w.printf(" %d -> %d [arrowsize=4, penwidth=3];%n", key, value); + }); w.println("}"); } }