프로그래밍 2016. 9. 9. 19:16
728x90

퍼지 (Fuzzy) 프로그래밍 - 2

 

시드값 두개를 넣어서, 퍼지로직을 이용하여,

결과값을 뽑아내는 클래스

결과값은 미리 값범위에 각각 매칭시켜 두어야 한다

 

 

//------------------------------------------------------------------------헤더
enum enFuzzyCalc
{
     enFuzzyCalc_Strict,
     enFuzzyCalc_Low,
     enFuzzyCalc_Balance,
};

 

class Fuzzy5x3
{
public:
     Fuzzy5x3()
     {
          ResetCalc();
          SetColumnRow();
          SetColumnRow_Point();
     }
     ~Fuzzy5x3()
     {
     }

 

     void ResetCalc()
     {
          memset( m_fWeight, 0, sizeof(float) * 5 * 3 );
  
          memset( m_iSavePoint, 0, sizeof(int) * 10 );
          m_iSaveCount = 0;
     }
     void SetColumnRow( void );
     void SetColumnRow_Point( void );
     int FuzzyCalc( const float _fColumnSeed, const float _fRowSeed,

const enFuzzyCalc _enF = enFuzzyCalc_Strict );

 

protected:
     int FuzzyCalc_Strict();
     int FuzzyCalc_Low();
     int FuzzyCalc_Balance();

 

protected:
     float m_fColumn[5][3]; //5x3
     float m_fRow[3][3]; //3x3
     int m_fCRPoint[5][3]; //5x3
     float m_fWeight[5][3]; //5x3

 

     int m_iSaveCount;
     int m_iSavePoint[10];
};

 


//------------------------------------------------------------------------본문


/*
퍼지이론에서 사용되는 값은
딱 떨어지는 값이 아니라,
범위를 가지고, 다른 값과도 어느정도의 교집합 영역을 가지는 숫자영역으로 설정된다

 

예)
column[0] 의 값범위는 0 ~ 2
column[1] 의 값범위는 1 ~ 3

column[0] 과 column[1] 사이의 관계만을 볼때,
1~2 사이의 값은 column[0] 과 column[1] 에서 공통으로 가지고 있는(교집합) 숫자영역이 되겠다
*/
void
Fuzzy5x3::SetColumnRow( void )
{
     //[x][1]번째 요소는 값범위안에서의 중심값
     //[x][1]번째 요소는 반드시 필요한 값은 아니나, 나중에 퍼지계산시

     //편하게 사용하기 위해서 추가


     m_fColumn[0][0] = 0.f; m_fColumn[0][1] = 1.f; m_fColumn[0][2] = 2.f;
     m_fColumn[1][0] = 1.f; m_fColumn[1][1] = 2.f; m_fColumn[1][2] = 3.f;
     m_fColumn[2][0] = 2.f; m_fColumn[2][1] = 3.f; m_fColumn[2][2] = 4.f;
     m_fColumn[3][0] = 3.f; m_fColumn[3][1] = 4.f; m_fColumn[3][2] = 5.f;
     m_fColumn[4][0] = 4.f; m_fColumn[4][1] = 5.f; m_fColumn[4][2] = 6.f;

 

//
m_fRow[0][0] = 0.f; m_fRow[0][1] = 1.f; m_fRow[0][2] = 2.f;
m_fRow[1][0] = 1.f; m_fRow[1][1] = 2.f; m_fRow[1][2] = 3.f;
m_fRow[2][0] = 2.f; m_fRow[2][1] = 3.f; m_fRow[2][2] = 4.f;

}

 

/*
일반적인 퍼지값 분포도

(퍼지값의 범위를 1 ~ 5 라고 할때)

 

                  작음        보통       많음
매우작음         1           1           2
작음               1           2           3
보통               2           3           4
많음               3           4           5
매우많음         4           5           5


위분포도에서
     컬럼부분은 캐릭터의 HP
     로우부분은 캐릭터의 파워
     퍼지값은  캐릭터의 특수능력값
으로 생각해볼때,

 

HP가 작고, 파워가 작으면 특수능력값이 작고
HP가 크고, 파워가 많으면 특수능력값이 크다라는 방식으로 구성되어졌음을 알수있다
*/


void
Fuzzy5x3::SetColumnRow_Point( void )
{
     m_fCRPoint[0][0] = m_fCRPoint[0][1] = m_fCRPoint[1][0] = 1;
     m_fCRPoint[2][0] = m_fCRPoint[1][1] = m_fCRPoint[0][2] = 2;
     m_fCRPoint[3][0] = m_fCRPoint[2][1] = m_fCRPoint[1][2] = 3;
     m_fCRPoint[4][0] = m_fCRPoint[3][1] = m_fCRPoint[2][2] = 4;
     m_fCRPoint[4][1] = m_fCRPoint[3][2] = m_fCRPoint[4][2] = 5;
}

 

//--------------------------------------------------------------
//CREA: 2016. 9. 9. jsw
//DESC: seed 는 두개, seed 값범위는 0 ~ 1
//--------------------------------------------------------------
int
Fuzzy5x3::FuzzyCalc( float _fColumnSeed, float _fRowSeed , const enFuzzyCalc _enF )
{
     float fCx = _fColumnSeed * 6.f;
     float fRx = _fRowSeed * 4.f;
     float fWeight_C = 0.f;
     float fWeight_R = 0.f;
     float fWeight = 0.f;
     float fGap = 0.001f;

 

ResetCalc();

 

for( int i=0; i<5; i++ )
{
      if( m_fColumn[i][0] <= fCx && fCx <= m_fColumn[i][2] )
      {
           for( int k=0; k<3; k++ )
           {
                if( m_fRow[k][0] <= fRx && fRx <= m_fRow[k][2] )
                {
                      //컬럼씨드와 로우씨드가 공통으로 속하는 영역을 알아내서,
                      //컬럼과 로우에 대한 각각의 중심값에 대한, 가중치 구하기
                      //중심값에 가까울수록 가중치가 높다

 

     //
     if( fCx <= m_fColumn[i][1] )
     {
      fWeight_C = fCx - m_fColumn[i][0] + fGap;
     }
     else
     {
      fWeight_C = m_fColumn[i][2] - fCx + fGap;
     }

 

     //
     if( fRx <= m_fRow[k][1] )
     {
      fWeight_R = fRx - m_fRow[k][0] + fGap;
     }
     else
     {
      fWeight_R = m_fRow[k][2] - fRx + fGap;
     }

 

     //
     m_fWeight[i][k] = (fWeight_C + fWeight_R) * 0.5f;

 

     //일단 속해진 영역의 포인트를 바로 구해서, 저장해둔다
     //필요하면, 사용
     check( m_iSaveCount < 10 )
     m_iSavePoint[m_iSaveCount] = m_fCRPoint[i][k];
     m_iSaveCount += 1;
}

}

}

}

 

switch( _enF )
{
     case enFuzzyCalc_Strict: //가장 정확한 값
          return FuzzyCalc_Strict();

 

     case enFuzzyCalc_Low: //가장 낮은 가중치의 값
          return FuzzyCalc_Low();

 

     case enFuzzyCalc_Balance: //정확한값과 낮은값의 중간 값
          return FuzzyCalc_Balance();

 

     default:
     {
           //Sys_Error( "FuzzyCalc> error _enF(%d)!", _enF );
     }
     return 0;
}

}

 

//--------------------------------------------------------------
//CREA: 2016. 9. 9. jsw
//DESC: 가장 높은 가중치를 찾는다 - 가장 정확한 값
//--------------------------------------------------------------
int
Fuzzy5x3::FuzzyCalc_Strict()
{
     int iIdxC = 0, iIdxR = 0;
     float fMaxW = -1.f;

 

     //가장높은 가중치를 찾아낸다
     for( int i=0; i<5; i++ )
     {
          for( int k=0; k<3; k++ )
          {
               if( fMaxW < m_fWeight[i][k] )
               {
                    fMaxW = m_fWeight[i][k];
                    iIdxC = i, iIdxR = k;
               }
          }
     }

 

     //찾아낸 가중치값에 해당하는 m_fCRPoint 포인트를 반환
     //check( 0 <= iIdxC && iIdxC < 5 && 0 <= iIdxR && iIdxR < 3 )
     int iPoint = m_fCRPoint[iIdxC][iIdxR];
     return iPoint;
}

 

//--------------------------------------------------------------
//CREA: 2016. 9. 9. jsw
//DESC: 가장 낮은 가중치를 찾는다 - 가장 낮은 값
//--------------------------------------------------------------
int
Fuzzy5x3::FuzzyCalc_Low()
{
     int iIdxC = 0, iIdxR = 0;
     float fLowW = 999999.f;

 

     //가장낮은 가중치를 찾아낸다
     for( int i=0; i<5; i++ )
     {
          for( int k=0; k<3; k++ )
          {
               if( m_fWeight[i][k] > 0.f
                && fLowW > m_fWeight[i][k] )
                {
                    fLowW = m_fWeight[i][k];
                    iIdxC = i, iIdxR = k;
                }
          }
     }

 

//check( 0 <= iIdxC && iIdxC < 5 && 0 <= iIdxR && iIdxR < 3 )
int iPoint = m_fCRPoint[iIdxC][iIdxR];
return iPoint;

}

 

//--------------------------------------------------------------
//CREA: 2016. 9. 9. jsw
//DESC: 높은값과 낮은값의 평균치를 구한것
//--------------------------------------------------------------
int
Fuzzy5x3::FuzzyCalc_Balance()
{

     int i1 = FuzzyCalc_Strict();
     int i2 = FuzzyCalc_Low();

     return ( i1 + i2 ) / 2;
}

 

 

//------------------------------------------------------------------------테스트 코드

 

Fuzzy5x3 fuzzy;
int ip = 0;

 

ip = fuzzy.FuzzyCalc( 0.5, 0.5, enFuzzyCalc_Strict );

ip = fuzzy.FuzzyCalc( 0.5, 0.5, enFuzzyCalc_Low );
ip = fuzzy.FuzzyCalc( 0.5, 0.5, enFuzzyCalc_Balance );

...
ip = fuzzy.FuzzyCalc( 0.6, 0.7, enFuzzyCalc_Strict );
ip = fuzzy.FuzzyCalc( 0.6, 0.7, enFuzzyCalc_Low );
ip = fuzzy.FuzzyCalc( 0.6, 0.7, enFuzzyCalc_Balance );

...

 

 

 

728x90
posted by BK dddDang
: