Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Генетические алгоритмы

Автор: Mystic
WEB-сайт: http://delphibase.endimus.com

{ **** UBPFD *********** by delphibase.endimus.com ****
>> Генетические алгоритмы

Класс, реализующий генетический алгоритм.

Зависимости: Classes, SysUtils, Windows, Math
Автор:       Mystic, mystic2000@newmail.ru, ICQ:125905046, Харьков
Copyright:   Mystic
Дата:        25 апреля 2002 г.
***************************************************** }

unit Genes;

interface

uses {Fuzzy,}  Classes, SysUtils, Windows, Math;

type
  TGeneAlgorithm = class;
  TExtendedArray = array of Extended;

  TEstimateEvent = procedure(Sender: TObject; const X: TExtendedArray; var Y:
    Extended) of object;
  TIterationEvent = procedure(Sender: TObject; Iteration: Integer);
  TBestChangeEvent = procedure(Sender: TObject; BestEstimate: Extended);

  EGeneError = class(Exception)
  end;

  TCardinalArray = array of Cardinal;
  TGeneRecord = record
    Bits: TCardinalArray;
    Values: TExtendedArray;
    Estimate: Extended;
  end;
  TGeneRecords = array of TGeneRecord;

  TSolutionThread = class(TThread)
  private
    FOwner: TGeneAlgorithm;
  protected
    procedure Execute; override;
    property Owner: TGeneAlgorithm read FOwner;
  public
    constructor Create(AOwner: TGeneAlgorithm);
  end;

  TGeneState = (gsExecute, gsSuspend, gsTune);

  TGeneAlgorithm = class
  private
    FData: array of TGeneRecord; // Algorithm data
    FLock: TRTLCriticalSection;
    FLowValues: TExtendedArray;
    FHighValues: TExtendedArray;
    FSolutionThread: TSolutionThread;
    FMutation: Extended;
    FInversion: Extended;
    FCrossover: Extended;
    FMaxPopulation: Integer;
    FBitPerNumber: Integer;
    FMinPopulation: Integer;
    FDimCount: Integer;
    FOnBestChange: TBestChangeEvent;
    FOnEstimate: TEstimateEvent;
    FOnIteration: TIterationEvent;
    FIteration: Integer;
    // FBestEstimate: Extended;
    FState: TGeneState;

    BitSize: Integer;

    function GetBestEstimate: Extended;
    function GetHighValues(I: Integer): Extended;
    function GetIteration: Integer;
    function GetLowValues(I: Integer): Extended;
    procedure SetBitPerNumber(const Value: Integer);
    procedure SetCrossover(const Value: Extended);
    procedure SetDimCount(const Value: Integer);
    procedure SetHighValues(I: Integer; const Value: Extended);
    procedure SetInversion(const Value: Extended);
    procedure SetLowValues(I: Integer; const Value: Extended);
    procedure SetMaxPopulation(const Value: Integer);
    procedure SetMinPopulation(const Value: Integer);
    procedure SetMutation(const Value: Extended);
    procedure SetOnBestChange(const Value: TBestChangeEvent);
    procedure SetOnEstimate(const Value: TEstimateEvent);
    procedure SetOnIteration(const Value: TIterationEvent);
    procedure Lock;
    procedure Unlock;
    function GetBestX(I: Integer): Extended;
    function GetState: TGeneState;

    procedure DoCrossover(N: Integer);
    procedure DoMutation(N: Integer);
    procedure DoInversion(N: Integer);

    procedure EstimatePopulation(StartIndex: Integer);
    procedure SortPopulation;
    procedure MakeChild;

  public
    // Creation & destroying
    constructor Create;
    destructor Destroy; override;

    // Running / stopping
    procedure Run;
    procedure Abort;
    procedure Suspend;
    procedure Resume;

    // Saving / opening
    procedure LoadFromStream(S: TStream);
    procedure SaveToStream(S: TStream);

    // Algorithm param
    property BitPerNumber: Integer read FBitPerNumber write SetBitPerNumber;
    property MaxPopulation: Integer read FMaxPopulation write SetMaxPopulation;
    property MinPopulation: Integer read FMinPopulation write SetMinPopulation;
    property Crossover: Extended read FCrossover write SetCrossover;
    property Mutation: Extended read FMutation write SetMutation;
    property Inversion: Extended read FInversion write SetInversion;
    property DimCount: Integer read FDimCount write SetDimCount;
    property LowValues[I: Integer]: Extended read GetLowValues write
      SetLowValues;
    property HighValues[I: Integer]: Extended read GetHighValues write
      SetHighValues;

    // Info property
    property Iteration: Integer read GetIteration;
    property BestX[I: Integer]: Extended read GetBestX;
    property BestEstimate: Extended read GetBestEstimate;
    property State: TGeneState read GetState;

    // Events
    property OnEstimate: TEstimateEvent read FOnEstimate write SetOnEstimate;
    property OnIteration: TIterationEvent read FOnIteration write
      SetOnIteration;
    property OnBestChange: TBestChangeEvent read FOnBestChange write
      SetOnBestChange;

  end;

