package com.company.simulated_annealing; import java.util.Random; public class SimulatedAnnealing { private Random randomGenerator; // the actual state (state = x) private double currentCoordinateX; // this is the next state (neighbor) private double nextCoordinateX; private double bestCoordinateX; public SimulatedAnnealing() { this.randomGenerator = new Random(); } public void findOptimum() { double temp = Constants.MAX_TEMPERATURE; while(temp > Constants.MIN_TEMPERATURE) { // generate the neigboring state at random nextCoordinateX = getRandomX(); // calculate the energy values double currentEnergy = getEnergy(currentCoordinateX); double newEnergy = getEnergy(nextCoordinateX); double g = acceptanceProbability(currentEnergy, newEnergy, temp); double r = Math.random(); if(g > r){ currentCoordinateX = nextCoordinateX; System.out.println("U: " + currentEnergy + ", V: " + newEnergy + ", T: " + temp + "g(u,v,t) = " + g + " > r=" + r + " Accept v" ); } else{ System.out.println("U: " + currentEnergy + ", V: " + newEnergy + ", T: " + temp + "g(u,v,t) = " + g + " <= r=" + r + " Denied v" ); } if(f(currentCoordinateX) > f(bestCoordinateX)) bestCoordinateX = currentCoordinateX; temp = temp * (1-Constants.COOLING_RATE); } System.out.println("Global extremum is: x="+bestCoordinateX + " f(x) = " + f(bestCoordinateX)); } // return a double value in the range [-2,2] private double getRandomX() { return randomGenerator.nextDouble()*(Constants.MAX_COORDINATE_X - Constants.MIN_COORDINATE_X) + Constants.MIN_COORDINATE_X; } private double getEnergy(double x) { return f(x); } private double f(double x) { return (x-0.3)*(x-0.3)*(x-0.3)-5*x+x*x-2; } // this is the Metropolis-function acceptance Probability private double acceptanceProbability(double actualEnergy, double newEnergy, double temp) { // if the new state is better then we take that new state if(newEnergy > actualEnergy) return 1.0; // if the new solution is worse, calculate an acceptance probability // T is small: we accept worse solutions with lower probability !!! return Math.exp((actualEnergy - newEnergy) / temp); } }