evodef.SearchSpace.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of NTBEA Show documentation
Show all versions of NTBEA Show documentation
Parameter optimisation with the N-Tuple Bandit Evolutionary Algorithm
package evodef
import java.io.FileReader
import java.lang.AssertionError
import kotlin.reflect.KClass
/**
* Created by sml on 16/08/2016.
*
* This models a search space where there is a fixed number of dimensions
* but each dimension may have a different cardinality (i.e. a different number of possible values)
*
*/
interface SearchSpace {
// number of dimensions
fun nDims(): Int
// number of possible values in the ith dimension
fun nValues(i: Int): Int
fun name(i: Int): String
fun value(d: Int, i: Int): Any {
return 0.00
}
fun sampleAt(indices: IntArray): DoubleArray {
return doubleArrayOf(0.0)
}
fun valueAt(indices: IntArray): DoubleArray {
return doubleArrayOf(0.0)
}
}
private fun setupSearchDimensions(fileName: String): List {
val allDimensions = if (fileName != "") FileReader(fileName).readLines() else emptyList()
return allDimensions.filter { it.contains(",") } // this filters out any dimension with only one entry
}
abstract class AgentSearchSpace(val searchDimensions: List) : SearchSpace {
constructor(fileName: String) : this(setupSearchDimensions(fileName))
// val searchDimensions: List = setupSearchDimensions(fileName)
val searchKeys: List = searchDimensions.map { it.split("=").first() }
val searchTypes: List> = searchKeys.map {
types[it] ?: throw AssertionError("Unknown search variable $it")
}
val searchValues: List> = searchDimensions.zip(searchTypes)
.map { (allV, cl) ->
allV.split("=")[1] // get the stuff after the colon, which should be values to be searched
.split(",")
.map(String::trim).map {
when (cl) {
Int::class, Int::class.javaObjectType, Int::class.javaPrimitiveType -> it.toInt()
Double::class, Double::class.javaObjectType, Double::class.javaPrimitiveType -> it.toDouble()
Boolean::class.java, Boolean::class.javaObjectType, Boolean::class.javaPrimitiveType -> it.toBoolean()
String::class.java, String::class.javaObjectType -> it
else -> throw AssertionError("Currently unsupported class $cl.")
}
}
}
abstract val types: Map>
fun convertSettings(settings: IntArray): DoubleArray {
return settings.zip(searchValues).map { (i, values) ->
val v = values[i]
when (v) {
is Int -> v.toDouble()
is Double -> values[i]
is Boolean -> if (v) 1.0 else 0.0
is String -> i.toDouble() // if a String, then we return the index of this
else -> settings[i].toDouble() // if not numeric, default to the category
} as Double
}.toDoubleArray()
}
fun settingsToMap(settings: DoubleArray): Map {
return settings.withIndex().map { (i, v) ->
searchKeys[i] to when (searchTypes[i]) {
Int::class, Int::class.javaObjectType, Int::class.javaPrimitiveType -> (v + 0.5).toInt()
Double::class, Double::class.javaObjectType, Double::class.javaPrimitiveType -> v
Boolean::class.java, Boolean::class.javaObjectType, Boolean::class.javaPrimitiveType -> v > 0.5
String::class.java, String::class.javaObjectType -> searchValues[i][(v + 0.5).toInt()]
else -> throw AssertionError("Unsupported class ${searchTypes[i]}")
}
}.toMap()
}
abstract fun getAgent(settings: DoubleArray): T
override fun nValues(i: Int) = searchValues[i].size
override fun nDims() = searchValues.size
override fun name(i: Int) = searchKeys[i]
override fun value(d: Int, i: Int) = searchValues[d][i]
}