diff --git a/pom.xml b/pom.xml index 0765296..0cba845 100644 --- a/pom.xml +++ b/pom.xml @@ -59,6 +59,19 @@ junit-jupiter test + + + org.eclipse.collections + eclipse-collections-api + 13.0.0 + test + + + org.eclipse.collections + eclipse-collections + 13.0.0 + test + 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 9840741..568cb11 100644 --- a/src/test/java/com/github/bibenga/alns/tsp/Tsp.java +++ b/src/test/java/com/github/bibenga/alns/tsp/Tsp.java @@ -6,13 +6,15 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; -import java.util.HashMap; 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; + import com.github.bibenga.alns.ALNS; import com.github.bibenga.alns.State; import com.github.bibenga.alns.accept.HillClimbing; @@ -29,7 +31,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"); @@ -248,7 +250,7 @@ private 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++; } } @@ -285,9 +287,11 @@ private static State worstRemoval(State state, RandomGenerator rng) { private static State greedyRepair(State state, RandomGenerator rng) { TspState cur = (TspState) state; - boolean[] visited = new boolean[cur.nodes.length]; - for (int v : cur.edges.values()) - visited[v] = true; + 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); @@ -306,21 +310,21 @@ private 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[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); - visited[nearest] = true; + visited.add(nearest); } return cur; } @@ -336,8 +340,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) @@ -346,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; @@ -367,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("}"); } } 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..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,17 +1,17 @@ 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; 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 +19,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