implementation

resourcestring
  SCannotSetParam = 'Невозможно установить параметр %s в состоянии %s';
  SCannotGetParam = 'Невозможно прочитать параметр %s в состоянии %s';
  SInvalidParam = 'Параметр %s не может быть %s (%d).';
  SNonPositive = 'отрицательным или нулевым';
  SInvalidProbality = 'вероятность %s должна быть в диапазоне 0..1 (%f).';
  SLess2 = 'меньше двух';
  SEmpty =
    'Неправильный индекс при обращении к %s (%d) при нулевом количества элементов.';
  SInvalidIndex =
    'Неправильный индекс при обращении к %s (%d). Индекс должен лежать в диапазоне от %d до %d';
  SNonEstimate = 'Не задана функция оценки.';

const
  SState: array[TGeneState] of string = (
    'настройки параметров алгоритма',
    'работы алгоритма',
    'остановки алгоритма');

  { TGeneAlgorithm }

procedure TGeneAlgorithm.Abort;
var
  I: Integer;
begin
  if FState = gsExecute then
  begin
    FSolutionThread.Terminate;
    FSolutionThread.WaitFor;
  end;
  Lock;
  try
    for I := 0 to Length(FData) - 1 do
    begin
      SetLength(FData[I].Bits, 0);
      SetLength(FData[I].Values, 0);
    end;
    SetLength(FData, 0);
    FState := gsTune;
  finally
    Unlock;
  end;
end;

constructor TGeneAlgorithm.Create;
begin
  InitializeCriticalSection(FLock);
  FBitPerNumber := 8;
  FMinPopulation := 5000;
  FMaxPopulation := 10000;
  FMutation := 0.1;
  FCrossover := 0.89;
  FInversion := 0.01;
  FDimCount := 0;
  FState := gsTune;
end;

destructor TGeneAlgorithm.Destroy;
begin
  Abort;
  DeleteCriticalSection(FLock);
  SetLength(FLowValues, 0);
  SetLength(FHighValues, 0);
  inherited;
end;

procedure TGeneAlgorithm.DoCrossover(N: Integer);
var
  I: Integer;
  Parent1, Parent2: Integer;
  Bit, ByteCount: Integer;
  BitPos: Byte;
  Mask: Integer;
begin
  Parent1 := Random(FMinPopulation);
  Parent2 := Random(FMinPopulation);
  Bit := Random(FDimCount * FBitPerNumber - 1);
  ByteCount := Bit div 32;
  for I := 0 to ByteCount - 1 do
    FData[N].Bits[I] := FData[Parent1].Bits[I];
  for I := ByteCount + 1 to BitSize - 1 do
    FData[N].Bits[I] := FData[Parent2].Bits[I];
  BitPos := Bit - 32 * ByteCount;
  asm
    MOV CL, BitPos
    MOV EAX, -1
    SHL EAX, CL
    MOV Mask, EAX
  end;
  FData[N].Bits[ByteCount] :=
    (FData[Parent1].Bits[ByteCount] and not Mask) or
    (FData[Parent2].Bits[ByteCount] and Mask);
