unit SimKohonen;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, StdCtrls,Math, Buttons;
type

  TForm_Kohonen = class (TForm)
  GroupBox1 : TGroupBox;
  GroupBox2 : TGroupBox;
  GroupBox3 : TGroupBox;
  Image1 : TImage;
  GroupBox4 : TGroupBox;
  Image2 : TImage;
  GroupBox5 : TGroupBox;
  GroupBox6 : TGroupBox;
  GroupBox7 : TGroupBox;
  ImageCurva : TImage;
  GroupBox8 : TGroupBox;
  Button_para : TButton;
  Treinar : TButton;
  BtReset : TButton;
  Button2_abre : TButton;
  Uniforme : TButton;
  CheckBox1 : TCheckBox;
  CheckBox2 : TCheckBox;
  Label1 : TLabel;
  Label2 : TLabel;
  Label3 : TLabel;
  Edit5 : TEdit;
  Edit3 : TEdit;
  Edit6 : TEdit;
  Edit7 : TEdit;
  RadioButton1 : TRadioButton;
  RadioButton2 : TRadioButton;
  Edit9 : TEdit;
  Edit8 : TEdit;
  Edit4 : TEdit;
  Label4 : TLabel;
  Edit1 : TEdit;
  Edit2 : TEdit;
  Label5 : TLabel;
  Label6 : TLabel;
  Label7 : TLabel;
  Label8 : TLabel;
  Label9 : TLabel;
  Label10 : TLabel;
  Label11 : TLabel;
  Label12 : TLabel;
  OpenDialog1 : TOpenDialog;
  procedure Button2_abreClick (Sender : TObject);
  procedure UniformeClick (Sender : TObject);
  procedure TreinarClick (Sender : TObject);
  procedure Button_paraClick (Sender : TObject);
  procedure BtResetClick (Sender : TObject);
  procedure FormCreate (Sender : TObject);
  procedure AgrupadoClick (Sender : TObject);
  procedure FormClose (Sender : TObject; var Action : TCloseAction);
    procedure FormActivate(Sender: TObject);
private
  // Private declarations
public
  // Public declarations
end;
ponto = record
  x, y : real;
  classe : char;
end;
neuronio = record
  w1, w2 : real;
  rotulo : integer;
  rotulou : byte;
end;
// Prototype
procedure PlotaRede;
procedure PlotaCurvaAprendizagem;
function DistanciaEuclidiana (x, y, padrao : integer) : real;
procedure InicializaRede;
procedure RotularTestarRede (ConjTreinamento : integer);
function TaxaAprendizagem (n : real) : real;
procedure PlotaPontos (indice : integer);
function Vizinhanca (n, VencedorI, VencedorJ, AtualI, AtualJ : integer) : real;
procedure PintaPixel (x, y : real; Imagem : TImage; Cor : TColor);
var
  Form_Kohonen : TForm_Kohonen;
  rede : array [0..9, 0..9] of neuronio;
  EspacoDominio : array [0..999] of ponto;
  // 1 a 50 depois de 10 em 10 ate 500 ==> Total de 95
  // Quantidade de acertos
  CurvaAprendizagem : array [0..94] of integer;
  arqporc : string;
  indicecurva, NumeroNeuroniosL, NumeroNeuroniosC, parar : integer;
implementation
uses Unit1;
{$R *.DFM}
//--------------------------------------------------------------------------
function ExtraiChar (classe : string) : char;
Var i : integer;
begin
  i := 1;
  while classe [i] = ' ' do
    inc (i);
  result := classe [i];
end;
//--------------------------------------------------------------------------
procedure TForm_Kohonen.Button2_abreClick (Sender : TObject);
Var
  arq : TextFile;
  classe, diretorio, namefile : string;
  x, y : real;
  cont, tam, posarq : integer;
begin
  if OpenDialog1.Execute then begin
    namefile := OpenDialog1.FileName;
    AssignFile (arq, namefile);
    try
      try
        reset (arq);
      except
        showmessage ('Nome de arquivo inválido:' + namefile);
      end;
    finally
      tam := Length (namefile);
      diretorio := GetCurrentDir + '\';
      posarq := Length(diretorio) + 1;
      tam := tam - posarq;
      arqporc := 'k' + Copy (namefile, posarq, tam + 1);
      tam := Length (arqporc) - 3;
      arqporc := diretorio + Copy (arqporc, 1, tam) + 'dat';
      ReadLn (arq, x, y, classe);
      cont := 0;
      while (not eof (arq)) do
      begin
        EspacoDominio [cont].x := x;
        EspacoDominio [cont].y := y;
        EspacoDominio [cont].classe := ExtraiChar (classe);
        inc (cont);
        ReadLn (arq, x, y, classe);
      end;
    end
  end;
  CloseFile (arq);
  PlotaPontos (1000);
end;
//--------------------------------------------------------------------------
procedure TForm_Kohonen.AgrupadoClick (Sender : TObject);
Var x, y : real;
  i : integer;
begin
  Form_Kohonen.Image2.Canvas.Brush.Color := clWhite;
  Image1.Canvas.FillRect (Rect (0, 0, 300, 300));
  // int i=0; i<500; i++)  n pontos
  for i := 0 to 499 do
  begin
    Randomize;
    // Quadrado de n px de lado com centro no clique
    x := 50 + (random (50) - 50 / 2);
    Randomize;
    // Quadrado de n px de lado com centro no clique
    y := 50 + (random (50) -50 / 2);
    // Verificando se nao estrapolou para fora da imagem
    if (x > 300) then x := 300;
    if (x < 0) then x := 0;
    if (y > 300) then y := 300;
    if (y < 0) then y := 0;
    EspacoDominio [i].x := (x / 150) - 1;
    EspacoDominio [i].y := (y / 150) - 1;
  end;
  // int i=0; i<500; i++)  n pontos
  for i := 0 to 499 do
  begin
    Randomize;
    // Quadrado de n px de lado com centro no clique
    x := 250 + (random (50) - 50 / 2);
    Randomize();
    // Quadrado de n px de lado com centro no clique
    y := 250 + (random (50) - 50 / 2);
    // Verificando se nao estrapolou para fora da imagem
    if (x > 300) then x := 300;
    if (x < 0) then x := 0;
    if (y > 300) then y := 300;
    if (y < 0) then y := 0;
    EspacoDominio [500 + i].x := (x / 150) - 1;
    EspacoDominio [500 + i].y := (y / 150) - 1;
  end;
  // (int i=0; i<1000; i++)
  for i := 0 to 999 do
  begin
    x := (EspacoDominio [i].x + 1) * 150;
    y := (EspacoDominio [i].y + 1) * 150;
    PintaPixel (x, y, Image1, clWhite);
  end;
end;
//---------------------------------------------------------------------------
//  USAR ESTE PROCEDIMENTO PARA FAZER COM QUE OS PONTOS APAREÇAM BEM MAIS,
//  INCLUINDO NAIVE BAYES
//--------------------------------------------------------------------------
procedure PintaPixel (x, y : real; Imagem : TImage; Cor : TColor);
Var ix, iy : integer;
begin
  ix := Round (x);
  iy := Round (y);
  // Pinta ao redor do ponto
  Imagem.Canvas.Pixels [ix, iy] :=Cor;
  Imagem.Canvas.Pixels [ix -1, iy] :=Cor;
  Imagem.Canvas.Pixels [ix, iy - 1] :=Cor;
  Imagem.Canvas.Pixels [ix + 1, iy] :=Cor;
  Imagem.Canvas.Pixels [ix,iy + 1] :=Cor;
end;
//--------------------------------------------------------------------------
procedure PlotaRede;
Var x, y, xaux, yaux : real;
  i, j : integer;
begin
  // Limpa imagem
  Form_Kohonen.Image2.Canvas.Brush.Color := clWhite;
  Form_Kohonen.Image2.Canvas.FillRect (Rect (0, 0, 300, 300));
  // Plota rede
  for i := 0 to NumeroNeuroniosL - 1 do begin
    for j := 0 to NumeroNeuroniosC - 1 do begin
      x := (rede [i, j].w1 + 1) * 150;
      y := (rede [i, j].w2 + 1) * 150;
      Form_Kohonen.Image2.Canvas.MoveTo (Round (x), Round (y));
      if (i <> 0) then begin
        xaux := (rede [i - 1, j].w1 + 1) * 150;
        yaux := (rede [i - 1, j].w2 + 1) * 150;
        Form_Kohonen.Image2.Canvas.LineTo (Round (xaux), Round (yaux));
        Form_Kohonen.Image2.Canvas.MoveTo (Round (x), Round (y));
      end;
      if (j <> 0) then begin
        xaux := (rede [i, j - 1].w1 + 1) * 150;
        yaux := (rede [i, j - 1].w2 + 1) * 150;
        Form_Kohonen.Image2.Canvas.LineTo (Round (xaux), Round (yaux));
        Form_Kohonen.Image2.Canvas.MoveTo (Round (x), Round (y));
      end;
      Form_Kohonen.Image2.Canvas.MoveTo (Round (x), Round (y));
      if (rede[i,j].rotulou<>0) then begin
        if (rede[i,j].rotulo = 0) then begin
          Form_Kohonen.Image2.Canvas.Brush.Color := clWhite;
          Form_Kohonen.Image2.Canvas.Ellipse(Round(x-3),Round(y-3),Round(x+3),Round(y+3));
        end
        else begin
          if (rede [i, j].rotulo > 0) then begin
            Form_Kohonen.Image2.Canvas.Brush.Color := clBlue;
            Form_Kohonen.Image2.Canvas.Ellipse(Round(x-3),Round(y-3),Round(x+3),Round(y+3));
          end
          else begin
            Form_Kohonen.Image2.Canvas.Brush.Color := clRed;
            Form_Kohonen.Image2.Canvas.Ellipse(Round(x-3),Round(y-3),Round(x+3),Round(y+3));
          end;
        end;
      end;
    end;
  end;
  Form_Kohonen.Image2.Refresh;
end;
//--------------------------------------------------------------------------
procedure PlotaPontos (indice : integer);
Var
  x, y : real;
  i : integer;
begin
  Form_Kohonen.Image2.Canvas.Brush.Color := clWhite;
  Form_Kohonen.Image1.Canvas.FillRect (Rect (0, 0, 300, 300));
  // (int i=0; i<indice; i++)
  for i := 0 to indice - 1 do begin
    x := (EspacoDominio [i].x + 1) * 150;
    y := (EspacoDominio [i].y + 1) * 150;
    if (EspacoDominio [i].classe = 'B') then begin
      PintaPixel (x, y, Form_Kohonen.Image1, clBlue);
    end
    else begin
      PintaPixel (x, y, Form_Kohonen.Image1, clRed);
    end;
  end;
end;
//---------------------------------------------------------------------------
procedure InicializaRede;
Var
  x, y : real;
  i, j : integer;
begin
  // Setando o número de neurônios
  NumeroNeuroniosL := StrToInt (Form_Kohonen.Edit6.Text);
  NumeroNeuroniosC := StrToInt (Form_Kohonen.Edit7.Text);
  if (NumeroNeuroniosL > 10) then NumeroNeuroniosL := 10;
  if (NumeroNeuroniosC > 10) then NumeroNeuroniosC := 10;
  // for (int i=0; i<NumeroNeuroniosL; i++)
  for i := 0 to NumeroNeuroniosL - 1 do begin
    // (int j=0; j<NumeroNeuroniosC; j++)
    for j := 0 to NumeroNeuroniosC - 1 do begin
      if (Form_Kohonen.RadioButton1.Checked) then begin
        x := (i * 30) + 15;
        y := (j * 30) + 15;
      end
      else begin
        Randomize();
        x := 100 + random (100);
        Randomize();
        y := 100 + random (100);
      end;
      rede [i, j].w1 := (x / 150) - 1;
      rede [i, j].w2 := (y / 150) - 1;
      rede [i, j].rotulo := 0;
      rede [i, j].rotulou := 0;
    end;
  end;
end;
//---------------------------------------------------------------------------
procedure TForm_Kohonen.UniformeClick (Sender : TObject);
Var
  x, y : real;
  i : integer;
begin
  Form_Kohonen.Image2.Canvas.Brush.Color := clWhite;
  Image1.Canvas.FillRect (Rect (0, 0, 300, 300));
  // (int i=0; i<1000; i++)
  for i:=0 to 999 do begin
    Randomize;
    x := random (300);
    Randomize;
    y := random (300);
    EspacoDominio [i].x := (x / 150) - 1;
    EspacoDominio [i].y := (y / 150) - 1;
    if (random(2) = 0) then begin
      EspacoDominio [i].classe := 'B';
      PintaPixel (x, y, Image1, clBlue);
    end
    else begin
      EspacoDominio [i].classe := 'R';
      PintaPixel (x, y, Image1, clRed);
    end;
  end;
end;
//---------------------------------------------------------------------------
procedure TForm_Kohonen.TreinarClick  (Sender : TObject);
Var
   padrao, aux1, aux2, vencedori, vencedorj : integer;
   MenorDistanciaEuclidianaAtual, TaxaAprendizagemAtual : real;
   VizinhancaAux, aux, editTaxa : real;
   tempo, ControleTamanhoTreinamento, i, j : integer;
   ConjTreinamento : integer;
   begin
   if (CheckBox1.Checked) then begin
     ControleTamanhoTreinamento := 500;
     ConjTreinamento := 1;
   end
   else begin
     ControleTamanhoTreinamento := 1000;
     ConjTreinamento := 1000;
   end;
   parar := 0;
   // Loop de curva de aprendizagem
   while ((ConjTreinamento <= ControleTamanhoTreinamento) and (parar = 0)) do begin
     InicializaRede;
     tempo := 1;
     TaxaAprendizagemAtual := TaxaAprendizagem (tempo);
     Form_Kohonen.Edit1.Text := FloatToStr (TaxaAprendizagemAtual);
     Form_Kohonen.Edit1.Refresh();
     editTaxa := StrToFloat (Form_Kohonen.Edit3.Text);
     // Loop de treinamento da primeira fase
     while ((TaxaAprendizagemAtual > editTaxa) and (parar = 0)) do begin
       while (CheckBox2.Checked) do begin
         Application.ProcessMessages;
       end;
       if (not CheckBox1.Checked) then begin
         // Limpando a imagem
         Image2.Canvas.Brush.Color:= clWhite;
         Image2.Canvas.FillRect (Rect (0, 0, 300, 300));
         // Plot do estado atual da rede
         PlotaRede;
       end;
       // Seleção do padrão apresentado a rede
       // Dentro do limite do conj. de treinamento
       Randomize;
       padrao := random (ConjTreinamento);
       // Busca pelo neurônio vencedor
       MenorDistanciaEuclidianaAtual := distanciaEuclidiana (0, 0, padrao);
       vencedori := 0;
       vencedorj := 0;
       // (int i=0; i<NumeroNeuroniosL; i++)
       // Procurando na rede o melhor neuronio para o padrao
       for i := 0 to NumeroNeuroniosL - 1 do begin
         // (int j=0; j<NumeroNeuroniosC; j++)
         for j := 0 to NumeroNeuroniosC - 1 do begin
           aux:=distanciaEuclidiana (i, j, padrao);
           // Argumento minimo da distancia euclidiana
           if (aux < MenorDistanciaEuclidianaAtual) then begin
             MenorDistanciaEuclidianaAtual := aux;
             vencedori := i;
             vencedorj := j;
           end;
         end;
       end;
       //AJUSTE DOS PESOS
       // Ajuste dos pesos sinapticos de toda a grade com base no vencedor
       // for (int i=0; i<NumeroNeuroniosL; i++)
       for i := 0 to NumeroNeuroniosL - 1 do
       begin
         // int j=0; j<NumeroNeuroniosC; j++)
         for j := 0 to NumeroNeuroniosC - 1 do
           begin
             VizinhancaAux := Vizinhanca (tempo, vencedori, vencedorj, i,j );
             rede[i,j].w1:=rede[i,j].w1+(TaxaAprendizagemAtual*VizinhancaAux*(EspacoDominio[padrao].x-rede[i,j].w1));
             rede[i,j].w2:=rede[i,j].w2+(TaxaAprendizagemAtual*VizinhancaAux*(EspacoDominio[padrao].y-rede[i,j].w2));
           end;
       end;
       inc (tempo);
       TaxaAprendizagemAtual := TaxaAprendizagem (tempo);
       Form_Kohonen.Edit1.Text := FloatToStr (TaxaAprendizagemAtual);
       Form_Kohonen.Edit1.Refresh;
       Form_Kohonen.Edit2.Text := FloatToStr (tempo);
       Form_Kohonen.Edit2.Refresh;
       Application.ProcessMessages;
     end;
     RotularTestarRede (ConjTreinamento);
     PlotaRede;
     PlotaPontos (ConjTreinamento);
     Form_Kohonen.Edit5.Text := IntToStr (ConjTreinamento);
     Form_Kohonen.Edit5.Refresh;
     // Atualizando o tamanho do conjunto de treinamento
     if (ConjTreinamento < 50) then begin
       inc (ConjTreinamento);
     end
     else begin
       ConjTreinamento := ConjTreinamento + 10;
     end;
   end;
   if (CheckBox1.Checked) then PlotaCurvaAprendizagem;
end;
//---------------------------------------------------------------------------
procedure TForm_Kohonen.Button_paraClick (Sender : TObject);
begin
  parar := 1;
end;
//---------------------------------------------------------------------------
procedure TForm_Kohonen.BtResetClick (Sender : TObject);
Var i : integer;
begin
  InicializaRede;
  PlotaRede;
  PlotaPontos (1000);
  Form_Kohonen.ImageCurva.Canvas.Brush.Color := clWhite;
  Form_Kohonen.ImageCurva.Canvas.FillRect (Rect (0, 0, Form_Kohonen.ImageCurva.Width, Form_Kohonen.ImageCurva.Height));
  indicecurva := 0;
  // (int i=0; i<95; i++)
  for i := 0 to 94 do begin
    CurvaAprendizagem [i] := 0;
  end;
end;
//---------------------------------------------------------------------------
procedure TForm_Kohonen.FormCreate (Sender : TObject);
Var
  x, y : real;
  i : integer;
begin
  decimalseparator := '.';
  indicecurva := 0;
  // Setando o número de neurônios
  NumeroNeuroniosL := StrToInt(Edit7.Text);
  NumeroNeuroniosC := StrToInt(Edit6.Text);
  if (NumeroNeuroniosL > 10) then NumeroNeuroniosL := 10;
  if (NumeroNeuroniosC > 10) then NumeroNeuroniosC := 10;
  // Setando os brushes
  Form_Kohonen.Image1.Canvas.Brush.Color := clWhite;
  Form_Kohonen.Image2.Canvas.Brush.Color := clWhite;
  // Limpando as imagens
  Image1.Canvas.FillRect (Rect (0, 0, 300, 300));
  Image2.Canvas.FillRect (Rect (0, 0, 300, 300));
  // Inicializando o domínio com uma distribuição uniforme
  // (int i=0; i<1000; i++)
  for i:=0 to 999 do
  begin
    Randomize();
    x := random (300);
    Randomize();
    y := random (300);
    EspacoDominio [i].x := (x / 150) - 1;
    EspacoDominio [i].y := (y / 150) - 1;
    if (random (2) = 0) then begin
      EspacoDominio [i].classe := 'B';
      PintaPixel (x, y, Image1, clBlue);
    end
    else begin
      EspacoDominio [i].classe := 'R';
      PintaPixel (x, y, Image1, clRed);
    end;
  end;
  // Inicializando a rede
  InicializaRede();
  // Plotando a rede
  PlotaRede();
  // Exibindo a taxa de aprendizagem inicial
  Form_Kohonen.Edit1.Text := FloatToStr (TaxaAprendizagem (1));
end;
//---------------------------------------------------------------------------
function DistanciaEuclidiana(x, y, padrao : integer) : real;
Var distancia : real;
begin
  distancia := power (rede [x, y].w1 - EspacoDominio [padrao].x, 2);
  distancia := distancia + power (rede [x, y].w2 - EspacoDominio [padrao].y, 2);
  result := sqrt (distancia);
end;
//---------------------------------------------------------------------------
function TaxaAprendizagem (n : real) : real;
Var n0, t2 : real;
begin
  n0 := (1.0 / 10.0);
  t2 := 1000;
  result := (n0 * exp (-n / t2));
end;
//---------------------------------------------------------------------------
function Vizinhanca (n, VencedorI, VencedorJ, AtualI, AtualJ : integer) : real;
Var lambda0, lambda, t1, d2, aux : real;
begin
  lambda0 := StrToFloat (Form_Kohonen.Edit8.Text);
  t1 := (1000 / ln (lambda0));
  d2 := power ((AtualI - VencedorI), 2) + power ((AtualJ - VencedorJ), 2);
  lambda := lambda0 * exp (-n / t1);
  aux := exp (-d2 * (n / StrToFloat (Form_Kohonen.Edit9.Text)) / 2 * power (lambda, 2));
  if (aux < StrToFloat(Form_Kohonen.Edit4.Text)) then
  begin
    if(AtualI-1=VencedorI)and(AtualJ=VencedorJ)then aux:=StrToFloat(Form_Kohonen.Edit4.Text);
    if(AtualI+1=VencedorI)and(AtualJ=VencedorJ)then aux:=StrToFloat(Form_Kohonen.Edit4.Text);
    if(AtualI=VencedorI)and(AtualJ-1=VencedorJ)then aux:=StrToFloat(Form_Kohonen.Edit4.Text);
    if(AtualI=VencedorI)and(AtualJ+1=VencedorJ)then aux:=StrToFloat(Form_Kohonen.Edit4.Text);
  end;
  result := (aux);
end;
//---------------------------------------------------------------------------
procedure RotularTestarRede (ConjTreinamento : integer);
Var
  aux, MenorDistanciaEuclidianaAtual : real;
  vencedori, vencedorj, acertos, i, j, treino, teste : integer;
begin
  // Rotulando
  for treino := 0 to ConjTreinamento - 1 do begin
    MenorDistanciaEuclidianaAtual := distanciaEuclidiana (0, 0, treino);
    vencedori := 0;
    vencedorj := 0;
    // Procurando na rede o melhor neuronio para o padrao
    for i := 0 to NumeroNeuroniosL-1 do begin
      for j := 0 to NumeroNeuroniosC-1 do begin
        aux := distanciaEuclidiana (i, j, treino);
        // Argumento minimo da distancia euclidiana
        if (aux < MenorDistanciaEuclidianaAtual) then begin
          MenorDistanciaEuclidianaAtual := aux;
          vencedori := i;
          vencedorj := j;
        end;
      end;
    end;
    // Ajusta o rotulo do melhor neuronio para o padrao de treino
    if (EspacoDominio [treino].classe = 'B') then begin
      if (rede [vencedori, vencedorj].rotulou = 0) then begin
        rede [vencedori, vencedorj].rotulou := 1;
      end;
      inc (rede [vencedori, vencedorj].rotulo);
    end
    else begin
      if (rede [vencedori, vencedorj].rotulou = 0) then begin
        rede [vencedori, vencedorj].rotulou := 1;
      end;
      dec (rede [vencedori, vencedorj].rotulo);
    end;
  end;
  acertos := 0;
  // Loop de teste
  for teste := 500 to 999 do begin
    MenorDistanciaEuclidianaAtual := distanciaEuclidiana (0, 0, teste);
    vencedori := 0;
    vencedorj := 0;
    // Procurando na rede o melhor neuronio para o padrao
    for i := 0 to NumeroNeuroniosL - 1 do begin
      for j := 0 to NumeroNeuroniosC - 1 do begin
        aux := distanciaEuclidiana (i, j, teste);
        // Argumento minimo da distancia euclidiana
        if (aux < MenorDistanciaEuclidianaAtual) then begin
          MenorDistanciaEuclidianaAtual := aux;
          vencedori := i;
          vencedorj := j;
        end;
      end;
    end;
    if (rede [vencedori, vencedorj].rotulou <> 0) then begin
      if (rede [vencedori, vencedorj].rotulo = 0) then begin
        inc (acertos);
      end
      else begin
        if (rede [vencedori, vencedorj].rotulo > 0) then begin
          if (EspacoDominio [teste].classe = 'B') then begin
            inc (acertos);
          end;
        end
        else begin
          if (EspacoDominio [teste].classe = 'R') then begin
            inc (acertos);
          end;
        end;
      end;
    end;
  end;
  CurvaAprendizagem [indicecurva] := acertos;
  inc (indicecurva);
end;
//---------------------------------------------------------------------------
procedure PlotaCurvaAprendizagem;
Var
  i, cont : integer;
  F : TextFile;
  PorcAcertos : real;
begin
  decimalseparator := '.';

  Form_Kohonen.ImageCurva.Canvas.Brush.Color := clWhite;
  Form_Kohonen.ImageCurva.Canvas.FillRect (Rect (0, 0, 300, 145));
  Form_Kohonen.ImageCurva.Canvas.Brush.Color := clRed;
  Form_Kohonen.ImageCurva.Canvas.MoveTo (0, 72);
  Form_Kohonen.ImageCurva.Canvas.LineTo (300, 72);
  Form_Kohonen.ImageCurva.Canvas.MoveTo (0, 36);
  Form_Kohonen.ImageCurva.Canvas.LineTo (300, 36);
  Form_Kohonen.ImageCurva.Canvas.MoveTo (0, 108);
  Form_Kohonen.ImageCurva.Canvas.LineTo (300, 108);
  Form_Kohonen.ImageCurva.Canvas.Brush.Color := clGreen;
  cont := 0;
  AssignFile (F, arqporc);
  Rewrite (F);
  for i := 0 to 94 do begin
     if cont < 50 then inc (cont)
     else cont := cont+10;
    // 145 é a altura do ImageCurva, a largura é 300
    Form_Kohonen.ImageCurva.Canvas.MoveTo (i * 3 + 7, 145);
    // CurvaAprendizagem tem o numero de acertos
    // CurvaApredizagem / 500 = % acertos
    PorcAcertos := (CurvaAprendizagem [i] / 500);
    // FormatFloat('0.00',PorcAcertos);
    Form_Kohonen.ImageCurva.Canvas.LineTo (i * 3 + 7, Round (145 - PorcAcertos * 145));
    Writeln (F,cont,' ',PorcAcertos:2:2);
  end;
  CloseFile (F);
end;
//---------------------------------------------------------------------------
procedure TForm_Kohonen.FormClose (Sender : TObject;
  var Action: TCloseAction);
begin
  Form1.PageControl1.ActivePageIndex := 0;
end;
//---------------------------------------------------------------------------
procedure TForm_Kohonen.FormActivate(Sender: TObject);
begin
   Image1.Canvas.Brush.Color:= clWhite;
   Image1.Canvas.FillRect (Rect (0, 0, Image2.Width , Image2.Height));
   Image2.Canvas.Brush.Color:= clWhite;
   Image2.Canvas.FillRect (Rect (0, 0, Image2.Width , Image2.Height));
end;

end.
