2013-04-09 78 views
2

我有一個Matlab代碼的蝙蝠算法,我寫這個算法的java版本 蝙蝠算法是一個簡單的尋找任何函數的最小值的算法 這裏是matlab代碼和我的java這段代碼的版本java版蝙蝠算法在matlab中

這個算法我的Java版本無法找到像MATLAB版本 最佳的結果,我找不到在哪裏是我的代碼從MATLAB轉換成Java

誰能幫助錯誤我的錯在哪裏?

import java.util.Random; 

public class Bat 
{ 
    private int n; 
    private float A, r; 
    private float Qmin, Qmax; 
    private int d; 
    private int NofGen; 
    private float fmin; 
    private int fminIndex; 
    private float Fnew; 
    private int loopCounter; 

    private float Q[], V[][], Sol[][], UL_bound[][], fitness[], S[][], Best[]; 

    private Random myRand; 

    public Bat(
      int NBats, 
      float loudness, 
      float pulseRate, 
      float minFreq, 
      float maxFreq, 
      int NofGeneration, 
      int dimension 
      ) 
    { 
     n = NBats; 
     A = loudness; 
     r = pulseRate; 
     Qmin = minFreq; 
     Qmax = maxFreq; 
     NofGen = NofGeneration; 
     d = dimension; 

     S = new float[n][d]; 
     Best = new float[d]; 
     UL_bound = new float[2][d]; 

     //default bounds 
     for(int i = 0 ; i < d ; i++) 
     { 
      UL_bound[0][i] = -10000; 
      UL_bound[1][i] = 10000; 
     } 

     loopCounter = 0; 
     myRand = new Random(); 

     Q = new float[n]; 
     for(int i = 0 ; i < n ; i++) 
      Q[i] = 0; 

     V = new float[n][d]; 
     for(int i = 0 ; i < n ; i++) 
      for(int j = 0 ; j < d ; j++) 
       V[i][j] = 0; 

    } 



    public void intial() 
    { 

     Sol = new float[n][d]; 
     for(int i = 0 ; i < n ; i++) 
      for(int j = 0 ; j < d ; j++) 
      { 
       float t = myRand.nextFloat(); 
       //(upper -lower)*rand + lower 
       Sol[i][j] = t * (UL_bound[1][j] - UL_bound[0][j]) + UL_bound[0][j]; 
      } 


     fitness = new float[n]; 
     for(int i = 0 ; i < n ; i++) 
      fitness[i] = function(Sol[i]); 

     //finding fmin 
     fmin = fitness[0]; 
     fminIndex = 0; 
     for(int i = 0 ; i < n ; i++) 
     { 
      if (fitness[i] < fmin) 
      { 
       fmin = fitness[i]; 
       fminIndex = i; 
      } 
     } 

     //setting best 
     for(int j = 0 ; j < d ; j++) 
      Best[j] = Sol[fminIndex][j]; 

    } 

    public void start() 
    { 

     while(loopCounter < NofGen) 
     { 

      for(int i = 0 ; i < n ; i++) 
      { 

       Q[i] = Qmin + (Qmin - Qmax)* myRand.nextFloat(); 

       for(int j = 0 ; j < d ; j++) 
        V[i][j] = V[i][j] + (Sol[i][j]-Best[j])*Q[i]; 

       for(int j = 0 ; j < d ; j++) 
        S[i][j] = Sol[i][j] + V[i][j]; 

       Sol[i] = simpleBounds(Sol[i]); 

       if(myRand.nextFloat() > r)   
        for(int j = 0 ; j < d ; j++) 
         S[i][j] = (float) (Best[j] + (.001 * myRand.nextFloat())); 

       Fnew = function(S[i]); 

       if(Fnew <= fitness[i] && myRand.nextFloat() < A) 
       { 
        for(int j = 0 ; j < d ; j++) 
         Sol[i][j] = S[i][j]; 

        fitness[i] = Fnew; 
       } 

       if(Fnew <= fmin) 
       { 
        fmin = Fnew; 
        for(int j = 0 ; j < d ; j++) 
         Best[j] = S[i][j]; 
       } 

      } 
      loopCounter++; 

     } 

    } 

    public float[] simpleBounds(float p[]) 
    { 
     for(int i = 0 ; i < d ; i++) 
     { 
      if(p[i] < UL_bound[0][i]) 
       p[i] = UL_bound[0][i]; 

      if(p[i] > UL_bound[1][i]) 
       p[i] = UL_bound[1][i]; 
     } 
     return p; 
    } 
    float function(float p[]) 
    { 
     // Sphere function with fmin=0 at (0,0,...,0) 
     float sum = 0; 
     for(int i = 0 ; i < p.length ; i++) 
      sum = sum + p[i]*p[i]; 
     return sum; 

    } 
    public float printResult() 
    { 
     System.out.println("After " + loopCounter + "Repeats :"); 

     for(int i = 0 ; i < d ; i++) 
      System.out.print(Best[i] + ", "); 

     System.out.println ("F(x) = " + fmin); 
     return fmin; 
    } 

    public void set_UL_Bound(int n, float L, float U) 
    { 
     if(n < d && n >= 0) 
     { 
      UL_bound[0][n] = L; 
      UL_bound[1][n] = U; 
     } 
    } 




} 

,這是versian

function [best,fmin,N_iter]=bat_algorithm(para) 
% Display help 
help bat_algorithm.m 

% Default parameters 
if nargin<1, para=[20 1000 0.5 0.5]; end 
n=para(1);  % Population size, typically 10 to 40 
N_gen=para(2); % Number of generations 
A=para(3);  % Loudness (constant or decreasing) 
r=para(4);  % Pulse rate (constant or decreasing) 
% This frequency range determines the scalings 
% You should change these values if necessary 
Qmin=0;   % Frequency minimum 
Qmax=2;   % Frequency maximum 
% Iteration parameters 
N_iter=0;  % Total number of function evaluations 
% Dimension of the search variables 
d=5;   % Number of dimensions 
% Lower limit/bounds/ a vector 
Lb=-3*ones(1,d); 
% Upper limit/bounds/ a vector 
Ub=6*ones(1,d); 
% Initializing arrays 
Q=zeros(n,1); % Frequency 
v=zeros(n,d); % Velocities 
% Initialize the population/solutions 
for i=1:n, 
    Sol(i,:)=Lb+(Ub-Lb).*rand(1,d); 
    Fitness(i)=Fun(Sol(i,:)); 
end 
% Find the initial best solution 
[fmin,I]=min(Fitness); 
best=Sol(I,:); 


for t=1:N_gen, 
% Loop over all bats/solutions 
     for i=1:n, 
      Q(i)=Qmin+(Qmin-Qmax)*rand; 
      v(i,:)=v(i,:)+(Sol(i,:)-best)*Q(i); 
      S(i,:)=Sol(i,:)+v(i,:); 
      % Apply simple bounds/limits 
      Sol(i,:)=simplebounds(Sol(i,:),Lb,Ub); 
      % Pulse rate 
      if rand>r 
      % The factor 0.001 limits the step sizes of random walks 
       S(i,:)=best+0.001*randn(1,d); 
      end 

    % Evaluate new solutions 
      Fnew=Fun(S(i,:)); 
    % Update if the solution improves, or not too loud 
      if (Fnew<=Fitness(i)) & (rand<A) , 
       Sol(i,:)=S(i,:); 
       Fitness(i)=Fnew; 
      end 

      % Update the current best solution 
      if Fnew<=fmin, 
       best=S(i,:); 
       fmin=Fnew; 
      end 
     end 
     N_iter=N_iter+n; 
end 
% Output/display 
disp(['Number of evaluations: ',num2str(N_iter)]); 
disp(['Best =',num2str(best),' fmin=',num2str(fmin)]); 

% Application of simple limits/bounds 
function s=simplebounds(s,Lb,Ub) 
    % Apply the lower bound vector 
    ns_tmp=s; 
    I=ns_tmp<Lb; 
    ns_tmp(I)=Lb(I); 

    % Apply the upper bound vector 
    J=ns_tmp>Ub; 
    ns_tmp(J)=Ub(J); 
    % Update this new move 
    s=ns_tmp; 


function z=Fun(u) 
% Sphere function with fmin=0 at (0,0,...,0) 
z=sum(u.^2); 
%%%%% ============ end ==================================== 
+0

在調試器中運行兩個步驟,直到結果分歧爲止? – Patashu 2013-04-09 05:50:47

+1

結果的差異可能是由於(某些)變量的精確度不同所致。在Java中,你聲明瞭很多浮點數,在Matlab中,默認情況下,變量是雙精度浮點數;我沒有看到證據表明你已經制作了任何你的Matlab變量的非默認類型。 – 2013-04-09 06:34:30

+0

謝謝 所以我會將所有花車換成雙倍 – Amir 2013-04-09 13:58:33

回答

2
  • matlab的兩個碼

之間的差異在Matlab代碼:

S(I,:)=最佳+ 0.001 * randn(1,d);

randn =>標準正態分佈。

儘管在Java代碼:

S [i] [j] =(浮子)(最佳[J] +(0.001 * myRand.nextFloat()));

java.util.Random.nextFloat()=>均勻分佈的0.0和1.0之間浮點值。

1

這將是我第一次在堆棧溢出,所以如果我的迴應會有點模棱兩可,並且有很多問題,我會事先說對不起。我只希望我的這個答案能夠幫助未來的訪問者想要通過java學習蝙蝠算法。

無論如何,我看過你的代碼,因爲我現在正在學習蝙蝠算法。 試圖運行它,它與matlab版本相比的結果遠遠不夠。

我注意到的是,你只是「字面上」試圖轉換的matlab代碼沒有完全理解每個matlab線。我想指出所有你錯過的東西,但我現在感覺很懶,所以我只會把我的版本的蝙蝠算法留在Java中。

注意:我只是在java中製作了一個正在運行的蝙蝠算法。不是一個高效的,完全調試的matlab的java等效蝙蝠算法。

import java.util.Random; 

public class Mybat { 

/** 
* @param args the command line arguments 
*/ 
public int n, N_gen, Qmin, Qmax, N_iter, d; 
public double A,r,min,max,fnew,fmin; 
public double Lb[][],Ub[][],Q[],v[][],Sol[][],S[][],fitness[],temp[],best[]; 
public Random random; 
public static void main(String[] args) { 
    Mybat x = new Mybat(20,1000,0.5,0.5,5); 

} 

public Mybat(
     int bats, 
     int generations, 
     double loud, 
     double pulse, 
     int dimension 
     ){ 

    //initialization of variables 
    n=bats; 
    N_gen = generations; 
    A = loud; 
    r = pulse; 
    d = dimension; 

    Random rand = new Random(); 

    //plan to change later and added as parameter 
    min = -15; 
    max = 15; 


    fmin = 0; 
     //decleration for the bounds 
    Lb = new double[1][d]; 
    Ub = new double[1][d]; 

    Q = new double[n]; // frequency 
    v = new double[n][d]; //velocity 


    //initialize solution array 
    Sol = new double[n][d]; 
    S = new double[n][d]; 
    fitness = new double[n]; // fitness container 
    best =new double[d]; 
    temp = new double[d]; //temporary holder for a row in array Sol 

    for(int i=0;i<n;i++){ 

     // for minimal coding : added initialize Q[]array with '0' as element 
     Q[i] = 0; 

     for(int x=0;x<d;x++){ 

      // for minimal coding : added initialize v[][] array with '0' as element 
      v[i][x] = 0; 

      //find random double values from LB to UB 
      Sol[i][x]= (rand.nextDouble()*(max - min)) + min; 
      temp[x] = Sol[i][x]; 
      //System.out.println("sol["+i+"]["+x+"] = "+Sol[i][x]); //test line 
      //System.out.println(rand.nextDouble()); //test line 
     } 
     fitness[i] = function(temp); 

     //initialize best and the fmin 
     if(i==0 || fmin > fitness[i]){ 
      fmin = fitness[i]; 

      for(int x=0;x<d;x++){ 
       best[x] = Sol[i][x]; 
      } 
     } 
     System.out.println("fitness["+i+"]"+fitness[i]); //test 
    } 
    System.out.println("fmin = "+fmin); //test 

     // special note to these variables (below) 
     // change if required for maximum effectivity 
    Qmin = 0; 
    Qmax = 2; 
    N_iter = 1; //number of function evaluation 

    // bat proper 
    for(int loop=0;loop<N_iter;loop++){ 

     // loop over all bats/solutions 
     for(int i=0;i<n;i++){ 
      Q[i] = Qmin+((Qmin-Qmax)*rand.nextDouble()); 

      // loop for velocity 
      for(int vel=0;vel<d;vel++){ 
       v[i][vel] = v[i][vel]+((Sol[i][vel]-best[vel])*Q[i]); 
      } 

      //new solutions 
      for(int x=0;x<d;x++){ 
       S[i][x] = Sol[i][x] + v[i][x]; 
      } 

      /** 
      * RESERVED SPOT for the QUESTIONABLE AREA ON THE 
      * MATLAB CODE (i think it is not needed for the java equivalent) 
      */ 

      // pulse rate 
      if(rand.nextDouble()>r){ 
       for(int x=0;x<d;x++){ 
        S[i][x] = best[x]+(0.001*rand.nextGaussian()); 
       } 
      } 

      //putting current row of Sol to a temp array 
      for(int x=0;x<d;x++){ 
       temp[x] = S[i][x]; 
      } 
      fnew = function(temp); 

      // update if solution is improved, and not too loud 
      if((fnew<=fitness[i]) && (rand.nextDouble()<A)){ 
       for(int x=0;x<d;x++){ 
        Sol[i][x] = S[i][x]; 
        fitness[i] = fnew; 
       } 
      } 

      //update current best solution 
      if(fnew<=fmin){ 
       for(int x=0;x<d;x++){ 
        best[x] = S[i][x]; 
        fmin = fnew; 
       } 
      } 
     } 

    } 

    System.out.println(" "); 
    System.out.println("new fitness"); 
    for(int i=0;i<n;i++){ 

     System.out.println("fitness["+i+"]"+fitness[i]); 
    } 
    System.out.println("Fmin = "+fmin); 
} 

//possible that this function is not needed in java 
public void set_bounds(int x, double L, double U){ 
    //double temp_Lb[x]; 
    //double temp_Ub[x]; 
    for(int i=0; i<x; i++){ 
     Lb[0][i] = L; 
     Ub[0][i] = U; 
    } 

} 

public double function(double value[]){ 
    // sphere function where fmin is at 0 
    double result = 0; 

    for(int i=0;i<d;i++){ 
     result += (value[i]*value[i]); 
    } 
    return result; 
} 


} 
1

我一直在尋找C#解決方案,並偶然發現了這一點。完成工作足夠了。這裏是C#中的解決方案,它用java重新命名變量和一個附加的適應函數來尋找兩個x,y方程xy = 6和x + y = 5的解。還包括找到.3的平方根:

using System; 

    namespace BatAlgorithmC 

    namespace BatAlgorithmC 
    { 
     class Program 
     { 
      static void Main(string[] args) 
      { 
      //  Mybat x = new Mybat(100, 1000, 0.5, 0.5, 5, Mybat.sphere); 
     //  Mybat x = new Mybat(1000, 1000, 0.5, 0.5, 1, Mybat.squareRoot); 

      Mybat x = new Mybat(1000, 1000, 0.5, 0.5, 2, Mybat.RootOfXYEquations); 
       Console.WriteLine("Hit any key to continue."); 
       Console.ReadLine(); 


      } 



     } 

     public class Mybat 
     { 
    /** 
    * @param args the command line arguments 
    */ 
      public int _numberOfBats, _generations, Qmin, Qmax, N_iter, _dimension; 
      public double _volume, _pulseRate, min, max, fnew, fmin; 
      public double[][] _lowerBound, _upperBound, _velocity, _solution, S; 
      public double[] _fitness, _tempSolution, _bestSolution, Q; 
      public Random random; 
    //public static void main(String[] args) { 
    // Mybat x = new Mybat(20,1000,0.5,0.5,5, Mybat.sphere); 

    //} 

      public static void initJagged(double[][] array, int n, int d) 
      { 
       for (int i = 0; i < n; i++) array[i] = new double[d]; 
      } 

      public Mybat(
       int bats, 
       int generations, 
       double loud, 
       double pulse, 
       int dimension, 
       Func<double[], int, double> function 
       ) 
      { 
       //initialization of variables 
       _numberOfBats = bats; 
       _generations = generations; 
       _volume = loud; 
       _pulseRate = pulse; 
       _dimension = dimension; 

       Random random = new Random(); 

       //plan to change later and added as parameter 
       min = -15; 
       max = 15; 


       fmin = 0; 
       //decleration for the bounds 
       _lowerBound = new double[1][]; 
       _upperBound = new double[1][]; 

       Q = new double[_numberOfBats]; // frequency 
       _velocity = new double[_numberOfBats][]; //velocity 

       initJagged(_velocity, _numberOfBats, _dimension); 
       initJagged(_lowerBound, 1, _dimension); 
       initJagged(_upperBound, 1, _dimension); 


       //initialize solution array 
       _solution = new double[_numberOfBats][]; 
       S = new double[_numberOfBats][]; 
       _fitness = new double[_numberOfBats]; // fitness container 
       _bestSolution = new double[_dimension]; 
       _tempSolution = new double[_dimension]; //temporary holder for a row in array _solution 

       initJagged(_solution, _numberOfBats, _dimension); 
       initJagged(S, _numberOfBats, _dimension); 

       for (int i = 0; i < _numberOfBats; i++) 
       { 
        // for minimal coding : added initialize Q[]array with '0' as element 
        Q[i] = 0; 

        for (int x = 0; x < _dimension; x++) 
        { 
         // for minimal coding : added initialize _velocity[][] array with '0' as element 
         _velocity[i][x] = 0; 

         //find random double values from LB to UB 
         _solution[i][x] = (random.NextDouble()*(max - min)) + min; 
         _tempSolution[x] = _solution[i][x]; 
         //Console.WriteLine("sol["+i+"]["+x+"] = "+_solution[i][x]); //test line 
         //Console.WriteLine(rand.nextDouble()); //test line 
        } 
        _fitness[i] = function(_tempSolution, _dimension); 

        //initialize best and the fmin 
        if (i == 0 || fmin > _fitness[i]) 
        { 
         fmin = _fitness[i]; 

         for (int x = 0; x < _dimension; x++) 
         { 
          _bestSolution[x] = _solution[i][x]; 
         } 
        } 
        Console.WriteLine("fitness[" + i + "]" + _fitness[i]); //test 
       } 
       Console.WriteLine("fmin = " + fmin); //test 

       // special note to these variables (below) 
       // change if required for maximum effectivity 
       Qmin = 0; 
       Qmax = 2; 
       N_iter = 1; //number of function evaluation 

       // bat proper 
       for (int loop = 0; loop < N_iter; loop++) 
       { 
        // loop over all bats/solutions 
        for (int nextBat = 0; nextBat < _numberOfBats; nextBat++) 
        { 
         Q[nextBat] = Qmin + ((Qmin - Qmax)*random.NextDouble()); 

         // loop for velocity 
         for (int vel = 0; vel < _dimension; vel++) 
         { 
          _velocity[nextBat][vel] = _velocity[nextBat][vel] + 
                 ((_solution[nextBat][vel] - _bestSolution[vel])*Q[nextBat]); 
         } 

         //new solutions 
         for (int nextDimension = 0; nextDimension < _dimension; nextDimension++) 
         { 
          S[nextBat][nextDimension] = _solution[nextBat][nextDimension] + 
                 _velocity[nextBat][nextDimension]; 
         } 

         /** 
       * RESERVED SPOT for the QUESTIONABLE AREA ON THE 
       * MATLAB CODE (i think it is not needed for the java equivalent) 
       */ 

         // pulse rate 
         if (random.NextDouble() > _pulseRate) 
         { 
          for (int nextDimension = 0; nextDimension < _dimension; nextDimension++) 
          { 
           S[nextBat][nextDimension] = _bestSolution[nextDimension] + (0.001*random.NextGaussian()); 
          } 
         } 

         //putting current row of _solution to a temp array 
         for (int nextDimension = 0; nextDimension < _dimension; nextDimension++) 
         { 
          _tempSolution[nextDimension] = S[nextBat][nextDimension]; 
         } 
         fnew = function(_tempSolution, _dimension); 

         // update if solution is improved, and not too loud 
         if ((fnew <= _fitness[nextBat]) && (random.NextDouble() < _volume)) 
         { 
          for (int x = 0; x < _dimension; x++) 
          { 
           _solution[nextBat][x] = S[nextBat][x]; 
           _fitness[nextBat] = fnew; 
          } 
         } 

         //update current best solution 
         if (fnew <= fmin) 
         { 
          for (int nextDimension = 0; nextDimension < _dimension; nextDimension++) 
          { 
           _bestSolution[nextDimension] = S[nextBat][nextDimension]; 
           fmin = fnew; 
          } 
         } 
        } 
       } 

       Console.WriteLine(" "); 
       Console.WriteLine("new fitness"); 
       for (int i = 0; i < _numberOfBats; i++) 
       { 
        Console.WriteLine("fitness[" + i + "]" + _fitness[i]); 
       } 

       for (int nextDimension = 0; nextDimension < _dimension; nextDimension++) 
       { 
        Console.WriteLine("best[" + nextDimension + "]" + _bestSolution[nextDimension]); 
       } 
       Console.WriteLine("Fmin = " + fmin); 
      } 

    //possible that this function is not needed in java 
      public void set_bounds(int x, double L, double U) 
      { 
       //double temp_Lb[x]; 
       //double temp_Ub[x]; 
       for (int i = 0; i < x; i++) 
       { 
        _lowerBound[0][i] = L; 
        _upperBound[0][i] = U; 
       } 
      } 

      public static double sphere(double[] value, int d) 
      { 
       // sphere function where fmin is at 0 
       double result = 0; 

       for (int i = 0; i < d; i++) 
       { 
        result += (value[i]*value[i]); 
       } 
       return result; 
      } 

      public static double squareRoot(double[] value, int d) 
      { 
       // find the square root of .3 
       double result = 0; 

       for (int i = 0; i < d; i++) 
       { 
        result += Math.Abs(.3 - (value[i]*value[i])); 
       } 
       return result; 
      } 

    public static double RootOfXYEquations(double[] value, int d) 
    { 
     // solve for x and y xy = 6 and x+y = 5 
     double result = 0; 

     result += Math.Abs(5 - (value[0] + value[1])); 
     result += Math.Abs(6 - (value[0] * value[1])); 


     return result; 
    } 
     } 


     static class MathExtensiionns 
     { 
      public static double NextGaussian(this Random rand) 
      { 
      double u1 = rand.NextDouble(); //these are uniform(0,1) random doubles 
      double u2 = rand.NextDouble(); 
      double mean = 0, stdDev = 1; 
      double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) * 
         Math.Sin(2.0 * Math.PI * u2); //random normal(0,1) 
      double randNormal = 
         mean + stdDev * randStdNormal; //random normal(mean,stdDev^2) 
      return randNormal; 
      } 
     } 
    }