end;

procedure TGeneAlgorithm.DoInversion(N: Integer);

  function GetBit(Addr: Pointer; No: Integer): Byte; assembler;
  asm
  MOV EAX, Addr
  MOV ECX, No
  BT [EAX], ECX
  SBB EAX, EAX
  AND EAX, 1
  end;

  procedure SetBit(Addr: Pointer; No: Integer; Value: Byte); assembler;
  asm
  MOV EAX, Addr
  OR Value,Value
  JZ @@1
  BTS [EAX], No
  RET
@@1:
  BTR [EAX], No
  RET
  end;

var
  Parent, Bit, I: Integer;
  B: Byte;

begin
  Parent := Random(FMinPopulation);
  Bit := Random(FDimCount * FBitPerNumber - 1);
  FData[N].Bits := FData[Parent].Bits;
  repeat
    B := GetBit(FData[N].Bits, 0);
    for I := 0 to FDimCount * FBitPerNumber - 2 do
      SetBit(FData[N].Bits, I, GetBit(FData[N].Bits, I + 1));
    SetBit(FData[N].Bits, FDimCount * FBitPerNumber - 1, B);
    if Bit = 0 then
      Break;
    Bit := Bit - 1;
  until False;
end;

procedure TGeneAlgorithm.DoMutation(N: Integer);
var
  Parent: Integer;
  Bit, BitPos, ByteCount: Integer;
  Mask: Cardinal;
begin
  Parent := Random(FMinPopulation);
  Bit := Random(FDimCount * FBitPerNumber);
  ByteCount := Bit div 32;
  BitPos := Bit - 32 * ByteCount;
  Mask := 1 shl BitPos;
  FData[N].Bits := FData[Parent].Bits;
  FData[N].Bits[ByteCount] := FData[N].Bits[ByteCount] xor Mask;
end;

procedure TGeneAlgorithm.EstimatePopulation(StartIndex: Integer);
var
  I, J, K, Index: Integer;
  P, Q, Y: Extended;
  MaxWeight, Weight: Extended;
  Addr: Pointer;
  GrayBit, BinBit: Cardinal;
begin
  MaxWeight := Power(2, FBitPerNumber);
  for I := StartIndex to Length(FData) - 1 do
  begin
    Index := 0;
    Addr := FData[I].Bits;
    for J := 0 to FDimCount - 1 do
    begin
      Weight := 0.5 * MaxWeight;
      P := 0.0;
      BinBit := 0;

      for K := 0 to FBitPerNumber - 1 do
      begin
        asm
          MOV EAX, Addr
          MOV ECX, Index
          BT [EAX], ECX
          SBB EAX, EAX
          AND EAX, 1
          MOV GrayBit, EAX
          INC Index
        end;
        BinBit := BinBit xor GrayBit;
        if BinBit = 1 then
          P := P + Weight;
        Weight := 0.5 * Weight;
      end;

      P := P / MaxWeight;
      Q := 1 - P;
      FData[I].Values[J] := P * FHighValues[J] + Q * FLowValues[J];
    end;
    Y := 0;
    FOnEstimate(Self, FData[I].Values, Y);
    FData[I].Estimate := Y;
  end;
end;

function TGeneAlgorithm.GetBestEstimate: Extended;
begin
  Lock;
  try
    Result := 0.0; //Kill warning
    if FState = gsTune then
      raise EGeneError.CreateFmt(SCannotGetParam, ['BestEstimate',
        SState[FState]]);
    Result := FData[0].Estimate;
  finally
    Unlock;
  end;
end;

function TGeneAlgorithm.GetBestX(I: Integer): Extended;
begin
  Lock;
  try
    Result := 0.0; // Kill warning
    if FState = gsTune then
      raise EGeneError.CreateFmt(SCannotGetParam, ['BestX', SState[FState]]);
    if (FDimCount = 0) then
      raise EGeneError.CreateFmt(SEmpty, ['BestX', I]);
    if (I < 0) or (I >= FDimCount) then
      raise EGeneError.CreateFmt(SInvalidIndex, ['BestX', I, 0, DimCount]);
    Result := FData[0].Values[I];
  finally
    Unlock;
  end;
end;

function TGeneAlgorithm.GetHighValues(I: Integer): Extended;
begin
  Lock;
  try
    Result := 0.0; // Kill warning
    if FState <> gsTune then
      raise EGeneError.CreateFmt(SCannotGetParam, ['HighValues',
        SState[FState]]);
    if (FDimCount = 0) then
      raise EGeneError.CreateFmt(SEmpty, ['HighValues', I]);
    if (I < 0) or (I >= FDimCount) then
      raise EGeneError.CreateFmt(SInvalidIndex, ['HighValues', I, 0, DimCount]);
    Result := FHighValues[I];
  finally
    Unlock;
  end;
end;

function TGeneAlgorithm.GetIteration: Integer;
begin
  Lock;
  try
    Result := 0; // Kill warning
    if FState = gsTune then
      raise EGeneError.CreateFmt(SCannotGetParam, ['Iteration',
        SState[FState]]);
    Result := FIteration;
  finally
    Unlock;
  end;
end;

function TGeneAlgorithm.GetLowValues(I: Integer): Extended;
begin
  Lock;
  try
    Result := 0.0; // Kill warning
    if FState <> gsTune then
      raise EGeneError.CreateFmt(SCannotGetParam, ['LowValues',
        SState[FState]]);
    if (FDimCount = 0) then
      raise EGeneError.CreateFmt(SEmpty, ['LowValues', I]);
    if (I < 0) or (I >= FDimCount) then
      raise EGeneError.CreateFmt(SInvalidIndex, ['LowValues', I, 0, DimCount]);
    Result := FLowValues[I];
  finally
    Unlock;
  end;
end;

function TGeneAlgorithm.GetState: TGeneState;
begin
  Lock;
  try
    Result := FState;
  finally
    Unlock;
  end;
end;

procedure TGeneAlgorithm.LoadFromStream(S: TStream);
begin

end;

procedure TGeneAlgorithm.Lock;
begin
  EnterCriticalSection(FLock);
end;

procedure TGeneAlgorithm.MakeChild;
var
  I: Integer;
  RandomValue: Extended;
begin
  for I := FMinPopulation to FMaxPopulation - 1 do
  begin
    RandomValue := Random;
    if RandomValue < FCrossover then
      DoCrossover(I)
    else if RandomValue < FCrossover + FMutation then
      DoMutation(I)
    else
      DoInversion(I);
  end;
end;

procedure TGeneAlgorithm.Resume;
begin
  if FState <> gsSuspend then
    raise EGeneError.Create('Прежде чем возобновить, надо начать!');
  FSolutionThread.Create(Self);
  FState := gsExecute;
end;

procedure TGeneAlgorithm.Run;
var
  I, J: Integer;
  b1, b2: Cardinal;
begin
  Lock;
  try
    if not Assigned(FOnEstimate) then
      raise EGeneError.Create(SNonEstimate);
    Abort;

    try

      // Getting memory
      SetLength(FData, FMaxPopulation);
      for I := 0 to Length(FData) - 1 do
      begin
        FData[I].Values := nil;
        FData[I].bits := nil;
      end;
      BitSize := FDimCount * FBitPerNumber + 31;
      BitSize := BitSize and not 31;
      BitSize := BitSize div 32;
      for I := 0 to Length(FData) - 1 do
      begin
        SetLength(FData[I].Values, DimCount);
        SetLength(FData[I].Bits, BitSize);
      end;

      // Initializing Population
      for I := 0 to Length(FData) - 1 do
      begin
        for J := 0 to BitSize - 1 do
        begin
          b1 := Random(35536);
          b2 := Random(35536);
          FData[I].Bits[J] := b1 shl 16 + b2;
        end;
      end;

      EstimatePopulation(0);
      SortPopulation;
      FIteration := 0;
      FState := gsExecute;
      FSolutionThread := TSolutionThread.Create(Self);

    except

      Abort;

    end;

  finally
    Unlock;
  end;

