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

📄 symbreg.cc

📁 用C++编写的遗传算法
💻 CC
📖 第 1 页 / 共 2 页
字号:
      tout << "\\begin{eqnarray}" << endl;      // Print all ADF's, if any      GPGene* current;      for (int n=0; n<containerSize(); n++)	{	  if (n!=0)	    os << "\\\\" << endl;	  os << "f_" << n+1 << " & = & ";	  if ((current=NthGene (n)))	    os << *current;	  else	    os << " NONE";	  os << "\\nonumber ";	}      tout << endl << "\\end{eqnarray}" << endl << endl;          }  else    // Just call the print function of our base class to do the    // standard job.    GP::printOn (os);}// This function is the divide with closure. Basically if you divide// anything by zero you get an error so we have to stop this// process. We check for a very small denominator and return a very// high value.inline double divide (double x, double y){  if (fabs (y)<1e-6)    {      if (x*y<0.0) 	return -1e6;      else	return 1e6;    }  else    return x/y;}// We have the freedom to define this function in any way we like. In// this case, it takes the parameter x that represents the terminal X,// and returns the value of the expression. It's recursive of course.double MyGene::evaluate (double x, MyGP& gp, double arg0, double arg1){  double ret, a0, a1;  if (isFunction ())    switch (node->value ())      {      case '*': 	ret=NthMyChild(0)->evaluate (x, gp, arg0, arg1)	  * NthMyChild(1)->evaluate (x, gp, arg0, arg1);	break;      case '+': 	ret=NthMyChild(0)->evaluate (x, gp, arg0, arg1)	  + NthMyChild(1)->evaluate (x, gp, arg0, arg1);	break;      case '-': 	ret=NthMyChild(0)->evaluate (x, gp, arg0, arg1)	  - NthMyChild(1)->evaluate (x, gp, arg0, arg1);	break;      case '%': 	// We use the function divide rather than "/" to ensure the	// closure property	ret=divide (NthMyChild(0)->evaluate (x, gp, arg0, arg1), 		    NthMyChild(1)->evaluate (x, gp, arg0, arg1));	break;      case 'A': 	// This is the ADF0 function call.  We have access to that	// subtree, as the GP gave us a reference to itself as	// parameter.  We first evaluate the subtrees, and then call	// the adf with the parameters	a0=NthMyChild(0)->evaluate (x, gp, arg0, arg1);	a1=NthMyChild(1)->evaluate (x, gp, arg0, arg1);	ret=gp.NthMyGene(1)->evaluate (x, gp, a0, a1);	break;      default: 	GPExitSystem ("MyGene::evaluate", "Undefined function value");      }  if (isTerminal ())    switch (node->value ())      {      case 'X': 	ret=x;	break;      case 1:	ret=arg0;	break;      case 2:	ret=arg1;	break;      default: 	GPExitSystem ("MyGene::evaluate", "Undefined terminal value");      }  // Restrict the return value (it may become really large, especially  // for large trees)  const double maxValue=1e6;  if (ret>maxValue)    return maxValue;  if (ret<-maxValue)    return -maxValue;  return ret;}// Evaluate the fitness of a GP and save it into the GP class variable// stdFitness.void MyGP::evaluate (){  double rawfitness=0.0, diff=0.0;  // The evaluation function checks with some values of the  // mathematical function  for (int i=0; i<DATAPOINTS; i++)    {      // Calculate genetic programs answer.  ques[i] is the current x      // value of the function.      double result=NthMyGene(0)->evaluate (ques[i], *this, 0, 0);      // Calculate square error between the genetic program and the      // actual answer.      diff=pow (answ[i]-result, 2);      // Add this difference to total rawfitness      rawfitness+=diff;    }  rawfitness=sqrt (rawfitness);  // We want a short solution and put the total GP length to the  // fitness.  As we know that the best solution has the length 12, we  // create such a formula that the fitness will be 1.0 in this case.  // This standardized fitness is saved in the GP object.  stdFitness=rawfitness+(double)length ()/12.0;}// Create function and terminal setvoid createNodeSet (GPAdfNodeSet& adfNs){  // Reserve space for the node sets  adfNs.reserveSpace (2);  // Now define the function and terminal set for each ADF and place  // function/terminal sets into overall ADF container  GPNodeSet& ns0=*new GPNodeSet (6);  GPNodeSet& ns1=*new GPNodeSet (4);  adfNs.put (0, ns0);  adfNs.put (1, ns1);  // Define functions/terminals and place them into the appropriate  // sets. Terminals take two arguments, functions three (the third  // parameter is the number of arguments the function has)  ns0.putNode (*new GPNode ('+', "+", 2));  ns0.putNode (*new GPNode ('-', "-", 2));  ns0.putNode (*new GPNode ('*', "*", 2));  ns0.putNode (*new GPNode ('%', "%", 2));  ns0.putNode (*new GPNode ('A', "ADF0", 2));  ns0.putNode (*new GPNode ('X', "x"));  ns1.putNode (*new GPNode ('+', "+", 2));  ns1.putNode (*new GPNode ('*', "*", 2));  ns1.putNode (*new GPNode (1, "x1"));  ns1.putNode (*new GPNode (2, "x2"));}void newHandler (){  cerr << "\nFatal error: Out of memory." << endl;  exit (1);}int main (){  // We set up a new-handler, because we might need a lot of memory,  // and we don't know it's there.  set_new_handler (newHandler);  // Set up the array with data points. This is for the evaluation  // process.  for (int i=0; i<DATAPOINTS; i++)    {      ques[i]=i;      answ[i]=EQUATION(ques[i]);    }  // Init GP system.  GPInit (1, -1);  // Declare the GP Variables, set defaults and read configuration  // file.  The defaults will be overwritten by the configuration file  // when read.  If it doesn't exist, the defaults will be written to  // the file.  GPConfiguration config (cout, "symbreg.ini", configArray);  // Open the main output file for data and statistics file. First set  // up names for data file. We use also a TeX-file where the  // equations are written to in TeX-style. Very nice to look at!  // Remember we should delete the string from the stream, well just a  // few bytes  ostrstream strOutFile, strStatFile, strTeXFile;  strOutFile  << InfoFileName << ".dat" << ends;  strStatFile << InfoFileName << ".stc" << ends;  strTeXFile  << InfoFileName << ".tex" << ends;  ofstream fout (strOutFile.str());  ofstream bout (strStatFile.str());  tout.open (strTeXFile.str(), ios::out);  tout << endl       << "\\documentstyle[a4]{article}" << endl       << "\\begin{document}" << endl;    // Print the configuration to the files just opened  fout << cfg << endl;  cout << cfg << endl;  tout << "\\begin{verbatim}\n" << cfg << "\\end{verbatim}\n" << endl;    // Create the adf function/terminal set and print it out.  GPAdfNodeSet adfNs;  createNodeSet (adfNs);  cout << adfNs << endl;   fout << adfNs << endl;    // Create a population with this configuration  cout << "Creating initial population ..." << endl;  MyPopulation* pop=new MyPopulation (cfg, adfNs);  pop->create ();  cout << "Ok." << endl;  pop->createGenerationReport (1, 0, fout, bout);  // Print the best of generation to the LaTeX-file.  printTexStyle=1;  tout << *pop->NthGP (pop->bestOfPopulation);  printTexStyle=0;  // This next for statement is the actual genetic programming system  // which is in essence just repeated reproduction and crossover loop  // through all the generations .....  MyPopulation* newPop=NULL;  for (int gen=1; gen<=cfg.NumberOfGenerations; gen++)    {      // Create a new generation from the old one by applying the      // genetic operators      if (!cfg.SteadyState)	newPop=new MyPopulation (cfg, adfNs);      pop->generate (*newPop);            // Delete the old generation and make the new the old one      if (!cfg.SteadyState)	{	  delete pop;	  pop=newPop;	}      // Print the best of generation to the LaTeX-file.      printTexStyle=1;      tout << "Generation " << gen << ", fitness " 	   << pop->NthGP (pop->bestOfPopulation)->getFitness()	   << endl;      tout << *pop->NthGP (pop->bestOfPopulation);      printTexStyle=0;      // Create a report of this generation and how well it is doing      pop->createGenerationReport (0, gen, fout, bout);    }  // TeX-file: end of document  tout << endl       << "\\end{document}"       << endl;  tout.close ();  cout << "\nResults are in "        << InfoFileName << ".dat,"        << InfoFileName << ".tex,"       << InfoFileName << ".stc." << endl;  return 0;}

⌨️ 快捷键说明

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