📄 gabase.pas
字号:
unit GABase;{Developed by Shu Jun, 2000/6/24, PMI, NCEPU}{TGABase is a abstract class. You must Derivate a sub_class from it. You mustoverride abstract function calculateFitness. By the way, this class can onlyget minimum solution} interfaceuses Dialogs,Sysutils;type CIndividual = record IntegerSection: array of integer; FloatSection: array of double; IsSurvival: boolean;//在选择中存活的个体, 不被交叉和变异 IsProtected: boolean;//受保护的个体不被且不参与交叉和变异, //用于专家控制和优化群体复制. Fitness: double; end; CISectionLimit = record UpperLimit: integer; LowerLimit: integer; end; CFSectionLimit = record UpperLimit: double; LowerLimit: double; end; TGABase = class(TObject) private MaxJudge :Boolean; //True—最大值,False—最小值 Temp_Population: array of CIndividual; ISectionLimit : array of CISectionLimit; FSectionLimit : array of CFSectionLimit; IntegerNum : integer; FloatNum : integer; MutationRatio : double; CrossOverRatio : double; Generations : integer; NSurvivors : integer; CurrentGen : integer; procedure SetRandom; function RandVal(ALow, AUp: integer): integer; overload; function RandVal(ALow, AUp: double): double; overload; function FindCanCopyed: integer; procedure SelectFace2Face; //遗传 procedure EquablyCrossOver; //交叉 procedure Mutation; virtual; //变异 public Population: array of CIndividual; constructor Create; destructor Destroy;override; procedure IniData(AINum, AFNum: integer; AIUp, AILow: array of integer; AFUp, AFLow: array of double); procedure IniParameter(Max:Boolean = False; AGens: integer = 200; APop: integer = 60; AMutionR: double = 0.01; ACrossOverR: double = 0.5); procedure Calculate(ACurGen: integer); virtual; procedure CopyData(var ADes: CIndividual; ASrc: CIndividual); protected PopSize: integer; procedure CalculateFitness; virtual; abstract; end; implementation{ TGABase }uses math;constructor TGABase.Create;begin SetRandom();end;destructor TGABase.Destroy;begin Population := nil; Temp_Population := nil;end;procedure TGABase.IniData(AINum, AFNum: integer; AIUp, AILow: array of integer; AFUp, AFLow: array of double);var I, J: integer;begin SetRandom(); IntegerNum := AINum; FloatNum := AFNum; SetLength(ISectionLimit, AINum); SetLength(FSectionLimit, AFNum); for I := 0 to AINum - 1 do begin ISectionLimit[I].UpperLimit := AIUp[I]; ISectionLimit[I].LowerLimit := AILow[I]; end;//for for I := 0 to AFNum - 1 do begin FSectionLimit[I].UpperLimit := AFUp[I]; FSectionLimit[I].LowerLimit := AFLow[I]; end; SetLength(Population, PopSize + 1); SetLength(Temp_Population, PopSize + 1); for I := 0 to PopSize do begin SetLength(Population[I].IntegerSection, AINum); SetLength(Population[I].FloatSection, AFNum); SetLength(Temp_Population[I].IntegerSection, AINum); SetLength(Temp_Population[I].FloatSection, AFNum); Population[I].IsProtected := false; for J := 0 to AINum - 1 do Population[I].IntegerSection[J] := RandVal(ISectionLimit[J].LowerLimit, ISectionLimit[J].UpperLimit); for J := 0 to AFNum - 1 do Population[I].FloatSection[J] := RandVal(FSectionLimit[J].LowerLimit, FSectionLimit[J].UpperLimit); end;//for Population[PopSize].Fitness := 10E100;end;procedure TGABase.IniParameter(Max:Boolean;AGens, APop: integer; AMutionR, ACrossOverR: double);begin MaxJudge:=Max; Generations := AGens; PopSize := APop; MutationRatio := AMutionR; CrossOverRatio := ACrossOverR;end;procedure TGABase.SetRandom;begin RandSeed := 0;end;function TGABase.RandVal(ALow, AUp: integer): integer;var Num: integer;begin Num := AUp - ALow; result := ALow + random(Num + 1);end;function TGABase.RandVal(ALow, AUp: double): double;var Temp: double;begin Temp := AUp - ALow; result := ALow + random * Temp;end;procedure TGABase.SelectFace2Face;var I, FirstMem, SecondMem, Winner: integer;begin //如果最优解失去,拷贝一份 I := 0; while (I < PopSize) and ((Population[I].IsProtected = true) or (Population[I].Fitness <> Population[PopSize].Fitness)) do I := I + 1; if I = PopSize then begin FirstMem := FindCanCopyed; CopyData(Population[FirstMem], Population[PopSize]) end; //选择好个体进入Temp_Population, 保留的最好个体与受保护个体不参与竞争 for I := 0 to PopSize - 1 do begin FirstMem := Random(PopSize); while Population[FirstMem].IsProtected = true do FirstMem := Random(PopSize); SecondMem := Random(PopSize); while Population[SecondMem].IsProtected = true do SecondMem := Random(PopSize); if MaxJudge then //求最大值 begin if Population[FirstMem].Fitness>Population[SecondMem].Fitness then Winner :=FirstMem else Winner :=SecondMem; end else begin //求最小值 if Population[FirstMem].Fitness<Population[SecondMem].Fitness then Winner :=FirstMem else Winner :=SecondMem; end; CopyData(Temp_Population[I], Population[Winner]); end;//for //将Temp_Population考入Population,保证Population中受保护的个体不被覆盖 for I := 0 to PopSize - 1 do begin if Population[I].IsProtected = false then begin CopyData(Population[I], Temp_Population[I]); end;//if end;//for NSurvivors := 0; for I := 0 to PopSize - 1 do if CrossOverRatio < Random then begin Population[I].IsSurvival := true; NSurvivors := NSurvivors + 1; end else Population[I].IsSurvival := false; Population[Popsize].IsSurvival := true;end;procedure TGABase.EquablyCrossOver;var I, J, a, b, POne, PTwo, Count: integer;begin{ for I := 0 to PopSize - 1 do begin if random(2) = 0 then Population[I].IsSurvival := true else Population[I].IsSurvival := false; end;} for I := 0 to PopSize - 1 do begin POne := 0; PTwo := 0; if Population[I].IsSurvival = false then begin a := random(NSurvivors + 1); b := random(NSurvivors + 1); Count := 0; for J := 0 to PopSize - 1 do begin if (Population[J].IsSurvival = true) and (Population[J].IsProtected = false) then begin Count := Count + 1; if Count = a then POne := J; if Count = b then PTwo := J; end;//if end;//for for J := 0 to IntegerNum - 1 do begin if random(2) = 0 then Population[I].IntegerSection[J] := Population[POne].IntegerSection[J] else Population[I].IntegerSection[J] := Population[PTwo].IntegerSection[J]; end;//for for J := 0 to FloatNum - 1 do begin if random(2) = 0 then Population[I].FloatSection[J] := Population[POne].FloatSection[J] else Population[I].FloatSection[J] := Population[PTwo].FloatSection[J]; end;//for end;//if end;//forend;procedure TGABase.Mutation;var I, MutationNum, Member, Point: integer;begin MutationNum := Round(PopSize * (IntegerNum + FloatNum) * MutationRatio); I := 0; while I < MutationNum do begin Member := Random(PopSize); if Population[Member].IsProtected <> true then begin if IntegerNum > 0 then begin Point := Random(IntegerNum); if Random(2) = 0 then begin Population[Member].IntegerSection[Point] := RandVal(ISectionLimit[Point].LowerLimit, Population[Member].IntegerSection[Point]); end else begin Population[Member].IntegerSection[Point] := RandVal(Population[Member].IntegerSection[Point], ISectionLimit[Point].UpperLimit); end;//if end;//if if FloatNum > 0 then begin Point := Random(FloatNum); if Random(2) = 0 then begin Population[Member].FloatSection[Point] := RandVal(FSectionLimit[Point].LowerLimit, Population[Member].FloatSection[Point]); end else begin Population[Member].FloatSection[Point] := RandVal(Population[Member].FloatSection[Point], FSectionLimit[Point].UpperLimit); end;//if end;//if I := I + 1; end;//if end;//whileend;function TGABase.FindCanCopyed: integer;var Member: integer;begin Member := Random(PopSize); while Population[Member].IsProtected = true do Member := Random(PopSize); if Member < PopSize then result := Member else result := -1;end;procedure TGABase.Calculate(ACurGen: integer);begin CurrentGen := ACurGen; if CurrentGen < Generations then begin CalculateFitness; if CurrentGen = Generations - 1 then exit; SelectFace2Face; EquablyCrossOver; Mutation; end;end;procedure TGABase.CopyData(var ADes: CIndividual; ASrc: CIndividual);var I: integer;begin for I := 0 to IntegerNum - 1 do ADes.IntegerSection[I] := ASrc.IntegerSection[I]; for I := 0 to FloatNum - 1 do ADes.FloatSection[I] := ASrc.FloatSection[I]; ADes.IsSurvival := ASrc.IsSurvival; ADes.IsProtected := ASrc.IsProtected; ADes.Fitness := ASrc.Fitness;end;end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -