// TTeacher.cpp: implementation of the TTeacher class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "TTeacher.h"
#include "TConfig.h"
#include "TPattern.h"
#include "TCommonNeuroConsts.h"
#include "TControlSystem.h"

#include <math.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

void TTeacherLearnPattern::destroyPattern( void )
{
   if( patt ) 
   {
      delete [] patt;
      patt = NULL;
   }

   numb = 0;
}

int TTeacherLearnPattern::loadPattern
(
   const char *fileName
)
{
   FILE     *fp;
   unsigned  numbElems;

   destroyPattern();
   
   fp = fopen( fileName, "rt" );
      
   if( fp == NULL ) 
      return 1;
      
   fscanf( fp, "%u\n" , &numbElems );
   numb = numbElems;

   patt = new TTeacherPatternElem[numbElems];

   for( int j = 0; j < numbElems; j++ )
   {
      int i[TEACHER_INPUTS_NUMB], o[TEACHER_OUTPUTS_NUMB];

      fscanf( 
         fp,
         "%d %d %d    %d\n",
         &i[0],
         &i[1],
         &i[2],

         &o[0]
         );

      for( int i1 = 0; i1 < TEACHER_INPUTS_NUMB; i1++ )
         patt[j].i[i1] = ((float)i[i1])/TEACHER_PATT_COEFF;

      for( int o1 = 0; o1 < TEACHER_OUTPUTS_NUMB; o1++ )
         patt[j].o[o1] = ((float)o[o1])/TEACHER_PATT_COEFF;
   }

   fclose( fp );
   return 0;
}


TTeacher::TTeacher() :
 NetBP( 3,    
      TEACHER_INPUTS_NUMB,  
      TEACHER_MIDDLE_NUMB,  
      TEACHER_OUTPUTS_NUMB
      )
{
   stopLearning = false;

   FullConnect();
   Randomize( 1 );
   SetCycle( 0 );
}

TTeacher::~TTeacher()
{
}

void TTeacher::reset()
{
   SetCycle( 0 );
}

void TTeacher::loadFromFile()
{
   LoadFromFile( "teacher.img" );
   FullConnect();
}

#define LAST_DIFF_DELTA 0.01

void TTeacher::learn( TTeacherLearnPattern &p )
{
   lastDiff = 1.0;

   while( lastDiff > LAST_DIFF_DELTA  && !stopLearning )
   {
      NextCycle();

      int numb = p.getNumb();

      int *ref = new int[numb];
      
      for( int i = 0; i < numb; i++ )
         ref[i] = 0;

      lastDiff = 0.0;
      for( i = 0; i < numb; i++ )
      {
         int j = rand()%numb;
         while( ref[j] )
         {
            j = rand()%numb;
         }

         ref[j] = 1;
         Cycle( p.get(j)->i, p.get(j)->o );
      }
     
      delete [] ref;
   }

   if( stopLearning ) stopLearning = false;
}

void TTeacher::teach
( 
   TEffCriteriaParms &ecp, 
   TSolverLearnPattern &solverPat
)
{
   LayerBP    *layer;
   unsigned    rL, numbImgs;
   float       inp[TEACHER_INPUTS_NUMB];
   float       out[TEACHER_OUTPUTS_NUMB];
   
   inp[0] = ecp.effCritWhereChange;
   inp[1] = ecp.oldECWhereChanged;
   inp[2] = config.ksuWhereChanged;
   
   for( int i = 0; i < TEACHER_INPUTS_NUMB; i++ )
      inp[i] = ((float)inp[i])/TEACHER_PATT_COEFF;

   SetNetInputs( inp );
   Propagate();
   layer = GetLayer( rang - 1 );

      // Находим выходы
   for( rL = 0; rL < TEACHER_OUTPUTS_NUMB; rL++ )
      out[rL] = layer->neurons[rL].axon;

   for( int o = 0; o < TEACHER_OUTPUTS_NUMB; o++ )
   {
      out[o] *= TEACHER_PATT_COEFF;
      out[o] = floorf(out[o]+0.5);
   }

   config.ksuWhereChanged = out[0];
   
   switch( config.ksuWhereChanged )
   {
      case 1:
         config.ksu -= config.teacherKSUStep;
         if( config.ksu < 0.0 ) config.ksu = 0.0;
         break;
   
      case 2:
         break;

      case 3:
         config.ksu += config.teacherKSUStep;
         if( config.ksu > 1.0 ) config.ksu = 1.0;
         break;
   }

/*
   //
   // теперь меняем выборку, так, чтобы все было хорошо
   //   
   for( i = 0; i < solverPat.getNumb(); i++ )
   {
      TSolverPatternElem *elem = solverPat.get(i);

      for( int i1 = 0; i1 < SOLVER_INPUTS_NUMB; i1++ )
         elem->i[i1] = (elem->i[i1])/SOLVER_PATT_COEFF;

      if( elem->i[0]*SOLVER_PATT_COEFF == 0 &&
          elem->i[1]*SOLVER_PATT_COEFF == 0 &&
          elem->i[2]*SOLVER_PATT_COEFF == 0 &&
          elem->i[3]*SOLVER_PATT_COEFF == 9 &&
          elem->i[4]*SOLVER_PATT_COEFF == 0 &&
          elem->i[5]*SOLVER_PATT_COEFF == 0 &&
          elem->i[6]*SOLVER_PATT_COEFF == 0    )
      {
         if( elem->i[7]*SOLVER_PATT_COEFF > 0 &&
             elem->i[7]*SOLVER_PATT_COEFF < config.ksu )
         {
            elem->o[2] = 0.0;
            elem->o[3] = 8.0/SOLVER_PATT_COEFF;
            elem->o[4] = 0.0;
            continue;
         }

         if( elem->i[7]*SOLVER_PATT_COEFF < 0 &&
             elem->i[7]*SOLVER_PATT_COEFF > config.ksu )
         {
            elem->o[2] = 0.0;
            elem->o[3] = 0.0;
            elem->o[4] = 8.0/SOLVER_PATT_COEFF;
            continue;
         }

         elem->o[2] = 0.0;
         elem->o[3] = 0.0;
         elem->o[4] = 0.0;
      }
   }
//   controlSystem->messageHandler( CSM_SAVE_SOLVER_PAT, NULL );
*/
}
