⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 opticalnetworkdlg.cpp

📁 用vc++做的一个简单的基因算法程序,可以实现简单的基因算法功能
💻 CPP
📖 第 1 页 / 共 2 页
字号:

// 搜索最小C值
double COpticalNetworkDlg::FindMiniC(double *data, int len)
{ 
	double mini=data[0];
	int mininum=0;
	for(int n=0;n<len;n++)
	{
		if(data[n]<mini)
		{
			mini=data[n];
		    mininum=n;
		}
	}
	return mini;
}

// 基因算法的具体实现
void COpticalNetworkDlg::OnButtonGa() 
{     
	 // 取得基因算法所需参数 
	 UpdateData(TRUE);
     // 分配内存
     OBD_OLT=(double *)malloc(sizeof(double)*m_nOBDNum);
     ONU_OBD=(double *)malloc(sizeof(double)*m_nONUNum*m_nOBDNum);
     // 根据群体规模和交叉概率计算出交叉个体个数
	 nGACrossNum = m_nGroupSize*m_GACrossProb/2;
	 // 根据群体规模和变异概率计算出变异个体个数
     nGAVariNum  = m_nGroupSize*m_GAVariProb;
	 // 设置已进行过基因算法标志
	 m_bIsGa=TRUE;
	 // 为当前一代个体分配内存
     for(int k=0;k<m_nGroupSize;k++)
          GeneSerial[k]=(int *) malloc(sizeof(int)*m_nONUNum);
	  // 为当前一代个体交叉和变异后的新产生的个体分配内存
     for(int u=0;u<nGACrossNum*2+nGAVariNum;u++)
          NextGeneSerial[u]=(int *)malloc(sizeof(int)*m_nONUNum);
     // 参数有效性检查
	 if(m_nONUNum>=m_nOBDLimit*m_nOBDNum)
	 {
		  AfxMessageBox("ONU数目过多,或者OBD数目过少,或OBD最大连接数目过小!",MB_OK|MB_ICONINFORMATION,NULL);
          return; 
	 }
	 if(m_nGroupSize<nGACrossNum*2+nGAVariNum)
	 {
		  AfxMessageBox("群体规模过小,或者交叉概率过大,或者变异概率过大!",MB_OK|MB_ICONINFORMATION,NULL);
          return; 
	 }
     for(int n1=0;n1<m_nOBDNum;n1++)
     {
          OBD_OLT[n1]=sqrt((m_OBDX[n1]-m_OLTX)*(m_OBDX[n1]-m_OLTX)+(m_OBDY[n1]-m_OLTY)*(m_OBDY[n1]-m_OLTY));
          nOBDLimit[n1]=m_nOBDLimit;
     } 
     int LimitTotal=0;
     int CurGroupSize=1;
     for(int p=0;p<m_nOBDNum;p++)
          LimitTotal+=nOBDLimit[p];
     for(int q=0;q<m_nONUNum;q++)
     {
          if(CurGroupSize>MAX_GROUPSIZE*10)
          break;
          else
          {
             CurGroupSize=LimitTotal*CurGroupSize;
             LimitTotal--;
          }
     }
     if(m_nGroupSize>CurGroupSize||m_nGroupSize>MAX_GROUPSIZE*10)
          return;	
	 // 计算ONU和OBD之间距离
     for(int i=0;i<m_nONUNum;i++)
          for(int j=0;j<m_nOBDNum;j++)                                            
		     *(ONU_OBD+i*m_nOBDNum+j)=sqrt((m_ONUX[i]-m_OBDX[j])*(m_ONUX[i]-m_OBDX[j])+(m_ONUY[i]-m_OBDY[j])*(m_ONUY[i]-m_OBDY[j]));
     // 产生初始基因序列   
	 for(int i1=0;i1<m_nGroupSize;i1++)
     {          
          for(int k=0;k<m_nOBDNum;k++)
              nCurOBDLimit[i1][k]=0;
          for(int j1=0;j1<m_nONUNum;j1++)
          {
             int RandInt;
      Random:RandInt=RandomInt(0,m_nOBDNum-1);
             if(nCurOBDLimit[i1][RandInt]<=nOBDLimit[RandInt]-1)
             {
                *(GeneSerial[i1]+j1)=RandInt;
                nCurOBDLimit[i1][RandInt]++; 
             }
             else
                goto Random;   // 不满足约束条件2时,重新产生基因序列
          } 
     }
	 // 基因算法具体实现
     for( nCurGANum=0;nCurGANum<m_GANum;nCurGANum++)
     {   
          // 计算当前一代群体中每个个体的适应度数值F
		  for(int i=0;i<m_nGroupSize;i++)
          {    
             Cost[i]=0;
			 for(int j=0;j<m_nONUNum;j++)
			 {   
				 Cost[i]=Cost[i]+*(ONU_OBD+j*m_nOBDNum+*(GeneSerial[i]+j))+*(OBD_OLT+*(GeneSerial[i]+j));             
   			     temp[i][j]=*(ONU_OBD+j*m_nOBDNum+*(GeneSerial[i]+j));
			 }  
			 F[i]=1/Cost[i]; 
			 TotalF=F[i]+TotalF;
          }
          // 归一化F值
		  for(int a=0;a<m_nGroupSize;a++)
             Pm[a]=F[a]/TotalF*100;
          // 将当前一代群体中的个体按F值从大到小排序
		  for(int b=0;b<m_nGroupSize-1;b++)
		  {
			  FindMiniF(Pm,m_nGroupSize-b);
		  }
		  m_CurGANum=nCurGANum;
    	  // 查找当前一代中的最小费用个体
		  m_MiniCost=FindMiniC(Cost,m_nGroupSize);
		  // 绘制图形
		  DrawNetwork();
          // 交叉操作
		  for(int c=0;c<nGACrossNum;c++)
          {  
			 int nExchangePos,temp=0;
             int nNextOBD1;
             int nNextOBD2;
			 int LimitLoop=0;
             int new1=0;     // 发生交叉个体1在当前一代群体中位置
			 int new2=0;     // 发生交叉个体2在当前一代群体中位置
             //int temp=0;
      Limit1:new1=RandomInt(0,m_nGroupSize-1);   
			 temp=RandomInt(0,m_nGroupSize-1);
             // 由于当前一代群体中个体已经按照F从大到小排序
			 // 如果new1>temp,则位置new1处个体F值小于temp处个体F值
			 // 所以选定new1=temp处个体进行交叉,体现了F值较大的个体有较多机会进行交叉
			 if(new1>temp)  
                new1=temp;
             new2=RandomInt(0,m_nGroupSize-1);
             temp=RandomInt(0,m_nGroupSize-1);
             if(new2>temp)
                new2=temp;             
             for(int g=0;g<m_nOBDNum;g++)
             { 
                 nNextOBDLimit[2*c][g]=nCurOBDLimit[new1][g];
                 nNextOBDLimit[2*c+1][g]=nCurOBDLimit[new2][g];
             } 
            
      Limit2:nExchangePos=RandomInt(0,m_nONUNum-1);  // 被选中交叉个体的基因序列中用于交叉的基因位
             nNextOBD1=nNextOBDLimit[2*c][*(GeneSerial[new2]+nExchangePos)]+1;
             nNextOBD2=nNextOBDLimit[2*c+1][*(GeneSerial[new1]+nExchangePos)]+1;
			 LimitLoop++;
             if((nNextOBD1>nOBDLimit[*(GeneSerial[new2]+nExchangePos)])||(nNextOBD2>nOBDLimit[*(GeneSerial[new1]+nExchangePos)]))
                 if(LimitLoop>50)   // 跳转到Limit2重新产生交叉位满50次,仍未满足约束条件2,
					goto Limit1;    // 则跳转到Limit1,重新产生交叉个体在当前一代群体中位置
				 else
				    goto Limit2;    // 交叉后,不满足约束条件2,跳转到Limit2重新产生交叉位
             
		     // 交叉成功,产生新的个体
			 for(int m=0;m<m_nONUNum;m++)
             {   
                 if(m==nExchangePos)
                 {
                    *(NextGeneSerial[2*c]+nExchangePos)=*(GeneSerial[new2]+nExchangePos);
                    *(NextGeneSerial[2*c+1]+nExchangePos)=*(GeneSerial[new1]+nExchangePos);
                    nNextOBDLimit[2*c][*(GeneSerial[new2]+nExchangePos)]++;
                    nNextOBDLimit[2*c][*(GeneSerial[new1]+nExchangePos)]--;
                    nNextOBDLimit[2*c+1][*(GeneSerial[new2]+nExchangePos)]--;
                    nNextOBDLimit[2*c+1][*(GeneSerial[new1]+nExchangePos)]++;                   
                 }
                 else
                 {
                    *(NextGeneSerial[2*c]+m)=*(GeneSerial[new1]+m);
                    *(NextGeneSerial[2*c+1]+m)=*(GeneSerial[new2]+m);
                 }
              }            
           } 

           // 变异操作
		   for(int d=0;d<nGAVariNum;d++)
           {
               int nVariIndividual=0;
               int nVariPos=0;
			   int VariLoop=0;
         Vari1:VariLoop=0;
			   nVariIndividual=RandomInt(0,m_nGroupSize-1); // 发生变异个体在当前一代群体中位置
			   nVariPos=RandomInt(0,m_nONUNum-1);           // 发生变异个体的基因序列中变异的基因位
               for(int z=0;z<m_nOBDNum;z++)
                   nNextOBDLimit[2*nGACrossNum+d][z]=nCurOBDLimit[nVariIndividual][z];
               for(int h=0;h<m_nONUNum;h++)
               {
                   if(h==nVariPos)
                   {
                      int nVariValue;
                      int nNextVari;
               Vari2: nVariValue=RandomInt(0,m_nOBDNum-1);  // 产生变异位变异后的值
                      if(nVariValue==*(GeneSerial[nVariIndividual]+nVariPos))
					  {   
						  VariLoop++;
						  if(VariLoop==100) // 跳转到Vari2满50次,随机产生的变异位的值仍等于待变异位的当前值
							  goto Vari1;   // 则跳转到Vair1,重新产生变异个体在当前一代群体中位置
						  else
						      goto Vari2; // 变异位的值等于待变异位的当前值,跳转到Vari2,重新产生变异位变异后的值
					  }
                      nNextVari=nNextOBDLimit[2*nGACrossNum+d][nVariValue]+1;
                      if(nNextVari>nOBDLimit[nVariValue])
                      {   
						  VariLoop++;
						  if(VariLoop==100)// 跳转到Vari2重新产生变异位满50次,仍未满足约束条件2,
							  goto Vari1;  // 则跳转到Vair1,重新产生变异个体在当前一代群体中位置
						  else
						      goto Vari2;  // 变异后,不满足约束条件2,跳转到Vari2重新产生变异位
					  }
					  // 变异成功
                      *(NextGeneSerial[2*nGACrossNum+d]+h)=nVariValue;
                      nNextOBDLimit[2*nGACrossNum+d][nVariValue]++;
                      nNextOBDLimit[2*nGACrossNum+d][*(GeneSerial[nVariIndividual]+nVariPos)]--;
                   }
                   else
                      *(NextGeneSerial[2*nGACrossNum+d]+h)=*(GeneSerial[nVariIndividual]+h);
                }
           } 
           
           // 产生下一代群体
		   for(int e=0;e<2*nGACrossNum+nGAVariNum;e++)
           {
               for(int f=0;f<m_nONUNum;f++)
                   *(GeneSerial[m_nGroupSize-e-1]+f)=*(NextGeneSerial[e]+f);
               for(int x=0;x<m_nOBDNum;x++)
                   nCurOBDLimit[m_nGroupSize-e-1][x]=nNextOBDLimit[e][x];
           }
		   Sleep(m_SleepTime);
      }
}

// 产生1~100之间的随机整数
int COpticalNetworkDlg::RandomInt(int low,int high)
{
    int result;
	result=rand();
    return result%(high+1);
}

// 搜索最小F值
void COpticalNetworkDlg::FindMiniF(double *data,int len)
{
   double mini=data[0];
   int    mininum=0;
   int    CurOBDTemp;
   int    *GeneSerTemp;
   double datatemp;   
   for(int n=0;n<len;n++)
      if(mini>data[n])
      {
         mini=data[n];
         mininum=n;
      }
   if(mininum!=len-1)
   {
      datatemp=*(data+len-1);
      *(data+len-1)=*(data+mininum);
      *(data+mininum)=datatemp;
      GeneSerTemp=GeneSerial[len-1];
	  GeneSerial[len-1]=GeneSerial[mininum];
	  GeneSerial[mininum]=GeneSerTemp;	  
	  for(int n2=0;n2<m_nOBDNum;n2++)
	  {
		  CurOBDTemp=nCurOBDLimit[mininum][n2];
	      nCurOBDLimit[mininum][n2]=nCurOBDLimit[len-1][n2];
		  nCurOBDLimit[len-1][n2]=CurOBDTemp; 
	  }
   }
}

void COpticalNetworkDlg::DrawNetwork()
{
     int NetLeft,NetBottom;
	 int x_coordinate=0,y_coordinate=0;
	 char txt[4];
	 CString info;	 
	 CDC* pDC=GetDC();
     CRect RectClient,Workarea;
     GetClientRect(RectClient);
     Workarea.left=RectClient.left+RectClient.right/3-15;
     Workarea.right=RectClient.right;
     Workarea.top=RectClient.top;
     Workarea.bottom=RectClient.bottom;
     pDC->Rectangle(Workarea);
     pDC->SetBkColor(0x00FFFFFF);
	 NetLeft=Workarea.left+25;
	 NetBottom=Workarea.bottom-20;
	 pDC->MoveTo(NetLeft,NetBottom);
     pDC->LineTo(NetLeft+500,NetBottom);
	 pDC->MoveTo(NetLeft,NetBottom);
	 pDC->LineTo(NetLeft,NetBottom-500);	 
	 pDC->TextOut(NetLeft+500,NetBottom-12,"X");
	 pDC->TextOut(NetLeft+5,NetBottom-505,"Y");
	 pDC->SetTextColor(0x000000FF);
	 info.Format("已进化代数 %d",m_CurGANum+1);
	 pDC->TextOut(NetLeft+100,NetBottom-520,info);
	 info.Format("最小费用 %5.5f",m_MiniCost);
	 pDC->TextOut(NetLeft+250,NetBottom-520,info);
	 pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
	 for(x_coordinate=0;x_coordinate<=10;x_coordinate++)
	 {
	    char xn[4];
		wsprintf(xn,"%d",x_coordinate*10);
		pDC->TextOut(NetLeft+x_coordinate*50-8,NetBottom+2,xn);
	 }
	 for(y_coordinate=1;y_coordinate<=10;y_coordinate++)
	 {
	    char yn[4];
		wsprintf(yn,"%d",y_coordinate*10);
		if(y_coordinate==10)
		pDC->TextOut(NetLeft-24,NetBottom-y_coordinate*50,yn);
		else
		pDC->TextOut(NetLeft-22,NetBottom-y_coordinate*50,yn);
	 }

	 PtrOldPen=pDC->SelectObject(&PenOBD);
	 for(int b1=0;b1<m_nOBDNum;b1++)
	 {   
		 pDC->MoveTo(NetLeft+m_OBDX[b1]*5,NetBottom-m_OBDY[b1]*5);
		 pDC->LineTo(NetLeft+m_OLTX*5,NetBottom-m_OLTY*5);
	 }
	 for(int b2=0;b2<m_nONUNum;b2++)
	 {  
		 pDC->SelectObject(&PenONU[colornum]);
		 pDC->MoveTo(NetLeft+m_ONUX[b2]*5,NetBottom-m_ONUY[b2]*5);
		 pDC->LineTo(NetLeft+m_OBDX[*(GeneSerial[0]+b2)]*5,NetBottom-m_OBDY[*(GeneSerial[0]+b2)]*5);
		 colornum++;
		 if(colornum==16)
			colornum=0;		 
	 }
	 pDC->SelectObject(PtrOldPen);    
	 pDC->SetTextColor(0x000000FF);
	 pDC->TextOut(NetLeft+m_OLTX*5-7,NetBottom-m_OLTY*5-7,"★");
	 pDC->SetTextColor(0x00FF0000);
	 for(int a1=0;a1<m_nOBDNum;a1++)
	 {
		 wsprintf(txt,"%d",a1+1);
	     pDC->TextOut(NetLeft+m_OBDX[a1]*5-3,NetBottom-m_OBDY[a1]*5-9,txt);
	 }
	 pDC->SetTextColor(0x0000FF00);
	 for(int a2=0;a2<m_nONUNum;a2++)
	 {
         wsprintf(txt,"%d",a2+1);
         pDC->TextOut(NetLeft+m_ONUX[a2]*5-3,NetBottom-m_ONUY[a2]*5-9,txt);
	 }
	 pDC->SetTextColor(0x00FFFFFF);
	 pDC->TextOut(NetLeft+507,NetBottom-508,"c");
	 pDC->SetTextColor(GetSysColor(COLOR_WINDOWTEXT));
	 pDC->SetBkColor(GetSysColor(COLOR_WINDOW));
	 
}

void COpticalNetworkDlg::OnAbout() 
{
     CAboutDlg dlg;
     dlg.DoModal();
}

void COpticalNetworkDlg::OnOK() 
{
	CDialog::OnOK();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -