//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit3.h"
#pragma package(smart_init)
//---------------------------------------------------------------------------

//   Important: Methods and properties of objects in VCL can only be
//   used in a method called using Synchronize, for example:
//
//      Synchronize(UpdateCaption);
//
//   where UpdateCaption could look like:
//
//      void __fastcall ThreadMLP::UpdateCaption()
//      {
//        Form1->Caption = "Updated in a thread";
//      }
//---------------------------------------------------------------------------

__fastcall ThreadMLP::ThreadMLP(bool CreateSuspended)
  : TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
void ThreadMLP::SetName()
{
  THREADNAME_INFO info;
  info.dwType = 0x1000;
  info.szName = "MLP";
  info.dwThreadID = -1;
  info.dwFlags = 0;

  __try
  {
     RaiseException( 0x406D1388, 0, sizeof(info)/sizeof(DWORD),(DWORD*)&info );
  }
  __except (EXCEPTION_CONTINUE_EXECUTION)
  {
  }
}
//---------------------------------------------------------------------------
void __fastcall ThreadMLP::Execute()
{
  SetName();
  Study();
  //---- Place thread code here ----
}
//---------------------------------------------------------------------------
double	 ThreadMLP::Vector_Multiple (const vector<double	> lhs , const vector<double	> rhs )
{
  double multiple = 0.0;
  if ( lhs.size() != rhs.size() )
    return -0.1;

  for ( size_t Itr = 0 ; Itr < lhs.size() ; Itr ++ )
    multiple += lhs[Itr] * rhs[Itr];

  return multiple;
};
//---------------------------------------------------------------------------
double	 ThreadMLP::TSS(const vector<double	> V)
{
  double tss= 0.0;
    for ( size_t inc = 0 ; inc < V.size() ; inc ++ )
      tss += (V[inc] * V[inc]);
  return tss;
}
//---------------------------------------------------------------------------
void  ThreadMLP::Study( void )
{
  VOutput.clear();
  VAdd.clear();
  VDelta.clear();
  VLDelta.clear();
  double MidData[29];
  // Data 저장소 초기화
  for ( size_t i = 0 ; i < VInputMatrix[0].size() ; i ++ )
    VAdd.push_back(0.0);

  for (size_t i = 0 ; i < VTarget.size() ; i ++ )
    {
      VOutput.push_back(0.0);
      VDelta.push_back(0.0);
      VLDelta.push_back(0.0);
    }
  // Data 저장소의 확보

  for (unsigned int inc = 0  ; inc < FRun_Count ;inc++ )
    {
      for ( size_t i = 0 ; i < VInputMatrix.size() ; i ++ )
        {
          VOutput[i] = Vector_Multiple(VInputMatrix[i],VAdd);
          //Output = 가중치 * 입력치

          VDelta[i] = VTarget[i] - VOutput[i];
          //Delta = 목표치 - 실 출력치

          for ( size_t inc = 0 ; inc < VInputMatrix[i].size() ; inc ++ )
            VLDelta[inc] = FStudyAddition * VDelta[i] * VInputMatrix[i][inc];
          //VDelta = 학습가중치 * Delta * 입력치

          for ( size_t Itr = 0 ; Itr < VAdd.size() ; Itr ++ )
            VAdd[Itr] += VLDelta[Itr];
            //가중치 = 가중치 + VDelta
            //VAdd = VAdd + VDelta
          MidData[0] = inc;
          MidData[1] = i;
          MidData[2] = VOutput[i];
          MidData[3] = VDelta[i];
          size_t size = VAdd.size();
          for ( size_t Itr = 0 ; Itr < VAdd.size() ; Itr ++ )
            MidData[3+Itr] = VAdd[Itr];

          SendMessage(FHandle ,WM_TERM_VALUE,0,(long)MidData);
        }
      Tss = TSS(VDelta);
      SendMessage(FHandle ,WM_TSS,0,(long)Tss);
      if ( Tss == 0.0 )
        {
          break;
          PostMessage(FHandle ,WM_TERM_END,0,0);
        }
    }
  PostMessage(FHandle ,WM_TERM_END,0,0);
}
//---------------------------------------------------------------------------
double	  ThreadMLP::Test( vector<double	> Data )
{
  return Vector_Multiple(Data,VAdd);
}