Skip to content

Instantly share code, notes, and snippets.

@VizGhar
Last active March 9, 2022 10:28
Show Gist options
  • Save VizGhar/c10be05a269ae14a9a1a47b624ae7d76 to your computer and use it in GitHub Desktop.
Save VizGhar/c10be05a269ae14a9a1a47b624ae7d76 to your computer and use it in GitHub Desktop.
"Hello World!" Simplistic Simulated Annealing Algorithm.This sample is meant to be readable and is not efficient at all, so!!! Do not use in production !!!
import kotlin.math.abs
import kotlin.math.pow
import kotlin.random.Random
const val target = "Hello World!"
const val possibilities = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789 .,!?"
val random = Random(System.currentTimeMillis())
val String.fitness: Int get() = // lower fitness better (for this case) fitness of 0 = solution
indices.sumOf { index ->
val indexFirst = possibilities.indexOf(target[index])
val indexSecond = possibilities.indexOf(this[index])
val high = maxOf(indexFirst, indexSecond)
val low = minOf(indexFirst, indexSecond)
if ((high - low) > possibilities.length / 2) {
abs(high - possibilities.length - low)
} else {
high - low
}
}
var current = (target.indices).map { possibilities.random() }.joinToString("")
fun String.neighbor() : String {
val pos = random.nextInt(this.length)
val sign = if (random.nextBoolean()) 1 else -1
val result = (possibilities.indexOf(this[pos]) + sign * 1) % possibilities.length
val character = possibilities[if (result < 0) result + possibilities.length else result]
return this.substring(0, pos) + character + this.substring(pos + 1)
}
fun accept(current: String, neighbor: String, temperature: Double) : Double {
return Math.E.pow(- ((neighbor.fitness - current.fitness)/temperature))
}
fun main() {
val startAt = System.currentTimeMillis()
for (i in 0 until 10000) {
if (i % 100 == 0) {
println("Solution \"$current\" score ${current.fitness} found in $i iterations")
}
val temperature = 100.0 / (i + 100)
val neighbor = current.neighbor()
val diff = neighbor.fitness - current.fitness
if (diff < 0 || random.nextDouble() < accept(current, neighbor, temperature)) {
current = neighbor
}
if (current.fitness == 0) {
println("Solution \"$current\" found in $i iterations and ${System.currentTimeMillis() - startAt}ms")
return
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment