// <summary>ソースコード：ニューラルネットワークコーディングサンプル</summary>
// <author>CommonMP</author>
using System;
using System.Collections.Generic;
using System.Text;

namespace CommonMP.HYMCO.OptionImpl.NeuralNetworkSample
{
    /// <summary><para>class outline:</para>
    /// <para>ニューロン層</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2010/02/01][新規作成]</para>
    /// </remarks>
    public class NN_Layer
    {
        /// <summary>上位ネットワーク層 への結合ネットワーク</summary>
        protected NN_Network m_csUpperNetwork = null;
        /// <summary>下位ネットワーク層 への結合ネットワーク</summary>
        protected NN_Network m_csLowerNetwork = null;
        /// <summary>層内ニューロン数</summary>
        protected int m_iNeuronNum = 0;
        /// <summary>層内ニューロン配列</summary>
        protected NN_Neuron[] m_csNeuron = null;

        /// <summary><para>method outline:</para>
        /// <para>ニューロン生成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>CreateNetwork(ref csUpperLayer,ref csLowerLayer)</para>
        /// </example>
        /// <param name="iNeuronNum">ニューロン数</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void CreateNeuron( int iNeuronNum )
        {
            m_iNeuronNum = iNeuronNum;
            m_csNeuron = new NN_Neuron[iNeuronNum+1];
            for (int i = 0; i < iNeuronNum; i++)
            {
                m_csNeuron[i] = new NN_Neuron();
            }
            m_csNeuron[iNeuronNum] = new NN_BiasNeuron();
        }
        /// <summary><para>method outline:</para>
        /// <para>ニューロン数取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>int iNum = GetNeuronNum( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>ニューロン数</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual int GetNeuronNum()
        { return m_iNeuronNum; }

        /// <summary><para>method outline:</para>
        /// <para>ニューロン配列取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>NN_Neuron[] csNN = GetNeuron( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>NN_Neuron[] ニューロン配列</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual NN_Neuron[] GetNeuron()
        { return m_csNeuron; }

        /// <summary><para>method outline:</para>
        /// <para>上位結合層設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetUpperNetwork(csUpperNetwork)</para>
        /// </example>
        /// <param name="csUpperNetwork">上位結合層</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void SetUpperNetwork(NN_Network csUpperNetwork)
        {
            m_csUpperNetwork = csUpperNetwork;
        }   
        /// <summary><para>method outline:</para>
        /// <para>下位結合層設定</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetLowerNetwork(csLowerNetwork)</para>
        /// </example>
        /// <param name="csLowerNetwork">下位結合層</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void SetLowerNetwork(NN_Network csLowerNetwork)
        {
            m_csLowerNetwork = csLowerNetwork;
        }

        /// <summary><para>method outline:</para>
        /// <para>想起処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Learn()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void Recognize()
        {
            // 上位層連想
            m_csUpperNetwork.Recognize();
        }
        /// <summary><para>method outline:</para>
        /// <para>学習処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Learn()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void Learn()
        {
            // 下位層学習
            m_csLowerNetwork.Learn();
        }
    }

    /// <summary><para>class outline:</para>
    /// <para>入力層</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2010/02/01][新規作成]</para>
    /// </remarks>
    public class NN_InputLayer : NN_Layer
    {
        /// <summary><para>method outline:</para>
        /// <para>ニューロン生成</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>CreateNetwork(ref csUpperLayer,ref csLowerLayer)</para>
        /// </example>
        /// <param name="iNeuronNum">ニューロン数</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override void CreateNeuron(int iNeuronNum)
        {
            m_iNeuronNum = iNeuronNum;
            m_csNeuron = new NN_Neuron[iNeuronNum + 1];
            for (int i = 0; i < iNeuronNum; i++)
            {
                m_csNeuron[i] = new NN_InputNeuron();
            }
            m_csNeuron[iNeuronNum] = new NN_BiasNeuron();
        }

        /// <summary><para>method outline:</para>
        /// <para>学習処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Learn()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override void Learn()
        {
            // Do Nothing
        }

        /// <summary><para>method outline:</para>
        /// <para>想起処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Learn(dInputDt)</para>
        /// </example>
        /// <param name="dInputDt">入力データ</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void Recognize( double[] dInputDt)
        {
            for (int i = 0; i < m_iNeuronNum; i++)
            {
                m_csNeuron[i].CalOut(dInputDt[i]);
            }
            // 上位層連想
            m_csUpperNetwork.Recognize();
        }
    }

    /// <summary><para>class outline:</para>
    /// <para>出力層</para>
    /// </summary>
    /// <remarks><para>history:</para>
    /// <para>[CommonMP][ver 1.0.0][2010/02/01][新規作成]</para>
    /// </remarks>
    public class NN_OutputLayer : NN_Layer
    {
        /// <summary><para>method outline:</para>
        /// <para>想起処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Recognize()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override void Recognize()
        {
            // Do Nothing
        }
        /// <summary><para>method outline:</para>
        /// <para>学習処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Learn(dTeacherDt)</para>
        /// </example>
        /// <param name="dTeacherDt">教師データ</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void Learn( double[] dTeacherDt )
        {
            for (int i = 0; i < m_iNeuronNum; i++)
            {
                //m_csNeuron[i].CalDlt(m_csNeuron[i].GetOut() - dTeacherDt[i]);
                m_csNeuron[i].CalDlt(dTeacherDt[i] - m_csNeuron[i].GetOut());
            }
            // 下位層学習
            m_csLowerNetwork.Learn();
        }
        /// <summary><para>method outline:</para>
        /// <para>ニューロン出力値取得</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>double dDt = GetOut(ref dOutputDt)</para>
        /// </example>
        /// <param name="dOutputDt">ニューロン出力値(配列)</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public virtual void GetOut(ref double[] dOutputDt)
        {
            for (int i = 0; i < m_iNeuronNum; i++)
            {
                dOutputDt[i] = m_csNeuron[i].GetOut();
            }
        }
    }
}
