All Downloads are FREE. Search and download functionalities are using the official Maven repository.

mathFunctions.FunctionEvaluator.kt Maven / Gradle / Ivy

There is a newer version: 0.3.0
Show newest version
package mathFunctions

import evodef.*
import kotlin.AssertionError
import kotlin.random.Random

class FunctionEvaluator(val f: NTBEAFunction, val searchSpace: SearchSpace) : SolutionEvaluator {

    private val rnd = Random(System.currentTimeMillis())

    var nEvals = 0

    override fun searchSpace() = searchSpace

    override fun reset() {
        nEvals = 0
    }

    override fun nEvals() = nEvals
    override fun evaluate(settings: IntArray): Double {
        return evaluate(searchSpace.sampleAt(settings))
    }

    override fun evaluate(settings: DoubleArray): Double {
        nEvals++
        return if (rnd.nextDouble() < f.functionValue(settings)) 1.0 else 0.0
    }
}

fun main(args: Array) {
    val f = when (args[0]) {
        "Hartmann3" -> Hartmann3
        "Hartmann6" -> Hartmann6
        "Branin" -> Branin
        "GoldsteinPrice" -> GoldsteinPrice
        else -> throw AssertionError("Unknown function ${args[0]}")
    }
    FunctionExhaustiveResult(f, FunctionSearchSpace(f.dimension, args[1].toInt())).calculate()
}

class FunctionExhaustiveResult(val f: NTBEAFunction, val searchSpace: FunctionSearchSpace) {

    // We run through every possible setting in the searchSpace, and run maxGames, logging the average result
    val stateSpaceSize = (0 until searchSpace.nDims()).fold(1, { acc, i -> acc * searchSpace.nValues(i) })

    val allRanges = (0 until searchSpace.nDims()).map { 0 until searchSpace.nValues(it) }

    fun addDimension(start: List>, next: IntRange): List> {
        return start.flatMap { list -> next.map { list + it } }
    }

    val allOptions = allRanges.fold(listOf(emptyList()), { acc, r -> addDimension(acc, r) })

    fun calculate() {
        val optionScores = allOptions.map {
            val params = it.toIntArray()
            //   StatsCollator.clear()
            val perfectScore = f.functionValue(searchSpace.valueAt(params))
            println("${params.joinToString()} has mean score ${String.format("%.3g", perfectScore)}")
            //   println(StatsCollator.summaryString())
            params to perfectScore
        }

        val numberPositive = optionScores.filter { it.second > 0.0 }.count().toDouble()
        val sortedScores = optionScores.sortedBy { it.second }.reversed().take(50)
        println("Best scores are : \n" + sortedScores.joinToString("\n") { String.format("\t%.3g at %s", it.second, it.first.joinToString()) })
        println("A total of ${String.format("%.1f%% are above zero", 100.0 * numberPositive / optionScores.size)}")
    }
}

class FunctionSearchSpace(val dimensions: Int, val valuesPerDimension: Int) : SearchSpace {

    val increment = 1.0 / valuesPerDimension
    override fun nDims(): Int {
        return dimensions
    }

    override fun nValues(i: Int): Int {
        return valuesPerDimension
    }

    override fun name(i: Int): String {
        return ""
    }

    override fun value(d: Int, i: Int): Double {
        return i * increment
    }

    override fun sampleAt(indices: IntArray): DoubleArray {
        return indices.withIndex().map { value(it.index, it.value) }.toDoubleArray()
    }

    override fun valueAt(indices: IntArray): DoubleArray {
        return sampleAt(indices)
    }

}

class GaussianSearchSpace(val dimensions: Int, val valuesPerDimension: IntArray, val minMus: DoubleArray, val maxMus: DoubleArray, val minSigs: DoubleArray, val maxSigs: DoubleArray) : SearchSpace {

    var muSig: Array>

    init {
        // Build the search space
        muSig = Array(dimensions * 2) { i ->
            val nIncrements = valuesPerDimension[i]
            if (i >= dimensions) {
                val sigIdx = i-dimensions
                val minSig = minSigs[sigIdx]
                val maxSig = maxSigs[sigIdx]
                val sigInc = (maxSig - minSig) / nIncrements

                Array(valuesPerDimension[i]) { j ->
                    minSig + sigInc * j
                }
            } else {
                val minMu = minMus[i]
                val maxMu = maxMus[i]
                val muInc = (maxMu - minMu) / nIncrements
                Array(valuesPerDimension[i]) { j ->
                    minMu + muInc * j
                }
            }
        }
    }

    override fun nDims(): Int {
        return dimensions * 2
    }

    override fun nValues(i: Int): Int {
        return valuesPerDimension[i];
    }

    override fun name(i: Int): String {
        return ""
    }

    override fun value(d: Int, i: Int): Any {
        return muSig[d][i]
    }

    fun sample(idx: IntArray): DoubleArray {

        return DoubleArray(dimensions) { d ->
            val so = d + dimensions
            val mu = muSig[d][idx[d]]
            val sig = muSig[so][idx[so]]

            java.util.Random().nextGaussian() * sig + mu
        }
    }

    override fun sampleAt(indices: IntArray): DoubleArray {
        return sample(indices)
    }

    override fun valueAt(indices: IntArray): DoubleArray {
        return DoubleArray(dimensions) { d ->
            muSig[d][indices[d]]
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy