Я реализовал алгоритм BAT в Scala (меня интересует стиль функционального программирования). В алгоритме BAT используются следующие шаги:
Параметры BATАлгоритм:
Мой код работает нормально, без ошибок, но еговывод не желателен, так как нет изменений в положении BAT после указанной итерации.Мне интересно, где что-то не так в коде.Мой код ниже.Я также хочу удалить цикл while, чтобы код стал чисто функциональным по стилю.
import breeze.linalg.{DenseVector, sum}
import scala.util.Random
object BATalgo {
def Sphere(list: DenseVector[Double]) : Double ={
val power = list.map(math.pow(_, 2))
sum(power)
}
def main(args: Array[String]): Unit = {
println("***BAT for function optimization***")
println("***Enter values for following arguments***")
println("Enter Number of artificial bat")
val N = 5//scala.io.StdIn.readInt();
print("Enter Lower Bound = ")
var MinVal = 1//scala.io.StdIn.readDouble();
print("Enter Upper Bound = ")
var MaxVal = 10//scala.io.StdIn.readDouble();
print("Enter Minimum Frequency Fmin ")
val Fmin = 0//scala.io.StdIn.readDouble();
print("Enter Maximum Frequency Fmax ")
val Fmax = 1//scala.io.StdIn.readDouble();
print("Number of Dimensions(d) = ")
val d = 4//scala.io.StdIn.readInt(); //Dimensions ; Number of unknown Decision variables
print("Enter Maximum Number of Iteration ")
val MaxIt = 15//scala.io.StdIn.readDouble();
val InitialPulseRate = 0.1
val alpha = 0.95
val gyma = 0.95
val random = new Random()
val Bandwidth = 0.001//random.nextDouble()*(1-(-1))+(-1)
var Fx = math.random
var GlobalBest_Fitness = Double.PositiveInfinity
var GlobalBest_Position = DenseVector.fill(d)(math.random)
var bat = DenseVector.fill(N)(new BAT12(d , MinVal , MaxVal ))
println()
bat.foreach{x => x.BestPosition = x.position;x.fitness = Sphere(x.position) ; x.BestFitness = x.fitness}
bat.foreach(x =>
if(x.BestFitness < GlobalBest_Fitness)
{
GlobalBest_Fitness =x.BestFitness ;GlobalBest_Position = x.BestPosition
})
println("Global Best Pos "+GlobalBest_Position)
var itr =1
while (itr <= MaxIt)
{
var sum =0.0
bat.foreach(x => println(x.position , x.fitness))
println()
bat.foreach{ j=>
j.frequency = Fmin +(Fmax - Fmin) * math.random
j.velocity = j.velocity + (j.position - GlobalBest_Position) * j.frequency
j.position = j.position + j.velocity
sum += j.LoudnessRate
if(math.random > j.PulseRate ){
j.position = j.BestPosition + (Bandwidth * sum / N) //sum/d is mean of Loudness , where N is number of BAT's
}
var NewFitness = Sphere(j.position) //Compute fitness of each BAT
if(math.random < j.LoudnessRate && NewFitness < j.fitness ){ //Update local best
j.BestPosition = j.position
j.BestFitness = j.fitness
//update Global Best
if(j.BestFitness < GlobalBest_Fitness) {
GlobalBest_Position = j.BestPosition //Set local best position to Global best
GlobalBest_Fitness = Sphere(GlobalBest_Position) //GlobalBest_Fitness = j.BestFitness
j.LoudnessRate = alpha * j.LoudnessRate
j.PulseRate = InitialPulseRate * (1 - math.pow(math.E, (-gyma * itr)))
}
}
}
itr += 1
}
println(GlobalBest_Fitness , GlobalBest_Position ,"Last")
}
}
class BAT12 ( dim:Int , min:Double , max:Double){
val random = new Random()
var position = DenseVector.fill(dim)(random.nextDouble() * (max-min)+min )
var velocity = DenseVector.fill(dim)( math.random)
var PulseRate = 0.1
var LoudnessRate = 0.95
var frequency = math.random
var fitness = math.random//DenseVector.fill(1)(math.random)
var BestPosition = DenseVector.fill(dim)(math.random)
var BestFitness = math.random//DenseVector.fill(1)(math.random)
}