diff --git a/core-java/pom.xml b/core-java/pom.xml
index 0c14da2245..f5a800d508 100644
--- a/core-java/pom.xml
+++ b/core-java/pom.xml
@@ -85,6 +85,12 @@
log4j-over-slf4j
${org.slf4j.version}
+
+ org.projectlombok
+ lombok
+ 1.16.12
+ provided
+
diff --git a/core-java/src/main/java/com/baeldung/algorithms/City.java b/core-java/src/main/java/com/baeldung/algorithms/City.java
new file mode 100644
index 0000000000..1a96dc759d
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/algorithms/City.java
@@ -0,0 +1,22 @@
+package com.baeldung.algorithms;
+
+import lombok.Data;
+
+@Data
+public class City {
+
+ private int x;
+ private int y;
+
+ public City() {
+ this.x = (int) (Math.random() * 500);
+ this.y = (int) (Math.random() * 500);
+ }
+
+ public double distanceToCity(City city) {
+ int x = Math.abs(getX() - city.getX());
+ int y = Math.abs(getY() - city.getY());
+ return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/algorithms/SimulatedAnnealing.java b/core-java/src/main/java/com/baeldung/algorithms/SimulatedAnnealing.java
new file mode 100644
index 0000000000..b62e861399
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/algorithms/SimulatedAnnealing.java
@@ -0,0 +1,41 @@
+package com.baeldung.algorithms;
+
+public class SimulatedAnnealing {
+
+ private static Travel travel = new Travel(10);
+
+ public static double simulateAnnealing(double startingTemperature, int numberOfIterations, double coolingRate) {
+ System.out.println("Starting SA with temperature: " + startingTemperature + ", # of iterations: "
+ + numberOfIterations + " and colling rate: " + coolingRate);
+ double t = startingTemperature;
+ travel.generateInitialTravel();
+ double bestDistance = travel.getDistance();
+ System.out.println("Initial distance of travel: " + bestDistance);
+ Travel bestSolution = travel;
+ Travel currentSolution = bestSolution;
+
+ for (int i = 0; i < numberOfIterations; i++) {
+ if (t > 0.1) {
+ currentSolution.swapCities();
+ double currentDistance = currentSolution.getDistance();
+ if (currentDistance == 0)
+ continue;
+ if (currentDistance < bestDistance) {
+ bestDistance = currentDistance;
+ } else if (Math.exp((currentDistance - bestDistance) / t) < Math.random()) {
+ currentSolution.revertSwap();
+ }
+ t *= coolingRate;
+ }
+ if (i % 100 == 0) {
+ System.out.println("Iteration #" + i);
+ }
+ }
+ return bestDistance;
+ }
+
+ public static void main(String[] args) {
+ System.out.println("Optimized distance for travel: " + simulateAnnealing(10, 10000, 0.9));
+ }
+
+}
diff --git a/core-java/src/main/java/com/baeldung/algorithms/Travel.java b/core-java/src/main/java/com/baeldung/algorithms/Travel.java
new file mode 100644
index 0000000000..9921b2516e
--- /dev/null
+++ b/core-java/src/main/java/com/baeldung/algorithms/Travel.java
@@ -0,0 +1,60 @@
+package com.baeldung.algorithms;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+import lombok.Data;
+
+@Data
+public class Travel {
+
+ private ArrayList travel = new ArrayList<>();
+ private ArrayList previousTravel = new ArrayList<>();
+
+ public Travel(int numberOfCities) {
+ for (int i = 0; i < numberOfCities; i++) {
+ travel.add(new City());
+ }
+ }
+
+ public void generateInitialTravel() {
+ if (travel.isEmpty())
+ new Travel(10);
+ Collections.shuffle(travel);
+ }
+
+ public void swapCities() {
+ int a = generateRandomIndex();
+ int b = generateRandomIndex();
+ previousTravel = travel;
+ travel.set(a, travel.get(b));
+ }
+
+ public void revertSwap() {
+ travel = previousTravel;
+ }
+
+ private int generateRandomIndex() {
+ return (int) (Math.random() * travel.size());
+ }
+
+ public City getCity(int index) {
+ return travel.get(index);
+ }
+
+ public int getDistance() {
+ int distance = 0;
+ for (int index = 0; index < travel.size(); index++) {
+ City starting = getCity(index);
+ City destination;
+ if (index + 1 < travel.size()) {
+ destination = getCity(index + 1);
+ } else {
+ destination = getCity(0);
+ }
+ distance += starting.distanceToCity(destination);
+ }
+ return distance;
+ }
+
+}