Scala中BAT算法的实现

时间:2019-06-02 11:16:53

标签: scala functional-programming

我已经在Scala中实现了BAT算法(我对函数式编程风格很感兴趣)。BAT算法涉及的步骤如下

enter image description here

BAT算法的参数是

enter image description here

  • x: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)
}

1 个答案:

答案 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
        }

如果您注释掉此代码块,则您的位置会改变。由于我不是蝙蝠专家,所以我不知道更改是否正确,但是它们确实会更改。

希望这足以正确调试算法。