我已经在Scala中实现了BAT算法(我对函数式编程风格很感兴趣)。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)
}
答案 0 :(得分:0)
我不知道为什么,但是看来,当单步通过您的程序时,这些代码行将您的位置重置为原始值:
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
}
如果您注释掉此代码块,则您的位置会改变。由于我不是蝙蝠专家,所以我不知道更改是否正确,但是它们确实会更改。
希望这足以正确调试算法。