Created
March 8, 2022 07:13
-
-
Save VizGhar/5eeacfd17250cdeb3adc688b3ad7ba7c to your computer and use it in GitHub Desktop.
"Hello World!" Simplistic Tabu Search Algorithm. This sample is meant to be readable and is not efficient at all, so !!! Do not use in production !!!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import kotlin.math.abs | |
const val target = "Hello World!" | |
const val possibilities = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789 .,!?" | |
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("") | |
val tabu = mutableSetOf(current) | |
fun String.neighbors() : Set<String> { | |
val result = mutableSetOf(this) | |
for (i in this.indices) { | |
val posIndex = possibilities.indexOf(current[i]) | |
var testPos1 = posIndex + 1 | |
var testPos2 = posIndex - 1 | |
if (testPos2 < 0) testPos2 = possibilities.length - 1 | |
if (testPos1 >= possibilities.length) testPos1 = 0 | |
val new1 = current.replaceRange(i, i + 1, possibilities[testPos2].toString()) | |
val new2 = current.replaceRange(i, i + 1, possibilities[testPos1].toString()) | |
result += new1 | |
result += new2 | |
} | |
return result | |
} | |
fun main() { | |
val startAt = System.currentTimeMillis() | |
var iteration = 0 | |
while(current.fitness != 0) { | |
if (iteration % 100 == 0) { | |
println("\"$current\" score ${current.fitness} found in $iteration iterations") | |
} | |
val best = current.neighbors() | |
.filter { it !in tabu } | |
.minByOrNull { it.fitness - current.fitness } ?: break | |
tabu.add(best) | |
current = best | |
iteration++ | |
} | |
println("Solution \"$current\" found in $iteration iterations and ${System.currentTimeMillis() - startAt}ms") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment