多线程模拟退火

Multi-threaded Simulated Annealing

本文关键字:模拟退火 多线程      更新时间:2023-10-16

我写了一个多线程模拟退火程序,但它没有运行。我不确定代码是否正确。代码能够编译,但当我运行代码时,它崩溃了。这只是一个运行时错误。

#include <stdio.h> 
#include <time.h>
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <string>
#include <vector>
#include <algorithm>
#include <fstream>
#include <ctime>
#include <windows.h>
#include <process.h> 
using namespace std;

typedef vector<double> Layer; //defines a vector type
typedef struct {
   Layer Solution1;
   double temp1;
   double coolingrate1;
   int MCL1;
   int prob1;
}t; 
//void SA(Layer Solution, double temp, double coolingrate, int MCL, int prob){

double  Rand_NormalDistri(double mean, double stddev) {
 //Random Number from Normal Distribution
    static double n2 = 0.0;
    static int n2_cached = 0;
    if (!n2_cached) {
       // choose a point x,y in the unit circle uniformly at random
     double x, y, r;
     do {
  //  scale two random integers to doubles between -1 and 1
   x = 2.0*rand()/RAND_MAX - 1;
   y = 2.0*rand()/RAND_MAX - 1;
    r = x*x + y*y;
   } while (r == 0.0 || r > 1.0);
        {
       // Apply Box-Muller transform on x, y
        double d = sqrt(-2.0*log(r)/r);
      double n1 = x*d;
      n2 = y*d;
       // scale and translate to get desired mean and standard deviation
      double result = n1*stddev + mean;
        n2_cached = 1;
        return result;
        }
    } else {
        n2_cached = 0;
        return n2*stddev + mean;
    }
}

double   FitnessFunc(Layer x, int ProbNum)
{

    int i,j,k;
    double z; 
  double fit = 0;  
  double   sumSCH; 
 if(ProbNum==1){
  // Ellipsoidal function
  for(j=0;j< x.size();j++)
    fit+=((j+1)*(x[j]*x[j]));
}
 else if(ProbNum==2){
  // Schwefel's function
  for(j=0; j< x.size(); j++)
    {
      sumSCH=0;
      for(i=0; i<j; i++)
    sumSCH += x[i];
      fit += sumSCH * sumSCH;
    }
}
 else if(ProbNum==3){
  // Rosenbrock's function
  for(j=0; j< x.size()-1; j++)
    fit += 100.0*(x[j]*x[j] - x[j+1])*(x[j]*x[j] - x[j+1]) + (x[j]-1.0)*(x[j]-1.0);
}
  return fit;
}
double probl(double energychange, double temp){
    double a;
    a= (-energychange)/temp;
    return double(min(1.0,exp(a)));
}
int random (int min, int max){
    int n = max - min + 1;
    int remainder = RAND_MAX % n;
    int x;
    do{
        x = rand();
    }while (x >= RAND_MAX - remainder);
    return min + x % n;
}
//void SA(Layer Solution, double temp, double coolingrate, int MCL, int prob){
void SA(void *param){
    t *args = (t*) param;
    Layer Solution = args->Solution1;
    double temp = args->temp1;
    double coolingrate = args->coolingrate1;
    int MCL = args->MCL1;
    int prob = args->prob1;
    double Energy;
    double EnergyNew;
    double EnergyChange;
    Layer SolutionNew(50);
    Energy = FitnessFunc(Solution, prob);
    while (temp > 0.01){
        for ( int i = 0; i < MCL; i++){
            for (int j = 0 ; j < SolutionNew.size(); j++){
                SolutionNew[j] = Rand_NormalDistri(5, 1);
            }
            EnergyNew = FitnessFunc(SolutionNew, prob);
            EnergyChange = EnergyNew - Energy;
            if(EnergyChange <= 0){
                Solution = SolutionNew;
                 Energy = EnergyNew;    
            }
            if(probl(EnergyChange ,temp ) >  random(0,1)){
                //cout<<SolutionNew[i]<<endl;
                Solution = SolutionNew;
                 Energy = EnergyNew;
                cout << temp << "=" << Energy << endl;
            }
        }
        temp = temp * coolingrate;
    }
}


int main ()
{ 
 srand ( time(NULL) ); //seed for getting different numbers each time the prog is run

Layer SearchSpace(50); //declare a vector of 20 dimensions
//for(int a = 0;a < 10; a++){
for (int i = 0 ; i < SearchSpace.size(); i++){
    SearchSpace[i] = Rand_NormalDistri(5, 1);
}
t *arg1;
arg1 = (t *)malloc(sizeof(t));
arg1->Solution1 = SearchSpace;
arg1->temp1 = 1000;
arg1->coolingrate1 = 0.01;
arg1->MCL1 = 100;
arg1->prob1 = 3;
//cout << "Test " << ""<<endl;
_beginthread( SA, 0, (void*) arg1);
Sleep( 100 );
//SA(SearchSpace, 1000, 0.01, 100, 3);
//}
  return 0;
}

请帮助。

谢谢Avinesh

正如leftaroundabout指出的那样,您正在c++代码中使用malloc。这就是你崩溃的原因。

Malloc将分配一块内存,但由于它实际上是为C设计的,因此它不调用任何c++构造函数。在本例中,vector从来没有被正确构造过。当

arg1->Solution1 = SearchSpace;
调用

时,成员变量"Solution1"的状态为未定义,并且赋值操作符崩溃。

代替malloc try

arg1 = new t;

这将完成大致相同的事情,但"new"关键字还调用任何必要的构造函数来确保vector

这也带来了另一个小问题,您新建的内存也需要在某个地方删除。在这种情况下,由于arg1被传递给了另一个线程,因此应该像

那样清理它。
delete args;

在你的"SA"函数完成args变量之后。

虽然我不知道你崩溃的实际原因,但我对你陷入困境并不感到惊讶。例如,Rand_NormalDistri中的那些"缓存"静态变量显然容易受到数据竞争的影响。为什么不用std::normal_distribution呢?当标准库例程可用时,使用它们几乎总是一个好主意,当您需要考虑多线程技巧时更是如此。

更糟糕的是,你大量混合使用C和c++。malloc是你实际上不应该在c++代码中使用的东西-它不知道RAII,这是你可以在c++中坚持的少数几个本质上安全的东西之一。