end;

procedure TGeneAlgorithm.SaveToStream(S: TStream);
begin

end;

procedure TGeneAlgorithm.SetBitPerNumber(const Value: Integer);
begin
  Lock;
  try
    if FState <> gsTune then
      raise EGeneError.CreateFmt(SCannotSetParam, ['BitPerNumber',
        SState[FState]]);
    if Value <= 0 then
      raise EGeneError.CreateFmt(SInvalidParam, ['BitPerNumber', SNonPositive,
        Value]);
    FBitPerNumber := Value;
  finally
    Unlock;
  end;
end;

procedure TGeneAlgorithm.SetCrossover(const Value: Extended);
begin
  Lock;
  try
    if FState <> gsTune then
      raise EGeneError.CreateFmt(SCannotSetParam, ['Crossover',
        SState[FState]]);
    if (Value < 0) or (Value > 1) then
      raise EGeneError.CreateFmt(SInvalidProbality, ['кроссовера', Value]);
    FCrossover := Value;
    if FCrossover + FMutation > 1.0 then
    begin
      FMutation := 1.0 - FCrossover;
      FInversion := 0.0;
    end
    else
    begin
      FInversion := 1.0 - FMutation - FCrossover;
    end;
  finally
    Unlock;
  end;
end;

procedure TGeneAlgorithm.SetDimCount(const Value: Integer);
var
  I: Integer;
begin
  Lock;
  try
    if FState <> gsTune then
      raise EGeneError.CreateFmt(SCannotSetParam, ['DimCount', SState[FState]]);
    if FDimCount = Value then
      Exit;
    if Value <= 0 then
      raise EGeneError.CreateFmt(SInvalidParam, ['DimCount', SNonPositive,
        Value]);
    SetLength(FLowValues, Value);
    SetLength(FHighValues, Value);
    for I := FDimCount to Value - 1 do
    begin
      FLowValues[I] := 0.0;
      FHighValues[I] := 1.0;
    end;
    FDimCount := Value;
  finally
    Unlock;
  end;
end;

procedure TGeneAlgorithm.SetHighValues(I: Integer; const Value: Extended);
begin
  Lock;
  try
    if FState <> gsTune then
      raise EGeneError.CreateFmt(SCannotSetParam, ['HighValues',
        SState[FState]]);
    if (FDimCount = 0) then
      raise EGeneError.CreateFmt(SEmpty, ['HighValues', Value]);
    if (I < 0) or (I >= FDimCount) then
      raise EGeneError.CreateFmt(SInvalidIndex, ['HighValues', Value, 0,
        DimCount]);
    FHighValues[I] := Value;
    if FLowValues[I] > FHighValues[I] then
      FLowValues[I] := FHighValues[I];
  finally
    Unlock;
  end;
end;

procedure TGeneAlgorithm.SetInversion(const Value: Extended);
begin
  Lock;
  try
    if FState <> gsTune then
      raise EGeneError.CreateFmt(SCannotSetParam, ['Crossover',
        SState[FState]]);
    if (Value < 0) or (Value > 1) then
      raise EGeneError.CreateFmt(SInvalidProbality, ['инверсии', Value]);
    FInversion := Value;
    if FCrossover + FInversion > 1.0 then
    begin
      FCrossover := 1.0 - FInversion;
      FMutation := 0.0;
    end
    else
    begin
      FMutation := 1.0 - FInversion - FCrossover;
    end;
  finally
    Unlock;
  end;
end;

procedure TGeneAlgorithm.SetLowValues(I: Integer; const Value: Extended);
begin
  Lock;
  try
    if FState <> gsTune then
      raise EGeneError.CreateFmt(SCannotSetParam, ['LowValues',
        SState[FState]]);
    if (FDimCount = 0) then
      raise EGeneError.CreateFmt(SEmpty, ['LowValues', Value]);
    if (I < 0) or (I >= FDimCount) then
      raise EGeneError.CreateFmt(SInvalidIndex, ['LowValues', Value, 0,
        DimCount]);
    FLowValues[I] := Value;
    if FHighValues[I] < FLowValues[I] then
      FHighValues[I] := FLowValues[I];
  finally
    Unlock;
  end;
end;

procedure TGeneAlgorithm.SetMaxPopulation(const Value: Integer);
begin
  Lock;
  try
    if FState <> gsTune then
      raise EGeneError.CreateFmt(SCannotSetParam, ['MaxPopulation',
        SState[FState]]);
    if Value < 2 then
      raise EGeneError.CreateFmt(SInvalidParam, ['MaxPopulation', SLess2,
        Value]);
    FMaxPopulation := Value;
    if FMinPopulation >= FMaxPopulation then
      FMinPopulation := FMaxPopulation - 1;
  finally
    Unlock;
  end;
end;

procedure TGeneAlgorithm.SetMinPopulation(const Value: Integer);
begin
  Lock;
  try
    if FState <> gsTune then
      raise EGeneError.CreateFmt(SCannotSetParam, ['MinPopulation',
        SState[FState]]);
    if Value <= 0 then
      raise EGeneError.CreateFmt(SInvalidParam, ['MinPopulation', SNonPositive,
        Value]);
    FMinPopulation := Value;
    if FMinPopulation >= FMaxPopulation then
      FMaxPopulation := FMinPopulation + 1;
  finally
    Unlock;
  end;
end;

procedure TGeneAlgorithm.SetMutation(const Value: Extended);
begin
  Lock;
  try
    if FState <> gsTune then
      raise EGeneError.CreateFmt(SCannotSetParam, ['Crossover',
        SState[FState]]);
    if (Value < 0) or (Value > 1) then
      raise EGeneError.CreateFmt(SInvalidProbality, ['мутации', Value]);
    FMutation := Value;
    if FCrossover + FMutation > 1.0 then
    begin
      FCrossover := 1.0 - FMutation;
      FInversion := 0.0;
    end
    else
    begin
      FInversion := 1.0 - FMutation - FCrossover;
    end;
  finally
    Unlock;
  end;
end;

procedure TGeneAlgorithm.SetOnBestChange(const Value: TBestChangeEvent);
begin
  Lock;
  try
    FOnBestChange := Value;
  finally
    Unlock;
  end;
end;

procedure TGeneAlgorithm.SetOnEstimate(const Value: TEstimateEvent);
begin
  Lock;
  try
    if FState <> gsTune then
      raise EGeneError.CreateFmt(SCannotSetParam, ['OnEstimate',
        SState[FState]]);
    FOnEstimate := Value;
  finally
    Unlock;
  end;
end;

procedure TGeneAlgorithm.SetOnIteration(const Value: TIterationEvent);
begin
  Lock;
  try
    FOnIteration := Value;
  finally
    Unlock;
  end;
end;

procedure TGeneAlgorithm.SortPopulation;

  procedure QuickSort(L, R: Integer);
  var
    I, J: Integer;
    P: Extended;
    T: TGeneRecord;
  begin
    repeat
      I := L;
      J := R;
      P := FData[(L + R) shr 1].Estimate;
      repeat
        while FData[I].Estimate > P do
          Inc(I);
        while FData[J].Estimate < P do
          Dec(J);
        if I <= J then
        begin
          if (I = 0) or (J = 0) then
            Lock;
          try
            T := FData[I];
            FData[I] := FData[J];
            FData[J] := T;
          finally
            if (I = 0) or (J = 0) then
              UnLock;
          end;
          Inc(I);
          Dec(J);
        end;
      until I > J;
      if L < J then
        QuickSort(L, J);
      L := I;
    until I >= R;
  end;

begin
  QuickSort(0, Length(FData) - 1);
end;

procedure TGeneAlgorithm.Suspend;
begin
  if FState <> gsExecute then
    raise EGeneError.Create('Прежде чем остановить, надо запустить!');
  FSolutionThread.Terminate;
  // FSolutionThread.WaitFor;
  FState := gsSuspend;
end;

procedure TGeneAlgorithm.Unlock;
begin
  LeaveCriticalSection(FLock);
end;

{ TSolutionThread }

constructor TSolutionThread.Create(AOwner: TGeneAlgorithm);
begin
  FOwner := AOwner;
  FreeOnTerminate := True;
  inherited Create(False);
end;

procedure TSolutionThread.Execute;
begin
  repeat
    Owner.MakeChild;
    Owner.EstimatePopulation(Owner.FMinPopulation);
    Owner.SortPopulation;
    Inc(Owner.FIteration);
  until Terminated;
  Sleep(10);
end;

end.

Пример использования:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Genes, ExtCtrls, Grids;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Edit4: TEdit;
    Button4: TButton;
    Button5: TButton;
    Timer1: TTimer;
    Button7: TButton;
    Label1: TLabel;
    Grid: TStringGrid;
    Label2: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button7Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    procedure Refresh;
    procedure GeneEstimate(Sender: TObject; const X: TExtendedArray; var Y:
      Extended);
  public
    FGene: TGeneAlgorithm;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  DecimalSeparator := '.';
  FGene := TGeneAlgorithm.Create;
  Refresh;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FGene.Free;
end;

procedure TForm1.Refresh;
begin
  Edit1.Text := FloaTtoStr(FGene.Crossover);
  Edit2.Text := FloatToStr(FGene.Mutation);
  Edit3.Text := FloatToStr(FGene.Inversion);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  FGene.Crossover := StrTofloat(Edit1.Text);
  Refresh;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  FGene.Mutation := StrTofloat(Edit2.Text);
  Refresh;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  FGene.Inversion := StrTofloat(Edit3.Text);
  Refresh;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  FGene.BitPerNumber := StrToInt(Edit4.Text);
  Edit4.Text := IntToStr(FGene.BitPerNumber);
end;

procedure TForm1.Button5Click(Sender: TObject);
var
  I: Integer;
begin
  Randomize;
  FGene.DimCount := 5;
  FGene.MaxPopulation := 10000;
  FGene.MinPopulation := 5000;
  FGene.OnEstimate := GeneEstimate;
  for I := 0 to 4 do
  begin
    FGene.LowValues[I] := 0;
    FGene.HighValues[I] := 10;
  end;
  FGene.Run;
  Timer1.Enabled := True;
end;

procedure TForm1.GeneEstimate(Sender: TObject; const X: TExtendedArray;
  var Y: Extended);
var
  I: Integer;
begin
  Y := 0;
  for I := Low(X) to High(X) do
    Y := Y + Sqr(X[I] - I);
  Y := -Y;
end;

procedure TForm1.Button7Click(Sender: TObject);
var
  I: Integer;
begin
  Timer1.Enabled := False;
  Label1.Caption := '';
  FGene.Suspend;
  Grid.RowCount := FGene.DimCount + 1;
  for I := 0 to FGene.DimCount - 1 do
    Grid.Cells[0, I + 1] := FloattoStr(FGene.BestX[I]);
  FGene.Abort;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Label1.Caption := FloatToStr(FGene.BestEstimate);
end;

end.
Проект Delphi World © Выпуск 2002 - 2004
Автор проекта: ___Nikolay