3

我有一个 bat 算法的 Matlab 代码,我编写了这个算法的 java 版本 Bat 算法是一个简单的优化算法,用于找到任何函数的最小值这里是 matlab 代码和我的这个代码的 java 版本

我的这个算法的 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;
        }
    }   




}

这是matlab版本

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 ====================================
4

3 回答 3

3
  • 两个代码之间的差异

在 Matlab 代码中:

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

randn=>标准正态分布。

在 Java 代码中:

S[i][j] = (float) (Best[j] + (.001 * myRand.nextFloat()) );

java.util.Random.nextFloat()=> 0.0 到 1.0 之间均匀分布的浮点值。

于 2014-07-09T07:39:32.383 回答
2

我一直在寻找 C# 中的解决方案并偶然发现了这一点。这足以完成工作。这是从 java 中翻译过来的 C# 解决方案,其中变量重命名,以及一个额外的适应度函数,用于找到两个 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;
            }
        }
    }
于 2015-06-23T15:08:09.910 回答
1

这将是我第一次在这里堆栈溢出,所以如果我的回答有点模棱两可并且有很多问题,我会事先说抱歉。我只是希望我的这个答案能帮助这个线程上想要通过java学习蝙蝠算法的未来访问者。

无论如何,我确实看过你的代码,因为我目前正在研究蝙蝠算法。尝试运行它,与 matlab 版本相比,它确实给出了很远的结果。

我注意到的是,您只是“从字面上”尝试在没有完全理解每个 matlab 行的情况下转换 matlab 代码。我想指出你错过的所有东西,但我现在感觉很懒,所以我将把我的 bat 算法版本留在 java 中。

注意:我刚刚在 java 中制作了一个运行中的 bat 算法。不是一个高效的、完全调试的、matlab 的 java 等效 bat 算法。

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;
}


}
于 2015-01-15T19:13:16.597 回答