Реализация алгоритма BAT в Scala - PullRequest
1 голос
/ 02 июня 2019

Я реализовал алгоритм BAT в Scala (меня интересует стиль функционального программирования). В алгоритме 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 голосов
/ 03 июня 2019

Я не знаю, почему это так, но похоже, что при однократном шаге через вашу программу эти строки кода сбрасывают ваши позиции до их первоначальных значений:

        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
        }

Если вы прокомментируете этот блок кода, то ваши позиции изменятся. Поскольку я не эксперт по летучим мышам, я понятия не имею, правильно ли это изменение или нет, но они меняются.

Надеюсь, этого достаточно для правильной отладки вашего алгоритма.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...