一、题目要求
将一段用C语言实现的求解下列方程:
f(x1,x2,x3)=x1^2-x1*x2+x3
在给定区间的最大值的遗传算法程序改成C#程序。要求:
(1)、数据从文件读入,结果输出到另一文件;
(2) 实现多线程。
二、原C语言代码
以下是李老师提供的原C语言代码,我根据自己的理解添加了一些自己人为较为重要的注释。
/******************************************************************** /* This is a simple genetic algorithm implementation where the */ /* evaluation function takes positive values only and the */ /* fitness of an individual is the same as the value of the */ /* objective function */ /*******************************************************************/ #include <stdio.h> #include <stdlib.h> #include <math.h> /* Change any of these parameters to match your needs */ #define POPSIZE 50 /* population size */ #define MAXGENS 1000 /* max. number of generations */ #define NVARS 3 /* no. of problem variables */ #define PXOVER 0.8 /* probability of crossover */ #define PMUTATION 0.15 /* probability of mutation */ #define TRUE 1 #define FALSE 0 int generation; /* current generation no. */ int cur_best; /* best individual */ FILE *galog; /* an output file */ struct genotype /* genotype (GT), a member of the population */ { double gene[NVARS]; /* a string of variables */ double fitness; /* GT's fitness */ double upper[NVARS]; /* GT's variables upper bound */ double lower[NVARS]; /* GT's variables lower bound */ double rfitness; /* relative fitness */ double cfitness; /* cumulative fitness */ }; struct genotype population[POPSIZE+1]; /* population */ struct genotype newpopulation[POPSIZE+1]; /* new population; */ /* replaces the */ /* old generation */ /* Declaration of procedures used by this genetic algorithm */ void initialize(void); double randval(double, double); void evaluate(void); void keep_the_best(void); void elitist(void);//优秀人才,精英主义 void select(void); void crossover(void); void Xover(int,int); void swap(double *, double *); void mutate(void); void report(void); /***************************************************************/ /* Initialization function: Initializes the values of genes */ /* within the variables bounds. It also initializes (to zero) */ /* all fitness values for each member of the population. It */ /* reads upper and lower bounds of each variable from the */ /* input file `gadata.txt'. It randomly generates values */ /* between these bounds for each gene of each genotype in the */ /////////////////////////////////////////////////////////////////////////////////// /* population. The format of the input file gadata.txt' is */ /* var1_lower_bound var1_upper bound */ /* var2_lower_bound var2_upper bound ... */ /***************************************************************/ void initialize(void) { FILE *infile; int i, j; double lbound, ubound; if ((infile = fopen("gadata.txt","r"))==NULL) { fprintf(galog,"/nCannot open input file!/n"); exit(1); } /* initialize variables within the bounds */ for (i = 0; i < NVARS; i++) { fscanf(infile, "%lf",&lbound); fscanf(infile, "%lf",&ubound); for (j = 0; j < POPSIZE; j++) { population[j].fitness = 0; population[j].rfitness = 0; population[j].cfitness = 0; population[j].lower[i] = lbound; population[j].upper[i]= ubound; population[j].gene[i] = randval(population[j].lower[i], population[j].upper[i]); } } fclose(infile); } /***********************************************************/ /* Random value generator: Generates a value within bounds */ /***********************************************************/ double randval(double low, double high) { double val; val = ((double)(rand()%1000)/1000.0)*(high - low) + low; // val = ((double)(rand()%(1000+1))/1000.0)*(high - low) + low; return(val); } /*************************************************************/ /* Evaluation function: This takes a user defined function. */ /* Each time this is changed, the code has to be recompiled. */ ///////////////////////////////////////////////////////////////////////////// /* The current function is: x[1]^2-x[1]*x[2]+x[3] */ /*************************************************************/ void evaluate(void) { int mem; int i; double x[NVARS+1]; for (mem = 0; mem < POPSIZE; mem++) { for (i = 0; i < NVARS; i++) x[i+1] = population[mem].gene[i]; population[mem].fitness = (x[1]*x[1]) - (x[1]*x[2]) + x[3]; } } /***************************************************************/ /* Keep_the_best function: This function keeps track of the */ /* best member of the population. Note that the last entry in */ /* the array Population holds a copy of the best individual */ /***************************************************************/ void keep_the_best() { int mem; int i; cur_best = 0; /* stores the index of the best individual */ for (mem = 0; mem < POPSIZE; mem++) { if (population[mem].fitness > population[POPSIZE].fitness) { cur_best = mem; population[POPSIZE].fitness = population[mem].fitness; } } /* once the best member in the population is found, copy the genes */ for (i = 0; i < NVARS; i++) population[POPSIZE].gene[i] = population[cur_best].gene[i]; } /****************************************************************/ /* Elitist function: The best member of the previous generation */ /* is stored as the last in the array. If the best member of */ /* the current generation is worse then the best member of the */ /* previous generation, the latter one would replace the worst */ /* member of the current population */ /****************************************************************/ void elitist() { int i; double best, worst; /* best and worst fitness values */ int best_mem, worst_mem; /* indexes of the best and worst member */ best = population[0].fitness; worst = population[0].fitness; for (i = 0; i < POPSIZE - 1; ++i) { if(population[i].fitness > population[i+1].fitness) { if (population[i].fitness >= best) { best = population[i].fitness; best_mem = i; } if (population[i+1].fitness <= worst) { worst = population[i+1].fitness; worst_mem = i + 1; } } else { if (population[i].fitness <= worst) { worst = population[i].fitness; worst_mem = i; } if (population[i+1].fitness >= best) { best = population[i+1].fitness; best_mem = i + 1; } } } /* if best individual from the new population is better than */ /* the best individual from the previous population, then */ /* copy the best from the new population; else replace the */ /* worst individual from the current population with the */ /* best one from the previous generation */ if (best >= population[POPSIZE].fitness) { for (i = 0; i < NVARS; i++) population[POPSIZE].gene[i] = population[best_mem].gene[i]; population[POPSIZE].fitness = population[best_mem].fitness; } else { for (i = 0; i < NVARS; i++) population[worst_mem].gene[i] = population[POPSIZE].gene[i]; population[worst_mem].fitness = population[POPSIZE].fitness; } } /**************************************************************/ /* Selection function: Standard proportional selection for */ /* maximization problems incorporating elitist model - makes */ /* sure that the best member survives */ /**************************************************************/ void select(void) { int mem, i, j, k; double sum = 0; double p; /* find total fitness of the population */ for (mem = 0; mem < POPSIZE; mem++) { sum += population[mem].fitness; } /* calculate relative fitness */ for (mem = 0; mem < POPSIZE; mem++) { population[mem].rfitness = population[mem].fitness/sum; } population[0].cfitness = population[0].rfitness; /* calculate cumulative fitness */ for (mem = 1; mem < POPSIZE; mem++) { population[mem].cfitness = population[mem-1].cfitness + population[mem].rfitness; } /* finally select survivors using cumulative fitness. */ for (i = 0; i < POPSIZE; i++) { p = rand()%1000/1000.0; if (p < population[0].cfitness) newpopulation[i] = population[0]; else { for (j = 0; j < POPSIZE;j++) if (p >= population[j].cfitness && p<population[j+1].cfitness) newpopulation[i] = population[j+1]; } } /* once a new population is created, copy it back */ for (i = 0; i < POPSIZE; i++) population[i] = newpopulation[i]; } /***************************************************************/ /* Crossover selection: selects two parents that take part in */ /* the crossover. Implements a single point crossover */ /***************************************************************/ void crossover(void) { int i, mem, one; int first = 0; /* count of the number of members chosen */ double x; for (mem = 0; mem < POPSIZE; ++mem) { x = rand()%1000/1000.0; if (x < PXOVER) { ++first; if (first % 2 == 0) Xover(one, mem); else one = mem; } } } /**************************************************************/ /* Crossover: performs crossover of the two selected parents. */ /**************************************************************/ void Xover(int one, int two) { int i; int point; /* crossover point */ /* select crossover point */ if(NVARS > 1) { if(NVARS == 2) point = 1; else point = (rand() % (NVARS - 1)) + 1; for (i = 0; i < point; i++) swap(&population[one].gene[i], &population[two].gene[i]); } } /*************************************************************/ /* Swap: A swap procedure that helps in swapping 2 variables */ /*************************************************************/ void swap(double *x, double *y) { double temp; temp = *x; *x = *y; *y = temp; } /**************************************************************/ /* Mutation: Random uniform mutation. A variable selected for */ /* mutation is replaced by a random value between lower and */ /* upper bounds of this variable */ /**************************************************************/ void mutate(void) { int i, j; double lbound, hbound; double x; for (i = 0; i < POPSIZE; i++) for (j = 0; j < NVARS; j++) { x = rand()%1000/1000.0; if (x < PMUTATION) { /* find the bounds on the variable to be mutated */ lbound = population[i].lower[j]; hbound = population[i].upper[j]; population[i].gene[j] = randval(lbound, hbound); } } } /***************************************************************/ /* Report function: Reports progress of the simulation. Data */ /* dumped into the output file are separated by commas */ /***************************************************************/ void report(void) { int i; double best_val; /* best population fitness */ double avg; /* avg population fitness */ double stddev; /* std. deviation of population fitness */ double sum_square; /* sum of square for std. calc */ double square_sum; /* square of sum for std. calc */ double sum; /* total population fitness */ sum = 0.0; sum_square = 0.0; for (i = 0; i < POPSIZE; i++) { sum += population[i].fitness; sum_square += population[i].fitness * population[i].fitness; } avg = sum/(double)POPSIZE; square_sum = avg * avg * POPSIZE; stddev = sqrt((sum_square - square_sum)/(POPSIZE - 1)); best_val = population[POPSIZE].fitness; fprintf(galog, "\n%5d, %6.3f, %6.3f, %6.3f %6.3f, %6.3f\n\n", generation,best_val, avg, square_sum,sum_square,stddev); } /**************************************************************/ /* Main function: Each generation involves selecting the best */ /* members, performing crossover & mutation and then */ /* evaluating the resulting population, until the terminating */ /* condition is satisfied */ /**************************************************************/ void main(void) { int i; if ((galog = fopen("galog.txt","w"))==NULL) { exit(1); } generation = 0; fprintf(galog, "\n generation best average standard \n"); fprintf(galog, " number value fitness deviation \n"); initialize(); evaluate(); keep_the_best(); while(generation<MAXGENS) { generation++; select(); crossover(); mutate(); report(); evaluate(); elitist(); } fprintf(galog,"\n\n Simulation completed\n"); fprintf(galog,"\n Best member: \n"); for (i = 0; i < NVARS; i++) { fprintf (galog,"\n var(%d) = %3.3f",i,population[POPSIZE].gene[i]); } fprintf(galog,"\n\n Best fitness = %3.3f",population[POPSIZE].fitness); fclose(galog); printf("Success\n"); }
三、我的C#代码
//Chrosome.cs文件 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace myCWindowsProgram { class Chrosome { private const int NVARS = 3; private double PMUTATION; private double[] gene = new double[NVARS]; private double[] upper = new double[NVARS]; private double[] lower = new double[NVARS]; private double fitness; private double rFitness; private double cFitness; private Random myRandom; public Chrosome(double tempPMUTATION) { PMUTATION = tempPMUTATION; myRandom = new Random(unchecked((int)DateTime.Now.Ticks)); } public double Fitness { get { return fitness; } set { fitness = value; } } public double RFitness { get { return rFitness; } set { rFitness = value; } } public double CFitness { get { return cFitness; } set { cFitness = value; } } public double GetIOneGen(int id) { return this.gene[id]; } public void SetIOneGen(int id,double tempGen) { this.gene[id] = tempGen; } public double GetIOneLower(int id) { return this.lower[id]; } public void SetIOneLower(int id, double tempLower) { this.lower[id] = tempLower; } public double GetIOneUpper(int id) { return this.upper[id]; } public void SetIOneUpper(int id, double tempUpper) { this.upper[id] = tempUpper; } /********************************************************* * 参数:分别表示上下界 * 返回值:doule * 功能:产生介于[low,high)的随机数 * *********************************************************/ public double RandValue(double low, double high) { double val; val = (double)myRandom.Next(0, 1000); val = val / 1000.0 * (high - low) + low; return val; } /********************************************************* * 参数:无 * 返回值:无 * 功能:单个染色体变异 * *********************************************************/ public void ChrosomeMution() { double lbound, hbound,x; for (int i = 0; i < NVARS; i++) { x = myRandom.Next(0, 1000) / 1000.0; if (x < PMUTATION) { lbound = this.lower[i]; hbound = this.upper[i]; this.SetIOneGen(i, RandValue(lbound, hbound)); } } } /********************************************************* * 参数:无 * 返回值:无 * 功能:单个染色体评价适应度 * *********************************************************/ public void ChrosomeEvaluate() { double[] x = new double[NVARS + 1]; for (int i = 0; i < NVARS; i++) x[i + 1] = this.GetIOneGen(i); this.fitness = (x[1] * x[1]) - (x[1] * x[2]) + x[3]; } /********************************************************* * 参数:模板基因染色体 * 返回值:无 * 功能:复制染色体基因 * *********************************************************/ public void CopyAllGene(Chrosome tempChrosome) { for (int i = 0; i < NVARS; i++) this.gene[i] = tempChrosome.GetIOneGen(i); } /********************************************************* * 参数:模板基因染色体 * 返回值:无 * 功能:复制整个染色体 * *********************************************************/ public void CopyChrosome(Chrosome tempChrosome) { for (int i = 0; i < NVARS; i++) this.gene[i] = tempChrosome.GetIOneGen(i); for (int i = 0; i < NVARS; i++) this.upper[i] = tempChrosome.GetIOneUpper(i); for (int i = 0; i < NVARS; i++) this.lower[i] = tempChrosome.GetIOneLower(i); this.fitness = tempChrosome.Fitness; this.rFitness = tempChrosome.RFitness; this.cFitness = tempChrosome.CFitness; } } } //Population.cs文件 using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; namespace myCWindowsProgram { class Population {//PDF265 private int POPSIZE; private int MAXGENS; private double PXOVER; private double PMUTATION; private const int NVARS = 3; private int generation; private int curBest; private Chrosome[] myChrosome; private Chrosome[] newChrosome; private Random myRandom; private bool isFirstWrite; private string readerPath; private const string writePath = @"C:\Users\Chrome\Desktop\myCWindowsProgram\myCWindowsProgram\Write.txt"; private const string resultPath = @"C:\Users\Chrome\Desktop\myCWindowsProgram\myCWindowsProgram\Result.txt"; private MyWindows myWindows; private double[] lbound; private double[] ubound; /********************************************************* * 参数:无 * 返回值:无 * 功能:读入待处理数据集 * *********************************************************/ public void ReadDataSet() { int i = 0; lbound=new double[NVARS]; ubound = new double[NVARS]; using (StreamReader sr = new StreamReader(readerPath)) { string line; while ((line = sr.ReadLine()) != null) { string[] strcol = line.Split(new char[] { ' ' }); lbound[i] = Convert.ToDouble(strcol[0]); ubound[i] = Convert.ToDouble(strcol[1]); i++; } sr.Close(); } } /********************************************************* * 参数:分别别表示种群规模、迭代次数、种群交叉率、基因变异率、窗口句柄 * 返回值:无 * 功能:初始化种群 * *********************************************************/ public Population(int tempPOPSIZE, int tempMAXGENS, double tempPXOVER, double tempPMUTATION, string tempReaderPath, MyWindows tempMyWindows) { POPSIZE=tempPOPSIZE; MAXGENS=tempMAXGENS; PXOVER=tempPXOVER; PMUTATION = tempPMUTATION; readerPath=tempReaderPath; myWindows = tempMyWindows; isFirstWrite = true; myRandom = new Random(unchecked((int)DateTime.Now.Ticks)); myChrosome=new Chrosome[POPSIZE+1]; newChrosome = new Chrosome[POPSIZE + 1]; ReadDataSet(); for (int i = 0; i <= POPSIZE; i++) { myChrosome[i] = new Chrosome(PMUTATION); newChrosome[i] = new Chrosome(PMUTATION); } for (int i = 0; i < NVARS; i++) { for (int j = 0; j < POPSIZE; j++) { myChrosome[j].Fitness = 0; myChrosome[j].RFitness = 0; myChrosome[j].CFitness = 0; myChrosome[j].SetIOneLower(i,lbound[i]); myChrosome[j].SetIOneUpper(i, ubound[i]); myChrosome[j].SetIOneGen(i,myChrosome[j].RandValue( myChrosome[j].GetIOneLower(i),myChrosome[j].GetIOneUpper(i))); } } } /********************************************************* * 参数:无 * 返回值:无 * 功能:评价当前种群每个个体的适应度 * *********************************************************/ public void PopulationEvaluate() { for (int i = 0; i < POPSIZE; i++) myChrosome[i].ChrosomeEvaluate(); } /********************************************************* * 参数:无 * 返回值:无 * 功能:精英主义(选择当前种群适应度最好个体存活下来) * *********************************************************/ public void PopulationKeepTheBest() { curBest = 0; for (int i = 0; i < POPSIZE; i++) { if (myChrosome[i].Fitness > myChrosome[POPSIZE].Fitness) { curBest = i; myChrosome[POPSIZE].Fitness = myChrosome[i].Fitness; } } myChrosome[POPSIZE].CopyAllGene(myChrosome[curBest]); } /********************************************************* * 参数:无 * 返回值:无 * 功能:遗传算子-精英主义操作(保留最好个体,淘汰最坏个体) * *********************************************************/ public void PopulationElitist() { double best, worst; int bestMem=0, worstMem=0; best = myChrosome[0].Fitness; worst = myChrosome[0].Fitness; for (int i = 0; i < POPSIZE - 1; ++i) { if (myChrosome[i].Fitness> myChrosome[i + 1].Fitness) { if (myChrosome[i].Fitness >= best) { best = myChrosome[i].Fitness; bestMem= i; } if (myChrosome[i + 1].Fitness <= worst) { worst = myChrosome[i + 1].Fitness; worstMem = i + 1; } } else { if (myChrosome[i].Fitness <= worst) { worst = myChrosome[i].Fitness; worstMem= i; } if (myChrosome[i + 1].Fitness>= best) { best = myChrosome[i + 1].Fitness; bestMem= i + 1; } } } if (best >= myChrosome[POPSIZE].Fitness) { myChrosome[POPSIZE].CopyAllGene(myChrosome[bestMem]); myChrosome[POPSIZE].Fitness = myChrosome[bestMem].Fitness; } else { myChrosome[worstMem].CopyAllGene(myChrosome[POPSIZE]); myChrosome[worstMem].Fitness = myChrosome[POPSIZE].Fitness; } } /********************************************************* * 参数:无 * 返回值:无 * 功能:遗传算子-选择操作(采用轮盘赌方法选择适应度较高个体) * *********************************************************/ public void PopulationSelect() { double sum = 0; for (int i = 0; i < POPSIZE;i++) { sum += myChrosome[i].Fitness; } for (int i = 0; i < POPSIZE; i++) { myChrosome[i].RFitness = myChrosome[i].Fitness/ sum; } myChrosome[0].CFitness= myChrosome[0].RFitness; for (int i = 1; i < POPSIZE; i++) { myChrosome[i].CFitness = myChrosome[i - 1].CFitness + myChrosome[i].RFitness; } for (int i = 0; i < POPSIZE; i++) { int val = (int)myRandom.Next(0, 1000); double p = val % 1000 / 1000.0; if (p < myChrosome[0].CFitness) newChrosome[i].CopyChrosome(myChrosome[0]); else { for (int j = 0; j < POPSIZE; j++) if (p >= myChrosome[j].CFitness && p < myChrosome[j + 1].CFitness) newChrosome[i].CopyChrosome(myChrosome[j + 1]); } } for (int i = 0; i < POPSIZE; i++) myChrosome[i].CopyChrosome(newChrosome[i]); } /********************************************************* * 参数:one,two代表两个带交叉的染色体 * 返回值:无 * 功能:交叉子操作(交换两染色体部分基因) * *********************************************************/ public void PopulationXover(int one, int two) { int point; if (NVARS > 1) { if (NVARS == 2) point = 1; else point = ((int)myRandom.Next(0, NVARS - 1)) + 1; for (int i = 0; i < point; i++) { double temp = myChrosome[one].GetIOneGen(i); myChrosome[one].SetIOneGen(i, myChrosome[two].GetIOneGen(i)); myChrosome[two].SetIOneGen(i, temp); } } } /********************************************************* * 参数:无 * 返回值:无 * 功能:遗传算子-交叉操作(依概率选择染色体杂交) * *********************************************************/ public void PopulationCrossover() { int i, mem, one=-1; int first = 0; double x; for (mem = 0; mem < POPSIZE; ++mem) { x =myRandom.Next(0, 1000)/1000.0; if (x < PXOVER) { ++first; if (first % 2 == 0) PopulationXover(one, mem); else one = mem; } } } /********************************************************* * 参数:无 * 返回值:无 * 功能:遗传算子-变异操作(基因变异) * *********************************************************/ public void PopulationMutate() { for (int i = 0; i < POPSIZE; i++) { myChrosome[i].ChrosomeMution(); } } /********************************************************* * 参数:无 * 返回值:无 * 功能:打印当前种群适应度信息 * *********************************************************/ public void PopulationReport() { double bestVal, avg, stddev, sumSquare,squareSum,sum; sum = 0.0; sumSquare = 0.0; for (int i = 0; i < POPSIZE; i++) { sum += myChrosome[i].Fitness; sumSquare += myChrosome[i].Fitness * myChrosome[i].Fitness; } avg = sum/(double)POPSIZE; squareSum = avg * avg * POPSIZE; stddev = Math.Sqrt((sumSquare - squareSum) /(double) (POPSIZE - 1)); bestVal = myChrosome[POPSIZE].Fitness; try { //保证在第一次读写时覆盖上个数据集的处理结果,同时保证当前结果累加输到文件末尾 if (isFirstWrite) //保证当前结果累加输到文件末尾 using (StreamWriter br = new StreamWriter(writePath, false)) { br.WriteLine("generation best average standard"); br.WriteLine("number value fitness deviation"); br.WriteLine("{0}, {1}, {2}, {3}", generation, bestVal, avg, stddev); br.Close(); } else //保证在第一次读写时覆盖上个数据集的处理结果 using (StreamWriter br = new StreamWriter(writePath, true)) { br.WriteLine("{0}, {1}, {2}, {3}", generation, bestVal, avg, stddev); br.Close(); } this.myWindows.setList(bestVal, 2); this.myWindows.setList(avg, 3); this.myWindows.setList(sumSquare, 4); this.myWindows.setList(squareSum, 5); this.myWindows.setList(stddev, 6); this.myWindows.setList(myChrosome[POPSIZE].GetIOneGen(0), 7); this.myWindows.setList(myChrosome[POPSIZE].GetIOneGen(1), 8); this.myWindows.setList(myChrosome[POPSIZE].GetIOneGen(2), 9); if (isFirstWrite) isFirstWrite = false; } catch (EndOfStreamException e) { Console.WriteLine(e.Message); Console.WriteLine("已经读到末尾"); } } /********************************************************* * 参数:无 * 返回值:无 * 功能:遗传算法主框架程序 * *********************************************************/ public void GeneticAlgorithm() { DateTime starttime = DateTime.Now; TimeSpan timespan; this.generation = 0; this.myWindows.setProgressBar(0, MAXGENS); this.myWindows.setList(1.0*this.generation,1); this.PopulationEvaluate(); this.PopulationKeepTheBest(); while (this.generation < MAXGENS) { this.generation++; this.PopulationSelect(); this.PopulationCrossover(); this.PopulationMutate(); this.PopulationReport(); this.PopulationEvaluate(); this.PopulationElitist(); this.myWindows.setProgressBar(this.generation, MAXGENS); this.myWindows.setList(1.0*this.generation, 1); } //显示最优解 try { using (StreamWriter br = new StreamWriter(writePath, true)) { br.WriteLine(); br.WriteLine(); br.WriteLine(); br.WriteLine("Simulation completed"); br.WriteLine("Best member: "); for (int i = 0; i < NVARS; i++) { br.WriteLine("var({0}) ={1} ", i, myChrosome[POPSIZE].GetIOneGen(i)); } br.WriteLine(" Best fitness = {0}", myChrosome[POPSIZE].Fitness); timespan = DateTime.Now.Subtract(starttime);//获取就是开始时间很结束时间差 string diff = timespan.TotalSeconds.ToString(); br.WriteLine("the total time of program :{0} Seconds", diff); br.Close(); } } catch (EndOfStreamException e) { Console.WriteLine(e.Message); Console.WriteLine("已经读到末尾"); } //显示计算时间 try { using (StreamWriter br = new StreamWriter(resultPath, true)) { br.WriteLine("geration={0} Best fitness = {1}", MAXGENS,myChrosome[POPSIZE].Fitness); timespan = DateTime.Now.Subtract(starttime);//获取就是开始时间很结束时间差 string diff = timespan.TotalSeconds.ToString(); br.WriteLine("the total time of program :{0} Seconds", diff); br.WriteLine(); br.WriteLine(); br.WriteLine(); br.Close(); } } catch (EndOfStreamException e) { Console.WriteLine(e.Message); Console.WriteLine("已经读到末尾"); } } } } //MyWindows.Designer.cs文件 namespace myCWindowsProgram { partial class MyWindows { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.label1 = new System.Windows.Forms.Label(); this.textBox1 = new System.Windows.Forms.TextBox(); this.label2 = new System.Windows.Forms.Label(); this.textBox2 = new System.Windows.Forms.TextBox(); this.label3 = new System.Windows.Forms.Label(); this.textBox3 = new System.Windows.Forms.TextBox(); this.label4 = new System.Windows.Forms.Label(); this.label5 = new System.Windows.Forms.Label(); this.label6 = new System.Windows.Forms.Label(); this.textBox4 = new System.Windows.Forms.TextBox(); this.textBox5 = new System.Windows.Forms.TextBox(); this.textBox6 = new System.Windows.Forms.TextBox(); this.button1 = new System.Windows.Forms.Button(); this.button2 = new System.Windows.Forms.Button(); this.button3 = new System.Windows.Forms.Button(); this.label7 = new System.Windows.Forms.Label(); this.label8 = new System.Windows.Forms.Label(); this.label9 = new System.Windows.Forms.Label(); this.label10 = new System.Windows.Forms.Label(); this.label11 = new System.Windows.Forms.Label(); this.textBox7 = new System.Windows.Forms.TextBox(); this.textBox8 = new System.Windows.Forms.TextBox(); this.textBox9 = new System.Windows.Forms.TextBox(); this.textBox10 = new System.Windows.Forms.TextBox(); this.progressBar1 = new System.Windows.Forms.ProgressBar(); this.label12 = new System.Windows.Forms.Label(); this.button4 = new System.Windows.Forms.Button(); this.label13 = new System.Windows.Forms.Label(); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.textBox13 = new System.Windows.Forms.TextBox(); this.textBox12 = new System.Windows.Forms.TextBox(); this.textBox11 = new System.Windows.Forms.TextBox(); this.label16 = new System.Windows.Forms.Label(); this.label15 = new System.Windows.Forms.Label(); this.label14 = new System.Windows.Forms.Label(); this.groupBox2 = new System.Windows.Forms.GroupBox(); this.groupBox3 = new System.Windows.Forms.GroupBox(); this.comboBox1 = new System.Windows.Forms.ComboBox(); this.label17 = new System.Windows.Forms.Label(); this.groupBox1.SuspendLayout(); this.groupBox2.SuspendLayout(); this.groupBox3.SuspendLayout(); this.SuspendLayout(); // // label1 // this.label1.AutoSize = true; this.label1.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label1.ForeColor = System.Drawing.SystemColors.InactiveCaptionText; this.label1.Location = new System.Drawing.Point(12, 31); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(65, 20); this.label1.TabIndex = 0; this.label1.Text = "当前代数"; // // textBox1 // this.textBox1.Location = new System.Drawing.Point(109, 25); this.textBox1.Multiline = true; this.textBox1.Name = "textBox1"; this.textBox1.Size = new System.Drawing.Size(100, 21); this.textBox1.TabIndex = 1; // // label2 // this.label2.AutoSize = true; this.label2.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label2.ForeColor = System.Drawing.SystemColors.InactiveCaptionText; this.label2.Location = new System.Drawing.Point(241, 28); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(79, 20); this.label2.TabIndex = 2; this.label2.Text = "当前最优解"; // // textBox2 // this.textBox2.Location = new System.Drawing.Point(357, 20); this.textBox2.Name = "textBox2"; this.textBox2.Size = new System.Drawing.Size(100, 26); this.textBox2.TabIndex = 3; // // label3 // this.label3.AutoSize = true; this.label3.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label3.ForeColor = System.Drawing.SystemColors.InactiveCaptionText; this.label3.Location = new System.Drawing.Point(479, 26); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(107, 20); this.label3.TabIndex = 4; this.label3.Text = "当前平均适应度"; // // textBox3 // this.textBox3.Location = new System.Drawing.Point(620, 25); this.textBox3.Name = "textBox3"; this.textBox3.Size = new System.Drawing.Size(113, 26); this.textBox3.TabIndex = 5; // // label4 // this.label4.AutoSize = true; this.label4.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label4.ForeColor = System.Drawing.SystemColors.InactiveCaptionText; this.label4.Location = new System.Drawing.Point(12, 81); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(79, 20); this.label4.TabIndex = 6; this.label4.Text = "当前平方和"; // // label5 // this.label5.AutoSize = true; this.label5.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label5.ForeColor = System.Drawing.SystemColors.InactiveCaptionText; this.label5.Location = new System.Drawing.Point(241, 81); this.label5.Name = "label5"; this.label5.Size = new System.Drawing.Size(93, 20); this.label5.TabIndex = 7; this.label5.Text = "当前和的平方"; // // label6 // this.label6.AutoSize = true; this.label6.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label6.Location = new System.Drawing.Point(479, 78); this.label6.Name = "label6"; this.label6.Size = new System.Drawing.Size(65, 20); this.label6.TabIndex = 8; this.label6.Text = "当前方差"; // // textBox4 // this.textBox4.Location = new System.Drawing.Point(109, 78); this.textBox4.Name = "textBox4"; this.textBox4.Size = new System.Drawing.Size(100, 26); this.textBox4.TabIndex = 9; // // textBox5 // this.textBox5.Location = new System.Drawing.Point(357, 78); this.textBox5.Name = "textBox5"; this.textBox5.Size = new System.Drawing.Size(100, 26); this.textBox5.TabIndex = 10; // // textBox6 // this.textBox6.Location = new System.Drawing.Point(620, 75); this.textBox6.Name = "textBox6"; this.textBox6.Size = new System.Drawing.Size(113, 26); this.textBox6.TabIndex = 11; // // button1 // this.button1.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.button1.Location = new System.Drawing.Point(16, 168); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(251, 34); this.button1.TabIndex = 12; this.button1.Text = "开始"; this.button1.UseVisualStyleBackColor = true; this.button1.Click += new System.EventHandler(this.button1_Click); // // button2 // this.button2.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.button2.Location = new System.Drawing.Point(16, 187); this.button2.Name = "button2"; this.button2.Size = new System.Drawing.Size(251, 34); this.button2.TabIndex = 13; this.button2.Text = "暂停"; this.button2.UseVisualStyleBackColor = true; this.button2.Click += new System.EventHandler(this.button2_Click); // // button3 // this.button3.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.button3.Location = new System.Drawing.Point(465, 168); this.button3.Name = "button3"; this.button3.Size = new System.Drawing.Size(268, 34); this.button3.TabIndex = 14; this.button3.Text = "退出"; this.button3.UseVisualStyleBackColor = true; this.button3.Click += new System.EventHandler(this.button3_Click); // // label7 // this.label7.AutoSize = true; this.label7.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label7.Location = new System.Drawing.Point(12, 38); this.label7.Name = "label7"; this.label7.Size = new System.Drawing.Size(79, 20); this.label7.TabIndex = 15; this.label7.Text = "种群个体数"; // // label8 // this.label8.AutoSize = true; this.label8.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label8.Location = new System.Drawing.Point(451, 38); this.label8.Name = "label8"; this.label8.Size = new System.Drawing.Size(93, 20); this.label8.TabIndex = 16; this.label8.Text = "种群迭代次数"; // // label9 // this.label9.AutoSize = true; this.label9.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label9.Location = new System.Drawing.Point(391, 300); this.label9.Name = "label9"; this.label9.Size = new System.Drawing.Size(0, 20); this.label9.TabIndex = 17; // // label10 // this.label10.AutoSize = true; this.label10.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label10.Location = new System.Drawing.Point(12, 82); this.label10.Name = "label10"; this.label10.Size = new System.Drawing.Size(79, 20); this.label10.TabIndex = 18; this.label10.Text = "种群变异率"; // // label11 // this.label11.AutoSize = true; this.label11.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label11.Location = new System.Drawing.Point(451, 73); this.label11.Name = "label11"; this.label11.Size = new System.Drawing.Size(79, 20); this.label11.TabIndex = 19; this.label11.Text = "种群交叉率"; // // textBox7 // this.textBox7.Location = new System.Drawing.Point(97, 32); this.textBox7.Name = "textBox7"; this.textBox7.Size = new System.Drawing.Size(135, 26); this.textBox7.TabIndex = 20; // // textBox8 // this.textBox8.Location = new System.Drawing.Point(591, 35); this.textBox8.Name = "textBox8"; this.textBox8.Size = new System.Drawing.Size(142, 26); this.textBox8.TabIndex = 21; // // textBox9 // this.textBox9.Location = new System.Drawing.Point(97, 76); this.textBox9.Name = "textBox9"; this.textBox9.Size = new System.Drawing.Size(135, 26); this.textBox9.TabIndex = 22; // // textBox10 // this.textBox10.Location = new System.Drawing.Point(591, 73); this.textBox10.Name = "textBox10"; this.textBox10.Size = new System.Drawing.Size(142, 26); this.textBox10.TabIndex = 23; // // progressBar1 // this.progressBar1.Location = new System.Drawing.Point(109, 144); this.progressBar1.Name = "progressBar1"; this.progressBar1.Size = new System.Drawing.Size(533, 23); this.progressBar1.TabIndex = 24; // // label12 // this.label12.AutoSize = true; this.label12.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label12.Location = new System.Drawing.Point(12, 147); this.label12.Name = "label12"; this.label12.Size = new System.Drawing.Size(65, 20); this.label12.TabIndex = 25; this.label12.Text = "当前进度"; // // button4 // this.button4.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.button4.Location = new System.Drawing.Point(465, 187); this.button4.Name = "button4"; this.button4.Size = new System.Drawing.Size(268, 34); this.button4.TabIndex = 26; this.button4.Text = "继续"; this.button4.UseVisualStyleBackColor = true; this.button4.Click += new System.EventHandler(this.button4_Click); // // label13 // this.label13.AutoSize = true; this.label13.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label13.Location = new System.Drawing.Point(677, 144); this.label13.Name = "label13"; this.label13.Size = new System.Drawing.Size(56, 20); this.label13.TabIndex = 27; this.label13.Text = "0.000%"; // // groupBox1 // this.groupBox1.Controls.Add(this.textBox13); this.groupBox1.Controls.Add(this.textBox12); this.groupBox1.Controls.Add(this.textBox11); this.groupBox1.Controls.Add(this.label16); this.groupBox1.Controls.Add(this.label15); this.groupBox1.Controls.Add(this.label14); this.groupBox1.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.groupBox1.Location = new System.Drawing.Point(42, 510); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(761, 107); this.groupBox1.TabIndex = 28; this.groupBox1.TabStop = false; this.groupBox1.Text = "当前迭代次数下最优解对应各变量取值区"; // // textBox13 // this.textBox13.Location = new System.Drawing.Point(620, 49); this.textBox13.Name = "textBox13"; this.textBox13.Size = new System.Drawing.Size(113, 26); this.textBox13.TabIndex = 34; // // textBox12 // this.textBox12.Location = new System.Drawing.Point(353, 49); this.textBox12.Name = "textBox12"; this.textBox12.Size = new System.Drawing.Size(100, 26); this.textBox12.TabIndex = 33; // // textBox11 // this.textBox11.Location = new System.Drawing.Point(109, 49); this.textBox11.Name = "textBox11"; this.textBox11.Size = new System.Drawing.Size(100, 26); this.textBox11.TabIndex = 32; // // label16 // this.label16.AutoSize = true; this.label16.Location = new System.Drawing.Point(492, 55); this.label16.Name = "label16"; this.label16.Size = new System.Drawing.Size(52, 20); this.label16.TabIndex = 31; this.label16.Text = "x3取值"; // // label15 // this.label15.AutoSize = true; this.label15.Location = new System.Drawing.Point(241, 55); this.label15.Name = "label15"; this.label15.Size = new System.Drawing.Size(52, 20); this.label15.TabIndex = 30; this.label15.Text = "x2取值"; // // label14 // this.label14.AutoSize = true; this.label14.Location = new System.Drawing.Point(12, 52); this.label14.Name = "label14"; this.label14.Size = new System.Drawing.Size(52, 20); this.label14.TabIndex = 29; this.label14.Text = "x1取值"; // // groupBox2 // this.groupBox2.Controls.Add(this.label1); this.groupBox2.Controls.Add(this.textBox1); this.groupBox2.Controls.Add(this.button4); this.groupBox2.Controls.Add(this.label13); this.groupBox2.Controls.Add(this.label2); this.groupBox2.Controls.Add(this.textBox2); this.groupBox2.Controls.Add(this.label12); this.groupBox2.Controls.Add(this.label3); this.groupBox2.Controls.Add(this.progressBar1); this.groupBox2.Controls.Add(this.textBox3); this.groupBox2.Controls.Add(this.label4); this.groupBox2.Controls.Add(this.textBox4); this.groupBox2.Controls.Add(this.label5); this.groupBox2.Controls.Add(this.textBox5); this.groupBox2.Controls.Add(this.button2); this.groupBox2.Controls.Add(this.label6); this.groupBox2.Controls.Add(this.textBox6); this.groupBox2.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.groupBox2.Location = new System.Drawing.Point(42, 254); this.groupBox2.Name = "groupBox2"; this.groupBox2.Size = new System.Drawing.Size(761, 237); this.groupBox2.TabIndex = 29; this.groupBox2.TabStop = false; this.groupBox2.Text = "当前迭代次数下种群信息区"; // // groupBox3 // this.groupBox3.Controls.Add(this.comboBox1); this.groupBox3.Controls.Add(this.label17); this.groupBox3.Controls.Add(this.label7); this.groupBox3.Controls.Add(this.textBox7); this.groupBox3.Controls.Add(this.label8); this.groupBox3.Controls.Add(this.label10); this.groupBox3.Controls.Add(this.textBox9); this.groupBox3.Controls.Add(this.textBox10); this.groupBox3.Controls.Add(this.textBox8); this.groupBox3.Controls.Add(this.button1); this.groupBox3.Controls.Add(this.label11); this.groupBox3.Controls.Add(this.button3); this.groupBox3.Font = new System.Drawing.Font("Microsoft YaHei", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.groupBox3.Location = new System.Drawing.Point(42, 12); this.groupBox3.Name = "groupBox3"; this.groupBox3.Size = new System.Drawing.Size(761, 224); this.groupBox3.TabIndex = 30; this.groupBox3.TabStop = false; this.groupBox3.Text = "设置种群初始信息区"; // // comboBox1 // this.comboBox1.FormattingEnabled = true; this.comboBox1.Items.AddRange(new object[] { "C:\\Users\\Chrome\\Desktop\\myCWindowsProgram\\myCWindowsProgram\\DataSet_One.txt", "C:\\Users\\Chrome\\Desktop\\myCWindowsProgram\\myCWindowsProgram\\DataSet_Two.txt", "C:\\Users\\Chrome\\Desktop\\myCWindowsProgram\\myCWindowsProgram\\DataSet_Three.txt"}); this.comboBox1.Location = new System.Drawing.Point(97, 121); this.comboBox1.Name = "comboBox1"; this.comboBox1.Size = new System.Drawing.Size(636, 28); this.comboBox1.TabIndex = 25; // // label17 // this.label17.AutoSize = true; this.label17.Location = new System.Drawing.Point(12, 129); this.label17.Name = "label17"; this.label17.Size = new System.Drawing.Size(79, 20); this.label17.TabIndex = 24; this.label17.Text = "导入数据集"; // // MyWindows // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(834, 639); this.Controls.Add(this.groupBox3); this.Controls.Add(this.groupBox2); this.Controls.Add(this.groupBox1); this.Controls.Add(this.label9); this.ForeColor = System.Drawing.SystemColors.InactiveCaptionText; this.Name = "MyWindows"; this.Text = "遗传算法求解函数最大值C#应用程序"; this.Load += new System.EventHandler(this.MyWindows_Load); this.groupBox1.ResumeLayout(false); this.groupBox1.PerformLayout(); this.groupBox2.ResumeLayout(false); this.groupBox2.PerformLayout(); this.groupBox3.ResumeLayout(false); this.groupBox3.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.Label label1; private System.Windows.Forms.TextBox textBox1; private System.Windows.Forms.Label label2; private System.Windows.Forms.TextBox textBox2; private System.Windows.Forms.Label label3; private System.Windows.Forms.TextBox textBox3; private System.Windows.Forms.Label label4; private System.Windows.Forms.Label label5; private System.Windows.Forms.Label label6; private System.Windows.Forms.TextBox textBox4; private System.Windows.Forms.TextBox textBox5; private System.Windows.Forms.TextBox textBox6; private System.Windows.Forms.Button button1; private System.Windows.Forms.Button button2; private System.Windows.Forms.Button button3; private System.Windows.Forms.Label label7; private System.Windows.Forms.Label label8; private System.Windows.Forms.Label label9; private System.Windows.Forms.Label label10; private System.Windows.Forms.Label label11; private System.Windows.Forms.TextBox textBox7; private System.Windows.Forms.TextBox textBox8; private System.Windows.Forms.TextBox textBox9; private System.Windows.Forms.TextBox textBox10; private System.Windows.Forms.ProgressBar progressBar1; private System.Windows.Forms.Label label12; private System.Windows.Forms.Button button4; private System.Windows.Forms.Label label13; private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.TextBox textBox13; private System.Windows.Forms.TextBox textBox12; private System.Windows.Forms.TextBox textBox11; private System.Windows.Forms.Label label16; private System.Windows.Forms.Label label15; private System.Windows.Forms.Label label14; private System.Windows.Forms.GroupBox groupBox2; private System.Windows.Forms.GroupBox groupBox3; private System.Windows.Forms.ComboBox comboBox1; private System.Windows.Forms.Label label17; } } //MyWindows.cs文件 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Threading; namespace myCWindowsProgram { public partial class MyWindows : Form { private Thread myThread;//遗传算法对应线程 public MyWindows() { InitializeComponent(); } /************************************************ * 参数:分别表示当前进度与总进度 * 返回值:无 * 功能:完成进程框的设定 * ***********************************************/ public delegate void setProgressInvoke(int num,int MAXGENS); public void setProgressBar(int num,int MAXGENS) { if (this.InvokeRequired) { setProgressInvoke _setInvoke = new setProgressInvoke(setProgressBar); this.Invoke(_setInvoke, new object[] { num ,MAXGENS}); } else { label13.Text =Math.Round((100.0 * num / MAXGENS), 3).ToString("f1")+"%"; progressBar1.Value =(int)((int)((1.0*num/ MAXGENS)*100)%(100+1)); } } /************************************************ * 参数:分别表示文本框待显示的值与对应文本框归属 * 返回值:无 * 功能:完成6个文本框的设定 * ***********************************************/ public delegate void setListInvoke(double val, int flag); public void setList(double val, int flag) { if (this.InvokeRequired) { setListInvoke _setInvoke = new setListInvoke(setList); this.Invoke(_setInvoke, new object[] { val, flag }); } else { switch (flag) { case 1: textBox1.Text = val.ToString(); break; case 2: textBox2.Text = Math.Round(val, 8).ToString("f8"); break; case 3: textBox3.Text = Math.Round(val, 8).ToString("f8"); break; case 4: textBox4.Text = Math.Round(val, 8).ToString("f8"); break; case 5: textBox5.Text = Math.Round(val, 8).ToString("f8"); break; case 6: textBox6.Text = Math.Round(val, 8).ToString("f8"); break; case 7: textBox11.Text = Math.Round(val, 8).ToString("f8"); break; case 8: textBox12.Text = Math.Round(val, 8).ToString("f8"); break; case 9: textBox13.Text = Math.Round(val, 8).ToString("f8"); break; default: break; } } } /************************************************ *“开始”按钮 * ***********************************************/ private void button1_Click(object sender, EventArgs e) { //组合框为空,未选择数据集,重新选择 if (comboBox1.Text == "") { MessageBox.Show("请选择数据集!"); return; } //当前线程未结束,直接结束该线程 if (null != myThread) myThread.Abort(); Population myPopulation = new Population(Convert.ToInt32(textBox7.Text), Convert.ToInt32(textBox8.Text), Convert.ToDouble(textBox10.Text), Convert.ToDouble(textBox9.Text), comboBox1.Text, this); myThread = new Thread(myPopulation.GeneticAlgorithm); myThread.Start(); } /************************************************ *“暂停”按钮 * ***********************************************/ private void button2_Click(object sender, EventArgs e) { if (null == myThread) { MessageBox.Show("请确认程序正在运行!"); return; } myThread.Suspend(); } /************************************************ *“退出”按钮 * ***********************************************/ private void button3_Click(object sender, EventArgs e) { MessageBox.Show("你按了退出键"); //当前线程未结束,直接结束该线程 if (null != myThread) myThread.Abort(); Application.Exit(); } /************************************************ *“继续”按钮 * ***********************************************/ private void button4_Click(object sender, EventArgs e) { //保证当前线程处在挂起状态 if (ThreadState.Suspended == myThread.ThreadState) myThread.Resume(); else { MessageBox.Show("请确认当前程序处于暂停状态!"); } } /************************************************ *初始化窗口 * ***********************************************/ private void MyWindows_Load(object sender, EventArgs e) { this.textBox7.Text = "100"; this.textBox8.Text = "10000"; this.textBox9.Text = "0.15"; this.textBox10.Text = "0.80"; } } } //Program.cs文件 using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; namespace myCWindowsProgram { static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MyWindows()); } } }
四、运行结果分析
上面是程序最终跑出的结果,当然文件Result.txt中也有,截图
五、我的特色
根据题目特点,我的C#程序总体架构为有用户界面的运用遗传算法求解函数f(x1,x2,x3)=x1^2-x1*x2+x3最大值的应用程序。作为一名即将步入职场的软件开发者,准确说是奋战在编程一线的程序员—码农。由于之前做ACM,程序要求简单高效,所以总是在用C语言或者说是放弃对象的C++进行面向过程编程,近来我一改以往编程风格,转而尝试使用面向对象技术,当然这也是C#语言的特点之一。
1.特色一:C#特色语言知识的运用
1.1属性的使用:
属性是C#不同于C/C++、Java的特色功能,属性的值是对象相应的状态值。属性体现了类的封装性:不直接访问类的数据成员而是通过访问器来访问。属性通常两个函数:获取属性值的get,和设置属性值的set。我的理解是属性的引入可以完成对私有字段的访问,同时在访问的过程中检测类型或完成其他一些工作。下面是我尝试使用的属性:
public double Fitness { get { return fitness; } set { fitness = value; } } public double RFitness { get { return rFitness; } set { rFitness = value; } } public double CFitness { get { return cFitness; } set { cFitness = value; } } 其中fitness、rFitness、cFitness本是private型的,为了安全的对其进行访问,引入属性。
1.2委托:
在C/C++中回调函数其实是通过引入指向函数的指针来实现的,这种方法直接操作内存,但不是安全的。在C#中, 引入了委托的概念。委托是一种特殊的数据类型,它引用一个或多个方法,这些方法对应C/C++中的回调函数,委托是类型安全的,可以将方法作为参数传递,可用于定义回调方法,可以连接在一起。委托通常与触发它的事件联系在一起。事件是指当类或对象状态发生变化时,通过其他的类或对象所引发的事情。事件并不是C#中的新名词,在此不展开。如果要使用事件,就要使用委托,事件是个特殊的签名的委托,可以从发行类中调用。我的程序做了可视化界面,往往要监听控件的变化,于是我很自然地尝试委托和事件。我的程序有进程条,我设置了委托完成类似函调函数的功能:
/************************************************ * 参数:分别表示当前进度与总进度 * 返回值:无 * 功能:完成进程框的设定 * ***********************************************/ public delegate void setProgressInvoke(int num,int MAXGENS); public void setProgressBar(int num,int MAXGENS) { if (this.InvokeRequired) { setProgressInvoke _setInvoke = new setProgressInvoke(setProgressBar); this.Invoke(_setInvoke, new object[] { num ,MAXGENS}); } else { label13.Text =Math.Round((100.0 * num / MAXGENS), 3).ToString("f1")+"%"; progressBar1.Value =(int)((int)((1.0*num/ MAXGENS)*100)%(100+1)); } } /************************************************ * 参数:分别表示文本框待显示的值与对应文本框归属 * 返回值:无 * 功能:完成6个文本框的设定 * ***********************************************/ public delegate void setListInvoke(double val, int flag); public void setList(double val, int flag) { if (this.InvokeRequired) { setListInvoke _setInvoke = new setListInvoke(setList); this.Invoke(_setInvoke, new object[] { val, flag }); } else { switch (flag) { case 1: textBox1.Text = val.ToString(); break; case 2: textBox2.Text = Math.Round(val, 8).ToString("f8"); break; case 3: textBox3.Text = Math.Round(val, 8).ToString("f8"); break; case 4: textBox4.Text = Math.Round(val, 8).ToString("f8"); break; case 5: textBox5.Text = Math.Round(val, 8).ToString("f8"); break; case 6: textBox6.Text = Math.Round(val, 8).ToString("f8"); break; case 7: textBox11.Text = Math.Round(val, 8).ToString("f8"); break; case 8: textBox12.Text = Math.Round(val, 8).ToString("f8"); break; case 9: textBox13.Text = Math.Round(val, 8).ToString("f8"); break; default: break; } } }
2.特色二:模块化
C#是面向对象的语言,在进行本次C#程序的编写时我将自己的程序分成了3个相对独立的功能模块,并将他们加以抽象封装成3各类,分别是染色体类、种群类、窗口类,从而很好的保证的程序模块的低耦合、高内聚的特点,从而提高程序的可读性、可扩展性、扩维护性。
2.1染色体类
完成单个个体即染色体的字段、属性、接口的设定,如单个染色体变异、单个染色体适应度评价等;
2.2种群类
聚合染色体模拟自然界的演化规律。完成种群的相关遗传算子:选择、交叉、变异等。总的来说是算法的核心与框架。
2.3窗口类
具体与算法设计无关,只是为了直观的呈现给用户一个可视化的界面,这样也是我第一次尝试在C#下做界面。完成当前代数、当前最好适应度、当前平方和、当前方差等的实时显示。
3.特色三:多线程的引入
首先我谈谈对多线程的理解。提起线程,就不得不说进程。程序关于某个数据集在处理机上的一次执行过程。而线程是进程的某个执行路径。一个进程可能有多个执行路径,每个线程仅是其中的一条。
关于多线程,如果是多台计算机分布式计算,则可通过多线程完全实现真正意义上的并行计算;如果是单台计算机,但是有多个CPU,通过多线程也可实现真正意义上的并行计算;如果是我们普通的计算机-单机单CPU单核,即使在计算的时候使用多线程我认为也是不能够实现真正意义上的并行的。
在本题中,演化计算中的遗传算法在计算部分几乎全部资源就是CPU计算,但就计算而言,单机单CPU单核引入多线程我认为是没有多大意义的。因为都只用CPU计算,即使线程挂起也是在等待空闲的CPU时间,引入多线程相互穿插的执行,或者单线程直接顺序执行,是没有改善的。
如上图,在遗传计算中都要用CPU,且都只用CPU,当然内存读取时间很短在此忽略。线程越多,分的越细(在实际中一个线程并不是以下执行完的,上图只是示意图),同等CPU时间内完成的计算任务不可能提高,而且反而会大幅降低。因为CPU在不同线程之中切换需要CPU时间、需要系统资源。单核CPU上运行的多线程程序, 同一时间只能一个线程在跑, 系统帮你切换线程而已, 系统给每个线程分配时间片来执行, 每个时间片大概10ms左右,
看起来像是同时跑, 但实际上是每个线程跑一点点就换到其它线程继续跑效率不会有提高的切换线程反倒会增加开销。
3.1、分组+多线程=失败
我首先写了个将当前代数下种群分成更小的子种群,子种群分别独立完成交叉、变异、选择等操作,然后从中提取更好的。看似可以多线程实现并行计算,实则效率会大幅降低,原因如上分析。
3.2、磁盘读写与演化计算并行+多线程=困难+低效
在分组失败后,我尝试结合操作系统中的知识,将同一进程下IO操作(在此程序中为最开始从文件gadata.txt读入初始边界,以及后面将当前迭代次数下最好结果写入文件galog.txt,为典型的磁盘读写)与CPU计算分别写成一个线程,然后分别执行。
这样理论上是可行的。但是问题很大。
(1)、在读入文件gadata.txt中全部内容之前,种群的初始信息不全面,不能执行CPU计算,此处多线程会导致程序出错。
(2)、在写入文件galog.txt时执行CPU计算,这是理论可行的。但得不偿失。因为李老师的给的C语言程序只要求将当前最好个体信息输出(还有其他的),
generation、best、average、standard number value fitness 、deviation
总的来说写入到文件的内容少。对应时间几乎可以忽略。试想一下在如此短暂地时间内CPU能做什么事?况且引入多线程后系统开销增加,可能效率不增反降。如果每次输出很多,尝试多线程是必要的,因为长时间等待IO操作而挂起CPU计算是不划算的,此时可以让其他线程来执行CPU计算,本进程继续负责IO操作,二者所占计算机资源不同,完全可以并行执行。
当用多线程时,运用多线程各自独立分管计算是不会改善效率的而会降低效率。当既要CPU计算,又有IO操作时,可以尝试多线程。但要注意数据冲突,即保证正确的读写次序。当涉及既要读某段数据又来写时,如果控制不合理,会导致错误。例如,当前IO操作要输出最好的个体myChrosome[POPSIZE],但我们知道IO操作都比较慢而CPU计算是很快的,此时可能经过CPU计算后myChrosome[POPSIZE]被赋予了新值,从而导致输出出错。这就是操作系统中的读者-写者问题,涉及到互斥与同步,这在本题是很复杂的。本题输出较少,对应时间几乎可以忽略,从而完全可以不用多线程。
3.3、遗传算子+盲目多线程=错误
在本题的遗传操作 GeneticAlgorithm()中,主要有以下算子:
<span style="font-family:Verdana;font-size:14px;">this.PopulationSelect(); this.PopulationCrossover(); this.PopulationMutate(); this.PopulationReport(); this.PopulationEvaluate(); this.PopulationElitist();</span>
如果直接将上面的函数分别置于不同的线程中,肯定是错误的。上面的函数本应该由时序关系的,即是顺序执行的。直接多线程会导致穿插执行,完全打乱执行流程,使得当前myChrosome[j]中染色体的所处的迭代次数、当前迭代次数下计算状态完全不一致,导致灾难后果。这样的做法错误的根本原因是根本没有考虑互斥与同步,盲目引入多线程,对多线程的适用场合和本质完全不清楚。
3.4、主线程+有关窗口的线程=正确
我的程序做了可视化界面,关于遗传算法的实现没有多线程,但窗口的刷新涉及多线程,程序中至少存在主线程与有关窗口的线程,如在主线程中有:
Application.Run(new MyWindows())
4.特色四:窗口界面的设计
学习一门语言,最主要的是灵活运用。要用所学的语言多编程、做些实用软件,而编写实用软件很重要的是完成人机交互,良好的用户体验至关重要。所以,我认为可视化界面是很关键的。而且,可视化界面掌握或尝试使用一门语言的体现。我的程序就做了个可视化界面,将输出到文件的数据同时也显示到窗口对应的文本中,并提供进程条、原始数据选择目录等。下面贴几张图:
上面button提供出错处理,保证程序的健壮性。如保证点击“继续”按钮唤醒当前线程之前必须保证当前线程处于挂起状态,即点击过“暂停”按钮,否则直接返回等。
在添加控件的过程中,发现C和VS比VC方便多了,以后的多用VS,多用更加现代的IDE。
六、编程中遇到的困难及解决方案
由于本次课程报告在非编程言语方面几乎没有难度(只是改改),所以编程中遇到的困难并不多。在做本次报告之前,也就是课下写了几个C#小程序加之2次实习,在写报告时遇到了一些语言方面的小问题、小bug,但经过debug,都能很快解决。下面我就总结一下遇到的问题以及解决方案。
1.数组元素出现空引用
在初始化种群时,我用了
myChrosome=new Chrosome[POPSIZE+1];
上面声明,可是运行程序时出错了。经过查看出错提示,我明白了Chrosome是自定义对象,上述只是声明并创建了数组,并没有给具体的每个元素myChrosome[i]分配内存空间,从而导致myChrosome=null,进而引发错误。
在C#中是很少用指针的,引用很大程度上替代了指针。在C#中定义数组、某种类库中的对象、自定义对象等都是声明该类型的引用,并未分配实际存储空间,此时必须通过 new操作符来完成相关初始化工作。
2.深拷贝与浅拷贝
在遗传操作-选择算子时我直接复制稍加修改用了李老师的代码
myChrosome[]=newChrosome[] ;
结果发现myChrosome[]中改变的数据会影响newChrosome[]中的数据,在C/C++中是不允许这样的(不能对数组赋值,可以声明指针来完成相关的操作)。经过断点调试,我发现myChrosome、newChrosome是共用同一内存区,两个都只是数组引用。上述语句是浅拷贝,即不另外开辟存储空间存放副本,二者共用同一内存区;而我要的是深拷贝,即另外开辟存储空间存放副本,二者不共用内存区,于是我编写函数完成了相同功能。代码如下:
<span style="font-family:Verdana;font-size:14px;"> for(int i = 0; i < POPSIZE ; i++) myChrosome[i].CopyChrosome(newChrosome[i]);</span>
在编程工程中还遇到了其它困难,但都是具体语言知识使用方面的,如怎样按给定格式从文件中读书数据等(在网上完全可以找到),不具有总结价值,在此就不再赘言。
以上是我C#作业,由于初学,可能问题很多,欢迎斧正!源码点击此处C#源码。