// <summary>ソースコード：ＨＹＭＣＯ演算モデルクラス</summary>
// <author>CommonMP</author>

using System;
using System.Collections.Generic;
using System.Text;

namespace CommonMP.HYMCO.OptionImple.GAModelSampleLIB.GACtlTools
{
    /// <summary><para>class outline:</para>
    /// <para>適合値管理表</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.3][2010/10/01][新規作成]</para>
    /// <para>remarks</para>
    /// <para>
    /// 各個体が１世代競争した後、各個体の適合値を管理する
    /// </para>
    /// </remarks>
    public class GAFitValueTable
    {
        /// <summary>固体数 </summary>
        long m_lNum;
        /// <summary>適合値 </summary>
        double[] m_dVal;
        /// <summary>標準化した適合値 </summary>
        double[] m_dNormalizedVal;

        /// <summary><para>method outline:</para>
        /// <para>コンストラクタ</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>GAFitValueTable csFitValueTable = new GAFitValueTable(lNum)</para>
        /// </example>
        /// <param name="lNum">固体数</param>
        /// <returns>GAFitValueTable 生成されたインスタンス</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public GAFitValueTable(long lNum)
        {
            m_lNum = lNum;
            m_dVal = new double[m_lNum];
            m_dNormalizedVal = new double[m_lNum];
            for (long lLp = 0; lLp < m_lNum; lLp++)
            {
                m_dVal[lLp] = 0.0;
                m_dNormalizedVal[lLp] = 0.0;
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>固体の適合値設定（個別設定）</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>SetFitVal(lIndividualOdr,dVal)</para>
        /// </example>
        /// <param name="lIndividualOdr">固体の配列上のアイテム番号（０相対）</param>
        /// <param name="dVal">固体の適合度</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public bool SetFitVal(long lIndividualOdr, double dVal)
        {
            bool bRtn = true;
            if (lIndividualOdr < m_lNum)
            {
                m_dVal[lIndividualOdr] = dVal;
            }
            else
            {
                bRtn = false;
            }
            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>固体の適合値設定（一括設定）</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>SetFitVal(dVal)</para>
        /// </example>
        /// <param name="dVal">固体の適合度</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public bool SetFitVal(double[] dVal)
        {
            bool bRtn = false;
            if (dVal.Length == m_lNum)
            {
                for (long lLp = 0; lLp < m_lNum; lLp++)
                {
                    m_dVal[lLp] = dVal[lLp];
                }
                bRtn = true;
            }
            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>適合度の正規化</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>　Normalize( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>後の計算の為、固体の適合値のオーダーを１程度に合わせる</para>
        /// </remarks>
        public void Normalize()
        {
            double dOffSet = 0.1/(double)m_lNum;
            double dMin = 1.0E30;
            double dMax = -1.0E30;
            for (long lLp = 0; lLp < m_lNum; lLp++)
            {
                if (dMin > m_dVal[lLp]) { dMin = m_dVal[lLp]; }
                if (dMax < m_dVal[lLp]) { dMax = m_dVal[lLp]; }
            }
            double dDlt = dMax - dMin;
            if (dDlt == 0.0)
            {
                dDlt = 1.0 / (double)m_lNum;
                dOffSet = 1.0 / (double)m_lNum;
            }
            else
            {
                dMin -= dDlt * 0.1; // 10%程度最小データにもチャンスを与える(あまりにも淘汰圧力が高いと遺伝子の多様性が損なわれるため)
            }

            for (long lLp = 0; lLp < m_lNum; lLp++)
            {
                m_dNormalizedVal[lLp] = (m_dVal[lLp] - dMin)/dDlt + dOffSet;
            }
        }
        /// <summary><para>method outline:</para>
        /// <para>適合値テーブル配列数取得</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>　Normalize( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>適合値テーブルの配列数</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public long GetTableNum()
        { return m_lNum; }
        /// <summary><para>method outline:</para>
        /// <para>規格化した適合値値取得</para>
        /// </summary>
        /// <example>
        /// <para>usage:</para>
        /// <para>　GetNormalizedFitVal( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>規格化した適合値値</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public double[] GetNormalizedFitVal()
        { return m_dNormalizedVal; }
    }
}
